diff --git a/.github/workflows/bench-lsp.yml b/.github/workflows/bench-lsp.yml deleted file mode 100644 index 64b2d46e9bc..00000000000 --- a/.github/workflows/bench-lsp.yml +++ /dev/null @@ -1,26 +0,0 @@ -name: Benchmark LSP - -on: - pull_request: - draft: false - paths: - - forc-plugins/forc-lsp/** - - sway-lsp/** - - forc-pkg/** - - sway-core/** - -concurrency: - group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} - cancel-in-progress: true - -jobs: - compare-master: - runs-on: ubuntu-latest - steps: - - uses: Swatinem/rust-cache@v2 - - uses: actions/checkout@v3 - - uses: boa-dev/criterion-compare-action@v3.2.4 - with: - cwd: "./sway-lsp" - branchName: ${{ github.base_ref }} - token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/benchmark.yml b/.github/workflows/benchmark.yml new file mode 100644 index 00000000000..7f5389b81c0 --- /dev/null +++ b/.github/workflows/benchmark.yml @@ -0,0 +1,41 @@ +name: Codspeed Benchmarks + +on: + push: + branches: + - "master" + pull_request: + paths: + - forc-plugins/forc-lsp/** + - sway-lsp/** + - forc-pkg/** + - sway-core/** + # `workflow_dispatch` allows CodSpeed to trigger backtest + # performance analysis in order to generate initial data. + workflow_dispatch: + +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + +jobs: + benchmarks: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + + - name: Setup rust toolchain, cache and cargo-codspeed binary + uses: moonrepo/setup-rust@v0 + with: + channel: stable + cache-target: release + bins: cargo-codspeed + + - name: Build the benchmark target(s) + run: cargo codspeed build + + - name: Run the benchmarks + uses: CodSpeedHQ/action@v3 + with: + run: cargo codspeed run + token: ${{ secrets.CODSPEED_TOKEN }} diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4c1995aff32..58be69c8e88 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -15,12 +15,12 @@ concurrency: env: CARGO_TERM_COLOR: always REGISTRY: ghcr.io - RUST_VERSION: 1.76.0 - NIGHTLY_RUST_VERSION: nightly-2024-02-07 + RUST_VERSION: 1.79.0 + NIGHTLY_RUST_VERSION: nightly-2024-07-16 jobs: get-fuel-core-version: - runs-on: ubuntu-latest + runs-on: buildjet-4vcpu-ubuntu-2204 outputs: fuel_core_version: ${{steps.get_fuel_core_ver.outputs.version}} steps: @@ -40,7 +40,7 @@ jobs: echo "version=$version" >> "$GITHUB_OUTPUT" build-sway-lib-core: - runs-on: ubuntu-latest + runs-on: buildjet-4vcpu-ubuntu-2204 steps: - uses: actions/checkout@v3 - name: Install toolchain @@ -48,13 +48,15 @@ jobs: with: toolchain: ${{ env.RUST_VERSION }} - uses: Swatinem/rust-cache@v2 + with: + cache-provider: "buildjet" - name: Install Forc run: cargo install --locked --debug --path ./forc - name: Build sway-lib-core run: forc build --path sway-lib-core build-sway-lib-std: - runs-on: ubuntu-latest + runs-on: buildjet-4vcpu-ubuntu-2204 steps: - uses: actions/checkout@v3 - name: Install toolchain @@ -62,13 +64,15 @@ jobs: with: toolchain: ${{ env.RUST_VERSION }} - uses: Swatinem/rust-cache@v2 + with: + cache-provider: "buildjet" - name: Install Forc run: cargo install --locked --debug --path ./forc - name: Build sway-lib-std run: forc build --path sway-lib-std build-sway-examples: - runs-on: ubuntu-latest + runs-on: buildjet-4vcpu-ubuntu-2204 steps: - uses: actions/checkout@v3 - name: Install toolchain @@ -76,11 +80,13 @@ jobs: with: toolchain: ${{ env.RUST_VERSION }} - uses: Swatinem/rust-cache@v2 + with: + cache-provider: "buildjet" - name: Build Sway examples workspace run: cargo run --locked -p forc -- build --locked --path ./examples/Forc.toml build-reference-examples: - runs-on: ubuntu-latest + runs-on: buildjet-4vcpu-ubuntu-2204 steps: - uses: actions/checkout@v3 - name: Install toolchain @@ -88,11 +94,13 @@ jobs: with: toolchain: ${{ env.RUST_VERSION }} - uses: Swatinem/rust-cache@v2 + with: + cache-provider: "buildjet" - name: Build Sway examples workspace run: cargo run --locked -p forc -- build --locked --path ./docs/reference/src/code/Forc.toml forc-fmt-check-sway-lib-core: - runs-on: ubuntu-latest + runs-on: buildjet-4vcpu-ubuntu-2204 steps: - uses: actions/checkout@v3 - name: Install toolchain @@ -100,11 +108,13 @@ jobs: with: toolchain: ${{ env.RUST_VERSION }} - uses: Swatinem/rust-cache@v2 + with: + cache-provider: "buildjet" - name: Check Sway sway-lib-core formatting run: cargo run --locked -p forc-fmt -- --check --path ./sway-lib-core forc-fmt-check-sway-lib-std: - runs-on: ubuntu-latest + runs-on: buildjet-4vcpu-ubuntu-2204 steps: - uses: actions/checkout@v3 - name: Install toolchain @@ -112,11 +122,13 @@ jobs: with: toolchain: ${{ env.RUST_VERSION }} - uses: Swatinem/rust-cache@v2 + with: + cache-provider: "buildjet" - name: Check Sway sway-lib-std formatting run: cargo run --locked -p forc-fmt -- --check --path ./sway-lib-std forc-fmt-check-sway-examples: - runs-on: ubuntu-latest + runs-on: buildjet-4vcpu-ubuntu-2204 steps: - uses: actions/checkout@v3 - name: Install toolchain @@ -124,11 +136,13 @@ jobs: with: toolchain: ${{ env.RUST_VERSION }} - uses: Swatinem/rust-cache@v2 + with: + cache-provider: "buildjet" - name: Check Sway examples formatting run: cargo run --locked -p forc-fmt -- --check --path ./examples forc-fmt-check-panic: - runs-on: ubuntu-latest + runs-on: buildjet-4vcpu-ubuntu-2204 steps: - uses: actions/checkout@v3 - name: Install toolchain @@ -136,17 +150,19 @@ jobs: with: toolchain: ${{ env.RUST_VERSION }} - uses: Swatinem/rust-cache@v2 + with: + cache-provider: "buildjet" - name: Install forc-fmt run: cargo install --locked --debug --path ./forc-plugins/forc-fmt - name: Run the formatter against all sway projects and fail if any of them panic run: scripts/formatter/forc-fmt-check-panic.sh check-sdk-harness-test-suite-compatibility: - runs-on: ubuntu-latest + runs-on: buildjet-4vcpu-ubuntu-2204 steps: - name: Checkout code uses: actions/checkout@v2 - + - name: Set up Rust uses: actions-rs/toolchain@v1 with: @@ -194,7 +210,7 @@ jobs: - name: Run mdbook build uses: peaceiris/actions-mdbook@v1 with: - mdbook-version: '0.4.25' + mdbook-version: "0.4.25" - name: Emit book logs to tmp.txt, fail if build logs contain 'ERROR' run: | MDBOOK_preprocessor__FORC_documenter__STRICT="true" mdbook build docs/book 2>&1 | tee tmp.txt @@ -219,7 +235,7 @@ jobs: fi build-forc-doc-sway-lib-std: - runs-on: ubuntu-latest + runs-on: buildjet-4vcpu-ubuntu-2204 steps: - uses: actions/checkout@v3 - name: Install toolchain @@ -227,6 +243,8 @@ jobs: with: toolchain: ${{ env.RUST_VERSION }} - uses: Swatinem/rust-cache@v2 + with: + cache-provider: "buildjet" - name: Install Forc run: cargo install --locked --debug --path ./forc - name: Install Forc plugins @@ -236,14 +254,17 @@ jobs: run: forc doc --manifest-path ./sway-lib-std build-forc-test-project: - runs-on: ubuntu-latest + runs-on: buildjet-4vcpu-ubuntu-2204 steps: - uses: actions/checkout@v3 - name: Install toolchain uses: dtolnay/rust-toolchain@master with: toolchain: ${{ env.RUST_VERSION }} + targets: wasm32-unknown-unknown - uses: Swatinem/rust-cache@v2 + with: + cache-provider: "buildjet" - name: Install Forc run: cargo install --locked --debug --path ./forc - name: Initialize test project @@ -257,6 +278,8 @@ jobs: # run: (cd test-proj && forc test) - name: Install cargo-generate run: cargo install --locked cargo-generate + - name: Install fuel-core + run: cargo install --locked fuel-core-bin - name: Generate Rust Integration Tests run: (cd test-proj && cargo generate --init --path ../templates/sway-test-rs --name test-proj) - name: Update project cargo manifest with workspace @@ -268,7 +291,7 @@ jobs: run: (cd test-proj && cargo test --release) cargo-build-workspace: - runs-on: ubuntu-latest + runs-on: buildjet-8vcpu-ubuntu-2204 steps: - uses: actions/checkout@v3 - name: Install toolchain @@ -276,13 +299,15 @@ jobs: with: toolchain: ${{ env.RUST_VERSION }} - uses: Swatinem/rust-cache@v2 - - name: 'Build Workspace' + with: + cache-provider: "buildjet" + - name: "Build Workspace" run: cargo build --locked --workspace --all-features --all-targets env: - RUSTFLAGS: '-D warnings' + RUSTFLAGS: "-D warnings" cargo-clippy: - runs-on: ubuntu-latest + runs-on: buildjet-4vcpu-ubuntu-2204 steps: - uses: actions/checkout@v3 - name: Install toolchain @@ -291,11 +316,13 @@ jobs: toolchain: ${{ env.RUST_VERSION }} components: clippy - uses: Swatinem/rust-cache@v2 + with: + cache-provider: "buildjet" - name: Check Clippy Linter run: cargo clippy --all-features --all-targets -- -D warnings cargo-toml-fmt-check: - runs-on: ubuntu-latest + runs-on: ubuntu-latest # Switching this runner to buildjet causes failure. steps: - uses: actions/checkout@v3 - name: Install toolchain @@ -306,12 +333,12 @@ jobs: uses: baptiste0928/cargo-install@v1 with: crate: cargo-toml-lint - version: '0.1' + version: "0.1" - name: Run Cargo.toml linter run: git ls-files | grep Cargo.toml$ | grep -v 'templates/' | xargs --verbose -n 1 cargo-toml-lint cargo-fmt-check: - runs-on: ubuntu-latest + runs-on: buildjet-4vcpu-ubuntu-2204 steps: - uses: actions/checkout@v3 - name: Install toolchain @@ -323,7 +350,7 @@ jobs: run: cargo fmt --all -- --check cargo-run-e2e-test: - runs-on: ubuntu-latest + runs-on: buildjet-4vcpu-ubuntu-2204 needs: get-fuel-core-version steps: - uses: actions/checkout@v3 @@ -333,6 +360,8 @@ jobs: toolchain: ${{ env.RUST_VERSION }} targets: "x86_64-unknown-linux-gnu, wasm32-unknown-unknown" - uses: Swatinem/rust-cache@v2 + with: + cache-provider: "buildjet" - name: Install fuel-core for tests run: | curl -sSLf https://github.com/FuelLabs/fuel-core/releases/download/v${{ needs.get-fuel-core-version.outputs.fuel_core_version }}/fuel-core-${{ needs.get-fuel-core-version.outputs.fuel_core_version }}-x86_64-unknown-linux-gnu.tar.gz -L -o fuel-core.tar.gz @@ -341,12 +370,12 @@ jobs: mv fuel-core-${{ needs.get-fuel-core-version.outputs.fuel_core_version }}-x86_64-unknown-linux-gnu/fuel-core /usr/local/bin/fuel-core - name: Cargo Run E2E Tests (Fuel VM) run: | - fuel-core run --db-type in-memory --debug --snapshot ./.github/workflows/local-testnode & + fuel-core run --db-type in-memory --debug & sleep 5 && cargo run --locked --release --bin test -- --locked cargo-run-e2e-test-release: - runs-on: ubuntu-latest + runs-on: buildjet-4vcpu-ubuntu-2204 needs: get-fuel-core-version steps: - uses: actions/checkout@v3 @@ -356,6 +385,8 @@ jobs: toolchain: ${{ env.RUST_VERSION }} targets: "x86_64-unknown-linux-gnu, wasm32-unknown-unknown" - uses: Swatinem/rust-cache@v2 + with: + cache-provider: "buildjet" - name: Install fuel-core for tests run: | curl -sSLf https://github.com/FuelLabs/fuel-core/releases/download/v${{ needs.get-fuel-core-version.outputs.fuel_core_version }}/fuel-core-${{ needs.get-fuel-core-version.outputs.fuel_core_version }}-x86_64-unknown-linux-gnu.tar.gz -L -o fuel-core.tar.gz @@ -364,12 +395,12 @@ jobs: mv fuel-core-${{ needs.get-fuel-core-version.outputs.fuel_core_version }}-x86_64-unknown-linux-gnu/fuel-core /usr/local/bin/fuel-core - name: Cargo Run E2E Tests (Fuel VM) run: | - fuel-core run --db-type in-memory --debug --snapshot ./.github/workflows/local-testnode & + fuel-core run --db-type in-memory --debug & sleep 5 && cargo run --locked --release --bin test -- --locked --release cargo-run-e2e-test-evm: - runs-on: ubuntu-latest + runs-on: buildjet-4vcpu-ubuntu-2204 steps: - uses: actions/checkout@v3 - name: Install toolchain @@ -378,20 +409,10 @@ jobs: toolchain: ${{ env.RUST_VERSION }} targets: "x86_64-unknown-linux-gnu, wasm32-unknown-unknown" - uses: Swatinem/rust-cache@v2 - - name: Cargo Run E2E Tests (EVM) - run: cargo run --locked --release --bin test -- --target evm --locked --no-encoding-v1 - - cargo-run-e2e-test-midenvm: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - name: Install toolchain - uses: dtolnay/rust-toolchain@master with: - toolchain: ${{ env.RUST_VERSION }} - - uses: Swatinem/rust-cache@v2 + cache-provider: "buildjet" - name: Cargo Run E2E Tests (EVM) - run: cargo run --locked --release --bin test -- --target midenvm --locked --no-encoding-v1 + run: cargo run --locked --release --bin test -- --target evm --locked --no-encoding-v1 # TODO: Remove this upon merging std tests with the rest of the E2E tests. cargo-test-lib-std: @@ -402,6 +423,7 @@ jobs: uses: dtolnay/rust-toolchain@master with: toolchain: ${{ env.RUST_VERSION }} + targets: "x86_64-unknown-linux-gnu, wasm32-unknown-unknown" - uses: buildjet/cache@v3 with: path: | @@ -414,7 +436,7 @@ jobs: run: cargo test --locked --release --manifest-path ./test/src/sdk-harness/Cargo.toml -- --nocapture forc-run-benchmarks: - runs-on: ubuntu-latest + runs-on: buildjet-4vcpu-ubuntu-2204 permissions: contents: write steps: @@ -424,6 +446,8 @@ jobs: with: toolchain: ${{ env.RUST_VERSION }} - uses: Swatinem/rust-cache@v2 + with: + cache-provider: "buildjet" - name: Install Forc run: cargo install --locked --debug --path ./forc - name: Run benchmarks @@ -446,12 +470,12 @@ jobs: run: ./benchmark.sh --prepare-for-commit - uses: EndBug/add-and-commit@v9 with: - cwd: './performance-data' - message: 'Updated benchmark data' + cwd: "./performance-data" + message: "Updated benchmark data" default_author: github_actions forc-unit-tests: - runs-on: ubuntu-latest + runs-on: buildjet-4vcpu-ubuntu-2204 steps: - uses: actions/checkout@v3 - name: Install toolchain @@ -459,13 +483,19 @@ jobs: with: toolchain: ${{ env.RUST_VERSION }} - uses: Swatinem/rust-cache@v2 + with: + cache-provider: "buildjet" - name: Install Forc run: cargo install --locked --debug --path ./forc - - name: Run Unit Tests - run: forc build --path sway-lib-core && forc test --path sway-lib-core && forc build --path sway-lib-std && forc test --path sway-lib-std && forc build --path test/src/in_language_tests & forc test --path test/src/in_language_tests + - name: Run Core Unit Tests + run: forc build --path sway-lib-core && forc test --path sway-lib-core + - name: Run Std Unit Tests + run: forc build --path sway-lib-std && forc test --path sway-lib-std + - name: Run In Language Unit Tests + run: forc build --path test/src/in_language_tests && forc test --path test/src/in_language_tests forc-pkg-fuels-deps-check: - runs-on: ubuntu-latest + runs-on: buildjet-4vcpu-ubuntu-2204 steps: - uses: actions/checkout@v3 - name: Install toolchain @@ -473,15 +503,14 @@ jobs: with: toolchain: ${{ env.RUST_VERSION }} - uses: Swatinem/rust-cache@v2 - - - name: Install cargo-deps - run: cargo install cargo-deps + with: + cache-provider: "buildjet" # We require this check to avoid cyclic dependencies between 'fuels' and 'forc-pkg'. # Detailed explanation is found in the echo below. - name: Check 'forc-pkg' dependencies for 'fuels' crates run: | - deps=$(cargo deps --manifest-path forc-pkg/Cargo.toml) + deps=$(cargo tree --manifest-path forc-pkg/Cargo.toml) case "$deps" in *fuels*) @@ -499,7 +528,7 @@ jobs: ;; esac cargo-test-forc-debug: - runs-on: ubuntu-latest + runs-on: buildjet-4vcpu-ubuntu-2204 needs: get-fuel-core-version steps: - uses: actions/checkout@v3 @@ -509,6 +538,8 @@ jobs: toolchain: ${{ env.RUST_VERSION }} targets: "x86_64-unknown-linux-gnu, wasm32-unknown-unknown" - uses: Swatinem/rust-cache@v2 + with: + cache-provider: "buildjet" - name: Install fuel-core for tests run: | curl -sSLf https://github.com/FuelLabs/fuel-core/releases/download/v${{ needs.get-fuel-core-version.outputs.fuel_core_version }}/fuel-core-${{ needs.get-fuel-core-version.outputs.fuel_core_version }}-x86_64-unknown-linux-gnu.tar.gz -L -o fuel-core.tar.gz @@ -517,19 +548,58 @@ jobs: mv fuel-core-${{ needs.get-fuel-core-version.outputs.fuel_core_version }}-x86_64-unknown-linux-gnu/fuel-core /usr/local/bin/fuel-core - name: Run tests run: cargo test --locked --release -p forc-debug - cargo-test-sway-lsp: - runs-on: ubuntu-latest + cargo-test-forc-client: + runs-on: buildjet-4vcpu-ubuntu-2204 + needs: get-fuel-core-version steps: - uses: actions/checkout@v3 - name: Install toolchain uses: dtolnay/rust-toolchain@master with: toolchain: ${{ env.RUST_VERSION }} + targets: "x86_64-unknown-linux-gnu, wasm32-unknown-unknown" - uses: Swatinem/rust-cache@v2 + with: + cache-provider: "buildjet" + - name: Install fuel-core for tests + run: | + curl -sSLf https://github.com/FuelLabs/fuel-core/releases/download/v${{ needs.get-fuel-core-version.outputs.fuel_core_version }}/fuel-core-${{ needs.get-fuel-core-version.outputs.fuel_core_version }}-x86_64-unknown-linux-gnu.tar.gz -L -o fuel-core.tar.gz + tar -xvf fuel-core.tar.gz + chmod +x fuel-core-${{ needs.get-fuel-core-version.outputs.fuel_core_version }}-x86_64-unknown-linux-gnu/fuel-core + mv fuel-core-${{ needs.get-fuel-core-version.outputs.fuel_core_version }}-x86_64-unknown-linux-gnu/fuel-core /usr/local/bin/fuel-core + - name: Run tests + run: cargo test --locked --release -p forc-client -- --test-threads 1 + cargo-test-sway-lsp: + runs-on: buildjet-4vcpu-ubuntu-2204 + steps: + - uses: actions/checkout@v3 + - name: Setup Rust and cargo-nextest + uses: moonrepo/setup-rust@v0 + with: + channel: stable + cache-target: release + bins: cargo-nextest - name: Run sway-lsp tests sequentially - run: cargo test --locked --release -p sway-lsp -- --nocapture --test-threads=1 + env: + RUST_BACKTRACE: full + run: cargo nextest run --locked --release -p sway-lsp --no-capture --profile ci --config-file sway-lsp/tests/nextest.toml + cargo-test-forc: + runs-on: buildjet-4vcpu-ubuntu-2204 + steps: + - uses: actions/checkout@v3 + - name: Install toolchain + uses: dtolnay/rust-toolchain@master + with: + toolchain: ${{ env.RUST_VERSION }} + - uses: Swatinem/rust-cache@v2 + with: + cache-provider: "buildjet" + - name: Run forc tests separately + env: + RUST_BACKTRACE: full + run: cargo test --locked --release -p forc -- --nocapture cargo-test-workspace: - runs-on: ubuntu-latest + runs-on: buildjet-4vcpu-ubuntu-2204 steps: - uses: actions/checkout@v3 - name: Install toolchain @@ -537,10 +607,12 @@ jobs: with: toolchain: ${{ env.RUST_VERSION }} - uses: Swatinem/rust-cache@v2 + with: + cache-provider: "buildjet" - name: Run tests - run: cargo test --locked --release --workspace --exclude forc-debug --exclude sway-lsp + run: cargo test --locked --release --workspace --exclude forc-debug --exclude sway-lsp --exclude forc-client --exclude forc cargo-unused-deps-check: - runs-on: ubuntu-latest + runs-on: buildjet-4vcpu-ubuntu-2204 steps: - uses: actions/checkout@v3 - name: Install toolchain @@ -549,6 +621,8 @@ jobs: # `cargo-udeps` requires nightly to run toolchain: ${{ env.NIGHTLY_RUST_VERSION }} - uses: Swatinem/rust-cache@v2 + with: + cache-provider: "buildjet" - name: Install cargo-udeps run: cargo install --locked cargo-udeps - name: Check Unused Deps @@ -571,7 +645,7 @@ jobs: cargo-test-sway-lsp, cargo-unused-deps-check, ] - runs-on: ubuntu-latest + runs-on: buildjet-4vcpu-ubuntu-2204 steps: - name: Notify Slack On Failure uses: ravsamhq/notify-slack-action@v2 @@ -579,10 +653,10 @@ jobs: with: status: ${{ job.status }} token: ${{ secrets.GITHUB_TOKEN }} - notification_title: '{workflow} has {status_message}' - message_format: '{emoji} *{workflow}* {status_message} in <{repo_url}|{repo}> : <{run_url}|View Run Results>' - footer: '' - notify_when: 'failure' + notification_title: "{workflow} has {status_message}" + message_format: "{emoji} *{workflow}* {status_message} in <{repo_url}|{repo}> : <{run_url}|View Run Results>" + footer: "" + notify_when: "failure" env: SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_NOTIFY_BUILD }} @@ -590,7 +664,7 @@ jobs: # This is a separate job because we want this to fail fast if something is invalid here. pre-publish-check: if: github.event_name == 'release' && github.event.action == 'published' - runs-on: ubuntu-latest + runs-on: buildjet-4vcpu-ubuntu-2204 steps: - name: Checkout repository uses: actions/checkout@v3 @@ -603,28 +677,7 @@ jobs: - name: Verify tag version run: | cargo install toml-cli - ./.github/workflows/scripts/verify_tag.sh ${{ github.ref_name }} forc/Cargo.toml - ./.github/workflows/scripts/verify_tag.sh ${{ github.ref_name }} forc-pkg/Cargo.toml - ./.github/workflows/scripts/verify_tag.sh ${{ github.ref_name }} forc-plugins/forc-client/Cargo.toml - ./.github/workflows/scripts/verify_tag.sh ${{ github.ref_name }} forc-plugins/forc-debug/Cargo.toml - ./.github/workflows/scripts/verify_tag.sh ${{ github.ref_name }} forc-plugins/forc-doc/Cargo.toml - ./.github/workflows/scripts/verify_tag.sh ${{ github.ref_name }} forc-plugins/forc-fmt/Cargo.toml - ./.github/workflows/scripts/verify_tag.sh ${{ github.ref_name }} forc-plugins/forc-lsp/Cargo.toml - ./.github/workflows/scripts/verify_tag.sh ${{ github.ref_name }} forc-plugins/forc-tx/Cargo.toml - ./.github/workflows/scripts/verify_tag.sh ${{ github.ref_name }} forc-plugins/forc-crypto/Cargo.toml - ./.github/workflows/scripts/verify_tag.sh ${{ github.ref_name }} forc-test/Cargo.toml - ./.github/workflows/scripts/verify_tag.sh ${{ github.ref_name }} forc-tracing/Cargo.toml - ./.github/workflows/scripts/verify_tag.sh ${{ github.ref_name }} forc-util/Cargo.toml - ./.github/workflows/scripts/verify_tag.sh ${{ github.ref_name }} sway-ast/Cargo.toml - ./.github/workflows/scripts/verify_tag.sh ${{ github.ref_name }} sway-core/Cargo.toml - ./.github/workflows/scripts/verify_tag.sh ${{ github.ref_name }} sway-error/Cargo.toml - ./.github/workflows/scripts/verify_tag.sh ${{ github.ref_name }} sway-ir/Cargo.toml - ./.github/workflows/scripts/verify_tag.sh ${{ github.ref_name }} sway-ir/sway-ir-macros/Cargo.toml - ./.github/workflows/scripts/verify_tag.sh ${{ github.ref_name }} sway-lsp/Cargo.toml - ./.github/workflows/scripts/verify_tag.sh ${{ github.ref_name }} sway-parse/Cargo.toml - ./.github/workflows/scripts/verify_tag.sh ${{ github.ref_name }} sway-types/Cargo.toml - ./.github/workflows/scripts/verify_tag.sh ${{ github.ref_name }} sway-utils/Cargo.toml - ./.github/workflows/scripts/verify_tag.sh ${{ github.ref_name }} swayfmt/Cargo.toml + ./.github/workflows/scripts/verify_tag.sh ${{ github.ref_name }} - name: Notify if Job Fails uses: ravsamhq/notify-slack-action@v2 @@ -632,10 +685,10 @@ jobs: with: status: ${{ job.status }} token: ${{ secrets.GITHUB_TOKEN }} - notification_title: '{workflow} has {status_message}' - message_format: '{emoji} *{workflow}* {status_message} in <{repo_url}|{repo}> : <{run_url}|View Run Results>' - footer: '' - notify_when: 'failure' + notification_title: "{workflow} has {status_message}" + message_format: "{emoji} *{workflow}* {status_message} in <{repo_url}|{repo}> : <{run_url}|View Run Results>" + footer: "" + notify_when: "failure" env: SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_NOTIFY_BUILD }} @@ -671,7 +724,7 @@ jobs: toolchain: ${{ env.RUST_VERSION }} - name: Publish crate - uses: xgreenx/publish-crates@v1 + uses: FuelLabs/publish-crates@v1 with: publish-delay: 30000 registry-token: ${{ secrets.CARGO_REGISTRY_TOKEN }} @@ -682,10 +735,10 @@ jobs: with: status: ${{ job.status }} token: ${{ secrets.GITHUB_TOKEN }} - notification_title: '{workflow} has {status_message}' - message_format: '{emoji} *{workflow}* {status_message} in <{repo_url}|{repo}> : <{run_url}|View Run Results>' - footer: '' - notify_when: 'failure' + notification_title: "{workflow} has {status_message}" + message_format: "{emoji} *{workflow}* {status_message} in <{repo_url}|{repo}> : <{run_url}|View Run Results>" + footer: "" + notify_when: "failure" env: SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_NOTIFY_BUILD }} @@ -707,7 +760,7 @@ jobs: cargo-unused-deps-check, ] if: github.ref == 'refs/heads/master' - runs-on: ubuntu-latest + runs-on: buildjet-4vcpu-ubuntu-2204 permissions: contents: read packages: write @@ -759,17 +812,17 @@ jobs: with: status: ${{ job.status }} token: ${{ secrets.GITHUB_TOKEN }} - notification_title: '{workflow} has {status_message}' - message_format: '{emoji} *{workflow}* {status_message} in <{repo_url}|{repo}> : <{run_url}|View Run Results>' - footer: '' - notify_when: 'failure' + notification_title: "{workflow} has {status_message}" + message_format: "{emoji} *{workflow}* {status_message} in <{repo_url}|{repo}> : <{run_url}|View Run Results>" + footer: "" + notify_when: "failure" env: SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_NOTIFY_BUILD }} build-publish-release-image: # Build & Publish Docker Image Per Sway Release needs: publish - runs-on: ubuntu-latest + runs-on: buildjet-4vcpu-ubuntu-2204 permissions: contents: read packages: write @@ -814,10 +867,10 @@ jobs: with: status: ${{ job.status }} token: ${{ secrets.GITHUB_TOKEN }} - notification_title: '{workflow} has {status_message}' - message_format: '{emoji} *{workflow}* {status_message} in <{repo_url}|{repo}> : <{run_url}|View Run Results>' - footer: '' - notify_when: 'failure' + notification_title: "{workflow} has {status_message}" + message_format: "{emoji} *{workflow}* {status_message} in <{repo_url}|{repo}> : <{run_url}|View Run Results>" + footer: "" + notify_when: "failure" env: SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_NOTIFY_BUILD }} @@ -862,13 +915,13 @@ jobs: - uses: Swatinem/rust-cache@v2 with: cache-on-failure: true - key: '${{ matrix.job.target }}' + key: "${{ matrix.job.target }}" - name: Use Cross uses: baptiste0928/cargo-install@v1 with: crate: cross - cache-key: '${{ matrix.job.target }}' + cache-key: "${{ matrix.job.target }}" - name: Build forc binaries run: | diff --git a/.github/workflows/local-testnode/chain_config.json b/.github/workflows/local-testnode/chain_config.json deleted file mode 100644 index 334f6f89508..00000000000 --- a/.github/workflows/local-testnode/chain_config.json +++ /dev/null @@ -1,271 +0,0 @@ -{ - "chain_name": "Local network", - "consensus_parameters": { - "V1": { - "tx_params": { - "V1": { - "max_inputs": 255, - "max_outputs": 255, - "max_witnesses": 255, - "max_gas_per_tx": 100000000, - "max_size": 262144, - "max_bytecode_subsections": 256 - } - }, - "predicate_params": { - "V1": { - "max_predicate_length": 102400, - "max_predicate_data_length": 102400, - "max_message_data_length": 102400, - "max_gas_per_predicate": 100000000 - } - }, - "script_params": { - "V1": { - "max_script_length": 102400, - "max_script_data_length": 102400 - } - }, - "contract_params": { - "V1": { - "contract_max_size": 262144, - "max_storage_slots": 1760 - } - }, - "fee_params": { - "V1": { - "gas_price_factor": 92, - "gas_per_byte": 63 - } - }, - "chain_id": 0, - "gas_costs": { - "V1": { - "add": 2, - "addi": 2, - "aloc": 2, - "and": 2, - "andi": 2, - "bal": 86, - "bhei": 2, - "bhsh": 2, - "burn": 25770, - "cb": 2, - "cfei": 2, - "cfsi": 2, - "div": 2, - "divi": 2, - "eck1": 3114, - "ecr1": 42270, - "ed19": 2878, - "eq": 2, - "exp": 2, - "expi": 2, - "flag": 1, - "gm": 2, - "gt": 2, - "gtf": 12, - "ji": 2, - "jmp": 2, - "jne": 2, - "jnei": 2, - "jnzi": 2, - "jmpf": 1, - "jmpb": 1, - "jnzf": 1, - "jnzb": 1, - "jnef": 1, - "jneb": 1, - "lb": 2, - "log": 165, - "lt": 2, - "lw": 2, - "mint": 29024, - "mlog": 2, - "mod": 2, - "modi": 2, - "move": 2, - "movi": 2, - "mroo": 4, - "mul": 2, - "muli": 2, - "mldv": 3, - "noop": 1, - "not": 2, - "or": 2, - "ori": 2, - "poph": 3, - "popl": 3, - "pshh": 4, - "pshl": 4, - "ret_contract": 134, - "rvrt_contract": 153, - "sb": 2, - "sll": 2, - "slli": 2, - "srl": 2, - "srli": 2, - "srw": 209, - "sub": 2, - "subi": 2, - "sw": 2, - "sww": 22501, - "time": 50, - "tr": 33912, - "tro": 24294, - "wdcm": 2, - "wqcm": 3, - "wdop": 3, - "wqop": 3, - "wdml": 3, - "wqml": 4, - "wddv": 5, - "wqdv": 6, - "wdmd": 10, - "wqmd": 17, - "wdam": 9, - "wqam": 11, - "wdmm": 10, - "wqmm": 10, - "xor": 2, - "xori": 2, - "call": { - "LightOperation": { - "base": 18190, - "units_per_gas": 5 - } - }, - "ccp": { - "LightOperation": { - "base": 48, - "units_per_gas": 22 - } - }, - "croo": { - "LightOperation": { - "base": 131, - "units_per_gas": 2 - } - }, - "csiz": { - "LightOperation": { - "base": 45, - "units_per_gas": 237 - } - }, - "k256": { - "LightOperation": { - "base": 37, - "units_per_gas": 3 - } - }, - "ldc": { - "LightOperation": { - "base": 39, - "units_per_gas": 68 - } - }, - "logd": { - "LightOperation": { - "base": 565, - "units_per_gas": 2 - } - }, - "mcl": { - "LightOperation": { - "base": 3, - "units_per_gas": 564 - } - }, - "mcli": { - "LightOperation": { - "base": 3, - "units_per_gas": 560 - } - }, - "mcp": { - "LightOperation": { - "base": 4, - "units_per_gas": 185 - } - }, - "mcpi": { - "LightOperation": { - "base": 9, - "units_per_gas": 455 - } - }, - "meq": { - "LightOperation": { - "base": 3, - "units_per_gas": 766 - } - }, - "retd_contract": { - "LightOperation": { - "base": 485, - "units_per_gas": 3 - } - }, - "s256": { - "LightOperation": { - "base": 42, - "units_per_gas": 3 - } - }, - "scwq": { - "HeavyOperation": { - "base": 21672, - "gas_per_unit": 22146 - } - }, - "smo": { - "LightOperation": { - "base": 44437, - "units_per_gas": 1 - } - }, - "srwq": { - "HeavyOperation": { - "base": 239, - "gas_per_unit": 234 - } - }, - "swwq": { - "HeavyOperation": { - "base": 22724, - "gas_per_unit": 21231 - } - }, - "contract_root": { - "LightOperation": { - "base": 42, - "units_per_gas": 2 - } - }, - "state_root": { - "HeavyOperation": { - "base": 323, - "gas_per_unit": 169 - } - }, - "new_storage_per_byte": 63, - "vm_initialization": { - "HeavyOperation": { - "base": 5254820, - "gas_per_unit": 0 - } - } - } - }, - "base_asset_id": "0xf8f8b6283d7fa5b672b530cbb84fcccb4ff8dc40f8176ef4544ddb1f1952ad07", - "block_gas_limit": 100000000, - "privileged_address": "9f0e19d6c2a6283a3222426ab2630d35516b1799b503f37b02105bebe1b8a3e9" - } - }, - "consensus": { - "PoA": { - "signing_key": "e0a9fcde1b73f545252e01b30b50819eb9547d07531fa3df0385c5695736634d" - } - } -} \ No newline at end of file diff --git a/.github/workflows/local-testnode/metadata.json b/.github/workflows/local-testnode/metadata.json deleted file mode 100644 index 9d12c38b64e..00000000000 --- a/.github/workflows/local-testnode/metadata.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "chain_config": "chain_config.json", - "table_encoding": { - "Json": { - "filepath": "state_config.json" - } - } -} diff --git a/.github/workflows/local-testnode/state_config.json b/.github/workflows/local-testnode/state_config.json deleted file mode 100644 index 879ee797e15..00000000000 --- a/.github/workflows/local-testnode/state_config.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "coins": [ - { - "tx_id": "0000000000000000000000000000000000000000000000000000000000000001", - "output_index": 0, - "tx_pointer_block_height": 0, - "tx_pointer_tx_idx": 0, - "owner": "6b63804cfbf9856e68e5b6e7aef238dc8311ec55bec04df774003a2c96e0418e", - "amount": 1152921504606846976, - "asset_id": "0xf8f8b6283d7fa5b672b530cbb84fcccb4ff8dc40f8176ef4544ddb1f1952ad07" - } - ], - "messages": [], - "contracts": [ - { - "contract_id": "7777777777777777777777777777777777777777777777777777777777777777", - "code": "900000097b4b30b2437b0073e5ba5a9324cf55831d180a89f66332b541827e12e647b7516140000a504d00205d4d30001a4860004945048076440001240400005050c0043d51345024040000", - "tx_id": "0000000000000000000000000000000000000000000000000000000000000000", - "output_index": 0, - "tx_pointer_block_height": 0, - "tx_pointer_tx_idx": 0, - "states": [], - "balances": [] - }, - { - "contract_id": "0x7e2becd64cd598da59b4d1064b711661898656c6b1f4918a787156b8965dc83c", - "code": "1af030007400000200000000000014605dffc00110ffff00740000001aec500091000b285d43f015104103001a4460005d4d10491b441000104934405d47f008104404405d4920001b44144010453440504fb0205fed10045fed20055047ba8872500010284535005047ba88504fb46072500010284d15005d453000504fb0105fed10025fed20035047ba2872480010284534805047ba285fed00005d43f0085fed00015043b2d0724800102843b480504bb650724c0010284914c05047b660724c0010284504c01ae920001ae5100020f8330058fbe00250fbe0047400041a1a43d00076400001740000a71a4060005d41004a1b441000104104405047ba9872480020284504805043ba985047b03072480020284504805043b0b072480020284114805047b95072480020284504805043b95071440006504bb0f8724c0020284914c05047b890724c0020284504c05043b8f0724c0020284124c0a1411420764000065043b2e05fec005c504bb7907244001028490440740000085043b2805fec10505045000f5c4bf0505e452000504bb79072440010284904405d43f00b264000001a4070005fed01365d43f00b5fed01375fec01385057b9b05043b53072440010284124405d43b0f213410000764000475d43b0a613410040764000025d43f00c364000005043b5305041000f5c4100001ae810001ae5500020f8330058fbe00250fbe0047400042e5d4550005d4950015d4d5002104d3040165124c076500001135124c0765000065047b3605fec006c504fb7a072480018284d14807400000d124d3480104d30401b4d24c0264c0000281d14801a447000504bb1185fec10235fed10245fed3025504fb7a072440018284d24405047b54072480018284534805d47b0f4134510007644000f5d47b0a813451040764400025d43f00c364000005047b54050451008504bb5405049200850492008724c0008285514c050455008724c0008284524c05d4550005d4950021b481480104514805e4500005d415002104100405f550002740000061ae800001ae5500020f8330058fbe00250fbe004740003ef5043b9b050450010504bb1e0724c0008284904c050412008724c0008284114c05043ba3872440010284124405043ba385047b6c072480010284504801ae9100020f8330058fbe00250fbe004740004311a43d0005047ba38504bb780724c0010284914c01ae9200020f8330058fbe00250fbe004740003c01a47d000254110005d43f016104103005047ba28504bb3505fed006a5d43f00d5fed006b5043b3f0724c0010284124c0504bb670724c0010284914c05047b710724c0010284504c01ae920001ae5100020f8330058fbe00250fbe0047400035a1a43d000764000017400012f1a4060005d41004a1b441000104104405047bab872480020284504805043bab85047b05072480020284504805043b13072480020284114805047b97072480020284504805043b97071440006504bb150724c0020284914c05047b8b0724c0020284504c05043b910724c0020284124c0a1411420764000065043b3105fec0062504bb7b872440020284904407400002d5043b2905fec10525047b6405d4bf01710492300724c0008284524c05d4bf008264800001a4c7000284d14805047b1f05fed303e5d4bf00f5fed203f504bb470724c0010284914c05d492001504fb48072500010284d15005d4530001b492040504fb4b05fed10965fed20975047b4c072480010284534805d451000504bb4d072500010284935005d4920015053b4e072540010285135405d4d40015fed10535fed20545fed3055504bb7b872440020284904405d43f00b264000001a4070005fed01395d43f00b5fed013a5fec013b5057b9c85043b58872440020284124405d43b0f713410000764000aa5d43b0b113410040764000025d43f00c364000005043b588504100085047baf872480018284504801ae810001ae5500020f8330058fbe00250fbe00474000347505bbaf85d43b1615d4550005d4950015d4d50025d53f008104d3500165124c076500001135124c0765000065047b3a85fec0075504fb7d872480018284d14807400000d124d3480104d30401b4d24c0264c0000281d14801a447000504bb1705fec102e5fed102f5fed3030504fb7d872440018284d24405047b5d872480018284534805d47b0fb134510007644000f5d47b0bb13451040764400025d43f00c364000005047b5d850451008504bb5d85049200850492008724c0008285514c050455008724c0008284524c05d4550005d4950021b481480104514805f4500005d4150025d47f008104104405f5500021a5c00005d41600216417400764000017400005f5d416002164505c076440001134505c07644000b5d416000104105c05047b2f05fec105e5c4100005049100f5e490000504bb7f07240001028491400740000055043b0705fec000e504bb7f072440010284904405043b62072440010284124405d43b0fe1341004076400001360000005043b6205041000f5c4100005d4550005d4950015d4d5002104d3040165124c076500001135124c0765000065047b3785fec006f504fb80072480018284d14807400000d124d3480104d30401b4d24c0264c0000281d14801a447000504bb2005fec10405fed10415fed3042504fb80072440018284d24405047b55872480018284534805d47b100134510007644000f5d47b0ab13451040764400025d43f00c364000005047b55850451008504bb5585049200850492008724c0008285514c050455008724c0008284524c05d4550005d4950021b481480104514805e4500005d415002104100405f550002105d70407500005b1ae800001ae5500020f8330058fbe00250fbe004740002a75043b9c850450010504bb260724c0008284904c050412008724c0008284114c05043ba4872440010284124405043ba485047b6d072480010284504801ae9100020f8330058fbe00250fbe004740002e91a43d0005047ba48504bb680724c0010284914c01ae9200020f8330058fbe00250fbe004740002781a47d000254110005d43f018104103005047ba28504bb4005fed00805d43f0105fed00815043b410724c0010284124c0504bb720724c0010284914c05047b730724c0010284504c01ae920001ae5100020f8330058fbe00250fbe004740002121a43d000764000017400012f1a4060005d41004a1b441000104104405047bad872480020284504805043bad85047b08072480020284504805043b18872480020284114805047b99072480020284504805043b99071440006504bb1a8724c0020284914c05047b8d0724c0020284504c05043b930724c0020284124c0a1411420764000065043b3305fec0066504bb81872440020284904407400002d5043b2b05fec10565047b6485d4bf01910492300724c0008284524c05d4bf008264800001a4c7000284d14805047b2185fed30435d4bf0125fed2044504bb4f0724c0010284914c05d492001504fb50072500010284d15005d4530001b492040504fb5105fed10a25fed20a35047b52072480010284534805d451000504bb49072500010284935005d4920015053b4a072540010285135405d4d40015fed10575fed20585fed3059504bb81872440020284904405d43f00b264000001a4070005fed013c5d43f00b5fed013d5fec013e5057b9e05043b5a872440020284124405d43b10313410000764000aa5d43b0b513410040764000025d43f00c364000005043b5a8504100085047bb1072480018284504801ae810001ae5500020f8330058fbe00250fbe004740001ff505bbb105d43b1645d4550005d4950015d4d50025d53f008104d3500165124c076500001135124c0765000065047b3c05fec0078504fb83872480018284d14807400000d124d3480104d30401b4d24c0264c0000281d14801a447000504bb1c85fec10395fed103a5fed303b504fb83872440018284d24405047b5f072480018284534805d47b107134510007644000f5d47b0be13451040764400025d43f00c364000005047b5f050451008504bb5f05049200850492008724c0008285514c050455008724c0008284524c05d4550005d4950021b481480104514805f4500005d4150025d47f008104104405f5500021a5c00005d41600216417400764000017400005f5d416002164505c076440001134505c07644000b5d416000104105c05047b3005fec10605c4100005049100f5e490000504bb8507240001028491400740000055043b0a05fec0014504bb85072440010284904405043b63072440010284124405d43b10a1341004076400001360000005043b6305041000f5c4100005d4550005d4950015d4d5002104d3040165124c076500001135124c0765000065047b3905fec0072504fb86072480018284d14807400000d124d3480104d30401b4d24c0264c0000281d14801a447000504bb2285fec10455fed10465fed3047504fb86072440018284d24405047b57072480018284534805d47b10c134510007644000f5d47b0ae13451040764400025d43f00c364000005047b57050451008504bb5705049200850492008724c0008285514c050455008724c0008284524c05d4550005d4950021b481480104514805e4500005d415002104100405f550002105d70407500005b1ae800001ae5500020f8330058fbe00250fbe0047400015f5043b9e050450010504bb270724c0008284904c050412008724c0008284114c05043ba5872440010284124405043ba585047b6e072480010284504801ae9100020f8330058fbe00250fbe004740001a11a43d0005047ba58504bb690724c0010284914c01ae9200020f8330058fbe00250fbe004740001301a47d000254110005d43f01a104103005047ba28504bb4205fed00845d43f0135fed00855043b430724c0010284124c0504bb740724c0010284914c05047b750724c0010284504c01ae920001ae5100020f8330058fbe00250fbe004740000ca1a43d00076400001740000635d43f00b264000001a4070005fed013f5d43f00b5fed01405fec01415053b9f85d43b13f5d47b1405d4bb1415d4ff008104924c0164d1480764c0001134d1480764c00065043b3d85fec007b504bb87872440018284904407400000d12492440104920401b49148026480000281d04401a4070005047b0d05fec101a5fed001b5fed201c504bb87872400018284914005043b60872440018284124405d43b10f134100007640000f5d43b0c113410040764000025d43f00c364000005043b608504100085047b608504510085045100872480008285104805041400872480008284114805d4140005d4540021b441440104104401a4410005f4110005d4140025d47f008104104405f5100025043b9f850450010504bb240724c0008284904c050412008724c0008284114c05043ba6872440010284124405043ba685047b6f072480010284504801ae9100020f8330058fbe00250fbe004740001251a43d0005047ba68504bb6a0724c0010284914c01ae9200020f8330058fbe00250fbe004740000b41a47d000254110005d43f01b104103005047ba28504bb4405fed00885d43f0135fed00895043b450724c0010284124c0504bb760724c0010284914c05047b770724c0010284504c01ae920001ae5100020f8330058fbe00250fbe0047400004e1a43d00076400001740000495043b2505fec004a5d47f00b264400001a4470005fed11425d47f00b5fed11435fec01445047ba10504bb5c8724c0010284904c05d43b04a13410000764000135d43b0b913410040764000025d43f00c364000005d43b0ba1ae810001ae5100020f8330058fbe00250fbe0047400008e1ae900001ae5100020f8330058fbe00250fbe00474000088740000061ae800001ae5100020f8330058fbe00250fbe004740000815043ba1050450010504bb0e8724c0008284904c050412008724c0008284114c05043ba7872440010284124405043ba785047b70072480010284504801ae9100020f8330058fbe00250fbe004740000c31a43d0005047ba78504bb6b0724c0010284914c01ae9200020f8330058fbe00250fbe004740000521a47d000254110005d43f014364000009500003f960800001aec5000910000501a43a0001a4790001a4be000724c001028ed04c01aebb00020f8330058fbe00250fbe004740000301a4fd0005053b01072540010285115401ae9400020f8330058fbe00250fbe004740000271a53d000134d3500134d30001a500000764c001c504fb03072500010284d05001ae9300020f8330058fbe00250fbe004740000811a4fd0005053b04072540010285115401ae9400020f8330058fbe00250fbe004740000781a47d0005053b02072540010285105401ae9400020f8330058fbe00250fbe004740000081a43d000295134501af54000920000501af92000980800009700003f4af8000095000007960800001aec5000910000101a43a0001a47e0007248001028ed04801a43b0005d4100011af50000920000101af9100098080000970000074af8000095000007960800001aec5000910000101a43a0001a47e0007248001028ed04801a43b0005d410001124100401af50000920000101af9100098080000970000074af800009500007f960800001aec5000910000601a4fa0001a5790001a53e0005d5950005d4150015d4550025d4bf00810451480164904407648000113490440764800065043b0185fec0003504bb04872440018284904407400000c12451400104510401b45044026440000281d64001a4070005fec10005fed00015fed1002504bb04872400018284bb4005043b03072440018284124405d43b009134100007640000f5d43b00613410040764000025d43f00c364000005043b030504100085047b030504510085045100872480008285504805041500872480008284114805d4150005d4550021b441440104104405f4130005d4150025d47f008104104405f5500021af40000920000601af94000980800009700007f4af8000095000007960800001aec5000910000101a43a0001a47e0007248001028ed04801a43b0005d4100001af50000920000101af9100098080000970000074af8000095000007960800001aec5000910000101a43a0001a47e0007248001028ed04801a43b0005d4100001af50000920000101af9100098080000970000074af8000047000000646563696d616c736e616d650000000073796d626f6c0000746f74616c5f61737365747300000000746f74616c5f737570706c790000000000000000000002480000000000000008000000000000025009000000000000000000000000000400cccccccccccc0002000000000000000445746865720000000000000000000005000000000000000645544800000000000000000000000003000000000000000c000000000000007b0000000000001460000000000000146800000000000014d0000000000000147000000000000014e800000000000014780000000000001488", - "tx_id": "0000000000000000000000000000000000000000000000000000000000000001", - "output_index": 0, - "tx_pointer_block_height": 0, - "tx_pointer_tx_idx": 0, - "states": [], - "balances": [] - } - ], - "last_block": null -} \ No newline at end of file diff --git a/.github/workflows/local-testnode/state_transition_bytecode.wasm b/.github/workflows/local-testnode/state_transition_bytecode.wasm deleted file mode 100755 index 7547b6d1b09..00000000000 Binary files a/.github/workflows/local-testnode/state_transition_bytecode.wasm and /dev/null differ diff --git a/.github/workflows/scripts/verify_tag.sh b/.github/workflows/scripts/verify_tag.sh index e029f651988..6277011a708 100755 --- a/.github/workflows/scripts/verify_tag.sh +++ b/.github/workflows/scripts/verify_tag.sh @@ -6,30 +6,66 @@ err() { } status() { - WIDTH=12 - printf "\e[32m\e[1m%${WIDTH}s\e[0m %s\n" "$1" "$2" + local width=12 + printf "\e[32m\e[1m%${width}s\e[0m %s\n" "$1" "$2" +} + +get_toml_version () { + local toml_path="$1" + + local manifest="Cargo.toml" + echo $(toml get $manifest $toml_path | tr -d '"') +} + +check_version () { + local ref=$1 + local toml_path=$2 + + # strip preceeding 'v' if it exists on tag + ref=${ref/#v} + + local toml_version=$(get_toml_version "$toml_path") + + if [ "$toml_version" != "$ref" ]; then + err "Crate version $toml_version for $toml_path, doesn't match tag version $ref" + exit 1 + else + status "Crate version for $toml_path matches tag $toml_version" + fi } REF=$1 -MANIFEST=$2 if [ -z "$REF" ]; then err "Expected ref to be set" exit 1 fi -if [ -z "$MANIFEST" ]; then - err "Expected manifest to be set" - exit 1 -fi - -# strip preceeding 'v' if it exists on tag -REF=${REF/#v} -TOML_VERSION=$(toml get $MANIFEST package.version | tr -d '"') - -if [ "$TOML_VERSION" != "$REF" ]; then - err "Crate version $TOML_VERSION, doesn't match tag version $REF" - exit 1 -else - status "Crate version matches tag $TOML_VERSION" -fi +for toml_path in \ + "workspace.package.version" \ + "workspace.dependencies.forc.version" \ + "workspace.dependencies.forc-pkg.version" \ + "workspace.dependencies.forc-test.version" \ + "workspace.dependencies.forc-tracing.version" \ + "workspace.dependencies.forc-util.version" \ + "workspace.dependencies.forc-plugins.version" \ + "workspace.dependencies.forc-client.version" \ + "workspace.dependencies.forc-crypto.version" \ + "workspace.dependencies.forc-debug.version" \ + "workspace.dependencies.forc-doc.version" \ + "workspace.dependencies.forc-fmt.version" \ + "workspace.dependencies.forc-lsp.version" \ + "workspace.dependencies.forc-tx.version" \ + "workspace.dependencies.sway-ast.version" \ + "workspace.dependencies.sway-core.version" \ + "workspace.dependencies.sway-error.version" \ + "workspace.dependencies.sway-lsp.version" \ + "workspace.dependencies.sway-parse.version" \ + "workspace.dependencies.sway-types.version" \ + "workspace.dependencies.sway-utils.version" \ + "workspace.dependencies.swayfmt.version" \ + "workspace.dependencies.sway-ir.version" \ + "workspace.dependencies.sway-ir-macros.version" \ +; do + check_version $REF $toml_path +done diff --git a/.gitignore b/.gitignore index 3de2d377b4e..3b09835e4ac 100644 --- a/.gitignore +++ b/.gitignore @@ -32,3 +32,6 @@ forc-plugins/forc-debug/tests/**/Forc.lock # Generated files in example directories examples/**/*/Forc.lock docs/reference/src/code/examples/**/*/Forc.lock + +# Insta files +*.snap.new diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 00000000000..eb5c4aa3642 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,23 @@ +// Configuration for debugging the Sway Language Server (forc-lsp) +// Usage instructions: +// 1. Ensure you've built forc-lsp with debug symbols: +// cargo build -p forc-lsp +// 2. Install the debug version: +// cargo install --path ./forc-plugins/forc-lsp --debug +// 3. Open your Sway project in a separate VSCode window (this starts forc-lsp) +// 4. In the forc-lsp project window, set breakpoints in the code +// 5. Go to Run and Debug view, select "Attach to forc-lsp", and start debugging +// 6. When prompted, select the forc-lsp process +// 7. Debug forc-lsp as it responds to actions in your Sway project +{ + "version": "0.2.0", + "configurations": [ + { + "type": "lldb", + "request": "attach", + "name": "Attach to forc-lsp", + "pid": "${command:pickProcess}", + "program": "${env:HOME}/.cargo/bin/forc-lsp" + } + ] +} \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index 81fc6bbc554..4b067e99ad1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -14,18 +14,18 @@ dependencies = [ [[package]] name = "addr2line" -version = "0.21.0" +version = "0.24.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" dependencies = [ "gimli", ] [[package]] -name = "adler" -version = "1.0.2" +name = "adler2" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" [[package]] name = "aes" @@ -38,6 +38,17 @@ dependencies = [ "cpufeatures", ] +[[package]] +name = "ahash" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "891477e0c6a8957309ee5c45a6368af3ae14bb510732d2684ffa19af310920f9" +dependencies = [ + "getrandom", + "once_cell", + "version_check", +] + [[package]] name = "ahash" version = "0.8.11" @@ -45,7 +56,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" dependencies = [ "cfg-if 1.0.0", - "getrandom 0.2.15", + "getrandom", "once_cell", "version_check", "zerocopy", @@ -66,6 +77,79 @@ version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" +[[package]] +name = "alloy-eip2930" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0069cf0642457f87a01a014f6dc29d5d893cd4fd8fddf0c3cdfad1bb3ebafc41" +dependencies = [ + "alloy-primitives", + "alloy-rlp", + "serde", +] + +[[package]] +name = "alloy-eip7702" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea59dc42102bc9a1905dc57901edc6dd48b9f38115df86c7d252acba70d71d04" +dependencies = [ + "alloy-primitives", + "alloy-rlp", + "k256", + "serde", +] + +[[package]] +name = "alloy-primitives" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38f35429a652765189c1c5092870d8360ee7b7769b09b06d89ebaefd34676446" +dependencies = [ + "alloy-rlp", + "bytes", + "cfg-if 1.0.0", + "const-hex", + "derive_more 1.0.0", + "foldhash", + "hashbrown 0.15.0", + "hex-literal", + "indexmap 2.6.0", + "itoa", + "k256", + "keccak-asm", + "paste", + "proptest", + "rand", + "ruint", + "rustc-hash 2.0.0", + "serde", + "sha3", + "tiny-keccak", +] + +[[package]] +name = "alloy-rlp" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26154390b1d205a4a7ac7352aa2eb4f81f391399d4e2f546fb81a2f8bb383f62" +dependencies = [ + "alloy-rlp-derive", + "arrayvec", + "bytes", +] + +[[package]] +name = "alloy-rlp-derive" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d0f2d905ebd295e7effec65e5f6868d153936130ae718352771de3e7d03c75c" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.79", +] + [[package]] name = "android-tzdata" version = "0.1.1" @@ -108,9 +192,9 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.14" +version = "0.6.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "418c75fa768af9c03be99d17643f93f79bbba589895012a80e3452a19ddda15b" +checksum = "64e15c1ab1f89faffbf04a634d5e1962e9074f2741eef6d97f3c4e322426d526" dependencies = [ "anstyle", "anstyle-parse", @@ -123,33 +207,33 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.7" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b" +checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1" [[package]] name = "anstyle-parse" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c03a11a9034d92058ceb6ee011ce58af4a9bf61491aa7e1e59ecd24bd40d22d4" +checksum = "eb47de1e80c2b463c735db5b217a0ddc39d612e7ac9e2e96a5aed1f57616c1cb" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.0.3" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a64c907d4e79225ac72e2a354c9ce84d50ebb4586dee56c82b3ee73004f537f5" +checksum = "6d36fc52c7f6c869915e99412912f22093507da8d9e942ceaf66fe4b7c14422a" dependencies = [ "windows-sys 0.52.0", ] [[package]] name = "anstyle-wincon" -version = "3.0.3" +version = "3.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61a38449feb7068f52bb06c12759005cf459ee52bb4adc1d5a7c4322d716fb19" +checksum = "5bf74e1b6e971609db8ca7a9ce79fd5768ab6ae46441c572e46cf596f59e57f8" dependencies = [ "anstyle", "windows-sys 0.52.0", @@ -157,27 +241,151 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.86" +version = "1.0.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" +checksum = "86fdf8605db99b54d3cd748a44c6d04df638eb5dafb219b135d0149bd0db01f6" [[package]] -name = "arrayref" -version = "0.3.7" +name = "arc-swap" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b4930d2cb77ce62f89ee5d5289b4ac049559b1c45539271f5ed4fdc7db34545" +checksum = "69f7f8c3906b62b754cd5326047894316021dcfe5a194c8ea52bdd94934a3457" [[package]] -name = "arrayvec" -version = "0.5.2" +name = "ark-ff" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b3235cc41ee7a12aaaf2c575a2ad7b46713a8a50bda2fc3b003a04845c05dd6" +dependencies = [ + "ark-ff-asm 0.3.0", + "ark-ff-macros 0.3.0", + "ark-serialize 0.3.0", + "ark-std 0.3.0", + "derivative", + "num-bigint", + "num-traits", + "paste", + "rustc_version 0.3.3", + "zeroize", +] + +[[package]] +name = "ark-ff" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec847af850f44ad29048935519032c33da8aa03340876d351dfab5660d2966ba" +dependencies = [ + "ark-ff-asm 0.4.2", + "ark-ff-macros 0.4.2", + "ark-serialize 0.4.2", + "ark-std 0.4.0", + "derivative", + "digest 0.10.7", + "itertools 0.10.5", + "num-bigint", + "num-traits", + "paste", + "rustc_version 0.4.1", + "zeroize", +] + +[[package]] +name = "ark-ff-asm" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db02d390bf6643fb404d3d22d31aee1c4bc4459600aef9113833d17e786c6e44" +dependencies = [ + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-ff-asm" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" +checksum = "3ed4aa4fe255d0bc6d79373f7e31d2ea147bcf486cba1be5ba7ea85abdb92348" +dependencies = [ + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-ff-macros" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db2fd794a08ccb318058009eefdf15bcaaaaf6f8161eb3345f907222bac38b20" +dependencies = [ + "num-bigint", + "num-traits", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-ff-macros" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7abe79b0e4288889c4574159ab790824d0033b9fdcb2a112a3182fac2e514565" +dependencies = [ + "num-bigint", + "num-traits", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-serialize" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d6c2b318ee6e10f8c2853e73a83adc0ccb88995aa978d8a3408d492ab2ee671" +dependencies = [ + "ark-std 0.3.0", + "digest 0.9.0", +] + +[[package]] +name = "ark-serialize" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adb7b85a02b83d2f22f89bd5cac66c9c89474240cb6207cb1efc16d098e822a5" +dependencies = [ + "ark-std 0.4.0", + "digest 0.10.7", + "num-bigint", +] + +[[package]] +name = "ark-std" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1df2c09229cbc5a028b1d70e00fdb2acee28b1055dfb5ca73eea49c5a25c4e7c" +dependencies = [ + "num-traits", + "rand", +] + +[[package]] +name = "ark-std" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94893f1e0c6eeab764ade8dc4c0db24caf4fe7cbbaafc0eba0a9030f447b5185" +dependencies = [ + "num-traits", + "rand", +] + +[[package]] +name = "arrayref" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb" [[package]] name = "arrayvec" -version = "0.7.4" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" [[package]] name = "ascii" @@ -208,114 +416,405 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b34d609dfbaf33d6889b2b7106d3ca345eacad44200913df5ba02bfd31d2ba9" [[package]] -name = "async-trait" -version = "0.1.80" +name = "async-trait" +version = "0.1.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.79", +] + +[[package]] +name = "atomic-polyfill" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8cf2bce30dfe09ef0bfaef228b9d414faaf7e563035494d7fe092dba54b300f4" +dependencies = [ + "critical-section", +] + +[[package]] +name = "atomic-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi 0.1.19", + "libc", + "winapi", +] + +[[package]] +name = "aurora-engine-modexp" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0aef7712851e524f35fbbb74fa6599c5cd8692056a1c36f9ca0d2001b670e7e5" +dependencies = [ + "hex", + "num", +] + +[[package]] +name = "auto_impl" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c87f3f15e7794432337fc718554eaa4dc8f04c9677a950ffe366f20a162ae42" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.79", +] + +[[package]] +name = "autocfg" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" + +[[package]] +name = "aws-config" +version = "1.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7198e6f03240fdceba36656d8be440297b6b82270325908c7381f37d826a74f6" +dependencies = [ + "aws-credential-types", + "aws-runtime", + "aws-sdk-sso", + "aws-sdk-ssooidc", + "aws-sdk-sts", + "aws-smithy-async", + "aws-smithy-http", + "aws-smithy-json", + "aws-smithy-runtime", + "aws-smithy-runtime-api", + "aws-smithy-types", + "aws-types", + "bytes", + "fastrand", + "hex", + "http 0.2.12", + "ring", + "time", + "tokio", + "tracing", + "url", + "zeroize", +] + +[[package]] +name = "aws-credential-types" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60e8f6b615cb5fc60a98132268508ad104310f0cfb25a1c22eee76efdf9154da" +dependencies = [ + "aws-smithy-async", + "aws-smithy-runtime-api", + "aws-smithy-types", + "zeroize", +] + +[[package]] +name = "aws-runtime" +version = "1.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a10d5c055aa540164d9561a0e2e74ad30f0dcf7393c3a92f6733ddf9c5762468" +dependencies = [ + "aws-credential-types", + "aws-sigv4", + "aws-smithy-async", + "aws-smithy-http", + "aws-smithy-runtime", + "aws-smithy-runtime-api", + "aws-smithy-types", + "aws-types", + "bytes", + "fastrand", + "http 0.2.12", + "http-body 0.4.6", + "once_cell", + "percent-encoding", + "pin-project-lite", + "tracing", + "uuid 1.11.0", +] + +[[package]] +name = "aws-sdk-kms" +version = "1.47.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "564a597a3c71a957d60a2e4c62c93d78ee5a0d636531e15b760acad983a5c18e" +dependencies = [ + "aws-credential-types", + "aws-runtime", + "aws-smithy-async", + "aws-smithy-http", + "aws-smithy-json", + "aws-smithy-runtime", + "aws-smithy-runtime-api", + "aws-smithy-types", + "aws-types", + "bytes", + "http 0.2.12", + "once_cell", + "regex-lite", + "tracing", +] + +[[package]] +name = "aws-sdk-sso" +version = "1.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dc2faec3205d496c7e57eff685dd944203df7ce16a4116d0281c44021788a7b" +dependencies = [ + "aws-credential-types", + "aws-runtime", + "aws-smithy-async", + "aws-smithy-http", + "aws-smithy-json", + "aws-smithy-runtime", + "aws-smithy-runtime-api", + "aws-smithy-types", + "aws-types", + "bytes", + "http 0.2.12", + "once_cell", + "regex-lite", + "tracing", +] + +[[package]] +name = "aws-sdk-ssooidc" +version = "1.47.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c93c241f52bc5e0476e259c953234dab7e2a35ee207ee202e86c0095ec4951dc" +dependencies = [ + "aws-credential-types", + "aws-runtime", + "aws-smithy-async", + "aws-smithy-http", + "aws-smithy-json", + "aws-smithy-runtime", + "aws-smithy-runtime-api", + "aws-smithy-types", + "aws-types", + "bytes", + "http 0.2.12", + "once_cell", + "regex-lite", + "tracing", +] + +[[package]] +name = "aws-sdk-sts" +version = "1.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b259429be94a3459fa1b00c5684faee118d74f9577cc50aebadc36e507c63b5f" +dependencies = [ + "aws-credential-types", + "aws-runtime", + "aws-smithy-async", + "aws-smithy-http", + "aws-smithy-json", + "aws-smithy-query", + "aws-smithy-runtime", + "aws-smithy-runtime-api", + "aws-smithy-types", + "aws-smithy-xml", + "aws-types", + "http 0.2.12", + "once_cell", + "regex-lite", + "tracing", +] + +[[package]] +name = "aws-sigv4" +version = "1.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc8db6904450bafe7473c6ca9123f88cc11089e41a025408f992db4e22d3be68" +dependencies = [ + "aws-credential-types", + "aws-smithy-http", + "aws-smithy-runtime-api", + "aws-smithy-types", + "bytes", + "form_urlencoded", + "hex", + "hmac 0.12.1", + "http 0.2.12", + "http 1.1.0", + "once_cell", + "percent-encoding", + "sha2 0.10.8", + "time", + "tracing", +] + +[[package]] +name = "aws-smithy-async" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62220bc6e97f946ddd51b5f1361f78996e704677afc518a4ff66b7a72ea1378c" +dependencies = [ + "futures-util", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "aws-smithy-http" +version = "0.60.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6fa2087f2753a7da8cc1c0dbfcf89579dd57458e36769de5ac750b4671737ca" +checksum = "5c8bc3e8fdc6b8d07d976e301c02fe553f72a39b7a9fea820e023268467d7ab6" dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.65", + "aws-smithy-runtime-api", + "aws-smithy-types", + "bytes", + "bytes-utils", + "futures-core", + "http 0.2.12", + "http-body 0.4.6", + "once_cell", + "percent-encoding", + "pin-project-lite", + "pin-utils", + "tracing", ] [[package]] -name = "atomic-polyfill" -version = "1.0.3" +name = "aws-smithy-json" +version = "0.60.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cf2bce30dfe09ef0bfaef228b9d414faaf7e563035494d7fe092dba54b300f4" +checksum = "4683df9469ef09468dad3473d129960119a0d3593617542b7d52086c8486f2d6" dependencies = [ - "critical-section", + "aws-smithy-types", ] [[package]] -name = "atty" -version = "0.2.14" +name = "aws-smithy-query" +version = "0.60.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +checksum = "f2fbd61ceb3fe8a1cb7352e42689cec5335833cd9f94103a61e98f9bb61c64bb" dependencies = [ - "hermit-abi 0.1.19", - "libc", - "winapi", + "aws-smithy-types", + "urlencoding", ] [[package]] -name = "auto_impl" -version = "1.2.0" +name = "aws-smithy-runtime" +version = "1.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c87f3f15e7794432337fc718554eaa4dc8f04c9677a950ffe366f20a162ae42" +checksum = "a065c0fe6fdbdf9f11817eb68582b2ab4aff9e9c39e986ae48f7ec576c6322db" dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.65", + "aws-smithy-async", + "aws-smithy-http", + "aws-smithy-runtime-api", + "aws-smithy-types", + "bytes", + "fastrand", + "h2 0.3.26", + "http 0.2.12", + "http-body 0.4.6", + "http-body 1.0.1", + "httparse", + "hyper 0.14.31", + "hyper-rustls 0.24.2", + "once_cell", + "pin-project-lite", + "pin-utils", + "rustls 0.21.12", + "tokio", + "tracing", ] [[package]] -name = "autocfg" -version = "1.3.0" +name = "aws-smithy-runtime-api" +version = "1.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" +checksum = "e086682a53d3aa241192aa110fa8dfce98f2f5ac2ead0de84d41582c7e8fdb96" +dependencies = [ + "aws-smithy-async", + "aws-smithy-types", + "bytes", + "http 0.2.12", + "http 1.1.0", + "pin-project-lite", + "tokio", + "tracing", + "zeroize", +] [[package]] -name = "axum" -version = "0.5.17" +name = "aws-smithy-types" +version = "1.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acee9fd5073ab6b045a275b3e709c163dd36c90685219cb21804a147b58dba43" +checksum = "147100a7bea70fa20ef224a6bad700358305f5dc0f84649c53769761395b355b" dependencies = [ - "async-trait", - "axum-core", - "bitflags 1.3.2", + "base64-simd", "bytes", - "futures-util", - "http", - "http-body", - "hyper", + "bytes-utils", + "futures-core", + "http 0.2.12", + "http 1.1.0", + "http-body 0.4.6", + "http-body 1.0.1", + "http-body-util", "itoa", - "matchit", - "memchr", - "mime", - "percent-encoding", + "num-integer", "pin-project-lite", + "pin-utils", + "ryu", "serde", - "serde_json", - "serde_urlencoded", - "sync_wrapper", + "time", "tokio", - "tower", - "tower-http", - "tower-layer", - "tower-service", + "tokio-util", ] [[package]] -name = "axum-core" -version = "0.2.9" +name = "aws-smithy-xml" +version = "0.60.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37e5939e02c56fecd5c017c37df4238c0a839fa76b7f97acdd7efb804fd181cc" +checksum = "ab0b0166827aa700d3dc519f72f8b3a91c35d0b8d042dc5d643a91e6f80648fc" dependencies = [ - "async-trait", - "bytes", - "futures-util", - "http", - "http-body", - "mime", - "tower-layer", - "tower-service", + "xmlparser", +] + +[[package]] +name = "aws-types" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5221b91b3e441e6675310829fd8984801b772cb1546ef6c0e54dec9f1ac13fef" +dependencies = [ + "aws-credential-types", + "aws-smithy-async", + "aws-smithy-runtime-api", + "aws-smithy-types", + "rustc_version 0.4.1", + "tracing", ] [[package]] name = "backtrace" -version = "0.3.71" +version = "0.3.74" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" +checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" dependencies = [ "addr2line", - "cc", "cfg-if 1.0.0", "libc", "miniz_oxide", "object", "rustc-demangle", "serde", + "windows-targets 0.52.6", ] [[package]] @@ -348,6 +847,16 @@ version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" +[[package]] +name = "base64-simd" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "339abbe78e73178762e23bea9dfd08e697eb3f3301cd4be981c0f78ba5859195" +dependencies = [ + "outref", + "vsimd", +] + [[package]] name = "base64ct" version = "1.6.0" @@ -398,9 +907,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.5.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" dependencies = [ "serde", ] @@ -427,67 +936,57 @@ dependencies = [ ] [[package]] -name = "blake2b_simd" -version = "0.5.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afa748e348ad3be8263be728124b24a24f268266f6f5d58af9d75f6a40b5c587" -dependencies = [ - "arrayref", - "arrayvec 0.5.2", - "constant_time_eq 0.1.5", -] - -[[package]] -name = "blake2b_simd" -version = "1.0.2" +name = "block-buffer" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23285ad32269793932e830392f2fe2f83e26488fd3ec778883a93c8323735780" +checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" dependencies = [ - "arrayref", - "arrayvec 0.7.4", - "constant_time_eq 0.3.0", + "generic-array", ] [[package]] -name = "blake2s_simd" -version = "1.0.2" +name = "block-buffer" +version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94230421e395b9920d23df13ea5d77a20e1725331f90fbbf6df6040b33f756ae" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" dependencies = [ - "arrayref", - "arrayvec 0.7.4", - "constant_time_eq 0.3.0", + "generic-array", ] [[package]] -name = "blake3" -version = "1.5.1" +name = "blst" +version = "0.3.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30cca6d3674597c30ddf2c587bf8d9d65c9a84d2326d941cc79c9842dfe0ef52" +checksum = "4378725facc195f1a538864863f6de233b500a8862747e7f165078a419d5e874" dependencies = [ - "arrayref", - "arrayvec 0.7.4", "cc", - "cfg-if 1.0.0", - "constant_time_eq 0.3.0", + "glob", + "threadpool", + "zeroize", ] [[package]] -name = "block-buffer" -version = "0.9.0" +name = "borsh" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" +checksum = "a6362ed55def622cddc70a4746a68554d7b687713770de539e59a739b249f8ed" dependencies = [ - "generic-array", + "borsh-derive", + "cfg_aliases", ] [[package]] -name = "block-buffer" -version = "0.10.4" +name = "borsh-derive" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +checksum = "c3ef8005764f53cd4dca619f5bf64cafd4664dada50ece25e4d81de54c80cc0b" dependencies = [ - "generic-array", + "once_cell", + "proc-macro-crate 3.2.0", + "proc-macro2", + "quote", + "syn 2.0.79", + "syn_derive", ] [[package]] @@ -502,12 +1001,12 @@ dependencies = [ [[package]] name = "bstr" -version = "1.9.1" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05efc5cfd9110c8416e471df0e96702d58690178e206e61b7173706673c93706" +checksum = "40723b8fb387abc38f4f4a37c09073622e41dd12327033091ef8950659e6dc0c" dependencies = [ "memchr", - "regex-automata 0.4.6", + "regex-automata 0.4.8", "serde", ] @@ -523,6 +1022,39 @@ version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3ac9f8b63eca6fd385229b3675f6cc0dc5c8a5c8a54a59d4f52ffd670d87b0c" +[[package]] +name = "byte-unit" +version = "5.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33ac19bdf0b2665407c39d82dbc937e951e7e2001609f0fb32edd0af45a2d63e" +dependencies = [ + "rust_decimal", + "serde", + "utf8-width", +] + +[[package]] +name = "bytecheck" +version = "0.6.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23cdc57ce23ac53c931e88a43d06d070a6fd142f2617be5855eb75efc9beb1c2" +dependencies = [ + "bytecheck_derive", + "ptr_meta", + "simdutf8", +] + +[[package]] +name = "bytecheck_derive" +version = "0.6.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3db406d29fbcd95542e92559bed4d8ad92636d1ca8b3b72ede10b4bcc010e659" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "bytecount" version = "0.6.8" @@ -537,9 +1069,44 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.6.0" +version = "1.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "428d9aa8fbc0670b7b8d6030a7fadd0f86151cae55e4dbbece15f3780a3dfaf3" + +[[package]] +name = "bytes-utils" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dafe3a8757b027e2be6e4e5601ed563c55989fcf1546e933c66c8eb3a058d35" +dependencies = [ + "bytes", + "either", +] + +[[package]] +name = "c-kzg" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0307f72feab3300336fb803a57134159f6e20139af1357f36c54cb90d8e8928" +dependencies = [ + "blst", + "cc", + "glob", + "hex", + "libc", + "once_cell", + "serde", +] + +[[package]] +name = "caseless" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" +checksum = "808dab3318747be122cb31d36de18d4d1c81277a76f8332a02b81a3d73463d7f" +dependencies = [ + "regex", + "unicode-normalization", +] [[package]] name = "cast" @@ -549,13 +1116,13 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.0.98" +version = "1.1.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41c270e7540d725e65ac7f1b212ac8ce349719624d7bcff99f8e2e488e8cf03f" +checksum = "b16803a61b81d9eabb7eae2588776c4c1e584b738ede45fdbb4c972cec1e9945" dependencies = [ "jobserver", "libc", - "once_cell", + "shlex", ] [[package]] @@ -570,6 +1137,12 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "cfg_aliases" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" + [[package]] name = "chrono" version = "0.4.38" @@ -582,7 +1155,7 @@ dependencies = [ "num-traits", "serde", "wasm-bindgen", - "windows-targets 0.52.5", + "windows-targets 0.52.6", ] [[package]] @@ -614,15 +1187,14 @@ dependencies = [ [[package]] name = "cid" -version = "0.10.1" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd94671561e36e4e7de75f753f577edafb0e7c05d6e4547229fdf7938fbcd2c3" +checksum = "3147d8272e8fa0ccd29ce51194dd98f79ddfb8191ba9e3409884e751798acf3a" dependencies = [ "core2", "multibase", - "multihash 0.18.1", - "serde", - "unsigned-varint", + "multihash 0.19.1", + "unsigned-varint 0.8.0", ] [[package]] @@ -652,9 +1224,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.4" +version = "4.5.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90bc066a67923782aa8515dbaea16946c5bcc5addbd668bb80af688e53e548a0" +checksum = "b97f376d85a664d5837dbae44bf546e6477a679ff6610010f17276f686d867e8" dependencies = [ "clap_builder", "clap_derive", @@ -662,9 +1234,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.2" +version = "4.5.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae129e2e766ae0ec03484e609954119f123cc1fe650337e155d03b022f24f7b4" +checksum = "19bc80abd44e4bed93ca373a0704ccbd1b710dc5749406201bb018272808dc54" dependencies = [ "anstream", "anstyle", @@ -675,50 +1247,48 @@ dependencies = [ [[package]] name = "clap_complete" -version = "4.5.2" +version = "4.5.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd79504325bf38b10165b02e89b4347300f855f273c4cb30c4a3209e6583275e" +checksum = "9646e2e245bf62f45d39a0f3f36f1171ad1ea0d6967fd114bca72cb02a8fcdfb" dependencies = [ - "clap 4.5.4", + "clap 4.5.20", ] [[package]] name = "clap_complete_fig" -version = "4.5.0" +version = "4.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54b3e65f91fabdd23cac3d57d39d5d938b4daabd070c335c006dccb866a61110" +checksum = "d494102c8ff3951810c72baf96910b980fb065ca5d3101243e6a8dc19747c86b" dependencies = [ - "clap 4.5.4", + "clap 4.5.20", "clap_complete", ] [[package]] name = "clap_derive" -version = "4.5.4" +version = "4.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "528131438037fd55894f62d6e9f068b8f45ac57ffa77517819645d10aed04f64" +checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab" dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.65", + "syn 2.0.79", ] [[package]] name = "clap_lex" -version = "0.7.0" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce" +checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97" [[package]] name = "clipboard-win" -version = "4.5.0" +version = "5.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7191c27c2357d9b7ef96baac1773290d4ca63b24205b82a3fd8a0637afcf0362" +checksum = "15efe7a882b08f34e38556b14f2fb3daa98769d06c7f0c1b076dfd0d983bc892" dependencies = [ "error-code", - "str-buf", - "winapi", ] [[package]] @@ -727,6 +1297,28 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "67ba02a97a2bd10f4b59b25c7973101c79642302776489e030cd13cdab09ed15" +[[package]] +name = "codspeed" +version = "2.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "450a0e9df9df1c154156f4344f99d8f6f6e69d0fc4de96ef6e2e68b2ec3bce97" +dependencies = [ + "colored", + "libc", + "serde_json", +] + +[[package]] +name = "codspeed-criterion-compat" +version = "2.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8eb1a6cb9c20e177fde58cdef97c1c7c9264eb1424fe45c4fccedc2fb078a569" +dependencies = [ + "codspeed", + "colored", + "criterion", +] + [[package]] name = "coins-bip32" version = "0.8.7" @@ -781,9 +1373,9 @@ dependencies = [ [[package]] name = "colorchoice" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422" +checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0" [[package]] name = "colored" @@ -808,6 +1400,12 @@ dependencies = [ "unreachable", ] +[[package]] +name = "comma" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55b672471b4e9f9e95499ea597ff64941a309b2cdbffcc46f2cc5e2d971fd335" + [[package]] name = "common-multipart-rfc7578" version = "0.6.0" @@ -817,7 +1415,7 @@ dependencies = [ "bytes", "futures-core", "futures-util", - "http", + "http 0.2.12", "mime", "mime_guess", "rand", @@ -826,15 +1424,15 @@ dependencies = [ [[package]] name = "completest" -version = "0.4.0" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8229e041ca8f8130ad7f0ce1afb9cfdb3033de7fd548e6422dbb2f4f12184f41" +checksum = "410de1ffe61368aa040f599747584e9e3d19235cf4045be6159edb167ef45ddb" [[package]] name = "completest-pty" -version = "0.5.0" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a6d1272e27f608f97616be67a2aed03ed8d73910b5df9a7f4a50c4ffd59d185" +checksum = "fbd2f22a999db122bd2861c504aa363bbacaa32ebea29edf6924ee6cfe044313" dependencies = [ "completest", "ptyprocess", @@ -843,16 +1441,16 @@ dependencies = [ [[package]] name = "comrak" -version = "0.16.0" +version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "784836d0812dade01579cc0cc9b1684847044e716fd7aa6bffbc172e42199500" +checksum = "c93ab3577cca16b4a1d80a88c2e0cd8b6e969e51696f0bbb0d1dcb0157109832" dependencies = [ - "clap 4.5.4", + "caseless", + "clap 4.5.20", + "derive_builder", "entities", "memchr", "once_cell", - "pest", - "pest_derive", "regex", "shell-words", "slug", @@ -871,26 +1469,28 @@ dependencies = [ "encode_unicode 0.3.6", "lazy_static", "libc", + "unicode-width", "windows-sys 0.52.0", ] [[package]] -name = "const-oid" -version = "0.9.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" - -[[package]] -name = "constant_time_eq" -version = "0.1.5" +name = "const-hex" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" +checksum = "0121754e84117e65f9d90648ee6aa4882a6e63110307ab73967a4c5e7e69e586" +dependencies = [ + "cfg-if 1.0.0", + "cpufeatures", + "hex", + "proptest", + "serde", +] [[package]] -name = "constant_time_eq" -version = "0.3.0" +name = "const-oid" +version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7144d30dcf0fafbce74250a3963025d8d52177934239851c917d29f1df280c2" +checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" [[package]] name = "convert_case" @@ -938,9 +1538,9 @@ dependencies = [ [[package]] name = "core-foundation-sys" -version = "0.8.6" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] name = "core2" @@ -962,15 +1562,15 @@ dependencies = [ [[package]] name = "countme" -version = "2.0.4" +version = "3.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "328b822bdcba4d4e402be8d9adb6eebf269f969f8eadef977a553ff3c4fbcb58" +checksum = "7704b5fdd17b18ae31c4c1da5a2e0305a2bf17b5249300a9ee9ed7b72114c636" [[package]] name = "cpufeatures" -version = "0.2.12" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" +checksum = "608697df725056feaccfa42cffdaeeec3fccc4ffc38358ecd19b243e716a78e0" dependencies = [ "libc", ] @@ -993,7 +1593,7 @@ dependencies = [ "anes", "cast", "ciborium", - "clap 4.5.4", + "clap 4.5.20", "criterion-plot", "is-terminal", "itertools 0.10.5", @@ -1022,9 +1622,9 @@ dependencies = [ [[package]] name = "critical-section" -version = "1.1.2" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7059fff8937831a9ae6f0fe4d658ffabf58f2ca96aa9dec1c889f936f705f216" +checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b" [[package]] name = "crossbeam-channel" @@ -1119,15 +1719,6 @@ dependencies = [ "memchr", ] -[[package]] -name = "ct-logs" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1a816186fa68d9e426e3cb4ae4dff1fcd8e4a2c34b781bf7a822574a0d0aac8" -dependencies = [ - "sct 0.6.1", -] - [[package]] name = "ctr" version = "0.9.2" @@ -1139,17 +1730,16 @@ dependencies = [ [[package]] name = "curve25519-dalek" -version = "4.1.2" +version = "4.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a677b8922c94e01bdbb12126b0bc852f00447528dee1782229af9c720c3f348" +checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be" dependencies = [ "cfg-if 1.0.0", "cpufeatures", "curve25519-dalek-derive", "digest 0.10.7", "fiat-crypto", - "platforms", - "rustc_version", + "rustc_version 0.4.1", "subtle", ] @@ -1161,7 +1751,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.65", + "syn 2.0.79", ] [[package]] @@ -1171,7 +1761,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b1afa0591b1021e427e548a1f0f147fe6168f6c7c7f7006bace77f28856051b8" dependencies = [ "cynic-proc-macros", - "reqwest", + "reqwest 0.11.27", "serde", "serde_json", "static_assertions", @@ -1227,12 +1817,12 @@ dependencies = [ [[package]] name = "darling" -version = "0.20.9" +version = "0.20.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83b2eb4d90d12bdda5ed17de686c2acb4c57914f8f921b8da7e112b5a36f3fe1" +checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989" dependencies = [ - "darling_core 0.20.9", - "darling_macro 0.20.9", + "darling_core 0.20.10", + "darling_macro 0.20.10", ] [[package]] @@ -1251,16 +1841,16 @@ dependencies = [ [[package]] name = "darling_core" -version = "0.20.9" +version = "0.20.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "622687fe0bac72a04e5599029151f5796111b90f1baaa9b544d807a5e31cd120" +checksum = "95133861a8032aaea082871032f5815eb9e98cef03fa916ab4500513994df9e5" dependencies = [ "fnv", "ident_case", "proc-macro2", "quote", "strsim 0.11.1", - "syn 2.0.65", + "syn 2.0.79", ] [[package]] @@ -1276,22 +1866,36 @@ dependencies = [ [[package]] name = "darling_macro" -version = "0.20.9" +version = "0.20.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "733cabb43482b1a1b53eee8583c2b9e8684d592215ea83efd305dd31bc2f0178" +checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" dependencies = [ - "darling_core 0.20.9", + "darling_core 0.20.10", "quote", - "syn 2.0.65", + "syn 2.0.79", +] + +[[package]] +name = "dashmap" +version = "5.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" +dependencies = [ + "cfg-if 1.0.0", + "hashbrown 0.14.5", + "lock_api", + "once_cell", + "parking_lot_core 0.9.10", ] [[package]] name = "dashmap" -version = "5.5.3" +version = "6.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" +checksum = "5041cc499144891f3790297212f32a74fb938e5136a14943f338ef9e0ae276cf" dependencies = [ "cfg-if 1.0.0", + "crossbeam-utils", "hashbrown 0.14.5", "lock_api", "once_cell", @@ -1366,17 +1970,69 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "derive_builder" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "507dfb09ea8b7fa618fcf76e953f4f5e192547945816d5358edffe39f6f94947" +dependencies = [ + "derive_builder_macro", +] + +[[package]] +name = "derive_builder_core" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d5bcf7b024d6835cfb3d473887cd966994907effbe9227e8c8219824d06c4e8" +dependencies = [ + "darling 0.20.10", + "proc-macro2", + "quote", + "syn 2.0.79", +] + +[[package]] +name = "derive_builder_macro" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c" +dependencies = [ + "derive_builder_core", + "syn 2.0.79", +] + [[package]] name = "derive_more" -version = "0.99.17" +version = "0.99.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" +checksum = "5f33878137e4dafd7fa914ad4e259e18a4e8e532b9617a2d0150262bf53abfce" dependencies = [ "convert_case", "proc-macro2", "quote", - "rustc_version", - "syn 1.0.109", + "rustc_version 0.4.1", + "syn 2.0.79", +] + +[[package]] +name = "derive_more" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a9b99b9cbbe49445b21764dc0625032a89b145a2642e67603e1c936f5458d05" +dependencies = [ + "derive_more-impl", +] + +[[package]] +name = "derive_more-impl" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7330aeadfbe296029522e6c40f315320aba36fc43a5b3632f3795348f3bd22" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.79", + "unicode-xid", ] [[package]] @@ -1387,15 +2043,28 @@ checksum = "339544cc9e2c4dc3fc7149fd630c5f22263a4fdf18a98afd0075784968b5cf00" [[package]] name = "devault" -version = "0.1.0" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffc1d36b1abcd53bf307972de38ed2da0a57ddeb762b141420067149d3952c9a" +checksum = "b6bd8149b97caf4a72d9dd6b09a4192fcc07c2551ef5c949ea488554a9994649" dependencies = [ "proc-macro2", "quote", "syn 1.0.109", ] +[[package]] +name = "dialoguer" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "658bce805d770f407bc62102fca7c2c64ceef2fbcb2b8bd19d2765ce093980de" +dependencies = [ + "console", + "shell-words", + "tempfile", + "thiserror", + "zeroize", +] + [[package]] name = "diff" version = "0.1.13" @@ -1437,31 +2106,20 @@ checksum = "363641827cb8d8387a69364aa2f85433db83b8b00270ed2c786235d83bf0aa0a" [[package]] name = "dirs" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fd78930633bd1c6e35c4b42b1df7b0cbc6bc191146e512bb3bedf243fcc3901" -dependencies = [ - "libc", - "redox_users 0.3.5", - "winapi", -] - -[[package]] -name = "dirs" -version = "3.0.2" +version = "4.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30baa043103c9d0c2a57cf537cc2f35623889dc0d405e6c3cccfadbc81c71309" +checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059" dependencies = [ - "dirs-sys", + "dirs-sys 0.3.7", ] [[package]] name = "dirs" -version = "4.0.0" +version = "5.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059" +checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225" dependencies = [ - "dirs-sys", + "dirs-sys 0.4.1", ] [[package]] @@ -1481,10 +2139,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6" dependencies = [ "libc", - "redox_users 0.4.5", + "redox_users", "winapi", ] +[[package]] +name = "dirs-sys" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c" +dependencies = [ + "libc", + "option-ext", + "redox_users", + "windows-sys 0.48.0", +] + [[package]] name = "dirs-sys-next" version = "0.1.2" @@ -1492,7 +2162,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" dependencies = [ "libc", - "redox_users 0.4.5", + "redox_users", "winapi", ] @@ -1520,6 +2190,24 @@ version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dcbb2bf8e87535c23f7a8a321e364ce21462d0ff10cb6407820e8e96dfff6653" +[[package]] +name = "duct" +version = "0.13.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4ab5718d1224b63252cd0c6f74f6480f9ffeb117438a2e0f5cf6d9a4798929c" +dependencies = [ + "libc", + "once_cell", + "os_pipe", + "shared_child", +] + +[[package]] +name = "dyn-clone" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d6ef0072f8a535281e4876be788938b528e9a1d43900b82c2569af7da799125" + [[package]] name = "ecdsa" version = "0.16.9" @@ -1569,9 +2257,9 @@ dependencies = [ [[package]] name = "either" -version = "1.12.0" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3dca9240753cf90908d7e4aac30f630662b02aebaa1b58a3cadabdb23385b58b" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" [[package]] name = "elliptic-curve" @@ -1598,6 +2286,12 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ef1a6892d9eef45c8fa6b9e0086428a2cca8491aca8f787c534a3d6d0bcb3ced" +[[package]] +name = "embedded-io" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edd0f118536f44f5ccd48bcb8b111bdc3de888b58c74639dfb034a357d0f206d" + [[package]] name = "encode_unicode" version = "0.3.6" @@ -1648,7 +2342,7 @@ checksum = "a1ab991c1362ac86c61ab6f556cff143daa22e5a15e4e189df818b2fd19fe65b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.65", + "syn 2.0.79", ] [[package]] @@ -1661,14 +2355,25 @@ dependencies = [ "num-traits", "proc-macro2", "quote", - "syn 2.0.65", + "syn 2.0.79", +] + +[[package]] +name = "enumn" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f9ed6b3789237c8a0c1c505af1c7eb2c560df6186f01b098c3a1064ea532f38" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.79", ] [[package]] name = "env_filter" -version = "0.1.0" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a009aa4810eb158359dda09d0c87378e4bbb89b5a801f016885a4707ba24f7ea" +checksum = "4f2c92ceda6ceec50f43169f9ee8424fe2db276791afde7b2cd8bc084cb376ab" dependencies = [ "log", "regex", @@ -1676,9 +2381,9 @@ dependencies = [ [[package]] name = "env_logger" -version = "0.11.3" +version = "0.11.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38b35839ba51819680ba087cd351788c9a3c476841207e0b8cee0b04722343b9" +checksum = "e13fa619b91fb2381732789fc5de83b45675e882f66623b7d8cb4f643017018d" dependencies = [ "anstream", "anstyle", @@ -1715,19 +2420,21 @@ dependencies = [ [[package]] name = "error-code" -version = "2.3.1" +version = "3.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64f18991e7bf11e7ffee451b5318b5c1a73c52d0d0ada6e5a3017c8c1ced6a21" -dependencies = [ - "libc", - "str-buf", -] +checksum = "a5d9305ccc6942a704f4335694ecd3de2ea531b114ac2d51f5f843750787a92f" + +[[package]] +name = "escape8259" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5692dd7b5a1978a5aeb0ce83b7655c58ca8efdcb79d21036ea249da95afec2c6" [[package]] name = "escargot" -version = "0.5.10" +version = "0.5.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f474c6844cbd04e783d0f25757583db4f491770ca618bedf2fb01815fc79939" +checksum = "c000f23e9d459aef148b7267e02b03b94a0aaacf4ec64c65612f67e02f525fb6" dependencies = [ "log", "once_cell", @@ -1754,7 +2461,7 @@ dependencies = [ "sha2 0.10.8", "sha3", "thiserror", - "uuid", + "uuid 0.8.2", ] [[package]] @@ -1792,16 +2499,17 @@ checksum = "b90ca2580b73ab6a1f724b76ca11ab632df820fd6040c336200d2c1df7b3c82c" [[package]] name = "eventsource-client" -version = "0.10.2" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9146112ee3ce031aa5aebe3e049e10b1d353b9c7630cc6be488c2c62cc5d9c42" +checksum = "43ddc25e1ad2cc0106d5e2d967397b4fb2068a66677ee9b0eea4600e5cfe8fb4" dependencies = [ "futures", - "hyper", - "hyper-rustls 0.22.1", + "hyper 0.14.31", + "hyper-rustls 0.24.2", "hyper-timeout", "log", "pin-project", + "rand", "tokio", ] @@ -1823,7 +2531,7 @@ checksum = "dd65f1b59dd22d680c7a626cc4a000c1e03d241c51c3e034d2bc9f1e90734f9b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.65", + "syn 2.0.79", ] [[package]] @@ -1842,20 +2550,27 @@ dependencies = [ "regex", ] +[[package]] +name = "faster-hex" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2a2b11eda1d40935b26cf18f6833c526845ae8c41e58d09af6adeb6f0269183" + [[package]] name = "fastrand" -version = "2.1.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a" +checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6" [[package]] -name = "fd-lock" -version = "2.0.0" +name = "fastrlp" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0010f02effd88c702318c5dde0463206be67495d0b4d906ba7c0a8f166cc7f06" +checksum = "139834ddba373bbdd213dffe02c8d110508dcf1726c2be27e8d1f7d7e1856418" dependencies = [ - "libc", - "winapi", + "arrayvec", + "auto_impl", + "bytes", ] [[package]] @@ -1908,14 +2623,14 @@ dependencies = [ [[package]] name = "filetime" -version = "0.2.23" +version = "0.2.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ee447700ac8aa0b2f2bd7bc4462ad686ba06baa6727ac149a2d6277f0d240fd" +checksum = "35c0522e981e68cbfa8c3f978441a5f34b30b96e146b33cd3359176b50fe8586" dependencies = [ "cfg-if 1.0.0", "libc", - "redox_syscall 0.4.1", - "windows-sys 0.52.0", + "libredox 0.1.3", + "windows-sys 0.59.0", ] [[package]] @@ -1938,9 +2653,9 @@ checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" [[package]] name = "flate2" -version = "1.0.30" +version = "1.0.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f54427cfd1c7829e2a139fcefea601bf088ebca651d2bf53ebc600eac295dae" +checksum = "a1b589b4dc103969ad3cf85c950899926ec64300a1a46d76c03a6072957036f0" dependencies = [ "crc32fast", "miniz_oxide", @@ -1952,24 +2667,31 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +[[package]] +name = "foldhash" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f81ec6369c545a7d40e4589b5597581fa1c441fe1cce96dd1de43159910a36a2" + [[package]] name = "forc" -version = "0.60.0" +version = "0.66.2" dependencies = [ "annotate-snippets", "ansi_term", "anyhow", - "clap 4.5.4", + "clap 4.5.20", "clap_complete", "clap_complete_fig", "completest-pty", "forc-pkg", "forc-test", - "forc-tracing 0.60.0", + "forc-tracing 0.66.2", "forc-util", "fs_extra", "fuel-asm", "hex", + "rexpect 0.5.0", "serde", "serde_json", "sway-core", @@ -1979,8 +2701,8 @@ dependencies = [ "sway-utils", "term-table", "tokio", - "toml 0.7.8", - "toml_edit 0.19.15", + "toml 0.8.19", + "toml_edit", "tracing", "url", "uwuify", @@ -1990,16 +2712,19 @@ dependencies = [ [[package]] name = "forc-client" -version = "0.60.0" +version = "0.66.2" dependencies = [ "anyhow", "async-trait", + "aws-config", + "aws-sdk-kms", "chrono", - "clap 4.5.4", + "clap 4.5.20", "devault", + "dialoguer", "forc", "forc-pkg", - "forc-tracing 0.60.0", + "forc-tracing 0.66.2", "forc-tx", "forc-util", "forc-wallet", @@ -2009,63 +2734,77 @@ dependencies = [ "fuel-crypto", "fuel-tx", "fuel-vm", + "fuels", "fuels-accounts", "fuels-core", "futures", "hex", + "k256", + "portpicker", + "pretty_assertions", "rand", + "regex", + "rexpect 0.5.0", "rpassword", "serde", "serde_json", "sway-core", "sway-types", "sway-utils", + "tempfile", "tokio", + "toml_edit", "tracing", ] [[package]] name = "forc-crypto" -version = "0.60.0" +version = "0.66.2" dependencies = [ "anyhow", "async-trait", "atty", - "clap 4.5.4", - "forc-tracing 0.60.0", + "clap 4.5.20", + "criterion", + "forc-tracing 0.66.2", "forc-util", "fuel-core-types", "fuel-crypto", + "fuels-accounts", "fuels-core", "futures", "hex", "libp2p-identity", "rand", + "rayon", + "regex", "serde", "serde_json", "serde_yaml", "sha3", - "termion", + "tempfile", + "termion 4.0.3", "tokio", "tracing", ] [[package]] name = "forc-debug" -version = "0.60.0" +version = "0.66.2" dependencies = [ "anyhow", - "clap 4.5.4", + "clap 4.5.20", "dap", "escargot", "forc-pkg", "forc-test", + "forc-tracing 0.66.2", "fuel-core-client", "fuel-types", "fuel-vm", "portpicker", "rayon", - "rexpect", + "rexpect 0.4.0", "serde", "serde_json", "shellfish", @@ -2077,20 +2816,20 @@ dependencies = [ [[package]] name = "forc-doc" -version = "0.60.0" +version = "0.66.2" dependencies = [ "anyhow", - "clap 4.5.4", - "colored", + "clap 4.5.20", "comrak", "dir_indexer", "expect-test", "forc-pkg", + "forc-tracing 0.66.2", "forc-util", "horrorshow", "include_dir", "minifier", - "opener 0.5.2", + "opener", "serde", "serde_json", "sway-ast", @@ -2102,14 +2841,14 @@ dependencies = [ [[package]] name = "forc-fmt" -version = "0.60.0" +version = "0.66.2" dependencies = [ "anyhow", - "clap 4.5.4", + "clap 4.5.20", "forc-pkg", - "forc-tracing 0.60.0", + "forc-tracing 0.66.2", "forc-util", - "prettydiff 0.5.1", + "prettydiff 0.7.0", "sway-core", "sway-utils", "swayfmt", @@ -2119,10 +2858,10 @@ dependencies = [ [[package]] name = "forc-lsp" -version = "0.60.0" +version = "0.66.2" dependencies = [ "anyhow", - "clap 4.5.4", + "clap 4.5.20", "sway-lsp", "tikv-jemallocator", "tokio", @@ -2130,12 +2869,13 @@ dependencies = [ [[package]] name = "forc-pkg" -version = "0.60.0" +version = "0.66.2" dependencies = [ "ansi_term", "anyhow", + "byte-unit", "cid", - "forc-tracing 0.60.0", + "forc-tracing 0.66.2", "forc-util", "fuel-abi-types", "futures", @@ -2145,8 +2885,8 @@ dependencies = [ "ipfs-api-backend-hyper", "petgraph", "regex", - "reqwest", - "semver", + "reqwest 0.12.8", + "semver 1.0.23", "serde", "serde_ignored", "serde_json", @@ -2157,7 +2897,7 @@ dependencies = [ "sway-utils", "sysinfo", "tar", - "toml 0.7.8", + "toml 0.8.19", "tracing", "url", "vec1", @@ -2166,7 +2906,7 @@ dependencies = [ [[package]] name = "forc-test" -version = "0.60.0" +version = "0.66.2" dependencies = [ "anyhow", "forc-pkg", @@ -2193,19 +2933,20 @@ dependencies = [ [[package]] name = "forc-tracing" -version = "0.60.0" +version = "0.66.2" dependencies = [ "ansi_term", "tracing", "tracing-subscriber", + "tracing-test", ] [[package]] name = "forc-tx" -version = "0.60.0" +version = "0.66.2" dependencies = [ "anyhow", - "clap 4.5.4", + "clap 4.5.20", "devault", "forc-util", "fuel-tx", @@ -2217,15 +2958,15 @@ dependencies = [ [[package]] name = "forc-util" -version = "0.60.0" +version = "0.66.2" dependencies = [ "annotate-snippets", "ansi_term", "anyhow", - "clap 4.5.4", - "dirs 3.0.2", - "fd-lock 4.0.2", - "forc-tracing 0.60.0", + "clap 4.5.20", + "dirs 5.0.1", + "fd-lock", + "forc-tracing 0.66.2", "fuel-tx", "hex", "paste", @@ -2244,12 +2985,12 @@ dependencies = [ [[package]] name = "forc-wallet" -version = "0.8.0" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "223adda9aca17455167e0bea681b31a7a5819c83b73978876424eafc4ee48611" +checksum = "4e6ad4498ecab72fa7c5e134ade0137279d1b8f4a6df50963bb3803fdeb69dac" dependencies = [ "anyhow", - "clap 4.5.4", + "clap 4.5.20", "eth-keystore", "forc-tracing 0.47.0", "fuel-crypto", @@ -2262,7 +3003,7 @@ dependencies = [ "rand", "rpassword", "serde_json", - "termion", + "termion 2.0.3", "tiny-bip39", "tokio", "url", @@ -2309,9 +3050,9 @@ dependencies = [ [[package]] name = "fuel-abi-types" -version = "0.5.2" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0e7e87f94417ff1a5d60e496906033c58bfe5367546621f131fe8cdabaa2671" +checksum = "bce44ac13b1971be7cea024a2003cf944522093dafec454fea9ff792f0ff2577" dependencies = [ "itertools 0.10.5", "lazy_static", @@ -2320,17 +3061,17 @@ dependencies = [ "regex", "serde", "serde_json", - "syn 2.0.65", + "syn 2.0.79", "thiserror", ] [[package]] name = "fuel-asm" -version = "0.50.0" +version = "0.58.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db81c0bdf07b052d1c595b5ee71e20f0286ca3dc88c7ab3f775e08c8e055c34f" +checksum = "5f325971bf9047ec70004f80a989e03456316bc19cbef3ff3a39a38b192ab56e" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "fuel-types", "serde", "strum 0.24.1", @@ -2338,9 +3079,9 @@ dependencies = [ [[package]] name = "fuel-core-chain-config" -version = "0.27.0" +version = "0.40.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16323762c4a5d58b11121580bee9f3a76ac7f655f95d727f957b05a9e35f477f" +checksum = "990db3029efd3766c4ae7c92a53c159ae66abf6f568ac6a3d58354f11400e6e2" dependencies = [ "anyhow", "bech32", @@ -2358,20 +3099,21 @@ dependencies = [ [[package]] name = "fuel-core-client" -version = "0.27.0" +version = "0.40.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f33af785942254f23e30a03a08a08ffb8eea645a87f06895e5d84f4205fc191a" +checksum = "f09b3a35e82226d77b10653829beb508dc4bcf698fbdaa96610faf894e794444" dependencies = [ "anyhow", + "base64 0.22.1", "cynic", - "derive_more", + "derive_more 0.99.18", "eventsource-client", "fuel-core-types", "futures", "hex", "hyper-rustls 0.24.2", "itertools 0.12.1", - "reqwest", + "reqwest 0.11.27", "schemafy_lib", "serde", "serde_json", @@ -2382,23 +3124,25 @@ dependencies = [ [[package]] name = "fuel-core-metrics" -version = "0.27.0" +version = "0.40.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a47f442a32f2e5917066bbf9be3d6fd5d85252a131f1b5fc2f2f0ee75008066" +checksum = "94a1c3eb92040d95d27f7c658801bb5c04ad4aaf67de380cececbeed5aab6e61" dependencies = [ - "axum", "once_cell", + "parking_lot 0.12.3", "pin-project-lite", "prometheus-client", "regex", + "strum 0.25.0", + "strum_macros 0.25.3", "tracing", ] [[package]] name = "fuel-core-poa" -version = "0.27.0" +version = "0.40.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f6185f492f9ddb65228db0f250b3f6384637ebf76b72fc81b2efb629d887912" +checksum = "2f6f78fa31dc56b9458e3ca9a7058b4bea381e16e49fcab0db49923be8a30f9c" dependencies = [ "anyhow", "async-trait", @@ -2406,6 +3150,8 @@ dependencies = [ "fuel-core-services", "fuel-core-storage", "fuel-core-types", + "serde", + "serde_json", "tokio", "tokio-stream", "tracing", @@ -2413,33 +3159,34 @@ dependencies = [ [[package]] name = "fuel-core-services" -version = "0.27.0" +version = "0.40.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d35200489fdcdafbe5a6a3a39baad4da523e5c004db9a885056be0137ee35098" +checksum = "8312b598da4b9a6503c9263c1c2a7ea58d34ab1f86e7f345490e12d309fb29bb" dependencies = [ "anyhow", "async-trait", "fuel-core-metrics", "futures", - "parking_lot 0.12.2", + "parking_lot 0.12.3", + "pin-project-lite", "tokio", "tracing", ] [[package]] name = "fuel-core-storage" -version = "0.27.0" +version = "0.40.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87f4e85b634f42fb53193da517b4a2efa8ac73031cdab653029a5b1d3725572d" +checksum = "bda9242ebc9e8ef3251b9eae85f4ce5cdb376348baa30925606f3ce602db7ec5" dependencies = [ "anyhow", - "derive_more", + "derive_more 0.99.18", "enum-iterator", "fuel-core-types", "fuel-vm", "impl-tools", "itertools 0.12.1", - "num_enum 0.7.2", + "num_enum", "paste", "postcard", "primitive-types", @@ -2450,28 +3197,27 @@ dependencies = [ [[package]] name = "fuel-core-types" -version = "0.27.0" +version = "0.40.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffe21004dd036f4c454666e339bd0fc3b037535bbc5510321db2565087edd4fc" +checksum = "6ee3a95b189bf729d21354a761862bb481298cbd883550adc3fef1bc7beb0b67" dependencies = [ "anyhow", "bs58", "derivative", - "derive_more", + "derive_more 0.99.18", "fuel-vm", "rand", "secrecy", "serde", "tai64", - "thiserror", "zeroize", ] [[package]] name = "fuel-crypto" -version = "0.50.0" +version = "0.58.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ca73b3409086e772315625304cabd2eeec10e4bd1f8b8a99cc72e0aed755e5c" +checksum = "65e318850ca64890ff123a99b6b866954ef49da94ab9bc6827cf6ee045568585" dependencies = [ "coins-bip32", "coins-bip39", @@ -2482,7 +3228,7 @@ dependencies = [ "lazy_static", "p256", "rand", - "secp256k1 0.26.0", + "secp256k1", "serde", "sha2 0.10.8", "zeroize", @@ -2490,13 +3236,13 @@ dependencies = [ [[package]] name = "fuel-derive" -version = "0.50.0" +version = "0.58.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8d6e66d1b68eb916640c12a1c6c40880e11fcf569359b04483d5e18237c5229" +checksum = "ab0bc46a3552964bae5169e79b383761a54bd115ea66951a1a7a229edcefa55a" dependencies = [ "proc-macro2", "quote", - "syn 2.0.65", + "syn 2.0.79", "synstructure 0.13.1", ] @@ -2549,11 +3295,11 @@ dependencies = [ [[package]] name = "fuel-merkle" -version = "0.50.0" +version = "0.58.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "faa4b60ddfa51b64d02a1d71b0cf51488171d313b32ae3fb9f39f64ddd21791b" +checksum = "c79eca6a452311c70978a5df796c0f99f27e474b69719e0db4c1d82e68800d07" dependencies = [ - "derive_more", + "derive_more 0.99.18", "digest 0.10.7", "fuel-storage", "hashbrown 0.13.2", @@ -2564,19 +3310,19 @@ dependencies = [ [[package]] name = "fuel-storage" -version = "0.50.0" +version = "0.58.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "beef5f12c40118e87ef6abf611c6bba5c88754e727fb825120ae7d0872123055" +checksum = "2d0c46b5d76b3e11197bd31e036cd8b1cb46c4d822cacc48836638080c6d2b76" [[package]] name = "fuel-tx" -version = "0.50.0" +version = "0.58.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc95857e761db34a50967f53af7a74be08130d210bd985c5585f36bd753d346c" +checksum = "6723bb8710ba2b70516ac94d34459593225870c937670fb3afaf82e0354667ac" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "derivative", - "derive_more", + "derive_more 0.99.18", "fuel-asm", "fuel-crypto", "fuel-merkle", @@ -2586,16 +3332,15 @@ dependencies = [ "postcard", "rand", "serde", - "serde_json", "strum 0.24.1", "strum_macros 0.24.3", ] [[package]] name = "fuel-types" -version = "0.50.0" +version = "0.58.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0af9f9d8c9eb3f4e644731c829ee7da5c3cae0886864731089627af25e336cea" +checksum = "982265415a99b5bd6277bc24194a233bb2e18764df11c937b3dbb11a02c9e545" dependencies = [ "fuel-derive", "hex", @@ -2605,16 +3350,16 @@ dependencies = [ [[package]] name = "fuel-vm" -version = "0.50.0" +version = "0.58.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71df1a9ede5237febbc7864888f26365814327732ccd11002e9bddac1ce9a4e6" +checksum = "54b5362d7d072c72eec20581f67fc5400090c356a7f3ae77c79880b3b177b667" dependencies = [ "anyhow", "async-trait", "backtrace", - "bitflags 2.5.0", + "bitflags 2.6.0", "derivative", - "derive_more", + "derive_more 0.99.18", "ethnum", "fuel-asm", "fuel-crypto", @@ -2639,9 +3384,9 @@ dependencies = [ [[package]] name = "fuels" -version = "0.63.0" +version = "0.66.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e318b107e6fef3d786f2366cc78a6314a6b326342d375203238f130a7356fe49" +checksum = "6ed08053e72bdb285d5a167c27a7a0d10f1dc4e27d1e6e5296dd2a67813bd13f" dependencies = [ "fuel-core-client", "fuel-crypto", @@ -2655,12 +3400,13 @@ dependencies = [ [[package]] name = "fuels-accounts" -version = "0.63.0" +version = "0.66.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e17d23b925d3d5e21dc5428330695c596db356d4adfc90eadecc2a490d7d5ce" +checksum = "49fee90e8f3a4fc9392a6cde3010c561fa50da0f805d66fdb659eaa4d5d8a504" dependencies = [ "async-trait", "chrono", + "cynic", "elliptic-curve", "eth-keystore", "fuel-core-client", @@ -2669,8 +3415,9 @@ dependencies = [ "fuel-tx", "fuel-types", "fuels-core", + "itertools 0.12.1", "rand", - "semver", + "semver 1.0.23", "tai64", "thiserror", "tokio", @@ -2679,9 +3426,9 @@ dependencies = [ [[package]] name = "fuels-code-gen" -version = "0.63.0" +version = "0.66.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86a7a5b4811f5563bb5c2485efc7653ed6ce465c452a1182ae9062aa13dd19af" +checksum = "f857b7ff658400506ca6be57bb84fedda44b566e78f5f0a8d0782242f41615c0" dependencies = [ "Inflector", "fuel-abi-types", @@ -2690,14 +3437,14 @@ dependencies = [ "quote", "regex", "serde_json", - "syn 2.0.65", + "syn 2.0.79", ] [[package]] name = "fuels-core" -version = "0.63.0" +version = "0.66.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9774ae9b35f808fa18b92d0478a3b0acbea41011409efa3117f972dfe528ae09" +checksum = "baccbdd81e624f57950dcb136b32b853c520dd954badf26b9f58de33f3d71c7e" dependencies = [ "async-trait", "bech32", @@ -2717,28 +3464,29 @@ dependencies = [ "postcard", "serde", "serde_json", + "sha2 0.10.8", "thiserror", "uint", ] [[package]] name = "fuels-macros" -version = "0.63.0" +version = "0.66.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba92a701fa86eed843db68d991807207b8b3d47099d49fb82467e8900f680e01" +checksum = "5da75294c5e9da312bdc49239736699ee84ea9c5bfbc19a61a8ee588a1247aa1" dependencies = [ "fuels-code-gen", "itertools 0.12.1", "proc-macro2", "quote", - "syn 2.0.65", + "syn 2.0.79", ] [[package]] name = "fuels-programs" -version = "0.63.0" +version = "0.66.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6c72ac2f1cdda800dbc1c3714459f83bf208cef78812448992b6dbdda6841dc" +checksum = "32675ed1c08edd28ddb648dfae0c60a1946d4368a69ddfa6434f2316e33f0520" dependencies = [ "async-trait", "fuel-abi-types", @@ -2755,9 +3503,9 @@ dependencies = [ [[package]] name = "fuels-test-helpers" -version = "0.63.0" +version = "0.66.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30b8a632f2b4ddb52e8ad92871f63521e9f5cc299f842a3207f3655acc21c148" +checksum = "02176c0fb1bf8cf58b8a9e5372efb650324740abcd4847b45bd0b041a0f133a2" dependencies = [ "fuel-core-chain-config", "fuel-core-client", @@ -2785,9 +3533,9 @@ checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" [[package]] name = "futures" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" +checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" dependencies = [ "futures-channel", "futures-core", @@ -2800,9 +3548,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" +checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" dependencies = [ "futures-core", "futures-sink", @@ -2810,15 +3558,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" [[package]] name = "futures-executor" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" +checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" dependencies = [ "futures-core", "futures-task", @@ -2827,38 +3575,38 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" +checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" [[package]] name = "futures-macro" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" +checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.65", + "syn 2.0.79", ] [[package]] name = "futures-sink" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" +checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" [[package]] name = "futures-task" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" [[package]] name = "futures-util" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" dependencies = [ "futures-channel", "futures-core", @@ -2893,17 +3641,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "getrandom" -version = "0.1.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" -dependencies = [ - "cfg-if 1.0.0", - "libc", - "wasi 0.9.0+wasi-snapshot-preview1", -] - [[package]] name = "getrandom" version = "0.2.15" @@ -2912,27 +3649,27 @@ checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ "cfg-if 1.0.0", "libc", - "wasi 0.11.0+wasi-snapshot-preview1", + "wasi", ] [[package]] name = "gimli" -version = "0.28.1" +version = "0.31.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" +checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" dependencies = [ "fallible-iterator", - "indexmap 2.2.6", + "indexmap 2.6.0", "stable_deref_trait", ] [[package]] name = "git2" -version = "0.17.2" +version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b989d6a7ca95a362cf2cfc5ad688b3a467be1f87e480b8dad07fee8c79b0044" +checksum = "b903b73e45dc0c6c596f2d37eccece7c1c8bb6e4407b001096387c63d0d93724" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.6.0", "libc", "libgit2-sys", "log", @@ -2943,39 +3680,49 @@ dependencies = [ [[package]] name = "gix-features" -version = "0.28.1" +version = "0.38.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b76f9a80f6dd7be66442ae86e1f534effad9546676a392acc95e269d0c21c22" +checksum = "ac7045ac9fe5f9c727f38799d002a7ed3583cd777e3322a7c4b43e3cf437dc69" dependencies = [ "gix-hash", + "gix-trace", "libc", ] [[package]] name = "gix-hash" -version = "0.10.4" +version = "0.14.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a258595457bc192d1f1c59d0d168a1e34e2be9b97a614e14995416185de41a7" +checksum = "f93d7df7366121b5018f947a04d37f034717e113dcf9ccd85c34b58e57a74d5e" dependencies = [ - "hex", + "faster-hex", "thiserror", ] [[package]] name = "gix-path" -version = "0.7.3" +version = "0.10.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32370dce200bb951df013e03dff35b4233fc7a89458642b047629b91734a7e19" +checksum = "ebfc4febd088abdcbc9f1246896e57e37b7a34f6909840045a1767c6dafac7af" dependencies = [ "bstr", + "gix-trace", + "home", + "once_cell", "thiserror", ] +[[package]] +name = "gix-trace" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6cae0e8661c3ff92688ce1c8b8058b3efb312aba9492bbe93661a21705ab431b" + [[package]] name = "gix-url" -version = "0.16.0" +version = "0.27.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6a22b4b32ad14d68f7b7fb6458fa58d44b01797d94c1b8f4db2d9c7b3c366b5" +checksum = "fd280c5e84fb22e128ed2a053a0daeacb6379469be6a85e3d518a0636e160c89" dependencies = [ "bstr", "gix-features", @@ -2992,13 +3739,26 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" +[[package]] +name = "globset" +version = "0.4.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15f1ce686646e7f1e19bf7d5533fe443a45dbfb990e00629110797578b42fb19" +dependencies = [ + "aho-corasick", + "bstr", + "log", + "regex-automata 0.4.8", + "regex-syntax 0.8.5", +] + [[package]] name = "graph-cycles" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3a6ad932c6dd3cfaf16b66754a42f87bbeefd591530c4b6a8334270a7df3e853" dependencies = [ - "ahash", + "ahash 0.8.11", "petgraph", "thiserror", ] @@ -3035,8 +3795,27 @@ dependencies = [ "futures-core", "futures-sink", "futures-util", - "http", - "indexmap 2.2.6", + "http 0.2.12", + "indexmap 2.6.0", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "h2" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "524e8ac6999421f49a846c2d4411f337e53497d8ec55d67753beffa43c5d9205" +dependencies = [ + "atomic-waker", + "bytes", + "fnv", + "futures-core", + "futures-sink", + "http 1.1.0", + "indexmap 2.6.0", "slab", "tokio", "tokio-util", @@ -3076,17 +3855,14 @@ dependencies = [ "byteorder", ] -[[package]] -name = "hashbrown" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" - [[package]] name = "hashbrown" version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +dependencies = [ + "ahash 0.7.8", +] [[package]] name = "hashbrown" @@ -3094,7 +3870,7 @@ version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" dependencies = [ - "ahash", + "ahash 0.8.11", ] [[package]] @@ -3103,11 +3879,20 @@ version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" dependencies = [ - "ahash", + "ahash 0.8.11", "allocator-api2", "serde", ] +[[package]] +name = "hashbrown" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" +dependencies = [ + "foldhash", +] + [[package]] name = "heapless" version = "0.7.17" @@ -3116,9 +3901,9 @@ checksum = "cdc6457c0eb62c71aac4bc17216026d8410337c4126773b9c5daba343f17964f" dependencies = [ "atomic-polyfill", "hash32", - "rustc_version", + "rustc_version 0.4.1", "serde", - "spin 0.9.8", + "spin", "stable_deref_trait", ] @@ -3158,11 +3943,26 @@ version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" +[[package]] +name = "hermit-abi" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc" + [[package]] name = "hex" version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +dependencies = [ + "serde", +] + +[[package]] +name = "hex-literal" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fe2267d4ed49bc07b63801559be28c718ea06c4738b7a03c94df7386d2cde46" [[package]] name = "hkdf" @@ -3229,6 +4029,17 @@ dependencies = [ "itoa", ] +[[package]] +name = "http" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + [[package]] name = "http-body" version = "0.4.6" @@ -3236,21 +4047,38 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" dependencies = [ "bytes", - "http", + "http 0.2.12", "pin-project-lite", ] [[package]] -name = "http-range-header" -version = "0.3.1" +name = "http-body" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" +dependencies = [ + "bytes", + "http 1.1.0", +] + +[[package]] +name = "http-body-util" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "add0ab9360ddbd88cfeb3bd9574a1d85cfdfa14db10b3e21d3700dbc4328758f" +checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" +dependencies = [ + "bytes", + "futures-util", + "http 1.1.0", + "http-body 1.0.1", + "pin-project-lite", +] [[package]] name = "httparse" -version = "1.8.0" +version = "1.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" +checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" [[package]] name = "httpdate" @@ -3266,17 +4094,17 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "hyper" -version = "0.14.28" +version = "0.14.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf96e135eb83a2a8ddf766e426a841d8ddd7449d5f00d34ea02b41d2f19eef80" +checksum = "8c08302e8fa335b151b788c775ff56e7a03ae64ff85c548ee820fecb70356e85" dependencies = [ "bytes", "futures-channel", "futures-core", "futures-util", - "h2", - "http", - "http-body", + "h2 0.3.26", + "http 0.2.12", + "http-body 0.4.6", "httparse", "httpdate", "itoa", @@ -3288,6 +4116,26 @@ dependencies = [ "want", ] +[[package]] +name = "hyper" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbbff0a806a4728c99295b254c8838933b5b082d75e3cb70c8dab21fdfbcfa9a" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "h2 0.4.6", + "http 1.1.0", + "http-body 1.0.1", + "httparse", + "itoa", + "pin-project-lite", + "smallvec", + "tokio", + "want", +] + [[package]] name = "hyper-multipart-rfc7578" version = "0.8.0" @@ -3297,42 +4145,42 @@ dependencies = [ "bytes", "common-multipart-rfc7578", "futures-core", - "http", - "hyper", + "http 0.2.12", + "hyper 0.14.31", ] [[package]] name = "hyper-rustls" -version = "0.22.1" +version = "0.24.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f9f7a97316d44c0af9b0301e65010573a853a9fc97046d7331d7f6bc0fd5a64" +checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" dependencies = [ - "ct-logs", "futures-util", - "hyper", + "http 0.2.12", + "hyper 0.14.31", "log", - "rustls 0.19.1", - "rustls-native-certs 0.5.0", + "rustls 0.21.12", + "rustls-native-certs", "tokio", - "tokio-rustls 0.22.0", - "webpki", + "tokio-rustls 0.24.1", + "webpki-roots", ] [[package]] name = "hyper-rustls" -version = "0.24.2" +version = "0.27.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" +checksum = "08afdbb5c31130e3034af566421053ab03787c640246a446327f550d11bcb333" dependencies = [ "futures-util", - "http", - "hyper", - "log", - "rustls 0.21.12", - "rustls-native-certs 0.6.3", + "http 1.1.0", + "hyper 1.5.0", + "hyper-util", + "rustls 0.23.15", + "rustls-pki-types", "tokio", - "tokio-rustls 0.24.1", - "webpki-roots", + "tokio-rustls 0.26.0", + "tower-service", ] [[package]] @@ -3341,7 +4189,7 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbb958482e8c7be4bc3cf272a766a2b0bf1a6755e7a6ae777f017a31d11b13b1" dependencies = [ - "hyper", + "hyper 0.14.31", "pin-project-lite", "tokio", "tokio-io-timeout", @@ -3349,22 +4197,44 @@ dependencies = [ [[package]] name = "hyper-tls" -version = "0.5.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" +checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" dependencies = [ "bytes", - "hyper", + "http-body-util", + "hyper 1.5.0", + "hyper-util", "native-tls", "tokio", "tokio-native-tls", + "tower-service", +] + +[[package]] +name = "hyper-util" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41296eb09f183ac68eec06e03cdbea2e759633d4067b2f6552fc2e009bcad08b" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "http 1.1.0", + "http-body 1.0.1", + "hyper 1.5.0", + "pin-project-lite", + "socket2", + "tokio", + "tower-service", + "tracing", ] [[package]] name = "iana-time-zone" -version = "0.1.60" +version = "0.1.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" +checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220" dependencies = [ "android_system_properties", "core-foundation-sys", @@ -3459,7 +4329,7 @@ dependencies = [ "autocfg", "impl-tools-lib", "proc-macro-error", - "syn 2.0.65", + "syn 2.0.79", ] [[package]] @@ -3471,7 +4341,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.65", + "syn 2.0.79", ] [[package]] @@ -3493,18 +4363,18 @@ checksum = "b5bd47a3c8188d842aa7ff4dd65a9732f740fcbe04689ecfbfef43c465b381de" [[package]] name = "include_dir" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18762faeff7122e89e0857b02f7ce6fcc0d101d5e9ad2ad7846cc01d61b7f19e" +checksum = "923d117408f1e49d914f1a379a309cffe4f18c05cf4e3d12e613a15fc81bd0dd" dependencies = [ "include_dir_macros", ] [[package]] name = "include_dir_macros" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b139284b5cf57ecfa712bcc66950bb635b31aff41c188e8a4cfc758eca374a3f" +checksum = "7cab85a7ed0bd5f0e76d93846e0147172bed2e2d3f859bcc33a8d9699cad1a75" dependencies = [ "proc-macro2", "quote", @@ -3523,16 +4393,22 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.2.6" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" +checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" dependencies = [ "equivalent", - "hashbrown 0.14.5", + "hashbrown 0.15.0", "rayon", "serde", ] +[[package]] +name = "indoc" +version = "2.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b248f5224d1d606005e02c97f5aa4e88eeb230488bcc03bc9ca4d7991399f2b5" + [[package]] name = "inotify" version = "0.9.6" @@ -3564,9 +4440,9 @@ dependencies = [ [[package]] name = "insta" -version = "1.39.0" +version = "1.40.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "810ae6042d48e2c9e9215043563a58a80b877bc863228a74cf10c49d4620a6f5" +checksum = "6593a41c7a73841868772495db7dc1e8ecab43bb5c0b6da2059246c4b506ab60" dependencies = [ "console", "lazy_static", @@ -3595,8 +4471,8 @@ dependencies = [ "base64 0.13.1", "bytes", "futures", - "http", - "hyper", + "http 0.2.12", + "hyper 0.14.31", "hyper-multipart-rfc7578", "ipfs-api-prelude", "thiserror", @@ -3614,7 +4490,7 @@ dependencies = [ "common-multipart-rfc7578", "dirs 4.0.0", "futures", - "http", + "http 0.2.12", "multiaddr", "multibase", "serde", @@ -3630,26 +4506,26 @@ dependencies = [ [[package]] name = "ipnet" -version = "2.9.0" +version = "2.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" +checksum = "ddc24109865250148c2e0f3d25d4f0f479571723792d3802153c60922a4fb708" [[package]] name = "is-terminal" -version = "0.4.12" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f23ff5ef2b80d608d61efee834934d862cd92461afc0560dedf493e4c033738b" +checksum = "261f68e344040fbd0edea105bef17c66edf46f984ddb1115b775ce31be948f4b" dependencies = [ - "hermit-abi 0.3.9", + "hermit-abi 0.4.0", "libc", "windows-sys 0.52.0", ] [[package]] name = "is_terminal_polyfill" -version = "1.70.0" +version = "1.70.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800" +checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" [[package]] name = "itertools" @@ -3678,6 +4554,15 @@ dependencies = [ "either", ] +[[package]] +name = "itertools" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" +dependencies = [ + "either", +] + [[package]] name = "itoa" version = "1.0.11" @@ -3686,27 +4571,27 @@ checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] name = "jobserver" -version = "0.1.31" +version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2b099aaa34a9751c5bf0878add70444e1ed2dd73f347be99003d4577277de6e" +checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0" dependencies = [ "libc", ] [[package]] name = "js-sys" -version = "0.3.69" +version = "0.3.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" +checksum = "6a88f1bda2bd75b0452a14784937d796722fdebfe50df998aeb3f0b7603019a9" dependencies = [ "wasm-bindgen", ] [[package]] name = "k256" -version = "0.13.3" +version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "956ff9b67e26e1a6a866cb758f12c6f8746208489e3e4a4b5580802f2f0a587b" +checksum = "f6e3919bbaa2945715f0bb6d3934a173d1e9a59ac23767fbaaef277265a7411b" dependencies = [ "cfg-if 1.0.0", "ecdsa", @@ -3725,6 +4610,16 @@ dependencies = [ "cpufeatures", ] +[[package]] +name = "keccak-asm" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "505d1856a39b200489082f90d897c3f07c455563880bc5952e38eabf731c83b6" +dependencies = [ + "digest 0.10.7", + "sha3-asm", +] + [[package]] name = "kqueue" version = "1.0.8" @@ -3747,18 +4642,18 @@ dependencies = [ [[package]] name = "lazy_static" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" dependencies = [ - "spin 0.5.2", + "spin", ] [[package]] name = "libc" -version = "0.2.155" +version = "0.2.161" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" +checksum = "8e9489c2807c139ffd9c1794f4af0ebe86a828db53ecdc7fea2111d0fed085d1" [[package]] name = "libdbus-sys" @@ -3772,9 +4667,9 @@ dependencies = [ [[package]] name = "libgit2-sys" -version = "0.15.2+1.6.4" +version = "0.17.0+1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a80df2e11fb4a61f4ba2ab42dbe7f74468da143f1a75c74e11dee7c813f694fa" +checksum = "10472326a8a6477c3c20a64547b0059e4b0d086869eee31e6d7da728a8eb7224" dependencies = [ "cc", "libc", @@ -3792,9 +4687,9 @@ checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" [[package]] name = "libp2p-identity" -version = "0.2.8" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "999ec70441b2fb35355076726a6bc466c932e9bdc66f6a11c6c0aa17c7ab9be0" +checksum = "55cca1eb2bc1fd29f099f3daaab7effd01e1a54b7c577d0ed082521034d912e8" dependencies = [ "asn1_der", "bs58", @@ -3814,7 +4709,7 @@ version = "0.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3af92c55d7d839293953fcd0fda5ecfe93297cfde6ffbdec13b41d99c0ba6607" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "libc", "redox_syscall 0.4.1", ] @@ -3825,8 +4720,9 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "libc", + "redox_syscall 0.5.7", ] [[package]] @@ -3891,11 +4787,23 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "libtest-mimic" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc0bda45ed5b3a2904262c1bb91e526127aa70e7ef3758aba2ef93cf896b9b58" +dependencies = [ + "clap 4.5.20", + "escape8259", + "termcolor", + "threadpool", +] + [[package]] name = "libz-sys" -version = "1.1.16" +version = "1.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e143b5e666b2695d28f6bca6497720813f699c9602dd7f5cac91008b8ada7f9" +checksum = "d2d16453e800a8cf6dd2fc3eb4bc99b786a9b90c663b8559a5b1a041bf89e472" dependencies = [ "cc", "libc", @@ -3903,12 +4811,6 @@ dependencies = [ "vcpkg", ] -[[package]] -name = "line-wrap" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd1bc4d24ad230d21fb898d1116b1801d7adfc449d42026475862ab48b11e70e" - [[package]] name = "linked-hash-map" version = "0.5.6" @@ -3933,9 +4835,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.21" +version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" [[package]] name = "logos" @@ -3982,12 +4884,6 @@ dependencies = [ "regex-automata 0.1.10", ] -[[package]] -name = "matchit" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73cbba799671b762df5a175adf59ce145165747bb891505c43d09aefbbf38beb" - [[package]] name = "mdbook" version = "0.4.40" @@ -3996,14 +4892,14 @@ checksum = "b45a38e19bd200220ef07c892b0157ad3d2365e5b5a267ca01ad12182491eea5" dependencies = [ "anyhow", "chrono", - "clap 4.5.4", + "clap 4.5.20", "clap_complete", "env_logger", "handlebars", "log", "memchr", "once_cell", - "opener 0.7.1", + "opener", "pulldown-cmark", "regex", "serde", @@ -4019,18 +4915,18 @@ name = "mdbook-forc-documenter" version = "0.0.0" dependencies = [ "anyhow", - "clap 4.5.4", + "clap 4.5.20", "mdbook", - "semver", + "semver 1.0.23", "serde", "serde_json", ] [[package]] name = "memchr" -version = "2.7.2" +version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "memoffset" @@ -4050,100 +4946,6 @@ dependencies = [ "autocfg", ] -[[package]] -name = "miden" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8d8a25e092075f58af207e2a42bad5fbbf40c5200f13d2432a806db751a52b5" -dependencies = [ - "log", - "miden-air", - "miden-assembly", - "miden-core", - "miden-processor", - "miden-prover", - "miden-stdlib", - "miden-verifier", -] - -[[package]] -name = "miden-air" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5046ab97d8c2b7136601e9430fd0a14e7d6c6cdd648c90c1e6b39186a38b9a8b" -dependencies = [ - "miden-core", - "winter-air", -] - -[[package]] -name = "miden-assembly" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a04eec160cbd5cf3051ad16a244c3d83e648eddbd3349120dc069f6e309259dc" -dependencies = [ - "miden-core", - "num_enum 0.5.11", - "winter-crypto", -] - -[[package]] -name = "miden-core" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e75a2446684f44e61afb27bbdbf2458e8ec58c5c55d9bd202981d7cd265f7cf4" -dependencies = [ - "winter-crypto", - "winter-math", - "winter-utils", -] - -[[package]] -name = "miden-processor" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb7a467447a7d6236f3971f91f8c47c8880a01a43c29b0b08285ec50454f02ed" -dependencies = [ - "log", - "miden-core", - "winter-prover", -] - -[[package]] -name = "miden-prover" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2343eaf338770b78fe421f36a3445bb491123e0787006dfa2b98788cd6440ec6" -dependencies = [ - "log", - "miden-air", - "miden-core", - "miden-processor", - "winter-prover", -] - -[[package]] -name = "miden-stdlib" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b2a52fd1a44b136dbce7a513ebe5a407dfebc17160af8a2707383df731fc098" -dependencies = [ - "miden-assembly", - "miden-core", -] - -[[package]] -name = "miden-verifier" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d942d5b0bdcad47359d52534ef6fbccebffc0c713d2c7ca65ab603c7965c0a8b" -dependencies = [ - "miden-air", - "miden-assembly", - "miden-core", - "winter-verifier", -] - [[package]] name = "mime" version = "0.3.17" @@ -4152,9 +4954,9 @@ checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" [[package]] name = "mime_guess" -version = "2.0.4" +version = "2.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4192263c238a5f0d0c6bfd21f336a313a4ce1c450542449ca191bb657b4642ef" +checksum = "f7c44f8e672c00fe5308fa235f821cb4198414e1c77935c1ab6948d3fd78550e" dependencies = [ "mime", "unicase", @@ -4162,17 +4964,20 @@ dependencies = [ [[package]] name = "minifier" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95bbbf96b9ac3482c2a25450b67a15ed851319bc5fabf3b40742ea9066e84282" +checksum = "9aa3f302fe0f8de065d4a2d1ed64f60204623cac58b80cd3c2a83a25d5a7d437" +dependencies = [ + "clap 4.5.20", +] [[package]] name = "miniz_oxide" -version = "0.7.3" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87dfd01fe195c66b572b37921ad8803d010623c0aca821bea2302239d155cdae" +checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" dependencies = [ - "adler", + "adler2", ] [[package]] @@ -4183,10 +4988,22 @@ checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" dependencies = [ "libc", "log", - "wasi 0.11.0+wasi-snapshot-preview1", + "wasi", "windows-sys 0.48.0", ] +[[package]] +name = "mio" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" +dependencies = [ + "hermit-abi 0.3.9", + "libc", + "wasi", + "windows-sys 0.52.0", +] + [[package]] name = "multiaddr" version = "0.17.1" @@ -4202,7 +5019,7 @@ dependencies = [ "percent-encoding", "serde", "static_assertions", - "unsigned-varint", + "unsigned-varint 0.7.2", "url", ] @@ -4225,24 +5042,7 @@ checksum = "835d6ff01d610179fbce3de1694d007e500bf33a7f29689838941d6bf783ae40" dependencies = [ "core2", "multihash-derive", - "unsigned-varint", -] - -[[package]] -name = "multihash" -version = "0.18.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfd8a792c1694c6da4f68db0a9d707c72bd260994da179e6030a5dcee00bb815" -dependencies = [ - "blake2b_simd 1.0.2", - "blake2s_simd", - "blake3", - "core2", - "digest 0.10.7", - "multihash-derive", - "sha2 0.10.8", - "sha3", - "unsigned-varint", + "unsigned-varint 0.7.2", ] [[package]] @@ -4252,7 +5052,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "076d548d76a0e2a0d4ab471d0b1c36c577786dfc4471242035d97a12a735c492" dependencies = [ "core2", - "unsigned-varint", + "unsigned-varint 0.7.2", ] [[package]] @@ -4271,11 +5071,10 @@ dependencies = [ [[package]] name = "native-tls" -version = "0.2.11" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e" +checksum = "a8614eb2c83d59d1c8cc974dd3f920198647674a0a035e1af1fa58707e317466" dependencies = [ - "lazy_static", "libc", "log", "openssl", @@ -4311,14 +5110,16 @@ dependencies = [ [[package]] name = "nix" -version = "0.20.0" +version = "0.25.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa9b4819da1bc61c0ea48b63b7bc8604064dd43013e7cc325df098d49cd7c18a" +checksum = "f346ff70e7dbfd675fe90590b92d59ef2de15a8779ae305ebcbfd3f0caf59be4" dependencies = [ + "autocfg", "bitflags 1.3.2", - "cc", "cfg-if 1.0.0", "libc", + "memoffset 0.6.5", + "pin-utils", ] [[package]] @@ -4334,40 +5135,59 @@ dependencies = [ "pin-utils", ] +[[package]] +name = "nix" +version = "0.27.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053" +dependencies = [ + "bitflags 2.6.0", + "cfg-if 1.0.0", + "libc", +] + +[[package]] +name = "normalize-path" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5438dd2b2ff4c6df6e1ce22d825ed2fa93ee2922235cc45186991717f0a892d" + [[package]] name = "normpath" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5831952a9476f2fed74b77d74182fa5ddc4d21c72ec45a333b250e3ed0272804" +checksum = "c8911957c4b1549ac0dc74e30db9c8b0e66ddcd6d7acc33098f4c63a64a6d7ed" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] name = "notify" -version = "5.2.0" +version = "6.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "729f63e1ca555a43fe3efa4f3efdf4801c479da85b432242a7b726f353c88486" +checksum = "6205bd8bb1e454ad2e27422015fb5e4f2bcc7e08fa8f27058670d208324a4d2d" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.6.0", "crossbeam-channel", "filetime", "fsevent-sys", "inotify", "kqueue", "libc", - "mio", + "log", + "mio 0.8.11", "walkdir", - "windows-sys 0.45.0", + "windows-sys 0.48.0", ] [[package]] name = "notify-debouncer-mini" -version = "0.2.1" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e23e9fa24f094b143c1eb61f90ac6457de87be6987bc70746e0179f7dbc9007b" +checksum = "5d40b221972a1fc5ef4d858a2f671fb34c75983eb385463dff3780eeff6a9d43" dependencies = [ "crossbeam-channel", + "log", "notify", ] @@ -4406,9 +5226,9 @@ dependencies = [ [[package]] name = "num-bigint" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c165a9ab64cf766f73521c0dd2cfdff64f488b8f0b3e621face3462d3db536d7" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" dependencies = [ "num-integer", "num-traits", @@ -4468,6 +5288,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", + "libm", ] [[package]] @@ -4482,71 +5303,56 @@ dependencies = [ [[package]] name = "num_enum" -version = "0.5.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f646caf906c20226733ed5b1374287eb97e3c2a5c227ce668c1f2ce20ae57c9" -dependencies = [ - "num_enum_derive 0.5.11", -] - -[[package]] -name = "num_enum" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02339744ee7253741199f897151b38e72257d13802d4ee837285cc2990a90845" +checksum = "4e613fc340b2220f734a8595782c551f1250e969d87d3be1ae0579e8d4065179" dependencies = [ - "num_enum_derive 0.7.2", + "num_enum_derive", ] [[package]] name = "num_enum_derive" -version = "0.5.11" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcbff9bc912032c62bf65ef1d5aea88983b420f4f839db1e9b0c281a25c9c799" +checksum = "af1844ef2428cc3e1cb900be36181049ef3d3193c63e43026cfe202983b27a56" dependencies = [ - "proc-macro-crate 1.1.3", + "proc-macro-crate 3.2.0", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.79", ] [[package]] -name = "num_enum_derive" -version = "0.7.2" +name = "numtoa" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "681030a937600a36906c185595136d26abfebb4aa9c65701cefcaf8578bb982b" -dependencies = [ - "proc-macro-crate 3.1.0", - "proc-macro2", - "quote", - "syn 2.0.65", -] +checksum = "b8f8bdf33df195859076e54ab11ee78a1b208382d3a26ec40d142ffc1ecc49ef" [[package]] name = "numtoa" -version = "0.1.0" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8f8bdf33df195859076e54ab11ee78a1b208382d3a26ec40d142ffc1ecc49ef" +checksum = "6aa2c4e539b869820a2b82e1aef6ff40aa85e65decdd5185e83fb4b1249cd00f" [[package]] name = "object" -version = "0.32.2" +version = "0.36.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" +checksum = "aedf0a2d09c573ed1d8d85b30c119153926a2b36dce0ab28322c09a117a4683e" dependencies = [ "crc32fast", "flate2", - "hashbrown 0.14.5", - "indexmap 2.2.6", + "hashbrown 0.15.0", + "indexmap 2.6.0", "memchr", "ruzstd", ] [[package]] name = "once_cell" -version = "1.19.0" +version = "1.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" [[package]] name = "onig" @@ -4572,9 +5378,9 @@ dependencies = [ [[package]] name = "oorandom" -version = "11.1.3" +version = "11.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575" +checksum = "b410bbe7e14ab526a0e86877eb47c6996a2bd7746f027ba551028c925390e4e9" [[package]] name = "opaque-debug" @@ -4584,33 +5390,23 @@ checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" [[package]] name = "opener" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "293c15678e37254c15bd2f092314abb4e51d7fdde05c2021279c12631b54f005" -dependencies = [ - "bstr", - "winapi", -] - -[[package]] -name = "opener" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8df34be653210fbe9ffaff41d3b92721c56ce82dfee58ee684f9afb5e3a90c0" +checksum = "d0812e5e4df08da354c851a3376fead46db31c2214f849d3de356d774d057681" dependencies = [ "bstr", "dbus", "normpath", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] name = "openssl" -version = "0.10.64" +version = "0.10.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95a0481286a310808298130d22dd1fef0fa571e05a8f44ec801801e84b216b1f" +checksum = "6174bc48f102d208783c2c84bf931bb75927a617866870de8a4ea85597f871f5" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "cfg-if 1.0.0", "foreign-types", "libc", @@ -4627,7 +5423,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.65", + "syn 2.0.79", ] [[package]] @@ -4638,18 +5434,18 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-src" -version = "300.3.0+3.3.0" +version = "300.3.2+3.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eba8804a1c5765b18c4b3f907e6897ebabeedebc9830e1a0046c4a4cf44663e1" +checksum = "a211a18d945ef7e648cc6e0058f4c548ee46aab922ea203e0d30e966ea23647b" dependencies = [ "cc", ] [[package]] name = "openssl-sys" -version = "0.9.102" +version = "0.9.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c597637d56fbc83893a35eb0dd04b2b8e7a50c91e64e9493e398b5df4fb45fa2" +checksum = "45abf306cbf99debc8195b66b7346498d7b10c210de50418b5ccd7ceba08c741" dependencies = [ "cc", "libc", @@ -4658,6 +5454,28 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "option-ext" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" + +[[package]] +name = "os_pipe" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ffd2b0a5634335b135d5728d84c5e0fd726954b87111f7506a61c502280d982" +dependencies = [ + "libc", + "windows-sys 0.59.0", +] + +[[package]] +name = "outref" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4030760ffd992bef45b0ae3f10ce1aba99e33464c90d14dd7c039884963ddc7a" + [[package]] name = "overload" version = "0.1.1" @@ -4670,6 +5488,12 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2386b4ebe91c2f7f51082d4cefa145d030e33a1842a96b12e4885cc3c01f7a55" +[[package]] +name = "owo-colors" +version = "3.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f" + [[package]] name = "p256" version = "0.13.2" @@ -4697,7 +5521,7 @@ version = "3.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "306800abfa29c7f16596b5970a588435e3d5b3149683d00c12b699cc19f895ee" dependencies = [ - "arrayvec 0.7.4", + "arrayvec", "bitvec", "byte-slice-cast", "impl-trait-for-tuples", @@ -4711,7 +5535,7 @@ version = "3.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d830939c76d294956402033aee57a6da7b438f2294eb94864c37b0569053a42c" dependencies = [ - "proc-macro-crate 3.1.0", + "proc-macro-crate 3.2.0", "proc-macro2", "quote", "syn 1.0.109", @@ -4730,9 +5554,9 @@ dependencies = [ [[package]] name = "parking_lot" -version = "0.12.2" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e4af0ca4f6caed20e900d564c242b8e5d4903fdacf31d3daf527b66fe6f42fb" +checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" dependencies = [ "lock_api", "parking_lot_core 0.9.10", @@ -4760,9 +5584,9 @@ checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" dependencies = [ "cfg-if 1.0.0", "libc", - "redox_syscall 0.5.1", + "redox_syscall 0.5.7", "smallvec", - "windows-targets 0.52.5", + "windows-targets 0.52.6", ] [[package]] @@ -4792,9 +5616,9 @@ dependencies = [ [[package]] name = "peg" -version = "0.7.0" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07c0b841ea54f523f7aa556956fbd293bcbe06f2e67d2eb732b7278aaf1d166a" +checksum = "295283b02df346d1ef66052a757869b2876ac29a6bb0ac3f5f7cd44aebe40e8f" dependencies = [ "peg-macros", "peg-runtime", @@ -4802,9 +5626,9 @@ dependencies = [ [[package]] name = "peg-macros" -version = "0.7.0" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5aa52829b8decbef693af90202711348ab001456803ba2a98eb4ec8fb70844c" +checksum = "bdad6a1d9cf116a059582ce415d5f5566aabcd4008646779dab7fdc2a9a9d426" dependencies = [ "peg-runtime", "proc-macro2", @@ -4813,9 +5637,9 @@ dependencies = [ [[package]] name = "peg-runtime" -version = "0.7.0" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c719dcf55f09a3a7e764c6649ab594c18a177e3599c467983cdf644bfc0a4088" +checksum = "e3aeb8f54c078314c2065ee649a7241f46b9d8e418e1a9581ba0546657d7aa3a" [[package]] name = "percent-encoding" @@ -4825,9 +5649,9 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "pest" -version = "2.7.10" +version = "2.7.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "560131c633294438da9f7c4b08189194b20946c8274c6b9e38881a7874dc8ee8" +checksum = "879952a81a83930934cbf1786752d6dedc3b1f29e8f8fb2ad1d0a36f377cf442" dependencies = [ "memchr", "thiserror", @@ -4836,9 +5660,9 @@ dependencies = [ [[package]] name = "pest_derive" -version = "2.7.10" +version = "2.7.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26293c9193fbca7b1a3bf9b79dc1e388e927e6cacaa78b4a3ab705a1d3d41459" +checksum = "d214365f632b123a47fd913301e14c946c61d1c183ee245fa76eb752e59a02dd" dependencies = [ "pest", "pest_generator", @@ -4846,22 +5670,22 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.7.10" +version = "2.7.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ec22af7d3fb470a85dd2ca96b7c577a1eb4ef6f1683a9fe9a8c16e136c04687" +checksum = "eb55586734301717aea2ac313f50b2eb8f60d2fc3dc01d190eefa2e625f60c4e" dependencies = [ "pest", "pest_meta", "proc-macro2", "quote", - "syn 2.0.65", + "syn 2.0.79", ] [[package]] name = "pest_meta" -version = "2.7.10" +version = "2.7.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7a240022f37c361ec1878d646fc5b7d7c4d28d5946e1a80ad5a7a4f4ca0bdcd" +checksum = "b75da2a70cf4d9cb76833c990ac9cd3923c9a8905a8929789ce347c84564d03d" dependencies = [ "once_cell", "pest", @@ -4875,27 +5699,26 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" dependencies = [ "fixedbitset", - "indexmap 2.2.6", + "indexmap 2.6.0", "serde", "serde_derive", ] [[package]] name = "phf" -version = "0.10.1" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fabbf1ead8a5bcbc20f5f8b939ee3f5b0f6f281b6ad3468b84656b658b455259" +checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" dependencies = [ "phf_macros", "phf_shared", - "proc-macro-hack", ] [[package]] name = "phf_generator" -version = "0.10.0" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d5285893bb5eb82e6aaf5d59ee909a06a16737a8970984dd7746ba9283498d6" +checksum = "48e4cc64c2ad9ebe670cb8fd69dd50ae301650392e81c05f9bfcb2d5bdbc24b0" dependencies = [ "phf_shared", "rand", @@ -4903,45 +5726,44 @@ dependencies = [ [[package]] name = "phf_macros" -version = "0.10.0" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58fdf3184dd560f160dd73922bea2d5cd6e8f064bf4b13110abd81b03697b4e0" +checksum = "3444646e286606587e49f3bcf1679b8cef1dc2c5ecc29ddacaffc305180d464b" dependencies = [ "phf_generator", "phf_shared", - "proc-macro-hack", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.79", ] [[package]] name = "phf_shared" -version = "0.10.0" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6796ad771acdc0123d2a88dc428b5e38ef24456743ddb1744ed628f9815c096" +checksum = "90fcb95eef784c2ac79119d1dd819e162b5da872ce6f3c3abe1e8ca1c082f72b" dependencies = [ "siphasher", ] [[package]] name = "pin-project" -version = "1.1.5" +version = "1.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" +checksum = "baf123a161dde1e524adf36f90bc5d8d3462824a9c43553ad07a8183161189ec" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.5" +version = "1.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" +checksum = "a4502d8515ca9f32f1fb543d987f63d95a14934883db45bdb48060b6b69257f8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.65", + "syn 2.0.79", ] [[package]] @@ -4968,25 +5790,18 @@ dependencies = [ [[package]] name = "pkg-config" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" - -[[package]] -name = "platforms" -version = "3.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db23d408679286588f4d4644f965003d056e3dd5abcaaa938116871d7ce2fee7" +checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" [[package]] name = "plist" -version = "1.6.1" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9d34169e64b3c7a80c8621a48adaf44e0cf62c78a9b25dd9dd35f1881a17cf9" +checksum = "42cf17e9a1800f5f396bc67d193dc9411b59012a5876445ef450d449881e1016" dependencies = [ - "base64 0.21.7", - "indexmap 2.2.6", - "line-wrap", + "base64 0.22.1", + "indexmap 2.6.0", "quick-xml", "serde", "time", @@ -4994,9 +5809,9 @@ dependencies = [ [[package]] name = "plotters" -version = "0.3.6" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a15b6eccb8484002195a3e44fe65a4ce8e93a625797a063735536fd59cb01cf3" +checksum = "5aeb6f403d7a4911efb1e33402027fc44f29b5bf6def3effcc22d7bb75f2b747" dependencies = [ "num-traits", "plotters-backend", @@ -5007,15 +5822,15 @@ dependencies = [ [[package]] name = "plotters-backend" -version = "0.3.6" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "414cec62c6634ae900ea1c56128dfe87cf63e7caece0852ec76aba307cebadb7" +checksum = "df42e13c12958a16b3f7f4386b9ab1f3e7933914ecea48da7139435263a4172a" [[package]] name = "plotters-svg" -version = "0.3.6" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81b30686a7d9c3e010b84284bdd26a29f2138574f52f5eb6f794fc0ad924e705" +checksum = "51bae2ac328883f7acdfea3d66a7c35751187f870bc81f94563733a154d7a670" dependencies = [ "plotters-backend", ] @@ -5031,12 +5846,13 @@ dependencies = [ [[package]] name = "postcard" -version = "1.0.8" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a55c51ee6c0db07e68448e336cf8ea4131a620edefebf9893e759b2d793420f8" +checksum = "5f7f0a8d620d71c457dd1d47df76bb18960378da56af4527aaa10f515eee732e" dependencies = [ "cobs", - "embedded-io", + "embedded-io 0.4.0", + "embedded-io 0.6.1", "heapless", "serde", ] @@ -5049,29 +5865,21 @@ checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" [[package]] name = "ppv-lite86" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" - -[[package]] -name = "pretty_assertions" -version = "1.4.0" +version = "0.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af7cee1a6c8a5b9208b3cb1061f10c0cb689087b3d8ce85fb9d2dd7a29b6ba66" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" dependencies = [ - "diff", - "yansi", + "zerocopy", ] [[package]] -name = "prettydiff" -version = "0.5.1" +name = "pretty_assertions" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb5671a83709b2755fe5b776d4915701bf36ed2cd9575035502ec12818141d71" +checksum = "3ae130e2f271fbc2ac3a40fb1d07180839cdbbe443c7a27e1e3c13c5cac0116d" dependencies = [ - "ansi_term", - "prettytable-rs 0.8.0", - "structopt", + "diff", + "yansi 1.0.1", ] [[package]] @@ -5082,22 +5890,19 @@ checksum = "8ff1fec61082821f8236cf6c0c14e8172b62ce8a72a0eedc30d3b247bb68dc11" dependencies = [ "ansi_term", "pad", - "prettytable-rs 0.10.0", + "prettytable-rs", "structopt", ] [[package]] -name = "prettytable-rs" -version = "0.8.0" +name = "prettydiff" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fd04b170004fa2daccf418a7f8253aaf033c27760b5f225889024cf66d7ac2e" +checksum = "abec3fb083c10660b3854367697da94c674e9e82aa7511014dc958beeb7215e9" dependencies = [ - "atty", - "csv", - "encode_unicode 0.3.6", - "lazy_static", - "term 0.5.2", - "unicode-width", + "owo-colors 3.5.0", + "pad", + "prettytable-rs", ] [[package]] @@ -5110,7 +5915,7 @@ dependencies = [ "encode_unicode 1.0.0", "is-terminal", "lazy_static", - "term 0.7.0", + "term", "unicode-width", ] @@ -5148,11 +5953,11 @@ dependencies = [ [[package]] name = "proc-macro-crate" -version = "3.1.0" +version = "3.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d37c51ca738a55da99dc0c4a34860fd675453b8b36209178c2249bb13651284" +checksum = "8ecf48c7ca261d60b74ab1a7b20da18bede46776b2e55535cb958eb595c5fa7b" dependencies = [ - "toml_edit 0.21.1", + "toml_edit", ] [[package]] @@ -5179,30 +5984,24 @@ dependencies = [ "version_check", ] -[[package]] -name = "proc-macro-hack" -version = "0.5.20+deprecated" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" - [[package]] name = "proc-macro2" -version = "1.0.83" +version = "1.0.88" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b33eb56c327dec362a9e55b3ad14f9d2f0904fb5a5b03b513ab5465399e9f43" +checksum = "7c3a7fc5db1e57d5a779a352c8cdb57b29aa4c40cc69c3a68a7fedc815fbf2f9" dependencies = [ "unicode-ident", ] [[package]] name = "prometheus-client" -version = "0.22.2" +version = "0.22.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1ca959da22a332509f2a73ae9e5f23f9dcfc31fd3a54d71f159495bd5909baa" +checksum = "504ee9ff529add891127c4827eb481bd69dc0ebc72e9a682e187db4caa60c3ca" dependencies = [ "dtoa", "itoa", - "parking_lot 0.12.2", + "parking_lot 0.12.3", "prometheus-client-derive-encode", ] @@ -5214,7 +6013,27 @@ checksum = "440f724eba9f6996b75d63681b0a92b06947f1457076d503a4d2e2c8f56442b8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.65", + "syn 2.0.79", +] + +[[package]] +name = "proptest" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4c2511913b88df1637da85cc8d96ec8e43a3f8bb8ccb71ee1ac240d6f3df58d" +dependencies = [ + "bit-set", + "bit-vec", + "bitflags 2.6.0", + "lazy_static", + "num-traits", + "rand", + "rand_chacha", + "rand_xorshift", + "regex-syntax 0.8.5", + "rusty-fork", + "tempfile", + "unarray", ] [[package]] @@ -5223,6 +6042,26 @@ version = "2.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33cb294fe86a74cbcf50d4445b37da762029549ebeea341421c7c70370f86cac" +[[package]] +name = "ptr_meta" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0738ccf7ea06b608c10564b31debd4f5bc5e197fc8bfe088f68ae5ce81e7a4f1" +dependencies = [ + "ptr_meta_derive", +] + +[[package]] +name = "ptr_meta_derive" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16b845dbfca988fa33db069c0e230574d15a3088f147a87b64c7589eb662c9ac" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "ptyprocess" version = "0.4.1" @@ -5248,7 +6087,7 @@ version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "76979bea66e7875e7509c4ec5300112b316af87fa7a252ca91c448b32dfe3993" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "memchr", "pulldown-cmark-escape", "unicase", @@ -5260,6 +6099,12 @@ version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bd348ff538bc9caeda7ee8cad2d1d48236a1f443c1fa3913c6a02fe0043b1dd3" +[[package]] +name = "quick-error" +version = "1.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" + [[package]] name = "quick-protobuf" version = "0.8.1" @@ -5271,18 +6116,18 @@ dependencies = [ [[package]] name = "quick-xml" -version = "0.31.0" +version = "0.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1004a344b30a54e2ee58d66a71b32d2db2feb0a31f9a2d302bf0536f15de2a33" +checksum = "1d3a6e5838b60e0e8fa7a43f22ade549a37d61f8bdbe636d0d7816191de969c2" dependencies = [ "memchr", ] [[package]] name = "quote" -version = "1.0.36" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" dependencies = [ "proc-macro2", ] @@ -5330,7 +6175,16 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom 0.2.15", + "getrandom", +] + +[[package]] +name = "rand_xorshift" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d25bf25ec5ae4a3f1b92f929810509a2f53d7dca2f50b794ff57e3face536c8f" +dependencies = [ + "rand_core", ] [[package]] @@ -5373,12 +6227,6 @@ dependencies = [ "crossbeam-utils", ] -[[package]] -name = "redox_syscall" -version = "0.1.57" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce" - [[package]] name = "redox_syscall" version = "0.2.16" @@ -5399,11 +6247,11 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.1" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "469052894dcb553421e483e4209ee581a45100d31b4018de03e5a7ad86374a7e" +checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", ] [[package]] @@ -5414,36 +6262,25 @@ checksum = "20145670ba436b55d91fc92d25e71160fbfbdd57831631c8d7d36377a476f1cb" [[package]] name = "redox_users" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de0737333e7a9502c789a36d7c7fa6092a49895d4faa31ca5df163857ded2e9d" -dependencies = [ - "getrandom 0.1.16", - "redox_syscall 0.1.57", - "rust-argon2", -] - -[[package]] -name = "redox_users" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd283d9651eeda4b2a83a43c1c91b266c40fd76ecd39a50a8c630ae69dc72891" +checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" dependencies = [ - "getrandom 0.2.15", + "getrandom", "libredox 0.1.3", "thiserror", ] [[package]] name = "regex" -version = "1.10.4" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c" +checksum = "38200e5ee88914975b69f657f0801b6f6dccafd44fd9326302a4aaeecfacb1d8" dependencies = [ "aho-corasick", "memchr", - "regex-automata 0.4.6", - "regex-syntax 0.8.3", + "regex-automata 0.4.8", + "regex-syntax 0.8.5", ] [[package]] @@ -5457,15 +6294,21 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.6" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" +checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3" dependencies = [ "aho-corasick", "memchr", - "regex-syntax 0.8.3", + "regex-syntax 0.8.5", ] +[[package]] +name = "regex-lite" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53a49587ad06b26609c52e423de037e7f57f20d53535d66e08c695f347df952a" + [[package]] name = "regex-syntax" version = "0.6.29" @@ -5474,9 +6317,18 @@ checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" [[package]] name = "regex-syntax" -version = "0.8.3" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" + +[[package]] +name = "rend" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" +checksum = "71fe3824f5629716b1589be05dacd749f6aa084c87e00e016714a8cdfccc997c" +dependencies = [ + "bytecheck", +] [[package]] name = "reqwest" @@ -5491,29 +6343,26 @@ dependencies = [ "encoding_rs", "futures-core", "futures-util", - "h2", - "http", - "http-body", - "hyper", + "h2 0.3.26", + "http 0.2.12", + "http-body 0.4.6", + "hyper 0.14.31", "hyper-rustls 0.24.2", - "hyper-tls", "ipnet", "js-sys", "log", "mime", - "native-tls", "once_cell", "percent-encoding", "pin-project-lite", "rustls 0.21.12", - "rustls-pemfile", + "rustls-pemfile 1.0.4", "serde", "serde_json", "serde_urlencoded", - "sync_wrapper", - "system-configuration", + "sync_wrapper 0.1.2", + "system-configuration 0.5.1", "tokio", - "tokio-native-tls", "tokio-rustls 0.24.1", "tower-service", "url", @@ -5524,41 +6373,113 @@ dependencies = [ "winreg", ] +[[package]] +name = "reqwest" +version = "0.12.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f713147fbe92361e52392c73b8c9e48c04c6625bce969ef54dc901e58e042a7b" +dependencies = [ + "base64 0.22.1", + "bytes", + "encoding_rs", + "futures-core", + "futures-util", + "h2 0.4.6", + "http 1.1.0", + "http-body 1.0.1", + "http-body-util", + "hyper 1.5.0", + "hyper-rustls 0.27.3", + "hyper-tls", + "hyper-util", + "ipnet", + "js-sys", + "log", + "mime", + "native-tls", + "once_cell", + "percent-encoding", + "pin-project-lite", + "rustls-pemfile 2.2.0", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper 1.0.1", + "system-configuration 0.6.1", + "tokio", + "tokio-native-tls", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "windows-registry", +] + [[package]] name = "revm" -version = "2.3.1" +version = "14.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73d84c8f9836efb0f5f5f8de4700a953c4e1f3119e5cfcb0aad8e5be73daf991" +checksum = "641702b12847f9ed418d552f4fcabe536d867a2c980e96b6e7e25d7b992f929f" dependencies = [ - "arrayref", "auto_impl", - "bytes", - "hashbrown 0.13.2", - "num_enum 0.5.11", - "primitive-types", - "revm_precompiles", - "rlp", - "sha3", + "cfg-if 1.0.0", + "dyn-clone", + "revm-interpreter", + "revm-precompile", + "serde", + "serde_json", ] [[package]] -name = "revm_precompiles" -version = "1.1.2" +name = "revm-interpreter" +version = "10.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0353d456ef3e989dc9190f42c6020f09bc2025930c37895826029304413204b5" +checksum = "2e5e14002afae20b5bf1566f22316122f42f57517000e559c55b25bf7a49cba2" dependencies = [ - "bytes", - "hashbrown 0.13.2", - "num", + "revm-primitives", + "serde", +] + +[[package]] +name = "revm-precompile" +version = "11.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3198c06247e8d4ad0d1312591edf049b0de4ddffa9fecb625c318fd67db8639b" +dependencies = [ + "aurora-engine-modexp", + "blst", + "c-kzg", + "cfg-if 1.0.0", + "k256", "once_cell", - "primitive-types", + "revm-primitives", "ripemd", - "secp256k1 0.24.3", + "secp256k1", "sha2 0.10.8", - "sha3", "substrate-bn", ] +[[package]] +name = "revm-primitives" +version = "10.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f1525851a03aff9a9d6a1d018b414d76252d6802ab54695b27093ecd7e7a101" +dependencies = [ + "alloy-eip2930", + "alloy-eip7702", + "alloy-primitives", + "auto_impl", + "bitflags 2.6.0", + "bitvec", + "c-kzg", + "cfg-if 1.0.0", + "dyn-clone", + "enumn", + "hex", + "serde", +] + [[package]] name = "rexpect" version = "0.4.0" @@ -5572,28 +6493,26 @@ dependencies = [ ] [[package]] -name = "rfc6979" -version = "0.4.0" +name = "rexpect" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" +checksum = "01ff60778f96fb5a48adbe421d21bf6578ed58c0872d712e7e08593c195adff8" dependencies = [ - "hmac 0.12.1", - "subtle", + "comma", + "nix 0.25.1", + "regex", + "tempfile", + "thiserror", ] [[package]] -name = "ring" -version = "0.16.20" +name = "rfc6979" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc" +checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" dependencies = [ - "cc", - "libc", - "once_cell", - "spin 0.5.2", - "untrusted 0.7.1", - "web-sys", - "winapi", + "hmac 0.12.1", + "subtle", ] [[package]] @@ -5604,10 +6523,10 @@ checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" dependencies = [ "cc", "cfg-if 1.0.0", - "getrandom 0.2.15", + "getrandom", "libc", - "spin 0.9.8", - "untrusted 0.9.0", + "spin", + "untrusted", "windows-sys 0.52.0", ] @@ -5620,6 +6539,35 @@ dependencies = [ "digest 0.10.7", ] +[[package]] +name = "rkyv" +version = "0.7.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9008cd6385b9e161d8229e1f6549dd23c3d022f132a2ea37ac3a10ac4935779b" +dependencies = [ + "bitvec", + "bytecheck", + "bytes", + "hashbrown 0.12.3", + "ptr_meta", + "rend", + "rkyv_derive", + "seahash", + "tinyvec", + "uuid 1.11.0", +] + +[[package]] +name = "rkyv_derive" +version = "0.7.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "503d1d27590a2b0a3a4ca4c94755aa2875657196ecbf401a42eff41d7de532c0" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "rlp" version = "0.5.2" @@ -5653,14 +6601,13 @@ dependencies = [ [[package]] name = "rowan" -version = "0.14.1" +version = "0.15.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f77412a3d1f26af0c0783c23b3555a301b1a49805cba7bf9a7827a9e9e285f0" +checksum = "0a542b0253fa46e632d27a1dc5cf7b930de4df8659dc6e720b647fc72147ae3d" dependencies = [ "countme", - "hashbrown 0.11.2", - "memoffset 0.6.5", - "rustc-hash", + "hashbrown 0.14.5", + "rustc-hash 1.1.0", "text-size", ] @@ -5686,15 +6633,49 @@ dependencies = [ ] [[package]] -name = "rust-argon2" -version = "0.8.3" +name = "ruint" +version = "1.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c3cc4c2511671f327125da14133d0c5c5d137f006a1017a16f557bc85b16286" +dependencies = [ + "alloy-rlp", + "ark-ff 0.3.0", + "ark-ff 0.4.2", + "bytes", + "fastrlp", + "num-bigint", + "num-traits", + "parity-scale-codec", + "primitive-types", + "proptest", + "rand", + "rlp", + "ruint-macro", + "serde", + "valuable", + "zeroize", +] + +[[package]] +name = "ruint-macro" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48fd7bd8a6377e15ad9d42a8ec25371b94ddc67abe7c8b9127bec79bebaaae18" + +[[package]] +name = "rust_decimal" +version = "1.36.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b18820d944b33caa75a71378964ac46f58517c92b6ae5f762636247c09e78fb" +checksum = "b082d80e3e3cc52b2ed634388d436fe1f4de6af5786cc2de9ba9737527bdf555" dependencies = [ - "base64 0.13.1", - "blake2b_simd 0.5.11", - "constant_time_eq 0.1.5", - "crossbeam-utils", + "arrayvec", + "borsh", + "bytes", + "num-traits", + "rand", + "rkyv", + "serde", + "serde_json", ] [[package]] @@ -5709,6 +6690,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" +[[package]] +name = "rustc-hash" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "583034fd73374156e66797ed8e5b0d5690409c9226b22d87cb7f19821c05d152" + [[package]] name = "rustc-hex" version = "2.1.0" @@ -5717,37 +6704,33 @@ checksum = "3e75f6a532d0fd9f7f13144f392b6ad56a32696bfcd9c78f797f16bbb6f072d6" [[package]] name = "rustc_version" -version = "0.4.0" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +checksum = "f0dfe2087c51c460008730de8b57e6a320782fbfb312e1f4d520e6c6fae155ee" dependencies = [ - "semver", + "semver 0.11.0", ] [[package]] -name = "rustix" -version = "0.38.34" +name = "rustc_version" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" dependencies = [ - "bitflags 2.5.0", - "errno", - "libc", - "linux-raw-sys", - "windows-sys 0.52.0", + "semver 1.0.23", ] [[package]] -name = "rustls" -version = "0.19.1" +name = "rustix" +version = "0.38.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35edb675feee39aec9c99fa5ff985081995a06d594114ae14cbe797ad7b7a6d7" +checksum = "8acb788b847c24f28525660c4d7758620a7210875711f79e7f663cc152726811" dependencies = [ - "base64 0.13.1", - "log", - "ring 0.16.20", - "sct 0.6.1", - "webpki", + "bitflags 2.6.0", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.52.0", ] [[package]] @@ -5757,21 +6740,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f56a14d1f48b391359b22f731fd4bd7e43c97f3c50eee276f3aa09c94784d3e" dependencies = [ "log", - "ring 0.17.8", - "rustls-webpki", - "sct 0.7.1", + "ring", + "rustls-webpki 0.101.7", + "sct", ] [[package]] -name = "rustls-native-certs" -version = "0.5.0" +name = "rustls" +version = "0.23.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a07b7c1885bd8ed3831c289b7870b13ef46fe0e856d288c30d9cc17d75a2092" +checksum = "5fbb44d7acc4e873d613422379f69f237a1b141928c02f6bc6ccfddddc2d7993" dependencies = [ - "openssl-probe", - "rustls 0.19.1", - "schannel", - "security-framework", + "once_cell", + "rustls-pki-types", + "rustls-webpki 0.102.8", + "subtle", + "zeroize", ] [[package]] @@ -5781,7 +6765,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a9aace74cb666635c918e9c12bc0d348266037aa8eb599b5cba565709a8dff00" dependencies = [ "openssl-probe", - "rustls-pemfile", + "rustls-pemfile 1.0.4", "schannel", "security-framework", ] @@ -5795,40 +6779,76 @@ dependencies = [ "base64 0.21.7", ] +[[package]] +name = "rustls-pemfile" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" +dependencies = [ + "rustls-pki-types", +] + +[[package]] +name = "rustls-pki-types" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16f1201b3c9a7ee8039bcadc17b7e605e2945b27eee7631788c1bd2b0643674b" + [[package]] name = "rustls-webpki" version = "0.101.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" dependencies = [ - "ring 0.17.8", - "untrusted 0.9.0", + "ring", + "untrusted", +] + +[[package]] +name = "rustls-webpki" +version = "0.102.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9" +dependencies = [ + "ring", + "rustls-pki-types", + "untrusted", ] [[package]] name = "rustversion" -version = "1.0.17" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e819f2bc632f285be6d7cd36e25940d45b2391dd6d9b939e79de557f7014248" + +[[package]] +name = "rusty-fork" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" +checksum = "cb3dcc6e454c328bb824492db107ab7c0ae8fcffe4ad210136ef014458c1bc4f" +dependencies = [ + "fnv", + "quick-error", + "tempfile", + "wait-timeout", +] [[package]] name = "rustyline" -version = "8.2.0" +version = "13.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbd4eaf7a7738f76c98e4f0395253ae853be3eb018f7b0bb57fe1b6c17e31874" +checksum = "02a2d683a4ac90aeef5b1013933f6d977bd37d51ff3f4dad829d4931a7e6be86" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.6.0", "cfg-if 1.0.0", "clipboard-win", - "dirs-next", - "fd-lock 2.0.0", + "fd-lock", + "home", "libc", "log", "memchr", - "nix 0.20.0", + "nix 0.27.1", "radix_trie", - "scopeguard", - "smallvec", "unicode-segmentation", "unicode-width", "utf8parse", @@ -5837,12 +6857,10 @@ dependencies = [ [[package]] name = "ruzstd" -version = "0.5.0" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58c4eb8a81997cf040a091d1f7e1938aeab6749d3a0dfa73af43cdc32393483d" +checksum = "99c3938e133aac070997ddc684d4b393777d293ba170f2988c8fd5ea2ad4ce21" dependencies = [ - "byteorder", - "derive_more", "twox-hash", ] @@ -5872,20 +6890,20 @@ dependencies = [ [[package]] name = "scc" -version = "2.1.1" +version = "2.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76ad2bbb0ae5100a07b7a6f2ed7ab5fd0045551a4c507989b7a620046ea3efdc" +checksum = "f2c1f7fc6deb21665a9060dfc7d271be784669295a31babdcd4dd2c79ae8cbfb" dependencies = [ "sdd", ] [[package]] name = "schannel" -version = "0.1.23" +version = "0.1.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbc91545643bcf3a0bbb6569265615222618bdf33ce4ffbbd13c4bbd4c093534" +checksum = "01227be5826fa0690321a2ba6c5cd57a19cf3f6a09e76973b58e61de6ab9d1c1" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -5932,31 +6950,27 @@ dependencies = [ "sha2 0.10.8", ] -[[package]] -name = "sct" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b362b83898e0e69f38515b82ee15aa80636befe47c3b6d3d89a911e78fc228ce" -dependencies = [ - "ring 0.16.20", - "untrusted 0.7.1", -] - [[package]] name = "sct" version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" dependencies = [ - "ring 0.17.8", - "untrusted 0.9.0", + "ring", + "untrusted", ] [[package]] name = "sdd" -version = "0.2.0" +version = "3.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49c1eeaf4b6a87c7479688c6d52b9f1153cedd3c489300564f932b065c6eab95" + +[[package]] +name = "seahash" +version = "4.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b84345e4c9bd703274a082fb80caaa99b7612be48dfaa1dd9266577ec412309d" +checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b" [[package]] name = "sec1" @@ -5974,37 +6988,19 @@ dependencies = [ [[package]] name = "secp256k1" -version = "0.24.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b1629c9c557ef9b293568b338dddfc8208c98a18c59d722a9d53f859d9c9b62" -dependencies = [ - "secp256k1-sys 0.6.1", -] - -[[package]] -name = "secp256k1" -version = "0.26.0" +version = "0.29.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4124a35fe33ae14259c490fd70fa199a32b9ce9502f2ee6bc4f81ec06fa65894" +checksum = "9465315bc9d4566e1724f0fffcbcc446268cb522e60f9a27bcded6b19c108113" dependencies = [ "rand", - "secp256k1-sys 0.8.1", + "secp256k1-sys", ] [[package]] name = "secp256k1-sys" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83080e2c2fc1006e625be82e5d1eb6a43b7fd9578b617fcc55814daf286bba4b" -dependencies = [ - "cc", -] - -[[package]] -name = "secp256k1-sys" -version = "0.8.1" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70a129b9e9efbfb223753b9163c4ab3b13cff7fd9c7f010fbac25ab4099fa07e" +checksum = "d4387882333d3aa8cb20530a17c69a3752e97837832f34f6dccc760e715001d9" dependencies = [ "cc", ] @@ -6020,11 +7016,11 @@ dependencies = [ [[package]] name = "security-framework" -version = "2.11.0" +version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c627723fd09706bacdb5cf41499e95098555af3c3c29d014dc3c458ef6be11c0" +checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "core-foundation", "core-foundation-sys", "libc", @@ -6033,14 +7029,23 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.11.0" +version = "2.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "317936bbbd05227752583946b9e66d7ce3b489f84e11a94a510b4437fef407d7" +checksum = "ea4a292869320c0272d7bc55a5a6aafaff59b4f63404a003887b679a2e05b4b6" dependencies = [ "core-foundation-sys", "libc", ] +[[package]] +name = "semver" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f301af10236f6df4160f7c3f04eec6dbc70ace82d23326abad5edee88801c6b6" +dependencies = [ + "semver-parser", +] + [[package]] name = "semver" version = "1.0.23" @@ -6050,24 +7055,33 @@ dependencies = [ "serde", ] +[[package]] +name = "semver-parser" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0bef5b7f9e0df16536d3961cfb6e84331c065b4066afb39768d0e319411f7" +dependencies = [ + "pest", +] + [[package]] name = "serde" -version = "1.0.202" +version = "1.0.210" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "226b61a0d411b2ba5ff6d7f73a476ac4f8bb900373459cd00fab8512828ba395" +checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.202" +version = "1.0.210" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6048858004bcff69094cd972ed40a32500f153bd3be9f716b2eed2e8217c4838" +checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.65", + "syn 2.0.79", ] [[package]] @@ -6081,11 +7095,13 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.117" +version = "1.0.129" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "455182ea6142b14f93f4bc5320a2b31c1f266b66a4a5c858b013302a5d8cbfc3" +checksum = "6dbcf9b78a125ee667ae19388837dd12294b858d101fdd393cb9d5501ef09eb2" dependencies = [ + "indexmap 2.6.0", "itoa", + "memchr", "ryu", "serde", ] @@ -6098,14 +7114,14 @@ checksum = "6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.65", + "syn 2.0.79", ] [[package]] name = "serde_spanned" -version = "0.6.6" +version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79e674e01f999af37c49f70a6ede167a8a60b2503e56c5599532a65baa5969a0" +checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1" dependencies = [ "serde", ] @@ -6124,15 +7140,15 @@ dependencies = [ [[package]] name = "serde_with" -version = "3.8.1" +version = "3.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ad483d2ab0149d5a5ebcd9972a3852711e0153d863bf5a5d0391d28883c4a20" +checksum = "8e28bdad6db2b8340e449f7108f020b3b092e8583a9e3fb82713e1d4e71fe817" dependencies = [ "base64 0.22.1", "chrono", "hex", "indexmap 1.9.3", - "indexmap 2.2.6", + "indexmap 2.6.0", "serde", "serde_derive", "serde_json", @@ -6142,14 +7158,14 @@ dependencies = [ [[package]] name = "serde_with_macros" -version = "3.8.1" +version = "3.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65569b702f41443e8bc8bbb1c5779bd0450bbe723b56198980e80ec45780bce2" +checksum = "9d846214a9854ef724f3da161b426242d8de7c1fc7de2f89bb1efcb154dca79d" dependencies = [ - "darling 0.20.9", + "darling 0.20.10", "proc-macro2", "quote", - "syn 2.0.65", + "syn 2.0.79", ] [[package]] @@ -6158,7 +7174,7 @@ version = "0.9.34+deprecated" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" dependencies = [ - "indexmap 2.2.6", + "indexmap 2.6.0", "itoa", "ryu", "serde", @@ -6174,7 +7190,7 @@ dependencies = [ "futures", "log", "once_cell", - "parking_lot 0.12.2", + "parking_lot 0.12.3", "scc", "serial_test_derive", ] @@ -6187,7 +7203,7 @@ checksum = "82fe9db325bcef1fbcde82e078a5cc4efdf787e96b3b9cf45b50b529f2083d67" dependencies = [ "proc-macro2", "quote", - "syn 2.0.65", + "syn 2.0.79", ] [[package]] @@ -6224,6 +7240,16 @@ dependencies = [ "keccak", ] +[[package]] +name = "sha3-asm" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c28efc5e327c837aa837c59eae585fc250715ef939ac32881bcc11677cd02d46" +dependencies = [ + "cc", + "cfg-if 1.0.0", +] + [[package]] name = "sharded-slab" version = "0.1.7" @@ -6233,6 +7259,16 @@ dependencies = [ "lazy_static", ] +[[package]] +name = "shared_child" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09fa9338aed9a1df411814a5b2252f7cd206c55ae9bf2fa763f8de84603aa60c" +dependencies = [ + "libc", + "windows-sys 0.59.0", +] + [[package]] name = "shell-words" version = "1.1.0" @@ -6241,15 +7277,17 @@ checksum = "24188a676b6ae68c3b2cb3a01be17fbf7240ce009799bb56d5b1409051e78fde" [[package]] name = "shellfish" -version = "0.6.0" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c66e6fc7a668d89939ee241fb342f401f8c11a80da8fb72fd14681f8d47440b" +checksum = "fef42fa3356b28a29aee098d1656681670da7eb15be0e89bba6f05aea540df3d" dependencies = [ "async-trait", "cfg-if 1.0.0", "rustyline", + "thiserror", "tokio", - "yansi", + "version_check", + "yansi 0.5.1", ] [[package]] @@ -6277,11 +7315,17 @@ dependencies = [ "rand_core", ] +[[package]] +name = "simdutf8" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e" + [[package]] name = "similar" -version = "2.5.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa42c91313f1d05da9b26f267f931cf178d4aba455b4c4622dd7355eb80c6640" +checksum = "1de1d4f81173b03af4c0cbed3c898f6bff5b870e4a7f5d6f4057d62a7a4b686e" [[package]] name = "siphasher" @@ -6319,9 +7363,9 @@ dependencies = [ [[package]] name = "slug" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3bd94acec9c8da640005f8e135a39fc0372e74535e6b368b7a04b875f784c8c4" +checksum = "882a80f72ee45de3cc9a5afeb2da0331d58df69e4e7d8eeb5d3c7784ae67e724" dependencies = [ "deunicode", "wasm-bindgen", @@ -6372,12 +7416,6 @@ dependencies = [ "windows-sys 0.52.0", ] -[[package]] -name = "spin" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" - [[package]] name = "spin" version = "0.9.8" @@ -6409,12 +7447,6 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" -[[package]] -name = "str-buf" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e08d8363704e6c71fc928674353e6b7c23dcea9d82d7012c8faf2a3a025f8d0" - [[package]] name = "str_indices" version = "0.4.3" @@ -6478,6 +7510,15 @@ version = "0.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "290d54ea6f91c969195bdbcd7442c8c2a2ba87da8bf60a7ee86a235d4bc1e125" +[[package]] +name = "strum" +version = "0.26.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06" +dependencies = [ + "strum_macros 0.26.4", +] + [[package]] name = "strum_macros" version = "0.24.3" @@ -6501,7 +7542,20 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.65", + "syn 2.0.79", +] + +[[package]] +name = "strum_macros" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" +dependencies = [ + "heck 0.5.0", + "proc-macro2", + "quote", + "rustversion", + "syn 2.0.79", ] [[package]] @@ -6519,13 +7573,13 @@ dependencies = [ [[package]] name = "subtle" -version = "2.5.0" +version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "sway-ast" -version = "0.60.0" +version = "0.66.2" dependencies = [ "extension-trait", "num-bigint", @@ -6537,11 +7591,11 @@ dependencies = [ [[package]] name = "sway-core" -version = "0.60.0" +version = "0.66.2" dependencies = [ - "clap 4.5.4", + "clap 4.5.20", "derivative", - "dirs 3.0.2", + "dirs 5.0.1", "either", "fuel-abi-types", "fuel-ethabi", @@ -6550,23 +7604,22 @@ dependencies = [ "fuel-vm", "gimli", "graph-cycles", - "hashbrown 0.13.2", + "hashbrown 0.14.5", "hex", "im", - "indexmap 2.2.6", - "itertools 0.10.5", + "indexmap 2.6.0", + "itertools 0.13.0", "lazy_static", - "miden-core", "object", - "parking_lot 0.12.2", + "parking_lot 0.12.3", "pest", "pest_derive", "petgraph", - "rustc-hash", + "rustc-hash 1.1.0", "serde", "serde_json", - "sha2 0.9.9", - "strum 0.24.1", + "sha2 0.10.8", + "strum 0.26.3", "sway-ast", "sway-error", "sway-ir", @@ -6582,12 +7635,13 @@ dependencies = [ [[package]] name = "sway-error" -version = "0.60.0" +version = "0.66.2" dependencies = [ "either", "in_definite", "num-traits", "smallvec", + "strsim 0.11.1", "sway-types", "thiserror", "uwuify", @@ -6595,17 +7649,17 @@ dependencies = [ [[package]] name = "sway-ir" -version = "0.60.0" +version = "0.66.2" dependencies = [ "anyhow", "downcast-rs", "filecheck", - "indexmap 2.2.6", - "itertools 0.10.5", + "indexmap 2.6.0", + "itertools 0.13.0", "once_cell", "peg", - "prettydiff 0.6.4", - "rustc-hash", + "prettydiff 0.7.0", + "rustc-hash 1.1.0", "slotmap", "sway-ir-macros", "sway-types", @@ -6614,34 +7668,35 @@ dependencies = [ [[package]] name = "sway-ir-macros" -version = "0.60.0" +version = "0.66.2" dependencies = [ - "itertools 0.10.5", + "itertools 0.13.0", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.79", ] [[package]] name = "sway-lsp" -version = "0.60.0" +version = "0.66.2" dependencies = [ "anyhow", "assert-json-diff", + "codspeed-criterion-compat", "criterion", "crossbeam-channel", - "dashmap", + "dashmap 6.1.0", "dirs 4.0.0", - "fd-lock 4.0.2", + "fd-lock", "forc-pkg", - "forc-tracing 0.60.0", + "forc-tracing 0.66.2", "forc-util", "futures", - "indexmap 2.2.6", + "indexmap 2.6.0", "lsp-types", "notify", "notify-debouncer-mini", - "parking_lot 0.12.2", + "parking_lot 0.12.3", "pretty_assertions", "proc-macro2", "quote", @@ -6649,7 +7704,6 @@ dependencies = [ "rayon", "rayon-cond", "regex", - "ropey", "serde", "serde_json", "sway-ast", @@ -6660,13 +7714,13 @@ dependencies = [ "sway-types", "sway-utils", "swayfmt", - "syn 1.0.109", + "syn 2.0.79", "tempfile", "thiserror", "tikv-jemallocator", "tokio", - "toml_edit 0.19.15", - "tower", + "toml_edit", + "tower 0.4.13", "tower-lsp", "tracing", "urlencoding", @@ -6674,7 +7728,7 @@ dependencies = [ [[package]] name = "sway-lsp-test-utils" -version = "0.1.0" +version = "0.66.2" dependencies = [ "assert-json-diff", "futures", @@ -6683,13 +7737,13 @@ dependencies = [ "serde", "serde_json", "tokio", - "tower", + "tower 0.5.1", "tower-lsp", ] [[package]] name = "sway-parse" -version = "0.60.0" +version = "0.66.2" dependencies = [ "assert_matches", "extension-trait", @@ -6707,18 +7761,18 @@ dependencies = [ [[package]] name = "sway-types" -version = "0.60.0" +version = "0.66.2" dependencies = [ "bytecount", "fuel-asm", "fuel-crypto", "fuel-tx", - "indexmap 2.2.6", + "indexmap 2.6.0", "lazy_static", "num-bigint", "num-traits", - "parking_lot 0.12.2", - "rustc-hash", + "parking_lot 0.12.3", + "rustc-hash 1.1.0", "serde", "sway-utils", "thiserror", @@ -6726,7 +7780,7 @@ dependencies = [ [[package]] name = "sway-utils" -version = "0.60.0" +version = "0.66.2" dependencies = [ "serde", "walkdir", @@ -6734,11 +7788,12 @@ dependencies = [ [[package]] name = "swayfmt" -version = "0.60.0" +version = "0.66.2" dependencies = [ "anyhow", "difference", - "forc-tracing 0.60.0", + "forc-tracing 0.66.2", + "indoc", "paste", "prettydiff 0.6.4", "ropey", @@ -6752,7 +7807,7 @@ dependencies = [ "sway-utils", "test-macros", "thiserror", - "toml 0.7.8", + "toml 0.8.19", ] [[package]] @@ -6768,21 +7823,42 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.65" +version = "2.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2863d96a84c6439701d7a38f9de935ec562c8832cc55d1dde0f513b52fad106" +checksum = "89132cd0bf050864e1d38dc3bbc07a0eb8e7530af26344d3d2bbbef83499f590" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] +[[package]] +name = "syn_derive" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1329189c02ff984e9736652b1631330da25eaa6bc639089ed4915d25446cbe7b" +dependencies = [ + "proc-macro-error", + "proc-macro2", + "quote", + "syn 2.0.79", +] + [[package]] name = "sync_wrapper" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" +[[package]] +name = "sync_wrapper" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" +dependencies = [ + "futures-core", +] + [[package]] name = "synstructure" version = "0.12.6" @@ -6803,7 +7879,7 @@ checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" dependencies = [ "proc-macro2", "quote", - "syn 2.0.65", + "syn 2.0.79", ] [[package]] @@ -6820,7 +7896,7 @@ dependencies = [ "once_cell", "onig", "plist", - "regex-syntax 0.8.3", + "regex-syntax 0.8.5", "serde", "serde_derive", "serde_json", @@ -6852,7 +7928,18 @@ checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" dependencies = [ "bitflags 1.3.2", "core-foundation", - "system-configuration-sys", + "system-configuration-sys 0.5.0", +] + +[[package]] +name = "system-configuration" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" +dependencies = [ + "bitflags 2.6.0", + "core-foundation", + "system-configuration-sys 0.6.0", ] [[package]] @@ -6865,6 +7952,16 @@ dependencies = [ "libc", ] +[[package]] +name = "system-configuration-sys" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "tai64" version = "4.0.0" @@ -6882,53 +7979,47 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] name = "taplo" -version = "0.7.0" +version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5d17cb5ff4095af064048f25a0a8df815384f63ce21c7410e96b93016757259" +checksum = "010941ac4171eaf12f1e26dfc11dadaf78619ea2330940fef01fe6bb0442d14d" dependencies = [ - "glob", - "indexmap 1.9.3", + "ahash 0.8.11", + "arc-swap", + "either", + "globset", + "itertools 0.10.5", "logos", - "regex", + "once_cell", "rowan", - "semver", - "smallvec", - "toml 0.5.11", - "wasm-bindgen", + "serde", + "serde_json", + "thiserror", + "time", + "tracing", ] [[package]] name = "tar" -version = "0.4.40" +version = "0.4.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b16afcea1f22891c49a00c751c7b63b2233284064f11a200fc624137c51e2ddb" +checksum = "4ff6c40d3aedb5e06b57c6f669ad17ab063dd1e63d977c6a88e7f4dfa4f04020" dependencies = [ "filetime", "libc", "xattr", ] -[[package]] -name = "tempfile" -version = "3.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" -dependencies = [ - "cfg-if 1.0.0", - "fastrand", - "rustix", - "windows-sys 0.52.0", -] - -[[package]] -name = "term" -version = "0.5.2" +[[package]] +name = "tempfile" +version = "3.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edd106a334b7657c10b7c540a0106114feadeb4dc314513e97df481d5d966f42" +checksum = "f0f2c9fc62d0beef6951ccffd757e241266a2c833136efbe35af6cd2567dca5b" dependencies = [ - "byteorder", - "dirs 1.0.5", - "winapi", + "cfg-if 1.0.0", + "fastrand", + "once_cell", + "rustix", + "windows-sys 0.59.0", ] [[package]] @@ -6944,23 +8035,32 @@ dependencies = [ [[package]] name = "term-table" -version = "1.3.2" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5e59d7fb313157de2a568be8d81e4d7f9af6e50e697702e8e00190a6566d3b8" +checksum = "210f90191b719267bc8b6307659faf54a77400d06b8033ece26692696fc002be" dependencies = [ "lazy_static", "regex", "unicode-width", ] +[[package]] +name = "termcolor" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" +dependencies = [ + "winapi-util", +] + [[package]] name = "terminal_size" -version = "0.3.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21bebf2b7c9e0a515f6e0f8c51dc0f8e4696391e6f1ff30379559f8365fb0df7" +checksum = "4f599bd7ca042cfdf8f4512b277c02ba102247820f9d9d4a9f521f496751a6ef" dependencies = [ "rustix", - "windows-sys 0.48.0", + "windows-sys 0.59.0", ] [[package]] @@ -6971,7 +8071,19 @@ checksum = "c4648c7def6f2043b2568617b9f9b75eae88ca185dbc1f1fda30e95a85d49d7d" dependencies = [ "libc", "libredox 0.0.2", - "numtoa", + "numtoa 0.1.0", + "redox_termios", +] + +[[package]] +name = "termion" +version = "4.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7eaa98560e51a2cf4f0bb884d8b2098a9ea11ecf3b7078e9c68242c74cc923a7" +dependencies = [ + "libc", + "libredox 0.1.3", + "numtoa 0.2.4", "redox_termios", ] @@ -6981,20 +8093,24 @@ version = "0.0.0" dependencies = [ "anyhow", "bytes", - "clap 4.5.4", + "clap 4.5.20", "colored", + "duct", "filecheck", "forc", "forc-client", "forc-pkg", "forc-test", - "forc-tracing 0.60.0", + "forc-tracing 0.66.2", "fuel-vm", "futures", "gag", + "glob", "hex", - "miden", - "prettydiff 0.6.4", + "insta", + "libtest-mimic", + "normalize-path", + "prettydiff 0.7.0", "rand", "regex", "revm", @@ -7006,8 +8122,9 @@ dependencies = [ "sway-utils", "textwrap 0.16.1", "tokio", - "toml 0.7.8", + "toml 0.8.19", "tracing", + "vte 0.13.0", ] [[package]] @@ -7046,22 +8163,22 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.61" +version = "1.0.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c546c80d6be4bc6a00c0f01730c08df82eaa7a7a61f11d656526506112cc1709" +checksum = "d50af8abc119fb8bb6dbabcfa89656f46f84aa0ac7688088608076ad2b459a84" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.61" +version = "1.0.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533" +checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.65", + "syn 2.0.79", ] [[package]] @@ -7074,11 +8191,20 @@ dependencies = [ "once_cell", ] +[[package]] +name = "threadpool" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d050e60b33d41c19108b32cea32164033a9013fe3b46cbd4457559bfbf77afaa" +dependencies = [ + "num_cpus", +] + [[package]] name = "tikv-jemalloc-sys" -version = "0.5.4+5.3.0-patched" +version = "0.6.0+5.3.0-1-ge13ca993e8ccb9ba9847cc330696e02839f328f7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9402443cb8fd499b6f327e40565234ff34dbda27460c5b47db0db77443dd85d1" +checksum = "cd3c60906412afa9c2b5b5a48ca6a5abe5736aec9eb48ad05037a677e52e4e2d" dependencies = [ "cc", "libc", @@ -7086,9 +8212,9 @@ dependencies = [ [[package]] name = "tikv-jemallocator" -version = "0.5.4" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "965fe0c26be5c56c94e38ba547249074803efd52adfb66de62107d95aab3eaca" +checksum = "4cec5ff18518d81584f477e9bfdf957f5bb0979b0bac3af4ca30b5b3ae2d2865" dependencies = [ "libc", "tikv-jemalloc-sys", @@ -7136,7 +8262,7 @@ dependencies = [ "once_cell", "pbkdf2 0.11.0", "rand", - "rustc-hash", + "rustc-hash 1.1.0", "sha2 0.10.8", "thiserror", "unicode-normalization", @@ -7165,9 +8291,9 @@ dependencies = [ [[package]] name = "tinyvec" -version = "1.6.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" dependencies = [ "tinyvec_macros", ] @@ -7180,21 +8306,20 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.37.0" +version = "1.40.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" +checksum = "e2b070231665d27ad9ec9b8df639893f46727666c6767db40317fbe920a5d998" dependencies = [ "backtrace", "bytes", "libc", - "mio", - "num_cpus", - "parking_lot 0.12.2", + "mio 1.0.2", + "parking_lot 0.12.3", "pin-project-lite", "signal-hook-registry", "socket2", "tokio-macros", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -7209,13 +8334,13 @@ dependencies = [ [[package]] name = "tokio-macros" -version = "2.2.0" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" +checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" dependencies = [ "proc-macro2", "quote", - "syn 2.0.65", + "syn 2.0.79", ] [[package]] @@ -7230,30 +8355,30 @@ dependencies = [ [[package]] name = "tokio-rustls" -version = "0.22.0" +version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc6844de72e57df1980054b38be3a9f4702aba4858be64dd700181a8a6d0e1b6" +checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" dependencies = [ - "rustls 0.19.1", + "rustls 0.21.12", "tokio", - "webpki", ] [[package]] name = "tokio-rustls" -version = "0.24.1" +version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" +checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" dependencies = [ - "rustls 0.21.12", + "rustls 0.23.15", + "rustls-pki-types", "tokio", ] [[package]] name = "tokio-stream" -version = "0.1.15" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af" +checksum = "4f4e6ce100d0eb49a2734f8c0812bcd324cf357d21810932c5df6b96ef2b86f1" dependencies = [ "futures-core", "pin-project-lite", @@ -7262,9 +8387,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.11" +version = "0.7.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cf6b47b3771c49ac75ad09a6162f53ad4b8088b76ac60e8ec1455b31a189fe1" +checksum = "61e7c3654c13bcd040d4a03abee2c75b1d14a37b423cf5a813ceae1cc903ec6a" dependencies = [ "bytes", "futures-core", @@ -7284,49 +8409,38 @@ dependencies = [ [[package]] name = "toml" -version = "0.7.8" +version = "0.8.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd79e69d3b627db300ff956027cc6c3798cef26d22526befdfcd12feeb6d2257" +checksum = "a1ed1f98e3fdc28d6d910e6737ae6ab1a93bf1985935a1193e68f93eeb68d24e" dependencies = [ "serde", "serde_spanned", "toml_datetime", - "toml_edit 0.19.15", + "toml_edit", ] [[package]] name = "toml_datetime" -version = "0.6.6" +version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4badfd56924ae69bcc9039335b2e017639ce3f9b001c393c1b2d1ef846ce2cbf" +checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" dependencies = [ "serde", ] [[package]] name = "toml_edit" -version = "0.19.15" +version = "0.22.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" +checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5" dependencies = [ - "indexmap 2.2.6", + "indexmap 2.6.0", "serde", "serde_spanned", "toml_datetime", "winnow", ] -[[package]] -name = "toml_edit" -version = "0.21.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1" -dependencies = [ - "indexmap 2.2.6", - "toml_datetime", - "winnow", -] - [[package]] name = "topological-sort" version = "0.2.2" @@ -7343,36 +8457,29 @@ dependencies = [ "futures-util", "pin-project", "pin-project-lite", - "tokio", "tower-layer", "tower-service", - "tracing", ] [[package]] -name = "tower-http" -version = "0.3.5" +name = "tower" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f873044bf02dd1e8239e9c1293ea39dad76dc594ec16185d0a1bf31d8dc8d858" +checksum = "2873938d487c3cfb9aed7546dc9f2711d867c9f90c46b889989a2cb84eba6b4f" dependencies = [ - "bitflags 1.3.2", - "bytes", "futures-core", "futures-util", - "http", - "http-body", - "http-range-header", "pin-project-lite", - "tower", + "sync_wrapper 0.1.2", "tower-layer", "tower-service", ] [[package]] name = "tower-layer" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" +checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" [[package]] name = "tower-lsp" @@ -7383,7 +8490,7 @@ dependencies = [ "async-trait", "auto_impl", "bytes", - "dashmap", + "dashmap 5.5.3", "futures", "httparse", "lsp-types", @@ -7392,7 +8499,7 @@ dependencies = [ "serde_json", "tokio", "tokio-util", - "tower", + "tower 0.4.13", "tower-lsp-macros", "tracing", ] @@ -7405,14 +8512,14 @@ checksum = "84fd902d4e0b9a4b27f2f440108dc034e1758628a9b702f8ec61ad66355422fa" dependencies = [ "proc-macro2", "quote", - "syn 2.0.65", + "syn 2.0.79", ] [[package]] name = "tower-service" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" [[package]] name = "tracing" @@ -7420,7 +8527,6 @@ version = "0.1.40" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" dependencies = [ - "log", "pin-project-lite", "tracing-attributes", "tracing-core", @@ -7434,7 +8540,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.65", + "syn 2.0.79", ] [[package]] @@ -7489,6 +8595,27 @@ dependencies = [ "tracing-serde", ] +[[package]] +name = "tracing-test" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "557b891436fe0d5e0e363427fc7f217abf9ccd510d5136549847bdcbcd011d68" +dependencies = [ + "tracing-core", + "tracing-subscriber", + "tracing-test-macro", +] + +[[package]] +name = "tracing-test-macro" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04659ddb06c87d233c566112c1c9c5b9e98256d9af50ec3bc9c8327f873a7568" +dependencies = [ + "quote", + "syn 2.0.79", +] + [[package]] name = "try-lock" version = "0.2.5" @@ -7530,9 +8657,9 @@ checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" [[package]] name = "ucd-trie" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed646292ffc8188ef8ea4d1e0e0150fb15a5c2e12ad9b8fc191ae7a8a7f3c4b9" +checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971" [[package]] name = "uint" @@ -7546,6 +8673,12 @@ dependencies = [ "static_assertions", ] +[[package]] +name = "unarray" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" + [[package]] name = "unicase" version = "2.7.0" @@ -7557,15 +8690,15 @@ dependencies = [ [[package]] name = "unicode-bidi" -version = "0.3.15" +version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" +checksum = "5ab17db44d7388991a428b2ee655ce0c212e862eff1768a455c58f9aad6e7893" [[package]] name = "unicode-ident" -version = "1.0.12" +version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" [[package]] name = "unicode-linebreak" @@ -7575,30 +8708,30 @@ checksum = "3b09c83c3c29d37506a3e260c08c03743a6bb66a9cd432c6934ab501a190571f" [[package]] name = "unicode-normalization" -version = "0.1.23" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" +checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956" dependencies = [ "tinyvec", ] [[package]] name = "unicode-segmentation" -version = "1.11.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" +checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" [[package]] name = "unicode-width" -version = "0.1.12" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68f5e5f3158ecfd4b8ff6fe086db7c8467a2dfdac97fe420f2b7c4aa97af66d6" +checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" [[package]] name = "unicode-xid" -version = "0.2.4" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" [[package]] name = "unicode_categories" @@ -7628,10 +8761,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6889a77d49f1f013504cec6bf97a2c730394adedaeb1deb5ea08949a50541105" [[package]] -name = "untrusted" -version = "0.7.1" +name = "unsigned-varint" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" +checksum = "eb066959b24b5196ae73cb057f45598450d2c5f71460e98c49b738086eff9c06" [[package]] name = "untrusted" @@ -7641,9 +8774,9 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "url" -version = "2.5.0" +version = "2.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" +checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" dependencies = [ "form_urlencoded", "idna 0.5.0", @@ -7657,11 +8790,17 @@ version = "2.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da" +[[package]] +name = "utf8-width" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86bd8d4e895da8537e5315b8254664e6b769c4ff3db18321b297a1e7004392e3" + [[package]] name = "utf8parse" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "uuid" @@ -7669,10 +8808,16 @@ version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7" dependencies = [ - "getrandom 0.2.15", + "getrandom", "serde", ] +[[package]] +name = "uuid" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8c5f0a0af699448548ad1a2fbf920fb4bee257eae39953ba95cb84891a0446a" + [[package]] name = "uwuify" version = "0.2.2" @@ -7680,7 +8825,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3db6840b7adcfd2e866c79157cc890ecdbbc1f739607134039ae64eaa6c07e24" dependencies = [ "clap 2.34.0", - "owo-colors", + "owo-colors 1.3.0", "parking_lot 0.11.2", "thiserror", ] @@ -7699,9 +8844,9 @@ checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" [[package]] name = "vec1" -version = "1.12.0" +version = "1.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffb60dcfffc189bfd4e2a81333c268619fee9db53da71bce2bcbd8e129c56936" +checksum = "eab68b56840f69efb0fefbe3ab6661499217ffdc58e2eef7c3f6f69835386322" [[package]] name = "vec_map" @@ -7711,9 +8856,9 @@ checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" [[package]] name = "version_check" -version = "0.9.4" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" [[package]] name = "void" @@ -7721,6 +8866,12 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" +[[package]] +name = "vsimd" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c3082ca00d5a5ef149bb8b555a72ae84c9c59f7250f013ac822ac2e49b19c64" + [[package]] name = "vt100" version = "0.15.2" @@ -7730,7 +8881,7 @@ dependencies = [ "itoa", "log", "unicode-width", - "vte", + "vte 0.11.1", ] [[package]] @@ -7739,21 +8890,41 @@ version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f5022b5fbf9407086c180e9557be968742d839e68346af7792b8592489732197" dependencies = [ - "arrayvec 0.7.4", + "arrayvec", + "utf8parse", + "vte_generate_state_changes", +] + +[[package]] +name = "vte" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40eb22ae96f050e0c0d6f7ce43feeae26c348fc4dea56928ca81537cfaa6188b" +dependencies = [ + "arrayvec", "utf8parse", "vte_generate_state_changes", ] [[package]] name = "vte_generate_state_changes" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d257817081c7dffcdbab24b9e62d2def62e2ff7d00b1c20062551e6cccc145ff" +checksum = "2e369bee1b05d510a7b4ed645f5faa90619e05437111783ea5848f28d97d3c2e" dependencies = [ "proc-macro2", "quote", ] +[[package]] +name = "wait-timeout" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f200f5b12eb75f8c1ed65abd4b2db8a6e1b138a20de009dacee265a2498f3f6" +dependencies = [ + "libc", +] + [[package]] name = "walkdir" version = "2.5.0" @@ -7773,12 +8944,6 @@ dependencies = [ "try-lock", ] -[[package]] -name = "wasi" -version = "0.9.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" - [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" @@ -7793,36 +8958,35 @@ checksum = "b8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855b" [[package]] name = "wasm-bindgen" -version = "0.2.92" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" +checksum = "128d1e363af62632b8eb57219c8fd7877144af57558fb2ef0368d0087bddeb2e" dependencies = [ "cfg-if 1.0.0", - "serde", - "serde_json", + "once_cell", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.92" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" +checksum = "cb6dd4d3ca0ddffd1dd1c9c04f94b868c37ff5fac97c30b97cff2d74fce3a358" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn 2.0.65", + "syn 2.0.79", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.42" +version = "0.4.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76bc14366121efc8dbb487ab05bcc9d346b3b5ec0eaa76e46594cabbe51762c0" +checksum = "cc7ec4f8827a71586374db3e87abdb5a2bb3a15afed140221307c3ec06b1f63b" dependencies = [ "cfg-if 1.0.0", "js-sys", @@ -7832,9 +8996,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.92" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" +checksum = "e79384be7f8f5a9dd5d7167216f022090cf1f9ec128e6e6a482a2cb5c5422c56" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -7842,43 +9006,33 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.92" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" +checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68" dependencies = [ "proc-macro2", "quote", - "syn 2.0.65", + "syn 2.0.79", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.92" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" +checksum = "65fc09f10666a9f147042251e0dda9c18f166ff7de300607007e96bdebc1068d" [[package]] name = "web-sys" -version = "0.3.69" +version = "0.3.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77afa9a11836342370f4817622a2f0f418b134426d91a82dfb48f532d2ec13ef" +checksum = "f6488b90108c040df0fe62fa815cbdee25124641df01814dd7282749234c6112" dependencies = [ "js-sys", "wasm-bindgen", ] -[[package]] -name = "webpki" -version = "0.21.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8e38c0608262c46d4a56202ebabdeb094cef7e560ca7a226c6bf055188aa4ea" -dependencies = [ - "ring 0.16.20", - "untrusted 0.7.1", -] - [[package]] name = "webpki-roots" version = "0.25.4" @@ -7887,9 +9041,9 @@ checksum = "5f20c57d8d7db6d3b86154206ae5d8fba62dd39573114de97c2cb0578251f8e1" [[package]] name = "which" -version = "6.0.1" +version = "6.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8211e4f58a2b2805adfbefbc07bab82958fc91e3836339b1ab7ae32465dce0d7" +checksum = "b4ee928febd44d98f2f459a4a79bd4d928591333a494a10a868418ac1b39cf1f" dependencies = [ "either", "home", @@ -7899,11 +9053,11 @@ dependencies = [ [[package]] name = "whoami" -version = "1.5.1" +version = "1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a44ab49fad634e88f55bf8f9bb3abd2f27d7204172a112c7c9987e01c1c94ea9" +checksum = "372d5b87f58ec45c384ba03563b03544dc5fadc3983e434b286913f5b4a9bb6d" dependencies = [ - "redox_syscall 0.4.1", + "redox_syscall 0.5.7", "wasite", "web-sys", ] @@ -7926,11 +9080,11 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" -version = "0.1.8" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d4cc384e1e73b93bafa6fb4f1df8c41695c8a91cf9c4c64358067d15a7b6c6b" +checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -7945,16 +9099,37 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" dependencies = [ - "windows-targets 0.52.5", + "windows-targets 0.52.6", ] [[package]] -name = "windows-sys" -version = "0.45.0" +name = "windows-registry" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e400001bb720a623c1c69032f8e3e4cf09984deec740f007dd2b03ec864804b0" +dependencies = [ + "windows-result", + "windows-strings", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-result" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-strings" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10" dependencies = [ - "windows-targets 0.42.2", + "windows-result", + "windows-targets 0.52.6", ] [[package]] @@ -7972,22 +9147,16 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.5", + "windows-targets 0.52.6", ] [[package]] -name = "windows-targets" -version = "0.42.2" +name = "windows-sys" +version = "0.59.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" dependencies = [ - "windows_aarch64_gnullvm 0.42.2", - "windows_aarch64_msvc 0.42.2", - "windows_i686_gnu 0.42.2", - "windows_i686_msvc 0.42.2", - "windows_x86_64_gnu 0.42.2", - "windows_x86_64_gnullvm 0.42.2", - "windows_x86_64_msvc 0.42.2", + "windows-targets 0.52.6", ] [[package]] @@ -8007,26 +9176,20 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm 0.52.5", - "windows_aarch64_msvc 0.52.5", - "windows_i686_gnu 0.52.5", + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", "windows_i686_gnullvm", - "windows_i686_msvc 0.52.5", - "windows_x86_64_gnu 0.52.5", - "windows_x86_64_gnullvm 0.52.5", - "windows_x86_64_msvc 0.52.5", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", ] -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" - [[package]] name = "windows_aarch64_gnullvm" version = "0.48.5" @@ -8035,15 +9198,9 @@ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_gnullvm" -version = "0.52.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.42.2" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] name = "windows_aarch64_msvc" @@ -8053,15 +9210,9 @@ checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_aarch64_msvc" -version = "0.52.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" - -[[package]] -name = "windows_i686_gnu" -version = "0.42.2" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_i686_gnu" @@ -8071,21 +9222,15 @@ checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_gnu" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" [[package]] name = "windows_i686_gnullvm" -version = "0.52.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" - -[[package]] -name = "windows_i686_msvc" -version = "0.42.2" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] name = "windows_i686_msvc" @@ -8095,15 +9240,9 @@ checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_i686_msvc" -version = "0.52.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.42.2" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_x86_64_gnu" @@ -8113,15 +9252,9 @@ checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnu" -version = "0.52.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.42.2" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] name = "windows_x86_64_gnullvm" @@ -8131,15 +9264,9 @@ checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_gnullvm" -version = "0.52.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.42.2" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] name = "windows_x86_64_msvc" @@ -8149,15 +9276,15 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "windows_x86_64_msvc" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winnow" -version = "0.5.40" +version = "0.6.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" +checksum = "36c1fec1a2bb5866f07c25f68c26e565c4c200aebb96d7e55710c19d3e8ac49b" dependencies = [ "memchr", ] @@ -8178,83 +9305,6 @@ version = "0.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d135d17ab770252ad95e9a872d365cf3090e3be864a34ab46f48555993efc904" -[[package]] -name = "winter-air" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef91b335c5fefa4e6d3c6274de75a7744b4eecae2d7ee3778c23570f35f83396" -dependencies = [ - "winter-crypto", - "winter-fri", - "winter-math", - "winter-utils", -] - -[[package]] -name = "winter-crypto" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3bd17ea728ff42185c54dfbabaafd0b442207df6b2cc60f74c607d8c01e9c4db" -dependencies = [ - "blake3", - "sha3", - "winter-math", - "winter-utils", -] - -[[package]] -name = "winter-fri" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2473f8b2c5c553e9f9d4d94b3b7a1e75806b4cdc964004f9bde4b5fc07c10c87" -dependencies = [ - "winter-crypto", - "winter-math", - "winter-utils", -] - -[[package]] -name = "winter-math" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "824b459961e5d679a1eb62ec1a71c85ac25c5d3bfd126874fcd32b591202d896" -dependencies = [ - "winter-utils", -] - -[[package]] -name = "winter-prover" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3831583fd662f49f23ea39427aba20a9b5ab6326230f7994e843d2bd34524411" -dependencies = [ - "log", - "winter-air", - "winter-crypto", - "winter-fri", - "winter-math", - "winter-utils", -] - -[[package]] -name = "winter-utils" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f0dbf7ca6aa5893b59928718bf1e7dbe7279bb277b5aa4c4898ddf5004f9417" - -[[package]] -name = "winter-verifier" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "922be4651b76aa80e132386a97d23788e2bc542d37b3c187a39998876a8094b6" -dependencies = [ - "winter-air", - "winter-crypto", - "winter-fri", - "winter-math", - "winter-utils", -] - [[package]] name = "wyz" version = "0.5.1" @@ -8281,6 +9331,12 @@ version = "2.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "213b7324336b53d2414b2db8537e56544d981803139155afa84f76eeebb7a546" +[[package]] +name = "xmlparser" +version = "0.13.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "66fee0b777b0f5ac1c69bb06d361268faafa61cd4682ae064a171c16c433e9e4" + [[package]] name = "yaml-rust" version = "0.4.5" @@ -8296,31 +9352,38 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec" +[[package]] +name = "yansi" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049" + [[package]] name = "zerocopy" -version = "0.7.34" +version = "0.7.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae87e3fcd617500e5d106f0380cf7b77f3c6092aae37191433159dda23cfb087" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" dependencies = [ + "byteorder", "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.7.34" +version = "0.7.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15e934569e47891f7d9411f1a451d947a60e000ab3bd24fbb970f000387d1b3b" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.65", + "syn 2.0.79", ] [[package]] name = "zeroize" -version = "1.7.0" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" dependencies = [ "zeroize_derive", ] @@ -8333,5 +9396,5 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.65", + "syn 2.0.79", ] diff --git a/Cargo.toml b/Cargo.toml index ae06a4828c1..760055fc845 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,38 +26,208 @@ members = [ "swayfmt", "test", ] -exclude = [ - "examples/*", - "swayfmt/test_macros", - "forc-test/test_data" -] +exclude = ["examples/*", "swayfmt/test_macros", "forc-test/test_data"] + +[workspace.package] +edition = "2021" +version = "0.66.2" +authors = ["Fuel Labs "] +homepage = "https://fuel.network/" +license = "Apache-2.0" +repository = "https://github.com/FuelLabs/sway" [workspace.dependencies] -# Dependencies from the `fuel-core` repository: -fuel-core-client = { version = "0.27.0", default-features = false } -fuel-core-types = { version = "0.27.0", default-features = false } +# +# Internal dependencies in order to propagate `workspace.version` +# -# Dependencies from the `fuel-vm` repository: -fuel-asm = "0.50.0" -fuel-crypto = "0.50.0" -fuel-types = "0.50.0" -fuel-tx = "0.50.0" -fuel-vm = "0.50.0" +forc = { path = "forc/", version = "0.66.2" } +forc-pkg = { path = "forc-pkg/", version = "0.66.2" } +forc-test = { path = "forc-test/", version = "0.66.2" } +forc-tracing = { path = "forc-tracing/", version = "0.66.2" } +forc-util = { path = "forc-util/", version = "0.66.2" } -# Dependencies from the `fuels-rs` repository: -fuels-core = "0.63.0" -fuels-accounts = "0.63.0" +# Forc plugins +forc-plugins = { path = "forc-plugins/", version = "0.66.2" } +forc-client = { path = "forc-plugins/forc-client/", version = "0.66.2" } +forc-crypto = { path = "forc-plugins/forc-crypto/", version = "0.66.2" } +forc-debug = { path = "forc-plugins/forc-debug/", version = "0.66.2" } +forc-doc = { path = "forc-plugins/forc-doc/", version = "0.66.2" } +forc-fmt = { path = "forc-plugins/forc-fmt/", version = "0.66.2" } +forc-lsp = { path = "forc-plugins/forc-lsp/", version = "0.66.2" } +forc-tx = { path = "forc-plugins/forc-tx/", version = "0.66.2" } -# Dependencies from the `forc-wallet` repository: -forc-wallet = "0.8.0" +sway-ast = { path = "sway-ast/", version = "0.66.2" } +sway-core = { path = "sway-core/", version = "0.66.2" } +sway-error = { path = "sway-error/", version = "0.66.2" } +sway-lsp = { path = "sway-lsp/", version = "0.66.2" } +sway-parse = { path = "sway-parse/", version = "0.66.2" } +sway-types = { path = "sway-types/", version = "0.66.2" } +sway-utils = { path = "sway-utils/", version = "0.66.2" } +swayfmt = { path = "swayfmt/", version = "0.66.2" } + +# Sway IR +sway-ir = { path = "sway-ir/", version = "0.66.2" } +sway-ir-macros = { path = "sway-ir/sway-ir-macros", version = "0.66.2" } + +# +# External Fuel dependencies +# # Dependencies from the `fuel-abi-types` repository: -fuel-abi-types = "0.5.0" +fuel-abi-types = "0.7" -[workspace.package] -edition = "2021" -authors = ["Fuel Labs "] -homepage = "https://fuel.network/" -license = "Apache-2.0" -repository = "https://github.com/FuelLabs/sway" +# Dependencies from the `fuel-core` repository: +# +# Although ALL verions are "X.Y", we need the complete semver for +# fuel-core-client as the GitHub Actions workflow parses this value to pull down +# the correct tarball +fuel-core-client = { version = "0.40.0", default-features = false } +fuel-core-types = { version = "0.40", default-features = false } + +# Dependencies from the `fuels-rs` repository: + +fuels = "0.66.9" +fuels-core = "0.66.9" +fuels-accounts = "0.66.9" + +# Dependencies from the `fuel-vm` repository: +fuel-asm = "0.58" +fuel-crypto = "0.58" +fuel-types = "0.58" +fuel-tx = "0.58" +fuel-vm = "0.58" + +# Dependencies from the `forc-wallet` repository: +forc-wallet = "0.11" + +# +# External dependencies +# +annotate-snippets = "0.10" +ansi_term = "0.12" +anyhow = "1.0" +assert-json-diff = "2.0" +async-trait = "0.1" +atty = "0.2" +aws-config = "1.5" +aws-sdk-kms = "1.44" +byte-unit = "5.1" +bytecount = "0.6" +bytes = "1.7" +chrono = { version = "0.4", default-features = false } +cid = "0.11" +clap = "4.5" +clap_complete = "4.5" +clap_complete_fig = "4.5" +colored = "2.0" +comrak = "0.28" +crossbeam-channel = "0.5" +dap = "0.4.1-alpha" +dashmap = "6.1" +derivative = "2.2" +devault = "0.2" +dialoguer = "0.11" +dirs = "5.0" +downcast-rs = "1.2" +either = "1.9" +ethabi = { package = "fuel-ethabi", version = "18.0" } +etk-asm = { package = "fuel-etk-asm", version = "0.3.1-dev" } +etk-ops = { package = "fuel-etk-ops", version = "0.3.1-dev" } +extension-trait = "1.0" +fd-lock = "4.0" +filecheck = "0.5" +fs_extra = "1.2" +futures = { version = "0.3", default-features = false } +gag = "1.0" +gimli = "0.31" +git2 = "0.19" +gix-url = "0.27" +glob = "0.3" +graph-cycles = "0.1" +hashbrown = "0.14" +hex = "0.4" +horrorshow = "0.8" +im = "15.0" +in_definite = "1.0" +include_dir = "0.7" +indexmap = "2.5" +indoc = "2.0" +insta = "1.40" +ipfs-api-backend-hyper = "0.6" +itertools = "0.13" +k256 = "0.13" +lazy_static = "1.4" +libp2p-identity = "0.2" +libtest-mimic = "0.7" +lsp-types = "0.94" +mdbook = { version = "0.4", default-features = false } +minifier = "0.3" +notify = "6.1" +notify-debouncer-mini = "0.4" +num-bigint = "0.4" +num-traits = "0.2" +object = "0.36" +once_cell = "1.18" +opener = "0.7" +parking_lot = "0.12" +paste = "1.0" +peg = "0.8" +pest = "2.7" +pest_derive = "2.7" +petgraph = "0.6" +phf = "0.11" +pretty_assertions = "1.4" +prettydiff = "0.7" +proc-macro2 = "1.0" +quote = "1.0" +rand = "0.8" +rayon = "1.7" +rayon-cond = "0.3" +regex = "1.10" +reqwest = "0.12" +revm = "14.0" +ropey = "1.5" +rpassword = "7.2" +rustc-hash = "1.1" +semver = "1.0" +serde = "1.0" +serde_ignored = "0.1" +serde_json = "1.0" +serde_with = "3.3" +serde_yaml = "0.9" +serial_test = "3.0" +sha2 = "0.10" +sha3 = "0.10" +shellfish = "0.9" +slotmap = "1.0" +smallvec = "1.7" +strsim = "0.11" +strum = "0.26" +syn = "2.0" +taplo = "0.13" +tar = "0.4" +tempfile = "3" +term-table = "1.3" +termion = "4.0" +textwrap = "0.16" +thiserror = "1.0" +tikv-jemallocator = "0.6" +tokio = "1.12" +toml = "0.8" +toml_edit = "0.22" +tower = { version = "0.5", default-features = false } +tower-lsp = "0.20" +tracing = "0.1" +tracing-subscriber = "0.3" +uint = "0.9" +unicode-bidi = "0.3" +unicode-xid = "0.2" +url = "2.2" +urlencoding = "2.1" +uwuify = "^0.2" +vec1 = "1.8" +vte = "0.13" +walkdir = "2.3" +whoami = "1.5" diff --git a/README.md b/README.md index 14eb838f01f..737fb61ebc7 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ [![docs](https://docs.rs/forc/badge.svg)](https://docs.rs/forc/) [![discord](https://img.shields.io/badge/chat%20on-discord-orange?&logo=discord&logoColor=ffffff&color=7389D8&labelColor=6A7EC2)](https://discord.gg/xfpK4Pe) -Sway is a language developed for the Fuel blockchain. It is heavily inspired by Rust and aims to bring modern language development and performance to the blockchain ecosystem. +Sway is a language developed for the [Fuel](https://docs.fuel.network/docs/intro/what-is-fuel/) blockchain. It is heavily inspired by Rust and aims to bring modern language development and performance to the blockchain ecosystem. ## Documentation diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 00000000000..dab1c5c4c2c --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,31 @@ +# Fuel Security Policy + +Thank you for helping make the Fuel ecosystem safe for everyone. The Fuel team take security bugs very seriously. We appreciate your efforts to responsibly disclose your findings, and will make every effort to acknowledge your contributions. + +## Reporting Security Issues + +If you believe you have found a security vulnerability in any Fuel-owned repository, please report it to us through coordinated disclosure. + +**Please do not report security vulnerabilities through public GitHub issues, discussions, or pull requests.** + +Instead, please use the GitHub Security Advisory ["Report a Vulnerability"](https://github.com/FuelLabs/sway/security/advisories/new) tab. + +The Fuel team will send a response indicating the next steps in handling your report. After the initial reply to your report, the team will keep you informed of the progress towards a fix and full announcement, and may ask for additional information or guidance. + +Please include as much of the information listed below as you can to help us better understand and resolve the issue: + +* The type of issue (e.g., buffer overflow, SQL injection, or cross-site scripting) +* Full paths of source file(s) related to the manifestation of the issue +* The location of the affected source code (tag/branch/commit or direct URL) +* Any special configuration required to reproduce the issue +* Step-by-step instructions to reproduce the issue +* Proof-of-concept or exploit code (if possible) +* Impact of the issue, including how an attacker might exploit the issue + +This information will help us triage your report more quickly. + +Report security bugs in third-party modules to the person or team maintaining the module. + +## Non-Security Issues + +If the issue is not security-related, please report it publicly by opening a [GitHub Issue](https://github.com/FuelLabs/sway/issues/new). diff --git a/deployment/Dockerfile b/deployment/Dockerfile index a9b865856af..10868781760 100644 --- a/deployment/Dockerfile +++ b/deployment/Dockerfile @@ -1,5 +1,5 @@ # Stage 1: Build -FROM lukemathwalker/cargo-chef:latest-rust-1.76 as chef +FROM lukemathwalker/cargo-chef:latest-rust-1.79 as chef WORKDIR /build/ # hadolint ignore=DL3008 RUN apt-get update && \ diff --git a/docs/book/spell-check-custom-words.txt b/docs/book/spell-check-custom-words.txt index 818c9a71b02..6e18232eaf0 100644 --- a/docs/book/spell-check-custom-words.txt +++ b/docs/book/spell-check-custom-words.txt @@ -4,6 +4,7 @@ ASM IDE IDEs LSP +lsp namespace ALU APIs @@ -210,4 +211,20 @@ namespacing unsafety prioritizations polymorphism -ContractId \ No newline at end of file +ContractId +booleans +underflows +Codec +bool +str +multisig +addr +addr2line +contract-id +init +parse-bytecode +predicate-root +forc-client +crypto +doc +fmt \ No newline at end of file diff --git a/docs/book/src/SUMMARY.md b/docs/book/src/SUMMARY.md index 78f0164d676..262437ea2cc 100644 --- a/docs/book/src/SUMMARY.md +++ b/docs/book/src/SUMMARY.md @@ -7,6 +7,7 @@ - [The Fuel Toolchain](./introduction/fuel_toolchain.md) - [A Forc Project](./introduction/forc_project.md) - [Standard Library](./introduction/standard_library.md) + - [Core Library](./introduction/core_library.md) - [Sway Language Standards](./introduction/sway_standards.md) - [Examples](./examples/index.md) - [Counter](./examples/counter.md) @@ -69,6 +70,7 @@ - [Attributes](./reference/attributes.md) - [Style Guide](./reference/style_guide.md) - [Known Issues and Workarounds](./reference/known_issues_and_workarounds.md) + - [Behavior Considered Undefined](./reference/undefined_behavior.md) - [Differences From Solidity](./reference/solidity_differences.md) - [Differences From Rust](./reference/rust_differences.md) - [Contributing To Sway](./reference/contributing_to_sway.md) @@ -78,28 +80,28 @@ - [Workspaces](./forc/workspaces.md) - [Dependencies](./forc/dependencies.md) - [Commands](./forc/commands/index.md) - - [`forc addr2line`](./forc/commands/forc_addr2line.md) - - [`forc build`](./forc/commands/forc_build.md) - - [`forc check`](./forc/commands/forc_check.md) - - [`forc clean`](./forc/commands/forc_clean.md) - - [`forc completions`](./forc/commands/forc_completions.md) - - [`forc contract-id`](./forc/commands/forc_contract-id.md) - - [`forc init`](./forc/commands/forc_init.md) - - [`forc new`](./forc/commands/forc_new.md) - - [`forc parse-bytecode`](./forc/commands/forc_parse-bytecode.md) - - [`forc plugins`](./forc/commands/forc_plugins.md) - - [`forc predicate-root`](./forc/commands/forc_predicate-root.md) - - [`forc test`](./forc/commands/forc_test.md) - - [`forc update`](./forc/commands/forc_update.md) - - [`forc template`](./forc/commands/forc_template.md) + - [forc addr2line](./forc/commands/forc_addr2line.md) + - [forc build](./forc/commands/forc_build.md) + - [forc check](./forc/commands/forc_check.md) + - [forc clean](./forc/commands/forc_clean.md) + - [forc completions](./forc/commands/forc_completions.md) + - [forc contract-id](./forc/commands/forc_contract-id.md) + - [forc init](./forc/commands/forc_init.md) + - [forc new](./forc/commands/forc_new.md) + - [forc parse-bytecode](./forc/commands/forc_parse-bytecode.md) + - [forc plugins](./forc/commands/forc_plugins.md) + - [forc predicate-root](./forc/commands/forc_predicate-root.md) + - [forc test](./forc/commands/forc_test.md) + - [forc update](./forc/commands/forc_update.md) + - [forc template](./forc/commands/forc_template.md) - [Plugins](./forc/plugins/index.md) - - [`forc client`](./forc/plugins/forc_client/index.md) - - [`forc deploy`](./forc/plugins/forc_client/forc_deploy.md) - - [`forc run`](./forc/plugins/forc_client/forc_run.md) - - [`forc submit`](./forc/plugins/forc_client/forc_submit.md) - - [`forc crypto`](./forc/plugins/forc_crypto.md) - - [`forc debug`](./forc/plugins/forc_debug.md) - - [`forc doc`](./forc/plugins/forc_doc.md) - - [`forc explore`](./forc/plugins/forc_explore.md) - - [`forc fmt`](./forc/plugins/forc_fmt.md) - - [`forc lsp`](./forc/plugins/forc_lsp.md) + - [forc client](./forc/plugins/forc_client/index.md) + - [forc deploy](./forc/plugins/forc_client/forc_deploy.md) + - [forc run](./forc/plugins/forc_client/forc_run.md) + - [forc submit](./forc/plugins/forc_client/forc_submit.md) + - [forc crypto](./forc/plugins/forc_crypto.md) + - [forc debug](./forc/plugins/forc_debug.md) + - [forc doc](./forc/plugins/forc_doc.md) + - [forc explore](./forc/plugins/forc_explore.md) + - [forc fmt](./forc/plugins/forc_fmt.md) + - [forc lsp](./forc/plugins/forc_lsp.md) diff --git a/docs/book/src/advanced/assembly.md b/docs/book/src/advanced/assembly.md index 3bad77ecab6..31d323f5a4d 100644 --- a/docs/book/src/advanced/assembly.md +++ b/docs/book/src/advanced/assembly.md @@ -1,6 +1,6 @@ # Inline Assembly in Sway -While many users will never have to touch assembly language while writing sway code, it is a powerful tool that enables many advanced use-cases (e.g., optimizations, building libraries, etc). +While many users will never have to touch assembly language while writing Sway code, it is a powerful tool that enables many advanced use-cases (e.g., optimizations, building libraries, etc). ## ASM Block @@ -11,7 +11,7 @@ asm() {...} ``` Declaring an `asm` block is similar to declaring a function. -We can specify register names to operate on as arguments, we can perform operations within the block, and we can return a value. +We can specify register names to operate on as arguments, we can perform assembly instructions within the block, and we can return a value by specifying a return register. Here's an example showing what this might look like: ```sway @@ -23,7 +23,12 @@ pub fn add_1(num: u32) -> u32 { } ``` -An `asm` block can only return a single register. If you really need to return more than one value, you can modify a tuple. Here's an example showing how you can implement this `(u64, u64)`: +The return register is specified at the end of the `asm` block, after all the assembly instructions. It consists of the register name and an optional return type. In the above example, the return register name is `r2` and the return type is `u32`. +If the return type is omitted, it is `u64` by default. + +The return register itself is optional. If it is not specified, similar to functions, the returned value from the `asm` block will be [unit](../basics/built_in_types.md#unit-type), `()`. + +An `asm` block can only return a single register. If you really need to return more than one value, you can modify a tuple. Here's an example showing how you can implement this for `(u64, u64)`: ```sway {{#include ../../../../examples/asm_return_tuple_pointer/src/main.sw}} @@ -37,7 +42,7 @@ Note that in the above example: - we declared a second register `r2` (you may choose any register names you want). - we use the `add` opcode to add `one` to the value of `r1` and store it in `r2`. - `one` is an example of a "reserved register", of which there are 16 in total. Further reading on this is linked below under "Semantics". -- we return `r2` & specify the return type as being u32 (the return type is u64 by default). +- we return `r2` and specify the return type as being `u32`. An important note is that the `ji` and `jnei` opcodes are not available within an `asm` block. For those looking to introduce control flow to `asm` blocks, it is recommended to surround smaller chunks of `asm` with control flow (`if`, `else`, and `while`). diff --git a/docs/book/src/basics/built_in_types.md b/docs/book/src/basics/built_in_types.md index ddfbb7b233b..e7798a803b0 100644 --- a/docs/book/src/basics/built_in_types.md +++ b/docs/book/src/basics/built_in_types.md @@ -13,6 +13,7 @@ Sway is a statically typed language. At compile time, the types of every value m Sway has the following primitive types: +1. `()` (unit type) 1. `u8` (8-bit unsigned integer) 1. `u16` (16-bit unsigned integer) 1. `u32` (32-bit unsigned integer) @@ -26,6 +27,25 @@ Sway has the following primitive types: All other types in Sway are built up of these primitive types, or references to these primitive types. You may notice that there are no signed integers—this is by design. In the blockchain domain that Sway occupies, floating-point values and negative numbers have smaller utility, so their implementation has been left up to libraries for specific use cases. +## Unit Type + +The unit type, `()`, is a type that allows only one value, and thus, represents a value with no information. It is used to indicate the absence of a meaningful value, or the result of a function that performs an action, but does not return any data. The value of the unit type, called simply unit, has the same symbol as the unit type, `()`. Unit type in Sway serves a similar purpose as `void` in imperative languages like C or Java. + +For example: + +```Sway +fn returns_unit() -> () { // Here, `()` represent the unit type. + () // Here, `()` represents the single unit value of the unit type. +} +``` + +In Sway, if the function return type is not specified, it is `()` by default. Thus, the above example is semantically same as the following: + +```Sway +fn returns_unit() { +} +``` + ## Numeric Types All of the unsigned integer types are numeric types. diff --git a/docs/book/src/blockchain-development/native_assets.md b/docs/book/src/blockchain-development/native_assets.md index 4cfc33fb029..7f1298326f9 100644 --- a/docs/book/src/blockchain-development/native_assets.md +++ b/docs/book/src/blockchain-development/native_assets.md @@ -199,9 +199,21 @@ It implements the [SRC-20; Native Asset](https://github.com/FuelLabs/sway-standa // ERC20 equivalent in Sway. contract; -use src3::SRC3; -use src5::{SRC5, State, AccessError}; -use src20::SRC20; +use standards::{ + src3::SRC3, + src5::{ + SRC5, + State, + AccessError, + }, + src20::{ + SetDecimalsEvent, + SetNameEvent, + SetSymbolEvent, + SRC20, + TotalSupplyEvent, + }, +}; use std::{ asset::{ burn, @@ -280,14 +292,21 @@ impl SRC5 for Contract { // Mint and Burn Standard impl SRC3 for Contract { #[storage(read, write)] - fn mint(recipient: Identity, sub_id: SubId, amount: u64) { - require(sub_id == DEFAULT_SUB_ID, "incorrect-sub-id"); + fn mint(recipient: Identity, sub_id: Option, amount: u64) { + require(sub_id.is_some() && sub_id.unwrap() == DEFAULT_SUB_ID, "incorrect-sub-id"); require_access_owner(); + let new_supply = storage.total_supply.read() + amount; storage .total_supply - .write(amount + storage.total_supply.read()); + .write(new_supply); mint_to(recipient, DEFAULT_SUB_ID, amount); + + TotalSupplyEvent::new( + AssetId::default(), + new_supply, + msg_sender().unwrap() + ).log(); } #[storage(read, write)] @@ -300,10 +319,17 @@ impl SRC3 for Contract { ); require_access_owner(); + let new_supply = storage.total_supply.read() - amount; storage .total_supply - .write(storage.total_supply.read() - amount); + .write(new_supply); burn(DEFAULT_SUB_ID, amount); + + TotalSupplyEvent::new( + AssetId::default(), + new_supply, + msg_sender().unwrap() + ).log(); } } @@ -327,6 +353,24 @@ fn require_access_owner() { AccessError::NotOwner, ); } + +abi EmitSRC20Events { + fn emit_src20_events(); +} + +impl EmitSRC20Events for Contract { + fn emit_src20_events() { + // Metadata that is stored as a configurable should only be emitted once. + let asset = AssetId::default(); + let sender = msg_sender().unwrap(); + let name = Some(String::from_ascii_str(from_str_array(NAME))); + let symbol = Some(String::from_ascii_str(from_str_array(SYMBOL))); + + SetNameEvent::new(asset, name, sender).log(); + SetSymbolEvent::new(asset, symbol, sender).log(); + SetDecimalsEvent::new(asset, DECIMALS, sender).log(); + } +} ``` ## Multi Native Asset Example @@ -339,9 +383,21 @@ It implements the [SRC-20; Native Asset](https://github.com/FuelLabs/sway-standa // ERC1155 equivalent in Sway. contract; -use src5::{SRC5, State, AccessError}; -use src20::SRC20; -use src3::SRC3; +use standards::{ + src5::{ + SRC5, + State, + AccessError + }, + src20::{ + SetDecimalsEvent, + SetNameEvent, + SetSymbolEvent, + SRC20, + TotalSupplyEvent, + } + src3::SRC3, +}; use std::{ asset::{ burn, @@ -397,28 +453,42 @@ impl SRC20 for Contract { // Mint and Burn Standard impl SRC3 for Contract { #[storage(read, write)] - fn mint(recipient: Identity, sub_id: SubId, amount: u64) { + fn mint(recipient: Identity, sub_id: Option, amount: u64) { + require(sub_id.is_some(), "Error: SubId is None"); require_access_owner(); - let asset_id = AssetId::new(contract_id(), sub_id); + + let asset_id = AssetId::new(ContractId::this(), sub_id.unwrap()); let supply = storage.total_supply.get(asset_id).try_read(); if supply.is_none() { storage.total_assets.write(storage.total_assets.try_read().unwrap_or(0) + 1); } - let current_supply = supply.unwrap_or(0); - storage.total_supply.insert(asset_id, current_supply + amount); + let new_supply = supply.unwrap_or(0) + amount; + storage.total_supply.insert(asset_id, new_supply); mint_to(recipient, sub_id, amount); + + TotalSupplyEvent::new( + asset_id, + new_supply, + msg_sender().unwrap() + ).log(); } #[storage(read, write)] fn burn(sub_id: SubId, amount: u64) { require_access_owner(); - let asset_id = AssetId::new(contract_id(), sub_id); + let asset_id = AssetId::new(ContractId::this(), sub_id); require(this_balance(asset_id) >= amount, "not-enough-coins"); let supply = storage.total_supply.get(asset_id).try_read(); - let current_supply = supply.unwrap_or(0); - storage.total_supply.insert(asset_id, current_supply - amount); + let new_supply = supply.unwrap_or(0) - amount; + storage.total_supply.insert(asset_id, new_supply); burn(sub_id, amount); + + TotalSupplyEvent::new( + asset_id, + new_supply, + msg_sender().unwrap() + ).log(); } } @@ -427,10 +497,10 @@ abi MultiAsset { fn constructor(owner_: Identity); #[storage(read, write)] - fn set_name(asset: AssetId, name: String); + fn set_name(asset: AssetId, name: Option); #[storage(read, write)] - fn set_symbol(asset: AssetId, symbol: String); + fn set_symbol(asset: AssetId, symbol: Option); #[storage(read, write)] fn set_decimals(asset: AssetId, decimals: u8); @@ -444,23 +514,29 @@ impl MultiAsset for Contract { } #[storage(read, write)] - fn set_name(asset: AssetId, name: String) { + fn set_name(asset: AssetId, name: Option) { require_access_owner(); storage.name.insert(asset, StorageString {}); storage.name.get(asset).write_slice(name); + + SetNameEvent::new(asset, name, msg_sender().unwrap()).log(); } #[storage(read, write)] - fn set_symbol(asset: AssetId, symbol: String) { + fn set_symbol(asset: AssetId, symbol: Option) { require_access_owner(); storage.symbol.insert(asset, StorageString {}); storage.symbol.get(asset).write_slice(symbol); + + SetSymbolEvent::new(asset, symbol, msg_sender().unwrap()).log(); } #[storage(read, write)] fn set_decimals(asset: AssetId, decimals: u8) { require_access_owner(); storage.decimals.insert(asset, decimals); + + SetDecimalsEvent::new(asset, decimals, msg_sender().unwrap()).log(); } } diff --git a/docs/book/src/blockchain-development/purity.md b/docs/book/src/blockchain-development/purity.md index b6ba55a54a8..35149ecfd74 100644 --- a/docs/book/src/blockchain-development/purity.md +++ b/docs/book/src/blockchain-development/purity.md @@ -5,6 +5,8 @@ A function is _pure_ if it does not access any [persistent storage](./storage.md). Conversely, the function is _impure_ if it does access any storage. Naturally, as storage is only available in smart contracts, impure functions cannot be used in predicates, scripts, or libraries. A pure function cannot call an impure function. In Sway, functions are pure by default but can be opted into impurity via the `storage` function attribute. The `storage` attribute may take `read` and/or `write` arguments indicating which type of access the function requires. + +The `storage` attribute without any arguments, `#[storage()]`, indicates a pure function, and has the same effect as not having the attribute at all. ```sway @@ -17,6 +19,15 @@ fn get_amount() -> u64 { fn increment_amount(increment: u64) -> u64 { ... } + +fn a_pure_function() { + ... +} + +#[storage()] +fn also_a_pure_function() { + ... +} ``` > **Note**: the `#[storage(write)]` attribute also permits a function to read from storage. This is due to the fact that partially writing a storage slot requires first reading the slot. @@ -31,6 +42,8 @@ The `storage` attribute may also be applied to [methods and associated functions A pure function gives you some guarantees: you will not incur excessive storage gas costs, the compiler can apply additional optimizations, and they are generally easy to reason about and audit. + +> **Note**: Purity does not provide an absolute guarantee that a storage access will not happen as a result of calling a pure function. E.g., it is possible for a pure function to call another contract, which can then call a write function in the original contract. The guarantee that the purity gives in this example is, that the original pure function itself does not change the storage, as well as that any function later called, that accesses storage, is clearly marked as impure. [A similar concept exists in Solidity](https://docs.soliditylang.org/en/v0.8.10/contracts.html#pure-functions). Note that Solidity refers to contract storage as _contract state_, and in the Sway/Fuel ecosystem, these two terms are largely interchangeable. diff --git a/docs/book/src/debugging/debugging_with_cli.md b/docs/book/src/debugging/debugging_with_cli.md index fd02bd5c2e2..740eb3e5bc3 100644 --- a/docs/book/src/debugging/debugging_with_cli.md +++ b/docs/book/src/debugging/debugging_with_cli.md @@ -83,46 +83,193 @@ Now we would like to inspect the program while it's running. To do this, we firs ```json { - "Script": { - "script_gas_limit": 1000000, - "script": [], - "script_data": [], - "policies": { - "bits": "GasPrice", - "values": [0,0,0,0] - }, - "inputs": [ - { - "CoinSigned": { - "utxo_id": { - "tx_id": "c49d65de61cf04588a764b557d25cc6c6b4bc0d7429227e2a21e61c213b3a3e2", - "output_index": 18 - }, - "owner": "f1e92c42b90934aa6372e30bc568a326f6e66a1a0288595e6e3fbd392a4f3e6e", - "amount": 10599410012256088338, - "asset_id": "2cafad611543e0265d89f1c2b60d9ebf5d56ad7e23d9827d6b522fd4d6e44bc3", - "tx_pointer": { - "block_height": 0, - "tx_index": 0 - }, - "witness_index": 0, - "maturity": 0, - "predicate_gas_used": null, - "predicate": null, - "predicate_data": null - } - } - ], - "outputs": [], - "witnesses": [ - { - "data": [ - 156,254,34,102,65,96,133,170,254,105,147,35,196,199,179,133,132,240,208,149,11,46,30,96,44,91,121,195,145,184,159,235,117,82,135,41,84,154,102,61,61,16,99,123,58,173,75,226,219,139,62,33,41,176,16,18,132,178,8,125,130,169,32,108 - ] - } - ], - "receipts_root": "0000000000000000000000000000000000000000000000000000000000000000" - } + "Script": { + "body": { + "script_gas_limit": 1000000, + "script": [ + 144, + 0, + 0, + 4, + 71, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 68, + 93, + 252, + 192, + 1, + 16, + 255, + 243, + 0, + 26, + 72, + 16, + 0, + 26, + 68, + 0, + 0, + 93, + 67, + 240, + 0, + 22, + 65, + 20, + 0, + 115, + 64, + 0, + 13, + 51, + 72, + 0, + 0, + 36, + 0, + 0, + 0, + 16, + 69, + 16, + 64, + 27, + 73, + 36, + 64, + 144, + 0, + 0, + 8, + 71, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 5 + ], + "script_data": [], + "receipts_root": "0000000000000000000000000000000000000000000000000000000000000000" + }, + "policies": { + "bits": "MaxFee", + "values": [ + 0, + 0, + 0, + 0 + ] + }, + "inputs": [ + { + "CoinSigned": { + "utxo_id": { + "tx_id": "c49d65de61cf04588a764b557d25cc6c6b4bc0d7429227e2a21e61c213b3a3e2", + "output_index": 18 + }, + "owner": "f1e92c42b90934aa6372e30bc568a326f6e66a1a0288595e6e3fbd392a4f3e6e", + "amount": 10599410012256088000, + "asset_id": "2cafad611543e0265d89f1c2b60d9ebf5d56ad7e23d9827d6b522fd4d6e44bc3", + "tx_pointer": { + "block_height": 0, + "tx_index": 0 + }, + "witness_index": 0, + "maturity": 0, + "predicate_gas_used": null, + "predicate": null, + "predicate_data": null + } + } + ], + "outputs": [], + "witnesses": [ + { + "data": [ + 156, + 254, + 34, + 102, + 65, + 96, + 133, + 170, + 254, + 105, + 147, + 35, + 196, + 199, + 179, + 133, + 132, + 240, + 208, + 149, + 11, + 46, + 30, + 96, + 44, + 91, + 121, + 195, + 145, + 184, + 159, + 235, + 117, + 82, + 135, + 41, + 84, + 154, + 102, + 61, + 61, + 16, + 99, + 123, + 58, + 173, + 75, + 226, + 219, + 139, + 62, + 33, + 41, + 176, + 16, + 18, + 132, + 178, + 8, + 125, + 130, + 169, + 32, + 108 + ] + } + ] + } } ``` diff --git a/docs/book/src/examples/counter.md b/docs/book/src/examples/counter.md index ef3079cc8bf..a9850f24742 100644 --- a/docs/book/src/examples/counter.md +++ b/docs/book/src/examples/counter.md @@ -9,3 +9,15 @@ forc template --template-name counter my_counter_project ```sway {{#include ../../../../examples/counter/src/main.sw}} ``` + +## Build and deploy + +The following commands can be used to build and deploy the contract. For a detailed tutorial, refer to [Building and Deploying](https://docs.fuel.network/guides/contract-quickstart/#building-the-contract). + +```bash +# Build the contract +forc build + +# Deploy the contract +forc deploy --testnet +``` diff --git a/docs/book/src/forc/commands/forc_addr2line.md b/docs/book/src/forc/commands/forc_addr2line.md index cd1835e1c49..9da1be10b3f 100644 --- a/docs/book/src/forc/commands/forc_addr2line.md +++ b/docs/book/src/forc/commands/forc_addr2line.md @@ -1 +1 @@ -# `forc addr2line` +# forc addr2line diff --git a/docs/book/src/forc/commands/forc_build.md b/docs/book/src/forc/commands/forc_build.md index 950396b5f28..f7285039bd7 100644 --- a/docs/book/src/forc/commands/forc_build.md +++ b/docs/book/src/forc/commands/forc_build.md @@ -1 +1 @@ -# `forc build` +# forc build diff --git a/docs/book/src/forc/commands/forc_check.md b/docs/book/src/forc/commands/forc_check.md index 88bd1757b61..49f24c6bc70 100644 --- a/docs/book/src/forc/commands/forc_check.md +++ b/docs/book/src/forc/commands/forc_check.md @@ -1 +1 @@ -# `forc check` +# forc check diff --git a/docs/book/src/forc/commands/forc_clean.md b/docs/book/src/forc/commands/forc_clean.md index 5ce65cb93c3..bbe1d3db337 100644 --- a/docs/book/src/forc/commands/forc_clean.md +++ b/docs/book/src/forc/commands/forc_clean.md @@ -1 +1 @@ -# `forc clean` +# forc clean diff --git a/docs/book/src/forc/commands/forc_completions.md b/docs/book/src/forc/commands/forc_completions.md index 309573d4870..91ae73c0015 100644 --- a/docs/book/src/forc/commands/forc_completions.md +++ b/docs/book/src/forc/commands/forc_completions.md @@ -1 +1 @@ -# `forc completions` +# forc completions diff --git a/docs/book/src/forc/commands/forc_contract-id.md b/docs/book/src/forc/commands/forc_contract-id.md index 81c0f140465..f6c47b041e2 100644 --- a/docs/book/src/forc/commands/forc_contract-id.md +++ b/docs/book/src/forc/commands/forc_contract-id.md @@ -1 +1 @@ -# `forc contract-id` +# forc contract-id diff --git a/docs/book/src/forc/commands/forc_init.md b/docs/book/src/forc/commands/forc_init.md index 0a5ba539d84..9931411557d 100644 --- a/docs/book/src/forc/commands/forc_init.md +++ b/docs/book/src/forc/commands/forc_init.md @@ -1 +1 @@ -# `forc init` +# forc init diff --git a/docs/book/src/forc/commands/forc_new.md b/docs/book/src/forc/commands/forc_new.md index 58fd660c119..0e6e939318c 100644 --- a/docs/book/src/forc/commands/forc_new.md +++ b/docs/book/src/forc/commands/forc_new.md @@ -1 +1 @@ -# `forc new` +# forc new diff --git a/docs/book/src/forc/commands/forc_parse-bytecode.md b/docs/book/src/forc/commands/forc_parse-bytecode.md index 80c67edb461..79d718cc9f7 100644 --- a/docs/book/src/forc/commands/forc_parse-bytecode.md +++ b/docs/book/src/forc/commands/forc_parse-bytecode.md @@ -1 +1 @@ -# `forc parse-bytecode` +# forc parse-bytecode diff --git a/docs/book/src/forc/commands/forc_plugins.md b/docs/book/src/forc/commands/forc_plugins.md index bc0e7aa6c00..a6cfa94c56e 100644 --- a/docs/book/src/forc/commands/forc_plugins.md +++ b/docs/book/src/forc/commands/forc_plugins.md @@ -1 +1 @@ -# `forc plugins` +# forc plugins diff --git a/docs/book/src/forc/commands/forc_predicate-root.md b/docs/book/src/forc/commands/forc_predicate-root.md index 9ed1d7ca56d..863450ebb50 100644 --- a/docs/book/src/forc/commands/forc_predicate-root.md +++ b/docs/book/src/forc/commands/forc_predicate-root.md @@ -1 +1 @@ -# `forc predicate-root` +# forc predicate-root diff --git a/docs/book/src/forc/commands/forc_template.md b/docs/book/src/forc/commands/forc_template.md index 4bc677ff08c..a6cd711e7aa 100644 --- a/docs/book/src/forc/commands/forc_template.md +++ b/docs/book/src/forc/commands/forc_template.md @@ -1 +1 @@ -# `forc template` +# forc template diff --git a/docs/book/src/forc/commands/forc_test.md b/docs/book/src/forc/commands/forc_test.md index 7c4ce2723b7..85254c0002e 100644 --- a/docs/book/src/forc/commands/forc_test.md +++ b/docs/book/src/forc/commands/forc_test.md @@ -1 +1 @@ -# `forc test` +# forc test diff --git a/docs/book/src/forc/commands/forc_update.md b/docs/book/src/forc/commands/forc_update.md index 6805c316eed..0dcb013a3d0 100644 --- a/docs/book/src/forc/commands/forc_update.md +++ b/docs/book/src/forc/commands/forc_update.md @@ -1 +1 @@ -# `forc update` +# forc update diff --git a/docs/book/src/forc/manifest_reference.md b/docs/book/src/forc/manifest_reference.md index 55539866850..e9be681e5c8 100644 --- a/docs/book/src/forc/manifest_reference.md +++ b/docs/book/src/forc/manifest_reference.md @@ -76,7 +76,6 @@ The following fields can be provided for a build-profile: * `terse` - Terse mode. Limited warning and error output, defaults to false. * `time_phases` - Whether to output the time elapsed over each part of the compilation process, defaults to false. * `include_tests` - Whether or not to include test functions in parsing, type-checking, and code generation. This is set to true by invocations like `forc test`, but defaults to false. -* `json_abi_with_callpaths` - Whether to generate a JSON ABI with `callpaths` instead of names for structs and enums, defaults to false. This option can help prevent conflicting struct or enum definitions by using the full path instead of the name. * `error_on_warnings` - Whether to treat errors as warnings, defaults to false. There are two default `[build-profile]` available with every manifest file. These are `debug` and `release` profiles. If you want to override these profiles, you can provide them explicitly in the manifest file like the following example: @@ -111,7 +110,6 @@ print-asm = { virtual = true, allocated = true, final = true } terse = false time-phases = false include-tests = false -json-abi-with-callpaths = false error-on-warnings = false experimental-private-modules = false ``` diff --git a/docs/book/src/forc/plugins/forc_client/forc_deploy.md b/docs/book/src/forc/plugins/forc_client/forc_deploy.md index 96a3b57a5a5..5fd00d93425 100644 --- a/docs/book/src/forc/plugins/forc_client/forc_deploy.md +++ b/docs/book/src/forc/plugins/forc_client/forc_deploy.md @@ -1 +1 @@ -# `forc deploy` +# forc deploy diff --git a/docs/book/src/forc/plugins/forc_client/forc_run.md b/docs/book/src/forc/plugins/forc_client/forc_run.md index 008a92b9593..7d6f88c8db5 100644 --- a/docs/book/src/forc/plugins/forc_client/forc_run.md +++ b/docs/book/src/forc/plugins/forc_client/forc_run.md @@ -1 +1 @@ -# `forc run` +# forc run diff --git a/docs/book/src/forc/plugins/forc_client/forc_submit.md b/docs/book/src/forc/plugins/forc_client/forc_submit.md index 54e1e5f6c5e..ad314de43e7 100644 --- a/docs/book/src/forc/plugins/forc_client/forc_submit.md +++ b/docs/book/src/forc/plugins/forc_client/forc_submit.md @@ -1 +1 @@ -# `forc submit` +# forc submit diff --git a/docs/book/src/forc/plugins/forc_client/index.md b/docs/book/src/forc/plugins/forc_client/index.md index 9c044221f47..feb436af788 100644 --- a/docs/book/src/forc/plugins/forc_client/index.md +++ b/docs/book/src/forc/plugins/forc_client/index.md @@ -1,26 +1,64 @@ -# `forc-client` +# forc-client -Forc plugin for interacting with a Fuel node. +The forc plugin for interacting with a Fuel node. -## Initializing the wallet and adding accounts +Since transactions are going to require some gas, you need to sign them with an account that has enough coins to pay for them. -If you don't have an initialized wallet or any account for your wallet you won't be able to sign transactions. +We offer multiple ways to sign the transaction: -To create a wallet you can use `forc wallet new`. It will ask you to choose a password to encrypt your wallet. After the initialization is done you will have your mnemonic phrase. + 1. Sign the transaction via your local wallet using `forc-client` which integrates with our CLI wallet, `forc-wallet`. + 2. Use the default signer to deploy to a local node + 3. Use `forc-wallet` to manually sign transactions, and copy the signed transaction back to `forc-client`. -After you have created a wallet, you can derive a new account by running `forc wallet account new`. It will ask your password to decrypt the wallet before deriving an account. +The easiest and recommended way to interact with deployed networks such as our testnets is option 1, using `forc-client` to sign your transactions which reads your default `forc-wallet` vault. For interacting with local node, we recommend using the second option, which leads `forc-client` to sign transactions with the private key that comes pre-funded in local environments. -## Signing transactions using `forc-wallet` CLI +## Option 1: Sign transactions via forc-client using your local forc-wallet vault -To submit the transactions created by `forc deploy` or `forc run`, you need to sign them first (unless you are using a client without UTXO validation). To sign a transaction you can use `forc-wallet` CLI. This section is going to walk you through the whole signing process. +If you've used `forc-wallet` before, you'll already have a secure, password-protected vault holding your private key written to your file-system. `forc-client` is compatible with `forc-wallet` such that it can read that vault by asking you your password and use your account to sign transactions. -By default `fuel-core` runs without UTXO validation, this allows you to send invalid inputs to emulate different conditions. +Example: -If you want to run `fuel-core` with UTXO validation, you can pass `--utxo-validation` to `fuel-core run`. +```console +> forc deploy -To install `forc-wallet` please refer to `forc-wallet`'s [GitHub repo](https://github.com/FuelLabs/forc-wallet#forc-wallet). + Building /Users/yourname/test-projects/test-contract + Finished release [optimized + fuel] target(s) in 11.39s + Confirming transactions [deploy impl-contract] + Network: https://testnet.fuel.network + Wallet: /Users/yourname/.fuel/wallets/.wallet +āœ” Wallet password Ā· ******** +? Wallet account ā€ŗ +āÆ [0] fuel12pls73y9hnqdqthvduy2x44x48zt8s50pkerf32kq26f2afeqdwq6rj9ar - 0.002197245 ETH + [1] fuel1vzrm6kw9s3tv85gl25lpptsxrdguyzfhq6c8rk07tr6ft5g45nwqqh0uty - 0.001963631 ETH +? Do you agree to sign 1 transaction? (y/n) ā€ŗ yes + Finished deploying impl-contract https://app.fuel.network/contract/0x94b712901f04332682d14c998a5fc5a078ed15321438f46d58d0383200cde43d + Deployed in block https://app.fuel.network/block/5958351 +``` + +As it can be seen from the example, `forc-client` asks for your password to decrypt the `forc-wallet` vault, and list your accounts so that you can select the one you want to fund the transaction with. + +## Option 2: Using default signer + +If you are not interacting with a deployed network, such as testnets, your local `fuel-core` environment can be structured such that it funds an account by default. Using `--default-signer` flag with `forc-client` binaries (run, deploy) will instruct `forc-client` to sign transactions with this pre-funded account. This makes it a useful command while working against a local node. + +Example: + +```console +> forc deploy --default-signer -1. Construct the transaction by using either `forc deploy` or `forc run`. To do so simply run `forc deploy` or `forc run` with your desired parameters. For a list of parameters please refer to the [forc-deploy](./forc_deploy.md) or [forc-run](./forc_run.md) section of the book. Once you run either command you will be asked the address of the wallet you are going to be signing with. After the address is given the transaction will be generated and you will be given a transaction ID. At this point CLI will actively wait for you to insert the signature. + Building /Users/test/test-projects/test-contract + Finished release [optimized + fuel] target(s) in 11.40s + Confirming transactions [deploy impl-contract] + Network: http://127.0.0.1:4000 + Finished deploying impl-contract 0xf9fb08ef18ce226954270d6d4f67677d484b8782a5892b3d436572b405407544 + Deployed in block 00000001 +``` + +## Option 3: Manually signing through forc-wallet (Deprecated) + +This option is for creating the transaction first, signing it manually, and supplying the signed transaction back to forc-client. Since it requires multiple steps, it is more error-prone and not recommended for general use cases. Also this will be deprecated soon. + +1. Construct the transaction by using either `forc deploy` or `forc run`. To do so simply run `forc deploy --manual-sign` or `forc run --manual-sign` with your desired parameters. For a list of parameters please refer to the [forc-deploy](./forc_deploy.md) or [forc-run](./forc_run.md) section of the book. Once you run either command you will be asked the address of the wallet you are going to be signing with. After the address is given the transaction will be generated and you will be given a transaction ID. At this point CLI will actively wait for you to insert the signature. 2. Take the transaction ID generated in the first step and sign it with `forc wallet sign --account tx-id `. This will generate a signature. 3. Take the signature generated in the second step and provide it to `forc-deploy` (or `forc-run`). Once the signature is provided, the signed transaction will be submitted. @@ -54,28 +92,44 @@ By default `--default-signer` flag would sign your transactions with the followi 0xde97d8624a438121b86a1956544bd72ed68cd69f2c99555b08b1e8c51ffd511c ``` -## Interacting with the testnet +## Selecting a target network -To interact with the latest testnet, use the `--testnet` flag. When this flag is passed, transactions created by `forc-deploy` will be sent to the `beta-4` testnet. +By default, `local` is used for the target network. To interact with the latest testnet, use the `--testnet` flag. When this flag is passed, transactions created by `forc-deploy` will be sent to the latest `testnet`: ```sh forc-deploy --testnet ``` -It is also possible to pass the exact node URL while using `forc-deploy` or `forc-run` which can be done using `--node-url` flag. +The same can be done to target mainnet: + +```sh +forc-deploy --mainnet +``` + +It is also possible to pass the exact node URL while using `forc-deploy` or `forc-run` which can be done using `--node-url` flag: ```sh -forc-deploy --node-url https://beta-3.fuel.network +forc-deploy --node-url https://mainnet.fuel.network ``` -Another alternative is the `--target` option, which provides useful aliases to all targets. For example if you want to deploy to `beta-3` you can use: +Another alternative is the `--target` option, which provides useful aliases to all targets. For example if you want to deploy to `testnet` you can use: ```sh -forc-deploy --target beta-3 +forc-deploy --target testnet ``` Since deploying and running projects on the testnet cost gas, you will need coins to pay for them. You can get some using the [testnet faucet](https://faucet-testnet.fuel.network/). +## Delayed transactions + +For delayed transactions, you can use the `--submit-only` flag. This flag allows you to submit the transaction without waiting for its finalization. + +One use case for this is multisig transactions, where a deployment transaction may stay in a pending state while waiting for all signatures. + +```sh +forc-deploy --submit-only +``` + ## Deployment Artifacts forc-deploy saves the details of each deployment in the `out/deployments` folder within the project's root directory. Below is an example of a deployment artifact: @@ -91,3 +145,65 @@ forc-deploy saves the details of each deployment in the `out/deployments` folder "deployed_block_id": "0x915c6f372252be6bc54bd70df6362dae9bf750ba652bf5582d9b31c7023ca6cf" } ``` + +## Proxy Contracts + +`forc-deploy` supports deploying proxy contracts automatically if it is enabled in the `Forc.toml` of the contract. + +```TOML +[project] +name = "test_contract" +authors = ["Fuel Labs "] +entry = "main.sw" +license = "Apache-2.0" +implicit-std = false + +[proxy] +enabled = true +``` + +If there is no `address` field present under the proxy table, like the example above, `forc` will automatically create a proxy contract based on the [SRC-14](https://github.com/FuelLabs/sway-standards/blob/master/docs/src/src-14-simple-upgradeable-proxies.md) implementation from [sway-standards](https://github.com/FuelLabs/sway-standards). After generating and deploying the proxy contract, the target is set to the current contract, and the owner of the proxy is set to the account that is signing the transaction for deployment. + +This means that if you simply enable proxy in the `Forc.toml`, forc will automatically deploy a proxy contract for you and you do not need to do anything manually aside from signing the deployment transactions for the proxy contract. After deploying the proxy contract, the address is added into the `address` field of the proxy table. + +If you want to update the target of an [SRC-14](https://github.com/FuelLabs/sway-standards/blob/master/docs/src/src-14-simple-upgradeable-proxies.md) compliant proxy contract rather than deploying a new one, simply add its `address` in the `address` field, like the following example: + +```TOML +[project] +name = "test_contract" +authors = ["Fuel Labs "] +entry = "main.sw" +license = "Apache-2.0" +implicit-std = false + +[proxy] +enabled = true +address = "0xd8c4b07a0d1be57b228f4c18ba7bca0c8655eb6e9d695f14080f2cf4fc7cd946" # example proxy contract address +``` + +If an `address` is present, `forc` calls into that contract to update its `target` instead of deploying a new contract. Since a new proxy deployment adds its own `address` into the `Forc.toml` automatically, you can simply enable the proxy once and after the initial deployment, `forc` will keep updating the target accordingly for each new deployment of the same contract. + +## Large Contracts + +For contracts over the maximum contract size limit (currently `100kB`) defined by the network, `forc-deploy` will split the contract into chunks and deploy the contract with multiple transactions using the Rust SDK's [loader contract](https://github.com/FuelLabs/fuels-rs/blob/master/docs/src/deploying/large_contracts.md) functionality. Chunks that have already been deployed will be reused on subsequent deployments. + +## Deploying Scripts and Predicates + +`forc deploy` now supports deploying scripts and predicates in addition to contracts. These are deployed as blobs with generated loaders for efficiency. + +Scripts and predicates are deployed automatically when you run `forc deploy` on a project that contains them. The deployment process differs slightly from contract deployment: + +1. For scripts and predicates, the bytecode is uploaded as a blob. +2. A loader is generated that can load and execute the blob. +3. The loader bytecode is saved in the project's output directory. + +After deployment, you'll find new files in your project's output directory: + +- For scripts: `-loader.bin` +- For predicates: `-loader.bin` and `-loader-root` + +The loader files contain the bytecode necessary to load and execute your script or predicate from the deployed blob. + +This new deployment method allows for more efficient storage and execution of scripts and predicates on the Fuel network. + +Note: Contracts are still deployed directly, not as blobs given that the contract size is under the maximum contract size limit defined by network (currently `100kB`). diff --git a/docs/book/src/forc/plugins/forc_crypto.md b/docs/book/src/forc/plugins/forc_crypto.md index c0789970b64..7c5aa994161 100644 --- a/docs/book/src/forc/plugins/forc_crypto.md +++ b/docs/book/src/forc/plugins/forc_crypto.md @@ -1 +1 @@ -# `forc crypto` +# forc crypto diff --git a/docs/book/src/forc/plugins/forc_doc.md b/docs/book/src/forc/plugins/forc_doc.md index e554a752e6d..2f664873b33 100644 --- a/docs/book/src/forc/plugins/forc_doc.md +++ b/docs/book/src/forc/plugins/forc_doc.md @@ -1 +1 @@ -# `forc doc` +# forc doc diff --git a/docs/book/src/forc/plugins/forc_explore.md b/docs/book/src/forc/plugins/forc_explore.md index b86cb623cdf..c8d4ca5ed5b 100644 --- a/docs/book/src/forc/plugins/forc_explore.md +++ b/docs/book/src/forc/plugins/forc_explore.md @@ -1 +1 @@ -# `forc explore` +# forc explore diff --git a/docs/book/src/forc/plugins/forc_fmt.md b/docs/book/src/forc/plugins/forc_fmt.md index 667a7c1b635..f49f6b7877b 100644 --- a/docs/book/src/forc/plugins/forc_fmt.md +++ b/docs/book/src/forc/plugins/forc_fmt.md @@ -1 +1 @@ -# `forc fmt` +# forc fmt diff --git a/docs/book/src/forc/plugins/forc_lsp.md b/docs/book/src/forc/plugins/forc_lsp.md index b5a93f24f24..624d69001f7 100644 --- a/docs/book/src/forc/plugins/forc_lsp.md +++ b/docs/book/src/forc/plugins/forc_lsp.md @@ -1 +1 @@ -# `forc lsp` +# forc lsp diff --git a/docs/book/src/index.md b/docs/book/src/index.md index 5873263e144..00b6fad6375 100644 --- a/docs/book/src/index.md +++ b/docs/book/src/index.md @@ -59,11 +59,11 @@ You can find example applications built with Sway in the [Sway Applications repo **Q: What is the standard library?** -The [standard library](./introduction/standard_library.md), also referred to as `std`, is a library that offers core functions and helpers for developing in Sway. The standard library has it's own [reference documentation](https://fuellabs.github.io/sway/master/std/) that has detailed information about each module in `std`. +The [standard library](./introduction/standard_library.md), also referred to as `std`, is a library that offers core functions and helpers for developing in Sway. The standard library has its own [reference documentation](https://fuellabs.github.io/sway/master/std/) that has detailed information about each module in `std`. **Q: What are Sway standards?** -Similar to ERC standards for Ethereum and Solidity, Sway has it's own SRC standards that help enable cross compatibility across different smart contracts. For more information on using a Sway Standard, you can check out the [Sway-Standards Repository](https://github.com/FuelLabs/sway-standards). +Similar to ERC standards for Ethereum and Solidity, Sway has its own SRC standards that help enable cross compatibility across different smart contracts. For more information on using a Sway Standard, you can check out the [Sway-Standards Repository](https://github.com/FuelLabs/sway-standards). **Q: How can I make a token?** diff --git a/docs/book/src/introduction/core_library.md b/docs/book/src/introduction/core_library.md new file mode 100644 index 00000000000..314db3e5c02 --- /dev/null +++ b/docs/book/src/introduction/core_library.md @@ -0,0 +1,30 @@ +# Core Library + +The Sway Core Library, like the name suggests contains core operators and logic for the primitive types of the Sway programming language. These traits and methods are an extension of the [primitive types](https://docs.fuel.network/docs/sway/basics/built_in_types/#primitive-types) `u8`, `u16`, `u32`, `u64`, `u256`, `str[]`, `str`, `bool` and , `b256` and can be used where appropriate. + +The latest core library documentation can be found [here](https://fuellabs.github.io/sway/master/core/). If the latest version is not compatible please refer to the appropriate tagged release. + +## Using the Core Library + +Core library functionalities do not need to be explicitly imported and will work out of the box after creating any new Sway project with [`forc new`](../forc/commands/forc_new.md). The `use` keyword is simply not required. + +Consider this example of using the modulo function for two like value types: + +```sway +let val_1 = 10; +let val_2 = 2; +let result = val_1 % val_2; +``` + +## Core Library Prelude + +The prelude contains a list of operations essential to all Sway programs. The latest version of the prelude can be found [here](https://github.com/FuelLabs/sway/blob/master/sway-lib-core/src/prelude.sw). + +- [`core::primitives::*`](https://github.com/FuelLabs/sway/blob/master/sway-lib-core/src/primitives.sw) +- [`core::primitive_conversions::*`](https://github.com/FuelLabs/sway/blob/master/sway-lib-core/src/primitive_conversions.sw) +- [`core::raw_ptr::*`](https://github.com/FuelLabs/sway/blob/master/sway-lib-core/src/raw_ptr.sw) +- [`core::raw_slice::*`](https://github.com/FuelLabs/sway/blob/master/sway-lib-core/src/raw_slice.sw) +- [`core::ops::*`](https://github.com/FuelLabs/sway/blob/master/sway-lib-core/src/ops.sw) +- [`core::storage::*`](https://github.com/FuelLabs/sway/blob/master/sway-lib-core/src/storage.sw) +- [`core::str::*`](https://github.com/FuelLabs/sway/blob/master/sway-lib-core/src/str.sw) +- [`core::codec::*`](https://github.com/FuelLabs/sway/blob/master/sway-lib-core/src/codec.sw) diff --git a/docs/book/src/introduction/index.md b/docs/book/src/introduction/index.md index 8328fdaf1ba..33694f3f541 100644 --- a/docs/book/src/introduction/index.md +++ b/docs/book/src/introduction/index.md @@ -6,4 +6,5 @@ To get started with Forc and Sway smart contract development, install the Fuel t - [The Fuel Toolchain](./fuel_toolchain.md) - [A Forc Project](./forc_project.md) - [Standard Library](./standard_library.md) +- [Core Library](./core_library.md) - [Sway Language Standards](./sway_standards.md) diff --git a/docs/book/src/lsp/features.md b/docs/book/src/lsp/features.md index c5791915956..56a8c8acb31 100644 --- a/docs/book/src/lsp/features.md +++ b/docs/book/src/lsp/features.md @@ -12,17 +12,13 @@ _Source:_ [completion.rs](https://github.com/FuelLabs/sway/blob/master/sway-lsp/ Suggests code to follow partially written statements for functions and variables. -## Diagnostics - -_Source:_ [diagnostic.rs](https://github.com/FuelLabs/sway/blob/master/sway-lsp/src/capabilities/diagnostic.rs) - -Displays compiler warnings and errors inline. +## Go to Definition -## Syntax Highlighting +Jumps to the definition of a symbol from its usage. -_Source:_ [highlight.rs](https://github.com/FuelLabs/sway/blob/master/sway-lsp/src/capabilities/highlight.rs) +## Find All References -Highlights code based on type and context. +Locates all occurrences of a symbol throughout the project. ## Hover @@ -42,6 +38,18 @@ _Source:_ [rename.rs](https://github.com/FuelLabs/sway/blob/master/sway-lsp/src/ Renames a symbol everywhere in the workspace. +## Diagnostics + +_Source:_ [diagnostic.rs](https://github.com/FuelLabs/sway/blob/master/sway-lsp/src/capabilities/diagnostic.rs) + +Displays compiler warnings and errors inline. + +## Syntax Highlighting + +_Source:_ [highlight.rs](https://github.com/FuelLabs/sway/blob/master/sway-lsp/src/capabilities/highlight.rs) + +Highlights code based on type and context. + ## Run _Source:_ [runnable.rs](https://github.com/FuelLabs/sway/blob/master/sway-lsp/src/capabilities/runnable.rs) diff --git a/docs/book/src/lsp/troubleshooting.md b/docs/book/src/lsp/troubleshooting.md index 2f17bf8c028..954e1a668e3 100644 --- a/docs/book/src/lsp/troubleshooting.md +++ b/docs/book/src/lsp/troubleshooting.md @@ -34,7 +34,7 @@ In the meantime, if it's too slow, you can disable the LSP server entirely with ## Server Logs -You can you enable verbose logging of the LSP server. +You can enable verbose logging of the LSP server. In VSCode, this is under the setting: diff --git a/docs/book/src/reference/compiler_intrinsics.md b/docs/book/src/reference/compiler_intrinsics.md index a0dfd0f7c62..c3ba29ce0e0 100644 --- a/docs/book/src/reference/compiler_intrinsics.md +++ b/docs/book/src/reference/compiler_intrinsics.md @@ -2,7 +2,7 @@ The Sway compiler supports a list of intrinsics that perform various low level operations that are useful for building libraries. Compiler intrinsics should rarely be used but are preferred over `asm` blocks because they are type-checked and are safer overall. Below is a list of all available compiler intrinsics: -___ +--- ```sway __size_of_val(val: T) -> u64 @@ -12,7 +12,7 @@ __size_of_val(val: T) -> u64 **Constraints:** None. -___ +--- ```sway __size_of() -> u64 @@ -22,7 +22,7 @@ __size_of() -> u64 **Constraints:** None. -___ +--- ```sway __size_of_str_array() -> u64 @@ -32,7 +32,7 @@ __size_of_str_array() -> u64 **Constraints:** None. -___ +--- ```sway __assert_is_str_array() @@ -42,7 +42,7 @@ __assert_is_str_array() **Constraints:** None. -___ +--- ```sway __to_str_array(s: str) -> str[N] @@ -52,7 +52,7 @@ __to_str_array(s: str) -> str[N] **Constraints:** None. -___ +--- ```sway __is_reference_type() -> bool @@ -62,7 +62,7 @@ __is_reference_type() -> bool **Constraints:** None. -___ +--- ```sway __is_str_array() -> bool @@ -72,7 +72,7 @@ __is_str_array() -> bool **Constraints:** None. -___ +--- ```sway __eq(lhs: T, rhs: T) -> bool @@ -82,7 +82,7 @@ __eq(lhs: T, rhs: T) -> bool **Constraints:** `T` is `bool`, `u8`, `u16`, `u32`, `u64`, `u256`, `b256` or `raw_ptr`. -___ +--- ```sway __gt(lhs: T, rhs: T) -> bool @@ -91,7 +91,8 @@ __gt(lhs: T, rhs: T) -> bool **Description:** Returns whether `lhs` is greater than `rhs`. **Constraints:** `T` is `u8`, `u16`, `u32`, `u64`, `u256`, `b256`. -___ + +--- ```sway __lt(lhs: T, rhs: T) -> bool @@ -100,7 +101,8 @@ __lt(lhs: T, rhs: T) -> bool **Description:** Returns whether `lhs` is less than `rhs`. **Constraints:** `T` is `u8`, `u16`, `u32`, `u64`, `u256`, `b256`. -___ + +--- ```sway __gtf(index: u64, tx_field_id: u64) -> T @@ -110,7 +112,7 @@ __gtf(index: u64, tx_field_id: u64) -> T **Constraints:** None. -___ +--- ```sway __addr_of(val: T) -> raw_ptr @@ -120,7 +122,7 @@ __addr_of(val: T) -> raw_ptr **Constraints:** `T` is a reference type. -___ +--- ```sway __state_load_word(key: b256) -> u64 @@ -130,7 +132,7 @@ __state_load_word(key: b256) -> u64 **Constraints:** None. -___ +--- ```sway __state_load_quad(key: b256, ptr: raw_ptr, slots: u64) -> bool @@ -140,7 +142,7 @@ __state_load_quad(key: b256, ptr: raw_ptr, slots: u64) -> bool **Constraints:** None. -___ +--- ```sway __state_store_word(key: b256, val: u64) -> bool @@ -150,7 +152,7 @@ __state_store_word(key: b256, val: u64) -> bool **Constraints:** None. -___ +--- ```sway __state_store_quad(key: b256, ptr: raw_ptr, slots: u64) -> bool @@ -160,7 +162,7 @@ __state_store_quad(key: b256, ptr: raw_ptr, slots: u64) -> bool **Constraints:** None. -___ +--- ```sway __log(val: T) @@ -170,7 +172,7 @@ __log(val: T) **Constraints:** None. -___ +--- ```sway __add(lhs: T, rhs: T) -> T @@ -180,7 +182,7 @@ __add(lhs: T, rhs: T) -> T **Constraints:** `T` is an integer type, i.e. `u8`, `u16`, `u32`, `u64`, `u256`. -___ +--- ```sway __sub(lhs: T, rhs: T) -> T @@ -190,7 +192,7 @@ __sub(lhs: T, rhs: T) -> T **Constraints:** `T` is an integer type, i.e. `u8`, `u16`, `u32`, `u64`, `u256`. -___ +--- ```sway __mul(lhs: T, rhs: T) -> T @@ -200,7 +202,7 @@ __mul(lhs: T, rhs: T) -> T **Constraints:** `T` is an integer type, i.e. `u8`, `u16`, `u32`, `u64`, `u256`. -___ +--- ```sway __div(lhs: T, rhs: T) -> T @@ -210,7 +212,7 @@ __div(lhs: T, rhs: T) -> T **Constraints:** `T` is an integer type, i.e. `u8`, `u16`, `u32`, `u64`, `u256`. -___ +--- ```sway __and(lhs: T, rhs: T) -> T @@ -220,7 +222,7 @@ __and(lhs: T, rhs: T) -> T **Constraints:** `T` is an integer type, i.e. `u8`, `u16`, `u32`, `u64`, `u256`, `b256`. -___ +--- ```sway __or(lhs: T, rhs: T) -> T @@ -230,7 +232,7 @@ __or(lhs: T, rhs: T) -> T **Constraints:** `T` is an integer type, i.e. `u8`, `u16`, `u32`, `u64`, `u256`, `b256`. -___ +--- ```sway __xor(lhs: T, rhs: T) -> T @@ -239,7 +241,8 @@ __xor(lhs: T, rhs: T) -> T **Description:** Bitwise XOR `lhs` and `rhs`. **Constraints:** `T` is an integer type, i.e. `u8`, `u16`, `u32`, `u64`, `u256`, `b256`. -___ + +--- ```sway __mod(lhs: T, rhs: T) -> T @@ -248,7 +251,8 @@ __mod(lhs: T, rhs: T) -> T **Description:** Modulo of `lhs` by `rhs`. **Constraints:** `T` is an integer type, i.e. `u8`, `u16`, `u32`, `u64`, `u256`. -___ + +--- ```sway __rsh(lhs: T, rhs: u64) -> T @@ -257,7 +261,8 @@ __rsh(lhs: T, rhs: u64) -> T **Description:** Logical right shift of `lhs` by `rhs`. **Constraints:** `T` is an integer type, i.e. `u8`, `u16`, `u32`, `u64`, `u256`, `b256`. -___ + +--- ```sway __lsh(lhs: T, rhs: u64) -> T @@ -266,7 +271,8 @@ __lsh(lhs: T, rhs: u64) -> T **Description:** Logical left shift of `lhs` by `rhs`. **Constraints:** `T` is an integer type, i.e. `u8`, `u16`, `u32`, `u64`, `u256`, `b256`. -___ + +--- ```sway __revert(code: u64) @@ -276,7 +282,7 @@ __revert(code: u64) **Constraints:** None. -___ +--- ```sway __ptr_add(ptr: raw_ptr, offset: u64) @@ -286,7 +292,7 @@ __ptr_add(ptr: raw_ptr, offset: u64) **Constraints:** None. -___ +--- ```sway __ptr_sub(ptr: raw_ptr, offset: u64) @@ -296,7 +302,7 @@ __ptr_sub(ptr: raw_ptr, offset: u64) **Constraints:** None. -___ +--- ```sway __smo(recipient: b256, data: T, coins: u64) @@ -306,7 +312,7 @@ __smo(recipient: b256, data: T, coins: u64) **Constraints:** None. -___ +--- ```sway __not(op: T) -> T @@ -316,7 +322,7 @@ __not(op: T) -> T **Constraints:** `T` is an integer type, i.e. `u8`, `u16`, `u32`, `u64`, `u256`, `b256`. -___ +--- ```sway __jmp_mem() @@ -325,3 +331,44 @@ __jmp_mem() **Description:** Jumps to `MEM[$hp]`. **Constraints:** None. + +--- + +```sway +__slice(item: &[T; N], start: u64, end: u64) -> &[T] +__slice(item: &[T], start: u64, end: u64) -> &[T] +__slice(item: &mut [T; N], start: u64, end: u64) -> &mut [T] +__slice(item: &mut [T], start: u64, end: u64) -> &mut [T] +``` + +**Description:** Slices an array or another slice. + +This intrinsic returns a reference to a slice containing the range of elements inside `item`. +The mutability of reference is defined by the first parameter mutability. + +Runtime bound checks are not generated, and must be done manually when and where appropriated. Compile time bound checks are done when possible. + +**Constraints:** + +- `item` is an array or a slice; +- when `start` is a literal, it must be smaller than `item` length; +- when `end` is a literal, it must be smaller than or equal to `item` length; +- `end` must be greater than or equal to `start` + +--- + +```sway +__elem_at(item: &[T; N], index: u64) -> &T +__elem_at(item: &[T], index: u64) -> &T +__elem_at(item: &mut [T; N], index: u64) -> &mut T +__elem_at(item: &mut [T], index: u64) -> &mut T +``` + +**Description:** Returns a reference to the indexed element. The mutability of reference is defined by the first parameter mutability. + +Runtime bound checks are not generated, and must be done manually when and where appropriated. Compile time bound checks are done when possible. + +**Constraints:** + +- `item` is a reference to an array or a reference to a slice; +- when `index` is a literal, it must be smaller than `item` length; diff --git a/docs/book/src/reference/known_issues_and_workarounds.md b/docs/book/src/reference/known_issues_and_workarounds.md index 50ae1052b67..d60c5d23de3 100644 --- a/docs/book/src/reference/known_issues_and_workarounds.md +++ b/docs/book/src/reference/known_issues_and_workarounds.md @@ -6,7 +6,7 @@ ## Missing Features -* [#1182](https://github.com/FuelLabs/sway/issues/1182) Arrays in a `storage` block are not yet supported. See the [Manual Storage Management](../blockchain-development/storage.md#manual-storage-management) section for details on how to use `store` and `get` from the standard library to manage storage slots directly. Note, however, that `StorageMap` _does_ support arbitrary types for `K` and `V` without any limitations. +* [#1182](https://github.com/FuelLabs/sway/issues/1182) Arrays in a `storage` block are not yet supported. See the [Manual Storage Management](../advanced/advanced_storage.md#manual-storage-management) section for details on how to use `store` and `get` from the standard library to manage storage slots directly. Note, however, that `StorageMap` _does_ support arbitrary types for `K` and `V` without any limitations. ## General diff --git a/docs/book/src/reference/undefined_behavior.md b/docs/book/src/reference/undefined_behavior.md new file mode 100644 index 00000000000..07555223aad --- /dev/null +++ b/docs/book/src/reference/undefined_behavior.md @@ -0,0 +1,15 @@ +# Behavior Considered Undefined + +Sway code that contains any of the following behavior is considered undefined. +The compiler is allowed to treat undefined Sway code however it desires, +including removing it or replacing it with any other Sway code. + +This is not an exhaustive list, it may grow or shrink, there is no formal model +of Sway's semantics so there may be more behavior considered undefined. We +reserve the right to make some of the listed behavior defined in the future. + +* Invalid arithmetic operations (overflows, underflows, division by zero, etc) +* Misuse of compiler intrinsics +* Incorrect use of inline assembly +* Reading and writing `raw_ptr` and `raw_slice` +* Slicing and indexing out of bounds by directly using compiler intrinsics. diff --git a/docs/book/src/sway-program-types/index.md b/docs/book/src/sway-program-types/index.md index fdd076181da..4efe5b47057 100644 --- a/docs/book/src/sway-program-types/index.md +++ b/docs/book/src/sway-program-types/index.md @@ -9,7 +9,7 @@ Every Sway file _must_ begin with a declaration of what type of program it is. A Contracts are used primarily for protocols or systems that operate within a fixed set of rules. A good example would be a staking contract or a decentralized exchange (also called a DEX). -Scripts are used for complex on-chain interactions that won't persist. An example of this may be using a DEX and Lender to create a leveraged position (borrow, swap, re-collateralize, borrow) which is a complex transaction that would usually take multiple steps. +Scripts are used for complex on-chain interactions that won't persist. An example of this may be using a DEX and Lender to create a leveraged position (borrow, swap, re-collateralize) which is a complex transaction that would usually take multiple steps. Libraries are for code that is reusable and useful for handling common situations. A good example of this would be a library to handle fixed-point math or big number math. diff --git a/docs/book/src/testing/testing-with-rust.md b/docs/book/src/testing/testing-with-rust.md index ce6fddf52c7..d87402f9c7d 100644 --- a/docs/book/src/testing/testing-with-rust.md +++ b/docs/book/src/testing/testing-with-rust.md @@ -74,18 +74,21 @@ Let's have a look at the result: $ tree . ā”œā”€ā”€ Cargo.toml ā”œā”€ā”€ Forc.toml +ā”œā”€ā”€ build.rs ā”œā”€ā”€ src ā”‚Ā Ā  ā””ā”€ā”€ main.sw ā””ā”€ā”€ tests ā””ā”€ā”€ harness.rs ``` -We have two new files! +We have three new files! - The `Cargo.toml` is the manifest for our new test harness and specifies the required dependencies including `fuels` the Fuel Rust SDK. - The `tests/harness.rs` contains some boilerplate test code to get us started, though doesn't call any contract methods just yet. +- The `build.rs` is a build script that compiles the Sway project with `forc build` + whenever `cargo test` is run. ### 4. Build the forc project @@ -111,6 +114,7 @@ $ tree ā”œā”€ā”€ Cargo.toml ā”œā”€ā”€ Forc.lock ā”œā”€ā”€ Forc.toml +ā”œā”€ā”€ build.rs ā”œā”€ā”€ out ā”‚Ā Ā  ā””ā”€ā”€ debug ā”‚Ā Ā  ā”œā”€ā”€ my-fuel-project-abi.json @@ -176,10 +180,13 @@ following: ```rust,ignore use fuels::{prelude::*, types::ContractId}; -// Load ABI from JSON -abigen!(TestContract, "out/debug/my-fuel-project-abi.json"); +// Load abi from json +abigen!(Contract( + name = "MyContract", + abi = "out/debug/my-fuel-project-abi.json" +)); -async fn get_contract_instance() -> (TestContract, ContractId) { +async fn get_contract_instance() -> (MyContract, ContractId) { // Launch a local network and deploy the contract let mut wallets = launch_custom_provider_and_get_wallets( WalletsConfig::new( @@ -188,8 +195,10 @@ async fn get_contract_instance() -> (TestContract, ContractId) { Some(1_000_000_000), /* Amount per coin */ ), None, + None, ) - .await; + .await + .unwrap(); let wallet = wallets.pop().unwrap(); let id = Contract::load_from( @@ -202,11 +211,11 @@ async fn get_contract_instance() -> (TestContract, ContractId) { ), ) .unwrap() - .deploy(&wallet, TxParameters::default()) + .deploy(&wallet, TxPolicies::default()) .await .unwrap(); - let instance = TestContract::new(id.to_string(), wallet); + let instance = MyContract::new(id.clone(), wallet); (instance, id.into()) } diff --git a/forc-plugins/forc-client/test/data/standalone_contract_b/.gitignore b/docs/reference/src/code/language/built-ins/slices/.gitignore similarity index 100% rename from forc-plugins/forc-client/test/data/standalone_contract_b/.gitignore rename to docs/reference/src/code/language/built-ins/slices/.gitignore diff --git a/docs/reference/src/code/language/built-ins/slices/Forc.lock b/docs/reference/src/code/language/built-ins/slices/Forc.lock new file mode 100644 index 00000000000..d064967bf3b --- /dev/null +++ b/docs/reference/src/code/language/built-ins/slices/Forc.lock @@ -0,0 +1,14 @@ +[[package]] +name = 'arrays' +source = 'root' +dependencies = ['std'] + +[[package]] +name = 'core' +source = 'path+from-root-54F92B42A645EA2B' +dependencies = [] + +[[package]] +name = 'std' +source = 'git+https://github.com/fuellabs/sway?tag=v0.24.5#e695606d8884a18664f6231681333a784e623bc9' +dependencies = ['core'] diff --git a/docs/reference/src/code/language/built-ins/slices/Forc.toml b/docs/reference/src/code/language/built-ins/slices/Forc.toml new file mode 100644 index 00000000000..d62b0a85072 --- /dev/null +++ b/docs/reference/src/code/language/built-ins/slices/Forc.toml @@ -0,0 +1,8 @@ +[project] +authors = ["Fuel Labs "] +entry = "lib.sw" +license = "Apache-2.0" +name = "slices" + +[dependencies] +std = { path = "../../../../../../../sway-lib-std" } diff --git a/docs/reference/src/code/language/built-ins/slices/src/lib.sw b/docs/reference/src/code/language/built-ins/slices/src/lib.sw new file mode 100644 index 00000000000..5319cec8dac --- /dev/null +++ b/docs/reference/src/code/language/built-ins/slices/src/lib.sw @@ -0,0 +1,7 @@ +library; + +// ANCHOR: syntax +fn syntax(s: &[u64]) -> u64 { + s.len() +} +// ANCHOR_END: syntax diff --git a/docs/reference/src/documentation/introduction/installation/cargo.md b/docs/reference/src/documentation/introduction/installation/cargo.md index 2bb6adc28c9..f4a4cd68267 100644 --- a/docs/reference/src/documentation/introduction/installation/cargo.md +++ b/docs/reference/src/documentation/introduction/installation/cargo.md @@ -1,7 +1,7 @@ # Cargo -Cargo can be used to install the Sway toolchain with various [`plugins`](https://fuellabs.github.io/sway/v0.60.0/book/forc/plugins/index.html). +Cargo can be used to install the Sway toolchain with various [`plugins`](https://fuellabs.github.io/sway/v0.61.1/book/forc/plugins/index.html). ## Dependencies diff --git a/docs/reference/src/documentation/introduction/installation/index.md b/docs/reference/src/documentation/introduction/installation/index.md index 010ec129353..2dddb76e902 100644 --- a/docs/reference/src/documentation/introduction/installation/index.md +++ b/docs/reference/src/documentation/introduction/installation/index.md @@ -19,9 +19,9 @@ The supported operating systems include Linux and macOS; however, Windows is [`u `Cargo` may be used instead of [`Fuelup`](fuelup.md); however, the user needs to manage the toolchain themselves. -The advantage of using `Cargo` is the installation of [`plugins`](https://fuellabs.github.io/sway/v0.60.0/book/forc/plugins/index.html) that have not been added into [`Fuelup`](fuelup.md). +The advantage of using `Cargo` is the installation of [`plugins`](https://fuellabs.github.io/sway/v0.61.1/book/forc/plugins/index.html) that have not been added into [`Fuelup`](fuelup.md). -The disadvantage occurs when [`Fuelup`](fuelup.md) and `Cargo` are used in tandem because the latest [`plugins`](https://fuellabs.github.io/sway/v0.60.0/book/forc/plugins/index.html) may not be recognized. +The disadvantage occurs when [`Fuelup`](fuelup.md) and `Cargo` are used in tandem because the latest [`plugins`](https://fuellabs.github.io/sway/v0.61.1/book/forc/plugins/index.html) may not be recognized. ## Source diff --git a/docs/reference/src/documentation/introduction/installation/source.md b/docs/reference/src/documentation/introduction/installation/source.md index 1826684e933..283c4e19de6 100644 --- a/docs/reference/src/documentation/introduction/installation/source.md +++ b/docs/reference/src/documentation/introduction/installation/source.md @@ -5,7 +5,7 @@ The `Sway toolchain` can be built directly from the [`Sway repository`](https:// ## Installation & Updating -In the root of the repository `/sway/` build [`forc`](https://fuellabs.github.io/sway/v0.60.0/book/forc/commands/index.html) with the following command: +In the root of the repository `/sway/` build [`forc`](https://fuellabs.github.io/sway/v0.61.1/book/forc/commands/index.html) with the following command: ```bash diff --git a/docs/reference/src/documentation/language/built-ins/index.md b/docs/reference/src/documentation/language/built-ins/index.md index a3ec2dcf7e0..be937b242b4 100644 --- a/docs/reference/src/documentation/language/built-ins/index.md +++ b/docs/reference/src/documentation/language/built-ins/index.md @@ -22,8 +22,10 @@ Sway has the following primitive types: 1. `str[n]` (fixed-length string of size n) 4. [Bytes](b256.md) 1. `b256` (256 bits / 32 bytes, i.e. a hash) +5. [Slices](slices.md) + The default numeric type is `u64`. The FuelVM's word size is 64 bits, and the cases where using a smaller numeric type to save space are minimal. All other types in Sway are built up of these primitive types, or references to these primitive types. diff --git a/docs/reference/src/documentation/language/built-ins/slices.md b/docs/reference/src/documentation/language/built-ins/slices.md new file mode 100644 index 00000000000..777a7cb1b8a --- /dev/null +++ b/docs/reference/src/documentation/language/built-ins/slices.md @@ -0,0 +1,14 @@ +# Slices + +A slice is similar to an [array](arrays.md), in the sense that it is a contiguous sequence of elements of the same type. + +Unlike arrays, slices cannot be allocated, because its size is unknown at compilation time. The only way to use slices is through references to a slice. + +References to slice are "fat pointers" containing two items: + +- a pointer to the first element of the slice; +- a `u64` with how many elements the slice has. + +```sway +{{#include ../../../code/language/built-ins/slices/src/lib.sw:syntax}} +``` diff --git a/docs/reference/src/documentation/language/program-types/index.md b/docs/reference/src/documentation/language/program-types/index.md index 30b14667164..1e0154b93ae 100644 --- a/docs/reference/src/documentation/language/program-types/index.md +++ b/docs/reference/src/documentation/language/program-types/index.md @@ -9,7 +9,7 @@ A Sway program can be one of four types: - [library](libraries/index.md) - Reusable code for handling common operations - [script](script.md) - - Used for complex, multi-step, on-chain interactions that won't persist, such as using a decentralized exchange to create a leveraged position (borrow, swap, re-collateralize, borrow) + - Used for complex, multi-step, on-chain interactions that won't persist, such as using a decentralized exchange to create a leveraged position (borrow, swap, re-collateralize) - [predicate](predicate.md) - A set of preconditions to the construction of a transaction, the result of which must be a Boolean value of `true` in order for the transaction to be considered valid diff --git a/docs/reference/src/index.md b/docs/reference/src/index.md index 9a9ec8fedb0..400aef9503b 100644 --- a/docs/reference/src/index.md +++ b/docs/reference/src/index.md @@ -1,5 +1,5 @@ # The Sway Reference -This is the technical reference for the Sway programming language. For a prose explanation and introduction to the language, please refer to the [Sway Book](https://fuellabs.github.io/sway/v0.60.0/book/). +This is the technical reference for the Sway programming language. For a prose explanation and introduction to the language, please refer to the [Sway Book](https://fuellabs.github.io/sway/v0.61.1/book/). diff --git a/examples/advanced_storage_variables/src/main.sw b/examples/advanced_storage_variables/src/main.sw index ac955c6e45c..75054ab7149 100644 --- a/examples/advanced_storage_variables/src/main.sw +++ b/examples/advanced_storage_variables/src/main.sw @@ -14,9 +14,9 @@ use std::storage::storage_vec::*; use std::storage::storage_bytes::*; // ANCHOR: storage_bytes_import -// ANCHOR: storage_bytes_import +// ANCHOR: storage_string_import use std::storage::storage_string::*; -// ANCHOR: storage_bytes_import +// ANCHOR: storage_string_import // ANCHOR: advanced_storage_declaration storage { diff --git a/examples/storage_namespace/src/main.sw b/examples/storage_namespace/src/main.sw index 40ddb1632a8..7adad8f5cbe 100644 --- a/examples/storage_namespace/src/main.sw +++ b/examples/storage_namespace/src/main.sw @@ -3,10 +3,11 @@ contract; use std::storage::storage_api::{read, write}; // ANCHOR: storage_namespace -#[namespace(example_namespace)] storage { + example_namespace { + foo: u64 = 0, + }, // ANCHOR_END: storage_namespace - foo: u64 = 0, } abi StorageNamespaceExample { diff --git a/forc-pkg/Cargo.toml b/forc-pkg/Cargo.toml index dae1aab96fc..7c5618d4a4e 100644 --- a/forc-pkg/Cargo.toml +++ b/forc-pkg/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "forc-pkg" -version = "0.60.0" +version.workspace = true description = "Building, locking, fetching and updating Sway projects as Forc packages." authors.workspace = true edition.workspace = true @@ -9,40 +9,41 @@ license.workspace = true repository.workspace = true [dependencies] -ansi_term = "0.12" -anyhow = "1" -cid = "0.10" -forc-tracing = { version = "0.60.0", path = "../forc-tracing" } -forc-util = { version = "0.60.0", path = "../forc-util" } -fuel-abi-types = { workspace = true } -futures = "0.3" -git2 = { version = "0.17.2", features = [ +ansi_term.workspace = true +anyhow.workspace = true +byte-unit.workspace = true +cid.workspace = true +forc-tracing.workspace = true +forc-util.workspace = true +fuel-abi-types.workspace = true +futures.workspace = true +git2 = { workspace = true, features = [ "vendored-libgit2", "vendored-openssl", ] } -gix-url = { version = "0.16.0", features = ["serde1"] } -hex = "0.4.3" -ipfs-api-backend-hyper = { version = "0.6", features = ["with-builder"] } -petgraph = { version = "0.6", features = ["serde-1"] } -reqwest = "0.11.7" -semver = { version = "1.0", features = ["serde"] } -serde = { version = "1.0", features = ["derive"] } -serde_ignored = "0.1.9" -serde_json = "1.0" -serde_with = "3.3.0" -sway-core = { version = "0.60.0", path = "../sway-core" } -sway-error = { version = "0.60.0", path = "../sway-error" } -sway-types = { version = "0.60.0", path = "../sway-types" } -sway-utils = { version = "0.60.0", path = "../sway-utils" } -tar = "0.4.38" -toml = { version = "0.7", features = ["parse"] } -tracing = "0.1" -url = { version = "2.2", features = ["serde"] } -vec1 = "1.8.0" -walkdir = "2" +gix-url = { workspace = true, features = ["serde"] } +hex.workspace = true +ipfs-api-backend-hyper = { workspace = true, features = ["with-builder"] } +petgraph = { workspace = true, features = ["serde-1"] } +reqwest.workspace = true +semver = { workspace = true, features = ["serde"] } +serde = { workspace = true, features = ["derive"] } +serde_ignored.workspace = true +serde_json.workspace = true +serde_with.workspace = true +sway-core.workspace = true +sway-error.workspace = true +sway-types.workspace = true +sway-utils.workspace = true +tar.workspace = true +toml = { workspace = true, features = ["parse"] } +tracing.workspace = true +url = { workspace = true, features = ["serde"] } +vec1.workspace = true +walkdir.workspace = true [dev-dependencies] regex = "^1.10.2" [target.'cfg(not(target_os = "macos"))'.dependencies] -sysinfo = "0.29.0" +sysinfo = "0.29" diff --git a/forc-pkg/src/lock.rs b/forc-pkg/src/lock.rs index b44504cf2b7..594c107bc09 100644 --- a/forc-pkg/src/lock.rs +++ b/forc-pkg/src/lock.rs @@ -1,5 +1,6 @@ use crate::{pkg, source, DepKind, Edge}; use anyhow::{anyhow, Result}; +use forc_tracing::{println_action_green, println_action_red}; use petgraph::{visit::EdgeRef, Direction}; use serde::{Deserialize, Serialize}; use std::{ @@ -351,10 +352,9 @@ where true => format!(" {}", pkg.source), false => String::new(), }; - tracing::info!( - " {} {}{src}", - ansi_term::Colour::Red.bold().paint("Removing"), - ansi_term::Style::new().bold().paint(&pkg.name) + println_action_red( + "Removing", + &format!("{}{src}", ansi_term::Style::new().bold().paint(&pkg.name)), ); } } @@ -370,10 +370,9 @@ where true => format!(" {}", pkg.source), false => "".to_string(), }; - tracing::info!( - " {} {}{src}", - ansi_term::Colour::Green.bold().paint("Adding"), - ansi_term::Style::new().bold().paint(&pkg.name) + println_action_green( + "Adding", + &format!("{}{src}", ansi_term::Style::new().bold().paint(&pkg.name)), ); } } diff --git a/forc-pkg/src/manifest/build_profile.rs b/forc-pkg/src/manifest/build_profile.rs index 0922ba59124..59610ee8bf9 100644 --- a/forc-pkg/src/manifest/build_profile.rs +++ b/forc-pkg/src/manifest/build_profile.rs @@ -24,6 +24,8 @@ pub struct BuildProfile { #[serde(default)] pub print_bytecode: bool, #[serde(default)] + pub print_bytecode_spans: bool, + #[serde(default)] pub terse: bool, #[serde(default)] pub time_phases: bool, @@ -32,8 +34,6 @@ pub struct BuildProfile { #[serde(default)] pub include_tests: bool, #[serde(default)] - pub json_abi_with_callpaths: bool, - #[serde(default)] pub error_on_warnings: bool, #[serde(default)] pub reverse_results: bool, @@ -57,11 +57,11 @@ impl BuildProfile { print_ir: PrintIr::default(), print_asm: PrintAsm::default(), print_bytecode: false, + print_bytecode_spans: false, terse: false, time_phases: false, metrics_outfile: None, include_tests: false, - json_abi_with_callpaths: false, error_on_warnings: false, reverse_results: false, optimization_level: OptLevel::Opt0, @@ -80,11 +80,11 @@ impl BuildProfile { print_ir: PrintIr::default(), print_asm: PrintAsm::default(), print_bytecode: false, + print_bytecode_spans: false, terse: false, time_phases: false, metrics_outfile: None, include_tests: false, - json_abi_with_callpaths: false, error_on_warnings: false, reverse_results: false, optimization_level: OptLevel::Opt1, @@ -152,11 +152,11 @@ mod tests { print_ir: PrintIr::r#final(), print_asm: PrintAsm::all(), print_bytecode: true, + print_bytecode_spans: false, terse: true, time_phases: true, metrics_outfile: Some("metrics_outfile".into()), include_tests: true, - json_abi_with_callpaths: true, error_on_warnings: true, reverse_results: true, optimization_level: OptLevel::Opt0, diff --git a/forc-pkg/src/manifest/mod.rs b/forc-pkg/src/manifest/mod.rs index 3f7bc21b1bd..28729aff757 100644 --- a/forc-pkg/src/manifest/mod.rs +++ b/forc-pkg/src/manifest/mod.rs @@ -186,6 +186,7 @@ pub struct PackageManifest { pub build_target: Option>, build_profile: Option>, pub contract_dependencies: Option>, + pub proxy: Option, } #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)] @@ -273,6 +274,17 @@ pub struct DependencyDetails { pub(crate) ipfs: Option, } +/// Describes the details around proxy contract. +#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, Eq)] +#[serde(rename_all = "kebab-case")] +pub struct Proxy { + pub enabled: bool, + /// Points to the proxy contract to be updated with the new contract id. + /// If there is a value for this field, forc will try to update the proxy contract's storage + /// field such that it points to current contract's deployed instance. + pub address: Option, +} + impl DependencyDetails { /// Checks if dependency details reserved for a specific dependency type used without the main /// detail for that type. @@ -650,6 +662,11 @@ impl PackageManifest { .and_then(|patches| patches.get(patch_name)) } + /// Retrieve the proxy table for the package. + pub fn proxy(&self) -> Option<&Proxy> { + self.proxy.as_ref() + } + /// Check for the `core` and `std` packages under `[dependencies]`. If both are missing, add /// `std` implicitly. /// diff --git a/forc-pkg/src/pkg.rs b/forc-pkg/src/pkg.rs index 09b00fa5057..9467b483b2e 100644 --- a/forc-pkg/src/pkg.rs +++ b/forc-pkg/src/pkg.rs @@ -9,12 +9,12 @@ use crate::{ BuildProfile, }; use anyhow::{anyhow, bail, Context, Error, Result}; -use forc_tracing::println_warning; +use byte_unit::{Byte, UnitType}; +use forc_tracing::{println_action_green, println_warning}; use forc_util::{ default_output_directory, find_file_name, kebab_to_snake_case, print_compiling, print_on_failure, print_warnings, }; -use fuel_abi_types::abi::program as program_abi; use petgraph::{ self, dot, visit::{Bfs, Dfs, EdgeRef, Walker}, @@ -241,8 +241,6 @@ pub struct PkgOpts { /// /// By default, this is `/out`. pub output_directory: Option, - /// Outputs json abi with callpath instead of struct and enum names. - pub json_abi_with_callpaths: bool, /// The IPFS node to be used for fetching IPFS sources. pub ipfs_node: IPFSNode, } @@ -262,6 +260,8 @@ pub struct PrintOpts { pub asm: PrintAsm, /// Print the bytecode. This is the final output of the compiler. pub bytecode: bool, + /// Print the original source code together with bytecode. + pub bytecode_spans: bool, /// Print the generated Sway IR (Intermediate Representation). pub ir: PrintIr, /// Output build errors and warnings in reverse order. @@ -282,7 +282,7 @@ pub struct MinifyOpts { type ContractIdConst = String; /// The set of options provided to the `build` functions. -#[derive(Default)] +#[derive(Default, Clone)] pub struct BuildOpts { pub pkg: PkgOpts, pub print: PrintOpts, @@ -315,6 +315,7 @@ pub struct BuildOpts { } /// The set of options to filter type of projects to build in a workspace. +#[derive(Clone)] pub struct MemberFilter { pub build_contracts: bool, pub build_scripts: bool, @@ -497,7 +498,11 @@ impl BuiltPackage { let json_abi_path = output_dir.join(program_abi_stem).with_extension("json"); self.write_json_abi(&json_abi_path, minify)?; - info!(" Bytecode size: {} bytes", self.bytecode.bytes.len()); + debug!( + " Bytecode size: {} bytes ({})", + self.bytecode.bytes.len(), + format_bytecode_size(self.bytecode.bytes.len()) + ); // Additional ops required depending on the program type match self.tree_type { TreeType::Contract => { @@ -531,7 +536,7 @@ impl BuiltPackage { let hash_file_name = format!("{}{}", &pkg_name, SWAY_BIN_HASH_SUFFIX); let hash_path = output_dir.join(hash_file_name); fs::write(hash_path, &bytecode_hash)?; - info!(" Bytecode hash: {}", bytecode_hash); + debug!(" Bytecode hash: {}", bytecode_hash); } _ => (), } @@ -575,8 +580,8 @@ impl BuildPlan { /// /// To do so, it tries to read the manifet file at the target path and creates the plan with /// `BuildPlan::from_lock_and_manifest`. - pub fn from_build_opts(build_options: &BuildOpts) -> Result { - let path = &build_options.pkg.path; + pub fn from_pkg_opts(pkg_options: &PkgOpts) -> Result { + let path = &pkg_options.path; let manifest_dir = if let Some(ref path) = path { PathBuf::from(path) @@ -594,9 +599,9 @@ impl BuildPlan { Self::from_lock_and_manifests( &lock_path, &member_manifests, - build_options.pkg.locked, - build_options.pkg.offline, - &build_options.pkg.ipfs_node, + pkg_options.locked, + pkg_options.offline, + &pkg_options.ipfs_node, ) } @@ -713,7 +718,10 @@ impl BuildPlan { cause, ); } - info!(" Creating a new `Forc.lock` file. (Cause: {})", cause); + println_action_green( + "Creating", + &format!("a new `Forc.lock` file. (Cause: {})", cause), + ); let member_names = manifests .iter() .map(|(_, manifest)| manifest.project.name.to_string()) @@ -723,7 +731,7 @@ impl BuildPlan { .map_err(|e| anyhow!("failed to serialize lock file: {}", e))?; fs::write(lock_path, string) .map_err(|e| anyhow!("failed to write lock file: {}", e))?; - info!(" Created new lock file at {}", lock_path.display()); + debug!(" Created new lock file at {}", lock_path.display()); } Ok(plan) @@ -1549,7 +1557,10 @@ pub fn sway_build_config( .with_print_dca_graph(build_profile.print_dca_graph.clone()) .with_print_dca_graph_url_format(build_profile.print_dca_graph_url_format.clone()) .with_print_asm(build_profile.print_asm) - .with_print_bytecode(build_profile.print_bytecode) + .with_print_bytecode( + build_profile.print_bytecode, + build_profile.print_bytecode_spans, + ) .with_print_ir(build_profile.print_ir.clone()) .with_include_tests(build_profile.include_tests) .with_time_phases(build_profile.time_phases) @@ -1587,18 +1598,19 @@ pub fn dependency_namespace( ) -> Result> { // TODO: Clean this up when config-time constants v1 are removed. let node_idx = &graph[node]; - let name = Some(Ident::new_no_span(node_idx.name.clone())); + let name = Ident::new_no_span(node_idx.name.clone()); let mut root_module = if let Some(contract_id_value) = contract_id_value { - namespace::default_with_contract_id(engines, name.clone(), contract_id_value, experimental)? + namespace::default_with_contract_id( + engines, + name.clone(), + Visibility::Public, + contract_id_value, + experimental, + )? } else { - namespace::Module::default() + namespace::Module::new(name, Visibility::Public, None) }; - root_module.write(engines, |root_module| { - root_module.name.clone_from(&name); - root_module.visibility = Visibility::Public; - }); - // Add direct dependencies. let mut core_added = false; for edge in graph.edges_directed(node, Direction::Outgoing) { @@ -1620,16 +1632,14 @@ pub fn dependency_namespace( // Construct namespace with contract id let contract_id_value = format!("0x{dep_contract_id}"); let node_idx = &graph[dep_node]; - let name = Some(Ident::new_no_span(node_idx.name.clone())); - let mut module = namespace::default_with_contract_id( + let name = Ident::new_no_span(node_idx.name.clone()); + namespace::default_with_contract_id( engines, name.clone(), + Visibility::Private, contract_id_value, experimental, - )?; - module.name = name; - module.visibility = Visibility::Public; - module + )? } }; dep_namespace.is_external = true; @@ -1652,20 +1662,22 @@ pub fn dependency_namespace( let mut root = namespace::Root::from(root_module); if core_added { - let _ = root.star_import_with_reexports( + let _ = root.star_import( &Handler::default(), engines, &[CORE, PRELUDE].map(|s| Ident::new_no_span(s.into())), &[], + Visibility::Private, ); } if has_std_dep(graph, node) { - let _ = root.star_import_with_reexports( + let _ = root.star_import( &Handler::default(), engines, &[STD, PRELUDE].map(|s| Ident::new_no_span(s.into())), &[], + Visibility::Private, ); } @@ -1746,7 +1758,7 @@ pub fn compile( pkg: &PackageDescriptor, profile: &BuildProfile, engines: &Engines, - namespace: namespace::Root, + namespace: &mut namespace::Root, source_map: &mut SourceMap, ) -> Result { let mut metrics = PerformanceData::default(); @@ -1818,29 +1830,38 @@ pub fn compile( metrics ); + const OLD_ENCODING_VERSION: &str = "0"; const NEW_ENCODING_VERSION: &str = "1"; + const SPEC_VERSION: &str = "1"; let mut program_abi = match pkg.target { BuildTarget::Fuel => { - let mut types = vec![]; - ProgramABI::Fuel(time_expr!( + let program_abi_res = time_expr!( "generate JSON ABI program", "generate_json_abi", fuel_abi::generate_program_abi( + &handler, &mut AbiContext { program: typed_program, - abi_with_callpaths: profile.json_abi_with_callpaths, + abi_with_callpaths: true, + type_ids_to_full_type_str: HashMap::::new(), }, engines, - &mut types, profile .experimental .new_encoding - .then(|| NEW_ENCODING_VERSION.into()), + .then(|| NEW_ENCODING_VERSION.into()) + .unwrap_or(OLD_ENCODING_VERSION.into()), + SPEC_VERSION.into(), ), Some(sway_build_config.clone()), metrics - )) + ); + let program_abi = match program_abi_res { + Err(_) => return fail(handler), + Ok(program_abi) => program_abi, + }; + ProgramABI::Fuel(program_abi) } BuildTarget::EVM => { // Merge the ABI output of ASM gen with ABI gen to handle internal constructors @@ -1865,8 +1886,6 @@ pub fn compile( ProgramABI::Evm(ops) } - - BuildTarget::MidenVM => ProgramABI::MidenVM(()), }; let entries = asm_res @@ -2079,13 +2098,13 @@ fn build_profile_from_opts( profile.print_ir |= print.ir.clone(); profile.print_asm |= print.asm; profile.print_bytecode |= print.bytecode; + profile.print_bytecode_spans |= print.bytecode_spans; profile.terse |= pkg.terse; profile.time_phases |= time_phases; if profile.metrics_outfile.is_none() { profile.metrics_outfile.clone_from(metrics_outfile); } profile.include_tests |= tests; - profile.json_abi_with_callpaths |= pkg.json_abi_with_callpaths; profile.error_on_warnings |= error_on_warnings; profile.experimental = ExperimentalFlags { new_encoding: experimental.new_encoding, @@ -2104,6 +2123,12 @@ fn profile_target_string(profile_name: &str, build_target: &BuildTarget) -> Stri }; format!("{profile_name} [{}] target(s)", targets.join(" + ")) } +/// Returns the size of the bytecode in a human-readable format. +pub fn format_bytecode_size(bytes_len: usize) -> String { + let size = Byte::from_u64(bytes_len as u64); + let adjusted_byte = size.get_appropriate_unit(UnitType::Decimal); + adjusted_byte.to_string() +} /// Check if the given node is a contract dependency of any node in the graph. fn is_contract_dependency(graph: &Graph, node: NodeIx) -> bool { @@ -2132,7 +2157,9 @@ pub fn build_with_options(build_options: &BuildOpts) -> Result { .as_ref() .map_or_else(|| current_dir, PathBuf::from); - let build_plan = BuildPlan::from_build_opts(build_options)?; + println_action_green("Building", &path.display().to_string()); + + let build_plan = BuildPlan::from_pkg_opts(&build_options.pkg)?; let graph = build_plan.graph(); let manifest_map = build_plan.manifest_map(); @@ -2170,12 +2197,19 @@ pub fn build_with_options(build_options: &BuildOpts) -> Result { }, )?; let output_dir = pkg.output_directory.as_ref().map(PathBuf::from); - - let finished = ansi_term::Colour::Green.bold().paint("Finished"); - info!( - " {finished} {} in {:.2}s", - profile_target_string(&build_profile.name, build_target), - build_start.elapsed().as_secs_f32() + let total_size = built_packages + .iter() + .map(|(_, pkg)| pkg.bytecode.bytes.len()) + .sum::(); + + println_action_green( + "Finished", + &format!( + "{} [{}] in {:.2}s", + profile_target_string(&build_profile.name, build_target), + format_bytecode_size(total_size), + build_start.elapsed().as_secs_f32() + ), ); for (node_ix, built_package) in built_packages { print_pkg_summary_header(&built_package); @@ -2289,6 +2323,7 @@ pub fn build( let mut lib_namespace_map = HashMap::default(); let mut compiled_contract_deps = HashMap::new(); + for &node in plan .compilation_order .iter() @@ -2343,7 +2378,7 @@ pub fn build( // `ContractIdConst` is a None here since we do not yet have a // contract ID value at this point. - let dep_namespace = match dependency_namespace( + let mut dep_namespace = match dependency_namespace( &lib_namespace_map, &compiled_contract_deps, plan.graph(), @@ -2360,7 +2395,7 @@ pub fn build( &descriptor, &profile, &engines, - dep_namespace, + &mut dep_namespace, &mut source_map, )?; @@ -2407,7 +2442,7 @@ pub fn build( }; // Note that the contract ID value here is only Some if tests are enabled. - let dep_namespace = match dependency_namespace( + let mut dep_namespace = match dependency_namespace( &lib_namespace_map, &compiled_contract_deps, plan.graph(), @@ -2429,11 +2464,11 @@ pub fn build( } }; - let mut compiled = compile( + let compiled = compile( &descriptor, &profile, &engines, - dep_namespace, + &mut dep_namespace, &mut source_map, )?; @@ -2445,18 +2480,10 @@ pub fn build( } if let TreeType::Library = compiled.tree_type { - compiled.root_module.write(&engines, |root_module| { - root_module.name = Some(Ident::new_no_span(pkg.name.clone())); - }); lib_namespace_map.insert(node, compiled.root_module); } source_map.insert_dependency(descriptor.manifest_file.dir()); - // TODO: This should probably be in `fuel_abi_json::generate_json_abi_program`? - if let ProgramABI::Fuel(ref mut program_abi) = compiled.program_abi { - standardize_json_abi_types(program_abi); - } - let built_pkg = BuiltPackage { descriptor, program_abi: compiled.program_abi, @@ -2476,136 +2503,6 @@ pub fn build( Ok(built_packages) } -/// Standardize the JSON ABI data structure by eliminating duplicate types. This is an iterative -/// process because every time two types are merged, new opportunities for more merging arise. -fn standardize_json_abi_types(json_abi_program: &mut program_abi::ProgramABI) { - loop { - // If type with id_1 is a duplicate of type with id_2, then keep track of the mapping - // between id_1 and id_2 in the HashMap below. - let mut old_to_new_id: HashMap = HashMap::new(); - - // A vector containing unique `program_abi::TypeDeclaration`s. - // - // Two `program_abi::TypeDeclaration` are deemed the same if the have the same - // `type_field`, `components`, and `type_parameters` (even if their `type_id`s are - // different). - let mut deduped_types: Vec = Vec::new(); - - // Insert values in `deduped_types` if they haven't been inserted before. Otherwise, create - // an appropriate mapping between type IDs in the HashMap `old_to_new_id`. - for decl in &json_abi_program.types { - if let Some(ty) = deduped_types.iter().find(|d| { - d.type_field == decl.type_field - && d.components == decl.components - && d.type_parameters == decl.type_parameters - }) { - old_to_new_id.insert(decl.type_id, ty.type_id); - } else { - deduped_types.push(decl.clone()); - } - } - - // Nothing to do if the hash map is empty as there are not merge opportunities. We can now - // exit the loop. - if old_to_new_id.is_empty() { - break; - } - - json_abi_program.types = deduped_types; - - // Update all `program_abi::TypeApplication`s and all `program_abi::TypeDeclaration`s - update_all_types(json_abi_program, &old_to_new_id); - } - - // Sort the `program_abi::TypeDeclaration`s - json_abi_program - .types - .sort_by(|t1, t2| t1.type_field.cmp(&t2.type_field)); - - // Standardize IDs (i.e. change them to 0,1,2,... according to the alphabetical order above - let mut old_to_new_id: HashMap = HashMap::new(); - for (ix, decl) in json_abi_program.types.iter_mut().enumerate() { - old_to_new_id.insert(decl.type_id, ix); - decl.type_id = ix; - } - - // Update all `program_abi::TypeApplication`s and all `program_abi::TypeDeclaration`s - update_all_types(json_abi_program, &old_to_new_id); -} - -/// Recursively updates the type IDs used in a program_abi::ProgramABI -fn update_all_types( - json_abi_program: &mut program_abi::ProgramABI, - old_to_new_id: &HashMap, -) { - // Update all `program_abi::TypeApplication`s in every function - for func in &mut json_abi_program.functions { - for input in &mut func.inputs { - update_json_type_application(input, old_to_new_id); - } - - update_json_type_application(&mut func.output, old_to_new_id); - } - - // Update all `program_abi::TypeDeclaration` - for decl in &mut json_abi_program.types { - update_json_type_declaration(decl, old_to_new_id); - } - if let Some(logged_types) = &mut json_abi_program.logged_types { - for logged_type in logged_types { - update_json_type_application(&mut logged_type.application, old_to_new_id); - } - } - if let Some(messages_types) = &mut json_abi_program.messages_types { - for logged_type in messages_types { - update_json_type_application(&mut logged_type.application, old_to_new_id); - } - } - if let Some(configurables) = &mut json_abi_program.configurables { - for logged_type in configurables { - update_json_type_application(&mut logged_type.application, old_to_new_id); - } - } -} - -/// Recursively updates the type IDs used in a `program_abi::TypeApplication` given a HashMap from -/// old to new IDs -fn update_json_type_application( - type_application: &mut program_abi::TypeApplication, - old_to_new_id: &HashMap, -) { - if let Some(new_id) = old_to_new_id.get(&type_application.type_id) { - type_application.type_id = *new_id; - } - - if let Some(args) = &mut type_application.type_arguments { - for arg in args.iter_mut() { - update_json_type_application(arg, old_to_new_id); - } - } -} - -/// Recursively updates the type IDs used in a `program_abi::TypeDeclaration` given a HashMap from -/// old to new IDs -fn update_json_type_declaration( - type_declaration: &mut program_abi::TypeDeclaration, - old_to_new_id: &HashMap, -) { - if let Some(params) = &mut type_declaration.type_parameters { - for param in params.iter_mut() { - if let Some(new_id) = old_to_new_id.get(param) { - *param = *new_id; - } - } - } - - if let Some(components) = &mut type_declaration.components { - for component in components.iter_mut() { - update_json_type_application(component, old_to_new_id); - } - } -} - /// Compile the entire forc package and return the lexed, parsed and typed programs /// of the dependencies and project. /// The final item in the returned vector is the project. @@ -2642,7 +2539,7 @@ pub fn check( let contract_id_value = (idx == plan.compilation_order.len() - 1).then(|| DUMMY_CONTRACT_ID.to_string()); - let dep_namespace = dependency_namespace( + let mut dep_namespace = dependency_namespace( &lib_namespace_map, &compiled_contract_deps, &plan.graph, @@ -2673,7 +2570,7 @@ pub fn check( &handler, engines, input, - dep_namespace, + &mut dep_namespace, Some(&build_config), &pkg.name, retrigger_compilation.clone(), @@ -2701,8 +2598,7 @@ pub fn check( .namespace .program_id(engines) .read(engines, |m| m.clone()); - module.name = Some(Ident::new_no_span(pkg.name.clone())); - module.span = Some( + module.set_span( Span::new( manifest.entry_string()?, 0, diff --git a/forc-pkg/src/source/git/mod.rs b/forc-pkg/src/source/git/mod.rs index fdaf0b8a8b0..a89e77f3128 100644 --- a/forc-pkg/src/source/git/mod.rs +++ b/forc-pkg/src/source/git/mod.rs @@ -6,6 +6,7 @@ use crate::{ source, }; use anyhow::{anyhow, bail, Context, Result}; +use forc_tracing::println_action_green; use forc_util::git_checkouts_directory; use serde::{Deserialize, Serialize}; use std::fmt::Display; @@ -15,7 +16,6 @@ use std::{ path::{Path, PathBuf}, str::FromStr, }; -use tracing::info; #[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd, Deserialize, Serialize)] pub struct Url { @@ -204,11 +204,13 @@ impl source::Fetch for Pinned { { let _guard = lock.write()?; if !repo_path.exists() { - info!( - " {} {} {}", - ansi_term::Color::Green.bold().paint("Fetching"), - ansi_term::Style::new().bold().paint(ctx.name), - self + println_action_green( + "Fetching", + &format!( + "{} {}", + ansi_term::Style::new().bold().paint(ctx.name), + self + ), ); fetch(ctx.fetch_id(), ctx.name(), self)?; } diff --git a/forc-pkg/src/source/ipfs.rs b/forc-pkg/src/source/ipfs.rs index 70dc988588d..1391348834c 100644 --- a/forc-pkg/src/source/ipfs.rs +++ b/forc-pkg/src/source/ipfs.rs @@ -4,6 +4,7 @@ use crate::{ source, }; use anyhow::Result; +use forc_tracing::println_action_green; use futures::TryStreamExt; use ipfs_api::IpfsApi; use ipfs_api_backend_hyper as ipfs_api; @@ -14,7 +15,6 @@ use std::{ str::FromStr, }; use tar::Archive; -use tracing::info; #[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] pub struct Cid(cid::Cid); @@ -67,11 +67,13 @@ impl source::Fetch for Pinned { { let _guard = lock.write()?; if !repo_path.exists() { - info!( - " {} {} {}", - ansi_term::Color::Green.bold().paint("Fetching"), - ansi_term::Style::new().bold().paint(ctx.name), - self + println_action_green( + "Fetching", + &format!( + "{} {}", + ansi_term::Style::new().bold().paint(ctx.name), + self + ), ); let cid = &self.0; let ipfs_client = ipfs_client(); @@ -79,17 +81,16 @@ impl source::Fetch for Pinned { futures::executor::block_on(async { match ctx.ipfs_node() { source::IPFSNode::Local => { - info!( - " {} with local IPFS node", - ansi_term::Color::Green.bold().paint("Fetching") - ); + println_action_green("Fetching", "with local IPFS node"); cid.fetch_with_client(&ipfs_client, &dest).await } source::IPFSNode::WithUrl(ipfs_node_gateway_url) => { - info!( - " {} from {}. Note: This can take several minutes.", - ansi_term::Color::Green.bold().paint("Fetching"), - ipfs_node_gateway_url + println_action_green( + "Fetching", + &format!( + "from {}. Note: This can take several minutes.", + ipfs_node_gateway_url + ), ); cid.fetch_with_gateway_url(ipfs_node_gateway_url, &dest) .await @@ -136,7 +137,7 @@ impl Cid { /// Using local node, fetches the content described by this cid. async fn fetch_with_client(&self, ipfs_client: &IpfsClient, dst: &Path) -> Result<()> { let cid_path = format!("/ipfs/{}", self.0); - // Since we are fetching packages as a fodler, they are returned as a tar archive. + // Since we are fetching packages as a folder, they are returned as a tar archive. let bytes = ipfs_client .get(&cid_path) .map_ok(|chunk| chunk.to_vec()) diff --git a/forc-pkg/tests/sections/Forc.toml b/forc-pkg/tests/sections/Forc.toml index e4d70be8857..88b012cd138 100644 --- a/forc-pkg/tests/sections/Forc.toml +++ b/forc-pkg/tests/sections/Forc.toml @@ -17,7 +17,6 @@ terse = true time-phases = true metrics-outfile = "metrics_outfile" include-tests = true -json-abi-with-callpaths = true error-on-warnings = true reverse-results = true optimization-level = 0 diff --git a/forc-plugins/forc-client/Cargo.toml b/forc-plugins/forc-client/Cargo.toml index 521c6e03f13..ee1b03ea173 100644 --- a/forc-plugins/forc-client/Cargo.toml +++ b/forc-plugins/forc-client/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "forc-client" -version = "0.60.0" +version.workspace = true description = "A `forc` plugin for interacting with a Fuel node." authors.workspace = true edition.workspace = true @@ -9,36 +9,51 @@ license.workspace = true repository.workspace = true [dependencies] -anyhow = "1" -async-trait = "0.1.58" -chrono = { version = "0.4", default-features = false, features = ["std"] } -clap = { version = "4.5.4", features = ["derive", "env"] } -devault = "0.1" -forc = { version = "0.60.0", path = "../../forc" } -forc-pkg = { version = "0.60.0", path = "../../forc-pkg" } -forc-tracing = { version = "0.60.0", path = "../../forc-tracing" } -forc-tx = { version = "0.60.0", path = "../forc-tx" } -forc-util = { version = "0.60.0", path = "../../forc-util" } -forc-wallet = { workspace = true } -fuel-abi-types = { workspace = true } +anyhow.workspace = true +async-trait.workspace = true +aws-config.workspace = true +aws-sdk-kms.workspace = true +chrono = { workspace = true, features = ["std"] } +clap = { workspace = true, features = ["derive", "env"] } +devault.workspace = true +dialoguer.workspace = true +forc.workspace = true +forc-pkg.workspace = true +forc-tracing.workspace = true +forc-tx.workspace = true +forc-util.workspace = true +forc-wallet.workspace = true +fuel-abi-types.workspace = true fuel-core-client = { workspace = true, features = ["subscriptions"] } -fuel-core-types = { workspace = true } -fuel-crypto = { workspace = true } +fuel-core-types.workspace = true +fuel-crypto.workspace = true fuel-tx = { workspace = true, features = ["test-helpers"] } -fuel-vm = { workspace = true } -fuels-accounts = { workspace = true } -fuels-core = { workspace = true } -futures = "0.3" -hex = "0.4.3" -rand = "0.8" -rpassword = "7.2" -serde = "1.0" -serde_json = "1" -sway-core = { version = "0.60.0", path = "../../sway-core" } -sway-types = { version = "0.60.0", path = "../../sway-types" } -sway-utils = { version = "0.60.0", path = "../../sway-utils" } -tokio = { version = "1.8", features = ["macros", "rt-multi-thread", "process"] } -tracing = "0.1" +fuel-vm.workspace = true +fuels.workspace = true +fuels-accounts.workspace = true +fuels-core.workspace = true +futures.workspace = true +hex.workspace = true +k256.workspace = true +rand.workspace = true +rpassword.workspace = true +serde.workspace = true +serde_json.workspace = true +sway-core.workspace = true +sway-types.workspace = true +sway-utils.workspace = true +tokio = { workspace = true, features = ["macros", "process", "rt-multi-thread"] } +toml_edit.workspace = true +tracing.workspace = true + +[dev-dependencies] +portpicker = "0.1.1" +pretty_assertions = "1.4.1" +rexpect = "0.5" +tempfile = "3" + +[build-dependencies] +regex = "1.5.4" [[bin]] name = "forc-deploy" diff --git a/forc-plugins/forc-client/build.rs b/forc-plugins/forc-client/build.rs new file mode 100644 index 00000000000..00e28aaef3a --- /dev/null +++ b/forc-plugins/forc-client/build.rs @@ -0,0 +1,79 @@ +use std::fs; +use std::path::{Path, PathBuf}; + +fn minify_json(json: &str) -> String { + let mut result = String::with_capacity(json.len()); + let mut in_string = false; + let mut previous_char: Option = None; + + for c in json.chars() { + if in_string { + result.push(c); + if c == '"' && previous_char != Some('\\') { + in_string = false; + } + } else { + match c { + '"' => { + result.push(c); + in_string = true; + } + ' ' | '\n' | '\r' | '\t' => continue, // Skip whitespace + _ => result.push(c), + } + } + previous_char = Some(c); + } + result +} + +fn update_proxy_abi_decl_with_file(source_file_path: &Path, minified_json: &str) { + // Read the contents of the source file + let mut source_code = fs::read_to_string(source_file_path).expect("Unable to read source file"); + + // Prepare the replacement string for the `abigen!` macro + let escaped_json = minified_json.replace('\\', "\\\\").replace('"', "\\\""); + let new_abigen = format!( + "abigen!(Contract(name = \"ProxyContract\", abi = \"{}\",));", + escaped_json + ); + + // Use a regular expression to find and replace the `abigen!` macro + let re = regex::Regex::new(r#"abigen!\(Contract\(name = "ProxyContract", abi = ".*?",\)\);"#) + .expect("Invalid regex pattern"); + + // Replace the existing `abigen!` macro with the new one containing the updated ABI + if re.is_match(&source_code) { + source_code = re.replace(&source_code, new_abigen.as_str()).to_string(); + } else { + panic!("abigen! macro not found in the source file"); + } + + // Write the modified source code back to the source file + fs::write(source_file_path, source_code).expect("Unable to write back to the source file"); +} + +fn main() { + // Path to the JSON file in the root directory next to the `src` folder + let json_path = PathBuf::from("proxy_abi/proxy_contract-abi.json"); + // Read the contents of the JSON file + let json_content = + fs::read_to_string(json_path).expect("Unable to read proxy_contract-abi.json"); + + // Minify the JSON content + let minified_json = minify_json(&json_content); + + // If proxy_contract-abi.json is changed, re-run this script + println!("cargo:rerun-if-changed=proxy_abi/proxy_contract-abi.json"); + + // Path to the Rust source file that contains the `abigen!` macro that + // creates a `ProxyContract`. + let util_tx_path = PathBuf::from("src/util/tx.rs"); + update_proxy_abi_decl_with_file(&util_tx_path, &minified_json); + + let test_path = PathBuf::from("tests/deploy.rs"); + update_proxy_abi_decl_with_file(&test_path, &minified_json); + + let deploy_path = PathBuf::from("src/op/deploy.rs"); + update_proxy_abi_decl_with_file(&deploy_path, &minified_json); +} diff --git a/forc-plugins/forc-client/proxy_abi/README.md b/forc-plugins/forc-client/proxy_abi/README.md new file mode 100644 index 00000000000..684e8ceff17 --- /dev/null +++ b/forc-plugins/forc-client/proxy_abi/README.md @@ -0,0 +1,8 @@ +# Proxy Contract + +This folder contains pre-built version of the owned proxy contract, its abi and `storage-slots.json` file. + +*contract url*: [sway-standard-implementation/src-14/owned_proxy](https://github.com/FuelLabs/sway-standard-implementations/tree/174f5ed9c79c23a6aaf5db906fe27ecdb29c22eb). +*commit hash*: `174f5ed9c79c23a6aaf5db906fe27ecdb29c22eb` +*forc version*: `v0.63.6` +*build command*: `forc build --release` diff --git a/forc-plugins/forc-client/proxy_abi/proxy_contract-abi.json b/forc-plugins/forc-client/proxy_abi/proxy_contract-abi.json new file mode 100644 index 00000000000..9fa09e507ba --- /dev/null +++ b/forc-plugins/forc-client/proxy_abi/proxy_contract-abi.json @@ -0,0 +1,724 @@ +{ + "programType": "contract", + "specVersion": "1", + "encodingVersion": "1", + "concreteTypes": [ + { + "type": "()", + "concreteTypeId": "2e38e77b22c314a449e91fafed92a43826ac6aa403ae6a8acb6cf58239fbaf5d" + }, + { + "type": "enum standards::src5::AccessError", + "concreteTypeId": "3f702ea3351c9c1ece2b84048006c8034a24cbc2bad2e740d0412b4172951d3d", + "metadataTypeId": 1 + }, + { + "type": "enum standards::src5::State", + "concreteTypeId": "192bc7098e2fe60635a9918afb563e4e5419d386da2bdbf0d716b4bc8549802c", + "metadataTypeId": 2 + }, + { + "type": "enum std::option::Option", + "concreteTypeId": "0d79387ad3bacdc3b7aad9da3a96f4ce60d9a1b6002df254069ad95a3931d5c8", + "metadataTypeId": 4, + "typeArguments": [ + "29c10735d33b5159f0c71ee1dbd17b36a3e69e41f00fab0d42e1bd9f428d8a54" + ] + }, + { + "type": "enum sway_libs::ownership::errors::InitializationError", + "concreteTypeId": "1dfe7feadc1d9667a4351761230f948744068a090fe91b1bc6763a90ed5d3893", + "metadataTypeId": 5 + }, + { + "type": "enum sway_libs::upgradability::errors::SetProxyOwnerError", + "concreteTypeId": "3c6e90ae504df6aad8b34a93ba77dc62623e00b777eecacfa034a8ac6e890c74", + "metadataTypeId": 6 + }, + { + "type": "str", + "concreteTypeId": "8c25cb3686462e9a86d2883c5688a22fe738b0bbc85f458d2d2b5f3f667c6d5a" + }, + { + "type": "struct std::contract_id::ContractId", + "concreteTypeId": "29c10735d33b5159f0c71ee1dbd17b36a3e69e41f00fab0d42e1bd9f428d8a54", + "metadataTypeId": 9 + }, + { + "type": "struct sway_libs::upgradability::events::ProxyOwnerSet", + "concreteTypeId": "96dd838b44f99d8ccae2a7948137ab6256c48ca4abc6168abc880de07fba7247", + "metadataTypeId": 10 + }, + { + "type": "struct sway_libs::upgradability::events::ProxyTargetSet", + "concreteTypeId": "1ddc0adda1270a016c08ffd614f29f599b4725407c8954c8b960bdf651a9a6c8", + "metadataTypeId": 11 + } + ], + "metadataTypes": [ + { + "type": "b256", + "metadataTypeId": 0 + }, + { + "type": "enum standards::src5::AccessError", + "metadataTypeId": 1, + "components": [ + { + "name": "NotOwner", + "typeId": "2e38e77b22c314a449e91fafed92a43826ac6aa403ae6a8acb6cf58239fbaf5d" + } + ] + }, + { + "type": "enum standards::src5::State", + "metadataTypeId": 2, + "components": [ + { + "name": "Uninitialized", + "typeId": "2e38e77b22c314a449e91fafed92a43826ac6aa403ae6a8acb6cf58239fbaf5d" + }, + { + "name": "Initialized", + "typeId": 3 + }, + { + "name": "Revoked", + "typeId": "2e38e77b22c314a449e91fafed92a43826ac6aa403ae6a8acb6cf58239fbaf5d" + } + ] + }, + { + "type": "enum std::identity::Identity", + "metadataTypeId": 3, + "components": [ + { + "name": "Address", + "typeId": 8 + }, + { + "name": "ContractId", + "typeId": 9 + } + ] + }, + { + "type": "enum std::option::Option", + "metadataTypeId": 4, + "components": [ + { + "name": "None", + "typeId": "2e38e77b22c314a449e91fafed92a43826ac6aa403ae6a8acb6cf58239fbaf5d" + }, + { + "name": "Some", + "typeId": 7 + } + ], + "typeParameters": [ + 7 + ] + }, + { + "type": "enum sway_libs::ownership::errors::InitializationError", + "metadataTypeId": 5, + "components": [ + { + "name": "CannotReinitialized", + "typeId": "2e38e77b22c314a449e91fafed92a43826ac6aa403ae6a8acb6cf58239fbaf5d" + } + ] + }, + { + "type": "enum sway_libs::upgradability::errors::SetProxyOwnerError", + "metadataTypeId": 6, + "components": [ + { + "name": "CannotUninitialize", + "typeId": "2e38e77b22c314a449e91fafed92a43826ac6aa403ae6a8acb6cf58239fbaf5d" + } + ] + }, + { + "type": "generic T", + "metadataTypeId": 7 + }, + { + "type": "struct std::address::Address", + "metadataTypeId": 8, + "components": [ + { + "name": "bits", + "typeId": 0 + } + ] + }, + { + "type": "struct std::contract_id::ContractId", + "metadataTypeId": 9, + "components": [ + { + "name": "bits", + "typeId": 0 + } + ] + }, + { + "type": "struct sway_libs::upgradability::events::ProxyOwnerSet", + "metadataTypeId": 10, + "components": [ + { + "name": "new_proxy_owner", + "typeId": 2 + } + ] + }, + { + "type": "struct sway_libs::upgradability::events::ProxyTargetSet", + "metadataTypeId": 11, + "components": [ + { + "name": "new_target", + "typeId": 9 + } + ] + } + ], + "functions": [ + { + "inputs": [], + "name": "proxy_target", + "output": "0d79387ad3bacdc3b7aad9da3a96f4ce60d9a1b6002df254069ad95a3931d5c8", + "attributes": [ + { + "name": "doc-comment", + "arguments": [ + " Returns the target contract of the proxy contract." + ] + }, + { + "name": "doc-comment", + "arguments": [ + "" + ] + }, + { + "name": "doc-comment", + "arguments": [ + " # Returns" + ] + }, + { + "name": "doc-comment", + "arguments": [ + "" + ] + }, + { + "name": "doc-comment", + "arguments": [ + " * [Option] - The new proxy contract to which all fallback calls will be passed or `None`." + ] + }, + { + "name": "doc-comment", + "arguments": [ + "" + ] + }, + { + "name": "doc-comment", + "arguments": [ + " # Number of Storage Accesses" + ] + }, + { + "name": "doc-comment", + "arguments": [ + "" + ] + }, + { + "name": "doc-comment", + "arguments": [ + " * Reads: `1`" + ] + }, + { + "name": "storage", + "arguments": [ + "read" + ] + } + ] + }, + { + "inputs": [ + { + "name": "new_target", + "concreteTypeId": "29c10735d33b5159f0c71ee1dbd17b36a3e69e41f00fab0d42e1bd9f428d8a54" + } + ], + "name": "set_proxy_target", + "output": "2e38e77b22c314a449e91fafed92a43826ac6aa403ae6a8acb6cf58239fbaf5d", + "attributes": [ + { + "name": "doc-comment", + "arguments": [ + " Change the target contract of the proxy contract." + ] + }, + { + "name": "doc-comment", + "arguments": [ + "" + ] + }, + { + "name": "doc-comment", + "arguments": [ + " # Additional Information" + ] + }, + { + "name": "doc-comment", + "arguments": [ + "" + ] + }, + { + "name": "doc-comment", + "arguments": [ + " This method can only be called by the `proxy_owner`." + ] + }, + { + "name": "doc-comment", + "arguments": [ + "" + ] + }, + { + "name": "doc-comment", + "arguments": [ + " # Arguments" + ] + }, + { + "name": "doc-comment", + "arguments": [ + "" + ] + }, + { + "name": "doc-comment", + "arguments": [ + " * `new_target`: [ContractId] - The new proxy contract to which all fallback calls will be passed." + ] + }, + { + "name": "doc-comment", + "arguments": [ + "" + ] + }, + { + "name": "doc-comment", + "arguments": [ + " # Reverts" + ] + }, + { + "name": "doc-comment", + "arguments": [ + "" + ] + }, + { + "name": "doc-comment", + "arguments": [ + " * When not called by `proxy_owner`." + ] + }, + { + "name": "doc-comment", + "arguments": [ + "" + ] + }, + { + "name": "doc-comment", + "arguments": [ + " # Number of Storage Accesses" + ] + }, + { + "name": "doc-comment", + "arguments": [ + "" + ] + }, + { + "name": "doc-comment", + "arguments": [ + " * Reads: `1`" + ] + }, + { + "name": "doc-comment", + "arguments": [ + " * Write: `1`" + ] + }, + { + "name": "storage", + "arguments": [ + "read", + "write" + ] + } + ] + }, + { + "inputs": [], + "name": "proxy_owner", + "output": "192bc7098e2fe60635a9918afb563e4e5419d386da2bdbf0d716b4bc8549802c", + "attributes": [ + { + "name": "doc-comment", + "arguments": [ + " Returns the owner of the proxy contract." + ] + }, + { + "name": "doc-comment", + "arguments": [ + "" + ] + }, + { + "name": "doc-comment", + "arguments": [ + " # Returns" + ] + }, + { + "name": "doc-comment", + "arguments": [ + "" + ] + }, + { + "name": "doc-comment", + "arguments": [ + " * [State] - Represents the state of ownership for this contract." + ] + }, + { + "name": "doc-comment", + "arguments": [ + "" + ] + }, + { + "name": "doc-comment", + "arguments": [ + " # Number of Storage Accesses" + ] + }, + { + "name": "doc-comment", + "arguments": [ + "" + ] + }, + { + "name": "doc-comment", + "arguments": [ + " * Reads: `1`" + ] + }, + { + "name": "storage", + "arguments": [ + "read" + ] + } + ] + }, + { + "inputs": [], + "name": "initialize_proxy", + "output": "2e38e77b22c314a449e91fafed92a43826ac6aa403ae6a8acb6cf58239fbaf5d", + "attributes": [ + { + "name": "doc-comment", + "arguments": [ + " Initializes the proxy contract." + ] + }, + { + "name": "doc-comment", + "arguments": [ + "" + ] + }, + { + "name": "doc-comment", + "arguments": [ + " # Additional Information" + ] + }, + { + "name": "doc-comment", + "arguments": [ + "" + ] + }, + { + "name": "doc-comment", + "arguments": [ + " This method sets the storage values using the values of the configurable constants `INITIAL_TARGET` and `INITIAL_OWNER`." + ] + }, + { + "name": "doc-comment", + "arguments": [ + " This then allows methods that write to storage to be called." + ] + }, + { + "name": "doc-comment", + "arguments": [ + " This method can only be called once." + ] + }, + { + "name": "doc-comment", + "arguments": [ + "" + ] + }, + { + "name": "doc-comment", + "arguments": [ + " # Reverts" + ] + }, + { + "name": "doc-comment", + "arguments": [ + "" + ] + }, + { + "name": "doc-comment", + "arguments": [ + " * When `storage::SRC14.proxy_owner` is not [State::Uninitialized]." + ] + }, + { + "name": "doc-comment", + "arguments": [ + "" + ] + }, + { + "name": "doc-comment", + "arguments": [ + " # Number of Storage Accesses" + ] + }, + { + "name": "doc-comment", + "arguments": [ + "" + ] + }, + { + "name": "doc-comment", + "arguments": [ + " * Writes: `2`" + ] + }, + { + "name": "storage", + "arguments": [ + "write" + ] + } + ] + }, + { + "inputs": [ + { + "name": "new_proxy_owner", + "concreteTypeId": "192bc7098e2fe60635a9918afb563e4e5419d386da2bdbf0d716b4bc8549802c" + } + ], + "name": "set_proxy_owner", + "output": "2e38e77b22c314a449e91fafed92a43826ac6aa403ae6a8acb6cf58239fbaf5d", + "attributes": [ + { + "name": "doc-comment", + "arguments": [ + " Changes proxy ownership to the passed State." + ] + }, + { + "name": "doc-comment", + "arguments": [ + "" + ] + }, + { + "name": "doc-comment", + "arguments": [ + " # Additional Information" + ] + }, + { + "name": "doc-comment", + "arguments": [ + "" + ] + }, + { + "name": "doc-comment", + "arguments": [ + " This method can be used to transfer ownership between Identities or to revoke ownership." + ] + }, + { + "name": "doc-comment", + "arguments": [ + "" + ] + }, + { + "name": "doc-comment", + "arguments": [ + " # Arguments" + ] + }, + { + "name": "doc-comment", + "arguments": [ + "" + ] + }, + { + "name": "doc-comment", + "arguments": [ + " * `new_proxy_owner`: [State] - The new state of the proxy ownership." + ] + }, + { + "name": "doc-comment", + "arguments": [ + "" + ] + }, + { + "name": "doc-comment", + "arguments": [ + " # Reverts" + ] + }, + { + "name": "doc-comment", + "arguments": [ + "" + ] + }, + { + "name": "doc-comment", + "arguments": [ + " * When the sender is not the current proxy owner." + ] + }, + { + "name": "doc-comment", + "arguments": [ + " * When the new state of the proxy ownership is [State::Uninitialized]." + ] + }, + { + "name": "doc-comment", + "arguments": [ + "" + ] + }, + { + "name": "doc-comment", + "arguments": [ + " # Number of Storage Accesses" + ] + }, + { + "name": "doc-comment", + "arguments": [ + "" + ] + }, + { + "name": "doc-comment", + "arguments": [ + " * Reads: `1`" + ] + }, + { + "name": "doc-comment", + "arguments": [ + " * Writes: `1`" + ] + }, + { + "name": "storage", + "arguments": [ + "write" + ] + } + ] + } + ], + "loggedTypes": [ + { + "logId": "4571204900286667806", + "concreteTypeId": "3f702ea3351c9c1ece2b84048006c8034a24cbc2bad2e740d0412b4172951d3d" + }, + { + "logId": "2151606668983994881", + "concreteTypeId": "1ddc0adda1270a016c08ffd614f29f599b4725407c8954c8b960bdf651a9a6c8" + }, + { + "logId": "2161305517876418151", + "concreteTypeId": "1dfe7feadc1d9667a4351761230f948744068a090fe91b1bc6763a90ed5d3893" + }, + { + "logId": "4354576968059844266", + "concreteTypeId": "3c6e90ae504df6aad8b34a93ba77dc62623e00b777eecacfa034a8ac6e890c74" + }, + { + "logId": "10870989709723147660", + "concreteTypeId": "96dd838b44f99d8ccae2a7948137ab6256c48ca4abc6168abc880de07fba7247" + }, + { + "logId": "10098701174489624218", + "concreteTypeId": "8c25cb3686462e9a86d2883c5688a22fe738b0bbc85f458d2d2b5f3f667c6d5a" + } + ], + "messagesTypes": [], + "configurables": [ + { + "name": "INITIAL_TARGET", + "concreteTypeId": "0d79387ad3bacdc3b7aad9da3a96f4ce60d9a1b6002df254069ad95a3931d5c8", + "offset": 13368 + }, + { + "name": "INITIAL_OWNER", + "concreteTypeId": "192bc7098e2fe60635a9918afb563e4e5419d386da2bdbf0d716b4bc8549802c", + "offset": 13320 + } + ] +} \ No newline at end of file diff --git a/forc-plugins/forc-client/proxy_abi/proxy_contract-storage_slots.json b/forc-plugins/forc-client/proxy_abi/proxy_contract-storage_slots.json new file mode 100644 index 00000000000..72849c97055 --- /dev/null +++ b/forc-plugins/forc-client/proxy_abi/proxy_contract-storage_slots.json @@ -0,0 +1,18 @@ +[ + { + "key": "7bb458adc1d118713319a5baa00a2d049dd64d2916477d2688d76970c898cd55", + "value": "0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "key": "7bb458adc1d118713319a5baa00a2d049dd64d2916477d2688d76970c898cd56", + "value": "0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "key": "bb79927b15d9259ea316f2ecb2297d6cc8851888a98278c0a2e03e1a091ea754", + "value": "0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "key": "bb79927b15d9259ea316f2ecb2297d6cc8851888a98278c0a2e03e1a091ea755", + "value": "0000000000000000000000000000000000000000000000000000000000000000" + } +] \ No newline at end of file diff --git a/forc-plugins/forc-client/proxy_abi/proxy_contract.bin b/forc-plugins/forc-client/proxy_abi/proxy_contract.bin new file mode 100644 index 00000000000..9ce27196250 Binary files /dev/null and b/forc-plugins/forc-client/proxy_abi/proxy_contract.bin differ diff --git a/forc-plugins/forc-client/src/cmd/deploy.rs b/forc-plugins/forc-client/src/cmd/deploy.rs index cf1f26e2a2e..87428dfbca7 100644 --- a/forc-plugins/forc-client/src/cmd/deploy.rs +++ b/forc-plugins/forc-client/src/cmd/deploy.rs @@ -10,7 +10,7 @@ forc_util::cli_examples! { super::Command { [ Deploy a single contract => "forc deploy bc09bfa7a11a04ce42b0a5abf04fd437387ee49bf4561d575177e2946468b408" ] [ Deploy a single contract from a different path => "forc deploy bc09bfa7a11a04ce42b0a5abf04fd437387ee49bf4561d575177e2946468b408 --path {path}" ] - [ Deploy to a custom network => "forc deploy --node-url https://beta-5.fuel.network/graphql" ] + [ Deploy to a custom network => "forc deploy --node-url https://testnet.fuel.network/graphql" ] } } @@ -55,6 +55,9 @@ pub struct Command { /// Deprecated in favor of `--default-signer`. #[clap(long)] pub unsigned: bool, + /// Submit the deployment transaction(s) without waiting for execution to complete. + #[clap(long)] + pub submit_only: bool, /// Set the key to be used for signing. pub signing_key: Option, /// Sign the deployment transaction manually. @@ -84,4 +87,8 @@ pub struct Command { /// Disable the "new encoding" feature #[clap(long)] pub no_encoding_v1: bool, + + /// AWS KMS signer arn. If present forc-deploy will automatically use AWS KMS signer instead of forc-wallet. + #[clap(long)] + pub aws_kms_signer: Option, } diff --git a/forc-plugins/forc-client/src/cmd/run.rs b/forc-plugins/forc-client/src/cmd/run.rs index e23d9f6cb43..5875b270adc 100644 --- a/forc-plugins/forc-client/src/cmd/run.rs +++ b/forc-plugins/forc-client/src/cmd/run.rs @@ -52,9 +52,6 @@ pub struct Command { pub unsigned: bool, /// Set the key to be used for signing. pub signing_key: Option, - /// Sign the deployment transaction manually. - #[clap(long)] - pub manual_signing: bool, /// Arguments to pass into main function with forc run. #[clap(long)] pub args: Option>, diff --git a/forc-plugins/forc-client/src/constants.rs b/forc-plugins/forc-client/src/constants.rs index bd946af2f44..1b195f733e6 100644 --- a/forc-plugins/forc-client/src/constants.rs +++ b/forc-plugins/forc-client/src/constants.rs @@ -1,14 +1,15 @@ /// Default to localhost to favour the common case of testing. pub const NODE_URL: &str = sway_utils::constants::DEFAULT_NODE_URL; -pub const BETA_2_ENDPOINT_URL: &str = "https://node-beta-2.fuel.network"; -pub const BETA_3_ENDPOINT_URL: &str = "https://beta-3.fuel.network"; -pub const BETA_4_ENDPOINT_URL: &str = "https://beta-4.fuel.network"; -pub const BETA_5_ENDPOINT_URL: &str = "https://beta-5.fuel.network"; -pub const BETA_2_FAUCET_URL: &str = "https://faucet-beta-2.fuel.network"; -pub const BETA_3_FAUCET_URL: &str = "https://faucet-beta-3.fuel.network"; -pub const BETA_4_FAUCET_URL: &str = "https://faucet-beta-4.fuel.network"; -pub const BETA_5_FAUCET_URL: &str = "https://faucet-beta-5.fuel.network"; -pub const DEVNET_FAUCET_URL: &str = "https://faucet-devnet.fuel.network"; -pub const DEVNET_ENDPOINT_URL: &str = "https://devnet.fuel.network"; -pub const TESTNET_FAUCET_URL: &str = "https://faucet-testnet.fuel.network"; pub const TESTNET_ENDPOINT_URL: &str = "https://testnet.fuel.network"; +pub const MAINNET_ENDPOINT_URL: &str = "https://mainnet.fuel.network"; + +pub const TESTNET_FAUCET_URL: &str = "https://faucet-testnet.fuel.network"; + +pub const TESTNET_EXPLORER_URL: &str = "https://app-testnet.fuel.network"; +pub const MAINNET_EXPLORER_URL: &str = "https://app.fuel.network"; + +/// Default PrivateKey to sign transactions submitted to local node. +pub const DEFAULT_PRIVATE_KEY: &str = + "0xde97d8624a438121b86a1956544bd72ed68cd69f2c99555b08b1e8c51ffd511c"; +/// The maximum time to wait for a transaction to be included in a block by the node +pub const TX_SUBMIT_TIMEOUT_MS: u64 = 30_000u64; diff --git a/forc-plugins/forc-client/src/lib.rs b/forc-plugins/forc-client/src/lib.rs index 0c8cb335f5f..a4db6b262a1 100644 --- a/forc-plugins/forc-client/src/lib.rs +++ b/forc-plugins/forc-client/src/lib.rs @@ -1,7 +1,7 @@ pub mod cmd; -mod constants; +pub mod constants; pub mod op; -mod util; +pub mod util; use clap::Parser; use serde::{Deserialize, Serialize}; @@ -14,19 +14,27 @@ pub struct NodeTarget { /// If unspecified, checks the manifest's `network` table, then falls back /// to `http://127.0.0.1:4000` /// - /// You can also use `--target` or `--testnet` to specify the Fuel node. + /// You can also use `--target`, `--testnet`, or `--mainnet` to specify the Fuel node. #[clap(long, env = "FUEL_NODE_URL")] pub node_url: Option, + /// Use preset configurations for deploying to a specific target. /// - /// You can also use `--node-url` or `--testnet` to specify the Fuel node. + /// You can also use `--node-url`, `--testnet`, or `--mainnet` to specify the Fuel node. /// - /// Possible values are: [beta-1, beta-2, beta-3, beta-4, local] + /// Possible values are: [local, testnet, mainnet] #[clap(long)] pub target: Option, - /// Use preset configuration for the latest testnet. + + /// Use preset configuration for testnet. /// - /// You can also use `--node-url` or `--target` to specify the Fuel node. + /// You can also use `--node-url`, `--target`, or `--mainnet` to specify the Fuel node. #[clap(long)] pub testnet: bool, + + /// Use preset configuration for mainnet. + /// + /// You can also use `--node-url`, `--target`, or `--testnet` to specify the Fuel node. + #[clap(long)] + pub mainnet: bool, } diff --git a/forc-plugins/forc-client/src/op/deploy.rs b/forc-plugins/forc-client/src/op/deploy.rs index e0270fa5245..cdc5d35162c 100644 --- a/forc-plugins/forc-client/src/op/deploy.rs +++ b/forc-plugins/forc-client/src/op/deploy.rs @@ -1,38 +1,83 @@ use crate::{ cmd, + constants::TX_SUBMIT_TIMEOUT_MS, util::{ - gas::get_estimated_max_fee, + account::ForcClientAccount, node_url::get_node_url, - pkg::built_pkgs, - tx::{TransactionBuilderExt, WalletSelectionMode, TX_SUBMIT_TIMEOUT_MS}, + pkg::{built_pkgs, create_proxy_contract, update_proxy_address_in_manifest}, + target::Target, + tx::{ + prompt_forc_wallet_password, select_account, update_proxy_contract_target, + SignerSelectionMode, + }, }, }; use anyhow::{bail, Context, Result}; -use forc_pkg::manifest::GenericManifestFile; use forc_pkg::{self as pkg, PackageManifestFile}; -use forc_tracing::println_warning; +use forc_pkg::{manifest::GenericManifestFile, MemberFilter}; +use forc_tracing::{println_action_green, println_warning}; use forc_util::default_output_directory; -use fuel_core_client::client::types::TransactionStatus; +use forc_wallet::utils::default_wallet_path; +use fuel_abi_types::abi::program::Configurable; +use fuel_core_client::client::types::{ChainInfo, TransactionStatus}; use fuel_core_client::client::FuelClient; use fuel_crypto::fuel_types::ChainId; -use fuel_tx::{Output, Salt, TransactionBuilder}; -use fuel_vm::prelude::*; -use fuels_accounts::provider::Provider; +use fuel_tx::{Salt, Transaction}; +use fuel_vm::{consts::WORD_SIZE, fuel_asm::op, prelude::*}; +use fuels::{ + macros::abigen, + programs::{ + contract::{LoadConfiguration, StorageConfiguration}, + executable::Executable, + }, + types::{ + bech32::Bech32ContractId, + transaction_builders::{Blob, BlobId}, + }, +}; +use fuels_accounts::{provider::Provider, Account, ViewOnlyAccount}; +use fuels_core::types::{transaction::TxPolicies, transaction_builders::CreateTransactionBuilder}; use futures::FutureExt; use pkg::{manifest::build_profile::ExperimentalFlags, BuildProfile, BuiltPackage}; use serde::{Deserialize, Serialize}; -use std::time::Duration; use std::{ collections::BTreeMap, path::{Path, PathBuf}, + str::FromStr, + sync::Arc, + time::Duration, }; -use sway_core::language::parsed::TreeType; use sway_core::BuildTarget; -use tracing::info; +use sway_core::{asm_generation::ProgramABI, language::parsed::TreeType}; + +/// Default maximum contract size allowed for a single contract. If the target +/// contract size is bigger than this amount, forc-deploy will automatically +/// starts dividing the contract and deploy them in chunks automatically. +/// The value is in bytes +const MAX_CONTRACT_SIZE: usize = 100_000; + +/// Represents a deployed instance of a forc package. +/// Packages other than libraries are deployable through different mechanisms. +#[derive(Debug, PartialEq, Eq, Clone)] +pub enum DeployedPackage { + Contract(DeployedContract), + Script(DeployedExecutable), + Predicate(DeployedExecutable), +} -#[derive(Debug)] +/// Represents a deployed contract on the Fuel network. +#[derive(Debug, PartialEq, Eq, Clone, PartialOrd, Ord)] pub struct DeployedContract { pub id: fuel_tx::ContractId, + pub proxy: Option, + pub chunked: bool, +} + +/// Represents a deployed executable (script or predicate) on the Fuel network. +/// Executables are deployed as blobs with generated loaders for efficiency. +#[derive(Debug, PartialEq, Eq, Clone, PartialOrd, Ord)] +pub struct DeployedExecutable { + pub bytecode: Vec, } #[derive(Debug, Clone, Serialize, Deserialize)] @@ -43,7 +88,7 @@ pub struct DeploymentArtifact { chain_id: ChainId, contract_id: String, deployment_size: usize, - deployed_block_height: u32, + deployed_block_height: Option, } impl DeploymentArtifact { @@ -113,39 +158,424 @@ fn validate_and_parse_salts<'a>( Ok(contract_salt_map) } -/// Builds and deploys contract(s). If the given path corresponds to a workspace, all deployable members -/// will be built and deployed. +/// Depending on the cli options user passed, either returns storage slots from +/// compiled package, or the ones user provided as overrides. +fn resolve_storage_slots( + command: &cmd::Deploy, + compiled: &BuiltPackage, +) -> Result> { + let mut storage_slots = + if let Some(storage_slot_override_file) = &command.override_storage_slots { + let storage_slots_file = std::fs::read_to_string(storage_slot_override_file)?; + let storage_slots: Vec = serde_json::from_str(&storage_slots_file)?; + storage_slots + } else { + compiled.storage_slots.clone() + }; + storage_slots.sort(); + Ok(storage_slots) +} + +/// Creates blobs from the contract to deploy contracts that are larger than +/// maximum contract size. Created blobs are deployed, and a loader contract is +/// generated such that it loads all the deployed blobs, and provides the user +/// a single contract (loader contract that loads the blobs) to call into. +async fn deploy_chunked( + command: &cmd::Deploy, + compiled: &BuiltPackage, + salt: Salt, + account: &ForcClientAccount, + provider: &Provider, + pkg_name: &str, +) -> anyhow::Result { + println_action_green("Deploying", &format!("contract {pkg_name} chunks")); + + let storage_slots = resolve_storage_slots(command, compiled)?; + let chain_info = provider.chain_info().await?; + let target = Target::from_str(&chain_info.name).unwrap_or_default(); + let contract_url = match target.explorer_url() { + Some(explorer_url) => format!("{explorer_url}/contract/0x"), + None => "".to_string(), + }; + + let blobs = compiled + .bytecode + .bytes + .chunks(MAX_CONTRACT_SIZE) + .map(|chunk| Blob::new(chunk.to_vec())) + .collect(); + + let tx_policies = tx_policies_from_cmd(command); + let contract_id = + fuels::programs::contract::Contract::loader_from_blobs(blobs, salt, storage_slots)? + .deploy(account, tx_policies) + .await? + .into(); + + println_action_green( + "Finished", + &format!("deploying loader contract for {pkg_name} {contract_url}{contract_id}"), + ); + + Ok(contract_id) +} + +/// Deploys a new proxy contract for the given package. +async fn deploy_new_proxy( + command: &cmd::Deploy, + pkg_name: &str, + pkg_storage_slots: &[StorageSlot], + impl_contract: &fuel_tx::ContractId, + provider: &Provider, + account: &ForcClientAccount, +) -> Result { + abigen!(Contract(name = "ProxyContract", abi = "{\"programType\":\"contract\",\"specVersion\":\"1\",\"encodingVersion\":\"1\",\"concreteTypes\":[{\"type\":\"()\",\"concreteTypeId\":\"2e38e77b22c314a449e91fafed92a43826ac6aa403ae6a8acb6cf58239fbaf5d\"},{\"type\":\"enum standards::src5::AccessError\",\"concreteTypeId\":\"3f702ea3351c9c1ece2b84048006c8034a24cbc2bad2e740d0412b4172951d3d\",\"metadataTypeId\":1},{\"type\":\"enum standards::src5::State\",\"concreteTypeId\":\"192bc7098e2fe60635a9918afb563e4e5419d386da2bdbf0d716b4bc8549802c\",\"metadataTypeId\":2},{\"type\":\"enum std::option::Option\",\"concreteTypeId\":\"0d79387ad3bacdc3b7aad9da3a96f4ce60d9a1b6002df254069ad95a3931d5c8\",\"metadataTypeId\":4,\"typeArguments\":[\"29c10735d33b5159f0c71ee1dbd17b36a3e69e41f00fab0d42e1bd9f428d8a54\"]},{\"type\":\"enum sway_libs::ownership::errors::InitializationError\",\"concreteTypeId\":\"1dfe7feadc1d9667a4351761230f948744068a090fe91b1bc6763a90ed5d3893\",\"metadataTypeId\":5},{\"type\":\"enum sway_libs::upgradability::errors::SetProxyOwnerError\",\"concreteTypeId\":\"3c6e90ae504df6aad8b34a93ba77dc62623e00b777eecacfa034a8ac6e890c74\",\"metadataTypeId\":6},{\"type\":\"str\",\"concreteTypeId\":\"8c25cb3686462e9a86d2883c5688a22fe738b0bbc85f458d2d2b5f3f667c6d5a\"},{\"type\":\"struct std::contract_id::ContractId\",\"concreteTypeId\":\"29c10735d33b5159f0c71ee1dbd17b36a3e69e41f00fab0d42e1bd9f428d8a54\",\"metadataTypeId\":9},{\"type\":\"struct sway_libs::upgradability::events::ProxyOwnerSet\",\"concreteTypeId\":\"96dd838b44f99d8ccae2a7948137ab6256c48ca4abc6168abc880de07fba7247\",\"metadataTypeId\":10},{\"type\":\"struct sway_libs::upgradability::events::ProxyTargetSet\",\"concreteTypeId\":\"1ddc0adda1270a016c08ffd614f29f599b4725407c8954c8b960bdf651a9a6c8\",\"metadataTypeId\":11}],\"metadataTypes\":[{\"type\":\"b256\",\"metadataTypeId\":0},{\"type\":\"enum standards::src5::AccessError\",\"metadataTypeId\":1,\"components\":[{\"name\":\"NotOwner\",\"typeId\":\"2e38e77b22c314a449e91fafed92a43826ac6aa403ae6a8acb6cf58239fbaf5d\"}]},{\"type\":\"enum standards::src5::State\",\"metadataTypeId\":2,\"components\":[{\"name\":\"Uninitialized\",\"typeId\":\"2e38e77b22c314a449e91fafed92a43826ac6aa403ae6a8acb6cf58239fbaf5d\"},{\"name\":\"Initialized\",\"typeId\":3},{\"name\":\"Revoked\",\"typeId\":\"2e38e77b22c314a449e91fafed92a43826ac6aa403ae6a8acb6cf58239fbaf5d\"}]},{\"type\":\"enum std::identity::Identity\",\"metadataTypeId\":3,\"components\":[{\"name\":\"Address\",\"typeId\":8},{\"name\":\"ContractId\",\"typeId\":9}]},{\"type\":\"enum std::option::Option\",\"metadataTypeId\":4,\"components\":[{\"name\":\"None\",\"typeId\":\"2e38e77b22c314a449e91fafed92a43826ac6aa403ae6a8acb6cf58239fbaf5d\"},{\"name\":\"Some\",\"typeId\":7}],\"typeParameters\":[7]},{\"type\":\"enum sway_libs::ownership::errors::InitializationError\",\"metadataTypeId\":5,\"components\":[{\"name\":\"CannotReinitialized\",\"typeId\":\"2e38e77b22c314a449e91fafed92a43826ac6aa403ae6a8acb6cf58239fbaf5d\"}]},{\"type\":\"enum sway_libs::upgradability::errors::SetProxyOwnerError\",\"metadataTypeId\":6,\"components\":[{\"name\":\"CannotUninitialize\",\"typeId\":\"2e38e77b22c314a449e91fafed92a43826ac6aa403ae6a8acb6cf58239fbaf5d\"}]},{\"type\":\"generic T\",\"metadataTypeId\":7},{\"type\":\"struct std::address::Address\",\"metadataTypeId\":8,\"components\":[{\"name\":\"bits\",\"typeId\":0}]},{\"type\":\"struct std::contract_id::ContractId\",\"metadataTypeId\":9,\"components\":[{\"name\":\"bits\",\"typeId\":0}]},{\"type\":\"struct sway_libs::upgradability::events::ProxyOwnerSet\",\"metadataTypeId\":10,\"components\":[{\"name\":\"new_proxy_owner\",\"typeId\":2}]},{\"type\":\"struct sway_libs::upgradability::events::ProxyTargetSet\",\"metadataTypeId\":11,\"components\":[{\"name\":\"new_target\",\"typeId\":9}]}],\"functions\":[{\"inputs\":[],\"name\":\"proxy_target\",\"output\":\"0d79387ad3bacdc3b7aad9da3a96f4ce60d9a1b6002df254069ad95a3931d5c8\",\"attributes\":[{\"name\":\"doc-comment\",\"arguments\":[\" Returns the target contract of the proxy contract.\"]},{\"name\":\"doc-comment\",\"arguments\":[\"\"]},{\"name\":\"doc-comment\",\"arguments\":[\" # Returns\"]},{\"name\":\"doc-comment\",\"arguments\":[\"\"]},{\"name\":\"doc-comment\",\"arguments\":[\" * [Option] - The new proxy contract to which all fallback calls will be passed or `None`.\"]},{\"name\":\"doc-comment\",\"arguments\":[\"\"]},{\"name\":\"doc-comment\",\"arguments\":[\" # Number of Storage Accesses\"]},{\"name\":\"doc-comment\",\"arguments\":[\"\"]},{\"name\":\"doc-comment\",\"arguments\":[\" * Reads: `1`\"]},{\"name\":\"storage\",\"arguments\":[\"read\"]}]},{\"inputs\":[{\"name\":\"new_target\",\"concreteTypeId\":\"29c10735d33b5159f0c71ee1dbd17b36a3e69e41f00fab0d42e1bd9f428d8a54\"}],\"name\":\"set_proxy_target\",\"output\":\"2e38e77b22c314a449e91fafed92a43826ac6aa403ae6a8acb6cf58239fbaf5d\",\"attributes\":[{\"name\":\"doc-comment\",\"arguments\":[\" Change the target contract of the proxy contract.\"]},{\"name\":\"doc-comment\",\"arguments\":[\"\"]},{\"name\":\"doc-comment\",\"arguments\":[\" # Additional Information\"]},{\"name\":\"doc-comment\",\"arguments\":[\"\"]},{\"name\":\"doc-comment\",\"arguments\":[\" This method can only be called by the `proxy_owner`.\"]},{\"name\":\"doc-comment\",\"arguments\":[\"\"]},{\"name\":\"doc-comment\",\"arguments\":[\" # Arguments\"]},{\"name\":\"doc-comment\",\"arguments\":[\"\"]},{\"name\":\"doc-comment\",\"arguments\":[\" * `new_target`: [ContractId] - The new proxy contract to which all fallback calls will be passed.\"]},{\"name\":\"doc-comment\",\"arguments\":[\"\"]},{\"name\":\"doc-comment\",\"arguments\":[\" # Reverts\"]},{\"name\":\"doc-comment\",\"arguments\":[\"\"]},{\"name\":\"doc-comment\",\"arguments\":[\" * When not called by `proxy_owner`.\"]},{\"name\":\"doc-comment\",\"arguments\":[\"\"]},{\"name\":\"doc-comment\",\"arguments\":[\" # Number of Storage Accesses\"]},{\"name\":\"doc-comment\",\"arguments\":[\"\"]},{\"name\":\"doc-comment\",\"arguments\":[\" * Reads: `1`\"]},{\"name\":\"doc-comment\",\"arguments\":[\" * Write: `1`\"]},{\"name\":\"storage\",\"arguments\":[\"read\",\"write\"]}]},{\"inputs\":[],\"name\":\"proxy_owner\",\"output\":\"192bc7098e2fe60635a9918afb563e4e5419d386da2bdbf0d716b4bc8549802c\",\"attributes\":[{\"name\":\"doc-comment\",\"arguments\":[\" Returns the owner of the proxy contract.\"]},{\"name\":\"doc-comment\",\"arguments\":[\"\"]},{\"name\":\"doc-comment\",\"arguments\":[\" # Returns\"]},{\"name\":\"doc-comment\",\"arguments\":[\"\"]},{\"name\":\"doc-comment\",\"arguments\":[\" * [State] - Represents the state of ownership for this contract.\"]},{\"name\":\"doc-comment\",\"arguments\":[\"\"]},{\"name\":\"doc-comment\",\"arguments\":[\" # Number of Storage Accesses\"]},{\"name\":\"doc-comment\",\"arguments\":[\"\"]},{\"name\":\"doc-comment\",\"arguments\":[\" * Reads: `1`\"]},{\"name\":\"storage\",\"arguments\":[\"read\"]}]},{\"inputs\":[],\"name\":\"initialize_proxy\",\"output\":\"2e38e77b22c314a449e91fafed92a43826ac6aa403ae6a8acb6cf58239fbaf5d\",\"attributes\":[{\"name\":\"doc-comment\",\"arguments\":[\" Initializes the proxy contract.\"]},{\"name\":\"doc-comment\",\"arguments\":[\"\"]},{\"name\":\"doc-comment\",\"arguments\":[\" # Additional Information\"]},{\"name\":\"doc-comment\",\"arguments\":[\"\"]},{\"name\":\"doc-comment\",\"arguments\":[\" This method sets the storage values using the values of the configurable constants `INITIAL_TARGET` and `INITIAL_OWNER`.\"]},{\"name\":\"doc-comment\",\"arguments\":[\" This then allows methods that write to storage to be called.\"]},{\"name\":\"doc-comment\",\"arguments\":[\" This method can only be called once.\"]},{\"name\":\"doc-comment\",\"arguments\":[\"\"]},{\"name\":\"doc-comment\",\"arguments\":[\" # Reverts\"]},{\"name\":\"doc-comment\",\"arguments\":[\"\"]},{\"name\":\"doc-comment\",\"arguments\":[\" * When `storage::SRC14.proxy_owner` is not [State::Uninitialized].\"]},{\"name\":\"doc-comment\",\"arguments\":[\"\"]},{\"name\":\"doc-comment\",\"arguments\":[\" # Number of Storage Accesses\"]},{\"name\":\"doc-comment\",\"arguments\":[\"\"]},{\"name\":\"doc-comment\",\"arguments\":[\" * Writes: `2`\"]},{\"name\":\"storage\",\"arguments\":[\"write\"]}]},{\"inputs\":[{\"name\":\"new_proxy_owner\",\"concreteTypeId\":\"192bc7098e2fe60635a9918afb563e4e5419d386da2bdbf0d716b4bc8549802c\"}],\"name\":\"set_proxy_owner\",\"output\":\"2e38e77b22c314a449e91fafed92a43826ac6aa403ae6a8acb6cf58239fbaf5d\",\"attributes\":[{\"name\":\"doc-comment\",\"arguments\":[\" Changes proxy ownership to the passed State.\"]},{\"name\":\"doc-comment\",\"arguments\":[\"\"]},{\"name\":\"doc-comment\",\"arguments\":[\" # Additional Information\"]},{\"name\":\"doc-comment\",\"arguments\":[\"\"]},{\"name\":\"doc-comment\",\"arguments\":[\" This method can be used to transfer ownership between Identities or to revoke ownership.\"]},{\"name\":\"doc-comment\",\"arguments\":[\"\"]},{\"name\":\"doc-comment\",\"arguments\":[\" # Arguments\"]},{\"name\":\"doc-comment\",\"arguments\":[\"\"]},{\"name\":\"doc-comment\",\"arguments\":[\" * `new_proxy_owner`: [State] - The new state of the proxy ownership.\"]},{\"name\":\"doc-comment\",\"arguments\":[\"\"]},{\"name\":\"doc-comment\",\"arguments\":[\" # Reverts\"]},{\"name\":\"doc-comment\",\"arguments\":[\"\"]},{\"name\":\"doc-comment\",\"arguments\":[\" * When the sender is not the current proxy owner.\"]},{\"name\":\"doc-comment\",\"arguments\":[\" * When the new state of the proxy ownership is [State::Uninitialized].\"]},{\"name\":\"doc-comment\",\"arguments\":[\"\"]},{\"name\":\"doc-comment\",\"arguments\":[\" # Number of Storage Accesses\"]},{\"name\":\"doc-comment\",\"arguments\":[\"\"]},{\"name\":\"doc-comment\",\"arguments\":[\" * Reads: `1`\"]},{\"name\":\"doc-comment\",\"arguments\":[\" * Writes: `1`\"]},{\"name\":\"storage\",\"arguments\":[\"write\"]}]}],\"loggedTypes\":[{\"logId\":\"4571204900286667806\",\"concreteTypeId\":\"3f702ea3351c9c1ece2b84048006c8034a24cbc2bad2e740d0412b4172951d3d\"},{\"logId\":\"2151606668983994881\",\"concreteTypeId\":\"1ddc0adda1270a016c08ffd614f29f599b4725407c8954c8b960bdf651a9a6c8\"},{\"logId\":\"2161305517876418151\",\"concreteTypeId\":\"1dfe7feadc1d9667a4351761230f948744068a090fe91b1bc6763a90ed5d3893\"},{\"logId\":\"4354576968059844266\",\"concreteTypeId\":\"3c6e90ae504df6aad8b34a93ba77dc62623e00b777eecacfa034a8ac6e890c74\"},{\"logId\":\"10870989709723147660\",\"concreteTypeId\":\"96dd838b44f99d8ccae2a7948137ab6256c48ca4abc6168abc880de07fba7247\"},{\"logId\":\"10098701174489624218\",\"concreteTypeId\":\"8c25cb3686462e9a86d2883c5688a22fe738b0bbc85f458d2d2b5f3f667c6d5a\"}],\"messagesTypes\":[],\"configurables\":[{\"name\":\"INITIAL_TARGET\",\"concreteTypeId\":\"0d79387ad3bacdc3b7aad9da3a96f4ce60d9a1b6002df254069ad95a3931d5c8\",\"offset\":13368},{\"name\":\"INITIAL_OWNER\",\"concreteTypeId\":\"192bc7098e2fe60635a9918afb563e4e5419d386da2bdbf0d716b4bc8549802c\",\"offset\":13320}]}",)); + let proxy_dir_output = create_proxy_contract(pkg_name)?; + let address = account.address(); + + // Add the combined storage slots from the original contract and the proxy contract. + let proxy_storage_path = proxy_dir_output.join("proxy-storage_slots.json"); + let storage_configuration = StorageConfiguration::default() + .add_slot_overrides(pkg_storage_slots.iter().cloned()) + .add_slot_overrides_from_file(proxy_storage_path)?; + + let configurables = ProxyContractConfigurables::default() + .with_INITIAL_TARGET(Some(*impl_contract))? + .with_INITIAL_OWNER(State::Initialized(Address::from(address).into()))?; + + let configuration = LoadConfiguration::default() + .with_storage_configuration(storage_configuration) + .with_configurables(configurables); + + let tx_policies = tx_policies_from_cmd(command); + let proxy_contract_id: ContractId = fuels::programs::contract::Contract::load_from( + proxy_dir_output.join("proxy.bin"), + configuration, + )? + .deploy(account, tx_policies) + .await? + .into(); + + let chain_info = provider.chain_info().await?; + let target = Target::from_str(&chain_info.name).unwrap_or_default(); + let contract_url = match target.explorer_url() { + Some(explorer_url) => format!("{explorer_url}/contract/0x"), + None => "".to_string(), + }; + + println_action_green( + "Finished", + &format!("deploying proxy contract for {pkg_name} {contract_url}{proxy_contract_id}"), + ); + + let proxy_contract_bech_id: Bech32ContractId = proxy_contract_id.into(); + let instance = ProxyContract::new(&proxy_contract_bech_id, account.clone()); + instance.methods().initialize_proxy().call().await?; + println_action_green("Initialized", &format!("proxy contract for {pkg_name}")); + Ok(proxy_contract_id) +} + +/// Builds and deploys contracts, scripts, and predicates from the given path or workspace. /// -/// Upon success, returns the ID of each deployed contract in order of deployment. +/// Contracts are deployed directly, while scripts and predicates are deployed as blobs with generated loaders. /// -/// When deploying a single contract, only that contract's ID is returned. -pub async fn deploy(command: cmd::Deploy) -> Result> { +/// Returns a vector of `DeployedPackage` representing all successful deployments. +pub async fn deploy(command: cmd::Deploy) -> Result> { if command.unsigned { println_warning("--unsigned flag is deprecated, please prefer using --default-signer. Assuming `--default-signer` is passed. This means your transaction will be signed by an account that is funded by fuel-core by default for testing purposes."); } - - let mut contract_ids = Vec::new(); let curr_dir = if let Some(ref path) = command.pkg.path { PathBuf::from(path) } else { std::env::current_dir()? }; - - let build_opts = build_opts_from_cmd(&command); + let build_opts = build_opts_from_cmd(&command, MemberFilter::default()); let built_pkgs = built_pkgs(&curr_dir, &build_opts)?; + let mut deployed_packages = Vec::new(); + + let contracts_to_deploy = built_pkgs + .iter() + .filter(|pkg| { + pkg.descriptor + .manifest_file + .check_program_type(&[TreeType::Contract]) + .is_ok() + }) + .cloned() + .collect::>(); + + let scripts_to_deploy = built_pkgs + .iter() + .filter(|pkg| { + pkg.descriptor + .manifest_file + .check_program_type(&[TreeType::Script]) + .is_ok() + }) + .cloned() + .collect::>(); - if built_pkgs.is_empty() { - println_warning("No deployable contracts found in the current directory."); - return Ok(contract_ids); + let predicates_to_deploy = built_pkgs + .iter() + .filter(|pkg| { + pkg.descriptor + .manifest_file + .check_program_type(&[TreeType::Predicate]) + .is_ok() + }) + .cloned() + .collect::>(); + + if contracts_to_deploy.is_empty() + && scripts_to_deploy.is_empty() + && predicates_to_deploy.is_empty() + { + println_warning("No deployable package was found in the current directory."); + } else { + deployed_packages.extend( + deploy_contracts(&command, &contracts_to_deploy) + .await? + .into_iter() + .map(DeployedPackage::Contract), + ); + deployed_packages.extend( + deploy_executables(&command, &scripts_to_deploy) + .await? + .into_iter() + .map(DeployedPackage::Script), + ); + deployed_packages.extend( + deploy_executables(&command, &predicates_to_deploy) + .await? + .into_iter() + .map(DeployedPackage::Predicate), + ); + } + + Ok(deployed_packages) +} + +/// Calculates the loader data offset. Returns a `None` if the original `binary` +/// does not have a data section (no configurables and no args). Otherwise +/// returns the new offset of the data section. +fn loader_data_offset(binary: &[u8], blob_id: &BlobId) -> Result> { + // The following code is taken from SDK, and once they expose the offsets + // we will no longer need to maintain this duplicate version here. + + // The final code is going to have this structure (if the data section is non-empty): + // 1. loader instructions + // 2. blob id + // 3. length_of_data_section + // 4. the data_section (updated with configurables as needed) + const BLOB_ID_SIZE: u16 = 32; + const REG_ADDRESS_OF_DATA_AFTER_CODE: u8 = 0x10; + const REG_START_OF_LOADED_CODE: u8 = 0x11; + const REG_GENERAL_USE: u8 = 0x12; + let get_instructions = |num_of_instructions| { + // There are 3 main steps: + // 1. Load the blob content into memory + // 2. Load the data section right after the blob + // 3. Jump to the beginning of the memory where the blob was loaded + [ + // 1. Load the blob content into memory + // Find the start of the hardcoded blob ID, which is located after the loader code ends. + op::move_(REG_ADDRESS_OF_DATA_AFTER_CODE, RegId::PC), + // hold the address of the blob ID. + op::addi( + REG_ADDRESS_OF_DATA_AFTER_CODE, + REG_ADDRESS_OF_DATA_AFTER_CODE, + num_of_instructions * Instruction::SIZE as u16, + ), + // The code is going to be loaded from the current value of SP onwards, save + // the location into REG_START_OF_LOADED_CODE so we can jump into it at the end. + op::move_(REG_START_OF_LOADED_CODE, RegId::SP), + // REG_GENERAL_USE to hold the size of the blob. + op::bsiz(REG_GENERAL_USE, REG_ADDRESS_OF_DATA_AFTER_CODE), + // Push the blob contents onto the stack. + op::ldc(REG_ADDRESS_OF_DATA_AFTER_CODE, 0, REG_GENERAL_USE, 1), + // Move on to the data section length + op::addi( + REG_ADDRESS_OF_DATA_AFTER_CODE, + REG_ADDRESS_OF_DATA_AFTER_CODE, + BLOB_ID_SIZE, + ), + // load the size of the data section into REG_GENERAL_USE + op::lw(REG_GENERAL_USE, REG_ADDRESS_OF_DATA_AFTER_CODE, 0), + // after we have read the length of the data section, we move the pointer to the actual + // data by skipping WORD_SIZE B. + op::addi( + REG_ADDRESS_OF_DATA_AFTER_CODE, + REG_ADDRESS_OF_DATA_AFTER_CODE, + WORD_SIZE as u16, + ), + // load the data section of the executable + op::ldc(REG_ADDRESS_OF_DATA_AFTER_CODE, 0, REG_GENERAL_USE, 2), + // Jump into the memory where the contract is loaded. + // What follows is called _jmp_mem by the sway compiler. + // Subtract the address contained in IS because jmp will add it back. + op::sub( + REG_START_OF_LOADED_CODE, + REG_START_OF_LOADED_CODE, + RegId::IS, + ), + // jmp will multiply by 4, so we need to divide to cancel that out. + op::divi(REG_START_OF_LOADED_CODE, REG_START_OF_LOADED_CODE, 4), + // Jump to the start of the contract we loaded. + op::jmp(REG_START_OF_LOADED_CODE), + ] + }; + + let offset = extract_data_offset(binary)?; + + if binary.len() < offset { + anyhow::bail!("data sectio offset is out of bounds"); + } + + let data_section = binary[offset..].to_vec(); + + if !data_section.is_empty() { + let num_of_instructions = u16::try_from(get_instructions(0).len()) + .expect("to never have more than u16::MAX instructions"); + + let instruction_bytes = get_instructions(num_of_instructions) + .into_iter() + .flat_map(|instruction| instruction.to_bytes()); + + let blob_bytes = blob_id.iter().copied(); + + let loader_offset = + instruction_bytes.count() + blob_bytes.count() + data_section.len().to_be_bytes().len(); + + Ok(Some(loader_offset)) + } else { + Ok(None) + } +} + +/// Builds and deploys executable (script and predicate) package(s) as blobs, +/// and generates a loader for each of them. +pub async fn deploy_executables( + command: &cmd::Deploy, + executables_to_deploy: &[Arc], +) -> Result> { + let mut deployed_executable = vec![]; + if executables_to_deploy.is_empty() { + return Ok(deployed_executable); + } + + let node_url = validate_and_get_node_url(command, executables_to_deploy).await?; + // We will have 1 transaction per executable as each deployment uses a single blob. + let tx_count = executables_to_deploy.len(); + let account = setup_deployment_account(command, &node_url, tx_count).await?; + + for pkg in executables_to_deploy { + let script = Executable::from_bytes(pkg.bytecode.bytes.clone()); + let loader = script.convert_to_loader()?; + println_action_green("Uploading", "blob containing executable bytecode."); + loader.upload_blob(account.clone()).await?; + println_action_green("Generating", "loader bytecode for the uploaded executable."); + let loader_bytecode = loader.code(); + let pkg_name = &pkg.descriptor.name; + let out_dir = pkg.descriptor.manifest_file.dir().join("out"); + let bin_path = out_dir.join(format!("{pkg_name}-loader.bin")); + std::fs::write(&bin_path, &loader_bytecode)?; + println_action_green( + "Saved", + &format!("loader bytecode at {}", bin_path.display()), + ); + if let Some(loader_data_section_offset) = + loader_data_offset(&pkg.bytecode.bytes, &BlobId::default())? + { + if let ProgramABI::Fuel(mut fuel_abi) = pkg.program_abi.clone() { + println_action_green("Generating", "loader abi for the uploaded executable."); + let json_abi_path = out_dir.join(format!("{pkg_name}-loader-abi.json")); + let original_data_section = extract_data_offset(&pkg.bytecode.bytes).unwrap(); + let offset_shift = original_data_section - loader_data_section_offset; + // if there are configurables in the abi we need to shift them by `offset_shift`. + let configurables = fuel_abi.configurables.clone().map(|configs| { + configs + .into_iter() + .map(|config| Configurable { + offset: config.offset - offset_shift as u64, + ..config.clone() + }) + .collect() + }); + fuel_abi.configurables = configurables; + let json_string = serde_json::to_string_pretty(&fuel_abi)?; + std::fs::write(json_abi_path, json_string)?; + } + } + // If the executable is a predicate, we also want to display and save the predicate root. + if pkg + .descriptor + .manifest_file + .program_type() + .with_context(|| { + "error while trying to retrieve program type for executable deployment." + })? + == TreeType::Predicate + { + // Calculate the root. + let root = format!("0x{}", fuel_tx::Input::predicate_owner(&loader_bytecode)); + // Root files are named in `pkg-name-root` format, since this is a + // loader we are also adding an identifier to differentiate it from + // the root of the "original" predicate. + let root_file_name = format!("{}-loader-root", &pkg_name); + let root_path = out_dir.join(root_file_name); + std::fs::write(&root_path, &root)?; + println_action_green( + "Saved", + &format!("loader root ({}) at {}", root, root_path.display()), + ); + } + let deployed = DeployedExecutable { + bytecode: loader_bytecode, + }; + deployed_executable.push(deployed); + println_action_green("Finished", &format!("deploying executable {pkg_name}")); + } + Ok(deployed_executable) +} + +fn extract_data_offset(binary: &[u8]) -> Result { + if binary.len() < 16 { + anyhow::bail!( + "given binary is too short to contain a data offset, len: {}", + binary.len() + ); + } + + let data_offset: [u8; 8] = binary[8..16].try_into().expect("checked above"); + + Ok(u64::from_be_bytes(data_offset) as usize) +} + +/// Builds and deploys contract(s). If the given path corresponds to a workspace, all deployable members +/// will be built and deployed. +/// +/// Upon success, returns the ID of each deployed contract in order of deployment. +/// +/// When deploying a single contract, only that contract's ID is returned. +pub async fn deploy_contracts( + command: &cmd::Deploy, + contracts_to_deploy: &[Arc], +) -> Result> { + let mut deployed_contracts = Vec::new(); + + if contracts_to_deploy.is_empty() { + return Ok(deployed_contracts); } let contract_salt_map = if let Some(salt_input) = &command.salt { // If we're building 1 package, we just parse the salt as a string, ie. 0x00... // If we're building >1 package, we must parse the salt as a pair of strings, ie. contract_name:0x00... - if built_pkgs.len() > 1 { + if contracts_to_deploy.len() > 1 { let map = validate_and_parse_salts( salt_input, - built_pkgs.iter().map(|b| &b.descriptor.manifest_file), + contracts_to_deploy + .iter() + .map(|b| &b.descriptor.manifest_file), )?; Some(map) @@ -163,7 +593,7 @@ pub async fn deploy(command: cmd::Deploy) -> Result> { .unwrap(); let mut contract_salt_map = ContractSaltMap::default(); contract_salt_map.insert( - built_pkgs[0] + contracts_to_deploy[0] .descriptor .manifest_file .project_name() @@ -176,167 +606,294 @@ pub async fn deploy(command: cmd::Deploy) -> Result> { None }; - for pkg in built_pkgs { - if pkg - .descriptor - .manifest_file - .check_program_type(&[TreeType::Contract]) - .is_ok() - { - let salt = match (&contract_salt_map, command.default_salt) { - (Some(map), false) => { - if let Some(salt) = map.get(pkg.descriptor.manifest_file.project_name()) { - *salt + let node_url = validate_and_get_node_url(command, contracts_to_deploy).await?; + let provider = Provider::connect(node_url.clone()).await?; + + // Confirmation step. Summarize the transaction(s) for the deployment. + let account = confirm_transaction_details( + contracts_to_deploy, + command, + node_url.clone(), + MAX_CONTRACT_SIZE, + ) + .await?; + + for pkg in contracts_to_deploy { + let salt = match (&contract_salt_map, command.default_salt) { + (Some(map), false) => { + if let Some(salt) = map.get(pkg.descriptor.manifest_file.project_name()) { + *salt + } else { + Default::default() + } + } + (None, true) => Default::default(), + (None, false) => rand::random(), + (Some(_), true) => { + bail!("Both `--salt` and `--default-salt` were specified: must choose one") + } + }; + let bytecode_size = pkg.bytecode.bytes.len(); + let deployed_contract_id = if bytecode_size > MAX_CONTRACT_SIZE { + // Deploy chunked + let node_url = get_node_url(&command.node, &pkg.descriptor.manifest_file.network)?; + let provider = Provider::connect(node_url).await?; + + deploy_chunked( + command, + pkg, + salt, + &account, + &provider, + &pkg.descriptor.name, + ) + .await? + } else { + deploy_pkg(command, pkg, salt, &provider, &account).await? + }; + + let proxy_id = match &pkg.descriptor.manifest_file.proxy { + Some(forc_pkg::manifest::Proxy { + enabled: true, + address: Some(proxy_addr), + }) => { + // Make a call into the contract to update impl contract address to 'deployed_contract'. + + // Create a contract instance for the proxy contract using default proxy contract abi and + // specified address. + let proxy_contract = + ContractId::from_str(proxy_addr).map_err(|e| anyhow::anyhow!(e))?; + + update_proxy_contract_target(&account, proxy_contract, deployed_contract_id) + .await?; + Some(proxy_contract) + } + Some(forc_pkg::manifest::Proxy { + enabled: true, + address: None, + }) => { + let pkg_name = &pkg.descriptor.name; + let pkg_storage_slots = &pkg.storage_slots; + // Deploy a new proxy contract. + let deployed_proxy_contract = deploy_new_proxy( + command, + pkg_name, + pkg_storage_slots, + &deployed_contract_id, + &provider, + &account, + ) + .await?; + + // Update manifest file such that the proxy address field points to the new proxy contract. + update_proxy_address_in_manifest( + &format!("0x{}", deployed_proxy_contract), + &pkg.descriptor.manifest_file, + )?; + Some(deployed_proxy_contract) + } + // Proxy not enabled. + _ => None, + }; + + let deployed_contract = DeployedContract { + id: deployed_contract_id, + proxy: proxy_id, + chunked: bytecode_size > MAX_CONTRACT_SIZE, + }; + deployed_contracts.push(deployed_contract); + } + Ok(deployed_contracts) +} + +/// Prompt the user to confirm the transactions required for deployment, as well as the signing key. +async fn confirm_transaction_details( + pkgs_to_deploy: &[Arc], + command: &cmd::Deploy, + node_url: String, + max_contract_size: usize, +) -> Result { + // Confirmation step. Summarize the transaction(s) for the deployment. + let mut tx_count = 0; + let tx_summary = pkgs_to_deploy + .iter() + .map(|pkg| { + tx_count += 1; + let proxy_text = match &pkg.descriptor.manifest_file.proxy { + Some(forc_pkg::manifest::Proxy { + enabled: true, + address, + }) => { + tx_count += 1; + if address.is_some() { + " + update proxy" } else { - Default::default() + " + deploy proxy" } } - (None, true) => Default::default(), - (None, false) => rand::random(), - (Some(_), true) => { - bail!("Both `--salt` and `--default-salt` were specified: must choose one") - } + _ => "", }; - let contract_id = - deploy_pkg(&command, &pkg.descriptor.manifest_file, &pkg, salt).await?; - contract_ids.push(contract_id); - } - } - Ok(contract_ids) + + let pkg_bytecode_len = pkg.bytecode.bytes.len(); + let blob_text = if pkg_bytecode_len > max_contract_size { + let number_of_blobs = pkg_bytecode_len.div_ceil(max_contract_size); + tx_count += number_of_blobs; + &format!(" + {number_of_blobs} blobs") + } else { + "" + }; + + format!( + "deploy {}{blob_text}{proxy_text}", + pkg.descriptor.manifest_file.project_name() + ) + }) + .collect::>() + .join(" + "); + + println_action_green("Confirming", &format!("transactions [{tx_summary}]")); + println_action_green("", &format!("Network: {node_url}")); + + let account = setup_deployment_account(command, &node_url, tx_count).await?; + + // TODO: Display the estimated gas cost of the transaction(s). + // https://github.com/FuelLabs/sway/issues/6277 + + Ok(account) } /// Deploy a single pkg given deploy command and the manifest file pub async fn deploy_pkg( command: &cmd::Deploy, - manifest: &PackageManifestFile, compiled: &BuiltPackage, salt: Salt, -) -> Result { - let node_url = get_node_url(&command.node, &manifest.network)?; - let client = FuelClient::new(node_url.clone())?; + provider: &Provider, + account: &ForcClientAccount, +) -> Result { + let manifest = &compiled.descriptor.manifest_file; + let node_url = provider.url(); + let client = FuelClient::new(node_url)?; let bytecode = &compiled.bytecode.bytes; - let mut storage_slots = - if let Some(storage_slot_override_file) = &command.override_storage_slots { - let storage_slots_file = std::fs::read_to_string(storage_slot_override_file)?; - let storage_slots: Vec = serde_json::from_str(&storage_slots_file)?; - storage_slots - } else { - compiled.storage_slots.clone() - }; - storage_slots.sort(); - + let storage_slots = resolve_storage_slots(command, compiled)?; let contract = Contract::from(bytecode.clone()); let root = contract.root(); let state_root = Contract::initial_state_root(storage_slots.iter()); let contract_id = contract.id(&salt, &root, &state_root); + let tx_policies = tx_policies_from_cmd(command); - let wallet_mode = if command.manual_signing { - WalletSelectionMode::Manual - } else { - WalletSelectionMode::ForcWallet - }; - - let provider = Provider::connect(node_url.clone()).await?; + let mut tb = CreateTransactionBuilder::prepare_contract_deployment( + bytecode.clone(), + contract_id, + state_root, + salt, + storage_slots.clone(), + tx_policies, + ); - // We need a tx for estimation without the signature. - let mut tb = - TransactionBuilder::create(bytecode.as_slice().into(), salt, storage_slots.clone()); - tb.maturity(command.maturity.maturity.into()) - .add_output(Output::contract_created(contract_id, state_root)); - let tx_for_estimation = tb.finalize_without_signature_inner(); + account.add_witnesses(&mut tb)?; + account.adjust_for_fee(&mut tb, 0).await?; - // If user specified max_fee use that but if not, we will estimate with %10 safety margin. - let max_fee = if let Some(max_fee) = command.gas.max_fee { - max_fee - } else { - let estimation_margin = 10; - get_estimated_max_fee( - tx_for_estimation.clone(), - &provider, - &client, - estimation_margin, - ) - .await? - }; - - let tx = tb - .max_fee_limit(max_fee) - .finalize_signed( - provider.clone(), - command.default_signer || command.unsigned, - command.signing_key, - wallet_mode, - ) - .await?; + let tx = tb.build(provider).await?; let tx = Transaction::from(tx); - let chain_id = client.chain_info().await?.consensus_parameters.chain_id(); - - let deployment_request = client.submit_and_await_commit(&tx).map(|res| match res { - Ok(logs) => match logs { - TransactionStatus::Submitted { .. } => { - bail!("contract {} deployment timed out", &contract_id); - } - TransactionStatus::Success { block_height, .. } => { - let pkg_name = manifest.project_name(); - info!("\n\nContract {pkg_name} Deployed!"); - - info!("\nNetwork: {node_url}"); - info!("Contract ID: 0x{contract_id}"); - info!("Deployed in block {}", &block_height); + let chain_info = client.chain_info().await?; + let chain_id = chain_info.consensus_parameters.chain_id(); + // If only submitting the transaction, don't wait for the deployment to complete + let contract_id: ContractId = if command.submit_only { + match client.submit(&tx).await { + Ok(transaction_id) => { // Create a deployment artifact. - let deployment_size = bytecode.len(); - let deployment_artifact = DeploymentArtifact { - transaction_id: format!("0x{}", tx.id(&chain_id)), - salt: format!("0x{}", salt), - network_endpoint: node_url.to_string(), - chain_id, - contract_id: format!("0x{}", contract_id), - deployment_size, - deployed_block_height: *block_height, - }; - - let output_dir = command - .pkg - .output_directory - .as_ref() - .map(PathBuf::from) - .unwrap_or_else(|| default_output_directory(manifest.dir())) - .join("deployments"); - deployment_artifact.to_file(&output_dir, pkg_name, contract_id)?; - - Ok(contract_id) + create_deployment_artifact( + DeploymentArtifact { + transaction_id: format!("0x{}", transaction_id), + salt: format!("0x{}", salt), + network_endpoint: node_url.to_string(), + chain_id, + contract_id: format!("0x{}", contract_id), + deployment_size: bytecode.len(), + deployed_block_height: None, + }, + command, + manifest, + chain_info, + )?; + + contract_id } - e => { + Err(e) => { bail!( "contract {} failed to deploy due to an error: {:?}", &contract_id, e ) } - }, - Err(e) => bail!("{e}"), - }); + } + } else { + let deployment_request = client.submit_and_await_commit(&tx).map(|res| match res { + Ok(logs) => match logs { + TransactionStatus::Submitted { .. } => { + bail!("contract {} deployment timed out", &contract_id); + } + TransactionStatus::Success { block_height, .. } => { + // Create a deployment artifact. + create_deployment_artifact( + DeploymentArtifact { + transaction_id: format!("0x{}", tx.id(&chain_id)), + salt: format!("0x{}", salt), + network_endpoint: node_url.to_string(), + chain_id, + contract_id: format!("0x{}", contract_id), + deployment_size: bytecode.len(), + deployed_block_height: Some(*block_height), + }, + command, + manifest, + chain_info, + )?; - // submit contract deployment with a timeout - let contract_id = tokio::time::timeout( - Duration::from_millis(TX_SUBMIT_TIMEOUT_MS), - deployment_request, - ) - .await - .with_context(|| { - format!( - "Timed out waiting for contract {} to deploy. The transaction may have been dropped.", - &contract_id + Ok(contract_id) + } + e => { + bail!( + "contract {} failed to deploy due to an error: {:?}", + &contract_id, + e + ) + } + }, + Err(e) => bail!("{e}"), + }); + tokio::time::timeout( + Duration::from_millis(TX_SUBMIT_TIMEOUT_MS), + deployment_request, ) - })??; - Ok(DeployedContract { id: contract_id }) + .await + .with_context(|| { + format!( + "Timed out waiting for contract {} to deploy. The transaction may have been dropped.", + &contract_id + ) + })?? + }; + + Ok(contract_id) } -fn build_opts_from_cmd(cmd: &cmd::Deploy) -> pkg::BuildOpts { +fn tx_policies_from_cmd(cmd: &cmd::Deploy) -> TxPolicies { + let mut tx_policies = TxPolicies::default(); + if let Some(max_fee) = cmd.gas.max_fee { + tx_policies = tx_policies.with_max_fee(max_fee); + } + if let Some(script_gas_limit) = cmd.gas.script_gas_limit { + tx_policies = tx_policies.with_script_gas_limit(script_gas_limit); + } + tx_policies +} + +fn build_opts_from_cmd(cmd: &cmd::Deploy, member_filter: pkg::MemberFilter) -> pkg::BuildOpts { pkg::BuildOpts { pkg: pkg::PkgOpts { path: cmd.pkg.path.clone(), @@ -344,7 +901,6 @@ fn build_opts_from_cmd(cmd: &cmd::Deploy) -> pkg::BuildOpts { terse: cmd.pkg.terse, locked: cmd.pkg.locked, output_directory: cmd.pkg.output_directory.clone(), - json_abi_with_callpaths: cmd.pkg.json_abi_with_callpaths, ipfs_node: cmd.pkg.ipfs_node.clone().unwrap_or_default(), }, print: pkg::PrintOpts { @@ -353,6 +909,7 @@ fn build_opts_from_cmd(cmd: &cmd::Deploy) -> pkg::BuildOpts { dca_graph_url_format: cmd.print.dca_graph_url_format.clone(), asm: cmd.print.asm(), bytecode: cmd.print.bytecode, + bytecode_spans: false, ir: cmd.print.ir(), reverse_order: cmd.print.reverse_order, }, @@ -369,13 +926,100 @@ fn build_opts_from_cmd(cmd: &cmd::Deploy) -> pkg::BuildOpts { debug_outfile: cmd.build_output.debug_file.clone(), build_target: BuildTarget::default(), tests: false, - member_filter: pkg::MemberFilter::only_contracts(), + member_filter, experimental: ExperimentalFlags { new_encoding: !cmd.no_encoding_v1, }, } } +/// Creates a deployment artifact and writes it to a file. +/// +/// This function is used to generate a deployment artifact containing details +/// about the deployment, such as the transaction ID, salt, network endpoint, +/// chain ID, contract ID, deployment size, and deployed block height. It then +/// writes this artifact to a specified output directory. +fn create_deployment_artifact( + deployment_artifact: DeploymentArtifact, + cmd: &cmd::Deploy, + manifest: &PackageManifestFile, + chain_info: ChainInfo, +) -> Result<()> { + let contract_id = ContractId::from_str(&deployment_artifact.contract_id).unwrap(); + let pkg_name = manifest.project_name(); + + let target = Target::from_str(&chain_info.name).unwrap_or_default(); + let (contract_url, block_url) = match target.explorer_url() { + Some(explorer_url) => ( + format!("{explorer_url}/contract/0x"), + format!("{explorer_url}/block/"), + ), + None => ("".to_string(), "".to_string()), + }; + println_action_green( + "Finished", + &format!("deploying {pkg_name} {contract_url}{contract_id}"), + ); + + let block_height = deployment_artifact.deployed_block_height; + if let Some(block_height) = block_height { + println_action_green("Deployed", &format!("in block {block_url}{block_height}")); + } + + let output_dir = cmd + .pkg + .output_directory + .as_ref() + .map(PathBuf::from) + .unwrap_or_else(|| default_output_directory(manifest.dir())) + .join("deployments"); + deployment_artifact.to_file(&output_dir, pkg_name, contract_id) +} + +/// Validates that all packages are being deployed to the same node and returns the node URL. +async fn validate_and_get_node_url( + command: &cmd::Deploy, + packages: &[Arc], +) -> Result { + let node_url = get_node_url(&command.node, &packages[0].descriptor.manifest_file.network)?; + if !packages.iter().all(|pkg| { + get_node_url(&command.node, &pkg.descriptor.manifest_file.network).ok() + == Some(node_url.clone()) + }) { + bail!("All packages in a deployment should be deployed to the same node. Please ensure that the network specified in the Forc.toml files of all packages is the same."); + } + Ok(node_url) +} + +/// Sets up and returns the account for deployment. +async fn setup_deployment_account( + command: &cmd::Deploy, + node_url: &str, + tx_count: usize, +) -> Result { + let provider = Provider::connect(node_url).await?; + + let wallet_mode = if command.default_signer || command.signing_key.is_some() { + SignerSelectionMode::Manual + } else if let Some(arn) = &command.aws_kms_signer { + SignerSelectionMode::AwsSigner(arn.clone()) + } else { + println_action_green("", &format!("Wallet: {}", default_wallet_path().display())); + let password = prompt_forc_wallet_password()?; + SignerSelectionMode::ForcWallet(password) + }; + + let account = select_account( + &wallet_mode, + command.default_signer || command.unsigned, + command.signing_key, + &provider, + tx_count, + ) + .await?; + + Ok(account) +} #[cfg(test)] mod test { use super::*; diff --git a/forc-plugins/forc-client/src/op/mod.rs b/forc-plugins/forc-client/src/op/mod.rs index bb7e5746eb4..f11f8c63b7c 100644 --- a/forc-plugins/forc-client/src/op/mod.rs +++ b/forc-plugins/forc-client/src/op/mod.rs @@ -2,6 +2,6 @@ mod deploy; mod run; mod submit; -pub use deploy::deploy; +pub use deploy::{deploy, DeployedContract, DeployedExecutable, DeployedPackage}; pub use run::run; pub use submit::submit; diff --git a/forc-plugins/forc-client/src/op/run/encode.rs b/forc-plugins/forc-client/src/op/run/encode.rs index c1f36524591..99473403312 100644 --- a/forc-plugins/forc-client/src/op/run/encode.rs +++ b/forc-plugins/forc-client/src/op/run/encode.rs @@ -62,14 +62,18 @@ impl ScriptCallHandler { mod tests { use super::{ScriptCallHandler, Type}; + const TEST_JSON_ABI: &str = r#"{"programType": "contract","specVersion": "1","encodingVersion": "1","metadataTypes":[], + "concreteTypes":[{"concreteTypeId":"2e38e77b22c314a449e91fafed92a43826ac6aa403ae6a8acb6cf58239fbaf5d", + "type":"()"},{"concreteTypeId":"b760f44fa5965c2474a3b471467a22c43185152129295af588b022ae50b50903","type":"bool"}, + {"concreteTypeId":"c89951a24c6ca28c13fd1cfdc646b2b656d69e61a92b91023be7eb58eb914b6b","type":"u8"}], + "functions":[{"inputs":[{"name":"test_u8","concreteTypeId":"c89951a24c6ca28c13fd1cfdc646b2b656d69e61a92b91023be7eb58eb914b6b"}, + {"name":"test_bool","concreteTypeId":"b760f44fa5965c2474a3b471467a22c43185152129295af588b022ae50b50903"}],"name":"main", + "output":"2e38e77b22c314a449e91fafed92a43826ac6aa403ae6a8acb6cf58239fbaf5d"}],"loggedTypes":[], + "messagesTypes":[],"configurables":[]}"#; + #[test] fn test_script_call_handler_generation_success() { - let test_json_abi = r#"{"types":[{"typeId":0,"type":"()","components":[],"typeParameters":null}, -{"typeId":1,"type":"bool","components":null,"typeParameters":null},{"typeId":2,"type":"u8","components":null, -"typeParameters":null}],"functions":[{"inputs":[{"name":"test_u8","type":2,"typeArguments":null},{"name":"test_bool", -"type":1,"typeArguments":null}],"name":"main","output":{"name":"","type":0,"typeArguments":null},"attributes":null}], -"loggedTypes":[],"messagesTypes":[],"configurables":[]}"#; - let generated_call_handler = ScriptCallHandler::from_json_abi_str(test_json_abi).unwrap(); + let generated_call_handler = ScriptCallHandler::from_json_abi_str(TEST_JSON_ABI).unwrap(); let expected_call_handler = ScriptCallHandler { main_arg_types: vec![Type::U8, Type::Bool], @@ -88,12 +92,7 @@ mod tests { #[test] fn test_main_encoding_success() { - let test_json_abi = r#"{"types":[{"typeId":0,"type":"()","components":[],"typeParameters":null}, -{"typeId":1,"type":"bool","components":null,"typeParameters":null},{"typeId":2,"type":"u8","components":null, -"typeParameters":null}],"functions":[{"inputs":[{"name":"test_u8","type":2,"typeArguments":null},{"name":"test_bool", -"type":1,"typeArguments":null}],"name":"main","output":{"name":"","type":0,"typeArguments":null},"attributes":null}], -"loggedTypes":[],"messagesTypes":[],"configurables":[]}"#; - let call_handler = ScriptCallHandler::from_json_abi_str(test_json_abi).unwrap(); + let call_handler = ScriptCallHandler::from_json_abi_str(TEST_JSON_ABI).unwrap(); let values = ["2", "true"]; let encoded_bytes = call_handler.encode_arguments(&values).unwrap(); @@ -104,12 +103,7 @@ mod tests { #[test] #[should_panic] fn test_main_encoding_fail_arg_type_mismatch() { - let test_json_abi = r#"{"types":[{"typeId":0,"type":"()","components":[],"typeParameters":null}, -{"typeId":1,"type":"bool","components":null,"typeParameters":null},{"typeId":2,"type":"u8","components":null, -"typeParameters":null}],"functions":[{"inputs":[{"name":"test_u8","type":2,"typeArguments":null},{"name":"test_bool", -"type":1,"typeArguments":null}],"name":"main","output":{"name":"","type":0,"typeArguments":null},"attributes":null}], -"loggedTypes":[],"messagesTypes":[],"configurables":[]}"#; - let call_handler = ScriptCallHandler::from_json_abi_str(test_json_abi).unwrap(); + let call_handler = ScriptCallHandler::from_json_abi_str(TEST_JSON_ABI).unwrap(); // The abi describes the following main function: // - fn main(test_u8: u8, test_bool: bool) // Providing a bool to u8 field should return an error. @@ -120,12 +114,7 @@ mod tests { #[test] #[should_panic(expected = "main function takes 2 arguments, 1 provided")] fn test_main_encoding_fail_arg_count_mismatch() { - let test_json_abi = r#"{"types":[{"typeId":0,"type":"()","components":[],"typeParameters":null}, -{"typeId":1,"type":"bool","components":null,"typeParameters":null},{"typeId":2,"type":"u8","components":null, -"typeParameters":null}],"functions":[{"inputs":[{"name":"test_u8","type":2,"typeArguments":null},{"name":"test_bool", -"type":1,"typeArguments":null}],"name":"main","output":{"name":"","type":0,"typeArguments":null},"attributes":null}], -"loggedTypes":[],"messagesTypes":[],"configurables":[]}"#; - let call_handler = ScriptCallHandler::from_json_abi_str(test_json_abi).unwrap(); + let call_handler = ScriptCallHandler::from_json_abi_str(TEST_JSON_ABI).unwrap(); // The abi describes the following main function: // - fn main(test_u8: u8, test_bool: bool) // Providing only 1 value should return an error as function requires 2 args. diff --git a/forc-plugins/forc-client/src/op/run/mod.rs b/forc-plugins/forc-client/src/op/run/mod.rs index 0ea4f073b2a..5e58835fca0 100644 --- a/forc-plugins/forc-client/src/op/run/mod.rs +++ b/forc-plugins/forc-client/src/op/run/mod.rs @@ -1,11 +1,11 @@ mod encode; use crate::{ cmd, + constants::TX_SUBMIT_TIMEOUT_MS, util::{ - gas::get_script_gas_used, node_url::get_node_url, pkg::built_pkgs, - tx::{TransactionBuilderExt, WalletSelectionMode, TX_SUBMIT_TIMEOUT_MS}, + tx::{prompt_forc_wallet_password, select_account, SignerSelectionMode}, }, }; use anyhow::{anyhow, bail, Context, Result}; @@ -13,8 +13,16 @@ use forc_pkg::{self as pkg, fuel_core_not_running, PackageManifestFile}; use forc_tracing::println_warning; use forc_util::tx_utils::format_log_receipts; use fuel_core_client::client::FuelClient; -use fuel_tx::{ContractId, Transaction, TransactionBuilder}; -use fuels_accounts::provider::Provider; +use fuel_tx::{ContractId, Transaction}; +use fuels::{ + programs::calls::{traits::TransactionTuner, ScriptCall}, + types::{ + bech32::Bech32ContractId, + transaction::TxPolicies, + transaction_builders::{BuildableTransaction, VariableOutputPolicy}, + }, +}; +use fuels_accounts::{provider::Provider, Account}; use pkg::{manifest::build_profile::ExperimentalFlags, BuiltPackage}; use std::time::Duration; use std::{path::PathBuf, str::FromStr}; @@ -49,6 +57,12 @@ pub async fn run(command: cmd::Run) -> Result> { }; let build_opts = build_opts_from_cmd(&command); let built_pkgs_with_manifest = built_pkgs(&curr_dir, &build_opts)?; + let wallet_mode = if command.default_signer || command.signing_key.is_some() { + SignerSelectionMode::Manual + } else { + let password = prompt_forc_wallet_password()?; + SignerSelectionMode::ForcWallet(password) + }; for built in built_pkgs_with_manifest { if built .descriptor @@ -56,7 +70,13 @@ pub async fn run(command: cmd::Run) -> Result> { .check_program_type(&[TreeType::Script]) .is_ok() { - let pkg_receipts = run_pkg(&command, &built.descriptor.manifest_file, &built).await?; + let pkg_receipts = run_pkg( + &command, + &built.descriptor.manifest_file, + &built, + &wallet_mode, + ) + .await?; receipts.push(pkg_receipts); } } @@ -64,12 +84,34 @@ pub async fn run(command: cmd::Run) -> Result> { Ok(receipts) } +fn tx_policies_from_cmd(cmd: &cmd::Run) -> TxPolicies { + let mut tx_policies = TxPolicies::default(); + if let Some(max_fee) = cmd.gas.max_fee { + tx_policies = tx_policies.with_max_fee(max_fee); + } + if let Some(script_gas_limit) = cmd.gas.script_gas_limit { + tx_policies = tx_policies.with_script_gas_limit(script_gas_limit); + } + tx_policies +} + pub async fn run_pkg( command: &cmd::Run, manifest: &PackageManifestFile, compiled: &BuiltPackage, + signer_mode: &SignerSelectionMode, ) -> Result { let node_url = get_node_url(&command.node, &manifest.network)?; + let provider = Provider::connect(node_url.clone()).await?; + let tx_count = 1; + let account = select_account( + signer_mode, + command.default_signer || command.unsigned, + command.signing_key, + &provider, + tx_count, + ) + .await?; let script_data = match (&command.data, &command.args) { (None, Some(args)) => { @@ -101,37 +143,29 @@ pub async fn run_pkg( .map_err(|e| anyhow!("Failed to parse contract id: {}", e)) }) .collect::>>()?; - let wallet_mode = if command.manual_signing { - WalletSelectionMode::Manual - } else { - WalletSelectionMode::ForcWallet - }; - - let mut tb = TransactionBuilder::script(compiled.bytecode.bytes.clone(), script_data); - tb.maturity(command.maturity.maturity.into()) - .add_contracts(contract_ids); - let provider = Provider::connect(node_url.clone()).await?; - - let script_gas_limit = if compiled.bytecode.bytes.is_empty() { - 0 - } else if let Some(script_gas_limit) = command.gas.script_gas_limit { - script_gas_limit - // Dry run tx and get `gas_used` - } else { - get_script_gas_used(tb.clone().finalize_without_signature_inner(), &provider).await? + let script_binary = compiled.bytecode.bytes.clone(); + let external_contracts = contract_ids + .into_iter() + .map(Bech32ContractId::from) + .collect::>(); + let call = ScriptCall { + script_binary, + encoded_args: Ok(script_data), + inputs: vec![], + outputs: vec![], + external_contracts, }; - tb.script_gas_limit(script_gas_limit); - - let tx = tb - .finalize_signed( - Provider::connect(node_url.clone()).await?, - command.default_signer, - command.signing_key, - wallet_mode, - ) + let tx_policies = tx_policies_from_cmd(command); + let mut tb = call + .transaction_builder(tx_policies, VariableOutputPolicy::EstimateMinimum, &account) .await?; + account.add_witnesses(&mut tb)?; + account.adjust_for_fee(&mut tb, 0).await?; + + let tx = tb.build(provider).await?; + if command.dry_run { info!("{:?}", tx); Ok(RanScript { receipts: vec![] }) @@ -212,7 +246,6 @@ fn build_opts_from_cmd(cmd: &cmd::Run) -> pkg::BuildOpts { terse: cmd.pkg.terse, locked: cmd.pkg.locked, output_directory: cmd.pkg.output_directory.clone(), - json_abi_with_callpaths: cmd.pkg.json_abi_with_callpaths, ipfs_node: cmd.pkg.ipfs_node.clone().unwrap_or_default(), }, print: pkg::PrintOpts { @@ -221,6 +254,7 @@ fn build_opts_from_cmd(cmd: &cmd::Run) -> pkg::BuildOpts { dca_graph_url_format: cmd.print.dca_graph_url_format.clone(), asm: cmd.print.asm(), bytecode: cmd.print.bytecode, + bytecode_spans: false, ir: cmd.print.ir(), reverse_order: cmd.print.reverse_order, }, diff --git a/forc-plugins/forc-client/src/util/account.rs b/forc-plugins/forc-client/src/util/account.rs new file mode 100644 index 00000000000..17ecc6781b8 --- /dev/null +++ b/forc-plugins/forc-client/src/util/account.rs @@ -0,0 +1,87 @@ +use async_trait::async_trait; +use fuel_crypto::{Message, Signature}; +use fuels::{ + prelude::*, + types::{coin_type_id::CoinTypeId, input::Input}, +}; +use fuels_accounts::{wallet::WalletUnlocked, Account}; + +use super::aws::AwsSigner; + +#[derive(Clone, Debug)] +/// Set of different signers available to be used with `forc-client` operations. +pub enum ForcClientAccount { + /// Local signer where the private key owned locally. This can be + /// generated through `forc-wallet` integration or manually by providing + /// a private-key. + Wallet(WalletUnlocked), + /// A KMS Signer specifically using AWS KMS service. The signing key + /// is managed by another entity for KMS signers. Messages are + /// signed by the KMS entity. Signed transactions are retrieved + /// and submitted to the node by `forc-client`. + KmsSigner(AwsSigner), +} + +#[async_trait] +impl Account for ForcClientAccount { + async fn get_asset_inputs_for_amount( + &self, + asset_id: AssetId, + amount: u64, + excluded_coins: Option>, + ) -> Result> { + match self { + ForcClientAccount::Wallet(wallet) => { + wallet + .get_asset_inputs_for_amount(asset_id, amount, excluded_coins) + .await + } + ForcClientAccount::KmsSigner(account) => { + account + .get_asset_inputs_for_amount(asset_id, amount, excluded_coins) + .await + } + } + } + + fn add_witnesses(&self, tb: &mut Tb) -> Result<()> { + tb.add_signer(self.clone())?; + + Ok(()) + } +} + +impl ViewOnlyAccount for ForcClientAccount { + fn address(&self) -> &Bech32Address { + match self { + ForcClientAccount::Wallet(wallet) => wallet.address(), + ForcClientAccount::KmsSigner(account) => { + fuels_accounts::ViewOnlyAccount::address(account) + } + } + } + + fn try_provider(&self) -> Result<&Provider> { + match self { + ForcClientAccount::Wallet(wallet) => wallet.try_provider(), + ForcClientAccount::KmsSigner(account) => Ok(account.provider()), + } + } +} + +#[async_trait] +impl Signer for ForcClientAccount { + async fn sign(&self, message: Message) -> Result { + match self { + ForcClientAccount::Wallet(wallet) => wallet.sign(message).await, + ForcClientAccount::KmsSigner(account) => account.sign(message).await, + } + } + + fn address(&self) -> &Bech32Address { + match self { + ForcClientAccount::Wallet(wallet) => wallet.address(), + ForcClientAccount::KmsSigner(account) => fuels_core::traits::Signer::address(account), + } + } +} diff --git a/forc-plugins/forc-client/src/util/aws.rs b/forc-plugins/forc-client/src/util/aws.rs new file mode 100644 index 00000000000..90da533815c --- /dev/null +++ b/forc-plugins/forc-client/src/util/aws.rs @@ -0,0 +1,269 @@ +use async_trait::async_trait; +use aws_config::{default_provider::credentials::DefaultCredentialsChain, Region, SdkConfig}; +use aws_sdk_kms::config::Credentials; +use aws_sdk_kms::operation::get_public_key::GetPublicKeyOutput; +use aws_sdk_kms::primitives::Blob; +use aws_sdk_kms::types::{MessageType, SigningAlgorithmSpec}; +use aws_sdk_kms::{config::BehaviorVersion, Client}; +use fuel_crypto::Message; +use fuels::prelude::*; +use fuels::types::bech32::{Bech32Address, FUEL_BECH32_HRP}; +use fuels::types::coin_type_id::CoinTypeId; +use fuels::types::input::Input; +use fuels_accounts::provider::Provider; +use fuels_accounts::{Account, ViewOnlyAccount}; +use fuels_core::traits::Signer; + +/// AWS configuration for the `AwsSigner` to be created. +/// De-facto way of creating the configuration is to load it from env. +#[derive(Debug, Clone)] +pub struct AwsConfig { + sdk_config: SdkConfig, +} + +impl AwsConfig { + /// Load configuration from environment variables. + /// For more details see: https://docs.rs/aws-config/latest/aws_config/ + pub async fn from_env() -> Self { + let loader = aws_config::defaults(BehaviorVersion::latest()) + .credentials_provider(DefaultCredentialsChain::builder().build().await); + + let loader = match std::env::var("E2E_TEST_AWS_ENDPOINT") { + Ok(url) => loader.endpoint_url(url), + _ => loader, + }; + + Self { + sdk_config: loader.load().await, + } + } + + pub async fn for_testing(url: String) -> Self { + let sdk_config = aws_config::defaults(BehaviorVersion::latest()) + .credentials_provider(Credentials::new( + "test", + "test", + None, + None, + "Static Credentials", + )) + .endpoint_url(url) + .region(Region::new("us-east-1")) // placeholder region for test + .load() + .await; + + Self { sdk_config } + } + + pub fn url(&self) -> Option<&str> { + self.sdk_config.endpoint_url() + } + + pub fn region(&self) -> Option<&Region> { + self.sdk_config.region() + } +} + +/// A configured `AwsClient` which allows using the AWS KMS SDK. +#[derive(Clone, Debug)] +pub struct AwsClient { + client: Client, +} + +impl AwsClient { + pub fn new(config: AwsConfig) -> Self { + let config = config.sdk_config; + let client = Client::new(&config); + + Self { client } + } + + pub fn inner(&self) -> &Client { + &self.client + } +} + +/// A signer which is capable of signing `fuel_crypto::Message`s using AWS KMS. +/// This is both a `Signer` and `Account`, which means it is directly usable +/// with most of the fuels-* calls, without any additional operations on the +/// representation. +#[derive(Clone, Debug)] +pub struct AwsSigner { + kms: AwsClient, + key_id: String, + bech: Bech32Address, + public_key_bytes: Vec, + provider: Provider, +} + +async fn request_get_pubkey( + kms: &Client, + key_id: String, +) -> std::result::Result { + kms.get_public_key() + .key_id(key_id) + .send() + .await + .map_err(Into::into) +} + +/// Decode an AWS KMS Pubkey response. +fn decode_pubkey(resp: &GetPublicKeyOutput) -> std::result::Result, anyhow::Error> { + let raw = resp + .public_key + .as_ref() + .ok_or(anyhow::anyhow!("public key not found"))?; + Ok(raw.clone().into_inner()) +} + +async fn sign_with_kms( + client: &aws_sdk_kms::Client, + key_id: &str, + public_key_bytes: &[u8], + message: Message, +) -> anyhow::Result { + use k256::{ + ecdsa::{RecoveryId, VerifyingKey}, + pkcs8::DecodePublicKey, + }; + + let reply = client + .sign() + .key_id(key_id) + .signing_algorithm(SigningAlgorithmSpec::EcdsaSha256) + .message_type(MessageType::Digest) + .message(Blob::new(*message)) + .send() + .await + .inspect_err(|err| tracing::error!("Failed to sign with AWS KMS: {err:?}"))?; + let signature_der = reply + .signature + .ok_or_else(|| anyhow::anyhow!("no signature returned from AWS KMS"))? + .into_inner(); + // https://stackoverflow.com/a/71475108 + let sig = k256::ecdsa::Signature::from_der(&signature_der) + .map_err(|_| anyhow::anyhow!("invalid DER signature from AWS KMS"))?; + let sig = sig.normalize_s().unwrap_or(sig); + + // This is a hack to get the recovery id. The signature should be normalized + // before computing the recovery id, but aws kms doesn't support this, and + // instead always computes the recovery id from non-normalized signature. + // So instead the recovery id is determined by checking which variant matches + // the original public key. + + let recid1 = RecoveryId::new(false, false); + let recid2 = RecoveryId::new(true, false); + + let rec1 = VerifyingKey::recover_from_prehash(&*message, &sig, recid1); + let rec2 = VerifyingKey::recover_from_prehash(&*message, &sig, recid2); + + let correct_public_key = k256::PublicKey::from_public_key_der(public_key_bytes) + .map_err(|_| anyhow::anyhow!("invalid DER public key from AWS KMS"))? + .into(); + + let recovery_id = if rec1.map(|r| r == correct_public_key).unwrap_or(false) { + recid1 + } else if rec2.map(|r| r == correct_public_key).unwrap_or(false) { + recid2 + } else { + anyhow::bail!("Invalid signature generated (reduced-x form coordinate)"); + }; + + // Insert the recovery id into the signature + debug_assert!( + !recovery_id.is_x_reduced(), + "reduced-x form coordinates are caught by the if-else chain above" + ); + let v = recovery_id.is_y_odd() as u8; + let mut signature = <[u8; 64]>::from(sig.to_bytes()); + signature[32] = (v << 7) | (signature[32] & 0x7f); + Ok(fuel_crypto::Signature::from_bytes(signature)) +} + +impl AwsSigner { + pub async fn new( + kms: AwsClient, + key_id: String, + provider: Provider, + ) -> std::result::Result { + use k256::pkcs8::DecodePublicKey; + + let resp = request_get_pubkey(kms.inner(), key_id.clone()).await?; + let public_key_bytes = decode_pubkey(&resp)?; + let k256_public_key = k256::PublicKey::from_public_key_der(&public_key_bytes)?; + + let public_key = fuel_crypto::PublicKey::from(k256_public_key); + let hashed = public_key.hash(); + let bech = Bech32Address::new(FUEL_BECH32_HRP, hashed); + Ok(Self { + kms, + key_id, + bech, + public_key_bytes, + provider, + }) + } + + /// Sign a digest with the key associated with a key ID. + pub async fn sign_message_with_key( + &self, + key_id: String, + message: Message, + ) -> std::result::Result { + sign_with_kms(self.kms.inner(), &key_id, &self.public_key_bytes, message).await + } + + /// Sign a digest with this signer's key. + pub async fn sign_message( + &self, + message: Message, + ) -> std::result::Result { + self.sign_message_with_key(self.key_id.clone(), message) + .await + } + + pub fn provider(&self) -> &Provider { + &self.provider + } +} + +#[async_trait] +impl Signer for AwsSigner { + async fn sign(&self, message: Message) -> Result { + let sig = self.sign_message(message).await.map_err(|_| { + fuels_core::types::errors::Error::Other("aws signer failed".to_string()) + })?; + Ok(sig) + } + + fn address(&self) -> &Bech32Address { + &self.bech + } +} + +impl ViewOnlyAccount for AwsSigner { + fn address(&self) -> &Bech32Address { + &self.bech + } + + fn try_provider(&self) -> Result<&Provider> { + Ok(&self.provider) + } +} + +#[async_trait] +impl Account for AwsSigner { + async fn get_asset_inputs_for_amount( + &self, + asset_id: AssetId, + amount: u64, + excluded_coins: Option>, + ) -> Result> { + Ok(self + .get_spendable_resources(asset_id, amount, excluded_coins) + .await? + .into_iter() + .map(Input::resource_signed) + .collect::>()) + } +} diff --git a/forc-plugins/forc-client/src/util/gas.rs b/forc-plugins/forc-client/src/util/gas.rs deleted file mode 100644 index 8ccc885488f..00000000000 --- a/forc-plugins/forc-client/src/util/gas.rs +++ /dev/null @@ -1,112 +0,0 @@ -use anyhow::Result; - -use fuel_core_client::client::FuelClient; -use fuel_core_types::services::executor::TransactionExecutionResult; -use fuel_tx::{ - field::{Inputs, MaxFeeLimit, Witnesses}, - Buildable, Chargeable, Create, Input, Script, Transaction, TxPointer, -}; -use fuels_accounts::provider::Provider; -use fuels_core::{ - constants::DEFAULT_GAS_ESTIMATION_BLOCK_HORIZON, types::transaction_builders::DryRunner, -}; - -fn no_spendable_input<'a, I: IntoIterator>(inputs: I) -> bool { - !inputs.into_iter().any(|i| { - matches!( - i, - Input::CoinSigned(_) - | Input::CoinPredicate(_) - | Input::MessageCoinSigned(_) - | Input::MessageCoinPredicate(_) - ) - }) -} - -pub(crate) async fn get_script_gas_used(mut tx: Script, provider: &Provider) -> Result { - let no_spendable_input = no_spendable_input(tx.inputs()); - let base_asset_id = provider.base_asset_id(); - if no_spendable_input { - tx.inputs_mut().push(Input::coin_signed( - Default::default(), - Default::default(), - 1_000_000_000, - *base_asset_id, - TxPointer::default(), - 0, - )); - - // Add an empty `Witness` for the `coin_signed` we just added - // and increase the witness limit - tx.witnesses_mut().push(Default::default()); - } - let consensus_params = provider.consensus_parameters(); - - // Get `max_gas` used by everything except the script execution. Add `1` because of rounding. - let max_gas_per_tx = consensus_params.tx_params().max_gas_per_tx(); - let max_gas = tx.max_gas(consensus_params.gas_costs(), consensus_params.fee_params()) + 1; - // Increase `script_gas_limit` to the maximum allowed value. - tx.set_script_gas_limit(max_gas_per_tx - max_gas); - - get_gas_used(Transaction::Script(tx), provider).await -} - -/// Returns gas_used for an arbitrary tx, by doing dry run with the provided `Provider`. -pub(crate) async fn get_gas_used(tx: Transaction, provider: &Provider) -> Result { - let tolerance = 0.1; - let gas_used = provider.dry_run_and_get_used_gas(tx, tolerance).await?; - Ok(gas_used) -} - -/// Returns an estimation for the max fee of `Create` transactions. -/// Accepts a `tolerance` which is used to add some safety margin to the estimation. -/// Resulting estimation is calculated as `(dry_run_estimation * tolerance)/100 + dry_run_estimation)`. -pub(crate) async fn get_estimated_max_fee( - tx: Create, - provider: &Provider, - client: &FuelClient, - tolerance: u64, -) -> Result { - let mut tx = tx.clone(); - // Add dummy input to get past validation for dry run. - let no_spendable_input = no_spendable_input(tx.inputs()); - let base_asset_id = provider.base_asset_id(); - if no_spendable_input { - tx.inputs_mut().push(Input::coin_signed( - Default::default(), - Default::default(), - 1_000_000_000, - *base_asset_id, - TxPointer::default(), - 0, - )); - - // Add an empty `Witness` for the `coin_signed` we just added - // and increase the witness limit - tx.witnesses_mut().push(Default::default()); - } - let consensus_params = provider.consensus_parameters(); - let gas_price = provider - .estimate_gas_price(DEFAULT_GAS_ESTIMATION_BLOCK_HORIZON) - .await? - .gas_price; - let max_fee = tx.max_fee( - consensus_params.gas_costs(), - consensus_params.fee_params(), - gas_price, - ); - tx.set_max_fee_limit(max_fee as u64); - let tx = Transaction::from(tx); - - let tx_status = client - .dry_run_opt(&[tx], Some(false)) - .await - .map(|mut status_vec| status_vec.remove(0))?; - let total_fee = match tx_status.result { - TransactionExecutionResult::Success { total_fee, .. } => total_fee, - TransactionExecutionResult::Failed { total_fee, .. } => total_fee, - }; - - let total_fee_with_tolerance = ((total_fee * tolerance) / 100) + total_fee; - Ok(total_fee_with_tolerance) -} diff --git a/forc-plugins/forc-client/src/util/mod.rs b/forc-plugins/forc-client/src/util/mod.rs index 3b99a89659f..2e58fc41c79 100644 --- a/forc-plugins/forc-client/src/util/mod.rs +++ b/forc-plugins/forc-client/src/util/mod.rs @@ -1,6 +1,7 @@ +pub mod account; +pub mod aws; pub(crate) mod encode; -pub(crate) mod gas; pub(crate) mod node_url; pub(crate) mod pkg; pub(crate) mod target; -pub(crate) mod tx; +pub mod tx; diff --git a/forc-plugins/forc-client/src/util/node_url.rs b/forc-plugins/forc-client/src/util/node_url.rs index b7fe3f8bf39..58e9dcd87e1 100644 --- a/forc-plugins/forc-client/src/util/node_url.rs +++ b/forc-plugins/forc-client/src/util/node_url.rs @@ -12,18 +12,22 @@ pub fn get_node_url( ) -> Result { let node_url = match ( node_target.testnet, + node_target.mainnet, node_target.target.clone(), node_target.node_url.clone(), ) { - (true, None, None) => Target::testnet().target_url(), - (false, Some(target), None) => target.target_url(), - (false, None, Some(node_url)) => node_url, - (false, None, None) => manifest_network + (true, false, None, None) => Target::testnet().target_url(), + (false, true, None, None) => Target::mainnet().target_url(), + (false, false, Some(target), None) => target.target_url(), + (false, false, None, Some(node_url)) => node_url, + (false, false, None, None) => manifest_network .as_ref() .map(|nw| &nw.url[..]) .unwrap_or(crate::constants::NODE_URL) .to_string(), - _ => bail!("Only one of `--testnet`, `--target`, or `--node-url` should be specified"), + _ => bail!( + "Only one of `--testnet`, `--mainnet`, `--target`, or `--node-url` should be specified" + ), }; Ok(node_url) @@ -35,6 +39,7 @@ fn test_get_node_url_testnet() { target: None, node_url: None, testnet: true, + mainnet: false, }; let actual = get_node_url(&input, &None).unwrap(); @@ -42,63 +47,41 @@ fn test_get_node_url_testnet() { } #[test] -fn test_get_node_url_target_devnet() { +fn test_get_node_url_mainnet() { let input = NodeTarget { - target: Some(Target::Devnet), - node_url: None, - testnet: false, - }; - let actual = get_node_url(&input, &None).unwrap(); - assert_eq!("https://devnet.fuel.network", actual); -} - -#[test] -fn test_get_node_url_target_testnet() { - let input = NodeTarget { - target: Some(Target::Testnet), + target: None, node_url: None, testnet: false, + mainnet: true, }; let actual = get_node_url(&input, &None).unwrap(); - assert_eq!("https://testnet.fuel.network", actual); + assert_eq!("https://mainnet.fuel.network", actual); } #[test] -fn test_get_node_url_beta5() { +fn test_get_node_url_target_mainnet() { let input = NodeTarget { - target: Some(Target::Beta5), + target: Some(Target::Mainnet), node_url: None, testnet: false, + mainnet: false, }; let actual = get_node_url(&input, &None).unwrap(); - assert_eq!("https://beta-5.fuel.network", actual); + assert_eq!("https://mainnet.fuel.network", actual); } #[test] -fn test_get_node_url_beta4() { - let input = NodeTarget { - target: None, - node_url: Some("https://beta-4.fuel.network".to_string()), - testnet: false, - }; - let actual = get_node_url(&input, &None).unwrap(); - assert_eq!("https://beta-4.fuel.network", actual); -} - -#[test] -fn test_get_node_url_url_beta4_manifest() { - let network = Network { - url: "https://beta-4.fuel.network".to_string(), - }; +fn test_get_node_url_target_testnet() { let input = NodeTarget { - target: None, + target: Some(Target::Testnet), node_url: None, testnet: false, + mainnet: false, }; - let actual = get_node_url(&input, &Some(network)).unwrap(); - assert_eq!("https://beta-4.fuel.network", actual); + let actual = get_node_url(&input, &None).unwrap(); + assert_eq!("https://testnet.fuel.network", actual); } #[test] @@ -107,29 +90,20 @@ fn test_get_node_url_default() { target: None, node_url: None, testnet: false, + mainnet: false, }; let actual = get_node_url(&input, &None).unwrap(); assert_eq!("http://127.0.0.1:4000", actual); } -#[test] -fn test_get_node_url_beta3() { - let input = NodeTarget { - target: Some(Target::Beta3), - node_url: None, - testnet: false, - }; - let actual = get_node_url(&input, &None).unwrap(); - assert_eq!("https://beta-3.fuel.network", actual); -} - #[test] fn test_get_node_url_local() { let input = NodeTarget { target: Some(Target::Local), node_url: None, testnet: false, + mainnet: false, }; let actual = get_node_url(&input, &None).unwrap(); assert_eq!("http://127.0.0.1:4000", actual); @@ -137,26 +111,28 @@ fn test_get_node_url_local() { #[test] #[should_panic( - expected = "Only one of `--testnet`, `--target`, or `--node-url` should be specified" + expected = "Only one of `--testnet`, `--mainnet`, `--target`, or `--node-url` should be specified" )] fn test_get_node_url_local_testnet() { let input = NodeTarget { target: Some(Target::Local), node_url: None, testnet: true, + mainnet: false, }; get_node_url(&input, &None).unwrap(); } #[test] #[should_panic( - expected = "Only one of `--testnet`, `--target`, or `--node-url` should be specified" + expected = "Only one of `--testnet`, `--mainnet`, `--target`, or `--node-url` should be specified" )] fn test_get_node_url_same_url() { let input = NodeTarget { - target: Some(Target::Beta3), - node_url: Some("beta-3.fuel.network".to_string()), + target: Some(Target::Testnet), + node_url: Some("testnet.fuel.network".to_string()), testnet: false, + mainnet: false, }; get_node_url(&input, &None).unwrap(); } diff --git a/forc-plugins/forc-client/src/util/pkg.rs b/forc-plugins/forc-client/src/util/pkg.rs index f7b6384cb74..c93df24bacc 100644 --- a/forc-plugins/forc-client/src/util/pkg.rs +++ b/forc-plugins/forc-client/src/util/pkg.rs @@ -1,9 +1,62 @@ use anyhow::Result; use forc_pkg::manifest::GenericManifestFile; use forc_pkg::{self as pkg, manifest::ManifestFile, BuildOpts, BuildPlan}; -use pkg::{build_with_options, BuiltPackage}; +use forc_util::user_forc_directory; +use pkg::{build_with_options, BuiltPackage, PackageManifestFile}; +use std::fs::File; +use std::io::{Read, Write}; +use std::path::PathBuf; use std::{collections::HashMap, path::Path, sync::Arc}; +/// The name of the folder that forc generated proxy contract project will reside at. +pub const GENERATED_CONTRACT_FOLDER_NAME: &str = ".generated_contracts"; +pub const PROXY_CONTRACT_BIN: &[u8] = include_bytes!("../../proxy_abi/proxy_contract.bin"); +pub const PROXY_CONTRACT_STORAGE_SLOTS: &str = + include_str!("../../proxy_abi/proxy_contract-storage_slots.json"); +pub const PROXY_BIN_FILE_NAME: &str = "proxy.bin"; +pub const PROXY_STORAGE_SLOTS_FILE_NAME: &str = "proxy-storage_slots.json"; + +/// Updates the given package manifest file such that the address field under the proxy table updated to the given value. +/// Updated manifest file is written back to the same location, without thouching anything else such as comments etc. +/// A safety check is done to ensure the proxy table exists before attempting to udpdate the value. +pub(crate) fn update_proxy_address_in_manifest( + address: &str, + manifest: &PackageManifestFile, +) -> Result<()> { + let mut toml = String::new(); + let mut file = File::open(manifest.path())?; + file.read_to_string(&mut toml)?; + let mut manifest_toml = toml.parse::()?; + if manifest.proxy().is_some() { + manifest_toml["proxy"]["address"] = toml_edit::value(address); + let mut file = std::fs::OpenOptions::new() + .write(true) + .truncate(true) + .open(manifest.path())?; + file.write_all(manifest_toml.to_string().as_bytes())?; + } + Ok(()) +} + +/// Creates a proxy contract project at the given path, adds a forc.toml and source file. +pub(crate) fn create_proxy_contract(pkg_name: &str) -> Result { + // Create the proxy contract folder. + let proxy_contract_dir = user_forc_directory() + .join(GENERATED_CONTRACT_FOLDER_NAME) + .join(format!("{}-proxy", pkg_name)); + std::fs::create_dir_all(&proxy_contract_dir)?; + std::fs::write( + proxy_contract_dir.join(PROXY_BIN_FILE_NAME), + PROXY_CONTRACT_BIN, + )?; + std::fs::write( + proxy_contract_dir.join(PROXY_STORAGE_SLOTS_FILE_NAME), + PROXY_CONTRACT_STORAGE_SLOTS, + )?; + + Ok(proxy_contract_dir) +} + pub(crate) fn built_pkgs(path: &Path, build_opts: &BuildOpts) -> Result>> { let manifest_file = ManifestFile::from_dir(path)?; let lock_path = manifest_file.lock_path()?; diff --git a/forc-plugins/forc-client/src/util/target.rs b/forc-plugins/forc-client/src/util/target.rs index 8c9d598ab4d..bbc5679e844 100644 --- a/forc-plugins/forc-client/src/util/target.rs +++ b/forc-plugins/forc-client/src/util/target.rs @@ -1,7 +1,6 @@ use crate::constants::{ - BETA_2_ENDPOINT_URL, BETA_2_FAUCET_URL, BETA_3_ENDPOINT_URL, BETA_3_FAUCET_URL, - BETA_4_ENDPOINT_URL, BETA_4_FAUCET_URL, BETA_5_ENDPOINT_URL, BETA_5_FAUCET_URL, - DEVNET_ENDPOINT_URL, DEVNET_FAUCET_URL, NODE_URL, TESTNET_ENDPOINT_URL, TESTNET_FAUCET_URL, + MAINNET_ENDPOINT_URL, MAINNET_EXPLORER_URL, NODE_URL, TESTNET_ENDPOINT_URL, + TESTNET_EXPLORER_URL, TESTNET_FAUCET_URL, }; use anyhow::{bail, Result}; use serde::{Deserialize, Serialize}; @@ -10,12 +9,8 @@ use std::str::FromStr; #[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)] /// Possible target values that forc-client can interact with. pub enum Target { - Beta2, - Beta3, - Beta4, - Beta5, - Devnet, Testnet, + Mainnet, Local, } @@ -28,12 +23,8 @@ impl Default for Target { impl Target { pub fn target_url(&self) -> String { let url = match self { - Target::Beta2 => BETA_2_ENDPOINT_URL, - Target::Beta3 => BETA_3_ENDPOINT_URL, - Target::Beta4 => BETA_4_ENDPOINT_URL, - Target::Beta5 => BETA_5_ENDPOINT_URL, - Target::Devnet => DEVNET_ENDPOINT_URL, Target::Testnet => TESTNET_ENDPOINT_URL, + Target::Mainnet => MAINNET_ENDPOINT_URL, Target::Local => NODE_URL, }; url.to_string() @@ -41,30 +32,38 @@ impl Target { pub fn from_target_url(target_url: &str) -> Option { match target_url { - BETA_2_ENDPOINT_URL => Some(Target::Beta2), - BETA_3_ENDPOINT_URL => Some(Target::Beta3), - BETA_4_ENDPOINT_URL => Some(Target::Beta4), - BETA_5_ENDPOINT_URL => Some(Target::Beta5), - DEVNET_ENDPOINT_URL => Some(Target::Devnet), TESTNET_ENDPOINT_URL => Some(Target::Testnet), + MAINNET_ENDPOINT_URL => Some(Target::Mainnet), NODE_URL => Some(Target::Local), _ => None, } } + pub fn local() -> Self { + Target::Local + } + pub fn testnet() -> Self { Target::Testnet } - pub fn faucet_url(&self) -> String { + pub fn mainnet() -> Self { + Target::Mainnet + } + + pub fn faucet_url(&self) -> Option { match self { - Target::Beta2 => BETA_2_FAUCET_URL.to_string(), - Target::Beta3 => BETA_3_FAUCET_URL.to_string(), - Target::Beta4 => BETA_4_FAUCET_URL.to_string(), - Target::Beta5 => BETA_5_FAUCET_URL.to_string(), - Target::Devnet => DEVNET_FAUCET_URL.to_string(), - Target::Testnet => TESTNET_FAUCET_URL.to_string(), - Target::Local => "http://localhost:3000".to_string(), + Target::Testnet => Some(TESTNET_FAUCET_URL.to_string()), + Target::Mainnet => None, + Target::Local => Some("http://localhost:3000".to_string()), + } + } + + pub fn explorer_url(&self) -> Option { + match self { + Target::Testnet => Some(TESTNET_EXPLORER_URL.to_string()), + Target::Mainnet => Some(MAINNET_EXPLORER_URL.to_string()), + _ => None, } } } @@ -74,21 +73,13 @@ impl FromStr for Target { fn from_str(s: &str) -> Result { match s { - "beta-2" => Ok(Target::Beta2), - "beta-3" => Ok(Target::Beta3), - "beta-4" => Ok(Target::Beta4), - "beta-5" => Ok(Target::Beta5), - "devnet" => Ok(Target::Devnet), - "testnet" => Ok(Target::Testnet), + "Fuel Sepolia Testnet" => Ok(Target::Testnet), + "Ignition" => Ok(Target::Mainnet), "local" => Ok(Target::Local), _ => bail!( - "'{s}' is not a valid target name. Possible values: '{}', '{}', '{}', '{}', '{}', '{}', '{}'", - Target::Beta2, - Target::Beta3, - Target::Beta4, - Target::Beta5, - Target::Devnet, + "'{s}' is not a valid target name. Possible values: '{}', '{}', '{}'", Target::Testnet, + Target::Mainnet, Target::Local ), } @@ -98,12 +89,8 @@ impl FromStr for Target { impl std::fmt::Display for Target { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { let s = match self { - Target::Beta2 => "beta-2", - Target::Beta3 => "beta-3", - Target::Beta4 => "beta-4", - Target::Beta5 => "beta-5", - Target::Devnet => "devnet", - Target::Testnet => "testnet", + Target::Testnet => "Fuel Sepolia Testnet", + Target::Mainnet => "Ignition", Target::Local => "local", }; write!(f, "{}", s) diff --git a/forc-plugins/forc-client/src/util/tx.rs b/forc-plugins/forc-client/src/util/tx.rs index 84441b79933..e9f8b220121 100644 --- a/forc-plugins/forc-client/src/util/tx.rs +++ b/forc-plugins/forc-client/src/util/tx.rs @@ -1,71 +1,126 @@ -use std::{io::Write, str::FromStr}; - -use anyhow::{Error, Result}; -use async_trait::async_trait; -use forc_tracing::println_warning; - -use fuel_crypto::{Message, PublicKey, SecretKey, Signature}; -use fuel_tx::{field, Address, Buildable, ContractId, Input, Output, TransactionBuilder, Witness}; -use fuels_accounts::{provider::Provider, wallet::Wallet, ViewOnlyAccount}; -use fuels_core::types::{ - bech32::{Bech32Address, FUEL_BECH32_HRP}, - coin_type::CoinType, - transaction_builders::{create_coin_input, create_coin_message_input}, +use crate::{ + constants::DEFAULT_PRIVATE_KEY, + util::{account::ForcClientAccount, aws::AwsSigner, target::Target}, }; - +use anyhow::Result; +use dialoguer::{theme::ColorfulTheme, Confirm, Password, Select}; +use forc_tracing::{println_action_green, println_warning}; use forc_wallet::{ account::{derive_secret_key, new_at_index_cli}, balance::{ - collect_accounts_with_verification, print_account_balances, AccountBalances, - AccountVerification, AccountsMap, + collect_accounts_with_verification, AccountBalances, AccountVerification, AccountsMap, }, new::{new_wallet_cli, New}, utils::default_wallet_path, }; +use fuel_crypto::SecretKey; +use fuel_tx::{AssetId, ContractId}; +use fuels::{ + macros::abigen, programs::responses::CallResponse, types::checksum_address::checksum_encode, +}; +use fuels_accounts::{ + provider::Provider, + wallet::{Wallet, WalletUnlocked}, + ViewOnlyAccount, +}; +use std::{collections::BTreeMap, path::Path, str::FromStr}; -use crate::util::target::Target; - -/// The maximum time to wait for a transaction to be included in a block by the node -pub const TX_SUBMIT_TIMEOUT_MS: u64 = 30_000u64; - -/// Default PrivateKey to sign transactions submitted to local node. -pub const DEFAULT_PRIVATE_KEY: &str = - "0xde97d8624a438121b86a1956544bd72ed68cd69f2c99555b08b1e8c51ffd511c"; +use super::aws::{AwsClient, AwsConfig}; #[derive(PartialEq, Eq)] -pub enum WalletSelectionMode { - ForcWallet, +pub enum SignerSelectionMode { + /// Holds the password of forc-wallet instance. + ForcWallet(String), + /// Holds ARN of the AWS signer. + AwsSigner(String), Manual, } -fn prompt_address() -> Result { - print!("Please provide the address of the wallet you are going to sign this transaction with:"); - std::io::stdout().flush()?; - let mut buf = String::new(); - std::io::stdin().read_line(&mut buf)?; - Bech32Address::from_str(buf.trim()).map_err(Error::msg) +fn ask_user_yes_no_question(question: &str) -> Result { + let answer = Confirm::with_theme(&ColorfulTheme::default()) + .with_prompt(question) + .default(false) + .show_default(false) + .interact()?; + Ok(answer) +} + +fn collect_user_accounts( + wallet_path: &Path, + password: &str, +) -> Result> { + let verification = AccountVerification::Yes(password.to_string()); + let accounts = collect_accounts_with_verification(wallet_path, verification).map_err(|e| { + if e.to_string().contains("Mac Mismatch") { + anyhow::anyhow!("Failed to access forc-wallet vault. Please check your password") + } else { + e + } + })?; + Ok(accounts) } -fn prompt_signature(tx_id: fuel_tx::Bytes32) -> Result { - println!("Transaction id to sign: {tx_id}"); - print!("Please provide the signature:"); - std::io::stdout().flush()?; - let mut buf = String::new(); - std::io::stdin().read_line(&mut buf)?; - Signature::from_str(buf.trim()).map_err(Error::msg) +pub(crate) fn prompt_forc_wallet_password() -> Result { + let password = Password::with_theme(&ColorfulTheme::default()) + .with_prompt("Wallet password") + .allow_empty_password(true) + .interact()?; + + Ok(password) } -fn ask_user_yes_no_question(question: &str) -> Result { - print!("{question}"); - std::io::stdout().flush()?; - let mut ans = String::new(); - std::io::stdin().read_line(&mut ans)?; - // Pop trailing \n as users press enter to submit their answers. - ans.pop(); - // Trim the user input as it might have an additional space. - let ans = ans.trim(); - Ok(ans == "y" || ans == "Y") +pub(crate) fn check_and_create_wallet_at_default_path(wallet_path: &Path) -> Result<()> { + if !wallet_path.exists() { + let question = format!("Could not find a wallet at {wallet_path:?}, would you like to create a new one? [y/N]: "); + let accepted = ask_user_yes_no_question(&question)?; + let new_options = New { + force: false, + cache_accounts: None, + }; + if accepted { + new_wallet_cli(wallet_path, new_options)?; + println!("Wallet created successfully."); + // Derive first account for the fresh wallet we created. + new_at_index_cli(wallet_path, 0)?; + println!("Account derived successfully."); + } else { + anyhow::bail!("Refused to create a new wallet. If you don't want to use forc-wallet, you can sign this transaction manually with --manual-signing flag.") + } + } + Ok(()) } + +pub(crate) fn secret_key_from_forc_wallet( + wallet_path: &Path, + account_index: usize, + password: &str, +) -> Result { + let secret_key = derive_secret_key(wallet_path, account_index, password).map_err(|e| { + if e.to_string().contains("Mac Mismatch") { + anyhow::anyhow!("Failed to access forc-wallet vault. Please check your password") + } else { + e + } + })?; + Ok(secret_key) +} + +pub(crate) fn select_manual_secret_key( + default_signer: bool, + signing_key: Option, +) -> Option { + match (default_signer, signing_key) { + // Note: unwrap is safe here as we already know that 'DEFAULT_PRIVATE_KEY' is a valid private key. + (true, None) => Some(SecretKey::from_str(DEFAULT_PRIVATE_KEY).unwrap()), + (true, Some(signing_key)) => { + println_warning("Signing key is provided while requesting to sign with a default signer. Using signing key"); + Some(signing_key) + } + (false, None) => None, + (false, Some(signing_key)) => Some(signing_key), + } +} + /// Collect and return balances of each account in the accounts map. async fn collect_account_balances( accounts_map: &AccountsMap, @@ -73,7 +128,7 @@ async fn collect_account_balances( ) -> Result { let accounts: Vec<_> = accounts_map .values() - .map(|addr| Wallet::from_address(addr.clone(), Some(provider.clone()))) + .map(|addr| Wallet::from_address((*addr).into(), Some(provider.clone()))) .collect(); futures::future::try_join_all(accounts.iter().map(|acc| acc.get_balances())) @@ -81,262 +136,202 @@ async fn collect_account_balances( .map_err(|e| anyhow::anyhow!("{e}")) } -#[async_trait] -pub trait TransactionBuilderExt { - fn add_contract(&mut self, contract_id: ContractId) -> &mut Self; - fn add_contracts(&mut self, contract_ids: Vec) -> &mut Self; - fn add_inputs(&mut self, inputs: Vec) -> &mut Self; - async fn fund( - &mut self, - address: Address, - provider: Provider, - signature_witness_index: u16, - ) -> Result<&mut Self>; - async fn finalize_signed( - &mut self, - client: Provider, - unsigned: bool, - signing_key: Option, - wallet_mode: WalletSelectionMode, - ) -> Result; +/// Format collected account balances for each asset type, including only the balance of the base asset that can be used to pay gas. +pub fn format_base_asset_account_balances( + accounts_map: &AccountsMap, + account_balances: &AccountBalances, + base_asset_id: &AssetId, +) -> Result> { + accounts_map + .iter() + .zip(account_balances) + .map(|((ix, address), balance)| { + let base_asset_amount = balance + .get(&base_asset_id.to_string()) + .copied() + .unwrap_or(0); + let raw_addr = format!("0x{address}"); + let checksum_addr = checksum_encode(&raw_addr)?; + let eth_amount = base_asset_amount as f64 / 1_000_000_000.0; + Ok(format!("[{ix}] {checksum_addr} - {eth_amount} ETH")) + }) + .collect::>>() } -#[async_trait] -impl TransactionBuilderExt for TransactionBuilder { - fn add_contract(&mut self, contract_id: ContractId) -> &mut Self { - let input_index = self - .inputs() - .len() - .try_into() - .expect("limit of 256 inputs exceeded"); - self.add_input(fuel_tx::Input::contract( - fuel_tx::UtxoId::new(fuel_tx::Bytes32::zeroed(), 0), - fuel_tx::Bytes32::zeroed(), - fuel_tx::Bytes32::zeroed(), - fuel_tx::TxPointer::new(0u32.into(), 0), - contract_id, - )) - .add_output(fuel_tx::Output::Contract( - fuel_tx::output::contract::Contract { - input_index, - balance_root: fuel_tx::Bytes32::zeroed(), - state_root: fuel_tx::Bytes32::zeroed(), - }, - )) - } - fn add_contracts(&mut self, contract_ids: Vec) -> &mut Self { - for contract_id in contract_ids { - self.add_contract(contract_id); - } - self - } - fn add_inputs(&mut self, inputs: Vec) -> &mut Self { - for input in inputs { - self.add_input(input); - } - self - } - async fn fund( - &mut self, - address: Address, - provider: Provider, - signature_witness_index: u16, - ) -> Result<&mut Self> { - let asset_id = *provider.base_asset_id(); - let wallet = Wallet::from_address(Bech32Address::from(address), Some(provider)); - - let amount = 1_000_000; - let inputs: Vec<_> = wallet - .get_spendable_resources(asset_id, amount) - .await? - .into_iter() - .map(|coin_type| match coin_type { - CoinType::Coin(coin) => create_coin_input(coin, signature_witness_index), - CoinType::Message(message) => { - create_coin_message_input(message, signature_witness_index) - } - }) - .collect(); - let output = Output::change(wallet.address().into(), 0, asset_id); +// TODO: Simplify the function signature once https://github.com/FuelLabs/sway/issues/6071 is closed. +pub(crate) async fn select_account( + wallet_mode: &SignerSelectionMode, + default_sign: bool, + signing_key: Option, + provider: &Provider, + tx_count: usize, +) -> Result { + let chain_info = provider.chain_info().await?; + match wallet_mode { + SignerSelectionMode::ForcWallet(password) => { + let wallet_path = default_wallet_path(); + check_and_create_wallet_at_default_path(&wallet_path)?; + // TODO: This is a very simple TUI, we should consider adding a nice TUI + // capabilities for selections and answer collection. + let accounts = collect_user_accounts(&wallet_path, password)?; + let account_balances = collect_account_balances(&accounts, provider).await?; + let base_asset_id = provider.base_asset_id(); - self.add_inputs(inputs).add_output(output); + let total_balance = account_balances + .iter() + .flat_map(|account| account.values()) + .sum::(); + if total_balance == 0 { + let first_account = accounts + .get(&0) + .ok_or_else(|| anyhow::anyhow!("No account derived for this wallet"))?; + let target = Target::from_str(&chain_info.name).unwrap_or_default(); + let message = if let Some(faucet_url) = target.faucet_url() { + format!( + "Your wallet does not have any funds to pay for the transaction.\ + \n\nIf you are interacting with a testnet, consider using the faucet.\ + \n-> {target} network faucet: {}/?address={first_account}\ + \nIf you are interacting with a local node, consider providing a chainConfig which funds your account.", + faucet_url + ) + } else { + "Your wallet does not have any funds to pay for the transaction.".to_string() + }; + anyhow::bail!(message) + } + let selections = + format_base_asset_account_balances(&accounts, &account_balances, base_asset_id)?; - Ok(self) - } - async fn finalize_signed( - &mut self, - provider: Provider, - default_sign: bool, - signing_key: Option, - wallet_mode: WalletSelectionMode, - ) -> Result { - let chain_info = provider.chain_info().await?; - let params = chain_info.consensus_parameters; - let signing_key = match (wallet_mode, signing_key, default_sign) { - (WalletSelectionMode::ForcWallet, None, false) => { - // TODO: This is a very simple TUI, we should consider adding a nice TUI - // capabilities for selections and answer collection. - let wallet_path = default_wallet_path(); - if !wallet_path.exists() { - let question = format!("Could not find a wallet at {wallet_path:?}, would you like to create a new one? [y/N]: "); - let accepted = ask_user_yes_no_question(&question)?; - let new_options = New { - force: false, - cache_accounts: None, - }; - if accepted { - new_wallet_cli(&wallet_path, new_options)?; - println!("Wallet created successfully."); - // Derive first account for the fresh wallet we created. - new_at_index_cli(&wallet_path, 0)?; - println!("Account derived successfully."); - } else { - anyhow::bail!("Refused to create a new wallet. If you don't want to use forc-wallet, you can sign this transaction manually with --manual-signing flag.") - } - } - let prompt = format!( - "\nPlease provide the password of your encrypted wallet vault at {wallet_path:?}: " - ); - let password = rpassword::prompt_password(prompt)?; - let verification = AccountVerification::Yes(password.clone()); - let accounts = collect_accounts_with_verification(&wallet_path, verification) - .map_err(|e| { - if e.to_string().contains("Mac Mismatch") { - anyhow::anyhow!( - "Failed to access forc-wallet vault. Please check your password" - ) - } else { - e - } - })?; - let account_balances = collect_account_balances(&accounts, &provider).await?; - - let total_balance = account_balances - .iter() - .flat_map(|account| account.values()) - .sum::(); - if total_balance == 0 { - let first_account = accounts - .get(&0) - .ok_or_else(|| anyhow::anyhow!("No account derived for this wallet"))?; - let target = Target::from_str(&chain_info.name).unwrap_or(Target::testnet()); - let faucet_link = format!("{}/?address={first_account}", target.faucet_url()); - anyhow::bail!("Your wallet does not have any funds to pay for the transaction.\ - \n\nIf you are interacting with a testnet consider using the faucet.\ - \n-> {target} network faucet: {faucet_link}\ - \nIf you are interacting with a local node, consider providing a chainConfig which funds your account.") - } - print_account_balances(&accounts, &account_balances); - - let mut account_index; - loop { - print!("\nPlease provide the index of account to use for signing: "); - std::io::stdout().flush()?; - let mut input_account_index = String::new(); - std::io::stdin().read_line(&mut input_account_index)?; - account_index = input_account_index.trim().parse::()?; - if accounts.contains_key(&account_index) { - break; - } - let options: Vec = accounts.keys().map(|key| key.to_string()).collect(); - println_warning(&format!( - "\"{}\" is not a valid account.\nPlease choose a valid option from {}", - account_index, - options.join(","), - )); - } + let mut account_index; + loop { + account_index = Select::with_theme(&ColorfulTheme::default()) + .with_prompt("Wallet account") + .max_length(5) + .items(&selections[..]) + .default(0) + .interact()?; - let secret_key = derive_secret_key(&wallet_path, account_index, &password) - .map_err(|e| { - if e.to_string().contains("Mac Mismatch") { - anyhow::anyhow!( - "Failed to access forc-wallet vault. Please check your password" - ) - } else { - e - } - })?; - - // TODO: Do this via forc-wallet once the functionality is exposed. - let public_key = PublicKey::from(&secret_key); - let hashed = public_key.hash(); - let bech32 = Bech32Address::new(FUEL_BECH32_HRP, hashed); - let question = format!( - "Do you agree to sign this transaction with {}? [y/N]: ", - bech32 - ); - let accepted = ask_user_yes_no_question(&question)?; - if !accepted { - anyhow::bail!("User refused to sign"); + if accounts.contains_key(&account_index) { + break; } - - Some(secret_key) - } - (WalletSelectionMode::ForcWallet, Some(key), _) => { - println_warning("Signing key is provided while requesting to sign with forc-wallet or with default signer. Using signing key"); - Some(key) + let options: Vec = accounts + .keys() + .map(|key| { + let raw_addr = format!("0x{key}"); + let checksum_addr = checksum_encode(&raw_addr)?; + Ok(checksum_addr) + }) + .collect::>>()?; + println_warning(&format!( + "\"{}\" is not a valid account.\nPlease choose a valid option from {}", + account_index, + options.join(","), + )); } - (WalletSelectionMode::Manual, None, false) => None, - (WalletSelectionMode::Manual, Some(key), false) => Some(key), - (_, None, true) => { - // Generate a `SecretKey` to sign this transaction from a default private key used - // by fuel-core. - let secret_key = SecretKey::from_str(DEFAULT_PRIVATE_KEY)?; - Some(secret_key) - } - (WalletSelectionMode::Manual, Some(key), true) => { - println_warning("Signing key is provided while requesting to sign with a default signer. Using signing key"); - Some(key) - } - }; - // Get the address - let address = if let Some(key) = signing_key { - Address::from(*key.public_key().hash()) - } else { - Address::from(prompt_address()?) - }; - // Insert dummy witness for signature - let signature_witness_index = self.witnesses().len().try_into()?; - self.add_witness(Witness::default()); - - // Add input coin and output change - self.fund( - address, - provider, - signature_witness_index, - ) - .await.map_err(|e| if e.to_string().contains("not enough coins to fit the target") { - anyhow::anyhow!("Deployment failed due to insufficient funds. Please be sure to have enough coins to pay for deployment transaction.") - } else { - e - })?; - - let mut tx = self.finalize_without_signature_inner(); - - let signature = if let Some(signing_key) = signing_key { - let message = Message::from_bytes(*tx.id(¶ms.chain_id())); - Signature::sign(&signing_key, &message) - } else { - prompt_signature(tx.id(¶ms.chain_id()))? - }; + let secret_key = secret_key_from_forc_wallet(&wallet_path, account_index, password)?; - let witness = Witness::from(signature.as_ref()); - tx.replace_witness(signature_witness_index, witness); - tx.precompute(¶ms.chain_id()) - .map_err(anyhow::Error::msg)?; + // TODO: Do this via forc-wallet once the functionality is exposed. + // TODO: calculate the number of transactions to sign and ask the user to confirm. + let question = format!( + "Do you agree to sign {tx_count} transaction{}?", + if tx_count > 1 { "s" } else { "" } + ); + let accepted = ask_user_yes_no_question(&question)?; + if !accepted { + anyhow::bail!("User refused to sign"); + } - Ok(tx) + let wallet = WalletUnlocked::new_from_private_key(secret_key, Some(provider.clone())); + Ok(ForcClientAccount::Wallet(wallet)) + } + SignerSelectionMode::Manual => { + let secret_key = select_manual_secret_key(default_sign, signing_key) + .ok_or_else(|| anyhow::anyhow!("missing manual secret key"))?; + let wallet = WalletUnlocked::new_from_private_key(secret_key, Some(provider.clone())); + Ok(ForcClientAccount::Wallet(wallet)) + } + SignerSelectionMode::AwsSigner(arn) => { + let aws_config = AwsConfig::from_env().await; + let aws_client = AwsClient::new(aws_config); + let aws_signer = AwsSigner::new(aws_client, arn.clone(), provider.clone()).await?; + + let account = ForcClientAccount::KmsSigner(aws_signer); + Ok(account) + } } } -pub trait TransactionExt { - fn replace_witness(&mut self, witness_index: u16, witness: Witness) -> &mut Self; +pub async fn update_proxy_contract_target( + account: &ForcClientAccount, + proxy_contract_id: ContractId, + new_target: ContractId, +) -> Result> { + abigen!(Contract(name = "ProxyContract", abi = "{\"programType\":\"contract\",\"specVersion\":\"1\",\"encodingVersion\":\"1\",\"concreteTypes\":[{\"type\":\"()\",\"concreteTypeId\":\"2e38e77b22c314a449e91fafed92a43826ac6aa403ae6a8acb6cf58239fbaf5d\"},{\"type\":\"enum standards::src5::AccessError\",\"concreteTypeId\":\"3f702ea3351c9c1ece2b84048006c8034a24cbc2bad2e740d0412b4172951d3d\",\"metadataTypeId\":1},{\"type\":\"enum standards::src5::State\",\"concreteTypeId\":\"192bc7098e2fe60635a9918afb563e4e5419d386da2bdbf0d716b4bc8549802c\",\"metadataTypeId\":2},{\"type\":\"enum std::option::Option\",\"concreteTypeId\":\"0d79387ad3bacdc3b7aad9da3a96f4ce60d9a1b6002df254069ad95a3931d5c8\",\"metadataTypeId\":4,\"typeArguments\":[\"29c10735d33b5159f0c71ee1dbd17b36a3e69e41f00fab0d42e1bd9f428d8a54\"]},{\"type\":\"enum sway_libs::ownership::errors::InitializationError\",\"concreteTypeId\":\"1dfe7feadc1d9667a4351761230f948744068a090fe91b1bc6763a90ed5d3893\",\"metadataTypeId\":5},{\"type\":\"enum sway_libs::upgradability::errors::SetProxyOwnerError\",\"concreteTypeId\":\"3c6e90ae504df6aad8b34a93ba77dc62623e00b777eecacfa034a8ac6e890c74\",\"metadataTypeId\":6},{\"type\":\"str\",\"concreteTypeId\":\"8c25cb3686462e9a86d2883c5688a22fe738b0bbc85f458d2d2b5f3f667c6d5a\"},{\"type\":\"struct std::contract_id::ContractId\",\"concreteTypeId\":\"29c10735d33b5159f0c71ee1dbd17b36a3e69e41f00fab0d42e1bd9f428d8a54\",\"metadataTypeId\":9},{\"type\":\"struct sway_libs::upgradability::events::ProxyOwnerSet\",\"concreteTypeId\":\"96dd838b44f99d8ccae2a7948137ab6256c48ca4abc6168abc880de07fba7247\",\"metadataTypeId\":10},{\"type\":\"struct sway_libs::upgradability::events::ProxyTargetSet\",\"concreteTypeId\":\"1ddc0adda1270a016c08ffd614f29f599b4725407c8954c8b960bdf651a9a6c8\",\"metadataTypeId\":11}],\"metadataTypes\":[{\"type\":\"b256\",\"metadataTypeId\":0},{\"type\":\"enum standards::src5::AccessError\",\"metadataTypeId\":1,\"components\":[{\"name\":\"NotOwner\",\"typeId\":\"2e38e77b22c314a449e91fafed92a43826ac6aa403ae6a8acb6cf58239fbaf5d\"}]},{\"type\":\"enum standards::src5::State\",\"metadataTypeId\":2,\"components\":[{\"name\":\"Uninitialized\",\"typeId\":\"2e38e77b22c314a449e91fafed92a43826ac6aa403ae6a8acb6cf58239fbaf5d\"},{\"name\":\"Initialized\",\"typeId\":3},{\"name\":\"Revoked\",\"typeId\":\"2e38e77b22c314a449e91fafed92a43826ac6aa403ae6a8acb6cf58239fbaf5d\"}]},{\"type\":\"enum std::identity::Identity\",\"metadataTypeId\":3,\"components\":[{\"name\":\"Address\",\"typeId\":8},{\"name\":\"ContractId\",\"typeId\":9}]},{\"type\":\"enum std::option::Option\",\"metadataTypeId\":4,\"components\":[{\"name\":\"None\",\"typeId\":\"2e38e77b22c314a449e91fafed92a43826ac6aa403ae6a8acb6cf58239fbaf5d\"},{\"name\":\"Some\",\"typeId\":7}],\"typeParameters\":[7]},{\"type\":\"enum sway_libs::ownership::errors::InitializationError\",\"metadataTypeId\":5,\"components\":[{\"name\":\"CannotReinitialized\",\"typeId\":\"2e38e77b22c314a449e91fafed92a43826ac6aa403ae6a8acb6cf58239fbaf5d\"}]},{\"type\":\"enum sway_libs::upgradability::errors::SetProxyOwnerError\",\"metadataTypeId\":6,\"components\":[{\"name\":\"CannotUninitialize\",\"typeId\":\"2e38e77b22c314a449e91fafed92a43826ac6aa403ae6a8acb6cf58239fbaf5d\"}]},{\"type\":\"generic T\",\"metadataTypeId\":7},{\"type\":\"struct std::address::Address\",\"metadataTypeId\":8,\"components\":[{\"name\":\"bits\",\"typeId\":0}]},{\"type\":\"struct std::contract_id::ContractId\",\"metadataTypeId\":9,\"components\":[{\"name\":\"bits\",\"typeId\":0}]},{\"type\":\"struct sway_libs::upgradability::events::ProxyOwnerSet\",\"metadataTypeId\":10,\"components\":[{\"name\":\"new_proxy_owner\",\"typeId\":2}]},{\"type\":\"struct sway_libs::upgradability::events::ProxyTargetSet\",\"metadataTypeId\":11,\"components\":[{\"name\":\"new_target\",\"typeId\":9}]}],\"functions\":[{\"inputs\":[],\"name\":\"proxy_target\",\"output\":\"0d79387ad3bacdc3b7aad9da3a96f4ce60d9a1b6002df254069ad95a3931d5c8\",\"attributes\":[{\"name\":\"doc-comment\",\"arguments\":[\" Returns the target contract of the proxy contract.\"]},{\"name\":\"doc-comment\",\"arguments\":[\"\"]},{\"name\":\"doc-comment\",\"arguments\":[\" # Returns\"]},{\"name\":\"doc-comment\",\"arguments\":[\"\"]},{\"name\":\"doc-comment\",\"arguments\":[\" * [Option] - The new proxy contract to which all fallback calls will be passed or `None`.\"]},{\"name\":\"doc-comment\",\"arguments\":[\"\"]},{\"name\":\"doc-comment\",\"arguments\":[\" # Number of Storage Accesses\"]},{\"name\":\"doc-comment\",\"arguments\":[\"\"]},{\"name\":\"doc-comment\",\"arguments\":[\" * Reads: `1`\"]},{\"name\":\"storage\",\"arguments\":[\"read\"]}]},{\"inputs\":[{\"name\":\"new_target\",\"concreteTypeId\":\"29c10735d33b5159f0c71ee1dbd17b36a3e69e41f00fab0d42e1bd9f428d8a54\"}],\"name\":\"set_proxy_target\",\"output\":\"2e38e77b22c314a449e91fafed92a43826ac6aa403ae6a8acb6cf58239fbaf5d\",\"attributes\":[{\"name\":\"doc-comment\",\"arguments\":[\" Change the target contract of the proxy contract.\"]},{\"name\":\"doc-comment\",\"arguments\":[\"\"]},{\"name\":\"doc-comment\",\"arguments\":[\" # Additional Information\"]},{\"name\":\"doc-comment\",\"arguments\":[\"\"]},{\"name\":\"doc-comment\",\"arguments\":[\" This method can only be called by the `proxy_owner`.\"]},{\"name\":\"doc-comment\",\"arguments\":[\"\"]},{\"name\":\"doc-comment\",\"arguments\":[\" # Arguments\"]},{\"name\":\"doc-comment\",\"arguments\":[\"\"]},{\"name\":\"doc-comment\",\"arguments\":[\" * `new_target`: [ContractId] - The new proxy contract to which all fallback calls will be passed.\"]},{\"name\":\"doc-comment\",\"arguments\":[\"\"]},{\"name\":\"doc-comment\",\"arguments\":[\" # Reverts\"]},{\"name\":\"doc-comment\",\"arguments\":[\"\"]},{\"name\":\"doc-comment\",\"arguments\":[\" * When not called by `proxy_owner`.\"]},{\"name\":\"doc-comment\",\"arguments\":[\"\"]},{\"name\":\"doc-comment\",\"arguments\":[\" # Number of Storage Accesses\"]},{\"name\":\"doc-comment\",\"arguments\":[\"\"]},{\"name\":\"doc-comment\",\"arguments\":[\" * Reads: `1`\"]},{\"name\":\"doc-comment\",\"arguments\":[\" * Write: `1`\"]},{\"name\":\"storage\",\"arguments\":[\"read\",\"write\"]}]},{\"inputs\":[],\"name\":\"proxy_owner\",\"output\":\"192bc7098e2fe60635a9918afb563e4e5419d386da2bdbf0d716b4bc8549802c\",\"attributes\":[{\"name\":\"doc-comment\",\"arguments\":[\" Returns the owner of the proxy contract.\"]},{\"name\":\"doc-comment\",\"arguments\":[\"\"]},{\"name\":\"doc-comment\",\"arguments\":[\" # Returns\"]},{\"name\":\"doc-comment\",\"arguments\":[\"\"]},{\"name\":\"doc-comment\",\"arguments\":[\" * [State] - Represents the state of ownership for this contract.\"]},{\"name\":\"doc-comment\",\"arguments\":[\"\"]},{\"name\":\"doc-comment\",\"arguments\":[\" # Number of Storage Accesses\"]},{\"name\":\"doc-comment\",\"arguments\":[\"\"]},{\"name\":\"doc-comment\",\"arguments\":[\" * Reads: `1`\"]},{\"name\":\"storage\",\"arguments\":[\"read\"]}]},{\"inputs\":[],\"name\":\"initialize_proxy\",\"output\":\"2e38e77b22c314a449e91fafed92a43826ac6aa403ae6a8acb6cf58239fbaf5d\",\"attributes\":[{\"name\":\"doc-comment\",\"arguments\":[\" Initializes the proxy contract.\"]},{\"name\":\"doc-comment\",\"arguments\":[\"\"]},{\"name\":\"doc-comment\",\"arguments\":[\" # Additional Information\"]},{\"name\":\"doc-comment\",\"arguments\":[\"\"]},{\"name\":\"doc-comment\",\"arguments\":[\" This method sets the storage values using the values of the configurable constants `INITIAL_TARGET` and `INITIAL_OWNER`.\"]},{\"name\":\"doc-comment\",\"arguments\":[\" This then allows methods that write to storage to be called.\"]},{\"name\":\"doc-comment\",\"arguments\":[\" This method can only be called once.\"]},{\"name\":\"doc-comment\",\"arguments\":[\"\"]},{\"name\":\"doc-comment\",\"arguments\":[\" # Reverts\"]},{\"name\":\"doc-comment\",\"arguments\":[\"\"]},{\"name\":\"doc-comment\",\"arguments\":[\" * When `storage::SRC14.proxy_owner` is not [State::Uninitialized].\"]},{\"name\":\"doc-comment\",\"arguments\":[\"\"]},{\"name\":\"doc-comment\",\"arguments\":[\" # Number of Storage Accesses\"]},{\"name\":\"doc-comment\",\"arguments\":[\"\"]},{\"name\":\"doc-comment\",\"arguments\":[\" * Writes: `2`\"]},{\"name\":\"storage\",\"arguments\":[\"write\"]}]},{\"inputs\":[{\"name\":\"new_proxy_owner\",\"concreteTypeId\":\"192bc7098e2fe60635a9918afb563e4e5419d386da2bdbf0d716b4bc8549802c\"}],\"name\":\"set_proxy_owner\",\"output\":\"2e38e77b22c314a449e91fafed92a43826ac6aa403ae6a8acb6cf58239fbaf5d\",\"attributes\":[{\"name\":\"doc-comment\",\"arguments\":[\" Changes proxy ownership to the passed State.\"]},{\"name\":\"doc-comment\",\"arguments\":[\"\"]},{\"name\":\"doc-comment\",\"arguments\":[\" # Additional Information\"]},{\"name\":\"doc-comment\",\"arguments\":[\"\"]},{\"name\":\"doc-comment\",\"arguments\":[\" This method can be used to transfer ownership between Identities or to revoke ownership.\"]},{\"name\":\"doc-comment\",\"arguments\":[\"\"]},{\"name\":\"doc-comment\",\"arguments\":[\" # Arguments\"]},{\"name\":\"doc-comment\",\"arguments\":[\"\"]},{\"name\":\"doc-comment\",\"arguments\":[\" * `new_proxy_owner`: [State] - The new state of the proxy ownership.\"]},{\"name\":\"doc-comment\",\"arguments\":[\"\"]},{\"name\":\"doc-comment\",\"arguments\":[\" # Reverts\"]},{\"name\":\"doc-comment\",\"arguments\":[\"\"]},{\"name\":\"doc-comment\",\"arguments\":[\" * When the sender is not the current proxy owner.\"]},{\"name\":\"doc-comment\",\"arguments\":[\" * When the new state of the proxy ownership is [State::Uninitialized].\"]},{\"name\":\"doc-comment\",\"arguments\":[\"\"]},{\"name\":\"doc-comment\",\"arguments\":[\" # Number of Storage Accesses\"]},{\"name\":\"doc-comment\",\"arguments\":[\"\"]},{\"name\":\"doc-comment\",\"arguments\":[\" * Reads: `1`\"]},{\"name\":\"doc-comment\",\"arguments\":[\" * Writes: `1`\"]},{\"name\":\"storage\",\"arguments\":[\"write\"]}]}],\"loggedTypes\":[{\"logId\":\"4571204900286667806\",\"concreteTypeId\":\"3f702ea3351c9c1ece2b84048006c8034a24cbc2bad2e740d0412b4172951d3d\"},{\"logId\":\"2151606668983994881\",\"concreteTypeId\":\"1ddc0adda1270a016c08ffd614f29f599b4725407c8954c8b960bdf651a9a6c8\"},{\"logId\":\"2161305517876418151\",\"concreteTypeId\":\"1dfe7feadc1d9667a4351761230f948744068a090fe91b1bc6763a90ed5d3893\"},{\"logId\":\"4354576968059844266\",\"concreteTypeId\":\"3c6e90ae504df6aad8b34a93ba77dc62623e00b777eecacfa034a8ac6e890c74\"},{\"logId\":\"10870989709723147660\",\"concreteTypeId\":\"96dd838b44f99d8ccae2a7948137ab6256c48ca4abc6168abc880de07fba7247\"},{\"logId\":\"10098701174489624218\",\"concreteTypeId\":\"8c25cb3686462e9a86d2883c5688a22fe738b0bbc85f458d2d2b5f3f667c6d5a\"}],\"messagesTypes\":[],\"configurables\":[{\"name\":\"INITIAL_TARGET\",\"concreteTypeId\":\"0d79387ad3bacdc3b7aad9da3a96f4ce60d9a1b6002df254069ad95a3931d5c8\",\"offset\":13368},{\"name\":\"INITIAL_OWNER\",\"concreteTypeId\":\"192bc7098e2fe60635a9918afb563e4e5419d386da2bdbf0d716b4bc8549802c\",\"offset\":13320}]}",)); + + let proxy_contract = ProxyContract::new(proxy_contract_id, account.clone()); + + let result = proxy_contract + .methods() + .set_proxy_target(new_target) + .call() + .await?; + println_action_green( + "Updated", + &format!("proxy contract target to 0x{new_target}"), + ); + Ok(result) } -impl TransactionExt for T { - fn replace_witness(&mut self, index: u16, witness: Witness) -> &mut Self { - self.witnesses_mut()[index as usize] = witness; - self +#[cfg(test)] +mod tests { + use super::*; + use fuels::types::bech32::Bech32Address; + use std::collections::{BTreeMap, HashMap}; + + #[test] + fn test_format_base_asset_account_balances() { + let mut accounts_map: AccountsMap = BTreeMap::new(); + + let address1: fuel_tx::Address = Bech32Address::from_str( + "fuel1dved7k25uxadatl7l5kql309jnw07dcn4t3a6x9hm9nxyjcpqqns50p7n2", + ) + .expect("address1") + .into(); + + let address2: fuel_tx::Address = Bech32Address::from_str( + "fuel1x9f3ysyk7fmey5ac23s2p4rwg4gjye2kke3nu3pvrs5p4qc4m4qqwx56k3", + ) + .expect("address2") + .into(); + + let base_asset_id = AssetId::zeroed(); + + accounts_map.insert(0, address1); + accounts_map.insert(1, address2); + + let mut account_balances: AccountBalances = Vec::new(); + let mut balance1 = HashMap::new(); + balance1.insert(base_asset_id.to_string(), 1_500_000_000); + balance1.insert("other_asset".to_string(), 2_000_000_000); + account_balances.push(balance1); + + let mut balance2 = HashMap::new(); + balance2.insert("other_asset".to_string(), 3_000_000_000); + account_balances.push(balance2); + + let address1_expected = + "0x6B32DF5954e1BaDEAFFEFD2c0fc5E594dcff3713aaE3Dd18B7d966624B010027"; + let address2_expected = + "0x3153124096f2779253B85460a0D46e4551226556b6633E442c1C281a8315dd40"; + let expected = vec![ + format!("[0] {address1_expected} - 1.5 ETH"), + format!("[1] {address2_expected} - 0 ETH"), + ]; + + let result = + format_base_asset_account_balances(&accounts_map, &account_balances, &base_asset_id) + .unwrap(); + assert_eq!(result, expected); } } diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/unit_tests/log_decode/.gitignore b/forc-plugins/forc-client/test/data/big_contract/.gitignore similarity index 100% rename from test/src/e2e_vm_tests/test_programs/should_pass/unit_tests/log_decode/.gitignore rename to forc-plugins/forc-client/test/data/big_contract/.gitignore diff --git a/forc-plugins/forc-client/test/data/big_contract/Forc.toml b/forc-plugins/forc-client/test/data/big_contract/Forc.toml new file mode 100644 index 00000000000..539c466315e --- /dev/null +++ b/forc-plugins/forc-client/test/data/big_contract/Forc.toml @@ -0,0 +1,8 @@ +[project] +authors = ["Fuel Labs "] +entry = "main.sw" +license = "Apache-2.0" +name = "big_contract" + +[dependencies] +std = { path = "../../../../../sway-lib-std/" } diff --git a/forc-plugins/forc-client/test/data/big_contract/big_contract-abi.json b/forc-plugins/forc-client/test/data/big_contract/big_contract-abi.json new file mode 100644 index 00000000000..0fa70821c2c --- /dev/null +++ b/forc-plugins/forc-client/test/data/big_contract/big_contract-abi.json @@ -0,0 +1,502 @@ +{ + "programType": "contract", + "specVersion": "1", + "encodingVersion": "1", + "concreteTypes": [ + { + "type": "()", + "concreteTypeId": "2e38e77b22c314a449e91fafed92a43826ac6aa403ae6a8acb6cf58239fbaf5d" + }, + { + "type": "(bool, u64)", + "concreteTypeId": "c998ca9a5f221fe7b5c66ae70c8a9562b86d964408b00d17f883c906bc1fe4be", + "metadataTypeId": 0 + }, + { + "type": "[bool; 3]", + "concreteTypeId": "4926d35d1a5157936b0a29bc126b8aace6d911209a5c130e9b716b0c73643ea6", + "metadataTypeId": 5 + }, + { + "type": "[enum Location; 2]", + "concreteTypeId": "fb7957f865b6c8ee87b25381a2861c279107dc2fff0e6bd25586198dc65470d0", + "metadataTypeId": 1 + }, + { + "type": "[struct SimpleStruct; 3]", + "concreteTypeId": "96dffad5a46b9db38f00f4431235e7e9bab7a85e8ee9a514aa81063d429ceb7a", + "metadataTypeId": 7 + }, + { + "type": "[u64; 3]", + "concreteTypeId": "776fb5a3824169d6736138565fdc20aad684d9111266a5ff6d5c675280b7e199", + "metadataTypeId": 6 + }, + { + "type": "b256", + "concreteTypeId": "7c5ee1cecf5f8eacd1284feb5f0bf2bdea533a51e2f0c9aabe9236d335989f3b" + }, + { + "type": "bool", + "concreteTypeId": "b760f44fa5965c2474a3b471467a22c43185152129295af588b022ae50b50903" + }, + { + "type": "enum Location", + "concreteTypeId": "6966f221767e2951c5d68ba5e81e897449375a9f51f5e4c9e3b65f1dd7defabb", + "metadataTypeId": 9 + }, + { + "type": "str[4]", + "concreteTypeId": "94f0fa95c830be5e4f711963e83259fe7e8bc723278ab6ec34449e791a99b53a" + }, + { + "type": "struct Person", + "concreteTypeId": "a6b272bcf0f572840e2cc1241bdcf8d42db51eeb1aead750c8e608160f83f926", + "metadataTypeId": 11 + }, + { + "type": "struct SimpleStruct", + "concreteTypeId": "75f7f7a06026cab5d7a70984d1fde56001e83505e3a091ff9722b92d7f56d8be", + "metadataTypeId": 12 + }, + { + "type": "u16", + "concreteTypeId": "29881aad8730c5ab11d275376323d8e4ff4179aae8ccb6c13fe4902137e162ef" + }, + { + "type": "u256", + "concreteTypeId": "1b5759d94094368cfd443019e7ca5ec4074300e544e5ea993a979f5da627261e" + }, + { + "type": "u32", + "concreteTypeId": "d7649d428b9ff33d188ecbf38a7e4d8fd167fa01b2e10fe9a8f9308e52f1d7cc" + }, + { + "type": "u64", + "concreteTypeId": "1506e6f44c1d6291cdf46395a8e573276a4fa79e8ace3fc891e092ef32d1b0a0" + }, + { + "type": "u8", + "concreteTypeId": "c89951a24c6ca28c13fd1cfdc646b2b656d69e61a92b91023be7eb58eb914b6b" + } + ], + "metadataTypes": [ + { + "type": "(_, _)", + "metadataTypeId": 0, + "components": [ + { + "name": "__tuple_element", + "typeId": "b760f44fa5965c2474a3b471467a22c43185152129295af588b022ae50b50903" + }, + { + "name": "__tuple_element", + "typeId": "1506e6f44c1d6291cdf46395a8e573276a4fa79e8ace3fc891e092ef32d1b0a0" + } + ] + }, + { + "type": "[_; 2]", + "metadataTypeId": 1, + "components": [ + { + "name": "__array_element", + "typeId": 9 + } + ] + }, + { + "type": "[_; 2]", + "metadataTypeId": 2, + "components": [ + { + "name": "__array_element", + "typeId": 8 + } + ] + }, + { + "type": "[_; 2]", + "metadataTypeId": 3, + "components": [ + { + "name": "__array_element", + "typeId": 12 + } + ] + }, + { + "type": "[_; 2]", + "metadataTypeId": 4, + "components": [ + { + "name": "__array_element", + "typeId": "1506e6f44c1d6291cdf46395a8e573276a4fa79e8ace3fc891e092ef32d1b0a0" + } + ] + }, + { + "type": "[_; 3]", + "metadataTypeId": 5, + "components": [ + { + "name": "__array_element", + "typeId": "b760f44fa5965c2474a3b471467a22c43185152129295af588b022ae50b50903" + } + ] + }, + { + "type": "[_; 3]", + "metadataTypeId": 6, + "components": [ + { + "name": "__array_element", + "typeId": "1506e6f44c1d6291cdf46395a8e573276a4fa79e8ace3fc891e092ef32d1b0a0" + } + ] + }, + { + "type": "[_; 3]", + "metadataTypeId": 7, + "components": [ + { + "name": "__array_element", + "typeId": 12 + } + ] + }, + { + "type": "enum Color", + "metadataTypeId": 8, + "components": [ + { + "name": "Red", + "typeId": "2e38e77b22c314a449e91fafed92a43826ac6aa403ae6a8acb6cf58239fbaf5d" + }, + { + "name": "Blue", + "typeId": "1506e6f44c1d6291cdf46395a8e573276a4fa79e8ace3fc891e092ef32d1b0a0" + } + ] + }, + { + "type": "enum Location", + "metadataTypeId": 9, + "components": [ + { + "name": "Earth", + "typeId": "1506e6f44c1d6291cdf46395a8e573276a4fa79e8ace3fc891e092ef32d1b0a0" + }, + { + "name": "Mars", + "typeId": "2e38e77b22c314a449e91fafed92a43826ac6aa403ae6a8acb6cf58239fbaf5d" + }, + { + "name": "SimpleJupiter", + "typeId": 8 + }, + { + "name": "Jupiter", + "typeId": 2 + }, + { + "name": "SimplePluto", + "typeId": 12 + }, + { + "name": "Pluto", + "typeId": 3 + } + ] + }, + { + "type": "str", + "metadataTypeId": 10 + }, + { + "type": "struct Person", + "metadataTypeId": 11, + "components": [ + { + "name": "name", + "typeId": 10 + }, + { + "name": "age", + "typeId": "1506e6f44c1d6291cdf46395a8e573276a4fa79e8ace3fc891e092ef32d1b0a0" + }, + { + "name": "alive", + "typeId": "b760f44fa5965c2474a3b471467a22c43185152129295af588b022ae50b50903" + }, + { + "name": "location", + "typeId": 9 + }, + { + "name": "some_tuple", + "typeId": 0 + }, + { + "name": "some_array", + "typeId": 4 + }, + { + "name": "some_b256", + "typeId": "7c5ee1cecf5f8eacd1284feb5f0bf2bdea533a51e2f0c9aabe9236d335989f3b" + } + ] + }, + { + "type": "struct SimpleStruct", + "metadataTypeId": 12, + "components": [ + { + "name": "a", + "typeId": "b760f44fa5965c2474a3b471467a22c43185152129295af588b022ae50b50903" + }, + { + "name": "b", + "typeId": "1506e6f44c1d6291cdf46395a8e573276a4fa79e8ace3fc891e092ef32d1b0a0" + } + ] + } + ], + "functions": [ + { + "inputs": [ + { + "name": "aoe", + "concreteTypeId": "fb7957f865b6c8ee87b25381a2861c279107dc2fff0e6bd25586198dc65470d0" + } + ], + "name": "array_of_enum_input_output", + "output": "fb7957f865b6c8ee87b25381a2861c279107dc2fff0e6bd25586198dc65470d0", + "attributes": null + }, + { + "inputs": [], + "name": "assert_configurables", + "output": "b760f44fa5965c2474a3b471467a22c43185152129295af588b022ae50b50903", + "attributes": null + }, + { + "inputs": [ + { + "name": "loc", + "concreteTypeId": "6966f221767e2951c5d68ba5e81e897449375a9f51f5e4c9e3b65f1dd7defabb" + } + ], + "name": "enum_input_output", + "output": "6966f221767e2951c5d68ba5e81e897449375a9f51f5e4c9e3b65f1dd7defabb", + "attributes": null + }, + { + "inputs": [ + { + "name": "index", + "concreteTypeId": "1506e6f44c1d6291cdf46395a8e573276a4fa79e8ace3fc891e092ef32d1b0a0" + } + ], + "name": "get_storage_location", + "output": "6966f221767e2951c5d68ba5e81e897449375a9f51f5e4c9e3b65f1dd7defabb", + "attributes": [ + { + "name": "storage", + "arguments": [ + "read" + ] + } + ] + }, + { + "inputs": [ + { + "name": "index", + "concreteTypeId": "1506e6f44c1d6291cdf46395a8e573276a4fa79e8ace3fc891e092ef32d1b0a0" + } + ], + "name": "get_storage_simple", + "output": "75f7f7a06026cab5d7a70984d1fde56001e83505e3a091ff9722b92d7f56d8be", + "attributes": [ + { + "name": "storage", + "arguments": [ + "read" + ] + } + ] + }, + { + "inputs": [ + { + "name": "index", + "concreteTypeId": "1506e6f44c1d6291cdf46395a8e573276a4fa79e8ace3fc891e092ef32d1b0a0" + } + ], + "name": "get_storage_u16", + "output": "29881aad8730c5ab11d275376323d8e4ff4179aae8ccb6c13fe4902137e162ef", + "attributes": [ + { + "name": "storage", + "arguments": [ + "read" + ] + } + ] + }, + { + "inputs": [], + "name": "large_blob", + "output": "b760f44fa5965c2474a3b471467a22c43185152129295af588b022ae50b50903", + "attributes": null + }, + { + "inputs": [ + { + "name": "value", + "concreteTypeId": "6966f221767e2951c5d68ba5e81e897449375a9f51f5e4c9e3b65f1dd7defabb" + } + ], + "name": "push_storage_location", + "output": "2e38e77b22c314a449e91fafed92a43826ac6aa403ae6a8acb6cf58239fbaf5d", + "attributes": [ + { + "name": "storage", + "arguments": [ + "read", + "write" + ] + } + ] + }, + { + "inputs": [ + { + "name": "value", + "concreteTypeId": "75f7f7a06026cab5d7a70984d1fde56001e83505e3a091ff9722b92d7f56d8be" + } + ], + "name": "push_storage_simple", + "output": "2e38e77b22c314a449e91fafed92a43826ac6aa403ae6a8acb6cf58239fbaf5d", + "attributes": [ + { + "name": "storage", + "arguments": [ + "read", + "write" + ] + } + ] + }, + { + "inputs": [ + { + "name": "value", + "concreteTypeId": "29881aad8730c5ab11d275376323d8e4ff4179aae8ccb6c13fe4902137e162ef" + } + ], + "name": "push_storage_u16", + "output": "2e38e77b22c314a449e91fafed92a43826ac6aa403ae6a8acb6cf58239fbaf5d", + "attributes": [ + { + "name": "storage", + "arguments": [ + "read", + "write" + ] + } + ] + }, + { + "inputs": [ + { + "name": "person", + "concreteTypeId": "a6b272bcf0f572840e2cc1241bdcf8d42db51eeb1aead750c8e608160f83f926" + } + ], + "name": "struct_input_output", + "output": "a6b272bcf0f572840e2cc1241bdcf8d42db51eeb1aead750c8e608160f83f926", + "attributes": null + } + ], + "loggedTypes": [], + "messagesTypes": [], + "configurables": [ + { + "name": "BOOL", + "concreteTypeId": "b760f44fa5965c2474a3b471467a22c43185152129295af588b022ae50b50903", + "offset": 392688 + }, + { + "name": "U8", + "concreteTypeId": "c89951a24c6ca28c13fd1cfdc646b2b656d69e61a92b91023be7eb58eb914b6b", + "offset": 392832 + }, + { + "name": "U16", + "concreteTypeId": "29881aad8730c5ab11d275376323d8e4ff4179aae8ccb6c13fe4902137e162ef", + "offset": 392776 + }, + { + "name": "U32", + "concreteTypeId": "d7649d428b9ff33d188ecbf38a7e4d8fd167fa01b2e10fe9a8f9308e52f1d7cc", + "offset": 392816 + }, + { + "name": "U64", + "concreteTypeId": "d7649d428b9ff33d188ecbf38a7e4d8fd167fa01b2e10fe9a8f9308e52f1d7cc", + "offset": 392824 + }, + { + "name": "U256", + "concreteTypeId": "1b5759d94094368cfd443019e7ca5ec4074300e544e5ea993a979f5da627261e", + "offset": 392784 + }, + { + "name": "B256", + "concreteTypeId": "7c5ee1cecf5f8eacd1284feb5f0bf2bdea533a51e2f0c9aabe9236d335989f3b", + "offset": 392656 + }, + { + "name": "CONFIGURABLE_STRUCT", + "concreteTypeId": "75f7f7a06026cab5d7a70984d1fde56001e83505e3a091ff9722b92d7f56d8be", + "offset": 392736 + }, + { + "name": "CONFIGURABLE_ENUM", + "concreteTypeId": "6966f221767e2951c5d68ba5e81e897449375a9f51f5e4c9e3b65f1dd7defabb", + "offset": 392696 + }, + { + "name": "ARRAY_BOOL", + "concreteTypeId": "4926d35d1a5157936b0a29bc126b8aace6d911209a5c130e9b716b0c73643ea6", + "offset": 392512 + }, + { + "name": "ARRAY_U64", + "concreteTypeId": "776fb5a3824169d6736138565fdc20aad684d9111266a5ff6d5c675280b7e199", + "offset": 392632 + }, + { + "name": "ARRAY_LOCATION", + "concreteTypeId": "fb7957f865b6c8ee87b25381a2861c279107dc2fff0e6bd25586198dc65470d0", + "offset": 392520 + }, + { + "name": "ARRAY_SIMPLE_STRUCT", + "concreteTypeId": "96dffad5a46b9db38f00f4431235e7e9bab7a85e8ee9a514aa81063d429ceb7a", + "offset": 392600 + }, + { + "name": "TUPLE_BOOL_U64", + "concreteTypeId": "c998ca9a5f221fe7b5c66ae70c8a9562b86d964408b00d17f883c906bc1fe4be", + "offset": 392760 + }, + { + "name": "STR_4", + "concreteTypeId": "94f0fa95c830be5e4f711963e83259fe7e8bc723278ab6ec34449e791a99b53a", + "offset": 392752 + } + ] +} \ No newline at end of file diff --git a/forc-plugins/forc-client/test/data/big_contract/src/main.sw b/forc-plugins/forc-client/test/data/big_contract/src/main.sw new file mode 100644 index 00000000000..83eb21e2d1f --- /dev/null +++ b/forc-plugins/forc-client/test/data/big_contract/src/main.sw @@ -0,0 +1,210 @@ +contract; + +use std::storage::storage_vec::*; +use std::hash::*; + +abi MyContract { + fn large_blob() -> bool; + + fn enum_input_output(loc: Location) -> Location; + + fn struct_input_output(person: Person) -> Person; + + fn array_of_enum_input_output(aoe: [Location; 2]) -> [Location; 2]; + + #[storage(read, write)] + fn push_storage_u16(value: u16); + + #[storage(read)] + fn get_storage_u16(index: u64) -> u16; + + #[storage(read, write)] + fn push_storage_simple(value: SimpleStruct); + + #[storage(read)] + fn get_storage_simple(index: u64) -> SimpleStruct; + + #[storage(read, write)] + fn push_storage_location(value: Location); + + #[storage(read)] + fn get_storage_location(index: u64) -> Location; + + fn assert_configurables() -> bool; +} + +enum Location { + Earth: u64, + Mars: (), + SimpleJupiter: Color, + Jupiter: [Color; 2], + SimplePluto: SimpleStruct, + Pluto: [SimpleStruct; 2], +} + +enum Color { + Red: (), + Blue: u64, +} + +struct Person { + name: str, + age: u64, + alive: bool, + location: Location, + some_tuple: (bool, u64), + some_array: [u64; 2], + some_b256: b256, +} + +struct SimpleStruct { + a: bool, + b: u64, +} + +storage { + my_vec: StorageVec = StorageVec {}, + my_simple_vec: StorageVec = StorageVec {}, + my_location_vec: StorageVec = StorageVec {}, +} + +configurable { + BOOL: bool = true, + U8: u8 = 1, + U16: u16 = 2, + U32: u32 = 3, + U64: u32 = 4, + U256: u256 = 0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAu256, + B256: b256 = 0xBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB, + CONFIGURABLE_STRUCT: SimpleStruct = SimpleStruct { a: true, b: 5 }, + CONFIGURABLE_ENUM: Location = Location::Earth(1), + ARRAY_BOOL: [bool; 3] = [true, false, true], + ARRAY_U64: [u64; 3] = [9, 8, 7], + ARRAY_LOCATION: [Location; 2] = [Location::Earth(10), Location::Mars], + ARRAY_SIMPLE_STRUCT: [SimpleStruct; 3] = [ SimpleStruct { a: true, b: 5}, SimpleStruct { a: false, b: 0 }, SimpleStruct { a: true, b: u64::max() }], + TUPLE_BOOL_U64: (bool, u64) = (true, 11), + STR_4: str[4] = __to_str_array("abcd"), +} + +impl core::ops::Eq for Color { + fn eq(self, other: Color) -> bool { + match (self, other) { + (Color::Red, Color::Red) => true, + (Color::Blue(inner1), Color::Blue(inner2)) => inner1 == inner2, + _ => false, + } + } +} + +impl core::ops::Eq for SimpleStruct { + fn eq(self, other: SimpleStruct) -> bool { + self.a == other.a && self.b == other.b + } +} + +impl core::ops::Eq for Location { + fn eq(self, other: Location) -> bool { + match (self, other) { + (Location::Earth(inner1), Location::Earth(inner2)) => inner1 == inner2, + (Location::Mars, Location::Mars) => true, + (Location::SimpleJupiter(inner1), Location::SimpleJupiter(inner2)) => inner1 == inner2, + (Location::Jupiter(inner1), Location::Jupiter(inner2)) => (inner1[0] == inner2[0] && inner1[1] == inner2[1]), + (Location::SimplePluto(inner1), Location::SimplePluto(inner2)) => inner1 == inner2, + (Location::Pluto(inner1), Location::Pluto(inner2)) => (inner1[0] == inner2[0] && inner1[1] == inner2[1]), + _ => false, + } + } +} + +impl MyContract for Contract { + fn large_blob() -> bool { + asm() { + blob i91000; + } + true + } + + fn enum_input_output(loc: Location) -> Location { + loc + } + + fn struct_input_output(person: Person) -> Person { + person + } + + fn array_of_enum_input_output(aoe: [Location; 2]) -> [Location; 2] { + aoe + } + + #[storage(read, write)] + fn push_storage_u16(value: u16) { + storage.my_vec.push(value); + } + + #[storage(read)] + fn get_storage_u16(index: u64) -> u16 { + storage.my_vec.get(index).unwrap().read() + } + + #[storage(read, write)] + fn push_storage_simple(value: SimpleStruct) { + storage.my_simple_vec.push(value); + } + + #[storage(read)] + fn get_storage_simple(index: u64) -> SimpleStruct { + storage.my_simple_vec.get(index).unwrap().read() + } + + #[storage(read, write)] + fn push_storage_location(value: Location) { + storage.my_location_vec.push(value); + } + + #[storage(read)] + fn get_storage_location(index: u64) -> Location { + storage.my_location_vec.get(index).unwrap().read() + } + + fn assert_configurables() -> bool { + assert(BOOL == true); + assert(U8 == 1); + assert(U16 == 2); + assert(U32 == 3); + assert(U64 == 4); + assert(U256 == 0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAu256); + assert(B256 == 0xBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB); + assert(CONFIGURABLE_STRUCT.a == true); + assert(CONFIGURABLE_STRUCT.b == 5); + assert(CONFIGURABLE_ENUM == Location::Earth(1)); + assert(ARRAY_BOOL[0] == true); + assert(ARRAY_BOOL[1] == false); + assert(ARRAY_BOOL[2] == true); + assert(ARRAY_U64[0] == 9); + assert(ARRAY_U64[1] == 8); + assert(ARRAY_U64[2] == 7); + assert(ARRAY_LOCATION[0] == Location::Earth(10)); + assert(ARRAY_LOCATION[1] == Location::Mars); + assert(ARRAY_SIMPLE_STRUCT[0].a == true); + assert(ARRAY_SIMPLE_STRUCT[0].b == 5); + assert(ARRAY_SIMPLE_STRUCT[1].a == false); + assert(ARRAY_SIMPLE_STRUCT[1].b == 0); + assert(ARRAY_SIMPLE_STRUCT[2].a == true); + assert(ARRAY_SIMPLE_STRUCT[2].b == u64::max()); + assert(ARRAY_LOCATION[1] == Location::Mars); + assert(ARRAY_LOCATION[1] == Location::Mars); + assert(TUPLE_BOOL_U64.0 == true); + assert(TUPLE_BOOL_U64.1 == 11); + assert(sha256_str_array(STR_4) == sha256("abcd")); + + // Assert address do not change + let addr_1 = asm(addr: __addr_of(&BOOL)) { + addr: u64 + }; + let addr_2 = asm(addr: __addr_of(&BOOL)) { + addr: u64 + }; + assert(addr_1 == addr_2); + true + } +} diff --git a/forc-plugins/forc-client/test/data/contract_with_dep/Forc.toml b/forc-plugins/forc-client/test/data/contract_with_dep/Forc.toml index 45be87cb3b6..4d1d6e8308b 100644 --- a/forc-plugins/forc-client/test/data/contract_with_dep/Forc.toml +++ b/forc-plugins/forc-client/test/data/contract_with_dep/Forc.toml @@ -6,7 +6,7 @@ license = "Apache-2.0" name = "contract_with_dep" [dependencies] -std = { path = "../../../../../../../../sway-lib-std/" } +std = { path = "../../../../../sway-lib-std/" } [contract-dependencies] standalone_contract = { path = "../standalone_contract", salt = "0x0000000000000000000000000000000000000000000000000000000000000001" } diff --git a/forc-plugins/forc-client/test/data/contract_with_dep_with_salt_conflict/Forc.toml b/forc-plugins/forc-client/test/data/contract_with_dep_with_salt_conflict/Forc.toml index 4123009928a..fe10c17663d 100644 --- a/forc-plugins/forc-client/test/data/contract_with_dep_with_salt_conflict/Forc.toml +++ b/forc-plugins/forc-client/test/data/contract_with_dep_with_salt_conflict/Forc.toml @@ -6,7 +6,7 @@ license = "Apache-2.0" name = "contract_with_dep_with_salt_conflict" [dependencies] -std = { path = "../../../../../../../../sway-lib-std/" } +std = { path = "../../../../../sway-lib-std/" } [contract-dependencies] contract_with_dep = { path = "../contract_with_dep" } diff --git a/forc-plugins/forc-client/test/data/deployed_predicate/.gitignore b/forc-plugins/forc-client/test/data/deployed_predicate/.gitignore new file mode 100644 index 00000000000..77d3844f58c --- /dev/null +++ b/forc-plugins/forc-client/test/data/deployed_predicate/.gitignore @@ -0,0 +1,2 @@ +out +target diff --git a/forc-plugins/forc-client/test/data/deployed_predicate/Forc.lock b/forc-plugins/forc-client/test/data/deployed_predicate/Forc.lock new file mode 100644 index 00000000000..2be3d70a3ca --- /dev/null +++ b/forc-plugins/forc-client/test/data/deployed_predicate/Forc.lock @@ -0,0 +1,13 @@ +[[package]] +name = "core" +source = "path+from-root-661979F06117CBCE" + +[[package]] +name = "deployed_predicate" +source = "member" +dependencies = ["std"] + +[[package]] +name = "std" +source = "path+from-root-661979F06117CBCE" +dependencies = ["core"] diff --git a/forc-plugins/forc-client/test/data/deployed_predicate/Forc.toml b/forc-plugins/forc-client/test/data/deployed_predicate/Forc.toml new file mode 100644 index 00000000000..68b7cb9dff1 --- /dev/null +++ b/forc-plugins/forc-client/test/data/deployed_predicate/Forc.toml @@ -0,0 +1,8 @@ +[project] +authors = ["Fuel Labs "] +entry = "main.sw" +license = "Apache-2.0" +name = "deployed_predicate" + +[dependencies] +std = { path = "../../../../../sway-lib-std/" } diff --git a/forc-plugins/forc-client/test/data/deployed_predicate/deployed_predicate-abi.json b/forc-plugins/forc-client/test/data/deployed_predicate/deployed_predicate-abi.json new file mode 100644 index 00000000000..f38d1dbedd6 --- /dev/null +++ b/forc-plugins/forc-client/test/data/deployed_predicate/deployed_predicate-abi.json @@ -0,0 +1,128 @@ +{ + "programType": "predicate", + "specVersion": "1", + "encodingVersion": "1", + "concreteTypes": [ + { + "type": "bool", + "concreteTypeId": "b760f44fa5965c2474a3b471467a22c43185152129295af588b022ae50b50903" + }, + { + "type": "enum EnumWithGeneric", + "concreteTypeId": "37cd1cba311039a851ac8bfa614cc41359b4ad95c8656fcef2e8f504fe7a1272", + "metadataTypeId": 1, + "typeArguments": [ + "b760f44fa5965c2474a3b471467a22c43185152129295af588b022ae50b50903" + ] + }, + { + "type": "struct StructWithGeneric", + "concreteTypeId": "563310524b4f4447a10d0e50556310253dfb3b5eb4b29c3773222b737c8b7075", + "metadataTypeId": 3, + "typeArguments": [ + "c89951a24c6ca28c13fd1cfdc646b2b656d69e61a92b91023be7eb58eb914b6b" + ] + }, + { + "type": "u8", + "concreteTypeId": "c89951a24c6ca28c13fd1cfdc646b2b656d69e61a92b91023be7eb58eb914b6b" + } + ], + "metadataTypes": [ + { + "type": "()", + "metadataTypeId": 0 + }, + { + "type": "enum EnumWithGeneric", + "metadataTypeId": 1, + "components": [ + { + "name": "VariantOne", + "typeId": 2 + }, + { + "name": "VariantTwo", + "typeId": 0 + } + ], + "typeParameters": [ + 2 + ] + }, + { + "type": "generic D", + "metadataTypeId": 2 + }, + { + "type": "struct StructWithGeneric", + "metadataTypeId": 3, + "components": [ + { + "name": "field_1", + "typeId": 2 + }, + { + "name": "field_2", + "typeId": 4 + } + ], + "typeParameters": [ + 2 + ] + }, + { + "type": "u64", + "metadataTypeId": 4 + } + ], + "functions": [ + { + "inputs": [ + { + "name": "switch", + "concreteTypeId": "b760f44fa5965c2474a3b471467a22c43185152129295af588b022ae50b50903" + }, + { + "name": "u_8", + "concreteTypeId": "c89951a24c6ca28c13fd1cfdc646b2b656d69e61a92b91023be7eb58eb914b6b" + }, + { + "name": "some_struct", + "concreteTypeId": "563310524b4f4447a10d0e50556310253dfb3b5eb4b29c3773222b737c8b7075" + }, + { + "name": "some_enum", + "concreteTypeId": "37cd1cba311039a851ac8bfa614cc41359b4ad95c8656fcef2e8f504fe7a1272" + } + ], + "name": "main", + "output": "b760f44fa5965c2474a3b471467a22c43185152129295af588b022ae50b50903", + "attributes": null + } + ], + "loggedTypes": [], + "messagesTypes": [], + "configurables": [ + { + "name": "BOOL", + "concreteTypeId": "b760f44fa5965c2474a3b471467a22c43185152129295af588b022ae50b50903", + "offset": 1896 + }, + { + "name": "U8", + "concreteTypeId": "c89951a24c6ca28c13fd1cfdc646b2b656d69e61a92b91023be7eb58eb914b6b", + "offset": 1936 + }, + { + "name": "STRUCT", + "concreteTypeId": "563310524b4f4447a10d0e50556310253dfb3b5eb4b29c3773222b737c8b7075", + "offset": 1920 + }, + { + "name": "ENUM", + "concreteTypeId": "37cd1cba311039a851ac8bfa614cc41359b4ad95c8656fcef2e8f504fe7a1272", + "offset": 1904 + } + ] +} \ No newline at end of file diff --git a/forc-plugins/forc-client/test/data/deployed_predicate/src/main.sw b/forc-plugins/forc-client/test/data/deployed_predicate/src/main.sw new file mode 100644 index 00000000000..f33b61faf40 --- /dev/null +++ b/forc-plugins/forc-client/test/data/deployed_predicate/src/main.sw @@ -0,0 +1,53 @@ +predicate; + +#[allow(dead_code)] +enum EnumWithGeneric { + VariantOne: D, + VariantTwo: (), +} + +struct StructWithGeneric { + field_1: D, + field_2: u64, +} + +impl Eq for EnumWithGeneric +where + D: Eq, +{ + fn eq(self, other: Self) -> bool { + match (self, other) { + (EnumWithGeneric::VariantOne(d1), EnumWithGeneric::VariantOne(d2)) => d1 == d2, + (EnumWithGeneric::VariantTwo, EnumWithGeneric::VariantTwo) => true, + _ => false, + } + } +} + +impl Eq for StructWithGeneric +where + D: Eq, +{ + fn eq(self, other: Self) -> bool { + self.field_1 == other.field_1 && self.field_2 == other.field_2 + } +} + +configurable { + BOOL: bool = true, + U8: u8 = 8, + STRUCT: StructWithGeneric = StructWithGeneric { + field_1: 8, + field_2: 16, + }, + ENUM: EnumWithGeneric = EnumWithGeneric::VariantOne(true), +} + +fn main( + switch: bool, + u_8: u8, + some_struct: StructWithGeneric, + some_enum: EnumWithGeneric, +) -> bool { + switch == BOOL && u_8 == U8 && some_struct == STRUCT && some_enum == ENUM +} diff --git a/forc-plugins/forc-client/test/data/deployed_script/.gitignore b/forc-plugins/forc-client/test/data/deployed_script/.gitignore new file mode 100644 index 00000000000..77d3844f58c --- /dev/null +++ b/forc-plugins/forc-client/test/data/deployed_script/.gitignore @@ -0,0 +1,2 @@ +out +target diff --git a/forc-plugins/forc-client/test/data/deployed_script/Forc.toml b/forc-plugins/forc-client/test/data/deployed_script/Forc.toml new file mode 100644 index 00000000000..3eb3cdf653b --- /dev/null +++ b/forc-plugins/forc-client/test/data/deployed_script/Forc.toml @@ -0,0 +1,8 @@ +[project] +authors = ["Fuel Labs "] +entry = "main.sw" +license = "Apache-2.0" +name = "deployed_script" + +[dependencies] +std = { path = "../../../../../sway-lib-std/" } diff --git a/forc-plugins/forc-client/test/data/deployed_script/deployed_script-abi.json b/forc-plugins/forc-client/test/data/deployed_script/deployed_script-abi.json new file mode 100644 index 00000000000..7689a658d2a --- /dev/null +++ b/forc-plugins/forc-client/test/data/deployed_script/deployed_script-abi.json @@ -0,0 +1,312 @@ +{ + "programType": "script", + "specVersion": "1", + "encodingVersion": "1", + "concreteTypes": [ + { + "type": "((bool, u8, u16, u32, u64, u256, b256, str[4], (u8, bool), [u32; 3], struct StructWithGeneric, enum EnumWithGeneric), bool, u64, u8)", + "concreteTypeId": "25fbba860b8a1983ebcfa3f135136266a7edb7ca3a7e1f8ec988135c12a9f873", + "metadataTypeId": 2 + }, + { + "type": "(u8, bool)", + "concreteTypeId": "e0128f7be9902d1fe16326cafe703b52038064a7997b03ebfc1c9dd607e1536c", + "metadataTypeId": 1 + }, + { + "type": "[u32; 3]", + "concreteTypeId": "d9fac01ab38fe10950758ae9604da330d6406a71fda3ef1ea818121261132d56", + "metadataTypeId": 4 + }, + { + "type": "b256", + "concreteTypeId": "7c5ee1cecf5f8eacd1284feb5f0bf2bdea533a51e2f0c9aabe9236d335989f3b" + }, + { + "type": "bool", + "concreteTypeId": "b760f44fa5965c2474a3b471467a22c43185152129295af588b022ae50b50903" + }, + { + "type": "enum EnumWithGeneric", + "concreteTypeId": "37cd1cba311039a851ac8bfa614cc41359b4ad95c8656fcef2e8f504fe7a1272", + "metadataTypeId": 5, + "typeArguments": [ + "b760f44fa5965c2474a3b471467a22c43185152129295af588b022ae50b50903" + ] + }, + { + "type": "str[4]", + "concreteTypeId": "94f0fa95c830be5e4f711963e83259fe7e8bc723278ab6ec34449e791a99b53a" + }, + { + "type": "struct StructWithGeneric", + "concreteTypeId": "563310524b4f4447a10d0e50556310253dfb3b5eb4b29c3773222b737c8b7075", + "metadataTypeId": 7, + "typeArguments": [ + "c89951a24c6ca28c13fd1cfdc646b2b656d69e61a92b91023be7eb58eb914b6b" + ] + }, + { + "type": "u16", + "concreteTypeId": "29881aad8730c5ab11d275376323d8e4ff4179aae8ccb6c13fe4902137e162ef" + }, + { + "type": "u256", + "concreteTypeId": "1b5759d94094368cfd443019e7ca5ec4074300e544e5ea993a979f5da627261e" + }, + { + "type": "u32", + "concreteTypeId": "d7649d428b9ff33d188ecbf38a7e4d8fd167fa01b2e10fe9a8f9308e52f1d7cc" + }, + { + "type": "u64", + "concreteTypeId": "1506e6f44c1d6291cdf46395a8e573276a4fa79e8ace3fc891e092ef32d1b0a0" + }, + { + "type": "u8", + "concreteTypeId": "c89951a24c6ca28c13fd1cfdc646b2b656d69e61a92b91023be7eb58eb914b6b" + } + ], + "metadataTypes": [ + { + "type": "()", + "metadataTypeId": 0 + }, + { + "type": "(_, _)", + "metadataTypeId": 1, + "components": [ + { + "name": "__tuple_element", + "typeId": "c89951a24c6ca28c13fd1cfdc646b2b656d69e61a92b91023be7eb58eb914b6b" + }, + { + "name": "__tuple_element", + "typeId": "b760f44fa5965c2474a3b471467a22c43185152129295af588b022ae50b50903" + } + ] + }, + { + "type": "(_, _, _, _)", + "metadataTypeId": 2, + "components": [ + { + "name": "__tuple_element", + "typeId": 3 + }, + { + "name": "__tuple_element", + "typeId": "b760f44fa5965c2474a3b471467a22c43185152129295af588b022ae50b50903" + }, + { + "name": "__tuple_element", + "typeId": "1506e6f44c1d6291cdf46395a8e573276a4fa79e8ace3fc891e092ef32d1b0a0" + }, + { + "name": "__tuple_element", + "typeId": "c89951a24c6ca28c13fd1cfdc646b2b656d69e61a92b91023be7eb58eb914b6b" + } + ] + }, + { + "type": "(_, _, _, _, _, _, _, _, _, _, _, _)", + "metadataTypeId": 3, + "components": [ + { + "name": "__tuple_element", + "typeId": "b760f44fa5965c2474a3b471467a22c43185152129295af588b022ae50b50903" + }, + { + "name": "__tuple_element", + "typeId": "c89951a24c6ca28c13fd1cfdc646b2b656d69e61a92b91023be7eb58eb914b6b" + }, + { + "name": "__tuple_element", + "typeId": "29881aad8730c5ab11d275376323d8e4ff4179aae8ccb6c13fe4902137e162ef" + }, + { + "name": "__tuple_element", + "typeId": "d7649d428b9ff33d188ecbf38a7e4d8fd167fa01b2e10fe9a8f9308e52f1d7cc" + }, + { + "name": "__tuple_element", + "typeId": "1506e6f44c1d6291cdf46395a8e573276a4fa79e8ace3fc891e092ef32d1b0a0" + }, + { + "name": "__tuple_element", + "typeId": "1b5759d94094368cfd443019e7ca5ec4074300e544e5ea993a979f5da627261e" + }, + { + "name": "__tuple_element", + "typeId": "7c5ee1cecf5f8eacd1284feb5f0bf2bdea533a51e2f0c9aabe9236d335989f3b" + }, + { + "name": "__tuple_element", + "typeId": "94f0fa95c830be5e4f711963e83259fe7e8bc723278ab6ec34449e791a99b53a" + }, + { + "name": "__tuple_element", + "typeId": 1 + }, + { + "name": "__tuple_element", + "typeId": 4 + }, + { + "name": "__tuple_element", + "typeId": 7, + "typeArguments": [ + { + "name": "", + "typeId": "c89951a24c6ca28c13fd1cfdc646b2b656d69e61a92b91023be7eb58eb914b6b" + } + ] + }, + { + "name": "__tuple_element", + "typeId": 5, + "typeArguments": [ + { + "name": "", + "typeId": "b760f44fa5965c2474a3b471467a22c43185152129295af588b022ae50b50903" + } + ] + } + ] + }, + { + "type": "[_; 3]", + "metadataTypeId": 4, + "components": [ + { + "name": "__array_element", + "typeId": "d7649d428b9ff33d188ecbf38a7e4d8fd167fa01b2e10fe9a8f9308e52f1d7cc" + } + ] + }, + { + "type": "enum EnumWithGeneric", + "metadataTypeId": 5, + "components": [ + { + "name": "VariantOne", + "typeId": 6 + }, + { + "name": "VariantTwo", + "typeId": 0 + } + ], + "typeParameters": [ + 6 + ] + }, + { + "type": "generic D", + "metadataTypeId": 6 + }, + { + "type": "struct StructWithGeneric", + "metadataTypeId": 7, + "components": [ + { + "name": "field_1", + "typeId": 6 + }, + { + "name": "field_2", + "typeId": "1506e6f44c1d6291cdf46395a8e573276a4fa79e8ace3fc891e092ef32d1b0a0" + } + ], + "typeParameters": [ + 6 + ] + } + ], + "functions": [ + { + "inputs": [ + { + "name": "a", + "concreteTypeId": "d7649d428b9ff33d188ecbf38a7e4d8fd167fa01b2e10fe9a8f9308e52f1d7cc" + }, + { + "name": "contract_addr", + "concreteTypeId": "7c5ee1cecf5f8eacd1284feb5f0bf2bdea533a51e2f0c9aabe9236d335989f3b" + } + ], + "name": "main", + "output": "25fbba860b8a1983ebcfa3f135136266a7edb7ca3a7e1f8ec988135c12a9f873", + "attributes": null + } + ], + "loggedTypes": [ + { + "logId": "14454674236531057292", + "concreteTypeId": "c89951a24c6ca28c13fd1cfdc646b2b656d69e61a92b91023be7eb58eb914b6b" + } + ], + "messagesTypes": [], + "configurables": [ + { + "name": "BOOL", + "concreteTypeId": "b760f44fa5965c2474a3b471467a22c43185152129295af588b022ae50b50903", + "offset": 8560 + }, + { + "name": "U8", + "concreteTypeId": "c89951a24c6ca28c13fd1cfdc646b2b656d69e61a92b91023be7eb58eb914b6b", + "offset": 8672 + }, + { + "name": "U16", + "concreteTypeId": "29881aad8730c5ab11d275376323d8e4ff4179aae8ccb6c13fe4902137e162ef", + "offset": 8616 + }, + { + "name": "U32", + "concreteTypeId": "d7649d428b9ff33d188ecbf38a7e4d8fd167fa01b2e10fe9a8f9308e52f1d7cc", + "offset": 8656 + }, + { + "name": "U64", + "concreteTypeId": "1506e6f44c1d6291cdf46395a8e573276a4fa79e8ace3fc891e092ef32d1b0a0", + "offset": 8664 + }, + { + "name": "U256", + "concreteTypeId": "1b5759d94094368cfd443019e7ca5ec4074300e544e5ea993a979f5da627261e", + "offset": 8624 + }, + { + "name": "B256", + "concreteTypeId": "7c5ee1cecf5f8eacd1284feb5f0bf2bdea533a51e2f0c9aabe9236d335989f3b", + "offset": 8528 + }, + { + "name": "STR_4", + "concreteTypeId": "94f0fa95c830be5e4f711963e83259fe7e8bc723278ab6ec34449e791a99b53a", + "offset": 8600 + }, + { + "name": "TUPLE", + "concreteTypeId": "e0128f7be9902d1fe16326cafe703b52038064a7997b03ebfc1c9dd607e1536c", + "offset": 8608 + }, + { + "name": "ARRAY", + "concreteTypeId": "d9fac01ab38fe10950758ae9604da330d6406a71fda3ef1ea818121261132d56", + "offset": 8512 + }, + { + "name": "STRUCT", + "concreteTypeId": "563310524b4f4447a10d0e50556310253dfb3b5eb4b29c3773222b737c8b7075", + "offset": 8584 + }, + { + "name": "ENUM", + "concreteTypeId": "37cd1cba311039a851ac8bfa614cc41359b4ad95c8656fcef2e8f504fe7a1272", + "offset": 8568 + } + ] +} \ No newline at end of file diff --git a/forc-plugins/forc-client/test/data/deployed_script/deployed_script-loader-abi.json b/forc-plugins/forc-client/test/data/deployed_script/deployed_script-loader-abi.json new file mode 100644 index 00000000000..81b65c43cd7 --- /dev/null +++ b/forc-plugins/forc-client/test/data/deployed_script/deployed_script-loader-abi.json @@ -0,0 +1,312 @@ +{ + "programType": "script", + "specVersion": "1", + "encodingVersion": "1", + "concreteTypes": [ + { + "type": "((bool, u8, u16, u32, u64, u256, b256, str[4], (u8, bool), [u32; 3], struct StructWithGeneric, enum EnumWithGeneric), bool, u64, u8)", + "concreteTypeId": "25fbba860b8a1983ebcfa3f135136266a7edb7ca3a7e1f8ec988135c12a9f873", + "metadataTypeId": 2 + }, + { + "type": "(u8, bool)", + "concreteTypeId": "e0128f7be9902d1fe16326cafe703b52038064a7997b03ebfc1c9dd607e1536c", + "metadataTypeId": 1 + }, + { + "type": "[u32; 3]", + "concreteTypeId": "d9fac01ab38fe10950758ae9604da330d6406a71fda3ef1ea818121261132d56", + "metadataTypeId": 4 + }, + { + "type": "b256", + "concreteTypeId": "7c5ee1cecf5f8eacd1284feb5f0bf2bdea533a51e2f0c9aabe9236d335989f3b" + }, + { + "type": "bool", + "concreteTypeId": "b760f44fa5965c2474a3b471467a22c43185152129295af588b022ae50b50903" + }, + { + "type": "enum EnumWithGeneric", + "concreteTypeId": "37cd1cba311039a851ac8bfa614cc41359b4ad95c8656fcef2e8f504fe7a1272", + "metadataTypeId": 5, + "typeArguments": [ + "b760f44fa5965c2474a3b471467a22c43185152129295af588b022ae50b50903" + ] + }, + { + "type": "str[4]", + "concreteTypeId": "94f0fa95c830be5e4f711963e83259fe7e8bc723278ab6ec34449e791a99b53a" + }, + { + "type": "struct StructWithGeneric", + "concreteTypeId": "563310524b4f4447a10d0e50556310253dfb3b5eb4b29c3773222b737c8b7075", + "metadataTypeId": 7, + "typeArguments": [ + "c89951a24c6ca28c13fd1cfdc646b2b656d69e61a92b91023be7eb58eb914b6b" + ] + }, + { + "type": "u16", + "concreteTypeId": "29881aad8730c5ab11d275376323d8e4ff4179aae8ccb6c13fe4902137e162ef" + }, + { + "type": "u256", + "concreteTypeId": "1b5759d94094368cfd443019e7ca5ec4074300e544e5ea993a979f5da627261e" + }, + { + "type": "u32", + "concreteTypeId": "d7649d428b9ff33d188ecbf38a7e4d8fd167fa01b2e10fe9a8f9308e52f1d7cc" + }, + { + "type": "u64", + "concreteTypeId": "1506e6f44c1d6291cdf46395a8e573276a4fa79e8ace3fc891e092ef32d1b0a0" + }, + { + "type": "u8", + "concreteTypeId": "c89951a24c6ca28c13fd1cfdc646b2b656d69e61a92b91023be7eb58eb914b6b" + } + ], + "metadataTypes": [ + { + "type": "()", + "metadataTypeId": 0 + }, + { + "type": "(_, _)", + "metadataTypeId": 1, + "components": [ + { + "name": "__tuple_element", + "typeId": "c89951a24c6ca28c13fd1cfdc646b2b656d69e61a92b91023be7eb58eb914b6b" + }, + { + "name": "__tuple_element", + "typeId": "b760f44fa5965c2474a3b471467a22c43185152129295af588b022ae50b50903" + } + ] + }, + { + "type": "(_, _, _, _)", + "metadataTypeId": 2, + "components": [ + { + "name": "__tuple_element", + "typeId": 3 + }, + { + "name": "__tuple_element", + "typeId": "b760f44fa5965c2474a3b471467a22c43185152129295af588b022ae50b50903" + }, + { + "name": "__tuple_element", + "typeId": "1506e6f44c1d6291cdf46395a8e573276a4fa79e8ace3fc891e092ef32d1b0a0" + }, + { + "name": "__tuple_element", + "typeId": "c89951a24c6ca28c13fd1cfdc646b2b656d69e61a92b91023be7eb58eb914b6b" + } + ] + }, + { + "type": "(_, _, _, _, _, _, _, _, _, _, _, _)", + "metadataTypeId": 3, + "components": [ + { + "name": "__tuple_element", + "typeId": "b760f44fa5965c2474a3b471467a22c43185152129295af588b022ae50b50903" + }, + { + "name": "__tuple_element", + "typeId": "c89951a24c6ca28c13fd1cfdc646b2b656d69e61a92b91023be7eb58eb914b6b" + }, + { + "name": "__tuple_element", + "typeId": "29881aad8730c5ab11d275376323d8e4ff4179aae8ccb6c13fe4902137e162ef" + }, + { + "name": "__tuple_element", + "typeId": "d7649d428b9ff33d188ecbf38a7e4d8fd167fa01b2e10fe9a8f9308e52f1d7cc" + }, + { + "name": "__tuple_element", + "typeId": "1506e6f44c1d6291cdf46395a8e573276a4fa79e8ace3fc891e092ef32d1b0a0" + }, + { + "name": "__tuple_element", + "typeId": "1b5759d94094368cfd443019e7ca5ec4074300e544e5ea993a979f5da627261e" + }, + { + "name": "__tuple_element", + "typeId": "7c5ee1cecf5f8eacd1284feb5f0bf2bdea533a51e2f0c9aabe9236d335989f3b" + }, + { + "name": "__tuple_element", + "typeId": "94f0fa95c830be5e4f711963e83259fe7e8bc723278ab6ec34449e791a99b53a" + }, + { + "name": "__tuple_element", + "typeId": 1 + }, + { + "name": "__tuple_element", + "typeId": 4 + }, + { + "name": "__tuple_element", + "typeId": 7, + "typeArguments": [ + { + "name": "", + "typeId": "c89951a24c6ca28c13fd1cfdc646b2b656d69e61a92b91023be7eb58eb914b6b" + } + ] + }, + { + "name": "__tuple_element", + "typeId": 5, + "typeArguments": [ + { + "name": "", + "typeId": "b760f44fa5965c2474a3b471467a22c43185152129295af588b022ae50b50903" + } + ] + } + ] + }, + { + "type": "[_; 3]", + "metadataTypeId": 4, + "components": [ + { + "name": "__array_element", + "typeId": "d7649d428b9ff33d188ecbf38a7e4d8fd167fa01b2e10fe9a8f9308e52f1d7cc" + } + ] + }, + { + "type": "enum EnumWithGeneric", + "metadataTypeId": 5, + "components": [ + { + "name": "VariantOne", + "typeId": 6 + }, + { + "name": "VariantTwo", + "typeId": 0 + } + ], + "typeParameters": [ + 6 + ] + }, + { + "type": "generic D", + "metadataTypeId": 6 + }, + { + "type": "struct StructWithGeneric", + "metadataTypeId": 7, + "components": [ + { + "name": "field_1", + "typeId": 6 + }, + { + "name": "field_2", + "typeId": "1506e6f44c1d6291cdf46395a8e573276a4fa79e8ace3fc891e092ef32d1b0a0" + } + ], + "typeParameters": [ + 6 + ] + } + ], + "functions": [ + { + "inputs": [ + { + "name": "a", + "concreteTypeId": "d7649d428b9ff33d188ecbf38a7e4d8fd167fa01b2e10fe9a8f9308e52f1d7cc" + }, + { + "name": "contract_addr", + "concreteTypeId": "7c5ee1cecf5f8eacd1284feb5f0bf2bdea533a51e2f0c9aabe9236d335989f3b" + } + ], + "name": "main", + "output": "25fbba860b8a1983ebcfa3f135136266a7edb7ca3a7e1f8ec988135c12a9f873", + "attributes": null + } + ], + "loggedTypes": [ + { + "logId": "14454674236531057292", + "concreteTypeId": "c89951a24c6ca28c13fd1cfdc646b2b656d69e61a92b91023be7eb58eb914b6b" + } + ], + "messagesTypes": [], + "configurables": [ + { + "name": "BOOL", + "concreteTypeId": "b760f44fa5965c2474a3b471467a22c43185152129295af588b022ae50b50903", + "offset": 136 + }, + { + "name": "U8", + "concreteTypeId": "c89951a24c6ca28c13fd1cfdc646b2b656d69e61a92b91023be7eb58eb914b6b", + "offset": 248 + }, + { + "name": "U16", + "concreteTypeId": "29881aad8730c5ab11d275376323d8e4ff4179aae8ccb6c13fe4902137e162ef", + "offset": 192 + }, + { + "name": "U32", + "concreteTypeId": "d7649d428b9ff33d188ecbf38a7e4d8fd167fa01b2e10fe9a8f9308e52f1d7cc", + "offset": 232 + }, + { + "name": "U64", + "concreteTypeId": "1506e6f44c1d6291cdf46395a8e573276a4fa79e8ace3fc891e092ef32d1b0a0", + "offset": 240 + }, + { + "name": "U256", + "concreteTypeId": "1b5759d94094368cfd443019e7ca5ec4074300e544e5ea993a979f5da627261e", + "offset": 200 + }, + { + "name": "B256", + "concreteTypeId": "7c5ee1cecf5f8eacd1284feb5f0bf2bdea533a51e2f0c9aabe9236d335989f3b", + "offset": 104 + }, + { + "name": "STR_4", + "concreteTypeId": "94f0fa95c830be5e4f711963e83259fe7e8bc723278ab6ec34449e791a99b53a", + "offset": 176 + }, + { + "name": "TUPLE", + "concreteTypeId": "e0128f7be9902d1fe16326cafe703b52038064a7997b03ebfc1c9dd607e1536c", + "offset": 184 + }, + { + "name": "ARRAY", + "concreteTypeId": "d9fac01ab38fe10950758ae9604da330d6406a71fda3ef1ea818121261132d56", + "offset": 88 + }, + { + "name": "STRUCT", + "concreteTypeId": "563310524b4f4447a10d0e50556310253dfb3b5eb4b29c3773222b737c8b7075", + "offset": 160 + }, + { + "name": "ENUM", + "concreteTypeId": "37cd1cba311039a851ac8bfa614cc41359b4ad95c8656fcef2e8f504fe7a1272", + "offset": 144 + } + ] +} \ No newline at end of file diff --git a/forc-plugins/forc-client/test/data/deployed_script/deployed_script.bin b/forc-plugins/forc-client/test/data/deployed_script/deployed_script.bin new file mode 100644 index 00000000000..0daa7de8f3e Binary files /dev/null and b/forc-plugins/forc-client/test/data/deployed_script/deployed_script.bin differ diff --git a/forc-plugins/forc-client/test/data/deployed_script/src/main.sw b/forc-plugins/forc-client/test/data/deployed_script/src/main.sw new file mode 100644 index 00000000000..c47105d4d74 --- /dev/null +++ b/forc-plugins/forc-client/test/data/deployed_script/src/main.sw @@ -0,0 +1,72 @@ +script; + +use std::logging::log; + +#[allow(dead_code)] +enum EnumWithGeneric { + VariantOne: D, + VariantTwo: (), +} + +struct StructWithGeneric { + field_1: D, + field_2: u64, +} + +abi MyContract { + fn test_function() -> bool; + + #[storage(read)] + fn test_function_read() -> u8; + + #[storage(read, write)] + fn test_function_write(value: u8) -> u8; +} + +configurable { + BOOL: bool = true, + U8: u8 = 8, + U16: u16 = 16, + U32: u32 = 32, + U64: u64 = 63, + U256: u256 = 0x0000000000000000000000000000000000000000000000000000000000000008u256, + B256: b256 = 0x0101010101010101010101010101010101010101010101010101010101010101, + STR_4: str[4] = __to_str_array("fuel"), + TUPLE: (u8, bool) = (8, true), + ARRAY: [u32; 3] = [253, 254, 255], + STRUCT: StructWithGeneric = StructWithGeneric { + field_1: 8, + field_2: 16, + }, + ENUM: EnumWithGeneric = EnumWithGeneric::VariantOne(true), +} + +fn get_configurables() -> (bool, u8, u16, u32, u64, u256, b256, str[4], (u8, bool), [u32; 3], StructWithGeneric, EnumWithGeneric) { + (BOOL, U8, U16, U32, U64, U256, B256, STR_4, TUPLE, ARRAY, STRUCT, ENUM) +} + +fn basic_function_with_input(a: u32) -> bool { + if a % 2 == 0 { + true + }else { + false + } +} + +fn basic_function_without_input() -> u64 { + let a = 100; + let b = 25; + a*b +} + +fn main(a: u32, contract_addr: b256) -> ((bool, u8, u16, u32, u64, u256, b256, str[4], (u8, bool), [u32; 3], StructWithGeneric, EnumWithGeneric), bool, u64, u8) { + log(U8); + let configs = get_configurables(); + let with_in = basic_function_with_input(a); + let without_in = basic_function_without_input(); + + let contract_instance = abi(MyContract, contract_addr); + let from_contract = contract_instance.test_function_read(); + + return (configs, with_in, without_in, from_contract); +} diff --git a/forc-plugins/forc-client/test/data/standalone_contract/Forc.lock b/forc-plugins/forc-client/test/data/standalone_contract/Forc.lock new file mode 100644 index 00000000000..7b517045569 --- /dev/null +++ b/forc-plugins/forc-client/test/data/standalone_contract/Forc.lock @@ -0,0 +1,13 @@ +[[package]] +name = "core" +source = "path+from-root-79BB3EA8498403DE" + +[[package]] +name = "standalone_contract" +source = "member" +dependencies = ["std"] + +[[package]] +name = "std" +source = "path+from-root-79BB3EA8498403DE" +dependencies = ["core"] diff --git a/forc-plugins/forc-client/test/data/standalone_contract/Forc.toml b/forc-plugins/forc-client/test/data/standalone_contract/Forc.toml index de97c7bf31f..2324ff98894 100644 --- a/forc-plugins/forc-client/test/data/standalone_contract/Forc.toml +++ b/forc-plugins/forc-client/test/data/standalone_contract/Forc.toml @@ -6,4 +6,4 @@ license = "Apache-2.0" name = "standalone_contract" [dependencies] -std = { path = "../../../../../../../../sway-lib-std/" } +std = { path = "../../../../../sway-lib-std/" } diff --git a/forc-plugins/forc-client/test/data/standalone_contract/src/main.sw b/forc-plugins/forc-client/test/data/standalone_contract/src/main.sw index 7d4a75493c6..49e0ac20ae2 100644 --- a/forc-plugins/forc-client/test/data/standalone_contract/src/main.sw +++ b/forc-plugins/forc-client/test/data/standalone_contract/src/main.sw @@ -1,11 +1,32 @@ contract; +storage { + value: u8 = 5, +} + abi MyContract { fn test_function() -> bool; + + #[storage(read)] + fn test_function_read() -> u8; + + #[storage(read, write)] + fn test_function_write(value: u8) -> u8; } impl MyContract for Contract { fn test_function() -> bool { true } + + #[storage(read)] + fn test_function_read() -> u8 { + storage.value.read() + } + + #[storage(read, write)] + fn test_function_write(value: u8) -> u8 { + storage.value.write(value); + storage.value.read() + } } diff --git a/forc-plugins/forc-client/test/data/standalone_contract/standalone_contract-abi.json b/forc-plugins/forc-client/test/data/standalone_contract/standalone_contract-abi.json new file mode 100644 index 00000000000..0dfb6f2fad7 --- /dev/null +++ b/forc-plugins/forc-client/test/data/standalone_contract/standalone_contract-abi.json @@ -0,0 +1,59 @@ +{ + "programType": "contract", + "specVersion": "1", + "encodingVersion": "1", + "concreteTypes": [ + { + "type": "bool", + "concreteTypeId": "b760f44fa5965c2474a3b471467a22c43185152129295af588b022ae50b50903" + }, + { + "type": "u8", + "concreteTypeId": "c89951a24c6ca28c13fd1cfdc646b2b656d69e61a92b91023be7eb58eb914b6b" + } + ], + "metadataTypes": [], + "functions": [ + { + "inputs": [], + "name": "test_function", + "output": "b760f44fa5965c2474a3b471467a22c43185152129295af588b022ae50b50903", + "attributes": null + }, + { + "inputs": [], + "name": "test_function_read", + "output": "c89951a24c6ca28c13fd1cfdc646b2b656d69e61a92b91023be7eb58eb914b6b", + "attributes": [ + { + "name": "storage", + "arguments": [ + "read" + ] + } + ] + }, + { + "inputs": [ + { + "name": "value", + "concreteTypeId": "c89951a24c6ca28c13fd1cfdc646b2b656d69e61a92b91023be7eb58eb914b6b" + } + ], + "name": "test_function_write", + "output": "c89951a24c6ca28c13fd1cfdc646b2b656d69e61a92b91023be7eb58eb914b6b", + "attributes": [ + { + "name": "storage", + "arguments": [ + "read", + "write" + ] + } + ] + } + ], + "loggedTypes": [], + "messagesTypes": [], + "configurables": [] +} \ No newline at end of file diff --git a/forc-plugins/forc-client/tests/deploy.rs b/forc-plugins/forc-client/tests/deploy.rs new file mode 100644 index 00000000000..dae3c123f51 --- /dev/null +++ b/forc-plugins/forc-client/tests/deploy.rs @@ -0,0 +1,1313 @@ +use forc::cli::shared::Pkg; +use forc_client::{ + cmd, + op::{deploy, DeployedContract, DeployedExecutable, DeployedPackage}, + util::{account::ForcClientAccount, tx::update_proxy_contract_target}, + NodeTarget, +}; +use forc_pkg::manifest::Proxy; +use fuel_crypto::SecretKey; +use fuel_tx::{ContractId, Salt}; +use fuels::{ + macros::abigen, + types::{transaction::TxPolicies, AsciiString, Bits256, SizedAsciiString}, +}; +use fuels_accounts::{provider::Provider, wallet::WalletUnlocked, Account, ViewOnlyAccount}; +use portpicker::Port; +use rand::thread_rng; +use rexpect::spawn; +use std::{ + fs, + path::{Path, PathBuf}, + process::{Child, Command}, + str::FromStr, +}; +use tempfile::tempdir; +use toml_edit::{value, DocumentMut, InlineTable, Item, Table, Value}; + +fn get_workspace_root() -> PathBuf { + PathBuf::from(env!("CARGO_MANIFEST_DIR")) + .join("../") + .join("../") + .canonicalize() + .unwrap() +} + +fn test_data_path() -> PathBuf { + PathBuf::from(env!("CARGO_MANIFEST_DIR")) + .join("test") + .join("data") + .canonicalize() + .unwrap() +} + +fn run_node() -> (Child, Port) { + let port = portpicker::pick_unused_port().expect("No ports free"); + + let child = Command::new("fuel-core") + .arg("run") + .arg("--debug") + .arg("--db-type") + .arg("in-memory") + .arg("--port") + .arg(port.to_string()) + .spawn() + .expect("Failed to start fuel-core"); + (child, port) +} + +/// Copy a directory recursively from `source` to `dest`. +fn copy_dir(source: &Path, dest: &Path) -> anyhow::Result<()> { + fs::create_dir_all(dest)?; + for e in fs::read_dir(source)? { + let entry = e?; + let file_type = entry.file_type()?; + if file_type.is_dir() { + copy_dir(&entry.path(), &dest.join(entry.file_name()))?; + } else { + fs::copy(entry.path(), dest.join(entry.file_name()))?; + } + } + Ok(()) +} + +/// Tries to get an `DeployedContract` out of the given `DeployedPackage`. +/// Panics otherwise. +fn expect_deployed_contract(deployed_package: DeployedPackage) -> DeployedContract { + if let DeployedPackage::Contract(contract) = deployed_package { + contract + } else { + println!("{deployed_package:?}"); + panic!("expected deployed package to be a contract") + } +} + +/// Tries to get a script (`DeployedExecutable`) out of given deployed package. +/// Panics otherwise. +fn expect_deployed_script(deployed_package: DeployedPackage) -> DeployedExecutable { + if let DeployedPackage::Script(script) = deployed_package { + script + } else { + panic!("expected deployed package to be a script") + } +} + +/// Tries to get a predicate (`DeployedExecutable`) out of given deployed package. +/// Panics otherwise. +fn expect_deployed_predicate(deployed_package: DeployedPackage) -> DeployedExecutable { + if let DeployedPackage::Predicate(predicate) = deployed_package { + predicate + } else { + panic!("expected deployed package to be a predicate") + } +} + +fn patch_manifest_file_with_path_std(manifest_dir: &Path) -> anyhow::Result<()> { + let toml_path = manifest_dir.join(sway_utils::constants::MANIFEST_FILE_NAME); + let toml_content = fs::read_to_string(&toml_path).unwrap(); + + let mut doc = toml_content.parse::().unwrap(); + let new_std_path = get_workspace_root().join("sway-lib-std"); + + let mut std_dependency = InlineTable::new(); + std_dependency.insert("path", Value::from(new_std_path.display().to_string())); + doc["dependencies"]["std"] = Item::Value(Value::InlineTable(std_dependency)); + + fs::write(&toml_path, doc.to_string()).unwrap(); + Ok(()) +} + +fn patch_manifest_file_with_proxy_table(manifest_dir: &Path, proxy: Proxy) -> anyhow::Result<()> { + let toml_path = manifest_dir.join(sway_utils::constants::MANIFEST_FILE_NAME); + let toml_content = fs::read_to_string(&toml_path)?; + let mut doc = toml_content.parse::()?; + + let proxy_table = doc.entry("proxy").or_insert(Item::Table(Table::new())); + let proxy_table = proxy_table.as_table_mut().unwrap(); + + proxy_table.insert("enabled", value(proxy.enabled)); + + if let Some(address) = proxy.address { + proxy_table.insert("address", value(address)); + } else { + proxy_table.remove("address"); + } + + fs::write(&toml_path, doc.to_string())?; + Ok(()) +} + +fn update_main_sw(tmp_dir: &Path) -> anyhow::Result<()> { + let main_sw_path = tmp_dir.join("src").join("main.sw"); + let content = fs::read_to_string(&main_sw_path)?; + let updated_content = content.replace("true", "false"); + fs::write(main_sw_path, updated_content)?; + Ok(()) +} + +async fn assert_big_contract_calls(wallet: WalletUnlocked, contract_id: ContractId) { + abigen!(Contract( + name = "BigContract", + abi = "forc-plugins/forc-client/test/data/big_contract/big_contract-abi.json" + )); + + let instance = BigContract::new(contract_id, wallet); + + let result = instance.methods().large_blob().call().await.unwrap().value; + assert!(result); + + let result = instance + .methods() + .enum_input_output(Location::Mars) + .call() + .await + .unwrap() + .value; + assert_eq!(result, Location::Mars); + + // Test enum with "tuple like struct" with simple value. + let result = instance + .methods() + .enum_input_output(Location::Earth(u64::MAX)) + .call() + .await + .unwrap() + .value; + assert_eq!(result, Location::Earth(u64::MAX)); + + // Test enum with "tuple like struct" with enum value. + let result = instance + .methods() + .enum_input_output(Location::SimpleJupiter(Color::Red)) + .call() + .await + .unwrap() + .value; + assert_eq!(result, Location::SimpleJupiter(Color::Red)); + + // Test enum with "tuple like struct" with enum value. + let result = instance + .methods() + .enum_input_output(Location::SimpleJupiter(Color::Blue(u64::MAX))) + .call() + .await + .unwrap() + .value; + assert_eq!(result, Location::SimpleJupiter(Color::Blue(u64::MAX))); + + // Test enum with "tuple like struct" with enum array value. + let result = instance + .methods() + .enum_input_output(Location::Jupiter([Color::Red, Color::Blue(u64::MAX)])) + .call() + .await + .unwrap() + .value; + assert_eq!( + result, + Location::Jupiter([Color::Red, Color::Blue(u64::MAX)]) + ); + + // Test enum with "tuple like struct" with struct array value. + let result = instance + .methods() + .enum_input_output(Location::SimplePluto(SimpleStruct { + a: true, + b: u64::MAX, + })) + .call() + .await + .unwrap() + .value; + assert_eq!( + result, + Location::SimplePluto(SimpleStruct { + a: true, + b: u64::MAX, + }) + ); + + let input = Person { + name: AsciiString::new("Alice".into()).unwrap(), + age: 42, + alive: true, + location: Location::Earth(1), + some_tuple: (false, 42), + some_array: [4, 2], + some_b_256: Bits256::zeroed(), + }; + let result = instance + .methods() + .struct_input_output(input.clone()) + .call() + .await + .unwrap() + .value; + assert_eq!(result, input); + + let _ = instance + .methods() + .push_storage_u16(42) + .call() + .await + .unwrap(); + let result = instance + .methods() + .get_storage_u16(0) + .call() + .await + .unwrap() + .value; + assert_eq!(result, 42); + + let _ = instance + .methods() + .push_storage_simple(SimpleStruct { + a: true, + b: u64::MAX, + }) + .call() + .await + .unwrap(); + let result = instance + .methods() + .get_storage_simple(0) + .call() + .await + .unwrap() + .value; + assert_eq!( + result, + SimpleStruct { + a: true, + b: u64::MAX, + } + ); + + let _ = instance + .methods() + .push_storage_location(Location::Mars) + .call() + .await + .unwrap(); + let result = instance + .methods() + .get_storage_location(0) + .call() + .await + .unwrap() + .value; + assert_eq!(result, Location::Mars); + + let _ = instance + .methods() + .push_storage_location(Location::Earth(u64::MAX)) + .call() + .await + .unwrap(); + let result = instance + .methods() + .get_storage_location(1) + .call() + .await + .unwrap() + .value; + assert_eq!(result, Location::Earth(u64::MAX)); + + let _ = instance + .methods() + .push_storage_location(Location::Jupiter([Color::Red, Color::Blue(u64::MAX)])) + .call() + .await + .unwrap(); + let result = instance + .methods() + .get_storage_location(2) + .call() + .await + .unwrap() + .value; + assert_eq!( + result, + Location::Jupiter([Color::Red, Color::Blue(u64::MAX)]) + ); + + let result = instance + .methods() + .assert_configurables() + .call() + .await + .unwrap() + .value; + assert!(result); +} + +#[tokio::test] +async fn test_simple_deploy() { + let (mut node, port) = run_node(); + let tmp_dir = tempdir().unwrap(); + let project_dir = test_data_path().join("standalone_contract"); + copy_dir(&project_dir, tmp_dir.path()).unwrap(); + patch_manifest_file_with_path_std(tmp_dir.path()).unwrap(); + + let pkg = Pkg { + path: Some(tmp_dir.path().display().to_string()), + ..Default::default() + }; + + let node_url = format!("http://127.0.0.1:{}/v1/graphql", port); + let target = NodeTarget { + node_url: Some(node_url), + target: None, + testnet: false, + mainnet: false, + }; + let cmd = cmd::Deploy { + pkg, + salt: Some(vec![format!("{}", Salt::default())]), + node: target, + default_signer: true, + ..Default::default() + }; + let contract_ids = deploy(cmd).await.unwrap(); + node.kill().unwrap(); + let expected = vec![DeployedPackage::Contract(DeployedContract { + id: ContractId::from_str( + "e50f0b4b396504398c0aff45951b1e44e108399c856cb92257dfa58fe96d53eb", + ) + .unwrap(), + proxy: None, + chunked: false, + })]; + + assert_eq!(contract_ids, expected) +} + +#[tokio::test] +async fn test_deploy_submit_only() { + let (mut node, port) = run_node(); + let tmp_dir = tempdir().unwrap(); + let project_dir = test_data_path().join("standalone_contract"); + copy_dir(&project_dir, tmp_dir.path()).unwrap(); + patch_manifest_file_with_path_std(tmp_dir.path()).unwrap(); + + let pkg = Pkg { + path: Some(tmp_dir.path().display().to_string()), + ..Default::default() + }; + + let node_url = format!("http://127.0.0.1:{}/v1/graphql", port); + + let target = NodeTarget { + node_url: Some(node_url), + target: None, + testnet: false, + mainnet: false, + }; + let cmd = cmd::Deploy { + pkg, + salt: Some(vec![format!("{}", Salt::default())]), + node: target, + default_signer: true, + submit_only: true, + ..Default::default() + }; + let contract_ids = deploy(cmd).await.unwrap(); + node.kill().unwrap(); + let expected = vec![DeployedPackage::Contract(DeployedContract { + id: ContractId::from_str( + "e50f0b4b396504398c0aff45951b1e44e108399c856cb92257dfa58fe96d53eb", + ) + .unwrap(), + proxy: None, + chunked: false, + })]; + + assert_eq!(contract_ids, expected) +} + +#[tokio::test] +async fn test_deploy_fresh_proxy() { + let (mut node, port) = run_node(); + let tmp_dir = tempdir().unwrap(); + let project_dir = test_data_path().join("standalone_contract"); + copy_dir(&project_dir, tmp_dir.path()).unwrap(); + patch_manifest_file_with_path_std(tmp_dir.path()).unwrap(); + let proxy = Proxy { + enabled: true, + address: None, + }; + patch_manifest_file_with_proxy_table(tmp_dir.path(), proxy).unwrap(); + + let pkg = Pkg { + path: Some(tmp_dir.path().display().to_string()), + ..Default::default() + }; + + let node_url = format!("http://127.0.0.1:{}/v1/graphql", port); + let target = NodeTarget { + node_url: Some(node_url), + target: None, + testnet: false, + mainnet: false, + }; + let cmd = cmd::Deploy { + pkg, + salt: Some(vec![format!("{}", Salt::default())]), + node: target, + default_signer: true, + ..Default::default() + }; + let contract_ids = deploy(cmd).await.unwrap(); + node.kill().unwrap(); + let impl_contract = DeployedPackage::Contract(DeployedContract { + id: ContractId::from_str( + "e50f0b4b396504398c0aff45951b1e44e108399c856cb92257dfa58fe96d53eb", + ) + .unwrap(), + proxy: Some( + ContractId::from_str( + "1c50e2d4d602fdd88b47fb7b84b7f87bbdefcf9b7e5985bb7ceeee9266a8e977", + ) + .unwrap(), + ), + chunked: false, + }); + let expected = vec![impl_contract]; + + assert_eq!(contract_ids, expected) +} + +#[tokio::test] +async fn test_proxy_contract_re_routes_call() { + let (mut node, port) = run_node(); + let tmp_dir = tempdir().unwrap(); + let project_dir = test_data_path().join("standalone_contract"); + copy_dir(&project_dir, tmp_dir.path()).unwrap(); + patch_manifest_file_with_path_std(tmp_dir.path()).unwrap(); + let proxy = Proxy { + enabled: true, + address: None, + }; + patch_manifest_file_with_proxy_table(tmp_dir.path(), proxy).unwrap(); + + let pkg = Pkg { + path: Some(tmp_dir.path().display().to_string()), + ..Default::default() + }; + + let node_url = format!("http://127.0.0.1:{}/v1/graphql", port); + let target = NodeTarget { + node_url: Some(node_url.clone()), + target: None, + testnet: false, + mainnet: false, + }; + let cmd = cmd::Deploy { + pkg, + salt: Some(vec![format!("{}", Salt::default())]), + node: target, + default_signer: true, + ..Default::default() + }; + let deployed_contract = expect_deployed_contract(deploy(cmd).await.unwrap().remove(0)); + // At this point we deployed a contract with proxy. + let proxy_contract_id = deployed_contract.proxy.unwrap(); + let impl_contract_id = deployed_contract.id; + // Make a contract call into proxy contract, and check if the initial + // contract returns a true. + let provider = Provider::connect(&node_url).await.unwrap(); + let secret_key = SecretKey::from_str(forc_client::constants::DEFAULT_PRIVATE_KEY).unwrap(); + let wallet_unlocked = WalletUnlocked::new_from_private_key(secret_key, Some(provider)); + + abigen!(Contract( + name = "ImplementationContract", + abi = "forc-plugins/forc-client/test/data/standalone_contract/standalone_contract-abi.json" + )); + + let impl_contract_a = ImplementationContract::new(proxy_contract_id, wallet_unlocked.clone()); + + // Test storage functions + let res = impl_contract_a + .methods() + .test_function_read() + .with_contract_ids(&[impl_contract_id.into()]) + .call() + .await + .unwrap(); + assert_eq!(res.value, 5); + let res = impl_contract_a + .methods() + .test_function_write(8) + .with_contract_ids(&[impl_contract_id.into()]) + .call() + .await + .unwrap(); + assert_eq!(res.value, 8); + + let res = impl_contract_a + .methods() + .test_function() + .with_contract_ids(&[impl_contract_id.into()]) + .call() + .await + .unwrap(); + assert!(res.value); + + update_main_sw(tmp_dir.path()).unwrap(); + let target = NodeTarget { + node_url: Some(node_url.clone()), + target: None, + testnet: false, + mainnet: false, + }; + let pkg = Pkg { + path: Some(tmp_dir.path().display().to_string()), + ..Default::default() + }; + + let cmd = cmd::Deploy { + pkg, + salt: Some(vec![format!("{}", Salt::default())]), + node: target, + default_signer: true, + ..Default::default() + }; + let deployed_contract = expect_deployed_contract(deploy(cmd).await.unwrap().remove(0)); + // proxy contract id should be the same. + let proxy_contract_after_update = deployed_contract.proxy.unwrap(); + assert_eq!(proxy_contract_id, proxy_contract_after_update); + let impl_contract_id_after_update = deployed_contract.id; + assert!(impl_contract_id != impl_contract_id_after_update); + let impl_contract_a = ImplementationContract::new(proxy_contract_after_update, wallet_unlocked); + + // Test storage functions + let res = impl_contract_a + .methods() + .test_function_read() + .with_contract_ids(&[impl_contract_id_after_update.into()]) + .call() + .await + .unwrap(); + // Storage should be preserved from the previous target contract. + assert_eq!(res.value, 8); + let res = impl_contract_a + .methods() + .test_function_write(9) + .with_contract_ids(&[impl_contract_id_after_update.into()]) + .call() + .await + .unwrap(); + assert_eq!(res.value, 9); + + let res = impl_contract_a + .methods() + .test_function() + .with_contract_ids(&[impl_contract_id_after_update.into()]) + .call() + .await + .unwrap(); + assert!(!res.value); + node.kill().unwrap(); +} + +#[tokio::test] +async fn test_non_owner_fails_to_set_target() { + let (mut node, port) = run_node(); + let tmp_dir = tempdir().unwrap(); + let project_dir = test_data_path().join("standalone_contract"); + copy_dir(&project_dir, tmp_dir.path()).unwrap(); + patch_manifest_file_with_path_std(tmp_dir.path()).unwrap(); + let proxy = Proxy { + enabled: true, + address: None, + }; + patch_manifest_file_with_proxy_table(tmp_dir.path(), proxy).unwrap(); + + let pkg = Pkg { + path: Some(tmp_dir.path().display().to_string()), + ..Default::default() + }; + + let node_url = format!("http://127.0.0.1:{}/v1/graphql", port); + let target = NodeTarget { + node_url: Some(node_url.clone()), + target: None, + testnet: false, + mainnet: false, + }; + let cmd = cmd::Deploy { + pkg, + salt: Some(vec![format!("{}", Salt::default())]), + node: target, + default_signer: true, + ..Default::default() + }; + let contract_id = expect_deployed_contract(deploy(cmd).await.unwrap().remove(0)); + // Proxy contract's id. + let proxy_id = contract_id.proxy.unwrap(); + + // Create and fund an owner account and an attacker account. + let provider = Provider::connect(&node_url).await.unwrap(); + let attacker_secret_key = SecretKey::random(&mut thread_rng()); + let attacker_wallet = + WalletUnlocked::new_from_private_key(attacker_secret_key, Some(provider.clone())); + + let owner_secret_key = + SecretKey::from_str(forc_client::constants::DEFAULT_PRIVATE_KEY).unwrap(); + let owner_wallet = + WalletUnlocked::new_from_private_key(owner_secret_key, Some(provider.clone())); + let base_asset_id = provider.base_asset_id(); + + // Fund attacker wallet so that it can try to make a set proxy target call. + owner_wallet + .transfer( + attacker_wallet.address(), + 100000, + *base_asset_id, + TxPolicies::default(), + ) + .await + .unwrap(); + + let dummy_contract_id_target = ContractId::default(); + abigen!(Contract(name = "ProxyContract", abi = "{\"programType\":\"contract\",\"specVersion\":\"1\",\"encodingVersion\":\"1\",\"concreteTypes\":[{\"type\":\"()\",\"concreteTypeId\":\"2e38e77b22c314a449e91fafed92a43826ac6aa403ae6a8acb6cf58239fbaf5d\"},{\"type\":\"enum standards::src5::AccessError\",\"concreteTypeId\":\"3f702ea3351c9c1ece2b84048006c8034a24cbc2bad2e740d0412b4172951d3d\",\"metadataTypeId\":1},{\"type\":\"enum standards::src5::State\",\"concreteTypeId\":\"192bc7098e2fe60635a9918afb563e4e5419d386da2bdbf0d716b4bc8549802c\",\"metadataTypeId\":2},{\"type\":\"enum std::option::Option\",\"concreteTypeId\":\"0d79387ad3bacdc3b7aad9da3a96f4ce60d9a1b6002df254069ad95a3931d5c8\",\"metadataTypeId\":4,\"typeArguments\":[\"29c10735d33b5159f0c71ee1dbd17b36a3e69e41f00fab0d42e1bd9f428d8a54\"]},{\"type\":\"enum sway_libs::ownership::errors::InitializationError\",\"concreteTypeId\":\"1dfe7feadc1d9667a4351761230f948744068a090fe91b1bc6763a90ed5d3893\",\"metadataTypeId\":5},{\"type\":\"enum sway_libs::upgradability::errors::SetProxyOwnerError\",\"concreteTypeId\":\"3c6e90ae504df6aad8b34a93ba77dc62623e00b777eecacfa034a8ac6e890c74\",\"metadataTypeId\":6},{\"type\":\"str\",\"concreteTypeId\":\"8c25cb3686462e9a86d2883c5688a22fe738b0bbc85f458d2d2b5f3f667c6d5a\"},{\"type\":\"struct std::contract_id::ContractId\",\"concreteTypeId\":\"29c10735d33b5159f0c71ee1dbd17b36a3e69e41f00fab0d42e1bd9f428d8a54\",\"metadataTypeId\":9},{\"type\":\"struct sway_libs::upgradability::events::ProxyOwnerSet\",\"concreteTypeId\":\"96dd838b44f99d8ccae2a7948137ab6256c48ca4abc6168abc880de07fba7247\",\"metadataTypeId\":10},{\"type\":\"struct sway_libs::upgradability::events::ProxyTargetSet\",\"concreteTypeId\":\"1ddc0adda1270a016c08ffd614f29f599b4725407c8954c8b960bdf651a9a6c8\",\"metadataTypeId\":11}],\"metadataTypes\":[{\"type\":\"b256\",\"metadataTypeId\":0},{\"type\":\"enum standards::src5::AccessError\",\"metadataTypeId\":1,\"components\":[{\"name\":\"NotOwner\",\"typeId\":\"2e38e77b22c314a449e91fafed92a43826ac6aa403ae6a8acb6cf58239fbaf5d\"}]},{\"type\":\"enum standards::src5::State\",\"metadataTypeId\":2,\"components\":[{\"name\":\"Uninitialized\",\"typeId\":\"2e38e77b22c314a449e91fafed92a43826ac6aa403ae6a8acb6cf58239fbaf5d\"},{\"name\":\"Initialized\",\"typeId\":3},{\"name\":\"Revoked\",\"typeId\":\"2e38e77b22c314a449e91fafed92a43826ac6aa403ae6a8acb6cf58239fbaf5d\"}]},{\"type\":\"enum std::identity::Identity\",\"metadataTypeId\":3,\"components\":[{\"name\":\"Address\",\"typeId\":8},{\"name\":\"ContractId\",\"typeId\":9}]},{\"type\":\"enum std::option::Option\",\"metadataTypeId\":4,\"components\":[{\"name\":\"None\",\"typeId\":\"2e38e77b22c314a449e91fafed92a43826ac6aa403ae6a8acb6cf58239fbaf5d\"},{\"name\":\"Some\",\"typeId\":7}],\"typeParameters\":[7]},{\"type\":\"enum sway_libs::ownership::errors::InitializationError\",\"metadataTypeId\":5,\"components\":[{\"name\":\"CannotReinitialized\",\"typeId\":\"2e38e77b22c314a449e91fafed92a43826ac6aa403ae6a8acb6cf58239fbaf5d\"}]},{\"type\":\"enum sway_libs::upgradability::errors::SetProxyOwnerError\",\"metadataTypeId\":6,\"components\":[{\"name\":\"CannotUninitialize\",\"typeId\":\"2e38e77b22c314a449e91fafed92a43826ac6aa403ae6a8acb6cf58239fbaf5d\"}]},{\"type\":\"generic T\",\"metadataTypeId\":7},{\"type\":\"struct std::address::Address\",\"metadataTypeId\":8,\"components\":[{\"name\":\"bits\",\"typeId\":0}]},{\"type\":\"struct std::contract_id::ContractId\",\"metadataTypeId\":9,\"components\":[{\"name\":\"bits\",\"typeId\":0}]},{\"type\":\"struct sway_libs::upgradability::events::ProxyOwnerSet\",\"metadataTypeId\":10,\"components\":[{\"name\":\"new_proxy_owner\",\"typeId\":2}]},{\"type\":\"struct sway_libs::upgradability::events::ProxyTargetSet\",\"metadataTypeId\":11,\"components\":[{\"name\":\"new_target\",\"typeId\":9}]}],\"functions\":[{\"inputs\":[],\"name\":\"proxy_target\",\"output\":\"0d79387ad3bacdc3b7aad9da3a96f4ce60d9a1b6002df254069ad95a3931d5c8\",\"attributes\":[{\"name\":\"doc-comment\",\"arguments\":[\" Returns the target contract of the proxy contract.\"]},{\"name\":\"doc-comment\",\"arguments\":[\"\"]},{\"name\":\"doc-comment\",\"arguments\":[\" # Returns\"]},{\"name\":\"doc-comment\",\"arguments\":[\"\"]},{\"name\":\"doc-comment\",\"arguments\":[\" * [Option] - The new proxy contract to which all fallback calls will be passed or `None`.\"]},{\"name\":\"doc-comment\",\"arguments\":[\"\"]},{\"name\":\"doc-comment\",\"arguments\":[\" # Number of Storage Accesses\"]},{\"name\":\"doc-comment\",\"arguments\":[\"\"]},{\"name\":\"doc-comment\",\"arguments\":[\" * Reads: `1`\"]},{\"name\":\"storage\",\"arguments\":[\"read\"]}]},{\"inputs\":[{\"name\":\"new_target\",\"concreteTypeId\":\"29c10735d33b5159f0c71ee1dbd17b36a3e69e41f00fab0d42e1bd9f428d8a54\"}],\"name\":\"set_proxy_target\",\"output\":\"2e38e77b22c314a449e91fafed92a43826ac6aa403ae6a8acb6cf58239fbaf5d\",\"attributes\":[{\"name\":\"doc-comment\",\"arguments\":[\" Change the target contract of the proxy contract.\"]},{\"name\":\"doc-comment\",\"arguments\":[\"\"]},{\"name\":\"doc-comment\",\"arguments\":[\" # Additional Information\"]},{\"name\":\"doc-comment\",\"arguments\":[\"\"]},{\"name\":\"doc-comment\",\"arguments\":[\" This method can only be called by the `proxy_owner`.\"]},{\"name\":\"doc-comment\",\"arguments\":[\"\"]},{\"name\":\"doc-comment\",\"arguments\":[\" # Arguments\"]},{\"name\":\"doc-comment\",\"arguments\":[\"\"]},{\"name\":\"doc-comment\",\"arguments\":[\" * `new_target`: [ContractId] - The new proxy contract to which all fallback calls will be passed.\"]},{\"name\":\"doc-comment\",\"arguments\":[\"\"]},{\"name\":\"doc-comment\",\"arguments\":[\" # Reverts\"]},{\"name\":\"doc-comment\",\"arguments\":[\"\"]},{\"name\":\"doc-comment\",\"arguments\":[\" * When not called by `proxy_owner`.\"]},{\"name\":\"doc-comment\",\"arguments\":[\"\"]},{\"name\":\"doc-comment\",\"arguments\":[\" # Number of Storage Accesses\"]},{\"name\":\"doc-comment\",\"arguments\":[\"\"]},{\"name\":\"doc-comment\",\"arguments\":[\" * Reads: `1`\"]},{\"name\":\"doc-comment\",\"arguments\":[\" * Write: `1`\"]},{\"name\":\"storage\",\"arguments\":[\"read\",\"write\"]}]},{\"inputs\":[],\"name\":\"proxy_owner\",\"output\":\"192bc7098e2fe60635a9918afb563e4e5419d386da2bdbf0d716b4bc8549802c\",\"attributes\":[{\"name\":\"doc-comment\",\"arguments\":[\" Returns the owner of the proxy contract.\"]},{\"name\":\"doc-comment\",\"arguments\":[\"\"]},{\"name\":\"doc-comment\",\"arguments\":[\" # Returns\"]},{\"name\":\"doc-comment\",\"arguments\":[\"\"]},{\"name\":\"doc-comment\",\"arguments\":[\" * [State] - Represents the state of ownership for this contract.\"]},{\"name\":\"doc-comment\",\"arguments\":[\"\"]},{\"name\":\"doc-comment\",\"arguments\":[\" # Number of Storage Accesses\"]},{\"name\":\"doc-comment\",\"arguments\":[\"\"]},{\"name\":\"doc-comment\",\"arguments\":[\" * Reads: `1`\"]},{\"name\":\"storage\",\"arguments\":[\"read\"]}]},{\"inputs\":[],\"name\":\"initialize_proxy\",\"output\":\"2e38e77b22c314a449e91fafed92a43826ac6aa403ae6a8acb6cf58239fbaf5d\",\"attributes\":[{\"name\":\"doc-comment\",\"arguments\":[\" Initializes the proxy contract.\"]},{\"name\":\"doc-comment\",\"arguments\":[\"\"]},{\"name\":\"doc-comment\",\"arguments\":[\" # Additional Information\"]},{\"name\":\"doc-comment\",\"arguments\":[\"\"]},{\"name\":\"doc-comment\",\"arguments\":[\" This method sets the storage values using the values of the configurable constants `INITIAL_TARGET` and `INITIAL_OWNER`.\"]},{\"name\":\"doc-comment\",\"arguments\":[\" This then allows methods that write to storage to be called.\"]},{\"name\":\"doc-comment\",\"arguments\":[\" This method can only be called once.\"]},{\"name\":\"doc-comment\",\"arguments\":[\"\"]},{\"name\":\"doc-comment\",\"arguments\":[\" # Reverts\"]},{\"name\":\"doc-comment\",\"arguments\":[\"\"]},{\"name\":\"doc-comment\",\"arguments\":[\" * When `storage::SRC14.proxy_owner` is not [State::Uninitialized].\"]},{\"name\":\"doc-comment\",\"arguments\":[\"\"]},{\"name\":\"doc-comment\",\"arguments\":[\" # Number of Storage Accesses\"]},{\"name\":\"doc-comment\",\"arguments\":[\"\"]},{\"name\":\"doc-comment\",\"arguments\":[\" * Writes: `2`\"]},{\"name\":\"storage\",\"arguments\":[\"write\"]}]},{\"inputs\":[{\"name\":\"new_proxy_owner\",\"concreteTypeId\":\"192bc7098e2fe60635a9918afb563e4e5419d386da2bdbf0d716b4bc8549802c\"}],\"name\":\"set_proxy_owner\",\"output\":\"2e38e77b22c314a449e91fafed92a43826ac6aa403ae6a8acb6cf58239fbaf5d\",\"attributes\":[{\"name\":\"doc-comment\",\"arguments\":[\" Changes proxy ownership to the passed State.\"]},{\"name\":\"doc-comment\",\"arguments\":[\"\"]},{\"name\":\"doc-comment\",\"arguments\":[\" # Additional Information\"]},{\"name\":\"doc-comment\",\"arguments\":[\"\"]},{\"name\":\"doc-comment\",\"arguments\":[\" This method can be used to transfer ownership between Identities or to revoke ownership.\"]},{\"name\":\"doc-comment\",\"arguments\":[\"\"]},{\"name\":\"doc-comment\",\"arguments\":[\" # Arguments\"]},{\"name\":\"doc-comment\",\"arguments\":[\"\"]},{\"name\":\"doc-comment\",\"arguments\":[\" * `new_proxy_owner`: [State] - The new state of the proxy ownership.\"]},{\"name\":\"doc-comment\",\"arguments\":[\"\"]},{\"name\":\"doc-comment\",\"arguments\":[\" # Reverts\"]},{\"name\":\"doc-comment\",\"arguments\":[\"\"]},{\"name\":\"doc-comment\",\"arguments\":[\" * When the sender is not the current proxy owner.\"]},{\"name\":\"doc-comment\",\"arguments\":[\" * When the new state of the proxy ownership is [State::Uninitialized].\"]},{\"name\":\"doc-comment\",\"arguments\":[\"\"]},{\"name\":\"doc-comment\",\"arguments\":[\" # Number of Storage Accesses\"]},{\"name\":\"doc-comment\",\"arguments\":[\"\"]},{\"name\":\"doc-comment\",\"arguments\":[\" * Reads: `1`\"]},{\"name\":\"doc-comment\",\"arguments\":[\" * Writes: `1`\"]},{\"name\":\"storage\",\"arguments\":[\"write\"]}]}],\"loggedTypes\":[{\"logId\":\"4571204900286667806\",\"concreteTypeId\":\"3f702ea3351c9c1ece2b84048006c8034a24cbc2bad2e740d0412b4172951d3d\"},{\"logId\":\"2151606668983994881\",\"concreteTypeId\":\"1ddc0adda1270a016c08ffd614f29f599b4725407c8954c8b960bdf651a9a6c8\"},{\"logId\":\"2161305517876418151\",\"concreteTypeId\":\"1dfe7feadc1d9667a4351761230f948744068a090fe91b1bc6763a90ed5d3893\"},{\"logId\":\"4354576968059844266\",\"concreteTypeId\":\"3c6e90ae504df6aad8b34a93ba77dc62623e00b777eecacfa034a8ac6e890c74\"},{\"logId\":\"10870989709723147660\",\"concreteTypeId\":\"96dd838b44f99d8ccae2a7948137ab6256c48ca4abc6168abc880de07fba7247\"},{\"logId\":\"10098701174489624218\",\"concreteTypeId\":\"8c25cb3686462e9a86d2883c5688a22fe738b0bbc85f458d2d2b5f3f667c6d5a\"}],\"messagesTypes\":[],\"configurables\":[{\"name\":\"INITIAL_TARGET\",\"concreteTypeId\":\"0d79387ad3bacdc3b7aad9da3a96f4ce60d9a1b6002df254069ad95a3931d5c8\",\"offset\":13368},{\"name\":\"INITIAL_OWNER\",\"concreteTypeId\":\"192bc7098e2fe60635a9918afb563e4e5419d386da2bdbf0d716b4bc8549802c\",\"offset\":13320}]}",)); + + let wallet = WalletUnlocked::new_from_private_key(attacker_secret_key, Some(provider.clone())); + let attacker_account = ForcClientAccount::Wallet(wallet); + // Try to change target of the proxy with a random wallet which is not the owner of the proxy. + let res = update_proxy_contract_target(&attacker_account, proxy_id, dummy_contract_id_target) + .await + .err() + .unwrap(); + + node.kill().unwrap(); + assert!(res + .to_string() + .starts_with("transaction reverted: NotOwner")); +} + +// TODO: https://github.com/FuelLabs/sway/issues/6283 +// Add interactive tests for the happy path cases. This requires starting the node with funded accounts and setting up +// the wallet with the correct password. The tests should be run in a separate test suite that is not run by default. +// It would also require overriding `default_wallet_path` function for tests, so as not to interfere with the user's wallet. + +#[test] +fn test_deploy_interactive_wrong_password() -> Result<(), rexpect::error::Error> { + let (mut node, port) = run_node(); + let node_url = format!("http://127.0.0.1:{}/v1/graphql", port); + + // Spawn the forc-deploy binary using cargo run + let project_dir = test_data_path().join("standalone_contract"); + let mut process = spawn( + &format!( + "cargo run --bin forc-deploy -- --node-url {node_url} -p {}", + project_dir.display() + ), + Some(300000), + )?; + + // Confirmation prompts + process + .exp_string("\u{1b}[1;32mConfirming\u{1b}[0m transactions [deploy standalone_contract]")?; + process.exp_string(&format!("Network: {node_url}"))?; + process.exp_string("Wallet: ")?; + process.exp_string("Wallet password")?; + process.send_line("mock_password")?; + + process.process.exit()?; + node.kill().unwrap(); + Ok(()) +} + +#[tokio::test] +async fn chunked_deploy() { + let (mut node, port) = run_node(); + let tmp_dir = tempdir().unwrap(); + let project_dir = test_data_path().join("big_contract"); + copy_dir(&project_dir, tmp_dir.path()).unwrap(); + patch_manifest_file_with_path_std(tmp_dir.path()).unwrap(); + + let pkg = Pkg { + path: Some(tmp_dir.path().display().to_string()), + ..Default::default() + }; + + let node_url = format!("http://127.0.0.1:{}/v1/graphql", port); + let target = NodeTarget { + node_url: Some(node_url), + target: None, + testnet: false, + mainnet: false, + }; + let cmd = cmd::Deploy { + pkg, + salt: Some(vec![format!("{}", Salt::default())]), + node: target, + default_signer: true, + ..Default::default() + }; + let deployed_contract = expect_deployed_contract(deploy(cmd).await.unwrap().remove(0)); + node.kill().unwrap(); + + assert!(deployed_contract.chunked); +} + +#[tokio::test] +async fn chunked_deploy_re_routes_calls() { + let (mut node, port) = run_node(); + let tmp_dir = tempdir().unwrap(); + let project_dir = test_data_path().join("big_contract"); + copy_dir(&project_dir, tmp_dir.path()).unwrap(); + patch_manifest_file_with_path_std(tmp_dir.path()).unwrap(); + + let pkg = Pkg { + path: Some(tmp_dir.path().display().to_string()), + ..Default::default() + }; + + let node_url = format!("http://127.0.0.1:{}/v1/graphql", port); + let target = NodeTarget { + node_url: Some(node_url.clone()), + target: None, + testnet: false, + mainnet: false, + }; + let cmd = cmd::Deploy { + pkg, + salt: Some(vec![format!("{}", Salt::default())]), + node: target, + default_signer: true, + ..Default::default() + }; + let deployed_contract = expect_deployed_contract(deploy(cmd).await.unwrap().remove(0)); + + let provider = Provider::connect(&node_url).await.unwrap(); + let secret_key = SecretKey::from_str(forc_client::constants::DEFAULT_PRIVATE_KEY).unwrap(); + let wallet_unlocked = WalletUnlocked::new_from_private_key(secret_key, Some(provider)); + + assert_big_contract_calls(wallet_unlocked, deployed_contract.id).await; + + node.kill().unwrap(); +} + +#[tokio::test] +async fn chunked_deploy_with_proxy_re_routes_call() { + let (mut node, port) = run_node(); + let tmp_dir = tempdir().unwrap(); + let project_dir = test_data_path().join("big_contract"); + copy_dir(&project_dir, tmp_dir.path()).unwrap(); + patch_manifest_file_with_path_std(tmp_dir.path()).unwrap(); + let proxy = Proxy { + enabled: true, + address: None, + }; + patch_manifest_file_with_proxy_table(tmp_dir.path(), proxy).unwrap(); + + let pkg = Pkg { + path: Some(tmp_dir.path().display().to_string()), + ..Default::default() + }; + + let node_url = format!("http://127.0.0.1:{}/v1/graphql", port); + let target = NodeTarget { + node_url: Some(node_url.clone()), + target: None, + testnet: false, + mainnet: false, + }; + let cmd = cmd::Deploy { + pkg, + salt: Some(vec![format!("{}", Salt::default())]), + node: target, + default_signer: true, + ..Default::default() + }; + let deployed_contract = expect_deployed_contract(deploy(cmd).await.unwrap().remove(0)); + + let provider = Provider::connect(&node_url).await.unwrap(); + let secret_key = SecretKey::from_str(forc_client::constants::DEFAULT_PRIVATE_KEY).unwrap(); + let wallet_unlocked = WalletUnlocked::new_from_private_key(secret_key, Some(provider)); + + assert_big_contract_calls(wallet_unlocked, deployed_contract.id).await; + + node.kill().unwrap(); +} + +#[tokio::test] +async fn can_deploy_script() { + let (mut node, port) = run_node(); + let tmp_dir = tempdir().unwrap(); + let project_dir = test_data_path().join("deployed_script"); + copy_dir(&project_dir, tmp_dir.path()).unwrap(); + patch_manifest_file_with_path_std(tmp_dir.path()).unwrap(); + + let node_url = format!("http://127.0.0.1:{}/v1/graphql", port); + let target = NodeTarget { + node_url: Some(node_url.clone()), + target: None, + testnet: false, + mainnet: false, + }; + let pkg = Pkg { + path: Some(tmp_dir.path().display().to_string()), + ..Default::default() + }; + let cmd = cmd::Deploy { + pkg, + salt: Some(vec![format!("{}", Salt::default())]), + node: target, + default_signer: true, + ..Default::default() + }; + + expect_deployed_script(deploy(cmd).await.unwrap().remove(0)); + node.kill().unwrap(); +} + +#[tokio::test] +async fn deploy_script_calls() { + let (mut node, port) = run_node(); + let tmp_dir = tempdir().unwrap(); + let project_dir = test_data_path().join("deployed_script"); + copy_dir(&project_dir, tmp_dir.path()).unwrap(); + patch_manifest_file_with_path_std(tmp_dir.path()).unwrap(); + + let node_url = format!("http://127.0.0.1:{}/v1/graphql", port); + let target = NodeTarget { + node_url: Some(node_url.clone()), + target: None, + testnet: false, + mainnet: false, + }; + let pkg = Pkg { + path: Some(tmp_dir.path().display().to_string()), + ..Default::default() + }; + let cmd = cmd::Deploy { + pkg, + salt: Some(vec![format!("{}", Salt::default())]), + node: target, + default_signer: true, + ..Default::default() + }; + + expect_deployed_script(deploy(cmd).await.unwrap().remove(0)); + + // Deploy the contract the script is going to be calling. + let contract_tmp_dir = tempdir().unwrap(); + let project_dir = test_data_path().join("standalone_contract"); + copy_dir(&project_dir, contract_tmp_dir.path()).unwrap(); + patch_manifest_file_with_path_std(contract_tmp_dir.path()).unwrap(); + + let pkg = Pkg { + path: Some(contract_tmp_dir.path().display().to_string()), + ..Default::default() + }; + + let node_url = format!("http://127.0.0.1:{}/v1/graphql", port); + let target = NodeTarget { + node_url: Some(node_url.clone()), + target: None, + testnet: false, + mainnet: false, + }; + let cmd = cmd::Deploy { + pkg, + salt: Some(vec![format!("{}", Salt::default())]), + node: target, + default_signer: true, + ..Default::default() + }; + let deployed_packages = deploy(cmd).await.unwrap().remove(0); + let contract = expect_deployed_contract(deployed_packages); + let contract_id = contract.id; + + abigen!(Script( + name = "MyScript", + abi = "forc-plugins/forc-client/test/data/deployed_script/deployed_script-abi.json" + )); + + let provider = Provider::connect(&node_url).await.unwrap(); + let secret_key = SecretKey::from_str(forc_client::constants::DEFAULT_PRIVATE_KEY).unwrap(); + let wallet_unlocked = WalletUnlocked::new_from_private_key(secret_key, Some(provider)); + + let loader_path = tmp_dir.path().join("out/deployed_script-loader.bin"); + let instance = MyScript::new(wallet_unlocked, &loader_path.display().to_string()); + + let contract_id_bits256 = Bits256(contract.id.into()); + let call_handler = instance + .main(10, contract_id_bits256) + .with_contract_ids(&[contract_id.into()]) + .call() + .await + .unwrap(); + let (configs, with_input, without_input, from_contract) = call_handler.value; + let receipts = call_handler.receipts; + + assert!(configs.0); // bool + assert_eq!(configs.1, 8); // u8 + assert_eq!(configs.2, 16); // u16 + assert_eq!(configs.3, 32); // u32 + assert_eq!(configs.4, 63); // u64 + assert_eq!(configs.5, 8.into()); // u256 + assert_eq!( + configs.6, + Bits256::from_hex_str("0x0101010101010101010101010101010101010101010101010101010101010101") + .unwrap() + ); // b256 + assert_eq!( + configs.7, + SizedAsciiString::new("fuel".to_string()).unwrap() + ); // str[4] + assert_eq!(configs.8, (8, true)); // tuple + assert_eq!(configs.9, [253, 254, 255]); // array + + let expected_struct = StructWithGeneric { + field_1: 8, + field_2: 16, + }; + assert_eq!(configs.10, expected_struct); // struct + + let expected_enum = EnumWithGeneric::VariantOne(true); + assert_eq!(configs.11, expected_enum); // enum + + assert!(with_input); // 10 % 2 == 0 + assert_eq!(without_input, 2500); // 25 * 100 = 2500 + + assert_eq!(from_contract, 5); + + receipts.iter().find(|receipt| { + if let fuel_tx::Receipt::LogData { data, .. } = receipt { + *data == Some(vec![0x08]) + } else { + false + } + }); + + node.kill().unwrap(); +} + +#[tokio::test] +async fn can_deploy_predicates() { + let (mut node, port) = run_node(); + let tmp_dir = tempdir().unwrap(); + let project_dir = test_data_path().join("deployed_predicate"); + copy_dir(&project_dir, tmp_dir.path()).unwrap(); + patch_manifest_file_with_path_std(tmp_dir.path()).unwrap(); + + let node_url = format!("http://127.0.0.1:{}/v1/graphql", port); + let target = NodeTarget { + node_url: Some(node_url.clone()), + target: None, + testnet: false, + mainnet: false, + }; + let pkg = Pkg { + path: Some(tmp_dir.path().display().to_string()), + ..Default::default() + }; + let cmd = cmd::Deploy { + pkg, + salt: Some(vec![format!("{}", Salt::default())]), + node: target, + default_signer: true, + ..Default::default() + }; + + expect_deployed_predicate(deploy(cmd).await.unwrap().remove(0)); + node.kill().unwrap(); +} + +#[tokio::test] +async fn deployed_predicate_call() { + let (mut node, port) = run_node(); + let tmp_dir = tempdir().unwrap(); + let project_dir = test_data_path().join("deployed_predicate"); + copy_dir(&project_dir, tmp_dir.path()).unwrap(); + patch_manifest_file_with_path_std(tmp_dir.path()).unwrap(); + + let node_url = format!("http://127.0.0.1:{}/v1/graphql", port); + let target = NodeTarget { + node_url: Some(node_url.clone()), + target: None, + testnet: false, + mainnet: false, + }; + let pkg = Pkg { + path: Some(tmp_dir.path().display().to_string()), + ..Default::default() + }; + let cmd = cmd::Deploy { + pkg, + salt: Some(vec![format!("{}", Salt::default())]), + node: target, + default_signer: true, + ..Default::default() + }; + expect_deployed_predicate(deploy(cmd).await.unwrap().remove(0)); + + abigen!(Predicate( + name = "MyPredicate", + abi = "forc-plugins/forc-client/test/data/deployed_predicate/deployed_predicate-abi.json" + )); + + let provider = Provider::connect(&node_url).await.unwrap(); + let base_asset_id = *provider.base_asset_id(); + let secret_key = SecretKey::from_str(forc_client::constants::DEFAULT_PRIVATE_KEY).unwrap(); + let wallet_unlocked = WalletUnlocked::new_from_private_key(secret_key, Some(provider.clone())); + let loader_path = tmp_dir.path().join("out/deployed_predicate-loader.bin"); + let strct = StructWithGeneric { + field_1: 8, + field_2: 16, + }; + let enm = EnumWithGeneric::VariantOne(true); + let encoded_data = MyPredicateEncoder::default() + .encode_data(true, 8, strct, enm) + .unwrap(); + let predicate: fuels::prelude::Predicate = + fuels::prelude::Predicate::load_from(&loader_path.display().to_string()) + .unwrap() + .with_data(encoded_data) + .with_provider(provider); + + // lock some amount under the predicate + wallet_unlocked + .transfer( + predicate.address(), + 500, + base_asset_id, + TxPolicies::default(), + ) + .await + .unwrap(); + + // Check predicate balance. + let balance = predicate.get_asset_balance(&base_asset_id).await.unwrap(); + assert_eq!(balance, 500); + + // Try to spend it + let amount_to_unlock = 300; + predicate + .transfer( + wallet_unlocked.address(), + amount_to_unlock, + base_asset_id, + TxPolicies::default(), + ) + .await + .unwrap(); + + // Check predicate balance again. + let balance = predicate.get_asset_balance(&base_asset_id).await.unwrap(); + assert_eq!(balance, 200); + + node.kill().unwrap(); +} + +/// Generates a script instance using SDK, and returns the result as a string. +async fn call_with_sdk_generated_overrides(node_url: &str, contract_id: ContractId) -> String { + let project_dir = test_data_path().join("deployed_script"); + abigen!(Script( + name = "MyScript", + abi = "forc-plugins/forc-client/test/data/deployed_script/deployed_script-abi.json" + )); + let provider = Provider::connect(&node_url).await.unwrap(); + let secret_key = SecretKey::from_str(forc_client::constants::DEFAULT_PRIVATE_KEY).unwrap(); + let wallet_unlocked = WalletUnlocked::new_from_private_key(secret_key, Some(provider.clone())); + let bin_dir = project_dir.join("deployed_script.bin"); + let script_instance = MyScript::new(wallet_unlocked, bin_dir.display().to_string().as_str()); + + let strc = StructWithGeneric { + field_1: 1u8, + field_2: 2, + }; + let encoded = MyScriptConfigurables::default() + .with_BOOL(false) + .unwrap() + .with_U8(1) + .unwrap() + .with_U16(2) + .unwrap() + .with_U32(3) + .unwrap() + .with_U64(4) + .unwrap() + .with_U256(5.into()) + .unwrap() + .with_B256(Bits256::zeroed()) + .unwrap() + .with_ARRAY([1, 2, 3]) + .unwrap() + .with_STRUCT(strc) + .unwrap() + .with_ENUM(EnumWithGeneric::VariantTwo) + .unwrap(); + + let mut script_instance_with_configs = script_instance.with_configurables(encoded); + + let loader_from_sdk = script_instance_with_configs + .convert_into_loader() + .await + .unwrap(); + + let contract_ids_bits256 = Bits256(contract_id.into()); + format!( + "{:?}", + loader_from_sdk + .main(10, contract_ids_bits256) + .with_contract_ids(&[contract_id.into()]) + .call() + .await + .unwrap() + .value + ) +} + +/// Generates a script instance using the shifted abi, and returns the result as a string. +async fn call_with_forc_generated_overrides(node_url: &str, contract_id: ContractId) -> String { + let provider = Provider::connect(&node_url).await.unwrap(); + let secret_key = SecretKey::from_str(forc_client::constants::DEFAULT_PRIVATE_KEY).unwrap(); + let wallet_unlocked = WalletUnlocked::new_from_private_key(secret_key, Some(provider.clone())); + let tmp_dir = tempdir().unwrap(); + let project_dir = test_data_path().join("deployed_script"); + copy_dir(&project_dir, tmp_dir.path()).unwrap(); + patch_manifest_file_with_path_std(tmp_dir.path()).unwrap(); + + let target = NodeTarget { + node_url: Some(node_url.to_string()), + target: None, + testnet: false, + mainnet: false, + }; + let pkg = Pkg { + path: Some(tmp_dir.path().display().to_string()), + ..Default::default() + }; + let cmd = cmd::Deploy { + pkg, + salt: Some(vec![format!("{}", Salt::default())]), + node: target, + default_signer: true, + ..Default::default() + }; + + expect_deployed_script(deploy(cmd).await.unwrap().remove(0)); + + // Since `abigen!` macro does not allow for dynamic paths, we need to + // pre-generate the loader bin and abi and read them from project dir. Here + // we are ensuring forc-deploy indeed generated the files we are basing our + // tests below. + let generated_loader_abi_path = tmp_dir.path().join("out/deployed_script-loader-abi.json"); + let generated_loader_abi = fs::read_to_string(generated_loader_abi_path).unwrap(); + + // this path is basically, `forc-plugins/forc-client/test/data/deployed_script/deployed_script-loader-abi.json`. + let used_loader_abi_path = project_dir.join("deployed_script-loader-abi.json"); + let used_loader_abi = fs::read_to_string(used_loader_abi_path).unwrap(); + + assert_eq!(generated_loader_abi, used_loader_abi); + + let generated_loader_bin = tmp_dir.path().join("out/deployed_script-loader.bin"); + abigen!(Script( + name = "MyScript", + abi = "forc-plugins/forc-client/test/data/deployed_script/deployed_script-loader-abi.json" + )); + let forc_generated_script_instance = MyScript::new( + wallet_unlocked, + generated_loader_bin.display().to_string().as_str(), + ); + let strc = StructWithGeneric { + field_1: 1u8, + field_2: 2, + }; + let encoded = MyScriptConfigurables::default() + .with_BOOL(false) + .unwrap() + .with_U8(1) + .unwrap() + .with_U16(2) + .unwrap() + .with_U32(3) + .unwrap() + .with_U64(4) + .unwrap() + .with_U256(5.into()) + .unwrap() + .with_B256(Bits256::zeroed()) + .unwrap() + .with_ARRAY([1, 2, 3]) + .unwrap() + .with_STRUCT(strc) + .unwrap() + .with_ENUM(EnumWithGeneric::VariantTwo) + .unwrap(); + + let forc_generated_script_with_configs = + forc_generated_script_instance.with_configurables(encoded); + let contract_ids_bits256 = Bits256(contract_id.into()); + format!( + "{:?}", + forc_generated_script_with_configs + .main(10, contract_ids_bits256) + .with_contract_ids(&[contract_id.into()]) + .call() + .await + .unwrap() + .value + ) +} + +#[tokio::test] +async fn offset_shifted_abi_works() { + // To test if offset shifted abi works or not, we generate a loader + // contract using sdk and give a configurable override, and call the + // main function. + + // We also create the shited abi using forc-deploy and create a script + // instance using this new shifted abi, and generate a normal script out of + // the loader binary generated again by forc-deploy. + + // We then override the configurables with the same values as sdk flow on + // this script, generated with loader abi and bin coming from forc-deploy. + + // If returned value is equal, than the configurables work correctly. + let (mut node, port) = run_node(); + // Deploy the contract the script is going to be calling. + let contract_tmp_dir = tempdir().unwrap(); + let project_dir = test_data_path().join("standalone_contract"); + copy_dir(&project_dir, contract_tmp_dir.path()).unwrap(); + patch_manifest_file_with_path_std(contract_tmp_dir.path()).unwrap(); + + let pkg = Pkg { + path: Some(contract_tmp_dir.path().display().to_string()), + ..Default::default() + }; + + let node_url = format!("http://127.0.0.1:{}/v1/graphql", port); + let target = NodeTarget { + node_url: Some(node_url.clone()), + target: None, + testnet: false, + mainnet: false, + }; + let cmd = cmd::Deploy { + pkg, + salt: Some(vec![format!("{}", Salt::default())]), + node: target, + default_signer: true, + ..Default::default() + }; + let deployed_packages = deploy(cmd).await.unwrap().remove(0); + let contract = expect_deployed_contract(deployed_packages); + let contract_id = contract.id; + // Generating the sdk loader bytecode with configurables. + let loader_with_configs_from_sdk = + call_with_sdk_generated_overrides(&node_url, contract_id).await; + + // Genearating the forc-deploy loader bytecode and loader abi. + let loader_with_configs_from_forc = + call_with_forc_generated_overrides(&node_url, contract_id).await; + pretty_assertions::assert_eq!(loader_with_configs_from_forc, loader_with_configs_from_sdk); + + node.kill().unwrap() +} diff --git a/forc-plugins/forc-crypto/Cargo.toml b/forc-plugins/forc-crypto/Cargo.toml index ca598c5d7e2..bea4711b7d5 100644 --- a/forc-plugins/forc-crypto/Cargo.toml +++ b/forc-plugins/forc-crypto/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "forc-crypto" -version = "0.60.0" +version.workspace = true description = "A `forc` plugin for handling various cryptographic operations and conversions." authors.workspace = true edition.workspace = true @@ -9,23 +9,34 @@ license.workspace = true repository.workspace = true [dependencies] -anyhow = "1.0.75" -async-trait = "0.1.58" -atty = "0.2.14" -clap = { version = "4.5.4", features = ["derive", "env"] } -forc-tracing = { version = "0.60.0", path = "../../forc-tracing" } -forc-util = { version = "0.60.0", path = "../../forc-util" } -fuel-core-types = { workspace = true } +anyhow.workspace = true +async-trait.workspace = true +atty.workspace = true +clap = { workspace = true, features = ["derive", "env"] } +forc-tracing.workspace = true +forc-util.workspace = true +fuel-core-types.workspace = true fuel-crypto = { workspace = true, features = ["random"] } -fuels-core = { workspace = true } -futures = "0.3" -hex = "0.4.3" -libp2p-identity = { version = "0.2.4", features = ["secp256k1", "peerid"] } -rand = "0.8" -serde = "1.0" -serde_json = "1" -serde_yaml = "0.9.27" -sha3 = "0.10.8" -termion = "2.0.1" -tokio = { version = "1.8", features = ["macros", "rt-multi-thread", "process"] } -tracing = "0.1" +fuels-accounts.workspace = true +fuels-core.workspace = true +futures.workspace = true +hex.workspace = true +libp2p-identity = { workspace = true, features = ["peerid", "secp256k1"] } +rand.workspace = true +rayon.workspace = true +regex.workspace = true +serde.workspace = true +serde_json.workspace = true +serde_yaml.workspace = true +sha3.workspace = true +termion.workspace = true +tokio = { workspace = true, features = ["macros", "rt-multi-thread", "process"] } +tracing.workspace = true + +[dev-dependencies] +criterion = "0.5" +tempfile.workspace = true + +[[bench]] +name = "bench_main" +harness = false diff --git a/forc-plugins/forc-crypto/benches/bench_main.rs b/forc-plugins/forc-crypto/benches/bench_main.rs new file mode 100644 index 00000000000..675923911cb --- /dev/null +++ b/forc-plugins/forc-crypto/benches/bench_main.rs @@ -0,0 +1,73 @@ +use criterion::{black_box, criterion_group, criterion_main, Criterion}; +use forc_crypto::keys::vanity::{find_vanity_address_with_timeout, HexMatcher, RegexMatcher}; +use rayon::iter::Either; + +fn benchmark_vanity_address(c: &mut Criterion) { + let mut group = c.benchmark_group("Vanity Address Generation"); + + // Benchmark HexMatcher with prefix + group.bench_function("HexMatcher (starts with 'a')", |b| { + b.iter(|| { + let matcher = Either::Right(HexMatcher::new("a", "").unwrap()); + find_vanity_address_with_timeout(black_box(matcher), false, None) + }) + }); + + // Benchmark HexMatcher with suffix + group.bench_function("HexMatcher (ends with 'f')", |b| { + b.iter(|| { + let matcher = Either::Right(HexMatcher::new("", "f").unwrap()); + find_vanity_address_with_timeout(black_box(matcher), false, None) + }) + }); + + // Benchmark HexMatcher with both prefix and suffix + group.bench_function("HexMatcher (starts with 'a' ends with 'f')", |b| { + b.iter(|| { + let matcher = Either::Right(HexMatcher::new("a", "f").unwrap()); + find_vanity_address_with_timeout(black_box(matcher), false, None) + }) + }); + + // Benchmark RegexMatcher with simple pattern + group.bench_function("RegexMatcher (starts with 'a')", |b| { + b.iter(|| { + let matcher = Either::Left(RegexMatcher::new("^a.*").unwrap()); + find_vanity_address_with_timeout(black_box(matcher), false, None) + }) + }); + + // Benchmark RegexMatcher with complex pattern + group.bench_function("RegexMatcher (contains two consecutive digits)", |b| { + b.iter(|| { + let matcher = Either::Left(RegexMatcher::new(r"[0-9]{2}").unwrap()); + find_vanity_address_with_timeout(black_box(matcher), false, None) + }) + }); + + // Benchmark with mnemonic generation + group.bench_function("HexMatcher with Mnemonic (starts with 'a')", |b| { + b.iter(|| { + let matcher = Either::Right(HexMatcher::new("a", "").unwrap()); + find_vanity_address_with_timeout(black_box(matcher), true, None) + }) + }); + + group.bench_function("RegexMatcher with Mnemonic (starts with 'a')", |b| { + b.iter(|| { + let matcher = Either::Left(RegexMatcher::new("^a.*").unwrap()); + find_vanity_address_with_timeout(black_box(matcher), true, None) + }) + }); + + group.finish(); +} + +criterion_group! { + name = benches; + config = Criterion::default() + .sample_size(10) // Reduced sample size due to potentially long-running benchmarks + .measurement_time(std::time::Duration::from_secs(20)); + targets = benchmark_vanity_address +} +criterion_main!(benches); diff --git a/forc-plugins/forc-crypto/src/args.rs b/forc-plugins/forc-crypto/src/args.rs index 8e4bcee25fd..4201894632c 100644 --- a/forc-plugins/forc-crypto/src/args.rs +++ b/forc-plugins/forc-crypto/src/args.rs @@ -24,17 +24,17 @@ forc_util::cli_examples! { pub struct HashArgs { /// This argument is optional, it can be either: /// - /// 1. A path to a file. If that is the case, the content of the file is - /// loaded. + /// 1. A path to a file. If that is the case, the content of the file is + /// loaded /// - /// 2. A binary string encoded as a hex string. If that is the case, the - /// hex is decoded and passed as a Vec + /// 2. A binary string encoded as a hex string. If that is the case, the + /// hex is decoded and passed as a Vec /// - /// 3. A string. This is the last option, if the string is "-", `stdin` - /// is read instead. Otherwise the raw string is converted to a Vec - /// and passed + /// 3. A string. This is the last option, if the string is "-", "stdin" + /// is read instead. Otherwise the raw string is converted to a Vec + /// and passed /// - /// 4. If it nos not provided, `stdin` is read + /// 4. If it is not provided, "stdin" is read content_or_filepath: Option, } diff --git a/forc-plugins/forc-crypto/src/keys/mod.rs b/forc-plugins/forc-crypto/src/keys/mod.rs index 9741e32623c..8935b5f366e 100644 --- a/forc-plugins/forc-crypto/src/keys/mod.rs +++ b/forc-plugins/forc-crypto/src/keys/mod.rs @@ -3,6 +3,7 @@ use clap::ValueEnum; pub mod get_public_key; pub mod new_key; pub mod parse_secret; +pub mod vanity; #[derive(Clone, Debug, Default, ValueEnum)] pub enum KeyType { diff --git a/forc-plugins/forc-crypto/src/keys/vanity.rs b/forc-plugins/forc-crypto/src/keys/vanity.rs new file mode 100644 index 00000000000..640165dc818 --- /dev/null +++ b/forc-plugins/forc-crypto/src/keys/vanity.rs @@ -0,0 +1,457 @@ +use fuel_crypto::{fuel_types::Address, PublicKey, SecretKey}; +use fuels_accounts::wallet::{generate_mnemonic_phrase, DEFAULT_DERIVATION_PATH_PREFIX}; +use fuels_core::types::{ + bech32::{Bech32Address, FUEL_BECH32_HRP}, + checksum_address::checksum_encode, +}; +use rayon::iter::{self, Either, ParallelIterator}; +use regex::Regex; +use serde_json::json; +use std::{ + path::PathBuf, + time::{Duration, Instant}, +}; +use tokio::runtime::Runtime; + +forc_util::cli_examples! { + crate::Command { + [ Generate a checksummed vanity address with a given prefix => "forc crypto vanity --starts-with \"aaa\"" ] + [ Generate a checksummed vanity address with a given suffix => "forc crypto vanity --ends-with \"aaa\"" ] + [ Generate a checksummed vanity address with a given prefix and suffix => "forc crypto vanity --starts-with \"00\" --ends-with \"ff\"" ] + [ Generate a checksummed vanity address with a given regex pattern => "forc crypto vanity --regex \"^00.*ff$\"" ] + } +} + +fn validate_hex_string(s: &str) -> Result { + if !s.chars().all(|c| c.is_ascii_hexdigit()) { + return Err("Pattern must contain only hex characters (0-9, a-f)".to_string()); + } + Ok(s.to_string()) +} + +fn validate_regex_pattern(s: &str) -> Result { + if s.len() > 128 { + return Err("Regex pattern too long: max 128 characters".to_string()); + } + + if let Err(e) = Regex::new(&format!("(?i){}", s)) { + return Err(format!("Invalid regex pattern: {}", e)); + } + + Ok(s.to_string()) +} + +#[derive(Debug, clap::Parser)] +#[clap( + version, + about = "Generate a vanity address", + after_help = "Generate vanity addresses for the Fuel blockchain" +)] +pub struct Arg { + /// Desired hex string prefix for the address + #[arg( + long, + value_name = "HEX_STRING", + required_unless_present = "ends_with", + required_unless_present = "regex", + conflicts_with = "regex", + value_parser = validate_hex_string, + )] + pub starts_with: Option, + + /// Desired hex string suffix for the address + #[arg(long, value_name = "HEX_STRING", conflicts_with = "regex", value_parser = validate_hex_string)] + pub ends_with: Option, + + /// Desired regex pattern to match the entire address (case-insensitive) + #[arg(long, value_name = "PATTERN", conflicts_with = "starts_with", value_parser = validate_regex_pattern)] + pub regex: Option, + + /// Timeout in seconds for address generation + #[arg(long, value_name = "SECONDS")] + pub timeout: Option, + + /// Return mnemonic with address (default false) + #[arg(long)] + pub mnemonic: bool, + + /// Path to save the generated vanity address to. + #[arg(long, value_hint = clap::ValueHint::FilePath, value_name = "PATH")] + pub save_path: Option, +} + +impl Arg { + pub fn validate(&self) -> anyhow::Result<()> { + let total_length = self.starts_with.as_ref().map_or(0, |s| s.len()) + + self.ends_with.as_ref().map_or(0, |s| s.len()); + if total_length > 64 { + return Err(anyhow::anyhow!( + "Combined pattern length exceeds 64 characters" + )); + } + Ok(()) + } +} + +pub fn handler(args: Arg) -> anyhow::Result { + args.validate()?; + + let Arg { + starts_with, + ends_with, + regex, + mnemonic, + timeout, + save_path, + } = args; + + let matcher = if let Some(pattern) = regex { + Either::Left(RegexMatcher::new(&pattern)?) + } else { + let starts_with = starts_with.as_deref().unwrap_or(""); + let ends_with = ends_with.as_deref().unwrap_or(""); + Either::Right(HexMatcher::new(starts_with, ends_with)?) + }; + + println!("Starting to generate vanity address..."); + let start_time = Instant::now(); + + let result = find_vanity_address_with_timeout(matcher, mnemonic, timeout)?; + let (address, secret_key, mnemonic) = result; + + let duration = start_time.elapsed(); + println!( + "Successfully found vanity address in {:.3} seconds.\n", + duration.as_secs_f64() + ); + + let checksum_address = checksum_encode(&address.to_string())?; + let result = if let Some(mnemonic) = mnemonic { + json!({ + "Address": checksum_address, + "PrivateKey": hex::encode(secret_key.as_ref()), + "Mnemonic": mnemonic, + }) + } else { + json!({ + "Address": checksum_address, + "PrivateKey": hex::encode(secret_key.as_ref()), + }) + }; + + if let Some(path) = save_path { + std::fs::write(path, serde_json::to_string_pretty(&result)?)?; + } + + Ok(result) +} + +pub trait VanityMatcher: Send + Sync + 'static { + fn is_match(&self, addr: &Address) -> bool; +} + +pub struct HexMatcher { + prefix: String, + suffix: String, +} + +impl HexMatcher { + pub fn new(prefix: &str, suffix: &str) -> anyhow::Result { + Ok(Self { + prefix: prefix.to_lowercase(), + suffix: suffix.to_lowercase(), + }) + } +} + +impl VanityMatcher for HexMatcher { + fn is_match(&self, addr: &Address) -> bool { + let hex_addr = hex::encode(addr.as_ref()).to_lowercase(); + hex_addr.starts_with(&self.prefix) && hex_addr.ends_with(&self.suffix) + } +} + +pub struct RegexMatcher { + re: Regex, +} + +impl RegexMatcher { + pub fn new(pattern: &str) -> anyhow::Result { + let re = Regex::new(&format!("(?i){}", pattern))?; + Ok(Self { re }) + } +} + +impl VanityMatcher for RegexMatcher { + fn is_match(&self, addr: &Address) -> bool { + let addr = hex::encode(addr.as_ref()); + self.re.is_match(&addr) + } +} + +use std::sync::atomic::{AtomicBool, Ordering}; +use std::sync::Arc; + +pub fn find_vanity_address_with_timeout( + matcher: Either, + use_mnemonic: bool, + timeout_secs: Option, +) -> anyhow::Result<(Address, SecretKey, Option)> { + let should_stop = Arc::new(AtomicBool::new(false)); + let should_stop_clone = should_stop.clone(); + + let generate_wallet = move || { + let breakpoint = if use_mnemonic { 1_000 } else { 100_000 }; + let start = Instant::now(); + let attempts = std::sync::atomic::AtomicUsize::new(0); + + wallet_generator(use_mnemonic) + .find_any(|result| { + // Check if we should stop due to timeout + if should_stop.load(Ordering::Relaxed) { + return true; // This will cause find_any to return the current result + } + + let current = attempts.fetch_add(1, std::sync::atomic::Ordering::Relaxed); + if current != 0 && current % breakpoint == 0 { + let elapsed = start.elapsed().as_secs_f64(); + let rate = current as f64 / elapsed; + println!( + "ā””ā”€ tried {} addresses ({:.2} addresses/sec)...", + current, rate + ); + } + + if let Ok((addr, _, _)) = result { + match &matcher { + Either::Left(regex_matcher) => regex_matcher.is_match(addr), + Either::Right(hex_matcher) => hex_matcher.is_match(addr), + } + } else { + false + } + }) + .ok_or_else(|| anyhow::anyhow!("No matching address found"))? + }; + + let Some(secs) = timeout_secs else { + return generate_wallet(); + }; + + Runtime::new()?.block_on(async { + let generation_task = tokio::task::spawn_blocking(generate_wallet); + + tokio::select! { + result = generation_task => { + match result { + Ok(wallet_result) => wallet_result, + Err(_) => Err(anyhow::anyhow!("No matching address found")), + } + } + _ = tokio::time::sleep(Duration::from_secs(secs)) => { + // Signal all threads to stop + should_stop_clone.store(true, Ordering::Relaxed); + // Wait a short time for threads to notice the stop signal + tokio::time::sleep(Duration::from_millis(100)).await; + Err(anyhow::anyhow!("Vanity address generation timed out after {} seconds", secs)) + } + } + }) +} + +#[inline] +fn wallet_generator( + use_mnemonic: bool, +) -> impl ParallelIterator)>> { + iter::repeat(()).map(move |()| generate_wallet(use_mnemonic)) +} + +fn generate_wallet(use_mnemonic: bool) -> anyhow::Result<(Address, SecretKey, Option)> { + let mut rng = rand::thread_rng(); + + let (private_key, mnemonic) = if use_mnemonic { + let mnemonic = generate_mnemonic_phrase(&mut rng, 24)?; + let account_ix = 0; + let derivation_path = format!("{DEFAULT_DERIVATION_PATH_PREFIX}/{account_ix}'/0/0"); + let private_key = + SecretKey::new_from_mnemonic_phrase_with_path(&mnemonic, &derivation_path)?; + (private_key, Some(mnemonic)) + } else { + (SecretKey::random(&mut rng), None) + }; + + let public = PublicKey::from(&private_key); + let hashed = public.hash(); + let address = Bech32Address::new(FUEL_BECH32_HRP, hashed); + + Ok((address.into(), private_key, mnemonic)) +} + +#[cfg(test)] +mod tests { + use super::*; + use clap::Parser; + + // Helper function to parse args and get validation errors + fn parse_args(args: Vec<&str>) -> Result { + let args = + Arg::try_parse_from(std::iter::once("test").chain(args)).map_err(|e| e.to_string())?; + args.validate().map_err(|e| e.to_string())?; + Ok(args) + } + + #[test] + fn test_invalid_hex_characters() { + let result = parse_args(vec!["--starts-with", "xyz"]); + assert!(result.is_err()); + assert_eq!(result.unwrap_err(), "error: invalid value 'xyz' for '--starts-with ': Pattern must contain only hex characters (0-9, a-f)\n\nFor more information, try '--help'.\n"); + } + + #[test] + fn test_pattern_too_long() { + let result = parse_args(vec![ + "--starts-with", + &"a".repeat(32), + "--ends-with", + &"b".repeat(33), + ]); + assert!(result.is_err()); + assert_eq!( + result.unwrap_err(), + "Combined pattern length exceeds 64 characters" + ); + } + + #[test] + fn test_invalid_regex_syntax() { + let result = parse_args(vec!["--regex", "["]); + assert!(result.is_err()); + assert_eq!(result.unwrap_err(), "error: invalid value '[' for '--regex ': Invalid regex pattern: regex parse error:\n (?i)[\n ^\nerror: unclosed character class\n\nFor more information, try '--help'.\n"); + } + + #[test] + fn test_regex_too_long() { + let result = parse_args(vec!["--regex", &"a".repeat(129)]); + assert!(result.is_err()); + assert_eq!(result.unwrap_err(), "error: invalid value 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' for '--regex ': Regex pattern too long: max 128 characters\n\nFor more information, try '--help'.\n"); + } + + #[test] + fn test_conflicting_args() { + let result = parse_args(vec!["--starts-with", "aa", "--regex", "^aa"]); + assert!(result.is_err()); + assert_eq!(result.unwrap_err(), "error: the argument '--starts-with ' cannot be used with '--regex '\n\nUsage: test --starts-with \n\nFor more information, try '--help'.\n"); + } + + #[test] + fn test_timeout_respected() { + // This pattern should take a long time to generate + let args = parse_args(vec!["--starts-with", "fffffffffffff", "--timeout", "1"]).unwrap(); + + let result = handler(args); + assert!(result.is_err()); + assert_eq!( + result.unwrap_err().to_string(), + "Vanity address generation timed out after 1 seconds" + ); + } + + // Test actual functionality with minimal patterns + #[test] + fn test_valid_short_prefix() { + let args = parse_args(vec!["--starts-with", "a"]).unwrap(); + let result = handler(args).unwrap(); + let address = result["Address"].as_str().unwrap(); + assert!( + address.to_lowercase().starts_with("0xa"), + "Address should start with 'a'" + ); + } + + #[test] + fn test_valid_short_suffix() { + let args = parse_args(vec!["--ends-with", "a"]).unwrap(); + let result = handler(args).unwrap(); + let address = result["Address"].as_str().unwrap(); + assert!( + address.to_lowercase().ends_with('a'), + "Address should end with 'a'" + ); + } + + #[test] + fn test_both_prefix_and_suffix() { + let args = parse_args(vec!["--starts-with", "a", "--ends-with", "b"]).unwrap(); + let result = handler(args).unwrap(); + let address = result["Address"].as_str().unwrap().to_lowercase(); + assert!(address.starts_with("0xa"), "Address should start with 'a'"); + assert!(address.ends_with('b'), "Address should end with 'b'"); + } + + #[test] + fn test_simple_regex() { + let args = parse_args(vec!["--regex", "^a.*b$"]).unwrap(); + let result = handler(args).unwrap(); + let address = result["Address"].as_str().unwrap().to_lowercase(); + assert!(address.starts_with("0xa"), "Address should start with 'a'"); + assert!(address.ends_with('b'), "Address should end with 'b'"); + } + + #[test] + fn test_simple_regex_uppercase() { + let args = parse_args(vec!["--regex", "^A.*B$"]).unwrap(); + let result = handler(args).unwrap(); + let address = result["Address"].as_str().unwrap().to_lowercase(); + assert!(address.starts_with("0xa"), "Address should start with 'a'"); + assert!(address.ends_with('b'), "Address should end with 'b'"); + } + + #[test] + fn test_mnemonic_generation() { + let args = parse_args(vec!["--starts-with", "a", "--mnemonic"]).unwrap(); + let result = handler(args).unwrap(); + + assert!(result["Mnemonic"].is_string(), "Mnemonic should be present"); + assert_eq!( + result["Mnemonic"] + .as_str() + .unwrap() + .split_whitespace() + .count(), + 24, + "Mnemonic should have 24 words" + ); + + let address = result["Address"].as_str().unwrap(); + assert!( + address.to_lowercase().starts_with("0xa"), + "Address should start with 'a'" + ); + } + + #[test] + fn test_save_path() { + let tmp = tempfile::NamedTempFile::new().unwrap(); + let args = parse_args(vec![ + "--starts-with", + "a", + "--save-path", + tmp.path().to_str().unwrap(), + ]) + .unwrap(); + + handler(args).unwrap(); + + assert!(tmp.path().exists(), "File should exist"); + let content = std::fs::read_to_string(tmp.path()).unwrap(); + let saved_result: serde_json::Value = serde_json::from_str(&content).unwrap(); + assert!( + saved_result["Address"].is_string(), + "Saved result should contain an Address" + ); + assert!( + saved_result["PrivateKey"].is_string(), + "Saved result should contain a PrivateKey" + ); + } +} diff --git a/forc-plugins/forc-crypto/src/lib.rs b/forc-plugins/forc-crypto/src/lib.rs new file mode 100644 index 00000000000..7c89d848120 --- /dev/null +++ b/forc-plugins/forc-crypto/src/lib.rs @@ -0,0 +1,37 @@ +pub mod address; +pub mod args; +pub mod keccak256; +pub mod keys; +pub mod sha256; + +pub(crate) fn help() -> &'static str { + Box::leak( + format!( + "EXAMPLES:\n{}{}{}{}{}{}", + args::examples(), + address::examples(), + keys::new_key::examples(), + keys::parse_secret::examples(), + keys::get_public_key::examples(), + keys::vanity::examples(), + ) + .into_boxed_str(), + ) +} + +/// Forc plugin for hashing arbitrary data +#[derive(Debug, clap::Parser)] +#[clap( + name = "forc-crypto", + after_help = help(), + version +)] +pub enum Command { + Keccak256(args::HashArgs), + Sha256(args::HashArgs), + Address(address::Args), + GetPublicKey(keys::get_public_key::Arg), + NewKey(keys::new_key::Arg), + ParseSecret(keys::parse_secret::Arg), + Vanity(keys::vanity::Arg), +} diff --git a/forc-plugins/forc-crypto/src/main.rs b/forc-plugins/forc-crypto/src/main.rs index fba619b2b59..c9ae55b23f0 100644 --- a/forc-plugins/forc-crypto/src/main.rs +++ b/forc-plugins/forc-crypto/src/main.rs @@ -3,6 +3,7 @@ use anyhow::Result; use atty::Stream; use clap::Parser; +use forc_crypto::{address, keccak256, keys, sha256, Command}; use forc_tracing::{init_tracing_subscriber, println_error}; use std::{ default::Default, @@ -10,42 +11,6 @@ use std::{ }; use termion::screen::IntoAlternateScreen; -mod address; -mod args; -mod keccak256; -mod keys; -mod sha256; - -fn help() -> &'static str { - Box::leak( - format!( - "EXAMPLES:\n{}{}{}{}{}", - args::examples(), - address::examples(), - keys::new_key::examples(), - keys::parse_secret::examples(), - keys::get_public_key::examples(), - ) - .into_boxed_str(), - ) -} - -/// Forc plugin for hashing arbitrary data -#[derive(Debug, Parser)] -#[clap( - name = "forc-crypto", - after_help = help(), - version -)] -pub enum Command { - Keccak256(args::HashArgs), - Sha256(args::HashArgs), - Address(address::Args), - GetPublicKey(keys::get_public_key::Arg), - NewKey(keys::new_key::Arg), - ParseSecret(keys::parse_secret::Arg), -} - fn main() { init_tracing_subscriber(Default::default()); if let Err(err) = run() { @@ -59,6 +24,7 @@ fn run() -> Result<()> { let content = match app { Command::Keccak256(arg) => keccak256::hash(arg)?, Command::GetPublicKey(arg) => keys::get_public_key::handler(arg)?, + Command::Vanity(arg) => keys::vanity::handler(arg)?, Command::Sha256(arg) => sha256::hash(arg)?, Command::Address(arg) => address::dump_address(arg.address)?, Command::NewKey(arg) => keys::new_key::handler(arg)?, @@ -83,7 +49,7 @@ where } } -pub(crate) fn display_output(message: T) -> anyhow::Result<()> +pub fn display_output(message: T) -> anyhow::Result<()> where T: serde::Serialize, { diff --git a/forc-plugins/forc-debug/Cargo.toml b/forc-plugins/forc-debug/Cargo.toml index 604cb8134ba..4911d214c2e 100644 --- a/forc-plugins/forc-debug/Cargo.toml +++ b/forc-plugins/forc-debug/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "forc-debug" -version = "0.60.0" +version.workspace = true description = "Supports debugging Sway code via CLI and DAP server." authors.workspace = true edition.workspace = true @@ -9,25 +9,26 @@ license.workspace = true repository.workspace = true [dependencies] -anyhow = "1.0" # Used by the examples and for conversion only -clap = { version = "4.5.4", features = ["derive", "env"] } -dap = "0.4.1-alpha1" -forc-pkg = { version = "0.60.0", path = "../../forc-pkg" } -forc-test = { version = "0.60.0", path = "../../forc-test" } -fuel-core-client = { workspace = true } +anyhow.workspace = true +clap = { workspace = true, features = ["derive", "env"] } +dap.workspace = true +forc-pkg.workspace = true +forc-test.workspace = true +forc-tracing.workspace = true +fuel-core-client.workspace = true fuel-types = { workspace = true, features = ["serde"] } fuel-vm = { workspace = true, features = ["serde"] } -rayon = "1.7.0" -serde = "1.0" -serde_json = "1.0" -shellfish = { version = "0.6.0", features = ["rustyline", "async", "tokio"] } -sway-core = { version = "0.60.0", path = "../../sway-core" } -sway-types = { version = "0.60.0", path = "../../sway-types" } -thiserror = "1.0" -tokio = { version = "1.8", features = [ - "net", +rayon.workspace = true +serde.workspace = true +serde_json.workspace = true +shellfish = { workspace = true, features = ["async", "rustyline", "tokio"] } +sway-core.workspace = true +sway-types.workspace = true +thiserror.workspace = true +tokio = { workspace = true, features = [ "io-util", "macros", + "net", "rt-multi-thread", ] } diff --git a/forc-plugins/forc-debug/src/main.rs b/forc-plugins/forc-debug/src/main.rs index a3a452baa95..7bf6a13b81a 100644 --- a/forc-plugins/forc-debug/src/main.rs +++ b/forc-plugins/forc-debug/src/main.rs @@ -4,6 +4,7 @@ use forc_debug::{ server::DapServer, ContractId, FuelClient, RunResult, Transaction, }; +use forc_tracing::{init_tracing_subscriber, println_error}; use fuel_vm::consts::{VM_MAX_RAM, VM_REGISTER_COUNT, WORD_SIZE}; use shellfish::{async_fn, Command as ShCommand, Shell}; use std::error::Error; @@ -21,9 +22,17 @@ pub struct Opt { } #[tokio::main] -async fn main() -> Result<(), Box> { +async fn main() { + init_tracing_subscriber(Default::default()); let config = Opt::parse(); + if let Err(err) = run(&config).await { + println_error(&format!("{}", err)); + std::process::exit(1); + } +} + +async fn run(config: &Opt) -> Result<(), Box> { if config.serve { return DapServer::default().start(); } @@ -123,7 +132,7 @@ async fn cmd_start_tx(state: &mut State, mut args: Vec) -> Result<(), Bo } let tx_json = std::fs::read(path_to_tx_json)?; - let tx: Transaction = serde_json::from_slice(&tx_json).unwrap(); + let tx: Transaction = serde_json::from_slice(&tx_json)?; let status = state.client.start_tx(&state.session_id, &tx).await?; pretty_print_run_result(&status); diff --git a/forc-plugins/forc-debug/src/server/handlers/handle_set_breakpoints.rs b/forc-plugins/forc-debug/src/server/handlers/handle_set_breakpoints.rs index af08e198ac3..63390fb458e 100644 --- a/forc-plugins/forc-debug/src/server/handlers/handle_set_breakpoints.rs +++ b/forc-plugins/forc-debug/src/server/handlers/handle_set_breakpoints.rs @@ -43,7 +43,7 @@ impl DapServer { .unwrap_or_default() .iter() .map(|source_bp| { - let verified = source_map.get(&source_bp.line).is_some(); + let verified = source_map.contains_key(&source_bp.line); match existing_breakpoints.iter().find(|bp| match bp.line { Some(line) => line == source_bp.line, diff --git a/forc-plugins/forc-doc/Cargo.toml b/forc-plugins/forc-doc/Cargo.toml index 2df059d920b..e6780e0fe80 100644 --- a/forc-plugins/forc-doc/Cargo.toml +++ b/forc-plugins/forc-doc/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "forc-doc" -version = "0.60.0" +version.workspace = true description = "Build the documentation for the local package and all dependencies. The output is placed in `out/doc` in the same format as the project." authors.workspace = true edition.workspace = true @@ -9,23 +9,23 @@ license.workspace = true repository.workspace = true [dependencies] -anyhow = "1.0.65" -clap = { version = "4.5.4", features = ["derive"] } -colored = "2.0.0" -comrak = "0.16" -forc-pkg = { version = "0.60.0", path = "../../forc-pkg" } -forc-util = { version = "0.60.0", path = "../../forc-util" } -horrorshow = "0.8.4" -include_dir = "0.7.3" -minifier = "0.3.0" -opener = "0.5.0" -serde = "1.0" -serde_json = "1.0" -sway-ast = { version = "0.60.0", path = "../../sway-ast" } -sway-core = { version = "0.60.0", path = "../../sway-core" } -sway-lsp = { version = "0.60.0", path = "../../sway-lsp" } -sway-types = { version = "0.60.0", path = "../../sway-types" } -swayfmt = { version = "0.60.0", path = "../../swayfmt" } +anyhow.workspace = true +clap = { workspace = true, features = ["derive"] } +comrak.workspace = true +forc-pkg.workspace = true +forc-tracing.workspace = true +forc-util.workspace = true +horrorshow.workspace = true +include_dir.workspace = true +minifier.workspace = true +opener.workspace = true +serde.workspace = true +serde_json.workspace = true +sway-ast.workspace = true +sway-core.workspace = true +sway-lsp.workspace = true +sway-types.workspace = true +swayfmt.workspace = true [dev-dependencies] dir_indexer = "0.0.2" diff --git a/forc-plugins/forc-doc/src/doc/mod.rs b/forc-plugins/forc-doc/src/doc/mod.rs index 384939a2964..f407eefead7 100644 --- a/forc-plugins/forc-doc/src/doc/mod.rs +++ b/forc-plugins/forc-doc/src/doc/mod.rs @@ -15,7 +15,7 @@ use std::{ }; use sway_core::{ decl_engine::DeclEngine, - language::ty::{TyAstNodeContent, TyDecl, TyImplTrait, TyModule, TyProgram, TySubmodule}, + language::ty::{TyAstNodeContent, TyDecl, TyImplSelfOrTrait, TyModule, TyProgram, TySubmodule}, Engines, }; use sway_types::BaseIdent; @@ -36,7 +36,7 @@ impl Documentation { ) -> Result { // the first module prefix will always be the project name let mut docs = Documentation::default(); - let mut impl_traits: Vec<(TyImplTrait, ModuleInfo)> = Vec::new(); + let mut impl_traits: Vec<(TyImplSelfOrTrait, ModuleInfo)> = Vec::new(); let module_info = ModuleInfo::from_ty_module(vec![project_name.to_owned()], None); Documentation::from_ty_module( engines.de(), @@ -144,14 +144,14 @@ impl Documentation { module_info: &ModuleInfo, ty_module: &TyModule, docs: &mut Documentation, - impl_traits: &mut Vec<(TyImplTrait, ModuleInfo)>, + impl_traits: &mut Vec<(TyImplSelfOrTrait, ModuleInfo)>, document_private_items: bool, ) -> Result<()> { for ast_node in &ty_module.all_nodes { if let TyAstNodeContent::Declaration(ref decl) = ast_node.content { - if let TyDecl::ImplTrait(impl_trait) = decl { + if let TyDecl::ImplSelfOrTrait(impl_trait) = decl { impl_traits.push(( - (*decl_engine.get_impl_trait(&impl_trait.decl_id)).clone(), + (*decl_engine.get_impl_self_or_trait(&impl_trait.decl_id)).clone(), module_info.clone(), )); } else { @@ -175,7 +175,7 @@ impl Documentation { decl_engine: &DeclEngine, typed_submodule: &TySubmodule, docs: &mut Documentation, - impl_traits: &mut Vec<(TyImplTrait, ModuleInfo)>, + impl_traits: &mut Vec<(TyImplSelfOrTrait, ModuleInfo)>, module_info: &ModuleInfo, document_private_items: bool, ) -> Result<()> { diff --git a/forc-plugins/forc-doc/src/lib.rs b/forc-plugins/forc-doc/src/lib.rs index 5369d5b327f..d629b606563 100644 --- a/forc-plugins/forc-doc/src/lib.rs +++ b/forc-plugins/forc-doc/src/lib.rs @@ -6,13 +6,13 @@ pub mod tests; use anyhow::{bail, Result}; use cli::Command; -use colored::Colorize; use doc::Documentation; use forc_pkg as pkg; use forc_pkg::{ manifest::{GenericManifestFile, ManifestFile}, PackageManifestFile, }; +use forc_tracing::println_action_green; use forc_util::default_output_directory; use render::RenderedDocumentation; use std::{ @@ -77,11 +77,13 @@ pub fn compile_html( } fs::create_dir_all(&doc_path)?; - println!( - " {} {} ({})", - "Compiling".bold().yellow(), - pkg_manifest.project_name(), - manifest.dir().to_string_lossy() + println_action_green( + "Compiling", + &format!( + "{} ({})", + pkg_manifest.project_name(), + manifest.dir().to_string_lossy() + ), ); let member_manifests = manifest.member_manifests()?; @@ -179,11 +181,13 @@ fn build_docs( pkg_manifest, } = program_info; - println!( - " {} documentation for {} ({})", - "Building".bold().yellow(), - pkg_manifest.project_name(), - manifest.dir().to_string_lossy() + println_action_green( + "Building", + &format!( + "documentation for {} ({})", + pkg_manifest.project_name(), + manifest.dir().to_string_lossy() + ), ); let raw_docs = Documentation::from_ty_program( @@ -210,7 +214,7 @@ fn build_docs( // write file contents to doc folder write_content(rendered_docs, doc_path)?; - println!(" {}", "Finished".bold().yellow()); + println_action_green("Finished", pkg_manifest.project_name()); Ok(raw_docs) } diff --git a/forc-plugins/forc-doc/src/render/item/context.rs b/forc-plugins/forc-doc/src/render/item/context.rs index a5720ea1394..3e4a49cc29f 100644 --- a/forc-plugins/forc-doc/src/render/item/context.rs +++ b/forc-plugins/forc-doc/src/render/item/context.rs @@ -16,7 +16,7 @@ use anyhow::Result; use horrorshow::{box_html, Raw, RenderBox, Template}; use std::{collections::BTreeMap, fmt::Write}; use sway_core::language::ty::{ - TyEnumVariant, TyImplTrait, TyStorageField, TyStructField, TyTraitFn, TyTraitItem, + TyEnumVariant, TyImplSelfOrTrait, TyStorageField, TyStructField, TyTraitFn, TyTraitItem, }; /// The actual context of the item displayed by [ItemContext]. @@ -268,7 +268,7 @@ impl Renderable for Context { #[derive(Debug, Clone)] pub struct DocImplTrait { pub impl_for_module: ModuleInfo, - pub impl_trait: TyImplTrait, + pub impl_trait: TyImplSelfOrTrait, pub module_info_override: Option>, } @@ -495,7 +495,7 @@ impl Renderable for ItemContext { } impl Renderable for DocImplTrait { fn render(self, render_plan: RenderPlan) -> Result> { - let TyImplTrait { + let TyImplSelfOrTrait { trait_name, items, implementing_for, diff --git a/forc-plugins/forc-doc/src/render/item/type_anchor.rs b/forc-plugins/forc-doc/src/render/item/type_anchor.rs index 17bc2de06c2..514d7f6dcd2 100644 --- a/forc-plugins/forc-doc/src/render/item/type_anchor.rs +++ b/forc-plugins/forc-doc/src/render/item/type_anchor.rs @@ -3,7 +3,7 @@ use crate::{doc::module::ModuleInfo, RenderPlan}; use anyhow::{anyhow, Result}; use horrorshow::{box_html, RenderBox}; use sway_core::{AbiName, TypeInfo}; -use sway_types::Spanned; +use sway_types::{Named, Spanned}; /// Handles types & nested types that should have links /// eg. (`[]` represent types with links). @@ -33,6 +33,18 @@ pub(crate) fn render_type_anchor( : format!("; {}]", len.val()); }) } + TypeInfo::Slice(ty_arg) => { + let inner = render_type_anchor( + (*render_plan.engines.te().get(ty_arg.type_id)).clone(), + render_plan, + current_module_info, + )?; + Ok(box_html! { + : "__slice["; + : inner; + : "]"; + }) + } TypeInfo::Tuple(ty_args) => { let mut rendered_args: Vec<_> = Vec::new(); for ty_arg in ty_args { @@ -50,38 +62,38 @@ pub(crate) fn render_type_anchor( : ")"; }) } - TypeInfo::Enum(decl_ref) => { - let enum_decl = render_plan.engines.de().get_enum(&decl_ref); + TypeInfo::Enum(decl_id) => { + let enum_decl = render_plan.engines.de().get_enum(&decl_id); if !render_plan.document_private_items && enum_decl.visibility.is_private() { Ok(box_html! { - : decl_ref.name().clone().as_str(); + : enum_decl.name().clone().as_str(); }) } else { let module_info = ModuleInfo::from_call_path(&enum_decl.call_path); - let file_name = format!("enum.{}.html", decl_ref.name().clone().as_str()); + let file_name = format!("enum.{}.html", enum_decl.name().clone().as_str()); let href = module_info.file_path_from_location(&file_name, current_module_info, false)?; Ok(box_html! { a(class="enum", href=href) { - : decl_ref.name().clone().as_str(); + : enum_decl.name().clone().as_str(); } }) } } - TypeInfo::Struct(decl_ref) => { - let struct_decl = render_plan.engines.de().get_struct(&decl_ref); + TypeInfo::Struct(decl_id) => { + let struct_decl = render_plan.engines.de().get_struct(&decl_id); if !render_plan.document_private_items && struct_decl.visibility.is_private() { Ok(box_html! { - : decl_ref.name().clone().as_str(); + : struct_decl.name().clone().as_str(); }) } else { let module_info = ModuleInfo::from_call_path(&struct_decl.call_path); - let file_name = format!("struct.{}.html", decl_ref.name().clone().as_str()); + let file_name = format!("struct.{}.html", struct_decl.name().clone().as_str()); let href = module_info.file_path_from_location(&file_name, current_module_info, false)?; Ok(box_html! { a(class="struct", href=href) { - : decl_ref.name().clone().as_str(); + : struct_decl.name().clone().as_str(); } }) } diff --git a/forc-plugins/forc-doc/src/render/search.rs b/forc-plugins/forc-doc/src/render/search.rs index e0f84216ebe..9213c17210d 100644 --- a/forc-plugins/forc-doc/src/render/search.rs +++ b/forc-plugins/forc-doc/src/render/search.rs @@ -25,10 +25,10 @@ pub(crate) fn generate_searchbar(module_info: &ModuleInfo) -> Box const searchbar = document.getElementById("search-input"); const searchForm = document.getElementById("search-form"); searchbar.addEventListener("keyup", function(event) {{ - searchForm.dispatchEvent(new Event('submit')); + onSearchFormSubmit(event); }}); searchbar.addEventListener("search", function(event) {{ - searchForm.dispatchEvent(new Event('submit')); + onSearchFormSubmit(event); }}); function onQueryParamsChange() {{ diff --git a/forc-plugins/forc-doc/src/render/title.rs b/forc-plugins/forc-doc/src/render/title.rs index ee4b1a44271..26dcc1e85fd 100644 --- a/forc-plugins/forc-doc/src/render/title.rs +++ b/forc-plugins/forc-doc/src/render/title.rs @@ -119,7 +119,7 @@ impl DocBlock for TyDecl { TyDecl::TraitDecl(_) => "trait", TyDecl::AbiDecl(_) => "abi", TyDecl::StorageDecl(_) => "contract_storage", - TyDecl::ImplTrait(_) => "impl_trait", + TyDecl::ImplSelfOrTrait(_) => "impl_trait", TyDecl::FunctionDecl(_) => "fn", TyDecl::ConstantDecl(_) => "constant", TyDecl::TypeAliasDecl(_) => "type_alias", diff --git a/forc-plugins/forc-doc/src/tests/expects/impl_trait/mod.rs b/forc-plugins/forc-doc/src/tests/expects/impl_trait/mod.rs index 5ab755043de..8f96a41e856 100644 --- a/forc-plugins/forc-doc/src/tests/expects/impl_trait/mod.rs +++ b/forc-plugins/forc-doc/src/tests/expects/impl_trait/mod.rs @@ -37,15 +37,14 @@ fn test_impl_traits_default() { assert_index_html( &doc_path, project_name, - &expect![[ - r##"Bar in bar - Sway
pub struct Bar {}

Implementations

fn foo_bar()

Trait Implementations

fn foo()

something more about foo();

-

fn add(self, other: Self) -> Self

fn subtract(self, other: Self) -> Self

"## - ]], + &expect![[r##" + Bar in bar - Sway
pub struct Bar {}

Implementations

fn foo_bar()

Trait Implementations

fn foo()

something more about foo();

+

fn add(self, other: Self) -> Self

fn subtract(self, other: Self) -> Self

"##]], ); assert_search_js( &doc_path, &expect![[r#" - var SEARCH_INDEX={"core":[{"html_filename":"trait.AsRawSlice.html","module_info":["core","raw_slice"],"name":"AsRawSlice","preview":"Trait to return a type as a raw_slice.\n","type_name":"trait"},{"html_filename":"fn.from_str_array.html","module_info":["core","str"],"name":"from_str_array","preview":"","type_name":"function"},{"html_filename":"trait.Add.html","module_info":["core","ops"],"name":"Add","preview":"Trait for the addition of two values.\n","type_name":"trait"},{"html_filename":"trait.Subtract.html","module_info":["core","ops"],"name":"Subtract","preview":"Trait for the subtraction of two values.\n","type_name":"trait"},{"html_filename":"trait.Multiply.html","module_info":["core","ops"],"name":"Multiply","preview":"Trait for the multiplication of two values.\n","type_name":"trait"},{"html_filename":"trait.Divide.html","module_info":["core","ops"],"name":"Divide","preview":"Trait for the division of two values.\n","type_name":"trait"},{"html_filename":"trait.Mod.html","module_info":["core","ops"],"name":"Mod","preview":"Trait for the modulo of two values.\n","type_name":"trait"},{"html_filename":"trait.Not.html","module_info":["core","ops"],"name":"Not","preview":"Trait to invert a type.\n","type_name":"trait"},{"html_filename":"trait.Eq.html","module_info":["core","ops"],"name":"Eq","preview":"Trait to evaluate if two types are equal.\n","type_name":"trait"},{"html_filename":"trait.Ord.html","module_info":["core","ops"],"name":"Ord","preview":"Trait to evaluate if one value is greater or less than another of the same type.\n","type_name":"trait"},{"html_filename":"trait.BitwiseAnd.html","module_info":["core","ops"],"name":"BitwiseAnd","preview":"Trait to bitwise AND two values of the same type.\n","type_name":"trait"},{"html_filename":"trait.BitwiseOr.html","module_info":["core","ops"],"name":"BitwiseOr","preview":"Trait to bitwise OR two values of the same type.\n","type_name":"trait"},{"html_filename":"trait.BitwiseXor.html","module_info":["core","ops"],"name":"BitwiseXor","preview":"Trait to bitwise XOR two values of the same type.\n","type_name":"trait"},{"html_filename":"trait.Shift.html","module_info":["core","ops"],"name":"Shift","preview":"Trait to bit shift a value.\n","type_name":"trait"},{"html_filename":"fn.ok_str_eq.html","module_info":["core","ops"],"name":"ok_str_eq","preview":"","type_name":"function"},{"html_filename":"struct.StorageKey.html","module_info":["core","storage"],"name":"StorageKey","preview":"Describes a location in storage.\n","type_name":"struct"},{"html_filename":"struct.Buffer.html","module_info":["core","codec"],"name":"Buffer","preview":"","type_name":"struct"},{"html_filename":"struct.BufferReader.html","module_info":["core","codec"],"name":"BufferReader","preview":"","type_name":"struct"},{"html_filename":"trait.AbiDecode.html","module_info":["core","codec"],"name":"AbiDecode","preview":"","type_name":"trait"},{"html_filename":"trait.AbiEncode.html","module_info":["core","codec"],"name":"AbiEncode","preview":"","type_name":"trait"},{"html_filename":"fn.encode.html","module_info":["core","codec"],"name":"encode","preview":"","type_name":"function"},{"html_filename":"fn.abi_decode.html","module_info":["core","codec"],"name":"abi_decode","preview":"","type_name":"function"},{"html_filename":"fn.abi_decode_in_place.html","module_info":["core","codec"],"name":"abi_decode_in_place","preview":"","type_name":"function"},{"html_filename":"fn.contract_call.html","module_info":["core","codec"],"name":"contract_call","preview":"","type_name":"function"},{"html_filename":"fn.decode_script_data.html","module_info":["core","codec"],"name":"decode_script_data","preview":"","type_name":"function"},{"html_filename":"fn.decode_predicate_data.html","module_info":["core","codec"],"name":"decode_predicate_data","preview":"","type_name":"function"},{"html_filename":"fn.decode_predicate_data_by_index.html","module_info":["core","codec"],"name":"decode_predicate_data_by_index","preview":"","type_name":"function"},{"html_filename":"fn.decode_first_param.html","module_info":["core","codec"],"name":"decode_first_param","preview":"","type_name":"function"},{"html_filename":"fn.decode_second_param.html","module_info":["core","codec"],"name":"decode_second_param","preview":"","type_name":"function"},{"html_filename":"primitive.u256.html","module_info":["core"],"name":"u256","preview":"256-bit unsigned integer","type_name":"primitive"},{"html_filename":"primitive.u64.html","module_info":["core"],"name":"u64","preview":"64-bit unsigned integer","type_name":"primitive"},{"html_filename":"primitive.u32.html","module_info":["core"],"name":"u32","preview":"32-bit unsigned integer","type_name":"primitive"},{"html_filename":"primitive.u16.html","module_info":["core"],"name":"u16","preview":"16-bit unsigned integer","type_name":"primitive"},{"html_filename":"primitive.u8.html","module_info":["core"],"name":"u8","preview":"8-bit unsigned integer","type_name":"primitive"},{"html_filename":"primitive.b256.html","module_info":["core"],"name":"b256","preview":"256 bits (32 bytes), i.e. a hash","type_name":"primitive"},{"html_filename":"primitive.str.html","module_info":["core"],"name":"str","preview":"string slice","type_name":"primitive"},{"html_filename":"primitive.bool.html","module_info":["core"],"name":"bool","preview":"Boolean true or false","type_name":"primitive"},{"html_filename":"primitive.str[0].html","module_info":["core"],"name":"str[0]","preview":"fixed-length string","type_name":"primitive"},{"html_filename":"primitive.str[1].html","module_info":["core"],"name":"str[1]","preview":"fixed-length string","type_name":"primitive"},{"html_filename":"primitive.str[2].html","module_info":["core"],"name":"str[2]","preview":"fixed-length string","type_name":"primitive"},{"html_filename":"primitive.str[3].html","module_info":["core"],"name":"str[3]","preview":"fixed-length string","type_name":"primitive"},{"html_filename":"primitive.str[4].html","module_info":["core"],"name":"str[4]","preview":"fixed-length string","type_name":"primitive"},{"html_filename":"primitive.str[5].html","module_info":["core"],"name":"str[5]","preview":"fixed-length string","type_name":"primitive"},{"html_filename":"primitive.str[6].html","module_info":["core"],"name":"str[6]","preview":"fixed-length string","type_name":"primitive"},{"html_filename":"primitive.str[7].html","module_info":["core"],"name":"str[7]","preview":"fixed-length string","type_name":"primitive"},{"html_filename":"primitive.str[8].html","module_info":["core"],"name":"str[8]","preview":"fixed-length string","type_name":"primitive"},{"html_filename":"primitive.str[9].html","module_info":["core"],"name":"str[9]","preview":"fixed-length string","type_name":"primitive"},{"html_filename":"primitive.str[10].html","module_info":["core"],"name":"str[10]","preview":"fixed-length string","type_name":"primitive"},{"html_filename":"primitive.str[11].html","module_info":["core"],"name":"str[11]","preview":"fixed-length string","type_name":"primitive"},{"html_filename":"primitive.str[12].html","module_info":["core"],"name":"str[12]","preview":"fixed-length string","type_name":"primitive"},{"html_filename":"primitive.str[13].html","module_info":["core"],"name":"str[13]","preview":"fixed-length string","type_name":"primitive"},{"html_filename":"primitive.str[14].html","module_info":["core"],"name":"str[14]","preview":"fixed-length string","type_name":"primitive"},{"html_filename":"primitive.str[15].html","module_info":["core"],"name":"str[15]","preview":"fixed-length string","type_name":"primitive"},{"html_filename":"primitive.str[16].html","module_info":["core"],"name":"str[16]","preview":"fixed-length string","type_name":"primitive"},{"html_filename":"primitive.str[17].html","module_info":["core"],"name":"str[17]","preview":"fixed-length string","type_name":"primitive"},{"html_filename":"primitive.str[18].html","module_info":["core"],"name":"str[18]","preview":"fixed-length string","type_name":"primitive"},{"html_filename":"primitive.str[19].html","module_info":["core"],"name":"str[19]","preview":"fixed-length string","type_name":"primitive"},{"html_filename":"primitive.str[20].html","module_info":["core"],"name":"str[20]","preview":"fixed-length string","type_name":"primitive"},{"html_filename":"primitive.str[21].html","module_info":["core"],"name":"str[21]","preview":"fixed-length string","type_name":"primitive"},{"html_filename":"primitive.str[22].html","module_info":["core"],"name":"str[22]","preview":"fixed-length string","type_name":"primitive"},{"html_filename":"primitive.str[23].html","module_info":["core"],"name":"str[23]","preview":"fixed-length string","type_name":"primitive"},{"html_filename":"primitive.str[24].html","module_info":["core"],"name":"str[24]","preview":"fixed-length string","type_name":"primitive"},{"html_filename":"primitive.str[25].html","module_info":["core"],"name":"str[25]","preview":"fixed-length string","type_name":"primitive"},{"html_filename":"primitive.str[26].html","module_info":["core"],"name":"str[26]","preview":"fixed-length string","type_name":"primitive"},{"html_filename":"primitive.str[27].html","module_info":["core"],"name":"str[27]","preview":"fixed-length string","type_name":"primitive"},{"html_filename":"primitive.str[28].html","module_info":["core"],"name":"str[28]","preview":"fixed-length string","type_name":"primitive"},{"html_filename":"primitive.str[29].html","module_info":["core"],"name":"str[29]","preview":"fixed-length string","type_name":"primitive"},{"html_filename":"primitive.str[30].html","module_info":["core"],"name":"str[30]","preview":"fixed-length string","type_name":"primitive"},{"html_filename":"primitive.str[31].html","module_info":["core"],"name":"str[31]","preview":"fixed-length string","type_name":"primitive"},{"html_filename":"primitive.str[32].html","module_info":["core"],"name":"str[32]","preview":"fixed-length string","type_name":"primitive"},{"html_filename":"primitive.str[33].html","module_info":["core"],"name":"str[33]","preview":"fixed-length string","type_name":"primitive"},{"html_filename":"primitive.str[34].html","module_info":["core"],"name":"str[34]","preview":"fixed-length string","type_name":"primitive"},{"html_filename":"primitive.str[35].html","module_info":["core"],"name":"str[35]","preview":"fixed-length string","type_name":"primitive"},{"html_filename":"primitive.str[36].html","module_info":["core"],"name":"str[36]","preview":"fixed-length string","type_name":"primitive"},{"html_filename":"primitive.str[37].html","module_info":["core"],"name":"str[37]","preview":"fixed-length string","type_name":"primitive"},{"html_filename":"primitive.str[38].html","module_info":["core"],"name":"str[38]","preview":"fixed-length string","type_name":"primitive"},{"html_filename":"primitive.str[39].html","module_info":["core"],"name":"str[39]","preview":"fixed-length string","type_name":"primitive"},{"html_filename":"primitive.str[40].html","module_info":["core"],"name":"str[40]","preview":"fixed-length string","type_name":"primitive"},{"html_filename":"primitive.str[41].html","module_info":["core"],"name":"str[41]","preview":"fixed-length string","type_name":"primitive"},{"html_filename":"primitive.str[42].html","module_info":["core"],"name":"str[42]","preview":"fixed-length string","type_name":"primitive"},{"html_filename":"primitive.str[43].html","module_info":["core"],"name":"str[43]","preview":"fixed-length string","type_name":"primitive"},{"html_filename":"primitive.str[44].html","module_info":["core"],"name":"str[44]","preview":"fixed-length string","type_name":"primitive"},{"html_filename":"primitive.str[45].html","module_info":["core"],"name":"str[45]","preview":"fixed-length string","type_name":"primitive"},{"html_filename":"primitive.str[46].html","module_info":["core"],"name":"str[46]","preview":"fixed-length string","type_name":"primitive"},{"html_filename":"primitive.str[47].html","module_info":["core"],"name":"str[47]","preview":"fixed-length string","type_name":"primitive"},{"html_filename":"primitive.str[48].html","module_info":["core"],"name":"str[48]","preview":"fixed-length string","type_name":"primitive"},{"html_filename":"primitive.str[49].html","module_info":["core"],"name":"str[49]","preview":"fixed-length string","type_name":"primitive"},{"html_filename":"primitive.str[50].html","module_info":["core"],"name":"str[50]","preview":"fixed-length string","type_name":"primitive"},{"html_filename":"primitive.str[51].html","module_info":["core"],"name":"str[51]","preview":"fixed-length string","type_name":"primitive"},{"html_filename":"primitive.str[52].html","module_info":["core"],"name":"str[52]","preview":"fixed-length string","type_name":"primitive"},{"html_filename":"primitive.str[53].html","module_info":["core"],"name":"str[53]","preview":"fixed-length string","type_name":"primitive"},{"html_filename":"primitive.str[54].html","module_info":["core"],"name":"str[54]","preview":"fixed-length string","type_name":"primitive"},{"html_filename":"primitive.str[55].html","module_info":["core"],"name":"str[55]","preview":"fixed-length string","type_name":"primitive"},{"html_filename":"primitive.str[56].html","module_info":["core"],"name":"str[56]","preview":"fixed-length string","type_name":"primitive"},{"html_filename":"primitive.str[57].html","module_info":["core"],"name":"str[57]","preview":"fixed-length string","type_name":"primitive"},{"html_filename":"primitive.str[58].html","module_info":["core"],"name":"str[58]","preview":"fixed-length string","type_name":"primitive"},{"html_filename":"primitive.str[59].html","module_info":["core"],"name":"str[59]","preview":"fixed-length string","type_name":"primitive"},{"html_filename":"primitive.str[60].html","module_info":["core"],"name":"str[60]","preview":"fixed-length string","type_name":"primitive"},{"html_filename":"primitive.str[61].html","module_info":["core"],"name":"str[61]","preview":"fixed-length string","type_name":"primitive"},{"html_filename":"primitive.str[62].html","module_info":["core"],"name":"str[62]","preview":"fixed-length string","type_name":"primitive"},{"html_filename":"primitive.str[63].html","module_info":["core"],"name":"str[63]","preview":"fixed-length string","type_name":"primitive"},{"html_filename":"primitive.str[64].html","module_info":["core"],"name":"str[64]","preview":"fixed-length string","type_name":"primitive"}],"impl_traits":[{"html_filename":"trait.Foo.html","module_info":["impl_traits","foo"],"name":"Foo","preview":"","type_name":"trait"},{"html_filename":"trait.Baz.html","module_info":["impl_traits","foo"],"name":"Baz","preview":"","type_name":"trait"},{"html_filename":"struct.Bar.html","module_info":["impl_traits","bar"],"name":"Bar","preview":"","type_name":"struct"}]}; + var SEARCH_INDEX={"core":[{"html_filename":"trait.AsRawSlice.html","module_info":["core","raw_slice"],"name":"AsRawSlice","preview":"Trait to return a type as a raw_slice.\n","type_name":"trait"},{"html_filename":"fn.from_str_array.html","module_info":["core","str"],"name":"from_str_array","preview":"","type_name":"function"},{"html_filename":"trait.Add.html","module_info":["core","ops"],"name":"Add","preview":"Trait for the addition of two values.\n","type_name":"trait"},{"html_filename":"trait.Subtract.html","module_info":["core","ops"],"name":"Subtract","preview":"Trait for the subtraction of two values.\n","type_name":"trait"},{"html_filename":"trait.Multiply.html","module_info":["core","ops"],"name":"Multiply","preview":"Trait for the multiplication of two values.\n","type_name":"trait"},{"html_filename":"trait.Divide.html","module_info":["core","ops"],"name":"Divide","preview":"Trait for the division of two values.\n","type_name":"trait"},{"html_filename":"trait.Mod.html","module_info":["core","ops"],"name":"Mod","preview":"Trait for the modulo of two values.\n","type_name":"trait"},{"html_filename":"trait.Not.html","module_info":["core","ops"],"name":"Not","preview":"Trait to invert a type.\n","type_name":"trait"},{"html_filename":"trait.Eq.html","module_info":["core","ops"],"name":"Eq","preview":"Trait to evaluate if two types are equal.\n","type_name":"trait"},{"html_filename":"trait.Ord.html","module_info":["core","ops"],"name":"Ord","preview":"Trait to evaluate if one value is greater or less than another of the same type.\n","type_name":"trait"},{"html_filename":"trait.BitwiseAnd.html","module_info":["core","ops"],"name":"BitwiseAnd","preview":"Trait to bitwise AND two values of the same type.\n","type_name":"trait"},{"html_filename":"trait.BitwiseOr.html","module_info":["core","ops"],"name":"BitwiseOr","preview":"Trait to bitwise OR two values of the same type.\n","type_name":"trait"},{"html_filename":"trait.BitwiseXor.html","module_info":["core","ops"],"name":"BitwiseXor","preview":"Trait to bitwise XOR two values of the same type.\n","type_name":"trait"},{"html_filename":"trait.Shift.html","module_info":["core","ops"],"name":"Shift","preview":"Trait to bit shift a value.\n","type_name":"trait"},{"html_filename":"trait.TotalOrd.html","module_info":["core","ops"],"name":"TotalOrd","preview":"Trait to compare values of the same type.\n","type_name":"trait"},{"html_filename":"fn.ok_str_eq.html","module_info":["core","ops"],"name":"ok_str_eq","preview":"","type_name":"function"},{"html_filename":"struct.StorageKey.html","module_info":["core","storage"],"name":"StorageKey","preview":"Describes a location in storage.\n","type_name":"struct"},{"html_filename":"struct.Buffer.html","module_info":["core","codec"],"name":"Buffer","preview":"","type_name":"struct"},{"html_filename":"struct.BufferReader.html","module_info":["core","codec"],"name":"BufferReader","preview":"","type_name":"struct"},{"html_filename":"trait.AbiDecode.html","module_info":["core","codec"],"name":"AbiDecode","preview":"","type_name":"trait"},{"html_filename":"trait.AbiEncode.html","module_info":["core","codec"],"name":"AbiEncode","preview":"","type_name":"trait"},{"html_filename":"fn.encode.html","module_info":["core","codec"],"name":"encode","preview":"","type_name":"function"},{"html_filename":"fn.abi_decode.html","module_info":["core","codec"],"name":"abi_decode","preview":"","type_name":"function"},{"html_filename":"fn.abi_decode_in_place.html","module_info":["core","codec"],"name":"abi_decode_in_place","preview":"","type_name":"function"},{"html_filename":"fn.contract_call.html","module_info":["core","codec"],"name":"contract_call","preview":"","type_name":"function"},{"html_filename":"fn.decode_script_data.html","module_info":["core","codec"],"name":"decode_script_data","preview":"","type_name":"function"},{"html_filename":"fn.decode_predicate_data.html","module_info":["core","codec"],"name":"decode_predicate_data","preview":"","type_name":"function"},{"html_filename":"fn.decode_predicate_data_by_index.html","module_info":["core","codec"],"name":"decode_predicate_data_by_index","preview":"","type_name":"function"},{"html_filename":"fn.decode_first_param.html","module_info":["core","codec"],"name":"decode_first_param","preview":"","type_name":"function"},{"html_filename":"fn.decode_second_param.html","module_info":["core","codec"],"name":"decode_second_param","preview":"","type_name":"function"},{"html_filename":"primitive.u256.html","module_info":["core"],"name":"u256","preview":"256-bit unsigned integer","type_name":"primitive"},{"html_filename":"primitive.u64.html","module_info":["core"],"name":"u64","preview":"64-bit unsigned integer","type_name":"primitive"},{"html_filename":"primitive.u32.html","module_info":["core"],"name":"u32","preview":"32-bit unsigned integer","type_name":"primitive"},{"html_filename":"primitive.u16.html","module_info":["core"],"name":"u16","preview":"16-bit unsigned integer","type_name":"primitive"},{"html_filename":"primitive.u8.html","module_info":["core"],"name":"u8","preview":"8-bit unsigned integer","type_name":"primitive"},{"html_filename":"primitive.b256.html","module_info":["core"],"name":"b256","preview":"256 bits (32 bytes), i.e. a hash","type_name":"primitive"},{"html_filename":"primitive.str.html","module_info":["core"],"name":"str","preview":"string slice","type_name":"primitive"},{"html_filename":"primitive.bool.html","module_info":["core"],"name":"bool","preview":"Boolean true or false","type_name":"primitive"},{"html_filename":"primitive.str[0].html","module_info":["core"],"name":"str[0]","preview":"fixed-length string","type_name":"primitive"},{"html_filename":"primitive.str[1].html","module_info":["core"],"name":"str[1]","preview":"fixed-length string","type_name":"primitive"},{"html_filename":"primitive.str[2].html","module_info":["core"],"name":"str[2]","preview":"fixed-length string","type_name":"primitive"},{"html_filename":"primitive.str[3].html","module_info":["core"],"name":"str[3]","preview":"fixed-length string","type_name":"primitive"},{"html_filename":"primitive.str[4].html","module_info":["core"],"name":"str[4]","preview":"fixed-length string","type_name":"primitive"},{"html_filename":"primitive.str[5].html","module_info":["core"],"name":"str[5]","preview":"fixed-length string","type_name":"primitive"},{"html_filename":"primitive.str[6].html","module_info":["core"],"name":"str[6]","preview":"fixed-length string","type_name":"primitive"},{"html_filename":"primitive.str[7].html","module_info":["core"],"name":"str[7]","preview":"fixed-length string","type_name":"primitive"},{"html_filename":"primitive.str[8].html","module_info":["core"],"name":"str[8]","preview":"fixed-length string","type_name":"primitive"},{"html_filename":"primitive.str[9].html","module_info":["core"],"name":"str[9]","preview":"fixed-length string","type_name":"primitive"},{"html_filename":"primitive.str[10].html","module_info":["core"],"name":"str[10]","preview":"fixed-length string","type_name":"primitive"},{"html_filename":"primitive.str[11].html","module_info":["core"],"name":"str[11]","preview":"fixed-length string","type_name":"primitive"},{"html_filename":"primitive.str[12].html","module_info":["core"],"name":"str[12]","preview":"fixed-length string","type_name":"primitive"},{"html_filename":"primitive.str[13].html","module_info":["core"],"name":"str[13]","preview":"fixed-length string","type_name":"primitive"},{"html_filename":"primitive.str[14].html","module_info":["core"],"name":"str[14]","preview":"fixed-length string","type_name":"primitive"},{"html_filename":"primitive.str[15].html","module_info":["core"],"name":"str[15]","preview":"fixed-length string","type_name":"primitive"},{"html_filename":"primitive.str[16].html","module_info":["core"],"name":"str[16]","preview":"fixed-length string","type_name":"primitive"},{"html_filename":"primitive.str[17].html","module_info":["core"],"name":"str[17]","preview":"fixed-length string","type_name":"primitive"},{"html_filename":"primitive.str[18].html","module_info":["core"],"name":"str[18]","preview":"fixed-length string","type_name":"primitive"},{"html_filename":"primitive.str[19].html","module_info":["core"],"name":"str[19]","preview":"fixed-length string","type_name":"primitive"},{"html_filename":"primitive.str[20].html","module_info":["core"],"name":"str[20]","preview":"fixed-length string","type_name":"primitive"},{"html_filename":"primitive.str[21].html","module_info":["core"],"name":"str[21]","preview":"fixed-length string","type_name":"primitive"},{"html_filename":"primitive.str[22].html","module_info":["core"],"name":"str[22]","preview":"fixed-length string","type_name":"primitive"},{"html_filename":"primitive.str[23].html","module_info":["core"],"name":"str[23]","preview":"fixed-length string","type_name":"primitive"},{"html_filename":"primitive.str[24].html","module_info":["core"],"name":"str[24]","preview":"fixed-length string","type_name":"primitive"},{"html_filename":"primitive.str[25].html","module_info":["core"],"name":"str[25]","preview":"fixed-length string","type_name":"primitive"},{"html_filename":"primitive.str[26].html","module_info":["core"],"name":"str[26]","preview":"fixed-length string","type_name":"primitive"},{"html_filename":"primitive.str[27].html","module_info":["core"],"name":"str[27]","preview":"fixed-length string","type_name":"primitive"},{"html_filename":"primitive.str[28].html","module_info":["core"],"name":"str[28]","preview":"fixed-length string","type_name":"primitive"},{"html_filename":"primitive.str[29].html","module_info":["core"],"name":"str[29]","preview":"fixed-length string","type_name":"primitive"},{"html_filename":"primitive.str[30].html","module_info":["core"],"name":"str[30]","preview":"fixed-length string","type_name":"primitive"},{"html_filename":"primitive.str[31].html","module_info":["core"],"name":"str[31]","preview":"fixed-length string","type_name":"primitive"},{"html_filename":"primitive.str[32].html","module_info":["core"],"name":"str[32]","preview":"fixed-length string","type_name":"primitive"},{"html_filename":"primitive.str[33].html","module_info":["core"],"name":"str[33]","preview":"fixed-length string","type_name":"primitive"},{"html_filename":"primitive.str[34].html","module_info":["core"],"name":"str[34]","preview":"fixed-length string","type_name":"primitive"},{"html_filename":"primitive.str[35].html","module_info":["core"],"name":"str[35]","preview":"fixed-length string","type_name":"primitive"},{"html_filename":"primitive.str[36].html","module_info":["core"],"name":"str[36]","preview":"fixed-length string","type_name":"primitive"},{"html_filename":"primitive.str[37].html","module_info":["core"],"name":"str[37]","preview":"fixed-length string","type_name":"primitive"},{"html_filename":"primitive.str[38].html","module_info":["core"],"name":"str[38]","preview":"fixed-length string","type_name":"primitive"},{"html_filename":"primitive.str[39].html","module_info":["core"],"name":"str[39]","preview":"fixed-length string","type_name":"primitive"},{"html_filename":"primitive.str[40].html","module_info":["core"],"name":"str[40]","preview":"fixed-length string","type_name":"primitive"},{"html_filename":"primitive.str[41].html","module_info":["core"],"name":"str[41]","preview":"fixed-length string","type_name":"primitive"},{"html_filename":"primitive.str[42].html","module_info":["core"],"name":"str[42]","preview":"fixed-length string","type_name":"primitive"},{"html_filename":"primitive.str[43].html","module_info":["core"],"name":"str[43]","preview":"fixed-length string","type_name":"primitive"},{"html_filename":"primitive.str[44].html","module_info":["core"],"name":"str[44]","preview":"fixed-length string","type_name":"primitive"},{"html_filename":"primitive.str[45].html","module_info":["core"],"name":"str[45]","preview":"fixed-length string","type_name":"primitive"},{"html_filename":"primitive.str[46].html","module_info":["core"],"name":"str[46]","preview":"fixed-length string","type_name":"primitive"},{"html_filename":"primitive.str[47].html","module_info":["core"],"name":"str[47]","preview":"fixed-length string","type_name":"primitive"},{"html_filename":"primitive.str[48].html","module_info":["core"],"name":"str[48]","preview":"fixed-length string","type_name":"primitive"},{"html_filename":"primitive.str[49].html","module_info":["core"],"name":"str[49]","preview":"fixed-length string","type_name":"primitive"},{"html_filename":"primitive.str[50].html","module_info":["core"],"name":"str[50]","preview":"fixed-length string","type_name":"primitive"},{"html_filename":"primitive.str[51].html","module_info":["core"],"name":"str[51]","preview":"fixed-length string","type_name":"primitive"},{"html_filename":"primitive.str[52].html","module_info":["core"],"name":"str[52]","preview":"fixed-length string","type_name":"primitive"},{"html_filename":"primitive.str[53].html","module_info":["core"],"name":"str[53]","preview":"fixed-length string","type_name":"primitive"},{"html_filename":"primitive.str[54].html","module_info":["core"],"name":"str[54]","preview":"fixed-length string","type_name":"primitive"},{"html_filename":"primitive.str[55].html","module_info":["core"],"name":"str[55]","preview":"fixed-length string","type_name":"primitive"},{"html_filename":"primitive.str[56].html","module_info":["core"],"name":"str[56]","preview":"fixed-length string","type_name":"primitive"},{"html_filename":"primitive.str[57].html","module_info":["core"],"name":"str[57]","preview":"fixed-length string","type_name":"primitive"},{"html_filename":"primitive.str[58].html","module_info":["core"],"name":"str[58]","preview":"fixed-length string","type_name":"primitive"},{"html_filename":"primitive.str[59].html","module_info":["core"],"name":"str[59]","preview":"fixed-length string","type_name":"primitive"},{"html_filename":"primitive.str[60].html","module_info":["core"],"name":"str[60]","preview":"fixed-length string","type_name":"primitive"},{"html_filename":"primitive.str[61].html","module_info":["core"],"name":"str[61]","preview":"fixed-length string","type_name":"primitive"},{"html_filename":"primitive.str[62].html","module_info":["core"],"name":"str[62]","preview":"fixed-length string","type_name":"primitive"},{"html_filename":"primitive.str[63].html","module_info":["core"],"name":"str[63]","preview":"fixed-length string","type_name":"primitive"},{"html_filename":"primitive.str[64].html","module_info":["core"],"name":"str[64]","preview":"fixed-length string","type_name":"primitive"}],"impl_traits":[{"html_filename":"trait.Foo.html","module_info":["impl_traits","foo"],"name":"Foo","preview":"","type_name":"trait"},{"html_filename":"trait.Baz.html","module_info":["impl_traits","foo"],"name":"Baz","preview":"","type_name":"trait"},{"html_filename":"struct.Bar.html","module_info":["impl_traits","bar"],"name":"Bar","preview":"","type_name":"struct"}]}; "object"==typeof exports&&"undefined"!=typeof module&&(module.exports=SEARCH_INDEX);"#]], ); assert_file_tree( @@ -155,6 +154,7 @@ fn test_impl_traits_default() { "core/ops/trait.Ord.html", "core/ops/trait.Shift.html", "core/ops/trait.Subtract.html", + "core/ops/trait.TotalOrd.html", "core/raw_slice/index.html", "core/raw_slice/trait.AsRawSlice.html", "core/storage/index.html", @@ -195,7 +195,7 @@ fn test_impl_traits_no_deps() { &doc_path, project_name, &expect![[ - r##"Bar in bar - Sway
pub struct Bar {}

Implementations

fn foo_bar()

Trait Implementations

fn foo()

something more about foo();

+ r##"Bar in bar - Sway
pub struct Bar {}

Implementations

fn foo_bar()

Trait Implementations

fn foo()

something more about foo();

fn add(self, other: Self) -> Self

fn subtract(self, other: Self) -> Self

"## ]], ); diff --git a/forc-plugins/forc-fmt/Cargo.toml b/forc-plugins/forc-fmt/Cargo.toml index fd0ae98f45e..d1fdedcce41 100644 --- a/forc-plugins/forc-fmt/Cargo.toml +++ b/forc-plugins/forc-fmt/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "forc-fmt" -version = "0.60.0" +version.workspace = true description = "A `forc` plugin for running the Sway code formatter." authors.workspace = true edition.workspace = true @@ -9,14 +9,14 @@ license.workspace = true repository.workspace = true [dependencies] -anyhow = "1" -clap = { version = "4.5.4", features = ["derive"] } -forc-pkg = { version = "0.60.0", path = "../../forc-pkg" } -forc-tracing = { version = "0.60.0", path = "../../forc-tracing" } -forc-util = { version = "0.60.0", path = "../../forc-util" } -prettydiff = "0.5" -sway-core = { version = "0.60.0", path = "../../sway-core" } -sway-utils = { version = "0.60.0", path = "../../sway-utils" } -swayfmt = { version = "0.60.0", path = "../../swayfmt" } -taplo = "0.7" -tracing = "0.1" +anyhow.workspace = true +clap = { workspace = true, features = ["derive"] } +forc-pkg.workspace = true +forc-tracing.workspace = true +forc-util.workspace = true +prettydiff.workspace = true +sway-core.workspace = true +sway-utils.workspace = true +swayfmt.workspace = true +taplo.workspace = true +tracing.workspace = true diff --git a/forc-plugins/forc-lsp/Cargo.toml b/forc-plugins/forc-lsp/Cargo.toml index f49074fe946..83ed86b61ad 100644 --- a/forc-plugins/forc-lsp/Cargo.toml +++ b/forc-plugins/forc-lsp/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "forc-lsp" -version = "0.60.0" +version.workspace = true description = "A simple `forc` plugin for starting the sway language server." authors.workspace = true edition.workspace = true @@ -9,8 +9,8 @@ license.workspace = true repository.workspace = true [dependencies] -anyhow = "1" -clap = { version = "4.5.4", features = ["derive"] } -sway-lsp = { version = "0.60.0", path = "../../sway-lsp" } -tikv-jemallocator = "0.5" -tokio = { version = "1.8" } +anyhow.workspace = true +clap = { workspace = true, features = ["derive"] } +sway-lsp.workspace = true +tikv-jemallocator.workspace = true +tokio.workspace = true diff --git a/forc-plugins/forc-lsp/src/main.rs b/forc-plugins/forc-lsp/src/main.rs index 2303f7785b2..b859e136135 100644 --- a/forc-plugins/forc-lsp/src/main.rs +++ b/forc-plugins/forc-lsp/src/main.rs @@ -1,7 +1,7 @@ //! A simple `forc` plugin for starting the sway language server. //! //! Once installed and available via `PATH`, can be executed via `forc lsp`. - +#![recursion_limit = "256"] // Use Jemalloc for main binary #[global_allocator] static GLOBAL: tikv_jemallocator::Jemalloc = tikv_jemallocator::Jemalloc; diff --git a/forc-plugins/forc-tx/Cargo.toml b/forc-plugins/forc-tx/Cargo.toml index 0130164aff0..91fee672cf3 100644 --- a/forc-plugins/forc-tx/Cargo.toml +++ b/forc-plugins/forc-tx/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "forc-tx" -version = "0.60.0" +version.workspace = true description = "A `forc` plugin for constructing transactions." authors.workspace = true edition.workspace = true @@ -16,12 +16,12 @@ name = "forc-tx" path = "src/main.rs" [dependencies] -anyhow = "1" -clap = { version = "4.5.4", features = ["derive", "env"] } -devault = "0.1" -forc-util = { version = "0.60.0", path = "../../forc-util" } -fuel-tx = { workspace = true, features = ["serde", "test-helpers", "random"] } +anyhow.workspace = true +clap = { workspace = true, features = ["derive", "env"] } +devault.workspace = true +forc-util.workspace = true +fuel-tx = { workspace = true, features = ["random", "test-helpers"] } fuel-types = { workspace = true, features = ["serde"] } -serde = "1.0" -serde_json = { version = "1" } -thiserror = "1" +serde.workspace = true +serde_json.workspace = true +thiserror.workspace = true diff --git a/forc-test/Cargo.toml b/forc-test/Cargo.toml index 70f7476dec9..3034b60dfbf 100644 --- a/forc-test/Cargo.toml +++ b/forc-test/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "forc-test" -version = "0.60.0" +version.workspace = true description = "A library for building and running Sway unit tests within Forc packages." authors.workspace = true edition.workspace = true @@ -9,13 +9,13 @@ license.workspace = true repository.workspace = true [dependencies] -anyhow = "1" -forc-pkg = { version = "0.60.0", path = "../forc-pkg" } -fuel-abi-types = { workspace = true } +anyhow.workspace = true +forc-pkg.workspace = true +fuel-abi-types.workspace = true fuel-tx = { workspace = true, features = ["test-helpers"] } fuel-vm = { workspace = true, features = ["random", "test-helpers"] } -fuels-core = { workspace = true } -rand = "0.8" -rayon = "1.7.0" -sway-core = { version = "0.60.0", path = "../sway-core" } -sway-types = { version = "0.60.0", path = "../sway-types" } +fuels-core.workspace = true +rand.workspace = true +rayon.workspace = true +sway-core.workspace = true +sway-types.workspace = true diff --git a/forc-test/src/execute.rs b/forc-test/src/execute.rs index a2c6fe5eda5..3436261af94 100644 --- a/forc-test/src/execute.rs +++ b/forc-test/src/execute.rs @@ -16,14 +16,14 @@ use rand::{Rng, SeedableRng}; use tx::Receipt; -use vm::interpreter::InterpreterParams; +use vm::interpreter::{InterpreterParams, MemoryInstance}; use vm::state::DebugEval; use vm::state::ProgramState; /// An interface for executing a test within a VM [Interpreter] instance. #[derive(Debug, Clone)] pub struct TestExecutor { - pub interpreter: Interpreter, + pub interpreter: Interpreter, pub tx: vm::checked_transaction::Ready, pub test_entry: PkgTestEntry, pub name: String, @@ -118,9 +118,11 @@ impl TestExecutor { .map_err(|e| anyhow::anyhow!("{e:?}"))?; let interpreter_params = InterpreterParams::new(gas_price, &consensus_params); + let memory_instance = MemoryInstance::new(); + let interpreter = Interpreter::with_storage(memory_instance, storage, interpreter_params); Ok(TestExecutor { - interpreter: Interpreter::with_storage(storage, interpreter_params), + interpreter, tx, test_entry: test_entry.clone(), name, diff --git a/forc-test/src/lib.rs b/forc-test/src/lib.rs index 70a255e47b6..58394055d75 100644 --- a/forc-test/src/lib.rs +++ b/forc-test/src/lib.rs @@ -5,7 +5,7 @@ use crate::execute::TestExecutor; use crate::setup::{ ContractDeploymentSetup, ContractTestSetup, DeploymentSetup, ScriptTestSetup, TestSetup, }; -use forc_pkg as pkg; +use forc_pkg::{self as pkg, BuildOpts}; use fuel_abi_types::error_codes::ErrorSignal; use fuel_tx as tx; use fuel_vm::checked_transaction::builder::TransactionBuilderExt; @@ -23,7 +23,7 @@ use sway_core::BuildTarget; use sway_types::Span; use tx::consensus_parameters::ConsensusParametersV1; use tx::{ConsensusParameters, ContractParameters, ScriptParameters, TxParameters}; -use vm::interpreter::InterpreterParams; +use vm::interpreter::{InterpreterParams, MemoryInstance}; use vm::prelude::SecretKey; /// The result of a `forc test` invocation. @@ -209,8 +209,12 @@ impl PackageWithDeploymentToTest { let params = maxed_consensus_params(); let storage = vm::storage::MemoryStorage::default(); let interpreter_params = InterpreterParams::new(gas_price, params.clone()); - let mut interpreter: vm::prelude::Interpreter<_, _, vm::interpreter::NotSupportedEcal> = - vm::interpreter::Interpreter::with_storage(storage, interpreter_params); + let mut interpreter: vm::prelude::Interpreter<_, _, _, vm::interpreter::NotSupportedEcal> = + vm::interpreter::Interpreter::with_storage( + MemoryInstance::new(), + storage, + interpreter_params, + ); // Iterate and create deployment transactions for contract dependencies of the root // contract. @@ -597,8 +601,8 @@ impl BuiltTests { /// First builds the package or workspace, ready for execution. pub fn build(opts: TestOpts) -> anyhow::Result { - let build_opts = opts.into(); - let build_plan = pkg::BuildPlan::from_build_opts(&build_opts)?; + let build_opts: BuildOpts = opts.into(); + let build_plan = pkg::BuildPlan::from_pkg_opts(&build_opts.pkg)?; let built = pkg::build_with_options(&build_opts)?; BuiltTests::from_built(built, &build_plan) } @@ -668,7 +672,9 @@ pub fn decode_log_data( program_abi: &ProgramABI, ) -> anyhow::Result { let program_abi = match program_abi { - ProgramABI::Fuel(fuel_abi) => Some(fuel_abi), + ProgramABI::Fuel(fuel_abi) => Some( + fuel_abi_types::abi::unified_program::UnifiedProgramABI::from_counterpart(fuel_abi)?, + ), _ => None, } .ok_or_else(|| anyhow::anyhow!("only fuelvm is supported for log decoding"))?; diff --git a/forc-tracing/Cargo.toml b/forc-tracing/Cargo.toml index 24fec50a2d2..85240eec345 100644 --- a/forc-tracing/Cargo.toml +++ b/forc-tracing/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "forc-tracing" -version = "0.60.0" +version.workspace = true description = "Tracing utility shared between forc crates." authors.workspace = true edition.workspace = true @@ -9,6 +9,9 @@ license.workspace = true repository.workspace = true [dependencies] -ansi_term = "0.12" -tracing = "0.1" -tracing-subscriber = { version = "0.3", features = ["ansi", "env-filter", "json"] } +ansi_term.workspace = true +tracing.workspace = true +tracing-subscriber = { workspace = true, features = ["ansi", "env-filter", "json"] } + +[dev-dependencies] +tracing-test = "0.2" \ No newline at end of file diff --git a/forc-tracing/src/lib.rs b/forc-tracing/src/lib.rs index 7411091da19..656cb14ca14 100644 --- a/forc-tracing/src/lib.rs +++ b/forc-tracing/src/lib.rs @@ -4,11 +4,43 @@ use ansi_term::Colour; use std::str; use std::{env, io}; use tracing::{Level, Metadata}; -use tracing_subscriber::{ +pub use tracing_subscriber::{ + self, filter::{EnvFilter, LevelFilter}, - fmt::MakeWriter, + fmt::{format::FmtSpan, MakeWriter}, }; +const ACTION_COLUMN_WIDTH: usize = 12; + +/// Returns the indentation for the action prefix relative to [ACTION_COLUMN_WIDTH]. +fn get_action_indentation(action: &str) -> String { + if action.len() < ACTION_COLUMN_WIDTH { + " ".repeat(ACTION_COLUMN_WIDTH - action.len()) + } else { + "".to_string() + } +} + +/// Prints an action message with a green-bold prefix like " Compiling ". +pub fn println_action_green(action: &str, txt: &str) { + tracing::info!( + "{}{} {}", + get_action_indentation(action), + Colour::Green.bold().paint(action), + txt + ); +} + +/// Prints an action message with a red-bold prefix like " Removing ". +pub fn println_action_red(action: &str, txt: &str) { + tracing::info!( + "{}{} {}", + get_action_indentation(action), + Colour::Red.bold().paint(action), + txt + ); +} + /// Prints a warning message to stdout with the yellow prefix "warning: ". pub fn println_warning(txt: &str) { tracing::warn!("{}: {}", Colour::Yellow.paint("warning"), txt); @@ -52,8 +84,8 @@ const LOG_FILTER: &str = "RUST_LOG"; // This allows us to write ERROR and WARN level logs to stderr and everything else to stdout. // https://docs.rs/tracing-subscriber/latest/tracing_subscriber/fmt/trait.MakeWriter.html -struct StdioTracingWriter { - writer_mode: TracingWriterMode, +pub struct StdioTracingWriter { + pub writer_mode: TracingWriterMode, } impl<'a> MakeWriter<'a> for StdioTracingWriter { @@ -111,7 +143,6 @@ pub fn init_tracing_subscriber(options: TracingSubscriberOptions) { Some(_) => EnvFilter::try_from_default_env().expect("Invalid `RUST_LOG` provided"), None => EnvFilter::new("info"), }; - let level_filter = options .log_level .or_else(|| { @@ -148,3 +179,39 @@ pub fn init_tracing_subscriber(options: TracingSubscriberOptions) { builder.init(); } } + +#[cfg(test)] +mod tests { + use super::*; + use tracing_test::traced_test; + + #[traced_test] + #[test] + fn test_println_action_green() { + let txt = "main.sw"; + println_action_green("Compiling", txt); + + let expected_action = "\x1b[1;32mCompiling\x1b[0m"; + assert!(logs_contain(&format!(" {} {}", expected_action, txt))); + } + + #[traced_test] + #[test] + fn test_println_action_green_long() { + let txt = "main.sw"; + println_action_green("Supercalifragilistic", txt); + + let expected_action = "\x1b[1;32mSupercalifragilistic\x1b[0m"; + assert!(logs_contain(&format!("{} {}", expected_action, txt))); + } + + #[traced_test] + #[test] + fn test_println_action_red() { + let txt = "main"; + println_action_red("Removing", txt); + + let expected_action = "\x1b[1;31mRemoving\x1b[0m"; + assert!(logs_contain(&format!(" {} {}", expected_action, txt))); + } +} diff --git a/forc-util/Cargo.toml b/forc-util/Cargo.toml index 3baf7848b75..f224c3028cb 100644 --- a/forc-util/Cargo.toml +++ b/forc-util/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "forc-util" -version = "0.60.0" +version.workspace = true description = "Utility items shared between forc crates." authors.workspace = true edition.workspace = true @@ -9,31 +9,31 @@ license.workspace = true repository.workspace = true [dependencies] -annotate-snippets = { version = "0.10.1" } -ansi_term = "0.12" -anyhow = "1" -clap = { version = "4.5.4", features = ["cargo", "derive", "env"] } -dirs = "3.0.2" -fd-lock = "4.0" -forc-tracing = { version = "0.60.0", path = "../forc-tracing" } -fuel-tx = { workspace = true, features = ["serde"], optional = true } -hex = "0.4.3" -paste = "1.0.14" -regex = "1.10.2" -serde = { version = "1.0", features = ["derive"] } -serde_json = "1.0.73" -serial_test = "3.0.0" -sway-core = { version = "0.60.0", path = "../sway-core" } -sway-error = { version = "0.60.0", path = "../sway-error" } -sway-types = { version = "0.60.0", path = "../sway-types" } -sway-utils = { version = "0.60.0", path = "../sway-utils" } -tracing = "0.1" -tracing-subscriber = { version = "0.3", features = [ +annotate-snippets.workspace = true +ansi_term.workspace = true +anyhow.workspace = true +clap = { workspace = true, features = ["cargo", "derive", "env"] } +dirs.workspace = true +fd-lock.workspace = true +forc-tracing.workspace = true +fuel-tx = { workspace = true, optional = true } +hex.workspace = true +paste.workspace = true +regex.workspace = true +serde = { workspace = true, features = ["derive"] } +serde_json.workspace = true +serial_test.workspace = true +sway-core.workspace = true +sway-error.workspace = true +sway-types.workspace = true +sway-utils.workspace = true +tracing.workspace = true +tracing-subscriber = { workspace = true, features = [ "ansi", "env-filter", "json", ] } -unicode-xid = "0.2.2" +unicode-xid.workspace = true [features] default = ["fuel-tx"] diff --git a/forc-util/src/fs_locking.rs b/forc-util/src/fs_locking.rs index 23772bc6d30..8e6f438337b 100644 --- a/forc-util/src/fs_locking.rs +++ b/forc-util/src/fs_locking.rs @@ -35,7 +35,7 @@ impl PidFileLocking { } /// Checks if the given pid is active - #[cfg(not(target = "windows"))] + #[cfg(not(target_os = "windows"))] fn is_pid_active(pid: usize) -> bool { // Not using sysinfo here because it has compatibility issues with fuel.nix // https://github.com/FuelLabs/fuel.nix/issues/64 @@ -50,7 +50,7 @@ impl PidFileLocking { output_str.contains(&format!("{} ", pid)) } - #[cfg(target = "windows")] + #[cfg(target_os = "windows")] fn is_pid_active(pid: usize) -> bool { // Not using sysinfo here because it has compatibility issues with fuel.nix // https://github.com/FuelLabs/fuel.nix/issues/64 diff --git a/forc-util/src/lib.rs b/forc-util/src/lib.rs index da996311fc2..7cf7f45b2b4 100644 --- a/forc-util/src/lib.rs +++ b/forc-util/src/lib.rs @@ -3,9 +3,8 @@ use annotate_snippets::{ renderer::{AnsiColor, Style}, Annotation, AnnotationType, Renderer, Slice, Snippet, SourceAnnotation, }; -use ansi_term::Colour; use anyhow::{bail, Context, Result}; -use forc_tracing::{println_error, println_red_err, println_yellow_err}; +use forc_tracing::{println_action_green, println_error, println_red_err, println_yellow_err}; use std::{ collections::{hash_map, HashSet}, fmt::Display, @@ -346,10 +345,9 @@ pub fn print_compiling(ty: Option<&TreeType>, name: &str, src: &dyn std::fmt::Di Some(ty) => format!("{} ", program_type_str(ty)), None => "".to_string(), }; - tracing::debug!( - " {} {ty}{} ({src})", - Colour::Green.bold().paint("Compiling"), - ansi_term::Style::new().bold().paint(name) + println_action_green( + "Compiling", + &format!("{ty}{} ({src})", ansi_term::Style::new().bold().paint(name)), ); } @@ -718,43 +716,104 @@ fn construct_window<'a>( let total_lines_of_highlight = end.line - start.line; debug_assert!(total_lines_in_input >= total_lines_of_highlight); - let mut current_line = 0; - let mut lines_to_start_of_snippet = 0; - let mut calculated_start_ix = None; - let mut calculated_end_ix = None; - let mut pos = 0; - for character in input.chars() { + let mut current_line = 1usize; + + let mut chars = input.char_indices().map(|(char_offset, character)| { + let r = (current_line, char_offset); if character == '\n' { - current_line += 1 + current_line += 1; } + r + }); - if current_line + NUM_LINES_BUFFER >= start.line && calculated_start_ix.is_none() { - calculated_start_ix = Some(pos); - lines_to_start_of_snippet = current_line; - } + // Find the first char of the first line + let first_char = chars + .by_ref() + .find(|(current_line, _)| current_line + NUM_LINES_BUFFER >= start.line); - if current_line >= end.line + NUM_LINES_BUFFER && calculated_end_ix.is_none() { - calculated_end_ix = Some(pos); - } + // Find the last char of the last line + let last_char = chars + .by_ref() + .find(|(current_line, _)| *current_line > end.line + NUM_LINES_BUFFER) + .map(|x| x.1); - if calculated_start_ix.is_some() && calculated_end_ix.is_some() { - break; + // this releases the borrow of `current_line` + drop(chars); + + let (first_char_line, first_char_offset, last_char_offset) = match (first_char, last_char) { + // has first and last + (Some((first_char_line, first_char_offset)), Some(last_char_offset)) => { + (first_char_line, first_char_offset, last_char_offset) } - pos += character.len_utf8(); + // has first and no last + (Some((first_char_line, first_char_offset)), None) => { + (first_char_line, first_char_offset, input.len()) + } + // others + _ => (current_line, input.len(), input.len()), + }; + + // adjust indices to be inside the returned window + start.line = first_char_line; + *start_ix = start_ix.saturating_sub(first_char_offset); + *end_ix = end_ix.saturating_sub(first_char_offset); + + &input[first_char_offset..last_char_offset] +} + +#[test] +fn ok_construct_window() { + fn t( + start_line: usize, + start_col: usize, + end_line: usize, + end_col: usize, + start_char: usize, + end_char: usize, + input: &str, + ) -> (usize, usize, &str) { + let mut s = LineCol { + line: start_line, + col: start_col, + }; + let mut start = start_char; + let mut end = end_char; + let r = construct_window( + &mut s, + LineCol { + line: end_line, + col: end_col, + }, + &mut start, + &mut end, + input, + ); + (start, end, r) } - let calculated_start_ix = calculated_start_ix.unwrap_or(0); - let calculated_end_ix = calculated_end_ix.unwrap_or(input.len()); - let start_ix_bytes = *start_ix - std::cmp::min(calculated_start_ix, *start_ix); - let end_ix_bytes = *end_ix - std::cmp::min(calculated_start_ix, *end_ix); - // We want the start_ix and end_ix in terms of chars and not bytes, so translate. - *start_ix = input[calculated_start_ix..(calculated_start_ix + start_ix_bytes)] - .chars() - .count(); - *end_ix = input[calculated_start_ix..(calculated_start_ix + end_ix_bytes)] - .chars() - .count(); - - start.line = lines_to_start_of_snippet; - &input[calculated_start_ix..calculated_end_ix] + // Invalid Empty file + assert_eq!(t(0, 0, 0, 0, 0, 0, ""), (0, 0, "")); + + // Valid Empty File + assert_eq!(t(1, 1, 1, 1, 0, 0, ""), (0, 0, "")); + + // One line, error after the last char + assert_eq!(t(1, 7, 1, 7, 6, 6, "script"), (6, 6, "script")); + + // 01 23 45 67 89 AB CD E + let eight_lines = "1\n2\n3\n4\n5\n6\n7\n8"; + + assert_eq!(t(1, 1, 1, 1, 0, 1, eight_lines), (0, 1, "1\n2\n3\n")); + assert_eq!(t(2, 1, 2, 1, 2, 3, eight_lines), (2, 3, "1\n2\n3\n4\n")); + assert_eq!(t(3, 1, 3, 1, 4, 5, eight_lines), (4, 5, "1\n2\n3\n4\n5\n")); + assert_eq!(t(4, 1, 4, 1, 6, 7, eight_lines), (4, 5, "2\n3\n4\n5\n6\n")); + assert_eq!(t(5, 1, 5, 1, 8, 9, eight_lines), (4, 5, "3\n4\n5\n6\n7\n")); + assert_eq!(t(6, 1, 6, 1, 10, 11, eight_lines), (4, 5, "4\n5\n6\n7\n8")); + assert_eq!(t(7, 1, 7, 1, 12, 13, eight_lines), (4, 5, "5\n6\n7\n8")); + assert_eq!(t(8, 1, 8, 1, 14, 15, eight_lines), (4, 5, "6\n7\n8")); + + // Invalid lines + assert_eq!(t(9, 1, 9, 1, 14, 15, eight_lines), (2, 3, "7\n8")); + assert_eq!(t(10, 1, 10, 1, 14, 15, eight_lines), (0, 1, "8")); + assert_eq!(t(11, 1, 11, 1, 14, 15, eight_lines), (0, 0, "")); } diff --git a/forc/Cargo.toml b/forc/Cargo.toml index 8f6c5aa04e7..2f5d6dda481 100644 --- a/forc/Cargo.toml +++ b/forc/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "forc" -version = "0.60.0" +version.workspace = true description = "Fuel Orchestrator." authors.workspace = true edition.workspace = true @@ -17,35 +17,35 @@ name = "forc" path = "src/main.rs" [dependencies] -annotate-snippets = { version = "0.10.1" } -ansi_term = "0.12" -anyhow = "1.0.41" -clap = { version = "4.5.4", features = ["cargo", "derive", "env"] } -clap_complete = "4.5.2" -clap_complete_fig = "4.5.0" -forc-pkg = { version = "0.60.0", path = "../forc-pkg" } -forc-test = { version = "0.60.0", path = "../forc-test" } -forc-tracing = { version = "0.60.0", path = "../forc-tracing" } -forc-util = { version = "0.60.0", path = "../forc-util" } -fs_extra = "1.2" -fuel-asm = { workspace = true } -hex = "0.4.3" -serde = { version = "1.0", features = ["derive"] } -serde_json = "1.0.73" -sway-core = { version = "0.60.0", path = "../sway-core" } -sway-error = { version = "0.60.0", path = "../sway-error" } -sway-ir = { version = "0.60.0", path = "../sway-ir" } -sway-types = { version = "0.60.0", path = "../sway-types" } -sway-utils = { version = "0.60.0", path = "../sway-utils" } -term-table = "1.3" -tokio = { version = "1.8.0", features = ["macros", "rt-multi-thread"] } -toml = { version = "0.7", features = ["parse"] } -toml_edit = "0.19" -tracing = "0.1" -url = "2.2" -uwuify = { version = "^0.2", optional = true } -walkdir = "2.3" -whoami = "1.1" +annotate-snippets.workspace = true +ansi_term.workspace = true +anyhow.workspace = true +clap = { workspace = true, features = ["cargo", "derive", "env"] } +clap_complete.workspace = true +clap_complete_fig.workspace = true +forc-pkg.workspace = true +forc-test.workspace = true +forc-tracing.workspace = true +forc-util.workspace = true +fs_extra.workspace = true +fuel-asm.workspace = true +hex.workspace = true +serde = { workspace = true, features = ["derive"] } +serde_json.workspace = true +sway-core.workspace = true +sway-error.workspace = true +sway-ir.workspace = true +sway-types.workspace = true +sway-utils.workspace = true +term-table.workspace = true +tokio = { workspace = true, features = ["macros", "rt-multi-thread"] } +toml = { workspace = true, features = ["parse"] } +toml_edit.workspace = true +tracing.workspace = true +url.workspace = true +uwuify = { workspace = true, optional = true } +walkdir.workspace = true +whoami.workspace = true [features] default = [] @@ -55,3 +55,4 @@ uwu = ["uwuify"] [dev-dependencies] completest-pty = "0.5.0" +rexpect = "0.5" diff --git a/forc/src/cli/commands/completions.rs b/forc/src/cli/commands/completions.rs index ffa06fa9286..cf4b0160173 100644 --- a/forc/src/cli/commands/completions.rs +++ b/forc/src/cli/commands/completions.rs @@ -1,3 +1,5 @@ +use std::fmt::Display; + use clap::{Command as ClapCommand, CommandFactory, Parser}; use clap_complete::{generate, Generator, Shell}; use forc_util::ForcResult; @@ -18,16 +20,20 @@ enum Target { Fig, } -impl ToString for Target { - fn to_string(&self) -> String { - match self { - Target::Bash => "bash".to_string(), - Target::Elvish => "elvish".to_string(), - Target::Fish => "fish".to_string(), - Target::PowerShell => "powershell".to_string(), - Target::Zsh => "zsh".to_string(), - Target::Fig => "fig".to_string(), - } +impl Display for Target { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!( + f, + "{}", + match self { + Target::Bash => "bash".to_string(), + Target::Elvish => "elvish".to_string(), + Target::Fish => "fish".to_string(), + Target::PowerShell => "powershell".to_string(), + Target::Zsh => "zsh".to_string(), + Target::Fig => "fig".to_string(), + } + ) } } diff --git a/forc/src/cli/commands/parse_bytecode.rs b/forc/src/cli/commands/parse_bytecode.rs index 2b8957e3f2c..f4a30c82d6d 100644 --- a/forc/src/cli/commands/parse_bytecode.rs +++ b/forc/src/cli/commands/parse_bytecode.rs @@ -62,7 +62,10 @@ pub(crate) fn exec(command: Command) -> ForcResult<()> { Ok(_) | Err(fuel_asm::InvalidOpcode) => "".into(), }; table.add_row(Row::new(vec![ - TableCell::new_with_alignment(word_ix, 1, Alignment::Right), + TableCell::builder(word_ix) + .col_span(1) + .alignment(Alignment::Right) + .build(), TableCell::new(word_ix * 4), TableCell::new(match result { Ok(inst) => format!("{inst:?}"), diff --git a/forc/src/cli/commands/test.rs b/forc/src/cli/commands/test.rs index f8e4001fa42..5ffa1c51d75 100644 --- a/forc/src/cli/commands/test.rs +++ b/forc/src/cli/commands/test.rs @@ -3,6 +3,7 @@ use ansi_term::Colour; use clap::Parser; use forc_pkg as pkg; use forc_test::{decode_log_data, TestFilter, TestRunnerCount, TestedPackage}; +use forc_tracing::println_action_green; use forc_util::{tx_utils::format_log_receipts, ForcError, ForcResult}; use pkg::manifest::build_profile::ExperimentalFlags; use sway_core::fuel_prelude::fuel_tx::Receipt; @@ -60,16 +61,15 @@ pub struct Command { #[derive(Parser, Debug, Clone)] #[clap(after_help = help())] pub struct TestPrintOpts { - #[clap(long = "pretty-print", short = 'r')] + #[clap(long = "pretty")] /// Pretty-print the logs emitted from tests. pub pretty_print: bool, /// Print `Log` and `LogData` receipts for tests. #[clap(long = "logs", short = 'l')] pub print_logs: bool, - /// Decode logs and show decoded log information in human readable format alongside the raw - /// logs. - #[clap(long = "decode", short = 'd')] - pub decode_logs: bool, + /// Print the raw logs for tests. + #[clap(long)] + pub raw_logs: bool, } pub(crate) fn exec(cmd: Command) -> ForcResult<()> { @@ -90,12 +90,15 @@ pub(crate) fn exec(cmd: Command) -> ForcResult<()> { let test_count = built_tests.test_count(test_filter.as_ref()); let num_tests_running = test_count.total - test_count.ignored; let num_tests_ignored = test_count.ignored; - info!( - " Running {} {}, filtered {} {}", - num_tests_running, - formatted_test_count_string(&num_tests_running), - num_tests_ignored, - formatted_test_count_string(&num_tests_ignored) + println_action_green( + "Running", + &format!( + "{} {}, filtered {} {}", + num_tests_running, + formatted_test_count_string(&num_tests_running), + num_tests_ignored, + formatted_test_count_string(&num_tests_ignored) + ), ); let tested = built_tests.run(test_runner_count, test_filter)?; let duration = start.elapsed(); @@ -105,10 +108,11 @@ pub(crate) fn exec(cmd: Command) -> ForcResult<()> { forc_test::Tested::Workspace(pkgs) => { for pkg in &pkgs { let built = &pkg.built.descriptor.name; - info!("\n tested -- {built}\n"); + info!("\ntested -- {built}\n"); print_tested_pkg(pkg, &test_print_opts)?; } - info!("\n Finished in {:?}", duration); + info!(""); + println_action_green("Finished", &format!("in {:?}", duration)); pkgs.iter().all(|pkg| pkg.tests_passed()) } forc_test::Tested::Package(pkg) => { @@ -145,26 +149,26 @@ fn print_tested_pkg(pkg: &TestedPackage, test_print_opts: &TestPrintOpts) -> For ); // If logs are enabled, print them. + let logs = &test.logs; if test_print_opts.print_logs { - let logs = &test.logs; - if test_print_opts.decode_logs { - for log in logs { - if let Receipt::LogData { - rb, - data: Some(data), - .. - } = log - { - let decoded_log_data = - decode_log_data(&rb.to_string(), data, &pkg.built.program_abi)?; - let var_value = decoded_log_data.value; - info!("Decoded log value: {}, log rb: {}", var_value, rb); - } + for log in logs { + if let Receipt::LogData { + rb, + data: Some(data), + .. + } = log + { + let decoded_log_data = + decode_log_data(&rb.to_string(), data, &pkg.built.program_abi)?; + let var_value = decoded_log_data.value; + info!("Decoded log value: {}, log rb: {}", var_value, rb); } - info!("Raw logs:"); } + } + + if test_print_opts.raw_logs { let formatted_logs = format_log_receipts(logs, test_print_opts.pretty_print)?; - info!("{}", formatted_logs); + info!("Raw logs:\n{}", formatted_logs); } // If the test is failing, save the test result for printing the details later on. @@ -210,7 +214,7 @@ fn print_tested_pkg(pkg: &TestedPackage, test_print_opts: &TestPrintOpts) -> For .map(|test_result| test_result.duration) .sum(); info!( - " Result: {}. {} passed. {} failed. Finished in {:?}.", + "\ntest result: {}. {} passed; {} failed; finished in {:?}", color.paint(state), succeeded, failed, @@ -228,7 +232,6 @@ fn opts_from_cmd(cmd: Command) -> forc_test::TestOpts { terse: cmd.build.pkg.terse, locked: cmd.build.pkg.locked, output_directory: cmd.build.pkg.output_directory, - json_abi_with_callpaths: cmd.build.pkg.json_abi_with_callpaths, ipfs_node: cmd.build.pkg.ipfs_node.unwrap_or_default(), }, print: pkg::PrintOpts { @@ -237,6 +240,7 @@ fn opts_from_cmd(cmd: Command) -> forc_test::TestOpts { dca_graph_url_format: cmd.build.print.dca_graph_url_format.clone(), asm: cmd.build.print.asm(), bytecode: cmd.build.print.bytecode, + bytecode_spans: false, ir: cmd.build.print.ir(), reverse_order: cmd.build.print.reverse_order, }, diff --git a/forc/src/cli/shared.rs b/forc/src/cli/shared.rs index 313edcd08b1..28b38465df3 100644 --- a/forc/src/cli/shared.rs +++ b/forc/src/cli/shared.rs @@ -150,9 +150,6 @@ pub struct Pkg { /// If the lock file is missing, or it needs to be updated, Forc will exit with an error. #[clap(long)] pub locked: bool, - /// Outputs JSON ABI with callpaths instead of only names for structs and enums. - #[clap(long)] - pub json_abi_with_callpaths: bool, /// The IPFS node to use for fetching IPFS sources. /// /// [possible values: PUBLIC, LOCAL, ] diff --git a/forc/src/ops/forc_build.rs b/forc/src/ops/forc_build.rs index 35a03b611a7..49c0c27f955 100644 --- a/forc/src/ops/forc_build.rs +++ b/forc/src/ops/forc_build.rs @@ -17,7 +17,6 @@ fn opts_from_cmd(cmd: BuildCommand) -> pkg::BuildOpts { terse: cmd.build.pkg.terse, locked: cmd.build.pkg.locked, output_directory: cmd.build.pkg.output_directory, - json_abi_with_callpaths: cmd.build.pkg.json_abi_with_callpaths, ipfs_node: cmd.build.pkg.ipfs_node.unwrap_or_default(), }, print: pkg::PrintOpts { @@ -26,6 +25,7 @@ fn opts_from_cmd(cmd: BuildCommand) -> pkg::BuildOpts { dca_graph_url_format: cmd.build.print.dca_graph_url_format.clone(), asm: cmd.build.print.asm(), bytecode: cmd.build.print.bytecode, + bytecode_spans: false, ir: cmd.build.print.ir(), reverse_order: cmd.build.print.reverse_order, }, diff --git a/forc/src/ops/forc_contract_id.rs b/forc/src/ops/forc_contract_id.rs index 3a6d975ac40..f81441637a5 100644 --- a/forc/src/ops/forc_contract_id.rs +++ b/forc/src/ops/forc_contract_id.rs @@ -8,7 +8,7 @@ use tracing::info; pub fn contract_id(command: ContractIdCommand) -> Result<()> { let build_options = build_opts_from_cmd(&command); - let build_plan = pkg::BuildPlan::from_build_opts(&build_options)?; + let build_plan = pkg::BuildPlan::from_pkg_opts(&build_options.pkg)?; // If a salt was specified but we have more than one member to build, there // may be ambiguity in how the salt should be applied, especially if the // workspace contains multiple contracts, and especially if one contract @@ -52,7 +52,6 @@ fn build_opts_from_cmd(cmd: &ContractIdCommand) -> pkg::BuildOpts { terse: cmd.pkg.terse, locked: cmd.pkg.locked, output_directory: cmd.pkg.output_directory.clone(), - json_abi_with_callpaths: cmd.pkg.json_abi_with_callpaths, ipfs_node: cmd.pkg.ipfs_node.clone().unwrap_or_default(), }, print: pkg::PrintOpts { @@ -61,6 +60,7 @@ fn build_opts_from_cmd(cmd: &ContractIdCommand) -> pkg::BuildOpts { dca_graph_url_format: cmd.print.dca_graph_url_format.clone(), asm: cmd.print.asm(), bytecode: cmd.print.bytecode, + bytecode_spans: false, ir: cmd.print.ir(), reverse_order: cmd.print.reverse_order, }, diff --git a/forc/src/ops/forc_predicate_root.rs b/forc/src/ops/forc_predicate_root.rs index febf7b96ca6..1381aec392e 100644 --- a/forc/src/ops/forc_predicate_root.rs +++ b/forc/src/ops/forc_predicate_root.rs @@ -21,7 +21,6 @@ fn build_opts_from_cmd(cmd: PredicateRootCommand) -> pkg::BuildOpts { terse: cmd.pkg.terse, locked: cmd.pkg.locked, output_directory: cmd.pkg.output_directory.clone(), - json_abi_with_callpaths: cmd.pkg.json_abi_with_callpaths, ipfs_node: cmd.pkg.ipfs_node.unwrap_or_default(), }, print: pkg::PrintOpts { @@ -30,6 +29,7 @@ fn build_opts_from_cmd(cmd: PredicateRootCommand) -> pkg::BuildOpts { dca_graph_url_format: cmd.print.dca_graph_url_format.clone(), asm: cmd.print.asm(), bytecode: cmd.print.bytecode, + bytecode_spans: false, ir: cmd.print.ir(), reverse_order: cmd.print.reverse_order, }, diff --git a/forc/src/ops/forc_template.rs b/forc/src/ops/forc_template.rs index 07a0b5846bb..0304a9d298a 100644 --- a/forc/src/ops/forc_template.rs +++ b/forc/src/ops/forc_template.rs @@ -4,6 +4,7 @@ use forc_pkg::{ manifest::{self, PackageManifest}, source::{self, git::Url}, }; +use forc_tracing::println_action_green; use forc_util::validate_project_name; use fs_extra::dir::{copy, CopyOptions}; use std::fs::File; @@ -11,7 +12,6 @@ use std::io::{Read, Write}; use std::path::{Path, PathBuf}; use std::{env, str::FromStr}; use sway_utils::constants; -use tracing::info; pub fn init(command: TemplateCommand) -> Result<()> { validate_project_name(&command.project_name)?; @@ -31,7 +31,7 @@ pub fn init(command: TemplateCommand) -> Result<()> { let fetch_ts = std::time::Instant::now(); let fetch_id = source::fetch_id(current_dir, fetch_ts); - info!("Resolving the HEAD of {}", source.repo); + println_action_green("Resolving", &format!("the HEAD of {}", source.repo)); let git_source = source::git::pin(fetch_id, &local_repo_name, source)?; let repo_path = source::git::commit_path( @@ -40,7 +40,7 @@ pub fn init(command: TemplateCommand) -> Result<()> { &git_source.commit_hash, ); if !repo_path.exists() { - info!(" Fetching {}", git_source.to_string()); + println_action_green("Fetching", git_source.to_string().as_str()); source::git::fetch(fetch_id, &local_repo_name, &git_source)?; } @@ -65,7 +65,10 @@ pub fn init(command: TemplateCommand) -> Result<()> { // Create the target dir let target_dir = current_dir.join(&command.project_name); - info!("Creating {} from template", &command.project_name); + println_action_green( + "Creating", + &format!("{} from template", &command.project_name), + ); // Copy contents from template to target dir copy_template_to_target(&from_path, &target_dir)?; @@ -81,7 +84,7 @@ fn edit_forc_toml(out_dir: &Path, project_name: &str, real_name: &str) -> Result let mut file = File::open(out_dir.join(constants::MANIFEST_FILE_NAME))?; let mut toml = String::new(); file.read_to_string(&mut toml)?; - let mut manifest_toml = toml.parse::()?; + let mut manifest_toml = toml.parse::()?; let mut authors = Vec::new(); let forc_toml: toml::Value = toml::de::from_str(&toml)?; @@ -141,7 +144,7 @@ fn edit_cargo_toml(out_dir: &Path, project_name: &str, real_name: &str) -> Resul } updated_authors.push(real_name); - let mut manifest_toml = toml.parse::()?; + let mut manifest_toml = toml.parse::()?; manifest_toml["package"]["authors"] = toml_edit::value(updated_authors); manifest_toml["package"]["name"] = toml_edit::value(project_name); diff --git a/forc/tests/cli_integration.rs b/forc/tests/cli_integration.rs new file mode 100644 index 00000000000..407cda7489d --- /dev/null +++ b/forc/tests/cli_integration.rs @@ -0,0 +1,84 @@ +use std::path::PathBuf; + +use rexpect::spawn; + +const TIMEOUT_MS: u64 = 300000; + +fn test_fixtures_path() -> PathBuf { + PathBuf::from(env!("CARGO_MANIFEST_DIR")) + .join("tests") + .join("fixtures") + .canonicalize() + .unwrap() +} + +#[test] +fn test_forc_test_decoded_logs() -> Result<(), rexpect::error::Error> { + // Spawn the forc binary using cargo run + let project_dir = test_fixtures_path().join("test_contract"); + let mut process = spawn( + &format!( + "cargo run --bin forc -- test --logs --path {}", + project_dir.to_string_lossy() + ), + Some(TIMEOUT_MS), + )?; + + // Assert that the output is correct + process.exp_string(" test test_log_4")?; + process.exp_string("Decoded log value: 4, log rb: 1515152261580153489")?; + process.exp_string(" test test_log_2")?; + process.exp_string("Decoded log value: 2, log rb: 1515152261580153489")?; + + process.process.exit()?; + Ok(()) +} + +#[test] +fn test_forc_test_raw_logs() -> Result<(), rexpect::error::Error> { + // Spawn the forc binary using cargo run + let project_dir = test_fixtures_path().join("test_contract"); + let mut process = spawn( + &format!( + "cargo run --bin forc -- test --raw-logs --path {}", + project_dir.to_string_lossy() + ), + Some(TIMEOUT_MS), + )?; + + // Assert that the output is correct + process.exp_string(" test test_log_4")?; + process.exp_string("Raw logs:")?; + process.exp_string(r#"[{"LogData":{"data":"0000000000000004","digest":"8005f02d43fa06e7d0585fb64c961d57e318b27a145c857bcd3a6bdb413ff7fc","id":"0000000000000000000000000000000000000000000000000000000000000000","is":10368,"len":8,"pc":12652,"ptr":67107840,"ra":0,"rb":1515152261580153489}}]"#)?; + process.exp_string(" test test_log_2")?; + process.exp_string("Raw logs:")?; + process.exp_string(r#"[{"LogData":{"data":"0000000000000002","digest":"cd04a4754498e06db5a13c5f371f1f04ff6d2470f24aa9bd886540e5dce77f70","id":"0000000000000000000000000000000000000000000000000000000000000000","is":10368,"len":8,"pc":12652,"ptr":67107840,"ra":0,"rb":1515152261580153489}}]"#)?; + + process.process.exit()?; + Ok(()) +} + +#[test] +fn test_forc_test_both_logs() -> Result<(), rexpect::error::Error> { + // Spawn the forc binary using cargo run + let project_dir = test_fixtures_path().join("test_contract"); + let mut process = spawn( + &format!( + "cargo run --bin forc -- test --logs --raw-logs --path {}", + project_dir.to_string_lossy() + ), + Some(TIMEOUT_MS), + )?; + + // Assert that the output is correct + process.exp_string(" test test_log_4")?; + process.exp_string("Decoded log value: 4, log rb: 1515152261580153489")?; + process.exp_string("Raw logs:")?; + process.exp_string(r#"[{"LogData":{"data":"0000000000000004","digest":"8005f02d43fa06e7d0585fb64c961d57e318b27a145c857bcd3a6bdb413ff7fc","id":"0000000000000000000000000000000000000000000000000000000000000000","is":10368,"len":8,"pc":12652,"ptr":67107840,"ra":0,"rb":1515152261580153489}}]"#)?; + process.exp_string(" test test_log_2")?; + process.exp_string("Decoded log value: 2, log rb: 1515152261580153489")?; + process.exp_string("Raw logs:")?; + process.exp_string(r#"[{"LogData":{"data":"0000000000000002","digest":"cd04a4754498e06db5a13c5f371f1f04ff6d2470f24aa9bd886540e5dce77f70","id":"0000000000000000000000000000000000000000000000000000000000000000","is":10368,"len":8,"pc":12652,"ptr":67107840,"ra":0,"rb":1515152261580153489}}]"#)?; + process.process.exit()?; + Ok(()) +} diff --git a/forc/tests/fixtures/test_contract/.gitignore b/forc/tests/fixtures/test_contract/.gitignore new file mode 100644 index 00000000000..77d3844f58c --- /dev/null +++ b/forc/tests/fixtures/test_contract/.gitignore @@ -0,0 +1,2 @@ +out +target diff --git a/forc/tests/fixtures/test_contract/Forc.lock b/forc/tests/fixtures/test_contract/Forc.lock new file mode 100644 index 00000000000..943d47b39ef --- /dev/null +++ b/forc/tests/fixtures/test_contract/Forc.lock @@ -0,0 +1,13 @@ +[[package]] +name = "core" +source = "path+from-root-4D4735C41181917E" + +[[package]] +name = "std" +source = "path+from-root-4D4735C41181917E" +dependencies = ["core"] + +[[package]] +name = "test_contract" +source = "member" +dependencies = ["std"] diff --git a/forc/tests/fixtures/test_contract/Forc.toml b/forc/tests/fixtures/test_contract/Forc.toml new file mode 100644 index 00000000000..4342f8dbc65 --- /dev/null +++ b/forc/tests/fixtures/test_contract/Forc.toml @@ -0,0 +1,8 @@ +[project] +authors = ["Fuel Labs "] +entry = "main.sw" +license = "Apache-2.0" +name = "test_contract" + +[dependencies] +std = { path = "../../../../sway-lib-std/" } diff --git a/forc-plugins/forc-client/test/data/standalone_contract_b/src/main.sw b/forc/tests/fixtures/test_contract/src/main.sw similarity index 56% rename from forc-plugins/forc-client/test/data/standalone_contract_b/src/main.sw rename to forc/tests/fixtures/test_contract/src/main.sw index 7d4a75493c6..2314fa4dc47 100644 --- a/forc-plugins/forc-client/test/data/standalone_contract_b/src/main.sw +++ b/forc/tests/fixtures/test_contract/src/main.sw @@ -9,3 +9,15 @@ impl MyContract for Contract { true } } + +#[test] +fn test_log_4() { + log(4); + assert(1 == 1) +} + +#[test] +fn test_log_2() { + log(2); + assert(1 == 1) +} diff --git a/scripts/mdbook-forc-documenter/Cargo.toml b/scripts/mdbook-forc-documenter/Cargo.toml index eae79eff1ef..8db19ab6db6 100644 --- a/scripts/mdbook-forc-documenter/Cargo.toml +++ b/scripts/mdbook-forc-documenter/Cargo.toml @@ -13,9 +13,9 @@ name = "mdbook_forc_documenter" path = "src/lib.rs" [dependencies] -anyhow = "1" -clap = { version = "4.5.4", features = ["derive"] } -mdbook = { version = "0.4", default-features = false } -semver = "1.0" -serde = "1.0" -serde_json = "1.0" +anyhow.workspace = true +clap = { workspace = true, features = ["derive"] } +mdbook.workspace = true +semver.workspace = true +serde.workspace = true +serde_json.workspace = true diff --git a/scripts/mdbook-forc-documenter/src/bin/mdbook-forc-documenter.rs b/scripts/mdbook-forc-documenter/src/bin/mdbook-forc-documenter.rs index b273e9550db..1de59586abf 100644 --- a/scripts/mdbook-forc-documenter/src/bin/mdbook-forc-documenter.rs +++ b/scripts/mdbook-forc-documenter/src/bin/mdbook-forc-documenter.rs @@ -1,18 +1,21 @@ use clap::{Arg, ArgMatches, Command}; use mdbook::errors::Error; use mdbook::preprocess::{CmdPreprocessor, Preprocessor}; +use mdbook_forc_documenter::ForcDocumenter; use semver::{Version, VersionReq}; use std::io; use std::process; -use mdbook_forc_documenter::ForcDocumenter; - pub fn make_app() -> Command { Command::new("forc-documenter") .about("A mdbook preprocessor which documents Forc commands") .subcommand( Command::new("supports") - .arg(Arg::new("renderer").required(true)) + .arg( + Arg::new("renderer") + .required(true) + .value_parser(clap::value_parser!(String)), + ) .about("Check whether a renderer is supported by this preprocessor"), ) } @@ -53,7 +56,7 @@ fn handle_preprocessing(pre: &dyn Preprocessor) -> Result<(), Error> { } fn handle_supports(pre: &dyn Preprocessor, sub_args: &ArgMatches) -> ! { - let renderer: &Option<&str> = sub_args.get_one("renderer").expect("Required argument"); + let renderer = sub_args.get_one::("renderer").map(String::as_str); let supported = renderer.map(|r| pre.supports_renderer(r)).unwrap_or(false); // Signal whether the renderer is supported by exiting with 1 or 0. diff --git a/scripts/mdbook-forc-documenter/src/commands.rs b/scripts/mdbook-forc-documenter/src/commands.rs index afbda6ae985..4f1723fc9d8 100644 --- a/scripts/mdbook-forc-documenter/src/commands.rs +++ b/scripts/mdbook-forc-documenter/src/commands.rs @@ -1,11 +1,8 @@ use crate::formatter::{format_header_line, format_line}; use anyhow::{anyhow, Result}; -use std::collections::HashMap; -use std::ffi::OsString; -use std::process; +use std::{collections::HashMap, ffi::OsString, process}; pub fn possible_forc_commands() -> Vec { - let mut possible_commands = Vec::new(); let output = process::Command::new("forc") .arg("--help") .output() @@ -14,18 +11,27 @@ pub fn possible_forc_commands() -> Vec { let output_str = String::from_utf8_lossy(&output.stdout); let lines = output_str.lines(); - let mut has_parsed_subcommand_header = false; + let mut possible_commands = Vec::new(); + let mut in_commands_section = false; for line in lines { - if has_parsed_subcommand_header { - let (command, _) = line.trim().split_once(' ').unwrap_or(("", "")); - possible_commands.push(command.to_string()); + if line.trim() == "Commands:" { + // Start of commands section + in_commands_section = true; + continue; } - if line == "SUBCOMMANDS:" { - has_parsed_subcommand_header = true; + + if in_commands_section { + if line.trim().is_empty() || line.trim().starts_with("Options:") { + // End of commands section + break; + } + // Extract command name (first word of the line) + if let Some(command) = line.split_whitespace().next() { + possible_commands.push(command.to_string()); + } } } - possible_commands } diff --git a/scripts/mdbook-forc-documenter/src/formatter.rs b/scripts/mdbook-forc-documenter/src/formatter.rs index d21298363d5..883df32b82f 100644 --- a/scripts/mdbook-forc-documenter/src/formatter.rs +++ b/scripts/mdbook-forc-documenter/src/formatter.rs @@ -110,7 +110,7 @@ fn format_option_line(option_line: &str) -> String { a }) .trim() - .to_owned(); + .to_string(); break; } } diff --git a/sway-ast/Cargo.toml b/sway-ast/Cargo.toml index 1f031a959cc..ad73333213d 100644 --- a/sway-ast/Cargo.toml +++ b/sway-ast/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "sway-ast" -version = "0.60.0" +version.workspace = true description = "Sway's AST" authors.workspace = true edition.workspace = true @@ -9,12 +9,12 @@ license.workspace = true repository.workspace = true [dependencies] -extension-trait = "1.0.1" -num-bigint = { version = "0.4.3", features = ["serde"] } -num-traits = "0.2.14" -serde = { version = "1.0", features = ["derive"] } -sway-error = { version = "0.60.0", path = "../sway-error" } -sway-types = { version = "0.60.0", path = "../sway-types" } +extension-trait.workspace = true +num-bigint = { workspace = true, features = ["serde"] } +num-traits.workspace = true +serde = { workspace = true, features = ["derive"] } +sway-error.workspace = true +sway-types.workspace = true [lints.clippy] iter_over_hash_type = "deny" diff --git a/sway-ast/src/assignable.rs b/sway-ast/src/assignable.rs index 0eedcc3bf45..a6a07eb8a9b 100644 --- a/sway-ast/src/assignable.rs +++ b/sway-ast/src/assignable.rs @@ -7,6 +7,7 @@ pub enum Assignable { /// E.g.: /// - `my_variable` /// - `array[0].field.x.1` + /// /// Note that within the path, we cannot have dereferencing /// (except, of course, in expressions inside of array index operator). /// This is guaranteed by the grammar. diff --git a/sway-ast/src/expr/op_code.rs b/sway-ast/src/expr/op_code.rs index 47f9665897b..acfc54411eb 100644 --- a/sway-ast/src/expr/op_code.rs +++ b/sway-ast/src/expr/op_code.rs @@ -200,6 +200,13 @@ define_op_codes!( (Srli, SrliOpcode, "srli", (ret: reg, lhs: reg, rhs: imm)), (Sub, SubOpcode, "sub", (ret: reg, lhs: reg, rhs: reg)), (Subi, SubiOpcode, "subi", (ret: reg, lhs: reg, rhs: imm)), + (Wqcm, WqcmOpcode, "wqcm", (ret: reg, lhs: reg, rhs: reg, op_mode: imm)), + (Wqop, WqopOpcode, "wqop", (ret: reg, lhs: reg, rhs: reg, op_mode: imm)), + (Wqml, WqmlOpcode, "wqml", (ret: reg, lhs: reg, rhs: reg, indirect: imm)), + (Wqdv, WqdvOpcode, "wqdv", (ret: reg, lhs: reg, rhs: reg, indirect: imm)), + (Wqmd, WqmdOpcode, "wqmd", (ret: reg, lhs_a: reg, lhs_b: reg, rhs: reg)), + (Wqam, WqamOpcode, "wqam", (ret: reg, lhs_a: reg, lhs_b: reg, rhs: reg)), + (Wqmm, WqmmOpcode, "wqmm", (ret: reg, lhs_a: reg, lhs_b: reg, rhs: reg)), (Xor, XorOpcode, "xor", (ret: reg, lhs: reg, rhs: reg)), (Xori, XoriOpcode, "xori", (ret: reg, lhs: reg, rhs: imm)), /* Control Flow Instructions */ @@ -259,7 +266,9 @@ define_op_codes!( ), (Croo, CrooOpcode, "croo", (addr: reg, contract: reg)), (Csiz, CsizOpcode, "csiz", (ret: reg, contract: reg)), - (Ldc, LdcOpcode, "ldc", (contract: reg, addr: reg, size: reg)), + (Bsiz, BsizOpcode, "bsiz", (ret: reg, contract: reg)), + (Ldc, LdcOpcode, "ldc", (contract: reg, addr: reg, size: reg, mode: imm)), + (Bldd, BlddOpcode, "bldd", (dst_ptr: reg, addr: reg, offset: reg, len: reg)), ( Log, LogOpcode, @@ -317,7 +326,7 @@ define_op_codes!( /* Cryptographic Instructions */ (Eck1, Eck1Opcode, "eck1", (addr: reg, sig: reg, hash: reg)), (Ecr1, Ecr1Opcode, "ecr1", (addr: reg, sig: reg, hash: reg)), - (Ed19, Ed19Opcode, "ed19", (addr: reg, sig: reg, hash: reg)), + (Ed19, Ed19Opcode, "ed19", (addr: reg, sig: reg, hash: reg, len: reg)), (K256, K256Opcode, "k256", (addr: reg, data: reg, size: reg)), (S256, S256Opcode, "s256", (addr: reg, data: reg, size: reg)), /* Other Instructions */ diff --git a/sway-ast/src/intrinsics.rs b/sway-ast/src/intrinsics.rs index 5200da142ae..182d47fa3d9 100644 --- a/sway-ast/src/intrinsics.rs +++ b/sway-ast/src/intrinsics.rs @@ -41,6 +41,8 @@ pub enum Intrinsic { EncodeBufferEmpty, // let buffer: (raw_ptr, u64, u64) = __encode_buffer_empty() EncodeBufferAppend, // let buffer: (raw_ptr, u64, u64) = __encode_buffer_append(buffer, primitive data type) EncodeBufferAsRawSlice, // let slice: raw_slice = __encode_buffer_as_raw_slice(buffer) + Slice, // let ref_to_slice = __slice::(item: T, inclusive_start_index, exclusive_end_index) + ElemAt, // let elem: &T = __elem_at::(item: T, index) } impl fmt::Display for Intrinsic { @@ -85,6 +87,8 @@ impl fmt::Display for Intrinsic { Intrinsic::EncodeBufferEmpty => "encode_buffer_empty", Intrinsic::EncodeBufferAppend => "encode_buffer_append", Intrinsic::EncodeBufferAsRawSlice => "encode_buffer_as_raw_slice", + Intrinsic::Slice => "slice", + Intrinsic::ElemAt => "elem_at", }; write!(f, "{s}") } @@ -133,6 +137,8 @@ impl Intrinsic { "__encode_buffer_empty" => EncodeBufferEmpty, "__encode_buffer_append" => EncodeBufferAppend, "__encode_buffer_as_raw_slice" => EncodeBufferAsRawSlice, + "__slice" => Slice, + "__elem_at" => ElemAt, _ => return None, }) } diff --git a/sway-ast/src/token.rs b/sway-ast/src/token.rs index f834ad34792..31161a5f862 100644 --- a/sway-ast/src/token.rs +++ b/sway-ast/src/token.rs @@ -259,29 +259,6 @@ impl CharExt for char { } } -struct CharIndicesInner<'a> { - src: &'a str, - position: usize, -} - -impl<'a> Iterator for CharIndicesInner<'a> { - type Item = (usize, char); - - fn next(&mut self) -> Option<(usize, char)> { - let mut char_indices = self.src[self.position..].char_indices(); - let c = match char_indices.next() { - Some((_, c)) => c, - None => return None, - }; - let ret = (self.position, c); - match char_indices.next() { - Some((char_width, _)) => self.position += char_width, - None => self.position = self.src.len(), - }; - Some(ret) - } -} - impl TokenStream { pub fn token_trees(&self) -> &[TokenTree] { &self.token_trees diff --git a/sway-ast/src/ty/mod.rs b/sway-ast/src/ty/mod.rs index 3973a276372..7e2bbc35cab 100644 --- a/sway-ast/src/ty/mod.rs +++ b/sway-ast/src/ty/mod.rs @@ -19,7 +19,7 @@ pub enum Ty { ty: SquareBrackets>, }, Slice { - slice_token: SliceToken, + slice_token: Option, ty: SquareBrackets>, }, Ref { @@ -42,7 +42,12 @@ impl Spanned for Ty { Ty::StringArray { str_token, length } => Span::join(str_token.span(), &length.span()), Ty::Infer { underscore_token } => underscore_token.span(), Ty::Ptr { ptr_token, ty } => Span::join(ptr_token.span(), &ty.span()), - Ty::Slice { slice_token, ty } => Span::join(slice_token.span(), &ty.span()), + Ty::Slice { slice_token, ty } => { + let span = slice_token + .as_ref() + .map(|s| Span::join(s.span(), &ty.span())); + span.unwrap_or_else(|| ty.span()) + } Ty::Ref { ampersand_token, mut_token: _, diff --git a/sway-core/Cargo.toml b/sway-core/Cargo.toml index 4c99385bbc2..668959fab61 100644 --- a/sway-core/Cargo.toml +++ b/sway-core/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "sway-core" -version = "0.60.0" +version.workspace = true description = "Sway core language." authors.workspace = true edition.workspace = true @@ -9,46 +9,43 @@ license.workspace = true repository.workspace = true [dependencies] -clap = { version = "4.5.4", features = ["derive"] } -derivative = "2.2.0" -dirs = "3.0" -either = "1.9.0" -ethabi = { package = "fuel-ethabi", version = "18.0.0" } -etk-asm = { package = "fuel-etk-asm", version = "0.3.1-dev", features = [ - "backtraces", -] } -etk-ops = { package = "fuel-etk-ops", version = "0.3.1-dev" } -fuel-abi-types = { workspace = true } +clap = { workspace = true, features = ["derive"] } +derivative.workspace = true +dirs.workspace = true +either.workspace = true +ethabi.workspace = true +etk-asm = { workspace = true, features = ["backtraces"] } +etk-ops.workspace = true +fuel-abi-types.workspace = true fuel-vm = { workspace = true, features = ["serde"] } -gimli = "0.28.1" -graph-cycles = "0.1.0" -hashbrown = "0.13.1" -hex = { version = "0.4", optional = true } -im = "15.0" -indexmap = "2.0.0" -itertools = "0.10" -lazy_static = "1.4" -miden-core = "0.3.0" -object = { version = "0.32.2", features = ["write"] } -parking_lot = "0.12" -pest = "2.1.3" -pest_derive = "2.1" -petgraph = "0.6" -rustc-hash = "1.1.0" -serde = { version = "1.0", features = ["derive"] } -serde_json = "1.0.91" -sha2 = "0.9" -strum = { version = "0.24.1", features = ["derive"] } -sway-ast = { version = "0.60.0", path = "../sway-ast" } -sway-error = { version = "0.60.0", path = "../sway-error" } -sway-ir = { version = "0.60.0", path = "../sway-ir" } -sway-parse = { version = "0.60.0", path = "../sway-parse" } -sway-types = { version = "0.60.0", path = "../sway-types" } -sway-utils = { version = "0.60.0", path = "../sway-utils" } -thiserror = "1.0" -tracing = "0.1" -uint = "0.9" -vec1 = "1.8.0" +gimli.workspace = true +graph-cycles.workspace = true +hashbrown.workspace = true +hex = { workspace = true, optional = true } +im.workspace = true +indexmap.workspace = true +itertools.workspace = true +lazy_static.workspace = true +object = { workspace = true, features = ["write"] } +parking_lot.workspace = true +pest.workspace = true +pest_derive.workspace = true +petgraph.workspace = true +rustc-hash.workspace = true +serde = { workspace = true, features = ["derive"] } +serde_json.workspace = true +sha2.workspace = true +strum = { workspace = true, features = ["derive"] } +sway-ast.workspace = true +sway-error.workspace = true +sway-ir.workspace = true +sway-parse.workspace = true +sway-types.workspace = true +sway-utils.workspace = true +thiserror.workspace = true +tracing.workspace = true +uint.workspace = true +vec1.workspace = true [target.'cfg(not(target_os = "macos"))'.dependencies] sysinfo = "0.29.0" diff --git a/sway-core/src/abi_generation/abi_str.rs b/sway-core/src/abi_generation/abi_str.rs index 3c94fc3a731..254b8a805ad 100644 --- a/sway-core/src/abi_generation/abi_str.rs +++ b/sway-core/src/abi_generation/abi_str.rs @@ -2,10 +2,12 @@ use sway_types::integer_bits::IntegerBits; use crate::{language::CallPath, Engines, TypeArgument, TypeId, TypeInfo}; +#[derive(Clone)] pub struct AbiStrContext { - pub program_name: Option, + pub program_name: String, pub abi_with_callpaths: bool, pub abi_with_fully_specified_types: bool, + pub abi_root_type_without_generic_type_parameters: bool, } impl TypeId { @@ -17,29 +19,28 @@ impl TypeId { resolved_type_id: TypeId, ) -> String { let type_engine = engines.te(); + let self_abi_str = type_engine.get(*self).abi_str(ctx, engines, true); if self.is_generic_parameter(engines, resolved_type_id) { - format!("generic {}", type_engine.get(*self).abi_str(ctx, engines)) + format!("generic {}", self_abi_str) } else { match ( &*type_engine.get(*self), &*type_engine.get(resolved_type_id), ) { - (TypeInfo::Custom { .. }, TypeInfo::Struct { .. }) => { - type_engine.get(resolved_type_id).abi_str(ctx, engines) - } - (TypeInfo::Custom { .. }, TypeInfo::Enum { .. }) => { - type_engine.get(resolved_type_id).abi_str(ctx, engines) - } - (TypeInfo::Custom { .. }, TypeInfo::Alias { .. }) => { - type_engine.get(resolved_type_id).abi_str(ctx, engines) + (TypeInfo::Custom { .. }, TypeInfo::Struct { .. }) + | (TypeInfo::Custom { .. }, TypeInfo::Enum { .. }) => type_engine + .get(resolved_type_id) + .abi_str(ctx, engines, true), + (_, TypeInfo::Alias { ty, .. }) => { + ty.type_id.get_abi_type_str(ctx, engines, ty.type_id) } (TypeInfo::Tuple(fields), TypeInfo::Tuple(resolved_fields)) => { assert_eq!(fields.len(), resolved_fields.len()); - let field_strs = fields + let field_strs = resolved_fields .iter() .map(|f| { if ctx.abi_with_fully_specified_types { - type_engine.get(f.type_id).abi_str(ctx, engines) + type_engine.get(f.type_id).abi_str(ctx, engines, false) } else { "_".to_string() } @@ -47,26 +48,40 @@ impl TypeId { .collect::>(); format!("({})", field_strs.join(", ")) } - (TypeInfo::Array(type_arg, count), TypeInfo::Array(_, resolved_count)) => { + (TypeInfo::Array(_, count), TypeInfo::Array(type_arg, resolved_count)) => { assert_eq!(count.val(), resolved_count.val()); let inner_type = if ctx.abi_with_fully_specified_types { - type_engine.get(type_arg.type_id).abi_str(ctx, engines) + type_engine + .get(type_arg.type_id) + .abi_str(ctx, engines, false) } else { "_".to_string() }; format!("[{}; {}]", inner_type, count.val()) } + (TypeInfo::Slice(type_arg), TypeInfo::Slice(_)) => { + let inner_type = if ctx.abi_with_fully_specified_types { + type_engine + .get(type_arg.type_id) + .abi_str(ctx, engines, false) + } else { + "_".to_string() + }; + format!("[{}]", inner_type) + } (TypeInfo::Custom { .. }, _) => { - format!("generic {}", type_engine.get(*self).abi_str(ctx, engines)) + format!("generic {}", self_abi_str) } - _ => type_engine.get(resolved_type_id).abi_str(ctx, engines), + _ => type_engine + .get(resolved_type_id) + .abi_str(ctx, engines, true), } } } } impl TypeInfo { - pub fn abi_str(&self, ctx: &AbiStrContext, engines: &Engines) -> String { + pub fn abi_str(&self, ctx: &AbiStrContext, engines: &Engines, is_root: bool) -> String { use TypeInfo::*; let decl_engine = engines.de(); let type_engine = engines.te(); @@ -94,7 +109,7 @@ impl TypeInfo { Tuple(fields) => { let field_strs = fields .iter() - .map(|field| field.abi_str(ctx, engines)) + .map(|field| field.abi_str(ctx, engines, false)) .collect::>(); format!("({})", field_strs.join(", ")) } @@ -102,21 +117,30 @@ impl TypeInfo { Numeric => "u64".into(), // u64 is the default Contract => "contract".into(), ErrorRecovery(_) => "unknown due to error".into(), + UntypedEnum(decl_id) => { + let decl = engines.pe().get_enum(decl_id); + format!("untyped enum {}", decl.name) + } + UntypedStruct(decl_id) => { + let decl = engines.pe().get_struct(decl_id); + format!("untyped struct {}", decl.name) + } Enum(decl_ref) => { let decl = decl_engine.get_enum(decl_ref); - let type_params = - if !ctx.abi_with_fully_specified_types || decl.type_parameters.is_empty() { - "".into() - } else { - format!( - "<{}>", - decl.type_parameters - .iter() - .map(|p| type_engine.get(p.type_id).abi_str(ctx, engines)) - .collect::>() - .join(",") - ) - }; + let type_params = if (ctx.abi_root_type_without_generic_type_parameters && is_root) + || decl.type_parameters.is_empty() + { + "".into() + } else { + format!( + "<{}>", + decl.type_parameters + .iter() + .map(|p| type_engine.get(p.type_id).abi_str(ctx, engines, false)) + .collect::>() + .join(",") + ) + }; format!( "enum {}{}", call_path_display(ctx, &decl.call_path), @@ -125,19 +149,20 @@ impl TypeInfo { } Struct(decl_ref) => { let decl = decl_engine.get_struct(decl_ref); - let type_params = - if !ctx.abi_with_fully_specified_types || decl.type_parameters.is_empty() { - "".into() - } else { - format!( - "<{}>", - decl.type_parameters - .iter() - .map(|p| type_engine.get(p.type_id).abi_str(ctx, engines)) - .collect::>() - .join(",") - ) - }; + let type_params = if (ctx.abi_root_type_without_generic_type_parameters && is_root) + || decl.type_parameters.is_empty() + { + "".into() + } else { + format!( + "<{}>", + decl.type_parameters + .iter() + .map(|p| type_engine.get(p.type_id).abi_str(ctx, engines, false)) + .collect::>() + .join(",") + ) + }; format!( "struct {}{}", call_path_display(ctx, &decl.call_path), @@ -148,18 +173,22 @@ impl TypeInfo { format!("contract caller {abi_name}") } Array(elem_ty, length) => { - format!("[{}; {}]", elem_ty.abi_str(ctx, engines), length.val()) + format!( + "[{}; {}]", + elem_ty.abi_str(ctx, engines, false), + length.val() + ) } Storage { .. } => "contract storage".into(), RawUntypedPtr => "raw untyped ptr".into(), RawUntypedSlice => "raw untyped slice".into(), Ptr(ty) => { - format!("__ptr {}", ty.abi_str(ctx, engines)) + format!("__ptr {}", ty.abi_str(ctx, engines, false)) } Slice(ty) => { - format!("__slice {}", ty.abi_str(ctx, engines)) + format!("__slice {}", ty.abi_str(ctx, engines, false)) } - Alias { ty, .. } => ty.abi_str(ctx, engines), + Alias { ty, .. } => ty.abi_str(ctx, engines, false), TraitType { name, trait_type_id: _, @@ -171,7 +200,7 @@ impl TypeInfo { format!( "__ref {}{}", // TODO-IG: No references in ABIs according to the RFC. Or we want to have them? if *to_mutable_value { "mut " } else { "" }, - referenced_type.abi_str(ctx, engines) + referenced_type.abi_str(ctx, engines, false) ) } } @@ -186,18 +215,11 @@ fn call_path_display(ctx: &AbiStrContext, call_path: &CallPath) -> String { } let mut buf = String::new(); for (index, prefix) in call_path.prefixes.iter().enumerate() { - let mut skip_prefix = false; - if index == 0 { - if let Some(root_name) = &ctx.program_name { - if prefix.as_str() == root_name.as_str() { - skip_prefix = true; - } - } - } - if !skip_prefix { - buf.push_str(prefix.as_str()); - buf.push_str("::"); + if index == 0 && prefix.as_str() == ctx.program_name { + continue; } + buf.push_str(prefix.as_str()); + buf.push_str("::"); } buf.push_str(&call_path.suffix.to_string()); @@ -205,7 +227,10 @@ fn call_path_display(ctx: &AbiStrContext, call_path: &CallPath) -> String { } impl TypeArgument { - pub(self) fn abi_str(&self, ctx: &AbiStrContext, engines: &Engines) -> String { - engines.te().get(self.type_id).abi_str(ctx, engines) + pub(self) fn abi_str(&self, ctx: &AbiStrContext, engines: &Engines, is_root: bool) -> String { + engines + .te() + .get(self.type_id) + .abi_str(ctx, engines, is_root) } } diff --git a/sway-core/src/abi_generation/evm_abi.rs b/sway-core/src/abi_generation/evm_abi.rs index 6cfb1040484..f723f36d14a 100644 --- a/sway-core/src/abi_generation/evm_abi.rs +++ b/sway-core/src/abi_generation/evm_abi.rs @@ -49,6 +49,7 @@ fn get_type_str(type_id: &TypeId, engines: &Engines, resolved_type_id: TypeId) - assert_eq!(count.val(), resolved_count.val()); format!("[_; {}]", count.val()) } + (TypeInfo::Slice(_), TypeInfo::Slice(_)) => "__slice[_]".into(), (TypeInfo::Custom { .. }, _) => { format!("generic {}", abi_str(&type_engine.get(*type_id), engines)) } @@ -92,6 +93,14 @@ pub fn abi_str(type_info: &TypeInfo, engines: &Engines) -> String { Numeric => "u64".into(), // u64 is the default Contract => "contract".into(), ErrorRecovery(_) => "unknown due to error".into(), + UntypedEnum(decl_id) => { + let decl = engines.pe().get_enum(decl_id); + format!("untyped enum {}", decl.name) + } + UntypedStruct(decl_id) => { + let decl = engines.pe().get_struct(decl_id); + format!("untyped struct {}", decl.name) + } Enum(decl_ref) => { let decl = decl_engine.get_enum(decl_ref); format!("enum {}", decl.call_path.suffix) diff --git a/sway-core/src/abi_generation/fuel_abi.rs b/sway-core/src/abi_generation/fuel_abi.rs index 1479dd2c155..7fdd704155d 100644 --- a/sway-core/src/abi_generation/fuel_abi.rs +++ b/sway-core/src/abi_generation/fuel_abi.rs @@ -1,5 +1,10 @@ -use fuel_abi_types::abi::program as program_abi; -use std::collections::HashSet; +use fuel_abi_types::abi::program::{ + self as program_abi, ConcreteTypeId, MetadataTypeId, TypeConcreteDeclaration, +}; +use sha2::{Digest, Sha256}; +use std::collections::{HashMap, HashSet}; +use sway_error::handler::{ErrorEmitted, Handler}; +use sway_types::Span; use crate::{ language::ty::{TyFunctionDecl, TyProgram, TyProgramKind}, @@ -12,395 +17,799 @@ use super::abi_str::AbiStrContext; pub struct AbiContext<'a> { pub program: &'a TyProgram, pub abi_with_callpaths: bool, + pub type_ids_to_full_type_str: HashMap, } impl<'a> AbiContext<'a> { - fn to_str_context( - &self, - engines: &Engines, - abi_with_fully_specified_types: bool, - ) -> AbiStrContext { + fn to_str_context(&self, engines: &Engines, abi_full: bool) -> AbiStrContext { AbiStrContext { program_name: self .program .root .namespace .program_id(engines) - .read(engines, |m| m.name.clone().map(|v| v.as_str().to_string())), + .read(engines, |m| m.name().to_string()), abi_with_callpaths: self.abi_with_callpaths, - abi_with_fully_specified_types, + abi_with_fully_specified_types: abi_full, + abi_root_type_without_generic_type_parameters: !abi_full, } } } +impl TypeId { + fn get_abi_type_field_and_concrete_id( + &self, + handler: &Handler, + ctx: &mut AbiContext, + engines: &Engines, + resolved_type_id: TypeId, + ) -> Result<(String, ConcreteTypeId), ErrorEmitted> { + let type_str = self.get_abi_type_str( + &AbiStrContext { + program_name: ctx + .program + .root + .namespace + .program_id(engines) + .read(engines, |m| m.name().clone().as_str().to_string()), + abi_with_callpaths: true, + abi_with_fully_specified_types: true, + abi_root_type_without_generic_type_parameters: false, + }, + engines, + resolved_type_id, + ); + let mut hasher = Sha256::new(); + hasher.update(type_str.clone()); + let result = hasher.finalize(); + let type_id = format!("{:x}", result); + + if let Some(old_type_str) = ctx + .type_ids_to_full_type_str + .insert(type_id.clone(), type_str.clone()) + { + if old_type_str != type_str { + return Err( + handler.emit_err(sway_error::error::CompileError::ABIHashCollision { + span: Span::dummy(), + hash: type_id, + first_type: old_type_str, + second_type: type_str, + }), + ); + } + } + + Ok((type_str, ConcreteTypeId(type_id))) + } +} + pub fn generate_program_abi( + handler: &Handler, ctx: &mut AbiContext, engines: &Engines, - types: &mut Vec, - encoding: Option, -) -> program_abi::ProgramABI { + encoding_version: program_abi::Version, + spec_version: program_abi::Version, +) -> Result { let decl_engine = engines.de(); - match &ctx.program.kind { + let metadata_types: &mut Vec = &mut vec![]; + let concrete_types: &mut Vec = &mut vec![]; + let mut program_abi = match &ctx.program.kind { TyProgramKind::Contract { abi_entries, .. } => { let functions = abi_entries .iter() .map(|x| { let fn_decl = decl_engine.get_function(x); - fn_decl.generate_abi_function(ctx, engines, types) + fn_decl.generate_abi_function( + handler, + ctx, + engines, + metadata_types, + concrete_types, + ) }) - .collect(); - let logged_types = generate_logged_types(ctx, engines, types); - let messages_types = generate_messages_types(ctx, engines, types); - let configurables = generate_configurables(ctx, engines, types); + .collect::, _>>()?; + let logged_types = + generate_logged_types(handler, ctx, engines, metadata_types, concrete_types)?; + let messages_types = + generate_messages_types(handler, ctx, engines, metadata_types, concrete_types)?; + let configurables = + generate_configurables(handler, ctx, engines, metadata_types, concrete_types)?; + program_abi::ProgramABI { + program_type: "contract".to_string(), + spec_version, + encoding_version, + metadata_types: metadata_types.to_vec(), + concrete_types: concrete_types.to_vec(), + functions, + logged_types: Some(logged_types), + messages_types: Some(messages_types), + configurables: Some(configurables), + } + } + TyProgramKind::Script { main_function, .. } => { + let main_function = decl_engine.get_function(main_function); + let functions = vec![main_function.generate_abi_function( + handler, + ctx, + engines, + metadata_types, + concrete_types, + )?]; + let logged_types = + generate_logged_types(handler, ctx, engines, metadata_types, concrete_types)?; + let messages_types = + generate_messages_types(handler, ctx, engines, metadata_types, concrete_types)?; + let configurables = + generate_configurables(handler, ctx, engines, metadata_types, concrete_types)?; program_abi::ProgramABI { - encoding, - types: types.to_vec(), + program_type: "script".to_string(), + spec_version, + encoding_version, + metadata_types: metadata_types.to_vec(), + concrete_types: concrete_types.to_vec(), functions, logged_types: Some(logged_types), messages_types: Some(messages_types), configurables: Some(configurables), } } - TyProgramKind::Script { main_function, .. } - | TyProgramKind::Predicate { main_function, .. } => { + TyProgramKind::Predicate { main_function, .. } => { let main_function = decl_engine.get_function(main_function); - let functions = vec![main_function.generate_abi_function(ctx, engines, types)]; - let logged_types = generate_logged_types(ctx, engines, types); - let messages_types = generate_messages_types(ctx, engines, types); - let configurables = generate_configurables(ctx, engines, types); + let functions = vec![main_function.generate_abi_function( + handler, + ctx, + engines, + metadata_types, + concrete_types, + )?]; + let logged_types = + generate_logged_types(handler, ctx, engines, metadata_types, concrete_types)?; + let messages_types = + generate_messages_types(handler, ctx, engines, metadata_types, concrete_types)?; + let configurables = + generate_configurables(handler, ctx, engines, metadata_types, concrete_types)?; program_abi::ProgramABI { - encoding, - types: types.to_vec(), + program_type: "predicate".to_string(), + spec_version, + encoding_version, + metadata_types: metadata_types.to_vec(), + concrete_types: concrete_types.to_vec(), functions, logged_types: Some(logged_types), messages_types: Some(messages_types), configurables: Some(configurables), } } - _ => program_abi::ProgramABI { - encoding, - types: vec![], - functions: vec![], - logged_types: None, - messages_types: None, - configurables: None, - }, + TyProgramKind::Library { .. } => { + let logged_types = + generate_logged_types(handler, ctx, engines, metadata_types, concrete_types)?; + let messages_types = + generate_messages_types(handler, ctx, engines, metadata_types, concrete_types)?; + + program_abi::ProgramABI { + program_type: "library".to_string(), + spec_version, + encoding_version, + metadata_types: metadata_types.to_vec(), + concrete_types: concrete_types.to_vec(), + functions: vec![], + logged_types: Some(logged_types), + messages_types: Some(messages_types), + configurables: None, + } + } + }; + + standardize_json_abi_types(&mut program_abi); + + Ok(program_abi) +} + +/// Standardize the JSON ABI data structure by eliminating duplicate types. This is an iterative +/// process because every time two types are merged, new opportunities for more merging arise. +fn standardize_json_abi_types(json_abi_program: &mut program_abi::ProgramABI) { + // Dedup TypeMetadataDeclaration + loop { + // If type with id_1 is a duplicate of type with id_2, then keep track of the mapping + // between id_1 and id_2 in the HashMap below. + let mut old_to_new_id: HashMap = HashMap::new(); + + // A vector containing unique `program_abi::TypeMetadataDeclaration`s. + // + // Two `program_abi::TypeMetadataDeclaration` are deemed the same if the have the same + // `type_field`, `components`, and `type_parameters` (even if their `type_id`s are + // different). + let mut deduped_types: Vec = Vec::new(); + + // Insert values in `deduped_types` if they haven't been inserted before. Otherwise, create + // an appropriate mapping between type IDs in the HashMap `old_to_new_id`. + for decl in &json_abi_program.metadata_types { + // First replace metadata_type_id with concrete_type_id when possible + if let Some(ty) = json_abi_program.concrete_types.iter().find(|d| { + d.type_field == decl.type_field + && decl.components.is_none() + && decl.type_parameters.is_none() + }) { + old_to_new_id.insert( + decl.metadata_type_id.clone(), + program_abi::TypeId::Concrete(ty.concrete_type_id.clone()), + ); + } else { + // Second replace metadata_type_id with metadata_type_id when possible + if let Some(ty) = deduped_types.iter().find(|d| { + d.type_field == decl.type_field + && d.components == decl.components + && d.type_parameters == decl.type_parameters + }) { + old_to_new_id.insert( + decl.metadata_type_id.clone(), + program_abi::TypeId::Metadata(ty.metadata_type_id.clone()), + ); + } else { + deduped_types.push(decl.clone()); + } + } + } + + // Nothing to do if the hash map is empty as there are not merge opportunities. We can now + // exit the loop. + if old_to_new_id.is_empty() { + break; + } + + json_abi_program.metadata_types = deduped_types; + + update_all_types(json_abi_program, &old_to_new_id); + } + + // Dedup TypeConcreteDeclaration + let mut concrete_declarations_map: HashMap = + HashMap::new(); + for decl in &json_abi_program.concrete_types { + concrete_declarations_map.insert(decl.concrete_type_id.clone(), decl.clone()); } + json_abi_program.concrete_types = concrete_declarations_map.values().cloned().collect(); + + // Sort the `program_abi::TypeMetadataDeclaration`s + json_abi_program + .metadata_types + .sort_by(|t1, t2| t1.type_field.cmp(&t2.type_field)); + + // Sort the `program_abi::TypeConcreteDeclaration`s + json_abi_program + .concrete_types + .sort_by(|t1, t2| t1.type_field.cmp(&t2.type_field)); + + // Standardize IDs (i.e. change them to 0,1,2,... according to the alphabetical order above + let mut old_to_new_id: HashMap = HashMap::new(); + for (ix, decl) in json_abi_program.metadata_types.iter_mut().enumerate() { + old_to_new_id.insert( + decl.metadata_type_id.clone(), + program_abi::TypeId::Metadata(MetadataTypeId(ix)), + ); + decl.metadata_type_id = MetadataTypeId(ix); + } + + update_all_types(json_abi_program, &old_to_new_id); } -fn generate_logged_types( +/// Recursively updates the type IDs used in a program_abi::ProgramABI +fn update_all_types( + json_abi_program: &mut program_abi::ProgramABI, + old_to_new_id: &HashMap, +) { + // Update all `program_abi::TypeMetadataDeclaration` + for decl in &mut json_abi_program.metadata_types { + update_json_type_metadata_declaration(decl, old_to_new_id); + } + + // Update all `program_abi::TypeConcreteDeclaration` + for decl in &mut json_abi_program.concrete_types { + update_json_type_concrete_declaration(decl, old_to_new_id); + } +} + +/// Recursively updates the type IDs used in a `program_abi::TypeApplication` given a HashMap from +/// old to new IDs +fn update_json_type_application( + type_application: &mut program_abi::TypeApplication, + old_to_new_id: &HashMap, +) { + if let fuel_abi_types::abi::program::TypeId::Metadata(metadata_type_id) = + &type_application.type_id + { + if let Some(new_id) = old_to_new_id.get(metadata_type_id) { + type_application.type_id = new_id.clone(); + } + } + + if let Some(args) = &mut type_application.type_arguments { + for arg in args.iter_mut() { + update_json_type_application(arg, old_to_new_id); + } + } +} + +/// Recursively updates the metadata type IDs used in a `program_abi::TypeMetadataDeclaration` given a HashMap from +/// old to new IDs +fn update_json_type_metadata_declaration( + type_declaration: &mut program_abi::TypeMetadataDeclaration, + old_to_new_id: &HashMap, +) { + if let Some(params) = &mut type_declaration.type_parameters { + for param in params.iter_mut() { + if let Some(fuel_abi_types::abi::program::TypeId::Metadata(new_id)) = + old_to_new_id.get(param) + { + *param = new_id.clone(); + } + } + } + + if let Some(components) = &mut type_declaration.components { + for component in components.iter_mut() { + update_json_type_application(component, old_to_new_id); + } + } +} + +/// RUpdates the metadata type IDs used in a `program_abi::TypeConcreteDeclaration` given a HashMap from +/// old to new IDs +fn update_json_type_concrete_declaration( + type_declaration: &mut program_abi::TypeConcreteDeclaration, + old_to_new_id: &HashMap, +) { + if let Some(metadata_type_id) = &mut type_declaration.metadata_type_id { + if let Some(fuel_abi_types::abi::program::TypeId::Metadata(new_id)) = + old_to_new_id.get(metadata_type_id) + { + *metadata_type_id = new_id.clone(); + } + } +} + +fn generate_concrete_type_declaration( + handler: &Handler, ctx: &mut AbiContext, engines: &Engines, - types: &mut Vec, -) -> Vec { - // A list of all `program_abi::TypeDeclaration`s needed for the logged types - let logged_types = ctx - .program - .logged_types - .iter() - .map(|(_, type_id)| program_abi::TypeDeclaration { - type_id: type_id.index(), - type_field: type_id.get_abi_type_str( - &ctx.to_str_context(engines, false), - engines, - *type_id, - ), - components: type_id.get_abi_type_components(ctx, engines, types, *type_id), - type_parameters: type_id.get_abi_type_parameters(ctx, engines, types, *type_id), - }) - .collect::>(); + metadata_types: &mut Vec, + concrete_types: &mut Vec, + type_id: TypeId, + resolved_type_id: TypeId, +) -> Result { + let mut new_metadata_types_to_add = Vec::::new(); + let type_metadata_decl = program_abi::TypeMetadataDeclaration { + metadata_type_id: MetadataTypeId(type_id.index()), + type_field: type_id.get_abi_type_str( + &ctx.to_str_context(engines, false), + engines, + resolved_type_id, + ), + components: type_id.get_abi_type_components( + handler, + ctx, + engines, + metadata_types, + concrete_types, + resolved_type_id, + &mut new_metadata_types_to_add, + )?, + type_parameters: type_id.get_abi_type_parameters( + handler, + ctx, + engines, + metadata_types, + concrete_types, + resolved_type_id, + &mut new_metadata_types_to_add, + )?, + }; + + let metadata_type_id = if type_metadata_decl.type_parameters.is_some() + || type_metadata_decl.components.is_some() + { + Some(type_metadata_decl.metadata_type_id.clone()) + } else { + None + }; + let type_arguments = if type_metadata_decl.type_parameters.is_some() { + type_id.get_abi_type_arguments_as_concrete_type_ids( + handler, + ctx, + engines, + metadata_types, + concrete_types, + resolved_type_id, + )? + } else { + None + }; + + metadata_types.push(type_metadata_decl); + metadata_types.extend(new_metadata_types_to_add); + + let (type_field, concrete_type_id) = + type_id.get_abi_type_field_and_concrete_id(handler, ctx, engines, resolved_type_id)?; + let concrete_type_decl = TypeConcreteDeclaration { + type_field, + concrete_type_id: concrete_type_id.clone(), + metadata_type_id, + type_arguments, + }; + + concrete_types.push(concrete_type_decl); - // Add the new types to `types` - types.extend(logged_types); + Ok(concrete_type_id) +} + +#[allow(clippy::too_many_arguments)] +fn generate_type_metadata_declaration( + handler: &Handler, + ctx: &mut AbiContext, + engines: &Engines, + metadata_types: &mut Vec, + concrete_types: &mut Vec, + type_id: TypeId, + resolved_type_id: TypeId, + metadata_types_to_add: &mut Vec, +) -> Result<(), ErrorEmitted> { + let mut new_metadata_types_to_add = Vec::::new(); + let components = type_id.get_abi_type_components( + handler, + ctx, + engines, + metadata_types, + concrete_types, + resolved_type_id, + &mut new_metadata_types_to_add, + )?; + let type_parameters = type_id.get_abi_type_parameters( + handler, + ctx, + engines, + metadata_types, + concrete_types, + resolved_type_id, + &mut new_metadata_types_to_add, + )?; + let type_metadata_decl = program_abi::TypeMetadataDeclaration { + metadata_type_id: MetadataTypeId(type_id.index()), + type_field: type_id.get_abi_type_str( + &ctx.to_str_context(engines, false), + engines, + resolved_type_id, + ), + components, + type_parameters, + }; + + metadata_types_to_add.push(type_metadata_decl.clone()); + metadata_types_to_add.extend(new_metadata_types_to_add); + + Ok(()) +} +fn generate_logged_types( + handler: &Handler, + ctx: &mut AbiContext, + engines: &Engines, + metadata_types: &mut Vec, + concrete_types: &mut Vec, +) -> Result, ErrorEmitted> { // Generate the JSON data for the logged types let mut log_ids: HashSet = HashSet::default(); - ctx.program + Ok(ctx + .program .logged_types .iter() - .filter_map(|(log_id, type_id)| { + .map(|(log_id, type_id)| { let log_id = log_id.hash_id; if log_ids.contains(&log_id) { - None + Ok(None) } else { log_ids.insert(log_id); - Some(program_abi::LoggedType { + Ok(Some(program_abi::LoggedType { log_id: log_id.to_string(), - application: program_abi::TypeApplication { - name: "".to_string(), - type_id: type_id.index(), - type_arguments: type_id - .get_abi_type_arguments(ctx, engines, types, *type_id), - }, - }) + concrete_type_id: generate_concrete_type_declaration( + handler, + ctx, + engines, + metadata_types, + concrete_types, + *type_id, + *type_id, + )?, + })) } }) - .collect() + .collect::, _>>()? + .into_iter() + .flatten() + .collect()) } fn generate_messages_types( + handler: &Handler, ctx: &mut AbiContext, engines: &Engines, - types: &mut Vec, -) -> Vec { - // A list of all `program_abi::TypeDeclaration`s needed for the messages types - let messages_types = ctx - .program - .messages_types - .iter() - .map(|(_, type_id)| program_abi::TypeDeclaration { - type_id: type_id.index(), - type_field: type_id.get_abi_type_str( - &ctx.to_str_context(engines, false), - engines, - *type_id, - ), - components: type_id.get_abi_type_components(ctx, engines, types, *type_id), - type_parameters: type_id.get_abi_type_parameters(ctx, engines, types, *type_id), - }) - .collect::>(); - - // Add the new types to `types` - types.extend(messages_types); - + metadata_types: &mut Vec, + concrete_types: &mut Vec, +) -> Result, ErrorEmitted> { // Generate the JSON data for the messages types ctx.program .messages_types .iter() - .map(|(message_id, type_id)| program_abi::MessageType { - message_id: **message_id as u64, - application: program_abi::TypeApplication { - name: "".to_string(), - type_id: type_id.index(), - type_arguments: type_id.get_abi_type_arguments(ctx, engines, types, *type_id), - }, + .map(|(message_id, type_id)| { + Ok(program_abi::MessageType { + message_id: (**message_id as u64).to_string(), + concrete_type_id: generate_concrete_type_declaration( + handler, + ctx, + engines, + metadata_types, + concrete_types, + *type_id, + *type_id, + )?, + }) }) - .collect() + .collect::, _>>() } fn generate_configurables( + handler: &Handler, ctx: &mut AbiContext, engines: &Engines, - types: &mut Vec, -) -> Vec { - // A list of all `program_abi::TypeDeclaration`s needed for the configurables types - let configurables_types = ctx - .program - .configurables - .iter() - .map(|decl| program_abi::TypeDeclaration { - type_id: decl.type_ascription.type_id.index(), - type_field: decl.type_ascription.type_id.get_abi_type_str( - &ctx.to_str_context(engines, false), - engines, - decl.type_ascription.type_id, - ), - components: decl.type_ascription.type_id.get_abi_type_components( - ctx, - engines, - types, - decl.type_ascription.type_id, - ), - type_parameters: decl.type_ascription.type_id.get_abi_type_parameters( - ctx, - engines, - types, - decl.type_ascription.type_id, - ), - }) - .collect::>(); - - // Add the new types to `types` - types.extend(configurables_types); - + metadata_types: &mut Vec, + concrete_types: &mut Vec, +) -> Result, ErrorEmitted> { // Generate the JSON data for the configurables types ctx.program .configurables .iter() - .map(|decl| program_abi::Configurable { - name: decl.call_path.suffix.to_string(), - application: program_abi::TypeApplication { - name: "".to_string(), - type_id: decl.type_ascription.type_id.index(), - type_arguments: decl.type_ascription.type_id.get_abi_type_arguments( + .map(|decl| { + Ok(program_abi::Configurable { + name: decl.call_path.suffix.to_string(), + concrete_type_id: generate_concrete_type_declaration( + handler, ctx, engines, - types, + metadata_types, + concrete_types, decl.type_ascription.type_id, - ), - }, - offset: 0, + decl.type_ascription.type_id, + )?, + offset: 0, + }) }) - .collect() + .collect::, _>>() } impl TypeId { /// Return the type parameters of a given (potentially generic) type while considering what it /// actually resolves to. These parameters are essentially of type of `usize` which are - /// basically the IDs of some set of `program_abi::TypeDeclaration`s. The method below also - /// updates the provide list of `program_abi::TypeDeclaration`s to add the newly discovered + /// basically the IDs of some set of `program_abi::TypeMetadataDeclaration`s. The method below also + /// updates the provide list of `program_abi::TypeMetadataDeclaration`s to add the newly discovered /// types. + #[allow(clippy::too_many_arguments)] pub(self) fn get_abi_type_parameters( &self, + handler: &Handler, ctx: &mut AbiContext, engines: &Engines, - types: &mut Vec, + metadata_types: &mut Vec, + concrete_types: &mut Vec, resolved_type_id: TypeId, - ) -> Option> { + metadata_types_to_add: &mut Vec, + ) -> Result>, ErrorEmitted> { match self.is_generic_parameter(engines, resolved_type_id) { - true => None, - false => resolved_type_id.get_type_parameters(engines).map(|v| { - v.iter() - .map(|v| v.get_abi_type_parameter(ctx, engines, types)) - .collect::>() - }), + true => Ok(None), + false => resolved_type_id + .get_type_parameters(engines) + .map(|v| { + v.iter() + .map(|v| { + v.get_abi_type_parameter( + handler, + ctx, + engines, + metadata_types, + concrete_types, + metadata_types_to_add, + ) + }) + .collect::, _>>() + }) + .map_or(Ok(None), |v| v.map(Some)), } } + /// Return the components of a given (potentially generic) type while considering what it /// actually resolves to. These components are essentially of type of /// `program_abi::TypeApplication`. The method below also updates the provided list of - /// `program_abi::TypeDeclaration`s to add the newly discovered types. + /// `program_abi::TypeMetadataDeclaration`s to add the newly discovered types. + #[allow(clippy::too_many_arguments)] pub(self) fn get_abi_type_components( &self, + handler: &Handler, ctx: &mut AbiContext, engines: &Engines, - types: &mut Vec, + metadata_types: &mut Vec, + concrete_types: &mut Vec, resolved_type_id: TypeId, - ) -> Option> { + metadata_types_to_add: &mut Vec, + ) -> Result>, ErrorEmitted> { let type_engine = engines.te(); let decl_engine = engines.de(); - match &*type_engine.get(*self) { + Ok(match &*type_engine.get(*self) { TypeInfo::Enum(decl_ref) => { let decl = decl_engine.get_enum(decl_ref); - // A list of all `program_abi::TypeDeclaration`s needed for the enum variants - let variants = decl - .variants - .iter() - .map(|x| program_abi::TypeDeclaration { - type_id: x.type_argument.initial_type_id.index(), - type_field: x.type_argument.initial_type_id.get_abi_type_str( - &ctx.to_str_context(engines, false), - engines, - x.type_argument.type_id, - ), - components: x.type_argument.initial_type_id.get_abi_type_components( - ctx, - engines, - types, - x.type_argument.type_id, - ), - type_parameters: x.type_argument.initial_type_id.get_abi_type_parameters( - ctx, - engines, - types, - x.type_argument.type_id, - ), - }) - .collect::>(); - types.extend(variants); + + let mut new_metadata_types_to_add = + Vec::::new(); + for x in decl.variants.iter() { + generate_type_metadata_declaration( + handler, + ctx, + engines, + metadata_types, + concrete_types, + x.type_argument.initial_type_id, + x.type_argument.type_id, + &mut new_metadata_types_to_add, + )?; + } // Generate the JSON data for the enum. This is basically a list of // `program_abi::TypeApplication`s - Some( - decl.variants - .iter() - .map(|x| program_abi::TypeApplication { + let components = decl + .variants + .iter() + .map(|x| { + Ok(program_abi::TypeApplication { name: x.name.to_string(), - type_id: x.type_argument.initial_type_id.index(), - type_arguments: x.type_argument.initial_type_id.get_abi_type_arguments( - ctx, - engines, - types, - x.type_argument.type_id, - ), + type_id: program_abi::TypeId::Metadata(MetadataTypeId( + x.type_argument.initial_type_id.index(), + )), + type_arguments: x + .type_argument + .initial_type_id + .get_abi_type_arguments( + handler, + ctx, + engines, + metadata_types, + concrete_types, + x.type_argument.type_id, + &mut new_metadata_types_to_add, + )?, }) - .collect(), - ) + }) + .collect::, _>>()?; + + if components.is_empty() { + None + } else { + metadata_types_to_add.extend(new_metadata_types_to_add); + Some(components) + } } TypeInfo::Struct(decl_ref) => { let decl = decl_engine.get_struct(decl_ref); - // A list of all `program_abi::TypeDeclaration`s needed for the struct fields - let field_types = decl - .fields - .iter() - .map(|x| program_abi::TypeDeclaration { - type_id: x.type_argument.initial_type_id.index(), - type_field: x.type_argument.initial_type_id.get_abi_type_str( - &ctx.to_str_context(engines, false), - engines, - x.type_argument.type_id, - ), - components: x.type_argument.initial_type_id.get_abi_type_components( - ctx, - engines, - types, - x.type_argument.type_id, - ), - type_parameters: x.type_argument.initial_type_id.get_abi_type_parameters( - ctx, - engines, - types, - x.type_argument.type_id, - ), - }) - .collect::>(); - types.extend(field_types); + let mut new_metadata_types_to_add = + Vec::::new(); + for x in decl.fields.iter() { + generate_type_metadata_declaration( + handler, + ctx, + engines, + metadata_types, + concrete_types, + x.type_argument.initial_type_id, + x.type_argument.type_id, + &mut new_metadata_types_to_add, + )?; + } // Generate the JSON data for the struct. This is basically a list of // `program_abi::TypeApplication`s - Some( - decl.fields - .iter() - .map(|x| program_abi::TypeApplication { + let components = decl + .fields + .iter() + .map(|x| { + Ok(program_abi::TypeApplication { name: x.name.to_string(), - type_id: x.type_argument.initial_type_id.index(), - type_arguments: x.type_argument.initial_type_id.get_abi_type_arguments( - ctx, - engines, - types, - x.type_argument.type_id, - ), + type_id: program_abi::TypeId::Metadata(MetadataTypeId( + x.type_argument.initial_type_id.index(), + )), + type_arguments: x + .type_argument + .initial_type_id + .get_abi_type_arguments( + handler, + ctx, + engines, + metadata_types, + concrete_types, + x.type_argument.type_id, + &mut new_metadata_types_to_add, + )?, }) - .collect(), - ) + }) + .collect::, _>>()?; + + if components.is_empty() { + None + } else { + metadata_types_to_add.extend(new_metadata_types_to_add); + Some(components) + } } TypeInfo::Array(..) => { if let TypeInfo::Array(elem_ty, _) = &*type_engine.get(resolved_type_id) { - // The `program_abi::TypeDeclaration`s needed for the array element type - let elem_abi_ty = program_abi::TypeDeclaration { - type_id: elem_ty.initial_type_id.index(), - type_field: elem_ty.initial_type_id.get_abi_type_str( - &ctx.to_str_context(engines, false), - engines, - elem_ty.type_id, - ), - components: elem_ty.initial_type_id.get_abi_type_components( - ctx, - engines, - types, - elem_ty.type_id, - ), - type_parameters: elem_ty.initial_type_id.get_abi_type_parameters( + generate_type_metadata_declaration( + handler, + ctx, + engines, + metadata_types, + concrete_types, + elem_ty.initial_type_id, + elem_ty.type_id, + metadata_types_to_add, + )?; + + // Generate the JSON data for the array. This is basically a single + // `program_abi::TypeApplication` for the array element type + Some(vec![program_abi::TypeApplication { + name: "__array_element".to_string(), + type_id: program_abi::TypeId::Metadata(MetadataTypeId( + elem_ty.initial_type_id.index(), + )), + type_arguments: elem_ty.initial_type_id.get_abi_type_arguments( + handler, ctx, engines, - types, + metadata_types, + concrete_types, elem_ty.type_id, - ), - }; - types.push(elem_abi_ty); + metadata_types_to_add, + )?, + }]) + } else { + unreachable!(); + } + } + TypeInfo::Slice(..) => { + if let TypeInfo::Slice(elem_ty) = &*type_engine.get(resolved_type_id) { + generate_type_metadata_declaration( + handler, + ctx, + engines, + metadata_types, + concrete_types, + elem_ty.initial_type_id, + elem_ty.type_id, + metadata_types_to_add, + )?; // Generate the JSON data for the array. This is basically a single // `program_abi::TypeApplication` for the array element type Some(vec![program_abi::TypeApplication { - name: "__array_element".to_string(), - type_id: elem_ty.initial_type_id.index(), + name: "__slice_element".to_string(), + type_id: program_abi::TypeId::Metadata(MetadataTypeId( + elem_ty.initial_type_id.index(), + )), type_arguments: elem_ty.initial_type_id.get_abi_type_arguments( + handler, ctx, engines, - types, + metadata_types, + concrete_types, elem_ty.type_id, - ), + metadata_types_to_add, + )?, }]) } else { unreachable!(); @@ -408,84 +817,96 @@ impl TypeId { } TypeInfo::Tuple(_) => { if let TypeInfo::Tuple(fields) = &*type_engine.get(resolved_type_id) { - // A list of all `program_abi::TypeDeclaration`s needed for the tuple fields - let fields_types = fields - .iter() - .map(|x| program_abi::TypeDeclaration { - type_id: x.initial_type_id.index(), - type_field: x.initial_type_id.get_abi_type_str( - &ctx.to_str_context(engines, false), - engines, - x.type_id, - ), - components: x - .initial_type_id - .get_abi_type_components(ctx, engines, types, x.type_id), - type_parameters: x - .initial_type_id - .get_abi_type_parameters(ctx, engines, types, x.type_id), - }) - .collect::>(); - - types.extend(fields_types); + let mut new_metadata_types_to_add = + Vec::::new(); + for x in fields.iter() { + generate_type_metadata_declaration( + handler, + ctx, + engines, + metadata_types, + concrete_types, + x.initial_type_id, + x.type_id, + &mut new_metadata_types_to_add, + )?; + } // Generate the JSON data for the tuple. This is basically a list of // `program_abi::TypeApplication`s - Some( - fields - .iter() - .map(|x| program_abi::TypeApplication { + let components = fields + .iter() + .map(|x| { + Ok(program_abi::TypeApplication { name: "__tuple_element".to_string(), - type_id: x.initial_type_id.index(), - type_arguments: x - .initial_type_id - .get_abi_type_arguments(ctx, engines, types, x.type_id), + type_id: program_abi::TypeId::Metadata(MetadataTypeId( + x.initial_type_id.index(), + )), + type_arguments: x.initial_type_id.get_abi_type_arguments( + handler, + ctx, + engines, + metadata_types, + concrete_types, + x.type_id, + metadata_types_to_add, + )?, }) - .collect(), - ) + }) + .collect::, _>>()?; + if components.is_empty() { + None + } else { + metadata_types_to_add.extend(new_metadata_types_to_add); + Some(components) + } } else { unreachable!() } } TypeInfo::Custom { type_arguments, .. } => { if !self.is_generic_parameter(engines, resolved_type_id) { - // A list of all `program_abi::TypeDeclaration`s needed for the type arguments - let type_args = type_arguments - .clone() - .unwrap_or_default() - .iter() - .zip( - resolved_type_id - .get_type_parameters(engines) - .unwrap_or_default() - .iter(), - ) - .map(|(v, p)| program_abi::TypeDeclaration { - type_id: v.initial_type_id.index(), - type_field: v.initial_type_id.get_abi_type_str( - &ctx.to_str_context(engines, false), - engines, - p.type_id, - ), - components: v - .initial_type_id - .get_abi_type_components(ctx, engines, types, p.type_id), - type_parameters: v - .initial_type_id - .get_abi_type_parameters(ctx, engines, types, p.type_id), - }) - .collect::>(); - types.extend(type_args); - - resolved_type_id.get_abi_type_components(ctx, engines, types, resolved_type_id) + for (v, p) in type_arguments.clone().unwrap_or_default().iter().zip( + resolved_type_id + .get_type_parameters(engines) + .unwrap_or_default() + .iter(), + ) { + generate_type_metadata_declaration( + handler, + ctx, + engines, + metadata_types, + concrete_types, + v.initial_type_id, + p.type_id, + metadata_types_to_add, + )?; + } + resolved_type_id.get_abi_type_components( + handler, + ctx, + engines, + metadata_types, + concrete_types, + resolved_type_id, + metadata_types_to_add, + )? } else { None } } TypeInfo::Alias { .. } => { if let TypeInfo::Alias { ty, .. } = &*type_engine.get(resolved_type_id) { - ty.initial_type_id - .get_abi_type_components(ctx, engines, types, ty.type_id) + ty.initial_type_id.get_abi_type_components( + handler, + ctx, + engines, + metadata_types, + concrete_types, + ty.type_id, + metadata_types_to_add, + )? } else { None } @@ -495,239 +916,302 @@ impl TypeId { if *self == resolved_type_id { None } else { - resolved_type_id.get_abi_type_components(ctx, engines, types, resolved_type_id) + resolved_type_id.get_abi_type_components( + handler, + ctx, + engines, + metadata_types, + concrete_types, + resolved_type_id, + metadata_types_to_add, + )? } } _ => None, - } + }) } /// Return the type arguments of a given (potentially generic) type while considering what it /// actually resolves to. These arguments are essentially of type of /// `program_abi::TypeApplication`. The method below also updates the provided list of - /// `program_abi::TypeDeclaration`s to add the newly discovered types. + /// `program_abi::TypeMetadataDeclaration`s to add the newly discovered types. + #[allow(clippy::too_many_arguments)] pub(self) fn get_abi_type_arguments( &self, + handler: &Handler, ctx: &mut AbiContext, engines: &Engines, - types: &mut Vec, + metadata_types: &mut Vec, + concrete_types: &mut Vec, resolved_type_id: TypeId, - ) -> Option> { + metadata_types_to_add: &mut Vec, + ) -> Result>, ErrorEmitted> { let type_engine = engines.te(); let decl_engine = engines.de(); let resolved_params = resolved_type_id.get_type_parameters(engines); - match &*type_engine.get(*self) { + Ok(match &*type_engine.get(*self) { TypeInfo::Custom { type_arguments: Some(type_arguments), .. } => (!type_arguments.is_empty()).then_some({ let resolved_params = resolved_params.unwrap_or_default(); - let abi_type_arguments = type_arguments - .iter() - .zip(resolved_params.iter()) - .map(|(v, p)| program_abi::TypeDeclaration { - type_id: v.initial_type_id.index(), - type_field: v.initial_type_id.get_abi_type_str( - &ctx.to_str_context(engines, false), - engines, - p.type_id, - ), - components: v - .initial_type_id - .get_abi_type_components(ctx, engines, types, p.type_id), - type_parameters: v - .initial_type_id - .get_abi_type_parameters(ctx, engines, types, p.type_id), - }) - .collect::>(); - types.extend(abi_type_arguments); + + for (v, p) in type_arguments.iter().zip(resolved_params.iter()) { + generate_type_metadata_declaration( + handler, + ctx, + engines, + metadata_types, + concrete_types, + v.type_id, + p.type_id, + metadata_types_to_add, + )?; + } type_arguments .iter() - .map(|arg| program_abi::TypeApplication { - name: "".to_string(), - type_id: arg.initial_type_id.index(), - type_arguments: arg.initial_type_id.get_abi_type_arguments( - ctx, - engines, - types, - arg.type_id, - ), + .zip(resolved_params.iter()) + .map(|(arg, p)| { + Ok(program_abi::TypeApplication { + name: "".to_string(), + type_id: program_abi::TypeId::Metadata(MetadataTypeId( + arg.initial_type_id.index(), + )), + type_arguments: arg.initial_type_id.get_abi_type_arguments( + handler, + ctx, + engines, + metadata_types, + concrete_types, + p.type_id, + metadata_types_to_add, + )?, + }) }) - .collect::>() + .collect::, _>>()? }), TypeInfo::Enum(decl_ref) => { let decl = decl_engine.get_enum(decl_ref); - // Here, type_id for each type parameter should contain resolved types - let abi_type_arguments = decl + + let mut new_metadata_types_to_add = + Vec::::new(); + for v in decl.type_parameters.iter() { + generate_type_metadata_declaration( + handler, + ctx, + engines, + metadata_types, + concrete_types, + v.type_id, + v.type_id, + &mut new_metadata_types_to_add, + )?; + } + + let type_arguments = decl .type_parameters .iter() - .map(|v| program_abi::TypeDeclaration { - type_id: v.type_id.index(), - type_field: v.type_id.get_abi_type_str( - &ctx.to_str_context(engines, false), - engines, - v.type_id, - ), - components: v - .type_id - .get_abi_type_components(ctx, engines, types, v.type_id), - type_parameters: v - .type_id - .get_abi_type_parameters(ctx, engines, types, v.type_id), - }) - .collect::>(); - types.extend(abi_type_arguments); - - Some( - decl.type_parameters - .iter() - .map(|arg| program_abi::TypeApplication { + .map(|arg| { + Ok(program_abi::TypeApplication { name: "".to_string(), - type_id: arg.type_id.index(), + type_id: program_abi::TypeId::Metadata(MetadataTypeId( + arg.type_id.index(), + )), type_arguments: arg.type_id.get_abi_type_arguments( + handler, ctx, engines, - types, + metadata_types, + concrete_types, arg.type_id, - ), + &mut new_metadata_types_to_add, + )?, }) - .collect::>(), - ) + }) + .collect::, _>>()?; + + if type_arguments.is_empty() { + None + } else { + metadata_types_to_add.extend(new_metadata_types_to_add); + Some(type_arguments) + } } TypeInfo::Struct(decl_ref) => { let decl = decl_engine.get_struct(decl_ref); - // Here, type_id for each type parameter should contain resolved types - let abi_type_arguments = decl + + let mut new_metadata_types_to_add = + Vec::::new(); + for v in decl.type_parameters.iter() { + generate_type_metadata_declaration( + handler, + ctx, + engines, + metadata_types, + concrete_types, + v.type_id, + v.type_id, + &mut new_metadata_types_to_add, + )?; + } + + let type_arguments = decl .type_parameters .iter() - .map(|v| program_abi::TypeDeclaration { - type_id: v.type_id.index(), - type_field: v.type_id.get_abi_type_str( - &ctx.to_str_context(engines, false), - engines, - v.type_id, - ), - components: v - .type_id - .get_abi_type_components(ctx, engines, types, v.type_id), - type_parameters: v - .type_id - .get_abi_type_parameters(ctx, engines, types, v.type_id), + .map(|arg| { + Ok(program_abi::TypeApplication { + name: "".to_string(), + type_id: program_abi::TypeId::Metadata(MetadataTypeId( + arg.type_id.index(), + )), + type_arguments: arg.type_id.get_abi_type_arguments( + handler, + ctx, + engines, + metadata_types, + concrete_types, + arg.type_id, + &mut new_metadata_types_to_add, + )?, + }) }) - .collect::>(); - types.extend(abi_type_arguments); + .collect::, _>>()?; + if type_arguments.is_empty() { + None + } else { + metadata_types_to_add.extend(new_metadata_types_to_add); + Some(type_arguments) + } + } + _ => None, + }) + } + + /// Return the type arguments of a given (potentially generic) type while considering what it + /// actually resolves to. These arguments are essentially of type of + /// `program_abi::TypeApplication`. The method below also updates the provided list of + /// `program_abi::TypeMetadataDeclaration`s to add the newly discovered types. + pub(self) fn get_abi_type_arguments_as_concrete_type_ids( + &self, + handler: &Handler, + ctx: &mut AbiContext, + engines: &Engines, + metadata_types: &mut Vec, + concrete_types: &mut Vec, + resolved_type_id: TypeId, + ) -> Result>, ErrorEmitted> { + let type_engine = engines.te(); + let decl_engine = engines.de(); + let resolved_params = resolved_type_id.get_type_parameters(engines); + Ok(match &*type_engine.get(*self) { + TypeInfo::Custom { + type_arguments: Some(type_arguments), + .. + } => (!type_arguments.is_empty()).then_some({ + let resolved_params = resolved_params.unwrap_or_default(); + type_arguments + .iter() + .zip(resolved_params.iter()) + .map(|(arg, p)| { + generate_concrete_type_declaration( + handler, + ctx, + engines, + metadata_types, + concrete_types, + arg.initial_type_id, + p.type_id, + ) + }) + .collect::, _>>()? + }), + TypeInfo::Enum(decl_ref) => { + let decl = decl_engine.get_enum(decl_ref); Some( decl.type_parameters .iter() - .map(|arg| program_abi::TypeApplication { - name: "".to_string(), - type_id: arg.type_id.index(), - type_arguments: arg.type_id.get_abi_type_arguments( + .map(|arg| { + generate_concrete_type_declaration( + handler, ctx, engines, - types, + metadata_types, + concrete_types, arg.type_id, - ), + arg.type_id, + ) }) - .collect::>(), + .collect::, _>>()?, + ) + } + TypeInfo::Struct(decl_ref) => { + let decl = decl_engine.get_struct(decl_ref); + Some( + decl.type_parameters + .iter() + .map(|arg| { + generate_concrete_type_declaration( + handler, + ctx, + engines, + metadata_types, + concrete_types, + arg.type_id, + arg.type_id, + ) + }) + .collect::, _>>()?, ) } _ => None, - } + }) } } impl TyFunctionDecl { pub(self) fn generate_abi_function( &self, + handler: &Handler, ctx: &mut AbiContext, engines: &Engines, - types: &mut Vec, - ) -> program_abi::ABIFunction { - // A list of all `program_abi::TypeDeclaration`s needed for inputs - let input_types = self - .parameters - .iter() - .map(|x| program_abi::TypeDeclaration { - type_id: x.type_argument.initial_type_id.index(), - type_field: x.type_argument.initial_type_id.get_abi_type_str( - &ctx.to_str_context(engines, false), - engines, - x.type_argument.type_id, - ), - components: x.type_argument.initial_type_id.get_abi_type_components( - ctx, - engines, - types, - x.type_argument.type_id, - ), - type_parameters: x.type_argument.type_id.get_abi_type_parameters( - ctx, - engines, - types, - x.type_argument.type_id, - ), - }) - .collect::>(); - - // The single `program_abi::TypeDeclaration` needed for the output - let output_type = program_abi::TypeDeclaration { - type_id: self.return_type.initial_type_id.index(), - type_field: self.return_type.initial_type_id.get_abi_type_str( - &ctx.to_str_context(engines, false), - engines, - self.return_type.type_id, - ), - components: self.return_type.type_id.get_abi_type_components( - ctx, - engines, - types, - self.return_type.type_id, - ), - type_parameters: self.return_type.type_id.get_abi_type_parameters( - ctx, - engines, - types, - self.return_type.type_id, - ), - }; - - // Add the new types to `types` - types.extend(input_types); - types.push(output_type); - + metadata_types: &mut Vec, + concrete_types: &mut Vec, + ) -> Result { // Generate the JSON data for the function - program_abi::ABIFunction { + Ok(program_abi::ABIFunction { name: self.name.as_str().to_string(), inputs: self .parameters .iter() - .map(|x| program_abi::TypeApplication { - name: x.name.to_string(), - type_id: x.type_argument.initial_type_id.index(), - type_arguments: x.type_argument.initial_type_id.get_abi_type_arguments( - ctx, - engines, - types, - x.type_argument.type_id, - ), + .map(|x| { + Ok(program_abi::TypeConcreteParameter { + name: x.name.to_string(), + concrete_type_id: generate_concrete_type_declaration( + handler, + ctx, + engines, + metadata_types, + concrete_types, + x.type_argument.initial_type_id, + x.type_argument.type_id, + )?, + }) }) - .collect(), - output: program_abi::TypeApplication { - name: "".to_string(), - type_id: self.return_type.initial_type_id.index(), - type_arguments: self.return_type.initial_type_id.get_abi_type_arguments( - ctx, - engines, - types, - self.return_type.type_id, - ), - }, + .collect::, _>>()?, + output: generate_concrete_type_declaration( + handler, + ctx, + engines, + metadata_types, + concrete_types, + self.return_type.initial_type_id, + self.return_type.type_id, + )?, attributes: generate_attributes_map(&self.attributes), - } + }) } } @@ -751,29 +1235,36 @@ fn generate_attributes_map(attr_map: &AttributesMap) -> Option, - ) -> usize { - let type_parameter = program_abi::TypeDeclaration { - type_id: self.initial_type_id.index(), + metadata_types: &mut Vec, + concrete_types: &mut Vec, + metadata_types_to_add: &mut Vec, + ) -> Result { + let type_id = MetadataTypeId(self.initial_type_id.index()); + let type_parameter = program_abi::TypeMetadataDeclaration { + metadata_type_id: type_id.clone(), type_field: self.initial_type_id.get_abi_type_str( &ctx.to_str_context(engines, false), engines, self.type_id, ), components: self.initial_type_id.get_abi_type_components( + handler, ctx, engines, - types, + metadata_types, + concrete_types, self.type_id, - ), + metadata_types_to_add, + )?, type_parameters: None, }; - types.push(type_parameter); - self.initial_type_id.index() + metadata_types_to_add.push(type_parameter); + Ok(type_id) } } diff --git a/sway-core/src/asm_generation/finalized_asm.rs b/sway-core/src/asm_generation/finalized_asm.rs index 2fc0fe4326d..ce3c81e3a56 100644 --- a/sway-core/src/asm_generation/finalized_asm.rs +++ b/sway-core/src/asm_generation/finalized_asm.rs @@ -1,9 +1,9 @@ use super::instruction_set::InstructionSet; -use super::ToMidenBytecode; use super::{ fuel::{checks, data_section::DataSection}, ProgramABI, ProgramKind, }; +use crate::asm_generation::fuel::data_section::{DataId, Datum, Entry}; use crate::asm_lang::allocated_ops::{AllocatedOp, AllocatedOpcode}; use crate::decl_engine::DeclRefFunction; use crate::source_map::SourceMap; @@ -77,10 +77,6 @@ impl FinalizedAsm { }) } } - InstructionSet::MidenVM { ops } => Ok(CompiledBytecode { - bytecode: ops.to_bytecode().into(), - named_data_section_entries_offsets: Default::default(), - }), } } } @@ -151,6 +147,13 @@ fn to_bytecode_mut( println!(";; --- START OF TARGET BYTECODE ---\n"); } + let mut last_span = None; + let mut indentation = if build_config.print_bytecode_spans { + 4 + } else { + 0 + }; + let mut half_word_ix = 0; let mut offset_from_instr_start = 0; for op in ops.iter() { @@ -165,7 +168,7 @@ fn to_bytecode_mut( match fuel_op { Either::Right(data) => { if build_config.print_bytecode { - print!("{:#010x} ", bytecode.len()); + print!("{}{:#010x} ", " ".repeat(indentation), bytecode.len()); println!( " ;; {:?}", data @@ -181,8 +184,45 @@ fn to_bytecode_mut( } Either::Left(instructions) => { for instruction in instructions { + // Print original source span only once + if build_config.print_bytecode_spans { + last_span = match (last_span, &span) { + (None, Some(span)) => { + indentation = 4; + let line_col = span.start_pos().line_col(); + println!( + "{} @ {}:{}:{}", + span.as_str(), + span.source_id() + .map(|source_id| source_engine.get_path(source_id)) + .map(|x| x.display().to_string()) + .unwrap_or("".to_string()), + line_col.line, + line_col.col + ); + Some(span.clone()) + } + (Some(last), Some(span)) if last != *span => { + indentation = 4; + let line_col = span.start_pos().line_col(); + println!( + "{} @ {}:{}:{}", + span.as_str(), + span.source_id() + .map(|source_id| source_engine.get_path(source_id)) + .map(|x| x.display().to_string()) + .unwrap_or("".to_string()), + line_col.line, + line_col.col + ); + Some(span.clone()) + } + (last, _) => last, + }; + } + if build_config.print_bytecode { - print!("{:#010x} ", bytecode.len()); + print!("{}{:#010x} ", " ".repeat(indentation), bytecode.len()); print_instruction(&instruction); } @@ -202,8 +242,64 @@ fn to_bytecode_mut( } } } + if build_config.print_bytecode { - println!("{}", data_section); + println!(".data_section:"); + + let offset = bytecode.len(); + + fn print_entry(indentation: usize, offset: usize, pair: &Entry) { + print!("{}{:#010x} ", " ".repeat(indentation), offset); + + match &pair.value { + Datum::Byte(w) => println!(".byte i{w}, as hex {w:02X}"), + Datum::Word(w) => { + println!(".word i{w}, as hex be bytes ({:02X?})", w.to_be_bytes()) + } + Datum::ByteArray(bs) => { + print!(".bytes as hex ({bs:02X?}), len i{}, as ascii \"", bs.len()); + + for b in bs { + print!( + "{}", + if *b == b' ' || b.is_ascii_graphic() { + *b as char + } else { + '.' + } + ); + } + println!("\""); + } + Datum::Slice(bs) => { + print!(".slice as hex ({bs:02X?}), len i{}, as ascii \"", bs.len()); + + for b in bs { + print!( + "{}", + if *b == b' ' || b.is_ascii_graphic() { + *b as char + } else { + '.' + } + ); + } + println!("\""); + } + Datum::Collection(els) => { + println!(".collection"); + for e in els { + print_entry(indentation + 1, offset, e); + } + } + }; + } + + for (i, entry) in data_section.value_pairs.iter().enumerate() { + let entry_offset = data_section.data_id_to_offset(&DataId(i as u32)); + print_entry(indentation, offset + entry_offset, entry); + } + println!(";; --- END OF TARGET BYTECODE ---\n"); } @@ -436,6 +532,8 @@ fn print_instruction(op: &Instruction) { Instruction::WDMM(x) => f("WDMM", x.unpack()), Instruction::WQMM(x) => f("WQMM", x.unpack()), Instruction::ECAL(x) => f("ECAL", x.unpack()), + Instruction::BSIZ(x) => f("BSIZ", x.unpack()), + Instruction::BLDD(x) => f("BLDD", x.unpack()), } } @@ -450,6 +548,5 @@ pub fn check_invalid_opcodes(handler: &Handler, asm: &FinalizedAsm) -> Result<() ProgramKind::Predicate => checks::check_predicate_opcodes(handler, &ops[..]), }, InstructionSet::Evm { ops: _ } => Ok(()), - InstructionSet::MidenVM { ops: _ } => Ok(()), } } diff --git a/sway-core/src/asm_generation/from_ir.rs b/sway-core/src/asm_generation/from_ir.rs index f29354c2fca..1a0435409ff 100644 --- a/sway-core/src/asm_generation/from_ir.rs +++ b/sway-core/src/asm_generation/from_ir.rs @@ -7,7 +7,6 @@ use super::{ fuel_asm_builder::FuelAsmBuilder, register_sequencer::RegisterSequencer, }, - MidenVMAsmBuilder, }; use crate::{asm_generation::ProgramKind, BuildConfig, BuildTarget}; @@ -57,13 +56,6 @@ pub fn compile_ir_context_to_finalized_asm( build_config, EvmAsmBuilder::new(kind, ir), ), - BuildTarget::MidenVM => compile( - handler, - ir, - module, - build_config, - MidenVMAsmBuilder::new(kind, ir), - ), }?; check_invalid_opcodes(handler, &finalized_asm)?; diff --git a/sway-core/src/asm_generation/fuel/abstract_instruction_set.rs b/sway-core/src/asm_generation/fuel/abstract_instruction_set.rs index cd1156f38e8..32ef5a7f538 100644 --- a/sway-core/src/asm_generation/fuel/abstract_instruction_set.rs +++ b/sway-core/src/asm_generation/fuel/abstract_instruction_set.rs @@ -27,9 +27,10 @@ impl AbstractInstructionSet { pub(crate) fn optimize(self, data_section: &DataSection) -> AbstractInstructionSet { self.const_indexing_aggregates_function(data_section) .dce() + .simplify_cfg() .remove_sequential_jumps() .remove_redundant_moves() - .remove_unused_ops() + .remove_redundant_ops() } /// Removes any jumps to the subsequent line. @@ -51,7 +52,7 @@ impl AbstractInstructionSet { for idx in dead_jumps { self.ops[idx] = Op { opcode: Either::Left(VirtualOp::NOOP), - comment: "removed redundant JUMP".into(), + comment: "remove redundant jump operation".into(), owning_span: None, }; } @@ -104,7 +105,7 @@ impl AbstractInstructionSet { for idx in dead_moves { self.ops[idx] = Op { opcode: Either::Left(VirtualOp::NOOP), - comment: "removed redundant MOVE".into(), + comment: "remove redundant move operation".into(), owning_span: None, }; } @@ -113,11 +114,18 @@ impl AbstractInstructionSet { self } - fn remove_unused_ops(mut self) -> AbstractInstructionSet { - // Just remove NOPs for now. - self.ops.retain(|op| match &op.opcode { - Either::Left(VirtualOp::NOOP) => false, - _otherwise => true, + fn remove_redundant_ops(mut self) -> AbstractInstructionSet { + self.ops.retain(|op| { + // It is easier to think in terms of operations we want to remove + // than the operations we want to retain ;-) + #[allow(clippy::match_like_matches_macro)] + // Keep the `match` for adding more ops in the future. + let remove = match &op.opcode { + Either::Left(VirtualOp::NOOP) => true, + _ => false, + }; + + !remove }); self diff --git a/sway-core/src/asm_generation/fuel/allocated_abstract_instruction_set.rs b/sway-core/src/asm_generation/fuel/allocated_abstract_instruction_set.rs index 38466cf3edc..0865687f5c8 100644 --- a/sway-core/src/asm_generation/fuel/allocated_abstract_instruction_set.rs +++ b/sway-core/src/asm_generation/fuel/allocated_abstract_instruction_set.rs @@ -35,6 +35,30 @@ pub struct AllocatedAbstractInstructionSet { } impl AllocatedAbstractInstructionSet { + pub(crate) fn optimize(self) -> AllocatedAbstractInstructionSet { + self.remove_redundant_ops() + } + + fn remove_redundant_ops(mut self) -> AllocatedAbstractInstructionSet { + self.ops.retain(|op| { + // It is easier to think in terms of operations we want to remove + // than the operations we want to retain ;-) + let remove = match &op.opcode { + // `cfei i0` and `cfsi i0` pairs. + Either::Left(AllocatedOpcode::CFEI(imm)) + | Either::Left(AllocatedOpcode::CFSI(imm)) => imm.value == 0u32, + // `cfe $zero` and `cfs $zero` pairs. + Either::Left(AllocatedOpcode::CFE(reg)) + | Either::Left(AllocatedOpcode::CFS(reg)) => reg.is_zero(), + _ => false, + }; + + !remove + }); + + self + } + /// Replace each PUSHA instruction with stores of all used registers to the stack, and each /// POPA with respective loads from the stack. /// @@ -120,15 +144,15 @@ impl AllocatedAbstractInstructionSet { if mask_l.value != 0 { new_ops.push(AllocatedAbstractOp { opcode: Either::Left(AllocatedOpcode::PSHL(mask_l)), - comment: "Save registers 16..40".into(), - owning_span: None, + comment: "save registers 16..40".into(), + owning_span: op.owning_span.clone(), }); } if mask_h.value != 0 { new_ops.push(AllocatedAbstractOp { opcode: Either::Left(AllocatedOpcode::PSHH(mask_h)), - comment: "Save registers 40..64".into(), - owning_span: None, + comment: "save registers 40..64".into(), + owning_span: op.owning_span.clone(), }); } } @@ -146,15 +170,15 @@ impl AllocatedAbstractInstructionSet { if mask_h.value != 0 { new_ops.push(AllocatedAbstractOp { opcode: Either::Left(AllocatedOpcode::POPH(mask_h)), - comment: "Restore registers 40..64".into(), - owning_span: None, + comment: "restore registers 40..64".into(), + owning_span: op.owning_span.clone(), }); } if mask_l.value != 0 { new_ops.push(AllocatedAbstractOp { opcode: Either::Left(AllocatedOpcode::POPL(mask_l)), - comment: "Restore registers 16..40".into(), - owning_span: None, + comment: "restore registers 16..40".into(), + owning_span: op.owning_span.clone(), }); } } @@ -299,7 +323,8 @@ impl AllocatedAbstractInstructionSet { AllocatedRegister::Constant(ConstantRegister::InstructionStart), ), owning_span: owning_span.clone(), - comment: "Get current instruction offset from Instruction start".into(), + comment: "get current instruction offset from instructions start ($is)" + .into(), }); realized_ops.push(RealizedOp { opcode: AllocatedOpcode::SRLI( @@ -308,7 +333,7 @@ impl AllocatedAbstractInstructionSet { VirtualImmediate12 { value: 2 }, ), owning_span: owning_span.clone(), - comment: "Current instruction offset in 32b words".into(), + comment: "get current instruction offset in 32-bit words".into(), }); realized_ops.push(RealizedOp { opcode: AllocatedOpcode::ADDI(r1.clone(), r1, imm), @@ -540,7 +565,7 @@ impl AllocatedAbstractInstructionSet { if rel_offset(lab) == 0 { new_ops.push(AllocatedAbstractOp { opcode: Either::Left(AllocatedOpcode::NOOP), - comment: "NOP for self loop".into(), + comment: "emit noop for self loop".into(), owning_span: None, }); new_ops.push(op); @@ -583,7 +608,7 @@ impl AllocatedAbstractInstructionSet { if rel_offset(lab) == 0 { new_ops.push(AllocatedAbstractOp { opcode: Either::Left(AllocatedOpcode::NOOP), - comment: "NOP for self loop".into(), + comment: "emit noop for self loop".into(), owning_span: None, }); new_ops.push(op); @@ -628,7 +653,7 @@ impl AllocatedAbstractInstructionSet { if rel_offset(lab) <= consts::TWELVE_BITS { new_ops.push(op) } else { - panic!("Return to address must be right after the call for which we saved this addr."); + panic!("Return to address must be right after the call for which we saved this address."); } } diff --git a/sway-core/src/asm_generation/fuel/data_section.rs b/sway-core/src/asm_generation/fuel/data_section.rs index 10dc27f0da8..3db12443f4f 100644 --- a/sway-core/src/asm_generation/fuel/data_section.rs +++ b/sway-core/src/asm_generation/fuel/data_section.rs @@ -137,6 +137,9 @@ impl Entry { ConstantValue::Reference(_) => { todo!("Constant references are currently not supported.") } + ConstantValue::Slice(_) => { + todo!("Constant slices are currently not supported.") + } } } diff --git a/sway-core/src/asm_generation/fuel/fuel_asm_builder.rs b/sway-core/src/asm_generation/fuel/fuel_asm_builder.rs index 9b8a6076e6f..b08361476c2 100644 --- a/sway-core/src/asm_generation/fuel/fuel_asm_builder.rs +++ b/sway-core/src/asm_generation/fuel/fuel_asm_builder.rs @@ -114,7 +114,7 @@ impl<'ir, 'eng> AsmBuilder for FuelAsmBuilder<'ir, 'eng> { self.globals_section.insert(name, size_in_bytes); let global = self.globals_section.get_by_name(name).unwrap(); - let (decode_fn_label, _) = self.func_label_map.get(decode_fn).unwrap(); + let (decode_fn_label, _) = self.func_label_map.get(&decode_fn.get()).unwrap(); let dataid = self.data_section.insert_data_value(Entry::new_byte_array( encoded_bytes.clone(), Some(name.clone()), @@ -126,7 +126,7 @@ impl<'ir, 'eng> AsmBuilder for FuelAsmBuilder<'ir, 'eng> { VirtualRegister::Constant(ConstantRegister::FuncArg0), dataid, )), - comment: format!("ptr to {} default value", name), + comment: format!("get pointer to configurable {} default value", name), owning_span: None, }); @@ -138,7 +138,7 @@ impl<'ir, 'eng> AsmBuilder for FuelAsmBuilder<'ir, 'eng> { value: encoded_bytes.len() as u16, }, )), - comment: format!("length of {} default value", name), + comment: format!("get length of configurable {} default value", name), owning_span: None, }); @@ -150,7 +150,7 @@ impl<'ir, 'eng> AsmBuilder for FuelAsmBuilder<'ir, 'eng> { value: global.offset_in_bytes as u16, }, )), - comment: format!("ptr to global {} stack address", name), + comment: format!("get pointer to configurable {} stack address", name), owning_span: None, }); @@ -159,14 +159,14 @@ impl<'ir, 'eng> AsmBuilder for FuelAsmBuilder<'ir, 'eng> { self.before_entries.push(Op::save_ret_addr( VirtualRegister::Constant(ConstantRegister::CallReturnAddress), ret_label, - "", + "set new return address", None, )); // call decode self.before_entries.push(Op { opcode: Either::Right(crate::asm_lang::ControlFlowOp::Call(*decode_fn_label)), - comment: format!("decode {}", name), + comment: format!("decode configurable {}", name), owning_span: None, }); @@ -334,7 +334,7 @@ impl<'ir, 'eng> FuelAsmBuilder<'ir, 'eng> { self.cur_bytecode.push(Op::register_move( arg_reg.clone(), phi_reg.clone(), - "parameter from branch to block argument", + "move parameter from branch to block argument", None, )); } @@ -354,7 +354,7 @@ impl<'ir, 'eng> FuelAsmBuilder<'ir, 'eng> { ) -> Result<(), ErrorEmitted> { let Some(instruction) = instr_val.get_instruction(self.context) else { return Err(handler.emit_err(CompileError::Internal( - "Value not an instruction.", + "Value is not an instruction.", self.md_mgr .val_to_span(self.context, *instr_val) .unwrap_or_else(Span::dummy), @@ -543,7 +543,9 @@ impl<'ir, 'eng> FuelAsmBuilder<'ir, 'eng> { const_copy.clone(), init_val_reg, )), - comment: "copy const asm init to GP reg".into(), + comment: + "copy ASM block argument's constant initial value to register" + .into(), owning_span: self.md_mgr.val_to_span(self.context, *instr_val), }); const_copy @@ -609,10 +611,11 @@ impl<'ir, 'eng> FuelAsmBuilder<'ir, 'eng> { }); } - // Now, load the designated asm return register into the desired return register, but only - // if it was named. - if let Some(ret_reg_name) = &asm_block.return_name { - // Lookup and replace the return register. + // ASM block always returns a value. The return value is either the one contained in + // the return register specified at the end of the ASM block, or it is unit, `()`, in + // the case of an ASM block without the return register specified. + let (ret_reg, comment) = if let Some(ret_reg_name) = &asm_block.return_name { + // If the return register is specified, lookup it by name. let ret_reg = match realize_register(ret_reg_name.as_str()) { Some(reg) => reg, None => { @@ -626,14 +629,40 @@ impl<'ir, 'eng> FuelAsmBuilder<'ir, 'eng> { })); } }; - let instr_reg = self.reg_seqr.next(); - inline_ops.push(Op { - opcode: Either::Left(VirtualOp::MOVE(instr_reg.clone(), ret_reg)), - comment: format!("return value from inline asm ({})", ret_reg_name), - owning_span: self.md_mgr.val_to_span(self.context, *instr_val), - }); - self.reg_map.insert(*instr_val, instr_reg); - } + + ( + ret_reg, + format!( + "return value from ASM block with return register {}", + ret_reg_name + ), + ) + } else { + // If the return register is not specified, the return value is unit, `()`, and we + // move constant register $zero to the final instruction register. + if !asm_block.return_type.is_unit(self.context) { + return Err(handler.emit_err(CompileError::InternalOwned( + format!("Return type of an ASM block without return register must be unit, but it was {}.", asm_block.return_type.as_string(self.context)), + self.md_mgr + .val_to_span(self.context, *instr_val) + .unwrap_or_else(Span::dummy), + ))); + } + + ( + VirtualRegister::Constant(ConstantRegister::Zero), + "return unit value from ASM block without return register".into(), + ) + }; + + // Move the return register to the instruction register. + let instr_reg = self.reg_seqr.next(); + inline_ops.push(Op { + opcode: Either::Left(VirtualOp::MOVE(instr_reg.clone(), ret_reg)), + comment, + owning_span: self.md_mgr.val_to_span(self.context, *instr_val), + }); + self.reg_map.insert(*instr_val, instr_reg); self.cur_bytecode.append(&mut inline_ops); @@ -648,7 +677,8 @@ impl<'ir, 'eng> FuelAsmBuilder<'ir, 'eng> { ) -> Result<(), CompileError> { let val_reg = self.value_to_register(bitcast_val)?; let reg = if to_type.is_bool(self.context) { - // This may not be necessary if we just treat a non-zero value as 'true'. + // We treat only one as `true`, and not every non-zero value. + // So, every non-zero value must be converted to one. let res_reg = self.reg_seqr.next(); self.cur_bytecode.push(Op { opcode: Either::Left(VirtualOp::EQ( @@ -656,7 +686,7 @@ impl<'ir, 'eng> FuelAsmBuilder<'ir, 'eng> { val_reg, VirtualRegister::Constant(ConstantRegister::Zero), )), - comment: "convert to inversed boolean".into(), + comment: "[bitcast to bool]: convert value to inverted boolean".into(), owning_span: self.md_mgr.val_to_span(self.context, *instr_val), }); self.cur_bytecode.push(Op { @@ -665,13 +695,15 @@ impl<'ir, 'eng> FuelAsmBuilder<'ir, 'eng> { res_reg.clone(), VirtualImmediate12 { value: 1 }, )), - comment: "invert boolean".into(), + comment: "[bitcast to bool]: invert inverted boolean".into(), owning_span: self.md_mgr.val_to_span(self.context, *instr_val), }); res_reg + } else if to_type.is_unit(self.context) { + // Unit is represented as zero. + VirtualRegister::Constant(ConstantRegister::Zero) } else { - // This is a no-op, although strictly speaking Unit should probably be compiled as - // a zero. + // For all other values, bitcast is a no-op. val_reg }; self.reg_map.insert(*instr_val, reg); @@ -1019,7 +1051,7 @@ impl<'ir, 'eng> FuelAsmBuilder<'ir, 'eng> { self.cur_bytecode.push(Op::register_move( phi_reg.clone(), local_reg, - "parameter from branch to block argument", + "move parameter from branch to block argument", None, )); } @@ -1052,13 +1084,13 @@ impl<'ir, 'eng> FuelAsmBuilder<'ir, 'eng> { owning_span: self.md_mgr.val_to_span(self.context, *instr_val), }); - // now, move the return value of the contract call to the return register. + // Now, move the return value of the contract call to the return register. // TODO validate RETL matches the expected type (this is a comment from the old codegen) let instr_reg = self.reg_seqr.next(); self.cur_bytecode.push(Op::register_move( instr_reg.clone(), VirtualRegister::Constant(ConstantRegister::ReturnValue), - "save call result", + "save external contract call result", None, )); self.reg_map.insert(*instr_val, instr_reg); @@ -1153,7 +1185,7 @@ impl<'ir, 'eng> FuelAsmBuilder<'ir, 'eng> { array_elem_size, size_reg.clone(), None, - "get size of element", + "get array element size", owning_span.clone(), ); @@ -1175,7 +1207,7 @@ impl<'ir, 'eng> FuelAsmBuilder<'ir, 'eng> { reg, offset_reg.clone(), )), - comment: "add to array base".into(), + comment: "add array element offset to array base".into(), owning_span: owning_span.clone(), }); @@ -1198,7 +1230,7 @@ impl<'ir, 'eng> FuelAsmBuilder<'ir, 'eng> { const_offs, instr_reg.clone(), Some(&base_reg), - "get offset to element", + "get offset to aggregate element", owning_span.clone(), ); self.reg_map.insert(*instr_val, instr_reg); @@ -1312,7 +1344,7 @@ impl<'ir, 'eng> FuelAsmBuilder<'ir, 'eng> { value: g.offset_in_bytes as u16, }, )), - comment: format!("configurable {} address", name), + comment: format!("get address of configurable {}", name), owning_span: self.md_mgr.val_to_span(self.context, *addr_val), }); self.reg_map.insert(*addr_val, addr_reg); @@ -1324,7 +1356,7 @@ impl<'ir, 'eng> FuelAsmBuilder<'ir, 'eng> { addr_reg.clone(), dataid.clone(), )), - comment: format!("configurable {} address", name), + comment: format!("get address of configurable {}", name), owning_span: self.md_mgr.val_to_span(self.context, *addr_val), }); self.reg_map.insert(*addr_val, addr_reg); @@ -1381,7 +1413,7 @@ impl<'ir, 'eng> FuelAsmBuilder<'ir, 'eng> { src_reg, VirtualImmediate12 { value: 0 }, )), - comment: "load value".into(), + comment: "load byte".into(), owning_span, }); } @@ -1392,7 +1424,7 @@ impl<'ir, 'eng> FuelAsmBuilder<'ir, 'eng> { src_reg, VirtualImmediate12 { value: 0 }, )), - comment: "load value".into(), + comment: "load word".into(), owning_span, }); } @@ -1433,13 +1465,13 @@ impl<'ir, 'eng> FuelAsmBuilder<'ir, 'eng> { value: byte_len as u32, }, )), - comment: "get length for mcp".into(), + comment: "get data length for memory copy".into(), owning_span: owning_span.clone(), }); self.cur_bytecode.push(Op { opcode: Either::Left(VirtualOp::MCP(dst_reg, src_reg, len_reg)), - comment: "copy memory with mem_copy".into(), + comment: "copy memory".into(), owning_span, }); @@ -1487,7 +1519,7 @@ impl<'ir, 'eng> FuelAsmBuilder<'ir, 'eng> { VirtualRegister::Constant(ConstantRegister::Zero), VirtualRegister::Constant(ConstantRegister::Zero), )), - comment: "".into(), + comment: "log non-pointer value".into(), }); } else { // If the type is a pointer then we use LOGD to log the data. First put the size into @@ -1507,7 +1539,7 @@ impl<'ir, 'eng> FuelAsmBuilder<'ir, 'eng> { VirtualImmediate12 { value: 0 }, )), owning_span: owning_span.clone(), - comment: "load slice ptr".into(), + comment: "load slice pointer for logging data".into(), }); self.cur_bytecode.push(Op { opcode: Either::Left(VirtualOp::LW( @@ -1516,7 +1548,7 @@ impl<'ir, 'eng> FuelAsmBuilder<'ir, 'eng> { VirtualImmediate12 { value: 1 }, )), owning_span: owning_span.clone(), - comment: "load slice size".into(), + comment: "load slice size for logging data".into(), }); self.cur_bytecode.push(Op { owning_span, @@ -1536,7 +1568,7 @@ impl<'ir, 'eng> FuelAsmBuilder<'ir, 'eng> { size_in_bytes, size_reg.clone(), None, - "loading size for LOGD", + "load data size for logging data", owning_span.clone(), ); @@ -1548,7 +1580,7 @@ impl<'ir, 'eng> FuelAsmBuilder<'ir, 'eng> { log_val_reg.clone(), size_reg, )), - comment: "log ptr".into(), + comment: "log data".into(), }); } } @@ -1578,7 +1610,7 @@ impl<'ir, 'eng> FuelAsmBuilder<'ir, 'eng> { sway_ir::Register::Flag => ConstantRegister::Flags, }), )), - comment: "move register into abi function".to_owned(), + comment: "read special register".to_owned(), owning_span: self.md_mgr.val_to_span(self.context, *instr_val), }); @@ -1601,7 +1633,7 @@ impl<'ir, 'eng> FuelAsmBuilder<'ir, 'eng> { ConstantRegister::Zero, ))), owning_span, - comment: "returning unit as zero".into(), + comment: "return unit as zero".into(), }); } else { let ret_reg = self.value_to_register(ret_val)?; @@ -1636,7 +1668,7 @@ impl<'ir, 'eng> FuelAsmBuilder<'ir, 'eng> { VirtualImmediate12 { value: 0 }, )), owning_span: owning_span.clone(), - comment: "load ptr of returned slice".into(), + comment: "load pointer to returned slice".into(), }); } else { let size_in_bytes = ret_type @@ -1648,7 +1680,7 @@ impl<'ir, 'eng> FuelAsmBuilder<'ir, 'eng> { size_in_bytes, size_reg.clone(), None, - "get size of returned ref", + "get size of type returned by pointer", owning_span.clone(), ); } @@ -1693,7 +1725,7 @@ impl<'ir, 'eng> FuelAsmBuilder<'ir, 'eng> { VirtualRegister::Constant(ConstantRegister::HeapPointer), VirtualImmediate12::new(0, Span::dummy()).unwrap(), )), - comment: "jmp_mem: Load MEM[$hp]".into(), + comment: "[jump]: load word from MEM[$hp]".into(), }); self.cur_bytecode.push(Op { owning_span: owning_span.clone(), @@ -1702,7 +1734,7 @@ impl<'ir, 'eng> FuelAsmBuilder<'ir, 'eng> { target_reg, VirtualRegister::Constant(ConstantRegister::InstructionStart), )), - comment: "jmp_mem: Subtract $is since Jmp adds it back.".into(), + comment: "[jump]: subtract instructions start ($is) since jmp adds it back".into(), }); self.cur_bytecode.push(Op { owning_span: owning_span.clone(), @@ -1711,13 +1743,13 @@ impl<'ir, 'eng> FuelAsmBuilder<'ir, 'eng> { is_target_reg.clone(), VirtualImmediate12::new(4, Span::dummy()).unwrap(), )), - comment: "jmp_mem: Divide by 4 since Jmp multiplies by 4.".into(), + comment: "[jump]: divide by 4 since jmp multiplies by 4".into(), }); self.cur_bytecode.push(Op { owning_span, opcode: Either::Left(VirtualOp::JMP(by4_reg)), - comment: "jmp_mem: Jump to computed value".into(), + comment: "[jump]: jump to computed value".into(), }); Ok(()) @@ -1785,7 +1817,7 @@ impl<'ir, 'eng> FuelAsmBuilder<'ir, 'eng> { was_slot_set_reg.clone(), number_of_slots_reg, )), - comment: "clear a sequence of storage slots".into(), + comment: "clear sequence of storage slots".into(), owning_span, }); @@ -1839,7 +1871,13 @@ impl<'ir, 'eng> FuelAsmBuilder<'ir, 'eng> { number_of_slots_reg, ), }), - comment: "access a sequence of storage slots".into(), + comment: format!( + "{} sequence of storage slots", + match access_type { + StateAccessType::Read => "read", + StateAccessType::Write => "write", + } + ), owning_span, }); @@ -1872,7 +1910,7 @@ impl<'ir, 'eng> FuelAsmBuilder<'ir, 'eng> { self.cur_bytecode.push(Op { opcode: Either::Left(VirtualOp::SRW(load_reg.clone(), was_slot_set_reg, key_reg)), - comment: "single word state access".into(), + comment: "read single word from contract state".into(), owning_span, }); @@ -1909,7 +1947,7 @@ impl<'ir, 'eng> FuelAsmBuilder<'ir, 'eng> { self.cur_bytecode.push(Op { opcode: Either::Left(VirtualOp::SWW(key_reg, was_slot_set_reg.clone(), store_reg)), - comment: "single word state access".into(), + comment: "write single word to contract state".into(), owning_span, }); @@ -1949,7 +1987,7 @@ impl<'ir, 'eng> FuelAsmBuilder<'ir, 'eng> { val_reg, VirtualImmediate12 { value: 0 }, )), - comment: "store value".into(), + comment: "store byte".into(), owning_span, }); } @@ -1960,7 +1998,7 @@ impl<'ir, 'eng> FuelAsmBuilder<'ir, 'eng> { val_reg, VirtualImmediate12 { value: 0 }, )), - comment: "store value".into(), + comment: "store word".into(), owning_span, }); } @@ -2015,7 +2053,7 @@ impl<'ir, 'eng> FuelAsmBuilder<'ir, 'eng> { (VirtualRegister::Constant(ConstantRegister::Zero), None) } - ConstantValue::Uint(1) if config_name.is_none() => { + ConstantValue::Uint(1) | ConstantValue::Bool(true) if config_name.is_none() => { (VirtualRegister::Constant(ConstantRegister::One), None) } @@ -2031,7 +2069,7 @@ impl<'ir, 'eng> FuelAsmBuilder<'ir, 'eng> { reg.clone(), data_id.clone(), )), - comment: "literal instantiation".into(), + comment: "load constant from data section".into(), owning_span: span, }); (reg, Some(data_id)) @@ -2055,7 +2093,7 @@ impl<'ir, 'eng> FuelAsmBuilder<'ir, 'eng> { // to determine when it may be initialised and/or reused. } - // Get the reg corresponding to `value`. Returns an ICE if the value is not in reg_map or is + // Get the reg corresponding to `value`. Returns an ICE if the value is not in `reg_map` or is // not a constant. pub(super) fn value_to_register( &mut self, @@ -2080,7 +2118,7 @@ impl<'ir, 'eng> FuelAsmBuilder<'ir, 'eng> { let reg = self.reg_seqr.next(); self.cur_bytecode.push(Op { opcode: Either::Left(VirtualOp::MOVI(reg.clone(), imm)), - comment: "initializer constant into register".into(), + comment: "initialize constant into register".into(), owning_span: None, }); reg diff --git a/sway-core/src/asm_generation/fuel/functions.rs b/sway-core/src/asm_generation/fuel/functions.rs index fed3a7ed0a3..42577c543d6 100644 --- a/sway-core/src/asm_generation/fuel/functions.rs +++ b/sway-core/src/asm_generation/fuel/functions.rs @@ -79,54 +79,14 @@ impl<'ir, 'eng> FuelAsmBuilder<'ir, 'eng> { self.cur_bytecode.push(Op::register_move( VirtualRegister::Constant(ConstantRegister::ARG_REGS[idx]), arg_reg, - format!("pass arg {idx}"), + format!("[call]: pass argument {idx}"), self.md_mgr.val_to_span(self.context, *arg_val), )); } } else { - // Put NUM_ARG_REGISTERS - 1 arguments into arg registers and rest into the stack. - for (idx, arg_val) in args.iter().enumerate() { - let arg_reg = self.value_to_register(arg_val)?; - // Except for the last arg register, the others hold an argument. - if idx < compiler_constants::NUM_ARG_REGISTERS as usize - 1 { - self.cur_bytecode.push(Op::register_move( - VirtualRegister::Constant(ConstantRegister::ARG_REGS[idx]), - arg_reg, - format!("pass arg {idx}"), - self.md_mgr.val_to_span(self.context, *arg_val), - )); - } else { - // All arguments [NUM_ARG_REGISTERS - 1 ..] go into the stack. - assert!( - self.locals_size_bytes() % 8 == 0, - "The size of locals is not word aligned" - ); - let stack_offset_bytes = self.locals_size_bytes() - + (((idx as u64 + 1) - compiler_constants::NUM_ARG_REGISTERS as u64) * 8); - assert!( - stack_offset_bytes - < self.locals_size_bytes() + (self.max_num_extra_args() * 8) - ); - self.cur_bytecode.push(Op { - opcode: Either::Left(VirtualOp::SW( - VirtualRegister::Constant(ConstantRegister::LocalsBase), - arg_reg, - VirtualImmediate12::new( - // The VM multiples the offset by 8, so we divide it by 8. - stack_offset_bytes / 8, - self.md_mgr - .val_to_span(self.context, *arg_val) - .unwrap_or(Span::dummy()), - ) - .expect("Too many arguments, cannot handle."), - )), - comment: format!("Pass arg {idx} via its stack slot"), - owning_span: self.md_mgr.val_to_span(self.context, *arg_val), - }); - } - } // Register ARG_REGS[NUM_ARG_REGISTERS-1] must contain LocalsBase + locals_size // so that the callee can index the stack arguments from there. + // It's also useful for us to save the arguments to the stack next. if self.locals_size_bytes() <= TWELVE_BITS { self.cur_bytecode.push(Op { opcode: Either::Left(VirtualOp::ADDI( @@ -138,7 +98,8 @@ impl<'ir, 'eng> FuelAsmBuilder<'ir, 'eng> { VirtualImmediate12::new(self.locals_size_bytes(), Span::dummy()) .expect("Stack size too big for these many arguments, cannot handle."), )), - comment: "Save address of stack arguments in last arg register".to_string(), + comment: "[call]: save address of stack arguments in last argument register" + .to_string(), owning_span: self.md_mgr.val_to_span(self.context, *instr_val), }); } else { @@ -151,7 +112,7 @@ impl<'ir, 'eng> FuelAsmBuilder<'ir, 'eng> { VirtualImmediate18::new(self.locals_size_bytes(), Span::dummy()) .expect("Stack size too big for these many arguments, cannot handle."), )), - comment: "Temporarily save the locals size to add up next".to_string(), + comment: "[call]: temporarily save locals size to add up next".to_string(), owning_span: self.md_mgr.val_to_span(self.context, *instr_val), }); self.cur_bytecode.push(Op { @@ -166,10 +127,56 @@ impl<'ir, 'eng> FuelAsmBuilder<'ir, 'eng> { [(compiler_constants::NUM_ARG_REGISTERS - 1) as usize], ), )), - comment: "Save address of stack arguments in last arg register".to_string(), + comment: "[call]: save address of stack arguments in last argument register" + .to_string(), owning_span: self.md_mgr.val_to_span(self.context, *instr_val), }); } + + // Put NUM_ARG_REGISTERS - 1 arguments into arg registers and rest into the stack. + for (idx, arg_val) in args.iter().enumerate() { + let arg_reg = self.value_to_register(arg_val)?; + // Except for the last arg register, the others hold an argument. + if idx < compiler_constants::NUM_ARG_REGISTERS as usize - 1 { + self.cur_bytecode.push(Op::register_move( + VirtualRegister::Constant(ConstantRegister::ARG_REGS[idx]), + arg_reg, + format!("[call]: pass argument {idx}"), + self.md_mgr.val_to_span(self.context, *arg_val), + )); + } else { + // All arguments [NUM_ARG_REGISTERS - 1 ..] go into the stack. + assert!( + self.locals_size_bytes() % 8 == 0, + "The size of locals is not word aligned" + ); + let stack_offset = + (idx as u64 + 1) - compiler_constants::NUM_ARG_REGISTERS as u64; + let stack_offset_bytes = self.locals_size_bytes() + (stack_offset * 8); + assert!( + stack_offset_bytes + < self.locals_size_bytes() + (self.max_num_extra_args() * 8) + ); + self.cur_bytecode.push(Op { + opcode: Either::Left(VirtualOp::SW( + VirtualRegister::Constant( + ConstantRegister::ARG_REGS + [compiler_constants::NUM_ARG_REGISTERS as usize - 1], + ), + arg_reg, + VirtualImmediate12::new( + stack_offset, + self.md_mgr + .val_to_span(self.context, *arg_val) + .unwrap_or(Span::dummy()), + ) + .expect("Too many arguments, cannot handle."), + )), + comment: format!("[call]: pass argument {idx} via its stack slot"), + owning_span: self.md_mgr.val_to_span(self.context, *arg_val), + }); + } + } } // Set a new return address. @@ -177,7 +184,7 @@ impl<'ir, 'eng> FuelAsmBuilder<'ir, 'eng> { self.cur_bytecode.push(Op::save_ret_addr( VirtualRegister::Constant(ConstantRegister::CallReturnAddress), ret_label, - "set new return addr", + "[call]: set new return address", None, )); @@ -185,7 +192,7 @@ impl<'ir, 'eng> FuelAsmBuilder<'ir, 'eng> { let (fn_label, _) = self.func_to_labels(function); self.cur_bytecode.push(Op { opcode: Either::Right(OrganizationalOp::Call(fn_label)), - comment: format!("call {}", function.get_name(self.context)), + comment: format!("[call]: call {}", function.get_name(self.context)), owning_span: None, }); self.cur_bytecode.push(Op::unowned_jump_label(ret_label)); @@ -197,7 +204,7 @@ impl<'ir, 'eng> FuelAsmBuilder<'ir, 'eng> { ret_reg.clone(), VirtualRegister::Constant(ConstantRegister::CallReturnValue), )), - comment: "copy the return value".into(), + comment: "[call]: copy the return value".into(), owning_span: None, }); self.reg_map.insert(*instr_val, ret_reg); @@ -274,8 +281,8 @@ impl<'ir, 'eng> FuelAsmBuilder<'ir, 'eng> { function.get_name(self.context) ); - self.cur_bytecode.push(match span { - Some(span) => Op::jump_label_comment(start_label, span, comment), + self.cur_bytecode.push(match &span { + Some(span) => Op::jump_label_comment(start_label, span.clone(), comment), None => Op::unowned_jump_label_comment(start_label, comment), }); @@ -284,8 +291,8 @@ impl<'ir, 'eng> FuelAsmBuilder<'ir, 'eng> { // Save any general purpose registers used here on the stack. self.cur_bytecode.push(Op { opcode: Either::Right(OrganizationalOp::PushAll(start_label)), - comment: "save all regs".to_owned(), - owning_span: None, + comment: "save all registers".to_owned(), + owning_span: span.clone(), }); } @@ -305,14 +312,14 @@ impl<'ir, 'eng> FuelAsmBuilder<'ir, 'eng> { self.cur_bytecode.push(Op::register_move( reta.clone(), VirtualRegister::Constant(ConstantRegister::CallReturnAddress), - "save reta", + "save return address", None, )); let retv = self.reg_seqr.next(); self.cur_bytecode.push(Op::register_move( retv.clone(), VirtualRegister::Constant(ConstantRegister::CallReturnValue), - "save retv", + "save return value", None, )); @@ -346,14 +353,14 @@ impl<'ir, 'eng> FuelAsmBuilder<'ir, 'eng> { self.cur_bytecode.push(Op::register_move( VirtualRegister::Constant(ConstantRegister::CallReturnAddress), reta, - "restore reta", + "restore return address", None, )); // Restore GP regs. self.cur_bytecode.push(Op { opcode: Either::Right(OrganizationalOp::PopAll(start_label)), - comment: "restore all regs".to_owned(), + comment: "restore all registers".to_owned(), owning_span: None, }); @@ -387,7 +394,7 @@ impl<'ir, 'eng> FuelAsmBuilder<'ir, 'eng> { self.cur_bytecode.push(Op::register_move( arg_copy_reg.clone(), VirtualRegister::Constant(ConstantRegister::ARG_REGS[idx]), - format!("save arg {idx} ({arg_name})"), + format!("save argument {idx} ({arg_name})"), self.md_mgr.val_to_span(self.context, *arg_val), )); @@ -396,7 +403,7 @@ impl<'ir, 'eng> FuelAsmBuilder<'ir, 'eng> { } } else { // Get NUM_ARG_REGISTERS - 1 arguments from arg registers and rest from the stack. - for (idx, (_, arg_val)) in function.args_iter(self.context).enumerate() { + for (idx, (arg_name, arg_val)) in function.args_iter(self.context).enumerate() { let arg_copy_reg = self.reg_seqr.next(); // Except for the last arg register, the others hold an argument. if idx < compiler_constants::NUM_ARG_REGISTERS as usize - 1 { @@ -404,7 +411,7 @@ impl<'ir, 'eng> FuelAsmBuilder<'ir, 'eng> { self.cur_bytecode.push(Op::register_move( arg_copy_reg.clone(), VirtualRegister::Constant(ConstantRegister::ARG_REGS[idx]), - format!("save arg {idx}"), + format!("save argument {idx} ({arg_name})"), self.md_mgr.val_to_span(self.context, *arg_val), )); } else { @@ -430,7 +437,7 @@ impl<'ir, 'eng> FuelAsmBuilder<'ir, 'eng> { ) .expect("Too many arguments, cannot handle."), )), - comment: format!("Load arg {idx} from its stack slot"), + comment: format!("load argument {idx} ({arg_name}) from its stack slot"), owning_span: self.md_mgr.val_to_span(self.context, *arg_val), }); } @@ -475,7 +482,7 @@ impl<'ir, 'eng> FuelAsmBuilder<'ir, 'eng> { single_arg_reg.clone(), VirtualImmediate12 { value: 0 }, )), - comment: "load main fn parameter".into(), + comment: "load main function parameter".into(), owning_span: None, }); } @@ -519,7 +526,7 @@ impl<'ir, 'eng> FuelAsmBuilder<'ir, 'eng> { args_base_reg.clone(), offs_reg.clone(), )), - comment: format!("get offset for arg {name}"), + comment: format!("get offset of argument {name}"), owning_span: None, }); @@ -530,7 +537,7 @@ impl<'ir, 'eng> FuelAsmBuilder<'ir, 'eng> { offs_reg, VirtualImmediate12 { value: 0 }, )), - comment: format!("get arg {name}"), + comment: format!("get argument {name}"), owning_span: None, }); } else { @@ -540,7 +547,7 @@ impl<'ir, 'eng> FuelAsmBuilder<'ir, 'eng> { offs_reg, VirtualImmediate12 { value: 0 }, )), - comment: format!("get arg {name}"), + comment: format!("get argument {name}"), owning_span: None, }); } @@ -553,7 +560,7 @@ impl<'ir, 'eng> FuelAsmBuilder<'ir, 'eng> { value: arg_word_offset as u16 * 8, }, )), - comment: format!("get arg {name}"), + comment: format!("get argument {name}"), owning_span: None, }); } else { @@ -565,7 +572,7 @@ impl<'ir, 'eng> FuelAsmBuilder<'ir, 'eng> { value: arg_word_offset as u16, }, )), - comment: format!("get arg {name}"), + comment: format!("get argument {name}"), owning_span: None, }); } @@ -574,7 +581,7 @@ impl<'ir, 'eng> FuelAsmBuilder<'ir, 'eng> { arg_word_offset * 8, current_arg_reg.clone(), Some(&args_base_reg), - format!("get offset or arg {name}"), + format!("get offset of argument {name}"), None, ); } @@ -597,7 +604,7 @@ impl<'ir, 'eng> FuelAsmBuilder<'ir, 'eng> { // see https://github.com/FuelLabs/fuel-specs/pull/193#issuecomment-876496372 VirtualImmediate12 { value: 74 }, )), - comment: "base register for method parameter".into(), + comment: "get base register for method arguments".into(), owning_span: None, }); } @@ -612,7 +619,7 @@ impl<'ir, 'eng> FuelAsmBuilder<'ir, 'eng> { value: GTFArgs::ScriptData as u16, }, )), - comment: "base register for main fn parameter".into(), + comment: "get base register for main function arguments".into(), owning_span: None, }); } @@ -650,7 +657,7 @@ impl<'ir, 'eng> FuelAsmBuilder<'ir, 'eng> { value: GTFArgs::InputType as u16, }, )), - comment: "get input type".into(), + comment: "get predicate input type".into(), owning_span: None, }); @@ -671,7 +678,7 @@ impl<'ir, 'eng> FuelAsmBuilder<'ir, 'eng> { value: GTFArgs::InputCoinPredicateData as u16, }, )), - comment: "get input coin predicate data pointer".into(), + comment: "get predicate input coin data pointer".into(), owning_span: None, }); @@ -692,7 +699,9 @@ impl<'ir, 'eng> FuelAsmBuilder<'ir, 'eng> { two.clone(), VirtualImmediate18 { value: 2u32 }, )), - comment: "register containing 2".into(), + comment: + "[predicate input is message]: set register to 2 (Input::Message discriminator)" + .into(), owning_span: None, }); self.cur_bytecode.push(Op { @@ -701,7 +710,7 @@ impl<'ir, 'eng> FuelAsmBuilder<'ir, 'eng> { input_type, two, )), - comment: "input type is message(2)".into(), + comment: "[predicate input is message]: check if input type is message".into(), owning_span: None, }); @@ -713,16 +722,17 @@ impl<'ir, 'eng> FuelAsmBuilder<'ir, 'eng> { input_type_is_message, VirtualImmediate12 { value: 1 }, )), - comment: "input type is not message(2)".into(), + comment: "[predicate input is message]: check if input type is not message".into(), owning_span: None, }); // Label to jump to if the input type is *not* 2, i.e. not "message" (and not "coin" since // we checked that earlier). Then do the jump. let input_type_not_message_label = self.reg_seqr.get_label(); - self.cur_bytecode.push(Op::jump_if_not_zero( + self.cur_bytecode.push(Op::jump_if_not_zero_comment( input_type_not_message, input_type_not_message_label, + "[predicate input is message]: jump to return false from predicate", )); // If the input is indeed a "message", then use `GTF` to get the "input message predicate @@ -735,7 +745,7 @@ impl<'ir, 'eng> FuelAsmBuilder<'ir, 'eng> { value: GTFArgs::InputMessagePredicateData as u16, }, )), - comment: "input message predicate data pointer".into(), + comment: "get predicate input message data pointer".into(), owning_span: None, }); self.cur_bytecode.push(Op::jump_to_label(success_label)); @@ -751,7 +761,7 @@ impl<'ir, 'eng> FuelAsmBuilder<'ir, 'eng> { ConstantRegister::Zero, ))), owning_span: None, - comment: "return false".into(), + comment: "return false from predicate".into(), }); // Final success label to continue execution at if we successfully obtained the predicate @@ -873,7 +883,7 @@ impl<'ir, 'eng> FuelAsmBuilder<'ir, 'eng> { locals_base_reg.clone(), VirtualRegister::Constant(ConstantRegister::StackPointer), format!( - "save locals base register for {}", + "save locals base register for function {}", function.get_name(self.context) ) .to_string(), @@ -888,7 +898,7 @@ impl<'ir, 'eng> FuelAsmBuilder<'ir, 'eng> { opcode: Either::Left(VirtualOp::CFEI(VirtualImmediate24 { value: locals_size_bytes as u32 + (max_num_extra_args * 8) as u32, })), - comment: format!("allocate {locals_size_bytes} bytes for locals and {max_num_extra_args} slots for call arguments."), + comment: format!("allocate {locals_size_bytes} bytes for locals and {max_num_extra_args} slots for call arguments"), owning_span: None, }); ( @@ -927,7 +937,7 @@ impl<'ir, 'eng> FuelAsmBuilder<'ir, 'eng> { VirtualRegister::Constant(ConstantRegister::Scratch), data_id, )), - comment: "load initializer from data section".to_owned(), + comment: "load local variable initializer from data section".to_owned(), owning_span: None, }); } @@ -938,7 +948,7 @@ impl<'ir, 'eng> FuelAsmBuilder<'ir, 'eng> { VirtualRegister::Constant(ConstantRegister::Scratch), c.clone(), )), - comment: "load initializer from register".into(), + comment: "load local variable initializer from register".into(), owning_span: None, }); } @@ -958,7 +968,7 @@ impl<'ir, 'eng> FuelAsmBuilder<'ir, 'eng> { value: var_stack_off_bytes as u16, }, )), - comment: "calc local variable address".to_owned(), + comment: "get local variable address".to_owned(), owning_span: None, }); } else { @@ -971,7 +981,7 @@ impl<'ir, 'eng> FuelAsmBuilder<'ir, 'eng> { value: var_stack_off_bytes as u32, }, )), - comment: "stack offset of local variable into register".to_owned(), + comment: "move stack offset of local variable into register".to_owned(), owning_span: None, }); self.cur_bytecode.push(Op { @@ -980,7 +990,7 @@ impl<'ir, 'eng> FuelAsmBuilder<'ir, 'eng> { locals_base_reg.clone(), dst_reg.clone(), )), - comment: "calc local variable address".to_owned(), + comment: "get local variable address".to_owned(), owning_span: None, }); } @@ -994,7 +1004,7 @@ impl<'ir, 'eng> FuelAsmBuilder<'ir, 'eng> { VirtualRegister::Constant(ConstantRegister::Scratch), VirtualImmediate12 { value: 0 }, )), - comment: "store initializer to local variable".to_owned(), + comment: "store byte initializer to local variable".to_owned(), owning_span: None, }); } else { @@ -1004,7 +1014,7 @@ impl<'ir, 'eng> FuelAsmBuilder<'ir, 'eng> { VirtualRegister::Constant(ConstantRegister::Scratch), VirtualImmediate12 { value: 0 }, )), - comment: "store initializer to local variable".to_owned(), + comment: "store word initializer to local variable".to_owned(), owning_span: None, }); } @@ -1039,7 +1049,7 @@ impl<'ir, 'eng> FuelAsmBuilder<'ir, 'eng> { opcode: Either::Left(VirtualOp::CFSI(VirtualImmediate24 { value: u32::try_from(locals_size_bytes + (max_num_extra_args * 8)).unwrap(), })), - comment: format!("free {locals_size_bytes} bytes for locals and {max_num_extra_args} slots for extra call arguments."), + comment: format!("free {locals_size_bytes} bytes for locals and {max_num_extra_args} slots for extra call arguments"), owning_span: None, }); } diff --git a/sway-core/src/asm_generation/fuel/optimizations.rs b/sway-core/src/asm_generation/fuel/optimizations.rs index 63fd044c039..4800ba6906f 100644 --- a/sway-core/src/asm_generation/fuel/optimizations.rs +++ b/sway-core/src/asm_generation/fuel/optimizations.rs @@ -1,11 +1,11 @@ -use std::collections::BTreeSet; +use std::collections::{BTreeSet, HashMap}; use either::Either; use rustc_hash::{FxHashMap, FxHashSet}; use crate::{ asm_generation::fuel::compiler_constants, - asm_lang::{ControlFlowOp, VirtualImmediate12, VirtualOp, VirtualRegister}, + asm_lang::{ControlFlowOp, Label, VirtualImmediate12, VirtualOp, VirtualRegister}, }; use super::{ @@ -269,4 +269,44 @@ impl AbstractInstructionSet { self } + + // Remove unreachable instructions. + pub(crate) fn simplify_cfg(mut self) -> AbstractInstructionSet { + let ops = &self.ops; + + if ops.is_empty() { + return self; + } + + // Keep track of a map between jump labels and op indices. Useful to compute op successors. + let mut label_to_index: HashMap = HashMap::default(); + for (idx, op) in ops.iter().enumerate() { + if let Either::Right(ControlFlowOp::Label(op_label)) = op.opcode { + label_to_index.insert(op_label, idx); + } + } + + let mut reachables = vec![false; ops.len()]; + let mut worklist = vec![0]; + while let Some(op_idx) = worklist.pop() { + assert!(!reachables[op_idx]); + reachables[op_idx] = true; + let op = &ops[op_idx]; + for s in &op.successors(op_idx, ops, &label_to_index) { + if !reachables[*s] { + worklist.push(*s); + } + } + } + + let reachable_ops = self + .ops + .into_iter() + .enumerate() + .filter_map(|(idx, op)| if reachables[idx] { Some(op) } else { None }) + .collect(); + self.ops = reachable_ops; + + self + } } diff --git a/sway-core/src/asm_generation/fuel/programs/abstract.rs b/sway-core/src/asm_generation/fuel/programs/abstract.rs index 9f81c767c42..17b6240a95d 100644 --- a/sway-core/src/asm_generation/fuel/programs/abstract.rs +++ b/sway-core/src/asm_generation/fuel/programs/abstract.rs @@ -78,7 +78,7 @@ impl AbstractProgram { && self.data_section.value_pairs.is_empty() } - /// Adds prologue, globals allocation, before entries, contract method switch, and allocates virtual register + /// Adds prologue, globals allocation, before entries, contract method switch, and allocates virtual register. pub(crate) fn into_allocated_program( mut self, fallback_fn: Option, @@ -111,21 +111,21 @@ impl AbstractProgram { }) .collect(); - // Gather all functions + // Gather all functions. let all_functions = self .entries .into_iter() .map(|entry| entry.ops) .chain(self.non_entries); - // optimise and then verify these functions. + // Optimize and then verify abstract functions. let abstract_functions = all_functions .map(|instruction_set| instruction_set.optimize(&self.data_section)) .map(AbstractInstructionSet::verify) .collect::, CompileError>>()?; // Allocate the registers for each function. - let functions = abstract_functions + let allocated_functions = abstract_functions .into_iter() .map(|abstract_instruction_set| { let allocated = abstract_instruction_set.allocate_registers()?; @@ -133,7 +133,12 @@ impl AbstractProgram { }) .collect::, CompileError>>()?; - // XXX need to verify that the stack use for each function is balanced. + // Optimize allocated functions. + // TODO: Add verification. E.g., verify that the stack use for each function is balanced. + let functions = allocated_functions + .into_iter() + .map(|instruction_set| instruction_set.optimize()) + .collect::>(); Ok(AllocatedProgram { kind: self.kind, @@ -225,7 +230,7 @@ impl AbstractProgram { let entry = self.entries.iter().find(|x| x.name == "__entry").unwrap(); asm.ops.push(AllocatedAbstractOp { opcode: Either::Right(ControlFlowOp::Jump(entry.label)), - comment: "jump to abi method selector".into(), + comment: "jump to ABI function selector".into(), owning_span: None, }); } @@ -247,7 +252,7 @@ impl AbstractProgram { // Build the switch statement for selectors. asm.ops.push(AllocatedAbstractOp { opcode: Either::Right(ControlFlowOp::Comment), - comment: "Begin contract ABI selector switch".into(), + comment: "[function selection]: begin contract function selector switch".into(), owning_span: None, }); @@ -261,7 +266,7 @@ impl AbstractProgram { "constant infallible value", ), )), - comment: "load input function selector".into(), + comment: "[function selection]: load input function selector".into(), owning_span: None, }); @@ -283,7 +288,10 @@ impl AbstractProgram { // Load the data into a register for comparison. asm.ops.push(AllocatedAbstractOp { opcode: Either::Left(AllocatedOpcode::LoadDataId(PROG_SELECTOR_REG, data_label)), - comment: format!("load fn selector for comparison {}", entry.name), + comment: format!( + "[function selection]: load function {} selector for comparison", + entry.name + ), owning_span: None, }); @@ -294,7 +302,10 @@ impl AbstractProgram { INPUT_SELECTOR_REG, PROG_SELECTOR_REG, )), - comment: "function selector comparison".into(), + comment: format!( + "[function selection]: compare function {} selector with input selector", + entry.name + ), owning_span: None, }); @@ -302,7 +313,7 @@ impl AbstractProgram { asm.ops.push(AllocatedAbstractOp { // If the comparison result is _not_ equal to 0, then it was indeed equal. opcode: Either::Right(ControlFlowOp::JumpIfNotZero(CMP_RESULT_REG, entry.label)), - comment: "jump to selected function".into(), + comment: "[function selection]: jump to selected contract function".into(), owning_span: None, }); } @@ -310,7 +321,7 @@ impl AbstractProgram { if let Some(fallback_fn) = fallback_fn { asm.ops.push(AllocatedAbstractOp { opcode: Either::Right(ControlFlowOp::Call(fallback_fn)), - comment: "call fallback function".into(), + comment: "[function selection]: call contract fallback function".into(), owning_span: None, }); } @@ -322,14 +333,15 @@ impl AbstractProgram { value: compiler_constants::MISMATCHED_SELECTOR_REVERT_CODE, }, )), - comment: "special code for mismatched selector".into(), + comment: "[function selection]: load revert code for mismatched function selector" + .into(), owning_span: None, }); asm.ops.push(AllocatedAbstractOp { opcode: Either::Left(AllocatedOpcode::RVRT(AllocatedRegister::Constant( ConstantRegister::Scratch, ))), - comment: "revert if no selectors matched".into(), + comment: "[function selection]: revert if no selectors have matched".into(), owning_span: None, }); } @@ -340,7 +352,7 @@ impl AbstractProgram { opcode: Either::Left(AllocatedOpcode::CFEI(VirtualImmediate24 { value: len_in_bytes as u32, })), - comment: "stack space for globals".into(), + comment: "allocate stack space for globals".into(), owning_span: None, }); } diff --git a/sway-core/src/asm_generation/fuel/register_allocator.rs b/sway-core/src/asm_generation/fuel/register_allocator.rs index 9cae883fe26..8e02d2d29fa 100644 --- a/sway-core/src/asm_generation/fuel/register_allocator.rs +++ b/sway-core/src/asm_generation/fuel/register_allocator.rs @@ -791,7 +791,7 @@ fn spill(ops: &[Op], spills: &FxHashSet) -> Vec { value: offset_bytes, }, )), - comment: "Spill/Refill: Set offset".to_string(), + comment: "[spill/refill]: set offset".to_string(), owning_span: None, }; inst_list.push(offset_mov_instr); @@ -801,7 +801,7 @@ fn spill(ops: &[Op], spills: &FxHashSet) -> Vec { VirtualRegister::Constant(ConstantRegister::Scratch), VirtualRegister::Constant(ConstantRegister::LocalsBase), )), - comment: "Spill/Refill: Add offset to stack base".to_string(), + comment: "[spill/refill]: add offset to stack base".to_string(), owning_span: None, }; inst_list.push(offset_add_instr); @@ -827,7 +827,7 @@ fn spill(ops: &[Op], spills: &FxHashSet) -> Vec { value: offset_upper_12, }, )), - comment: "Spill/Refill: Offset computation".to_string(), + comment: "[spill/refill]: compute offset".to_string(), owning_span: None, }; inst_list.push(offset_upper_mov_instr); @@ -837,7 +837,7 @@ fn spill(ops: &[Op], spills: &FxHashSet) -> Vec { VirtualRegister::Constant(ConstantRegister::Scratch), VirtualImmediate12 { value: 12 }, )), - comment: "Spill/Refill: Offset computation".to_string(), + comment: "[spill/refill]: compute offset".to_string(), owning_span: None, }; inst_list.push(offset_upper_shift_instr); @@ -847,7 +847,7 @@ fn spill(ops: &[Op], spills: &FxHashSet) -> Vec { VirtualRegister::Constant(ConstantRegister::Scratch), VirtualRegister::Constant(ConstantRegister::LocalsBase), )), - comment: "Spill/Refill: Offset computation".to_string(), + comment: "[spill/refill]: compute offset".to_string(), owning_span: None, }; inst_list.push(offset_add_instr); @@ -876,7 +876,7 @@ fn spill(ops: &[Op], spills: &FxHashSet) -> Vec { value: (offset_bytes / 8) as u16, }, )), - comment: "Refilling from spill".to_string(), + comment: "[spill/refill]: refill from spill".to_string(), owning_span: None, }); } else { @@ -889,7 +889,7 @@ fn spill(ops: &[Op], spills: &FxHashSet) -> Vec { // This will be multiplied by 8 by the VM offset_imm_word, )), - comment: "Refilling from spill".to_string(), + comment: "[spill/refill]: refill from spill".to_string(), owning_span: None, }; spilled.push(lw); @@ -914,7 +914,7 @@ fn spill(ops: &[Op], spills: &FxHashSet) -> Vec { value: (offset_bytes / 8) as u16, }, )), - comment: "Spill".to_string(), + comment: "[spill/refill]: spill".to_string(), owning_span: None, }); } else { @@ -927,7 +927,7 @@ fn spill(ops: &[Op], spills: &FxHashSet) -> Vec { // This will be multiplied by 8 by the VM offset_imm_word, )), - comment: "Spill".to_string(), + comment: "[spill/refill]: spill".to_string(), owning_span: None, }; spilled.push(sw); diff --git a/sway-core/src/asm_generation/instruction_set.rs b/sway-core/src/asm_generation/instruction_set.rs index 6e5f007e305..c96c3f69df0 100644 --- a/sway-core/src/asm_generation/instruction_set.rs +++ b/sway-core/src/asm_generation/instruction_set.rs @@ -4,15 +4,8 @@ use std::fmt; /// An [InstructionSet] is produced by allocating registers on an [AbstractInstructionSet]. #[derive(Clone)] pub enum InstructionSet { - Fuel { - ops: Vec, - }, - Evm { - ops: Vec, - }, - MidenVM { - ops: Vec, - }, + Fuel { ops: Vec }, + Evm { ops: Vec }, } impl fmt::Display for InstructionSet { @@ -31,12 +24,6 @@ impl fmt::Display for InstructionSet { .map(|x| format!("{x}")) .collect::>() .join("\n"), - InstructionSet::MidenVM { ops } => { - ops.iter() - .map(|x| format!("{x}")) - .collect::>() - .join("\n") - } } ) } diff --git a/sway-core/src/asm_generation/miden_vm/miden_vm_asm_builder.rs b/sway-core/src/asm_generation/miden_vm/miden_vm_asm_builder.rs deleted file mode 100644 index ff0575219a0..00000000000 --- a/sway-core/src/asm_generation/miden_vm/miden_vm_asm_builder.rs +++ /dev/null @@ -1,704 +0,0 @@ -#![allow(dead_code)] -use std::{collections::HashMap, sync::Arc}; -mod miden_op; -use indexmap::IndexMap; -pub use miden_op::MidenAsmOp; - -use crate::{ - asm_generation::{ - asm_builder::AsmBuilder, - from_ir::StateAccessType, - fuel::data_section::DataSection, - instruction_set::InstructionSet, - miden_vm::miden_vm_asm_builder::miden_op::{MidenStackValue, Push}, - FinalizedAsm, ProgramKind, - }, - asm_lang::Label, - metadata::MetadataManager, - BuildConfig, -}; - -use sway_error::{ - error::CompileError, - handler::{ErrorEmitted, Handler}, -}; -use sway_ir::{Context, *}; -use sway_types::Span; - -pub use miden_op::DirectOp; - -#[derive(Default)] -pub struct MidenVMAsmSection { - ops: Vec, -} - -/// A procedure block is used to define a frequently-used sequence of instructions. A procedure must -/// start with a proc.