diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 0e1cc42b02..9fbf83bbd7 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -15,7 +15,7 @@ on: jobs: analyze: name: Analyze - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 strategy: fail-fast: false diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml index 53727f9d0f..f1fd33028d 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/go.yml @@ -9,7 +9,7 @@ jobs: complete: if: always() needs: [check, build, test] - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 steps: - if: contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') run: exit 1 @@ -17,8 +17,8 @@ jobs: check: strategy: matrix: - os: [ubuntu-latest] - go: [1.19] + os: [ubuntu-22.04] + go: ["1.21"] runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v3 @@ -37,8 +37,8 @@ jobs: build: strategy: matrix: - os: [ubuntu-latest] - go: [1.18, 1.19] + os: [ubuntu-22.04] + go: ["1.20", "1.21"] runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v3 @@ -49,13 +49,15 @@ jobs: with: go-version: ${{ matrix.go }} - run: go build ./... + - name: Build binaries + run: go run ./support/scripts/build_release_artifacts/main.go test: strategy: matrix: - os: [ubuntu-latest] - go: [1.18, 1.19] - pg: [9.6.5, 10] + os: [ubuntu-22.04] + go: ["1.19", "1.20"] + pg: [12] runs-on: ${{ matrix.os }} services: postgres: @@ -80,7 +82,7 @@ jobs: --health-retries 5 ports: - 6379:6379 - env: + env: PGHOST: localhost PGPORT: 5432 PGUSER: postgres diff --git a/.github/workflows/golangci-lint.yml b/.github/workflows/golangci-lint.yml new file mode 100644 index 0000000000..fe31e4671b --- /dev/null +++ b/.github/workflows/golangci-lint.yml @@ -0,0 +1,33 @@ +name: Linters +on: + push: + branches: + - master + pull_request: + +permissions: + contents: read + # Optional: allow read access to pull request. Use with `only-new-issues` option. + pull-requests: read + +jobs: + golangci: + runs-on: ubuntu-22.04 + steps: + - name: Checkout + uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # version v3.0.2 + with: + fetch-depth: 0 # required for new-from-rev option in .golangci.yml + - name: Setup GO + uses: actions/setup-go@268d8c0ca0432bb2cf416faae41297df9d262d7f # version v3.3.0 + - name: Run golangci-lint + uses: golangci/golangci-lint-action@537aa1903e5d359d0b27dbc19ddd22c5087f3fbc # version v3.2.0 + with: + version: v1.52.2 # this is the golangci-lint version + args: --issues-exit-code=0 # exit without errors for now - won't fail the build + github-token: ${{ secrets.GITHUB_TOKEN }} + only-new-issues: true + + + + diff --git a/.github/workflows/horizon-master.yml b/.github/workflows/horizon-master.yml index ba4bdcae1e..e2487a0d64 100644 --- a/.github/workflows/horizon-master.yml +++ b/.github/workflows/horizon-master.yml @@ -6,34 +6,9 @@ on: jobs: - push-horizon-image-sha: - name: Push stellar/horizon:sha to DockerHub - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - - name: Get image tag (short sha) - shell: bash - id: get_tag - run: echo ::set-output name=TAG::$(git rev-parse --short ${{ github.sha }} ) - - - name: Login to DockerHub - uses: docker/login-action@bb984efc561711aaa26e433c32c3521176eae55b - with: - username: ${{ secrets.DOCKERHUB_USERNAME }} - password: ${{ secrets.DOCKERHUB_TOKEN }} - - - name: Build and push to DockerHub - uses: docker/build-push-action@7f9d37fa544684fb73bfe4835ed7214c255ce02b - with: - # TODO: Commented out until we disable the CircleCI jobs - # push: true - tags: stellar/horizon:${{ steps.get_tag.outputs.TAG }} - file: services/horizon/docker/Dockerfile.dev - push-state-diff-image: name: Push stellar/ledger-state-diff:{sha,latest} to DockerHub - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 steps: - uses: actions/checkout@v3 diff --git a/.github/workflows/horizon-release.yml b/.github/workflows/horizon-release.yml index 95386239df..f8dda0ceac 100644 --- a/.github/workflows/horizon-release.yml +++ b/.github/workflows/horizon-release.yml @@ -7,7 +7,7 @@ on: jobs: publish-artifacts: - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 name: Upload artifacts to GitHub release steps: - name: Run deprecation tests @@ -22,7 +22,7 @@ jobs: - uses: ./.github/actions/setup-go with: - go-version: 1.18 + go-version: "1.20" - name: Check dependencies run: ./gomod.sh diff --git a/.github/workflows/horizon.yml b/.github/workflows/horizon.yml index d2555d1184..9743ffd85f 100644 --- a/.github/workflows/horizon.yml +++ b/.github/workflows/horizon.yml @@ -6,16 +6,15 @@ on: pull_request: jobs: - integration: name: Integration tests strategy: matrix: - os: [ubuntu-latest] - go: [1.18, 1.19] - pg: [9.6.5] - ingestion-backend: [db, captive-core, captive-core-remote-storage] - protocol-version: [18, 19] + os: [ubuntu-20.04, ubuntu-22.04] + go: ["1.20", "1.21"] + pg: [12] + ingestion-backend: [captive-core, captive-core-remote-storage] + protocol-version: [19, 20] runs-on: ${{ matrix.os }} services: postgres: @@ -30,98 +29,135 @@ jobs: --health-timeout 5s --health-retries 5 ports: - - 5432:5432 + - 5432:5432 env: HORIZON_INTEGRATION_TESTS_ENABLED: true HORIZON_INTEGRATION_TESTS_CORE_MAX_SUPPORTED_PROTOCOL: ${{ matrix.protocol-version }} - PROTOCOL_19_CORE_DEBIAN_PKG_VERSION: 19.3.0-1006.9ce6dc4e9.focal - PROTOCOL_19_CORE_DOCKER_IMG: stellar/stellar-core:19.3.0-1006.9ce6dc4e9.focal - PROTOCOL_18_CORE_DEBIAN_PKG_VERSION: 19.3.0-1006.9ce6dc4e9.focal - PROTOCOL_18_CORE_DOCKER_IMG: stellar/stellar-core:19.3.0-1006.9ce6dc4e9.focal + PROTOCOL_20_CORE_DEBIAN_PKG_VERSION: 20.0.2-1633.669916b56.focal + PROTOCOL_20_CORE_DOCKER_IMG: stellar/unsafe-stellar-core:20.0.2-1633.669916b56.focal + PROTOCOL_20_SOROBAN_RPC_DOCKER_IMG: stellar/soroban-rpc:20.0.2-47 + PROTOCOL_19_CORE_DEBIAN_PKG_VERSION: 19.14.0-1500.5664eff4e.focal + PROTOCOL_19_CORE_DOCKER_IMG: stellar/stellar-core:19.14.0-1500.5664eff4e.focal PGHOST: localhost PGPORT: 5432 PGUSER: postgres PGPASSWORD: postgres PGDATABASE: postgres steps: - - uses: actions/checkout@v3 - with: - # For pull requests, build and test the PR head not a merge of the PR with the destination. - ref: ${{ github.event.pull_request.head.sha || github.ref }} - # We need to full history for git-restore-mtime to know what modification dates to use. - # Otherwise, the Go test cache will fail (due to the modification time of fixtures changing). - fetch-depth: '0' - - # In order to debug the integration tests, run 'touch continue' once you connect to the ssh session - # - # - name: Setup upterm session - # uses: lhotari/action-upterm@d23c2722bdab893785c9fbeae314cbf080645bd7 - # with: - # ## limits ssh access and adds the ssh public key for the user which triggered the workflow - # limit-access-to-actor: true - # ## limits ssh access and adds the ssh public keys of the listed GitHub users - # limit-access-to-users: - - - uses: ./.github/actions/setup-go - with: - go-version: ${{ matrix.go }} - - - name: Pull and set Stellar Core image - shell: bash - run: | - docker pull "$PROTOCOL_${{ matrix.protocol-version }}_CORE_DOCKER_IMG" - echo HORIZON_INTEGRATION_TESTS_DOCKER_IMG="$PROTOCOL_${{ matrix.protocol-version }}_CORE_DOCKER_IMG" >> $GITHUB_ENV - - - if: ${{ startsWith(matrix.ingestion-backend, 'captive-core') }} - name: Install and enable Captive Core - run: | - # Workaround for https://github.com/actions/virtual-environments/issues/5245, - # libc++1-8 won't be installed if another version is installed (but apt won't give you a helpul - # message about why the installation fails) - sudo apt-get remove -y libc++1-10 libc++abi1-10 || true - - sudo wget -qO - https://apt.stellar.org/SDF.asc | APT_KEY_DONT_WARN_ON_DANGEROUS_USAGE=true sudo apt-key add - - sudo bash -c 'echo "deb https://apt.stellar.org focal unstable" > /etc/apt/sources.list.d/SDF-unstable.list' - sudo apt-get update && sudo apt-get install -y stellar-core="$PROTOCOL_${{ matrix.protocol-version }}_CORE_DEBIAN_PKG_VERSION" - echo "Using stellar core version $(stellar-core version)" - echo 'HORIZON_INTEGRATION_TESTS_ENABLE_CAPTIVE_CORE=true' >> $GITHUB_ENV - echo 'HORIZON_INTEGRATION_TESTS_CAPTIVE_CORE_BIN=/usr/bin/stellar-core' >> $GITHUB_ENV - - - if: ${{ matrix.ingestion-backend == 'captive-core-remote-storage' }} - name: Setup Captive Core Remote Storage - run: echo 'HORIZON_INTEGRATION_TESTS_CAPTIVE_CORE_USE_DB=true' >> $GITHUB_ENV - - - run: go test -race -timeout 25m -v ./services/horizon/internal/integration/... + - uses: actions/checkout@v3 + with: + # For pull requests, build and test the PR head not a merge of the PR with the destination. + ref: ${{ github.event.pull_request.head.sha || github.ref }} + # We need to full history for git-restore-mtime to know what modification dates to use. + # Otherwise, the Go test cache will fail (due to the modification time of fixtures changing). + fetch-depth: "0" + + # In order to debug the integration tests, run 'touch continue' once you connect to the ssh session + # + # - name: Setup upterm session + # uses: lhotari/action-upterm@d23c2722bdab893785c9fbeae314cbf080645bd7 + # with: + # ## limits ssh access and adds the ssh public key for the user which triggered the workflow + # limit-access-to-actor: true + # ## limits ssh access and adds the ssh public keys of the listed GitHub users + # limit-access-to-users: + + - uses: ./.github/actions/setup-go + with: + go-version: ${{ matrix.go }} + + - name: Pull and set Stellar Core image + shell: bash + run: | + docker pull "$PROTOCOL_${{ matrix.protocol-version }}_CORE_DOCKER_IMG" + echo HORIZON_INTEGRATION_TESTS_DOCKER_IMG="$PROTOCOL_${{ matrix.protocol-version }}_CORE_DOCKER_IMG" >> $GITHUB_ENV + + - if: ${{ matrix.protocol-version == '20' }} + name: Pull and set Soroban RPC image + shell: bash + run: | + docker pull "$PROTOCOL_${{ matrix.protocol-version }}_SOROBAN_RPC_DOCKER_IMG" + echo HORIZON_INTEGRATION_TESTS_SOROBAN_RPC_DOCKER_IMG="$PROTOCOL_${{ matrix.protocol-version }}_SOROBAN_RPC_DOCKER_IMG" >> $GITHUB_ENV + echo HORIZON_INTEGRATION_TESTS_ENABLE_SOROBAN_RPC=true >> $GITHUB_ENV + + - if: ${{ startsWith(matrix.ingestion-backend, 'captive-core') }} + name: Install and enable Captive Core + run: | + # Workaround for https://github.com/actions/virtual-environments/issues/5245, + # libc++1-8 won't be installed if another version is installed (but apt won't give you a helpul + # message about why the installation fails) + sudo apt list --installed | grep libc++ + sudo apt-get remove -y libc++1-* libc++abi1-* || true + + sudo wget -qO - https://apt.stellar.org/SDF.asc | APT_KEY_DONT_WARN_ON_DANGEROUS_USAGE=true sudo apt-key add - + sudo bash -c 'echo "deb https://apt.stellar.org focal unstable" > /etc/apt/sources.list.d/SDF-unstable.list' + sudo apt-get update && sudo apt-get install -y stellar-core="$PROTOCOL_${{ matrix.protocol-version }}_CORE_DEBIAN_PKG_VERSION" + echo "Using stellar core version $(stellar-core version)" + echo 'HORIZON_INTEGRATION_TESTS_ENABLE_CAPTIVE_CORE=true' >> $GITHUB_ENV + echo 'HORIZON_INTEGRATION_TESTS_CAPTIVE_CORE_BIN=/usr/bin/stellar-core' >> $GITHUB_ENV + + - if: ${{ matrix.ingestion-backend == 'captive-core-remote-storage' }} + name: Setup Captive Core Remote Storage + run: echo 'HORIZON_INTEGRATION_TESTS_CAPTIVE_CORE_USE_DB=true' >> $GITHUB_ENV + + - name: Build Horizon reproducible build + run: | + go build -v -trimpath -buildvcs=false ./services/horizon + touch empty + + - name: Calculate the source hash + id: calculate_source_hash + run: | + combined_hash=$(echo "horizon-hash-${{ hashFiles('./horizon') }}-${{ hashFiles('./clients/horizonclient/**') }}-${{ hashFiles('./protocols/horizon/**') }}-${{ hashFiles('./txnbuild/**') }}-${{ hashFiles('./ingest/**') }}-${{ hashFiles('./xdr/**') }}-${{ hashFiles('./services/**') }}-${{ env.PROTOCOL_20_CORE_DOCKER_IMG }}-${{ env.PROTOCOL_19_CORE_DOCKER_IMG }}-${{ env.PREFIX }}" | sha256sum | cut -d ' ' -f 1) + echo "COMBINED_SOURCE_HASH=$combined_hash" >> "$GITHUB_ENV" + + - name: Restore Horizon binary and integration tests source hash to cache + id: horizon_binary_tests_hash + uses: actions/cache/restore@v3 + with: + path: ./empty + lookup-only: true + key: ${{ env.COMBINED_SOURCE_HASH }} + + - if: ${{ steps.horizon_binary_tests_hash.outputs.cache-hit != 'true' }} + run: go test -race -timeout 45m -v ./services/horizon/internal/integration/... + + - name: Save Horizon binary and integration tests source hash to cache + if: ${{ success() && steps.horizon_binary_tests_hash.outputs.cache-hit != 'true' }} + uses: actions/cache/save@v3 + with: + path: ./empty + key: ${{ env.COMBINED_SOURCE_HASH }} verify-range: name: Test (and push) verify-range image - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 env: - STELLAR_CORE_VERSION: 19.3.0-1006.9ce6dc4e9.focal + STELLAR_CORE_VERSION: 19.14.0-1500.5664eff4e.focal CAPTIVE_CORE_STORAGE_PATH: /tmp steps: - - uses: actions/checkout@v3 - with: - # For pull requests, build and test the PR head not a merge of the PR with the destination. - ref: ${{ github.event.pull_request.head.sha || github.ref }} - - - name: Build and test the Verify Range Docker image - run: | - docker build -f services/horizon/docker/verify-range/Dockerfile -t stellar/horizon-verify-range services/horizon/docker/verify-range/ - # Any range should do for basic testing, this range was chosen pretty early in history so that it only takes a few mins to run - docker run -e BRANCH=$(git rev-parse HEAD) -e FROM=10000063 -e TO=10000127 stellar/horizon-verify-range + - uses: actions/checkout@v3 + with: + # For pull requests, build and test the PR head not a merge of the PR with the destination. + ref: ${{ github.event.pull_request.head.sha || github.ref }} - # Push image - - if: github.ref == 'refs/heads/master' - name: Login to DockerHub - uses: docker/login-action@bb984efc561711aaa26e433c32c3521176eae55b - with: - username: ${{ secrets.DOCKERHUB_USERNAME }} - password: ${{ secrets.DOCKERHUB_TOKEN }} + - name: Build and test the Verify Range Docker image + run: | + docker build -f services/horizon/docker/verify-range/Dockerfile -t stellar/horizon-verify-range services/horizon/docker/verify-range/ + # Any range should do for basic testing, this range was chosen pretty early in history so that it only takes a few mins to run + docker run -e BRANCH=$(git rev-parse HEAD) -e FROM=10000063 -e TO=10000127 stellar/horizon-verify-range - - if: github.ref == 'refs/heads/master' - name: Push to DockerHub - run: docker push stellar/horizon-verify-range:latest + # Push image + - if: github.ref == 'refs/heads/master' + name: Login to DockerHub + uses: docker/login-action@bb984efc561711aaa26e433c32c3521176eae55b + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + + - if: github.ref == 'refs/heads/master' + name: Push to DockerHub + run: docker push stellar/horizon-verify-range:latest horizon-light: name: Test and Push the horizon light images @@ -147,7 +183,7 @@ jobs: -e HISTORY_ARCHIVE_URLS="https://history.stellar.org/prd/core-live/core_live_001"\ -v $PWD/ledgerexport:/ledgerexport\ stellar/lighthorizon-ledgerexporter - + # run map job docker run -e NETWORK_PASSPHRASE='pubnet' -e JOB_INDEX_ENV=AWS_BATCH_JOB_ARRAY_INDEX -e AWS_BATCH_JOB_ARRAY_INDEX=0 -e BATCH_SIZE=64 -e FIRST_CHECKPOINT=64 \ -e WORKER_COUNT=1 -e RUN_MODE=map -v $PWD/ledgerexport:/ledgermeta -e TXMETA_SOURCE=file:///ledgermeta -v $PWD/index:/index -e INDEX_TARGET=file:///index stellar/lighthorizon-index-batch @@ -155,7 +191,7 @@ jobs: # run reduce job docker run -e NETWORK_PASSPHRASE='pubnet' -e JOB_INDEX_ENV=AWS_BATCH_JOB_ARRAY_INDEX -e AWS_BATCH_JOB_ARRAY_INDEX=0 -e MAP_JOB_COUNT=1 -e REDUCE_JOB_COUNT=1 \ -e WORKER_COUNT=1 -e RUN_MODE=reduce -v $PWD/index:/index -e INDEX_SOURCE_ROOT=file:///index -e INDEX_TARGET=file:///index stellar/lighthorizon-index-batch - + # Push images - if: github.ref == 'refs/heads/master' || github.ref == 'refs/heads/lighthorizon' name: Login to DockerHub @@ -166,6 +202,6 @@ jobs: - if: github.ref == 'refs/heads/master' || github.ref == 'refs/heads/lighthorizon' name: Push to DockerHub - run: | + run: | chmod 755 ./exp/lighthorizon/build/build.sh - ./exp/lighthorizon/build/build.sh all stellar latest true + ./exp/lighthorizon/build/build.sh all stellar latest true diff --git a/.github/workflows/update-completed-sprint-on-issue-closed.yml b/.github/workflows/update-completed-sprint-on-issue-closed.yml new file mode 100644 index 0000000000..8ca1cf26e7 --- /dev/null +++ b/.github/workflows/update-completed-sprint-on-issue-closed.yml @@ -0,0 +1,25 @@ +name: Update CompletedSprint on Issue Closed + +on: + issues: + types: [closed] + pull_request: + types: [closed] + +jobs: + update-completed-sprint: + runs-on: ubuntu-latest + steps: + - name: Generate token + id: generate_token + uses: tibdex/github-app-token@v1 + with: + app_id: ${{ secrets.GH_PROJECT_MANAGEMENT_APP_ID }} + private_key: ${{ secrets.GH_PROJECT_MANAGEMENT_APP_PEM }} + - name: Update CompletedSprint on Issue Closed + id: update_completedsprint_on_issue_closed + uses: stellar/actions/update-completed-sprint-on-issue-closed@main + with: + project_name: "Platform Scrum" + field_name: "CompletedSprint" + project_token: ${{ steps.generate_token.outputs.token }} diff --git a/.gitignore b/.gitignore index a9238c91c4..e4760a698c 100644 --- a/.gitignore +++ b/.gitignore @@ -2,8 +2,10 @@ /vendor /dist /local-archive -/.vscode/*.sql -/.vscode/settings.json +/services/horizon/captive-core +/services/horizon/horizon +/services/horizon/stellar-horizon +.vscode .idea debug .bundle @@ -13,3 +15,8 @@ debug *.key *.prof *.test +*.index +*.xdr +*.db +*.conf +*.lock diff --git a/.golangci.yml b/.golangci.yml new file mode 100644 index 0000000000..979ef6c0bc --- /dev/null +++ b/.golangci.yml @@ -0,0 +1,129 @@ +linters-settings: + depguard: + list-type: denylist + packages: + # logging is allowed only by logutils.Log, logrus + # is allowed to use only in logutils package + - github.com/sirupsen/logrus + packages-with-error-message: + - github.com/sirupsen/logrus: "logging is allowed only by logutils.Log" + dupl: + threshold: 100 + funlen: + lines: 100 + statements: 50 + goconst: + min-len: 2 + min-occurrences: 3 + gocritic: + enabled-tags: + - diagnostic + - experimental + - opinionated + - performance + - style + disabled-checks: + - dupImport # https://github.com/go-critic/go-critic/issues/845 + - ifElseChain + - octalLiteral + - whyNoLint + gocyclo: + min-complexity: 15 + goimports: + local-prefixes: github.com/golangci/golangci-lint + gomnd: + # don't include the "operation" and "assign" + checks: + - argument + - case + - condition + - return + ignored-numbers: + - '0' + - '1' + - '2' + - '3' + ignored-functions: + - strings.SplitN + + govet: + check-shadowing: true + settings: + printf: + funcs: + - (github.com/golangci/golangci-lint/pkg/logutils.Log).Infof + - (github.com/golangci/golangci-lint/pkg/logutils.Log).Warnf + - (github.com/golangci/golangci-lint/pkg/logutils.Log).Errorf + - (github.com/golangci/golangci-lint/pkg/logutils.Log).Fatalf + lll: + line-length: 140 + misspell: + locale: US + nolintlint: + allow-unused: false # report any unused nolint directives + require-explanation: false # don't require an explanation for nolint directives + require-specific: false # don't require nolint directives to be specific about which linter is being skipped + +linters: + disable-all: true + enable: + - bodyclose + - depguard + - dogsled + - dupl + - errcheck + - exportloopref + - funlen + - gochecknoinits + - goconst + #- gocritic + - gocyclo + - gofmt + - goimports + - gomnd + - goprintffuncname + - gosec + - gosimple + - govet + - ineffassign + - lll + - misspell + - nakedret + - noctx + - nolintlint + - staticcheck + - stylecheck + - typecheck + - unconvert + - unparam + - unused + #- whitespace + + # don't enable: + # - asciicheck + # - scopelint + # - gochecknoglobals + # - gocognit + # - godot + # - godox + # - goerr113 + # - interfacer + # - maligned + # - nestif + # - prealloc + # - testpackage + # - revive + # - wsl + +issues: + # Excluding configuration per-path, per-linter, per-text and per-source + exclude-rules: + - path: _test\.go + linters: + - govet + +run: + timeout: 5m + skip-dirs: + - docs + - vendor diff --git a/.vscode/launch.json b/.vscode/launch.json deleted file mode 100644 index af306a8c35..0000000000 --- a/.vscode/launch.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "version": "0.2.0", - "configurations": [ - { - "name": "Launch", - "type": "go", - "request": "launch", - "mode": "debug", - "remotePath": "", - "port": 2345, - "host": "127.0.0.1", - "program": "${workspaceRoot}/services/horizon/main.go", - "env": {}, - "args": [] - }, - { - "name": "Remote", - "type": "go", - "request": "launch", - "mode": "remote", - "remotePath": "${workspaceRoot}", - "port": 2345, - "host": "127.0.0.1", - "program": "${workspaceRoot}", - "env": {}, - "args": [] - } - ] -} \ No newline at end of file diff --git a/.vscode/spell.json b/.vscode/spell.json deleted file mode 100644 index 75b13c2429..0000000000 --- a/.vscode/spell.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "language": "en", - "ignoreWordsList": [ - "funcs", - "consts", - "unexported" - ], - "mistakeTypeToStatus": { - "Passive voice": "Hint", - "Spelling": "Error", - "Complex Expression": "Disable", - "Hidden Verbs": "Information", - "Hyphen Required": "Disable", - "Redundant Expression": "Disable", - "Did you mean...": "Disable", - "Repeated Word": "Warning", - "Missing apostrophe": "Warning", - "Cliches": "Disable", - "Missing Word": "Disable", - "Make I uppercase": "Warning" - }, - "languageIDs": [ - "markdown", - "plaintext" - ], - "ignoreRegExp": [ - "/\\(.*\\.(jpg|jpeg|png|md|gif|JPG|JPEG|PNG|MD|GIF)\\)/g", - "/((http|https|ftp|git)\\S*)/g" - ] -} \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json deleted file mode 100644 index a7e67b450f..0000000000 --- a/.vscode/tasks.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - // See https://go.microsoft.com/fwlink/?LinkId=733558 - // for the documentation about the tasks.json format - "version": "2.0.0", - "command": "go", - "options": { - "cwd": "${workspaceRoot}" - }, - "tasks": [ - { - "label": "go", - "type": "shell", - "command": "go", - "problemMatcher": [], - "group": { - "_id": "build", - "isDefault": false - } - } - ] -} diff --git a/DEVELOPING.md b/DEVELOPING.md index d138368c5b..fb9874b822 100644 --- a/DEVELOPING.md +++ b/DEVELOPING.md @@ -14,7 +14,7 @@ To checkout, build, and run most tests these tools are required: - [Go](https://golang.org/dl) (this repository is officially supported on the last two releases of Go) To run some tests these tools are also required: -- PostgreSQL 9.6+ server running locally, or set [environment variables](https://www.postgresql.org/docs/9.6/libpq-envars.html) (e.g. `PGHOST`, etc) for alternative host. +- PostgreSQL 12+ server running locally, or set [environment variables](https://www.postgresql.org/docs/12/libpq-envars.html) (e.g. `PGHOST`, etc) for alternative host. - MySQL 10.1+ server running locally. ## Get the code diff --git a/Makefile b/Makefile index bb86d10b14..e07da4d9b8 100644 --- a/Makefile +++ b/Makefile @@ -7,9 +7,16 @@ xdr/Stellar-ledger.x \ xdr/Stellar-overlay.x \ xdr/Stellar-transaction.x \ xdr/Stellar-types.x \ +xdr/Stellar-contract-env-meta.x \ +xdr/Stellar-contract-meta.x \ +xdr/Stellar-contract-spec.x \ +xdr/Stellar-contract.x \ +xdr/Stellar-internal.x \ +xdr/Stellar-contract-config-setting.x \ xdr/Stellar-lighthorizon.x -XDRGEN_COMMIT=3f6808cd161d72474ffbe9eedbd7013de7f92748 +XDRGEN_COMMIT=e2cac557162d99b12ae73b846cf3d5bfe16636de +XDR_COMMIT=bb54e505f814386a3f45172e0b7e95b7badbe969 .PHONY: xdr xdr-clean xdr-update @@ -22,6 +29,9 @@ ticker: friendbot: $(MAKE) -C services/friendbot/ docker-build +horizon: + $(MAKE) -C services/horizon/ binary-build + webauth: $(MAKE) -C exp/services/webauth/ docker-build @@ -33,21 +43,24 @@ regulated-assets-approval-server: gxdr/xdr_generated.go: $(XDRS) go run github.com/xdrpp/goxdr/cmd/goxdr -p gxdr -enum-comments -o $@ $(XDRS) - go fmt $@ + gofmt -s -w $@ xdr/%.x: - curl -Lsf -o $@ https://raw.githubusercontent.com/stellar/stellar-core/master/src/protocol-curr/$@ + printf "%s" ${XDR_COMMIT} > xdr/xdr_commit_generated.txt + curl -Lsf -o $@ https://raw.githubusercontent.com/stellar/stellar-xdr/$(XDR_COMMIT)/$(@F) xdr/xdr_generated.go: $(XDRS) docker run -it --rm -v $$PWD:/wd -w /wd ruby /bin/bash -c '\ - gem install specific_install -v 0.3.7 && \ + gem install specific_install -v 0.3.8 && \ gem specific_install https://github.com/stellar/xdrgen.git -b $(XDRGEN_COMMIT) && \ xdrgen \ --language go \ --namespace xdr \ --output xdr/ \ $(XDRS)' - go fmt $@ + # No, you're not reading the following wrong. Apperantly, running gofmt twice required to complete it's formatting. + gofmt -s -w $@ + gofmt -s -w $@ xdr: gxdr/xdr_generated.go xdr/xdr_generated.go diff --git a/README.md b/README.md index b303f907e2..8045b39839 100644 --- a/README.md +++ b/README.md @@ -80,6 +80,6 @@ Contributions are welcome! See [CONTRIBUTING.md](CONTRIBUTING.md) for more detai ### Developing -See [DEVELOPING.md](DEVELOPING.md) for helpful instructions for getting started developing code in this repository. +See [GUIDE_FOR_DEVELOPERS.md](/services/horizon/internal/docs/GUIDE_FOR_DEVELOPERS.md) for helpful instructions for getting started developing code in this repository. [Stellar Development Foundation]: https://stellar.org diff --git a/amount/main.go b/amount/main.go index b1b7bc1474..bb7b9964b4 100644 --- a/amount/main.go +++ b/amount/main.go @@ -117,6 +117,22 @@ func String(v xdr.Int64) string { return StringFromInt64(int64(v)) } +// String128 converts a signed 128-bit integer into a string, boldly assuming +// 7-decimal precision. +// +// TODO: This should be adapted to variable precision when appopriate, but 7 +// decimals is the correct default for Stellar Classic amounts. +func String128(v xdr.Int128Parts) string { + // the upper half of the i128 always indicates its sign regardless of its + // value, just like a native signed type + val := big.NewInt(int64(v.Hi)) + val.Lsh(val, 64).Add(val, new(big.Int).SetUint64(uint64(v.Lo))) + + rat := new(big.Rat).SetInt(val) + rat.Quo(rat, bigOne) + return rat.FloatString(7) +} + // StringFromInt64 returns an "amount string" from the provided raw int64 value `v`. func StringFromInt64(v int64) string { r := big.NewRat(v, 1) diff --git a/clients/horizonclient/CHANGELOG.md b/clients/horizonclient/CHANGELOG.md index df3a7dcb67..bcd3ef331d 100644 --- a/clients/horizonclient/CHANGELOG.md +++ b/clients/horizonclient/CHANGELOG.md @@ -5,6 +5,8 @@ file. This project adheres to [Semantic Versioning](http://semver.org/). ## Unreleased +## [v11.0.0](https://github.com/stellar/go/releases/tag/horizonclient-v11.0.0) - 2023-03-29 + * Type of `AccountSequence` field in `protocols/horizon.Account` was changed to `int64`. ## [v10.0.0](https://github.com/stellar/go/releases/tag/horizonclient-v10.0.0) - 2022-04-18 diff --git a/clients/horizonclient/client.go b/clients/horizonclient/client.go index e6b8d80df5..b27b400364 100644 --- a/clients/horizonclient/client.go +++ b/clients/horizonclient/client.go @@ -179,7 +179,7 @@ func (c *Client) stream( var buffer bytes.Buffer nonEmptylinesRead := 0 for { - // Check if ctx is not cancelled + // Check if ctx is not canceled select { case <-ctx.Done(): return nil @@ -197,7 +197,7 @@ func (c *Client) stream( // // In the former case, that (again) should never happen in Horizon, we need to // check if there are any events we need to decode. We do this in the `if` - // statement below just in case if Horizon behaviour changes in a future. + // statement below just in case if Horizon behavior changes in a future. // // From spec: // > Once the end of the file is reached, the user agent must dispatch the @@ -278,7 +278,7 @@ func (c *Client) fixHorizonURL() string { return c.HorizonURL } -// SetHorizonTimeout allows users to set the timeout before a horizon request is cancelled. +// SetHorizonTimeout allows users to set the timeout before a horizon request is canceled. // The timeout is specified as a time.Duration which is in nanoseconds. func (c *Client) SetHorizonTimeout(t time.Duration) *Client { c.horizonTimeout = t diff --git a/clients/horizonclient/internal.go b/clients/horizonclient/internal.go index 2133125550..123788caa9 100644 --- a/clients/horizonclient/internal.go +++ b/clients/horizonclient/internal.go @@ -140,9 +140,9 @@ func setCurrentServerTime(host string, serverDate []string, clock *clock.Clock) // currentServerTime returns the current server time for a given horizon server func currentServerTime(host string, currentTimeUTC int64) int64 { serverTimeMapMutex.Lock() - st := ServerTimeMap[host] + st, has := ServerTimeMap[host] serverTimeMapMutex.Unlock() - if &st == nil { + if !has { return 0 } diff --git a/clients/horizonclient/internal_test.go b/clients/horizonclient/internal_test.go new file mode 100644 index 0000000000..80391c1d0c --- /dev/null +++ b/clients/horizonclient/internal_test.go @@ -0,0 +1,44 @@ +package horizonclient + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func TestCurrentServerTime(t *testing.T) { + t.Run("non-existing-host-name", func(t *testing.T) { + currentTime := currentServerTime("non-existing-host-name", 60) + require.Zerof(t, currentTime, "server time for non-existing time is expected to be zero, but was %d instead", currentTime) + }) + + t.Run("server-behind", func(t *testing.T) { + serverTimeMapMutex.Lock() + ServerTimeMap["TestCurrentServerTime-server-behind"] = ServerTimeRecord{ServerTime: 27, LocalTimeRecorded: 23} + serverTimeMapMutex.Unlock() + + currentTime := currentServerTime("TestCurrentServerTime-server-behind", 500) + defer func() { + serverTimeMapMutex.Lock() + delete(ServerTimeMap, "TestCurrentServerTime-server-behind") + serverTimeMapMutex.Unlock() + }() + + require.Zerof(t, currentTime, "server time is too old and the method should have returned 0; instead, %d was returned", currentTime) + }) + + t.Run("normal", func(t *testing.T) { + serverTimeMapMutex.Lock() + ServerTimeMap["TestCurrentServerTime-server"] = ServerTimeRecord{ServerTime: 27, LocalTimeRecorded: 23} + serverTimeMapMutex.Unlock() + + defer func() { + serverTimeMapMutex.Lock() + delete(ServerTimeMap, "TestCurrentServerTime-server") + serverTimeMapMutex.Unlock() + }() + + currentTime := currentServerTime("TestCurrentServerTime-server", 37) + require.Equalf(t, currentTime, int64(41), "currentServerTime should have returned %d, but returned %d instead", 41, currentTime) + }) +} diff --git a/clients/horizonclient/main_test.go b/clients/horizonclient/main_test.go index d42fab46e5..2149bbbf29 100644 --- a/clients/horizonclient/main_test.go +++ b/clients/horizonclient/main_test.go @@ -58,7 +58,7 @@ func TestCheckMemoRequired(t *testing.T) { Asset: txnbuild.NativeAsset{}, } - asset := txnbuild.CreditAsset{"ABCD", kp.Address()} + asset := txnbuild.CreditAsset{Code: "ABCD", Issuer: kp.Address()} pathPaymentStrictSend := txnbuild.PathPaymentStrictSend{ SendAsset: asset, SendAmount: "10", @@ -1455,7 +1455,9 @@ func TestFetchTimebounds(t *testing.T) { // When no saved server time, return local time st, err := client.FetchTimebounds(100) if assert.NoError(t, err) { + serverTimeMapMutex.Lock() assert.IsType(t, ServerTimeMap["localhost"], ServerTimeRecord{}) + serverTimeMapMutex.Unlock() assert.Equal(t, st.MinTime, int64(0)) } @@ -1472,7 +1474,9 @@ func TestFetchTimebounds(t *testing.T) { // get saved server time st, err = client.FetchTimebounds(100) if assert.NoError(t, err) { + serverTimeMapMutex.Lock() assert.IsType(t, ServerTimeMap["localhost"], ServerTimeRecord{}) + serverTimeMapMutex.Unlock() assert.Equal(t, st.MinTime, int64(0)) // serverTime + 100seconds assert.Equal(t, st.MaxTime, int64(1560947196)) @@ -1480,7 +1484,9 @@ func TestFetchTimebounds(t *testing.T) { // mock server time newRecord := ServerTimeRecord{ServerTime: 100, LocalTimeRecorded: 1560947096} + serverTimeMapMutex.Lock() ServerTimeMap["localhost"] = newRecord + serverTimeMapMutex.Unlock() st, err = client.FetchTimebounds(100) assert.NoError(t, err) assert.IsType(t, st, txnbuild.TimeBounds{}) diff --git a/clients/stellarcore/client.go b/clients/stellarcore/client.go index 7fdb62515a..931a076021 100644 --- a/clients/stellarcore/client.go +++ b/clients/stellarcore/client.go @@ -4,6 +4,7 @@ import ( "context" "encoding/json" "fmt" + "io" "io/ioutil" "net/http" "net/url" @@ -14,6 +15,7 @@ import ( proto "github.com/stellar/go/protocols/stellarcore" "github.com/stellar/go/support/errors" + "github.com/stellar/go/xdr" ) // Client represents a client that is capable of communicating with a @@ -27,47 +29,117 @@ type Client struct { URL string } +// drainReponse is a helper method for draining the body stream off the http +// response object and optionally close the stream. It would also update the +// error but only as long as there wasn't an error before - this would allow +// the various methods to report the first error that took place. +// in case an error was encountered during either the draining or closing of the +// stream, that error would be returned. +func drainReponse(hresp *http.Response, close bool, err *error) (outerror error) { + _, err2 := io.Copy(ioutil.Discard, hresp.Body) + if err2 != nil { + if err != nil && *err == nil { + *err = errors.Wrap(err2, "unable to read excess data from response") + } + outerror = err2 + } + if close { + err2 = hresp.Body.Close() + if err2 != nil { + if err != nil && *err == nil { + *err = errors.Wrap(err2, "unable to close response body") + } + outerror = err2 + } + } + return +} + // Upgrade upgrades the protocol version running on the stellar core instance -func (c *Client) Upgrade(ctx context.Context, version int) error { +func (c *Client) Upgrade(ctx context.Context, version int) (err error) { queryParams := url.Values{} queryParams.Add("mode", "set") queryParams.Add("upgradetime", "1970-01-01T00:00:00Z") queryParams.Add("protocolversion", strconv.Itoa(version)) - req, err := c.simpleGet(ctx, "upgrades", queryParams) + var req *http.Request + req, err = c.simpleGet(ctx, "upgrades", queryParams) if err != nil { return errors.Wrap(err, "failed to create request") } - hresp, err := c.http().Do(req) + var hresp *http.Response + hresp, err = c.http().Do(req) if err != nil { return errors.Wrap(err, "http request errored") } + defer drainReponse(hresp, true, &err) //nolint:errcheck + + if !(hresp.StatusCode >= 200 && hresp.StatusCode < 300) { + err = errors.New("http request failed with non-200 status code") + return + } + return nil +} + +// GetLedgerEntry submits a request to the stellar core instance to get the latest +// state of a given ledger entry. +func (c *Client) GetLedgerEntry(ctx context.Context, ledgerKey xdr.LedgerKey) (proto.GetLedgerEntryResponse, error) { + b64, err := xdr.MarshalBase64(ledgerKey) + if err != nil { + return proto.GetLedgerEntryResponse{}, errors.Wrap(err, "failed to marshal ledger key") + } + q := url.Values{} + q.Set("key", b64) + + req, err := c.simpleGet(ctx, "getledgerentry", q) + if err != nil { + return proto.GetLedgerEntryResponse{}, errors.Wrap(err, "failed to create request") + } + + hresp, err := c.http().Do(req) + if err != nil { + return proto.GetLedgerEntryResponse{}, errors.Wrap(err, "http request errored") + } defer hresp.Body.Close() if !(hresp.StatusCode >= 200 && hresp.StatusCode < 300) { - return errors.New("http request failed with non-200 status code") + if drainReponse(hresp, false, &err) != nil { + return proto.GetLedgerEntryResponse{}, err + } + return proto.GetLedgerEntryResponse{}, errors.New("http request failed with non-200 status code") } - return nil + responseBytes, err := io.ReadAll(hresp.Body) + if err != nil { + return proto.GetLedgerEntryResponse{}, errors.Wrap(err, "could not read response") + } + + var response proto.GetLedgerEntryResponse + if err = json.Unmarshal(responseBytes, &response); err != nil { + return proto.GetLedgerEntryResponse{}, errors.Wrap(err, "json decode failed: "+string(responseBytes)) + } + + return response, nil } // Info calls the `info` command on the connected stellar core and returns the // provided response func (c *Client) Info(ctx context.Context) (resp *proto.InfoResponse, err error) { - - req, err := c.simpleGet(ctx, "info", nil) + var req *http.Request + req, err = c.simpleGet(ctx, "info", nil) if err != nil { err = errors.Wrap(err, "failed to create request") return } - hresp, err := c.http().Do(req) + var hresp *http.Response + hresp, err = c.http().Do(req) if err != nil { err = errors.Wrap(err, "http request errored") return } - defer hresp.Body.Close() + defer drainReponse(hresp, true, &err) //nolint:errcheck if !(hresp.StatusCode >= 200 && hresp.StatusCode < 300) { err = errors.New("http request failed with non-200 status code") @@ -75,7 +147,6 @@ func (c *Client) Info(ctx context.Context) (resp *proto.InfoResponse, err error) } err = json.NewDecoder(hresp.Body).Decode(&resp) - if err != nil { err = errors.Wrap(err, "json decode failed") return @@ -85,8 +156,9 @@ func (c *Client) Info(ctx context.Context) (resp *proto.InfoResponse, err error) } // SetCursor calls the `setcursor` command on the connected stellar core -func (c *Client) SetCursor(ctx context.Context, id string, cursor int32) error { - req, err := c.simpleGet(ctx, "setcursor", url.Values{ +func (c *Client) SetCursor(ctx context.Context, id string, cursor int32) (err error) { + var req *http.Request + req, err = c.simpleGet(ctx, "setcursor", url.Values{ "id": []string{id}, "cursor": []string{fmt.Sprintf("%d", cursor)}, }) @@ -95,13 +167,20 @@ func (c *Client) SetCursor(ctx context.Context, id string, cursor int32) error { return errors.Wrap(err, "failed to create request") } - hresp, err := c.http().Do(req) + var hresp *http.Response + hresp, err = c.http().Do(req) if err != nil { return errors.Wrap(err, "http request errored") } - defer hresp.Body.Close() + defer drainReponse(hresp, true, &err) //nolint:errcheck - raw, err := ioutil.ReadAll(hresp.Body) + if !(hresp.StatusCode >= 200 && hresp.StatusCode < 300) { + err = errors.New("http request failed with non-200 status code") + return err + } + + var raw []byte + raw, err = ioutil.ReadAll(hresp.Body) if err != nil { return err } @@ -120,18 +199,25 @@ func (c *Client) SubmitTransaction(ctx context.Context, envelope string) (resp * q := url.Values{} q.Set("blob", envelope) - req, err := c.simpleGet(ctx, "tx", q) + var req *http.Request + req, err = c.simpleGet(ctx, "tx", q) if err != nil { err = errors.Wrap(err, "failed to create request") return } - hresp, err := c.http().Do(req) + var hresp *http.Response + hresp, err = c.http().Do(req) if err != nil { err = errors.Wrap(err, "http request errored") return } - defer hresp.Body.Close() + defer drainReponse(hresp, true, &err) //nolint:errcheck + + if !(hresp.StatusCode >= 200 && hresp.StatusCode < 300) { + err = errors.New("http request failed with non-200 status code") + return + } err = json.NewDecoder(hresp.Body).Decode(&resp) @@ -173,21 +259,24 @@ func (c *Client) ManualClose(ctx context.Context) (err error) { q := url.Values{} - req, err := c.simpleGet(ctx, "manualclose", q) + var req *http.Request + req, err = c.simpleGet(ctx, "manualclose", q) if err != nil { err = errors.Wrap(err, "failed to create request") return } - hresp, err := c.http().Do(req) + var hresp *http.Response + hresp, err = c.http().Do(req) if err != nil { err = errors.Wrap(err, "http request errored") return } - defer hresp.Body.Close() + defer drainReponse(hresp, true, &err) //nolint:errcheck if !(hresp.StatusCode >= 200 && hresp.StatusCode < 300) { err = errors.New("http request failed with non-200 status code") + return } // verify there wasn't an exception @@ -195,6 +284,9 @@ func (c *Client) ManualClose(ctx context.Context) (err error) { Exception string `json:"exception"` }{} if decErr := json.NewDecoder(hresp.Body).Decode(&resp); decErr != nil { + // At this point we want to do `err = decErr`, but that breaks our unit tests. + // we should look into this situation and figure out how to validate + // a correct output for this command. return } if resp.Exception != "" { @@ -232,10 +324,11 @@ func (c *Client) simpleGet( } newURL := u.String() - req, err := http.NewRequest(http.MethodGet, newURL, nil) + var req *http.Request + req, err = http.NewRequestWithContext(ctx, http.MethodGet, newURL, nil) if err != nil { return nil, errors.Wrap(err, "failed to create request") } - return req.WithContext(ctx), nil + return req, nil } diff --git a/clients/stellarcore/client_test.go b/clients/stellarcore/client_test.go index 90f4c1cc55..6cfd01b210 100644 --- a/clients/stellarcore/client_test.go +++ b/clients/stellarcore/client_test.go @@ -5,9 +5,10 @@ import ( "net/http" "testing" + "github.com/stretchr/testify/assert" + proto "github.com/stellar/go/protocols/stellarcore" "github.com/stellar/go/support/http/httptest" - "github.com/stretchr/testify/assert" ) func TestSubmitTransaction(t *testing.T) { @@ -27,6 +28,26 @@ func TestSubmitTransaction(t *testing.T) { } } +func TestSubmitTransactionError(t *testing.T) { + hmock := httptest.NewClient() + c := &Client{HTTP: hmock, URL: "http://localhost:11626"} + + // happy path - new transaction + hmock.On("GET", "http://localhost:11626/tx?blob=foo"). + ReturnString( + 200, + `{"diagnostic_events":"AAAAAQAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAgAAAA8AAAAFZXJyb3IAAAAAAAACAAAAAwAAAAUAAAAQAAAAAQAAAAMAAAAOAAAAU3RyYW5zYWN0aW9uIGBzb3JvYmFuRGF0YS5yZXNvdXJjZUZlZWAgaXMgbG93ZXIgdGhhbiB0aGUgYWN0dWFsIFNvcm9iYW4gcmVzb3VyY2UgZmVlAAAAAAUAAAAAAAEJcwAAAAUAAAAAAAG6fA==","error":"AAAAAAABCdf////vAAAAAA==","status":"ERROR"}`, + ) + + resp, err := c.SubmitTransaction(context.Background(), "foo") + + if assert.NoError(t, err) { + assert.Equal(t, "ERROR", resp.Status) + assert.Equal(t, resp.Error, "AAAAAAABCdf////vAAAAAA==") + assert.Equal(t, "AAAAAQAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAgAAAA8AAAAFZXJyb3IAAAAAAAACAAAAAwAAAAUAAAAQAAAAAQAAAAMAAAAOAAAAU3RyYW5zYWN0aW9uIGBzb3JvYmFuRGF0YS5yZXNvdXJjZUZlZWAgaXMgbG93ZXIgdGhhbiB0aGUgYWN0dWFsIFNvcm9iYW4gcmVzb3VyY2UgZmVlAAAAAAUAAAAAAAEJcwAAAAUAAAAAAAG6fA==", resp.DiagnosticEvents) + } +} + func TestManualClose(t *testing.T) { hmock := httptest.NewClient() c := &Client{HTTP: hmock, URL: "http://localhost:11626"} diff --git a/exp/lighthorizon/build/ledgerexporter/captive-core-pubnet.cfg b/exp/lighthorizon/build/ledgerexporter/captive-core-pubnet.cfg index fc4ce4c7da..22b149e3f8 100644 --- a/exp/lighthorizon/build/ledgerexporter/captive-core-pubnet.cfg +++ b/exp/lighthorizon/build/ledgerexporter/captive-core-pubnet.cfg @@ -3,6 +3,11 @@ DATABASE = "sqlite3:///cc/stellar.db" FAILURE_SAFETY=1 +# WARNING! Do not use this config in production. Quorum sets should +# be carefully selected manually. +NETWORK_PASSPHRASE="Public Global Stellar Network ; September 2015" +HTTP_PORT=11626 + [[HOME_DOMAINS]] HOME_DOMAIN="stellar.org" QUALITY="HIGH" @@ -28,8 +33,8 @@ HOME_DOMAIN="stellar.blockdaemon.com" QUALITY="HIGH" [[HOME_DOMAINS]] -HOME_DOMAIN="wirexapp.com" -QUALITY="HIGH" +HOME_DOMAIN = "www.franklintempleton.com" +QUALITY = "HIGH" [[VALIDATORS]] NAME="sdf_1" @@ -172,22 +177,30 @@ ADDRESS="stellar-full-validator3.bdnodes.net" HISTORY="curl -sf https://stellar-full-history3.bdnodes.net/{0} -o {1}" [[VALIDATORS]] -NAME="wirexUS" -ADDRESS="us.stellar.wirexapp.com" -HOME_DOMAIN="wirexapp.com" -PUBLIC_KEY="GDXUKFGG76WJC7ACEH3JUPLKM5N5S76QSMNDBONREUXPCZYVPOLFWXUS" -HISTORY="curl -sf http://wxhorizonusstga1.blob.core.windows.net/history/{0} -o {1}" +NAME = "FT_SCV_1" +HOME_DOMAIN = "www.franklintempleton.com" +PUBLIC_KEY = "GARYGQ5F2IJEBCZJCBNPWNWVDOFK7IBOHLJKKSG2TMHDQKEEC6P4PE4V" +ADDRESS = "stellar1.franklintempleton.com:11625" +HISTORY = "curl -sf https://stellar-history-usw.franklintempleton.com/azuswshf401/{0} -o {1}" [[VALIDATORS]] -NAME="wirexUK" -ADDRESS="uk.stellar.wirexapp.com" -HOME_DOMAIN="wirexapp.com" -PUBLIC_KEY="GBBQQT3EIUSXRJC6TGUCGVA3FVPXVZLGG3OJYACWBEWYBHU46WJLWXEU" -HISTORY="curl -sf http://wxhorizonukstga1.blob.core.windows.net/history/{0} -o {1}" +NAME = "FT_SCV_2" +HOME_DOMAIN = "www.franklintempleton.com" +PUBLIC_KEY = "GCMSM2VFZGRPTZKPH5OABHGH4F3AVS6XTNJXDGCZ3MKCOSUBH3FL6DOB" +ADDRESS = "stellar2.franklintempleton.com:11625" +HISTORY = "curl -sf https://stellar-history-usc.franklintempleton.com/azuscshf401/{0} -o {1}" [[VALIDATORS]] +<<<<<<<< HEAD:exp/lighthorizon/build/ledgerexporter/captive-core-pubnet.cfg NAME="wirexSG" ADDRESS="sg.stellar.wirexapp.com" HOME_DOMAIN="wirexapp.com" PUBLIC_KEY="GAB3GZIE6XAYWXGZUDM4GMFFLJBFMLE2JDPUCWUZXMOMT3NHXDHEWXAS" HISTORY="curl -sf http://wxhorizonasiastga1.blob.core.windows.net/history/{0} -o {1}" +======== +NAME = "FT_SCV_3" +HOME_DOMAIN = "www.franklintempleton.com" +PUBLIC_KEY = "GA7DV63PBUUWNUFAF4GAZVXU2OZMYRATDLKTC7VTCG7AU4XUPN5VRX4A" +ADDRESS = "stellar3.franklintempleton.com:11625" +HISTORY = "curl -sf https://stellar-history-ins.franklintempleton.com/azinsshf401/{0} -o {1}" +>>>>>>>> master:services/horizon/internal/configs/captive-core-pubnet.cfg diff --git a/exp/orderbook/batch.go b/exp/orderbook/batch.go index 0497de001e..32da7a2ddc 100644 --- a/exp/orderbook/batch.go +++ b/exp/orderbook/batch.go @@ -87,6 +87,8 @@ func (tx *orderBookBatchedUpdates) apply(ledger uint32) error { return errUnexpectedLedger } + reallocatePairs := map[tradingPair]struct{}{} + for _, operation := range tx.operations { switch operation.operationType { case addOfferOperationType: @@ -94,8 +96,10 @@ func (tx *orderBookBatchedUpdates) apply(ledger uint32) error { panic(errors.Wrap(err, "could not apply update in batch")) } case removeOfferOperationType: - if _, ok := tx.orderbook.tradingPairForOffer[operation.offerID]; !ok { + if pair, ok := tx.orderbook.tradingPairForOffer[operation.offerID]; !ok { continue + } else { + reallocatePairs[pair] = struct{}{} } if err := tx.orderbook.removeOffer(operation.offerID); err != nil { panic(errors.Wrap(err, "could not apply update in batch")) @@ -114,5 +118,9 @@ func (tx *orderBookBatchedUpdates) apply(ledger uint32) error { tx.orderbook.lastLedger = ledger + for pair := range reallocatePairs { + tx.orderbook.venuesForSellingAsset[pair.sellingAsset].reallocate() + tx.orderbook.venuesForBuyingAsset[pair.buyingAsset].reallocate() + } return nil } diff --git a/exp/orderbook/edges.go b/exp/orderbook/edges.go index 44a90f45fe..6bd01bc81b 100644 --- a/exp/orderbook/edges.go +++ b/exp/orderbook/edges.go @@ -4,6 +4,7 @@ import ( "sort" "github.com/stellar/go/xdr" + "golang.org/x/exp/slices" ) // edgeSet maintains a mapping of assets to a set of venues, which @@ -14,6 +15,10 @@ type edgeSet []edge type edge struct { key int32 value Venues + + // reallocate is set to true when some offers were removed from the edge. + // See edgeSet.reallocate() godoc for more information. + reallocate bool } func (e edgeSet) find(key int32) int { @@ -35,17 +40,12 @@ func (e edgeSet) addOffer(key int32, offer xdr.OfferEntry) edgeSet { } offers := e[i].value.offers - // find the smallest i such that Price of offers[i] > Price of offer + // find the smallest i such that Price of offers[i] > Price of offer insertIndex := sort.Search(len(offers), func(j int) bool { return offer.Price.Cheaper(offers[j].Price) }) - // then insert it into the slice (taken from Method 2 at - // https://github.com/golang/go/wiki/SliceTricks#insert). - offers = append(offers, xdr.OfferEntry{}) // add to end - copy(offers[insertIndex+1:], offers[insertIndex:]) // shift right by 1 - offers[insertIndex] = offer // insert - + offers = slices.Insert(offers, insertIndex, offer) e[i].value = Venues{offers: offers, pool: e[i].value.pool} return e } @@ -76,9 +76,7 @@ func (e edgeSet) removeOffer(key int32, offerID xdr.Int64) (edgeSet, bool) { continue } - // remove the entry in the slice at this location (taken from - // https://github.com/golang/go/wiki/SliceTricks#cut). - updatedOffers = append(offers[:i], offers[i+1:]...) + updatedOffers = slices.Delete(offers, i, i+1) contains = true break } @@ -88,9 +86,10 @@ func (e edgeSet) removeOffer(key int32, offerID xdr.Int64) (edgeSet, bool) { } if len(updatedOffers) == 0 && e[i].value.pool.Body.ConstantProduct == nil { - return append(e[:i], e[i+1:]...), true + return slices.Delete(e, i, i+1), true } e[i].value.offers = updatedOffers + e[i].reallocate = true return e, true } @@ -101,9 +100,24 @@ func (e edgeSet) removePool(key int32) edgeSet { } if len(e[i].value.offers) == 0 { - return append(e[:i], e[i+1:]...) + return slices.Delete(e, i, i+1) } e[i].value = Venues{offers: e[i].value.offers} return e } + +// reallocate recreates offers slice when edge.reallocate is set to true and +// this is true after an offer is removed. +// Without periodic reallocations an arbitrary account could create 1000s of +// offers in an orderbook, then remove them but the space occupied by these +// offers would not be released by GC because an array used internally is +// the same. This can lead to DoS attack by OOM. +func (e edgeSet) reallocate() { + for i := 0; i < len(e); i++ { + if e[i].reallocate { + e[i].value.offers = append([]xdr.OfferEntry(nil), e[i].value.offers[:]...) + e[i].reallocate = false + } + } +} diff --git a/exp/orderbook/edges_test.go b/exp/orderbook/edges_test.go new file mode 100644 index 0000000000..039954aa98 --- /dev/null +++ b/exp/orderbook/edges_test.go @@ -0,0 +1,46 @@ +package orderbook + +import ( + "runtime" + "testing" + + "github.com/stellar/go/xdr" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestRemoveOffersMemoryUsage(t *testing.T) { + edges := edgeSet{} + for i := 0; i < 2000; i++ { + edges = edges.addOffer(1, xdr.OfferEntry{ + SellerId: xdr.MustAddress("GCZFUQEPMLGUE2NB5RR7C3I2LTTLOEBM7GYD7PDKI4SU5HHWTDB553WD"), + OfferId: xdr.Int64(i), + }) + } + + var afterAdded, afterRemoved, afterReallocate runtime.MemStats + runtime.ReadMemStats(&afterAdded) + + t.Logf("after added: %d\n", afterAdded.HeapInuse) + + // Remove all offers except one + for i := 0; i < 2000-1; i++ { + var removed bool + edges, removed = edges.removeOffer(1, xdr.Int64(i)) + require.True(t, removed) + + } + + runtime.ReadMemStats(&afterRemoved) + t.Logf("after removed: %d\n", afterRemoved.HeapInuse) + + require.True(t, edges[0].reallocate) + edges.reallocate() + runtime.GC() + + runtime.ReadMemStats(&afterReallocate) + t.Logf("after reallocate: %d\n", afterReallocate.HeapInuse) + + assert.Less(t, afterReallocate.HeapInuse, afterAdded.HeapInuse) + assert.Less(t, afterReallocate.HeapInuse, afterRemoved.HeapInuse) +} diff --git a/exp/orderbook/graph_benchmark_test.go b/exp/orderbook/graph_benchmark_test.go index 8588a2f36a..8ad04fd401 100644 --- a/exp/orderbook/graph_benchmark_test.go +++ b/exp/orderbook/graph_benchmark_test.go @@ -268,7 +268,7 @@ func BenchmarkLiquidityPoolExpectations(b *testing.B) { func createRandomAmounts(quantity int) []xdr.Int64 { amounts := make([]xdr.Int64, quantity) - for i, _ := range amounts { + for i := range amounts { amounts[i] = xdr.Int64(1 + rand.Int63n(math.MaxInt64-100)) } return amounts diff --git a/exp/orderbook/graph_test.go b/exp/orderbook/graph_test.go index 203c923167..6793db49b5 100644 --- a/exp/orderbook/graph_test.go +++ b/exp/orderbook/graph_test.go @@ -166,7 +166,7 @@ func assertGraphEquals(t *testing.T, a, b *OrderBookGraph) { assert.Equalf(t, len(a.liquidityPools), len(b.liquidityPools), "expected same # of liquidity pools but got %v %v", a, b) - for assetString, _ := range a.assetStringToID { + for assetString := range a.assetStringToID { asset := a.assetStringToID[assetString] otherAsset, ok := b.assetStringToID[assetString] if !ok { @@ -463,22 +463,26 @@ func TestAddOffersOrderBook(t *testing.T) { { assetStringToID[usdAsset.String()], makeVenues(quarterOffer, fiftyCentsOffer, dollarOffer), + false, }, { assetStringToID[eurAsset.String()], makeVenues(eurOffer, twoEurOffer, threeEurOffer), + false, }, }, { { assetStringToID[eurAsset.String()], makeVenues(eurUsdOffer, otherEurUsdOffer), + false, }, }, { { assetStringToID[usdAsset.String()], makeVenues(usdEurOffer), + false, }, }, }, @@ -488,20 +492,24 @@ func TestAddOffersOrderBook(t *testing.T) { { assetStringToID[eurAsset.String()], makeVenues(usdEurOffer), + false, }, { assetStringToID[nativeAsset.String()], makeVenues(quarterOffer, fiftyCentsOffer, dollarOffer), + false, }, }, { { assetStringToID[usdAsset.String()], makeVenues(eurUsdOffer, otherEurUsdOffer), + false, }, { assetStringToID[nativeAsset.String()], makeVenues(eurOffer, twoEurOffer, threeEurOffer), + false, }, }, }, @@ -705,22 +713,26 @@ func TestUpdateOfferOrderBook(t *testing.T) { { assetStringToID[usdAsset.String()], makeVenues(quarterOffer, fiftyCentsOffer, dollarOffer), + false, }, { assetStringToID[eurAsset.String()], makeVenues(eurOffer, twoEurOffer, threeEurOffer), + false, }, }, { { assetStringToID[eurAsset.String()], makeVenues(otherEurUsdOffer, eurUsdOffer), + false, }, }, { { assetStringToID[usdAsset.String()], makeVenues(usdEurOffer), + false, }, }, }, @@ -730,20 +742,24 @@ func TestUpdateOfferOrderBook(t *testing.T) { { assetStringToID[nativeAsset.String()], makeVenues(quarterOffer, fiftyCentsOffer, dollarOffer), + false, }, { assetStringToID[eurAsset.String()], makeVenues(usdEurOffer), + false, }, }, { { assetStringToID[nativeAsset.String()], makeVenues(eurOffer, twoEurOffer, threeEurOffer), + false, }, { assetStringToID[usdAsset.String()], makeVenues(otherEurUsdOffer, eurUsdOffer), + false, }, }, }, @@ -876,16 +892,19 @@ func TestRemoveOfferOrderBook(t *testing.T) { { assetStringToID[usdAsset.String()], makeVenues(quarterOffer, fiftyCentsOffer), + false, }, { assetStringToID[eurAsset.String()], makeVenues(eurOffer, twoEurOffer, threeEurOffer), + false, }, }, { { assetStringToID[eurAsset.String()], makeVenues(eurUsdOffer), + false, }, }, {}, @@ -896,16 +915,19 @@ func TestRemoveOfferOrderBook(t *testing.T) { { assetStringToID[nativeAsset.String()], makeVenues(quarterOffer, fiftyCentsOffer), + false, }, }, { { assetStringToID[nativeAsset.String()], makeVenues(eurOffer, twoEurOffer, threeEurOffer), + false, }, { assetStringToID[usdAsset.String()], makeVenues(eurUsdOffer), + false, }, }, }, diff --git a/exp/orderbook/search.go b/exp/orderbook/search.go index 06b0f0f8b9..86bf14cf76 100644 --- a/exp/orderbook/search.go +++ b/exp/orderbook/search.go @@ -162,7 +162,7 @@ func search( pathToCurrentAsset := bestPath[currentAsset] edges := state.venues(currentAsset) for j := 0; j < len(edges); j++ { - // Exit early if the context was cancelled. + // Exit early if the context was canceled. if err := ctx.Err(); err != nil { return err } diff --git a/exp/services/captivecore/README.md b/exp/services/captivecore/README.md deleted file mode 100644 index 3d621008fe..0000000000 --- a/exp/services/captivecore/README.md +++ /dev/null @@ -1,97 +0,0 @@ -# captivecore - -The Captive Stellar-Core Server allows you to run a dedicated Stellar-Core instance -for the purpose of ingestion. The server must be bundled with a Stellar Core binary. - -If you run Horizon with Captive Stellar-Core ingestion enabled Horizon will spawn a Stellar-Core -subprocess. Horizon's ingestion system will then stream ledgers from the subprocess via -a filesystem pipe. The disadvantage of running both Horizon and the Stellar-Core subprocess -on the same machine is it requires detailed per-process monitoring to be able to attribute -potential issues (like memory leaks) to a specific service. - -Now you can run Horizon and pair it with a remote Captive Stellar-Core instance. The -Captive Stellar-Core Server can run on a separate machine from Horizon. The server -will manage Stellar-Core as a subprocess and provide an HTTP API which Horizon -can use remotely to stream ledgers for the purpose of ingestion. - -Note that, currently, a single Captive Stellar-Core Server cannot be shared by -multiple Horizon instances. - -## API - -### `GET /latest-sequence` - -Fetches the latest ledger sequence available on the captive core instance. - -Response: - -```json -{ - "sequence": 12345 -} -``` - - -### `GET /ledger/` - -Fetches the ledger with the given sequence number from the captive core instance. - -Response: - - -```json -{ - "present": true, - "ledger": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" -} -``` - -### `POST /prepare-range` - -Preloads the given range of ledgers in the captive core instance. - -Bounded request: -```json -{ - "from": 123, - "to": 150, - "bounded": true -} -``` - -Unbounded request: -```json -{ - "from": 123, - "bounded": false -} -``` - -Response: -```json -{ - "ledgerRange": {"from": 123, "bounded": false}, - "startTime": "2020-08-31T13:29:09Z", - "ready": true, - "readyDuration": 1000 -} -``` - -## Usage - -``` -$ captivecore --help -Run the Captive Stellar-Core Server - -Usage: - captivecore [flags] - -Flags: - --db-url Horizon Postgres URL (optional) used to lookup the ledger hash for sequence numbers - --stellar-core-binary-path Path to stellar core binary - --stellar-core-config-path Path to stellar core config file - --history-archive-urls Comma-separated list of stellar history archives to connect with - --log-level Minimum log severity (debug, info, warn, error) to log (default info) - --network-passphrase string Network passphrase of the Stellar network transactions should be signed for (NETWORK_PASSPHRASE) (default "Test SDF Network ; September 2015") - --port int Port to listen and serve on (PORT) (default 8000) -``` \ No newline at end of file diff --git a/exp/services/captivecore/internal/api.go b/exp/services/captivecore/internal/api.go deleted file mode 100644 index b39f7c0854..0000000000 --- a/exp/services/captivecore/internal/api.go +++ /dev/null @@ -1,186 +0,0 @@ -package internal - -import ( - "context" - "sync" - "time" - - "github.com/stellar/go/ingest/ledgerbackend" - "github.com/stellar/go/support/errors" - "github.com/stellar/go/support/log" -) - -var ( - // ErrMissingPrepareRange is returned when attempting an operation without satisfying - // its PrepareRange dependency - ErrMissingPrepareRange = errors.New("PrepareRange must be called before any other operations") - // ErrMissingPrepareRange is returned when attempting an operation before PrepareRange has finished - // running - ErrPrepareRangeNotReady = errors.New("PrepareRange operation is not yet complete") -) - -type rangeRequest struct { - ledgerRange ledgerbackend.Range - startTime time.Time - readyDuration int - valid bool - ready bool - sync.Mutex -} - -// CaptiveCoreAPI manages a shared captive core subprocess and exposes an API for -// executing commands remotely on the captive core instance. -type CaptiveCoreAPI struct { - ctx context.Context - cancel context.CancelFunc - core ledgerbackend.LedgerBackend - activeRequest *rangeRequest - wg *sync.WaitGroup - log *log.Entry -} - -// NewCaptiveCoreAPI constructs a new CaptiveCoreAPI instance. -func NewCaptiveCoreAPI(core ledgerbackend.LedgerBackend, log *log.Entry) CaptiveCoreAPI { - ctx, cancel := context.WithCancel(context.Background()) - return CaptiveCoreAPI{ - ctx: ctx, - cancel: cancel, - core: core, - log: log, - activeRequest: &rangeRequest{}, - wg: &sync.WaitGroup{}, - } -} - -// Shutdown disables the PrepareRange endpoint and closes -// the captive core process. -func (c *CaptiveCoreAPI) Shutdown() { - c.activeRequest.Lock() - c.cancel() - c.activeRequest.Unlock() - - c.wg.Wait() - c.core.Close() -} - -func (c *CaptiveCoreAPI) isShutdown() bool { - return c.ctx.Err() != nil -} - -func (c *CaptiveCoreAPI) startPrepareRange(ctx context.Context, ledgerRange ledgerbackend.Range) { - defer c.wg.Done() - - err := c.core.PrepareRange(ctx, ledgerRange) - - c.activeRequest.Lock() - defer c.activeRequest.Unlock() - if c.isShutdown() { - return - } - - if !c.activeRequest.valid || c.activeRequest.ledgerRange != ledgerRange { - c.log.WithFields(log.F{ - "requestedRange": c.activeRequest.ledgerRange, - "valid": c.activeRequest.valid, - "preparedRange": ledgerRange, - }).Warn("Prepared range does not match requested range") - return - } - - if c.activeRequest.ready { - c.log.WithField("preparedRange", ledgerRange).Warn("Prepared range already completed") - return - } - - if err != nil { - c.log.WithError(err).WithField("preparedRange", ledgerRange).Warn("Could not prepare range") - c.activeRequest.valid = false - c.activeRequest.ready = false - return - } - - c.activeRequest.ready = true - c.activeRequest.readyDuration = int(time.Since(c.activeRequest.startTime).Seconds()) -} - -// PrepareRange executes the PrepareRange operation on the captive core instance. -func (c *CaptiveCoreAPI) PrepareRange(ctx context.Context, ledgerRange ledgerbackend.Range) (ledgerbackend.PrepareRangeResponse, error) { - c.activeRequest.Lock() - defer c.activeRequest.Unlock() - if c.isShutdown() { - return ledgerbackend.PrepareRangeResponse{}, errors.New("Cannot prepare range when shut down") - } - - if !c.activeRequest.valid || !c.activeRequest.ledgerRange.Contains(ledgerRange) { - if c.activeRequest.valid { - c.log.WithFields(log.F{ - "activeRange": c.activeRequest.ledgerRange, - "requestedRange": ledgerRange, - }).Info("Requested range differs from previously requested range") - } - - c.activeRequest.ledgerRange = ledgerRange - c.activeRequest.startTime = time.Now() - c.activeRequest.ready = false - c.activeRequest.valid = true - - c.wg.Add(1) - go c.startPrepareRange(c.ctx, ledgerRange) - - return ledgerbackend.PrepareRangeResponse{ - LedgerRange: ledgerRange, - StartTime: c.activeRequest.startTime, - Ready: false, - ReadyDuration: 0, - }, nil - } - - return ledgerbackend.PrepareRangeResponse{ - LedgerRange: c.activeRequest.ledgerRange, - StartTime: c.activeRequest.startTime, - Ready: c.activeRequest.ready, - ReadyDuration: c.activeRequest.readyDuration, - }, nil -} - -// GetLatestLedgerSequence determines the latest ledger sequence available on the captive core instance. -func (c *CaptiveCoreAPI) GetLatestLedgerSequence(ctx context.Context) (ledgerbackend.LatestLedgerSequenceResponse, error) { - c.activeRequest.Lock() - defer c.activeRequest.Unlock() - - if !c.activeRequest.valid { - return ledgerbackend.LatestLedgerSequenceResponse{}, ErrMissingPrepareRange - } - if !c.activeRequest.ready { - return ledgerbackend.LatestLedgerSequenceResponse{}, ErrPrepareRangeNotReady - } - - seq, err := c.core.GetLatestLedgerSequence(ctx) - if err != nil { - c.activeRequest.valid = false - } - return ledgerbackend.LatestLedgerSequenceResponse{Sequence: seq}, err -} - -// GetLedger fetches the ledger with the given sequence number from the captive core instance. -func (c *CaptiveCoreAPI) GetLedger(ctx context.Context, sequence uint32) (ledgerbackend.LedgerResponse, error) { - c.activeRequest.Lock() - defer c.activeRequest.Unlock() - - if !c.activeRequest.valid { - return ledgerbackend.LedgerResponse{}, ErrMissingPrepareRange - } - if !c.activeRequest.ready { - return ledgerbackend.LedgerResponse{}, ErrPrepareRangeNotReady - } - - ledger, err := c.core.GetLedger(ctx, sequence) - if err != nil { - c.activeRequest.valid = false - } - // TODO: We are always true here now, so this changes the semantics of this - // call a bit. We need to change the client to long-poll this endpoint. - return ledgerbackend.LedgerResponse{ - Ledger: ledgerbackend.Base64Ledger(ledger), - }, err -} diff --git a/exp/services/captivecore/internal/api_test.go b/exp/services/captivecore/internal/api_test.go deleted file mode 100644 index b9c96bf8b4..0000000000 --- a/exp/services/captivecore/internal/api_test.go +++ /dev/null @@ -1,244 +0,0 @@ -package internal - -import ( - "context" - "fmt" - "testing" - "time" - - "github.com/stretchr/testify/mock" - "github.com/stretchr/testify/suite" - - "github.com/stellar/go/ingest/ledgerbackend" - "github.com/stellar/go/support/log" - "github.com/stellar/go/xdr" -) - -func TestAPITestSuite(t *testing.T) { - suite.Run(t, new(APITestSuite)) -} - -type APITestSuite struct { - suite.Suite - ctx context.Context - ledgerBackend *ledgerbackend.MockDatabaseBackend - api CaptiveCoreAPI -} - -func (s *APITestSuite) SetupTest() { - s.ctx = context.Background() - s.ledgerBackend = &ledgerbackend.MockDatabaseBackend{} - s.api = NewCaptiveCoreAPI(s.ledgerBackend, log.New()) -} - -func (s *APITestSuite) TearDownTest() { - s.ledgerBackend.AssertExpectations(s.T()) -} - -func (s *APITestSuite) TestLatestSeqActiveRequestInvalid() { - _, err := s.api.GetLatestLedgerSequence(s.ctx) - s.Assert().Equal(err, ErrMissingPrepareRange) -} - -func (s *APITestSuite) TestGetLedgerActiveRequestInvalid() { - _, err := s.api.GetLedger(s.ctx, 64) - s.Assert().Equal(err, ErrMissingPrepareRange) -} - -func (s *APITestSuite) runBeforeReady(prepareRangeErr error, f func()) { - waitChan := make(chan time.Time) - ledgerRange := ledgerbackend.UnboundedRange(63) - s.ledgerBackend.On("PrepareRange", mock.Anything, ledgerRange). - WaitUntil(waitChan). - Return(prepareRangeErr).Once() - - response, err := s.api.PrepareRange(s.ctx, ledgerRange) - s.Assert().NoError(err) - s.Assert().False(response.Ready) - s.Assert().Equal(response.LedgerRange, ledgerRange) - - f() - - close(waitChan) - s.api.wg.Wait() -} - -func (s *APITestSuite) TestLatestSeqActiveRequestNotReady() { - s.runBeforeReady(nil, func() { - _, err := s.api.GetLatestLedgerSequence(s.ctx) - s.Assert().Equal(err, ErrPrepareRangeNotReady) - }) -} - -func (s *APITestSuite) TestGetLedgerNotReady() { - s.runBeforeReady(nil, func() { - _, err := s.api.GetLedger(s.ctx, 64) - s.Assert().Equal(err, ErrPrepareRangeNotReady) - }) -} - -func (s *APITestSuite) waitUntilReady(ledgerRange ledgerbackend.Range) { - s.ledgerBackend.On("PrepareRange", mock.Anything, ledgerRange). - Return(nil).Once() - - response, err := s.api.PrepareRange(s.ctx, ledgerRange) - s.Assert().NoError(err) - s.Assert().False(response.Ready) - s.Assert().Equal(response.LedgerRange, ledgerRange) - - s.api.wg.Wait() -} - -func (s *APITestSuite) TestLatestSeqError() { - s.waitUntilReady(ledgerbackend.UnboundedRange(63)) - - expectedErr := fmt.Errorf("test error") - s.ledgerBackend.On("GetLatestLedgerSequence", s.ctx).Return(uint32(0), expectedErr).Once() - - _, err := s.api.GetLatestLedgerSequence(s.ctx) - s.Assert().Equal(err, expectedErr) -} - -func (s *APITestSuite) TestGetLedgerError() { - s.waitUntilReady(ledgerbackend.UnboundedRange(63)) - - expectedErr := fmt.Errorf("test error") - s.ledgerBackend.On("GetLedger", s.ctx, uint32(64)). - Return(xdr.LedgerCloseMeta{}, expectedErr).Once() - - _, err := s.api.GetLedger(s.ctx, 64) - s.Assert().Equal(err, expectedErr) -} - -func (s *APITestSuite) TestLatestSeqSucceeds() { - s.waitUntilReady(ledgerbackend.UnboundedRange(63)) - - expectedSeq := uint32(100) - s.ledgerBackend.On("GetLatestLedgerSequence", s.ctx).Return(expectedSeq, nil).Once() - seq, err := s.api.GetLatestLedgerSequence(s.ctx) - s.Assert().NoError(err) - s.Assert().Equal(seq, ledgerbackend.LatestLedgerSequenceResponse{Sequence: expectedSeq}) -} - -func (s *APITestSuite) TestGetLedgerSucceeds() { - s.waitUntilReady(ledgerbackend.UnboundedRange(63)) - - expectedLedger := xdr.LedgerCloseMeta{ - V0: &xdr.LedgerCloseMetaV0{ - LedgerHeader: xdr.LedgerHeaderHistoryEntry{ - Header: xdr.LedgerHeader{ - LedgerSeq: 64, - }, - }, - }, - } - s.ledgerBackend.On("GetLedger", s.ctx, uint32(64)). - Return(expectedLedger, nil).Once() - seq, err := s.api.GetLedger(s.ctx, 64) - - s.Assert().NoError(err) - s.Assert().Equal(seq, ledgerbackend.LedgerResponse{ - Ledger: ledgerbackend.Base64Ledger(expectedLedger), - }) -} - -func (s *APITestSuite) TestShutDownBeforePrepareRange() { - s.ledgerBackend.On("Close").Return(nil).Once() - s.api.Shutdown() - _, err := s.api.PrepareRange(s.ctx, ledgerbackend.UnboundedRange(63)) - s.Assert().EqualError(err, "Cannot prepare range when shut down") -} - -func (s *APITestSuite) TestShutDownDuringPrepareRange() { - s.runBeforeReady(nil, func() { - s.api.cancel() - }) - - s.Assert().False(s.api.activeRequest.ready) -} - -func (s *APITestSuite) TestPrepareRangeInvalidActiveRequest() { - s.runBeforeReady(nil, func() { - s.Assert().True(s.api.activeRequest.valid) - s.api.activeRequest.valid = false - }) - s.Assert().False(s.api.activeRequest.ready) - - s.api.activeRequest = &rangeRequest{} - - s.runBeforeReady(fmt.Errorf("with error"), func() { - s.Assert().True(s.api.activeRequest.valid) - s.api.activeRequest.valid = false - }) - s.Assert().False(s.api.activeRequest.ready) -} - -func (s *APITestSuite) TestPrepareRangeDoesNotMatchActiveRequestRange() { - s.runBeforeReady(nil, func() { - s.Assert().Equal(ledgerbackend.UnboundedRange(63), s.api.activeRequest.ledgerRange) - s.api.activeRequest.ledgerRange = ledgerbackend.UnboundedRange(1000) - }) - s.Assert().False(s.api.activeRequest.ready) - s.Assert().Equal(ledgerbackend.UnboundedRange(1000), s.api.activeRequest.ledgerRange) - - s.api.activeRequest = &rangeRequest{} - - s.runBeforeReady(fmt.Errorf("with error"), func() { - s.Assert().Equal(ledgerbackend.UnboundedRange(63), s.api.activeRequest.ledgerRange) - s.api.activeRequest.ledgerRange = ledgerbackend.UnboundedRange(10) - }) - s.Assert().False(s.api.activeRequest.ready) - s.Assert().Equal(ledgerbackend.UnboundedRange(10), s.api.activeRequest.ledgerRange) -} - -func (s *APITestSuite) TestPrepareRangeActiveRequestReady() { - s.runBeforeReady(nil, func() { - s.api.activeRequest.ready = true - }) - s.Assert().True(s.api.activeRequest.ready) - s.Assert().True(s.api.activeRequest.valid) - s.Assert().Equal(0, s.api.activeRequest.readyDuration) - - s.api.activeRequest = &rangeRequest{} - - s.runBeforeReady(fmt.Errorf("with error"), func() { - s.api.activeRequest.ready = true - }) - s.Assert().True(s.api.activeRequest.ready) - s.Assert().True(s.api.activeRequest.valid) - s.Assert().Equal(0, s.api.activeRequest.readyDuration) -} - -func (s *APITestSuite) TestPrepareRangeError() { - s.runBeforeReady(fmt.Errorf("with error"), func() { - s.Assert().False(s.api.activeRequest.ready) - s.Assert().True(s.api.activeRequest.valid) - }) - s.Assert().False(s.api.activeRequest.ready) - s.Assert().False(s.api.activeRequest.valid) - - s.api.activeRequest = &rangeRequest{} -} - -func (s *APITestSuite) TestRangeAlreadyPrepared() { - superSetRange := ledgerbackend.UnboundedRange(63) - s.waitUntilReady(superSetRange) - - for _, ledgerRange := range []ledgerbackend.Range{ - superSetRange, - ledgerbackend.UnboundedRange(100), - ledgerbackend.BoundedRange(63, 70), - } { - response, err := s.api.PrepareRange(s.ctx, ledgerRange) - s.Assert().NoError(err) - s.Assert().True(response.Ready) - s.Assert().Equal(superSetRange, response.LedgerRange) - } -} - -func (s *APITestSuite) TestNewPrepareRange() { - s.waitUntilReady(ledgerbackend.UnboundedRange(63)) - s.waitUntilReady(ledgerbackend.UnboundedRange(50)) - s.waitUntilReady(ledgerbackend.BoundedRange(45, 50)) - s.waitUntilReady(ledgerbackend.UnboundedRange(46)) -} diff --git a/exp/services/captivecore/internal/server.go b/exp/services/captivecore/internal/server.go deleted file mode 100644 index 127444611f..0000000000 --- a/exp/services/captivecore/internal/server.go +++ /dev/null @@ -1,89 +0,0 @@ -package internal - -import ( - "context" - "encoding/json" - "net/http" - "time" - - "github.com/stellar/go/ingest/ledgerbackend" - supporthttp "github.com/stellar/go/support/http" - "github.com/stellar/go/support/http/httpdecode" - supportlog "github.com/stellar/go/support/log" -) - -func serializeResponse( - logger *supportlog.Entry, - w http.ResponseWriter, - r *http.Request, - response interface{}, - err error, -) { - if err != nil { - w.WriteHeader(http.StatusInternalServerError) - w.Write([]byte(err.Error())) - return - } - - w.Header().Set("Content-Type", "application/json; charset=utf-8") - if err := json.NewEncoder(w).Encode(response); err != nil { - logger.WithContext(r.Context()).WithError(err).Warn("could not serialize response") - w.WriteHeader(http.StatusInternalServerError) - } -} - -type GetLedgerRequest struct { - Sequence uint32 `path:"sequence"` -} - -// Handler returns an HTTP handler which exposes captive core operations via HTTP endpoints. -func Handler(api CaptiveCoreAPI) http.Handler { - mux := supporthttp.NewMux(api.log) - - mux.Get("/latest-sequence", func(w http.ResponseWriter, r *http.Request) { - response, err := api.GetLatestLedgerSequence(r.Context()) - serializeResponse(api.log, w, r, response, err) - }) - - mux.Get("/ledger/{sequence}", func(w http.ResponseWriter, r *http.Request) { - req := GetLedgerRequest{} - if err := httpdecode.Decode(r, &req); err != nil { - w.WriteHeader(http.StatusBadRequest) - w.Write([]byte(err.Error())) - return - } - - // must be shorter than the RemoteCaptiveCore http client timeout. - ctx, cancel := context.WithTimeout(r.Context(), 5*time.Second) - defer cancel() // release timer - - var response ledgerbackend.LedgerResponse - var err error - done := make(chan struct{}) - go func() { - response, err = api.GetLedger(ctx, req.Sequence) - close(done) - }() - - select { - case <-ctx.Done(): - w.WriteHeader(http.StatusRequestTimeout) - case <-done: - serializeResponse(api.log, w, r, response, err) - } - }) - - mux.Post("/prepare-range", func(w http.ResponseWriter, r *http.Request) { - ledgerRange := ledgerbackend.Range{} - if err := json.NewDecoder(r.Body).Decode(&ledgerRange); err != nil { - w.WriteHeader(http.StatusBadRequest) - w.Write([]byte(err.Error())) - return - } - - response, err := api.PrepareRange(r.Context(), ledgerRange) - serializeResponse(api.log, w, r, response, err) - }) - - return mux -} diff --git a/exp/services/captivecore/internal/server_test.go b/exp/services/captivecore/internal/server_test.go deleted file mode 100644 index 86ad989191..0000000000 --- a/exp/services/captivecore/internal/server_test.go +++ /dev/null @@ -1,182 +0,0 @@ -package internal - -import ( - "context" - "fmt" - "io/ioutil" - "net/http" - "net/http/httptest" - "testing" - "time" - - "github.com/stretchr/testify/mock" - "github.com/stretchr/testify/suite" - - "github.com/stellar/go/ingest/ledgerbackend" - "github.com/stellar/go/support/log" - "github.com/stellar/go/xdr" -) - -func TestServerTestSuite(t *testing.T) { - suite.Run(t, new(ServerTestSuite)) -} - -type ServerTestSuite struct { - suite.Suite - ctx context.Context - ledgerBackend *ledgerbackend.MockDatabaseBackend - api CaptiveCoreAPI - handler http.Handler - server *httptest.Server - client ledgerbackend.RemoteCaptiveStellarCore -} - -func (s *ServerTestSuite) SetupTest() { - s.ctx = context.Background() - s.ledgerBackend = &ledgerbackend.MockDatabaseBackend{} - s.api = NewCaptiveCoreAPI(s.ledgerBackend, log.New()) - s.handler = Handler(s.api) - s.server = httptest.NewServer(s.handler) - var err error - s.client, err = ledgerbackend.NewRemoteCaptive( - s.server.URL, - ledgerbackend.PrepareRangePollInterval(time.Millisecond), - ) - s.Assert().NoError(err) -} - -func (s *ServerTestSuite) TearDownTest() { - s.ledgerBackend.AssertExpectations(s.T()) - s.server.Close() - s.client.Close() -} - -func (s *ServerTestSuite) TestLatestSequence() { - s.api.activeRequest.valid = true - s.api.activeRequest.ready = true - - expectedSeq := uint32(100) - s.ledgerBackend.On("GetLatestLedgerSequence", mock.Anything).Return(expectedSeq, nil).Once() - - seq, err := s.client.GetLatestLedgerSequence(s.ctx) - s.Assert().NoError(err) - s.Assert().Equal(expectedSeq, seq) -} - -func (s *ServerTestSuite) TestLatestSequenceError() { - s.api.activeRequest.valid = true - s.api.activeRequest.ready = true - - s.ledgerBackend.On("GetLatestLedgerSequence", mock.Anything).Return(uint32(100), fmt.Errorf("test error")).Once() - - _, err := s.client.GetLatestLedgerSequence(s.ctx) - s.Assert().EqualError(err, "test error") -} - -func (s *ServerTestSuite) TestPrepareBoundedRange() { - ledgerRange := ledgerbackend.BoundedRange(10, 30) - s.ledgerBackend.On("PrepareRange", mock.Anything, ledgerRange). - Return(nil).Once() - - s.Assert().NoError(s.client.PrepareRange(s.ctx, ledgerRange)) - s.Assert().True(s.api.activeRequest.ready) - - prepared, err := s.client.IsPrepared(s.ctx, ledgerRange) - s.Assert().NoError(err) - s.Assert().True(prepared) -} - -func (s *ServerTestSuite) TestPrepareUnboundedRange() { - ledgerRange := ledgerbackend.UnboundedRange(100) - s.ledgerBackend.On("PrepareRange", mock.Anything, ledgerRange). - Return(nil).Once() - - s.Assert().NoError(s.client.PrepareRange(s.ctx, ledgerRange)) - s.Assert().True(s.api.activeRequest.ready) - - prepared, err := s.client.IsPrepared(s.ctx, ledgerRange) - s.Assert().NoError(err) - s.Assert().True(prepared) -} - -func (s *ServerTestSuite) TestPrepareError() { - s.ledgerBackend.On("Close").Return(nil).Once() - s.api.Shutdown() - - s.Assert().EqualError( - s.client.PrepareRange(s.ctx, ledgerbackend.UnboundedRange(100)), - "Cannot prepare range when shut down", - ) -} - -func (s *ServerTestSuite) TestGetLedgerInvalidSequence() { - req := httptest.NewRequest("GET", "/ledger/abcdef", nil) - req = req.WithContext(s.ctx) - w := httptest.NewRecorder() - - s.handler.ServeHTTP(w, req) - - resp := w.Result() - body, err := ioutil.ReadAll(resp.Body) - s.Assert().NoError(err) - - s.Assert().Equal(http.StatusBadRequest, resp.StatusCode) - s.Assert().Equal("path params could not be parsed: schema: error converting value for \"sequence\"", string(body)) -} - -func (s *ServerTestSuite) TestGetLedgerError() { - s.api.activeRequest.valid = true - s.api.activeRequest.ready = true - - expectedErr := fmt.Errorf("test error") - s.ledgerBackend.On("GetLedger", mock.Anything, uint32(64)). - Return(xdr.LedgerCloseMeta{}, expectedErr).Once() - - _, err := s.client.GetLedger(s.ctx, 64) - s.Assert().EqualError(err, "test error") -} - -func (s *ServerTestSuite) TestGetLedgerSucceeds() { - s.api.activeRequest.valid = true - s.api.activeRequest.ready = true - - expectedLedger := xdr.LedgerCloseMeta{ - V0: &xdr.LedgerCloseMetaV0{ - LedgerHeader: xdr.LedgerHeaderHistoryEntry{ - Header: xdr.LedgerHeader{ - LedgerSeq: 64, - }, - }, - }, - } - s.ledgerBackend.On("GetLedger", mock.Anything, uint32(64)). - Return(expectedLedger, nil).Once() - - ledger, err := s.client.GetLedger(s.ctx, 64) - s.Assert().NoError(err) - s.Assert().Equal(expectedLedger, ledger) -} - -func (s *ServerTestSuite) TestGetLedgerTakesAWhile() { - s.api.activeRequest.valid = true - s.api.activeRequest.ready = true - - expectedLedger := xdr.LedgerCloseMeta{ - V0: &xdr.LedgerCloseMetaV0{ - LedgerHeader: xdr.LedgerHeaderHistoryEntry{ - Header: xdr.LedgerHeader{ - LedgerSeq: 64, - }, - }, - }, - } - s.ledgerBackend.On("GetLedger", mock.Anything, uint32(64)). - Run(func(mock.Arguments) { time.Sleep(6 * time.Second) }). - Return(xdr.LedgerCloseMeta{}, nil).Once() - s.ledgerBackend.On("GetLedger", mock.Anything, uint32(64)). - Return(expectedLedger, nil).Once() - - ledger, err := s.client.GetLedger(s.ctx, 64) - s.Assert().NoError(err) - s.Assert().Equal(expectedLedger, ledger) -} diff --git a/exp/services/captivecore/main.go b/exp/services/captivecore/main.go deleted file mode 100644 index 69d7da0b5f..0000000000 --- a/exp/services/captivecore/main.go +++ /dev/null @@ -1,185 +0,0 @@ -package main - -import ( - "fmt" - "go/types" - "strings" - - "github.com/sirupsen/logrus" - "github.com/spf13/cobra" - "github.com/spf13/viper" - - "github.com/stellar/go/exp/services/captivecore/internal" - "github.com/stellar/go/ingest/ledgerbackend" - "github.com/stellar/go/network" - "github.com/stellar/go/support/config" - "github.com/stellar/go/support/db" - supporthttp "github.com/stellar/go/support/http" - supportlog "github.com/stellar/go/support/log" -) - -func main() { - var port int - var networkPassphrase, binaryPath, configPath, dbURL string - var captiveCoreTomlParams ledgerbackend.CaptiveCoreTomlParams - var historyArchiveURLs []string - var checkpointFrequency uint32 - var logLevel logrus.Level - logger := supportlog.New() - - configOpts := config.ConfigOptions{ - { - Name: "port", - Usage: "Port to listen and serve on", - OptType: types.Int, - ConfigKey: &port, - FlagDefault: 8000, - Required: true, - }, - { - Name: "network-passphrase", - Usage: "Network passphrase of the Stellar network transactions should be signed for", - OptType: types.String, - ConfigKey: &networkPassphrase, - FlagDefault: network.TestNetworkPassphrase, - Required: true, - }, - &config.ConfigOption{ - Name: "stellar-core-binary-path", - OptType: types.String, - FlagDefault: "", - Required: true, - Usage: "path to stellar core binary", - ConfigKey: &binaryPath, - }, - &config.ConfigOption{ - Name: "captive-core-config-path", - OptType: types.String, - FlagDefault: "", - Required: true, - Usage: "path to additional configuration for the Stellar Core configuration file used by captive core. It must, at least, include enough details to define a quorum set", - ConfigKey: &configPath, - }, - &config.ConfigOption{ - Name: "history-archive-urls", - ConfigKey: &historyArchiveURLs, - OptType: types.String, - Required: true, - FlagDefault: "", - CustomSetValue: func(co *config.ConfigOption) error { - stringOfUrls := viper.GetString(co.Name) - urlStrings := strings.Split(stringOfUrls, ",") - - *(co.ConfigKey.(*[]string)) = urlStrings - return nil - }, - Usage: "comma-separated list of stellar history archives to connect with", - }, - &config.ConfigOption{ - Name: "log-level", - ConfigKey: &logLevel, - OptType: types.String, - FlagDefault: "info", - CustomSetValue: func(co *config.ConfigOption) error { - ll, err := logrus.ParseLevel(viper.GetString(co.Name)) - if err != nil { - return fmt.Errorf("Could not parse log-level: %v", viper.GetString(co.Name)) - } - *(co.ConfigKey.(*logrus.Level)) = ll - return nil - }, - Usage: "minimum log severity (debug, info, warn, error) to log", - }, - &config.ConfigOption{ - Name: "db-url", - EnvVar: "DATABASE_URL", - ConfigKey: &dbURL, - OptType: types.String, - Required: false, - Usage: "horizon postgres database to connect with", - }, - &config.ConfigOption{ - Name: "stellar-captive-core-http-port", - ConfigKey: &captiveCoreTomlParams.HTTPPort, - OptType: types.Uint, - CustomSetValue: config.SetOptionalUint, - Required: false, - FlagDefault: uint(11626), - Usage: "HTTP port for Captive Core to listen on (0 disables the HTTP server)", - }, - &config.ConfigOption{ - Name: "checkpoint-frequency", - ConfigKey: &checkpointFrequency, - OptType: types.Uint32, - FlagDefault: uint32(64), - Required: false, - Usage: "establishes how many ledgers exist between checkpoints, do NOT change this unless you really know what you are doing", - }, - } - cmd := &cobra.Command{ - Use: "captivecore", - Short: "Run the remote captive core server", - Run: func(_ *cobra.Command, _ []string) { - configOpts.Require() - configOpts.SetValues() - logger.SetLevel(logLevel) - - captiveCoreTomlParams.HistoryArchiveURLs = historyArchiveURLs - captiveCoreTomlParams.NetworkPassphrase = networkPassphrase - captiveCoreTomlParams.Strict = true - captiveCoreToml, err := ledgerbackend.NewCaptiveCoreTomlFromFile(configPath, captiveCoreTomlParams) - if err != nil { - logger.WithError(err).Fatal("Invalid captive core toml") - } - - captiveConfig := ledgerbackend.CaptiveCoreConfig{ - BinaryPath: binaryPath, - NetworkPassphrase: networkPassphrase, - HistoryArchiveURLs: historyArchiveURLs, - CheckpointFrequency: checkpointFrequency, - Log: logger.WithField("subservice", "stellar-core"), - Toml: captiveCoreToml, - UserAgent: "captivecore", - } - - var dbConn *db.Session - if len(dbURL) > 0 { - dbConn, err = db.Open("postgres", dbURL) - if err != nil { - logger.WithError(err).Fatal("Could not create db connection instance") - } - captiveConfig.LedgerHashStore = ledgerbackend.NewHorizonDBLedgerHashStore(dbConn) - } - - core, err := ledgerbackend.NewCaptive(captiveConfig) - if err != nil { - logger.WithError(err).Fatal("Could not create captive core instance") - } - api := internal.NewCaptiveCoreAPI(core, logger.WithField("subservice", "api")) - - supporthttp.Run(supporthttp.Config{ - ListenAddr: fmt.Sprintf(":%d", port), - Handler: internal.Handler(api), - OnStarting: func() { - logger.Infof("Starting Captive Core server on %v", port) - }, - OnStopping: func() { - // TODO: Check this aborts in-progress requests instead of letting - // them finish, to preserve existing behaviour. - api.Shutdown() - if dbConn != nil { - dbConn.Close() - } - }, - }) - }, - } - - if err := configOpts.Init(cmd); err != nil { - logger.WithError(err).Fatal("could not parse config options") - } - - if err := cmd.Execute(); err != nil { - logger.WithError(err).Fatal("could not run") - } -} diff --git a/exp/services/market-tracker/calc_test.go b/exp/services/market-tracker/calc_test.go index 590336af9f..d71d0626f4 100644 --- a/exp/services/market-tracker/calc_test.go +++ b/exp/services/market-tracker/calc_test.go @@ -82,7 +82,7 @@ func TestCalcSpread(t *testing.T) { func TestCalcSpreadPctAtDepth(t *testing.T) { bids := []usdOrder{ - usdOrder{ + { xlmAmount: 100.0, usdAmount: 10.0, usdPrice: 10.0, @@ -134,17 +134,17 @@ func TestCalcBestOrderAtDepth(t *testing.T) { func TestCalcSlippageAtDepth(t *testing.T) { bids := []usdOrder{ - usdOrder{ + { xlmAmount: 1., usdAmount: 30., usdPrice: 30., }, - usdOrder{ + { xlmAmount: 1., usdAmount: 25., usdPrice: 25., }, - usdOrder{ + { xlmAmount: 1., usdAmount: 50., usdPrice: 20., @@ -152,17 +152,17 @@ func TestCalcSlippageAtDepth(t *testing.T) { } asks := []usdOrder{ - usdOrder{ + { xlmAmount: 5., usdAmount: 100., usdPrice: 20., }, - usdOrder{ + { xlmAmount: 4., usdAmount: 100., usdPrice: 25., }, - usdOrder{ + { xlmAmount: 4., usdAmount: 120., usdPrice: 30., @@ -209,17 +209,17 @@ func TestCalcAvgPriceAtDepth(t *testing.T) { func TestCalcFairValuePct(t *testing.T) { bids := []usdOrder{ - usdOrder{ + { xlmAmount: 1., usdAmount: 30., usdPrice: 30., }, - usdOrder{ + { xlmAmount: 1., usdAmount: 25., usdPrice: 25., }, - usdOrder{ + { xlmAmount: 1., usdAmount: 50., usdPrice: 20., @@ -227,17 +227,17 @@ func TestCalcFairValuePct(t *testing.T) { } asks := []usdOrder{ - usdOrder{ + { xlmAmount: 5., usdAmount: 100., usdPrice: 20., }, - usdOrder{ + { xlmAmount: 4., usdAmount: 100., usdPrice: 25., }, - usdOrder{ + { xlmAmount: 4., usdAmount: 120., usdPrice: 30., diff --git a/exp/services/market-tracker/go.mod b/exp/services/market-tracker/go.mod index e3551fbcf9..0b21049ae8 100644 --- a/exp/services/market-tracker/go.mod +++ b/exp/services/market-tracker/go.mod @@ -8,7 +8,7 @@ require ( github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88 // indirect github.com/klauspost/compress v1.15.1 // indirect github.com/matryer/try v0.0.0-20161228173917-9ac251b645a2 // indirect - github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829 + github.com/prometheus/client_golang v1.11.1 github.com/stellar/go v0.0.0-20211208234857-bf7909b45bd4 github.com/stretchr/testify v1.7.0 github.com/valyala/fasthttp v1.35.0 // indirect diff --git a/exp/services/market-tracker/go.sum b/exp/services/market-tracker/go.sum index feaeab95bc..a05c1261ef 100644 --- a/exp/services/market-tracker/go.sum +++ b/exp/services/market-tracker/go.sum @@ -49,14 +49,21 @@ github.com/adjust/goautoneg v0.0.0-20150426214442-d788f35a0315/go.mod h1:4U522Xv github.com/ajg/form v0.0.0-20160822230020-523a5da1a92f h1:zvClvFQwU++UpIUBGC8YmDlfhUrweEy1R1Fj1gu5iIM= github.com/ajg/form v0.0.0-20160822230020-523a5da1a92f/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= github.com/andybalholm/brotli v1.0.4 h1:V7DdXeJtZscaqfNuAdSRuRFzuiKlHSC/Zh3zl9qY3JY= github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= github.com/aws/aws-sdk-go v1.39.5/go.mod h1:585smgzpB/KqRA+K3y/NL/oYRqQvpNJYvLm+LY1U59Q= -github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973 h1:xJ4a3vCFaGF/jqvzLMYoU8P317H5OQ+Via4RmuPwCS0= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= +github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= +github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= +github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cheekybits/is v0.0.0-20150225183255-68e9c0620927 h1:SKI1/fuSdodxmNNyVBR8d7X/HuLnRpvvFO0AgyQk764= github.com/cheekybits/is v0.0.0-20150225183255-68e9c0620927/go.mod h1:h/aW8ynjgkuj+NQRlZcDbAbM1ORAbXjXX77sX7T289U= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= @@ -92,7 +99,11 @@ github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9 github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= +github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= +github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/gobuffalo/packr v1.12.1/go.mod h1:H2dZhQFqHeZwr/5A/uGQkBp7xYuMGuzXFeKhYdcz5No= @@ -146,6 +157,7 @@ github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-querystring v0.0.0-20160401233042-9235644dd9e5 h1:oERTZ1buOUYlpmKaqlO5fYmz8cZ1rYu5DieJzF4ZVmU= github.com/google/go-querystring v0.0.0-20160401233042-9235644dd9e5/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= @@ -192,25 +204,28 @@ github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfC github.com/jmoiron/sqlx v1.2.0/go.mod h1:1FEQNm3xlJgrMD+FBdI9+xvCksHtbpVBBw5dYhBSsks= github.com/joho/godotenv v1.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc= github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg= +github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= +github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= +github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88 h1:uC1QfSlInpQF+M0ao65imhwqKnz3Q2z/d8PWZRMQvDM= github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88/go.mod h1:3w7q1U84EfirKl04SVQ/s7nPm1ZPhiXd34z40TNz36k= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/klauspost/compress v0.0.0-20161106143436-e3b7981a12dd h1:vQ0EEfHpdFUtNRj1ri25MUq5jb3Vma+kKhLyjeUTVow= github.com/klauspost/compress v0.0.0-20161106143436-e3b7981a12dd/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= github.com/klauspost/compress v1.15.0/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= github.com/klauspost/compress v1.15.1 h1:y9FcTHGyrebwfP0ZZqFiaxTaiDnUrGkJkI+f583BL1A= github.com/klauspost/compress v1.15.1/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= -github.com/klauspost/cpuid v0.0.0-20160302075316-09cded8978dc h1:WW8B7p7QBnFlqRVv/k6ro/S8Z7tCnYjJHcQNScx9YVs= github.com/klauspost/cpuid v0.0.0-20160302075316-09cded8978dc/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= -github.com/klauspost/crc32 v0.0.0-20161016154125-cb6bfca970f6 h1:KAZ1BW2TCmT6PRihDPpocIy1QTtsAsrx6TneU/4+CMg= github.com/klauspost/crc32 v0.0.0-20161016154125-cb6bfca970f6/go.mod h1:+ZoRqAPRLkC4NPOvfYeR5KNOrY6TD+/sAC3HXPZgDYg= -github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/konsorten/go-windows-terminal-sequences v1.0.3 h1:CE8S1cTafDpPvMhIxNJKvHsGVBgn1xWYf1NbHQhywc8= +github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= @@ -235,9 +250,14 @@ github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0j github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/mapstructure v0.0.0-20150613213606-2caf8efc9366/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/moul/http2curl v0.0.0-20161031194548-4e24498b31db h1:eZgFHVkk9uOTaOQLC6tgjkzdp7Ays8eEVecBcfHZlJQ= github.com/moul/http2curl v0.0.0-20161031194548-4e24498b31db/go.mod h1:8UbvGypXm98wA/IqH45anm5Y2Z6ep6O31QGOAZ3H0fQ= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0 h1:WSHQ+IS43OoUrWtD1/bbclrwK8TTH5hzp+umCiuxHgs= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= @@ -253,17 +273,28 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= -github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829 h1:D+CiwcpGTW6pL6bv6KI3KbyEyCKyS+1JWS2h8PNDnGA= github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs= +github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= +github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= +github.com/prometheus/client_golang v1.11.1 h1:+4eQaD7vAZ6DsfsxB15hbE0odUjGI5ARs9yskGu1v4s= +github.com/prometheus/client_golang v1.11.1/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= -github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4 h1:gQz4mCbXsO+nc9n1hCxHcGA3Zx3Eo+UHZoInFGUIXNM= +github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/common v0.2.0 h1:kUZDBDTdBVBYBj5Tmh2NZLlF60mfjA27rM34b+cVwNU= +github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M= +github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= +github.com/prometheus/common v0.26.0 h1:iMAkS2TDoNWnKM+Kopnx/8tnEStIfpYA0ur0xQzzhMQ= +github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1 h1:/K3IL0Z1quvmJ7X0A1AwNEK7CRkVK3YwfOU/QAL4WGg= github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= +github.com/prometheus/procfs v0.6.0 h1:mxy4L2jP6qMonqmq+aTtOx1ifVWUgG/TAmntgbh3xv4= +github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rs/cors v0.0.0-20160617231935-a62a804a8a00/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/rs/xhandler v0.0.0-20160618193221-ed27b6fd6521/go.mod h1:RvLn4FgxWubrpZHtQLnOf6EwhN2hEMusxZOhcW9H3UQ= @@ -274,8 +305,10 @@ github.com/sergi/go-diff v0.0.0-20161205080420-83532ca1c1ca h1:oR/RycYTFTVXzND5r github.com/sergi/go-diff v0.0.0-20161205080420-83532ca1c1ca/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= -github.com/sirupsen/logrus v1.4.1 h1:GL2rEmy6nsikmW0r8opw9JIRScdMF5hA8cOYLH7In1k= github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= +github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/sirupsen/logrus v1.6.0 h1:UBcNElsrwanuuMsnGSlYmtmgbb23qDR5dG+6X6Oo89I= +github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v0.0.0-20190731233626-505e41936337 h1:WN9BUFbdyOsSH/XohnWpXOlq9NBD5sGAB2FciQMUEe8= @@ -304,7 +337,6 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/tyler-smith/go-bip39 v0.0.0-20180618194314-52158e4697b8/go.mod h1:sJ5fKU0s6JVwZjjcUEX2zFOnvq0ASQ2K9Zr6cf67kNs= github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= -github.com/valyala/fasthttp v0.0.0-20170109085056-0a7f0a797cd6 h1:s0IDmR1jFyWvOK7jVIuAsmHQaGkXUuTas8NXFUOwuAI= github.com/valyala/fasthttp v0.0.0-20170109085056-0a7f0a797cd6/go.mod h1:+g/po7GqyG5E+1CNgquiIxJnsXEi5vwFn5weFujbO78= github.com/valyala/fasthttp v1.35.0 h1:wwkR8mZn2NbigFsaw2Zj5r+xkmzjbrA/lyTmiSlal/Y= github.com/valyala/fasthttp v1.35.0/go.mod h1:t/G+3rLek+CyY9bnIE+YlMRddxVAAGjhxndDB4i4C0I= @@ -394,6 +426,7 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -422,8 +455,8 @@ golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLd golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 h1:CIJ76btIcR3eFI5EgSo6k1qKw9KJexJuRLI9G7Hp5wE= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20220225172249-27dd8689420f h1:oA4XRj0qtSt8Yo1Zms0CUlsT3KG69V2UGQWPBxujDmc= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -457,6 +490,7 @@ golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -465,6 +499,7 @@ golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -477,6 +512,8 @@ golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -484,6 +521,7 @@ golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210223095934-7937bea0104d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -493,12 +531,13 @@ golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c h1:F1jZWGFhYfh0Ci55sIpILtKKK8p3i2/krTr0H1rg74I= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9 h1:nhht2DYV/Sn3qOayu8lM+cU1ii9sTLUeBQwQQfUHtrs= golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= @@ -509,8 +548,8 @@ golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -685,8 +724,9 @@ google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/l google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= @@ -701,8 +741,11 @@ gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWD gopkg.in/tylerb/graceful.v1 v1.2.13/go.mod h1:yBhekWvR20ACXVObSSdD3u6S9DeSylanL2PAbAC/uJ8= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/exp/services/market-tracker/orders_test.go b/exp/services/market-tracker/orders_test.go index 22a13774df..00c363d6b3 100644 --- a/exp/services/market-tracker/orders_test.go +++ b/exp/services/market-tracker/orders_test.go @@ -7,7 +7,7 @@ import ( "github.com/stretchr/testify/assert" ) -var badAmtOrders = []hProtocol.PriceLevel{hProtocol.PriceLevel{ +var badAmtOrders = []hProtocol.PriceLevel{{ PriceR: hProtocol.Price{ N: 4, D: 2, diff --git a/exp/services/recoverysigner/docker/Dockerfile b/exp/services/recoverysigner/docker/Dockerfile index fff4aef3d2..8cd9a72ae6 100644 --- a/exp/services/recoverysigner/docker/Dockerfile +++ b/exp/services/recoverysigner/docker/Dockerfile @@ -1,11 +1,11 @@ -FROM golang:1.18 as build +FROM golang:1.20-bullseye as build ADD . /src/recoverysigner WORKDIR /src/recoverysigner RUN go build -o /bin/recoverysigner ./exp/services/recoverysigner -FROM ubuntu:20.04 +FROM ubuntu:22.04 RUN apt-get update && apt-get install -y --no-install-recommends ca-certificates COPY --from=build /bin/recoverysigner /app/ diff --git a/exp/services/recoverysigner/internal/db/dbmigrate/dbmigrate_generated.go b/exp/services/recoverysigner/internal/db/dbmigrate/dbmigrate_generated.go index 0b5322861f..0088292d53 100644 --- a/exp/services/recoverysigner/internal/db/dbmigrate/dbmigrate_generated.go +++ b/exp/services/recoverysigner/internal/db/dbmigrate/dbmigrate_generated.go @@ -341,13 +341,11 @@ var _bindata = map[string]func() (*asset, error){ // directory embedded in the file by go-bindata. // For example if you run go-bindata on data/... and data contains the // following hierarchy: -// -// data/ -// foo.txt -// img/ -// a.png -// b.png -// +// data/ +// foo.txt +// img/ +// a.png +// b.png // then AssetDir("data") would return []string{"foo.txt", "img"}, // AssetDir("data/img") would return []string{"a.png", "b.png"}, // AssetDir("foo.txt") and AssetDir("notexist") would return an error, and diff --git a/exp/services/recoverysigner/internal/db/dbtest/dbtest.go b/exp/services/recoverysigner/internal/db/dbtest/dbtest.go index 0e41f434cc..1d09be2e41 100644 --- a/exp/services/recoverysigner/internal/db/dbtest/dbtest.go +++ b/exp/services/recoverysigner/internal/db/dbtest/dbtest.go @@ -16,7 +16,7 @@ func OpenWithoutMigrations(t *testing.T) *dbtest.DB { // instead of SERIAL/BIGSERIAL, which are recommended against. dbVersion := db.Version() if dbVersion < 10 { - t.Skipf("Skipping test becuase Postgres v%d found, and Postgres v10+ required for this test.", dbVersion) + t.Skipf("Skipping test because Postgres v%d found, and Postgres v10+ required for this test.", dbVersion) } return db diff --git a/exp/services/recoverysigner/internal/serve/serve.go b/exp/services/recoverysigner/internal/serve/serve.go index 88a4200377..8b5b856bfe 100644 --- a/exp/services/recoverysigner/internal/serve/serve.go +++ b/exp/services/recoverysigner/internal/serve/serve.go @@ -145,12 +145,14 @@ func getHandlerDeps(opts Options) (handlerDeps, error) { } allowedSourceAccounts := []*keypair.FromAddress{} - for _, addressStr := range strings.Split(opts.AllowedSourceAccounts, ",") { - accountAddress, err := keypair.ParseAddress(addressStr) - if err != nil { - return handlerDeps{}, errors.Wrap(err, "parsing allowed source accounts") + if opts.AllowedSourceAccounts != "" { + for _, addressStr := range strings.Split(opts.AllowedSourceAccounts, ",") { + accountAddress, err := keypair.ParseAddress(addressStr) + if err != nil { + return handlerDeps{}, errors.Wrap(err, "parsing allowed source accounts") + } + allowedSourceAccounts = append(allowedSourceAccounts, accountAddress) } - allowedSourceAccounts = append(allowedSourceAccounts, accountAddress) } deps := handlerDeps{ diff --git a/exp/services/recoverysigner/internal/serve/serve_test.go b/exp/services/recoverysigner/internal/serve/serve_test.go new file mode 100644 index 0000000000..db40d80390 --- /dev/null +++ b/exp/services/recoverysigner/internal/serve/serve_test.go @@ -0,0 +1,35 @@ +package serve + +import ( + "encoding/json" + "testing" + + "github.com/stellar/go/keypair" + supportlog "github.com/stellar/go/support/log" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "gopkg.in/square/go-jose.v2" +) + +func TestGetHandlerDeps(t *testing.T) { + signingKey := "SBWLXUTJR2CGVPGCZDIGGLQDPX7ZGGBHBFXBJ555MNIQ2PZCCLM643Z3" + signingKeyFull := keypair.MustParseFull(signingKey) + + opts := Options{ + Logger: supportlog.DefaultLogger, + SigningKeys: signingKey, + SEP10JWKS: `{"keys":[{"kty":"EC","crv":"P-256","alg":"ES256","x":"i8chX_7Slm4VQ_Y6XBWVBnxIO5-XSWH1GJsXWNkal3E","y":"G22r0OgrcQnkfCAqsS6wvtHgR0SbfvXNJy6-jJfvc94"}]}`, + } + + sep10JWKS := jose.JSONWebKeySet{} + err := json.Unmarshal([]byte(opts.SEP10JWKS), &sep10JWKS) + require.NoError(t, err) + + got, err := getHandlerDeps(opts) + assert.NoError(t, err) + + assert.Equal(t, []*keypair.Full{signingKeyFull}, got.SigningKeys) + assert.Equal(t, []*keypair.FromAddress{signingKeyFull.FromAddress()}, got.SigningAddresses) + assert.Equal(t, sep10JWKS, got.SEP10JWKS) + assert.Equal(t, []*keypair.FromAddress{}, got.AllowedSourceAccounts) +} diff --git a/exp/services/soroban-rpc/README.md b/exp/services/soroban-rpc/README.md new file mode 100644 index 0000000000..1f3db8a56b --- /dev/null +++ b/exp/services/soroban-rpc/README.md @@ -0,0 +1,2 @@ +The soroban-rpc project was moved to the soroban-tools repository. +You can find it at https://github.com/stellar/soroban-tools/tree/main/cmd/soroban-rpc. diff --git a/exp/services/webauth/docker/Dockerfile b/exp/services/webauth/docker/Dockerfile index 1c0b5ec308..c6bc287d5b 100644 --- a/exp/services/webauth/docker/Dockerfile +++ b/exp/services/webauth/docker/Dockerfile @@ -1,11 +1,11 @@ -FROM golang:1.18 as build +FROM golang:1.20-bullseye as build ADD . /src/webauth WORKDIR /src/webauth RUN go build -o /bin/webauth ./exp/services/webauth -FROM ubuntu:20.04 +FROM ubuntu:22.04 RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends ca-certificates COPY --from=build /bin/webauth /app/ diff --git a/exp/services/webauth/internal/serve/challenge.go b/exp/services/webauth/internal/serve/challenge.go index a01458215d..dccfd06494 100644 --- a/exp/services/webauth/internal/serve/challenge.go +++ b/exp/services/webauth/internal/serve/challenge.go @@ -2,6 +2,7 @@ package serve import ( "net/http" + "strconv" "strings" "time" @@ -33,7 +34,9 @@ func (h challengeHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { queryValues := r.URL.Query() account := queryValues.Get("account") - if !strkey.IsValidEd25519PublicKey(account) { + isStellarAccount := strkey.IsValidEd25519PublicKey(account) + isMuxedAccount := strkey.IsValidMuxedAccountEd25519PublicKey(account) + if !isStellarAccount && !isMuxedAccount { badRequest.Render(w) return } @@ -57,6 +60,18 @@ func (h challengeHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { homeDomain = h.HomeDomains[0] } + var memo *txnbuild.MemoID + memoParam := queryValues.Get("memo") + if memoParam != "" { + memoInt, err := strconv.ParseUint(memoParam, 10, 64) + if err != nil { + badRequest.Render(w) + return + } + memoId := txnbuild.MemoID(memoInt) + memo = &memoId + } + tx, err := txnbuild.BuildChallengeTx( h.SigningKey.Seed(), account, @@ -64,10 +79,11 @@ func (h challengeHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { homeDomain, h.NetworkPassphrase, h.ChallengeExpiresIn, + memo, ) if err != nil { h.Logger.Ctx(ctx).WithStack(err).Error(err) - serverError.Render(w) + badRequest.Render(w) return } diff --git a/exp/services/webauth/internal/serve/challenge_test.go b/exp/services/webauth/internal/serve/challenge_test.go index 9391224763..cd5deb2451 100644 --- a/exp/services/webauth/internal/serve/challenge_test.go +++ b/exp/services/webauth/internal/serve/challenge_test.go @@ -11,7 +11,9 @@ import ( "github.com/stellar/go/keypair" "github.com/stellar/go/network" + "github.com/stellar/go/strkey" supportlog "github.com/stellar/go/support/log" + "github.com/stellar/go/txnbuild" "github.com/stellar/go/xdr" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -185,3 +187,107 @@ func TestChallenge_invalidHomeDomain(t *testing.T) { require.NoError(t, err) assert.JSONEq(t, `{"error":"The request was invalid in some way."}`, string(body)) } + +func TestChallengeWithMemo(t *testing.T) { + serverKey := keypair.MustRandom() + account := keypair.MustRandom() + + h := challengeHandler{ + Logger: supportlog.DefaultLogger, + NetworkPassphrase: network.TestNetworkPassphrase, + SigningKey: serverKey, + ChallengeExpiresIn: time.Minute, + Domain: "webauthdomain", + HomeDomains: []string{"testdomain"}, + } + + r := httptest.NewRequest("GET", "/?account="+account.Address()+"&memo=1", nil) + w := httptest.NewRecorder() + h.ServeHTTP(w, r) + resp := w.Result() + + require.Equal(t, http.StatusOK, resp.StatusCode) + assert.Equal(t, "application/json; charset=utf-8", resp.Header.Get("Content-Type")) + + res := struct { + Transaction string `json:"transaction"` + NetworkPassphrase string `json:"network_passphrase"` + }{} + err := json.NewDecoder(resp.Body).Decode(&res) + require.NoError(t, err) + + var tx xdr.TransactionEnvelope + err = xdr.SafeUnmarshalBase64(res.Transaction, &tx) + require.NoError(t, err) + + memo, err := txnbuild.MemoID(1).ToXDR() + require.NoError(t, err) + require.Equal(t, tx.Memo(), memo) +} + +func TestChallengeWithBadMemo(t *testing.T) { + serverKey := keypair.MustRandom() + account := keypair.MustRandom() + + h := challengeHandler{ + Logger: supportlog.DefaultLogger, + NetworkPassphrase: network.TestNetworkPassphrase, + SigningKey: serverKey, + ChallengeExpiresIn: time.Minute, + Domain: "webauthdomain", + HomeDomains: []string{"testdomain"}, + } + + r := httptest.NewRequest("GET", "/?account="+account.Address()+"&memo=test", nil) + w := httptest.NewRecorder() + h.ServeHTTP(w, r) + resp := w.Result() + + require.Equal(t, http.StatusBadRequest, resp.StatusCode) + assert.Equal(t, "application/json; charset=utf-8", resp.Header.Get("Content-Type")) + + body, err := ioutil.ReadAll(resp.Body) + require.NoError(t, err) + assert.JSONEq(t, `{"error":"The request was invalid in some way."}`, string(body)) +} + +func TestChallengeWithMuxedAccount(t *testing.T) { + serverKey := keypair.MustRandom() + account := keypair.MustRandom() + + muxedAccount := strkey.MuxedAccount{} + muxedAccount.SetAccountID(account.Address()) + muxedAccount.SetID(1) + muxedAccountAddress, err := muxedAccount.Address() + require.NoError(t, err) + + h := challengeHandler{ + Logger: supportlog.DefaultLogger, + NetworkPassphrase: network.TestNetworkPassphrase, + SigningKey: serverKey, + ChallengeExpiresIn: time.Minute, + Domain: "webauthdomain", + HomeDomains: []string{"testdomain"}, + } + + r := httptest.NewRequest("GET", "/?account="+muxedAccountAddress, nil) + w := httptest.NewRecorder() + h.ServeHTTP(w, r) + resp := w.Result() + + require.Equal(t, http.StatusOK, resp.StatusCode) + assert.Equal(t, "application/json; charset=utf-8", resp.Header.Get("Content-Type")) + + res := struct { + Transaction string `json:"transaction"` + NetworkPassphrase string `json:"network_passphrase"` + }{} + err = json.NewDecoder(resp.Body).Decode(&res) + require.NoError(t, err) + + var tx xdr.TransactionEnvelope + err = xdr.SafeUnmarshalBase64(res.Transaction, &tx) + require.NoError(t, err) + + require.Equal(t, tx.Operations()[0].SourceAccount.Address(), muxedAccountAddress) +} diff --git a/exp/services/webauth/internal/serve/token.go b/exp/services/webauth/internal/serve/token.go index 56db5f269f..8b8a722526 100644 --- a/exp/services/webauth/internal/serve/token.go +++ b/exp/services/webauth/internal/serve/token.go @@ -2,6 +2,7 @@ package serve import ( "net/http" + "strconv" "strings" "time" @@ -11,6 +12,7 @@ import ( supportlog "github.com/stellar/go/support/log" "github.com/stellar/go/support/render/httpjson" "github.com/stellar/go/txnbuild" + "github.com/stellar/go/xdr" "gopkg.in/square/go-jose.v2" "gopkg.in/square/go-jose.v2/jwt" ) @@ -52,9 +54,10 @@ func (h tokenHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { clientAccountID string signingAddress *keypair.FromAddress homeDomain string + memo *txnbuild.MemoID ) for _, s := range h.SigningAddresses { - tx, clientAccountID, homeDomain, err = txnbuild.ReadChallengeTx(req.Transaction, s.Address(), h.NetworkPassphrase, h.Domain, h.HomeDomains) + tx, clientAccountID, homeDomain, memo, err = txnbuild.ReadChallengeTx(req.Transaction, s.Address(), h.NetworkPassphrase, h.Domain, h.HomeDomains) if err == nil { signingAddress = s break @@ -80,10 +83,20 @@ func (h tokenHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { WithField("tx", hash). WithField("account", clientAccountID). WithField("serversigner", signingAddress.Address()). - WithField("homedomain", homeDomain) + WithField("homedomain", homeDomain). + WithField("memo", memo) l.Info("Start verifying challenge transaction.") + muxedAccount, err := xdr.AddressToMuxedAccount(clientAccountID) + if err != nil { + badRequest.Render(w) + return + } + if muxedAccount.Type == xdr.CryptoKeyTypeKeyTypeMuxedEd25519 { + clientAccountID = muxedAccount.ToAccountId().Address() + } + var clientAccountExists bool clientAccount, err := h.HorizonClient.AccountDetail(horizonclient.AccountRequest{AccountID: clientAccountID}) switch { @@ -140,10 +153,20 @@ func (h tokenHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { return } + var sub string + if muxedAccount.Type == xdr.CryptoKeyTypeKeyTypeEd25519 { + sub = clientAccountID + if memo != nil { + sub += ":" + strconv.FormatUint(uint64(*memo), 10) + } + } else { + sub = muxedAccount.Address() + } + issuedAt := time.Unix(tx.Timebounds().MinTime, 0) claims := jwt.Claims{ Issuer: h.JWTIssuer, - Subject: clientAccountID, + Subject: sub, IssuedAt: jwt.NewNumericDate(issuedAt), Expiry: jwt.NewNumericDate(issuedAt.Add(h.JWTExpiresIn)), } diff --git a/exp/services/webauth/internal/serve/token_test.go b/exp/services/webauth/internal/serve/token_test.go index 7aa41d4b78..1f120ed7c1 100644 --- a/exp/services/webauth/internal/serve/token_test.go +++ b/exp/services/webauth/internal/serve/token_test.go @@ -8,6 +8,7 @@ import ( "net/http" "net/http/httptest" "net/url" + "strconv" "strings" "testing" "time" @@ -18,6 +19,7 @@ import ( "github.com/stellar/go/keypair" "github.com/stellar/go/network" "github.com/stellar/go/protocols/horizon" + "github.com/stellar/go/strkey" supportlog "github.com/stellar/go/support/log" "github.com/stellar/go/support/render/problem" "github.com/stellar/go/txnbuild" @@ -46,6 +48,7 @@ func TestToken_formInputSuccess(t *testing.T) { homeDomain, network.TestNetworkPassphrase, time.Minute, + nil, ) require.NoError(t, err) @@ -146,6 +149,7 @@ func TestToken_formInputSuccess_jwtHeaderAndPayloadAreDeterministic(t *testing.T homeDomain, network.TestNetworkPassphrase, time.Minute, + nil, ) require.NoError(t, err) @@ -255,6 +259,7 @@ func TestToken_jsonInputSuccess(t *testing.T) { homeDomain, network.TestNetworkPassphrase, time.Minute, + nil, ) require.NoError(t, err) @@ -412,6 +417,7 @@ func TestToken_jsonInputValidRotatingServerSigners(t *testing.T) { homeDomain, network.TestNetworkPassphrase, time.Minute, + nil, ) require.NoError(t, err) @@ -497,6 +503,7 @@ func TestToken_jsonInputValidMultipleSigners(t *testing.T) { homeDomain, network.TestNetworkPassphrase, time.Minute, + nil, ) require.NoError(t, err) @@ -605,6 +612,7 @@ func TestToken_jsonInputNotEnoughWeight(t *testing.T) { homeDomain, network.TestNetworkPassphrase, time.Minute, + nil, ) require.NoError(t, err) @@ -691,6 +699,7 @@ func TestToken_jsonInputUnrecognizedSigner(t *testing.T) { homeDomain, network.TestNetworkPassphrase, time.Minute, + nil, ) require.NoError(t, err) @@ -777,6 +786,7 @@ func TestToken_jsonInputAccountNotExistSuccess(t *testing.T) { homeDomain, network.TestNetworkPassphrase, time.Minute, + nil, ) require.NoError(t, err) @@ -881,6 +891,7 @@ func TestToken_jsonInputAccountNotExistFail(t *testing.T) { homeDomain, network.TestNetworkPassphrase, time.Minute, + nil, ) require.NoError(t, err) @@ -963,6 +974,7 @@ func TestToken_jsonInputAccountNotExistNotAllowed(t *testing.T) { homeDomain, network.TestNetworkPassphrase, time.Minute, + nil, ) require.NoError(t, err) @@ -1047,6 +1059,7 @@ func TestToken_jsonInputUnrecognizedServerSigner(t *testing.T) { homeDomain, network.TestNetworkPassphrase, time.Minute, + nil, ) require.NoError(t, err) @@ -1248,6 +1261,7 @@ func TestToken_jsonInputInvalidWebAuthDomainFail(t *testing.T) { homeDomain, network.TestNetworkPassphrase, time.Minute, + nil, ) require.NoError(t, err) @@ -1309,3 +1323,217 @@ func TestToken_jsonInputInvalidWebAuthDomainFail(t *testing.T) { assert.JSONEq(t, `{"error":"The request was invalid in some way."}`, string(respBodyBytes)) } + +func TestToken_successWithIdMemo(t *testing.T) { + serverKey := keypair.MustRandom() + t.Logf("Server signing key: %s", serverKey.Address()) + + jwtPrivateKey, err := jwtkey.GenerateKey() + require.NoError(t, err) + jwk := jose.JSONWebKey{Key: jwtPrivateKey, Algorithm: string(jose.ES256)} + + account := keypair.MustRandom() + t.Logf("Client account: %s", account.Address()) + + domain := "webauth.example.com" + homeDomain := "example.com" + + memo := txnbuild.MemoID(1) + tx, err := txnbuild.BuildChallengeTx( + serverKey.Seed(), + account.Address(), + domain, + homeDomain, + network.TestNetworkPassphrase, + time.Minute, + &memo, + ) + require.NoError(t, err) + + chTx, err := tx.Base64() + require.NoError(t, err) + t.Logf("Tx: %s", chTx) + + tx, err = tx.Sign(network.TestNetworkPassphrase, account) + require.NoError(t, err) + txSigned, err := tx.Base64() + require.NoError(t, err) + t.Logf("Signed: %s", txSigned) + + horizonClient := &horizonclient.MockClient{} + horizonClient. + On("AccountDetail", horizonclient.AccountRequest{AccountID: account.Address()}). + Return( + horizon.Account{ + Thresholds: horizon.AccountThresholds{ + LowThreshold: 1, + MedThreshold: 10, + HighThreshold: 100, + }, + Signers: []horizon.Signer{ + { + Key: account.Address(), + Weight: 100, + }, + }}, + nil, + ) + + h := tokenHandler{ + Logger: supportlog.DefaultLogger, + HorizonClient: horizonClient, + NetworkPassphrase: network.TestNetworkPassphrase, + SigningAddresses: []*keypair.FromAddress{serverKey.FromAddress()}, + JWK: jwk, + JWTIssuer: "https://example.com", + JWTExpiresIn: time.Minute, + Domain: domain, + HomeDomains: []string{homeDomain}, + } + + body := struct { + Transaction string `json:"transaction"` + }{ + Transaction: txSigned, + } + bodyBytes, err := json.Marshal(body) + require.NoError(t, err) + r := httptest.NewRequest("POST", "/", bytes.NewReader(bodyBytes)) + r.Header.Set("Content-Type", "application/json") + w := httptest.NewRecorder() + h.ServeHTTP(w, r) + resp := w.Result() + + require.Equal(t, http.StatusOK, resp.StatusCode) + assert.Equal(t, "application/json; charset=utf-8", resp.Header.Get("Content-Type")) + + res := struct { + Token string `json:"token"` + }{} + err = json.NewDecoder(resp.Body).Decode(&res) + require.NoError(t, err) + + t.Logf("JWT: %s", res.Token) + + token, err := jwt.Parse(res.Token, func(token *jwt.Token) (interface{}, error) { + if _, ok := token.Method.(*jwt.SigningMethodECDSA); !ok { + return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"]) + } + return &jwtPrivateKey.PublicKey, nil + }) + require.NoError(t, err) + + claims := token.Claims.(jwt.MapClaims) + + require.Equal(t, account.Address()+":"+strconv.FormatUint(uint64(memo), 10), claims["sub"]) +} + +func TestToken_successWithMuxedAccount(t *testing.T) { + serverKey := keypair.MustRandom() + t.Logf("Server signing key: %s", serverKey.Address()) + + jwtPrivateKey, err := jwtkey.GenerateKey() + require.NoError(t, err) + jwk := jose.JSONWebKey{Key: jwtPrivateKey, Algorithm: string(jose.ES256)} + + account := keypair.MustRandom() + t.Logf("Stellar account: %s", account.Address()) + + muxedAccount := strkey.MuxedAccount{} + muxedAccount.SetAccountID(account.Address()) + muxedAccount.SetID(1) + muxedAccountAddress, err := muxedAccount.Address() + require.NoError(t, err) + t.Logf("Muxed account: %s", muxedAccountAddress) + + domain := "webauth.example.com" + homeDomain := "example.com" + + tx, err := txnbuild.BuildChallengeTx( + serverKey.Seed(), + muxedAccountAddress, + domain, + homeDomain, + network.TestNetworkPassphrase, + time.Minute, + nil, + ) + require.NoError(t, err) + + chTx, err := tx.Base64() + require.NoError(t, err) + t.Logf("Tx: %s", chTx) + + tx, err = tx.Sign(network.TestNetworkPassphrase, account) + require.NoError(t, err) + txSigned, err := tx.Base64() + require.NoError(t, err) + t.Logf("Signed: %s", txSigned) + + horizonClient := &horizonclient.MockClient{} + horizonClient. + On("AccountDetail", horizonclient.AccountRequest{AccountID: account.Address()}). + Return( + horizon.Account{ + Thresholds: horizon.AccountThresholds{ + LowThreshold: 1, + MedThreshold: 10, + HighThreshold: 100, + }, + Signers: []horizon.Signer{ + { + Key: account.Address(), + Weight: 100, + }, + }}, + nil, + ) + + h := tokenHandler{ + Logger: supportlog.DefaultLogger, + HorizonClient: horizonClient, + NetworkPassphrase: network.TestNetworkPassphrase, + SigningAddresses: []*keypair.FromAddress{serverKey.FromAddress()}, + JWK: jwk, + JWTIssuer: "https://example.com", + JWTExpiresIn: time.Minute, + Domain: domain, + HomeDomains: []string{homeDomain}, + } + + body := struct { + Transaction string `json:"transaction"` + }{ + Transaction: txSigned, + } + bodyBytes, err := json.Marshal(body) + require.NoError(t, err) + r := httptest.NewRequest("POST", "/", bytes.NewReader(bodyBytes)) + r.Header.Set("Content-Type", "application/json") + w := httptest.NewRecorder() + h.ServeHTTP(w, r) + resp := w.Result() + + require.Equal(t, http.StatusOK, resp.StatusCode) + assert.Equal(t, "application/json; charset=utf-8", resp.Header.Get("Content-Type")) + + res := struct { + Token string `json:"token"` + }{} + err = json.NewDecoder(resp.Body).Decode(&res) + require.NoError(t, err) + + t.Logf("JWT: %s", res.Token) + + token, err := jwt.Parse(res.Token, func(token *jwt.Token) (interface{}, error) { + if _, ok := token.Method.(*jwt.SigningMethodECDSA); !ok { + return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"]) + } + return &jwtPrivateKey.PublicKey, nil + }) + require.NoError(t, err) + + claims := token.Claims.(jwt.MapClaims) + + require.Equal(t, muxedAccountAddress, claims["sub"]) +} diff --git a/exp/support/pipeline/main.go b/exp/support/pipeline/main.go index 766b4548fb..8683424995 100644 --- a/exp/support/pipeline/main.go +++ b/exp/support/pipeline/main.go @@ -55,7 +55,7 @@ type Pipeline struct { mutex sync.Mutex running bool shutDown bool - cancelled bool + canceled bool cancelFunc context.CancelFunc } diff --git a/exp/support/pipeline/pipeline.go b/exp/support/pipeline/pipeline.go index edefb14dd2..4dd75e9cd0 100644 --- a/exp/support/pipeline/pipeline.go +++ b/exp/support/pipeline/pipeline.go @@ -95,7 +95,7 @@ func (p *Pipeline) IsRunning() bool { // reset resets internal state of the pipeline and all the nodes and processors. func (p *Pipeline) reset() { - p.cancelled = false + p.canceled = false p.resetNode(p.root) } @@ -132,7 +132,7 @@ func (p *Pipeline) resetNode(node *PipelineNode) { } } -// Process starts pipeline. Return channel will return if an error occured in +// Process starts pipeline. Return channel will return if an error occurred in // any of the processors or any of the pipeline hooks. Will return ErrShutdown // if the pipeline was shutdown. func (p *Pipeline) Process(reader Reader) <-chan error { @@ -183,17 +183,17 @@ func (p *Pipeline) processStateNode(ctx context.Context, store *Store, node *Pip err := node.Processor.Process(ctx, store, reader, writer) if err != nil { - // Protects from cancelling twice and sending multiple errors to err channel + // Protects from canceling twice and sending multiple errors to err channel p.mutex.Lock() defer p.mutex.Unlock() - if p.cancelled { + if p.canceled { return } wrappedErr := errors.Wrap(err, fmt.Sprintf("Processor %s errored", node.Processor.Name())) - p.cancelled = true + p.canceled = true p.cancelFunc() processingError = wrappedErr } @@ -257,11 +257,11 @@ func (p *Pipeline) Shutdown() { p.mutex.Lock() defer p.mutex.Unlock() - if p.cancelled { + if p.canceled { return } p.shutDown = true - p.cancelled = true + p.canceled = true // It's possible that Shutdown will be called before first run. if p.cancelFunc != nil { p.cancelFunc() diff --git a/exp/tools/captive-core-start-tester/main.go b/exp/tools/captive-core-start-tester/main.go index 7e44dea282..8f29385083 100644 --- a/exp/tools/captive-core-start-tester/main.go +++ b/exp/tools/captive-core-start-tester/main.go @@ -9,7 +9,7 @@ import ( // This little app helped testing CaptiveStellarCore.runFromParams on a living // Stellar-Core. Adding it to the repo because it can be useful in a future if -// Stellar-Core behaviour changes again. +// Stellar-Core behavior changes again. // To make it work, run standalone network (RUN_STANDALONE=false to allow outside // connections) and update paths below. func main() { diff --git a/exp/tools/dump-ledger-state/Dockerfile b/exp/tools/dump-ledger-state/Dockerfile index 3935e5789e..dc735ab55e 100644 --- a/exp/tools/dump-ledger-state/Dockerfile +++ b/exp/tools/dump-ledger-state/Dockerfile @@ -1,6 +1,6 @@ -FROM ubuntu:20.04 +FROM ubuntu:22.04 -ENV STELLAR_CORE_VERSION=19.2.0-966.d18d54aa3.focal +ENV STELLAR_CORE_VERSION=19.14.0-1500.5664eff4e.focal ENV DEBIAN_FRONTEND=noninteractive RUN apt-get update && apt-get install -y --no-install-recommends ca-certificates curl wget gnupg apt-utils @@ -26,7 +26,7 @@ RUN echo "host all all all trust" > /etc/postgresql/9.6/main/pg_hba.conf # And add `listen_addresses` to `/etc/postgresql/9.6/main/postgresql.conf` RUN echo "listen_addresses='*'" >> /etc/postgresql/9.6/main/postgresql.conf -RUN curl -sL https://storage.googleapis.com/golang/go1.16.5.linux-amd64.tar.gz | tar -C /usr/local -xz +RUN curl -sL https://storage.googleapis.com/golang/go1.19.linux-amd64.tar.gz | tar -C /usr/local -xz RUN ln -s /usr/local/go/bin/go /usr/local/bin/go WORKDIR /go/src/github.com/stellar/go COPY go.mod go.sum ./ diff --git a/go.mod b/go.mod index 4b3c377a7c..e823093e11 100644 --- a/go.mod +++ b/go.mod @@ -1,100 +1,127 @@ module github.com/stellar/go -go 1.18 +go 1.20 require ( - cloud.google.com/go/firestore v1.5.0 // indirect - cloud.google.com/go/storage v1.10.0 + cloud.google.com/go/firestore v1.13.0 // indirect + cloud.google.com/go/storage v1.30.1 firebase.google.com/go v3.12.0+incompatible - github.com/BurntSushi/toml v0.3.1 - github.com/Masterminds/squirrel v1.5.0 - github.com/Microsoft/go-winio v0.4.14 + github.com/2opremio/pretty v0.2.2-0.20230601220618-e1d5758b2a95 + github.com/BurntSushi/toml v1.3.2 + github.com/Masterminds/squirrel v1.5.4 + github.com/Microsoft/go-winio v0.6.1 github.com/adjust/goautoneg v0.0.0-20150426214442-d788f35a0315 - github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d - github.com/aws/aws-sdk-go v1.39.5 - github.com/elazarl/go-bindata-assetfs v1.0.0 - github.com/getsentry/raven-go v0.0.0-20160805001729-c9d3cc542ad1 - github.com/go-chi/chi v4.0.3+incompatible - github.com/go-errors/errors v0.0.0-20150906023321-a41850380601 - github.com/golang-jwt/jwt v3.2.1+incompatible - github.com/google/uuid v1.2.0 - github.com/gorilla/schema v1.1.0 + github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 + github.com/aws/aws-sdk-go v1.45.26 + github.com/creachadair/jrpc2 v1.1.0 + github.com/elazarl/go-bindata-assetfs v1.0.1 + github.com/getsentry/raven-go v0.2.0 + github.com/go-chi/chi v4.1.2+incompatible + github.com/go-errors/errors v1.5.1 + github.com/golang-jwt/jwt v3.2.2+incompatible + github.com/google/uuid v1.3.1 + github.com/gorilla/schema v1.2.0 github.com/graph-gophers/graphql-go v1.3.0 - github.com/guregu/null v2.1.3-0.20151024101046-79c5bd36b615+incompatible - github.com/holiman/uint256 v1.2.0 + github.com/guregu/null v4.0.0+incompatible + github.com/holiman/uint256 v1.2.3 github.com/howeyc/gopass v0.0.0-20170109162249-bf9dde6d0d2c github.com/jarcoal/httpmock v0.0.0-20161210151336-4442edb3db31 - github.com/jmoiron/sqlx v1.2.0 - github.com/lib/pq v1.2.0 + github.com/jmoiron/sqlx v1.3.5 + github.com/lib/pq v1.10.9 github.com/manucorporat/sse v0.0.0-20160126180136-ee05b128a739 github.com/mitchellh/go-homedir v1.1.0 - github.com/onsi/ginkgo v1.7.0 - github.com/onsi/gomega v1.4.3 - github.com/pelletier/go-toml v1.9.0 + github.com/onsi/ginkgo v1.16.5 + github.com/onsi/gomega v1.27.10 + github.com/pelletier/go-toml v1.9.5 github.com/pkg/errors v0.9.1 - github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829 - github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4 - github.com/rs/cors v0.0.0-20160617231935-a62a804a8a00 - github.com/rubenv/sql-migrate v0.0.0-20190717103323-87ce952f7079 + github.com/prometheus/client_golang v1.17.0 + github.com/prometheus/client_model v0.5.0 + github.com/rs/cors v1.10.1 + github.com/rubenv/sql-migrate v1.5.2 github.com/segmentio/go-loggly v0.5.1-0.20171222203950-eb91657e62b2 - github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749 - github.com/sirupsen/logrus v1.4.1 - github.com/spf13/cobra v0.0.0-20160830174925-9c28e4bbd74e - github.com/spf13/pflag v0.0.0-20161005214240-4bd69631f475 - github.com/spf13/viper v0.0.0-20150621231900-db7ff930a189 - github.com/stellar/go-xdr v0.0.0-20211103144802-8017fc4bdfee + github.com/shurcooL/httpfs v0.0.0-20230704072500-f1e31cf0ba5c + github.com/sirupsen/logrus v1.9.3 + github.com/spf13/cobra v1.7.0 + github.com/spf13/pflag v1.0.5 + github.com/spf13/viper v1.17.0 + github.com/stellar/go-xdr v0.0.0-20231122183749-b53fb00bcac2 github.com/stellar/throttled v2.2.3-0.20190823235211-89d75816f59d+incompatible - github.com/stretchr/testify v1.7.0 + github.com/stretchr/testify v1.8.4 github.com/tyler-smith/go-bip39 v0.0.0-20180618194314-52158e4697b8 github.com/xdrpp/goxdr v0.1.1 - google.golang.org/api v0.50.0 + google.golang.org/api v0.143.0 gopkg.in/gavv/httpexpect.v1 v1.0.0-20170111145843-40724cf1e4a0 gopkg.in/square/go-jose.v2 v2.4.1 - gopkg.in/tylerb/graceful.v1 v1.2.13 + gopkg.in/tylerb/graceful.v1 v1.2.15 ) -require github.com/andybalholm/brotli v1.0.4 // indirect +require golang.org/x/sync v0.4.0 require ( - cloud.google.com/go v0.84.0 // indirect + cloud.google.com/go/compute v1.23.0 // indirect + cloud.google.com/go/compute/metadata v0.2.3 // indirect + cloud.google.com/go/iam v1.1.1 // indirect + cloud.google.com/go/longrunning v0.5.1 // indirect + github.com/andybalholm/brotli v1.0.4 // indirect + github.com/certifi/gocertifi v0.0.0-20210507211836-431795d63e8d // indirect + github.com/cespare/xxhash/v2 v2.2.0 // indirect + github.com/creachadair/mds v0.0.1 // indirect + github.com/fsnotify/fsnotify v1.6.0 // indirect + github.com/go-gorp/gorp/v3 v3.1.0 // indirect + github.com/gobuffalo/packd v1.0.2 // indirect + github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 // indirect + github.com/google/s2a-go v0.1.7 // indirect + github.com/googleapis/enterprise-certificate-proxy v0.3.1 // indirect + github.com/hashicorp/hcl v1.0.0 // indirect + github.com/nxadm/tail v1.4.8 // indirect + github.com/pelletier/go-toml/v2 v2.1.0 // indirect + github.com/rogpeppe/go-internal v1.11.0 // indirect + github.com/sagikazarmark/locafero v0.3.0 // indirect + github.com/sagikazarmark/slog-shim v0.1.0 // indirect + github.com/sourcegraph/conc v0.3.0 // indirect + github.com/spf13/afero v1.10.0 // indirect + github.com/subosito/gotenv v1.6.0 // indirect + go.uber.org/multierr v1.11.0 // indirect + golang.org/x/mod v0.13.0 // indirect + golang.org/x/tools v0.14.0 // indirect + golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20230913181813-007df8e322eb // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20230920204549-e6e6cdab5c13 // indirect + gopkg.in/ini.v1 v1.67.0 // indirect +) + +require ( + cloud.google.com/go v0.110.7 // indirect github.com/ajg/form v0.0.0-20160822230020-523a5da1a92f // indirect - github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973 // indirect - github.com/davecgh/go-spew v1.1.1 // indirect + github.com/beorn7/perks v1.0.1 // indirect + github.com/buger/goreplay v1.3.2 + github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/fatih/structs v1.0.0 // indirect github.com/gavv/monotime v0.0.0-20161010190848-47d58efa6955 // indirect - github.com/gobuffalo/packr v1.12.1 // indirect - github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e // indirect - github.com/golang/protobuf v1.5.2 // indirect - github.com/google/go-cmp v0.5.8 // indirect + github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect + github.com/golang/protobuf v1.5.3 // indirect + github.com/google/go-cmp v0.5.9 // indirect github.com/google/go-querystring v0.0.0-20160401233042-9235644dd9e5 // indirect - github.com/googleapis/gax-go/v2 v2.0.5 // indirect - github.com/hashicorp/golang-lru v0.5.1 - github.com/hpcloud/tail v1.0.0 // indirect + github.com/googleapis/gax-go/v2 v2.12.0 // indirect + github.com/hashicorp/golang-lru v1.0.2 github.com/imkira/go-interpol v1.1.0 // indirect - github.com/inconshreveable/mousetrap v1.0.0 // indirect + github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect - github.com/jstemmer/go-junit-report v0.9.1 // indirect - github.com/klauspost/compress v1.15.0 // indirect - github.com/konsorten/go-windows-terminal-sequences v1.0.1 // indirect - github.com/kr/pretty v0.1.0 // indirect - github.com/kr/text v0.1.0 // indirect + github.com/klauspost/compress v1.17.0 // indirect + github.com/kr/text v0.2.0 // indirect github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 // indirect github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 // indirect - github.com/magiconair/properties v1.5.4 // indirect - github.com/mattn/go-colorable v0.1.2 // indirect - github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect - github.com/mitchellh/mapstructure v0.0.0-20150613213606-2caf8efc9366 // indirect + github.com/magiconair/properties v1.8.7 // indirect + github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect + github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/moul/http2curl v0.0.0-20161031194548-4e24498b31db // indirect github.com/opentracing/opentracing-go v1.1.0 // indirect - github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/prometheus/common v0.2.0 // indirect - github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1 // indirect - github.com/rs/xhandler v0.0.0-20160618193221-ed27b6fd6521 // indirect + github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect + github.com/prometheus/common v0.44.0 // indirect + github.com/prometheus/procfs v0.12.0 // indirect github.com/sergi/go-diff v0.0.0-20161205080420-83532ca1c1ca // indirect - github.com/smartystreets/goconvey v0.0.0-20190731233626-505e41936337 // indirect - github.com/spf13/cast v0.0.0-20150508191742-4d07383ffe94 // indirect - github.com/spf13/jwalterweatherman v0.0.0-20141219030609-3d60171a6431 // indirect - github.com/stretchr/objx v0.3.0 // indirect + github.com/spf13/cast v1.5.1 // indirect + github.com/stretchr/objx v0.5.1 // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect github.com/valyala/fasthttp v1.34.0 // indirect github.com/xeipuuv/gojsonpointer v0.0.0-20151027082146-e0fe6f683076 // indirect @@ -104,28 +131,19 @@ require ( github.com/yudai/gojsondiff v0.0.0-20170107030110-7b1b7adf999d // indirect github.com/yudai/golcs v0.0.0-20150405163532-d1c525dea8ce // indirect github.com/yudai/pp v2.0.1+incompatible // indirect - github.com/ziutek/mymysql v1.5.4 // indirect - go.opencensus.io v0.23.0 // indirect - golang.org/x/crypto v0.0.0-20220214200702-86341886e292 // indirect - golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e - golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 // indirect - golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3 // indirect - golang.org/x/net v0.0.0-20220225172249-27dd8689420f // indirect - golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914 // indirect - golang.org/x/sync v0.0.0-20210220032951-036812b2e83c - golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9 // indirect - golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect - golang.org/x/text v0.3.7 // indirect - golang.org/x/time v0.0.0-20220224211638-0e9765cccd65 - golang.org/x/tools v0.1.10 // indirect - golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect + go.opencensus.io v0.24.0 // indirect + golang.org/x/crypto v0.14.0 // indirect + golang.org/x/exp v0.0.0-20231006140011-7918f672742d + golang.org/x/net v0.17.0 // indirect + golang.org/x/oauth2 v0.12.0 // indirect + golang.org/x/sys v0.13.0 // indirect + golang.org/x/term v0.13.0 // indirect + golang.org/x/text v0.13.0 // indirect + golang.org/x/time v0.3.0 google.golang.org/appengine v1.6.7 // indirect - google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84 // indirect - google.golang.org/grpc v1.38.0 // indirect - google.golang.org/protobuf v1.26.0 // indirect - gopkg.in/fsnotify.v1 v1.4.7 // indirect - gopkg.in/gorp.v1 v1.7.1 // indirect + google.golang.org/genproto v0.0.0-20230913181813-007df8e322eb // indirect + google.golang.org/grpc v1.58.3 // indirect + google.golang.org/protobuf v1.31.0 // indirect gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect - gopkg.in/yaml.v2 v2.2.8 // indirect - gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index d2d588c26f..bb1175e120 100644 --- a/go.sum +++ b/go.sum @@ -3,6 +3,7 @@ cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= +cloud.google.com/go v0.44.3/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= @@ -16,22 +17,26 @@ cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHOb cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY= -cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg= -cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8= -cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0= -cloud.google.com/go v0.83.0/go.mod h1:Z7MJUsANfY0pYPdw0lbnivPx4/vhy/e2FEkSkF7vAVY= -cloud.google.com/go v0.84.0 h1:hVhK90DwCdOAYGME/FJd9vNIZye9HBR6Yy3fu4js3N8= -cloud.google.com/go v0.84.0/go.mod h1:RazrYuxIK6Kb7YrzzhPoLmCVzl7Sup4NrbKPg8KHSUM= +cloud.google.com/go v0.110.7 h1:rJyC7nWRg2jWGZ4wSJ5nY65GTdYJkg0cd/uXb+ACI6o= +cloud.google.com/go v0.110.7/go.mod h1:+EYjdK8e5RME/VY/qLCAtuyALQ9q67dvuum8i+H5xsI= cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= +cloud.google.com/go/compute v1.23.0 h1:tP41Zoavr8ptEqaW6j+LQOnyBBhO7OkOMAGrgLopTwY= +cloud.google.com/go/compute v1.23.0/go.mod h1:4tCnrn48xsqlwSAiLf1HXMQk8CONslYbdiEZc9FEIbM= +cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY= +cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= -cloud.google.com/go/firestore v1.5.0 h1:4qNItsmc4GP6UOZPGemmHY4ZfPofVhcaKXsYw9wm9oA= -cloud.google.com/go/firestore v1.5.0/go.mod h1:c4nNYR1qdq7eaZ+jSc5fonrQN2k3M7sWATcYTiakjEo= +cloud.google.com/go/firestore v1.13.0 h1:/3S4RssUV4GO/kvgJZB+tayjhOfyAHs+KcpJgRVu/Qk= +cloud.google.com/go/firestore v1.13.0/go.mod h1:QojqqOh8IntInDUSTAh0c8ZsPYAr68Ma8c5DWOy8xb8= +cloud.google.com/go/iam v1.1.1 h1:lW7fzj15aVIXYHREOqjRBV9PsH0Z6u8Y46a1YGvQP4Y= +cloud.google.com/go/iam v1.1.1/go.mod h1:A5avdyVL2tCppe4unb0951eI9jreack+RJ0/d+KUZOU= +cloud.google.com/go/longrunning v0.5.1 h1:Fr7TXftcqTudoyRJa113hyaqlGdiBQkp0Gq7tErFDWI= +cloud.google.com/go/longrunning v0.5.1/go.mod h1:spvimkwdz6SPWKEt/XBij79E9fiTkHSQl/fRUUQJYJc= cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= @@ -40,33 +45,48 @@ cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiy cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= -cloud.google.com/go/storage v1.10.0 h1:STgFzyU5/8miMl0//zKh2aQeTyeaUH3WN9bSUiJ09bA= cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= +cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo= +cloud.google.com/go/storage v1.30.1 h1:uOdMxAs8HExqBlnLtnQyP0YkvbiDpdGShGKtx6U/oNM= +cloud.google.com/go/storage v1.30.1/go.mod h1:NfxhC0UJE1aXSx7CIIbCf7y9HKT7BiccwkR7+P7gN8E= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= firebase.google.com/go v3.12.0+incompatible h1:q70KCp/J0oOL8kJ8oV2j3646kV4TB8Y5IvxXC0WT1bo= firebase.google.com/go v3.12.0+incompatible/go.mod h1:xlah6XbEyW6tbfSklcfe5FHJIwjt8toICdV5Wh9ptHs= -github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= +github.com/2opremio/pretty v0.2.2-0.20230601220618-e1d5758b2a95 h1:vvMDiVd621MU1Djr7Ep7OXu8gHOtsdwrI4tjnIGvpTg= +github.com/2opremio/pretty v0.2.2-0.20230601220618-e1d5758b2a95/go.mod h1:Gv4NIpY67KDahg+DtIG5/2Ok4l8vzYEekiirSCH+IGA= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= +github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/Masterminds/squirrel v1.5.0 h1:JukIZisrUXadA9pl3rMkjhiamxiB0cXiu+HGp/Y8cY8= -github.com/Masterminds/squirrel v1.5.0/go.mod h1:NNaOrjSoIDfDA40n7sr2tPNZRfjzjA400rg+riTZj10= -github.com/Microsoft/go-winio v0.4.14 h1:+hMXMk01us9KgxGb7ftKQt2Xpf5hH/yky+TDA+qxleU= -github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= +github.com/Masterminds/squirrel v1.5.4 h1:uUcX/aBc8O7Fg9kaISIUsHXdKuqehiXAMQTYX8afzqM= +github.com/Masterminds/squirrel v1.5.4/go.mod h1:NNaOrjSoIDfDA40n7sr2tPNZRfjzjA400rg+riTZj10= +github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= +github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= +github.com/Shopify/sarama v1.26.4/go.mod h1:NbSGBSSndYaIhRcBtY9V0U7AyH+x71bG668AuWys/yU= +github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= github.com/adjust/goautoneg v0.0.0-20150426214442-d788f35a0315 h1:zje9aPr1kQ5nKwjO5MC0S/jehRtNrjfYuLfFRWZH6kY= github.com/adjust/goautoneg v0.0.0-20150426214442-d788f35a0315/go.mod h1:4U522XvlkqOY2AVBUM7ISHODDb6tdB+KAXfGaBDsWts= github.com/ajg/form v0.0.0-20160822230020-523a5da1a92f h1:zvClvFQwU++UpIUBGC8YmDlfhUrweEy1R1Fj1gu5iIM= github.com/ajg/form v0.0.0-20160822230020-523a5da1a92f/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= -github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/andybalholm/brotli v1.0.4 h1:V7DdXeJtZscaqfNuAdSRuRFzuiKlHSC/Zh3zl9qY3JY= github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= -github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d h1:Byv0BzEl3/e6D5CLfI0j/7hiIEtvGVFPCZ7Ei2oq8iQ= -github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= -github.com/aws/aws-sdk-go v1.39.5 h1:yoJEE1NJxbpZ3CtPxvOSFJ9ByxiXmBTKk8J+XU5ldtg= -github.com/aws/aws-sdk-go v1.39.5/go.mod h1:585smgzpB/KqRA+K3y/NL/oYRqQvpNJYvLm+LY1U59Q= -github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973 h1:xJ4a3vCFaGF/jqvzLMYoU8P317H5OQ+Via4RmuPwCS0= -github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= +github.com/araddon/gou v0.0.0-20190110011759-c797efecbb61/go.mod h1:ikc1XA58M+Rx7SEbf0bLJCfBkwayZ8T5jBo5FXK8Uz8= +github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so= +github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= +github.com/aws/aws-sdk-go v1.33.2/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0= +github.com/aws/aws-sdk-go v1.45.26 h1:PJ2NJNY5N/yeobLYe1Y+xLdavBi67ZI8gvph6ftwVCg= +github.com/aws/aws-sdk-go v1.45.26/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= +github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/bitly/go-hostpool v0.1.0/go.mod h1:4gOCgp6+NZnVqlKyZ/iBZFTAJKembaVENUpMkpg42fw= +github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4= +github.com/buger/goreplay v1.3.2 h1:MFAStZZCsHMPeN5xJ11rhUtV4ZctFRgzSHTfWSWOJsg= +github.com/buger/goreplay v1.3.2/go.mod h1:EyAKHxJR6K6phd0NaoPETSDbJRB/ogIw3Y15UlSbVBM= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/certifi/gocertifi v0.0.0-20210507211836-431795d63e8d h1:S2NE3iHSwP0XV47EEXL8mWmRdEfGscSJ+7EgePNgt0s= +github.com/certifi/gocertifi v0.0.0-20210507211836-431795d63e8d/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA= +github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= +github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= @@ -74,48 +94,68 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/creachadair/jrpc2 v1.1.0 h1:SgpJf0v1rVCZx68+4APv6dgsTFsIHlpgFD1NlQAWA0A= +github.com/creachadair/jrpc2 v1.1.0/go.mod h1:5jN7MKwsm8qvgfTsTzLX3JIfidsAkZ1c8DZSQmp+g38= +github.com/creachadair/mds v0.0.1 h1:2nX6Sww4dXpScx3b6aYjH1n7iuEH715+jj+cKkKw9BY= +github.com/creachadair/mds v0.0.1/go.mod h1:caBACU+n1Q/rZ252FTzfnG0/H+ZUi+UnIQtEOraMv/g= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/elazarl/go-bindata-assetfs v1.0.0 h1:G/bYguwHIzWq9ZoyUQqrjTmJbbYn3j3CKKpKinvZLFk= -github.com/elazarl/go-bindata-assetfs v1.0.0/go.mod h1:v+YaWX3bdea5J/mo8dSETolEo7R71Vk1u8bnjau5yw4= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/eapache/go-resiliency v1.2.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= +github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= +github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= +github.com/elazarl/go-bindata-assetfs v1.0.1 h1:m0kkaHRKEu7tUIUFVwhGGGYClXvyl4RE03qmvRTNfbw= +github.com/elazarl/go-bindata-assetfs v1.0.1/go.mod h1:v+YaWX3bdea5J/mo8dSETolEo7R71Vk1u8bnjau5yw4= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= -github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/fatih/structs v1.0.0 h1:BrX964Rv5uQ3wwS+KRUAJCBBw5PQmgJfJ6v4yly5QwU= github.com/fatih/structs v1.0.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= -github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= +github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw= +github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= +github.com/frankban/quicktest v1.7.2/go.mod h1:jaStnuzAqU1AJdCO0l53JDCJrVDKcS03DbaAcR7Ks/o= +github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= +github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= github.com/gavv/monotime v0.0.0-20161010190848-47d58efa6955 h1:gmtGRvSexPU4B1T/yYo0sLOKzER1YT+b4kPxPpm0Ty4= github.com/gavv/monotime v0.0.0-20161010190848-47d58efa6955/go.mod h1:vmp8DIyckQMXOPl0AQVHt+7n5h7Gb7hS6CUydiV8QeA= -github.com/getsentry/raven-go v0.0.0-20160805001729-c9d3cc542ad1 h1:qIqziX4EA/OBdmMgtaqdKBWWOZIfyXYClCoa56NgVEk= -github.com/getsentry/raven-go v0.0.0-20160805001729-c9d3cc542ad1/go.mod h1:KungGk8q33+aIAZUIVWZDr2OfAEBsO49PX4NzFV5kcQ= -github.com/go-chi/chi v4.0.3+incompatible h1:gakN3pDJnzZN5jqFV2TEdF66rTfKeITyR8qu6ekICEY= -github.com/go-chi/chi v4.0.3+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ= -github.com/go-errors/errors v0.0.0-20150906023321-a41850380601 h1:jxTbmDuqQUTI6MscgbqB39vtxGfr2fi61nYIcFQUnlE= -github.com/go-errors/errors v0.0.0-20150906023321-a41850380601/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= +github.com/getsentry/raven-go v0.2.0 h1:no+xWJRb5ZI7eE8TWgIq1jLulQiIoLG0IfYxv5JYMGs= +github.com/getsentry/raven-go v0.2.0/go.mod h1:KungGk8q33+aIAZUIVWZDr2OfAEBsO49PX4NzFV5kcQ= +github.com/go-chi/chi v4.1.2+incompatible h1:fGFk2Gmi/YKXk0OmGfBh0WgmN3XB8lVnEyNz34tQRec= +github.com/go-chi/chi v4.1.2+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ= +github.com/go-errors/errors v1.5.1 h1:ZwEMSLRCapFLflTpT7NKaAc7ukJ8ZPEjzlxt8rPN8bk= +github.com/go-errors/errors v1.5.1/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= -github.com/go-sql-driver/mysql v1.4.0 h1:7LxgVwFb2hIQtMm87NdgAVfXjnt4OePseqT1tKx+opk= -github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= -github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/gobuffalo/packr v1.12.1 h1:+5u3rqgdhswdYXhrX6DHaO7BM4P8oxrbvgZm9H1cRI4= -github.com/gobuffalo/packr v1.12.1/go.mod h1:H2dZhQFqHeZwr/5A/uGQkBp7xYuMGuzXFeKhYdcz5No= -github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= -github.com/golang-jwt/jwt v3.2.1+incompatible h1:73Z+4BJcrTC+KczS6WvTPvRGOp1WmfEP4Q1lOd9Z/+c= -github.com/golang-jwt/jwt v3.2.1+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= +github.com/go-gorp/gorp/v3 v3.1.0 h1:ItKF/Vbuj31dmV4jxA1qblpSwkl9g1typ24xoe70IGs= +github.com/go-gorp/gorp/v3 v3.1.0/go.mod h1:dLEjIyyRNiXvNZ8PSmzpt1GsWAUK8kjVhEpjH8TixEw= +github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= +github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= +github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE= +github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= +github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= +github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= +github.com/gobuffalo/logger v1.0.6 h1:nnZNpxYo0zx+Aj9RfMPBm+x9zAU2OayFh/xrAWi34HU= +github.com/gobuffalo/packd v1.0.2 h1:Yg523YqnOxGIWCp69W12yYBKsoChwI7mtu6ceM9Bwfw= +github.com/gobuffalo/packd v1.0.2/go.mod h1:sUc61tDqGMXON80zpKGp92lDb86Km28jfvX7IAyxFT8= +github.com/gobuffalo/packr/v2 v2.8.3 h1:xE1yzvnO56cUC0sTpKR3DIbxZgB54AftTFMhB2XEWlY= +github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY= +github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e h1:1r7pUrabqp18hOBcwBwiTsbnFeTZHV9eER/QT5JVZxY= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= @@ -123,7 +163,6 @@ github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= -github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -139,10 +178,9 @@ github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QD github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM= -github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= -github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= +github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= @@ -156,17 +194,16 @@ github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= -github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-querystring v0.0.0-20160401233042-9235644dd9e5 h1:oERTZ1buOUYlpmKaqlO5fYmz8cZ1rYu5DieJzF4ZVmU= github.com/google/go-querystring v0.0.0-20160401233042-9235644dd9e5/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= +github.com/google/gopacket v1.1.20-0.20210429153827-3eaba0894325/go.mod h1:riddUzxTSBpJXk3qBHtYr4qOhFhT6k/1c0E3qkQjQpA= github.com/google/martian v2.1.0+incompatible h1:/CP5g8u/VJHijgedC/Legn3BAbAaWPgecwXBIDzw5no= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= -github.com/google/martian/v3 v3.2.1 h1:d8MncMlErDFTwQGBK1xhv026j9kqhvw1Qv9IbWT1VLQ= -github.com/google/martian/v3 v3.2.1/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk= +github.com/google/martian/v3 v3.3.2 h1:IqNFLAmvJOgVlpdEBiQbDc2EwKW77amAycfTuWKdfvw= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= @@ -177,162 +214,199 @@ github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hf github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 h1:K6RDEckDVWvDI9JAJYCmNdQXq6neHJOYx3V6jnqNEec= +github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/s2a-go v0.1.7 h1:60BLSyTrOV4/haCDW4zb1guZItoSq8foHCXrAnjBo/o= +github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.2.0 h1:qJYtXnJRWmpe7m/3XlyhrsLrEURqHRM2kxzoxXqyUDs= -github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4= +github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/googleapis/enterprise-certificate-proxy v0.3.1 h1:SBWmZhjUDRorQxrN0nwzf+AHBxnbFjViHQS4P0yVpmQ= +github.com/googleapis/enterprise-certificate-proxy v0.3.1/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= -github.com/googleapis/gax-go/v2 v2.0.5 h1:sjZBwGj9Jlw33ImPtvFviGYvseOtDM7hkSKB7+Tv3SM= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= +github.com/googleapis/gax-go/v2 v2.12.0 h1:A+gCJKdRfqXkr+BIRGtZLibNXf0m1f9E4HG56etFpas= +github.com/googleapis/gax-go/v2 v2.12.0/go.mod h1:y+aIqrI5eb1YGMVJfuV3185Ts/D7qKpsEkdD5+I6QGU= +github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= -github.com/gorilla/schema v1.1.0 h1:CamqUDOFUBqzrvxuz2vEwo8+SUdwsluFh7IlzJh30LY= -github.com/gorilla/schema v1.1.0/go.mod h1:kgLaKoK1FELgZqMAVxx/5cbj0kT+57qxUrAlIO2eleU= +github.com/gorilla/schema v1.2.0 h1:YufUaxZYCKGFuAq3c96BOhjgd5nmXiOY9NGzF247Tsc= +github.com/gorilla/schema v1.2.0/go.mod h1:kgLaKoK1FELgZqMAVxx/5cbj0kT+57qxUrAlIO2eleU= github.com/graph-gophers/graphql-go v1.3.0 h1:Eb9x/q6MFpCLz7jBCiP/WTxjSDrYLR1QY41SORZyNJ0= github.com/graph-gophers/graphql-go v1.3.0/go.mod h1:9CQHMSxwO4MprSdzoIEobiHpoLtHm77vfxsvsIN5Vuc= -github.com/guregu/null v2.1.3-0.20151024101046-79c5bd36b615+incompatible h1:SZmF1M6CdAm4MmTPYYTG+x9EC8D3FOxUq9S4D37irQg= -github.com/guregu/null v2.1.3-0.20151024101046-79c5bd36b615+incompatible/go.mod h1:ePGpQaN9cw0tj45IR5E5ehMvsFlLlQZAkkOXZurJ3NM= +github.com/guregu/null v4.0.0+incompatible h1:4zw0ckM7ECd6FNNddc3Fu4aty9nTlpkkzH7dPn4/4Gw= +github.com/guregu/null v4.0.0+incompatible/go.mod h1:ePGpQaN9cw0tj45IR5E5ehMvsFlLlQZAkkOXZurJ3NM= +github.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.1 h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+dAcgU= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/holiman/uint256 v1.2.0 h1:gpSYcPLWGv4sG43I2mVLiDZCNDh/EpGjSk8tmtxitHM= -github.com/holiman/uint256 v1.2.0/go.mod h1:y4ga/t+u+Xwd7CpDgZESaRcWy0I7XMlTMA25ApIH5Jw= +github.com/hashicorp/golang-lru v1.0.2 h1:dV3g9Z/unq5DpblPpw+Oqcv4dU/1omnb4Ok8iPY6p1c= +github.com/hashicorp/golang-lru v1.0.2/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= +github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= +github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/holiman/uint256 v1.2.3 h1:K8UWO1HUJpRMXBxbmaY1Y8IAMZC/RsKB+ArEnnK4l5o= +github.com/holiman/uint256 v1.2.3/go.mod h1:SC8Ryt4n+UBbPbIBKaG9zbbDlp4jOru9xFZmPzLUTxw= github.com/howeyc/gopass v0.0.0-20170109162249-bf9dde6d0d2c h1:kQWxfPIHVLbgLzphqk3QUflDy9QdksZR4ygR807bpy0= github.com/howeyc/gopass v0.0.0-20170109162249-bf9dde6d0d2c/go.mod h1:lADxMC39cJJqL93Duh1xhAs4I2Zs8mKS89XWXFGp9cs= -github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/imkira/go-interpol v1.1.0 h1:KIiKr0VSG2CUW1hl1jpiyuzuJeKUUpC8iM1AIE7N1Vk= github.com/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA= -github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= -github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= +github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/jarcoal/httpmock v0.0.0-20161210151336-4442edb3db31 h1:Aw95BEvxJ3K6o9GGv5ppCd1P8hkeIeEJ30FO+OhOJpM= github.com/jarcoal/httpmock v0.0.0-20161210151336-4442edb3db31/go.mod h1:ks+b9deReOc7jgqp+e7LuFiCBH6Rm5hL32cLcEAArb4= +github.com/jcmturner/gofork v1.0.0/go.mod h1:MK8+TM0La+2rjBD4jE12Kj1pCCxK7d2LK/UM3ncEo0o= +github.com/jmespath/go-jmespath v0.3.0/go.mod h1:9QtRXoHjLGCJ5IBSaohpXITPlowMeeYCZ7fLUTSywik= github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= -github.com/jmoiron/sqlx v1.2.0 h1:41Ip0zITnmWNR/vHV+S4m+VoUivnWY5E4OJfLZjCJMA= -github.com/jmoiron/sqlx v1.2.0/go.mod h1:1FEQNm3xlJgrMD+FBdI9+xvCksHtbpVBBw5dYhBSsks= +github.com/jmoiron/sqlx v1.3.5 h1:vFFPA71p1o5gAeqtEAwLU4dnX2napprKtHr7PYIcN3g= +github.com/jmoiron/sqlx v1.3.5/go.mod h1:nRVWtLre0KfCLJvgxzCsLVMogSvQ1zNJtpYr2Ccp0mQ= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= -github.com/jstemmer/go-junit-report v0.9.1 h1:6QPYqodiu3GuPL+7mfx+NwDdp2eTkp9IfEUpgAwUN0o= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= -github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= +github.com/karrick/godirwalk v1.16.1 h1:DynhcF+bztK8gooS0+NDJFrdNZjJ3gzVzC545UNA9iw= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/klauspost/compress v1.15.0 h1:xqfchp4whNFxn5A4XFyyYtitiWI8Hy5EW59jEwcyL6U= +github.com/klauspost/compress v1.9.8/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= +github.com/klauspost/compress v1.10.10/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.15.0/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= -github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk= -github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= -github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= +github.com/klauspost/compress v1.17.0 h1:Rnbp4K9EjcDuVuHtd0dgA4qNuv9yKDYKK1ulpJwgrqM= +github.com/klauspost/compress v1.17.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= +github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 h1:SOEGU9fKiNWd/HOJuq6+3iTQz8KNCLtVX6idSoTLdUw= github.com/lann/builder v0.0.0-20180802200727-47ae307949d0/go.mod h1:dXGbAdH5GtBTC4WfIxhKZfyBF/HBFgRZSWwZ9g/He9o= github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 h1:P6pPBnrTSX3DEVR4fDembhRWSsG5rVo6hYhAB/ADZrk= github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0/go.mod h1:vmVJ0l/dxyfGW6FmdpVm2joNMFikkuWg0EoCKLGUMNw= -github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= -github.com/lib/pq v1.2.0 h1:LXpIM/LZ5xGFhOpXAQUIMM1HdyqzVYM13zNdjCEEcA0= github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= -github.com/magiconair/properties v1.5.4 h1:5Y3GEEL4cWijFkb6jtcVs3lX2EWA1ZKq64qu9cd8W7s= -github.com/magiconair/properties v1.5.4/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= +github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= +github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= github.com/manucorporat/sse v0.0.0-20160126180136-ee05b128a739 h1:ykXz+pRRTibcSjG1yRhpdSHInF8yZY/mfn+Rz2Nd1rE= github.com/manucorporat/sse v0.0.0-20160126180136-ee05b128a739/go.mod h1:zUx1mhth20V3VKgL5jbd1BSQcW4Fy6Qs4PZvQwRFwzM= -github.com/mattn/go-colorable v0.1.2 h1:/bC9yWikZXAL9uJdulbSfyVNIR3n3trXl+v8+1sx8mU= -github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= -github.com/mattn/go-isatty v0.0.8 h1:HLtExJ+uU2HOZ+wI0Tt5DtUDrx8yhUqDcp7fYERX4CE= -github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -github.com/mattn/go-sqlite3 v1.9.0 h1:pDRiWfl+++eC2FEFRy6jXmQlvp4Yh3z1MJKg4UeYM/4= -github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= -github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= -github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/markbates/errx v1.1.0 h1:QDFeR+UP95dO12JgW+tgi2UVfo0V8YBHiUIOaeBPiEI= +github.com/markbates/oncer v1.0.0 h1:E83IaVAHygyndzPimgUYJjbshhDTALZyXxvk9FOlQRY= +github.com/markbates/safe v1.0.1 h1:yjZkbvRM6IzKj9tlu/zMJLS0n/V351OZWRnF3QfaUxI= +github.com/mattbaird/elastigo v0.0.0-20170123220020-2fe47fd29e4b/go.mod h1:5MWrJXKRQyhQdUCF+vu6U5c4nQpg70vW3eHaU0/AYbU= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng= +github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= +github.com/mattn/go-sqlite3 v1.14.15 h1:vfoHhTN1af61xCRSWzFIWzx2YskyMTwHLrExkBOjvxI= +github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= +github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/mitchellh/mapstructure v0.0.0-20150613213606-2caf8efc9366 h1:1ypTpKUfEOyX1YsJru6lLq7hrmK+QGECpJQ1PHUHuGo= -github.com/mitchellh/mapstructure v0.0.0-20150613213606-2caf8efc9366/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= +github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/moul/http2curl v0.0.0-20161031194548-4e24498b31db h1:eZgFHVkk9uOTaOQLC6tgjkzdp7Ays8eEVecBcfHZlJQ= github.com/moul/http2curl v0.0.0-20161031194548-4e24498b31db/go.mod h1:8UbvGypXm98wA/IqH45anm5Y2Z6ep6O31QGOAZ3H0fQ= -github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= +github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= +github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.7.0 h1:WSHQ+IS43OoUrWtD1/bbclrwK8TTH5hzp+umCiuxHgs= -github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/gomega v1.4.3 h1:RE1xgDvH7imwFD45h+u2SgIfERHlS2yNG4DObb5BSKU= -github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= +github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= +github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= +github.com/onsi/ginkgo/v2 v2.11.0 h1:WgqUCUt/lT6yXoQ8Wef0fsNn5cAuMK7+KT9UFRz2tcU= +github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= +github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= +github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI= +github.com/onsi/gomega v1.27.10/go.mod h1:RsS8tutOdbdgzbPtzzATp12yT7kM5I5aElG3evPbQ0M= github.com/opentracing/opentracing-go v1.1.0 h1:pWlfV3Bxv7k65HYwkikxat0+s3pV4bsqf19k25Ur8rU= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= -github.com/pelletier/go-toml v1.9.0 h1:NOd0BRdOKpPf0SxkL3HxSQOG7rNh+4kl6PHcBPFs7Q0= -github.com/pelletier/go-toml v1.9.0/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= -github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= +github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= +github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4= +github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= +github.com/pierrec/lz4 v2.4.1+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= +github.com/pierrec/lz4 v2.5.2+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= -github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829 h1:D+CiwcpGTW6pL6bv6KI3KbyEyCKyS+1JWS2h8PNDnGA= -github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs= -github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= -github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= -github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4 h1:gQz4mCbXsO+nc9n1hCxHcGA3Zx3Eo+UHZoInFGUIXNM= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/poy/onpar v1.1.2 h1:QaNrNiZx0+Nar5dLgTVp5mXkyoVFIbepjyEoGSnhbAY= +github.com/prometheus/client_golang v1.17.0 h1:rl2sfwZMtSthVU752MqfjQozy7blglC+1SOtjMAMh+Q= +github.com/prometheus/client_golang v1.17.0/go.mod h1:VeL+gMmOAxkS2IqfCq0ZmHSL+LjWfWDUmp1mBz9JgUY= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/common v0.2.0 h1:kUZDBDTdBVBYBj5Tmh2NZLlF60mfjA27rM34b+cVwNU= -github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1 h1:/K3IL0Z1quvmJ7X0A1AwNEK7CRkVK3YwfOU/QAL4WGg= -github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw= +github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI= +github.com/prometheus/common v0.44.0 h1:+5BrQJwiBB9xsMygAB3TNvpQKOwlkc25LbISbrdOOfY= +github.com/prometheus/common v0.44.0/go.mod h1:ofAIvZbQ1e/nugmZGz4/qCb9Ap1VoSTIO7x0VV9VvuY= +github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= +github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= +github.com/rcrowley/go-metrics v0.0.0-20190826022208-cac0b30c2563/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= +github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rs/cors v0.0.0-20160617231935-a62a804a8a00 h1:8DPul/X0IT/1TNMIxoKLwdemEOBBHDC/K4EB16Cw5WE= -github.com/rs/cors v0.0.0-20160617231935-a62a804a8a00/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= -github.com/rs/xhandler v0.0.0-20160618193221-ed27b6fd6521 h1:3hxavr+IHMsQBrYUPQM5v0CgENFktkkbg1sfpgM3h20= -github.com/rs/xhandler v0.0.0-20160618193221-ed27b6fd6521/go.mod h1:RvLn4FgxWubrpZHtQLnOf6EwhN2hEMusxZOhcW9H3UQ= -github.com/rubenv/sql-migrate v0.0.0-20190717103323-87ce952f7079 h1:xPeaaIHjF9j8jbYQ5xdvLnFp+lpmGYFG1uBPtXNBHno= -github.com/rubenv/sql-migrate v0.0.0-20190717103323-87ce952f7079/go.mod h1:WS0rl9eEliYI8DPnr3TOwz4439pay+qNgzJoVya/DmY= +github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= +github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= +github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= +github.com/rs/cors v1.10.1 h1:L0uuZVXIKlI1SShY2nhFfo44TYvDPQ1w4oFkUJNfhyo= +github.com/rs/cors v1.10.1/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= +github.com/rubenv/sql-migrate v1.5.2 h1:bMDqOnrJVV/6JQgQ/MxOpU+AdO8uzYYA/TxFUBzFtS0= +github.com/rubenv/sql-migrate v1.5.2/go.mod h1:H38GW8Vqf8F0Su5XignRyaRcbXbJunSWxs+kmzlg0Is= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/sagikazarmark/locafero v0.3.0 h1:zT7VEGWC2DTflmccN/5T1etyKvxSxpHsjb9cJvm4SvQ= +github.com/sagikazarmark/locafero v0.3.0/go.mod h1:w+v7UsPNFwzF1cHuOajOOzoq4U7v/ig1mpRjqV+Bu1U= +github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE= +github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ= github.com/segmentio/go-loggly v0.5.1-0.20171222203950-eb91657e62b2 h1:S4OC0+OBKz6mJnzuHioeEat74PuQ4Sgvbf8eus695sc= github.com/segmentio/go-loggly v0.5.1-0.20171222203950-eb91657e62b2/go.mod h1:8zLRYR5npGjaOXgPSKat5+oOh+UHd8OdbS18iqX9F6Y= github.com/sergi/go-diff v0.0.0-20161205080420-83532ca1c1ca h1:oR/RycYTFTVXzND5r4FdsvbnBn0HJXSVeNAnwaTXRwk= github.com/sergi/go-diff v0.0.0-20161205080420-83532ca1c1ca/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= -github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749 h1:bUGsEnyNbVPw06Bs80sCeARAlK8lhwqGyi6UT8ymuGk= -github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg= -github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= -github.com/sirupsen/logrus v1.4.1 h1:GL2rEmy6nsikmW0r8opw9JIRScdMF5hA8cOYLH7In1k= -github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= +github.com/shurcooL/httpfs v0.0.0-20230704072500-f1e31cf0ba5c h1:aqg5Vm5dwtvL+YgDpBcK1ITf3o96N/K7/wsRXQnUTEs= +github.com/shurcooL/httpfs v0.0.0-20230704072500-f1e31cf0ba5c/go.mod h1:owqhoLW1qZoYLZzLnBw+QkPP9WZnjlSWihhxAJC1+/M= +github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= +github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= -github.com/smartystreets/goconvey v0.0.0-20190731233626-505e41936337 h1:WN9BUFbdyOsSH/XohnWpXOlq9NBD5sGAB2FciQMUEe8= -github.com/smartystreets/goconvey v0.0.0-20190731233626-505e41936337/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= -github.com/spf13/cast v0.0.0-20150508191742-4d07383ffe94 h1:JmfC365KywYwHB946TTiQWEb8kqPY+pybPLoGE9GgVk= -github.com/spf13/cast v0.0.0-20150508191742-4d07383ffe94/go.mod h1:r2rcYCSwa1IExKTDiTfzaxqT2FNHs8hODu4LnUfgKEg= -github.com/spf13/cobra v0.0.0-20160830174925-9c28e4bbd74e h1:YdP6GKJS0Ls++kXc85WCCX2ArKToqixBwpBrWP/5J/k= -github.com/spf13/cobra v0.0.0-20160830174925-9c28e4bbd74e/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= -github.com/spf13/jwalterweatherman v0.0.0-20141219030609-3d60171a6431 h1:XTHrT015sxHyJ5FnQ0AeemSspZWaDq7DoTRW0EVsDCE= -github.com/spf13/jwalterweatherman v0.0.0-20141219030609-3d60171a6431/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= -github.com/spf13/pflag v0.0.0-20161005214240-4bd69631f475 h1:RtZIgreTwcayPTOw7G5jqNSaRISGXa9CwlUl+hSyMtg= -github.com/spf13/pflag v0.0.0-20161005214240-4bd69631f475/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= -github.com/spf13/viper v0.0.0-20150621231900-db7ff930a189 h1:fvB1AFbBd6SfI9Rd0ooAJp8uLkZDbZaLFHi7ZnNP6uI= -github.com/spf13/viper v0.0.0-20150621231900-db7ff930a189/go.mod h1:A8kyI5cUJhb8N+3pkfONlcEcZbueH6nhAm0Fq7SrnBM= -github.com/stellar/go-xdr v0.0.0-20211103144802-8017fc4bdfee h1:fbVs0xmXpBvVS4GBeiRmAE3Le70ofAqFMch1GTiq/e8= -github.com/stellar/go-xdr v0.0.0-20211103144802-8017fc4bdfee/go.mod h1:yoxyU/M8nl9LKeWIoBrbDPQ7Cy+4jxRcWcOayZ4BMps= +github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s= +github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= +github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= +github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= +github.com/spf13/afero v1.10.0 h1:EaGW2JJh15aKOejeuJ+wpFSHnbd7GE6Wvp3TsNhb6LY= +github.com/spf13/afero v1.10.0/go.mod h1:UBogFpq8E9Hx+xc5CNTTEpTnuHVmXDwZcZcE1eb/UhQ= +github.com/spf13/cast v1.5.1 h1:R+kOtfhWQE6TVQzY+4D7wJLBgkdVasCEFxSUBYBYIlA= +github.com/spf13/cast v1.5.1/go.mod h1:b9PdjNptOpzXr7Rq1q9gJML/2cdGQAo69NKzQ10KN48= +github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I= +github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0= +github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/viper v1.17.0 h1:I5txKw7MJasPL/BrfkbA0Jyo/oELqVmux4pR/UxOMfI= +github.com/spf13/viper v1.17.0/go.mod h1:BmMMMLQXSbcHK6KAOiFLz0l5JHrU89OdIRHvsk0+yVI= +github.com/stellar/go-xdr v0.0.0-20231122183749-b53fb00bcac2 h1:OzCVd0SV5qE3ZcDeSFCmOWLZfEWZ3Oe8KtmSOYKEVWE= +github.com/stellar/go-xdr v0.0.0-20231122183749-b53fb00bcac2/go.mod h1:yoxyU/M8nl9LKeWIoBrbDPQ7Cy+4jxRcWcOayZ4BMps= github.com/stellar/throttled v2.2.3-0.20190823235211-89d75816f59d+incompatible h1:jMXXAcz6xTarGDQ4VtVbtERogcmDQw4RaE85Cr9CgoQ= github.com/stellar/throttled v2.2.3-0.20190823235211-89d75816f59d+incompatible/go.mod h1:7CJ23pXirXBJq45DqvO6clzTEGM/l1SfKrgrzLry8b4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.3.0 h1:NGXK3lHquSN08v5vWalVI/L8XU9hdzE/G6xsrze47As= -github.com/stretchr/objx v0.3.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.1 h1:4VhoImhV/Bm0ToFkXFi8hXNXwpDRZ/ynw3amt82mzq0= +github.com/stretchr/objx v0.5.1/go.mod h1:/iHQpkQwBD6DLUmQ4pE+s1TXdob1mORJ4/UFdrifcy0= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= -github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= +github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= github.com/tyler-smith/go-bip39 v0.0.0-20180618194314-52158e4697b8 h1:g3yQGZK+G6dfF/mw/SOwsTMzUVkpT4hB8pHxpbTXkKw= github.com/tyler-smith/go-bip39 v0.0.0-20180618194314-52158e4697b8/go.mod h1:sJ5fKU0s6JVwZjjcUEX2zFOnvq0ASQ2K9Zr6cf67kNs= github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= @@ -340,6 +414,11 @@ github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyC github.com/valyala/fasthttp v1.34.0 h1:d3AAQJ2DRcxJYHm7OXNXtXt2as1vMDfxeIcFvhmGGm4= github.com/valyala/fasthttp v1.34.0/go.mod h1:epZA5N+7pY6ZaEKRmstzOuYJx9HI8DI1oaCGZpdH4h0= github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc= +github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE= +github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU= +github.com/vishvananda/netns v0.0.0-20210104183010-2eb08e3e575f/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0= +github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c/go.mod h1:lB8K/P019DLNhemzwFU4jHLhdvlE6uDZjXFejJXr49I= +github.com/xdg/stringprep v1.0.0/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y= github.com/xdrpp/goxdr v0.1.1 h1:E1B2c6E8eYhOVyd7yEpOyopzTPirUeF6mVOfXfGyJyc= github.com/xdrpp/goxdr v0.1.1/go.mod h1:dXo1scL/l6s7iME1gxHWo2XCppbHEKZS7m/KyYWkNzA= github.com/xeipuuv/gojsonpointer v0.0.0-20151027082146-e0fe6f683076 h1:KM4T3G70MiR+JtqplcYkNVoNz7pDwYaBxWBXQK804So= @@ -360,25 +439,29 @@ github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -github.com/ziutek/mymysql v1.5.4 h1:GB0qdRGsTwQSBVYuVShFBKaXSnSnYYC2d9knnE1LHFs= -github.com/ziutek/mymysql v1.5.4/go.mod h1:LMSpPZ6DbqWFxNCHW77HeMg9I646SAhApZ/wKdgO/C0= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= -go.opencensus.io v0.23.0 h1:gqCw0LfLxScz8irSi8exQc7fyQ0fKQU/qnC/X8+V/1M= -go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= -golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= +go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= +go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= +go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200204104054-c9f3fb736b72/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20220214200702-86341886e292 h1:f+lwQ+GtmgoY+A2YaQxlSOnDjXcQ7ZRLWOHbC6HtRqE= +golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc= +golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -389,8 +472,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e h1:+WEEuIdZHnUeJJmEUjyYC2gfUMj69yZXw17EnHg/otA= -golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e/go.mod h1:Kr81I6Kryrl9sr8s2FK3vxD90NdsKWRuOIl2O4CvYbA= +golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI= +golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -404,8 +487,6 @@ golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRu golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 h1:VLliZ0d+/avPrXXH+OakdXhpJuEoBZuwh1m2j7U6Iug= -golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= @@ -416,15 +497,13 @@ golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3 h1:kQgndtyPBW/JIYERgdxfwMYh3AVStj88WQTlNDi2a+o= -golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.13.0 h1:I/DsJXRlw/8l/0c24sM9yb0T4z9liZTduXvdAWYiysY= +golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -444,6 +523,7 @@ golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/ golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= @@ -453,15 +533,13 @@ golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwY golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= -golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= -golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20220225172249-27dd8689420f h1:oA4XRj0qtSt8Yo1Zms0CUlsT3KG69V2UGQWPBxujDmc= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= +golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= +golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -471,11 +549,8 @@ golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914 h1:3B43BWw0xEBsLZ/NO1VALz6fppU3481pik+2Ksv45z8= -golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.12.0 h1:smVPGxink+n1ZI5pkQa8y6fZT0RW0MgCO5bFpepy4B4= +golang.org/x/oauth2 v0.12.0/go.mod h1:A74bZ3aGXgCY0qaIC9Ahg6Lglin4AMAco8cIv9baba4= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -486,28 +561,31 @@ golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ= -golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ= +golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -522,40 +600,42 @@ golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210223095934-7937bea0104d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9 h1:nhht2DYV/Sn3qOayu8lM+cU1ii9sTLUeBQwQQfUHtrs= golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= +golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek= +golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= +golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20220224211638-0e9765cccd65 h1:M73Iuj3xbbb9Uk1DYhzydthsj6oOd6l9bpuFcNoUvTs= -golang.org/x/time v0.0.0-20220224211638-0e9765cccd65/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= +golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= @@ -601,20 +681,19 @@ golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82u golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= -golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.10 h1:QjFRCZxdOhBJ/UNgnBZLbNV13DlbnK0quyivTnXJM20= -golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.14.0 h1:jvNa2pY0M4r62jkRQ6RwEZZyPcymeL9XZMLBbV7U2nc= +golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk= +golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= @@ -634,12 +713,8 @@ google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz513 google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE= google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= -google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU= -google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94= -google.golang.org/api v0.47.0/go.mod h1:Wbvgpq1HddcWVtzsVLyfLp8lDg6AA241LmgIL59tHXo= -google.golang.org/api v0.48.0/go.mod h1:71Pr1vy+TAZRPkPs/xlCf5SsU8WjuAWv1Pfjbtukyy4= -google.golang.org/api v0.50.0 h1:LX7NFCFYOHzr7WHaYiRUpeipZe9o5L8T+2F4Z798VDw= -google.golang.org/api v0.50.0/go.mod h1:4bNT5pAuq5ji4SRZm+5QIkjny9JAyVD/3gaSihNefaw= +google.golang.org/api v0.143.0 h1:o8cekTkqhywkbZT6p1UHJPZ9+9uuCAJs/KYomxZB8fA= +google.golang.org/api v0.143.0/go.mod h1:FoX9DO9hT7DLNn97OuoZAGSDuNAXdJRuGK98rSUgurk= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -683,17 +758,13 @@ google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= -google.golang.org/genproto v0.0.0-20210513213006-bf773b8c8384/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A= -google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= -google.golang.org/genproto v0.0.0-20210604141403-392c879c8b08/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= -google.golang.org/genproto v0.0.0-20210608205507-b6d2f5bf0d7d/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= -google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84 h1:R1r5J0u6Cx+RNl/6mezTw6oA14cmKC96FeUwL6A9bd4= -google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24= +google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20230913181813-007df8e322eb h1:XFBgcDwm7irdHTbz4Zk2h7Mh+eis4nfJEFQFYzJzuIA= +google.golang.org/genproto v0.0.0-20230913181813-007df8e322eb/go.mod h1:yZTlhN0tQnXo3h00fuXNCxJdLdIdnVFVBaRJ5LWBbw4= +google.golang.org/genproto/googleapis/api v0.0.0-20230913181813-007df8e322eb h1:lK0oleSc7IQsUxO3U5TjL9DWlsxpEBemh+zpB7IqhWI= +google.golang.org/genproto/googleapis/api v0.0.0-20230913181813-007df8e322eb/go.mod h1:KjSP20unUpOx5kyQUFa7k4OJg0qeJ7DEZflGDu2p6Bk= +google.golang.org/genproto/googleapis/rpc v0.0.0-20230920204549-e6e6cdab5c13 h1:N3bU/SQDCDyD6R528GJ/PwW9KjYcJA3dgyH+MovAkIM= +google.golang.org/genproto/googleapis/rpc v0.0.0-20230920204549-e6e6cdab5c13/go.mod h1:KSqppvjFjtoCI+KGd4PELB0qLNxdJHRGqRI09mB6pQA= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= @@ -710,13 +781,8 @@ google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc v1.37.1/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc v1.38.0 h1:/9BgsAsa5nWe26HqOlvlgJnqBuktYOLCgjCPqsa56W0= -google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= +google.golang.org/grpc v1.58.3 h1:BjnpXut1btbtgN/6sp+brB2Kbm2LjNXnidYujAVbSoQ= +google.golang.org/grpc v1.58.3/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -728,31 +794,38 @@ google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpAD google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= +google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= +google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= -gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/gavv/httpexpect.v1 v1.0.0-20170111145843-40724cf1e4a0 h1:r5ptJ1tBxVAeqw4CrYWhXIMr0SybY3CDHuIbCg5CFVw= gopkg.in/gavv/httpexpect.v1 v1.0.0-20170111145843-40724cf1e4a0/go.mod h1:WtiW9ZA1LdaWqtQRo1VbIL/v4XZ8NDta+O/kSpGgVek= -gopkg.in/gorp.v1 v1.7.1 h1:GBB9KrWRATQZh95HJyVGUZrWwOPswitEYEyqlK8JbAA= -gopkg.in/gorp.v1 v1.7.1/go.mod h1:Wo3h+DBQZIxATwftsglhdD/62zRFPhGhTiu5jUJmCaw= +gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= +gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/jcmturner/aescts.v1 v1.0.1/go.mod h1:nsR8qBOg+OucoIW+WMhB3GspUQXq9XorLnQb9XtvcOo= +gopkg.in/jcmturner/dnsutils.v1 v1.0.1/go.mod h1:m3v+5svpVOhtFAP/wSz+yzh4Mc0Fg7eRhxkJMWSIz9Q= +gopkg.in/jcmturner/goidentity.v3 v3.0.0/go.mod h1:oG2kH0IvSYNIu80dVAyu/yoefjq1mNfM5bm88whjWx4= +gopkg.in/jcmturner/gokrb5.v7 v7.5.0/go.mod h1:l8VISx+WGYp+Fp7KRbsiUuXTTOnxIc3Tuvyavf11/WM= +gopkg.in/jcmturner/rpc.v1 v1.1.0/go.mod h1:YIdkC4XfD6GXbzje11McwsDuOlZQSb9W4vfLvuNnlv8= gopkg.in/square/go-jose.v2 v2.4.1 h1:H0TmLt7/KmzlrDOpa1F+zr0Tk90PbJYBfsVUmRLrf9Y= gopkg.in/square/go-jose.v2 v2.4.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= -gopkg.in/tylerb/graceful.v1 v1.2.13 h1:UWJlWJHZepntB0PJ9RTgW3X+zVLjfmWbx/V1X/V/XoA= -gopkg.in/tylerb/graceful.v1 v1.2.13/go.mod h1:yBhekWvR20ACXVObSSdD3u6S9DeSylanL2PAbAC/uJ8= -gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/tylerb/graceful.v1 v1.2.15 h1:1JmOyhKqAyX3BgTXMI84LwT6FOJ4tP2N9e2kwTCM0nQ= +gopkg.in/tylerb/graceful.v1 v1.2.15/go.mod h1:yBhekWvR20ACXVObSSdD3u6S9DeSylanL2PAbAC/uJ8= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/gofmt.sh b/gofmt.sh index f51f2c931c..98b1791261 100755 --- a/gofmt.sh +++ b/gofmt.sh @@ -2,7 +2,7 @@ set -e printf "Running gofmt checks...\n" -OUTPUT=$(gofmt -d .) +OUTPUT=$(gofmt -d -s .) if [[ $OUTPUT ]]; then printf "gofmt found unformatted files:\n\n" diff --git a/gogenerate.sh b/gogenerate.sh index 307b87eecb..cb89037136 100755 --- a/gogenerate.sh +++ b/gogenerate.sh @@ -2,7 +2,7 @@ set -e printf "Running go generate...\n" -go generate ./... && go fmt ./... +go generate ./... && gofmt -s -w -d . printf "Checking for no diff...\n" git diff --exit-code || (echo "Files changed after running go generate. Run go generate ./... locally and update generated files." && exit 1) diff --git a/gxdr/dump.go b/gxdr/dump.go index 0146a8e585..06a124278e 100644 --- a/gxdr/dump.go +++ b/gxdr/dump.go @@ -16,7 +16,7 @@ func Dump(v goxdr.XdrType) []byte { } // Convert serializes the given goxdr value into another destination value -// which supports binary unmarshalling. +// which supports binary unmarshaling. // // This function can be used to convert github.com/xdrpp/goxdr/xdr values into // equivalent https://github.com/stellar/go-xdr values. diff --git a/gxdr/xdr_generated.go b/gxdr/xdr_generated.go index 3ae27a7c3a..b66e0a2c7c 100644 --- a/gxdr/xdr_generated.go +++ b/gxdr/xdr_generated.go @@ -1,4 +1,4 @@ -// Code generated by goxdr -p gxdr -enum-comments -o gxdr/xdr_generated.go xdr/Stellar-SCP.x xdr/Stellar-ledger-entries.x xdr/Stellar-ledger.x xdr/Stellar-overlay.x xdr/Stellar-transaction.x xdr/Stellar-types.x xdr/Stellar-lighthorizon.x; DO NOT EDIT. +// Code generated by goxdr -p gxdr -enum-comments -o gxdr/xdr_generated.go xdr/Stellar-SCP.x xdr/Stellar-ledger-entries.x xdr/Stellar-ledger.x xdr/Stellar-overlay.x xdr/Stellar-transaction.x xdr/Stellar-types.x xdr/Stellar-contract-env-meta.x xdr/Stellar-contract-meta.x xdr/Stellar-contract-spec.x xdr/Stellar-contract.x xdr/Stellar-internal.x xdr/Stellar-contract-config-setting.x xdr/Stellar-lighthorizon.x; DO NOT EDIT. package gxdr @@ -109,8 +109,6 @@ type SCPQuorumSet struct { InnerSets []SCPQuorumSet } -type AccountID = PublicKey - type Thresholds = [4]byte type String32 = string // bound 32 @@ -119,10 +117,6 @@ type String64 = string // bound 64 type SequenceNumber = Int64 -type TimePoint = Uint64 - -type Duration = Uint64 - type DataValue = []byte // bound 64 // SHA256(LiquidityPoolParameters) @@ -208,6 +202,10 @@ const ( DATA LedgerEntryType = 3 CLAIMABLE_BALANCE LedgerEntryType = 4 LIQUIDITY_POOL LedgerEntryType = 5 + CONTRACT_DATA LedgerEntryType = 6 + CONTRACT_CODE LedgerEntryType = 7 + CONFIG_SETTING LedgerEntryType = 8 + TTL LedgerEntryType = 9 ) type Signer struct { @@ -626,6 +624,33 @@ type XdrAnon_LiquidityPoolEntry_Body_ConstantProduct struct { PoolSharesTrustLineCount Int64 } +type ContractDataDurability int32 + +const ( + TEMPORARY ContractDataDurability = 0 + PERSISTENT ContractDataDurability = 1 +) + +type ContractDataEntry struct { + Ext ExtensionPoint + Contract SCAddress + Key SCVal + Durability ContractDataDurability + Val SCVal +} + +type ContractCodeEntry struct { + Ext ExtensionPoint + Hash Hash + Code []byte +} + +type TTLEntry struct { + // Hash of the LedgerKey that is associated with this TTLEntry + KeyHash Hash + LiveUntilLedgerSeq Uint32 +} + type LedgerEntryExtensionV1 struct { SponsoringID SponsorshipDescriptor Ext XdrAnon_LedgerEntryExtensionV1_Ext @@ -658,6 +683,14 @@ type XdrAnon_LedgerEntry_Data struct { // ClaimableBalance() *ClaimableBalanceEntry // LIQUIDITY_POOL: // LiquidityPool() *LiquidityPoolEntry + // CONTRACT_DATA: + // ContractData() *ContractDataEntry + // CONTRACT_CODE: + // ContractCode() *ContractCodeEntry + // CONFIG_SETTING: + // ConfigSetting() *ConfigSettingEntry + // TTL: + // Ttl() *TTLEntry Type LedgerEntryType _u interface{} } @@ -687,6 +720,14 @@ type LedgerKey struct { // ClaimableBalance() *XdrAnon_LedgerKey_ClaimableBalance // LIQUIDITY_POOL: // LiquidityPool() *XdrAnon_LedgerKey_LiquidityPool + // CONTRACT_DATA: + // ContractData() *XdrAnon_LedgerKey_ContractData + // CONTRACT_CODE: + // ContractCode() *XdrAnon_LedgerKey_ContractCode + // CONFIG_SETTING: + // ConfigSetting() *XdrAnon_LedgerKey_ConfigSetting + // TTL: + // Ttl() *XdrAnon_LedgerKey_Ttl Type LedgerEntryType _u interface{} } @@ -711,6 +752,21 @@ type XdrAnon_LedgerKey_ClaimableBalance struct { type XdrAnon_LedgerKey_LiquidityPool struct { LiquidityPoolID PoolID } +type XdrAnon_LedgerKey_ContractData struct { + Contract SCAddress + Key SCVal + Durability ContractDataDurability +} +type XdrAnon_LedgerKey_ContractCode struct { + Hash Hash +} +type XdrAnon_LedgerKey_ConfigSetting struct { + ConfigSettingID ConfigSettingID +} +type XdrAnon_LedgerKey_Ttl struct { + // Hash of the LedgerKey that is associated with this TTLEntry + KeyHash Hash +} // list of all envelope types used in the application // those are prefixes used when building signatures for @@ -718,14 +774,16 @@ type XdrAnon_LedgerKey_LiquidityPool struct { type EnvelopeType int32 const ( - ENVELOPE_TYPE_TX_V0 EnvelopeType = 0 - ENVELOPE_TYPE_SCP EnvelopeType = 1 - ENVELOPE_TYPE_TX EnvelopeType = 2 - ENVELOPE_TYPE_AUTH EnvelopeType = 3 - ENVELOPE_TYPE_SCPVALUE EnvelopeType = 4 - ENVELOPE_TYPE_TX_FEE_BUMP EnvelopeType = 5 - ENVELOPE_TYPE_OP_ID EnvelopeType = 6 - ENVELOPE_TYPE_POOL_REVOKE_OP_ID EnvelopeType = 7 + ENVELOPE_TYPE_TX_V0 EnvelopeType = 0 + ENVELOPE_TYPE_SCP EnvelopeType = 1 + ENVELOPE_TYPE_TX EnvelopeType = 2 + ENVELOPE_TYPE_AUTH EnvelopeType = 3 + ENVELOPE_TYPE_SCPVALUE EnvelopeType = 4 + ENVELOPE_TYPE_TX_FEE_BUMP EnvelopeType = 5 + ENVELOPE_TYPE_OP_ID EnvelopeType = 6 + ENVELOPE_TYPE_POOL_REVOKE_OP_ID EnvelopeType = 7 + ENVELOPE_TYPE_CONTRACT_ID EnvelopeType = 8 + ENVELOPE_TYPE_SOROBAN_AUTHORIZATION EnvelopeType = 9 ) type UpgradeType = []byte // bound 128 @@ -850,13 +908,20 @@ in ascending order type LedgerUpgradeType int32 const ( - LEDGER_UPGRADE_VERSION LedgerUpgradeType = 1 - LEDGER_UPGRADE_BASE_FEE LedgerUpgradeType = 2 - LEDGER_UPGRADE_MAX_TX_SET_SIZE LedgerUpgradeType = 3 - LEDGER_UPGRADE_BASE_RESERVE LedgerUpgradeType = 4 - LEDGER_UPGRADE_FLAGS LedgerUpgradeType = 5 + LEDGER_UPGRADE_VERSION LedgerUpgradeType = 1 + LEDGER_UPGRADE_BASE_FEE LedgerUpgradeType = 2 + LEDGER_UPGRADE_MAX_TX_SET_SIZE LedgerUpgradeType = 3 + LEDGER_UPGRADE_BASE_RESERVE LedgerUpgradeType = 4 + LEDGER_UPGRADE_FLAGS LedgerUpgradeType = 5 + LEDGER_UPGRADE_CONFIG LedgerUpgradeType = 6 + LEDGER_UPGRADE_MAX_SOROBAN_TX_SET_SIZE LedgerUpgradeType = 7 ) +type ConfigUpgradeSetKey struct { + ContractID Hash + ContentHash Hash +} + type LedgerUpgrade struct { // The union discriminant Type selects among the following arms: // LEDGER_UPGRADE_VERSION: @@ -869,10 +934,18 @@ type LedgerUpgrade struct { // NewBaseReserve() *Uint32 // LEDGER_UPGRADE_FLAGS: // NewFlags() *Uint32 + // LEDGER_UPGRADE_CONFIG: + // NewConfig() *ConfigUpgradeSetKey + // LEDGER_UPGRADE_MAX_SOROBAN_TX_SET_SIZE: + // NewMaxSorobanTxSetSize() *Uint32 Type LedgerUpgradeType _u interface{} } +type ConfigUpgradeSet struct { + UpdatedEntry []ConfigSettingEntry +} + /* Entries used to define the bucket list */ type BucketEntryType int32 @@ -1091,6 +1164,69 @@ type TransactionMetaV2 struct { TxChangesAfter LedgerEntryChanges } +type ContractEventType int32 + +const ( + SYSTEM ContractEventType = 0 + CONTRACT ContractEventType = 1 + DIAGNOSTIC ContractEventType = 2 +) + +type ContractEvent struct { + // We can use this to add more fields, or because it + // is first, to change ContractEvent into a union. + Ext ExtensionPoint + ContractID *Hash + Type ContractEventType + Body XdrAnon_ContractEvent_Body +} +type XdrAnon_ContractEvent_Body struct { + // The union discriminant V selects among the following arms: + // 0: + // V0() *XdrAnon_ContractEvent_Body_V0 + V int32 + _u interface{} +} +type XdrAnon_ContractEvent_Body_V0 struct { + Topics []SCVal + Data SCVal +} + +type DiagnosticEvent struct { + InSuccessfulContractCall bool + Event ContractEvent +} + +type SorobanTransactionMeta struct { + Ext ExtensionPoint + // custom events populated by the + Events []ContractEvent + // contracts themselves. + ReturnValue SCVal + // Diagnostics events that are not hashed. + // This will contain all contract and diagnostic events. Even ones + // that were emitted in a failed contract call. + DiagnosticEvents []DiagnosticEvent +} + +type TransactionMetaV3 struct { + Ext ExtensionPoint + // tx level changes before operations + TxChangesBefore LedgerEntryChanges + // are applied if any + Operations []OperationMeta + // tx level changes after operations are + TxChangesAfter LedgerEntryChanges + // applied if any + SorobanMeta *SorobanTransactionMeta +} + +// This is in Stellar-ledger.x to due to a circular dependency +type InvokeHostFunctionSuccessPreImage struct { + ReturnValue SCVal + Events []ContractEvent +} + // this is the meta produced when applying transactions // it does not include pre-apply updates such as fees type TransactionMeta struct { @@ -1101,6 +1237,8 @@ type TransactionMeta struct { // V1() *TransactionMetaV1 // 2: // V2() *TransactionMetaV2 + // 3: + // V3() *TransactionMetaV3 V int32 _u interface{} } @@ -1136,6 +1274,9 @@ type LedgerCloseMetaV0 struct { } type LedgerCloseMetaV1 struct { + // We forgot to add an ExtensionPoint in v0 but at least + // we can add one now in v1. + Ext ExtensionPoint LedgerHeader LedgerHeaderHistoryEntry TxSet GeneralizedTransactionSet // NB: transactions are sorted in apply order here @@ -1146,6 +1287,14 @@ type LedgerCloseMetaV1 struct { UpgradesProcessing []UpgradeEntryMeta // other misc information attached to the ledger close ScpInfo []SCPHistoryEntry + // Size in bytes of BucketList, to support downstream + // systems calculating storage fees correctly. + TotalByteSizeOfBucketList Uint64 + // Temp keys that are being evicted at this ledger. + EvictedTemporaryLedgerKeys []LedgerKey + // Archived restorable ledger entries that are being + // evicted at this ledger. + EvictedPersistentLedgerEntries []LedgerEntry } type LedgerCloseMeta struct { @@ -1182,6 +1331,11 @@ type SendMore struct { NumMessages Uint32 } +type SendMoreExtended struct { + NumMessages Uint32 + NumBytes Uint32 +} + type AuthCert struct { Pubkey Curve25519Public Expiration Uint64 @@ -1200,10 +1354,17 @@ type Hello struct { Nonce Uint256 } +// During the roll-out phrase, nodes can disable flow control in bytes. +// Therefore, we need a way to communicate with other nodes +// that we want/don't want flow control in bytes. +// We use the `flags` field in the Auth message with a special value +// set to communicate this. Note that AUTH_MSG_FLAG_FLOW_CONTROL_BYTES_REQUESTED != 0 +// AND AUTH_MSG_FLAG_FLOW_CONTROL_BYTES_REQUESTED != 100 (as previously +// that value was used for other purposes). +const AUTH_MSG_FLAG_FLOW_CONTROL_BYTES_REQUESTED = 200 + type Auth struct { - // Empty message, just to confirm - // establishment of MAC keys. - Unused int32 + Flags int32 } type IPAddrType int32 @@ -1228,7 +1389,7 @@ type XdrAnon_PeerAddress_Ip struct { _u interface{} } -// Next ID: 18 +// Next ID: 21 type MessageType int32 const ( @@ -1250,10 +1411,13 @@ const ( SCP_MESSAGE MessageType = 11 GET_SCP_STATE MessageType = 12 // new messages - HELLO MessageType = 13 - SURVEY_REQUEST MessageType = 14 - SURVEY_RESPONSE MessageType = 15 - SEND_MORE MessageType = 16 + HELLO MessageType = 13 + SURVEY_REQUEST MessageType = 14 + SURVEY_RESPONSE MessageType = 15 + SEND_MORE MessageType = 16 + SEND_MORE_EXTENDED MessageType = 20 + FLOOD_ADVERT MessageType = 18 + FLOOD_DEMAND MessageType = 19 ) type DontHave struct { @@ -1267,6 +1431,13 @@ const ( SURVEY_TOPOLOGY SurveyMessageCommandType = 0 ) +type SurveyMessageResponseType int32 + +const ( + SURVEY_TOPOLOGY_RESPONSE_V0 SurveyMessageResponseType = 0 + SURVEY_TOPOLOGY_RESPONSE_V1 SurveyMessageResponseType = 1 +) + type SurveyRequestMessage struct { SurveyorPeerID NodeID SurveyedPeerID NodeID @@ -1315,21 +1486,48 @@ type PeerStats struct { type PeerStatList = []PeerStats // bound 25 -type TopologyResponseBody struct { +type TopologyResponseBodyV0 struct { + InboundPeers PeerStatList + OutboundPeers PeerStatList + TotalInboundPeerCount Uint32 + TotalOutboundPeerCount Uint32 +} + +type TopologyResponseBodyV1 struct { InboundPeers PeerStatList OutboundPeers PeerStatList TotalInboundPeerCount Uint32 TotalOutboundPeerCount Uint32 + MaxInboundPeerCount Uint32 + MaxOutboundPeerCount Uint32 } type SurveyResponseBody struct { // The union discriminant Type selects among the following arms: - // SURVEY_TOPOLOGY: - // TopologyResponseBody() *TopologyResponseBody - Type SurveyMessageCommandType + // SURVEY_TOPOLOGY_RESPONSE_V0: + // TopologyResponseBodyV0() *TopologyResponseBodyV0 + // SURVEY_TOPOLOGY_RESPONSE_V1: + // TopologyResponseBodyV1() *TopologyResponseBodyV1 + Type SurveyMessageResponseType _u interface{} } +const TX_ADVERT_VECTOR_MAX_SIZE = 1000 + +type TxAdvertVector = []Hash // bound TX_ADVERT_VECTOR_MAX_SIZE + +type FloodAdvert struct { + TxHashes TxAdvertVector +} + +const TX_DEMAND_VECTOR_MAX_SIZE = 1000 + +type TxDemandVector = []Hash // bound TX_DEMAND_VECTOR_MAX_SIZE + +type FloodDemand struct { + TxHashes TxDemandVector +} + type StellarMessage struct { // The union discriminant Type selects among the following arms: // ERROR_MSG: @@ -1366,6 +1564,12 @@ type StellarMessage struct { // GetSCPLedgerSeq() *Uint32 // SEND_MORE: // SendMoreMessage() *SendMore + // SEND_MORE_EXTENDED: + // SendMoreExtendedMessage() *SendMoreExtended + // FLOOD_ADVERT: + // FloodAdvert() *FloodAdvert + // FLOOD_DEMAND: + // FloodDemand() *FloodDemand Type MessageType _u interface{} } @@ -1383,6 +1587,9 @@ type XdrAnon_AuthenticatedMessage_V0 struct { Mac HmacSha256Mac } +// maximum number of operations per transaction +const MAX_OPS_PER_TX = 100 + type LiquidityPoolParameters struct { // The union discriminant Type selects among the following arms: // LIQUIDITY_POOL_CONSTANT_PRODUCT: @@ -1440,6 +1647,9 @@ const ( SET_TRUST_LINE_FLAGS OperationType = 21 LIQUIDITY_POOL_DEPOSIT OperationType = 22 LIQUIDITY_POOL_WITHDRAW OperationType = 23 + INVOKE_HOST_FUNCTION OperationType = 24 + EXTEND_FOOTPRINT_TTL OperationType = 25 + RESTORE_FOOTPRINT OperationType = 26 ) /* @@ -1839,6 +2049,151 @@ type LiquidityPoolWithdrawOp struct { MinAmountB Int64 } +type HostFunctionType int32 + +const ( + HOST_FUNCTION_TYPE_INVOKE_CONTRACT HostFunctionType = 0 + HOST_FUNCTION_TYPE_CREATE_CONTRACT HostFunctionType = 1 + HOST_FUNCTION_TYPE_UPLOAD_CONTRACT_WASM HostFunctionType = 2 +) + +type ContractIDPreimageType int32 + +const ( + CONTRACT_ID_PREIMAGE_FROM_ADDRESS ContractIDPreimageType = 0 + CONTRACT_ID_PREIMAGE_FROM_ASSET ContractIDPreimageType = 1 +) + +type ContractIDPreimage struct { + // The union discriminant Type selects among the following arms: + // CONTRACT_ID_PREIMAGE_FROM_ADDRESS: + // FromAddress() *XdrAnon_ContractIDPreimage_FromAddress + // CONTRACT_ID_PREIMAGE_FROM_ASSET: + // FromAsset() *Asset + Type ContractIDPreimageType + _u interface{} +} +type XdrAnon_ContractIDPreimage_FromAddress struct { + Address SCAddress + Salt Uint256 +} + +type CreateContractArgs struct { + ContractIDPreimage ContractIDPreimage + Executable ContractExecutable +} + +type InvokeContractArgs struct { + ContractAddress SCAddress + FunctionName SCSymbol + Args []SCVal +} + +type HostFunction struct { + // The union discriminant Type selects among the following arms: + // HOST_FUNCTION_TYPE_INVOKE_CONTRACT: + // InvokeContract() *InvokeContractArgs + // HOST_FUNCTION_TYPE_CREATE_CONTRACT: + // CreateContract() *CreateContractArgs + // HOST_FUNCTION_TYPE_UPLOAD_CONTRACT_WASM: + // Wasm() *[]byte + Type HostFunctionType + _u interface{} +} + +type SorobanAuthorizedFunctionType int32 + +const ( + SOROBAN_AUTHORIZED_FUNCTION_TYPE_CONTRACT_FN SorobanAuthorizedFunctionType = 0 + SOROBAN_AUTHORIZED_FUNCTION_TYPE_CREATE_CONTRACT_HOST_FN SorobanAuthorizedFunctionType = 1 +) + +type SorobanAuthorizedFunction struct { + // The union discriminant Type selects among the following arms: + // SOROBAN_AUTHORIZED_FUNCTION_TYPE_CONTRACT_FN: + // ContractFn() *InvokeContractArgs + // SOROBAN_AUTHORIZED_FUNCTION_TYPE_CREATE_CONTRACT_HOST_FN: + // CreateContractHostFn() *CreateContractArgs + Type SorobanAuthorizedFunctionType + _u interface{} +} + +type SorobanAuthorizedInvocation struct { + Function SorobanAuthorizedFunction + SubInvocations []SorobanAuthorizedInvocation +} + +type SorobanAddressCredentials struct { + Address SCAddress + Nonce Int64 + SignatureExpirationLedger Uint32 + Signature SCVal +} + +type SorobanCredentialsType int32 + +const ( + SOROBAN_CREDENTIALS_SOURCE_ACCOUNT SorobanCredentialsType = 0 + SOROBAN_CREDENTIALS_ADDRESS SorobanCredentialsType = 1 +) + +type SorobanCredentials struct { + // The union discriminant Type selects among the following arms: + // SOROBAN_CREDENTIALS_SOURCE_ACCOUNT: + // void + // SOROBAN_CREDENTIALS_ADDRESS: + // Address() *SorobanAddressCredentials + Type SorobanCredentialsType + _u interface{} +} + +/* +Unit of authorization data for Soroban. + + Represents an authorization for executing the tree of authorized contract + and/or host function calls by the user defined by `credentials`. +*/ +type SorobanAuthorizationEntry struct { + Credentials SorobanCredentials + RootInvocation SorobanAuthorizedInvocation +} + +/* +Upload Wasm, create, and invoke contracts in Soroban. + + Threshold: med + Result: InvokeHostFunctionResult +*/ +type InvokeHostFunctionOp struct { + // Host function to invoke. + HostFunction HostFunction + // Per-address authorizations for this host function. + Auth []SorobanAuthorizationEntry +} + +/* +Extend the TTL of the entries specified in the readOnly footprint + + so they will live at least extendTo ledgers from lcl. + + Threshold: low + Result: ExtendFootprintTTLResult +*/ +type ExtendFootprintTTLOp struct { + Ext ExtensionPoint + ExtendTo Uint32 +} + +/* +Restore the archived entries specified in the readWrite footprint. + + Threshold: low + Result: RestoreFootprintOp +*/ +type RestoreFootprintOp struct { + Ext ExtensionPoint +} + /* An operation is the lowest unit of work that a transaction does */ type Operation struct { // sourceAccount is the account used to run the operation @@ -1897,6 +2252,12 @@ type XdrAnon_Operation_Body struct { // LiquidityPoolDepositOp() *LiquidityPoolDepositOp // LIQUIDITY_POOL_WITHDRAW: // LiquidityPoolWithdrawOp() *LiquidityPoolWithdrawOp + // INVOKE_HOST_FUNCTION: + // InvokeHostFunctionOp() *InvokeHostFunctionOp + // EXTEND_FOOTPRINT_TTL: + // ExtendFootprintTTLOp() *ExtendFootprintTTLOp + // RESTORE_FOOTPRINT: + // RestoreFootprintOp() *RestoreFootprintOp Type OperationType _u interface{} } @@ -1907,6 +2268,10 @@ type HashIDPreimage struct { // OperationID() *XdrAnon_HashIDPreimage_OperationID // ENVELOPE_TYPE_POOL_REVOKE_OP_ID: // RevokeID() *XdrAnon_HashIDPreimage_RevokeID + // ENVELOPE_TYPE_CONTRACT_ID: + // ContractID() *XdrAnon_HashIDPreimage_ContractID + // ENVELOPE_TYPE_SOROBAN_AUTHORIZATION: + // SorobanAuthorization() *XdrAnon_HashIDPreimage_SorobanAuthorization Type EnvelopeType _u interface{} } @@ -1922,6 +2287,16 @@ type XdrAnon_HashIDPreimage_RevokeID struct { LiquidityPoolID PoolID Asset Asset } +type XdrAnon_HashIDPreimage_ContractID struct { + NetworkID Hash + ContractIDPreimage ContractIDPreimage +} +type XdrAnon_HashIDPreimage_SorobanAuthorization struct { + NetworkID Hash + Nonce Int64 + SignatureExpirationLedger Uint32 + Invocation SorobanAuthorizedInvocation +} type MemoType int32 @@ -2008,8 +2383,40 @@ type Preconditions struct { _u interface{} } -// maximum number of operations per transaction -const MAX_OPS_PER_TX = 100 +// Ledger key sets touched by a smart contract transaction. +type LedgerFootprint struct { + ReadOnly []LedgerKey + ReadWrite []LedgerKey +} + +// Resource limits for a Soroban transaction. +// The transaction will fail if it exceeds any of these limits. +type SorobanResources struct { + // The ledger footprint of the transaction. + Footprint LedgerFootprint + // The maximum number of instructions this transaction can use + Instructions Uint32 + // The maximum number of bytes this transaction can read from ledger + ReadBytes Uint32 + // The maximum number of bytes this transaction can write to ledger + WriteBytes Uint32 +} + +// The transaction extension for Soroban. +type SorobanTransactionData struct { + Ext ExtensionPoint + Resources SorobanResources + // Amount of the transaction `fee` allocated to the Soroban resource fees. + // The fraction of `resourceFee` corresponding to `resources` specified + // above is *not* refundable (i.e. fees for instructions, ledger I/O), as + // well as fees for the transaction size. + // The remaining part of the fee is refundable and the charged value is + // based on the actual consumption of refundable resources (events, ledger + // rent bumps). + // The `inclusionFee` used for prioritization of the transaction is defined + // as `tx.fee - resourceFee`. + ResourceFee Int64 +} // TransactionV0 is a transaction with the AccountID discriminant stripped off, // leaving a raw ed25519 public key to identify the source account. This is used @@ -2068,6 +2475,8 @@ type XdrAnon_Transaction_Ext struct { // The union discriminant V selects among the following arms: // 0: // void + // 1: + // SorobanData() *SorobanTransactionData V int32 _u interface{} } @@ -2895,6 +3304,71 @@ type LiquidityPoolWithdrawResult struct { _u interface{} } +type InvokeHostFunctionResultCode int32 + +const ( + // codes considered as "success" for the operation + INVOKE_HOST_FUNCTION_SUCCESS InvokeHostFunctionResultCode = 0 + // codes considered as "failure" for the operation + INVOKE_HOST_FUNCTION_MALFORMED InvokeHostFunctionResultCode = -1 + INVOKE_HOST_FUNCTION_TRAPPED InvokeHostFunctionResultCode = -2 + INVOKE_HOST_FUNCTION_RESOURCE_LIMIT_EXCEEDED InvokeHostFunctionResultCode = -3 + INVOKE_HOST_FUNCTION_ENTRY_ARCHIVED InvokeHostFunctionResultCode = -4 + INVOKE_HOST_FUNCTION_INSUFFICIENT_REFUNDABLE_FEE InvokeHostFunctionResultCode = -5 +) + +type InvokeHostFunctionResult struct { + // The union discriminant Code selects among the following arms: + // INVOKE_HOST_FUNCTION_SUCCESS: + // Success() *Hash + // INVOKE_HOST_FUNCTION_MALFORMED, INVOKE_HOST_FUNCTION_TRAPPED, INVOKE_HOST_FUNCTION_RESOURCE_LIMIT_EXCEEDED, INVOKE_HOST_FUNCTION_ENTRY_ARCHIVED, INVOKE_HOST_FUNCTION_INSUFFICIENT_REFUNDABLE_FEE: + // void + Code InvokeHostFunctionResultCode + _u interface{} +} + +type ExtendFootprintTTLResultCode int32 + +const ( + // codes considered as "success" for the operation + EXTEND_FOOTPRINT_TTL_SUCCESS ExtendFootprintTTLResultCode = 0 + // codes considered as "failure" for the operation + EXTEND_FOOTPRINT_TTL_MALFORMED ExtendFootprintTTLResultCode = -1 + EXTEND_FOOTPRINT_TTL_RESOURCE_LIMIT_EXCEEDED ExtendFootprintTTLResultCode = -2 + EXTEND_FOOTPRINT_TTL_INSUFFICIENT_REFUNDABLE_FEE ExtendFootprintTTLResultCode = -3 +) + +type ExtendFootprintTTLResult struct { + // The union discriminant Code selects among the following arms: + // EXTEND_FOOTPRINT_TTL_SUCCESS: + // void + // EXTEND_FOOTPRINT_TTL_MALFORMED, EXTEND_FOOTPRINT_TTL_RESOURCE_LIMIT_EXCEEDED, EXTEND_FOOTPRINT_TTL_INSUFFICIENT_REFUNDABLE_FEE: + // void + Code ExtendFootprintTTLResultCode + _u interface{} +} + +type RestoreFootprintResultCode int32 + +const ( + // codes considered as "success" for the operation + RESTORE_FOOTPRINT_SUCCESS RestoreFootprintResultCode = 0 + // codes considered as "failure" for the operation + RESTORE_FOOTPRINT_MALFORMED RestoreFootprintResultCode = -1 + RESTORE_FOOTPRINT_RESOURCE_LIMIT_EXCEEDED RestoreFootprintResultCode = -2 + RESTORE_FOOTPRINT_INSUFFICIENT_REFUNDABLE_FEE RestoreFootprintResultCode = -3 +) + +type RestoreFootprintResult struct { + // The union discriminant Code selects among the following arms: + // RESTORE_FOOTPRINT_SUCCESS: + // void + // RESTORE_FOOTPRINT_MALFORMED, RESTORE_FOOTPRINT_RESOURCE_LIMIT_EXCEEDED, RESTORE_FOOTPRINT_INSUFFICIENT_REFUNDABLE_FEE: + // void + Code RestoreFootprintResultCode + _u interface{} +} + /* High level Operation Result */ type OperationResultCode int32 @@ -2974,6 +3448,12 @@ type XdrAnon_OperationResult_Tr struct { // LiquidityPoolDepositResult() *LiquidityPoolDepositResult // LIQUIDITY_POOL_WITHDRAW: // LiquidityPoolWithdrawResult() *LiquidityPoolWithdrawResult + // INVOKE_HOST_FUNCTION: + // InvokeHostFunctionResult() *InvokeHostFunctionResult + // EXTEND_FOOTPRINT_TTL: + // ExtendFootprintTTLResult() *ExtendFootprintTTLResult + // RESTORE_FOOTPRINT: + // RestoreFootprintResult() *RestoreFootprintResult Type OperationType _u interface{} } @@ -3017,6 +3497,8 @@ const ( TxBAD_MIN_SEQ_AGE_OR_GAP TransactionResultCode = -15 // precondition is invalid TxMALFORMED TransactionResultCode = -16 + // soroban-specific preconditions were not met + TxSOROBAN_INVALID TransactionResultCode = -17 ) // InnerTransactionResult must be binary compatible with TransactionResult @@ -3031,7 +3513,7 @@ type XdrAnon_InnerTransactionResult_Result struct { // The union discriminant Code selects among the following arms: // TxSUCCESS, TxFAILED: // Results() *[]OperationResult - // TxTOO_EARLY, TxTOO_LATE, TxMISSING_OPERATION, TxBAD_SEQ, TxBAD_AUTH, TxINSUFFICIENT_BALANCE, TxNO_ACCOUNT, TxINSUFFICIENT_FEE, TxBAD_AUTH_EXTRA, TxINTERNAL_ERROR, TxNOT_SUPPORTED, TxBAD_SPONSORSHIP, TxBAD_MIN_SEQ_AGE_OR_GAP, TxMALFORMED: + // TxTOO_EARLY, TxTOO_LATE, TxMISSING_OPERATION, TxBAD_SEQ, TxBAD_AUTH, TxINSUFFICIENT_BALANCE, TxNO_ACCOUNT, TxINSUFFICIENT_FEE, TxBAD_AUTH_EXTRA, TxINTERNAL_ERROR, TxNOT_SUPPORTED, TxBAD_SPONSORSHIP, TxBAD_MIN_SEQ_AGE_OR_GAP, TxMALFORMED, TxSOROBAN_INVALID: // void Code TransactionResultCode _u interface{} @@ -3065,7 +3547,7 @@ type XdrAnon_TransactionResult_Result struct { // InnerResultPair() *InnerTransactionResultPair // TxSUCCESS, TxFAILED: // Results() *[]OperationResult - // TxTOO_EARLY, TxTOO_LATE, TxMISSING_OPERATION, TxBAD_SEQ, TxBAD_AUTH, TxINSUFFICIENT_BALANCE, TxNO_ACCOUNT, TxINSUFFICIENT_FEE, TxBAD_AUTH_EXTRA, TxINTERNAL_ERROR, TxNOT_SUPPORTED, TxBAD_SPONSORSHIP, TxBAD_MIN_SEQ_AGE_OR_GAP, TxMALFORMED: + // TxTOO_EARLY, TxTOO_LATE, TxMISSING_OPERATION, TxBAD_SEQ, TxBAD_AUTH, TxINSUFFICIENT_BALANCE, TxNO_ACCOUNT, TxINSUFFICIENT_FEE, TxBAD_AUTH_EXTRA, TxINTERNAL_ERROR, TxNOT_SUPPORTED, TxBAD_SPONSORSHIP, TxBAD_MIN_SEQ_AGE_OR_GAP, TxMALFORMED, TxSOROBAN_INVALID: // void Code TransactionResultCode _u interface{} @@ -3092,6 +3574,10 @@ type Uint64 = uint64 type Int64 = int64 +type TimePoint = Uint64 + +type Duration = Uint64 + // An ExtensionPoint is always marshaled as a 32-bit 0 value. At a // later point, it can be replaced by a different union so as to // extend a structure. @@ -3165,6 +3651,8 @@ type SignatureHint = [4]byte type NodeID = PublicKey +type AccountID = PublicKey + type Curve25519Secret struct { Key [32]byte } @@ -3181,73 +3669,816 @@ type HmacSha256Mac struct { Mac [32]byte } -type BitmapIndex struct { - FirstBit Uint32 - LastBit Uint32 - Bitmap Value -} +type SCEnvMetaKind int32 -type TrieIndex struct { - // goxdr gives an error if we simply use "version" as an identifier - Version_ Uint32 - Root TrieNode +const ( + SC_ENV_META_KIND_INTERFACE_VERSION SCEnvMetaKind = 0 +) + +type SCEnvMetaEntry struct { + // The union discriminant Kind selects among the following arms: + // SC_ENV_META_KIND_INTERFACE_VERSION: + // InterfaceVersion() *Uint64 + Kind SCEnvMetaKind + _u interface{} } -type TrieNodeChild struct { - Key [1]byte - Node TrieNode +type SCMetaV0 struct { + Key string + Val string } -type TrieNode struct { - Prefix Value - Value Value - Children []TrieNodeChild +type SCMetaKind int32 + +const ( + SC_META_V0 SCMetaKind = 0 +) + +type SCMetaEntry struct { + // The union discriminant Kind selects among the following arms: + // SC_META_V0: + // V0() *SCMetaV0 + Kind SCMetaKind + _u interface{} } -type SerializedLedgerCloseMeta struct { - // The union discriminant V selects among the following arms: - // 0: - // V0() *LedgerCloseMeta - V int32 - _u interface{} +const SC_SPEC_DOC_LIMIT = 1024 + +type SCSpecType int32 + +const ( + SC_SPEC_TYPE_VAL SCSpecType = 0 + // Types with no parameters. + SC_SPEC_TYPE_BOOL SCSpecType = 1 + SC_SPEC_TYPE_VOID SCSpecType = 2 + SC_SPEC_TYPE_ERROR SCSpecType = 3 + SC_SPEC_TYPE_U32 SCSpecType = 4 + SC_SPEC_TYPE_I32 SCSpecType = 5 + SC_SPEC_TYPE_U64 SCSpecType = 6 + SC_SPEC_TYPE_I64 SCSpecType = 7 + SC_SPEC_TYPE_TIMEPOINT SCSpecType = 8 + SC_SPEC_TYPE_DURATION SCSpecType = 9 + SC_SPEC_TYPE_U128 SCSpecType = 10 + SC_SPEC_TYPE_I128 SCSpecType = 11 + SC_SPEC_TYPE_U256 SCSpecType = 12 + SC_SPEC_TYPE_I256 SCSpecType = 13 + SC_SPEC_TYPE_BYTES SCSpecType = 14 + SC_SPEC_TYPE_STRING SCSpecType = 16 + SC_SPEC_TYPE_SYMBOL SCSpecType = 17 + SC_SPEC_TYPE_ADDRESS SCSpecType = 19 + // Types with parameters. + SC_SPEC_TYPE_OPTION SCSpecType = 1000 + SC_SPEC_TYPE_RESULT SCSpecType = 1001 + SC_SPEC_TYPE_VEC SCSpecType = 1002 + SC_SPEC_TYPE_MAP SCSpecType = 1004 + SC_SPEC_TYPE_TUPLE SCSpecType = 1005 + SC_SPEC_TYPE_BYTES_N SCSpecType = 1006 + // User defined types. + SC_SPEC_TYPE_UDT SCSpecType = 2000 +) + +type SCSpecTypeOption struct { + ValueType SCSpecTypeDef } -// -// Helper types and generated marshaling functions -// +type SCSpecTypeResult struct { + OkType SCSpecTypeDef + ErrorType SCSpecTypeDef +} -type XdrType_Value struct { - XdrVecOpaque +type SCSpecTypeVec struct { + ElementType SCSpecTypeDef } -func XDR_Value(v *Value) XdrType_Value { - return XdrType_Value{XdrVecOpaque{v, 0xffffffff}} +type SCSpecTypeMap struct { + KeyType SCSpecTypeDef + ValueType SCSpecTypeDef } -func (XdrType_Value) XdrTypeName() string { return "Value" } -func (v XdrType_Value) XdrUnwrap() XdrType { return v.XdrVecOpaque } -type XdrType_SCPBallot = *SCPBallot +type SCSpecTypeTuple struct { + ValueTypes []SCSpecTypeDef // bound 12 +} -func (v *SCPBallot) XdrPointer() interface{} { return v } -func (SCPBallot) XdrTypeName() string { return "SCPBallot" } -func (v SCPBallot) XdrValue() interface{} { return v } -func (v *SCPBallot) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -func (v *SCPBallot) XdrRecurse(x XDR, name string) { - if name != "" { - name = x.Sprintf("%s.", name) - } - x.Marshal(x.Sprintf("%scounter", name), XDR_Uint32(&v.Counter)) - x.Marshal(x.Sprintf("%svalue", name), XDR_Value(&v.Value)) +type SCSpecTypeBytesN struct { + N Uint32 } -func XDR_SCPBallot(v *SCPBallot) *SCPBallot { return v } -var _XdrNames_SCPStatementType = map[int32]string{ - int32(SCP_ST_PREPARE): "SCP_ST_PREPARE", - int32(SCP_ST_CONFIRM): "SCP_ST_CONFIRM", - int32(SCP_ST_EXTERNALIZE): "SCP_ST_EXTERNALIZE", - int32(SCP_ST_NOMINATE): "SCP_ST_NOMINATE", +type SCSpecTypeUDT struct { + Name string // bound 60 } -var _XdrValues_SCPStatementType = map[string]int32{ + +type SCSpecTypeDef struct { + // The union discriminant Type selects among the following arms: + // SC_SPEC_TYPE_VAL, SC_SPEC_TYPE_BOOL, SC_SPEC_TYPE_VOID, SC_SPEC_TYPE_ERROR, SC_SPEC_TYPE_U32, SC_SPEC_TYPE_I32, SC_SPEC_TYPE_U64, SC_SPEC_TYPE_I64, SC_SPEC_TYPE_TIMEPOINT, SC_SPEC_TYPE_DURATION, SC_SPEC_TYPE_U128, SC_SPEC_TYPE_I128, SC_SPEC_TYPE_U256, SC_SPEC_TYPE_I256, SC_SPEC_TYPE_BYTES, SC_SPEC_TYPE_STRING, SC_SPEC_TYPE_SYMBOL, SC_SPEC_TYPE_ADDRESS: + // void + // SC_SPEC_TYPE_OPTION: + // Option() *SCSpecTypeOption + // SC_SPEC_TYPE_RESULT: + // Result() *SCSpecTypeResult + // SC_SPEC_TYPE_VEC: + // Vec() *SCSpecTypeVec + // SC_SPEC_TYPE_MAP: + // Map() *SCSpecTypeMap + // SC_SPEC_TYPE_TUPLE: + // Tuple() *SCSpecTypeTuple + // SC_SPEC_TYPE_BYTES_N: + // BytesN() *SCSpecTypeBytesN + // SC_SPEC_TYPE_UDT: + // Udt() *SCSpecTypeUDT + Type SCSpecType + _u interface{} +} + +type SCSpecUDTStructFieldV0 struct { + Doc string // bound SC_SPEC_DOC_LIMIT + Name string // bound 30 + Type SCSpecTypeDef +} + +type SCSpecUDTStructV0 struct { + Doc string // bound SC_SPEC_DOC_LIMIT + Lib string // bound 80 + Name string // bound 60 + Fields []SCSpecUDTStructFieldV0 // bound 40 +} + +type SCSpecUDTUnionCaseVoidV0 struct { + Doc string // bound SC_SPEC_DOC_LIMIT + Name string // bound 60 +} + +type SCSpecUDTUnionCaseTupleV0 struct { + Doc string // bound SC_SPEC_DOC_LIMIT + Name string // bound 60 + Type []SCSpecTypeDef // bound 12 +} + +type SCSpecUDTUnionCaseV0Kind int32 + +const ( + SC_SPEC_UDT_UNION_CASE_VOID_V0 SCSpecUDTUnionCaseV0Kind = 0 + SC_SPEC_UDT_UNION_CASE_TUPLE_V0 SCSpecUDTUnionCaseV0Kind = 1 +) + +type SCSpecUDTUnionCaseV0 struct { + // The union discriminant Kind selects among the following arms: + // SC_SPEC_UDT_UNION_CASE_VOID_V0: + // VoidCase() *SCSpecUDTUnionCaseVoidV0 + // SC_SPEC_UDT_UNION_CASE_TUPLE_V0: + // TupleCase() *SCSpecUDTUnionCaseTupleV0 + Kind SCSpecUDTUnionCaseV0Kind + _u interface{} +} + +type SCSpecUDTUnionV0 struct { + Doc string // bound SC_SPEC_DOC_LIMIT + Lib string // bound 80 + Name string // bound 60 + Cases []SCSpecUDTUnionCaseV0 // bound 50 +} + +type SCSpecUDTEnumCaseV0 struct { + Doc string // bound SC_SPEC_DOC_LIMIT + Name string // bound 60 + Value Uint32 +} + +type SCSpecUDTEnumV0 struct { + Doc string // bound SC_SPEC_DOC_LIMIT + Lib string // bound 80 + Name string // bound 60 + Cases []SCSpecUDTEnumCaseV0 // bound 50 +} + +type SCSpecUDTErrorEnumCaseV0 struct { + Doc string // bound SC_SPEC_DOC_LIMIT + Name string // bound 60 + Value Uint32 +} + +type SCSpecUDTErrorEnumV0 struct { + Doc string // bound SC_SPEC_DOC_LIMIT + Lib string // bound 80 + Name string // bound 60 + Cases []SCSpecUDTErrorEnumCaseV0 // bound 50 +} + +type SCSpecFunctionInputV0 struct { + Doc string // bound SC_SPEC_DOC_LIMIT + Name string // bound 30 + Type SCSpecTypeDef +} + +type SCSpecFunctionV0 struct { + Doc string // bound SC_SPEC_DOC_LIMIT + Name SCSymbol + Inputs []SCSpecFunctionInputV0 // bound 10 + Outputs []SCSpecTypeDef // bound 1 +} + +type SCSpecEntryKind int32 + +const ( + SC_SPEC_ENTRY_FUNCTION_V0 SCSpecEntryKind = 0 + SC_SPEC_ENTRY_UDT_STRUCT_V0 SCSpecEntryKind = 1 + SC_SPEC_ENTRY_UDT_UNION_V0 SCSpecEntryKind = 2 + SC_SPEC_ENTRY_UDT_ENUM_V0 SCSpecEntryKind = 3 + SC_SPEC_ENTRY_UDT_ERROR_ENUM_V0 SCSpecEntryKind = 4 +) + +type SCSpecEntry struct { + // The union discriminant Kind selects among the following arms: + // SC_SPEC_ENTRY_FUNCTION_V0: + // FunctionV0() *SCSpecFunctionV0 + // SC_SPEC_ENTRY_UDT_STRUCT_V0: + // UdtStructV0() *SCSpecUDTStructV0 + // SC_SPEC_ENTRY_UDT_UNION_V0: + // UdtUnionV0() *SCSpecUDTUnionV0 + // SC_SPEC_ENTRY_UDT_ENUM_V0: + // UdtEnumV0() *SCSpecUDTEnumV0 + // SC_SPEC_ENTRY_UDT_ERROR_ENUM_V0: + // UdtErrorEnumV0() *SCSpecUDTErrorEnumV0 + Kind SCSpecEntryKind + _u interface{} +} + +type SCValType int32 + +const ( + SCV_BOOL SCValType = 0 + SCV_VOID SCValType = 1 + SCV_ERROR SCValType = 2 + // 32 bits is the smallest type in WASM or XDR; no need for u8/u16. + SCV_U32 SCValType = 3 + SCV_I32 SCValType = 4 + // 64 bits is naturally supported by both WASM and XDR also. + SCV_U64 SCValType = 5 + SCV_I64 SCValType = 6 + // Time-related u64 subtypes with their own functions and formatting. + SCV_TIMEPOINT SCValType = 7 + SCV_DURATION SCValType = 8 + // 128 bits is naturally supported by Rust and we use it for Soroban + // fixed-point arithmetic prices / balances / similar "quantities". These + // are represented in XDR as a pair of 2 u64s. + SCV_U128 SCValType = 9 + SCV_I128 SCValType = 10 + // 256 bits is the size of sha256 output, ed25519 keys, and the EVM machine + // word, so for interop use we include this even though it requires a small + // amount of Rust guest and/or host library code. + SCV_U256 SCValType = 11 + SCV_I256 SCValType = 12 + // Bytes come in 3 flavors, 2 of which have meaningfully different + // formatting and validity-checking / domain-restriction. + SCV_BYTES SCValType = 13 + SCV_STRING SCValType = 14 + SCV_SYMBOL SCValType = 15 + // Vecs and maps are just polymorphic containers of other ScVals. + SCV_VEC SCValType = 16 + SCV_MAP SCValType = 17 + // Address is the universal identifier for contracts and classic + // accounts. + SCV_ADDRESS SCValType = 18 + // The following are the internal SCVal variants that are not + // exposed to the contracts. + SCV_CONTRACT_INSTANCE SCValType = 19 + // SCV_LEDGER_KEY_CONTRACT_INSTANCE and SCV_LEDGER_KEY_NONCE are unique + // symbolic SCVals used as the key for ledger entries for a contract's + // instance and an address' nonce, respectively. + SCV_LEDGER_KEY_CONTRACT_INSTANCE SCValType = 20 + SCV_LEDGER_KEY_NONCE SCValType = 21 +) + +type SCErrorType int32 + +const ( + // Contract-specific, user-defined codes. + SCE_CONTRACT SCErrorType = 0 + // Errors while interpreting WASM bytecode. + SCE_WASM_VM SCErrorType = 1 + // Errors in the contract's host context. + SCE_CONTEXT SCErrorType = 2 + // Errors accessing host storage. + SCE_STORAGE SCErrorType = 3 + // Errors working with host objects. + SCE_OBJECT SCErrorType = 4 + // Errors in cryptographic operations. + SCE_CRYPTO SCErrorType = 5 + // Errors while emitting events. + SCE_EVENTS SCErrorType = 6 + // Errors relating to budget limits. + SCE_BUDGET SCErrorType = 7 + // Errors working with host values or SCVals. + SCE_VALUE SCErrorType = 8 + // Errors from the authentication subsystem. + SCE_AUTH SCErrorType = 9 +) + +type SCErrorCode int32 + +const ( + // Some arithmetic was undefined (overflow, divide-by-zero). + SCEC_ARITH_DOMAIN SCErrorCode = 0 + // Something was indexed beyond its bounds. + SCEC_INDEX_BOUNDS SCErrorCode = 1 + // User provided some otherwise-bad data. + SCEC_INVALID_INPUT SCErrorCode = 2 + // Some value was required but not provided. + SCEC_MISSING_VALUE SCErrorCode = 3 + // Some value was provided where not allowed. + SCEC_EXISTING_VALUE SCErrorCode = 4 + // Some arbitrary limit -- gas or otherwise -- was hit. + SCEC_EXCEEDED_LIMIT SCErrorCode = 5 + // Data was valid but action requested was not. + SCEC_INVALID_ACTION SCErrorCode = 6 + // The host detected an error in its own logic. + SCEC_INTERNAL_ERROR SCErrorCode = 7 + // Some type wasn't as expected. + SCEC_UNEXPECTED_TYPE SCErrorCode = 8 + // Something's size wasn't as expected. + SCEC_UNEXPECTED_SIZE SCErrorCode = 9 +) + +type SCError struct { + // The union discriminant Type selects among the following arms: + // SCE_CONTRACT: + // ContractCode() *Uint32 + // SCE_WASM_VM, SCE_CONTEXT, SCE_STORAGE, SCE_OBJECT, SCE_CRYPTO, SCE_EVENTS, SCE_BUDGET, SCE_VALUE, SCE_AUTH: + // Code() *SCErrorCode + Type SCErrorType + _u interface{} +} + +type UInt128Parts struct { + Hi Uint64 + Lo Uint64 +} + +// A signed int128 has a high sign bit and 127 value bits. We break it into a +// signed high int64 (that carries the sign bit and the high 63 value bits) and +// a low unsigned uint64 that carries the low 64 bits. This will sort in +// generated code in the same order the underlying int128 sorts. +type Int128Parts struct { + Hi Int64 + Lo Uint64 +} + +type UInt256Parts struct { + Hi_hi Uint64 + Hi_lo Uint64 + Lo_hi Uint64 + Lo_lo Uint64 +} + +// A signed int256 has a high sign bit and 255 value bits. We break it into a +// signed high int64 (that carries the sign bit and the high 63 value bits) and +// three low unsigned `uint64`s that carry the lower bits. This will sort in +// generated code in the same order the underlying int256 sorts. +type Int256Parts struct { + Hi_hi Int64 + Hi_lo Uint64 + Lo_hi Uint64 + Lo_lo Uint64 +} + +type ContractExecutableType int32 + +const ( + CONTRACT_EXECUTABLE_WASM ContractExecutableType = 0 + CONTRACT_EXECUTABLE_STELLAR_ASSET ContractExecutableType = 1 +) + +type ContractExecutable struct { + // The union discriminant Type selects among the following arms: + // CONTRACT_EXECUTABLE_WASM: + // Wasm_hash() *Hash + // CONTRACT_EXECUTABLE_STELLAR_ASSET: + // void + Type ContractExecutableType + _u interface{} +} + +type SCAddressType int32 + +const ( + SC_ADDRESS_TYPE_ACCOUNT SCAddressType = 0 + SC_ADDRESS_TYPE_CONTRACT SCAddressType = 1 +) + +type SCAddress struct { + // The union discriminant Type selects among the following arms: + // SC_ADDRESS_TYPE_ACCOUNT: + // AccountId() *AccountID + // SC_ADDRESS_TYPE_CONTRACT: + // ContractId() *Hash + Type SCAddressType + _u interface{} +} + +const SCSYMBOL_LIMIT = 32 + +type SCVec = []SCVal + +type SCMap = []SCMapEntry + +type SCBytes = []byte + +type SCString = string + +type SCSymbol = string // bound SCSYMBOL_LIMIT + +type SCNonceKey struct { + Nonce Int64 +} + +type SCContractInstance struct { + Executable ContractExecutable + Storage *SCMap +} + +type SCVal struct { + // The union discriminant Type selects among the following arms: + // SCV_BOOL: + // B() *bool + // SCV_VOID: + // void + // SCV_ERROR: + // Error() *SCError + // SCV_U32: + // U32() *Uint32 + // SCV_I32: + // I32() *Int32 + // SCV_U64: + // U64() *Uint64 + // SCV_I64: + // I64() *Int64 + // SCV_TIMEPOINT: + // Timepoint() *TimePoint + // SCV_DURATION: + // Duration() *Duration + // SCV_U128: + // U128() *UInt128Parts + // SCV_I128: + // I128() *Int128Parts + // SCV_U256: + // U256() *UInt256Parts + // SCV_I256: + // I256() *Int256Parts + // SCV_BYTES: + // Bytes() *SCBytes + // SCV_STRING: + // Str() *SCString + // SCV_SYMBOL: + // Sym() *SCSymbol + // SCV_VEC: + // Vec() **SCVec + // SCV_MAP: + // Map() **SCMap + // SCV_ADDRESS: + // Address() *SCAddress + // SCV_LEDGER_KEY_CONTRACT_INSTANCE: + // void + // SCV_LEDGER_KEY_NONCE: + // Nonce_key() *SCNonceKey + // SCV_CONTRACT_INSTANCE: + // Instance() *SCContractInstance + Type SCValType + _u interface{} +} + +type SCMapEntry struct { + Key SCVal + Val SCVal +} + +type StoredTransactionSet struct { + // The union discriminant V selects among the following arms: + // 0: + // TxSet() *TransactionSet + // 1: + // GeneralizedTxSet() *GeneralizedTransactionSet + V int32 + _u interface{} +} + +type StoredDebugTransactionSet struct { + TxSet StoredTransactionSet + LedgerSeq Uint32 + ScpValue StellarValue +} + +type PersistedSCPStateV0 struct { + ScpEnvelopes []SCPEnvelope + QuorumSets []SCPQuorumSet + TxSets []StoredTransactionSet +} + +type PersistedSCPStateV1 struct { + // Tx sets are saved separately + ScpEnvelopes []SCPEnvelope + QuorumSets []SCPQuorumSet +} + +type PersistedSCPState struct { + // The union discriminant V selects among the following arms: + // 0: + // V0() *PersistedSCPStateV0 + // 1: + // V1() *PersistedSCPStateV1 + V int32 + _u interface{} +} + +// General “Soroban execution lane” settings +type ConfigSettingContractExecutionLanesV0 struct { + // maximum number of Soroban transactions per ledger + LedgerMaxTxCount Uint32 +} + +// "Compute" settings for contracts (instructions and memory). +type ConfigSettingContractComputeV0 struct { + // Maximum instructions per ledger + LedgerMaxInstructions Int64 + // Maximum instructions per transaction + TxMaxInstructions Int64 + // Cost of 10000 instructions + FeeRatePerInstructionsIncrement Int64 + // Memory limit per transaction. Unlike instructions, there is no fee + // for memory, just the limit. + TxMemoryLimit Uint32 +} + +// Ledger access settings for contracts. +type ConfigSettingContractLedgerCostV0 struct { + // Maximum number of ledger entry read operations per ledger + LedgerMaxReadLedgerEntries Uint32 + // Maximum number of bytes that can be read per ledger + LedgerMaxReadBytes Uint32 + // Maximum number of ledger entry write operations per ledger + LedgerMaxWriteLedgerEntries Uint32 + // Maximum number of bytes that can be written per ledger + LedgerMaxWriteBytes Uint32 + // Maximum number of ledger entry read operations per transaction + TxMaxReadLedgerEntries Uint32 + // Maximum number of bytes that can be read per transaction + TxMaxReadBytes Uint32 + // Maximum number of ledger entry write operations per transaction + TxMaxWriteLedgerEntries Uint32 + // Maximum number of bytes that can be written per transaction + TxMaxWriteBytes Uint32 + // Fee per ledger entry read + FeeReadLedgerEntry Int64 + // Fee per ledger entry write + FeeWriteLedgerEntry Int64 + // Fee for reading 1KB + FeeRead1KB Int64 + // The following parameters determine the write fee per 1KB. + // Write fee grows linearly until bucket list reaches this size + BucketListTargetSizeBytes Int64 + // Fee per 1KB write when the bucket list is empty + WriteFee1KBBucketListLow Int64 + // Fee per 1KB write when the bucket list has reached `bucketListTargetSizeBytes` + WriteFee1KBBucketListHigh Int64 + // Write fee multiplier for any additional data past the first `bucketListTargetSizeBytes` + BucketListWriteFeeGrowthFactor Uint32 +} + +// Historical data (pushed to core archives) settings for contracts. +type ConfigSettingContractHistoricalDataV0 struct { + // Fee for storing 1KB in archives + FeeHistorical1KB Int64 +} + +// Contract event-related settings. +type ConfigSettingContractEventsV0 struct { + // Maximum size of events that a contract call can emit. + TxMaxContractEventsSizeBytes Uint32 + // Fee for generating 1KB of contract events. + FeeContractEvents1KB Int64 +} + +// Bandwidth related data settings for contracts. +// We consider bandwidth to only be consumed by the transaction envelopes, hence +// this concerns only transaction sizes. +type ConfigSettingContractBandwidthV0 struct { + // Maximum sum of all transaction sizes in the ledger in bytes + LedgerMaxTxsSizeBytes Uint32 + // Maximum size in bytes for a transaction + TxMaxSizeBytes Uint32 + // Fee for 1 KB of transaction size + FeeTxSize1KB Int64 +} + +type ContractCostType int32 + +const ( + // Cost of running 1 wasm instruction + WasmInsnExec ContractCostType = 0 + // Cost of allocating a slice of memory (in bytes) + MemAlloc ContractCostType = 1 + // Cost of copying a slice of bytes into a pre-allocated memory + MemCpy ContractCostType = 2 + // Cost of comparing two slices of memory + MemCmp ContractCostType = 3 + // Cost of a host function dispatch, not including the actual work done by + // the function nor the cost of VM invocation machinary + DispatchHostFunction ContractCostType = 4 + // Cost of visiting a host object from the host object storage. Exists to + // make sure some baseline cost coverage, i.e. repeatly visiting objects + // by the guest will always incur some charges. + VisitObject ContractCostType = 5 + // Cost of serializing an xdr object to bytes + ValSer ContractCostType = 6 + // Cost of deserializing an xdr object from bytes + ValDeser ContractCostType = 7 + // Cost of computing the sha256 hash from bytes + ComputeSha256Hash ContractCostType = 8 + // Cost of computing the ed25519 pubkey from bytes + ComputeEd25519PubKey ContractCostType = 9 + // Cost of verifying ed25519 signature of a payload. + VerifyEd25519Sig ContractCostType = 10 + // Cost of instantiation a VM from wasm bytes code. + VmInstantiation ContractCostType = 11 + // Cost of instantiation a VM from a cached state. + VmCachedInstantiation ContractCostType = 12 + // Cost of invoking a function on the VM. If the function is a host function, + // additional cost will be covered by `DispatchHostFunction`. + InvokeVmFunction ContractCostType = 13 + // Cost of computing a keccak256 hash from bytes. + ComputeKeccak256Hash ContractCostType = 14 + // Cost of computing an ECDSA secp256k1 signature from bytes. + ComputeEcdsaSecp256k1Sig ContractCostType = 15 + // Cost of recovering an ECDSA secp256k1 key from a signature. + RecoverEcdsaSecp256k1Key ContractCostType = 16 + // Cost of int256 addition (`+`) and subtraction (`-`) operations + Int256AddSub ContractCostType = 17 + // Cost of int256 multiplication (`*`) operation + Int256Mul ContractCostType = 18 + // Cost of int256 division (`/`) operation + Int256Div ContractCostType = 19 + // Cost of int256 power (`exp`) operation + Int256Pow ContractCostType = 20 + // Cost of int256 shift (`shl`, `shr`) operation + Int256Shift ContractCostType = 21 + // Cost of drawing random bytes using a ChaCha20 PRNG + ChaCha20DrawBytes ContractCostType = 22 +) + +type ContractCostParamEntry struct { + // use `ext` to add more terms (e.g. higher order polynomials) in the future + Ext ExtensionPoint + ConstTerm Int64 + LinearTerm Int64 +} + +type StateArchivalSettings struct { + MaxEntryTTL Uint32 + MinTemporaryTTL Uint32 + MinPersistentTTL Uint32 + // rent_fee = wfee_rate_average / rent_rate_denominator_for_type + PersistentRentRateDenominator Int64 + TempRentRateDenominator Int64 + // max number of entries that emit archival meta in a single ledger + MaxEntriesToArchive Uint32 + // Number of snapshots to use when calculating average BucketList size + BucketListSizeWindowSampleSize Uint32 + // Maximum number of bytes that we scan for eviction per ledger + EvictionScanSize Uint64 + // Lowest BucketList level to be scanned to evict entries + StartingEvictionScanLevel Uint32 +} + +type EvictionIterator struct { + BucketListLevel Uint32 + IsCurrBucket bool + BucketFileOffset Uint64 +} + +// limits the ContractCostParams size to 20kB +const CONTRACT_COST_COUNT_LIMIT = 1024 + +type ContractCostParams = []ContractCostParamEntry // bound CONTRACT_COST_COUNT_LIMIT + +// Identifiers of all the network settings. +type ConfigSettingID int32 + +const ( + CONFIG_SETTING_CONTRACT_MAX_SIZE_BYTES ConfigSettingID = 0 + CONFIG_SETTING_CONTRACT_COMPUTE_V0 ConfigSettingID = 1 + CONFIG_SETTING_CONTRACT_LEDGER_COST_V0 ConfigSettingID = 2 + CONFIG_SETTING_CONTRACT_HISTORICAL_DATA_V0 ConfigSettingID = 3 + CONFIG_SETTING_CONTRACT_EVENTS_V0 ConfigSettingID = 4 + CONFIG_SETTING_CONTRACT_BANDWIDTH_V0 ConfigSettingID = 5 + CONFIG_SETTING_CONTRACT_COST_PARAMS_CPU_INSTRUCTIONS ConfigSettingID = 6 + CONFIG_SETTING_CONTRACT_COST_PARAMS_MEMORY_BYTES ConfigSettingID = 7 + CONFIG_SETTING_CONTRACT_DATA_KEY_SIZE_BYTES ConfigSettingID = 8 + CONFIG_SETTING_CONTRACT_DATA_ENTRY_SIZE_BYTES ConfigSettingID = 9 + CONFIG_SETTING_STATE_ARCHIVAL ConfigSettingID = 10 + CONFIG_SETTING_CONTRACT_EXECUTION_LANES ConfigSettingID = 11 + CONFIG_SETTING_BUCKETLIST_SIZE_WINDOW ConfigSettingID = 12 + CONFIG_SETTING_EVICTION_ITERATOR ConfigSettingID = 13 +) + +type ConfigSettingEntry struct { + // The union discriminant ConfigSettingID selects among the following arms: + // CONFIG_SETTING_CONTRACT_MAX_SIZE_BYTES: + // ContractMaxSizeBytes() *Uint32 + // CONFIG_SETTING_CONTRACT_COMPUTE_V0: + // ContractCompute() *ConfigSettingContractComputeV0 + // CONFIG_SETTING_CONTRACT_LEDGER_COST_V0: + // ContractLedgerCost() *ConfigSettingContractLedgerCostV0 + // CONFIG_SETTING_CONTRACT_HISTORICAL_DATA_V0: + // ContractHistoricalData() *ConfigSettingContractHistoricalDataV0 + // CONFIG_SETTING_CONTRACT_EVENTS_V0: + // ContractEvents() *ConfigSettingContractEventsV0 + // CONFIG_SETTING_CONTRACT_BANDWIDTH_V0: + // ContractBandwidth() *ConfigSettingContractBandwidthV0 + // CONFIG_SETTING_CONTRACT_COST_PARAMS_CPU_INSTRUCTIONS: + // ContractCostParamsCpuInsns() *ContractCostParams + // CONFIG_SETTING_CONTRACT_COST_PARAMS_MEMORY_BYTES: + // ContractCostParamsMemBytes() *ContractCostParams + // CONFIG_SETTING_CONTRACT_DATA_KEY_SIZE_BYTES: + // ContractDataKeySizeBytes() *Uint32 + // CONFIG_SETTING_CONTRACT_DATA_ENTRY_SIZE_BYTES: + // ContractDataEntrySizeBytes() *Uint32 + // CONFIG_SETTING_STATE_ARCHIVAL: + // StateArchivalSettings() *StateArchivalSettings + // CONFIG_SETTING_CONTRACT_EXECUTION_LANES: + // ContractExecutionLanes() *ConfigSettingContractExecutionLanesV0 + // CONFIG_SETTING_BUCKETLIST_SIZE_WINDOW: + // BucketListSizeWindow() *[]Uint64 + // CONFIG_SETTING_EVICTION_ITERATOR: + // EvictionIterator() *EvictionIterator + ConfigSettingID ConfigSettingID + _u interface{} +} + +type BitmapIndex struct { + FirstBit Uint32 + LastBit Uint32 + Bitmap Value +} + +type TrieIndex struct { + // goxdr gives an error if we simply use "version" as an identifier + Version_ Uint32 + Root TrieNode +} + +type TrieNodeChild struct { + Key [1]byte + Node TrieNode +} + +type TrieNode struct { + Prefix Value + Value Value + Children []TrieNodeChild +} + +type SerializedLedgerCloseMeta struct { + // The union discriminant V selects among the following arms: + // 0: + // V0() *LedgerCloseMeta + V int32 + _u interface{} +} + +// +// Helper types and generated marshaling functions +// + +type XdrType_Value struct { + XdrVecOpaque +} + +func XDR_Value(v *Value) XdrType_Value { + return XdrType_Value{XdrVecOpaque{v, 0xffffffff}} +} +func (XdrType_Value) XdrTypeName() string { return "Value" } +func (v XdrType_Value) XdrUnwrap() XdrType { return v.XdrVecOpaque } + +type XdrType_SCPBallot = *SCPBallot + +func (v *SCPBallot) XdrPointer() interface{} { return v } +func (SCPBallot) XdrTypeName() string { return "SCPBallot" } +func (v SCPBallot) XdrValue() interface{} { return v } +func (v *SCPBallot) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v *SCPBallot) XdrRecurse(x XDR, name string) { + if name != "" { + name = x.Sprintf("%s.", name) + } + x.Marshal(x.Sprintf("%scounter", name), XDR_Uint32(&v.Counter)) + x.Marshal(x.Sprintf("%svalue", name), XDR_Value(&v.Value)) +} +func XDR_SCPBallot(v *SCPBallot) *SCPBallot { return v } + +var _XdrNames_SCPStatementType = map[int32]string{ + int32(SCP_ST_PREPARE): "SCP_ST_PREPARE", + int32(SCP_ST_CONFIRM): "SCP_ST_CONFIRM", + int32(SCP_ST_EXTERNALIZE): "SCP_ST_EXTERNALIZE", + int32(SCP_ST_NOMINATE): "SCP_ST_NOMINATE", +} +var _XdrValues_SCPStatementType = map[string]int32{ "SCP_ST_PREPARE": int32(SCP_ST_PREPARE), "SCP_ST_CONFIRM": int32(SCP_ST_CONFIRM), "SCP_ST_EXTERNALIZE": int32(SCP_ST_EXTERNALIZE), @@ -3803,16 +5034,6 @@ func (v *SCPQuorumSet) XdrRecurse(x XDR, name string) { } func XDR_SCPQuorumSet(v *SCPQuorumSet) *SCPQuorumSet { return v } -type XdrType_AccountID struct { - XdrType_PublicKey -} - -func XDR_AccountID(v *AccountID) XdrType_AccountID { - return XdrType_AccountID{XDR_PublicKey(v)} -} -func (XdrType_AccountID) XdrTypeName() string { return "AccountID" } -func (v XdrType_AccountID) XdrUnwrap() XdrType { return v.XdrType_PublicKey } - type _XdrArray_4_opaque [4]byte func (v *_XdrArray_4_opaque) GetByteSlice() []byte { return v[:] } @@ -3869,26 +5090,6 @@ func XDR_SequenceNumber(v *SequenceNumber) XdrType_SequenceNumber { func (XdrType_SequenceNumber) XdrTypeName() string { return "SequenceNumber" } func (v XdrType_SequenceNumber) XdrUnwrap() XdrType { return v.XdrType_Int64 } -type XdrType_TimePoint struct { - XdrType_Uint64 -} - -func XDR_TimePoint(v *TimePoint) XdrType_TimePoint { - return XdrType_TimePoint{XDR_Uint64(v)} -} -func (XdrType_TimePoint) XdrTypeName() string { return "TimePoint" } -func (v XdrType_TimePoint) XdrUnwrap() XdrType { return v.XdrType_Uint64 } - -type XdrType_Duration struct { - XdrType_Uint64 -} - -func XDR_Duration(v *Duration) XdrType_Duration { - return XdrType_Duration{XDR_Uint64(v)} -} -func (XdrType_Duration) XdrTypeName() string { return "Duration" } -func (v XdrType_Duration) XdrUnwrap() XdrType { return v.XdrType_Uint64 } - type XdrType_DataValue struct { XdrVecOpaque } @@ -4313,6 +5514,10 @@ var _XdrNames_LedgerEntryType = map[int32]string{ int32(DATA): "DATA", int32(CLAIMABLE_BALANCE): "CLAIMABLE_BALANCE", int32(LIQUIDITY_POOL): "LIQUIDITY_POOL", + int32(CONTRACT_DATA): "CONTRACT_DATA", + int32(CONTRACT_CODE): "CONTRACT_CODE", + int32(CONFIG_SETTING): "CONFIG_SETTING", + int32(TTL): "TTL", } var _XdrValues_LedgerEntryType = map[string]int32{ "ACCOUNT": int32(ACCOUNT), @@ -4321,6 +5526,10 @@ var _XdrValues_LedgerEntryType = map[string]int32{ "DATA": int32(DATA), "CLAIMABLE_BALANCE": int32(CLAIMABLE_BALANCE), "LIQUIDITY_POOL": int32(LIQUIDITY_POOL), + "CONTRACT_DATA": int32(CONTRACT_DATA), + "CONTRACT_CODE": int32(CONTRACT_CODE), + "CONFIG_SETTING": int32(CONFIG_SETTING), + "TTL": int32(TTL), } func (LedgerEntryType) XdrEnumNames() map[int32]string { @@ -6682,25 +7891,119 @@ func (v *LiquidityPoolEntry) XdrRecurse(x XDR, name string) { } func XDR_LiquidityPoolEntry(v *LiquidityPoolEntry) *LiquidityPoolEntry { return v } -var _XdrTags_XdrAnon_LedgerEntryExtensionV1_Ext = map[int32]bool{ - XdrToI32(0): true, +var _XdrNames_ContractDataDurability = map[int32]string{ + int32(TEMPORARY): "TEMPORARY", + int32(PERSISTENT): "PERSISTENT", +} +var _XdrValues_ContractDataDurability = map[string]int32{ + "TEMPORARY": int32(TEMPORARY), + "PERSISTENT": int32(PERSISTENT), } -func (_ XdrAnon_LedgerEntryExtensionV1_Ext) XdrValidTags() map[int32]bool { - return _XdrTags_XdrAnon_LedgerEntryExtensionV1_Ext +func (ContractDataDurability) XdrEnumNames() map[int32]string { + return _XdrNames_ContractDataDurability } -func (u XdrAnon_LedgerEntryExtensionV1_Ext) XdrValid() bool { - switch u.V { - case 0: - return true +func (v ContractDataDurability) String() string { + if s, ok := _XdrNames_ContractDataDurability[int32(v)]; ok { + return s } - return false -} -func (u *XdrAnon_LedgerEntryExtensionV1_Ext) XdrUnionTag() XdrNum32 { - return XDR_int32(&u.V) -} -func (u *XdrAnon_LedgerEntryExtensionV1_Ext) XdrUnionTagName() string { - return "V" + return fmt.Sprintf("ContractDataDurability#%d", v) +} +func (v *ContractDataDurability) Scan(ss fmt.ScanState, _ rune) error { + if tok, err := ss.Token(true, XdrSymChar); err != nil { + return err + } else { + stok := string(tok) + if val, ok := _XdrValues_ContractDataDurability[stok]; ok { + *v = ContractDataDurability(val) + return nil + } else if stok == "ContractDataDurability" { + if n, err := fmt.Fscanf(ss, "#%d", (*int32)(v)); n == 1 && err == nil { + return nil + } + } + return XdrError(fmt.Sprintf("%s is not a valid ContractDataDurability.", stok)) + } +} +func (v ContractDataDurability) GetU32() uint32 { return uint32(v) } +func (v *ContractDataDurability) SetU32(n uint32) { *v = ContractDataDurability(n) } +func (v *ContractDataDurability) XdrPointer() interface{} { return v } +func (ContractDataDurability) XdrTypeName() string { return "ContractDataDurability" } +func (v ContractDataDurability) XdrValue() interface{} { return v } +func (v *ContractDataDurability) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } + +type XdrType_ContractDataDurability = *ContractDataDurability + +func XDR_ContractDataDurability(v *ContractDataDurability) *ContractDataDurability { return v } + +type XdrType_ContractDataEntry = *ContractDataEntry + +func (v *ContractDataEntry) XdrPointer() interface{} { return v } +func (ContractDataEntry) XdrTypeName() string { return "ContractDataEntry" } +func (v ContractDataEntry) XdrValue() interface{} { return v } +func (v *ContractDataEntry) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v *ContractDataEntry) XdrRecurse(x XDR, name string) { + if name != "" { + name = x.Sprintf("%s.", name) + } + x.Marshal(x.Sprintf("%sext", name), XDR_ExtensionPoint(&v.Ext)) + x.Marshal(x.Sprintf("%scontract", name), XDR_SCAddress(&v.Contract)) + x.Marshal(x.Sprintf("%skey", name), XDR_SCVal(&v.Key)) + x.Marshal(x.Sprintf("%sdurability", name), XDR_ContractDataDurability(&v.Durability)) + x.Marshal(x.Sprintf("%sval", name), XDR_SCVal(&v.Val)) +} +func XDR_ContractDataEntry(v *ContractDataEntry) *ContractDataEntry { return v } + +type XdrType_ContractCodeEntry = *ContractCodeEntry + +func (v *ContractCodeEntry) XdrPointer() interface{} { return v } +func (ContractCodeEntry) XdrTypeName() string { return "ContractCodeEntry" } +func (v ContractCodeEntry) XdrValue() interface{} { return v } +func (v *ContractCodeEntry) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v *ContractCodeEntry) XdrRecurse(x XDR, name string) { + if name != "" { + name = x.Sprintf("%s.", name) + } + x.Marshal(x.Sprintf("%sext", name), XDR_ExtensionPoint(&v.Ext)) + x.Marshal(x.Sprintf("%shash", name), XDR_Hash(&v.Hash)) + x.Marshal(x.Sprintf("%scode", name), XdrVecOpaque{&v.Code, 0xffffffff}) +} +func XDR_ContractCodeEntry(v *ContractCodeEntry) *ContractCodeEntry { return v } + +type XdrType_TTLEntry = *TTLEntry + +func (v *TTLEntry) XdrPointer() interface{} { return v } +func (TTLEntry) XdrTypeName() string { return "TTLEntry" } +func (v TTLEntry) XdrValue() interface{} { return v } +func (v *TTLEntry) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v *TTLEntry) XdrRecurse(x XDR, name string) { + if name != "" { + name = x.Sprintf("%s.", name) + } + x.Marshal(x.Sprintf("%skeyHash", name), XDR_Hash(&v.KeyHash)) + x.Marshal(x.Sprintf("%sliveUntilLedgerSeq", name), XDR_Uint32(&v.LiveUntilLedgerSeq)) +} +func XDR_TTLEntry(v *TTLEntry) *TTLEntry { return v } + +var _XdrTags_XdrAnon_LedgerEntryExtensionV1_Ext = map[int32]bool{ + XdrToI32(0): true, +} + +func (_ XdrAnon_LedgerEntryExtensionV1_Ext) XdrValidTags() map[int32]bool { + return _XdrTags_XdrAnon_LedgerEntryExtensionV1_Ext +} +func (u XdrAnon_LedgerEntryExtensionV1_Ext) XdrValid() bool { + switch u.V { + case 0: + return true + } + return false +} +func (u *XdrAnon_LedgerEntryExtensionV1_Ext) XdrUnionTag() XdrNum32 { + return XDR_int32(&u.V) +} +func (u *XdrAnon_LedgerEntryExtensionV1_Ext) XdrUnionTagName() string { + return "V" } func (u *XdrAnon_LedgerEntryExtensionV1_Ext) XdrUnionBody() XdrType { switch u.V { @@ -6762,6 +8065,10 @@ var _XdrTags_XdrAnon_LedgerEntry_Data = map[int32]bool{ XdrToI32(DATA): true, XdrToI32(CLAIMABLE_BALANCE): true, XdrToI32(LIQUIDITY_POOL): true, + XdrToI32(CONTRACT_DATA): true, + XdrToI32(CONTRACT_CODE): true, + XdrToI32(CONFIG_SETTING): true, + XdrToI32(TTL): true, } func (_ XdrAnon_LedgerEntry_Data) XdrValidTags() map[int32]bool { @@ -6857,9 +8164,69 @@ func (u *XdrAnon_LedgerEntry_Data) LiquidityPool() *LiquidityPoolEntry { return nil } } +func (u *XdrAnon_LedgerEntry_Data) ContractData() *ContractDataEntry { + switch u.Type { + case CONTRACT_DATA: + if v, ok := u._u.(*ContractDataEntry); ok { + return v + } else { + var zero ContractDataEntry + u._u = &zero + return &zero + } + default: + XdrPanic("XdrAnon_LedgerEntry_Data.ContractData accessed when Type == %v", u.Type) + return nil + } +} +func (u *XdrAnon_LedgerEntry_Data) ContractCode() *ContractCodeEntry { + switch u.Type { + case CONTRACT_CODE: + if v, ok := u._u.(*ContractCodeEntry); ok { + return v + } else { + var zero ContractCodeEntry + u._u = &zero + return &zero + } + default: + XdrPanic("XdrAnon_LedgerEntry_Data.ContractCode accessed when Type == %v", u.Type) + return nil + } +} +func (u *XdrAnon_LedgerEntry_Data) ConfigSetting() *ConfigSettingEntry { + switch u.Type { + case CONFIG_SETTING: + if v, ok := u._u.(*ConfigSettingEntry); ok { + return v + } else { + var zero ConfigSettingEntry + u._u = &zero + return &zero + } + default: + XdrPanic("XdrAnon_LedgerEntry_Data.ConfigSetting accessed when Type == %v", u.Type) + return nil + } +} +func (u *XdrAnon_LedgerEntry_Data) Ttl() *TTLEntry { + switch u.Type { + case TTL: + if v, ok := u._u.(*TTLEntry); ok { + return v + } else { + var zero TTLEntry + u._u = &zero + return &zero + } + default: + XdrPanic("XdrAnon_LedgerEntry_Data.Ttl accessed when Type == %v", u.Type) + return nil + } +} func (u XdrAnon_LedgerEntry_Data) XdrValid() bool { switch u.Type { - case ACCOUNT, TRUSTLINE, OFFER, DATA, CLAIMABLE_BALANCE, LIQUIDITY_POOL: + case ACCOUNT, TRUSTLINE, OFFER, DATA, CLAIMABLE_BALANCE, LIQUIDITY_POOL, CONTRACT_DATA, CONTRACT_CODE, CONFIG_SETTING, TTL: return true } return false @@ -6884,6 +8251,14 @@ func (u *XdrAnon_LedgerEntry_Data) XdrUnionBody() XdrType { return XDR_ClaimableBalanceEntry(u.ClaimableBalance()) case LIQUIDITY_POOL: return XDR_LiquidityPoolEntry(u.LiquidityPool()) + case CONTRACT_DATA: + return XDR_ContractDataEntry(u.ContractData()) + case CONTRACT_CODE: + return XDR_ContractCodeEntry(u.ContractCode()) + case CONFIG_SETTING: + return XDR_ConfigSettingEntry(u.ConfigSetting()) + case TTL: + return XDR_TTLEntry(u.Ttl()) } return nil } @@ -6901,6 +8276,14 @@ func (u *XdrAnon_LedgerEntry_Data) XdrUnionBodyName() string { return "ClaimableBalance" case LIQUIDITY_POOL: return "LiquidityPool" + case CONTRACT_DATA: + return "ContractData" + case CONTRACT_CODE: + return "ContractCode" + case CONFIG_SETTING: + return "ConfigSetting" + case TTL: + return "Ttl" } return "" } @@ -6935,6 +8318,18 @@ func (u *XdrAnon_LedgerEntry_Data) XdrRecurse(x XDR, name string) { case LIQUIDITY_POOL: x.Marshal(x.Sprintf("%sliquidityPool", name), XDR_LiquidityPoolEntry(u.LiquidityPool())) return + case CONTRACT_DATA: + x.Marshal(x.Sprintf("%scontractData", name), XDR_ContractDataEntry(u.ContractData())) + return + case CONTRACT_CODE: + x.Marshal(x.Sprintf("%scontractCode", name), XDR_ContractCodeEntry(u.ContractCode())) + return + case CONFIG_SETTING: + x.Marshal(x.Sprintf("%sconfigSetting", name), XDR_ConfigSettingEntry(u.ConfigSetting())) + return + case TTL: + x.Marshal(x.Sprintf("%sttl", name), XDR_TTLEntry(u.Ttl())) + return } XdrPanic("invalid Type (%v) in XdrAnon_LedgerEntry_Data", u.Type) } @@ -7128,6 +8523,70 @@ func XDR_XdrAnon_LedgerKey_LiquidityPool(v *XdrAnon_LedgerKey_LiquidityPool) *Xd return v } +type XdrType_XdrAnon_LedgerKey_ContractData = *XdrAnon_LedgerKey_ContractData + +func (v *XdrAnon_LedgerKey_ContractData) XdrPointer() interface{} { return v } +func (XdrAnon_LedgerKey_ContractData) XdrTypeName() string { return "XdrAnon_LedgerKey_ContractData" } +func (v XdrAnon_LedgerKey_ContractData) XdrValue() interface{} { return v } +func (v *XdrAnon_LedgerKey_ContractData) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v *XdrAnon_LedgerKey_ContractData) XdrRecurse(x XDR, name string) { + if name != "" { + name = x.Sprintf("%s.", name) + } + x.Marshal(x.Sprintf("%scontract", name), XDR_SCAddress(&v.Contract)) + x.Marshal(x.Sprintf("%skey", name), XDR_SCVal(&v.Key)) + x.Marshal(x.Sprintf("%sdurability", name), XDR_ContractDataDurability(&v.Durability)) +} +func XDR_XdrAnon_LedgerKey_ContractData(v *XdrAnon_LedgerKey_ContractData) *XdrAnon_LedgerKey_ContractData { + return v +} + +type XdrType_XdrAnon_LedgerKey_ContractCode = *XdrAnon_LedgerKey_ContractCode + +func (v *XdrAnon_LedgerKey_ContractCode) XdrPointer() interface{} { return v } +func (XdrAnon_LedgerKey_ContractCode) XdrTypeName() string { return "XdrAnon_LedgerKey_ContractCode" } +func (v XdrAnon_LedgerKey_ContractCode) XdrValue() interface{} { return v } +func (v *XdrAnon_LedgerKey_ContractCode) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v *XdrAnon_LedgerKey_ContractCode) XdrRecurse(x XDR, name string) { + if name != "" { + name = x.Sprintf("%s.", name) + } + x.Marshal(x.Sprintf("%shash", name), XDR_Hash(&v.Hash)) +} +func XDR_XdrAnon_LedgerKey_ContractCode(v *XdrAnon_LedgerKey_ContractCode) *XdrAnon_LedgerKey_ContractCode { + return v +} + +type XdrType_XdrAnon_LedgerKey_ConfigSetting = *XdrAnon_LedgerKey_ConfigSetting + +func (v *XdrAnon_LedgerKey_ConfigSetting) XdrPointer() interface{} { return v } +func (XdrAnon_LedgerKey_ConfigSetting) XdrTypeName() string { return "XdrAnon_LedgerKey_ConfigSetting" } +func (v XdrAnon_LedgerKey_ConfigSetting) XdrValue() interface{} { return v } +func (v *XdrAnon_LedgerKey_ConfigSetting) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v *XdrAnon_LedgerKey_ConfigSetting) XdrRecurse(x XDR, name string) { + if name != "" { + name = x.Sprintf("%s.", name) + } + x.Marshal(x.Sprintf("%sconfigSettingID", name), XDR_ConfigSettingID(&v.ConfigSettingID)) +} +func XDR_XdrAnon_LedgerKey_ConfigSetting(v *XdrAnon_LedgerKey_ConfigSetting) *XdrAnon_LedgerKey_ConfigSetting { + return v +} + +type XdrType_XdrAnon_LedgerKey_Ttl = *XdrAnon_LedgerKey_Ttl + +func (v *XdrAnon_LedgerKey_Ttl) XdrPointer() interface{} { return v } +func (XdrAnon_LedgerKey_Ttl) XdrTypeName() string { return "XdrAnon_LedgerKey_Ttl" } +func (v XdrAnon_LedgerKey_Ttl) XdrValue() interface{} { return v } +func (v *XdrAnon_LedgerKey_Ttl) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v *XdrAnon_LedgerKey_Ttl) XdrRecurse(x XDR, name string) { + if name != "" { + name = x.Sprintf("%s.", name) + } + x.Marshal(x.Sprintf("%skeyHash", name), XDR_Hash(&v.KeyHash)) +} +func XDR_XdrAnon_LedgerKey_Ttl(v *XdrAnon_LedgerKey_Ttl) *XdrAnon_LedgerKey_Ttl { return v } + var _XdrTags_LedgerKey = map[int32]bool{ XdrToI32(ACCOUNT): true, XdrToI32(TRUSTLINE): true, @@ -7135,6 +8594,10 @@ var _XdrTags_LedgerKey = map[int32]bool{ XdrToI32(DATA): true, XdrToI32(CLAIMABLE_BALANCE): true, XdrToI32(LIQUIDITY_POOL): true, + XdrToI32(CONTRACT_DATA): true, + XdrToI32(CONTRACT_CODE): true, + XdrToI32(CONFIG_SETTING): true, + XdrToI32(TTL): true, } func (_ LedgerKey) XdrValidTags() map[int32]bool { @@ -7230,9 +8693,69 @@ func (u *LedgerKey) LiquidityPool() *XdrAnon_LedgerKey_LiquidityPool { return nil } } +func (u *LedgerKey) ContractData() *XdrAnon_LedgerKey_ContractData { + switch u.Type { + case CONTRACT_DATA: + if v, ok := u._u.(*XdrAnon_LedgerKey_ContractData); ok { + return v + } else { + var zero XdrAnon_LedgerKey_ContractData + u._u = &zero + return &zero + } + default: + XdrPanic("LedgerKey.ContractData accessed when Type == %v", u.Type) + return nil + } +} +func (u *LedgerKey) ContractCode() *XdrAnon_LedgerKey_ContractCode { + switch u.Type { + case CONTRACT_CODE: + if v, ok := u._u.(*XdrAnon_LedgerKey_ContractCode); ok { + return v + } else { + var zero XdrAnon_LedgerKey_ContractCode + u._u = &zero + return &zero + } + default: + XdrPanic("LedgerKey.ContractCode accessed when Type == %v", u.Type) + return nil + } +} +func (u *LedgerKey) ConfigSetting() *XdrAnon_LedgerKey_ConfigSetting { + switch u.Type { + case CONFIG_SETTING: + if v, ok := u._u.(*XdrAnon_LedgerKey_ConfigSetting); ok { + return v + } else { + var zero XdrAnon_LedgerKey_ConfigSetting + u._u = &zero + return &zero + } + default: + XdrPanic("LedgerKey.ConfigSetting accessed when Type == %v", u.Type) + return nil + } +} +func (u *LedgerKey) Ttl() *XdrAnon_LedgerKey_Ttl { + switch u.Type { + case TTL: + if v, ok := u._u.(*XdrAnon_LedgerKey_Ttl); ok { + return v + } else { + var zero XdrAnon_LedgerKey_Ttl + u._u = &zero + return &zero + } + default: + XdrPanic("LedgerKey.Ttl accessed when Type == %v", u.Type) + return nil + } +} func (u LedgerKey) XdrValid() bool { switch u.Type { - case ACCOUNT, TRUSTLINE, OFFER, DATA, CLAIMABLE_BALANCE, LIQUIDITY_POOL: + case ACCOUNT, TRUSTLINE, OFFER, DATA, CLAIMABLE_BALANCE, LIQUIDITY_POOL, CONTRACT_DATA, CONTRACT_CODE, CONFIG_SETTING, TTL: return true } return false @@ -7257,6 +8780,14 @@ func (u *LedgerKey) XdrUnionBody() XdrType { return XDR_XdrAnon_LedgerKey_ClaimableBalance(u.ClaimableBalance()) case LIQUIDITY_POOL: return XDR_XdrAnon_LedgerKey_LiquidityPool(u.LiquidityPool()) + case CONTRACT_DATA: + return XDR_XdrAnon_LedgerKey_ContractData(u.ContractData()) + case CONTRACT_CODE: + return XDR_XdrAnon_LedgerKey_ContractCode(u.ContractCode()) + case CONFIG_SETTING: + return XDR_XdrAnon_LedgerKey_ConfigSetting(u.ConfigSetting()) + case TTL: + return XDR_XdrAnon_LedgerKey_Ttl(u.Ttl()) } return nil } @@ -7274,6 +8805,14 @@ func (u *LedgerKey) XdrUnionBodyName() string { return "ClaimableBalance" case LIQUIDITY_POOL: return "LiquidityPool" + case CONTRACT_DATA: + return "ContractData" + case CONTRACT_CODE: + return "ContractCode" + case CONFIG_SETTING: + return "ConfigSetting" + case TTL: + return "Ttl" } return "" } @@ -7308,30 +8847,46 @@ func (u *LedgerKey) XdrRecurse(x XDR, name string) { case LIQUIDITY_POOL: x.Marshal(x.Sprintf("%sliquidityPool", name), XDR_XdrAnon_LedgerKey_LiquidityPool(u.LiquidityPool())) return + case CONTRACT_DATA: + x.Marshal(x.Sprintf("%scontractData", name), XDR_XdrAnon_LedgerKey_ContractData(u.ContractData())) + return + case CONTRACT_CODE: + x.Marshal(x.Sprintf("%scontractCode", name), XDR_XdrAnon_LedgerKey_ContractCode(u.ContractCode())) + return + case CONFIG_SETTING: + x.Marshal(x.Sprintf("%sconfigSetting", name), XDR_XdrAnon_LedgerKey_ConfigSetting(u.ConfigSetting())) + return + case TTL: + x.Marshal(x.Sprintf("%sttl", name), XDR_XdrAnon_LedgerKey_Ttl(u.Ttl())) + return } XdrPanic("invalid Type (%v) in LedgerKey", u.Type) } func XDR_LedgerKey(v *LedgerKey) *LedgerKey { return v } var _XdrNames_EnvelopeType = map[int32]string{ - int32(ENVELOPE_TYPE_TX_V0): "ENVELOPE_TYPE_TX_V0", - int32(ENVELOPE_TYPE_SCP): "ENVELOPE_TYPE_SCP", - int32(ENVELOPE_TYPE_TX): "ENVELOPE_TYPE_TX", - int32(ENVELOPE_TYPE_AUTH): "ENVELOPE_TYPE_AUTH", - int32(ENVELOPE_TYPE_SCPVALUE): "ENVELOPE_TYPE_SCPVALUE", - int32(ENVELOPE_TYPE_TX_FEE_BUMP): "ENVELOPE_TYPE_TX_FEE_BUMP", - int32(ENVELOPE_TYPE_OP_ID): "ENVELOPE_TYPE_OP_ID", - int32(ENVELOPE_TYPE_POOL_REVOKE_OP_ID): "ENVELOPE_TYPE_POOL_REVOKE_OP_ID", + int32(ENVELOPE_TYPE_TX_V0): "ENVELOPE_TYPE_TX_V0", + int32(ENVELOPE_TYPE_SCP): "ENVELOPE_TYPE_SCP", + int32(ENVELOPE_TYPE_TX): "ENVELOPE_TYPE_TX", + int32(ENVELOPE_TYPE_AUTH): "ENVELOPE_TYPE_AUTH", + int32(ENVELOPE_TYPE_SCPVALUE): "ENVELOPE_TYPE_SCPVALUE", + int32(ENVELOPE_TYPE_TX_FEE_BUMP): "ENVELOPE_TYPE_TX_FEE_BUMP", + int32(ENVELOPE_TYPE_OP_ID): "ENVELOPE_TYPE_OP_ID", + int32(ENVELOPE_TYPE_POOL_REVOKE_OP_ID): "ENVELOPE_TYPE_POOL_REVOKE_OP_ID", + int32(ENVELOPE_TYPE_CONTRACT_ID): "ENVELOPE_TYPE_CONTRACT_ID", + int32(ENVELOPE_TYPE_SOROBAN_AUTHORIZATION): "ENVELOPE_TYPE_SOROBAN_AUTHORIZATION", } var _XdrValues_EnvelopeType = map[string]int32{ - "ENVELOPE_TYPE_TX_V0": int32(ENVELOPE_TYPE_TX_V0), - "ENVELOPE_TYPE_SCP": int32(ENVELOPE_TYPE_SCP), - "ENVELOPE_TYPE_TX": int32(ENVELOPE_TYPE_TX), - "ENVELOPE_TYPE_AUTH": int32(ENVELOPE_TYPE_AUTH), - "ENVELOPE_TYPE_SCPVALUE": int32(ENVELOPE_TYPE_SCPVALUE), - "ENVELOPE_TYPE_TX_FEE_BUMP": int32(ENVELOPE_TYPE_TX_FEE_BUMP), - "ENVELOPE_TYPE_OP_ID": int32(ENVELOPE_TYPE_OP_ID), - "ENVELOPE_TYPE_POOL_REVOKE_OP_ID": int32(ENVELOPE_TYPE_POOL_REVOKE_OP_ID), + "ENVELOPE_TYPE_TX_V0": int32(ENVELOPE_TYPE_TX_V0), + "ENVELOPE_TYPE_SCP": int32(ENVELOPE_TYPE_SCP), + "ENVELOPE_TYPE_TX": int32(ENVELOPE_TYPE_TX), + "ENVELOPE_TYPE_AUTH": int32(ENVELOPE_TYPE_AUTH), + "ENVELOPE_TYPE_SCPVALUE": int32(ENVELOPE_TYPE_SCPVALUE), + "ENVELOPE_TYPE_TX_FEE_BUMP": int32(ENVELOPE_TYPE_TX_FEE_BUMP), + "ENVELOPE_TYPE_OP_ID": int32(ENVELOPE_TYPE_OP_ID), + "ENVELOPE_TYPE_POOL_REVOKE_OP_ID": int32(ENVELOPE_TYPE_POOL_REVOKE_OP_ID), + "ENVELOPE_TYPE_CONTRACT_ID": int32(ENVELOPE_TYPE_CONTRACT_ID), + "ENVELOPE_TYPE_SOROBAN_AUTHORIZATION": int32(ENVELOPE_TYPE_SOROBAN_AUTHORIZATION), } func (EnvelopeType) XdrEnumNames() map[int32]string { @@ -7842,18 +9397,22 @@ func (v *LedgerHeader) XdrRecurse(x XDR, name string) { func XDR_LedgerHeader(v *LedgerHeader) *LedgerHeader { return v } var _XdrNames_LedgerUpgradeType = map[int32]string{ - int32(LEDGER_UPGRADE_VERSION): "LEDGER_UPGRADE_VERSION", - int32(LEDGER_UPGRADE_BASE_FEE): "LEDGER_UPGRADE_BASE_FEE", - int32(LEDGER_UPGRADE_MAX_TX_SET_SIZE): "LEDGER_UPGRADE_MAX_TX_SET_SIZE", - int32(LEDGER_UPGRADE_BASE_RESERVE): "LEDGER_UPGRADE_BASE_RESERVE", - int32(LEDGER_UPGRADE_FLAGS): "LEDGER_UPGRADE_FLAGS", + int32(LEDGER_UPGRADE_VERSION): "LEDGER_UPGRADE_VERSION", + int32(LEDGER_UPGRADE_BASE_FEE): "LEDGER_UPGRADE_BASE_FEE", + int32(LEDGER_UPGRADE_MAX_TX_SET_SIZE): "LEDGER_UPGRADE_MAX_TX_SET_SIZE", + int32(LEDGER_UPGRADE_BASE_RESERVE): "LEDGER_UPGRADE_BASE_RESERVE", + int32(LEDGER_UPGRADE_FLAGS): "LEDGER_UPGRADE_FLAGS", + int32(LEDGER_UPGRADE_CONFIG): "LEDGER_UPGRADE_CONFIG", + int32(LEDGER_UPGRADE_MAX_SOROBAN_TX_SET_SIZE): "LEDGER_UPGRADE_MAX_SOROBAN_TX_SET_SIZE", } var _XdrValues_LedgerUpgradeType = map[string]int32{ - "LEDGER_UPGRADE_VERSION": int32(LEDGER_UPGRADE_VERSION), - "LEDGER_UPGRADE_BASE_FEE": int32(LEDGER_UPGRADE_BASE_FEE), - "LEDGER_UPGRADE_MAX_TX_SET_SIZE": int32(LEDGER_UPGRADE_MAX_TX_SET_SIZE), - "LEDGER_UPGRADE_BASE_RESERVE": int32(LEDGER_UPGRADE_BASE_RESERVE), - "LEDGER_UPGRADE_FLAGS": int32(LEDGER_UPGRADE_FLAGS), + "LEDGER_UPGRADE_VERSION": int32(LEDGER_UPGRADE_VERSION), + "LEDGER_UPGRADE_BASE_FEE": int32(LEDGER_UPGRADE_BASE_FEE), + "LEDGER_UPGRADE_MAX_TX_SET_SIZE": int32(LEDGER_UPGRADE_MAX_TX_SET_SIZE), + "LEDGER_UPGRADE_BASE_RESERVE": int32(LEDGER_UPGRADE_BASE_RESERVE), + "LEDGER_UPGRADE_FLAGS": int32(LEDGER_UPGRADE_FLAGS), + "LEDGER_UPGRADE_CONFIG": int32(LEDGER_UPGRADE_CONFIG), + "LEDGER_UPGRADE_MAX_SOROBAN_TX_SET_SIZE": int32(LEDGER_UPGRADE_MAX_SOROBAN_TX_SET_SIZE), } func (LedgerUpgradeType) XdrEnumNames() map[int32]string { @@ -7893,7 +9452,7 @@ type XdrType_LedgerUpgradeType = *LedgerUpgradeType func XDR_LedgerUpgradeType(v *LedgerUpgradeType) *LedgerUpgradeType { return v } func (v *LedgerUpgradeType) XdrInitialize() { switch LedgerUpgradeType(0) { - case LEDGER_UPGRADE_VERSION, LEDGER_UPGRADE_BASE_FEE, LEDGER_UPGRADE_MAX_TX_SET_SIZE, LEDGER_UPGRADE_BASE_RESERVE, LEDGER_UPGRADE_FLAGS: + case LEDGER_UPGRADE_VERSION, LEDGER_UPGRADE_BASE_FEE, LEDGER_UPGRADE_MAX_TX_SET_SIZE, LEDGER_UPGRADE_BASE_RESERVE, LEDGER_UPGRADE_FLAGS, LEDGER_UPGRADE_CONFIG, LEDGER_UPGRADE_MAX_SOROBAN_TX_SET_SIZE: default: if *v == LedgerUpgradeType(0) { *v = LEDGER_UPGRADE_VERSION @@ -7901,12 +9460,29 @@ func (v *LedgerUpgradeType) XdrInitialize() { } } +type XdrType_ConfigUpgradeSetKey = *ConfigUpgradeSetKey + +func (v *ConfigUpgradeSetKey) XdrPointer() interface{} { return v } +func (ConfigUpgradeSetKey) XdrTypeName() string { return "ConfigUpgradeSetKey" } +func (v ConfigUpgradeSetKey) XdrValue() interface{} { return v } +func (v *ConfigUpgradeSetKey) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v *ConfigUpgradeSetKey) XdrRecurse(x XDR, name string) { + if name != "" { + name = x.Sprintf("%s.", name) + } + x.Marshal(x.Sprintf("%scontractID", name), XDR_Hash(&v.ContractID)) + x.Marshal(x.Sprintf("%scontentHash", name), XDR_Hash(&v.ContentHash)) +} +func XDR_ConfigUpgradeSetKey(v *ConfigUpgradeSetKey) *ConfigUpgradeSetKey { return v } + var _XdrTags_LedgerUpgrade = map[int32]bool{ - XdrToI32(LEDGER_UPGRADE_VERSION): true, - XdrToI32(LEDGER_UPGRADE_BASE_FEE): true, - XdrToI32(LEDGER_UPGRADE_MAX_TX_SET_SIZE): true, - XdrToI32(LEDGER_UPGRADE_BASE_RESERVE): true, - XdrToI32(LEDGER_UPGRADE_FLAGS): true, + XdrToI32(LEDGER_UPGRADE_VERSION): true, + XdrToI32(LEDGER_UPGRADE_BASE_FEE): true, + XdrToI32(LEDGER_UPGRADE_MAX_TX_SET_SIZE): true, + XdrToI32(LEDGER_UPGRADE_BASE_RESERVE): true, + XdrToI32(LEDGER_UPGRADE_FLAGS): true, + XdrToI32(LEDGER_UPGRADE_CONFIG): true, + XdrToI32(LEDGER_UPGRADE_MAX_SOROBAN_TX_SET_SIZE): true, } func (_ LedgerUpgrade) XdrValidTags() map[int32]bool { @@ -7997,9 +9573,44 @@ func (u *LedgerUpgrade) NewFlags() *Uint32 { return nil } } + +// Update arbitrary `ConfigSetting` entries identified by the key. +func (u *LedgerUpgrade) NewConfig() *ConfigUpgradeSetKey { + switch u.Type { + case LEDGER_UPGRADE_CONFIG: + if v, ok := u._u.(*ConfigUpgradeSetKey); ok { + return v + } else { + var zero ConfigUpgradeSetKey + u._u = &zero + return &zero + } + default: + XdrPanic("LedgerUpgrade.NewConfig accessed when Type == %v", u.Type) + return nil + } +} + +// Update ConfigSettingContractExecutionLanesV0.ledgerMaxTxCount without +// using `LEDGER_UPGRADE_CONFIG`. +func (u *LedgerUpgrade) NewMaxSorobanTxSetSize() *Uint32 { + switch u.Type { + case LEDGER_UPGRADE_MAX_SOROBAN_TX_SET_SIZE: + if v, ok := u._u.(*Uint32); ok { + return v + } else { + var zero Uint32 + u._u = &zero + return &zero + } + default: + XdrPanic("LedgerUpgrade.NewMaxSorobanTxSetSize accessed when Type == %v", u.Type) + return nil + } +} func (u LedgerUpgrade) XdrValid() bool { switch u.Type { - case LEDGER_UPGRADE_VERSION, LEDGER_UPGRADE_BASE_FEE, LEDGER_UPGRADE_MAX_TX_SET_SIZE, LEDGER_UPGRADE_BASE_RESERVE, LEDGER_UPGRADE_FLAGS: + case LEDGER_UPGRADE_VERSION, LEDGER_UPGRADE_BASE_FEE, LEDGER_UPGRADE_MAX_TX_SET_SIZE, LEDGER_UPGRADE_BASE_RESERVE, LEDGER_UPGRADE_FLAGS, LEDGER_UPGRADE_CONFIG, LEDGER_UPGRADE_MAX_SOROBAN_TX_SET_SIZE: return true } return false @@ -8022,6 +9633,10 @@ func (u *LedgerUpgrade) XdrUnionBody() XdrType { return XDR_Uint32(u.NewBaseReserve()) case LEDGER_UPGRADE_FLAGS: return XDR_Uint32(u.NewFlags()) + case LEDGER_UPGRADE_CONFIG: + return XDR_ConfigUpgradeSetKey(u.NewConfig()) + case LEDGER_UPGRADE_MAX_SOROBAN_TX_SET_SIZE: + return XDR_Uint32(u.NewMaxSorobanTxSetSize()) } return nil } @@ -8037,6 +9652,10 @@ func (u *LedgerUpgrade) XdrUnionBodyName() string { return "NewBaseReserve" case LEDGER_UPGRADE_FLAGS: return "NewFlags" + case LEDGER_UPGRADE_CONFIG: + return "NewConfig" + case LEDGER_UPGRADE_MAX_SOROBAN_TX_SET_SIZE: + return "NewMaxSorobanTxSetSize" } return "" } @@ -8068,13 +9687,19 @@ func (u *LedgerUpgrade) XdrRecurse(x XDR, name string) { case LEDGER_UPGRADE_FLAGS: x.Marshal(x.Sprintf("%snewFlags", name), XDR_Uint32(u.NewFlags())) return + case LEDGER_UPGRADE_CONFIG: + x.Marshal(x.Sprintf("%snewConfig", name), XDR_ConfigUpgradeSetKey(u.NewConfig())) + return + case LEDGER_UPGRADE_MAX_SOROBAN_TX_SET_SIZE: + x.Marshal(x.Sprintf("%snewMaxSorobanTxSetSize", name), XDR_Uint32(u.NewMaxSorobanTxSetSize())) + return } XdrPanic("invalid Type (%v) in LedgerUpgrade", u.Type) } func (v *LedgerUpgrade) XdrInitialize() { var zero LedgerUpgradeType switch zero { - case LEDGER_UPGRADE_VERSION, LEDGER_UPGRADE_BASE_FEE, LEDGER_UPGRADE_MAX_TX_SET_SIZE, LEDGER_UPGRADE_BASE_RESERVE, LEDGER_UPGRADE_FLAGS: + case LEDGER_UPGRADE_VERSION, LEDGER_UPGRADE_BASE_FEE, LEDGER_UPGRADE_MAX_TX_SET_SIZE, LEDGER_UPGRADE_BASE_RESERVE, LEDGER_UPGRADE_FLAGS, LEDGER_UPGRADE_CONFIG, LEDGER_UPGRADE_MAX_SOROBAN_TX_SET_SIZE: default: if v.Type == zero { v.Type = LEDGER_UPGRADE_VERSION @@ -8083,6 +9708,81 @@ func (v *LedgerUpgrade) XdrInitialize() { } func XDR_LedgerUpgrade(v *LedgerUpgrade) *LedgerUpgrade { return v } +type _XdrVec_unbounded_ConfigSettingEntry []ConfigSettingEntry + +func (_XdrVec_unbounded_ConfigSettingEntry) XdrBound() uint32 { + const bound uint32 = 4294967295 // Force error if not const or doesn't fit + return bound +} +func (_XdrVec_unbounded_ConfigSettingEntry) XdrCheckLen(length uint32) { + if length > uint32(4294967295) { + XdrPanic("_XdrVec_unbounded_ConfigSettingEntry length %d exceeds bound 4294967295", length) + } else if int(length) < 0 { + XdrPanic("_XdrVec_unbounded_ConfigSettingEntry length %d exceeds max int", length) + } +} +func (v _XdrVec_unbounded_ConfigSettingEntry) GetVecLen() uint32 { return uint32(len(v)) } +func (v *_XdrVec_unbounded_ConfigSettingEntry) SetVecLen(length uint32) { + v.XdrCheckLen(length) + if int(length) <= cap(*v) { + if int(length) != len(*v) { + *v = (*v)[:int(length)] + } + return + } + newcap := 2 * cap(*v) + if newcap < int(length) { // also catches overflow where 2*cap < 0 + newcap = int(length) + } else if bound := uint(4294967295); uint(newcap) > bound { + if int(bound) < 0 { + bound = ^uint(0) >> 1 + } + newcap = int(bound) + } + nv := make([]ConfigSettingEntry, int(length), newcap) + copy(nv, *v) + *v = nv +} +func (v *_XdrVec_unbounded_ConfigSettingEntry) XdrMarshalN(x XDR, name string, n uint32) { + v.XdrCheckLen(n) + for i := 0; i < int(n); i++ { + if i >= len(*v) { + v.SetVecLen(uint32(i + 1)) + } + XDR_ConfigSettingEntry(&(*v)[i]).XdrMarshal(x, x.Sprintf("%s[%d]", name, i)) + } + if int(n) < len(*v) { + *v = (*v)[:int(n)] + } +} +func (v *_XdrVec_unbounded_ConfigSettingEntry) XdrRecurse(x XDR, name string) { + size := XdrSize{Size: uint32(len(*v)), Bound: 4294967295} + x.Marshal(name, &size) + v.XdrMarshalN(x, name, size.Size) +} +func (_XdrVec_unbounded_ConfigSettingEntry) XdrTypeName() string { return "ConfigSettingEntry<>" } +func (v *_XdrVec_unbounded_ConfigSettingEntry) XdrPointer() interface{} { + return (*[]ConfigSettingEntry)(v) +} +func (v _XdrVec_unbounded_ConfigSettingEntry) XdrValue() interface{} { + return ([]ConfigSettingEntry)(v) +} +func (v *_XdrVec_unbounded_ConfigSettingEntry) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } + +type XdrType_ConfigUpgradeSet = *ConfigUpgradeSet + +func (v *ConfigUpgradeSet) XdrPointer() interface{} { return v } +func (ConfigUpgradeSet) XdrTypeName() string { return "ConfigUpgradeSet" } +func (v ConfigUpgradeSet) XdrValue() interface{} { return v } +func (v *ConfigUpgradeSet) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v *ConfigUpgradeSet) XdrRecurse(x XDR, name string) { + if name != "" { + name = x.Sprintf("%s.", name) + } + x.Marshal(x.Sprintf("%supdatedEntry", name), (*_XdrVec_unbounded_ConfigSettingEntry)(&v.UpdatedEntry)) +} +func XDR_ConfigUpgradeSet(v *ConfigUpgradeSet) *ConfigUpgradeSet { return v } + var _XdrNames_BucketEntryType = map[int32]string{ int32(METAENTRY): "METAENTRY", int32(LIVEENTRY): "LIVEENTRY", @@ -9769,168 +11469,319 @@ func (v *TransactionMetaV2) XdrRecurse(x XDR, name string) { } func XDR_TransactionMetaV2(v *TransactionMetaV2) *TransactionMetaV2 { return v } -var _XdrTags_TransactionMeta = map[int32]bool{ - XdrToI32(0): true, - XdrToI32(1): true, - XdrToI32(2): true, +var _XdrNames_ContractEventType = map[int32]string{ + int32(SYSTEM): "SYSTEM", + int32(CONTRACT): "CONTRACT", + int32(DIAGNOSTIC): "DIAGNOSTIC", +} +var _XdrValues_ContractEventType = map[string]int32{ + "SYSTEM": int32(SYSTEM), + "CONTRACT": int32(CONTRACT), + "DIAGNOSTIC": int32(DIAGNOSTIC), } -func (_ TransactionMeta) XdrValidTags() map[int32]bool { - return _XdrTags_TransactionMeta +func (ContractEventType) XdrEnumNames() map[int32]string { + return _XdrNames_ContractEventType } -func (u *TransactionMeta) Operations() *[]OperationMeta { - switch u.V { - case 0: - if v, ok := u._u.(*[]OperationMeta); ok { - return v - } else { - var zero []OperationMeta - u._u = &zero - return &zero +func (v ContractEventType) String() string { + if s, ok := _XdrNames_ContractEventType[int32(v)]; ok { + return s + } + return fmt.Sprintf("ContractEventType#%d", v) +} +func (v *ContractEventType) Scan(ss fmt.ScanState, _ rune) error { + if tok, err := ss.Token(true, XdrSymChar); err != nil { + return err + } else { + stok := string(tok) + if val, ok := _XdrValues_ContractEventType[stok]; ok { + *v = ContractEventType(val) + return nil + } else if stok == "ContractEventType" { + if n, err := fmt.Fscanf(ss, "#%d", (*int32)(v)); n == 1 && err == nil { + return nil + } } - default: - XdrPanic("TransactionMeta.Operations accessed when V == %v", u.V) - return nil + return XdrError(fmt.Sprintf("%s is not a valid ContractEventType.", stok)) } } -func (u *TransactionMeta) V1() *TransactionMetaV1 { - switch u.V { - case 1: - if v, ok := u._u.(*TransactionMetaV1); ok { - return v - } else { - var zero TransactionMetaV1 - u._u = &zero - return &zero +func (v ContractEventType) GetU32() uint32 { return uint32(v) } +func (v *ContractEventType) SetU32(n uint32) { *v = ContractEventType(n) } +func (v *ContractEventType) XdrPointer() interface{} { return v } +func (ContractEventType) XdrTypeName() string { return "ContractEventType" } +func (v ContractEventType) XdrValue() interface{} { return v } +func (v *ContractEventType) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } + +type XdrType_ContractEventType = *ContractEventType + +func XDR_ContractEventType(v *ContractEventType) *ContractEventType { return v } + +type _XdrVec_unbounded_SCVal []SCVal + +func (_XdrVec_unbounded_SCVal) XdrBound() uint32 { + const bound uint32 = 4294967295 // Force error if not const or doesn't fit + return bound +} +func (_XdrVec_unbounded_SCVal) XdrCheckLen(length uint32) { + if length > uint32(4294967295) { + XdrPanic("_XdrVec_unbounded_SCVal length %d exceeds bound 4294967295", length) + } else if int(length) < 0 { + XdrPanic("_XdrVec_unbounded_SCVal length %d exceeds max int", length) + } +} +func (v _XdrVec_unbounded_SCVal) GetVecLen() uint32 { return uint32(len(v)) } +func (v *_XdrVec_unbounded_SCVal) SetVecLen(length uint32) { + v.XdrCheckLen(length) + if int(length) <= cap(*v) { + if int(length) != len(*v) { + *v = (*v)[:int(length)] } - default: - XdrPanic("TransactionMeta.V1 accessed when V == %v", u.V) - return nil + return + } + newcap := 2 * cap(*v) + if newcap < int(length) { // also catches overflow where 2*cap < 0 + newcap = int(length) + } else if bound := uint(4294967295); uint(newcap) > bound { + if int(bound) < 0 { + bound = ^uint(0) >> 1 + } + newcap = int(bound) } + nv := make([]SCVal, int(length), newcap) + copy(nv, *v) + *v = nv } -func (u *TransactionMeta) V2() *TransactionMetaV2 { +func (v *_XdrVec_unbounded_SCVal) XdrMarshalN(x XDR, name string, n uint32) { + v.XdrCheckLen(n) + for i := 0; i < int(n); i++ { + if i >= len(*v) { + v.SetVecLen(uint32(i + 1)) + } + XDR_SCVal(&(*v)[i]).XdrMarshal(x, x.Sprintf("%s[%d]", name, i)) + } + if int(n) < len(*v) { + *v = (*v)[:int(n)] + } +} +func (v *_XdrVec_unbounded_SCVal) XdrRecurse(x XDR, name string) { + size := XdrSize{Size: uint32(len(*v)), Bound: 4294967295} + x.Marshal(name, &size) + v.XdrMarshalN(x, name, size.Size) +} +func (_XdrVec_unbounded_SCVal) XdrTypeName() string { return "SCVal<>" } +func (v *_XdrVec_unbounded_SCVal) XdrPointer() interface{} { return (*[]SCVal)(v) } +func (v _XdrVec_unbounded_SCVal) XdrValue() interface{} { return ([]SCVal)(v) } +func (v *_XdrVec_unbounded_SCVal) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } + +type XdrType_XdrAnon_ContractEvent_Body_V0 = *XdrAnon_ContractEvent_Body_V0 + +func (v *XdrAnon_ContractEvent_Body_V0) XdrPointer() interface{} { return v } +func (XdrAnon_ContractEvent_Body_V0) XdrTypeName() string { return "XdrAnon_ContractEvent_Body_V0" } +func (v XdrAnon_ContractEvent_Body_V0) XdrValue() interface{} { return v } +func (v *XdrAnon_ContractEvent_Body_V0) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v *XdrAnon_ContractEvent_Body_V0) XdrRecurse(x XDR, name string) { + if name != "" { + name = x.Sprintf("%s.", name) + } + x.Marshal(x.Sprintf("%stopics", name), (*_XdrVec_unbounded_SCVal)(&v.Topics)) + x.Marshal(x.Sprintf("%sdata", name), XDR_SCVal(&v.Data)) +} +func XDR_XdrAnon_ContractEvent_Body_V0(v *XdrAnon_ContractEvent_Body_V0) *XdrAnon_ContractEvent_Body_V0 { + return v +} + +var _XdrTags_XdrAnon_ContractEvent_Body = map[int32]bool{ + XdrToI32(0): true, +} + +func (_ XdrAnon_ContractEvent_Body) XdrValidTags() map[int32]bool { + return _XdrTags_XdrAnon_ContractEvent_Body +} +func (u *XdrAnon_ContractEvent_Body) V0() *XdrAnon_ContractEvent_Body_V0 { switch u.V { - case 2: - if v, ok := u._u.(*TransactionMetaV2); ok { + case 0: + if v, ok := u._u.(*XdrAnon_ContractEvent_Body_V0); ok { return v } else { - var zero TransactionMetaV2 + var zero XdrAnon_ContractEvent_Body_V0 u._u = &zero return &zero } default: - XdrPanic("TransactionMeta.V2 accessed when V == %v", u.V) + XdrPanic("XdrAnon_ContractEvent_Body.V0 accessed when V == %v", u.V) return nil } } -func (u TransactionMeta) XdrValid() bool { +func (u XdrAnon_ContractEvent_Body) XdrValid() bool { switch u.V { - case 0, 1, 2: + case 0: return true } return false } -func (u *TransactionMeta) XdrUnionTag() XdrNum32 { +func (u *XdrAnon_ContractEvent_Body) XdrUnionTag() XdrNum32 { return XDR_int32(&u.V) } -func (u *TransactionMeta) XdrUnionTagName() string { +func (u *XdrAnon_ContractEvent_Body) XdrUnionTagName() string { return "V" } -func (u *TransactionMeta) XdrUnionBody() XdrType { +func (u *XdrAnon_ContractEvent_Body) XdrUnionBody() XdrType { switch u.V { case 0: - return (*_XdrVec_unbounded_OperationMeta)(u.Operations()) - case 1: - return XDR_TransactionMetaV1(u.V1()) - case 2: - return XDR_TransactionMetaV2(u.V2()) + return XDR_XdrAnon_ContractEvent_Body_V0(u.V0()) } return nil } -func (u *TransactionMeta) XdrUnionBodyName() string { +func (u *XdrAnon_ContractEvent_Body) XdrUnionBodyName() string { switch u.V { case 0: - return "Operations" - case 1: - return "V1" - case 2: - return "V2" + return "V0" } return "" } -type XdrType_TransactionMeta = *TransactionMeta +type XdrType_XdrAnon_ContractEvent_Body = *XdrAnon_ContractEvent_Body -func (v *TransactionMeta) XdrPointer() interface{} { return v } -func (TransactionMeta) XdrTypeName() string { return "TransactionMeta" } -func (v TransactionMeta) XdrValue() interface{} { return v } -func (v *TransactionMeta) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -func (u *TransactionMeta) XdrRecurse(x XDR, name string) { +func (v *XdrAnon_ContractEvent_Body) XdrPointer() interface{} { return v } +func (XdrAnon_ContractEvent_Body) XdrTypeName() string { return "XdrAnon_ContractEvent_Body" } +func (v XdrAnon_ContractEvent_Body) XdrValue() interface{} { return v } +func (v *XdrAnon_ContractEvent_Body) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (u *XdrAnon_ContractEvent_Body) XdrRecurse(x XDR, name string) { if name != "" { name = x.Sprintf("%s.", name) } XDR_int32(&u.V).XdrMarshal(x, x.Sprintf("%sv", name)) switch u.V { case 0: - x.Marshal(x.Sprintf("%soperations", name), (*_XdrVec_unbounded_OperationMeta)(u.Operations())) + x.Marshal(x.Sprintf("%sv0", name), XDR_XdrAnon_ContractEvent_Body_V0(u.V0())) return + } + XdrPanic("invalid V (%v) in XdrAnon_ContractEvent_Body", u.V) +} +func XDR_XdrAnon_ContractEvent_Body(v *XdrAnon_ContractEvent_Body) *XdrAnon_ContractEvent_Body { + return v +} + +type _XdrPtr_Hash struct { + p **Hash +} +type _ptrflag_Hash _XdrPtr_Hash + +func (v _ptrflag_Hash) String() string { + if *v.p == nil { + return "nil" + } + return "non-nil" +} +func (v _ptrflag_Hash) Scan(ss fmt.ScanState, r rune) error { + tok, err := ss.Token(true, func(c rune) bool { + return c == '-' || (c >= 'a' && c <= 'z') + }) + if err != nil { + return err + } + switch string(tok) { + case "nil": + v.SetU32(0) + case "non-nil": + v.SetU32(1) + default: + return XdrError("Hash flag should be \"nil\" or \"non-nil\"") + } + return nil +} +func (v _ptrflag_Hash) GetU32() uint32 { + if *v.p == nil { + return 0 + } + return 1 +} +func (v _ptrflag_Hash) SetU32(nv uint32) { + switch nv { + case 0: + *v.p = nil case 1: - x.Marshal(x.Sprintf("%sv1", name), XDR_TransactionMetaV1(u.V1())) - return - case 2: - x.Marshal(x.Sprintf("%sv2", name), XDR_TransactionMetaV2(u.V2())) - return + if *v.p == nil { + *v.p = new(Hash) + } + default: + XdrPanic("*Hash present flag value %d should be 0 or 1", nv) } - XdrPanic("invalid V (%v) in TransactionMeta", u.V) } -func XDR_TransactionMeta(v *TransactionMeta) *TransactionMeta { return v } +func (_ptrflag_Hash) XdrTypeName() string { return "Hash?" } +func (v _ptrflag_Hash) XdrPointer() interface{} { return nil } +func (v _ptrflag_Hash) XdrValue() interface{} { return v.GetU32() != 0 } +func (v _ptrflag_Hash) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v _ptrflag_Hash) XdrBound() uint32 { return 1 } +func (v _XdrPtr_Hash) GetPresent() bool { return *v.p != nil } +func (v _XdrPtr_Hash) SetPresent(present bool) { + if !present { + *v.p = nil + } else if *v.p == nil { + *v.p = new(Hash) + } +} +func (v _XdrPtr_Hash) XdrMarshalValue(x XDR, name string) { + if *v.p != nil { + XDR_Hash(*v.p).XdrMarshal(x, name) + } +} +func (v _XdrPtr_Hash) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v _XdrPtr_Hash) XdrRecurse(x XDR, name string) { + x.Marshal(name, _ptrflag_Hash(v)) + v.XdrMarshalValue(x, name) +} +func (_XdrPtr_Hash) XdrTypeName() string { return "Hash*" } +func (v _XdrPtr_Hash) XdrPointer() interface{} { return v.p } +func (v _XdrPtr_Hash) XdrValue() interface{} { return *v.p } -type XdrType_TransactionResultMeta = *TransactionResultMeta +type XdrType_ContractEvent = *ContractEvent -func (v *TransactionResultMeta) XdrPointer() interface{} { return v } -func (TransactionResultMeta) XdrTypeName() string { return "TransactionResultMeta" } -func (v TransactionResultMeta) XdrValue() interface{} { return v } -func (v *TransactionResultMeta) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -func (v *TransactionResultMeta) XdrRecurse(x XDR, name string) { +func (v *ContractEvent) XdrPointer() interface{} { return v } +func (ContractEvent) XdrTypeName() string { return "ContractEvent" } +func (v ContractEvent) XdrValue() interface{} { return v } +func (v *ContractEvent) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v *ContractEvent) XdrRecurse(x XDR, name string) { if name != "" { name = x.Sprintf("%s.", name) } - x.Marshal(x.Sprintf("%sresult", name), XDR_TransactionResultPair(&v.Result)) - x.Marshal(x.Sprintf("%sfeeProcessing", name), XDR_LedgerEntryChanges(&v.FeeProcessing)) - x.Marshal(x.Sprintf("%stxApplyProcessing", name), XDR_TransactionMeta(&v.TxApplyProcessing)) + x.Marshal(x.Sprintf("%sext", name), XDR_ExtensionPoint(&v.Ext)) + x.Marshal(x.Sprintf("%scontractID", name), _XdrPtr_Hash{&v.ContractID}) + x.Marshal(x.Sprintf("%stype", name), XDR_ContractEventType(&v.Type)) + x.Marshal(x.Sprintf("%sbody", name), XDR_XdrAnon_ContractEvent_Body(&v.Body)) } -func XDR_TransactionResultMeta(v *TransactionResultMeta) *TransactionResultMeta { return v } +func XDR_ContractEvent(v *ContractEvent) *ContractEvent { return v } -type XdrType_UpgradeEntryMeta = *UpgradeEntryMeta +type XdrType_DiagnosticEvent = *DiagnosticEvent -func (v *UpgradeEntryMeta) XdrPointer() interface{} { return v } -func (UpgradeEntryMeta) XdrTypeName() string { return "UpgradeEntryMeta" } -func (v UpgradeEntryMeta) XdrValue() interface{} { return v } -func (v *UpgradeEntryMeta) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -func (v *UpgradeEntryMeta) XdrRecurse(x XDR, name string) { +func (v *DiagnosticEvent) XdrPointer() interface{} { return v } +func (DiagnosticEvent) XdrTypeName() string { return "DiagnosticEvent" } +func (v DiagnosticEvent) XdrValue() interface{} { return v } +func (v *DiagnosticEvent) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v *DiagnosticEvent) XdrRecurse(x XDR, name string) { if name != "" { name = x.Sprintf("%s.", name) } - x.Marshal(x.Sprintf("%supgrade", name), XDR_LedgerUpgrade(&v.Upgrade)) - x.Marshal(x.Sprintf("%schanges", name), XDR_LedgerEntryChanges(&v.Changes)) + x.Marshal(x.Sprintf("%sinSuccessfulContractCall", name), XDR_bool(&v.InSuccessfulContractCall)) + x.Marshal(x.Sprintf("%sevent", name), XDR_ContractEvent(&v.Event)) } -func XDR_UpgradeEntryMeta(v *UpgradeEntryMeta) *UpgradeEntryMeta { return v } +func XDR_DiagnosticEvent(v *DiagnosticEvent) *DiagnosticEvent { return v } -type _XdrVec_unbounded_TransactionResultMeta []TransactionResultMeta +type _XdrVec_unbounded_ContractEvent []ContractEvent -func (_XdrVec_unbounded_TransactionResultMeta) XdrBound() uint32 { +func (_XdrVec_unbounded_ContractEvent) XdrBound() uint32 { const bound uint32 = 4294967295 // Force error if not const or doesn't fit return bound } -func (_XdrVec_unbounded_TransactionResultMeta) XdrCheckLen(length uint32) { +func (_XdrVec_unbounded_ContractEvent) XdrCheckLen(length uint32) { if length > uint32(4294967295) { - XdrPanic("_XdrVec_unbounded_TransactionResultMeta length %d exceeds bound 4294967295", length) + XdrPanic("_XdrVec_unbounded_ContractEvent length %d exceeds bound 4294967295", length) } else if int(length) < 0 { - XdrPanic("_XdrVec_unbounded_TransactionResultMeta length %d exceeds max int", length) + XdrPanic("_XdrVec_unbounded_ContractEvent length %d exceeds max int", length) } } -func (v _XdrVec_unbounded_TransactionResultMeta) GetVecLen() uint32 { return uint32(len(v)) } -func (v *_XdrVec_unbounded_TransactionResultMeta) SetVecLen(length uint32) { +func (v _XdrVec_unbounded_ContractEvent) GetVecLen() uint32 { return uint32(len(v)) } +func (v *_XdrVec_unbounded_ContractEvent) SetVecLen(length uint32) { v.XdrCheckLen(length) if int(length) <= cap(*v) { if int(length) != len(*v) { @@ -9947,51 +11798,47 @@ func (v *_XdrVec_unbounded_TransactionResultMeta) SetVecLen(length uint32) { } newcap = int(bound) } - nv := make([]TransactionResultMeta, int(length), newcap) + nv := make([]ContractEvent, int(length), newcap) copy(nv, *v) *v = nv } -func (v *_XdrVec_unbounded_TransactionResultMeta) XdrMarshalN(x XDR, name string, n uint32) { +func (v *_XdrVec_unbounded_ContractEvent) XdrMarshalN(x XDR, name string, n uint32) { v.XdrCheckLen(n) for i := 0; i < int(n); i++ { if i >= len(*v) { v.SetVecLen(uint32(i + 1)) } - XDR_TransactionResultMeta(&(*v)[i]).XdrMarshal(x, x.Sprintf("%s[%d]", name, i)) + XDR_ContractEvent(&(*v)[i]).XdrMarshal(x, x.Sprintf("%s[%d]", name, i)) } if int(n) < len(*v) { *v = (*v)[:int(n)] } } -func (v *_XdrVec_unbounded_TransactionResultMeta) XdrRecurse(x XDR, name string) { +func (v *_XdrVec_unbounded_ContractEvent) XdrRecurse(x XDR, name string) { size := XdrSize{Size: uint32(len(*v)), Bound: 4294967295} x.Marshal(name, &size) v.XdrMarshalN(x, name, size.Size) } -func (_XdrVec_unbounded_TransactionResultMeta) XdrTypeName() string { return "TransactionResultMeta<>" } -func (v *_XdrVec_unbounded_TransactionResultMeta) XdrPointer() interface{} { - return (*[]TransactionResultMeta)(v) -} -func (v _XdrVec_unbounded_TransactionResultMeta) XdrValue() interface{} { - return ([]TransactionResultMeta)(v) -} -func (v *_XdrVec_unbounded_TransactionResultMeta) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (_XdrVec_unbounded_ContractEvent) XdrTypeName() string { return "ContractEvent<>" } +func (v *_XdrVec_unbounded_ContractEvent) XdrPointer() interface{} { return (*[]ContractEvent)(v) } +func (v _XdrVec_unbounded_ContractEvent) XdrValue() interface{} { return ([]ContractEvent)(v) } +func (v *_XdrVec_unbounded_ContractEvent) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -type _XdrVec_unbounded_UpgradeEntryMeta []UpgradeEntryMeta +type _XdrVec_unbounded_DiagnosticEvent []DiagnosticEvent -func (_XdrVec_unbounded_UpgradeEntryMeta) XdrBound() uint32 { +func (_XdrVec_unbounded_DiagnosticEvent) XdrBound() uint32 { const bound uint32 = 4294967295 // Force error if not const or doesn't fit return bound } -func (_XdrVec_unbounded_UpgradeEntryMeta) XdrCheckLen(length uint32) { +func (_XdrVec_unbounded_DiagnosticEvent) XdrCheckLen(length uint32) { if length > uint32(4294967295) { - XdrPanic("_XdrVec_unbounded_UpgradeEntryMeta length %d exceeds bound 4294967295", length) + XdrPanic("_XdrVec_unbounded_DiagnosticEvent length %d exceeds bound 4294967295", length) } else if int(length) < 0 { - XdrPanic("_XdrVec_unbounded_UpgradeEntryMeta length %d exceeds max int", length) + XdrPanic("_XdrVec_unbounded_DiagnosticEvent length %d exceeds max int", length) } } -func (v _XdrVec_unbounded_UpgradeEntryMeta) GetVecLen() uint32 { return uint32(len(v)) } -func (v *_XdrVec_unbounded_UpgradeEntryMeta) SetVecLen(length uint32) { +func (v _XdrVec_unbounded_DiagnosticEvent) GetVecLen() uint32 { return uint32(len(v)) } +func (v *_XdrVec_unbounded_DiagnosticEvent) SetVecLen(length uint32) { v.XdrCheckLen(length) if int(length) <= cap(*v) { if int(length) != len(*v) { @@ -10008,1292 +11855,2086 @@ func (v *_XdrVec_unbounded_UpgradeEntryMeta) SetVecLen(length uint32) { } newcap = int(bound) } - nv := make([]UpgradeEntryMeta, int(length), newcap) + nv := make([]DiagnosticEvent, int(length), newcap) copy(nv, *v) *v = nv } -func (v *_XdrVec_unbounded_UpgradeEntryMeta) XdrMarshalN(x XDR, name string, n uint32) { +func (v *_XdrVec_unbounded_DiagnosticEvent) XdrMarshalN(x XDR, name string, n uint32) { v.XdrCheckLen(n) for i := 0; i < int(n); i++ { if i >= len(*v) { v.SetVecLen(uint32(i + 1)) } - XDR_UpgradeEntryMeta(&(*v)[i]).XdrMarshal(x, x.Sprintf("%s[%d]", name, i)) + XDR_DiagnosticEvent(&(*v)[i]).XdrMarshal(x, x.Sprintf("%s[%d]", name, i)) } if int(n) < len(*v) { *v = (*v)[:int(n)] } } -func (v *_XdrVec_unbounded_UpgradeEntryMeta) XdrRecurse(x XDR, name string) { +func (v *_XdrVec_unbounded_DiagnosticEvent) XdrRecurse(x XDR, name string) { size := XdrSize{Size: uint32(len(*v)), Bound: 4294967295} x.Marshal(name, &size) v.XdrMarshalN(x, name, size.Size) } -func (_XdrVec_unbounded_UpgradeEntryMeta) XdrTypeName() string { return "UpgradeEntryMeta<>" } -func (v *_XdrVec_unbounded_UpgradeEntryMeta) XdrPointer() interface{} { - return (*[]UpgradeEntryMeta)(v) -} -func (v _XdrVec_unbounded_UpgradeEntryMeta) XdrValue() interface{} { return ([]UpgradeEntryMeta)(v) } -func (v *_XdrVec_unbounded_UpgradeEntryMeta) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (_XdrVec_unbounded_DiagnosticEvent) XdrTypeName() string { return "DiagnosticEvent<>" } +func (v *_XdrVec_unbounded_DiagnosticEvent) XdrPointer() interface{} { return (*[]DiagnosticEvent)(v) } +func (v _XdrVec_unbounded_DiagnosticEvent) XdrValue() interface{} { return ([]DiagnosticEvent)(v) } +func (v *_XdrVec_unbounded_DiagnosticEvent) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -type _XdrVec_unbounded_SCPHistoryEntry []SCPHistoryEntry +type XdrType_SorobanTransactionMeta = *SorobanTransactionMeta -func (_XdrVec_unbounded_SCPHistoryEntry) XdrBound() uint32 { - const bound uint32 = 4294967295 // Force error if not const or doesn't fit - return bound +func (v *SorobanTransactionMeta) XdrPointer() interface{} { return v } +func (SorobanTransactionMeta) XdrTypeName() string { return "SorobanTransactionMeta" } +func (v SorobanTransactionMeta) XdrValue() interface{} { return v } +func (v *SorobanTransactionMeta) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v *SorobanTransactionMeta) XdrRecurse(x XDR, name string) { + if name != "" { + name = x.Sprintf("%s.", name) + } + x.Marshal(x.Sprintf("%sext", name), XDR_ExtensionPoint(&v.Ext)) + x.Marshal(x.Sprintf("%sevents", name), (*_XdrVec_unbounded_ContractEvent)(&v.Events)) + x.Marshal(x.Sprintf("%sreturnValue", name), XDR_SCVal(&v.ReturnValue)) + x.Marshal(x.Sprintf("%sdiagnosticEvents", name), (*_XdrVec_unbounded_DiagnosticEvent)(&v.DiagnosticEvents)) } -func (_XdrVec_unbounded_SCPHistoryEntry) XdrCheckLen(length uint32) { - if length > uint32(4294967295) { - XdrPanic("_XdrVec_unbounded_SCPHistoryEntry length %d exceeds bound 4294967295", length) - } else if int(length) < 0 { - XdrPanic("_XdrVec_unbounded_SCPHistoryEntry length %d exceeds max int", length) +func XDR_SorobanTransactionMeta(v *SorobanTransactionMeta) *SorobanTransactionMeta { return v } + +type _XdrPtr_SorobanTransactionMeta struct { + p **SorobanTransactionMeta +} +type _ptrflag_SorobanTransactionMeta _XdrPtr_SorobanTransactionMeta + +func (v _ptrflag_SorobanTransactionMeta) String() string { + if *v.p == nil { + return "nil" } + return "non-nil" } -func (v _XdrVec_unbounded_SCPHistoryEntry) GetVecLen() uint32 { return uint32(len(v)) } -func (v *_XdrVec_unbounded_SCPHistoryEntry) SetVecLen(length uint32) { - v.XdrCheckLen(length) - if int(length) <= cap(*v) { - if int(length) != len(*v) { - *v = (*v)[:int(length)] - } - return +func (v _ptrflag_SorobanTransactionMeta) Scan(ss fmt.ScanState, r rune) error { + tok, err := ss.Token(true, func(c rune) bool { + return c == '-' || (c >= 'a' && c <= 'z') + }) + if err != nil { + return err } - newcap := 2 * cap(*v) - if newcap < int(length) { // also catches overflow where 2*cap < 0 - newcap = int(length) - } else if bound := uint(4294967295); uint(newcap) > bound { - if int(bound) < 0 { - bound = ^uint(0) >> 1 - } - newcap = int(bound) + switch string(tok) { + case "nil": + v.SetU32(0) + case "non-nil": + v.SetU32(1) + default: + return XdrError("SorobanTransactionMeta flag should be \"nil\" or \"non-nil\"") } - nv := make([]SCPHistoryEntry, int(length), newcap) - copy(nv, *v) - *v = nv + return nil } -func (v *_XdrVec_unbounded_SCPHistoryEntry) XdrMarshalN(x XDR, name string, n uint32) { - v.XdrCheckLen(n) - for i := 0; i < int(n); i++ { - if i >= len(*v) { - v.SetVecLen(uint32(i + 1)) +func (v _ptrflag_SorobanTransactionMeta) GetU32() uint32 { + if *v.p == nil { + return 0 + } + return 1 +} +func (v _ptrflag_SorobanTransactionMeta) SetU32(nv uint32) { + switch nv { + case 0: + *v.p = nil + case 1: + if *v.p == nil { + *v.p = new(SorobanTransactionMeta) } - XDR_SCPHistoryEntry(&(*v)[i]).XdrMarshal(x, x.Sprintf("%s[%d]", name, i)) + default: + XdrPanic("*SorobanTransactionMeta present flag value %d should be 0 or 1", nv) } - if int(n) < len(*v) { - *v = (*v)[:int(n)] +} +func (_ptrflag_SorobanTransactionMeta) XdrTypeName() string { return "SorobanTransactionMeta?" } +func (v _ptrflag_SorobanTransactionMeta) XdrPointer() interface{} { return nil } +func (v _ptrflag_SorobanTransactionMeta) XdrValue() interface{} { return v.GetU32() != 0 } +func (v _ptrflag_SorobanTransactionMeta) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v _ptrflag_SorobanTransactionMeta) XdrBound() uint32 { return 1 } +func (v _XdrPtr_SorobanTransactionMeta) GetPresent() bool { return *v.p != nil } +func (v _XdrPtr_SorobanTransactionMeta) SetPresent(present bool) { + if !present { + *v.p = nil + } else if *v.p == nil { + *v.p = new(SorobanTransactionMeta) } } -func (v *_XdrVec_unbounded_SCPHistoryEntry) XdrRecurse(x XDR, name string) { - size := XdrSize{Size: uint32(len(*v)), Bound: 4294967295} - x.Marshal(name, &size) - v.XdrMarshalN(x, name, size.Size) +func (v _XdrPtr_SorobanTransactionMeta) XdrMarshalValue(x XDR, name string) { + if *v.p != nil { + XDR_SorobanTransactionMeta(*v.p).XdrMarshal(x, name) + } } -func (_XdrVec_unbounded_SCPHistoryEntry) XdrTypeName() string { return "SCPHistoryEntry<>" } -func (v *_XdrVec_unbounded_SCPHistoryEntry) XdrPointer() interface{} { return (*[]SCPHistoryEntry)(v) } -func (v _XdrVec_unbounded_SCPHistoryEntry) XdrValue() interface{} { return ([]SCPHistoryEntry)(v) } -func (v *_XdrVec_unbounded_SCPHistoryEntry) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v _XdrPtr_SorobanTransactionMeta) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v _XdrPtr_SorobanTransactionMeta) XdrRecurse(x XDR, name string) { + x.Marshal(name, _ptrflag_SorobanTransactionMeta(v)) + v.XdrMarshalValue(x, name) +} +func (_XdrPtr_SorobanTransactionMeta) XdrTypeName() string { return "SorobanTransactionMeta*" } +func (v _XdrPtr_SorobanTransactionMeta) XdrPointer() interface{} { return v.p } +func (v _XdrPtr_SorobanTransactionMeta) XdrValue() interface{} { return *v.p } -type XdrType_LedgerCloseMetaV0 = *LedgerCloseMetaV0 +type XdrType_TransactionMetaV3 = *TransactionMetaV3 -func (v *LedgerCloseMetaV0) XdrPointer() interface{} { return v } -func (LedgerCloseMetaV0) XdrTypeName() string { return "LedgerCloseMetaV0" } -func (v LedgerCloseMetaV0) XdrValue() interface{} { return v } -func (v *LedgerCloseMetaV0) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -func (v *LedgerCloseMetaV0) XdrRecurse(x XDR, name string) { +func (v *TransactionMetaV3) XdrPointer() interface{} { return v } +func (TransactionMetaV3) XdrTypeName() string { return "TransactionMetaV3" } +func (v TransactionMetaV3) XdrValue() interface{} { return v } +func (v *TransactionMetaV3) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v *TransactionMetaV3) XdrRecurse(x XDR, name string) { if name != "" { name = x.Sprintf("%s.", name) } - x.Marshal(x.Sprintf("%sledgerHeader", name), XDR_LedgerHeaderHistoryEntry(&v.LedgerHeader)) - x.Marshal(x.Sprintf("%stxSet", name), XDR_TransactionSet(&v.TxSet)) - x.Marshal(x.Sprintf("%stxProcessing", name), (*_XdrVec_unbounded_TransactionResultMeta)(&v.TxProcessing)) - x.Marshal(x.Sprintf("%supgradesProcessing", name), (*_XdrVec_unbounded_UpgradeEntryMeta)(&v.UpgradesProcessing)) - x.Marshal(x.Sprintf("%sscpInfo", name), (*_XdrVec_unbounded_SCPHistoryEntry)(&v.ScpInfo)) + x.Marshal(x.Sprintf("%sext", name), XDR_ExtensionPoint(&v.Ext)) + x.Marshal(x.Sprintf("%stxChangesBefore", name), XDR_LedgerEntryChanges(&v.TxChangesBefore)) + x.Marshal(x.Sprintf("%soperations", name), (*_XdrVec_unbounded_OperationMeta)(&v.Operations)) + x.Marshal(x.Sprintf("%stxChangesAfter", name), XDR_LedgerEntryChanges(&v.TxChangesAfter)) + x.Marshal(x.Sprintf("%ssorobanMeta", name), _XdrPtr_SorobanTransactionMeta{&v.SorobanMeta}) } -func XDR_LedgerCloseMetaV0(v *LedgerCloseMetaV0) *LedgerCloseMetaV0 { return v } +func XDR_TransactionMetaV3(v *TransactionMetaV3) *TransactionMetaV3 { return v } -type XdrType_LedgerCloseMetaV1 = *LedgerCloseMetaV1 +type XdrType_InvokeHostFunctionSuccessPreImage = *InvokeHostFunctionSuccessPreImage -func (v *LedgerCloseMetaV1) XdrPointer() interface{} { return v } -func (LedgerCloseMetaV1) XdrTypeName() string { return "LedgerCloseMetaV1" } -func (v LedgerCloseMetaV1) XdrValue() interface{} { return v } -func (v *LedgerCloseMetaV1) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -func (v *LedgerCloseMetaV1) XdrRecurse(x XDR, name string) { +func (v *InvokeHostFunctionSuccessPreImage) XdrPointer() interface{} { return v } +func (InvokeHostFunctionSuccessPreImage) XdrTypeName() string { + return "InvokeHostFunctionSuccessPreImage" +} +func (v InvokeHostFunctionSuccessPreImage) XdrValue() interface{} { return v } +func (v *InvokeHostFunctionSuccessPreImage) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v *InvokeHostFunctionSuccessPreImage) XdrRecurse(x XDR, name string) { if name != "" { name = x.Sprintf("%s.", name) } - x.Marshal(x.Sprintf("%sledgerHeader", name), XDR_LedgerHeaderHistoryEntry(&v.LedgerHeader)) - x.Marshal(x.Sprintf("%stxSet", name), XDR_GeneralizedTransactionSet(&v.TxSet)) - x.Marshal(x.Sprintf("%stxProcessing", name), (*_XdrVec_unbounded_TransactionResultMeta)(&v.TxProcessing)) - x.Marshal(x.Sprintf("%supgradesProcessing", name), (*_XdrVec_unbounded_UpgradeEntryMeta)(&v.UpgradesProcessing)) - x.Marshal(x.Sprintf("%sscpInfo", name), (*_XdrVec_unbounded_SCPHistoryEntry)(&v.ScpInfo)) + x.Marshal(x.Sprintf("%sreturnValue", name), XDR_SCVal(&v.ReturnValue)) + x.Marshal(x.Sprintf("%sevents", name), (*_XdrVec_unbounded_ContractEvent)(&v.Events)) +} +func XDR_InvokeHostFunctionSuccessPreImage(v *InvokeHostFunctionSuccessPreImage) *InvokeHostFunctionSuccessPreImage { + return v } -func XDR_LedgerCloseMetaV1(v *LedgerCloseMetaV1) *LedgerCloseMetaV1 { return v } -var _XdrTags_LedgerCloseMeta = map[int32]bool{ +var _XdrTags_TransactionMeta = map[int32]bool{ XdrToI32(0): true, XdrToI32(1): true, + XdrToI32(2): true, + XdrToI32(3): true, } -func (_ LedgerCloseMeta) XdrValidTags() map[int32]bool { - return _XdrTags_LedgerCloseMeta +func (_ TransactionMeta) XdrValidTags() map[int32]bool { + return _XdrTags_TransactionMeta } -func (u *LedgerCloseMeta) V0() *LedgerCloseMetaV0 { +func (u *TransactionMeta) Operations() *[]OperationMeta { switch u.V { case 0: - if v, ok := u._u.(*LedgerCloseMetaV0); ok { + if v, ok := u._u.(*[]OperationMeta); ok { return v } else { - var zero LedgerCloseMetaV0 + var zero []OperationMeta u._u = &zero return &zero } default: - XdrPanic("LedgerCloseMeta.V0 accessed when V == %v", u.V) + XdrPanic("TransactionMeta.Operations accessed when V == %v", u.V) return nil } } -func (u *LedgerCloseMeta) V1() *LedgerCloseMetaV1 { +func (u *TransactionMeta) V1() *TransactionMetaV1 { switch u.V { case 1: - if v, ok := u._u.(*LedgerCloseMetaV1); ok { + if v, ok := u._u.(*TransactionMetaV1); ok { return v } else { - var zero LedgerCloseMetaV1 + var zero TransactionMetaV1 u._u = &zero return &zero } default: - XdrPanic("LedgerCloseMeta.V1 accessed when V == %v", u.V) + XdrPanic("TransactionMeta.V1 accessed when V == %v", u.V) return nil } } -func (u LedgerCloseMeta) XdrValid() bool { +func (u *TransactionMeta) V2() *TransactionMetaV2 { switch u.V { - case 0, 1: + case 2: + if v, ok := u._u.(*TransactionMetaV2); ok { + return v + } else { + var zero TransactionMetaV2 + u._u = &zero + return &zero + } + default: + XdrPanic("TransactionMeta.V2 accessed when V == %v", u.V) + return nil + } +} +func (u *TransactionMeta) V3() *TransactionMetaV3 { + switch u.V { + case 3: + if v, ok := u._u.(*TransactionMetaV3); ok { + return v + } else { + var zero TransactionMetaV3 + u._u = &zero + return &zero + } + default: + XdrPanic("TransactionMeta.V3 accessed when V == %v", u.V) + return nil + } +} +func (u TransactionMeta) XdrValid() bool { + switch u.V { + case 0, 1, 2, 3: return true } return false } -func (u *LedgerCloseMeta) XdrUnionTag() XdrNum32 { +func (u *TransactionMeta) XdrUnionTag() XdrNum32 { return XDR_int32(&u.V) } -func (u *LedgerCloseMeta) XdrUnionTagName() string { +func (u *TransactionMeta) XdrUnionTagName() string { return "V" } -func (u *LedgerCloseMeta) XdrUnionBody() XdrType { +func (u *TransactionMeta) XdrUnionBody() XdrType { switch u.V { case 0: - return XDR_LedgerCloseMetaV0(u.V0()) + return (*_XdrVec_unbounded_OperationMeta)(u.Operations()) case 1: - return XDR_LedgerCloseMetaV1(u.V1()) + return XDR_TransactionMetaV1(u.V1()) + case 2: + return XDR_TransactionMetaV2(u.V2()) + case 3: + return XDR_TransactionMetaV3(u.V3()) } return nil } -func (u *LedgerCloseMeta) XdrUnionBodyName() string { +func (u *TransactionMeta) XdrUnionBodyName() string { switch u.V { case 0: - return "V0" + return "Operations" case 1: return "V1" + case 2: + return "V2" + case 3: + return "V3" } return "" } -type XdrType_LedgerCloseMeta = *LedgerCloseMeta +type XdrType_TransactionMeta = *TransactionMeta -func (v *LedgerCloseMeta) XdrPointer() interface{} { return v } -func (LedgerCloseMeta) XdrTypeName() string { return "LedgerCloseMeta" } -func (v LedgerCloseMeta) XdrValue() interface{} { return v } -func (v *LedgerCloseMeta) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -func (u *LedgerCloseMeta) XdrRecurse(x XDR, name string) { +func (v *TransactionMeta) XdrPointer() interface{} { return v } +func (TransactionMeta) XdrTypeName() string { return "TransactionMeta" } +func (v TransactionMeta) XdrValue() interface{} { return v } +func (v *TransactionMeta) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (u *TransactionMeta) XdrRecurse(x XDR, name string) { if name != "" { name = x.Sprintf("%s.", name) } XDR_int32(&u.V).XdrMarshal(x, x.Sprintf("%sv", name)) switch u.V { case 0: - x.Marshal(x.Sprintf("%sv0", name), XDR_LedgerCloseMetaV0(u.V0())) + x.Marshal(x.Sprintf("%soperations", name), (*_XdrVec_unbounded_OperationMeta)(u.Operations())) return case 1: - x.Marshal(x.Sprintf("%sv1", name), XDR_LedgerCloseMetaV1(u.V1())) + x.Marshal(x.Sprintf("%sv1", name), XDR_TransactionMetaV1(u.V1())) + return + case 2: + x.Marshal(x.Sprintf("%sv2", name), XDR_TransactionMetaV2(u.V2())) + return + case 3: + x.Marshal(x.Sprintf("%sv3", name), XDR_TransactionMetaV3(u.V3())) return } - XdrPanic("invalid V (%v) in LedgerCloseMeta", u.V) + XdrPanic("invalid V (%v) in TransactionMeta", u.V) } -func XDR_LedgerCloseMeta(v *LedgerCloseMeta) *LedgerCloseMeta { return v } +func XDR_TransactionMeta(v *TransactionMeta) *TransactionMeta { return v } -var _XdrNames_ErrorCode = map[int32]string{ - int32(ERR_MISC): "ERR_MISC", - int32(ERR_DATA): "ERR_DATA", - int32(ERR_CONF): "ERR_CONF", - int32(ERR_AUTH): "ERR_AUTH", - int32(ERR_LOAD): "ERR_LOAD", +type XdrType_TransactionResultMeta = *TransactionResultMeta + +func (v *TransactionResultMeta) XdrPointer() interface{} { return v } +func (TransactionResultMeta) XdrTypeName() string { return "TransactionResultMeta" } +func (v TransactionResultMeta) XdrValue() interface{} { return v } +func (v *TransactionResultMeta) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v *TransactionResultMeta) XdrRecurse(x XDR, name string) { + if name != "" { + name = x.Sprintf("%s.", name) + } + x.Marshal(x.Sprintf("%sresult", name), XDR_TransactionResultPair(&v.Result)) + x.Marshal(x.Sprintf("%sfeeProcessing", name), XDR_LedgerEntryChanges(&v.FeeProcessing)) + x.Marshal(x.Sprintf("%stxApplyProcessing", name), XDR_TransactionMeta(&v.TxApplyProcessing)) } -var _XdrValues_ErrorCode = map[string]int32{ - "ERR_MISC": int32(ERR_MISC), - "ERR_DATA": int32(ERR_DATA), - "ERR_CONF": int32(ERR_CONF), - "ERR_AUTH": int32(ERR_AUTH), - "ERR_LOAD": int32(ERR_LOAD), +func XDR_TransactionResultMeta(v *TransactionResultMeta) *TransactionResultMeta { return v } + +type XdrType_UpgradeEntryMeta = *UpgradeEntryMeta + +func (v *UpgradeEntryMeta) XdrPointer() interface{} { return v } +func (UpgradeEntryMeta) XdrTypeName() string { return "UpgradeEntryMeta" } +func (v UpgradeEntryMeta) XdrValue() interface{} { return v } +func (v *UpgradeEntryMeta) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v *UpgradeEntryMeta) XdrRecurse(x XDR, name string) { + if name != "" { + name = x.Sprintf("%s.", name) + } + x.Marshal(x.Sprintf("%supgrade", name), XDR_LedgerUpgrade(&v.Upgrade)) + x.Marshal(x.Sprintf("%schanges", name), XDR_LedgerEntryChanges(&v.Changes)) } +func XDR_UpgradeEntryMeta(v *UpgradeEntryMeta) *UpgradeEntryMeta { return v } -func (ErrorCode) XdrEnumNames() map[int32]string { - return _XdrNames_ErrorCode +type _XdrVec_unbounded_TransactionResultMeta []TransactionResultMeta + +func (_XdrVec_unbounded_TransactionResultMeta) XdrBound() uint32 { + const bound uint32 = 4294967295 // Force error if not const or doesn't fit + return bound } -func (v ErrorCode) String() string { - if s, ok := _XdrNames_ErrorCode[int32(v)]; ok { - return s +func (_XdrVec_unbounded_TransactionResultMeta) XdrCheckLen(length uint32) { + if length > uint32(4294967295) { + XdrPanic("_XdrVec_unbounded_TransactionResultMeta length %d exceeds bound 4294967295", length) + } else if int(length) < 0 { + XdrPanic("_XdrVec_unbounded_TransactionResultMeta length %d exceeds max int", length) } - return fmt.Sprintf("ErrorCode#%d", v) } -func (v *ErrorCode) Scan(ss fmt.ScanState, _ rune) error { - if tok, err := ss.Token(true, XdrSymChar); err != nil { - return err - } else { - stok := string(tok) - if val, ok := _XdrValues_ErrorCode[stok]; ok { - *v = ErrorCode(val) - return nil - } else if stok == "ErrorCode" { - if n, err := fmt.Fscanf(ss, "#%d", (*int32)(v)); n == 1 && err == nil { - return nil - } +func (v _XdrVec_unbounded_TransactionResultMeta) GetVecLen() uint32 { return uint32(len(v)) } +func (v *_XdrVec_unbounded_TransactionResultMeta) SetVecLen(length uint32) { + v.XdrCheckLen(length) + if int(length) <= cap(*v) { + if int(length) != len(*v) { + *v = (*v)[:int(length)] } - return XdrError(fmt.Sprintf("%s is not a valid ErrorCode.", stok)) + return } + newcap := 2 * cap(*v) + if newcap < int(length) { // also catches overflow where 2*cap < 0 + newcap = int(length) + } else if bound := uint(4294967295); uint(newcap) > bound { + if int(bound) < 0 { + bound = ^uint(0) >> 1 + } + newcap = int(bound) + } + nv := make([]TransactionResultMeta, int(length), newcap) + copy(nv, *v) + *v = nv } -func (v ErrorCode) GetU32() uint32 { return uint32(v) } -func (v *ErrorCode) SetU32(n uint32) { *v = ErrorCode(n) } -func (v *ErrorCode) XdrPointer() interface{} { return v } -func (ErrorCode) XdrTypeName() string { return "ErrorCode" } -func (v ErrorCode) XdrValue() interface{} { return v } -func (v *ErrorCode) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } - -type XdrType_ErrorCode = *ErrorCode - -func XDR_ErrorCode(v *ErrorCode) *ErrorCode { return v } - -var _XdrComments_ErrorCode = map[int32]string{ - int32(ERR_MISC): "Unspecific error", - int32(ERR_DATA): "Malformed data", - int32(ERR_CONF): "Misconfiguration error", - int32(ERR_AUTH): "Authentication failure", - int32(ERR_LOAD): "System overloaded", +func (v *_XdrVec_unbounded_TransactionResultMeta) XdrMarshalN(x XDR, name string, n uint32) { + v.XdrCheckLen(n) + for i := 0; i < int(n); i++ { + if i >= len(*v) { + v.SetVecLen(uint32(i + 1)) + } + XDR_TransactionResultMeta(&(*v)[i]).XdrMarshal(x, x.Sprintf("%s[%d]", name, i)) + } + if int(n) < len(*v) { + *v = (*v)[:int(n)] + } } - -func (e ErrorCode) XdrEnumComments() map[int32]string { - return _XdrComments_ErrorCode +func (v *_XdrVec_unbounded_TransactionResultMeta) XdrRecurse(x XDR, name string) { + size := XdrSize{Size: uint32(len(*v)), Bound: 4294967295} + x.Marshal(name, &size) + v.XdrMarshalN(x, name, size.Size) +} +func (_XdrVec_unbounded_TransactionResultMeta) XdrTypeName() string { return "TransactionResultMeta<>" } +func (v *_XdrVec_unbounded_TransactionResultMeta) XdrPointer() interface{} { + return (*[]TransactionResultMeta)(v) +} +func (v _XdrVec_unbounded_TransactionResultMeta) XdrValue() interface{} { + return ([]TransactionResultMeta)(v) } +func (v *_XdrVec_unbounded_TransactionResultMeta) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -type XdrType_Error = *Error +type _XdrVec_unbounded_UpgradeEntryMeta []UpgradeEntryMeta -func (v *Error) XdrPointer() interface{} { return v } -func (Error) XdrTypeName() string { return "Error" } -func (v Error) XdrValue() interface{} { return v } -func (v *Error) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -func (v *Error) XdrRecurse(x XDR, name string) { - if name != "" { - name = x.Sprintf("%s.", name) +func (_XdrVec_unbounded_UpgradeEntryMeta) XdrBound() uint32 { + const bound uint32 = 4294967295 // Force error if not const or doesn't fit + return bound +} +func (_XdrVec_unbounded_UpgradeEntryMeta) XdrCheckLen(length uint32) { + if length > uint32(4294967295) { + XdrPanic("_XdrVec_unbounded_UpgradeEntryMeta length %d exceeds bound 4294967295", length) + } else if int(length) < 0 { + XdrPanic("_XdrVec_unbounded_UpgradeEntryMeta length %d exceeds max int", length) } - x.Marshal(x.Sprintf("%scode", name), XDR_ErrorCode(&v.Code)) - x.Marshal(x.Sprintf("%smsg", name), XdrString{&v.Msg, 100}) } -func XDR_Error(v *Error) *Error { return v } - -type XdrType_SendMore = *SendMore - -func (v *SendMore) XdrPointer() interface{} { return v } -func (SendMore) XdrTypeName() string { return "SendMore" } -func (v SendMore) XdrValue() interface{} { return v } -func (v *SendMore) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -func (v *SendMore) XdrRecurse(x XDR, name string) { - if name != "" { - name = x.Sprintf("%s.", name) +func (v _XdrVec_unbounded_UpgradeEntryMeta) GetVecLen() uint32 { return uint32(len(v)) } +func (v *_XdrVec_unbounded_UpgradeEntryMeta) SetVecLen(length uint32) { + v.XdrCheckLen(length) + if int(length) <= cap(*v) { + if int(length) != len(*v) { + *v = (*v)[:int(length)] + } + return } - x.Marshal(x.Sprintf("%snumMessages", name), XDR_Uint32(&v.NumMessages)) + newcap := 2 * cap(*v) + if newcap < int(length) { // also catches overflow where 2*cap < 0 + newcap = int(length) + } else if bound := uint(4294967295); uint(newcap) > bound { + if int(bound) < 0 { + bound = ^uint(0) >> 1 + } + newcap = int(bound) + } + nv := make([]UpgradeEntryMeta, int(length), newcap) + copy(nv, *v) + *v = nv } -func XDR_SendMore(v *SendMore) *SendMore { return v } - -type XdrType_AuthCert = *AuthCert - -func (v *AuthCert) XdrPointer() interface{} { return v } -func (AuthCert) XdrTypeName() string { return "AuthCert" } -func (v AuthCert) XdrValue() interface{} { return v } -func (v *AuthCert) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -func (v *AuthCert) XdrRecurse(x XDR, name string) { - if name != "" { - name = x.Sprintf("%s.", name) +func (v *_XdrVec_unbounded_UpgradeEntryMeta) XdrMarshalN(x XDR, name string, n uint32) { + v.XdrCheckLen(n) + for i := 0; i < int(n); i++ { + if i >= len(*v) { + v.SetVecLen(uint32(i + 1)) + } + XDR_UpgradeEntryMeta(&(*v)[i]).XdrMarshal(x, x.Sprintf("%s[%d]", name, i)) + } + if int(n) < len(*v) { + *v = (*v)[:int(n)] } - x.Marshal(x.Sprintf("%spubkey", name), XDR_Curve25519Public(&v.Pubkey)) - x.Marshal(x.Sprintf("%sexpiration", name), XDR_Uint64(&v.Expiration)) - x.Marshal(x.Sprintf("%ssig", name), XDR_Signature(&v.Sig)) } -func XDR_AuthCert(v *AuthCert) *AuthCert { return v } +func (v *_XdrVec_unbounded_UpgradeEntryMeta) XdrRecurse(x XDR, name string) { + size := XdrSize{Size: uint32(len(*v)), Bound: 4294967295} + x.Marshal(name, &size) + v.XdrMarshalN(x, name, size.Size) +} +func (_XdrVec_unbounded_UpgradeEntryMeta) XdrTypeName() string { return "UpgradeEntryMeta<>" } +func (v *_XdrVec_unbounded_UpgradeEntryMeta) XdrPointer() interface{} { + return (*[]UpgradeEntryMeta)(v) +} +func (v _XdrVec_unbounded_UpgradeEntryMeta) XdrValue() interface{} { return ([]UpgradeEntryMeta)(v) } +func (v *_XdrVec_unbounded_UpgradeEntryMeta) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -type XdrType_Hello = *Hello +type _XdrVec_unbounded_SCPHistoryEntry []SCPHistoryEntry -func (v *Hello) XdrPointer() interface{} { return v } -func (Hello) XdrTypeName() string { return "Hello" } -func (v Hello) XdrValue() interface{} { return v } -func (v *Hello) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -func (v *Hello) XdrRecurse(x XDR, name string) { - if name != "" { - name = x.Sprintf("%s.", name) +func (_XdrVec_unbounded_SCPHistoryEntry) XdrBound() uint32 { + const bound uint32 = 4294967295 // Force error if not const or doesn't fit + return bound +} +func (_XdrVec_unbounded_SCPHistoryEntry) XdrCheckLen(length uint32) { + if length > uint32(4294967295) { + XdrPanic("_XdrVec_unbounded_SCPHistoryEntry length %d exceeds bound 4294967295", length) + } else if int(length) < 0 { + XdrPanic("_XdrVec_unbounded_SCPHistoryEntry length %d exceeds max int", length) } - x.Marshal(x.Sprintf("%sledgerVersion", name), XDR_Uint32(&v.LedgerVersion)) - x.Marshal(x.Sprintf("%soverlayVersion", name), XDR_Uint32(&v.OverlayVersion)) - x.Marshal(x.Sprintf("%soverlayMinVersion", name), XDR_Uint32(&v.OverlayMinVersion)) - x.Marshal(x.Sprintf("%snetworkID", name), XDR_Hash(&v.NetworkID)) - x.Marshal(x.Sprintf("%sversionStr", name), XdrString{&v.VersionStr, 100}) - x.Marshal(x.Sprintf("%slisteningPort", name), XDR_int32(&v.ListeningPort)) - x.Marshal(x.Sprintf("%speerID", name), XDR_NodeID(&v.PeerID)) - x.Marshal(x.Sprintf("%scert", name), XDR_AuthCert(&v.Cert)) - x.Marshal(x.Sprintf("%snonce", name), XDR_Uint256(&v.Nonce)) } -func XDR_Hello(v *Hello) *Hello { return v } +func (v _XdrVec_unbounded_SCPHistoryEntry) GetVecLen() uint32 { return uint32(len(v)) } +func (v *_XdrVec_unbounded_SCPHistoryEntry) SetVecLen(length uint32) { + v.XdrCheckLen(length) + if int(length) <= cap(*v) { + if int(length) != len(*v) { + *v = (*v)[:int(length)] + } + return + } + newcap := 2 * cap(*v) + if newcap < int(length) { // also catches overflow where 2*cap < 0 + newcap = int(length) + } else if bound := uint(4294967295); uint(newcap) > bound { + if int(bound) < 0 { + bound = ^uint(0) >> 1 + } + newcap = int(bound) + } + nv := make([]SCPHistoryEntry, int(length), newcap) + copy(nv, *v) + *v = nv +} +func (v *_XdrVec_unbounded_SCPHistoryEntry) XdrMarshalN(x XDR, name string, n uint32) { + v.XdrCheckLen(n) + for i := 0; i < int(n); i++ { + if i >= len(*v) { + v.SetVecLen(uint32(i + 1)) + } + XDR_SCPHistoryEntry(&(*v)[i]).XdrMarshal(x, x.Sprintf("%s[%d]", name, i)) + } + if int(n) < len(*v) { + *v = (*v)[:int(n)] + } +} +func (v *_XdrVec_unbounded_SCPHistoryEntry) XdrRecurse(x XDR, name string) { + size := XdrSize{Size: uint32(len(*v)), Bound: 4294967295} + x.Marshal(name, &size) + v.XdrMarshalN(x, name, size.Size) +} +func (_XdrVec_unbounded_SCPHistoryEntry) XdrTypeName() string { return "SCPHistoryEntry<>" } +func (v *_XdrVec_unbounded_SCPHistoryEntry) XdrPointer() interface{} { return (*[]SCPHistoryEntry)(v) } +func (v _XdrVec_unbounded_SCPHistoryEntry) XdrValue() interface{} { return ([]SCPHistoryEntry)(v) } +func (v *_XdrVec_unbounded_SCPHistoryEntry) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -type XdrType_Auth = *Auth +type XdrType_LedgerCloseMetaV0 = *LedgerCloseMetaV0 -func (v *Auth) XdrPointer() interface{} { return v } -func (Auth) XdrTypeName() string { return "Auth" } -func (v Auth) XdrValue() interface{} { return v } -func (v *Auth) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -func (v *Auth) XdrRecurse(x XDR, name string) { +func (v *LedgerCloseMetaV0) XdrPointer() interface{} { return v } +func (LedgerCloseMetaV0) XdrTypeName() string { return "LedgerCloseMetaV0" } +func (v LedgerCloseMetaV0) XdrValue() interface{} { return v } +func (v *LedgerCloseMetaV0) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v *LedgerCloseMetaV0) XdrRecurse(x XDR, name string) { if name != "" { name = x.Sprintf("%s.", name) } - x.Marshal(x.Sprintf("%sunused", name), XDR_int32(&v.Unused)) + x.Marshal(x.Sprintf("%sledgerHeader", name), XDR_LedgerHeaderHistoryEntry(&v.LedgerHeader)) + x.Marshal(x.Sprintf("%stxSet", name), XDR_TransactionSet(&v.TxSet)) + x.Marshal(x.Sprintf("%stxProcessing", name), (*_XdrVec_unbounded_TransactionResultMeta)(&v.TxProcessing)) + x.Marshal(x.Sprintf("%supgradesProcessing", name), (*_XdrVec_unbounded_UpgradeEntryMeta)(&v.UpgradesProcessing)) + x.Marshal(x.Sprintf("%sscpInfo", name), (*_XdrVec_unbounded_SCPHistoryEntry)(&v.ScpInfo)) } -func XDR_Auth(v *Auth) *Auth { return v } +func XDR_LedgerCloseMetaV0(v *LedgerCloseMetaV0) *LedgerCloseMetaV0 { return v } -var _XdrNames_IPAddrType = map[int32]string{ - int32(IPv4): "IPv4", - int32(IPv6): "IPv6", +type _XdrVec_unbounded_LedgerKey []LedgerKey + +func (_XdrVec_unbounded_LedgerKey) XdrBound() uint32 { + const bound uint32 = 4294967295 // Force error if not const or doesn't fit + return bound } -var _XdrValues_IPAddrType = map[string]int32{ - "IPv4": int32(IPv4), - "IPv6": int32(IPv6), -} - -func (IPAddrType) XdrEnumNames() map[int32]string { - return _XdrNames_IPAddrType +func (_XdrVec_unbounded_LedgerKey) XdrCheckLen(length uint32) { + if length > uint32(4294967295) { + XdrPanic("_XdrVec_unbounded_LedgerKey length %d exceeds bound 4294967295", length) + } else if int(length) < 0 { + XdrPanic("_XdrVec_unbounded_LedgerKey length %d exceeds max int", length) + } } -func (v IPAddrType) String() string { - if s, ok := _XdrNames_IPAddrType[int32(v)]; ok { - return s +func (v _XdrVec_unbounded_LedgerKey) GetVecLen() uint32 { return uint32(len(v)) } +func (v *_XdrVec_unbounded_LedgerKey) SetVecLen(length uint32) { + v.XdrCheckLen(length) + if int(length) <= cap(*v) { + if int(length) != len(*v) { + *v = (*v)[:int(length)] + } + return } - return fmt.Sprintf("IPAddrType#%d", v) + newcap := 2 * cap(*v) + if newcap < int(length) { // also catches overflow where 2*cap < 0 + newcap = int(length) + } else if bound := uint(4294967295); uint(newcap) > bound { + if int(bound) < 0 { + bound = ^uint(0) >> 1 + } + newcap = int(bound) + } + nv := make([]LedgerKey, int(length), newcap) + copy(nv, *v) + *v = nv } -func (v *IPAddrType) Scan(ss fmt.ScanState, _ rune) error { - if tok, err := ss.Token(true, XdrSymChar); err != nil { - return err - } else { - stok := string(tok) - if val, ok := _XdrValues_IPAddrType[stok]; ok { - *v = IPAddrType(val) - return nil - } else if stok == "IPAddrType" { - if n, err := fmt.Fscanf(ss, "#%d", (*int32)(v)); n == 1 && err == nil { - return nil - } +func (v *_XdrVec_unbounded_LedgerKey) XdrMarshalN(x XDR, name string, n uint32) { + v.XdrCheckLen(n) + for i := 0; i < int(n); i++ { + if i >= len(*v) { + v.SetVecLen(uint32(i + 1)) } - return XdrError(fmt.Sprintf("%s is not a valid IPAddrType.", stok)) + XDR_LedgerKey(&(*v)[i]).XdrMarshal(x, x.Sprintf("%s[%d]", name, i)) + } + if int(n) < len(*v) { + *v = (*v)[:int(n)] } } -func (v IPAddrType) GetU32() uint32 { return uint32(v) } -func (v *IPAddrType) SetU32(n uint32) { *v = IPAddrType(n) } -func (v *IPAddrType) XdrPointer() interface{} { return v } -func (IPAddrType) XdrTypeName() string { return "IPAddrType" } -func (v IPAddrType) XdrValue() interface{} { return v } -func (v *IPAddrType) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v *_XdrVec_unbounded_LedgerKey) XdrRecurse(x XDR, name string) { + size := XdrSize{Size: uint32(len(*v)), Bound: 4294967295} + x.Marshal(name, &size) + v.XdrMarshalN(x, name, size.Size) +} +func (_XdrVec_unbounded_LedgerKey) XdrTypeName() string { return "LedgerKey<>" } +func (v *_XdrVec_unbounded_LedgerKey) XdrPointer() interface{} { return (*[]LedgerKey)(v) } +func (v _XdrVec_unbounded_LedgerKey) XdrValue() interface{} { return ([]LedgerKey)(v) } +func (v *_XdrVec_unbounded_LedgerKey) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -type XdrType_IPAddrType = *IPAddrType +type _XdrVec_unbounded_LedgerEntry []LedgerEntry -func XDR_IPAddrType(v *IPAddrType) *IPAddrType { return v } +func (_XdrVec_unbounded_LedgerEntry) XdrBound() uint32 { + const bound uint32 = 4294967295 // Force error if not const or doesn't fit + return bound +} +func (_XdrVec_unbounded_LedgerEntry) XdrCheckLen(length uint32) { + if length > uint32(4294967295) { + XdrPanic("_XdrVec_unbounded_LedgerEntry length %d exceeds bound 4294967295", length) + } else if int(length) < 0 { + XdrPanic("_XdrVec_unbounded_LedgerEntry length %d exceeds max int", length) + } +} +func (v _XdrVec_unbounded_LedgerEntry) GetVecLen() uint32 { return uint32(len(v)) } +func (v *_XdrVec_unbounded_LedgerEntry) SetVecLen(length uint32) { + v.XdrCheckLen(length) + if int(length) <= cap(*v) { + if int(length) != len(*v) { + *v = (*v)[:int(length)] + } + return + } + newcap := 2 * cap(*v) + if newcap < int(length) { // also catches overflow where 2*cap < 0 + newcap = int(length) + } else if bound := uint(4294967295); uint(newcap) > bound { + if int(bound) < 0 { + bound = ^uint(0) >> 1 + } + newcap = int(bound) + } + nv := make([]LedgerEntry, int(length), newcap) + copy(nv, *v) + *v = nv +} +func (v *_XdrVec_unbounded_LedgerEntry) XdrMarshalN(x XDR, name string, n uint32) { + v.XdrCheckLen(n) + for i := 0; i < int(n); i++ { + if i >= len(*v) { + v.SetVecLen(uint32(i + 1)) + } + XDR_LedgerEntry(&(*v)[i]).XdrMarshal(x, x.Sprintf("%s[%d]", name, i)) + } + if int(n) < len(*v) { + *v = (*v)[:int(n)] + } +} +func (v *_XdrVec_unbounded_LedgerEntry) XdrRecurse(x XDR, name string) { + size := XdrSize{Size: uint32(len(*v)), Bound: 4294967295} + x.Marshal(name, &size) + v.XdrMarshalN(x, name, size.Size) +} +func (_XdrVec_unbounded_LedgerEntry) XdrTypeName() string { return "LedgerEntry<>" } +func (v *_XdrVec_unbounded_LedgerEntry) XdrPointer() interface{} { return (*[]LedgerEntry)(v) } +func (v _XdrVec_unbounded_LedgerEntry) XdrValue() interface{} { return ([]LedgerEntry)(v) } +func (v *_XdrVec_unbounded_LedgerEntry) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -type _XdrArray_16_opaque [16]byte +type XdrType_LedgerCloseMetaV1 = *LedgerCloseMetaV1 -func (v *_XdrArray_16_opaque) GetByteSlice() []byte { return v[:] } -func (v *_XdrArray_16_opaque) XdrTypeName() string { return "opaque[]" } -func (v *_XdrArray_16_opaque) XdrValue() interface{} { return v[:] } -func (v *_XdrArray_16_opaque) XdrPointer() interface{} { return (*[16]byte)(v) } -func (v *_XdrArray_16_opaque) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -func (v *_XdrArray_16_opaque) String() string { return fmt.Sprintf("%x", v[:]) } -func (v *_XdrArray_16_opaque) Scan(ss fmt.ScanState, c rune) error { - return XdrArrayOpaqueScan(v[:], ss, c) -} -func (_XdrArray_16_opaque) XdrArraySize() uint32 { - const bound uint32 = 16 // Force error if not const or doesn't fit - return bound +func (v *LedgerCloseMetaV1) XdrPointer() interface{} { return v } +func (LedgerCloseMetaV1) XdrTypeName() string { return "LedgerCloseMetaV1" } +func (v LedgerCloseMetaV1) XdrValue() interface{} { return v } +func (v *LedgerCloseMetaV1) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v *LedgerCloseMetaV1) XdrRecurse(x XDR, name string) { + if name != "" { + name = x.Sprintf("%s.", name) + } + x.Marshal(x.Sprintf("%sext", name), XDR_ExtensionPoint(&v.Ext)) + x.Marshal(x.Sprintf("%sledgerHeader", name), XDR_LedgerHeaderHistoryEntry(&v.LedgerHeader)) + x.Marshal(x.Sprintf("%stxSet", name), XDR_GeneralizedTransactionSet(&v.TxSet)) + x.Marshal(x.Sprintf("%stxProcessing", name), (*_XdrVec_unbounded_TransactionResultMeta)(&v.TxProcessing)) + x.Marshal(x.Sprintf("%supgradesProcessing", name), (*_XdrVec_unbounded_UpgradeEntryMeta)(&v.UpgradesProcessing)) + x.Marshal(x.Sprintf("%sscpInfo", name), (*_XdrVec_unbounded_SCPHistoryEntry)(&v.ScpInfo)) + x.Marshal(x.Sprintf("%stotalByteSizeOfBucketList", name), XDR_Uint64(&v.TotalByteSizeOfBucketList)) + x.Marshal(x.Sprintf("%sevictedTemporaryLedgerKeys", name), (*_XdrVec_unbounded_LedgerKey)(&v.EvictedTemporaryLedgerKeys)) + x.Marshal(x.Sprintf("%sevictedPersistentLedgerEntries", name), (*_XdrVec_unbounded_LedgerEntry)(&v.EvictedPersistentLedgerEntries)) } +func XDR_LedgerCloseMetaV1(v *LedgerCloseMetaV1) *LedgerCloseMetaV1 { return v } -var _XdrTags_XdrAnon_PeerAddress_Ip = map[int32]bool{ - XdrToI32(IPv4): true, - XdrToI32(IPv6): true, +var _XdrTags_LedgerCloseMeta = map[int32]bool{ + XdrToI32(0): true, + XdrToI32(1): true, } -func (_ XdrAnon_PeerAddress_Ip) XdrValidTags() map[int32]bool { - return _XdrTags_XdrAnon_PeerAddress_Ip +func (_ LedgerCloseMeta) XdrValidTags() map[int32]bool { + return _XdrTags_LedgerCloseMeta } -func (u *XdrAnon_PeerAddress_Ip) Ipv4() *[4]byte { - switch u.Type { - case IPv4: - if v, ok := u._u.(*[4]byte); ok { +func (u *LedgerCloseMeta) V0() *LedgerCloseMetaV0 { + switch u.V { + case 0: + if v, ok := u._u.(*LedgerCloseMetaV0); ok { return v } else { - var zero [4]byte + var zero LedgerCloseMetaV0 u._u = &zero return &zero } default: - XdrPanic("XdrAnon_PeerAddress_Ip.Ipv4 accessed when Type == %v", u.Type) + XdrPanic("LedgerCloseMeta.V0 accessed when V == %v", u.V) return nil } } -func (u *XdrAnon_PeerAddress_Ip) Ipv6() *[16]byte { - switch u.Type { - case IPv6: - if v, ok := u._u.(*[16]byte); ok { +func (u *LedgerCloseMeta) V1() *LedgerCloseMetaV1 { + switch u.V { + case 1: + if v, ok := u._u.(*LedgerCloseMetaV1); ok { return v } else { - var zero [16]byte + var zero LedgerCloseMetaV1 u._u = &zero return &zero } default: - XdrPanic("XdrAnon_PeerAddress_Ip.Ipv6 accessed when Type == %v", u.Type) + XdrPanic("LedgerCloseMeta.V1 accessed when V == %v", u.V) return nil } } -func (u XdrAnon_PeerAddress_Ip) XdrValid() bool { - switch u.Type { - case IPv4, IPv6: +func (u LedgerCloseMeta) XdrValid() bool { + switch u.V { + case 0, 1: return true } return false } -func (u *XdrAnon_PeerAddress_Ip) XdrUnionTag() XdrNum32 { - return XDR_IPAddrType(&u.Type) +func (u *LedgerCloseMeta) XdrUnionTag() XdrNum32 { + return XDR_int32(&u.V) } -func (u *XdrAnon_PeerAddress_Ip) XdrUnionTagName() string { - return "Type" +func (u *LedgerCloseMeta) XdrUnionTagName() string { + return "V" } -func (u *XdrAnon_PeerAddress_Ip) XdrUnionBody() XdrType { - switch u.Type { - case IPv4: - return (*_XdrArray_4_opaque)(u.Ipv4()) - case IPv6: - return (*_XdrArray_16_opaque)(u.Ipv6()) +func (u *LedgerCloseMeta) XdrUnionBody() XdrType { + switch u.V { + case 0: + return XDR_LedgerCloseMetaV0(u.V0()) + case 1: + return XDR_LedgerCloseMetaV1(u.V1()) } return nil } -func (u *XdrAnon_PeerAddress_Ip) XdrUnionBodyName() string { - switch u.Type { - case IPv4: - return "Ipv4" - case IPv6: - return "Ipv6" +func (u *LedgerCloseMeta) XdrUnionBodyName() string { + switch u.V { + case 0: + return "V0" + case 1: + return "V1" } return "" } -type XdrType_XdrAnon_PeerAddress_Ip = *XdrAnon_PeerAddress_Ip +type XdrType_LedgerCloseMeta = *LedgerCloseMeta -func (v *XdrAnon_PeerAddress_Ip) XdrPointer() interface{} { return v } -func (XdrAnon_PeerAddress_Ip) XdrTypeName() string { return "XdrAnon_PeerAddress_Ip" } -func (v XdrAnon_PeerAddress_Ip) XdrValue() interface{} { return v } -func (v *XdrAnon_PeerAddress_Ip) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -func (u *XdrAnon_PeerAddress_Ip) XdrRecurse(x XDR, name string) { +func (v *LedgerCloseMeta) XdrPointer() interface{} { return v } +func (LedgerCloseMeta) XdrTypeName() string { return "LedgerCloseMeta" } +func (v LedgerCloseMeta) XdrValue() interface{} { return v } +func (v *LedgerCloseMeta) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (u *LedgerCloseMeta) XdrRecurse(x XDR, name string) { if name != "" { name = x.Sprintf("%s.", name) } - XDR_IPAddrType(&u.Type).XdrMarshal(x, x.Sprintf("%stype", name)) - switch u.Type { - case IPv4: - x.Marshal(x.Sprintf("%sipv4", name), (*_XdrArray_4_opaque)(u.Ipv4())) + XDR_int32(&u.V).XdrMarshal(x, x.Sprintf("%sv", name)) + switch u.V { + case 0: + x.Marshal(x.Sprintf("%sv0", name), XDR_LedgerCloseMetaV0(u.V0())) return - case IPv6: - x.Marshal(x.Sprintf("%sipv6", name), (*_XdrArray_16_opaque)(u.Ipv6())) + case 1: + x.Marshal(x.Sprintf("%sv1", name), XDR_LedgerCloseMetaV1(u.V1())) return } - XdrPanic("invalid Type (%v) in XdrAnon_PeerAddress_Ip", u.Type) + XdrPanic("invalid V (%v) in LedgerCloseMeta", u.V) } -func XDR_XdrAnon_PeerAddress_Ip(v *XdrAnon_PeerAddress_Ip) *XdrAnon_PeerAddress_Ip { return v } - -type XdrType_PeerAddress = *PeerAddress +func XDR_LedgerCloseMeta(v *LedgerCloseMeta) *LedgerCloseMeta { return v } -func (v *PeerAddress) XdrPointer() interface{} { return v } -func (PeerAddress) XdrTypeName() string { return "PeerAddress" } -func (v PeerAddress) XdrValue() interface{} { return v } -func (v *PeerAddress) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -func (v *PeerAddress) XdrRecurse(x XDR, name string) { - if name != "" { - name = x.Sprintf("%s.", name) - } - x.Marshal(x.Sprintf("%sip", name), XDR_XdrAnon_PeerAddress_Ip(&v.Ip)) - x.Marshal(x.Sprintf("%sport", name), XDR_Uint32(&v.Port)) - x.Marshal(x.Sprintf("%snumFailures", name), XDR_Uint32(&v.NumFailures)) +var _XdrNames_ErrorCode = map[int32]string{ + int32(ERR_MISC): "ERR_MISC", + int32(ERR_DATA): "ERR_DATA", + int32(ERR_CONF): "ERR_CONF", + int32(ERR_AUTH): "ERR_AUTH", + int32(ERR_LOAD): "ERR_LOAD", } -func XDR_PeerAddress(v *PeerAddress) *PeerAddress { return v } - -var _XdrNames_MessageType = map[int32]string{ - int32(ERROR_MSG): "ERROR_MSG", - int32(AUTH): "AUTH", - int32(DONT_HAVE): "DONT_HAVE", - int32(GET_PEERS): "GET_PEERS", - int32(PEERS): "PEERS", - int32(GET_TX_SET): "GET_TX_SET", - int32(TX_SET): "TX_SET", - int32(GENERALIZED_TX_SET): "GENERALIZED_TX_SET", - int32(TRANSACTION): "TRANSACTION", - int32(GET_SCP_QUORUMSET): "GET_SCP_QUORUMSET", - int32(SCP_QUORUMSET): "SCP_QUORUMSET", - int32(SCP_MESSAGE): "SCP_MESSAGE", - int32(GET_SCP_STATE): "GET_SCP_STATE", - int32(HELLO): "HELLO", - int32(SURVEY_REQUEST): "SURVEY_REQUEST", - int32(SURVEY_RESPONSE): "SURVEY_RESPONSE", - int32(SEND_MORE): "SEND_MORE", -} -var _XdrValues_MessageType = map[string]int32{ - "ERROR_MSG": int32(ERROR_MSG), - "AUTH": int32(AUTH), - "DONT_HAVE": int32(DONT_HAVE), - "GET_PEERS": int32(GET_PEERS), - "PEERS": int32(PEERS), - "GET_TX_SET": int32(GET_TX_SET), - "TX_SET": int32(TX_SET), - "GENERALIZED_TX_SET": int32(GENERALIZED_TX_SET), - "TRANSACTION": int32(TRANSACTION), - "GET_SCP_QUORUMSET": int32(GET_SCP_QUORUMSET), - "SCP_QUORUMSET": int32(SCP_QUORUMSET), - "SCP_MESSAGE": int32(SCP_MESSAGE), - "GET_SCP_STATE": int32(GET_SCP_STATE), - "HELLO": int32(HELLO), - "SURVEY_REQUEST": int32(SURVEY_REQUEST), - "SURVEY_RESPONSE": int32(SURVEY_RESPONSE), - "SEND_MORE": int32(SEND_MORE), +var _XdrValues_ErrorCode = map[string]int32{ + "ERR_MISC": int32(ERR_MISC), + "ERR_DATA": int32(ERR_DATA), + "ERR_CONF": int32(ERR_CONF), + "ERR_AUTH": int32(ERR_AUTH), + "ERR_LOAD": int32(ERR_LOAD), } -func (MessageType) XdrEnumNames() map[int32]string { - return _XdrNames_MessageType +func (ErrorCode) XdrEnumNames() map[int32]string { + return _XdrNames_ErrorCode } -func (v MessageType) String() string { - if s, ok := _XdrNames_MessageType[int32(v)]; ok { +func (v ErrorCode) String() string { + if s, ok := _XdrNames_ErrorCode[int32(v)]; ok { return s } - return fmt.Sprintf("MessageType#%d", v) + return fmt.Sprintf("ErrorCode#%d", v) } -func (v *MessageType) Scan(ss fmt.ScanState, _ rune) error { +func (v *ErrorCode) Scan(ss fmt.ScanState, _ rune) error { if tok, err := ss.Token(true, XdrSymChar); err != nil { return err } else { stok := string(tok) - if val, ok := _XdrValues_MessageType[stok]; ok { - *v = MessageType(val) + if val, ok := _XdrValues_ErrorCode[stok]; ok { + *v = ErrorCode(val) return nil - } else if stok == "MessageType" { + } else if stok == "ErrorCode" { if n, err := fmt.Fscanf(ss, "#%d", (*int32)(v)); n == 1 && err == nil { return nil } } - return XdrError(fmt.Sprintf("%s is not a valid MessageType.", stok)) + return XdrError(fmt.Sprintf("%s is not a valid ErrorCode.", stok)) } } -func (v MessageType) GetU32() uint32 { return uint32(v) } -func (v *MessageType) SetU32(n uint32) { *v = MessageType(n) } -func (v *MessageType) XdrPointer() interface{} { return v } -func (MessageType) XdrTypeName() string { return "MessageType" } -func (v MessageType) XdrValue() interface{} { return v } -func (v *MessageType) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v ErrorCode) GetU32() uint32 { return uint32(v) } +func (v *ErrorCode) SetU32(n uint32) { *v = ErrorCode(n) } +func (v *ErrorCode) XdrPointer() interface{} { return v } +func (ErrorCode) XdrTypeName() string { return "ErrorCode" } +func (v ErrorCode) XdrValue() interface{} { return v } +func (v *ErrorCode) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -type XdrType_MessageType = *MessageType +type XdrType_ErrorCode = *ErrorCode -func XDR_MessageType(v *MessageType) *MessageType { return v } +func XDR_ErrorCode(v *ErrorCode) *ErrorCode { return v } -var _XdrComments_MessageType = map[int32]string{ - int32(GET_PEERS): "gets a list of peers this guy knows about", - int32(GET_TX_SET): "gets a particular txset by hash", - int32(TRANSACTION): "pass on a tx you have heard about", - int32(GET_SCP_QUORUMSET): "SCP", - int32(HELLO): "new messages", +var _XdrComments_ErrorCode = map[int32]string{ + int32(ERR_MISC): "Unspecific error", + int32(ERR_DATA): "Malformed data", + int32(ERR_CONF): "Misconfiguration error", + int32(ERR_AUTH): "Authentication failure", + int32(ERR_LOAD): "System overloaded", } -func (e MessageType) XdrEnumComments() map[int32]string { - return _XdrComments_MessageType +func (e ErrorCode) XdrEnumComments() map[int32]string { + return _XdrComments_ErrorCode } -type XdrType_DontHave = *DontHave +type XdrType_Error = *Error -func (v *DontHave) XdrPointer() interface{} { return v } -func (DontHave) XdrTypeName() string { return "DontHave" } -func (v DontHave) XdrValue() interface{} { return v } -func (v *DontHave) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -func (v *DontHave) XdrRecurse(x XDR, name string) { +func (v *Error) XdrPointer() interface{} { return v } +func (Error) XdrTypeName() string { return "Error" } +func (v Error) XdrValue() interface{} { return v } +func (v *Error) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v *Error) XdrRecurse(x XDR, name string) { if name != "" { name = x.Sprintf("%s.", name) } - x.Marshal(x.Sprintf("%stype", name), XDR_MessageType(&v.Type)) - x.Marshal(x.Sprintf("%sreqHash", name), XDR_Uint256(&v.ReqHash)) + x.Marshal(x.Sprintf("%scode", name), XDR_ErrorCode(&v.Code)) + x.Marshal(x.Sprintf("%smsg", name), XdrString{&v.Msg, 100}) } -func XDR_DontHave(v *DontHave) *DontHave { return v } +func XDR_Error(v *Error) *Error { return v } -var _XdrNames_SurveyMessageCommandType = map[int32]string{ - int32(SURVEY_TOPOLOGY): "SURVEY_TOPOLOGY", -} -var _XdrValues_SurveyMessageCommandType = map[string]int32{ - "SURVEY_TOPOLOGY": int32(SURVEY_TOPOLOGY), -} +type XdrType_SendMore = *SendMore -func (SurveyMessageCommandType) XdrEnumNames() map[int32]string { - return _XdrNames_SurveyMessageCommandType -} -func (v SurveyMessageCommandType) String() string { - if s, ok := _XdrNames_SurveyMessageCommandType[int32(v)]; ok { - return s - } - return fmt.Sprintf("SurveyMessageCommandType#%d", v) -} -func (v *SurveyMessageCommandType) Scan(ss fmt.ScanState, _ rune) error { - if tok, err := ss.Token(true, XdrSymChar); err != nil { - return err - } else { - stok := string(tok) - if val, ok := _XdrValues_SurveyMessageCommandType[stok]; ok { - *v = SurveyMessageCommandType(val) - return nil - } else if stok == "SurveyMessageCommandType" { - if n, err := fmt.Fscanf(ss, "#%d", (*int32)(v)); n == 1 && err == nil { - return nil - } - } - return XdrError(fmt.Sprintf("%s is not a valid SurveyMessageCommandType.", stok)) +func (v *SendMore) XdrPointer() interface{} { return v } +func (SendMore) XdrTypeName() string { return "SendMore" } +func (v SendMore) XdrValue() interface{} { return v } +func (v *SendMore) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v *SendMore) XdrRecurse(x XDR, name string) { + if name != "" { + name = x.Sprintf("%s.", name) } + x.Marshal(x.Sprintf("%snumMessages", name), XDR_Uint32(&v.NumMessages)) } -func (v SurveyMessageCommandType) GetU32() uint32 { return uint32(v) } -func (v *SurveyMessageCommandType) SetU32(n uint32) { *v = SurveyMessageCommandType(n) } -func (v *SurveyMessageCommandType) XdrPointer() interface{} { return v } -func (SurveyMessageCommandType) XdrTypeName() string { return "SurveyMessageCommandType" } -func (v SurveyMessageCommandType) XdrValue() interface{} { return v } -func (v *SurveyMessageCommandType) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } - -type XdrType_SurveyMessageCommandType = *SurveyMessageCommandType - -func XDR_SurveyMessageCommandType(v *SurveyMessageCommandType) *SurveyMessageCommandType { return v } +func XDR_SendMore(v *SendMore) *SendMore { return v } -type XdrType_SurveyRequestMessage = *SurveyRequestMessage +type XdrType_SendMoreExtended = *SendMoreExtended -func (v *SurveyRequestMessage) XdrPointer() interface{} { return v } -func (SurveyRequestMessage) XdrTypeName() string { return "SurveyRequestMessage" } -func (v SurveyRequestMessage) XdrValue() interface{} { return v } -func (v *SurveyRequestMessage) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -func (v *SurveyRequestMessage) XdrRecurse(x XDR, name string) { +func (v *SendMoreExtended) XdrPointer() interface{} { return v } +func (SendMoreExtended) XdrTypeName() string { return "SendMoreExtended" } +func (v SendMoreExtended) XdrValue() interface{} { return v } +func (v *SendMoreExtended) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v *SendMoreExtended) XdrRecurse(x XDR, name string) { if name != "" { name = x.Sprintf("%s.", name) } - x.Marshal(x.Sprintf("%ssurveyorPeerID", name), XDR_NodeID(&v.SurveyorPeerID)) - x.Marshal(x.Sprintf("%ssurveyedPeerID", name), XDR_NodeID(&v.SurveyedPeerID)) - x.Marshal(x.Sprintf("%sledgerNum", name), XDR_Uint32(&v.LedgerNum)) - x.Marshal(x.Sprintf("%sencryptionKey", name), XDR_Curve25519Public(&v.EncryptionKey)) - x.Marshal(x.Sprintf("%scommandType", name), XDR_SurveyMessageCommandType(&v.CommandType)) + x.Marshal(x.Sprintf("%snumMessages", name), XDR_Uint32(&v.NumMessages)) + x.Marshal(x.Sprintf("%snumBytes", name), XDR_Uint32(&v.NumBytes)) } -func XDR_SurveyRequestMessage(v *SurveyRequestMessage) *SurveyRequestMessage { return v } +func XDR_SendMoreExtended(v *SendMoreExtended) *SendMoreExtended { return v } -type XdrType_SignedSurveyRequestMessage = *SignedSurveyRequestMessage +type XdrType_AuthCert = *AuthCert -func (v *SignedSurveyRequestMessage) XdrPointer() interface{} { return v } -func (SignedSurveyRequestMessage) XdrTypeName() string { return "SignedSurveyRequestMessage" } -func (v SignedSurveyRequestMessage) XdrValue() interface{} { return v } -func (v *SignedSurveyRequestMessage) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -func (v *SignedSurveyRequestMessage) XdrRecurse(x XDR, name string) { +func (v *AuthCert) XdrPointer() interface{} { return v } +func (AuthCert) XdrTypeName() string { return "AuthCert" } +func (v AuthCert) XdrValue() interface{} { return v } +func (v *AuthCert) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v *AuthCert) XdrRecurse(x XDR, name string) { if name != "" { name = x.Sprintf("%s.", name) } - x.Marshal(x.Sprintf("%srequestSignature", name), XDR_Signature(&v.RequestSignature)) - x.Marshal(x.Sprintf("%srequest", name), XDR_SurveyRequestMessage(&v.Request)) -} -func XDR_SignedSurveyRequestMessage(v *SignedSurveyRequestMessage) *SignedSurveyRequestMessage { - return v -} - -type XdrType_EncryptedBody struct { - XdrVecOpaque -} - -func XDR_EncryptedBody(v *EncryptedBody) XdrType_EncryptedBody { - return XdrType_EncryptedBody{XdrVecOpaque{v, 64000}} + x.Marshal(x.Sprintf("%spubkey", name), XDR_Curve25519Public(&v.Pubkey)) + x.Marshal(x.Sprintf("%sexpiration", name), XDR_Uint64(&v.Expiration)) + x.Marshal(x.Sprintf("%ssig", name), XDR_Signature(&v.Sig)) } -func (XdrType_EncryptedBody) XdrTypeName() string { return "EncryptedBody" } -func (v XdrType_EncryptedBody) XdrUnwrap() XdrType { return v.XdrVecOpaque } +func XDR_AuthCert(v *AuthCert) *AuthCert { return v } -type XdrType_SurveyResponseMessage = *SurveyResponseMessage +type XdrType_Hello = *Hello -func (v *SurveyResponseMessage) XdrPointer() interface{} { return v } -func (SurveyResponseMessage) XdrTypeName() string { return "SurveyResponseMessage" } -func (v SurveyResponseMessage) XdrValue() interface{} { return v } -func (v *SurveyResponseMessage) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -func (v *SurveyResponseMessage) XdrRecurse(x XDR, name string) { +func (v *Hello) XdrPointer() interface{} { return v } +func (Hello) XdrTypeName() string { return "Hello" } +func (v Hello) XdrValue() interface{} { return v } +func (v *Hello) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v *Hello) XdrRecurse(x XDR, name string) { if name != "" { name = x.Sprintf("%s.", name) } - x.Marshal(x.Sprintf("%ssurveyorPeerID", name), XDR_NodeID(&v.SurveyorPeerID)) - x.Marshal(x.Sprintf("%ssurveyedPeerID", name), XDR_NodeID(&v.SurveyedPeerID)) - x.Marshal(x.Sprintf("%sledgerNum", name), XDR_Uint32(&v.LedgerNum)) - x.Marshal(x.Sprintf("%scommandType", name), XDR_SurveyMessageCommandType(&v.CommandType)) - x.Marshal(x.Sprintf("%sencryptedBody", name), XDR_EncryptedBody(&v.EncryptedBody)) + x.Marshal(x.Sprintf("%sledgerVersion", name), XDR_Uint32(&v.LedgerVersion)) + x.Marshal(x.Sprintf("%soverlayVersion", name), XDR_Uint32(&v.OverlayVersion)) + x.Marshal(x.Sprintf("%soverlayMinVersion", name), XDR_Uint32(&v.OverlayMinVersion)) + x.Marshal(x.Sprintf("%snetworkID", name), XDR_Hash(&v.NetworkID)) + x.Marshal(x.Sprintf("%sversionStr", name), XdrString{&v.VersionStr, 100}) + x.Marshal(x.Sprintf("%slisteningPort", name), XDR_int32(&v.ListeningPort)) + x.Marshal(x.Sprintf("%speerID", name), XDR_NodeID(&v.PeerID)) + x.Marshal(x.Sprintf("%scert", name), XDR_AuthCert(&v.Cert)) + x.Marshal(x.Sprintf("%snonce", name), XDR_Uint256(&v.Nonce)) } -func XDR_SurveyResponseMessage(v *SurveyResponseMessage) *SurveyResponseMessage { return v } +func XDR_Hello(v *Hello) *Hello { return v } -type XdrType_SignedSurveyResponseMessage = *SignedSurveyResponseMessage +type XdrType_Auth = *Auth -func (v *SignedSurveyResponseMessage) XdrPointer() interface{} { return v } -func (SignedSurveyResponseMessage) XdrTypeName() string { return "SignedSurveyResponseMessage" } -func (v SignedSurveyResponseMessage) XdrValue() interface{} { return v } -func (v *SignedSurveyResponseMessage) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -func (v *SignedSurveyResponseMessage) XdrRecurse(x XDR, name string) { +func (v *Auth) XdrPointer() interface{} { return v } +func (Auth) XdrTypeName() string { return "Auth" } +func (v Auth) XdrValue() interface{} { return v } +func (v *Auth) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v *Auth) XdrRecurse(x XDR, name string) { if name != "" { name = x.Sprintf("%s.", name) } - x.Marshal(x.Sprintf("%sresponseSignature", name), XDR_Signature(&v.ResponseSignature)) - x.Marshal(x.Sprintf("%sresponse", name), XDR_SurveyResponseMessage(&v.Response)) + x.Marshal(x.Sprintf("%sflags", name), XDR_int32(&v.Flags)) } -func XDR_SignedSurveyResponseMessage(v *SignedSurveyResponseMessage) *SignedSurveyResponseMessage { - return v +func XDR_Auth(v *Auth) *Auth { return v } + +var _XdrNames_IPAddrType = map[int32]string{ + int32(IPv4): "IPv4", + int32(IPv6): "IPv6", +} +var _XdrValues_IPAddrType = map[string]int32{ + "IPv4": int32(IPv4), + "IPv6": int32(IPv6), } -type XdrType_PeerStats = *PeerStats - -func (v *PeerStats) XdrPointer() interface{} { return v } -func (PeerStats) XdrTypeName() string { return "PeerStats" } -func (v PeerStats) XdrValue() interface{} { return v } -func (v *PeerStats) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -func (v *PeerStats) XdrRecurse(x XDR, name string) { - if name != "" { - name = x.Sprintf("%s.", name) - } - x.Marshal(x.Sprintf("%sid", name), XDR_NodeID(&v.Id)) - x.Marshal(x.Sprintf("%sversionStr", name), XdrString{&v.VersionStr, 100}) - x.Marshal(x.Sprintf("%smessagesRead", name), XDR_Uint64(&v.MessagesRead)) - x.Marshal(x.Sprintf("%smessagesWritten", name), XDR_Uint64(&v.MessagesWritten)) - x.Marshal(x.Sprintf("%sbytesRead", name), XDR_Uint64(&v.BytesRead)) - x.Marshal(x.Sprintf("%sbytesWritten", name), XDR_Uint64(&v.BytesWritten)) - x.Marshal(x.Sprintf("%ssecondsConnected", name), XDR_Uint64(&v.SecondsConnected)) - x.Marshal(x.Sprintf("%suniqueFloodBytesRecv", name), XDR_Uint64(&v.UniqueFloodBytesRecv)) - x.Marshal(x.Sprintf("%sduplicateFloodBytesRecv", name), XDR_Uint64(&v.DuplicateFloodBytesRecv)) - x.Marshal(x.Sprintf("%suniqueFetchBytesRecv", name), XDR_Uint64(&v.UniqueFetchBytesRecv)) - x.Marshal(x.Sprintf("%sduplicateFetchBytesRecv", name), XDR_Uint64(&v.DuplicateFetchBytesRecv)) - x.Marshal(x.Sprintf("%suniqueFloodMessageRecv", name), XDR_Uint64(&v.UniqueFloodMessageRecv)) - x.Marshal(x.Sprintf("%sduplicateFloodMessageRecv", name), XDR_Uint64(&v.DuplicateFloodMessageRecv)) - x.Marshal(x.Sprintf("%suniqueFetchMessageRecv", name), XDR_Uint64(&v.UniqueFetchMessageRecv)) - x.Marshal(x.Sprintf("%sduplicateFetchMessageRecv", name), XDR_Uint64(&v.DuplicateFetchMessageRecv)) -} -func XDR_PeerStats(v *PeerStats) *PeerStats { return v } - -type _XdrVec_25_PeerStats []PeerStats - -func (_XdrVec_25_PeerStats) XdrBound() uint32 { - const bound uint32 = 25 // Force error if not const or doesn't fit - return bound -} -func (_XdrVec_25_PeerStats) XdrCheckLen(length uint32) { - if length > uint32(25) { - XdrPanic("_XdrVec_25_PeerStats length %d exceeds bound 25", length) - } else if int(length) < 0 { - XdrPanic("_XdrVec_25_PeerStats length %d exceeds max int", length) - } +func (IPAddrType) XdrEnumNames() map[int32]string { + return _XdrNames_IPAddrType } -func (v _XdrVec_25_PeerStats) GetVecLen() uint32 { return uint32(len(v)) } -func (v *_XdrVec_25_PeerStats) SetVecLen(length uint32) { - v.XdrCheckLen(length) - if int(length) <= cap(*v) { - if int(length) != len(*v) { - *v = (*v)[:int(length)] - } - return - } - newcap := 2 * cap(*v) - if newcap < int(length) { // also catches overflow where 2*cap < 0 - newcap = int(length) - } else if bound := uint(25); uint(newcap) > bound { - if int(bound) < 0 { - bound = ^uint(0) >> 1 - } - newcap = int(bound) +func (v IPAddrType) String() string { + if s, ok := _XdrNames_IPAddrType[int32(v)]; ok { + return s } - nv := make([]PeerStats, int(length), newcap) - copy(nv, *v) - *v = nv + return fmt.Sprintf("IPAddrType#%d", v) } -func (v *_XdrVec_25_PeerStats) XdrMarshalN(x XDR, name string, n uint32) { - v.XdrCheckLen(n) - for i := 0; i < int(n); i++ { - if i >= len(*v) { - v.SetVecLen(uint32(i + 1)) +func (v *IPAddrType) Scan(ss fmt.ScanState, _ rune) error { + if tok, err := ss.Token(true, XdrSymChar); err != nil { + return err + } else { + stok := string(tok) + if val, ok := _XdrValues_IPAddrType[stok]; ok { + *v = IPAddrType(val) + return nil + } else if stok == "IPAddrType" { + if n, err := fmt.Fscanf(ss, "#%d", (*int32)(v)); n == 1 && err == nil { + return nil + } } - XDR_PeerStats(&(*v)[i]).XdrMarshal(x, x.Sprintf("%s[%d]", name, i)) - } - if int(n) < len(*v) { - *v = (*v)[:int(n)] + return XdrError(fmt.Sprintf("%s is not a valid IPAddrType.", stok)) } } -func (v *_XdrVec_25_PeerStats) XdrRecurse(x XDR, name string) { - size := XdrSize{Size: uint32(len(*v)), Bound: 25} - x.Marshal(name, &size) - v.XdrMarshalN(x, name, size.Size) -} -func (_XdrVec_25_PeerStats) XdrTypeName() string { return "PeerStats<>" } -func (v *_XdrVec_25_PeerStats) XdrPointer() interface{} { return (*[]PeerStats)(v) } -func (v _XdrVec_25_PeerStats) XdrValue() interface{} { return ([]PeerStats)(v) } -func (v *_XdrVec_25_PeerStats) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v IPAddrType) GetU32() uint32 { return uint32(v) } +func (v *IPAddrType) SetU32(n uint32) { *v = IPAddrType(n) } +func (v *IPAddrType) XdrPointer() interface{} { return v } +func (IPAddrType) XdrTypeName() string { return "IPAddrType" } +func (v IPAddrType) XdrValue() interface{} { return v } +func (v *IPAddrType) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -type XdrType_PeerStatList struct { - *_XdrVec_25_PeerStats -} +type XdrType_IPAddrType = *IPAddrType -func XDR_PeerStatList(v *PeerStatList) XdrType_PeerStatList { - return XdrType_PeerStatList{(*_XdrVec_25_PeerStats)(v)} -} -func (XdrType_PeerStatList) XdrTypeName() string { return "PeerStatList" } -func (v XdrType_PeerStatList) XdrUnwrap() XdrType { return v._XdrVec_25_PeerStats } +func XDR_IPAddrType(v *IPAddrType) *IPAddrType { return v } -type XdrType_TopologyResponseBody = *TopologyResponseBody +type _XdrArray_16_opaque [16]byte -func (v *TopologyResponseBody) XdrPointer() interface{} { return v } -func (TopologyResponseBody) XdrTypeName() string { return "TopologyResponseBody" } -func (v TopologyResponseBody) XdrValue() interface{} { return v } -func (v *TopologyResponseBody) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -func (v *TopologyResponseBody) XdrRecurse(x XDR, name string) { - if name != "" { - name = x.Sprintf("%s.", name) - } - x.Marshal(x.Sprintf("%sinboundPeers", name), XDR_PeerStatList(&v.InboundPeers)) - x.Marshal(x.Sprintf("%soutboundPeers", name), XDR_PeerStatList(&v.OutboundPeers)) - x.Marshal(x.Sprintf("%stotalInboundPeerCount", name), XDR_Uint32(&v.TotalInboundPeerCount)) - x.Marshal(x.Sprintf("%stotalOutboundPeerCount", name), XDR_Uint32(&v.TotalOutboundPeerCount)) +func (v *_XdrArray_16_opaque) GetByteSlice() []byte { return v[:] } +func (v *_XdrArray_16_opaque) XdrTypeName() string { return "opaque[]" } +func (v *_XdrArray_16_opaque) XdrValue() interface{} { return v[:] } +func (v *_XdrArray_16_opaque) XdrPointer() interface{} { return (*[16]byte)(v) } +func (v *_XdrArray_16_opaque) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v *_XdrArray_16_opaque) String() string { return fmt.Sprintf("%x", v[:]) } +func (v *_XdrArray_16_opaque) Scan(ss fmt.ScanState, c rune) error { + return XdrArrayOpaqueScan(v[:], ss, c) +} +func (_XdrArray_16_opaque) XdrArraySize() uint32 { + const bound uint32 = 16 // Force error if not const or doesn't fit + return bound } -func XDR_TopologyResponseBody(v *TopologyResponseBody) *TopologyResponseBody { return v } -var _XdrTags_SurveyResponseBody = map[int32]bool{ - XdrToI32(SURVEY_TOPOLOGY): true, +var _XdrTags_XdrAnon_PeerAddress_Ip = map[int32]bool{ + XdrToI32(IPv4): true, + XdrToI32(IPv6): true, } -func (_ SurveyResponseBody) XdrValidTags() map[int32]bool { - return _XdrTags_SurveyResponseBody +func (_ XdrAnon_PeerAddress_Ip) XdrValidTags() map[int32]bool { + return _XdrTags_XdrAnon_PeerAddress_Ip } -func (u *SurveyResponseBody) TopologyResponseBody() *TopologyResponseBody { +func (u *XdrAnon_PeerAddress_Ip) Ipv4() *[4]byte { switch u.Type { - case SURVEY_TOPOLOGY: - if v, ok := u._u.(*TopologyResponseBody); ok { + case IPv4: + if v, ok := u._u.(*[4]byte); ok { return v } else { - var zero TopologyResponseBody + var zero [4]byte u._u = &zero return &zero } default: - XdrPanic("SurveyResponseBody.TopologyResponseBody accessed when Type == %v", u.Type) + XdrPanic("XdrAnon_PeerAddress_Ip.Ipv4 accessed when Type == %v", u.Type) return nil } } -func (u SurveyResponseBody) XdrValid() bool { +func (u *XdrAnon_PeerAddress_Ip) Ipv6() *[16]byte { + switch u.Type { + case IPv6: + if v, ok := u._u.(*[16]byte); ok { + return v + } else { + var zero [16]byte + u._u = &zero + return &zero + } + default: + XdrPanic("XdrAnon_PeerAddress_Ip.Ipv6 accessed when Type == %v", u.Type) + return nil + } +} +func (u XdrAnon_PeerAddress_Ip) XdrValid() bool { switch u.Type { - case SURVEY_TOPOLOGY: + case IPv4, IPv6: return true } return false } -func (u *SurveyResponseBody) XdrUnionTag() XdrNum32 { - return XDR_SurveyMessageCommandType(&u.Type) +func (u *XdrAnon_PeerAddress_Ip) XdrUnionTag() XdrNum32 { + return XDR_IPAddrType(&u.Type) } -func (u *SurveyResponseBody) XdrUnionTagName() string { +func (u *XdrAnon_PeerAddress_Ip) XdrUnionTagName() string { return "Type" } -func (u *SurveyResponseBody) XdrUnionBody() XdrType { +func (u *XdrAnon_PeerAddress_Ip) XdrUnionBody() XdrType { switch u.Type { - case SURVEY_TOPOLOGY: - return XDR_TopologyResponseBody(u.TopologyResponseBody()) + case IPv4: + return (*_XdrArray_4_opaque)(u.Ipv4()) + case IPv6: + return (*_XdrArray_16_opaque)(u.Ipv6()) } return nil } -func (u *SurveyResponseBody) XdrUnionBodyName() string { +func (u *XdrAnon_PeerAddress_Ip) XdrUnionBodyName() string { switch u.Type { - case SURVEY_TOPOLOGY: - return "TopologyResponseBody" + case IPv4: + return "Ipv4" + case IPv6: + return "Ipv6" } return "" } -type XdrType_SurveyResponseBody = *SurveyResponseBody +type XdrType_XdrAnon_PeerAddress_Ip = *XdrAnon_PeerAddress_Ip -func (v *SurveyResponseBody) XdrPointer() interface{} { return v } -func (SurveyResponseBody) XdrTypeName() string { return "SurveyResponseBody" } -func (v SurveyResponseBody) XdrValue() interface{} { return v } -func (v *SurveyResponseBody) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -func (u *SurveyResponseBody) XdrRecurse(x XDR, name string) { +func (v *XdrAnon_PeerAddress_Ip) XdrPointer() interface{} { return v } +func (XdrAnon_PeerAddress_Ip) XdrTypeName() string { return "XdrAnon_PeerAddress_Ip" } +func (v XdrAnon_PeerAddress_Ip) XdrValue() interface{} { return v } +func (v *XdrAnon_PeerAddress_Ip) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (u *XdrAnon_PeerAddress_Ip) XdrRecurse(x XDR, name string) { if name != "" { name = x.Sprintf("%s.", name) } - XDR_SurveyMessageCommandType(&u.Type).XdrMarshal(x, x.Sprintf("%stype", name)) + XDR_IPAddrType(&u.Type).XdrMarshal(x, x.Sprintf("%stype", name)) switch u.Type { - case SURVEY_TOPOLOGY: - x.Marshal(x.Sprintf("%stopologyResponseBody", name), XDR_TopologyResponseBody(u.TopologyResponseBody())) + case IPv4: + x.Marshal(x.Sprintf("%sipv4", name), (*_XdrArray_4_opaque)(u.Ipv4())) + return + case IPv6: + x.Marshal(x.Sprintf("%sipv6", name), (*_XdrArray_16_opaque)(u.Ipv6())) return } - XdrPanic("invalid Type (%v) in SurveyResponseBody", u.Type) + XdrPanic("invalid Type (%v) in XdrAnon_PeerAddress_Ip", u.Type) } -func XDR_SurveyResponseBody(v *SurveyResponseBody) *SurveyResponseBody { return v } +func XDR_XdrAnon_PeerAddress_Ip(v *XdrAnon_PeerAddress_Ip) *XdrAnon_PeerAddress_Ip { return v } -type _XdrVec_100_PeerAddress []PeerAddress +type XdrType_PeerAddress = *PeerAddress -func (_XdrVec_100_PeerAddress) XdrBound() uint32 { - const bound uint32 = 100 // Force error if not const or doesn't fit - return bound -} -func (_XdrVec_100_PeerAddress) XdrCheckLen(length uint32) { - if length > uint32(100) { - XdrPanic("_XdrVec_100_PeerAddress length %d exceeds bound 100", length) - } else if int(length) < 0 { - XdrPanic("_XdrVec_100_PeerAddress length %d exceeds max int", length) - } -} -func (v _XdrVec_100_PeerAddress) GetVecLen() uint32 { return uint32(len(v)) } -func (v *_XdrVec_100_PeerAddress) SetVecLen(length uint32) { - v.XdrCheckLen(length) - if int(length) <= cap(*v) { - if int(length) != len(*v) { - *v = (*v)[:int(length)] - } - return - } - newcap := 2 * cap(*v) - if newcap < int(length) { // also catches overflow where 2*cap < 0 - newcap = int(length) - } else if bound := uint(100); uint(newcap) > bound { - if int(bound) < 0 { - bound = ^uint(0) >> 1 - } - newcap = int(bound) +func (v *PeerAddress) XdrPointer() interface{} { return v } +func (PeerAddress) XdrTypeName() string { return "PeerAddress" } +func (v PeerAddress) XdrValue() interface{} { return v } +func (v *PeerAddress) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v *PeerAddress) XdrRecurse(x XDR, name string) { + if name != "" { + name = x.Sprintf("%s.", name) } - nv := make([]PeerAddress, int(length), newcap) - copy(nv, *v) - *v = nv + x.Marshal(x.Sprintf("%sip", name), XDR_XdrAnon_PeerAddress_Ip(&v.Ip)) + x.Marshal(x.Sprintf("%sport", name), XDR_Uint32(&v.Port)) + x.Marshal(x.Sprintf("%snumFailures", name), XDR_Uint32(&v.NumFailures)) } -func (v *_XdrVec_100_PeerAddress) XdrMarshalN(x XDR, name string, n uint32) { - v.XdrCheckLen(n) - for i := 0; i < int(n); i++ { - if i >= len(*v) { - v.SetVecLen(uint32(i + 1)) - } - XDR_PeerAddress(&(*v)[i]).XdrMarshal(x, x.Sprintf("%s[%d]", name, i)) - } - if int(n) < len(*v) { - *v = (*v)[:int(n)] - } +func XDR_PeerAddress(v *PeerAddress) *PeerAddress { return v } + +var _XdrNames_MessageType = map[int32]string{ + int32(ERROR_MSG): "ERROR_MSG", + int32(AUTH): "AUTH", + int32(DONT_HAVE): "DONT_HAVE", + int32(GET_PEERS): "GET_PEERS", + int32(PEERS): "PEERS", + int32(GET_TX_SET): "GET_TX_SET", + int32(TX_SET): "TX_SET", + int32(GENERALIZED_TX_SET): "GENERALIZED_TX_SET", + int32(TRANSACTION): "TRANSACTION", + int32(GET_SCP_QUORUMSET): "GET_SCP_QUORUMSET", + int32(SCP_QUORUMSET): "SCP_QUORUMSET", + int32(SCP_MESSAGE): "SCP_MESSAGE", + int32(GET_SCP_STATE): "GET_SCP_STATE", + int32(HELLO): "HELLO", + int32(SURVEY_REQUEST): "SURVEY_REQUEST", + int32(SURVEY_RESPONSE): "SURVEY_RESPONSE", + int32(SEND_MORE): "SEND_MORE", + int32(SEND_MORE_EXTENDED): "SEND_MORE_EXTENDED", + int32(FLOOD_ADVERT): "FLOOD_ADVERT", + int32(FLOOD_DEMAND): "FLOOD_DEMAND", } -func (v *_XdrVec_100_PeerAddress) XdrRecurse(x XDR, name string) { - size := XdrSize{Size: uint32(len(*v)), Bound: 100} - x.Marshal(name, &size) - v.XdrMarshalN(x, name, size.Size) +var _XdrValues_MessageType = map[string]int32{ + "ERROR_MSG": int32(ERROR_MSG), + "AUTH": int32(AUTH), + "DONT_HAVE": int32(DONT_HAVE), + "GET_PEERS": int32(GET_PEERS), + "PEERS": int32(PEERS), + "GET_TX_SET": int32(GET_TX_SET), + "TX_SET": int32(TX_SET), + "GENERALIZED_TX_SET": int32(GENERALIZED_TX_SET), + "TRANSACTION": int32(TRANSACTION), + "GET_SCP_QUORUMSET": int32(GET_SCP_QUORUMSET), + "SCP_QUORUMSET": int32(SCP_QUORUMSET), + "SCP_MESSAGE": int32(SCP_MESSAGE), + "GET_SCP_STATE": int32(GET_SCP_STATE), + "HELLO": int32(HELLO), + "SURVEY_REQUEST": int32(SURVEY_REQUEST), + "SURVEY_RESPONSE": int32(SURVEY_RESPONSE), + "SEND_MORE": int32(SEND_MORE), + "SEND_MORE_EXTENDED": int32(SEND_MORE_EXTENDED), + "FLOOD_ADVERT": int32(FLOOD_ADVERT), + "FLOOD_DEMAND": int32(FLOOD_DEMAND), } -func (_XdrVec_100_PeerAddress) XdrTypeName() string { return "PeerAddress<>" } -func (v *_XdrVec_100_PeerAddress) XdrPointer() interface{} { return (*[]PeerAddress)(v) } -func (v _XdrVec_100_PeerAddress) XdrValue() interface{} { return ([]PeerAddress)(v) } -func (v *_XdrVec_100_PeerAddress) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -var _XdrTags_StellarMessage = map[int32]bool{ - XdrToI32(ERROR_MSG): true, - XdrToI32(HELLO): true, - XdrToI32(AUTH): true, - XdrToI32(DONT_HAVE): true, - XdrToI32(GET_PEERS): true, - XdrToI32(PEERS): true, - XdrToI32(GET_TX_SET): true, - XdrToI32(TX_SET): true, - XdrToI32(GENERALIZED_TX_SET): true, - XdrToI32(TRANSACTION): true, - XdrToI32(SURVEY_REQUEST): true, - XdrToI32(SURVEY_RESPONSE): true, - XdrToI32(GET_SCP_QUORUMSET): true, - XdrToI32(SCP_QUORUMSET): true, - XdrToI32(SCP_MESSAGE): true, - XdrToI32(GET_SCP_STATE): true, - XdrToI32(SEND_MORE): true, +func (MessageType) XdrEnumNames() map[int32]string { + return _XdrNames_MessageType } - -func (_ StellarMessage) XdrValidTags() map[int32]bool { - return _XdrTags_StellarMessage +func (v MessageType) String() string { + if s, ok := _XdrNames_MessageType[int32(v)]; ok { + return s + } + return fmt.Sprintf("MessageType#%d", v) } -func (u *StellarMessage) Error() *Error { - switch u.Type { - case ERROR_MSG: - if v, ok := u._u.(*Error); ok { - return v - } else { - var zero Error - u._u = &zero - return &zero +func (v *MessageType) Scan(ss fmt.ScanState, _ rune) error { + if tok, err := ss.Token(true, XdrSymChar); err != nil { + return err + } else { + stok := string(tok) + if val, ok := _XdrValues_MessageType[stok]; ok { + *v = MessageType(val) + return nil + } else if stok == "MessageType" { + if n, err := fmt.Fscanf(ss, "#%d", (*int32)(v)); n == 1 && err == nil { + return nil + } } - default: - XdrPanic("StellarMessage.Error accessed when Type == %v", u.Type) - return nil + return XdrError(fmt.Sprintf("%s is not a valid MessageType.", stok)) } } -func (u *StellarMessage) Hello() *Hello { - switch u.Type { - case HELLO: - if v, ok := u._u.(*Hello); ok { - return v - } else { - var zero Hello - u._u = &zero - return &zero - } - default: - XdrPanic("StellarMessage.Hello accessed when Type == %v", u.Type) - return nil +func (v MessageType) GetU32() uint32 { return uint32(v) } +func (v *MessageType) SetU32(n uint32) { *v = MessageType(n) } +func (v *MessageType) XdrPointer() interface{} { return v } +func (MessageType) XdrTypeName() string { return "MessageType" } +func (v MessageType) XdrValue() interface{} { return v } +func (v *MessageType) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } + +type XdrType_MessageType = *MessageType + +func XDR_MessageType(v *MessageType) *MessageType { return v } + +var _XdrComments_MessageType = map[int32]string{ + int32(GET_PEERS): "gets a list of peers this guy knows about", + int32(GET_TX_SET): "gets a particular txset by hash", + int32(TRANSACTION): "pass on a tx you have heard about", + int32(GET_SCP_QUORUMSET): "SCP", + int32(HELLO): "new messages", +} + +func (e MessageType) XdrEnumComments() map[int32]string { + return _XdrComments_MessageType +} + +type XdrType_DontHave = *DontHave + +func (v *DontHave) XdrPointer() interface{} { return v } +func (DontHave) XdrTypeName() string { return "DontHave" } +func (v DontHave) XdrValue() interface{} { return v } +func (v *DontHave) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v *DontHave) XdrRecurse(x XDR, name string) { + if name != "" { + name = x.Sprintf("%s.", name) } + x.Marshal(x.Sprintf("%stype", name), XDR_MessageType(&v.Type)) + x.Marshal(x.Sprintf("%sreqHash", name), XDR_Uint256(&v.ReqHash)) } -func (u *StellarMessage) Auth() *Auth { - switch u.Type { - case AUTH: - if v, ok := u._u.(*Auth); ok { - return v - } else { - var zero Auth - u._u = &zero - return &zero - } - default: - XdrPanic("StellarMessage.Auth accessed when Type == %v", u.Type) - return nil +func XDR_DontHave(v *DontHave) *DontHave { return v } + +var _XdrNames_SurveyMessageCommandType = map[int32]string{ + int32(SURVEY_TOPOLOGY): "SURVEY_TOPOLOGY", +} +var _XdrValues_SurveyMessageCommandType = map[string]int32{ + "SURVEY_TOPOLOGY": int32(SURVEY_TOPOLOGY), +} + +func (SurveyMessageCommandType) XdrEnumNames() map[int32]string { + return _XdrNames_SurveyMessageCommandType +} +func (v SurveyMessageCommandType) String() string { + if s, ok := _XdrNames_SurveyMessageCommandType[int32(v)]; ok { + return s } + return fmt.Sprintf("SurveyMessageCommandType#%d", v) } -func (u *StellarMessage) DontHave() *DontHave { - switch u.Type { - case DONT_HAVE: - if v, ok := u._u.(*DontHave); ok { - return v - } else { - var zero DontHave - u._u = &zero - return &zero +func (v *SurveyMessageCommandType) Scan(ss fmt.ScanState, _ rune) error { + if tok, err := ss.Token(true, XdrSymChar); err != nil { + return err + } else { + stok := string(tok) + if val, ok := _XdrValues_SurveyMessageCommandType[stok]; ok { + *v = SurveyMessageCommandType(val) + return nil + } else if stok == "SurveyMessageCommandType" { + if n, err := fmt.Fscanf(ss, "#%d", (*int32)(v)); n == 1 && err == nil { + return nil + } } - default: - XdrPanic("StellarMessage.DontHave accessed when Type == %v", u.Type) - return nil + return XdrError(fmt.Sprintf("%s is not a valid SurveyMessageCommandType.", stok)) } } -func (u *StellarMessage) Peers() *[]PeerAddress { - switch u.Type { - case PEERS: - if v, ok := u._u.(*[]PeerAddress); ok { - return v - } else { - var zero []PeerAddress - u._u = &zero - return &zero - } - default: - XdrPanic("StellarMessage.Peers accessed when Type == %v", u.Type) - return nil +func (v SurveyMessageCommandType) GetU32() uint32 { return uint32(v) } +func (v *SurveyMessageCommandType) SetU32(n uint32) { *v = SurveyMessageCommandType(n) } +func (v *SurveyMessageCommandType) XdrPointer() interface{} { return v } +func (SurveyMessageCommandType) XdrTypeName() string { return "SurveyMessageCommandType" } +func (v SurveyMessageCommandType) XdrValue() interface{} { return v } +func (v *SurveyMessageCommandType) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } + +type XdrType_SurveyMessageCommandType = *SurveyMessageCommandType + +func XDR_SurveyMessageCommandType(v *SurveyMessageCommandType) *SurveyMessageCommandType { return v } + +var _XdrNames_SurveyMessageResponseType = map[int32]string{ + int32(SURVEY_TOPOLOGY_RESPONSE_V0): "SURVEY_TOPOLOGY_RESPONSE_V0", + int32(SURVEY_TOPOLOGY_RESPONSE_V1): "SURVEY_TOPOLOGY_RESPONSE_V1", +} +var _XdrValues_SurveyMessageResponseType = map[string]int32{ + "SURVEY_TOPOLOGY_RESPONSE_V0": int32(SURVEY_TOPOLOGY_RESPONSE_V0), + "SURVEY_TOPOLOGY_RESPONSE_V1": int32(SURVEY_TOPOLOGY_RESPONSE_V1), +} + +func (SurveyMessageResponseType) XdrEnumNames() map[int32]string { + return _XdrNames_SurveyMessageResponseType +} +func (v SurveyMessageResponseType) String() string { + if s, ok := _XdrNames_SurveyMessageResponseType[int32(v)]; ok { + return s } + return fmt.Sprintf("SurveyMessageResponseType#%d", v) } -func (u *StellarMessage) TxSetHash() *Uint256 { - switch u.Type { - case GET_TX_SET: - if v, ok := u._u.(*Uint256); ok { - return v - } else { - var zero Uint256 - u._u = &zero - return &zero +func (v *SurveyMessageResponseType) Scan(ss fmt.ScanState, _ rune) error { + if tok, err := ss.Token(true, XdrSymChar); err != nil { + return err + } else { + stok := string(tok) + if val, ok := _XdrValues_SurveyMessageResponseType[stok]; ok { + *v = SurveyMessageResponseType(val) + return nil + } else if stok == "SurveyMessageResponseType" { + if n, err := fmt.Fscanf(ss, "#%d", (*int32)(v)); n == 1 && err == nil { + return nil + } } - default: - XdrPanic("StellarMessage.TxSetHash accessed when Type == %v", u.Type) - return nil + return XdrError(fmt.Sprintf("%s is not a valid SurveyMessageResponseType.", stok)) } } -func (u *StellarMessage) TxSet() *TransactionSet { - switch u.Type { - case TX_SET: - if v, ok := u._u.(*TransactionSet); ok { - return v - } else { - var zero TransactionSet - u._u = &zero - return &zero - } - default: - XdrPanic("StellarMessage.TxSet accessed when Type == %v", u.Type) - return nil +func (v SurveyMessageResponseType) GetU32() uint32 { return uint32(v) } +func (v *SurveyMessageResponseType) SetU32(n uint32) { *v = SurveyMessageResponseType(n) } +func (v *SurveyMessageResponseType) XdrPointer() interface{} { return v } +func (SurveyMessageResponseType) XdrTypeName() string { return "SurveyMessageResponseType" } +func (v SurveyMessageResponseType) XdrValue() interface{} { return v } +func (v *SurveyMessageResponseType) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } + +type XdrType_SurveyMessageResponseType = *SurveyMessageResponseType + +func XDR_SurveyMessageResponseType(v *SurveyMessageResponseType) *SurveyMessageResponseType { return v } + +type XdrType_SurveyRequestMessage = *SurveyRequestMessage + +func (v *SurveyRequestMessage) XdrPointer() interface{} { return v } +func (SurveyRequestMessage) XdrTypeName() string { return "SurveyRequestMessage" } +func (v SurveyRequestMessage) XdrValue() interface{} { return v } +func (v *SurveyRequestMessage) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v *SurveyRequestMessage) XdrRecurse(x XDR, name string) { + if name != "" { + name = x.Sprintf("%s.", name) } + x.Marshal(x.Sprintf("%ssurveyorPeerID", name), XDR_NodeID(&v.SurveyorPeerID)) + x.Marshal(x.Sprintf("%ssurveyedPeerID", name), XDR_NodeID(&v.SurveyedPeerID)) + x.Marshal(x.Sprintf("%sledgerNum", name), XDR_Uint32(&v.LedgerNum)) + x.Marshal(x.Sprintf("%sencryptionKey", name), XDR_Curve25519Public(&v.EncryptionKey)) + x.Marshal(x.Sprintf("%scommandType", name), XDR_SurveyMessageCommandType(&v.CommandType)) } -func (u *StellarMessage) GeneralizedTxSet() *GeneralizedTransactionSet { - switch u.Type { - case GENERALIZED_TX_SET: - if v, ok := u._u.(*GeneralizedTransactionSet); ok { - return v - } else { - var zero GeneralizedTransactionSet - u._u = &zero - return &zero - } - default: - XdrPanic("StellarMessage.GeneralizedTxSet accessed when Type == %v", u.Type) - return nil +func XDR_SurveyRequestMessage(v *SurveyRequestMessage) *SurveyRequestMessage { return v } + +type XdrType_SignedSurveyRequestMessage = *SignedSurveyRequestMessage + +func (v *SignedSurveyRequestMessage) XdrPointer() interface{} { return v } +func (SignedSurveyRequestMessage) XdrTypeName() string { return "SignedSurveyRequestMessage" } +func (v SignedSurveyRequestMessage) XdrValue() interface{} { return v } +func (v *SignedSurveyRequestMessage) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v *SignedSurveyRequestMessage) XdrRecurse(x XDR, name string) { + if name != "" { + name = x.Sprintf("%s.", name) } + x.Marshal(x.Sprintf("%srequestSignature", name), XDR_Signature(&v.RequestSignature)) + x.Marshal(x.Sprintf("%srequest", name), XDR_SurveyRequestMessage(&v.Request)) } -func (u *StellarMessage) Transaction() *TransactionEnvelope { - switch u.Type { - case TRANSACTION: - if v, ok := u._u.(*TransactionEnvelope); ok { - return v - } else { - var zero TransactionEnvelope - u._u = &zero - return &zero +func XDR_SignedSurveyRequestMessage(v *SignedSurveyRequestMessage) *SignedSurveyRequestMessage { + return v +} + +type XdrType_EncryptedBody struct { + XdrVecOpaque +} + +func XDR_EncryptedBody(v *EncryptedBody) XdrType_EncryptedBody { + return XdrType_EncryptedBody{XdrVecOpaque{v, 64000}} +} +func (XdrType_EncryptedBody) XdrTypeName() string { return "EncryptedBody" } +func (v XdrType_EncryptedBody) XdrUnwrap() XdrType { return v.XdrVecOpaque } + +type XdrType_SurveyResponseMessage = *SurveyResponseMessage + +func (v *SurveyResponseMessage) XdrPointer() interface{} { return v } +func (SurveyResponseMessage) XdrTypeName() string { return "SurveyResponseMessage" } +func (v SurveyResponseMessage) XdrValue() interface{} { return v } +func (v *SurveyResponseMessage) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v *SurveyResponseMessage) XdrRecurse(x XDR, name string) { + if name != "" { + name = x.Sprintf("%s.", name) + } + x.Marshal(x.Sprintf("%ssurveyorPeerID", name), XDR_NodeID(&v.SurveyorPeerID)) + x.Marshal(x.Sprintf("%ssurveyedPeerID", name), XDR_NodeID(&v.SurveyedPeerID)) + x.Marshal(x.Sprintf("%sledgerNum", name), XDR_Uint32(&v.LedgerNum)) + x.Marshal(x.Sprintf("%scommandType", name), XDR_SurveyMessageCommandType(&v.CommandType)) + x.Marshal(x.Sprintf("%sencryptedBody", name), XDR_EncryptedBody(&v.EncryptedBody)) +} +func XDR_SurveyResponseMessage(v *SurveyResponseMessage) *SurveyResponseMessage { return v } + +type XdrType_SignedSurveyResponseMessage = *SignedSurveyResponseMessage + +func (v *SignedSurveyResponseMessage) XdrPointer() interface{} { return v } +func (SignedSurveyResponseMessage) XdrTypeName() string { return "SignedSurveyResponseMessage" } +func (v SignedSurveyResponseMessage) XdrValue() interface{} { return v } +func (v *SignedSurveyResponseMessage) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v *SignedSurveyResponseMessage) XdrRecurse(x XDR, name string) { + if name != "" { + name = x.Sprintf("%s.", name) + } + x.Marshal(x.Sprintf("%sresponseSignature", name), XDR_Signature(&v.ResponseSignature)) + x.Marshal(x.Sprintf("%sresponse", name), XDR_SurveyResponseMessage(&v.Response)) +} +func XDR_SignedSurveyResponseMessage(v *SignedSurveyResponseMessage) *SignedSurveyResponseMessage { + return v +} + +type XdrType_PeerStats = *PeerStats + +func (v *PeerStats) XdrPointer() interface{} { return v } +func (PeerStats) XdrTypeName() string { return "PeerStats" } +func (v PeerStats) XdrValue() interface{} { return v } +func (v *PeerStats) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v *PeerStats) XdrRecurse(x XDR, name string) { + if name != "" { + name = x.Sprintf("%s.", name) + } + x.Marshal(x.Sprintf("%sid", name), XDR_NodeID(&v.Id)) + x.Marshal(x.Sprintf("%sversionStr", name), XdrString{&v.VersionStr, 100}) + x.Marshal(x.Sprintf("%smessagesRead", name), XDR_Uint64(&v.MessagesRead)) + x.Marshal(x.Sprintf("%smessagesWritten", name), XDR_Uint64(&v.MessagesWritten)) + x.Marshal(x.Sprintf("%sbytesRead", name), XDR_Uint64(&v.BytesRead)) + x.Marshal(x.Sprintf("%sbytesWritten", name), XDR_Uint64(&v.BytesWritten)) + x.Marshal(x.Sprintf("%ssecondsConnected", name), XDR_Uint64(&v.SecondsConnected)) + x.Marshal(x.Sprintf("%suniqueFloodBytesRecv", name), XDR_Uint64(&v.UniqueFloodBytesRecv)) + x.Marshal(x.Sprintf("%sduplicateFloodBytesRecv", name), XDR_Uint64(&v.DuplicateFloodBytesRecv)) + x.Marshal(x.Sprintf("%suniqueFetchBytesRecv", name), XDR_Uint64(&v.UniqueFetchBytesRecv)) + x.Marshal(x.Sprintf("%sduplicateFetchBytesRecv", name), XDR_Uint64(&v.DuplicateFetchBytesRecv)) + x.Marshal(x.Sprintf("%suniqueFloodMessageRecv", name), XDR_Uint64(&v.UniqueFloodMessageRecv)) + x.Marshal(x.Sprintf("%sduplicateFloodMessageRecv", name), XDR_Uint64(&v.DuplicateFloodMessageRecv)) + x.Marshal(x.Sprintf("%suniqueFetchMessageRecv", name), XDR_Uint64(&v.UniqueFetchMessageRecv)) + x.Marshal(x.Sprintf("%sduplicateFetchMessageRecv", name), XDR_Uint64(&v.DuplicateFetchMessageRecv)) +} +func XDR_PeerStats(v *PeerStats) *PeerStats { return v } + +type _XdrVec_25_PeerStats []PeerStats + +func (_XdrVec_25_PeerStats) XdrBound() uint32 { + const bound uint32 = 25 // Force error if not const or doesn't fit + return bound +} +func (_XdrVec_25_PeerStats) XdrCheckLen(length uint32) { + if length > uint32(25) { + XdrPanic("_XdrVec_25_PeerStats length %d exceeds bound 25", length) + } else if int(length) < 0 { + XdrPanic("_XdrVec_25_PeerStats length %d exceeds max int", length) + } +} +func (v _XdrVec_25_PeerStats) GetVecLen() uint32 { return uint32(len(v)) } +func (v *_XdrVec_25_PeerStats) SetVecLen(length uint32) { + v.XdrCheckLen(length) + if int(length) <= cap(*v) { + if int(length) != len(*v) { + *v = (*v)[:int(length)] } - default: - XdrPanic("StellarMessage.Transaction accessed when Type == %v", u.Type) - return nil + return + } + newcap := 2 * cap(*v) + if newcap < int(length) { // also catches overflow where 2*cap < 0 + newcap = int(length) + } else if bound := uint(25); uint(newcap) > bound { + if int(bound) < 0 { + bound = ^uint(0) >> 1 + } + newcap = int(bound) } + nv := make([]PeerStats, int(length), newcap) + copy(nv, *v) + *v = nv } -func (u *StellarMessage) SignedSurveyRequestMessage() *SignedSurveyRequestMessage { - switch u.Type { - case SURVEY_REQUEST: - if v, ok := u._u.(*SignedSurveyRequestMessage); ok { - return v - } else { - var zero SignedSurveyRequestMessage - u._u = &zero - return &zero +func (v *_XdrVec_25_PeerStats) XdrMarshalN(x XDR, name string, n uint32) { + v.XdrCheckLen(n) + for i := 0; i < int(n); i++ { + if i >= len(*v) { + v.SetVecLen(uint32(i + 1)) } - default: - XdrPanic("StellarMessage.SignedSurveyRequestMessage accessed when Type == %v", u.Type) - return nil + XDR_PeerStats(&(*v)[i]).XdrMarshal(x, x.Sprintf("%s[%d]", name, i)) + } + if int(n) < len(*v) { + *v = (*v)[:int(n)] } } -func (u *StellarMessage) SignedSurveyResponseMessage() *SignedSurveyResponseMessage { +func (v *_XdrVec_25_PeerStats) XdrRecurse(x XDR, name string) { + size := XdrSize{Size: uint32(len(*v)), Bound: 25} + x.Marshal(name, &size) + v.XdrMarshalN(x, name, size.Size) +} +func (_XdrVec_25_PeerStats) XdrTypeName() string { return "PeerStats<>" } +func (v *_XdrVec_25_PeerStats) XdrPointer() interface{} { return (*[]PeerStats)(v) } +func (v _XdrVec_25_PeerStats) XdrValue() interface{} { return ([]PeerStats)(v) } +func (v *_XdrVec_25_PeerStats) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } + +type XdrType_PeerStatList struct { + *_XdrVec_25_PeerStats +} + +func XDR_PeerStatList(v *PeerStatList) XdrType_PeerStatList { + return XdrType_PeerStatList{(*_XdrVec_25_PeerStats)(v)} +} +func (XdrType_PeerStatList) XdrTypeName() string { return "PeerStatList" } +func (v XdrType_PeerStatList) XdrUnwrap() XdrType { return v._XdrVec_25_PeerStats } + +type XdrType_TopologyResponseBodyV0 = *TopologyResponseBodyV0 + +func (v *TopologyResponseBodyV0) XdrPointer() interface{} { return v } +func (TopologyResponseBodyV0) XdrTypeName() string { return "TopologyResponseBodyV0" } +func (v TopologyResponseBodyV0) XdrValue() interface{} { return v } +func (v *TopologyResponseBodyV0) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v *TopologyResponseBodyV0) XdrRecurse(x XDR, name string) { + if name != "" { + name = x.Sprintf("%s.", name) + } + x.Marshal(x.Sprintf("%sinboundPeers", name), XDR_PeerStatList(&v.InboundPeers)) + x.Marshal(x.Sprintf("%soutboundPeers", name), XDR_PeerStatList(&v.OutboundPeers)) + x.Marshal(x.Sprintf("%stotalInboundPeerCount", name), XDR_Uint32(&v.TotalInboundPeerCount)) + x.Marshal(x.Sprintf("%stotalOutboundPeerCount", name), XDR_Uint32(&v.TotalOutboundPeerCount)) +} +func XDR_TopologyResponseBodyV0(v *TopologyResponseBodyV0) *TopologyResponseBodyV0 { return v } + +type XdrType_TopologyResponseBodyV1 = *TopologyResponseBodyV1 + +func (v *TopologyResponseBodyV1) XdrPointer() interface{} { return v } +func (TopologyResponseBodyV1) XdrTypeName() string { return "TopologyResponseBodyV1" } +func (v TopologyResponseBodyV1) XdrValue() interface{} { return v } +func (v *TopologyResponseBodyV1) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v *TopologyResponseBodyV1) XdrRecurse(x XDR, name string) { + if name != "" { + name = x.Sprintf("%s.", name) + } + x.Marshal(x.Sprintf("%sinboundPeers", name), XDR_PeerStatList(&v.InboundPeers)) + x.Marshal(x.Sprintf("%soutboundPeers", name), XDR_PeerStatList(&v.OutboundPeers)) + x.Marshal(x.Sprintf("%stotalInboundPeerCount", name), XDR_Uint32(&v.TotalInboundPeerCount)) + x.Marshal(x.Sprintf("%stotalOutboundPeerCount", name), XDR_Uint32(&v.TotalOutboundPeerCount)) + x.Marshal(x.Sprintf("%smaxInboundPeerCount", name), XDR_Uint32(&v.MaxInboundPeerCount)) + x.Marshal(x.Sprintf("%smaxOutboundPeerCount", name), XDR_Uint32(&v.MaxOutboundPeerCount)) +} +func XDR_TopologyResponseBodyV1(v *TopologyResponseBodyV1) *TopologyResponseBodyV1 { return v } + +var _XdrTags_SurveyResponseBody = map[int32]bool{ + XdrToI32(SURVEY_TOPOLOGY_RESPONSE_V0): true, + XdrToI32(SURVEY_TOPOLOGY_RESPONSE_V1): true, +} + +func (_ SurveyResponseBody) XdrValidTags() map[int32]bool { + return _XdrTags_SurveyResponseBody +} +func (u *SurveyResponseBody) TopologyResponseBodyV0() *TopologyResponseBodyV0 { switch u.Type { - case SURVEY_RESPONSE: - if v, ok := u._u.(*SignedSurveyResponseMessage); ok { + case SURVEY_TOPOLOGY_RESPONSE_V0: + if v, ok := u._u.(*TopologyResponseBodyV0); ok { return v } else { - var zero SignedSurveyResponseMessage + var zero TopologyResponseBodyV0 u._u = &zero return &zero } default: - XdrPanic("StellarMessage.SignedSurveyResponseMessage accessed when Type == %v", u.Type) + XdrPanic("SurveyResponseBody.TopologyResponseBodyV0 accessed when Type == %v", u.Type) return nil } } -func (u *StellarMessage) QSetHash() *Uint256 { +func (u *SurveyResponseBody) TopologyResponseBodyV1() *TopologyResponseBodyV1 { switch u.Type { - case GET_SCP_QUORUMSET: - if v, ok := u._u.(*Uint256); ok { + case SURVEY_TOPOLOGY_RESPONSE_V1: + if v, ok := u._u.(*TopologyResponseBodyV1); ok { return v } else { - var zero Uint256 + var zero TopologyResponseBodyV1 u._u = &zero return &zero } default: - XdrPanic("StellarMessage.QSetHash accessed when Type == %v", u.Type) + XdrPanic("SurveyResponseBody.TopologyResponseBodyV1 accessed when Type == %v", u.Type) return nil } } -func (u *StellarMessage) QSet() *SCPQuorumSet { +func (u SurveyResponseBody) XdrValid() bool { switch u.Type { - case SCP_QUORUMSET: - if v, ok := u._u.(*SCPQuorumSet); ok { - return v - } else { - var zero SCPQuorumSet - u._u = &zero - return &zero + case SURVEY_TOPOLOGY_RESPONSE_V0, SURVEY_TOPOLOGY_RESPONSE_V1: + return true + } + return false +} +func (u *SurveyResponseBody) XdrUnionTag() XdrNum32 { + return XDR_SurveyMessageResponseType(&u.Type) +} +func (u *SurveyResponseBody) XdrUnionTagName() string { + return "Type" +} +func (u *SurveyResponseBody) XdrUnionBody() XdrType { + switch u.Type { + case SURVEY_TOPOLOGY_RESPONSE_V0: + return XDR_TopologyResponseBodyV0(u.TopologyResponseBodyV0()) + case SURVEY_TOPOLOGY_RESPONSE_V1: + return XDR_TopologyResponseBodyV1(u.TopologyResponseBodyV1()) + } + return nil +} +func (u *SurveyResponseBody) XdrUnionBodyName() string { + switch u.Type { + case SURVEY_TOPOLOGY_RESPONSE_V0: + return "TopologyResponseBodyV0" + case SURVEY_TOPOLOGY_RESPONSE_V1: + return "TopologyResponseBodyV1" + } + return "" +} + +type XdrType_SurveyResponseBody = *SurveyResponseBody + +func (v *SurveyResponseBody) XdrPointer() interface{} { return v } +func (SurveyResponseBody) XdrTypeName() string { return "SurveyResponseBody" } +func (v SurveyResponseBody) XdrValue() interface{} { return v } +func (v *SurveyResponseBody) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (u *SurveyResponseBody) XdrRecurse(x XDR, name string) { + if name != "" { + name = x.Sprintf("%s.", name) + } + XDR_SurveyMessageResponseType(&u.Type).XdrMarshal(x, x.Sprintf("%stype", name)) + switch u.Type { + case SURVEY_TOPOLOGY_RESPONSE_V0: + x.Marshal(x.Sprintf("%stopologyResponseBodyV0", name), XDR_TopologyResponseBodyV0(u.TopologyResponseBodyV0())) + return + case SURVEY_TOPOLOGY_RESPONSE_V1: + x.Marshal(x.Sprintf("%stopologyResponseBodyV1", name), XDR_TopologyResponseBodyV1(u.TopologyResponseBodyV1())) + return + } + XdrPanic("invalid Type (%v) in SurveyResponseBody", u.Type) +} +func XDR_SurveyResponseBody(v *SurveyResponseBody) *SurveyResponseBody { return v } + +type _XdrVec_1000_Hash []Hash + +func (_XdrVec_1000_Hash) XdrBound() uint32 { + const bound uint32 = 1000 // Force error if not const or doesn't fit + return bound +} +func (_XdrVec_1000_Hash) XdrCheckLen(length uint32) { + if length > uint32(1000) { + XdrPanic("_XdrVec_1000_Hash length %d exceeds bound 1000", length) + } else if int(length) < 0 { + XdrPanic("_XdrVec_1000_Hash length %d exceeds max int", length) + } +} +func (v _XdrVec_1000_Hash) GetVecLen() uint32 { return uint32(len(v)) } +func (v *_XdrVec_1000_Hash) SetVecLen(length uint32) { + v.XdrCheckLen(length) + if int(length) <= cap(*v) { + if int(length) != len(*v) { + *v = (*v)[:int(length)] + } + return + } + newcap := 2 * cap(*v) + if newcap < int(length) { // also catches overflow where 2*cap < 0 + newcap = int(length) + } else if bound := uint(1000); uint(newcap) > bound { + if int(bound) < 0 { + bound = ^uint(0) >> 1 + } + newcap = int(bound) + } + nv := make([]Hash, int(length), newcap) + copy(nv, *v) + *v = nv +} +func (v *_XdrVec_1000_Hash) XdrMarshalN(x XDR, name string, n uint32) { + v.XdrCheckLen(n) + for i := 0; i < int(n); i++ { + if i >= len(*v) { + v.SetVecLen(uint32(i + 1)) + } + XDR_Hash(&(*v)[i]).XdrMarshal(x, x.Sprintf("%s[%d]", name, i)) + } + if int(n) < len(*v) { + *v = (*v)[:int(n)] + } +} +func (v *_XdrVec_1000_Hash) XdrRecurse(x XDR, name string) { + size := XdrSize{Size: uint32(len(*v)), Bound: 1000} + x.Marshal(name, &size) + v.XdrMarshalN(x, name, size.Size) +} +func (_XdrVec_1000_Hash) XdrTypeName() string { return "Hash<>" } +func (v *_XdrVec_1000_Hash) XdrPointer() interface{} { return (*[]Hash)(v) } +func (v _XdrVec_1000_Hash) XdrValue() interface{} { return ([]Hash)(v) } +func (v *_XdrVec_1000_Hash) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } + +type XdrType_TxAdvertVector struct { + *_XdrVec_1000_Hash +} + +func XDR_TxAdvertVector(v *TxAdvertVector) XdrType_TxAdvertVector { + return XdrType_TxAdvertVector{(*_XdrVec_1000_Hash)(v)} +} +func (XdrType_TxAdvertVector) XdrTypeName() string { return "TxAdvertVector" } +func (v XdrType_TxAdvertVector) XdrUnwrap() XdrType { return v._XdrVec_1000_Hash } + +type XdrType_FloodAdvert = *FloodAdvert + +func (v *FloodAdvert) XdrPointer() interface{} { return v } +func (FloodAdvert) XdrTypeName() string { return "FloodAdvert" } +func (v FloodAdvert) XdrValue() interface{} { return v } +func (v *FloodAdvert) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v *FloodAdvert) XdrRecurse(x XDR, name string) { + if name != "" { + name = x.Sprintf("%s.", name) + } + x.Marshal(x.Sprintf("%stxHashes", name), XDR_TxAdvertVector(&v.TxHashes)) +} +func XDR_FloodAdvert(v *FloodAdvert) *FloodAdvert { return v } + +type XdrType_TxDemandVector struct { + *_XdrVec_1000_Hash +} + +func XDR_TxDemandVector(v *TxDemandVector) XdrType_TxDemandVector { + return XdrType_TxDemandVector{(*_XdrVec_1000_Hash)(v)} +} +func (XdrType_TxDemandVector) XdrTypeName() string { return "TxDemandVector" } +func (v XdrType_TxDemandVector) XdrUnwrap() XdrType { return v._XdrVec_1000_Hash } + +type XdrType_FloodDemand = *FloodDemand + +func (v *FloodDemand) XdrPointer() interface{} { return v } +func (FloodDemand) XdrTypeName() string { return "FloodDemand" } +func (v FloodDemand) XdrValue() interface{} { return v } +func (v *FloodDemand) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v *FloodDemand) XdrRecurse(x XDR, name string) { + if name != "" { + name = x.Sprintf("%s.", name) + } + x.Marshal(x.Sprintf("%stxHashes", name), XDR_TxDemandVector(&v.TxHashes)) +} +func XDR_FloodDemand(v *FloodDemand) *FloodDemand { return v } + +type _XdrVec_100_PeerAddress []PeerAddress + +func (_XdrVec_100_PeerAddress) XdrBound() uint32 { + const bound uint32 = 100 // Force error if not const or doesn't fit + return bound +} +func (_XdrVec_100_PeerAddress) XdrCheckLen(length uint32) { + if length > uint32(100) { + XdrPanic("_XdrVec_100_PeerAddress length %d exceeds bound 100", length) + } else if int(length) < 0 { + XdrPanic("_XdrVec_100_PeerAddress length %d exceeds max int", length) + } +} +func (v _XdrVec_100_PeerAddress) GetVecLen() uint32 { return uint32(len(v)) } +func (v *_XdrVec_100_PeerAddress) SetVecLen(length uint32) { + v.XdrCheckLen(length) + if int(length) <= cap(*v) { + if int(length) != len(*v) { + *v = (*v)[:int(length)] + } + return + } + newcap := 2 * cap(*v) + if newcap < int(length) { // also catches overflow where 2*cap < 0 + newcap = int(length) + } else if bound := uint(100); uint(newcap) > bound { + if int(bound) < 0 { + bound = ^uint(0) >> 1 + } + newcap = int(bound) + } + nv := make([]PeerAddress, int(length), newcap) + copy(nv, *v) + *v = nv +} +func (v *_XdrVec_100_PeerAddress) XdrMarshalN(x XDR, name string, n uint32) { + v.XdrCheckLen(n) + for i := 0; i < int(n); i++ { + if i >= len(*v) { + v.SetVecLen(uint32(i + 1)) + } + XDR_PeerAddress(&(*v)[i]).XdrMarshal(x, x.Sprintf("%s[%d]", name, i)) + } + if int(n) < len(*v) { + *v = (*v)[:int(n)] + } +} +func (v *_XdrVec_100_PeerAddress) XdrRecurse(x XDR, name string) { + size := XdrSize{Size: uint32(len(*v)), Bound: 100} + x.Marshal(name, &size) + v.XdrMarshalN(x, name, size.Size) +} +func (_XdrVec_100_PeerAddress) XdrTypeName() string { return "PeerAddress<>" } +func (v *_XdrVec_100_PeerAddress) XdrPointer() interface{} { return (*[]PeerAddress)(v) } +func (v _XdrVec_100_PeerAddress) XdrValue() interface{} { return ([]PeerAddress)(v) } +func (v *_XdrVec_100_PeerAddress) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } + +var _XdrTags_StellarMessage = map[int32]bool{ + XdrToI32(ERROR_MSG): true, + XdrToI32(HELLO): true, + XdrToI32(AUTH): true, + XdrToI32(DONT_HAVE): true, + XdrToI32(GET_PEERS): true, + XdrToI32(PEERS): true, + XdrToI32(GET_TX_SET): true, + XdrToI32(TX_SET): true, + XdrToI32(GENERALIZED_TX_SET): true, + XdrToI32(TRANSACTION): true, + XdrToI32(SURVEY_REQUEST): true, + XdrToI32(SURVEY_RESPONSE): true, + XdrToI32(GET_SCP_QUORUMSET): true, + XdrToI32(SCP_QUORUMSET): true, + XdrToI32(SCP_MESSAGE): true, + XdrToI32(GET_SCP_STATE): true, + XdrToI32(SEND_MORE): true, + XdrToI32(SEND_MORE_EXTENDED): true, + XdrToI32(FLOOD_ADVERT): true, + XdrToI32(FLOOD_DEMAND): true, +} + +func (_ StellarMessage) XdrValidTags() map[int32]bool { + return _XdrTags_StellarMessage +} +func (u *StellarMessage) Error() *Error { + switch u.Type { + case ERROR_MSG: + if v, ok := u._u.(*Error); ok { + return v + } else { + var zero Error + u._u = &zero + return &zero } default: - XdrPanic("StellarMessage.QSet accessed when Type == %v", u.Type) + XdrPanic("StellarMessage.Error accessed when Type == %v", u.Type) return nil } } -func (u *StellarMessage) Envelope() *SCPEnvelope { +func (u *StellarMessage) Hello() *Hello { switch u.Type { - case SCP_MESSAGE: - if v, ok := u._u.(*SCPEnvelope); ok { + case HELLO: + if v, ok := u._u.(*Hello); ok { return v } else { - var zero SCPEnvelope + var zero Hello u._u = &zero return &zero } default: - XdrPanic("StellarMessage.Envelope accessed when Type == %v", u.Type) + XdrPanic("StellarMessage.Hello accessed when Type == %v", u.Type) return nil } } - -// ledger seq requested ; if 0, requests the latest -func (u *StellarMessage) GetSCPLedgerSeq() *Uint32 { +func (u *StellarMessage) Auth() *Auth { switch u.Type { - case GET_SCP_STATE: - if v, ok := u._u.(*Uint32); ok { + case AUTH: + if v, ok := u._u.(*Auth); ok { return v } else { - var zero Uint32 + var zero Auth u._u = &zero return &zero } default: - XdrPanic("StellarMessage.GetSCPLedgerSeq accessed when Type == %v", u.Type) + XdrPanic("StellarMessage.Auth accessed when Type == %v", u.Type) return nil } } -func (u *StellarMessage) SendMoreMessage() *SendMore { +func (u *StellarMessage) DontHave() *DontHave { switch u.Type { - case SEND_MORE: - if v, ok := u._u.(*SendMore); ok { + case DONT_HAVE: + if v, ok := u._u.(*DontHave); ok { return v } else { - var zero SendMore + var zero DontHave u._u = &zero return &zero } default: - XdrPanic("StellarMessage.SendMoreMessage accessed when Type == %v", u.Type) + XdrPanic("StellarMessage.DontHave accessed when Type == %v", u.Type) return nil } } -func (u StellarMessage) XdrValid() bool { +func (u *StellarMessage) Peers() *[]PeerAddress { switch u.Type { - case ERROR_MSG, HELLO, AUTH, DONT_HAVE, GET_PEERS, PEERS, GET_TX_SET, TX_SET, GENERALIZED_TX_SET, TRANSACTION, SURVEY_REQUEST, SURVEY_RESPONSE, GET_SCP_QUORUMSET, SCP_QUORUMSET, SCP_MESSAGE, GET_SCP_STATE, SEND_MORE: - return true + case PEERS: + if v, ok := u._u.(*[]PeerAddress); ok { + return v + } else { + var zero []PeerAddress + u._u = &zero + return &zero + } + default: + XdrPanic("StellarMessage.Peers accessed when Type == %v", u.Type) + return nil } - return false -} -func (u *StellarMessage) XdrUnionTag() XdrNum32 { - return XDR_MessageType(&u.Type) -} -func (u *StellarMessage) XdrUnionTagName() string { - return "Type" } -func (u *StellarMessage) XdrUnionBody() XdrType { +func (u *StellarMessage) TxSetHash() *Uint256 { switch u.Type { - case ERROR_MSG: - return XDR_Error(u.Error()) - case HELLO: - return XDR_Hello(u.Hello()) - case AUTH: - return XDR_Auth(u.Auth()) - case DONT_HAVE: - return XDR_DontHave(u.DontHave()) - case GET_PEERS: - return nil - case PEERS: - return (*_XdrVec_100_PeerAddress)(u.Peers()) case GET_TX_SET: - return XDR_Uint256(u.TxSetHash()) + if v, ok := u._u.(*Uint256); ok { + return v + } else { + var zero Uint256 + u._u = &zero + return &zero + } + default: + XdrPanic("StellarMessage.TxSetHash accessed when Type == %v", u.Type) + return nil + } +} +func (u *StellarMessage) TxSet() *TransactionSet { + switch u.Type { + case TX_SET: + if v, ok := u._u.(*TransactionSet); ok { + return v + } else { + var zero TransactionSet + u._u = &zero + return &zero + } + default: + XdrPanic("StellarMessage.TxSet accessed when Type == %v", u.Type) + return nil + } +} +func (u *StellarMessage) GeneralizedTxSet() *GeneralizedTransactionSet { + switch u.Type { + case GENERALIZED_TX_SET: + if v, ok := u._u.(*GeneralizedTransactionSet); ok { + return v + } else { + var zero GeneralizedTransactionSet + u._u = &zero + return &zero + } + default: + XdrPanic("StellarMessage.GeneralizedTxSet accessed when Type == %v", u.Type) + return nil + } +} +func (u *StellarMessage) Transaction() *TransactionEnvelope { + switch u.Type { + case TRANSACTION: + if v, ok := u._u.(*TransactionEnvelope); ok { + return v + } else { + var zero TransactionEnvelope + u._u = &zero + return &zero + } + default: + XdrPanic("StellarMessage.Transaction accessed when Type == %v", u.Type) + return nil + } +} +func (u *StellarMessage) SignedSurveyRequestMessage() *SignedSurveyRequestMessage { + switch u.Type { + case SURVEY_REQUEST: + if v, ok := u._u.(*SignedSurveyRequestMessage); ok { + return v + } else { + var zero SignedSurveyRequestMessage + u._u = &zero + return &zero + } + default: + XdrPanic("StellarMessage.SignedSurveyRequestMessage accessed when Type == %v", u.Type) + return nil + } +} +func (u *StellarMessage) SignedSurveyResponseMessage() *SignedSurveyResponseMessage { + switch u.Type { + case SURVEY_RESPONSE: + if v, ok := u._u.(*SignedSurveyResponseMessage); ok { + return v + } else { + var zero SignedSurveyResponseMessage + u._u = &zero + return &zero + } + default: + XdrPanic("StellarMessage.SignedSurveyResponseMessage accessed when Type == %v", u.Type) + return nil + } +} +func (u *StellarMessage) QSetHash() *Uint256 { + switch u.Type { + case GET_SCP_QUORUMSET: + if v, ok := u._u.(*Uint256); ok { + return v + } else { + var zero Uint256 + u._u = &zero + return &zero + } + default: + XdrPanic("StellarMessage.QSetHash accessed when Type == %v", u.Type) + return nil + } +} +func (u *StellarMessage) QSet() *SCPQuorumSet { + switch u.Type { + case SCP_QUORUMSET: + if v, ok := u._u.(*SCPQuorumSet); ok { + return v + } else { + var zero SCPQuorumSet + u._u = &zero + return &zero + } + default: + XdrPanic("StellarMessage.QSet accessed when Type == %v", u.Type) + return nil + } +} +func (u *StellarMessage) Envelope() *SCPEnvelope { + switch u.Type { + case SCP_MESSAGE: + if v, ok := u._u.(*SCPEnvelope); ok { + return v + } else { + var zero SCPEnvelope + u._u = &zero + return &zero + } + default: + XdrPanic("StellarMessage.Envelope accessed when Type == %v", u.Type) + return nil + } +} + +// ledger seq requested ; if 0, requests the latest +func (u *StellarMessage) GetSCPLedgerSeq() *Uint32 { + switch u.Type { + case GET_SCP_STATE: + if v, ok := u._u.(*Uint32); ok { + return v + } else { + var zero Uint32 + u._u = &zero + return &zero + } + default: + XdrPanic("StellarMessage.GetSCPLedgerSeq accessed when Type == %v", u.Type) + return nil + } +} +func (u *StellarMessage) SendMoreMessage() *SendMore { + switch u.Type { + case SEND_MORE: + if v, ok := u._u.(*SendMore); ok { + return v + } else { + var zero SendMore + u._u = &zero + return &zero + } + default: + XdrPanic("StellarMessage.SendMoreMessage accessed when Type == %v", u.Type) + return nil + } +} +func (u *StellarMessage) SendMoreExtendedMessage() *SendMoreExtended { + switch u.Type { + case SEND_MORE_EXTENDED: + if v, ok := u._u.(*SendMoreExtended); ok { + return v + } else { + var zero SendMoreExtended + u._u = &zero + return &zero + } + default: + XdrPanic("StellarMessage.SendMoreExtendedMessage accessed when Type == %v", u.Type) + return nil + } +} +func (u *StellarMessage) FloodAdvert() *FloodAdvert { + switch u.Type { + case FLOOD_ADVERT: + if v, ok := u._u.(*FloodAdvert); ok { + return v + } else { + var zero FloodAdvert + u._u = &zero + return &zero + } + default: + XdrPanic("StellarMessage.FloodAdvert accessed when Type == %v", u.Type) + return nil + } +} +func (u *StellarMessage) FloodDemand() *FloodDemand { + switch u.Type { + case FLOOD_DEMAND: + if v, ok := u._u.(*FloodDemand); ok { + return v + } else { + var zero FloodDemand + u._u = &zero + return &zero + } + default: + XdrPanic("StellarMessage.FloodDemand accessed when Type == %v", u.Type) + return nil + } +} +func (u StellarMessage) XdrValid() bool { + switch u.Type { + case ERROR_MSG, HELLO, AUTH, DONT_HAVE, GET_PEERS, PEERS, GET_TX_SET, TX_SET, GENERALIZED_TX_SET, TRANSACTION, SURVEY_REQUEST, SURVEY_RESPONSE, GET_SCP_QUORUMSET, SCP_QUORUMSET, SCP_MESSAGE, GET_SCP_STATE, SEND_MORE, SEND_MORE_EXTENDED, FLOOD_ADVERT, FLOOD_DEMAND: + return true + } + return false +} +func (u *StellarMessage) XdrUnionTag() XdrNum32 { + return XDR_MessageType(&u.Type) +} +func (u *StellarMessage) XdrUnionTagName() string { + return "Type" +} +func (u *StellarMessage) XdrUnionBody() XdrType { + switch u.Type { + case ERROR_MSG: + return XDR_Error(u.Error()) + case HELLO: + return XDR_Hello(u.Hello()) + case AUTH: + return XDR_Auth(u.Auth()) + case DONT_HAVE: + return XDR_DontHave(u.DontHave()) + case GET_PEERS: + return nil + case PEERS: + return (*_XdrVec_100_PeerAddress)(u.Peers()) + case GET_TX_SET: + return XDR_Uint256(u.TxSetHash()) case TX_SET: return XDR_TransactionSet(u.TxSet()) case GENERALIZED_TX_SET: @@ -11314,6 +13955,12 @@ func (u *StellarMessage) XdrUnionBody() XdrType { return XDR_Uint32(u.GetSCPLedgerSeq()) case SEND_MORE: return XDR_SendMore(u.SendMoreMessage()) + case SEND_MORE_EXTENDED: + return XDR_SendMoreExtended(u.SendMoreExtendedMessage()) + case FLOOD_ADVERT: + return XDR_FloodAdvert(u.FloodAdvert()) + case FLOOD_DEMAND: + return XDR_FloodDemand(u.FloodDemand()) } return nil } @@ -11353,6 +14000,12 @@ func (u *StellarMessage) XdrUnionBodyName() string { return "GetSCPLedgerSeq" case SEND_MORE: return "SendMoreMessage" + case SEND_MORE_EXTENDED: + return "SendMoreExtendedMessage" + case FLOOD_ADVERT: + return "FloodAdvert" + case FLOOD_DEMAND: + return "FloodDemand" } return "" } @@ -11419,6 +14072,15 @@ func (u *StellarMessage) XdrRecurse(x XDR, name string) { case SEND_MORE: x.Marshal(x.Sprintf("%ssendMoreMessage", name), XDR_SendMore(u.SendMoreMessage())) return + case SEND_MORE_EXTENDED: + x.Marshal(x.Sprintf("%ssendMoreExtendedMessage", name), XDR_SendMoreExtended(u.SendMoreExtendedMessage())) + return + case FLOOD_ADVERT: + x.Marshal(x.Sprintf("%sfloodAdvert", name), XDR_FloodAdvert(u.FloodAdvert())) + return + case FLOOD_DEMAND: + x.Marshal(x.Sprintf("%sfloodDemand", name), XDR_FloodDemand(u.FloodDemand())) + return } XdrPanic("invalid Type (%v) in StellarMessage", u.Type) } @@ -11732,6 +14394,9 @@ var _XdrNames_OperationType = map[int32]string{ int32(SET_TRUST_LINE_FLAGS): "SET_TRUST_LINE_FLAGS", int32(LIQUIDITY_POOL_DEPOSIT): "LIQUIDITY_POOL_DEPOSIT", int32(LIQUIDITY_POOL_WITHDRAW): "LIQUIDITY_POOL_WITHDRAW", + int32(INVOKE_HOST_FUNCTION): "INVOKE_HOST_FUNCTION", + int32(EXTEND_FOOTPRINT_TTL): "EXTEND_FOOTPRINT_TTL", + int32(RESTORE_FOOTPRINT): "RESTORE_FOOTPRINT", } var _XdrValues_OperationType = map[string]int32{ "CREATE_ACCOUNT": int32(CREATE_ACCOUNT), @@ -11758,6 +14423,9 @@ var _XdrValues_OperationType = map[string]int32{ "SET_TRUST_LINE_FLAGS": int32(SET_TRUST_LINE_FLAGS), "LIQUIDITY_POOL_DEPOSIT": int32(LIQUIDITY_POOL_DEPOSIT), "LIQUIDITY_POOL_WITHDRAW": int32(LIQUIDITY_POOL_WITHDRAW), + "INVOKE_HOST_FUNCTION": int32(INVOKE_HOST_FUNCTION), + "EXTEND_FOOTPRINT_TTL": int32(EXTEND_FOOTPRINT_TTL), + "RESTORE_FOOTPRINT": int32(RESTORE_FOOTPRINT), } func (OperationType) XdrEnumNames() map[int32]string { @@ -12761,1120 +15429,1490 @@ func (v *LiquidityPoolWithdrawOp) XdrRecurse(x XDR, name string) { } func XDR_LiquidityPoolWithdrawOp(v *LiquidityPoolWithdrawOp) *LiquidityPoolWithdrawOp { return v } -var _XdrTags_XdrAnon_Operation_Body = map[int32]bool{ - XdrToI32(CREATE_ACCOUNT): true, - XdrToI32(PAYMENT): true, - XdrToI32(PATH_PAYMENT_STRICT_RECEIVE): true, - XdrToI32(MANAGE_SELL_OFFER): true, - XdrToI32(CREATE_PASSIVE_SELL_OFFER): true, - XdrToI32(SET_OPTIONS): true, - XdrToI32(CHANGE_TRUST): true, - XdrToI32(ALLOW_TRUST): true, - XdrToI32(ACCOUNT_MERGE): true, - XdrToI32(INFLATION): true, - XdrToI32(MANAGE_DATA): true, - XdrToI32(BUMP_SEQUENCE): true, - XdrToI32(MANAGE_BUY_OFFER): true, - XdrToI32(PATH_PAYMENT_STRICT_SEND): true, - XdrToI32(CREATE_CLAIMABLE_BALANCE): true, - XdrToI32(CLAIM_CLAIMABLE_BALANCE): true, - XdrToI32(BEGIN_SPONSORING_FUTURE_RESERVES): true, - XdrToI32(END_SPONSORING_FUTURE_RESERVES): true, - XdrToI32(REVOKE_SPONSORSHIP): true, - XdrToI32(CLAWBACK): true, - XdrToI32(CLAWBACK_CLAIMABLE_BALANCE): true, - XdrToI32(SET_TRUST_LINE_FLAGS): true, - XdrToI32(LIQUIDITY_POOL_DEPOSIT): true, - XdrToI32(LIQUIDITY_POOL_WITHDRAW): true, +var _XdrNames_HostFunctionType = map[int32]string{ + int32(HOST_FUNCTION_TYPE_INVOKE_CONTRACT): "HOST_FUNCTION_TYPE_INVOKE_CONTRACT", + int32(HOST_FUNCTION_TYPE_CREATE_CONTRACT): "HOST_FUNCTION_TYPE_CREATE_CONTRACT", + int32(HOST_FUNCTION_TYPE_UPLOAD_CONTRACT_WASM): "HOST_FUNCTION_TYPE_UPLOAD_CONTRACT_WASM", +} +var _XdrValues_HostFunctionType = map[string]int32{ + "HOST_FUNCTION_TYPE_INVOKE_CONTRACT": int32(HOST_FUNCTION_TYPE_INVOKE_CONTRACT), + "HOST_FUNCTION_TYPE_CREATE_CONTRACT": int32(HOST_FUNCTION_TYPE_CREATE_CONTRACT), + "HOST_FUNCTION_TYPE_UPLOAD_CONTRACT_WASM": int32(HOST_FUNCTION_TYPE_UPLOAD_CONTRACT_WASM), } -func (_ XdrAnon_Operation_Body) XdrValidTags() map[int32]bool { - return _XdrTags_XdrAnon_Operation_Body +func (HostFunctionType) XdrEnumNames() map[int32]string { + return _XdrNames_HostFunctionType } -func (u *XdrAnon_Operation_Body) CreateAccountOp() *CreateAccountOp { - switch u.Type { - case CREATE_ACCOUNT: - if v, ok := u._u.(*CreateAccountOp); ok { - return v - } else { - var zero CreateAccountOp - u._u = &zero - return &zero +func (v HostFunctionType) String() string { + if s, ok := _XdrNames_HostFunctionType[int32(v)]; ok { + return s + } + return fmt.Sprintf("HostFunctionType#%d", v) +} +func (v *HostFunctionType) Scan(ss fmt.ScanState, _ rune) error { + if tok, err := ss.Token(true, XdrSymChar); err != nil { + return err + } else { + stok := string(tok) + if val, ok := _XdrValues_HostFunctionType[stok]; ok { + *v = HostFunctionType(val) + return nil + } else if stok == "HostFunctionType" { + if n, err := fmt.Fscanf(ss, "#%d", (*int32)(v)); n == 1 && err == nil { + return nil + } } - default: - XdrPanic("XdrAnon_Operation_Body.CreateAccountOp accessed when Type == %v", u.Type) - return nil + return XdrError(fmt.Sprintf("%s is not a valid HostFunctionType.", stok)) } } -func (u *XdrAnon_Operation_Body) PaymentOp() *PaymentOp { - switch u.Type { - case PAYMENT: - if v, ok := u._u.(*PaymentOp); ok { - return v - } else { - var zero PaymentOp - u._u = &zero - return &zero +func (v HostFunctionType) GetU32() uint32 { return uint32(v) } +func (v *HostFunctionType) SetU32(n uint32) { *v = HostFunctionType(n) } +func (v *HostFunctionType) XdrPointer() interface{} { return v } +func (HostFunctionType) XdrTypeName() string { return "HostFunctionType" } +func (v HostFunctionType) XdrValue() interface{} { return v } +func (v *HostFunctionType) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } + +type XdrType_HostFunctionType = *HostFunctionType + +func XDR_HostFunctionType(v *HostFunctionType) *HostFunctionType { return v } + +var _XdrNames_ContractIDPreimageType = map[int32]string{ + int32(CONTRACT_ID_PREIMAGE_FROM_ADDRESS): "CONTRACT_ID_PREIMAGE_FROM_ADDRESS", + int32(CONTRACT_ID_PREIMAGE_FROM_ASSET): "CONTRACT_ID_PREIMAGE_FROM_ASSET", +} +var _XdrValues_ContractIDPreimageType = map[string]int32{ + "CONTRACT_ID_PREIMAGE_FROM_ADDRESS": int32(CONTRACT_ID_PREIMAGE_FROM_ADDRESS), + "CONTRACT_ID_PREIMAGE_FROM_ASSET": int32(CONTRACT_ID_PREIMAGE_FROM_ASSET), +} + +func (ContractIDPreimageType) XdrEnumNames() map[int32]string { + return _XdrNames_ContractIDPreimageType +} +func (v ContractIDPreimageType) String() string { + if s, ok := _XdrNames_ContractIDPreimageType[int32(v)]; ok { + return s + } + return fmt.Sprintf("ContractIDPreimageType#%d", v) +} +func (v *ContractIDPreimageType) Scan(ss fmt.ScanState, _ rune) error { + if tok, err := ss.Token(true, XdrSymChar); err != nil { + return err + } else { + stok := string(tok) + if val, ok := _XdrValues_ContractIDPreimageType[stok]; ok { + *v = ContractIDPreimageType(val) + return nil + } else if stok == "ContractIDPreimageType" { + if n, err := fmt.Fscanf(ss, "#%d", (*int32)(v)); n == 1 && err == nil { + return nil + } } - default: - XdrPanic("XdrAnon_Operation_Body.PaymentOp accessed when Type == %v", u.Type) - return nil + return XdrError(fmt.Sprintf("%s is not a valid ContractIDPreimageType.", stok)) } } -func (u *XdrAnon_Operation_Body) PathPaymentStrictReceiveOp() *PathPaymentStrictReceiveOp { +func (v ContractIDPreimageType) GetU32() uint32 { return uint32(v) } +func (v *ContractIDPreimageType) SetU32(n uint32) { *v = ContractIDPreimageType(n) } +func (v *ContractIDPreimageType) XdrPointer() interface{} { return v } +func (ContractIDPreimageType) XdrTypeName() string { return "ContractIDPreimageType" } +func (v ContractIDPreimageType) XdrValue() interface{} { return v } +func (v *ContractIDPreimageType) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } + +type XdrType_ContractIDPreimageType = *ContractIDPreimageType + +func XDR_ContractIDPreimageType(v *ContractIDPreimageType) *ContractIDPreimageType { return v } + +type XdrType_XdrAnon_ContractIDPreimage_FromAddress = *XdrAnon_ContractIDPreimage_FromAddress + +func (v *XdrAnon_ContractIDPreimage_FromAddress) XdrPointer() interface{} { return v } +func (XdrAnon_ContractIDPreimage_FromAddress) XdrTypeName() string { + return "XdrAnon_ContractIDPreimage_FromAddress" +} +func (v XdrAnon_ContractIDPreimage_FromAddress) XdrValue() interface{} { return v } +func (v *XdrAnon_ContractIDPreimage_FromAddress) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v *XdrAnon_ContractIDPreimage_FromAddress) XdrRecurse(x XDR, name string) { + if name != "" { + name = x.Sprintf("%s.", name) + } + x.Marshal(x.Sprintf("%saddress", name), XDR_SCAddress(&v.Address)) + x.Marshal(x.Sprintf("%ssalt", name), XDR_Uint256(&v.Salt)) +} +func XDR_XdrAnon_ContractIDPreimage_FromAddress(v *XdrAnon_ContractIDPreimage_FromAddress) *XdrAnon_ContractIDPreimage_FromAddress { + return v +} + +var _XdrTags_ContractIDPreimage = map[int32]bool{ + XdrToI32(CONTRACT_ID_PREIMAGE_FROM_ADDRESS): true, + XdrToI32(CONTRACT_ID_PREIMAGE_FROM_ASSET): true, +} + +func (_ ContractIDPreimage) XdrValidTags() map[int32]bool { + return _XdrTags_ContractIDPreimage +} +func (u *ContractIDPreimage) FromAddress() *XdrAnon_ContractIDPreimage_FromAddress { switch u.Type { - case PATH_PAYMENT_STRICT_RECEIVE: - if v, ok := u._u.(*PathPaymentStrictReceiveOp); ok { + case CONTRACT_ID_PREIMAGE_FROM_ADDRESS: + if v, ok := u._u.(*XdrAnon_ContractIDPreimage_FromAddress); ok { return v } else { - var zero PathPaymentStrictReceiveOp + var zero XdrAnon_ContractIDPreimage_FromAddress u._u = &zero return &zero } default: - XdrPanic("XdrAnon_Operation_Body.PathPaymentStrictReceiveOp accessed when Type == %v", u.Type) + XdrPanic("ContractIDPreimage.FromAddress accessed when Type == %v", u.Type) return nil } } -func (u *XdrAnon_Operation_Body) ManageSellOfferOp() *ManageSellOfferOp { +func (u *ContractIDPreimage) FromAsset() *Asset { switch u.Type { - case MANAGE_SELL_OFFER: - if v, ok := u._u.(*ManageSellOfferOp); ok { + case CONTRACT_ID_PREIMAGE_FROM_ASSET: + if v, ok := u._u.(*Asset); ok { return v } else { - var zero ManageSellOfferOp + var zero Asset u._u = &zero return &zero } default: - XdrPanic("XdrAnon_Operation_Body.ManageSellOfferOp accessed when Type == %v", u.Type) + XdrPanic("ContractIDPreimage.FromAsset accessed when Type == %v", u.Type) return nil } } -func (u *XdrAnon_Operation_Body) CreatePassiveSellOfferOp() *CreatePassiveSellOfferOp { +func (u ContractIDPreimage) XdrValid() bool { switch u.Type { - case CREATE_PASSIVE_SELL_OFFER: - if v, ok := u._u.(*CreatePassiveSellOfferOp); ok { - return v - } else { - var zero CreatePassiveSellOfferOp - u._u = &zero - return &zero - } - default: - XdrPanic("XdrAnon_Operation_Body.CreatePassiveSellOfferOp accessed when Type == %v", u.Type) - return nil + case CONTRACT_ID_PREIMAGE_FROM_ADDRESS, CONTRACT_ID_PREIMAGE_FROM_ASSET: + return true } + return false } -func (u *XdrAnon_Operation_Body) SetOptionsOp() *SetOptionsOp { +func (u *ContractIDPreimage) XdrUnionTag() XdrNum32 { + return XDR_ContractIDPreimageType(&u.Type) +} +func (u *ContractIDPreimage) XdrUnionTagName() string { + return "Type" +} +func (u *ContractIDPreimage) XdrUnionBody() XdrType { switch u.Type { - case SET_OPTIONS: - if v, ok := u._u.(*SetOptionsOp); ok { - return v - } else { - var zero SetOptionsOp - u._u = &zero - return &zero - } - default: - XdrPanic("XdrAnon_Operation_Body.SetOptionsOp accessed when Type == %v", u.Type) - return nil + case CONTRACT_ID_PREIMAGE_FROM_ADDRESS: + return XDR_XdrAnon_ContractIDPreimage_FromAddress(u.FromAddress()) + case CONTRACT_ID_PREIMAGE_FROM_ASSET: + return XDR_Asset(u.FromAsset()) } + return nil } -func (u *XdrAnon_Operation_Body) ChangeTrustOp() *ChangeTrustOp { +func (u *ContractIDPreimage) XdrUnionBodyName() string { switch u.Type { - case CHANGE_TRUST: - if v, ok := u._u.(*ChangeTrustOp); ok { - return v - } else { - var zero ChangeTrustOp - u._u = &zero - return &zero - } - default: - XdrPanic("XdrAnon_Operation_Body.ChangeTrustOp accessed when Type == %v", u.Type) - return nil + case CONTRACT_ID_PREIMAGE_FROM_ADDRESS: + return "FromAddress" + case CONTRACT_ID_PREIMAGE_FROM_ASSET: + return "FromAsset" } + return "" } -func (u *XdrAnon_Operation_Body) AllowTrustOp() *AllowTrustOp { + +type XdrType_ContractIDPreimage = *ContractIDPreimage + +func (v *ContractIDPreimage) XdrPointer() interface{} { return v } +func (ContractIDPreimage) XdrTypeName() string { return "ContractIDPreimage" } +func (v ContractIDPreimage) XdrValue() interface{} { return v } +func (v *ContractIDPreimage) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (u *ContractIDPreimage) XdrRecurse(x XDR, name string) { + if name != "" { + name = x.Sprintf("%s.", name) + } + XDR_ContractIDPreimageType(&u.Type).XdrMarshal(x, x.Sprintf("%stype", name)) switch u.Type { - case ALLOW_TRUST: - if v, ok := u._u.(*AllowTrustOp); ok { - return v - } else { - var zero AllowTrustOp - u._u = &zero - return &zero - } - default: - XdrPanic("XdrAnon_Operation_Body.AllowTrustOp accessed when Type == %v", u.Type) - return nil + case CONTRACT_ID_PREIMAGE_FROM_ADDRESS: + x.Marshal(x.Sprintf("%sfromAddress", name), XDR_XdrAnon_ContractIDPreimage_FromAddress(u.FromAddress())) + return + case CONTRACT_ID_PREIMAGE_FROM_ASSET: + x.Marshal(x.Sprintf("%sfromAsset", name), XDR_Asset(u.FromAsset())) + return } + XdrPanic("invalid Type (%v) in ContractIDPreimage", u.Type) } -func (u *XdrAnon_Operation_Body) Destination() *MuxedAccount { +func XDR_ContractIDPreimage(v *ContractIDPreimage) *ContractIDPreimage { return v } + +type XdrType_CreateContractArgs = *CreateContractArgs + +func (v *CreateContractArgs) XdrPointer() interface{} { return v } +func (CreateContractArgs) XdrTypeName() string { return "CreateContractArgs" } +func (v CreateContractArgs) XdrValue() interface{} { return v } +func (v *CreateContractArgs) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v *CreateContractArgs) XdrRecurse(x XDR, name string) { + if name != "" { + name = x.Sprintf("%s.", name) + } + x.Marshal(x.Sprintf("%scontractIDPreimage", name), XDR_ContractIDPreimage(&v.ContractIDPreimage)) + x.Marshal(x.Sprintf("%sexecutable", name), XDR_ContractExecutable(&v.Executable)) +} +func XDR_CreateContractArgs(v *CreateContractArgs) *CreateContractArgs { return v } + +type XdrType_InvokeContractArgs = *InvokeContractArgs + +func (v *InvokeContractArgs) XdrPointer() interface{} { return v } +func (InvokeContractArgs) XdrTypeName() string { return "InvokeContractArgs" } +func (v InvokeContractArgs) XdrValue() interface{} { return v } +func (v *InvokeContractArgs) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v *InvokeContractArgs) XdrRecurse(x XDR, name string) { + if name != "" { + name = x.Sprintf("%s.", name) + } + x.Marshal(x.Sprintf("%scontractAddress", name), XDR_SCAddress(&v.ContractAddress)) + x.Marshal(x.Sprintf("%sfunctionName", name), XDR_SCSymbol(&v.FunctionName)) + x.Marshal(x.Sprintf("%sargs", name), (*_XdrVec_unbounded_SCVal)(&v.Args)) +} +func XDR_InvokeContractArgs(v *InvokeContractArgs) *InvokeContractArgs { return v } + +var _XdrTags_HostFunction = map[int32]bool{ + XdrToI32(HOST_FUNCTION_TYPE_INVOKE_CONTRACT): true, + XdrToI32(HOST_FUNCTION_TYPE_CREATE_CONTRACT): true, + XdrToI32(HOST_FUNCTION_TYPE_UPLOAD_CONTRACT_WASM): true, +} + +func (_ HostFunction) XdrValidTags() map[int32]bool { + return _XdrTags_HostFunction +} +func (u *HostFunction) InvokeContract() *InvokeContractArgs { switch u.Type { - case ACCOUNT_MERGE: - if v, ok := u._u.(*MuxedAccount); ok { + case HOST_FUNCTION_TYPE_INVOKE_CONTRACT: + if v, ok := u._u.(*InvokeContractArgs); ok { return v } else { - var zero MuxedAccount + var zero InvokeContractArgs u._u = &zero return &zero } default: - XdrPanic("XdrAnon_Operation_Body.Destination accessed when Type == %v", u.Type) + XdrPanic("HostFunction.InvokeContract accessed when Type == %v", u.Type) return nil } } -func (u *XdrAnon_Operation_Body) ManageDataOp() *ManageDataOp { +func (u *HostFunction) CreateContract() *CreateContractArgs { switch u.Type { - case MANAGE_DATA: - if v, ok := u._u.(*ManageDataOp); ok { + case HOST_FUNCTION_TYPE_CREATE_CONTRACT: + if v, ok := u._u.(*CreateContractArgs); ok { return v } else { - var zero ManageDataOp + var zero CreateContractArgs u._u = &zero return &zero } default: - XdrPanic("XdrAnon_Operation_Body.ManageDataOp accessed when Type == %v", u.Type) + XdrPanic("HostFunction.CreateContract accessed when Type == %v", u.Type) return nil } } -func (u *XdrAnon_Operation_Body) BumpSequenceOp() *BumpSequenceOp { +func (u *HostFunction) Wasm() *[]byte { switch u.Type { - case BUMP_SEQUENCE: - if v, ok := u._u.(*BumpSequenceOp); ok { + case HOST_FUNCTION_TYPE_UPLOAD_CONTRACT_WASM: + if v, ok := u._u.(*[]byte); ok { return v } else { - var zero BumpSequenceOp + var zero []byte u._u = &zero return &zero } default: - XdrPanic("XdrAnon_Operation_Body.BumpSequenceOp accessed when Type == %v", u.Type) + XdrPanic("HostFunction.Wasm accessed when Type == %v", u.Type) return nil } } -func (u *XdrAnon_Operation_Body) ManageBuyOfferOp() *ManageBuyOfferOp { +func (u HostFunction) XdrValid() bool { switch u.Type { - case MANAGE_BUY_OFFER: - if v, ok := u._u.(*ManageBuyOfferOp); ok { - return v - } else { - var zero ManageBuyOfferOp - u._u = &zero - return &zero - } - default: - XdrPanic("XdrAnon_Operation_Body.ManageBuyOfferOp accessed when Type == %v", u.Type) - return nil + case HOST_FUNCTION_TYPE_INVOKE_CONTRACT, HOST_FUNCTION_TYPE_CREATE_CONTRACT, HOST_FUNCTION_TYPE_UPLOAD_CONTRACT_WASM: + return true } + return false } -func (u *XdrAnon_Operation_Body) PathPaymentStrictSendOp() *PathPaymentStrictSendOp { +func (u *HostFunction) XdrUnionTag() XdrNum32 { + return XDR_HostFunctionType(&u.Type) +} +func (u *HostFunction) XdrUnionTagName() string { + return "Type" +} +func (u *HostFunction) XdrUnionBody() XdrType { switch u.Type { - case PATH_PAYMENT_STRICT_SEND: - if v, ok := u._u.(*PathPaymentStrictSendOp); ok { - return v - } else { - var zero PathPaymentStrictSendOp - u._u = &zero - return &zero + case HOST_FUNCTION_TYPE_INVOKE_CONTRACT: + return XDR_InvokeContractArgs(u.InvokeContract()) + case HOST_FUNCTION_TYPE_CREATE_CONTRACT: + return XDR_CreateContractArgs(u.CreateContract()) + case HOST_FUNCTION_TYPE_UPLOAD_CONTRACT_WASM: + return XdrVecOpaque{u.Wasm(), 0xffffffff} + } + return nil +} +func (u *HostFunction) XdrUnionBodyName() string { + switch u.Type { + case HOST_FUNCTION_TYPE_INVOKE_CONTRACT: + return "InvokeContract" + case HOST_FUNCTION_TYPE_CREATE_CONTRACT: + return "CreateContract" + case HOST_FUNCTION_TYPE_UPLOAD_CONTRACT_WASM: + return "Wasm" + } + return "" +} + +type XdrType_HostFunction = *HostFunction + +func (v *HostFunction) XdrPointer() interface{} { return v } +func (HostFunction) XdrTypeName() string { return "HostFunction" } +func (v HostFunction) XdrValue() interface{} { return v } +func (v *HostFunction) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (u *HostFunction) XdrRecurse(x XDR, name string) { + if name != "" { + name = x.Sprintf("%s.", name) + } + XDR_HostFunctionType(&u.Type).XdrMarshal(x, x.Sprintf("%stype", name)) + switch u.Type { + case HOST_FUNCTION_TYPE_INVOKE_CONTRACT: + x.Marshal(x.Sprintf("%sinvokeContract", name), XDR_InvokeContractArgs(u.InvokeContract())) + return + case HOST_FUNCTION_TYPE_CREATE_CONTRACT: + x.Marshal(x.Sprintf("%screateContract", name), XDR_CreateContractArgs(u.CreateContract())) + return + case HOST_FUNCTION_TYPE_UPLOAD_CONTRACT_WASM: + x.Marshal(x.Sprintf("%swasm", name), XdrVecOpaque{u.Wasm(), 0xffffffff}) + return + } + XdrPanic("invalid Type (%v) in HostFunction", u.Type) +} +func XDR_HostFunction(v *HostFunction) *HostFunction { return v } + +var _XdrNames_SorobanAuthorizedFunctionType = map[int32]string{ + int32(SOROBAN_AUTHORIZED_FUNCTION_TYPE_CONTRACT_FN): "SOROBAN_AUTHORIZED_FUNCTION_TYPE_CONTRACT_FN", + int32(SOROBAN_AUTHORIZED_FUNCTION_TYPE_CREATE_CONTRACT_HOST_FN): "SOROBAN_AUTHORIZED_FUNCTION_TYPE_CREATE_CONTRACT_HOST_FN", +} +var _XdrValues_SorobanAuthorizedFunctionType = map[string]int32{ + "SOROBAN_AUTHORIZED_FUNCTION_TYPE_CONTRACT_FN": int32(SOROBAN_AUTHORIZED_FUNCTION_TYPE_CONTRACT_FN), + "SOROBAN_AUTHORIZED_FUNCTION_TYPE_CREATE_CONTRACT_HOST_FN": int32(SOROBAN_AUTHORIZED_FUNCTION_TYPE_CREATE_CONTRACT_HOST_FN), +} + +func (SorobanAuthorizedFunctionType) XdrEnumNames() map[int32]string { + return _XdrNames_SorobanAuthorizedFunctionType +} +func (v SorobanAuthorizedFunctionType) String() string { + if s, ok := _XdrNames_SorobanAuthorizedFunctionType[int32(v)]; ok { + return s + } + return fmt.Sprintf("SorobanAuthorizedFunctionType#%d", v) +} +func (v *SorobanAuthorizedFunctionType) Scan(ss fmt.ScanState, _ rune) error { + if tok, err := ss.Token(true, XdrSymChar); err != nil { + return err + } else { + stok := string(tok) + if val, ok := _XdrValues_SorobanAuthorizedFunctionType[stok]; ok { + *v = SorobanAuthorizedFunctionType(val) + return nil + } else if stok == "SorobanAuthorizedFunctionType" { + if n, err := fmt.Fscanf(ss, "#%d", (*int32)(v)); n == 1 && err == nil { + return nil + } } - default: - XdrPanic("XdrAnon_Operation_Body.PathPaymentStrictSendOp accessed when Type == %v", u.Type) - return nil + return XdrError(fmt.Sprintf("%s is not a valid SorobanAuthorizedFunctionType.", stok)) } } -func (u *XdrAnon_Operation_Body) CreateClaimableBalanceOp() *CreateClaimableBalanceOp { +func (v SorobanAuthorizedFunctionType) GetU32() uint32 { return uint32(v) } +func (v *SorobanAuthorizedFunctionType) SetU32(n uint32) { *v = SorobanAuthorizedFunctionType(n) } +func (v *SorobanAuthorizedFunctionType) XdrPointer() interface{} { return v } +func (SorobanAuthorizedFunctionType) XdrTypeName() string { return "SorobanAuthorizedFunctionType" } +func (v SorobanAuthorizedFunctionType) XdrValue() interface{} { return v } +func (v *SorobanAuthorizedFunctionType) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } + +type XdrType_SorobanAuthorizedFunctionType = *SorobanAuthorizedFunctionType + +func XDR_SorobanAuthorizedFunctionType(v *SorobanAuthorizedFunctionType) *SorobanAuthorizedFunctionType { + return v +} + +var _XdrTags_SorobanAuthorizedFunction = map[int32]bool{ + XdrToI32(SOROBAN_AUTHORIZED_FUNCTION_TYPE_CONTRACT_FN): true, + XdrToI32(SOROBAN_AUTHORIZED_FUNCTION_TYPE_CREATE_CONTRACT_HOST_FN): true, +} + +func (_ SorobanAuthorizedFunction) XdrValidTags() map[int32]bool { + return _XdrTags_SorobanAuthorizedFunction +} +func (u *SorobanAuthorizedFunction) ContractFn() *InvokeContractArgs { switch u.Type { - case CREATE_CLAIMABLE_BALANCE: - if v, ok := u._u.(*CreateClaimableBalanceOp); ok { + case SOROBAN_AUTHORIZED_FUNCTION_TYPE_CONTRACT_FN: + if v, ok := u._u.(*InvokeContractArgs); ok { return v } else { - var zero CreateClaimableBalanceOp + var zero InvokeContractArgs u._u = &zero return &zero } default: - XdrPanic("XdrAnon_Operation_Body.CreateClaimableBalanceOp accessed when Type == %v", u.Type) + XdrPanic("SorobanAuthorizedFunction.ContractFn accessed when Type == %v", u.Type) return nil } } -func (u *XdrAnon_Operation_Body) ClaimClaimableBalanceOp() *ClaimClaimableBalanceOp { +func (u *SorobanAuthorizedFunction) CreateContractHostFn() *CreateContractArgs { switch u.Type { - case CLAIM_CLAIMABLE_BALANCE: - if v, ok := u._u.(*ClaimClaimableBalanceOp); ok { + case SOROBAN_AUTHORIZED_FUNCTION_TYPE_CREATE_CONTRACT_HOST_FN: + if v, ok := u._u.(*CreateContractArgs); ok { return v } else { - var zero ClaimClaimableBalanceOp + var zero CreateContractArgs u._u = &zero return &zero } default: - XdrPanic("XdrAnon_Operation_Body.ClaimClaimableBalanceOp accessed when Type == %v", u.Type) + XdrPanic("SorobanAuthorizedFunction.CreateContractHostFn accessed when Type == %v", u.Type) return nil } } -func (u *XdrAnon_Operation_Body) BeginSponsoringFutureReservesOp() *BeginSponsoringFutureReservesOp { +func (u SorobanAuthorizedFunction) XdrValid() bool { switch u.Type { - case BEGIN_SPONSORING_FUTURE_RESERVES: - if v, ok := u._u.(*BeginSponsoringFutureReservesOp); ok { - return v - } else { - var zero BeginSponsoringFutureReservesOp - u._u = &zero - return &zero - } - default: - XdrPanic("XdrAnon_Operation_Body.BeginSponsoringFutureReservesOp accessed when Type == %v", u.Type) - return nil + case SOROBAN_AUTHORIZED_FUNCTION_TYPE_CONTRACT_FN, SOROBAN_AUTHORIZED_FUNCTION_TYPE_CREATE_CONTRACT_HOST_FN: + return true } + return false } -func (u *XdrAnon_Operation_Body) RevokeSponsorshipOp() *RevokeSponsorshipOp { +func (u *SorobanAuthorizedFunction) XdrUnionTag() XdrNum32 { + return XDR_SorobanAuthorizedFunctionType(&u.Type) +} +func (u *SorobanAuthorizedFunction) XdrUnionTagName() string { + return "Type" +} +func (u *SorobanAuthorizedFunction) XdrUnionBody() XdrType { switch u.Type { - case REVOKE_SPONSORSHIP: - if v, ok := u._u.(*RevokeSponsorshipOp); ok { - return v - } else { - var zero RevokeSponsorshipOp - u._u = &zero - return &zero - } - default: - XdrPanic("XdrAnon_Operation_Body.RevokeSponsorshipOp accessed when Type == %v", u.Type) - return nil + case SOROBAN_AUTHORIZED_FUNCTION_TYPE_CONTRACT_FN: + return XDR_InvokeContractArgs(u.ContractFn()) + case SOROBAN_AUTHORIZED_FUNCTION_TYPE_CREATE_CONTRACT_HOST_FN: + return XDR_CreateContractArgs(u.CreateContractHostFn()) } + return nil } -func (u *XdrAnon_Operation_Body) ClawbackOp() *ClawbackOp { +func (u *SorobanAuthorizedFunction) XdrUnionBodyName() string { switch u.Type { - case CLAWBACK: - if v, ok := u._u.(*ClawbackOp); ok { - return v - } else { - var zero ClawbackOp - u._u = &zero - return &zero - } - default: - XdrPanic("XdrAnon_Operation_Body.ClawbackOp accessed when Type == %v", u.Type) - return nil + case SOROBAN_AUTHORIZED_FUNCTION_TYPE_CONTRACT_FN: + return "ContractFn" + case SOROBAN_AUTHORIZED_FUNCTION_TYPE_CREATE_CONTRACT_HOST_FN: + return "CreateContractHostFn" } + return "" } -func (u *XdrAnon_Operation_Body) ClawbackClaimableBalanceOp() *ClawbackClaimableBalanceOp { + +type XdrType_SorobanAuthorizedFunction = *SorobanAuthorizedFunction + +func (v *SorobanAuthorizedFunction) XdrPointer() interface{} { return v } +func (SorobanAuthorizedFunction) XdrTypeName() string { return "SorobanAuthorizedFunction" } +func (v SorobanAuthorizedFunction) XdrValue() interface{} { return v } +func (v *SorobanAuthorizedFunction) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (u *SorobanAuthorizedFunction) XdrRecurse(x XDR, name string) { + if name != "" { + name = x.Sprintf("%s.", name) + } + XDR_SorobanAuthorizedFunctionType(&u.Type).XdrMarshal(x, x.Sprintf("%stype", name)) switch u.Type { - case CLAWBACK_CLAIMABLE_BALANCE: - if v, ok := u._u.(*ClawbackClaimableBalanceOp); ok { - return v - } else { - var zero ClawbackClaimableBalanceOp - u._u = &zero - return &zero + case SOROBAN_AUTHORIZED_FUNCTION_TYPE_CONTRACT_FN: + x.Marshal(x.Sprintf("%scontractFn", name), XDR_InvokeContractArgs(u.ContractFn())) + return + case SOROBAN_AUTHORIZED_FUNCTION_TYPE_CREATE_CONTRACT_HOST_FN: + x.Marshal(x.Sprintf("%screateContractHostFn", name), XDR_CreateContractArgs(u.CreateContractHostFn())) + return + } + XdrPanic("invalid Type (%v) in SorobanAuthorizedFunction", u.Type) +} +func XDR_SorobanAuthorizedFunction(v *SorobanAuthorizedFunction) *SorobanAuthorizedFunction { return v } + +type _XdrVec_unbounded_SorobanAuthorizedInvocation []SorobanAuthorizedInvocation + +func (_XdrVec_unbounded_SorobanAuthorizedInvocation) XdrBound() uint32 { + const bound uint32 = 4294967295 // Force error if not const or doesn't fit + return bound +} +func (_XdrVec_unbounded_SorobanAuthorizedInvocation) XdrCheckLen(length uint32) { + if length > uint32(4294967295) { + XdrPanic("_XdrVec_unbounded_SorobanAuthorizedInvocation length %d exceeds bound 4294967295", length) + } else if int(length) < 0 { + XdrPanic("_XdrVec_unbounded_SorobanAuthorizedInvocation length %d exceeds max int", length) + } +} +func (v _XdrVec_unbounded_SorobanAuthorizedInvocation) GetVecLen() uint32 { return uint32(len(v)) } +func (v *_XdrVec_unbounded_SorobanAuthorizedInvocation) SetVecLen(length uint32) { + v.XdrCheckLen(length) + if int(length) <= cap(*v) { + if int(length) != len(*v) { + *v = (*v)[:int(length)] } - default: - XdrPanic("XdrAnon_Operation_Body.ClawbackClaimableBalanceOp accessed when Type == %v", u.Type) - return nil + return + } + newcap := 2 * cap(*v) + if newcap < int(length) { // also catches overflow where 2*cap < 0 + newcap = int(length) + } else if bound := uint(4294967295); uint(newcap) > bound { + if int(bound) < 0 { + bound = ^uint(0) >> 1 + } + newcap = int(bound) } + nv := make([]SorobanAuthorizedInvocation, int(length), newcap) + copy(nv, *v) + *v = nv } -func (u *XdrAnon_Operation_Body) SetTrustLineFlagsOp() *SetTrustLineFlagsOp { - switch u.Type { - case SET_TRUST_LINE_FLAGS: - if v, ok := u._u.(*SetTrustLineFlagsOp); ok { - return v - } else { - var zero SetTrustLineFlagsOp - u._u = &zero - return &zero +func (v *_XdrVec_unbounded_SorobanAuthorizedInvocation) XdrMarshalN(x XDR, name string, n uint32) { + v.XdrCheckLen(n) + for i := 0; i < int(n); i++ { + if i >= len(*v) { + v.SetVecLen(uint32(i + 1)) } - default: - XdrPanic("XdrAnon_Operation_Body.SetTrustLineFlagsOp accessed when Type == %v", u.Type) - return nil + XDR_SorobanAuthorizedInvocation(&(*v)[i]).XdrMarshal(x, x.Sprintf("%s[%d]", name, i)) + } + if int(n) < len(*v) { + *v = (*v)[:int(n)] } } -func (u *XdrAnon_Operation_Body) LiquidityPoolDepositOp() *LiquidityPoolDepositOp { - switch u.Type { - case LIQUIDITY_POOL_DEPOSIT: - if v, ok := u._u.(*LiquidityPoolDepositOp); ok { - return v - } else { - var zero LiquidityPoolDepositOp - u._u = &zero - return &zero +func (v *_XdrVec_unbounded_SorobanAuthorizedInvocation) XdrRecurse(x XDR, name string) { + size := XdrSize{Size: uint32(len(*v)), Bound: 4294967295} + x.Marshal(name, &size) + v.XdrMarshalN(x, name, size.Size) +} +func (_XdrVec_unbounded_SorobanAuthorizedInvocation) XdrTypeName() string { + return "SorobanAuthorizedInvocation<>" +} +func (v *_XdrVec_unbounded_SorobanAuthorizedInvocation) XdrPointer() interface{} { + return (*[]SorobanAuthorizedInvocation)(v) +} +func (v _XdrVec_unbounded_SorobanAuthorizedInvocation) XdrValue() interface{} { + return ([]SorobanAuthorizedInvocation)(v) +} +func (v *_XdrVec_unbounded_SorobanAuthorizedInvocation) XdrMarshal(x XDR, name string) { + x.Marshal(name, v) +} + +type XdrType_SorobanAuthorizedInvocation = *SorobanAuthorizedInvocation + +func (v *SorobanAuthorizedInvocation) XdrPointer() interface{} { return v } +func (SorobanAuthorizedInvocation) XdrTypeName() string { return "SorobanAuthorizedInvocation" } +func (v SorobanAuthorizedInvocation) XdrValue() interface{} { return v } +func (v *SorobanAuthorizedInvocation) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v *SorobanAuthorizedInvocation) XdrRecurse(x XDR, name string) { + if name != "" { + name = x.Sprintf("%s.", name) + } + x.Marshal(x.Sprintf("%sfunction", name), XDR_SorobanAuthorizedFunction(&v.Function)) + x.Marshal(x.Sprintf("%ssubInvocations", name), (*_XdrVec_unbounded_SorobanAuthorizedInvocation)(&v.SubInvocations)) +} +func XDR_SorobanAuthorizedInvocation(v *SorobanAuthorizedInvocation) *SorobanAuthorizedInvocation { + return v +} + +type XdrType_SorobanAddressCredentials = *SorobanAddressCredentials + +func (v *SorobanAddressCredentials) XdrPointer() interface{} { return v } +func (SorobanAddressCredentials) XdrTypeName() string { return "SorobanAddressCredentials" } +func (v SorobanAddressCredentials) XdrValue() interface{} { return v } +func (v *SorobanAddressCredentials) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v *SorobanAddressCredentials) XdrRecurse(x XDR, name string) { + if name != "" { + name = x.Sprintf("%s.", name) + } + x.Marshal(x.Sprintf("%saddress", name), XDR_SCAddress(&v.Address)) + x.Marshal(x.Sprintf("%snonce", name), XDR_Int64(&v.Nonce)) + x.Marshal(x.Sprintf("%ssignatureExpirationLedger", name), XDR_Uint32(&v.SignatureExpirationLedger)) + x.Marshal(x.Sprintf("%ssignature", name), XDR_SCVal(&v.Signature)) +} +func XDR_SorobanAddressCredentials(v *SorobanAddressCredentials) *SorobanAddressCredentials { return v } + +var _XdrNames_SorobanCredentialsType = map[int32]string{ + int32(SOROBAN_CREDENTIALS_SOURCE_ACCOUNT): "SOROBAN_CREDENTIALS_SOURCE_ACCOUNT", + int32(SOROBAN_CREDENTIALS_ADDRESS): "SOROBAN_CREDENTIALS_ADDRESS", +} +var _XdrValues_SorobanCredentialsType = map[string]int32{ + "SOROBAN_CREDENTIALS_SOURCE_ACCOUNT": int32(SOROBAN_CREDENTIALS_SOURCE_ACCOUNT), + "SOROBAN_CREDENTIALS_ADDRESS": int32(SOROBAN_CREDENTIALS_ADDRESS), +} + +func (SorobanCredentialsType) XdrEnumNames() map[int32]string { + return _XdrNames_SorobanCredentialsType +} +func (v SorobanCredentialsType) String() string { + if s, ok := _XdrNames_SorobanCredentialsType[int32(v)]; ok { + return s + } + return fmt.Sprintf("SorobanCredentialsType#%d", v) +} +func (v *SorobanCredentialsType) Scan(ss fmt.ScanState, _ rune) error { + if tok, err := ss.Token(true, XdrSymChar); err != nil { + return err + } else { + stok := string(tok) + if val, ok := _XdrValues_SorobanCredentialsType[stok]; ok { + *v = SorobanCredentialsType(val) + return nil + } else if stok == "SorobanCredentialsType" { + if n, err := fmt.Fscanf(ss, "#%d", (*int32)(v)); n == 1 && err == nil { + return nil + } } - default: - XdrPanic("XdrAnon_Operation_Body.LiquidityPoolDepositOp accessed when Type == %v", u.Type) - return nil + return XdrError(fmt.Sprintf("%s is not a valid SorobanCredentialsType.", stok)) } } -func (u *XdrAnon_Operation_Body) LiquidityPoolWithdrawOp() *LiquidityPoolWithdrawOp { +func (v SorobanCredentialsType) GetU32() uint32 { return uint32(v) } +func (v *SorobanCredentialsType) SetU32(n uint32) { *v = SorobanCredentialsType(n) } +func (v *SorobanCredentialsType) XdrPointer() interface{} { return v } +func (SorobanCredentialsType) XdrTypeName() string { return "SorobanCredentialsType" } +func (v SorobanCredentialsType) XdrValue() interface{} { return v } +func (v *SorobanCredentialsType) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } + +type XdrType_SorobanCredentialsType = *SorobanCredentialsType + +func XDR_SorobanCredentialsType(v *SorobanCredentialsType) *SorobanCredentialsType { return v } + +var _XdrTags_SorobanCredentials = map[int32]bool{ + XdrToI32(SOROBAN_CREDENTIALS_SOURCE_ACCOUNT): true, + XdrToI32(SOROBAN_CREDENTIALS_ADDRESS): true, +} + +func (_ SorobanCredentials) XdrValidTags() map[int32]bool { + return _XdrTags_SorobanCredentials +} +func (u *SorobanCredentials) Address() *SorobanAddressCredentials { switch u.Type { - case LIQUIDITY_POOL_WITHDRAW: - if v, ok := u._u.(*LiquidityPoolWithdrawOp); ok { + case SOROBAN_CREDENTIALS_ADDRESS: + if v, ok := u._u.(*SorobanAddressCredentials); ok { return v } else { - var zero LiquidityPoolWithdrawOp + var zero SorobanAddressCredentials u._u = &zero return &zero } default: - XdrPanic("XdrAnon_Operation_Body.LiquidityPoolWithdrawOp accessed when Type == %v", u.Type) + XdrPanic("SorobanCredentials.Address accessed when Type == %v", u.Type) return nil } } -func (u XdrAnon_Operation_Body) XdrValid() bool { +func (u SorobanCredentials) XdrValid() bool { switch u.Type { - case CREATE_ACCOUNT, PAYMENT, PATH_PAYMENT_STRICT_RECEIVE, MANAGE_SELL_OFFER, CREATE_PASSIVE_SELL_OFFER, SET_OPTIONS, CHANGE_TRUST, ALLOW_TRUST, ACCOUNT_MERGE, INFLATION, MANAGE_DATA, BUMP_SEQUENCE, MANAGE_BUY_OFFER, PATH_PAYMENT_STRICT_SEND, CREATE_CLAIMABLE_BALANCE, CLAIM_CLAIMABLE_BALANCE, BEGIN_SPONSORING_FUTURE_RESERVES, END_SPONSORING_FUTURE_RESERVES, REVOKE_SPONSORSHIP, CLAWBACK, CLAWBACK_CLAIMABLE_BALANCE, SET_TRUST_LINE_FLAGS, LIQUIDITY_POOL_DEPOSIT, LIQUIDITY_POOL_WITHDRAW: + case SOROBAN_CREDENTIALS_SOURCE_ACCOUNT, SOROBAN_CREDENTIALS_ADDRESS: return true } return false } -func (u *XdrAnon_Operation_Body) XdrUnionTag() XdrNum32 { - return XDR_OperationType(&u.Type) +func (u *SorobanCredentials) XdrUnionTag() XdrNum32 { + return XDR_SorobanCredentialsType(&u.Type) } -func (u *XdrAnon_Operation_Body) XdrUnionTagName() string { +func (u *SorobanCredentials) XdrUnionTagName() string { return "Type" } -func (u *XdrAnon_Operation_Body) XdrUnionBody() XdrType { +func (u *SorobanCredentials) XdrUnionBody() XdrType { switch u.Type { - case CREATE_ACCOUNT: - return XDR_CreateAccountOp(u.CreateAccountOp()) - case PAYMENT: - return XDR_PaymentOp(u.PaymentOp()) - case PATH_PAYMENT_STRICT_RECEIVE: - return XDR_PathPaymentStrictReceiveOp(u.PathPaymentStrictReceiveOp()) - case MANAGE_SELL_OFFER: - return XDR_ManageSellOfferOp(u.ManageSellOfferOp()) - case CREATE_PASSIVE_SELL_OFFER: - return XDR_CreatePassiveSellOfferOp(u.CreatePassiveSellOfferOp()) - case SET_OPTIONS: - return XDR_SetOptionsOp(u.SetOptionsOp()) - case CHANGE_TRUST: - return XDR_ChangeTrustOp(u.ChangeTrustOp()) - case ALLOW_TRUST: - return XDR_AllowTrustOp(u.AllowTrustOp()) - case ACCOUNT_MERGE: - return XDR_MuxedAccount(u.Destination()) - case INFLATION: - return nil - case MANAGE_DATA: - return XDR_ManageDataOp(u.ManageDataOp()) - case BUMP_SEQUENCE: - return XDR_BumpSequenceOp(u.BumpSequenceOp()) - case MANAGE_BUY_OFFER: - return XDR_ManageBuyOfferOp(u.ManageBuyOfferOp()) - case PATH_PAYMENT_STRICT_SEND: - return XDR_PathPaymentStrictSendOp(u.PathPaymentStrictSendOp()) - case CREATE_CLAIMABLE_BALANCE: - return XDR_CreateClaimableBalanceOp(u.CreateClaimableBalanceOp()) - case CLAIM_CLAIMABLE_BALANCE: - return XDR_ClaimClaimableBalanceOp(u.ClaimClaimableBalanceOp()) - case BEGIN_SPONSORING_FUTURE_RESERVES: - return XDR_BeginSponsoringFutureReservesOp(u.BeginSponsoringFutureReservesOp()) - case END_SPONSORING_FUTURE_RESERVES: + case SOROBAN_CREDENTIALS_SOURCE_ACCOUNT: return nil - case REVOKE_SPONSORSHIP: - return XDR_RevokeSponsorshipOp(u.RevokeSponsorshipOp()) - case CLAWBACK: - return XDR_ClawbackOp(u.ClawbackOp()) - case CLAWBACK_CLAIMABLE_BALANCE: - return XDR_ClawbackClaimableBalanceOp(u.ClawbackClaimableBalanceOp()) - case SET_TRUST_LINE_FLAGS: - return XDR_SetTrustLineFlagsOp(u.SetTrustLineFlagsOp()) - case LIQUIDITY_POOL_DEPOSIT: - return XDR_LiquidityPoolDepositOp(u.LiquidityPoolDepositOp()) - case LIQUIDITY_POOL_WITHDRAW: - return XDR_LiquidityPoolWithdrawOp(u.LiquidityPoolWithdrawOp()) + case SOROBAN_CREDENTIALS_ADDRESS: + return XDR_SorobanAddressCredentials(u.Address()) } return nil } -func (u *XdrAnon_Operation_Body) XdrUnionBodyName() string { +func (u *SorobanCredentials) XdrUnionBodyName() string { switch u.Type { - case CREATE_ACCOUNT: - return "CreateAccountOp" - case PAYMENT: - return "PaymentOp" - case PATH_PAYMENT_STRICT_RECEIVE: - return "PathPaymentStrictReceiveOp" - case MANAGE_SELL_OFFER: - return "ManageSellOfferOp" - case CREATE_PASSIVE_SELL_OFFER: - return "CreatePassiveSellOfferOp" - case SET_OPTIONS: - return "SetOptionsOp" - case CHANGE_TRUST: - return "ChangeTrustOp" - case ALLOW_TRUST: - return "AllowTrustOp" - case ACCOUNT_MERGE: - return "Destination" - case INFLATION: - return "" - case MANAGE_DATA: - return "ManageDataOp" - case BUMP_SEQUENCE: - return "BumpSequenceOp" - case MANAGE_BUY_OFFER: - return "ManageBuyOfferOp" - case PATH_PAYMENT_STRICT_SEND: - return "PathPaymentStrictSendOp" - case CREATE_CLAIMABLE_BALANCE: - return "CreateClaimableBalanceOp" - case CLAIM_CLAIMABLE_BALANCE: - return "ClaimClaimableBalanceOp" - case BEGIN_SPONSORING_FUTURE_RESERVES: - return "BeginSponsoringFutureReservesOp" - case END_SPONSORING_FUTURE_RESERVES: + case SOROBAN_CREDENTIALS_SOURCE_ACCOUNT: return "" - case REVOKE_SPONSORSHIP: - return "RevokeSponsorshipOp" - case CLAWBACK: - return "ClawbackOp" - case CLAWBACK_CLAIMABLE_BALANCE: - return "ClawbackClaimableBalanceOp" - case SET_TRUST_LINE_FLAGS: - return "SetTrustLineFlagsOp" - case LIQUIDITY_POOL_DEPOSIT: - return "LiquidityPoolDepositOp" - case LIQUIDITY_POOL_WITHDRAW: - return "LiquidityPoolWithdrawOp" + case SOROBAN_CREDENTIALS_ADDRESS: + return "Address" } return "" } -type XdrType_XdrAnon_Operation_Body = *XdrAnon_Operation_Body +type XdrType_SorobanCredentials = *SorobanCredentials -func (v *XdrAnon_Operation_Body) XdrPointer() interface{} { return v } -func (XdrAnon_Operation_Body) XdrTypeName() string { return "XdrAnon_Operation_Body" } -func (v XdrAnon_Operation_Body) XdrValue() interface{} { return v } -func (v *XdrAnon_Operation_Body) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -func (u *XdrAnon_Operation_Body) XdrRecurse(x XDR, name string) { +func (v *SorobanCredentials) XdrPointer() interface{} { return v } +func (SorobanCredentials) XdrTypeName() string { return "SorobanCredentials" } +func (v SorobanCredentials) XdrValue() interface{} { return v } +func (v *SorobanCredentials) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (u *SorobanCredentials) XdrRecurse(x XDR, name string) { if name != "" { name = x.Sprintf("%s.", name) } - XDR_OperationType(&u.Type).XdrMarshal(x, x.Sprintf("%stype", name)) + XDR_SorobanCredentialsType(&u.Type).XdrMarshal(x, x.Sprintf("%stype", name)) switch u.Type { - case CREATE_ACCOUNT: - x.Marshal(x.Sprintf("%screateAccountOp", name), XDR_CreateAccountOp(u.CreateAccountOp())) - return - case PAYMENT: - x.Marshal(x.Sprintf("%spaymentOp", name), XDR_PaymentOp(u.PaymentOp())) - return - case PATH_PAYMENT_STRICT_RECEIVE: - x.Marshal(x.Sprintf("%spathPaymentStrictReceiveOp", name), XDR_PathPaymentStrictReceiveOp(u.PathPaymentStrictReceiveOp())) - return - case MANAGE_SELL_OFFER: - x.Marshal(x.Sprintf("%smanageSellOfferOp", name), XDR_ManageSellOfferOp(u.ManageSellOfferOp())) - return - case CREATE_PASSIVE_SELL_OFFER: - x.Marshal(x.Sprintf("%screatePassiveSellOfferOp", name), XDR_CreatePassiveSellOfferOp(u.CreatePassiveSellOfferOp())) - return - case SET_OPTIONS: - x.Marshal(x.Sprintf("%ssetOptionsOp", name), XDR_SetOptionsOp(u.SetOptionsOp())) - return - case CHANGE_TRUST: - x.Marshal(x.Sprintf("%schangeTrustOp", name), XDR_ChangeTrustOp(u.ChangeTrustOp())) - return - case ALLOW_TRUST: - x.Marshal(x.Sprintf("%sallowTrustOp", name), XDR_AllowTrustOp(u.AllowTrustOp())) - return - case ACCOUNT_MERGE: - x.Marshal(x.Sprintf("%sdestination", name), XDR_MuxedAccount(u.Destination())) - return - case INFLATION: - return - case MANAGE_DATA: - x.Marshal(x.Sprintf("%smanageDataOp", name), XDR_ManageDataOp(u.ManageDataOp())) - return - case BUMP_SEQUENCE: - x.Marshal(x.Sprintf("%sbumpSequenceOp", name), XDR_BumpSequenceOp(u.BumpSequenceOp())) - return - case MANAGE_BUY_OFFER: - x.Marshal(x.Sprintf("%smanageBuyOfferOp", name), XDR_ManageBuyOfferOp(u.ManageBuyOfferOp())) - return - case PATH_PAYMENT_STRICT_SEND: - x.Marshal(x.Sprintf("%spathPaymentStrictSendOp", name), XDR_PathPaymentStrictSendOp(u.PathPaymentStrictSendOp())) - return - case CREATE_CLAIMABLE_BALANCE: - x.Marshal(x.Sprintf("%screateClaimableBalanceOp", name), XDR_CreateClaimableBalanceOp(u.CreateClaimableBalanceOp())) - return - case CLAIM_CLAIMABLE_BALANCE: - x.Marshal(x.Sprintf("%sclaimClaimableBalanceOp", name), XDR_ClaimClaimableBalanceOp(u.ClaimClaimableBalanceOp())) - return - case BEGIN_SPONSORING_FUTURE_RESERVES: - x.Marshal(x.Sprintf("%sbeginSponsoringFutureReservesOp", name), XDR_BeginSponsoringFutureReservesOp(u.BeginSponsoringFutureReservesOp())) - return - case END_SPONSORING_FUTURE_RESERVES: - return - case REVOKE_SPONSORSHIP: - x.Marshal(x.Sprintf("%srevokeSponsorshipOp", name), XDR_RevokeSponsorshipOp(u.RevokeSponsorshipOp())) - return - case CLAWBACK: - x.Marshal(x.Sprintf("%sclawbackOp", name), XDR_ClawbackOp(u.ClawbackOp())) - return - case CLAWBACK_CLAIMABLE_BALANCE: - x.Marshal(x.Sprintf("%sclawbackClaimableBalanceOp", name), XDR_ClawbackClaimableBalanceOp(u.ClawbackClaimableBalanceOp())) - return - case SET_TRUST_LINE_FLAGS: - x.Marshal(x.Sprintf("%ssetTrustLineFlagsOp", name), XDR_SetTrustLineFlagsOp(u.SetTrustLineFlagsOp())) - return - case LIQUIDITY_POOL_DEPOSIT: - x.Marshal(x.Sprintf("%sliquidityPoolDepositOp", name), XDR_LiquidityPoolDepositOp(u.LiquidityPoolDepositOp())) + case SOROBAN_CREDENTIALS_SOURCE_ACCOUNT: return - case LIQUIDITY_POOL_WITHDRAW: - x.Marshal(x.Sprintf("%sliquidityPoolWithdrawOp", name), XDR_LiquidityPoolWithdrawOp(u.LiquidityPoolWithdrawOp())) + case SOROBAN_CREDENTIALS_ADDRESS: + x.Marshal(x.Sprintf("%saddress", name), XDR_SorobanAddressCredentials(u.Address())) return } - XdrPanic("invalid Type (%v) in XdrAnon_Operation_Body", u.Type) + XdrPanic("invalid Type (%v) in SorobanCredentials", u.Type) } -func XDR_XdrAnon_Operation_Body(v *XdrAnon_Operation_Body) *XdrAnon_Operation_Body { return v } +func XDR_SorobanCredentials(v *SorobanCredentials) *SorobanCredentials { return v } -type _XdrPtr_MuxedAccount struct { - p **MuxedAccount -} -type _ptrflag_MuxedAccount _XdrPtr_MuxedAccount +type XdrType_SorobanAuthorizationEntry = *SorobanAuthorizationEntry -func (v _ptrflag_MuxedAccount) String() string { - if *v.p == nil { - return "nil" +func (v *SorobanAuthorizationEntry) XdrPointer() interface{} { return v } +func (SorobanAuthorizationEntry) XdrTypeName() string { return "SorobanAuthorizationEntry" } +func (v SorobanAuthorizationEntry) XdrValue() interface{} { return v } +func (v *SorobanAuthorizationEntry) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v *SorobanAuthorizationEntry) XdrRecurse(x XDR, name string) { + if name != "" { + name = x.Sprintf("%s.", name) } - return "non-nil" + x.Marshal(x.Sprintf("%scredentials", name), XDR_SorobanCredentials(&v.Credentials)) + x.Marshal(x.Sprintf("%srootInvocation", name), XDR_SorobanAuthorizedInvocation(&v.RootInvocation)) } -func (v _ptrflag_MuxedAccount) Scan(ss fmt.ScanState, r rune) error { - tok, err := ss.Token(true, func(c rune) bool { - return c == '-' || (c >= 'a' && c <= 'z') - }) - if err != nil { - return err - } - switch string(tok) { - case "nil": - v.SetU32(0) - case "non-nil": - v.SetU32(1) - default: - return XdrError("MuxedAccount flag should be \"nil\" or \"non-nil\"") - } - return nil +func XDR_SorobanAuthorizationEntry(v *SorobanAuthorizationEntry) *SorobanAuthorizationEntry { return v } + +type _XdrVec_unbounded_SorobanAuthorizationEntry []SorobanAuthorizationEntry + +func (_XdrVec_unbounded_SorobanAuthorizationEntry) XdrBound() uint32 { + const bound uint32 = 4294967295 // Force error if not const or doesn't fit + return bound } -func (v _ptrflag_MuxedAccount) GetU32() uint32 { - if *v.p == nil { - return 0 +func (_XdrVec_unbounded_SorobanAuthorizationEntry) XdrCheckLen(length uint32) { + if length > uint32(4294967295) { + XdrPanic("_XdrVec_unbounded_SorobanAuthorizationEntry length %d exceeds bound 4294967295", length) + } else if int(length) < 0 { + XdrPanic("_XdrVec_unbounded_SorobanAuthorizationEntry length %d exceeds max int", length) } - return 1 } -func (v _ptrflag_MuxedAccount) SetU32(nv uint32) { - switch nv { - case 0: - *v.p = nil - case 1: - if *v.p == nil { - *v.p = new(MuxedAccount) +func (v _XdrVec_unbounded_SorobanAuthorizationEntry) GetVecLen() uint32 { return uint32(len(v)) } +func (v *_XdrVec_unbounded_SorobanAuthorizationEntry) SetVecLen(length uint32) { + v.XdrCheckLen(length) + if int(length) <= cap(*v) { + if int(length) != len(*v) { + *v = (*v)[:int(length)] } - default: - XdrPanic("*MuxedAccount present flag value %d should be 0 or 1", nv) + return } -} -func (_ptrflag_MuxedAccount) XdrTypeName() string { return "MuxedAccount?" } -func (v _ptrflag_MuxedAccount) XdrPointer() interface{} { return nil } -func (v _ptrflag_MuxedAccount) XdrValue() interface{} { return v.GetU32() != 0 } -func (v _ptrflag_MuxedAccount) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -func (v _ptrflag_MuxedAccount) XdrBound() uint32 { return 1 } -func (v _XdrPtr_MuxedAccount) GetPresent() bool { return *v.p != nil } -func (v _XdrPtr_MuxedAccount) SetPresent(present bool) { - if !present { - *v.p = nil - } else if *v.p == nil { - *v.p = new(MuxedAccount) + newcap := 2 * cap(*v) + if newcap < int(length) { // also catches overflow where 2*cap < 0 + newcap = int(length) + } else if bound := uint(4294967295); uint(newcap) > bound { + if int(bound) < 0 { + bound = ^uint(0) >> 1 + } + newcap = int(bound) } + nv := make([]SorobanAuthorizationEntry, int(length), newcap) + copy(nv, *v) + *v = nv } -func (v _XdrPtr_MuxedAccount) XdrMarshalValue(x XDR, name string) { - if *v.p != nil { - XDR_MuxedAccount(*v.p).XdrMarshal(x, name) +func (v *_XdrVec_unbounded_SorobanAuthorizationEntry) XdrMarshalN(x XDR, name string, n uint32) { + v.XdrCheckLen(n) + for i := 0; i < int(n); i++ { + if i >= len(*v) { + v.SetVecLen(uint32(i + 1)) + } + XDR_SorobanAuthorizationEntry(&(*v)[i]).XdrMarshal(x, x.Sprintf("%s[%d]", name, i)) + } + if int(n) < len(*v) { + *v = (*v)[:int(n)] } } -func (v _XdrPtr_MuxedAccount) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -func (v _XdrPtr_MuxedAccount) XdrRecurse(x XDR, name string) { - x.Marshal(name, _ptrflag_MuxedAccount(v)) - v.XdrMarshalValue(x, name) +func (v *_XdrVec_unbounded_SorobanAuthorizationEntry) XdrRecurse(x XDR, name string) { + size := XdrSize{Size: uint32(len(*v)), Bound: 4294967295} + x.Marshal(name, &size) + v.XdrMarshalN(x, name, size.Size) +} +func (_XdrVec_unbounded_SorobanAuthorizationEntry) XdrTypeName() string { + return "SorobanAuthorizationEntry<>" +} +func (v *_XdrVec_unbounded_SorobanAuthorizationEntry) XdrPointer() interface{} { + return (*[]SorobanAuthorizationEntry)(v) +} +func (v _XdrVec_unbounded_SorobanAuthorizationEntry) XdrValue() interface{} { + return ([]SorobanAuthorizationEntry)(v) +} +func (v *_XdrVec_unbounded_SorobanAuthorizationEntry) XdrMarshal(x XDR, name string) { + x.Marshal(name, v) } -func (_XdrPtr_MuxedAccount) XdrTypeName() string { return "MuxedAccount*" } -func (v _XdrPtr_MuxedAccount) XdrPointer() interface{} { return v.p } -func (v _XdrPtr_MuxedAccount) XdrValue() interface{} { return *v.p } -type XdrType_Operation = *Operation +type XdrType_InvokeHostFunctionOp = *InvokeHostFunctionOp -func (v *Operation) XdrPointer() interface{} { return v } -func (Operation) XdrTypeName() string { return "Operation" } -func (v Operation) XdrValue() interface{} { return v } -func (v *Operation) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -func (v *Operation) XdrRecurse(x XDR, name string) { +func (v *InvokeHostFunctionOp) XdrPointer() interface{} { return v } +func (InvokeHostFunctionOp) XdrTypeName() string { return "InvokeHostFunctionOp" } +func (v InvokeHostFunctionOp) XdrValue() interface{} { return v } +func (v *InvokeHostFunctionOp) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v *InvokeHostFunctionOp) XdrRecurse(x XDR, name string) { if name != "" { name = x.Sprintf("%s.", name) } - x.Marshal(x.Sprintf("%ssourceAccount", name), _XdrPtr_MuxedAccount{&v.SourceAccount}) - x.Marshal(x.Sprintf("%sbody", name), XDR_XdrAnon_Operation_Body(&v.Body)) + x.Marshal(x.Sprintf("%shostFunction", name), XDR_HostFunction(&v.HostFunction)) + x.Marshal(x.Sprintf("%sauth", name), (*_XdrVec_unbounded_SorobanAuthorizationEntry)(&v.Auth)) } -func XDR_Operation(v *Operation) *Operation { return v } +func XDR_InvokeHostFunctionOp(v *InvokeHostFunctionOp) *InvokeHostFunctionOp { return v } -type XdrType_XdrAnon_HashIDPreimage_OperationID = *XdrAnon_HashIDPreimage_OperationID +type XdrType_ExtendFootprintTTLOp = *ExtendFootprintTTLOp -func (v *XdrAnon_HashIDPreimage_OperationID) XdrPointer() interface{} { return v } -func (XdrAnon_HashIDPreimage_OperationID) XdrTypeName() string { - return "XdrAnon_HashIDPreimage_OperationID" -} -func (v XdrAnon_HashIDPreimage_OperationID) XdrValue() interface{} { return v } -func (v *XdrAnon_HashIDPreimage_OperationID) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -func (v *XdrAnon_HashIDPreimage_OperationID) XdrRecurse(x XDR, name string) { +func (v *ExtendFootprintTTLOp) XdrPointer() interface{} { return v } +func (ExtendFootprintTTLOp) XdrTypeName() string { return "ExtendFootprintTTLOp" } +func (v ExtendFootprintTTLOp) XdrValue() interface{} { return v } +func (v *ExtendFootprintTTLOp) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v *ExtendFootprintTTLOp) XdrRecurse(x XDR, name string) { if name != "" { name = x.Sprintf("%s.", name) } - x.Marshal(x.Sprintf("%ssourceAccount", name), XDR_AccountID(&v.SourceAccount)) - x.Marshal(x.Sprintf("%sseqNum", name), XDR_SequenceNumber(&v.SeqNum)) - x.Marshal(x.Sprintf("%sopNum", name), XDR_Uint32(&v.OpNum)) -} -func XDR_XdrAnon_HashIDPreimage_OperationID(v *XdrAnon_HashIDPreimage_OperationID) *XdrAnon_HashIDPreimage_OperationID { - return v + x.Marshal(x.Sprintf("%sext", name), XDR_ExtensionPoint(&v.Ext)) + x.Marshal(x.Sprintf("%sextendTo", name), XDR_Uint32(&v.ExtendTo)) } +func XDR_ExtendFootprintTTLOp(v *ExtendFootprintTTLOp) *ExtendFootprintTTLOp { return v } -type XdrType_XdrAnon_HashIDPreimage_RevokeID = *XdrAnon_HashIDPreimage_RevokeID +type XdrType_RestoreFootprintOp = *RestoreFootprintOp -func (v *XdrAnon_HashIDPreimage_RevokeID) XdrPointer() interface{} { return v } -func (XdrAnon_HashIDPreimage_RevokeID) XdrTypeName() string { return "XdrAnon_HashIDPreimage_RevokeID" } -func (v XdrAnon_HashIDPreimage_RevokeID) XdrValue() interface{} { return v } -func (v *XdrAnon_HashIDPreimage_RevokeID) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -func (v *XdrAnon_HashIDPreimage_RevokeID) XdrRecurse(x XDR, name string) { +func (v *RestoreFootprintOp) XdrPointer() interface{} { return v } +func (RestoreFootprintOp) XdrTypeName() string { return "RestoreFootprintOp" } +func (v RestoreFootprintOp) XdrValue() interface{} { return v } +func (v *RestoreFootprintOp) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v *RestoreFootprintOp) XdrRecurse(x XDR, name string) { if name != "" { name = x.Sprintf("%s.", name) } - x.Marshal(x.Sprintf("%ssourceAccount", name), XDR_AccountID(&v.SourceAccount)) - x.Marshal(x.Sprintf("%sseqNum", name), XDR_SequenceNumber(&v.SeqNum)) - x.Marshal(x.Sprintf("%sopNum", name), XDR_Uint32(&v.OpNum)) - x.Marshal(x.Sprintf("%sliquidityPoolID", name), XDR_PoolID(&v.LiquidityPoolID)) - x.Marshal(x.Sprintf("%sasset", name), XDR_Asset(&v.Asset)) -} -func XDR_XdrAnon_HashIDPreimage_RevokeID(v *XdrAnon_HashIDPreimage_RevokeID) *XdrAnon_HashIDPreimage_RevokeID { - return v + x.Marshal(x.Sprintf("%sext", name), XDR_ExtensionPoint(&v.Ext)) } +func XDR_RestoreFootprintOp(v *RestoreFootprintOp) *RestoreFootprintOp { return v } -var _XdrTags_HashIDPreimage = map[int32]bool{ - XdrToI32(ENVELOPE_TYPE_OP_ID): true, - XdrToI32(ENVELOPE_TYPE_POOL_REVOKE_OP_ID): true, +var _XdrTags_XdrAnon_Operation_Body = map[int32]bool{ + XdrToI32(CREATE_ACCOUNT): true, + XdrToI32(PAYMENT): true, + XdrToI32(PATH_PAYMENT_STRICT_RECEIVE): true, + XdrToI32(MANAGE_SELL_OFFER): true, + XdrToI32(CREATE_PASSIVE_SELL_OFFER): true, + XdrToI32(SET_OPTIONS): true, + XdrToI32(CHANGE_TRUST): true, + XdrToI32(ALLOW_TRUST): true, + XdrToI32(ACCOUNT_MERGE): true, + XdrToI32(INFLATION): true, + XdrToI32(MANAGE_DATA): true, + XdrToI32(BUMP_SEQUENCE): true, + XdrToI32(MANAGE_BUY_OFFER): true, + XdrToI32(PATH_PAYMENT_STRICT_SEND): true, + XdrToI32(CREATE_CLAIMABLE_BALANCE): true, + XdrToI32(CLAIM_CLAIMABLE_BALANCE): true, + XdrToI32(BEGIN_SPONSORING_FUTURE_RESERVES): true, + XdrToI32(END_SPONSORING_FUTURE_RESERVES): true, + XdrToI32(REVOKE_SPONSORSHIP): true, + XdrToI32(CLAWBACK): true, + XdrToI32(CLAWBACK_CLAIMABLE_BALANCE): true, + XdrToI32(SET_TRUST_LINE_FLAGS): true, + XdrToI32(LIQUIDITY_POOL_DEPOSIT): true, + XdrToI32(LIQUIDITY_POOL_WITHDRAW): true, + XdrToI32(INVOKE_HOST_FUNCTION): true, + XdrToI32(EXTEND_FOOTPRINT_TTL): true, + XdrToI32(RESTORE_FOOTPRINT): true, } -func (_ HashIDPreimage) XdrValidTags() map[int32]bool { - return _XdrTags_HashIDPreimage +func (_ XdrAnon_Operation_Body) XdrValidTags() map[int32]bool { + return _XdrTags_XdrAnon_Operation_Body } -func (u *HashIDPreimage) OperationID() *XdrAnon_HashIDPreimage_OperationID { +func (u *XdrAnon_Operation_Body) CreateAccountOp() *CreateAccountOp { switch u.Type { - case ENVELOPE_TYPE_OP_ID: - if v, ok := u._u.(*XdrAnon_HashIDPreimage_OperationID); ok { - return v + case CREATE_ACCOUNT: + if v, ok := u._u.(*CreateAccountOp); ok { + return v } else { - var zero XdrAnon_HashIDPreimage_OperationID + var zero CreateAccountOp u._u = &zero return &zero } default: - XdrPanic("HashIDPreimage.OperationID accessed when Type == %v", u.Type) + XdrPanic("XdrAnon_Operation_Body.CreateAccountOp accessed when Type == %v", u.Type) return nil } } -func (u *HashIDPreimage) RevokeID() *XdrAnon_HashIDPreimage_RevokeID { +func (u *XdrAnon_Operation_Body) PaymentOp() *PaymentOp { switch u.Type { - case ENVELOPE_TYPE_POOL_REVOKE_OP_ID: - if v, ok := u._u.(*XdrAnon_HashIDPreimage_RevokeID); ok { + case PAYMENT: + if v, ok := u._u.(*PaymentOp); ok { return v } else { - var zero XdrAnon_HashIDPreimage_RevokeID + var zero PaymentOp u._u = &zero return &zero } default: - XdrPanic("HashIDPreimage.RevokeID accessed when Type == %v", u.Type) + XdrPanic("XdrAnon_Operation_Body.PaymentOp accessed when Type == %v", u.Type) return nil } } -func (u HashIDPreimage) XdrValid() bool { +func (u *XdrAnon_Operation_Body) PathPaymentStrictReceiveOp() *PathPaymentStrictReceiveOp { switch u.Type { - case ENVELOPE_TYPE_OP_ID, ENVELOPE_TYPE_POOL_REVOKE_OP_ID: - return true + case PATH_PAYMENT_STRICT_RECEIVE: + if v, ok := u._u.(*PathPaymentStrictReceiveOp); ok { + return v + } else { + var zero PathPaymentStrictReceiveOp + u._u = &zero + return &zero + } + default: + XdrPanic("XdrAnon_Operation_Body.PathPaymentStrictReceiveOp accessed when Type == %v", u.Type) + return nil } - return false } -func (u *HashIDPreimage) XdrUnionTag() XdrNum32 { - return XDR_EnvelopeType(&u.Type) -} -func (u *HashIDPreimage) XdrUnionTagName() string { - return "Type" -} -func (u *HashIDPreimage) XdrUnionBody() XdrType { +func (u *XdrAnon_Operation_Body) ManageSellOfferOp() *ManageSellOfferOp { switch u.Type { - case ENVELOPE_TYPE_OP_ID: - return XDR_XdrAnon_HashIDPreimage_OperationID(u.OperationID()) - case ENVELOPE_TYPE_POOL_REVOKE_OP_ID: - return XDR_XdrAnon_HashIDPreimage_RevokeID(u.RevokeID()) + case MANAGE_SELL_OFFER: + if v, ok := u._u.(*ManageSellOfferOp); ok { + return v + } else { + var zero ManageSellOfferOp + u._u = &zero + return &zero + } + default: + XdrPanic("XdrAnon_Operation_Body.ManageSellOfferOp accessed when Type == %v", u.Type) + return nil } - return nil } -func (u *HashIDPreimage) XdrUnionBodyName() string { +func (u *XdrAnon_Operation_Body) CreatePassiveSellOfferOp() *CreatePassiveSellOfferOp { switch u.Type { - case ENVELOPE_TYPE_OP_ID: - return "OperationID" - case ENVELOPE_TYPE_POOL_REVOKE_OP_ID: - return "RevokeID" + case CREATE_PASSIVE_SELL_OFFER: + if v, ok := u._u.(*CreatePassiveSellOfferOp); ok { + return v + } else { + var zero CreatePassiveSellOfferOp + u._u = &zero + return &zero + } + default: + XdrPanic("XdrAnon_Operation_Body.CreatePassiveSellOfferOp accessed when Type == %v", u.Type) + return nil } - return "" } - -type XdrType_HashIDPreimage = *HashIDPreimage - -func (v *HashIDPreimage) XdrPointer() interface{} { return v } -func (HashIDPreimage) XdrTypeName() string { return "HashIDPreimage" } -func (v HashIDPreimage) XdrValue() interface{} { return v } -func (v *HashIDPreimage) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -func (u *HashIDPreimage) XdrRecurse(x XDR, name string) { - if name != "" { - name = x.Sprintf("%s.", name) - } - XDR_EnvelopeType(&u.Type).XdrMarshal(x, x.Sprintf("%stype", name)) +func (u *XdrAnon_Operation_Body) SetOptionsOp() *SetOptionsOp { switch u.Type { - case ENVELOPE_TYPE_OP_ID: - x.Marshal(x.Sprintf("%soperationID", name), XDR_XdrAnon_HashIDPreimage_OperationID(u.OperationID())) - return - case ENVELOPE_TYPE_POOL_REVOKE_OP_ID: - x.Marshal(x.Sprintf("%srevokeID", name), XDR_XdrAnon_HashIDPreimage_RevokeID(u.RevokeID())) - return - } - XdrPanic("invalid Type (%v) in HashIDPreimage", u.Type) -} -func (v *HashIDPreimage) XdrInitialize() { - var zero EnvelopeType - switch zero { - case ENVELOPE_TYPE_OP_ID, ENVELOPE_TYPE_POOL_REVOKE_OP_ID: - default: - if v.Type == zero { - v.Type = ENVELOPE_TYPE_OP_ID + case SET_OPTIONS: + if v, ok := u._u.(*SetOptionsOp); ok { + return v + } else { + var zero SetOptionsOp + u._u = &zero + return &zero } + default: + XdrPanic("XdrAnon_Operation_Body.SetOptionsOp accessed when Type == %v", u.Type) + return nil } } -func XDR_HashIDPreimage(v *HashIDPreimage) *HashIDPreimage { return v } - -var _XdrNames_MemoType = map[int32]string{ - int32(MEMO_NONE): "MEMO_NONE", - int32(MEMO_TEXT): "MEMO_TEXT", - int32(MEMO_ID): "MEMO_ID", - int32(MEMO_HASH): "MEMO_HASH", - int32(MEMO_RETURN): "MEMO_RETURN", -} -var _XdrValues_MemoType = map[string]int32{ - "MEMO_NONE": int32(MEMO_NONE), - "MEMO_TEXT": int32(MEMO_TEXT), - "MEMO_ID": int32(MEMO_ID), - "MEMO_HASH": int32(MEMO_HASH), - "MEMO_RETURN": int32(MEMO_RETURN), -} - -func (MemoType) XdrEnumNames() map[int32]string { - return _XdrNames_MemoType -} -func (v MemoType) String() string { - if s, ok := _XdrNames_MemoType[int32(v)]; ok { - return s +func (u *XdrAnon_Operation_Body) ChangeTrustOp() *ChangeTrustOp { + switch u.Type { + case CHANGE_TRUST: + if v, ok := u._u.(*ChangeTrustOp); ok { + return v + } else { + var zero ChangeTrustOp + u._u = &zero + return &zero + } + default: + XdrPanic("XdrAnon_Operation_Body.ChangeTrustOp accessed when Type == %v", u.Type) + return nil } - return fmt.Sprintf("MemoType#%d", v) } -func (v *MemoType) Scan(ss fmt.ScanState, _ rune) error { - if tok, err := ss.Token(true, XdrSymChar); err != nil { - return err - } else { - stok := string(tok) - if val, ok := _XdrValues_MemoType[stok]; ok { - *v = MemoType(val) - return nil - } else if stok == "MemoType" { - if n, err := fmt.Fscanf(ss, "#%d", (*int32)(v)); n == 1 && err == nil { - return nil - } +func (u *XdrAnon_Operation_Body) AllowTrustOp() *AllowTrustOp { + switch u.Type { + case ALLOW_TRUST: + if v, ok := u._u.(*AllowTrustOp); ok { + return v + } else { + var zero AllowTrustOp + u._u = &zero + return &zero } - return XdrError(fmt.Sprintf("%s is not a valid MemoType.", stok)) + default: + XdrPanic("XdrAnon_Operation_Body.AllowTrustOp accessed when Type == %v", u.Type) + return nil } } -func (v MemoType) GetU32() uint32 { return uint32(v) } -func (v *MemoType) SetU32(n uint32) { *v = MemoType(n) } -func (v *MemoType) XdrPointer() interface{} { return v } -func (MemoType) XdrTypeName() string { return "MemoType" } -func (v MemoType) XdrValue() interface{} { return v } -func (v *MemoType) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } - -type XdrType_MemoType = *MemoType - -func XDR_MemoType(v *MemoType) *MemoType { return v } - -var _XdrTags_Memo = map[int32]bool{ - XdrToI32(MEMO_NONE): true, - XdrToI32(MEMO_TEXT): true, - XdrToI32(MEMO_ID): true, - XdrToI32(MEMO_HASH): true, - XdrToI32(MEMO_RETURN): true, -} - -func (_ Memo) XdrValidTags() map[int32]bool { - return _XdrTags_Memo -} -func (u *Memo) Text() *string { +func (u *XdrAnon_Operation_Body) Destination() *MuxedAccount { switch u.Type { - case MEMO_TEXT: - if v, ok := u._u.(*string); ok { + case ACCOUNT_MERGE: + if v, ok := u._u.(*MuxedAccount); ok { return v } else { - var zero string + var zero MuxedAccount u._u = &zero return &zero } default: - XdrPanic("Memo.Text accessed when Type == %v", u.Type) + XdrPanic("XdrAnon_Operation_Body.Destination accessed when Type == %v", u.Type) return nil } } -func (u *Memo) Id() *Uint64 { +func (u *XdrAnon_Operation_Body) ManageDataOp() *ManageDataOp { switch u.Type { - case MEMO_ID: - if v, ok := u._u.(*Uint64); ok { + case MANAGE_DATA: + if v, ok := u._u.(*ManageDataOp); ok { return v } else { - var zero Uint64 + var zero ManageDataOp u._u = &zero return &zero } default: - XdrPanic("Memo.Id accessed when Type == %v", u.Type) + XdrPanic("XdrAnon_Operation_Body.ManageDataOp accessed when Type == %v", u.Type) return nil } } - -// the hash of what to pull from the content server -func (u *Memo) Hash() *Hash { +func (u *XdrAnon_Operation_Body) BumpSequenceOp() *BumpSequenceOp { switch u.Type { - case MEMO_HASH: - if v, ok := u._u.(*Hash); ok { + case BUMP_SEQUENCE: + if v, ok := u._u.(*BumpSequenceOp); ok { return v } else { - var zero Hash + var zero BumpSequenceOp u._u = &zero return &zero } default: - XdrPanic("Memo.Hash accessed when Type == %v", u.Type) + XdrPanic("XdrAnon_Operation_Body.BumpSequenceOp accessed when Type == %v", u.Type) return nil } } - -// the hash of the tx you are rejecting -func (u *Memo) RetHash() *Hash { +func (u *XdrAnon_Operation_Body) ManageBuyOfferOp() *ManageBuyOfferOp { switch u.Type { - case MEMO_RETURN: - if v, ok := u._u.(*Hash); ok { + case MANAGE_BUY_OFFER: + if v, ok := u._u.(*ManageBuyOfferOp); ok { return v } else { - var zero Hash + var zero ManageBuyOfferOp u._u = &zero return &zero } default: - XdrPanic("Memo.RetHash accessed when Type == %v", u.Type) + XdrPanic("XdrAnon_Operation_Body.ManageBuyOfferOp accessed when Type == %v", u.Type) return nil } } -func (u Memo) XdrValid() bool { +func (u *XdrAnon_Operation_Body) PathPaymentStrictSendOp() *PathPaymentStrictSendOp { switch u.Type { - case MEMO_NONE, MEMO_TEXT, MEMO_ID, MEMO_HASH, MEMO_RETURN: - return true + case PATH_PAYMENT_STRICT_SEND: + if v, ok := u._u.(*PathPaymentStrictSendOp); ok { + return v + } else { + var zero PathPaymentStrictSendOp + u._u = &zero + return &zero + } + default: + XdrPanic("XdrAnon_Operation_Body.PathPaymentStrictSendOp accessed when Type == %v", u.Type) + return nil } - return false } -func (u *Memo) XdrUnionTag() XdrNum32 { - return XDR_MemoType(&u.Type) -} -func (u *Memo) XdrUnionTagName() string { - return "Type" -} -func (u *Memo) XdrUnionBody() XdrType { +func (u *XdrAnon_Operation_Body) CreateClaimableBalanceOp() *CreateClaimableBalanceOp { switch u.Type { - case MEMO_NONE: + case CREATE_CLAIMABLE_BALANCE: + if v, ok := u._u.(*CreateClaimableBalanceOp); ok { + return v + } else { + var zero CreateClaimableBalanceOp + u._u = &zero + return &zero + } + default: + XdrPanic("XdrAnon_Operation_Body.CreateClaimableBalanceOp accessed when Type == %v", u.Type) return nil - case MEMO_TEXT: - return XdrString{u.Text(), 28} - case MEMO_ID: - return XDR_Uint64(u.Id()) - case MEMO_HASH: - return XDR_Hash(u.Hash()) - case MEMO_RETURN: - return XDR_Hash(u.RetHash()) } - return nil } -func (u *Memo) XdrUnionBodyName() string { +func (u *XdrAnon_Operation_Body) ClaimClaimableBalanceOp() *ClaimClaimableBalanceOp { switch u.Type { - case MEMO_NONE: - return "" - case MEMO_TEXT: - return "Text" - case MEMO_ID: - return "Id" - case MEMO_HASH: - return "Hash" - case MEMO_RETURN: - return "RetHash" + case CLAIM_CLAIMABLE_BALANCE: + if v, ok := u._u.(*ClaimClaimableBalanceOp); ok { + return v + } else { + var zero ClaimClaimableBalanceOp + u._u = &zero + return &zero + } + default: + XdrPanic("XdrAnon_Operation_Body.ClaimClaimableBalanceOp accessed when Type == %v", u.Type) + return nil } - return "" } - -type XdrType_Memo = *Memo - -func (v *Memo) XdrPointer() interface{} { return v } -func (Memo) XdrTypeName() string { return "Memo" } -func (v Memo) XdrValue() interface{} { return v } -func (v *Memo) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -func (u *Memo) XdrRecurse(x XDR, name string) { - if name != "" { - name = x.Sprintf("%s.", name) - } - XDR_MemoType(&u.Type).XdrMarshal(x, x.Sprintf("%stype", name)) +func (u *XdrAnon_Operation_Body) BeginSponsoringFutureReservesOp() *BeginSponsoringFutureReservesOp { switch u.Type { - case MEMO_NONE: - return - case MEMO_TEXT: - x.Marshal(x.Sprintf("%stext", name), XdrString{u.Text(), 28}) - return - case MEMO_ID: - x.Marshal(x.Sprintf("%sid", name), XDR_Uint64(u.Id())) - return - case MEMO_HASH: - x.Marshal(x.Sprintf("%shash", name), XDR_Hash(u.Hash())) - return - case MEMO_RETURN: - x.Marshal(x.Sprintf("%sretHash", name), XDR_Hash(u.RetHash())) - return + case BEGIN_SPONSORING_FUTURE_RESERVES: + if v, ok := u._u.(*BeginSponsoringFutureReservesOp); ok { + return v + } else { + var zero BeginSponsoringFutureReservesOp + u._u = &zero + return &zero + } + default: + XdrPanic("XdrAnon_Operation_Body.BeginSponsoringFutureReservesOp accessed when Type == %v", u.Type) + return nil } - XdrPanic("invalid Type (%v) in Memo", u.Type) } -func XDR_Memo(v *Memo) *Memo { return v } - -type XdrType_TimeBounds = *TimeBounds - -func (v *TimeBounds) XdrPointer() interface{} { return v } -func (TimeBounds) XdrTypeName() string { return "TimeBounds" } -func (v TimeBounds) XdrValue() interface{} { return v } -func (v *TimeBounds) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -func (v *TimeBounds) XdrRecurse(x XDR, name string) { - if name != "" { - name = x.Sprintf("%s.", name) +func (u *XdrAnon_Operation_Body) RevokeSponsorshipOp() *RevokeSponsorshipOp { + switch u.Type { + case REVOKE_SPONSORSHIP: + if v, ok := u._u.(*RevokeSponsorshipOp); ok { + return v + } else { + var zero RevokeSponsorshipOp + u._u = &zero + return &zero + } + default: + XdrPanic("XdrAnon_Operation_Body.RevokeSponsorshipOp accessed when Type == %v", u.Type) + return nil } - x.Marshal(x.Sprintf("%sminTime", name), XDR_TimePoint(&v.MinTime)) - x.Marshal(x.Sprintf("%smaxTime", name), XDR_TimePoint(&v.MaxTime)) } -func XDR_TimeBounds(v *TimeBounds) *TimeBounds { return v } - -type XdrType_LedgerBounds = *LedgerBounds - -func (v *LedgerBounds) XdrPointer() interface{} { return v } -func (LedgerBounds) XdrTypeName() string { return "LedgerBounds" } -func (v LedgerBounds) XdrValue() interface{} { return v } -func (v *LedgerBounds) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -func (v *LedgerBounds) XdrRecurse(x XDR, name string) { - if name != "" { - name = x.Sprintf("%s.", name) +func (u *XdrAnon_Operation_Body) ClawbackOp() *ClawbackOp { + switch u.Type { + case CLAWBACK: + if v, ok := u._u.(*ClawbackOp); ok { + return v + } else { + var zero ClawbackOp + u._u = &zero + return &zero + } + default: + XdrPanic("XdrAnon_Operation_Body.ClawbackOp accessed when Type == %v", u.Type) + return nil } - x.Marshal(x.Sprintf("%sminLedger", name), XDR_Uint32(&v.MinLedger)) - x.Marshal(x.Sprintf("%smaxLedger", name), XDR_Uint32(&v.MaxLedger)) -} -func XDR_LedgerBounds(v *LedgerBounds) *LedgerBounds { return v } - -type _XdrPtr_TimeBounds struct { - p **TimeBounds } -type _ptrflag_TimeBounds _XdrPtr_TimeBounds - -func (v _ptrflag_TimeBounds) String() string { - if *v.p == nil { - return "nil" +func (u *XdrAnon_Operation_Body) ClawbackClaimableBalanceOp() *ClawbackClaimableBalanceOp { + switch u.Type { + case CLAWBACK_CLAIMABLE_BALANCE: + if v, ok := u._u.(*ClawbackClaimableBalanceOp); ok { + return v + } else { + var zero ClawbackClaimableBalanceOp + u._u = &zero + return &zero + } + default: + XdrPanic("XdrAnon_Operation_Body.ClawbackClaimableBalanceOp accessed when Type == %v", u.Type) + return nil } - return "non-nil" } -func (v _ptrflag_TimeBounds) Scan(ss fmt.ScanState, r rune) error { - tok, err := ss.Token(true, func(c rune) bool { - return c == '-' || (c >= 'a' && c <= 'z') - }) - if err != nil { - return err +func (u *XdrAnon_Operation_Body) SetTrustLineFlagsOp() *SetTrustLineFlagsOp { + switch u.Type { + case SET_TRUST_LINE_FLAGS: + if v, ok := u._u.(*SetTrustLineFlagsOp); ok { + return v + } else { + var zero SetTrustLineFlagsOp + u._u = &zero + return &zero + } + default: + XdrPanic("XdrAnon_Operation_Body.SetTrustLineFlagsOp accessed when Type == %v", u.Type) + return nil } - switch string(tok) { - case "nil": - v.SetU32(0) - case "non-nil": - v.SetU32(1) +} +func (u *XdrAnon_Operation_Body) LiquidityPoolDepositOp() *LiquidityPoolDepositOp { + switch u.Type { + case LIQUIDITY_POOL_DEPOSIT: + if v, ok := u._u.(*LiquidityPoolDepositOp); ok { + return v + } else { + var zero LiquidityPoolDepositOp + u._u = &zero + return &zero + } default: - return XdrError("TimeBounds flag should be \"nil\" or \"non-nil\"") + XdrPanic("XdrAnon_Operation_Body.LiquidityPoolDepositOp accessed when Type == %v", u.Type) + return nil } - return nil } -func (v _ptrflag_TimeBounds) GetU32() uint32 { - if *v.p == nil { - return 0 +func (u *XdrAnon_Operation_Body) LiquidityPoolWithdrawOp() *LiquidityPoolWithdrawOp { + switch u.Type { + case LIQUIDITY_POOL_WITHDRAW: + if v, ok := u._u.(*LiquidityPoolWithdrawOp); ok { + return v + } else { + var zero LiquidityPoolWithdrawOp + u._u = &zero + return &zero + } + default: + XdrPanic("XdrAnon_Operation_Body.LiquidityPoolWithdrawOp accessed when Type == %v", u.Type) + return nil } - return 1 } -func (v _ptrflag_TimeBounds) SetU32(nv uint32) { - switch nv { - case 0: - *v.p = nil - case 1: - if *v.p == nil { - *v.p = new(TimeBounds) +func (u *XdrAnon_Operation_Body) InvokeHostFunctionOp() *InvokeHostFunctionOp { + switch u.Type { + case INVOKE_HOST_FUNCTION: + if v, ok := u._u.(*InvokeHostFunctionOp); ok { + return v + } else { + var zero InvokeHostFunctionOp + u._u = &zero + return &zero } default: - XdrPanic("*TimeBounds present flag value %d should be 0 or 1", nv) + XdrPanic("XdrAnon_Operation_Body.InvokeHostFunctionOp accessed when Type == %v", u.Type) + return nil } } -func (_ptrflag_TimeBounds) XdrTypeName() string { return "TimeBounds?" } -func (v _ptrflag_TimeBounds) XdrPointer() interface{} { return nil } -func (v _ptrflag_TimeBounds) XdrValue() interface{} { return v.GetU32() != 0 } -func (v _ptrflag_TimeBounds) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -func (v _ptrflag_TimeBounds) XdrBound() uint32 { return 1 } -func (v _XdrPtr_TimeBounds) GetPresent() bool { return *v.p != nil } -func (v _XdrPtr_TimeBounds) SetPresent(present bool) { - if !present { - *v.p = nil - } else if *v.p == nil { - *v.p = new(TimeBounds) +func (u *XdrAnon_Operation_Body) ExtendFootprintTTLOp() *ExtendFootprintTTLOp { + switch u.Type { + case EXTEND_FOOTPRINT_TTL: + if v, ok := u._u.(*ExtendFootprintTTLOp); ok { + return v + } else { + var zero ExtendFootprintTTLOp + u._u = &zero + return &zero + } + default: + XdrPanic("XdrAnon_Operation_Body.ExtendFootprintTTLOp accessed when Type == %v", u.Type) + return nil } } -func (v _XdrPtr_TimeBounds) XdrMarshalValue(x XDR, name string) { - if *v.p != nil { - XDR_TimeBounds(*v.p).XdrMarshal(x, name) +func (u *XdrAnon_Operation_Body) RestoreFootprintOp() *RestoreFootprintOp { + switch u.Type { + case RESTORE_FOOTPRINT: + if v, ok := u._u.(*RestoreFootprintOp); ok { + return v + } else { + var zero RestoreFootprintOp + u._u = &zero + return &zero + } + default: + XdrPanic("XdrAnon_Operation_Body.RestoreFootprintOp accessed when Type == %v", u.Type) + return nil } } -func (v _XdrPtr_TimeBounds) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -func (v _XdrPtr_TimeBounds) XdrRecurse(x XDR, name string) { - x.Marshal(name, _ptrflag_TimeBounds(v)) - v.XdrMarshalValue(x, name) +func (u XdrAnon_Operation_Body) XdrValid() bool { + switch u.Type { + case CREATE_ACCOUNT, PAYMENT, PATH_PAYMENT_STRICT_RECEIVE, MANAGE_SELL_OFFER, CREATE_PASSIVE_SELL_OFFER, SET_OPTIONS, CHANGE_TRUST, ALLOW_TRUST, ACCOUNT_MERGE, INFLATION, MANAGE_DATA, BUMP_SEQUENCE, MANAGE_BUY_OFFER, PATH_PAYMENT_STRICT_SEND, CREATE_CLAIMABLE_BALANCE, CLAIM_CLAIMABLE_BALANCE, BEGIN_SPONSORING_FUTURE_RESERVES, END_SPONSORING_FUTURE_RESERVES, REVOKE_SPONSORSHIP, CLAWBACK, CLAWBACK_CLAIMABLE_BALANCE, SET_TRUST_LINE_FLAGS, LIQUIDITY_POOL_DEPOSIT, LIQUIDITY_POOL_WITHDRAW, INVOKE_HOST_FUNCTION, EXTEND_FOOTPRINT_TTL, RESTORE_FOOTPRINT: + return true + } + return false +} +func (u *XdrAnon_Operation_Body) XdrUnionTag() XdrNum32 { + return XDR_OperationType(&u.Type) +} +func (u *XdrAnon_Operation_Body) XdrUnionTagName() string { + return "Type" +} +func (u *XdrAnon_Operation_Body) XdrUnionBody() XdrType { + switch u.Type { + case CREATE_ACCOUNT: + return XDR_CreateAccountOp(u.CreateAccountOp()) + case PAYMENT: + return XDR_PaymentOp(u.PaymentOp()) + case PATH_PAYMENT_STRICT_RECEIVE: + return XDR_PathPaymentStrictReceiveOp(u.PathPaymentStrictReceiveOp()) + case MANAGE_SELL_OFFER: + return XDR_ManageSellOfferOp(u.ManageSellOfferOp()) + case CREATE_PASSIVE_SELL_OFFER: + return XDR_CreatePassiveSellOfferOp(u.CreatePassiveSellOfferOp()) + case SET_OPTIONS: + return XDR_SetOptionsOp(u.SetOptionsOp()) + case CHANGE_TRUST: + return XDR_ChangeTrustOp(u.ChangeTrustOp()) + case ALLOW_TRUST: + return XDR_AllowTrustOp(u.AllowTrustOp()) + case ACCOUNT_MERGE: + return XDR_MuxedAccount(u.Destination()) + case INFLATION: + return nil + case MANAGE_DATA: + return XDR_ManageDataOp(u.ManageDataOp()) + case BUMP_SEQUENCE: + return XDR_BumpSequenceOp(u.BumpSequenceOp()) + case MANAGE_BUY_OFFER: + return XDR_ManageBuyOfferOp(u.ManageBuyOfferOp()) + case PATH_PAYMENT_STRICT_SEND: + return XDR_PathPaymentStrictSendOp(u.PathPaymentStrictSendOp()) + case CREATE_CLAIMABLE_BALANCE: + return XDR_CreateClaimableBalanceOp(u.CreateClaimableBalanceOp()) + case CLAIM_CLAIMABLE_BALANCE: + return XDR_ClaimClaimableBalanceOp(u.ClaimClaimableBalanceOp()) + case BEGIN_SPONSORING_FUTURE_RESERVES: + return XDR_BeginSponsoringFutureReservesOp(u.BeginSponsoringFutureReservesOp()) + case END_SPONSORING_FUTURE_RESERVES: + return nil + case REVOKE_SPONSORSHIP: + return XDR_RevokeSponsorshipOp(u.RevokeSponsorshipOp()) + case CLAWBACK: + return XDR_ClawbackOp(u.ClawbackOp()) + case CLAWBACK_CLAIMABLE_BALANCE: + return XDR_ClawbackClaimableBalanceOp(u.ClawbackClaimableBalanceOp()) + case SET_TRUST_LINE_FLAGS: + return XDR_SetTrustLineFlagsOp(u.SetTrustLineFlagsOp()) + case LIQUIDITY_POOL_DEPOSIT: + return XDR_LiquidityPoolDepositOp(u.LiquidityPoolDepositOp()) + case LIQUIDITY_POOL_WITHDRAW: + return XDR_LiquidityPoolWithdrawOp(u.LiquidityPoolWithdrawOp()) + case INVOKE_HOST_FUNCTION: + return XDR_InvokeHostFunctionOp(u.InvokeHostFunctionOp()) + case EXTEND_FOOTPRINT_TTL: + return XDR_ExtendFootprintTTLOp(u.ExtendFootprintTTLOp()) + case RESTORE_FOOTPRINT: + return XDR_RestoreFootprintOp(u.RestoreFootprintOp()) + } + return nil +} +func (u *XdrAnon_Operation_Body) XdrUnionBodyName() string { + switch u.Type { + case CREATE_ACCOUNT: + return "CreateAccountOp" + case PAYMENT: + return "PaymentOp" + case PATH_PAYMENT_STRICT_RECEIVE: + return "PathPaymentStrictReceiveOp" + case MANAGE_SELL_OFFER: + return "ManageSellOfferOp" + case CREATE_PASSIVE_SELL_OFFER: + return "CreatePassiveSellOfferOp" + case SET_OPTIONS: + return "SetOptionsOp" + case CHANGE_TRUST: + return "ChangeTrustOp" + case ALLOW_TRUST: + return "AllowTrustOp" + case ACCOUNT_MERGE: + return "Destination" + case INFLATION: + return "" + case MANAGE_DATA: + return "ManageDataOp" + case BUMP_SEQUENCE: + return "BumpSequenceOp" + case MANAGE_BUY_OFFER: + return "ManageBuyOfferOp" + case PATH_PAYMENT_STRICT_SEND: + return "PathPaymentStrictSendOp" + case CREATE_CLAIMABLE_BALANCE: + return "CreateClaimableBalanceOp" + case CLAIM_CLAIMABLE_BALANCE: + return "ClaimClaimableBalanceOp" + case BEGIN_SPONSORING_FUTURE_RESERVES: + return "BeginSponsoringFutureReservesOp" + case END_SPONSORING_FUTURE_RESERVES: + return "" + case REVOKE_SPONSORSHIP: + return "RevokeSponsorshipOp" + case CLAWBACK: + return "ClawbackOp" + case CLAWBACK_CLAIMABLE_BALANCE: + return "ClawbackClaimableBalanceOp" + case SET_TRUST_LINE_FLAGS: + return "SetTrustLineFlagsOp" + case LIQUIDITY_POOL_DEPOSIT: + return "LiquidityPoolDepositOp" + case LIQUIDITY_POOL_WITHDRAW: + return "LiquidityPoolWithdrawOp" + case INVOKE_HOST_FUNCTION: + return "InvokeHostFunctionOp" + case EXTEND_FOOTPRINT_TTL: + return "ExtendFootprintTTLOp" + case RESTORE_FOOTPRINT: + return "RestoreFootprintOp" + } + return "" } -func (_XdrPtr_TimeBounds) XdrTypeName() string { return "TimeBounds*" } -func (v _XdrPtr_TimeBounds) XdrPointer() interface{} { return v.p } -func (v _XdrPtr_TimeBounds) XdrValue() interface{} { return *v.p } -type _XdrPtr_LedgerBounds struct { - p **LedgerBounds +type XdrType_XdrAnon_Operation_Body = *XdrAnon_Operation_Body + +func (v *XdrAnon_Operation_Body) XdrPointer() interface{} { return v } +func (XdrAnon_Operation_Body) XdrTypeName() string { return "XdrAnon_Operation_Body" } +func (v XdrAnon_Operation_Body) XdrValue() interface{} { return v } +func (v *XdrAnon_Operation_Body) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (u *XdrAnon_Operation_Body) XdrRecurse(x XDR, name string) { + if name != "" { + name = x.Sprintf("%s.", name) + } + XDR_OperationType(&u.Type).XdrMarshal(x, x.Sprintf("%stype", name)) + switch u.Type { + case CREATE_ACCOUNT: + x.Marshal(x.Sprintf("%screateAccountOp", name), XDR_CreateAccountOp(u.CreateAccountOp())) + return + case PAYMENT: + x.Marshal(x.Sprintf("%spaymentOp", name), XDR_PaymentOp(u.PaymentOp())) + return + case PATH_PAYMENT_STRICT_RECEIVE: + x.Marshal(x.Sprintf("%spathPaymentStrictReceiveOp", name), XDR_PathPaymentStrictReceiveOp(u.PathPaymentStrictReceiveOp())) + return + case MANAGE_SELL_OFFER: + x.Marshal(x.Sprintf("%smanageSellOfferOp", name), XDR_ManageSellOfferOp(u.ManageSellOfferOp())) + return + case CREATE_PASSIVE_SELL_OFFER: + x.Marshal(x.Sprintf("%screatePassiveSellOfferOp", name), XDR_CreatePassiveSellOfferOp(u.CreatePassiveSellOfferOp())) + return + case SET_OPTIONS: + x.Marshal(x.Sprintf("%ssetOptionsOp", name), XDR_SetOptionsOp(u.SetOptionsOp())) + return + case CHANGE_TRUST: + x.Marshal(x.Sprintf("%schangeTrustOp", name), XDR_ChangeTrustOp(u.ChangeTrustOp())) + return + case ALLOW_TRUST: + x.Marshal(x.Sprintf("%sallowTrustOp", name), XDR_AllowTrustOp(u.AllowTrustOp())) + return + case ACCOUNT_MERGE: + x.Marshal(x.Sprintf("%sdestination", name), XDR_MuxedAccount(u.Destination())) + return + case INFLATION: + return + case MANAGE_DATA: + x.Marshal(x.Sprintf("%smanageDataOp", name), XDR_ManageDataOp(u.ManageDataOp())) + return + case BUMP_SEQUENCE: + x.Marshal(x.Sprintf("%sbumpSequenceOp", name), XDR_BumpSequenceOp(u.BumpSequenceOp())) + return + case MANAGE_BUY_OFFER: + x.Marshal(x.Sprintf("%smanageBuyOfferOp", name), XDR_ManageBuyOfferOp(u.ManageBuyOfferOp())) + return + case PATH_PAYMENT_STRICT_SEND: + x.Marshal(x.Sprintf("%spathPaymentStrictSendOp", name), XDR_PathPaymentStrictSendOp(u.PathPaymentStrictSendOp())) + return + case CREATE_CLAIMABLE_BALANCE: + x.Marshal(x.Sprintf("%screateClaimableBalanceOp", name), XDR_CreateClaimableBalanceOp(u.CreateClaimableBalanceOp())) + return + case CLAIM_CLAIMABLE_BALANCE: + x.Marshal(x.Sprintf("%sclaimClaimableBalanceOp", name), XDR_ClaimClaimableBalanceOp(u.ClaimClaimableBalanceOp())) + return + case BEGIN_SPONSORING_FUTURE_RESERVES: + x.Marshal(x.Sprintf("%sbeginSponsoringFutureReservesOp", name), XDR_BeginSponsoringFutureReservesOp(u.BeginSponsoringFutureReservesOp())) + return + case END_SPONSORING_FUTURE_RESERVES: + return + case REVOKE_SPONSORSHIP: + x.Marshal(x.Sprintf("%srevokeSponsorshipOp", name), XDR_RevokeSponsorshipOp(u.RevokeSponsorshipOp())) + return + case CLAWBACK: + x.Marshal(x.Sprintf("%sclawbackOp", name), XDR_ClawbackOp(u.ClawbackOp())) + return + case CLAWBACK_CLAIMABLE_BALANCE: + x.Marshal(x.Sprintf("%sclawbackClaimableBalanceOp", name), XDR_ClawbackClaimableBalanceOp(u.ClawbackClaimableBalanceOp())) + return + case SET_TRUST_LINE_FLAGS: + x.Marshal(x.Sprintf("%ssetTrustLineFlagsOp", name), XDR_SetTrustLineFlagsOp(u.SetTrustLineFlagsOp())) + return + case LIQUIDITY_POOL_DEPOSIT: + x.Marshal(x.Sprintf("%sliquidityPoolDepositOp", name), XDR_LiquidityPoolDepositOp(u.LiquidityPoolDepositOp())) + return + case LIQUIDITY_POOL_WITHDRAW: + x.Marshal(x.Sprintf("%sliquidityPoolWithdrawOp", name), XDR_LiquidityPoolWithdrawOp(u.LiquidityPoolWithdrawOp())) + return + case INVOKE_HOST_FUNCTION: + x.Marshal(x.Sprintf("%sinvokeHostFunctionOp", name), XDR_InvokeHostFunctionOp(u.InvokeHostFunctionOp())) + return + case EXTEND_FOOTPRINT_TTL: + x.Marshal(x.Sprintf("%sextendFootprintTTLOp", name), XDR_ExtendFootprintTTLOp(u.ExtendFootprintTTLOp())) + return + case RESTORE_FOOTPRINT: + x.Marshal(x.Sprintf("%srestoreFootprintOp", name), XDR_RestoreFootprintOp(u.RestoreFootprintOp())) + return + } + XdrPanic("invalid Type (%v) in XdrAnon_Operation_Body", u.Type) } -type _ptrflag_LedgerBounds _XdrPtr_LedgerBounds +func XDR_XdrAnon_Operation_Body(v *XdrAnon_Operation_Body) *XdrAnon_Operation_Body { return v } -func (v _ptrflag_LedgerBounds) String() string { +type _XdrPtr_MuxedAccount struct { + p **MuxedAccount +} +type _ptrflag_MuxedAccount _XdrPtr_MuxedAccount + +func (v _ptrflag_MuxedAccount) String() string { if *v.p == nil { return "nil" } return "non-nil" } -func (v _ptrflag_LedgerBounds) Scan(ss fmt.ScanState, r rune) error { +func (v _ptrflag_MuxedAccount) Scan(ss fmt.ScanState, r rune) error { tok, err := ss.Token(true, func(c rune) bool { return c == '-' || (c >= 'a' && c <= 'z') }) @@ -13887,3253 +16925,6950 @@ func (v _ptrflag_LedgerBounds) Scan(ss fmt.ScanState, r rune) error { case "non-nil": v.SetU32(1) default: - return XdrError("LedgerBounds flag should be \"nil\" or \"non-nil\"") + return XdrError("MuxedAccount flag should be \"nil\" or \"non-nil\"") } return nil } -func (v _ptrflag_LedgerBounds) GetU32() uint32 { +func (v _ptrflag_MuxedAccount) GetU32() uint32 { if *v.p == nil { return 0 } return 1 } -func (v _ptrflag_LedgerBounds) SetU32(nv uint32) { +func (v _ptrflag_MuxedAccount) SetU32(nv uint32) { switch nv { case 0: *v.p = nil case 1: if *v.p == nil { - *v.p = new(LedgerBounds) + *v.p = new(MuxedAccount) } default: - XdrPanic("*LedgerBounds present flag value %d should be 0 or 1", nv) + XdrPanic("*MuxedAccount present flag value %d should be 0 or 1", nv) } } -func (_ptrflag_LedgerBounds) XdrTypeName() string { return "LedgerBounds?" } -func (v _ptrflag_LedgerBounds) XdrPointer() interface{} { return nil } -func (v _ptrflag_LedgerBounds) XdrValue() interface{} { return v.GetU32() != 0 } -func (v _ptrflag_LedgerBounds) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -func (v _ptrflag_LedgerBounds) XdrBound() uint32 { return 1 } -func (v _XdrPtr_LedgerBounds) GetPresent() bool { return *v.p != nil } -func (v _XdrPtr_LedgerBounds) SetPresent(present bool) { - if !present { - *v.p = nil - } else if *v.p == nil { - *v.p = new(LedgerBounds) +func (_ptrflag_MuxedAccount) XdrTypeName() string { return "MuxedAccount?" } +func (v _ptrflag_MuxedAccount) XdrPointer() interface{} { return nil } +func (v _ptrflag_MuxedAccount) XdrValue() interface{} { return v.GetU32() != 0 } +func (v _ptrflag_MuxedAccount) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v _ptrflag_MuxedAccount) XdrBound() uint32 { return 1 } +func (v _XdrPtr_MuxedAccount) GetPresent() bool { return *v.p != nil } +func (v _XdrPtr_MuxedAccount) SetPresent(present bool) { + if !present { + *v.p = nil + } else if *v.p == nil { + *v.p = new(MuxedAccount) } } -func (v _XdrPtr_LedgerBounds) XdrMarshalValue(x XDR, name string) { +func (v _XdrPtr_MuxedAccount) XdrMarshalValue(x XDR, name string) { if *v.p != nil { - XDR_LedgerBounds(*v.p).XdrMarshal(x, name) + XDR_MuxedAccount(*v.p).XdrMarshal(x, name) } } -func (v _XdrPtr_LedgerBounds) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -func (v _XdrPtr_LedgerBounds) XdrRecurse(x XDR, name string) { - x.Marshal(name, _ptrflag_LedgerBounds(v)) +func (v _XdrPtr_MuxedAccount) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v _XdrPtr_MuxedAccount) XdrRecurse(x XDR, name string) { + x.Marshal(name, _ptrflag_MuxedAccount(v)) v.XdrMarshalValue(x, name) } -func (_XdrPtr_LedgerBounds) XdrTypeName() string { return "LedgerBounds*" } -func (v _XdrPtr_LedgerBounds) XdrPointer() interface{} { return v.p } -func (v _XdrPtr_LedgerBounds) XdrValue() interface{} { return *v.p } +func (_XdrPtr_MuxedAccount) XdrTypeName() string { return "MuxedAccount*" } +func (v _XdrPtr_MuxedAccount) XdrPointer() interface{} { return v.p } +func (v _XdrPtr_MuxedAccount) XdrValue() interface{} { return *v.p } -type _XdrPtr_SequenceNumber struct { - p **SequenceNumber -} -type _ptrflag_SequenceNumber _XdrPtr_SequenceNumber +type XdrType_Operation = *Operation -func (v _ptrflag_SequenceNumber) String() string { - if *v.p == nil { - return "nil" - } - return "non-nil" -} -func (v _ptrflag_SequenceNumber) Scan(ss fmt.ScanState, r rune) error { - tok, err := ss.Token(true, func(c rune) bool { - return c == '-' || (c >= 'a' && c <= 'z') - }) - if err != nil { - return err - } - switch string(tok) { - case "nil": - v.SetU32(0) - case "non-nil": - v.SetU32(1) - default: - return XdrError("SequenceNumber flag should be \"nil\" or \"non-nil\"") +func (v *Operation) XdrPointer() interface{} { return v } +func (Operation) XdrTypeName() string { return "Operation" } +func (v Operation) XdrValue() interface{} { return v } +func (v *Operation) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v *Operation) XdrRecurse(x XDR, name string) { + if name != "" { + name = x.Sprintf("%s.", name) } - return nil + x.Marshal(x.Sprintf("%ssourceAccount", name), _XdrPtr_MuxedAccount{&v.SourceAccount}) + x.Marshal(x.Sprintf("%sbody", name), XDR_XdrAnon_Operation_Body(&v.Body)) } -func (v _ptrflag_SequenceNumber) GetU32() uint32 { - if *v.p == nil { - return 0 - } - return 1 +func XDR_Operation(v *Operation) *Operation { return v } + +type XdrType_XdrAnon_HashIDPreimage_OperationID = *XdrAnon_HashIDPreimage_OperationID + +func (v *XdrAnon_HashIDPreimage_OperationID) XdrPointer() interface{} { return v } +func (XdrAnon_HashIDPreimage_OperationID) XdrTypeName() string { + return "XdrAnon_HashIDPreimage_OperationID" } -func (v _ptrflag_SequenceNumber) SetU32(nv uint32) { - switch nv { - case 0: - *v.p = nil - case 1: - if *v.p == nil { - *v.p = new(SequenceNumber) - } - default: - XdrPanic("*SequenceNumber present flag value %d should be 0 or 1", nv) +func (v XdrAnon_HashIDPreimage_OperationID) XdrValue() interface{} { return v } +func (v *XdrAnon_HashIDPreimage_OperationID) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v *XdrAnon_HashIDPreimage_OperationID) XdrRecurse(x XDR, name string) { + if name != "" { + name = x.Sprintf("%s.", name) } + x.Marshal(x.Sprintf("%ssourceAccount", name), XDR_AccountID(&v.SourceAccount)) + x.Marshal(x.Sprintf("%sseqNum", name), XDR_SequenceNumber(&v.SeqNum)) + x.Marshal(x.Sprintf("%sopNum", name), XDR_Uint32(&v.OpNum)) } -func (_ptrflag_SequenceNumber) XdrTypeName() string { return "SequenceNumber?" } -func (v _ptrflag_SequenceNumber) XdrPointer() interface{} { return nil } -func (v _ptrflag_SequenceNumber) XdrValue() interface{} { return v.GetU32() != 0 } -func (v _ptrflag_SequenceNumber) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -func (v _ptrflag_SequenceNumber) XdrBound() uint32 { return 1 } -func (v _XdrPtr_SequenceNumber) GetPresent() bool { return *v.p != nil } -func (v _XdrPtr_SequenceNumber) SetPresent(present bool) { - if !present { - *v.p = nil - } else if *v.p == nil { - *v.p = new(SequenceNumber) - } +func XDR_XdrAnon_HashIDPreimage_OperationID(v *XdrAnon_HashIDPreimage_OperationID) *XdrAnon_HashIDPreimage_OperationID { + return v } -func (v _XdrPtr_SequenceNumber) XdrMarshalValue(x XDR, name string) { - if *v.p != nil { - XDR_SequenceNumber(*v.p).XdrMarshal(x, name) + +type XdrType_XdrAnon_HashIDPreimage_RevokeID = *XdrAnon_HashIDPreimage_RevokeID + +func (v *XdrAnon_HashIDPreimage_RevokeID) XdrPointer() interface{} { return v } +func (XdrAnon_HashIDPreimage_RevokeID) XdrTypeName() string { return "XdrAnon_HashIDPreimage_RevokeID" } +func (v XdrAnon_HashIDPreimage_RevokeID) XdrValue() interface{} { return v } +func (v *XdrAnon_HashIDPreimage_RevokeID) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v *XdrAnon_HashIDPreimage_RevokeID) XdrRecurse(x XDR, name string) { + if name != "" { + name = x.Sprintf("%s.", name) } + x.Marshal(x.Sprintf("%ssourceAccount", name), XDR_AccountID(&v.SourceAccount)) + x.Marshal(x.Sprintf("%sseqNum", name), XDR_SequenceNumber(&v.SeqNum)) + x.Marshal(x.Sprintf("%sopNum", name), XDR_Uint32(&v.OpNum)) + x.Marshal(x.Sprintf("%sliquidityPoolID", name), XDR_PoolID(&v.LiquidityPoolID)) + x.Marshal(x.Sprintf("%sasset", name), XDR_Asset(&v.Asset)) } -func (v _XdrPtr_SequenceNumber) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -func (v _XdrPtr_SequenceNumber) XdrRecurse(x XDR, name string) { - x.Marshal(name, _ptrflag_SequenceNumber(v)) - v.XdrMarshalValue(x, name) +func XDR_XdrAnon_HashIDPreimage_RevokeID(v *XdrAnon_HashIDPreimage_RevokeID) *XdrAnon_HashIDPreimage_RevokeID { + return v } -func (_XdrPtr_SequenceNumber) XdrTypeName() string { return "SequenceNumber*" } -func (v _XdrPtr_SequenceNumber) XdrPointer() interface{} { return v.p } -func (v _XdrPtr_SequenceNumber) XdrValue() interface{} { return *v.p } -type _XdrVec_2_SignerKey []SignerKey +type XdrType_XdrAnon_HashIDPreimage_ContractID = *XdrAnon_HashIDPreimage_ContractID -func (_XdrVec_2_SignerKey) XdrBound() uint32 { - const bound uint32 = 2 // Force error if not const or doesn't fit - return bound -} -func (_XdrVec_2_SignerKey) XdrCheckLen(length uint32) { - if length > uint32(2) { - XdrPanic("_XdrVec_2_SignerKey length %d exceeds bound 2", length) - } else if int(length) < 0 { - XdrPanic("_XdrVec_2_SignerKey length %d exceeds max int", length) - } -} -func (v _XdrVec_2_SignerKey) GetVecLen() uint32 { return uint32(len(v)) } -func (v *_XdrVec_2_SignerKey) SetVecLen(length uint32) { - v.XdrCheckLen(length) - if int(length) <= cap(*v) { - if int(length) != len(*v) { - *v = (*v)[:int(length)] - } - return - } - newcap := 2 * cap(*v) - if newcap < int(length) { // also catches overflow where 2*cap < 0 - newcap = int(length) - } else if bound := uint(2); uint(newcap) > bound { - if int(bound) < 0 { - bound = ^uint(0) >> 1 - } - newcap = int(bound) - } - nv := make([]SignerKey, int(length), newcap) - copy(nv, *v) - *v = nv +func (v *XdrAnon_HashIDPreimage_ContractID) XdrPointer() interface{} { return v } +func (XdrAnon_HashIDPreimage_ContractID) XdrTypeName() string { + return "XdrAnon_HashIDPreimage_ContractID" } -func (v *_XdrVec_2_SignerKey) XdrMarshalN(x XDR, name string, n uint32) { - v.XdrCheckLen(n) - for i := 0; i < int(n); i++ { - if i >= len(*v) { - v.SetVecLen(uint32(i + 1)) - } - XDR_SignerKey(&(*v)[i]).XdrMarshal(x, x.Sprintf("%s[%d]", name, i)) - } - if int(n) < len(*v) { - *v = (*v)[:int(n)] +func (v XdrAnon_HashIDPreimage_ContractID) XdrValue() interface{} { return v } +func (v *XdrAnon_HashIDPreimage_ContractID) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v *XdrAnon_HashIDPreimage_ContractID) XdrRecurse(x XDR, name string) { + if name != "" { + name = x.Sprintf("%s.", name) } + x.Marshal(x.Sprintf("%snetworkID", name), XDR_Hash(&v.NetworkID)) + x.Marshal(x.Sprintf("%scontractIDPreimage", name), XDR_ContractIDPreimage(&v.ContractIDPreimage)) } -func (v *_XdrVec_2_SignerKey) XdrRecurse(x XDR, name string) { - size := XdrSize{Size: uint32(len(*v)), Bound: 2} - x.Marshal(name, &size) - v.XdrMarshalN(x, name, size.Size) +func XDR_XdrAnon_HashIDPreimage_ContractID(v *XdrAnon_HashIDPreimage_ContractID) *XdrAnon_HashIDPreimage_ContractID { + return v } -func (_XdrVec_2_SignerKey) XdrTypeName() string { return "SignerKey<>" } -func (v *_XdrVec_2_SignerKey) XdrPointer() interface{} { return (*[]SignerKey)(v) } -func (v _XdrVec_2_SignerKey) XdrValue() interface{} { return ([]SignerKey)(v) } -func (v *_XdrVec_2_SignerKey) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -type XdrType_PreconditionsV2 = *PreconditionsV2 +type XdrType_XdrAnon_HashIDPreimage_SorobanAuthorization = *XdrAnon_HashIDPreimage_SorobanAuthorization -func (v *PreconditionsV2) XdrPointer() interface{} { return v } -func (PreconditionsV2) XdrTypeName() string { return "PreconditionsV2" } -func (v PreconditionsV2) XdrValue() interface{} { return v } -func (v *PreconditionsV2) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -func (v *PreconditionsV2) XdrRecurse(x XDR, name string) { +func (v *XdrAnon_HashIDPreimage_SorobanAuthorization) XdrPointer() interface{} { return v } +func (XdrAnon_HashIDPreimage_SorobanAuthorization) XdrTypeName() string { + return "XdrAnon_HashIDPreimage_SorobanAuthorization" +} +func (v XdrAnon_HashIDPreimage_SorobanAuthorization) XdrValue() interface{} { return v } +func (v *XdrAnon_HashIDPreimage_SorobanAuthorization) XdrMarshal(x XDR, name string) { + x.Marshal(name, v) +} +func (v *XdrAnon_HashIDPreimage_SorobanAuthorization) XdrRecurse(x XDR, name string) { if name != "" { name = x.Sprintf("%s.", name) } - x.Marshal(x.Sprintf("%stimeBounds", name), _XdrPtr_TimeBounds{&v.TimeBounds}) - x.Marshal(x.Sprintf("%sledgerBounds", name), _XdrPtr_LedgerBounds{&v.LedgerBounds}) - x.Marshal(x.Sprintf("%sminSeqNum", name), _XdrPtr_SequenceNumber{&v.MinSeqNum}) - x.Marshal(x.Sprintf("%sminSeqAge", name), XDR_Duration(&v.MinSeqAge)) - x.Marshal(x.Sprintf("%sminSeqLedgerGap", name), XDR_Uint32(&v.MinSeqLedgerGap)) - x.Marshal(x.Sprintf("%sextraSigners", name), (*_XdrVec_2_SignerKey)(&v.ExtraSigners)) -} -func XDR_PreconditionsV2(v *PreconditionsV2) *PreconditionsV2 { return v } - -var _XdrNames_PreconditionType = map[int32]string{ - int32(PRECOND_NONE): "PRECOND_NONE", - int32(PRECOND_TIME): "PRECOND_TIME", - int32(PRECOND_V2): "PRECOND_V2", + x.Marshal(x.Sprintf("%snetworkID", name), XDR_Hash(&v.NetworkID)) + x.Marshal(x.Sprintf("%snonce", name), XDR_Int64(&v.Nonce)) + x.Marshal(x.Sprintf("%ssignatureExpirationLedger", name), XDR_Uint32(&v.SignatureExpirationLedger)) + x.Marshal(x.Sprintf("%sinvocation", name), XDR_SorobanAuthorizedInvocation(&v.Invocation)) } -var _XdrValues_PreconditionType = map[string]int32{ - "PRECOND_NONE": int32(PRECOND_NONE), - "PRECOND_TIME": int32(PRECOND_TIME), - "PRECOND_V2": int32(PRECOND_V2), +func XDR_XdrAnon_HashIDPreimage_SorobanAuthorization(v *XdrAnon_HashIDPreimage_SorobanAuthorization) *XdrAnon_HashIDPreimage_SorobanAuthorization { + return v } -func (PreconditionType) XdrEnumNames() map[int32]string { - return _XdrNames_PreconditionType +var _XdrTags_HashIDPreimage = map[int32]bool{ + XdrToI32(ENVELOPE_TYPE_OP_ID): true, + XdrToI32(ENVELOPE_TYPE_POOL_REVOKE_OP_ID): true, + XdrToI32(ENVELOPE_TYPE_CONTRACT_ID): true, + XdrToI32(ENVELOPE_TYPE_SOROBAN_AUTHORIZATION): true, } -func (v PreconditionType) String() string { - if s, ok := _XdrNames_PreconditionType[int32(v)]; ok { - return s - } - return fmt.Sprintf("PreconditionType#%d", v) + +func (_ HashIDPreimage) XdrValidTags() map[int32]bool { + return _XdrTags_HashIDPreimage } -func (v *PreconditionType) Scan(ss fmt.ScanState, _ rune) error { - if tok, err := ss.Token(true, XdrSymChar); err != nil { - return err - } else { - stok := string(tok) - if val, ok := _XdrValues_PreconditionType[stok]; ok { - *v = PreconditionType(val) - return nil - } else if stok == "PreconditionType" { - if n, err := fmt.Fscanf(ss, "#%d", (*int32)(v)); n == 1 && err == nil { - return nil - } +func (u *HashIDPreimage) OperationID() *XdrAnon_HashIDPreimage_OperationID { + switch u.Type { + case ENVELOPE_TYPE_OP_ID: + if v, ok := u._u.(*XdrAnon_HashIDPreimage_OperationID); ok { + return v + } else { + var zero XdrAnon_HashIDPreimage_OperationID + u._u = &zero + return &zero } - return XdrError(fmt.Sprintf("%s is not a valid PreconditionType.", stok)) + default: + XdrPanic("HashIDPreimage.OperationID accessed when Type == %v", u.Type) + return nil } } -func (v PreconditionType) GetU32() uint32 { return uint32(v) } -func (v *PreconditionType) SetU32(n uint32) { *v = PreconditionType(n) } -func (v *PreconditionType) XdrPointer() interface{} { return v } -func (PreconditionType) XdrTypeName() string { return "PreconditionType" } -func (v PreconditionType) XdrValue() interface{} { return v } -func (v *PreconditionType) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } - -type XdrType_PreconditionType = *PreconditionType - -func XDR_PreconditionType(v *PreconditionType) *PreconditionType { return v } - -var _XdrTags_Preconditions = map[int32]bool{ - XdrToI32(PRECOND_NONE): true, - XdrToI32(PRECOND_TIME): true, - XdrToI32(PRECOND_V2): true, -} - -func (_ Preconditions) XdrValidTags() map[int32]bool { - return _XdrTags_Preconditions +func (u *HashIDPreimage) RevokeID() *XdrAnon_HashIDPreimage_RevokeID { + switch u.Type { + case ENVELOPE_TYPE_POOL_REVOKE_OP_ID: + if v, ok := u._u.(*XdrAnon_HashIDPreimage_RevokeID); ok { + return v + } else { + var zero XdrAnon_HashIDPreimage_RevokeID + u._u = &zero + return &zero + } + default: + XdrPanic("HashIDPreimage.RevokeID accessed when Type == %v", u.Type) + return nil + } } -func (u *Preconditions) TimeBounds() *TimeBounds { +func (u *HashIDPreimage) ContractID() *XdrAnon_HashIDPreimage_ContractID { switch u.Type { - case PRECOND_TIME: - if v, ok := u._u.(*TimeBounds); ok { + case ENVELOPE_TYPE_CONTRACT_ID: + if v, ok := u._u.(*XdrAnon_HashIDPreimage_ContractID); ok { return v } else { - var zero TimeBounds + var zero XdrAnon_HashIDPreimage_ContractID u._u = &zero return &zero } default: - XdrPanic("Preconditions.TimeBounds accessed when Type == %v", u.Type) + XdrPanic("HashIDPreimage.ContractID accessed when Type == %v", u.Type) return nil } } -func (u *Preconditions) V2() *PreconditionsV2 { +func (u *HashIDPreimage) SorobanAuthorization() *XdrAnon_HashIDPreimage_SorobanAuthorization { switch u.Type { - case PRECOND_V2: - if v, ok := u._u.(*PreconditionsV2); ok { + case ENVELOPE_TYPE_SOROBAN_AUTHORIZATION: + if v, ok := u._u.(*XdrAnon_HashIDPreimage_SorobanAuthorization); ok { return v } else { - var zero PreconditionsV2 + var zero XdrAnon_HashIDPreimage_SorobanAuthorization u._u = &zero return &zero } default: - XdrPanic("Preconditions.V2 accessed when Type == %v", u.Type) + XdrPanic("HashIDPreimage.SorobanAuthorization accessed when Type == %v", u.Type) return nil } } -func (u Preconditions) XdrValid() bool { +func (u HashIDPreimage) XdrValid() bool { switch u.Type { - case PRECOND_NONE, PRECOND_TIME, PRECOND_V2: + case ENVELOPE_TYPE_OP_ID, ENVELOPE_TYPE_POOL_REVOKE_OP_ID, ENVELOPE_TYPE_CONTRACT_ID, ENVELOPE_TYPE_SOROBAN_AUTHORIZATION: return true } return false } -func (u *Preconditions) XdrUnionTag() XdrNum32 { - return XDR_PreconditionType(&u.Type) +func (u *HashIDPreimage) XdrUnionTag() XdrNum32 { + return XDR_EnvelopeType(&u.Type) } -func (u *Preconditions) XdrUnionTagName() string { +func (u *HashIDPreimage) XdrUnionTagName() string { return "Type" } -func (u *Preconditions) XdrUnionBody() XdrType { +func (u *HashIDPreimage) XdrUnionBody() XdrType { switch u.Type { - case PRECOND_NONE: - return nil - case PRECOND_TIME: - return XDR_TimeBounds(u.TimeBounds()) - case PRECOND_V2: - return XDR_PreconditionsV2(u.V2()) + case ENVELOPE_TYPE_OP_ID: + return XDR_XdrAnon_HashIDPreimage_OperationID(u.OperationID()) + case ENVELOPE_TYPE_POOL_REVOKE_OP_ID: + return XDR_XdrAnon_HashIDPreimage_RevokeID(u.RevokeID()) + case ENVELOPE_TYPE_CONTRACT_ID: + return XDR_XdrAnon_HashIDPreimage_ContractID(u.ContractID()) + case ENVELOPE_TYPE_SOROBAN_AUTHORIZATION: + return XDR_XdrAnon_HashIDPreimage_SorobanAuthorization(u.SorobanAuthorization()) } return nil } -func (u *Preconditions) XdrUnionBodyName() string { +func (u *HashIDPreimage) XdrUnionBodyName() string { switch u.Type { - case PRECOND_NONE: - return "" - case PRECOND_TIME: - return "TimeBounds" - case PRECOND_V2: - return "V2" + case ENVELOPE_TYPE_OP_ID: + return "OperationID" + case ENVELOPE_TYPE_POOL_REVOKE_OP_ID: + return "RevokeID" + case ENVELOPE_TYPE_CONTRACT_ID: + return "ContractID" + case ENVELOPE_TYPE_SOROBAN_AUTHORIZATION: + return "SorobanAuthorization" } return "" } -type XdrType_Preconditions = *Preconditions +type XdrType_HashIDPreimage = *HashIDPreimage -func (v *Preconditions) XdrPointer() interface{} { return v } -func (Preconditions) XdrTypeName() string { return "Preconditions" } -func (v Preconditions) XdrValue() interface{} { return v } -func (v *Preconditions) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -func (u *Preconditions) XdrRecurse(x XDR, name string) { +func (v *HashIDPreimage) XdrPointer() interface{} { return v } +func (HashIDPreimage) XdrTypeName() string { return "HashIDPreimage" } +func (v HashIDPreimage) XdrValue() interface{} { return v } +func (v *HashIDPreimage) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (u *HashIDPreimage) XdrRecurse(x XDR, name string) { if name != "" { name = x.Sprintf("%s.", name) } - XDR_PreconditionType(&u.Type).XdrMarshal(x, x.Sprintf("%stype", name)) + XDR_EnvelopeType(&u.Type).XdrMarshal(x, x.Sprintf("%stype", name)) switch u.Type { - case PRECOND_NONE: + case ENVELOPE_TYPE_OP_ID: + x.Marshal(x.Sprintf("%soperationID", name), XDR_XdrAnon_HashIDPreimage_OperationID(u.OperationID())) return - case PRECOND_TIME: - x.Marshal(x.Sprintf("%stimeBounds", name), XDR_TimeBounds(u.TimeBounds())) + case ENVELOPE_TYPE_POOL_REVOKE_OP_ID: + x.Marshal(x.Sprintf("%srevokeID", name), XDR_XdrAnon_HashIDPreimage_RevokeID(u.RevokeID())) return - case PRECOND_V2: - x.Marshal(x.Sprintf("%sv2", name), XDR_PreconditionsV2(u.V2())) + case ENVELOPE_TYPE_CONTRACT_ID: + x.Marshal(x.Sprintf("%scontractID", name), XDR_XdrAnon_HashIDPreimage_ContractID(u.ContractID())) + return + case ENVELOPE_TYPE_SOROBAN_AUTHORIZATION: + x.Marshal(x.Sprintf("%ssorobanAuthorization", name), XDR_XdrAnon_HashIDPreimage_SorobanAuthorization(u.SorobanAuthorization())) return } - XdrPanic("invalid Type (%v) in Preconditions", u.Type) + XdrPanic("invalid Type (%v) in HashIDPreimage", u.Type) } -func XDR_Preconditions(v *Preconditions) *Preconditions { return v } - -var _XdrTags_XdrAnon_TransactionV0_Ext = map[int32]bool{ - XdrToI32(0): true, +func (v *HashIDPreimage) XdrInitialize() { + var zero EnvelopeType + switch zero { + case ENVELOPE_TYPE_OP_ID, ENVELOPE_TYPE_POOL_REVOKE_OP_ID, ENVELOPE_TYPE_CONTRACT_ID, ENVELOPE_TYPE_SOROBAN_AUTHORIZATION: + default: + if v.Type == zero { + v.Type = ENVELOPE_TYPE_OP_ID + } + } } +func XDR_HashIDPreimage(v *HashIDPreimage) *HashIDPreimage { return v } -func (_ XdrAnon_TransactionV0_Ext) XdrValidTags() map[int32]bool { - return _XdrTags_XdrAnon_TransactionV0_Ext -} -func (u XdrAnon_TransactionV0_Ext) XdrValid() bool { - switch u.V { - case 0: - return true - } - return false +var _XdrNames_MemoType = map[int32]string{ + int32(MEMO_NONE): "MEMO_NONE", + int32(MEMO_TEXT): "MEMO_TEXT", + int32(MEMO_ID): "MEMO_ID", + int32(MEMO_HASH): "MEMO_HASH", + int32(MEMO_RETURN): "MEMO_RETURN", } -func (u *XdrAnon_TransactionV0_Ext) XdrUnionTag() XdrNum32 { - return XDR_int32(&u.V) +var _XdrValues_MemoType = map[string]int32{ + "MEMO_NONE": int32(MEMO_NONE), + "MEMO_TEXT": int32(MEMO_TEXT), + "MEMO_ID": int32(MEMO_ID), + "MEMO_HASH": int32(MEMO_HASH), + "MEMO_RETURN": int32(MEMO_RETURN), } -func (u *XdrAnon_TransactionV0_Ext) XdrUnionTagName() string { - return "V" + +func (MemoType) XdrEnumNames() map[int32]string { + return _XdrNames_MemoType } -func (u *XdrAnon_TransactionV0_Ext) XdrUnionBody() XdrType { - switch u.V { - case 0: - return nil +func (v MemoType) String() string { + if s, ok := _XdrNames_MemoType[int32(v)]; ok { + return s } - return nil + return fmt.Sprintf("MemoType#%d", v) } -func (u *XdrAnon_TransactionV0_Ext) XdrUnionBodyName() string { - switch u.V { - case 0: - return "" +func (v *MemoType) Scan(ss fmt.ScanState, _ rune) error { + if tok, err := ss.Token(true, XdrSymChar); err != nil { + return err + } else { + stok := string(tok) + if val, ok := _XdrValues_MemoType[stok]; ok { + *v = MemoType(val) + return nil + } else if stok == "MemoType" { + if n, err := fmt.Fscanf(ss, "#%d", (*int32)(v)); n == 1 && err == nil { + return nil + } + } + return XdrError(fmt.Sprintf("%s is not a valid MemoType.", stok)) } - return "" } +func (v MemoType) GetU32() uint32 { return uint32(v) } +func (v *MemoType) SetU32(n uint32) { *v = MemoType(n) } +func (v *MemoType) XdrPointer() interface{} { return v } +func (MemoType) XdrTypeName() string { return "MemoType" } +func (v MemoType) XdrValue() interface{} { return v } +func (v *MemoType) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -type XdrType_XdrAnon_TransactionV0_Ext = *XdrAnon_TransactionV0_Ext - -func (v *XdrAnon_TransactionV0_Ext) XdrPointer() interface{} { return v } -func (XdrAnon_TransactionV0_Ext) XdrTypeName() string { return "XdrAnon_TransactionV0_Ext" } -func (v XdrAnon_TransactionV0_Ext) XdrValue() interface{} { return v } -func (v *XdrAnon_TransactionV0_Ext) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -func (u *XdrAnon_TransactionV0_Ext) XdrRecurse(x XDR, name string) { - if name != "" { - name = x.Sprintf("%s.", name) - } - XDR_int32(&u.V).XdrMarshal(x, x.Sprintf("%sv", name)) - switch u.V { - case 0: - return - } - XdrPanic("invalid V (%v) in XdrAnon_TransactionV0_Ext", u.V) -} -func XDR_XdrAnon_TransactionV0_Ext(v *XdrAnon_TransactionV0_Ext) *XdrAnon_TransactionV0_Ext { return v } +type XdrType_MemoType = *MemoType -type _XdrVec_100_Operation []Operation +func XDR_MemoType(v *MemoType) *MemoType { return v } -func (_XdrVec_100_Operation) XdrBound() uint32 { - const bound uint32 = 100 // Force error if not const or doesn't fit - return bound +var _XdrTags_Memo = map[int32]bool{ + XdrToI32(MEMO_NONE): true, + XdrToI32(MEMO_TEXT): true, + XdrToI32(MEMO_ID): true, + XdrToI32(MEMO_HASH): true, + XdrToI32(MEMO_RETURN): true, } -func (_XdrVec_100_Operation) XdrCheckLen(length uint32) { - if length > uint32(100) { - XdrPanic("_XdrVec_100_Operation length %d exceeds bound 100", length) - } else if int(length) < 0 { - XdrPanic("_XdrVec_100_Operation length %d exceeds max int", length) - } + +func (_ Memo) XdrValidTags() map[int32]bool { + return _XdrTags_Memo } -func (v _XdrVec_100_Operation) GetVecLen() uint32 { return uint32(len(v)) } -func (v *_XdrVec_100_Operation) SetVecLen(length uint32) { - v.XdrCheckLen(length) - if int(length) <= cap(*v) { - if int(length) != len(*v) { - *v = (*v)[:int(length)] +func (u *Memo) Text() *string { + switch u.Type { + case MEMO_TEXT: + if v, ok := u._u.(*string); ok { + return v + } else { + var zero string + u._u = &zero + return &zero } - return + default: + XdrPanic("Memo.Text accessed when Type == %v", u.Type) + return nil } - newcap := 2 * cap(*v) - if newcap < int(length) { // also catches overflow where 2*cap < 0 - newcap = int(length) - } else if bound := uint(100); uint(newcap) > bound { - if int(bound) < 0 { - bound = ^uint(0) >> 1 +} +func (u *Memo) Id() *Uint64 { + switch u.Type { + case MEMO_ID: + if v, ok := u._u.(*Uint64); ok { + return v + } else { + var zero Uint64 + u._u = &zero + return &zero } - newcap = int(bound) + default: + XdrPanic("Memo.Id accessed when Type == %v", u.Type) + return nil } - nv := make([]Operation, int(length), newcap) - copy(nv, *v) - *v = nv } -func (v *_XdrVec_100_Operation) XdrMarshalN(x XDR, name string, n uint32) { - v.XdrCheckLen(n) - for i := 0; i < int(n); i++ { - if i >= len(*v) { - v.SetVecLen(uint32(i + 1)) - } - XDR_Operation(&(*v)[i]).XdrMarshal(x, x.Sprintf("%s[%d]", name, i)) - } - if int(n) < len(*v) { - *v = (*v)[:int(n)] - } -} -func (v *_XdrVec_100_Operation) XdrRecurse(x XDR, name string) { - size := XdrSize{Size: uint32(len(*v)), Bound: 100} - x.Marshal(name, &size) - v.XdrMarshalN(x, name, size.Size) -} -func (_XdrVec_100_Operation) XdrTypeName() string { return "Operation<>" } -func (v *_XdrVec_100_Operation) XdrPointer() interface{} { return (*[]Operation)(v) } -func (v _XdrVec_100_Operation) XdrValue() interface{} { return ([]Operation)(v) } -func (v *_XdrVec_100_Operation) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } - -type XdrType_TransactionV0 = *TransactionV0 - -func (v *TransactionV0) XdrPointer() interface{} { return v } -func (TransactionV0) XdrTypeName() string { return "TransactionV0" } -func (v TransactionV0) XdrValue() interface{} { return v } -func (v *TransactionV0) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -func (v *TransactionV0) XdrRecurse(x XDR, name string) { - if name != "" { - name = x.Sprintf("%s.", name) - } - x.Marshal(x.Sprintf("%ssourceAccountEd25519", name), XDR_Uint256(&v.SourceAccountEd25519)) - x.Marshal(x.Sprintf("%sfee", name), XDR_Uint32(&v.Fee)) - x.Marshal(x.Sprintf("%sseqNum", name), XDR_SequenceNumber(&v.SeqNum)) - x.Marshal(x.Sprintf("%stimeBounds", name), _XdrPtr_TimeBounds{&v.TimeBounds}) - x.Marshal(x.Sprintf("%smemo", name), XDR_Memo(&v.Memo)) - x.Marshal(x.Sprintf("%soperations", name), (*_XdrVec_100_Operation)(&v.Operations)) - x.Marshal(x.Sprintf("%sext", name), XDR_XdrAnon_TransactionV0_Ext(&v.Ext)) -} -func XDR_TransactionV0(v *TransactionV0) *TransactionV0 { return v } - -type _XdrVec_20_DecoratedSignature []DecoratedSignature -func (_XdrVec_20_DecoratedSignature) XdrBound() uint32 { - const bound uint32 = 20 // Force error if not const or doesn't fit - return bound -} -func (_XdrVec_20_DecoratedSignature) XdrCheckLen(length uint32) { - if length > uint32(20) { - XdrPanic("_XdrVec_20_DecoratedSignature length %d exceeds bound 20", length) - } else if int(length) < 0 { - XdrPanic("_XdrVec_20_DecoratedSignature length %d exceeds max int", length) - } -} -func (v _XdrVec_20_DecoratedSignature) GetVecLen() uint32 { return uint32(len(v)) } -func (v *_XdrVec_20_DecoratedSignature) SetVecLen(length uint32) { - v.XdrCheckLen(length) - if int(length) <= cap(*v) { - if int(length) != len(*v) { - *v = (*v)[:int(length)] - } - return - } - newcap := 2 * cap(*v) - if newcap < int(length) { // also catches overflow where 2*cap < 0 - newcap = int(length) - } else if bound := uint(20); uint(newcap) > bound { - if int(bound) < 0 { - bound = ^uint(0) >> 1 - } - newcap = int(bound) - } - nv := make([]DecoratedSignature, int(length), newcap) - copy(nv, *v) - *v = nv -} -func (v *_XdrVec_20_DecoratedSignature) XdrMarshalN(x XDR, name string, n uint32) { - v.XdrCheckLen(n) - for i := 0; i < int(n); i++ { - if i >= len(*v) { - v.SetVecLen(uint32(i + 1)) +// the hash of what to pull from the content server +func (u *Memo) Hash() *Hash { + switch u.Type { + case MEMO_HASH: + if v, ok := u._u.(*Hash); ok { + return v + } else { + var zero Hash + u._u = &zero + return &zero } - XDR_DecoratedSignature(&(*v)[i]).XdrMarshal(x, x.Sprintf("%s[%d]", name, i)) - } - if int(n) < len(*v) { - *v = (*v)[:int(n)] + default: + XdrPanic("Memo.Hash accessed when Type == %v", u.Type) + return nil } } -func (v *_XdrVec_20_DecoratedSignature) XdrRecurse(x XDR, name string) { - size := XdrSize{Size: uint32(len(*v)), Bound: 20} - x.Marshal(name, &size) - v.XdrMarshalN(x, name, size.Size) -} -func (_XdrVec_20_DecoratedSignature) XdrTypeName() string { return "DecoratedSignature<>" } -func (v *_XdrVec_20_DecoratedSignature) XdrPointer() interface{} { return (*[]DecoratedSignature)(v) } -func (v _XdrVec_20_DecoratedSignature) XdrValue() interface{} { return ([]DecoratedSignature)(v) } -func (v *_XdrVec_20_DecoratedSignature) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } - -type XdrType_TransactionV0Envelope = *TransactionV0Envelope -func (v *TransactionV0Envelope) XdrPointer() interface{} { return v } -func (TransactionV0Envelope) XdrTypeName() string { return "TransactionV0Envelope" } -func (v TransactionV0Envelope) XdrValue() interface{} { return v } -func (v *TransactionV0Envelope) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -func (v *TransactionV0Envelope) XdrRecurse(x XDR, name string) { - if name != "" { - name = x.Sprintf("%s.", name) +// the hash of the tx you are rejecting +func (u *Memo) RetHash() *Hash { + switch u.Type { + case MEMO_RETURN: + if v, ok := u._u.(*Hash); ok { + return v + } else { + var zero Hash + u._u = &zero + return &zero + } + default: + XdrPanic("Memo.RetHash accessed when Type == %v", u.Type) + return nil } - x.Marshal(x.Sprintf("%stx", name), XDR_TransactionV0(&v.Tx)) - x.Marshal(x.Sprintf("%ssignatures", name), (*_XdrVec_20_DecoratedSignature)(&v.Signatures)) -} -func XDR_TransactionV0Envelope(v *TransactionV0Envelope) *TransactionV0Envelope { return v } - -var _XdrTags_XdrAnon_Transaction_Ext = map[int32]bool{ - XdrToI32(0): true, -} - -func (_ XdrAnon_Transaction_Ext) XdrValidTags() map[int32]bool { - return _XdrTags_XdrAnon_Transaction_Ext } -func (u XdrAnon_Transaction_Ext) XdrValid() bool { - switch u.V { - case 0: +func (u Memo) XdrValid() bool { + switch u.Type { + case MEMO_NONE, MEMO_TEXT, MEMO_ID, MEMO_HASH, MEMO_RETURN: return true } return false } -func (u *XdrAnon_Transaction_Ext) XdrUnionTag() XdrNum32 { - return XDR_int32(&u.V) +func (u *Memo) XdrUnionTag() XdrNum32 { + return XDR_MemoType(&u.Type) } -func (u *XdrAnon_Transaction_Ext) XdrUnionTagName() string { - return "V" +func (u *Memo) XdrUnionTagName() string { + return "Type" } -func (u *XdrAnon_Transaction_Ext) XdrUnionBody() XdrType { - switch u.V { - case 0: +func (u *Memo) XdrUnionBody() XdrType { + switch u.Type { + case MEMO_NONE: return nil + case MEMO_TEXT: + return XdrString{u.Text(), 28} + case MEMO_ID: + return XDR_Uint64(u.Id()) + case MEMO_HASH: + return XDR_Hash(u.Hash()) + case MEMO_RETURN: + return XDR_Hash(u.RetHash()) } return nil } -func (u *XdrAnon_Transaction_Ext) XdrUnionBodyName() string { - switch u.V { - case 0: +func (u *Memo) XdrUnionBodyName() string { + switch u.Type { + case MEMO_NONE: return "" + case MEMO_TEXT: + return "Text" + case MEMO_ID: + return "Id" + case MEMO_HASH: + return "Hash" + case MEMO_RETURN: + return "RetHash" } return "" } -type XdrType_XdrAnon_Transaction_Ext = *XdrAnon_Transaction_Ext +type XdrType_Memo = *Memo -func (v *XdrAnon_Transaction_Ext) XdrPointer() interface{} { return v } -func (XdrAnon_Transaction_Ext) XdrTypeName() string { return "XdrAnon_Transaction_Ext" } -func (v XdrAnon_Transaction_Ext) XdrValue() interface{} { return v } -func (v *XdrAnon_Transaction_Ext) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -func (u *XdrAnon_Transaction_Ext) XdrRecurse(x XDR, name string) { +func (v *Memo) XdrPointer() interface{} { return v } +func (Memo) XdrTypeName() string { return "Memo" } +func (v Memo) XdrValue() interface{} { return v } +func (v *Memo) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (u *Memo) XdrRecurse(x XDR, name string) { if name != "" { name = x.Sprintf("%s.", name) } - XDR_int32(&u.V).XdrMarshal(x, x.Sprintf("%sv", name)) - switch u.V { - case 0: + XDR_MemoType(&u.Type).XdrMarshal(x, x.Sprintf("%stype", name)) + switch u.Type { + case MEMO_NONE: + return + case MEMO_TEXT: + x.Marshal(x.Sprintf("%stext", name), XdrString{u.Text(), 28}) + return + case MEMO_ID: + x.Marshal(x.Sprintf("%sid", name), XDR_Uint64(u.Id())) + return + case MEMO_HASH: + x.Marshal(x.Sprintf("%shash", name), XDR_Hash(u.Hash())) + return + case MEMO_RETURN: + x.Marshal(x.Sprintf("%sretHash", name), XDR_Hash(u.RetHash())) return } - XdrPanic("invalid V (%v) in XdrAnon_Transaction_Ext", u.V) + XdrPanic("invalid Type (%v) in Memo", u.Type) } -func XDR_XdrAnon_Transaction_Ext(v *XdrAnon_Transaction_Ext) *XdrAnon_Transaction_Ext { return v } +func XDR_Memo(v *Memo) *Memo { return v } -type XdrType_Transaction = *Transaction +type XdrType_TimeBounds = *TimeBounds -func (v *Transaction) XdrPointer() interface{} { return v } -func (Transaction) XdrTypeName() string { return "Transaction" } -func (v Transaction) XdrValue() interface{} { return v } -func (v *Transaction) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -func (v *Transaction) XdrRecurse(x XDR, name string) { +func (v *TimeBounds) XdrPointer() interface{} { return v } +func (TimeBounds) XdrTypeName() string { return "TimeBounds" } +func (v TimeBounds) XdrValue() interface{} { return v } +func (v *TimeBounds) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v *TimeBounds) XdrRecurse(x XDR, name string) { if name != "" { name = x.Sprintf("%s.", name) } - x.Marshal(x.Sprintf("%ssourceAccount", name), XDR_MuxedAccount(&v.SourceAccount)) - x.Marshal(x.Sprintf("%sfee", name), XDR_Uint32(&v.Fee)) - x.Marshal(x.Sprintf("%sseqNum", name), XDR_SequenceNumber(&v.SeqNum)) - x.Marshal(x.Sprintf("%scond", name), XDR_Preconditions(&v.Cond)) - x.Marshal(x.Sprintf("%smemo", name), XDR_Memo(&v.Memo)) - x.Marshal(x.Sprintf("%soperations", name), (*_XdrVec_100_Operation)(&v.Operations)) - x.Marshal(x.Sprintf("%sext", name), XDR_XdrAnon_Transaction_Ext(&v.Ext)) + x.Marshal(x.Sprintf("%sminTime", name), XDR_TimePoint(&v.MinTime)) + x.Marshal(x.Sprintf("%smaxTime", name), XDR_TimePoint(&v.MaxTime)) } -func XDR_Transaction(v *Transaction) *Transaction { return v } +func XDR_TimeBounds(v *TimeBounds) *TimeBounds { return v } -type XdrType_TransactionV1Envelope = *TransactionV1Envelope +type XdrType_LedgerBounds = *LedgerBounds -func (v *TransactionV1Envelope) XdrPointer() interface{} { return v } -func (TransactionV1Envelope) XdrTypeName() string { return "TransactionV1Envelope" } -func (v TransactionV1Envelope) XdrValue() interface{} { return v } -func (v *TransactionV1Envelope) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -func (v *TransactionV1Envelope) XdrRecurse(x XDR, name string) { +func (v *LedgerBounds) XdrPointer() interface{} { return v } +func (LedgerBounds) XdrTypeName() string { return "LedgerBounds" } +func (v LedgerBounds) XdrValue() interface{} { return v } +func (v *LedgerBounds) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v *LedgerBounds) XdrRecurse(x XDR, name string) { if name != "" { name = x.Sprintf("%s.", name) } - x.Marshal(x.Sprintf("%stx", name), XDR_Transaction(&v.Tx)) - x.Marshal(x.Sprintf("%ssignatures", name), (*_XdrVec_20_DecoratedSignature)(&v.Signatures)) + x.Marshal(x.Sprintf("%sminLedger", name), XDR_Uint32(&v.MinLedger)) + x.Marshal(x.Sprintf("%smaxLedger", name), XDR_Uint32(&v.MaxLedger)) } -func XDR_TransactionV1Envelope(v *TransactionV1Envelope) *TransactionV1Envelope { return v } +func XDR_LedgerBounds(v *LedgerBounds) *LedgerBounds { return v } -var _XdrTags_XdrAnon_FeeBumpTransaction_InnerTx = map[int32]bool{ - XdrToI32(ENVELOPE_TYPE_TX): true, +type _XdrPtr_TimeBounds struct { + p **TimeBounds } +type _ptrflag_TimeBounds _XdrPtr_TimeBounds -func (_ XdrAnon_FeeBumpTransaction_InnerTx) XdrValidTags() map[int32]bool { - return _XdrTags_XdrAnon_FeeBumpTransaction_InnerTx -} -func (u *XdrAnon_FeeBumpTransaction_InnerTx) V1() *TransactionV1Envelope { - switch u.Type { - case ENVELOPE_TYPE_TX: - if v, ok := u._u.(*TransactionV1Envelope); ok { - return v - } else { - var zero TransactionV1Envelope - u._u = &zero - return &zero - } - default: - XdrPanic("XdrAnon_FeeBumpTransaction_InnerTx.V1 accessed when Type == %v", u.Type) - return nil +func (v _ptrflag_TimeBounds) String() string { + if *v.p == nil { + return "nil" } + return "non-nil" } -func (u XdrAnon_FeeBumpTransaction_InnerTx) XdrValid() bool { - switch u.Type { - case ENVELOPE_TYPE_TX: - return true +func (v _ptrflag_TimeBounds) Scan(ss fmt.ScanState, r rune) error { + tok, err := ss.Token(true, func(c rune) bool { + return c == '-' || (c >= 'a' && c <= 'z') + }) + if err != nil { + return err } - return false -} -func (u *XdrAnon_FeeBumpTransaction_InnerTx) XdrUnionTag() XdrNum32 { - return XDR_EnvelopeType(&u.Type) -} -func (u *XdrAnon_FeeBumpTransaction_InnerTx) XdrUnionTagName() string { - return "Type" -} -func (u *XdrAnon_FeeBumpTransaction_InnerTx) XdrUnionBody() XdrType { - switch u.Type { - case ENVELOPE_TYPE_TX: - return XDR_TransactionV1Envelope(u.V1()) + switch string(tok) { + case "nil": + v.SetU32(0) + case "non-nil": + v.SetU32(1) + default: + return XdrError("TimeBounds flag should be \"nil\" or \"non-nil\"") } return nil } -func (u *XdrAnon_FeeBumpTransaction_InnerTx) XdrUnionBodyName() string { - switch u.Type { - case ENVELOPE_TYPE_TX: - return "V1" +func (v _ptrflag_TimeBounds) GetU32() uint32 { + if *v.p == nil { + return 0 } - return "" -} - -type XdrType_XdrAnon_FeeBumpTransaction_InnerTx = *XdrAnon_FeeBumpTransaction_InnerTx - -func (v *XdrAnon_FeeBumpTransaction_InnerTx) XdrPointer() interface{} { return v } -func (XdrAnon_FeeBumpTransaction_InnerTx) XdrTypeName() string { - return "XdrAnon_FeeBumpTransaction_InnerTx" + return 1 } -func (v XdrAnon_FeeBumpTransaction_InnerTx) XdrValue() interface{} { return v } -func (v *XdrAnon_FeeBumpTransaction_InnerTx) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -func (u *XdrAnon_FeeBumpTransaction_InnerTx) XdrRecurse(x XDR, name string) { - if name != "" { - name = x.Sprintf("%s.", name) +func (v _ptrflag_TimeBounds) SetU32(nv uint32) { + switch nv { + case 0: + *v.p = nil + case 1: + if *v.p == nil { + *v.p = new(TimeBounds) + } + default: + XdrPanic("*TimeBounds present flag value %d should be 0 or 1", nv) } - XDR_EnvelopeType(&u.Type).XdrMarshal(x, x.Sprintf("%stype", name)) - switch u.Type { - case ENVELOPE_TYPE_TX: - x.Marshal(x.Sprintf("%sv1", name), XDR_TransactionV1Envelope(u.V1())) - return +} +func (_ptrflag_TimeBounds) XdrTypeName() string { return "TimeBounds?" } +func (v _ptrflag_TimeBounds) XdrPointer() interface{} { return nil } +func (v _ptrflag_TimeBounds) XdrValue() interface{} { return v.GetU32() != 0 } +func (v _ptrflag_TimeBounds) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v _ptrflag_TimeBounds) XdrBound() uint32 { return 1 } +func (v _XdrPtr_TimeBounds) GetPresent() bool { return *v.p != nil } +func (v _XdrPtr_TimeBounds) SetPresent(present bool) { + if !present { + *v.p = nil + } else if *v.p == nil { + *v.p = new(TimeBounds) } - XdrPanic("invalid Type (%v) in XdrAnon_FeeBumpTransaction_InnerTx", u.Type) } -func (v *XdrAnon_FeeBumpTransaction_InnerTx) XdrInitialize() { - var zero EnvelopeType - switch zero { - case ENVELOPE_TYPE_TX: - default: - if v.Type == zero { - v.Type = ENVELOPE_TYPE_TX - } +func (v _XdrPtr_TimeBounds) XdrMarshalValue(x XDR, name string) { + if *v.p != nil { + XDR_TimeBounds(*v.p).XdrMarshal(x, name) } } -func XDR_XdrAnon_FeeBumpTransaction_InnerTx(v *XdrAnon_FeeBumpTransaction_InnerTx) *XdrAnon_FeeBumpTransaction_InnerTx { - return v +func (v _XdrPtr_TimeBounds) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v _XdrPtr_TimeBounds) XdrRecurse(x XDR, name string) { + x.Marshal(name, _ptrflag_TimeBounds(v)) + v.XdrMarshalValue(x, name) } +func (_XdrPtr_TimeBounds) XdrTypeName() string { return "TimeBounds*" } +func (v _XdrPtr_TimeBounds) XdrPointer() interface{} { return v.p } +func (v _XdrPtr_TimeBounds) XdrValue() interface{} { return *v.p } -var _XdrTags_XdrAnon_FeeBumpTransaction_Ext = map[int32]bool{ - XdrToI32(0): true, +type _XdrPtr_LedgerBounds struct { + p **LedgerBounds } +type _ptrflag_LedgerBounds _XdrPtr_LedgerBounds -func (_ XdrAnon_FeeBumpTransaction_Ext) XdrValidTags() map[int32]bool { - return _XdrTags_XdrAnon_FeeBumpTransaction_Ext -} -func (u XdrAnon_FeeBumpTransaction_Ext) XdrValid() bool { - switch u.V { - case 0: - return true +func (v _ptrflag_LedgerBounds) String() string { + if *v.p == nil { + return "nil" } - return false -} -func (u *XdrAnon_FeeBumpTransaction_Ext) XdrUnionTag() XdrNum32 { - return XDR_int32(&u.V) -} -func (u *XdrAnon_FeeBumpTransaction_Ext) XdrUnionTagName() string { - return "V" + return "non-nil" } -func (u *XdrAnon_FeeBumpTransaction_Ext) XdrUnionBody() XdrType { - switch u.V { - case 0: - return nil +func (v _ptrflag_LedgerBounds) Scan(ss fmt.ScanState, r rune) error { + tok, err := ss.Token(true, func(c rune) bool { + return c == '-' || (c >= 'a' && c <= 'z') + }) + if err != nil { + return err + } + switch string(tok) { + case "nil": + v.SetU32(0) + case "non-nil": + v.SetU32(1) + default: + return XdrError("LedgerBounds flag should be \"nil\" or \"non-nil\"") } return nil } -func (u *XdrAnon_FeeBumpTransaction_Ext) XdrUnionBodyName() string { - switch u.V { - case 0: - return "" +func (v _ptrflag_LedgerBounds) GetU32() uint32 { + if *v.p == nil { + return 0 } - return "" + return 1 } - -type XdrType_XdrAnon_FeeBumpTransaction_Ext = *XdrAnon_FeeBumpTransaction_Ext - -func (v *XdrAnon_FeeBumpTransaction_Ext) XdrPointer() interface{} { return v } -func (XdrAnon_FeeBumpTransaction_Ext) XdrTypeName() string { return "XdrAnon_FeeBumpTransaction_Ext" } -func (v XdrAnon_FeeBumpTransaction_Ext) XdrValue() interface{} { return v } -func (v *XdrAnon_FeeBumpTransaction_Ext) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -func (u *XdrAnon_FeeBumpTransaction_Ext) XdrRecurse(x XDR, name string) { - if name != "" { - name = x.Sprintf("%s.", name) - } - XDR_int32(&u.V).XdrMarshal(x, x.Sprintf("%sv", name)) - switch u.V { +func (v _ptrflag_LedgerBounds) SetU32(nv uint32) { + switch nv { case 0: - return + *v.p = nil + case 1: + if *v.p == nil { + *v.p = new(LedgerBounds) + } + default: + XdrPanic("*LedgerBounds present flag value %d should be 0 or 1", nv) } - XdrPanic("invalid V (%v) in XdrAnon_FeeBumpTransaction_Ext", u.V) -} -func XDR_XdrAnon_FeeBumpTransaction_Ext(v *XdrAnon_FeeBumpTransaction_Ext) *XdrAnon_FeeBumpTransaction_Ext { - return v } - -type XdrType_FeeBumpTransaction = *FeeBumpTransaction - -func (v *FeeBumpTransaction) XdrPointer() interface{} { return v } -func (FeeBumpTransaction) XdrTypeName() string { return "FeeBumpTransaction" } -func (v FeeBumpTransaction) XdrValue() interface{} { return v } -func (v *FeeBumpTransaction) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -func (v *FeeBumpTransaction) XdrRecurse(x XDR, name string) { - if name != "" { - name = x.Sprintf("%s.", name) +func (_ptrflag_LedgerBounds) XdrTypeName() string { return "LedgerBounds?" } +func (v _ptrflag_LedgerBounds) XdrPointer() interface{} { return nil } +func (v _ptrflag_LedgerBounds) XdrValue() interface{} { return v.GetU32() != 0 } +func (v _ptrflag_LedgerBounds) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v _ptrflag_LedgerBounds) XdrBound() uint32 { return 1 } +func (v _XdrPtr_LedgerBounds) GetPresent() bool { return *v.p != nil } +func (v _XdrPtr_LedgerBounds) SetPresent(present bool) { + if !present { + *v.p = nil + } else if *v.p == nil { + *v.p = new(LedgerBounds) } - x.Marshal(x.Sprintf("%sfeeSource", name), XDR_MuxedAccount(&v.FeeSource)) - x.Marshal(x.Sprintf("%sfee", name), XDR_Int64(&v.Fee)) - x.Marshal(x.Sprintf("%sinnerTx", name), XDR_XdrAnon_FeeBumpTransaction_InnerTx(&v.InnerTx)) - x.Marshal(x.Sprintf("%sext", name), XDR_XdrAnon_FeeBumpTransaction_Ext(&v.Ext)) } -func XDR_FeeBumpTransaction(v *FeeBumpTransaction) *FeeBumpTransaction { return v } - -type XdrType_FeeBumpTransactionEnvelope = *FeeBumpTransactionEnvelope - -func (v *FeeBumpTransactionEnvelope) XdrPointer() interface{} { return v } -func (FeeBumpTransactionEnvelope) XdrTypeName() string { return "FeeBumpTransactionEnvelope" } -func (v FeeBumpTransactionEnvelope) XdrValue() interface{} { return v } -func (v *FeeBumpTransactionEnvelope) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -func (v *FeeBumpTransactionEnvelope) XdrRecurse(x XDR, name string) { - if name != "" { - name = x.Sprintf("%s.", name) +func (v _XdrPtr_LedgerBounds) XdrMarshalValue(x XDR, name string) { + if *v.p != nil { + XDR_LedgerBounds(*v.p).XdrMarshal(x, name) } - x.Marshal(x.Sprintf("%stx", name), XDR_FeeBumpTransaction(&v.Tx)) - x.Marshal(x.Sprintf("%ssignatures", name), (*_XdrVec_20_DecoratedSignature)(&v.Signatures)) } -func XDR_FeeBumpTransactionEnvelope(v *FeeBumpTransactionEnvelope) *FeeBumpTransactionEnvelope { - return v +func (v _XdrPtr_LedgerBounds) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v _XdrPtr_LedgerBounds) XdrRecurse(x XDR, name string) { + x.Marshal(name, _ptrflag_LedgerBounds(v)) + v.XdrMarshalValue(x, name) } +func (_XdrPtr_LedgerBounds) XdrTypeName() string { return "LedgerBounds*" } +func (v _XdrPtr_LedgerBounds) XdrPointer() interface{} { return v.p } +func (v _XdrPtr_LedgerBounds) XdrValue() interface{} { return *v.p } -var _XdrTags_TransactionEnvelope = map[int32]bool{ - XdrToI32(ENVELOPE_TYPE_TX_V0): true, - XdrToI32(ENVELOPE_TYPE_TX): true, - XdrToI32(ENVELOPE_TYPE_TX_FEE_BUMP): true, +type _XdrPtr_SequenceNumber struct { + p **SequenceNumber } +type _ptrflag_SequenceNumber _XdrPtr_SequenceNumber -func (_ TransactionEnvelope) XdrValidTags() map[int32]bool { - return _XdrTags_TransactionEnvelope +func (v _ptrflag_SequenceNumber) String() string { + if *v.p == nil { + return "nil" + } + return "non-nil" } -func (u *TransactionEnvelope) V0() *TransactionV0Envelope { - switch u.Type { - case ENVELOPE_TYPE_TX_V0: - if v, ok := u._u.(*TransactionV0Envelope); ok { - return v - } else { - var zero TransactionV0Envelope - u._u = &zero - return &zero +func (v _ptrflag_SequenceNumber) Scan(ss fmt.ScanState, r rune) error { + tok, err := ss.Token(true, func(c rune) bool { + return c == '-' || (c >= 'a' && c <= 'z') + }) + if err != nil { + return err + } + switch string(tok) { + case "nil": + v.SetU32(0) + case "non-nil": + v.SetU32(1) + default: + return XdrError("SequenceNumber flag should be \"nil\" or \"non-nil\"") + } + return nil +} +func (v _ptrflag_SequenceNumber) GetU32() uint32 { + if *v.p == nil { + return 0 + } + return 1 +} +func (v _ptrflag_SequenceNumber) SetU32(nv uint32) { + switch nv { + case 0: + *v.p = nil + case 1: + if *v.p == nil { + *v.p = new(SequenceNumber) } default: - XdrPanic("TransactionEnvelope.V0 accessed when Type == %v", u.Type) - return nil + XdrPanic("*SequenceNumber present flag value %d should be 0 or 1", nv) } } -func (u *TransactionEnvelope) V1() *TransactionV1Envelope { +func (_ptrflag_SequenceNumber) XdrTypeName() string { return "SequenceNumber?" } +func (v _ptrflag_SequenceNumber) XdrPointer() interface{} { return nil } +func (v _ptrflag_SequenceNumber) XdrValue() interface{} { return v.GetU32() != 0 } +func (v _ptrflag_SequenceNumber) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v _ptrflag_SequenceNumber) XdrBound() uint32 { return 1 } +func (v _XdrPtr_SequenceNumber) GetPresent() bool { return *v.p != nil } +func (v _XdrPtr_SequenceNumber) SetPresent(present bool) { + if !present { + *v.p = nil + } else if *v.p == nil { + *v.p = new(SequenceNumber) + } +} +func (v _XdrPtr_SequenceNumber) XdrMarshalValue(x XDR, name string) { + if *v.p != nil { + XDR_SequenceNumber(*v.p).XdrMarshal(x, name) + } +} +func (v _XdrPtr_SequenceNumber) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v _XdrPtr_SequenceNumber) XdrRecurse(x XDR, name string) { + x.Marshal(name, _ptrflag_SequenceNumber(v)) + v.XdrMarshalValue(x, name) +} +func (_XdrPtr_SequenceNumber) XdrTypeName() string { return "SequenceNumber*" } +func (v _XdrPtr_SequenceNumber) XdrPointer() interface{} { return v.p } +func (v _XdrPtr_SequenceNumber) XdrValue() interface{} { return *v.p } + +type _XdrVec_2_SignerKey []SignerKey + +func (_XdrVec_2_SignerKey) XdrBound() uint32 { + const bound uint32 = 2 // Force error if not const or doesn't fit + return bound +} +func (_XdrVec_2_SignerKey) XdrCheckLen(length uint32) { + if length > uint32(2) { + XdrPanic("_XdrVec_2_SignerKey length %d exceeds bound 2", length) + } else if int(length) < 0 { + XdrPanic("_XdrVec_2_SignerKey length %d exceeds max int", length) + } +} +func (v _XdrVec_2_SignerKey) GetVecLen() uint32 { return uint32(len(v)) } +func (v *_XdrVec_2_SignerKey) SetVecLen(length uint32) { + v.XdrCheckLen(length) + if int(length) <= cap(*v) { + if int(length) != len(*v) { + *v = (*v)[:int(length)] + } + return + } + newcap := 2 * cap(*v) + if newcap < int(length) { // also catches overflow where 2*cap < 0 + newcap = int(length) + } else if bound := uint(2); uint(newcap) > bound { + if int(bound) < 0 { + bound = ^uint(0) >> 1 + } + newcap = int(bound) + } + nv := make([]SignerKey, int(length), newcap) + copy(nv, *v) + *v = nv +} +func (v *_XdrVec_2_SignerKey) XdrMarshalN(x XDR, name string, n uint32) { + v.XdrCheckLen(n) + for i := 0; i < int(n); i++ { + if i >= len(*v) { + v.SetVecLen(uint32(i + 1)) + } + XDR_SignerKey(&(*v)[i]).XdrMarshal(x, x.Sprintf("%s[%d]", name, i)) + } + if int(n) < len(*v) { + *v = (*v)[:int(n)] + } +} +func (v *_XdrVec_2_SignerKey) XdrRecurse(x XDR, name string) { + size := XdrSize{Size: uint32(len(*v)), Bound: 2} + x.Marshal(name, &size) + v.XdrMarshalN(x, name, size.Size) +} +func (_XdrVec_2_SignerKey) XdrTypeName() string { return "SignerKey<>" } +func (v *_XdrVec_2_SignerKey) XdrPointer() interface{} { return (*[]SignerKey)(v) } +func (v _XdrVec_2_SignerKey) XdrValue() interface{} { return ([]SignerKey)(v) } +func (v *_XdrVec_2_SignerKey) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } + +type XdrType_PreconditionsV2 = *PreconditionsV2 + +func (v *PreconditionsV2) XdrPointer() interface{} { return v } +func (PreconditionsV2) XdrTypeName() string { return "PreconditionsV2" } +func (v PreconditionsV2) XdrValue() interface{} { return v } +func (v *PreconditionsV2) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v *PreconditionsV2) XdrRecurse(x XDR, name string) { + if name != "" { + name = x.Sprintf("%s.", name) + } + x.Marshal(x.Sprintf("%stimeBounds", name), _XdrPtr_TimeBounds{&v.TimeBounds}) + x.Marshal(x.Sprintf("%sledgerBounds", name), _XdrPtr_LedgerBounds{&v.LedgerBounds}) + x.Marshal(x.Sprintf("%sminSeqNum", name), _XdrPtr_SequenceNumber{&v.MinSeqNum}) + x.Marshal(x.Sprintf("%sminSeqAge", name), XDR_Duration(&v.MinSeqAge)) + x.Marshal(x.Sprintf("%sminSeqLedgerGap", name), XDR_Uint32(&v.MinSeqLedgerGap)) + x.Marshal(x.Sprintf("%sextraSigners", name), (*_XdrVec_2_SignerKey)(&v.ExtraSigners)) +} +func XDR_PreconditionsV2(v *PreconditionsV2) *PreconditionsV2 { return v } + +var _XdrNames_PreconditionType = map[int32]string{ + int32(PRECOND_NONE): "PRECOND_NONE", + int32(PRECOND_TIME): "PRECOND_TIME", + int32(PRECOND_V2): "PRECOND_V2", +} +var _XdrValues_PreconditionType = map[string]int32{ + "PRECOND_NONE": int32(PRECOND_NONE), + "PRECOND_TIME": int32(PRECOND_TIME), + "PRECOND_V2": int32(PRECOND_V2), +} + +func (PreconditionType) XdrEnumNames() map[int32]string { + return _XdrNames_PreconditionType +} +func (v PreconditionType) String() string { + if s, ok := _XdrNames_PreconditionType[int32(v)]; ok { + return s + } + return fmt.Sprintf("PreconditionType#%d", v) +} +func (v *PreconditionType) Scan(ss fmt.ScanState, _ rune) error { + if tok, err := ss.Token(true, XdrSymChar); err != nil { + return err + } else { + stok := string(tok) + if val, ok := _XdrValues_PreconditionType[stok]; ok { + *v = PreconditionType(val) + return nil + } else if stok == "PreconditionType" { + if n, err := fmt.Fscanf(ss, "#%d", (*int32)(v)); n == 1 && err == nil { + return nil + } + } + return XdrError(fmt.Sprintf("%s is not a valid PreconditionType.", stok)) + } +} +func (v PreconditionType) GetU32() uint32 { return uint32(v) } +func (v *PreconditionType) SetU32(n uint32) { *v = PreconditionType(n) } +func (v *PreconditionType) XdrPointer() interface{} { return v } +func (PreconditionType) XdrTypeName() string { return "PreconditionType" } +func (v PreconditionType) XdrValue() interface{} { return v } +func (v *PreconditionType) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } + +type XdrType_PreconditionType = *PreconditionType + +func XDR_PreconditionType(v *PreconditionType) *PreconditionType { return v } + +var _XdrTags_Preconditions = map[int32]bool{ + XdrToI32(PRECOND_NONE): true, + XdrToI32(PRECOND_TIME): true, + XdrToI32(PRECOND_V2): true, +} + +func (_ Preconditions) XdrValidTags() map[int32]bool { + return _XdrTags_Preconditions +} +func (u *Preconditions) TimeBounds() *TimeBounds { switch u.Type { - case ENVELOPE_TYPE_TX: - if v, ok := u._u.(*TransactionV1Envelope); ok { + case PRECOND_TIME: + if v, ok := u._u.(*TimeBounds); ok { return v } else { - var zero TransactionV1Envelope + var zero TimeBounds u._u = &zero return &zero } default: - XdrPanic("TransactionEnvelope.V1 accessed when Type == %v", u.Type) + XdrPanic("Preconditions.TimeBounds accessed when Type == %v", u.Type) return nil } } -func (u *TransactionEnvelope) FeeBump() *FeeBumpTransactionEnvelope { +func (u *Preconditions) V2() *PreconditionsV2 { switch u.Type { - case ENVELOPE_TYPE_TX_FEE_BUMP: - if v, ok := u._u.(*FeeBumpTransactionEnvelope); ok { + case PRECOND_V2: + if v, ok := u._u.(*PreconditionsV2); ok { return v } else { - var zero FeeBumpTransactionEnvelope + var zero PreconditionsV2 u._u = &zero return &zero } default: - XdrPanic("TransactionEnvelope.FeeBump accessed when Type == %v", u.Type) + XdrPanic("Preconditions.V2 accessed when Type == %v", u.Type) return nil } } -func (u TransactionEnvelope) XdrValid() bool { +func (u Preconditions) XdrValid() bool { switch u.Type { - case ENVELOPE_TYPE_TX_V0, ENVELOPE_TYPE_TX, ENVELOPE_TYPE_TX_FEE_BUMP: + case PRECOND_NONE, PRECOND_TIME, PRECOND_V2: return true } return false } -func (u *TransactionEnvelope) XdrUnionTag() XdrNum32 { - return XDR_EnvelopeType(&u.Type) +func (u *Preconditions) XdrUnionTag() XdrNum32 { + return XDR_PreconditionType(&u.Type) } -func (u *TransactionEnvelope) XdrUnionTagName() string { +func (u *Preconditions) XdrUnionTagName() string { return "Type" } -func (u *TransactionEnvelope) XdrUnionBody() XdrType { +func (u *Preconditions) XdrUnionBody() XdrType { switch u.Type { - case ENVELOPE_TYPE_TX_V0: - return XDR_TransactionV0Envelope(u.V0()) - case ENVELOPE_TYPE_TX: - return XDR_TransactionV1Envelope(u.V1()) - case ENVELOPE_TYPE_TX_FEE_BUMP: - return XDR_FeeBumpTransactionEnvelope(u.FeeBump()) + case PRECOND_NONE: + return nil + case PRECOND_TIME: + return XDR_TimeBounds(u.TimeBounds()) + case PRECOND_V2: + return XDR_PreconditionsV2(u.V2()) } return nil } -func (u *TransactionEnvelope) XdrUnionBodyName() string { +func (u *Preconditions) XdrUnionBodyName() string { switch u.Type { - case ENVELOPE_TYPE_TX_V0: - return "V0" - case ENVELOPE_TYPE_TX: - return "V1" - case ENVELOPE_TYPE_TX_FEE_BUMP: - return "FeeBump" + case PRECOND_NONE: + return "" + case PRECOND_TIME: + return "TimeBounds" + case PRECOND_V2: + return "V2" } return "" } -type XdrType_TransactionEnvelope = *TransactionEnvelope +type XdrType_Preconditions = *Preconditions -func (v *TransactionEnvelope) XdrPointer() interface{} { return v } -func (TransactionEnvelope) XdrTypeName() string { return "TransactionEnvelope" } -func (v TransactionEnvelope) XdrValue() interface{} { return v } -func (v *TransactionEnvelope) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -func (u *TransactionEnvelope) XdrRecurse(x XDR, name string) { +func (v *Preconditions) XdrPointer() interface{} { return v } +func (Preconditions) XdrTypeName() string { return "Preconditions" } +func (v Preconditions) XdrValue() interface{} { return v } +func (v *Preconditions) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (u *Preconditions) XdrRecurse(x XDR, name string) { if name != "" { name = x.Sprintf("%s.", name) } - XDR_EnvelopeType(&u.Type).XdrMarshal(x, x.Sprintf("%stype", name)) + XDR_PreconditionType(&u.Type).XdrMarshal(x, x.Sprintf("%stype", name)) switch u.Type { - case ENVELOPE_TYPE_TX_V0: - x.Marshal(x.Sprintf("%sv0", name), XDR_TransactionV0Envelope(u.V0())) + case PRECOND_NONE: return - case ENVELOPE_TYPE_TX: - x.Marshal(x.Sprintf("%sv1", name), XDR_TransactionV1Envelope(u.V1())) + case PRECOND_TIME: + x.Marshal(x.Sprintf("%stimeBounds", name), XDR_TimeBounds(u.TimeBounds())) return - case ENVELOPE_TYPE_TX_FEE_BUMP: - x.Marshal(x.Sprintf("%sfeeBump", name), XDR_FeeBumpTransactionEnvelope(u.FeeBump())) + case PRECOND_V2: + x.Marshal(x.Sprintf("%sv2", name), XDR_PreconditionsV2(u.V2())) return } - XdrPanic("invalid Type (%v) in TransactionEnvelope", u.Type) + XdrPanic("invalid Type (%v) in Preconditions", u.Type) } -func XDR_TransactionEnvelope(v *TransactionEnvelope) *TransactionEnvelope { return v } +func XDR_Preconditions(v *Preconditions) *Preconditions { return v } -var _XdrTags_XdrAnon_TransactionSignaturePayload_TaggedTransaction = map[int32]bool{ - XdrToI32(ENVELOPE_TYPE_TX): true, - XdrToI32(ENVELOPE_TYPE_TX_FEE_BUMP): true, -} +type XdrType_LedgerFootprint = *LedgerFootprint -func (_ XdrAnon_TransactionSignaturePayload_TaggedTransaction) XdrValidTags() map[int32]bool { - return _XdrTags_XdrAnon_TransactionSignaturePayload_TaggedTransaction +func (v *LedgerFootprint) XdrPointer() interface{} { return v } +func (LedgerFootprint) XdrTypeName() string { return "LedgerFootprint" } +func (v LedgerFootprint) XdrValue() interface{} { return v } +func (v *LedgerFootprint) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v *LedgerFootprint) XdrRecurse(x XDR, name string) { + if name != "" { + name = x.Sprintf("%s.", name) + } + x.Marshal(x.Sprintf("%sreadOnly", name), (*_XdrVec_unbounded_LedgerKey)(&v.ReadOnly)) + x.Marshal(x.Sprintf("%sreadWrite", name), (*_XdrVec_unbounded_LedgerKey)(&v.ReadWrite)) } -func (u *XdrAnon_TransactionSignaturePayload_TaggedTransaction) Tx() *Transaction { - switch u.Type { - case ENVELOPE_TYPE_TX: - if v, ok := u._u.(*Transaction); ok { - return v - } else { - var zero Transaction - u._u = &zero - return &zero - } - default: - XdrPanic("XdrAnon_TransactionSignaturePayload_TaggedTransaction.Tx accessed when Type == %v", u.Type) - return nil +func XDR_LedgerFootprint(v *LedgerFootprint) *LedgerFootprint { return v } + +type XdrType_SorobanResources = *SorobanResources + +func (v *SorobanResources) XdrPointer() interface{} { return v } +func (SorobanResources) XdrTypeName() string { return "SorobanResources" } +func (v SorobanResources) XdrValue() interface{} { return v } +func (v *SorobanResources) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v *SorobanResources) XdrRecurse(x XDR, name string) { + if name != "" { + name = x.Sprintf("%s.", name) } + x.Marshal(x.Sprintf("%sfootprint", name), XDR_LedgerFootprint(&v.Footprint)) + x.Marshal(x.Sprintf("%sinstructions", name), XDR_Uint32(&v.Instructions)) + x.Marshal(x.Sprintf("%sreadBytes", name), XDR_Uint32(&v.ReadBytes)) + x.Marshal(x.Sprintf("%swriteBytes", name), XDR_Uint32(&v.WriteBytes)) } -func (u *XdrAnon_TransactionSignaturePayload_TaggedTransaction) FeeBump() *FeeBumpTransaction { - switch u.Type { - case ENVELOPE_TYPE_TX_FEE_BUMP: - if v, ok := u._u.(*FeeBumpTransaction); ok { - return v - } else { - var zero FeeBumpTransaction - u._u = &zero - return &zero - } - default: - XdrPanic("XdrAnon_TransactionSignaturePayload_TaggedTransaction.FeeBump accessed when Type == %v", u.Type) - return nil +func XDR_SorobanResources(v *SorobanResources) *SorobanResources { return v } + +type XdrType_SorobanTransactionData = *SorobanTransactionData + +func (v *SorobanTransactionData) XdrPointer() interface{} { return v } +func (SorobanTransactionData) XdrTypeName() string { return "SorobanTransactionData" } +func (v SorobanTransactionData) XdrValue() interface{} { return v } +func (v *SorobanTransactionData) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v *SorobanTransactionData) XdrRecurse(x XDR, name string) { + if name != "" { + name = x.Sprintf("%s.", name) } + x.Marshal(x.Sprintf("%sext", name), XDR_ExtensionPoint(&v.Ext)) + x.Marshal(x.Sprintf("%sresources", name), XDR_SorobanResources(&v.Resources)) + x.Marshal(x.Sprintf("%sresourceFee", name), XDR_Int64(&v.ResourceFee)) } -func (u XdrAnon_TransactionSignaturePayload_TaggedTransaction) XdrValid() bool { - switch u.Type { - case ENVELOPE_TYPE_TX, ENVELOPE_TYPE_TX_FEE_BUMP: +func XDR_SorobanTransactionData(v *SorobanTransactionData) *SorobanTransactionData { return v } + +var _XdrTags_XdrAnon_TransactionV0_Ext = map[int32]bool{ + XdrToI32(0): true, +} + +func (_ XdrAnon_TransactionV0_Ext) XdrValidTags() map[int32]bool { + return _XdrTags_XdrAnon_TransactionV0_Ext +} +func (u XdrAnon_TransactionV0_Ext) XdrValid() bool { + switch u.V { + case 0: return true } return false } -func (u *XdrAnon_TransactionSignaturePayload_TaggedTransaction) XdrUnionTag() XdrNum32 { - return XDR_EnvelopeType(&u.Type) +func (u *XdrAnon_TransactionV0_Ext) XdrUnionTag() XdrNum32 { + return XDR_int32(&u.V) } -func (u *XdrAnon_TransactionSignaturePayload_TaggedTransaction) XdrUnionTagName() string { - return "Type" +func (u *XdrAnon_TransactionV0_Ext) XdrUnionTagName() string { + return "V" } -func (u *XdrAnon_TransactionSignaturePayload_TaggedTransaction) XdrUnionBody() XdrType { - switch u.Type { - case ENVELOPE_TYPE_TX: - return XDR_Transaction(u.Tx()) - case ENVELOPE_TYPE_TX_FEE_BUMP: - return XDR_FeeBumpTransaction(u.FeeBump()) +func (u *XdrAnon_TransactionV0_Ext) XdrUnionBody() XdrType { + switch u.V { + case 0: + return nil } return nil } -func (u *XdrAnon_TransactionSignaturePayload_TaggedTransaction) XdrUnionBodyName() string { - switch u.Type { - case ENVELOPE_TYPE_TX: - return "Tx" - case ENVELOPE_TYPE_TX_FEE_BUMP: - return "FeeBump" +func (u *XdrAnon_TransactionV0_Ext) XdrUnionBodyName() string { + switch u.V { + case 0: + return "" } return "" } -type XdrType_XdrAnon_TransactionSignaturePayload_TaggedTransaction = *XdrAnon_TransactionSignaturePayload_TaggedTransaction +type XdrType_XdrAnon_TransactionV0_Ext = *XdrAnon_TransactionV0_Ext -func (v *XdrAnon_TransactionSignaturePayload_TaggedTransaction) XdrPointer() interface{} { return v } -func (XdrAnon_TransactionSignaturePayload_TaggedTransaction) XdrTypeName() string { - return "XdrAnon_TransactionSignaturePayload_TaggedTransaction" -} -func (v XdrAnon_TransactionSignaturePayload_TaggedTransaction) XdrValue() interface{} { return v } -func (v *XdrAnon_TransactionSignaturePayload_TaggedTransaction) XdrMarshal(x XDR, name string) { - x.Marshal(name, v) -} -func (u *XdrAnon_TransactionSignaturePayload_TaggedTransaction) XdrRecurse(x XDR, name string) { +func (v *XdrAnon_TransactionV0_Ext) XdrPointer() interface{} { return v } +func (XdrAnon_TransactionV0_Ext) XdrTypeName() string { return "XdrAnon_TransactionV0_Ext" } +func (v XdrAnon_TransactionV0_Ext) XdrValue() interface{} { return v } +func (v *XdrAnon_TransactionV0_Ext) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (u *XdrAnon_TransactionV0_Ext) XdrRecurse(x XDR, name string) { if name != "" { name = x.Sprintf("%s.", name) } - XDR_EnvelopeType(&u.Type).XdrMarshal(x, x.Sprintf("%stype", name)) - switch u.Type { - case ENVELOPE_TYPE_TX: - x.Marshal(x.Sprintf("%stx", name), XDR_Transaction(u.Tx())) + XDR_int32(&u.V).XdrMarshal(x, x.Sprintf("%sv", name)) + switch u.V { + case 0: return - case ENVELOPE_TYPE_TX_FEE_BUMP: - x.Marshal(x.Sprintf("%sfeeBump", name), XDR_FeeBumpTransaction(u.FeeBump())) + } + XdrPanic("invalid V (%v) in XdrAnon_TransactionV0_Ext", u.V) +} +func XDR_XdrAnon_TransactionV0_Ext(v *XdrAnon_TransactionV0_Ext) *XdrAnon_TransactionV0_Ext { return v } + +type _XdrVec_100_Operation []Operation + +func (_XdrVec_100_Operation) XdrBound() uint32 { + const bound uint32 = 100 // Force error if not const or doesn't fit + return bound +} +func (_XdrVec_100_Operation) XdrCheckLen(length uint32) { + if length > uint32(100) { + XdrPanic("_XdrVec_100_Operation length %d exceeds bound 100", length) + } else if int(length) < 0 { + XdrPanic("_XdrVec_100_Operation length %d exceeds max int", length) + } +} +func (v _XdrVec_100_Operation) GetVecLen() uint32 { return uint32(len(v)) } +func (v *_XdrVec_100_Operation) SetVecLen(length uint32) { + v.XdrCheckLen(length) + if int(length) <= cap(*v) { + if int(length) != len(*v) { + *v = (*v)[:int(length)] + } return } - XdrPanic("invalid Type (%v) in XdrAnon_TransactionSignaturePayload_TaggedTransaction", u.Type) + newcap := 2 * cap(*v) + if newcap < int(length) { // also catches overflow where 2*cap < 0 + newcap = int(length) + } else if bound := uint(100); uint(newcap) > bound { + if int(bound) < 0 { + bound = ^uint(0) >> 1 + } + newcap = int(bound) + } + nv := make([]Operation, int(length), newcap) + copy(nv, *v) + *v = nv } -func (v *XdrAnon_TransactionSignaturePayload_TaggedTransaction) XdrInitialize() { - var zero EnvelopeType - switch zero { - case ENVELOPE_TYPE_TX, ENVELOPE_TYPE_TX_FEE_BUMP: - default: - if v.Type == zero { - v.Type = ENVELOPE_TYPE_TX +func (v *_XdrVec_100_Operation) XdrMarshalN(x XDR, name string, n uint32) { + v.XdrCheckLen(n) + for i := 0; i < int(n); i++ { + if i >= len(*v) { + v.SetVecLen(uint32(i + 1)) } + XDR_Operation(&(*v)[i]).XdrMarshal(x, x.Sprintf("%s[%d]", name, i)) + } + if int(n) < len(*v) { + *v = (*v)[:int(n)] } } -func XDR_XdrAnon_TransactionSignaturePayload_TaggedTransaction(v *XdrAnon_TransactionSignaturePayload_TaggedTransaction) *XdrAnon_TransactionSignaturePayload_TaggedTransaction { - return v +func (v *_XdrVec_100_Operation) XdrRecurse(x XDR, name string) { + size := XdrSize{Size: uint32(len(*v)), Bound: 100} + x.Marshal(name, &size) + v.XdrMarshalN(x, name, size.Size) } +func (_XdrVec_100_Operation) XdrTypeName() string { return "Operation<>" } +func (v *_XdrVec_100_Operation) XdrPointer() interface{} { return (*[]Operation)(v) } +func (v _XdrVec_100_Operation) XdrValue() interface{} { return ([]Operation)(v) } +func (v *_XdrVec_100_Operation) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -type XdrType_TransactionSignaturePayload = *TransactionSignaturePayload +type XdrType_TransactionV0 = *TransactionV0 -func (v *TransactionSignaturePayload) XdrPointer() interface{} { return v } -func (TransactionSignaturePayload) XdrTypeName() string { return "TransactionSignaturePayload" } -func (v TransactionSignaturePayload) XdrValue() interface{} { return v } -func (v *TransactionSignaturePayload) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -func (v *TransactionSignaturePayload) XdrRecurse(x XDR, name string) { +func (v *TransactionV0) XdrPointer() interface{} { return v } +func (TransactionV0) XdrTypeName() string { return "TransactionV0" } +func (v TransactionV0) XdrValue() interface{} { return v } +func (v *TransactionV0) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v *TransactionV0) XdrRecurse(x XDR, name string) { if name != "" { name = x.Sprintf("%s.", name) } - x.Marshal(x.Sprintf("%snetworkId", name), XDR_Hash(&v.NetworkId)) - x.Marshal(x.Sprintf("%staggedTransaction", name), XDR_XdrAnon_TransactionSignaturePayload_TaggedTransaction(&v.TaggedTransaction)) -} -func XDR_TransactionSignaturePayload(v *TransactionSignaturePayload) *TransactionSignaturePayload { - return v + x.Marshal(x.Sprintf("%ssourceAccountEd25519", name), XDR_Uint256(&v.SourceAccountEd25519)) + x.Marshal(x.Sprintf("%sfee", name), XDR_Uint32(&v.Fee)) + x.Marshal(x.Sprintf("%sseqNum", name), XDR_SequenceNumber(&v.SeqNum)) + x.Marshal(x.Sprintf("%stimeBounds", name), _XdrPtr_TimeBounds{&v.TimeBounds}) + x.Marshal(x.Sprintf("%smemo", name), XDR_Memo(&v.Memo)) + x.Marshal(x.Sprintf("%soperations", name), (*_XdrVec_100_Operation)(&v.Operations)) + x.Marshal(x.Sprintf("%sext", name), XDR_XdrAnon_TransactionV0_Ext(&v.Ext)) } +func XDR_TransactionV0(v *TransactionV0) *TransactionV0 { return v } -var _XdrNames_ClaimAtomType = map[int32]string{ - int32(CLAIM_ATOM_TYPE_V0): "CLAIM_ATOM_TYPE_V0", - int32(CLAIM_ATOM_TYPE_ORDER_BOOK): "CLAIM_ATOM_TYPE_ORDER_BOOK", - int32(CLAIM_ATOM_TYPE_LIQUIDITY_POOL): "CLAIM_ATOM_TYPE_LIQUIDITY_POOL", -} -var _XdrValues_ClaimAtomType = map[string]int32{ - "CLAIM_ATOM_TYPE_V0": int32(CLAIM_ATOM_TYPE_V0), - "CLAIM_ATOM_TYPE_ORDER_BOOK": int32(CLAIM_ATOM_TYPE_ORDER_BOOK), - "CLAIM_ATOM_TYPE_LIQUIDITY_POOL": int32(CLAIM_ATOM_TYPE_LIQUIDITY_POOL), -} +type _XdrVec_20_DecoratedSignature []DecoratedSignature -func (ClaimAtomType) XdrEnumNames() map[int32]string { - return _XdrNames_ClaimAtomType +func (_XdrVec_20_DecoratedSignature) XdrBound() uint32 { + const bound uint32 = 20 // Force error if not const or doesn't fit + return bound } -func (v ClaimAtomType) String() string { - if s, ok := _XdrNames_ClaimAtomType[int32(v)]; ok { - return s +func (_XdrVec_20_DecoratedSignature) XdrCheckLen(length uint32) { + if length > uint32(20) { + XdrPanic("_XdrVec_20_DecoratedSignature length %d exceeds bound 20", length) + } else if int(length) < 0 { + XdrPanic("_XdrVec_20_DecoratedSignature length %d exceeds max int", length) } - return fmt.Sprintf("ClaimAtomType#%d", v) } -func (v *ClaimAtomType) Scan(ss fmt.ScanState, _ rune) error { - if tok, err := ss.Token(true, XdrSymChar); err != nil { - return err - } else { - stok := string(tok) - if val, ok := _XdrValues_ClaimAtomType[stok]; ok { - *v = ClaimAtomType(val) - return nil - } else if stok == "ClaimAtomType" { - if n, err := fmt.Fscanf(ss, "#%d", (*int32)(v)); n == 1 && err == nil { - return nil - } +func (v _XdrVec_20_DecoratedSignature) GetVecLen() uint32 { return uint32(len(v)) } +func (v *_XdrVec_20_DecoratedSignature) SetVecLen(length uint32) { + v.XdrCheckLen(length) + if int(length) <= cap(*v) { + if int(length) != len(*v) { + *v = (*v)[:int(length)] } - return XdrError(fmt.Sprintf("%s is not a valid ClaimAtomType.", stok)) + return } -} -func (v ClaimAtomType) GetU32() uint32 { return uint32(v) } -func (v *ClaimAtomType) SetU32(n uint32) { *v = ClaimAtomType(n) } -func (v *ClaimAtomType) XdrPointer() interface{} { return v } -func (ClaimAtomType) XdrTypeName() string { return "ClaimAtomType" } -func (v ClaimAtomType) XdrValue() interface{} { return v } -func (v *ClaimAtomType) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } - -type XdrType_ClaimAtomType = *ClaimAtomType - -func XDR_ClaimAtomType(v *ClaimAtomType) *ClaimAtomType { return v } - -type XdrType_ClaimOfferAtomV0 = *ClaimOfferAtomV0 - -func (v *ClaimOfferAtomV0) XdrPointer() interface{} { return v } -func (ClaimOfferAtomV0) XdrTypeName() string { return "ClaimOfferAtomV0" } -func (v ClaimOfferAtomV0) XdrValue() interface{} { return v } -func (v *ClaimOfferAtomV0) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -func (v *ClaimOfferAtomV0) XdrRecurse(x XDR, name string) { - if name != "" { - name = x.Sprintf("%s.", name) + newcap := 2 * cap(*v) + if newcap < int(length) { // also catches overflow where 2*cap < 0 + newcap = int(length) + } else if bound := uint(20); uint(newcap) > bound { + if int(bound) < 0 { + bound = ^uint(0) >> 1 + } + newcap = int(bound) } - x.Marshal(x.Sprintf("%ssellerEd25519", name), XDR_Uint256(&v.SellerEd25519)) - x.Marshal(x.Sprintf("%sofferID", name), XDR_Int64(&v.OfferID)) - x.Marshal(x.Sprintf("%sassetSold", name), XDR_Asset(&v.AssetSold)) - x.Marshal(x.Sprintf("%samountSold", name), XDR_Int64(&v.AmountSold)) - x.Marshal(x.Sprintf("%sassetBought", name), XDR_Asset(&v.AssetBought)) - x.Marshal(x.Sprintf("%samountBought", name), XDR_Int64(&v.AmountBought)) + nv := make([]DecoratedSignature, int(length), newcap) + copy(nv, *v) + *v = nv } -func XDR_ClaimOfferAtomV0(v *ClaimOfferAtomV0) *ClaimOfferAtomV0 { return v } - -type XdrType_ClaimOfferAtom = *ClaimOfferAtom - -func (v *ClaimOfferAtom) XdrPointer() interface{} { return v } -func (ClaimOfferAtom) XdrTypeName() string { return "ClaimOfferAtom" } -func (v ClaimOfferAtom) XdrValue() interface{} { return v } -func (v *ClaimOfferAtom) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -func (v *ClaimOfferAtom) XdrRecurse(x XDR, name string) { - if name != "" { - name = x.Sprintf("%s.", name) +func (v *_XdrVec_20_DecoratedSignature) XdrMarshalN(x XDR, name string, n uint32) { + v.XdrCheckLen(n) + for i := 0; i < int(n); i++ { + if i >= len(*v) { + v.SetVecLen(uint32(i + 1)) + } + XDR_DecoratedSignature(&(*v)[i]).XdrMarshal(x, x.Sprintf("%s[%d]", name, i)) + } + if int(n) < len(*v) { + *v = (*v)[:int(n)] } - x.Marshal(x.Sprintf("%ssellerID", name), XDR_AccountID(&v.SellerID)) - x.Marshal(x.Sprintf("%sofferID", name), XDR_Int64(&v.OfferID)) - x.Marshal(x.Sprintf("%sassetSold", name), XDR_Asset(&v.AssetSold)) - x.Marshal(x.Sprintf("%samountSold", name), XDR_Int64(&v.AmountSold)) - x.Marshal(x.Sprintf("%sassetBought", name), XDR_Asset(&v.AssetBought)) - x.Marshal(x.Sprintf("%samountBought", name), XDR_Int64(&v.AmountBought)) } -func XDR_ClaimOfferAtom(v *ClaimOfferAtom) *ClaimOfferAtom { return v } +func (v *_XdrVec_20_DecoratedSignature) XdrRecurse(x XDR, name string) { + size := XdrSize{Size: uint32(len(*v)), Bound: 20} + x.Marshal(name, &size) + v.XdrMarshalN(x, name, size.Size) +} +func (_XdrVec_20_DecoratedSignature) XdrTypeName() string { return "DecoratedSignature<>" } +func (v *_XdrVec_20_DecoratedSignature) XdrPointer() interface{} { return (*[]DecoratedSignature)(v) } +func (v _XdrVec_20_DecoratedSignature) XdrValue() interface{} { return ([]DecoratedSignature)(v) } +func (v *_XdrVec_20_DecoratedSignature) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -type XdrType_ClaimLiquidityAtom = *ClaimLiquidityAtom +type XdrType_TransactionV0Envelope = *TransactionV0Envelope -func (v *ClaimLiquidityAtom) XdrPointer() interface{} { return v } -func (ClaimLiquidityAtom) XdrTypeName() string { return "ClaimLiquidityAtom" } -func (v ClaimLiquidityAtom) XdrValue() interface{} { return v } -func (v *ClaimLiquidityAtom) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -func (v *ClaimLiquidityAtom) XdrRecurse(x XDR, name string) { +func (v *TransactionV0Envelope) XdrPointer() interface{} { return v } +func (TransactionV0Envelope) XdrTypeName() string { return "TransactionV0Envelope" } +func (v TransactionV0Envelope) XdrValue() interface{} { return v } +func (v *TransactionV0Envelope) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v *TransactionV0Envelope) XdrRecurse(x XDR, name string) { if name != "" { name = x.Sprintf("%s.", name) } - x.Marshal(x.Sprintf("%sliquidityPoolID", name), XDR_PoolID(&v.LiquidityPoolID)) - x.Marshal(x.Sprintf("%sassetSold", name), XDR_Asset(&v.AssetSold)) - x.Marshal(x.Sprintf("%samountSold", name), XDR_Int64(&v.AmountSold)) - x.Marshal(x.Sprintf("%sassetBought", name), XDR_Asset(&v.AssetBought)) - x.Marshal(x.Sprintf("%samountBought", name), XDR_Int64(&v.AmountBought)) + x.Marshal(x.Sprintf("%stx", name), XDR_TransactionV0(&v.Tx)) + x.Marshal(x.Sprintf("%ssignatures", name), (*_XdrVec_20_DecoratedSignature)(&v.Signatures)) } -func XDR_ClaimLiquidityAtom(v *ClaimLiquidityAtom) *ClaimLiquidityAtom { return v } +func XDR_TransactionV0Envelope(v *TransactionV0Envelope) *TransactionV0Envelope { return v } -var _XdrTags_ClaimAtom = map[int32]bool{ - XdrToI32(CLAIM_ATOM_TYPE_V0): true, - XdrToI32(CLAIM_ATOM_TYPE_ORDER_BOOK): true, - XdrToI32(CLAIM_ATOM_TYPE_LIQUIDITY_POOL): true, +var _XdrTags_XdrAnon_Transaction_Ext = map[int32]bool{ + XdrToI32(0): true, + XdrToI32(1): true, } -func (_ ClaimAtom) XdrValidTags() map[int32]bool { - return _XdrTags_ClaimAtom -} -func (u *ClaimAtom) V0() *ClaimOfferAtomV0 { - switch u.Type { - case CLAIM_ATOM_TYPE_V0: - if v, ok := u._u.(*ClaimOfferAtomV0); ok { - return v - } else { - var zero ClaimOfferAtomV0 - u._u = &zero - return &zero - } - default: - XdrPanic("ClaimAtom.V0 accessed when Type == %v", u.Type) - return nil - } -} -func (u *ClaimAtom) OrderBook() *ClaimOfferAtom { - switch u.Type { - case CLAIM_ATOM_TYPE_ORDER_BOOK: - if v, ok := u._u.(*ClaimOfferAtom); ok { - return v - } else { - var zero ClaimOfferAtom - u._u = &zero - return &zero - } - default: - XdrPanic("ClaimAtom.OrderBook accessed when Type == %v", u.Type) - return nil - } +func (_ XdrAnon_Transaction_Ext) XdrValidTags() map[int32]bool { + return _XdrTags_XdrAnon_Transaction_Ext } -func (u *ClaimAtom) LiquidityPool() *ClaimLiquidityAtom { - switch u.Type { - case CLAIM_ATOM_TYPE_LIQUIDITY_POOL: - if v, ok := u._u.(*ClaimLiquidityAtom); ok { +func (u *XdrAnon_Transaction_Ext) SorobanData() *SorobanTransactionData { + switch u.V { + case 1: + if v, ok := u._u.(*SorobanTransactionData); ok { return v } else { - var zero ClaimLiquidityAtom + var zero SorobanTransactionData u._u = &zero return &zero } default: - XdrPanic("ClaimAtom.LiquidityPool accessed when Type == %v", u.Type) + XdrPanic("XdrAnon_Transaction_Ext.SorobanData accessed when V == %v", u.V) return nil } } -func (u ClaimAtom) XdrValid() bool { - switch u.Type { - case CLAIM_ATOM_TYPE_V0, CLAIM_ATOM_TYPE_ORDER_BOOK, CLAIM_ATOM_TYPE_LIQUIDITY_POOL: +func (u XdrAnon_Transaction_Ext) XdrValid() bool { + switch u.V { + case 0, 1: return true } return false } -func (u *ClaimAtom) XdrUnionTag() XdrNum32 { - return XDR_ClaimAtomType(&u.Type) +func (u *XdrAnon_Transaction_Ext) XdrUnionTag() XdrNum32 { + return XDR_int32(&u.V) } -func (u *ClaimAtom) XdrUnionTagName() string { - return "Type" +func (u *XdrAnon_Transaction_Ext) XdrUnionTagName() string { + return "V" } -func (u *ClaimAtom) XdrUnionBody() XdrType { - switch u.Type { - case CLAIM_ATOM_TYPE_V0: - return XDR_ClaimOfferAtomV0(u.V0()) - case CLAIM_ATOM_TYPE_ORDER_BOOK: - return XDR_ClaimOfferAtom(u.OrderBook()) - case CLAIM_ATOM_TYPE_LIQUIDITY_POOL: - return XDR_ClaimLiquidityAtom(u.LiquidityPool()) +func (u *XdrAnon_Transaction_Ext) XdrUnionBody() XdrType { + switch u.V { + case 0: + return nil + case 1: + return XDR_SorobanTransactionData(u.SorobanData()) } return nil } -func (u *ClaimAtom) XdrUnionBodyName() string { - switch u.Type { - case CLAIM_ATOM_TYPE_V0: - return "V0" - case CLAIM_ATOM_TYPE_ORDER_BOOK: - return "OrderBook" - case CLAIM_ATOM_TYPE_LIQUIDITY_POOL: - return "LiquidityPool" +func (u *XdrAnon_Transaction_Ext) XdrUnionBodyName() string { + switch u.V { + case 0: + return "" + case 1: + return "SorobanData" } return "" } -type XdrType_ClaimAtom = *ClaimAtom +type XdrType_XdrAnon_Transaction_Ext = *XdrAnon_Transaction_Ext -func (v *ClaimAtom) XdrPointer() interface{} { return v } -func (ClaimAtom) XdrTypeName() string { return "ClaimAtom" } -func (v ClaimAtom) XdrValue() interface{} { return v } -func (v *ClaimAtom) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -func (u *ClaimAtom) XdrRecurse(x XDR, name string) { +func (v *XdrAnon_Transaction_Ext) XdrPointer() interface{} { return v } +func (XdrAnon_Transaction_Ext) XdrTypeName() string { return "XdrAnon_Transaction_Ext" } +func (v XdrAnon_Transaction_Ext) XdrValue() interface{} { return v } +func (v *XdrAnon_Transaction_Ext) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (u *XdrAnon_Transaction_Ext) XdrRecurse(x XDR, name string) { if name != "" { name = x.Sprintf("%s.", name) } - XDR_ClaimAtomType(&u.Type).XdrMarshal(x, x.Sprintf("%stype", name)) - switch u.Type { - case CLAIM_ATOM_TYPE_V0: - x.Marshal(x.Sprintf("%sv0", name), XDR_ClaimOfferAtomV0(u.V0())) - return - case CLAIM_ATOM_TYPE_ORDER_BOOK: - x.Marshal(x.Sprintf("%sorderBook", name), XDR_ClaimOfferAtom(u.OrderBook())) + XDR_int32(&u.V).XdrMarshal(x, x.Sprintf("%sv", name)) + switch u.V { + case 0: return - case CLAIM_ATOM_TYPE_LIQUIDITY_POOL: - x.Marshal(x.Sprintf("%sliquidityPool", name), XDR_ClaimLiquidityAtom(u.LiquidityPool())) + case 1: + x.Marshal(x.Sprintf("%ssorobanData", name), XDR_SorobanTransactionData(u.SorobanData())) return } - XdrPanic("invalid Type (%v) in ClaimAtom", u.Type) + XdrPanic("invalid V (%v) in XdrAnon_Transaction_Ext", u.V) } -func XDR_ClaimAtom(v *ClaimAtom) *ClaimAtom { return v } +func XDR_XdrAnon_Transaction_Ext(v *XdrAnon_Transaction_Ext) *XdrAnon_Transaction_Ext { return v } -var _XdrNames_CreateAccountResultCode = map[int32]string{ - int32(CREATE_ACCOUNT_SUCCESS): "CREATE_ACCOUNT_SUCCESS", - int32(CREATE_ACCOUNT_MALFORMED): "CREATE_ACCOUNT_MALFORMED", - int32(CREATE_ACCOUNT_UNDERFUNDED): "CREATE_ACCOUNT_UNDERFUNDED", - int32(CREATE_ACCOUNT_LOW_RESERVE): "CREATE_ACCOUNT_LOW_RESERVE", - int32(CREATE_ACCOUNT_ALREADY_EXIST): "CREATE_ACCOUNT_ALREADY_EXIST", -} -var _XdrValues_CreateAccountResultCode = map[string]int32{ - "CREATE_ACCOUNT_SUCCESS": int32(CREATE_ACCOUNT_SUCCESS), - "CREATE_ACCOUNT_MALFORMED": int32(CREATE_ACCOUNT_MALFORMED), - "CREATE_ACCOUNT_UNDERFUNDED": int32(CREATE_ACCOUNT_UNDERFUNDED), - "CREATE_ACCOUNT_LOW_RESERVE": int32(CREATE_ACCOUNT_LOW_RESERVE), - "CREATE_ACCOUNT_ALREADY_EXIST": int32(CREATE_ACCOUNT_ALREADY_EXIST), -} +type XdrType_Transaction = *Transaction -func (CreateAccountResultCode) XdrEnumNames() map[int32]string { - return _XdrNames_CreateAccountResultCode -} -func (v CreateAccountResultCode) String() string { - if s, ok := _XdrNames_CreateAccountResultCode[int32(v)]; ok { - return s - } - return fmt.Sprintf("CreateAccountResultCode#%d", v) -} -func (v *CreateAccountResultCode) Scan(ss fmt.ScanState, _ rune) error { - if tok, err := ss.Token(true, XdrSymChar); err != nil { - return err - } else { - stok := string(tok) - if val, ok := _XdrValues_CreateAccountResultCode[stok]; ok { - *v = CreateAccountResultCode(val) - return nil - } else if stok == "CreateAccountResultCode" { - if n, err := fmt.Fscanf(ss, "#%d", (*int32)(v)); n == 1 && err == nil { - return nil - } - } - return XdrError(fmt.Sprintf("%s is not a valid CreateAccountResultCode.", stok)) +func (v *Transaction) XdrPointer() interface{} { return v } +func (Transaction) XdrTypeName() string { return "Transaction" } +func (v Transaction) XdrValue() interface{} { return v } +func (v *Transaction) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v *Transaction) XdrRecurse(x XDR, name string) { + if name != "" { + name = x.Sprintf("%s.", name) } + x.Marshal(x.Sprintf("%ssourceAccount", name), XDR_MuxedAccount(&v.SourceAccount)) + x.Marshal(x.Sprintf("%sfee", name), XDR_Uint32(&v.Fee)) + x.Marshal(x.Sprintf("%sseqNum", name), XDR_SequenceNumber(&v.SeqNum)) + x.Marshal(x.Sprintf("%scond", name), XDR_Preconditions(&v.Cond)) + x.Marshal(x.Sprintf("%smemo", name), XDR_Memo(&v.Memo)) + x.Marshal(x.Sprintf("%soperations", name), (*_XdrVec_100_Operation)(&v.Operations)) + x.Marshal(x.Sprintf("%sext", name), XDR_XdrAnon_Transaction_Ext(&v.Ext)) } -func (v CreateAccountResultCode) GetU32() uint32 { return uint32(v) } -func (v *CreateAccountResultCode) SetU32(n uint32) { *v = CreateAccountResultCode(n) } -func (v *CreateAccountResultCode) XdrPointer() interface{} { return v } -func (CreateAccountResultCode) XdrTypeName() string { return "CreateAccountResultCode" } -func (v CreateAccountResultCode) XdrValue() interface{} { return v } -func (v *CreateAccountResultCode) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } - -type XdrType_CreateAccountResultCode = *CreateAccountResultCode +func XDR_Transaction(v *Transaction) *Transaction { return v } -func XDR_CreateAccountResultCode(v *CreateAccountResultCode) *CreateAccountResultCode { return v } +type XdrType_TransactionV1Envelope = *TransactionV1Envelope -var _XdrComments_CreateAccountResultCode = map[int32]string{ - int32(CREATE_ACCOUNT_SUCCESS): "account was created", - int32(CREATE_ACCOUNT_MALFORMED): "invalid destination", - int32(CREATE_ACCOUNT_UNDERFUNDED): "not enough funds in source account", - int32(CREATE_ACCOUNT_LOW_RESERVE): "would create an account below the min reserve", - int32(CREATE_ACCOUNT_ALREADY_EXIST): "account already exists", +func (v *TransactionV1Envelope) XdrPointer() interface{} { return v } +func (TransactionV1Envelope) XdrTypeName() string { return "TransactionV1Envelope" } +func (v TransactionV1Envelope) XdrValue() interface{} { return v } +func (v *TransactionV1Envelope) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v *TransactionV1Envelope) XdrRecurse(x XDR, name string) { + if name != "" { + name = x.Sprintf("%s.", name) + } + x.Marshal(x.Sprintf("%stx", name), XDR_Transaction(&v.Tx)) + x.Marshal(x.Sprintf("%ssignatures", name), (*_XdrVec_20_DecoratedSignature)(&v.Signatures)) } +func XDR_TransactionV1Envelope(v *TransactionV1Envelope) *TransactionV1Envelope { return v } -func (e CreateAccountResultCode) XdrEnumComments() map[int32]string { - return _XdrComments_CreateAccountResultCode +var _XdrTags_XdrAnon_FeeBumpTransaction_InnerTx = map[int32]bool{ + XdrToI32(ENVELOPE_TYPE_TX): true, } -var _XdrTags_CreateAccountResult = map[int32]bool{ - XdrToI32(CREATE_ACCOUNT_SUCCESS): true, - XdrToI32(CREATE_ACCOUNT_MALFORMED): true, - XdrToI32(CREATE_ACCOUNT_UNDERFUNDED): true, - XdrToI32(CREATE_ACCOUNT_LOW_RESERVE): true, - XdrToI32(CREATE_ACCOUNT_ALREADY_EXIST): true, +func (_ XdrAnon_FeeBumpTransaction_InnerTx) XdrValidTags() map[int32]bool { + return _XdrTags_XdrAnon_FeeBumpTransaction_InnerTx } - -func (_ CreateAccountResult) XdrValidTags() map[int32]bool { - return _XdrTags_CreateAccountResult +func (u *XdrAnon_FeeBumpTransaction_InnerTx) V1() *TransactionV1Envelope { + switch u.Type { + case ENVELOPE_TYPE_TX: + if v, ok := u._u.(*TransactionV1Envelope); ok { + return v + } else { + var zero TransactionV1Envelope + u._u = &zero + return &zero + } + default: + XdrPanic("XdrAnon_FeeBumpTransaction_InnerTx.V1 accessed when Type == %v", u.Type) + return nil + } } -func (u CreateAccountResult) XdrValid() bool { - switch u.Code { - case CREATE_ACCOUNT_SUCCESS, CREATE_ACCOUNT_MALFORMED, CREATE_ACCOUNT_UNDERFUNDED, CREATE_ACCOUNT_LOW_RESERVE, CREATE_ACCOUNT_ALREADY_EXIST: +func (u XdrAnon_FeeBumpTransaction_InnerTx) XdrValid() bool { + switch u.Type { + case ENVELOPE_TYPE_TX: return true } return false } -func (u *CreateAccountResult) XdrUnionTag() XdrNum32 { - return XDR_CreateAccountResultCode(&u.Code) +func (u *XdrAnon_FeeBumpTransaction_InnerTx) XdrUnionTag() XdrNum32 { + return XDR_EnvelopeType(&u.Type) } -func (u *CreateAccountResult) XdrUnionTagName() string { - return "Code" +func (u *XdrAnon_FeeBumpTransaction_InnerTx) XdrUnionTagName() string { + return "Type" } -func (u *CreateAccountResult) XdrUnionBody() XdrType { - switch u.Code { - case CREATE_ACCOUNT_SUCCESS: - return nil - case CREATE_ACCOUNT_MALFORMED, CREATE_ACCOUNT_UNDERFUNDED, CREATE_ACCOUNT_LOW_RESERVE, CREATE_ACCOUNT_ALREADY_EXIST: - return nil +func (u *XdrAnon_FeeBumpTransaction_InnerTx) XdrUnionBody() XdrType { + switch u.Type { + case ENVELOPE_TYPE_TX: + return XDR_TransactionV1Envelope(u.V1()) } return nil } -func (u *CreateAccountResult) XdrUnionBodyName() string { - switch u.Code { - case CREATE_ACCOUNT_SUCCESS: - return "" - case CREATE_ACCOUNT_MALFORMED, CREATE_ACCOUNT_UNDERFUNDED, CREATE_ACCOUNT_LOW_RESERVE, CREATE_ACCOUNT_ALREADY_EXIST: - return "" +func (u *XdrAnon_FeeBumpTransaction_InnerTx) XdrUnionBodyName() string { + switch u.Type { + case ENVELOPE_TYPE_TX: + return "V1" } return "" } -type XdrType_CreateAccountResult = *CreateAccountResult +type XdrType_XdrAnon_FeeBumpTransaction_InnerTx = *XdrAnon_FeeBumpTransaction_InnerTx -func (v *CreateAccountResult) XdrPointer() interface{} { return v } -func (CreateAccountResult) XdrTypeName() string { return "CreateAccountResult" } -func (v CreateAccountResult) XdrValue() interface{} { return v } -func (v *CreateAccountResult) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -func (u *CreateAccountResult) XdrRecurse(x XDR, name string) { +func (v *XdrAnon_FeeBumpTransaction_InnerTx) XdrPointer() interface{} { return v } +func (XdrAnon_FeeBumpTransaction_InnerTx) XdrTypeName() string { + return "XdrAnon_FeeBumpTransaction_InnerTx" +} +func (v XdrAnon_FeeBumpTransaction_InnerTx) XdrValue() interface{} { return v } +func (v *XdrAnon_FeeBumpTransaction_InnerTx) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (u *XdrAnon_FeeBumpTransaction_InnerTx) XdrRecurse(x XDR, name string) { if name != "" { name = x.Sprintf("%s.", name) } - XDR_CreateAccountResultCode(&u.Code).XdrMarshal(x, x.Sprintf("%scode", name)) - switch u.Code { - case CREATE_ACCOUNT_SUCCESS: - return - case CREATE_ACCOUNT_MALFORMED, CREATE_ACCOUNT_UNDERFUNDED, CREATE_ACCOUNT_LOW_RESERVE, CREATE_ACCOUNT_ALREADY_EXIST: + XDR_EnvelopeType(&u.Type).XdrMarshal(x, x.Sprintf("%stype", name)) + switch u.Type { + case ENVELOPE_TYPE_TX: + x.Marshal(x.Sprintf("%sv1", name), XDR_TransactionV1Envelope(u.V1())) return } - XdrPanic("invalid Code (%v) in CreateAccountResult", u.Code) + XdrPanic("invalid Type (%v) in XdrAnon_FeeBumpTransaction_InnerTx", u.Type) } -func XDR_CreateAccountResult(v *CreateAccountResult) *CreateAccountResult { return v } - -var _XdrNames_PaymentResultCode = map[int32]string{ - int32(PAYMENT_SUCCESS): "PAYMENT_SUCCESS", - int32(PAYMENT_MALFORMED): "PAYMENT_MALFORMED", - int32(PAYMENT_UNDERFUNDED): "PAYMENT_UNDERFUNDED", - int32(PAYMENT_SRC_NO_TRUST): "PAYMENT_SRC_NO_TRUST", - int32(PAYMENT_SRC_NOT_AUTHORIZED): "PAYMENT_SRC_NOT_AUTHORIZED", - int32(PAYMENT_NO_DESTINATION): "PAYMENT_NO_DESTINATION", - int32(PAYMENT_NO_TRUST): "PAYMENT_NO_TRUST", - int32(PAYMENT_NOT_AUTHORIZED): "PAYMENT_NOT_AUTHORIZED", - int32(PAYMENT_LINE_FULL): "PAYMENT_LINE_FULL", - int32(PAYMENT_NO_ISSUER): "PAYMENT_NO_ISSUER", +func (v *XdrAnon_FeeBumpTransaction_InnerTx) XdrInitialize() { + var zero EnvelopeType + switch zero { + case ENVELOPE_TYPE_TX: + default: + if v.Type == zero { + v.Type = ENVELOPE_TYPE_TX + } + } } -var _XdrValues_PaymentResultCode = map[string]int32{ - "PAYMENT_SUCCESS": int32(PAYMENT_SUCCESS), - "PAYMENT_MALFORMED": int32(PAYMENT_MALFORMED), - "PAYMENT_UNDERFUNDED": int32(PAYMENT_UNDERFUNDED), - "PAYMENT_SRC_NO_TRUST": int32(PAYMENT_SRC_NO_TRUST), - "PAYMENT_SRC_NOT_AUTHORIZED": int32(PAYMENT_SRC_NOT_AUTHORIZED), - "PAYMENT_NO_DESTINATION": int32(PAYMENT_NO_DESTINATION), - "PAYMENT_NO_TRUST": int32(PAYMENT_NO_TRUST), - "PAYMENT_NOT_AUTHORIZED": int32(PAYMENT_NOT_AUTHORIZED), - "PAYMENT_LINE_FULL": int32(PAYMENT_LINE_FULL), - "PAYMENT_NO_ISSUER": int32(PAYMENT_NO_ISSUER), +func XDR_XdrAnon_FeeBumpTransaction_InnerTx(v *XdrAnon_FeeBumpTransaction_InnerTx) *XdrAnon_FeeBumpTransaction_InnerTx { + return v } -func (PaymentResultCode) XdrEnumNames() map[int32]string { - return _XdrNames_PaymentResultCode +var _XdrTags_XdrAnon_FeeBumpTransaction_Ext = map[int32]bool{ + XdrToI32(0): true, } -func (v PaymentResultCode) String() string { - if s, ok := _XdrNames_PaymentResultCode[int32(v)]; ok { - return s + +func (_ XdrAnon_FeeBumpTransaction_Ext) XdrValidTags() map[int32]bool { + return _XdrTags_XdrAnon_FeeBumpTransaction_Ext +} +func (u XdrAnon_FeeBumpTransaction_Ext) XdrValid() bool { + switch u.V { + case 0: + return true } - return fmt.Sprintf("PaymentResultCode#%d", v) + return false } -func (v *PaymentResultCode) Scan(ss fmt.ScanState, _ rune) error { - if tok, err := ss.Token(true, XdrSymChar); err != nil { - return err - } else { - stok := string(tok) - if val, ok := _XdrValues_PaymentResultCode[stok]; ok { - *v = PaymentResultCode(val) - return nil - } else if stok == "PaymentResultCode" { - if n, err := fmt.Fscanf(ss, "#%d", (*int32)(v)); n == 1 && err == nil { - return nil - } - } - return XdrError(fmt.Sprintf("%s is not a valid PaymentResultCode.", stok)) +func (u *XdrAnon_FeeBumpTransaction_Ext) XdrUnionTag() XdrNum32 { + return XDR_int32(&u.V) +} +func (u *XdrAnon_FeeBumpTransaction_Ext) XdrUnionTagName() string { + return "V" +} +func (u *XdrAnon_FeeBumpTransaction_Ext) XdrUnionBody() XdrType { + switch u.V { + case 0: + return nil } + return nil +} +func (u *XdrAnon_FeeBumpTransaction_Ext) XdrUnionBodyName() string { + switch u.V { + case 0: + return "" + } + return "" } -func (v PaymentResultCode) GetU32() uint32 { return uint32(v) } -func (v *PaymentResultCode) SetU32(n uint32) { *v = PaymentResultCode(n) } -func (v *PaymentResultCode) XdrPointer() interface{} { return v } -func (PaymentResultCode) XdrTypeName() string { return "PaymentResultCode" } -func (v PaymentResultCode) XdrValue() interface{} { return v } -func (v *PaymentResultCode) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } - -type XdrType_PaymentResultCode = *PaymentResultCode -func XDR_PaymentResultCode(v *PaymentResultCode) *PaymentResultCode { return v } +type XdrType_XdrAnon_FeeBumpTransaction_Ext = *XdrAnon_FeeBumpTransaction_Ext -var _XdrComments_PaymentResultCode = map[int32]string{ - int32(PAYMENT_SUCCESS): "payment successfully completed", - int32(PAYMENT_MALFORMED): "bad input", - int32(PAYMENT_UNDERFUNDED): "not enough funds in source account", - int32(PAYMENT_SRC_NO_TRUST): "no trust line on source account", - int32(PAYMENT_SRC_NOT_AUTHORIZED): "source not authorized to transfer", - int32(PAYMENT_NO_DESTINATION): "destination account does not exist", - int32(PAYMENT_NO_TRUST): "destination missing a trust line for asset", - int32(PAYMENT_NOT_AUTHORIZED): "destination not authorized to hold asset", - int32(PAYMENT_LINE_FULL): "destination would go above their limit", - int32(PAYMENT_NO_ISSUER): "missing issuer on asset", +func (v *XdrAnon_FeeBumpTransaction_Ext) XdrPointer() interface{} { return v } +func (XdrAnon_FeeBumpTransaction_Ext) XdrTypeName() string { return "XdrAnon_FeeBumpTransaction_Ext" } +func (v XdrAnon_FeeBumpTransaction_Ext) XdrValue() interface{} { return v } +func (v *XdrAnon_FeeBumpTransaction_Ext) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (u *XdrAnon_FeeBumpTransaction_Ext) XdrRecurse(x XDR, name string) { + if name != "" { + name = x.Sprintf("%s.", name) + } + XDR_int32(&u.V).XdrMarshal(x, x.Sprintf("%sv", name)) + switch u.V { + case 0: + return + } + XdrPanic("invalid V (%v) in XdrAnon_FeeBumpTransaction_Ext", u.V) +} +func XDR_XdrAnon_FeeBumpTransaction_Ext(v *XdrAnon_FeeBumpTransaction_Ext) *XdrAnon_FeeBumpTransaction_Ext { + return v } -func (e PaymentResultCode) XdrEnumComments() map[int32]string { - return _XdrComments_PaymentResultCode +type XdrType_FeeBumpTransaction = *FeeBumpTransaction + +func (v *FeeBumpTransaction) XdrPointer() interface{} { return v } +func (FeeBumpTransaction) XdrTypeName() string { return "FeeBumpTransaction" } +func (v FeeBumpTransaction) XdrValue() interface{} { return v } +func (v *FeeBumpTransaction) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v *FeeBumpTransaction) XdrRecurse(x XDR, name string) { + if name != "" { + name = x.Sprintf("%s.", name) + } + x.Marshal(x.Sprintf("%sfeeSource", name), XDR_MuxedAccount(&v.FeeSource)) + x.Marshal(x.Sprintf("%sfee", name), XDR_Int64(&v.Fee)) + x.Marshal(x.Sprintf("%sinnerTx", name), XDR_XdrAnon_FeeBumpTransaction_InnerTx(&v.InnerTx)) + x.Marshal(x.Sprintf("%sext", name), XDR_XdrAnon_FeeBumpTransaction_Ext(&v.Ext)) } +func XDR_FeeBumpTransaction(v *FeeBumpTransaction) *FeeBumpTransaction { return v } -var _XdrTags_PaymentResult = map[int32]bool{ - XdrToI32(PAYMENT_SUCCESS): true, - XdrToI32(PAYMENT_MALFORMED): true, - XdrToI32(PAYMENT_UNDERFUNDED): true, - XdrToI32(PAYMENT_SRC_NO_TRUST): true, - XdrToI32(PAYMENT_SRC_NOT_AUTHORIZED): true, - XdrToI32(PAYMENT_NO_DESTINATION): true, - XdrToI32(PAYMENT_NO_TRUST): true, - XdrToI32(PAYMENT_NOT_AUTHORIZED): true, - XdrToI32(PAYMENT_LINE_FULL): true, - XdrToI32(PAYMENT_NO_ISSUER): true, +type XdrType_FeeBumpTransactionEnvelope = *FeeBumpTransactionEnvelope + +func (v *FeeBumpTransactionEnvelope) XdrPointer() interface{} { return v } +func (FeeBumpTransactionEnvelope) XdrTypeName() string { return "FeeBumpTransactionEnvelope" } +func (v FeeBumpTransactionEnvelope) XdrValue() interface{} { return v } +func (v *FeeBumpTransactionEnvelope) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v *FeeBumpTransactionEnvelope) XdrRecurse(x XDR, name string) { + if name != "" { + name = x.Sprintf("%s.", name) + } + x.Marshal(x.Sprintf("%stx", name), XDR_FeeBumpTransaction(&v.Tx)) + x.Marshal(x.Sprintf("%ssignatures", name), (*_XdrVec_20_DecoratedSignature)(&v.Signatures)) +} +func XDR_FeeBumpTransactionEnvelope(v *FeeBumpTransactionEnvelope) *FeeBumpTransactionEnvelope { + return v } -func (_ PaymentResult) XdrValidTags() map[int32]bool { - return _XdrTags_PaymentResult +var _XdrTags_TransactionEnvelope = map[int32]bool{ + XdrToI32(ENVELOPE_TYPE_TX_V0): true, + XdrToI32(ENVELOPE_TYPE_TX): true, + XdrToI32(ENVELOPE_TYPE_TX_FEE_BUMP): true, } -func (u PaymentResult) XdrValid() bool { - switch u.Code { - case PAYMENT_SUCCESS, PAYMENT_MALFORMED, PAYMENT_UNDERFUNDED, PAYMENT_SRC_NO_TRUST, PAYMENT_SRC_NOT_AUTHORIZED, PAYMENT_NO_DESTINATION, PAYMENT_NO_TRUST, PAYMENT_NOT_AUTHORIZED, PAYMENT_LINE_FULL, PAYMENT_NO_ISSUER: + +func (_ TransactionEnvelope) XdrValidTags() map[int32]bool { + return _XdrTags_TransactionEnvelope +} +func (u *TransactionEnvelope) V0() *TransactionV0Envelope { + switch u.Type { + case ENVELOPE_TYPE_TX_V0: + if v, ok := u._u.(*TransactionV0Envelope); ok { + return v + } else { + var zero TransactionV0Envelope + u._u = &zero + return &zero + } + default: + XdrPanic("TransactionEnvelope.V0 accessed when Type == %v", u.Type) + return nil + } +} +func (u *TransactionEnvelope) V1() *TransactionV1Envelope { + switch u.Type { + case ENVELOPE_TYPE_TX: + if v, ok := u._u.(*TransactionV1Envelope); ok { + return v + } else { + var zero TransactionV1Envelope + u._u = &zero + return &zero + } + default: + XdrPanic("TransactionEnvelope.V1 accessed when Type == %v", u.Type) + return nil + } +} +func (u *TransactionEnvelope) FeeBump() *FeeBumpTransactionEnvelope { + switch u.Type { + case ENVELOPE_TYPE_TX_FEE_BUMP: + if v, ok := u._u.(*FeeBumpTransactionEnvelope); ok { + return v + } else { + var zero FeeBumpTransactionEnvelope + u._u = &zero + return &zero + } + default: + XdrPanic("TransactionEnvelope.FeeBump accessed when Type == %v", u.Type) + return nil + } +} +func (u TransactionEnvelope) XdrValid() bool { + switch u.Type { + case ENVELOPE_TYPE_TX_V0, ENVELOPE_TYPE_TX, ENVELOPE_TYPE_TX_FEE_BUMP: return true } return false } -func (u *PaymentResult) XdrUnionTag() XdrNum32 { - return XDR_PaymentResultCode(&u.Code) +func (u *TransactionEnvelope) XdrUnionTag() XdrNum32 { + return XDR_EnvelopeType(&u.Type) } -func (u *PaymentResult) XdrUnionTagName() string { - return "Code" +func (u *TransactionEnvelope) XdrUnionTagName() string { + return "Type" } -func (u *PaymentResult) XdrUnionBody() XdrType { - switch u.Code { - case PAYMENT_SUCCESS: - return nil - case PAYMENT_MALFORMED, PAYMENT_UNDERFUNDED, PAYMENT_SRC_NO_TRUST, PAYMENT_SRC_NOT_AUTHORIZED, PAYMENT_NO_DESTINATION, PAYMENT_NO_TRUST, PAYMENT_NOT_AUTHORIZED, PAYMENT_LINE_FULL, PAYMENT_NO_ISSUER: - return nil +func (u *TransactionEnvelope) XdrUnionBody() XdrType { + switch u.Type { + case ENVELOPE_TYPE_TX_V0: + return XDR_TransactionV0Envelope(u.V0()) + case ENVELOPE_TYPE_TX: + return XDR_TransactionV1Envelope(u.V1()) + case ENVELOPE_TYPE_TX_FEE_BUMP: + return XDR_FeeBumpTransactionEnvelope(u.FeeBump()) } return nil } -func (u *PaymentResult) XdrUnionBodyName() string { - switch u.Code { - case PAYMENT_SUCCESS: - return "" - case PAYMENT_MALFORMED, PAYMENT_UNDERFUNDED, PAYMENT_SRC_NO_TRUST, PAYMENT_SRC_NOT_AUTHORIZED, PAYMENT_NO_DESTINATION, PAYMENT_NO_TRUST, PAYMENT_NOT_AUTHORIZED, PAYMENT_LINE_FULL, PAYMENT_NO_ISSUER: - return "" +func (u *TransactionEnvelope) XdrUnionBodyName() string { + switch u.Type { + case ENVELOPE_TYPE_TX_V0: + return "V0" + case ENVELOPE_TYPE_TX: + return "V1" + case ENVELOPE_TYPE_TX_FEE_BUMP: + return "FeeBump" } return "" } -type XdrType_PaymentResult = *PaymentResult +type XdrType_TransactionEnvelope = *TransactionEnvelope -func (v *PaymentResult) XdrPointer() interface{} { return v } -func (PaymentResult) XdrTypeName() string { return "PaymentResult" } -func (v PaymentResult) XdrValue() interface{} { return v } -func (v *PaymentResult) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -func (u *PaymentResult) XdrRecurse(x XDR, name string) { +func (v *TransactionEnvelope) XdrPointer() interface{} { return v } +func (TransactionEnvelope) XdrTypeName() string { return "TransactionEnvelope" } +func (v TransactionEnvelope) XdrValue() interface{} { return v } +func (v *TransactionEnvelope) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (u *TransactionEnvelope) XdrRecurse(x XDR, name string) { if name != "" { name = x.Sprintf("%s.", name) } - XDR_PaymentResultCode(&u.Code).XdrMarshal(x, x.Sprintf("%scode", name)) - switch u.Code { - case PAYMENT_SUCCESS: + XDR_EnvelopeType(&u.Type).XdrMarshal(x, x.Sprintf("%stype", name)) + switch u.Type { + case ENVELOPE_TYPE_TX_V0: + x.Marshal(x.Sprintf("%sv0", name), XDR_TransactionV0Envelope(u.V0())) return - case PAYMENT_MALFORMED, PAYMENT_UNDERFUNDED, PAYMENT_SRC_NO_TRUST, PAYMENT_SRC_NOT_AUTHORIZED, PAYMENT_NO_DESTINATION, PAYMENT_NO_TRUST, PAYMENT_NOT_AUTHORIZED, PAYMENT_LINE_FULL, PAYMENT_NO_ISSUER: + case ENVELOPE_TYPE_TX: + x.Marshal(x.Sprintf("%sv1", name), XDR_TransactionV1Envelope(u.V1())) + return + case ENVELOPE_TYPE_TX_FEE_BUMP: + x.Marshal(x.Sprintf("%sfeeBump", name), XDR_FeeBumpTransactionEnvelope(u.FeeBump())) return } - XdrPanic("invalid Code (%v) in PaymentResult", u.Code) + XdrPanic("invalid Type (%v) in TransactionEnvelope", u.Type) } -func XDR_PaymentResult(v *PaymentResult) *PaymentResult { return v } +func XDR_TransactionEnvelope(v *TransactionEnvelope) *TransactionEnvelope { return v } -var _XdrNames_PathPaymentStrictReceiveResultCode = map[int32]string{ - int32(PATH_PAYMENT_STRICT_RECEIVE_SUCCESS): "PATH_PAYMENT_STRICT_RECEIVE_SUCCESS", - int32(PATH_PAYMENT_STRICT_RECEIVE_MALFORMED): "PATH_PAYMENT_STRICT_RECEIVE_MALFORMED", - int32(PATH_PAYMENT_STRICT_RECEIVE_UNDERFUNDED): "PATH_PAYMENT_STRICT_RECEIVE_UNDERFUNDED", - int32(PATH_PAYMENT_STRICT_RECEIVE_SRC_NO_TRUST): "PATH_PAYMENT_STRICT_RECEIVE_SRC_NO_TRUST", - int32(PATH_PAYMENT_STRICT_RECEIVE_SRC_NOT_AUTHORIZED): "PATH_PAYMENT_STRICT_RECEIVE_SRC_NOT_AUTHORIZED", - int32(PATH_PAYMENT_STRICT_RECEIVE_NO_DESTINATION): "PATH_PAYMENT_STRICT_RECEIVE_NO_DESTINATION", - int32(PATH_PAYMENT_STRICT_RECEIVE_NO_TRUST): "PATH_PAYMENT_STRICT_RECEIVE_NO_TRUST", - int32(PATH_PAYMENT_STRICT_RECEIVE_NOT_AUTHORIZED): "PATH_PAYMENT_STRICT_RECEIVE_NOT_AUTHORIZED", - int32(PATH_PAYMENT_STRICT_RECEIVE_LINE_FULL): "PATH_PAYMENT_STRICT_RECEIVE_LINE_FULL", - int32(PATH_PAYMENT_STRICT_RECEIVE_NO_ISSUER): "PATH_PAYMENT_STRICT_RECEIVE_NO_ISSUER", - int32(PATH_PAYMENT_STRICT_RECEIVE_TOO_FEW_OFFERS): "PATH_PAYMENT_STRICT_RECEIVE_TOO_FEW_OFFERS", - int32(PATH_PAYMENT_STRICT_RECEIVE_OFFER_CROSS_SELF): "PATH_PAYMENT_STRICT_RECEIVE_OFFER_CROSS_SELF", - int32(PATH_PAYMENT_STRICT_RECEIVE_OVER_SENDMAX): "PATH_PAYMENT_STRICT_RECEIVE_OVER_SENDMAX", -} -var _XdrValues_PathPaymentStrictReceiveResultCode = map[string]int32{ - "PATH_PAYMENT_STRICT_RECEIVE_SUCCESS": int32(PATH_PAYMENT_STRICT_RECEIVE_SUCCESS), - "PATH_PAYMENT_STRICT_RECEIVE_MALFORMED": int32(PATH_PAYMENT_STRICT_RECEIVE_MALFORMED), - "PATH_PAYMENT_STRICT_RECEIVE_UNDERFUNDED": int32(PATH_PAYMENT_STRICT_RECEIVE_UNDERFUNDED), - "PATH_PAYMENT_STRICT_RECEIVE_SRC_NO_TRUST": int32(PATH_PAYMENT_STRICT_RECEIVE_SRC_NO_TRUST), - "PATH_PAYMENT_STRICT_RECEIVE_SRC_NOT_AUTHORIZED": int32(PATH_PAYMENT_STRICT_RECEIVE_SRC_NOT_AUTHORIZED), - "PATH_PAYMENT_STRICT_RECEIVE_NO_DESTINATION": int32(PATH_PAYMENT_STRICT_RECEIVE_NO_DESTINATION), - "PATH_PAYMENT_STRICT_RECEIVE_NO_TRUST": int32(PATH_PAYMENT_STRICT_RECEIVE_NO_TRUST), - "PATH_PAYMENT_STRICT_RECEIVE_NOT_AUTHORIZED": int32(PATH_PAYMENT_STRICT_RECEIVE_NOT_AUTHORIZED), - "PATH_PAYMENT_STRICT_RECEIVE_LINE_FULL": int32(PATH_PAYMENT_STRICT_RECEIVE_LINE_FULL), - "PATH_PAYMENT_STRICT_RECEIVE_NO_ISSUER": int32(PATH_PAYMENT_STRICT_RECEIVE_NO_ISSUER), - "PATH_PAYMENT_STRICT_RECEIVE_TOO_FEW_OFFERS": int32(PATH_PAYMENT_STRICT_RECEIVE_TOO_FEW_OFFERS), - "PATH_PAYMENT_STRICT_RECEIVE_OFFER_CROSS_SELF": int32(PATH_PAYMENT_STRICT_RECEIVE_OFFER_CROSS_SELF), - "PATH_PAYMENT_STRICT_RECEIVE_OVER_SENDMAX": int32(PATH_PAYMENT_STRICT_RECEIVE_OVER_SENDMAX), +var _XdrTags_XdrAnon_TransactionSignaturePayload_TaggedTransaction = map[int32]bool{ + XdrToI32(ENVELOPE_TYPE_TX): true, + XdrToI32(ENVELOPE_TYPE_TX_FEE_BUMP): true, } -func (PathPaymentStrictReceiveResultCode) XdrEnumNames() map[int32]string { - return _XdrNames_PathPaymentStrictReceiveResultCode +func (_ XdrAnon_TransactionSignaturePayload_TaggedTransaction) XdrValidTags() map[int32]bool { + return _XdrTags_XdrAnon_TransactionSignaturePayload_TaggedTransaction } -func (v PathPaymentStrictReceiveResultCode) String() string { - if s, ok := _XdrNames_PathPaymentStrictReceiveResultCode[int32(v)]; ok { - return s +func (u *XdrAnon_TransactionSignaturePayload_TaggedTransaction) Tx() *Transaction { + switch u.Type { + case ENVELOPE_TYPE_TX: + if v, ok := u._u.(*Transaction); ok { + return v + } else { + var zero Transaction + u._u = &zero + return &zero + } + default: + XdrPanic("XdrAnon_TransactionSignaturePayload_TaggedTransaction.Tx accessed when Type == %v", u.Type) + return nil } - return fmt.Sprintf("PathPaymentStrictReceiveResultCode#%d", v) } -func (v *PathPaymentStrictReceiveResultCode) Scan(ss fmt.ScanState, _ rune) error { - if tok, err := ss.Token(true, XdrSymChar); err != nil { - return err - } else { - stok := string(tok) - if val, ok := _XdrValues_PathPaymentStrictReceiveResultCode[stok]; ok { - *v = PathPaymentStrictReceiveResultCode(val) - return nil - } else if stok == "PathPaymentStrictReceiveResultCode" { - if n, err := fmt.Fscanf(ss, "#%d", (*int32)(v)); n == 1 && err == nil { - return nil - } - } - return XdrError(fmt.Sprintf("%s is not a valid PathPaymentStrictReceiveResultCode.", stok)) +func (u *XdrAnon_TransactionSignaturePayload_TaggedTransaction) FeeBump() *FeeBumpTransaction { + switch u.Type { + case ENVELOPE_TYPE_TX_FEE_BUMP: + if v, ok := u._u.(*FeeBumpTransaction); ok { + return v + } else { + var zero FeeBumpTransaction + u._u = &zero + return &zero + } + default: + XdrPanic("XdrAnon_TransactionSignaturePayload_TaggedTransaction.FeeBump accessed when Type == %v", u.Type) + return nil } } -func (v PathPaymentStrictReceiveResultCode) GetU32() uint32 { return uint32(v) } -func (v *PathPaymentStrictReceiveResultCode) SetU32(n uint32) { - *v = PathPaymentStrictReceiveResultCode(n) -} -func (v *PathPaymentStrictReceiveResultCode) XdrPointer() interface{} { return v } -func (PathPaymentStrictReceiveResultCode) XdrTypeName() string { - return "PathPaymentStrictReceiveResultCode" +func (u XdrAnon_TransactionSignaturePayload_TaggedTransaction) XdrValid() bool { + switch u.Type { + case ENVELOPE_TYPE_TX, ENVELOPE_TYPE_TX_FEE_BUMP: + return true + } + return false } -func (v PathPaymentStrictReceiveResultCode) XdrValue() interface{} { return v } -func (v *PathPaymentStrictReceiveResultCode) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } - -type XdrType_PathPaymentStrictReceiveResultCode = *PathPaymentStrictReceiveResultCode - -func XDR_PathPaymentStrictReceiveResultCode(v *PathPaymentStrictReceiveResultCode) *PathPaymentStrictReceiveResultCode { - return v +func (u *XdrAnon_TransactionSignaturePayload_TaggedTransaction) XdrUnionTag() XdrNum32 { + return XDR_EnvelopeType(&u.Type) } - -var _XdrComments_PathPaymentStrictReceiveResultCode = map[int32]string{ - int32(PATH_PAYMENT_STRICT_RECEIVE_SUCCESS): "success", - int32(PATH_PAYMENT_STRICT_RECEIVE_MALFORMED): "bad input", - int32(PATH_PAYMENT_STRICT_RECEIVE_UNDERFUNDED): "not enough funds in source account", - int32(PATH_PAYMENT_STRICT_RECEIVE_SRC_NO_TRUST): "no trust line on source account", - int32(PATH_PAYMENT_STRICT_RECEIVE_SRC_NOT_AUTHORIZED): "source not authorized to transfer", - int32(PATH_PAYMENT_STRICT_RECEIVE_NO_DESTINATION): "destination account does not exist", - int32(PATH_PAYMENT_STRICT_RECEIVE_NO_TRUST): "dest missing a trust line for asset", - int32(PATH_PAYMENT_STRICT_RECEIVE_NOT_AUTHORIZED): "dest not authorized to hold asset", - int32(PATH_PAYMENT_STRICT_RECEIVE_LINE_FULL): "dest would go above their limit", - int32(PATH_PAYMENT_STRICT_RECEIVE_NO_ISSUER): "missing issuer on one asset", - int32(PATH_PAYMENT_STRICT_RECEIVE_TOO_FEW_OFFERS): "not enough offers to satisfy path", - int32(PATH_PAYMENT_STRICT_RECEIVE_OFFER_CROSS_SELF): "would cross one of its own offers", - int32(PATH_PAYMENT_STRICT_RECEIVE_OVER_SENDMAX): "could not satisfy sendmax", +func (u *XdrAnon_TransactionSignaturePayload_TaggedTransaction) XdrUnionTagName() string { + return "Type" } - -func (e PathPaymentStrictReceiveResultCode) XdrEnumComments() map[int32]string { - return _XdrComments_PathPaymentStrictReceiveResultCode +func (u *XdrAnon_TransactionSignaturePayload_TaggedTransaction) XdrUnionBody() XdrType { + switch u.Type { + case ENVELOPE_TYPE_TX: + return XDR_Transaction(u.Tx()) + case ENVELOPE_TYPE_TX_FEE_BUMP: + return XDR_FeeBumpTransaction(u.FeeBump()) + } + return nil } - -type XdrType_SimplePaymentResult = *SimplePaymentResult - -func (v *SimplePaymentResult) XdrPointer() interface{} { return v } -func (SimplePaymentResult) XdrTypeName() string { return "SimplePaymentResult" } -func (v SimplePaymentResult) XdrValue() interface{} { return v } -func (v *SimplePaymentResult) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -func (v *SimplePaymentResult) XdrRecurse(x XDR, name string) { - if name != "" { - name = x.Sprintf("%s.", name) +func (u *XdrAnon_TransactionSignaturePayload_TaggedTransaction) XdrUnionBodyName() string { + switch u.Type { + case ENVELOPE_TYPE_TX: + return "Tx" + case ENVELOPE_TYPE_TX_FEE_BUMP: + return "FeeBump" } - x.Marshal(x.Sprintf("%sdestination", name), XDR_AccountID(&v.Destination)) - x.Marshal(x.Sprintf("%sasset", name), XDR_Asset(&v.Asset)) - x.Marshal(x.Sprintf("%samount", name), XDR_Int64(&v.Amount)) + return "" } -func XDR_SimplePaymentResult(v *SimplePaymentResult) *SimplePaymentResult { return v } -type _XdrVec_unbounded_ClaimAtom []ClaimAtom +type XdrType_XdrAnon_TransactionSignaturePayload_TaggedTransaction = *XdrAnon_TransactionSignaturePayload_TaggedTransaction -func (_XdrVec_unbounded_ClaimAtom) XdrBound() uint32 { - const bound uint32 = 4294967295 // Force error if not const or doesn't fit - return bound +func (v *XdrAnon_TransactionSignaturePayload_TaggedTransaction) XdrPointer() interface{} { return v } +func (XdrAnon_TransactionSignaturePayload_TaggedTransaction) XdrTypeName() string { + return "XdrAnon_TransactionSignaturePayload_TaggedTransaction" } -func (_XdrVec_unbounded_ClaimAtom) XdrCheckLen(length uint32) { - if length > uint32(4294967295) { - XdrPanic("_XdrVec_unbounded_ClaimAtom length %d exceeds bound 4294967295", length) - } else if int(length) < 0 { - XdrPanic("_XdrVec_unbounded_ClaimAtom length %d exceeds max int", length) - } +func (v XdrAnon_TransactionSignaturePayload_TaggedTransaction) XdrValue() interface{} { return v } +func (v *XdrAnon_TransactionSignaturePayload_TaggedTransaction) XdrMarshal(x XDR, name string) { + x.Marshal(name, v) } -func (v _XdrVec_unbounded_ClaimAtom) GetVecLen() uint32 { return uint32(len(v)) } -func (v *_XdrVec_unbounded_ClaimAtom) SetVecLen(length uint32) { - v.XdrCheckLen(length) - if int(length) <= cap(*v) { - if int(length) != len(*v) { - *v = (*v)[:int(length)] - } - return +func (u *XdrAnon_TransactionSignaturePayload_TaggedTransaction) XdrRecurse(x XDR, name string) { + if name != "" { + name = x.Sprintf("%s.", name) } - newcap := 2 * cap(*v) - if newcap < int(length) { // also catches overflow where 2*cap < 0 - newcap = int(length) - } else if bound := uint(4294967295); uint(newcap) > bound { - if int(bound) < 0 { - bound = ^uint(0) >> 1 - } - newcap = int(bound) + XDR_EnvelopeType(&u.Type).XdrMarshal(x, x.Sprintf("%stype", name)) + switch u.Type { + case ENVELOPE_TYPE_TX: + x.Marshal(x.Sprintf("%stx", name), XDR_Transaction(u.Tx())) + return + case ENVELOPE_TYPE_TX_FEE_BUMP: + x.Marshal(x.Sprintf("%sfeeBump", name), XDR_FeeBumpTransaction(u.FeeBump())) + return } - nv := make([]ClaimAtom, int(length), newcap) - copy(nv, *v) - *v = nv + XdrPanic("invalid Type (%v) in XdrAnon_TransactionSignaturePayload_TaggedTransaction", u.Type) } -func (v *_XdrVec_unbounded_ClaimAtom) XdrMarshalN(x XDR, name string, n uint32) { - v.XdrCheckLen(n) - for i := 0; i < int(n); i++ { - if i >= len(*v) { - v.SetVecLen(uint32(i + 1)) +func (v *XdrAnon_TransactionSignaturePayload_TaggedTransaction) XdrInitialize() { + var zero EnvelopeType + switch zero { + case ENVELOPE_TYPE_TX, ENVELOPE_TYPE_TX_FEE_BUMP: + default: + if v.Type == zero { + v.Type = ENVELOPE_TYPE_TX } - XDR_ClaimAtom(&(*v)[i]).XdrMarshal(x, x.Sprintf("%s[%d]", name, i)) - } - if int(n) < len(*v) { - *v = (*v)[:int(n)] } } -func (v *_XdrVec_unbounded_ClaimAtom) XdrRecurse(x XDR, name string) { - size := XdrSize{Size: uint32(len(*v)), Bound: 4294967295} - x.Marshal(name, &size) - v.XdrMarshalN(x, name, size.Size) +func XDR_XdrAnon_TransactionSignaturePayload_TaggedTransaction(v *XdrAnon_TransactionSignaturePayload_TaggedTransaction) *XdrAnon_TransactionSignaturePayload_TaggedTransaction { + return v } -func (_XdrVec_unbounded_ClaimAtom) XdrTypeName() string { return "ClaimAtom<>" } -func (v *_XdrVec_unbounded_ClaimAtom) XdrPointer() interface{} { return (*[]ClaimAtom)(v) } -func (v _XdrVec_unbounded_ClaimAtom) XdrValue() interface{} { return ([]ClaimAtom)(v) } -func (v *_XdrVec_unbounded_ClaimAtom) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -type XdrType_XdrAnon_PathPaymentStrictReceiveResult_Success = *XdrAnon_PathPaymentStrictReceiveResult_Success +type XdrType_TransactionSignaturePayload = *TransactionSignaturePayload -func (v *XdrAnon_PathPaymentStrictReceiveResult_Success) XdrPointer() interface{} { return v } -func (XdrAnon_PathPaymentStrictReceiveResult_Success) XdrTypeName() string { - return "XdrAnon_PathPaymentStrictReceiveResult_Success" -} -func (v XdrAnon_PathPaymentStrictReceiveResult_Success) XdrValue() interface{} { return v } -func (v *XdrAnon_PathPaymentStrictReceiveResult_Success) XdrMarshal(x XDR, name string) { - x.Marshal(name, v) -} -func (v *XdrAnon_PathPaymentStrictReceiveResult_Success) XdrRecurse(x XDR, name string) { +func (v *TransactionSignaturePayload) XdrPointer() interface{} { return v } +func (TransactionSignaturePayload) XdrTypeName() string { return "TransactionSignaturePayload" } +func (v TransactionSignaturePayload) XdrValue() interface{} { return v } +func (v *TransactionSignaturePayload) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v *TransactionSignaturePayload) XdrRecurse(x XDR, name string) { if name != "" { name = x.Sprintf("%s.", name) } - x.Marshal(x.Sprintf("%soffers", name), (*_XdrVec_unbounded_ClaimAtom)(&v.Offers)) - x.Marshal(x.Sprintf("%slast", name), XDR_SimplePaymentResult(&v.Last)) + x.Marshal(x.Sprintf("%snetworkId", name), XDR_Hash(&v.NetworkId)) + x.Marshal(x.Sprintf("%staggedTransaction", name), XDR_XdrAnon_TransactionSignaturePayload_TaggedTransaction(&v.TaggedTransaction)) } -func XDR_XdrAnon_PathPaymentStrictReceiveResult_Success(v *XdrAnon_PathPaymentStrictReceiveResult_Success) *XdrAnon_PathPaymentStrictReceiveResult_Success { +func XDR_TransactionSignaturePayload(v *TransactionSignaturePayload) *TransactionSignaturePayload { return v } -var _XdrTags_PathPaymentStrictReceiveResult = map[int32]bool{ - XdrToI32(PATH_PAYMENT_STRICT_RECEIVE_SUCCESS): true, - XdrToI32(PATH_PAYMENT_STRICT_RECEIVE_MALFORMED): true, - XdrToI32(PATH_PAYMENT_STRICT_RECEIVE_UNDERFUNDED): true, - XdrToI32(PATH_PAYMENT_STRICT_RECEIVE_SRC_NO_TRUST): true, - XdrToI32(PATH_PAYMENT_STRICT_RECEIVE_SRC_NOT_AUTHORIZED): true, - XdrToI32(PATH_PAYMENT_STRICT_RECEIVE_NO_DESTINATION): true, - XdrToI32(PATH_PAYMENT_STRICT_RECEIVE_NO_TRUST): true, - XdrToI32(PATH_PAYMENT_STRICT_RECEIVE_NOT_AUTHORIZED): true, - XdrToI32(PATH_PAYMENT_STRICT_RECEIVE_LINE_FULL): true, - XdrToI32(PATH_PAYMENT_STRICT_RECEIVE_NO_ISSUER): true, - XdrToI32(PATH_PAYMENT_STRICT_RECEIVE_TOO_FEW_OFFERS): true, - XdrToI32(PATH_PAYMENT_STRICT_RECEIVE_OFFER_CROSS_SELF): true, - XdrToI32(PATH_PAYMENT_STRICT_RECEIVE_OVER_SENDMAX): true, +var _XdrNames_ClaimAtomType = map[int32]string{ + int32(CLAIM_ATOM_TYPE_V0): "CLAIM_ATOM_TYPE_V0", + int32(CLAIM_ATOM_TYPE_ORDER_BOOK): "CLAIM_ATOM_TYPE_ORDER_BOOK", + int32(CLAIM_ATOM_TYPE_LIQUIDITY_POOL): "CLAIM_ATOM_TYPE_LIQUIDITY_POOL", +} +var _XdrValues_ClaimAtomType = map[string]int32{ + "CLAIM_ATOM_TYPE_V0": int32(CLAIM_ATOM_TYPE_V0), + "CLAIM_ATOM_TYPE_ORDER_BOOK": int32(CLAIM_ATOM_TYPE_ORDER_BOOK), + "CLAIM_ATOM_TYPE_LIQUIDITY_POOL": int32(CLAIM_ATOM_TYPE_LIQUIDITY_POOL), } -func (_ PathPaymentStrictReceiveResult) XdrValidTags() map[int32]bool { - return _XdrTags_PathPaymentStrictReceiveResult +func (ClaimAtomType) XdrEnumNames() map[int32]string { + return _XdrNames_ClaimAtomType } -func (u *PathPaymentStrictReceiveResult) Success() *XdrAnon_PathPaymentStrictReceiveResult_Success { - switch u.Code { - case PATH_PAYMENT_STRICT_RECEIVE_SUCCESS: - if v, ok := u._u.(*XdrAnon_PathPaymentStrictReceiveResult_Success); ok { - return v - } else { - var zero XdrAnon_PathPaymentStrictReceiveResult_Success - u._u = &zero - return &zero - } - default: - XdrPanic("PathPaymentStrictReceiveResult.Success accessed when Code == %v", u.Code) - return nil +func (v ClaimAtomType) String() string { + if s, ok := _XdrNames_ClaimAtomType[int32(v)]; ok { + return s } + return fmt.Sprintf("ClaimAtomType#%d", v) } - -// the asset that caused the error -func (u *PathPaymentStrictReceiveResult) NoIssuer() *Asset { - switch u.Code { - case PATH_PAYMENT_STRICT_RECEIVE_NO_ISSUER: - if v, ok := u._u.(*Asset); ok { - return v - } else { - var zero Asset - u._u = &zero - return &zero +func (v *ClaimAtomType) Scan(ss fmt.ScanState, _ rune) error { + if tok, err := ss.Token(true, XdrSymChar); err != nil { + return err + } else { + stok := string(tok) + if val, ok := _XdrValues_ClaimAtomType[stok]; ok { + *v = ClaimAtomType(val) + return nil + } else if stok == "ClaimAtomType" { + if n, err := fmt.Fscanf(ss, "#%d", (*int32)(v)); n == 1 && err == nil { + return nil + } } - default: - XdrPanic("PathPaymentStrictReceiveResult.NoIssuer accessed when Code == %v", u.Code) - return nil + return XdrError(fmt.Sprintf("%s is not a valid ClaimAtomType.", stok)) } } -func (u PathPaymentStrictReceiveResult) XdrValid() bool { - switch u.Code { - case PATH_PAYMENT_STRICT_RECEIVE_SUCCESS, PATH_PAYMENT_STRICT_RECEIVE_MALFORMED, PATH_PAYMENT_STRICT_RECEIVE_UNDERFUNDED, PATH_PAYMENT_STRICT_RECEIVE_SRC_NO_TRUST, PATH_PAYMENT_STRICT_RECEIVE_SRC_NOT_AUTHORIZED, PATH_PAYMENT_STRICT_RECEIVE_NO_DESTINATION, PATH_PAYMENT_STRICT_RECEIVE_NO_TRUST, PATH_PAYMENT_STRICT_RECEIVE_NOT_AUTHORIZED, PATH_PAYMENT_STRICT_RECEIVE_LINE_FULL, PATH_PAYMENT_STRICT_RECEIVE_NO_ISSUER, PATH_PAYMENT_STRICT_RECEIVE_TOO_FEW_OFFERS, PATH_PAYMENT_STRICT_RECEIVE_OFFER_CROSS_SELF, PATH_PAYMENT_STRICT_RECEIVE_OVER_SENDMAX: - return true - } - return false -} -func (u *PathPaymentStrictReceiveResult) XdrUnionTag() XdrNum32 { - return XDR_PathPaymentStrictReceiveResultCode(&u.Code) -} -func (u *PathPaymentStrictReceiveResult) XdrUnionTagName() string { - return "Code" -} -func (u *PathPaymentStrictReceiveResult) XdrUnionBody() XdrType { - switch u.Code { - case PATH_PAYMENT_STRICT_RECEIVE_SUCCESS: - return XDR_XdrAnon_PathPaymentStrictReceiveResult_Success(u.Success()) - case PATH_PAYMENT_STRICT_RECEIVE_MALFORMED, PATH_PAYMENT_STRICT_RECEIVE_UNDERFUNDED, PATH_PAYMENT_STRICT_RECEIVE_SRC_NO_TRUST, PATH_PAYMENT_STRICT_RECEIVE_SRC_NOT_AUTHORIZED, PATH_PAYMENT_STRICT_RECEIVE_NO_DESTINATION, PATH_PAYMENT_STRICT_RECEIVE_NO_TRUST, PATH_PAYMENT_STRICT_RECEIVE_NOT_AUTHORIZED, PATH_PAYMENT_STRICT_RECEIVE_LINE_FULL: - return nil - case PATH_PAYMENT_STRICT_RECEIVE_NO_ISSUER: - return XDR_Asset(u.NoIssuer()) - case PATH_PAYMENT_STRICT_RECEIVE_TOO_FEW_OFFERS, PATH_PAYMENT_STRICT_RECEIVE_OFFER_CROSS_SELF, PATH_PAYMENT_STRICT_RECEIVE_OVER_SENDMAX: - return nil - } - return nil -} -func (u *PathPaymentStrictReceiveResult) XdrUnionBodyName() string { - switch u.Code { - case PATH_PAYMENT_STRICT_RECEIVE_SUCCESS: - return "Success" - case PATH_PAYMENT_STRICT_RECEIVE_MALFORMED, PATH_PAYMENT_STRICT_RECEIVE_UNDERFUNDED, PATH_PAYMENT_STRICT_RECEIVE_SRC_NO_TRUST, PATH_PAYMENT_STRICT_RECEIVE_SRC_NOT_AUTHORIZED, PATH_PAYMENT_STRICT_RECEIVE_NO_DESTINATION, PATH_PAYMENT_STRICT_RECEIVE_NO_TRUST, PATH_PAYMENT_STRICT_RECEIVE_NOT_AUTHORIZED, PATH_PAYMENT_STRICT_RECEIVE_LINE_FULL: - return "" - case PATH_PAYMENT_STRICT_RECEIVE_NO_ISSUER: - return "NoIssuer" - case PATH_PAYMENT_STRICT_RECEIVE_TOO_FEW_OFFERS, PATH_PAYMENT_STRICT_RECEIVE_OFFER_CROSS_SELF, PATH_PAYMENT_STRICT_RECEIVE_OVER_SENDMAX: - return "" - } - return "" -} +func (v ClaimAtomType) GetU32() uint32 { return uint32(v) } +func (v *ClaimAtomType) SetU32(n uint32) { *v = ClaimAtomType(n) } +func (v *ClaimAtomType) XdrPointer() interface{} { return v } +func (ClaimAtomType) XdrTypeName() string { return "ClaimAtomType" } +func (v ClaimAtomType) XdrValue() interface{} { return v } +func (v *ClaimAtomType) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -type XdrType_PathPaymentStrictReceiveResult = *PathPaymentStrictReceiveResult +type XdrType_ClaimAtomType = *ClaimAtomType -func (v *PathPaymentStrictReceiveResult) XdrPointer() interface{} { return v } -func (PathPaymentStrictReceiveResult) XdrTypeName() string { return "PathPaymentStrictReceiveResult" } -func (v PathPaymentStrictReceiveResult) XdrValue() interface{} { return v } -func (v *PathPaymentStrictReceiveResult) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -func (u *PathPaymentStrictReceiveResult) XdrRecurse(x XDR, name string) { +func XDR_ClaimAtomType(v *ClaimAtomType) *ClaimAtomType { return v } + +type XdrType_ClaimOfferAtomV0 = *ClaimOfferAtomV0 + +func (v *ClaimOfferAtomV0) XdrPointer() interface{} { return v } +func (ClaimOfferAtomV0) XdrTypeName() string { return "ClaimOfferAtomV0" } +func (v ClaimOfferAtomV0) XdrValue() interface{} { return v } +func (v *ClaimOfferAtomV0) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v *ClaimOfferAtomV0) XdrRecurse(x XDR, name string) { if name != "" { name = x.Sprintf("%s.", name) } - XDR_PathPaymentStrictReceiveResultCode(&u.Code).XdrMarshal(x, x.Sprintf("%scode", name)) - switch u.Code { - case PATH_PAYMENT_STRICT_RECEIVE_SUCCESS: - x.Marshal(x.Sprintf("%ssuccess", name), XDR_XdrAnon_PathPaymentStrictReceiveResult_Success(u.Success())) - return - case PATH_PAYMENT_STRICT_RECEIVE_MALFORMED, PATH_PAYMENT_STRICT_RECEIVE_UNDERFUNDED, PATH_PAYMENT_STRICT_RECEIVE_SRC_NO_TRUST, PATH_PAYMENT_STRICT_RECEIVE_SRC_NOT_AUTHORIZED, PATH_PAYMENT_STRICT_RECEIVE_NO_DESTINATION, PATH_PAYMENT_STRICT_RECEIVE_NO_TRUST, PATH_PAYMENT_STRICT_RECEIVE_NOT_AUTHORIZED, PATH_PAYMENT_STRICT_RECEIVE_LINE_FULL: - return - case PATH_PAYMENT_STRICT_RECEIVE_NO_ISSUER: - x.Marshal(x.Sprintf("%snoIssuer", name), XDR_Asset(u.NoIssuer())) - return - case PATH_PAYMENT_STRICT_RECEIVE_TOO_FEW_OFFERS, PATH_PAYMENT_STRICT_RECEIVE_OFFER_CROSS_SELF, PATH_PAYMENT_STRICT_RECEIVE_OVER_SENDMAX: - return - } - XdrPanic("invalid Code (%v) in PathPaymentStrictReceiveResult", u.Code) -} -func XDR_PathPaymentStrictReceiveResult(v *PathPaymentStrictReceiveResult) *PathPaymentStrictReceiveResult { - return v + x.Marshal(x.Sprintf("%ssellerEd25519", name), XDR_Uint256(&v.SellerEd25519)) + x.Marshal(x.Sprintf("%sofferID", name), XDR_Int64(&v.OfferID)) + x.Marshal(x.Sprintf("%sassetSold", name), XDR_Asset(&v.AssetSold)) + x.Marshal(x.Sprintf("%samountSold", name), XDR_Int64(&v.AmountSold)) + x.Marshal(x.Sprintf("%sassetBought", name), XDR_Asset(&v.AssetBought)) + x.Marshal(x.Sprintf("%samountBought", name), XDR_Int64(&v.AmountBought)) } +func XDR_ClaimOfferAtomV0(v *ClaimOfferAtomV0) *ClaimOfferAtomV0 { return v } -var _XdrNames_PathPaymentStrictSendResultCode = map[int32]string{ - int32(PATH_PAYMENT_STRICT_SEND_SUCCESS): "PATH_PAYMENT_STRICT_SEND_SUCCESS", - int32(PATH_PAYMENT_STRICT_SEND_MALFORMED): "PATH_PAYMENT_STRICT_SEND_MALFORMED", - int32(PATH_PAYMENT_STRICT_SEND_UNDERFUNDED): "PATH_PAYMENT_STRICT_SEND_UNDERFUNDED", - int32(PATH_PAYMENT_STRICT_SEND_SRC_NO_TRUST): "PATH_PAYMENT_STRICT_SEND_SRC_NO_TRUST", - int32(PATH_PAYMENT_STRICT_SEND_SRC_NOT_AUTHORIZED): "PATH_PAYMENT_STRICT_SEND_SRC_NOT_AUTHORIZED", - int32(PATH_PAYMENT_STRICT_SEND_NO_DESTINATION): "PATH_PAYMENT_STRICT_SEND_NO_DESTINATION", - int32(PATH_PAYMENT_STRICT_SEND_NO_TRUST): "PATH_PAYMENT_STRICT_SEND_NO_TRUST", - int32(PATH_PAYMENT_STRICT_SEND_NOT_AUTHORIZED): "PATH_PAYMENT_STRICT_SEND_NOT_AUTHORIZED", - int32(PATH_PAYMENT_STRICT_SEND_LINE_FULL): "PATH_PAYMENT_STRICT_SEND_LINE_FULL", - int32(PATH_PAYMENT_STRICT_SEND_NO_ISSUER): "PATH_PAYMENT_STRICT_SEND_NO_ISSUER", - int32(PATH_PAYMENT_STRICT_SEND_TOO_FEW_OFFERS): "PATH_PAYMENT_STRICT_SEND_TOO_FEW_OFFERS", - int32(PATH_PAYMENT_STRICT_SEND_OFFER_CROSS_SELF): "PATH_PAYMENT_STRICT_SEND_OFFER_CROSS_SELF", - int32(PATH_PAYMENT_STRICT_SEND_UNDER_DESTMIN): "PATH_PAYMENT_STRICT_SEND_UNDER_DESTMIN", -} -var _XdrValues_PathPaymentStrictSendResultCode = map[string]int32{ - "PATH_PAYMENT_STRICT_SEND_SUCCESS": int32(PATH_PAYMENT_STRICT_SEND_SUCCESS), - "PATH_PAYMENT_STRICT_SEND_MALFORMED": int32(PATH_PAYMENT_STRICT_SEND_MALFORMED), - "PATH_PAYMENT_STRICT_SEND_UNDERFUNDED": int32(PATH_PAYMENT_STRICT_SEND_UNDERFUNDED), - "PATH_PAYMENT_STRICT_SEND_SRC_NO_TRUST": int32(PATH_PAYMENT_STRICT_SEND_SRC_NO_TRUST), - "PATH_PAYMENT_STRICT_SEND_SRC_NOT_AUTHORIZED": int32(PATH_PAYMENT_STRICT_SEND_SRC_NOT_AUTHORIZED), - "PATH_PAYMENT_STRICT_SEND_NO_DESTINATION": int32(PATH_PAYMENT_STRICT_SEND_NO_DESTINATION), - "PATH_PAYMENT_STRICT_SEND_NO_TRUST": int32(PATH_PAYMENT_STRICT_SEND_NO_TRUST), - "PATH_PAYMENT_STRICT_SEND_NOT_AUTHORIZED": int32(PATH_PAYMENT_STRICT_SEND_NOT_AUTHORIZED), - "PATH_PAYMENT_STRICT_SEND_LINE_FULL": int32(PATH_PAYMENT_STRICT_SEND_LINE_FULL), - "PATH_PAYMENT_STRICT_SEND_NO_ISSUER": int32(PATH_PAYMENT_STRICT_SEND_NO_ISSUER), - "PATH_PAYMENT_STRICT_SEND_TOO_FEW_OFFERS": int32(PATH_PAYMENT_STRICT_SEND_TOO_FEW_OFFERS), - "PATH_PAYMENT_STRICT_SEND_OFFER_CROSS_SELF": int32(PATH_PAYMENT_STRICT_SEND_OFFER_CROSS_SELF), - "PATH_PAYMENT_STRICT_SEND_UNDER_DESTMIN": int32(PATH_PAYMENT_STRICT_SEND_UNDER_DESTMIN), -} +type XdrType_ClaimOfferAtom = *ClaimOfferAtom -func (PathPaymentStrictSendResultCode) XdrEnumNames() map[int32]string { - return _XdrNames_PathPaymentStrictSendResultCode -} -func (v PathPaymentStrictSendResultCode) String() string { - if s, ok := _XdrNames_PathPaymentStrictSendResultCode[int32(v)]; ok { - return s - } - return fmt.Sprintf("PathPaymentStrictSendResultCode#%d", v) -} -func (v *PathPaymentStrictSendResultCode) Scan(ss fmt.ScanState, _ rune) error { - if tok, err := ss.Token(true, XdrSymChar); err != nil { - return err - } else { - stok := string(tok) - if val, ok := _XdrValues_PathPaymentStrictSendResultCode[stok]; ok { - *v = PathPaymentStrictSendResultCode(val) - return nil - } else if stok == "PathPaymentStrictSendResultCode" { - if n, err := fmt.Fscanf(ss, "#%d", (*int32)(v)); n == 1 && err == nil { - return nil - } - } - return XdrError(fmt.Sprintf("%s is not a valid PathPaymentStrictSendResultCode.", stok)) +func (v *ClaimOfferAtom) XdrPointer() interface{} { return v } +func (ClaimOfferAtom) XdrTypeName() string { return "ClaimOfferAtom" } +func (v ClaimOfferAtom) XdrValue() interface{} { return v } +func (v *ClaimOfferAtom) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v *ClaimOfferAtom) XdrRecurse(x XDR, name string) { + if name != "" { + name = x.Sprintf("%s.", name) } + x.Marshal(x.Sprintf("%ssellerID", name), XDR_AccountID(&v.SellerID)) + x.Marshal(x.Sprintf("%sofferID", name), XDR_Int64(&v.OfferID)) + x.Marshal(x.Sprintf("%sassetSold", name), XDR_Asset(&v.AssetSold)) + x.Marshal(x.Sprintf("%samountSold", name), XDR_Int64(&v.AmountSold)) + x.Marshal(x.Sprintf("%sassetBought", name), XDR_Asset(&v.AssetBought)) + x.Marshal(x.Sprintf("%samountBought", name), XDR_Int64(&v.AmountBought)) } -func (v PathPaymentStrictSendResultCode) GetU32() uint32 { return uint32(v) } -func (v *PathPaymentStrictSendResultCode) SetU32(n uint32) { *v = PathPaymentStrictSendResultCode(n) } -func (v *PathPaymentStrictSendResultCode) XdrPointer() interface{} { return v } -func (PathPaymentStrictSendResultCode) XdrTypeName() string { return "PathPaymentStrictSendResultCode" } -func (v PathPaymentStrictSendResultCode) XdrValue() interface{} { return v } -func (v *PathPaymentStrictSendResultCode) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } - -type XdrType_PathPaymentStrictSendResultCode = *PathPaymentStrictSendResultCode - -func XDR_PathPaymentStrictSendResultCode(v *PathPaymentStrictSendResultCode) *PathPaymentStrictSendResultCode { - return v -} - -var _XdrComments_PathPaymentStrictSendResultCode = map[int32]string{ - int32(PATH_PAYMENT_STRICT_SEND_SUCCESS): "success", - int32(PATH_PAYMENT_STRICT_SEND_MALFORMED): "bad input", - int32(PATH_PAYMENT_STRICT_SEND_UNDERFUNDED): "not enough funds in source account", - int32(PATH_PAYMENT_STRICT_SEND_SRC_NO_TRUST): "no trust line on source account", - int32(PATH_PAYMENT_STRICT_SEND_SRC_NOT_AUTHORIZED): "source not authorized to transfer", - int32(PATH_PAYMENT_STRICT_SEND_NO_DESTINATION): "destination account does not exist", - int32(PATH_PAYMENT_STRICT_SEND_NO_TRUST): "dest missing a trust line for asset", - int32(PATH_PAYMENT_STRICT_SEND_NOT_AUTHORIZED): "dest not authorized to hold asset", - int32(PATH_PAYMENT_STRICT_SEND_LINE_FULL): "dest would go above their limit", - int32(PATH_PAYMENT_STRICT_SEND_NO_ISSUER): "missing issuer on one asset", - int32(PATH_PAYMENT_STRICT_SEND_TOO_FEW_OFFERS): "not enough offers to satisfy path", - int32(PATH_PAYMENT_STRICT_SEND_OFFER_CROSS_SELF): "would cross one of its own offers", - int32(PATH_PAYMENT_STRICT_SEND_UNDER_DESTMIN): "could not satisfy destMin", -} - -func (e PathPaymentStrictSendResultCode) XdrEnumComments() map[int32]string { - return _XdrComments_PathPaymentStrictSendResultCode -} +func XDR_ClaimOfferAtom(v *ClaimOfferAtom) *ClaimOfferAtom { return v } -type XdrType_XdrAnon_PathPaymentStrictSendResult_Success = *XdrAnon_PathPaymentStrictSendResult_Success +type XdrType_ClaimLiquidityAtom = *ClaimLiquidityAtom -func (v *XdrAnon_PathPaymentStrictSendResult_Success) XdrPointer() interface{} { return v } -func (XdrAnon_PathPaymentStrictSendResult_Success) XdrTypeName() string { - return "XdrAnon_PathPaymentStrictSendResult_Success" -} -func (v XdrAnon_PathPaymentStrictSendResult_Success) XdrValue() interface{} { return v } -func (v *XdrAnon_PathPaymentStrictSendResult_Success) XdrMarshal(x XDR, name string) { - x.Marshal(name, v) -} -func (v *XdrAnon_PathPaymentStrictSendResult_Success) XdrRecurse(x XDR, name string) { +func (v *ClaimLiquidityAtom) XdrPointer() interface{} { return v } +func (ClaimLiquidityAtom) XdrTypeName() string { return "ClaimLiquidityAtom" } +func (v ClaimLiquidityAtom) XdrValue() interface{} { return v } +func (v *ClaimLiquidityAtom) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v *ClaimLiquidityAtom) XdrRecurse(x XDR, name string) { if name != "" { name = x.Sprintf("%s.", name) } - x.Marshal(x.Sprintf("%soffers", name), (*_XdrVec_unbounded_ClaimAtom)(&v.Offers)) - x.Marshal(x.Sprintf("%slast", name), XDR_SimplePaymentResult(&v.Last)) -} -func XDR_XdrAnon_PathPaymentStrictSendResult_Success(v *XdrAnon_PathPaymentStrictSendResult_Success) *XdrAnon_PathPaymentStrictSendResult_Success { - return v + x.Marshal(x.Sprintf("%sliquidityPoolID", name), XDR_PoolID(&v.LiquidityPoolID)) + x.Marshal(x.Sprintf("%sassetSold", name), XDR_Asset(&v.AssetSold)) + x.Marshal(x.Sprintf("%samountSold", name), XDR_Int64(&v.AmountSold)) + x.Marshal(x.Sprintf("%sassetBought", name), XDR_Asset(&v.AssetBought)) + x.Marshal(x.Sprintf("%samountBought", name), XDR_Int64(&v.AmountBought)) } +func XDR_ClaimLiquidityAtom(v *ClaimLiquidityAtom) *ClaimLiquidityAtom { return v } -var _XdrTags_PathPaymentStrictSendResult = map[int32]bool{ - XdrToI32(PATH_PAYMENT_STRICT_SEND_SUCCESS): true, - XdrToI32(PATH_PAYMENT_STRICT_SEND_MALFORMED): true, - XdrToI32(PATH_PAYMENT_STRICT_SEND_UNDERFUNDED): true, - XdrToI32(PATH_PAYMENT_STRICT_SEND_SRC_NO_TRUST): true, - XdrToI32(PATH_PAYMENT_STRICT_SEND_SRC_NOT_AUTHORIZED): true, - XdrToI32(PATH_PAYMENT_STRICT_SEND_NO_DESTINATION): true, - XdrToI32(PATH_PAYMENT_STRICT_SEND_NO_TRUST): true, - XdrToI32(PATH_PAYMENT_STRICT_SEND_NOT_AUTHORIZED): true, - XdrToI32(PATH_PAYMENT_STRICT_SEND_LINE_FULL): true, - XdrToI32(PATH_PAYMENT_STRICT_SEND_NO_ISSUER): true, - XdrToI32(PATH_PAYMENT_STRICT_SEND_TOO_FEW_OFFERS): true, - XdrToI32(PATH_PAYMENT_STRICT_SEND_OFFER_CROSS_SELF): true, - XdrToI32(PATH_PAYMENT_STRICT_SEND_UNDER_DESTMIN): true, +var _XdrTags_ClaimAtom = map[int32]bool{ + XdrToI32(CLAIM_ATOM_TYPE_V0): true, + XdrToI32(CLAIM_ATOM_TYPE_ORDER_BOOK): true, + XdrToI32(CLAIM_ATOM_TYPE_LIQUIDITY_POOL): true, } -func (_ PathPaymentStrictSendResult) XdrValidTags() map[int32]bool { - return _XdrTags_PathPaymentStrictSendResult +func (_ ClaimAtom) XdrValidTags() map[int32]bool { + return _XdrTags_ClaimAtom } -func (u *PathPaymentStrictSendResult) Success() *XdrAnon_PathPaymentStrictSendResult_Success { - switch u.Code { - case PATH_PAYMENT_STRICT_SEND_SUCCESS: - if v, ok := u._u.(*XdrAnon_PathPaymentStrictSendResult_Success); ok { +func (u *ClaimAtom) V0() *ClaimOfferAtomV0 { + switch u.Type { + case CLAIM_ATOM_TYPE_V0: + if v, ok := u._u.(*ClaimOfferAtomV0); ok { return v } else { - var zero XdrAnon_PathPaymentStrictSendResult_Success + var zero ClaimOfferAtomV0 u._u = &zero return &zero } default: - XdrPanic("PathPaymentStrictSendResult.Success accessed when Code == %v", u.Code) + XdrPanic("ClaimAtom.V0 accessed when Type == %v", u.Type) return nil } } - -// the asset that caused the error -func (u *PathPaymentStrictSendResult) NoIssuer() *Asset { - switch u.Code { - case PATH_PAYMENT_STRICT_SEND_NO_ISSUER: - if v, ok := u._u.(*Asset); ok { +func (u *ClaimAtom) OrderBook() *ClaimOfferAtom { + switch u.Type { + case CLAIM_ATOM_TYPE_ORDER_BOOK: + if v, ok := u._u.(*ClaimOfferAtom); ok { return v } else { - var zero Asset + var zero ClaimOfferAtom u._u = &zero return &zero } default: - XdrPanic("PathPaymentStrictSendResult.NoIssuer accessed when Code == %v", u.Code) + XdrPanic("ClaimAtom.OrderBook accessed when Type == %v", u.Type) return nil } } -func (u PathPaymentStrictSendResult) XdrValid() bool { - switch u.Code { - case PATH_PAYMENT_STRICT_SEND_SUCCESS, PATH_PAYMENT_STRICT_SEND_MALFORMED, PATH_PAYMENT_STRICT_SEND_UNDERFUNDED, PATH_PAYMENT_STRICT_SEND_SRC_NO_TRUST, PATH_PAYMENT_STRICT_SEND_SRC_NOT_AUTHORIZED, PATH_PAYMENT_STRICT_SEND_NO_DESTINATION, PATH_PAYMENT_STRICT_SEND_NO_TRUST, PATH_PAYMENT_STRICT_SEND_NOT_AUTHORIZED, PATH_PAYMENT_STRICT_SEND_LINE_FULL, PATH_PAYMENT_STRICT_SEND_NO_ISSUER, PATH_PAYMENT_STRICT_SEND_TOO_FEW_OFFERS, PATH_PAYMENT_STRICT_SEND_OFFER_CROSS_SELF, PATH_PAYMENT_STRICT_SEND_UNDER_DESTMIN: +func (u *ClaimAtom) LiquidityPool() *ClaimLiquidityAtom { + switch u.Type { + case CLAIM_ATOM_TYPE_LIQUIDITY_POOL: + if v, ok := u._u.(*ClaimLiquidityAtom); ok { + return v + } else { + var zero ClaimLiquidityAtom + u._u = &zero + return &zero + } + default: + XdrPanic("ClaimAtom.LiquidityPool accessed when Type == %v", u.Type) + return nil + } +} +func (u ClaimAtom) XdrValid() bool { + switch u.Type { + case CLAIM_ATOM_TYPE_V0, CLAIM_ATOM_TYPE_ORDER_BOOK, CLAIM_ATOM_TYPE_LIQUIDITY_POOL: return true } return false } -func (u *PathPaymentStrictSendResult) XdrUnionTag() XdrNum32 { - return XDR_PathPaymentStrictSendResultCode(&u.Code) +func (u *ClaimAtom) XdrUnionTag() XdrNum32 { + return XDR_ClaimAtomType(&u.Type) } -func (u *PathPaymentStrictSendResult) XdrUnionTagName() string { - return "Code" +func (u *ClaimAtom) XdrUnionTagName() string { + return "Type" } -func (u *PathPaymentStrictSendResult) XdrUnionBody() XdrType { - switch u.Code { - case PATH_PAYMENT_STRICT_SEND_SUCCESS: - return XDR_XdrAnon_PathPaymentStrictSendResult_Success(u.Success()) - case PATH_PAYMENT_STRICT_SEND_MALFORMED, PATH_PAYMENT_STRICT_SEND_UNDERFUNDED, PATH_PAYMENT_STRICT_SEND_SRC_NO_TRUST, PATH_PAYMENT_STRICT_SEND_SRC_NOT_AUTHORIZED, PATH_PAYMENT_STRICT_SEND_NO_DESTINATION, PATH_PAYMENT_STRICT_SEND_NO_TRUST, PATH_PAYMENT_STRICT_SEND_NOT_AUTHORIZED, PATH_PAYMENT_STRICT_SEND_LINE_FULL: - return nil - case PATH_PAYMENT_STRICT_SEND_NO_ISSUER: - return XDR_Asset(u.NoIssuer()) - case PATH_PAYMENT_STRICT_SEND_TOO_FEW_OFFERS, PATH_PAYMENT_STRICT_SEND_OFFER_CROSS_SELF, PATH_PAYMENT_STRICT_SEND_UNDER_DESTMIN: - return nil +func (u *ClaimAtom) XdrUnionBody() XdrType { + switch u.Type { + case CLAIM_ATOM_TYPE_V0: + return XDR_ClaimOfferAtomV0(u.V0()) + case CLAIM_ATOM_TYPE_ORDER_BOOK: + return XDR_ClaimOfferAtom(u.OrderBook()) + case CLAIM_ATOM_TYPE_LIQUIDITY_POOL: + return XDR_ClaimLiquidityAtom(u.LiquidityPool()) } return nil } -func (u *PathPaymentStrictSendResult) XdrUnionBodyName() string { - switch u.Code { - case PATH_PAYMENT_STRICT_SEND_SUCCESS: - return "Success" - case PATH_PAYMENT_STRICT_SEND_MALFORMED, PATH_PAYMENT_STRICT_SEND_UNDERFUNDED, PATH_PAYMENT_STRICT_SEND_SRC_NO_TRUST, PATH_PAYMENT_STRICT_SEND_SRC_NOT_AUTHORIZED, PATH_PAYMENT_STRICT_SEND_NO_DESTINATION, PATH_PAYMENT_STRICT_SEND_NO_TRUST, PATH_PAYMENT_STRICT_SEND_NOT_AUTHORIZED, PATH_PAYMENT_STRICT_SEND_LINE_FULL: - return "" - case PATH_PAYMENT_STRICT_SEND_NO_ISSUER: - return "NoIssuer" - case PATH_PAYMENT_STRICT_SEND_TOO_FEW_OFFERS, PATH_PAYMENT_STRICT_SEND_OFFER_CROSS_SELF, PATH_PAYMENT_STRICT_SEND_UNDER_DESTMIN: - return "" +func (u *ClaimAtom) XdrUnionBodyName() string { + switch u.Type { + case CLAIM_ATOM_TYPE_V0: + return "V0" + case CLAIM_ATOM_TYPE_ORDER_BOOK: + return "OrderBook" + case CLAIM_ATOM_TYPE_LIQUIDITY_POOL: + return "LiquidityPool" } return "" } -type XdrType_PathPaymentStrictSendResult = *PathPaymentStrictSendResult +type XdrType_ClaimAtom = *ClaimAtom -func (v *PathPaymentStrictSendResult) XdrPointer() interface{} { return v } -func (PathPaymentStrictSendResult) XdrTypeName() string { return "PathPaymentStrictSendResult" } -func (v PathPaymentStrictSendResult) XdrValue() interface{} { return v } -func (v *PathPaymentStrictSendResult) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -func (u *PathPaymentStrictSendResult) XdrRecurse(x XDR, name string) { +func (v *ClaimAtom) XdrPointer() interface{} { return v } +func (ClaimAtom) XdrTypeName() string { return "ClaimAtom" } +func (v ClaimAtom) XdrValue() interface{} { return v } +func (v *ClaimAtom) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (u *ClaimAtom) XdrRecurse(x XDR, name string) { if name != "" { name = x.Sprintf("%s.", name) } - XDR_PathPaymentStrictSendResultCode(&u.Code).XdrMarshal(x, x.Sprintf("%scode", name)) - switch u.Code { - case PATH_PAYMENT_STRICT_SEND_SUCCESS: - x.Marshal(x.Sprintf("%ssuccess", name), XDR_XdrAnon_PathPaymentStrictSendResult_Success(u.Success())) - return - case PATH_PAYMENT_STRICT_SEND_MALFORMED, PATH_PAYMENT_STRICT_SEND_UNDERFUNDED, PATH_PAYMENT_STRICT_SEND_SRC_NO_TRUST, PATH_PAYMENT_STRICT_SEND_SRC_NOT_AUTHORIZED, PATH_PAYMENT_STRICT_SEND_NO_DESTINATION, PATH_PAYMENT_STRICT_SEND_NO_TRUST, PATH_PAYMENT_STRICT_SEND_NOT_AUTHORIZED, PATH_PAYMENT_STRICT_SEND_LINE_FULL: + XDR_ClaimAtomType(&u.Type).XdrMarshal(x, x.Sprintf("%stype", name)) + switch u.Type { + case CLAIM_ATOM_TYPE_V0: + x.Marshal(x.Sprintf("%sv0", name), XDR_ClaimOfferAtomV0(u.V0())) return - case PATH_PAYMENT_STRICT_SEND_NO_ISSUER: - x.Marshal(x.Sprintf("%snoIssuer", name), XDR_Asset(u.NoIssuer())) + case CLAIM_ATOM_TYPE_ORDER_BOOK: + x.Marshal(x.Sprintf("%sorderBook", name), XDR_ClaimOfferAtom(u.OrderBook())) return - case PATH_PAYMENT_STRICT_SEND_TOO_FEW_OFFERS, PATH_PAYMENT_STRICT_SEND_OFFER_CROSS_SELF, PATH_PAYMENT_STRICT_SEND_UNDER_DESTMIN: + case CLAIM_ATOM_TYPE_LIQUIDITY_POOL: + x.Marshal(x.Sprintf("%sliquidityPool", name), XDR_ClaimLiquidityAtom(u.LiquidityPool())) return } - XdrPanic("invalid Code (%v) in PathPaymentStrictSendResult", u.Code) -} -func XDR_PathPaymentStrictSendResult(v *PathPaymentStrictSendResult) *PathPaymentStrictSendResult { - return v + XdrPanic("invalid Type (%v) in ClaimAtom", u.Type) } +func XDR_ClaimAtom(v *ClaimAtom) *ClaimAtom { return v } -var _XdrNames_ManageSellOfferResultCode = map[int32]string{ - int32(MANAGE_SELL_OFFER_SUCCESS): "MANAGE_SELL_OFFER_SUCCESS", - int32(MANAGE_SELL_OFFER_MALFORMED): "MANAGE_SELL_OFFER_MALFORMED", - int32(MANAGE_SELL_OFFER_SELL_NO_TRUST): "MANAGE_SELL_OFFER_SELL_NO_TRUST", - int32(MANAGE_SELL_OFFER_BUY_NO_TRUST): "MANAGE_SELL_OFFER_BUY_NO_TRUST", - int32(MANAGE_SELL_OFFER_SELL_NOT_AUTHORIZED): "MANAGE_SELL_OFFER_SELL_NOT_AUTHORIZED", - int32(MANAGE_SELL_OFFER_BUY_NOT_AUTHORIZED): "MANAGE_SELL_OFFER_BUY_NOT_AUTHORIZED", - int32(MANAGE_SELL_OFFER_LINE_FULL): "MANAGE_SELL_OFFER_LINE_FULL", - int32(MANAGE_SELL_OFFER_UNDERFUNDED): "MANAGE_SELL_OFFER_UNDERFUNDED", - int32(MANAGE_SELL_OFFER_CROSS_SELF): "MANAGE_SELL_OFFER_CROSS_SELF", - int32(MANAGE_SELL_OFFER_SELL_NO_ISSUER): "MANAGE_SELL_OFFER_SELL_NO_ISSUER", - int32(MANAGE_SELL_OFFER_BUY_NO_ISSUER): "MANAGE_SELL_OFFER_BUY_NO_ISSUER", - int32(MANAGE_SELL_OFFER_NOT_FOUND): "MANAGE_SELL_OFFER_NOT_FOUND", - int32(MANAGE_SELL_OFFER_LOW_RESERVE): "MANAGE_SELL_OFFER_LOW_RESERVE", +var _XdrNames_CreateAccountResultCode = map[int32]string{ + int32(CREATE_ACCOUNT_SUCCESS): "CREATE_ACCOUNT_SUCCESS", + int32(CREATE_ACCOUNT_MALFORMED): "CREATE_ACCOUNT_MALFORMED", + int32(CREATE_ACCOUNT_UNDERFUNDED): "CREATE_ACCOUNT_UNDERFUNDED", + int32(CREATE_ACCOUNT_LOW_RESERVE): "CREATE_ACCOUNT_LOW_RESERVE", + int32(CREATE_ACCOUNT_ALREADY_EXIST): "CREATE_ACCOUNT_ALREADY_EXIST", } -var _XdrValues_ManageSellOfferResultCode = map[string]int32{ - "MANAGE_SELL_OFFER_SUCCESS": int32(MANAGE_SELL_OFFER_SUCCESS), - "MANAGE_SELL_OFFER_MALFORMED": int32(MANAGE_SELL_OFFER_MALFORMED), - "MANAGE_SELL_OFFER_SELL_NO_TRUST": int32(MANAGE_SELL_OFFER_SELL_NO_TRUST), - "MANAGE_SELL_OFFER_BUY_NO_TRUST": int32(MANAGE_SELL_OFFER_BUY_NO_TRUST), - "MANAGE_SELL_OFFER_SELL_NOT_AUTHORIZED": int32(MANAGE_SELL_OFFER_SELL_NOT_AUTHORIZED), - "MANAGE_SELL_OFFER_BUY_NOT_AUTHORIZED": int32(MANAGE_SELL_OFFER_BUY_NOT_AUTHORIZED), - "MANAGE_SELL_OFFER_LINE_FULL": int32(MANAGE_SELL_OFFER_LINE_FULL), - "MANAGE_SELL_OFFER_UNDERFUNDED": int32(MANAGE_SELL_OFFER_UNDERFUNDED), - "MANAGE_SELL_OFFER_CROSS_SELF": int32(MANAGE_SELL_OFFER_CROSS_SELF), - "MANAGE_SELL_OFFER_SELL_NO_ISSUER": int32(MANAGE_SELL_OFFER_SELL_NO_ISSUER), - "MANAGE_SELL_OFFER_BUY_NO_ISSUER": int32(MANAGE_SELL_OFFER_BUY_NO_ISSUER), - "MANAGE_SELL_OFFER_NOT_FOUND": int32(MANAGE_SELL_OFFER_NOT_FOUND), - "MANAGE_SELL_OFFER_LOW_RESERVE": int32(MANAGE_SELL_OFFER_LOW_RESERVE), +var _XdrValues_CreateAccountResultCode = map[string]int32{ + "CREATE_ACCOUNT_SUCCESS": int32(CREATE_ACCOUNT_SUCCESS), + "CREATE_ACCOUNT_MALFORMED": int32(CREATE_ACCOUNT_MALFORMED), + "CREATE_ACCOUNT_UNDERFUNDED": int32(CREATE_ACCOUNT_UNDERFUNDED), + "CREATE_ACCOUNT_LOW_RESERVE": int32(CREATE_ACCOUNT_LOW_RESERVE), + "CREATE_ACCOUNT_ALREADY_EXIST": int32(CREATE_ACCOUNT_ALREADY_EXIST), } -func (ManageSellOfferResultCode) XdrEnumNames() map[int32]string { - return _XdrNames_ManageSellOfferResultCode +func (CreateAccountResultCode) XdrEnumNames() map[int32]string { + return _XdrNames_CreateAccountResultCode } -func (v ManageSellOfferResultCode) String() string { - if s, ok := _XdrNames_ManageSellOfferResultCode[int32(v)]; ok { +func (v CreateAccountResultCode) String() string { + if s, ok := _XdrNames_CreateAccountResultCode[int32(v)]; ok { return s } - return fmt.Sprintf("ManageSellOfferResultCode#%d", v) + return fmt.Sprintf("CreateAccountResultCode#%d", v) } -func (v *ManageSellOfferResultCode) Scan(ss fmt.ScanState, _ rune) error { +func (v *CreateAccountResultCode) Scan(ss fmt.ScanState, _ rune) error { if tok, err := ss.Token(true, XdrSymChar); err != nil { return err } else { stok := string(tok) - if val, ok := _XdrValues_ManageSellOfferResultCode[stok]; ok { - *v = ManageSellOfferResultCode(val) + if val, ok := _XdrValues_CreateAccountResultCode[stok]; ok { + *v = CreateAccountResultCode(val) return nil - } else if stok == "ManageSellOfferResultCode" { + } else if stok == "CreateAccountResultCode" { if n, err := fmt.Fscanf(ss, "#%d", (*int32)(v)); n == 1 && err == nil { return nil } } - return XdrError(fmt.Sprintf("%s is not a valid ManageSellOfferResultCode.", stok)) + return XdrError(fmt.Sprintf("%s is not a valid CreateAccountResultCode.", stok)) } } -func (v ManageSellOfferResultCode) GetU32() uint32 { return uint32(v) } -func (v *ManageSellOfferResultCode) SetU32(n uint32) { *v = ManageSellOfferResultCode(n) } -func (v *ManageSellOfferResultCode) XdrPointer() interface{} { return v } -func (ManageSellOfferResultCode) XdrTypeName() string { return "ManageSellOfferResultCode" } -func (v ManageSellOfferResultCode) XdrValue() interface{} { return v } -func (v *ManageSellOfferResultCode) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v CreateAccountResultCode) GetU32() uint32 { return uint32(v) } +func (v *CreateAccountResultCode) SetU32(n uint32) { *v = CreateAccountResultCode(n) } +func (v *CreateAccountResultCode) XdrPointer() interface{} { return v } +func (CreateAccountResultCode) XdrTypeName() string { return "CreateAccountResultCode" } +func (v CreateAccountResultCode) XdrValue() interface{} { return v } +func (v *CreateAccountResultCode) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -type XdrType_ManageSellOfferResultCode = *ManageSellOfferResultCode +type XdrType_CreateAccountResultCode = *CreateAccountResultCode -func XDR_ManageSellOfferResultCode(v *ManageSellOfferResultCode) *ManageSellOfferResultCode { return v } +func XDR_CreateAccountResultCode(v *CreateAccountResultCode) *CreateAccountResultCode { return v } -var _XdrComments_ManageSellOfferResultCode = map[int32]string{ - int32(MANAGE_SELL_OFFER_SUCCESS): "codes considered as \"success\" for the operation", - int32(MANAGE_SELL_OFFER_MALFORMED): "generated offer would be invalid", - int32(MANAGE_SELL_OFFER_SELL_NO_TRUST): "no trust line for what we're selling", - int32(MANAGE_SELL_OFFER_BUY_NO_TRUST): "no trust line for what we're buying", - int32(MANAGE_SELL_OFFER_SELL_NOT_AUTHORIZED): "not authorized to sell", - int32(MANAGE_SELL_OFFER_BUY_NOT_AUTHORIZED): "not authorized to buy", - int32(MANAGE_SELL_OFFER_LINE_FULL): "can't receive more of what it's buying", - int32(MANAGE_SELL_OFFER_UNDERFUNDED): "doesn't hold what it's trying to sell", - int32(MANAGE_SELL_OFFER_CROSS_SELF): "would cross an offer from the same user", - int32(MANAGE_SELL_OFFER_SELL_NO_ISSUER): "no issuer for what we're selling", - int32(MANAGE_SELL_OFFER_BUY_NO_ISSUER): "no issuer for what we're buying", - int32(MANAGE_SELL_OFFER_NOT_FOUND): "offerID does not match an existing offer", - int32(MANAGE_SELL_OFFER_LOW_RESERVE): "not enough funds to create a new Offer", +var _XdrComments_CreateAccountResultCode = map[int32]string{ + int32(CREATE_ACCOUNT_SUCCESS): "account was created", + int32(CREATE_ACCOUNT_MALFORMED): "invalid destination", + int32(CREATE_ACCOUNT_UNDERFUNDED): "not enough funds in source account", + int32(CREATE_ACCOUNT_LOW_RESERVE): "would create an account below the min reserve", + int32(CREATE_ACCOUNT_ALREADY_EXIST): "account already exists", } -func (e ManageSellOfferResultCode) XdrEnumComments() map[int32]string { - return _XdrComments_ManageSellOfferResultCode +func (e CreateAccountResultCode) XdrEnumComments() map[int32]string { + return _XdrComments_CreateAccountResultCode } -var _XdrNames_ManageOfferEffect = map[int32]string{ - int32(MANAGE_OFFER_CREATED): "MANAGE_OFFER_CREATED", - int32(MANAGE_OFFER_UPDATED): "MANAGE_OFFER_UPDATED", - int32(MANAGE_OFFER_DELETED): "MANAGE_OFFER_DELETED", -} -var _XdrValues_ManageOfferEffect = map[string]int32{ - "MANAGE_OFFER_CREATED": int32(MANAGE_OFFER_CREATED), - "MANAGE_OFFER_UPDATED": int32(MANAGE_OFFER_UPDATED), - "MANAGE_OFFER_DELETED": int32(MANAGE_OFFER_DELETED), +var _XdrTags_CreateAccountResult = map[int32]bool{ + XdrToI32(CREATE_ACCOUNT_SUCCESS): true, + XdrToI32(CREATE_ACCOUNT_MALFORMED): true, + XdrToI32(CREATE_ACCOUNT_UNDERFUNDED): true, + XdrToI32(CREATE_ACCOUNT_LOW_RESERVE): true, + XdrToI32(CREATE_ACCOUNT_ALREADY_EXIST): true, } -func (ManageOfferEffect) XdrEnumNames() map[int32]string { - return _XdrNames_ManageOfferEffect +func (_ CreateAccountResult) XdrValidTags() map[int32]bool { + return _XdrTags_CreateAccountResult } -func (v ManageOfferEffect) String() string { - if s, ok := _XdrNames_ManageOfferEffect[int32(v)]; ok { - return s +func (u CreateAccountResult) XdrValid() bool { + switch u.Code { + case CREATE_ACCOUNT_SUCCESS, CREATE_ACCOUNT_MALFORMED, CREATE_ACCOUNT_UNDERFUNDED, CREATE_ACCOUNT_LOW_RESERVE, CREATE_ACCOUNT_ALREADY_EXIST: + return true } - return fmt.Sprintf("ManageOfferEffect#%d", v) + return false } -func (v *ManageOfferEffect) Scan(ss fmt.ScanState, _ rune) error { - if tok, err := ss.Token(true, XdrSymChar); err != nil { - return err - } else { - stok := string(tok) - if val, ok := _XdrValues_ManageOfferEffect[stok]; ok { - *v = ManageOfferEffect(val) - return nil - } else if stok == "ManageOfferEffect" { - if n, err := fmt.Fscanf(ss, "#%d", (*int32)(v)); n == 1 && err == nil { - return nil - } - } - return XdrError(fmt.Sprintf("%s is not a valid ManageOfferEffect.", stok)) +func (u *CreateAccountResult) XdrUnionTag() XdrNum32 { + return XDR_CreateAccountResultCode(&u.Code) +} +func (u *CreateAccountResult) XdrUnionTagName() string { + return "Code" +} +func (u *CreateAccountResult) XdrUnionBody() XdrType { + switch u.Code { + case CREATE_ACCOUNT_SUCCESS: + return nil + case CREATE_ACCOUNT_MALFORMED, CREATE_ACCOUNT_UNDERFUNDED, CREATE_ACCOUNT_LOW_RESERVE, CREATE_ACCOUNT_ALREADY_EXIST: + return nil } + return nil } -func (v ManageOfferEffect) GetU32() uint32 { return uint32(v) } -func (v *ManageOfferEffect) SetU32(n uint32) { *v = ManageOfferEffect(n) } -func (v *ManageOfferEffect) XdrPointer() interface{} { return v } -func (ManageOfferEffect) XdrTypeName() string { return "ManageOfferEffect" } -func (v ManageOfferEffect) XdrValue() interface{} { return v } -func (v *ManageOfferEffect) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } - -type XdrType_ManageOfferEffect = *ManageOfferEffect - -func XDR_ManageOfferEffect(v *ManageOfferEffect) *ManageOfferEffect { return v } - -var _XdrTags_XdrAnon_ManageOfferSuccessResult_Offer = map[int32]bool{ - XdrToI32(MANAGE_OFFER_CREATED): true, - XdrToI32(MANAGE_OFFER_UPDATED): true, - XdrToI32(MANAGE_OFFER_DELETED): true, -} - -func (_ XdrAnon_ManageOfferSuccessResult_Offer) XdrValidTags() map[int32]bool { - return _XdrTags_XdrAnon_ManageOfferSuccessResult_Offer -} -func (u *XdrAnon_ManageOfferSuccessResult_Offer) Offer() *OfferEntry { - switch u.Effect { - case MANAGE_OFFER_CREATED, MANAGE_OFFER_UPDATED: - if v, ok := u._u.(*OfferEntry); ok { - return v - } else { - var zero OfferEntry - u._u = &zero - return &zero - } - default: - XdrPanic("XdrAnon_ManageOfferSuccessResult_Offer.Offer accessed when Effect == %v", u.Effect) - return nil - } -} -func (u XdrAnon_ManageOfferSuccessResult_Offer) XdrValid() bool { - switch u.Effect { - case MANAGE_OFFER_CREATED, MANAGE_OFFER_UPDATED, MANAGE_OFFER_DELETED: - return true - } - return false -} -func (u *XdrAnon_ManageOfferSuccessResult_Offer) XdrUnionTag() XdrNum32 { - return XDR_ManageOfferEffect(&u.Effect) -} -func (u *XdrAnon_ManageOfferSuccessResult_Offer) XdrUnionTagName() string { - return "Effect" -} -func (u *XdrAnon_ManageOfferSuccessResult_Offer) XdrUnionBody() XdrType { - switch u.Effect { - case MANAGE_OFFER_CREATED, MANAGE_OFFER_UPDATED: - return XDR_OfferEntry(u.Offer()) - case MANAGE_OFFER_DELETED: - return nil - } - return nil -} -func (u *XdrAnon_ManageOfferSuccessResult_Offer) XdrUnionBodyName() string { - switch u.Effect { - case MANAGE_OFFER_CREATED, MANAGE_OFFER_UPDATED: - return "Offer" - case MANAGE_OFFER_DELETED: +func (u *CreateAccountResult) XdrUnionBodyName() string { + switch u.Code { + case CREATE_ACCOUNT_SUCCESS: + return "" + case CREATE_ACCOUNT_MALFORMED, CREATE_ACCOUNT_UNDERFUNDED, CREATE_ACCOUNT_LOW_RESERVE, CREATE_ACCOUNT_ALREADY_EXIST: return "" } return "" } -type XdrType_XdrAnon_ManageOfferSuccessResult_Offer = *XdrAnon_ManageOfferSuccessResult_Offer +type XdrType_CreateAccountResult = *CreateAccountResult -func (v *XdrAnon_ManageOfferSuccessResult_Offer) XdrPointer() interface{} { return v } -func (XdrAnon_ManageOfferSuccessResult_Offer) XdrTypeName() string { - return "XdrAnon_ManageOfferSuccessResult_Offer" -} -func (v XdrAnon_ManageOfferSuccessResult_Offer) XdrValue() interface{} { return v } -func (v *XdrAnon_ManageOfferSuccessResult_Offer) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -func (u *XdrAnon_ManageOfferSuccessResult_Offer) XdrRecurse(x XDR, name string) { +func (v *CreateAccountResult) XdrPointer() interface{} { return v } +func (CreateAccountResult) XdrTypeName() string { return "CreateAccountResult" } +func (v CreateAccountResult) XdrValue() interface{} { return v } +func (v *CreateAccountResult) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (u *CreateAccountResult) XdrRecurse(x XDR, name string) { if name != "" { name = x.Sprintf("%s.", name) } - XDR_ManageOfferEffect(&u.Effect).XdrMarshal(x, x.Sprintf("%seffect", name)) - switch u.Effect { - case MANAGE_OFFER_CREATED, MANAGE_OFFER_UPDATED: - x.Marshal(x.Sprintf("%soffer", name), XDR_OfferEntry(u.Offer())) + XDR_CreateAccountResultCode(&u.Code).XdrMarshal(x, x.Sprintf("%scode", name)) + switch u.Code { + case CREATE_ACCOUNT_SUCCESS: return - case MANAGE_OFFER_DELETED: + case CREATE_ACCOUNT_MALFORMED, CREATE_ACCOUNT_UNDERFUNDED, CREATE_ACCOUNT_LOW_RESERVE, CREATE_ACCOUNT_ALREADY_EXIST: return } - XdrPanic("invalid Effect (%v) in XdrAnon_ManageOfferSuccessResult_Offer", u.Effect) -} -func XDR_XdrAnon_ManageOfferSuccessResult_Offer(v *XdrAnon_ManageOfferSuccessResult_Offer) *XdrAnon_ManageOfferSuccessResult_Offer { - return v + XdrPanic("invalid Code (%v) in CreateAccountResult", u.Code) } +func XDR_CreateAccountResult(v *CreateAccountResult) *CreateAccountResult { return v } -type XdrType_ManageOfferSuccessResult = *ManageOfferSuccessResult +var _XdrNames_PaymentResultCode = map[int32]string{ + int32(PAYMENT_SUCCESS): "PAYMENT_SUCCESS", + int32(PAYMENT_MALFORMED): "PAYMENT_MALFORMED", + int32(PAYMENT_UNDERFUNDED): "PAYMENT_UNDERFUNDED", + int32(PAYMENT_SRC_NO_TRUST): "PAYMENT_SRC_NO_TRUST", + int32(PAYMENT_SRC_NOT_AUTHORIZED): "PAYMENT_SRC_NOT_AUTHORIZED", + int32(PAYMENT_NO_DESTINATION): "PAYMENT_NO_DESTINATION", + int32(PAYMENT_NO_TRUST): "PAYMENT_NO_TRUST", + int32(PAYMENT_NOT_AUTHORIZED): "PAYMENT_NOT_AUTHORIZED", + int32(PAYMENT_LINE_FULL): "PAYMENT_LINE_FULL", + int32(PAYMENT_NO_ISSUER): "PAYMENT_NO_ISSUER", +} +var _XdrValues_PaymentResultCode = map[string]int32{ + "PAYMENT_SUCCESS": int32(PAYMENT_SUCCESS), + "PAYMENT_MALFORMED": int32(PAYMENT_MALFORMED), + "PAYMENT_UNDERFUNDED": int32(PAYMENT_UNDERFUNDED), + "PAYMENT_SRC_NO_TRUST": int32(PAYMENT_SRC_NO_TRUST), + "PAYMENT_SRC_NOT_AUTHORIZED": int32(PAYMENT_SRC_NOT_AUTHORIZED), + "PAYMENT_NO_DESTINATION": int32(PAYMENT_NO_DESTINATION), + "PAYMENT_NO_TRUST": int32(PAYMENT_NO_TRUST), + "PAYMENT_NOT_AUTHORIZED": int32(PAYMENT_NOT_AUTHORIZED), + "PAYMENT_LINE_FULL": int32(PAYMENT_LINE_FULL), + "PAYMENT_NO_ISSUER": int32(PAYMENT_NO_ISSUER), +} -func (v *ManageOfferSuccessResult) XdrPointer() interface{} { return v } -func (ManageOfferSuccessResult) XdrTypeName() string { return "ManageOfferSuccessResult" } -func (v ManageOfferSuccessResult) XdrValue() interface{} { return v } -func (v *ManageOfferSuccessResult) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -func (v *ManageOfferSuccessResult) XdrRecurse(x XDR, name string) { - if name != "" { - name = x.Sprintf("%s.", name) +func (PaymentResultCode) XdrEnumNames() map[int32]string { + return _XdrNames_PaymentResultCode +} +func (v PaymentResultCode) String() string { + if s, ok := _XdrNames_PaymentResultCode[int32(v)]; ok { + return s } - x.Marshal(x.Sprintf("%soffersClaimed", name), (*_XdrVec_unbounded_ClaimAtom)(&v.OffersClaimed)) - x.Marshal(x.Sprintf("%soffer", name), XDR_XdrAnon_ManageOfferSuccessResult_Offer(&v.Offer)) + return fmt.Sprintf("PaymentResultCode#%d", v) } -func XDR_ManageOfferSuccessResult(v *ManageOfferSuccessResult) *ManageOfferSuccessResult { return v } +func (v *PaymentResultCode) Scan(ss fmt.ScanState, _ rune) error { + if tok, err := ss.Token(true, XdrSymChar); err != nil { + return err + } else { + stok := string(tok) + if val, ok := _XdrValues_PaymentResultCode[stok]; ok { + *v = PaymentResultCode(val) + return nil + } else if stok == "PaymentResultCode" { + if n, err := fmt.Fscanf(ss, "#%d", (*int32)(v)); n == 1 && err == nil { + return nil + } + } + return XdrError(fmt.Sprintf("%s is not a valid PaymentResultCode.", stok)) + } +} +func (v PaymentResultCode) GetU32() uint32 { return uint32(v) } +func (v *PaymentResultCode) SetU32(n uint32) { *v = PaymentResultCode(n) } +func (v *PaymentResultCode) XdrPointer() interface{} { return v } +func (PaymentResultCode) XdrTypeName() string { return "PaymentResultCode" } +func (v PaymentResultCode) XdrValue() interface{} { return v } +func (v *PaymentResultCode) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -var _XdrTags_ManageSellOfferResult = map[int32]bool{ - XdrToI32(MANAGE_SELL_OFFER_SUCCESS): true, - XdrToI32(MANAGE_SELL_OFFER_MALFORMED): true, - XdrToI32(MANAGE_SELL_OFFER_SELL_NO_TRUST): true, - XdrToI32(MANAGE_SELL_OFFER_BUY_NO_TRUST): true, - XdrToI32(MANAGE_SELL_OFFER_SELL_NOT_AUTHORIZED): true, - XdrToI32(MANAGE_SELL_OFFER_BUY_NOT_AUTHORIZED): true, - XdrToI32(MANAGE_SELL_OFFER_LINE_FULL): true, - XdrToI32(MANAGE_SELL_OFFER_UNDERFUNDED): true, - XdrToI32(MANAGE_SELL_OFFER_CROSS_SELF): true, - XdrToI32(MANAGE_SELL_OFFER_SELL_NO_ISSUER): true, - XdrToI32(MANAGE_SELL_OFFER_BUY_NO_ISSUER): true, - XdrToI32(MANAGE_SELL_OFFER_NOT_FOUND): true, - XdrToI32(MANAGE_SELL_OFFER_LOW_RESERVE): true, +type XdrType_PaymentResultCode = *PaymentResultCode + +func XDR_PaymentResultCode(v *PaymentResultCode) *PaymentResultCode { return v } + +var _XdrComments_PaymentResultCode = map[int32]string{ + int32(PAYMENT_SUCCESS): "payment successfully completed", + int32(PAYMENT_MALFORMED): "bad input", + int32(PAYMENT_UNDERFUNDED): "not enough funds in source account", + int32(PAYMENT_SRC_NO_TRUST): "no trust line on source account", + int32(PAYMENT_SRC_NOT_AUTHORIZED): "source not authorized to transfer", + int32(PAYMENT_NO_DESTINATION): "destination account does not exist", + int32(PAYMENT_NO_TRUST): "destination missing a trust line for asset", + int32(PAYMENT_NOT_AUTHORIZED): "destination not authorized to hold asset", + int32(PAYMENT_LINE_FULL): "destination would go above their limit", + int32(PAYMENT_NO_ISSUER): "missing issuer on asset", } -func (_ ManageSellOfferResult) XdrValidTags() map[int32]bool { - return _XdrTags_ManageSellOfferResult +func (e PaymentResultCode) XdrEnumComments() map[int32]string { + return _XdrComments_PaymentResultCode } -func (u *ManageSellOfferResult) Success() *ManageOfferSuccessResult { - switch u.Code { - case MANAGE_SELL_OFFER_SUCCESS: - if v, ok := u._u.(*ManageOfferSuccessResult); ok { - return v - } else { - var zero ManageOfferSuccessResult - u._u = &zero - return &zero - } - default: - XdrPanic("ManageSellOfferResult.Success accessed when Code == %v", u.Code) - return nil - } + +var _XdrTags_PaymentResult = map[int32]bool{ + XdrToI32(PAYMENT_SUCCESS): true, + XdrToI32(PAYMENT_MALFORMED): true, + XdrToI32(PAYMENT_UNDERFUNDED): true, + XdrToI32(PAYMENT_SRC_NO_TRUST): true, + XdrToI32(PAYMENT_SRC_NOT_AUTHORIZED): true, + XdrToI32(PAYMENT_NO_DESTINATION): true, + XdrToI32(PAYMENT_NO_TRUST): true, + XdrToI32(PAYMENT_NOT_AUTHORIZED): true, + XdrToI32(PAYMENT_LINE_FULL): true, + XdrToI32(PAYMENT_NO_ISSUER): true, } -func (u ManageSellOfferResult) XdrValid() bool { + +func (_ PaymentResult) XdrValidTags() map[int32]bool { + return _XdrTags_PaymentResult +} +func (u PaymentResult) XdrValid() bool { switch u.Code { - case MANAGE_SELL_OFFER_SUCCESS, MANAGE_SELL_OFFER_MALFORMED, MANAGE_SELL_OFFER_SELL_NO_TRUST, MANAGE_SELL_OFFER_BUY_NO_TRUST, MANAGE_SELL_OFFER_SELL_NOT_AUTHORIZED, MANAGE_SELL_OFFER_BUY_NOT_AUTHORIZED, MANAGE_SELL_OFFER_LINE_FULL, MANAGE_SELL_OFFER_UNDERFUNDED, MANAGE_SELL_OFFER_CROSS_SELF, MANAGE_SELL_OFFER_SELL_NO_ISSUER, MANAGE_SELL_OFFER_BUY_NO_ISSUER, MANAGE_SELL_OFFER_NOT_FOUND, MANAGE_SELL_OFFER_LOW_RESERVE: + case PAYMENT_SUCCESS, PAYMENT_MALFORMED, PAYMENT_UNDERFUNDED, PAYMENT_SRC_NO_TRUST, PAYMENT_SRC_NOT_AUTHORIZED, PAYMENT_NO_DESTINATION, PAYMENT_NO_TRUST, PAYMENT_NOT_AUTHORIZED, PAYMENT_LINE_FULL, PAYMENT_NO_ISSUER: return true } return false } -func (u *ManageSellOfferResult) XdrUnionTag() XdrNum32 { - return XDR_ManageSellOfferResultCode(&u.Code) +func (u *PaymentResult) XdrUnionTag() XdrNum32 { + return XDR_PaymentResultCode(&u.Code) } -func (u *ManageSellOfferResult) XdrUnionTagName() string { +func (u *PaymentResult) XdrUnionTagName() string { return "Code" } -func (u *ManageSellOfferResult) XdrUnionBody() XdrType { +func (u *PaymentResult) XdrUnionBody() XdrType { switch u.Code { - case MANAGE_SELL_OFFER_SUCCESS: - return XDR_ManageOfferSuccessResult(u.Success()) - case MANAGE_SELL_OFFER_MALFORMED, MANAGE_SELL_OFFER_SELL_NO_TRUST, MANAGE_SELL_OFFER_BUY_NO_TRUST, MANAGE_SELL_OFFER_SELL_NOT_AUTHORIZED, MANAGE_SELL_OFFER_BUY_NOT_AUTHORIZED, MANAGE_SELL_OFFER_LINE_FULL, MANAGE_SELL_OFFER_UNDERFUNDED, MANAGE_SELL_OFFER_CROSS_SELF, MANAGE_SELL_OFFER_SELL_NO_ISSUER, MANAGE_SELL_OFFER_BUY_NO_ISSUER, MANAGE_SELL_OFFER_NOT_FOUND, MANAGE_SELL_OFFER_LOW_RESERVE: + case PAYMENT_SUCCESS: + return nil + case PAYMENT_MALFORMED, PAYMENT_UNDERFUNDED, PAYMENT_SRC_NO_TRUST, PAYMENT_SRC_NOT_AUTHORIZED, PAYMENT_NO_DESTINATION, PAYMENT_NO_TRUST, PAYMENT_NOT_AUTHORIZED, PAYMENT_LINE_FULL, PAYMENT_NO_ISSUER: return nil } return nil } -func (u *ManageSellOfferResult) XdrUnionBodyName() string { +func (u *PaymentResult) XdrUnionBodyName() string { switch u.Code { - case MANAGE_SELL_OFFER_SUCCESS: - return "Success" - case MANAGE_SELL_OFFER_MALFORMED, MANAGE_SELL_OFFER_SELL_NO_TRUST, MANAGE_SELL_OFFER_BUY_NO_TRUST, MANAGE_SELL_OFFER_SELL_NOT_AUTHORIZED, MANAGE_SELL_OFFER_BUY_NOT_AUTHORIZED, MANAGE_SELL_OFFER_LINE_FULL, MANAGE_SELL_OFFER_UNDERFUNDED, MANAGE_SELL_OFFER_CROSS_SELF, MANAGE_SELL_OFFER_SELL_NO_ISSUER, MANAGE_SELL_OFFER_BUY_NO_ISSUER, MANAGE_SELL_OFFER_NOT_FOUND, MANAGE_SELL_OFFER_LOW_RESERVE: + case PAYMENT_SUCCESS: + return "" + case PAYMENT_MALFORMED, PAYMENT_UNDERFUNDED, PAYMENT_SRC_NO_TRUST, PAYMENT_SRC_NOT_AUTHORIZED, PAYMENT_NO_DESTINATION, PAYMENT_NO_TRUST, PAYMENT_NOT_AUTHORIZED, PAYMENT_LINE_FULL, PAYMENT_NO_ISSUER: return "" } return "" } -type XdrType_ManageSellOfferResult = *ManageSellOfferResult +type XdrType_PaymentResult = *PaymentResult -func (v *ManageSellOfferResult) XdrPointer() interface{} { return v } -func (ManageSellOfferResult) XdrTypeName() string { return "ManageSellOfferResult" } -func (v ManageSellOfferResult) XdrValue() interface{} { return v } -func (v *ManageSellOfferResult) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -func (u *ManageSellOfferResult) XdrRecurse(x XDR, name string) { - if name != "" { +func (v *PaymentResult) XdrPointer() interface{} { return v } +func (PaymentResult) XdrTypeName() string { return "PaymentResult" } +func (v PaymentResult) XdrValue() interface{} { return v } +func (v *PaymentResult) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (u *PaymentResult) XdrRecurse(x XDR, name string) { + if name != "" { name = x.Sprintf("%s.", name) } - XDR_ManageSellOfferResultCode(&u.Code).XdrMarshal(x, x.Sprintf("%scode", name)) + XDR_PaymentResultCode(&u.Code).XdrMarshal(x, x.Sprintf("%scode", name)) switch u.Code { - case MANAGE_SELL_OFFER_SUCCESS: - x.Marshal(x.Sprintf("%ssuccess", name), XDR_ManageOfferSuccessResult(u.Success())) + case PAYMENT_SUCCESS: return - case MANAGE_SELL_OFFER_MALFORMED, MANAGE_SELL_OFFER_SELL_NO_TRUST, MANAGE_SELL_OFFER_BUY_NO_TRUST, MANAGE_SELL_OFFER_SELL_NOT_AUTHORIZED, MANAGE_SELL_OFFER_BUY_NOT_AUTHORIZED, MANAGE_SELL_OFFER_LINE_FULL, MANAGE_SELL_OFFER_UNDERFUNDED, MANAGE_SELL_OFFER_CROSS_SELF, MANAGE_SELL_OFFER_SELL_NO_ISSUER, MANAGE_SELL_OFFER_BUY_NO_ISSUER, MANAGE_SELL_OFFER_NOT_FOUND, MANAGE_SELL_OFFER_LOW_RESERVE: + case PAYMENT_MALFORMED, PAYMENT_UNDERFUNDED, PAYMENT_SRC_NO_TRUST, PAYMENT_SRC_NOT_AUTHORIZED, PAYMENT_NO_DESTINATION, PAYMENT_NO_TRUST, PAYMENT_NOT_AUTHORIZED, PAYMENT_LINE_FULL, PAYMENT_NO_ISSUER: return } - XdrPanic("invalid Code (%v) in ManageSellOfferResult", u.Code) + XdrPanic("invalid Code (%v) in PaymentResult", u.Code) } -func XDR_ManageSellOfferResult(v *ManageSellOfferResult) *ManageSellOfferResult { return v } +func XDR_PaymentResult(v *PaymentResult) *PaymentResult { return v } -var _XdrNames_ManageBuyOfferResultCode = map[int32]string{ - int32(MANAGE_BUY_OFFER_SUCCESS): "MANAGE_BUY_OFFER_SUCCESS", - int32(MANAGE_BUY_OFFER_MALFORMED): "MANAGE_BUY_OFFER_MALFORMED", - int32(MANAGE_BUY_OFFER_SELL_NO_TRUST): "MANAGE_BUY_OFFER_SELL_NO_TRUST", - int32(MANAGE_BUY_OFFER_BUY_NO_TRUST): "MANAGE_BUY_OFFER_BUY_NO_TRUST", - int32(MANAGE_BUY_OFFER_SELL_NOT_AUTHORIZED): "MANAGE_BUY_OFFER_SELL_NOT_AUTHORIZED", - int32(MANAGE_BUY_OFFER_BUY_NOT_AUTHORIZED): "MANAGE_BUY_OFFER_BUY_NOT_AUTHORIZED", - int32(MANAGE_BUY_OFFER_LINE_FULL): "MANAGE_BUY_OFFER_LINE_FULL", - int32(MANAGE_BUY_OFFER_UNDERFUNDED): "MANAGE_BUY_OFFER_UNDERFUNDED", - int32(MANAGE_BUY_OFFER_CROSS_SELF): "MANAGE_BUY_OFFER_CROSS_SELF", - int32(MANAGE_BUY_OFFER_SELL_NO_ISSUER): "MANAGE_BUY_OFFER_SELL_NO_ISSUER", - int32(MANAGE_BUY_OFFER_BUY_NO_ISSUER): "MANAGE_BUY_OFFER_BUY_NO_ISSUER", - int32(MANAGE_BUY_OFFER_NOT_FOUND): "MANAGE_BUY_OFFER_NOT_FOUND", - int32(MANAGE_BUY_OFFER_LOW_RESERVE): "MANAGE_BUY_OFFER_LOW_RESERVE", +var _XdrNames_PathPaymentStrictReceiveResultCode = map[int32]string{ + int32(PATH_PAYMENT_STRICT_RECEIVE_SUCCESS): "PATH_PAYMENT_STRICT_RECEIVE_SUCCESS", + int32(PATH_PAYMENT_STRICT_RECEIVE_MALFORMED): "PATH_PAYMENT_STRICT_RECEIVE_MALFORMED", + int32(PATH_PAYMENT_STRICT_RECEIVE_UNDERFUNDED): "PATH_PAYMENT_STRICT_RECEIVE_UNDERFUNDED", + int32(PATH_PAYMENT_STRICT_RECEIVE_SRC_NO_TRUST): "PATH_PAYMENT_STRICT_RECEIVE_SRC_NO_TRUST", + int32(PATH_PAYMENT_STRICT_RECEIVE_SRC_NOT_AUTHORIZED): "PATH_PAYMENT_STRICT_RECEIVE_SRC_NOT_AUTHORIZED", + int32(PATH_PAYMENT_STRICT_RECEIVE_NO_DESTINATION): "PATH_PAYMENT_STRICT_RECEIVE_NO_DESTINATION", + int32(PATH_PAYMENT_STRICT_RECEIVE_NO_TRUST): "PATH_PAYMENT_STRICT_RECEIVE_NO_TRUST", + int32(PATH_PAYMENT_STRICT_RECEIVE_NOT_AUTHORIZED): "PATH_PAYMENT_STRICT_RECEIVE_NOT_AUTHORIZED", + int32(PATH_PAYMENT_STRICT_RECEIVE_LINE_FULL): "PATH_PAYMENT_STRICT_RECEIVE_LINE_FULL", + int32(PATH_PAYMENT_STRICT_RECEIVE_NO_ISSUER): "PATH_PAYMENT_STRICT_RECEIVE_NO_ISSUER", + int32(PATH_PAYMENT_STRICT_RECEIVE_TOO_FEW_OFFERS): "PATH_PAYMENT_STRICT_RECEIVE_TOO_FEW_OFFERS", + int32(PATH_PAYMENT_STRICT_RECEIVE_OFFER_CROSS_SELF): "PATH_PAYMENT_STRICT_RECEIVE_OFFER_CROSS_SELF", + int32(PATH_PAYMENT_STRICT_RECEIVE_OVER_SENDMAX): "PATH_PAYMENT_STRICT_RECEIVE_OVER_SENDMAX", } -var _XdrValues_ManageBuyOfferResultCode = map[string]int32{ - "MANAGE_BUY_OFFER_SUCCESS": int32(MANAGE_BUY_OFFER_SUCCESS), - "MANAGE_BUY_OFFER_MALFORMED": int32(MANAGE_BUY_OFFER_MALFORMED), - "MANAGE_BUY_OFFER_SELL_NO_TRUST": int32(MANAGE_BUY_OFFER_SELL_NO_TRUST), - "MANAGE_BUY_OFFER_BUY_NO_TRUST": int32(MANAGE_BUY_OFFER_BUY_NO_TRUST), - "MANAGE_BUY_OFFER_SELL_NOT_AUTHORIZED": int32(MANAGE_BUY_OFFER_SELL_NOT_AUTHORIZED), - "MANAGE_BUY_OFFER_BUY_NOT_AUTHORIZED": int32(MANAGE_BUY_OFFER_BUY_NOT_AUTHORIZED), - "MANAGE_BUY_OFFER_LINE_FULL": int32(MANAGE_BUY_OFFER_LINE_FULL), - "MANAGE_BUY_OFFER_UNDERFUNDED": int32(MANAGE_BUY_OFFER_UNDERFUNDED), - "MANAGE_BUY_OFFER_CROSS_SELF": int32(MANAGE_BUY_OFFER_CROSS_SELF), - "MANAGE_BUY_OFFER_SELL_NO_ISSUER": int32(MANAGE_BUY_OFFER_SELL_NO_ISSUER), - "MANAGE_BUY_OFFER_BUY_NO_ISSUER": int32(MANAGE_BUY_OFFER_BUY_NO_ISSUER), - "MANAGE_BUY_OFFER_NOT_FOUND": int32(MANAGE_BUY_OFFER_NOT_FOUND), - "MANAGE_BUY_OFFER_LOW_RESERVE": int32(MANAGE_BUY_OFFER_LOW_RESERVE), +var _XdrValues_PathPaymentStrictReceiveResultCode = map[string]int32{ + "PATH_PAYMENT_STRICT_RECEIVE_SUCCESS": int32(PATH_PAYMENT_STRICT_RECEIVE_SUCCESS), + "PATH_PAYMENT_STRICT_RECEIVE_MALFORMED": int32(PATH_PAYMENT_STRICT_RECEIVE_MALFORMED), + "PATH_PAYMENT_STRICT_RECEIVE_UNDERFUNDED": int32(PATH_PAYMENT_STRICT_RECEIVE_UNDERFUNDED), + "PATH_PAYMENT_STRICT_RECEIVE_SRC_NO_TRUST": int32(PATH_PAYMENT_STRICT_RECEIVE_SRC_NO_TRUST), + "PATH_PAYMENT_STRICT_RECEIVE_SRC_NOT_AUTHORIZED": int32(PATH_PAYMENT_STRICT_RECEIVE_SRC_NOT_AUTHORIZED), + "PATH_PAYMENT_STRICT_RECEIVE_NO_DESTINATION": int32(PATH_PAYMENT_STRICT_RECEIVE_NO_DESTINATION), + "PATH_PAYMENT_STRICT_RECEIVE_NO_TRUST": int32(PATH_PAYMENT_STRICT_RECEIVE_NO_TRUST), + "PATH_PAYMENT_STRICT_RECEIVE_NOT_AUTHORIZED": int32(PATH_PAYMENT_STRICT_RECEIVE_NOT_AUTHORIZED), + "PATH_PAYMENT_STRICT_RECEIVE_LINE_FULL": int32(PATH_PAYMENT_STRICT_RECEIVE_LINE_FULL), + "PATH_PAYMENT_STRICT_RECEIVE_NO_ISSUER": int32(PATH_PAYMENT_STRICT_RECEIVE_NO_ISSUER), + "PATH_PAYMENT_STRICT_RECEIVE_TOO_FEW_OFFERS": int32(PATH_PAYMENT_STRICT_RECEIVE_TOO_FEW_OFFERS), + "PATH_PAYMENT_STRICT_RECEIVE_OFFER_CROSS_SELF": int32(PATH_PAYMENT_STRICT_RECEIVE_OFFER_CROSS_SELF), + "PATH_PAYMENT_STRICT_RECEIVE_OVER_SENDMAX": int32(PATH_PAYMENT_STRICT_RECEIVE_OVER_SENDMAX), } -func (ManageBuyOfferResultCode) XdrEnumNames() map[int32]string { - return _XdrNames_ManageBuyOfferResultCode +func (PathPaymentStrictReceiveResultCode) XdrEnumNames() map[int32]string { + return _XdrNames_PathPaymentStrictReceiveResultCode } -func (v ManageBuyOfferResultCode) String() string { - if s, ok := _XdrNames_ManageBuyOfferResultCode[int32(v)]; ok { +func (v PathPaymentStrictReceiveResultCode) String() string { + if s, ok := _XdrNames_PathPaymentStrictReceiveResultCode[int32(v)]; ok { return s } - return fmt.Sprintf("ManageBuyOfferResultCode#%d", v) + return fmt.Sprintf("PathPaymentStrictReceiveResultCode#%d", v) } -func (v *ManageBuyOfferResultCode) Scan(ss fmt.ScanState, _ rune) error { +func (v *PathPaymentStrictReceiveResultCode) Scan(ss fmt.ScanState, _ rune) error { if tok, err := ss.Token(true, XdrSymChar); err != nil { return err } else { stok := string(tok) - if val, ok := _XdrValues_ManageBuyOfferResultCode[stok]; ok { - *v = ManageBuyOfferResultCode(val) + if val, ok := _XdrValues_PathPaymentStrictReceiveResultCode[stok]; ok { + *v = PathPaymentStrictReceiveResultCode(val) return nil - } else if stok == "ManageBuyOfferResultCode" { + } else if stok == "PathPaymentStrictReceiveResultCode" { if n, err := fmt.Fscanf(ss, "#%d", (*int32)(v)); n == 1 && err == nil { return nil } } - return XdrError(fmt.Sprintf("%s is not a valid ManageBuyOfferResultCode.", stok)) + return XdrError(fmt.Sprintf("%s is not a valid PathPaymentStrictReceiveResultCode.", stok)) } } -func (v ManageBuyOfferResultCode) GetU32() uint32 { return uint32(v) } -func (v *ManageBuyOfferResultCode) SetU32(n uint32) { *v = ManageBuyOfferResultCode(n) } -func (v *ManageBuyOfferResultCode) XdrPointer() interface{} { return v } -func (ManageBuyOfferResultCode) XdrTypeName() string { return "ManageBuyOfferResultCode" } -func (v ManageBuyOfferResultCode) XdrValue() interface{} { return v } -func (v *ManageBuyOfferResultCode) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v PathPaymentStrictReceiveResultCode) GetU32() uint32 { return uint32(v) } +func (v *PathPaymentStrictReceiveResultCode) SetU32(n uint32) { + *v = PathPaymentStrictReceiveResultCode(n) +} +func (v *PathPaymentStrictReceiveResultCode) XdrPointer() interface{} { return v } +func (PathPaymentStrictReceiveResultCode) XdrTypeName() string { + return "PathPaymentStrictReceiveResultCode" +} +func (v PathPaymentStrictReceiveResultCode) XdrValue() interface{} { return v } +func (v *PathPaymentStrictReceiveResultCode) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -type XdrType_ManageBuyOfferResultCode = *ManageBuyOfferResultCode +type XdrType_PathPaymentStrictReceiveResultCode = *PathPaymentStrictReceiveResultCode -func XDR_ManageBuyOfferResultCode(v *ManageBuyOfferResultCode) *ManageBuyOfferResultCode { return v } +func XDR_PathPaymentStrictReceiveResultCode(v *PathPaymentStrictReceiveResultCode) *PathPaymentStrictReceiveResultCode { + return v +} -var _XdrComments_ManageBuyOfferResultCode = map[int32]string{ - int32(MANAGE_BUY_OFFER_SUCCESS): "codes considered as \"success\" for the operation", - int32(MANAGE_BUY_OFFER_MALFORMED): "generated offer would be invalid", - int32(MANAGE_BUY_OFFER_SELL_NO_TRUST): "no trust line for what we're selling", - int32(MANAGE_BUY_OFFER_BUY_NO_TRUST): "no trust line for what we're buying", - int32(MANAGE_BUY_OFFER_SELL_NOT_AUTHORIZED): "not authorized to sell", - int32(MANAGE_BUY_OFFER_BUY_NOT_AUTHORIZED): "not authorized to buy", - int32(MANAGE_BUY_OFFER_LINE_FULL): "can't receive more of what it's buying", - int32(MANAGE_BUY_OFFER_UNDERFUNDED): "doesn't hold what it's trying to sell", - int32(MANAGE_BUY_OFFER_CROSS_SELF): "would cross an offer from the same user", - int32(MANAGE_BUY_OFFER_SELL_NO_ISSUER): "no issuer for what we're selling", - int32(MANAGE_BUY_OFFER_BUY_NO_ISSUER): "no issuer for what we're buying", - int32(MANAGE_BUY_OFFER_NOT_FOUND): "offerID does not match an existing offer", - int32(MANAGE_BUY_OFFER_LOW_RESERVE): "not enough funds to create a new Offer", +var _XdrComments_PathPaymentStrictReceiveResultCode = map[int32]string{ + int32(PATH_PAYMENT_STRICT_RECEIVE_SUCCESS): "success", + int32(PATH_PAYMENT_STRICT_RECEIVE_MALFORMED): "bad input", + int32(PATH_PAYMENT_STRICT_RECEIVE_UNDERFUNDED): "not enough funds in source account", + int32(PATH_PAYMENT_STRICT_RECEIVE_SRC_NO_TRUST): "no trust line on source account", + int32(PATH_PAYMENT_STRICT_RECEIVE_SRC_NOT_AUTHORIZED): "source not authorized to transfer", + int32(PATH_PAYMENT_STRICT_RECEIVE_NO_DESTINATION): "destination account does not exist", + int32(PATH_PAYMENT_STRICT_RECEIVE_NO_TRUST): "dest missing a trust line for asset", + int32(PATH_PAYMENT_STRICT_RECEIVE_NOT_AUTHORIZED): "dest not authorized to hold asset", + int32(PATH_PAYMENT_STRICT_RECEIVE_LINE_FULL): "dest would go above their limit", + int32(PATH_PAYMENT_STRICT_RECEIVE_NO_ISSUER): "missing issuer on one asset", + int32(PATH_PAYMENT_STRICT_RECEIVE_TOO_FEW_OFFERS): "not enough offers to satisfy path", + int32(PATH_PAYMENT_STRICT_RECEIVE_OFFER_CROSS_SELF): "would cross one of its own offers", + int32(PATH_PAYMENT_STRICT_RECEIVE_OVER_SENDMAX): "could not satisfy sendmax", } -func (e ManageBuyOfferResultCode) XdrEnumComments() map[int32]string { - return _XdrComments_ManageBuyOfferResultCode +func (e PathPaymentStrictReceiveResultCode) XdrEnumComments() map[int32]string { + return _XdrComments_PathPaymentStrictReceiveResultCode } -var _XdrTags_ManageBuyOfferResult = map[int32]bool{ - XdrToI32(MANAGE_BUY_OFFER_SUCCESS): true, - XdrToI32(MANAGE_BUY_OFFER_MALFORMED): true, - XdrToI32(MANAGE_BUY_OFFER_SELL_NO_TRUST): true, - XdrToI32(MANAGE_BUY_OFFER_BUY_NO_TRUST): true, - XdrToI32(MANAGE_BUY_OFFER_SELL_NOT_AUTHORIZED): true, - XdrToI32(MANAGE_BUY_OFFER_BUY_NOT_AUTHORIZED): true, - XdrToI32(MANAGE_BUY_OFFER_LINE_FULL): true, - XdrToI32(MANAGE_BUY_OFFER_UNDERFUNDED): true, - XdrToI32(MANAGE_BUY_OFFER_CROSS_SELF): true, - XdrToI32(MANAGE_BUY_OFFER_SELL_NO_ISSUER): true, - XdrToI32(MANAGE_BUY_OFFER_BUY_NO_ISSUER): true, - XdrToI32(MANAGE_BUY_OFFER_NOT_FOUND): true, - XdrToI32(MANAGE_BUY_OFFER_LOW_RESERVE): true, +type XdrType_SimplePaymentResult = *SimplePaymentResult + +func (v *SimplePaymentResult) XdrPointer() interface{} { return v } +func (SimplePaymentResult) XdrTypeName() string { return "SimplePaymentResult" } +func (v SimplePaymentResult) XdrValue() interface{} { return v } +func (v *SimplePaymentResult) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v *SimplePaymentResult) XdrRecurse(x XDR, name string) { + if name != "" { + name = x.Sprintf("%s.", name) + } + x.Marshal(x.Sprintf("%sdestination", name), XDR_AccountID(&v.Destination)) + x.Marshal(x.Sprintf("%sasset", name), XDR_Asset(&v.Asset)) + x.Marshal(x.Sprintf("%samount", name), XDR_Int64(&v.Amount)) } +func XDR_SimplePaymentResult(v *SimplePaymentResult) *SimplePaymentResult { return v } -func (_ ManageBuyOfferResult) XdrValidTags() map[int32]bool { - return _XdrTags_ManageBuyOfferResult +type _XdrVec_unbounded_ClaimAtom []ClaimAtom + +func (_XdrVec_unbounded_ClaimAtom) XdrBound() uint32 { + const bound uint32 = 4294967295 // Force error if not const or doesn't fit + return bound } -func (u *ManageBuyOfferResult) Success() *ManageOfferSuccessResult { - switch u.Code { - case MANAGE_BUY_OFFER_SUCCESS: - if v, ok := u._u.(*ManageOfferSuccessResult); ok { - return v - } else { - var zero ManageOfferSuccessResult - u._u = &zero - return &zero - } - default: - XdrPanic("ManageBuyOfferResult.Success accessed when Code == %v", u.Code) - return nil +func (_XdrVec_unbounded_ClaimAtom) XdrCheckLen(length uint32) { + if length > uint32(4294967295) { + XdrPanic("_XdrVec_unbounded_ClaimAtom length %d exceeds bound 4294967295", length) + } else if int(length) < 0 { + XdrPanic("_XdrVec_unbounded_ClaimAtom length %d exceeds max int", length) } } -func (u ManageBuyOfferResult) XdrValid() bool { - switch u.Code { - case MANAGE_BUY_OFFER_SUCCESS, MANAGE_BUY_OFFER_MALFORMED, MANAGE_BUY_OFFER_SELL_NO_TRUST, MANAGE_BUY_OFFER_BUY_NO_TRUST, MANAGE_BUY_OFFER_SELL_NOT_AUTHORIZED, MANAGE_BUY_OFFER_BUY_NOT_AUTHORIZED, MANAGE_BUY_OFFER_LINE_FULL, MANAGE_BUY_OFFER_UNDERFUNDED, MANAGE_BUY_OFFER_CROSS_SELF, MANAGE_BUY_OFFER_SELL_NO_ISSUER, MANAGE_BUY_OFFER_BUY_NO_ISSUER, MANAGE_BUY_OFFER_NOT_FOUND, MANAGE_BUY_OFFER_LOW_RESERVE: - return true +func (v _XdrVec_unbounded_ClaimAtom) GetVecLen() uint32 { return uint32(len(v)) } +func (v *_XdrVec_unbounded_ClaimAtom) SetVecLen(length uint32) { + v.XdrCheckLen(length) + if int(length) <= cap(*v) { + if int(length) != len(*v) { + *v = (*v)[:int(length)] + } + return } - return false -} -func (u *ManageBuyOfferResult) XdrUnionTag() XdrNum32 { - return XDR_ManageBuyOfferResultCode(&u.Code) -} -func (u *ManageBuyOfferResult) XdrUnionTagName() string { - return "Code" -} -func (u *ManageBuyOfferResult) XdrUnionBody() XdrType { - switch u.Code { - case MANAGE_BUY_OFFER_SUCCESS: - return XDR_ManageOfferSuccessResult(u.Success()) - case MANAGE_BUY_OFFER_MALFORMED, MANAGE_BUY_OFFER_SELL_NO_TRUST, MANAGE_BUY_OFFER_BUY_NO_TRUST, MANAGE_BUY_OFFER_SELL_NOT_AUTHORIZED, MANAGE_BUY_OFFER_BUY_NOT_AUTHORIZED, MANAGE_BUY_OFFER_LINE_FULL, MANAGE_BUY_OFFER_UNDERFUNDED, MANAGE_BUY_OFFER_CROSS_SELF, MANAGE_BUY_OFFER_SELL_NO_ISSUER, MANAGE_BUY_OFFER_BUY_NO_ISSUER, MANAGE_BUY_OFFER_NOT_FOUND, MANAGE_BUY_OFFER_LOW_RESERVE: - return nil + newcap := 2 * cap(*v) + if newcap < int(length) { // also catches overflow where 2*cap < 0 + newcap = int(length) + } else if bound := uint(4294967295); uint(newcap) > bound { + if int(bound) < 0 { + bound = ^uint(0) >> 1 + } + newcap = int(bound) } - return nil + nv := make([]ClaimAtom, int(length), newcap) + copy(nv, *v) + *v = nv } -func (u *ManageBuyOfferResult) XdrUnionBodyName() string { - switch u.Code { - case MANAGE_BUY_OFFER_SUCCESS: - return "Success" - case MANAGE_BUY_OFFER_MALFORMED, MANAGE_BUY_OFFER_SELL_NO_TRUST, MANAGE_BUY_OFFER_BUY_NO_TRUST, MANAGE_BUY_OFFER_SELL_NOT_AUTHORIZED, MANAGE_BUY_OFFER_BUY_NOT_AUTHORIZED, MANAGE_BUY_OFFER_LINE_FULL, MANAGE_BUY_OFFER_UNDERFUNDED, MANAGE_BUY_OFFER_CROSS_SELF, MANAGE_BUY_OFFER_SELL_NO_ISSUER, MANAGE_BUY_OFFER_BUY_NO_ISSUER, MANAGE_BUY_OFFER_NOT_FOUND, MANAGE_BUY_OFFER_LOW_RESERVE: - return "" +func (v *_XdrVec_unbounded_ClaimAtom) XdrMarshalN(x XDR, name string, n uint32) { + v.XdrCheckLen(n) + for i := 0; i < int(n); i++ { + if i >= len(*v) { + v.SetVecLen(uint32(i + 1)) + } + XDR_ClaimAtom(&(*v)[i]).XdrMarshal(x, x.Sprintf("%s[%d]", name, i)) + } + if int(n) < len(*v) { + *v = (*v)[:int(n)] } - return "" } - -type XdrType_ManageBuyOfferResult = *ManageBuyOfferResult - -func (v *ManageBuyOfferResult) XdrPointer() interface{} { return v } -func (ManageBuyOfferResult) XdrTypeName() string { return "ManageBuyOfferResult" } -func (v ManageBuyOfferResult) XdrValue() interface{} { return v } -func (v *ManageBuyOfferResult) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -func (u *ManageBuyOfferResult) XdrRecurse(x XDR, name string) { - if name != "" { - name = x.Sprintf("%s.", name) - } - XDR_ManageBuyOfferResultCode(&u.Code).XdrMarshal(x, x.Sprintf("%scode", name)) - switch u.Code { - case MANAGE_BUY_OFFER_SUCCESS: - x.Marshal(x.Sprintf("%ssuccess", name), XDR_ManageOfferSuccessResult(u.Success())) - return - case MANAGE_BUY_OFFER_MALFORMED, MANAGE_BUY_OFFER_SELL_NO_TRUST, MANAGE_BUY_OFFER_BUY_NO_TRUST, MANAGE_BUY_OFFER_SELL_NOT_AUTHORIZED, MANAGE_BUY_OFFER_BUY_NOT_AUTHORIZED, MANAGE_BUY_OFFER_LINE_FULL, MANAGE_BUY_OFFER_UNDERFUNDED, MANAGE_BUY_OFFER_CROSS_SELF, MANAGE_BUY_OFFER_SELL_NO_ISSUER, MANAGE_BUY_OFFER_BUY_NO_ISSUER, MANAGE_BUY_OFFER_NOT_FOUND, MANAGE_BUY_OFFER_LOW_RESERVE: - return - } - XdrPanic("invalid Code (%v) in ManageBuyOfferResult", u.Code) +func (v *_XdrVec_unbounded_ClaimAtom) XdrRecurse(x XDR, name string) { + size := XdrSize{Size: uint32(len(*v)), Bound: 4294967295} + x.Marshal(name, &size) + v.XdrMarshalN(x, name, size.Size) } -func XDR_ManageBuyOfferResult(v *ManageBuyOfferResult) *ManageBuyOfferResult { return v } +func (_XdrVec_unbounded_ClaimAtom) XdrTypeName() string { return "ClaimAtom<>" } +func (v *_XdrVec_unbounded_ClaimAtom) XdrPointer() interface{} { return (*[]ClaimAtom)(v) } +func (v _XdrVec_unbounded_ClaimAtom) XdrValue() interface{} { return ([]ClaimAtom)(v) } +func (v *_XdrVec_unbounded_ClaimAtom) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -var _XdrNames_SetOptionsResultCode = map[int32]string{ - int32(SET_OPTIONS_SUCCESS): "SET_OPTIONS_SUCCESS", - int32(SET_OPTIONS_LOW_RESERVE): "SET_OPTIONS_LOW_RESERVE", - int32(SET_OPTIONS_TOO_MANY_SIGNERS): "SET_OPTIONS_TOO_MANY_SIGNERS", - int32(SET_OPTIONS_BAD_FLAGS): "SET_OPTIONS_BAD_FLAGS", - int32(SET_OPTIONS_INVALID_INFLATION): "SET_OPTIONS_INVALID_INFLATION", - int32(SET_OPTIONS_CANT_CHANGE): "SET_OPTIONS_CANT_CHANGE", - int32(SET_OPTIONS_UNKNOWN_FLAG): "SET_OPTIONS_UNKNOWN_FLAG", - int32(SET_OPTIONS_THRESHOLD_OUT_OF_RANGE): "SET_OPTIONS_THRESHOLD_OUT_OF_RANGE", - int32(SET_OPTIONS_BAD_SIGNER): "SET_OPTIONS_BAD_SIGNER", - int32(SET_OPTIONS_INVALID_HOME_DOMAIN): "SET_OPTIONS_INVALID_HOME_DOMAIN", - int32(SET_OPTIONS_AUTH_REVOCABLE_REQUIRED): "SET_OPTIONS_AUTH_REVOCABLE_REQUIRED", -} -var _XdrValues_SetOptionsResultCode = map[string]int32{ - "SET_OPTIONS_SUCCESS": int32(SET_OPTIONS_SUCCESS), - "SET_OPTIONS_LOW_RESERVE": int32(SET_OPTIONS_LOW_RESERVE), - "SET_OPTIONS_TOO_MANY_SIGNERS": int32(SET_OPTIONS_TOO_MANY_SIGNERS), - "SET_OPTIONS_BAD_FLAGS": int32(SET_OPTIONS_BAD_FLAGS), - "SET_OPTIONS_INVALID_INFLATION": int32(SET_OPTIONS_INVALID_INFLATION), - "SET_OPTIONS_CANT_CHANGE": int32(SET_OPTIONS_CANT_CHANGE), - "SET_OPTIONS_UNKNOWN_FLAG": int32(SET_OPTIONS_UNKNOWN_FLAG), - "SET_OPTIONS_THRESHOLD_OUT_OF_RANGE": int32(SET_OPTIONS_THRESHOLD_OUT_OF_RANGE), - "SET_OPTIONS_BAD_SIGNER": int32(SET_OPTIONS_BAD_SIGNER), - "SET_OPTIONS_INVALID_HOME_DOMAIN": int32(SET_OPTIONS_INVALID_HOME_DOMAIN), - "SET_OPTIONS_AUTH_REVOCABLE_REQUIRED": int32(SET_OPTIONS_AUTH_REVOCABLE_REQUIRED), -} +type XdrType_XdrAnon_PathPaymentStrictReceiveResult_Success = *XdrAnon_PathPaymentStrictReceiveResult_Success -func (SetOptionsResultCode) XdrEnumNames() map[int32]string { - return _XdrNames_SetOptionsResultCode +func (v *XdrAnon_PathPaymentStrictReceiveResult_Success) XdrPointer() interface{} { return v } +func (XdrAnon_PathPaymentStrictReceiveResult_Success) XdrTypeName() string { + return "XdrAnon_PathPaymentStrictReceiveResult_Success" } -func (v SetOptionsResultCode) String() string { - if s, ok := _XdrNames_SetOptionsResultCode[int32(v)]; ok { - return s - } - return fmt.Sprintf("SetOptionsResultCode#%d", v) +func (v XdrAnon_PathPaymentStrictReceiveResult_Success) XdrValue() interface{} { return v } +func (v *XdrAnon_PathPaymentStrictReceiveResult_Success) XdrMarshal(x XDR, name string) { + x.Marshal(name, v) } -func (v *SetOptionsResultCode) Scan(ss fmt.ScanState, _ rune) error { - if tok, err := ss.Token(true, XdrSymChar); err != nil { - return err - } else { - stok := string(tok) - if val, ok := _XdrValues_SetOptionsResultCode[stok]; ok { - *v = SetOptionsResultCode(val) - return nil - } else if stok == "SetOptionsResultCode" { - if n, err := fmt.Fscanf(ss, "#%d", (*int32)(v)); n == 1 && err == nil { - return nil - } - } - return XdrError(fmt.Sprintf("%s is not a valid SetOptionsResultCode.", stok)) +func (v *XdrAnon_PathPaymentStrictReceiveResult_Success) XdrRecurse(x XDR, name string) { + if name != "" { + name = x.Sprintf("%s.", name) } + x.Marshal(x.Sprintf("%soffers", name), (*_XdrVec_unbounded_ClaimAtom)(&v.Offers)) + x.Marshal(x.Sprintf("%slast", name), XDR_SimplePaymentResult(&v.Last)) } -func (v SetOptionsResultCode) GetU32() uint32 { return uint32(v) } -func (v *SetOptionsResultCode) SetU32(n uint32) { *v = SetOptionsResultCode(n) } -func (v *SetOptionsResultCode) XdrPointer() interface{} { return v } -func (SetOptionsResultCode) XdrTypeName() string { return "SetOptionsResultCode" } -func (v SetOptionsResultCode) XdrValue() interface{} { return v } -func (v *SetOptionsResultCode) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } - -type XdrType_SetOptionsResultCode = *SetOptionsResultCode - -func XDR_SetOptionsResultCode(v *SetOptionsResultCode) *SetOptionsResultCode { return v } - -var _XdrComments_SetOptionsResultCode = map[int32]string{ - int32(SET_OPTIONS_SUCCESS): "codes considered as \"success\" for the operation", - int32(SET_OPTIONS_LOW_RESERVE): "not enough funds to add a signer", - int32(SET_OPTIONS_TOO_MANY_SIGNERS): "max number of signers already reached", - int32(SET_OPTIONS_BAD_FLAGS): "invalid combination of clear/set flags", - int32(SET_OPTIONS_INVALID_INFLATION): "inflation account does not exist", - int32(SET_OPTIONS_CANT_CHANGE): "can no longer change this option", - int32(SET_OPTIONS_UNKNOWN_FLAG): "can't set an unknown flag", - int32(SET_OPTIONS_THRESHOLD_OUT_OF_RANGE): "bad value for weight/threshold", - int32(SET_OPTIONS_BAD_SIGNER): "signer cannot be masterkey", - int32(SET_OPTIONS_INVALID_HOME_DOMAIN): "malformed home domain", - int32(SET_OPTIONS_AUTH_REVOCABLE_REQUIRED): "auth revocable is required for clawback", +func XDR_XdrAnon_PathPaymentStrictReceiveResult_Success(v *XdrAnon_PathPaymentStrictReceiveResult_Success) *XdrAnon_PathPaymentStrictReceiveResult_Success { + return v } -func (e SetOptionsResultCode) XdrEnumComments() map[int32]string { - return _XdrComments_SetOptionsResultCode +var _XdrTags_PathPaymentStrictReceiveResult = map[int32]bool{ + XdrToI32(PATH_PAYMENT_STRICT_RECEIVE_SUCCESS): true, + XdrToI32(PATH_PAYMENT_STRICT_RECEIVE_MALFORMED): true, + XdrToI32(PATH_PAYMENT_STRICT_RECEIVE_UNDERFUNDED): true, + XdrToI32(PATH_PAYMENT_STRICT_RECEIVE_SRC_NO_TRUST): true, + XdrToI32(PATH_PAYMENT_STRICT_RECEIVE_SRC_NOT_AUTHORIZED): true, + XdrToI32(PATH_PAYMENT_STRICT_RECEIVE_NO_DESTINATION): true, + XdrToI32(PATH_PAYMENT_STRICT_RECEIVE_NO_TRUST): true, + XdrToI32(PATH_PAYMENT_STRICT_RECEIVE_NOT_AUTHORIZED): true, + XdrToI32(PATH_PAYMENT_STRICT_RECEIVE_LINE_FULL): true, + XdrToI32(PATH_PAYMENT_STRICT_RECEIVE_NO_ISSUER): true, + XdrToI32(PATH_PAYMENT_STRICT_RECEIVE_TOO_FEW_OFFERS): true, + XdrToI32(PATH_PAYMENT_STRICT_RECEIVE_OFFER_CROSS_SELF): true, + XdrToI32(PATH_PAYMENT_STRICT_RECEIVE_OVER_SENDMAX): true, } -var _XdrTags_SetOptionsResult = map[int32]bool{ - XdrToI32(SET_OPTIONS_SUCCESS): true, - XdrToI32(SET_OPTIONS_LOW_RESERVE): true, - XdrToI32(SET_OPTIONS_TOO_MANY_SIGNERS): true, - XdrToI32(SET_OPTIONS_BAD_FLAGS): true, - XdrToI32(SET_OPTIONS_INVALID_INFLATION): true, - XdrToI32(SET_OPTIONS_CANT_CHANGE): true, - XdrToI32(SET_OPTIONS_UNKNOWN_FLAG): true, - XdrToI32(SET_OPTIONS_THRESHOLD_OUT_OF_RANGE): true, - XdrToI32(SET_OPTIONS_BAD_SIGNER): true, - XdrToI32(SET_OPTIONS_INVALID_HOME_DOMAIN): true, - XdrToI32(SET_OPTIONS_AUTH_REVOCABLE_REQUIRED): true, +func (_ PathPaymentStrictReceiveResult) XdrValidTags() map[int32]bool { + return _XdrTags_PathPaymentStrictReceiveResult +} +func (u *PathPaymentStrictReceiveResult) Success() *XdrAnon_PathPaymentStrictReceiveResult_Success { + switch u.Code { + case PATH_PAYMENT_STRICT_RECEIVE_SUCCESS: + if v, ok := u._u.(*XdrAnon_PathPaymentStrictReceiveResult_Success); ok { + return v + } else { + var zero XdrAnon_PathPaymentStrictReceiveResult_Success + u._u = &zero + return &zero + } + default: + XdrPanic("PathPaymentStrictReceiveResult.Success accessed when Code == %v", u.Code) + return nil + } } -func (_ SetOptionsResult) XdrValidTags() map[int32]bool { - return _XdrTags_SetOptionsResult +// the asset that caused the error +func (u *PathPaymentStrictReceiveResult) NoIssuer() *Asset { + switch u.Code { + case PATH_PAYMENT_STRICT_RECEIVE_NO_ISSUER: + if v, ok := u._u.(*Asset); ok { + return v + } else { + var zero Asset + u._u = &zero + return &zero + } + default: + XdrPanic("PathPaymentStrictReceiveResult.NoIssuer accessed when Code == %v", u.Code) + return nil + } } -func (u SetOptionsResult) XdrValid() bool { +func (u PathPaymentStrictReceiveResult) XdrValid() bool { switch u.Code { - case SET_OPTIONS_SUCCESS, SET_OPTIONS_LOW_RESERVE, SET_OPTIONS_TOO_MANY_SIGNERS, SET_OPTIONS_BAD_FLAGS, SET_OPTIONS_INVALID_INFLATION, SET_OPTIONS_CANT_CHANGE, SET_OPTIONS_UNKNOWN_FLAG, SET_OPTIONS_THRESHOLD_OUT_OF_RANGE, SET_OPTIONS_BAD_SIGNER, SET_OPTIONS_INVALID_HOME_DOMAIN, SET_OPTIONS_AUTH_REVOCABLE_REQUIRED: + case PATH_PAYMENT_STRICT_RECEIVE_SUCCESS, PATH_PAYMENT_STRICT_RECEIVE_MALFORMED, PATH_PAYMENT_STRICT_RECEIVE_UNDERFUNDED, PATH_PAYMENT_STRICT_RECEIVE_SRC_NO_TRUST, PATH_PAYMENT_STRICT_RECEIVE_SRC_NOT_AUTHORIZED, PATH_PAYMENT_STRICT_RECEIVE_NO_DESTINATION, PATH_PAYMENT_STRICT_RECEIVE_NO_TRUST, PATH_PAYMENT_STRICT_RECEIVE_NOT_AUTHORIZED, PATH_PAYMENT_STRICT_RECEIVE_LINE_FULL, PATH_PAYMENT_STRICT_RECEIVE_NO_ISSUER, PATH_PAYMENT_STRICT_RECEIVE_TOO_FEW_OFFERS, PATH_PAYMENT_STRICT_RECEIVE_OFFER_CROSS_SELF, PATH_PAYMENT_STRICT_RECEIVE_OVER_SENDMAX: return true } return false } -func (u *SetOptionsResult) XdrUnionTag() XdrNum32 { - return XDR_SetOptionsResultCode(&u.Code) +func (u *PathPaymentStrictReceiveResult) XdrUnionTag() XdrNum32 { + return XDR_PathPaymentStrictReceiveResultCode(&u.Code) } -func (u *SetOptionsResult) XdrUnionTagName() string { +func (u *PathPaymentStrictReceiveResult) XdrUnionTagName() string { return "Code" } -func (u *SetOptionsResult) XdrUnionBody() XdrType { +func (u *PathPaymentStrictReceiveResult) XdrUnionBody() XdrType { switch u.Code { - case SET_OPTIONS_SUCCESS: + case PATH_PAYMENT_STRICT_RECEIVE_SUCCESS: + return XDR_XdrAnon_PathPaymentStrictReceiveResult_Success(u.Success()) + case PATH_PAYMENT_STRICT_RECEIVE_MALFORMED, PATH_PAYMENT_STRICT_RECEIVE_UNDERFUNDED, PATH_PAYMENT_STRICT_RECEIVE_SRC_NO_TRUST, PATH_PAYMENT_STRICT_RECEIVE_SRC_NOT_AUTHORIZED, PATH_PAYMENT_STRICT_RECEIVE_NO_DESTINATION, PATH_PAYMENT_STRICT_RECEIVE_NO_TRUST, PATH_PAYMENT_STRICT_RECEIVE_NOT_AUTHORIZED, PATH_PAYMENT_STRICT_RECEIVE_LINE_FULL: return nil - case SET_OPTIONS_LOW_RESERVE, SET_OPTIONS_TOO_MANY_SIGNERS, SET_OPTIONS_BAD_FLAGS, SET_OPTIONS_INVALID_INFLATION, SET_OPTIONS_CANT_CHANGE, SET_OPTIONS_UNKNOWN_FLAG, SET_OPTIONS_THRESHOLD_OUT_OF_RANGE, SET_OPTIONS_BAD_SIGNER, SET_OPTIONS_INVALID_HOME_DOMAIN, SET_OPTIONS_AUTH_REVOCABLE_REQUIRED: + case PATH_PAYMENT_STRICT_RECEIVE_NO_ISSUER: + return XDR_Asset(u.NoIssuer()) + case PATH_PAYMENT_STRICT_RECEIVE_TOO_FEW_OFFERS, PATH_PAYMENT_STRICT_RECEIVE_OFFER_CROSS_SELF, PATH_PAYMENT_STRICT_RECEIVE_OVER_SENDMAX: return nil } return nil } -func (u *SetOptionsResult) XdrUnionBodyName() string { +func (u *PathPaymentStrictReceiveResult) XdrUnionBodyName() string { switch u.Code { - case SET_OPTIONS_SUCCESS: + case PATH_PAYMENT_STRICT_RECEIVE_SUCCESS: + return "Success" + case PATH_PAYMENT_STRICT_RECEIVE_MALFORMED, PATH_PAYMENT_STRICT_RECEIVE_UNDERFUNDED, PATH_PAYMENT_STRICT_RECEIVE_SRC_NO_TRUST, PATH_PAYMENT_STRICT_RECEIVE_SRC_NOT_AUTHORIZED, PATH_PAYMENT_STRICT_RECEIVE_NO_DESTINATION, PATH_PAYMENT_STRICT_RECEIVE_NO_TRUST, PATH_PAYMENT_STRICT_RECEIVE_NOT_AUTHORIZED, PATH_PAYMENT_STRICT_RECEIVE_LINE_FULL: return "" - case SET_OPTIONS_LOW_RESERVE, SET_OPTIONS_TOO_MANY_SIGNERS, SET_OPTIONS_BAD_FLAGS, SET_OPTIONS_INVALID_INFLATION, SET_OPTIONS_CANT_CHANGE, SET_OPTIONS_UNKNOWN_FLAG, SET_OPTIONS_THRESHOLD_OUT_OF_RANGE, SET_OPTIONS_BAD_SIGNER, SET_OPTIONS_INVALID_HOME_DOMAIN, SET_OPTIONS_AUTH_REVOCABLE_REQUIRED: + case PATH_PAYMENT_STRICT_RECEIVE_NO_ISSUER: + return "NoIssuer" + case PATH_PAYMENT_STRICT_RECEIVE_TOO_FEW_OFFERS, PATH_PAYMENT_STRICT_RECEIVE_OFFER_CROSS_SELF, PATH_PAYMENT_STRICT_RECEIVE_OVER_SENDMAX: return "" } return "" } -type XdrType_SetOptionsResult = *SetOptionsResult +type XdrType_PathPaymentStrictReceiveResult = *PathPaymentStrictReceiveResult -func (v *SetOptionsResult) XdrPointer() interface{} { return v } -func (SetOptionsResult) XdrTypeName() string { return "SetOptionsResult" } -func (v SetOptionsResult) XdrValue() interface{} { return v } -func (v *SetOptionsResult) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -func (u *SetOptionsResult) XdrRecurse(x XDR, name string) { +func (v *PathPaymentStrictReceiveResult) XdrPointer() interface{} { return v } +func (PathPaymentStrictReceiveResult) XdrTypeName() string { return "PathPaymentStrictReceiveResult" } +func (v PathPaymentStrictReceiveResult) XdrValue() interface{} { return v } +func (v *PathPaymentStrictReceiveResult) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (u *PathPaymentStrictReceiveResult) XdrRecurse(x XDR, name string) { if name != "" { name = x.Sprintf("%s.", name) } - XDR_SetOptionsResultCode(&u.Code).XdrMarshal(x, x.Sprintf("%scode", name)) + XDR_PathPaymentStrictReceiveResultCode(&u.Code).XdrMarshal(x, x.Sprintf("%scode", name)) switch u.Code { - case SET_OPTIONS_SUCCESS: + case PATH_PAYMENT_STRICT_RECEIVE_SUCCESS: + x.Marshal(x.Sprintf("%ssuccess", name), XDR_XdrAnon_PathPaymentStrictReceiveResult_Success(u.Success())) return - case SET_OPTIONS_LOW_RESERVE, SET_OPTIONS_TOO_MANY_SIGNERS, SET_OPTIONS_BAD_FLAGS, SET_OPTIONS_INVALID_INFLATION, SET_OPTIONS_CANT_CHANGE, SET_OPTIONS_UNKNOWN_FLAG, SET_OPTIONS_THRESHOLD_OUT_OF_RANGE, SET_OPTIONS_BAD_SIGNER, SET_OPTIONS_INVALID_HOME_DOMAIN, SET_OPTIONS_AUTH_REVOCABLE_REQUIRED: + case PATH_PAYMENT_STRICT_RECEIVE_MALFORMED, PATH_PAYMENT_STRICT_RECEIVE_UNDERFUNDED, PATH_PAYMENT_STRICT_RECEIVE_SRC_NO_TRUST, PATH_PAYMENT_STRICT_RECEIVE_SRC_NOT_AUTHORIZED, PATH_PAYMENT_STRICT_RECEIVE_NO_DESTINATION, PATH_PAYMENT_STRICT_RECEIVE_NO_TRUST, PATH_PAYMENT_STRICT_RECEIVE_NOT_AUTHORIZED, PATH_PAYMENT_STRICT_RECEIVE_LINE_FULL: + return + case PATH_PAYMENT_STRICT_RECEIVE_NO_ISSUER: + x.Marshal(x.Sprintf("%snoIssuer", name), XDR_Asset(u.NoIssuer())) + return + case PATH_PAYMENT_STRICT_RECEIVE_TOO_FEW_OFFERS, PATH_PAYMENT_STRICT_RECEIVE_OFFER_CROSS_SELF, PATH_PAYMENT_STRICT_RECEIVE_OVER_SENDMAX: return } - XdrPanic("invalid Code (%v) in SetOptionsResult", u.Code) -} -func XDR_SetOptionsResult(v *SetOptionsResult) *SetOptionsResult { return v } - -var _XdrNames_ChangeTrustResultCode = map[int32]string{ - int32(CHANGE_TRUST_SUCCESS): "CHANGE_TRUST_SUCCESS", - int32(CHANGE_TRUST_MALFORMED): "CHANGE_TRUST_MALFORMED", - int32(CHANGE_TRUST_NO_ISSUER): "CHANGE_TRUST_NO_ISSUER", - int32(CHANGE_TRUST_INVALID_LIMIT): "CHANGE_TRUST_INVALID_LIMIT", - int32(CHANGE_TRUST_LOW_RESERVE): "CHANGE_TRUST_LOW_RESERVE", - int32(CHANGE_TRUST_SELF_NOT_ALLOWED): "CHANGE_TRUST_SELF_NOT_ALLOWED", - int32(CHANGE_TRUST_TRUST_LINE_MISSING): "CHANGE_TRUST_TRUST_LINE_MISSING", - int32(CHANGE_TRUST_CANNOT_DELETE): "CHANGE_TRUST_CANNOT_DELETE", - int32(CHANGE_TRUST_NOT_AUTH_MAINTAIN_LIABILITIES): "CHANGE_TRUST_NOT_AUTH_MAINTAIN_LIABILITIES", + XdrPanic("invalid Code (%v) in PathPaymentStrictReceiveResult", u.Code) } -var _XdrValues_ChangeTrustResultCode = map[string]int32{ - "CHANGE_TRUST_SUCCESS": int32(CHANGE_TRUST_SUCCESS), - "CHANGE_TRUST_MALFORMED": int32(CHANGE_TRUST_MALFORMED), - "CHANGE_TRUST_NO_ISSUER": int32(CHANGE_TRUST_NO_ISSUER), - "CHANGE_TRUST_INVALID_LIMIT": int32(CHANGE_TRUST_INVALID_LIMIT), - "CHANGE_TRUST_LOW_RESERVE": int32(CHANGE_TRUST_LOW_RESERVE), - "CHANGE_TRUST_SELF_NOT_ALLOWED": int32(CHANGE_TRUST_SELF_NOT_ALLOWED), - "CHANGE_TRUST_TRUST_LINE_MISSING": int32(CHANGE_TRUST_TRUST_LINE_MISSING), - "CHANGE_TRUST_CANNOT_DELETE": int32(CHANGE_TRUST_CANNOT_DELETE), - "CHANGE_TRUST_NOT_AUTH_MAINTAIN_LIABILITIES": int32(CHANGE_TRUST_NOT_AUTH_MAINTAIN_LIABILITIES), +func XDR_PathPaymentStrictReceiveResult(v *PathPaymentStrictReceiveResult) *PathPaymentStrictReceiveResult { + return v } -func (ChangeTrustResultCode) XdrEnumNames() map[int32]string { - return _XdrNames_ChangeTrustResultCode +var _XdrNames_PathPaymentStrictSendResultCode = map[int32]string{ + int32(PATH_PAYMENT_STRICT_SEND_SUCCESS): "PATH_PAYMENT_STRICT_SEND_SUCCESS", + int32(PATH_PAYMENT_STRICT_SEND_MALFORMED): "PATH_PAYMENT_STRICT_SEND_MALFORMED", + int32(PATH_PAYMENT_STRICT_SEND_UNDERFUNDED): "PATH_PAYMENT_STRICT_SEND_UNDERFUNDED", + int32(PATH_PAYMENT_STRICT_SEND_SRC_NO_TRUST): "PATH_PAYMENT_STRICT_SEND_SRC_NO_TRUST", + int32(PATH_PAYMENT_STRICT_SEND_SRC_NOT_AUTHORIZED): "PATH_PAYMENT_STRICT_SEND_SRC_NOT_AUTHORIZED", + int32(PATH_PAYMENT_STRICT_SEND_NO_DESTINATION): "PATH_PAYMENT_STRICT_SEND_NO_DESTINATION", + int32(PATH_PAYMENT_STRICT_SEND_NO_TRUST): "PATH_PAYMENT_STRICT_SEND_NO_TRUST", + int32(PATH_PAYMENT_STRICT_SEND_NOT_AUTHORIZED): "PATH_PAYMENT_STRICT_SEND_NOT_AUTHORIZED", + int32(PATH_PAYMENT_STRICT_SEND_LINE_FULL): "PATH_PAYMENT_STRICT_SEND_LINE_FULL", + int32(PATH_PAYMENT_STRICT_SEND_NO_ISSUER): "PATH_PAYMENT_STRICT_SEND_NO_ISSUER", + int32(PATH_PAYMENT_STRICT_SEND_TOO_FEW_OFFERS): "PATH_PAYMENT_STRICT_SEND_TOO_FEW_OFFERS", + int32(PATH_PAYMENT_STRICT_SEND_OFFER_CROSS_SELF): "PATH_PAYMENT_STRICT_SEND_OFFER_CROSS_SELF", + int32(PATH_PAYMENT_STRICT_SEND_UNDER_DESTMIN): "PATH_PAYMENT_STRICT_SEND_UNDER_DESTMIN", } -func (v ChangeTrustResultCode) String() string { - if s, ok := _XdrNames_ChangeTrustResultCode[int32(v)]; ok { +var _XdrValues_PathPaymentStrictSendResultCode = map[string]int32{ + "PATH_PAYMENT_STRICT_SEND_SUCCESS": int32(PATH_PAYMENT_STRICT_SEND_SUCCESS), + "PATH_PAYMENT_STRICT_SEND_MALFORMED": int32(PATH_PAYMENT_STRICT_SEND_MALFORMED), + "PATH_PAYMENT_STRICT_SEND_UNDERFUNDED": int32(PATH_PAYMENT_STRICT_SEND_UNDERFUNDED), + "PATH_PAYMENT_STRICT_SEND_SRC_NO_TRUST": int32(PATH_PAYMENT_STRICT_SEND_SRC_NO_TRUST), + "PATH_PAYMENT_STRICT_SEND_SRC_NOT_AUTHORIZED": int32(PATH_PAYMENT_STRICT_SEND_SRC_NOT_AUTHORIZED), + "PATH_PAYMENT_STRICT_SEND_NO_DESTINATION": int32(PATH_PAYMENT_STRICT_SEND_NO_DESTINATION), + "PATH_PAYMENT_STRICT_SEND_NO_TRUST": int32(PATH_PAYMENT_STRICT_SEND_NO_TRUST), + "PATH_PAYMENT_STRICT_SEND_NOT_AUTHORIZED": int32(PATH_PAYMENT_STRICT_SEND_NOT_AUTHORIZED), + "PATH_PAYMENT_STRICT_SEND_LINE_FULL": int32(PATH_PAYMENT_STRICT_SEND_LINE_FULL), + "PATH_PAYMENT_STRICT_SEND_NO_ISSUER": int32(PATH_PAYMENT_STRICT_SEND_NO_ISSUER), + "PATH_PAYMENT_STRICT_SEND_TOO_FEW_OFFERS": int32(PATH_PAYMENT_STRICT_SEND_TOO_FEW_OFFERS), + "PATH_PAYMENT_STRICT_SEND_OFFER_CROSS_SELF": int32(PATH_PAYMENT_STRICT_SEND_OFFER_CROSS_SELF), + "PATH_PAYMENT_STRICT_SEND_UNDER_DESTMIN": int32(PATH_PAYMENT_STRICT_SEND_UNDER_DESTMIN), +} + +func (PathPaymentStrictSendResultCode) XdrEnumNames() map[int32]string { + return _XdrNames_PathPaymentStrictSendResultCode +} +func (v PathPaymentStrictSendResultCode) String() string { + if s, ok := _XdrNames_PathPaymentStrictSendResultCode[int32(v)]; ok { return s } - return fmt.Sprintf("ChangeTrustResultCode#%d", v) + return fmt.Sprintf("PathPaymentStrictSendResultCode#%d", v) } -func (v *ChangeTrustResultCode) Scan(ss fmt.ScanState, _ rune) error { +func (v *PathPaymentStrictSendResultCode) Scan(ss fmt.ScanState, _ rune) error { if tok, err := ss.Token(true, XdrSymChar); err != nil { return err } else { stok := string(tok) - if val, ok := _XdrValues_ChangeTrustResultCode[stok]; ok { - *v = ChangeTrustResultCode(val) + if val, ok := _XdrValues_PathPaymentStrictSendResultCode[stok]; ok { + *v = PathPaymentStrictSendResultCode(val) return nil - } else if stok == "ChangeTrustResultCode" { + } else if stok == "PathPaymentStrictSendResultCode" { if n, err := fmt.Fscanf(ss, "#%d", (*int32)(v)); n == 1 && err == nil { return nil } } - return XdrError(fmt.Sprintf("%s is not a valid ChangeTrustResultCode.", stok)) + return XdrError(fmt.Sprintf("%s is not a valid PathPaymentStrictSendResultCode.", stok)) } } -func (v ChangeTrustResultCode) GetU32() uint32 { return uint32(v) } -func (v *ChangeTrustResultCode) SetU32(n uint32) { *v = ChangeTrustResultCode(n) } -func (v *ChangeTrustResultCode) XdrPointer() interface{} { return v } -func (ChangeTrustResultCode) XdrTypeName() string { return "ChangeTrustResultCode" } -func (v ChangeTrustResultCode) XdrValue() interface{} { return v } -func (v *ChangeTrustResultCode) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v PathPaymentStrictSendResultCode) GetU32() uint32 { return uint32(v) } +func (v *PathPaymentStrictSendResultCode) SetU32(n uint32) { *v = PathPaymentStrictSendResultCode(n) } +func (v *PathPaymentStrictSendResultCode) XdrPointer() interface{} { return v } +func (PathPaymentStrictSendResultCode) XdrTypeName() string { return "PathPaymentStrictSendResultCode" } +func (v PathPaymentStrictSendResultCode) XdrValue() interface{} { return v } +func (v *PathPaymentStrictSendResultCode) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -type XdrType_ChangeTrustResultCode = *ChangeTrustResultCode +type XdrType_PathPaymentStrictSendResultCode = *PathPaymentStrictSendResultCode -func XDR_ChangeTrustResultCode(v *ChangeTrustResultCode) *ChangeTrustResultCode { return v } +func XDR_PathPaymentStrictSendResultCode(v *PathPaymentStrictSendResultCode) *PathPaymentStrictSendResultCode { + return v +} -var _XdrComments_ChangeTrustResultCode = map[int32]string{ - int32(CHANGE_TRUST_SUCCESS): "codes considered as \"success\" for the operation", - int32(CHANGE_TRUST_MALFORMED): "bad input", - int32(CHANGE_TRUST_NO_ISSUER): "could not find issuer", - int32(CHANGE_TRUST_INVALID_LIMIT): "cannot drop limit below balance", - int32(CHANGE_TRUST_LOW_RESERVE): "not enough funds to create a new trust line,", - int32(CHANGE_TRUST_SELF_NOT_ALLOWED): "trusting self is not allowed", - int32(CHANGE_TRUST_TRUST_LINE_MISSING): "Asset trustline is missing for pool", - int32(CHANGE_TRUST_CANNOT_DELETE): "Asset trustline is still referenced in a pool", - int32(CHANGE_TRUST_NOT_AUTH_MAINTAIN_LIABILITIES): "Asset trustline is deauthorized", +var _XdrComments_PathPaymentStrictSendResultCode = map[int32]string{ + int32(PATH_PAYMENT_STRICT_SEND_SUCCESS): "success", + int32(PATH_PAYMENT_STRICT_SEND_MALFORMED): "bad input", + int32(PATH_PAYMENT_STRICT_SEND_UNDERFUNDED): "not enough funds in source account", + int32(PATH_PAYMENT_STRICT_SEND_SRC_NO_TRUST): "no trust line on source account", + int32(PATH_PAYMENT_STRICT_SEND_SRC_NOT_AUTHORIZED): "source not authorized to transfer", + int32(PATH_PAYMENT_STRICT_SEND_NO_DESTINATION): "destination account does not exist", + int32(PATH_PAYMENT_STRICT_SEND_NO_TRUST): "dest missing a trust line for asset", + int32(PATH_PAYMENT_STRICT_SEND_NOT_AUTHORIZED): "dest not authorized to hold asset", + int32(PATH_PAYMENT_STRICT_SEND_LINE_FULL): "dest would go above their limit", + int32(PATH_PAYMENT_STRICT_SEND_NO_ISSUER): "missing issuer on one asset", + int32(PATH_PAYMENT_STRICT_SEND_TOO_FEW_OFFERS): "not enough offers to satisfy path", + int32(PATH_PAYMENT_STRICT_SEND_OFFER_CROSS_SELF): "would cross one of its own offers", + int32(PATH_PAYMENT_STRICT_SEND_UNDER_DESTMIN): "could not satisfy destMin", } -func (e ChangeTrustResultCode) XdrEnumComments() map[int32]string { - return _XdrComments_ChangeTrustResultCode +func (e PathPaymentStrictSendResultCode) XdrEnumComments() map[int32]string { + return _XdrComments_PathPaymentStrictSendResultCode } -var _XdrTags_ChangeTrustResult = map[int32]bool{ - XdrToI32(CHANGE_TRUST_SUCCESS): true, - XdrToI32(CHANGE_TRUST_MALFORMED): true, - XdrToI32(CHANGE_TRUST_NO_ISSUER): true, - XdrToI32(CHANGE_TRUST_INVALID_LIMIT): true, - XdrToI32(CHANGE_TRUST_LOW_RESERVE): true, - XdrToI32(CHANGE_TRUST_SELF_NOT_ALLOWED): true, - XdrToI32(CHANGE_TRUST_TRUST_LINE_MISSING): true, - XdrToI32(CHANGE_TRUST_CANNOT_DELETE): true, - XdrToI32(CHANGE_TRUST_NOT_AUTH_MAINTAIN_LIABILITIES): true, +type XdrType_XdrAnon_PathPaymentStrictSendResult_Success = *XdrAnon_PathPaymentStrictSendResult_Success + +func (v *XdrAnon_PathPaymentStrictSendResult_Success) XdrPointer() interface{} { return v } +func (XdrAnon_PathPaymentStrictSendResult_Success) XdrTypeName() string { + return "XdrAnon_PathPaymentStrictSendResult_Success" +} +func (v XdrAnon_PathPaymentStrictSendResult_Success) XdrValue() interface{} { return v } +func (v *XdrAnon_PathPaymentStrictSendResult_Success) XdrMarshal(x XDR, name string) { + x.Marshal(name, v) +} +func (v *XdrAnon_PathPaymentStrictSendResult_Success) XdrRecurse(x XDR, name string) { + if name != "" { + name = x.Sprintf("%s.", name) + } + x.Marshal(x.Sprintf("%soffers", name), (*_XdrVec_unbounded_ClaimAtom)(&v.Offers)) + x.Marshal(x.Sprintf("%slast", name), XDR_SimplePaymentResult(&v.Last)) +} +func XDR_XdrAnon_PathPaymentStrictSendResult_Success(v *XdrAnon_PathPaymentStrictSendResult_Success) *XdrAnon_PathPaymentStrictSendResult_Success { + return v } -func (_ ChangeTrustResult) XdrValidTags() map[int32]bool { - return _XdrTags_ChangeTrustResult +var _XdrTags_PathPaymentStrictSendResult = map[int32]bool{ + XdrToI32(PATH_PAYMENT_STRICT_SEND_SUCCESS): true, + XdrToI32(PATH_PAYMENT_STRICT_SEND_MALFORMED): true, + XdrToI32(PATH_PAYMENT_STRICT_SEND_UNDERFUNDED): true, + XdrToI32(PATH_PAYMENT_STRICT_SEND_SRC_NO_TRUST): true, + XdrToI32(PATH_PAYMENT_STRICT_SEND_SRC_NOT_AUTHORIZED): true, + XdrToI32(PATH_PAYMENT_STRICT_SEND_NO_DESTINATION): true, + XdrToI32(PATH_PAYMENT_STRICT_SEND_NO_TRUST): true, + XdrToI32(PATH_PAYMENT_STRICT_SEND_NOT_AUTHORIZED): true, + XdrToI32(PATH_PAYMENT_STRICT_SEND_LINE_FULL): true, + XdrToI32(PATH_PAYMENT_STRICT_SEND_NO_ISSUER): true, + XdrToI32(PATH_PAYMENT_STRICT_SEND_TOO_FEW_OFFERS): true, + XdrToI32(PATH_PAYMENT_STRICT_SEND_OFFER_CROSS_SELF): true, + XdrToI32(PATH_PAYMENT_STRICT_SEND_UNDER_DESTMIN): true, } -func (u ChangeTrustResult) XdrValid() bool { + +func (_ PathPaymentStrictSendResult) XdrValidTags() map[int32]bool { + return _XdrTags_PathPaymentStrictSendResult +} +func (u *PathPaymentStrictSendResult) Success() *XdrAnon_PathPaymentStrictSendResult_Success { switch u.Code { - case CHANGE_TRUST_SUCCESS, CHANGE_TRUST_MALFORMED, CHANGE_TRUST_NO_ISSUER, CHANGE_TRUST_INVALID_LIMIT, CHANGE_TRUST_LOW_RESERVE, CHANGE_TRUST_SELF_NOT_ALLOWED, CHANGE_TRUST_TRUST_LINE_MISSING, CHANGE_TRUST_CANNOT_DELETE, CHANGE_TRUST_NOT_AUTH_MAINTAIN_LIABILITIES: + case PATH_PAYMENT_STRICT_SEND_SUCCESS: + if v, ok := u._u.(*XdrAnon_PathPaymentStrictSendResult_Success); ok { + return v + } else { + var zero XdrAnon_PathPaymentStrictSendResult_Success + u._u = &zero + return &zero + } + default: + XdrPanic("PathPaymentStrictSendResult.Success accessed when Code == %v", u.Code) + return nil + } +} + +// the asset that caused the error +func (u *PathPaymentStrictSendResult) NoIssuer() *Asset { + switch u.Code { + case PATH_PAYMENT_STRICT_SEND_NO_ISSUER: + if v, ok := u._u.(*Asset); ok { + return v + } else { + var zero Asset + u._u = &zero + return &zero + } + default: + XdrPanic("PathPaymentStrictSendResult.NoIssuer accessed when Code == %v", u.Code) + return nil + } +} +func (u PathPaymentStrictSendResult) XdrValid() bool { + switch u.Code { + case PATH_PAYMENT_STRICT_SEND_SUCCESS, PATH_PAYMENT_STRICT_SEND_MALFORMED, PATH_PAYMENT_STRICT_SEND_UNDERFUNDED, PATH_PAYMENT_STRICT_SEND_SRC_NO_TRUST, PATH_PAYMENT_STRICT_SEND_SRC_NOT_AUTHORIZED, PATH_PAYMENT_STRICT_SEND_NO_DESTINATION, PATH_PAYMENT_STRICT_SEND_NO_TRUST, PATH_PAYMENT_STRICT_SEND_NOT_AUTHORIZED, PATH_PAYMENT_STRICT_SEND_LINE_FULL, PATH_PAYMENT_STRICT_SEND_NO_ISSUER, PATH_PAYMENT_STRICT_SEND_TOO_FEW_OFFERS, PATH_PAYMENT_STRICT_SEND_OFFER_CROSS_SELF, PATH_PAYMENT_STRICT_SEND_UNDER_DESTMIN: return true } return false } -func (u *ChangeTrustResult) XdrUnionTag() XdrNum32 { - return XDR_ChangeTrustResultCode(&u.Code) +func (u *PathPaymentStrictSendResult) XdrUnionTag() XdrNum32 { + return XDR_PathPaymentStrictSendResultCode(&u.Code) } -func (u *ChangeTrustResult) XdrUnionTagName() string { +func (u *PathPaymentStrictSendResult) XdrUnionTagName() string { return "Code" } -func (u *ChangeTrustResult) XdrUnionBody() XdrType { +func (u *PathPaymentStrictSendResult) XdrUnionBody() XdrType { switch u.Code { - case CHANGE_TRUST_SUCCESS: + case PATH_PAYMENT_STRICT_SEND_SUCCESS: + return XDR_XdrAnon_PathPaymentStrictSendResult_Success(u.Success()) + case PATH_PAYMENT_STRICT_SEND_MALFORMED, PATH_PAYMENT_STRICT_SEND_UNDERFUNDED, PATH_PAYMENT_STRICT_SEND_SRC_NO_TRUST, PATH_PAYMENT_STRICT_SEND_SRC_NOT_AUTHORIZED, PATH_PAYMENT_STRICT_SEND_NO_DESTINATION, PATH_PAYMENT_STRICT_SEND_NO_TRUST, PATH_PAYMENT_STRICT_SEND_NOT_AUTHORIZED, PATH_PAYMENT_STRICT_SEND_LINE_FULL: return nil - case CHANGE_TRUST_MALFORMED, CHANGE_TRUST_NO_ISSUER, CHANGE_TRUST_INVALID_LIMIT, CHANGE_TRUST_LOW_RESERVE, CHANGE_TRUST_SELF_NOT_ALLOWED, CHANGE_TRUST_TRUST_LINE_MISSING, CHANGE_TRUST_CANNOT_DELETE, CHANGE_TRUST_NOT_AUTH_MAINTAIN_LIABILITIES: + case PATH_PAYMENT_STRICT_SEND_NO_ISSUER: + return XDR_Asset(u.NoIssuer()) + case PATH_PAYMENT_STRICT_SEND_TOO_FEW_OFFERS, PATH_PAYMENT_STRICT_SEND_OFFER_CROSS_SELF, PATH_PAYMENT_STRICT_SEND_UNDER_DESTMIN: return nil } return nil } -func (u *ChangeTrustResult) XdrUnionBodyName() string { +func (u *PathPaymentStrictSendResult) XdrUnionBodyName() string { switch u.Code { - case CHANGE_TRUST_SUCCESS: + case PATH_PAYMENT_STRICT_SEND_SUCCESS: + return "Success" + case PATH_PAYMENT_STRICT_SEND_MALFORMED, PATH_PAYMENT_STRICT_SEND_UNDERFUNDED, PATH_PAYMENT_STRICT_SEND_SRC_NO_TRUST, PATH_PAYMENT_STRICT_SEND_SRC_NOT_AUTHORIZED, PATH_PAYMENT_STRICT_SEND_NO_DESTINATION, PATH_PAYMENT_STRICT_SEND_NO_TRUST, PATH_PAYMENT_STRICT_SEND_NOT_AUTHORIZED, PATH_PAYMENT_STRICT_SEND_LINE_FULL: return "" - case CHANGE_TRUST_MALFORMED, CHANGE_TRUST_NO_ISSUER, CHANGE_TRUST_INVALID_LIMIT, CHANGE_TRUST_LOW_RESERVE, CHANGE_TRUST_SELF_NOT_ALLOWED, CHANGE_TRUST_TRUST_LINE_MISSING, CHANGE_TRUST_CANNOT_DELETE, CHANGE_TRUST_NOT_AUTH_MAINTAIN_LIABILITIES: + case PATH_PAYMENT_STRICT_SEND_NO_ISSUER: + return "NoIssuer" + case PATH_PAYMENT_STRICT_SEND_TOO_FEW_OFFERS, PATH_PAYMENT_STRICT_SEND_OFFER_CROSS_SELF, PATH_PAYMENT_STRICT_SEND_UNDER_DESTMIN: return "" } return "" } -type XdrType_ChangeTrustResult = *ChangeTrustResult +type XdrType_PathPaymentStrictSendResult = *PathPaymentStrictSendResult -func (v *ChangeTrustResult) XdrPointer() interface{} { return v } -func (ChangeTrustResult) XdrTypeName() string { return "ChangeTrustResult" } -func (v ChangeTrustResult) XdrValue() interface{} { return v } -func (v *ChangeTrustResult) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -func (u *ChangeTrustResult) XdrRecurse(x XDR, name string) { +func (v *PathPaymentStrictSendResult) XdrPointer() interface{} { return v } +func (PathPaymentStrictSendResult) XdrTypeName() string { return "PathPaymentStrictSendResult" } +func (v PathPaymentStrictSendResult) XdrValue() interface{} { return v } +func (v *PathPaymentStrictSendResult) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (u *PathPaymentStrictSendResult) XdrRecurse(x XDR, name string) { if name != "" { name = x.Sprintf("%s.", name) } - XDR_ChangeTrustResultCode(&u.Code).XdrMarshal(x, x.Sprintf("%scode", name)) + XDR_PathPaymentStrictSendResultCode(&u.Code).XdrMarshal(x, x.Sprintf("%scode", name)) switch u.Code { - case CHANGE_TRUST_SUCCESS: + case PATH_PAYMENT_STRICT_SEND_SUCCESS: + x.Marshal(x.Sprintf("%ssuccess", name), XDR_XdrAnon_PathPaymentStrictSendResult_Success(u.Success())) return - case CHANGE_TRUST_MALFORMED, CHANGE_TRUST_NO_ISSUER, CHANGE_TRUST_INVALID_LIMIT, CHANGE_TRUST_LOW_RESERVE, CHANGE_TRUST_SELF_NOT_ALLOWED, CHANGE_TRUST_TRUST_LINE_MISSING, CHANGE_TRUST_CANNOT_DELETE, CHANGE_TRUST_NOT_AUTH_MAINTAIN_LIABILITIES: + case PATH_PAYMENT_STRICT_SEND_MALFORMED, PATH_PAYMENT_STRICT_SEND_UNDERFUNDED, PATH_PAYMENT_STRICT_SEND_SRC_NO_TRUST, PATH_PAYMENT_STRICT_SEND_SRC_NOT_AUTHORIZED, PATH_PAYMENT_STRICT_SEND_NO_DESTINATION, PATH_PAYMENT_STRICT_SEND_NO_TRUST, PATH_PAYMENT_STRICT_SEND_NOT_AUTHORIZED, PATH_PAYMENT_STRICT_SEND_LINE_FULL: + return + case PATH_PAYMENT_STRICT_SEND_NO_ISSUER: + x.Marshal(x.Sprintf("%snoIssuer", name), XDR_Asset(u.NoIssuer())) + return + case PATH_PAYMENT_STRICT_SEND_TOO_FEW_OFFERS, PATH_PAYMENT_STRICT_SEND_OFFER_CROSS_SELF, PATH_PAYMENT_STRICT_SEND_UNDER_DESTMIN: return } - XdrPanic("invalid Code (%v) in ChangeTrustResult", u.Code) -} -func XDR_ChangeTrustResult(v *ChangeTrustResult) *ChangeTrustResult { return v } - -var _XdrNames_AllowTrustResultCode = map[int32]string{ - int32(ALLOW_TRUST_SUCCESS): "ALLOW_TRUST_SUCCESS", - int32(ALLOW_TRUST_MALFORMED): "ALLOW_TRUST_MALFORMED", - int32(ALLOW_TRUST_NO_TRUST_LINE): "ALLOW_TRUST_NO_TRUST_LINE", - int32(ALLOW_TRUST_TRUST_NOT_REQUIRED): "ALLOW_TRUST_TRUST_NOT_REQUIRED", - int32(ALLOW_TRUST_CANT_REVOKE): "ALLOW_TRUST_CANT_REVOKE", - int32(ALLOW_TRUST_SELF_NOT_ALLOWED): "ALLOW_TRUST_SELF_NOT_ALLOWED", - int32(ALLOW_TRUST_LOW_RESERVE): "ALLOW_TRUST_LOW_RESERVE", + XdrPanic("invalid Code (%v) in PathPaymentStrictSendResult", u.Code) } -var _XdrValues_AllowTrustResultCode = map[string]int32{ - "ALLOW_TRUST_SUCCESS": int32(ALLOW_TRUST_SUCCESS), - "ALLOW_TRUST_MALFORMED": int32(ALLOW_TRUST_MALFORMED), - "ALLOW_TRUST_NO_TRUST_LINE": int32(ALLOW_TRUST_NO_TRUST_LINE), - "ALLOW_TRUST_TRUST_NOT_REQUIRED": int32(ALLOW_TRUST_TRUST_NOT_REQUIRED), - "ALLOW_TRUST_CANT_REVOKE": int32(ALLOW_TRUST_CANT_REVOKE), - "ALLOW_TRUST_SELF_NOT_ALLOWED": int32(ALLOW_TRUST_SELF_NOT_ALLOWED), - "ALLOW_TRUST_LOW_RESERVE": int32(ALLOW_TRUST_LOW_RESERVE), +func XDR_PathPaymentStrictSendResult(v *PathPaymentStrictSendResult) *PathPaymentStrictSendResult { + return v } -func (AllowTrustResultCode) XdrEnumNames() map[int32]string { - return _XdrNames_AllowTrustResultCode +var _XdrNames_ManageSellOfferResultCode = map[int32]string{ + int32(MANAGE_SELL_OFFER_SUCCESS): "MANAGE_SELL_OFFER_SUCCESS", + int32(MANAGE_SELL_OFFER_MALFORMED): "MANAGE_SELL_OFFER_MALFORMED", + int32(MANAGE_SELL_OFFER_SELL_NO_TRUST): "MANAGE_SELL_OFFER_SELL_NO_TRUST", + int32(MANAGE_SELL_OFFER_BUY_NO_TRUST): "MANAGE_SELL_OFFER_BUY_NO_TRUST", + int32(MANAGE_SELL_OFFER_SELL_NOT_AUTHORIZED): "MANAGE_SELL_OFFER_SELL_NOT_AUTHORIZED", + int32(MANAGE_SELL_OFFER_BUY_NOT_AUTHORIZED): "MANAGE_SELL_OFFER_BUY_NOT_AUTHORIZED", + int32(MANAGE_SELL_OFFER_LINE_FULL): "MANAGE_SELL_OFFER_LINE_FULL", + int32(MANAGE_SELL_OFFER_UNDERFUNDED): "MANAGE_SELL_OFFER_UNDERFUNDED", + int32(MANAGE_SELL_OFFER_CROSS_SELF): "MANAGE_SELL_OFFER_CROSS_SELF", + int32(MANAGE_SELL_OFFER_SELL_NO_ISSUER): "MANAGE_SELL_OFFER_SELL_NO_ISSUER", + int32(MANAGE_SELL_OFFER_BUY_NO_ISSUER): "MANAGE_SELL_OFFER_BUY_NO_ISSUER", + int32(MANAGE_SELL_OFFER_NOT_FOUND): "MANAGE_SELL_OFFER_NOT_FOUND", + int32(MANAGE_SELL_OFFER_LOW_RESERVE): "MANAGE_SELL_OFFER_LOW_RESERVE", } -func (v AllowTrustResultCode) String() string { - if s, ok := _XdrNames_AllowTrustResultCode[int32(v)]; ok { +var _XdrValues_ManageSellOfferResultCode = map[string]int32{ + "MANAGE_SELL_OFFER_SUCCESS": int32(MANAGE_SELL_OFFER_SUCCESS), + "MANAGE_SELL_OFFER_MALFORMED": int32(MANAGE_SELL_OFFER_MALFORMED), + "MANAGE_SELL_OFFER_SELL_NO_TRUST": int32(MANAGE_SELL_OFFER_SELL_NO_TRUST), + "MANAGE_SELL_OFFER_BUY_NO_TRUST": int32(MANAGE_SELL_OFFER_BUY_NO_TRUST), + "MANAGE_SELL_OFFER_SELL_NOT_AUTHORIZED": int32(MANAGE_SELL_OFFER_SELL_NOT_AUTHORIZED), + "MANAGE_SELL_OFFER_BUY_NOT_AUTHORIZED": int32(MANAGE_SELL_OFFER_BUY_NOT_AUTHORIZED), + "MANAGE_SELL_OFFER_LINE_FULL": int32(MANAGE_SELL_OFFER_LINE_FULL), + "MANAGE_SELL_OFFER_UNDERFUNDED": int32(MANAGE_SELL_OFFER_UNDERFUNDED), + "MANAGE_SELL_OFFER_CROSS_SELF": int32(MANAGE_SELL_OFFER_CROSS_SELF), + "MANAGE_SELL_OFFER_SELL_NO_ISSUER": int32(MANAGE_SELL_OFFER_SELL_NO_ISSUER), + "MANAGE_SELL_OFFER_BUY_NO_ISSUER": int32(MANAGE_SELL_OFFER_BUY_NO_ISSUER), + "MANAGE_SELL_OFFER_NOT_FOUND": int32(MANAGE_SELL_OFFER_NOT_FOUND), + "MANAGE_SELL_OFFER_LOW_RESERVE": int32(MANAGE_SELL_OFFER_LOW_RESERVE), +} + +func (ManageSellOfferResultCode) XdrEnumNames() map[int32]string { + return _XdrNames_ManageSellOfferResultCode +} +func (v ManageSellOfferResultCode) String() string { + if s, ok := _XdrNames_ManageSellOfferResultCode[int32(v)]; ok { return s } - return fmt.Sprintf("AllowTrustResultCode#%d", v) + return fmt.Sprintf("ManageSellOfferResultCode#%d", v) } -func (v *AllowTrustResultCode) Scan(ss fmt.ScanState, _ rune) error { +func (v *ManageSellOfferResultCode) Scan(ss fmt.ScanState, _ rune) error { if tok, err := ss.Token(true, XdrSymChar); err != nil { return err } else { stok := string(tok) - if val, ok := _XdrValues_AllowTrustResultCode[stok]; ok { - *v = AllowTrustResultCode(val) + if val, ok := _XdrValues_ManageSellOfferResultCode[stok]; ok { + *v = ManageSellOfferResultCode(val) return nil - } else if stok == "AllowTrustResultCode" { + } else if stok == "ManageSellOfferResultCode" { if n, err := fmt.Fscanf(ss, "#%d", (*int32)(v)); n == 1 && err == nil { return nil } } - return XdrError(fmt.Sprintf("%s is not a valid AllowTrustResultCode.", stok)) + return XdrError(fmt.Sprintf("%s is not a valid ManageSellOfferResultCode.", stok)) } } -func (v AllowTrustResultCode) GetU32() uint32 { return uint32(v) } -func (v *AllowTrustResultCode) SetU32(n uint32) { *v = AllowTrustResultCode(n) } -func (v *AllowTrustResultCode) XdrPointer() interface{} { return v } -func (AllowTrustResultCode) XdrTypeName() string { return "AllowTrustResultCode" } -func (v AllowTrustResultCode) XdrValue() interface{} { return v } -func (v *AllowTrustResultCode) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v ManageSellOfferResultCode) GetU32() uint32 { return uint32(v) } +func (v *ManageSellOfferResultCode) SetU32(n uint32) { *v = ManageSellOfferResultCode(n) } +func (v *ManageSellOfferResultCode) XdrPointer() interface{} { return v } +func (ManageSellOfferResultCode) XdrTypeName() string { return "ManageSellOfferResultCode" } +func (v ManageSellOfferResultCode) XdrValue() interface{} { return v } +func (v *ManageSellOfferResultCode) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -type XdrType_AllowTrustResultCode = *AllowTrustResultCode +type XdrType_ManageSellOfferResultCode = *ManageSellOfferResultCode -func XDR_AllowTrustResultCode(v *AllowTrustResultCode) *AllowTrustResultCode { return v } +func XDR_ManageSellOfferResultCode(v *ManageSellOfferResultCode) *ManageSellOfferResultCode { return v } -var _XdrComments_AllowTrustResultCode = map[int32]string{ - int32(ALLOW_TRUST_SUCCESS): "codes considered as \"success\" for the operation", - int32(ALLOW_TRUST_MALFORMED): "asset is not ASSET_TYPE_ALPHANUM", - int32(ALLOW_TRUST_NO_TRUST_LINE): "trustor does not have a trustline", - int32(ALLOW_TRUST_TRUST_NOT_REQUIRED): "source account does not require trust", - int32(ALLOW_TRUST_CANT_REVOKE): "source account can't revoke trust,", - int32(ALLOW_TRUST_SELF_NOT_ALLOWED): "trusting self is not allowed", - int32(ALLOW_TRUST_LOW_RESERVE): "claimable balances can't be created", +var _XdrComments_ManageSellOfferResultCode = map[int32]string{ + int32(MANAGE_SELL_OFFER_SUCCESS): "codes considered as \"success\" for the operation", + int32(MANAGE_SELL_OFFER_MALFORMED): "generated offer would be invalid", + int32(MANAGE_SELL_OFFER_SELL_NO_TRUST): "no trust line for what we're selling", + int32(MANAGE_SELL_OFFER_BUY_NO_TRUST): "no trust line for what we're buying", + int32(MANAGE_SELL_OFFER_SELL_NOT_AUTHORIZED): "not authorized to sell", + int32(MANAGE_SELL_OFFER_BUY_NOT_AUTHORIZED): "not authorized to buy", + int32(MANAGE_SELL_OFFER_LINE_FULL): "can't receive more of what it's buying", + int32(MANAGE_SELL_OFFER_UNDERFUNDED): "doesn't hold what it's trying to sell", + int32(MANAGE_SELL_OFFER_CROSS_SELF): "would cross an offer from the same user", + int32(MANAGE_SELL_OFFER_SELL_NO_ISSUER): "no issuer for what we're selling", + int32(MANAGE_SELL_OFFER_BUY_NO_ISSUER): "no issuer for what we're buying", + int32(MANAGE_SELL_OFFER_NOT_FOUND): "offerID does not match an existing offer", + int32(MANAGE_SELL_OFFER_LOW_RESERVE): "not enough funds to create a new Offer", } -func (e AllowTrustResultCode) XdrEnumComments() map[int32]string { - return _XdrComments_AllowTrustResultCode +func (e ManageSellOfferResultCode) XdrEnumComments() map[int32]string { + return _XdrComments_ManageSellOfferResultCode } -var _XdrTags_AllowTrustResult = map[int32]bool{ - XdrToI32(ALLOW_TRUST_SUCCESS): true, - XdrToI32(ALLOW_TRUST_MALFORMED): true, - XdrToI32(ALLOW_TRUST_NO_TRUST_LINE): true, - XdrToI32(ALLOW_TRUST_TRUST_NOT_REQUIRED): true, - XdrToI32(ALLOW_TRUST_CANT_REVOKE): true, - XdrToI32(ALLOW_TRUST_SELF_NOT_ALLOWED): true, - XdrToI32(ALLOW_TRUST_LOW_RESERVE): true, +var _XdrNames_ManageOfferEffect = map[int32]string{ + int32(MANAGE_OFFER_CREATED): "MANAGE_OFFER_CREATED", + int32(MANAGE_OFFER_UPDATED): "MANAGE_OFFER_UPDATED", + int32(MANAGE_OFFER_DELETED): "MANAGE_OFFER_DELETED", +} +var _XdrValues_ManageOfferEffect = map[string]int32{ + "MANAGE_OFFER_CREATED": int32(MANAGE_OFFER_CREATED), + "MANAGE_OFFER_UPDATED": int32(MANAGE_OFFER_UPDATED), + "MANAGE_OFFER_DELETED": int32(MANAGE_OFFER_DELETED), } -func (_ AllowTrustResult) XdrValidTags() map[int32]bool { - return _XdrTags_AllowTrustResult +func (ManageOfferEffect) XdrEnumNames() map[int32]string { + return _XdrNames_ManageOfferEffect } -func (u AllowTrustResult) XdrValid() bool { - switch u.Code { - case ALLOW_TRUST_SUCCESS, ALLOW_TRUST_MALFORMED, ALLOW_TRUST_NO_TRUST_LINE, ALLOW_TRUST_TRUST_NOT_REQUIRED, ALLOW_TRUST_CANT_REVOKE, ALLOW_TRUST_SELF_NOT_ALLOWED, ALLOW_TRUST_LOW_RESERVE: +func (v ManageOfferEffect) String() string { + if s, ok := _XdrNames_ManageOfferEffect[int32(v)]; ok { + return s + } + return fmt.Sprintf("ManageOfferEffect#%d", v) +} +func (v *ManageOfferEffect) Scan(ss fmt.ScanState, _ rune) error { + if tok, err := ss.Token(true, XdrSymChar); err != nil { + return err + } else { + stok := string(tok) + if val, ok := _XdrValues_ManageOfferEffect[stok]; ok { + *v = ManageOfferEffect(val) + return nil + } else if stok == "ManageOfferEffect" { + if n, err := fmt.Fscanf(ss, "#%d", (*int32)(v)); n == 1 && err == nil { + return nil + } + } + return XdrError(fmt.Sprintf("%s is not a valid ManageOfferEffect.", stok)) + } +} +func (v ManageOfferEffect) GetU32() uint32 { return uint32(v) } +func (v *ManageOfferEffect) SetU32(n uint32) { *v = ManageOfferEffect(n) } +func (v *ManageOfferEffect) XdrPointer() interface{} { return v } +func (ManageOfferEffect) XdrTypeName() string { return "ManageOfferEffect" } +func (v ManageOfferEffect) XdrValue() interface{} { return v } +func (v *ManageOfferEffect) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } + +type XdrType_ManageOfferEffect = *ManageOfferEffect + +func XDR_ManageOfferEffect(v *ManageOfferEffect) *ManageOfferEffect { return v } + +var _XdrTags_XdrAnon_ManageOfferSuccessResult_Offer = map[int32]bool{ + XdrToI32(MANAGE_OFFER_CREATED): true, + XdrToI32(MANAGE_OFFER_UPDATED): true, + XdrToI32(MANAGE_OFFER_DELETED): true, +} + +func (_ XdrAnon_ManageOfferSuccessResult_Offer) XdrValidTags() map[int32]bool { + return _XdrTags_XdrAnon_ManageOfferSuccessResult_Offer +} +func (u *XdrAnon_ManageOfferSuccessResult_Offer) Offer() *OfferEntry { + switch u.Effect { + case MANAGE_OFFER_CREATED, MANAGE_OFFER_UPDATED: + if v, ok := u._u.(*OfferEntry); ok { + return v + } else { + var zero OfferEntry + u._u = &zero + return &zero + } + default: + XdrPanic("XdrAnon_ManageOfferSuccessResult_Offer.Offer accessed when Effect == %v", u.Effect) + return nil + } +} +func (u XdrAnon_ManageOfferSuccessResult_Offer) XdrValid() bool { + switch u.Effect { + case MANAGE_OFFER_CREATED, MANAGE_OFFER_UPDATED, MANAGE_OFFER_DELETED: return true } return false } -func (u *AllowTrustResult) XdrUnionTag() XdrNum32 { - return XDR_AllowTrustResultCode(&u.Code) +func (u *XdrAnon_ManageOfferSuccessResult_Offer) XdrUnionTag() XdrNum32 { + return XDR_ManageOfferEffect(&u.Effect) } -func (u *AllowTrustResult) XdrUnionTagName() string { - return "Code" +func (u *XdrAnon_ManageOfferSuccessResult_Offer) XdrUnionTagName() string { + return "Effect" } -func (u *AllowTrustResult) XdrUnionBody() XdrType { - switch u.Code { - case ALLOW_TRUST_SUCCESS: - return nil - case ALLOW_TRUST_MALFORMED, ALLOW_TRUST_NO_TRUST_LINE, ALLOW_TRUST_TRUST_NOT_REQUIRED, ALLOW_TRUST_CANT_REVOKE, ALLOW_TRUST_SELF_NOT_ALLOWED, ALLOW_TRUST_LOW_RESERVE: +func (u *XdrAnon_ManageOfferSuccessResult_Offer) XdrUnionBody() XdrType { + switch u.Effect { + case MANAGE_OFFER_CREATED, MANAGE_OFFER_UPDATED: + return XDR_OfferEntry(u.Offer()) + case MANAGE_OFFER_DELETED: return nil } return nil } -func (u *AllowTrustResult) XdrUnionBodyName() string { - switch u.Code { - case ALLOW_TRUST_SUCCESS: - return "" - case ALLOW_TRUST_MALFORMED, ALLOW_TRUST_NO_TRUST_LINE, ALLOW_TRUST_TRUST_NOT_REQUIRED, ALLOW_TRUST_CANT_REVOKE, ALLOW_TRUST_SELF_NOT_ALLOWED, ALLOW_TRUST_LOW_RESERVE: +func (u *XdrAnon_ManageOfferSuccessResult_Offer) XdrUnionBodyName() string { + switch u.Effect { + case MANAGE_OFFER_CREATED, MANAGE_OFFER_UPDATED: + return "Offer" + case MANAGE_OFFER_DELETED: return "" } return "" } -type XdrType_AllowTrustResult = *AllowTrustResult +type XdrType_XdrAnon_ManageOfferSuccessResult_Offer = *XdrAnon_ManageOfferSuccessResult_Offer -func (v *AllowTrustResult) XdrPointer() interface{} { return v } -func (AllowTrustResult) XdrTypeName() string { return "AllowTrustResult" } -func (v AllowTrustResult) XdrValue() interface{} { return v } -func (v *AllowTrustResult) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -func (u *AllowTrustResult) XdrRecurse(x XDR, name string) { +func (v *XdrAnon_ManageOfferSuccessResult_Offer) XdrPointer() interface{} { return v } +func (XdrAnon_ManageOfferSuccessResult_Offer) XdrTypeName() string { + return "XdrAnon_ManageOfferSuccessResult_Offer" +} +func (v XdrAnon_ManageOfferSuccessResult_Offer) XdrValue() interface{} { return v } +func (v *XdrAnon_ManageOfferSuccessResult_Offer) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (u *XdrAnon_ManageOfferSuccessResult_Offer) XdrRecurse(x XDR, name string) { if name != "" { name = x.Sprintf("%s.", name) } - XDR_AllowTrustResultCode(&u.Code).XdrMarshal(x, x.Sprintf("%scode", name)) - switch u.Code { - case ALLOW_TRUST_SUCCESS: + XDR_ManageOfferEffect(&u.Effect).XdrMarshal(x, x.Sprintf("%seffect", name)) + switch u.Effect { + case MANAGE_OFFER_CREATED, MANAGE_OFFER_UPDATED: + x.Marshal(x.Sprintf("%soffer", name), XDR_OfferEntry(u.Offer())) return - case ALLOW_TRUST_MALFORMED, ALLOW_TRUST_NO_TRUST_LINE, ALLOW_TRUST_TRUST_NOT_REQUIRED, ALLOW_TRUST_CANT_REVOKE, ALLOW_TRUST_SELF_NOT_ALLOWED, ALLOW_TRUST_LOW_RESERVE: + case MANAGE_OFFER_DELETED: return } - XdrPanic("invalid Code (%v) in AllowTrustResult", u.Code) -} -func XDR_AllowTrustResult(v *AllowTrustResult) *AllowTrustResult { return v } - -var _XdrNames_AccountMergeResultCode = map[int32]string{ - int32(ACCOUNT_MERGE_SUCCESS): "ACCOUNT_MERGE_SUCCESS", - int32(ACCOUNT_MERGE_MALFORMED): "ACCOUNT_MERGE_MALFORMED", - int32(ACCOUNT_MERGE_NO_ACCOUNT): "ACCOUNT_MERGE_NO_ACCOUNT", - int32(ACCOUNT_MERGE_IMMUTABLE_SET): "ACCOUNT_MERGE_IMMUTABLE_SET", - int32(ACCOUNT_MERGE_HAS_SUB_ENTRIES): "ACCOUNT_MERGE_HAS_SUB_ENTRIES", - int32(ACCOUNT_MERGE_SEQNUM_TOO_FAR): "ACCOUNT_MERGE_SEQNUM_TOO_FAR", - int32(ACCOUNT_MERGE_DEST_FULL): "ACCOUNT_MERGE_DEST_FULL", - int32(ACCOUNT_MERGE_IS_SPONSOR): "ACCOUNT_MERGE_IS_SPONSOR", + XdrPanic("invalid Effect (%v) in XdrAnon_ManageOfferSuccessResult_Offer", u.Effect) } -var _XdrValues_AccountMergeResultCode = map[string]int32{ - "ACCOUNT_MERGE_SUCCESS": int32(ACCOUNT_MERGE_SUCCESS), - "ACCOUNT_MERGE_MALFORMED": int32(ACCOUNT_MERGE_MALFORMED), - "ACCOUNT_MERGE_NO_ACCOUNT": int32(ACCOUNT_MERGE_NO_ACCOUNT), - "ACCOUNT_MERGE_IMMUTABLE_SET": int32(ACCOUNT_MERGE_IMMUTABLE_SET), - "ACCOUNT_MERGE_HAS_SUB_ENTRIES": int32(ACCOUNT_MERGE_HAS_SUB_ENTRIES), - "ACCOUNT_MERGE_SEQNUM_TOO_FAR": int32(ACCOUNT_MERGE_SEQNUM_TOO_FAR), - "ACCOUNT_MERGE_DEST_FULL": int32(ACCOUNT_MERGE_DEST_FULL), - "ACCOUNT_MERGE_IS_SPONSOR": int32(ACCOUNT_MERGE_IS_SPONSOR), +func XDR_XdrAnon_ManageOfferSuccessResult_Offer(v *XdrAnon_ManageOfferSuccessResult_Offer) *XdrAnon_ManageOfferSuccessResult_Offer { + return v } -func (AccountMergeResultCode) XdrEnumNames() map[int32]string { - return _XdrNames_AccountMergeResultCode -} -func (v AccountMergeResultCode) String() string { - if s, ok := _XdrNames_AccountMergeResultCode[int32(v)]; ok { +type XdrType_ManageOfferSuccessResult = *ManageOfferSuccessResult + +func (v *ManageOfferSuccessResult) XdrPointer() interface{} { return v } +func (ManageOfferSuccessResult) XdrTypeName() string { return "ManageOfferSuccessResult" } +func (v ManageOfferSuccessResult) XdrValue() interface{} { return v } +func (v *ManageOfferSuccessResult) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v *ManageOfferSuccessResult) XdrRecurse(x XDR, name string) { + if name != "" { + name = x.Sprintf("%s.", name) + } + x.Marshal(x.Sprintf("%soffersClaimed", name), (*_XdrVec_unbounded_ClaimAtom)(&v.OffersClaimed)) + x.Marshal(x.Sprintf("%soffer", name), XDR_XdrAnon_ManageOfferSuccessResult_Offer(&v.Offer)) +} +func XDR_ManageOfferSuccessResult(v *ManageOfferSuccessResult) *ManageOfferSuccessResult { return v } + +var _XdrTags_ManageSellOfferResult = map[int32]bool{ + XdrToI32(MANAGE_SELL_OFFER_SUCCESS): true, + XdrToI32(MANAGE_SELL_OFFER_MALFORMED): true, + XdrToI32(MANAGE_SELL_OFFER_SELL_NO_TRUST): true, + XdrToI32(MANAGE_SELL_OFFER_BUY_NO_TRUST): true, + XdrToI32(MANAGE_SELL_OFFER_SELL_NOT_AUTHORIZED): true, + XdrToI32(MANAGE_SELL_OFFER_BUY_NOT_AUTHORIZED): true, + XdrToI32(MANAGE_SELL_OFFER_LINE_FULL): true, + XdrToI32(MANAGE_SELL_OFFER_UNDERFUNDED): true, + XdrToI32(MANAGE_SELL_OFFER_CROSS_SELF): true, + XdrToI32(MANAGE_SELL_OFFER_SELL_NO_ISSUER): true, + XdrToI32(MANAGE_SELL_OFFER_BUY_NO_ISSUER): true, + XdrToI32(MANAGE_SELL_OFFER_NOT_FOUND): true, + XdrToI32(MANAGE_SELL_OFFER_LOW_RESERVE): true, +} + +func (_ ManageSellOfferResult) XdrValidTags() map[int32]bool { + return _XdrTags_ManageSellOfferResult +} +func (u *ManageSellOfferResult) Success() *ManageOfferSuccessResult { + switch u.Code { + case MANAGE_SELL_OFFER_SUCCESS: + if v, ok := u._u.(*ManageOfferSuccessResult); ok { + return v + } else { + var zero ManageOfferSuccessResult + u._u = &zero + return &zero + } + default: + XdrPanic("ManageSellOfferResult.Success accessed when Code == %v", u.Code) + return nil + } +} +func (u ManageSellOfferResult) XdrValid() bool { + switch u.Code { + case MANAGE_SELL_OFFER_SUCCESS, MANAGE_SELL_OFFER_MALFORMED, MANAGE_SELL_OFFER_SELL_NO_TRUST, MANAGE_SELL_OFFER_BUY_NO_TRUST, MANAGE_SELL_OFFER_SELL_NOT_AUTHORIZED, MANAGE_SELL_OFFER_BUY_NOT_AUTHORIZED, MANAGE_SELL_OFFER_LINE_FULL, MANAGE_SELL_OFFER_UNDERFUNDED, MANAGE_SELL_OFFER_CROSS_SELF, MANAGE_SELL_OFFER_SELL_NO_ISSUER, MANAGE_SELL_OFFER_BUY_NO_ISSUER, MANAGE_SELL_OFFER_NOT_FOUND, MANAGE_SELL_OFFER_LOW_RESERVE: + return true + } + return false +} +func (u *ManageSellOfferResult) XdrUnionTag() XdrNum32 { + return XDR_ManageSellOfferResultCode(&u.Code) +} +func (u *ManageSellOfferResult) XdrUnionTagName() string { + return "Code" +} +func (u *ManageSellOfferResult) XdrUnionBody() XdrType { + switch u.Code { + case MANAGE_SELL_OFFER_SUCCESS: + return XDR_ManageOfferSuccessResult(u.Success()) + case MANAGE_SELL_OFFER_MALFORMED, MANAGE_SELL_OFFER_SELL_NO_TRUST, MANAGE_SELL_OFFER_BUY_NO_TRUST, MANAGE_SELL_OFFER_SELL_NOT_AUTHORIZED, MANAGE_SELL_OFFER_BUY_NOT_AUTHORIZED, MANAGE_SELL_OFFER_LINE_FULL, MANAGE_SELL_OFFER_UNDERFUNDED, MANAGE_SELL_OFFER_CROSS_SELF, MANAGE_SELL_OFFER_SELL_NO_ISSUER, MANAGE_SELL_OFFER_BUY_NO_ISSUER, MANAGE_SELL_OFFER_NOT_FOUND, MANAGE_SELL_OFFER_LOW_RESERVE: + return nil + } + return nil +} +func (u *ManageSellOfferResult) XdrUnionBodyName() string { + switch u.Code { + case MANAGE_SELL_OFFER_SUCCESS: + return "Success" + case MANAGE_SELL_OFFER_MALFORMED, MANAGE_SELL_OFFER_SELL_NO_TRUST, MANAGE_SELL_OFFER_BUY_NO_TRUST, MANAGE_SELL_OFFER_SELL_NOT_AUTHORIZED, MANAGE_SELL_OFFER_BUY_NOT_AUTHORIZED, MANAGE_SELL_OFFER_LINE_FULL, MANAGE_SELL_OFFER_UNDERFUNDED, MANAGE_SELL_OFFER_CROSS_SELF, MANAGE_SELL_OFFER_SELL_NO_ISSUER, MANAGE_SELL_OFFER_BUY_NO_ISSUER, MANAGE_SELL_OFFER_NOT_FOUND, MANAGE_SELL_OFFER_LOW_RESERVE: + return "" + } + return "" +} + +type XdrType_ManageSellOfferResult = *ManageSellOfferResult + +func (v *ManageSellOfferResult) XdrPointer() interface{} { return v } +func (ManageSellOfferResult) XdrTypeName() string { return "ManageSellOfferResult" } +func (v ManageSellOfferResult) XdrValue() interface{} { return v } +func (v *ManageSellOfferResult) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (u *ManageSellOfferResult) XdrRecurse(x XDR, name string) { + if name != "" { + name = x.Sprintf("%s.", name) + } + XDR_ManageSellOfferResultCode(&u.Code).XdrMarshal(x, x.Sprintf("%scode", name)) + switch u.Code { + case MANAGE_SELL_OFFER_SUCCESS: + x.Marshal(x.Sprintf("%ssuccess", name), XDR_ManageOfferSuccessResult(u.Success())) + return + case MANAGE_SELL_OFFER_MALFORMED, MANAGE_SELL_OFFER_SELL_NO_TRUST, MANAGE_SELL_OFFER_BUY_NO_TRUST, MANAGE_SELL_OFFER_SELL_NOT_AUTHORIZED, MANAGE_SELL_OFFER_BUY_NOT_AUTHORIZED, MANAGE_SELL_OFFER_LINE_FULL, MANAGE_SELL_OFFER_UNDERFUNDED, MANAGE_SELL_OFFER_CROSS_SELF, MANAGE_SELL_OFFER_SELL_NO_ISSUER, MANAGE_SELL_OFFER_BUY_NO_ISSUER, MANAGE_SELL_OFFER_NOT_FOUND, MANAGE_SELL_OFFER_LOW_RESERVE: + return + } + XdrPanic("invalid Code (%v) in ManageSellOfferResult", u.Code) +} +func XDR_ManageSellOfferResult(v *ManageSellOfferResult) *ManageSellOfferResult { return v } + +var _XdrNames_ManageBuyOfferResultCode = map[int32]string{ + int32(MANAGE_BUY_OFFER_SUCCESS): "MANAGE_BUY_OFFER_SUCCESS", + int32(MANAGE_BUY_OFFER_MALFORMED): "MANAGE_BUY_OFFER_MALFORMED", + int32(MANAGE_BUY_OFFER_SELL_NO_TRUST): "MANAGE_BUY_OFFER_SELL_NO_TRUST", + int32(MANAGE_BUY_OFFER_BUY_NO_TRUST): "MANAGE_BUY_OFFER_BUY_NO_TRUST", + int32(MANAGE_BUY_OFFER_SELL_NOT_AUTHORIZED): "MANAGE_BUY_OFFER_SELL_NOT_AUTHORIZED", + int32(MANAGE_BUY_OFFER_BUY_NOT_AUTHORIZED): "MANAGE_BUY_OFFER_BUY_NOT_AUTHORIZED", + int32(MANAGE_BUY_OFFER_LINE_FULL): "MANAGE_BUY_OFFER_LINE_FULL", + int32(MANAGE_BUY_OFFER_UNDERFUNDED): "MANAGE_BUY_OFFER_UNDERFUNDED", + int32(MANAGE_BUY_OFFER_CROSS_SELF): "MANAGE_BUY_OFFER_CROSS_SELF", + int32(MANAGE_BUY_OFFER_SELL_NO_ISSUER): "MANAGE_BUY_OFFER_SELL_NO_ISSUER", + int32(MANAGE_BUY_OFFER_BUY_NO_ISSUER): "MANAGE_BUY_OFFER_BUY_NO_ISSUER", + int32(MANAGE_BUY_OFFER_NOT_FOUND): "MANAGE_BUY_OFFER_NOT_FOUND", + int32(MANAGE_BUY_OFFER_LOW_RESERVE): "MANAGE_BUY_OFFER_LOW_RESERVE", +} +var _XdrValues_ManageBuyOfferResultCode = map[string]int32{ + "MANAGE_BUY_OFFER_SUCCESS": int32(MANAGE_BUY_OFFER_SUCCESS), + "MANAGE_BUY_OFFER_MALFORMED": int32(MANAGE_BUY_OFFER_MALFORMED), + "MANAGE_BUY_OFFER_SELL_NO_TRUST": int32(MANAGE_BUY_OFFER_SELL_NO_TRUST), + "MANAGE_BUY_OFFER_BUY_NO_TRUST": int32(MANAGE_BUY_OFFER_BUY_NO_TRUST), + "MANAGE_BUY_OFFER_SELL_NOT_AUTHORIZED": int32(MANAGE_BUY_OFFER_SELL_NOT_AUTHORIZED), + "MANAGE_BUY_OFFER_BUY_NOT_AUTHORIZED": int32(MANAGE_BUY_OFFER_BUY_NOT_AUTHORIZED), + "MANAGE_BUY_OFFER_LINE_FULL": int32(MANAGE_BUY_OFFER_LINE_FULL), + "MANAGE_BUY_OFFER_UNDERFUNDED": int32(MANAGE_BUY_OFFER_UNDERFUNDED), + "MANAGE_BUY_OFFER_CROSS_SELF": int32(MANAGE_BUY_OFFER_CROSS_SELF), + "MANAGE_BUY_OFFER_SELL_NO_ISSUER": int32(MANAGE_BUY_OFFER_SELL_NO_ISSUER), + "MANAGE_BUY_OFFER_BUY_NO_ISSUER": int32(MANAGE_BUY_OFFER_BUY_NO_ISSUER), + "MANAGE_BUY_OFFER_NOT_FOUND": int32(MANAGE_BUY_OFFER_NOT_FOUND), + "MANAGE_BUY_OFFER_LOW_RESERVE": int32(MANAGE_BUY_OFFER_LOW_RESERVE), +} + +func (ManageBuyOfferResultCode) XdrEnumNames() map[int32]string { + return _XdrNames_ManageBuyOfferResultCode +} +func (v ManageBuyOfferResultCode) String() string { + if s, ok := _XdrNames_ManageBuyOfferResultCode[int32(v)]; ok { return s } - return fmt.Sprintf("AccountMergeResultCode#%d", v) + return fmt.Sprintf("ManageBuyOfferResultCode#%d", v) } -func (v *AccountMergeResultCode) Scan(ss fmt.ScanState, _ rune) error { +func (v *ManageBuyOfferResultCode) Scan(ss fmt.ScanState, _ rune) error { if tok, err := ss.Token(true, XdrSymChar); err != nil { return err } else { stok := string(tok) - if val, ok := _XdrValues_AccountMergeResultCode[stok]; ok { - *v = AccountMergeResultCode(val) + if val, ok := _XdrValues_ManageBuyOfferResultCode[stok]; ok { + *v = ManageBuyOfferResultCode(val) return nil - } else if stok == "AccountMergeResultCode" { + } else if stok == "ManageBuyOfferResultCode" { if n, err := fmt.Fscanf(ss, "#%d", (*int32)(v)); n == 1 && err == nil { return nil } } - return XdrError(fmt.Sprintf("%s is not a valid AccountMergeResultCode.", stok)) + return XdrError(fmt.Sprintf("%s is not a valid ManageBuyOfferResultCode.", stok)) + } +} +func (v ManageBuyOfferResultCode) GetU32() uint32 { return uint32(v) } +func (v *ManageBuyOfferResultCode) SetU32(n uint32) { *v = ManageBuyOfferResultCode(n) } +func (v *ManageBuyOfferResultCode) XdrPointer() interface{} { return v } +func (ManageBuyOfferResultCode) XdrTypeName() string { return "ManageBuyOfferResultCode" } +func (v ManageBuyOfferResultCode) XdrValue() interface{} { return v } +func (v *ManageBuyOfferResultCode) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } + +type XdrType_ManageBuyOfferResultCode = *ManageBuyOfferResultCode + +func XDR_ManageBuyOfferResultCode(v *ManageBuyOfferResultCode) *ManageBuyOfferResultCode { return v } + +var _XdrComments_ManageBuyOfferResultCode = map[int32]string{ + int32(MANAGE_BUY_OFFER_SUCCESS): "codes considered as \"success\" for the operation", + int32(MANAGE_BUY_OFFER_MALFORMED): "generated offer would be invalid", + int32(MANAGE_BUY_OFFER_SELL_NO_TRUST): "no trust line for what we're selling", + int32(MANAGE_BUY_OFFER_BUY_NO_TRUST): "no trust line for what we're buying", + int32(MANAGE_BUY_OFFER_SELL_NOT_AUTHORIZED): "not authorized to sell", + int32(MANAGE_BUY_OFFER_BUY_NOT_AUTHORIZED): "not authorized to buy", + int32(MANAGE_BUY_OFFER_LINE_FULL): "can't receive more of what it's buying", + int32(MANAGE_BUY_OFFER_UNDERFUNDED): "doesn't hold what it's trying to sell", + int32(MANAGE_BUY_OFFER_CROSS_SELF): "would cross an offer from the same user", + int32(MANAGE_BUY_OFFER_SELL_NO_ISSUER): "no issuer for what we're selling", + int32(MANAGE_BUY_OFFER_BUY_NO_ISSUER): "no issuer for what we're buying", + int32(MANAGE_BUY_OFFER_NOT_FOUND): "offerID does not match an existing offer", + int32(MANAGE_BUY_OFFER_LOW_RESERVE): "not enough funds to create a new Offer", +} + +func (e ManageBuyOfferResultCode) XdrEnumComments() map[int32]string { + return _XdrComments_ManageBuyOfferResultCode +} + +var _XdrTags_ManageBuyOfferResult = map[int32]bool{ + XdrToI32(MANAGE_BUY_OFFER_SUCCESS): true, + XdrToI32(MANAGE_BUY_OFFER_MALFORMED): true, + XdrToI32(MANAGE_BUY_OFFER_SELL_NO_TRUST): true, + XdrToI32(MANAGE_BUY_OFFER_BUY_NO_TRUST): true, + XdrToI32(MANAGE_BUY_OFFER_SELL_NOT_AUTHORIZED): true, + XdrToI32(MANAGE_BUY_OFFER_BUY_NOT_AUTHORIZED): true, + XdrToI32(MANAGE_BUY_OFFER_LINE_FULL): true, + XdrToI32(MANAGE_BUY_OFFER_UNDERFUNDED): true, + XdrToI32(MANAGE_BUY_OFFER_CROSS_SELF): true, + XdrToI32(MANAGE_BUY_OFFER_SELL_NO_ISSUER): true, + XdrToI32(MANAGE_BUY_OFFER_BUY_NO_ISSUER): true, + XdrToI32(MANAGE_BUY_OFFER_NOT_FOUND): true, + XdrToI32(MANAGE_BUY_OFFER_LOW_RESERVE): true, +} + +func (_ ManageBuyOfferResult) XdrValidTags() map[int32]bool { + return _XdrTags_ManageBuyOfferResult +} +func (u *ManageBuyOfferResult) Success() *ManageOfferSuccessResult { + switch u.Code { + case MANAGE_BUY_OFFER_SUCCESS: + if v, ok := u._u.(*ManageOfferSuccessResult); ok { + return v + } else { + var zero ManageOfferSuccessResult + u._u = &zero + return &zero + } + default: + XdrPanic("ManageBuyOfferResult.Success accessed when Code == %v", u.Code) + return nil + } +} +func (u ManageBuyOfferResult) XdrValid() bool { + switch u.Code { + case MANAGE_BUY_OFFER_SUCCESS, MANAGE_BUY_OFFER_MALFORMED, MANAGE_BUY_OFFER_SELL_NO_TRUST, MANAGE_BUY_OFFER_BUY_NO_TRUST, MANAGE_BUY_OFFER_SELL_NOT_AUTHORIZED, MANAGE_BUY_OFFER_BUY_NOT_AUTHORIZED, MANAGE_BUY_OFFER_LINE_FULL, MANAGE_BUY_OFFER_UNDERFUNDED, MANAGE_BUY_OFFER_CROSS_SELF, MANAGE_BUY_OFFER_SELL_NO_ISSUER, MANAGE_BUY_OFFER_BUY_NO_ISSUER, MANAGE_BUY_OFFER_NOT_FOUND, MANAGE_BUY_OFFER_LOW_RESERVE: + return true + } + return false +} +func (u *ManageBuyOfferResult) XdrUnionTag() XdrNum32 { + return XDR_ManageBuyOfferResultCode(&u.Code) +} +func (u *ManageBuyOfferResult) XdrUnionTagName() string { + return "Code" +} +func (u *ManageBuyOfferResult) XdrUnionBody() XdrType { + switch u.Code { + case MANAGE_BUY_OFFER_SUCCESS: + return XDR_ManageOfferSuccessResult(u.Success()) + case MANAGE_BUY_OFFER_MALFORMED, MANAGE_BUY_OFFER_SELL_NO_TRUST, MANAGE_BUY_OFFER_BUY_NO_TRUST, MANAGE_BUY_OFFER_SELL_NOT_AUTHORIZED, MANAGE_BUY_OFFER_BUY_NOT_AUTHORIZED, MANAGE_BUY_OFFER_LINE_FULL, MANAGE_BUY_OFFER_UNDERFUNDED, MANAGE_BUY_OFFER_CROSS_SELF, MANAGE_BUY_OFFER_SELL_NO_ISSUER, MANAGE_BUY_OFFER_BUY_NO_ISSUER, MANAGE_BUY_OFFER_NOT_FOUND, MANAGE_BUY_OFFER_LOW_RESERVE: + return nil + } + return nil +} +func (u *ManageBuyOfferResult) XdrUnionBodyName() string { + switch u.Code { + case MANAGE_BUY_OFFER_SUCCESS: + return "Success" + case MANAGE_BUY_OFFER_MALFORMED, MANAGE_BUY_OFFER_SELL_NO_TRUST, MANAGE_BUY_OFFER_BUY_NO_TRUST, MANAGE_BUY_OFFER_SELL_NOT_AUTHORIZED, MANAGE_BUY_OFFER_BUY_NOT_AUTHORIZED, MANAGE_BUY_OFFER_LINE_FULL, MANAGE_BUY_OFFER_UNDERFUNDED, MANAGE_BUY_OFFER_CROSS_SELF, MANAGE_BUY_OFFER_SELL_NO_ISSUER, MANAGE_BUY_OFFER_BUY_NO_ISSUER, MANAGE_BUY_OFFER_NOT_FOUND, MANAGE_BUY_OFFER_LOW_RESERVE: + return "" + } + return "" +} + +type XdrType_ManageBuyOfferResult = *ManageBuyOfferResult + +func (v *ManageBuyOfferResult) XdrPointer() interface{} { return v } +func (ManageBuyOfferResult) XdrTypeName() string { return "ManageBuyOfferResult" } +func (v ManageBuyOfferResult) XdrValue() interface{} { return v } +func (v *ManageBuyOfferResult) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (u *ManageBuyOfferResult) XdrRecurse(x XDR, name string) { + if name != "" { + name = x.Sprintf("%s.", name) + } + XDR_ManageBuyOfferResultCode(&u.Code).XdrMarshal(x, x.Sprintf("%scode", name)) + switch u.Code { + case MANAGE_BUY_OFFER_SUCCESS: + x.Marshal(x.Sprintf("%ssuccess", name), XDR_ManageOfferSuccessResult(u.Success())) + return + case MANAGE_BUY_OFFER_MALFORMED, MANAGE_BUY_OFFER_SELL_NO_TRUST, MANAGE_BUY_OFFER_BUY_NO_TRUST, MANAGE_BUY_OFFER_SELL_NOT_AUTHORIZED, MANAGE_BUY_OFFER_BUY_NOT_AUTHORIZED, MANAGE_BUY_OFFER_LINE_FULL, MANAGE_BUY_OFFER_UNDERFUNDED, MANAGE_BUY_OFFER_CROSS_SELF, MANAGE_BUY_OFFER_SELL_NO_ISSUER, MANAGE_BUY_OFFER_BUY_NO_ISSUER, MANAGE_BUY_OFFER_NOT_FOUND, MANAGE_BUY_OFFER_LOW_RESERVE: + return + } + XdrPanic("invalid Code (%v) in ManageBuyOfferResult", u.Code) +} +func XDR_ManageBuyOfferResult(v *ManageBuyOfferResult) *ManageBuyOfferResult { return v } + +var _XdrNames_SetOptionsResultCode = map[int32]string{ + int32(SET_OPTIONS_SUCCESS): "SET_OPTIONS_SUCCESS", + int32(SET_OPTIONS_LOW_RESERVE): "SET_OPTIONS_LOW_RESERVE", + int32(SET_OPTIONS_TOO_MANY_SIGNERS): "SET_OPTIONS_TOO_MANY_SIGNERS", + int32(SET_OPTIONS_BAD_FLAGS): "SET_OPTIONS_BAD_FLAGS", + int32(SET_OPTIONS_INVALID_INFLATION): "SET_OPTIONS_INVALID_INFLATION", + int32(SET_OPTIONS_CANT_CHANGE): "SET_OPTIONS_CANT_CHANGE", + int32(SET_OPTIONS_UNKNOWN_FLAG): "SET_OPTIONS_UNKNOWN_FLAG", + int32(SET_OPTIONS_THRESHOLD_OUT_OF_RANGE): "SET_OPTIONS_THRESHOLD_OUT_OF_RANGE", + int32(SET_OPTIONS_BAD_SIGNER): "SET_OPTIONS_BAD_SIGNER", + int32(SET_OPTIONS_INVALID_HOME_DOMAIN): "SET_OPTIONS_INVALID_HOME_DOMAIN", + int32(SET_OPTIONS_AUTH_REVOCABLE_REQUIRED): "SET_OPTIONS_AUTH_REVOCABLE_REQUIRED", +} +var _XdrValues_SetOptionsResultCode = map[string]int32{ + "SET_OPTIONS_SUCCESS": int32(SET_OPTIONS_SUCCESS), + "SET_OPTIONS_LOW_RESERVE": int32(SET_OPTIONS_LOW_RESERVE), + "SET_OPTIONS_TOO_MANY_SIGNERS": int32(SET_OPTIONS_TOO_MANY_SIGNERS), + "SET_OPTIONS_BAD_FLAGS": int32(SET_OPTIONS_BAD_FLAGS), + "SET_OPTIONS_INVALID_INFLATION": int32(SET_OPTIONS_INVALID_INFLATION), + "SET_OPTIONS_CANT_CHANGE": int32(SET_OPTIONS_CANT_CHANGE), + "SET_OPTIONS_UNKNOWN_FLAG": int32(SET_OPTIONS_UNKNOWN_FLAG), + "SET_OPTIONS_THRESHOLD_OUT_OF_RANGE": int32(SET_OPTIONS_THRESHOLD_OUT_OF_RANGE), + "SET_OPTIONS_BAD_SIGNER": int32(SET_OPTIONS_BAD_SIGNER), + "SET_OPTIONS_INVALID_HOME_DOMAIN": int32(SET_OPTIONS_INVALID_HOME_DOMAIN), + "SET_OPTIONS_AUTH_REVOCABLE_REQUIRED": int32(SET_OPTIONS_AUTH_REVOCABLE_REQUIRED), +} + +func (SetOptionsResultCode) XdrEnumNames() map[int32]string { + return _XdrNames_SetOptionsResultCode +} +func (v SetOptionsResultCode) String() string { + if s, ok := _XdrNames_SetOptionsResultCode[int32(v)]; ok { + return s + } + return fmt.Sprintf("SetOptionsResultCode#%d", v) +} +func (v *SetOptionsResultCode) Scan(ss fmt.ScanState, _ rune) error { + if tok, err := ss.Token(true, XdrSymChar); err != nil { + return err + } else { + stok := string(tok) + if val, ok := _XdrValues_SetOptionsResultCode[stok]; ok { + *v = SetOptionsResultCode(val) + return nil + } else if stok == "SetOptionsResultCode" { + if n, err := fmt.Fscanf(ss, "#%d", (*int32)(v)); n == 1 && err == nil { + return nil + } + } + return XdrError(fmt.Sprintf("%s is not a valid SetOptionsResultCode.", stok)) + } +} +func (v SetOptionsResultCode) GetU32() uint32 { return uint32(v) } +func (v *SetOptionsResultCode) SetU32(n uint32) { *v = SetOptionsResultCode(n) } +func (v *SetOptionsResultCode) XdrPointer() interface{} { return v } +func (SetOptionsResultCode) XdrTypeName() string { return "SetOptionsResultCode" } +func (v SetOptionsResultCode) XdrValue() interface{} { return v } +func (v *SetOptionsResultCode) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } + +type XdrType_SetOptionsResultCode = *SetOptionsResultCode + +func XDR_SetOptionsResultCode(v *SetOptionsResultCode) *SetOptionsResultCode { return v } + +var _XdrComments_SetOptionsResultCode = map[int32]string{ + int32(SET_OPTIONS_SUCCESS): "codes considered as \"success\" for the operation", + int32(SET_OPTIONS_LOW_RESERVE): "not enough funds to add a signer", + int32(SET_OPTIONS_TOO_MANY_SIGNERS): "max number of signers already reached", + int32(SET_OPTIONS_BAD_FLAGS): "invalid combination of clear/set flags", + int32(SET_OPTIONS_INVALID_INFLATION): "inflation account does not exist", + int32(SET_OPTIONS_CANT_CHANGE): "can no longer change this option", + int32(SET_OPTIONS_UNKNOWN_FLAG): "can't set an unknown flag", + int32(SET_OPTIONS_THRESHOLD_OUT_OF_RANGE): "bad value for weight/threshold", + int32(SET_OPTIONS_BAD_SIGNER): "signer cannot be masterkey", + int32(SET_OPTIONS_INVALID_HOME_DOMAIN): "malformed home domain", + int32(SET_OPTIONS_AUTH_REVOCABLE_REQUIRED): "auth revocable is required for clawback", +} + +func (e SetOptionsResultCode) XdrEnumComments() map[int32]string { + return _XdrComments_SetOptionsResultCode +} + +var _XdrTags_SetOptionsResult = map[int32]bool{ + XdrToI32(SET_OPTIONS_SUCCESS): true, + XdrToI32(SET_OPTIONS_LOW_RESERVE): true, + XdrToI32(SET_OPTIONS_TOO_MANY_SIGNERS): true, + XdrToI32(SET_OPTIONS_BAD_FLAGS): true, + XdrToI32(SET_OPTIONS_INVALID_INFLATION): true, + XdrToI32(SET_OPTIONS_CANT_CHANGE): true, + XdrToI32(SET_OPTIONS_UNKNOWN_FLAG): true, + XdrToI32(SET_OPTIONS_THRESHOLD_OUT_OF_RANGE): true, + XdrToI32(SET_OPTIONS_BAD_SIGNER): true, + XdrToI32(SET_OPTIONS_INVALID_HOME_DOMAIN): true, + XdrToI32(SET_OPTIONS_AUTH_REVOCABLE_REQUIRED): true, +} + +func (_ SetOptionsResult) XdrValidTags() map[int32]bool { + return _XdrTags_SetOptionsResult +} +func (u SetOptionsResult) XdrValid() bool { + switch u.Code { + case SET_OPTIONS_SUCCESS, SET_OPTIONS_LOW_RESERVE, SET_OPTIONS_TOO_MANY_SIGNERS, SET_OPTIONS_BAD_FLAGS, SET_OPTIONS_INVALID_INFLATION, SET_OPTIONS_CANT_CHANGE, SET_OPTIONS_UNKNOWN_FLAG, SET_OPTIONS_THRESHOLD_OUT_OF_RANGE, SET_OPTIONS_BAD_SIGNER, SET_OPTIONS_INVALID_HOME_DOMAIN, SET_OPTIONS_AUTH_REVOCABLE_REQUIRED: + return true + } + return false +} +func (u *SetOptionsResult) XdrUnionTag() XdrNum32 { + return XDR_SetOptionsResultCode(&u.Code) +} +func (u *SetOptionsResult) XdrUnionTagName() string { + return "Code" +} +func (u *SetOptionsResult) XdrUnionBody() XdrType { + switch u.Code { + case SET_OPTIONS_SUCCESS: + return nil + case SET_OPTIONS_LOW_RESERVE, SET_OPTIONS_TOO_MANY_SIGNERS, SET_OPTIONS_BAD_FLAGS, SET_OPTIONS_INVALID_INFLATION, SET_OPTIONS_CANT_CHANGE, SET_OPTIONS_UNKNOWN_FLAG, SET_OPTIONS_THRESHOLD_OUT_OF_RANGE, SET_OPTIONS_BAD_SIGNER, SET_OPTIONS_INVALID_HOME_DOMAIN, SET_OPTIONS_AUTH_REVOCABLE_REQUIRED: + return nil + } + return nil +} +func (u *SetOptionsResult) XdrUnionBodyName() string { + switch u.Code { + case SET_OPTIONS_SUCCESS: + return "" + case SET_OPTIONS_LOW_RESERVE, SET_OPTIONS_TOO_MANY_SIGNERS, SET_OPTIONS_BAD_FLAGS, SET_OPTIONS_INVALID_INFLATION, SET_OPTIONS_CANT_CHANGE, SET_OPTIONS_UNKNOWN_FLAG, SET_OPTIONS_THRESHOLD_OUT_OF_RANGE, SET_OPTIONS_BAD_SIGNER, SET_OPTIONS_INVALID_HOME_DOMAIN, SET_OPTIONS_AUTH_REVOCABLE_REQUIRED: + return "" + } + return "" +} + +type XdrType_SetOptionsResult = *SetOptionsResult + +func (v *SetOptionsResult) XdrPointer() interface{} { return v } +func (SetOptionsResult) XdrTypeName() string { return "SetOptionsResult" } +func (v SetOptionsResult) XdrValue() interface{} { return v } +func (v *SetOptionsResult) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (u *SetOptionsResult) XdrRecurse(x XDR, name string) { + if name != "" { + name = x.Sprintf("%s.", name) + } + XDR_SetOptionsResultCode(&u.Code).XdrMarshal(x, x.Sprintf("%scode", name)) + switch u.Code { + case SET_OPTIONS_SUCCESS: + return + case SET_OPTIONS_LOW_RESERVE, SET_OPTIONS_TOO_MANY_SIGNERS, SET_OPTIONS_BAD_FLAGS, SET_OPTIONS_INVALID_INFLATION, SET_OPTIONS_CANT_CHANGE, SET_OPTIONS_UNKNOWN_FLAG, SET_OPTIONS_THRESHOLD_OUT_OF_RANGE, SET_OPTIONS_BAD_SIGNER, SET_OPTIONS_INVALID_HOME_DOMAIN, SET_OPTIONS_AUTH_REVOCABLE_REQUIRED: + return + } + XdrPanic("invalid Code (%v) in SetOptionsResult", u.Code) +} +func XDR_SetOptionsResult(v *SetOptionsResult) *SetOptionsResult { return v } + +var _XdrNames_ChangeTrustResultCode = map[int32]string{ + int32(CHANGE_TRUST_SUCCESS): "CHANGE_TRUST_SUCCESS", + int32(CHANGE_TRUST_MALFORMED): "CHANGE_TRUST_MALFORMED", + int32(CHANGE_TRUST_NO_ISSUER): "CHANGE_TRUST_NO_ISSUER", + int32(CHANGE_TRUST_INVALID_LIMIT): "CHANGE_TRUST_INVALID_LIMIT", + int32(CHANGE_TRUST_LOW_RESERVE): "CHANGE_TRUST_LOW_RESERVE", + int32(CHANGE_TRUST_SELF_NOT_ALLOWED): "CHANGE_TRUST_SELF_NOT_ALLOWED", + int32(CHANGE_TRUST_TRUST_LINE_MISSING): "CHANGE_TRUST_TRUST_LINE_MISSING", + int32(CHANGE_TRUST_CANNOT_DELETE): "CHANGE_TRUST_CANNOT_DELETE", + int32(CHANGE_TRUST_NOT_AUTH_MAINTAIN_LIABILITIES): "CHANGE_TRUST_NOT_AUTH_MAINTAIN_LIABILITIES", +} +var _XdrValues_ChangeTrustResultCode = map[string]int32{ + "CHANGE_TRUST_SUCCESS": int32(CHANGE_TRUST_SUCCESS), + "CHANGE_TRUST_MALFORMED": int32(CHANGE_TRUST_MALFORMED), + "CHANGE_TRUST_NO_ISSUER": int32(CHANGE_TRUST_NO_ISSUER), + "CHANGE_TRUST_INVALID_LIMIT": int32(CHANGE_TRUST_INVALID_LIMIT), + "CHANGE_TRUST_LOW_RESERVE": int32(CHANGE_TRUST_LOW_RESERVE), + "CHANGE_TRUST_SELF_NOT_ALLOWED": int32(CHANGE_TRUST_SELF_NOT_ALLOWED), + "CHANGE_TRUST_TRUST_LINE_MISSING": int32(CHANGE_TRUST_TRUST_LINE_MISSING), + "CHANGE_TRUST_CANNOT_DELETE": int32(CHANGE_TRUST_CANNOT_DELETE), + "CHANGE_TRUST_NOT_AUTH_MAINTAIN_LIABILITIES": int32(CHANGE_TRUST_NOT_AUTH_MAINTAIN_LIABILITIES), +} + +func (ChangeTrustResultCode) XdrEnumNames() map[int32]string { + return _XdrNames_ChangeTrustResultCode +} +func (v ChangeTrustResultCode) String() string { + if s, ok := _XdrNames_ChangeTrustResultCode[int32(v)]; ok { + return s + } + return fmt.Sprintf("ChangeTrustResultCode#%d", v) +} +func (v *ChangeTrustResultCode) Scan(ss fmt.ScanState, _ rune) error { + if tok, err := ss.Token(true, XdrSymChar); err != nil { + return err + } else { + stok := string(tok) + if val, ok := _XdrValues_ChangeTrustResultCode[stok]; ok { + *v = ChangeTrustResultCode(val) + return nil + } else if stok == "ChangeTrustResultCode" { + if n, err := fmt.Fscanf(ss, "#%d", (*int32)(v)); n == 1 && err == nil { + return nil + } + } + return XdrError(fmt.Sprintf("%s is not a valid ChangeTrustResultCode.", stok)) + } +} +func (v ChangeTrustResultCode) GetU32() uint32 { return uint32(v) } +func (v *ChangeTrustResultCode) SetU32(n uint32) { *v = ChangeTrustResultCode(n) } +func (v *ChangeTrustResultCode) XdrPointer() interface{} { return v } +func (ChangeTrustResultCode) XdrTypeName() string { return "ChangeTrustResultCode" } +func (v ChangeTrustResultCode) XdrValue() interface{} { return v } +func (v *ChangeTrustResultCode) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } + +type XdrType_ChangeTrustResultCode = *ChangeTrustResultCode + +func XDR_ChangeTrustResultCode(v *ChangeTrustResultCode) *ChangeTrustResultCode { return v } + +var _XdrComments_ChangeTrustResultCode = map[int32]string{ + int32(CHANGE_TRUST_SUCCESS): "codes considered as \"success\" for the operation", + int32(CHANGE_TRUST_MALFORMED): "bad input", + int32(CHANGE_TRUST_NO_ISSUER): "could not find issuer", + int32(CHANGE_TRUST_INVALID_LIMIT): "cannot drop limit below balance", + int32(CHANGE_TRUST_LOW_RESERVE): "not enough funds to create a new trust line,", + int32(CHANGE_TRUST_SELF_NOT_ALLOWED): "trusting self is not allowed", + int32(CHANGE_TRUST_TRUST_LINE_MISSING): "Asset trustline is missing for pool", + int32(CHANGE_TRUST_CANNOT_DELETE): "Asset trustline is still referenced in a pool", + int32(CHANGE_TRUST_NOT_AUTH_MAINTAIN_LIABILITIES): "Asset trustline is deauthorized", +} + +func (e ChangeTrustResultCode) XdrEnumComments() map[int32]string { + return _XdrComments_ChangeTrustResultCode +} + +var _XdrTags_ChangeTrustResult = map[int32]bool{ + XdrToI32(CHANGE_TRUST_SUCCESS): true, + XdrToI32(CHANGE_TRUST_MALFORMED): true, + XdrToI32(CHANGE_TRUST_NO_ISSUER): true, + XdrToI32(CHANGE_TRUST_INVALID_LIMIT): true, + XdrToI32(CHANGE_TRUST_LOW_RESERVE): true, + XdrToI32(CHANGE_TRUST_SELF_NOT_ALLOWED): true, + XdrToI32(CHANGE_TRUST_TRUST_LINE_MISSING): true, + XdrToI32(CHANGE_TRUST_CANNOT_DELETE): true, + XdrToI32(CHANGE_TRUST_NOT_AUTH_MAINTAIN_LIABILITIES): true, +} + +func (_ ChangeTrustResult) XdrValidTags() map[int32]bool { + return _XdrTags_ChangeTrustResult +} +func (u ChangeTrustResult) XdrValid() bool { + switch u.Code { + case CHANGE_TRUST_SUCCESS, CHANGE_TRUST_MALFORMED, CHANGE_TRUST_NO_ISSUER, CHANGE_TRUST_INVALID_LIMIT, CHANGE_TRUST_LOW_RESERVE, CHANGE_TRUST_SELF_NOT_ALLOWED, CHANGE_TRUST_TRUST_LINE_MISSING, CHANGE_TRUST_CANNOT_DELETE, CHANGE_TRUST_NOT_AUTH_MAINTAIN_LIABILITIES: + return true + } + return false +} +func (u *ChangeTrustResult) XdrUnionTag() XdrNum32 { + return XDR_ChangeTrustResultCode(&u.Code) +} +func (u *ChangeTrustResult) XdrUnionTagName() string { + return "Code" +} +func (u *ChangeTrustResult) XdrUnionBody() XdrType { + switch u.Code { + case CHANGE_TRUST_SUCCESS: + return nil + case CHANGE_TRUST_MALFORMED, CHANGE_TRUST_NO_ISSUER, CHANGE_TRUST_INVALID_LIMIT, CHANGE_TRUST_LOW_RESERVE, CHANGE_TRUST_SELF_NOT_ALLOWED, CHANGE_TRUST_TRUST_LINE_MISSING, CHANGE_TRUST_CANNOT_DELETE, CHANGE_TRUST_NOT_AUTH_MAINTAIN_LIABILITIES: + return nil + } + return nil +} +func (u *ChangeTrustResult) XdrUnionBodyName() string { + switch u.Code { + case CHANGE_TRUST_SUCCESS: + return "" + case CHANGE_TRUST_MALFORMED, CHANGE_TRUST_NO_ISSUER, CHANGE_TRUST_INVALID_LIMIT, CHANGE_TRUST_LOW_RESERVE, CHANGE_TRUST_SELF_NOT_ALLOWED, CHANGE_TRUST_TRUST_LINE_MISSING, CHANGE_TRUST_CANNOT_DELETE, CHANGE_TRUST_NOT_AUTH_MAINTAIN_LIABILITIES: + return "" + } + return "" +} + +type XdrType_ChangeTrustResult = *ChangeTrustResult + +func (v *ChangeTrustResult) XdrPointer() interface{} { return v } +func (ChangeTrustResult) XdrTypeName() string { return "ChangeTrustResult" } +func (v ChangeTrustResult) XdrValue() interface{} { return v } +func (v *ChangeTrustResult) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (u *ChangeTrustResult) XdrRecurse(x XDR, name string) { + if name != "" { + name = x.Sprintf("%s.", name) + } + XDR_ChangeTrustResultCode(&u.Code).XdrMarshal(x, x.Sprintf("%scode", name)) + switch u.Code { + case CHANGE_TRUST_SUCCESS: + return + case CHANGE_TRUST_MALFORMED, CHANGE_TRUST_NO_ISSUER, CHANGE_TRUST_INVALID_LIMIT, CHANGE_TRUST_LOW_RESERVE, CHANGE_TRUST_SELF_NOT_ALLOWED, CHANGE_TRUST_TRUST_LINE_MISSING, CHANGE_TRUST_CANNOT_DELETE, CHANGE_TRUST_NOT_AUTH_MAINTAIN_LIABILITIES: + return + } + XdrPanic("invalid Code (%v) in ChangeTrustResult", u.Code) +} +func XDR_ChangeTrustResult(v *ChangeTrustResult) *ChangeTrustResult { return v } + +var _XdrNames_AllowTrustResultCode = map[int32]string{ + int32(ALLOW_TRUST_SUCCESS): "ALLOW_TRUST_SUCCESS", + int32(ALLOW_TRUST_MALFORMED): "ALLOW_TRUST_MALFORMED", + int32(ALLOW_TRUST_NO_TRUST_LINE): "ALLOW_TRUST_NO_TRUST_LINE", + int32(ALLOW_TRUST_TRUST_NOT_REQUIRED): "ALLOW_TRUST_TRUST_NOT_REQUIRED", + int32(ALLOW_TRUST_CANT_REVOKE): "ALLOW_TRUST_CANT_REVOKE", + int32(ALLOW_TRUST_SELF_NOT_ALLOWED): "ALLOW_TRUST_SELF_NOT_ALLOWED", + int32(ALLOW_TRUST_LOW_RESERVE): "ALLOW_TRUST_LOW_RESERVE", +} +var _XdrValues_AllowTrustResultCode = map[string]int32{ + "ALLOW_TRUST_SUCCESS": int32(ALLOW_TRUST_SUCCESS), + "ALLOW_TRUST_MALFORMED": int32(ALLOW_TRUST_MALFORMED), + "ALLOW_TRUST_NO_TRUST_LINE": int32(ALLOW_TRUST_NO_TRUST_LINE), + "ALLOW_TRUST_TRUST_NOT_REQUIRED": int32(ALLOW_TRUST_TRUST_NOT_REQUIRED), + "ALLOW_TRUST_CANT_REVOKE": int32(ALLOW_TRUST_CANT_REVOKE), + "ALLOW_TRUST_SELF_NOT_ALLOWED": int32(ALLOW_TRUST_SELF_NOT_ALLOWED), + "ALLOW_TRUST_LOW_RESERVE": int32(ALLOW_TRUST_LOW_RESERVE), +} + +func (AllowTrustResultCode) XdrEnumNames() map[int32]string { + return _XdrNames_AllowTrustResultCode +} +func (v AllowTrustResultCode) String() string { + if s, ok := _XdrNames_AllowTrustResultCode[int32(v)]; ok { + return s + } + return fmt.Sprintf("AllowTrustResultCode#%d", v) +} +func (v *AllowTrustResultCode) Scan(ss fmt.ScanState, _ rune) error { + if tok, err := ss.Token(true, XdrSymChar); err != nil { + return err + } else { + stok := string(tok) + if val, ok := _XdrValues_AllowTrustResultCode[stok]; ok { + *v = AllowTrustResultCode(val) + return nil + } else if stok == "AllowTrustResultCode" { + if n, err := fmt.Fscanf(ss, "#%d", (*int32)(v)); n == 1 && err == nil { + return nil + } + } + return XdrError(fmt.Sprintf("%s is not a valid AllowTrustResultCode.", stok)) + } +} +func (v AllowTrustResultCode) GetU32() uint32 { return uint32(v) } +func (v *AllowTrustResultCode) SetU32(n uint32) { *v = AllowTrustResultCode(n) } +func (v *AllowTrustResultCode) XdrPointer() interface{} { return v } +func (AllowTrustResultCode) XdrTypeName() string { return "AllowTrustResultCode" } +func (v AllowTrustResultCode) XdrValue() interface{} { return v } +func (v *AllowTrustResultCode) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } + +type XdrType_AllowTrustResultCode = *AllowTrustResultCode + +func XDR_AllowTrustResultCode(v *AllowTrustResultCode) *AllowTrustResultCode { return v } + +var _XdrComments_AllowTrustResultCode = map[int32]string{ + int32(ALLOW_TRUST_SUCCESS): "codes considered as \"success\" for the operation", + int32(ALLOW_TRUST_MALFORMED): "asset is not ASSET_TYPE_ALPHANUM", + int32(ALLOW_TRUST_NO_TRUST_LINE): "trustor does not have a trustline", + int32(ALLOW_TRUST_TRUST_NOT_REQUIRED): "source account does not require trust", + int32(ALLOW_TRUST_CANT_REVOKE): "source account can't revoke trust,", + int32(ALLOW_TRUST_SELF_NOT_ALLOWED): "trusting self is not allowed", + int32(ALLOW_TRUST_LOW_RESERVE): "claimable balances can't be created", +} + +func (e AllowTrustResultCode) XdrEnumComments() map[int32]string { + return _XdrComments_AllowTrustResultCode +} + +var _XdrTags_AllowTrustResult = map[int32]bool{ + XdrToI32(ALLOW_TRUST_SUCCESS): true, + XdrToI32(ALLOW_TRUST_MALFORMED): true, + XdrToI32(ALLOW_TRUST_NO_TRUST_LINE): true, + XdrToI32(ALLOW_TRUST_TRUST_NOT_REQUIRED): true, + XdrToI32(ALLOW_TRUST_CANT_REVOKE): true, + XdrToI32(ALLOW_TRUST_SELF_NOT_ALLOWED): true, + XdrToI32(ALLOW_TRUST_LOW_RESERVE): true, +} + +func (_ AllowTrustResult) XdrValidTags() map[int32]bool { + return _XdrTags_AllowTrustResult +} +func (u AllowTrustResult) XdrValid() bool { + switch u.Code { + case ALLOW_TRUST_SUCCESS, ALLOW_TRUST_MALFORMED, ALLOW_TRUST_NO_TRUST_LINE, ALLOW_TRUST_TRUST_NOT_REQUIRED, ALLOW_TRUST_CANT_REVOKE, ALLOW_TRUST_SELF_NOT_ALLOWED, ALLOW_TRUST_LOW_RESERVE: + return true + } + return false +} +func (u *AllowTrustResult) XdrUnionTag() XdrNum32 { + return XDR_AllowTrustResultCode(&u.Code) +} +func (u *AllowTrustResult) XdrUnionTagName() string { + return "Code" +} +func (u *AllowTrustResult) XdrUnionBody() XdrType { + switch u.Code { + case ALLOW_TRUST_SUCCESS: + return nil + case ALLOW_TRUST_MALFORMED, ALLOW_TRUST_NO_TRUST_LINE, ALLOW_TRUST_TRUST_NOT_REQUIRED, ALLOW_TRUST_CANT_REVOKE, ALLOW_TRUST_SELF_NOT_ALLOWED, ALLOW_TRUST_LOW_RESERVE: + return nil + } + return nil +} +func (u *AllowTrustResult) XdrUnionBodyName() string { + switch u.Code { + case ALLOW_TRUST_SUCCESS: + return "" + case ALLOW_TRUST_MALFORMED, ALLOW_TRUST_NO_TRUST_LINE, ALLOW_TRUST_TRUST_NOT_REQUIRED, ALLOW_TRUST_CANT_REVOKE, ALLOW_TRUST_SELF_NOT_ALLOWED, ALLOW_TRUST_LOW_RESERVE: + return "" + } + return "" +} + +type XdrType_AllowTrustResult = *AllowTrustResult + +func (v *AllowTrustResult) XdrPointer() interface{} { return v } +func (AllowTrustResult) XdrTypeName() string { return "AllowTrustResult" } +func (v AllowTrustResult) XdrValue() interface{} { return v } +func (v *AllowTrustResult) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (u *AllowTrustResult) XdrRecurse(x XDR, name string) { + if name != "" { + name = x.Sprintf("%s.", name) + } + XDR_AllowTrustResultCode(&u.Code).XdrMarshal(x, x.Sprintf("%scode", name)) + switch u.Code { + case ALLOW_TRUST_SUCCESS: + return + case ALLOW_TRUST_MALFORMED, ALLOW_TRUST_NO_TRUST_LINE, ALLOW_TRUST_TRUST_NOT_REQUIRED, ALLOW_TRUST_CANT_REVOKE, ALLOW_TRUST_SELF_NOT_ALLOWED, ALLOW_TRUST_LOW_RESERVE: + return + } + XdrPanic("invalid Code (%v) in AllowTrustResult", u.Code) +} +func XDR_AllowTrustResult(v *AllowTrustResult) *AllowTrustResult { return v } + +var _XdrNames_AccountMergeResultCode = map[int32]string{ + int32(ACCOUNT_MERGE_SUCCESS): "ACCOUNT_MERGE_SUCCESS", + int32(ACCOUNT_MERGE_MALFORMED): "ACCOUNT_MERGE_MALFORMED", + int32(ACCOUNT_MERGE_NO_ACCOUNT): "ACCOUNT_MERGE_NO_ACCOUNT", + int32(ACCOUNT_MERGE_IMMUTABLE_SET): "ACCOUNT_MERGE_IMMUTABLE_SET", + int32(ACCOUNT_MERGE_HAS_SUB_ENTRIES): "ACCOUNT_MERGE_HAS_SUB_ENTRIES", + int32(ACCOUNT_MERGE_SEQNUM_TOO_FAR): "ACCOUNT_MERGE_SEQNUM_TOO_FAR", + int32(ACCOUNT_MERGE_DEST_FULL): "ACCOUNT_MERGE_DEST_FULL", + int32(ACCOUNT_MERGE_IS_SPONSOR): "ACCOUNT_MERGE_IS_SPONSOR", +} +var _XdrValues_AccountMergeResultCode = map[string]int32{ + "ACCOUNT_MERGE_SUCCESS": int32(ACCOUNT_MERGE_SUCCESS), + "ACCOUNT_MERGE_MALFORMED": int32(ACCOUNT_MERGE_MALFORMED), + "ACCOUNT_MERGE_NO_ACCOUNT": int32(ACCOUNT_MERGE_NO_ACCOUNT), + "ACCOUNT_MERGE_IMMUTABLE_SET": int32(ACCOUNT_MERGE_IMMUTABLE_SET), + "ACCOUNT_MERGE_HAS_SUB_ENTRIES": int32(ACCOUNT_MERGE_HAS_SUB_ENTRIES), + "ACCOUNT_MERGE_SEQNUM_TOO_FAR": int32(ACCOUNT_MERGE_SEQNUM_TOO_FAR), + "ACCOUNT_MERGE_DEST_FULL": int32(ACCOUNT_MERGE_DEST_FULL), + "ACCOUNT_MERGE_IS_SPONSOR": int32(ACCOUNT_MERGE_IS_SPONSOR), +} + +func (AccountMergeResultCode) XdrEnumNames() map[int32]string { + return _XdrNames_AccountMergeResultCode +} +func (v AccountMergeResultCode) String() string { + if s, ok := _XdrNames_AccountMergeResultCode[int32(v)]; ok { + return s + } + return fmt.Sprintf("AccountMergeResultCode#%d", v) +} +func (v *AccountMergeResultCode) Scan(ss fmt.ScanState, _ rune) error { + if tok, err := ss.Token(true, XdrSymChar); err != nil { + return err + } else { + stok := string(tok) + if val, ok := _XdrValues_AccountMergeResultCode[stok]; ok { + *v = AccountMergeResultCode(val) + return nil + } else if stok == "AccountMergeResultCode" { + if n, err := fmt.Fscanf(ss, "#%d", (*int32)(v)); n == 1 && err == nil { + return nil + } + } + return XdrError(fmt.Sprintf("%s is not a valid AccountMergeResultCode.", stok)) + } +} +func (v AccountMergeResultCode) GetU32() uint32 { return uint32(v) } +func (v *AccountMergeResultCode) SetU32(n uint32) { *v = AccountMergeResultCode(n) } +func (v *AccountMergeResultCode) XdrPointer() interface{} { return v } +func (AccountMergeResultCode) XdrTypeName() string { return "AccountMergeResultCode" } +func (v AccountMergeResultCode) XdrValue() interface{} { return v } +func (v *AccountMergeResultCode) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } + +type XdrType_AccountMergeResultCode = *AccountMergeResultCode + +func XDR_AccountMergeResultCode(v *AccountMergeResultCode) *AccountMergeResultCode { return v } + +var _XdrComments_AccountMergeResultCode = map[int32]string{ + int32(ACCOUNT_MERGE_SUCCESS): "codes considered as \"success\" for the operation", + int32(ACCOUNT_MERGE_MALFORMED): "can't merge onto itself", + int32(ACCOUNT_MERGE_NO_ACCOUNT): "destination does not exist", + int32(ACCOUNT_MERGE_IMMUTABLE_SET): "source account has AUTH_IMMUTABLE set", + int32(ACCOUNT_MERGE_HAS_SUB_ENTRIES): "account has trust lines/offers", + int32(ACCOUNT_MERGE_SEQNUM_TOO_FAR): "sequence number is over max allowed", + int32(ACCOUNT_MERGE_DEST_FULL): "can't add source balance to", + int32(ACCOUNT_MERGE_IS_SPONSOR): "destination balance", +} + +func (e AccountMergeResultCode) XdrEnumComments() map[int32]string { + return _XdrComments_AccountMergeResultCode +} + +var _XdrTags_AccountMergeResult = map[int32]bool{ + XdrToI32(ACCOUNT_MERGE_SUCCESS): true, + XdrToI32(ACCOUNT_MERGE_MALFORMED): true, + XdrToI32(ACCOUNT_MERGE_NO_ACCOUNT): true, + XdrToI32(ACCOUNT_MERGE_IMMUTABLE_SET): true, + XdrToI32(ACCOUNT_MERGE_HAS_SUB_ENTRIES): true, + XdrToI32(ACCOUNT_MERGE_SEQNUM_TOO_FAR): true, + XdrToI32(ACCOUNT_MERGE_DEST_FULL): true, + XdrToI32(ACCOUNT_MERGE_IS_SPONSOR): true, +} + +func (_ AccountMergeResult) XdrValidTags() map[int32]bool { + return _XdrTags_AccountMergeResult +} + +// how much got transferred from source account +func (u *AccountMergeResult) SourceAccountBalance() *Int64 { + switch u.Code { + case ACCOUNT_MERGE_SUCCESS: + if v, ok := u._u.(*Int64); ok { + return v + } else { + var zero Int64 + u._u = &zero + return &zero + } + default: + XdrPanic("AccountMergeResult.SourceAccountBalance accessed when Code == %v", u.Code) + return nil + } +} +func (u AccountMergeResult) XdrValid() bool { + switch u.Code { + case ACCOUNT_MERGE_SUCCESS, ACCOUNT_MERGE_MALFORMED, ACCOUNT_MERGE_NO_ACCOUNT, ACCOUNT_MERGE_IMMUTABLE_SET, ACCOUNT_MERGE_HAS_SUB_ENTRIES, ACCOUNT_MERGE_SEQNUM_TOO_FAR, ACCOUNT_MERGE_DEST_FULL, ACCOUNT_MERGE_IS_SPONSOR: + return true + } + return false +} +func (u *AccountMergeResult) XdrUnionTag() XdrNum32 { + return XDR_AccountMergeResultCode(&u.Code) +} +func (u *AccountMergeResult) XdrUnionTagName() string { + return "Code" +} +func (u *AccountMergeResult) XdrUnionBody() XdrType { + switch u.Code { + case ACCOUNT_MERGE_SUCCESS: + return XDR_Int64(u.SourceAccountBalance()) + case ACCOUNT_MERGE_MALFORMED, ACCOUNT_MERGE_NO_ACCOUNT, ACCOUNT_MERGE_IMMUTABLE_SET, ACCOUNT_MERGE_HAS_SUB_ENTRIES, ACCOUNT_MERGE_SEQNUM_TOO_FAR, ACCOUNT_MERGE_DEST_FULL, ACCOUNT_MERGE_IS_SPONSOR: + return nil + } + return nil +} +func (u *AccountMergeResult) XdrUnionBodyName() string { + switch u.Code { + case ACCOUNT_MERGE_SUCCESS: + return "SourceAccountBalance" + case ACCOUNT_MERGE_MALFORMED, ACCOUNT_MERGE_NO_ACCOUNT, ACCOUNT_MERGE_IMMUTABLE_SET, ACCOUNT_MERGE_HAS_SUB_ENTRIES, ACCOUNT_MERGE_SEQNUM_TOO_FAR, ACCOUNT_MERGE_DEST_FULL, ACCOUNT_MERGE_IS_SPONSOR: + return "" + } + return "" +} + +type XdrType_AccountMergeResult = *AccountMergeResult + +func (v *AccountMergeResult) XdrPointer() interface{} { return v } +func (AccountMergeResult) XdrTypeName() string { return "AccountMergeResult" } +func (v AccountMergeResult) XdrValue() interface{} { return v } +func (v *AccountMergeResult) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (u *AccountMergeResult) XdrRecurse(x XDR, name string) { + if name != "" { + name = x.Sprintf("%s.", name) + } + XDR_AccountMergeResultCode(&u.Code).XdrMarshal(x, x.Sprintf("%scode", name)) + switch u.Code { + case ACCOUNT_MERGE_SUCCESS: + x.Marshal(x.Sprintf("%ssourceAccountBalance", name), XDR_Int64(u.SourceAccountBalance())) + return + case ACCOUNT_MERGE_MALFORMED, ACCOUNT_MERGE_NO_ACCOUNT, ACCOUNT_MERGE_IMMUTABLE_SET, ACCOUNT_MERGE_HAS_SUB_ENTRIES, ACCOUNT_MERGE_SEQNUM_TOO_FAR, ACCOUNT_MERGE_DEST_FULL, ACCOUNT_MERGE_IS_SPONSOR: + return + } + XdrPanic("invalid Code (%v) in AccountMergeResult", u.Code) +} +func XDR_AccountMergeResult(v *AccountMergeResult) *AccountMergeResult { return v } + +var _XdrNames_InflationResultCode = map[int32]string{ + int32(INFLATION_SUCCESS): "INFLATION_SUCCESS", + int32(INFLATION_NOT_TIME): "INFLATION_NOT_TIME", +} +var _XdrValues_InflationResultCode = map[string]int32{ + "INFLATION_SUCCESS": int32(INFLATION_SUCCESS), + "INFLATION_NOT_TIME": int32(INFLATION_NOT_TIME), +} + +func (InflationResultCode) XdrEnumNames() map[int32]string { + return _XdrNames_InflationResultCode +} +func (v InflationResultCode) String() string { + if s, ok := _XdrNames_InflationResultCode[int32(v)]; ok { + return s + } + return fmt.Sprintf("InflationResultCode#%d", v) +} +func (v *InflationResultCode) Scan(ss fmt.ScanState, _ rune) error { + if tok, err := ss.Token(true, XdrSymChar); err != nil { + return err + } else { + stok := string(tok) + if val, ok := _XdrValues_InflationResultCode[stok]; ok { + *v = InflationResultCode(val) + return nil + } else if stok == "InflationResultCode" { + if n, err := fmt.Fscanf(ss, "#%d", (*int32)(v)); n == 1 && err == nil { + return nil + } + } + return XdrError(fmt.Sprintf("%s is not a valid InflationResultCode.", stok)) + } +} +func (v InflationResultCode) GetU32() uint32 { return uint32(v) } +func (v *InflationResultCode) SetU32(n uint32) { *v = InflationResultCode(n) } +func (v *InflationResultCode) XdrPointer() interface{} { return v } +func (InflationResultCode) XdrTypeName() string { return "InflationResultCode" } +func (v InflationResultCode) XdrValue() interface{} { return v } +func (v *InflationResultCode) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } + +type XdrType_InflationResultCode = *InflationResultCode + +func XDR_InflationResultCode(v *InflationResultCode) *InflationResultCode { return v } + +var _XdrComments_InflationResultCode = map[int32]string{ + int32(INFLATION_SUCCESS): "codes considered as \"success\" for the operation", + int32(INFLATION_NOT_TIME): "codes considered as \"failure\" for the operation", +} + +func (e InflationResultCode) XdrEnumComments() map[int32]string { + return _XdrComments_InflationResultCode +} + +type XdrType_InflationPayout = *InflationPayout + +func (v *InflationPayout) XdrPointer() interface{} { return v } +func (InflationPayout) XdrTypeName() string { return "InflationPayout" } +func (v InflationPayout) XdrValue() interface{} { return v } +func (v *InflationPayout) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v *InflationPayout) XdrRecurse(x XDR, name string) { + if name != "" { + name = x.Sprintf("%s.", name) + } + x.Marshal(x.Sprintf("%sdestination", name), XDR_AccountID(&v.Destination)) + x.Marshal(x.Sprintf("%samount", name), XDR_Int64(&v.Amount)) +} +func XDR_InflationPayout(v *InflationPayout) *InflationPayout { return v } + +type _XdrVec_unbounded_InflationPayout []InflationPayout + +func (_XdrVec_unbounded_InflationPayout) XdrBound() uint32 { + const bound uint32 = 4294967295 // Force error if not const or doesn't fit + return bound +} +func (_XdrVec_unbounded_InflationPayout) XdrCheckLen(length uint32) { + if length > uint32(4294967295) { + XdrPanic("_XdrVec_unbounded_InflationPayout length %d exceeds bound 4294967295", length) + } else if int(length) < 0 { + XdrPanic("_XdrVec_unbounded_InflationPayout length %d exceeds max int", length) + } +} +func (v _XdrVec_unbounded_InflationPayout) GetVecLen() uint32 { return uint32(len(v)) } +func (v *_XdrVec_unbounded_InflationPayout) SetVecLen(length uint32) { + v.XdrCheckLen(length) + if int(length) <= cap(*v) { + if int(length) != len(*v) { + *v = (*v)[:int(length)] + } + return + } + newcap := 2 * cap(*v) + if newcap < int(length) { // also catches overflow where 2*cap < 0 + newcap = int(length) + } else if bound := uint(4294967295); uint(newcap) > bound { + if int(bound) < 0 { + bound = ^uint(0) >> 1 + } + newcap = int(bound) + } + nv := make([]InflationPayout, int(length), newcap) + copy(nv, *v) + *v = nv +} +func (v *_XdrVec_unbounded_InflationPayout) XdrMarshalN(x XDR, name string, n uint32) { + v.XdrCheckLen(n) + for i := 0; i < int(n); i++ { + if i >= len(*v) { + v.SetVecLen(uint32(i + 1)) + } + XDR_InflationPayout(&(*v)[i]).XdrMarshal(x, x.Sprintf("%s[%d]", name, i)) + } + if int(n) < len(*v) { + *v = (*v)[:int(n)] + } +} +func (v *_XdrVec_unbounded_InflationPayout) XdrRecurse(x XDR, name string) { + size := XdrSize{Size: uint32(len(*v)), Bound: 4294967295} + x.Marshal(name, &size) + v.XdrMarshalN(x, name, size.Size) +} +func (_XdrVec_unbounded_InflationPayout) XdrTypeName() string { return "InflationPayout<>" } +func (v *_XdrVec_unbounded_InflationPayout) XdrPointer() interface{} { return (*[]InflationPayout)(v) } +func (v _XdrVec_unbounded_InflationPayout) XdrValue() interface{} { return ([]InflationPayout)(v) } +func (v *_XdrVec_unbounded_InflationPayout) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } + +var _XdrTags_InflationResult = map[int32]bool{ + XdrToI32(INFLATION_SUCCESS): true, + XdrToI32(INFLATION_NOT_TIME): true, +} + +func (_ InflationResult) XdrValidTags() map[int32]bool { + return _XdrTags_InflationResult +} +func (u *InflationResult) Payouts() *[]InflationPayout { + switch u.Code { + case INFLATION_SUCCESS: + if v, ok := u._u.(*[]InflationPayout); ok { + return v + } else { + var zero []InflationPayout + u._u = &zero + return &zero + } + default: + XdrPanic("InflationResult.Payouts accessed when Code == %v", u.Code) + return nil + } +} +func (u InflationResult) XdrValid() bool { + switch u.Code { + case INFLATION_SUCCESS, INFLATION_NOT_TIME: + return true + } + return false +} +func (u *InflationResult) XdrUnionTag() XdrNum32 { + return XDR_InflationResultCode(&u.Code) +} +func (u *InflationResult) XdrUnionTagName() string { + return "Code" +} +func (u *InflationResult) XdrUnionBody() XdrType { + switch u.Code { + case INFLATION_SUCCESS: + return (*_XdrVec_unbounded_InflationPayout)(u.Payouts()) + case INFLATION_NOT_TIME: + return nil + } + return nil +} +func (u *InflationResult) XdrUnionBodyName() string { + switch u.Code { + case INFLATION_SUCCESS: + return "Payouts" + case INFLATION_NOT_TIME: + return "" + } + return "" +} + +type XdrType_InflationResult = *InflationResult + +func (v *InflationResult) XdrPointer() interface{} { return v } +func (InflationResult) XdrTypeName() string { return "InflationResult" } +func (v InflationResult) XdrValue() interface{} { return v } +func (v *InflationResult) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (u *InflationResult) XdrRecurse(x XDR, name string) { + if name != "" { + name = x.Sprintf("%s.", name) + } + XDR_InflationResultCode(&u.Code).XdrMarshal(x, x.Sprintf("%scode", name)) + switch u.Code { + case INFLATION_SUCCESS: + x.Marshal(x.Sprintf("%spayouts", name), (*_XdrVec_unbounded_InflationPayout)(u.Payouts())) + return + case INFLATION_NOT_TIME: + return + } + XdrPanic("invalid Code (%v) in InflationResult", u.Code) +} +func XDR_InflationResult(v *InflationResult) *InflationResult { return v } + +var _XdrNames_ManageDataResultCode = map[int32]string{ + int32(MANAGE_DATA_SUCCESS): "MANAGE_DATA_SUCCESS", + int32(MANAGE_DATA_NOT_SUPPORTED_YET): "MANAGE_DATA_NOT_SUPPORTED_YET", + int32(MANAGE_DATA_NAME_NOT_FOUND): "MANAGE_DATA_NAME_NOT_FOUND", + int32(MANAGE_DATA_LOW_RESERVE): "MANAGE_DATA_LOW_RESERVE", + int32(MANAGE_DATA_INVALID_NAME): "MANAGE_DATA_INVALID_NAME", +} +var _XdrValues_ManageDataResultCode = map[string]int32{ + "MANAGE_DATA_SUCCESS": int32(MANAGE_DATA_SUCCESS), + "MANAGE_DATA_NOT_SUPPORTED_YET": int32(MANAGE_DATA_NOT_SUPPORTED_YET), + "MANAGE_DATA_NAME_NOT_FOUND": int32(MANAGE_DATA_NAME_NOT_FOUND), + "MANAGE_DATA_LOW_RESERVE": int32(MANAGE_DATA_LOW_RESERVE), + "MANAGE_DATA_INVALID_NAME": int32(MANAGE_DATA_INVALID_NAME), +} + +func (ManageDataResultCode) XdrEnumNames() map[int32]string { + return _XdrNames_ManageDataResultCode +} +func (v ManageDataResultCode) String() string { + if s, ok := _XdrNames_ManageDataResultCode[int32(v)]; ok { + return s + } + return fmt.Sprintf("ManageDataResultCode#%d", v) +} +func (v *ManageDataResultCode) Scan(ss fmt.ScanState, _ rune) error { + if tok, err := ss.Token(true, XdrSymChar); err != nil { + return err + } else { + stok := string(tok) + if val, ok := _XdrValues_ManageDataResultCode[stok]; ok { + *v = ManageDataResultCode(val) + return nil + } else if stok == "ManageDataResultCode" { + if n, err := fmt.Fscanf(ss, "#%d", (*int32)(v)); n == 1 && err == nil { + return nil + } + } + return XdrError(fmt.Sprintf("%s is not a valid ManageDataResultCode.", stok)) + } +} +func (v ManageDataResultCode) GetU32() uint32 { return uint32(v) } +func (v *ManageDataResultCode) SetU32(n uint32) { *v = ManageDataResultCode(n) } +func (v *ManageDataResultCode) XdrPointer() interface{} { return v } +func (ManageDataResultCode) XdrTypeName() string { return "ManageDataResultCode" } +func (v ManageDataResultCode) XdrValue() interface{} { return v } +func (v *ManageDataResultCode) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } + +type XdrType_ManageDataResultCode = *ManageDataResultCode + +func XDR_ManageDataResultCode(v *ManageDataResultCode) *ManageDataResultCode { return v } + +var _XdrComments_ManageDataResultCode = map[int32]string{ + int32(MANAGE_DATA_SUCCESS): "codes considered as \"success\" for the operation", + int32(MANAGE_DATA_NOT_SUPPORTED_YET): "The network hasn't moved to this protocol change yet", + int32(MANAGE_DATA_NAME_NOT_FOUND): "Trying to remove a Data Entry that isn't there", + int32(MANAGE_DATA_LOW_RESERVE): "not enough funds to create a new Data Entry", + int32(MANAGE_DATA_INVALID_NAME): "Name not a valid string", +} + +func (e ManageDataResultCode) XdrEnumComments() map[int32]string { + return _XdrComments_ManageDataResultCode +} + +var _XdrTags_ManageDataResult = map[int32]bool{ + XdrToI32(MANAGE_DATA_SUCCESS): true, + XdrToI32(MANAGE_DATA_NOT_SUPPORTED_YET): true, + XdrToI32(MANAGE_DATA_NAME_NOT_FOUND): true, + XdrToI32(MANAGE_DATA_LOW_RESERVE): true, + XdrToI32(MANAGE_DATA_INVALID_NAME): true, +} + +func (_ ManageDataResult) XdrValidTags() map[int32]bool { + return _XdrTags_ManageDataResult +} +func (u ManageDataResult) XdrValid() bool { + switch u.Code { + case MANAGE_DATA_SUCCESS, MANAGE_DATA_NOT_SUPPORTED_YET, MANAGE_DATA_NAME_NOT_FOUND, MANAGE_DATA_LOW_RESERVE, MANAGE_DATA_INVALID_NAME: + return true + } + return false +} +func (u *ManageDataResult) XdrUnionTag() XdrNum32 { + return XDR_ManageDataResultCode(&u.Code) +} +func (u *ManageDataResult) XdrUnionTagName() string { + return "Code" +} +func (u *ManageDataResult) XdrUnionBody() XdrType { + switch u.Code { + case MANAGE_DATA_SUCCESS: + return nil + case MANAGE_DATA_NOT_SUPPORTED_YET, MANAGE_DATA_NAME_NOT_FOUND, MANAGE_DATA_LOW_RESERVE, MANAGE_DATA_INVALID_NAME: + return nil + } + return nil +} +func (u *ManageDataResult) XdrUnionBodyName() string { + switch u.Code { + case MANAGE_DATA_SUCCESS: + return "" + case MANAGE_DATA_NOT_SUPPORTED_YET, MANAGE_DATA_NAME_NOT_FOUND, MANAGE_DATA_LOW_RESERVE, MANAGE_DATA_INVALID_NAME: + return "" + } + return "" +} + +type XdrType_ManageDataResult = *ManageDataResult + +func (v *ManageDataResult) XdrPointer() interface{} { return v } +func (ManageDataResult) XdrTypeName() string { return "ManageDataResult" } +func (v ManageDataResult) XdrValue() interface{} { return v } +func (v *ManageDataResult) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (u *ManageDataResult) XdrRecurse(x XDR, name string) { + if name != "" { + name = x.Sprintf("%s.", name) + } + XDR_ManageDataResultCode(&u.Code).XdrMarshal(x, x.Sprintf("%scode", name)) + switch u.Code { + case MANAGE_DATA_SUCCESS: + return + case MANAGE_DATA_NOT_SUPPORTED_YET, MANAGE_DATA_NAME_NOT_FOUND, MANAGE_DATA_LOW_RESERVE, MANAGE_DATA_INVALID_NAME: + return + } + XdrPanic("invalid Code (%v) in ManageDataResult", u.Code) +} +func XDR_ManageDataResult(v *ManageDataResult) *ManageDataResult { return v } + +var _XdrNames_BumpSequenceResultCode = map[int32]string{ + int32(BUMP_SEQUENCE_SUCCESS): "BUMP_SEQUENCE_SUCCESS", + int32(BUMP_SEQUENCE_BAD_SEQ): "BUMP_SEQUENCE_BAD_SEQ", +} +var _XdrValues_BumpSequenceResultCode = map[string]int32{ + "BUMP_SEQUENCE_SUCCESS": int32(BUMP_SEQUENCE_SUCCESS), + "BUMP_SEQUENCE_BAD_SEQ": int32(BUMP_SEQUENCE_BAD_SEQ), +} + +func (BumpSequenceResultCode) XdrEnumNames() map[int32]string { + return _XdrNames_BumpSequenceResultCode +} +func (v BumpSequenceResultCode) String() string { + if s, ok := _XdrNames_BumpSequenceResultCode[int32(v)]; ok { + return s + } + return fmt.Sprintf("BumpSequenceResultCode#%d", v) +} +func (v *BumpSequenceResultCode) Scan(ss fmt.ScanState, _ rune) error { + if tok, err := ss.Token(true, XdrSymChar); err != nil { + return err + } else { + stok := string(tok) + if val, ok := _XdrValues_BumpSequenceResultCode[stok]; ok { + *v = BumpSequenceResultCode(val) + return nil + } else if stok == "BumpSequenceResultCode" { + if n, err := fmt.Fscanf(ss, "#%d", (*int32)(v)); n == 1 && err == nil { + return nil + } + } + return XdrError(fmt.Sprintf("%s is not a valid BumpSequenceResultCode.", stok)) + } +} +func (v BumpSequenceResultCode) GetU32() uint32 { return uint32(v) } +func (v *BumpSequenceResultCode) SetU32(n uint32) { *v = BumpSequenceResultCode(n) } +func (v *BumpSequenceResultCode) XdrPointer() interface{} { return v } +func (BumpSequenceResultCode) XdrTypeName() string { return "BumpSequenceResultCode" } +func (v BumpSequenceResultCode) XdrValue() interface{} { return v } +func (v *BumpSequenceResultCode) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } + +type XdrType_BumpSequenceResultCode = *BumpSequenceResultCode + +func XDR_BumpSequenceResultCode(v *BumpSequenceResultCode) *BumpSequenceResultCode { return v } + +var _XdrComments_BumpSequenceResultCode = map[int32]string{ + int32(BUMP_SEQUENCE_SUCCESS): "codes considered as \"success\" for the operation", + int32(BUMP_SEQUENCE_BAD_SEQ): "codes considered as \"failure\" for the operation", +} + +func (e BumpSequenceResultCode) XdrEnumComments() map[int32]string { + return _XdrComments_BumpSequenceResultCode +} + +var _XdrTags_BumpSequenceResult = map[int32]bool{ + XdrToI32(BUMP_SEQUENCE_SUCCESS): true, + XdrToI32(BUMP_SEQUENCE_BAD_SEQ): true, +} + +func (_ BumpSequenceResult) XdrValidTags() map[int32]bool { + return _XdrTags_BumpSequenceResult +} +func (u BumpSequenceResult) XdrValid() bool { + switch u.Code { + case BUMP_SEQUENCE_SUCCESS, BUMP_SEQUENCE_BAD_SEQ: + return true + } + return false +} +func (u *BumpSequenceResult) XdrUnionTag() XdrNum32 { + return XDR_BumpSequenceResultCode(&u.Code) +} +func (u *BumpSequenceResult) XdrUnionTagName() string { + return "Code" +} +func (u *BumpSequenceResult) XdrUnionBody() XdrType { + switch u.Code { + case BUMP_SEQUENCE_SUCCESS: + return nil + case BUMP_SEQUENCE_BAD_SEQ: + return nil + } + return nil +} +func (u *BumpSequenceResult) XdrUnionBodyName() string { + switch u.Code { + case BUMP_SEQUENCE_SUCCESS: + return "" + case BUMP_SEQUENCE_BAD_SEQ: + return "" + } + return "" +} + +type XdrType_BumpSequenceResult = *BumpSequenceResult + +func (v *BumpSequenceResult) XdrPointer() interface{} { return v } +func (BumpSequenceResult) XdrTypeName() string { return "BumpSequenceResult" } +func (v BumpSequenceResult) XdrValue() interface{} { return v } +func (v *BumpSequenceResult) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (u *BumpSequenceResult) XdrRecurse(x XDR, name string) { + if name != "" { + name = x.Sprintf("%s.", name) + } + XDR_BumpSequenceResultCode(&u.Code).XdrMarshal(x, x.Sprintf("%scode", name)) + switch u.Code { + case BUMP_SEQUENCE_SUCCESS: + return + case BUMP_SEQUENCE_BAD_SEQ: + return + } + XdrPanic("invalid Code (%v) in BumpSequenceResult", u.Code) +} +func XDR_BumpSequenceResult(v *BumpSequenceResult) *BumpSequenceResult { return v } + +var _XdrNames_CreateClaimableBalanceResultCode = map[int32]string{ + int32(CREATE_CLAIMABLE_BALANCE_SUCCESS): "CREATE_CLAIMABLE_BALANCE_SUCCESS", + int32(CREATE_CLAIMABLE_BALANCE_MALFORMED): "CREATE_CLAIMABLE_BALANCE_MALFORMED", + int32(CREATE_CLAIMABLE_BALANCE_LOW_RESERVE): "CREATE_CLAIMABLE_BALANCE_LOW_RESERVE", + int32(CREATE_CLAIMABLE_BALANCE_NO_TRUST): "CREATE_CLAIMABLE_BALANCE_NO_TRUST", + int32(CREATE_CLAIMABLE_BALANCE_NOT_AUTHORIZED): "CREATE_CLAIMABLE_BALANCE_NOT_AUTHORIZED", + int32(CREATE_CLAIMABLE_BALANCE_UNDERFUNDED): "CREATE_CLAIMABLE_BALANCE_UNDERFUNDED", +} +var _XdrValues_CreateClaimableBalanceResultCode = map[string]int32{ + "CREATE_CLAIMABLE_BALANCE_SUCCESS": int32(CREATE_CLAIMABLE_BALANCE_SUCCESS), + "CREATE_CLAIMABLE_BALANCE_MALFORMED": int32(CREATE_CLAIMABLE_BALANCE_MALFORMED), + "CREATE_CLAIMABLE_BALANCE_LOW_RESERVE": int32(CREATE_CLAIMABLE_BALANCE_LOW_RESERVE), + "CREATE_CLAIMABLE_BALANCE_NO_TRUST": int32(CREATE_CLAIMABLE_BALANCE_NO_TRUST), + "CREATE_CLAIMABLE_BALANCE_NOT_AUTHORIZED": int32(CREATE_CLAIMABLE_BALANCE_NOT_AUTHORIZED), + "CREATE_CLAIMABLE_BALANCE_UNDERFUNDED": int32(CREATE_CLAIMABLE_BALANCE_UNDERFUNDED), +} + +func (CreateClaimableBalanceResultCode) XdrEnumNames() map[int32]string { + return _XdrNames_CreateClaimableBalanceResultCode +} +func (v CreateClaimableBalanceResultCode) String() string { + if s, ok := _XdrNames_CreateClaimableBalanceResultCode[int32(v)]; ok { + return s + } + return fmt.Sprintf("CreateClaimableBalanceResultCode#%d", v) +} +func (v *CreateClaimableBalanceResultCode) Scan(ss fmt.ScanState, _ rune) error { + if tok, err := ss.Token(true, XdrSymChar); err != nil { + return err + } else { + stok := string(tok) + if val, ok := _XdrValues_CreateClaimableBalanceResultCode[stok]; ok { + *v = CreateClaimableBalanceResultCode(val) + return nil + } else if stok == "CreateClaimableBalanceResultCode" { + if n, err := fmt.Fscanf(ss, "#%d", (*int32)(v)); n == 1 && err == nil { + return nil + } + } + return XdrError(fmt.Sprintf("%s is not a valid CreateClaimableBalanceResultCode.", stok)) + } +} +func (v CreateClaimableBalanceResultCode) GetU32() uint32 { return uint32(v) } +func (v *CreateClaimableBalanceResultCode) SetU32(n uint32) { *v = CreateClaimableBalanceResultCode(n) } +func (v *CreateClaimableBalanceResultCode) XdrPointer() interface{} { return v } +func (CreateClaimableBalanceResultCode) XdrTypeName() string { + return "CreateClaimableBalanceResultCode" +} +func (v CreateClaimableBalanceResultCode) XdrValue() interface{} { return v } +func (v *CreateClaimableBalanceResultCode) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } + +type XdrType_CreateClaimableBalanceResultCode = *CreateClaimableBalanceResultCode + +func XDR_CreateClaimableBalanceResultCode(v *CreateClaimableBalanceResultCode) *CreateClaimableBalanceResultCode { + return v +} + +var _XdrTags_CreateClaimableBalanceResult = map[int32]bool{ + XdrToI32(CREATE_CLAIMABLE_BALANCE_SUCCESS): true, + XdrToI32(CREATE_CLAIMABLE_BALANCE_MALFORMED): true, + XdrToI32(CREATE_CLAIMABLE_BALANCE_LOW_RESERVE): true, + XdrToI32(CREATE_CLAIMABLE_BALANCE_NO_TRUST): true, + XdrToI32(CREATE_CLAIMABLE_BALANCE_NOT_AUTHORIZED): true, + XdrToI32(CREATE_CLAIMABLE_BALANCE_UNDERFUNDED): true, +} + +func (_ CreateClaimableBalanceResult) XdrValidTags() map[int32]bool { + return _XdrTags_CreateClaimableBalanceResult +} +func (u *CreateClaimableBalanceResult) BalanceID() *ClaimableBalanceID { + switch u.Code { + case CREATE_CLAIMABLE_BALANCE_SUCCESS: + if v, ok := u._u.(*ClaimableBalanceID); ok { + return v + } else { + var zero ClaimableBalanceID + u._u = &zero + return &zero + } + default: + XdrPanic("CreateClaimableBalanceResult.BalanceID accessed when Code == %v", u.Code) + return nil + } +} +func (u CreateClaimableBalanceResult) XdrValid() bool { + switch u.Code { + case CREATE_CLAIMABLE_BALANCE_SUCCESS, CREATE_CLAIMABLE_BALANCE_MALFORMED, CREATE_CLAIMABLE_BALANCE_LOW_RESERVE, CREATE_CLAIMABLE_BALANCE_NO_TRUST, CREATE_CLAIMABLE_BALANCE_NOT_AUTHORIZED, CREATE_CLAIMABLE_BALANCE_UNDERFUNDED: + return true + } + return false +} +func (u *CreateClaimableBalanceResult) XdrUnionTag() XdrNum32 { + return XDR_CreateClaimableBalanceResultCode(&u.Code) +} +func (u *CreateClaimableBalanceResult) XdrUnionTagName() string { + return "Code" +} +func (u *CreateClaimableBalanceResult) XdrUnionBody() XdrType { + switch u.Code { + case CREATE_CLAIMABLE_BALANCE_SUCCESS: + return XDR_ClaimableBalanceID(u.BalanceID()) + case CREATE_CLAIMABLE_BALANCE_MALFORMED, CREATE_CLAIMABLE_BALANCE_LOW_RESERVE, CREATE_CLAIMABLE_BALANCE_NO_TRUST, CREATE_CLAIMABLE_BALANCE_NOT_AUTHORIZED, CREATE_CLAIMABLE_BALANCE_UNDERFUNDED: + return nil + } + return nil +} +func (u *CreateClaimableBalanceResult) XdrUnionBodyName() string { + switch u.Code { + case CREATE_CLAIMABLE_BALANCE_SUCCESS: + return "BalanceID" + case CREATE_CLAIMABLE_BALANCE_MALFORMED, CREATE_CLAIMABLE_BALANCE_LOW_RESERVE, CREATE_CLAIMABLE_BALANCE_NO_TRUST, CREATE_CLAIMABLE_BALANCE_NOT_AUTHORIZED, CREATE_CLAIMABLE_BALANCE_UNDERFUNDED: + return "" + } + return "" +} + +type XdrType_CreateClaimableBalanceResult = *CreateClaimableBalanceResult + +func (v *CreateClaimableBalanceResult) XdrPointer() interface{} { return v } +func (CreateClaimableBalanceResult) XdrTypeName() string { return "CreateClaimableBalanceResult" } +func (v CreateClaimableBalanceResult) XdrValue() interface{} { return v } +func (v *CreateClaimableBalanceResult) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (u *CreateClaimableBalanceResult) XdrRecurse(x XDR, name string) { + if name != "" { + name = x.Sprintf("%s.", name) + } + XDR_CreateClaimableBalanceResultCode(&u.Code).XdrMarshal(x, x.Sprintf("%scode", name)) + switch u.Code { + case CREATE_CLAIMABLE_BALANCE_SUCCESS: + x.Marshal(x.Sprintf("%sbalanceID", name), XDR_ClaimableBalanceID(u.BalanceID())) + return + case CREATE_CLAIMABLE_BALANCE_MALFORMED, CREATE_CLAIMABLE_BALANCE_LOW_RESERVE, CREATE_CLAIMABLE_BALANCE_NO_TRUST, CREATE_CLAIMABLE_BALANCE_NOT_AUTHORIZED, CREATE_CLAIMABLE_BALANCE_UNDERFUNDED: + return + } + XdrPanic("invalid Code (%v) in CreateClaimableBalanceResult", u.Code) +} +func XDR_CreateClaimableBalanceResult(v *CreateClaimableBalanceResult) *CreateClaimableBalanceResult { + return v +} + +var _XdrNames_ClaimClaimableBalanceResultCode = map[int32]string{ + int32(CLAIM_CLAIMABLE_BALANCE_SUCCESS): "CLAIM_CLAIMABLE_BALANCE_SUCCESS", + int32(CLAIM_CLAIMABLE_BALANCE_DOES_NOT_EXIST): "CLAIM_CLAIMABLE_BALANCE_DOES_NOT_EXIST", + int32(CLAIM_CLAIMABLE_BALANCE_CANNOT_CLAIM): "CLAIM_CLAIMABLE_BALANCE_CANNOT_CLAIM", + int32(CLAIM_CLAIMABLE_BALANCE_LINE_FULL): "CLAIM_CLAIMABLE_BALANCE_LINE_FULL", + int32(CLAIM_CLAIMABLE_BALANCE_NO_TRUST): "CLAIM_CLAIMABLE_BALANCE_NO_TRUST", + int32(CLAIM_CLAIMABLE_BALANCE_NOT_AUTHORIZED): "CLAIM_CLAIMABLE_BALANCE_NOT_AUTHORIZED", +} +var _XdrValues_ClaimClaimableBalanceResultCode = map[string]int32{ + "CLAIM_CLAIMABLE_BALANCE_SUCCESS": int32(CLAIM_CLAIMABLE_BALANCE_SUCCESS), + "CLAIM_CLAIMABLE_BALANCE_DOES_NOT_EXIST": int32(CLAIM_CLAIMABLE_BALANCE_DOES_NOT_EXIST), + "CLAIM_CLAIMABLE_BALANCE_CANNOT_CLAIM": int32(CLAIM_CLAIMABLE_BALANCE_CANNOT_CLAIM), + "CLAIM_CLAIMABLE_BALANCE_LINE_FULL": int32(CLAIM_CLAIMABLE_BALANCE_LINE_FULL), + "CLAIM_CLAIMABLE_BALANCE_NO_TRUST": int32(CLAIM_CLAIMABLE_BALANCE_NO_TRUST), + "CLAIM_CLAIMABLE_BALANCE_NOT_AUTHORIZED": int32(CLAIM_CLAIMABLE_BALANCE_NOT_AUTHORIZED), +} + +func (ClaimClaimableBalanceResultCode) XdrEnumNames() map[int32]string { + return _XdrNames_ClaimClaimableBalanceResultCode +} +func (v ClaimClaimableBalanceResultCode) String() string { + if s, ok := _XdrNames_ClaimClaimableBalanceResultCode[int32(v)]; ok { + return s + } + return fmt.Sprintf("ClaimClaimableBalanceResultCode#%d", v) +} +func (v *ClaimClaimableBalanceResultCode) Scan(ss fmt.ScanState, _ rune) error { + if tok, err := ss.Token(true, XdrSymChar); err != nil { + return err + } else { + stok := string(tok) + if val, ok := _XdrValues_ClaimClaimableBalanceResultCode[stok]; ok { + *v = ClaimClaimableBalanceResultCode(val) + return nil + } else if stok == "ClaimClaimableBalanceResultCode" { + if n, err := fmt.Fscanf(ss, "#%d", (*int32)(v)); n == 1 && err == nil { + return nil + } + } + return XdrError(fmt.Sprintf("%s is not a valid ClaimClaimableBalanceResultCode.", stok)) + } +} +func (v ClaimClaimableBalanceResultCode) GetU32() uint32 { return uint32(v) } +func (v *ClaimClaimableBalanceResultCode) SetU32(n uint32) { *v = ClaimClaimableBalanceResultCode(n) } +func (v *ClaimClaimableBalanceResultCode) XdrPointer() interface{} { return v } +func (ClaimClaimableBalanceResultCode) XdrTypeName() string { return "ClaimClaimableBalanceResultCode" } +func (v ClaimClaimableBalanceResultCode) XdrValue() interface{} { return v } +func (v *ClaimClaimableBalanceResultCode) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } + +type XdrType_ClaimClaimableBalanceResultCode = *ClaimClaimableBalanceResultCode + +func XDR_ClaimClaimableBalanceResultCode(v *ClaimClaimableBalanceResultCode) *ClaimClaimableBalanceResultCode { + return v +} + +var _XdrTags_ClaimClaimableBalanceResult = map[int32]bool{ + XdrToI32(CLAIM_CLAIMABLE_BALANCE_SUCCESS): true, + XdrToI32(CLAIM_CLAIMABLE_BALANCE_DOES_NOT_EXIST): true, + XdrToI32(CLAIM_CLAIMABLE_BALANCE_CANNOT_CLAIM): true, + XdrToI32(CLAIM_CLAIMABLE_BALANCE_LINE_FULL): true, + XdrToI32(CLAIM_CLAIMABLE_BALANCE_NO_TRUST): true, + XdrToI32(CLAIM_CLAIMABLE_BALANCE_NOT_AUTHORIZED): true, +} + +func (_ ClaimClaimableBalanceResult) XdrValidTags() map[int32]bool { + return _XdrTags_ClaimClaimableBalanceResult +} +func (u ClaimClaimableBalanceResult) XdrValid() bool { + switch u.Code { + case CLAIM_CLAIMABLE_BALANCE_SUCCESS, CLAIM_CLAIMABLE_BALANCE_DOES_NOT_EXIST, CLAIM_CLAIMABLE_BALANCE_CANNOT_CLAIM, CLAIM_CLAIMABLE_BALANCE_LINE_FULL, CLAIM_CLAIMABLE_BALANCE_NO_TRUST, CLAIM_CLAIMABLE_BALANCE_NOT_AUTHORIZED: + return true + } + return false +} +func (u *ClaimClaimableBalanceResult) XdrUnionTag() XdrNum32 { + return XDR_ClaimClaimableBalanceResultCode(&u.Code) +} +func (u *ClaimClaimableBalanceResult) XdrUnionTagName() string { + return "Code" +} +func (u *ClaimClaimableBalanceResult) XdrUnionBody() XdrType { + switch u.Code { + case CLAIM_CLAIMABLE_BALANCE_SUCCESS: + return nil + case CLAIM_CLAIMABLE_BALANCE_DOES_NOT_EXIST, CLAIM_CLAIMABLE_BALANCE_CANNOT_CLAIM, CLAIM_CLAIMABLE_BALANCE_LINE_FULL, CLAIM_CLAIMABLE_BALANCE_NO_TRUST, CLAIM_CLAIMABLE_BALANCE_NOT_AUTHORIZED: + return nil + } + return nil +} +func (u *ClaimClaimableBalanceResult) XdrUnionBodyName() string { + switch u.Code { + case CLAIM_CLAIMABLE_BALANCE_SUCCESS: + return "" + case CLAIM_CLAIMABLE_BALANCE_DOES_NOT_EXIST, CLAIM_CLAIMABLE_BALANCE_CANNOT_CLAIM, CLAIM_CLAIMABLE_BALANCE_LINE_FULL, CLAIM_CLAIMABLE_BALANCE_NO_TRUST, CLAIM_CLAIMABLE_BALANCE_NOT_AUTHORIZED: + return "" + } + return "" +} + +type XdrType_ClaimClaimableBalanceResult = *ClaimClaimableBalanceResult + +func (v *ClaimClaimableBalanceResult) XdrPointer() interface{} { return v } +func (ClaimClaimableBalanceResult) XdrTypeName() string { return "ClaimClaimableBalanceResult" } +func (v ClaimClaimableBalanceResult) XdrValue() interface{} { return v } +func (v *ClaimClaimableBalanceResult) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (u *ClaimClaimableBalanceResult) XdrRecurse(x XDR, name string) { + if name != "" { + name = x.Sprintf("%s.", name) + } + XDR_ClaimClaimableBalanceResultCode(&u.Code).XdrMarshal(x, x.Sprintf("%scode", name)) + switch u.Code { + case CLAIM_CLAIMABLE_BALANCE_SUCCESS: + return + case CLAIM_CLAIMABLE_BALANCE_DOES_NOT_EXIST, CLAIM_CLAIMABLE_BALANCE_CANNOT_CLAIM, CLAIM_CLAIMABLE_BALANCE_LINE_FULL, CLAIM_CLAIMABLE_BALANCE_NO_TRUST, CLAIM_CLAIMABLE_BALANCE_NOT_AUTHORIZED: + return + } + XdrPanic("invalid Code (%v) in ClaimClaimableBalanceResult", u.Code) +} +func XDR_ClaimClaimableBalanceResult(v *ClaimClaimableBalanceResult) *ClaimClaimableBalanceResult { + return v +} + +var _XdrNames_BeginSponsoringFutureReservesResultCode = map[int32]string{ + int32(BEGIN_SPONSORING_FUTURE_RESERVES_SUCCESS): "BEGIN_SPONSORING_FUTURE_RESERVES_SUCCESS", + int32(BEGIN_SPONSORING_FUTURE_RESERVES_MALFORMED): "BEGIN_SPONSORING_FUTURE_RESERVES_MALFORMED", + int32(BEGIN_SPONSORING_FUTURE_RESERVES_ALREADY_SPONSORED): "BEGIN_SPONSORING_FUTURE_RESERVES_ALREADY_SPONSORED", + int32(BEGIN_SPONSORING_FUTURE_RESERVES_RECURSIVE): "BEGIN_SPONSORING_FUTURE_RESERVES_RECURSIVE", +} +var _XdrValues_BeginSponsoringFutureReservesResultCode = map[string]int32{ + "BEGIN_SPONSORING_FUTURE_RESERVES_SUCCESS": int32(BEGIN_SPONSORING_FUTURE_RESERVES_SUCCESS), + "BEGIN_SPONSORING_FUTURE_RESERVES_MALFORMED": int32(BEGIN_SPONSORING_FUTURE_RESERVES_MALFORMED), + "BEGIN_SPONSORING_FUTURE_RESERVES_ALREADY_SPONSORED": int32(BEGIN_SPONSORING_FUTURE_RESERVES_ALREADY_SPONSORED), + "BEGIN_SPONSORING_FUTURE_RESERVES_RECURSIVE": int32(BEGIN_SPONSORING_FUTURE_RESERVES_RECURSIVE), +} + +func (BeginSponsoringFutureReservesResultCode) XdrEnumNames() map[int32]string { + return _XdrNames_BeginSponsoringFutureReservesResultCode +} +func (v BeginSponsoringFutureReservesResultCode) String() string { + if s, ok := _XdrNames_BeginSponsoringFutureReservesResultCode[int32(v)]; ok { + return s + } + return fmt.Sprintf("BeginSponsoringFutureReservesResultCode#%d", v) +} +func (v *BeginSponsoringFutureReservesResultCode) Scan(ss fmt.ScanState, _ rune) error { + if tok, err := ss.Token(true, XdrSymChar); err != nil { + return err + } else { + stok := string(tok) + if val, ok := _XdrValues_BeginSponsoringFutureReservesResultCode[stok]; ok { + *v = BeginSponsoringFutureReservesResultCode(val) + return nil + } else if stok == "BeginSponsoringFutureReservesResultCode" { + if n, err := fmt.Fscanf(ss, "#%d", (*int32)(v)); n == 1 && err == nil { + return nil + } + } + return XdrError(fmt.Sprintf("%s is not a valid BeginSponsoringFutureReservesResultCode.", stok)) + } +} +func (v BeginSponsoringFutureReservesResultCode) GetU32() uint32 { return uint32(v) } +func (v *BeginSponsoringFutureReservesResultCode) SetU32(n uint32) { + *v = BeginSponsoringFutureReservesResultCode(n) +} +func (v *BeginSponsoringFutureReservesResultCode) XdrPointer() interface{} { return v } +func (BeginSponsoringFutureReservesResultCode) XdrTypeName() string { + return "BeginSponsoringFutureReservesResultCode" +} +func (v BeginSponsoringFutureReservesResultCode) XdrValue() interface{} { return v } +func (v *BeginSponsoringFutureReservesResultCode) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } + +type XdrType_BeginSponsoringFutureReservesResultCode = *BeginSponsoringFutureReservesResultCode + +func XDR_BeginSponsoringFutureReservesResultCode(v *BeginSponsoringFutureReservesResultCode) *BeginSponsoringFutureReservesResultCode { + return v +} + +var _XdrComments_BeginSponsoringFutureReservesResultCode = map[int32]string{ + int32(BEGIN_SPONSORING_FUTURE_RESERVES_SUCCESS): "codes considered as \"success\" for the operation", + int32(BEGIN_SPONSORING_FUTURE_RESERVES_MALFORMED): "codes considered as \"failure\" for the operation", +} + +func (e BeginSponsoringFutureReservesResultCode) XdrEnumComments() map[int32]string { + return _XdrComments_BeginSponsoringFutureReservesResultCode +} + +var _XdrTags_BeginSponsoringFutureReservesResult = map[int32]bool{ + XdrToI32(BEGIN_SPONSORING_FUTURE_RESERVES_SUCCESS): true, + XdrToI32(BEGIN_SPONSORING_FUTURE_RESERVES_MALFORMED): true, + XdrToI32(BEGIN_SPONSORING_FUTURE_RESERVES_ALREADY_SPONSORED): true, + XdrToI32(BEGIN_SPONSORING_FUTURE_RESERVES_RECURSIVE): true, +} + +func (_ BeginSponsoringFutureReservesResult) XdrValidTags() map[int32]bool { + return _XdrTags_BeginSponsoringFutureReservesResult +} +func (u BeginSponsoringFutureReservesResult) XdrValid() bool { + switch u.Code { + case BEGIN_SPONSORING_FUTURE_RESERVES_SUCCESS, BEGIN_SPONSORING_FUTURE_RESERVES_MALFORMED, BEGIN_SPONSORING_FUTURE_RESERVES_ALREADY_SPONSORED, BEGIN_SPONSORING_FUTURE_RESERVES_RECURSIVE: + return true + } + return false +} +func (u *BeginSponsoringFutureReservesResult) XdrUnionTag() XdrNum32 { + return XDR_BeginSponsoringFutureReservesResultCode(&u.Code) +} +func (u *BeginSponsoringFutureReservesResult) XdrUnionTagName() string { + return "Code" +} +func (u *BeginSponsoringFutureReservesResult) XdrUnionBody() XdrType { + switch u.Code { + case BEGIN_SPONSORING_FUTURE_RESERVES_SUCCESS: + return nil + case BEGIN_SPONSORING_FUTURE_RESERVES_MALFORMED, BEGIN_SPONSORING_FUTURE_RESERVES_ALREADY_SPONSORED, BEGIN_SPONSORING_FUTURE_RESERVES_RECURSIVE: + return nil + } + return nil +} +func (u *BeginSponsoringFutureReservesResult) XdrUnionBodyName() string { + switch u.Code { + case BEGIN_SPONSORING_FUTURE_RESERVES_SUCCESS: + return "" + case BEGIN_SPONSORING_FUTURE_RESERVES_MALFORMED, BEGIN_SPONSORING_FUTURE_RESERVES_ALREADY_SPONSORED, BEGIN_SPONSORING_FUTURE_RESERVES_RECURSIVE: + return "" + } + return "" +} + +type XdrType_BeginSponsoringFutureReservesResult = *BeginSponsoringFutureReservesResult + +func (v *BeginSponsoringFutureReservesResult) XdrPointer() interface{} { return v } +func (BeginSponsoringFutureReservesResult) XdrTypeName() string { + return "BeginSponsoringFutureReservesResult" +} +func (v BeginSponsoringFutureReservesResult) XdrValue() interface{} { return v } +func (v *BeginSponsoringFutureReservesResult) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (u *BeginSponsoringFutureReservesResult) XdrRecurse(x XDR, name string) { + if name != "" { + name = x.Sprintf("%s.", name) + } + XDR_BeginSponsoringFutureReservesResultCode(&u.Code).XdrMarshal(x, x.Sprintf("%scode", name)) + switch u.Code { + case BEGIN_SPONSORING_FUTURE_RESERVES_SUCCESS: + return + case BEGIN_SPONSORING_FUTURE_RESERVES_MALFORMED, BEGIN_SPONSORING_FUTURE_RESERVES_ALREADY_SPONSORED, BEGIN_SPONSORING_FUTURE_RESERVES_RECURSIVE: + return + } + XdrPanic("invalid Code (%v) in BeginSponsoringFutureReservesResult", u.Code) +} +func XDR_BeginSponsoringFutureReservesResult(v *BeginSponsoringFutureReservesResult) *BeginSponsoringFutureReservesResult { + return v +} + +var _XdrNames_EndSponsoringFutureReservesResultCode = map[int32]string{ + int32(END_SPONSORING_FUTURE_RESERVES_SUCCESS): "END_SPONSORING_FUTURE_RESERVES_SUCCESS", + int32(END_SPONSORING_FUTURE_RESERVES_NOT_SPONSORED): "END_SPONSORING_FUTURE_RESERVES_NOT_SPONSORED", +} +var _XdrValues_EndSponsoringFutureReservesResultCode = map[string]int32{ + "END_SPONSORING_FUTURE_RESERVES_SUCCESS": int32(END_SPONSORING_FUTURE_RESERVES_SUCCESS), + "END_SPONSORING_FUTURE_RESERVES_NOT_SPONSORED": int32(END_SPONSORING_FUTURE_RESERVES_NOT_SPONSORED), +} + +func (EndSponsoringFutureReservesResultCode) XdrEnumNames() map[int32]string { + return _XdrNames_EndSponsoringFutureReservesResultCode +} +func (v EndSponsoringFutureReservesResultCode) String() string { + if s, ok := _XdrNames_EndSponsoringFutureReservesResultCode[int32(v)]; ok { + return s + } + return fmt.Sprintf("EndSponsoringFutureReservesResultCode#%d", v) +} +func (v *EndSponsoringFutureReservesResultCode) Scan(ss fmt.ScanState, _ rune) error { + if tok, err := ss.Token(true, XdrSymChar); err != nil { + return err + } else { + stok := string(tok) + if val, ok := _XdrValues_EndSponsoringFutureReservesResultCode[stok]; ok { + *v = EndSponsoringFutureReservesResultCode(val) + return nil + } else if stok == "EndSponsoringFutureReservesResultCode" { + if n, err := fmt.Fscanf(ss, "#%d", (*int32)(v)); n == 1 && err == nil { + return nil + } + } + return XdrError(fmt.Sprintf("%s is not a valid EndSponsoringFutureReservesResultCode.", stok)) + } +} +func (v EndSponsoringFutureReservesResultCode) GetU32() uint32 { return uint32(v) } +func (v *EndSponsoringFutureReservesResultCode) SetU32(n uint32) { + *v = EndSponsoringFutureReservesResultCode(n) +} +func (v *EndSponsoringFutureReservesResultCode) XdrPointer() interface{} { return v } +func (EndSponsoringFutureReservesResultCode) XdrTypeName() string { + return "EndSponsoringFutureReservesResultCode" +} +func (v EndSponsoringFutureReservesResultCode) XdrValue() interface{} { return v } +func (v *EndSponsoringFutureReservesResultCode) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } + +type XdrType_EndSponsoringFutureReservesResultCode = *EndSponsoringFutureReservesResultCode + +func XDR_EndSponsoringFutureReservesResultCode(v *EndSponsoringFutureReservesResultCode) *EndSponsoringFutureReservesResultCode { + return v +} + +var _XdrComments_EndSponsoringFutureReservesResultCode = map[int32]string{ + int32(END_SPONSORING_FUTURE_RESERVES_SUCCESS): "codes considered as \"success\" for the operation", + int32(END_SPONSORING_FUTURE_RESERVES_NOT_SPONSORED): "codes considered as \"failure\" for the operation", +} + +func (e EndSponsoringFutureReservesResultCode) XdrEnumComments() map[int32]string { + return _XdrComments_EndSponsoringFutureReservesResultCode +} + +var _XdrTags_EndSponsoringFutureReservesResult = map[int32]bool{ + XdrToI32(END_SPONSORING_FUTURE_RESERVES_SUCCESS): true, + XdrToI32(END_SPONSORING_FUTURE_RESERVES_NOT_SPONSORED): true, +} + +func (_ EndSponsoringFutureReservesResult) XdrValidTags() map[int32]bool { + return _XdrTags_EndSponsoringFutureReservesResult +} +func (u EndSponsoringFutureReservesResult) XdrValid() bool { + switch u.Code { + case END_SPONSORING_FUTURE_RESERVES_SUCCESS, END_SPONSORING_FUTURE_RESERVES_NOT_SPONSORED: + return true + } + return false +} +func (u *EndSponsoringFutureReservesResult) XdrUnionTag() XdrNum32 { + return XDR_EndSponsoringFutureReservesResultCode(&u.Code) +} +func (u *EndSponsoringFutureReservesResult) XdrUnionTagName() string { + return "Code" +} +func (u *EndSponsoringFutureReservesResult) XdrUnionBody() XdrType { + switch u.Code { + case END_SPONSORING_FUTURE_RESERVES_SUCCESS: + return nil + case END_SPONSORING_FUTURE_RESERVES_NOT_SPONSORED: + return nil + } + return nil +} +func (u *EndSponsoringFutureReservesResult) XdrUnionBodyName() string { + switch u.Code { + case END_SPONSORING_FUTURE_RESERVES_SUCCESS: + return "" + case END_SPONSORING_FUTURE_RESERVES_NOT_SPONSORED: + return "" + } + return "" +} + +type XdrType_EndSponsoringFutureReservesResult = *EndSponsoringFutureReservesResult + +func (v *EndSponsoringFutureReservesResult) XdrPointer() interface{} { return v } +func (EndSponsoringFutureReservesResult) XdrTypeName() string { + return "EndSponsoringFutureReservesResult" +} +func (v EndSponsoringFutureReservesResult) XdrValue() interface{} { return v } +func (v *EndSponsoringFutureReservesResult) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (u *EndSponsoringFutureReservesResult) XdrRecurse(x XDR, name string) { + if name != "" { + name = x.Sprintf("%s.", name) + } + XDR_EndSponsoringFutureReservesResultCode(&u.Code).XdrMarshal(x, x.Sprintf("%scode", name)) + switch u.Code { + case END_SPONSORING_FUTURE_RESERVES_SUCCESS: + return + case END_SPONSORING_FUTURE_RESERVES_NOT_SPONSORED: + return + } + XdrPanic("invalid Code (%v) in EndSponsoringFutureReservesResult", u.Code) +} +func XDR_EndSponsoringFutureReservesResult(v *EndSponsoringFutureReservesResult) *EndSponsoringFutureReservesResult { + return v +} + +var _XdrNames_RevokeSponsorshipResultCode = map[int32]string{ + int32(REVOKE_SPONSORSHIP_SUCCESS): "REVOKE_SPONSORSHIP_SUCCESS", + int32(REVOKE_SPONSORSHIP_DOES_NOT_EXIST): "REVOKE_SPONSORSHIP_DOES_NOT_EXIST", + int32(REVOKE_SPONSORSHIP_NOT_SPONSOR): "REVOKE_SPONSORSHIP_NOT_SPONSOR", + int32(REVOKE_SPONSORSHIP_LOW_RESERVE): "REVOKE_SPONSORSHIP_LOW_RESERVE", + int32(REVOKE_SPONSORSHIP_ONLY_TRANSFERABLE): "REVOKE_SPONSORSHIP_ONLY_TRANSFERABLE", + int32(REVOKE_SPONSORSHIP_MALFORMED): "REVOKE_SPONSORSHIP_MALFORMED", +} +var _XdrValues_RevokeSponsorshipResultCode = map[string]int32{ + "REVOKE_SPONSORSHIP_SUCCESS": int32(REVOKE_SPONSORSHIP_SUCCESS), + "REVOKE_SPONSORSHIP_DOES_NOT_EXIST": int32(REVOKE_SPONSORSHIP_DOES_NOT_EXIST), + "REVOKE_SPONSORSHIP_NOT_SPONSOR": int32(REVOKE_SPONSORSHIP_NOT_SPONSOR), + "REVOKE_SPONSORSHIP_LOW_RESERVE": int32(REVOKE_SPONSORSHIP_LOW_RESERVE), + "REVOKE_SPONSORSHIP_ONLY_TRANSFERABLE": int32(REVOKE_SPONSORSHIP_ONLY_TRANSFERABLE), + "REVOKE_SPONSORSHIP_MALFORMED": int32(REVOKE_SPONSORSHIP_MALFORMED), +} + +func (RevokeSponsorshipResultCode) XdrEnumNames() map[int32]string { + return _XdrNames_RevokeSponsorshipResultCode +} +func (v RevokeSponsorshipResultCode) String() string { + if s, ok := _XdrNames_RevokeSponsorshipResultCode[int32(v)]; ok { + return s + } + return fmt.Sprintf("RevokeSponsorshipResultCode#%d", v) +} +func (v *RevokeSponsorshipResultCode) Scan(ss fmt.ScanState, _ rune) error { + if tok, err := ss.Token(true, XdrSymChar); err != nil { + return err + } else { + stok := string(tok) + if val, ok := _XdrValues_RevokeSponsorshipResultCode[stok]; ok { + *v = RevokeSponsorshipResultCode(val) + return nil + } else if stok == "RevokeSponsorshipResultCode" { + if n, err := fmt.Fscanf(ss, "#%d", (*int32)(v)); n == 1 && err == nil { + return nil + } + } + return XdrError(fmt.Sprintf("%s is not a valid RevokeSponsorshipResultCode.", stok)) + } +} +func (v RevokeSponsorshipResultCode) GetU32() uint32 { return uint32(v) } +func (v *RevokeSponsorshipResultCode) SetU32(n uint32) { *v = RevokeSponsorshipResultCode(n) } +func (v *RevokeSponsorshipResultCode) XdrPointer() interface{} { return v } +func (RevokeSponsorshipResultCode) XdrTypeName() string { return "RevokeSponsorshipResultCode" } +func (v RevokeSponsorshipResultCode) XdrValue() interface{} { return v } +func (v *RevokeSponsorshipResultCode) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } + +type XdrType_RevokeSponsorshipResultCode = *RevokeSponsorshipResultCode + +func XDR_RevokeSponsorshipResultCode(v *RevokeSponsorshipResultCode) *RevokeSponsorshipResultCode { + return v +} + +var _XdrComments_RevokeSponsorshipResultCode = map[int32]string{ + int32(REVOKE_SPONSORSHIP_SUCCESS): "codes considered as \"success\" for the operation", + int32(REVOKE_SPONSORSHIP_DOES_NOT_EXIST): "codes considered as \"failure\" for the operation", +} + +func (e RevokeSponsorshipResultCode) XdrEnumComments() map[int32]string { + return _XdrComments_RevokeSponsorshipResultCode +} + +var _XdrTags_RevokeSponsorshipResult = map[int32]bool{ + XdrToI32(REVOKE_SPONSORSHIP_SUCCESS): true, + XdrToI32(REVOKE_SPONSORSHIP_DOES_NOT_EXIST): true, + XdrToI32(REVOKE_SPONSORSHIP_NOT_SPONSOR): true, + XdrToI32(REVOKE_SPONSORSHIP_LOW_RESERVE): true, + XdrToI32(REVOKE_SPONSORSHIP_ONLY_TRANSFERABLE): true, + XdrToI32(REVOKE_SPONSORSHIP_MALFORMED): true, +} + +func (_ RevokeSponsorshipResult) XdrValidTags() map[int32]bool { + return _XdrTags_RevokeSponsorshipResult +} +func (u RevokeSponsorshipResult) XdrValid() bool { + switch u.Code { + case REVOKE_SPONSORSHIP_SUCCESS, REVOKE_SPONSORSHIP_DOES_NOT_EXIST, REVOKE_SPONSORSHIP_NOT_SPONSOR, REVOKE_SPONSORSHIP_LOW_RESERVE, REVOKE_SPONSORSHIP_ONLY_TRANSFERABLE, REVOKE_SPONSORSHIP_MALFORMED: + return true + } + return false +} +func (u *RevokeSponsorshipResult) XdrUnionTag() XdrNum32 { + return XDR_RevokeSponsorshipResultCode(&u.Code) +} +func (u *RevokeSponsorshipResult) XdrUnionTagName() string { + return "Code" +} +func (u *RevokeSponsorshipResult) XdrUnionBody() XdrType { + switch u.Code { + case REVOKE_SPONSORSHIP_SUCCESS: + return nil + case REVOKE_SPONSORSHIP_DOES_NOT_EXIST, REVOKE_SPONSORSHIP_NOT_SPONSOR, REVOKE_SPONSORSHIP_LOW_RESERVE, REVOKE_SPONSORSHIP_ONLY_TRANSFERABLE, REVOKE_SPONSORSHIP_MALFORMED: + return nil + } + return nil +} +func (u *RevokeSponsorshipResult) XdrUnionBodyName() string { + switch u.Code { + case REVOKE_SPONSORSHIP_SUCCESS: + return "" + case REVOKE_SPONSORSHIP_DOES_NOT_EXIST, REVOKE_SPONSORSHIP_NOT_SPONSOR, REVOKE_SPONSORSHIP_LOW_RESERVE, REVOKE_SPONSORSHIP_ONLY_TRANSFERABLE, REVOKE_SPONSORSHIP_MALFORMED: + return "" + } + return "" +} + +type XdrType_RevokeSponsorshipResult = *RevokeSponsorshipResult + +func (v *RevokeSponsorshipResult) XdrPointer() interface{} { return v } +func (RevokeSponsorshipResult) XdrTypeName() string { return "RevokeSponsorshipResult" } +func (v RevokeSponsorshipResult) XdrValue() interface{} { return v } +func (v *RevokeSponsorshipResult) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (u *RevokeSponsorshipResult) XdrRecurse(x XDR, name string) { + if name != "" { + name = x.Sprintf("%s.", name) + } + XDR_RevokeSponsorshipResultCode(&u.Code).XdrMarshal(x, x.Sprintf("%scode", name)) + switch u.Code { + case REVOKE_SPONSORSHIP_SUCCESS: + return + case REVOKE_SPONSORSHIP_DOES_NOT_EXIST, REVOKE_SPONSORSHIP_NOT_SPONSOR, REVOKE_SPONSORSHIP_LOW_RESERVE, REVOKE_SPONSORSHIP_ONLY_TRANSFERABLE, REVOKE_SPONSORSHIP_MALFORMED: + return + } + XdrPanic("invalid Code (%v) in RevokeSponsorshipResult", u.Code) +} +func XDR_RevokeSponsorshipResult(v *RevokeSponsorshipResult) *RevokeSponsorshipResult { return v } + +var _XdrNames_ClawbackResultCode = map[int32]string{ + int32(CLAWBACK_SUCCESS): "CLAWBACK_SUCCESS", + int32(CLAWBACK_MALFORMED): "CLAWBACK_MALFORMED", + int32(CLAWBACK_NOT_CLAWBACK_ENABLED): "CLAWBACK_NOT_CLAWBACK_ENABLED", + int32(CLAWBACK_NO_TRUST): "CLAWBACK_NO_TRUST", + int32(CLAWBACK_UNDERFUNDED): "CLAWBACK_UNDERFUNDED", +} +var _XdrValues_ClawbackResultCode = map[string]int32{ + "CLAWBACK_SUCCESS": int32(CLAWBACK_SUCCESS), + "CLAWBACK_MALFORMED": int32(CLAWBACK_MALFORMED), + "CLAWBACK_NOT_CLAWBACK_ENABLED": int32(CLAWBACK_NOT_CLAWBACK_ENABLED), + "CLAWBACK_NO_TRUST": int32(CLAWBACK_NO_TRUST), + "CLAWBACK_UNDERFUNDED": int32(CLAWBACK_UNDERFUNDED), +} + +func (ClawbackResultCode) XdrEnumNames() map[int32]string { + return _XdrNames_ClawbackResultCode +} +func (v ClawbackResultCode) String() string { + if s, ok := _XdrNames_ClawbackResultCode[int32(v)]; ok { + return s + } + return fmt.Sprintf("ClawbackResultCode#%d", v) +} +func (v *ClawbackResultCode) Scan(ss fmt.ScanState, _ rune) error { + if tok, err := ss.Token(true, XdrSymChar); err != nil { + return err + } else { + stok := string(tok) + if val, ok := _XdrValues_ClawbackResultCode[stok]; ok { + *v = ClawbackResultCode(val) + return nil + } else if stok == "ClawbackResultCode" { + if n, err := fmt.Fscanf(ss, "#%d", (*int32)(v)); n == 1 && err == nil { + return nil + } + } + return XdrError(fmt.Sprintf("%s is not a valid ClawbackResultCode.", stok)) + } +} +func (v ClawbackResultCode) GetU32() uint32 { return uint32(v) } +func (v *ClawbackResultCode) SetU32(n uint32) { *v = ClawbackResultCode(n) } +func (v *ClawbackResultCode) XdrPointer() interface{} { return v } +func (ClawbackResultCode) XdrTypeName() string { return "ClawbackResultCode" } +func (v ClawbackResultCode) XdrValue() interface{} { return v } +func (v *ClawbackResultCode) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } + +type XdrType_ClawbackResultCode = *ClawbackResultCode + +func XDR_ClawbackResultCode(v *ClawbackResultCode) *ClawbackResultCode { return v } + +var _XdrComments_ClawbackResultCode = map[int32]string{ + int32(CLAWBACK_SUCCESS): "codes considered as \"success\" for the operation", + int32(CLAWBACK_MALFORMED): "codes considered as \"failure\" for the operation", +} + +func (e ClawbackResultCode) XdrEnumComments() map[int32]string { + return _XdrComments_ClawbackResultCode +} + +var _XdrTags_ClawbackResult = map[int32]bool{ + XdrToI32(CLAWBACK_SUCCESS): true, + XdrToI32(CLAWBACK_MALFORMED): true, + XdrToI32(CLAWBACK_NOT_CLAWBACK_ENABLED): true, + XdrToI32(CLAWBACK_NO_TRUST): true, + XdrToI32(CLAWBACK_UNDERFUNDED): true, +} + +func (_ ClawbackResult) XdrValidTags() map[int32]bool { + return _XdrTags_ClawbackResult +} +func (u ClawbackResult) XdrValid() bool { + switch u.Code { + case CLAWBACK_SUCCESS, CLAWBACK_MALFORMED, CLAWBACK_NOT_CLAWBACK_ENABLED, CLAWBACK_NO_TRUST, CLAWBACK_UNDERFUNDED: + return true + } + return false +} +func (u *ClawbackResult) XdrUnionTag() XdrNum32 { + return XDR_ClawbackResultCode(&u.Code) +} +func (u *ClawbackResult) XdrUnionTagName() string { + return "Code" +} +func (u *ClawbackResult) XdrUnionBody() XdrType { + switch u.Code { + case CLAWBACK_SUCCESS: + return nil + case CLAWBACK_MALFORMED, CLAWBACK_NOT_CLAWBACK_ENABLED, CLAWBACK_NO_TRUST, CLAWBACK_UNDERFUNDED: + return nil + } + return nil +} +func (u *ClawbackResult) XdrUnionBodyName() string { + switch u.Code { + case CLAWBACK_SUCCESS: + return "" + case CLAWBACK_MALFORMED, CLAWBACK_NOT_CLAWBACK_ENABLED, CLAWBACK_NO_TRUST, CLAWBACK_UNDERFUNDED: + return "" + } + return "" +} + +type XdrType_ClawbackResult = *ClawbackResult + +func (v *ClawbackResult) XdrPointer() interface{} { return v } +func (ClawbackResult) XdrTypeName() string { return "ClawbackResult" } +func (v ClawbackResult) XdrValue() interface{} { return v } +func (v *ClawbackResult) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (u *ClawbackResult) XdrRecurse(x XDR, name string) { + if name != "" { + name = x.Sprintf("%s.", name) + } + XDR_ClawbackResultCode(&u.Code).XdrMarshal(x, x.Sprintf("%scode", name)) + switch u.Code { + case CLAWBACK_SUCCESS: + return + case CLAWBACK_MALFORMED, CLAWBACK_NOT_CLAWBACK_ENABLED, CLAWBACK_NO_TRUST, CLAWBACK_UNDERFUNDED: + return + } + XdrPanic("invalid Code (%v) in ClawbackResult", u.Code) +} +func XDR_ClawbackResult(v *ClawbackResult) *ClawbackResult { return v } + +var _XdrNames_ClawbackClaimableBalanceResultCode = map[int32]string{ + int32(CLAWBACK_CLAIMABLE_BALANCE_SUCCESS): "CLAWBACK_CLAIMABLE_BALANCE_SUCCESS", + int32(CLAWBACK_CLAIMABLE_BALANCE_DOES_NOT_EXIST): "CLAWBACK_CLAIMABLE_BALANCE_DOES_NOT_EXIST", + int32(CLAWBACK_CLAIMABLE_BALANCE_NOT_ISSUER): "CLAWBACK_CLAIMABLE_BALANCE_NOT_ISSUER", + int32(CLAWBACK_CLAIMABLE_BALANCE_NOT_CLAWBACK_ENABLED): "CLAWBACK_CLAIMABLE_BALANCE_NOT_CLAWBACK_ENABLED", +} +var _XdrValues_ClawbackClaimableBalanceResultCode = map[string]int32{ + "CLAWBACK_CLAIMABLE_BALANCE_SUCCESS": int32(CLAWBACK_CLAIMABLE_BALANCE_SUCCESS), + "CLAWBACK_CLAIMABLE_BALANCE_DOES_NOT_EXIST": int32(CLAWBACK_CLAIMABLE_BALANCE_DOES_NOT_EXIST), + "CLAWBACK_CLAIMABLE_BALANCE_NOT_ISSUER": int32(CLAWBACK_CLAIMABLE_BALANCE_NOT_ISSUER), + "CLAWBACK_CLAIMABLE_BALANCE_NOT_CLAWBACK_ENABLED": int32(CLAWBACK_CLAIMABLE_BALANCE_NOT_CLAWBACK_ENABLED), +} + +func (ClawbackClaimableBalanceResultCode) XdrEnumNames() map[int32]string { + return _XdrNames_ClawbackClaimableBalanceResultCode +} +func (v ClawbackClaimableBalanceResultCode) String() string { + if s, ok := _XdrNames_ClawbackClaimableBalanceResultCode[int32(v)]; ok { + return s + } + return fmt.Sprintf("ClawbackClaimableBalanceResultCode#%d", v) +} +func (v *ClawbackClaimableBalanceResultCode) Scan(ss fmt.ScanState, _ rune) error { + if tok, err := ss.Token(true, XdrSymChar); err != nil { + return err + } else { + stok := string(tok) + if val, ok := _XdrValues_ClawbackClaimableBalanceResultCode[stok]; ok { + *v = ClawbackClaimableBalanceResultCode(val) + return nil + } else if stok == "ClawbackClaimableBalanceResultCode" { + if n, err := fmt.Fscanf(ss, "#%d", (*int32)(v)); n == 1 && err == nil { + return nil + } + } + return XdrError(fmt.Sprintf("%s is not a valid ClawbackClaimableBalanceResultCode.", stok)) + } +} +func (v ClawbackClaimableBalanceResultCode) GetU32() uint32 { return uint32(v) } +func (v *ClawbackClaimableBalanceResultCode) SetU32(n uint32) { + *v = ClawbackClaimableBalanceResultCode(n) +} +func (v *ClawbackClaimableBalanceResultCode) XdrPointer() interface{} { return v } +func (ClawbackClaimableBalanceResultCode) XdrTypeName() string { + return "ClawbackClaimableBalanceResultCode" +} +func (v ClawbackClaimableBalanceResultCode) XdrValue() interface{} { return v } +func (v *ClawbackClaimableBalanceResultCode) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } + +type XdrType_ClawbackClaimableBalanceResultCode = *ClawbackClaimableBalanceResultCode + +func XDR_ClawbackClaimableBalanceResultCode(v *ClawbackClaimableBalanceResultCode) *ClawbackClaimableBalanceResultCode { + return v +} + +var _XdrComments_ClawbackClaimableBalanceResultCode = map[int32]string{ + int32(CLAWBACK_CLAIMABLE_BALANCE_SUCCESS): "codes considered as \"success\" for the operation", + int32(CLAWBACK_CLAIMABLE_BALANCE_DOES_NOT_EXIST): "codes considered as \"failure\" for the operation", +} + +func (e ClawbackClaimableBalanceResultCode) XdrEnumComments() map[int32]string { + return _XdrComments_ClawbackClaimableBalanceResultCode +} + +var _XdrTags_ClawbackClaimableBalanceResult = map[int32]bool{ + XdrToI32(CLAWBACK_CLAIMABLE_BALANCE_SUCCESS): true, + XdrToI32(CLAWBACK_CLAIMABLE_BALANCE_DOES_NOT_EXIST): true, + XdrToI32(CLAWBACK_CLAIMABLE_BALANCE_NOT_ISSUER): true, + XdrToI32(CLAWBACK_CLAIMABLE_BALANCE_NOT_CLAWBACK_ENABLED): true, +} + +func (_ ClawbackClaimableBalanceResult) XdrValidTags() map[int32]bool { + return _XdrTags_ClawbackClaimableBalanceResult +} +func (u ClawbackClaimableBalanceResult) XdrValid() bool { + switch u.Code { + case CLAWBACK_CLAIMABLE_BALANCE_SUCCESS, CLAWBACK_CLAIMABLE_BALANCE_DOES_NOT_EXIST, CLAWBACK_CLAIMABLE_BALANCE_NOT_ISSUER, CLAWBACK_CLAIMABLE_BALANCE_NOT_CLAWBACK_ENABLED: + return true + } + return false +} +func (u *ClawbackClaimableBalanceResult) XdrUnionTag() XdrNum32 { + return XDR_ClawbackClaimableBalanceResultCode(&u.Code) +} +func (u *ClawbackClaimableBalanceResult) XdrUnionTagName() string { + return "Code" +} +func (u *ClawbackClaimableBalanceResult) XdrUnionBody() XdrType { + switch u.Code { + case CLAWBACK_CLAIMABLE_BALANCE_SUCCESS: + return nil + case CLAWBACK_CLAIMABLE_BALANCE_DOES_NOT_EXIST, CLAWBACK_CLAIMABLE_BALANCE_NOT_ISSUER, CLAWBACK_CLAIMABLE_BALANCE_NOT_CLAWBACK_ENABLED: + return nil + } + return nil +} +func (u *ClawbackClaimableBalanceResult) XdrUnionBodyName() string { + switch u.Code { + case CLAWBACK_CLAIMABLE_BALANCE_SUCCESS: + return "" + case CLAWBACK_CLAIMABLE_BALANCE_DOES_NOT_EXIST, CLAWBACK_CLAIMABLE_BALANCE_NOT_ISSUER, CLAWBACK_CLAIMABLE_BALANCE_NOT_CLAWBACK_ENABLED: + return "" + } + return "" +} + +type XdrType_ClawbackClaimableBalanceResult = *ClawbackClaimableBalanceResult + +func (v *ClawbackClaimableBalanceResult) XdrPointer() interface{} { return v } +func (ClawbackClaimableBalanceResult) XdrTypeName() string { return "ClawbackClaimableBalanceResult" } +func (v ClawbackClaimableBalanceResult) XdrValue() interface{} { return v } +func (v *ClawbackClaimableBalanceResult) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (u *ClawbackClaimableBalanceResult) XdrRecurse(x XDR, name string) { + if name != "" { + name = x.Sprintf("%s.", name) + } + XDR_ClawbackClaimableBalanceResultCode(&u.Code).XdrMarshal(x, x.Sprintf("%scode", name)) + switch u.Code { + case CLAWBACK_CLAIMABLE_BALANCE_SUCCESS: + return + case CLAWBACK_CLAIMABLE_BALANCE_DOES_NOT_EXIST, CLAWBACK_CLAIMABLE_BALANCE_NOT_ISSUER, CLAWBACK_CLAIMABLE_BALANCE_NOT_CLAWBACK_ENABLED: + return + } + XdrPanic("invalid Code (%v) in ClawbackClaimableBalanceResult", u.Code) +} +func XDR_ClawbackClaimableBalanceResult(v *ClawbackClaimableBalanceResult) *ClawbackClaimableBalanceResult { + return v +} + +var _XdrNames_SetTrustLineFlagsResultCode = map[int32]string{ + int32(SET_TRUST_LINE_FLAGS_SUCCESS): "SET_TRUST_LINE_FLAGS_SUCCESS", + int32(SET_TRUST_LINE_FLAGS_MALFORMED): "SET_TRUST_LINE_FLAGS_MALFORMED", + int32(SET_TRUST_LINE_FLAGS_NO_TRUST_LINE): "SET_TRUST_LINE_FLAGS_NO_TRUST_LINE", + int32(SET_TRUST_LINE_FLAGS_CANT_REVOKE): "SET_TRUST_LINE_FLAGS_CANT_REVOKE", + int32(SET_TRUST_LINE_FLAGS_INVALID_STATE): "SET_TRUST_LINE_FLAGS_INVALID_STATE", + int32(SET_TRUST_LINE_FLAGS_LOW_RESERVE): "SET_TRUST_LINE_FLAGS_LOW_RESERVE", +} +var _XdrValues_SetTrustLineFlagsResultCode = map[string]int32{ + "SET_TRUST_LINE_FLAGS_SUCCESS": int32(SET_TRUST_LINE_FLAGS_SUCCESS), + "SET_TRUST_LINE_FLAGS_MALFORMED": int32(SET_TRUST_LINE_FLAGS_MALFORMED), + "SET_TRUST_LINE_FLAGS_NO_TRUST_LINE": int32(SET_TRUST_LINE_FLAGS_NO_TRUST_LINE), + "SET_TRUST_LINE_FLAGS_CANT_REVOKE": int32(SET_TRUST_LINE_FLAGS_CANT_REVOKE), + "SET_TRUST_LINE_FLAGS_INVALID_STATE": int32(SET_TRUST_LINE_FLAGS_INVALID_STATE), + "SET_TRUST_LINE_FLAGS_LOW_RESERVE": int32(SET_TRUST_LINE_FLAGS_LOW_RESERVE), +} + +func (SetTrustLineFlagsResultCode) XdrEnumNames() map[int32]string { + return _XdrNames_SetTrustLineFlagsResultCode +} +func (v SetTrustLineFlagsResultCode) String() string { + if s, ok := _XdrNames_SetTrustLineFlagsResultCode[int32(v)]; ok { + return s + } + return fmt.Sprintf("SetTrustLineFlagsResultCode#%d", v) +} +func (v *SetTrustLineFlagsResultCode) Scan(ss fmt.ScanState, _ rune) error { + if tok, err := ss.Token(true, XdrSymChar); err != nil { + return err + } else { + stok := string(tok) + if val, ok := _XdrValues_SetTrustLineFlagsResultCode[stok]; ok { + *v = SetTrustLineFlagsResultCode(val) + return nil + } else if stok == "SetTrustLineFlagsResultCode" { + if n, err := fmt.Fscanf(ss, "#%d", (*int32)(v)); n == 1 && err == nil { + return nil + } + } + return XdrError(fmt.Sprintf("%s is not a valid SetTrustLineFlagsResultCode.", stok)) + } +} +func (v SetTrustLineFlagsResultCode) GetU32() uint32 { return uint32(v) } +func (v *SetTrustLineFlagsResultCode) SetU32(n uint32) { *v = SetTrustLineFlagsResultCode(n) } +func (v *SetTrustLineFlagsResultCode) XdrPointer() interface{} { return v } +func (SetTrustLineFlagsResultCode) XdrTypeName() string { return "SetTrustLineFlagsResultCode" } +func (v SetTrustLineFlagsResultCode) XdrValue() interface{} { return v } +func (v *SetTrustLineFlagsResultCode) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } + +type XdrType_SetTrustLineFlagsResultCode = *SetTrustLineFlagsResultCode + +func XDR_SetTrustLineFlagsResultCode(v *SetTrustLineFlagsResultCode) *SetTrustLineFlagsResultCode { + return v +} + +var _XdrComments_SetTrustLineFlagsResultCode = map[int32]string{ + int32(SET_TRUST_LINE_FLAGS_SUCCESS): "codes considered as \"success\" for the operation", + int32(SET_TRUST_LINE_FLAGS_MALFORMED): "codes considered as \"failure\" for the operation", + int32(SET_TRUST_LINE_FLAGS_LOW_RESERVE): "claimable balances can't be created", +} + +func (e SetTrustLineFlagsResultCode) XdrEnumComments() map[int32]string { + return _XdrComments_SetTrustLineFlagsResultCode +} + +var _XdrTags_SetTrustLineFlagsResult = map[int32]bool{ + XdrToI32(SET_TRUST_LINE_FLAGS_SUCCESS): true, + XdrToI32(SET_TRUST_LINE_FLAGS_MALFORMED): true, + XdrToI32(SET_TRUST_LINE_FLAGS_NO_TRUST_LINE): true, + XdrToI32(SET_TRUST_LINE_FLAGS_CANT_REVOKE): true, + XdrToI32(SET_TRUST_LINE_FLAGS_INVALID_STATE): true, + XdrToI32(SET_TRUST_LINE_FLAGS_LOW_RESERVE): true, +} + +func (_ SetTrustLineFlagsResult) XdrValidTags() map[int32]bool { + return _XdrTags_SetTrustLineFlagsResult +} +func (u SetTrustLineFlagsResult) XdrValid() bool { + switch u.Code { + case SET_TRUST_LINE_FLAGS_SUCCESS, SET_TRUST_LINE_FLAGS_MALFORMED, SET_TRUST_LINE_FLAGS_NO_TRUST_LINE, SET_TRUST_LINE_FLAGS_CANT_REVOKE, SET_TRUST_LINE_FLAGS_INVALID_STATE, SET_TRUST_LINE_FLAGS_LOW_RESERVE: + return true + } + return false +} +func (u *SetTrustLineFlagsResult) XdrUnionTag() XdrNum32 { + return XDR_SetTrustLineFlagsResultCode(&u.Code) +} +func (u *SetTrustLineFlagsResult) XdrUnionTagName() string { + return "Code" +} +func (u *SetTrustLineFlagsResult) XdrUnionBody() XdrType { + switch u.Code { + case SET_TRUST_LINE_FLAGS_SUCCESS: + return nil + case SET_TRUST_LINE_FLAGS_MALFORMED, SET_TRUST_LINE_FLAGS_NO_TRUST_LINE, SET_TRUST_LINE_FLAGS_CANT_REVOKE, SET_TRUST_LINE_FLAGS_INVALID_STATE, SET_TRUST_LINE_FLAGS_LOW_RESERVE: + return nil + } + return nil +} +func (u *SetTrustLineFlagsResult) XdrUnionBodyName() string { + switch u.Code { + case SET_TRUST_LINE_FLAGS_SUCCESS: + return "" + case SET_TRUST_LINE_FLAGS_MALFORMED, SET_TRUST_LINE_FLAGS_NO_TRUST_LINE, SET_TRUST_LINE_FLAGS_CANT_REVOKE, SET_TRUST_LINE_FLAGS_INVALID_STATE, SET_TRUST_LINE_FLAGS_LOW_RESERVE: + return "" + } + return "" +} + +type XdrType_SetTrustLineFlagsResult = *SetTrustLineFlagsResult + +func (v *SetTrustLineFlagsResult) XdrPointer() interface{} { return v } +func (SetTrustLineFlagsResult) XdrTypeName() string { return "SetTrustLineFlagsResult" } +func (v SetTrustLineFlagsResult) XdrValue() interface{} { return v } +func (v *SetTrustLineFlagsResult) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (u *SetTrustLineFlagsResult) XdrRecurse(x XDR, name string) { + if name != "" { + name = x.Sprintf("%s.", name) + } + XDR_SetTrustLineFlagsResultCode(&u.Code).XdrMarshal(x, x.Sprintf("%scode", name)) + switch u.Code { + case SET_TRUST_LINE_FLAGS_SUCCESS: + return + case SET_TRUST_LINE_FLAGS_MALFORMED, SET_TRUST_LINE_FLAGS_NO_TRUST_LINE, SET_TRUST_LINE_FLAGS_CANT_REVOKE, SET_TRUST_LINE_FLAGS_INVALID_STATE, SET_TRUST_LINE_FLAGS_LOW_RESERVE: + return + } + XdrPanic("invalid Code (%v) in SetTrustLineFlagsResult", u.Code) +} +func XDR_SetTrustLineFlagsResult(v *SetTrustLineFlagsResult) *SetTrustLineFlagsResult { return v } + +var _XdrNames_LiquidityPoolDepositResultCode = map[int32]string{ + int32(LIQUIDITY_POOL_DEPOSIT_SUCCESS): "LIQUIDITY_POOL_DEPOSIT_SUCCESS", + int32(LIQUIDITY_POOL_DEPOSIT_MALFORMED): "LIQUIDITY_POOL_DEPOSIT_MALFORMED", + int32(LIQUIDITY_POOL_DEPOSIT_NO_TRUST): "LIQUIDITY_POOL_DEPOSIT_NO_TRUST", + int32(LIQUIDITY_POOL_DEPOSIT_NOT_AUTHORIZED): "LIQUIDITY_POOL_DEPOSIT_NOT_AUTHORIZED", + int32(LIQUIDITY_POOL_DEPOSIT_UNDERFUNDED): "LIQUIDITY_POOL_DEPOSIT_UNDERFUNDED", + int32(LIQUIDITY_POOL_DEPOSIT_LINE_FULL): "LIQUIDITY_POOL_DEPOSIT_LINE_FULL", + int32(LIQUIDITY_POOL_DEPOSIT_BAD_PRICE): "LIQUIDITY_POOL_DEPOSIT_BAD_PRICE", + int32(LIQUIDITY_POOL_DEPOSIT_POOL_FULL): "LIQUIDITY_POOL_DEPOSIT_POOL_FULL", +} +var _XdrValues_LiquidityPoolDepositResultCode = map[string]int32{ + "LIQUIDITY_POOL_DEPOSIT_SUCCESS": int32(LIQUIDITY_POOL_DEPOSIT_SUCCESS), + "LIQUIDITY_POOL_DEPOSIT_MALFORMED": int32(LIQUIDITY_POOL_DEPOSIT_MALFORMED), + "LIQUIDITY_POOL_DEPOSIT_NO_TRUST": int32(LIQUIDITY_POOL_DEPOSIT_NO_TRUST), + "LIQUIDITY_POOL_DEPOSIT_NOT_AUTHORIZED": int32(LIQUIDITY_POOL_DEPOSIT_NOT_AUTHORIZED), + "LIQUIDITY_POOL_DEPOSIT_UNDERFUNDED": int32(LIQUIDITY_POOL_DEPOSIT_UNDERFUNDED), + "LIQUIDITY_POOL_DEPOSIT_LINE_FULL": int32(LIQUIDITY_POOL_DEPOSIT_LINE_FULL), + "LIQUIDITY_POOL_DEPOSIT_BAD_PRICE": int32(LIQUIDITY_POOL_DEPOSIT_BAD_PRICE), + "LIQUIDITY_POOL_DEPOSIT_POOL_FULL": int32(LIQUIDITY_POOL_DEPOSIT_POOL_FULL), +} + +func (LiquidityPoolDepositResultCode) XdrEnumNames() map[int32]string { + return _XdrNames_LiquidityPoolDepositResultCode +} +func (v LiquidityPoolDepositResultCode) String() string { + if s, ok := _XdrNames_LiquidityPoolDepositResultCode[int32(v)]; ok { + return s + } + return fmt.Sprintf("LiquidityPoolDepositResultCode#%d", v) +} +func (v *LiquidityPoolDepositResultCode) Scan(ss fmt.ScanState, _ rune) error { + if tok, err := ss.Token(true, XdrSymChar); err != nil { + return err + } else { + stok := string(tok) + if val, ok := _XdrValues_LiquidityPoolDepositResultCode[stok]; ok { + *v = LiquidityPoolDepositResultCode(val) + return nil + } else if stok == "LiquidityPoolDepositResultCode" { + if n, err := fmt.Fscanf(ss, "#%d", (*int32)(v)); n == 1 && err == nil { + return nil + } + } + return XdrError(fmt.Sprintf("%s is not a valid LiquidityPoolDepositResultCode.", stok)) + } +} +func (v LiquidityPoolDepositResultCode) GetU32() uint32 { return uint32(v) } +func (v *LiquidityPoolDepositResultCode) SetU32(n uint32) { *v = LiquidityPoolDepositResultCode(n) } +func (v *LiquidityPoolDepositResultCode) XdrPointer() interface{} { return v } +func (LiquidityPoolDepositResultCode) XdrTypeName() string { return "LiquidityPoolDepositResultCode" } +func (v LiquidityPoolDepositResultCode) XdrValue() interface{} { return v } +func (v *LiquidityPoolDepositResultCode) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } + +type XdrType_LiquidityPoolDepositResultCode = *LiquidityPoolDepositResultCode + +func XDR_LiquidityPoolDepositResultCode(v *LiquidityPoolDepositResultCode) *LiquidityPoolDepositResultCode { + return v +} + +var _XdrComments_LiquidityPoolDepositResultCode = map[int32]string{ + int32(LIQUIDITY_POOL_DEPOSIT_SUCCESS): "codes considered as \"success\" for the operation", + int32(LIQUIDITY_POOL_DEPOSIT_MALFORMED): "bad input", + int32(LIQUIDITY_POOL_DEPOSIT_NO_TRUST): "no trust line for one of the", + int32(LIQUIDITY_POOL_DEPOSIT_NOT_AUTHORIZED): "not authorized for one of the", + int32(LIQUIDITY_POOL_DEPOSIT_UNDERFUNDED): "not enough balance for one of", + int32(LIQUIDITY_POOL_DEPOSIT_LINE_FULL): "pool share trust line doesn't", + int32(LIQUIDITY_POOL_DEPOSIT_BAD_PRICE): "deposit price outside bounds", + int32(LIQUIDITY_POOL_DEPOSIT_POOL_FULL): "pool reserves are full", +} + +func (e LiquidityPoolDepositResultCode) XdrEnumComments() map[int32]string { + return _XdrComments_LiquidityPoolDepositResultCode +} + +var _XdrTags_LiquidityPoolDepositResult = map[int32]bool{ + XdrToI32(LIQUIDITY_POOL_DEPOSIT_SUCCESS): true, + XdrToI32(LIQUIDITY_POOL_DEPOSIT_MALFORMED): true, + XdrToI32(LIQUIDITY_POOL_DEPOSIT_NO_TRUST): true, + XdrToI32(LIQUIDITY_POOL_DEPOSIT_NOT_AUTHORIZED): true, + XdrToI32(LIQUIDITY_POOL_DEPOSIT_UNDERFUNDED): true, + XdrToI32(LIQUIDITY_POOL_DEPOSIT_LINE_FULL): true, + XdrToI32(LIQUIDITY_POOL_DEPOSIT_BAD_PRICE): true, + XdrToI32(LIQUIDITY_POOL_DEPOSIT_POOL_FULL): true, +} + +func (_ LiquidityPoolDepositResult) XdrValidTags() map[int32]bool { + return _XdrTags_LiquidityPoolDepositResult +} +func (u LiquidityPoolDepositResult) XdrValid() bool { + switch u.Code { + case LIQUIDITY_POOL_DEPOSIT_SUCCESS, LIQUIDITY_POOL_DEPOSIT_MALFORMED, LIQUIDITY_POOL_DEPOSIT_NO_TRUST, LIQUIDITY_POOL_DEPOSIT_NOT_AUTHORIZED, LIQUIDITY_POOL_DEPOSIT_UNDERFUNDED, LIQUIDITY_POOL_DEPOSIT_LINE_FULL, LIQUIDITY_POOL_DEPOSIT_BAD_PRICE, LIQUIDITY_POOL_DEPOSIT_POOL_FULL: + return true + } + return false +} +func (u *LiquidityPoolDepositResult) XdrUnionTag() XdrNum32 { + return XDR_LiquidityPoolDepositResultCode(&u.Code) +} +func (u *LiquidityPoolDepositResult) XdrUnionTagName() string { + return "Code" +} +func (u *LiquidityPoolDepositResult) XdrUnionBody() XdrType { + switch u.Code { + case LIQUIDITY_POOL_DEPOSIT_SUCCESS: + return nil + case LIQUIDITY_POOL_DEPOSIT_MALFORMED, LIQUIDITY_POOL_DEPOSIT_NO_TRUST, LIQUIDITY_POOL_DEPOSIT_NOT_AUTHORIZED, LIQUIDITY_POOL_DEPOSIT_UNDERFUNDED, LIQUIDITY_POOL_DEPOSIT_LINE_FULL, LIQUIDITY_POOL_DEPOSIT_BAD_PRICE, LIQUIDITY_POOL_DEPOSIT_POOL_FULL: + return nil + } + return nil +} +func (u *LiquidityPoolDepositResult) XdrUnionBodyName() string { + switch u.Code { + case LIQUIDITY_POOL_DEPOSIT_SUCCESS: + return "" + case LIQUIDITY_POOL_DEPOSIT_MALFORMED, LIQUIDITY_POOL_DEPOSIT_NO_TRUST, LIQUIDITY_POOL_DEPOSIT_NOT_AUTHORIZED, LIQUIDITY_POOL_DEPOSIT_UNDERFUNDED, LIQUIDITY_POOL_DEPOSIT_LINE_FULL, LIQUIDITY_POOL_DEPOSIT_BAD_PRICE, LIQUIDITY_POOL_DEPOSIT_POOL_FULL: + return "" + } + return "" +} + +type XdrType_LiquidityPoolDepositResult = *LiquidityPoolDepositResult + +func (v *LiquidityPoolDepositResult) XdrPointer() interface{} { return v } +func (LiquidityPoolDepositResult) XdrTypeName() string { return "LiquidityPoolDepositResult" } +func (v LiquidityPoolDepositResult) XdrValue() interface{} { return v } +func (v *LiquidityPoolDepositResult) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (u *LiquidityPoolDepositResult) XdrRecurse(x XDR, name string) { + if name != "" { + name = x.Sprintf("%s.", name) + } + XDR_LiquidityPoolDepositResultCode(&u.Code).XdrMarshal(x, x.Sprintf("%scode", name)) + switch u.Code { + case LIQUIDITY_POOL_DEPOSIT_SUCCESS: + return + case LIQUIDITY_POOL_DEPOSIT_MALFORMED, LIQUIDITY_POOL_DEPOSIT_NO_TRUST, LIQUIDITY_POOL_DEPOSIT_NOT_AUTHORIZED, LIQUIDITY_POOL_DEPOSIT_UNDERFUNDED, LIQUIDITY_POOL_DEPOSIT_LINE_FULL, LIQUIDITY_POOL_DEPOSIT_BAD_PRICE, LIQUIDITY_POOL_DEPOSIT_POOL_FULL: + return + } + XdrPanic("invalid Code (%v) in LiquidityPoolDepositResult", u.Code) +} +func XDR_LiquidityPoolDepositResult(v *LiquidityPoolDepositResult) *LiquidityPoolDepositResult { + return v +} + +var _XdrNames_LiquidityPoolWithdrawResultCode = map[int32]string{ + int32(LIQUIDITY_POOL_WITHDRAW_SUCCESS): "LIQUIDITY_POOL_WITHDRAW_SUCCESS", + int32(LIQUIDITY_POOL_WITHDRAW_MALFORMED): "LIQUIDITY_POOL_WITHDRAW_MALFORMED", + int32(LIQUIDITY_POOL_WITHDRAW_NO_TRUST): "LIQUIDITY_POOL_WITHDRAW_NO_TRUST", + int32(LIQUIDITY_POOL_WITHDRAW_UNDERFUNDED): "LIQUIDITY_POOL_WITHDRAW_UNDERFUNDED", + int32(LIQUIDITY_POOL_WITHDRAW_LINE_FULL): "LIQUIDITY_POOL_WITHDRAW_LINE_FULL", + int32(LIQUIDITY_POOL_WITHDRAW_UNDER_MINIMUM): "LIQUIDITY_POOL_WITHDRAW_UNDER_MINIMUM", +} +var _XdrValues_LiquidityPoolWithdrawResultCode = map[string]int32{ + "LIQUIDITY_POOL_WITHDRAW_SUCCESS": int32(LIQUIDITY_POOL_WITHDRAW_SUCCESS), + "LIQUIDITY_POOL_WITHDRAW_MALFORMED": int32(LIQUIDITY_POOL_WITHDRAW_MALFORMED), + "LIQUIDITY_POOL_WITHDRAW_NO_TRUST": int32(LIQUIDITY_POOL_WITHDRAW_NO_TRUST), + "LIQUIDITY_POOL_WITHDRAW_UNDERFUNDED": int32(LIQUIDITY_POOL_WITHDRAW_UNDERFUNDED), + "LIQUIDITY_POOL_WITHDRAW_LINE_FULL": int32(LIQUIDITY_POOL_WITHDRAW_LINE_FULL), + "LIQUIDITY_POOL_WITHDRAW_UNDER_MINIMUM": int32(LIQUIDITY_POOL_WITHDRAW_UNDER_MINIMUM), +} + +func (LiquidityPoolWithdrawResultCode) XdrEnumNames() map[int32]string { + return _XdrNames_LiquidityPoolWithdrawResultCode +} +func (v LiquidityPoolWithdrawResultCode) String() string { + if s, ok := _XdrNames_LiquidityPoolWithdrawResultCode[int32(v)]; ok { + return s + } + return fmt.Sprintf("LiquidityPoolWithdrawResultCode#%d", v) +} +func (v *LiquidityPoolWithdrawResultCode) Scan(ss fmt.ScanState, _ rune) error { + if tok, err := ss.Token(true, XdrSymChar); err != nil { + return err + } else { + stok := string(tok) + if val, ok := _XdrValues_LiquidityPoolWithdrawResultCode[stok]; ok { + *v = LiquidityPoolWithdrawResultCode(val) + return nil + } else if stok == "LiquidityPoolWithdrawResultCode" { + if n, err := fmt.Fscanf(ss, "#%d", (*int32)(v)); n == 1 && err == nil { + return nil + } + } + return XdrError(fmt.Sprintf("%s is not a valid LiquidityPoolWithdrawResultCode.", stok)) + } +} +func (v LiquidityPoolWithdrawResultCode) GetU32() uint32 { return uint32(v) } +func (v *LiquidityPoolWithdrawResultCode) SetU32(n uint32) { *v = LiquidityPoolWithdrawResultCode(n) } +func (v *LiquidityPoolWithdrawResultCode) XdrPointer() interface{} { return v } +func (LiquidityPoolWithdrawResultCode) XdrTypeName() string { return "LiquidityPoolWithdrawResultCode" } +func (v LiquidityPoolWithdrawResultCode) XdrValue() interface{} { return v } +func (v *LiquidityPoolWithdrawResultCode) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } + +type XdrType_LiquidityPoolWithdrawResultCode = *LiquidityPoolWithdrawResultCode + +func XDR_LiquidityPoolWithdrawResultCode(v *LiquidityPoolWithdrawResultCode) *LiquidityPoolWithdrawResultCode { + return v +} + +var _XdrComments_LiquidityPoolWithdrawResultCode = map[int32]string{ + int32(LIQUIDITY_POOL_WITHDRAW_SUCCESS): "codes considered as \"success\" for the operation", + int32(LIQUIDITY_POOL_WITHDRAW_MALFORMED): "bad input", + int32(LIQUIDITY_POOL_WITHDRAW_NO_TRUST): "no trust line for one of the", + int32(LIQUIDITY_POOL_WITHDRAW_UNDERFUNDED): "not enough balance of the", + int32(LIQUIDITY_POOL_WITHDRAW_LINE_FULL): "would go above limit for one", + int32(LIQUIDITY_POOL_WITHDRAW_UNDER_MINIMUM): "of the assets", +} + +func (e LiquidityPoolWithdrawResultCode) XdrEnumComments() map[int32]string { + return _XdrComments_LiquidityPoolWithdrawResultCode +} + +var _XdrTags_LiquidityPoolWithdrawResult = map[int32]bool{ + XdrToI32(LIQUIDITY_POOL_WITHDRAW_SUCCESS): true, + XdrToI32(LIQUIDITY_POOL_WITHDRAW_MALFORMED): true, + XdrToI32(LIQUIDITY_POOL_WITHDRAW_NO_TRUST): true, + XdrToI32(LIQUIDITY_POOL_WITHDRAW_UNDERFUNDED): true, + XdrToI32(LIQUIDITY_POOL_WITHDRAW_LINE_FULL): true, + XdrToI32(LIQUIDITY_POOL_WITHDRAW_UNDER_MINIMUM): true, +} + +func (_ LiquidityPoolWithdrawResult) XdrValidTags() map[int32]bool { + return _XdrTags_LiquidityPoolWithdrawResult +} +func (u LiquidityPoolWithdrawResult) XdrValid() bool { + switch u.Code { + case LIQUIDITY_POOL_WITHDRAW_SUCCESS, LIQUIDITY_POOL_WITHDRAW_MALFORMED, LIQUIDITY_POOL_WITHDRAW_NO_TRUST, LIQUIDITY_POOL_WITHDRAW_UNDERFUNDED, LIQUIDITY_POOL_WITHDRAW_LINE_FULL, LIQUIDITY_POOL_WITHDRAW_UNDER_MINIMUM: + return true + } + return false +} +func (u *LiquidityPoolWithdrawResult) XdrUnionTag() XdrNum32 { + return XDR_LiquidityPoolWithdrawResultCode(&u.Code) +} +func (u *LiquidityPoolWithdrawResult) XdrUnionTagName() string { + return "Code" +} +func (u *LiquidityPoolWithdrawResult) XdrUnionBody() XdrType { + switch u.Code { + case LIQUIDITY_POOL_WITHDRAW_SUCCESS: + return nil + case LIQUIDITY_POOL_WITHDRAW_MALFORMED, LIQUIDITY_POOL_WITHDRAW_NO_TRUST, LIQUIDITY_POOL_WITHDRAW_UNDERFUNDED, LIQUIDITY_POOL_WITHDRAW_LINE_FULL, LIQUIDITY_POOL_WITHDRAW_UNDER_MINIMUM: + return nil + } + return nil +} +func (u *LiquidityPoolWithdrawResult) XdrUnionBodyName() string { + switch u.Code { + case LIQUIDITY_POOL_WITHDRAW_SUCCESS: + return "" + case LIQUIDITY_POOL_WITHDRAW_MALFORMED, LIQUIDITY_POOL_WITHDRAW_NO_TRUST, LIQUIDITY_POOL_WITHDRAW_UNDERFUNDED, LIQUIDITY_POOL_WITHDRAW_LINE_FULL, LIQUIDITY_POOL_WITHDRAW_UNDER_MINIMUM: + return "" + } + return "" +} + +type XdrType_LiquidityPoolWithdrawResult = *LiquidityPoolWithdrawResult + +func (v *LiquidityPoolWithdrawResult) XdrPointer() interface{} { return v } +func (LiquidityPoolWithdrawResult) XdrTypeName() string { return "LiquidityPoolWithdrawResult" } +func (v LiquidityPoolWithdrawResult) XdrValue() interface{} { return v } +func (v *LiquidityPoolWithdrawResult) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (u *LiquidityPoolWithdrawResult) XdrRecurse(x XDR, name string) { + if name != "" { + name = x.Sprintf("%s.", name) + } + XDR_LiquidityPoolWithdrawResultCode(&u.Code).XdrMarshal(x, x.Sprintf("%scode", name)) + switch u.Code { + case LIQUIDITY_POOL_WITHDRAW_SUCCESS: + return + case LIQUIDITY_POOL_WITHDRAW_MALFORMED, LIQUIDITY_POOL_WITHDRAW_NO_TRUST, LIQUIDITY_POOL_WITHDRAW_UNDERFUNDED, LIQUIDITY_POOL_WITHDRAW_LINE_FULL, LIQUIDITY_POOL_WITHDRAW_UNDER_MINIMUM: + return + } + XdrPanic("invalid Code (%v) in LiquidityPoolWithdrawResult", u.Code) +} +func XDR_LiquidityPoolWithdrawResult(v *LiquidityPoolWithdrawResult) *LiquidityPoolWithdrawResult { + return v +} + +var _XdrNames_InvokeHostFunctionResultCode = map[int32]string{ + int32(INVOKE_HOST_FUNCTION_SUCCESS): "INVOKE_HOST_FUNCTION_SUCCESS", + int32(INVOKE_HOST_FUNCTION_MALFORMED): "INVOKE_HOST_FUNCTION_MALFORMED", + int32(INVOKE_HOST_FUNCTION_TRAPPED): "INVOKE_HOST_FUNCTION_TRAPPED", + int32(INVOKE_HOST_FUNCTION_RESOURCE_LIMIT_EXCEEDED): "INVOKE_HOST_FUNCTION_RESOURCE_LIMIT_EXCEEDED", + int32(INVOKE_HOST_FUNCTION_ENTRY_ARCHIVED): "INVOKE_HOST_FUNCTION_ENTRY_ARCHIVED", + int32(INVOKE_HOST_FUNCTION_INSUFFICIENT_REFUNDABLE_FEE): "INVOKE_HOST_FUNCTION_INSUFFICIENT_REFUNDABLE_FEE", +} +var _XdrValues_InvokeHostFunctionResultCode = map[string]int32{ + "INVOKE_HOST_FUNCTION_SUCCESS": int32(INVOKE_HOST_FUNCTION_SUCCESS), + "INVOKE_HOST_FUNCTION_MALFORMED": int32(INVOKE_HOST_FUNCTION_MALFORMED), + "INVOKE_HOST_FUNCTION_TRAPPED": int32(INVOKE_HOST_FUNCTION_TRAPPED), + "INVOKE_HOST_FUNCTION_RESOURCE_LIMIT_EXCEEDED": int32(INVOKE_HOST_FUNCTION_RESOURCE_LIMIT_EXCEEDED), + "INVOKE_HOST_FUNCTION_ENTRY_ARCHIVED": int32(INVOKE_HOST_FUNCTION_ENTRY_ARCHIVED), + "INVOKE_HOST_FUNCTION_INSUFFICIENT_REFUNDABLE_FEE": int32(INVOKE_HOST_FUNCTION_INSUFFICIENT_REFUNDABLE_FEE), +} + +func (InvokeHostFunctionResultCode) XdrEnumNames() map[int32]string { + return _XdrNames_InvokeHostFunctionResultCode +} +func (v InvokeHostFunctionResultCode) String() string { + if s, ok := _XdrNames_InvokeHostFunctionResultCode[int32(v)]; ok { + return s + } + return fmt.Sprintf("InvokeHostFunctionResultCode#%d", v) +} +func (v *InvokeHostFunctionResultCode) Scan(ss fmt.ScanState, _ rune) error { + if tok, err := ss.Token(true, XdrSymChar); err != nil { + return err + } else { + stok := string(tok) + if val, ok := _XdrValues_InvokeHostFunctionResultCode[stok]; ok { + *v = InvokeHostFunctionResultCode(val) + return nil + } else if stok == "InvokeHostFunctionResultCode" { + if n, err := fmt.Fscanf(ss, "#%d", (*int32)(v)); n == 1 && err == nil { + return nil + } + } + return XdrError(fmt.Sprintf("%s is not a valid InvokeHostFunctionResultCode.", stok)) + } +} +func (v InvokeHostFunctionResultCode) GetU32() uint32 { return uint32(v) } +func (v *InvokeHostFunctionResultCode) SetU32(n uint32) { *v = InvokeHostFunctionResultCode(n) } +func (v *InvokeHostFunctionResultCode) XdrPointer() interface{} { return v } +func (InvokeHostFunctionResultCode) XdrTypeName() string { return "InvokeHostFunctionResultCode" } +func (v InvokeHostFunctionResultCode) XdrValue() interface{} { return v } +func (v *InvokeHostFunctionResultCode) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } + +type XdrType_InvokeHostFunctionResultCode = *InvokeHostFunctionResultCode + +func XDR_InvokeHostFunctionResultCode(v *InvokeHostFunctionResultCode) *InvokeHostFunctionResultCode { + return v +} + +var _XdrComments_InvokeHostFunctionResultCode = map[int32]string{ + int32(INVOKE_HOST_FUNCTION_SUCCESS): "codes considered as \"success\" for the operation", + int32(INVOKE_HOST_FUNCTION_MALFORMED): "codes considered as \"failure\" for the operation", +} + +func (e InvokeHostFunctionResultCode) XdrEnumComments() map[int32]string { + return _XdrComments_InvokeHostFunctionResultCode +} + +var _XdrTags_InvokeHostFunctionResult = map[int32]bool{ + XdrToI32(INVOKE_HOST_FUNCTION_SUCCESS): true, + XdrToI32(INVOKE_HOST_FUNCTION_MALFORMED): true, + XdrToI32(INVOKE_HOST_FUNCTION_TRAPPED): true, + XdrToI32(INVOKE_HOST_FUNCTION_RESOURCE_LIMIT_EXCEEDED): true, + XdrToI32(INVOKE_HOST_FUNCTION_ENTRY_ARCHIVED): true, + XdrToI32(INVOKE_HOST_FUNCTION_INSUFFICIENT_REFUNDABLE_FEE): true, +} + +func (_ InvokeHostFunctionResult) XdrValidTags() map[int32]bool { + return _XdrTags_InvokeHostFunctionResult +} + +// sha256(InvokeHostFunctionSuccessPreImage) +func (u *InvokeHostFunctionResult) Success() *Hash { + switch u.Code { + case INVOKE_HOST_FUNCTION_SUCCESS: + if v, ok := u._u.(*Hash); ok { + return v + } else { + var zero Hash + u._u = &zero + return &zero + } + default: + XdrPanic("InvokeHostFunctionResult.Success accessed when Code == %v", u.Code) + return nil + } +} +func (u InvokeHostFunctionResult) XdrValid() bool { + switch u.Code { + case INVOKE_HOST_FUNCTION_SUCCESS, INVOKE_HOST_FUNCTION_MALFORMED, INVOKE_HOST_FUNCTION_TRAPPED, INVOKE_HOST_FUNCTION_RESOURCE_LIMIT_EXCEEDED, INVOKE_HOST_FUNCTION_ENTRY_ARCHIVED, INVOKE_HOST_FUNCTION_INSUFFICIENT_REFUNDABLE_FEE: + return true + } + return false +} +func (u *InvokeHostFunctionResult) XdrUnionTag() XdrNum32 { + return XDR_InvokeHostFunctionResultCode(&u.Code) +} +func (u *InvokeHostFunctionResult) XdrUnionTagName() string { + return "Code" +} +func (u *InvokeHostFunctionResult) XdrUnionBody() XdrType { + switch u.Code { + case INVOKE_HOST_FUNCTION_SUCCESS: + return XDR_Hash(u.Success()) + case INVOKE_HOST_FUNCTION_MALFORMED, INVOKE_HOST_FUNCTION_TRAPPED, INVOKE_HOST_FUNCTION_RESOURCE_LIMIT_EXCEEDED, INVOKE_HOST_FUNCTION_ENTRY_ARCHIVED, INVOKE_HOST_FUNCTION_INSUFFICIENT_REFUNDABLE_FEE: + return nil + } + return nil +} +func (u *InvokeHostFunctionResult) XdrUnionBodyName() string { + switch u.Code { + case INVOKE_HOST_FUNCTION_SUCCESS: + return "Success" + case INVOKE_HOST_FUNCTION_MALFORMED, INVOKE_HOST_FUNCTION_TRAPPED, INVOKE_HOST_FUNCTION_RESOURCE_LIMIT_EXCEEDED, INVOKE_HOST_FUNCTION_ENTRY_ARCHIVED, INVOKE_HOST_FUNCTION_INSUFFICIENT_REFUNDABLE_FEE: + return "" + } + return "" +} + +type XdrType_InvokeHostFunctionResult = *InvokeHostFunctionResult + +func (v *InvokeHostFunctionResult) XdrPointer() interface{} { return v } +func (InvokeHostFunctionResult) XdrTypeName() string { return "InvokeHostFunctionResult" } +func (v InvokeHostFunctionResult) XdrValue() interface{} { return v } +func (v *InvokeHostFunctionResult) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (u *InvokeHostFunctionResult) XdrRecurse(x XDR, name string) { + if name != "" { + name = x.Sprintf("%s.", name) + } + XDR_InvokeHostFunctionResultCode(&u.Code).XdrMarshal(x, x.Sprintf("%scode", name)) + switch u.Code { + case INVOKE_HOST_FUNCTION_SUCCESS: + x.Marshal(x.Sprintf("%ssuccess", name), XDR_Hash(u.Success())) + return + case INVOKE_HOST_FUNCTION_MALFORMED, INVOKE_HOST_FUNCTION_TRAPPED, INVOKE_HOST_FUNCTION_RESOURCE_LIMIT_EXCEEDED, INVOKE_HOST_FUNCTION_ENTRY_ARCHIVED, INVOKE_HOST_FUNCTION_INSUFFICIENT_REFUNDABLE_FEE: + return + } + XdrPanic("invalid Code (%v) in InvokeHostFunctionResult", u.Code) +} +func XDR_InvokeHostFunctionResult(v *InvokeHostFunctionResult) *InvokeHostFunctionResult { return v } + +var _XdrNames_ExtendFootprintTTLResultCode = map[int32]string{ + int32(EXTEND_FOOTPRINT_TTL_SUCCESS): "EXTEND_FOOTPRINT_TTL_SUCCESS", + int32(EXTEND_FOOTPRINT_TTL_MALFORMED): "EXTEND_FOOTPRINT_TTL_MALFORMED", + int32(EXTEND_FOOTPRINT_TTL_RESOURCE_LIMIT_EXCEEDED): "EXTEND_FOOTPRINT_TTL_RESOURCE_LIMIT_EXCEEDED", + int32(EXTEND_FOOTPRINT_TTL_INSUFFICIENT_REFUNDABLE_FEE): "EXTEND_FOOTPRINT_TTL_INSUFFICIENT_REFUNDABLE_FEE", +} +var _XdrValues_ExtendFootprintTTLResultCode = map[string]int32{ + "EXTEND_FOOTPRINT_TTL_SUCCESS": int32(EXTEND_FOOTPRINT_TTL_SUCCESS), + "EXTEND_FOOTPRINT_TTL_MALFORMED": int32(EXTEND_FOOTPRINT_TTL_MALFORMED), + "EXTEND_FOOTPRINT_TTL_RESOURCE_LIMIT_EXCEEDED": int32(EXTEND_FOOTPRINT_TTL_RESOURCE_LIMIT_EXCEEDED), + "EXTEND_FOOTPRINT_TTL_INSUFFICIENT_REFUNDABLE_FEE": int32(EXTEND_FOOTPRINT_TTL_INSUFFICIENT_REFUNDABLE_FEE), +} + +func (ExtendFootprintTTLResultCode) XdrEnumNames() map[int32]string { + return _XdrNames_ExtendFootprintTTLResultCode +} +func (v ExtendFootprintTTLResultCode) String() string { + if s, ok := _XdrNames_ExtendFootprintTTLResultCode[int32(v)]; ok { + return s + } + return fmt.Sprintf("ExtendFootprintTTLResultCode#%d", v) +} +func (v *ExtendFootprintTTLResultCode) Scan(ss fmt.ScanState, _ rune) error { + if tok, err := ss.Token(true, XdrSymChar); err != nil { + return err + } else { + stok := string(tok) + if val, ok := _XdrValues_ExtendFootprintTTLResultCode[stok]; ok { + *v = ExtendFootprintTTLResultCode(val) + return nil + } else if stok == "ExtendFootprintTTLResultCode" { + if n, err := fmt.Fscanf(ss, "#%d", (*int32)(v)); n == 1 && err == nil { + return nil + } + } + return XdrError(fmt.Sprintf("%s is not a valid ExtendFootprintTTLResultCode.", stok)) + } +} +func (v ExtendFootprintTTLResultCode) GetU32() uint32 { return uint32(v) } +func (v *ExtendFootprintTTLResultCode) SetU32(n uint32) { *v = ExtendFootprintTTLResultCode(n) } +func (v *ExtendFootprintTTLResultCode) XdrPointer() interface{} { return v } +func (ExtendFootprintTTLResultCode) XdrTypeName() string { return "ExtendFootprintTTLResultCode" } +func (v ExtendFootprintTTLResultCode) XdrValue() interface{} { return v } +func (v *ExtendFootprintTTLResultCode) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } + +type XdrType_ExtendFootprintTTLResultCode = *ExtendFootprintTTLResultCode + +func XDR_ExtendFootprintTTLResultCode(v *ExtendFootprintTTLResultCode) *ExtendFootprintTTLResultCode { + return v +} + +var _XdrComments_ExtendFootprintTTLResultCode = map[int32]string{ + int32(EXTEND_FOOTPRINT_TTL_SUCCESS): "codes considered as \"success\" for the operation", + int32(EXTEND_FOOTPRINT_TTL_MALFORMED): "codes considered as \"failure\" for the operation", +} + +func (e ExtendFootprintTTLResultCode) XdrEnumComments() map[int32]string { + return _XdrComments_ExtendFootprintTTLResultCode +} + +var _XdrTags_ExtendFootprintTTLResult = map[int32]bool{ + XdrToI32(EXTEND_FOOTPRINT_TTL_SUCCESS): true, + XdrToI32(EXTEND_FOOTPRINT_TTL_MALFORMED): true, + XdrToI32(EXTEND_FOOTPRINT_TTL_RESOURCE_LIMIT_EXCEEDED): true, + XdrToI32(EXTEND_FOOTPRINT_TTL_INSUFFICIENT_REFUNDABLE_FEE): true, +} + +func (_ ExtendFootprintTTLResult) XdrValidTags() map[int32]bool { + return _XdrTags_ExtendFootprintTTLResult +} +func (u ExtendFootprintTTLResult) XdrValid() bool { + switch u.Code { + case EXTEND_FOOTPRINT_TTL_SUCCESS, EXTEND_FOOTPRINT_TTL_MALFORMED, EXTEND_FOOTPRINT_TTL_RESOURCE_LIMIT_EXCEEDED, EXTEND_FOOTPRINT_TTL_INSUFFICIENT_REFUNDABLE_FEE: + return true + } + return false +} +func (u *ExtendFootprintTTLResult) XdrUnionTag() XdrNum32 { + return XDR_ExtendFootprintTTLResultCode(&u.Code) +} +func (u *ExtendFootprintTTLResult) XdrUnionTagName() string { + return "Code" +} +func (u *ExtendFootprintTTLResult) XdrUnionBody() XdrType { + switch u.Code { + case EXTEND_FOOTPRINT_TTL_SUCCESS: + return nil + case EXTEND_FOOTPRINT_TTL_MALFORMED, EXTEND_FOOTPRINT_TTL_RESOURCE_LIMIT_EXCEEDED, EXTEND_FOOTPRINT_TTL_INSUFFICIENT_REFUNDABLE_FEE: + return nil + } + return nil +} +func (u *ExtendFootprintTTLResult) XdrUnionBodyName() string { + switch u.Code { + case EXTEND_FOOTPRINT_TTL_SUCCESS: + return "" + case EXTEND_FOOTPRINT_TTL_MALFORMED, EXTEND_FOOTPRINT_TTL_RESOURCE_LIMIT_EXCEEDED, EXTEND_FOOTPRINT_TTL_INSUFFICIENT_REFUNDABLE_FEE: + return "" + } + return "" +} + +type XdrType_ExtendFootprintTTLResult = *ExtendFootprintTTLResult + +func (v *ExtendFootprintTTLResult) XdrPointer() interface{} { return v } +func (ExtendFootprintTTLResult) XdrTypeName() string { return "ExtendFootprintTTLResult" } +func (v ExtendFootprintTTLResult) XdrValue() interface{} { return v } +func (v *ExtendFootprintTTLResult) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (u *ExtendFootprintTTLResult) XdrRecurse(x XDR, name string) { + if name != "" { + name = x.Sprintf("%s.", name) + } + XDR_ExtendFootprintTTLResultCode(&u.Code).XdrMarshal(x, x.Sprintf("%scode", name)) + switch u.Code { + case EXTEND_FOOTPRINT_TTL_SUCCESS: + return + case EXTEND_FOOTPRINT_TTL_MALFORMED, EXTEND_FOOTPRINT_TTL_RESOURCE_LIMIT_EXCEEDED, EXTEND_FOOTPRINT_TTL_INSUFFICIENT_REFUNDABLE_FEE: + return + } + XdrPanic("invalid Code (%v) in ExtendFootprintTTLResult", u.Code) +} +func XDR_ExtendFootprintTTLResult(v *ExtendFootprintTTLResult) *ExtendFootprintTTLResult { return v } + +var _XdrNames_RestoreFootprintResultCode = map[int32]string{ + int32(RESTORE_FOOTPRINT_SUCCESS): "RESTORE_FOOTPRINT_SUCCESS", + int32(RESTORE_FOOTPRINT_MALFORMED): "RESTORE_FOOTPRINT_MALFORMED", + int32(RESTORE_FOOTPRINT_RESOURCE_LIMIT_EXCEEDED): "RESTORE_FOOTPRINT_RESOURCE_LIMIT_EXCEEDED", + int32(RESTORE_FOOTPRINT_INSUFFICIENT_REFUNDABLE_FEE): "RESTORE_FOOTPRINT_INSUFFICIENT_REFUNDABLE_FEE", +} +var _XdrValues_RestoreFootprintResultCode = map[string]int32{ + "RESTORE_FOOTPRINT_SUCCESS": int32(RESTORE_FOOTPRINT_SUCCESS), + "RESTORE_FOOTPRINT_MALFORMED": int32(RESTORE_FOOTPRINT_MALFORMED), + "RESTORE_FOOTPRINT_RESOURCE_LIMIT_EXCEEDED": int32(RESTORE_FOOTPRINT_RESOURCE_LIMIT_EXCEEDED), + "RESTORE_FOOTPRINT_INSUFFICIENT_REFUNDABLE_FEE": int32(RESTORE_FOOTPRINT_INSUFFICIENT_REFUNDABLE_FEE), +} + +func (RestoreFootprintResultCode) XdrEnumNames() map[int32]string { + return _XdrNames_RestoreFootprintResultCode +} +func (v RestoreFootprintResultCode) String() string { + if s, ok := _XdrNames_RestoreFootprintResultCode[int32(v)]; ok { + return s + } + return fmt.Sprintf("RestoreFootprintResultCode#%d", v) +} +func (v *RestoreFootprintResultCode) Scan(ss fmt.ScanState, _ rune) error { + if tok, err := ss.Token(true, XdrSymChar); err != nil { + return err + } else { + stok := string(tok) + if val, ok := _XdrValues_RestoreFootprintResultCode[stok]; ok { + *v = RestoreFootprintResultCode(val) + return nil + } else if stok == "RestoreFootprintResultCode" { + if n, err := fmt.Fscanf(ss, "#%d", (*int32)(v)); n == 1 && err == nil { + return nil + } + } + return XdrError(fmt.Sprintf("%s is not a valid RestoreFootprintResultCode.", stok)) + } +} +func (v RestoreFootprintResultCode) GetU32() uint32 { return uint32(v) } +func (v *RestoreFootprintResultCode) SetU32(n uint32) { *v = RestoreFootprintResultCode(n) } +func (v *RestoreFootprintResultCode) XdrPointer() interface{} { return v } +func (RestoreFootprintResultCode) XdrTypeName() string { return "RestoreFootprintResultCode" } +func (v RestoreFootprintResultCode) XdrValue() interface{} { return v } +func (v *RestoreFootprintResultCode) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } + +type XdrType_RestoreFootprintResultCode = *RestoreFootprintResultCode + +func XDR_RestoreFootprintResultCode(v *RestoreFootprintResultCode) *RestoreFootprintResultCode { + return v +} + +var _XdrComments_RestoreFootprintResultCode = map[int32]string{ + int32(RESTORE_FOOTPRINT_SUCCESS): "codes considered as \"success\" for the operation", + int32(RESTORE_FOOTPRINT_MALFORMED): "codes considered as \"failure\" for the operation", +} + +func (e RestoreFootprintResultCode) XdrEnumComments() map[int32]string { + return _XdrComments_RestoreFootprintResultCode +} + +var _XdrTags_RestoreFootprintResult = map[int32]bool{ + XdrToI32(RESTORE_FOOTPRINT_SUCCESS): true, + XdrToI32(RESTORE_FOOTPRINT_MALFORMED): true, + XdrToI32(RESTORE_FOOTPRINT_RESOURCE_LIMIT_EXCEEDED): true, + XdrToI32(RESTORE_FOOTPRINT_INSUFFICIENT_REFUNDABLE_FEE): true, +} + +func (_ RestoreFootprintResult) XdrValidTags() map[int32]bool { + return _XdrTags_RestoreFootprintResult +} +func (u RestoreFootprintResult) XdrValid() bool { + switch u.Code { + case RESTORE_FOOTPRINT_SUCCESS, RESTORE_FOOTPRINT_MALFORMED, RESTORE_FOOTPRINT_RESOURCE_LIMIT_EXCEEDED, RESTORE_FOOTPRINT_INSUFFICIENT_REFUNDABLE_FEE: + return true + } + return false +} +func (u *RestoreFootprintResult) XdrUnionTag() XdrNum32 { + return XDR_RestoreFootprintResultCode(&u.Code) +} +func (u *RestoreFootprintResult) XdrUnionTagName() string { + return "Code" +} +func (u *RestoreFootprintResult) XdrUnionBody() XdrType { + switch u.Code { + case RESTORE_FOOTPRINT_SUCCESS: + return nil + case RESTORE_FOOTPRINT_MALFORMED, RESTORE_FOOTPRINT_RESOURCE_LIMIT_EXCEEDED, RESTORE_FOOTPRINT_INSUFFICIENT_REFUNDABLE_FEE: + return nil + } + return nil +} +func (u *RestoreFootprintResult) XdrUnionBodyName() string { + switch u.Code { + case RESTORE_FOOTPRINT_SUCCESS: + return "" + case RESTORE_FOOTPRINT_MALFORMED, RESTORE_FOOTPRINT_RESOURCE_LIMIT_EXCEEDED, RESTORE_FOOTPRINT_INSUFFICIENT_REFUNDABLE_FEE: + return "" + } + return "" +} + +type XdrType_RestoreFootprintResult = *RestoreFootprintResult + +func (v *RestoreFootprintResult) XdrPointer() interface{} { return v } +func (RestoreFootprintResult) XdrTypeName() string { return "RestoreFootprintResult" } +func (v RestoreFootprintResult) XdrValue() interface{} { return v } +func (v *RestoreFootprintResult) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (u *RestoreFootprintResult) XdrRecurse(x XDR, name string) { + if name != "" { + name = x.Sprintf("%s.", name) + } + XDR_RestoreFootprintResultCode(&u.Code).XdrMarshal(x, x.Sprintf("%scode", name)) + switch u.Code { + case RESTORE_FOOTPRINT_SUCCESS: + return + case RESTORE_FOOTPRINT_MALFORMED, RESTORE_FOOTPRINT_RESOURCE_LIMIT_EXCEEDED, RESTORE_FOOTPRINT_INSUFFICIENT_REFUNDABLE_FEE: + return + } + XdrPanic("invalid Code (%v) in RestoreFootprintResult", u.Code) +} +func XDR_RestoreFootprintResult(v *RestoreFootprintResult) *RestoreFootprintResult { return v } + +var _XdrNames_OperationResultCode = map[int32]string{ + int32(OpINNER): "opINNER", + int32(OpBAD_AUTH): "opBAD_AUTH", + int32(OpNO_ACCOUNT): "opNO_ACCOUNT", + int32(OpNOT_SUPPORTED): "opNOT_SUPPORTED", + int32(OpTOO_MANY_SUBENTRIES): "opTOO_MANY_SUBENTRIES", + int32(OpEXCEEDED_WORK_LIMIT): "opEXCEEDED_WORK_LIMIT", + int32(OpTOO_MANY_SPONSORING): "opTOO_MANY_SPONSORING", +} +var _XdrValues_OperationResultCode = map[string]int32{ + "opINNER": int32(OpINNER), + "opBAD_AUTH": int32(OpBAD_AUTH), + "opNO_ACCOUNT": int32(OpNO_ACCOUNT), + "opNOT_SUPPORTED": int32(OpNOT_SUPPORTED), + "opTOO_MANY_SUBENTRIES": int32(OpTOO_MANY_SUBENTRIES), + "opEXCEEDED_WORK_LIMIT": int32(OpEXCEEDED_WORK_LIMIT), + "opTOO_MANY_SPONSORING": int32(OpTOO_MANY_SPONSORING), +} + +func (OperationResultCode) XdrEnumNames() map[int32]string { + return _XdrNames_OperationResultCode +} +func (v OperationResultCode) String() string { + if s, ok := _XdrNames_OperationResultCode[int32(v)]; ok { + return s + } + return fmt.Sprintf("OperationResultCode#%d", v) +} +func (v *OperationResultCode) Scan(ss fmt.ScanState, _ rune) error { + if tok, err := ss.Token(true, XdrSymChar); err != nil { + return err + } else { + stok := string(tok) + if val, ok := _XdrValues_OperationResultCode[stok]; ok { + *v = OperationResultCode(val) + return nil + } else if stok == "OperationResultCode" { + if n, err := fmt.Fscanf(ss, "#%d", (*int32)(v)); n == 1 && err == nil { + return nil + } + } + return XdrError(fmt.Sprintf("%s is not a valid OperationResultCode.", stok)) + } +} +func (v OperationResultCode) GetU32() uint32 { return uint32(v) } +func (v *OperationResultCode) SetU32(n uint32) { *v = OperationResultCode(n) } +func (v *OperationResultCode) XdrPointer() interface{} { return v } +func (OperationResultCode) XdrTypeName() string { return "OperationResultCode" } +func (v OperationResultCode) XdrValue() interface{} { return v } +func (v *OperationResultCode) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } + +type XdrType_OperationResultCode = *OperationResultCode + +func XDR_OperationResultCode(v *OperationResultCode) *OperationResultCode { return v } + +var _XdrComments_OperationResultCode = map[int32]string{ + int32(OpINNER): "inner object result is valid", + int32(OpBAD_AUTH): "too few valid signatures / wrong network", + int32(OpNO_ACCOUNT): "source account was not found", + int32(OpNOT_SUPPORTED): "operation not supported at this time", + int32(OpTOO_MANY_SUBENTRIES): "max number of subentries already reached", + int32(OpEXCEEDED_WORK_LIMIT): "operation did too much work", + int32(OpTOO_MANY_SPONSORING): "account is sponsoring too many entries", +} + +func (e OperationResultCode) XdrEnumComments() map[int32]string { + return _XdrComments_OperationResultCode +} + +var _XdrTags_XdrAnon_OperationResult_Tr = map[int32]bool{ + XdrToI32(CREATE_ACCOUNT): true, + XdrToI32(PAYMENT): true, + XdrToI32(PATH_PAYMENT_STRICT_RECEIVE): true, + XdrToI32(MANAGE_SELL_OFFER): true, + XdrToI32(CREATE_PASSIVE_SELL_OFFER): true, + XdrToI32(SET_OPTIONS): true, + XdrToI32(CHANGE_TRUST): true, + XdrToI32(ALLOW_TRUST): true, + XdrToI32(ACCOUNT_MERGE): true, + XdrToI32(INFLATION): true, + XdrToI32(MANAGE_DATA): true, + XdrToI32(BUMP_SEQUENCE): true, + XdrToI32(MANAGE_BUY_OFFER): true, + XdrToI32(PATH_PAYMENT_STRICT_SEND): true, + XdrToI32(CREATE_CLAIMABLE_BALANCE): true, + XdrToI32(CLAIM_CLAIMABLE_BALANCE): true, + XdrToI32(BEGIN_SPONSORING_FUTURE_RESERVES): true, + XdrToI32(END_SPONSORING_FUTURE_RESERVES): true, + XdrToI32(REVOKE_SPONSORSHIP): true, + XdrToI32(CLAWBACK): true, + XdrToI32(CLAWBACK_CLAIMABLE_BALANCE): true, + XdrToI32(SET_TRUST_LINE_FLAGS): true, + XdrToI32(LIQUIDITY_POOL_DEPOSIT): true, + XdrToI32(LIQUIDITY_POOL_WITHDRAW): true, + XdrToI32(INVOKE_HOST_FUNCTION): true, + XdrToI32(EXTEND_FOOTPRINT_TTL): true, + XdrToI32(RESTORE_FOOTPRINT): true, +} + +func (_ XdrAnon_OperationResult_Tr) XdrValidTags() map[int32]bool { + return _XdrTags_XdrAnon_OperationResult_Tr +} +func (u *XdrAnon_OperationResult_Tr) CreateAccountResult() *CreateAccountResult { + switch u.Type { + case CREATE_ACCOUNT: + if v, ok := u._u.(*CreateAccountResult); ok { + return v + } else { + var zero CreateAccountResult + u._u = &zero + return &zero + } + default: + XdrPanic("XdrAnon_OperationResult_Tr.CreateAccountResult accessed when Type == %v", u.Type) + return nil + } +} +func (u *XdrAnon_OperationResult_Tr) PaymentResult() *PaymentResult { + switch u.Type { + case PAYMENT: + if v, ok := u._u.(*PaymentResult); ok { + return v + } else { + var zero PaymentResult + u._u = &zero + return &zero + } + default: + XdrPanic("XdrAnon_OperationResult_Tr.PaymentResult accessed when Type == %v", u.Type) + return nil + } +} +func (u *XdrAnon_OperationResult_Tr) PathPaymentStrictReceiveResult() *PathPaymentStrictReceiveResult { + switch u.Type { + case PATH_PAYMENT_STRICT_RECEIVE: + if v, ok := u._u.(*PathPaymentStrictReceiveResult); ok { + return v + } else { + var zero PathPaymentStrictReceiveResult + u._u = &zero + return &zero + } + default: + XdrPanic("XdrAnon_OperationResult_Tr.PathPaymentStrictReceiveResult accessed when Type == %v", u.Type) + return nil + } +} +func (u *XdrAnon_OperationResult_Tr) ManageSellOfferResult() *ManageSellOfferResult { + switch u.Type { + case MANAGE_SELL_OFFER: + if v, ok := u._u.(*ManageSellOfferResult); ok { + return v + } else { + var zero ManageSellOfferResult + u._u = &zero + return &zero + } + default: + XdrPanic("XdrAnon_OperationResult_Tr.ManageSellOfferResult accessed when Type == %v", u.Type) + return nil + } +} +func (u *XdrAnon_OperationResult_Tr) CreatePassiveSellOfferResult() *ManageSellOfferResult { + switch u.Type { + case CREATE_PASSIVE_SELL_OFFER: + if v, ok := u._u.(*ManageSellOfferResult); ok { + return v + } else { + var zero ManageSellOfferResult + u._u = &zero + return &zero + } + default: + XdrPanic("XdrAnon_OperationResult_Tr.CreatePassiveSellOfferResult accessed when Type == %v", u.Type) + return nil + } +} +func (u *XdrAnon_OperationResult_Tr) SetOptionsResult() *SetOptionsResult { + switch u.Type { + case SET_OPTIONS: + if v, ok := u._u.(*SetOptionsResult); ok { + return v + } else { + var zero SetOptionsResult + u._u = &zero + return &zero + } + default: + XdrPanic("XdrAnon_OperationResult_Tr.SetOptionsResult accessed when Type == %v", u.Type) + return nil + } +} +func (u *XdrAnon_OperationResult_Tr) ChangeTrustResult() *ChangeTrustResult { + switch u.Type { + case CHANGE_TRUST: + if v, ok := u._u.(*ChangeTrustResult); ok { + return v + } else { + var zero ChangeTrustResult + u._u = &zero + return &zero + } + default: + XdrPanic("XdrAnon_OperationResult_Tr.ChangeTrustResult accessed when Type == %v", u.Type) + return nil + } +} +func (u *XdrAnon_OperationResult_Tr) AllowTrustResult() *AllowTrustResult { + switch u.Type { + case ALLOW_TRUST: + if v, ok := u._u.(*AllowTrustResult); ok { + return v + } else { + var zero AllowTrustResult + u._u = &zero + return &zero + } + default: + XdrPanic("XdrAnon_OperationResult_Tr.AllowTrustResult accessed when Type == %v", u.Type) + return nil + } +} +func (u *XdrAnon_OperationResult_Tr) AccountMergeResult() *AccountMergeResult { + switch u.Type { + case ACCOUNT_MERGE: + if v, ok := u._u.(*AccountMergeResult); ok { + return v + } else { + var zero AccountMergeResult + u._u = &zero + return &zero + } + default: + XdrPanic("XdrAnon_OperationResult_Tr.AccountMergeResult accessed when Type == %v", u.Type) + return nil + } +} +func (u *XdrAnon_OperationResult_Tr) InflationResult() *InflationResult { + switch u.Type { + case INFLATION: + if v, ok := u._u.(*InflationResult); ok { + return v + } else { + var zero InflationResult + u._u = &zero + return &zero + } + default: + XdrPanic("XdrAnon_OperationResult_Tr.InflationResult accessed when Type == %v", u.Type) + return nil + } +} +func (u *XdrAnon_OperationResult_Tr) ManageDataResult() *ManageDataResult { + switch u.Type { + case MANAGE_DATA: + if v, ok := u._u.(*ManageDataResult); ok { + return v + } else { + var zero ManageDataResult + u._u = &zero + return &zero + } + default: + XdrPanic("XdrAnon_OperationResult_Tr.ManageDataResult accessed when Type == %v", u.Type) + return nil + } +} +func (u *XdrAnon_OperationResult_Tr) BumpSeqResult() *BumpSequenceResult { + switch u.Type { + case BUMP_SEQUENCE: + if v, ok := u._u.(*BumpSequenceResult); ok { + return v + } else { + var zero BumpSequenceResult + u._u = &zero + return &zero + } + default: + XdrPanic("XdrAnon_OperationResult_Tr.BumpSeqResult accessed when Type == %v", u.Type) + return nil + } +} +func (u *XdrAnon_OperationResult_Tr) ManageBuyOfferResult() *ManageBuyOfferResult { + switch u.Type { + case MANAGE_BUY_OFFER: + if v, ok := u._u.(*ManageBuyOfferResult); ok { + return v + } else { + var zero ManageBuyOfferResult + u._u = &zero + return &zero + } + default: + XdrPanic("XdrAnon_OperationResult_Tr.ManageBuyOfferResult accessed when Type == %v", u.Type) + return nil + } +} +func (u *XdrAnon_OperationResult_Tr) PathPaymentStrictSendResult() *PathPaymentStrictSendResult { + switch u.Type { + case PATH_PAYMENT_STRICT_SEND: + if v, ok := u._u.(*PathPaymentStrictSendResult); ok { + return v + } else { + var zero PathPaymentStrictSendResult + u._u = &zero + return &zero + } + default: + XdrPanic("XdrAnon_OperationResult_Tr.PathPaymentStrictSendResult accessed when Type == %v", u.Type) + return nil + } +} +func (u *XdrAnon_OperationResult_Tr) CreateClaimableBalanceResult() *CreateClaimableBalanceResult { + switch u.Type { + case CREATE_CLAIMABLE_BALANCE: + if v, ok := u._u.(*CreateClaimableBalanceResult); ok { + return v + } else { + var zero CreateClaimableBalanceResult + u._u = &zero + return &zero + } + default: + XdrPanic("XdrAnon_OperationResult_Tr.CreateClaimableBalanceResult accessed when Type == %v", u.Type) + return nil + } +} +func (u *XdrAnon_OperationResult_Tr) ClaimClaimableBalanceResult() *ClaimClaimableBalanceResult { + switch u.Type { + case CLAIM_CLAIMABLE_BALANCE: + if v, ok := u._u.(*ClaimClaimableBalanceResult); ok { + return v + } else { + var zero ClaimClaimableBalanceResult + u._u = &zero + return &zero + } + default: + XdrPanic("XdrAnon_OperationResult_Tr.ClaimClaimableBalanceResult accessed when Type == %v", u.Type) + return nil + } +} +func (u *XdrAnon_OperationResult_Tr) BeginSponsoringFutureReservesResult() *BeginSponsoringFutureReservesResult { + switch u.Type { + case BEGIN_SPONSORING_FUTURE_RESERVES: + if v, ok := u._u.(*BeginSponsoringFutureReservesResult); ok { + return v + } else { + var zero BeginSponsoringFutureReservesResult + u._u = &zero + return &zero + } + default: + XdrPanic("XdrAnon_OperationResult_Tr.BeginSponsoringFutureReservesResult accessed when Type == %v", u.Type) + return nil + } +} +func (u *XdrAnon_OperationResult_Tr) EndSponsoringFutureReservesResult() *EndSponsoringFutureReservesResult { + switch u.Type { + case END_SPONSORING_FUTURE_RESERVES: + if v, ok := u._u.(*EndSponsoringFutureReservesResult); ok { + return v + } else { + var zero EndSponsoringFutureReservesResult + u._u = &zero + return &zero + } + default: + XdrPanic("XdrAnon_OperationResult_Tr.EndSponsoringFutureReservesResult accessed when Type == %v", u.Type) + return nil + } +} +func (u *XdrAnon_OperationResult_Tr) RevokeSponsorshipResult() *RevokeSponsorshipResult { + switch u.Type { + case REVOKE_SPONSORSHIP: + if v, ok := u._u.(*RevokeSponsorshipResult); ok { + return v + } else { + var zero RevokeSponsorshipResult + u._u = &zero + return &zero + } + default: + XdrPanic("XdrAnon_OperationResult_Tr.RevokeSponsorshipResult accessed when Type == %v", u.Type) + return nil + } +} +func (u *XdrAnon_OperationResult_Tr) ClawbackResult() *ClawbackResult { + switch u.Type { + case CLAWBACK: + if v, ok := u._u.(*ClawbackResult); ok { + return v + } else { + var zero ClawbackResult + u._u = &zero + return &zero + } + default: + XdrPanic("XdrAnon_OperationResult_Tr.ClawbackResult accessed when Type == %v", u.Type) + return nil + } +} +func (u *XdrAnon_OperationResult_Tr) ClawbackClaimableBalanceResult() *ClawbackClaimableBalanceResult { + switch u.Type { + case CLAWBACK_CLAIMABLE_BALANCE: + if v, ok := u._u.(*ClawbackClaimableBalanceResult); ok { + return v + } else { + var zero ClawbackClaimableBalanceResult + u._u = &zero + return &zero + } + default: + XdrPanic("XdrAnon_OperationResult_Tr.ClawbackClaimableBalanceResult accessed when Type == %v", u.Type) + return nil + } +} +func (u *XdrAnon_OperationResult_Tr) SetTrustLineFlagsResult() *SetTrustLineFlagsResult { + switch u.Type { + case SET_TRUST_LINE_FLAGS: + if v, ok := u._u.(*SetTrustLineFlagsResult); ok { + return v + } else { + var zero SetTrustLineFlagsResult + u._u = &zero + return &zero + } + default: + XdrPanic("XdrAnon_OperationResult_Tr.SetTrustLineFlagsResult accessed when Type == %v", u.Type) + return nil + } +} +func (u *XdrAnon_OperationResult_Tr) LiquidityPoolDepositResult() *LiquidityPoolDepositResult { + switch u.Type { + case LIQUIDITY_POOL_DEPOSIT: + if v, ok := u._u.(*LiquidityPoolDepositResult); ok { + return v + } else { + var zero LiquidityPoolDepositResult + u._u = &zero + return &zero + } + default: + XdrPanic("XdrAnon_OperationResult_Tr.LiquidityPoolDepositResult accessed when Type == %v", u.Type) + return nil + } +} +func (u *XdrAnon_OperationResult_Tr) LiquidityPoolWithdrawResult() *LiquidityPoolWithdrawResult { + switch u.Type { + case LIQUIDITY_POOL_WITHDRAW: + if v, ok := u._u.(*LiquidityPoolWithdrawResult); ok { + return v + } else { + var zero LiquidityPoolWithdrawResult + u._u = &zero + return &zero + } + default: + XdrPanic("XdrAnon_OperationResult_Tr.LiquidityPoolWithdrawResult accessed when Type == %v", u.Type) + return nil + } +} +func (u *XdrAnon_OperationResult_Tr) InvokeHostFunctionResult() *InvokeHostFunctionResult { + switch u.Type { + case INVOKE_HOST_FUNCTION: + if v, ok := u._u.(*InvokeHostFunctionResult); ok { + return v + } else { + var zero InvokeHostFunctionResult + u._u = &zero + return &zero + } + default: + XdrPanic("XdrAnon_OperationResult_Tr.InvokeHostFunctionResult accessed when Type == %v", u.Type) + return nil + } +} +func (u *XdrAnon_OperationResult_Tr) ExtendFootprintTTLResult() *ExtendFootprintTTLResult { + switch u.Type { + case EXTEND_FOOTPRINT_TTL: + if v, ok := u._u.(*ExtendFootprintTTLResult); ok { + return v + } else { + var zero ExtendFootprintTTLResult + u._u = &zero + return &zero + } + default: + XdrPanic("XdrAnon_OperationResult_Tr.ExtendFootprintTTLResult accessed when Type == %v", u.Type) + return nil + } +} +func (u *XdrAnon_OperationResult_Tr) RestoreFootprintResult() *RestoreFootprintResult { + switch u.Type { + case RESTORE_FOOTPRINT: + if v, ok := u._u.(*RestoreFootprintResult); ok { + return v + } else { + var zero RestoreFootprintResult + u._u = &zero + return &zero + } + default: + XdrPanic("XdrAnon_OperationResult_Tr.RestoreFootprintResult accessed when Type == %v", u.Type) + return nil + } +} +func (u XdrAnon_OperationResult_Tr) XdrValid() bool { + switch u.Type { + case CREATE_ACCOUNT, PAYMENT, PATH_PAYMENT_STRICT_RECEIVE, MANAGE_SELL_OFFER, CREATE_PASSIVE_SELL_OFFER, SET_OPTIONS, CHANGE_TRUST, ALLOW_TRUST, ACCOUNT_MERGE, INFLATION, MANAGE_DATA, BUMP_SEQUENCE, MANAGE_BUY_OFFER, PATH_PAYMENT_STRICT_SEND, CREATE_CLAIMABLE_BALANCE, CLAIM_CLAIMABLE_BALANCE, BEGIN_SPONSORING_FUTURE_RESERVES, END_SPONSORING_FUTURE_RESERVES, REVOKE_SPONSORSHIP, CLAWBACK, CLAWBACK_CLAIMABLE_BALANCE, SET_TRUST_LINE_FLAGS, LIQUIDITY_POOL_DEPOSIT, LIQUIDITY_POOL_WITHDRAW, INVOKE_HOST_FUNCTION, EXTEND_FOOTPRINT_TTL, RESTORE_FOOTPRINT: + return true + } + return false +} +func (u *XdrAnon_OperationResult_Tr) XdrUnionTag() XdrNum32 { + return XDR_OperationType(&u.Type) +} +func (u *XdrAnon_OperationResult_Tr) XdrUnionTagName() string { + return "Type" +} +func (u *XdrAnon_OperationResult_Tr) XdrUnionBody() XdrType { + switch u.Type { + case CREATE_ACCOUNT: + return XDR_CreateAccountResult(u.CreateAccountResult()) + case PAYMENT: + return XDR_PaymentResult(u.PaymentResult()) + case PATH_PAYMENT_STRICT_RECEIVE: + return XDR_PathPaymentStrictReceiveResult(u.PathPaymentStrictReceiveResult()) + case MANAGE_SELL_OFFER: + return XDR_ManageSellOfferResult(u.ManageSellOfferResult()) + case CREATE_PASSIVE_SELL_OFFER: + return XDR_ManageSellOfferResult(u.CreatePassiveSellOfferResult()) + case SET_OPTIONS: + return XDR_SetOptionsResult(u.SetOptionsResult()) + case CHANGE_TRUST: + return XDR_ChangeTrustResult(u.ChangeTrustResult()) + case ALLOW_TRUST: + return XDR_AllowTrustResult(u.AllowTrustResult()) + case ACCOUNT_MERGE: + return XDR_AccountMergeResult(u.AccountMergeResult()) + case INFLATION: + return XDR_InflationResult(u.InflationResult()) + case MANAGE_DATA: + return XDR_ManageDataResult(u.ManageDataResult()) + case BUMP_SEQUENCE: + return XDR_BumpSequenceResult(u.BumpSeqResult()) + case MANAGE_BUY_OFFER: + return XDR_ManageBuyOfferResult(u.ManageBuyOfferResult()) + case PATH_PAYMENT_STRICT_SEND: + return XDR_PathPaymentStrictSendResult(u.PathPaymentStrictSendResult()) + case CREATE_CLAIMABLE_BALANCE: + return XDR_CreateClaimableBalanceResult(u.CreateClaimableBalanceResult()) + case CLAIM_CLAIMABLE_BALANCE: + return XDR_ClaimClaimableBalanceResult(u.ClaimClaimableBalanceResult()) + case BEGIN_SPONSORING_FUTURE_RESERVES: + return XDR_BeginSponsoringFutureReservesResult(u.BeginSponsoringFutureReservesResult()) + case END_SPONSORING_FUTURE_RESERVES: + return XDR_EndSponsoringFutureReservesResult(u.EndSponsoringFutureReservesResult()) + case REVOKE_SPONSORSHIP: + return XDR_RevokeSponsorshipResult(u.RevokeSponsorshipResult()) + case CLAWBACK: + return XDR_ClawbackResult(u.ClawbackResult()) + case CLAWBACK_CLAIMABLE_BALANCE: + return XDR_ClawbackClaimableBalanceResult(u.ClawbackClaimableBalanceResult()) + case SET_TRUST_LINE_FLAGS: + return XDR_SetTrustLineFlagsResult(u.SetTrustLineFlagsResult()) + case LIQUIDITY_POOL_DEPOSIT: + return XDR_LiquidityPoolDepositResult(u.LiquidityPoolDepositResult()) + case LIQUIDITY_POOL_WITHDRAW: + return XDR_LiquidityPoolWithdrawResult(u.LiquidityPoolWithdrawResult()) + case INVOKE_HOST_FUNCTION: + return XDR_InvokeHostFunctionResult(u.InvokeHostFunctionResult()) + case EXTEND_FOOTPRINT_TTL: + return XDR_ExtendFootprintTTLResult(u.ExtendFootprintTTLResult()) + case RESTORE_FOOTPRINT: + return XDR_RestoreFootprintResult(u.RestoreFootprintResult()) + } + return nil +} +func (u *XdrAnon_OperationResult_Tr) XdrUnionBodyName() string { + switch u.Type { + case CREATE_ACCOUNT: + return "CreateAccountResult" + case PAYMENT: + return "PaymentResult" + case PATH_PAYMENT_STRICT_RECEIVE: + return "PathPaymentStrictReceiveResult" + case MANAGE_SELL_OFFER: + return "ManageSellOfferResult" + case CREATE_PASSIVE_SELL_OFFER: + return "CreatePassiveSellOfferResult" + case SET_OPTIONS: + return "SetOptionsResult" + case CHANGE_TRUST: + return "ChangeTrustResult" + case ALLOW_TRUST: + return "AllowTrustResult" + case ACCOUNT_MERGE: + return "AccountMergeResult" + case INFLATION: + return "InflationResult" + case MANAGE_DATA: + return "ManageDataResult" + case BUMP_SEQUENCE: + return "BumpSeqResult" + case MANAGE_BUY_OFFER: + return "ManageBuyOfferResult" + case PATH_PAYMENT_STRICT_SEND: + return "PathPaymentStrictSendResult" + case CREATE_CLAIMABLE_BALANCE: + return "CreateClaimableBalanceResult" + case CLAIM_CLAIMABLE_BALANCE: + return "ClaimClaimableBalanceResult" + case BEGIN_SPONSORING_FUTURE_RESERVES: + return "BeginSponsoringFutureReservesResult" + case END_SPONSORING_FUTURE_RESERVES: + return "EndSponsoringFutureReservesResult" + case REVOKE_SPONSORSHIP: + return "RevokeSponsorshipResult" + case CLAWBACK: + return "ClawbackResult" + case CLAWBACK_CLAIMABLE_BALANCE: + return "ClawbackClaimableBalanceResult" + case SET_TRUST_LINE_FLAGS: + return "SetTrustLineFlagsResult" + case LIQUIDITY_POOL_DEPOSIT: + return "LiquidityPoolDepositResult" + case LIQUIDITY_POOL_WITHDRAW: + return "LiquidityPoolWithdrawResult" + case INVOKE_HOST_FUNCTION: + return "InvokeHostFunctionResult" + case EXTEND_FOOTPRINT_TTL: + return "ExtendFootprintTTLResult" + case RESTORE_FOOTPRINT: + return "RestoreFootprintResult" } + return "" } -func (v AccountMergeResultCode) GetU32() uint32 { return uint32(v) } -func (v *AccountMergeResultCode) SetU32(n uint32) { *v = AccountMergeResultCode(n) } -func (v *AccountMergeResultCode) XdrPointer() interface{} { return v } -func (AccountMergeResultCode) XdrTypeName() string { return "AccountMergeResultCode" } -func (v AccountMergeResultCode) XdrValue() interface{} { return v } -func (v *AccountMergeResultCode) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } - -type XdrType_AccountMergeResultCode = *AccountMergeResultCode -func XDR_AccountMergeResultCode(v *AccountMergeResultCode) *AccountMergeResultCode { return v } +type XdrType_XdrAnon_OperationResult_Tr = *XdrAnon_OperationResult_Tr -var _XdrComments_AccountMergeResultCode = map[int32]string{ - int32(ACCOUNT_MERGE_SUCCESS): "codes considered as \"success\" for the operation", - int32(ACCOUNT_MERGE_MALFORMED): "can't merge onto itself", - int32(ACCOUNT_MERGE_NO_ACCOUNT): "destination does not exist", - int32(ACCOUNT_MERGE_IMMUTABLE_SET): "source account has AUTH_IMMUTABLE set", - int32(ACCOUNT_MERGE_HAS_SUB_ENTRIES): "account has trust lines/offers", - int32(ACCOUNT_MERGE_SEQNUM_TOO_FAR): "sequence number is over max allowed", - int32(ACCOUNT_MERGE_DEST_FULL): "can't add source balance to", - int32(ACCOUNT_MERGE_IS_SPONSOR): "destination balance", +func (v *XdrAnon_OperationResult_Tr) XdrPointer() interface{} { return v } +func (XdrAnon_OperationResult_Tr) XdrTypeName() string { return "XdrAnon_OperationResult_Tr" } +func (v XdrAnon_OperationResult_Tr) XdrValue() interface{} { return v } +func (v *XdrAnon_OperationResult_Tr) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (u *XdrAnon_OperationResult_Tr) XdrRecurse(x XDR, name string) { + if name != "" { + name = x.Sprintf("%s.", name) + } + XDR_OperationType(&u.Type).XdrMarshal(x, x.Sprintf("%stype", name)) + switch u.Type { + case CREATE_ACCOUNT: + x.Marshal(x.Sprintf("%screateAccountResult", name), XDR_CreateAccountResult(u.CreateAccountResult())) + return + case PAYMENT: + x.Marshal(x.Sprintf("%spaymentResult", name), XDR_PaymentResult(u.PaymentResult())) + return + case PATH_PAYMENT_STRICT_RECEIVE: + x.Marshal(x.Sprintf("%spathPaymentStrictReceiveResult", name), XDR_PathPaymentStrictReceiveResult(u.PathPaymentStrictReceiveResult())) + return + case MANAGE_SELL_OFFER: + x.Marshal(x.Sprintf("%smanageSellOfferResult", name), XDR_ManageSellOfferResult(u.ManageSellOfferResult())) + return + case CREATE_PASSIVE_SELL_OFFER: + x.Marshal(x.Sprintf("%screatePassiveSellOfferResult", name), XDR_ManageSellOfferResult(u.CreatePassiveSellOfferResult())) + return + case SET_OPTIONS: + x.Marshal(x.Sprintf("%ssetOptionsResult", name), XDR_SetOptionsResult(u.SetOptionsResult())) + return + case CHANGE_TRUST: + x.Marshal(x.Sprintf("%schangeTrustResult", name), XDR_ChangeTrustResult(u.ChangeTrustResult())) + return + case ALLOW_TRUST: + x.Marshal(x.Sprintf("%sallowTrustResult", name), XDR_AllowTrustResult(u.AllowTrustResult())) + return + case ACCOUNT_MERGE: + x.Marshal(x.Sprintf("%saccountMergeResult", name), XDR_AccountMergeResult(u.AccountMergeResult())) + return + case INFLATION: + x.Marshal(x.Sprintf("%sinflationResult", name), XDR_InflationResult(u.InflationResult())) + return + case MANAGE_DATA: + x.Marshal(x.Sprintf("%smanageDataResult", name), XDR_ManageDataResult(u.ManageDataResult())) + return + case BUMP_SEQUENCE: + x.Marshal(x.Sprintf("%sbumpSeqResult", name), XDR_BumpSequenceResult(u.BumpSeqResult())) + return + case MANAGE_BUY_OFFER: + x.Marshal(x.Sprintf("%smanageBuyOfferResult", name), XDR_ManageBuyOfferResult(u.ManageBuyOfferResult())) + return + case PATH_PAYMENT_STRICT_SEND: + x.Marshal(x.Sprintf("%spathPaymentStrictSendResult", name), XDR_PathPaymentStrictSendResult(u.PathPaymentStrictSendResult())) + return + case CREATE_CLAIMABLE_BALANCE: + x.Marshal(x.Sprintf("%screateClaimableBalanceResult", name), XDR_CreateClaimableBalanceResult(u.CreateClaimableBalanceResult())) + return + case CLAIM_CLAIMABLE_BALANCE: + x.Marshal(x.Sprintf("%sclaimClaimableBalanceResult", name), XDR_ClaimClaimableBalanceResult(u.ClaimClaimableBalanceResult())) + return + case BEGIN_SPONSORING_FUTURE_RESERVES: + x.Marshal(x.Sprintf("%sbeginSponsoringFutureReservesResult", name), XDR_BeginSponsoringFutureReservesResult(u.BeginSponsoringFutureReservesResult())) + return + case END_SPONSORING_FUTURE_RESERVES: + x.Marshal(x.Sprintf("%sendSponsoringFutureReservesResult", name), XDR_EndSponsoringFutureReservesResult(u.EndSponsoringFutureReservesResult())) + return + case REVOKE_SPONSORSHIP: + x.Marshal(x.Sprintf("%srevokeSponsorshipResult", name), XDR_RevokeSponsorshipResult(u.RevokeSponsorshipResult())) + return + case CLAWBACK: + x.Marshal(x.Sprintf("%sclawbackResult", name), XDR_ClawbackResult(u.ClawbackResult())) + return + case CLAWBACK_CLAIMABLE_BALANCE: + x.Marshal(x.Sprintf("%sclawbackClaimableBalanceResult", name), XDR_ClawbackClaimableBalanceResult(u.ClawbackClaimableBalanceResult())) + return + case SET_TRUST_LINE_FLAGS: + x.Marshal(x.Sprintf("%ssetTrustLineFlagsResult", name), XDR_SetTrustLineFlagsResult(u.SetTrustLineFlagsResult())) + return + case LIQUIDITY_POOL_DEPOSIT: + x.Marshal(x.Sprintf("%sliquidityPoolDepositResult", name), XDR_LiquidityPoolDepositResult(u.LiquidityPoolDepositResult())) + return + case LIQUIDITY_POOL_WITHDRAW: + x.Marshal(x.Sprintf("%sliquidityPoolWithdrawResult", name), XDR_LiquidityPoolWithdrawResult(u.LiquidityPoolWithdrawResult())) + return + case INVOKE_HOST_FUNCTION: + x.Marshal(x.Sprintf("%sinvokeHostFunctionResult", name), XDR_InvokeHostFunctionResult(u.InvokeHostFunctionResult())) + return + case EXTEND_FOOTPRINT_TTL: + x.Marshal(x.Sprintf("%sextendFootprintTTLResult", name), XDR_ExtendFootprintTTLResult(u.ExtendFootprintTTLResult())) + return + case RESTORE_FOOTPRINT: + x.Marshal(x.Sprintf("%srestoreFootprintResult", name), XDR_RestoreFootprintResult(u.RestoreFootprintResult())) + return + } + XdrPanic("invalid Type (%v) in XdrAnon_OperationResult_Tr", u.Type) } - -func (e AccountMergeResultCode) XdrEnumComments() map[int32]string { - return _XdrComments_AccountMergeResultCode +func XDR_XdrAnon_OperationResult_Tr(v *XdrAnon_OperationResult_Tr) *XdrAnon_OperationResult_Tr { + return v } -var _XdrTags_AccountMergeResult = map[int32]bool{ - XdrToI32(ACCOUNT_MERGE_SUCCESS): true, - XdrToI32(ACCOUNT_MERGE_MALFORMED): true, - XdrToI32(ACCOUNT_MERGE_NO_ACCOUNT): true, - XdrToI32(ACCOUNT_MERGE_IMMUTABLE_SET): true, - XdrToI32(ACCOUNT_MERGE_HAS_SUB_ENTRIES): true, - XdrToI32(ACCOUNT_MERGE_SEQNUM_TOO_FAR): true, - XdrToI32(ACCOUNT_MERGE_DEST_FULL): true, - XdrToI32(ACCOUNT_MERGE_IS_SPONSOR): true, +var _XdrTags_OperationResult = map[int32]bool{ + XdrToI32(OpINNER): true, + XdrToI32(OpBAD_AUTH): true, + XdrToI32(OpNO_ACCOUNT): true, + XdrToI32(OpNOT_SUPPORTED): true, + XdrToI32(OpTOO_MANY_SUBENTRIES): true, + XdrToI32(OpEXCEEDED_WORK_LIMIT): true, + XdrToI32(OpTOO_MANY_SPONSORING): true, } -func (_ AccountMergeResult) XdrValidTags() map[int32]bool { - return _XdrTags_AccountMergeResult +func (_ OperationResult) XdrValidTags() map[int32]bool { + return _XdrTags_OperationResult } - -// how much got transferred from source account -func (u *AccountMergeResult) SourceAccountBalance() *Int64 { +func (u *OperationResult) Tr() *XdrAnon_OperationResult_Tr { switch u.Code { - case ACCOUNT_MERGE_SUCCESS: - if v, ok := u._u.(*Int64); ok { + case OpINNER: + if v, ok := u._u.(*XdrAnon_OperationResult_Tr); ok { return v } else { - var zero Int64 + var zero XdrAnon_OperationResult_Tr u._u = &zero return &zero } default: - XdrPanic("AccountMergeResult.SourceAccountBalance accessed when Code == %v", u.Code) + XdrPanic("OperationResult.Tr accessed when Code == %v", u.Code) return nil } } -func (u AccountMergeResult) XdrValid() bool { +func (u OperationResult) XdrValid() bool { switch u.Code { - case ACCOUNT_MERGE_SUCCESS, ACCOUNT_MERGE_MALFORMED, ACCOUNT_MERGE_NO_ACCOUNT, ACCOUNT_MERGE_IMMUTABLE_SET, ACCOUNT_MERGE_HAS_SUB_ENTRIES, ACCOUNT_MERGE_SEQNUM_TOO_FAR, ACCOUNT_MERGE_DEST_FULL, ACCOUNT_MERGE_IS_SPONSOR: + case OpINNER, OpBAD_AUTH, OpNO_ACCOUNT, OpNOT_SUPPORTED, OpTOO_MANY_SUBENTRIES, OpEXCEEDED_WORK_LIMIT, OpTOO_MANY_SPONSORING: return true } return false } -func (u *AccountMergeResult) XdrUnionTag() XdrNum32 { - return XDR_AccountMergeResultCode(&u.Code) +func (u *OperationResult) XdrUnionTag() XdrNum32 { + return XDR_OperationResultCode(&u.Code) } -func (u *AccountMergeResult) XdrUnionTagName() string { +func (u *OperationResult) XdrUnionTagName() string { return "Code" } -func (u *AccountMergeResult) XdrUnionBody() XdrType { +func (u *OperationResult) XdrUnionBody() XdrType { switch u.Code { - case ACCOUNT_MERGE_SUCCESS: - return XDR_Int64(u.SourceAccountBalance()) - case ACCOUNT_MERGE_MALFORMED, ACCOUNT_MERGE_NO_ACCOUNT, ACCOUNT_MERGE_IMMUTABLE_SET, ACCOUNT_MERGE_HAS_SUB_ENTRIES, ACCOUNT_MERGE_SEQNUM_TOO_FAR, ACCOUNT_MERGE_DEST_FULL, ACCOUNT_MERGE_IS_SPONSOR: + case OpINNER: + return XDR_XdrAnon_OperationResult_Tr(u.Tr()) + case OpBAD_AUTH, OpNO_ACCOUNT, OpNOT_SUPPORTED, OpTOO_MANY_SUBENTRIES, OpEXCEEDED_WORK_LIMIT, OpTOO_MANY_SPONSORING: return nil } return nil } -func (u *AccountMergeResult) XdrUnionBodyName() string { +func (u *OperationResult) XdrUnionBodyName() string { switch u.Code { - case ACCOUNT_MERGE_SUCCESS: - return "SourceAccountBalance" - case ACCOUNT_MERGE_MALFORMED, ACCOUNT_MERGE_NO_ACCOUNT, ACCOUNT_MERGE_IMMUTABLE_SET, ACCOUNT_MERGE_HAS_SUB_ENTRIES, ACCOUNT_MERGE_SEQNUM_TOO_FAR, ACCOUNT_MERGE_DEST_FULL, ACCOUNT_MERGE_IS_SPONSOR: + case OpINNER: + return "Tr" + case OpBAD_AUTH, OpNO_ACCOUNT, OpNOT_SUPPORTED, OpTOO_MANY_SUBENTRIES, OpEXCEEDED_WORK_LIMIT, OpTOO_MANY_SPONSORING: return "" } return "" } -type XdrType_AccountMergeResult = *AccountMergeResult +type XdrType_OperationResult = *OperationResult -func (v *AccountMergeResult) XdrPointer() interface{} { return v } -func (AccountMergeResult) XdrTypeName() string { return "AccountMergeResult" } -func (v AccountMergeResult) XdrValue() interface{} { return v } -func (v *AccountMergeResult) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -func (u *AccountMergeResult) XdrRecurse(x XDR, name string) { +func (v *OperationResult) XdrPointer() interface{} { return v } +func (OperationResult) XdrTypeName() string { return "OperationResult" } +func (v OperationResult) XdrValue() interface{} { return v } +func (v *OperationResult) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (u *OperationResult) XdrRecurse(x XDR, name string) { if name != "" { name = x.Sprintf("%s.", name) } - XDR_AccountMergeResultCode(&u.Code).XdrMarshal(x, x.Sprintf("%scode", name)) + XDR_OperationResultCode(&u.Code).XdrMarshal(x, x.Sprintf("%scode", name)) switch u.Code { - case ACCOUNT_MERGE_SUCCESS: - x.Marshal(x.Sprintf("%ssourceAccountBalance", name), XDR_Int64(u.SourceAccountBalance())) + case OpINNER: + x.Marshal(x.Sprintf("%str", name), XDR_XdrAnon_OperationResult_Tr(u.Tr())) return - case ACCOUNT_MERGE_MALFORMED, ACCOUNT_MERGE_NO_ACCOUNT, ACCOUNT_MERGE_IMMUTABLE_SET, ACCOUNT_MERGE_HAS_SUB_ENTRIES, ACCOUNT_MERGE_SEQNUM_TOO_FAR, ACCOUNT_MERGE_DEST_FULL, ACCOUNT_MERGE_IS_SPONSOR: + case OpBAD_AUTH, OpNO_ACCOUNT, OpNOT_SUPPORTED, OpTOO_MANY_SUBENTRIES, OpEXCEEDED_WORK_LIMIT, OpTOO_MANY_SPONSORING: return } - XdrPanic("invalid Code (%v) in AccountMergeResult", u.Code) + XdrPanic("invalid Code (%v) in OperationResult", u.Code) } -func XDR_AccountMergeResult(v *AccountMergeResult) *AccountMergeResult { return v } +func XDR_OperationResult(v *OperationResult) *OperationResult { return v } -var _XdrNames_InflationResultCode = map[int32]string{ - int32(INFLATION_SUCCESS): "INFLATION_SUCCESS", - int32(INFLATION_NOT_TIME): "INFLATION_NOT_TIME", +var _XdrNames_TransactionResultCode = map[int32]string{ + int32(TxFEE_BUMP_INNER_SUCCESS): "txFEE_BUMP_INNER_SUCCESS", + int32(TxSUCCESS): "txSUCCESS", + int32(TxFAILED): "txFAILED", + int32(TxTOO_EARLY): "txTOO_EARLY", + int32(TxTOO_LATE): "txTOO_LATE", + int32(TxMISSING_OPERATION): "txMISSING_OPERATION", + int32(TxBAD_SEQ): "txBAD_SEQ", + int32(TxBAD_AUTH): "txBAD_AUTH", + int32(TxINSUFFICIENT_BALANCE): "txINSUFFICIENT_BALANCE", + int32(TxNO_ACCOUNT): "txNO_ACCOUNT", + int32(TxINSUFFICIENT_FEE): "txINSUFFICIENT_FEE", + int32(TxBAD_AUTH_EXTRA): "txBAD_AUTH_EXTRA", + int32(TxINTERNAL_ERROR): "txINTERNAL_ERROR", + int32(TxNOT_SUPPORTED): "txNOT_SUPPORTED", + int32(TxFEE_BUMP_INNER_FAILED): "txFEE_BUMP_INNER_FAILED", + int32(TxBAD_SPONSORSHIP): "txBAD_SPONSORSHIP", + int32(TxBAD_MIN_SEQ_AGE_OR_GAP): "txBAD_MIN_SEQ_AGE_OR_GAP", + int32(TxMALFORMED): "txMALFORMED", + int32(TxSOROBAN_INVALID): "txSOROBAN_INVALID", } -var _XdrValues_InflationResultCode = map[string]int32{ - "INFLATION_SUCCESS": int32(INFLATION_SUCCESS), - "INFLATION_NOT_TIME": int32(INFLATION_NOT_TIME), +var _XdrValues_TransactionResultCode = map[string]int32{ + "txFEE_BUMP_INNER_SUCCESS": int32(TxFEE_BUMP_INNER_SUCCESS), + "txSUCCESS": int32(TxSUCCESS), + "txFAILED": int32(TxFAILED), + "txTOO_EARLY": int32(TxTOO_EARLY), + "txTOO_LATE": int32(TxTOO_LATE), + "txMISSING_OPERATION": int32(TxMISSING_OPERATION), + "txBAD_SEQ": int32(TxBAD_SEQ), + "txBAD_AUTH": int32(TxBAD_AUTH), + "txINSUFFICIENT_BALANCE": int32(TxINSUFFICIENT_BALANCE), + "txNO_ACCOUNT": int32(TxNO_ACCOUNT), + "txINSUFFICIENT_FEE": int32(TxINSUFFICIENT_FEE), + "txBAD_AUTH_EXTRA": int32(TxBAD_AUTH_EXTRA), + "txINTERNAL_ERROR": int32(TxINTERNAL_ERROR), + "txNOT_SUPPORTED": int32(TxNOT_SUPPORTED), + "txFEE_BUMP_INNER_FAILED": int32(TxFEE_BUMP_INNER_FAILED), + "txBAD_SPONSORSHIP": int32(TxBAD_SPONSORSHIP), + "txBAD_MIN_SEQ_AGE_OR_GAP": int32(TxBAD_MIN_SEQ_AGE_OR_GAP), + "txMALFORMED": int32(TxMALFORMED), + "txSOROBAN_INVALID": int32(TxSOROBAN_INVALID), } -func (InflationResultCode) XdrEnumNames() map[int32]string { - return _XdrNames_InflationResultCode +func (TransactionResultCode) XdrEnumNames() map[int32]string { + return _XdrNames_TransactionResultCode } -func (v InflationResultCode) String() string { - if s, ok := _XdrNames_InflationResultCode[int32(v)]; ok { +func (v TransactionResultCode) String() string { + if s, ok := _XdrNames_TransactionResultCode[int32(v)]; ok { return s } - return fmt.Sprintf("InflationResultCode#%d", v) + return fmt.Sprintf("TransactionResultCode#%d", v) } -func (v *InflationResultCode) Scan(ss fmt.ScanState, _ rune) error { +func (v *TransactionResultCode) Scan(ss fmt.ScanState, _ rune) error { if tok, err := ss.Token(true, XdrSymChar); err != nil { return err } else { stok := string(tok) - if val, ok := _XdrValues_InflationResultCode[stok]; ok { - *v = InflationResultCode(val) + if val, ok := _XdrValues_TransactionResultCode[stok]; ok { + *v = TransactionResultCode(val) return nil - } else if stok == "InflationResultCode" { + } else if stok == "TransactionResultCode" { if n, err := fmt.Fscanf(ss, "#%d", (*int32)(v)); n == 1 && err == nil { return nil } } - return XdrError(fmt.Sprintf("%s is not a valid InflationResultCode.", stok)) + return XdrError(fmt.Sprintf("%s is not a valid TransactionResultCode.", stok)) } } -func (v InflationResultCode) GetU32() uint32 { return uint32(v) } -func (v *InflationResultCode) SetU32(n uint32) { *v = InflationResultCode(n) } -func (v *InflationResultCode) XdrPointer() interface{} { return v } -func (InflationResultCode) XdrTypeName() string { return "InflationResultCode" } -func (v InflationResultCode) XdrValue() interface{} { return v } -func (v *InflationResultCode) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } - -type XdrType_InflationResultCode = *InflationResultCode +func (v TransactionResultCode) GetU32() uint32 { return uint32(v) } +func (v *TransactionResultCode) SetU32(n uint32) { *v = TransactionResultCode(n) } +func (v *TransactionResultCode) XdrPointer() interface{} { return v } +func (TransactionResultCode) XdrTypeName() string { return "TransactionResultCode" } +func (v TransactionResultCode) XdrValue() interface{} { return v } +func (v *TransactionResultCode) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -func XDR_InflationResultCode(v *InflationResultCode) *InflationResultCode { return v } +type XdrType_TransactionResultCode = *TransactionResultCode -var _XdrComments_InflationResultCode = map[int32]string{ - int32(INFLATION_SUCCESS): "codes considered as \"success\" for the operation", - int32(INFLATION_NOT_TIME): "codes considered as \"failure\" for the operation", -} +func XDR_TransactionResultCode(v *TransactionResultCode) *TransactionResultCode { return v } -func (e InflationResultCode) XdrEnumComments() map[int32]string { - return _XdrComments_InflationResultCode +var _XdrComments_TransactionResultCode = map[int32]string{ + int32(TxFEE_BUMP_INNER_SUCCESS): "fee bump inner transaction succeeded", + int32(TxSUCCESS): "all operations succeeded", + int32(TxFAILED): "one of the operations failed (none were applied)", + int32(TxTOO_EARLY): "ledger closeTime before minTime", + int32(TxTOO_LATE): "ledger closeTime after maxTime", + int32(TxMISSING_OPERATION): "no operation was specified", + int32(TxBAD_SEQ): "sequence number does not match source account", + int32(TxBAD_AUTH): "too few valid signatures / wrong network", + int32(TxINSUFFICIENT_BALANCE): "fee would bring account below reserve", + int32(TxNO_ACCOUNT): "source account not found", + int32(TxINSUFFICIENT_FEE): "fee is too small", + int32(TxBAD_AUTH_EXTRA): "unused signatures attached to transaction", + int32(TxINTERNAL_ERROR): "an unknown error occurred", + int32(TxNOT_SUPPORTED): "transaction type not supported", + int32(TxFEE_BUMP_INNER_FAILED): "fee bump inner transaction failed", + int32(TxBAD_SPONSORSHIP): "sponsorship not confirmed", + int32(TxBAD_MIN_SEQ_AGE_OR_GAP): "minSeqAge or minSeqLedgerGap conditions not met", + int32(TxMALFORMED): "precondition is invalid", + int32(TxSOROBAN_INVALID): "soroban-specific preconditions were not met", } -type XdrType_InflationPayout = *InflationPayout - -func (v *InflationPayout) XdrPointer() interface{} { return v } -func (InflationPayout) XdrTypeName() string { return "InflationPayout" } -func (v InflationPayout) XdrValue() interface{} { return v } -func (v *InflationPayout) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -func (v *InflationPayout) XdrRecurse(x XDR, name string) { - if name != "" { - name = x.Sprintf("%s.", name) - } - x.Marshal(x.Sprintf("%sdestination", name), XDR_AccountID(&v.Destination)) - x.Marshal(x.Sprintf("%samount", name), XDR_Int64(&v.Amount)) +func (e TransactionResultCode) XdrEnumComments() map[int32]string { + return _XdrComments_TransactionResultCode } -func XDR_InflationPayout(v *InflationPayout) *InflationPayout { return v } -type _XdrVec_unbounded_InflationPayout []InflationPayout +type _XdrVec_unbounded_OperationResult []OperationResult -func (_XdrVec_unbounded_InflationPayout) XdrBound() uint32 { +func (_XdrVec_unbounded_OperationResult) XdrBound() uint32 { const bound uint32 = 4294967295 // Force error if not const or doesn't fit return bound } -func (_XdrVec_unbounded_InflationPayout) XdrCheckLen(length uint32) { +func (_XdrVec_unbounded_OperationResult) XdrCheckLen(length uint32) { if length > uint32(4294967295) { - XdrPanic("_XdrVec_unbounded_InflationPayout length %d exceeds bound 4294967295", length) + XdrPanic("_XdrVec_unbounded_OperationResult length %d exceeds bound 4294967295", length) } else if int(length) < 0 { - XdrPanic("_XdrVec_unbounded_InflationPayout length %d exceeds max int", length) + XdrPanic("_XdrVec_unbounded_OperationResult length %d exceeds max int", length) } } -func (v _XdrVec_unbounded_InflationPayout) GetVecLen() uint32 { return uint32(len(v)) } -func (v *_XdrVec_unbounded_InflationPayout) SetVecLen(length uint32) { +func (v _XdrVec_unbounded_OperationResult) GetVecLen() uint32 { return uint32(len(v)) } +func (v *_XdrVec_unbounded_OperationResult) SetVecLen(length uint32) { v.XdrCheckLen(length) if int(length) <= cap(*v) { if int(length) != len(*v) { @@ -17150,3545 +23885,5311 @@ func (v *_XdrVec_unbounded_InflationPayout) SetVecLen(length uint32) { } newcap = int(bound) } - nv := make([]InflationPayout, int(length), newcap) + nv := make([]OperationResult, int(length), newcap) copy(nv, *v) *v = nv } -func (v *_XdrVec_unbounded_InflationPayout) XdrMarshalN(x XDR, name string, n uint32) { +func (v *_XdrVec_unbounded_OperationResult) XdrMarshalN(x XDR, name string, n uint32) { v.XdrCheckLen(n) for i := 0; i < int(n); i++ { if i >= len(*v) { v.SetVecLen(uint32(i + 1)) } - XDR_InflationPayout(&(*v)[i]).XdrMarshal(x, x.Sprintf("%s[%d]", name, i)) + XDR_OperationResult(&(*v)[i]).XdrMarshal(x, x.Sprintf("%s[%d]", name, i)) } if int(n) < len(*v) { *v = (*v)[:int(n)] } } -func (v *_XdrVec_unbounded_InflationPayout) XdrRecurse(x XDR, name string) { +func (v *_XdrVec_unbounded_OperationResult) XdrRecurse(x XDR, name string) { size := XdrSize{Size: uint32(len(*v)), Bound: 4294967295} x.Marshal(name, &size) v.XdrMarshalN(x, name, size.Size) } -func (_XdrVec_unbounded_InflationPayout) XdrTypeName() string { return "InflationPayout<>" } -func (v *_XdrVec_unbounded_InflationPayout) XdrPointer() interface{} { return (*[]InflationPayout)(v) } -func (v _XdrVec_unbounded_InflationPayout) XdrValue() interface{} { return ([]InflationPayout)(v) } -func (v *_XdrVec_unbounded_InflationPayout) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (_XdrVec_unbounded_OperationResult) XdrTypeName() string { return "OperationResult<>" } +func (v *_XdrVec_unbounded_OperationResult) XdrPointer() interface{} { return (*[]OperationResult)(v) } +func (v _XdrVec_unbounded_OperationResult) XdrValue() interface{} { return ([]OperationResult)(v) } +func (v *_XdrVec_unbounded_OperationResult) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -var _XdrTags_InflationResult = map[int32]bool{ - XdrToI32(INFLATION_SUCCESS): true, - XdrToI32(INFLATION_NOT_TIME): true, +var _XdrTags_XdrAnon_InnerTransactionResult_Result = map[int32]bool{ + XdrToI32(TxSUCCESS): true, + XdrToI32(TxFAILED): true, + XdrToI32(TxTOO_EARLY): true, + XdrToI32(TxTOO_LATE): true, + XdrToI32(TxMISSING_OPERATION): true, + XdrToI32(TxBAD_SEQ): true, + XdrToI32(TxBAD_AUTH): true, + XdrToI32(TxINSUFFICIENT_BALANCE): true, + XdrToI32(TxNO_ACCOUNT): true, + XdrToI32(TxINSUFFICIENT_FEE): true, + XdrToI32(TxBAD_AUTH_EXTRA): true, + XdrToI32(TxINTERNAL_ERROR): true, + XdrToI32(TxNOT_SUPPORTED): true, + XdrToI32(TxBAD_SPONSORSHIP): true, + XdrToI32(TxBAD_MIN_SEQ_AGE_OR_GAP): true, + XdrToI32(TxMALFORMED): true, + XdrToI32(TxSOROBAN_INVALID): true, } -func (_ InflationResult) XdrValidTags() map[int32]bool { - return _XdrTags_InflationResult +func (_ XdrAnon_InnerTransactionResult_Result) XdrValidTags() map[int32]bool { + return _XdrTags_XdrAnon_InnerTransactionResult_Result } -func (u *InflationResult) Payouts() *[]InflationPayout { +func (u *XdrAnon_InnerTransactionResult_Result) Results() *[]OperationResult { switch u.Code { - case INFLATION_SUCCESS: - if v, ok := u._u.(*[]InflationPayout); ok { + case TxSUCCESS, TxFAILED: + if v, ok := u._u.(*[]OperationResult); ok { return v } else { - var zero []InflationPayout + var zero []OperationResult u._u = &zero return &zero } default: - XdrPanic("InflationResult.Payouts accessed when Code == %v", u.Code) + XdrPanic("XdrAnon_InnerTransactionResult_Result.Results accessed when Code == %v", u.Code) return nil } } -func (u InflationResult) XdrValid() bool { +func (u XdrAnon_InnerTransactionResult_Result) XdrValid() bool { switch u.Code { - case INFLATION_SUCCESS, INFLATION_NOT_TIME: + case TxSUCCESS, TxFAILED, TxTOO_EARLY, TxTOO_LATE, TxMISSING_OPERATION, TxBAD_SEQ, TxBAD_AUTH, TxINSUFFICIENT_BALANCE, TxNO_ACCOUNT, TxINSUFFICIENT_FEE, TxBAD_AUTH_EXTRA, TxINTERNAL_ERROR, TxNOT_SUPPORTED, TxBAD_SPONSORSHIP, TxBAD_MIN_SEQ_AGE_OR_GAP, TxMALFORMED, TxSOROBAN_INVALID: return true } return false } -func (u *InflationResult) XdrUnionTag() XdrNum32 { - return XDR_InflationResultCode(&u.Code) +func (u *XdrAnon_InnerTransactionResult_Result) XdrUnionTag() XdrNum32 { + return XDR_TransactionResultCode(&u.Code) } -func (u *InflationResult) XdrUnionTagName() string { +func (u *XdrAnon_InnerTransactionResult_Result) XdrUnionTagName() string { return "Code" } -func (u *InflationResult) XdrUnionBody() XdrType { +func (u *XdrAnon_InnerTransactionResult_Result) XdrUnionBody() XdrType { switch u.Code { - case INFLATION_SUCCESS: - return (*_XdrVec_unbounded_InflationPayout)(u.Payouts()) - case INFLATION_NOT_TIME: + case TxSUCCESS, TxFAILED: + return (*_XdrVec_unbounded_OperationResult)(u.Results()) + case TxTOO_EARLY, TxTOO_LATE, TxMISSING_OPERATION, TxBAD_SEQ, TxBAD_AUTH, TxINSUFFICIENT_BALANCE, TxNO_ACCOUNT, TxINSUFFICIENT_FEE, TxBAD_AUTH_EXTRA, TxINTERNAL_ERROR, TxNOT_SUPPORTED, TxBAD_SPONSORSHIP, TxBAD_MIN_SEQ_AGE_OR_GAP, TxMALFORMED, TxSOROBAN_INVALID: return nil } return nil } -func (u *InflationResult) XdrUnionBodyName() string { +func (u *XdrAnon_InnerTransactionResult_Result) XdrUnionBodyName() string { switch u.Code { - case INFLATION_SUCCESS: - return "Payouts" - case INFLATION_NOT_TIME: + case TxSUCCESS, TxFAILED: + return "Results" + case TxTOO_EARLY, TxTOO_LATE, TxMISSING_OPERATION, TxBAD_SEQ, TxBAD_AUTH, TxINSUFFICIENT_BALANCE, TxNO_ACCOUNT, TxINSUFFICIENT_FEE, TxBAD_AUTH_EXTRA, TxINTERNAL_ERROR, TxNOT_SUPPORTED, TxBAD_SPONSORSHIP, TxBAD_MIN_SEQ_AGE_OR_GAP, TxMALFORMED, TxSOROBAN_INVALID: + return "" + } + return "" +} + +type XdrType_XdrAnon_InnerTransactionResult_Result = *XdrAnon_InnerTransactionResult_Result + +func (v *XdrAnon_InnerTransactionResult_Result) XdrPointer() interface{} { return v } +func (XdrAnon_InnerTransactionResult_Result) XdrTypeName() string { + return "XdrAnon_InnerTransactionResult_Result" +} +func (v XdrAnon_InnerTransactionResult_Result) XdrValue() interface{} { return v } +func (v *XdrAnon_InnerTransactionResult_Result) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (u *XdrAnon_InnerTransactionResult_Result) XdrRecurse(x XDR, name string) { + if name != "" { + name = x.Sprintf("%s.", name) + } + XDR_TransactionResultCode(&u.Code).XdrMarshal(x, x.Sprintf("%scode", name)) + switch u.Code { + case TxSUCCESS, TxFAILED: + x.Marshal(x.Sprintf("%sresults", name), (*_XdrVec_unbounded_OperationResult)(u.Results())) + return + case TxTOO_EARLY, TxTOO_LATE, TxMISSING_OPERATION, TxBAD_SEQ, TxBAD_AUTH, TxINSUFFICIENT_BALANCE, TxNO_ACCOUNT, TxINSUFFICIENT_FEE, TxBAD_AUTH_EXTRA, TxINTERNAL_ERROR, TxNOT_SUPPORTED, TxBAD_SPONSORSHIP, TxBAD_MIN_SEQ_AGE_OR_GAP, TxMALFORMED, TxSOROBAN_INVALID: + return + } + XdrPanic("invalid Code (%v) in XdrAnon_InnerTransactionResult_Result", u.Code) +} +func XDR_XdrAnon_InnerTransactionResult_Result(v *XdrAnon_InnerTransactionResult_Result) *XdrAnon_InnerTransactionResult_Result { + return v +} + +var _XdrTags_XdrAnon_InnerTransactionResult_Ext = map[int32]bool{ + XdrToI32(0): true, +} + +func (_ XdrAnon_InnerTransactionResult_Ext) XdrValidTags() map[int32]bool { + return _XdrTags_XdrAnon_InnerTransactionResult_Ext +} +func (u XdrAnon_InnerTransactionResult_Ext) XdrValid() bool { + switch u.V { + case 0: + return true + } + return false +} +func (u *XdrAnon_InnerTransactionResult_Ext) XdrUnionTag() XdrNum32 { + return XDR_int32(&u.V) +} +func (u *XdrAnon_InnerTransactionResult_Ext) XdrUnionTagName() string { + return "V" +} +func (u *XdrAnon_InnerTransactionResult_Ext) XdrUnionBody() XdrType { + switch u.V { + case 0: + return nil + } + return nil +} +func (u *XdrAnon_InnerTransactionResult_Ext) XdrUnionBodyName() string { + switch u.V { + case 0: return "" } return "" } -type XdrType_InflationResult = *InflationResult +type XdrType_XdrAnon_InnerTransactionResult_Ext = *XdrAnon_InnerTransactionResult_Ext + +func (v *XdrAnon_InnerTransactionResult_Ext) XdrPointer() interface{} { return v } +func (XdrAnon_InnerTransactionResult_Ext) XdrTypeName() string { + return "XdrAnon_InnerTransactionResult_Ext" +} +func (v XdrAnon_InnerTransactionResult_Ext) XdrValue() interface{} { return v } +func (v *XdrAnon_InnerTransactionResult_Ext) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (u *XdrAnon_InnerTransactionResult_Ext) XdrRecurse(x XDR, name string) { + if name != "" { + name = x.Sprintf("%s.", name) + } + XDR_int32(&u.V).XdrMarshal(x, x.Sprintf("%sv", name)) + switch u.V { + case 0: + return + } + XdrPanic("invalid V (%v) in XdrAnon_InnerTransactionResult_Ext", u.V) +} +func XDR_XdrAnon_InnerTransactionResult_Ext(v *XdrAnon_InnerTransactionResult_Ext) *XdrAnon_InnerTransactionResult_Ext { + return v +} + +type XdrType_InnerTransactionResult = *InnerTransactionResult -func (v *InflationResult) XdrPointer() interface{} { return v } -func (InflationResult) XdrTypeName() string { return "InflationResult" } -func (v InflationResult) XdrValue() interface{} { return v } -func (v *InflationResult) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -func (u *InflationResult) XdrRecurse(x XDR, name string) { +func (v *InnerTransactionResult) XdrPointer() interface{} { return v } +func (InnerTransactionResult) XdrTypeName() string { return "InnerTransactionResult" } +func (v InnerTransactionResult) XdrValue() interface{} { return v } +func (v *InnerTransactionResult) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v *InnerTransactionResult) XdrRecurse(x XDR, name string) { if name != "" { name = x.Sprintf("%s.", name) } - XDR_InflationResultCode(&u.Code).XdrMarshal(x, x.Sprintf("%scode", name)) - switch u.Code { - case INFLATION_SUCCESS: - x.Marshal(x.Sprintf("%spayouts", name), (*_XdrVec_unbounded_InflationPayout)(u.Payouts())) - return - case INFLATION_NOT_TIME: - return - } - XdrPanic("invalid Code (%v) in InflationResult", u.Code) + x.Marshal(x.Sprintf("%sfeeCharged", name), XDR_Int64(&v.FeeCharged)) + x.Marshal(x.Sprintf("%sresult", name), XDR_XdrAnon_InnerTransactionResult_Result(&v.Result)) + x.Marshal(x.Sprintf("%sext", name), XDR_XdrAnon_InnerTransactionResult_Ext(&v.Ext)) } -func XDR_InflationResult(v *InflationResult) *InflationResult { return v } +func XDR_InnerTransactionResult(v *InnerTransactionResult) *InnerTransactionResult { return v } -var _XdrNames_ManageDataResultCode = map[int32]string{ - int32(MANAGE_DATA_SUCCESS): "MANAGE_DATA_SUCCESS", - int32(MANAGE_DATA_NOT_SUPPORTED_YET): "MANAGE_DATA_NOT_SUPPORTED_YET", - int32(MANAGE_DATA_NAME_NOT_FOUND): "MANAGE_DATA_NAME_NOT_FOUND", - int32(MANAGE_DATA_LOW_RESERVE): "MANAGE_DATA_LOW_RESERVE", - int32(MANAGE_DATA_INVALID_NAME): "MANAGE_DATA_INVALID_NAME", -} -var _XdrValues_ManageDataResultCode = map[string]int32{ - "MANAGE_DATA_SUCCESS": int32(MANAGE_DATA_SUCCESS), - "MANAGE_DATA_NOT_SUPPORTED_YET": int32(MANAGE_DATA_NOT_SUPPORTED_YET), - "MANAGE_DATA_NAME_NOT_FOUND": int32(MANAGE_DATA_NAME_NOT_FOUND), - "MANAGE_DATA_LOW_RESERVE": int32(MANAGE_DATA_LOW_RESERVE), - "MANAGE_DATA_INVALID_NAME": int32(MANAGE_DATA_INVALID_NAME), -} +type XdrType_InnerTransactionResultPair = *InnerTransactionResultPair -func (ManageDataResultCode) XdrEnumNames() map[int32]string { - return _XdrNames_ManageDataResultCode -} -func (v ManageDataResultCode) String() string { - if s, ok := _XdrNames_ManageDataResultCode[int32(v)]; ok { - return s +func (v *InnerTransactionResultPair) XdrPointer() interface{} { return v } +func (InnerTransactionResultPair) XdrTypeName() string { return "InnerTransactionResultPair" } +func (v InnerTransactionResultPair) XdrValue() interface{} { return v } +func (v *InnerTransactionResultPair) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v *InnerTransactionResultPair) XdrRecurse(x XDR, name string) { + if name != "" { + name = x.Sprintf("%s.", name) } - return fmt.Sprintf("ManageDataResultCode#%d", v) + x.Marshal(x.Sprintf("%stransactionHash", name), XDR_Hash(&v.TransactionHash)) + x.Marshal(x.Sprintf("%sresult", name), XDR_InnerTransactionResult(&v.Result)) } -func (v *ManageDataResultCode) Scan(ss fmt.ScanState, _ rune) error { - if tok, err := ss.Token(true, XdrSymChar); err != nil { - return err - } else { - stok := string(tok) - if val, ok := _XdrValues_ManageDataResultCode[stok]; ok { - *v = ManageDataResultCode(val) - return nil - } else if stok == "ManageDataResultCode" { - if n, err := fmt.Fscanf(ss, "#%d", (*int32)(v)); n == 1 && err == nil { - return nil - } - } - return XdrError(fmt.Sprintf("%s is not a valid ManageDataResultCode.", stok)) - } +func XDR_InnerTransactionResultPair(v *InnerTransactionResultPair) *InnerTransactionResultPair { + return v } -func (v ManageDataResultCode) GetU32() uint32 { return uint32(v) } -func (v *ManageDataResultCode) SetU32(n uint32) { *v = ManageDataResultCode(n) } -func (v *ManageDataResultCode) XdrPointer() interface{} { return v } -func (ManageDataResultCode) XdrTypeName() string { return "ManageDataResultCode" } -func (v ManageDataResultCode) XdrValue() interface{} { return v } -func (v *ManageDataResultCode) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } - -type XdrType_ManageDataResultCode = *ManageDataResultCode -func XDR_ManageDataResultCode(v *ManageDataResultCode) *ManageDataResultCode { return v } - -var _XdrComments_ManageDataResultCode = map[int32]string{ - int32(MANAGE_DATA_SUCCESS): "codes considered as \"success\" for the operation", - int32(MANAGE_DATA_NOT_SUPPORTED_YET): "The network hasn't moved to this protocol change yet", - int32(MANAGE_DATA_NAME_NOT_FOUND): "Trying to remove a Data Entry that isn't there", - int32(MANAGE_DATA_LOW_RESERVE): "not enough funds to create a new Data Entry", - int32(MANAGE_DATA_INVALID_NAME): "Name not a valid string", +var _XdrTags_XdrAnon_TransactionResult_Result = map[int32]bool{ + XdrToI32(TxFEE_BUMP_INNER_SUCCESS): true, + XdrToI32(TxFEE_BUMP_INNER_FAILED): true, + XdrToI32(TxSUCCESS): true, + XdrToI32(TxFAILED): true, + XdrToI32(TxTOO_EARLY): true, + XdrToI32(TxTOO_LATE): true, + XdrToI32(TxMISSING_OPERATION): true, + XdrToI32(TxBAD_SEQ): true, + XdrToI32(TxBAD_AUTH): true, + XdrToI32(TxINSUFFICIENT_BALANCE): true, + XdrToI32(TxNO_ACCOUNT): true, + XdrToI32(TxINSUFFICIENT_FEE): true, + XdrToI32(TxBAD_AUTH_EXTRA): true, + XdrToI32(TxINTERNAL_ERROR): true, + XdrToI32(TxNOT_SUPPORTED): true, + XdrToI32(TxBAD_SPONSORSHIP): true, + XdrToI32(TxBAD_MIN_SEQ_AGE_OR_GAP): true, + XdrToI32(TxMALFORMED): true, + XdrToI32(TxSOROBAN_INVALID): true, } -func (e ManageDataResultCode) XdrEnumComments() map[int32]string { - return _XdrComments_ManageDataResultCode +func (_ XdrAnon_TransactionResult_Result) XdrValidTags() map[int32]bool { + return _XdrTags_XdrAnon_TransactionResult_Result } - -var _XdrTags_ManageDataResult = map[int32]bool{ - XdrToI32(MANAGE_DATA_SUCCESS): true, - XdrToI32(MANAGE_DATA_NOT_SUPPORTED_YET): true, - XdrToI32(MANAGE_DATA_NAME_NOT_FOUND): true, - XdrToI32(MANAGE_DATA_LOW_RESERVE): true, - XdrToI32(MANAGE_DATA_INVALID_NAME): true, +func (u *XdrAnon_TransactionResult_Result) InnerResultPair() *InnerTransactionResultPair { + switch u.Code { + case TxFEE_BUMP_INNER_SUCCESS, TxFEE_BUMP_INNER_FAILED: + if v, ok := u._u.(*InnerTransactionResultPair); ok { + return v + } else { + var zero InnerTransactionResultPair + u._u = &zero + return &zero + } + default: + XdrPanic("XdrAnon_TransactionResult_Result.InnerResultPair accessed when Code == %v", u.Code) + return nil + } } - -func (_ ManageDataResult) XdrValidTags() map[int32]bool { - return _XdrTags_ManageDataResult +func (u *XdrAnon_TransactionResult_Result) Results() *[]OperationResult { + switch u.Code { + case TxSUCCESS, TxFAILED: + if v, ok := u._u.(*[]OperationResult); ok { + return v + } else { + var zero []OperationResult + u._u = &zero + return &zero + } + default: + XdrPanic("XdrAnon_TransactionResult_Result.Results accessed when Code == %v", u.Code) + return nil + } } -func (u ManageDataResult) XdrValid() bool { +func (u XdrAnon_TransactionResult_Result) XdrValid() bool { switch u.Code { - case MANAGE_DATA_SUCCESS, MANAGE_DATA_NOT_SUPPORTED_YET, MANAGE_DATA_NAME_NOT_FOUND, MANAGE_DATA_LOW_RESERVE, MANAGE_DATA_INVALID_NAME: + case TxFEE_BUMP_INNER_SUCCESS, TxFEE_BUMP_INNER_FAILED, TxSUCCESS, TxFAILED, TxTOO_EARLY, TxTOO_LATE, TxMISSING_OPERATION, TxBAD_SEQ, TxBAD_AUTH, TxINSUFFICIENT_BALANCE, TxNO_ACCOUNT, TxINSUFFICIENT_FEE, TxBAD_AUTH_EXTRA, TxINTERNAL_ERROR, TxNOT_SUPPORTED, TxBAD_SPONSORSHIP, TxBAD_MIN_SEQ_AGE_OR_GAP, TxMALFORMED, TxSOROBAN_INVALID: return true } return false } -func (u *ManageDataResult) XdrUnionTag() XdrNum32 { - return XDR_ManageDataResultCode(&u.Code) +func (u *XdrAnon_TransactionResult_Result) XdrUnionTag() XdrNum32 { + return XDR_TransactionResultCode(&u.Code) } -func (u *ManageDataResult) XdrUnionTagName() string { +func (u *XdrAnon_TransactionResult_Result) XdrUnionTagName() string { return "Code" } -func (u *ManageDataResult) XdrUnionBody() XdrType { +func (u *XdrAnon_TransactionResult_Result) XdrUnionBody() XdrType { switch u.Code { - case MANAGE_DATA_SUCCESS: - return nil - case MANAGE_DATA_NOT_SUPPORTED_YET, MANAGE_DATA_NAME_NOT_FOUND, MANAGE_DATA_LOW_RESERVE, MANAGE_DATA_INVALID_NAME: + case TxFEE_BUMP_INNER_SUCCESS, TxFEE_BUMP_INNER_FAILED: + return XDR_InnerTransactionResultPair(u.InnerResultPair()) + case TxSUCCESS, TxFAILED: + return (*_XdrVec_unbounded_OperationResult)(u.Results()) + case TxTOO_EARLY, TxTOO_LATE, TxMISSING_OPERATION, TxBAD_SEQ, TxBAD_AUTH, TxINSUFFICIENT_BALANCE, TxNO_ACCOUNT, TxINSUFFICIENT_FEE, TxBAD_AUTH_EXTRA, TxINTERNAL_ERROR, TxNOT_SUPPORTED, TxBAD_SPONSORSHIP, TxBAD_MIN_SEQ_AGE_OR_GAP, TxMALFORMED, TxSOROBAN_INVALID: return nil } return nil } -func (u *ManageDataResult) XdrUnionBodyName() string { +func (u *XdrAnon_TransactionResult_Result) XdrUnionBodyName() string { switch u.Code { - case MANAGE_DATA_SUCCESS: - return "" - case MANAGE_DATA_NOT_SUPPORTED_YET, MANAGE_DATA_NAME_NOT_FOUND, MANAGE_DATA_LOW_RESERVE, MANAGE_DATA_INVALID_NAME: + case TxFEE_BUMP_INNER_SUCCESS, TxFEE_BUMP_INNER_FAILED: + return "InnerResultPair" + case TxSUCCESS, TxFAILED: + return "Results" + case TxTOO_EARLY, TxTOO_LATE, TxMISSING_OPERATION, TxBAD_SEQ, TxBAD_AUTH, TxINSUFFICIENT_BALANCE, TxNO_ACCOUNT, TxINSUFFICIENT_FEE, TxBAD_AUTH_EXTRA, TxINTERNAL_ERROR, TxNOT_SUPPORTED, TxBAD_SPONSORSHIP, TxBAD_MIN_SEQ_AGE_OR_GAP, TxMALFORMED, TxSOROBAN_INVALID: return "" } return "" } -type XdrType_ManageDataResult = *ManageDataResult +type XdrType_XdrAnon_TransactionResult_Result = *XdrAnon_TransactionResult_Result -func (v *ManageDataResult) XdrPointer() interface{} { return v } -func (ManageDataResult) XdrTypeName() string { return "ManageDataResult" } -func (v ManageDataResult) XdrValue() interface{} { return v } -func (v *ManageDataResult) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -func (u *ManageDataResult) XdrRecurse(x XDR, name string) { +func (v *XdrAnon_TransactionResult_Result) XdrPointer() interface{} { return v } +func (XdrAnon_TransactionResult_Result) XdrTypeName() string { + return "XdrAnon_TransactionResult_Result" +} +func (v XdrAnon_TransactionResult_Result) XdrValue() interface{} { return v } +func (v *XdrAnon_TransactionResult_Result) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (u *XdrAnon_TransactionResult_Result) XdrRecurse(x XDR, name string) { if name != "" { name = x.Sprintf("%s.", name) } - XDR_ManageDataResultCode(&u.Code).XdrMarshal(x, x.Sprintf("%scode", name)) + XDR_TransactionResultCode(&u.Code).XdrMarshal(x, x.Sprintf("%scode", name)) switch u.Code { - case MANAGE_DATA_SUCCESS: + case TxFEE_BUMP_INNER_SUCCESS, TxFEE_BUMP_INNER_FAILED: + x.Marshal(x.Sprintf("%sinnerResultPair", name), XDR_InnerTransactionResultPair(u.InnerResultPair())) return - case MANAGE_DATA_NOT_SUPPORTED_YET, MANAGE_DATA_NAME_NOT_FOUND, MANAGE_DATA_LOW_RESERVE, MANAGE_DATA_INVALID_NAME: + case TxSUCCESS, TxFAILED: + x.Marshal(x.Sprintf("%sresults", name), (*_XdrVec_unbounded_OperationResult)(u.Results())) + return + case TxTOO_EARLY, TxTOO_LATE, TxMISSING_OPERATION, TxBAD_SEQ, TxBAD_AUTH, TxINSUFFICIENT_BALANCE, TxNO_ACCOUNT, TxINSUFFICIENT_FEE, TxBAD_AUTH_EXTRA, TxINTERNAL_ERROR, TxNOT_SUPPORTED, TxBAD_SPONSORSHIP, TxBAD_MIN_SEQ_AGE_OR_GAP, TxMALFORMED, TxSOROBAN_INVALID: return } - XdrPanic("invalid Code (%v) in ManageDataResult", u.Code) -} -func XDR_ManageDataResult(v *ManageDataResult) *ManageDataResult { return v } - -var _XdrNames_BumpSequenceResultCode = map[int32]string{ - int32(BUMP_SEQUENCE_SUCCESS): "BUMP_SEQUENCE_SUCCESS", - int32(BUMP_SEQUENCE_BAD_SEQ): "BUMP_SEQUENCE_BAD_SEQ", -} -var _XdrValues_BumpSequenceResultCode = map[string]int32{ - "BUMP_SEQUENCE_SUCCESS": int32(BUMP_SEQUENCE_SUCCESS), - "BUMP_SEQUENCE_BAD_SEQ": int32(BUMP_SEQUENCE_BAD_SEQ), -} - -func (BumpSequenceResultCode) XdrEnumNames() map[int32]string { - return _XdrNames_BumpSequenceResultCode -} -func (v BumpSequenceResultCode) String() string { - if s, ok := _XdrNames_BumpSequenceResultCode[int32(v)]; ok { - return s - } - return fmt.Sprintf("BumpSequenceResultCode#%d", v) -} -func (v *BumpSequenceResultCode) Scan(ss fmt.ScanState, _ rune) error { - if tok, err := ss.Token(true, XdrSymChar); err != nil { - return err - } else { - stok := string(tok) - if val, ok := _XdrValues_BumpSequenceResultCode[stok]; ok { - *v = BumpSequenceResultCode(val) - return nil - } else if stok == "BumpSequenceResultCode" { - if n, err := fmt.Fscanf(ss, "#%d", (*int32)(v)); n == 1 && err == nil { - return nil - } - } - return XdrError(fmt.Sprintf("%s is not a valid BumpSequenceResultCode.", stok)) - } -} -func (v BumpSequenceResultCode) GetU32() uint32 { return uint32(v) } -func (v *BumpSequenceResultCode) SetU32(n uint32) { *v = BumpSequenceResultCode(n) } -func (v *BumpSequenceResultCode) XdrPointer() interface{} { return v } -func (BumpSequenceResultCode) XdrTypeName() string { return "BumpSequenceResultCode" } -func (v BumpSequenceResultCode) XdrValue() interface{} { return v } -func (v *BumpSequenceResultCode) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } - -type XdrType_BumpSequenceResultCode = *BumpSequenceResultCode - -func XDR_BumpSequenceResultCode(v *BumpSequenceResultCode) *BumpSequenceResultCode { return v } - -var _XdrComments_BumpSequenceResultCode = map[int32]string{ - int32(BUMP_SEQUENCE_SUCCESS): "codes considered as \"success\" for the operation", - int32(BUMP_SEQUENCE_BAD_SEQ): "codes considered as \"failure\" for the operation", + XdrPanic("invalid Code (%v) in XdrAnon_TransactionResult_Result", u.Code) } - -func (e BumpSequenceResultCode) XdrEnumComments() map[int32]string { - return _XdrComments_BumpSequenceResultCode +func XDR_XdrAnon_TransactionResult_Result(v *XdrAnon_TransactionResult_Result) *XdrAnon_TransactionResult_Result { + return v } -var _XdrTags_BumpSequenceResult = map[int32]bool{ - XdrToI32(BUMP_SEQUENCE_SUCCESS): true, - XdrToI32(BUMP_SEQUENCE_BAD_SEQ): true, +var _XdrTags_XdrAnon_TransactionResult_Ext = map[int32]bool{ + XdrToI32(0): true, } -func (_ BumpSequenceResult) XdrValidTags() map[int32]bool { - return _XdrTags_BumpSequenceResult +func (_ XdrAnon_TransactionResult_Ext) XdrValidTags() map[int32]bool { + return _XdrTags_XdrAnon_TransactionResult_Ext } -func (u BumpSequenceResult) XdrValid() bool { - switch u.Code { - case BUMP_SEQUENCE_SUCCESS, BUMP_SEQUENCE_BAD_SEQ: +func (u XdrAnon_TransactionResult_Ext) XdrValid() bool { + switch u.V { + case 0: return true } return false } -func (u *BumpSequenceResult) XdrUnionTag() XdrNum32 { - return XDR_BumpSequenceResultCode(&u.Code) +func (u *XdrAnon_TransactionResult_Ext) XdrUnionTag() XdrNum32 { + return XDR_int32(&u.V) } -func (u *BumpSequenceResult) XdrUnionTagName() string { - return "Code" +func (u *XdrAnon_TransactionResult_Ext) XdrUnionTagName() string { + return "V" } -func (u *BumpSequenceResult) XdrUnionBody() XdrType { - switch u.Code { - case BUMP_SEQUENCE_SUCCESS: - return nil - case BUMP_SEQUENCE_BAD_SEQ: +func (u *XdrAnon_TransactionResult_Ext) XdrUnionBody() XdrType { + switch u.V { + case 0: return nil } return nil } -func (u *BumpSequenceResult) XdrUnionBodyName() string { - switch u.Code { - case BUMP_SEQUENCE_SUCCESS: - return "" - case BUMP_SEQUENCE_BAD_SEQ: +func (u *XdrAnon_TransactionResult_Ext) XdrUnionBodyName() string { + switch u.V { + case 0: return "" } return "" } -type XdrType_BumpSequenceResult = *BumpSequenceResult +type XdrType_XdrAnon_TransactionResult_Ext = *XdrAnon_TransactionResult_Ext -func (v *BumpSequenceResult) XdrPointer() interface{} { return v } -func (BumpSequenceResult) XdrTypeName() string { return "BumpSequenceResult" } -func (v BumpSequenceResult) XdrValue() interface{} { return v } -func (v *BumpSequenceResult) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -func (u *BumpSequenceResult) XdrRecurse(x XDR, name string) { +func (v *XdrAnon_TransactionResult_Ext) XdrPointer() interface{} { return v } +func (XdrAnon_TransactionResult_Ext) XdrTypeName() string { return "XdrAnon_TransactionResult_Ext" } +func (v XdrAnon_TransactionResult_Ext) XdrValue() interface{} { return v } +func (v *XdrAnon_TransactionResult_Ext) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (u *XdrAnon_TransactionResult_Ext) XdrRecurse(x XDR, name string) { if name != "" { name = x.Sprintf("%s.", name) } - XDR_BumpSequenceResultCode(&u.Code).XdrMarshal(x, x.Sprintf("%scode", name)) - switch u.Code { - case BUMP_SEQUENCE_SUCCESS: - return - case BUMP_SEQUENCE_BAD_SEQ: + XDR_int32(&u.V).XdrMarshal(x, x.Sprintf("%sv", name)) + switch u.V { + case 0: return } - XdrPanic("invalid Code (%v) in BumpSequenceResult", u.Code) + XdrPanic("invalid V (%v) in XdrAnon_TransactionResult_Ext", u.V) +} +func XDR_XdrAnon_TransactionResult_Ext(v *XdrAnon_TransactionResult_Ext) *XdrAnon_TransactionResult_Ext { + return v } -func XDR_BumpSequenceResult(v *BumpSequenceResult) *BumpSequenceResult { return v } -var _XdrNames_CreateClaimableBalanceResultCode = map[int32]string{ - int32(CREATE_CLAIMABLE_BALANCE_SUCCESS): "CREATE_CLAIMABLE_BALANCE_SUCCESS", - int32(CREATE_CLAIMABLE_BALANCE_MALFORMED): "CREATE_CLAIMABLE_BALANCE_MALFORMED", - int32(CREATE_CLAIMABLE_BALANCE_LOW_RESERVE): "CREATE_CLAIMABLE_BALANCE_LOW_RESERVE", - int32(CREATE_CLAIMABLE_BALANCE_NO_TRUST): "CREATE_CLAIMABLE_BALANCE_NO_TRUST", - int32(CREATE_CLAIMABLE_BALANCE_NOT_AUTHORIZED): "CREATE_CLAIMABLE_BALANCE_NOT_AUTHORIZED", - int32(CREATE_CLAIMABLE_BALANCE_UNDERFUNDED): "CREATE_CLAIMABLE_BALANCE_UNDERFUNDED", +type XdrType_TransactionResult = *TransactionResult + +func (v *TransactionResult) XdrPointer() interface{} { return v } +func (TransactionResult) XdrTypeName() string { return "TransactionResult" } +func (v TransactionResult) XdrValue() interface{} { return v } +func (v *TransactionResult) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v *TransactionResult) XdrRecurse(x XDR, name string) { + if name != "" { + name = x.Sprintf("%s.", name) + } + x.Marshal(x.Sprintf("%sfeeCharged", name), XDR_Int64(&v.FeeCharged)) + x.Marshal(x.Sprintf("%sresult", name), XDR_XdrAnon_TransactionResult_Result(&v.Result)) + x.Marshal(x.Sprintf("%sext", name), XDR_XdrAnon_TransactionResult_Ext(&v.Ext)) } -var _XdrValues_CreateClaimableBalanceResultCode = map[string]int32{ - "CREATE_CLAIMABLE_BALANCE_SUCCESS": int32(CREATE_CLAIMABLE_BALANCE_SUCCESS), - "CREATE_CLAIMABLE_BALANCE_MALFORMED": int32(CREATE_CLAIMABLE_BALANCE_MALFORMED), - "CREATE_CLAIMABLE_BALANCE_LOW_RESERVE": int32(CREATE_CLAIMABLE_BALANCE_LOW_RESERVE), - "CREATE_CLAIMABLE_BALANCE_NO_TRUST": int32(CREATE_CLAIMABLE_BALANCE_NO_TRUST), - "CREATE_CLAIMABLE_BALANCE_NOT_AUTHORIZED": int32(CREATE_CLAIMABLE_BALANCE_NOT_AUTHORIZED), - "CREATE_CLAIMABLE_BALANCE_UNDERFUNDED": int32(CREATE_CLAIMABLE_BALANCE_UNDERFUNDED), +func XDR_TransactionResult(v *TransactionResult) *TransactionResult { return v } + +type _XdrArray_32_opaque [32]byte + +func (v *_XdrArray_32_opaque) GetByteSlice() []byte { return v[:] } +func (v *_XdrArray_32_opaque) XdrTypeName() string { return "opaque[]" } +func (v *_XdrArray_32_opaque) XdrValue() interface{} { return v[:] } +func (v *_XdrArray_32_opaque) XdrPointer() interface{} { return (*[32]byte)(v) } +func (v *_XdrArray_32_opaque) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v *_XdrArray_32_opaque) String() string { return fmt.Sprintf("%x", v[:]) } +func (v *_XdrArray_32_opaque) Scan(ss fmt.ScanState, c rune) error { + return XdrArrayOpaqueScan(v[:], ss, c) +} +func (_XdrArray_32_opaque) XdrArraySize() uint32 { + const bound uint32 = 32 // Force error if not const or doesn't fit + return bound } -func (CreateClaimableBalanceResultCode) XdrEnumNames() map[int32]string { - return _XdrNames_CreateClaimableBalanceResultCode +type XdrType_Hash struct { + *_XdrArray_32_opaque } -func (v CreateClaimableBalanceResultCode) String() string { - if s, ok := _XdrNames_CreateClaimableBalanceResultCode[int32(v)]; ok { - return s - } - return fmt.Sprintf("CreateClaimableBalanceResultCode#%d", v) + +func XDR_Hash(v *Hash) XdrType_Hash { + return XdrType_Hash{(*_XdrArray_32_opaque)(v)} } -func (v *CreateClaimableBalanceResultCode) Scan(ss fmt.ScanState, _ rune) error { - if tok, err := ss.Token(true, XdrSymChar); err != nil { - return err - } else { - stok := string(tok) - if val, ok := _XdrValues_CreateClaimableBalanceResultCode[stok]; ok { - *v = CreateClaimableBalanceResultCode(val) - return nil - } else if stok == "CreateClaimableBalanceResultCode" { - if n, err := fmt.Fscanf(ss, "#%d", (*int32)(v)); n == 1 && err == nil { - return nil - } - } - return XdrError(fmt.Sprintf("%s is not a valid CreateClaimableBalanceResultCode.", stok)) - } +func (XdrType_Hash) XdrTypeName() string { return "Hash" } +func (v XdrType_Hash) XdrUnwrap() XdrType { return v._XdrArray_32_opaque } + +type XdrType_Uint256 struct { + *_XdrArray_32_opaque } -func (v CreateClaimableBalanceResultCode) GetU32() uint32 { return uint32(v) } -func (v *CreateClaimableBalanceResultCode) SetU32(n uint32) { *v = CreateClaimableBalanceResultCode(n) } -func (v *CreateClaimableBalanceResultCode) XdrPointer() interface{} { return v } -func (CreateClaimableBalanceResultCode) XdrTypeName() string { - return "CreateClaimableBalanceResultCode" + +func XDR_Uint256(v *Uint256) XdrType_Uint256 { + return XdrType_Uint256{(*_XdrArray_32_opaque)(v)} } -func (v CreateClaimableBalanceResultCode) XdrValue() interface{} { return v } -func (v *CreateClaimableBalanceResultCode) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (XdrType_Uint256) XdrTypeName() string { return "Uint256" } +func (v XdrType_Uint256) XdrUnwrap() XdrType { return v._XdrArray_32_opaque } -type XdrType_CreateClaimableBalanceResultCode = *CreateClaimableBalanceResultCode +type XdrType_Uint32 struct { + XdrType_uint32 +} -func XDR_CreateClaimableBalanceResultCode(v *CreateClaimableBalanceResultCode) *CreateClaimableBalanceResultCode { - return v +func XDR_Uint32(v *Uint32) XdrType_Uint32 { + return XdrType_Uint32{XDR_uint32(v)} } +func (XdrType_Uint32) XdrTypeName() string { return "Uint32" } +func (v XdrType_Uint32) XdrUnwrap() XdrType { return v.XdrType_uint32 } -var _XdrTags_CreateClaimableBalanceResult = map[int32]bool{ - XdrToI32(CREATE_CLAIMABLE_BALANCE_SUCCESS): true, - XdrToI32(CREATE_CLAIMABLE_BALANCE_MALFORMED): true, - XdrToI32(CREATE_CLAIMABLE_BALANCE_LOW_RESERVE): true, - XdrToI32(CREATE_CLAIMABLE_BALANCE_NO_TRUST): true, - XdrToI32(CREATE_CLAIMABLE_BALANCE_NOT_AUTHORIZED): true, - XdrToI32(CREATE_CLAIMABLE_BALANCE_UNDERFUNDED): true, +type XdrType_Int32 struct { + XdrType_int32 } -func (_ CreateClaimableBalanceResult) XdrValidTags() map[int32]bool { - return _XdrTags_CreateClaimableBalanceResult +func XDR_Int32(v *Int32) XdrType_Int32 { + return XdrType_Int32{XDR_int32(v)} } -func (u *CreateClaimableBalanceResult) BalanceID() *ClaimableBalanceID { - switch u.Code { - case CREATE_CLAIMABLE_BALANCE_SUCCESS: - if v, ok := u._u.(*ClaimableBalanceID); ok { - return v - } else { - var zero ClaimableBalanceID - u._u = &zero - return &zero - } - default: - XdrPanic("CreateClaimableBalanceResult.BalanceID accessed when Code == %v", u.Code) - return nil - } +func (XdrType_Int32) XdrTypeName() string { return "Int32" } +func (v XdrType_Int32) XdrUnwrap() XdrType { return v.XdrType_int32 } + +type XdrType_Uint64 struct { + XdrType_uint64 } -func (u CreateClaimableBalanceResult) XdrValid() bool { - switch u.Code { - case CREATE_CLAIMABLE_BALANCE_SUCCESS, CREATE_CLAIMABLE_BALANCE_MALFORMED, CREATE_CLAIMABLE_BALANCE_LOW_RESERVE, CREATE_CLAIMABLE_BALANCE_NO_TRUST, CREATE_CLAIMABLE_BALANCE_NOT_AUTHORIZED, CREATE_CLAIMABLE_BALANCE_UNDERFUNDED: + +func XDR_Uint64(v *Uint64) XdrType_Uint64 { + return XdrType_Uint64{XDR_uint64(v)} +} +func (XdrType_Uint64) XdrTypeName() string { return "Uint64" } +func (v XdrType_Uint64) XdrUnwrap() XdrType { return v.XdrType_uint64 } + +type XdrType_Int64 struct { + XdrType_int64 +} + +func XDR_Int64(v *Int64) XdrType_Int64 { + return XdrType_Int64{XDR_int64(v)} +} +func (XdrType_Int64) XdrTypeName() string { return "Int64" } +func (v XdrType_Int64) XdrUnwrap() XdrType { return v.XdrType_int64 } + +type XdrType_TimePoint struct { + XdrType_Uint64 +} + +func XDR_TimePoint(v *TimePoint) XdrType_TimePoint { + return XdrType_TimePoint{XDR_Uint64(v)} +} +func (XdrType_TimePoint) XdrTypeName() string { return "TimePoint" } +func (v XdrType_TimePoint) XdrUnwrap() XdrType { return v.XdrType_Uint64 } + +type XdrType_Duration struct { + XdrType_Uint64 +} + +func XDR_Duration(v *Duration) XdrType_Duration { + return XdrType_Duration{XDR_Uint64(v)} +} +func (XdrType_Duration) XdrTypeName() string { return "Duration" } +func (v XdrType_Duration) XdrUnwrap() XdrType { return v.XdrType_Uint64 } + +var _XdrTags_ExtensionPoint = map[int32]bool{ + XdrToI32(0): true, +} + +func (_ ExtensionPoint) XdrValidTags() map[int32]bool { + return _XdrTags_ExtensionPoint +} +func (u ExtensionPoint) XdrValid() bool { + switch u.V { + case 0: return true } return false } -func (u *CreateClaimableBalanceResult) XdrUnionTag() XdrNum32 { - return XDR_CreateClaimableBalanceResultCode(&u.Code) +func (u *ExtensionPoint) XdrUnionTag() XdrNum32 { + return XDR_int32(&u.V) } -func (u *CreateClaimableBalanceResult) XdrUnionTagName() string { - return "Code" +func (u *ExtensionPoint) XdrUnionTagName() string { + return "V" } -func (u *CreateClaimableBalanceResult) XdrUnionBody() XdrType { - switch u.Code { - case CREATE_CLAIMABLE_BALANCE_SUCCESS: - return XDR_ClaimableBalanceID(u.BalanceID()) - case CREATE_CLAIMABLE_BALANCE_MALFORMED, CREATE_CLAIMABLE_BALANCE_LOW_RESERVE, CREATE_CLAIMABLE_BALANCE_NO_TRUST, CREATE_CLAIMABLE_BALANCE_NOT_AUTHORIZED, CREATE_CLAIMABLE_BALANCE_UNDERFUNDED: +func (u *ExtensionPoint) XdrUnionBody() XdrType { + switch u.V { + case 0: return nil } return nil } -func (u *CreateClaimableBalanceResult) XdrUnionBodyName() string { - switch u.Code { - case CREATE_CLAIMABLE_BALANCE_SUCCESS: - return "BalanceID" - case CREATE_CLAIMABLE_BALANCE_MALFORMED, CREATE_CLAIMABLE_BALANCE_LOW_RESERVE, CREATE_CLAIMABLE_BALANCE_NO_TRUST, CREATE_CLAIMABLE_BALANCE_NOT_AUTHORIZED, CREATE_CLAIMABLE_BALANCE_UNDERFUNDED: +func (u *ExtensionPoint) XdrUnionBodyName() string { + switch u.V { + case 0: return "" } return "" } -type XdrType_CreateClaimableBalanceResult = *CreateClaimableBalanceResult +type XdrType_ExtensionPoint = *ExtensionPoint -func (v *CreateClaimableBalanceResult) XdrPointer() interface{} { return v } -func (CreateClaimableBalanceResult) XdrTypeName() string { return "CreateClaimableBalanceResult" } -func (v CreateClaimableBalanceResult) XdrValue() interface{} { return v } -func (v *CreateClaimableBalanceResult) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -func (u *CreateClaimableBalanceResult) XdrRecurse(x XDR, name string) { +func (v *ExtensionPoint) XdrPointer() interface{} { return v } +func (ExtensionPoint) XdrTypeName() string { return "ExtensionPoint" } +func (v ExtensionPoint) XdrValue() interface{} { return v } +func (v *ExtensionPoint) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (u *ExtensionPoint) XdrRecurse(x XDR, name string) { if name != "" { name = x.Sprintf("%s.", name) } - XDR_CreateClaimableBalanceResultCode(&u.Code).XdrMarshal(x, x.Sprintf("%scode", name)) - switch u.Code { - case CREATE_CLAIMABLE_BALANCE_SUCCESS: - x.Marshal(x.Sprintf("%sbalanceID", name), XDR_ClaimableBalanceID(u.BalanceID())) - return - case CREATE_CLAIMABLE_BALANCE_MALFORMED, CREATE_CLAIMABLE_BALANCE_LOW_RESERVE, CREATE_CLAIMABLE_BALANCE_NO_TRUST, CREATE_CLAIMABLE_BALANCE_NOT_AUTHORIZED, CREATE_CLAIMABLE_BALANCE_UNDERFUNDED: + XDR_int32(&u.V).XdrMarshal(x, x.Sprintf("%sv", name)) + switch u.V { + case 0: return } - XdrPanic("invalid Code (%v) in CreateClaimableBalanceResult", u.Code) -} -func XDR_CreateClaimableBalanceResult(v *CreateClaimableBalanceResult) *CreateClaimableBalanceResult { - return v + XdrPanic("invalid V (%v) in ExtensionPoint", u.V) } +func XDR_ExtensionPoint(v *ExtensionPoint) *ExtensionPoint { return v } -var _XdrNames_ClaimClaimableBalanceResultCode = map[int32]string{ - int32(CLAIM_CLAIMABLE_BALANCE_SUCCESS): "CLAIM_CLAIMABLE_BALANCE_SUCCESS", - int32(CLAIM_CLAIMABLE_BALANCE_DOES_NOT_EXIST): "CLAIM_CLAIMABLE_BALANCE_DOES_NOT_EXIST", - int32(CLAIM_CLAIMABLE_BALANCE_CANNOT_CLAIM): "CLAIM_CLAIMABLE_BALANCE_CANNOT_CLAIM", - int32(CLAIM_CLAIMABLE_BALANCE_LINE_FULL): "CLAIM_CLAIMABLE_BALANCE_LINE_FULL", - int32(CLAIM_CLAIMABLE_BALANCE_NO_TRUST): "CLAIM_CLAIMABLE_BALANCE_NO_TRUST", - int32(CLAIM_CLAIMABLE_BALANCE_NOT_AUTHORIZED): "CLAIM_CLAIMABLE_BALANCE_NOT_AUTHORIZED", +var _XdrNames_CryptoKeyType = map[int32]string{ + int32(KEY_TYPE_ED25519): "KEY_TYPE_ED25519", + int32(KEY_TYPE_PRE_AUTH_TX): "KEY_TYPE_PRE_AUTH_TX", + int32(KEY_TYPE_HASH_X): "KEY_TYPE_HASH_X", + int32(KEY_TYPE_ED25519_SIGNED_PAYLOAD): "KEY_TYPE_ED25519_SIGNED_PAYLOAD", + int32(KEY_TYPE_MUXED_ED25519): "KEY_TYPE_MUXED_ED25519", } -var _XdrValues_ClaimClaimableBalanceResultCode = map[string]int32{ - "CLAIM_CLAIMABLE_BALANCE_SUCCESS": int32(CLAIM_CLAIMABLE_BALANCE_SUCCESS), - "CLAIM_CLAIMABLE_BALANCE_DOES_NOT_EXIST": int32(CLAIM_CLAIMABLE_BALANCE_DOES_NOT_EXIST), - "CLAIM_CLAIMABLE_BALANCE_CANNOT_CLAIM": int32(CLAIM_CLAIMABLE_BALANCE_CANNOT_CLAIM), - "CLAIM_CLAIMABLE_BALANCE_LINE_FULL": int32(CLAIM_CLAIMABLE_BALANCE_LINE_FULL), - "CLAIM_CLAIMABLE_BALANCE_NO_TRUST": int32(CLAIM_CLAIMABLE_BALANCE_NO_TRUST), - "CLAIM_CLAIMABLE_BALANCE_NOT_AUTHORIZED": int32(CLAIM_CLAIMABLE_BALANCE_NOT_AUTHORIZED), +var _XdrValues_CryptoKeyType = map[string]int32{ + "KEY_TYPE_ED25519": int32(KEY_TYPE_ED25519), + "KEY_TYPE_PRE_AUTH_TX": int32(KEY_TYPE_PRE_AUTH_TX), + "KEY_TYPE_HASH_X": int32(KEY_TYPE_HASH_X), + "KEY_TYPE_ED25519_SIGNED_PAYLOAD": int32(KEY_TYPE_ED25519_SIGNED_PAYLOAD), + "KEY_TYPE_MUXED_ED25519": int32(KEY_TYPE_MUXED_ED25519), } -func (ClaimClaimableBalanceResultCode) XdrEnumNames() map[int32]string { - return _XdrNames_ClaimClaimableBalanceResultCode +func (CryptoKeyType) XdrEnumNames() map[int32]string { + return _XdrNames_CryptoKeyType } -func (v ClaimClaimableBalanceResultCode) String() string { - if s, ok := _XdrNames_ClaimClaimableBalanceResultCode[int32(v)]; ok { +func (v CryptoKeyType) String() string { + if s, ok := _XdrNames_CryptoKeyType[int32(v)]; ok { return s } - return fmt.Sprintf("ClaimClaimableBalanceResultCode#%d", v) + return fmt.Sprintf("CryptoKeyType#%d", v) } -func (v *ClaimClaimableBalanceResultCode) Scan(ss fmt.ScanState, _ rune) error { +func (v *CryptoKeyType) Scan(ss fmt.ScanState, _ rune) error { if tok, err := ss.Token(true, XdrSymChar); err != nil { return err } else { stok := string(tok) - if val, ok := _XdrValues_ClaimClaimableBalanceResultCode[stok]; ok { - *v = ClaimClaimableBalanceResultCode(val) + if val, ok := _XdrValues_CryptoKeyType[stok]; ok { + *v = CryptoKeyType(val) return nil - } else if stok == "ClaimClaimableBalanceResultCode" { + } else if stok == "CryptoKeyType" { if n, err := fmt.Fscanf(ss, "#%d", (*int32)(v)); n == 1 && err == nil { return nil } } - return XdrError(fmt.Sprintf("%s is not a valid ClaimClaimableBalanceResultCode.", stok)) + return XdrError(fmt.Sprintf("%s is not a valid CryptoKeyType.", stok)) } } -func (v ClaimClaimableBalanceResultCode) GetU32() uint32 { return uint32(v) } -func (v *ClaimClaimableBalanceResultCode) SetU32(n uint32) { *v = ClaimClaimableBalanceResultCode(n) } -func (v *ClaimClaimableBalanceResultCode) XdrPointer() interface{} { return v } -func (ClaimClaimableBalanceResultCode) XdrTypeName() string { return "ClaimClaimableBalanceResultCode" } -func (v ClaimClaimableBalanceResultCode) XdrValue() interface{} { return v } -func (v *ClaimClaimableBalanceResultCode) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v CryptoKeyType) GetU32() uint32 { return uint32(v) } +func (v *CryptoKeyType) SetU32(n uint32) { *v = CryptoKeyType(n) } +func (v *CryptoKeyType) XdrPointer() interface{} { return v } +func (CryptoKeyType) XdrTypeName() string { return "CryptoKeyType" } +func (v CryptoKeyType) XdrValue() interface{} { return v } +func (v *CryptoKeyType) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -type XdrType_ClaimClaimableBalanceResultCode = *ClaimClaimableBalanceResultCode +type XdrType_CryptoKeyType = *CryptoKeyType -func XDR_ClaimClaimableBalanceResultCode(v *ClaimClaimableBalanceResultCode) *ClaimClaimableBalanceResultCode { - return v -} +func XDR_CryptoKeyType(v *CryptoKeyType) *CryptoKeyType { return v } -var _XdrTags_ClaimClaimableBalanceResult = map[int32]bool{ - XdrToI32(CLAIM_CLAIMABLE_BALANCE_SUCCESS): true, - XdrToI32(CLAIM_CLAIMABLE_BALANCE_DOES_NOT_EXIST): true, - XdrToI32(CLAIM_CLAIMABLE_BALANCE_CANNOT_CLAIM): true, - XdrToI32(CLAIM_CLAIMABLE_BALANCE_LINE_FULL): true, - XdrToI32(CLAIM_CLAIMABLE_BALANCE_NO_TRUST): true, - XdrToI32(CLAIM_CLAIMABLE_BALANCE_NOT_AUTHORIZED): true, +var _XdrComments_CryptoKeyType = map[int32]string{ + int32(KEY_TYPE_MUXED_ED25519): "MUXED enum values for supported type are derived from the enum values above by ORing them with 0x100", } -func (_ ClaimClaimableBalanceResult) XdrValidTags() map[int32]bool { - return _XdrTags_ClaimClaimableBalanceResult +func (e CryptoKeyType) XdrEnumComments() map[int32]string { + return _XdrComments_CryptoKeyType } -func (u ClaimClaimableBalanceResult) XdrValid() bool { - switch u.Code { - case CLAIM_CLAIMABLE_BALANCE_SUCCESS, CLAIM_CLAIMABLE_BALANCE_DOES_NOT_EXIST, CLAIM_CLAIMABLE_BALANCE_CANNOT_CLAIM, CLAIM_CLAIMABLE_BALANCE_LINE_FULL, CLAIM_CLAIMABLE_BALANCE_NO_TRUST, CLAIM_CLAIMABLE_BALANCE_NOT_AUTHORIZED: - return true - } - return false + +var _XdrNames_PublicKeyType = map[int32]string{ + int32(PUBLIC_KEY_TYPE_ED25519): "PUBLIC_KEY_TYPE_ED25519", } -func (u *ClaimClaimableBalanceResult) XdrUnionTag() XdrNum32 { - return XDR_ClaimClaimableBalanceResultCode(&u.Code) +var _XdrValues_PublicKeyType = map[string]int32{ + "PUBLIC_KEY_TYPE_ED25519": int32(PUBLIC_KEY_TYPE_ED25519), } -func (u *ClaimClaimableBalanceResult) XdrUnionTagName() string { - return "Code" + +func (PublicKeyType) XdrEnumNames() map[int32]string { + return _XdrNames_PublicKeyType } -func (u *ClaimClaimableBalanceResult) XdrUnionBody() XdrType { - switch u.Code { - case CLAIM_CLAIMABLE_BALANCE_SUCCESS: - return nil - case CLAIM_CLAIMABLE_BALANCE_DOES_NOT_EXIST, CLAIM_CLAIMABLE_BALANCE_CANNOT_CLAIM, CLAIM_CLAIMABLE_BALANCE_LINE_FULL, CLAIM_CLAIMABLE_BALANCE_NO_TRUST, CLAIM_CLAIMABLE_BALANCE_NOT_AUTHORIZED: - return nil +func (v PublicKeyType) String() string { + if s, ok := _XdrNames_PublicKeyType[int32(v)]; ok { + return s } - return nil + return fmt.Sprintf("PublicKeyType#%d", v) } -func (u *ClaimClaimableBalanceResult) XdrUnionBodyName() string { - switch u.Code { - case CLAIM_CLAIMABLE_BALANCE_SUCCESS: - return "" - case CLAIM_CLAIMABLE_BALANCE_DOES_NOT_EXIST, CLAIM_CLAIMABLE_BALANCE_CANNOT_CLAIM, CLAIM_CLAIMABLE_BALANCE_LINE_FULL, CLAIM_CLAIMABLE_BALANCE_NO_TRUST, CLAIM_CLAIMABLE_BALANCE_NOT_AUTHORIZED: - return "" +func (v *PublicKeyType) Scan(ss fmt.ScanState, _ rune) error { + if tok, err := ss.Token(true, XdrSymChar); err != nil { + return err + } else { + stok := string(tok) + if val, ok := _XdrValues_PublicKeyType[stok]; ok { + *v = PublicKeyType(val) + return nil + } else if stok == "PublicKeyType" { + if n, err := fmt.Fscanf(ss, "#%d", (*int32)(v)); n == 1 && err == nil { + return nil + } + } + return XdrError(fmt.Sprintf("%s is not a valid PublicKeyType.", stok)) } - return "" } +func (v PublicKeyType) GetU32() uint32 { return uint32(v) } +func (v *PublicKeyType) SetU32(n uint32) { *v = PublicKeyType(n) } +func (v *PublicKeyType) XdrPointer() interface{} { return v } +func (PublicKeyType) XdrTypeName() string { return "PublicKeyType" } +func (v PublicKeyType) XdrValue() interface{} { return v } +func (v *PublicKeyType) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -type XdrType_ClaimClaimableBalanceResult = *ClaimClaimableBalanceResult +type XdrType_PublicKeyType = *PublicKeyType -func (v *ClaimClaimableBalanceResult) XdrPointer() interface{} { return v } -func (ClaimClaimableBalanceResult) XdrTypeName() string { return "ClaimClaimableBalanceResult" } -func (v ClaimClaimableBalanceResult) XdrValue() interface{} { return v } -func (v *ClaimClaimableBalanceResult) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -func (u *ClaimClaimableBalanceResult) XdrRecurse(x XDR, name string) { - if name != "" { - name = x.Sprintf("%s.", name) - } - XDR_ClaimClaimableBalanceResultCode(&u.Code).XdrMarshal(x, x.Sprintf("%scode", name)) - switch u.Code { - case CLAIM_CLAIMABLE_BALANCE_SUCCESS: - return - case CLAIM_CLAIMABLE_BALANCE_DOES_NOT_EXIST, CLAIM_CLAIMABLE_BALANCE_CANNOT_CLAIM, CLAIM_CLAIMABLE_BALANCE_LINE_FULL, CLAIM_CLAIMABLE_BALANCE_NO_TRUST, CLAIM_CLAIMABLE_BALANCE_NOT_AUTHORIZED: - return - } - XdrPanic("invalid Code (%v) in ClaimClaimableBalanceResult", u.Code) -} -func XDR_ClaimClaimableBalanceResult(v *ClaimClaimableBalanceResult) *ClaimClaimableBalanceResult { - return v -} +func XDR_PublicKeyType(v *PublicKeyType) *PublicKeyType { return v } -var _XdrNames_BeginSponsoringFutureReservesResultCode = map[int32]string{ - int32(BEGIN_SPONSORING_FUTURE_RESERVES_SUCCESS): "BEGIN_SPONSORING_FUTURE_RESERVES_SUCCESS", - int32(BEGIN_SPONSORING_FUTURE_RESERVES_MALFORMED): "BEGIN_SPONSORING_FUTURE_RESERVES_MALFORMED", - int32(BEGIN_SPONSORING_FUTURE_RESERVES_ALREADY_SPONSORED): "BEGIN_SPONSORING_FUTURE_RESERVES_ALREADY_SPONSORED", - int32(BEGIN_SPONSORING_FUTURE_RESERVES_RECURSIVE): "BEGIN_SPONSORING_FUTURE_RESERVES_RECURSIVE", +var _XdrNames_SignerKeyType = map[int32]string{ + int32(SIGNER_KEY_TYPE_ED25519): "SIGNER_KEY_TYPE_ED25519", + int32(SIGNER_KEY_TYPE_PRE_AUTH_TX): "SIGNER_KEY_TYPE_PRE_AUTH_TX", + int32(SIGNER_KEY_TYPE_HASH_X): "SIGNER_KEY_TYPE_HASH_X", + int32(SIGNER_KEY_TYPE_ED25519_SIGNED_PAYLOAD): "SIGNER_KEY_TYPE_ED25519_SIGNED_PAYLOAD", } -var _XdrValues_BeginSponsoringFutureReservesResultCode = map[string]int32{ - "BEGIN_SPONSORING_FUTURE_RESERVES_SUCCESS": int32(BEGIN_SPONSORING_FUTURE_RESERVES_SUCCESS), - "BEGIN_SPONSORING_FUTURE_RESERVES_MALFORMED": int32(BEGIN_SPONSORING_FUTURE_RESERVES_MALFORMED), - "BEGIN_SPONSORING_FUTURE_RESERVES_ALREADY_SPONSORED": int32(BEGIN_SPONSORING_FUTURE_RESERVES_ALREADY_SPONSORED), - "BEGIN_SPONSORING_FUTURE_RESERVES_RECURSIVE": int32(BEGIN_SPONSORING_FUTURE_RESERVES_RECURSIVE), +var _XdrValues_SignerKeyType = map[string]int32{ + "SIGNER_KEY_TYPE_ED25519": int32(SIGNER_KEY_TYPE_ED25519), + "SIGNER_KEY_TYPE_PRE_AUTH_TX": int32(SIGNER_KEY_TYPE_PRE_AUTH_TX), + "SIGNER_KEY_TYPE_HASH_X": int32(SIGNER_KEY_TYPE_HASH_X), + "SIGNER_KEY_TYPE_ED25519_SIGNED_PAYLOAD": int32(SIGNER_KEY_TYPE_ED25519_SIGNED_PAYLOAD), } -func (BeginSponsoringFutureReservesResultCode) XdrEnumNames() map[int32]string { - return _XdrNames_BeginSponsoringFutureReservesResultCode +func (SignerKeyType) XdrEnumNames() map[int32]string { + return _XdrNames_SignerKeyType } -func (v BeginSponsoringFutureReservesResultCode) String() string { - if s, ok := _XdrNames_BeginSponsoringFutureReservesResultCode[int32(v)]; ok { +func (v SignerKeyType) String() string { + if s, ok := _XdrNames_SignerKeyType[int32(v)]; ok { return s } - return fmt.Sprintf("BeginSponsoringFutureReservesResultCode#%d", v) + return fmt.Sprintf("SignerKeyType#%d", v) } -func (v *BeginSponsoringFutureReservesResultCode) Scan(ss fmt.ScanState, _ rune) error { +func (v *SignerKeyType) Scan(ss fmt.ScanState, _ rune) error { if tok, err := ss.Token(true, XdrSymChar); err != nil { return err } else { stok := string(tok) - if val, ok := _XdrValues_BeginSponsoringFutureReservesResultCode[stok]; ok { - *v = BeginSponsoringFutureReservesResultCode(val) + if val, ok := _XdrValues_SignerKeyType[stok]; ok { + *v = SignerKeyType(val) return nil - } else if stok == "BeginSponsoringFutureReservesResultCode" { + } else if stok == "SignerKeyType" { if n, err := fmt.Fscanf(ss, "#%d", (*int32)(v)); n == 1 && err == nil { return nil } } - return XdrError(fmt.Sprintf("%s is not a valid BeginSponsoringFutureReservesResultCode.", stok)) - } -} -func (v BeginSponsoringFutureReservesResultCode) GetU32() uint32 { return uint32(v) } -func (v *BeginSponsoringFutureReservesResultCode) SetU32(n uint32) { - *v = BeginSponsoringFutureReservesResultCode(n) -} -func (v *BeginSponsoringFutureReservesResultCode) XdrPointer() interface{} { return v } -func (BeginSponsoringFutureReservesResultCode) XdrTypeName() string { - return "BeginSponsoringFutureReservesResultCode" -} -func (v BeginSponsoringFutureReservesResultCode) XdrValue() interface{} { return v } -func (v *BeginSponsoringFutureReservesResultCode) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } - -type XdrType_BeginSponsoringFutureReservesResultCode = *BeginSponsoringFutureReservesResultCode - -func XDR_BeginSponsoringFutureReservesResultCode(v *BeginSponsoringFutureReservesResultCode) *BeginSponsoringFutureReservesResultCode { - return v + return XdrError(fmt.Sprintf("%s is not a valid SignerKeyType.", stok)) + } } +func (v SignerKeyType) GetU32() uint32 { return uint32(v) } +func (v *SignerKeyType) SetU32(n uint32) { *v = SignerKeyType(n) } +func (v *SignerKeyType) XdrPointer() interface{} { return v } +func (SignerKeyType) XdrTypeName() string { return "SignerKeyType" } +func (v SignerKeyType) XdrValue() interface{} { return v } +func (v *SignerKeyType) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -var _XdrComments_BeginSponsoringFutureReservesResultCode = map[int32]string{ - int32(BEGIN_SPONSORING_FUTURE_RESERVES_SUCCESS): "codes considered as \"success\" for the operation", - int32(BEGIN_SPONSORING_FUTURE_RESERVES_MALFORMED): "codes considered as \"failure\" for the operation", -} +type XdrType_SignerKeyType = *SignerKeyType -func (e BeginSponsoringFutureReservesResultCode) XdrEnumComments() map[int32]string { - return _XdrComments_BeginSponsoringFutureReservesResultCode -} +func XDR_SignerKeyType(v *SignerKeyType) *SignerKeyType { return v } -var _XdrTags_BeginSponsoringFutureReservesResult = map[int32]bool{ - XdrToI32(BEGIN_SPONSORING_FUTURE_RESERVES_SUCCESS): true, - XdrToI32(BEGIN_SPONSORING_FUTURE_RESERVES_MALFORMED): true, - XdrToI32(BEGIN_SPONSORING_FUTURE_RESERVES_ALREADY_SPONSORED): true, - XdrToI32(BEGIN_SPONSORING_FUTURE_RESERVES_RECURSIVE): true, +var _XdrTags_PublicKey = map[int32]bool{ + XdrToI32(PUBLIC_KEY_TYPE_ED25519): true, } -func (_ BeginSponsoringFutureReservesResult) XdrValidTags() map[int32]bool { - return _XdrTags_BeginSponsoringFutureReservesResult +func (_ PublicKey) XdrValidTags() map[int32]bool { + return _XdrTags_PublicKey } -func (u BeginSponsoringFutureReservesResult) XdrValid() bool { - switch u.Code { - case BEGIN_SPONSORING_FUTURE_RESERVES_SUCCESS, BEGIN_SPONSORING_FUTURE_RESERVES_MALFORMED, BEGIN_SPONSORING_FUTURE_RESERVES_ALREADY_SPONSORED, BEGIN_SPONSORING_FUTURE_RESERVES_RECURSIVE: +func (u *PublicKey) Ed25519() *Uint256 { + switch u.Type { + case PUBLIC_KEY_TYPE_ED25519: + if v, ok := u._u.(*Uint256); ok { + return v + } else { + var zero Uint256 + u._u = &zero + return &zero + } + default: + XdrPanic("PublicKey.Ed25519 accessed when Type == %v", u.Type) + return nil + } +} +func (u PublicKey) XdrValid() bool { + switch u.Type { + case PUBLIC_KEY_TYPE_ED25519: return true } return false } -func (u *BeginSponsoringFutureReservesResult) XdrUnionTag() XdrNum32 { - return XDR_BeginSponsoringFutureReservesResultCode(&u.Code) +func (u *PublicKey) XdrUnionTag() XdrNum32 { + return XDR_PublicKeyType(&u.Type) } -func (u *BeginSponsoringFutureReservesResult) XdrUnionTagName() string { - return "Code" +func (u *PublicKey) XdrUnionTagName() string { + return "Type" } -func (u *BeginSponsoringFutureReservesResult) XdrUnionBody() XdrType { - switch u.Code { - case BEGIN_SPONSORING_FUTURE_RESERVES_SUCCESS: - return nil - case BEGIN_SPONSORING_FUTURE_RESERVES_MALFORMED, BEGIN_SPONSORING_FUTURE_RESERVES_ALREADY_SPONSORED, BEGIN_SPONSORING_FUTURE_RESERVES_RECURSIVE: - return nil +func (u *PublicKey) XdrUnionBody() XdrType { + switch u.Type { + case PUBLIC_KEY_TYPE_ED25519: + return XDR_Uint256(u.Ed25519()) } return nil } -func (u *BeginSponsoringFutureReservesResult) XdrUnionBodyName() string { - switch u.Code { - case BEGIN_SPONSORING_FUTURE_RESERVES_SUCCESS: - return "" - case BEGIN_SPONSORING_FUTURE_RESERVES_MALFORMED, BEGIN_SPONSORING_FUTURE_RESERVES_ALREADY_SPONSORED, BEGIN_SPONSORING_FUTURE_RESERVES_RECURSIVE: - return "" +func (u *PublicKey) XdrUnionBodyName() string { + switch u.Type { + case PUBLIC_KEY_TYPE_ED25519: + return "Ed25519" } return "" } -type XdrType_BeginSponsoringFutureReservesResult = *BeginSponsoringFutureReservesResult +type XdrType_PublicKey = *PublicKey -func (v *BeginSponsoringFutureReservesResult) XdrPointer() interface{} { return v } -func (BeginSponsoringFutureReservesResult) XdrTypeName() string { - return "BeginSponsoringFutureReservesResult" -} -func (v BeginSponsoringFutureReservesResult) XdrValue() interface{} { return v } -func (v *BeginSponsoringFutureReservesResult) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -func (u *BeginSponsoringFutureReservesResult) XdrRecurse(x XDR, name string) { +func (v *PublicKey) XdrPointer() interface{} { return v } +func (PublicKey) XdrTypeName() string { return "PublicKey" } +func (v PublicKey) XdrValue() interface{} { return v } +func (v *PublicKey) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (u *PublicKey) XdrRecurse(x XDR, name string) { if name != "" { name = x.Sprintf("%s.", name) } - XDR_BeginSponsoringFutureReservesResultCode(&u.Code).XdrMarshal(x, x.Sprintf("%scode", name)) - switch u.Code { - case BEGIN_SPONSORING_FUTURE_RESERVES_SUCCESS: - return - case BEGIN_SPONSORING_FUTURE_RESERVES_MALFORMED, BEGIN_SPONSORING_FUTURE_RESERVES_ALREADY_SPONSORED, BEGIN_SPONSORING_FUTURE_RESERVES_RECURSIVE: + XDR_PublicKeyType(&u.Type).XdrMarshal(x, x.Sprintf("%stype", name)) + switch u.Type { + case PUBLIC_KEY_TYPE_ED25519: + x.Marshal(x.Sprintf("%sed25519", name), XDR_Uint256(u.Ed25519())) return } - XdrPanic("invalid Code (%v) in BeginSponsoringFutureReservesResult", u.Code) + XdrPanic("invalid Type (%v) in PublicKey", u.Type) } -func XDR_BeginSponsoringFutureReservesResult(v *BeginSponsoringFutureReservesResult) *BeginSponsoringFutureReservesResult { +func XDR_PublicKey(v *PublicKey) *PublicKey { return v } + +type XdrType_XdrAnon_SignerKey_Ed25519SignedPayload = *XdrAnon_SignerKey_Ed25519SignedPayload + +func (v *XdrAnon_SignerKey_Ed25519SignedPayload) XdrPointer() interface{} { return v } +func (XdrAnon_SignerKey_Ed25519SignedPayload) XdrTypeName() string { + return "XdrAnon_SignerKey_Ed25519SignedPayload" +} +func (v XdrAnon_SignerKey_Ed25519SignedPayload) XdrValue() interface{} { return v } +func (v *XdrAnon_SignerKey_Ed25519SignedPayload) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v *XdrAnon_SignerKey_Ed25519SignedPayload) XdrRecurse(x XDR, name string) { + if name != "" { + name = x.Sprintf("%s.", name) + } + x.Marshal(x.Sprintf("%sed25519", name), XDR_Uint256(&v.Ed25519)) + x.Marshal(x.Sprintf("%spayload", name), XdrVecOpaque{&v.Payload, 64}) +} +func XDR_XdrAnon_SignerKey_Ed25519SignedPayload(v *XdrAnon_SignerKey_Ed25519SignedPayload) *XdrAnon_SignerKey_Ed25519SignedPayload { return v } -var _XdrNames_EndSponsoringFutureReservesResultCode = map[int32]string{ - int32(END_SPONSORING_FUTURE_RESERVES_SUCCESS): "END_SPONSORING_FUTURE_RESERVES_SUCCESS", - int32(END_SPONSORING_FUTURE_RESERVES_NOT_SPONSORED): "END_SPONSORING_FUTURE_RESERVES_NOT_SPONSORED", +var _XdrTags_SignerKey = map[int32]bool{ + XdrToI32(SIGNER_KEY_TYPE_ED25519): true, + XdrToI32(SIGNER_KEY_TYPE_PRE_AUTH_TX): true, + XdrToI32(SIGNER_KEY_TYPE_HASH_X): true, + XdrToI32(SIGNER_KEY_TYPE_ED25519_SIGNED_PAYLOAD): true, } -var _XdrValues_EndSponsoringFutureReservesResultCode = map[string]int32{ - "END_SPONSORING_FUTURE_RESERVES_SUCCESS": int32(END_SPONSORING_FUTURE_RESERVES_SUCCESS), - "END_SPONSORING_FUTURE_RESERVES_NOT_SPONSORED": int32(END_SPONSORING_FUTURE_RESERVES_NOT_SPONSORED), + +func (_ SignerKey) XdrValidTags() map[int32]bool { + return _XdrTags_SignerKey +} +func (u *SignerKey) Ed25519() *Uint256 { + switch u.Type { + case SIGNER_KEY_TYPE_ED25519: + if v, ok := u._u.(*Uint256); ok { + return v + } else { + var zero Uint256 + u._u = &zero + return &zero + } + default: + XdrPanic("SignerKey.Ed25519 accessed when Type == %v", u.Type) + return nil + } } -func (EndSponsoringFutureReservesResultCode) XdrEnumNames() map[int32]string { - return _XdrNames_EndSponsoringFutureReservesResultCode +/* SHA-256 Hash of TransactionSignaturePayload structure */ +func (u *SignerKey) PreAuthTx() *Uint256 { + switch u.Type { + case SIGNER_KEY_TYPE_PRE_AUTH_TX: + if v, ok := u._u.(*Uint256); ok { + return v + } else { + var zero Uint256 + u._u = &zero + return &zero + } + default: + XdrPanic("SignerKey.PreAuthTx accessed when Type == %v", u.Type) + return nil + } } -func (v EndSponsoringFutureReservesResultCode) String() string { - if s, ok := _XdrNames_EndSponsoringFutureReservesResultCode[int32(v)]; ok { - return s + +/* Hash of random 256 bit preimage X */ +func (u *SignerKey) HashX() *Uint256 { + switch u.Type { + case SIGNER_KEY_TYPE_HASH_X: + if v, ok := u._u.(*Uint256); ok { + return v + } else { + var zero Uint256 + u._u = &zero + return &zero + } + default: + XdrPanic("SignerKey.HashX accessed when Type == %v", u.Type) + return nil } - return fmt.Sprintf("EndSponsoringFutureReservesResultCode#%d", v) } -func (v *EndSponsoringFutureReservesResultCode) Scan(ss fmt.ScanState, _ rune) error { - if tok, err := ss.Token(true, XdrSymChar); err != nil { - return err - } else { - stok := string(tok) - if val, ok := _XdrValues_EndSponsoringFutureReservesResultCode[stok]; ok { - *v = EndSponsoringFutureReservesResultCode(val) - return nil - } else if stok == "EndSponsoringFutureReservesResultCode" { - if n, err := fmt.Fscanf(ss, "#%d", (*int32)(v)); n == 1 && err == nil { - return nil - } +func (u *SignerKey) Ed25519SignedPayload() *XdrAnon_SignerKey_Ed25519SignedPayload { + switch u.Type { + case SIGNER_KEY_TYPE_ED25519_SIGNED_PAYLOAD: + if v, ok := u._u.(*XdrAnon_SignerKey_Ed25519SignedPayload); ok { + return v + } else { + var zero XdrAnon_SignerKey_Ed25519SignedPayload + u._u = &zero + return &zero } - return XdrError(fmt.Sprintf("%s is not a valid EndSponsoringFutureReservesResultCode.", stok)) + default: + XdrPanic("SignerKey.Ed25519SignedPayload accessed when Type == %v", u.Type) + return nil + } +} +func (u SignerKey) XdrValid() bool { + switch u.Type { + case SIGNER_KEY_TYPE_ED25519, SIGNER_KEY_TYPE_PRE_AUTH_TX, SIGNER_KEY_TYPE_HASH_X, SIGNER_KEY_TYPE_ED25519_SIGNED_PAYLOAD: + return true + } + return false +} +func (u *SignerKey) XdrUnionTag() XdrNum32 { + return XDR_SignerKeyType(&u.Type) +} +func (u *SignerKey) XdrUnionTagName() string { + return "Type" +} +func (u *SignerKey) XdrUnionBody() XdrType { + switch u.Type { + case SIGNER_KEY_TYPE_ED25519: + return XDR_Uint256(u.Ed25519()) + case SIGNER_KEY_TYPE_PRE_AUTH_TX: + return XDR_Uint256(u.PreAuthTx()) + case SIGNER_KEY_TYPE_HASH_X: + return XDR_Uint256(u.HashX()) + case SIGNER_KEY_TYPE_ED25519_SIGNED_PAYLOAD: + return XDR_XdrAnon_SignerKey_Ed25519SignedPayload(u.Ed25519SignedPayload()) + } + return nil +} +func (u *SignerKey) XdrUnionBodyName() string { + switch u.Type { + case SIGNER_KEY_TYPE_ED25519: + return "Ed25519" + case SIGNER_KEY_TYPE_PRE_AUTH_TX: + return "PreAuthTx" + case SIGNER_KEY_TYPE_HASH_X: + return "HashX" + case SIGNER_KEY_TYPE_ED25519_SIGNED_PAYLOAD: + return "Ed25519SignedPayload" + } + return "" +} + +type XdrType_SignerKey = *SignerKey + +func (v *SignerKey) XdrPointer() interface{} { return v } +func (SignerKey) XdrTypeName() string { return "SignerKey" } +func (v SignerKey) XdrValue() interface{} { return v } +func (v *SignerKey) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (u *SignerKey) XdrRecurse(x XDR, name string) { + if name != "" { + name = x.Sprintf("%s.", name) + } + XDR_SignerKeyType(&u.Type).XdrMarshal(x, x.Sprintf("%stype", name)) + switch u.Type { + case SIGNER_KEY_TYPE_ED25519: + x.Marshal(x.Sprintf("%sed25519", name), XDR_Uint256(u.Ed25519())) + return + case SIGNER_KEY_TYPE_PRE_AUTH_TX: + x.Marshal(x.Sprintf("%spreAuthTx", name), XDR_Uint256(u.PreAuthTx())) + return + case SIGNER_KEY_TYPE_HASH_X: + x.Marshal(x.Sprintf("%shashX", name), XDR_Uint256(u.HashX())) + return + case SIGNER_KEY_TYPE_ED25519_SIGNED_PAYLOAD: + x.Marshal(x.Sprintf("%sed25519SignedPayload", name), XDR_XdrAnon_SignerKey_Ed25519SignedPayload(u.Ed25519SignedPayload())) + return } + XdrPanic("invalid Type (%v) in SignerKey", u.Type) } -func (v EndSponsoringFutureReservesResultCode) GetU32() uint32 { return uint32(v) } -func (v *EndSponsoringFutureReservesResultCode) SetU32(n uint32) { - *v = EndSponsoringFutureReservesResultCode(n) +func XDR_SignerKey(v *SignerKey) *SignerKey { return v } + +type XdrType_Signature struct { + XdrVecOpaque } -func (v *EndSponsoringFutureReservesResultCode) XdrPointer() interface{} { return v } -func (EndSponsoringFutureReservesResultCode) XdrTypeName() string { - return "EndSponsoringFutureReservesResultCode" + +func XDR_Signature(v *Signature) XdrType_Signature { + return XdrType_Signature{XdrVecOpaque{v, 64}} } -func (v EndSponsoringFutureReservesResultCode) XdrValue() interface{} { return v } -func (v *EndSponsoringFutureReservesResultCode) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (XdrType_Signature) XdrTypeName() string { return "Signature" } +func (v XdrType_Signature) XdrUnwrap() XdrType { return v.XdrVecOpaque } -type XdrType_EndSponsoringFutureReservesResultCode = *EndSponsoringFutureReservesResultCode +type XdrType_SignatureHint struct { + *_XdrArray_4_opaque +} -func XDR_EndSponsoringFutureReservesResultCode(v *EndSponsoringFutureReservesResultCode) *EndSponsoringFutureReservesResultCode { - return v +func XDR_SignatureHint(v *SignatureHint) XdrType_SignatureHint { + return XdrType_SignatureHint{(*_XdrArray_4_opaque)(v)} } +func (XdrType_SignatureHint) XdrTypeName() string { return "SignatureHint" } +func (v XdrType_SignatureHint) XdrUnwrap() XdrType { return v._XdrArray_4_opaque } -var _XdrComments_EndSponsoringFutureReservesResultCode = map[int32]string{ - int32(END_SPONSORING_FUTURE_RESERVES_SUCCESS): "codes considered as \"success\" for the operation", - int32(END_SPONSORING_FUTURE_RESERVES_NOT_SPONSORED): "codes considered as \"failure\" for the operation", +type XdrType_NodeID struct { + XdrType_PublicKey } -func (e EndSponsoringFutureReservesResultCode) XdrEnumComments() map[int32]string { - return _XdrComments_EndSponsoringFutureReservesResultCode +func XDR_NodeID(v *NodeID) XdrType_NodeID { + return XdrType_NodeID{XDR_PublicKey(v)} } +func (XdrType_NodeID) XdrTypeName() string { return "NodeID" } +func (v XdrType_NodeID) XdrUnwrap() XdrType { return v.XdrType_PublicKey } -var _XdrTags_EndSponsoringFutureReservesResult = map[int32]bool{ - XdrToI32(END_SPONSORING_FUTURE_RESERVES_SUCCESS): true, - XdrToI32(END_SPONSORING_FUTURE_RESERVES_NOT_SPONSORED): true, +type XdrType_AccountID struct { + XdrType_PublicKey } -func (_ EndSponsoringFutureReservesResult) XdrValidTags() map[int32]bool { - return _XdrTags_EndSponsoringFutureReservesResult +func XDR_AccountID(v *AccountID) XdrType_AccountID { + return XdrType_AccountID{XDR_PublicKey(v)} } -func (u EndSponsoringFutureReservesResult) XdrValid() bool { - switch u.Code { - case END_SPONSORING_FUTURE_RESERVES_SUCCESS, END_SPONSORING_FUTURE_RESERVES_NOT_SPONSORED: - return true +func (XdrType_AccountID) XdrTypeName() string { return "AccountID" } +func (v XdrType_AccountID) XdrUnwrap() XdrType { return v.XdrType_PublicKey } + +type XdrType_Curve25519Secret = *Curve25519Secret + +func (v *Curve25519Secret) XdrPointer() interface{} { return v } +func (Curve25519Secret) XdrTypeName() string { return "Curve25519Secret" } +func (v Curve25519Secret) XdrValue() interface{} { return v } +func (v *Curve25519Secret) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v *Curve25519Secret) XdrRecurse(x XDR, name string) { + if name != "" { + name = x.Sprintf("%s.", name) } - return false -} -func (u *EndSponsoringFutureReservesResult) XdrUnionTag() XdrNum32 { - return XDR_EndSponsoringFutureReservesResultCode(&u.Code) -} -func (u *EndSponsoringFutureReservesResult) XdrUnionTagName() string { - return "Code" + x.Marshal(x.Sprintf("%skey", name), (*_XdrArray_32_opaque)(&v.Key)) } -func (u *EndSponsoringFutureReservesResult) XdrUnionBody() XdrType { - switch u.Code { - case END_SPONSORING_FUTURE_RESERVES_SUCCESS: - return nil - case END_SPONSORING_FUTURE_RESERVES_NOT_SPONSORED: - return nil +func XDR_Curve25519Secret(v *Curve25519Secret) *Curve25519Secret { return v } + +type XdrType_Curve25519Public = *Curve25519Public + +func (v *Curve25519Public) XdrPointer() interface{} { return v } +func (Curve25519Public) XdrTypeName() string { return "Curve25519Public" } +func (v Curve25519Public) XdrValue() interface{} { return v } +func (v *Curve25519Public) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v *Curve25519Public) XdrRecurse(x XDR, name string) { + if name != "" { + name = x.Sprintf("%s.", name) } - return nil + x.Marshal(x.Sprintf("%skey", name), (*_XdrArray_32_opaque)(&v.Key)) } -func (u *EndSponsoringFutureReservesResult) XdrUnionBodyName() string { - switch u.Code { - case END_SPONSORING_FUTURE_RESERVES_SUCCESS: - return "" - case END_SPONSORING_FUTURE_RESERVES_NOT_SPONSORED: - return "" +func XDR_Curve25519Public(v *Curve25519Public) *Curve25519Public { return v } + +type XdrType_HmacSha256Key = *HmacSha256Key + +func (v *HmacSha256Key) XdrPointer() interface{} { return v } +func (HmacSha256Key) XdrTypeName() string { return "HmacSha256Key" } +func (v HmacSha256Key) XdrValue() interface{} { return v } +func (v *HmacSha256Key) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v *HmacSha256Key) XdrRecurse(x XDR, name string) { + if name != "" { + name = x.Sprintf("%s.", name) } - return "" + x.Marshal(x.Sprintf("%skey", name), (*_XdrArray_32_opaque)(&v.Key)) } +func XDR_HmacSha256Key(v *HmacSha256Key) *HmacSha256Key { return v } -type XdrType_EndSponsoringFutureReservesResult = *EndSponsoringFutureReservesResult +type XdrType_HmacSha256Mac = *HmacSha256Mac -func (v *EndSponsoringFutureReservesResult) XdrPointer() interface{} { return v } -func (EndSponsoringFutureReservesResult) XdrTypeName() string { - return "EndSponsoringFutureReservesResult" -} -func (v EndSponsoringFutureReservesResult) XdrValue() interface{} { return v } -func (v *EndSponsoringFutureReservesResult) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -func (u *EndSponsoringFutureReservesResult) XdrRecurse(x XDR, name string) { +func (v *HmacSha256Mac) XdrPointer() interface{} { return v } +func (HmacSha256Mac) XdrTypeName() string { return "HmacSha256Mac" } +func (v HmacSha256Mac) XdrValue() interface{} { return v } +func (v *HmacSha256Mac) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v *HmacSha256Mac) XdrRecurse(x XDR, name string) { if name != "" { name = x.Sprintf("%s.", name) } - XDR_EndSponsoringFutureReservesResultCode(&u.Code).XdrMarshal(x, x.Sprintf("%scode", name)) - switch u.Code { - case END_SPONSORING_FUTURE_RESERVES_SUCCESS: - return - case END_SPONSORING_FUTURE_RESERVES_NOT_SPONSORED: - return - } - XdrPanic("invalid Code (%v) in EndSponsoringFutureReservesResult", u.Code) -} -func XDR_EndSponsoringFutureReservesResult(v *EndSponsoringFutureReservesResult) *EndSponsoringFutureReservesResult { - return v + x.Marshal(x.Sprintf("%smac", name), (*_XdrArray_32_opaque)(&v.Mac)) } +func XDR_HmacSha256Mac(v *HmacSha256Mac) *HmacSha256Mac { return v } -var _XdrNames_RevokeSponsorshipResultCode = map[int32]string{ - int32(REVOKE_SPONSORSHIP_SUCCESS): "REVOKE_SPONSORSHIP_SUCCESS", - int32(REVOKE_SPONSORSHIP_DOES_NOT_EXIST): "REVOKE_SPONSORSHIP_DOES_NOT_EXIST", - int32(REVOKE_SPONSORSHIP_NOT_SPONSOR): "REVOKE_SPONSORSHIP_NOT_SPONSOR", - int32(REVOKE_SPONSORSHIP_LOW_RESERVE): "REVOKE_SPONSORSHIP_LOW_RESERVE", - int32(REVOKE_SPONSORSHIP_ONLY_TRANSFERABLE): "REVOKE_SPONSORSHIP_ONLY_TRANSFERABLE", - int32(REVOKE_SPONSORSHIP_MALFORMED): "REVOKE_SPONSORSHIP_MALFORMED", +var _XdrNames_SCEnvMetaKind = map[int32]string{ + int32(SC_ENV_META_KIND_INTERFACE_VERSION): "SC_ENV_META_KIND_INTERFACE_VERSION", } -var _XdrValues_RevokeSponsorshipResultCode = map[string]int32{ - "REVOKE_SPONSORSHIP_SUCCESS": int32(REVOKE_SPONSORSHIP_SUCCESS), - "REVOKE_SPONSORSHIP_DOES_NOT_EXIST": int32(REVOKE_SPONSORSHIP_DOES_NOT_EXIST), - "REVOKE_SPONSORSHIP_NOT_SPONSOR": int32(REVOKE_SPONSORSHIP_NOT_SPONSOR), - "REVOKE_SPONSORSHIP_LOW_RESERVE": int32(REVOKE_SPONSORSHIP_LOW_RESERVE), - "REVOKE_SPONSORSHIP_ONLY_TRANSFERABLE": int32(REVOKE_SPONSORSHIP_ONLY_TRANSFERABLE), - "REVOKE_SPONSORSHIP_MALFORMED": int32(REVOKE_SPONSORSHIP_MALFORMED), +var _XdrValues_SCEnvMetaKind = map[string]int32{ + "SC_ENV_META_KIND_INTERFACE_VERSION": int32(SC_ENV_META_KIND_INTERFACE_VERSION), } -func (RevokeSponsorshipResultCode) XdrEnumNames() map[int32]string { - return _XdrNames_RevokeSponsorshipResultCode +func (SCEnvMetaKind) XdrEnumNames() map[int32]string { + return _XdrNames_SCEnvMetaKind } -func (v RevokeSponsorshipResultCode) String() string { - if s, ok := _XdrNames_RevokeSponsorshipResultCode[int32(v)]; ok { +func (v SCEnvMetaKind) String() string { + if s, ok := _XdrNames_SCEnvMetaKind[int32(v)]; ok { return s } - return fmt.Sprintf("RevokeSponsorshipResultCode#%d", v) + return fmt.Sprintf("SCEnvMetaKind#%d", v) } -func (v *RevokeSponsorshipResultCode) Scan(ss fmt.ScanState, _ rune) error { +func (v *SCEnvMetaKind) Scan(ss fmt.ScanState, _ rune) error { if tok, err := ss.Token(true, XdrSymChar); err != nil { return err } else { stok := string(tok) - if val, ok := _XdrValues_RevokeSponsorshipResultCode[stok]; ok { - *v = RevokeSponsorshipResultCode(val) + if val, ok := _XdrValues_SCEnvMetaKind[stok]; ok { + *v = SCEnvMetaKind(val) return nil - } else if stok == "RevokeSponsorshipResultCode" { + } else if stok == "SCEnvMetaKind" { if n, err := fmt.Fscanf(ss, "#%d", (*int32)(v)); n == 1 && err == nil { return nil } } - return XdrError(fmt.Sprintf("%s is not a valid RevokeSponsorshipResultCode.", stok)) + return XdrError(fmt.Sprintf("%s is not a valid SCEnvMetaKind.", stok)) } } -func (v RevokeSponsorshipResultCode) GetU32() uint32 { return uint32(v) } -func (v *RevokeSponsorshipResultCode) SetU32(n uint32) { *v = RevokeSponsorshipResultCode(n) } -func (v *RevokeSponsorshipResultCode) XdrPointer() interface{} { return v } -func (RevokeSponsorshipResultCode) XdrTypeName() string { return "RevokeSponsorshipResultCode" } -func (v RevokeSponsorshipResultCode) XdrValue() interface{} { return v } -func (v *RevokeSponsorshipResultCode) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } - -type XdrType_RevokeSponsorshipResultCode = *RevokeSponsorshipResultCode +func (v SCEnvMetaKind) GetU32() uint32 { return uint32(v) } +func (v *SCEnvMetaKind) SetU32(n uint32) { *v = SCEnvMetaKind(n) } +func (v *SCEnvMetaKind) XdrPointer() interface{} { return v } +func (SCEnvMetaKind) XdrTypeName() string { return "SCEnvMetaKind" } +func (v SCEnvMetaKind) XdrValue() interface{} { return v } +func (v *SCEnvMetaKind) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -func XDR_RevokeSponsorshipResultCode(v *RevokeSponsorshipResultCode) *RevokeSponsorshipResultCode { - return v -} +type XdrType_SCEnvMetaKind = *SCEnvMetaKind -var _XdrComments_RevokeSponsorshipResultCode = map[int32]string{ - int32(REVOKE_SPONSORSHIP_SUCCESS): "codes considered as \"success\" for the operation", - int32(REVOKE_SPONSORSHIP_DOES_NOT_EXIST): "codes considered as \"failure\" for the operation", -} +func XDR_SCEnvMetaKind(v *SCEnvMetaKind) *SCEnvMetaKind { return v } -func (e RevokeSponsorshipResultCode) XdrEnumComments() map[int32]string { - return _XdrComments_RevokeSponsorshipResultCode +var _XdrTags_SCEnvMetaEntry = map[int32]bool{ + XdrToI32(SC_ENV_META_KIND_INTERFACE_VERSION): true, } -var _XdrTags_RevokeSponsorshipResult = map[int32]bool{ - XdrToI32(REVOKE_SPONSORSHIP_SUCCESS): true, - XdrToI32(REVOKE_SPONSORSHIP_DOES_NOT_EXIST): true, - XdrToI32(REVOKE_SPONSORSHIP_NOT_SPONSOR): true, - XdrToI32(REVOKE_SPONSORSHIP_LOW_RESERVE): true, - XdrToI32(REVOKE_SPONSORSHIP_ONLY_TRANSFERABLE): true, - XdrToI32(REVOKE_SPONSORSHIP_MALFORMED): true, +func (_ SCEnvMetaEntry) XdrValidTags() map[int32]bool { + return _XdrTags_SCEnvMetaEntry } - -func (_ RevokeSponsorshipResult) XdrValidTags() map[int32]bool { - return _XdrTags_RevokeSponsorshipResult +func (u *SCEnvMetaEntry) InterfaceVersion() *Uint64 { + switch u.Kind { + case SC_ENV_META_KIND_INTERFACE_VERSION: + if v, ok := u._u.(*Uint64); ok { + return v + } else { + var zero Uint64 + u._u = &zero + return &zero + } + default: + XdrPanic("SCEnvMetaEntry.InterfaceVersion accessed when Kind == %v", u.Kind) + return nil + } } -func (u RevokeSponsorshipResult) XdrValid() bool { - switch u.Code { - case REVOKE_SPONSORSHIP_SUCCESS, REVOKE_SPONSORSHIP_DOES_NOT_EXIST, REVOKE_SPONSORSHIP_NOT_SPONSOR, REVOKE_SPONSORSHIP_LOW_RESERVE, REVOKE_SPONSORSHIP_ONLY_TRANSFERABLE, REVOKE_SPONSORSHIP_MALFORMED: +func (u SCEnvMetaEntry) XdrValid() bool { + switch u.Kind { + case SC_ENV_META_KIND_INTERFACE_VERSION: return true } return false } -func (u *RevokeSponsorshipResult) XdrUnionTag() XdrNum32 { - return XDR_RevokeSponsorshipResultCode(&u.Code) +func (u *SCEnvMetaEntry) XdrUnionTag() XdrNum32 { + return XDR_SCEnvMetaKind(&u.Kind) } -func (u *RevokeSponsorshipResult) XdrUnionTagName() string { - return "Code" +func (u *SCEnvMetaEntry) XdrUnionTagName() string { + return "Kind" } -func (u *RevokeSponsorshipResult) XdrUnionBody() XdrType { - switch u.Code { - case REVOKE_SPONSORSHIP_SUCCESS: - return nil - case REVOKE_SPONSORSHIP_DOES_NOT_EXIST, REVOKE_SPONSORSHIP_NOT_SPONSOR, REVOKE_SPONSORSHIP_LOW_RESERVE, REVOKE_SPONSORSHIP_ONLY_TRANSFERABLE, REVOKE_SPONSORSHIP_MALFORMED: - return nil +func (u *SCEnvMetaEntry) XdrUnionBody() XdrType { + switch u.Kind { + case SC_ENV_META_KIND_INTERFACE_VERSION: + return XDR_Uint64(u.InterfaceVersion()) } return nil } -func (u *RevokeSponsorshipResult) XdrUnionBodyName() string { - switch u.Code { - case REVOKE_SPONSORSHIP_SUCCESS: - return "" - case REVOKE_SPONSORSHIP_DOES_NOT_EXIST, REVOKE_SPONSORSHIP_NOT_SPONSOR, REVOKE_SPONSORSHIP_LOW_RESERVE, REVOKE_SPONSORSHIP_ONLY_TRANSFERABLE, REVOKE_SPONSORSHIP_MALFORMED: - return "" +func (u *SCEnvMetaEntry) XdrUnionBodyName() string { + switch u.Kind { + case SC_ENV_META_KIND_INTERFACE_VERSION: + return "InterfaceVersion" } return "" } -type XdrType_RevokeSponsorshipResult = *RevokeSponsorshipResult +type XdrType_SCEnvMetaEntry = *SCEnvMetaEntry -func (v *RevokeSponsorshipResult) XdrPointer() interface{} { return v } -func (RevokeSponsorshipResult) XdrTypeName() string { return "RevokeSponsorshipResult" } -func (v RevokeSponsorshipResult) XdrValue() interface{} { return v } -func (v *RevokeSponsorshipResult) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -func (u *RevokeSponsorshipResult) XdrRecurse(x XDR, name string) { +func (v *SCEnvMetaEntry) XdrPointer() interface{} { return v } +func (SCEnvMetaEntry) XdrTypeName() string { return "SCEnvMetaEntry" } +func (v SCEnvMetaEntry) XdrValue() interface{} { return v } +func (v *SCEnvMetaEntry) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (u *SCEnvMetaEntry) XdrRecurse(x XDR, name string) { if name != "" { name = x.Sprintf("%s.", name) } - XDR_RevokeSponsorshipResultCode(&u.Code).XdrMarshal(x, x.Sprintf("%scode", name)) - switch u.Code { - case REVOKE_SPONSORSHIP_SUCCESS: - return - case REVOKE_SPONSORSHIP_DOES_NOT_EXIST, REVOKE_SPONSORSHIP_NOT_SPONSOR, REVOKE_SPONSORSHIP_LOW_RESERVE, REVOKE_SPONSORSHIP_ONLY_TRANSFERABLE, REVOKE_SPONSORSHIP_MALFORMED: + XDR_SCEnvMetaKind(&u.Kind).XdrMarshal(x, x.Sprintf("%skind", name)) + switch u.Kind { + case SC_ENV_META_KIND_INTERFACE_VERSION: + x.Marshal(x.Sprintf("%sinterfaceVersion", name), XDR_Uint64(u.InterfaceVersion())) return } - XdrPanic("invalid Code (%v) in RevokeSponsorshipResult", u.Code) + XdrPanic("invalid Kind (%v) in SCEnvMetaEntry", u.Kind) +} +func XDR_SCEnvMetaEntry(v *SCEnvMetaEntry) *SCEnvMetaEntry { return v } + +type XdrType_SCMetaV0 = *SCMetaV0 + +func (v *SCMetaV0) XdrPointer() interface{} { return v } +func (SCMetaV0) XdrTypeName() string { return "SCMetaV0" } +func (v SCMetaV0) XdrValue() interface{} { return v } +func (v *SCMetaV0) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v *SCMetaV0) XdrRecurse(x XDR, name string) { + if name != "" { + name = x.Sprintf("%s.", name) + } + x.Marshal(x.Sprintf("%skey", name), XdrString{&v.Key, 0xffffffff}) + x.Marshal(x.Sprintf("%sval", name), XdrString{&v.Val, 0xffffffff}) } -func XDR_RevokeSponsorshipResult(v *RevokeSponsorshipResult) *RevokeSponsorshipResult { return v } +func XDR_SCMetaV0(v *SCMetaV0) *SCMetaV0 { return v } -var _XdrNames_ClawbackResultCode = map[int32]string{ - int32(CLAWBACK_SUCCESS): "CLAWBACK_SUCCESS", - int32(CLAWBACK_MALFORMED): "CLAWBACK_MALFORMED", - int32(CLAWBACK_NOT_CLAWBACK_ENABLED): "CLAWBACK_NOT_CLAWBACK_ENABLED", - int32(CLAWBACK_NO_TRUST): "CLAWBACK_NO_TRUST", - int32(CLAWBACK_UNDERFUNDED): "CLAWBACK_UNDERFUNDED", +var _XdrNames_SCMetaKind = map[int32]string{ + int32(SC_META_V0): "SC_META_V0", } -var _XdrValues_ClawbackResultCode = map[string]int32{ - "CLAWBACK_SUCCESS": int32(CLAWBACK_SUCCESS), - "CLAWBACK_MALFORMED": int32(CLAWBACK_MALFORMED), - "CLAWBACK_NOT_CLAWBACK_ENABLED": int32(CLAWBACK_NOT_CLAWBACK_ENABLED), - "CLAWBACK_NO_TRUST": int32(CLAWBACK_NO_TRUST), - "CLAWBACK_UNDERFUNDED": int32(CLAWBACK_UNDERFUNDED), +var _XdrValues_SCMetaKind = map[string]int32{ + "SC_META_V0": int32(SC_META_V0), } -func (ClawbackResultCode) XdrEnumNames() map[int32]string { - return _XdrNames_ClawbackResultCode +func (SCMetaKind) XdrEnumNames() map[int32]string { + return _XdrNames_SCMetaKind } -func (v ClawbackResultCode) String() string { - if s, ok := _XdrNames_ClawbackResultCode[int32(v)]; ok { +func (v SCMetaKind) String() string { + if s, ok := _XdrNames_SCMetaKind[int32(v)]; ok { return s } - return fmt.Sprintf("ClawbackResultCode#%d", v) + return fmt.Sprintf("SCMetaKind#%d", v) } -func (v *ClawbackResultCode) Scan(ss fmt.ScanState, _ rune) error { +func (v *SCMetaKind) Scan(ss fmt.ScanState, _ rune) error { if tok, err := ss.Token(true, XdrSymChar); err != nil { return err } else { stok := string(tok) - if val, ok := _XdrValues_ClawbackResultCode[stok]; ok { - *v = ClawbackResultCode(val) + if val, ok := _XdrValues_SCMetaKind[stok]; ok { + *v = SCMetaKind(val) return nil - } else if stok == "ClawbackResultCode" { + } else if stok == "SCMetaKind" { if n, err := fmt.Fscanf(ss, "#%d", (*int32)(v)); n == 1 && err == nil { return nil } } - return XdrError(fmt.Sprintf("%s is not a valid ClawbackResultCode.", stok)) + return XdrError(fmt.Sprintf("%s is not a valid SCMetaKind.", stok)) } } -func (v ClawbackResultCode) GetU32() uint32 { return uint32(v) } -func (v *ClawbackResultCode) SetU32(n uint32) { *v = ClawbackResultCode(n) } -func (v *ClawbackResultCode) XdrPointer() interface{} { return v } -func (ClawbackResultCode) XdrTypeName() string { return "ClawbackResultCode" } -func (v ClawbackResultCode) XdrValue() interface{} { return v } -func (v *ClawbackResultCode) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } - -type XdrType_ClawbackResultCode = *ClawbackResultCode +func (v SCMetaKind) GetU32() uint32 { return uint32(v) } +func (v *SCMetaKind) SetU32(n uint32) { *v = SCMetaKind(n) } +func (v *SCMetaKind) XdrPointer() interface{} { return v } +func (SCMetaKind) XdrTypeName() string { return "SCMetaKind" } +func (v SCMetaKind) XdrValue() interface{} { return v } +func (v *SCMetaKind) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -func XDR_ClawbackResultCode(v *ClawbackResultCode) *ClawbackResultCode { return v } +type XdrType_SCMetaKind = *SCMetaKind -var _XdrComments_ClawbackResultCode = map[int32]string{ - int32(CLAWBACK_SUCCESS): "codes considered as \"success\" for the operation", - int32(CLAWBACK_MALFORMED): "codes considered as \"failure\" for the operation", -} +func XDR_SCMetaKind(v *SCMetaKind) *SCMetaKind { return v } -func (e ClawbackResultCode) XdrEnumComments() map[int32]string { - return _XdrComments_ClawbackResultCode +var _XdrTags_SCMetaEntry = map[int32]bool{ + XdrToI32(SC_META_V0): true, } -var _XdrTags_ClawbackResult = map[int32]bool{ - XdrToI32(CLAWBACK_SUCCESS): true, - XdrToI32(CLAWBACK_MALFORMED): true, - XdrToI32(CLAWBACK_NOT_CLAWBACK_ENABLED): true, - XdrToI32(CLAWBACK_NO_TRUST): true, - XdrToI32(CLAWBACK_UNDERFUNDED): true, +func (_ SCMetaEntry) XdrValidTags() map[int32]bool { + return _XdrTags_SCMetaEntry } - -func (_ ClawbackResult) XdrValidTags() map[int32]bool { - return _XdrTags_ClawbackResult +func (u *SCMetaEntry) V0() *SCMetaV0 { + switch u.Kind { + case SC_META_V0: + if v, ok := u._u.(*SCMetaV0); ok { + return v + } else { + var zero SCMetaV0 + u._u = &zero + return &zero + } + default: + XdrPanic("SCMetaEntry.V0 accessed when Kind == %v", u.Kind) + return nil + } } -func (u ClawbackResult) XdrValid() bool { - switch u.Code { - case CLAWBACK_SUCCESS, CLAWBACK_MALFORMED, CLAWBACK_NOT_CLAWBACK_ENABLED, CLAWBACK_NO_TRUST, CLAWBACK_UNDERFUNDED: +func (u SCMetaEntry) XdrValid() bool { + switch u.Kind { + case SC_META_V0: return true } return false } -func (u *ClawbackResult) XdrUnionTag() XdrNum32 { - return XDR_ClawbackResultCode(&u.Code) +func (u *SCMetaEntry) XdrUnionTag() XdrNum32 { + return XDR_SCMetaKind(&u.Kind) } -func (u *ClawbackResult) XdrUnionTagName() string { - return "Code" +func (u *SCMetaEntry) XdrUnionTagName() string { + return "Kind" } -func (u *ClawbackResult) XdrUnionBody() XdrType { - switch u.Code { - case CLAWBACK_SUCCESS: - return nil - case CLAWBACK_MALFORMED, CLAWBACK_NOT_CLAWBACK_ENABLED, CLAWBACK_NO_TRUST, CLAWBACK_UNDERFUNDED: - return nil +func (u *SCMetaEntry) XdrUnionBody() XdrType { + switch u.Kind { + case SC_META_V0: + return XDR_SCMetaV0(u.V0()) } return nil } -func (u *ClawbackResult) XdrUnionBodyName() string { - switch u.Code { - case CLAWBACK_SUCCESS: - return "" - case CLAWBACK_MALFORMED, CLAWBACK_NOT_CLAWBACK_ENABLED, CLAWBACK_NO_TRUST, CLAWBACK_UNDERFUNDED: - return "" +func (u *SCMetaEntry) XdrUnionBodyName() string { + switch u.Kind { + case SC_META_V0: + return "V0" } return "" } -type XdrType_ClawbackResult = *ClawbackResult +type XdrType_SCMetaEntry = *SCMetaEntry -func (v *ClawbackResult) XdrPointer() interface{} { return v } -func (ClawbackResult) XdrTypeName() string { return "ClawbackResult" } -func (v ClawbackResult) XdrValue() interface{} { return v } -func (v *ClawbackResult) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -func (u *ClawbackResult) XdrRecurse(x XDR, name string) { +func (v *SCMetaEntry) XdrPointer() interface{} { return v } +func (SCMetaEntry) XdrTypeName() string { return "SCMetaEntry" } +func (v SCMetaEntry) XdrValue() interface{} { return v } +func (v *SCMetaEntry) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (u *SCMetaEntry) XdrRecurse(x XDR, name string) { if name != "" { name = x.Sprintf("%s.", name) } - XDR_ClawbackResultCode(&u.Code).XdrMarshal(x, x.Sprintf("%scode", name)) - switch u.Code { - case CLAWBACK_SUCCESS: - return - case CLAWBACK_MALFORMED, CLAWBACK_NOT_CLAWBACK_ENABLED, CLAWBACK_NO_TRUST, CLAWBACK_UNDERFUNDED: - return - } - XdrPanic("invalid Code (%v) in ClawbackResult", u.Code) -} -func XDR_ClawbackResult(v *ClawbackResult) *ClawbackResult { return v } - -var _XdrNames_ClawbackClaimableBalanceResultCode = map[int32]string{ - int32(CLAWBACK_CLAIMABLE_BALANCE_SUCCESS): "CLAWBACK_CLAIMABLE_BALANCE_SUCCESS", - int32(CLAWBACK_CLAIMABLE_BALANCE_DOES_NOT_EXIST): "CLAWBACK_CLAIMABLE_BALANCE_DOES_NOT_EXIST", - int32(CLAWBACK_CLAIMABLE_BALANCE_NOT_ISSUER): "CLAWBACK_CLAIMABLE_BALANCE_NOT_ISSUER", - int32(CLAWBACK_CLAIMABLE_BALANCE_NOT_CLAWBACK_ENABLED): "CLAWBACK_CLAIMABLE_BALANCE_NOT_CLAWBACK_ENABLED", -} -var _XdrValues_ClawbackClaimableBalanceResultCode = map[string]int32{ - "CLAWBACK_CLAIMABLE_BALANCE_SUCCESS": int32(CLAWBACK_CLAIMABLE_BALANCE_SUCCESS), - "CLAWBACK_CLAIMABLE_BALANCE_DOES_NOT_EXIST": int32(CLAWBACK_CLAIMABLE_BALANCE_DOES_NOT_EXIST), - "CLAWBACK_CLAIMABLE_BALANCE_NOT_ISSUER": int32(CLAWBACK_CLAIMABLE_BALANCE_NOT_ISSUER), - "CLAWBACK_CLAIMABLE_BALANCE_NOT_CLAWBACK_ENABLED": int32(CLAWBACK_CLAIMABLE_BALANCE_NOT_CLAWBACK_ENABLED), -} - -func (ClawbackClaimableBalanceResultCode) XdrEnumNames() map[int32]string { - return _XdrNames_ClawbackClaimableBalanceResultCode -} -func (v ClawbackClaimableBalanceResultCode) String() string { - if s, ok := _XdrNames_ClawbackClaimableBalanceResultCode[int32(v)]; ok { + XDR_SCMetaKind(&u.Kind).XdrMarshal(x, x.Sprintf("%skind", name)) + switch u.Kind { + case SC_META_V0: + x.Marshal(x.Sprintf("%sv0", name), XDR_SCMetaV0(u.V0())) + return + } + XdrPanic("invalid Kind (%v) in SCMetaEntry", u.Kind) +} +func XDR_SCMetaEntry(v *SCMetaEntry) *SCMetaEntry { return v } + +var _XdrNames_SCSpecType = map[int32]string{ + int32(SC_SPEC_TYPE_VAL): "SC_SPEC_TYPE_VAL", + int32(SC_SPEC_TYPE_BOOL): "SC_SPEC_TYPE_BOOL", + int32(SC_SPEC_TYPE_VOID): "SC_SPEC_TYPE_VOID", + int32(SC_SPEC_TYPE_ERROR): "SC_SPEC_TYPE_ERROR", + int32(SC_SPEC_TYPE_U32): "SC_SPEC_TYPE_U32", + int32(SC_SPEC_TYPE_I32): "SC_SPEC_TYPE_I32", + int32(SC_SPEC_TYPE_U64): "SC_SPEC_TYPE_U64", + int32(SC_SPEC_TYPE_I64): "SC_SPEC_TYPE_I64", + int32(SC_SPEC_TYPE_TIMEPOINT): "SC_SPEC_TYPE_TIMEPOINT", + int32(SC_SPEC_TYPE_DURATION): "SC_SPEC_TYPE_DURATION", + int32(SC_SPEC_TYPE_U128): "SC_SPEC_TYPE_U128", + int32(SC_SPEC_TYPE_I128): "SC_SPEC_TYPE_I128", + int32(SC_SPEC_TYPE_U256): "SC_SPEC_TYPE_U256", + int32(SC_SPEC_TYPE_I256): "SC_SPEC_TYPE_I256", + int32(SC_SPEC_TYPE_BYTES): "SC_SPEC_TYPE_BYTES", + int32(SC_SPEC_TYPE_STRING): "SC_SPEC_TYPE_STRING", + int32(SC_SPEC_TYPE_SYMBOL): "SC_SPEC_TYPE_SYMBOL", + int32(SC_SPEC_TYPE_ADDRESS): "SC_SPEC_TYPE_ADDRESS", + int32(SC_SPEC_TYPE_OPTION): "SC_SPEC_TYPE_OPTION", + int32(SC_SPEC_TYPE_RESULT): "SC_SPEC_TYPE_RESULT", + int32(SC_SPEC_TYPE_VEC): "SC_SPEC_TYPE_VEC", + int32(SC_SPEC_TYPE_MAP): "SC_SPEC_TYPE_MAP", + int32(SC_SPEC_TYPE_TUPLE): "SC_SPEC_TYPE_TUPLE", + int32(SC_SPEC_TYPE_BYTES_N): "SC_SPEC_TYPE_BYTES_N", + int32(SC_SPEC_TYPE_UDT): "SC_SPEC_TYPE_UDT", +} +var _XdrValues_SCSpecType = map[string]int32{ + "SC_SPEC_TYPE_VAL": int32(SC_SPEC_TYPE_VAL), + "SC_SPEC_TYPE_BOOL": int32(SC_SPEC_TYPE_BOOL), + "SC_SPEC_TYPE_VOID": int32(SC_SPEC_TYPE_VOID), + "SC_SPEC_TYPE_ERROR": int32(SC_SPEC_TYPE_ERROR), + "SC_SPEC_TYPE_U32": int32(SC_SPEC_TYPE_U32), + "SC_SPEC_TYPE_I32": int32(SC_SPEC_TYPE_I32), + "SC_SPEC_TYPE_U64": int32(SC_SPEC_TYPE_U64), + "SC_SPEC_TYPE_I64": int32(SC_SPEC_TYPE_I64), + "SC_SPEC_TYPE_TIMEPOINT": int32(SC_SPEC_TYPE_TIMEPOINT), + "SC_SPEC_TYPE_DURATION": int32(SC_SPEC_TYPE_DURATION), + "SC_SPEC_TYPE_U128": int32(SC_SPEC_TYPE_U128), + "SC_SPEC_TYPE_I128": int32(SC_SPEC_TYPE_I128), + "SC_SPEC_TYPE_U256": int32(SC_SPEC_TYPE_U256), + "SC_SPEC_TYPE_I256": int32(SC_SPEC_TYPE_I256), + "SC_SPEC_TYPE_BYTES": int32(SC_SPEC_TYPE_BYTES), + "SC_SPEC_TYPE_STRING": int32(SC_SPEC_TYPE_STRING), + "SC_SPEC_TYPE_SYMBOL": int32(SC_SPEC_TYPE_SYMBOL), + "SC_SPEC_TYPE_ADDRESS": int32(SC_SPEC_TYPE_ADDRESS), + "SC_SPEC_TYPE_OPTION": int32(SC_SPEC_TYPE_OPTION), + "SC_SPEC_TYPE_RESULT": int32(SC_SPEC_TYPE_RESULT), + "SC_SPEC_TYPE_VEC": int32(SC_SPEC_TYPE_VEC), + "SC_SPEC_TYPE_MAP": int32(SC_SPEC_TYPE_MAP), + "SC_SPEC_TYPE_TUPLE": int32(SC_SPEC_TYPE_TUPLE), + "SC_SPEC_TYPE_BYTES_N": int32(SC_SPEC_TYPE_BYTES_N), + "SC_SPEC_TYPE_UDT": int32(SC_SPEC_TYPE_UDT), +} + +func (SCSpecType) XdrEnumNames() map[int32]string { + return _XdrNames_SCSpecType +} +func (v SCSpecType) String() string { + if s, ok := _XdrNames_SCSpecType[int32(v)]; ok { return s } - return fmt.Sprintf("ClawbackClaimableBalanceResultCode#%d", v) + return fmt.Sprintf("SCSpecType#%d", v) } -func (v *ClawbackClaimableBalanceResultCode) Scan(ss fmt.ScanState, _ rune) error { +func (v *SCSpecType) Scan(ss fmt.ScanState, _ rune) error { if tok, err := ss.Token(true, XdrSymChar); err != nil { return err } else { stok := string(tok) - if val, ok := _XdrValues_ClawbackClaimableBalanceResultCode[stok]; ok { - *v = ClawbackClaimableBalanceResultCode(val) + if val, ok := _XdrValues_SCSpecType[stok]; ok { + *v = SCSpecType(val) return nil - } else if stok == "ClawbackClaimableBalanceResultCode" { + } else if stok == "SCSpecType" { if n, err := fmt.Fscanf(ss, "#%d", (*int32)(v)); n == 1 && err == nil { return nil } } - return XdrError(fmt.Sprintf("%s is not a valid ClawbackClaimableBalanceResultCode.", stok)) + return XdrError(fmt.Sprintf("%s is not a valid SCSpecType.", stok)) } } -func (v ClawbackClaimableBalanceResultCode) GetU32() uint32 { return uint32(v) } -func (v *ClawbackClaimableBalanceResultCode) SetU32(n uint32) { - *v = ClawbackClaimableBalanceResultCode(n) +func (v SCSpecType) GetU32() uint32 { return uint32(v) } +func (v *SCSpecType) SetU32(n uint32) { *v = SCSpecType(n) } +func (v *SCSpecType) XdrPointer() interface{} { return v } +func (SCSpecType) XdrTypeName() string { return "SCSpecType" } +func (v SCSpecType) XdrValue() interface{} { return v } +func (v *SCSpecType) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } + +type XdrType_SCSpecType = *SCSpecType + +func XDR_SCSpecType(v *SCSpecType) *SCSpecType { return v } + +var _XdrComments_SCSpecType = map[int32]string{ + int32(SC_SPEC_TYPE_BOOL): "Types with no parameters.", + int32(SC_SPEC_TYPE_OPTION): "Types with parameters.", + int32(SC_SPEC_TYPE_UDT): "User defined types.", } -func (v *ClawbackClaimableBalanceResultCode) XdrPointer() interface{} { return v } -func (ClawbackClaimableBalanceResultCode) XdrTypeName() string { - return "ClawbackClaimableBalanceResultCode" + +func (e SCSpecType) XdrEnumComments() map[int32]string { + return _XdrComments_SCSpecType } -func (v ClawbackClaimableBalanceResultCode) XdrValue() interface{} { return v } -func (v *ClawbackClaimableBalanceResultCode) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -type XdrType_ClawbackClaimableBalanceResultCode = *ClawbackClaimableBalanceResultCode +type XdrType_SCSpecTypeOption = *SCSpecTypeOption -func XDR_ClawbackClaimableBalanceResultCode(v *ClawbackClaimableBalanceResultCode) *ClawbackClaimableBalanceResultCode { - return v +func (v *SCSpecTypeOption) XdrPointer() interface{} { return v } +func (SCSpecTypeOption) XdrTypeName() string { return "SCSpecTypeOption" } +func (v SCSpecTypeOption) XdrValue() interface{} { return v } +func (v *SCSpecTypeOption) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v *SCSpecTypeOption) XdrRecurse(x XDR, name string) { + if name != "" { + name = x.Sprintf("%s.", name) + } + x.Marshal(x.Sprintf("%svalueType", name), XDR_SCSpecTypeDef(&v.ValueType)) } +func XDR_SCSpecTypeOption(v *SCSpecTypeOption) *SCSpecTypeOption { return v } -var _XdrComments_ClawbackClaimableBalanceResultCode = map[int32]string{ - int32(CLAWBACK_CLAIMABLE_BALANCE_SUCCESS): "codes considered as \"success\" for the operation", - int32(CLAWBACK_CLAIMABLE_BALANCE_DOES_NOT_EXIST): "codes considered as \"failure\" for the operation", +type XdrType_SCSpecTypeResult = *SCSpecTypeResult + +func (v *SCSpecTypeResult) XdrPointer() interface{} { return v } +func (SCSpecTypeResult) XdrTypeName() string { return "SCSpecTypeResult" } +func (v SCSpecTypeResult) XdrValue() interface{} { return v } +func (v *SCSpecTypeResult) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v *SCSpecTypeResult) XdrRecurse(x XDR, name string) { + if name != "" { + name = x.Sprintf("%s.", name) + } + x.Marshal(x.Sprintf("%sokType", name), XDR_SCSpecTypeDef(&v.OkType)) + x.Marshal(x.Sprintf("%serrorType", name), XDR_SCSpecTypeDef(&v.ErrorType)) } +func XDR_SCSpecTypeResult(v *SCSpecTypeResult) *SCSpecTypeResult { return v } -func (e ClawbackClaimableBalanceResultCode) XdrEnumComments() map[int32]string { - return _XdrComments_ClawbackClaimableBalanceResultCode +type XdrType_SCSpecTypeVec = *SCSpecTypeVec + +func (v *SCSpecTypeVec) XdrPointer() interface{} { return v } +func (SCSpecTypeVec) XdrTypeName() string { return "SCSpecTypeVec" } +func (v SCSpecTypeVec) XdrValue() interface{} { return v } +func (v *SCSpecTypeVec) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v *SCSpecTypeVec) XdrRecurse(x XDR, name string) { + if name != "" { + name = x.Sprintf("%s.", name) + } + x.Marshal(x.Sprintf("%selementType", name), XDR_SCSpecTypeDef(&v.ElementType)) +} +func XDR_SCSpecTypeVec(v *SCSpecTypeVec) *SCSpecTypeVec { return v } + +type XdrType_SCSpecTypeMap = *SCSpecTypeMap + +func (v *SCSpecTypeMap) XdrPointer() interface{} { return v } +func (SCSpecTypeMap) XdrTypeName() string { return "SCSpecTypeMap" } +func (v SCSpecTypeMap) XdrValue() interface{} { return v } +func (v *SCSpecTypeMap) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v *SCSpecTypeMap) XdrRecurse(x XDR, name string) { + if name != "" { + name = x.Sprintf("%s.", name) + } + x.Marshal(x.Sprintf("%skeyType", name), XDR_SCSpecTypeDef(&v.KeyType)) + x.Marshal(x.Sprintf("%svalueType", name), XDR_SCSpecTypeDef(&v.ValueType)) +} +func XDR_SCSpecTypeMap(v *SCSpecTypeMap) *SCSpecTypeMap { return v } + +type _XdrVec_12_SCSpecTypeDef []SCSpecTypeDef + +func (_XdrVec_12_SCSpecTypeDef) XdrBound() uint32 { + const bound uint32 = 12 // Force error if not const or doesn't fit + return bound +} +func (_XdrVec_12_SCSpecTypeDef) XdrCheckLen(length uint32) { + if length > uint32(12) { + XdrPanic("_XdrVec_12_SCSpecTypeDef length %d exceeds bound 12", length) + } else if int(length) < 0 { + XdrPanic("_XdrVec_12_SCSpecTypeDef length %d exceeds max int", length) + } +} +func (v _XdrVec_12_SCSpecTypeDef) GetVecLen() uint32 { return uint32(len(v)) } +func (v *_XdrVec_12_SCSpecTypeDef) SetVecLen(length uint32) { + v.XdrCheckLen(length) + if int(length) <= cap(*v) { + if int(length) != len(*v) { + *v = (*v)[:int(length)] + } + return + } + newcap := 2 * cap(*v) + if newcap < int(length) { // also catches overflow where 2*cap < 0 + newcap = int(length) + } else if bound := uint(12); uint(newcap) > bound { + if int(bound) < 0 { + bound = ^uint(0) >> 1 + } + newcap = int(bound) + } + nv := make([]SCSpecTypeDef, int(length), newcap) + copy(nv, *v) + *v = nv +} +func (v *_XdrVec_12_SCSpecTypeDef) XdrMarshalN(x XDR, name string, n uint32) { + v.XdrCheckLen(n) + for i := 0; i < int(n); i++ { + if i >= len(*v) { + v.SetVecLen(uint32(i + 1)) + } + XDR_SCSpecTypeDef(&(*v)[i]).XdrMarshal(x, x.Sprintf("%s[%d]", name, i)) + } + if int(n) < len(*v) { + *v = (*v)[:int(n)] + } +} +func (v *_XdrVec_12_SCSpecTypeDef) XdrRecurse(x XDR, name string) { + size := XdrSize{Size: uint32(len(*v)), Bound: 12} + x.Marshal(name, &size) + v.XdrMarshalN(x, name, size.Size) +} +func (_XdrVec_12_SCSpecTypeDef) XdrTypeName() string { return "SCSpecTypeDef<>" } +func (v *_XdrVec_12_SCSpecTypeDef) XdrPointer() interface{} { return (*[]SCSpecTypeDef)(v) } +func (v _XdrVec_12_SCSpecTypeDef) XdrValue() interface{} { return ([]SCSpecTypeDef)(v) } +func (v *_XdrVec_12_SCSpecTypeDef) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } + +type XdrType_SCSpecTypeTuple = *SCSpecTypeTuple + +func (v *SCSpecTypeTuple) XdrPointer() interface{} { return v } +func (SCSpecTypeTuple) XdrTypeName() string { return "SCSpecTypeTuple" } +func (v SCSpecTypeTuple) XdrValue() interface{} { return v } +func (v *SCSpecTypeTuple) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v *SCSpecTypeTuple) XdrRecurse(x XDR, name string) { + if name != "" { + name = x.Sprintf("%s.", name) + } + x.Marshal(x.Sprintf("%svalueTypes", name), (*_XdrVec_12_SCSpecTypeDef)(&v.ValueTypes)) +} +func XDR_SCSpecTypeTuple(v *SCSpecTypeTuple) *SCSpecTypeTuple { return v } + +type XdrType_SCSpecTypeBytesN = *SCSpecTypeBytesN + +func (v *SCSpecTypeBytesN) XdrPointer() interface{} { return v } +func (SCSpecTypeBytesN) XdrTypeName() string { return "SCSpecTypeBytesN" } +func (v SCSpecTypeBytesN) XdrValue() interface{} { return v } +func (v *SCSpecTypeBytesN) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v *SCSpecTypeBytesN) XdrRecurse(x XDR, name string) { + if name != "" { + name = x.Sprintf("%s.", name) + } + x.Marshal(x.Sprintf("%sn", name), XDR_Uint32(&v.N)) +} +func XDR_SCSpecTypeBytesN(v *SCSpecTypeBytesN) *SCSpecTypeBytesN { return v } + +type XdrType_SCSpecTypeUDT = *SCSpecTypeUDT + +func (v *SCSpecTypeUDT) XdrPointer() interface{} { return v } +func (SCSpecTypeUDT) XdrTypeName() string { return "SCSpecTypeUDT" } +func (v SCSpecTypeUDT) XdrValue() interface{} { return v } +func (v *SCSpecTypeUDT) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v *SCSpecTypeUDT) XdrRecurse(x XDR, name string) { + if name != "" { + name = x.Sprintf("%s.", name) + } + x.Marshal(x.Sprintf("%sname", name), XdrString{&v.Name, 60}) +} +func XDR_SCSpecTypeUDT(v *SCSpecTypeUDT) *SCSpecTypeUDT { return v } + +var _XdrTags_SCSpecTypeDef = map[int32]bool{ + XdrToI32(SC_SPEC_TYPE_VAL): true, + XdrToI32(SC_SPEC_TYPE_BOOL): true, + XdrToI32(SC_SPEC_TYPE_VOID): true, + XdrToI32(SC_SPEC_TYPE_ERROR): true, + XdrToI32(SC_SPEC_TYPE_U32): true, + XdrToI32(SC_SPEC_TYPE_I32): true, + XdrToI32(SC_SPEC_TYPE_U64): true, + XdrToI32(SC_SPEC_TYPE_I64): true, + XdrToI32(SC_SPEC_TYPE_TIMEPOINT): true, + XdrToI32(SC_SPEC_TYPE_DURATION): true, + XdrToI32(SC_SPEC_TYPE_U128): true, + XdrToI32(SC_SPEC_TYPE_I128): true, + XdrToI32(SC_SPEC_TYPE_U256): true, + XdrToI32(SC_SPEC_TYPE_I256): true, + XdrToI32(SC_SPEC_TYPE_BYTES): true, + XdrToI32(SC_SPEC_TYPE_STRING): true, + XdrToI32(SC_SPEC_TYPE_SYMBOL): true, + XdrToI32(SC_SPEC_TYPE_ADDRESS): true, + XdrToI32(SC_SPEC_TYPE_OPTION): true, + XdrToI32(SC_SPEC_TYPE_RESULT): true, + XdrToI32(SC_SPEC_TYPE_VEC): true, + XdrToI32(SC_SPEC_TYPE_MAP): true, + XdrToI32(SC_SPEC_TYPE_TUPLE): true, + XdrToI32(SC_SPEC_TYPE_BYTES_N): true, + XdrToI32(SC_SPEC_TYPE_UDT): true, +} + +func (_ SCSpecTypeDef) XdrValidTags() map[int32]bool { + return _XdrTags_SCSpecTypeDef +} +func (u *SCSpecTypeDef) Option() *SCSpecTypeOption { + switch u.Type { + case SC_SPEC_TYPE_OPTION: + if v, ok := u._u.(*SCSpecTypeOption); ok { + return v + } else { + var zero SCSpecTypeOption + u._u = &zero + return &zero + } + default: + XdrPanic("SCSpecTypeDef.Option accessed when Type == %v", u.Type) + return nil + } +} +func (u *SCSpecTypeDef) Result() *SCSpecTypeResult { + switch u.Type { + case SC_SPEC_TYPE_RESULT: + if v, ok := u._u.(*SCSpecTypeResult); ok { + return v + } else { + var zero SCSpecTypeResult + u._u = &zero + return &zero + } + default: + XdrPanic("SCSpecTypeDef.Result accessed when Type == %v", u.Type) + return nil + } +} +func (u *SCSpecTypeDef) Vec() *SCSpecTypeVec { + switch u.Type { + case SC_SPEC_TYPE_VEC: + if v, ok := u._u.(*SCSpecTypeVec); ok { + return v + } else { + var zero SCSpecTypeVec + u._u = &zero + return &zero + } + default: + XdrPanic("SCSpecTypeDef.Vec accessed when Type == %v", u.Type) + return nil + } +} +func (u *SCSpecTypeDef) Map() *SCSpecTypeMap { + switch u.Type { + case SC_SPEC_TYPE_MAP: + if v, ok := u._u.(*SCSpecTypeMap); ok { + return v + } else { + var zero SCSpecTypeMap + u._u = &zero + return &zero + } + default: + XdrPanic("SCSpecTypeDef.Map accessed when Type == %v", u.Type) + return nil + } +} +func (u *SCSpecTypeDef) Tuple() *SCSpecTypeTuple { + switch u.Type { + case SC_SPEC_TYPE_TUPLE: + if v, ok := u._u.(*SCSpecTypeTuple); ok { + return v + } else { + var zero SCSpecTypeTuple + u._u = &zero + return &zero + } + default: + XdrPanic("SCSpecTypeDef.Tuple accessed when Type == %v", u.Type) + return nil + } } - -var _XdrTags_ClawbackClaimableBalanceResult = map[int32]bool{ - XdrToI32(CLAWBACK_CLAIMABLE_BALANCE_SUCCESS): true, - XdrToI32(CLAWBACK_CLAIMABLE_BALANCE_DOES_NOT_EXIST): true, - XdrToI32(CLAWBACK_CLAIMABLE_BALANCE_NOT_ISSUER): true, - XdrToI32(CLAWBACK_CLAIMABLE_BALANCE_NOT_CLAWBACK_ENABLED): true, +func (u *SCSpecTypeDef) BytesN() *SCSpecTypeBytesN { + switch u.Type { + case SC_SPEC_TYPE_BYTES_N: + if v, ok := u._u.(*SCSpecTypeBytesN); ok { + return v + } else { + var zero SCSpecTypeBytesN + u._u = &zero + return &zero + } + default: + XdrPanic("SCSpecTypeDef.BytesN accessed when Type == %v", u.Type) + return nil + } } - -func (_ ClawbackClaimableBalanceResult) XdrValidTags() map[int32]bool { - return _XdrTags_ClawbackClaimableBalanceResult +func (u *SCSpecTypeDef) Udt() *SCSpecTypeUDT { + switch u.Type { + case SC_SPEC_TYPE_UDT: + if v, ok := u._u.(*SCSpecTypeUDT); ok { + return v + } else { + var zero SCSpecTypeUDT + u._u = &zero + return &zero + } + default: + XdrPanic("SCSpecTypeDef.Udt accessed when Type == %v", u.Type) + return nil + } } -func (u ClawbackClaimableBalanceResult) XdrValid() bool { - switch u.Code { - case CLAWBACK_CLAIMABLE_BALANCE_SUCCESS, CLAWBACK_CLAIMABLE_BALANCE_DOES_NOT_EXIST, CLAWBACK_CLAIMABLE_BALANCE_NOT_ISSUER, CLAWBACK_CLAIMABLE_BALANCE_NOT_CLAWBACK_ENABLED: +func (u SCSpecTypeDef) XdrValid() bool { + switch u.Type { + case SC_SPEC_TYPE_VAL, SC_SPEC_TYPE_BOOL, SC_SPEC_TYPE_VOID, SC_SPEC_TYPE_ERROR, SC_SPEC_TYPE_U32, SC_SPEC_TYPE_I32, SC_SPEC_TYPE_U64, SC_SPEC_TYPE_I64, SC_SPEC_TYPE_TIMEPOINT, SC_SPEC_TYPE_DURATION, SC_SPEC_TYPE_U128, SC_SPEC_TYPE_I128, SC_SPEC_TYPE_U256, SC_SPEC_TYPE_I256, SC_SPEC_TYPE_BYTES, SC_SPEC_TYPE_STRING, SC_SPEC_TYPE_SYMBOL, SC_SPEC_TYPE_ADDRESS, SC_SPEC_TYPE_OPTION, SC_SPEC_TYPE_RESULT, SC_SPEC_TYPE_VEC, SC_SPEC_TYPE_MAP, SC_SPEC_TYPE_TUPLE, SC_SPEC_TYPE_BYTES_N, SC_SPEC_TYPE_UDT: return true } return false } -func (u *ClawbackClaimableBalanceResult) XdrUnionTag() XdrNum32 { - return XDR_ClawbackClaimableBalanceResultCode(&u.Code) +func (u *SCSpecTypeDef) XdrUnionTag() XdrNum32 { + return XDR_SCSpecType(&u.Type) } -func (u *ClawbackClaimableBalanceResult) XdrUnionTagName() string { - return "Code" +func (u *SCSpecTypeDef) XdrUnionTagName() string { + return "Type" } -func (u *ClawbackClaimableBalanceResult) XdrUnionBody() XdrType { - switch u.Code { - case CLAWBACK_CLAIMABLE_BALANCE_SUCCESS: - return nil - case CLAWBACK_CLAIMABLE_BALANCE_DOES_NOT_EXIST, CLAWBACK_CLAIMABLE_BALANCE_NOT_ISSUER, CLAWBACK_CLAIMABLE_BALANCE_NOT_CLAWBACK_ENABLED: +func (u *SCSpecTypeDef) XdrUnionBody() XdrType { + switch u.Type { + case SC_SPEC_TYPE_VAL, SC_SPEC_TYPE_BOOL, SC_SPEC_TYPE_VOID, SC_SPEC_TYPE_ERROR, SC_SPEC_TYPE_U32, SC_SPEC_TYPE_I32, SC_SPEC_TYPE_U64, SC_SPEC_TYPE_I64, SC_SPEC_TYPE_TIMEPOINT, SC_SPEC_TYPE_DURATION, SC_SPEC_TYPE_U128, SC_SPEC_TYPE_I128, SC_SPEC_TYPE_U256, SC_SPEC_TYPE_I256, SC_SPEC_TYPE_BYTES, SC_SPEC_TYPE_STRING, SC_SPEC_TYPE_SYMBOL, SC_SPEC_TYPE_ADDRESS: return nil + case SC_SPEC_TYPE_OPTION: + return XDR_SCSpecTypeOption(u.Option()) + case SC_SPEC_TYPE_RESULT: + return XDR_SCSpecTypeResult(u.Result()) + case SC_SPEC_TYPE_VEC: + return XDR_SCSpecTypeVec(u.Vec()) + case SC_SPEC_TYPE_MAP: + return XDR_SCSpecTypeMap(u.Map()) + case SC_SPEC_TYPE_TUPLE: + return XDR_SCSpecTypeTuple(u.Tuple()) + case SC_SPEC_TYPE_BYTES_N: + return XDR_SCSpecTypeBytesN(u.BytesN()) + case SC_SPEC_TYPE_UDT: + return XDR_SCSpecTypeUDT(u.Udt()) } return nil } -func (u *ClawbackClaimableBalanceResult) XdrUnionBodyName() string { - switch u.Code { - case CLAWBACK_CLAIMABLE_BALANCE_SUCCESS: - return "" - case CLAWBACK_CLAIMABLE_BALANCE_DOES_NOT_EXIST, CLAWBACK_CLAIMABLE_BALANCE_NOT_ISSUER, CLAWBACK_CLAIMABLE_BALANCE_NOT_CLAWBACK_ENABLED: +func (u *SCSpecTypeDef) XdrUnionBodyName() string { + switch u.Type { + case SC_SPEC_TYPE_VAL, SC_SPEC_TYPE_BOOL, SC_SPEC_TYPE_VOID, SC_SPEC_TYPE_ERROR, SC_SPEC_TYPE_U32, SC_SPEC_TYPE_I32, SC_SPEC_TYPE_U64, SC_SPEC_TYPE_I64, SC_SPEC_TYPE_TIMEPOINT, SC_SPEC_TYPE_DURATION, SC_SPEC_TYPE_U128, SC_SPEC_TYPE_I128, SC_SPEC_TYPE_U256, SC_SPEC_TYPE_I256, SC_SPEC_TYPE_BYTES, SC_SPEC_TYPE_STRING, SC_SPEC_TYPE_SYMBOL, SC_SPEC_TYPE_ADDRESS: return "" + case SC_SPEC_TYPE_OPTION: + return "Option" + case SC_SPEC_TYPE_RESULT: + return "Result" + case SC_SPEC_TYPE_VEC: + return "Vec" + case SC_SPEC_TYPE_MAP: + return "Map" + case SC_SPEC_TYPE_TUPLE: + return "Tuple" + case SC_SPEC_TYPE_BYTES_N: + return "BytesN" + case SC_SPEC_TYPE_UDT: + return "Udt" } return "" } -type XdrType_ClawbackClaimableBalanceResult = *ClawbackClaimableBalanceResult +type XdrType_SCSpecTypeDef = *SCSpecTypeDef -func (v *ClawbackClaimableBalanceResult) XdrPointer() interface{} { return v } -func (ClawbackClaimableBalanceResult) XdrTypeName() string { return "ClawbackClaimableBalanceResult" } -func (v ClawbackClaimableBalanceResult) XdrValue() interface{} { return v } -func (v *ClawbackClaimableBalanceResult) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -func (u *ClawbackClaimableBalanceResult) XdrRecurse(x XDR, name string) { +func (v *SCSpecTypeDef) XdrPointer() interface{} { return v } +func (SCSpecTypeDef) XdrTypeName() string { return "SCSpecTypeDef" } +func (v SCSpecTypeDef) XdrValue() interface{} { return v } +func (v *SCSpecTypeDef) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (u *SCSpecTypeDef) XdrRecurse(x XDR, name string) { if name != "" { name = x.Sprintf("%s.", name) } - XDR_ClawbackClaimableBalanceResultCode(&u.Code).XdrMarshal(x, x.Sprintf("%scode", name)) - switch u.Code { - case CLAWBACK_CLAIMABLE_BALANCE_SUCCESS: + XDR_SCSpecType(&u.Type).XdrMarshal(x, x.Sprintf("%stype", name)) + switch u.Type { + case SC_SPEC_TYPE_VAL, SC_SPEC_TYPE_BOOL, SC_SPEC_TYPE_VOID, SC_SPEC_TYPE_ERROR, SC_SPEC_TYPE_U32, SC_SPEC_TYPE_I32, SC_SPEC_TYPE_U64, SC_SPEC_TYPE_I64, SC_SPEC_TYPE_TIMEPOINT, SC_SPEC_TYPE_DURATION, SC_SPEC_TYPE_U128, SC_SPEC_TYPE_I128, SC_SPEC_TYPE_U256, SC_SPEC_TYPE_I256, SC_SPEC_TYPE_BYTES, SC_SPEC_TYPE_STRING, SC_SPEC_TYPE_SYMBOL, SC_SPEC_TYPE_ADDRESS: return - case CLAWBACK_CLAIMABLE_BALANCE_DOES_NOT_EXIST, CLAWBACK_CLAIMABLE_BALANCE_NOT_ISSUER, CLAWBACK_CLAIMABLE_BALANCE_NOT_CLAWBACK_ENABLED: + case SC_SPEC_TYPE_OPTION: + x.Marshal(x.Sprintf("%soption", name), XDR_SCSpecTypeOption(u.Option())) + return + case SC_SPEC_TYPE_RESULT: + x.Marshal(x.Sprintf("%sresult", name), XDR_SCSpecTypeResult(u.Result())) + return + case SC_SPEC_TYPE_VEC: + x.Marshal(x.Sprintf("%svec", name), XDR_SCSpecTypeVec(u.Vec())) + return + case SC_SPEC_TYPE_MAP: + x.Marshal(x.Sprintf("%smap", name), XDR_SCSpecTypeMap(u.Map())) + return + case SC_SPEC_TYPE_TUPLE: + x.Marshal(x.Sprintf("%stuple", name), XDR_SCSpecTypeTuple(u.Tuple())) + return + case SC_SPEC_TYPE_BYTES_N: + x.Marshal(x.Sprintf("%sbytesN", name), XDR_SCSpecTypeBytesN(u.BytesN())) + return + case SC_SPEC_TYPE_UDT: + x.Marshal(x.Sprintf("%sudt", name), XDR_SCSpecTypeUDT(u.Udt())) return } - XdrPanic("invalid Code (%v) in ClawbackClaimableBalanceResult", u.Code) -} -func XDR_ClawbackClaimableBalanceResult(v *ClawbackClaimableBalanceResult) *ClawbackClaimableBalanceResult { - return v + XdrPanic("invalid Type (%v) in SCSpecTypeDef", u.Type) } +func XDR_SCSpecTypeDef(v *SCSpecTypeDef) *SCSpecTypeDef { return v } -var _XdrNames_SetTrustLineFlagsResultCode = map[int32]string{ - int32(SET_TRUST_LINE_FLAGS_SUCCESS): "SET_TRUST_LINE_FLAGS_SUCCESS", - int32(SET_TRUST_LINE_FLAGS_MALFORMED): "SET_TRUST_LINE_FLAGS_MALFORMED", - int32(SET_TRUST_LINE_FLAGS_NO_TRUST_LINE): "SET_TRUST_LINE_FLAGS_NO_TRUST_LINE", - int32(SET_TRUST_LINE_FLAGS_CANT_REVOKE): "SET_TRUST_LINE_FLAGS_CANT_REVOKE", - int32(SET_TRUST_LINE_FLAGS_INVALID_STATE): "SET_TRUST_LINE_FLAGS_INVALID_STATE", - int32(SET_TRUST_LINE_FLAGS_LOW_RESERVE): "SET_TRUST_LINE_FLAGS_LOW_RESERVE", -} -var _XdrValues_SetTrustLineFlagsResultCode = map[string]int32{ - "SET_TRUST_LINE_FLAGS_SUCCESS": int32(SET_TRUST_LINE_FLAGS_SUCCESS), - "SET_TRUST_LINE_FLAGS_MALFORMED": int32(SET_TRUST_LINE_FLAGS_MALFORMED), - "SET_TRUST_LINE_FLAGS_NO_TRUST_LINE": int32(SET_TRUST_LINE_FLAGS_NO_TRUST_LINE), - "SET_TRUST_LINE_FLAGS_CANT_REVOKE": int32(SET_TRUST_LINE_FLAGS_CANT_REVOKE), - "SET_TRUST_LINE_FLAGS_INVALID_STATE": int32(SET_TRUST_LINE_FLAGS_INVALID_STATE), - "SET_TRUST_LINE_FLAGS_LOW_RESERVE": int32(SET_TRUST_LINE_FLAGS_LOW_RESERVE), +type XdrType_SCSpecUDTStructFieldV0 = *SCSpecUDTStructFieldV0 + +func (v *SCSpecUDTStructFieldV0) XdrPointer() interface{} { return v } +func (SCSpecUDTStructFieldV0) XdrTypeName() string { return "SCSpecUDTStructFieldV0" } +func (v SCSpecUDTStructFieldV0) XdrValue() interface{} { return v } +func (v *SCSpecUDTStructFieldV0) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v *SCSpecUDTStructFieldV0) XdrRecurse(x XDR, name string) { + if name != "" { + name = x.Sprintf("%s.", name) + } + x.Marshal(x.Sprintf("%sdoc", name), XdrString{&v.Doc, SC_SPEC_DOC_LIMIT}) + x.Marshal(x.Sprintf("%sname", name), XdrString{&v.Name, 30}) + x.Marshal(x.Sprintf("%stype", name), XDR_SCSpecTypeDef(&v.Type)) } +func XDR_SCSpecUDTStructFieldV0(v *SCSpecUDTStructFieldV0) *SCSpecUDTStructFieldV0 { return v } -func (SetTrustLineFlagsResultCode) XdrEnumNames() map[int32]string { - return _XdrNames_SetTrustLineFlagsResultCode +type _XdrVec_40_SCSpecUDTStructFieldV0 []SCSpecUDTStructFieldV0 + +func (_XdrVec_40_SCSpecUDTStructFieldV0) XdrBound() uint32 { + const bound uint32 = 40 // Force error if not const or doesn't fit + return bound } -func (v SetTrustLineFlagsResultCode) String() string { - if s, ok := _XdrNames_SetTrustLineFlagsResultCode[int32(v)]; ok { - return s +func (_XdrVec_40_SCSpecUDTStructFieldV0) XdrCheckLen(length uint32) { + if length > uint32(40) { + XdrPanic("_XdrVec_40_SCSpecUDTStructFieldV0 length %d exceeds bound 40", length) + } else if int(length) < 0 { + XdrPanic("_XdrVec_40_SCSpecUDTStructFieldV0 length %d exceeds max int", length) } - return fmt.Sprintf("SetTrustLineFlagsResultCode#%d", v) } -func (v *SetTrustLineFlagsResultCode) Scan(ss fmt.ScanState, _ rune) error { - if tok, err := ss.Token(true, XdrSymChar); err != nil { - return err - } else { - stok := string(tok) - if val, ok := _XdrValues_SetTrustLineFlagsResultCode[stok]; ok { - *v = SetTrustLineFlagsResultCode(val) - return nil - } else if stok == "SetTrustLineFlagsResultCode" { - if n, err := fmt.Fscanf(ss, "#%d", (*int32)(v)); n == 1 && err == nil { - return nil - } +func (v _XdrVec_40_SCSpecUDTStructFieldV0) GetVecLen() uint32 { return uint32(len(v)) } +func (v *_XdrVec_40_SCSpecUDTStructFieldV0) SetVecLen(length uint32) { + v.XdrCheckLen(length) + if int(length) <= cap(*v) { + if int(length) != len(*v) { + *v = (*v)[:int(length)] } - return XdrError(fmt.Sprintf("%s is not a valid SetTrustLineFlagsResultCode.", stok)) + return + } + newcap := 2 * cap(*v) + if newcap < int(length) { // also catches overflow where 2*cap < 0 + newcap = int(length) + } else if bound := uint(40); uint(newcap) > bound { + if int(bound) < 0 { + bound = ^uint(0) >> 1 + } + newcap = int(bound) + } + nv := make([]SCSpecUDTStructFieldV0, int(length), newcap) + copy(nv, *v) + *v = nv +} +func (v *_XdrVec_40_SCSpecUDTStructFieldV0) XdrMarshalN(x XDR, name string, n uint32) { + v.XdrCheckLen(n) + for i := 0; i < int(n); i++ { + if i >= len(*v) { + v.SetVecLen(uint32(i + 1)) + } + XDR_SCSpecUDTStructFieldV0(&(*v)[i]).XdrMarshal(x, x.Sprintf("%s[%d]", name, i)) + } + if int(n) < len(*v) { + *v = (*v)[:int(n)] } } -func (v SetTrustLineFlagsResultCode) GetU32() uint32 { return uint32(v) } -func (v *SetTrustLineFlagsResultCode) SetU32(n uint32) { *v = SetTrustLineFlagsResultCode(n) } -func (v *SetTrustLineFlagsResultCode) XdrPointer() interface{} { return v } -func (SetTrustLineFlagsResultCode) XdrTypeName() string { return "SetTrustLineFlagsResultCode" } -func (v SetTrustLineFlagsResultCode) XdrValue() interface{} { return v } -func (v *SetTrustLineFlagsResultCode) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } - -type XdrType_SetTrustLineFlagsResultCode = *SetTrustLineFlagsResultCode - -func XDR_SetTrustLineFlagsResultCode(v *SetTrustLineFlagsResultCode) *SetTrustLineFlagsResultCode { - return v +func (v *_XdrVec_40_SCSpecUDTStructFieldV0) XdrRecurse(x XDR, name string) { + size := XdrSize{Size: uint32(len(*v)), Bound: 40} + x.Marshal(name, &size) + v.XdrMarshalN(x, name, size.Size) } - -var _XdrComments_SetTrustLineFlagsResultCode = map[int32]string{ - int32(SET_TRUST_LINE_FLAGS_SUCCESS): "codes considered as \"success\" for the operation", - int32(SET_TRUST_LINE_FLAGS_MALFORMED): "codes considered as \"failure\" for the operation", - int32(SET_TRUST_LINE_FLAGS_LOW_RESERVE): "claimable balances can't be created", +func (_XdrVec_40_SCSpecUDTStructFieldV0) XdrTypeName() string { return "SCSpecUDTStructFieldV0<>" } +func (v *_XdrVec_40_SCSpecUDTStructFieldV0) XdrPointer() interface{} { + return (*[]SCSpecUDTStructFieldV0)(v) } - -func (e SetTrustLineFlagsResultCode) XdrEnumComments() map[int32]string { - return _XdrComments_SetTrustLineFlagsResultCode +func (v _XdrVec_40_SCSpecUDTStructFieldV0) XdrValue() interface{} { + return ([]SCSpecUDTStructFieldV0)(v) } +func (v *_XdrVec_40_SCSpecUDTStructFieldV0) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -var _XdrTags_SetTrustLineFlagsResult = map[int32]bool{ - XdrToI32(SET_TRUST_LINE_FLAGS_SUCCESS): true, - XdrToI32(SET_TRUST_LINE_FLAGS_MALFORMED): true, - XdrToI32(SET_TRUST_LINE_FLAGS_NO_TRUST_LINE): true, - XdrToI32(SET_TRUST_LINE_FLAGS_CANT_REVOKE): true, - XdrToI32(SET_TRUST_LINE_FLAGS_INVALID_STATE): true, - XdrToI32(SET_TRUST_LINE_FLAGS_LOW_RESERVE): true, -} +type XdrType_SCSpecUDTStructV0 = *SCSpecUDTStructV0 -func (_ SetTrustLineFlagsResult) XdrValidTags() map[int32]bool { - return _XdrTags_SetTrustLineFlagsResult -} -func (u SetTrustLineFlagsResult) XdrValid() bool { - switch u.Code { - case SET_TRUST_LINE_FLAGS_SUCCESS, SET_TRUST_LINE_FLAGS_MALFORMED, SET_TRUST_LINE_FLAGS_NO_TRUST_LINE, SET_TRUST_LINE_FLAGS_CANT_REVOKE, SET_TRUST_LINE_FLAGS_INVALID_STATE, SET_TRUST_LINE_FLAGS_LOW_RESERVE: - return true - } - return false -} -func (u *SetTrustLineFlagsResult) XdrUnionTag() XdrNum32 { - return XDR_SetTrustLineFlagsResultCode(&u.Code) -} -func (u *SetTrustLineFlagsResult) XdrUnionTagName() string { - return "Code" -} -func (u *SetTrustLineFlagsResult) XdrUnionBody() XdrType { - switch u.Code { - case SET_TRUST_LINE_FLAGS_SUCCESS: - return nil - case SET_TRUST_LINE_FLAGS_MALFORMED, SET_TRUST_LINE_FLAGS_NO_TRUST_LINE, SET_TRUST_LINE_FLAGS_CANT_REVOKE, SET_TRUST_LINE_FLAGS_INVALID_STATE, SET_TRUST_LINE_FLAGS_LOW_RESERVE: - return nil +func (v *SCSpecUDTStructV0) XdrPointer() interface{} { return v } +func (SCSpecUDTStructV0) XdrTypeName() string { return "SCSpecUDTStructV0" } +func (v SCSpecUDTStructV0) XdrValue() interface{} { return v } +func (v *SCSpecUDTStructV0) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v *SCSpecUDTStructV0) XdrRecurse(x XDR, name string) { + if name != "" { + name = x.Sprintf("%s.", name) } - return nil + x.Marshal(x.Sprintf("%sdoc", name), XdrString{&v.Doc, SC_SPEC_DOC_LIMIT}) + x.Marshal(x.Sprintf("%slib", name), XdrString{&v.Lib, 80}) + x.Marshal(x.Sprintf("%sname", name), XdrString{&v.Name, 60}) + x.Marshal(x.Sprintf("%sfields", name), (*_XdrVec_40_SCSpecUDTStructFieldV0)(&v.Fields)) } -func (u *SetTrustLineFlagsResult) XdrUnionBodyName() string { - switch u.Code { - case SET_TRUST_LINE_FLAGS_SUCCESS: - return "" - case SET_TRUST_LINE_FLAGS_MALFORMED, SET_TRUST_LINE_FLAGS_NO_TRUST_LINE, SET_TRUST_LINE_FLAGS_CANT_REVOKE, SET_TRUST_LINE_FLAGS_INVALID_STATE, SET_TRUST_LINE_FLAGS_LOW_RESERVE: - return "" +func XDR_SCSpecUDTStructV0(v *SCSpecUDTStructV0) *SCSpecUDTStructV0 { return v } + +type XdrType_SCSpecUDTUnionCaseVoidV0 = *SCSpecUDTUnionCaseVoidV0 + +func (v *SCSpecUDTUnionCaseVoidV0) XdrPointer() interface{} { return v } +func (SCSpecUDTUnionCaseVoidV0) XdrTypeName() string { return "SCSpecUDTUnionCaseVoidV0" } +func (v SCSpecUDTUnionCaseVoidV0) XdrValue() interface{} { return v } +func (v *SCSpecUDTUnionCaseVoidV0) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v *SCSpecUDTUnionCaseVoidV0) XdrRecurse(x XDR, name string) { + if name != "" { + name = x.Sprintf("%s.", name) } - return "" + x.Marshal(x.Sprintf("%sdoc", name), XdrString{&v.Doc, SC_SPEC_DOC_LIMIT}) + x.Marshal(x.Sprintf("%sname", name), XdrString{&v.Name, 60}) } +func XDR_SCSpecUDTUnionCaseVoidV0(v *SCSpecUDTUnionCaseVoidV0) *SCSpecUDTUnionCaseVoidV0 { return v } -type XdrType_SetTrustLineFlagsResult = *SetTrustLineFlagsResult +type XdrType_SCSpecUDTUnionCaseTupleV0 = *SCSpecUDTUnionCaseTupleV0 -func (v *SetTrustLineFlagsResult) XdrPointer() interface{} { return v } -func (SetTrustLineFlagsResult) XdrTypeName() string { return "SetTrustLineFlagsResult" } -func (v SetTrustLineFlagsResult) XdrValue() interface{} { return v } -func (v *SetTrustLineFlagsResult) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -func (u *SetTrustLineFlagsResult) XdrRecurse(x XDR, name string) { +func (v *SCSpecUDTUnionCaseTupleV0) XdrPointer() interface{} { return v } +func (SCSpecUDTUnionCaseTupleV0) XdrTypeName() string { return "SCSpecUDTUnionCaseTupleV0" } +func (v SCSpecUDTUnionCaseTupleV0) XdrValue() interface{} { return v } +func (v *SCSpecUDTUnionCaseTupleV0) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v *SCSpecUDTUnionCaseTupleV0) XdrRecurse(x XDR, name string) { if name != "" { name = x.Sprintf("%s.", name) } - XDR_SetTrustLineFlagsResultCode(&u.Code).XdrMarshal(x, x.Sprintf("%scode", name)) - switch u.Code { - case SET_TRUST_LINE_FLAGS_SUCCESS: - return - case SET_TRUST_LINE_FLAGS_MALFORMED, SET_TRUST_LINE_FLAGS_NO_TRUST_LINE, SET_TRUST_LINE_FLAGS_CANT_REVOKE, SET_TRUST_LINE_FLAGS_INVALID_STATE, SET_TRUST_LINE_FLAGS_LOW_RESERVE: - return - } - XdrPanic("invalid Code (%v) in SetTrustLineFlagsResult", u.Code) + x.Marshal(x.Sprintf("%sdoc", name), XdrString{&v.Doc, SC_SPEC_DOC_LIMIT}) + x.Marshal(x.Sprintf("%sname", name), XdrString{&v.Name, 60}) + x.Marshal(x.Sprintf("%stype", name), (*_XdrVec_12_SCSpecTypeDef)(&v.Type)) } -func XDR_SetTrustLineFlagsResult(v *SetTrustLineFlagsResult) *SetTrustLineFlagsResult { return v } +func XDR_SCSpecUDTUnionCaseTupleV0(v *SCSpecUDTUnionCaseTupleV0) *SCSpecUDTUnionCaseTupleV0 { return v } -var _XdrNames_LiquidityPoolDepositResultCode = map[int32]string{ - int32(LIQUIDITY_POOL_DEPOSIT_SUCCESS): "LIQUIDITY_POOL_DEPOSIT_SUCCESS", - int32(LIQUIDITY_POOL_DEPOSIT_MALFORMED): "LIQUIDITY_POOL_DEPOSIT_MALFORMED", - int32(LIQUIDITY_POOL_DEPOSIT_NO_TRUST): "LIQUIDITY_POOL_DEPOSIT_NO_TRUST", - int32(LIQUIDITY_POOL_DEPOSIT_NOT_AUTHORIZED): "LIQUIDITY_POOL_DEPOSIT_NOT_AUTHORIZED", - int32(LIQUIDITY_POOL_DEPOSIT_UNDERFUNDED): "LIQUIDITY_POOL_DEPOSIT_UNDERFUNDED", - int32(LIQUIDITY_POOL_DEPOSIT_LINE_FULL): "LIQUIDITY_POOL_DEPOSIT_LINE_FULL", - int32(LIQUIDITY_POOL_DEPOSIT_BAD_PRICE): "LIQUIDITY_POOL_DEPOSIT_BAD_PRICE", - int32(LIQUIDITY_POOL_DEPOSIT_POOL_FULL): "LIQUIDITY_POOL_DEPOSIT_POOL_FULL", +var _XdrNames_SCSpecUDTUnionCaseV0Kind = map[int32]string{ + int32(SC_SPEC_UDT_UNION_CASE_VOID_V0): "SC_SPEC_UDT_UNION_CASE_VOID_V0", + int32(SC_SPEC_UDT_UNION_CASE_TUPLE_V0): "SC_SPEC_UDT_UNION_CASE_TUPLE_V0", } -var _XdrValues_LiquidityPoolDepositResultCode = map[string]int32{ - "LIQUIDITY_POOL_DEPOSIT_SUCCESS": int32(LIQUIDITY_POOL_DEPOSIT_SUCCESS), - "LIQUIDITY_POOL_DEPOSIT_MALFORMED": int32(LIQUIDITY_POOL_DEPOSIT_MALFORMED), - "LIQUIDITY_POOL_DEPOSIT_NO_TRUST": int32(LIQUIDITY_POOL_DEPOSIT_NO_TRUST), - "LIQUIDITY_POOL_DEPOSIT_NOT_AUTHORIZED": int32(LIQUIDITY_POOL_DEPOSIT_NOT_AUTHORIZED), - "LIQUIDITY_POOL_DEPOSIT_UNDERFUNDED": int32(LIQUIDITY_POOL_DEPOSIT_UNDERFUNDED), - "LIQUIDITY_POOL_DEPOSIT_LINE_FULL": int32(LIQUIDITY_POOL_DEPOSIT_LINE_FULL), - "LIQUIDITY_POOL_DEPOSIT_BAD_PRICE": int32(LIQUIDITY_POOL_DEPOSIT_BAD_PRICE), - "LIQUIDITY_POOL_DEPOSIT_POOL_FULL": int32(LIQUIDITY_POOL_DEPOSIT_POOL_FULL), +var _XdrValues_SCSpecUDTUnionCaseV0Kind = map[string]int32{ + "SC_SPEC_UDT_UNION_CASE_VOID_V0": int32(SC_SPEC_UDT_UNION_CASE_VOID_V0), + "SC_SPEC_UDT_UNION_CASE_TUPLE_V0": int32(SC_SPEC_UDT_UNION_CASE_TUPLE_V0), } -func (LiquidityPoolDepositResultCode) XdrEnumNames() map[int32]string { - return _XdrNames_LiquidityPoolDepositResultCode +func (SCSpecUDTUnionCaseV0Kind) XdrEnumNames() map[int32]string { + return _XdrNames_SCSpecUDTUnionCaseV0Kind } -func (v LiquidityPoolDepositResultCode) String() string { - if s, ok := _XdrNames_LiquidityPoolDepositResultCode[int32(v)]; ok { +func (v SCSpecUDTUnionCaseV0Kind) String() string { + if s, ok := _XdrNames_SCSpecUDTUnionCaseV0Kind[int32(v)]; ok { return s } - return fmt.Sprintf("LiquidityPoolDepositResultCode#%d", v) + return fmt.Sprintf("SCSpecUDTUnionCaseV0Kind#%d", v) } -func (v *LiquidityPoolDepositResultCode) Scan(ss fmt.ScanState, _ rune) error { +func (v *SCSpecUDTUnionCaseV0Kind) Scan(ss fmt.ScanState, _ rune) error { if tok, err := ss.Token(true, XdrSymChar); err != nil { return err } else { stok := string(tok) - if val, ok := _XdrValues_LiquidityPoolDepositResultCode[stok]; ok { - *v = LiquidityPoolDepositResultCode(val) + if val, ok := _XdrValues_SCSpecUDTUnionCaseV0Kind[stok]; ok { + *v = SCSpecUDTUnionCaseV0Kind(val) return nil - } else if stok == "LiquidityPoolDepositResultCode" { + } else if stok == "SCSpecUDTUnionCaseV0Kind" { if n, err := fmt.Fscanf(ss, "#%d", (*int32)(v)); n == 1 && err == nil { return nil - } - } - return XdrError(fmt.Sprintf("%s is not a valid LiquidityPoolDepositResultCode.", stok)) - } -} -func (v LiquidityPoolDepositResultCode) GetU32() uint32 { return uint32(v) } -func (v *LiquidityPoolDepositResultCode) SetU32(n uint32) { *v = LiquidityPoolDepositResultCode(n) } -func (v *LiquidityPoolDepositResultCode) XdrPointer() interface{} { return v } -func (LiquidityPoolDepositResultCode) XdrTypeName() string { return "LiquidityPoolDepositResultCode" } -func (v LiquidityPoolDepositResultCode) XdrValue() interface{} { return v } -func (v *LiquidityPoolDepositResultCode) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } + } + } + return XdrError(fmt.Sprintf("%s is not a valid SCSpecUDTUnionCaseV0Kind.", stok)) + } +} +func (v SCSpecUDTUnionCaseV0Kind) GetU32() uint32 { return uint32(v) } +func (v *SCSpecUDTUnionCaseV0Kind) SetU32(n uint32) { *v = SCSpecUDTUnionCaseV0Kind(n) } +func (v *SCSpecUDTUnionCaseV0Kind) XdrPointer() interface{} { return v } +func (SCSpecUDTUnionCaseV0Kind) XdrTypeName() string { return "SCSpecUDTUnionCaseV0Kind" } +func (v SCSpecUDTUnionCaseV0Kind) XdrValue() interface{} { return v } +func (v *SCSpecUDTUnionCaseV0Kind) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -type XdrType_LiquidityPoolDepositResultCode = *LiquidityPoolDepositResultCode +type XdrType_SCSpecUDTUnionCaseV0Kind = *SCSpecUDTUnionCaseV0Kind -func XDR_LiquidityPoolDepositResultCode(v *LiquidityPoolDepositResultCode) *LiquidityPoolDepositResultCode { - return v -} +func XDR_SCSpecUDTUnionCaseV0Kind(v *SCSpecUDTUnionCaseV0Kind) *SCSpecUDTUnionCaseV0Kind { return v } -var _XdrComments_LiquidityPoolDepositResultCode = map[int32]string{ - int32(LIQUIDITY_POOL_DEPOSIT_SUCCESS): "codes considered as \"success\" for the operation", - int32(LIQUIDITY_POOL_DEPOSIT_MALFORMED): "bad input", - int32(LIQUIDITY_POOL_DEPOSIT_NO_TRUST): "no trust line for one of the", - int32(LIQUIDITY_POOL_DEPOSIT_NOT_AUTHORIZED): "not authorized for one of the", - int32(LIQUIDITY_POOL_DEPOSIT_UNDERFUNDED): "not enough balance for one of", - int32(LIQUIDITY_POOL_DEPOSIT_LINE_FULL): "pool share trust line doesn't", - int32(LIQUIDITY_POOL_DEPOSIT_BAD_PRICE): "deposit price outside bounds", - int32(LIQUIDITY_POOL_DEPOSIT_POOL_FULL): "pool reserves are full", +var _XdrTags_SCSpecUDTUnionCaseV0 = map[int32]bool{ + XdrToI32(SC_SPEC_UDT_UNION_CASE_VOID_V0): true, + XdrToI32(SC_SPEC_UDT_UNION_CASE_TUPLE_V0): true, } -func (e LiquidityPoolDepositResultCode) XdrEnumComments() map[int32]string { - return _XdrComments_LiquidityPoolDepositResultCode +func (_ SCSpecUDTUnionCaseV0) XdrValidTags() map[int32]bool { + return _XdrTags_SCSpecUDTUnionCaseV0 } - -var _XdrTags_LiquidityPoolDepositResult = map[int32]bool{ - XdrToI32(LIQUIDITY_POOL_DEPOSIT_SUCCESS): true, - XdrToI32(LIQUIDITY_POOL_DEPOSIT_MALFORMED): true, - XdrToI32(LIQUIDITY_POOL_DEPOSIT_NO_TRUST): true, - XdrToI32(LIQUIDITY_POOL_DEPOSIT_NOT_AUTHORIZED): true, - XdrToI32(LIQUIDITY_POOL_DEPOSIT_UNDERFUNDED): true, - XdrToI32(LIQUIDITY_POOL_DEPOSIT_LINE_FULL): true, - XdrToI32(LIQUIDITY_POOL_DEPOSIT_BAD_PRICE): true, - XdrToI32(LIQUIDITY_POOL_DEPOSIT_POOL_FULL): true, +func (u *SCSpecUDTUnionCaseV0) VoidCase() *SCSpecUDTUnionCaseVoidV0 { + switch u.Kind { + case SC_SPEC_UDT_UNION_CASE_VOID_V0: + if v, ok := u._u.(*SCSpecUDTUnionCaseVoidV0); ok { + return v + } else { + var zero SCSpecUDTUnionCaseVoidV0 + u._u = &zero + return &zero + } + default: + XdrPanic("SCSpecUDTUnionCaseV0.VoidCase accessed when Kind == %v", u.Kind) + return nil + } } - -func (_ LiquidityPoolDepositResult) XdrValidTags() map[int32]bool { - return _XdrTags_LiquidityPoolDepositResult +func (u *SCSpecUDTUnionCaseV0) TupleCase() *SCSpecUDTUnionCaseTupleV0 { + switch u.Kind { + case SC_SPEC_UDT_UNION_CASE_TUPLE_V0: + if v, ok := u._u.(*SCSpecUDTUnionCaseTupleV0); ok { + return v + } else { + var zero SCSpecUDTUnionCaseTupleV0 + u._u = &zero + return &zero + } + default: + XdrPanic("SCSpecUDTUnionCaseV0.TupleCase accessed when Kind == %v", u.Kind) + return nil + } } -func (u LiquidityPoolDepositResult) XdrValid() bool { - switch u.Code { - case LIQUIDITY_POOL_DEPOSIT_SUCCESS, LIQUIDITY_POOL_DEPOSIT_MALFORMED, LIQUIDITY_POOL_DEPOSIT_NO_TRUST, LIQUIDITY_POOL_DEPOSIT_NOT_AUTHORIZED, LIQUIDITY_POOL_DEPOSIT_UNDERFUNDED, LIQUIDITY_POOL_DEPOSIT_LINE_FULL, LIQUIDITY_POOL_DEPOSIT_BAD_PRICE, LIQUIDITY_POOL_DEPOSIT_POOL_FULL: +func (u SCSpecUDTUnionCaseV0) XdrValid() bool { + switch u.Kind { + case SC_SPEC_UDT_UNION_CASE_VOID_V0, SC_SPEC_UDT_UNION_CASE_TUPLE_V0: return true } return false } -func (u *LiquidityPoolDepositResult) XdrUnionTag() XdrNum32 { - return XDR_LiquidityPoolDepositResultCode(&u.Code) +func (u *SCSpecUDTUnionCaseV0) XdrUnionTag() XdrNum32 { + return XDR_SCSpecUDTUnionCaseV0Kind(&u.Kind) } -func (u *LiquidityPoolDepositResult) XdrUnionTagName() string { - return "Code" +func (u *SCSpecUDTUnionCaseV0) XdrUnionTagName() string { + return "Kind" } -func (u *LiquidityPoolDepositResult) XdrUnionBody() XdrType { - switch u.Code { - case LIQUIDITY_POOL_DEPOSIT_SUCCESS: - return nil - case LIQUIDITY_POOL_DEPOSIT_MALFORMED, LIQUIDITY_POOL_DEPOSIT_NO_TRUST, LIQUIDITY_POOL_DEPOSIT_NOT_AUTHORIZED, LIQUIDITY_POOL_DEPOSIT_UNDERFUNDED, LIQUIDITY_POOL_DEPOSIT_LINE_FULL, LIQUIDITY_POOL_DEPOSIT_BAD_PRICE, LIQUIDITY_POOL_DEPOSIT_POOL_FULL: - return nil +func (u *SCSpecUDTUnionCaseV0) XdrUnionBody() XdrType { + switch u.Kind { + case SC_SPEC_UDT_UNION_CASE_VOID_V0: + return XDR_SCSpecUDTUnionCaseVoidV0(u.VoidCase()) + case SC_SPEC_UDT_UNION_CASE_TUPLE_V0: + return XDR_SCSpecUDTUnionCaseTupleV0(u.TupleCase()) } return nil } -func (u *LiquidityPoolDepositResult) XdrUnionBodyName() string { - switch u.Code { - case LIQUIDITY_POOL_DEPOSIT_SUCCESS: - return "" - case LIQUIDITY_POOL_DEPOSIT_MALFORMED, LIQUIDITY_POOL_DEPOSIT_NO_TRUST, LIQUIDITY_POOL_DEPOSIT_NOT_AUTHORIZED, LIQUIDITY_POOL_DEPOSIT_UNDERFUNDED, LIQUIDITY_POOL_DEPOSIT_LINE_FULL, LIQUIDITY_POOL_DEPOSIT_BAD_PRICE, LIQUIDITY_POOL_DEPOSIT_POOL_FULL: - return "" +func (u *SCSpecUDTUnionCaseV0) XdrUnionBodyName() string { + switch u.Kind { + case SC_SPEC_UDT_UNION_CASE_VOID_V0: + return "VoidCase" + case SC_SPEC_UDT_UNION_CASE_TUPLE_V0: + return "TupleCase" } return "" } -type XdrType_LiquidityPoolDepositResult = *LiquidityPoolDepositResult +type XdrType_SCSpecUDTUnionCaseV0 = *SCSpecUDTUnionCaseV0 -func (v *LiquidityPoolDepositResult) XdrPointer() interface{} { return v } -func (LiquidityPoolDepositResult) XdrTypeName() string { return "LiquidityPoolDepositResult" } -func (v LiquidityPoolDepositResult) XdrValue() interface{} { return v } -func (v *LiquidityPoolDepositResult) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -func (u *LiquidityPoolDepositResult) XdrRecurse(x XDR, name string) { +func (v *SCSpecUDTUnionCaseV0) XdrPointer() interface{} { return v } +func (SCSpecUDTUnionCaseV0) XdrTypeName() string { return "SCSpecUDTUnionCaseV0" } +func (v SCSpecUDTUnionCaseV0) XdrValue() interface{} { return v } +func (v *SCSpecUDTUnionCaseV0) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (u *SCSpecUDTUnionCaseV0) XdrRecurse(x XDR, name string) { if name != "" { name = x.Sprintf("%s.", name) } - XDR_LiquidityPoolDepositResultCode(&u.Code).XdrMarshal(x, x.Sprintf("%scode", name)) - switch u.Code { - case LIQUIDITY_POOL_DEPOSIT_SUCCESS: + XDR_SCSpecUDTUnionCaseV0Kind(&u.Kind).XdrMarshal(x, x.Sprintf("%skind", name)) + switch u.Kind { + case SC_SPEC_UDT_UNION_CASE_VOID_V0: + x.Marshal(x.Sprintf("%svoidCase", name), XDR_SCSpecUDTUnionCaseVoidV0(u.VoidCase())) return - case LIQUIDITY_POOL_DEPOSIT_MALFORMED, LIQUIDITY_POOL_DEPOSIT_NO_TRUST, LIQUIDITY_POOL_DEPOSIT_NOT_AUTHORIZED, LIQUIDITY_POOL_DEPOSIT_UNDERFUNDED, LIQUIDITY_POOL_DEPOSIT_LINE_FULL, LIQUIDITY_POOL_DEPOSIT_BAD_PRICE, LIQUIDITY_POOL_DEPOSIT_POOL_FULL: + case SC_SPEC_UDT_UNION_CASE_TUPLE_V0: + x.Marshal(x.Sprintf("%stupleCase", name), XDR_SCSpecUDTUnionCaseTupleV0(u.TupleCase())) return } - XdrPanic("invalid Code (%v) in LiquidityPoolDepositResult", u.Code) + XdrPanic("invalid Kind (%v) in SCSpecUDTUnionCaseV0", u.Kind) } -func XDR_LiquidityPoolDepositResult(v *LiquidityPoolDepositResult) *LiquidityPoolDepositResult { - return v +func XDR_SCSpecUDTUnionCaseV0(v *SCSpecUDTUnionCaseV0) *SCSpecUDTUnionCaseV0 { return v } + +type _XdrVec_50_SCSpecUDTUnionCaseV0 []SCSpecUDTUnionCaseV0 + +func (_XdrVec_50_SCSpecUDTUnionCaseV0) XdrBound() uint32 { + const bound uint32 = 50 // Force error if not const or doesn't fit + return bound +} +func (_XdrVec_50_SCSpecUDTUnionCaseV0) XdrCheckLen(length uint32) { + if length > uint32(50) { + XdrPanic("_XdrVec_50_SCSpecUDTUnionCaseV0 length %d exceeds bound 50", length) + } else if int(length) < 0 { + XdrPanic("_XdrVec_50_SCSpecUDTUnionCaseV0 length %d exceeds max int", length) + } +} +func (v _XdrVec_50_SCSpecUDTUnionCaseV0) GetVecLen() uint32 { return uint32(len(v)) } +func (v *_XdrVec_50_SCSpecUDTUnionCaseV0) SetVecLen(length uint32) { + v.XdrCheckLen(length) + if int(length) <= cap(*v) { + if int(length) != len(*v) { + *v = (*v)[:int(length)] + } + return + } + newcap := 2 * cap(*v) + if newcap < int(length) { // also catches overflow where 2*cap < 0 + newcap = int(length) + } else if bound := uint(50); uint(newcap) > bound { + if int(bound) < 0 { + bound = ^uint(0) >> 1 + } + newcap = int(bound) + } + nv := make([]SCSpecUDTUnionCaseV0, int(length), newcap) + copy(nv, *v) + *v = nv +} +func (v *_XdrVec_50_SCSpecUDTUnionCaseV0) XdrMarshalN(x XDR, name string, n uint32) { + v.XdrCheckLen(n) + for i := 0; i < int(n); i++ { + if i >= len(*v) { + v.SetVecLen(uint32(i + 1)) + } + XDR_SCSpecUDTUnionCaseV0(&(*v)[i]).XdrMarshal(x, x.Sprintf("%s[%d]", name, i)) + } + if int(n) < len(*v) { + *v = (*v)[:int(n)] + } +} +func (v *_XdrVec_50_SCSpecUDTUnionCaseV0) XdrRecurse(x XDR, name string) { + size := XdrSize{Size: uint32(len(*v)), Bound: 50} + x.Marshal(name, &size) + v.XdrMarshalN(x, name, size.Size) +} +func (_XdrVec_50_SCSpecUDTUnionCaseV0) XdrTypeName() string { return "SCSpecUDTUnionCaseV0<>" } +func (v *_XdrVec_50_SCSpecUDTUnionCaseV0) XdrPointer() interface{} { + return (*[]SCSpecUDTUnionCaseV0)(v) } +func (v _XdrVec_50_SCSpecUDTUnionCaseV0) XdrValue() interface{} { return ([]SCSpecUDTUnionCaseV0)(v) } +func (v *_XdrVec_50_SCSpecUDTUnionCaseV0) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -var _XdrNames_LiquidityPoolWithdrawResultCode = map[int32]string{ - int32(LIQUIDITY_POOL_WITHDRAW_SUCCESS): "LIQUIDITY_POOL_WITHDRAW_SUCCESS", - int32(LIQUIDITY_POOL_WITHDRAW_MALFORMED): "LIQUIDITY_POOL_WITHDRAW_MALFORMED", - int32(LIQUIDITY_POOL_WITHDRAW_NO_TRUST): "LIQUIDITY_POOL_WITHDRAW_NO_TRUST", - int32(LIQUIDITY_POOL_WITHDRAW_UNDERFUNDED): "LIQUIDITY_POOL_WITHDRAW_UNDERFUNDED", - int32(LIQUIDITY_POOL_WITHDRAW_LINE_FULL): "LIQUIDITY_POOL_WITHDRAW_LINE_FULL", - int32(LIQUIDITY_POOL_WITHDRAW_UNDER_MINIMUM): "LIQUIDITY_POOL_WITHDRAW_UNDER_MINIMUM", +type XdrType_SCSpecUDTUnionV0 = *SCSpecUDTUnionV0 + +func (v *SCSpecUDTUnionV0) XdrPointer() interface{} { return v } +func (SCSpecUDTUnionV0) XdrTypeName() string { return "SCSpecUDTUnionV0" } +func (v SCSpecUDTUnionV0) XdrValue() interface{} { return v } +func (v *SCSpecUDTUnionV0) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v *SCSpecUDTUnionV0) XdrRecurse(x XDR, name string) { + if name != "" { + name = x.Sprintf("%s.", name) + } + x.Marshal(x.Sprintf("%sdoc", name), XdrString{&v.Doc, SC_SPEC_DOC_LIMIT}) + x.Marshal(x.Sprintf("%slib", name), XdrString{&v.Lib, 80}) + x.Marshal(x.Sprintf("%sname", name), XdrString{&v.Name, 60}) + x.Marshal(x.Sprintf("%scases", name), (*_XdrVec_50_SCSpecUDTUnionCaseV0)(&v.Cases)) } -var _XdrValues_LiquidityPoolWithdrawResultCode = map[string]int32{ - "LIQUIDITY_POOL_WITHDRAW_SUCCESS": int32(LIQUIDITY_POOL_WITHDRAW_SUCCESS), - "LIQUIDITY_POOL_WITHDRAW_MALFORMED": int32(LIQUIDITY_POOL_WITHDRAW_MALFORMED), - "LIQUIDITY_POOL_WITHDRAW_NO_TRUST": int32(LIQUIDITY_POOL_WITHDRAW_NO_TRUST), - "LIQUIDITY_POOL_WITHDRAW_UNDERFUNDED": int32(LIQUIDITY_POOL_WITHDRAW_UNDERFUNDED), - "LIQUIDITY_POOL_WITHDRAW_LINE_FULL": int32(LIQUIDITY_POOL_WITHDRAW_LINE_FULL), - "LIQUIDITY_POOL_WITHDRAW_UNDER_MINIMUM": int32(LIQUIDITY_POOL_WITHDRAW_UNDER_MINIMUM), +func XDR_SCSpecUDTUnionV0(v *SCSpecUDTUnionV0) *SCSpecUDTUnionV0 { return v } + +type XdrType_SCSpecUDTEnumCaseV0 = *SCSpecUDTEnumCaseV0 + +func (v *SCSpecUDTEnumCaseV0) XdrPointer() interface{} { return v } +func (SCSpecUDTEnumCaseV0) XdrTypeName() string { return "SCSpecUDTEnumCaseV0" } +func (v SCSpecUDTEnumCaseV0) XdrValue() interface{} { return v } +func (v *SCSpecUDTEnumCaseV0) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v *SCSpecUDTEnumCaseV0) XdrRecurse(x XDR, name string) { + if name != "" { + name = x.Sprintf("%s.", name) + } + x.Marshal(x.Sprintf("%sdoc", name), XdrString{&v.Doc, SC_SPEC_DOC_LIMIT}) + x.Marshal(x.Sprintf("%sname", name), XdrString{&v.Name, 60}) + x.Marshal(x.Sprintf("%svalue", name), XDR_Uint32(&v.Value)) } +func XDR_SCSpecUDTEnumCaseV0(v *SCSpecUDTEnumCaseV0) *SCSpecUDTEnumCaseV0 { return v } -func (LiquidityPoolWithdrawResultCode) XdrEnumNames() map[int32]string { - return _XdrNames_LiquidityPoolWithdrawResultCode +type _XdrVec_50_SCSpecUDTEnumCaseV0 []SCSpecUDTEnumCaseV0 + +func (_XdrVec_50_SCSpecUDTEnumCaseV0) XdrBound() uint32 { + const bound uint32 = 50 // Force error if not const or doesn't fit + return bound } -func (v LiquidityPoolWithdrawResultCode) String() string { - if s, ok := _XdrNames_LiquidityPoolWithdrawResultCode[int32(v)]; ok { - return s +func (_XdrVec_50_SCSpecUDTEnumCaseV0) XdrCheckLen(length uint32) { + if length > uint32(50) { + XdrPanic("_XdrVec_50_SCSpecUDTEnumCaseV0 length %d exceeds bound 50", length) + } else if int(length) < 0 { + XdrPanic("_XdrVec_50_SCSpecUDTEnumCaseV0 length %d exceeds max int", length) } - return fmt.Sprintf("LiquidityPoolWithdrawResultCode#%d", v) } -func (v *LiquidityPoolWithdrawResultCode) Scan(ss fmt.ScanState, _ rune) error { - if tok, err := ss.Token(true, XdrSymChar); err != nil { - return err - } else { - stok := string(tok) - if val, ok := _XdrValues_LiquidityPoolWithdrawResultCode[stok]; ok { - *v = LiquidityPoolWithdrawResultCode(val) - return nil - } else if stok == "LiquidityPoolWithdrawResultCode" { - if n, err := fmt.Fscanf(ss, "#%d", (*int32)(v)); n == 1 && err == nil { - return nil - } +func (v _XdrVec_50_SCSpecUDTEnumCaseV0) GetVecLen() uint32 { return uint32(len(v)) } +func (v *_XdrVec_50_SCSpecUDTEnumCaseV0) SetVecLen(length uint32) { + v.XdrCheckLen(length) + if int(length) <= cap(*v) { + if int(length) != len(*v) { + *v = (*v)[:int(length)] } - return XdrError(fmt.Sprintf("%s is not a valid LiquidityPoolWithdrawResultCode.", stok)) + return + } + newcap := 2 * cap(*v) + if newcap < int(length) { // also catches overflow where 2*cap < 0 + newcap = int(length) + } else if bound := uint(50); uint(newcap) > bound { + if int(bound) < 0 { + bound = ^uint(0) >> 1 + } + newcap = int(bound) } + nv := make([]SCSpecUDTEnumCaseV0, int(length), newcap) + copy(nv, *v) + *v = nv } -func (v LiquidityPoolWithdrawResultCode) GetU32() uint32 { return uint32(v) } -func (v *LiquidityPoolWithdrawResultCode) SetU32(n uint32) { *v = LiquidityPoolWithdrawResultCode(n) } -func (v *LiquidityPoolWithdrawResultCode) XdrPointer() interface{} { return v } -func (LiquidityPoolWithdrawResultCode) XdrTypeName() string { return "LiquidityPoolWithdrawResultCode" } -func (v LiquidityPoolWithdrawResultCode) XdrValue() interface{} { return v } -func (v *LiquidityPoolWithdrawResultCode) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v *_XdrVec_50_SCSpecUDTEnumCaseV0) XdrMarshalN(x XDR, name string, n uint32) { + v.XdrCheckLen(n) + for i := 0; i < int(n); i++ { + if i >= len(*v) { + v.SetVecLen(uint32(i + 1)) + } + XDR_SCSpecUDTEnumCaseV0(&(*v)[i]).XdrMarshal(x, x.Sprintf("%s[%d]", name, i)) + } + if int(n) < len(*v) { + *v = (*v)[:int(n)] + } +} +func (v *_XdrVec_50_SCSpecUDTEnumCaseV0) XdrRecurse(x XDR, name string) { + size := XdrSize{Size: uint32(len(*v)), Bound: 50} + x.Marshal(name, &size) + v.XdrMarshalN(x, name, size.Size) +} +func (_XdrVec_50_SCSpecUDTEnumCaseV0) XdrTypeName() string { return "SCSpecUDTEnumCaseV0<>" } +func (v *_XdrVec_50_SCSpecUDTEnumCaseV0) XdrPointer() interface{} { return (*[]SCSpecUDTEnumCaseV0)(v) } +func (v _XdrVec_50_SCSpecUDTEnumCaseV0) XdrValue() interface{} { return ([]SCSpecUDTEnumCaseV0)(v) } +func (v *_XdrVec_50_SCSpecUDTEnumCaseV0) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -type XdrType_LiquidityPoolWithdrawResultCode = *LiquidityPoolWithdrawResultCode +type XdrType_SCSpecUDTEnumV0 = *SCSpecUDTEnumV0 -func XDR_LiquidityPoolWithdrawResultCode(v *LiquidityPoolWithdrawResultCode) *LiquidityPoolWithdrawResultCode { - return v +func (v *SCSpecUDTEnumV0) XdrPointer() interface{} { return v } +func (SCSpecUDTEnumV0) XdrTypeName() string { return "SCSpecUDTEnumV0" } +func (v SCSpecUDTEnumV0) XdrValue() interface{} { return v } +func (v *SCSpecUDTEnumV0) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v *SCSpecUDTEnumV0) XdrRecurse(x XDR, name string) { + if name != "" { + name = x.Sprintf("%s.", name) + } + x.Marshal(x.Sprintf("%sdoc", name), XdrString{&v.Doc, SC_SPEC_DOC_LIMIT}) + x.Marshal(x.Sprintf("%slib", name), XdrString{&v.Lib, 80}) + x.Marshal(x.Sprintf("%sname", name), XdrString{&v.Name, 60}) + x.Marshal(x.Sprintf("%scases", name), (*_XdrVec_50_SCSpecUDTEnumCaseV0)(&v.Cases)) } +func XDR_SCSpecUDTEnumV0(v *SCSpecUDTEnumV0) *SCSpecUDTEnumV0 { return v } -var _XdrComments_LiquidityPoolWithdrawResultCode = map[int32]string{ - int32(LIQUIDITY_POOL_WITHDRAW_SUCCESS): "codes considered as \"success\" for the operation", - int32(LIQUIDITY_POOL_WITHDRAW_MALFORMED): "bad input", - int32(LIQUIDITY_POOL_WITHDRAW_NO_TRUST): "no trust line for one of the", - int32(LIQUIDITY_POOL_WITHDRAW_UNDERFUNDED): "not enough balance of the", - int32(LIQUIDITY_POOL_WITHDRAW_LINE_FULL): "would go above limit for one", - int32(LIQUIDITY_POOL_WITHDRAW_UNDER_MINIMUM): "of the assets", -} +type XdrType_SCSpecUDTErrorEnumCaseV0 = *SCSpecUDTErrorEnumCaseV0 -func (e LiquidityPoolWithdrawResultCode) XdrEnumComments() map[int32]string { - return _XdrComments_LiquidityPoolWithdrawResultCode +func (v *SCSpecUDTErrorEnumCaseV0) XdrPointer() interface{} { return v } +func (SCSpecUDTErrorEnumCaseV0) XdrTypeName() string { return "SCSpecUDTErrorEnumCaseV0" } +func (v SCSpecUDTErrorEnumCaseV0) XdrValue() interface{} { return v } +func (v *SCSpecUDTErrorEnumCaseV0) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v *SCSpecUDTErrorEnumCaseV0) XdrRecurse(x XDR, name string) { + if name != "" { + name = x.Sprintf("%s.", name) + } + x.Marshal(x.Sprintf("%sdoc", name), XdrString{&v.Doc, SC_SPEC_DOC_LIMIT}) + x.Marshal(x.Sprintf("%sname", name), XdrString{&v.Name, 60}) + x.Marshal(x.Sprintf("%svalue", name), XDR_Uint32(&v.Value)) } +func XDR_SCSpecUDTErrorEnumCaseV0(v *SCSpecUDTErrorEnumCaseV0) *SCSpecUDTErrorEnumCaseV0 { return v } -var _XdrTags_LiquidityPoolWithdrawResult = map[int32]bool{ - XdrToI32(LIQUIDITY_POOL_WITHDRAW_SUCCESS): true, - XdrToI32(LIQUIDITY_POOL_WITHDRAW_MALFORMED): true, - XdrToI32(LIQUIDITY_POOL_WITHDRAW_NO_TRUST): true, - XdrToI32(LIQUIDITY_POOL_WITHDRAW_UNDERFUNDED): true, - XdrToI32(LIQUIDITY_POOL_WITHDRAW_LINE_FULL): true, - XdrToI32(LIQUIDITY_POOL_WITHDRAW_UNDER_MINIMUM): true, -} +type _XdrVec_50_SCSpecUDTErrorEnumCaseV0 []SCSpecUDTErrorEnumCaseV0 -func (_ LiquidityPoolWithdrawResult) XdrValidTags() map[int32]bool { - return _XdrTags_LiquidityPoolWithdrawResult +func (_XdrVec_50_SCSpecUDTErrorEnumCaseV0) XdrBound() uint32 { + const bound uint32 = 50 // Force error if not const or doesn't fit + return bound } -func (u LiquidityPoolWithdrawResult) XdrValid() bool { - switch u.Code { - case LIQUIDITY_POOL_WITHDRAW_SUCCESS, LIQUIDITY_POOL_WITHDRAW_MALFORMED, LIQUIDITY_POOL_WITHDRAW_NO_TRUST, LIQUIDITY_POOL_WITHDRAW_UNDERFUNDED, LIQUIDITY_POOL_WITHDRAW_LINE_FULL, LIQUIDITY_POOL_WITHDRAW_UNDER_MINIMUM: - return true +func (_XdrVec_50_SCSpecUDTErrorEnumCaseV0) XdrCheckLen(length uint32) { + if length > uint32(50) { + XdrPanic("_XdrVec_50_SCSpecUDTErrorEnumCaseV0 length %d exceeds bound 50", length) + } else if int(length) < 0 { + XdrPanic("_XdrVec_50_SCSpecUDTErrorEnumCaseV0 length %d exceeds max int", length) + } +} +func (v _XdrVec_50_SCSpecUDTErrorEnumCaseV0) GetVecLen() uint32 { return uint32(len(v)) } +func (v *_XdrVec_50_SCSpecUDTErrorEnumCaseV0) SetVecLen(length uint32) { + v.XdrCheckLen(length) + if int(length) <= cap(*v) { + if int(length) != len(*v) { + *v = (*v)[:int(length)] + } + return + } + newcap := 2 * cap(*v) + if newcap < int(length) { // also catches overflow where 2*cap < 0 + newcap = int(length) + } else if bound := uint(50); uint(newcap) > bound { + if int(bound) < 0 { + bound = ^uint(0) >> 1 + } + newcap = int(bound) + } + nv := make([]SCSpecUDTErrorEnumCaseV0, int(length), newcap) + copy(nv, *v) + *v = nv +} +func (v *_XdrVec_50_SCSpecUDTErrorEnumCaseV0) XdrMarshalN(x XDR, name string, n uint32) { + v.XdrCheckLen(n) + for i := 0; i < int(n); i++ { + if i >= len(*v) { + v.SetVecLen(uint32(i + 1)) + } + XDR_SCSpecUDTErrorEnumCaseV0(&(*v)[i]).XdrMarshal(x, x.Sprintf("%s[%d]", name, i)) + } + if int(n) < len(*v) { + *v = (*v)[:int(n)] } - return false } -func (u *LiquidityPoolWithdrawResult) XdrUnionTag() XdrNum32 { - return XDR_LiquidityPoolWithdrawResultCode(&u.Code) +func (v *_XdrVec_50_SCSpecUDTErrorEnumCaseV0) XdrRecurse(x XDR, name string) { + size := XdrSize{Size: uint32(len(*v)), Bound: 50} + x.Marshal(name, &size) + v.XdrMarshalN(x, name, size.Size) } -func (u *LiquidityPoolWithdrawResult) XdrUnionTagName() string { - return "Code" +func (_XdrVec_50_SCSpecUDTErrorEnumCaseV0) XdrTypeName() string { return "SCSpecUDTErrorEnumCaseV0<>" } +func (v *_XdrVec_50_SCSpecUDTErrorEnumCaseV0) XdrPointer() interface{} { + return (*[]SCSpecUDTErrorEnumCaseV0)(v) } -func (u *LiquidityPoolWithdrawResult) XdrUnionBody() XdrType { - switch u.Code { - case LIQUIDITY_POOL_WITHDRAW_SUCCESS: - return nil - case LIQUIDITY_POOL_WITHDRAW_MALFORMED, LIQUIDITY_POOL_WITHDRAW_NO_TRUST, LIQUIDITY_POOL_WITHDRAW_UNDERFUNDED, LIQUIDITY_POOL_WITHDRAW_LINE_FULL, LIQUIDITY_POOL_WITHDRAW_UNDER_MINIMUM: - return nil - } - return nil +func (v _XdrVec_50_SCSpecUDTErrorEnumCaseV0) XdrValue() interface{} { + return ([]SCSpecUDTErrorEnumCaseV0)(v) } -func (u *LiquidityPoolWithdrawResult) XdrUnionBodyName() string { - switch u.Code { - case LIQUIDITY_POOL_WITHDRAW_SUCCESS: - return "" - case LIQUIDITY_POOL_WITHDRAW_MALFORMED, LIQUIDITY_POOL_WITHDRAW_NO_TRUST, LIQUIDITY_POOL_WITHDRAW_UNDERFUNDED, LIQUIDITY_POOL_WITHDRAW_LINE_FULL, LIQUIDITY_POOL_WITHDRAW_UNDER_MINIMUM: - return "" +func (v *_XdrVec_50_SCSpecUDTErrorEnumCaseV0) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } + +type XdrType_SCSpecUDTErrorEnumV0 = *SCSpecUDTErrorEnumV0 + +func (v *SCSpecUDTErrorEnumV0) XdrPointer() interface{} { return v } +func (SCSpecUDTErrorEnumV0) XdrTypeName() string { return "SCSpecUDTErrorEnumV0" } +func (v SCSpecUDTErrorEnumV0) XdrValue() interface{} { return v } +func (v *SCSpecUDTErrorEnumV0) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v *SCSpecUDTErrorEnumV0) XdrRecurse(x XDR, name string) { + if name != "" { + name = x.Sprintf("%s.", name) } - return "" + x.Marshal(x.Sprintf("%sdoc", name), XdrString{&v.Doc, SC_SPEC_DOC_LIMIT}) + x.Marshal(x.Sprintf("%slib", name), XdrString{&v.Lib, 80}) + x.Marshal(x.Sprintf("%sname", name), XdrString{&v.Name, 60}) + x.Marshal(x.Sprintf("%scases", name), (*_XdrVec_50_SCSpecUDTErrorEnumCaseV0)(&v.Cases)) } +func XDR_SCSpecUDTErrorEnumV0(v *SCSpecUDTErrorEnumV0) *SCSpecUDTErrorEnumV0 { return v } -type XdrType_LiquidityPoolWithdrawResult = *LiquidityPoolWithdrawResult +type XdrType_SCSpecFunctionInputV0 = *SCSpecFunctionInputV0 -func (v *LiquidityPoolWithdrawResult) XdrPointer() interface{} { return v } -func (LiquidityPoolWithdrawResult) XdrTypeName() string { return "LiquidityPoolWithdrawResult" } -func (v LiquidityPoolWithdrawResult) XdrValue() interface{} { return v } -func (v *LiquidityPoolWithdrawResult) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -func (u *LiquidityPoolWithdrawResult) XdrRecurse(x XDR, name string) { +func (v *SCSpecFunctionInputV0) XdrPointer() interface{} { return v } +func (SCSpecFunctionInputV0) XdrTypeName() string { return "SCSpecFunctionInputV0" } +func (v SCSpecFunctionInputV0) XdrValue() interface{} { return v } +func (v *SCSpecFunctionInputV0) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v *SCSpecFunctionInputV0) XdrRecurse(x XDR, name string) { if name != "" { name = x.Sprintf("%s.", name) } - XDR_LiquidityPoolWithdrawResultCode(&u.Code).XdrMarshal(x, x.Sprintf("%scode", name)) - switch u.Code { - case LIQUIDITY_POOL_WITHDRAW_SUCCESS: - return - case LIQUIDITY_POOL_WITHDRAW_MALFORMED, LIQUIDITY_POOL_WITHDRAW_NO_TRUST, LIQUIDITY_POOL_WITHDRAW_UNDERFUNDED, LIQUIDITY_POOL_WITHDRAW_LINE_FULL, LIQUIDITY_POOL_WITHDRAW_UNDER_MINIMUM: - return - } - XdrPanic("invalid Code (%v) in LiquidityPoolWithdrawResult", u.Code) -} -func XDR_LiquidityPoolWithdrawResult(v *LiquidityPoolWithdrawResult) *LiquidityPoolWithdrawResult { - return v + x.Marshal(x.Sprintf("%sdoc", name), XdrString{&v.Doc, SC_SPEC_DOC_LIMIT}) + x.Marshal(x.Sprintf("%sname", name), XdrString{&v.Name, 30}) + x.Marshal(x.Sprintf("%stype", name), XDR_SCSpecTypeDef(&v.Type)) } +func XDR_SCSpecFunctionInputV0(v *SCSpecFunctionInputV0) *SCSpecFunctionInputV0 { return v } -var _XdrNames_OperationResultCode = map[int32]string{ - int32(OpINNER): "opINNER", - int32(OpBAD_AUTH): "opBAD_AUTH", - int32(OpNO_ACCOUNT): "opNO_ACCOUNT", - int32(OpNOT_SUPPORTED): "opNOT_SUPPORTED", - int32(OpTOO_MANY_SUBENTRIES): "opTOO_MANY_SUBENTRIES", - int32(OpEXCEEDED_WORK_LIMIT): "opEXCEEDED_WORK_LIMIT", - int32(OpTOO_MANY_SPONSORING): "opTOO_MANY_SPONSORING", -} -var _XdrValues_OperationResultCode = map[string]int32{ - "opINNER": int32(OpINNER), - "opBAD_AUTH": int32(OpBAD_AUTH), - "opNO_ACCOUNT": int32(OpNO_ACCOUNT), - "opNOT_SUPPORTED": int32(OpNOT_SUPPORTED), - "opTOO_MANY_SUBENTRIES": int32(OpTOO_MANY_SUBENTRIES), - "opEXCEEDED_WORK_LIMIT": int32(OpEXCEEDED_WORK_LIMIT), - "opTOO_MANY_SPONSORING": int32(OpTOO_MANY_SPONSORING), -} +type _XdrVec_10_SCSpecFunctionInputV0 []SCSpecFunctionInputV0 -func (OperationResultCode) XdrEnumNames() map[int32]string { - return _XdrNames_OperationResultCode +func (_XdrVec_10_SCSpecFunctionInputV0) XdrBound() uint32 { + const bound uint32 = 10 // Force error if not const or doesn't fit + return bound } -func (v OperationResultCode) String() string { - if s, ok := _XdrNames_OperationResultCode[int32(v)]; ok { - return s +func (_XdrVec_10_SCSpecFunctionInputV0) XdrCheckLen(length uint32) { + if length > uint32(10) { + XdrPanic("_XdrVec_10_SCSpecFunctionInputV0 length %d exceeds bound 10", length) + } else if int(length) < 0 { + XdrPanic("_XdrVec_10_SCSpecFunctionInputV0 length %d exceeds max int", length) } - return fmt.Sprintf("OperationResultCode#%d", v) } -func (v *OperationResultCode) Scan(ss fmt.ScanState, _ rune) error { - if tok, err := ss.Token(true, XdrSymChar); err != nil { - return err - } else { - stok := string(tok) - if val, ok := _XdrValues_OperationResultCode[stok]; ok { - *v = OperationResultCode(val) - return nil - } else if stok == "OperationResultCode" { - if n, err := fmt.Fscanf(ss, "#%d", (*int32)(v)); n == 1 && err == nil { - return nil - } +func (v _XdrVec_10_SCSpecFunctionInputV0) GetVecLen() uint32 { return uint32(len(v)) } +func (v *_XdrVec_10_SCSpecFunctionInputV0) SetVecLen(length uint32) { + v.XdrCheckLen(length) + if int(length) <= cap(*v) { + if int(length) != len(*v) { + *v = (*v)[:int(length)] } - return XdrError(fmt.Sprintf("%s is not a valid OperationResultCode.", stok)) + return + } + newcap := 2 * cap(*v) + if newcap < int(length) { // also catches overflow where 2*cap < 0 + newcap = int(length) + } else if bound := uint(10); uint(newcap) > bound { + if int(bound) < 0 { + bound = ^uint(0) >> 1 + } + newcap = int(bound) } + nv := make([]SCSpecFunctionInputV0, int(length), newcap) + copy(nv, *v) + *v = nv } -func (v OperationResultCode) GetU32() uint32 { return uint32(v) } -func (v *OperationResultCode) SetU32(n uint32) { *v = OperationResultCode(n) } -func (v *OperationResultCode) XdrPointer() interface{} { return v } -func (OperationResultCode) XdrTypeName() string { return "OperationResultCode" } -func (v OperationResultCode) XdrValue() interface{} { return v } -func (v *OperationResultCode) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } - -type XdrType_OperationResultCode = *OperationResultCode - -func XDR_OperationResultCode(v *OperationResultCode) *OperationResultCode { return v } - -var _XdrComments_OperationResultCode = map[int32]string{ - int32(OpINNER): "inner object result is valid", - int32(OpBAD_AUTH): "too few valid signatures / wrong network", - int32(OpNO_ACCOUNT): "source account was not found", - int32(OpNOT_SUPPORTED): "operation not supported at this time", - int32(OpTOO_MANY_SUBENTRIES): "max number of subentries already reached", - int32(OpEXCEEDED_WORK_LIMIT): "operation did too much work", - int32(OpTOO_MANY_SPONSORING): "account is sponsoring too many entries", +func (v *_XdrVec_10_SCSpecFunctionInputV0) XdrMarshalN(x XDR, name string, n uint32) { + v.XdrCheckLen(n) + for i := 0; i < int(n); i++ { + if i >= len(*v) { + v.SetVecLen(uint32(i + 1)) + } + XDR_SCSpecFunctionInputV0(&(*v)[i]).XdrMarshal(x, x.Sprintf("%s[%d]", name, i)) + } + if int(n) < len(*v) { + *v = (*v)[:int(n)] + } } - -func (e OperationResultCode) XdrEnumComments() map[int32]string { - return _XdrComments_OperationResultCode +func (v *_XdrVec_10_SCSpecFunctionInputV0) XdrRecurse(x XDR, name string) { + size := XdrSize{Size: uint32(len(*v)), Bound: 10} + x.Marshal(name, &size) + v.XdrMarshalN(x, name, size.Size) } - -var _XdrTags_XdrAnon_OperationResult_Tr = map[int32]bool{ - XdrToI32(CREATE_ACCOUNT): true, - XdrToI32(PAYMENT): true, - XdrToI32(PATH_PAYMENT_STRICT_RECEIVE): true, - XdrToI32(MANAGE_SELL_OFFER): true, - XdrToI32(CREATE_PASSIVE_SELL_OFFER): true, - XdrToI32(SET_OPTIONS): true, - XdrToI32(CHANGE_TRUST): true, - XdrToI32(ALLOW_TRUST): true, - XdrToI32(ACCOUNT_MERGE): true, - XdrToI32(INFLATION): true, - XdrToI32(MANAGE_DATA): true, - XdrToI32(BUMP_SEQUENCE): true, - XdrToI32(MANAGE_BUY_OFFER): true, - XdrToI32(PATH_PAYMENT_STRICT_SEND): true, - XdrToI32(CREATE_CLAIMABLE_BALANCE): true, - XdrToI32(CLAIM_CLAIMABLE_BALANCE): true, - XdrToI32(BEGIN_SPONSORING_FUTURE_RESERVES): true, - XdrToI32(END_SPONSORING_FUTURE_RESERVES): true, - XdrToI32(REVOKE_SPONSORSHIP): true, - XdrToI32(CLAWBACK): true, - XdrToI32(CLAWBACK_CLAIMABLE_BALANCE): true, - XdrToI32(SET_TRUST_LINE_FLAGS): true, - XdrToI32(LIQUIDITY_POOL_DEPOSIT): true, - XdrToI32(LIQUIDITY_POOL_WITHDRAW): true, +func (_XdrVec_10_SCSpecFunctionInputV0) XdrTypeName() string { return "SCSpecFunctionInputV0<>" } +func (v *_XdrVec_10_SCSpecFunctionInputV0) XdrPointer() interface{} { + return (*[]SCSpecFunctionInputV0)(v) } +func (v _XdrVec_10_SCSpecFunctionInputV0) XdrValue() interface{} { return ([]SCSpecFunctionInputV0)(v) } +func (v *_XdrVec_10_SCSpecFunctionInputV0) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -func (_ XdrAnon_OperationResult_Tr) XdrValidTags() map[int32]bool { - return _XdrTags_XdrAnon_OperationResult_Tr +type _XdrVec_1_SCSpecTypeDef []SCSpecTypeDef + +func (_XdrVec_1_SCSpecTypeDef) XdrBound() uint32 { + const bound uint32 = 1 // Force error if not const or doesn't fit + return bound } -func (u *XdrAnon_OperationResult_Tr) CreateAccountResult() *CreateAccountResult { - switch u.Type { - case CREATE_ACCOUNT: - if v, ok := u._u.(*CreateAccountResult); ok { - return v - } else { - var zero CreateAccountResult - u._u = &zero - return &zero - } - default: - XdrPanic("XdrAnon_OperationResult_Tr.CreateAccountResult accessed when Type == %v", u.Type) - return nil +func (_XdrVec_1_SCSpecTypeDef) XdrCheckLen(length uint32) { + if length > uint32(1) { + XdrPanic("_XdrVec_1_SCSpecTypeDef length %d exceeds bound 1", length) + } else if int(length) < 0 { + XdrPanic("_XdrVec_1_SCSpecTypeDef length %d exceeds max int", length) } } -func (u *XdrAnon_OperationResult_Tr) PaymentResult() *PaymentResult { - switch u.Type { - case PAYMENT: - if v, ok := u._u.(*PaymentResult); ok { - return v - } else { - var zero PaymentResult - u._u = &zero - return &zero +func (v _XdrVec_1_SCSpecTypeDef) GetVecLen() uint32 { return uint32(len(v)) } +func (v *_XdrVec_1_SCSpecTypeDef) SetVecLen(length uint32) { + v.XdrCheckLen(length) + if int(length) <= cap(*v) { + if int(length) != len(*v) { + *v = (*v)[:int(length)] } - default: - XdrPanic("XdrAnon_OperationResult_Tr.PaymentResult accessed when Type == %v", u.Type) - return nil + return } -} -func (u *XdrAnon_OperationResult_Tr) PathPaymentStrictReceiveResult() *PathPaymentStrictReceiveResult { - switch u.Type { - case PATH_PAYMENT_STRICT_RECEIVE: - if v, ok := u._u.(*PathPaymentStrictReceiveResult); ok { - return v - } else { - var zero PathPaymentStrictReceiveResult - u._u = &zero - return &zero + newcap := 2 * cap(*v) + if newcap < int(length) { // also catches overflow where 2*cap < 0 + newcap = int(length) + } else if bound := uint(1); uint(newcap) > bound { + if int(bound) < 0 { + bound = ^uint(0) >> 1 } - default: - XdrPanic("XdrAnon_OperationResult_Tr.PathPaymentStrictReceiveResult accessed when Type == %v", u.Type) - return nil + newcap = int(bound) } + nv := make([]SCSpecTypeDef, int(length), newcap) + copy(nv, *v) + *v = nv } -func (u *XdrAnon_OperationResult_Tr) ManageSellOfferResult() *ManageSellOfferResult { - switch u.Type { - case MANAGE_SELL_OFFER: - if v, ok := u._u.(*ManageSellOfferResult); ok { - return v - } else { - var zero ManageSellOfferResult - u._u = &zero - return &zero +func (v *_XdrVec_1_SCSpecTypeDef) XdrMarshalN(x XDR, name string, n uint32) { + v.XdrCheckLen(n) + for i := 0; i < int(n); i++ { + if i >= len(*v) { + v.SetVecLen(uint32(i + 1)) } - default: - XdrPanic("XdrAnon_OperationResult_Tr.ManageSellOfferResult accessed when Type == %v", u.Type) - return nil + XDR_SCSpecTypeDef(&(*v)[i]).XdrMarshal(x, x.Sprintf("%s[%d]", name, i)) + } + if int(n) < len(*v) { + *v = (*v)[:int(n)] + } +} +func (v *_XdrVec_1_SCSpecTypeDef) XdrRecurse(x XDR, name string) { + size := XdrSize{Size: uint32(len(*v)), Bound: 1} + x.Marshal(name, &size) + v.XdrMarshalN(x, name, size.Size) +} +func (_XdrVec_1_SCSpecTypeDef) XdrTypeName() string { return "SCSpecTypeDef<>" } +func (v *_XdrVec_1_SCSpecTypeDef) XdrPointer() interface{} { return (*[]SCSpecTypeDef)(v) } +func (v _XdrVec_1_SCSpecTypeDef) XdrValue() interface{} { return ([]SCSpecTypeDef)(v) } +func (v *_XdrVec_1_SCSpecTypeDef) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } + +type XdrType_SCSpecFunctionV0 = *SCSpecFunctionV0 + +func (v *SCSpecFunctionV0) XdrPointer() interface{} { return v } +func (SCSpecFunctionV0) XdrTypeName() string { return "SCSpecFunctionV0" } +func (v SCSpecFunctionV0) XdrValue() interface{} { return v } +func (v *SCSpecFunctionV0) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v *SCSpecFunctionV0) XdrRecurse(x XDR, name string) { + if name != "" { + name = x.Sprintf("%s.", name) + } + x.Marshal(x.Sprintf("%sdoc", name), XdrString{&v.Doc, SC_SPEC_DOC_LIMIT}) + x.Marshal(x.Sprintf("%sname", name), XDR_SCSymbol(&v.Name)) + x.Marshal(x.Sprintf("%sinputs", name), (*_XdrVec_10_SCSpecFunctionInputV0)(&v.Inputs)) + x.Marshal(x.Sprintf("%soutputs", name), (*_XdrVec_1_SCSpecTypeDef)(&v.Outputs)) +} +func XDR_SCSpecFunctionV0(v *SCSpecFunctionV0) *SCSpecFunctionV0 { return v } + +var _XdrNames_SCSpecEntryKind = map[int32]string{ + int32(SC_SPEC_ENTRY_FUNCTION_V0): "SC_SPEC_ENTRY_FUNCTION_V0", + int32(SC_SPEC_ENTRY_UDT_STRUCT_V0): "SC_SPEC_ENTRY_UDT_STRUCT_V0", + int32(SC_SPEC_ENTRY_UDT_UNION_V0): "SC_SPEC_ENTRY_UDT_UNION_V0", + int32(SC_SPEC_ENTRY_UDT_ENUM_V0): "SC_SPEC_ENTRY_UDT_ENUM_V0", + int32(SC_SPEC_ENTRY_UDT_ERROR_ENUM_V0): "SC_SPEC_ENTRY_UDT_ERROR_ENUM_V0", +} +var _XdrValues_SCSpecEntryKind = map[string]int32{ + "SC_SPEC_ENTRY_FUNCTION_V0": int32(SC_SPEC_ENTRY_FUNCTION_V0), + "SC_SPEC_ENTRY_UDT_STRUCT_V0": int32(SC_SPEC_ENTRY_UDT_STRUCT_V0), + "SC_SPEC_ENTRY_UDT_UNION_V0": int32(SC_SPEC_ENTRY_UDT_UNION_V0), + "SC_SPEC_ENTRY_UDT_ENUM_V0": int32(SC_SPEC_ENTRY_UDT_ENUM_V0), + "SC_SPEC_ENTRY_UDT_ERROR_ENUM_V0": int32(SC_SPEC_ENTRY_UDT_ERROR_ENUM_V0), +} + +func (SCSpecEntryKind) XdrEnumNames() map[int32]string { + return _XdrNames_SCSpecEntryKind +} +func (v SCSpecEntryKind) String() string { + if s, ok := _XdrNames_SCSpecEntryKind[int32(v)]; ok { + return s } + return fmt.Sprintf("SCSpecEntryKind#%d", v) } -func (u *XdrAnon_OperationResult_Tr) CreatePassiveSellOfferResult() *ManageSellOfferResult { - switch u.Type { - case CREATE_PASSIVE_SELL_OFFER: - if v, ok := u._u.(*ManageSellOfferResult); ok { - return v - } else { - var zero ManageSellOfferResult - u._u = &zero - return &zero +func (v *SCSpecEntryKind) Scan(ss fmt.ScanState, _ rune) error { + if tok, err := ss.Token(true, XdrSymChar); err != nil { + return err + } else { + stok := string(tok) + if val, ok := _XdrValues_SCSpecEntryKind[stok]; ok { + *v = SCSpecEntryKind(val) + return nil + } else if stok == "SCSpecEntryKind" { + if n, err := fmt.Fscanf(ss, "#%d", (*int32)(v)); n == 1 && err == nil { + return nil + } } - default: - XdrPanic("XdrAnon_OperationResult_Tr.CreatePassiveSellOfferResult accessed when Type == %v", u.Type) - return nil + return XdrError(fmt.Sprintf("%s is not a valid SCSpecEntryKind.", stok)) } } -func (u *XdrAnon_OperationResult_Tr) SetOptionsResult() *SetOptionsResult { - switch u.Type { - case SET_OPTIONS: - if v, ok := u._u.(*SetOptionsResult); ok { +func (v SCSpecEntryKind) GetU32() uint32 { return uint32(v) } +func (v *SCSpecEntryKind) SetU32(n uint32) { *v = SCSpecEntryKind(n) } +func (v *SCSpecEntryKind) XdrPointer() interface{} { return v } +func (SCSpecEntryKind) XdrTypeName() string { return "SCSpecEntryKind" } +func (v SCSpecEntryKind) XdrValue() interface{} { return v } +func (v *SCSpecEntryKind) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } + +type XdrType_SCSpecEntryKind = *SCSpecEntryKind + +func XDR_SCSpecEntryKind(v *SCSpecEntryKind) *SCSpecEntryKind { return v } + +var _XdrTags_SCSpecEntry = map[int32]bool{ + XdrToI32(SC_SPEC_ENTRY_FUNCTION_V0): true, + XdrToI32(SC_SPEC_ENTRY_UDT_STRUCT_V0): true, + XdrToI32(SC_SPEC_ENTRY_UDT_UNION_V0): true, + XdrToI32(SC_SPEC_ENTRY_UDT_ENUM_V0): true, + XdrToI32(SC_SPEC_ENTRY_UDT_ERROR_ENUM_V0): true, +} + +func (_ SCSpecEntry) XdrValidTags() map[int32]bool { + return _XdrTags_SCSpecEntry +} +func (u *SCSpecEntry) FunctionV0() *SCSpecFunctionV0 { + switch u.Kind { + case SC_SPEC_ENTRY_FUNCTION_V0: + if v, ok := u._u.(*SCSpecFunctionV0); ok { return v } else { - var zero SetOptionsResult + var zero SCSpecFunctionV0 u._u = &zero return &zero } default: - XdrPanic("XdrAnon_OperationResult_Tr.SetOptionsResult accessed when Type == %v", u.Type) + XdrPanic("SCSpecEntry.FunctionV0 accessed when Kind == %v", u.Kind) return nil } } -func (u *XdrAnon_OperationResult_Tr) ChangeTrustResult() *ChangeTrustResult { - switch u.Type { - case CHANGE_TRUST: - if v, ok := u._u.(*ChangeTrustResult); ok { +func (u *SCSpecEntry) UdtStructV0() *SCSpecUDTStructV0 { + switch u.Kind { + case SC_SPEC_ENTRY_UDT_STRUCT_V0: + if v, ok := u._u.(*SCSpecUDTStructV0); ok { return v } else { - var zero ChangeTrustResult + var zero SCSpecUDTStructV0 u._u = &zero return &zero } default: - XdrPanic("XdrAnon_OperationResult_Tr.ChangeTrustResult accessed when Type == %v", u.Type) + XdrPanic("SCSpecEntry.UdtStructV0 accessed when Kind == %v", u.Kind) return nil } } -func (u *XdrAnon_OperationResult_Tr) AllowTrustResult() *AllowTrustResult { - switch u.Type { - case ALLOW_TRUST: - if v, ok := u._u.(*AllowTrustResult); ok { +func (u *SCSpecEntry) UdtUnionV0() *SCSpecUDTUnionV0 { + switch u.Kind { + case SC_SPEC_ENTRY_UDT_UNION_V0: + if v, ok := u._u.(*SCSpecUDTUnionV0); ok { return v } else { - var zero AllowTrustResult + var zero SCSpecUDTUnionV0 u._u = &zero return &zero } default: - XdrPanic("XdrAnon_OperationResult_Tr.AllowTrustResult accessed when Type == %v", u.Type) + XdrPanic("SCSpecEntry.UdtUnionV0 accessed when Kind == %v", u.Kind) return nil } } -func (u *XdrAnon_OperationResult_Tr) AccountMergeResult() *AccountMergeResult { - switch u.Type { - case ACCOUNT_MERGE: - if v, ok := u._u.(*AccountMergeResult); ok { +func (u *SCSpecEntry) UdtEnumV0() *SCSpecUDTEnumV0 { + switch u.Kind { + case SC_SPEC_ENTRY_UDT_ENUM_V0: + if v, ok := u._u.(*SCSpecUDTEnumV0); ok { return v } else { - var zero AccountMergeResult + var zero SCSpecUDTEnumV0 u._u = &zero return &zero } default: - XdrPanic("XdrAnon_OperationResult_Tr.AccountMergeResult accessed when Type == %v", u.Type) + XdrPanic("SCSpecEntry.UdtEnumV0 accessed when Kind == %v", u.Kind) return nil } } -func (u *XdrAnon_OperationResult_Tr) InflationResult() *InflationResult { - switch u.Type { - case INFLATION: - if v, ok := u._u.(*InflationResult); ok { +func (u *SCSpecEntry) UdtErrorEnumV0() *SCSpecUDTErrorEnumV0 { + switch u.Kind { + case SC_SPEC_ENTRY_UDT_ERROR_ENUM_V0: + if v, ok := u._u.(*SCSpecUDTErrorEnumV0); ok { return v } else { - var zero InflationResult + var zero SCSpecUDTErrorEnumV0 u._u = &zero return &zero } default: - XdrPanic("XdrAnon_OperationResult_Tr.InflationResult accessed when Type == %v", u.Type) + XdrPanic("SCSpecEntry.UdtErrorEnumV0 accessed when Kind == %v", u.Kind) return nil } } -func (u *XdrAnon_OperationResult_Tr) ManageDataResult() *ManageDataResult { - switch u.Type { - case MANAGE_DATA: - if v, ok := u._u.(*ManageDataResult); ok { - return v - } else { - var zero ManageDataResult - u._u = &zero - return &zero - } - default: - XdrPanic("XdrAnon_OperationResult_Tr.ManageDataResult accessed when Type == %v", u.Type) - return nil +func (u SCSpecEntry) XdrValid() bool { + switch u.Kind { + case SC_SPEC_ENTRY_FUNCTION_V0, SC_SPEC_ENTRY_UDT_STRUCT_V0, SC_SPEC_ENTRY_UDT_UNION_V0, SC_SPEC_ENTRY_UDT_ENUM_V0, SC_SPEC_ENTRY_UDT_ERROR_ENUM_V0: + return true } + return false } -func (u *XdrAnon_OperationResult_Tr) BumpSeqResult() *BumpSequenceResult { - switch u.Type { - case BUMP_SEQUENCE: - if v, ok := u._u.(*BumpSequenceResult); ok { - return v - } else { - var zero BumpSequenceResult - u._u = &zero - return &zero - } - default: - XdrPanic("XdrAnon_OperationResult_Tr.BumpSeqResult accessed when Type == %v", u.Type) - return nil +func (u *SCSpecEntry) XdrUnionTag() XdrNum32 { + return XDR_SCSpecEntryKind(&u.Kind) +} +func (u *SCSpecEntry) XdrUnionTagName() string { + return "Kind" +} +func (u *SCSpecEntry) XdrUnionBody() XdrType { + switch u.Kind { + case SC_SPEC_ENTRY_FUNCTION_V0: + return XDR_SCSpecFunctionV0(u.FunctionV0()) + case SC_SPEC_ENTRY_UDT_STRUCT_V0: + return XDR_SCSpecUDTStructV0(u.UdtStructV0()) + case SC_SPEC_ENTRY_UDT_UNION_V0: + return XDR_SCSpecUDTUnionV0(u.UdtUnionV0()) + case SC_SPEC_ENTRY_UDT_ENUM_V0: + return XDR_SCSpecUDTEnumV0(u.UdtEnumV0()) + case SC_SPEC_ENTRY_UDT_ERROR_ENUM_V0: + return XDR_SCSpecUDTErrorEnumV0(u.UdtErrorEnumV0()) } + return nil } -func (u *XdrAnon_OperationResult_Tr) ManageBuyOfferResult() *ManageBuyOfferResult { - switch u.Type { - case MANAGE_BUY_OFFER: - if v, ok := u._u.(*ManageBuyOfferResult); ok { - return v - } else { - var zero ManageBuyOfferResult - u._u = &zero - return &zero +func (u *SCSpecEntry) XdrUnionBodyName() string { + switch u.Kind { + case SC_SPEC_ENTRY_FUNCTION_V0: + return "FunctionV0" + case SC_SPEC_ENTRY_UDT_STRUCT_V0: + return "UdtStructV0" + case SC_SPEC_ENTRY_UDT_UNION_V0: + return "UdtUnionV0" + case SC_SPEC_ENTRY_UDT_ENUM_V0: + return "UdtEnumV0" + case SC_SPEC_ENTRY_UDT_ERROR_ENUM_V0: + return "UdtErrorEnumV0" + } + return "" +} + +type XdrType_SCSpecEntry = *SCSpecEntry + +func (v *SCSpecEntry) XdrPointer() interface{} { return v } +func (SCSpecEntry) XdrTypeName() string { return "SCSpecEntry" } +func (v SCSpecEntry) XdrValue() interface{} { return v } +func (v *SCSpecEntry) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (u *SCSpecEntry) XdrRecurse(x XDR, name string) { + if name != "" { + name = x.Sprintf("%s.", name) + } + XDR_SCSpecEntryKind(&u.Kind).XdrMarshal(x, x.Sprintf("%skind", name)) + switch u.Kind { + case SC_SPEC_ENTRY_FUNCTION_V0: + x.Marshal(x.Sprintf("%sfunctionV0", name), XDR_SCSpecFunctionV0(u.FunctionV0())) + return + case SC_SPEC_ENTRY_UDT_STRUCT_V0: + x.Marshal(x.Sprintf("%sudtStructV0", name), XDR_SCSpecUDTStructV0(u.UdtStructV0())) + return + case SC_SPEC_ENTRY_UDT_UNION_V0: + x.Marshal(x.Sprintf("%sudtUnionV0", name), XDR_SCSpecUDTUnionV0(u.UdtUnionV0())) + return + case SC_SPEC_ENTRY_UDT_ENUM_V0: + x.Marshal(x.Sprintf("%sudtEnumV0", name), XDR_SCSpecUDTEnumV0(u.UdtEnumV0())) + return + case SC_SPEC_ENTRY_UDT_ERROR_ENUM_V0: + x.Marshal(x.Sprintf("%sudtErrorEnumV0", name), XDR_SCSpecUDTErrorEnumV0(u.UdtErrorEnumV0())) + return + } + XdrPanic("invalid Kind (%v) in SCSpecEntry", u.Kind) +} +func XDR_SCSpecEntry(v *SCSpecEntry) *SCSpecEntry { return v } + +var _XdrNames_SCValType = map[int32]string{ + int32(SCV_BOOL): "SCV_BOOL", + int32(SCV_VOID): "SCV_VOID", + int32(SCV_ERROR): "SCV_ERROR", + int32(SCV_U32): "SCV_U32", + int32(SCV_I32): "SCV_I32", + int32(SCV_U64): "SCV_U64", + int32(SCV_I64): "SCV_I64", + int32(SCV_TIMEPOINT): "SCV_TIMEPOINT", + int32(SCV_DURATION): "SCV_DURATION", + int32(SCV_U128): "SCV_U128", + int32(SCV_I128): "SCV_I128", + int32(SCV_U256): "SCV_U256", + int32(SCV_I256): "SCV_I256", + int32(SCV_BYTES): "SCV_BYTES", + int32(SCV_STRING): "SCV_STRING", + int32(SCV_SYMBOL): "SCV_SYMBOL", + int32(SCV_VEC): "SCV_VEC", + int32(SCV_MAP): "SCV_MAP", + int32(SCV_ADDRESS): "SCV_ADDRESS", + int32(SCV_CONTRACT_INSTANCE): "SCV_CONTRACT_INSTANCE", + int32(SCV_LEDGER_KEY_CONTRACT_INSTANCE): "SCV_LEDGER_KEY_CONTRACT_INSTANCE", + int32(SCV_LEDGER_KEY_NONCE): "SCV_LEDGER_KEY_NONCE", +} +var _XdrValues_SCValType = map[string]int32{ + "SCV_BOOL": int32(SCV_BOOL), + "SCV_VOID": int32(SCV_VOID), + "SCV_ERROR": int32(SCV_ERROR), + "SCV_U32": int32(SCV_U32), + "SCV_I32": int32(SCV_I32), + "SCV_U64": int32(SCV_U64), + "SCV_I64": int32(SCV_I64), + "SCV_TIMEPOINT": int32(SCV_TIMEPOINT), + "SCV_DURATION": int32(SCV_DURATION), + "SCV_U128": int32(SCV_U128), + "SCV_I128": int32(SCV_I128), + "SCV_U256": int32(SCV_U256), + "SCV_I256": int32(SCV_I256), + "SCV_BYTES": int32(SCV_BYTES), + "SCV_STRING": int32(SCV_STRING), + "SCV_SYMBOL": int32(SCV_SYMBOL), + "SCV_VEC": int32(SCV_VEC), + "SCV_MAP": int32(SCV_MAP), + "SCV_ADDRESS": int32(SCV_ADDRESS), + "SCV_CONTRACT_INSTANCE": int32(SCV_CONTRACT_INSTANCE), + "SCV_LEDGER_KEY_CONTRACT_INSTANCE": int32(SCV_LEDGER_KEY_CONTRACT_INSTANCE), + "SCV_LEDGER_KEY_NONCE": int32(SCV_LEDGER_KEY_NONCE), +} + +func (SCValType) XdrEnumNames() map[int32]string { + return _XdrNames_SCValType +} +func (v SCValType) String() string { + if s, ok := _XdrNames_SCValType[int32(v)]; ok { + return s + } + return fmt.Sprintf("SCValType#%d", v) +} +func (v *SCValType) Scan(ss fmt.ScanState, _ rune) error { + if tok, err := ss.Token(true, XdrSymChar); err != nil { + return err + } else { + stok := string(tok) + if val, ok := _XdrValues_SCValType[stok]; ok { + *v = SCValType(val) + return nil + } else if stok == "SCValType" { + if n, err := fmt.Fscanf(ss, "#%d", (*int32)(v)); n == 1 && err == nil { + return nil + } } - default: - XdrPanic("XdrAnon_OperationResult_Tr.ManageBuyOfferResult accessed when Type == %v", u.Type) - return nil + return XdrError(fmt.Sprintf("%s is not a valid SCValType.", stok)) + } +} +func (v SCValType) GetU32() uint32 { return uint32(v) } +func (v *SCValType) SetU32(n uint32) { *v = SCValType(n) } +func (v *SCValType) XdrPointer() interface{} { return v } +func (SCValType) XdrTypeName() string { return "SCValType" } +func (v SCValType) XdrValue() interface{} { return v } +func (v *SCValType) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } + +type XdrType_SCValType = *SCValType + +func XDR_SCValType(v *SCValType) *SCValType { return v } + +var _XdrComments_SCValType = map[int32]string{ + int32(SCV_U32): "32 bits is the smallest type in WASM or XDR; no need for u8/u16.", + int32(SCV_U64): "64 bits is naturally supported by both WASM and XDR also.", + int32(SCV_TIMEPOINT): "Time-related u64 subtypes with their own functions and formatting.", + int32(SCV_U128): "128 bits is naturally supported by Rust and we use it for Soroban fixed-point arithmetic prices / balances / similar \"quantities\". These are represented in XDR as a pair of 2 u64s.", + int32(SCV_U256): "256 bits is the size of sha256 output, ed25519 keys, and the EVM machine word, so for interop use we include this even though it requires a small amount of Rust guest and/or host library code.", + int32(SCV_BYTES): "Bytes come in 3 flavors, 2 of which have meaningfully different formatting and validity-checking / domain-restriction.", + int32(SCV_VEC): "Vecs and maps are just polymorphic containers of other ScVals.", + int32(SCV_ADDRESS): "Address is the universal identifier for contracts and classic accounts.", + int32(SCV_CONTRACT_INSTANCE): "The following are the internal SCVal variants that are not exposed to the contracts.", + int32(SCV_LEDGER_KEY_CONTRACT_INSTANCE): "SCV_LEDGER_KEY_CONTRACT_INSTANCE and SCV_LEDGER_KEY_NONCE are unique symbolic SCVals used as the key for ledger entries for a contract's instance and an address' nonce, respectively.", +} + +func (e SCValType) XdrEnumComments() map[int32]string { + return _XdrComments_SCValType +} + +var _XdrNames_SCErrorType = map[int32]string{ + int32(SCE_CONTRACT): "SCE_CONTRACT", + int32(SCE_WASM_VM): "SCE_WASM_VM", + int32(SCE_CONTEXT): "SCE_CONTEXT", + int32(SCE_STORAGE): "SCE_STORAGE", + int32(SCE_OBJECT): "SCE_OBJECT", + int32(SCE_CRYPTO): "SCE_CRYPTO", + int32(SCE_EVENTS): "SCE_EVENTS", + int32(SCE_BUDGET): "SCE_BUDGET", + int32(SCE_VALUE): "SCE_VALUE", + int32(SCE_AUTH): "SCE_AUTH", +} +var _XdrValues_SCErrorType = map[string]int32{ + "SCE_CONTRACT": int32(SCE_CONTRACT), + "SCE_WASM_VM": int32(SCE_WASM_VM), + "SCE_CONTEXT": int32(SCE_CONTEXT), + "SCE_STORAGE": int32(SCE_STORAGE), + "SCE_OBJECT": int32(SCE_OBJECT), + "SCE_CRYPTO": int32(SCE_CRYPTO), + "SCE_EVENTS": int32(SCE_EVENTS), + "SCE_BUDGET": int32(SCE_BUDGET), + "SCE_VALUE": int32(SCE_VALUE), + "SCE_AUTH": int32(SCE_AUTH), +} + +func (SCErrorType) XdrEnumNames() map[int32]string { + return _XdrNames_SCErrorType +} +func (v SCErrorType) String() string { + if s, ok := _XdrNames_SCErrorType[int32(v)]; ok { + return s } + return fmt.Sprintf("SCErrorType#%d", v) } -func (u *XdrAnon_OperationResult_Tr) PathPaymentStrictSendResult() *PathPaymentStrictSendResult { - switch u.Type { - case PATH_PAYMENT_STRICT_SEND: - if v, ok := u._u.(*PathPaymentStrictSendResult); ok { - return v - } else { - var zero PathPaymentStrictSendResult - u._u = &zero - return &zero +func (v *SCErrorType) Scan(ss fmt.ScanState, _ rune) error { + if tok, err := ss.Token(true, XdrSymChar); err != nil { + return err + } else { + stok := string(tok) + if val, ok := _XdrValues_SCErrorType[stok]; ok { + *v = SCErrorType(val) + return nil + } else if stok == "SCErrorType" { + if n, err := fmt.Fscanf(ss, "#%d", (*int32)(v)); n == 1 && err == nil { + return nil + } } - default: - XdrPanic("XdrAnon_OperationResult_Tr.PathPaymentStrictSendResult accessed when Type == %v", u.Type) - return nil + return XdrError(fmt.Sprintf("%s is not a valid SCErrorType.", stok)) + } +} +func (v SCErrorType) GetU32() uint32 { return uint32(v) } +func (v *SCErrorType) SetU32(n uint32) { *v = SCErrorType(n) } +func (v *SCErrorType) XdrPointer() interface{} { return v } +func (SCErrorType) XdrTypeName() string { return "SCErrorType" } +func (v SCErrorType) XdrValue() interface{} { return v } +func (v *SCErrorType) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } + +type XdrType_SCErrorType = *SCErrorType + +func XDR_SCErrorType(v *SCErrorType) *SCErrorType { return v } + +var _XdrComments_SCErrorType = map[int32]string{ + int32(SCE_CONTRACT): "Contract-specific, user-defined codes.", + int32(SCE_WASM_VM): "Errors while interpreting WASM bytecode.", + int32(SCE_CONTEXT): "Errors in the contract's host context.", + int32(SCE_STORAGE): "Errors accessing host storage.", + int32(SCE_OBJECT): "Errors working with host objects.", + int32(SCE_CRYPTO): "Errors in cryptographic operations.", + int32(SCE_EVENTS): "Errors while emitting events.", + int32(SCE_BUDGET): "Errors relating to budget limits.", + int32(SCE_VALUE): "Errors working with host values or SCVals.", + int32(SCE_AUTH): "Errors from the authentication subsystem.", +} + +func (e SCErrorType) XdrEnumComments() map[int32]string { + return _XdrComments_SCErrorType +} + +var _XdrNames_SCErrorCode = map[int32]string{ + int32(SCEC_ARITH_DOMAIN): "SCEC_ARITH_DOMAIN", + int32(SCEC_INDEX_BOUNDS): "SCEC_INDEX_BOUNDS", + int32(SCEC_INVALID_INPUT): "SCEC_INVALID_INPUT", + int32(SCEC_MISSING_VALUE): "SCEC_MISSING_VALUE", + int32(SCEC_EXISTING_VALUE): "SCEC_EXISTING_VALUE", + int32(SCEC_EXCEEDED_LIMIT): "SCEC_EXCEEDED_LIMIT", + int32(SCEC_INVALID_ACTION): "SCEC_INVALID_ACTION", + int32(SCEC_INTERNAL_ERROR): "SCEC_INTERNAL_ERROR", + int32(SCEC_UNEXPECTED_TYPE): "SCEC_UNEXPECTED_TYPE", + int32(SCEC_UNEXPECTED_SIZE): "SCEC_UNEXPECTED_SIZE", +} +var _XdrValues_SCErrorCode = map[string]int32{ + "SCEC_ARITH_DOMAIN": int32(SCEC_ARITH_DOMAIN), + "SCEC_INDEX_BOUNDS": int32(SCEC_INDEX_BOUNDS), + "SCEC_INVALID_INPUT": int32(SCEC_INVALID_INPUT), + "SCEC_MISSING_VALUE": int32(SCEC_MISSING_VALUE), + "SCEC_EXISTING_VALUE": int32(SCEC_EXISTING_VALUE), + "SCEC_EXCEEDED_LIMIT": int32(SCEC_EXCEEDED_LIMIT), + "SCEC_INVALID_ACTION": int32(SCEC_INVALID_ACTION), + "SCEC_INTERNAL_ERROR": int32(SCEC_INTERNAL_ERROR), + "SCEC_UNEXPECTED_TYPE": int32(SCEC_UNEXPECTED_TYPE), + "SCEC_UNEXPECTED_SIZE": int32(SCEC_UNEXPECTED_SIZE), +} + +func (SCErrorCode) XdrEnumNames() map[int32]string { + return _XdrNames_SCErrorCode +} +func (v SCErrorCode) String() string { + if s, ok := _XdrNames_SCErrorCode[int32(v)]; ok { + return s } + return fmt.Sprintf("SCErrorCode#%d", v) } -func (u *XdrAnon_OperationResult_Tr) CreateClaimableBalanceResult() *CreateClaimableBalanceResult { - switch u.Type { - case CREATE_CLAIMABLE_BALANCE: - if v, ok := u._u.(*CreateClaimableBalanceResult); ok { - return v - } else { - var zero CreateClaimableBalanceResult - u._u = &zero - return &zero +func (v *SCErrorCode) Scan(ss fmt.ScanState, _ rune) error { + if tok, err := ss.Token(true, XdrSymChar); err != nil { + return err + } else { + stok := string(tok) + if val, ok := _XdrValues_SCErrorCode[stok]; ok { + *v = SCErrorCode(val) + return nil + } else if stok == "SCErrorCode" { + if n, err := fmt.Fscanf(ss, "#%d", (*int32)(v)); n == 1 && err == nil { + return nil + } } - default: - XdrPanic("XdrAnon_OperationResult_Tr.CreateClaimableBalanceResult accessed when Type == %v", u.Type) - return nil + return XdrError(fmt.Sprintf("%s is not a valid SCErrorCode.", stok)) } } -func (u *XdrAnon_OperationResult_Tr) ClaimClaimableBalanceResult() *ClaimClaimableBalanceResult { +func (v SCErrorCode) GetU32() uint32 { return uint32(v) } +func (v *SCErrorCode) SetU32(n uint32) { *v = SCErrorCode(n) } +func (v *SCErrorCode) XdrPointer() interface{} { return v } +func (SCErrorCode) XdrTypeName() string { return "SCErrorCode" } +func (v SCErrorCode) XdrValue() interface{} { return v } +func (v *SCErrorCode) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } + +type XdrType_SCErrorCode = *SCErrorCode + +func XDR_SCErrorCode(v *SCErrorCode) *SCErrorCode { return v } + +var _XdrComments_SCErrorCode = map[int32]string{ + int32(SCEC_ARITH_DOMAIN): "Some arithmetic was undefined (overflow, divide-by-zero).", + int32(SCEC_INDEX_BOUNDS): "Something was indexed beyond its bounds.", + int32(SCEC_INVALID_INPUT): "User provided some otherwise-bad data.", + int32(SCEC_MISSING_VALUE): "Some value was required but not provided.", + int32(SCEC_EXISTING_VALUE): "Some value was provided where not allowed.", + int32(SCEC_EXCEEDED_LIMIT): "Some arbitrary limit -- gas or otherwise -- was hit.", + int32(SCEC_INVALID_ACTION): "Data was valid but action requested was not.", + int32(SCEC_INTERNAL_ERROR): "The host detected an error in its own logic.", + int32(SCEC_UNEXPECTED_TYPE): "Some type wasn't as expected.", + int32(SCEC_UNEXPECTED_SIZE): "Something's size wasn't as expected.", +} + +func (e SCErrorCode) XdrEnumComments() map[int32]string { + return _XdrComments_SCErrorCode +} + +var _XdrTags_SCError = map[int32]bool{ + XdrToI32(SCE_CONTRACT): true, + XdrToI32(SCE_WASM_VM): true, + XdrToI32(SCE_CONTEXT): true, + XdrToI32(SCE_STORAGE): true, + XdrToI32(SCE_OBJECT): true, + XdrToI32(SCE_CRYPTO): true, + XdrToI32(SCE_EVENTS): true, + XdrToI32(SCE_BUDGET): true, + XdrToI32(SCE_VALUE): true, + XdrToI32(SCE_AUTH): true, +} + +func (_ SCError) XdrValidTags() map[int32]bool { + return _XdrTags_SCError +} +func (u *SCError) ContractCode() *Uint32 { switch u.Type { - case CLAIM_CLAIMABLE_BALANCE: - if v, ok := u._u.(*ClaimClaimableBalanceResult); ok { + case SCE_CONTRACT: + if v, ok := u._u.(*Uint32); ok { return v } else { - var zero ClaimClaimableBalanceResult + var zero Uint32 u._u = &zero return &zero } default: - XdrPanic("XdrAnon_OperationResult_Tr.ClaimClaimableBalanceResult accessed when Type == %v", u.Type) + XdrPanic("SCError.ContractCode accessed when Type == %v", u.Type) return nil } } -func (u *XdrAnon_OperationResult_Tr) BeginSponsoringFutureReservesResult() *BeginSponsoringFutureReservesResult { +func (u *SCError) Code() *SCErrorCode { switch u.Type { - case BEGIN_SPONSORING_FUTURE_RESERVES: - if v, ok := u._u.(*BeginSponsoringFutureReservesResult); ok { + case SCE_WASM_VM, SCE_CONTEXT, SCE_STORAGE, SCE_OBJECT, SCE_CRYPTO, SCE_EVENTS, SCE_BUDGET, SCE_VALUE, SCE_AUTH: + if v, ok := u._u.(*SCErrorCode); ok { return v } else { - var zero BeginSponsoringFutureReservesResult + var zero SCErrorCode u._u = &zero return &zero } default: - XdrPanic("XdrAnon_OperationResult_Tr.BeginSponsoringFutureReservesResult accessed when Type == %v", u.Type) + XdrPanic("SCError.Code accessed when Type == %v", u.Type) return nil } } -func (u *XdrAnon_OperationResult_Tr) EndSponsoringFutureReservesResult() *EndSponsoringFutureReservesResult { +func (u SCError) XdrValid() bool { switch u.Type { - case END_SPONSORING_FUTURE_RESERVES: - if v, ok := u._u.(*EndSponsoringFutureReservesResult); ok { - return v - } else { - var zero EndSponsoringFutureReservesResult - u._u = &zero - return &zero - } - default: - XdrPanic("XdrAnon_OperationResult_Tr.EndSponsoringFutureReservesResult accessed when Type == %v", u.Type) - return nil + case SCE_CONTRACT, SCE_WASM_VM, SCE_CONTEXT, SCE_STORAGE, SCE_OBJECT, SCE_CRYPTO, SCE_EVENTS, SCE_BUDGET, SCE_VALUE, SCE_AUTH: + return true } + return false } -func (u *XdrAnon_OperationResult_Tr) RevokeSponsorshipResult() *RevokeSponsorshipResult { +func (u *SCError) XdrUnionTag() XdrNum32 { + return XDR_SCErrorType(&u.Type) +} +func (u *SCError) XdrUnionTagName() string { + return "Type" +} +func (u *SCError) XdrUnionBody() XdrType { switch u.Type { - case REVOKE_SPONSORSHIP: - if v, ok := u._u.(*RevokeSponsorshipResult); ok { - return v - } else { - var zero RevokeSponsorshipResult - u._u = &zero - return &zero - } - default: - XdrPanic("XdrAnon_OperationResult_Tr.RevokeSponsorshipResult accessed when Type == %v", u.Type) - return nil + case SCE_CONTRACT: + return XDR_Uint32(u.ContractCode()) + case SCE_WASM_VM, SCE_CONTEXT, SCE_STORAGE, SCE_OBJECT, SCE_CRYPTO, SCE_EVENTS, SCE_BUDGET, SCE_VALUE, SCE_AUTH: + return XDR_SCErrorCode(u.Code()) } + return nil } -func (u *XdrAnon_OperationResult_Tr) ClawbackResult() *ClawbackResult { +func (u *SCError) XdrUnionBodyName() string { switch u.Type { - case CLAWBACK: - if v, ok := u._u.(*ClawbackResult); ok { - return v - } else { - var zero ClawbackResult - u._u = &zero - return &zero - } - default: - XdrPanic("XdrAnon_OperationResult_Tr.ClawbackResult accessed when Type == %v", u.Type) - return nil + case SCE_CONTRACT: + return "ContractCode" + case SCE_WASM_VM, SCE_CONTEXT, SCE_STORAGE, SCE_OBJECT, SCE_CRYPTO, SCE_EVENTS, SCE_BUDGET, SCE_VALUE, SCE_AUTH: + return "Code" } + return "" } -func (u *XdrAnon_OperationResult_Tr) ClawbackClaimableBalanceResult() *ClawbackClaimableBalanceResult { + +type XdrType_SCError = *SCError + +func (v *SCError) XdrPointer() interface{} { return v } +func (SCError) XdrTypeName() string { return "SCError" } +func (v SCError) XdrValue() interface{} { return v } +func (v *SCError) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (u *SCError) XdrRecurse(x XDR, name string) { + if name != "" { + name = x.Sprintf("%s.", name) + } + XDR_SCErrorType(&u.Type).XdrMarshal(x, x.Sprintf("%stype", name)) switch u.Type { - case CLAWBACK_CLAIMABLE_BALANCE: - if v, ok := u._u.(*ClawbackClaimableBalanceResult); ok { - return v - } else { - var zero ClawbackClaimableBalanceResult - u._u = &zero - return &zero - } - default: - XdrPanic("XdrAnon_OperationResult_Tr.ClawbackClaimableBalanceResult accessed when Type == %v", u.Type) - return nil + case SCE_CONTRACT: + x.Marshal(x.Sprintf("%scontractCode", name), XDR_Uint32(u.ContractCode())) + return + case SCE_WASM_VM, SCE_CONTEXT, SCE_STORAGE, SCE_OBJECT, SCE_CRYPTO, SCE_EVENTS, SCE_BUDGET, SCE_VALUE, SCE_AUTH: + x.Marshal(x.Sprintf("%scode", name), XDR_SCErrorCode(u.Code())) + return + } + XdrPanic("invalid Type (%v) in SCError", u.Type) +} +func XDR_SCError(v *SCError) *SCError { return v } + +type XdrType_UInt128Parts = *UInt128Parts + +func (v *UInt128Parts) XdrPointer() interface{} { return v } +func (UInt128Parts) XdrTypeName() string { return "UInt128Parts" } +func (v UInt128Parts) XdrValue() interface{} { return v } +func (v *UInt128Parts) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v *UInt128Parts) XdrRecurse(x XDR, name string) { + if name != "" { + name = x.Sprintf("%s.", name) + } + x.Marshal(x.Sprintf("%shi", name), XDR_Uint64(&v.Hi)) + x.Marshal(x.Sprintf("%slo", name), XDR_Uint64(&v.Lo)) +} +func XDR_UInt128Parts(v *UInt128Parts) *UInt128Parts { return v } + +type XdrType_Int128Parts = *Int128Parts + +func (v *Int128Parts) XdrPointer() interface{} { return v } +func (Int128Parts) XdrTypeName() string { return "Int128Parts" } +func (v Int128Parts) XdrValue() interface{} { return v } +func (v *Int128Parts) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v *Int128Parts) XdrRecurse(x XDR, name string) { + if name != "" { + name = x.Sprintf("%s.", name) + } + x.Marshal(x.Sprintf("%shi", name), XDR_Int64(&v.Hi)) + x.Marshal(x.Sprintf("%slo", name), XDR_Uint64(&v.Lo)) +} +func XDR_Int128Parts(v *Int128Parts) *Int128Parts { return v } + +type XdrType_UInt256Parts = *UInt256Parts + +func (v *UInt256Parts) XdrPointer() interface{} { return v } +func (UInt256Parts) XdrTypeName() string { return "UInt256Parts" } +func (v UInt256Parts) XdrValue() interface{} { return v } +func (v *UInt256Parts) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v *UInt256Parts) XdrRecurse(x XDR, name string) { + if name != "" { + name = x.Sprintf("%s.", name) } + x.Marshal(x.Sprintf("%shi_hi", name), XDR_Uint64(&v.Hi_hi)) + x.Marshal(x.Sprintf("%shi_lo", name), XDR_Uint64(&v.Hi_lo)) + x.Marshal(x.Sprintf("%slo_hi", name), XDR_Uint64(&v.Lo_hi)) + x.Marshal(x.Sprintf("%slo_lo", name), XDR_Uint64(&v.Lo_lo)) } -func (u *XdrAnon_OperationResult_Tr) SetTrustLineFlagsResult() *SetTrustLineFlagsResult { - switch u.Type { - case SET_TRUST_LINE_FLAGS: - if v, ok := u._u.(*SetTrustLineFlagsResult); ok { - return v - } else { - var zero SetTrustLineFlagsResult - u._u = &zero - return &zero - } - default: - XdrPanic("XdrAnon_OperationResult_Tr.SetTrustLineFlagsResult accessed when Type == %v", u.Type) - return nil +func XDR_UInt256Parts(v *UInt256Parts) *UInt256Parts { return v } + +type XdrType_Int256Parts = *Int256Parts + +func (v *Int256Parts) XdrPointer() interface{} { return v } +func (Int256Parts) XdrTypeName() string { return "Int256Parts" } +func (v Int256Parts) XdrValue() interface{} { return v } +func (v *Int256Parts) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v *Int256Parts) XdrRecurse(x XDR, name string) { + if name != "" { + name = x.Sprintf("%s.", name) } + x.Marshal(x.Sprintf("%shi_hi", name), XDR_Int64(&v.Hi_hi)) + x.Marshal(x.Sprintf("%shi_lo", name), XDR_Uint64(&v.Hi_lo)) + x.Marshal(x.Sprintf("%slo_hi", name), XDR_Uint64(&v.Lo_hi)) + x.Marshal(x.Sprintf("%slo_lo", name), XDR_Uint64(&v.Lo_lo)) } -func (u *XdrAnon_OperationResult_Tr) LiquidityPoolDepositResult() *LiquidityPoolDepositResult { - switch u.Type { - case LIQUIDITY_POOL_DEPOSIT: - if v, ok := u._u.(*LiquidityPoolDepositResult); ok { - return v - } else { - var zero LiquidityPoolDepositResult - u._u = &zero - return &zero +func XDR_Int256Parts(v *Int256Parts) *Int256Parts { return v } + +var _XdrNames_ContractExecutableType = map[int32]string{ + int32(CONTRACT_EXECUTABLE_WASM): "CONTRACT_EXECUTABLE_WASM", + int32(CONTRACT_EXECUTABLE_STELLAR_ASSET): "CONTRACT_EXECUTABLE_STELLAR_ASSET", +} +var _XdrValues_ContractExecutableType = map[string]int32{ + "CONTRACT_EXECUTABLE_WASM": int32(CONTRACT_EXECUTABLE_WASM), + "CONTRACT_EXECUTABLE_STELLAR_ASSET": int32(CONTRACT_EXECUTABLE_STELLAR_ASSET), +} + +func (ContractExecutableType) XdrEnumNames() map[int32]string { + return _XdrNames_ContractExecutableType +} +func (v ContractExecutableType) String() string { + if s, ok := _XdrNames_ContractExecutableType[int32(v)]; ok { + return s + } + return fmt.Sprintf("ContractExecutableType#%d", v) +} +func (v *ContractExecutableType) Scan(ss fmt.ScanState, _ rune) error { + if tok, err := ss.Token(true, XdrSymChar); err != nil { + return err + } else { + stok := string(tok) + if val, ok := _XdrValues_ContractExecutableType[stok]; ok { + *v = ContractExecutableType(val) + return nil + } else if stok == "ContractExecutableType" { + if n, err := fmt.Fscanf(ss, "#%d", (*int32)(v)); n == 1 && err == nil { + return nil + } } - default: - XdrPanic("XdrAnon_OperationResult_Tr.LiquidityPoolDepositResult accessed when Type == %v", u.Type) - return nil + return XdrError(fmt.Sprintf("%s is not a valid ContractExecutableType.", stok)) } } -func (u *XdrAnon_OperationResult_Tr) LiquidityPoolWithdrawResult() *LiquidityPoolWithdrawResult { +func (v ContractExecutableType) GetU32() uint32 { return uint32(v) } +func (v *ContractExecutableType) SetU32(n uint32) { *v = ContractExecutableType(n) } +func (v *ContractExecutableType) XdrPointer() interface{} { return v } +func (ContractExecutableType) XdrTypeName() string { return "ContractExecutableType" } +func (v ContractExecutableType) XdrValue() interface{} { return v } +func (v *ContractExecutableType) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } + +type XdrType_ContractExecutableType = *ContractExecutableType + +func XDR_ContractExecutableType(v *ContractExecutableType) *ContractExecutableType { return v } + +var _XdrTags_ContractExecutable = map[int32]bool{ + XdrToI32(CONTRACT_EXECUTABLE_WASM): true, + XdrToI32(CONTRACT_EXECUTABLE_STELLAR_ASSET): true, +} + +func (_ ContractExecutable) XdrValidTags() map[int32]bool { + return _XdrTags_ContractExecutable +} +func (u *ContractExecutable) Wasm_hash() *Hash { switch u.Type { - case LIQUIDITY_POOL_WITHDRAW: - if v, ok := u._u.(*LiquidityPoolWithdrawResult); ok { + case CONTRACT_EXECUTABLE_WASM: + if v, ok := u._u.(*Hash); ok { return v } else { - var zero LiquidityPoolWithdrawResult + var zero Hash u._u = &zero return &zero } default: - XdrPanic("XdrAnon_OperationResult_Tr.LiquidityPoolWithdrawResult accessed when Type == %v", u.Type) + XdrPanic("ContractExecutable.Wasm_hash accessed when Type == %v", u.Type) return nil } } -func (u XdrAnon_OperationResult_Tr) XdrValid() bool { +func (u ContractExecutable) XdrValid() bool { switch u.Type { - case CREATE_ACCOUNT, PAYMENT, PATH_PAYMENT_STRICT_RECEIVE, MANAGE_SELL_OFFER, CREATE_PASSIVE_SELL_OFFER, SET_OPTIONS, CHANGE_TRUST, ALLOW_TRUST, ACCOUNT_MERGE, INFLATION, MANAGE_DATA, BUMP_SEQUENCE, MANAGE_BUY_OFFER, PATH_PAYMENT_STRICT_SEND, CREATE_CLAIMABLE_BALANCE, CLAIM_CLAIMABLE_BALANCE, BEGIN_SPONSORING_FUTURE_RESERVES, END_SPONSORING_FUTURE_RESERVES, REVOKE_SPONSORSHIP, CLAWBACK, CLAWBACK_CLAIMABLE_BALANCE, SET_TRUST_LINE_FLAGS, LIQUIDITY_POOL_DEPOSIT, LIQUIDITY_POOL_WITHDRAW: + case CONTRACT_EXECUTABLE_WASM, CONTRACT_EXECUTABLE_STELLAR_ASSET: return true } return false } -func (u *XdrAnon_OperationResult_Tr) XdrUnionTag() XdrNum32 { - return XDR_OperationType(&u.Type) +func (u *ContractExecutable) XdrUnionTag() XdrNum32 { + return XDR_ContractExecutableType(&u.Type) } -func (u *XdrAnon_OperationResult_Tr) XdrUnionTagName() string { +func (u *ContractExecutable) XdrUnionTagName() string { return "Type" } -func (u *XdrAnon_OperationResult_Tr) XdrUnionBody() XdrType { +func (u *ContractExecutable) XdrUnionBody() XdrType { switch u.Type { - case CREATE_ACCOUNT: - return XDR_CreateAccountResult(u.CreateAccountResult()) - case PAYMENT: - return XDR_PaymentResult(u.PaymentResult()) - case PATH_PAYMENT_STRICT_RECEIVE: - return XDR_PathPaymentStrictReceiveResult(u.PathPaymentStrictReceiveResult()) - case MANAGE_SELL_OFFER: - return XDR_ManageSellOfferResult(u.ManageSellOfferResult()) - case CREATE_PASSIVE_SELL_OFFER: - return XDR_ManageSellOfferResult(u.CreatePassiveSellOfferResult()) - case SET_OPTIONS: - return XDR_SetOptionsResult(u.SetOptionsResult()) - case CHANGE_TRUST: - return XDR_ChangeTrustResult(u.ChangeTrustResult()) - case ALLOW_TRUST: - return XDR_AllowTrustResult(u.AllowTrustResult()) - case ACCOUNT_MERGE: - return XDR_AccountMergeResult(u.AccountMergeResult()) - case INFLATION: - return XDR_InflationResult(u.InflationResult()) - case MANAGE_DATA: - return XDR_ManageDataResult(u.ManageDataResult()) - case BUMP_SEQUENCE: - return XDR_BumpSequenceResult(u.BumpSeqResult()) - case MANAGE_BUY_OFFER: - return XDR_ManageBuyOfferResult(u.ManageBuyOfferResult()) - case PATH_PAYMENT_STRICT_SEND: - return XDR_PathPaymentStrictSendResult(u.PathPaymentStrictSendResult()) - case CREATE_CLAIMABLE_BALANCE: - return XDR_CreateClaimableBalanceResult(u.CreateClaimableBalanceResult()) - case CLAIM_CLAIMABLE_BALANCE: - return XDR_ClaimClaimableBalanceResult(u.ClaimClaimableBalanceResult()) - case BEGIN_SPONSORING_FUTURE_RESERVES: - return XDR_BeginSponsoringFutureReservesResult(u.BeginSponsoringFutureReservesResult()) - case END_SPONSORING_FUTURE_RESERVES: - return XDR_EndSponsoringFutureReservesResult(u.EndSponsoringFutureReservesResult()) - case REVOKE_SPONSORSHIP: - return XDR_RevokeSponsorshipResult(u.RevokeSponsorshipResult()) - case CLAWBACK: - return XDR_ClawbackResult(u.ClawbackResult()) - case CLAWBACK_CLAIMABLE_BALANCE: - return XDR_ClawbackClaimableBalanceResult(u.ClawbackClaimableBalanceResult()) - case SET_TRUST_LINE_FLAGS: - return XDR_SetTrustLineFlagsResult(u.SetTrustLineFlagsResult()) - case LIQUIDITY_POOL_DEPOSIT: - return XDR_LiquidityPoolDepositResult(u.LiquidityPoolDepositResult()) - case LIQUIDITY_POOL_WITHDRAW: - return XDR_LiquidityPoolWithdrawResult(u.LiquidityPoolWithdrawResult()) + case CONTRACT_EXECUTABLE_WASM: + return XDR_Hash(u.Wasm_hash()) + case CONTRACT_EXECUTABLE_STELLAR_ASSET: + return nil } return nil } -func (u *XdrAnon_OperationResult_Tr) XdrUnionBodyName() string { +func (u *ContractExecutable) XdrUnionBodyName() string { switch u.Type { - case CREATE_ACCOUNT: - return "CreateAccountResult" - case PAYMENT: - return "PaymentResult" - case PATH_PAYMENT_STRICT_RECEIVE: - return "PathPaymentStrictReceiveResult" - case MANAGE_SELL_OFFER: - return "ManageSellOfferResult" - case CREATE_PASSIVE_SELL_OFFER: - return "CreatePassiveSellOfferResult" - case SET_OPTIONS: - return "SetOptionsResult" - case CHANGE_TRUST: - return "ChangeTrustResult" - case ALLOW_TRUST: - return "AllowTrustResult" - case ACCOUNT_MERGE: - return "AccountMergeResult" - case INFLATION: - return "InflationResult" - case MANAGE_DATA: - return "ManageDataResult" - case BUMP_SEQUENCE: - return "BumpSeqResult" - case MANAGE_BUY_OFFER: - return "ManageBuyOfferResult" - case PATH_PAYMENT_STRICT_SEND: - return "PathPaymentStrictSendResult" - case CREATE_CLAIMABLE_BALANCE: - return "CreateClaimableBalanceResult" - case CLAIM_CLAIMABLE_BALANCE: - return "ClaimClaimableBalanceResult" - case BEGIN_SPONSORING_FUTURE_RESERVES: - return "BeginSponsoringFutureReservesResult" - case END_SPONSORING_FUTURE_RESERVES: - return "EndSponsoringFutureReservesResult" - case REVOKE_SPONSORSHIP: - return "RevokeSponsorshipResult" - case CLAWBACK: - return "ClawbackResult" - case CLAWBACK_CLAIMABLE_BALANCE: - return "ClawbackClaimableBalanceResult" - case SET_TRUST_LINE_FLAGS: - return "SetTrustLineFlagsResult" - case LIQUIDITY_POOL_DEPOSIT: - return "LiquidityPoolDepositResult" - case LIQUIDITY_POOL_WITHDRAW: - return "LiquidityPoolWithdrawResult" + case CONTRACT_EXECUTABLE_WASM: + return "Wasm_hash" + case CONTRACT_EXECUTABLE_STELLAR_ASSET: + return "" } return "" } -type XdrType_XdrAnon_OperationResult_Tr = *XdrAnon_OperationResult_Tr +type XdrType_ContractExecutable = *ContractExecutable -func (v *XdrAnon_OperationResult_Tr) XdrPointer() interface{} { return v } -func (XdrAnon_OperationResult_Tr) XdrTypeName() string { return "XdrAnon_OperationResult_Tr" } -func (v XdrAnon_OperationResult_Tr) XdrValue() interface{} { return v } -func (v *XdrAnon_OperationResult_Tr) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -func (u *XdrAnon_OperationResult_Tr) XdrRecurse(x XDR, name string) { +func (v *ContractExecutable) XdrPointer() interface{} { return v } +func (ContractExecutable) XdrTypeName() string { return "ContractExecutable" } +func (v ContractExecutable) XdrValue() interface{} { return v } +func (v *ContractExecutable) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (u *ContractExecutable) XdrRecurse(x XDR, name string) { if name != "" { name = x.Sprintf("%s.", name) } - XDR_OperationType(&u.Type).XdrMarshal(x, x.Sprintf("%stype", name)) + XDR_ContractExecutableType(&u.Type).XdrMarshal(x, x.Sprintf("%stype", name)) switch u.Type { - case CREATE_ACCOUNT: - x.Marshal(x.Sprintf("%screateAccountResult", name), XDR_CreateAccountResult(u.CreateAccountResult())) - return - case PAYMENT: - x.Marshal(x.Sprintf("%spaymentResult", name), XDR_PaymentResult(u.PaymentResult())) - return - case PATH_PAYMENT_STRICT_RECEIVE: - x.Marshal(x.Sprintf("%spathPaymentStrictReceiveResult", name), XDR_PathPaymentStrictReceiveResult(u.PathPaymentStrictReceiveResult())) - return - case MANAGE_SELL_OFFER: - x.Marshal(x.Sprintf("%smanageSellOfferResult", name), XDR_ManageSellOfferResult(u.ManageSellOfferResult())) - return - case CREATE_PASSIVE_SELL_OFFER: - x.Marshal(x.Sprintf("%screatePassiveSellOfferResult", name), XDR_ManageSellOfferResult(u.CreatePassiveSellOfferResult())) - return - case SET_OPTIONS: - x.Marshal(x.Sprintf("%ssetOptionsResult", name), XDR_SetOptionsResult(u.SetOptionsResult())) - return - case CHANGE_TRUST: - x.Marshal(x.Sprintf("%schangeTrustResult", name), XDR_ChangeTrustResult(u.ChangeTrustResult())) - return - case ALLOW_TRUST: - x.Marshal(x.Sprintf("%sallowTrustResult", name), XDR_AllowTrustResult(u.AllowTrustResult())) - return - case ACCOUNT_MERGE: - x.Marshal(x.Sprintf("%saccountMergeResult", name), XDR_AccountMergeResult(u.AccountMergeResult())) - return - case INFLATION: - x.Marshal(x.Sprintf("%sinflationResult", name), XDR_InflationResult(u.InflationResult())) - return - case MANAGE_DATA: - x.Marshal(x.Sprintf("%smanageDataResult", name), XDR_ManageDataResult(u.ManageDataResult())) - return - case BUMP_SEQUENCE: - x.Marshal(x.Sprintf("%sbumpSeqResult", name), XDR_BumpSequenceResult(u.BumpSeqResult())) - return - case MANAGE_BUY_OFFER: - x.Marshal(x.Sprintf("%smanageBuyOfferResult", name), XDR_ManageBuyOfferResult(u.ManageBuyOfferResult())) - return - case PATH_PAYMENT_STRICT_SEND: - x.Marshal(x.Sprintf("%spathPaymentStrictSendResult", name), XDR_PathPaymentStrictSendResult(u.PathPaymentStrictSendResult())) - return - case CREATE_CLAIMABLE_BALANCE: - x.Marshal(x.Sprintf("%screateClaimableBalanceResult", name), XDR_CreateClaimableBalanceResult(u.CreateClaimableBalanceResult())) - return - case CLAIM_CLAIMABLE_BALANCE: - x.Marshal(x.Sprintf("%sclaimClaimableBalanceResult", name), XDR_ClaimClaimableBalanceResult(u.ClaimClaimableBalanceResult())) - return - case BEGIN_SPONSORING_FUTURE_RESERVES: - x.Marshal(x.Sprintf("%sbeginSponsoringFutureReservesResult", name), XDR_BeginSponsoringFutureReservesResult(u.BeginSponsoringFutureReservesResult())) + case CONTRACT_EXECUTABLE_WASM: + x.Marshal(x.Sprintf("%swasm_hash", name), XDR_Hash(u.Wasm_hash())) return - case END_SPONSORING_FUTURE_RESERVES: - x.Marshal(x.Sprintf("%sendSponsoringFutureReservesResult", name), XDR_EndSponsoringFutureReservesResult(u.EndSponsoringFutureReservesResult())) - return - case REVOKE_SPONSORSHIP: - x.Marshal(x.Sprintf("%srevokeSponsorshipResult", name), XDR_RevokeSponsorshipResult(u.RevokeSponsorshipResult())) - return - case CLAWBACK: - x.Marshal(x.Sprintf("%sclawbackResult", name), XDR_ClawbackResult(u.ClawbackResult())) - return - case CLAWBACK_CLAIMABLE_BALANCE: - x.Marshal(x.Sprintf("%sclawbackClaimableBalanceResult", name), XDR_ClawbackClaimableBalanceResult(u.ClawbackClaimableBalanceResult())) - return - case SET_TRUST_LINE_FLAGS: - x.Marshal(x.Sprintf("%ssetTrustLineFlagsResult", name), XDR_SetTrustLineFlagsResult(u.SetTrustLineFlagsResult())) - return - case LIQUIDITY_POOL_DEPOSIT: - x.Marshal(x.Sprintf("%sliquidityPoolDepositResult", name), XDR_LiquidityPoolDepositResult(u.LiquidityPoolDepositResult())) - return - case LIQUIDITY_POOL_WITHDRAW: - x.Marshal(x.Sprintf("%sliquidityPoolWithdrawResult", name), XDR_LiquidityPoolWithdrawResult(u.LiquidityPoolWithdrawResult())) + case CONTRACT_EXECUTABLE_STELLAR_ASSET: return } - XdrPanic("invalid Type (%v) in XdrAnon_OperationResult_Tr", u.Type) -} -func XDR_XdrAnon_OperationResult_Tr(v *XdrAnon_OperationResult_Tr) *XdrAnon_OperationResult_Tr { - return v + XdrPanic("invalid Type (%v) in ContractExecutable", u.Type) +} +func XDR_ContractExecutable(v *ContractExecutable) *ContractExecutable { return v } + +var _XdrNames_SCAddressType = map[int32]string{ + int32(SC_ADDRESS_TYPE_ACCOUNT): "SC_ADDRESS_TYPE_ACCOUNT", + int32(SC_ADDRESS_TYPE_CONTRACT): "SC_ADDRESS_TYPE_CONTRACT", +} +var _XdrValues_SCAddressType = map[string]int32{ + "SC_ADDRESS_TYPE_ACCOUNT": int32(SC_ADDRESS_TYPE_ACCOUNT), + "SC_ADDRESS_TYPE_CONTRACT": int32(SC_ADDRESS_TYPE_CONTRACT), +} + +func (SCAddressType) XdrEnumNames() map[int32]string { + return _XdrNames_SCAddressType +} +func (v SCAddressType) String() string { + if s, ok := _XdrNames_SCAddressType[int32(v)]; ok { + return s + } + return fmt.Sprintf("SCAddressType#%d", v) +} +func (v *SCAddressType) Scan(ss fmt.ScanState, _ rune) error { + if tok, err := ss.Token(true, XdrSymChar); err != nil { + return err + } else { + stok := string(tok) + if val, ok := _XdrValues_SCAddressType[stok]; ok { + *v = SCAddressType(val) + return nil + } else if stok == "SCAddressType" { + if n, err := fmt.Fscanf(ss, "#%d", (*int32)(v)); n == 1 && err == nil { + return nil + } + } + return XdrError(fmt.Sprintf("%s is not a valid SCAddressType.", stok)) + } } +func (v SCAddressType) GetU32() uint32 { return uint32(v) } +func (v *SCAddressType) SetU32(n uint32) { *v = SCAddressType(n) } +func (v *SCAddressType) XdrPointer() interface{} { return v } +func (SCAddressType) XdrTypeName() string { return "SCAddressType" } +func (v SCAddressType) XdrValue() interface{} { return v } +func (v *SCAddressType) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -var _XdrTags_OperationResult = map[int32]bool{ - XdrToI32(OpINNER): true, - XdrToI32(OpBAD_AUTH): true, - XdrToI32(OpNO_ACCOUNT): true, - XdrToI32(OpNOT_SUPPORTED): true, - XdrToI32(OpTOO_MANY_SUBENTRIES): true, - XdrToI32(OpEXCEEDED_WORK_LIMIT): true, - XdrToI32(OpTOO_MANY_SPONSORING): true, +type XdrType_SCAddressType = *SCAddressType + +func XDR_SCAddressType(v *SCAddressType) *SCAddressType { return v } + +var _XdrTags_SCAddress = map[int32]bool{ + XdrToI32(SC_ADDRESS_TYPE_ACCOUNT): true, + XdrToI32(SC_ADDRESS_TYPE_CONTRACT): true, } -func (_ OperationResult) XdrValidTags() map[int32]bool { - return _XdrTags_OperationResult +func (_ SCAddress) XdrValidTags() map[int32]bool { + return _XdrTags_SCAddress } -func (u *OperationResult) Tr() *XdrAnon_OperationResult_Tr { - switch u.Code { - case OpINNER: - if v, ok := u._u.(*XdrAnon_OperationResult_Tr); ok { +func (u *SCAddress) AccountId() *AccountID { + switch u.Type { + case SC_ADDRESS_TYPE_ACCOUNT: + if v, ok := u._u.(*AccountID); ok { return v } else { - var zero XdrAnon_OperationResult_Tr + var zero AccountID u._u = &zero return &zero } default: - XdrPanic("OperationResult.Tr accessed when Code == %v", u.Code) + XdrPanic("SCAddress.AccountId accessed when Type == %v", u.Type) return nil } } -func (u OperationResult) XdrValid() bool { - switch u.Code { - case OpINNER, OpBAD_AUTH, OpNO_ACCOUNT, OpNOT_SUPPORTED, OpTOO_MANY_SUBENTRIES, OpEXCEEDED_WORK_LIMIT, OpTOO_MANY_SPONSORING: +func (u *SCAddress) ContractId() *Hash { + switch u.Type { + case SC_ADDRESS_TYPE_CONTRACT: + if v, ok := u._u.(*Hash); ok { + return v + } else { + var zero Hash + u._u = &zero + return &zero + } + default: + XdrPanic("SCAddress.ContractId accessed when Type == %v", u.Type) + return nil + } +} +func (u SCAddress) XdrValid() bool { + switch u.Type { + case SC_ADDRESS_TYPE_ACCOUNT, SC_ADDRESS_TYPE_CONTRACT: return true } return false } -func (u *OperationResult) XdrUnionTag() XdrNum32 { - return XDR_OperationResultCode(&u.Code) +func (u *SCAddress) XdrUnionTag() XdrNum32 { + return XDR_SCAddressType(&u.Type) } -func (u *OperationResult) XdrUnionTagName() string { - return "Code" +func (u *SCAddress) XdrUnionTagName() string { + return "Type" } -func (u *OperationResult) XdrUnionBody() XdrType { - switch u.Code { - case OpINNER: - return XDR_XdrAnon_OperationResult_Tr(u.Tr()) - case OpBAD_AUTH, OpNO_ACCOUNT, OpNOT_SUPPORTED, OpTOO_MANY_SUBENTRIES, OpEXCEEDED_WORK_LIMIT, OpTOO_MANY_SPONSORING: - return nil +func (u *SCAddress) XdrUnionBody() XdrType { + switch u.Type { + case SC_ADDRESS_TYPE_ACCOUNT: + return XDR_AccountID(u.AccountId()) + case SC_ADDRESS_TYPE_CONTRACT: + return XDR_Hash(u.ContractId()) } return nil } -func (u *OperationResult) XdrUnionBodyName() string { - switch u.Code { - case OpINNER: - return "Tr" - case OpBAD_AUTH, OpNO_ACCOUNT, OpNOT_SUPPORTED, OpTOO_MANY_SUBENTRIES, OpEXCEEDED_WORK_LIMIT, OpTOO_MANY_SPONSORING: - return "" +func (u *SCAddress) XdrUnionBodyName() string { + switch u.Type { + case SC_ADDRESS_TYPE_ACCOUNT: + return "AccountId" + case SC_ADDRESS_TYPE_CONTRACT: + return "ContractId" } return "" } -type XdrType_OperationResult = *OperationResult +type XdrType_SCAddress = *SCAddress -func (v *OperationResult) XdrPointer() interface{} { return v } -func (OperationResult) XdrTypeName() string { return "OperationResult" } -func (v OperationResult) XdrValue() interface{} { return v } -func (v *OperationResult) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -func (u *OperationResult) XdrRecurse(x XDR, name string) { +func (v *SCAddress) XdrPointer() interface{} { return v } +func (SCAddress) XdrTypeName() string { return "SCAddress" } +func (v SCAddress) XdrValue() interface{} { return v } +func (v *SCAddress) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (u *SCAddress) XdrRecurse(x XDR, name string) { if name != "" { name = x.Sprintf("%s.", name) } - XDR_OperationResultCode(&u.Code).XdrMarshal(x, x.Sprintf("%scode", name)) - switch u.Code { - case OpINNER: - x.Marshal(x.Sprintf("%str", name), XDR_XdrAnon_OperationResult_Tr(u.Tr())) + XDR_SCAddressType(&u.Type).XdrMarshal(x, x.Sprintf("%stype", name)) + switch u.Type { + case SC_ADDRESS_TYPE_ACCOUNT: + x.Marshal(x.Sprintf("%saccountId", name), XDR_AccountID(u.AccountId())) return - case OpBAD_AUTH, OpNO_ACCOUNT, OpNOT_SUPPORTED, OpTOO_MANY_SUBENTRIES, OpEXCEEDED_WORK_LIMIT, OpTOO_MANY_SPONSORING: + case SC_ADDRESS_TYPE_CONTRACT: + x.Marshal(x.Sprintf("%scontractId", name), XDR_Hash(u.ContractId())) return } - XdrPanic("invalid Code (%v) in OperationResult", u.Code) + XdrPanic("invalid Type (%v) in SCAddress", u.Type) } -func XDR_OperationResult(v *OperationResult) *OperationResult { return v } +func XDR_SCAddress(v *SCAddress) *SCAddress { return v } -var _XdrNames_TransactionResultCode = map[int32]string{ - int32(TxFEE_BUMP_INNER_SUCCESS): "txFEE_BUMP_INNER_SUCCESS", - int32(TxSUCCESS): "txSUCCESS", - int32(TxFAILED): "txFAILED", - int32(TxTOO_EARLY): "txTOO_EARLY", - int32(TxTOO_LATE): "txTOO_LATE", - int32(TxMISSING_OPERATION): "txMISSING_OPERATION", - int32(TxBAD_SEQ): "txBAD_SEQ", - int32(TxBAD_AUTH): "txBAD_AUTH", - int32(TxINSUFFICIENT_BALANCE): "txINSUFFICIENT_BALANCE", - int32(TxNO_ACCOUNT): "txNO_ACCOUNT", - int32(TxINSUFFICIENT_FEE): "txINSUFFICIENT_FEE", - int32(TxBAD_AUTH_EXTRA): "txBAD_AUTH_EXTRA", - int32(TxINTERNAL_ERROR): "txINTERNAL_ERROR", - int32(TxNOT_SUPPORTED): "txNOT_SUPPORTED", - int32(TxFEE_BUMP_INNER_FAILED): "txFEE_BUMP_INNER_FAILED", - int32(TxBAD_SPONSORSHIP): "txBAD_SPONSORSHIP", - int32(TxBAD_MIN_SEQ_AGE_OR_GAP): "txBAD_MIN_SEQ_AGE_OR_GAP", - int32(TxMALFORMED): "txMALFORMED", +type XdrType_SCVec struct { + *_XdrVec_unbounded_SCVal } -var _XdrValues_TransactionResultCode = map[string]int32{ - "txFEE_BUMP_INNER_SUCCESS": int32(TxFEE_BUMP_INNER_SUCCESS), - "txSUCCESS": int32(TxSUCCESS), - "txFAILED": int32(TxFAILED), - "txTOO_EARLY": int32(TxTOO_EARLY), - "txTOO_LATE": int32(TxTOO_LATE), - "txMISSING_OPERATION": int32(TxMISSING_OPERATION), - "txBAD_SEQ": int32(TxBAD_SEQ), - "txBAD_AUTH": int32(TxBAD_AUTH), - "txINSUFFICIENT_BALANCE": int32(TxINSUFFICIENT_BALANCE), - "txNO_ACCOUNT": int32(TxNO_ACCOUNT), - "txINSUFFICIENT_FEE": int32(TxINSUFFICIENT_FEE), - "txBAD_AUTH_EXTRA": int32(TxBAD_AUTH_EXTRA), - "txINTERNAL_ERROR": int32(TxINTERNAL_ERROR), - "txNOT_SUPPORTED": int32(TxNOT_SUPPORTED), - "txFEE_BUMP_INNER_FAILED": int32(TxFEE_BUMP_INNER_FAILED), - "txBAD_SPONSORSHIP": int32(TxBAD_SPONSORSHIP), - "txBAD_MIN_SEQ_AGE_OR_GAP": int32(TxBAD_MIN_SEQ_AGE_OR_GAP), - "txMALFORMED": int32(TxMALFORMED), + +func XDR_SCVec(v *SCVec) XdrType_SCVec { + return XdrType_SCVec{(*_XdrVec_unbounded_SCVal)(v)} } +func (XdrType_SCVec) XdrTypeName() string { return "SCVec" } +func (v XdrType_SCVec) XdrUnwrap() XdrType { return v._XdrVec_unbounded_SCVal } -func (TransactionResultCode) XdrEnumNames() map[int32]string { - return _XdrNames_TransactionResultCode +type _XdrVec_unbounded_SCMapEntry []SCMapEntry + +func (_XdrVec_unbounded_SCMapEntry) XdrBound() uint32 { + const bound uint32 = 4294967295 // Force error if not const or doesn't fit + return bound } -func (v TransactionResultCode) String() string { - if s, ok := _XdrNames_TransactionResultCode[int32(v)]; ok { - return s +func (_XdrVec_unbounded_SCMapEntry) XdrCheckLen(length uint32) { + if length > uint32(4294967295) { + XdrPanic("_XdrVec_unbounded_SCMapEntry length %d exceeds bound 4294967295", length) + } else if int(length) < 0 { + XdrPanic("_XdrVec_unbounded_SCMapEntry length %d exceeds max int", length) } - return fmt.Sprintf("TransactionResultCode#%d", v) } -func (v *TransactionResultCode) Scan(ss fmt.ScanState, _ rune) error { - if tok, err := ss.Token(true, XdrSymChar); err != nil { - return err - } else { - stok := string(tok) - if val, ok := _XdrValues_TransactionResultCode[stok]; ok { - *v = TransactionResultCode(val) - return nil - } else if stok == "TransactionResultCode" { - if n, err := fmt.Fscanf(ss, "#%d", (*int32)(v)); n == 1 && err == nil { - return nil - } +func (v _XdrVec_unbounded_SCMapEntry) GetVecLen() uint32 { return uint32(len(v)) } +func (v *_XdrVec_unbounded_SCMapEntry) SetVecLen(length uint32) { + v.XdrCheckLen(length) + if int(length) <= cap(*v) { + if int(length) != len(*v) { + *v = (*v)[:int(length)] } - return XdrError(fmt.Sprintf("%s is not a valid TransactionResultCode.", stok)) + return + } + newcap := 2 * cap(*v) + if newcap < int(length) { // also catches overflow where 2*cap < 0 + newcap = int(length) + } else if bound := uint(4294967295); uint(newcap) > bound { + if int(bound) < 0 { + bound = ^uint(0) >> 1 + } + newcap = int(bound) } + nv := make([]SCMapEntry, int(length), newcap) + copy(nv, *v) + *v = nv } -func (v TransactionResultCode) GetU32() uint32 { return uint32(v) } -func (v *TransactionResultCode) SetU32(n uint32) { *v = TransactionResultCode(n) } -func (v *TransactionResultCode) XdrPointer() interface{} { return v } -func (TransactionResultCode) XdrTypeName() string { return "TransactionResultCode" } -func (v TransactionResultCode) XdrValue() interface{} { return v } -func (v *TransactionResultCode) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v *_XdrVec_unbounded_SCMapEntry) XdrMarshalN(x XDR, name string, n uint32) { + v.XdrCheckLen(n) + for i := 0; i < int(n); i++ { + if i >= len(*v) { + v.SetVecLen(uint32(i + 1)) + } + XDR_SCMapEntry(&(*v)[i]).XdrMarshal(x, x.Sprintf("%s[%d]", name, i)) + } + if int(n) < len(*v) { + *v = (*v)[:int(n)] + } +} +func (v *_XdrVec_unbounded_SCMapEntry) XdrRecurse(x XDR, name string) { + size := XdrSize{Size: uint32(len(*v)), Bound: 4294967295} + x.Marshal(name, &size) + v.XdrMarshalN(x, name, size.Size) +} +func (_XdrVec_unbounded_SCMapEntry) XdrTypeName() string { return "SCMapEntry<>" } +func (v *_XdrVec_unbounded_SCMapEntry) XdrPointer() interface{} { return (*[]SCMapEntry)(v) } +func (v _XdrVec_unbounded_SCMapEntry) XdrValue() interface{} { return ([]SCMapEntry)(v) } +func (v *_XdrVec_unbounded_SCMapEntry) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -type XdrType_TransactionResultCode = *TransactionResultCode +type XdrType_SCMap struct { + *_XdrVec_unbounded_SCMapEntry +} -func XDR_TransactionResultCode(v *TransactionResultCode) *TransactionResultCode { return v } +func XDR_SCMap(v *SCMap) XdrType_SCMap { + return XdrType_SCMap{(*_XdrVec_unbounded_SCMapEntry)(v)} +} +func (XdrType_SCMap) XdrTypeName() string { return "SCMap" } +func (v XdrType_SCMap) XdrUnwrap() XdrType { return v._XdrVec_unbounded_SCMapEntry } -var _XdrComments_TransactionResultCode = map[int32]string{ - int32(TxFEE_BUMP_INNER_SUCCESS): "fee bump inner transaction succeeded", - int32(TxSUCCESS): "all operations succeeded", - int32(TxFAILED): "one of the operations failed (none were applied)", - int32(TxTOO_EARLY): "ledger closeTime before minTime", - int32(TxTOO_LATE): "ledger closeTime after maxTime", - int32(TxMISSING_OPERATION): "no operation was specified", - int32(TxBAD_SEQ): "sequence number does not match source account", - int32(TxBAD_AUTH): "too few valid signatures / wrong network", - int32(TxINSUFFICIENT_BALANCE): "fee would bring account below reserve", - int32(TxNO_ACCOUNT): "source account not found", - int32(TxINSUFFICIENT_FEE): "fee is too small", - int32(TxBAD_AUTH_EXTRA): "unused signatures attached to transaction", - int32(TxINTERNAL_ERROR): "an unknown error occurred", - int32(TxNOT_SUPPORTED): "transaction type not supported", - int32(TxFEE_BUMP_INNER_FAILED): "fee bump inner transaction failed", - int32(TxBAD_SPONSORSHIP): "sponsorship not confirmed", - int32(TxBAD_MIN_SEQ_AGE_OR_GAP): "minSeqAge or minSeqLedgerGap conditions not met", - int32(TxMALFORMED): "precondition is invalid", +type XdrType_SCBytes struct { + XdrVecOpaque +} + +func XDR_SCBytes(v *SCBytes) XdrType_SCBytes { + return XdrType_SCBytes{XdrVecOpaque{v, 0xffffffff}} +} +func (XdrType_SCBytes) XdrTypeName() string { return "SCBytes" } +func (v XdrType_SCBytes) XdrUnwrap() XdrType { return v.XdrVecOpaque } + +type XdrType_SCString struct { + XdrString +} + +func XDR_SCString(v *SCString) XdrType_SCString { + return XdrType_SCString{XdrString{v, 0xffffffff}} +} +func (XdrType_SCString) XdrTypeName() string { return "SCString" } +func (v XdrType_SCString) XdrUnwrap() XdrType { return v.XdrString } + +type XdrType_SCSymbol struct { + XdrString +} + +func XDR_SCSymbol(v *SCSymbol) XdrType_SCSymbol { + return XdrType_SCSymbol{XdrString{v, SCSYMBOL_LIMIT}} +} +func (XdrType_SCSymbol) XdrTypeName() string { return "SCSymbol" } +func (v XdrType_SCSymbol) XdrUnwrap() XdrType { return v.XdrString } + +type XdrType_SCNonceKey = *SCNonceKey + +func (v *SCNonceKey) XdrPointer() interface{} { return v } +func (SCNonceKey) XdrTypeName() string { return "SCNonceKey" } +func (v SCNonceKey) XdrValue() interface{} { return v } +func (v *SCNonceKey) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v *SCNonceKey) XdrRecurse(x XDR, name string) { + if name != "" { + name = x.Sprintf("%s.", name) + } + x.Marshal(x.Sprintf("%snonce", name), XDR_Int64(&v.Nonce)) +} +func XDR_SCNonceKey(v *SCNonceKey) *SCNonceKey { return v } + +type _XdrPtr_SCMap struct { + p **SCMap +} +type _ptrflag_SCMap _XdrPtr_SCMap + +func (v _ptrflag_SCMap) String() string { + if *v.p == nil { + return "nil" + } + return "non-nil" +} +func (v _ptrflag_SCMap) Scan(ss fmt.ScanState, r rune) error { + tok, err := ss.Token(true, func(c rune) bool { + return c == '-' || (c >= 'a' && c <= 'z') + }) + if err != nil { + return err + } + switch string(tok) { + case "nil": + v.SetU32(0) + case "non-nil": + v.SetU32(1) + default: + return XdrError("SCMap flag should be \"nil\" or \"non-nil\"") + } + return nil +} +func (v _ptrflag_SCMap) GetU32() uint32 { + if *v.p == nil { + return 0 + } + return 1 +} +func (v _ptrflag_SCMap) SetU32(nv uint32) { + switch nv { + case 0: + *v.p = nil + case 1: + if *v.p == nil { + *v.p = new(SCMap) + } + default: + XdrPanic("*SCMap present flag value %d should be 0 or 1", nv) + } } - -func (e TransactionResultCode) XdrEnumComments() map[int32]string { - return _XdrComments_TransactionResultCode +func (_ptrflag_SCMap) XdrTypeName() string { return "SCMap?" } +func (v _ptrflag_SCMap) XdrPointer() interface{} { return nil } +func (v _ptrflag_SCMap) XdrValue() interface{} { return v.GetU32() != 0 } +func (v _ptrflag_SCMap) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v _ptrflag_SCMap) XdrBound() uint32 { return 1 } +func (v _XdrPtr_SCMap) GetPresent() bool { return *v.p != nil } +func (v _XdrPtr_SCMap) SetPresent(present bool) { + if !present { + *v.p = nil + } else if *v.p == nil { + *v.p = new(SCMap) + } } +func (v _XdrPtr_SCMap) XdrMarshalValue(x XDR, name string) { + if *v.p != nil { + XDR_SCMap(*v.p).XdrMarshal(x, name) + } +} +func (v _XdrPtr_SCMap) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v _XdrPtr_SCMap) XdrRecurse(x XDR, name string) { + x.Marshal(name, _ptrflag_SCMap(v)) + v.XdrMarshalValue(x, name) +} +func (_XdrPtr_SCMap) XdrTypeName() string { return "SCMap*" } +func (v _XdrPtr_SCMap) XdrPointer() interface{} { return v.p } +func (v _XdrPtr_SCMap) XdrValue() interface{} { return *v.p } -type _XdrVec_unbounded_OperationResult []OperationResult +type XdrType_SCContractInstance = *SCContractInstance -func (_XdrVec_unbounded_OperationResult) XdrBound() uint32 { - const bound uint32 = 4294967295 // Force error if not const or doesn't fit - return bound +func (v *SCContractInstance) XdrPointer() interface{} { return v } +func (SCContractInstance) XdrTypeName() string { return "SCContractInstance" } +func (v SCContractInstance) XdrValue() interface{} { return v } +func (v *SCContractInstance) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v *SCContractInstance) XdrRecurse(x XDR, name string) { + if name != "" { + name = x.Sprintf("%s.", name) + } + x.Marshal(x.Sprintf("%sexecutable", name), XDR_ContractExecutable(&v.Executable)) + x.Marshal(x.Sprintf("%sstorage", name), _XdrPtr_SCMap{&v.Storage}) } -func (_XdrVec_unbounded_OperationResult) XdrCheckLen(length uint32) { - if length > uint32(4294967295) { - XdrPanic("_XdrVec_unbounded_OperationResult length %d exceeds bound 4294967295", length) - } else if int(length) < 0 { - XdrPanic("_XdrVec_unbounded_OperationResult length %d exceeds max int", length) +func XDR_SCContractInstance(v *SCContractInstance) *SCContractInstance { return v } + +type _XdrPtr_SCVec struct { + p **SCVec +} +type _ptrflag_SCVec _XdrPtr_SCVec + +func (v _ptrflag_SCVec) String() string { + if *v.p == nil { + return "nil" } + return "non-nil" } -func (v _XdrVec_unbounded_OperationResult) GetVecLen() uint32 { return uint32(len(v)) } -func (v *_XdrVec_unbounded_OperationResult) SetVecLen(length uint32) { - v.XdrCheckLen(length) - if int(length) <= cap(*v) { - if int(length) != len(*v) { - *v = (*v)[:int(length)] - } - return +func (v _ptrflag_SCVec) Scan(ss fmt.ScanState, r rune) error { + tok, err := ss.Token(true, func(c rune) bool { + return c == '-' || (c >= 'a' && c <= 'z') + }) + if err != nil { + return err } - newcap := 2 * cap(*v) - if newcap < int(length) { // also catches overflow where 2*cap < 0 - newcap = int(length) - } else if bound := uint(4294967295); uint(newcap) > bound { - if int(bound) < 0 { - bound = ^uint(0) >> 1 - } - newcap = int(bound) + switch string(tok) { + case "nil": + v.SetU32(0) + case "non-nil": + v.SetU32(1) + default: + return XdrError("SCVec flag should be \"nil\" or \"non-nil\"") } - nv := make([]OperationResult, int(length), newcap) - copy(nv, *v) - *v = nv + return nil } -func (v *_XdrVec_unbounded_OperationResult) XdrMarshalN(x XDR, name string, n uint32) { - v.XdrCheckLen(n) - for i := 0; i < int(n); i++ { - if i >= len(*v) { - v.SetVecLen(uint32(i + 1)) - } - XDR_OperationResult(&(*v)[i]).XdrMarshal(x, x.Sprintf("%s[%d]", name, i)) +func (v _ptrflag_SCVec) GetU32() uint32 { + if *v.p == nil { + return 0 } - if int(n) < len(*v) { - *v = (*v)[:int(n)] + return 1 +} +func (v _ptrflag_SCVec) SetU32(nv uint32) { + switch nv { + case 0: + *v.p = nil + case 1: + if *v.p == nil { + *v.p = new(SCVec) + } + default: + XdrPanic("*SCVec present flag value %d should be 0 or 1", nv) } } -func (v *_XdrVec_unbounded_OperationResult) XdrRecurse(x XDR, name string) { - size := XdrSize{Size: uint32(len(*v)), Bound: 4294967295} - x.Marshal(name, &size) - v.XdrMarshalN(x, name, size.Size) +func (_ptrflag_SCVec) XdrTypeName() string { return "SCVec?" } +func (v _ptrflag_SCVec) XdrPointer() interface{} { return nil } +func (v _ptrflag_SCVec) XdrValue() interface{} { return v.GetU32() != 0 } +func (v _ptrflag_SCVec) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v _ptrflag_SCVec) XdrBound() uint32 { return 1 } +func (v _XdrPtr_SCVec) GetPresent() bool { return *v.p != nil } +func (v _XdrPtr_SCVec) SetPresent(present bool) { + if !present { + *v.p = nil + } else if *v.p == nil { + *v.p = new(SCVec) + } } -func (_XdrVec_unbounded_OperationResult) XdrTypeName() string { return "OperationResult<>" } -func (v *_XdrVec_unbounded_OperationResult) XdrPointer() interface{} { return (*[]OperationResult)(v) } -func (v _XdrVec_unbounded_OperationResult) XdrValue() interface{} { return ([]OperationResult)(v) } -func (v *_XdrVec_unbounded_OperationResult) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } - -var _XdrTags_XdrAnon_InnerTransactionResult_Result = map[int32]bool{ - XdrToI32(TxSUCCESS): true, - XdrToI32(TxFAILED): true, - XdrToI32(TxTOO_EARLY): true, - XdrToI32(TxTOO_LATE): true, - XdrToI32(TxMISSING_OPERATION): true, - XdrToI32(TxBAD_SEQ): true, - XdrToI32(TxBAD_AUTH): true, - XdrToI32(TxINSUFFICIENT_BALANCE): true, - XdrToI32(TxNO_ACCOUNT): true, - XdrToI32(TxINSUFFICIENT_FEE): true, - XdrToI32(TxBAD_AUTH_EXTRA): true, - XdrToI32(TxINTERNAL_ERROR): true, - XdrToI32(TxNOT_SUPPORTED): true, - XdrToI32(TxBAD_SPONSORSHIP): true, - XdrToI32(TxBAD_MIN_SEQ_AGE_OR_GAP): true, - XdrToI32(TxMALFORMED): true, +func (v _XdrPtr_SCVec) XdrMarshalValue(x XDR, name string) { + if *v.p != nil { + XDR_SCVec(*v.p).XdrMarshal(x, name) + } } - -func (_ XdrAnon_InnerTransactionResult_Result) XdrValidTags() map[int32]bool { - return _XdrTags_XdrAnon_InnerTransactionResult_Result +func (v _XdrPtr_SCVec) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v _XdrPtr_SCVec) XdrRecurse(x XDR, name string) { + x.Marshal(name, _ptrflag_SCVec(v)) + v.XdrMarshalValue(x, name) } -func (u *XdrAnon_InnerTransactionResult_Result) Results() *[]OperationResult { - switch u.Code { - case TxSUCCESS, TxFAILED: - if v, ok := u._u.(*[]OperationResult); ok { +func (_XdrPtr_SCVec) XdrTypeName() string { return "SCVec*" } +func (v _XdrPtr_SCVec) XdrPointer() interface{} { return v.p } +func (v _XdrPtr_SCVec) XdrValue() interface{} { return *v.p } + +var _XdrTags_SCVal = map[int32]bool{ + XdrToI32(SCV_BOOL): true, + XdrToI32(SCV_VOID): true, + XdrToI32(SCV_ERROR): true, + XdrToI32(SCV_U32): true, + XdrToI32(SCV_I32): true, + XdrToI32(SCV_U64): true, + XdrToI32(SCV_I64): true, + XdrToI32(SCV_TIMEPOINT): true, + XdrToI32(SCV_DURATION): true, + XdrToI32(SCV_U128): true, + XdrToI32(SCV_I128): true, + XdrToI32(SCV_U256): true, + XdrToI32(SCV_I256): true, + XdrToI32(SCV_BYTES): true, + XdrToI32(SCV_STRING): true, + XdrToI32(SCV_SYMBOL): true, + XdrToI32(SCV_VEC): true, + XdrToI32(SCV_MAP): true, + XdrToI32(SCV_ADDRESS): true, + XdrToI32(SCV_LEDGER_KEY_CONTRACT_INSTANCE): true, + XdrToI32(SCV_LEDGER_KEY_NONCE): true, + XdrToI32(SCV_CONTRACT_INSTANCE): true, +} + +func (_ SCVal) XdrValidTags() map[int32]bool { + return _XdrTags_SCVal +} +func (u *SCVal) B() *bool { + switch u.Type { + case SCV_BOOL: + if v, ok := u._u.(*bool); ok { return v } else { - var zero []OperationResult + var zero bool u._u = &zero return &zero } default: - XdrPanic("XdrAnon_InnerTransactionResult_Result.Results accessed when Code == %v", u.Code) + XdrPanic("SCVal.B accessed when Type == %v", u.Type) return nil } } -func (u XdrAnon_InnerTransactionResult_Result) XdrValid() bool { - switch u.Code { - case TxSUCCESS, TxFAILED, TxTOO_EARLY, TxTOO_LATE, TxMISSING_OPERATION, TxBAD_SEQ, TxBAD_AUTH, TxINSUFFICIENT_BALANCE, TxNO_ACCOUNT, TxINSUFFICIENT_FEE, TxBAD_AUTH_EXTRA, TxINTERNAL_ERROR, TxNOT_SUPPORTED, TxBAD_SPONSORSHIP, TxBAD_MIN_SEQ_AGE_OR_GAP, TxMALFORMED: - return true +func (u *SCVal) Error() *SCError { + switch u.Type { + case SCV_ERROR: + if v, ok := u._u.(*SCError); ok { + return v + } else { + var zero SCError + u._u = &zero + return &zero + } + default: + XdrPanic("SCVal.Error accessed when Type == %v", u.Type) + return nil } - return false } -func (u *XdrAnon_InnerTransactionResult_Result) XdrUnionTag() XdrNum32 { - return XDR_TransactionResultCode(&u.Code) -} -func (u *XdrAnon_InnerTransactionResult_Result) XdrUnionTagName() string { - return "Code" -} -func (u *XdrAnon_InnerTransactionResult_Result) XdrUnionBody() XdrType { - switch u.Code { - case TxSUCCESS, TxFAILED: - return (*_XdrVec_unbounded_OperationResult)(u.Results()) - case TxTOO_EARLY, TxTOO_LATE, TxMISSING_OPERATION, TxBAD_SEQ, TxBAD_AUTH, TxINSUFFICIENT_BALANCE, TxNO_ACCOUNT, TxINSUFFICIENT_FEE, TxBAD_AUTH_EXTRA, TxINTERNAL_ERROR, TxNOT_SUPPORTED, TxBAD_SPONSORSHIP, TxBAD_MIN_SEQ_AGE_OR_GAP, TxMALFORMED: +func (u *SCVal) U32() *Uint32 { + switch u.Type { + case SCV_U32: + if v, ok := u._u.(*Uint32); ok { + return v + } else { + var zero Uint32 + u._u = &zero + return &zero + } + default: + XdrPanic("SCVal.U32 accessed when Type == %v", u.Type) return nil } - return nil } -func (u *XdrAnon_InnerTransactionResult_Result) XdrUnionBodyName() string { - switch u.Code { - case TxSUCCESS, TxFAILED: - return "Results" - case TxTOO_EARLY, TxTOO_LATE, TxMISSING_OPERATION, TxBAD_SEQ, TxBAD_AUTH, TxINSUFFICIENT_BALANCE, TxNO_ACCOUNT, TxINSUFFICIENT_FEE, TxBAD_AUTH_EXTRA, TxINTERNAL_ERROR, TxNOT_SUPPORTED, TxBAD_SPONSORSHIP, TxBAD_MIN_SEQ_AGE_OR_GAP, TxMALFORMED: - return "" +func (u *SCVal) I32() *Int32 { + switch u.Type { + case SCV_I32: + if v, ok := u._u.(*Int32); ok { + return v + } else { + var zero Int32 + u._u = &zero + return &zero + } + default: + XdrPanic("SCVal.I32 accessed when Type == %v", u.Type) + return nil } - return "" -} - -type XdrType_XdrAnon_InnerTransactionResult_Result = *XdrAnon_InnerTransactionResult_Result - -func (v *XdrAnon_InnerTransactionResult_Result) XdrPointer() interface{} { return v } -func (XdrAnon_InnerTransactionResult_Result) XdrTypeName() string { - return "XdrAnon_InnerTransactionResult_Result" } -func (v XdrAnon_InnerTransactionResult_Result) XdrValue() interface{} { return v } -func (v *XdrAnon_InnerTransactionResult_Result) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -func (u *XdrAnon_InnerTransactionResult_Result) XdrRecurse(x XDR, name string) { - if name != "" { - name = x.Sprintf("%s.", name) - } - XDR_TransactionResultCode(&u.Code).XdrMarshal(x, x.Sprintf("%scode", name)) - switch u.Code { - case TxSUCCESS, TxFAILED: - x.Marshal(x.Sprintf("%sresults", name), (*_XdrVec_unbounded_OperationResult)(u.Results())) - return - case TxTOO_EARLY, TxTOO_LATE, TxMISSING_OPERATION, TxBAD_SEQ, TxBAD_AUTH, TxINSUFFICIENT_BALANCE, TxNO_ACCOUNT, TxINSUFFICIENT_FEE, TxBAD_AUTH_EXTRA, TxINTERNAL_ERROR, TxNOT_SUPPORTED, TxBAD_SPONSORSHIP, TxBAD_MIN_SEQ_AGE_OR_GAP, TxMALFORMED: - return +func (u *SCVal) U64() *Uint64 { + switch u.Type { + case SCV_U64: + if v, ok := u._u.(*Uint64); ok { + return v + } else { + var zero Uint64 + u._u = &zero + return &zero + } + default: + XdrPanic("SCVal.U64 accessed when Type == %v", u.Type) + return nil } - XdrPanic("invalid Code (%v) in XdrAnon_InnerTransactionResult_Result", u.Code) -} -func XDR_XdrAnon_InnerTransactionResult_Result(v *XdrAnon_InnerTransactionResult_Result) *XdrAnon_InnerTransactionResult_Result { - return v -} - -var _XdrTags_XdrAnon_InnerTransactionResult_Ext = map[int32]bool{ - XdrToI32(0): true, -} - -func (_ XdrAnon_InnerTransactionResult_Ext) XdrValidTags() map[int32]bool { - return _XdrTags_XdrAnon_InnerTransactionResult_Ext } -func (u XdrAnon_InnerTransactionResult_Ext) XdrValid() bool { - switch u.V { - case 0: - return true +func (u *SCVal) I64() *Int64 { + switch u.Type { + case SCV_I64: + if v, ok := u._u.(*Int64); ok { + return v + } else { + var zero Int64 + u._u = &zero + return &zero + } + default: + XdrPanic("SCVal.I64 accessed when Type == %v", u.Type) + return nil } - return false } -func (u *XdrAnon_InnerTransactionResult_Ext) XdrUnionTag() XdrNum32 { - return XDR_int32(&u.V) +func (u *SCVal) Timepoint() *TimePoint { + switch u.Type { + case SCV_TIMEPOINT: + if v, ok := u._u.(*TimePoint); ok { + return v + } else { + var zero TimePoint + u._u = &zero + return &zero + } + default: + XdrPanic("SCVal.Timepoint accessed when Type == %v", u.Type) + return nil + } } -func (u *XdrAnon_InnerTransactionResult_Ext) XdrUnionTagName() string { - return "V" +func (u *SCVal) Duration() *Duration { + switch u.Type { + case SCV_DURATION: + if v, ok := u._u.(*Duration); ok { + return v + } else { + var zero Duration + u._u = &zero + return &zero + } + default: + XdrPanic("SCVal.Duration accessed when Type == %v", u.Type) + return nil + } } -func (u *XdrAnon_InnerTransactionResult_Ext) XdrUnionBody() XdrType { - switch u.V { - case 0: +func (u *SCVal) U128() *UInt128Parts { + switch u.Type { + case SCV_U128: + if v, ok := u._u.(*UInt128Parts); ok { + return v + } else { + var zero UInt128Parts + u._u = &zero + return &zero + } + default: + XdrPanic("SCVal.U128 accessed when Type == %v", u.Type) return nil } - return nil } -func (u *XdrAnon_InnerTransactionResult_Ext) XdrUnionBodyName() string { - switch u.V { - case 0: - return "" +func (u *SCVal) I128() *Int128Parts { + switch u.Type { + case SCV_I128: + if v, ok := u._u.(*Int128Parts); ok { + return v + } else { + var zero Int128Parts + u._u = &zero + return &zero + } + default: + XdrPanic("SCVal.I128 accessed when Type == %v", u.Type) + return nil } - return "" } - -type XdrType_XdrAnon_InnerTransactionResult_Ext = *XdrAnon_InnerTransactionResult_Ext - -func (v *XdrAnon_InnerTransactionResult_Ext) XdrPointer() interface{} { return v } -func (XdrAnon_InnerTransactionResult_Ext) XdrTypeName() string { - return "XdrAnon_InnerTransactionResult_Ext" -} -func (v XdrAnon_InnerTransactionResult_Ext) XdrValue() interface{} { return v } -func (v *XdrAnon_InnerTransactionResult_Ext) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -func (u *XdrAnon_InnerTransactionResult_Ext) XdrRecurse(x XDR, name string) { - if name != "" { - name = x.Sprintf("%s.", name) +func (u *SCVal) U256() *UInt256Parts { + switch u.Type { + case SCV_U256: + if v, ok := u._u.(*UInt256Parts); ok { + return v + } else { + var zero UInt256Parts + u._u = &zero + return &zero + } + default: + XdrPanic("SCVal.U256 accessed when Type == %v", u.Type) + return nil } - XDR_int32(&u.V).XdrMarshal(x, x.Sprintf("%sv", name)) - switch u.V { - case 0: - return +} +func (u *SCVal) I256() *Int256Parts { + switch u.Type { + case SCV_I256: + if v, ok := u._u.(*Int256Parts); ok { + return v + } else { + var zero Int256Parts + u._u = &zero + return &zero + } + default: + XdrPanic("SCVal.I256 accessed when Type == %v", u.Type) + return nil } - XdrPanic("invalid V (%v) in XdrAnon_InnerTransactionResult_Ext", u.V) } -func XDR_XdrAnon_InnerTransactionResult_Ext(v *XdrAnon_InnerTransactionResult_Ext) *XdrAnon_InnerTransactionResult_Ext { - return v +func (u *SCVal) Bytes() *SCBytes { + switch u.Type { + case SCV_BYTES: + if v, ok := u._u.(*SCBytes); ok { + return v + } else { + var zero SCBytes + u._u = &zero + return &zero + } + default: + XdrPanic("SCVal.Bytes accessed when Type == %v", u.Type) + return nil + } } - -type XdrType_InnerTransactionResult = *InnerTransactionResult - -func (v *InnerTransactionResult) XdrPointer() interface{} { return v } -func (InnerTransactionResult) XdrTypeName() string { return "InnerTransactionResult" } -func (v InnerTransactionResult) XdrValue() interface{} { return v } -func (v *InnerTransactionResult) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -func (v *InnerTransactionResult) XdrRecurse(x XDR, name string) { - if name != "" { - name = x.Sprintf("%s.", name) +func (u *SCVal) Str() *SCString { + switch u.Type { + case SCV_STRING: + if v, ok := u._u.(*SCString); ok { + return v + } else { + var zero SCString + u._u = &zero + return &zero + } + default: + XdrPanic("SCVal.Str accessed when Type == %v", u.Type) + return nil } - x.Marshal(x.Sprintf("%sfeeCharged", name), XDR_Int64(&v.FeeCharged)) - x.Marshal(x.Sprintf("%sresult", name), XDR_XdrAnon_InnerTransactionResult_Result(&v.Result)) - x.Marshal(x.Sprintf("%sext", name), XDR_XdrAnon_InnerTransactionResult_Ext(&v.Ext)) } -func XDR_InnerTransactionResult(v *InnerTransactionResult) *InnerTransactionResult { return v } - -type XdrType_InnerTransactionResultPair = *InnerTransactionResultPair - -func (v *InnerTransactionResultPair) XdrPointer() interface{} { return v } -func (InnerTransactionResultPair) XdrTypeName() string { return "InnerTransactionResultPair" } -func (v InnerTransactionResultPair) XdrValue() interface{} { return v } -func (v *InnerTransactionResultPair) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -func (v *InnerTransactionResultPair) XdrRecurse(x XDR, name string) { - if name != "" { - name = x.Sprintf("%s.", name) +func (u *SCVal) Sym() *SCSymbol { + switch u.Type { + case SCV_SYMBOL: + if v, ok := u._u.(*SCSymbol); ok { + return v + } else { + var zero SCSymbol + u._u = &zero + return &zero + } + default: + XdrPanic("SCVal.Sym accessed when Type == %v", u.Type) + return nil } - x.Marshal(x.Sprintf("%stransactionHash", name), XDR_Hash(&v.TransactionHash)) - x.Marshal(x.Sprintf("%sresult", name), XDR_InnerTransactionResult(&v.Result)) } -func XDR_InnerTransactionResultPair(v *InnerTransactionResultPair) *InnerTransactionResultPair { - return v +func (u *SCVal) Vec() **SCVec { + switch u.Type { + case SCV_VEC: + if v, ok := u._u.(**SCVec); ok { + return v + } else { + var zero *SCVec + u._u = &zero + return &zero + } + default: + XdrPanic("SCVal.Vec accessed when Type == %v", u.Type) + return nil + } } - -var _XdrTags_XdrAnon_TransactionResult_Result = map[int32]bool{ - XdrToI32(TxFEE_BUMP_INNER_SUCCESS): true, - XdrToI32(TxFEE_BUMP_INNER_FAILED): true, - XdrToI32(TxSUCCESS): true, - XdrToI32(TxFAILED): true, - XdrToI32(TxTOO_EARLY): true, - XdrToI32(TxTOO_LATE): true, - XdrToI32(TxMISSING_OPERATION): true, - XdrToI32(TxBAD_SEQ): true, - XdrToI32(TxBAD_AUTH): true, - XdrToI32(TxINSUFFICIENT_BALANCE): true, - XdrToI32(TxNO_ACCOUNT): true, - XdrToI32(TxINSUFFICIENT_FEE): true, - XdrToI32(TxBAD_AUTH_EXTRA): true, - XdrToI32(TxINTERNAL_ERROR): true, - XdrToI32(TxNOT_SUPPORTED): true, - XdrToI32(TxBAD_SPONSORSHIP): true, - XdrToI32(TxBAD_MIN_SEQ_AGE_OR_GAP): true, - XdrToI32(TxMALFORMED): true, +func (u *SCVal) Map() **SCMap { + switch u.Type { + case SCV_MAP: + if v, ok := u._u.(**SCMap); ok { + return v + } else { + var zero *SCMap + u._u = &zero + return &zero + } + default: + XdrPanic("SCVal.Map accessed when Type == %v", u.Type) + return nil + } } - -func (_ XdrAnon_TransactionResult_Result) XdrValidTags() map[int32]bool { - return _XdrTags_XdrAnon_TransactionResult_Result +func (u *SCVal) Address() *SCAddress { + switch u.Type { + case SCV_ADDRESS: + if v, ok := u._u.(*SCAddress); ok { + return v + } else { + var zero SCAddress + u._u = &zero + return &zero + } + default: + XdrPanic("SCVal.Address accessed when Type == %v", u.Type) + return nil + } } -func (u *XdrAnon_TransactionResult_Result) InnerResultPair() *InnerTransactionResultPair { - switch u.Code { - case TxFEE_BUMP_INNER_SUCCESS, TxFEE_BUMP_INNER_FAILED: - if v, ok := u._u.(*InnerTransactionResultPair); ok { +func (u *SCVal) Nonce_key() *SCNonceKey { + switch u.Type { + case SCV_LEDGER_KEY_NONCE: + if v, ok := u._u.(*SCNonceKey); ok { return v } else { - var zero InnerTransactionResultPair + var zero SCNonceKey u._u = &zero return &zero } default: - XdrPanic("XdrAnon_TransactionResult_Result.InnerResultPair accessed when Code == %v", u.Code) + XdrPanic("SCVal.Nonce_key accessed when Type == %v", u.Type) return nil } } -func (u *XdrAnon_TransactionResult_Result) Results() *[]OperationResult { - switch u.Code { - case TxSUCCESS, TxFAILED: - if v, ok := u._u.(*[]OperationResult); ok { +func (u *SCVal) Instance() *SCContractInstance { + switch u.Type { + case SCV_CONTRACT_INSTANCE: + if v, ok := u._u.(*SCContractInstance); ok { return v } else { - var zero []OperationResult + var zero SCContractInstance u._u = &zero return &zero } default: - XdrPanic("XdrAnon_TransactionResult_Result.Results accessed when Code == %v", u.Code) + XdrPanic("SCVal.Instance accessed when Type == %v", u.Type) return nil } } -func (u XdrAnon_TransactionResult_Result) XdrValid() bool { - switch u.Code { - case TxFEE_BUMP_INNER_SUCCESS, TxFEE_BUMP_INNER_FAILED, TxSUCCESS, TxFAILED, TxTOO_EARLY, TxTOO_LATE, TxMISSING_OPERATION, TxBAD_SEQ, TxBAD_AUTH, TxINSUFFICIENT_BALANCE, TxNO_ACCOUNT, TxINSUFFICIENT_FEE, TxBAD_AUTH_EXTRA, TxINTERNAL_ERROR, TxNOT_SUPPORTED, TxBAD_SPONSORSHIP, TxBAD_MIN_SEQ_AGE_OR_GAP, TxMALFORMED: +func (u SCVal) XdrValid() bool { + switch u.Type { + case SCV_BOOL, SCV_VOID, SCV_ERROR, SCV_U32, SCV_I32, SCV_U64, SCV_I64, SCV_TIMEPOINT, SCV_DURATION, SCV_U128, SCV_I128, SCV_U256, SCV_I256, SCV_BYTES, SCV_STRING, SCV_SYMBOL, SCV_VEC, SCV_MAP, SCV_ADDRESS, SCV_LEDGER_KEY_CONTRACT_INSTANCE, SCV_LEDGER_KEY_NONCE, SCV_CONTRACT_INSTANCE: return true } return false } -func (u *XdrAnon_TransactionResult_Result) XdrUnionTag() XdrNum32 { - return XDR_TransactionResultCode(&u.Code) +func (u *SCVal) XdrUnionTag() XdrNum32 { + return XDR_SCValType(&u.Type) } -func (u *XdrAnon_TransactionResult_Result) XdrUnionTagName() string { - return "Code" +func (u *SCVal) XdrUnionTagName() string { + return "Type" } -func (u *XdrAnon_TransactionResult_Result) XdrUnionBody() XdrType { - switch u.Code { - case TxFEE_BUMP_INNER_SUCCESS, TxFEE_BUMP_INNER_FAILED: - return XDR_InnerTransactionResultPair(u.InnerResultPair()) - case TxSUCCESS, TxFAILED: - return (*_XdrVec_unbounded_OperationResult)(u.Results()) - case TxTOO_EARLY, TxTOO_LATE, TxMISSING_OPERATION, TxBAD_SEQ, TxBAD_AUTH, TxINSUFFICIENT_BALANCE, TxNO_ACCOUNT, TxINSUFFICIENT_FEE, TxBAD_AUTH_EXTRA, TxINTERNAL_ERROR, TxNOT_SUPPORTED, TxBAD_SPONSORSHIP, TxBAD_MIN_SEQ_AGE_OR_GAP, TxMALFORMED: +func (u *SCVal) XdrUnionBody() XdrType { + switch u.Type { + case SCV_BOOL: + return XDR_bool(u.B()) + case SCV_VOID: return nil + case SCV_ERROR: + return XDR_SCError(u.Error()) + case SCV_U32: + return XDR_Uint32(u.U32()) + case SCV_I32: + return XDR_Int32(u.I32()) + case SCV_U64: + return XDR_Uint64(u.U64()) + case SCV_I64: + return XDR_Int64(u.I64()) + case SCV_TIMEPOINT: + return XDR_TimePoint(u.Timepoint()) + case SCV_DURATION: + return XDR_Duration(u.Duration()) + case SCV_U128: + return XDR_UInt128Parts(u.U128()) + case SCV_I128: + return XDR_Int128Parts(u.I128()) + case SCV_U256: + return XDR_UInt256Parts(u.U256()) + case SCV_I256: + return XDR_Int256Parts(u.I256()) + case SCV_BYTES: + return XDR_SCBytes(u.Bytes()) + case SCV_STRING: + return XDR_SCString(u.Str()) + case SCV_SYMBOL: + return XDR_SCSymbol(u.Sym()) + case SCV_VEC: + return _XdrPtr_SCVec{u.Vec()} + case SCV_MAP: + return _XdrPtr_SCMap{u.Map()} + case SCV_ADDRESS: + return XDR_SCAddress(u.Address()) + case SCV_LEDGER_KEY_CONTRACT_INSTANCE: + return nil + case SCV_LEDGER_KEY_NONCE: + return XDR_SCNonceKey(u.Nonce_key()) + case SCV_CONTRACT_INSTANCE: + return XDR_SCContractInstance(u.Instance()) } return nil } -func (u *XdrAnon_TransactionResult_Result) XdrUnionBodyName() string { - switch u.Code { - case TxFEE_BUMP_INNER_SUCCESS, TxFEE_BUMP_INNER_FAILED: - return "InnerResultPair" - case TxSUCCESS, TxFAILED: - return "Results" - case TxTOO_EARLY, TxTOO_LATE, TxMISSING_OPERATION, TxBAD_SEQ, TxBAD_AUTH, TxINSUFFICIENT_BALANCE, TxNO_ACCOUNT, TxINSUFFICIENT_FEE, TxBAD_AUTH_EXTRA, TxINTERNAL_ERROR, TxNOT_SUPPORTED, TxBAD_SPONSORSHIP, TxBAD_MIN_SEQ_AGE_OR_GAP, TxMALFORMED: +func (u *SCVal) XdrUnionBodyName() string { + switch u.Type { + case SCV_BOOL: + return "B" + case SCV_VOID: return "" + case SCV_ERROR: + return "Error" + case SCV_U32: + return "U32" + case SCV_I32: + return "I32" + case SCV_U64: + return "U64" + case SCV_I64: + return "I64" + case SCV_TIMEPOINT: + return "Timepoint" + case SCV_DURATION: + return "Duration" + case SCV_U128: + return "U128" + case SCV_I128: + return "I128" + case SCV_U256: + return "U256" + case SCV_I256: + return "I256" + case SCV_BYTES: + return "Bytes" + case SCV_STRING: + return "Str" + case SCV_SYMBOL: + return "Sym" + case SCV_VEC: + return "Vec" + case SCV_MAP: + return "Map" + case SCV_ADDRESS: + return "Address" + case SCV_LEDGER_KEY_CONTRACT_INSTANCE: + return "" + case SCV_LEDGER_KEY_NONCE: + return "Nonce_key" + case SCV_CONTRACT_INSTANCE: + return "Instance" } return "" } -type XdrType_XdrAnon_TransactionResult_Result = *XdrAnon_TransactionResult_Result +type XdrType_SCVal = *SCVal -func (v *XdrAnon_TransactionResult_Result) XdrPointer() interface{} { return v } -func (XdrAnon_TransactionResult_Result) XdrTypeName() string { - return "XdrAnon_TransactionResult_Result" -} -func (v XdrAnon_TransactionResult_Result) XdrValue() interface{} { return v } -func (v *XdrAnon_TransactionResult_Result) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -func (u *XdrAnon_TransactionResult_Result) XdrRecurse(x XDR, name string) { +func (v *SCVal) XdrPointer() interface{} { return v } +func (SCVal) XdrTypeName() string { return "SCVal" } +func (v SCVal) XdrValue() interface{} { return v } +func (v *SCVal) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (u *SCVal) XdrRecurse(x XDR, name string) { if name != "" { name = x.Sprintf("%s.", name) } - XDR_TransactionResultCode(&u.Code).XdrMarshal(x, x.Sprintf("%scode", name)) - switch u.Code { - case TxFEE_BUMP_INNER_SUCCESS, TxFEE_BUMP_INNER_FAILED: - x.Marshal(x.Sprintf("%sinnerResultPair", name), XDR_InnerTransactionResultPair(u.InnerResultPair())) + XDR_SCValType(&u.Type).XdrMarshal(x, x.Sprintf("%stype", name)) + switch u.Type { + case SCV_BOOL: + x.Marshal(x.Sprintf("%sb", name), XDR_bool(u.B())) return - case TxSUCCESS, TxFAILED: - x.Marshal(x.Sprintf("%sresults", name), (*_XdrVec_unbounded_OperationResult)(u.Results())) + case SCV_VOID: + return + case SCV_ERROR: + x.Marshal(x.Sprintf("%serror", name), XDR_SCError(u.Error())) + return + case SCV_U32: + x.Marshal(x.Sprintf("%su32", name), XDR_Uint32(u.U32())) + return + case SCV_I32: + x.Marshal(x.Sprintf("%si32", name), XDR_Int32(u.I32())) + return + case SCV_U64: + x.Marshal(x.Sprintf("%su64", name), XDR_Uint64(u.U64())) + return + case SCV_I64: + x.Marshal(x.Sprintf("%si64", name), XDR_Int64(u.I64())) + return + case SCV_TIMEPOINT: + x.Marshal(x.Sprintf("%stimepoint", name), XDR_TimePoint(u.Timepoint())) + return + case SCV_DURATION: + x.Marshal(x.Sprintf("%sduration", name), XDR_Duration(u.Duration())) + return + case SCV_U128: + x.Marshal(x.Sprintf("%su128", name), XDR_UInt128Parts(u.U128())) + return + case SCV_I128: + x.Marshal(x.Sprintf("%si128", name), XDR_Int128Parts(u.I128())) + return + case SCV_U256: + x.Marshal(x.Sprintf("%su256", name), XDR_UInt256Parts(u.U256())) + return + case SCV_I256: + x.Marshal(x.Sprintf("%si256", name), XDR_Int256Parts(u.I256())) + return + case SCV_BYTES: + x.Marshal(x.Sprintf("%sbytes", name), XDR_SCBytes(u.Bytes())) + return + case SCV_STRING: + x.Marshal(x.Sprintf("%sstr", name), XDR_SCString(u.Str())) + return + case SCV_SYMBOL: + x.Marshal(x.Sprintf("%ssym", name), XDR_SCSymbol(u.Sym())) + return + case SCV_VEC: + x.Marshal(x.Sprintf("%svec", name), _XdrPtr_SCVec{u.Vec()}) return - case TxTOO_EARLY, TxTOO_LATE, TxMISSING_OPERATION, TxBAD_SEQ, TxBAD_AUTH, TxINSUFFICIENT_BALANCE, TxNO_ACCOUNT, TxINSUFFICIENT_FEE, TxBAD_AUTH_EXTRA, TxINTERNAL_ERROR, TxNOT_SUPPORTED, TxBAD_SPONSORSHIP, TxBAD_MIN_SEQ_AGE_OR_GAP, TxMALFORMED: + case SCV_MAP: + x.Marshal(x.Sprintf("%smap", name), _XdrPtr_SCMap{u.Map()}) + return + case SCV_ADDRESS: + x.Marshal(x.Sprintf("%saddress", name), XDR_SCAddress(u.Address())) + return + case SCV_LEDGER_KEY_CONTRACT_INSTANCE: + return + case SCV_LEDGER_KEY_NONCE: + x.Marshal(x.Sprintf("%snonce_key", name), XDR_SCNonceKey(u.Nonce_key())) + return + case SCV_CONTRACT_INSTANCE: + x.Marshal(x.Sprintf("%sinstance", name), XDR_SCContractInstance(u.Instance())) return } - XdrPanic("invalid Code (%v) in XdrAnon_TransactionResult_Result", u.Code) + XdrPanic("invalid Type (%v) in SCVal", u.Type) } -func XDR_XdrAnon_TransactionResult_Result(v *XdrAnon_TransactionResult_Result) *XdrAnon_TransactionResult_Result { - return v +func XDR_SCVal(v *SCVal) *SCVal { return v } + +type XdrType_SCMapEntry = *SCMapEntry + +func (v *SCMapEntry) XdrPointer() interface{} { return v } +func (SCMapEntry) XdrTypeName() string { return "SCMapEntry" } +func (v SCMapEntry) XdrValue() interface{} { return v } +func (v *SCMapEntry) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v *SCMapEntry) XdrRecurse(x XDR, name string) { + if name != "" { + name = x.Sprintf("%s.", name) + } + x.Marshal(x.Sprintf("%skey", name), XDR_SCVal(&v.Key)) + x.Marshal(x.Sprintf("%sval", name), XDR_SCVal(&v.Val)) } +func XDR_SCMapEntry(v *SCMapEntry) *SCMapEntry { return v } -var _XdrTags_XdrAnon_TransactionResult_Ext = map[int32]bool{ +var _XdrTags_StoredTransactionSet = map[int32]bool{ XdrToI32(0): true, + XdrToI32(1): true, } -func (_ XdrAnon_TransactionResult_Ext) XdrValidTags() map[int32]bool { - return _XdrTags_XdrAnon_TransactionResult_Ext +func (_ StoredTransactionSet) XdrValidTags() map[int32]bool { + return _XdrTags_StoredTransactionSet +} +func (u *StoredTransactionSet) TxSet() *TransactionSet { + switch u.V { + case 0: + if v, ok := u._u.(*TransactionSet); ok { + return v + } else { + var zero TransactionSet + u._u = &zero + return &zero + } + default: + XdrPanic("StoredTransactionSet.TxSet accessed when V == %v", u.V) + return nil + } +} +func (u *StoredTransactionSet) GeneralizedTxSet() *GeneralizedTransactionSet { + switch u.V { + case 1: + if v, ok := u._u.(*GeneralizedTransactionSet); ok { + return v + } else { + var zero GeneralizedTransactionSet + u._u = &zero + return &zero + } + default: + XdrPanic("StoredTransactionSet.GeneralizedTxSet accessed when V == %v", u.V) + return nil + } } -func (u XdrAnon_TransactionResult_Ext) XdrValid() bool { +func (u StoredTransactionSet) XdrValid() bool { switch u.V { - case 0: + case 0, 1: return true } return false } -func (u *XdrAnon_TransactionResult_Ext) XdrUnionTag() XdrNum32 { +func (u *StoredTransactionSet) XdrUnionTag() XdrNum32 { return XDR_int32(&u.V) } -func (u *XdrAnon_TransactionResult_Ext) XdrUnionTagName() string { +func (u *StoredTransactionSet) XdrUnionTagName() string { return "V" } -func (u *XdrAnon_TransactionResult_Ext) XdrUnionBody() XdrType { +func (u *StoredTransactionSet) XdrUnionBody() XdrType { switch u.V { case 0: - return nil + return XDR_TransactionSet(u.TxSet()) + case 1: + return XDR_GeneralizedTransactionSet(u.GeneralizedTxSet()) } return nil } -func (u *XdrAnon_TransactionResult_Ext) XdrUnionBodyName() string { +func (u *StoredTransactionSet) XdrUnionBodyName() string { switch u.V { case 0: - return "" + return "TxSet" + case 1: + return "GeneralizedTxSet" } return "" } -type XdrType_XdrAnon_TransactionResult_Ext = *XdrAnon_TransactionResult_Ext +type XdrType_StoredTransactionSet = *StoredTransactionSet -func (v *XdrAnon_TransactionResult_Ext) XdrPointer() interface{} { return v } -func (XdrAnon_TransactionResult_Ext) XdrTypeName() string { return "XdrAnon_TransactionResult_Ext" } -func (v XdrAnon_TransactionResult_Ext) XdrValue() interface{} { return v } -func (v *XdrAnon_TransactionResult_Ext) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -func (u *XdrAnon_TransactionResult_Ext) XdrRecurse(x XDR, name string) { +func (v *StoredTransactionSet) XdrPointer() interface{} { return v } +func (StoredTransactionSet) XdrTypeName() string { return "StoredTransactionSet" } +func (v StoredTransactionSet) XdrValue() interface{} { return v } +func (v *StoredTransactionSet) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (u *StoredTransactionSet) XdrRecurse(x XDR, name string) { if name != "" { name = x.Sprintf("%s.", name) } XDR_int32(&u.V).XdrMarshal(x, x.Sprintf("%sv", name)) switch u.V { case 0: + x.Marshal(x.Sprintf("%stxSet", name), XDR_TransactionSet(u.TxSet())) + return + case 1: + x.Marshal(x.Sprintf("%sgeneralizedTxSet", name), XDR_GeneralizedTransactionSet(u.GeneralizedTxSet())) return } - XdrPanic("invalid V (%v) in XdrAnon_TransactionResult_Ext", u.V) -} -func XDR_XdrAnon_TransactionResult_Ext(v *XdrAnon_TransactionResult_Ext) *XdrAnon_TransactionResult_Ext { - return v + XdrPanic("invalid V (%v) in StoredTransactionSet", u.V) } +func XDR_StoredTransactionSet(v *StoredTransactionSet) *StoredTransactionSet { return v } -type XdrType_TransactionResult = *TransactionResult +type XdrType_StoredDebugTransactionSet = *StoredDebugTransactionSet -func (v *TransactionResult) XdrPointer() interface{} { return v } -func (TransactionResult) XdrTypeName() string { return "TransactionResult" } -func (v TransactionResult) XdrValue() interface{} { return v } -func (v *TransactionResult) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -func (v *TransactionResult) XdrRecurse(x XDR, name string) { +func (v *StoredDebugTransactionSet) XdrPointer() interface{} { return v } +func (StoredDebugTransactionSet) XdrTypeName() string { return "StoredDebugTransactionSet" } +func (v StoredDebugTransactionSet) XdrValue() interface{} { return v } +func (v *StoredDebugTransactionSet) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v *StoredDebugTransactionSet) XdrRecurse(x XDR, name string) { if name != "" { name = x.Sprintf("%s.", name) } - x.Marshal(x.Sprintf("%sfeeCharged", name), XDR_Int64(&v.FeeCharged)) - x.Marshal(x.Sprintf("%sresult", name), XDR_XdrAnon_TransactionResult_Result(&v.Result)) - x.Marshal(x.Sprintf("%sext", name), XDR_XdrAnon_TransactionResult_Ext(&v.Ext)) + x.Marshal(x.Sprintf("%stxSet", name), XDR_StoredTransactionSet(&v.TxSet)) + x.Marshal(x.Sprintf("%sledgerSeq", name), XDR_Uint32(&v.LedgerSeq)) + x.Marshal(x.Sprintf("%sscpValue", name), XDR_StellarValue(&v.ScpValue)) } -func XDR_TransactionResult(v *TransactionResult) *TransactionResult { return v } +func XDR_StoredDebugTransactionSet(v *StoredDebugTransactionSet) *StoredDebugTransactionSet { return v } -type _XdrArray_32_opaque [32]byte +type _XdrVec_unbounded_StoredTransactionSet []StoredTransactionSet -func (v *_XdrArray_32_opaque) GetByteSlice() []byte { return v[:] } -func (v *_XdrArray_32_opaque) XdrTypeName() string { return "opaque[]" } -func (v *_XdrArray_32_opaque) XdrValue() interface{} { return v[:] } -func (v *_XdrArray_32_opaque) XdrPointer() interface{} { return (*[32]byte)(v) } -func (v *_XdrArray_32_opaque) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -func (v *_XdrArray_32_opaque) String() string { return fmt.Sprintf("%x", v[:]) } -func (v *_XdrArray_32_opaque) Scan(ss fmt.ScanState, c rune) error { - return XdrArrayOpaqueScan(v[:], ss, c) -} -func (_XdrArray_32_opaque) XdrArraySize() uint32 { - const bound uint32 = 32 // Force error if not const or doesn't fit +func (_XdrVec_unbounded_StoredTransactionSet) XdrBound() uint32 { + const bound uint32 = 4294967295 // Force error if not const or doesn't fit return bound } - -type XdrType_Hash struct { - *_XdrArray_32_opaque -} - -func XDR_Hash(v *Hash) XdrType_Hash { - return XdrType_Hash{(*_XdrArray_32_opaque)(v)} -} -func (XdrType_Hash) XdrTypeName() string { return "Hash" } -func (v XdrType_Hash) XdrUnwrap() XdrType { return v._XdrArray_32_opaque } - -type XdrType_Uint256 struct { - *_XdrArray_32_opaque +func (_XdrVec_unbounded_StoredTransactionSet) XdrCheckLen(length uint32) { + if length > uint32(4294967295) { + XdrPanic("_XdrVec_unbounded_StoredTransactionSet length %d exceeds bound 4294967295", length) + } else if int(length) < 0 { + XdrPanic("_XdrVec_unbounded_StoredTransactionSet length %d exceeds max int", length) + } } - -func XDR_Uint256(v *Uint256) XdrType_Uint256 { - return XdrType_Uint256{(*_XdrArray_32_opaque)(v)} +func (v _XdrVec_unbounded_StoredTransactionSet) GetVecLen() uint32 { return uint32(len(v)) } +func (v *_XdrVec_unbounded_StoredTransactionSet) SetVecLen(length uint32) { + v.XdrCheckLen(length) + if int(length) <= cap(*v) { + if int(length) != len(*v) { + *v = (*v)[:int(length)] + } + return + } + newcap := 2 * cap(*v) + if newcap < int(length) { // also catches overflow where 2*cap < 0 + newcap = int(length) + } else if bound := uint(4294967295); uint(newcap) > bound { + if int(bound) < 0 { + bound = ^uint(0) >> 1 + } + newcap = int(bound) + } + nv := make([]StoredTransactionSet, int(length), newcap) + copy(nv, *v) + *v = nv } -func (XdrType_Uint256) XdrTypeName() string { return "Uint256" } -func (v XdrType_Uint256) XdrUnwrap() XdrType { return v._XdrArray_32_opaque } - -type XdrType_Uint32 struct { - XdrType_uint32 +func (v *_XdrVec_unbounded_StoredTransactionSet) XdrMarshalN(x XDR, name string, n uint32) { + v.XdrCheckLen(n) + for i := 0; i < int(n); i++ { + if i >= len(*v) { + v.SetVecLen(uint32(i + 1)) + } + XDR_StoredTransactionSet(&(*v)[i]).XdrMarshal(x, x.Sprintf("%s[%d]", name, i)) + } + if int(n) < len(*v) { + *v = (*v)[:int(n)] + } } - -func XDR_Uint32(v *Uint32) XdrType_Uint32 { - return XdrType_Uint32{XDR_uint32(v)} +func (v *_XdrVec_unbounded_StoredTransactionSet) XdrRecurse(x XDR, name string) { + size := XdrSize{Size: uint32(len(*v)), Bound: 4294967295} + x.Marshal(name, &size) + v.XdrMarshalN(x, name, size.Size) } -func (XdrType_Uint32) XdrTypeName() string { return "Uint32" } -func (v XdrType_Uint32) XdrUnwrap() XdrType { return v.XdrType_uint32 } - -type XdrType_Int32 struct { - XdrType_int32 +func (_XdrVec_unbounded_StoredTransactionSet) XdrTypeName() string { return "StoredTransactionSet<>" } +func (v *_XdrVec_unbounded_StoredTransactionSet) XdrPointer() interface{} { + return (*[]StoredTransactionSet)(v) } - -func XDR_Int32(v *Int32) XdrType_Int32 { - return XdrType_Int32{XDR_int32(v)} +func (v _XdrVec_unbounded_StoredTransactionSet) XdrValue() interface{} { + return ([]StoredTransactionSet)(v) } -func (XdrType_Int32) XdrTypeName() string { return "Int32" } -func (v XdrType_Int32) XdrUnwrap() XdrType { return v.XdrType_int32 } +func (v *_XdrVec_unbounded_StoredTransactionSet) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -type XdrType_Uint64 struct { - XdrType_uint64 -} +type XdrType_PersistedSCPStateV0 = *PersistedSCPStateV0 -func XDR_Uint64(v *Uint64) XdrType_Uint64 { - return XdrType_Uint64{XDR_uint64(v)} +func (v *PersistedSCPStateV0) XdrPointer() interface{} { return v } +func (PersistedSCPStateV0) XdrTypeName() string { return "PersistedSCPStateV0" } +func (v PersistedSCPStateV0) XdrValue() interface{} { return v } +func (v *PersistedSCPStateV0) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v *PersistedSCPStateV0) XdrRecurse(x XDR, name string) { + if name != "" { + name = x.Sprintf("%s.", name) + } + x.Marshal(x.Sprintf("%sscpEnvelopes", name), (*_XdrVec_unbounded_SCPEnvelope)(&v.ScpEnvelopes)) + x.Marshal(x.Sprintf("%squorumSets", name), (*_XdrVec_unbounded_SCPQuorumSet)(&v.QuorumSets)) + x.Marshal(x.Sprintf("%stxSets", name), (*_XdrVec_unbounded_StoredTransactionSet)(&v.TxSets)) } -func (XdrType_Uint64) XdrTypeName() string { return "Uint64" } -func (v XdrType_Uint64) XdrUnwrap() XdrType { return v.XdrType_uint64 } +func XDR_PersistedSCPStateV0(v *PersistedSCPStateV0) *PersistedSCPStateV0 { return v } -type XdrType_Int64 struct { - XdrType_int64 -} +type XdrType_PersistedSCPStateV1 = *PersistedSCPStateV1 -func XDR_Int64(v *Int64) XdrType_Int64 { - return XdrType_Int64{XDR_int64(v)} +func (v *PersistedSCPStateV1) XdrPointer() interface{} { return v } +func (PersistedSCPStateV1) XdrTypeName() string { return "PersistedSCPStateV1" } +func (v PersistedSCPStateV1) XdrValue() interface{} { return v } +func (v *PersistedSCPStateV1) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v *PersistedSCPStateV1) XdrRecurse(x XDR, name string) { + if name != "" { + name = x.Sprintf("%s.", name) + } + x.Marshal(x.Sprintf("%sscpEnvelopes", name), (*_XdrVec_unbounded_SCPEnvelope)(&v.ScpEnvelopes)) + x.Marshal(x.Sprintf("%squorumSets", name), (*_XdrVec_unbounded_SCPQuorumSet)(&v.QuorumSets)) } -func (XdrType_Int64) XdrTypeName() string { return "Int64" } -func (v XdrType_Int64) XdrUnwrap() XdrType { return v.XdrType_int64 } +func XDR_PersistedSCPStateV1(v *PersistedSCPStateV1) *PersistedSCPStateV1 { return v } -var _XdrTags_ExtensionPoint = map[int32]bool{ +var _XdrTags_PersistedSCPState = map[int32]bool{ XdrToI32(0): true, + XdrToI32(1): true, } -func (_ ExtensionPoint) XdrValidTags() map[int32]bool { - return _XdrTags_ExtensionPoint +func (_ PersistedSCPState) XdrValidTags() map[int32]bool { + return _XdrTags_PersistedSCPState } -func (u ExtensionPoint) XdrValid() bool { +func (u *PersistedSCPState) V0() *PersistedSCPStateV0 { switch u.V { case 0: + if v, ok := u._u.(*PersistedSCPStateV0); ok { + return v + } else { + var zero PersistedSCPStateV0 + u._u = &zero + return &zero + } + default: + XdrPanic("PersistedSCPState.V0 accessed when V == %v", u.V) + return nil + } +} +func (u *PersistedSCPState) V1() *PersistedSCPStateV1 { + switch u.V { + case 1: + if v, ok := u._u.(*PersistedSCPStateV1); ok { + return v + } else { + var zero PersistedSCPStateV1 + u._u = &zero + return &zero + } + default: + XdrPanic("PersistedSCPState.V1 accessed when V == %v", u.V) + return nil + } +} +func (u PersistedSCPState) XdrValid() bool { + switch u.V { + case 0, 1: return true } return false } -func (u *ExtensionPoint) XdrUnionTag() XdrNum32 { +func (u *PersistedSCPState) XdrUnionTag() XdrNum32 { return XDR_int32(&u.V) } -func (u *ExtensionPoint) XdrUnionTagName() string { +func (u *PersistedSCPState) XdrUnionTagName() string { return "V" } -func (u *ExtensionPoint) XdrUnionBody() XdrType { +func (u *PersistedSCPState) XdrUnionBody() XdrType { switch u.V { case 0: - return nil + return XDR_PersistedSCPStateV0(u.V0()) + case 1: + return XDR_PersistedSCPStateV1(u.V1()) } return nil } -func (u *ExtensionPoint) XdrUnionBodyName() string { +func (u *PersistedSCPState) XdrUnionBodyName() string { switch u.V { case 0: - return "" + return "V0" + case 1: + return "V1" } return "" } -type XdrType_ExtensionPoint = *ExtensionPoint +type XdrType_PersistedSCPState = *PersistedSCPState -func (v *ExtensionPoint) XdrPointer() interface{} { return v } -func (ExtensionPoint) XdrTypeName() string { return "ExtensionPoint" } -func (v ExtensionPoint) XdrValue() interface{} { return v } -func (v *ExtensionPoint) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -func (u *ExtensionPoint) XdrRecurse(x XDR, name string) { +func (v *PersistedSCPState) XdrPointer() interface{} { return v } +func (PersistedSCPState) XdrTypeName() string { return "PersistedSCPState" } +func (v PersistedSCPState) XdrValue() interface{} { return v } +func (v *PersistedSCPState) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (u *PersistedSCPState) XdrRecurse(x XDR, name string) { if name != "" { name = x.Sprintf("%s.", name) } XDR_int32(&u.V).XdrMarshal(x, x.Sprintf("%sv", name)) switch u.V { case 0: + x.Marshal(x.Sprintf("%sv0", name), XDR_PersistedSCPStateV0(u.V0())) + return + case 1: + x.Marshal(x.Sprintf("%sv1", name), XDR_PersistedSCPStateV1(u.V1())) return } - XdrPanic("invalid V (%v) in ExtensionPoint", u.V) + XdrPanic("invalid V (%v) in PersistedSCPState", u.V) } -func XDR_ExtensionPoint(v *ExtensionPoint) *ExtensionPoint { return v } +func XDR_PersistedSCPState(v *PersistedSCPState) *PersistedSCPState { return v } -var _XdrNames_CryptoKeyType = map[int32]string{ - int32(KEY_TYPE_ED25519): "KEY_TYPE_ED25519", - int32(KEY_TYPE_PRE_AUTH_TX): "KEY_TYPE_PRE_AUTH_TX", - int32(KEY_TYPE_HASH_X): "KEY_TYPE_HASH_X", - int32(KEY_TYPE_ED25519_SIGNED_PAYLOAD): "KEY_TYPE_ED25519_SIGNED_PAYLOAD", - int32(KEY_TYPE_MUXED_ED25519): "KEY_TYPE_MUXED_ED25519", +type XdrType_ConfigSettingContractExecutionLanesV0 = *ConfigSettingContractExecutionLanesV0 + +func (v *ConfigSettingContractExecutionLanesV0) XdrPointer() interface{} { return v } +func (ConfigSettingContractExecutionLanesV0) XdrTypeName() string { + return "ConfigSettingContractExecutionLanesV0" } -var _XdrValues_CryptoKeyType = map[string]int32{ - "KEY_TYPE_ED25519": int32(KEY_TYPE_ED25519), - "KEY_TYPE_PRE_AUTH_TX": int32(KEY_TYPE_PRE_AUTH_TX), - "KEY_TYPE_HASH_X": int32(KEY_TYPE_HASH_X), - "KEY_TYPE_ED25519_SIGNED_PAYLOAD": int32(KEY_TYPE_ED25519_SIGNED_PAYLOAD), - "KEY_TYPE_MUXED_ED25519": int32(KEY_TYPE_MUXED_ED25519), +func (v ConfigSettingContractExecutionLanesV0) XdrValue() interface{} { return v } +func (v *ConfigSettingContractExecutionLanesV0) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v *ConfigSettingContractExecutionLanesV0) XdrRecurse(x XDR, name string) { + if name != "" { + name = x.Sprintf("%s.", name) + } + x.Marshal(x.Sprintf("%sledgerMaxTxCount", name), XDR_Uint32(&v.LedgerMaxTxCount)) +} +func XDR_ConfigSettingContractExecutionLanesV0(v *ConfigSettingContractExecutionLanesV0) *ConfigSettingContractExecutionLanesV0 { + return v +} + +type XdrType_ConfigSettingContractComputeV0 = *ConfigSettingContractComputeV0 + +func (v *ConfigSettingContractComputeV0) XdrPointer() interface{} { return v } +func (ConfigSettingContractComputeV0) XdrTypeName() string { return "ConfigSettingContractComputeV0" } +func (v ConfigSettingContractComputeV0) XdrValue() interface{} { return v } +func (v *ConfigSettingContractComputeV0) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v *ConfigSettingContractComputeV0) XdrRecurse(x XDR, name string) { + if name != "" { + name = x.Sprintf("%s.", name) + } + x.Marshal(x.Sprintf("%sledgerMaxInstructions", name), XDR_Int64(&v.LedgerMaxInstructions)) + x.Marshal(x.Sprintf("%stxMaxInstructions", name), XDR_Int64(&v.TxMaxInstructions)) + x.Marshal(x.Sprintf("%sfeeRatePerInstructionsIncrement", name), XDR_Int64(&v.FeeRatePerInstructionsIncrement)) + x.Marshal(x.Sprintf("%stxMemoryLimit", name), XDR_Uint32(&v.TxMemoryLimit)) +} +func XDR_ConfigSettingContractComputeV0(v *ConfigSettingContractComputeV0) *ConfigSettingContractComputeV0 { + return v +} + +type XdrType_ConfigSettingContractLedgerCostV0 = *ConfigSettingContractLedgerCostV0 + +func (v *ConfigSettingContractLedgerCostV0) XdrPointer() interface{} { return v } +func (ConfigSettingContractLedgerCostV0) XdrTypeName() string { + return "ConfigSettingContractLedgerCostV0" +} +func (v ConfigSettingContractLedgerCostV0) XdrValue() interface{} { return v } +func (v *ConfigSettingContractLedgerCostV0) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v *ConfigSettingContractLedgerCostV0) XdrRecurse(x XDR, name string) { + if name != "" { + name = x.Sprintf("%s.", name) + } + x.Marshal(x.Sprintf("%sledgerMaxReadLedgerEntries", name), XDR_Uint32(&v.LedgerMaxReadLedgerEntries)) + x.Marshal(x.Sprintf("%sledgerMaxReadBytes", name), XDR_Uint32(&v.LedgerMaxReadBytes)) + x.Marshal(x.Sprintf("%sledgerMaxWriteLedgerEntries", name), XDR_Uint32(&v.LedgerMaxWriteLedgerEntries)) + x.Marshal(x.Sprintf("%sledgerMaxWriteBytes", name), XDR_Uint32(&v.LedgerMaxWriteBytes)) + x.Marshal(x.Sprintf("%stxMaxReadLedgerEntries", name), XDR_Uint32(&v.TxMaxReadLedgerEntries)) + x.Marshal(x.Sprintf("%stxMaxReadBytes", name), XDR_Uint32(&v.TxMaxReadBytes)) + x.Marshal(x.Sprintf("%stxMaxWriteLedgerEntries", name), XDR_Uint32(&v.TxMaxWriteLedgerEntries)) + x.Marshal(x.Sprintf("%stxMaxWriteBytes", name), XDR_Uint32(&v.TxMaxWriteBytes)) + x.Marshal(x.Sprintf("%sfeeReadLedgerEntry", name), XDR_Int64(&v.FeeReadLedgerEntry)) + x.Marshal(x.Sprintf("%sfeeWriteLedgerEntry", name), XDR_Int64(&v.FeeWriteLedgerEntry)) + x.Marshal(x.Sprintf("%sfeeRead1KB", name), XDR_Int64(&v.FeeRead1KB)) + x.Marshal(x.Sprintf("%sbucketListTargetSizeBytes", name), XDR_Int64(&v.BucketListTargetSizeBytes)) + x.Marshal(x.Sprintf("%swriteFee1KBBucketListLow", name), XDR_Int64(&v.WriteFee1KBBucketListLow)) + x.Marshal(x.Sprintf("%swriteFee1KBBucketListHigh", name), XDR_Int64(&v.WriteFee1KBBucketListHigh)) + x.Marshal(x.Sprintf("%sbucketListWriteFeeGrowthFactor", name), XDR_Uint32(&v.BucketListWriteFeeGrowthFactor)) +} +func XDR_ConfigSettingContractLedgerCostV0(v *ConfigSettingContractLedgerCostV0) *ConfigSettingContractLedgerCostV0 { + return v +} + +type XdrType_ConfigSettingContractHistoricalDataV0 = *ConfigSettingContractHistoricalDataV0 + +func (v *ConfigSettingContractHistoricalDataV0) XdrPointer() interface{} { return v } +func (ConfigSettingContractHistoricalDataV0) XdrTypeName() string { + return "ConfigSettingContractHistoricalDataV0" +} +func (v ConfigSettingContractHistoricalDataV0) XdrValue() interface{} { return v } +func (v *ConfigSettingContractHistoricalDataV0) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v *ConfigSettingContractHistoricalDataV0) XdrRecurse(x XDR, name string) { + if name != "" { + name = x.Sprintf("%s.", name) + } + x.Marshal(x.Sprintf("%sfeeHistorical1KB", name), XDR_Int64(&v.FeeHistorical1KB)) +} +func XDR_ConfigSettingContractHistoricalDataV0(v *ConfigSettingContractHistoricalDataV0) *ConfigSettingContractHistoricalDataV0 { + return v +} + +type XdrType_ConfigSettingContractEventsV0 = *ConfigSettingContractEventsV0 + +func (v *ConfigSettingContractEventsV0) XdrPointer() interface{} { return v } +func (ConfigSettingContractEventsV0) XdrTypeName() string { return "ConfigSettingContractEventsV0" } +func (v ConfigSettingContractEventsV0) XdrValue() interface{} { return v } +func (v *ConfigSettingContractEventsV0) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v *ConfigSettingContractEventsV0) XdrRecurse(x XDR, name string) { + if name != "" { + name = x.Sprintf("%s.", name) + } + x.Marshal(x.Sprintf("%stxMaxContractEventsSizeBytes", name), XDR_Uint32(&v.TxMaxContractEventsSizeBytes)) + x.Marshal(x.Sprintf("%sfeeContractEvents1KB", name), XDR_Int64(&v.FeeContractEvents1KB)) +} +func XDR_ConfigSettingContractEventsV0(v *ConfigSettingContractEventsV0) *ConfigSettingContractEventsV0 { + return v +} + +type XdrType_ConfigSettingContractBandwidthV0 = *ConfigSettingContractBandwidthV0 + +func (v *ConfigSettingContractBandwidthV0) XdrPointer() interface{} { return v } +func (ConfigSettingContractBandwidthV0) XdrTypeName() string { + return "ConfigSettingContractBandwidthV0" +} +func (v ConfigSettingContractBandwidthV0) XdrValue() interface{} { return v } +func (v *ConfigSettingContractBandwidthV0) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v *ConfigSettingContractBandwidthV0) XdrRecurse(x XDR, name string) { + if name != "" { + name = x.Sprintf("%s.", name) + } + x.Marshal(x.Sprintf("%sledgerMaxTxsSizeBytes", name), XDR_Uint32(&v.LedgerMaxTxsSizeBytes)) + x.Marshal(x.Sprintf("%stxMaxSizeBytes", name), XDR_Uint32(&v.TxMaxSizeBytes)) + x.Marshal(x.Sprintf("%sfeeTxSize1KB", name), XDR_Int64(&v.FeeTxSize1KB)) } - -func (CryptoKeyType) XdrEnumNames() map[int32]string { - return _XdrNames_CryptoKeyType +func XDR_ConfigSettingContractBandwidthV0(v *ConfigSettingContractBandwidthV0) *ConfigSettingContractBandwidthV0 { + return v } -func (v CryptoKeyType) String() string { - if s, ok := _XdrNames_CryptoKeyType[int32(v)]; ok { + +var _XdrNames_ContractCostType = map[int32]string{ + int32(WasmInsnExec): "WasmInsnExec", + int32(MemAlloc): "MemAlloc", + int32(MemCpy): "MemCpy", + int32(MemCmp): "MemCmp", + int32(DispatchHostFunction): "DispatchHostFunction", + int32(VisitObject): "VisitObject", + int32(ValSer): "ValSer", + int32(ValDeser): "ValDeser", + int32(ComputeSha256Hash): "ComputeSha256Hash", + int32(ComputeEd25519PubKey): "ComputeEd25519PubKey", + int32(VerifyEd25519Sig): "VerifyEd25519Sig", + int32(VmInstantiation): "VmInstantiation", + int32(VmCachedInstantiation): "VmCachedInstantiation", + int32(InvokeVmFunction): "InvokeVmFunction", + int32(ComputeKeccak256Hash): "ComputeKeccak256Hash", + int32(ComputeEcdsaSecp256k1Sig): "ComputeEcdsaSecp256k1Sig", + int32(RecoverEcdsaSecp256k1Key): "RecoverEcdsaSecp256k1Key", + int32(Int256AddSub): "Int256AddSub", + int32(Int256Mul): "Int256Mul", + int32(Int256Div): "Int256Div", + int32(Int256Pow): "Int256Pow", + int32(Int256Shift): "Int256Shift", + int32(ChaCha20DrawBytes): "ChaCha20DrawBytes", +} +var _XdrValues_ContractCostType = map[string]int32{ + "WasmInsnExec": int32(WasmInsnExec), + "MemAlloc": int32(MemAlloc), + "MemCpy": int32(MemCpy), + "MemCmp": int32(MemCmp), + "DispatchHostFunction": int32(DispatchHostFunction), + "VisitObject": int32(VisitObject), + "ValSer": int32(ValSer), + "ValDeser": int32(ValDeser), + "ComputeSha256Hash": int32(ComputeSha256Hash), + "ComputeEd25519PubKey": int32(ComputeEd25519PubKey), + "VerifyEd25519Sig": int32(VerifyEd25519Sig), + "VmInstantiation": int32(VmInstantiation), + "VmCachedInstantiation": int32(VmCachedInstantiation), + "InvokeVmFunction": int32(InvokeVmFunction), + "ComputeKeccak256Hash": int32(ComputeKeccak256Hash), + "ComputeEcdsaSecp256k1Sig": int32(ComputeEcdsaSecp256k1Sig), + "RecoverEcdsaSecp256k1Key": int32(RecoverEcdsaSecp256k1Key), + "Int256AddSub": int32(Int256AddSub), + "Int256Mul": int32(Int256Mul), + "Int256Div": int32(Int256Div), + "Int256Pow": int32(Int256Pow), + "Int256Shift": int32(Int256Shift), + "ChaCha20DrawBytes": int32(ChaCha20DrawBytes), +} + +func (ContractCostType) XdrEnumNames() map[int32]string { + return _XdrNames_ContractCostType +} +func (v ContractCostType) String() string { + if s, ok := _XdrNames_ContractCostType[int32(v)]; ok { return s } - return fmt.Sprintf("CryptoKeyType#%d", v) + return fmt.Sprintf("ContractCostType#%d", v) } -func (v *CryptoKeyType) Scan(ss fmt.ScanState, _ rune) error { +func (v *ContractCostType) Scan(ss fmt.ScanState, _ rune) error { if tok, err := ss.Token(true, XdrSymChar); err != nil { return err } else { stok := string(tok) - if val, ok := _XdrValues_CryptoKeyType[stok]; ok { - *v = CryptoKeyType(val) + if val, ok := _XdrValues_ContractCostType[stok]; ok { + *v = ContractCostType(val) return nil - } else if stok == "CryptoKeyType" { + } else if stok == "ContractCostType" { if n, err := fmt.Fscanf(ss, "#%d", (*int32)(v)); n == 1 && err == nil { return nil } } - return XdrError(fmt.Sprintf("%s is not a valid CryptoKeyType.", stok)) + return XdrError(fmt.Sprintf("%s is not a valid ContractCostType.", stok)) + } +} +func (v ContractCostType) GetU32() uint32 { return uint32(v) } +func (v *ContractCostType) SetU32(n uint32) { *v = ContractCostType(n) } +func (v *ContractCostType) XdrPointer() interface{} { return v } +func (ContractCostType) XdrTypeName() string { return "ContractCostType" } +func (v ContractCostType) XdrValue() interface{} { return v } +func (v *ContractCostType) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } + +type XdrType_ContractCostType = *ContractCostType + +func XDR_ContractCostType(v *ContractCostType) *ContractCostType { return v } + +var _XdrComments_ContractCostType = map[int32]string{ + int32(WasmInsnExec): "Cost of running 1 wasm instruction", + int32(MemAlloc): "Cost of allocating a slice of memory (in bytes)", + int32(MemCpy): "Cost of copying a slice of bytes into a pre-allocated memory", + int32(MemCmp): "Cost of comparing two slices of memory", + int32(DispatchHostFunction): "Cost of a host function dispatch, not including the actual work done by the function nor the cost of VM invocation machinary", + int32(VisitObject): "Cost of visiting a host object from the host object storage. Exists to make sure some baseline cost coverage, i.e. repeatly visiting objects by the guest will always incur some charges.", + int32(ValSer): "Cost of serializing an xdr object to bytes", + int32(ValDeser): "Cost of deserializing an xdr object from bytes", + int32(ComputeSha256Hash): "Cost of computing the sha256 hash from bytes", + int32(ComputeEd25519PubKey): "Cost of computing the ed25519 pubkey from bytes", + int32(VerifyEd25519Sig): "Cost of verifying ed25519 signature of a payload.", + int32(VmInstantiation): "Cost of instantiation a VM from wasm bytes code.", + int32(VmCachedInstantiation): "Cost of instantiation a VM from a cached state.", + int32(InvokeVmFunction): "Cost of invoking a function on the VM. If the function is a host function, additional cost will be covered by `DispatchHostFunction`.", + int32(ComputeKeccak256Hash): "Cost of computing a keccak256 hash from bytes.", + int32(ComputeEcdsaSecp256k1Sig): "Cost of computing an ECDSA secp256k1 signature from bytes.", + int32(RecoverEcdsaSecp256k1Key): "Cost of recovering an ECDSA secp256k1 key from a signature.", + int32(Int256AddSub): "Cost of int256 addition (`+`) and subtraction (`-`) operations", + int32(Int256Mul): "Cost of int256 multiplication (`*`) operation", + int32(Int256Div): "Cost of int256 division (`/`) operation", + int32(Int256Pow): "Cost of int256 power (`exp`) operation", + int32(Int256Shift): "Cost of int256 shift (`shl`, `shr`) operation", + int32(ChaCha20DrawBytes): "Cost of drawing random bytes using a ChaCha20 PRNG", +} + +func (e ContractCostType) XdrEnumComments() map[int32]string { + return _XdrComments_ContractCostType +} + +type XdrType_ContractCostParamEntry = *ContractCostParamEntry + +func (v *ContractCostParamEntry) XdrPointer() interface{} { return v } +func (ContractCostParamEntry) XdrTypeName() string { return "ContractCostParamEntry" } +func (v ContractCostParamEntry) XdrValue() interface{} { return v } +func (v *ContractCostParamEntry) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v *ContractCostParamEntry) XdrRecurse(x XDR, name string) { + if name != "" { + name = x.Sprintf("%s.", name) } + x.Marshal(x.Sprintf("%sext", name), XDR_ExtensionPoint(&v.Ext)) + x.Marshal(x.Sprintf("%sconstTerm", name), XDR_Int64(&v.ConstTerm)) + x.Marshal(x.Sprintf("%slinearTerm", name), XDR_Int64(&v.LinearTerm)) } -func (v CryptoKeyType) GetU32() uint32 { return uint32(v) } -func (v *CryptoKeyType) SetU32(n uint32) { *v = CryptoKeyType(n) } -func (v *CryptoKeyType) XdrPointer() interface{} { return v } -func (CryptoKeyType) XdrTypeName() string { return "CryptoKeyType" } -func (v CryptoKeyType) XdrValue() interface{} { return v } -func (v *CryptoKeyType) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func XDR_ContractCostParamEntry(v *ContractCostParamEntry) *ContractCostParamEntry { return v } -type XdrType_CryptoKeyType = *CryptoKeyType - -func XDR_CryptoKeyType(v *CryptoKeyType) *CryptoKeyType { return v } +type XdrType_StateArchivalSettings = *StateArchivalSettings -var _XdrComments_CryptoKeyType = map[int32]string{ - int32(KEY_TYPE_MUXED_ED25519): "MUXED enum values for supported type are derived from the enum values above by ORing them with 0x100", +func (v *StateArchivalSettings) XdrPointer() interface{} { return v } +func (StateArchivalSettings) XdrTypeName() string { return "StateArchivalSettings" } +func (v StateArchivalSettings) XdrValue() interface{} { return v } +func (v *StateArchivalSettings) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v *StateArchivalSettings) XdrRecurse(x XDR, name string) { + if name != "" { + name = x.Sprintf("%s.", name) + } + x.Marshal(x.Sprintf("%smaxEntryTTL", name), XDR_Uint32(&v.MaxEntryTTL)) + x.Marshal(x.Sprintf("%sminTemporaryTTL", name), XDR_Uint32(&v.MinTemporaryTTL)) + x.Marshal(x.Sprintf("%sminPersistentTTL", name), XDR_Uint32(&v.MinPersistentTTL)) + x.Marshal(x.Sprintf("%spersistentRentRateDenominator", name), XDR_Int64(&v.PersistentRentRateDenominator)) + x.Marshal(x.Sprintf("%stempRentRateDenominator", name), XDR_Int64(&v.TempRentRateDenominator)) + x.Marshal(x.Sprintf("%smaxEntriesToArchive", name), XDR_Uint32(&v.MaxEntriesToArchive)) + x.Marshal(x.Sprintf("%sbucketListSizeWindowSampleSize", name), XDR_Uint32(&v.BucketListSizeWindowSampleSize)) + x.Marshal(x.Sprintf("%sevictionScanSize", name), XDR_Uint64(&v.EvictionScanSize)) + x.Marshal(x.Sprintf("%sstartingEvictionScanLevel", name), XDR_Uint32(&v.StartingEvictionScanLevel)) +} +func XDR_StateArchivalSettings(v *StateArchivalSettings) *StateArchivalSettings { return v } + +type XdrType_EvictionIterator = *EvictionIterator + +func (v *EvictionIterator) XdrPointer() interface{} { return v } +func (EvictionIterator) XdrTypeName() string { return "EvictionIterator" } +func (v EvictionIterator) XdrValue() interface{} { return v } +func (v *EvictionIterator) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v *EvictionIterator) XdrRecurse(x XDR, name string) { + if name != "" { + name = x.Sprintf("%s.", name) + } + x.Marshal(x.Sprintf("%sbucketListLevel", name), XDR_Uint32(&v.BucketListLevel)) + x.Marshal(x.Sprintf("%sisCurrBucket", name), XDR_bool(&v.IsCurrBucket)) + x.Marshal(x.Sprintf("%sbucketFileOffset", name), XDR_Uint64(&v.BucketFileOffset)) } +func XDR_EvictionIterator(v *EvictionIterator) *EvictionIterator { return v } -func (e CryptoKeyType) XdrEnumComments() map[int32]string { - return _XdrComments_CryptoKeyType -} +type _XdrVec_1024_ContractCostParamEntry []ContractCostParamEntry -var _XdrNames_PublicKeyType = map[int32]string{ - int32(PUBLIC_KEY_TYPE_ED25519): "PUBLIC_KEY_TYPE_ED25519", +func (_XdrVec_1024_ContractCostParamEntry) XdrBound() uint32 { + const bound uint32 = 1024 // Force error if not const or doesn't fit + return bound } -var _XdrValues_PublicKeyType = map[string]int32{ - "PUBLIC_KEY_TYPE_ED25519": int32(PUBLIC_KEY_TYPE_ED25519), +func (_XdrVec_1024_ContractCostParamEntry) XdrCheckLen(length uint32) { + if length > uint32(1024) { + XdrPanic("_XdrVec_1024_ContractCostParamEntry length %d exceeds bound 1024", length) + } else if int(length) < 0 { + XdrPanic("_XdrVec_1024_ContractCostParamEntry length %d exceeds max int", length) + } } - -func (PublicKeyType) XdrEnumNames() map[int32]string { - return _XdrNames_PublicKeyType +func (v _XdrVec_1024_ContractCostParamEntry) GetVecLen() uint32 { return uint32(len(v)) } +func (v *_XdrVec_1024_ContractCostParamEntry) SetVecLen(length uint32) { + v.XdrCheckLen(length) + if int(length) <= cap(*v) { + if int(length) != len(*v) { + *v = (*v)[:int(length)] + } + return + } + newcap := 2 * cap(*v) + if newcap < int(length) { // also catches overflow where 2*cap < 0 + newcap = int(length) + } else if bound := uint(1024); uint(newcap) > bound { + if int(bound) < 0 { + bound = ^uint(0) >> 1 + } + newcap = int(bound) + } + nv := make([]ContractCostParamEntry, int(length), newcap) + copy(nv, *v) + *v = nv } -func (v PublicKeyType) String() string { - if s, ok := _XdrNames_PublicKeyType[int32(v)]; ok { +func (v *_XdrVec_1024_ContractCostParamEntry) XdrMarshalN(x XDR, name string, n uint32) { + v.XdrCheckLen(n) + for i := 0; i < int(n); i++ { + if i >= len(*v) { + v.SetVecLen(uint32(i + 1)) + } + XDR_ContractCostParamEntry(&(*v)[i]).XdrMarshal(x, x.Sprintf("%s[%d]", name, i)) + } + if int(n) < len(*v) { + *v = (*v)[:int(n)] + } +} +func (v *_XdrVec_1024_ContractCostParamEntry) XdrRecurse(x XDR, name string) { + size := XdrSize{Size: uint32(len(*v)), Bound: 1024} + x.Marshal(name, &size) + v.XdrMarshalN(x, name, size.Size) +} +func (_XdrVec_1024_ContractCostParamEntry) XdrTypeName() string { return "ContractCostParamEntry<>" } +func (v *_XdrVec_1024_ContractCostParamEntry) XdrPointer() interface{} { + return (*[]ContractCostParamEntry)(v) +} +func (v _XdrVec_1024_ContractCostParamEntry) XdrValue() interface{} { + return ([]ContractCostParamEntry)(v) +} +func (v *_XdrVec_1024_ContractCostParamEntry) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } + +type XdrType_ContractCostParams struct { + *_XdrVec_1024_ContractCostParamEntry +} + +func XDR_ContractCostParams(v *ContractCostParams) XdrType_ContractCostParams { + return XdrType_ContractCostParams{(*_XdrVec_1024_ContractCostParamEntry)(v)} +} +func (XdrType_ContractCostParams) XdrTypeName() string { return "ContractCostParams" } +func (v XdrType_ContractCostParams) XdrUnwrap() XdrType { return v._XdrVec_1024_ContractCostParamEntry } + +var _XdrNames_ConfigSettingID = map[int32]string{ + int32(CONFIG_SETTING_CONTRACT_MAX_SIZE_BYTES): "CONFIG_SETTING_CONTRACT_MAX_SIZE_BYTES", + int32(CONFIG_SETTING_CONTRACT_COMPUTE_V0): "CONFIG_SETTING_CONTRACT_COMPUTE_V0", + int32(CONFIG_SETTING_CONTRACT_LEDGER_COST_V0): "CONFIG_SETTING_CONTRACT_LEDGER_COST_V0", + int32(CONFIG_SETTING_CONTRACT_HISTORICAL_DATA_V0): "CONFIG_SETTING_CONTRACT_HISTORICAL_DATA_V0", + int32(CONFIG_SETTING_CONTRACT_EVENTS_V0): "CONFIG_SETTING_CONTRACT_EVENTS_V0", + int32(CONFIG_SETTING_CONTRACT_BANDWIDTH_V0): "CONFIG_SETTING_CONTRACT_BANDWIDTH_V0", + int32(CONFIG_SETTING_CONTRACT_COST_PARAMS_CPU_INSTRUCTIONS): "CONFIG_SETTING_CONTRACT_COST_PARAMS_CPU_INSTRUCTIONS", + int32(CONFIG_SETTING_CONTRACT_COST_PARAMS_MEMORY_BYTES): "CONFIG_SETTING_CONTRACT_COST_PARAMS_MEMORY_BYTES", + int32(CONFIG_SETTING_CONTRACT_DATA_KEY_SIZE_BYTES): "CONFIG_SETTING_CONTRACT_DATA_KEY_SIZE_BYTES", + int32(CONFIG_SETTING_CONTRACT_DATA_ENTRY_SIZE_BYTES): "CONFIG_SETTING_CONTRACT_DATA_ENTRY_SIZE_BYTES", + int32(CONFIG_SETTING_STATE_ARCHIVAL): "CONFIG_SETTING_STATE_ARCHIVAL", + int32(CONFIG_SETTING_CONTRACT_EXECUTION_LANES): "CONFIG_SETTING_CONTRACT_EXECUTION_LANES", + int32(CONFIG_SETTING_BUCKETLIST_SIZE_WINDOW): "CONFIG_SETTING_BUCKETLIST_SIZE_WINDOW", + int32(CONFIG_SETTING_EVICTION_ITERATOR): "CONFIG_SETTING_EVICTION_ITERATOR", +} +var _XdrValues_ConfigSettingID = map[string]int32{ + "CONFIG_SETTING_CONTRACT_MAX_SIZE_BYTES": int32(CONFIG_SETTING_CONTRACT_MAX_SIZE_BYTES), + "CONFIG_SETTING_CONTRACT_COMPUTE_V0": int32(CONFIG_SETTING_CONTRACT_COMPUTE_V0), + "CONFIG_SETTING_CONTRACT_LEDGER_COST_V0": int32(CONFIG_SETTING_CONTRACT_LEDGER_COST_V0), + "CONFIG_SETTING_CONTRACT_HISTORICAL_DATA_V0": int32(CONFIG_SETTING_CONTRACT_HISTORICAL_DATA_V0), + "CONFIG_SETTING_CONTRACT_EVENTS_V0": int32(CONFIG_SETTING_CONTRACT_EVENTS_V0), + "CONFIG_SETTING_CONTRACT_BANDWIDTH_V0": int32(CONFIG_SETTING_CONTRACT_BANDWIDTH_V0), + "CONFIG_SETTING_CONTRACT_COST_PARAMS_CPU_INSTRUCTIONS": int32(CONFIG_SETTING_CONTRACT_COST_PARAMS_CPU_INSTRUCTIONS), + "CONFIG_SETTING_CONTRACT_COST_PARAMS_MEMORY_BYTES": int32(CONFIG_SETTING_CONTRACT_COST_PARAMS_MEMORY_BYTES), + "CONFIG_SETTING_CONTRACT_DATA_KEY_SIZE_BYTES": int32(CONFIG_SETTING_CONTRACT_DATA_KEY_SIZE_BYTES), + "CONFIG_SETTING_CONTRACT_DATA_ENTRY_SIZE_BYTES": int32(CONFIG_SETTING_CONTRACT_DATA_ENTRY_SIZE_BYTES), + "CONFIG_SETTING_STATE_ARCHIVAL": int32(CONFIG_SETTING_STATE_ARCHIVAL), + "CONFIG_SETTING_CONTRACT_EXECUTION_LANES": int32(CONFIG_SETTING_CONTRACT_EXECUTION_LANES), + "CONFIG_SETTING_BUCKETLIST_SIZE_WINDOW": int32(CONFIG_SETTING_BUCKETLIST_SIZE_WINDOW), + "CONFIG_SETTING_EVICTION_ITERATOR": int32(CONFIG_SETTING_EVICTION_ITERATOR), +} + +func (ConfigSettingID) XdrEnumNames() map[int32]string { + return _XdrNames_ConfigSettingID +} +func (v ConfigSettingID) String() string { + if s, ok := _XdrNames_ConfigSettingID[int32(v)]; ok { return s } - return fmt.Sprintf("PublicKeyType#%d", v) + return fmt.Sprintf("ConfigSettingID#%d", v) } -func (v *PublicKeyType) Scan(ss fmt.ScanState, _ rune) error { +func (v *ConfigSettingID) Scan(ss fmt.ScanState, _ rune) error { if tok, err := ss.Token(true, XdrSymChar); err != nil { return err } else { stok := string(tok) - if val, ok := _XdrValues_PublicKeyType[stok]; ok { - *v = PublicKeyType(val) + if val, ok := _XdrValues_ConfigSettingID[stok]; ok { + *v = ConfigSettingID(val) return nil - } else if stok == "PublicKeyType" { + } else if stok == "ConfigSettingID" { if n, err := fmt.Fscanf(ss, "#%d", (*int32)(v)); n == 1 && err == nil { return nil } } - return XdrError(fmt.Sprintf("%s is not a valid PublicKeyType.", stok)) + return XdrError(fmt.Sprintf("%s is not a valid ConfigSettingID.", stok)) } } -func (v PublicKeyType) GetU32() uint32 { return uint32(v) } -func (v *PublicKeyType) SetU32(n uint32) { *v = PublicKeyType(n) } -func (v *PublicKeyType) XdrPointer() interface{} { return v } -func (PublicKeyType) XdrTypeName() string { return "PublicKeyType" } -func (v PublicKeyType) XdrValue() interface{} { return v } -func (v *PublicKeyType) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v ConfigSettingID) GetU32() uint32 { return uint32(v) } +func (v *ConfigSettingID) SetU32(n uint32) { *v = ConfigSettingID(n) } +func (v *ConfigSettingID) XdrPointer() interface{} { return v } +func (ConfigSettingID) XdrTypeName() string { return "ConfigSettingID" } +func (v ConfigSettingID) XdrValue() interface{} { return v } +func (v *ConfigSettingID) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -type XdrType_PublicKeyType = *PublicKeyType +type XdrType_ConfigSettingID = *ConfigSettingID -func XDR_PublicKeyType(v *PublicKeyType) *PublicKeyType { return v } +func XDR_ConfigSettingID(v *ConfigSettingID) *ConfigSettingID { return v } -var _XdrNames_SignerKeyType = map[int32]string{ - int32(SIGNER_KEY_TYPE_ED25519): "SIGNER_KEY_TYPE_ED25519", - int32(SIGNER_KEY_TYPE_PRE_AUTH_TX): "SIGNER_KEY_TYPE_PRE_AUTH_TX", - int32(SIGNER_KEY_TYPE_HASH_X): "SIGNER_KEY_TYPE_HASH_X", - int32(SIGNER_KEY_TYPE_ED25519_SIGNED_PAYLOAD): "SIGNER_KEY_TYPE_ED25519_SIGNED_PAYLOAD", +type _XdrVec_unbounded_Uint64 []Uint64 + +func (_XdrVec_unbounded_Uint64) XdrBound() uint32 { + const bound uint32 = 4294967295 // Force error if not const or doesn't fit + return bound } -var _XdrValues_SignerKeyType = map[string]int32{ - "SIGNER_KEY_TYPE_ED25519": int32(SIGNER_KEY_TYPE_ED25519), - "SIGNER_KEY_TYPE_PRE_AUTH_TX": int32(SIGNER_KEY_TYPE_PRE_AUTH_TX), - "SIGNER_KEY_TYPE_HASH_X": int32(SIGNER_KEY_TYPE_HASH_X), - "SIGNER_KEY_TYPE_ED25519_SIGNED_PAYLOAD": int32(SIGNER_KEY_TYPE_ED25519_SIGNED_PAYLOAD), +func (_XdrVec_unbounded_Uint64) XdrCheckLen(length uint32) { + if length > uint32(4294967295) { + XdrPanic("_XdrVec_unbounded_Uint64 length %d exceeds bound 4294967295", length) + } else if int(length) < 0 { + XdrPanic("_XdrVec_unbounded_Uint64 length %d exceeds max int", length) + } } - -func (SignerKeyType) XdrEnumNames() map[int32]string { - return _XdrNames_SignerKeyType +func (v _XdrVec_unbounded_Uint64) GetVecLen() uint32 { return uint32(len(v)) } +func (v *_XdrVec_unbounded_Uint64) SetVecLen(length uint32) { + v.XdrCheckLen(length) + if int(length) <= cap(*v) { + if int(length) != len(*v) { + *v = (*v)[:int(length)] + } + return + } + newcap := 2 * cap(*v) + if newcap < int(length) { // also catches overflow where 2*cap < 0 + newcap = int(length) + } else if bound := uint(4294967295); uint(newcap) > bound { + if int(bound) < 0 { + bound = ^uint(0) >> 1 + } + newcap = int(bound) + } + nv := make([]Uint64, int(length), newcap) + copy(nv, *v) + *v = nv } -func (v SignerKeyType) String() string { - if s, ok := _XdrNames_SignerKeyType[int32(v)]; ok { - return s +func (v *_XdrVec_unbounded_Uint64) XdrMarshalN(x XDR, name string, n uint32) { + v.XdrCheckLen(n) + for i := 0; i < int(n); i++ { + if i >= len(*v) { + v.SetVecLen(uint32(i + 1)) + } + XDR_Uint64(&(*v)[i]).XdrMarshal(x, x.Sprintf("%s[%d]", name, i)) + } + if int(n) < len(*v) { + *v = (*v)[:int(n)] } - return fmt.Sprintf("SignerKeyType#%d", v) } -func (v *SignerKeyType) Scan(ss fmt.ScanState, _ rune) error { - if tok, err := ss.Token(true, XdrSymChar); err != nil { - return err - } else { - stok := string(tok) - if val, ok := _XdrValues_SignerKeyType[stok]; ok { - *v = SignerKeyType(val) - return nil - } else if stok == "SignerKeyType" { - if n, err := fmt.Fscanf(ss, "#%d", (*int32)(v)); n == 1 && err == nil { - return nil - } +func (v *_XdrVec_unbounded_Uint64) XdrRecurse(x XDR, name string) { + size := XdrSize{Size: uint32(len(*v)), Bound: 4294967295} + x.Marshal(name, &size) + v.XdrMarshalN(x, name, size.Size) +} +func (_XdrVec_unbounded_Uint64) XdrTypeName() string { return "Uint64<>" } +func (v *_XdrVec_unbounded_Uint64) XdrPointer() interface{} { return (*[]Uint64)(v) } +func (v _XdrVec_unbounded_Uint64) XdrValue() interface{} { return ([]Uint64)(v) } +func (v *_XdrVec_unbounded_Uint64) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } + +var _XdrTags_ConfigSettingEntry = map[int32]bool{ + XdrToI32(CONFIG_SETTING_CONTRACT_MAX_SIZE_BYTES): true, + XdrToI32(CONFIG_SETTING_CONTRACT_COMPUTE_V0): true, + XdrToI32(CONFIG_SETTING_CONTRACT_LEDGER_COST_V0): true, + XdrToI32(CONFIG_SETTING_CONTRACT_HISTORICAL_DATA_V0): true, + XdrToI32(CONFIG_SETTING_CONTRACT_EVENTS_V0): true, + XdrToI32(CONFIG_SETTING_CONTRACT_BANDWIDTH_V0): true, + XdrToI32(CONFIG_SETTING_CONTRACT_COST_PARAMS_CPU_INSTRUCTIONS): true, + XdrToI32(CONFIG_SETTING_CONTRACT_COST_PARAMS_MEMORY_BYTES): true, + XdrToI32(CONFIG_SETTING_CONTRACT_DATA_KEY_SIZE_BYTES): true, + XdrToI32(CONFIG_SETTING_CONTRACT_DATA_ENTRY_SIZE_BYTES): true, + XdrToI32(CONFIG_SETTING_STATE_ARCHIVAL): true, + XdrToI32(CONFIG_SETTING_CONTRACT_EXECUTION_LANES): true, + XdrToI32(CONFIG_SETTING_BUCKETLIST_SIZE_WINDOW): true, + XdrToI32(CONFIG_SETTING_EVICTION_ITERATOR): true, +} + +func (_ ConfigSettingEntry) XdrValidTags() map[int32]bool { + return _XdrTags_ConfigSettingEntry +} +func (u *ConfigSettingEntry) ContractMaxSizeBytes() *Uint32 { + switch u.ConfigSettingID { + case CONFIG_SETTING_CONTRACT_MAX_SIZE_BYTES: + if v, ok := u._u.(*Uint32); ok { + return v + } else { + var zero Uint32 + u._u = &zero + return &zero } - return XdrError(fmt.Sprintf("%s is not a valid SignerKeyType.", stok)) + default: + XdrPanic("ConfigSettingEntry.ContractMaxSizeBytes accessed when ConfigSettingID == %v", u.ConfigSettingID) + return nil } } -func (v SignerKeyType) GetU32() uint32 { return uint32(v) } -func (v *SignerKeyType) SetU32(n uint32) { *v = SignerKeyType(n) } -func (v *SignerKeyType) XdrPointer() interface{} { return v } -func (SignerKeyType) XdrTypeName() string { return "SignerKeyType" } -func (v SignerKeyType) XdrValue() interface{} { return v } -func (v *SignerKeyType) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } - -type XdrType_SignerKeyType = *SignerKeyType - -func XDR_SignerKeyType(v *SignerKeyType) *SignerKeyType { return v } - -var _XdrTags_PublicKey = map[int32]bool{ - XdrToI32(PUBLIC_KEY_TYPE_ED25519): true, +func (u *ConfigSettingEntry) ContractCompute() *ConfigSettingContractComputeV0 { + switch u.ConfigSettingID { + case CONFIG_SETTING_CONTRACT_COMPUTE_V0: + if v, ok := u._u.(*ConfigSettingContractComputeV0); ok { + return v + } else { + var zero ConfigSettingContractComputeV0 + u._u = &zero + return &zero + } + default: + XdrPanic("ConfigSettingEntry.ContractCompute accessed when ConfigSettingID == %v", u.ConfigSettingID) + return nil + } } - -func (_ PublicKey) XdrValidTags() map[int32]bool { - return _XdrTags_PublicKey +func (u *ConfigSettingEntry) ContractLedgerCost() *ConfigSettingContractLedgerCostV0 { + switch u.ConfigSettingID { + case CONFIG_SETTING_CONTRACT_LEDGER_COST_V0: + if v, ok := u._u.(*ConfigSettingContractLedgerCostV0); ok { + return v + } else { + var zero ConfigSettingContractLedgerCostV0 + u._u = &zero + return &zero + } + default: + XdrPanic("ConfigSettingEntry.ContractLedgerCost accessed when ConfigSettingID == %v", u.ConfigSettingID) + return nil + } +} +func (u *ConfigSettingEntry) ContractHistoricalData() *ConfigSettingContractHistoricalDataV0 { + switch u.ConfigSettingID { + case CONFIG_SETTING_CONTRACT_HISTORICAL_DATA_V0: + if v, ok := u._u.(*ConfigSettingContractHistoricalDataV0); ok { + return v + } else { + var zero ConfigSettingContractHistoricalDataV0 + u._u = &zero + return &zero + } + default: + XdrPanic("ConfigSettingEntry.ContractHistoricalData accessed when ConfigSettingID == %v", u.ConfigSettingID) + return nil + } +} +func (u *ConfigSettingEntry) ContractEvents() *ConfigSettingContractEventsV0 { + switch u.ConfigSettingID { + case CONFIG_SETTING_CONTRACT_EVENTS_V0: + if v, ok := u._u.(*ConfigSettingContractEventsV0); ok { + return v + } else { + var zero ConfigSettingContractEventsV0 + u._u = &zero + return &zero + } + default: + XdrPanic("ConfigSettingEntry.ContractEvents accessed when ConfigSettingID == %v", u.ConfigSettingID) + return nil + } +} +func (u *ConfigSettingEntry) ContractBandwidth() *ConfigSettingContractBandwidthV0 { + switch u.ConfigSettingID { + case CONFIG_SETTING_CONTRACT_BANDWIDTH_V0: + if v, ok := u._u.(*ConfigSettingContractBandwidthV0); ok { + return v + } else { + var zero ConfigSettingContractBandwidthV0 + u._u = &zero + return &zero + } + default: + XdrPanic("ConfigSettingEntry.ContractBandwidth accessed when ConfigSettingID == %v", u.ConfigSettingID) + return nil + } +} +func (u *ConfigSettingEntry) ContractCostParamsCpuInsns() *ContractCostParams { + switch u.ConfigSettingID { + case CONFIG_SETTING_CONTRACT_COST_PARAMS_CPU_INSTRUCTIONS: + if v, ok := u._u.(*ContractCostParams); ok { + return v + } else { + var zero ContractCostParams + u._u = &zero + return &zero + } + default: + XdrPanic("ConfigSettingEntry.ContractCostParamsCpuInsns accessed when ConfigSettingID == %v", u.ConfigSettingID) + return nil + } +} +func (u *ConfigSettingEntry) ContractCostParamsMemBytes() *ContractCostParams { + switch u.ConfigSettingID { + case CONFIG_SETTING_CONTRACT_COST_PARAMS_MEMORY_BYTES: + if v, ok := u._u.(*ContractCostParams); ok { + return v + } else { + var zero ContractCostParams + u._u = &zero + return &zero + } + default: + XdrPanic("ConfigSettingEntry.ContractCostParamsMemBytes accessed when ConfigSettingID == %v", u.ConfigSettingID) + return nil + } +} +func (u *ConfigSettingEntry) ContractDataKeySizeBytes() *Uint32 { + switch u.ConfigSettingID { + case CONFIG_SETTING_CONTRACT_DATA_KEY_SIZE_BYTES: + if v, ok := u._u.(*Uint32); ok { + return v + } else { + var zero Uint32 + u._u = &zero + return &zero + } + default: + XdrPanic("ConfigSettingEntry.ContractDataKeySizeBytes accessed when ConfigSettingID == %v", u.ConfigSettingID) + return nil + } } -func (u *PublicKey) Ed25519() *Uint256 { - switch u.Type { - case PUBLIC_KEY_TYPE_ED25519: - if v, ok := u._u.(*Uint256); ok { +func (u *ConfigSettingEntry) ContractDataEntrySizeBytes() *Uint32 { + switch u.ConfigSettingID { + case CONFIG_SETTING_CONTRACT_DATA_ENTRY_SIZE_BYTES: + if v, ok := u._u.(*Uint32); ok { return v } else { - var zero Uint256 + var zero Uint32 u._u = &zero return &zero } default: - XdrPanic("PublicKey.Ed25519 accessed when Type == %v", u.Type) + XdrPanic("ConfigSettingEntry.ContractDataEntrySizeBytes accessed when ConfigSettingID == %v", u.ConfigSettingID) return nil } } -func (u PublicKey) XdrValid() bool { - switch u.Type { - case PUBLIC_KEY_TYPE_ED25519: - return true - } - return false -} -func (u *PublicKey) XdrUnionTag() XdrNum32 { - return XDR_PublicKeyType(&u.Type) -} -func (u *PublicKey) XdrUnionTagName() string { - return "Type" -} -func (u *PublicKey) XdrUnionBody() XdrType { - switch u.Type { - case PUBLIC_KEY_TYPE_ED25519: - return XDR_Uint256(u.Ed25519()) - } - return nil -} -func (u *PublicKey) XdrUnionBodyName() string { - switch u.Type { - case PUBLIC_KEY_TYPE_ED25519: - return "Ed25519" - } - return "" -} - -type XdrType_PublicKey = *PublicKey - -func (v *PublicKey) XdrPointer() interface{} { return v } -func (PublicKey) XdrTypeName() string { return "PublicKey" } -func (v PublicKey) XdrValue() interface{} { return v } -func (v *PublicKey) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -func (u *PublicKey) XdrRecurse(x XDR, name string) { - if name != "" { - name = x.Sprintf("%s.", name) - } - XDR_PublicKeyType(&u.Type).XdrMarshal(x, x.Sprintf("%stype", name)) - switch u.Type { - case PUBLIC_KEY_TYPE_ED25519: - x.Marshal(x.Sprintf("%sed25519", name), XDR_Uint256(u.Ed25519())) - return - } - XdrPanic("invalid Type (%v) in PublicKey", u.Type) -} -func XDR_PublicKey(v *PublicKey) *PublicKey { return v } - -type XdrType_XdrAnon_SignerKey_Ed25519SignedPayload = *XdrAnon_SignerKey_Ed25519SignedPayload - -func (v *XdrAnon_SignerKey_Ed25519SignedPayload) XdrPointer() interface{} { return v } -func (XdrAnon_SignerKey_Ed25519SignedPayload) XdrTypeName() string { - return "XdrAnon_SignerKey_Ed25519SignedPayload" -} -func (v XdrAnon_SignerKey_Ed25519SignedPayload) XdrValue() interface{} { return v } -func (v *XdrAnon_SignerKey_Ed25519SignedPayload) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -func (v *XdrAnon_SignerKey_Ed25519SignedPayload) XdrRecurse(x XDR, name string) { - if name != "" { - name = x.Sprintf("%s.", name) - } - x.Marshal(x.Sprintf("%sed25519", name), XDR_Uint256(&v.Ed25519)) - x.Marshal(x.Sprintf("%spayload", name), XdrVecOpaque{&v.Payload, 64}) -} -func XDR_XdrAnon_SignerKey_Ed25519SignedPayload(v *XdrAnon_SignerKey_Ed25519SignedPayload) *XdrAnon_SignerKey_Ed25519SignedPayload { - return v -} - -var _XdrTags_SignerKey = map[int32]bool{ - XdrToI32(SIGNER_KEY_TYPE_ED25519): true, - XdrToI32(SIGNER_KEY_TYPE_PRE_AUTH_TX): true, - XdrToI32(SIGNER_KEY_TYPE_HASH_X): true, - XdrToI32(SIGNER_KEY_TYPE_ED25519_SIGNED_PAYLOAD): true, -} - -func (_ SignerKey) XdrValidTags() map[int32]bool { - return _XdrTags_SignerKey -} -func (u *SignerKey) Ed25519() *Uint256 { - switch u.Type { - case SIGNER_KEY_TYPE_ED25519: - if v, ok := u._u.(*Uint256); ok { +func (u *ConfigSettingEntry) StateArchivalSettings() *StateArchivalSettings { + switch u.ConfigSettingID { + case CONFIG_SETTING_STATE_ARCHIVAL: + if v, ok := u._u.(*StateArchivalSettings); ok { return v } else { - var zero Uint256 + var zero StateArchivalSettings u._u = &zero return &zero } default: - XdrPanic("SignerKey.Ed25519 accessed when Type == %v", u.Type) + XdrPanic("ConfigSettingEntry.StateArchivalSettings accessed when ConfigSettingID == %v", u.ConfigSettingID) return nil } } - -/* SHA-256 Hash of TransactionSignaturePayload structure */ -func (u *SignerKey) PreAuthTx() *Uint256 { - switch u.Type { - case SIGNER_KEY_TYPE_PRE_AUTH_TX: - if v, ok := u._u.(*Uint256); ok { +func (u *ConfigSettingEntry) ContractExecutionLanes() *ConfigSettingContractExecutionLanesV0 { + switch u.ConfigSettingID { + case CONFIG_SETTING_CONTRACT_EXECUTION_LANES: + if v, ok := u._u.(*ConfigSettingContractExecutionLanesV0); ok { return v } else { - var zero Uint256 + var zero ConfigSettingContractExecutionLanesV0 u._u = &zero return &zero } default: - XdrPanic("SignerKey.PreAuthTx accessed when Type == %v", u.Type) + XdrPanic("ConfigSettingEntry.ContractExecutionLanes accessed when ConfigSettingID == %v", u.ConfigSettingID) return nil } } - -/* Hash of random 256 bit preimage X */ -func (u *SignerKey) HashX() *Uint256 { - switch u.Type { - case SIGNER_KEY_TYPE_HASH_X: - if v, ok := u._u.(*Uint256); ok { +func (u *ConfigSettingEntry) BucketListSizeWindow() *[]Uint64 { + switch u.ConfigSettingID { + case CONFIG_SETTING_BUCKETLIST_SIZE_WINDOW: + if v, ok := u._u.(*[]Uint64); ok { return v } else { - var zero Uint256 + var zero []Uint64 u._u = &zero return &zero } default: - XdrPanic("SignerKey.HashX accessed when Type == %v", u.Type) + XdrPanic("ConfigSettingEntry.BucketListSizeWindow accessed when ConfigSettingID == %v", u.ConfigSettingID) return nil } } -func (u *SignerKey) Ed25519SignedPayload() *XdrAnon_SignerKey_Ed25519SignedPayload { - switch u.Type { - case SIGNER_KEY_TYPE_ED25519_SIGNED_PAYLOAD: - if v, ok := u._u.(*XdrAnon_SignerKey_Ed25519SignedPayload); ok { +func (u *ConfigSettingEntry) EvictionIterator() *EvictionIterator { + switch u.ConfigSettingID { + case CONFIG_SETTING_EVICTION_ITERATOR: + if v, ok := u._u.(*EvictionIterator); ok { return v } else { - var zero XdrAnon_SignerKey_Ed25519SignedPayload + var zero EvictionIterator u._u = &zero return &zero } default: - XdrPanic("SignerKey.Ed25519SignedPayload accessed when Type == %v", u.Type) + XdrPanic("ConfigSettingEntry.EvictionIterator accessed when ConfigSettingID == %v", u.ConfigSettingID) return nil } } -func (u SignerKey) XdrValid() bool { - switch u.Type { - case SIGNER_KEY_TYPE_ED25519, SIGNER_KEY_TYPE_PRE_AUTH_TX, SIGNER_KEY_TYPE_HASH_X, SIGNER_KEY_TYPE_ED25519_SIGNED_PAYLOAD: +func (u ConfigSettingEntry) XdrValid() bool { + switch u.ConfigSettingID { + case CONFIG_SETTING_CONTRACT_MAX_SIZE_BYTES, CONFIG_SETTING_CONTRACT_COMPUTE_V0, CONFIG_SETTING_CONTRACT_LEDGER_COST_V0, CONFIG_SETTING_CONTRACT_HISTORICAL_DATA_V0, CONFIG_SETTING_CONTRACT_EVENTS_V0, CONFIG_SETTING_CONTRACT_BANDWIDTH_V0, CONFIG_SETTING_CONTRACT_COST_PARAMS_CPU_INSTRUCTIONS, CONFIG_SETTING_CONTRACT_COST_PARAMS_MEMORY_BYTES, CONFIG_SETTING_CONTRACT_DATA_KEY_SIZE_BYTES, CONFIG_SETTING_CONTRACT_DATA_ENTRY_SIZE_BYTES, CONFIG_SETTING_STATE_ARCHIVAL, CONFIG_SETTING_CONTRACT_EXECUTION_LANES, CONFIG_SETTING_BUCKETLIST_SIZE_WINDOW, CONFIG_SETTING_EVICTION_ITERATOR: return true } return false } -func (u *SignerKey) XdrUnionTag() XdrNum32 { - return XDR_SignerKeyType(&u.Type) -} -func (u *SignerKey) XdrUnionTagName() string { - return "Type" -} -func (u *SignerKey) XdrUnionBody() XdrType { - switch u.Type { - case SIGNER_KEY_TYPE_ED25519: - return XDR_Uint256(u.Ed25519()) - case SIGNER_KEY_TYPE_PRE_AUTH_TX: - return XDR_Uint256(u.PreAuthTx()) - case SIGNER_KEY_TYPE_HASH_X: - return XDR_Uint256(u.HashX()) - case SIGNER_KEY_TYPE_ED25519_SIGNED_PAYLOAD: - return XDR_XdrAnon_SignerKey_Ed25519SignedPayload(u.Ed25519SignedPayload()) +func (u *ConfigSettingEntry) XdrUnionTag() XdrNum32 { + return XDR_ConfigSettingID(&u.ConfigSettingID) +} +func (u *ConfigSettingEntry) XdrUnionTagName() string { + return "ConfigSettingID" +} +func (u *ConfigSettingEntry) XdrUnionBody() XdrType { + switch u.ConfigSettingID { + case CONFIG_SETTING_CONTRACT_MAX_SIZE_BYTES: + return XDR_Uint32(u.ContractMaxSizeBytes()) + case CONFIG_SETTING_CONTRACT_COMPUTE_V0: + return XDR_ConfigSettingContractComputeV0(u.ContractCompute()) + case CONFIG_SETTING_CONTRACT_LEDGER_COST_V0: + return XDR_ConfigSettingContractLedgerCostV0(u.ContractLedgerCost()) + case CONFIG_SETTING_CONTRACT_HISTORICAL_DATA_V0: + return XDR_ConfigSettingContractHistoricalDataV0(u.ContractHistoricalData()) + case CONFIG_SETTING_CONTRACT_EVENTS_V0: + return XDR_ConfigSettingContractEventsV0(u.ContractEvents()) + case CONFIG_SETTING_CONTRACT_BANDWIDTH_V0: + return XDR_ConfigSettingContractBandwidthV0(u.ContractBandwidth()) + case CONFIG_SETTING_CONTRACT_COST_PARAMS_CPU_INSTRUCTIONS: + return XDR_ContractCostParams(u.ContractCostParamsCpuInsns()) + case CONFIG_SETTING_CONTRACT_COST_PARAMS_MEMORY_BYTES: + return XDR_ContractCostParams(u.ContractCostParamsMemBytes()) + case CONFIG_SETTING_CONTRACT_DATA_KEY_SIZE_BYTES: + return XDR_Uint32(u.ContractDataKeySizeBytes()) + case CONFIG_SETTING_CONTRACT_DATA_ENTRY_SIZE_BYTES: + return XDR_Uint32(u.ContractDataEntrySizeBytes()) + case CONFIG_SETTING_STATE_ARCHIVAL: + return XDR_StateArchivalSettings(u.StateArchivalSettings()) + case CONFIG_SETTING_CONTRACT_EXECUTION_LANES: + return XDR_ConfigSettingContractExecutionLanesV0(u.ContractExecutionLanes()) + case CONFIG_SETTING_BUCKETLIST_SIZE_WINDOW: + return (*_XdrVec_unbounded_Uint64)(u.BucketListSizeWindow()) + case CONFIG_SETTING_EVICTION_ITERATOR: + return XDR_EvictionIterator(u.EvictionIterator()) } return nil } -func (u *SignerKey) XdrUnionBodyName() string { - switch u.Type { - case SIGNER_KEY_TYPE_ED25519: - return "Ed25519" - case SIGNER_KEY_TYPE_PRE_AUTH_TX: - return "PreAuthTx" - case SIGNER_KEY_TYPE_HASH_X: - return "HashX" - case SIGNER_KEY_TYPE_ED25519_SIGNED_PAYLOAD: - return "Ed25519SignedPayload" +func (u *ConfigSettingEntry) XdrUnionBodyName() string { + switch u.ConfigSettingID { + case CONFIG_SETTING_CONTRACT_MAX_SIZE_BYTES: + return "ContractMaxSizeBytes" + case CONFIG_SETTING_CONTRACT_COMPUTE_V0: + return "ContractCompute" + case CONFIG_SETTING_CONTRACT_LEDGER_COST_V0: + return "ContractLedgerCost" + case CONFIG_SETTING_CONTRACT_HISTORICAL_DATA_V0: + return "ContractHistoricalData" + case CONFIG_SETTING_CONTRACT_EVENTS_V0: + return "ContractEvents" + case CONFIG_SETTING_CONTRACT_BANDWIDTH_V0: + return "ContractBandwidth" + case CONFIG_SETTING_CONTRACT_COST_PARAMS_CPU_INSTRUCTIONS: + return "ContractCostParamsCpuInsns" + case CONFIG_SETTING_CONTRACT_COST_PARAMS_MEMORY_BYTES: + return "ContractCostParamsMemBytes" + case CONFIG_SETTING_CONTRACT_DATA_KEY_SIZE_BYTES: + return "ContractDataKeySizeBytes" + case CONFIG_SETTING_CONTRACT_DATA_ENTRY_SIZE_BYTES: + return "ContractDataEntrySizeBytes" + case CONFIG_SETTING_STATE_ARCHIVAL: + return "StateArchivalSettings" + case CONFIG_SETTING_CONTRACT_EXECUTION_LANES: + return "ContractExecutionLanes" + case CONFIG_SETTING_BUCKETLIST_SIZE_WINDOW: + return "BucketListSizeWindow" + case CONFIG_SETTING_EVICTION_ITERATOR: + return "EvictionIterator" } return "" } -type XdrType_SignerKey = *SignerKey +type XdrType_ConfigSettingEntry = *ConfigSettingEntry -func (v *SignerKey) XdrPointer() interface{} { return v } -func (SignerKey) XdrTypeName() string { return "SignerKey" } -func (v SignerKey) XdrValue() interface{} { return v } -func (v *SignerKey) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -func (u *SignerKey) XdrRecurse(x XDR, name string) { +func (v *ConfigSettingEntry) XdrPointer() interface{} { return v } +func (ConfigSettingEntry) XdrTypeName() string { return "ConfigSettingEntry" } +func (v ConfigSettingEntry) XdrValue() interface{} { return v } +func (v *ConfigSettingEntry) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (u *ConfigSettingEntry) XdrRecurse(x XDR, name string) { if name != "" { name = x.Sprintf("%s.", name) } - XDR_SignerKeyType(&u.Type).XdrMarshal(x, x.Sprintf("%stype", name)) - switch u.Type { - case SIGNER_KEY_TYPE_ED25519: - x.Marshal(x.Sprintf("%sed25519", name), XDR_Uint256(u.Ed25519())) + XDR_ConfigSettingID(&u.ConfigSettingID).XdrMarshal(x, x.Sprintf("%sconfigSettingID", name)) + switch u.ConfigSettingID { + case CONFIG_SETTING_CONTRACT_MAX_SIZE_BYTES: + x.Marshal(x.Sprintf("%scontractMaxSizeBytes", name), XDR_Uint32(u.ContractMaxSizeBytes())) return - case SIGNER_KEY_TYPE_PRE_AUTH_TX: - x.Marshal(x.Sprintf("%spreAuthTx", name), XDR_Uint256(u.PreAuthTx())) + case CONFIG_SETTING_CONTRACT_COMPUTE_V0: + x.Marshal(x.Sprintf("%scontractCompute", name), XDR_ConfigSettingContractComputeV0(u.ContractCompute())) return - case SIGNER_KEY_TYPE_HASH_X: - x.Marshal(x.Sprintf("%shashX", name), XDR_Uint256(u.HashX())) + case CONFIG_SETTING_CONTRACT_LEDGER_COST_V0: + x.Marshal(x.Sprintf("%scontractLedgerCost", name), XDR_ConfigSettingContractLedgerCostV0(u.ContractLedgerCost())) return - case SIGNER_KEY_TYPE_ED25519_SIGNED_PAYLOAD: - x.Marshal(x.Sprintf("%sed25519SignedPayload", name), XDR_XdrAnon_SignerKey_Ed25519SignedPayload(u.Ed25519SignedPayload())) + case CONFIG_SETTING_CONTRACT_HISTORICAL_DATA_V0: + x.Marshal(x.Sprintf("%scontractHistoricalData", name), XDR_ConfigSettingContractHistoricalDataV0(u.ContractHistoricalData())) + return + case CONFIG_SETTING_CONTRACT_EVENTS_V0: + x.Marshal(x.Sprintf("%scontractEvents", name), XDR_ConfigSettingContractEventsV0(u.ContractEvents())) + return + case CONFIG_SETTING_CONTRACT_BANDWIDTH_V0: + x.Marshal(x.Sprintf("%scontractBandwidth", name), XDR_ConfigSettingContractBandwidthV0(u.ContractBandwidth())) + return + case CONFIG_SETTING_CONTRACT_COST_PARAMS_CPU_INSTRUCTIONS: + x.Marshal(x.Sprintf("%scontractCostParamsCpuInsns", name), XDR_ContractCostParams(u.ContractCostParamsCpuInsns())) + return + case CONFIG_SETTING_CONTRACT_COST_PARAMS_MEMORY_BYTES: + x.Marshal(x.Sprintf("%scontractCostParamsMemBytes", name), XDR_ContractCostParams(u.ContractCostParamsMemBytes())) + return + case CONFIG_SETTING_CONTRACT_DATA_KEY_SIZE_BYTES: + x.Marshal(x.Sprintf("%scontractDataKeySizeBytes", name), XDR_Uint32(u.ContractDataKeySizeBytes())) + return + case CONFIG_SETTING_CONTRACT_DATA_ENTRY_SIZE_BYTES: + x.Marshal(x.Sprintf("%scontractDataEntrySizeBytes", name), XDR_Uint32(u.ContractDataEntrySizeBytes())) + return + case CONFIG_SETTING_STATE_ARCHIVAL: + x.Marshal(x.Sprintf("%sstateArchivalSettings", name), XDR_StateArchivalSettings(u.StateArchivalSettings())) + return + case CONFIG_SETTING_CONTRACT_EXECUTION_LANES: + x.Marshal(x.Sprintf("%scontractExecutionLanes", name), XDR_ConfigSettingContractExecutionLanesV0(u.ContractExecutionLanes())) + return + case CONFIG_SETTING_BUCKETLIST_SIZE_WINDOW: + x.Marshal(x.Sprintf("%sbucketListSizeWindow", name), (*_XdrVec_unbounded_Uint64)(u.BucketListSizeWindow())) + return + case CONFIG_SETTING_EVICTION_ITERATOR: + x.Marshal(x.Sprintf("%sevictionIterator", name), XDR_EvictionIterator(u.EvictionIterator())) return } - XdrPanic("invalid Type (%v) in SignerKey", u.Type) -} -func XDR_SignerKey(v *SignerKey) *SignerKey { return v } - -type XdrType_Signature struct { - XdrVecOpaque -} - -func XDR_Signature(v *Signature) XdrType_Signature { - return XdrType_Signature{XdrVecOpaque{v, 64}} -} -func (XdrType_Signature) XdrTypeName() string { return "Signature" } -func (v XdrType_Signature) XdrUnwrap() XdrType { return v.XdrVecOpaque } - -type XdrType_SignatureHint struct { - *_XdrArray_4_opaque -} - -func XDR_SignatureHint(v *SignatureHint) XdrType_SignatureHint { - return XdrType_SignatureHint{(*_XdrArray_4_opaque)(v)} -} -func (XdrType_SignatureHint) XdrTypeName() string { return "SignatureHint" } -func (v XdrType_SignatureHint) XdrUnwrap() XdrType { return v._XdrArray_4_opaque } - -type XdrType_NodeID struct { - XdrType_PublicKey -} - -func XDR_NodeID(v *NodeID) XdrType_NodeID { - return XdrType_NodeID{XDR_PublicKey(v)} -} -func (XdrType_NodeID) XdrTypeName() string { return "NodeID" } -func (v XdrType_NodeID) XdrUnwrap() XdrType { return v.XdrType_PublicKey } - -type XdrType_Curve25519Secret = *Curve25519Secret - -func (v *Curve25519Secret) XdrPointer() interface{} { return v } -func (Curve25519Secret) XdrTypeName() string { return "Curve25519Secret" } -func (v Curve25519Secret) XdrValue() interface{} { return v } -func (v *Curve25519Secret) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -func (v *Curve25519Secret) XdrRecurse(x XDR, name string) { - if name != "" { - name = x.Sprintf("%s.", name) - } - x.Marshal(x.Sprintf("%skey", name), (*_XdrArray_32_opaque)(&v.Key)) -} -func XDR_Curve25519Secret(v *Curve25519Secret) *Curve25519Secret { return v } - -type XdrType_Curve25519Public = *Curve25519Public - -func (v *Curve25519Public) XdrPointer() interface{} { return v } -func (Curve25519Public) XdrTypeName() string { return "Curve25519Public" } -func (v Curve25519Public) XdrValue() interface{} { return v } -func (v *Curve25519Public) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -func (v *Curve25519Public) XdrRecurse(x XDR, name string) { - if name != "" { - name = x.Sprintf("%s.", name) - } - x.Marshal(x.Sprintf("%skey", name), (*_XdrArray_32_opaque)(&v.Key)) -} -func XDR_Curve25519Public(v *Curve25519Public) *Curve25519Public { return v } - -type XdrType_HmacSha256Key = *HmacSha256Key - -func (v *HmacSha256Key) XdrPointer() interface{} { return v } -func (HmacSha256Key) XdrTypeName() string { return "HmacSha256Key" } -func (v HmacSha256Key) XdrValue() interface{} { return v } -func (v *HmacSha256Key) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -func (v *HmacSha256Key) XdrRecurse(x XDR, name string) { - if name != "" { - name = x.Sprintf("%s.", name) - } - x.Marshal(x.Sprintf("%skey", name), (*_XdrArray_32_opaque)(&v.Key)) -} -func XDR_HmacSha256Key(v *HmacSha256Key) *HmacSha256Key { return v } - -type XdrType_HmacSha256Mac = *HmacSha256Mac - -func (v *HmacSha256Mac) XdrPointer() interface{} { return v } -func (HmacSha256Mac) XdrTypeName() string { return "HmacSha256Mac" } -func (v HmacSha256Mac) XdrValue() interface{} { return v } -func (v *HmacSha256Mac) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -func (v *HmacSha256Mac) XdrRecurse(x XDR, name string) { - if name != "" { - name = x.Sprintf("%s.", name) - } - x.Marshal(x.Sprintf("%smac", name), (*_XdrArray_32_opaque)(&v.Mac)) + XdrPanic("invalid ConfigSettingID (%v) in ConfigSettingEntry", u.ConfigSettingID) } -func XDR_HmacSha256Mac(v *HmacSha256Mac) *HmacSha256Mac { return v } +func XDR_ConfigSettingEntry(v *ConfigSettingEntry) *ConfigSettingEntry { return v } type XdrType_BitmapIndex = *BitmapIndex diff --git a/handlers/federation/main.go b/handlers/federation/main.go index 00c192713a..b0b8ab3c17 100644 --- a/handlers/federation/main.go +++ b/handlers/federation/main.go @@ -93,7 +93,7 @@ type ReverseSQLDriver struct { SQLDriver // LookupReverseRecordQuery is a SQL query used for performing "reverse" - // federation queries. This query should accomodate a single parameter, using + // federation queries. This query should accommodate a single parameter, using // "?" as the placeholder. This provided parameter will be a strkey-encoded // stellar account id to lookup, such as // "GDOP3VI4UA5LS7AMLJI66RJUXEQ4HX46WUXTRTJGI5IKDLNWUBOW3FUK". @@ -115,7 +115,7 @@ type SQLDriver struct { Dialect string // LookupRecordQuery is a SQL query used for performing "forward" federation - // queries. This query should accomodate one or two parameters, using "?" as + // queries. This query should accommodate one or two parameters, using "?" as // the placeholder. This provided parameters will be a name and domain LookupRecordQuery string diff --git a/ingest/change.go b/ingest/change.go index 11877cde61..027b37b861 100644 --- a/ingest/change.go +++ b/ingest/change.go @@ -2,6 +2,7 @@ package ingest import ( "bytes" + "sort" "github.com/stellar/go/support/errors" "github.com/stellar/go/xdr" @@ -20,6 +21,13 @@ type Change struct { Post *xdr.LedgerEntry } +func (c *Change) ledgerKey() (xdr.LedgerKey, error) { + if c.Pre != nil { + return c.Pre.LedgerKey() + } + return c.Post.LedgerKey() +} + // GetChangesFromLedgerEntryChanges transforms LedgerEntryChanges to []Change. // Each `update` and `removed` is preceded with `state` and `create` changes // are alone, without `state`. The transformation we're doing is to move each @@ -32,8 +40,7 @@ type Change struct { // stellar-core source: // https://github.com/stellar/stellar-core/blob/e584b43/src/ledger/LedgerTxn.cpp#L582 func GetChangesFromLedgerEntryChanges(ledgerEntryChanges xdr.LedgerEntryChanges) []Change { - changes := []Change{} - + changes := make([]Change, 0, len(ledgerEntryChanges)) for i, entryChange := range ledgerEntryChanges { switch entryChange.Type { case xdr.LedgerEntryChangeTypeLedgerEntryCreated: @@ -65,9 +72,57 @@ func GetChangesFromLedgerEntryChanges(ledgerEntryChanges xdr.LedgerEntryChanges) } } + sortChanges(changes) return changes } +type sortableChanges struct { + changes []Change + ledgerKeys [][]byte +} + +func newSortableChanges(changes []Change) sortableChanges { + ledgerKeys := make([][]byte, len(changes)) + for i, c := range changes { + lk, err := c.ledgerKey() + if err != nil { + panic(err) + } + lkBytes, err := lk.MarshalBinary() + if err != nil { + panic(err) + } + ledgerKeys[i] = lkBytes + } + return sortableChanges{ + changes: changes, + ledgerKeys: ledgerKeys, + } +} + +func (s sortableChanges) Len() int { + return len(s.changes) +} + +func (s sortableChanges) Less(i, j int) bool { + return bytes.Compare(s.ledgerKeys[i], s.ledgerKeys[j]) < 0 +} + +func (s sortableChanges) Swap(i, j int) { + s.changes[i], s.changes[j] = s.changes[j], s.changes[i] + s.ledgerKeys[i], s.ledgerKeys[j] = s.ledgerKeys[j], s.ledgerKeys[i] +} + +// sortChanges is applied on a list of changes to ensure that LedgerEntryChanges +// from Tx Meta are ingested in a deterministic order. +// The changes are sorted by ledger key. It is unexpected for there to be +// multiple changes with the same ledger key in a LedgerEntryChanges group, +// but if that is the case, we fall back to the original ordering of the changes +// by using a stable sorting algorithm. +func sortChanges(changes []Change) { + sort.Stable(newSortableChanges(changes)) +} + // LedgerEntryChangeType returns type in terms of LedgerEntryChangeType. func (c *Change) LedgerEntryChangeType() xdr.LedgerEntryChangeType { switch { diff --git a/ingest/change_compactor.go b/ingest/change_compactor.go index 6a82966131..b93082761e 100644 --- a/ingest/change_compactor.go +++ b/ingest/change_compactor.go @@ -2,7 +2,6 @@ package ingest import ( "encoding/base64" - "sync" "github.com/stellar/go/support/errors" "github.com/stellar/go/xdr" @@ -50,7 +49,6 @@ import ( type ChangeCompactor struct { // ledger key => Change cache map[string]Change - mutex sync.Mutex encodingBuffer *xdr.EncodingBuffer } @@ -70,9 +68,6 @@ func NewChangeCompactor() *ChangeCompactor { // cache takes too much memory, you apply changes returned by GetChanges and // create a new ChangeCompactor object to continue ingestion. func (c *ChangeCompactor) AddChange(change Change) error { - c.mutex.Lock() - defer c.mutex.Unlock() - switch { case change.Pre == nil && change.Post != nil: return c.addCreatedChange(change) @@ -89,9 +84,13 @@ func (c *ChangeCompactor) AddChange(change Change) error { // change is unexpected. func (c *ChangeCompactor) addCreatedChange(change Change) error { // safe, since we later cast to string (causing a copy) - ledgerKey, err := c.encodingBuffer.UnsafeMarshalBinary(change.Post.LedgerKey()) + key, err := change.Post.LedgerKey() + if err != nil { + return errors.Wrap(err, "error getting ledger key for new entry") + } + ledgerKey, err := c.encodingBuffer.UnsafeMarshalBinary(key) if err != nil { - return errors.Wrap(err, "Error MarshalBinary") + return errors.Wrap(err, "error marshaling ledger key for new entry") } ledgerKeyString := string(ledgerKey) @@ -117,7 +116,7 @@ func (c *ChangeCompactor) addCreatedChange(change Change) error { // If existing type is removed it means that this entry does exist // in a DB so we update entry change. c.cache[ledgerKeyString] = Change{ - Type: change.Post.LedgerKey().Type, + Type: key.Type, Pre: existingChange.Pre, Post: change.Post, } @@ -132,9 +131,13 @@ func (c *ChangeCompactor) addCreatedChange(change Change) error { // change is unexpected. func (c *ChangeCompactor) addUpdatedChange(change Change) error { // safe, since we later cast to string (causing a copy) - ledgerKey, err := c.encodingBuffer.UnsafeMarshalBinary(change.Post.LedgerKey()) + key, err := change.Post.LedgerKey() + if err != nil { + return errors.Wrap(err, "error getting ledger key for updated entry") + } + ledgerKey, err := c.encodingBuffer.UnsafeMarshalBinary(key) if err != nil { - return errors.Wrap(err, "Error MarshalBinary") + return errors.Wrap(err, "error marshaling ledger key for updated entry") } ledgerKeyString := string(ledgerKey) @@ -150,13 +153,13 @@ func (c *ChangeCompactor) addUpdatedChange(change Change) error { // If existing type is created it means that this entry does not // exist in a DB so we update entry change. c.cache[ledgerKeyString] = Change{ - Type: change.Post.LedgerKey().Type, + Type: key.Type, Pre: existingChange.Pre, // = nil Post: change.Post, } case xdr.LedgerEntryChangeTypeLedgerEntryUpdated: c.cache[ledgerKeyString] = Change{ - Type: change.Post.LedgerKey().Type, + Type: key.Type, Pre: existingChange.Pre, Post: change.Post, } @@ -176,9 +179,13 @@ func (c *ChangeCompactor) addUpdatedChange(change Change) error { // change is unexpected. func (c *ChangeCompactor) addRemovedChange(change Change) error { // safe, since we later cast to string (causing a copy) - ledgerKey, err := c.encodingBuffer.UnsafeMarshalBinary(change.Pre.LedgerKey()) + key, err := change.Pre.LedgerKey() + if err != nil { + return errors.Wrap(err, "error getting ledger key for removed entry") + } + ledgerKey, err := c.encodingBuffer.UnsafeMarshalBinary(key) if err != nil { - return errors.Wrap(err, "Error MarshalBinary") + return errors.Wrap(err, "error marshaling ledger key for removed entry") } ledgerKeyString := string(ledgerKey) @@ -196,7 +203,7 @@ func (c *ChangeCompactor) addRemovedChange(change Change) error { delete(c.cache, ledgerKeyString) case xdr.LedgerEntryChangeTypeLedgerEntryUpdated: c.cache[ledgerKeyString] = Change{ - Type: change.Pre.LedgerKey().Type, + Type: key.Type, Pre: existingChange.Pre, Post: nil, } @@ -215,9 +222,6 @@ func (c *ChangeCompactor) addRemovedChange(change Change) error { // GetChanges returns a slice of Changes in the cache. The order of changes is // random but each change is connected to a separate entry. func (c *ChangeCompactor) GetChanges() []Change { - c.mutex.Lock() - defer c.mutex.Unlock() - changes := make([]Change, 0, len(c.cache)) for _, entryChange := range c.cache { @@ -229,7 +233,5 @@ func (c *ChangeCompactor) GetChanges() []Change { // Size returns number of ledger entries in the cache. func (c *ChangeCompactor) Size() int { - c.mutex.Lock() - defer c.mutex.Unlock() return len(c.cache) } diff --git a/ingest/change_test.go b/ingest/change_test.go new file mode 100644 index 0000000000..03af4f2cb4 --- /dev/null +++ b/ingest/change_test.go @@ -0,0 +1,215 @@ +package ingest + +import ( + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/stellar/go/xdr" +) + +func assertChangesAreEqual(t *testing.T, a, b Change) { + assert.Equal(t, a.Type, b.Type) + if a.Pre == nil { + assert.Nil(t, b.Pre) + } else { + aBytes, err := a.Pre.MarshalBinary() + assert.NoError(t, err) + bBytes, err := b.Pre.MarshalBinary() + assert.NoError(t, err) + assert.Equal(t, aBytes, bBytes) + } + if a.Post == nil { + assert.Nil(t, b.Post) + } else { + aBytes, err := a.Post.MarshalBinary() + assert.NoError(t, err) + bBytes, err := b.Post.MarshalBinary() + assert.NoError(t, err) + assert.Equal(t, aBytes, bBytes) + } +} + +func TestSortChanges(t *testing.T) { + for _, testCase := range []struct { + input []Change + expected []Change + }{ + {[]Change{}, []Change{}}, + { + []Change{ + { + Type: xdr.LedgerEntryTypeAccount, + Pre: nil, + Post: &xdr.LedgerEntry{ + LastModifiedLedgerSeq: 11, + Data: xdr.LedgerEntryData{ + Type: xdr.LedgerEntryTypeAccount, + Account: &xdr.AccountEntry{ + AccountId: xdr.MustAddress("GC3C4AKRBQLHOJ45U4XG35ESVWRDECWO5XLDGYADO6DPR3L7KIDVUMML"), + }, + }, + }, + }, + }, + []Change{ + { + Type: xdr.LedgerEntryTypeAccount, + Pre: nil, + Post: &xdr.LedgerEntry{ + LastModifiedLedgerSeq: 11, + Data: xdr.LedgerEntryData{ + Type: xdr.LedgerEntryTypeAccount, + Account: &xdr.AccountEntry{ + AccountId: xdr.MustAddress("GC3C4AKRBQLHOJ45U4XG35ESVWRDECWO5XLDGYADO6DPR3L7KIDVUMML"), + }, + }, + }, + }, + }, + }, + { + []Change{ + { + Type: xdr.LedgerEntryTypeAccount, + Pre: nil, + Post: &xdr.LedgerEntry{ + LastModifiedLedgerSeq: 11, + Data: xdr.LedgerEntryData{ + Type: xdr.LedgerEntryTypeAccount, + Account: &xdr.AccountEntry{ + AccountId: xdr.MustAddress("GC3C4AKRBQLHOJ45U4XG35ESVWRDECWO5XLDGYADO6DPR3L7KIDVUMML"), + Balance: 25, + }, + }, + }, + }, + { + Type: xdr.LedgerEntryTypeAccount, + Pre: &xdr.LedgerEntry{ + LastModifiedLedgerSeq: 11, + Data: xdr.LedgerEntryData{ + Type: xdr.LedgerEntryTypeAccount, + Account: &xdr.AccountEntry{ + AccountId: xdr.MustAddress("GCMNSW2UZMSH3ZFRLWP6TW2TG4UX4HLSYO5HNIKUSFMLN2KFSF26JKWF"), + Balance: 20, + }, + }, + }, + Post: nil, + }, + { + Type: xdr.LedgerEntryTypeTtl, + Pre: &xdr.LedgerEntry{ + LastModifiedLedgerSeq: 11, + Data: xdr.LedgerEntryData{ + Type: xdr.LedgerEntryTypeTtl, + Ttl: &xdr.TtlEntry{ + KeyHash: xdr.Hash{1}, + LiveUntilLedgerSeq: 50, + }, + }, + }, + Post: &xdr.LedgerEntry{ + LastModifiedLedgerSeq: 11, + Data: xdr.LedgerEntryData{ + Type: xdr.LedgerEntryTypeTtl, + Ttl: &xdr.TtlEntry{ + KeyHash: xdr.Hash{1}, + LiveUntilLedgerSeq: 100, + }, + }, + }, + }, + { + Type: xdr.LedgerEntryTypeAccount, + Pre: &xdr.LedgerEntry{ + LastModifiedLedgerSeq: 11, + Data: xdr.LedgerEntryData{ + Type: xdr.LedgerEntryTypeAccount, + Account: &xdr.AccountEntry{ + AccountId: xdr.MustAddress("GC3C4AKRBQLHOJ45U4XG35ESVWRDECWO5XLDGYADO6DPR3L7KIDVUMML"), + Balance: 25, + }, + }, + }, + Post: nil, + }, + }, + []Change{ + { + Type: xdr.LedgerEntryTypeAccount, + Pre: &xdr.LedgerEntry{ + LastModifiedLedgerSeq: 11, + Data: xdr.LedgerEntryData{ + Type: xdr.LedgerEntryTypeAccount, + Account: &xdr.AccountEntry{ + AccountId: xdr.MustAddress("GCMNSW2UZMSH3ZFRLWP6TW2TG4UX4HLSYO5HNIKUSFMLN2KFSF26JKWF"), + Balance: 20, + }, + }, + }, + Post: nil, + }, + { + Type: xdr.LedgerEntryTypeAccount, + Pre: nil, + Post: &xdr.LedgerEntry{ + LastModifiedLedgerSeq: 11, + Data: xdr.LedgerEntryData{ + Type: xdr.LedgerEntryTypeAccount, + Account: &xdr.AccountEntry{ + AccountId: xdr.MustAddress("GC3C4AKRBQLHOJ45U4XG35ESVWRDECWO5XLDGYADO6DPR3L7KIDVUMML"), + Balance: 25, + }, + }, + }, + }, + { + Type: xdr.LedgerEntryTypeAccount, + Pre: &xdr.LedgerEntry{ + LastModifiedLedgerSeq: 11, + Data: xdr.LedgerEntryData{ + Type: xdr.LedgerEntryTypeAccount, + Account: &xdr.AccountEntry{ + AccountId: xdr.MustAddress("GC3C4AKRBQLHOJ45U4XG35ESVWRDECWO5XLDGYADO6DPR3L7KIDVUMML"), + Balance: 25, + }, + }, + }, + Post: nil, + }, + + { + Type: xdr.LedgerEntryTypeTtl, + Pre: &xdr.LedgerEntry{ + LastModifiedLedgerSeq: 11, + Data: xdr.LedgerEntryData{ + Type: xdr.LedgerEntryTypeTtl, + Ttl: &xdr.TtlEntry{ + KeyHash: xdr.Hash{1}, + LiveUntilLedgerSeq: 50, + }, + }, + }, + Post: &xdr.LedgerEntry{ + LastModifiedLedgerSeq: 11, + Data: xdr.LedgerEntryData{ + Type: xdr.LedgerEntryTypeTtl, + Ttl: &xdr.TtlEntry{ + KeyHash: xdr.Hash{1}, + LiveUntilLedgerSeq: 100, + }, + }, + }, + }, + }, + }, + } { + sortChanges(testCase.input) + assert.Equal(t, len(testCase.input), len(testCase.expected)) + for i := range testCase.input { + assertChangesAreEqual(t, testCase.input[i], testCase.expected[i]) + } + } +} diff --git a/ingest/checkpoint_change_reader.go b/ingest/checkpoint_change_reader.go index f8d7e18026..37e5e994e1 100644 --- a/ingest/checkpoint_change_reader.go +++ b/ingest/checkpoint_change_reader.go @@ -325,6 +325,8 @@ func (r *CheckpointChangeReader) streamBucketContents(hash historyarchive.Hash, var batch []xdr.BucketEntry lastBatch := false + preloadKeys := make([]string, 0, preloadedEntries) + LoopBucketEntry: for { // Preload entries for faster retrieve from temp store. @@ -332,8 +334,10 @@ LoopBucketEntry: if lastBatch { return true } + batch = make([]xdr.BucketEntry, 0, preloadedEntries) - preloadKeys := []string{} + // reset the content of the preloadKeys + preloadKeys = preloadKeys[:0] for i := 0; i < preloadedEntries; i++ { var entry xdr.BucketEntry @@ -357,11 +361,18 @@ LoopBucketEntry: // Generate a key var key xdr.LedgerKey + var err error switch entry.Type { case xdr.BucketEntryTypeLiveentry, xdr.BucketEntryTypeInitentry: liveEntry := entry.MustLiveEntry() - key = liveEntry.LedgerKey() + key, err = liveEntry.LedgerKey() + if err != nil { + r.readChan <- r.error( + errors.Wrapf(err, "Error generating ledger key for XDR record %d of hash '%s'", n, hash.String()), + ) + return false + } case xdr.BucketEntryTypeDeadentry: key = entry.MustDeadEntry() default: @@ -396,6 +407,7 @@ LoopBucketEntry: n++ var key xdr.LedgerKey + var err error switch entry.Type { case xdr.BucketEntryTypeMetaentry: @@ -414,7 +426,13 @@ LoopBucketEntry: continue LoopBucketEntry case xdr.BucketEntryTypeLiveentry, xdr.BucketEntryTypeInitentry: liveEntry := entry.MustLiveEntry() - key = liveEntry.LedgerKey() + key, err = liveEntry.LedgerKey() + if err != nil { + r.readChan <- r.error( + errors.Wrapf(err, "Error generating ledger key for XDR record %d of hash '%s'", n, hash.String()), + ) + return false + } case xdr.BucketEntryTypeDeadentry: key = entry.MustDeadEntry() default: @@ -523,8 +541,12 @@ func (r *CheckpointChangeReader) Read() (Change, error) { if result.e != nil { return Change{}, errors.Wrap(result.e, "Error while reading from buckets") } + entryType, err := result.entryChange.EntryType() + if err != nil { + return Change{}, errors.Wrap(err, "Error getting entry type") + } return Change{ - Type: result.entryChange.EntryType(), + Type: entryType, Post: result.entryChange.State, }, nil } diff --git a/ingest/checkpoint_change_reader_test.go b/ingest/checkpoint_change_reader_test.go index 6f580a9e0e..08730ddd0f 100644 --- a/ingest/checkpoint_change_reader_test.go +++ b/ingest/checkpoint_change_reader_test.go @@ -757,11 +757,11 @@ func entryAccount(t xdr.BucketEntryType, id string, balance uint32) xdr.BucketEn Type: xdr.BucketEntryTypeDeadentry, DeadEntry: &xdr.LedgerKey{ Type: xdr.LedgerEntryTypeAccount, - Account: &xdr.LedgerKeyAccount{xdr.MustAddress(id)}, + Account: &xdr.LedgerKeyAccount{AccountId: xdr.MustAddress(id)}, }, } default: - panic("Unkown entry type") + panic("Unknown entry type") } } diff --git a/ingest/ledger_change_reader.go b/ingest/ledger_change_reader.go index e1aa3fb2ed..d09c579dbd 100644 --- a/ingest/ledger_change_reader.go +++ b/ingest/ledger_change_reader.go @@ -25,9 +25,11 @@ type ledgerChangeReaderState int const ( // feeChangesState is active when LedgerChangeReader is reading fee changes. feeChangesState ledgerChangeReaderState = iota - // feeChangesState is active when LedgerChangeReader is reading transaction meta changes. + // metaChangesState is active when LedgerChangeReader is reading transaction meta changes. metaChangesState - // feeChangesState is active when LedgerChangeReader is reading upgrade changes. + // evictionChangesState is active when LedgerChangeReader is reading ledger entry evictions. + evictionChangesState + // upgradeChanges is active when LedgerChangeReader is reading upgrade changes. upgradeChangesState ) @@ -122,11 +124,30 @@ func (r *LedgerChangeReader) Read() (Change, error) { r.pending = append(r.pending, metaChanges...) } return r.Read() + case evictionChangesState: + entries, err := r.ledgerCloseMeta.EvictedPersistentLedgerEntries() + if err != nil { + return Change{}, err + } + changes := make([]Change, len(entries)) + for i := range entries { + entry := entries[i] + // when a ledger entry is evicted it is removed from the ledger + changes[i] = Change{ + Type: entry.Data.Type, + Pre: &entry, + Post: nil, + } + } + sortChanges(changes) + r.pending = append(r.pending, changes...) + r.state++ + return r.Read() case upgradeChangesState: // Get upgrade changes - if r.upgradeIndex < len(r.LedgerTransactionReader.ledgerCloseMeta.V0.UpgradesProcessing) { + if r.upgradeIndex < len(r.LedgerTransactionReader.ledgerCloseMeta.UpgradesProcessing()) { changes := GetChangesFromLedgerEntryChanges( - r.LedgerTransactionReader.ledgerCloseMeta.V0.UpgradesProcessing[r.upgradeIndex].Changes, + r.LedgerTransactionReader.ledgerCloseMeta.UpgradesProcessing()[r.upgradeIndex].Changes, ) r.pending = append(r.pending, changes...) r.upgradeIndex++ diff --git a/ingest/ledger_change_reader_test.go b/ingest/ledger_change_reader_test.go index c461ef28c3..0b077007e5 100644 --- a/ingest/ledger_change_reader_test.go +++ b/ingest/ledger_change_reader_test.go @@ -2,11 +2,13 @@ package ingest import ( "context" + "encoding/hex" "fmt" "io" "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "github.com/stellar/go/ingest/ledgerbackend" "github.com/stellar/go/network" @@ -77,16 +79,38 @@ func buildChange(account string, balance int64) xdr.LedgerEntryChange { } } -type balanceEntry struct { - address string - balance int64 +type changePredicate func(*testing.T, int, Change) + +func isBalance(address string, balance int64) changePredicate { + return func(t *testing.T, idx int, change Change) { + msg := fmt.Sprintf("change %d", idx) + require.NotNil(t, change.Post, msg) + assert.Equal(t, xdr.LedgerEntryTypeAccount.String(), change.Post.Data.Type.String(), msg) + assert.Equal(t, address, change.Post.Data.Account.AccountId.Address(), msg) + assert.EqualValues(t, balance, change.Post.Data.Account.Balance, msg) + } } -func parseChange(change Change) balanceEntry { - address := change.Post.Data.Account.AccountId.Address() - balance := int64(change.Post.Data.Account.Balance) +func isContractDataExtension(contract xdr.ScAddress, key xdr.ScVal, extension uint32) changePredicate { + return func(t *testing.T, idx int, change Change) { + msg := fmt.Sprintf("change %d", idx) + require.NotNil(t, change.Post, msg) + require.NotNil(t, change.Pre, msg) + assert.Equal(t, xdr.LedgerEntryTypeContractData.String(), change.Post.Data.Type.String(), msg) + assert.Equal(t, contract, change.Post.Data.ContractData.Contract, msg) + assert.Equal(t, key, change.Post.Data.ContractData.Key, msg) + } +} - return balanceEntry{address, balance} +func isContractDataEviction(contract xdr.ScAddress, key xdr.ScVal) changePredicate { + return func(t *testing.T, idx int, change Change) { + msg := fmt.Sprintf("change %d", idx) + require.NotNil(t, change.Pre, msg) + assert.Nil(t, change.Post, msg) + assert.Equal(t, xdr.LedgerEntryTypeContractData.String(), change.Pre.Data.Type.String(), msg) + assert.Equal(t, contract, change.Pre.Data.ContractData.Contract, msg) + assert.Equal(t, key, change.Pre.Data.ContractData.Key, msg) + } } func assertChangesEqual( @@ -94,12 +118,13 @@ func assertChangesEqual( ctx context.Context, sequence uint32, backend ledgerbackend.LedgerBackend, - expected []balanceEntry, + expectations []changePredicate, ) { reader, err := NewLedgerChangeReader(ctx, backend, network.TestNetworkPassphrase, sequence) assert.NoError(t, err) - changes := []balanceEntry{} + // Read all the changes + var changes []Change for { change, err := reader.Read() if err == io.EOF { @@ -108,11 +133,15 @@ func assertChangesEqual( if err != nil { t.Fatalf("unexpected error: %v", err) } - - changes = append(changes, parseChange(change)) + changes = append(changes, change) } - assert.Equal(t, expected, changes) + assert.Len(t, changes, len(expectations), "unexpected number of changes") + + // Check each change is what we expect + for i, change := range changes { + expectations[i](t, i+1, change) + } } func TestLedgerChangeReaderOrder(t *testing.T) { @@ -224,18 +253,18 @@ func TestLedgerChangeReaderOrder(t *testing.T) { } mock.On("GetLedger", ctx, seq).Return(ledger, nil).Once() - assertChangesEqual(t, ctx, seq, mock, []balanceEntry{ - {feeAddress, 100}, - {feeAddress, 200}, - {feeAddress, 300}, - {metaAddress, 300}, - {metaAddress, 400}, - {metaAddress, 600}, - {metaAddress, 700}, - {metaAddress, 800}, - {metaAddress, 900}, - {upgradeAddress, 2}, - {upgradeAddress, 3}, + assertChangesEqual(t, ctx, seq, mock, []changePredicate{ + isBalance(feeAddress, 100), + isBalance(feeAddress, 200), + isBalance(feeAddress, 300), + isBalance(metaAddress, 300), + isBalance(metaAddress, 400), + isBalance(metaAddress, 600), + isBalance(metaAddress, 700), + isBalance(metaAddress, 800), + isBalance(metaAddress, 900), + isBalance(upgradeAddress, 2), + isBalance(upgradeAddress, 3), }) mock.AssertExpectations(t) @@ -255,15 +284,15 @@ func TestLedgerChangeReaderOrder(t *testing.T) { ledger.V0.TxProcessing[1].FeeProcessing = xdr.LedgerEntryChanges{} mock.On("GetLedger", ctx, seq).Return(ledger, nil).Once() - assertChangesEqual(t, ctx, seq, mock, []balanceEntry{ - {metaAddress, 300}, - {metaAddress, 400}, - {metaAddress, 600}, - {metaAddress, 700}, - {metaAddress, 800}, - {metaAddress, 900}, - {upgradeAddress, 2}, - {upgradeAddress, 3}, + assertChangesEqual(t, ctx, seq, mock, []changePredicate{ + isBalance(metaAddress, 300), + isBalance(metaAddress, 400), + isBalance(metaAddress, 600), + isBalance(metaAddress, 700), + isBalance(metaAddress, 800), + isBalance(metaAddress, 900), + isBalance(upgradeAddress, 2), + isBalance(upgradeAddress, 3), }) mock.AssertExpectations(t) @@ -272,15 +301,15 @@ func TestLedgerChangeReaderOrder(t *testing.T) { ledger.V0.TxProcessing[1].FeeProcessing = xdr.LedgerEntryChanges{} mock.On("GetLedger", ctx, seq).Return(ledger, nil).Once() - assertChangesEqual(t, ctx, seq, mock, []balanceEntry{ - {metaAddress, 300}, - {metaAddress, 400}, - {metaAddress, 600}, - {metaAddress, 700}, - {metaAddress, 800}, - {metaAddress, 900}, - {upgradeAddress, 2}, - {upgradeAddress, 3}, + assertChangesEqual(t, ctx, seq, mock, []changePredicate{ + isBalance(metaAddress, 300), + isBalance(metaAddress, 400), + isBalance(metaAddress, 600), + isBalance(metaAddress, 700), + isBalance(metaAddress, 800), + isBalance(metaAddress, 900), + isBalance(upgradeAddress, 2), + isBalance(upgradeAddress, 3), }) mock.AssertExpectations(t) @@ -294,13 +323,13 @@ func TestLedgerChangeReaderOrder(t *testing.T) { } mock.On("GetLedger", ctx, seq).Return(ledger, nil).Once() - assertChangesEqual(t, ctx, seq, mock, []balanceEntry{ - {metaAddress, 300}, - {metaAddress, 400}, - {metaAddress, 600}, - {metaAddress, 700}, - {metaAddress, 800}, - {metaAddress, 900}, + assertChangesEqual(t, ctx, seq, mock, []changePredicate{ + isBalance(metaAddress, 300), + isBalance(metaAddress, 400), + isBalance(metaAddress, 600), + isBalance(metaAddress, 700), + isBalance(metaAddress, 800), + isBalance(metaAddress, 900), }) mock.AssertExpectations(t) @@ -318,6 +347,295 @@ func TestLedgerChangeReaderOrder(t *testing.T) { } mock.On("GetLedger", ctx, seq).Return(ledger, nil).Once() - assertChangesEqual(t, ctx, seq, mock, []balanceEntry{}) + assertChangesEqual(t, ctx, seq, mock, []changePredicate{}) + mock.AssertExpectations(t) +} + +func TestLedgerChangeLedgerCloseMetaV2(t *testing.T) { + ctx := context.Background() + mock := &ledgerbackend.MockDatabaseBackend{} + seq := uint32(123) + + src := xdr.MustAddress("GBXGQJWVLWOYHFLVTKWV5FGHA3LNYY2JQKM7OAJAUEQFU6LPCSEFVXON") + firstTx := xdr.TransactionEnvelope{ + Type: xdr.EnvelopeTypeEnvelopeTypeTx, + V1: &xdr.TransactionV1Envelope{ + Tx: xdr.Transaction{ + Fee: 1, + SourceAccount: src.ToMuxedAccount(), + }, + }, + } + firstTxHash, err := network.HashTransactionInEnvelope(firstTx, network.TestNetworkPassphrase) + assert.NoError(t, err) + + src = xdr.MustAddress("GCXKG6RN4ONIEPCMNFB732A436Z5PNDSRLGWK7GBLCMQLIFO4S7EYWVU") + secondTx := xdr.TransactionEnvelope{ + Type: xdr.EnvelopeTypeEnvelopeTypeTx, + V1: &xdr.TransactionV1Envelope{ + Tx: xdr.Transaction{ + Fee: 2, + SourceAccount: src.ToMuxedAccount(), + }, + }, + } + secondTxHash, err := network.HashTransactionInEnvelope(secondTx, network.TestNetworkPassphrase) + assert.NoError(t, err) + + baseFee := xdr.Int64(100) + tempKey := xdr.ScSymbol("TEMPKEY") + persistentKey := xdr.ScSymbol("TEMPVAL") + contractIDBytes, err := hex.DecodeString("df06d62447fd25da07c0135eed7557e5a5497ee7d15b7fe345bd47e191d8f577") + assert.NoError(t, err) + var contractID xdr.Hash + copy(contractID[:], contractIDBytes) + contractAddress := xdr.ScAddress{ + Type: xdr.ScAddressTypeScAddressTypeContract, + ContractId: &contractID, + } + ledger := xdr.LedgerCloseMeta{ + V: 1, + V1: &xdr.LedgerCloseMetaV1{ + LedgerHeader: xdr.LedgerHeaderHistoryEntry{Header: xdr.LedgerHeader{LedgerVersion: 10}}, + TxSet: xdr.GeneralizedTransactionSet{ + V: 1, + V1TxSet: &xdr.TransactionSetV1{ + PreviousLedgerHash: xdr.Hash{1, 2, 3}, + Phases: []xdr.TransactionPhase{ + { + V0Components: &[]xdr.TxSetComponent{ + { + Type: xdr.TxSetComponentTypeTxsetCompTxsMaybeDiscountedFee, + TxsMaybeDiscountedFee: &xdr.TxSetComponentTxsMaybeDiscountedFee{ + BaseFee: &baseFee, + Txs: []xdr.TransactionEnvelope{ + secondTx, + firstTx, + }, + }, + }, + }, + }, + }, + }, + }, + TxProcessing: []xdr.TransactionResultMeta{ + { + Result: xdr.TransactionResultPair{TransactionHash: firstTxHash}, + FeeProcessing: xdr.LedgerEntryChanges{ + buildChange(feeAddress, 100), + buildChange(feeAddress, 200), + }, + TxApplyProcessing: xdr.TransactionMeta{ + V: 3, + V3: &xdr.TransactionMetaV3{ + Operations: []xdr.OperationMeta{ + { + Changes: xdr.LedgerEntryChanges{ + buildChange( + metaAddress, + 300, + ), + buildChange( + metaAddress, + 400, + ), + + // Add a couple changes simulating a ledger entry extension + { + Type: xdr.LedgerEntryChangeTypeLedgerEntryState, + State: &xdr.LedgerEntry{ + LastModifiedLedgerSeq: 1, + Data: xdr.LedgerEntryData{ + Type: xdr.LedgerEntryTypeContractData, + ContractData: &xdr.ContractDataEntry{ + Contract: contractAddress, + Key: xdr.ScVal{ + Type: xdr.ScValTypeScvSymbol, + Sym: &persistentKey, + }, + Durability: xdr.ContractDataDurabilityPersistent, + }, + }, + }, + }, + { + Type: xdr.LedgerEntryChangeTypeLedgerEntryUpdated, + Updated: &xdr.LedgerEntry{ + LastModifiedLedgerSeq: 1, + Data: xdr.LedgerEntryData{ + Type: xdr.LedgerEntryTypeContractData, + ContractData: &xdr.ContractDataEntry{ + Contract: xdr.ScAddress{ + Type: xdr.ScAddressTypeScAddressTypeContract, + ContractId: &contractID, + }, + Key: xdr.ScVal{ + Type: xdr.ScValTypeScvSymbol, + Sym: &persistentKey, + }, + Durability: xdr.ContractDataDurabilityPersistent, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + { + Result: xdr.TransactionResultPair{TransactionHash: secondTxHash}, + FeeProcessing: xdr.LedgerEntryChanges{ + buildChange(feeAddress, 300), + }, + TxApplyProcessing: xdr.TransactionMeta{ + V: 3, + V3: &xdr.TransactionMetaV3{ + TxChangesBefore: xdr.LedgerEntryChanges{ + buildChange(metaAddress, 600), + }, + Operations: []xdr.OperationMeta{ + { + Changes: xdr.LedgerEntryChanges{ + buildChange(metaAddress, 700), + }, + }, + }, + TxChangesAfter: xdr.LedgerEntryChanges{ + buildChange(metaAddress, 800), + buildChange(metaAddress, 900), + }, + }, + }, + }, + }, + UpgradesProcessing: []xdr.UpgradeEntryMeta{ + { + Changes: xdr.LedgerEntryChanges{ + buildChange(upgradeAddress, 2), + }, + }, + { + Changes: xdr.LedgerEntryChanges{ + buildChange(upgradeAddress, 3), + }, + }, + }, + EvictedTemporaryLedgerKeys: []xdr.LedgerKey{ + { + Type: xdr.LedgerEntryTypeContractData, + ContractData: &xdr.LedgerKeyContractData{ + Contract: contractAddress, + Key: xdr.ScVal{ + Type: xdr.ScValTypeScvSymbol, + Sym: &tempKey, + }, + Durability: xdr.ContractDataDurabilityTemporary, + }, + }, + }, + EvictedPersistentLedgerEntries: []xdr.LedgerEntry{ + { + LastModifiedLedgerSeq: 123, + Data: xdr.LedgerEntryData{ + Type: xdr.LedgerEntryTypeContractData, + ContractData: &xdr.ContractDataEntry{ + Contract: contractAddress, + Key: xdr.ScVal{ + Type: xdr.ScValTypeScvSymbol, + Sym: &persistentKey, + }, + Durability: xdr.ContractDataDurabilityTemporary, + }, + }, + }, + }, + }, + } + mock.On("GetLedger", ctx, seq).Return(ledger, nil).Once() + + // Check the changes are as expected + assertChangesEqual(t, ctx, seq, mock, []changePredicate{ + // First the first txn balance xfers + isBalance(feeAddress, 100), + isBalance(feeAddress, 200), + isBalance(feeAddress, 300), + isBalance(metaAddress, 300), + isBalance(metaAddress, 400), + // Then the first txn data entry extension + isContractDataExtension( + contractAddress, + xdr.ScVal{ + Type: xdr.ScValTypeScvSymbol, + Sym: &persistentKey, + }, + 5904, + ), + + // Second txn transfers + isBalance(metaAddress, 600), + isBalance(metaAddress, 700), + isBalance(metaAddress, 800), + isBalance(metaAddress, 900), + + // Evictions + isContractDataEviction( + contractAddress, + xdr.ScVal{ + Type: xdr.ScValTypeScvSymbol, + Sym: &persistentKey, + }, + ), + + // Upgrades last + isBalance(upgradeAddress, 2), + isBalance(upgradeAddress, 3), + }) + mock.AssertExpectations(t) + + mock.AssertExpectations(t) +} + +func TestLedgerChangeLedgerCloseMetaV2Empty(t *testing.T) { + ctx := context.Background() + mock := &ledgerbackend.MockDatabaseBackend{} + seq := uint32(123) + + baseFee := xdr.Int64(100) + ledger := xdr.LedgerCloseMeta{ + V: 1, + V1: &xdr.LedgerCloseMetaV1{ + LedgerHeader: xdr.LedgerHeaderHistoryEntry{Header: xdr.LedgerHeader{LedgerVersion: 10}}, + TxSet: xdr.GeneralizedTransactionSet{ + V: 1, + V1TxSet: &xdr.TransactionSetV1{ + PreviousLedgerHash: xdr.Hash{1, 2, 3}, + Phases: []xdr.TransactionPhase{ + { + V0Components: &[]xdr.TxSetComponent{ + { + Type: xdr.TxSetComponentTypeTxsetCompTxsMaybeDiscountedFee, + TxsMaybeDiscountedFee: &xdr.TxSetComponentTxsMaybeDiscountedFee{ + BaseFee: &baseFee, + Txs: []xdr.TransactionEnvelope{}, + }, + }, + }, + }, + }, + }, + }, + TxProcessing: []xdr.TransactionResultMeta{}, + UpgradesProcessing: []xdr.UpgradeEntryMeta{}, + EvictedTemporaryLedgerKeys: []xdr.LedgerKey{}, + EvictedPersistentLedgerEntries: []xdr.LedgerEntry{}, + }, + } + mock.On("GetLedger", ctx, seq).Return(ledger, nil).Once() + + // Check there are no changes + assertChangesEqual(t, ctx, seq, mock, []changePredicate{}) mock.AssertExpectations(t) } diff --git a/ingest/ledger_transaction.go b/ingest/ledger_transaction.go index 6fdc8b10a7..56f5af6070 100644 --- a/ingest/ledger_transaction.go +++ b/ingest/ledger_transaction.go @@ -1,6 +1,8 @@ package ingest import ( + "fmt" + "github.com/stellar/go/support/errors" "github.com/stellar/go/xdr" ) @@ -14,8 +16,9 @@ type LedgerTransaction struct { // you know what you are doing. // Use LedgerTransaction.GetChanges() for higher level access to ledger // entry changes. - FeeChanges xdr.LedgerEntryChanges - UnsafeMeta xdr.TransactionMeta + FeeChanges xdr.LedgerEntryChanges + UnsafeMeta xdr.TransactionMeta + LedgerVersion uint32 } func (t *LedgerTransaction) txInternalError() bool { @@ -45,7 +48,7 @@ func (t *LedgerTransaction) GetChanges() ([]Change, error) { changes = append(changes, txChanges...) // Ignore operations meta if txInternalError https://github.com/stellar/go/issues/2111 - if t.txInternalError() { + if t.txInternalError() && t.LedgerVersion <= 12 { return changes, nil } @@ -55,26 +58,44 @@ func (t *LedgerTransaction) GetChanges() ([]Change, error) { ) changes = append(changes, opChanges...) } + case 2, 3: + var ( + beforeChanges, afterChanges xdr.LedgerEntryChanges + operationMeta []xdr.OperationMeta + ) + + switch t.UnsafeMeta.V { + case 2: + v2Meta := t.UnsafeMeta.MustV2() + beforeChanges = v2Meta.TxChangesBefore + afterChanges = v2Meta.TxChangesAfter + operationMeta = v2Meta.Operations + case 3: + v3Meta := t.UnsafeMeta.MustV3() + beforeChanges = v3Meta.TxChangesBefore + afterChanges = v3Meta.TxChangesAfter + operationMeta = v3Meta.Operations + default: + panic("Invalid meta version, expected 2 or 3") + } - case 2: - v2Meta := t.UnsafeMeta.MustV2() - txChangesBefore := GetChangesFromLedgerEntryChanges(v2Meta.TxChangesBefore) + txChangesBefore := GetChangesFromLedgerEntryChanges(beforeChanges) changes = append(changes, txChangesBefore...) // Ignore operations meta and txChangesAfter if txInternalError // https://github.com/stellar/go/issues/2111 - if t.txInternalError() { + if t.txInternalError() && t.LedgerVersion <= 12 { return changes, nil } - for _, operationMeta := range v2Meta.Operations { + for _, operationMeta := range operationMeta { opChanges := GetChangesFromLedgerEntryChanges( operationMeta.Changes, ) changes = append(changes, opChanges...) } - txChangesAfter := GetChangesFromLedgerEntryChanges(v2Meta.TxChangesAfter) + txChangesAfter := GetChangesFromLedgerEntryChanges(afterChanges) changes = append(changes, txChangesAfter...) default: return changes, errors.New("Unsupported TransactionMeta version") @@ -97,31 +118,28 @@ func (t *LedgerTransaction) GetOperation(index uint32) (xdr.Operation, bool) { func (t *LedgerTransaction) GetOperationChanges(operationIndex uint32) ([]Change, error) { changes := []Change{} - // Transaction meta - switch t.UnsafeMeta.V { - case 0: + if t.UnsafeMeta.V == 0 { return changes, errors.New("TransactionMeta.V=0 not supported") - case 1: - // Ignore operations meta if txInternalError https://github.com/stellar/go/issues/2111 - if t.txInternalError() { - return changes, nil - } + } - v1Meta := t.UnsafeMeta.MustV1() - changes = operationChanges(v1Meta.Operations, operationIndex) - case 2: - // Ignore operations meta if txInternalError https://github.com/stellar/go/issues/2111 - if t.txInternalError() { - return changes, nil - } + // Ignore operations meta if txInternalError https://github.com/stellar/go/issues/2111 + if t.txInternalError() && t.LedgerVersion <= 12 { + return changes, nil + } - v2Meta := t.UnsafeMeta.MustV2() - changes = operationChanges(v2Meta.Operations, operationIndex) + var operationMeta []xdr.OperationMeta + switch t.UnsafeMeta.V { + case 1: + operationMeta = t.UnsafeMeta.MustV1().Operations + case 2: + operationMeta = t.UnsafeMeta.MustV2().Operations + case 3: + operationMeta = t.UnsafeMeta.MustV3().Operations default: return changes, errors.New("Unsupported TransactionMeta version") } - return changes, nil + return operationChanges(operationMeta, operationIndex), nil } func operationChanges(ops []xdr.OperationMeta, index uint32) []Change { @@ -134,3 +152,43 @@ func operationChanges(ops []xdr.OperationMeta, index uint32) []Change { operationMeta.Changes, ) } + +// GetDiagnosticEvents returns all contract events emitted by a given operation. +func (t *LedgerTransaction) GetDiagnosticEvents() ([]xdr.DiagnosticEvent, error) { + switch t.UnsafeMeta.V { + case 1: + return nil, nil + case 2: + return nil, nil + case 3: + var diagnosticEvents []xdr.DiagnosticEvent + var contractEvents []xdr.ContractEvent + if sorobanMeta := t.UnsafeMeta.MustV3().SorobanMeta; sorobanMeta != nil { + diagnosticEvents = sorobanMeta.DiagnosticEvents + if len(diagnosticEvents) > 0 { + // all contract events and diag events for a single operation(by it's index in the tx) were available + // in tx meta's DiagnosticEvents, no need to look anywhere else for events + return diagnosticEvents, nil + } + + contractEvents = sorobanMeta.Events + if len(contractEvents) == 0 { + // no events were present in this tx meta + return nil, nil + } + } + + // tx meta only provided contract events, no diagnostic events, we convert the contract + // event to a diagnostic event, to fit the response interface. + convertedDiagnosticEvents := make([]xdr.DiagnosticEvent, len(contractEvents)) + for i, event := range contractEvents { + convertedDiagnosticEvents[i] = xdr.DiagnosticEvent{ + InSuccessfulContractCall: true, + Event: event, + } + } + return convertedDiagnosticEvents, nil + default: + return nil, fmt.Errorf("unsupported TransactionMeta version: %v", t.UnsafeMeta.V) + } +} diff --git a/ingest/ledger_transaction_reader.go b/ingest/ledger_transaction_reader.go index ef68e67aa0..8199309944 100644 --- a/ingest/ledger_transaction_reader.go +++ b/ingest/ledger_transaction_reader.go @@ -30,7 +30,7 @@ func NewLedgerTransactionReader(ctx context.Context, backend ledgerbackend.Ledge return NewLedgerTransactionReaderFromLedgerCloseMeta(networkPassphrase, ledgerCloseMeta) } -// NewLedgerTransactionReaderFromXdr creates a new TransactionReader instance from xdr.LedgerCloseMeta. +// NewLedgerTransactionReaderFromLedgerCloseMeta creates a new TransactionReader instance from xdr.LedgerCloseMeta. // Note that TransactionReader is not thread safe and should not be shared by multiple goroutines. func NewLedgerTransactionReaderFromLedgerCloseMeta(networkPassphrase string, ledgerCloseMeta xdr.LedgerCloseMeta) (*LedgerTransactionReader, error) { reader := &LedgerTransactionReader{ledgerCloseMeta: ledgerCloseMeta} @@ -47,7 +47,7 @@ func (reader *LedgerTransactionReader) GetSequence() uint32 { // GetHeader returns the XDR Header data associated with the stored ledger. func (reader *LedgerTransactionReader) GetHeader() xdr.LedgerHeaderHistoryEntry { - return reader.ledgerCloseMeta.V0.LedgerHeader + return reader.ledgerCloseMeta.LedgerHeaderHistoryEntry() } // Read returns the next transaction in the ledger, ordered by tx number, each time @@ -69,7 +69,7 @@ func (reader *LedgerTransactionReader) Rewind() { // a per-transaction view of the data when Read() is called. func (reader *LedgerTransactionReader) storeTransactions(lcm xdr.LedgerCloseMeta, networkPassphrase string) error { byHash := map[xdr.Hash]xdr.TransactionEnvelope{} - for i, tx := range lcm.V0.TxSet.Txs { + for i, tx := range lcm.TransactionEnvelopes() { hash, err := network.HashTransactionInEnvelope(tx, networkPassphrase) if err != nil { return errors.Wrapf(err, "could not hash transaction %d in TxSet", i) @@ -77,18 +77,18 @@ func (reader *LedgerTransactionReader) storeTransactions(lcm xdr.LedgerCloseMeta byHash[hash] = tx } - for i := range lcm.V0.TxProcessing { - result := lcm.V0.TxProcessing[i].Result - envelope, ok := byHash[result.TransactionHash] + for i := 0; i < lcm.CountTransactions(); i++ { + hash := lcm.TransactionHash(i) + envelope, ok := byHash[hash] if !ok { - hexHash := hex.EncodeToString(result.TransactionHash[:]) + hexHash := hex.EncodeToString(hash[:]) return errors.Errorf("unknown tx hash in LedgerCloseMeta: %v", hexHash) } // We check the version only if FeeProcessing are non empty because some backends // (like HistoryArchiveBackend) do not return meta. - if lcm.V0.LedgerHeader.Header.LedgerVersion < 10 && lcm.V0.TxProcessing[i].TxApplyProcessing.V != 2 && - len(lcm.V0.TxProcessing[i].FeeProcessing) > 0 { + if lcm.ProtocolVersion() < 10 && lcm.TxApplyProcessing(i).V < 2 && + len(lcm.FeeProcessing(i)) > 0 { return errors.New( "TransactionMeta.V=2 is required in protocol version older than version 10. " + "Please process ledgers again using the latest stellar-core version.", @@ -96,11 +96,12 @@ func (reader *LedgerTransactionReader) storeTransactions(lcm xdr.LedgerCloseMeta } reader.transactions = append(reader.transactions, LedgerTransaction{ - Index: uint32(i + 1), // Transactions start at '1' - Envelope: envelope, - Result: result, - UnsafeMeta: lcm.V0.TxProcessing[i].TxApplyProcessing, - FeeChanges: lcm.V0.TxProcessing[i].FeeProcessing, + Index: uint32(i + 1), // Transactions start at '1' + Envelope: envelope, + Result: lcm.TransactionResultPair(i), + UnsafeMeta: lcm.TxApplyProcessing(i), + FeeChanges: lcm.FeeProcessing(i), + LedgerVersion: uint32(lcm.LedgerHeaderHistoryEntry().Header.LedgerVersion), }) } return nil diff --git a/ingest/ledger_transaction_test.go b/ingest/ledger_transaction_test.go index 348b1d9688..9533d21585 100644 --- a/ingest/ledger_transaction_test.go +++ b/ingest/ledger_transaction_test.go @@ -5,6 +5,7 @@ import ( "github.com/stellar/go/xdr" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestChangeAccountChangedExceptSignersInvalidType(t *testing.T) { @@ -12,13 +13,249 @@ func TestChangeAccountChangedExceptSignersInvalidType(t *testing.T) { Type: xdr.LedgerEntryTypeOffer, } + var err error assert.Panics(t, func() { - change.AccountChangedExceptSigners() + _, err = change.AccountChangedExceptSigners() }) + // the following is here only to avoid false-positive warning by the linter. + require.NoError(t, err) +} + +func TestGetContractEventsEmpty(t *testing.T) { + tx := LedgerTransaction{ + FeeChanges: xdr.LedgerEntryChanges{}, + UnsafeMeta: xdr.TransactionMeta{ + V: 3, + V3: &xdr.TransactionMetaV3{ + SorobanMeta: &xdr.SorobanTransactionMeta{ + Events: []xdr.ContractEvent{}, + }, + }, + }, + } + + events, err := tx.GetDiagnosticEvents() + assert.NoError(t, err) + assert.Empty(t, events) +} + +func TestGetContractEventsSingle(t *testing.T) { + value := xdr.Uint32(1) + tx := LedgerTransaction{ + FeeChanges: xdr.LedgerEntryChanges{}, + UnsafeMeta: xdr.TransactionMeta{ + V: 3, + V3: &xdr.TransactionMetaV3{ + SorobanMeta: &xdr.SorobanTransactionMeta{ + Events: []xdr.ContractEvent{ + { + Type: xdr.ContractEventTypeSystem, + Body: xdr.ContractEventBody{ + V: 0, + V0: &xdr.ContractEventV0{ + Data: xdr.ScVal{Type: xdr.ScValTypeScvU32, U32: &value}, + }, + }, + }, + }, + }, + }, + }, + } + + events, err := tx.GetDiagnosticEvents() + assert.Len(t, events, 1) + assert.True(t, events[0].InSuccessfulContractCall) + assert.Equal(t, *events[0].Event.Body.V0.Data.U32, value) + + tx.UnsafeMeta.V = 0 + _, err = tx.GetDiagnosticEvents() + assert.EqualError(t, err, "unsupported TransactionMeta version: 0") + + tx.UnsafeMeta.V = 4 + _, err = tx.GetDiagnosticEvents() + assert.EqualError(t, err, "unsupported TransactionMeta version: 4") + + tx.UnsafeMeta.V = 1 + events, err = tx.GetDiagnosticEvents() + assert.NoError(t, err) + assert.Empty(t, events) + + tx.UnsafeMeta.V = 2 + events, err = tx.GetDiagnosticEvents() + assert.NoError(t, err) + assert.Empty(t, events) +} + +func TestGetContractEventsMultiple(t *testing.T) { + values := make([]xdr.Uint32, 2) + for i := range values { + values[i] = xdr.Uint32(i) + } + tx := LedgerTransaction{ + FeeChanges: xdr.LedgerEntryChanges{}, + UnsafeMeta: xdr.TransactionMeta{ + V: 3, + V3: &xdr.TransactionMetaV3{ + SorobanMeta: &xdr.SorobanTransactionMeta{ + Events: []xdr.ContractEvent{ + { + Type: xdr.ContractEventTypeSystem, + Body: xdr.ContractEventBody{ + V: 0, + V0: &xdr.ContractEventV0{ + Data: xdr.ScVal{Type: xdr.ScValTypeScvU32, U32: &values[0]}, + }, + }, + }, + { + Type: xdr.ContractEventTypeSystem, + Body: xdr.ContractEventBody{ + V: 0, + V0: &xdr.ContractEventV0{ + Data: xdr.ScVal{Type: xdr.ScValTypeScvU32, U32: &values[1]}, + }, + }, + }, + }, + }, + }, + }, + } + events, err := tx.GetDiagnosticEvents() + assert.NoError(t, err) + assert.Len(t, events, 2) + assert.True(t, events[0].InSuccessfulContractCall) + assert.Equal(t, *events[0].Event.Body.V0.Data.U32, values[0]) + assert.True(t, events[1].InSuccessfulContractCall) + assert.Equal(t, *events[1].Event.Body.V0.Data.U32, values[1]) +} + +func TestGetDiagnosticEventsEmpty(t *testing.T) { + tx := LedgerTransaction{ + FeeChanges: xdr.LedgerEntryChanges{}, + UnsafeMeta: xdr.TransactionMeta{ + V: 3, + V3: &xdr.TransactionMetaV3{ + SorobanMeta: &xdr.SorobanTransactionMeta{ + DiagnosticEvents: []xdr.DiagnosticEvent{}, + }, + }, + }, + } + + events, err := tx.GetDiagnosticEvents() + assert.NoError(t, err) + assert.Empty(t, events) +} + +func TestGetDiagnosticEventsSingle(t *testing.T) { + value := xdr.Uint32(1) + tx := LedgerTransaction{ + FeeChanges: xdr.LedgerEntryChanges{}, + UnsafeMeta: xdr.TransactionMeta{ + V: 3, + V3: &xdr.TransactionMetaV3{ + SorobanMeta: &xdr.SorobanTransactionMeta{ + DiagnosticEvents: []xdr.DiagnosticEvent{ + { + InSuccessfulContractCall: false, + Event: xdr.ContractEvent{ + Type: xdr.ContractEventTypeSystem, + Body: xdr.ContractEventBody{ + V: 0, + V0: &xdr.ContractEventV0{ + Data: xdr.ScVal{Type: xdr.ScValTypeScvU32, U32: &value}, + }, + }, + }, + }, + }, + }, + }, + }, + } + + events, err := tx.GetDiagnosticEvents() + assert.NoError(t, err) + assert.Len(t, events, 1) + assert.False(t, events[0].InSuccessfulContractCall) + assert.Equal(t, *events[0].Event.Body.V0.Data.U32, value) + + tx.UnsafeMeta.V = 0 + _, err = tx.GetDiagnosticEvents() + assert.EqualError(t, err, "unsupported TransactionMeta version: 0") + + tx.UnsafeMeta.V = 4 + _, err = tx.GetDiagnosticEvents() + assert.EqualError(t, err, "unsupported TransactionMeta version: 4") + + tx.UnsafeMeta.V = 1 + events, err = tx.GetDiagnosticEvents() + assert.NoError(t, err) + assert.Empty(t, events) + + tx.UnsafeMeta.V = 2 + events, err = tx.GetDiagnosticEvents() + assert.NoError(t, err) + assert.Empty(t, events) +} + +func TestGetDiagnosticEventsMultiple(t *testing.T) { + values := make([]xdr.Uint32, 2) + for i := range values { + values[i] = xdr.Uint32(i) + } + tx := LedgerTransaction{ + FeeChanges: xdr.LedgerEntryChanges{}, + UnsafeMeta: xdr.TransactionMeta{ + V: 3, + V3: &xdr.TransactionMetaV3{ + SorobanMeta: &xdr.SorobanTransactionMeta{ + DiagnosticEvents: []xdr.DiagnosticEvent{ + { + InSuccessfulContractCall: true, + + Event: xdr.ContractEvent{ + Type: xdr.ContractEventTypeSystem, + Body: xdr.ContractEventBody{ + V: 0, + V0: &xdr.ContractEventV0{ + Data: xdr.ScVal{Type: xdr.ScValTypeScvU32, U32: &values[0]}, + }, + }, + }, + }, + { + InSuccessfulContractCall: true, + Event: xdr.ContractEvent{ + Type: xdr.ContractEventTypeSystem, + Body: xdr.ContractEventBody{ + V: 0, + V0: &xdr.ContractEventV0{ + Data: xdr.ScVal{Type: xdr.ScValTypeScvU32, U32: &values[1]}, + }, + }, + }, + }, + }, + }, + }, + }, + } + + events, err := tx.GetDiagnosticEvents() + assert.NoError(t, err) + assert.Len(t, events, 2) + assert.True(t, events[0].InSuccessfulContractCall) + assert.Equal(t, *events[0].Event.Body.V0.Data.U32, values[0]) + assert.True(t, events[1].InSuccessfulContractCall) + assert.Equal(t, *events[1].Event.Body.V0.Data.U32, values[1]) } func TestFeeMetaAndOperationsChangesSeparate(t *testing.T) { tx := LedgerTransaction{ + LedgerVersion: 12, FeeChanges: xdr.LedgerEntryChanges{ xdr.LedgerEntryChange{ Type: xdr.LedgerEntryChangeTypeLedgerEntryState, @@ -108,6 +345,21 @@ func TestFeeMetaAndOperationsChangesSeparate(t *testing.T) { operationChanges, err = tx.GetOperationChanges(0) assert.NoError(t, err) assert.Len(t, operationChanges, 0) + + // Starting from protocol 13, we no longer need to ignore txInternalError + tx.LedgerVersion = 13 + + metaChanges, err = tx.GetChanges() + assert.NoError(t, err) + assert.Len(t, metaChanges, 1) + assert.Equal(t, metaChanges[0].Pre.Data.MustAccount().Balance, xdr.Int64(300)) + assert.Equal(t, metaChanges[0].Post.Data.MustAccount().Balance, xdr.Int64(400)) + + operationChanges, err = tx.GetOperationChanges(0) + assert.NoError(t, err) + assert.Len(t, operationChanges, 1) + assert.Equal(t, operationChanges[0].Pre.Data.MustAccount().Balance, xdr.Int64(300)) + assert.Equal(t, operationChanges[0].Post.Data.MustAccount().Balance, xdr.Int64(400)) } func TestFailedTransactionOperationChangesMeta(t *testing.T) { diff --git a/ingest/ledgerbackend/buffered_meta_pipe_reader.go b/ingest/ledgerbackend/buffered_meta_pipe_reader.go index 7854beb2f0..791d9be72b 100644 --- a/ingest/ledgerbackend/buffered_meta_pipe_reader.go +++ b/ingest/ledgerbackend/buffered_meta_pipe_reader.go @@ -49,7 +49,7 @@ type metaResult struct { // It solves the following issues: // // - Decouples buffering from stellarCoreRunner so it can focus on running core. -// - Decouples unmarshalling and buffering of LedgerCloseMeta's from CaptiveCore. +// - Decouples unmarshaling and buffering of LedgerCloseMeta's from CaptiveCore. // - By adding buffering it allows unmarshaling the ledgers available in Stellar-Core // while previous ledger are being processed. // - Limits memory usage in case of large ledgers are closed by the network. @@ -97,9 +97,9 @@ func (b *bufferedLedgerMetaReader) readLedgerMetaFromPipe() (*xdr.LedgerCloseMet } var xlcm xdr.LedgerCloseMeta - _, err = xlcm.DecodeFrom(b.decoder) + _, err = xlcm.DecodeFrom(b.decoder, xdr3.DecodeDefaultMaxDepth) if err != nil { - return nil, errors.Wrap(err, "unmarshalling framed LedgerCloseMeta") + return nil, errors.Wrap(err, "unmarshaling framed LedgerCloseMeta") } return &xlcm, nil } diff --git a/ingest/ledgerbackend/captive_core_backend.go b/ingest/ledgerbackend/captive_core_backend.go index a9c84a22cd..a8acb19182 100644 --- a/ingest/ledgerbackend/captive_core_backend.go +++ b/ingest/ledgerbackend/captive_core_backend.go @@ -3,12 +3,17 @@ package ledgerbackend import ( "context" "encoding/hex" + "fmt" + "net/http" "os" "sync" + "time" "github.com/pkg/errors" + "github.com/prometheus/client_golang/prometheus" "github.com/sirupsen/logrus" + "github.com/stellar/go/clients/stellarcore" "github.com/stellar/go/historyarchive" "github.com/stellar/go/support/log" "github.com/stellar/go/support/storage" @@ -18,6 +23,9 @@ import ( // Ensure CaptiveStellarCore implements LedgerBackend var _ LedgerBackend = (*CaptiveStellarCore)(nil) +// ErrCannotStartFromGenesis is returned when attempting to prepare a range from ledger 1 +var ErrCannotStartFromGenesis = errors.New("CaptiveCore is unable to start from ledger 1, start from ledger 2") + func (c *CaptiveStellarCore) roundDownToFirstReplayAfterCheckpointStart(ledger uint32) uint32 { r := c.checkpointManager.GetCheckpointRange(ledger) if r.Low <= 1 { @@ -71,6 +79,7 @@ type CaptiveStellarCore struct { archive historyarchive.ArchiveInterface checkpointManager historyarchive.CheckpointManager ledgerHashStore TrustedLedgerHashStore + useDB bool // cancel is the CancelFunc for context which controls the lifetime of a CaptiveStellarCore instance. // Once it is invoked CaptiveStellarCore will not be able to stream ledgers from Stellar Core or @@ -89,11 +98,20 @@ type CaptiveStellarCore struct { // cachedMeta keeps that ledger data of the last fetched ledger. Updated in GetLedger(). cachedMeta *xdr.LedgerCloseMeta + // ledgerSequenceLock mutex is used to protect the member variables used in the + // read-only GetLatestLedgerSequence method from concurrent write operations. + // This is required when GetLatestLedgerSequence is called from other goroutine + // such as writing Prometheus metric captive_stellar_core_latest_ledger. + ledgerSequenceLock sync.RWMutex + prepared *Range // non-nil if any range is prepared closed bool // False until the core is closed nextLedger uint32 // next ledger expected, error w/ restart if not seen lastLedger *uint32 // end of current segment if offline, nil if online previousLedgerHash *string + + config CaptiveCoreConfig + stellarCoreClient *stellarcore.Client } // CaptiveCoreConfig contains all the parameters required to create a CaptiveStellarCore instance @@ -174,16 +192,90 @@ func NewCaptive(config CaptiveCoreConfig) (*CaptiveStellarCore, error) { c := &CaptiveStellarCore{ archive: &archivePool, ledgerHashStore: config.LedgerHashStore, + useDB: config.UseDB, cancel: cancel, + config: config, checkpointManager: historyarchive.NewCheckpointManager(config.CheckpointFrequency), } c.stellarCoreRunnerFactory = func() stellarCoreRunnerInterface { return newStellarCoreRunner(config) } + + if config.Toml != nil && config.Toml.HTTPPort != 0 { + c.stellarCoreClient = &stellarcore.Client{ + HTTP: &http.Client{ + Timeout: 2 * time.Second, + }, + URL: fmt.Sprintf("http://localhost:%d", config.Toml.HTTPPort), + } + } + return c, nil } +func (c *CaptiveStellarCore) coreSyncedMetric() float64 { + if c.stellarCoreClient == nil { + return -2 + } + + info, err := c.stellarCoreClient.Info(c.config.Context) + if err != nil { + c.config.Log.WithError(err).Warn("Cannot connect to Captive Stellar-Core HTTP server") + return -1 + } + + if info.IsSynced() { + return 1 + } else { + return 0 + } +} + +func (c *CaptiveStellarCore) coreVersionMetric() float64 { + if c.stellarCoreClient == nil { + return -2 + } + + info, err := c.stellarCoreClient.Info(c.config.Context) + if err != nil { + c.config.Log.WithError(err).Warn("Cannot connect to Captive Stellar-Core HTTP server") + return -1 + } + + return float64(info.Info.ProtocolVersion) +} + +func (c *CaptiveStellarCore) registerMetrics(registry *prometheus.Registry, namespace string) { + coreSynced := prometheus.NewGaugeFunc( + prometheus.GaugeOpts{ + Namespace: namespace, Subsystem: "ingest", Name: "captive_stellar_core_synced", + Help: "1 if sync, 0 if not synced, -1 if unable to connect or HTTP server disabled.", + }, + c.coreSyncedMetric, + ) + supportedProtocolVersion := prometheus.NewGaugeFunc( + prometheus.GaugeOpts{ + Namespace: namespace, Subsystem: "ingest", Name: "captive_stellar_core_supported_protocol_version", + Help: "determines the supported version of the protocol by Captive-Core", + }, + c.coreVersionMetric, + ) + latestLedger := prometheus.NewGaugeFunc(prometheus.GaugeOpts{ + Namespace: namespace, Subsystem: "ingest", Name: "captive_stellar_core_latest_ledger", + Help: "sequence number of the latest ledger available in the ledger backend", + }, + func() float64 { + latest, err := c.GetLatestLedgerSequence(context.Background()) + if err != nil { + return 0 + } + return float64(latest) + }, + ) + registry.MustRegister(coreSynced, supportedProtocolVersion, latestLedger) +} + func (c *CaptiveStellarCore) getLatestCheckpointSequence() (uint32, error) { has, err := c.archive.GetRootHAS() if err != nil { @@ -224,6 +316,9 @@ func (c *CaptiveStellarCore) openOfflineReplaySubprocess(from, to uint32) error // The next ledger should be the first ledger of the checkpoint containing // the requested ledger ran := BoundedRange(from, to) + c.ledgerSequenceLock.Lock() + defer c.ledgerSequenceLock.Unlock() + c.prepared = &ran c.nextLedger = c.roundDownToFirstReplayAfterCheckpointStart(from) c.lastLedger = &to @@ -233,30 +328,12 @@ func (c *CaptiveStellarCore) openOfflineReplaySubprocess(from, to uint32) error } func (c *CaptiveStellarCore) openOnlineReplaySubprocess(ctx context.Context, from uint32) error { - latestCheckpointSequence, err := c.getLatestCheckpointSequence() - if err != nil { - return errors.Wrap(err, "error getting latest checkpoint sequence") - } - - // We don't allow starting the online mode starting with more than two - // checkpoints from now. Such requests are likely buggy. - // We should allow only one checkpoint here but sometimes there are up to a - // minute delays when updating root HAS by stellar-core. - twoCheckPointsLength := (c.checkpointManager.GetCheckpoint(0) + 1) * 2 - maxLedger := latestCheckpointSequence + twoCheckPointsLength - if from > maxLedger { - return errors.Errorf( - "trying to start online mode too far (latest checkpoint=%d), only two checkpoints in the future allowed", - latestCheckpointSequence, - ) - } - - c.stellarCoreRunner = c.stellarCoreRunnerFactory() runFrom, ledgerHash, err := c.runFromParams(ctx, from) if err != nil { return errors.Wrap(err, "error calculating ledger and hash for stellar-core run") } + c.stellarCoreRunner = c.stellarCoreRunnerFactory() err = c.stellarCoreRunner.runFrom(runFrom, ledgerHash) if err != nil { return errors.Wrap(err, "error running stellar-core") @@ -265,6 +342,9 @@ func (c *CaptiveStellarCore) openOnlineReplaySubprocess(ctx context.Context, fro // In the online mode we update nextLedger after streaming the first ledger. // This is to support versions before and after/including v17.1.0 that // introduced minimal persistent DB. + c.ledgerSequenceLock.Lock() + defer c.ledgerSequenceLock.Unlock() + c.nextLedger = 0 ran := UnboundedRange(from) c.prepared = &ran @@ -276,17 +356,15 @@ func (c *CaptiveStellarCore) openOnlineReplaySubprocess(ctx context.Context, fro // runFromParams receives a ledger sequence and calculates the required values to call stellar-core run with --start-ledger and --start-hash func (c *CaptiveStellarCore) runFromParams(ctx context.Context, from uint32) (uint32, string, error) { - if from == 1 { // Trying to start-from 1 results in an error from Stellar-Core: // Target ledger 1 is not newer than last closed ledger 1 - nothing to do // TODO maybe we can fix it by generating 1st ledger meta // like GenesisLedgerStateReader? - err := errors.New("CaptiveCore is unable to start from ledger 1, start from ledger 2") - return 0, "", err + return 0, "", ErrCannotStartFromGenesis } - if from <= 63 { + if from <= c.checkpointManager.GetCheckpoint(0) { // The line below is to support a special case for streaming ledger 2 // that works for all other ledgers <= 63 (fast-forward). // We can't set from=2 because Stellar-Core will not allow starting from 1. @@ -295,10 +373,34 @@ func (c *CaptiveStellarCore) runFromParams(ctx context.Context, from uint32) (ui from = 3 } + latestCheckpointSequence, err := c.getLatestCheckpointSequence() + if err != nil { + return 0, "", errors.Wrap(err, "error getting latest checkpoint sequence") + } + + // We don't allow starting the online mode starting with more than two + // checkpoints from now. Such requests are likely buggy. + // We should allow only one checkpoint here but sometimes there are up to a + // minute delays when updating root HAS by stellar-core. + twoCheckPointsLength := (c.checkpointManager.GetCheckpoint(0) + 1) * 2 + maxLedger := latestCheckpointSequence + twoCheckPointsLength + if from > maxLedger { + return 0, "", errors.Errorf( + "trying to start online mode too far (latest checkpoint=%d), only two checkpoints in the future allowed", + latestCheckpointSequence, + ) + } + runFrom := from - 1 + if c.useDB { + // when running captive core with a db the ledger hash is not required + return runFrom, "", nil + } + if c.ledgerHashStore != nil { + var ledgerHash string var exists bool - ledgerHash, exists, err := c.ledgerHashStore.GetLedgerHash(ctx, runFrom) + ledgerHash, exists, err = c.ledgerHashStore.GetLedgerHash(ctx, runFrom) if err != nil { err = errors.Wrapf(err, "error trying to read ledger hash %d", runFrom) return 0, "", err @@ -308,6 +410,17 @@ func (c *CaptiveStellarCore) runFromParams(ctx context.Context, from uint32) (ui } } + // If from is ahead of the latest checkpoint and we need to obtain + // the ledgerHash from the history archives we will not be able to do + // so because the history archives only contains ledgers up to the latest + // checkpoint. In this case, we'll try to start from the latest checkpoint + // ledger so that we're able to obtain the ledgerHash successfully. + // Then we will seek ahead to the desired ledger in PrepareRange(). + if latestCheckpointSequence > 0 && from > latestCheckpointSequence { + from = latestCheckpointSequence + runFrom = from - 1 + } + ledgerHeader, err := c.archive.GetLedgerHeader(from) if err != nil { return 0, "", errors.Wrapf(err, "error trying to read ledger header %d from HAS", from) @@ -378,9 +491,13 @@ func (c *CaptiveStellarCore) PrepareRange(ctx context.Context, ledgerRange Range return nil } - _, err := c.GetLedger(ctx, ledgerRange.from) - if err != nil { - return errors.Wrapf(err, "Error fast-forwarding to %d", ledgerRange.from) + // the prepared range might be below ledgerRange.from so we + // need to seek ahead until we reach ledgerRange.from + for seq := c.prepared.from; seq <= ledgerRange.from; seq++ { + _, err := c.GetLedger(ctx, seq) + if err != nil { + return errors.Wrapf(err, "Error fast-forwarding to %d", ledgerRange.from) + } } return nil @@ -545,7 +662,10 @@ func (c *CaptiveStellarCore) handleMetaPipeResult(sequence uint32, result metaRe ) } + c.ledgerSequenceLock.Lock() c.nextLedger = result.LedgerSequence() + 1 + c.ledgerSequenceLock.Unlock() + currentLedgerHash := result.LedgerCloseMeta.LedgerHash().HexString() c.previousLedgerHash = ¤tLedgerHash @@ -566,28 +686,29 @@ func (c *CaptiveStellarCore) handleMetaPipeResult(sequence uint32, result metaRe } func (c *CaptiveStellarCore) checkMetaPipeResult(result metaResult, ok bool) error { - // There are 3 types of errors we check for: + // There are 4 error scenarios we check for: // 1. User initiated shutdown by canceling the parent context or calling Close(). - // 2. The stellar core process exited unexpectedly. + // 2. The stellar core process exited unexpectedly with an error message. // 3. Some error was encountered while consuming the ledgers emitted by captive core (e.g. parsing invalid xdr) + // 4. The stellar core process exited unexpectedly without an error message if err := c.stellarCoreRunner.context().Err(); err != nil { // Case 1 - User initiated shutdown by canceling the parent context or calling Close() return err } if !ok || result.err != nil { - if result.err != nil { + exited, err := c.stellarCoreRunner.getProcessExitError() + if exited && err != nil { + // Case 2 - The stellar core process exited unexpectedly with an error message + return errors.Wrap(err, "stellar core exited unexpectedly") + } else if result.err != nil { // Case 3 - Some error was encountered while consuming the ledger stream emitted by captive core. return result.err - } else if exited, err := c.stellarCoreRunner.getProcessExitError(); exited { - // Case 2 - The stellar core process exited unexpectedly - if err == nil { - return errors.Errorf("stellar core exited unexpectedly") - } else { - return errors.Wrap(err, "stellar core exited unexpectedly") - } + } else if exited { + // case 4 - The stellar core process exited unexpectedly without an error message + return errors.Errorf("stellar core exited unexpectedly") } else if !ok { // This case should never happen because the ledger buffer channel can only be closed - // if and only if the process exits or the context is cancelled. + // if and only if the process exits or the context is canceled. // However, we add this check for the sake of completeness return errors.Errorf("meta pipe closed unexpectedly") } @@ -606,6 +727,9 @@ func (c *CaptiveStellarCore) GetLatestLedgerSequence(ctx context.Context) (uint3 c.stellarCoreLock.RLock() defer c.stellarCoreLock.RUnlock() + c.ledgerSequenceLock.RLock() + defer c.ledgerSequenceLock.RUnlock() + if c.closed { return 0, errors.New("stellar-core is no longer usable") } diff --git a/ingest/ledgerbackend/captive_core_backend_test.go b/ingest/ledgerbackend/captive_core_backend_test.go index f0d7d30316..fb2ea4eff4 100644 --- a/ingest/ledgerbackend/captive_core_backend_test.go +++ b/ingest/ledgerbackend/captive_core_backend_test.go @@ -5,6 +5,7 @@ import ( "encoding/hex" "fmt" "os" + "sync" "testing" "github.com/stretchr/testify/assert" @@ -355,13 +356,15 @@ func TestCaptivePrepareRange_ErrGettingRootHAS(t *testing.T) { assert.EqualError(t, err, "error starting prepare range: opening subprocess: error getting latest checkpoint sequence: error getting root HAS: transient error") err = captiveBackend.PrepareRange(ctx, UnboundedRange(100)) - assert.EqualError(t, err, "error starting prepare range: opening subprocess: error getting latest checkpoint sequence: error getting root HAS: transient error") + assert.EqualError(t, err, "error starting prepare range: opening subprocess: error calculating ledger and hash for stellar-core run: error getting latest checkpoint sequence: error getting root HAS: transient error") mockArchive.AssertExpectations(t) } func TestCaptivePrepareRange_FromIsAheadOfRootHAS(t *testing.T) { ctx := context.Background() + mockRunner := &stellarCoreRunnerMock{} + mockArchive := &historyarchive.MockArchive{} mockArchive. On("GetRootHAS"). @@ -371,15 +374,80 @@ func TestCaptivePrepareRange_FromIsAheadOfRootHAS(t *testing.T) { captiveBackend := CaptiveStellarCore{ archive: mockArchive, + stellarCoreRunnerFactory: func() stellarCoreRunnerInterface { + return mockRunner + }, + checkpointManager: historyarchive.NewCheckpointManager(64), } err := captiveBackend.PrepareRange(ctx, BoundedRange(100, 200)) assert.EqualError(t, err, "error starting prepare range: opening subprocess: from sequence: 100 is greater than max available in history archives: 64") - err = captiveBackend.PrepareRange(ctx, UnboundedRange(100)) - assert.EqualError(t, err, "error starting prepare range: opening subprocess: trying to start online mode too far (latest checkpoint=64), only two checkpoints in the future allowed") + err = captiveBackend.PrepareRange(ctx, UnboundedRange(193)) + assert.EqualError(t, err, "error starting prepare range: opening subprocess: error calculating ledger and hash for stellar-core run: trying to start online mode too far (latest checkpoint=64), only two checkpoints in the future allowed") + + mockArchive. + On("GetLedgerHeader", uint32(64)). + Return(xdr.LedgerHeaderHistoryEntry{}, nil) + metaChan := make(chan metaResult, 100) + // Core will actually start with the last checkpoint before the from ledger + // and then rewind to the `from` ledger. + for i := 64; i <= 100; i++ { + meta := buildLedgerCloseMeta(testLedgerHeader{sequence: uint32(i)}) + metaChan <- metaResult{ + LedgerCloseMeta: &meta, + } + } + + mockRunner.On("runFrom", uint32(63), "0000000000000000000000000000000000000000000000000000000000000000").Return(nil).Once() + mockRunner.On("getMetaPipe").Return((<-chan metaResult)(metaChan)) + mockRunner.On("context").Return(ctx) + + assert.NoError(t, captiveBackend.PrepareRange(ctx, UnboundedRange(100))) + + mockArchive.AssertExpectations(t) + mockRunner.AssertExpectations(t) +} + +func TestCaptivePrepareRangeWithDB_FromIsAheadOfRootHAS(t *testing.T) { + ctx := context.Background() + mockRunner := &stellarCoreRunnerMock{} + + mockArchive := &historyarchive.MockArchive{} + mockArchive. + On("GetRootHAS"). + Return(historyarchive.HistoryArchiveState{ + CurrentLedger: uint32(64), + }, nil) + + captiveBackend := CaptiveStellarCore{ + archive: mockArchive, + useDB: true, + stellarCoreRunnerFactory: func() stellarCoreRunnerInterface { + return mockRunner + }, + checkpointManager: historyarchive.NewCheckpointManager(64), + } + + err := captiveBackend.PrepareRange(ctx, BoundedRange(100, 200)) + assert.EqualError(t, err, "error starting prepare range: opening subprocess: from sequence: 100 is greater than max available in history archives: 64") + + err = captiveBackend.PrepareRange(ctx, UnboundedRange(193)) + assert.EqualError(t, err, "error starting prepare range: opening subprocess: error calculating ledger and hash for stellar-core run: trying to start online mode too far (latest checkpoint=64), only two checkpoints in the future allowed") + + metaChan := make(chan metaResult, 100) + meta := buildLedgerCloseMeta(testLedgerHeader{sequence: 100}) + metaChan <- metaResult{ + LedgerCloseMeta: &meta, + } + mockRunner.On("runFrom", uint32(99), "").Return(nil).Once() + mockRunner.On("getMetaPipe").Return((<-chan metaResult)(metaChan)) + mockRunner.On("context").Return(ctx) + + assert.NoError(t, captiveBackend.PrepareRange(ctx, UnboundedRange(100))) mockArchive.AssertExpectations(t) + mockRunner.AssertExpectations(t) } func TestCaptivePrepareRange_ToIsAheadOfRootHAS(t *testing.T) { @@ -443,7 +511,7 @@ func TestCaptivePrepareRange_ErrCatchup(t *testing.T) { func TestCaptivePrepareRangeUnboundedRange_ErrRunFrom(t *testing.T) { mockRunner := &stellarCoreRunnerMock{} - mockRunner.On("runFrom", uint32(127), "0000000000000000000000000000000000000000000000000000000000000000").Return(errors.New("transient error")).Once() + mockRunner.On("runFrom", uint32(126), "0000000000000000000000000000000000000000000000000000000000000000").Return(errors.New("transient error")).Once() mockRunner.On("close").Return(nil).Once() mockArchive := &historyarchive.MockArchive{} @@ -454,7 +522,7 @@ func TestCaptivePrepareRangeUnboundedRange_ErrRunFrom(t *testing.T) { }, nil) mockArchive. - On("GetLedgerHeader", uint32(128)). + On("GetLedgerHeader", uint32(127)). Return(xdr.LedgerHeaderHistoryEntry{}, nil) ctx := context.Background() @@ -578,6 +646,71 @@ func TestGetLatestLedgerSequence(t *testing.T) { mockRunner.AssertExpectations(t) } +func TestGetLatestLedgerSequenceRaceCondition(t *testing.T) { + var fromSeq uint32 = 64 + var toSeq uint32 = 400 + metaChan := make(chan metaResult, toSeq) + + for i := fromSeq; i <= toSeq; i++ { + meta := buildLedgerCloseMeta(testLedgerHeader{sequence: i}) + metaChan <- metaResult{ + LedgerCloseMeta: &meta, + } + } + ctx, cancel := context.WithCancel(context.Background()) + mockRunner := &stellarCoreRunnerMock{} + mockRunner.On("getMetaPipe").Return((<-chan metaResult)(metaChan)) + mockRunner.On("context").Return(ctx) + mockRunner.On("runFrom", mock.Anything, mock.Anything).Return(nil) + + mockArchive := &historyarchive.MockArchive{} + mockArchive. + On("GetRootHAS"). + Return(historyarchive.HistoryArchiveState{ + CurrentLedger: toSeq * 2, + }, nil) + + mockArchive. + On("GetLedgerHeader", mock.Anything). + Return(xdr.LedgerHeaderHistoryEntry{}, nil) + + captiveBackend := CaptiveStellarCore{ + archive: mockArchive, + stellarCoreRunnerFactory: func() stellarCoreRunnerInterface { + return mockRunner + }, + checkpointManager: historyarchive.NewCheckpointManager(10), + } + + ledgerRange := UnboundedRange(fromSeq) + err := captiveBackend.PrepareRange(ctx, ledgerRange) + assert.NoError(t, err) + + var wg sync.WaitGroup + wg.Add(1) + + go func(ctx context.Context) { + defer wg.Done() + for { + select { + case <-ctx.Done(): + return + default: + _, _ = captiveBackend.GetLatestLedgerSequence(ctx) + } + } + }(ctx) + + for i := fromSeq; i < toSeq; i++ { + _, err = captiveBackend.GetLedger(ctx, i) + assert.NoError(t, err) + } + + cancel() + + wg.Wait() +} + func TestCaptiveGetLedger(t *testing.T) { tt := assert.New(t) metaChan := make(chan metaResult, 300) @@ -887,7 +1020,7 @@ func TestCaptiveGetLedger_ErrReadingMetaResult(t *testing.T) { } } metaChan <- metaResult{ - err: fmt.Errorf("unmarshalling error"), + err: fmt.Errorf("unmarshaling error"), } ctx := context.Background() @@ -899,6 +1032,7 @@ func TestCaptiveGetLedger_ErrReadingMetaResult(t *testing.T) { mockRunner.On("close").Return(nil).Run(func(args mock.Arguments) { cancel() }).Once() + mockRunner.On("getProcessExitError").Return(false, nil) // even if the request to fetch the latest checkpoint succeeds, we should fail at creating the subprocess mockArchive := &historyarchive.MockArchive{} @@ -927,7 +1061,7 @@ func TestCaptiveGetLedger_ErrReadingMetaResult(t *testing.T) { // try reading from an empty buffer _, err = captiveBackend.GetLedger(ctx, 66) - tt.EqualError(err, "unmarshalling error") + tt.EqualError(err, "unmarshaling error") // not closed even if there is an error getting ledger tt.False(captiveBackend.closed) @@ -1084,17 +1218,19 @@ func TestGetLedgerBoundsCheck(t *testing.T) { mockRunner.AssertExpectations(t) } -func TestCaptiveGetLedgerTerminatedUnexpectedly(t *testing.T) { +type GetLedgerTerminatedTestCase struct { + name string + ctx context.Context + ledgers []metaResult + processExited bool + processExitedError error + expectedError string +} + +func CaptiveGetLedgerTerminatedUnexpectedlyTestCases() []GetLedgerTerminatedTestCase { ledger64 := buildLedgerCloseMeta(testLedgerHeader{sequence: uint32(64)}) - for _, testCase := range []struct { - name string - ctx context.Context - ledgers []metaResult - processExited bool - processExitedError error - expectedError string - }{ + return []GetLedgerTerminatedTestCase{ { "stellar core exited unexpectedly without error", context.Background(), @@ -1135,7 +1271,29 @@ func TestCaptiveGetLedgerTerminatedUnexpectedly(t *testing.T) { nil, "meta pipe closed unexpectedly", }, - } { + { + "Parser error while reading from the pipe resulting in stellar-core exit", + context.Background(), + []metaResult{{LedgerCloseMeta: &ledger64}, + {LedgerCloseMeta: nil, err: errors.New("Parser error")}}, + true, + nil, + "Parser error", + }, + { + "stellar core exited unexpectedly with an error resulting in meta pipe closed", + context.Background(), + []metaResult{{LedgerCloseMeta: &ledger64}, + {LedgerCloseMeta: &ledger64, err: errors.New("EOF while decoding")}}, + true, + fmt.Errorf("signal kill"), + "stellar core exited unexpectedly: signal kill", + }, + } +} + +func TestCaptiveGetLedgerTerminatedUnexpectedly(t *testing.T) { + for _, testCase := range CaptiveGetLedgerTerminatedUnexpectedlyTestCases() { t.Run(testCase.name, func(t *testing.T) { metaChan := make(chan metaResult, 100) @@ -1194,6 +1352,12 @@ func TestCaptiveUseOfLedgerHashStore(t *testing.T) { }, }, nil) + mockArchive. + On("GetRootHAS"). + Return(historyarchive.HistoryArchiveState{ + CurrentLedger: uint32(4095), + }, nil) + mockLedgerHashStore := &MockLedgerHashStore{} mockLedgerHashStore.On("GetLedgerHash", ctx, uint32(1049)). Return("", false, fmt.Errorf("transient error")).Once() @@ -1284,6 +1448,11 @@ func TestCaptiveRunFromParams(t *testing.T) { PreviousLedgerHash: xdr.Hash{1, 1, 1, 1}, }, }, nil) + mockArchive. + On("GetRootHAS"). + Return(historyarchive.HistoryArchiveState{ + CurrentLedger: uint32(255), + }, nil) captiveBackend := CaptiveStellarCore{ archive: mockArchive, @@ -1362,7 +1531,7 @@ func TestCaptiveIsPrepared(t *testing.T) { } // TestCaptiveIsPreparedCoreContextCancelled checks if IsPrepared returns false -// if the stellarCoreRunner.context() is cancelled. This can happen when +// if the stellarCoreRunner.context() is canceled. This can happen when // stellarCoreRunner was closed, ex. when binary file was updated. func TestCaptiveIsPreparedCoreContextCancelled(t *testing.T) { mockRunner := &stellarCoreRunnerMock{} @@ -1419,7 +1588,7 @@ func TestCaptivePreviousLedgerCheck(t *testing.T) { ctx := context.Background() mockRunner := &stellarCoreRunnerMock{} - mockRunner.On("runFrom", uint32(299), "0101010100000000000000000000000000000000000000000000000000000000").Return(nil).Once() + mockRunner.On("runFrom", uint32(254), "0101010100000000000000000000000000000000000000000000000000000000").Return(nil).Once() mockRunner.On("getMetaPipe").Return((<-chan metaResult)(metaChan)) mockRunner.On("context").Return(ctx) mockRunner.On("close").Return(nil).Once() @@ -1431,7 +1600,7 @@ func TestCaptivePreviousLedgerCheck(t *testing.T) { CurrentLedger: uint32(255), }, nil) mockArchive. - On("GetLedgerHeader", uint32(300)). + On("GetLedgerHeader", uint32(255)). Return(xdr.LedgerHeaderHistoryEntry{ Header: xdr.LedgerHeader{ PreviousLedgerHash: xdr.Hash{1, 1, 1, 1}, diff --git a/ingest/ledgerbackend/hash_order_test.go b/ingest/ledgerbackend/hash_order_test.go index 3de34d8662..537c9d5148 100644 --- a/ingest/ledgerbackend/hash_order_test.go +++ b/ingest/ledgerbackend/hash_order_test.go @@ -1,10 +1,12 @@ package ledgerbackend import ( + "testing" + "github.com/stellar/go/network" "github.com/stellar/go/xdr" "github.com/stretchr/testify/assert" - "testing" + "github.com/stretchr/testify/require" ) func TestHashOrder(t *testing.T) { @@ -40,7 +42,7 @@ func TestHashOrder(t *testing.T) { }, } - sortByHash(original, network.TestNetworkPassphrase) + require.NoError(t, sortByHash(original, network.TestNetworkPassphrase)) hashes := map[int]xdr.Hash{} for i, tx := range original { diff --git a/ingest/ledgerbackend/metrics.go b/ingest/ledgerbackend/metrics.go new file mode 100644 index 0000000000..bebc42d733 --- /dev/null +++ b/ingest/ledgerbackend/metrics.go @@ -0,0 +1,44 @@ +package ledgerbackend + +import ( + "context" + "time" + + "github.com/prometheus/client_golang/prometheus" + + "github.com/stellar/go/xdr" +) + +// WithMetrics decorates the given LedgerBackend with metrics +func WithMetrics(base LedgerBackend, registry *prometheus.Registry, namespace string) LedgerBackend { + if captiveCoreBackend, ok := base.(*CaptiveStellarCore); ok { + captiveCoreBackend.registerMetrics(registry, namespace) + } + summary := prometheus.NewSummary( + prometheus.SummaryOpts{ + Namespace: namespace, Subsystem: "ingest", Name: "ledger_fetch_duration_seconds", + Help: "duration of fetching ledgers from ledger backend, sliding window = 10m", + Objectives: map[float64]float64{0.5: 0.05, 0.9: 0.01, 0.99: 0.001}, + }, + ) + registry.MustRegister(summary) + return metricsLedgerBackend{ + LedgerBackend: base, + ledgerFetchDurationSummary: summary, + } +} + +type metricsLedgerBackend struct { + LedgerBackend + ledgerFetchDurationSummary prometheus.Summary +} + +func (m metricsLedgerBackend) GetLedger(ctx context.Context, sequence uint32) (xdr.LedgerCloseMeta, error) { + startTime := time.Now() + lcm, err := m.LedgerBackend.GetLedger(ctx, sequence) + if err != nil { + return xdr.LedgerCloseMeta{}, err + } + m.ledgerFetchDurationSummary.Observe(time.Since(startTime).Seconds()) + return lcm, nil +} diff --git a/ingest/ledgerbackend/remote_captive_core_test.go b/ingest/ledgerbackend/remote_captive_core_test.go index 3a4b4d28a7..393b981589 100644 --- a/ingest/ledgerbackend/remote_captive_core_test.go +++ b/ingest/ledgerbackend/remote_captive_core_test.go @@ -5,6 +5,7 @@ import ( "encoding/json" "net/http" "net/http/httptest" + "sync/atomic" "testing" "github.com/stretchr/testify/require" @@ -23,11 +24,14 @@ func TestGetLedgerSucceeds(t *testing.T) { }, } called := 0 + var encodeFailed int64 server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { called++ - json.NewEncoder(w).Encode(LedgerResponse{ + if nil != json.NewEncoder(w).Encode(LedgerResponse{ Ledger: Base64Ledger(expectedLedger), - }) + }) { + atomic.AddInt64(&encodeFailed, 1) + } })) defer server.Close() @@ -38,6 +42,7 @@ func TestGetLedgerSucceeds(t *testing.T) { require.NoError(t, err) require.Equal(t, 1, called) require.Equal(t, expectedLedger, ledger) + require.Equal(t, int64(0), atomic.LoadInt64(&encodeFailed)) } func TestGetLedgerTakesAWhile(t *testing.T) { @@ -51,6 +56,7 @@ func TestGetLedgerTakesAWhile(t *testing.T) { }, } called := 0 + var encodeFailed int64 server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { called++ if called == 1 { @@ -58,9 +64,11 @@ func TestGetLedgerTakesAWhile(t *testing.T) { w.WriteHeader(http.StatusRequestTimeout) return } - json.NewEncoder(w).Encode(LedgerResponse{ + if nil != json.NewEncoder(w).Encode(LedgerResponse{ Ledger: Base64Ledger(expectedLedger), - }) + }) { + atomic.AddInt64(&encodeFailed, 1) + } })) defer server.Close() @@ -71,4 +79,5 @@ func TestGetLedgerTakesAWhile(t *testing.T) { require.NoError(t, err) require.Equal(t, 2, called) require.Equal(t, expectedLedger, ledger) + require.Equal(t, int64(0), atomic.LoadInt64(&encodeFailed)) } diff --git a/ingest/ledgerbackend/stellar_core_runner.go b/ingest/ledgerbackend/stellar_core_runner.go index e083444578..1c2c09c4a6 100644 --- a/ingest/ledgerbackend/stellar_core_runner.go +++ b/ingest/ledgerbackend/stellar_core_runner.go @@ -373,7 +373,7 @@ func (r *stellarCoreRunner) runFrom(from uint32, hash string) error { if err != nil { r.log.Infof("Error running offline-info: %v, removing existing storage-dir contents", err) removeStorageDir = true - } else if uint32(info.Info.Ledger.Num) != from { + } else if uint32(info.Info.Ledger.Num) > from { r.log.Infof("Unexpected LCL in Stellar-Core DB: %d (want: %d), removing existing storage-dir contents", info.Info.Ledger.Num, from) removeStorageDir = true } diff --git a/ingest/ledgerbackend/stellar_core_runner_test.go b/ingest/ledgerbackend/stellar_core_runner_test.go index e0ea580e3d..60871922b7 100644 --- a/ingest/ledgerbackend/stellar_core_runner_test.go +++ b/ingest/ledgerbackend/stellar_core_runner_test.go @@ -203,7 +203,7 @@ func TestRunFromUseDBLedgersMatch(t *testing.T) { assert.NoError(t, runner.close()) } -func TestRunFromUseDBLedgersNotMatch(t *testing.T) { +func TestRunFromUseDBLedgersBehind(t *testing.T) { captiveCoreToml, err := NewCaptiveCoreToml(CaptiveCoreTomlParams{}) assert.NoError(t, err) @@ -230,7 +230,67 @@ func TestRunFromUseDBLedgersNotMatch(t *testing.T) { offlineInfoCmdMock := simpleCommandMock() infoResponse := stellarcore.InfoResponse{} - infoResponse.Info.Ledger.Num = 101 // runner is one ledger behind + infoResponse.Info.Ledger.Num = 90 // runner is 10 ledgers behind + infoResponseBytes, err := json.Marshal(infoResponse) + assert.NoError(t, err) + offlineInfoCmdMock.On("Output").Return(infoResponseBytes, nil) + offlineInfoCmdMock.On("Wait").Return(nil) + + // Replace system calls with a mock + scMock := &mockSystemCaller{} + defer scMock.AssertExpectations(t) + // Storage dir is not removed because ledgers do not match + scMock.On("stat", mock.Anything).Return(isDirImpl(true), nil) + scMock.On("writeFile", mock.Anything, mock.Anything, mock.Anything).Return(nil) + scMock.On("command", + "/usr/bin/stellar-core", + "--conf", + mock.Anything, + "offline-info", + ).Return(offlineInfoCmdMock) + scMock.On("command", + "/usr/bin/stellar-core", + "--conf", + mock.Anything, + "--console", + "run", + "--metadata-output-stream", + "fd:3", + ).Return(cmdMock) + runner.systemCaller = scMock + + assert.NoError(t, runner.runFrom(100, "hash")) + assert.NoError(t, runner.close()) +} + +func TestRunFromUseDBLedgersInFront(t *testing.T) { + captiveCoreToml, err := NewCaptiveCoreToml(CaptiveCoreTomlParams{}) + assert.NoError(t, err) + + captiveCoreToml.AddExamplePubnetValidators() + + runner := newStellarCoreRunner(CaptiveCoreConfig{ + BinaryPath: "/usr/bin/stellar-core", + HistoryArchiveURLs: []string{"http://localhost"}, + Log: log.New(), + Context: context.Background(), + Toml: captiveCoreToml, + StoragePath: "/tmp/captive-core", + UseDB: true, + }) + + newDBCmdMock := simpleCommandMock() + newDBCmdMock.On("Run").Return(nil) + + catchupCmdMock := simpleCommandMock() + catchupCmdMock.On("Run").Return(nil) + + cmdMock := simpleCommandMock() + cmdMock.On("Wait").Return(nil) + + offlineInfoCmdMock := simpleCommandMock() + infoResponse := stellarcore.InfoResponse{} + infoResponse.Info.Ledger.Num = 110 // runner is 10 ledgers in front infoResponseBytes, err := json.Marshal(infoResponse) assert.NoError(t, err) offlineInfoCmdMock.On("Output").Return(infoResponseBytes, nil) diff --git a/ingest/ledgerbackend/stellar_core_runner_windows.go b/ingest/ledgerbackend/stellar_core_runner_windows.go index f942a44971..47368a55b6 100644 --- a/ingest/ledgerbackend/stellar_core_runner_windows.go +++ b/ingest/ledgerbackend/stellar_core_runner_windows.go @@ -5,7 +5,6 @@ package ledgerbackend import ( "fmt" - "os/exec" "github.com/Microsoft/go-winio" ) @@ -16,7 +15,7 @@ func (c *stellarCoreRunner) getPipeName() string { return fmt.Sprintf(`\\.\pipe\%s`, c.nonce) } -func (c *stellarCoreRunner) start(cmd cmd) (pipe, error) { +func (c *stellarCoreRunner) start(cmd cmdI) (pipe, error) { // First set up the server pipe. listener, err := winio.ListenPipe(c.getPipeName(), nil) if err != nil { diff --git a/ingest/ledgerbackend/testdata/appendix-disable-diagnostic-events.cfg b/ingest/ledgerbackend/testdata/appendix-disable-diagnostic-events.cfg new file mode 100644 index 0000000000..9fcb0f804b --- /dev/null +++ b/ingest/ledgerbackend/testdata/appendix-disable-diagnostic-events.cfg @@ -0,0 +1 @@ +ENABLE_SOROBAN_DIAGNOSTIC_EVENTS=false diff --git a/ingest/ledgerbackend/testdata/appendix-with-minimum-persistent-entry.cfg b/ingest/ledgerbackend/testdata/appendix-with-minimum-persistent-entry.cfg new file mode 100644 index 0000000000..3a8eade51d --- /dev/null +++ b/ingest/ledgerbackend/testdata/appendix-with-minimum-persistent-entry.cfg @@ -0,0 +1,11 @@ +TESTING_MINIMUM_PERSISTENT_ENTRY_LIFETIME=16 + +[[HOME_DOMAINS]] +HOME_DOMAIN="testnet.stellar.org" +QUALITY="MEDIUM" + +[[VALIDATORS]] +NAME="sdf_testnet_1" +HOME_DOMAIN="testnet.stellar.org" +PUBLIC_KEY="GDKXE2OZMJIPOSLNA6N6F2BVCI3O777I2OOC4BV7VOYUEHYX7RTRYA7Y" +ADDRESS="localhost:123" diff --git a/ingest/ledgerbackend/testdata/expected-offline-enforce-diagnostic-events.cfg b/ingest/ledgerbackend/testdata/expected-offline-enforce-diagnostic-events.cfg new file mode 100644 index 0000000000..48b6223377 --- /dev/null +++ b/ingest/ledgerbackend/testdata/expected-offline-enforce-diagnostic-events.cfg @@ -0,0 +1,15 @@ +# Generated file, do not edit +ENABLE_SOROBAN_DIAGNOSTIC_EVENTS = true +FAILURE_SAFETY = 0 +HTTP_PORT = 0 +LOG_FILE_PATH = "" +NETWORK_PASSPHRASE = "Public Global Stellar Network ; September 2015" +RUN_STANDALONE = true +UNSAFE_QUORUM = true + +[HISTORY.h0] + get = "curl -sf http://localhost:1170/{0} -o {1}" + +[QUORUM_SET] + THRESHOLD_PERCENT = 100 + VALIDATORS = ["GCZBOIAY4HLKAJVNJORXZOZRAY2BJDBZHKPBHZCRAIUR5IHC2UHBGCQR"] diff --git a/ingest/ledgerbackend/testdata/expected-offline-enforce-disabled-diagnostic-events.cfg b/ingest/ledgerbackend/testdata/expected-offline-enforce-disabled-diagnostic-events.cfg new file mode 100644 index 0000000000..df307a3a00 --- /dev/null +++ b/ingest/ledgerbackend/testdata/expected-offline-enforce-disabled-diagnostic-events.cfg @@ -0,0 +1,14 @@ +# Generated file, do not edit +FAILURE_SAFETY = 0 +HTTP_PORT = 0 +LOG_FILE_PATH = "" +NETWORK_PASSPHRASE = "Public Global Stellar Network ; September 2015" +RUN_STANDALONE = true +UNSAFE_QUORUM = true + +[HISTORY.h0] + get = "curl -sf http://localhost:1170/{0} -o {1}" + +[QUORUM_SET] + THRESHOLD_PERCENT = 100 + VALIDATORS = ["GCZBOIAY4HLKAJVNJORXZOZRAY2BJDBZHKPBHZCRAIUR5IHC2UHBGCQR"] diff --git a/ingest/ledgerbackend/testdata/expected-online-with-appendix-minimum-persistent-entry.cfg b/ingest/ledgerbackend/testdata/expected-online-with-appendix-minimum-persistent-entry.cfg new file mode 100644 index 0000000000..278c681595 --- /dev/null +++ b/ingest/ledgerbackend/testdata/expected-online-with-appendix-minimum-persistent-entry.cfg @@ -0,0 +1,19 @@ +# Generated file, do not edit +FAILURE_SAFETY = -1 +HTTP_PORT = 11626 +LOG_FILE_PATH = "" +NETWORK_PASSPHRASE = "Public Global Stellar Network ; September 2015" +TESTING_MINIMUM_PERSISTENT_ENTRY_LIFETIME = 16 + +[[HOME_DOMAINS]] + HOME_DOMAIN = "testnet.stellar.org" + QUALITY = "MEDIUM" + +[[VALIDATORS]] + ADDRESS = "localhost:123" + HOME_DOMAIN = "testnet.stellar.org" + NAME = "sdf_testnet_1" + PUBLIC_KEY = "GDKXE2OZMJIPOSLNA6N6F2BVCI3O777I2OOC4BV7VOYUEHYX7RTRYA7Y" + +[HISTORY.h0] + get = "curl -sf http://localhost:1170/{0} -o {1}" diff --git a/ingest/ledgerbackend/testdata/expected-online-with-no-http-port-diag-events.cfg b/ingest/ledgerbackend/testdata/expected-online-with-no-http-port-diag-events.cfg new file mode 100644 index 0000000000..fa785894e5 --- /dev/null +++ b/ingest/ledgerbackend/testdata/expected-online-with-no-http-port-diag-events.cfg @@ -0,0 +1,20 @@ +# Generated file, do not edit +ENABLE_SOROBAN_DIAGNOSTIC_EVENTS = true +FAILURE_SAFETY = -1 +HTTP_PORT = 11626 +LOG_FILE_PATH = "" +NETWORK_PASSPHRASE = "Public Global Stellar Network ; September 2015" +PEER_PORT = 12345 + +[[HOME_DOMAINS]] + HOME_DOMAIN = "testnet.stellar.org" + QUALITY = "MEDIUM" + +[[VALIDATORS]] + ADDRESS = "localhost:123" + HOME_DOMAIN = "testnet.stellar.org" + NAME = "sdf_testnet_1" + PUBLIC_KEY = "GDKXE2OZMJIPOSLNA6N6F2BVCI3O777I2OOC4BV7VOYUEHYX7RTRYA7Y" + +[HISTORY.h0] + get = "curl -sf http://localhost:1170/{0} -o {1}" diff --git a/ingest/ledgerbackend/toml.go b/ingest/ledgerbackend/toml.go index 3f34660af3..7c42bc11c8 100644 --- a/ingest/ledgerbackend/toml.go +++ b/ingest/ledgerbackend/toml.go @@ -3,8 +3,10 @@ package ledgerbackend import ( "bytes" "fmt" - "io/ioutil" + "os" + "os/exec" "regexp" + "strconv" "strings" "github.com/stellar/go/support/errors" @@ -75,14 +77,23 @@ type captiveCoreTomlValues struct { PeerPort uint `toml:"PEER_PORT,omitempty"` // we cannot omitempty because 0 is a valid configuration for FAILURE_SAFETY // and the default is -1 - FailureSafety int `toml:"FAILURE_SAFETY"` - UnsafeQuorum bool `toml:"UNSAFE_QUORUM,omitempty"` - RunStandalone bool `toml:"RUN_STANDALONE,omitempty"` - ArtificiallyAccelerateTimeForTesting bool `toml:"ARTIFICIALLY_ACCELERATE_TIME_FOR_TESTING,omitempty"` - HomeDomains []HomeDomain `toml:"HOME_DOMAINS,omitempty"` - Validators []Validator `toml:"VALIDATORS,omitempty"` - HistoryEntries map[string]History `toml:"-"` - QuorumSetEntries map[string]QuorumSet `toml:"-"` + FailureSafety int `toml:"FAILURE_SAFETY"` + UnsafeQuorum bool `toml:"UNSAFE_QUORUM,omitempty"` + RunStandalone bool `toml:"RUN_STANDALONE,omitempty"` + ArtificiallyAccelerateTimeForTesting bool `toml:"ARTIFICIALLY_ACCELERATE_TIME_FOR_TESTING,omitempty"` + PreferredPeers []string `toml:"PREFERRED_PEERS,omitempty"` + PreferredPeerKeys []string `toml:"PREFERRED_PEER_KEYS,omitempty"` + PreferredPeersOnly bool `toml:"PREFERRED_PEERS_ONLY,omitempty"` + HomeDomains []HomeDomain `toml:"HOME_DOMAINS,omitempty"` + Validators []Validator `toml:"VALIDATORS,omitempty"` + HistoryEntries map[string]History `toml:"-"` + QuorumSetEntries map[string]QuorumSet `toml:"-"` + UseBucketListDB bool `toml:"EXPERIMENTAL_BUCKETLIST_DB,omitempty"` + BucketListDBPageSizeExp *uint `toml:"EXPERIMENTAL_BUCKETLIST_DB_INDEX_PAGE_SIZE_EXPONENT,omitempty"` + BucketListDBCutoff *uint `toml:"EXPERIMENTAL_BUCKETLIST_DB_INDEX_CUTOFF,omitempty"` + EnableSorobanDiagnosticEvents *bool `toml:"ENABLE_SOROBAN_DIAGNOSTIC_EVENTS,omitempty"` + TestingMinimumPersistentEntryLifetime *uint `toml:"TESTING_MINIMUM_PERSISTENT_ENTRY_LIFETIME,omitempty"` + TestingSorobanHighLimitOverride *bool `toml:"TESTING_SOROBAN_HIGH_LIMIT_OVERRIDE,omitempty"` } // QuorumSetIsConfigured returns true if there is a quorum set defined in the configuration. @@ -317,34 +328,43 @@ type CaptiveCoreTomlParams struct { Strict bool // If true, specifies that captive core should be invoked with on-disk rather than in-memory option for ledger state UseDB bool + // the path to the core binary, used to introspect core at runtime, determine some toml capabilities + CoreBinaryPath string + // Enforce EnableSorobanDiagnosticEvents when not disabled explicitly + EnforceSorobanDiagnosticEvents bool } // NewCaptiveCoreTomlFromFile constructs a new CaptiveCoreToml instance by merging configuration // from the toml file located at `configPath` and the configuration provided by `params`. func NewCaptiveCoreTomlFromFile(configPath string, params CaptiveCoreTomlParams) (*CaptiveCoreToml, error) { - var captiveCoreToml CaptiveCoreToml - data, err := ioutil.ReadFile(configPath) + data, err := os.ReadFile(configPath) if err != nil { return nil, errors.Wrap(err, "could not load toml path") } + return NewCaptiveCoreTomlFromData(data, params) +} + +// NewCaptiveCoreTomlFromData constructs a new CaptiveCoreToml instance by merging configuration +// from the toml data and the configuration provided by `params`. +func NewCaptiveCoreTomlFromData(data []byte, params CaptiveCoreTomlParams) (*CaptiveCoreToml, error) { + var captiveCoreToml CaptiveCoreToml - if err = captiveCoreToml.unmarshal(data, params.Strict); err != nil { + if err := captiveCoreToml.unmarshal(data, params.Strict); err != nil { return nil, errors.Wrap(err, "could not unmarshal captive core toml") } // disallow setting BUCKET_DIR_PATH through a file since it can cause multiple // running captive-core instances to clash if params.Strict && captiveCoreToml.BucketDirPath != "" { - return nil, errors.New("could not unmarshal captive core toml: setting BUCKET_DIR_PATH is disallowed, it can cause clashes between instances") + return nil, errors.New("could not unmarshal captive core toml: setting BUCKET_DIR_PATH is disallowed for Captive Core, use CAPTIVE_CORE_STORAGE_PATH instead") } - if err = captiveCoreToml.validate(params); err != nil { + if err := captiveCoreToml.validate(params); err != nil { return nil, errors.Wrap(err, "invalid captive core toml") } if len(captiveCoreToml.HistoryEntries) > 0 { log.Warnf( - "Configuring captive core with history archive from %s instead of %v", - configPath, + "Configuring captive core with history archive from %s", params.HistoryArchiveURLs, ) } @@ -409,12 +429,107 @@ func (c *CaptiveCoreToml) CatchupToml() (*CaptiveCoreToml, error) { return offline, nil } -func (c *CaptiveCoreToml) setDefaults(params CaptiveCoreTomlParams) { +// coreVersion helper struct identify a core version and provides the +// utilities to compare the version ( i.e. minor + major pair ) to a predefined +// version. +type coreVersion struct { + major int + minor int + ledgerProtocolVersion int +} + +// IsEqualOrAbove compares the core version to a version specific. If unable +// to make the decision, the result is always "false", leaning toward the +// common denominator. +func (c *coreVersion) IsEqualOrAbove(major, minor int) bool { + if c.major == 0 && c.minor == 0 { + return false + } + return (c.major == major && c.minor >= minor) || (c.major > major) +} + +// IsEqualOrAbove compares the core version to a version specific. If unable +// to make the decision, the result is always "false", leaning toward the +// common denominator. +func (c *coreVersion) IsProtocolVersionEqualOrAbove(protocolVer int) bool { + if c.ledgerProtocolVersion == 0 { + return false + } + return c.ledgerProtocolVersion >= protocolVer +} + +func (c *CaptiveCoreToml) checkCoreVersion(coreBinaryPath string) coreVersion { + if coreBinaryPath == "" { + return coreVersion{} + } + + versionBytes, err := exec.Command(coreBinaryPath, "version").Output() + if err != nil { + return coreVersion{} + } + + // starting soroban, we want to use only the first row for the version. + versionRows := strings.Split(string(versionBytes), "\n") + versionRaw := versionRows[0] + + var version [2]int + + re := regexp.MustCompile(`\D*(\d*)\.(\d*).*`) + versionStr := re.FindStringSubmatch(versionRaw) + if err == nil && len(versionStr) == 3 { + for i := 1; i < len(versionStr); i++ { + val, err := strconv.Atoi((versionStr[i])) + if err != nil { + break + } + version[i-1] = val + } + } + re = regexp.MustCompile(`^\s*ledger protocol version: (\d*)`) + var ledgerProtocol int + var ledgerProtocolStrings []string + for _, line := range versionRows { + ledgerProtocolStrings = re.FindStringSubmatch(line) + if len(ledgerProtocolStrings) > 0 { + break + } + } + if len(ledgerProtocolStrings) == 2 { + if val, err := strconv.Atoi(ledgerProtocolStrings[1]); err == nil { + ledgerProtocol = val + } + } + + return coreVersion{ + major: version[0], + minor: version[1], + ledgerProtocolVersion: ledgerProtocol, + } +} + +const MinimalBucketListDBCoreSupportVersionMajor = 19 +const MinimalBucketListDBCoreSupportVersionMinor = 6 +const MinimalSorobanProtocolSupport = 20 + +func (c *CaptiveCoreToml) setDefaults(params CaptiveCoreTomlParams) { if params.UseDB && !c.tree.Has("DATABASE") { c.Database = "sqlite3://stellar.db" } + coreVersion := c.checkCoreVersion(params.CoreBinaryPath) + if def := c.tree.Has("EXPERIMENTAL_BUCKETLIST_DB"); !def && params.UseDB { + // Supports version 19.6 and above + if coreVersion.IsEqualOrAbove(MinimalBucketListDBCoreSupportVersionMajor, MinimalBucketListDBCoreSupportVersionMinor) { + c.UseBucketListDB = true + } + } + + if c.UseBucketListDB && !c.tree.Has("EXPERIMENTAL_BUCKETLIST_DB_INDEX_PAGE_SIZE_EXPONENT") { + n := uint(12) + c.BucketListDBPageSizeExp = &n // Set default page size to 4KB + } + if !c.tree.Has("NETWORK_PASSPHRASE") { c.NetworkPassphrase = params.NetworkPassphrase } @@ -447,6 +562,20 @@ func (c *CaptiveCoreToml) setDefaults(params CaptiveCoreTomlParams) { } } } + + // starting version 20, we have dignostics events. + if params.EnforceSorobanDiagnosticEvents && coreVersion.IsProtocolVersionEqualOrAbove(MinimalSorobanProtocolSupport) { + if c.EnableSorobanDiagnosticEvents == nil { + // We are generating the file from scratch or the user didn't explicitly oppose to diagnostic events in the config file. + // Enforce it. + t := true + c.EnableSorobanDiagnosticEvents = &t + } + if !*c.EnableSorobanDiagnosticEvents { + // The user opposed to diagnostic events in the config file, but there is no need to pass on the option + c.EnableSorobanDiagnosticEvents = nil + } + } } func (c *CaptiveCoreToml) validate(params CaptiveCoreTomlParams) error { @@ -482,6 +611,12 @@ func (c *CaptiveCoreToml) validate(params CaptiveCoreTomlParams) error { ) } + if def := c.tree.Has("EXPERIMENTAL_BUCKETLIST_DB"); def && !params.UseDB { + return fmt.Errorf( + "BucketListDB enabled in captive core config file, requires Horizon flag --captive-core-use-db", + ) + } + homeDomainSet := map[string]HomeDomain{} for _, hd := range c.HomeDomains { if _, ok := homeDomainSet[hd.HomeDomain]; ok { diff --git a/ingest/ledgerbackend/toml_test.go b/ingest/ledgerbackend/toml_test.go index 35a52d67dd..476a2ea953 100644 --- a/ingest/ledgerbackend/toml_test.go +++ b/ingest/ledgerbackend/toml_test.go @@ -2,10 +2,13 @@ package ledgerbackend import ( "io/ioutil" + "os" "path/filepath" + "strconv" "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func newUint(v uint) *uint { @@ -198,7 +201,7 @@ func TestCaptiveCoreTomlValidation(t *testing.T) { { name: "unexpected BUCKET_DIR_PATH", appendPath: filepath.Join("testdata", "appendix-with-bucket-dir-path.cfg"), - expectedError: "could not unmarshal captive core toml: setting BUCKET_DIR_PATH is disallowed, it can cause clashes between instances", + expectedError: "could not unmarshal captive core toml: setting BUCKET_DIR_PATH is disallowed for Captive Core, use CAPTIVE_CORE_STORAGE_PATH instead", }, } { t.Run(testCase.name, func(t *testing.T) { @@ -216,16 +219,29 @@ func TestCaptiveCoreTomlValidation(t *testing.T) { } } +func checkTestingAboveProtocol19() bool { + str := os.Getenv("HORIZON_INTEGRATION_TESTS_CORE_MAX_SUPPORTED_PROTOCOL") + if str == "" { + return false + } + version, err := strconv.ParseUint(str, 10, 32) + if err != nil { + return false + } + return uint32(version) > 19 +} + func TestGenerateConfig(t *testing.T) { - for _, testCase := range []struct { - name string - appendPath string - mode stellarCoreRunnerMode - expectedPath string - httpPort *uint - peerPort *uint - logPath *string - useDB bool + testCases := []struct { + name string + appendPath string + mode stellarCoreRunnerMode + expectedPath string + httpPort *uint + peerPort *uint + logPath *string + useDB bool + enforceSorobanDiagnosticEvents bool }{ { name: "offline config with no appendix", @@ -299,19 +315,67 @@ func TestGenerateConfig(t *testing.T) { httpPort: newUint(6789), peerPort: newUint(12345), logPath: nil, - }, - } { + }} + if checkTestingAboveProtocol19() { + testCases = append(testCases, []struct { + name string + appendPath string + mode stellarCoreRunnerMode + expectedPath string + httpPort *uint + peerPort *uint + logPath *string + useDB bool + enforceSorobanDiagnosticEvents bool + }{ + { + name: "offline config with enforce diagnostic events", + mode: stellarCoreRunnerModeOffline, + expectedPath: filepath.Join("testdata", "expected-offline-enforce-diagnostic-events.cfg"), + logPath: nil, + enforceSorobanDiagnosticEvents: true, + }, + { + name: "offline config disabling enforced diagnostic events", + mode: stellarCoreRunnerModeOffline, + expectedPath: filepath.Join("testdata", "expected-offline-enforce-disabled-diagnostic-events.cfg"), + appendPath: filepath.Join("testdata", "appendix-disable-diagnostic-events.cfg"), + logPath: nil, + enforceSorobanDiagnosticEvents: true, + }, + { + name: "online config with enforce diagnostic events", + mode: stellarCoreRunnerModeOnline, + appendPath: filepath.Join("testdata", "sample-appendix.cfg"), + expectedPath: filepath.Join("testdata", "expected-online-with-no-http-port-diag-events.cfg"), + httpPort: nil, + peerPort: newUint(12345), + logPath: nil, + enforceSorobanDiagnosticEvents: true, + }, + { + name: "offline config with minimum persistent entry in appendix", + mode: stellarCoreRunnerModeOnline, + appendPath: filepath.Join("testdata", "appendix-with-minimum-persistent-entry.cfg"), + expectedPath: filepath.Join("testdata", "expected-online-with-appendix-minimum-persistent-entry.cfg"), + logPath: nil, + }, + }...) + } + + for _, testCase := range testCases { t.Run(testCase.name, func(t *testing.T) { var err error var captiveCoreToml *CaptiveCoreToml params := CaptiveCoreTomlParams{ - NetworkPassphrase: "Public Global Stellar Network ; September 2015", - HistoryArchiveURLs: []string{"http://localhost:1170"}, - HTTPPort: testCase.httpPort, - PeerPort: testCase.peerPort, - LogPath: testCase.logPath, - Strict: false, - UseDB: testCase.useDB, + NetworkPassphrase: "Public Global Stellar Network ; September 2015", + HistoryArchiveURLs: []string{"http://localhost:1170"}, + HTTPPort: testCase.httpPort, + PeerPort: testCase.peerPort, + LogPath: testCase.logPath, + Strict: false, + UseDB: testCase.useDB, + EnforceSorobanDiagnosticEvents: testCase.enforceSorobanDiagnosticEvents, } if testCase.appendPath != "" { captiveCoreToml, err = NewCaptiveCoreTomlFromFile(testCase.appendPath, params) @@ -355,7 +419,7 @@ func TestExternalStorageConfigUsesDatabaseToml(t *testing.T) { assert.NoError(t, err) toml := CaptiveCoreToml{} - toml.unmarshal(configBytes, true) + require.NoError(t, toml.unmarshal(configBytes, true)) assert.Equal(t, toml.Database, "sqlite3:///etc/defaults/stellar.db") } @@ -383,7 +447,7 @@ func TestDBConfigDefaultsToSqlite(t *testing.T) { assert.NoError(t, err) toml := CaptiveCoreToml{} - toml.unmarshal(configBytes, true) + require.NoError(t, toml.unmarshal(configBytes, true)) assert.Equal(t, toml.Database, "sqlite3://stellar.db") } @@ -411,6 +475,17 @@ func TestNonDBConfigDoesNotUpdateDatabase(t *testing.T) { assert.NoError(t, err) toml := CaptiveCoreToml{} - toml.unmarshal(configBytes, true) + require.NoError(t, toml.unmarshal(configBytes, true)) assert.Equal(t, toml.Database, "") } + +func TestCheckCoreVersion(t *testing.T) { + coreBin := os.Getenv("HORIZON_INTEGRATION_TESTS_CAPTIVE_CORE_BIN") + if coreBin == "" { + t.SkipNow() + return + } + var cctoml CaptiveCoreToml + version := cctoml.checkCoreVersion(coreBin) + require.True(t, version.IsEqualOrAbove(19, 0)) +} diff --git a/ingest/stats_change_processor.go b/ingest/stats_change_processor.go index d342bc91d5..43a82011cb 100644 --- a/ingest/stats_change_processor.go +++ b/ingest/stats_change_processor.go @@ -2,6 +2,7 @@ package ingest import ( "context" + "fmt" "github.com/stellar/go/xdr" ) @@ -37,6 +38,22 @@ type StatsChangeProcessorResults struct { LiquidityPoolsCreated int64 LiquidityPoolsUpdated int64 LiquidityPoolsRemoved int64 + + ContractDataCreated int64 + ContractDataUpdated int64 + ContractDataRemoved int64 + + ContractCodeCreated int64 + ContractCodeUpdated int64 + ContractCodeRemoved int64 + + ConfigSettingsCreated int64 + ConfigSettingsUpdated int64 + ConfigSettingsRemoved int64 + + TtlCreated int64 + TtlUpdated int64 + TtlRemoved int64 } func (p *StatsChangeProcessor) ProcessChange(ctx context.Context, change Change) error { @@ -95,6 +112,44 @@ func (p *StatsChangeProcessor) ProcessChange(ctx context.Context, change Change) case xdr.LedgerEntryChangeTypeLedgerEntryRemoved: p.results.LiquidityPoolsRemoved++ } + case xdr.LedgerEntryTypeContractData: + switch change.LedgerEntryChangeType() { + case xdr.LedgerEntryChangeTypeLedgerEntryCreated: + p.results.ContractDataCreated++ + case xdr.LedgerEntryChangeTypeLedgerEntryUpdated: + p.results.ContractDataUpdated++ + case xdr.LedgerEntryChangeTypeLedgerEntryRemoved: + p.results.ContractDataRemoved++ + } + case xdr.LedgerEntryTypeContractCode: + switch change.LedgerEntryChangeType() { + case xdr.LedgerEntryChangeTypeLedgerEntryCreated: + p.results.ContractCodeCreated++ + case xdr.LedgerEntryChangeTypeLedgerEntryUpdated: + p.results.ContractCodeUpdated++ + case xdr.LedgerEntryChangeTypeLedgerEntryRemoved: + p.results.ContractCodeRemoved++ + } + case xdr.LedgerEntryTypeConfigSetting: + switch change.LedgerEntryChangeType() { + case xdr.LedgerEntryChangeTypeLedgerEntryCreated: + p.results.ConfigSettingsCreated++ + case xdr.LedgerEntryChangeTypeLedgerEntryUpdated: + p.results.ConfigSettingsUpdated++ + case xdr.LedgerEntryChangeTypeLedgerEntryRemoved: + p.results.ConfigSettingsRemoved++ + } + case xdr.LedgerEntryTypeTtl: + switch change.LedgerEntryChangeType() { + case xdr.LedgerEntryChangeTypeLedgerEntryCreated: + p.results.TtlCreated++ + case xdr.LedgerEntryChangeTypeLedgerEntryUpdated: + p.results.TtlUpdated++ + case xdr.LedgerEntryChangeTypeLedgerEntryRemoved: + p.results.TtlRemoved++ + } + default: + return fmt.Errorf("unsupported ledger entry type: %s", change.Type.String()) } return nil @@ -129,5 +184,21 @@ func (stats *StatsChangeProcessorResults) Map() map[string]interface{} { "stats_liquidity_pools_created": stats.LiquidityPoolsCreated, "stats_liquidity_pools_updated": stats.LiquidityPoolsUpdated, "stats_liquidity_pools_removed": stats.LiquidityPoolsRemoved, + + "stats_contract_data_created": stats.ContractDataCreated, + "stats_contract_data_updated": stats.ContractDataUpdated, + "stats_contract_data_removed": stats.ContractDataRemoved, + + "stats_contract_code_created": stats.ContractCodeCreated, + "stats_contract_code_updated": stats.ContractCodeUpdated, + "stats_contract_code_removed": stats.ContractCodeRemoved, + + "stats_config_settings_created": stats.ConfigSettingsCreated, + "stats_config_settings_updated": stats.ConfigSettingsUpdated, + "stats_config_settings_removed": stats.ConfigSettingsRemoved, + + "stats_ttl_created": stats.TtlCreated, + "stats_ttl_updated": stats.TtlUpdated, + "stats_ttl_removed": stats.TtlRemoved, } } diff --git a/ingest/stats_change_processor_test.go b/ingest/stats_change_processor_test.go index 5eb3bacd52..95cb6f1a85 100644 --- a/ingest/stats_change_processor_test.go +++ b/ingest/stats_change_processor_test.go @@ -4,124 +4,35 @@ import ( "context" "testing" - "github.com/stellar/go/xdr" "github.com/stretchr/testify/assert" + + "github.com/stellar/go/xdr" ) func TestStatsChangeProcessor(t *testing.T) { ctx := context.Background() processor := &StatsChangeProcessor{} - // Created - assert.NoError(t, processor.ProcessChange(ctx, Change{ - Type: xdr.LedgerEntryTypeAccount, - Pre: nil, - Post: &xdr.LedgerEntry{}, - })) - - assert.NoError(t, processor.ProcessChange(ctx, Change{ - Type: xdr.LedgerEntryTypeClaimableBalance, - Pre: nil, - Post: &xdr.LedgerEntry{}, - })) - - assert.NoError(t, processor.ProcessChange(ctx, Change{ - Type: xdr.LedgerEntryTypeData, - Pre: nil, - Post: &xdr.LedgerEntry{}, - })) - - assert.NoError(t, processor.ProcessChange(ctx, Change{ - Type: xdr.LedgerEntryTypeOffer, - Pre: nil, - Post: &xdr.LedgerEntry{}, - })) - - assert.NoError(t, processor.ProcessChange(ctx, Change{ - Type: xdr.LedgerEntryTypeTrustline, - Pre: nil, - Post: &xdr.LedgerEntry{}, - })) - - assert.NoError(t, processor.ProcessChange(ctx, Change{ - Type: xdr.LedgerEntryTypeLiquidityPool, - Pre: nil, - Post: &xdr.LedgerEntry{}, - })) - - // Updated - assert.NoError(t, processor.ProcessChange(ctx, Change{ - Type: xdr.LedgerEntryTypeAccount, - Pre: &xdr.LedgerEntry{}, - Post: &xdr.LedgerEntry{}, - })) - - assert.NoError(t, processor.ProcessChange(ctx, Change{ - Type: xdr.LedgerEntryTypeClaimableBalance, - Pre: &xdr.LedgerEntry{}, - Post: &xdr.LedgerEntry{}, - })) - - assert.NoError(t, processor.ProcessChange(ctx, Change{ - Type: xdr.LedgerEntryTypeData, - Pre: &xdr.LedgerEntry{}, - Post: &xdr.LedgerEntry{}, - })) - - assert.NoError(t, processor.ProcessChange(ctx, Change{ - Type: xdr.LedgerEntryTypeOffer, - Pre: &xdr.LedgerEntry{}, - Post: &xdr.LedgerEntry{}, - })) - - assert.NoError(t, processor.ProcessChange(ctx, Change{ - Type: xdr.LedgerEntryTypeTrustline, - Pre: &xdr.LedgerEntry{}, - Post: &xdr.LedgerEntry{}, - })) - - assert.NoError(t, processor.ProcessChange(ctx, Change{ - Type: xdr.LedgerEntryTypeLiquidityPool, - Pre: &xdr.LedgerEntry{}, - Post: &xdr.LedgerEntry{}, - })) - - // Removed - assert.NoError(t, processor.ProcessChange(ctx, Change{ - Type: xdr.LedgerEntryTypeAccount, - Pre: &xdr.LedgerEntry{}, - Post: nil, - })) - - assert.NoError(t, processor.ProcessChange(ctx, Change{ - Type: xdr.LedgerEntryTypeClaimableBalance, - Pre: &xdr.LedgerEntry{}, - Post: nil, - })) - - assert.NoError(t, processor.ProcessChange(ctx, Change{ - Type: xdr.LedgerEntryTypeData, - Pre: &xdr.LedgerEntry{}, - Post: nil, - })) - - assert.NoError(t, processor.ProcessChange(ctx, Change{ - Type: xdr.LedgerEntryTypeOffer, - Pre: &xdr.LedgerEntry{}, - Post: nil, - })) - - assert.NoError(t, processor.ProcessChange(ctx, Change{ - Type: xdr.LedgerEntryTypeTrustline, - Pre: &xdr.LedgerEntry{}, - Post: nil, - })) - - assert.NoError(t, processor.ProcessChange(ctx, Change{ - Type: xdr.LedgerEntryTypeLiquidityPool, - Pre: &xdr.LedgerEntry{}, - Post: nil, - })) + for ledgerEntryType := range xdr.LedgerEntryTypeMap { + // Created + assert.NoError(t, processor.ProcessChange(ctx, Change{ + Type: xdr.LedgerEntryType(ledgerEntryType), + Pre: nil, + Post: &xdr.LedgerEntry{}, + })) + // Updated + assert.NoError(t, processor.ProcessChange(ctx, Change{ + Type: xdr.LedgerEntryType(ledgerEntryType), + Pre: &xdr.LedgerEntry{}, + Post: &xdr.LedgerEntry{}, + })) + // Removed + assert.NoError(t, processor.ProcessChange(ctx, Change{ + Type: xdr.LedgerEntryType(ledgerEntryType), + Pre: &xdr.LedgerEntry{}, + Post: nil, + })) + } results := processor.GetResults() @@ -131,6 +42,10 @@ func TestStatsChangeProcessor(t *testing.T) { assert.Equal(t, int64(1), results.OffersCreated) assert.Equal(t, int64(1), results.TrustLinesCreated) assert.Equal(t, int64(1), results.LiquidityPoolsCreated) + assert.Equal(t, int64(1), results.ContractDataCreated) + assert.Equal(t, int64(1), results.ContractCodeCreated) + assert.Equal(t, int64(1), results.ConfigSettingsCreated) + assert.Equal(t, int64(1), results.TtlCreated) assert.Equal(t, int64(1), results.AccountsUpdated) assert.Equal(t, int64(1), results.ClaimableBalancesUpdated) @@ -138,6 +53,10 @@ func TestStatsChangeProcessor(t *testing.T) { assert.Equal(t, int64(1), results.OffersUpdated) assert.Equal(t, int64(1), results.TrustLinesUpdated) assert.Equal(t, int64(1), results.LiquidityPoolsUpdated) + assert.Equal(t, int64(1), results.ContractDataUpdated) + assert.Equal(t, int64(1), results.ContractCodeUpdated) + assert.Equal(t, int64(1), results.ConfigSettingsUpdated) + assert.Equal(t, int64(1), results.TtlUpdated) assert.Equal(t, int64(1), results.AccountsRemoved) assert.Equal(t, int64(1), results.ClaimableBalancesRemoved) @@ -145,4 +64,10 @@ func TestStatsChangeProcessor(t *testing.T) { assert.Equal(t, int64(1), results.OffersRemoved) assert.Equal(t, int64(1), results.TrustLinesRemoved) assert.Equal(t, int64(1), results.LiquidityPoolsRemoved) + assert.Equal(t, int64(1), results.ContractCodeRemoved) + assert.Equal(t, int64(1), results.ContractDataRemoved) + assert.Equal(t, int64(1), results.ConfigSettingsRemoved) + assert.Equal(t, int64(1), results.TtlRemoved) + + assert.Equal(t, len(xdr.LedgerEntryTypeMap)*3, len(results.Map())) } diff --git a/services/horizon/internal/ingest/verify/main.go b/ingest/verify/main.go similarity index 88% rename from services/horizon/internal/ingest/verify/main.go rename to ingest/verify/main.go index 0d4102b204..4b97ffc2f7 100644 --- a/services/horizon/internal/ingest/verify/main.go +++ b/ingest/verify/main.go @@ -57,15 +57,15 @@ func NewStateVerifier(stateReader ingest.ChangeReader, tf TransformLedgerEntryFu } } -// GetLedgerKeys returns up to `count` ledger keys from history buckets -// storing actual entries in cache to compare in Write. -func (v *StateVerifier) GetLedgerKeys(count int) ([]xdr.LedgerKey, error) { +// GetLedgerEntries returns up to `count` ledger entries from history buckets +// and stores the entries in cache to compare in Write. +func (v *StateVerifier) GetLedgerEntries(count int) ([]xdr.LedgerEntry, error) { err := v.checkUnreadEntries() if err != nil { return nil, err } - keys := make([]xdr.LedgerKey, 0, count) + entries := make([]xdr.LedgerEntry, 0, count) v.currentEntries = make(map[string]xdr.LedgerEntry) for count > 0 { @@ -73,9 +73,9 @@ func (v *StateVerifier) GetLedgerKeys(count int) ([]xdr.LedgerKey, error) { if err != nil { if err == io.EOF { v.readingDone = true - return keys, nil + return entries, nil } - return keys, err + return entries, err } entry := *entryChange.Post @@ -87,21 +87,24 @@ func (v *StateVerifier) GetLedgerKeys(count int) ([]xdr.LedgerKey, error) { } } - ledgerKey := entry.LedgerKey() + ledgerKey, err := entry.LedgerKey() + if err != nil { + return entries, errors.Wrap(err, "Error marshaling ledgerKey") + } key, err := v.encodingBuffer.MarshalBinary(ledgerKey) if err != nil { - return keys, errors.Wrap(err, "Error marshaling ledgerKey") + return entries, errors.Wrap(err, "Error marshaling ledgerKey") } - keys = append(keys, ledgerKey) entry.Normalize() + entries = append(entries, entry) v.currentEntries[string(key)] = entry count-- v.readEntries++ } - return keys, nil + return entries, nil } // Write compares the entry with entries in the latest batch of entries fetched @@ -117,20 +120,24 @@ func (v *StateVerifier) Write(entry xdr.LedgerEntry) error { } // safe, since we convert to string right away (causing a copy) - key, err := v.encodingBuffer.UnsafeMarshalBinary(actualEntry.LedgerKey()) + key, err := actualEntry.LedgerKey() if err != nil { return errors.Wrap(err, "Error marshaling ledgerKey") } - - expectedEntry, exist := v.currentEntries[string(key)] + keyBinary, err := v.encodingBuffer.UnsafeMarshalBinary(key) + if err != nil { + return errors.Wrap(err, "Error marshaling ledgerKey") + } + keyString := string(keyBinary) + expectedEntry, exist := v.currentEntries[keyString] if !exist { return ingest.NewStateError(errors.Errorf( "Cannot find entry in currentEntries map: %s (key = %s)", base64.StdEncoding.EncodeToString(actualEntryMarshaled), - base64.StdEncoding.EncodeToString(key), + base64.StdEncoding.EncodeToString(keyBinary), )) } - delete(v.currentEntries, string(key)) + delete(v.currentEntries, keyString) preTransformExpectedEntry := expectedEntry preTransformExpectedEntryMarshaled, err := v.encodingBuffer.MarshalBinary(&preTransformExpectedEntry) diff --git a/services/horizon/internal/ingest/verify/main_test.go b/ingest/verify/main_test.go similarity index 90% rename from services/horizon/internal/ingest/verify/main_test.go rename to ingest/verify/main_test.go index 4c61007622..070a4bb5dc 100644 --- a/services/horizon/internal/ingest/verify/main_test.go +++ b/ingest/verify/main_test.go @@ -46,15 +46,15 @@ func (s *StateVerifierTestSuite) TearDownTest() { func (s *StateVerifierTestSuite) TestNoEntries() { s.mockStateReader.On("Read").Return(ingest.Change{}, io.EOF).Once() - keys, err := s.verifier.GetLedgerKeys(10) + entries, err := s.verifier.GetLedgerEntries(10) s.Assert().NoError(err) - s.Assert().Len(keys, 0) + s.Assert().Len(entries, 0) } func (s *StateVerifierTestSuite) TestReturnErrorOnStateReaderError() { s.mockStateReader.On("Read").Return(ingest.Change{}, errors.New("Read error")).Once() - _, err := s.verifier.GetLedgerKeys(10) + _, err := s.verifier.GetLedgerEntries(10) s.Assert().EqualError(err, "Read error") } @@ -63,7 +63,8 @@ func (s *StateVerifierTestSuite) TestCurrentEntriesNotEmpty() { entryBase64, err := xdr.MarshalBase64(entry) s.Assert().NoError(err) - ledgerKey := entry.LedgerKey() + ledgerKey, err := entry.LedgerKey() + s.Assert().NoError(err) ledgerKeyBase64, err := xdr.MarshalBase64(ledgerKey) s.Assert().NoError(err) @@ -71,7 +72,7 @@ func (s *StateVerifierTestSuite) TestCurrentEntriesNotEmpty() { ledgerKeyBase64: entry, } - _, err = s.verifier.GetLedgerKeys(10) + _, err = s.verifier.GetLedgerEntries(10) s.Assert().Error(err) assertStateError(s.T(), err, true) s.Assert().EqualError(err, "Entries (1) not found locally, example: "+entryBase64) @@ -121,11 +122,13 @@ func (s *StateVerifierTestSuite) TestTransformFunction() { } } - _, err := s.verifier.GetLedgerKeys(10) + _, err := s.verifier.GetLedgerEntries(10) s.Assert().NoError(err) // Check currentEntries - ledgerKey, err := accountEntry.LedgerKey().MarshalBinary() + key, err := accountEntry.LedgerKey() + s.Assert().NoError(err) + ledgerKey, err := key.MarshalBinary() s.Assert().NoError(err) // Account entry transformed and offer entry ignored @@ -145,9 +148,9 @@ func (s *StateVerifierTestSuite) TestOnlyRequestedNumberOfKeysReturned() { // We don't mock Read() -> (io.Change{}, stdio.EOF) call here // because this would execute `stdio.EOF` code path. - keys, err := s.verifier.GetLedgerKeys(1) + entries, err := s.verifier.GetLedgerEntries(1) s.Assert().NoError(err) - s.Assert().Len(keys, 1) + s.Assert().Len(entries, 1) // In such case Verify() should notice that not all entries read from buckets err = s.verifier.Write(accountEntry) @@ -164,7 +167,8 @@ func (s *StateVerifierTestSuite) TestWriteEntryNotExist() { entryBase64, err := xdr.MarshalBase64(entry) s.Assert().NoError(err) - ledgerKey := entry.LedgerKey() + ledgerKey, err := entry.LedgerKey() + s.Assert().NoError(err) ledgerKeyBase64, err := xdr.MarshalBase64(ledgerKey) s.Assert().NoError(err) @@ -193,11 +197,11 @@ func (s *StateVerifierTestSuite) TestTransformFunctionBuggyIgnore() { return false, xdr.LedgerEntry{} } - keys, err := s.verifier.GetLedgerKeys(1) + entries, err := s.verifier.GetLedgerEntries(1) s.Assert().NoError(err) - s.Assert().Len(keys, 1) + s.Assert().Len(entries, 1) - // Check the behaviour of transformFunction to code path to test. + // Check the behavior of transformFunction to code path to test. s.verifier.transformFunction = func(entry xdr.LedgerEntry) (ignore bool, newEntry xdr.LedgerEntry) { return true, xdr.LedgerEntry{} @@ -222,9 +226,9 @@ func (s *StateVerifierTestSuite) TestActualExpectedEntryNotEqualWrite() { Post: &expectedEntry, }, nil).Once() - keys, err := s.verifier.GetLedgerKeys(1) + entries, err := s.verifier.GetLedgerEntries(1) s.Assert().NoError(err) - s.Assert().Len(keys, 1) + s.Assert().Len(entries, 1) actualEntry := makeAccountLedgerEntry() actualEntry.Data.Account.Thresholds = [4]byte{1, 1, 1, 0} @@ -258,9 +262,9 @@ func (s *StateVerifierTestSuite) TestVerifyCountersMatch() { s.mockStateReader.On("Read").Return(ingest.Change{}, io.EOF).Once() - keys, err := s.verifier.GetLedgerKeys(2) + entries, err := s.verifier.GetLedgerEntries(2) s.Assert().NoError(err) - s.Assert().Len(keys, 1) + s.Assert().Len(entries, 1) err = s.verifier.Write(accountEntry) s.Assert().NoError(err) diff --git a/integration.sh b/integration.sh index 3d98ec5de6..6a301547ce 100755 --- a/integration.sh +++ b/integration.sh @@ -17,7 +17,7 @@ if [[ "$(docker inspect integration_postgres -f '{{.State.Running}}')" != "true" --platform linux/amd64 \ --env POSTGRES_HOST_AUTH_METHOD=trust \ -p 5432:5432 \ - circleci/postgres:9.6.5-alpine + postgres:12-bullseye fi -exec go test -timeout 25m github.com/stellar/go/services/horizon/internal/integration/... "$@" +exec go test -timeout 35m github.com/stellar/go/services/horizon/internal/integration/... "$@" diff --git a/network/main.go b/network/main.go index 2e5a8a0d73..059a264b81 100644 --- a/network/main.go +++ b/network/main.go @@ -17,6 +17,20 @@ const ( PublicNetworkPassphrase = "Public Global Stellar Network ; September 2015" // TestNetworkPassphrase is the pass phrase used for every transaction intended for the SDF-run test network TestNetworkPassphrase = "Test SDF Network ; September 2015" + // FutureNetworkPassphrase is the pass phrase used for every transaction intended for the SDF-run future network + FutureNetworkPassphrase = "Test SDF Future Network ; October 2022" +) + +var ( + // PublicNetworkhistoryArchiveURLs is a list of history archive URLs for stellar 'pubnet' + PublicNetworkhistoryArchiveURLs = []string{"https://history.stellar.org/prd/core-live/core_live_001/", + "https://history.stellar.org/prd/core-live/core_live_002/", + "https://history.stellar.org/prd/core-live/core_live_003/"} + + // TestNetworkhistoryArchiveURLs is a list of history archive URLs for stellar 'testnet' + TestNetworkhistoryArchiveURLs = []string{"https://history.stellar.org/prd/core-testnet/core_testnet_001/", + "https://history.stellar.org/prd/core-testnet/core_testnet_002/", + "https://history.stellar.org/prd/core-testnet/core_testnet_003"} ) // ID returns the network ID derived from the provided passphrase. This value diff --git a/protocols/federation/main.go b/protocols/federation/main.go index ae4abf33ef..2090cbe8a5 100644 --- a/protocols/federation/main.go +++ b/protocols/federation/main.go @@ -26,7 +26,7 @@ type Memo struct { } func (m Memo) MarshalJSON() ([]byte, error) { - // Memo after marshalling should always be a string + // Memo after marshaling should always be a string value, err := json.Marshal(m.Value) if err != nil { return []byte{}, err diff --git a/protocols/horizon/effects/main.go b/protocols/horizon/effects/main.go index 5d04dff8c3..275ec15b95 100644 --- a/protocols/horizon/effects/main.go +++ b/protocols/horizon/effects/main.go @@ -199,6 +199,16 @@ const ( // EffectLiquidityPoolRevoked occurs when a liquidity pool is revoked EffectLiquidityPoolRevoked EffectType = 95 // from change_trust_line_flags and allow_trust + + // EffectContractCredited effects occur when a contract receives some + // currency from SAC events involving transfers, mints, and burns. + // https://github.com/stellar/rs-soroban-env/blob/5695440da452837555d8f7f259cc33341fdf07b0/soroban-env-host/src/native_contract/token/contract.rs#L51-L63 + EffectContractCredited EffectType = 96 + + // EffectContractDebited effects occur when a contract sends some currency + // from SAC events involving transfers, mints, and burns. + // https://github.com/stellar/rs-soroban-env/blob/5695440da452837555d8f7f259cc33341fdf07b0/soroban-env-host/src/native_contract/token/contract.rs#L51-L63 + EffectContractDebited EffectType = 97 ) // Peter 30-04-2019: this is copied from the resourcadapter package @@ -259,6 +269,8 @@ var EffectTypeNames = map[EffectType]string{ EffectLiquidityPoolCreated: "liquidity_pool_created", EffectLiquidityPoolRemoved: "liquidity_pool_removed", EffectLiquidityPoolRevoked: "liquidity_pool_revoked", + EffectContractCredited: "contract_credited", + EffectContractDebited: "contract_debited", } // Base provides the common structure for any effect resource effect. @@ -301,6 +313,20 @@ type AccountDebited struct { Amount string `json:"amount"` } +type ContractCredited struct { + Base + base.Asset + Contract string `json:"contract"` + Amount string `json:"amount"` +} + +type ContractDebited struct { + Base + base.Asset + Contract string `json:"contract"` + Amount string `json:"amount"` +} + type AccountThresholdsUpdated struct { Base LowThreshold int32 `json:"low_threshold"` @@ -952,6 +978,18 @@ func UnmarshalEffect(effectType string, dataString []byte) (effects Effect, err return } effects = effect + case EffectTypeNames[EffectContractCredited]: + var effect ContractCredited + if err = json.Unmarshal(dataString, &effect); err != nil { + return + } + effects = effect + case EffectTypeNames[EffectContractDebited]: + var effect ContractDebited + if err = json.Unmarshal(dataString, &effect); err != nil { + return + } + effects = effect default: var effect Base if err = json.Unmarshal(dataString, &effect); err != nil { diff --git a/protocols/horizon/main.go b/protocols/horizon/main.go index db33efa03b..08da47b7b4 100644 --- a/protocols/horizon/main.go +++ b/protocols/horizon/main.go @@ -166,16 +166,21 @@ type AssetStat struct { } `json:"_links"` base.Asset - PT string `json:"paging_token"` + PT string `json:"paging_token"` + ContractID string `json:"contract_id,omitempty"` // Action needed in release: horizon-v3.0.0: deprecated field NumAccounts int32 `json:"num_accounts"` NumClaimableBalances int32 `json:"num_claimable_balances"` NumLiquidityPools int32 `json:"num_liquidity_pools"` + NumContracts int32 `json:"num_contracts"` + NumArchivedContracts int32 `json:"num_archived_contracts"` // Action needed in release: horizon-v3.0.0: deprecated field Amount string `json:"amount"` Accounts AssetStatAccounts `json:"accounts"` ClaimableBalancesAmount string `json:"claimable_balances_amount"` LiquidityPoolsAmount string `json:"liquidity_pools_amount"` + ContractsAmount string `json:"contracts_amount"` + ArchivedContractsAmount string `json:"archived_contracts_amount"` Balances AssetStatBalances `json:"balances"` Flags AccountFlags `json:"flags"` } diff --git a/protocols/horizon/main_test.go b/protocols/horizon/main_test.go index ddcd9a6e9e..28e7e00708 100644 --- a/protocols/horizon/main_test.go +++ b/protocols/horizon/main_test.go @@ -67,7 +67,7 @@ func TestTransactionJSONMarshal(t *testing.T) { // Test that a typical friendbot fund response can unmarshal to the Transaction // type. The horizonclient uses the Transaction type for friendbot responses // also, but their response is a slimmed down version of the full transaction -// response. This test confirms there are no errors unmarshalling that slimmed +// response. This test confirms there are no errors unmarshaling that slimmed // down version. func TestTransactionUnmarshalsFriendbotFund(t *testing.T) { friendbotFundResponse := `{ diff --git a/protocols/horizon/operations/main.go b/protocols/horizon/operations/main.go index 2bf0ddf762..3e4af748b8 100644 --- a/protocols/horizon/operations/main.go +++ b/protocols/horizon/operations/main.go @@ -38,6 +38,9 @@ var TypeNames = map[xdr.OperationType]string{ xdr.OperationTypeSetTrustLineFlags: "set_trust_line_flags", xdr.OperationTypeLiquidityPoolDeposit: "liquidity_pool_deposit", xdr.OperationTypeLiquidityPoolWithdraw: "liquidity_pool_withdraw", + xdr.OperationTypeInvokeHostFunction: "invoke_host_function", + xdr.OperationTypeExtendFootprintTtl: "extend_footprint_ttl", + xdr.OperationTypeRestoreFootprint: "restore_footprint", } // Base represents the common attributes of an operation resource @@ -344,6 +347,68 @@ type LiquidityPoolWithdraw struct { ReservesReceived []base.AssetAmount `json:"reserves_received"` } +// InvokeHostFunction is the json resource representing a single InvokeHostFunctionOp. +// The model for InvokeHostFunction assimilates InvokeHostFunctionOp, but is simplified. +// HostFunction - contract function invocation to be performed. +// AssetBalanceChanges - array of asset balance changed records related to contract invocations in this host invocation. +// +// The asset balance change record is captured at ingestion time from the asset contract +// events present in tx meta. Only asset contract events that have a reference to classic account in +// either the 'from' or 'to' participants will be included here as an asset balance change. +// Any pure contract-to-contract events with no reference to classic accounts are not included, +// as there is no explicit model in horizon for contract addresses yet. +type InvokeHostFunction struct { + Base + Function string `json:"function"` + Parameters []HostFunctionParameter `json:"parameters"` + Address string `json:"address"` + Salt string `json:"salt"` + AssetBalanceChanges []AssetContractBalanceChange `json:"asset_balance_changes"` +} + +// InvokeHostFunction parameter model, intentionally simplified, Value +// just contains a base64 encoded string of the ScVal xdr serialization. +type HostFunctionParameter struct { + Value string `json:"value"` + Type string `json:"type"` +} + +// ExtendFootprintTtl is the json resource representing a single ExtendFootprintTtlOp. +// The model for ExtendFootprintTtl assimilates ExtendFootprintTtlOp, but is simplified. +type ExtendFootprintTtl struct { + Base + ExtendTo uint32 `json:"extend_to"` +} + +// RestoreFootprint is the json resource representing a single RestoreFootprint. +type RestoreFootprint struct { + Base +} + +// Type - refers to the source SAC Event +// +// it can only be one of 'transfer', 'mint', 'clawback' or 'burn' +// +// From - this is classic account that asset balance was changed, +// +// or absent if not applicable for function +// +// To - this is the classic account that asset balance was changed, +// +// or absent if not applicable for function +// +// for asset contract event type, it can be absent such as 'burn' +// +// Amount - expressed as a signed decimal to 7 digits precision. +// Asset - the classic asset expressed as issuer and code. +type AssetContractBalanceChange struct { + base.Asset + Type string `json:"type"` + From string `json:"from,omitempty"` + To string `json:"to,omitempty"` + Amount string `json:"amount"` +} + // Operation interface contains methods implemented by the operation types type Operation interface { GetBase() Base @@ -571,6 +636,24 @@ func UnmarshalOperation(operationTypeID int32, dataString []byte) (ops Operation return } ops = op + case xdr.OperationTypeInvokeHostFunction: + var op InvokeHostFunction + if err = json.Unmarshal(dataString, &op); err != nil { + return + } + ops = op + case xdr.OperationTypeExtendFootprintTtl: + var op ExtendFootprintTtl + if err = json.Unmarshal(dataString, &op); err != nil { + return + } + ops = op + case xdr.OperationTypeRestoreFootprint: + var op RestoreFootprint + if err = json.Unmarshal(dataString, &op); err != nil { + return + } + ops = op default: err = errors.New("Invalid operation format, unable to unmarshal json response") } diff --git a/protocols/stellarcore/getledgerentry_response.go b/protocols/stellarcore/getledgerentry_response.go new file mode 100644 index 0000000000..d3289c6aa8 --- /dev/null +++ b/protocols/stellarcore/getledgerentry_response.go @@ -0,0 +1,18 @@ +package stellarcore + +const ( + // LiveState represents the state value returned by stellar-core when a + // ledger entry is live + LiveState = "live" + + // DeadState represents the state value returned by stellar-core when a + // ledger entry is dead + DeadState = "dead" +) + +// GetLedgerEntryResponse is the response from Stellar Core for the getLedgerEntry endpoint +type GetLedgerEntryResponse struct { + State string `json:"state"` + Entry string `json:"entry"` + Ledger int64 `json:"ledger"` +} diff --git a/protocols/stellarcore/preflight_response.go b/protocols/stellarcore/preflight_response.go new file mode 100644 index 0000000000..4c7ded93aa --- /dev/null +++ b/protocols/stellarcore/preflight_response.go @@ -0,0 +1,22 @@ +package stellarcore + +const ( + // PreflightStatusError represents the status value returned by stellar-core when an error occurred from + // processing a preflight request + PreflightStatusError = "ERROR" + + // PreflightStatusOk represents the status value returned by stellar-core when a preflight request + // succeeded + PreflightStatusOk = "OK" +) + +// PreflightResponse is the response from Stellar Core for the preflight endpoint +type PreflightResponse struct { + Status string `json:"status"` + Detail string `json:"detail"` + Result string `json:"result"` + Footprint string `json:"footprint"` + CPUInstructions uint64 `json:"cpu_insns"` + MemoryBytes uint64 `json:"mem_bytes"` + Ledger int64 `json:"ledger"` +} diff --git a/protocols/stellarcore/tx_response.go b/protocols/stellarcore/tx_response.go index ee8556adc3..c4434ea280 100644 --- a/protocols/stellarcore/tx_response.go +++ b/protocols/stellarcore/tx_response.go @@ -1,5 +1,9 @@ package stellarcore +import ( + "github.com/stellar/go/xdr" +) + const ( // TXStatusError represents the status value returned by stellar-core when an error occurred from // submitting a transaction @@ -25,9 +29,42 @@ type TXResponse struct { Exception string `json:"exception"` Error string `json:"error"` Status string `json:"status"` + // DiagnosticEvents is an optional base64-encoded XDR Variable-Length Array of DiagnosticEvents + DiagnosticEvents string `json:"diagnostic_events,omitempty"` } // IsException returns true if the response represents an exception response from stellar-core func (resp *TXResponse) IsException() bool { return resp.Exception != "" } + +// DecodeDiagnosticEvents returns the decoded events +func DecodeDiagnosticEvents(events string) ([]xdr.DiagnosticEvent, error) { + var ret []xdr.DiagnosticEvent + if events == "" { + return ret, nil + } + err := xdr.SafeUnmarshalBase64(events, &ret) + if err != nil { + return nil, err + } + return ret, err +} + +// DiagnosticEventsToSlice transforms the base64 diagnostic events into a slice of individual +// base64-encoded diagnostic events +func DiagnosticEventsToSlice(events string) ([]string, error) { + decoded, err := DecodeDiagnosticEvents(events) + if err != nil { + return nil, err + } + result := make([]string, len(decoded)) + for i := 0; i < len(decoded); i++ { + encoded, err := xdr.MarshalBase64(decoded[i]) + if err != nil { + return nil, err + } + result[i] = encoded + } + return result, nil +} diff --git a/protocols/stellarcore/tx_response_test.go b/protocols/stellarcore/tx_response_test.go new file mode 100644 index 0000000000..bf2baf90d0 --- /dev/null +++ b/protocols/stellarcore/tx_response_test.go @@ -0,0 +1,16 @@ +package stellarcore + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func TestDiagnosticEventsToSlice(t *testing.T) { + events := "AAAAAgAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAgAAAA8AAAAFZXJyb3IAAAAAAAACAAAAAwAAAAUAAAAQAAAAAQAAAAMAAAAOAAAAU3RyYW5zYWN0aW9uIGBzb3JvYmFuRGF0YS5yZXNvdXJjZUZlZWAgaXMgbG93ZXIgdGhhbiB0aGUgYWN0dWFsIFNvcm9iYW4gcmVzb3VyY2UgZmVlAAAAAAUAAAAAAAEJcwAAAAUAAAAAAAG6fAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAgAAAA8AAAAFZXJyb3IAAAAAAAACAAAAAwAAAAUAAAAQAAAAAQAAAAMAAAAOAAAAU3RyYW5zYWN0aW9uIGBzb3JvYmFuRGF0YS5yZXNvdXJjZUZlZWAgaXMgbG93ZXIgdGhhbiB0aGUgYWN0dWFsIFNvcm9iYW4gcmVzb3VyY2UgZmVlAAAAAAUAAAAAAAEJcwAAAAUAAAAAAAG6fA==" + slice, err := DiagnosticEventsToSlice(events) + require.NoError(t, err) + require.Len(t, slice, 2) + require.Equal(t, slice[0], "AAAAAAAAAAAAAAAAAAAAAgAAAAAAAAACAAAADwAAAAVlcnJvcgAAAAAAAAIAAAADAAAABQAAABAAAAABAAAAAwAAAA4AAABTdHJhbnNhY3Rpb24gYHNvcm9iYW5EYXRhLnJlc291cmNlRmVlYCBpcyBsb3dlciB0aGFuIHRoZSBhY3R1YWwgU29yb2JhbiByZXNvdXJjZSBmZWUAAAAABQAAAAAAAQlzAAAABQAAAAAAAbp8") + require.Equal(t, slice[1], "AAAAAAAAAAAAAAAAAAAAAgAAAAAAAAACAAAADwAAAAVlcnJvcgAAAAAAAAIAAAADAAAABQAAABAAAAABAAAAAwAAAA4AAABTdHJhbnNhY3Rpb24gYHNvcm9iYW5EYXRhLnJlc291cmNlRmVlYCBpcyBsb3dlciB0aGFuIHRoZSBhY3R1YWwgU29yb2JhbiByZXNvdXJjZSBmZWUAAAAABQAAAAAAAQlzAAAABQAAAAAAAbp8") +} diff --git a/randxdr/generator_test.go b/randxdr/generator_test.go index 45ad9da2ea..db21815419 100644 --- a/randxdr/generator_test.go +++ b/randxdr/generator_test.go @@ -20,6 +20,7 @@ func TestRandLedgerCloseMeta(t *testing.T) { shape, []Preset{ {IsNestedInnerSet, SetVecLen(0)}, + {IsDeepAuthorizedInvocationTree, SetVecLen(0)}, }, ) // check that the goxdr representation matches the go-xdr representation @@ -39,6 +40,7 @@ func TestGeneratorIsDeterministic(t *testing.T) { shape, []Preset{ {IsNestedInnerSet, SetVecLen(0)}, + {IsDeepAuthorizedInvocationTree, SetVecLen(0)}, }, ) @@ -48,6 +50,7 @@ func TestGeneratorIsDeterministic(t *testing.T) { otherShape, []Preset{ {IsNestedInnerSet, SetVecLen(0)}, + {IsDeepAuthorizedInvocationTree, SetVecLen(0)}, }, ) diff --git a/randxdr/presets.go b/randxdr/presets.go index 46913472b4..7fcee3c8f2 100644 --- a/randxdr/presets.go +++ b/randxdr/presets.go @@ -67,6 +67,25 @@ var IsNestedInnerSet Selector = func(name string, xdrType goxdr.XdrType) bool { return false } +// IsDeepAuthorizedInvocationTree is a Selector which identifies deep trees of the following xdr type: +// +// struct AuthorizedInvocation +// { +// Hash contractID; +// SCSymbol functionName; +// SCVec args; +// AuthorizedInvocation subInvocations<>; +// }; +// +// only allows trees of height up to 2 +var IsDeepAuthorizedInvocationTree Selector = func(name string, xdrType goxdr.XdrType) bool { + if strings.HasSuffix(name, "subInvocations") && strings.Count(name, ".subInvocations[") > 0 { + _, ok := goxdr.XdrBaseType(xdrType).(goxdr.XdrVec) + return ok + } + return false +} + // SetPtr is a Setter which sets the xdr pointer to null if present is false func SetPtr(present bool) Setter { return func(m *randMarshaller, name string, xdrType goxdr.XdrType) { @@ -86,11 +105,12 @@ func SetVecLen(vecLen uint32) Setter { } } -// SetU32 returns a Setter which sets a uint32 XDR field to a fixed value -func SetU32(val uint32) Setter { +// SetU32 returns a Setter which sets a uint32 XDR field to a randomly selected +// element from vals +func SetU32(vals ...uint32) Setter { return func(x *randMarshaller, field string, xdrType goxdr.XdrType) { f := goxdr.XdrBaseType(xdrType).(goxdr.XdrNum32) - f.SetU32(val) + f.SetU32(vals[x.rand.Intn(len(vals))]) } } diff --git a/services/friendbot/docker/Dockerfile b/services/friendbot/docker/Dockerfile index bd1e48363e..dc1c74b93f 100644 --- a/services/friendbot/docker/Dockerfile +++ b/services/friendbot/docker/Dockerfile @@ -1,10 +1,10 @@ -FROM golang:1.18 as build +FROM golang:1.20-bullseye as build ADD . /src/friendbot WORKDIR /src/friendbot RUN go build -o /bin/friendbot ./services/friendbot -FROM ubuntu:20.04 +FROM ubuntu:22.04 RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends ca-certificates COPY --from=build /bin/friendbot /app/ diff --git a/services/horizon/CHANGELOG.md b/services/horizon/CHANGELOG.md index 74a50f7d76..619c1f40e7 100644 --- a/services/horizon/CHANGELOG.md +++ b/services/horizon/CHANGELOG.md @@ -3,9 +3,161 @@ All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). -## Pending -- Added indexes by id for claimable balance and liquidity pool id's in the respective tx/ops tables ([4455](https://github.com/stellar/go/pull/4477)) -- Improve restart time of Captive-Core when started with `--captive-core-use-db` flag. The solution does not work on Windows. ([4471)](https://github.com/stellar/go/pull/4471)) +## Unreleased + +### Added + +- Add a deprecation warning for using command-line flags when running Horizon ([5051](https://github.com/stellar/go/pull/5051)) +- Deprecate configuration flags related to legacy non-captive core ingestion ([5100](https://github.com/stellar/go/pull/5100)) +## 2.27.0 + +### Fixed +- Ordering of effects are now deterministic. Previously the order of some Horizon effects could vary upon reingestion but this issue has now been fixed ([5070](https://github.com/stellar/go/pull/5070)). + +## 2.27.0-rc2 +### Fixed +- treat null is_payment values as equivalent to false values, avoid sql nil conversion errors([5060](https://github.com/stellar/go/pull/5060)). + +## 2.27.0-rc1 + +**Upgrading to this version from <= 2.26.1 will trigger a state rebuild. During this process (which will take at least 10 minutes), Horizon will not ingest new ledgers.** + +**This release adds support for Protocol 20** + +### Breaking Changes +- The command line flag `--remote-captive-core-url` has been removed, as remote captive core functionality is now deprecated ([4940](https://github.com/stellar/go/pull/4940)). +- The functionality of generating default captive core configuration based on the --network-passphrase is now deprecated. Use the --network command instead ([4949](https://github.com/stellar/go/pull/4949)). + +### Added +- Added new command-line flag `--network` to specify the Stellar network (pubnet or testnet), aiming at simplifying the configuration process by automatically configuring the following parameters based on the chosen network: `--history-archive-urls`, `--network-passphrase`, and `--captive-core-config-path` ([4949](https://github.com/stellar/go/pull/4949)). +- Added `contract_credited` and `contract_debited` effects which are emitted whenever a Soroban contracts sends or receives a Stellar asset ([4832](https://github.com/stellar/go/pull/4832)). +* Added `num_contracts` (total number of Soroban contracts which hold an asset) and `contracts_amount` (total amount of the asset held by all Soroban contracts) fields to asset stat summaries at `/assets` ([4805](https://github.com/stellar/go/pull/4805)). +* Added responses for new operations introduced in protocol 20: `invoke_host_function`, `bump_footprint_expiration`, and `restore_footprint` ([4905](https://github.com/stellar/go/pull/4905)). + +### Fixed +- The same slippage calculation from the [`v2.26.1`](#2261) hotfix now properly excludes spikes for smoother trade aggregation plots ([4999](https://github.com/stellar/go/pull/4999)). +- Limit the display of global flags on command line help `-h` output ([5077](https://github.com/stellar/go/pull/5077)). + +### DB Schema Migration +- Drop unused indices from the Horizon database. For the database with full history, the migration is anticipated to take up to an hour and is expected to free up approximately 1.3TB of storage ([5081](https://github.com/stellar/go/pull/5081)). + +## 2.26.1 + +### Fixes +- Ingestion will not halt if liquidity pool overflows are detected. + + +## 2.26.0 +### Changes +- Improve error handling for when stellar-core crashes ([4893](https://github.com/stellar/go/pull/4893)) +- Suppress Core timeout error in log output such as `error ticking app: context deadline exceeded` when ingestion state machine is in build state. ([4860](https://github.com/stellar/go/pull/4860)) + + +### Breaking Changes +- Modify the default value of `--captive-core-use-db` to true ([4856](https://github.com/stellar/go/issues/4856)) + - This updates the default behavior of captive core to start in on-disk mode. + - To continue using the previous in-memory mode, explicitly set the `--captive-core-use-db` flag to false + +## 2.25.0 + +### Changes + +- Running Horizon with remote captive core is now deprecated ([4826](https://github.com/stellar/go/pull/4826)). +- Add two new configuration variables to control the behavior of state verification ([4821](https://github.com/stellar/go/pull/4821)): + - `--ingest-state-verification-frequency` which specifies the frequency in checkpoints for how often state verification is run + - `--ingest-state-verification-timeout` which specifies a timeout on how long state verification can run + +### Fixes + +* Fix crash in horizon ingestion when running horizon with a remote captive core ([4824](https://github.com/stellar/go/pull/4824)). + + +## 2.24.1 + +### Changes + +- Bump Go to the latest version (1.20.1), including crypto/tls, mime/multipart, net/http, and path/filepath security fixes. + +## 2.24.0 + +### Changes + +- Add support for the experimental _BucketListDB_ to Horizon, the parameters have been added to the Captive Core configuration / TOML files ([4733](https://github.com/stellar/go/pull/4733)): + + * _BucketListDB_ is enabled by default when `--captive-core-use-db` is set and your `stellar-core` version >= 19.6 + * If `--captive-core-use-db` set but your `stellar-core` version < 19.6, an on-disk SQLite database is used (as before). + * This update will not automatically trigger a state rebuild **unless** `EXPERIMENTAL_BUCKETLIST_DB` is set to false in the Captive Core TOML file. + +### Fixes + +* Improve error when setting `BUCKET_DIR_PATH` and using Captive Core ([4736](https://github.com/stellar/go/pull/4736)). + +## 2.23.1 + +### Changes + +- Bump Go to the latest version, including net/http security fixes. + +## 2.23.0 + +**Upgrading to this version will trigger a state rebuild. During this process, Horizon will not ingest new ledgers.** + +### Fixes + +* Improve performance of `/claimable_balances` filters. This change should significantly improve `?asset=` and `?claimant=` filters. ([#4690](https://github.com/stellar/go/pull/4690)). +* Reallocate slices after offer removals in order book graph. This is done to prevent keeping a large chunks of allocated but unused memory that can lead to OOM crash. +* The ingestion subsystem will now properly use a pool of history archives if more than one is provided. ([#4687](https://github.com/stellar/go/pull/4687)) +* Add `horizon ingest build-state` command which builds state at a specific ledger. Useful for debugging. ([#4636](https://github.com/stellar/go/pull/4636)) + +## 2.22.1 + +**Upgrading to this version from <= v2.8.3 will trigger a state rebuild. During this process (which will take at least 10 minutes), Horizon will not ingest new ledgers.** + +### Fixes + +- `horizon db migrate` commands will not apply migrations if ingestion is disabled ([4664](https://github.com/stellar/go/pull/4664)). + +## 2.22.0 + +**Upgrading to this version from <= v2.8.3 will trigger a state rebuild. During this process (which will take at least 10 minutes), Horizon will not ingest new ledgers.** + +### Fixes + +- Database migrations will now acquire a lock on ingestion, preventing possible deadlocks ([4587](https://github.com/stellar/go/pull/4587)). + +### Changes + +- Optimizes startup by preserving the Captive Core storage directory if Horizon has ingested ahead of the requested ledger ([4605](https://github.com/stellar/go/pull/4605)). + +### DB Schema Migration + +- Introduces a new index that optimizes account queries filtered by asset ([4635](https://github.com/stellar/go/pull/4635)). + +## 2.21.0 + +**Upgrading to this version from <= v2.8.3 will trigger a state rebuild. During this process (which will take at least 10 minutes), Horizon will not ingest new ledgers.** + +### Changes + +- Bump Go to the latest version, including net/http and net/url security fixes ([4577](https://github.com/stellar/go/pull/4577)) + +### DB Schema Migration + +- Added indexes by id for assets in the respective `history_trades` tables. Ingestion will stop while the migration is being applied. ([4565](https://github.com/stellar/go/pull/4565)) + +## 2.20.0 + +**Upgrading to this version from <= v2.8.3 will trigger a state rebuild. During this process (which will take at least 10 minutes), Horizon will not ingest new ledgers.** + +### DB Schema Migration + +- Added indexes by id for claimable balance and liquidity pool id's in the respective tx/ops tables. Ingestion will stop while the migration is being applied. ([4455](https://github.com/stellar/go/pull/4477)) + +### Changes + +- Orphaned rows in lookup tables (`history_accounts`, `history_claimable_balances` and `history_liquidity_pools`) are removed in small batches after each ledger if `--history-retention-count` is set. ([4518](https://github.com/stellar/go/pull/4518), [4525](https://github.com/stellar/go/pull/4525)) +- Improve restart time of Captive-Core when started with `--captive-core-use-db` flag. The solution does not work on Windows. ([4471](https://github.com/stellar/go/pull/4471)) +- Fix a bug in which state verifier would run if condition checking DB query fails. ([4523](https://github.com/stellar/go/pull/4523)) ## 2.19.0 @@ -494,7 +646,7 @@ This is a minor release with no DB Schema migrations nor explicit state rebuild. **Upgrading to this version from <= v2.1.1 will trigger a state rebuild. During this process (which can take up to 20 minutes), Horizon will not ingest new ledgers.** -* Add new command `horizon db detect-gaps`, which detects ingestion gaps in the database. The command prints out the `db reingest` commands to run in order to fill the gaps found ([3672](https://github.com/stellar/go/pull/3672)). +* Add new command `horizon db detect-gaps`, which detects ingestion gaps in the database. The command prints out the `db reingest` commands to run in order to fill the gaps found ([3672](https://github.com/stellar/go/pull/3672)). * Performance improvement: Captive Core now reuses bucket files whenever it finds existing ones in the corresponding `--captive-core-storage-path` (introduced in [v2.1.0](#v2.1.0) rather than generating a one-time temporary sub-directory ([3670](https://github.com/stellar/go/pull/3670)). **This feature requires Stellar-Core version 17.1 or later.** * Horizon now monitors the Stellar Core binary on disk (pointed to by `--stellar-core-binary-path`/`STELLAR_CORE_BINARY_PATH`) and restarts its Captive Core subprocess if it detects changes (i.e a more recent file timestamp for the Stellar Core binary) ([3687](https://github.com/stellar/go/pull/3687)). * `POST /transactions` return `503 Service Unavailable` instead of `504 Gateway Timeout` if connected Stellar-Core is out of sync ([3653](https://github.com/stellar/go/pull/3653)). @@ -520,13 +672,13 @@ This is a minor release with no DB Schema migrations nor explicit state rebuild. ### DB State Migration -* This release comes with a small DB schema change (new multiplexed-account-related columns are incorporated). It should not take more than five minutes to run due to new columns being NULL-able. +* This release comes with a small DB schema change (new multiplexed-account-related columns are incorporated). It should not take more than five minutes to run due to new columns being NULL-able. ### Deprecations * Deprecate `--captive-core-config-append-path` in favor of `--captive-core-config-path`. The difference between the two flags is that `--captive-core-config-path` will validate the configuration file to reject any fields which are not supported by captive core ([3629](https://github.com/stellar/go/pull/3629)). -### New features +### New features * Add more in-depth Prometheus metrics (count & duration) for db queries. ([3597](https://github.com/stellar/go/pull/3597), [3605](https://github.com/stellar/go/pull/3605)) @@ -784,7 +936,7 @@ To solve this it's now possible to start a [`captivecore`](https://github.com/st This patch release fixes a regression introduced in 1.7.0, breaking the `/offers` endpoint. Thus, we recommend upgrading as soon as possible. - + ### Changes * Fix path parameter mismatch in `/offers` endpoint [#2927](https://github.com/stellar/go/pull/2927). @@ -811,7 +963,7 @@ This patch release fixes a regression introduced in 1.7.0, breaking the * Add `--parallel-workers` and `--parallel-job-size` to `horizon db reingest range`. `--parallel-workers` will parallelize reingestion using the supplied number of workers. ([#2724](https://github.com/stellar/go/pull/2724)) * Remove Stellar Core's database dependency for non-ingesting instances of Horizon. ([#2759](https://github.com/stellar/go/pull/2759)) - Horizon doesn't require access to a Stellar Core database if it is only serving HTTP request, this allows the separation of front-end and ingesting instances. + Horizon doesn't require access to a Stellar Core database if it is only serving HTTP request, this allows the separation of front-end and ingesting instances. The following config parameters were removed: - `core-db-max-open-connections` - `core-db-max-idle-connections` diff --git a/services/horizon/Makefile b/services/horizon/Makefile new file mode 100644 index 0000000000..9c5a3a8ddf --- /dev/null +++ b/services/horizon/Makefile @@ -0,0 +1,18 @@ +SUDO := $(shell docker version >/dev/null 2>&1 || echo "sudo") + +ifndef VERSION_STRING + $(error VERSION_STRING environment variable must be set. For example "2.26.0-d2d01d39759f2f315f4af59e4b95700a4def44eb") +endif + +DOCKER_PLATFORM := $(shell docker system info --format '{{.OSType}}/{{.Architecture}}') + +binary-build: + $(SUDO) docker run --platform $(DOCKER_PLATFORM) --rm $(DOCKER_OPTS) -v $(shell pwd)/../../:/go/src/github.com/stellar/go \ + --pull always \ + --env CGO_ENABLED=0 \ + --env GOFLAGS="-ldflags=-X=github.com/stellar/go/support/app.version=$(VERSION_STRING)" \ + golang:1.20-bullseye \ + /bin/bash -c '\ + git config --global --add safe.directory /go/src/github.com/stellar/go && \ + cd /go/src/github.com/stellar/go && \ + go build -o stellar-horizon -trimpath -v ./services/horizon' diff --git a/services/horizon/README.md b/services/horizon/README.md index cd6eabcbdd..e041f0fc9e 100644 --- a/services/horizon/README.md +++ b/services/horizon/README.md @@ -3,11 +3,14 @@ Horizon is the client facing API server for the [Stellar ecosystem](https://developers.stellar.org/docs/start/introduction/). It acts as the interface between [Stellar Core](https://developers.stellar.org/docs/run-core-node/) and applications that want to access the Stellar network. It allows you to submit transactions to the network, check the status of accounts, subscribe to event streams and more. -## Try it out -See Horizon in action by running your own Stellar node as part of the Stellar [testnet](https://developers.stellar.org/docs/glossary/testnet/). With our Docker quick-start image, you can be running your own fully functional node in around 20 minutes. See the [Quickstart Guide](internal/docs/quickstart.md) to get up and running. +Check out the following resources to get started: +- [Horizon Development Guide](internal/docs/GUIDE_FOR_DEVELOPERS.md): Instructions for building and developing Horizon. Covers setup, building, testing, and contributing. Also contains some helpful notes and context for Horizon developers. +- [Quickstart Guide](https://github.com/stellar/quickstart): An external tool provided from a separate repository. It builds a docker image which can be used for running the stellar stack including Horizon locally for evaluation and testing situations. A great way to observe a reference runtime deployment, to see how everything fits together. +- [Horizon Testing Guide](internal/docs/TESTING_NOTES.md): Details on how to test Horizon, including unit tests, integration tests, and end-to-end tests. +- [Horizon SDK and API Guide](internal/docs/SDK_API_GUIDE.md): Documentation on the Horizon SDKs, APIs, resources, and examples. Useful for developers building on top of Horizon. ## Run a production server -If you're an administrator planning to run a production instance of Horizon as part of the public Stellar network, check out the detailed [Administration Guide](internal/docs/admin.md). It covers installation, monitoring, error scenarios and more. +If you're an administrator planning to run a production instance of Horizon as part of the public Stellar network, you should check out the instructions on our public developer docs - [Run an API Server](https://developers.stellar.org/docs/run-api-server/). It covers installation, monitoring, error scenarios and more. ## Contributing -As an open source project, development of Horizon is public, and you can help! We welcome new issue reports, documentation and bug fixes, and contributions that further the project roadmap. The [Development Guide](internal/docs/developing.md) will show you how to build Horizon, see what's going on behind the scenes, and set up an effective develop-test-push cycle so that you can get your work incorporated quickly. +As an open source project, development of Horizon is public, and you can help! We welcome new issue reports, documentation and bug fixes, and contributions that further the project roadmap. The [Development Guide](internal/docs/GUIDE_FOR_DEVELOPERS.md) will show you how to build Horizon, see what's going on behind the scenes, and set up an effective develop-test-push cycle so that you can get your work incorporated quickly. diff --git a/services/horizon/cmd/db.go b/services/horizon/cmd/db.go index c73c9afac0..a83597932e 100644 --- a/services/horizon/cmd/db.go +++ b/services/horizon/cmd/db.go @@ -8,6 +8,7 @@ import ( "log" "os" "strconv" + "strings" "github.com/spf13/cobra" "github.com/spf13/viper" @@ -32,15 +33,28 @@ var dbMigrateCmd = &cobra.Command{ Short: "commands to run schema migrations on horizon's postgres db", } -func requireAndSetFlag(name string) error { - for _, flag := range flags { - if flag.Name == name { +func requireAndSetFlags(names ...string) error { + set := map[string]bool{} + for _, name := range names { + set[name] = true + } + for _, flag := range globalFlags { + if set[flag.Name] { flag.Require() - flag.SetValue() - return nil + if err := flag.SetValue(); err != nil { + return err + } + delete(set, flag.Name) } } - return fmt.Errorf("could not find %s flag", name) + if len(set) == 0 { + return nil + } + var missing []string + for name := range set { + missing = append(missing, name) + } + return fmt.Errorf("could not find %s flags", strings.Join(missing, ",")) } var dbInitCmd = &cobra.Command{ @@ -48,11 +62,11 @@ var dbInitCmd = &cobra.Command{ Short: "install schema", Long: "init initializes the postgres database used by horizon.", RunE: func(cmd *cobra.Command, args []string) error { - if err := requireAndSetFlag(horizon.DatabaseURLFlagName); err != nil { + if err := requireAndSetFlags(horizon.DatabaseURLFlagName, horizon.IngestFlagName); err != nil { return err } - db, err := sql.Open("postgres", config.DatabaseURL) + db, err := sql.Open("postgres", globalConfig.DatabaseURL) if err != nil { return err } @@ -72,7 +86,12 @@ var dbInitCmd = &cobra.Command{ } func migrate(dir schema.MigrateDir, count int) error { - dbConn, err := db.Open("postgres", config.DatabaseURL) + if !globalConfig.Ingest { + log.Println("Skipping migrations because ingest flag is not enabled") + return nil + } + + dbConn, err := db.Open("postgres", globalConfig.DatabaseURL) if err != nil { return err } @@ -95,11 +114,11 @@ var dbMigrateDownCmd = &cobra.Command{ Short: "run downwards db schema migrations", Long: "performs a downards schema migration command", RunE: func(cmd *cobra.Command, args []string) error { - if err := requireAndSetFlag(horizon.DatabaseURLFlagName); err != nil { + if err := requireAndSetFlags(horizon.DatabaseURLFlagName, horizon.IngestFlagName); err != nil { return err } - // Only allow invokations with 1 args. + // Only allow invocations with 1 args. if len(args) != 1 { return ErrUsage{cmd} } @@ -119,11 +138,11 @@ var dbMigrateRedoCmd = &cobra.Command{ Short: "redo db schema migrations", Long: "performs a redo schema migration command", RunE: func(cmd *cobra.Command, args []string) error { - if err := requireAndSetFlag(horizon.DatabaseURLFlagName); err != nil { + if err := requireAndSetFlags(horizon.DatabaseURLFlagName, horizon.IngestFlagName); err != nil { return err } - // Only allow invokations with 1 args. + // Only allow invocations with 1 args. if len(args) != 1 { return ErrUsage{cmd} } @@ -143,17 +162,17 @@ var dbMigrateStatusCmd = &cobra.Command{ Short: "print current database migration status", Long: "print current database migration status", RunE: func(cmd *cobra.Command, args []string) error { - if err := requireAndSetFlag(horizon.DatabaseURLFlagName); err != nil { + if err := requireAndSetFlags(horizon.DatabaseURLFlagName); err != nil { return err } - // Only allow invokations with 0 args. + // Only allow invocations with 0 args. if len(args) != 0 { fmt.Println(args) return ErrUsage{cmd} } - dbConn, err := db.Open("postgres", config.DatabaseURL) + dbConn, err := db.Open("postgres", globalConfig.DatabaseURL) if err != nil { return err } @@ -173,11 +192,11 @@ var dbMigrateUpCmd = &cobra.Command{ Short: "run upwards db schema migrations", Long: "performs an upwards schema migration command", RunE: func(cmd *cobra.Command, args []string) error { - if err := requireAndSetFlag(horizon.DatabaseURLFlagName); err != nil { + if err := requireAndSetFlags(horizon.DatabaseURLFlagName, horizon.IngestFlagName); err != nil { return err } - // Only allow invokations with 0-1 args. + // Only allow invocations with 0-1 args. if len(args) > 1 { return ErrUsage{cmd} } @@ -201,7 +220,7 @@ var dbReapCmd = &cobra.Command{ Short: "reaps (i.e. removes) any reapable history data", Long: "reap removes any historical data that is earlier than the configured retention cutoff", RunE: func(cmd *cobra.Command, args []string) error { - app, err := horizon.NewAppFromFlags(config, flags) + app, err := horizon.NewAppFromFlags(globalConfig, globalFlags) if err != nil { return err } @@ -302,7 +321,7 @@ var dbReingestRangeCmd = &cobra.Command{ } } - err := horizon.ApplyFlags(config, flags, horizon.ApplyOptions{RequireCaptiveCoreConfig: false, AlwaysIngest: true}) + err := horizon.ApplyFlags(globalConfig, globalFlags, horizon.ApplyOptions{RequireCaptiveCoreFullConfig: false, AlwaysIngest: true}) if err != nil { return err } @@ -310,7 +329,7 @@ var dbReingestRangeCmd = &cobra.Command{ []history.LedgerRange{{StartSequence: argsUInt32[0], EndSequence: argsUInt32[1]}}, reingestForce, parallelWorkers, - *config, + *globalConfig, ) }, } @@ -350,26 +369,26 @@ var dbFillGapsCmd = &cobra.Command{ withRange = true } - err := horizon.ApplyFlags(config, flags, horizon.ApplyOptions{RequireCaptiveCoreConfig: false, AlwaysIngest: true}) + err := horizon.ApplyFlags(globalConfig, globalFlags, horizon.ApplyOptions{RequireCaptiveCoreFullConfig: false, AlwaysIngest: true}) if err != nil { return err } var gaps []history.LedgerRange if withRange { - gaps, err = runDBDetectGapsInRange(*config, uint32(start), uint32(end)) + gaps, err = runDBDetectGapsInRange(*globalConfig, uint32(start), uint32(end)) if err != nil { return err } hlog.Infof("found gaps %v within range [%v, %v]", gaps, start, end) } else { - gaps, err = runDBDetectGaps(*config) + gaps, err = runDBDetectGaps(*globalConfig) if err != nil { return err } hlog.Infof("found gaps %v", gaps) } - return runDBReingestRange(gaps, reingestForce, parallelWorkers, *config) + return runDBReingestRange(gaps, reingestForce, parallelWorkers, *globalConfig) }, } @@ -380,14 +399,18 @@ func runDBReingestRange(ledgerRanges []history.LedgerRange, reingestForce bool, return errors.New("--force is incompatible with --parallel-workers > 1") } + maxLedgersPerFlush := ingest.MaxLedgersPerFlush + if parallelJobSize < maxLedgersPerFlush { + maxLedgersPerFlush = parallelJobSize + } + ingestConfig := ingest.Config{ NetworkPassphrase: config.NetworkPassphrase, - HistoryArchiveURL: config.HistoryArchiveURLs[0], + HistoryArchiveURLs: config.HistoryArchiveURLs, CheckpointFrequency: config.CheckpointFrequency, ReingestEnabled: true, MaxReingestRetries: int(retries), ReingestRetryBackoffSeconds: int(retryBackoffSeconds), - EnableCaptiveCore: config.EnableCaptiveCoreIngestion, CaptiveCoreBinaryPath: config.CaptiveCoreBinaryPath, CaptiveCoreConfigUseDB: config.CaptiveCoreConfigUseDB, RemoteCaptiveCoreURL: config.RemoteCaptiveCoreURL, @@ -397,22 +420,13 @@ func runDBReingestRange(ledgerRanges []history.LedgerRange, reingestForce bool, StellarCoreURL: config.StellarCoreURL, RoundingSlippageFilter: config.RoundingSlippageFilter, EnableIngestionFiltering: config.EnableIngestionFiltering, + MaxLedgerPerFlush: maxLedgersPerFlush, } if ingestConfig.HistorySession, err = db.Open("postgres", config.DatabaseURL); err != nil { return fmt.Errorf("cannot open Horizon DB: %v", err) } - if !config.EnableCaptiveCoreIngestion { - if config.StellarCoreDatabaseURL == "" { - return fmt.Errorf("flag --%s cannot be empty", horizon.StellarCoreDBURLFlagName) - } - if ingestConfig.CoreSession, err = db.Open("postgres", config.StellarCoreDatabaseURL); err != nil { - ingestConfig.HistorySession.Close() - return fmt.Errorf("cannot open Core DB: %v", err) - } - } - if parallelWorkers > 1 { system, systemErr := ingest.NewParallelSystems(ingestConfig, parallelWorkers) if systemErr != nil { @@ -453,14 +467,14 @@ var dbDetectGapsCmd = &cobra.Command{ Short: "detects ingestion gaps in Horizon's database", Long: "detects ingestion gaps in Horizon's database and prints a list of reingest commands needed to fill the gaps", RunE: func(cmd *cobra.Command, args []string) error { - if err := requireAndSetFlag(horizon.DatabaseURLFlagName); err != nil { + if err := requireAndSetFlags(horizon.DatabaseURLFlagName); err != nil { return err } if len(args) != 0 { return ErrUsage{cmd} } - gaps, err := runDBDetectGaps(*config) + gaps, err := runDBDetectGaps(*globalConfig) if err != nil { return err } diff --git a/services/horizon/cmd/ingest.go b/services/horizon/cmd/ingest.go index fa7d712153..e2d38977ab 100644 --- a/services/horizon/cmd/ingest.go +++ b/services/horizon/cmd/ingest.go @@ -23,9 +23,30 @@ var ingestCmd = &cobra.Command{ Short: "ingestion related commands", } +var ingestBuildStateSequence uint32 +var ingestBuildStateSkipChecks bool var ingestVerifyFrom, ingestVerifyTo, ingestVerifyDebugServerPort uint32 var ingestVerifyState bool +var ingestBuildStateCmdOpts = []*support.ConfigOption{ + { + Name: "sequence", + ConfigKey: &ingestBuildStateSequence, + OptType: types.Uint32, + Required: true, + FlagDefault: uint32(0), + Usage: "checkpoint ledger sequence", + }, + { + Name: "skip-checks", + ConfigKey: &ingestBuildStateSkipChecks, + OptType: types.Bool, + Required: false, + FlagDefault: false, + Usage: "[optional] set to skip protocol version and bucket list hash verification, can speed up the process because does not require a running Stellar-Core", + }, +} + var ingestVerifyRangeCmdOpts = []*support.ConfigOption{ { Name: "from", @@ -73,7 +94,7 @@ var ingestVerifyRangeCmd = &cobra.Command{ co.SetValue() } - if err := horizon.ApplyFlags(config, flags, horizon.ApplyOptions{RequireCaptiveCoreConfig: false, AlwaysIngest: true}); err != nil { + if err := horizon.ApplyFlags(globalConfig, globalFlags, horizon.ApplyOptions{RequireCaptiveCoreFullConfig: false, AlwaysIngest: true}); err != nil { return err } @@ -90,44 +111,31 @@ var ingestVerifyRangeCmd = &cobra.Command{ }() } - horizonSession, err := db.Open("postgres", config.DatabaseURL) + horizonSession, err := db.Open("postgres", globalConfig.DatabaseURL) if err != nil { return fmt.Errorf("cannot open Horizon DB: %v", err) } - mngr := historyarchive.NewCheckpointManager(config.CheckpointFrequency) + mngr := historyarchive.NewCheckpointManager(globalConfig.CheckpointFrequency) if !mngr.IsCheckpoint(ingestVerifyFrom) && ingestVerifyFrom != 1 { return fmt.Errorf("`--from` must be a checkpoint ledger") } if ingestVerifyState && !mngr.IsCheckpoint(ingestVerifyTo) { - return fmt.Errorf("`--to` must be a checkpoint ledger when `--verify-state` is set.") + return fmt.Errorf("`--to` must be a checkpoint ledger when `--verify-state` is set") } ingestConfig := ingest.Config{ - NetworkPassphrase: config.NetworkPassphrase, + NetworkPassphrase: globalConfig.NetworkPassphrase, HistorySession: horizonSession, - HistoryArchiveURL: config.HistoryArchiveURLs[0], - EnableCaptiveCore: config.EnableCaptiveCoreIngestion, - CaptiveCoreBinaryPath: config.CaptiveCoreBinaryPath, - CaptiveCoreConfigUseDB: config.CaptiveCoreConfigUseDB, - RemoteCaptiveCoreURL: config.RemoteCaptiveCoreURL, - CheckpointFrequency: config.CheckpointFrequency, - CaptiveCoreToml: config.CaptiveCoreToml, - CaptiveCoreStoragePath: config.CaptiveCoreStoragePath, - RoundingSlippageFilter: config.RoundingSlippageFilter, - EnableIngestionFiltering: config.EnableIngestionFiltering, - } - - if !ingestConfig.EnableCaptiveCore { - if config.StellarCoreDatabaseURL == "" { - return fmt.Errorf("flag --%s cannot be empty", horizon.StellarCoreDBURLFlagName) - } - - coreSession, dbErr := db.Open("postgres", config.StellarCoreDatabaseURL) - if dbErr != nil { - return fmt.Errorf("cannot open Core DB: %v", dbErr) - } - ingestConfig.CoreSession = coreSession + HistoryArchiveURLs: globalConfig.HistoryArchiveURLs, + CaptiveCoreBinaryPath: globalConfig.CaptiveCoreBinaryPath, + CaptiveCoreConfigUseDB: globalConfig.CaptiveCoreConfigUseDB, + RemoteCaptiveCoreURL: globalConfig.RemoteCaptiveCoreURL, + CheckpointFrequency: globalConfig.CheckpointFrequency, + CaptiveCoreToml: globalConfig.CaptiveCoreToml, + CaptiveCoreStoragePath: globalConfig.CaptiveCoreStoragePath, + RoundingSlippageFilter: globalConfig.RoundingSlippageFilter, + EnableIngestionFiltering: globalConfig.EnableIngestionFiltering, } system, err := ingest.NewSystem(ingestConfig) @@ -182,11 +190,11 @@ var ingestStressTestCmd = &cobra.Command{ co.SetValue() } - if err := horizon.ApplyFlags(config, flags, horizon.ApplyOptions{RequireCaptiveCoreConfig: false, AlwaysIngest: true}); err != nil { + if err := horizon.ApplyFlags(globalConfig, globalFlags, horizon.ApplyOptions{RequireCaptiveCoreFullConfig: false, AlwaysIngest: true}); err != nil { return err } - horizonSession, err := db.Open("postgres", config.DatabaseURL) + horizonSession, err := db.Open("postgres", globalConfig.DatabaseURL) if err != nil { return fmt.Errorf("cannot open Horizon DB: %v", err) } @@ -200,27 +208,13 @@ var ingestStressTestCmd = &cobra.Command{ } ingestConfig := ingest.Config{ - NetworkPassphrase: config.NetworkPassphrase, + NetworkPassphrase: globalConfig.NetworkPassphrase, HistorySession: horizonSession, - HistoryArchiveURL: config.HistoryArchiveURLs[0], - EnableCaptiveCore: config.EnableCaptiveCoreIngestion, - RoundingSlippageFilter: config.RoundingSlippageFilter, - } - - if config.EnableCaptiveCoreIngestion { - ingestConfig.CaptiveCoreBinaryPath = config.CaptiveCoreBinaryPath - ingestConfig.RemoteCaptiveCoreURL = config.RemoteCaptiveCoreURL - ingestConfig.CaptiveCoreConfigUseDB = config.CaptiveCoreConfigUseDB - } else { - if config.StellarCoreDatabaseURL == "" { - return fmt.Errorf("flag --%s cannot be empty", horizon.StellarCoreDBURLFlagName) - } - - coreSession, dbErr := db.Open("postgres", config.StellarCoreDatabaseURL) - if dbErr != nil { - return fmt.Errorf("cannot open Core DB: %v", dbErr) - } - ingestConfig.CoreSession = coreSession + HistoryArchiveURLs: globalConfig.HistoryArchiveURLs, + RoundingSlippageFilter: globalConfig.RoundingSlippageFilter, + CaptiveCoreBinaryPath: globalConfig.CaptiveCoreBinaryPath, + RemoteCaptiveCoreURL: globalConfig.RemoteCaptiveCoreURL, + CaptiveCoreConfigUseDB: globalConfig.CaptiveCoreConfigUseDB, } system, err := ingest.NewSystem(ingestConfig) @@ -246,16 +240,16 @@ var ingestTriggerStateRebuildCmd = &cobra.Command{ Short: "updates a database to trigger state rebuild, state will be rebuilt by a running Horizon instance, DO NOT RUN production DB, some endpoints will be unavailable until state is rebuilt", RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - if err := horizon.ApplyFlags(config, flags, horizon.ApplyOptions{RequireCaptiveCoreConfig: false, AlwaysIngest: true}); err != nil { + if err := horizon.ApplyFlags(globalConfig, globalFlags, horizon.ApplyOptions{RequireCaptiveCoreFullConfig: false, AlwaysIngest: true}); err != nil { return err } - horizonSession, err := db.Open("postgres", config.DatabaseURL) + horizonSession, err := db.Open("postgres", globalConfig.DatabaseURL) if err != nil { return fmt.Errorf("cannot open Horizon DB: %v", err) } - historyQ := &history.Q{horizonSession} + historyQ := &history.Q{SessionInterface: horizonSession} if err := historyQ.UpdateIngestVersion(ctx, 0); err != nil { return fmt.Errorf("cannot trigger state rebuild: %v", err) } @@ -270,16 +264,16 @@ var ingestInitGenesisStateCmd = &cobra.Command{ Short: "ingests genesis state (ledger 1)", RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - if err := horizon.ApplyFlags(config, flags, horizon.ApplyOptions{RequireCaptiveCoreConfig: false, AlwaysIngest: true}); err != nil { + if err := horizon.ApplyFlags(globalConfig, globalFlags, horizon.ApplyOptions{RequireCaptiveCoreFullConfig: false, AlwaysIngest: true}); err != nil { return err } - horizonSession, err := db.Open("postgres", config.DatabaseURL) + horizonSession, err := db.Open("postgres", globalConfig.DatabaseURL) if err != nil { return fmt.Errorf("cannot open Horizon DB: %v", err) } - historyQ := &history.Q{horizonSession} + historyQ := &history.Q{SessionInterface: horizonSession} lastIngestedLedger, err := historyQ.GetLastLedgerIngestNonBlocking(ctx) if err != nil { @@ -291,28 +285,14 @@ var ingestInitGenesisStateCmd = &cobra.Command{ } ingestConfig := ingest.Config{ - NetworkPassphrase: config.NetworkPassphrase, + NetworkPassphrase: globalConfig.NetworkPassphrase, HistorySession: horizonSession, - HistoryArchiveURL: config.HistoryArchiveURLs[0], - EnableCaptiveCore: config.EnableCaptiveCoreIngestion, - CheckpointFrequency: config.CheckpointFrequency, - RoundingSlippageFilter: config.RoundingSlippageFilter, - EnableIngestionFiltering: config.EnableIngestionFiltering, - } - - if config.EnableCaptiveCoreIngestion { - ingestConfig.CaptiveCoreBinaryPath = config.CaptiveCoreBinaryPath - ingestConfig.CaptiveCoreConfigUseDB = config.CaptiveCoreConfigUseDB - } else { - if config.StellarCoreDatabaseURL == "" { - return fmt.Errorf("flag --%s cannot be empty", horizon.StellarCoreDBURLFlagName) - } - - coreSession, dbErr := db.Open("postgres", config.StellarCoreDatabaseURL) - if dbErr != nil { - return fmt.Errorf("cannot open Core DB: %v", dbErr) - } - ingestConfig.CoreSession = coreSession + HistoryArchiveURLs: globalConfig.HistoryArchiveURLs, + CheckpointFrequency: globalConfig.CheckpointFrequency, + RoundingSlippageFilter: globalConfig.RoundingSlippageFilter, + EnableIngestionFiltering: globalConfig.EnableIngestionFiltering, + CaptiveCoreBinaryPath: globalConfig.CaptiveCoreBinaryPath, + CaptiveCoreConfigUseDB: globalConfig.CaptiveCoreConfigUseDB, } system, err := ingest.NewSystem(ingestConfig) @@ -330,6 +310,75 @@ var ingestInitGenesisStateCmd = &cobra.Command{ }, } +var ingestBuildStateCmd = &cobra.Command{ + Use: "build-state", + Short: "builds state at a given checkpoint. warning! requires clean DB.", + Long: "useful for debugging or starting Horizon at specific checkpoint.", + RunE: func(cmd *cobra.Command, args []string) error { + for _, co := range ingestBuildStateCmdOpts { + if err := co.RequireE(); err != nil { + return err + } + co.SetValue() + } + + if err := horizon.ApplyFlags(globalConfig, globalFlags, horizon.ApplyOptions{RequireCaptiveCoreFullConfig: false, AlwaysIngest: true}); err != nil { + return err + } + + horizonSession, err := db.Open("postgres", globalConfig.DatabaseURL) + if err != nil { + return fmt.Errorf("cannot open Horizon DB: %v", err) + } + + historyQ := &history.Q{SessionInterface: horizonSession} + + lastIngestedLedger, err := historyQ.GetLastLedgerIngestNonBlocking(context.Background()) + if err != nil { + return fmt.Errorf("cannot get last ledger value: %v", err) + } + + if lastIngestedLedger != 0 { + return fmt.Errorf("cannot run on non-empty DB") + } + + mngr := historyarchive.NewCheckpointManager(globalConfig.CheckpointFrequency) + if !mngr.IsCheckpoint(ingestBuildStateSequence) && ingestBuildStateSequence != 1 { + return fmt.Errorf("`--sequence` must be a checkpoint ledger") + } + + ingestConfig := ingest.Config{ + NetworkPassphrase: globalConfig.NetworkPassphrase, + HistorySession: horizonSession, + HistoryArchiveURLs: globalConfig.HistoryArchiveURLs, + CaptiveCoreBinaryPath: globalConfig.CaptiveCoreBinaryPath, + CaptiveCoreConfigUseDB: globalConfig.CaptiveCoreConfigUseDB, + RemoteCaptiveCoreURL: globalConfig.RemoteCaptiveCoreURL, + CheckpointFrequency: globalConfig.CheckpointFrequency, + CaptiveCoreToml: globalConfig.CaptiveCoreToml, + CaptiveCoreStoragePath: globalConfig.CaptiveCoreStoragePath, + RoundingSlippageFilter: globalConfig.RoundingSlippageFilter, + EnableIngestionFiltering: globalConfig.EnableIngestionFiltering, + } + + system, err := ingest.NewSystem(ingestConfig) + if err != nil { + return err + } + + err = system.BuildState( + ingestBuildStateSequence, + ingestBuildStateSkipChecks, + ) + if err != nil { + return err + } + + log.Info("State built successfully!") + return nil + }, +} + func init() { for _, co := range ingestVerifyRangeCmdOpts { err := co.Init(ingestVerifyRangeCmd) @@ -345,6 +394,13 @@ func init() { } } + for _, co := range ingestBuildStateCmdOpts { + err := co.Init(ingestBuildStateCmd) + if err != nil { + log.Fatal(err.Error()) + } + } + viper.BindPFlags(ingestVerifyRangeCmd.PersistentFlags()) RootCmd.AddCommand(ingestCmd) @@ -353,5 +409,6 @@ func init() { ingestStressTestCmd, ingestTriggerStateRebuildCmd, ingestInitGenesisStateCmd, + ingestBuildStateCmd, ) } diff --git a/services/horizon/cmd/record_metrics.go b/services/horizon/cmd/record_metrics.go index cd4f335da1..fb6244b76b 100644 --- a/services/horizon/cmd/record_metrics.go +++ b/services/horizon/cmd/record_metrics.go @@ -19,7 +19,7 @@ var recordMetricsCmd = &cobra.Command{ Short: "records `/metrics` on admin port for debuging purposes", Long: "", RunE: func(cmd *cobra.Command, args []string) error { - if err := horizon.ApplyFlags(config, flags, horizon.ApplyOptions{}); err != nil { + if err := horizon.ApplyFlags(globalConfig, globalFlags, horizon.ApplyOptions{}); err != nil { return err } @@ -50,7 +50,7 @@ var recordMetricsCmd = &cobra.Command{ time.Duration(time.Duration(scrapeIntervalSeconds*(scrapesCount-i))*time.Second), ) - metricsResponse, err := client.Get(fmt.Sprintf("http://127.0.0.1:%d/metrics", config.AdminPort)) + metricsResponse, err := client.Get(fmt.Sprintf("http://127.0.0.1:%d/metrics", globalConfig.AdminPort)) if err != nil { return errors.Wrap(err, "Error fetching metrics. Is admin server running?") } diff --git a/services/horizon/cmd/root.go b/services/horizon/cmd/root.go index a387a8e90f..d2900496d4 100644 --- a/services/horizon/cmd/root.go +++ b/services/horizon/cmd/root.go @@ -6,25 +6,32 @@ import ( "github.com/spf13/cobra" horizon "github.com/stellar/go/services/horizon/internal" + "github.com/stellar/go/support/config" ) var ( - config, flags = horizon.Flags() + globalConfig, globalFlags = horizon.Flags() RootCmd = &cobra.Command{ Use: "horizon", Short: "client-facing api server for the Stellar network", SilenceErrors: true, SilenceUsage: true, - Long: "Client-facing API server for the Stellar network. It acts as the interface between Stellar Core and applications that want to access the Stellar network. It allows you to submit transactions to the network, check the status of accounts, subscribe to event streams and more.", + Long: "Client-facing API server for the Stellar network. It acts as the interface between Stellar Core " + + "and applications that want to access the Stellar network. It allows you to submit transactions to the " + + "network, check the status of accounts, subscribe to event streams and more.\n" + + "DEPRECATED - the use of command-line flags has been deprecated in favor of environment variables. Please" + + "consult our Configuring section in the developer documentation on how to use them - https://developers.stellar.org/docs/run-api-server/configuring", RunE: func(cmd *cobra.Command, args []string) error { - app, err := horizon.NewAppFromFlags(config, flags) + app, err := horizon.NewAppFromFlags(globalConfig, globalFlags) if err != nil { return err } return app.Serve() }, } + originalHelpFunc = RootCmd.HelpFunc() + originalUsageFunc = RootCmd.UsageFunc() ) // ErrUsage indicates we should print the usage string and exit with code 1 @@ -36,7 +43,7 @@ func (e ErrUsage) Error() string { return e.cmd.UsageString() } -// Indicates we want to exit with a specific error code without printing an error. +// ErrExitCode Indicates we want to exit with a specific error code without printing an error. type ErrExitCode int func (e ErrExitCode) Error() string { @@ -44,7 +51,20 @@ func (e ErrExitCode) Error() string { } func init() { - err := flags.Init(RootCmd) + + // override the default help output, apply further filtering on which global flags + // will be shown on the help outout dependent on the command help was issued upon. + RootCmd.SetHelpFunc(func(c *cobra.Command, args []string) { + enableGlobalOptionsInHelp(c, globalFlags) + originalHelpFunc(c, args) + }) + + RootCmd.SetUsageFunc(func(c *cobra.Command) error { + enableGlobalOptionsInHelp(c, globalFlags) + return originalUsageFunc(c) + }) + + err := globalFlags.Init(RootCmd) if err != nil { stdLog.Fatal(err.Error()) } @@ -53,3 +73,45 @@ func init() { func Execute() error { return RootCmd.Execute() } + +func enableGlobalOptionsInHelp(cmd *cobra.Command, cos config.ConfigOptions) { + for _, co := range cos { + if co.Hidden { + // this options was configured statically to be hidden + // Init() has already set that once, leave it as-is. + continue + } + + // we don't want' to display global flags in help output + // if no sub-command context given yet, i.e. just '-h' was used + // or there are subcomands required to use. + if cmd.Parent() == nil || cmd.HasAvailableSubCommands() { + co.ToggleHidden(true) + continue + } + + if len(co.UsedInCommands) > 0 && + !contains(co.UsedInCommands, cmd) { + co.ToggleHidden(true) + } else { + co.ToggleHidden(false) + } + } +} + +// check if this command or any of it's sub-level parents match +// supportedCommands +func contains(supportedCommands []string, cmd *cobra.Command) bool { + for _, supportedCommand := range supportedCommands { + if supportedCommand == cmd.Name() { + return true + } + } + + // don't do inheritance matching on the top most sub-commands. + // they are second level deep, the horizon itself is top level. + if cmd.Parent() != nil && cmd.Parent().Parent() != nil { + return contains(supportedCommands, cmd.Parent()) + } + return false +} diff --git a/services/horizon/cmd/serve.go b/services/horizon/cmd/serve.go index 8e06855d3c..21a34da3ad 100644 --- a/services/horizon/cmd/serve.go +++ b/services/horizon/cmd/serve.go @@ -10,7 +10,7 @@ var serveCmd = &cobra.Command{ Short: "run horizon server", Long: "serve initializes then starts the horizon HTTP server", RunE: func(cmd *cobra.Command, args []string) error { - app, err := horizon.NewAppFromFlags(config, flags) + app, err := horizon.NewAppFromFlags(globalConfig, globalFlags) if err != nil { return err } diff --git a/services/horizon/docker/Dockerfile b/services/horizon/docker/Dockerfile index 1b20729761..3c090d203c 100644 --- a/services/horizon/docker/Dockerfile +++ b/services/horizon/docker/Dockerfile @@ -1,12 +1,20 @@ FROM ubuntu:focal ARG VERSION +ARG STELLAR_CORE_VERSION ARG DEBIAN_FRONTEND=noninteractive +ARG ALLOW_CORE_UNSTABLE=no RUN apt-get update && apt-get install -y wget apt-transport-https gnupg2 && \ wget -qO /etc/apt/trusted.gpg.d/SDF.asc https://apt.stellar.org/SDF.asc && \ echo "deb https://apt.stellar.org focal stable" | tee -a /etc/apt/sources.list.d/SDF.list && \ - apt-get update && apt-cache madison stellar-horizon stellar-core && apt-get install -y stellar-horizon=${VERSION} stellar-core && \ + if [ "${ALLOW_CORE_UNSTABLE}" = "yes" ]; then echo "deb https://apt.stellar.org focal unstable" | tee -a /etc/apt/sources.list.d/SDF.list; fi && \ + cat /etc/apt/sources.list.d/SDF.list && \ + apt-get update && apt-cache madison stellar-core && eval "apt-get install -y stellar-core${STELLAR_CORE_VERSION+=$STELLAR_CORE_VERSION}" && \ + if [ "${ALLOW_CORE_UNSTABLE}" = "yes" ]; then sed -i '/unstable/d' /etc/apt/sources.list.d/SDF.list; fi && \ + cat /etc/apt/sources.list.d/SDF.list && \ + echo "deb https://apt.stellar.org focal testing" | tee -a /etc/apt/sources.list.d/SDF.list && \ + apt-get update && apt-cache madison stellar-horizon && apt-get install -y stellar-horizon=${VERSION} && \ apt-get clean && rm -rf /var/lib/apt/lists/* /var/log/*.log /var/log/*/*.log EXPOSE 8000 diff --git a/services/horizon/docker/Dockerfile.dev b/services/horizon/docker/Dockerfile.dev index 357f08188c..1d1be8d688 100644 --- a/services/horizon/docker/Dockerfile.dev +++ b/services/horizon/docker/Dockerfile.dev @@ -1,13 +1,14 @@ -FROM golang:1.18 AS builder +FROM golang:1.20-bullseye AS builder +ARG VERSION="devel" WORKDIR /go/src/github.com/stellar/go COPY go.mod go.sum ./ RUN go mod download COPY . ./ +ENV GOFLAGS="-ldflags=-X=github.com/stellar/go/support/app.version=${VERSION}-(built-from-source)" RUN go install github.com/stellar/go/services/horizon -RUN go install github.com/stellar/go/exp/services/captivecore -FROM ubuntu:20.04 +FROM ubuntu:22.04 ARG STELLAR_CORE_VERSION ENV STELLAR_CORE_VERSION=${STELLAR_CORE_VERSION:-*} ENV STELLAR_CORE_BINARY_PATH /usr/bin/stellar-core @@ -22,7 +23,6 @@ RUN apt-get update && apt-get install -y stellar-core=${STELLAR_CORE_VERSION} RUN apt-get clean COPY --from=builder /go/bin/horizon ./ -COPY --from=builder /go/bin/captivecore ./ ENTRYPOINT ["./horizon"] diff --git a/services/horizon/docker/Makefile b/services/horizon/docker/Makefile index a48ac13028..32074453f0 100644 --- a/services/horizon/docker/Makefile +++ b/services/horizon/docker/Makefile @@ -4,15 +4,26 @@ SUDO := $(shell docker version >/dev/null 2>&1 || echo "sudo") BUILD_DATE := $(shell date -u +%FT%TZ) TAG ?= stellar/stellar-horizon:$(VERSION) +ifeq ($(ALLOW_CORE_UNSTABLE),yes) + TAG := $(TAG)-UNSTABLE +endif docker-build: ifndef VERSION $(error VERSION environment variable must be set. For example VERSION=2.4.1-101 ) endif +ifndef STELLAR_CORE_VERSION $(SUDO) docker build --pull $(DOCKER_OPTS) \ --label org.opencontainers.image.created="$(BUILD_DATE)" \ - --build-arg VERSION=$(VERSION) \ + --build-arg VERSION=$(VERSION) --build-arg ALLOW_CORE_UNSTABLE=$(ALLOW_CORE_UNSTABLE) \ -t $(TAG) . +else + $(SUDO) docker build --pull $(DOCKER_OPTS) \ + --label org.opencontainers.image.created="$(BUILD_DATE)" \ + --build-arg VERSION=$(VERSION) --build-arg STELLAR_CORE_VERSION=$(STELLAR_CORE_VERSION) \ + --build-arg ALLOW_CORE_UNSTABLE=$(ALLOW_CORE_UNSTABLE) \ + -t $(TAG) . +endif docker-push: ifndef TAG diff --git a/services/horizon/docker/README.md b/services/horizon/docker/README.md deleted file mode 100644 index 04439bb8dd..0000000000 --- a/services/horizon/docker/README.md +++ /dev/null @@ -1,97 +0,0 @@ -# Overview - -Files related to docker and docker-compose -* `Dockerfile` and `Makefile` - used to build the official, package-based docker image for stellar-horizon -* `Dockerfile.dev` - used with docker-compose - -# Running Stellar with Docker Compose - -## Dependencies - -The only dependency you will need to install is [Docker](https://www.docker.com/products/docker-desktop). - -## Start script - -[start.sh](./start.sh) will setup the env file and run docker-compose to start the Stellar docker containers. Feel free to use this script, otherwise continue with the next two steps. - -The script takes one optional parameter which configures the Stellar network used by the docker containers. If no parameter is supplied, the containers will run on the Stellar test network. - -`./start.sh pubnet` will run the containers on the Stellar public network. - -`./start.sh standalone` will run the containers on a private standalone Stellar network. - -## Run docker-compose - -Run the following command to start all the Stellar docker containers: - -``` -docker-compose up -d --build -``` - -Horizon will be exposed on port 8000. Stellar Core will be exposed on port 11626. The Stellar Core postgres instance will be exposed on port 5641. -The Horizon postgres instance will be exposed on port 5432. - -## Swapping in a local service - -If you're developing a service locally you may want to run that service locally while also being able to interact with the other Stellar components running in Docker. You can do that by stopping the container corresponding to the service you're developing. - -For example, to run Horizon locally from source, you would perform the following steps: - -``` -# stop horizon in docker-compose -docker-compose stop horizon -``` - -Now you can run horizon locally in vscode using the following configuration: -``` - { - "name": "Launch", - "type": "go", - "request": "launch", - "mode": "debug", - "remotePath": "", - "port": 2345, - "host": "127.0.0.1", - "program": "${workspaceRoot}/services/horizon/main.go", - "env": { - "DATABASE_URL": "postgres://postgres@localhost:5432/horizon?sslmode=disable", - "STELLAR_CORE_DATABASE_URL": "postgres://postgres:mysecretpassword@localhost:5641/stellar?sslmode=disable", - "NETWORK_PASSPHRASE": "Test SDF Network ; September 2015", - "STELLAR_CORE_URL": "http://localhost:11626", - "INGEST": "true", - }, - "args": [] - } -``` - -Similarly, to run Stellar core locally from source and have it interact with Horizon in docker, all you need to do is run `docker-compose stop core` before running Stellar core from source. - -## Connecting to the Stellar Public Network - -By default, the Docker Compose file configures Stellar Core to connect to the Stellar test network. If you would like to run the docker containers on the -Stellar public network, run `docker-compose -f docker-compose.yml -f docker-compose.pubnet.yml up -d --build`. - -To run the containers on a private stand-alone network, run `docker-compose -f docker-compose.yml -f docker-compose.standalone.yml up -d --build`. -When you run Stellar Core on a private stand-alone network, an account will be created which will hold 100 billion Lumens. -The seed for the account will be emitted in the Stellar Core logs: - -``` -2020-04-22T18:39:19.248 GD5KD [Ledger INFO] Root account seed: SC5O7VZUXDJ6JBDSZ74DSERXL7W3Y5LTOAMRF7RQRL3TAGAPS7LUVG3L -``` - -When running Horizon on a private stand-alone network, Horizon will not start ingesting until Stellar Core creates its first history archive snapshot. Stellar Core creates snapshots every 64 ledgers, which means ingestion will be delayed until ledger 64. - -When you switch between different networks you will need to clear the Stellar Core and Stellar Horizon databases. You can wipe out the databases by running `docker-compose down --remove-orphans -v`. - -## Using a specific version of Stellar Core - -By default the Docker Compose file is configured to use version 18 of Protocol and Stellar Core. You want the Core version to be at same level as the version horizon repo expects for ingestion. You can specify optional environment variables from the command shell for stating version overrides for either the docker-compose or start.sh invocations. - -PROTOCOL_VERSION=18 // the Stellar Protocol version number -CORE_IMAGE=stellar/stellar-core:18 // the docker hub image:tag -STELLAR_CORE_VERSION=18.1.1-779.ef0f44b44.focal // the apt deb package version from apt.stellar.org - -Example: - -Runs Stellar Protocol and Core version 18, for any mode of testnet,standalone,pubnet -```PROTOCOL_VERSION=18 CORE_IMAGE=stellar/stellar-core:18 STELLAR_CORE_VERSION=18.1.1-779.ef0f44b44.focal ./start.sh [standalone|pubnet]``` diff --git a/services/horizon/docker/captive-core-classic-integration-tests.cfg b/services/horizon/docker/captive-core-classic-integration-tests.cfg new file mode 100644 index 0000000000..ed8ac3ed73 --- /dev/null +++ b/services/horizon/docker/captive-core-classic-integration-tests.cfg @@ -0,0 +1,13 @@ +PEER_PORT=11725 +ARTIFICIALLY_ACCELERATE_TIME_FOR_TESTING=true + +UNSAFE_QUORUM=true +FAILURE_SAFETY=0 + +[[VALIDATORS]] +NAME="local_core" +HOME_DOMAIN="core.local" +# From "SACJC372QBSSKJYTV5A7LWT4NXWHTQO6GHG4QDAVC2XDPX6CNNXFZ4JK" +PUBLIC_KEY="GD5KD2KEZJIGTC63IGW6UMUSMVUVG5IHG64HUTFWCHVZH2N2IBOQN7PS" +ADDRESS="localhost" +QUALITY="MEDIUM" diff --git a/services/horizon/docker/captive-core-integration-tests.cfg b/services/horizon/docker/captive-core-integration-tests.cfg index ed8ac3ed73..275599bacd 100644 --- a/services/horizon/docker/captive-core-integration-tests.cfg +++ b/services/horizon/docker/captive-core-integration-tests.cfg @@ -4,6 +4,12 @@ ARTIFICIALLY_ACCELERATE_TIME_FOR_TESTING=true UNSAFE_QUORUM=true FAILURE_SAFETY=0 +ENABLE_SOROBAN_DIAGNOSTIC_EVENTS=true +# Lower the TTL of persistent ledger entries +# so that ledger entry extension/restoring becomes testeable +TESTING_MINIMUM_PERSISTENT_ENTRY_LIFETIME=10 +TESTING_SOROBAN_HIGH_LIMIT_OVERRIDE=true + [[VALIDATORS]] NAME="local_core" HOME_DOMAIN="core.local" diff --git a/services/horizon/docker/captive-core-integration-tests.soroban-rpc.cfg b/services/horizon/docker/captive-core-integration-tests.soroban-rpc.cfg new file mode 100644 index 0000000000..9a7ad9d769 --- /dev/null +++ b/services/horizon/docker/captive-core-integration-tests.soroban-rpc.cfg @@ -0,0 +1,19 @@ +PEER_PORT=11725 +ARTIFICIALLY_ACCELERATE_TIME_FOR_TESTING=true + +UNSAFE_QUORUM=true +FAILURE_SAFETY=0 + +ENABLE_SOROBAN_DIAGNOSTIC_EVENTS=true +# Lower the TTL of persistent ledger entries +# so that ledger entry extension/restoring becomes testeable +TESTING_MINIMUM_PERSISTENT_ENTRY_LIFETIME=10 +TESTING_SOROBAN_HIGH_LIMIT_OVERRIDE=true + +[[VALIDATORS]] +NAME="local_core" +HOME_DOMAIN="core.local" +# From "SACJC372QBSSKJYTV5A7LWT4NXWHTQO6GHG4QDAVC2XDPX6CNNXFZ4JK" +PUBLIC_KEY="GD5KD2KEZJIGTC63IGW6UMUSMVUVG5IHG64HUTFWCHVZH2N2IBOQN7PS" +ADDRESS="core" +QUALITY="MEDIUM" diff --git a/services/horizon/docker/captive-core-reingest-range-classic-integration-tests.cfg b/services/horizon/docker/captive-core-reingest-range-classic-integration-tests.cfg new file mode 100644 index 0000000000..4902cf8d15 --- /dev/null +++ b/services/horizon/docker/captive-core-reingest-range-classic-integration-tests.cfg @@ -0,0 +1,9 @@ +ARTIFICIALLY_ACCELERATE_TIME_FOR_TESTING=true + +[[VALIDATORS]] +NAME="local_core" +HOME_DOMAIN="core.local" +# From "SACJC372QBSSKJYTV5A7LWT4NXWHTQO6GHG4QDAVC2XDPX6CNNXFZ4JK" +PUBLIC_KEY="GD5KD2KEZJIGTC63IGW6UMUSMVUVG5IHG64HUTFWCHVZH2N2IBOQN7PS" +ADDRESS="localhost" +QUALITY="MEDIUM" diff --git a/services/horizon/docker/captive-core-reingest-range-integration-tests.cfg b/services/horizon/docker/captive-core-reingest-range-integration-tests.cfg index 4902cf8d15..44820f5933 100644 --- a/services/horizon/docker/captive-core-reingest-range-integration-tests.cfg +++ b/services/horizon/docker/captive-core-reingest-range-integration-tests.cfg @@ -1,4 +1,7 @@ ARTIFICIALLY_ACCELERATE_TIME_FOR_TESTING=true +TESTING_SOROBAN_HIGH_LIMIT_OVERRIDE=true +TESTING_MINIMUM_PERSISTENT_ENTRY_LIFETIME=10 +ENABLE_SOROBAN_DIAGNOSTIC_EVENTS=true [[VALIDATORS]] NAME="local_core" diff --git a/services/horizon/docker/captive-core-testnet.cfg b/services/horizon/docker/captive-core-testnet.cfg deleted file mode 100644 index af327834d7..0000000000 --- a/services/horizon/docker/captive-core-testnet.cfg +++ /dev/null @@ -1,29 +0,0 @@ -PEER_PORT=11725 - -UNSAFE_QUORUM=true -FAILURE_SAFETY=1 - -[[HOME_DOMAINS]] -HOME_DOMAIN="testnet.stellar.org" -QUALITY="HIGH" - -[[VALIDATORS]] -NAME="sdf_testnet_1" -HOME_DOMAIN="testnet.stellar.org" -PUBLIC_KEY="GDKXE2OZMJIPOSLNA6N6F2BVCI3O777I2OOC4BV7VOYUEHYX7RTRYA7Y" -ADDRESS="core-testnet1.stellar.org" -HISTORY="curl -sf http://history.stellar.org/prd/core-testnet/core_testnet_001/{0} -o {1}" - -[[VALIDATORS]] -NAME="sdf_testnet_2" -HOME_DOMAIN="testnet.stellar.org" -PUBLIC_KEY="GCUCJTIYXSOXKBSNFGNFWW5MUQ54HKRPGJUTQFJ5RQXZXNOLNXYDHRAP" -ADDRESS="core-testnet2.stellar.org" -HISTORY="curl -sf http://history.stellar.org/prd/core-testnet/core_testnet_002/{0} -o {1}" - -[[VALIDATORS]] -NAME="sdf_testnet_3" -HOME_DOMAIN="testnet.stellar.org" -PUBLIC_KEY="GC2V2EFSXN6SQTWVYA5EPJPBWWIMSD2XQNKUOHGEKB535AQE2I6IXV2Z" -ADDRESS="core-testnet3.stellar.org" -HISTORY="curl -sf http://history.stellar.org/prd/core-testnet/core_testnet_003/{0} -o {1}" \ No newline at end of file diff --git a/services/horizon/docker/core-start.sh b/services/horizon/docker/core-start.sh index b0fadb6bb2..9dd89ba646 100755 --- a/services/horizon/docker/core-start.sh +++ b/services/horizon/docker/core-start.sh @@ -26,4 +26,4 @@ if [ "$1" = "standalone" ]; then popd fi -exec stellar-core run +exec stellar-core run --console diff --git a/services/horizon/docker/docker-compose.integration-tests.soroban-rpc.yml b/services/horizon/docker/docker-compose.integration-tests.soroban-rpc.yml new file mode 100644 index 0000000000..940c340a40 --- /dev/null +++ b/services/horizon/docker/docker-compose.integration-tests.soroban-rpc.yml @@ -0,0 +1,20 @@ +version: '3' +services: + soroban-rpc: + platform: linux/amd64 + image: ${SOROBAN_RPC_IMAGE:-stellar/soroban-rpc} + depends_on: + - core + restart: on-failure + ports: + - "8080:8080" + environment: + - ENDPOINT=:8080 + - NETWORK_PASSPHRASE=Standalone Network ; February 2017 + - CAPTIVE_CORE_CONFIG_PATH=/captive-core.cfg + - HISTORY_ARCHIVE_URLS=http://core:1570 + - CHECKPOINT_FREQUENCY=8 + - LOG_LEVEL=debug + volumes: + - ./captive-core-integration-tests.soroban-rpc.cfg:/captive-core.cfg + diff --git a/services/horizon/docker/docker-compose.integration-tests.yml b/services/horizon/docker/docker-compose.integration-tests.yml index d6dbc1360e..630e8b6b60 100644 --- a/services/horizon/docker/docker-compose.integration-tests.yml +++ b/services/horizon/docker/docker-compose.integration-tests.yml @@ -14,7 +14,8 @@ services: # Note: Please keep the image pinned to an immutable tag matching the Captive Core version. # This avoid implicit updates which break compatibility between # the Core container and captive core. - image: ${CORE_IMAGE:-stellar/stellar-core:19.3.0-1006.9ce6dc4e9.focal} + image: ${CORE_IMAGE:-stellar/stellar-core:19.13.1-1481.3acf6dd26.focal} + depends_on: - core-postgres restart: on-failure @@ -28,5 +29,5 @@ services: entrypoint: /usr/bin/env command: /start standalone volumes: - - ./stellar-core-integration-tests.cfg:/stellar-core.cfg + - ./${CORE_CONFIG_FILE:-stellar-core-integration-tests.cfg}:/stellar-core.cfg - ./core-start.sh:/start diff --git a/services/horizon/docker/docker-compose.pubnet.yml b/services/horizon/docker/docker-compose.pubnet.yml index f6e380749d..169045d7d1 100644 --- a/services/horizon/docker/docker-compose.pubnet.yml +++ b/services/horizon/docker/docker-compose.pubnet.yml @@ -3,8 +3,4 @@ services: horizon: platform: linux/amd64 environment: - - HISTORY_ARCHIVE_URLS=https://history.stellar.org/prd/core-live/core_live_001 - - NETWORK_PASSPHRASE=Public Global Stellar Network ; September 2015 - - CAPTIVE_CORE_CONFIG_APPEND_PATH=/captive-core-pubnet.cfg - volumes: - - ./captive-core-pubnet.cfg:/captive-core-pubnet.cfg + - NETWORK=pubnet \ No newline at end of file diff --git a/services/horizon/docker/docker-compose.standalone.yml b/services/horizon/docker/docker-compose.standalone.yml index 43bd9ac9d7..a537be0fb0 100644 --- a/services/horizon/docker/docker-compose.standalone.yml +++ b/services/horizon/docker/docker-compose.standalone.yml @@ -14,7 +14,7 @@ services: core: platform: linux/amd64 - image: ${CORE_IMAGE:-stellar/stellar-core:18} + image: ${CORE_IMAGE:-stellar/stellar-core:19.11.0-1323.7fb6d5e88.focal} depends_on: - core-postgres - core-upgrade @@ -37,6 +37,7 @@ services: - HISTORY_ARCHIVE_URLS=http://host.docker.internal:1570 - NETWORK_PASSPHRASE=Standalone Network ; February 2017 - CAPTIVE_CORE_CONFIG_APPEND_PATH=/captive-core-standalone.cfg + - STELLAR_CORE_URL=http://host.docker.internal:11626 volumes: - ./captive-core-standalone.cfg:/captive-core-standalone.cfg diff --git a/services/horizon/docker/docker-compose.yml b/services/horizon/docker/docker-compose.yml index 40bced6677..309df946a1 100644 --- a/services/horizon/docker/docker-compose.yml +++ b/services/horizon/docker/docker-compose.yml @@ -1,7 +1,8 @@ version: '3' services: horizon-postgres: - image: postgres:9.6.17-alpine + platform: linux/amd64 + image: postgres:12-bullseye restart: on-failure environment: - POSTGRES_HOST_AUTH_METHOD=trust @@ -27,13 +28,8 @@ services: - "11725:11725" environment: - DATABASE_URL=postgres://postgres@host.docker.internal:5432/horizon?sslmode=disable - - CAPTIVE_CORE_CONFIG_APPEND_PATH=/captive-core-testnet.cfg - - HISTORY_ARCHIVE_URLS=https://history.stellar.org/prd/core-testnet/core_testnet_001 - - NETWORK_PASSPHRASE=Test SDF Network ; September 2015 - - INGEST=true + - NETWORK=testnet - PER_HOUR_RATE_LIMIT=0 - volumes: - - ./captive-core-testnet.cfg:/captive-core-testnet.cfg command: ["--apply-migrations"] extra_hosts: - "host.docker.internal:host-gateway" diff --git a/services/horizon/docker/stellar-core-classic-integration-tests.cfg b/services/horizon/docker/stellar-core-classic-integration-tests.cfg new file mode 100644 index 0000000000..e27cfe14ed --- /dev/null +++ b/services/horizon/docker/stellar-core-classic-integration-tests.cfg @@ -0,0 +1,24 @@ +ARTIFICIALLY_ACCELERATE_TIME_FOR_TESTING=true + +NETWORK_PASSPHRASE="Standalone Network ; February 2017" + +PEER_PORT=11625 +HTTP_PORT=11626 +PUBLIC_HTTP_PORT=true + +NODE_SEED="SACJC372QBSSKJYTV5A7LWT4NXWHTQO6GHG4QDAVC2XDPX6CNNXFZ4JK" + +NODE_IS_VALIDATOR=true +UNSAFE_QUORUM=true +FAILURE_SAFETY=0 + +DATABASE="postgresql://user=postgres password=mysecretpassword host=core-postgres port=5641 dbname=stellar" + +[QUORUM_SET] +THRESHOLD_PERCENT=100 +VALIDATORS=["GD5KD2KEZJIGTC63IGW6UMUSMVUVG5IHG64HUTFWCHVZH2N2IBOQN7PS"] + +[HISTORY.vs] +get="cp history/vs/{0} {1}" +put="cp {0} history/vs/{1}" +mkdir="mkdir -p history/vs/{0}" \ No newline at end of file diff --git a/services/horizon/docker/stellar-core-integration-tests.cfg b/services/horizon/docker/stellar-core-integration-tests.cfg index e27cfe14ed..594a35b244 100644 --- a/services/horizon/docker/stellar-core-integration-tests.cfg +++ b/services/horizon/docker/stellar-core-integration-tests.cfg @@ -14,6 +14,11 @@ FAILURE_SAFETY=0 DATABASE="postgresql://user=postgres password=mysecretpassword host=core-postgres port=5641 dbname=stellar" +# Lower the TTL of persistent ledger entries +# so that ledger entry extension/restoring becomes testeable +TESTING_MINIMUM_PERSISTENT_ENTRY_LIFETIME=10 +TESTING_SOROBAN_HIGH_LIMIT_OVERRIDE=true + [QUORUM_SET] THRESHOLD_PERCENT=100 VALIDATORS=["GD5KD2KEZJIGTC63IGW6UMUSMVUVG5IHG64HUTFWCHVZH2N2IBOQN7PS"] @@ -21,4 +26,4 @@ VALIDATORS=["GD5KD2KEZJIGTC63IGW6UMUSMVUVG5IHG64HUTFWCHVZH2N2IBOQN7PS"] [HISTORY.vs] get="cp history/vs/{0} {1}" put="cp {0} history/vs/{1}" -mkdir="mkdir -p history/vs/{0}" \ No newline at end of file +mkdir="mkdir -p history/vs/{0}" diff --git a/services/horizon/docker/stellar-core-pubnet.cfg b/services/horizon/docker/stellar-core-pubnet.cfg index ab6ef6ea35..b851fbbf33 100644 --- a/services/horizon/docker/stellar-core-pubnet.cfg +++ b/services/horizon/docker/stellar-core-pubnet.cfg @@ -37,8 +37,8 @@ HOME_DOMAIN="stellar.blockdaemon.com" QUALITY="HIGH" [[HOME_DOMAINS]] -HOME_DOMAIN="wirexapp.com" -QUALITY="HIGH" +HOME_DOMAIN = "www.franklintempleton.com" +QUALITY = "HIGH" [[VALIDATORS]] NAME="sdf_1" @@ -181,22 +181,22 @@ ADDRESS="stellar-full-validator3.bdnodes.net" HISTORY="curl -sf https://stellar-full-history3.bdnodes.net/{0} -o {1}" [[VALIDATORS]] -NAME="wirexUS" -ADDRESS="us.stellar.wirexapp.com" -HOME_DOMAIN="wirexapp.com" -PUBLIC_KEY="GDXUKFGG76WJC7ACEH3JUPLKM5N5S76QSMNDBONREUXPCZYVPOLFWXUS" -HISTORY="curl -sf http://wxhorizonusstga1.blob.core.windows.net/history/{0} -o {1}" +NAME = "FT_SCV_1" +HOME_DOMAIN = "www.franklintempleton.com" +PUBLIC_KEY = "GARYGQ5F2IJEBCZJCBNPWNWVDOFK7IBOHLJKKSG2TMHDQKEEC6P4PE4V" +ADDRESS = "stellar1.franklintempleton.com:11625" +HISTORY = "curl -sf https://stellar-history-usw.franklintempleton.com/azuswshf401/{0} -o {1}" [[VALIDATORS]] -NAME="wirexUK" -ADDRESS="uk.stellar.wirexapp.com" -HOME_DOMAIN="wirexapp.com" -PUBLIC_KEY="GBBQQT3EIUSXRJC6TGUCGVA3FVPXVZLGG3OJYACWBEWYBHU46WJLWXEU" -HISTORY="curl -sf http://wxhorizonukstga1.blob.core.windows.net/history/{0} -o {1}" +NAME = "FT_SCV_2" +HOME_DOMAIN = "www.franklintempleton.com" +PUBLIC_KEY = "GCMSM2VFZGRPTZKPH5OABHGH4F3AVS6XTNJXDGCZ3MKCOSUBH3FL6DOB" +ADDRESS = "stellar2.franklintempleton.com:11625" +HISTORY = "curl -sf https://stellar-history-usc.franklintempleton.com/azuscshf401/{0} -o {1}" [[VALIDATORS]] -NAME="wirexSG" -ADDRESS="sg.stellar.wirexapp.com" -HOME_DOMAIN="wirexapp.com" -PUBLIC_KEY="GAB3GZIE6XAYWXGZUDM4GMFFLJBFMLE2JDPUCWUZXMOMT3NHXDHEWXAS" -HISTORY="curl -sf http://wxhorizonasiastga1.blob.core.windows.net/history/{0} -o {1}" \ No newline at end of file +NAME = "FT_SCV_3" +HOME_DOMAIN = "www.franklintempleton.com" +PUBLIC_KEY = "GA7DV63PBUUWNUFAF4GAZVXU2OZMYRATDLKTC7VTCG7AU4XUPN5VRX4A" +ADDRESS = "stellar3.franklintempleton.com:11625" +HISTORY = "curl -sf https://stellar-history-ins.franklintempleton.com/azinsshf401/{0} -o {1}" \ No newline at end of file diff --git a/services/horizon/docker/verify-range/Dockerfile b/services/horizon/docker/verify-range/Dockerfile index 499f86881e..0143dd2cfa 100644 --- a/services/horizon/docker/verify-range/Dockerfile +++ b/services/horizon/docker/verify-range/Dockerfile @@ -1,6 +1,4 @@ -FROM ubuntu:20.04 - -MAINTAINER Bartek Nowotarski +FROM ubuntu:22.04 ARG STELLAR_CORE_VERSION ENV STELLAR_CORE_VERSION=${STELLAR_CORE_VERSION:-*} @@ -8,7 +6,7 @@ ENV STELLAR_CORE_VERSION=${STELLAR_CORE_VERSION:-*} ENV DEBIAN_FRONTEND=noninteractive ADD dependencies / -RUN ["chmod", "+x", "dependencies"] +RUN ["chmod", "+x", "/dependencies"] RUN /dependencies ADD stellar-core.cfg / diff --git a/services/horizon/docker/verify-range/captive-core-pubnet.cfg b/services/horizon/docker/verify-range/captive-core-pubnet.cfg index 537325d4e9..5a702711fe 100644 --- a/services/horizon/docker/verify-range/captive-core-pubnet.cfg +++ b/services/horizon/docker/verify-range/captive-core-pubnet.cfg @@ -1,5 +1,4 @@ PEER_PORT=11725 -DATABASE = "sqlite3:///cc/stellar.db" FAILURE_SAFETY=1 @@ -7,187 +6,23 @@ FAILURE_SAFETY=1 HOME_DOMAIN="stellar.org" QUALITY="HIGH" -[[HOME_DOMAINS]] -HOME_DOMAIN="satoshipay.io" -QUALITY="HIGH" - -[[HOME_DOMAINS]] -HOME_DOMAIN="lobstr.co" -QUALITY="HIGH" - -[[HOME_DOMAINS]] -HOME_DOMAIN="www.coinqvest.com" -QUALITY="HIGH" - -[[HOME_DOMAINS]] -HOME_DOMAIN="publicnode.org" -QUALITY="HIGH" - -[[HOME_DOMAINS]] -HOME_DOMAIN="stellar.blockdaemon.com" -QUALITY="HIGH" - -[[HOME_DOMAINS]] -HOME_DOMAIN="wirexapp.com" -QUALITY="HIGH" - [[VALIDATORS]] NAME="sdf_1" HOME_DOMAIN="stellar.org" PUBLIC_KEY="GCGB2S2KGYARPVIA37HYZXVRM2YZUEXA6S33ZU5BUDC6THSB62LZSTYH" ADDRESS="core-live-a.stellar.org:11625" -HISTORY="curl -sf https://history.stellar.org/prd/core-live/core_live_001/{0} -o {1}" +HISTORY="curl -sf https://s3-eu-west-1.amazonaws.com/history.stellar.org/prd/core-live/core_live_001/{0} -o {1}" [[VALIDATORS]] NAME="sdf_2" HOME_DOMAIN="stellar.org" PUBLIC_KEY="GCM6QMP3DLRPTAZW2UZPCPX2LF3SXWXKPMP3GKFZBDSF3QZGV2G5QSTK" ADDRESS="core-live-b.stellar.org:11625" -HISTORY="curl -sf https://history.stellar.org/prd/core-live/core_live_002/{0} -o {1}" +HISTORY="curl -sf https://s3-eu-west-1.amazonaws.com/history.stellar.org/prd/core-live/core_live_002/{0} -o {1}" [[VALIDATORS]] NAME="sdf_3" HOME_DOMAIN="stellar.org" PUBLIC_KEY="GABMKJM6I25XI4K7U6XWMULOUQIQ27BCTMLS6BYYSOWKTBUXVRJSXHYQ" ADDRESS="core-live-c.stellar.org:11625" -HISTORY="curl -sf https://history.stellar.org/prd/core-live/core_live_003/{0} -o {1}" - -[[VALIDATORS]] -NAME="satoshipay_singapore" -HOME_DOMAIN="satoshipay.io" -PUBLIC_KEY="GBJQUIXUO4XSNPAUT6ODLZUJRV2NPXYASKUBY4G5MYP3M47PCVI55MNT" -ADDRESS="stellar-sg-sin.satoshipay.io:11625" -HISTORY="curl -sf https://stellar-history-sg-sin.satoshipay.io/{0} -o {1}" - -[[VALIDATORS]] -NAME="satoshipay_iowa" -HOME_DOMAIN="satoshipay.io" -PUBLIC_KEY="GAK6Z5UVGUVSEK6PEOCAYJISTT5EJBB34PN3NOLEQG2SUKXRVV2F6HZY" -ADDRESS="stellar-us-iowa.satoshipay.io:11625" -HISTORY="curl -sf https://stellar-history-us-iowa.satoshipay.io/{0} -o {1}" - -[[VALIDATORS]] -NAME="satoshipay_frankfurt" -HOME_DOMAIN="satoshipay.io" -PUBLIC_KEY="GC5SXLNAM3C4NMGK2PXK4R34B5GNZ47FYQ24ZIBFDFOCU6D4KBN4POAE" -ADDRESS="stellar-de-fra.satoshipay.io:11625" -HISTORY="curl -sf https://stellar-history-de-fra.satoshipay.io/{0} -o {1}" - -[[VALIDATORS]] -NAME="lobstr_1_europe" -HOME_DOMAIN="lobstr.co" -PUBLIC_KEY="GCFONE23AB7Y6C5YZOMKUKGETPIAJA4QOYLS5VNS4JHBGKRZCPYHDLW7" -ADDRESS="v1.stellar.lobstr.co:11625" -HISTORY="curl -sf https://stellar-archive-1-lobstr.s3.amazonaws.com/{0} -o {1}" - -[[VALIDATORS]] -NAME="lobstr_2_europe" -HOME_DOMAIN="lobstr.co" -PUBLIC_KEY="GDXQB3OMMQ6MGG43PWFBZWBFKBBDUZIVSUDAZZTRAWQZKES2CDSE5HKJ" -ADDRESS="v2.stellar.lobstr.co:11625" -HISTORY="curl -sf https://stellar-archive-2-lobstr.s3.amazonaws.com/{0} -o {1}" - -[[VALIDATORS]] -NAME="lobstr_3_north_america" -HOME_DOMAIN="lobstr.co" -PUBLIC_KEY="GD5QWEVV4GZZTQP46BRXV5CUMMMLP4JTGFD7FWYJJWRL54CELY6JGQ63" -ADDRESS="v3.stellar.lobstr.co:11625" -HISTORY="curl -sf https://stellar-archive-3-lobstr.s3.amazonaws.com/{0} -o {1}" - -[[VALIDATORS]] -NAME="lobstr_4_asia" -HOME_DOMAIN="lobstr.co" -PUBLIC_KEY="GA7TEPCBDQKI7JQLQ34ZURRMK44DVYCIGVXQQWNSWAEQR6KB4FMCBT7J" -ADDRESS="v4.stellar.lobstr.co:11625" -HISTORY="curl -sf https://stellar-archive-4-lobstr.s3.amazonaws.com/{0} -o {1}" - -[[VALIDATORS]] -NAME="lobstr_5_australia" -HOME_DOMAIN="lobstr.co" -PUBLIC_KEY="GA5STBMV6QDXFDGD62MEHLLHZTPDI77U3PFOD2SELU5RJDHQWBR5NNK7" -ADDRESS="v5.stellar.lobstr.co:11625" -HISTORY="curl -sf https://stellar-archive-5-lobstr.s3.amazonaws.com/{0} -o {1}" - -[[VALIDATORS]] -NAME="coinqvest_hong_kong" -HOME_DOMAIN="www.coinqvest.com" -PUBLIC_KEY="GAZ437J46SCFPZEDLVGDMKZPLFO77XJ4QVAURSJVRZK2T5S7XUFHXI2Z" -ADDRESS="hongkong.stellar.coinqvest.com:11625" -HISTORY="curl -sf https://hongkong.stellar.coinqvest.com/history/{0} -o {1}" - -[[VALIDATORS]] -NAME="coinqvest_germany" -HOME_DOMAIN="www.coinqvest.com" -PUBLIC_KEY="GD6SZQV3WEJUH352NTVLKEV2JM2RH266VPEM7EH5QLLI7ZZAALMLNUVN" -ADDRESS="germany.stellar.coinqvest.com:11625" -HISTORY="curl -sf https://germany.stellar.coinqvest.com/history/{0} -o {1}" - -[[VALIDATORS]] -NAME="coinqvest_finland" -HOME_DOMAIN="www.coinqvest.com" -PUBLIC_KEY="GADLA6BJK6VK33EM2IDQM37L5KGVCY5MSHSHVJA4SCNGNUIEOTCR6J5T" -ADDRESS="finland.stellar.coinqvest.com:11625" -HISTORY="curl -sf https://finland.stellar.coinqvest.com/history/{0} -o {1}" - -[[VALIDATORS]] -NAME="bootes" -HOME_DOMAIN="publicnode.org" -PUBLIC_KEY="GCVJ4Z6TI6Z2SOGENSPXDQ2U4RKH3CNQKYUHNSSPYFPNWTLGS6EBH7I2" -ADDRESS="bootes.publicnode.org" -HISTORY="curl -sf https://bootes-history.publicnode.org/{0} -o {1}" - -[[VALIDATORS]] -NAME="hercules" -HOME_DOMAIN="publicnode.org" -PUBLIC_KEY="GBLJNN3AVZZPG2FYAYTYQKECNWTQYYUUY2KVFN2OUKZKBULXIXBZ4FCT" -ADDRESS="hercules.publicnode.org" -HISTORY="curl -sf https://hercules-history.publicnode.org/{0} -o {1}" - -[[VALIDATORS]] -NAME="lyra" -HOME_DOMAIN="publicnode.org" -PUBLIC_KEY="GCIXVKNFPKWVMKJKVK2V4NK7D4TC6W3BUMXSIJ365QUAXWBRPPJXIR2Z" -ADDRESS="lyra.publicnode.org" -HISTORY="curl -sf https://lyra-history.publicnode.org/{0} -o {1}" - -[[VALIDATORS]] -NAME="Blockdaemon_Validator_1" -HOME_DOMAIN="stellar.blockdaemon.com" -PUBLIC_KEY="GAAV2GCVFLNN522ORUYFV33E76VPC22E72S75AQ6MBR5V45Z5DWVPWEU" -ADDRESS="stellar-full-validator1.bdnodes.net" -HISTORY="curl -sf https://stellar-full-history1.bdnodes.net/{0} -o {1}" - -[[VALIDATORS]] -NAME="Blockdaemon_Validator_2" -HOME_DOMAIN="stellar.blockdaemon.com" -PUBLIC_KEY="GAVXB7SBJRYHSG6KSQHY74N7JAFRL4PFVZCNWW2ARI6ZEKNBJSMSKW7C" -ADDRESS="stellar-full-validator2.bdnodes.net" -HISTORY="curl -sf https://stellar-full-history2.bdnodes.net/{0} -o {1}" - -[[VALIDATORS]] -NAME="Blockdaemon_Validator_3" -HOME_DOMAIN="stellar.blockdaemon.com" -PUBLIC_KEY="GAYXZ4PZ7P6QOX7EBHPIZXNWY4KCOBYWJCA4WKWRKC7XIUS3UJPT6EZ4" -ADDRESS="stellar-full-validator3.bdnodes.net" -HISTORY="curl -sf https://stellar-full-history3.bdnodes.net/{0} -o {1}" - -[[VALIDATORS]] -NAME="wirexUS" -ADDRESS="us.stellar.wirexapp.com" -HOME_DOMAIN="wirexapp.com" -PUBLIC_KEY="GDXUKFGG76WJC7ACEH3JUPLKM5N5S76QSMNDBONREUXPCZYVPOLFWXUS" -HISTORY="curl -sf http://wxhorizonusstga1.blob.core.windows.net/history/{0} -o {1}" - -[[VALIDATORS]] -NAME="wirexUK" -ADDRESS="uk.stellar.wirexapp.com" -HOME_DOMAIN="wirexapp.com" -PUBLIC_KEY="GBBQQT3EIUSXRJC6TGUCGVA3FVPXVZLGG3OJYACWBEWYBHU46WJLWXEU" -HISTORY="curl -sf http://wxhorizonukstga1.blob.core.windows.net/history/{0} -o {1}" - -[[VALIDATORS]] -NAME="wirexSG" -ADDRESS="sg.stellar.wirexapp.com" -HOME_DOMAIN="wirexapp.com" -PUBLIC_KEY="GAB3GZIE6XAYWXGZUDM4GMFFLJBFMLE2JDPUCWUZXMOMT3NHXDHEWXAS" -HISTORY="curl -sf http://wxhorizonasiastga1.blob.core.windows.net/history/{0} -o {1}" \ No newline at end of file +HISTORY="curl -sf https://s3-eu-west-1.amazonaws.com/history.stellar.org/prd/core-live/core_live_003/{0} -o {1}" \ No newline at end of file diff --git a/services/horizon/docker/verify-range/dependencies b/services/horizon/docker/verify-range/dependencies index fa622f9d2e..910ee9cf21 100644 --- a/services/horizon/docker/verify-range/dependencies +++ b/services/horizon/docker/verify-range/dependencies @@ -11,13 +11,17 @@ echo "deb https://apt.stellar.org $(lsb_release -cs) stable" | sudo tee -a /etc/ apt-get update apt-get install -y stellar-core=${STELLAR_CORE_VERSION} -wget -q https://dl.google.com/go/go1.18.linux-amd64.tar.gz -tar -C /usr/local -xzf go1.18.linux-amd64.tar.gz - git clone https://github.com/stellar/go.git stellar-go cd stellar-go + # By default "git fetch" only fetches refs/ # Below ensures we also fetch PR refs git config --add remote.origin.fetch "+refs/pull/*/head:refs/remotes/origin/pull/*" git fetch --force --quiet origin + +GO_VERSION=$(sed -En 's/^go[[:space:]]+([[:digit:].]+)$/\1/p' go.mod) +wget -q https://dl.google.com/go/go${GO_VERSION}.linux-amd64.tar.gz +tar -C /usr/local -xzf go${GO_VERSION}.linux-amd64.tar.gz +rm -f go${GO_VERSION}.linux-amd64.tar.gz + /usr/local/go/bin/go build -v ./services/horizon diff --git a/services/horizon/docker/verify-range/start b/services/horizon/docker/verify-range/start index a0c5f0df25..0e7c69403d 100644 --- a/services/horizon/docker/verify-range/start +++ b/services/horizon/docker/verify-range/start @@ -8,8 +8,8 @@ fi rm -rf "$PGDATA"/* sudo chown -R postgres "$PGDATA" sudo chmod -R 775 "$PGDATA" -sudo -u postgres --preserve-env=PGDATA /usr/lib/postgresql/12/bin/initdb -sudo -u postgres --preserve-env=PGDATA /usr/lib/postgresql/12/bin/pg_ctl start +sudo -u postgres --preserve-env=PGDATA /usr/lib/postgresql/14/bin/initdb +sudo -u postgres --preserve-env=PGDATA /usr/lib/postgresql/14/bin/pg_ctl start sudo -u postgres createdb horizon sudo -u postgres psql -c "ALTER USER postgres PASSWORD 'postgres';" @@ -50,9 +50,12 @@ dump_horizon_db() { echo "dumping history_ledgers" psql "postgres://postgres:postgres@localhost:5432/horizon?sslmode=disable" -t -A -F"," --variable="FETCH_COUNT=100" -c "select sequence, ledger_hash, previous_ledger_hash, transaction_count, operation_count, closed_at, id, total_coins, fee_pool, base_fee, base_reserve, max_tx_set_size, protocol_version, ledger_header, successful_transaction_count, failed_transaction_count from history_ledgers order by sequence asc" > "${1}_ledgers" echo "dumping history_operations" - psql "postgres://postgres:postgres@localhost:5432/horizon?sslmode=disable" -t -A -F"," --variable="FETCH_COUNT=100" -c "select * from history_operations order by id asc" > "${1}_operations" + # skip is_payment column which was only introduced in the most recent horizon v2.27.0 + psql "postgres://postgres:postgres@localhost:5432/horizon?sslmode=disable" -t -A -F"," --variable="FETCH_COUNT=100" -c "select id, transaction_id, application_order, type, details, source_account, source_account_muxed from history_operations order by id asc" > "${1}_operations" echo "dumping history_operation_claimable_balances" - psql "postgres://postgres:postgres@localhost:5432/horizon?sslmode=disable" -t -A -F"," --variable="FETCH_COUNT=100" -c "select history_operation_id, history_claimable_balance_id from history_operation_claimable_balances left join history_claimable_balances on history_claimable_balances.id = history_operation_claimable_balances.history_claimable_balance_id order by history_operation_id asc, id asc" > "${1}_operation_claimable_balances" + psql "postgres://postgres:postgres@localhost:5432/horizon?sslmode=disable" -t -A -F"," --variable="FETCH_COUNT=100" -c "select history_operation_id, claimable_balance_id from history_operation_claimable_balances left join history_claimable_balances on history_claimable_balances.id = history_operation_claimable_balances.history_claimable_balance_id order by history_operation_id asc, claimable_balance_id asc" > "${1}_operation_claimable_balances" + echo "dumping history_operation_liquidity_pools" + psql "postgres://postgres:postgres@localhost:5432/horizon?sslmode=disable" -t -A -F"," --variable="FETCH_COUNT=100" -c "select history_operation_id, liquidity_pool_id from history_operation_liquidity_pools left join history_liquidity_pools on history_liquidity_pools.id = history_operation_liquidity_pools.history_liquidity_pool_id order by history_operation_id asc, liquidity_pool_id asc" > "${1}_operation_liquidity_pools" echo "dumping history_operation_participants" psql "postgres://postgres:postgres@localhost:5432/horizon?sslmode=disable" -t -A -F"," --variable="FETCH_COUNT=100" -c "select history_operation_id, address from history_operation_participants left join history_accounts on history_accounts.id = history_operation_participants.history_account_id order by history_operation_id asc, address asc" > "${1}_operation_participants" echo "dumping history_trades" @@ -62,7 +65,9 @@ dump_horizon_db() { # in different Stellar-Core instances. The final fix should probably: unmarshal `tx_meta`, sort it, marshal and compare. psql "postgres://postgres:postgres@localhost:5432/horizon?sslmode=disable" -t -A -F"," --variable="FETCH_COUNT=100" -c "select transaction_hash, ledger_sequence, application_order, account, account_sequence, max_fee, operation_count, id, tx_envelope, tx_result, tx_fee_meta, signatures, memo_type, memo, time_bounds, successful, fee_charged, inner_transaction_hash, fee_account, inner_signatures, new_max_fee, account_muxed, fee_account_muxed from history_transactions order by id asc" > "${1}_transactions" echo "dumping history_transaction_claimable_balances" - psql "postgres://postgres:postgres@localhost:5432/horizon?sslmode=disable" -t -A -F"," --variable="FETCH_COUNT=100" -c "select history_transaction_id, history_claimable_balance_id from history_transaction_claimable_balances left join history_claimable_balances on history_claimable_balances.id = history_transaction_claimable_balances.history_claimable_balance_id order by history_transaction_id, id" > "${1}_transaction_claimable_balances" + psql "postgres://postgres:postgres@localhost:5432/horizon?sslmode=disable" -t -A -F"," --variable="FETCH_COUNT=100" -c "select history_transaction_id, claimable_balance_id from history_transaction_claimable_balances left join history_claimable_balances on history_claimable_balances.id = history_transaction_claimable_balances.history_claimable_balance_id order by history_transaction_id, claimable_balance_id" > "${1}_transaction_claimable_balances" + echo "dumping history_transaction_liquidity_pools" + psql "postgres://postgres:postgres@localhost:5432/horizon?sslmode=disable" -t -A -F"," --variable="FETCH_COUNT=100" -c "select history_transaction_id, liquidity_pool_id from history_transaction_liquidity_pools left join history_liquidity_pools on history_liquidity_pools.id = history_transaction_liquidity_pools.history_liquidity_pool_id order by history_transaction_id, liquidity_pool_id" > "${1}_transaction_liquidity_pools" echo "dumping history_transaction_participants" psql "postgres://postgres:postgres@localhost:5432/horizon?sslmode=disable" -t -A -F"," --variable="FETCH_COUNT=100" -c "select history_transaction_id, address from history_transaction_participants left join history_accounts on history_accounts.id = history_transaction_participants.history_account_id order by history_transaction_id, address" > "${1}_transaction_participants" } @@ -71,19 +76,8 @@ dump_horizon_db() { export NETWORK_PASSPHRASE="Public Global Stellar Network ; September 2015" export HISTORY_ARCHIVE_URLS="https://s3-eu-west-1.amazonaws.com/history.stellar.org/prd/core-live/core_live_001" export DATABASE_URL="postgres://postgres:postgres@localhost:5432/horizon?sslmode=disable" -export CAPTIVE_CORE_USE_DB="true" -export CAPTIVE_CORE_CONFIG_APPEND_PATH="/captive-core-pubnet.cfg" +export CAPTIVE_CORE_CONFIG_APPEND_PATH="/captive-core-pubnet.cfg" export STELLAR_CORE_BINARY_PATH="/usr/bin/stellar-core" -export ENABLE_CAPTIVE_CORE_INGESTION="true" - -# CAPTIVE_CORE_STORAGE_PATH will store the archive files that core downloads -# /cc path in this vm will have the sqlite3://stellar.db file which captive core will use for on-disk -# do a docker volume mount on /cc if the main disk storage devivce won't have at least 3k IOPS and 256GB -# which is required by core for the i/o it will do against sqlite3:///cc/stellardb -if [ -z "${CAPTIVE_CORE_STORAGE_PATH}" ]; then - export CAPTIVE_CORE_STORAGE_PATH="/cc" -fi -export CAPTIVE_CORE_REUSE_STORAGE_PATH="false" cd stellar-go git pull origin @@ -103,12 +97,15 @@ function alter_tables_unlogged() { psql "postgres://postgres:postgres@localhost:5432/horizon?sslmode=disable" -c "ALTER TABLE history_accounts SET UNLOGGED;" psql "postgres://postgres:postgres@localhost:5432/horizon?sslmode=disable" -c "ALTER TABLE history_assets SET UNLOGGED;" psql "postgres://postgres:postgres@localhost:5432/horizon?sslmode=disable" -c "ALTER TABLE history_claimable_balances SET UNLOGGED;" + psql "postgres://postgres:postgres@localhost:5432/horizon?sslmode=disable" -c "ALTER TABLE history_liquidity_pools SET UNLOGGED;" psql "postgres://postgres:postgres@localhost:5432/horizon?sslmode=disable" -c "ALTER TABLE history_effects SET UNLOGGED;" psql "postgres://postgres:postgres@localhost:5432/horizon?sslmode=disable" -c "ALTER TABLE history_ledgers SET UNLOGGED;" psql "postgres://postgres:postgres@localhost:5432/horizon?sslmode=disable" -c "ALTER TABLE history_operation_claimable_balances SET UNLOGGED;" + psql "postgres://postgres:postgres@localhost:5432/horizon?sslmode=disable" -c "ALTER TABLE history_operation_liquidity_pools SET UNLOGGED;" psql "postgres://postgres:postgres@localhost:5432/horizon?sslmode=disable" -c "ALTER TABLE history_operation_participants SET UNLOGGED;" psql "postgres://postgres:postgres@localhost:5432/horizon?sslmode=disable" -c "ALTER TABLE history_operations SET UNLOGGED;" psql "postgres://postgres:postgres@localhost:5432/horizon?sslmode=disable" -c "ALTER TABLE history_transaction_claimable_balances SET UNLOGGED;" + psql "postgres://postgres:postgres@localhost:5432/horizon?sslmode=disable" -c "ALTER TABLE history_transaction_liquidity_pools SET UNLOGGED;" psql "postgres://postgres:postgres@localhost:5432/horizon?sslmode=disable" -c "ALTER TABLE history_transaction_participants SET UNLOGGED;" psql "postgres://postgres:postgres@localhost:5432/horizon?sslmode=disable" -c "ALTER TABLE history_transactions SET UNLOGGED;" psql "postgres://postgres:postgres@localhost:5432/horizon?sslmode=disable" -c "ALTER TABLE offers SET UNLOGGED;" diff --git a/services/horizon/internal/action_offers_test.go b/services/horizon/internal/action_offers_test.go index 13458db9fe..464757c94e 100644 --- a/services/horizon/internal/action_offers_test.go +++ b/services/horizon/internal/action_offers_test.go @@ -24,7 +24,9 @@ func TestOfferActions_Show(t *testing.T) { ht.Assert.NoError(err) ledgerCloseTime := time.Now().Unix() - _, err = q.InsertLedger(ctx, xdr.LedgerHeaderHistoryEntry{ + ht.Assert.NoError(q.Begin(ctx)) + ledgerBatch := q.NewLedgerBatchInsertBuilder() + err = ledgerBatch.Add(xdr.LedgerHeaderHistoryEntry{ Header: xdr.LedgerHeader{ LedgerSeq: 100, ScpValue: xdr.StellarValue{ @@ -33,6 +35,8 @@ func TestOfferActions_Show(t *testing.T) { }, }, 0, 0, 0, 0, 0) ht.Assert.NoError(err) + ht.Assert.NoError(ledgerBatch.Exec(ht.Ctx, q)) + ht.Assert.NoError(q.Commit()) issuer := xdr.MustAddress("GBRPYHIL2CI3FNQ4BXLFMNDLFJUNPU2HY3ZMFSHONUCEOASW7QC7OX2H") nativeAsset := xdr.MustNewNativeAsset() diff --git a/services/horizon/internal/actions/account.go b/services/horizon/internal/actions/account.go index 82856de3b7..0a3eef1b95 100644 --- a/services/horizon/internal/actions/account.go +++ b/services/horizon/internal/actions/account.go @@ -23,7 +23,7 @@ func AccountInfo(ctx context.Context, hq *history.Q, addr string) (*protocol.Acc data []history.Data signers []history.AccountSigner trustlines []history.TrustLine - resouce protocol.Account + resource protocol.Account ) record, err := hq.GetAccountByID(ctx, addr) @@ -53,7 +53,7 @@ func AccountInfo(ctx context.Context, hq *history.Q, addr string) (*protocol.Acc err = resourceadapter.PopulateAccountEntry( ctx, - &resouce, + &resource, record, data, signers, @@ -64,7 +64,7 @@ func AccountInfo(ctx context.Context, hq *history.Q, addr string) (*protocol.Acc return nil, errors.Wrap(err, "populating account entry") } - return &resouce, nil + return &resource, nil } // AccountsQuery query struct for accounts end-point diff --git a/services/horizon/internal/actions/account_test.go b/services/horizon/internal/actions/account_test.go index ed3d529575..b8c9d0d03b 100644 --- a/services/horizon/internal/actions/account_test.go +++ b/services/horizon/internal/actions/account_test.go @@ -228,7 +228,9 @@ func TestAccountInfo(t *testing.T) { assert.NoError(t, err) ledgerFourCloseTime := time.Now().Unix() - _, err = q.InsertLedger(tt.Ctx, xdr.LedgerHeaderHistoryEntry{ + assert.NoError(t, q.Begin(tt.Ctx)) + ledgerBatch := q.NewLedgerBatchInsertBuilder() + err = ledgerBatch.Add(xdr.LedgerHeaderHistoryEntry{ Header: xdr.LedgerHeader{ LedgerSeq: 4, ScpValue: xdr.StellarValue{ @@ -237,6 +239,8 @@ func TestAccountInfo(t *testing.T) { }, }, 0, 0, 0, 0, 0) assert.NoError(t, err) + assert.NoError(t, ledgerBatch.Exec(tt.Ctx, q)) + assert.NoError(t, q.Commit()) account, err := AccountInfo(tt.Ctx, &history.Q{tt.HorizonSession()}, accountID) tt.Assert.NoError(err) @@ -408,7 +412,9 @@ func TestGetAccountsHandlerPageResultsByAsset(t *testing.T) { err := q.UpsertAccounts(tt.Ctx, []history.AccountEntry{account1, account2}) assert.NoError(t, err) ledgerCloseTime := time.Now().Unix() - _, err = q.InsertLedger(tt.Ctx, xdr.LedgerHeaderHistoryEntry{ + assert.NoError(t, q.Begin(tt.Ctx)) + ledgerBatch := q.NewLedgerBatchInsertBuilder() + err = ledgerBatch.Add(xdr.LedgerHeaderHistoryEntry{ Header: xdr.LedgerHeader{ LedgerSeq: 1234, ScpValue: xdr.StellarValue{ @@ -417,6 +423,8 @@ func TestGetAccountsHandlerPageResultsByAsset(t *testing.T) { }, }, 0, 0, 0, 0, 0) assert.NoError(t, err) + assert.NoError(t, ledgerBatch.Exec(tt.Ctx, q)) + assert.NoError(t, q.Commit()) for _, row := range accountSigners { _, err = q.CreateAccountSigner(tt.Ctx, row.Account, row.Signer, row.Weight, nil) @@ -511,7 +519,9 @@ func TestGetAccountsHandlerPageResultsByLiquidityPool(t *testing.T) { assert.NoError(t, err) ledgerCloseTime := time.Now().Unix() - _, err = q.InsertLedger(tt.Ctx, xdr.LedgerHeaderHistoryEntry{ + assert.NoError(t, q.Begin(tt.Ctx)) + ledgerBatch := q.NewLedgerBatchInsertBuilder() + err = ledgerBatch.Add(xdr.LedgerHeaderHistoryEntry{ Header: xdr.LedgerHeader{ LedgerSeq: 1234, ScpValue: xdr.StellarValue{ @@ -520,6 +530,9 @@ func TestGetAccountsHandlerPageResultsByLiquidityPool(t *testing.T) { }, }, 0, 0, 0, 0, 0) assert.NoError(t, err) + assert.NoError(t, ledgerBatch.Exec(tt.Ctx, q)) + assert.NoError(t, q.Commit()) + var assetType, code, issuer string usd.MustExtract(&assetType, &code, &issuer) params := map[string]string{ diff --git a/services/horizon/internal/actions/asset.go b/services/horizon/internal/actions/asset.go index 27235fb5eb..7236b482ff 100644 --- a/services/horizon/internal/actions/asset.go +++ b/services/horizon/internal/actions/asset.go @@ -81,7 +81,7 @@ func (handler AssetStatsHandler) validateAssetParams(code, issuer string, pq db2 func (handler AssetStatsHandler) findIssuersForAssets( ctx context.Context, historyQ *history.Q, - assetStats []history.ExpAssetStat, + assetStats []history.AssetAndContractStat, ) (map[string]history.AccountEntry, error) { issuerSet := map[string]bool{} issuers := []string{} diff --git a/services/horizon/internal/actions/asset_test.go b/services/horizon/internal/actions/asset_test.go index fcedf5985d..0e4995d93c 100644 --- a/services/horizon/internal/actions/asset_test.go +++ b/services/horizon/internal/actions/asset_test.go @@ -159,6 +159,8 @@ func TestAssetStats(t *testing.T) { LiquidityPoolsAmount: "0.0000020", Amount: "0.0000001", NumAccounts: usdAssetStat.NumAccounts, + ContractsAmount: "0.0000000", + ArchivedContractsAmount: "0.0000000", Asset: base.Asset{ Type: "credit_alphanum4", Code: usdAssetStat.AssetCode, @@ -202,6 +204,8 @@ func TestAssetStats(t *testing.T) { }, ClaimableBalancesAmount: "0.0000000", LiquidityPoolsAmount: "0.0000000", + ContractsAmount: "0.0000000", + ArchivedContractsAmount: "0.0000000", Amount: "0.0000023", NumAccounts: etherAssetStat.NumAccounts, Asset: base.Asset{ @@ -248,6 +252,8 @@ func TestAssetStats(t *testing.T) { ClaimableBalancesAmount: "0.0000000", LiquidityPoolsAmount: "0.0000000", Amount: "0.0000001", + ContractsAmount: "0.0000000", + ArchivedContractsAmount: "0.0000000", NumAccounts: otherUSDAssetStat.NumAccounts, Asset: base.Asset{ Type: "credit_alphanum4", @@ -295,6 +301,8 @@ func TestAssetStats(t *testing.T) { ClaimableBalancesAmount: "0.0000000", LiquidityPoolsAmount: "0.0000000", Amount: "0.0000111", + ContractsAmount: "0.0000000", + ArchivedContractsAmount: "0.0000000", NumAccounts: eurAssetStat.NumAccounts, Asset: base.Asset{ Type: "credit_alphanum4", @@ -471,6 +479,8 @@ func TestAssetStatsIssuerDoesNotExist(t *testing.T) { ClaimableBalancesAmount: "0.0000000", LiquidityPoolsAmount: "0.0000000", Amount: "0.0000001", + ContractsAmount: "0.0000000", + ArchivedContractsAmount: "0.0000000", NumAccounts: usdAssetStat.NumAccounts, Asset: base.Asset{ Type: "credit_alphanum4", diff --git a/services/horizon/internal/actions/claimable_balance_test.go b/services/horizon/internal/actions/claimable_balance_test.go index ad6bcd575a..fa922b930b 100644 --- a/services/horizon/internal/actions/claimable_balance_test.go +++ b/services/horizon/internal/actions/claimable_balance_test.go @@ -1,6 +1,7 @@ package actions import ( + "database/sql" "net/http/httptest" "testing" @@ -18,7 +19,12 @@ func TestGetClaimableBalanceByID(t *testing.T) { tt := test.Start(t) defer tt.Finish() test.ResetHorizonDB(t, tt.HorizonDB) - q := &history.Q{tt.HorizonSession()} + q := &history.Q{SessionInterface: tt.HorizonSession()} + + tt.Assert.NoError(q.BeginTx(tt.Ctx, &sql.TxOptions{})) + defer func() { + _ = q.Rollback() + }() accountID := "GC3C4AKRBQLHOJ45U4XG35ESVWRDECWO5XLDGYADO6DPR3L7KIDVUMML" asset := xdr.MustNewCreditAsset("USD", accountID) @@ -43,8 +49,21 @@ func TestGetClaimableBalanceByID(t *testing.T) { LastModifiedLedger: 123, } - err = q.UpsertClaimableBalances(tt.Ctx, []history.ClaimableBalance{cBalance}) - tt.Assert.NoError(err) + balanceInsertBuilder := q.NewClaimableBalanceBatchInsertBuilder() + tt.Assert.NoError(balanceInsertBuilder.Add(cBalance)) + + claimantsInsertBuilder := q.NewClaimableBalanceClaimantBatchInsertBuilder() + for _, claimant := range cBalance.Claimants { + claimant := history.ClaimableBalanceClaimant{ + BalanceID: cBalance.BalanceID, + Destination: claimant.Destination, + LastModifiedLedger: cBalance.LastModifiedLedger, + } + tt.Assert.NoError(claimantsInsertBuilder.Add(claimant)) + } + + tt.Assert.NoError(balanceInsertBuilder.Exec(tt.Ctx)) + tt.Assert.NoError(claimantsInsertBuilder.Exec(tt.Ctx)) handler := GetClaimableBalanceByIDHandler{} response, err := handler.GetResource(httptest.NewRecorder(), makeRequest( @@ -137,6 +156,11 @@ func TestGetClaimableBalances(t *testing.T) { test.ResetHorizonDB(t, tt.HorizonDB) q := &history.Q{tt.HorizonSession()} + tt.Assert.NoError(q.BeginTx(tt.Ctx, &sql.TxOptions{})) + defer func() { + _ = q.Rollback() + }() + entriesMeta := []struct { id xdr.Hash accountID string @@ -176,8 +200,25 @@ func TestGetClaimableBalances(t *testing.T) { hCBs = append(hCBs, cb) } - err := q.UpsertClaimableBalances(tt.Ctx, hCBs) - tt.Assert.NoError(err) + balanceInsertbuilder := q.NewClaimableBalanceBatchInsertBuilder() + + claimantsInsertBuilder := q.NewClaimableBalanceClaimantBatchInsertBuilder() + + for _, cBalance := range hCBs { + tt.Assert.NoError(balanceInsertbuilder.Add(cBalance)) + + for _, claimant := range cBalance.Claimants { + claimant := history.ClaimableBalanceClaimant{ + BalanceID: cBalance.BalanceID, + Destination: claimant.Destination, + LastModifiedLedger: cBalance.LastModifiedLedger, + } + tt.Assert.NoError(claimantsInsertBuilder.Add(claimant)) + } + } + + tt.Assert.NoError(balanceInsertbuilder.Exec(tt.Ctx)) + tt.Assert.NoError(claimantsInsertBuilder.Exec(tt.Ctx)) handler := GetClaimableBalancesHandler{} response, err := handler.GetResourcePage(httptest.NewRecorder(), makeRequest( @@ -256,11 +297,9 @@ func TestGetClaimableBalances(t *testing.T) { tt.Assert.NoError(err) tt.Assert.Len(response, 0) - // new claimable balances are ingest and one of them updated, they should appear in the next pages - cbToBeUpdated := hCBs[3] - cbToBeUpdated.Sponsor = null.StringFrom("GC3C4AKRBQLHOJ45U4XG35ESVWRDECWO5XLDGYADO6DPR3L7KIDVUMML") - cbToBeUpdated.LastModifiedLedger = 1238 - q.UpsertClaimableBalances(tt.Ctx, []history.ClaimableBalance{cbToBeUpdated}) + // new claimable balances are ingested, they should appear in the next pages + balanceInsertbuilder = q.NewClaimableBalanceBatchInsertBuilder() + claimantsInsertBuilder = q.NewClaimableBalanceClaimantBatchInsertBuilder() entriesMeta = []struct { id xdr.Hash @@ -282,14 +321,26 @@ func TestGetClaimableBalances(t *testing.T) { }, } - hCBs = nil for _, e := range entriesMeta { entry := buildClaimableBalance(tt, e.id, e.accountID, e.ledger, e.asset) hCBs = append(hCBs, entry) } - err = q.UpsertClaimableBalances(tt.Ctx, hCBs) - tt.Assert.NoError(err) + for _, cBalance := range hCBs[4:] { + tt.Assert.NoError(balanceInsertbuilder.Add(cBalance)) + + for _, claimant := range cBalance.Claimants { + claimant := history.ClaimableBalanceClaimant{ + BalanceID: cBalance.BalanceID, + Destination: claimant.Destination, + LastModifiedLedger: cBalance.LastModifiedLedger, + } + tt.Assert.NoError(claimantsInsertBuilder.Add(claimant)) + } + } + + tt.Assert.NoError(balanceInsertbuilder.Exec(tt.Ctx)) + tt.Assert.NoError(claimantsInsertBuilder.Exec(tt.Ctx)) response, err = handler.GetResourcePage(httptest.NewRecorder(), makeRequest( t, @@ -315,7 +366,7 @@ func TestGetClaimableBalances(t *testing.T) { tt.Assert.Len(response, 2) // response should be the first 2 elements of entries - for i, entry := range hCBs { + for i, entry := range hCBs[4:] { tt.Assert.Equal(entry.BalanceID, response[i].(protocol.ClaimableBalance).BalanceID) } @@ -329,21 +380,6 @@ func TestGetClaimableBalances(t *testing.T) { q, )) - tt.Assert.NoError(err) - tt.Assert.Len(response, 1) - - tt.Assert.Equal(cbToBeUpdated.BalanceID, response[0].(protocol.ClaimableBalance).BalanceID) - - response, err = handler.GetResourcePage(httptest.NewRecorder(), makeRequest( - t, - map[string]string{ - "limit": "2", - "cursor": response[0].(protocol.ClaimableBalance).PagingToken(), - }, - map[string]string{}, - q, - )) - tt.Assert.NoError(err) tt.Assert.Len(response, 0) @@ -361,9 +397,9 @@ func TestGetClaimableBalances(t *testing.T) { tt.Assert.NoError(err) tt.Assert.Len(response, 2) - tt.Assert.Equal(cbToBeUpdated.BalanceID, response[0].(protocol.ClaimableBalance).BalanceID) + tt.Assert.Equal(hCBs[5].BalanceID, response[0].(protocol.ClaimableBalance).BalanceID) - tt.Assert.Equal(hCBs[1].BalanceID, response[1].(protocol.ClaimableBalance).BalanceID) + tt.Assert.Equal(hCBs[4].BalanceID, response[1].(protocol.ClaimableBalance).BalanceID) response, err = handler.GetResourcePage(httptest.NewRecorder(), makeRequest( t, @@ -449,7 +485,7 @@ func TestGetClaimableBalances(t *testing.T) { )) tt.Assert.NoError(err) - tt.Assert.Len(response, 3) + tt.Assert.Len(response, 2) for _, resource := range response { tt.Assert.Equal( "GC3C4AKRBQLHOJ45U4XG35ESVWRDECWO5XLDGYADO6DPR3L7KIDVUMML", diff --git a/services/horizon/internal/actions/helpers_test.go b/services/horizon/internal/actions/helpers_test.go index 600a5c1472..445862c25e 100644 --- a/services/horizon/internal/actions/helpers_test.go +++ b/services/horizon/internal/actions/helpers_test.go @@ -6,6 +6,7 @@ import ( "math" "net/http" "net/url" + "strings" "testing" "github.com/go-chi/chi" @@ -141,7 +142,7 @@ func TestValidateCursorWithinHistory(t *testing.T) { if tc.valid { tt.NoError(err) } else { - tt.EqualError(err, "problem: before_history") + tt.True(strings.Contains(err.Error(), "problem: before_history")) } }) } diff --git a/services/horizon/internal/actions/offer_test.go b/services/horizon/internal/actions/offer_test.go index 41663c65d5..091dfba14c 100644 --- a/services/horizon/internal/actions/offer_test.go +++ b/services/horizon/internal/actions/offer_test.go @@ -79,7 +79,9 @@ func TestGetOfferByIDHandler(t *testing.T) { handler := GetOfferByID{} ledgerCloseTime := time.Now().Unix() - _, err := q.InsertLedger(tt.Ctx, xdr.LedgerHeaderHistoryEntry{ + assert.NoError(t, q.Begin(tt.Ctx)) + ledgerBatch := q.NewLedgerBatchInsertBuilder() + err := ledgerBatch.Add(xdr.LedgerHeaderHistoryEntry{ Header: xdr.LedgerHeader{ LedgerSeq: 3, ScpValue: xdr.StellarValue{ @@ -87,7 +89,9 @@ func TestGetOfferByIDHandler(t *testing.T) { }, }, }, 0, 0, 0, 0, 0) - tt.Assert.NoError(err) + assert.NoError(t, err) + assert.NoError(t, ledgerBatch.Exec(tt.Ctx, q)) + assert.NoError(t, q.Commit()) err = q.UpsertOffers(tt.Ctx, []history.Offer{eurOffer, usdOffer}) tt.Assert.NoError(err) @@ -186,7 +190,9 @@ func TestGetOffersHandler(t *testing.T) { handler := GetOffersHandler{} ledgerCloseTime := time.Now().Unix() - _, err := q.InsertLedger(tt.Ctx, xdr.LedgerHeaderHistoryEntry{ + assert.NoError(t, q.Begin(tt.Ctx)) + ledgerBatch := q.NewLedgerBatchInsertBuilder() + err := ledgerBatch.Add(xdr.LedgerHeaderHistoryEntry{ Header: xdr.LedgerHeader{ LedgerSeq: 3, ScpValue: xdr.StellarValue{ @@ -194,7 +200,9 @@ func TestGetOffersHandler(t *testing.T) { }, }, }, 0, 0, 0, 0, 0) - tt.Assert.NoError(err) + assert.NoError(t, err) + assert.NoError(t, ledgerBatch.Exec(tt.Ctx, q)) + assert.NoError(t, q.Commit()) err = q.UpsertOffers(tt.Ctx, []history.Offer{eurOffer, twoEurOffer, usdOffer}) tt.Assert.NoError(err) diff --git a/services/horizon/internal/actions/operation_test.go b/services/horizon/internal/actions/operation_test.go index 9144f5004c..9aa033fd24 100644 --- a/services/horizon/internal/actions/operation_test.go +++ b/services/horizon/internal/actions/operation_test.go @@ -2,19 +2,179 @@ package actions import ( "database/sql" + "encoding/hex" "fmt" "net/http/httptest" + "strings" "testing" "time" + "github.com/guregu/null" + "github.com/stellar/go/ingest" "github.com/stellar/go/protocols/horizon/operations" "github.com/stellar/go/services/horizon/internal/db2/history" "github.com/stellar/go/services/horizon/internal/ledger" "github.com/stellar/go/services/horizon/internal/render/problem" "github.com/stellar/go/services/horizon/internal/test" supportProblem "github.com/stellar/go/support/render/problem" + "github.com/stellar/go/toid" + "github.com/stellar/go/xdr" + "github.com/stretchr/testify/assert" ) +func TestInvokeHostFnDetailsInPaymentOperations(t *testing.T) { + tt := test.Start(t) + defer tt.Finish() + test.ResetHorizonDB(t, tt.HorizonDB) + + q := &history.Q{tt.HorizonSession()} + handler := GetOperationsHandler{OnlyPayments: true} + + txIndex := int32(1) + sequence := int32(56) + txID := toid.New(sequence, txIndex, 0).ToInt64() + opID1 := toid.New(sequence, txIndex, 1).ToInt64() + + ledgerCloseTime := time.Now().Unix() + ledgerBatch := q.NewLedgerBatchInsertBuilder() + err := ledgerBatch.Add( + xdr.LedgerHeaderHistoryEntry{ + Header: xdr.LedgerHeader{ + LedgerSeq: xdr.Uint32(sequence), + ScpValue: xdr.StellarValue{ + CloseTime: xdr.TimePoint(ledgerCloseTime), + }, + }, + }, 1, 0, 1, 0, 0) + tt.Assert.NoError(err) + tt.Assert.NoError(q.Begin(tt.Ctx)) + tt.Assert.NoError(ledgerBatch.Exec(tt.Ctx, q)) + + transactionBuilder := q.NewTransactionBatchInsertBuilder() + firstTransaction := buildLedgerTransaction(tt.T, testTransaction{ + index: uint32(txIndex), + envelopeXDR: "AAAAACiSTRmpH6bHC6Ekna5e82oiGY5vKDEEUgkq9CB//t+rAAAAyAEXUhsAADDRAAAAAAAAAAAAAAABAAAAAAAAAAsBF1IbAABX4QAAAAAAAAAA", + resultXDR: "AAAAAAAAASwAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAFAAAAAAAAAAA=", + feeChangesXDR: "AAAAAA==", + metaXDR: "AAAAAQAAAAAAAAAA", + hash: "19aaa18db88605aedec04659fb45e06f240b022eb2d429e05133e4d53cd945ba", + }) + err = transactionBuilder.Add(firstTransaction, uint32(sequence)) + tt.Assert.NoError(err) + tt.Assert.NoError(transactionBuilder.Exec(tt.Ctx, q)) + + operationBuilder := q.NewOperationBatchInsertBuilder() + + err = operationBuilder.Add( + opID1, + txID, + 1, + xdr.OperationTypeInvokeHostFunction, + []byte(`{ + "function": "HostFunctionTypeHostFunctionTypeInvokeContract", + "parameters": [ + { + "value": "AAAADwAAAAdmbl9uYW1lAA==", + "type": "Sym" + }, + { + "value": "AAAAAwAAAAI=", + "type": "U32" + } + ], + "asset_balance_changes": [ + { + "asset_type": "credit_alphanum4", + "asset_code": "abc", + "asset_issuer": "123", + "from": "C_CONTRACT_ADDRESS1", + "to": "G_CLASSIC_ADDRESS1", + "amount": "3", + "type": "transfer" + }, + { + "asset_type": "credit_alphanum4", + "asset_code": "abc", + "asset_issuer": "123", + "from": "G_CLASSIC_ADDRESS2", + "to": "G_CLASSIC_ADDRESS3", + "amount": "5", + "type": "clawback" + }, + { + "asset_type": "credit_alphanum4", + "asset_code": "abc", + "asset_issuer": "123", + "from": "G_CLASSIC_ADDRESS2", + "amount": "6", + "type": "burn" + }, + { + "asset_type": "credit_alphanum4", + "asset_code": "abc", + "asset_issuer": "123", + "from": "G_CLASSIC_ADDRESS2", + "to": "C_CONTRACT_ADDRESS3", + "amount": "10", + "type": "mint" + } + ] + }`), + "GAUJETIZVEP2NRYLUESJ3LS66NVCEGMON4UDCBCSBEVPIID773P2W6AY", + null.String{}, + true) + tt.Assert.NoError(err) + tt.Assert.NoError(operationBuilder.Exec(tt.Ctx, q)) + tt.Assert.NoError(q.Commit()) + + records, err := handler.GetResourcePage( + httptest.NewRecorder(), + makeRequest( + t, map[string]string{}, map[string]string{}, q, + ), + ) + tt.Assert.NoError(err) + tt.Assert.Len(records, 1) + + op := records[0].(operations.InvokeHostFunction) + tt.Assert.Equal(op.Function, "HostFunctionTypeHostFunctionTypeInvokeContract") + tt.Assert.Equal(len(op.Parameters), 2) + tt.Assert.Equal(op.Parameters[0].Value, "AAAADwAAAAdmbl9uYW1lAA==") + tt.Assert.Equal(op.Parameters[0].Type, "Sym") + tt.Assert.Equal(op.Parameters[1].Value, "AAAAAwAAAAI=") + tt.Assert.Equal(op.Parameters[1].Type, "U32") + + tt.Assert.Equal(len(op.AssetBalanceChanges), 4) + tt.Assert.Equal(op.AssetBalanceChanges[0].From, "C_CONTRACT_ADDRESS1") + tt.Assert.Equal(op.AssetBalanceChanges[0].To, "G_CLASSIC_ADDRESS1") + tt.Assert.Equal(op.AssetBalanceChanges[0].Amount, "3") + tt.Assert.Equal(op.AssetBalanceChanges[0].Type, "transfer") + tt.Assert.Equal(op.AssetBalanceChanges[0].Asset.Type, "credit_alphanum4") + tt.Assert.Equal(op.AssetBalanceChanges[0].Asset.Code, "abc") + tt.Assert.Equal(op.AssetBalanceChanges[0].Asset.Issuer, "123") + tt.Assert.Equal(op.AssetBalanceChanges[1].From, "G_CLASSIC_ADDRESS2") + tt.Assert.Equal(op.AssetBalanceChanges[1].To, "G_CLASSIC_ADDRESS3") + tt.Assert.Equal(op.AssetBalanceChanges[1].Amount, "5") + tt.Assert.Equal(op.AssetBalanceChanges[1].Type, "clawback") + tt.Assert.Equal(op.AssetBalanceChanges[1].Asset.Type, "credit_alphanum4") + tt.Assert.Equal(op.AssetBalanceChanges[1].Asset.Code, "abc") + tt.Assert.Equal(op.AssetBalanceChanges[1].Asset.Issuer, "123") + tt.Assert.Equal(op.AssetBalanceChanges[2].From, "G_CLASSIC_ADDRESS2") + tt.Assert.Equal(op.AssetBalanceChanges[2].To, "") + tt.Assert.Equal(op.AssetBalanceChanges[2].Amount, "6") + tt.Assert.Equal(op.AssetBalanceChanges[2].Type, "burn") + tt.Assert.Equal(op.AssetBalanceChanges[2].Asset.Type, "credit_alphanum4") + tt.Assert.Equal(op.AssetBalanceChanges[2].Asset.Code, "abc") + tt.Assert.Equal(op.AssetBalanceChanges[2].Asset.Issuer, "123") + tt.Assert.Equal(op.AssetBalanceChanges[3].From, "G_CLASSIC_ADDRESS2") + tt.Assert.Equal(op.AssetBalanceChanges[3].To, "C_CONTRACT_ADDRESS3") + tt.Assert.Equal(op.AssetBalanceChanges[3].Amount, "10") + tt.Assert.Equal(op.AssetBalanceChanges[3].Type, "mint") + tt.Assert.Equal(op.AssetBalanceChanges[3].Asset.Type, "credit_alphanum4") + tt.Assert.Equal(op.AssetBalanceChanges[3].Asset.Code, "abc") + tt.Assert.Equal(op.AssetBalanceChanges[3].Asset.Issuer, "123") +} + func TestGetOperationsWithoutFilter(t *testing.T) { tt := test.Start(t) defer tt.Finish() @@ -569,7 +729,7 @@ func TestGetOperationsPagination(t *testing.T) { ), ) tt.Assert.Error(err) - tt.Assert.EqualError(err, "problem: before_history") + tt.Assert.True(strings.Contains(err.Error(), "problem: before_history")) } func TestGetOperations_IncludeTransactions(t *testing.T) { @@ -695,3 +855,38 @@ func TestOperation_IncludeTransaction(t *testing.T) { tt.Assert.NotNil(op.Transaction) tt.Assert.Equal(op.TransactionHash, op.Transaction.ID) } + +type testTransaction struct { + index uint32 + envelopeXDR string + resultXDR string + feeChangesXDR string + metaXDR string + hash string +} + +func buildLedgerTransaction(t *testing.T, tx testTransaction) ingest.LedgerTransaction { + transaction := ingest.LedgerTransaction{ + Index: tx.index, + Envelope: xdr.TransactionEnvelope{}, + Result: xdr.TransactionResultPair{}, + FeeChanges: xdr.LedgerEntryChanges{}, + UnsafeMeta: xdr.TransactionMeta{}, + } + + tt := assert.New(t) + + err := xdr.SafeUnmarshalBase64(tx.envelopeXDR, &transaction.Envelope) + tt.NoError(err) + err = xdr.SafeUnmarshalBase64(tx.resultXDR, &transaction.Result.Result) + tt.NoError(err) + err = xdr.SafeUnmarshalBase64(tx.metaXDR, &transaction.UnsafeMeta) + tt.NoError(err) + err = xdr.SafeUnmarshalBase64(tx.feeChangesXDR, &transaction.FeeChanges) + tt.NoError(err) + + _, err = hex.Decode(transaction.Result.TransactionHash[:], []byte(tx.hash)) + tt.NoError(err) + + return transaction +} diff --git a/services/horizon/internal/actions/orderbook_test.go b/services/horizon/internal/actions/orderbook_test.go index b73191361a..5e3cdf0935 100644 --- a/services/horizon/internal/actions/orderbook_test.go +++ b/services/horizon/internal/actions/orderbook_test.go @@ -577,7 +577,7 @@ func TestOrderbookGetResource(t *testing.T) { assert.NoError(t, q.TruncateTables(tt.Ctx, []string{"offers"})) assert.NoError(t, q.UpsertOffers(tt.Ctx, offers)) - assert.NoError(t, q.BeginTx(&sql.TxOptions{ + assert.NoError(t, q.BeginTx(tt.Ctx, &sql.TxOptions{ Isolation: sql.LevelRepeatableRead, ReadOnly: true, })) diff --git a/services/horizon/internal/actions/path_test.go b/services/horizon/internal/actions/path_test.go index b481caf000..a7ebae38c3 100644 --- a/services/horizon/internal/actions/path_test.go +++ b/services/horizon/internal/actions/path_test.go @@ -27,7 +27,7 @@ func TestAssetsForAddressRequiresTransaction(t *testing.T) { _, _, err := assetsForAddress(r.WithContext(ctx), "GCATOZ7YJV2FANQQLX47TIV6P7VMPJCEEJGQGR6X7TONPKBN3UCLKEIS") assert.EqualError(t, err, "cannot be called outside of a transaction") - assert.NoError(t, q.Begin()) + assert.NoError(t, q.Begin(ctx)) defer q.Rollback() _, _, err = assetsForAddress(r.WithContext(ctx), "GCATOZ7YJV2FANQQLX47TIV6P7VMPJCEEJGQGR6X7TONPKBN3UCLKEIS") diff --git a/services/horizon/internal/actions/query_params_test.go b/services/horizon/internal/actions/query_params_test.go index 0f372885b5..793f9443c4 100644 --- a/services/horizon/internal/actions/query_params_test.go +++ b/services/horizon/internal/actions/query_params_test.go @@ -222,7 +222,7 @@ func TestSellingBuyingAssetQueryParams(t *testing.T) { } } -func TestSellingBuyingAssetQueryParamsWithCanonicalRepresenation(t *testing.T) { +func TestSellingBuyingAssetQueryParamsWithCanonicalRepresentation(t *testing.T) { testCases := []struct { desc string diff --git a/services/horizon/internal/actions/submit_transaction.go b/services/horizon/internal/actions/submit_transaction.go index 934b2ab14f..b877f75a7b 100644 --- a/services/horizon/internal/actions/submit_transaction.go +++ b/services/horizon/internal/actions/submit_transaction.go @@ -8,6 +8,7 @@ import ( "github.com/stellar/go/network" "github.com/stellar/go/protocols/horizon" + "github.com/stellar/go/protocols/stellarcore" hProblem "github.com/stellar/go/services/horizon/internal/render/problem" "github.com/stellar/go/services/horizon/internal/resourceadapter" "github.com/stellar/go/services/horizon/internal/txsub" @@ -24,6 +25,7 @@ type NetworkSubmitter interface { type SubmitTransactionHandler struct { Submitter NetworkSubmitter NetworkPassphrase string + DisableTxSub bool CoreStateGetter } @@ -34,7 +36,7 @@ type envelopeInfo struct { parsed xdr.TransactionEnvelope } -func extractEnvelopeInfo(raw string, passphrase string) (envelopeInfo, error) { +func (handler SubmitTransactionHandler) extractEnvelopeInfo(raw string, passphrase string) (envelopeInfo, error) { result := envelopeInfo{raw: raw} err := xdr.SafeUnmarshalBase64(raw, &result.parsed) if err != nil { @@ -94,15 +96,30 @@ func (handler SubmitTransactionHandler) response(r *http.Request, info envelopeI return nil, &hProblem.ClientDisconnected } - switch err := result.Err.(type) { - case *txsub.FailedTransactionError: + if failedErr, ok := result.Err.(*txsub.FailedTransactionError); ok { rcr := horizon.TransactionResultCodes{} - resourceadapter.PopulateTransactionResultCodes( + err := resourceadapter.PopulateTransactionResultCodes( r.Context(), info.hash, &rcr, - err, + failedErr, ) + if err != nil { + return nil, failedErr + } + + extras := map[string]interface{}{ + "envelope_xdr": info.raw, + "result_xdr": failedErr.ResultXDR, + "result_codes": rcr, + } + if failedErr.DiagnosticEventsXDR != "" { + events, err := stellarcore.DiagnosticEventsToSlice(failedErr.DiagnosticEventsXDR) + if err != nil { + return nil, err + } + extras["diagnostic_events"] = events + } return nil, &problem.P{ Type: "transaction_failed", @@ -112,11 +129,7 @@ func (handler SubmitTransactionHandler) response(r *http.Request, info envelopeI "The `extras.result_codes` field on this response contains further " + "details. Descriptions of each code can be found at: " + "https://developers.stellar.org/api/errors/http-status-codes/horizon-specific/transaction-failed/", - Extras: map[string]interface{}{ - "envelope_xdr": info.raw, - "result_xdr": err.ResultXDR, - "result_codes": rcr, - }, + Extras: extras, } } @@ -128,12 +141,23 @@ func (handler SubmitTransactionHandler) GetResource(w HeaderWriter, r *http.Requ return nil, err } + if handler.DisableTxSub { + return nil, &problem.P{ + Type: "transaction_submission_disabled", + Title: "Transaction Submission Disabled", + Status: http.StatusMethodNotAllowed, + Detail: "Transaction submission has been disabled for Horizon. " + + "To enable it again, remove env variable DISABLE_TX_SUB.", + Extras: map[string]interface{}{}, + } + } + raw, err := getString(r, "tx") if err != nil { return nil, err } - info, err := extractEnvelopeInfo(raw, handler.NetworkPassphrase) + info, err := handler.extractEnvelopeInfo(raw, handler.NetworkPassphrase) if err != nil { return nil, &problem.P{ Type: "transaction_malformed", diff --git a/services/horizon/internal/actions/submit_transaction_test.go b/services/horizon/internal/actions/submit_transaction_test.go index 0a93c9dba8..a15ce3bd94 100644 --- a/services/horizon/internal/actions/submit_transaction_test.go +++ b/services/horizon/internal/actions/submit_transaction_test.go @@ -9,15 +9,16 @@ import ( "testing" "time" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" + "github.com/stellar/go/network" "github.com/stellar/go/services/horizon/internal/corestate" hProblem "github.com/stellar/go/services/horizon/internal/render/problem" "github.com/stellar/go/services/horizon/internal/txsub" "github.com/stellar/go/support/render/problem" "github.com/stellar/go/xdr" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/mock" - "github.com/stretchr/testify/require" ) func TestStellarCoreMalformedTx(t *testing.T) { @@ -153,3 +154,93 @@ func TestClientDisconnectSubmission(t *testing.T) { _, err = handler.GetResource(w, request) assert.Equal(t, hProblem.ClientDisconnected, err) } + +func TestDisableTxSubFlagSubmission(t *testing.T) { + mockSubmitChannel := make(chan txsub.Result) + + mock := &coreStateGetterMock{} + mock.On("GetCoreState").Return(corestate.State{ + Synced: true, + }) + + mockSubmitter := &networkSubmitterMock{} + mockSubmitter.On("Submit").Return(mockSubmitChannel) + + handler := SubmitTransactionHandler{ + Submitter: mockSubmitter, + NetworkPassphrase: network.PublicNetworkPassphrase, + DisableTxSub: true, + CoreStateGetter: mock, + } + + form := url.Values{} + + var p = &problem.P{ + Type: "transaction_submission_disabled", + Title: "Transaction Submission Disabled", + Status: http.StatusMethodNotAllowed, + Detail: "Transaction submission has been disabled for Horizon. " + + "To enable it again, remove env variable DISABLE_TX_SUB.", + Extras: map[string]interface{}{}, + } + + request, err := http.NewRequest( + "POST", + "https://horizon.stellar.org/transactions", + strings.NewReader(form.Encode()), + ) + + require.NoError(t, err) + request.Header.Add("Content-Type", "application/x-www-form-urlencoded") + ctx, cancel := context.WithCancel(request.Context()) + cancel() + request = request.WithContext(ctx) + + w := httptest.NewRecorder() + _, err = handler.GetResource(w, request) + assert.Equal(t, p, err) +} + +func TestSubmissionSorobanDiagnosticEvents(t *testing.T) { + mockSubmitChannel := make(chan txsub.Result, 1) + mock := &coreStateGetterMock{} + mock.On("GetCoreState").Return(corestate.State{ + Synced: true, + }) + + mockSubmitter := &networkSubmitterMock{} + mockSubmitter.On("Submit").Return(mockSubmitChannel) + mockSubmitChannel <- txsub.Result{ + Err: &txsub.FailedTransactionError{ + ResultXDR: "AAAAAAABCdf////vAAAAAA==", + DiagnosticEventsXDR: "AAAAAQAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAgAAAA8AAAAFZXJyb3IAAAAAAAACAAAAAwAAAAUAAAAQAAAAAQAAAAMAAAAOAAAAU3RyYW5zYWN0aW9uIGBzb3JvYmFuRGF0YS5yZXNvdXJjZUZlZWAgaXMgbG93ZXIgdGhhbiB0aGUgYWN0dWFsIFNvcm9iYW4gcmVzb3VyY2UgZmVlAAAAAAUAAAAAAAEJcwAAAAUAAAAAAAG6fA==", + }, + } + + handler := SubmitTransactionHandler{ + Submitter: mockSubmitter, + NetworkPassphrase: network.PublicNetworkPassphrase, + CoreStateGetter: mock, + } + + form := url.Values{} + form.Set("tx", "AAAAAAGUcmKO5465JxTSLQOQljwk2SfqAJmZSG6JH6wtqpwhAAABLAAAAAAAAAABAAAAAAAAAAEAAAALaGVsbG8gd29ybGQAAAAAAwAAAAAAAAAAAAAAABbxCy3mLg3hiTqX4VUEEp60pFOrJNxYM1JtxXTwXhY2AAAAAAvrwgAAAAAAAAAAAQAAAAAW8Qst5i4N4Yk6l+FVBBKetKRTqyTcWDNSbcV08F4WNgAAAAAN4Lazj4x61AAAAAAAAAAFAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABLaqcIQAAAEBKwqWy3TaOxoGnfm9eUjfTRBvPf34dvDA0Nf+B8z4zBob90UXtuCqmQqwMCyH+okOI3c05br3khkH0yP4kCwcE") + + request, err := http.NewRequest( + "POST", + "https://horizon.stellar.org/transactions", + strings.NewReader(form.Encode()), + ) + + require.NoError(t, err) + request.Header.Add("Content-Type", "application/x-www-form-urlencoded") + + w := httptest.NewRecorder() + _, err = handler.GetResource(w, request) + require.Error(t, err) + require.IsType(t, &problem.P{}, err) + require.Contains(t, err.(*problem.P).Extras, "diagnostic_events") + require.IsType(t, []string{}, err.(*problem.P).Extras["diagnostic_events"]) + diagnosticEvents := err.(*problem.P).Extras["diagnostic_events"].([]string) + require.Equal(t, diagnosticEvents, []string{"AAAAAAAAAAAAAAAAAAAAAgAAAAAAAAACAAAADwAAAAVlcnJvcgAAAAAAAAIAAAADAAAABQAAABAAAAABAAAAAwAAAA4AAABTdHJhbnNhY3Rpb24gYHNvcm9iYW5EYXRhLnJlc291cmNlRmVlYCBpcyBsb3dlciB0aGFuIHRoZSBhY3R1YWwgU29yb2JhbiByZXNvdXJjZSBmZWUAAAAABQAAAAAAAQlzAAAABQAAAAAAAbp8"}) +} diff --git a/services/horizon/internal/actions/transaction.go b/services/horizon/internal/actions/transaction.go index 9b527afb46..f823ad9acb 100644 --- a/services/horizon/internal/actions/transaction.go +++ b/services/horizon/internal/actions/transaction.go @@ -172,7 +172,7 @@ func loadTransactionRecords(ctx context.Context, hq *history.Q, qp TransactionsQ var resultXDR xdr.TransactionResult err = xdr.SafeUnmarshalBase64(t.TxResult, &resultXDR) if err != nil { - return nil, errors.Wrap(err, "unmarshalling tx result") + return nil, errors.Wrap(err, "unmarshaling tx result") } if !resultXDR.Successful() { diff --git a/services/horizon/internal/actions/transaction_test.go b/services/horizon/internal/actions/transaction_test.go index e029edef3a..b76cf1b0bf 100644 --- a/services/horizon/internal/actions/transaction_test.go +++ b/services/horizon/internal/actions/transaction_test.go @@ -149,6 +149,7 @@ func checkOuterHashResponse( } func TestFeeBumpTransactionPage(t *testing.T) { + tt := test.Start(t) defer tt.Finish() test.ResetHorizonDB(t, tt.HorizonDB) diff --git a/services/horizon/internal/actions_account_test.go b/services/horizon/internal/actions_account_test.go index 541300c3a6..1fa2b12b14 100644 --- a/services/horizon/internal/actions_account_test.go +++ b/services/horizon/internal/actions_account_test.go @@ -18,12 +18,17 @@ func TestAccountActions_InvalidID(t *testing.T) { ht.Assert.NoError(err) err = q.UpdateIngestVersion(ht.Ctx, ingest.CurrentVersion) ht.Assert.NoError(err) - _, err = q.InsertLedger(ht.Ctx, xdr.LedgerHeaderHistoryEntry{ + + ht.Assert.NoError(q.Begin(ht.Ctx)) + ledgerBatch := q.NewLedgerBatchInsertBuilder() + err = ledgerBatch.Add(xdr.LedgerHeaderHistoryEntry{ Header: xdr.LedgerHeader{ LedgerSeq: 100, }, }, 0, 0, 0, 0, 0) ht.Assert.NoError(err) + ht.Assert.NoError(ledgerBatch.Exec(ht.Ctx, q)) + ht.Assert.NoError(q.Commit()) // existing account w := ht.Get( diff --git a/services/horizon/internal/actions_data_test.go b/services/horizon/internal/actions_data_test.go index 3de82a915d..1142a4000a 100644 --- a/services/horizon/internal/actions_data_test.go +++ b/services/horizon/internal/actions_data_test.go @@ -44,12 +44,16 @@ func TestDataActions_Show(t *testing.T) { ht.Assert.NoError(err) err = q.UpdateIngestVersion(ht.Ctx, ingest.CurrentVersion) ht.Assert.NoError(err) - _, err = q.InsertLedger(ht.Ctx, xdr.LedgerHeaderHistoryEntry{ + ht.Assert.NoError(q.Begin(ht.Ctx)) + ledgerBatch := q.NewLedgerBatchInsertBuilder() + err = ledgerBatch.Add(xdr.LedgerHeaderHistoryEntry{ Header: xdr.LedgerHeader{ LedgerSeq: 100, }, }, 0, 0, 0, 0, 0) ht.Assert.NoError(err) + ht.Assert.NoError(ledgerBatch.Exec(ht.Ctx, q)) + ht.Assert.NoError(q.Commit()) err = q.UpsertAccountData(ht.Ctx, []history.Data{data1, data2}) assert.NoError(t, err) diff --git a/services/horizon/internal/actions_path_test.go b/services/horizon/internal/actions_path_test.go index 1bb2bc8df6..4ee7a1fea4 100644 --- a/services/horizon/internal/actions_path_test.go +++ b/services/horizon/internal/actions_path_test.go @@ -52,10 +52,10 @@ func mockPathFindingClient( router.Use(func(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { s := session.Clone() - s.BeginTx(&sql.TxOptions{ + tt.Assert.NoError(s.BeginTx(r.Context(), &sql.TxOptions{ Isolation: sql.LevelRepeatableRead, ReadOnly: true, - }) + })) defer s.Rollback() ctx := context.WithValue( diff --git a/services/horizon/internal/actions_trade_test.go b/services/horizon/internal/actions_trade_test.go index 1aa7b157fb..72991c5da2 100644 --- a/services/horizon/internal/actions_trade_test.go +++ b/services/horizon/internal/actions_trade_test.go @@ -820,8 +820,11 @@ func IngestTestTrade( return err } - batch := q.NewTradeBatchInsertBuilder(0) - batch.Add(ctx, history.InsertTrade{ + if err = q.Begin(ctx); err != nil { + return err + } + batch := q.NewTradeBatchInsertBuilder() + err = batch.Add(history.InsertTrade{ HistoryOperationID: opCounter, Order: 0, CounterAssetID: assets[assetBought.String()].ID, @@ -839,7 +842,10 @@ func IngestTestTrade( Type: history.OrderbookTradeType, }) - err = batch.Exec(ctx) + if err != nil { + return err + } + err = batch.Exec(ctx, q) if err != nil { return err } @@ -849,6 +855,10 @@ func IngestTestTrade( return err } + if err := q.Commit(); err != nil { + return err + } + return nil } diff --git a/services/horizon/internal/app.go b/services/horizon/internal/app.go index 6b9376b759..b1cd7a1c85 100644 --- a/services/horizon/internal/app.go +++ b/services/horizon/internal/app.go @@ -7,6 +7,7 @@ import ( "net/http" "os" "os/signal" + "strings" "sync" "syscall" "time" @@ -19,7 +20,6 @@ import ( "github.com/stellar/go/services/horizon/internal/httpx" "github.com/stellar/go/services/horizon/internal/ingest" "github.com/stellar/go/services/horizon/internal/ledger" - "github.com/stellar/go/services/horizon/internal/logmetrics" "github.com/stellar/go/services/horizon/internal/operationfeestats" "github.com/stellar/go/services/horizon/internal/paths" "github.com/stellar/go/services/horizon/internal/reap" @@ -28,6 +28,7 @@ import ( "github.com/stellar/go/support/db" "github.com/stellar/go/support/errors" "github.com/stellar/go/support/log" + "github.com/stellar/go/support/logmetrics" ) // App represents the root of the state of a horizon instance. @@ -118,22 +119,6 @@ func (a *App) Serve() error { signalChan := make(chan os.Signal, 1) signal.Notify(signalChan, os.Interrupt, syscall.SIGINT, syscall.SIGTERM) - if a.config.UsingDefaultPubnetConfig { - const warnMsg = "Horizon started using the default pubnet configuration. " + - "This is not safe! Please provide a custom --captive-core-config-path." - log.Warn(warnMsg) - go func() { - for { - select { - case <-time.After(time.Hour): - log.Warn(warnMsg) - case <-a.done: - return - } - } - }() - } - go func() { select { case <-signalChan: @@ -212,12 +197,30 @@ func (a *App) Paths() paths.Finder { return a.paths } +func isLocalAddress(url string, port uint) bool { + localHostURL := fmt.Sprintf("http://localhost:%d", port) + localIPURL := fmt.Sprintf("http://127.0.0.1:%d", port) + + return strings.HasPrefix(url, localHostURL) || strings.HasPrefix(url, localIPURL) +} + // UpdateCoreLedgerState triggers a refresh of Stellar-Core ledger state. // This is done separately from Horizon ledger state update to prevent issues // in case Stellar-Core query timeout. func (a *App) UpdateCoreLedgerState(ctx context.Context) { var next ledger.CoreStatus + if a.config.StellarCoreURL == "" { + return + } + // #4446 If the ingestion state machine is in the build state, the query can time out + // because the captive-core buffer may be full. In this case, skip the check. + if a.config.CaptiveCoreToml != nil && + isLocalAddress(a.config.StellarCoreURL, a.config.CaptiveCoreToml.HTTPPort) && + a.ingester != nil && a.ingester.GetCurrentState() == ingest.Build { + return + } + logErr := func(err error, msg string) { log.WithStack(err).WithField("err", err.Error()).Error(msg) } @@ -400,6 +403,14 @@ func (a *App) UpdateStellarCoreInfo(ctx context.Context) error { return nil } + // #4446 If the ingestion state machine is in the build state, the query can time out + // because the captive-core buffer may be full. In this case, skip the check. + if a.config.CaptiveCoreToml != nil && + isLocalAddress(a.config.StellarCoreURL, a.config.CaptiveCoreToml.HTTPPort) && + a.ingester != nil && a.ingester.GetCurrentState() == ingest.Build { + return nil + } + core := &stellarcore.Client{ URL: a.config.StellarCoreURL, } @@ -464,7 +475,8 @@ func (a *App) init() error { // log log.DefaultLogger.SetLevel(a.config.LogLevel) - log.DefaultLogger.AddHook(logmetrics.DefaultMetrics) + logMetrics := logmetrics.New("horizon") + log.DefaultLogger.AddHook(logMetrics) // sentry initSentry(a) @@ -474,8 +486,8 @@ func (a *App) init() error { // metrics and log.metrics a.prometheusRegistry = prometheus.NewRegistry() - for _, meter := range *logmetrics.DefaultMetrics { - a.prometheusRegistry.MustRegister(meter) + for _, counter := range logMetrics { + a.prometheusRegistry.MustRegister(counter) } // stellarCoreInfo @@ -512,22 +524,25 @@ func (a *App) init() error { initTxSubMetrics(a) routerConfig := httpx.RouterConfig{ - DBSession: a.historyQ.SessionInterface, - TxSubmitter: a.submitter, - RateQuota: a.config.RateQuota, - BehindCloudflare: a.config.BehindCloudflare, - BehindAWSLoadBalancer: a.config.BehindAWSLoadBalancer, - SSEUpdateFrequency: a.config.SSEUpdateFrequency, - StaleThreshold: a.config.StaleThreshold, - ConnectionTimeout: a.config.ConnectionTimeout, - NetworkPassphrase: a.config.NetworkPassphrase, - MaxPathLength: a.config.MaxPathLength, - MaxAssetsPerPathRequest: a.config.MaxAssetsPerPathRequest, - PathFinder: a.paths, - PrometheusRegistry: a.prometheusRegistry, - CoreGetter: a, - HorizonVersion: a.horizonVersion, - FriendbotURL: a.config.FriendbotURL, + DBSession: a.historyQ.SessionInterface, + TxSubmitter: a.submitter, + RateQuota: a.config.RateQuota, + BehindCloudflare: a.config.BehindCloudflare, + BehindAWSLoadBalancer: a.config.BehindAWSLoadBalancer, + SSEUpdateFrequency: a.config.SSEUpdateFrequency, + StaleThreshold: a.config.StaleThreshold, + ConnectionTimeout: a.config.ConnectionTimeout, + MaxHTTPRequestSize: a.config.MaxHTTPRequestSize, + NetworkPassphrase: a.config.NetworkPassphrase, + MaxPathLength: a.config.MaxPathLength, + MaxAssetsPerPathRequest: a.config.MaxAssetsPerPathRequest, + PathFinder: a.paths, + PrometheusRegistry: a.prometheusRegistry, + CoreGetter: a, + HorizonVersion: a.horizonVersion, + FriendbotURL: a.config.FriendbotURL, + EnableIngestionFiltering: a.config.EnableIngestionFiltering, + DisableTxSub: a.config.DisableTxSub, HealthCheck: healthCheck{ session: a.historyQ.SessionInterface, ctx: a.ctx, @@ -537,7 +552,6 @@ func (a *App) init() error { }, cache: newHealthCache(healthCacheTTL), }, - EnableIngestionFiltering: a.config.EnableIngestionFiltering, } if a.primaryHistoryQ != nil { diff --git a/services/horizon/internal/codes/main.go b/services/horizon/internal/codes/main.go index 4e51fd5074..ebf90a0233 100644 --- a/services/horizon/internal/codes/main.go +++ b/services/horizon/internal/codes/main.go @@ -4,6 +4,7 @@ package codes import ( "github.com/go-errors/errors" + "github.com/stellar/go/xdr" ) @@ -78,6 +79,8 @@ func String(code interface{}) (string, error) { return "tx_bad_minseq_age_or_gap", nil case xdr.TransactionResultCodeTxMalformed: return "tx_malformed", nil + case xdr.TransactionResultCodeTxSorobanInvalid: + return "tx_soroban_invalid", nil } case xdr.OperationResultCode: switch code { @@ -491,6 +494,43 @@ func String(code interface{}) (string, error) { case xdr.LiquidityPoolWithdrawResultCodeLiquidityPoolWithdrawUnderMinimum: return "op_under_minimum", nil } + case xdr.InvokeHostFunctionResultCode: + switch code { + case xdr.InvokeHostFunctionResultCodeInvokeHostFunctionSuccess: + return OpSuccess, nil + case xdr.InvokeHostFunctionResultCodeInvokeHostFunctionMalformed: + return OpMalformed, nil + case xdr.InvokeHostFunctionResultCodeInvokeHostFunctionTrapped: + return "function_trapped", nil + case xdr.InvokeHostFunctionResultCodeInvokeHostFunctionResourceLimitExceeded: + return "resource_limit_exceeded", nil + case xdr.InvokeHostFunctionResultCodeInvokeHostFunctionEntryArchived: + return "entry_archived", nil + case xdr.InvokeHostFunctionResultCodeInvokeHostFunctionInsufficientRefundableFee: + return "insufficient_refundable_fee", nil + } + case xdr.ExtendFootprintTtlResultCode: + switch code { + case xdr.ExtendFootprintTtlResultCodeExtendFootprintTtlSuccess: + return OpSuccess, nil + case xdr.ExtendFootprintTtlResultCodeExtendFootprintTtlMalformed: + return OpMalformed, nil + case xdr.ExtendFootprintTtlResultCodeExtendFootprintTtlResourceLimitExceeded: + return "resource_limit_exceeded", nil + case xdr.ExtendFootprintTtlResultCodeExtendFootprintTtlInsufficientRefundableFee: + return "insufficient_refundable_fee", nil + } + case xdr.RestoreFootprintResultCode: + switch code { + case xdr.RestoreFootprintResultCodeRestoreFootprintSuccess: + return OpSuccess, nil + case xdr.RestoreFootprintResultCodeRestoreFootprintMalformed: + return OpMalformed, nil + case xdr.RestoreFootprintResultCodeRestoreFootprintResourceLimitExceeded: + return "resource_limit_exceeded", nil + case xdr.RestoreFootprintResultCodeRestoreFootprintInsufficientRefundableFee: + return "insufficient_refundable_fee", nil + } } return "", errors.New(ErrUnknownCode) @@ -555,6 +595,12 @@ func ForOperationResult(opr xdr.OperationResult) (string, error) { ic = ir.MustLiquidityPoolDepositResult().Code case xdr.OperationTypeLiquidityPoolWithdraw: ic = ir.MustLiquidityPoolWithdrawResult().Code + case xdr.OperationTypeInvokeHostFunction: + ic = ir.MustInvokeHostFunctionResult().Code + case xdr.OperationTypeExtendFootprintTtl: + ic = ir.MustExtendFootprintTtlResult().Code + case xdr.OperationTypeRestoreFootprint: + ic = ir.MustRestoreFootprintResult().Code } return String(ic) diff --git a/services/horizon/internal/codes/main_test.go b/services/horizon/internal/codes/main_test.go index 1a0ce3e601..88c622440a 100644 --- a/services/horizon/internal/codes/main_test.go +++ b/services/horizon/internal/codes/main_test.go @@ -5,8 +5,9 @@ import ( "reflect" "testing" - "github.com/stellar/go/xdr" "github.com/stretchr/testify/assert" + + "github.com/stellar/go/xdr" ) func TestForOperationResultCoversForAllOpTypes(t *testing.T) { @@ -50,6 +51,9 @@ func TestForOperationResultCoversForAllOpTypes(t *testing.T) { xdr.OperationTypeSetTrustLineFlags: reflect.TypeOf(xdr.SetTrustLineFlagsResultCode(0)), xdr.OperationTypeLiquidityPoolDeposit: reflect.TypeOf(xdr.LiquidityPoolDepositResultCode(0)), xdr.OperationTypeLiquidityPoolWithdraw: reflect.TypeOf(xdr.LiquidityPoolWithdrawResultCode(0)), + xdr.OperationTypeInvokeHostFunction: reflect.TypeOf(xdr.InvokeHostFunctionResultCode(0)), + xdr.OperationTypeExtendFootprintTtl: reflect.TypeOf(xdr.ExtendFootprintTtlResultCode(0)), + xdr.OperationTypeRestoreFootprint: reflect.TypeOf(xdr.RestoreFootprintResultCode(0)), } // If this is not equal it means one or more result struct is missing in resultTypes map. assert.Equal(t, len(xdr.OperationTypeToStringMap), len(resultTypes)) diff --git a/services/horizon/internal/config.go b/services/horizon/internal/config.go index 886254fd20..1cc14b4900 100644 --- a/services/horizon/internal/config.go +++ b/services/horizon/internal/config.go @@ -19,9 +19,7 @@ type Config struct { Port uint AdminPort uint - EnableCaptiveCoreIngestion bool EnableIngestionFiltering bool - UsingDefaultPubnetConfig bool CaptiveCoreBinaryPath string RemoteCaptiveCoreURL string CaptiveCoreConfigPath string @@ -31,8 +29,7 @@ type Config struct { CaptiveCoreReuseStoragePath bool CaptiveCoreConfigUseDB bool - StellarCoreDatabaseURL string - StellarCoreURL string + StellarCoreURL string // MaxDBConnections has a priority over all 4 values below. MaxDBConnections int @@ -41,6 +38,8 @@ type Config struct { SSEUpdateFrequency time.Duration ConnectionTimeout time.Duration + // MaxHTTPRequestSize is the maximum allowed request payload size + MaxHTTPRequestSize uint RateQuota *throttled.RateQuota FriendbotURL *url.URL LogLevel logrus.Level @@ -48,7 +47,7 @@ type Config struct { // MaxPathLength is the maximum length of the path returned by `/paths` endpoint. MaxPathLength uint - // MaxAssetsPerPathRequest is the maximum number of assets considered for `/paths/strict-send` and `/paths/strict-recieve` + // MaxAssetsPerPathRequest is the maximum number of assets considered for `/paths/strict-send` and `/paths/strict-receive` MaxAssetsPerPathRequest int // DisablePoolPathFinding configures horizon to run path finding without including liquidity pools // in the path finding search. @@ -89,6 +88,14 @@ type Config struct { // IngestDisableStateVerification disables state verification // `System.verifyState()` when set to `true`. IngestDisableStateVerification bool + // IngestStateVerificationCheckpointFrequency configures how often state verification is performed. + // If IngestStateVerificationCheckpointFrequency is set to 1 state verification is run on every checkpoint, + // If IngestStateVerificationCheckpointFrequency is set to 2 state verification is run on every second checkpoint, + // etc... + IngestStateVerificationCheckpointFrequency uint + // IngestStateVerificationTimeout configures a timeout on the state verification routine. + // If IngestStateVerificationTimeout is set to 0 the timeout is disabled. + IngestStateVerificationTimeout time.Duration // IngestEnableExtendedLogLedgerStats enables extended ledger stats in // logging. IngestEnableExtendedLogLedgerStats bool @@ -106,4 +113,8 @@ type Config struct { BehindAWSLoadBalancer bool // RoundingSlippageFilter excludes trades from /trade_aggregations with rounding slippage >x bps RoundingSlippageFilter int + // Stellar network: 'testnet' or 'pubnet' + Network string + // DisableTxSub disables transaction submission functionality for Horizon. + DisableTxSub bool } diff --git a/services/horizon/configs/captive-core-pubnet.cfg b/services/horizon/internal/configs/captive-core-pubnet.cfg similarity index 82% rename from services/horizon/configs/captive-core-pubnet.cfg rename to services/horizon/internal/configs/captive-core-pubnet.cfg index 9de0a062c8..31fdb238bc 100644 --- a/services/horizon/configs/captive-core-pubnet.cfg +++ b/services/horizon/internal/configs/captive-core-pubnet.cfg @@ -1,7 +1,14 @@ +<<<<<<<< HEAD:exp/lighthorizon/build/ledgerexporter/captive-core-pubnet.cfg +PEER_PORT=11725 +DATABASE = "sqlite3:///cc/stellar.db" + +FAILURE_SAFETY=1 +======== # WARNING! Do not use this config in production. Quorum sets should # be carefully selected manually. NETWORK_PASSPHRASE="Public Global Stellar Network ; September 2015" HTTP_PORT=11626 +>>>>>>>> master:services/horizon/internal/configs/captive-core-pubnet.cfg [[HOME_DOMAINS]] HOME_DOMAIN="stellar.org" @@ -28,8 +35,8 @@ HOME_DOMAIN="stellar.blockdaemon.com" QUALITY="HIGH" [[HOME_DOMAINS]] -HOME_DOMAIN="wirexapp.com" -QUALITY="HIGH" +HOME_DOMAIN = "www.franklintempleton.com" +QUALITY = "HIGH" [[VALIDATORS]] NAME="sdf_1" @@ -172,22 +179,30 @@ ADDRESS="stellar-full-validator3.bdnodes.net" HISTORY="curl -sf https://stellar-full-history3.bdnodes.net/{0} -o {1}" [[VALIDATORS]] -NAME="wirexUS" -ADDRESS="us.stellar.wirexapp.com" -HOME_DOMAIN="wirexapp.com" -PUBLIC_KEY="GDXUKFGG76WJC7ACEH3JUPLKM5N5S76QSMNDBONREUXPCZYVPOLFWXUS" -HISTORY="curl -sf http://wxhorizonusstga1.blob.core.windows.net/history/{0} -o {1}" +NAME = "FT_SCV_1" +HOME_DOMAIN = "www.franklintempleton.com" +PUBLIC_KEY = "GARYGQ5F2IJEBCZJCBNPWNWVDOFK7IBOHLJKKSG2TMHDQKEEC6P4PE4V" +ADDRESS = "stellar1.franklintempleton.com:11625" +HISTORY = "curl -sf https://stellar-history-usw.franklintempleton.com/azuswshf401/{0} -o {1}" [[VALIDATORS]] -NAME="wirexUK" -ADDRESS="uk.stellar.wirexapp.com" -HOME_DOMAIN="wirexapp.com" -PUBLIC_KEY="GBBQQT3EIUSXRJC6TGUCGVA3FVPXVZLGG3OJYACWBEWYBHU46WJLWXEU" -HISTORY="curl -sf http://wxhorizonukstga1.blob.core.windows.net/history/{0} -o {1}" +NAME = "FT_SCV_2" +HOME_DOMAIN = "www.franklintempleton.com" +PUBLIC_KEY = "GCMSM2VFZGRPTZKPH5OABHGH4F3AVS6XTNJXDGCZ3MKCOSUBH3FL6DOB" +ADDRESS = "stellar2.franklintempleton.com:11625" +HISTORY = "curl -sf https://stellar-history-usc.franklintempleton.com/azuscshf401/{0} -o {1}" [[VALIDATORS]] +<<<<<<<< HEAD:exp/lighthorizon/build/ledgerexporter/captive-core-pubnet.cfg NAME="wirexSG" ADDRESS="sg.stellar.wirexapp.com" HOME_DOMAIN="wirexapp.com" PUBLIC_KEY="GAB3GZIE6XAYWXGZUDM4GMFFLJBFMLE2JDPUCWUZXMOMT3NHXDHEWXAS" -HISTORY="curl -sf http://wxhorizonasiastga1.blob.core.windows.net/history/{0} -o {1}" \ No newline at end of file +HISTORY="curl -sf http://wxhorizonasiastga1.blob.core.windows.net/history/{0} -o {1}" +======== +NAME = "FT_SCV_3" +HOME_DOMAIN = "www.franklintempleton.com" +PUBLIC_KEY = "GA7DV63PBUUWNUFAF4GAZVXU2OZMYRATDLKTC7VTCG7AU4XUPN5VRX4A" +ADDRESS = "stellar3.franklintempleton.com:11625" +HISTORY = "curl -sf https://stellar-history-ins.franklintempleton.com/azinsshf401/{0} -o {1}" +>>>>>>>> master:services/horizon/internal/configs/captive-core-pubnet.cfg diff --git a/services/horizon/configs/captive-core-testnet.cfg b/services/horizon/internal/configs/captive-core-testnet.cfg similarity index 100% rename from services/horizon/configs/captive-core-testnet.cfg rename to services/horizon/internal/configs/captive-core-testnet.cfg diff --git a/services/horizon/internal/db2/assets/asset_stat.go b/services/horizon/internal/db2/assets/asset_stat.go deleted file mode 100644 index c7a5e69eec..0000000000 --- a/services/horizon/internal/db2/assets/asset_stat.go +++ /dev/null @@ -1,60 +0,0 @@ -package assets - -import ( - sq "github.com/Masterminds/squirrel" - "github.com/stellar/go/services/horizon/internal/db2" -) - -// PagingToken implementation for hal.Pageable -//func (res AssetStat) PagingToken() string { -// return res.PT -//} - -// AssetStatsQ is the query to fetch all assets in the system -type AssetStatsQ struct { - AssetCode *string - AssetIssuer *string - PageQuery *db2.PageQuery -} - -// GetSQL allows this query to be executed by the caller -func (q AssetStatsQ) GetSQL() (sq.SelectBuilder, error) { - sql := selectQuery - if q.AssetCode != nil && *q.AssetCode != "" { - sql = sql.Where("hist.asset_code = ?", *q.AssetCode) - } - if q.AssetIssuer != nil && *q.AssetIssuer != "" { - sql = sql.Where("hist.asset_issuer = ?", *q.AssetIssuer) - } - - var err error - if q.PageQuery != nil { - // cursor needs to work for descending case as well - cursor := q.PageQuery.Cursor - if q.PageQuery.Order == "desc" && cursor == "" { - cursor = "zzzzzzzzzzzzz" // 12 + 1 "z"s so it will always be greater than the _ delimiter since code is max 12 chars - } - - sql, err = q.PageQuery.ApplyToUsingCursor(sql, "concat(hist.asset_code, '_', hist.asset_issuer, '_', hist.asset_type)", cursor) - if err != nil { - return sql, err - } - } else { - sql = sql.OrderBy("sort_key ASC") - } - return sql, nil -} - -var selectQuery = sq. - Select( - "concat(hist.asset_code, '_', hist.asset_issuer, '_', hist.asset_type) as sort_key", - "hist.asset_type", - "hist.asset_code", - "hist.asset_issuer", - "stats.amount", - "stats.num_accounts", - "stats.flags", - "stats.toml", - ). - From("history_assets hist"). - Join("asset_stats stats ON hist.id = stats.id") diff --git a/services/horizon/internal/db2/assets/asset_stat_test.go b/services/horizon/internal/db2/assets/asset_stat_test.go deleted file mode 100644 index c87edc19cb..0000000000 --- a/services/horizon/internal/db2/assets/asset_stat_test.go +++ /dev/null @@ -1,107 +0,0 @@ -package assets - -import ( - "context" - "strconv" - "testing" - - "github.com/stellar/go/services/horizon/internal/db2" - "github.com/stellar/go/services/horizon/internal/db2/history" - "github.com/stellar/go/services/horizon/internal/test" -) - -// AssetStatsR is the result from the AssetStatsQ query -type AssetStatsR struct { - SortKey string `db:"sort_key"` - Type string `db:"asset_type"` - Code string `db:"asset_code"` - Issuer string `db:"asset_issuer"` - Amount string `db:"amount"` - NumAccounts int32 `db:"num_accounts"` - Flags int8 `db:"flags"` - Toml string `db:"toml"` -} - -func TestAssetsStatsQExec(t *testing.T) { - item0 := AssetStatsR{ - SortKey: "BTC_GC23QF2HUE52AMXUFUH3AYJAXXGXXV2VHXYYR6EYXETPKDXZSAW67XO4_credit_alphanum4", - Type: "credit_alphanum4", - Code: "BTC", - Issuer: "GC23QF2HUE52AMXUFUH3AYJAXXGXXV2VHXYYR6EYXETPKDXZSAW67XO4", - Amount: "1009876000", - NumAccounts: 1, - Flags: 1, - Toml: "https://test.com/.well-known/stellar.toml", - } - - item1 := AssetStatsR{ - SortKey: "SCOT_GCXKG6RN4ONIEPCMNFB732A436Z5PNDSRLGWK7GBLCMQLIFO4S7EYWVU_credit_alphanum4", - Type: "credit_alphanum4", - Code: "SCOT", - Issuer: "GCXKG6RN4ONIEPCMNFB732A436Z5PNDSRLGWK7GBLCMQLIFO4S7EYWVU", - Amount: "10000000000", - NumAccounts: 1, - Flags: 2, - Toml: "", - } - - item2 := AssetStatsR{ - SortKey: "USD_GC23QF2HUE52AMXUFUH3AYJAXXGXXV2VHXYYR6EYXETPKDXZSAW67XO4_credit_alphanum4", - Type: "credit_alphanum4", - Code: "USD", - Issuer: "GC23QF2HUE52AMXUFUH3AYJAXXGXXV2VHXYYR6EYXETPKDXZSAW67XO4", - Amount: "3000010434000", - NumAccounts: 2, - Flags: 1, - Toml: "https://test.com/.well-known/stellar.toml", - } - - testCases := []struct { - query AssetStatsQ - want []AssetStatsR - }{ - { - AssetStatsQ{}, - []AssetStatsR{item0, item1, item2}, - }, { - AssetStatsQ{ - PageQuery: &db2.PageQuery{ - Order: "asc", - Limit: 10, - }, - }, - []AssetStatsR{item0, item1, item2}, - }, { - AssetStatsQ{ - PageQuery: &db2.PageQuery{ - Order: "desc", - Limit: 10, - }, - }, - []AssetStatsR{item2, item1, item0}, - }, - } - - for i, kase := range testCases { - t.Run(strconv.Itoa(i), func(t *testing.T) { - tt := test.Start(t) - tt.Scenario("ingest_asset_stats") - defer tt.Finish() - - sql, err := kase.query.GetSQL() - tt.Require.NoError(err) - - var results []AssetStatsR - err = history.Q{SessionInterface: tt.HorizonSession()}.Select(context.Background(), &results, sql) - tt.Require.NoError(err) - if !tt.Assert.Equal(3, len(results)) { - return - } - - tt.Assert.Equal(len(kase.want), len(results)) - for i := range kase.want { - tt.Assert.Equal(kase.want[i], results[i]) - } - }) - } -} diff --git a/services/horizon/internal/db2/history/account_data_batch_insert_builder.go b/services/horizon/internal/db2/history/account_data_batch_insert_builder.go new file mode 100644 index 0000000000..75c8ff6124 --- /dev/null +++ b/services/horizon/internal/db2/history/account_data_batch_insert_builder.go @@ -0,0 +1,50 @@ +package history + +import ( + "context" + + "github.com/stellar/go/support/db" +) + +type AccountDataBatchInsertBuilder interface { + Add(data Data) error + Exec(ctx context.Context) error +} + +type accountDataBatchInsertBuilder struct { + session db.SessionInterface + builder db.FastBatchInsertBuilder + table string +} + +func (q *Q) NewAccountDataBatchInsertBuilder() AccountDataBatchInsertBuilder { + return &accountDataBatchInsertBuilder{ + session: q, + builder: db.FastBatchInsertBuilder{}, + table: "accounts_data", + } +} + +// Add adds a new account data to the batch +func (i *accountDataBatchInsertBuilder) Add(data Data) error { + ledgerKey, err := accountDataKeyToString(AccountDataKey{ + AccountID: data.AccountID, + DataName: data.Name, + }) + if err != nil { + return err + } + return i.builder.Row(map[string]interface{}{ + "ledger_key": ledgerKey, + "account_id": data.AccountID, + "name": data.Name, + "value": data.Value, + "last_modified_ledger": data.LastModifiedLedger, + "sponsor": data.Sponsor, + }) +} + +// Exec writes the batch of account data to the database. +func (i *accountDataBatchInsertBuilder) Exec(ctx context.Context) error { + return i.builder.Exec(ctx, i.session, i.table) +} diff --git a/services/horizon/internal/db2/history/account_data_value.go b/services/horizon/internal/db2/history/account_data_value.go index efcd8d319b..693420e034 100644 --- a/services/horizon/internal/db2/history/account_data_value.go +++ b/services/horizon/internal/db2/history/account_data_value.go @@ -22,7 +22,9 @@ func (t *AccountDataValue) Scan(src interface{}) error { // Value implements driver.Valuer func (value AccountDataValue) Value() (driver.Value, error) { - return driver.Value([]uint8(base64.StdEncoding.EncodeToString(value))), nil + // Return string to bypass buggy encoding in pq driver for []byte. + // More info https://github.com/stellar/go/issues/5086#issuecomment-1773215436) + return driver.Value(base64.StdEncoding.EncodeToString(value)), nil } func (value AccountDataValue) Base64() string { diff --git a/services/horizon/internal/db2/history/account_loader.go b/services/horizon/internal/db2/history/account_loader.go new file mode 100644 index 0000000000..f3946b0448 --- /dev/null +++ b/services/horizon/internal/db2/history/account_loader.go @@ -0,0 +1,214 @@ +package history + +import ( + "context" + "database/sql/driver" + "fmt" + "sort" + "strings" + + "github.com/lib/pq" + + "github.com/stellar/go/support/collections/set" + "github.com/stellar/go/support/db" + "github.com/stellar/go/support/errors" + "github.com/stellar/go/support/ordered" +) + +// FutureAccountID represents a future history account. +// A FutureAccountID is created by an AccountLoader and +// the account id is available after calling Exec() on +// the AccountLoader. +type FutureAccountID struct { + address string + loader *AccountLoader +} + +const loaderLookupBatchSize = 50000 + +// Value implements the database/sql/driver Valuer interface. +func (a FutureAccountID) Value() (driver.Value, error) { + return a.loader.GetNow(a.address) +} + +// AccountLoader will map account addresses to their history +// account ids. If there is no existing mapping for a given address, +// the AccountLoader will insert into the history_accounts table to +// establish a mapping. +type AccountLoader struct { + sealed bool + set set.Set[string] + ids map[string]int64 +} + +var errSealed = errors.New("cannot register more entries to loader after calling Exec()") + +// NewAccountLoader will construct a new AccountLoader instance. +func NewAccountLoader() *AccountLoader { + return &AccountLoader{ + sealed: false, + set: set.Set[string]{}, + ids: map[string]int64{}, + } +} + +// GetFuture registers the given account address into the loader and +// returns a FutureAccountID which will hold the history account id for +// the address after Exec() is called. +func (a *AccountLoader) GetFuture(address string) FutureAccountID { + if a.sealed { + panic(errSealed) + } + + a.set.Add(address) + return FutureAccountID{ + address: address, + loader: a, + } +} + +// GetNow returns the history account id for the given address. +// GetNow should only be called on values which were registered by +// GetFuture() calls. Also, Exec() must be called before any GetNow +// call can succeed. +func (a *AccountLoader) GetNow(address string) (int64, error) { + if !a.sealed { + return 0, fmt.Errorf(`invalid account loader state, + Exec was not called yet to properly seal and resolve %v id`, address) + } + if internalID, ok := a.ids[address]; !ok { + return 0, fmt.Errorf(`account loader address %q was not found`, address) + } else { + return internalID, nil + } +} + +func (a *AccountLoader) lookupKeys(ctx context.Context, q *Q, addresses []string) error { + for i := 0; i < len(addresses); i += loaderLookupBatchSize { + end := ordered.Min(len(addresses), i+loaderLookupBatchSize) + + var accounts []Account + if err := q.AccountsByAddresses(ctx, &accounts, addresses[i:end]); err != nil { + return errors.Wrap(err, "could not select accounts") + } + + for _, account := range accounts { + a.ids[account.Address] = account.ID + } + } + return nil +} + +// Exec will look up all the history account ids for the addresses registered in the loader. +// If there are no history account ids for a given set of addresses, Exec will insert rows +// into the history_accounts table to establish a mapping between address and history account id. +func (a *AccountLoader) Exec(ctx context.Context, session db.SessionInterface) error { + a.sealed = true + if len(a.set) == 0 { + return nil + } + q := &Q{session} + addresses := make([]string, 0, len(a.set)) + for address := range a.set { + addresses = append(addresses, address) + } + + if err := a.lookupKeys(ctx, q, addresses); err != nil { + return err + } + + insert := 0 + for _, address := range addresses { + if _, ok := a.ids[address]; ok { + continue + } + addresses[insert] = address + insert++ + } + if insert == 0 { + return nil + } + addresses = addresses[:insert] + // sort entries before inserting rows to prevent deadlocks on acquiring a ShareLock + // https://github.com/stellar/go/issues/2370 + sort.Strings(addresses) + + err := bulkInsert( + ctx, + q, + "history_accounts", + []string{"address"}, + []bulkInsertField{ + { + name: "address", + dbType: "character varying(64)", + objects: addresses, + }, + }, + ) + if err != nil { + return err + } + + return a.lookupKeys(ctx, q, addresses) +} + +type bulkInsertField struct { + name string + dbType string + objects []string +} + +func bulkInsert(ctx context.Context, q *Q, table string, conflictFields []string, fields []bulkInsertField) error { + unnestPart := make([]string, 0, len(fields)) + insertFieldsPart := make([]string, 0, len(fields)) + pqArrays := make([]interface{}, 0, len(fields)) + + for _, field := range fields { + unnestPart = append( + unnestPart, + fmt.Sprintf("unnest(?::%s[]) /* %s */", field.dbType, field.name), + ) + insertFieldsPart = append( + insertFieldsPart, + field.name, + ) + pqArrays = append( + pqArrays, + pq.Array(field.objects), + ) + } + + sql := ` + WITH r AS + (SELECT ` + strings.Join(unnestPart, ",") + `) + INSERT INTO ` + table + ` + (` + strings.Join(insertFieldsPart, ",") + `) + SELECT * from r + ON CONFLICT (` + strings.Join(conflictFields, ",") + `) DO NOTHING` + + _, err := q.ExecRaw( + context.WithValue(ctx, &db.QueryTypeContextKey, db.UpsertQueryType), + sql, + pqArrays..., + ) + return err +} + +// AccountLoaderStub is a stub wrapper around AccountLoader which allows +// you to manually configure the mapping of addresses to history account ids +type AccountLoaderStub struct { + Loader *AccountLoader +} + +// NewAccountLoaderStub returns a new AccountLoaderStub instance +func NewAccountLoaderStub() AccountLoaderStub { + return AccountLoaderStub{Loader: NewAccountLoader()} +} + +// Insert updates the wrapped AccountLoader so that the given account +// address is mapped to the provided history account id +func (a AccountLoaderStub) Insert(address string, id int64) { + a.Loader.sealed = true + a.Loader.ids[address] = id +} diff --git a/services/horizon/internal/db2/history/account_loader_test.go b/services/horizon/internal/db2/history/account_loader_test.go new file mode 100644 index 0000000000..54d2c7a143 --- /dev/null +++ b/services/horizon/internal/db2/history/account_loader_test.go @@ -0,0 +1,52 @@ +package history + +import ( + "context" + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/stellar/go/keypair" + "github.com/stellar/go/services/horizon/internal/test" +) + +func TestAccountLoader(t *testing.T) { + tt := test.Start(t) + defer tt.Finish() + test.ResetHorizonDB(t, tt.HorizonDB) + session := tt.HorizonSession() + + var addresses []string + for i := 0; i < 100; i++ { + addresses = append(addresses, keypair.MustRandom().Address()) + } + + loader := NewAccountLoader() + for _, address := range addresses { + future := loader.GetFuture(address) + _, err := future.Value() + assert.Error(t, err) + assert.Contains(t, err.Error(), `invalid account loader state,`) + duplicateFuture := loader.GetFuture(address) + assert.Equal(t, future, duplicateFuture) + } + + assert.NoError(t, loader.Exec(context.Background(), session)) + assert.Panics(t, func() { + loader.GetFuture(keypair.MustRandom().Address()) + }) + + q := &Q{session} + for _, address := range addresses { + internalId, err := loader.GetNow(address) + assert.NoError(t, err) + var account Account + assert.NoError(t, q.AccountByAddress(context.Background(), &account, address)) + assert.Equal(t, account.ID, internalId) + assert.Equal(t, account.Address, address) + } + + _, err := loader.GetNow("not present") + assert.Error(t, err) + assert.Contains(t, err.Error(), `was not found`) +} diff --git a/services/horizon/internal/db2/history/account_signers.go b/services/horizon/internal/db2/history/account_signers.go index 32c6cdc583..d523c96ff2 100644 --- a/services/horizon/internal/db2/history/account_signers.go +++ b/services/horizon/internal/db2/history/account_signers.go @@ -53,6 +53,9 @@ func (q *Q) AccountsForSigner(ctx context.Context, signer string, page db2.PageQ // CreateAccountSigner creates a row in the accounts_signers table. // Returns number of rows affected and error. func (q *Q) CreateAccountSigner(ctx context.Context, account, signer string, weight int32, sponsor *string) (int64, error) { + // This function is not used in the ingestion code path. SignersProcessor now uses bulk insertion with + // FastBatchInsertBuilder, but this function is used in unit tests when only a single row needs to be inserted. + sql := sq.Insert("accounts_signers"). Columns("account_id", "signer", "weight", "sponsor"). Values(account, signer, weight, sponsor) diff --git a/services/horizon/internal/db2/history/account_signers_batch_insert_builder.go b/services/horizon/internal/db2/history/account_signers_batch_insert_builder.go index fd1cab291c..d347fb3e17 100644 --- a/services/horizon/internal/db2/history/account_signers_batch_insert_builder.go +++ b/services/horizon/internal/db2/history/account_signers_batch_insert_builder.go @@ -4,8 +4,8 @@ import ( "context" ) -func (i *accountSignersBatchInsertBuilder) Add(ctx context.Context, signer AccountSigner) error { - return i.builder.Row(ctx, map[string]interface{}{ +func (i *accountSignersBatchInsertBuilder) Add(signer AccountSigner) error { + return i.builder.Row(map[string]interface{}{ "account_id": signer.Account, "signer": signer.Signer, "weight": signer.Weight, @@ -14,5 +14,5 @@ func (i *accountSignersBatchInsertBuilder) Add(ctx context.Context, signer Accou } func (i *accountSignersBatchInsertBuilder) Exec(ctx context.Context) error { - return i.builder.Exec(ctx) + return i.builder.Exec(ctx, i.session, i.table) } diff --git a/services/horizon/internal/db2/history/account_signers_test.go b/services/horizon/internal/db2/history/account_signers_test.go index bf4183396b..158df82409 100644 --- a/services/horizon/internal/db2/history/account_signers_test.go +++ b/services/horizon/internal/db2/history/account_signers_test.go @@ -95,12 +95,12 @@ func TestMultipleAccountsForSigner(t *testing.T) { tt.Assert.Equal(int64(1), rowsAffected) expected := []AccountSigner{ - AccountSigner{ + { Account: account, Signer: signer, Weight: weight, }, - AccountSigner{ + { Account: anotherAccount, Signer: signer, Weight: anotherWeight, @@ -112,7 +112,7 @@ func TestMultipleAccountsForSigner(t *testing.T) { tt.Assert.Equal(expected, results) } -func TestRemoveNonExistantAccountSigner(t *testing.T) { +func TestRemoveNonExistentAccountSigner(t *testing.T) { tt := test.Start(t) tt.Scenario("base") defer tt.Finish() diff --git a/services/horizon/internal/db2/history/accounts_batch_insert_builder.go b/services/horizon/internal/db2/history/accounts_batch_insert_builder.go new file mode 100644 index 0000000000..5e68468094 --- /dev/null +++ b/services/horizon/internal/db2/history/accounts_batch_insert_builder.go @@ -0,0 +1,39 @@ +package history + +import ( + "context" + + "github.com/stellar/go/support/db" +) + +// AccountsBatchInsertBuilder is used to insert accounts into the accounts table +type AccountsBatchInsertBuilder interface { + Add(account AccountEntry) error + Exec(ctx context.Context) error +} + +// AccountsBatchInsertBuilder is a simple wrapper around db.FastBatchInsertBuilder +type accountsBatchInsertBuilder struct { + session db.SessionInterface + builder db.FastBatchInsertBuilder + table string +} + +// NewAccountsBatchInsertBuilder constructs a new AccountsBatchInsertBuilder instance +func (q *Q) NewAccountsBatchInsertBuilder() AccountsBatchInsertBuilder { + return &accountsBatchInsertBuilder{ + session: q, + builder: db.FastBatchInsertBuilder{}, + table: "accounts", + } +} + +// Add adds a new account to the batch +func (i *accountsBatchInsertBuilder) Add(account AccountEntry) error { + return i.builder.RowStruct(account) +} + +// Exec writes the batch of accounts to the database. +func (i *accountsBatchInsertBuilder) Exec(ctx context.Context) error { + return i.builder.Exec(ctx, i.session, i.table) +} diff --git a/services/horizon/internal/db2/history/asset_loader.go b/services/horizon/internal/db2/history/asset_loader.go new file mode 100644 index 0000000000..b5ee9a8326 --- /dev/null +++ b/services/horizon/internal/db2/history/asset_loader.go @@ -0,0 +1,219 @@ +package history + +import ( + "context" + "database/sql/driver" + "fmt" + "sort" + "strings" + + sq "github.com/Masterminds/squirrel" + + "github.com/stellar/go/support/collections/set" + "github.com/stellar/go/support/db" + "github.com/stellar/go/support/errors" + "github.com/stellar/go/support/ordered" + "github.com/stellar/go/xdr" +) + +type AssetKey struct { + Type string + Code string + Issuer string +} + +func (key AssetKey) String() string { + if key.Type == xdr.AssetTypeToString[xdr.AssetTypeAssetTypeNative] { + return key.Type + } + return key.Type + "/" + key.Code + "/" + key.Issuer +} + +// AssetKeyFromXDR constructs an AssetKey from an xdr asset +func AssetKeyFromXDR(asset xdr.Asset) AssetKey { + return AssetKey{ + Type: xdr.AssetTypeToString[asset.Type], + Code: strings.TrimRight(asset.GetCode(), "\x00"), + Issuer: asset.GetIssuer(), + } +} + +// FutureAssetID represents a future history asset. +// A FutureAssetID is created by an AssetLoader and +// the asset id is available after calling Exec() on +// the AssetLoader. +type FutureAssetID struct { + asset AssetKey + loader *AssetLoader +} + +// Value implements the database/sql/driver Valuer interface. +func (a FutureAssetID) Value() (driver.Value, error) { + return a.loader.GetNow(a.asset) +} + +// AssetLoader will map assets to their history +// asset ids. If there is no existing mapping for a given sset, +// the AssetLoader will insert into the history_assets table to +// establish a mapping. +type AssetLoader struct { + sealed bool + set set.Set[AssetKey] + ids map[AssetKey]int64 +} + +// NewAssetLoader will construct a new AssetLoader instance. +func NewAssetLoader() *AssetLoader { + return &AssetLoader{ + sealed: false, + set: set.Set[AssetKey]{}, + ids: map[AssetKey]int64{}, + } +} + +// GetFuture registers the given asset into the loader and +// returns a FutureAssetID which will hold the history asset id for +// the asset after Exec() is called. +func (a *AssetLoader) GetFuture(asset AssetKey) FutureAssetID { + if a.sealed { + panic(errSealed) + } + a.set.Add(asset) + return FutureAssetID{ + asset: asset, + loader: a, + } +} + +// GetNow returns the history asset id for the given asset. +// GetNow should only be called on values which were registered by +// GetFuture() calls. Also, Exec() must be called before any GetNow +// call can succeed. +func (a *AssetLoader) GetNow(asset AssetKey) (int64, error) { + if !a.sealed { + return 0, fmt.Errorf(`invalid asset loader state, + Exec was not called yet to properly seal and resolve %v id`, asset) + } + if internalID, ok := a.ids[asset]; !ok { + return 0, fmt.Errorf(`asset loader id %v was not found`, asset) + } else { + return internalID, nil + } +} + +func (a *AssetLoader) lookupKeys(ctx context.Context, q *Q, keys []AssetKey) error { + var rows []Asset + for i := 0; i < len(keys); i += loaderLookupBatchSize { + end := ordered.Min(len(keys), i+loaderLookupBatchSize) + subset := keys[i:end] + keyStrings := make([]string, 0, len(subset)) + for _, key := range subset { + keyStrings = append(keyStrings, key.Type+"/"+key.Code+"/"+key.Issuer) + } + err := q.Select(ctx, &rows, sq.Select("*").From("history_assets").Where(sq.Eq{ + "concat(asset_type, '/', asset_code, '/', asset_issuer)": keyStrings, + })) + if err != nil { + return errors.Wrap(err, "could not select assets") + } + + for _, row := range rows { + a.ids[AssetKey{ + Type: row.Type, + Code: row.Code, + Issuer: row.Issuer, + }] = row.ID + } + } + return nil +} + +// Exec will look up all the history asset ids for the assets registered in the loader. +// If there are no history asset ids for a given set of assets, Exec will insert rows +// into the history_assets table. +func (a *AssetLoader) Exec(ctx context.Context, session db.SessionInterface) error { + a.sealed = true + if len(a.set) == 0 { + return nil + } + q := &Q{session} + keys := make([]AssetKey, 0, len(a.set)) + for key := range a.set { + keys = append(keys, key) + } + + if err := a.lookupKeys(ctx, q, keys); err != nil { + return err + } + + assetTypes := make([]string, 0, len(a.set)-len(a.ids)) + assetCodes := make([]string, 0, len(a.set)-len(a.ids)) + assetIssuers := make([]string, 0, len(a.set)-len(a.ids)) + // sort entries before inserting rows to prevent deadlocks on acquiring a ShareLock + // https://github.com/stellar/go/issues/2370 + sort.Slice(keys, func(i, j int) bool { + return keys[i].String() < keys[j].String() + }) + insert := 0 + for _, key := range keys { + if _, ok := a.ids[key]; ok { + continue + } + assetTypes = append(assetTypes, key.Type) + assetCodes = append(assetCodes, key.Code) + assetIssuers = append(assetIssuers, key.Issuer) + keys[insert] = key + insert++ + } + if insert == 0 { + return nil + } + keys = keys[:insert] + + err := bulkInsert( + ctx, + q, + "history_assets", + []string{"asset_code", "asset_type", "asset_issuer"}, + []bulkInsertField{ + { + name: "asset_code", + dbType: "character varying(12)", + objects: assetCodes, + }, + { + name: "asset_issuer", + dbType: "character varying(56)", + objects: assetIssuers, + }, + { + name: "asset_type", + dbType: "character varying(64)", + objects: assetTypes, + }, + }, + ) + if err != nil { + return err + } + + return a.lookupKeys(ctx, q, keys) +} + +// AssetLoaderStub is a stub wrapper around AssetLoader which allows +// you to manually configure the mapping of assets to history asset ids +type AssetLoaderStub struct { + Loader *AssetLoader +} + +// NewAssetLoaderStub returns a new AssetLoaderStub instance +func NewAssetLoaderStub() AssetLoaderStub { + return AssetLoaderStub{Loader: NewAssetLoader()} +} + +// Insert updates the wrapped AssetLoaderStub so that the given asset +// address is mapped to the provided history asset id +func (a AssetLoaderStub) Insert(asset AssetKey, id int64) { + a.Loader.sealed = true + a.Loader.ids[asset] = id +} diff --git a/services/horizon/internal/db2/history/asset_loader_test.go b/services/horizon/internal/db2/history/asset_loader_test.go new file mode 100644 index 0000000000..d67163d764 --- /dev/null +++ b/services/horizon/internal/db2/history/asset_loader_test.go @@ -0,0 +1,102 @@ +package history + +import ( + "context" + "fmt" + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/stellar/go/keypair" + "github.com/stellar/go/services/horizon/internal/test" + "github.com/stellar/go/xdr" +) + +func TestAssetKeyToString(t *testing.T) { + num4key := AssetKey{ + Type: "credit_alphanum4", + Code: "USD", + Issuer: "A1B2C3", + } + + num12key := AssetKey{ + Type: "credit_alphanum12", + Code: "USDABC", + Issuer: "A1B2C3", + } + + nativekey := AssetKey{ + Type: "native", + } + + assert.Equal(t, num4key.String(), "credit_alphanum4/USD/A1B2C3") + assert.Equal(t, num12key.String(), "credit_alphanum12/USDABC/A1B2C3") + assert.Equal(t, nativekey.String(), "native") +} + +func TestAssetLoader(t *testing.T) { + tt := test.Start(t) + defer tt.Finish() + test.ResetHorizonDB(t, tt.HorizonDB) + session := tt.HorizonSession() + + var keys []AssetKey + for i := 0; i < 100; i++ { + var key AssetKey + if i == 0 { + key = AssetKeyFromXDR(xdr.Asset{Type: xdr.AssetTypeAssetTypeNative}) + } else if i%2 == 0 { + code := [4]byte{0, 0, 0, 0} + copy(code[:], fmt.Sprintf("ab%d", i)) + key = AssetKeyFromXDR(xdr.Asset{ + Type: xdr.AssetTypeAssetTypeCreditAlphanum4, + AlphaNum4: &xdr.AlphaNum4{ + AssetCode: code, + Issuer: xdr.MustAddress(keypair.MustRandom().Address())}}) + } else { + code := [12]byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + copy(code[:], fmt.Sprintf("abcdef%d", i)) + key = AssetKeyFromXDR(xdr.Asset{ + Type: xdr.AssetTypeAssetTypeCreditAlphanum12, + AlphaNum12: &xdr.AlphaNum12{ + AssetCode: code, + Issuer: xdr.MustAddress(keypair.MustRandom().Address())}}) + + } + keys = append(keys, key) + } + + loader := NewAssetLoader() + for _, key := range keys { + future := loader.GetFuture(key) + _, err := future.Value() + assert.Error(t, err) + assert.Contains(t, err.Error(), `invalid asset loader state,`) + duplicateFuture := loader.GetFuture(key) + assert.Equal(t, future, duplicateFuture) + } + + assert.NoError(t, loader.Exec(context.Background(), session)) + assert.Panics(t, func() { + loader.GetFuture(AssetKey{Type: "invalid"}) + }) + + q := &Q{session} + for _, key := range keys { + internalID, err := loader.GetNow(key) + assert.NoError(t, err) + var assetXDR xdr.Asset + if key.Type == "native" { + assetXDR = xdr.MustNewNativeAsset() + } else { + assetXDR = xdr.MustNewCreditAsset(key.Code, key.Issuer) + } + assetID, err := q.GetAssetID(context.Background(), assetXDR) + assert.NoError(t, err) + assert.Equal(t, assetID, internalID) + } + + _, err := loader.GetNow(AssetKey{}) + assert.Error(t, err) + assert.Contains(t, err.Error(), `was not found`) +} diff --git a/services/horizon/internal/db2/history/asset_stats.go b/services/horizon/internal/db2/history/asset_stats.go index e24f3fe887..622619680b 100644 --- a/services/horizon/internal/db2/history/asset_stats.go +++ b/services/horizon/internal/db2/history/asset_stats.go @@ -6,6 +6,7 @@ import ( "strings" sq "github.com/Masterminds/squirrel" + "github.com/stellar/go/services/horizon/internal/db2" "github.com/stellar/go/support/db" "github.com/stellar/go/support/errors" @@ -21,6 +22,7 @@ func assetStatToMap(assetStat ExpAssetStat) map[string]interface{} { "balances": assetStat.Balances, "amount": assetStat.Amount, "num_accounts": assetStat.NumAccounts, + "contract_id": assetStat.ContractID, } } @@ -32,26 +34,201 @@ func assetStatToPrimaryKeyMap(assetStat ExpAssetStat) map[string]interface{} { } } +// ContractAssetStatRow represents a row in the contract_asset_stats table +type ContractAssetStatRow struct { + // ContractID is the contract id of the stellar asset contract + ContractID []byte `db:"contract_id"` + // Stat is a json blob containing statistics on the contract holders + // this asset + Stat ContractStat `db:"stat"` +} + // InsertAssetStats a set of asset stats into the exp_asset_stats -func (q *Q) InsertAssetStats(ctx context.Context, assetStats []ExpAssetStat, batchSize int) error { - builder := &db.BatchInsertBuilder{ - Table: q.GetTable("exp_asset_stats"), - MaxBatchSize: batchSize, +func (q *Q) InsertAssetStats(ctx context.Context, assetStats []ExpAssetStat) error { + if len(assetStats) == 0 { + return nil } + builder := &db.FastBatchInsertBuilder{} + for _, assetStat := range assetStats { - if err := builder.Row(ctx, assetStatToMap(assetStat)); err != nil { + if err := builder.Row(assetStatToMap(assetStat)); err != nil { + return errors.Wrap(err, "could not insert asset assetStat row") + } + } + + if err := builder.Exec(ctx, q, "exp_asset_stats"); err != nil { + return errors.Wrap(err, "could not exec asset assetStats insert builder") + } + + return nil +} + +// InsertContractAssetStats inserts the given list of rows into the contract_asset_stats table +func (q *Q) InsertContractAssetStats(ctx context.Context, rows []ContractAssetStatRow) error { + if len(rows) == 0 { + return nil + } + builder := &db.FastBatchInsertBuilder{} + + for _, row := range rows { + if err := builder.RowStruct(row); err != nil { + return errors.Wrap(err, "could not insert asset assetStat row") + } + } + + if err := builder.Exec(ctx, q, "contract_asset_stats"); err != nil { + return errors.Wrap(err, "could not exec asset assetStats insert builder") + } + + return nil +} + +// ContractAssetBalance represents a row in the contract_asset_balances table +type ContractAssetBalance struct { + // KeyHash is a hash of the contract balance's ledger entry key + KeyHash []byte `db:"key_hash"` + // ContractID is the contract id of the stellar asset contract + ContractID []byte `db:"asset_contract_id"` + // Amount is the amount held by the contract + Amount string `db:"amount"` + // ExpirationLedger is the latest ledger for which this contract balance + // ledger entry is active + ExpirationLedger uint32 `db:"expiration_ledger"` +} + +// InsertContractAssetBalances will insert the given list of rows into the contract_asset_balances table +func (q *Q) InsertContractAssetBalances(ctx context.Context, rows []ContractAssetBalance) error { + if len(rows) == 0 { + return nil + } + builder := &db.FastBatchInsertBuilder{} + + for _, row := range rows { + if err := builder.RowStruct(row); err != nil { return errors.Wrap(err, "could not insert asset assetStat row") } } - if err := builder.Exec(ctx); err != nil { + if err := builder.Exec(ctx, q, "contract_asset_balances"); err != nil { return errors.Wrap(err, "could not exec asset assetStats insert builder") } return nil } +const maxUpdateBatchSize = 30000 + +// UpdateContractAssetBalanceAmounts will update the expiration ledgers for the given list of keys +// (if they exist in the db). +func (q *Q) UpdateContractAssetBalanceAmounts(ctx context.Context, keys []xdr.Hash, amounts []string) error { + for len(keys) > 0 { + var args []interface{} + var values []string + + for i := 0; len(keys) > 0 && i < maxUpdateBatchSize; i++ { + args = append(args, keys[0][:], amounts[0]) + values = append(values, "(cast(? as bytea), cast(? as numeric))") + keys = keys[1:] + amounts = amounts[1:] + } + + sql := fmt.Sprintf(` + UPDATE contract_asset_balances + SET + amount = myvalues.amount + FROM ( + VALUES + %s + ) AS myvalues (key_hash, amount) + WHERE contract_asset_balances.key_hash = myvalues.key_hash`, + strings.Join(values, ","), + ) + + _, err := q.ExecRaw(ctx, sql, args...) + if err != nil { + return err + } + } + return nil +} + +// UpdateContractAssetBalanceExpirations will update the expiration ledgers for the given list of keys +// (if they exist in the db). +func (q *Q) UpdateContractAssetBalanceExpirations(ctx context.Context, keys []xdr.Hash, expirationLedgers []uint32) error { + for len(keys) > 0 { + var args []interface{} + var values []string + + for i := 0; len(keys) > 0 && i < maxUpdateBatchSize; i++ { + args = append(args, keys[0][:], expirationLedgers[0]) + values = append(values, "(cast(? as bytea), cast(? as integer))") + keys = keys[1:] + expirationLedgers = expirationLedgers[1:] + } + + sql := fmt.Sprintf(` + UPDATE contract_asset_balances + SET + expiration_ledger = myvalues.expiration + FROM ( + VALUES + %s + ) AS myvalues (key_hash, expiration) + WHERE contract_asset_balances.key_hash = myvalues.key_hash`, + strings.Join(values, ","), + ) + + _, err := q.ExecRaw(ctx, sql, args...) + if err != nil { + return err + } + } + + return nil +} + +// GetContractAssetBalancesExpiringAt returns all contract asset balances which are active +// at `ledger` and expired at `ledger+1` +func (q *Q) GetContractAssetBalancesExpiringAt(ctx context.Context, ledger uint32) ([]ContractAssetBalance, error) { + sql := sq.Select("contract_asset_balances.*").From("contract_asset_balances"). + Where(map[string]interface{}{"expiration_ledger": ledger}) + var balances []ContractAssetBalance + err := q.Select(ctx, &balances, sql) + return balances, err +} + +// GetContractAssetBalances fetches all contract_asset_balances rows for the +// given list of key hashes. +func (q *Q) GetContractAssetBalances(ctx context.Context, keys []xdr.Hash) ([]ContractAssetBalance, error) { + keyBytes := make([][]byte, len(keys)) + for i := range keys { + keyBytes[i] = keys[i][:] + } + sql := sq.Select("contract_asset_balances.*").From("contract_asset_balances"). + Where(map[string]interface{}{"key_hash": keyBytes}) + var balances []ContractAssetBalance + err := q.Select(ctx, &balances, sql) + return balances, err +} + +// RemoveContractAssetBalances removes rows from the contract_asset_balances table +func (q *Q) RemoveContractAssetBalances(ctx context.Context, keys []xdr.Hash) error { + if len(keys) == 0 { + return nil + } + keyBytes := make([][]byte, len(keys)) + for i := range keys { + keyBytes[i] = keys[i][:] + } + + _, err := q.Exec(ctx, sq.Delete("contract_asset_balances"). + Where(map[string]interface{}{ + "key_hash": keyBytes, + })) + return err +} + // InsertAssetStat a single asset assetStat row into the exp_asset_stats // Returns number of rows affected and error. func (q *Q) InsertAssetStat(ctx context.Context, assetStat ExpAssetStat) (int64, error) { @@ -64,6 +241,20 @@ func (q *Q) InsertAssetStat(ctx context.Context, assetStat ExpAssetStat) (int64, return result.RowsAffected() } +// InsertContractAssetStat inserts a row into the contract_asset_stats table +func (q *Q) InsertContractAssetStat(ctx context.Context, row ContractAssetStatRow) (int64, error) { + sql := sq.Insert("contract_asset_stats").SetMap(map[string]interface{}{ + "contract_id": row.ContractID, + "stat": row.Stat, + }) + result, err := q.Exec(ctx, sql) + if err != nil { + return 0, err + } + + return result.RowsAffected() +} + // UpdateAssetStat updates a row in the exp_asset_stats table. // Returns number of rows affected and error. func (q *Q) UpdateAssetStat(ctx context.Context, assetStat ExpAssetStat) (int64, error) { @@ -78,6 +269,19 @@ func (q *Q) UpdateAssetStat(ctx context.Context, assetStat ExpAssetStat) (int64, return result.RowsAffected() } +// UpdateContractAssetStat updates a row in the contract_asset_stats table. +// Returns number of rows afected and error. +func (q *Q) UpdateContractAssetStat(ctx context.Context, row ContractAssetStatRow) (int64, error) { + sql := sq.Update("contract_asset_stats").Set("stat", row.Stat). + Where("contract_id = ?", row.ContractID) + result, err := q.Exec(ctx, sql) + if err != nil { + return 0, err + } + + return result.RowsAffected() +} + // RemoveAssetStat removes a row in the exp_asset_stats table. func (q *Q) RemoveAssetStat(ctx context.Context, assetType xdr.AssetType, assetCode, assetIssuer string) (int64, error) { sql := sq.Delete("exp_asset_stats"). @@ -94,6 +298,18 @@ func (q *Q) RemoveAssetStat(ctx context.Context, assetType xdr.AssetType, assetC return result.RowsAffected() } +// RemoveAssetContractStat removes a row in the contract_asset_stats table. +func (q *Q) RemoveAssetContractStat(ctx context.Context, contractID []byte) (int64, error) { + sql := sq.Delete("contract_asset_stats"). + Where("contract_id = ?", contractID) + result, err := q.Exec(ctx, sql) + if err != nil { + return 0, err + } + + return result.RowsAffected() +} + // GetAssetStat returns a row in the exp_asset_stats table. func (q *Q) GetAssetStat(ctx context.Context, assetType xdr.AssetType, assetCode, assetIssuer string) (ExpAssetStat, error) { sql := selectAssetStats.Where(map[string]interface{}{ @@ -106,6 +322,23 @@ func (q *Q) GetAssetStat(ctx context.Context, assetType xdr.AssetType, assetCode return assetStat, err } +// GetContractAssetStat returns a row in the contract_asset_stats table. +func (q *Q) GetContractAssetStat(ctx context.Context, contractID []byte) (ContractAssetStatRow, error) { + sql := sq.Select("*").From("contract_asset_stats").Where("contract_id = ?", contractID) + var assetStat ContractAssetStatRow + err := q.Get(ctx, &assetStat, sql) + return assetStat, err +} + +// GetAssetStatByContract returns the row in the exp_asset_stats table corresponding +// to the given contract id +func (q *Q) GetAssetStatByContract(ctx context.Context, contractID xdr.Hash) (ExpAssetStat, error) { + sql := selectAssetStats.Where("contract_id = ?", contractID[:]) + var assetStat ExpAssetStat + err := q.Get(ctx, &assetStat, sql) + return assetStat, err +} + func parseAssetStatsCursor(cursor string) (string, string, error) { parts := strings.SplitN(cursor, "_", 3) if len(parts) != 3 { @@ -138,8 +371,10 @@ func parseAssetStatsCursor(cursor string) (string, string, error) { } // GetAssetStats returns a page of exp_asset_stats rows. -func (q *Q) GetAssetStats(ctx context.Context, assetCode, assetIssuer string, page db2.PageQuery) ([]ExpAssetStat, error) { - sql := selectAssetStats +func (q *Q) GetAssetStats(ctx context.Context, assetCode, assetIssuer string, page db2.PageQuery) ([]AssetAndContractStat, error) { + sql := sq.Select("exp_asset_stats.*, contract_asset_stats.stat as contracts"). + From("exp_asset_stats"). + LeftJoin("contract_asset_stats ON exp_asset_stats.contract_id = contract_asset_stats.contract_id") filters := map[string]interface{}{} if assetCode != "" { filters["asset_code"] = assetCode @@ -173,7 +408,7 @@ func (q *Q) GetAssetStats(ctx context.Context, assetCode, assetIssuer string, pa sql = sql.OrderBy("(asset_code, asset_issuer) " + orderBy).Limit(page.Limit) - var results []ExpAssetStat + var results []AssetAndContractStat if err := q.Select(ctx, &results, sql); err != nil { return nil, errors.Wrap(err, "could not run select query") } diff --git a/services/horizon/internal/db2/history/asset_stats_test.go b/services/horizon/internal/db2/history/asset_stats_test.go index 33a041fa7c..a8352e4d97 100644 --- a/services/horizon/internal/db2/history/asset_stats_test.go +++ b/services/horizon/internal/db2/history/asset_stats_test.go @@ -1,20 +1,206 @@ package history import ( + "bytes" + "context" "database/sql" + "sort" "testing" + "github.com/stretchr/testify/assert" + "golang.org/x/exp/slices" + "github.com/stellar/go/services/horizon/internal/db2" "github.com/stellar/go/services/horizon/internal/test" "github.com/stellar/go/xdr" ) +func TestAssetStatContracts(t *testing.T) { + tt := test.Start(t) + defer tt.Finish() + test.ResetHorizonDB(t, tt.HorizonDB) + q := &Q{tt.HorizonSession()} + + tt.Assert.NoError(q.Begin(context.Background())) + + assetStats := []ExpAssetStat{ + { + AssetType: xdr.AssetTypeAssetTypeNative, + Accounts: ExpAssetStatAccounts{ + Authorized: 0, + AuthorizedToMaintainLiabilities: 0, + ClaimableBalances: 0, + LiquidityPools: 0, + Unauthorized: 0, + }, + Balances: ExpAssetStatBalances{ + Authorized: "0", + AuthorizedToMaintainLiabilities: "0", + ClaimableBalances: "0", + LiquidityPools: "0", + Unauthorized: "0", + }, + Amount: "0", + NumAccounts: 0, + }, + { + AssetType: xdr.AssetTypeAssetTypeCreditAlphanum12, + AssetIssuer: "GBRPYHIL2CI3FNQ4BXLFMNDLFJUNPU2HY3ZMFSHONUCEOASW7QC7OX2H", + AssetCode: "ETHER", + Accounts: ExpAssetStatAccounts{ + Authorized: 1, + AuthorizedToMaintainLiabilities: 3, + Unauthorized: 4, + }, + Balances: ExpAssetStatBalances{ + Authorized: "23", + AuthorizedToMaintainLiabilities: "2", + Unauthorized: "3", + ClaimableBalances: "4", + LiquidityPools: "5", + }, + Amount: "23", + NumAccounts: 1, + }, + { + AssetType: xdr.AssetTypeAssetTypeCreditAlphanum4, + AssetIssuer: "GBRPYHIL2CI3FNQ4BXLFMNDLFJUNPU2HY3ZMFSHONUCEOASW7QC7OX2H", + AssetCode: "USD", + Accounts: ExpAssetStatAccounts{ + Authorized: 2, + AuthorizedToMaintainLiabilities: 3, + Unauthorized: 4, + }, + Balances: ExpAssetStatBalances{ + Authorized: "1", + AuthorizedToMaintainLiabilities: "2", + Unauthorized: "3", + ClaimableBalances: "4", + LiquidityPools: "5", + }, + Amount: "1", + NumAccounts: 2, + }, + } + var contractID [32]byte + for i := 0; i < 2; i++ { + assetStats[i].SetContractID(contractID) + contractID[0]++ + } + tt.Assert.NoError(q.InsertAssetStats(tt.Ctx, assetStats)) + tt.Assert.NoError(q.Commit()) + + contractID[0] = 0 + for i := 0; i < 2; i++ { + var assetStat ExpAssetStat + assetStat, err := q.GetAssetStatByContract(tt.Ctx, contractID) + tt.Assert.NoError(err) + tt.Assert.True(assetStat.Equals(assetStats[i])) + contractID[0]++ + } + + usd := assetStats[2] + usd.SetContractID([32]byte{}) + _, err := q.UpdateAssetStat(tt.Ctx, usd) + tt.Assert.EqualError(err, "exec failed: pq: duplicate key value violates unique constraint \"exp_asset_stats_contract_id_key\"") + + usd.SetContractID([32]byte{2}) + rowsUpdated, err := q.UpdateAssetStat(tt.Ctx, usd) + tt.Assert.NoError(err) + tt.Assert.Equal(int64(1), rowsUpdated) + + assetStats[2] = usd + contractID = [32]byte{} + for i := 0; i < 3; i++ { + var assetStat ExpAssetStat + assetStat, err = q.GetAssetStatByContract(tt.Ctx, contractID) + tt.Assert.NoError(err) + tt.Assert.True(assetStat.Equals(assetStats[i])) + contractID[0]++ + } +} + +func TestAssetContractStats(t *testing.T) { + tt := test.Start(t) + defer tt.Finish() + test.ResetHorizonDB(t, tt.HorizonDB) + q := &Q{tt.HorizonSession()} + + tt.Assert.NoError(q.Begin(context.Background())) + + c1 := ContractAssetStatRow{ + ContractID: []byte{1}, + Stat: ContractStat{ + ActiveBalance: "100", + ActiveHolders: 2, + ArchivedBalance: "0", + ArchivedHolders: 0, + }, + } + c2 := ContractAssetStatRow{ + ContractID: []byte{2}, + Stat: ContractStat{ + ActiveBalance: "40", + ActiveHolders: 1, + ArchivedBalance: "0", + ArchivedHolders: 0, + }, + } + c3 := ContractAssetStatRow{ + ContractID: []byte{3}, + Stat: ContractStat{ + ActiveBalance: "900", + ActiveHolders: 12, + ArchivedBalance: "23", + ArchivedHolders: 3, + }, + } + + rows := []ContractAssetStatRow{c1, c2, c3} + tt.Assert.NoError(q.InsertContractAssetStats(tt.Ctx, rows)) + + for _, row := range rows { + result, err := q.GetContractAssetStat(tt.Ctx, row.ContractID) + tt.Assert.NoError(err) + tt.Assert.Equal(result, row) + } + + c2.Stat.ActiveHolders = 3 + c2.Stat.ActiveBalance = "20" + c3.Stat.ArchivedBalance = "900" + c2.Stat.ActiveHolders = 5 + numRows, err := q.UpdateContractAssetStat(tt.Ctx, c2) + tt.Assert.NoError(err) + tt.Assert.Equal(int64(1), numRows) + row, err := q.GetContractAssetStat(tt.Ctx, c2.ContractID) + tt.Assert.NoError(err) + tt.Assert.Equal(c2, row) + + numRows, err = q.RemoveAssetContractStat(tt.Ctx, c3.ContractID) + tt.Assert.NoError(err) + tt.Assert.Equal(int64(1), numRows) + + _, err = q.GetContractAssetStat(tt.Ctx, c3.ContractID) + tt.Assert.Equal(sql.ErrNoRows, err) + + for _, row := range []ContractAssetStatRow{c1, c2} { + result, err := q.GetContractAssetStat(tt.Ctx, row.ContractID) + tt.Assert.NoError(err) + tt.Assert.Equal(result, row) + } + + tt.Assert.NoError(q.Rollback()) +} + func TestInsertAssetStats(t *testing.T) { tt := test.Start(t) defer tt.Finish() test.ResetHorizonDB(t, tt.HorizonDB) q := &Q{tt.HorizonSession()} - tt.Assert.NoError(q.InsertAssetStats(tt.Ctx, []ExpAssetStat{}, 1)) + + tt.Assert.NoError(q.Begin(context.Background())) + + tt.Assert.NoError(q.InsertAssetStats(tt.Ctx, []ExpAssetStat{})) assetStats := []ExpAssetStat{ { @@ -56,13 +242,15 @@ func TestInsertAssetStats(t *testing.T) { NumAccounts: 1, }, } - tt.Assert.NoError(q.InsertAssetStats(tt.Ctx, assetStats, 1)) + tt.Assert.NoError(q.InsertAssetStats(tt.Ctx, assetStats)) for _, assetStat := range assetStats { got, err := q.GetAssetStat(tt.Ctx, assetStat.AssetType, assetStat.AssetCode, assetStat.AssetIssuer) tt.Assert.NoError(err) tt.Assert.Equal(got, assetStat) } + + tt.Assert.NoError(q.Rollback()) } func TestInsertAssetStat(t *testing.T) { @@ -241,6 +429,7 @@ func TestUpdateStat(t *testing.T) { assetStat.NumAccounts = 50 assetStat.Amount = "23" + assetStat.SetContractID([32]byte{23}) numChanged, err = q.UpdateAssetStat(tt.Ctx, assetStat) tt.Assert.Nil(err) @@ -248,7 +437,7 @@ func TestUpdateStat(t *testing.T) { got, err = q.GetAssetStat(tt.Ctx, assetStat.AssetType, assetStat.AssetCode, assetStat.AssetIssuer) tt.Assert.NoError(err) - tt.Assert.Equal(got, assetStat) + tt.Assert.True(got.Equals(assetStat)) } func TestGetAssetStatDoesNotExist(t *testing.T) { @@ -410,115 +599,153 @@ func TestGetAssetStatsOrderValidation(t *testing.T) { tt.Assert.Contains(err.Error(), "invalid page order") } -func reverseAssetStats(a []ExpAssetStat) { - for i := len(a)/2 - 1; i >= 0; i-- { - opp := len(a) - 1 - i - a[i], a[opp] = a[opp], a[i] - } -} - func TestGetAssetStatsFiltersAndCursor(t *testing.T) { tt := test.Start(t) defer tt.Finish() test.ResetHorizonDB(t, tt.HorizonDB) q := &Q{tt.HorizonSession()} - - usdAssetStat := ExpAssetStat{ - AssetType: xdr.AssetTypeAssetTypeCreditAlphanum4, - AssetIssuer: "GBRPYHIL2CI3FNQ4BXLFMNDLFJUNPU2HY3ZMFSHONUCEOASW7QC7OX2H", - AssetCode: "USD", - Accounts: ExpAssetStatAccounts{ - Authorized: 2, - AuthorizedToMaintainLiabilities: 3, - Unauthorized: 4, - }, - Balances: ExpAssetStatBalances{ - Authorized: "1", - AuthorizedToMaintainLiabilities: "2", - Unauthorized: "3", - ClaimableBalances: "0", - LiquidityPools: "0", - }, - Amount: "1", - NumAccounts: 2, + zero := ContractStat{ + ActiveBalance: "0", + ActiveHolders: 0, + ArchivedBalance: "0", + ArchivedHolders: 0, } - etherAssetStat := ExpAssetStat{ - AssetType: xdr.AssetTypeAssetTypeCreditAlphanum12, - AssetIssuer: "GBRPYHIL2CI3FNQ4BXLFMNDLFJUNPU2HY3ZMFSHONUCEOASW7QC7OX2H", - AssetCode: "ETHER", - Accounts: ExpAssetStatAccounts{ - Authorized: 1, - AuthorizedToMaintainLiabilities: 3, - Unauthorized: 4, - }, - Balances: ExpAssetStatBalances{ - Authorized: "23", - AuthorizedToMaintainLiabilities: "2", - Unauthorized: "3", - ClaimableBalances: "0", - LiquidityPools: "0", + usdAssetStat := AssetAndContractStat{ + ExpAssetStat: ExpAssetStat{ + AssetType: xdr.AssetTypeAssetTypeCreditAlphanum4, + AssetIssuer: "GBRPYHIL2CI3FNQ4BXLFMNDLFJUNPU2HY3ZMFSHONUCEOASW7QC7OX2H", + AssetCode: "USD", + Accounts: ExpAssetStatAccounts{ + Authorized: 2, + AuthorizedToMaintainLiabilities: 3, + Unauthorized: 4, + }, + Balances: ExpAssetStatBalances{ + Authorized: "1", + AuthorizedToMaintainLiabilities: "2", + Unauthorized: "3", + ClaimableBalances: "0", + LiquidityPools: "0", + }, + Amount: "1", + NumAccounts: 2, }, - Amount: "23", - NumAccounts: 1, + Contracts: zero, } - otherUSDAssetStat := ExpAssetStat{ - AssetType: xdr.AssetTypeAssetTypeCreditAlphanum4, - AssetIssuer: "GA5WBPYA5Y4WAEHXWR2UKO2UO4BUGHUQ74EUPKON2QHV4WRHOIRNKKH2", - AssetCode: "USD", - Accounts: ExpAssetStatAccounts{ - Authorized: 2, - AuthorizedToMaintainLiabilities: 3, - Unauthorized: 4, + etherAssetStat := AssetAndContractStat{ + ExpAssetStat: ExpAssetStat{ + AssetType: xdr.AssetTypeAssetTypeCreditAlphanum12, + AssetIssuer: "GBRPYHIL2CI3FNQ4BXLFMNDLFJUNPU2HY3ZMFSHONUCEOASW7QC7OX2H", + AssetCode: "ETHER", + Accounts: ExpAssetStatAccounts{ + Authorized: 1, + AuthorizedToMaintainLiabilities: 3, + Unauthorized: 4, + }, + Balances: ExpAssetStatBalances{ + Authorized: "23", + AuthorizedToMaintainLiabilities: "2", + Unauthorized: "3", + ClaimableBalances: "0", + LiquidityPools: "0", + }, + Amount: "23", + NumAccounts: 1, }, - Balances: ExpAssetStatBalances{ - Authorized: "1", - AuthorizedToMaintainLiabilities: "2", - Unauthorized: "3", - ClaimableBalances: "0", - LiquidityPools: "0", + Contracts: zero, + } + otherUSDAssetStat := AssetAndContractStat{ + ExpAssetStat: ExpAssetStat{ + AssetType: xdr.AssetTypeAssetTypeCreditAlphanum4, + AssetIssuer: "GA5WBPYA5Y4WAEHXWR2UKO2UO4BUGHUQ74EUPKON2QHV4WRHOIRNKKH2", + AssetCode: "USD", + Accounts: ExpAssetStatAccounts{ + Authorized: 2, + AuthorizedToMaintainLiabilities: 3, + Unauthorized: 4, + }, + Balances: ExpAssetStatBalances{ + Authorized: "1", + AuthorizedToMaintainLiabilities: "2", + Unauthorized: "3", + ClaimableBalances: "0", + LiquidityPools: "0", + }, + Amount: "1", + NumAccounts: 2, }, - Amount: "1", - NumAccounts: 2, + Contracts: zero, } - eurAssetStat := ExpAssetStat{ - AssetType: xdr.AssetTypeAssetTypeCreditAlphanum4, - AssetIssuer: "GA5WBPYA5Y4WAEHXWR2UKO2UO4BUGHUQ74EUPKON2QHV4WRHOIRNKKH2", - AssetCode: "EUR", - Accounts: ExpAssetStatAccounts{ - Authorized: 3, - AuthorizedToMaintainLiabilities: 2, - Unauthorized: 4, + eurAssetStat := AssetAndContractStat{ + ExpAssetStat: ExpAssetStat{ + AssetType: xdr.AssetTypeAssetTypeCreditAlphanum4, + AssetIssuer: "GA5WBPYA5Y4WAEHXWR2UKO2UO4BUGHUQ74EUPKON2QHV4WRHOIRNKKH2", + AssetCode: "EUR", + Accounts: ExpAssetStatAccounts{ + Authorized: 3, + AuthorizedToMaintainLiabilities: 2, + Unauthorized: 4, + }, + Balances: ExpAssetStatBalances{ + Authorized: "111", + AuthorizedToMaintainLiabilities: "2", + Unauthorized: "3", + ClaimableBalances: "1", + LiquidityPools: "2", + }, + Amount: "111", + NumAccounts: 3, }, - Balances: ExpAssetStatBalances{ - Authorized: "111", - AuthorizedToMaintainLiabilities: "2", - Unauthorized: "3", - ClaimableBalances: "1", - LiquidityPools: "2", + Contracts: ContractStat{ + ActiveBalance: "120", + ActiveHolders: 3, + ArchivedBalance: "90", + ArchivedHolders: 1, }, - Amount: "111", - NumAccounts: 3, } - assetStats := []ExpAssetStat{ + eurAssetStat.SetContractID([32]byte{}) + assetStats := []AssetAndContractStat{ etherAssetStat, eurAssetStat, otherUSDAssetStat, usdAssetStat, } for _, assetStat := range assetStats { - numChanged, err := q.InsertAssetStat(tt.Ctx, assetStat) + numChanged, err := q.InsertAssetStat(tt.Ctx, assetStat.ExpAssetStat) tt.Assert.NoError(err) tt.Assert.Equal(numChanged, int64(1)) + if assetStat.Contracts != zero { + numChanged, err = q.InsertContractAssetStat(tt.Ctx, ContractAssetStatRow{ + ContractID: *assetStat.ContractID, + Stat: assetStat.Contracts, + }) + tt.Assert.NoError(err) + tt.Assert.Equal(numChanged, int64(1)) + } } + // insert contract stat which has no corresponding asset stat row + // to test that it isn't included in the results + numChanged, err := q.InsertContractAssetStat(tt.Ctx, ContractAssetStatRow{ + ContractID: []byte{1}, + Stat: ContractStat{ + ActiveBalance: "400", + ActiveHolders: 30, + ArchivedBalance: "0", + ArchivedHolders: 0, + }, + }) + tt.Assert.NoError(err) + tt.Assert.Equal(numChanged, int64(1)) + for _, testCase := range []struct { name string assetCode string assetIssuer string cursor string order string - expected []ExpAssetStat + expected []AssetAndContractStat }{ { "no filter without cursor", @@ -526,7 +753,7 @@ func TestGetAssetStatsFiltersAndCursor(t *testing.T) { "", "", "asc", - []ExpAssetStat{ + []AssetAndContractStat{ etherAssetStat, eurAssetStat, otherUSDAssetStat, @@ -539,7 +766,7 @@ func TestGetAssetStatsFiltersAndCursor(t *testing.T) { "", "ABC_GA5WBPYA5Y4WAEHXWR2UKO2UO4BUGHUQ74EUPKON2QHV4WRHOIRNKKH2_credit_alphanum4", "asc", - []ExpAssetStat{ + []AssetAndContractStat{ etherAssetStat, eurAssetStat, otherUSDAssetStat, @@ -552,7 +779,7 @@ func TestGetAssetStatsFiltersAndCursor(t *testing.T) { "", "ZZZ_GBRPYHIL2CI3FNQ4BXLFMNDLFJUNPU2HY3ZMFSHONUCEOASW7QC7OX2H_credit_alphanum4", "desc", - []ExpAssetStat{ + []AssetAndContractStat{ usdAssetStat, otherUSDAssetStat, eurAssetStat, @@ -565,7 +792,7 @@ func TestGetAssetStatsFiltersAndCursor(t *testing.T) { "", "ETHER_GBRPYHIL2CI3FNQ4BXLFMNDLFJUNPU2HY3ZMFSHONUCEOASW7QC7OX2H_credit_alphanum12", "asc", - []ExpAssetStat{ + []AssetAndContractStat{ eurAssetStat, otherUSDAssetStat, usdAssetStat, @@ -577,7 +804,7 @@ func TestGetAssetStatsFiltersAndCursor(t *testing.T) { "", "EUR_GA5WBPYA5Y4WAEHXWR2UKO2UO4BUGHUQ74EUPKON2QHV4WRHOIRNKKH2_credit_alphanum4", "desc", - []ExpAssetStat{ + []AssetAndContractStat{ etherAssetStat, }, }, @@ -587,7 +814,7 @@ func TestGetAssetStatsFiltersAndCursor(t *testing.T) { "", "EUR_GBRPYHIL2CI3FNQ4BXLFMNDLFJUNPU2HY3ZMFSHONUCEOASW7QC7OX2H_credit_alphanum4", "desc", - []ExpAssetStat{ + []AssetAndContractStat{ eurAssetStat, etherAssetStat, }, @@ -598,7 +825,7 @@ func TestGetAssetStatsFiltersAndCursor(t *testing.T) { "", "", "asc", - []ExpAssetStat{ + []AssetAndContractStat{ otherUSDAssetStat, usdAssetStat, }, @@ -609,7 +836,7 @@ func TestGetAssetStatsFiltersAndCursor(t *testing.T) { "", "USD_GA5WBPYA5Y4WAEHXWR2UKO2UO4BUGHUQ74EUPKON2QHV4WRHOIRNKKH2_credit_alphanum4", "asc", - []ExpAssetStat{ + []AssetAndContractStat{ usdAssetStat, }, }, @@ -619,7 +846,7 @@ func TestGetAssetStatsFiltersAndCursor(t *testing.T) { "", "USD_GBRPYHIL2CI3FNQ4BXLFMNDLFJUNPU2HY3ZMFSHONUCEOASW7QC7OX2H_credit_alphanum4", "desc", - []ExpAssetStat{ + []AssetAndContractStat{ otherUSDAssetStat, }, }, @@ -629,7 +856,7 @@ func TestGetAssetStatsFiltersAndCursor(t *testing.T) { "GA5WBPYA5Y4WAEHXWR2UKO2UO4BUGHUQ74EUPKON2QHV4WRHOIRNKKH2", "", "asc", - []ExpAssetStat{ + []AssetAndContractStat{ eurAssetStat, otherUSDAssetStat, }, @@ -640,7 +867,7 @@ func TestGetAssetStatsFiltersAndCursor(t *testing.T) { "GA5WBPYA5Y4WAEHXWR2UKO2UO4BUGHUQ74EUPKON2QHV4WRHOIRNKKH2", "EUR_GA5WBPYA5Y4WAEHXWR2UKO2UO4BUGHUQ74EUPKON2QHV4WRHOIRNKKH2_credit_alphanum4", "asc", - []ExpAssetStat{ + []AssetAndContractStat{ otherUSDAssetStat, }, }, @@ -650,12 +877,12 @@ func TestGetAssetStatsFiltersAndCursor(t *testing.T) { "GA5WBPYA5Y4WAEHXWR2UKO2UO4BUGHUQ74EUPKON2QHV4WRHOIRNKKH2", "USD_GA5WBPYA5Y4WAEHXWR2UKO2UO4BUGHUQ74EUPKON2QHV4WRHOIRNKKH2_credit_alphanum4", "desc", - []ExpAssetStat{ + []AssetAndContractStat{ eurAssetStat, }, }, { - "filter on non existant code without cursor", + "filter on non existent code without cursor", "BTC", "", "", @@ -663,7 +890,7 @@ func TestGetAssetStatsFiltersAndCursor(t *testing.T) { nil, }, { - "filter on non existant code with cursor", + "filter on non existent code with cursor", "BTC", "", "BTC_GA5WBPYA5Y4WAEHXWR2UKO2UO4BUGHUQ74EUPKON2QHV4WRHOIRNKKH2_credit_alphanum4", @@ -671,7 +898,7 @@ func TestGetAssetStatsFiltersAndCursor(t *testing.T) { nil, }, { - "filter on non existant issuer without cursor", + "filter on non existent issuer without cursor", "", "GAEIHD6U4WSBHJGA2HPWOQ3OQEFQ3Y7QZE2DR76YKZNKPW5YDLYW4UGF", "", @@ -679,7 +906,7 @@ func TestGetAssetStatsFiltersAndCursor(t *testing.T) { nil, }, { - "filter on non existant issuer with cursor", + "filter on non existent issuer with cursor", "", "GAEIHD6U4WSBHJGA2HPWOQ3OQEFQ3Y7QZE2DR76YKZNKPW5YDLYW4UGF", "AAA_GAEIHD6U4WSBHJGA2HPWOQ3OQEFQ3Y7QZE2DR76YKZNKPW5YDLYW4UGF_credit_alphanum4", @@ -687,7 +914,7 @@ func TestGetAssetStatsFiltersAndCursor(t *testing.T) { nil, }, { - "filter on non existant code and non existant issuer without cursor", + "filter on non existent code and non existent issuer without cursor", "BTC", "GAEIHD6U4WSBHJGA2HPWOQ3OQEFQ3Y7QZE2DR76YKZNKPW5YDLYW4UGF", "", @@ -695,7 +922,7 @@ func TestGetAssetStatsFiltersAndCursor(t *testing.T) { nil, }, { - "filter on non existant code and non existant issuer with cursor", + "filter on non existent code and non existent issuer with cursor", "BTC", "GAEIHD6U4WSBHJGA2HPWOQ3OQEFQ3Y7QZE2DR76YKZNKPW5YDLYW4UGF", "AAA_GA5WBPYA5Y4WAEHXWR2UKO2UO4BUGHUQ74EUPKON2QHV4WRHOIRNKKH2_credit_alphanum4", @@ -708,7 +935,7 @@ func TestGetAssetStatsFiltersAndCursor(t *testing.T) { "GA5WBPYA5Y4WAEHXWR2UKO2UO4BUGHUQ74EUPKON2QHV4WRHOIRNKKH2", "", "asc", - []ExpAssetStat{ + []AssetAndContractStat{ otherUSDAssetStat, }, }, @@ -718,7 +945,7 @@ func TestGetAssetStatsFiltersAndCursor(t *testing.T) { "GA5WBPYA5Y4WAEHXWR2UKO2UO4BUGHUQ74EUPKON2QHV4WRHOIRNKKH2", "USC_GA5WBPYA5Y4WAEHXWR2UKO2UO4BUGHUQ74EUPKON2QHV4WRHOIRNKKH2_credit_alphanum4", "asc", - []ExpAssetStat{ + []AssetAndContractStat{ otherUSDAssetStat, }, }, @@ -728,7 +955,7 @@ func TestGetAssetStatsFiltersAndCursor(t *testing.T) { "GA5WBPYA5Y4WAEHXWR2UKO2UO4BUGHUQ74EUPKON2QHV4WRHOIRNKKH2", "USE_GA5WBPYA5Y4WAEHXWR2UKO2UO4BUGHUQ74EUPKON2QHV4WRHOIRNKKH2_credit_alphanum4", "desc", - []ExpAssetStat{ + []AssetAndContractStat{ otherUSDAssetStat, }, }, @@ -766,9 +993,231 @@ func TestGetAssetStatsFiltersAndCursor(t *testing.T) { results, err = q.GetAssetStats(tt.Ctx, testCase.assetCode, testCase.assetIssuer, page) tt.Assert.NoError(err) - reverseAssetStats(results) + slices.Reverse(results) tt.Assert.Equal(testCase.expected, results) } }) } } + +func assertContractAssetBalancesEqual(t *testing.T, balances, otherBalances []ContractAssetBalance) { + assert.Equal(t, len(balances), len(otherBalances)) + + sort.Slice(balances, func(i, j int) bool { + return bytes.Compare(balances[i].KeyHash, balances[j].KeyHash) < 0 + }) + sort.Slice(otherBalances, func(i, j int) bool { + return bytes.Compare(otherBalances[i].KeyHash, otherBalances[j].KeyHash) < 0 + }) + + for i, balance := range balances { + other := otherBalances[i] + assert.Equal(t, balance, other) + } +} + +func TestInsertContractAssetBalances(t *testing.T) { + tt := test.Start(t) + defer tt.Finish() + test.ResetHorizonDB(t, tt.HorizonDB) + + q := &Q{tt.HorizonSession()} + + tt.Assert.NoError(q.Begin(context.Background())) + + keyHash := [32]byte{} + contractID := [32]byte{1} + balance := ContractAssetBalance{ + KeyHash: keyHash[:], + ContractID: contractID[:], + Amount: "100", + ExpirationLedger: 10, + } + + otherKeyHash := [32]byte{2} + otherContractID := [32]byte{3} + otherBalance := ContractAssetBalance{ + KeyHash: otherKeyHash[:], + ContractID: otherContractID[:], + Amount: "101", + ExpirationLedger: 11, + } + + tt.Assert.NoError( + q.InsertContractAssetBalances(context.Background(), []ContractAssetBalance{balance, otherBalance}), + ) + + nonExistantKeyHash := [32]byte{4} + balances, err := q.GetContractAssetBalances(context.Background(), []xdr.Hash{keyHash, otherKeyHash, nonExistantKeyHash}) + tt.Assert.NoError(err) + + assertContractAssetBalancesEqual(t, balances, []ContractAssetBalance{balance, otherBalance}) + + tt.Assert.NoError(q.Rollback()) +} + +func TestRemoveContractAssetBalances(t *testing.T) { + tt := test.Start(t) + defer tt.Finish() + test.ResetHorizonDB(t, tt.HorizonDB) + + q := &Q{tt.HorizonSession()} + tt.Assert.NoError(q.Begin(context.Background())) + + keyHash := [32]byte{} + contractID := [32]byte{1} + balance := ContractAssetBalance{ + KeyHash: keyHash[:], + ContractID: contractID[:], + Amount: "100", + ExpirationLedger: 10, + } + + otherKeyHash := [32]byte{2} + otherContractID := [32]byte{3} + otherBalance := ContractAssetBalance{ + KeyHash: otherKeyHash[:], + ContractID: otherContractID[:], + Amount: "101", + ExpirationLedger: 11, + } + + tt.Assert.NoError( + q.InsertContractAssetBalances(context.Background(), []ContractAssetBalance{balance, otherBalance}), + ) + nonExistantKeyHash := xdr.Hash{4} + + tt.Assert.NoError( + q.RemoveContractAssetBalances(context.Background(), []xdr.Hash{nonExistantKeyHash}), + ) + balances, err := q.GetContractAssetBalances(context.Background(), []xdr.Hash{keyHash, otherKeyHash, nonExistantKeyHash}) + tt.Assert.NoError(err) + + assertContractAssetBalancesEqual(t, balances, []ContractAssetBalance{balance, otherBalance}) + + tt.Assert.NoError( + q.RemoveContractAssetBalances(context.Background(), []xdr.Hash{nonExistantKeyHash, otherKeyHash}), + ) + + balances, err = q.GetContractAssetBalances(context.Background(), []xdr.Hash{keyHash, otherKeyHash, nonExistantKeyHash}) + tt.Assert.NoError(err) + + assertContractAssetBalancesEqual(t, balances, []ContractAssetBalance{balance}) + + tt.Assert.NoError(q.Rollback()) +} + +func TestUpdateContractAssetBalanceAmounts(t *testing.T) { + tt := test.Start(t) + defer tt.Finish() + test.ResetHorizonDB(t, tt.HorizonDB) + + q := &Q{tt.HorizonSession()} + tt.Assert.NoError(q.Begin(context.Background())) + + keyHash := [32]byte{} + contractID := [32]byte{1} + balance := ContractAssetBalance{ + KeyHash: keyHash[:], + ContractID: contractID[:], + Amount: "100", + ExpirationLedger: 10, + } + + otherKeyHash := [32]byte{2} + otherContractID := [32]byte{3} + otherBalance := ContractAssetBalance{ + KeyHash: otherKeyHash[:], + ContractID: otherContractID[:], + Amount: "101", + ExpirationLedger: 11, + } + + tt.Assert.NoError( + q.InsertContractAssetBalances(context.Background(), []ContractAssetBalance{balance, otherBalance}), + ) + + nonExistantKeyHash := xdr.Hash{4} + + tt.Assert.NoError( + q.UpdateContractAssetBalanceAmounts( + context.Background(), + []xdr.Hash{otherKeyHash, keyHash, nonExistantKeyHash}, + []string{"1", "2", "3"}, + ), + ) + + balances, err := q.GetContractAssetBalances(context.Background(), []xdr.Hash{keyHash, otherKeyHash}) + tt.Assert.NoError(err) + + balance.Amount = "2" + otherBalance.Amount = "1" + assertContractAssetBalancesEqual(t, balances, []ContractAssetBalance{balance, otherBalance}) + + tt.Assert.NoError(q.Rollback()) +} + +func TestUpdateContractAssetBalanceExpirations(t *testing.T) { + tt := test.Start(t) + defer tt.Finish() + test.ResetHorizonDB(t, tt.HorizonDB) + + q := &Q{tt.HorizonSession()} + tt.Assert.NoError(q.Begin(context.Background())) + + keyHash := [32]byte{} + contractID := [32]byte{1} + balance := ContractAssetBalance{ + KeyHash: keyHash[:], + ContractID: contractID[:], + Amount: "100", + ExpirationLedger: 10, + } + + otherKeyHash := [32]byte{2} + otherContractID := [32]byte{3} + otherBalance := ContractAssetBalance{ + KeyHash: otherKeyHash[:], + ContractID: otherContractID[:], + Amount: "101", + ExpirationLedger: 11, + } + + tt.Assert.NoError( + q.InsertContractAssetBalances(context.Background(), []ContractAssetBalance{balance, otherBalance}), + ) + + balances, err := q.GetContractAssetBalancesExpiringAt(context.Background(), 10) + tt.Assert.NoError(err) + assertContractAssetBalancesEqual(t, balances, []ContractAssetBalance{balance}) + + balances, err = q.GetContractAssetBalancesExpiringAt(context.Background(), 11) + tt.Assert.NoError(err) + assertContractAssetBalancesEqual(t, balances, []ContractAssetBalance{otherBalance}) + + nonExistantKeyHash := xdr.Hash{4} + + tt.Assert.NoError( + q.UpdateContractAssetBalanceExpirations( + context.Background(), + []xdr.Hash{otherKeyHash, keyHash, nonExistantKeyHash}, + []uint32{200, 200, 500}, + ), + ) + + balances, err = q.GetContractAssetBalances(context.Background(), []xdr.Hash{keyHash, otherKeyHash}) + tt.Assert.NoError(err) + balance.ExpirationLedger = 200 + otherBalance.ExpirationLedger = 200 + assertContractAssetBalancesEqual(t, balances, []ContractAssetBalance{balance, otherBalance}) + + balances, err = q.GetContractAssetBalancesExpiringAt(context.Background(), 10) + tt.Assert.NoError(err) + assert.Empty(t, balances) + + balances, err = q.GetContractAssetBalancesExpiringAt(context.Background(), 200) + tt.Assert.NoError(err) + assertContractAssetBalancesEqual(t, balances, []ContractAssetBalance{balance, otherBalance}) + + tt.Assert.NoError(q.Rollback()) +} diff --git a/services/horizon/internal/db2/history/claimable_balance_batch_insert_builder.go b/services/horizon/internal/db2/history/claimable_balance_batch_insert_builder.go new file mode 100644 index 0000000000..515cc1643c --- /dev/null +++ b/services/horizon/internal/db2/history/claimable_balance_batch_insert_builder.go @@ -0,0 +1,40 @@ +package history + +import ( + "context" + + "github.com/stellar/go/support/db" +) + +// ClaimableBalanceBatchInsertBuilder is used to insert claimable balance into the +// claimable_balances table +type ClaimableBalanceBatchInsertBuilder interface { + Add(claimableBalance ClaimableBalance) error + Exec(ctx context.Context) error +} + +// ClaimableBalanceBatchInsertBuilder is a simple wrapper around db.FastBatchInsertBuilder +type claimableBalanceBatchInsertBuilder struct { + session db.SessionInterface + builder db.FastBatchInsertBuilder + table string +} + +// NewClaimableBalanceBatchInsertBuilder constructs a new ClaimableBalanceBatchInsertBuilder instance +func (q *Q) NewClaimableBalanceBatchInsertBuilder() ClaimableBalanceBatchInsertBuilder { + return &claimableBalanceBatchInsertBuilder{ + session: q, + builder: db.FastBatchInsertBuilder{}, + table: "claimable_balances", + } +} + +// Add adds a new claimable balance to the batch +func (i *claimableBalanceBatchInsertBuilder) Add(claimableBalance ClaimableBalance) error { + return i.builder.RowStruct(claimableBalance) +} + +// Exec writes the batch of claimable balances to the database. +func (i *claimableBalanceBatchInsertBuilder) Exec(ctx context.Context) error { + return i.builder.Exec(ctx, i.session, i.table) +} diff --git a/services/horizon/internal/db2/history/claimable_balance_claimant_batch_insert_builder.go b/services/horizon/internal/db2/history/claimable_balance_claimant_batch_insert_builder.go new file mode 100644 index 0000000000..2f4dc6733c --- /dev/null +++ b/services/horizon/internal/db2/history/claimable_balance_claimant_batch_insert_builder.go @@ -0,0 +1,40 @@ +package history + +import ( + "context" + + "github.com/stellar/go/support/db" +) + +// ClaimableBalanceClaimantBatchInsertBuilder is used to insert claimants into the +// claimable_balance_claimants table +type ClaimableBalanceClaimantBatchInsertBuilder interface { + Add(claimableBalanceClaimant ClaimableBalanceClaimant) error + Exec(ctx context.Context) error +} + +// ClaimableBalanceClaimantBatchInsertBuilder is a simple wrapper around db.FastBatchInsertBuilder +type claimableBalanceClaimantBatchInsertBuilder struct { + session db.SessionInterface + builder db.FastBatchInsertBuilder + table string +} + +// NewClaimableBalanceClaimantBatchInsertBuilder constructs a new ClaimableBalanceClaimantBatchInsertBuilder instance +func (q *Q) NewClaimableBalanceClaimantBatchInsertBuilder() ClaimableBalanceClaimantBatchInsertBuilder { + return &claimableBalanceClaimantBatchInsertBuilder{ + session: q, + builder: db.FastBatchInsertBuilder{}, + table: "claimable_balance_claimants", + } +} + +// Add adds a new claimant to the batch +func (i *claimableBalanceClaimantBatchInsertBuilder) Add(claimableBalanceClaimant ClaimableBalanceClaimant) error { + return i.builder.RowStruct(claimableBalanceClaimant) +} + +// Exec writes the batch of claimants to the database. +func (i *claimableBalanceClaimantBatchInsertBuilder) Exec(ctx context.Context) error { + return i.builder.Exec(ctx, i.session, i.table) +} diff --git a/services/horizon/internal/db2/history/claimable_balance_loader.go b/services/horizon/internal/db2/history/claimable_balance_loader.go new file mode 100644 index 0000000000..dd7dee4ea5 --- /dev/null +++ b/services/horizon/internal/db2/history/claimable_balance_loader.go @@ -0,0 +1,147 @@ +package history + +import ( + "context" + "database/sql/driver" + "fmt" + "sort" + + "github.com/stellar/go/support/collections/set" + "github.com/stellar/go/support/db" + "github.com/stellar/go/support/errors" + "github.com/stellar/go/support/ordered" +) + +// FutureClaimableBalanceID represents a future history claimable balance. +// A FutureClaimableBalanceID is created by a ClaimableBalanceLoader and +// the claimable balance id is available after calling Exec() on +// the ClaimableBalanceLoader. +type FutureClaimableBalanceID struct { + id string + loader *ClaimableBalanceLoader +} + +// Value implements the database/sql/driver Valuer interface. +func (a FutureClaimableBalanceID) Value() (driver.Value, error) { + return a.loader.getNow(a.id) +} + +// ClaimableBalanceLoader will map claimable balance ids to their internal +// history ids. If there is no existing mapping for a given claimable balance id, +// the ClaimableBalanceLoader will insert into the history_claimable_balances table to +// establish a mapping. +type ClaimableBalanceLoader struct { + sealed bool + set set.Set[string] + ids map[string]int64 +} + +// NewClaimableBalanceLoader will construct a new ClaimableBalanceLoader instance. +func NewClaimableBalanceLoader() *ClaimableBalanceLoader { + return &ClaimableBalanceLoader{ + sealed: false, + set: set.Set[string]{}, + ids: map[string]int64{}, + } +} + +// GetFuture registers the given claimable balance into the loader and +// returns a FutureClaimableBalanceID which will hold the internal history id for +// the claimable balance after Exec() is called. +func (a *ClaimableBalanceLoader) GetFuture(id string) FutureClaimableBalanceID { + if a.sealed { + panic(errSealed) + } + + a.set.Add(id) + return FutureClaimableBalanceID{ + id: id, + loader: a, + } +} + +// getNow returns the internal history id for the given claimable balance. +// getNow should only be called on values which were registered by +// GetFuture() calls. Also, Exec() must be called before any getNow +// call can succeed. +func (a *ClaimableBalanceLoader) getNow(id string) (int64, error) { + if !a.sealed { + return 0, fmt.Errorf(`invalid claimable balance loader state, + Exec was not called yet to properly seal and resolve %v id`, id) + } + if internalID, ok := a.ids[id]; !ok { + return 0, fmt.Errorf(`claimable balance loader id %q was not found`, id) + } else { + return internalID, nil + } +} + +func (a *ClaimableBalanceLoader) lookupKeys(ctx context.Context, q *Q, ids []string) error { + for i := 0; i < len(ids); i += loaderLookupBatchSize { + end := ordered.Min(len(ids), i+loaderLookupBatchSize) + + cbs, err := q.ClaimableBalancesByIDs(ctx, ids[i:end]) + if err != nil { + return errors.Wrap(err, "could not select claimable balances") + } + + for _, cb := range cbs { + a.ids[cb.BalanceID] = cb.InternalID + } + } + return nil +} + +// Exec will look up all the internal history ids for the claimable balances registered in the loader. +// If there are no internal ids for a given set of claimable balances, Exec will insert rows +// into the history_claimable_balances table. +func (a *ClaimableBalanceLoader) Exec(ctx context.Context, session db.SessionInterface) error { + a.sealed = true + if len(a.set) == 0 { + return nil + } + q := &Q{session} + ids := make([]string, 0, len(a.set)) + for id := range a.set { + ids = append(ids, id) + } + + if err := a.lookupKeys(ctx, q, ids); err != nil { + return err + } + + insert := 0 + for _, id := range ids { + if _, ok := a.ids[id]; ok { + continue + } + ids[insert] = id + insert++ + } + if insert == 0 { + return nil + } + ids = ids[:insert] + // sort entries before inserting rows to prevent deadlocks on acquiring a ShareLock + // https://github.com/stellar/go/issues/2370 + sort.Strings(ids) + + err := bulkInsert( + ctx, + q, + "history_claimable_balances", + []string{"claimable_balance_id"}, + []bulkInsertField{ + { + name: "claimable_balance_id", + dbType: "text", + objects: ids, + }, + }, + ) + if err != nil { + return err + } + + return a.lookupKeys(ctx, q, ids) +} diff --git a/services/horizon/internal/db2/history/claimable_balance_loader_test.go b/services/horizon/internal/db2/history/claimable_balance_loader_test.go new file mode 100644 index 0000000000..4dd7324521 --- /dev/null +++ b/services/horizon/internal/db2/history/claimable_balance_loader_test.go @@ -0,0 +1,62 @@ +package history + +import ( + "context" + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/stellar/go/services/horizon/internal/test" + "github.com/stellar/go/xdr" +) + +func TestClaimableBalanceLoader(t *testing.T) { + tt := test.Start(t) + defer tt.Finish() + test.ResetHorizonDB(t, tt.HorizonDB) + session := tt.HorizonSession() + + var ids []string + for i := 0; i < 100; i++ { + balanceID := xdr.ClaimableBalanceId{ + Type: xdr.ClaimableBalanceIdTypeClaimableBalanceIdTypeV0, + V0: &xdr.Hash{byte(i)}, + } + id, err := xdr.MarshalHex(balanceID) + tt.Assert.NoError(err) + ids = append(ids, id) + } + + loader := NewClaimableBalanceLoader() + var futures []FutureClaimableBalanceID + for _, id := range ids { + future := loader.GetFuture(id) + futures = append(futures, future) + _, err := future.Value() + assert.Error(t, err) + assert.Contains(t, err.Error(), `invalid claimable balance loader state,`) + duplicateFuture := loader.GetFuture(id) + assert.Equal(t, future, duplicateFuture) + } + + assert.NoError(t, loader.Exec(context.Background(), session)) + assert.Panics(t, func() { + loader.GetFuture("not-present") + }) + + q := &Q{session} + for i, id := range ids { + future := futures[i] + internalID, err := future.Value() + assert.NoError(t, err) + cb, err := q.ClaimableBalanceByID(context.Background(), id) + assert.NoError(t, err) + assert.Equal(t, cb.BalanceID, id) + assert.Equal(t, cb.InternalID, internalID) + } + + futureCb := &FutureClaimableBalanceID{id: "not-present", loader: loader} + _, err := futureCb.Value() + assert.Error(t, err) + assert.Contains(t, err.Error(), `was not found`) +} diff --git a/services/horizon/internal/db2/history/claimable_balances.go b/services/horizon/internal/db2/history/claimable_balances.go index 31401ff2ef..5490bef11c 100644 --- a/services/horizon/internal/db2/history/claimable_balances.go +++ b/services/horizon/internal/db2/history/claimable_balances.go @@ -4,6 +4,7 @@ import ( "context" "database/sql/driver" "encoding/json" + "fmt" "strconv" "strings" @@ -46,7 +47,7 @@ func (cbq ClaimableBalancesQuery) Cursor() (int64, string, error) { } r = parts[1] if l < 0 { - return l, r, errors.Wrap(err, "Invalid cursor - first value should be higher than 0") + return l, r, errors.New("invalid cursor - first value should be higher than 0") } } @@ -56,39 +57,42 @@ func (cbq ClaimableBalancesQuery) Cursor() (int64, string, error) { // ApplyCursor applies cursor to the given sql. For performance reason the limit // is not applied here. This allows us to hint the planner later to use the right // indexes. -func (cbq ClaimableBalancesQuery) ApplyCursor(sql sq.SelectBuilder) (sq.SelectBuilder, error) { - p := cbq.PageQuery +func applyClaimableBalancesQueriesCursor(sql sq.SelectBuilder, lCursor int64, rCursor string, order string) (sq.SelectBuilder, error) { hasPagedLimit := false - l, r, err := cbq.Cursor() - if err != nil { - return sql, err - } - if l > 0 && r != "" { + if lCursor > 0 && rCursor != "" { hasPagedLimit = true } - switch p.Order { + switch order { case db2.OrderAscending: if hasPagedLimit { sql = sql. - Where(sq.Expr("(cb.last_modified_ledger, cb.id) > (?, ?)", l, r)) + Where(sq.Expr("(last_modified_ledger, id) > (?, ?)", lCursor, rCursor)) } - sql = sql.OrderBy("cb.last_modified_ledger asc, cb.id asc") + sql = sql.OrderBy("last_modified_ledger asc, id asc") case db2.OrderDescending: if hasPagedLimit { sql = sql. - Where(sq.Expr("(cb.last_modified_ledger, cb.id) < (?, ?)", l, r)) + Where(sq.Expr("(last_modified_ledger, id) < (?, ?)", lCursor, rCursor)) } - sql = sql.OrderBy("cb.last_modified_ledger desc, cb.id desc") + sql = sql.OrderBy("last_modified_ledger desc, id desc") default: - return sql, errors.Errorf("invalid order: %s", p.Order) + return sql, errors.Errorf("invalid order: %s", order) } return sql, nil } +// ClaimableBalanceClaimant is a row of data from the `claimable_balances_claimants` table. +// This table exists to allow faster querying for claimable balances for a specific claimant. +type ClaimableBalanceClaimant struct { + BalanceID string `db:"id"` + Destination string `db:"destination"` + LastModifiedLedger uint32 `db:"last_modified_ledger"` +} + // ClaimableBalance is a row of data from the `claimable_balances` table. type ClaimableBalance struct { BalanceID string `db:"id"` @@ -103,7 +107,11 @@ type ClaimableBalance struct { type Claimants []Claimant func (c Claimants) Value() (driver.Value, error) { - return json.Marshal(c) + // Convert the byte array into a string as a workaround to bypass buggy encoding in the pq driver + // (More info about this bug here https://github.com/stellar/go/issues/5086#issuecomment-1773215436). + // By doing so, the data will be written as a string rather than hex encoded bytes. + val, err := json.Marshal(c) + return string(val), err } func (c *Claimants) Scan(value interface{}) error { @@ -122,10 +130,13 @@ type Claimant struct { // QClaimableBalances defines claimable-balance-related related queries. type QClaimableBalances interface { - UpsertClaimableBalances(ctx context.Context, cb []ClaimableBalance) error RemoveClaimableBalances(ctx context.Context, ids []string) (int64, error) + RemoveClaimableBalanceClaimants(ctx context.Context, ids []string) (int64, error) GetClaimableBalancesByID(ctx context.Context, ids []string) ([]ClaimableBalance, error) CountClaimableBalances(ctx context.Context) (int, error) + NewClaimableBalanceClaimantBatchInsertBuilder() ClaimableBalanceClaimantBatchInsertBuilder + NewClaimableBalanceBatchInsertBuilder() ClaimableBalanceBatchInsertBuilder + GetClaimantsByClaimableBalances(ctx context.Context, ids []string) (map[string][]ClaimableBalanceClaimant, error) } // CountClaimableBalances returns the total number of claimable balances in the DB @@ -148,34 +159,20 @@ func (q *Q) GetClaimableBalancesByID(ctx context.Context, ids []string) ([]Claim return cBalances, err } -// UpsertClaimableBalances upserts a batch of claimable balances in the claimable_balances table. -// There's currently no limit of the number of offers this method can -// accept other than 2GB limit of the query string length what should be enough -// for each ledger with the current limits. -func (q *Q) UpsertClaimableBalances(ctx context.Context, cbs []ClaimableBalance) error { - var id, claimants, asset, amount, sponsor, lastModifiedLedger, flags []interface{} - - for _, cb := range cbs { - id = append(id, cb.BalanceID) - claimants = append(claimants, cb.Claimants) - asset = append(asset, cb.Asset) - amount = append(amount, cb.Amount) - sponsor = append(sponsor, cb.Sponsor) - lastModifiedLedger = append(lastModifiedLedger, cb.LastModifiedLedger) - flags = append(flags, cb.Flags) - } - - upsertFields := []upsertField{ - {"id", "text", id}, - {"claimants", "jsonb", claimants}, - {"asset", "text", asset}, - {"amount", "bigint", amount}, - {"sponsor", "text", sponsor}, - {"last_modified_ledger", "integer", lastModifiedLedger}, - {"flags", "int", flags}, +// GetClaimantsByClaimableBalances finds all claimants for ClaimableBalanceIds. +// The returned list is sorted by ids and then destination ids for each balance id. +func (q *Q) GetClaimantsByClaimableBalances(ctx context.Context, ids []string) (map[string][]ClaimableBalanceClaimant, error) { + var claimants []ClaimableBalanceClaimant + sql := sq.Select("*").From("claimable_balance_claimants cbc"). + Where(map[string]interface{}{"cbc.id": ids}). + OrderBy("id asc, destination asc") + err := q.Select(ctx, &claimants, sql) + + claimantsMap := make(map[string][]ClaimableBalanceClaimant) + for _, claimant := range claimants { + claimantsMap[claimant.BalanceID] = append(claimantsMap[claimant.BalanceID], claimant) } - - return q.upsertRows(ctx, "claimable_balances", "id", upsertFields) + return claimantsMap, err } // RemoveClaimableBalances deletes claimable balances table. @@ -191,6 +188,19 @@ func (q *Q) RemoveClaimableBalances(ctx context.Context, ids []string) (int64, e return result.RowsAffected() } +// RemoveClaimableBalanceClaimants deletes claimable balance claimants. +// Returns number of rows affected and error. +func (q *Q) RemoveClaimableBalanceClaimants(ctx context.Context, ids []string) (int64, error) { + sql := sq.Delete("claimable_balance_claimants"). + Where(sq.Eq{"id": ids}) + result, err := q.Exec(ctx, sql) + if err != nil { + return 0, err + } + + return result.RowsAffected() +} + // FindClaimableBalanceByID returns a claimable balance. func (q *Q) FindClaimableBalanceByID(ctx context.Context, balanceID string) (ClaimableBalance, error) { var claimableBalance ClaimableBalance @@ -201,39 +211,55 @@ func (q *Q) FindClaimableBalanceByID(ctx context.Context, balanceID string) (Cla // GetClaimableBalances finds all claimable balances where accountID is one of the claimants func (q *Q) GetClaimableBalances(ctx context.Context, query ClaimableBalancesQuery) ([]ClaimableBalance, error) { - sql, err := query.ApplyCursor(selectClaimableBalances) - // we need to use WITH syntax and correct LIMIT placement to force the query planner to use the right - // indexes, otherwise when the limit is small, it will use an index scan - // which will be very slow once we have millions of records - limitClausePlacement := "LIMIT ?) select " + claimableBalancesSelectStatement + " from cb" + l, r, err := query.Cursor() + if err != nil { + return nil, errors.Wrap(err, "error getting cursor") + } + sql, err := applyClaimableBalancesQueriesCursor(selectClaimableBalances, l, r, query.PageQuery.Order) if err != nil { return nil, errors.Wrap(err, "could not apply query to page") } - if query.Asset != nil { - // when search by asset, profiling has shown best performance to have the LIMIT on inner query - sql = sql.Where("cb.asset = ?", query.Asset) - } + if query.Asset != nil || query.Sponsor != nil { - if query.Sponsor != nil { - sql = sql.Where("cb.sponsor = ?", query.Sponsor.Address()) - } + // JOIN with claimable_balance_claimants table to query by claimants + if query.Claimant != nil { + sql = sql.Join("claimable_balance_claimants on claimable_balance_claimants.id = cb.id") + sql = sql.Where("claimable_balance_claimants.destination = ?", query.Claimant.Address()) + } + + // Apply filters for asset and sponsor + if query.Asset != nil { + sql = sql.Where("cb.asset = ?", query.Asset) + } + if query.Sponsor != nil { + sql = sql.Where("cb.sponsor = ?", query.Sponsor.Address()) + } + + } else if query.Claimant != nil { + // If only the claimant is provided without additional filters, a JOIN with claimable_balance_claimants + // does not perform efficiently. Instead, use a subquery (with LIMIT) to retrieve claimable balances based on + // the claimant's address. + + var selectClaimableBalanceClaimants = sq.Select("id").From("claimable_balance_claimants"). + Where("destination = ?", query.Claimant.Address()).Limit(query.PageQuery.Limit) + + subSql, err := applyClaimableBalancesQueriesCursor(selectClaimableBalanceClaimants, l, r, query.PageQuery.Order) + if err != nil { + return nil, errors.Wrap(err, "could not apply subquery to page") + } + + subSqlString, subSqlArgs, err := subSql.ToSql() + if err != nil { + return nil, errors.Wrap(err, "could not build subquery") + } - if query.Claimant != nil { sql = sql. - Where(`cb.claimants @> '[{"destination": "` + query.Claimant.Address() + `"}]'`) - // when search by claimant, profiling has shown the LIMIT should be on the outer query to - // hint appropriate indexes for best performance - limitClausePlacement = ") select " + claimableBalancesSelectStatement + " from cb LIMIT ?" + Where(fmt.Sprintf("cb.id IN (%s)", subSqlString), subSqlArgs...) } - sql = sql. - Prefix("WITH cb AS ("). - Suffix( - limitClausePlacement, - query.PageQuery.Limit, - ) + sql = sql.Limit(query.PageQuery.Limit) var results []ClaimableBalance if err := q.Select(ctx, &results, sql); err != nil { diff --git a/services/horizon/internal/db2/history/claimable_balances_test.go b/services/horizon/internal/db2/history/claimable_balances_test.go index 9321e6351f..ca32975c62 100644 --- a/services/horizon/internal/db2/history/claimable_balances_test.go +++ b/services/horizon/internal/db2/history/claimable_balances_test.go @@ -1,6 +1,7 @@ package history import ( + "database/sql" "fmt" "testing" @@ -15,6 +16,10 @@ func TestRemoveClaimableBalance(t *testing.T) { defer tt.Finish() test.ResetHorizonDB(t, tt.HorizonDB) q := &Q{tt.HorizonSession()} + tt.Assert.NoError(q.BeginTx(tt.Ctx, &sql.TxOptions{})) + defer func() { + _ = q.Rollback() + }() accountID := "GC3C4AKRBQLHOJ45U4XG35ESVWRDECWO5XLDGYADO6DPR3L7KIDVUMML" asset := xdr.MustNewCreditAsset("USD", accountID) @@ -39,8 +44,9 @@ func TestRemoveClaimableBalance(t *testing.T) { Amount: 10, } - err = q.UpsertClaimableBalances(tt.Ctx, []ClaimableBalance{cBalance}) - tt.Assert.NoError(err) + balanceBatchInsertBuilder := q.NewClaimableBalanceBatchInsertBuilder() + tt.Assert.NoError(balanceBatchInsertBuilder.Add(cBalance)) + tt.Assert.NoError(balanceBatchInsertBuilder.Exec(tt.Ctx)) r, err := q.FindClaimableBalanceByID(tt.Ctx, id) tt.Assert.NoError(err) @@ -58,12 +64,59 @@ func TestRemoveClaimableBalance(t *testing.T) { } } +func TestRemoveClaimableBalanceClaimants(t *testing.T) { + tt := test.Start(t) + defer tt.Finish() + test.ResetHorizonDB(t, tt.HorizonDB) + q := &Q{tt.HorizonSession()} + tt.Assert.NoError(q.BeginTx(tt.Ctx, &sql.TxOptions{})) + defer func() { + _ = q.Rollback() + }() + + accountID := "GC3C4AKRBQLHOJ45U4XG35ESVWRDECWO5XLDGYADO6DPR3L7KIDVUMML" + asset := xdr.MustNewCreditAsset("USD", accountID) + balanceID := xdr.ClaimableBalanceId{ + Type: xdr.ClaimableBalanceIdTypeClaimableBalanceIdTypeV0, + V0: &xdr.Hash{1, 2, 3}, + } + id, err := xdr.MarshalHex(balanceID) + tt.Assert.NoError(err) + cBalance := ClaimableBalance{ + BalanceID: id, + Claimants: []Claimant{ + { + Destination: accountID, + Predicate: xdr.ClaimPredicate{ + Type: xdr.ClaimPredicateTypeClaimPredicateUnconditional, + }, + }, + }, + Asset: asset, + LastModifiedLedger: 123, + Amount: 10, + } + + claimantsInsertBuilder := q.NewClaimableBalanceClaimantBatchInsertBuilder() + tt.Assert.NoError(insertClaimants(claimantsInsertBuilder, cBalance)) + tt.Assert.NoError(claimantsInsertBuilder.Exec(tt.Ctx)) + + removed, err := q.RemoveClaimableBalanceClaimants(tt.Ctx, []string{id}) + tt.Assert.NoError(err) + tt.Assert.Equal(int64(1), removed) +} + func TestFindClaimableBalancesByDestination(t *testing.T) { tt := test.Start(t) defer tt.Finish() test.ResetHorizonDB(t, tt.HorizonDB) q := &Q{tt.HorizonSession()} + tt.Assert.NoError(q.BeginTx(tt.Ctx, &sql.TxOptions{})) + defer func() { + _ = q.Rollback() + }() + dest1 := "GC3C4AKRBQLHOJ45U4XG35ESVWRDECWO5XLDGYADO6DPR3L7KIDVUMML" dest2 := "GBRPYHIL2CI3FNQ4BXLFMNDLFJUNPU2HY3ZMFSHONUCEOASW7QC7OX2H" @@ -89,8 +142,11 @@ func TestFindClaimableBalancesByDestination(t *testing.T) { Amount: 10, } - err = q.UpsertClaimableBalances(tt.Ctx, []ClaimableBalance{cBalance}) - tt.Assert.NoError(err) + balanceInsertBuilder := q.NewClaimableBalanceBatchInsertBuilder() + claimantsInsertBuilder := q.NewClaimableBalanceClaimantBatchInsertBuilder() + + tt.Assert.NoError(balanceInsertBuilder.Add(cBalance)) + tt.Assert.NoError(insertClaimants(claimantsInsertBuilder, cBalance)) balanceID = xdr.ClaimableBalanceId{ Type: xdr.ClaimableBalanceIdTypeClaimableBalanceIdTypeV0, @@ -119,8 +175,11 @@ func TestFindClaimableBalancesByDestination(t *testing.T) { Amount: 10, } - err = q.UpsertClaimableBalances(tt.Ctx, []ClaimableBalance{cBalance}) - tt.Assert.NoError(err) + tt.Assert.NoError(balanceInsertBuilder.Add(cBalance)) + tt.Assert.NoError(insertClaimants(claimantsInsertBuilder, cBalance)) + + tt.Assert.NoError(claimantsInsertBuilder.Exec(tt.Ctx)) + tt.Assert.NoError(balanceInsertBuilder.Exec(tt.Ctx)) query := ClaimableBalancesQuery{ PageQuery: db2.MustPageQuery("", false, "", 10), @@ -160,65 +219,190 @@ func TestFindClaimableBalancesByDestination(t *testing.T) { tt.Assert.Len(cbs, 1) } -func TestUpdateClaimableBalance(t *testing.T) { +func insertClaimants(claimantsInsertBuilder ClaimableBalanceClaimantBatchInsertBuilder, cBalance ClaimableBalance) error { + for _, claimant := range cBalance.Claimants { + claimant := ClaimableBalanceClaimant{ + BalanceID: cBalance.BalanceID, + Destination: claimant.Destination, + LastModifiedLedger: cBalance.LastModifiedLedger, + } + err := claimantsInsertBuilder.Add(claimant) + if err != nil { + return err + } + } + return nil +} + +type claimableBalanceQueryResult struct { + Claimants []string + Asset string + Sponsor string +} + +func validateClaimableBalanceQuery(t *test.T, q *Q, query ClaimableBalancesQuery, expectedQueryResult []claimableBalanceQueryResult) { + cbs, err := q.GetClaimableBalances(t.Ctx, query) + t.Assert.NoError(err) + for i, expected := range expectedQueryResult { + for j, claimant := range expected.Claimants { + t.Assert.Equal(claimant, cbs[i].Claimants[j].Destination) + } + if expected.Asset != "" { + t.Assert.Equal(expected.Asset, cbs[i].Asset.String()) + } + if expected.Sponsor != "" { + t.Assert.Equal(expected.Sponsor, cbs[i].Sponsor.String) + } + } +} + +// TestFindClaimableBalancesByDestinationWithLimit tests querying claimable balances by destination and asset +func TestFindClaimableBalancesByDestinationWithLimit(t *testing.T) { tt := test.Start(t) defer tt.Finish() + test.ResetHorizonDB(t, tt.HorizonDB) q := &Q{tt.HorizonSession()} - accountID := "GC3C4AKRBQLHOJ45U4XG35ESVWRDECWO5XLDGYADO6DPR3L7KIDVUMML" - lastModifiedLedgerSeq := xdr.Uint32(123) - asset := xdr.MustNewCreditAsset("USD", accountID) - balanceID := xdr.ClaimableBalanceId{ + tt.Assert.NoError(q.BeginTx(tt.Ctx, &sql.TxOptions{})) + defer func() { + _ = q.Rollback() + }() + + assetIssuer := "GA25GQLHJU3LPEJXEIAXK23AWEA5GWDUGRSHTQHDFT6HXHVMRULSQJUJ" + asset1 := xdr.MustNewCreditAsset("ASSET1", assetIssuer) + asset2 := xdr.MustNewCreditAsset("ASSET2", assetIssuer) + + sponsor1 := "GA25GQLHJU3LPEJXEIAXK23AWEA5GWDUGRSHTQHDFT6HXHVMRULSQJUJ" + sponsor2 := "GBRPYHIL2CI3FNQ4BXLFMNDLFJUNPU2HY3ZMFSHONUCEOASW7QC7OX2H" + + dest1 := "GC3C4AKRBQLHOJ45U4XG35ESVWRDECWO5XLDGYADO6DPR3L7KIDVUMML" + dest2 := "GBRPYHIL2CI3FNQ4BXLFMNDLFJUNPU2HY3ZMFSHONUCEOASW7QC7OX2H" + + claimants := []Claimant{ + { + Destination: dest1, + Predicate: xdr.ClaimPredicate{ + Type: xdr.ClaimPredicateTypeClaimPredicateUnconditional, + }, + }, + { + Destination: dest2, + Predicate: xdr.ClaimPredicate{ + Type: xdr.ClaimPredicateTypeClaimPredicateUnconditional, + }, + }, + } + + balanceID1 := xdr.ClaimableBalanceId{ Type: xdr.ClaimableBalanceIdTypeClaimableBalanceIdTypeV0, V0: &xdr.Hash{1, 2, 3}, } - id, err := xdr.MarshalHex(balanceID) + id, err := xdr.MarshalHex(balanceID1) tt.Assert.NoError(err) - cBalance := ClaimableBalance{ - BalanceID: id, - Claimants: []Claimant{ - { - Destination: accountID, - Predicate: xdr.ClaimPredicate{ - Type: xdr.ClaimPredicateTypeClaimPredicateUnconditional, - }, - }, - }, - Asset: asset, + cBalance1 := ClaimableBalance{ + BalanceID: id, + Claimants: claimants, + Asset: asset1, + Sponsor: null.StringFrom(sponsor1), LastModifiedLedger: 123, Amount: 10, } + balanceInsertBuilder := q.NewClaimableBalanceBatchInsertBuilder() + claimantsInsertBuilder := q.NewClaimableBalanceClaimantBatchInsertBuilder() - err = q.UpsertClaimableBalances(tt.Ctx, []ClaimableBalance{cBalance}) - tt.Assert.NoError(err) + tt.Assert.NoError(balanceInsertBuilder.Add(cBalance1)) + tt.Assert.NoError(insertClaimants(claimantsInsertBuilder, cBalance1)) - // add sponsor - cBalance2 := ClaimableBalance{ - BalanceID: id, - Claimants: []Claimant{ - { - Destination: accountID, - Predicate: xdr.ClaimPredicate{ - Type: xdr.ClaimPredicateTypeClaimPredicateUnconditional, - }, + claimants2 := []Claimant{ + { + Destination: dest2, + Predicate: xdr.ClaimPredicate{ + Type: xdr.ClaimPredicateTypeClaimPredicateUnconditional, }, }, - Asset: asset, - LastModifiedLedger: 123 + 1, - Amount: 10, - Sponsor: null.StringFrom("GC3C4AKRBQLHOJ45U4XG35ESVWRDECWO5XLDGYADO6DPR3L7KIDVUMML"), } - err = q.UpsertClaimableBalances(tt.Ctx, []ClaimableBalance{cBalance2}) + balanceID2 := xdr.ClaimableBalanceId{ + Type: xdr.ClaimableBalanceIdTypeClaimableBalanceIdTypeV0, + V0: &xdr.Hash{4, 5, 6}, + } + id, err = xdr.MarshalHex(balanceID2) tt.Assert.NoError(err) + cBalance2 := ClaimableBalance{ + BalanceID: id, + Claimants: claimants2, + Asset: asset2, + Sponsor: null.StringFrom(sponsor2), - cbs := []ClaimableBalance{} - err = q.Select(tt.Ctx, &cbs, selectClaimableBalances) - tt.Assert.NoError(err) - tt.Assert.Len(cbs, 1) - tt.Assert.Equal("GC3C4AKRBQLHOJ45U4XG35ESVWRDECWO5XLDGYADO6DPR3L7KIDVUMML", cbs[0].Sponsor.String) - tt.Assert.Equal(uint32(lastModifiedLedgerSeq+1), cbs[0].LastModifiedLedger) + LastModifiedLedger: 456, + Amount: 10, + } + + tt.Assert.NoError(balanceInsertBuilder.Add(cBalance2)) + tt.Assert.NoError(insertClaimants(claimantsInsertBuilder, cBalance2)) + + tt.Assert.NoError(claimantsInsertBuilder.Exec(tt.Ctx)) + tt.Assert.NoError(balanceInsertBuilder.Exec(tt.Ctx)) + + pageQuery := db2.MustPageQuery("", false, "", 1) + + // no claimant parameter, no filters + query := ClaimableBalancesQuery{ + PageQuery: pageQuery, + } + validateClaimableBalanceQuery(tt, q, query, []claimableBalanceQueryResult{ + {Claimants: []string{dest1, dest2}}, + }) + + // invalid claimant parameter + query = ClaimableBalancesQuery{ + PageQuery: pageQuery, + Claimant: xdr.MustAddressPtr("GA25GQLHJU3LPEJXEIAXK23AWEA5GWDUGRSHTQHDFT6HXHVMRULSQJUJ"), + Asset: &asset2, + Sponsor: xdr.MustAddressPtr(sponsor1), + } + validateClaimableBalanceQuery(tt, q, query, []claimableBalanceQueryResult{}) + + // claimant parameter, no filters + query = ClaimableBalancesQuery{ + PageQuery: pageQuery, + Claimant: xdr.MustAddressPtr(dest1), + } + validateClaimableBalanceQuery(tt, q, query, []claimableBalanceQueryResult{ + {Claimants: []string{dest1, dest2}}, + }) + + // claimant parameter, asset filter + query = ClaimableBalancesQuery{ + PageQuery: pageQuery, + Claimant: xdr.MustAddressPtr(dest2), + Asset: &asset1, + } + validateClaimableBalanceQuery(tt, q, query, []claimableBalanceQueryResult{ + {Claimants: []string{dest1, dest2}, Asset: asset1.String()}, + }) + + // claimant parameter, sponsor filter + query = ClaimableBalancesQuery{ + PageQuery: pageQuery, + Claimant: xdr.MustAddressPtr(dest2), + Sponsor: xdr.MustAddressPtr(sponsor1), + } + validateClaimableBalanceQuery(tt, q, query, []claimableBalanceQueryResult{ + {Claimants: []string{dest1, dest2}, Sponsor: sponsor1}, + }) + + //claimant parameter, asset filter, sponsor filter + query = ClaimableBalancesQuery{ + PageQuery: pageQuery, + Claimant: xdr.MustAddressPtr(dest2), + Asset: &asset2, + Sponsor: xdr.MustAddressPtr(sponsor2), + } + validateClaimableBalanceQuery(tt, q, query, []claimableBalanceQueryResult{ + {Claimants: []string{dest2}, Asset: asset2.String(), Sponsor: sponsor2}, + }) } func TestFindClaimableBalance(t *testing.T) { @@ -227,6 +411,11 @@ func TestFindClaimableBalance(t *testing.T) { test.ResetHorizonDB(t, tt.HorizonDB) q := &Q{tt.HorizonSession()} + tt.Assert.NoError(q.BeginTx(tt.Ctx, &sql.TxOptions{})) + defer func() { + _ = q.Rollback() + }() + accountID := "GC3C4AKRBQLHOJ45U4XG35ESVWRDECWO5XLDGYADO6DPR3L7KIDVUMML" asset := xdr.MustNewCreditAsset("USD", accountID) balanceID := xdr.ClaimableBalanceId{ @@ -250,11 +439,11 @@ func TestFindClaimableBalance(t *testing.T) { Amount: 10, } - err = q.UpsertClaimableBalances(tt.Ctx, []ClaimableBalance{cBalance}) - tt.Assert.NoError(err) + balanceInsertBuilder := q.NewClaimableBalanceBatchInsertBuilder() + tt.Assert.NoError(balanceInsertBuilder.Add(cBalance)) + tt.Assert.NoError(balanceInsertBuilder.Exec(tt.Ctx)) cb, err := q.FindClaimableBalanceByID(tt.Ctx, id) - tt.Assert.NoError(err) tt.Assert.Equal(cBalance.BalanceID, cb.BalanceID) tt.Assert.Equal(cBalance.Asset, cb.Asset) @@ -271,6 +460,11 @@ func TestGetClaimableBalancesByID(t *testing.T) { test.ResetHorizonDB(t, tt.HorizonDB) q := &Q{tt.HorizonSession()} + tt.Assert.NoError(q.BeginTx(tt.Ctx, &sql.TxOptions{})) + defer func() { + _ = q.Rollback() + }() + accountID := "GC3C4AKRBQLHOJ45U4XG35ESVWRDECWO5XLDGYADO6DPR3L7KIDVUMML" asset := xdr.MustNewCreditAsset("USD", accountID) balanceID := xdr.ClaimableBalanceId{ @@ -294,8 +488,9 @@ func TestGetClaimableBalancesByID(t *testing.T) { Amount: 10, } - err = q.UpsertClaimableBalances(tt.Ctx, []ClaimableBalance{cBalance}) - tt.Assert.NoError(err) + balanceInsertBuilder := q.NewClaimableBalanceBatchInsertBuilder() + tt.Assert.NoError(balanceInsertBuilder.Add(cBalance)) + tt.Assert.NoError(balanceInsertBuilder.Exec(tt.Ctx)) r, err := q.GetClaimableBalancesByID(tt.Ctx, []string{id}) tt.Assert.NoError(err) diff --git a/services/horizon/internal/db2/history/effect.go b/services/horizon/internal/db2/history/effect.go index c905479c6c..13a9c52519 100644 --- a/services/horizon/internal/db2/history/effect.go +++ b/services/horizon/internal/db2/history/effect.go @@ -246,7 +246,7 @@ func (q *EffectsQ) Select(ctx context.Context, dest interface{}) error { // QEffects defines history_effects related queries. type QEffects interface { QCreateAccountsHistory - NewEffectBatchInsertBuilder(maxBatchSize int) EffectBatchInsertBuilder + NewEffectBatchInsertBuilder() EffectBatchInsertBuilder } var selectEffect = sq.Select("heff.*, hacc.address"). diff --git a/services/horizon/internal/db2/history/effect_batch_insert_builder.go b/services/horizon/internal/db2/history/effect_batch_insert_builder.go index 8b2522cf9e..e4ae333cb2 100644 --- a/services/horizon/internal/db2/history/effect_batch_insert_builder.go +++ b/services/horizon/internal/db2/history/effect_batch_insert_builder.go @@ -4,6 +4,7 @@ import ( "context" "github.com/guregu/null" + "github.com/stellar/go/support/db" ) @@ -11,52 +12,49 @@ import ( // history_effects table type EffectBatchInsertBuilder interface { Add( - ctx context.Context, - accountID int64, + accountID FutureAccountID, muxedAccount null.String, operationID int64, order uint32, effectType EffectType, details []byte, ) error - Exec(ctx context.Context) error + Exec(ctx context.Context, session db.SessionInterface) error } // effectBatchInsertBuilder is a simple wrapper around db.BatchInsertBuilder type effectBatchInsertBuilder struct { - builder db.BatchInsertBuilder + table string + builder db.FastBatchInsertBuilder } // NewEffectBatchInsertBuilder constructs a new EffectBatchInsertBuilder instance -func (q *Q) NewEffectBatchInsertBuilder(maxBatchSize int) EffectBatchInsertBuilder { +func (q *Q) NewEffectBatchInsertBuilder() EffectBatchInsertBuilder { return &effectBatchInsertBuilder{ - builder: db.BatchInsertBuilder{ - Table: q.GetTable("history_effects"), - MaxBatchSize: maxBatchSize, - }, + table: "history_effects", + builder: db.FastBatchInsertBuilder{}, } } // Add adds a effect to the batch func (i *effectBatchInsertBuilder) Add( - ctx context.Context, - accountID int64, + accountID FutureAccountID, muxedAccount null.String, operationID int64, order uint32, effectType EffectType, details []byte, ) error { - return i.builder.Row(ctx, map[string]interface{}{ + return i.builder.Row(map[string]interface{}{ "history_account_id": accountID, "address_muxed": muxedAccount, "history_operation_id": operationID, - "\"order\"": order, + "order": order, "type": effectType, - "details": details, + "details": string(details), }) } -func (i *effectBatchInsertBuilder) Exec(ctx context.Context) error { - return i.builder.Exec(ctx) +func (i *effectBatchInsertBuilder) Exec(ctx context.Context, session db.SessionInterface) error { + return i.builder.Exec(ctx, session, i.table) } diff --git a/services/horizon/internal/db2/history/effect_batch_insert_builder_test.go b/services/horizon/internal/db2/history/effect_batch_insert_builder_test.go index bd57eb4414..dc02148a7d 100644 --- a/services/horizon/internal/db2/history/effect_batch_insert_builder_test.go +++ b/services/horizon/internal/db2/history/effect_batch_insert_builder_test.go @@ -5,6 +5,7 @@ import ( "testing" "github.com/guregu/null" + "github.com/stellar/go/services/horizon/internal/test" "github.com/stellar/go/toid" ) @@ -14,21 +15,21 @@ func TestAddEffect(t *testing.T) { defer tt.Finish() test.ResetHorizonDB(t, tt.HorizonDB) q := &Q{tt.HorizonSession()} + tt.Assert.NoError(q.Begin(tt.Ctx)) address := "GAQAA5L65LSYH7CQ3VTJ7F3HHLGCL3DSLAR2Y47263D56MNNGHSQSTVY" muxedAddres := "MAQAA5L65LSYH7CQ3VTJ7F3HHLGCL3DSLAR2Y47263D56MNNGHSQSAAAAAAAAAAE2LP26" - accounIDs, err := q.CreateAccounts(tt.Ctx, []string{address}, 1) - tt.Assert.NoError(err) + accountLoader := NewAccountLoader() - builder := q.NewEffectBatchInsertBuilder(2) + builder := q.NewEffectBatchInsertBuilder() sequence := int32(56) details, err := json.Marshal(map[string]string{ "amount": "1000.0000000", "asset_type": "native", }) - err = builder.Add(tt.Ctx, - accounIDs[address], + err = builder.Add( + accountLoader.GetFuture(address), null.StringFrom(muxedAddres), toid.New(sequence, 1, 1).ToInt64(), 1, @@ -37,8 +38,9 @@ func TestAddEffect(t *testing.T) { ) tt.Assert.NoError(err) - err = builder.Exec(tt.Ctx) - tt.Assert.NoError(err) + tt.Assert.NoError(accountLoader.Exec(tt.Ctx, q)) + tt.Assert.NoError(builder.Exec(tt.Ctx, q)) + tt.Assert.NoError(q.Commit()) effects := []Effect{} tt.Assert.NoError(q.Effects().Select(tt.Ctx, &effects)) diff --git a/services/horizon/internal/db2/history/effect_test.go b/services/horizon/internal/db2/history/effect_test.go index 6430049ab4..498d5e92df 100644 --- a/services/horizon/internal/db2/history/effect_test.go +++ b/services/horizon/internal/db2/history/effect_test.go @@ -6,6 +6,7 @@ import ( "testing" "github.com/guregu/null" + "github.com/stellar/go/protocols/horizon/effects" "github.com/stellar/go/services/horizon/internal/db2" "github.com/stellar/go/services/horizon/internal/test" @@ -17,45 +18,43 @@ func TestEffectsForLiquidityPool(t *testing.T) { defer tt.Finish() test.ResetHorizonDB(t, tt.HorizonDB) q := &Q{tt.HorizonSession()} + tt.Assert.NoError(q.Begin(tt.Ctx)) // Insert Effect address := "GAQAA5L65LSYH7CQ3VTJ7F3HHLGCL3DSLAR2Y47263D56MNNGHSQSTVY" muxedAddres := "MAQAA5L65LSYH7CQ3VTJ7F3HHLGCL3DSLAR2Y47263D56MNNGHSQSAAAAAAAAAAE2LP26" - accountIDs, err := q.CreateAccounts(tt.Ctx, []string{address}, 1) - tt.Assert.NoError(err) + accountLoader := NewAccountLoader() - builder := q.NewEffectBatchInsertBuilder(2) + builder := q.NewEffectBatchInsertBuilder() sequence := int32(56) details, err := json.Marshal(map[string]string{ "amount": "1000.0000000", "asset_type": "native", }) + tt.Assert.NoError(err) opID := toid.New(sequence, 1, 1).ToInt64() - err = builder.Add(tt.Ctx, - accountIDs[address], + tt.Assert.NoError(builder.Add( + accountLoader.GetFuture(address), null.StringFrom(muxedAddres), opID, 1, 3, details, - ) - tt.Assert.NoError(err) + )) - err = builder.Exec(tt.Ctx) - tt.Assert.NoError(err) + tt.Assert.NoError(accountLoader.Exec(tt.Ctx, q)) + tt.Assert.NoError(builder.Exec(tt.Ctx, q)) // Insert Liquidity Pool history liquidityPoolID := "abcde" - toInternalID, err := q.CreateHistoryLiquidityPools(tt.Ctx, []string{liquidityPoolID}, 2) - tt.Assert.NoError(err) - operationBuilder := q.NewOperationLiquidityPoolBatchInsertBuilder(2) - tt.Assert.NoError(err) - internalID, ok := toInternalID[liquidityPoolID] - tt.Assert.True(ok) - err = operationBuilder.Add(tt.Ctx, opID, internalID) - tt.Assert.NoError(err) - err = operationBuilder.Exec(tt.Ctx) - tt.Assert.NoError(err) + lpLoader := NewLiquidityPoolLoader() + + operationBuilder := q.NewOperationLiquidityPoolBatchInsertBuilder() + tt.Assert.NoError(operationBuilder.Add(opID, lpLoader.GetFuture(liquidityPoolID))) + tt.Assert.NoError(lpLoader.Exec(tt.Ctx, q)) + tt.Assert.NoError(operationBuilder.Exec(tt.Ctx, q)) + + tt.Assert.NoError(q.Commit()) var result []Effect err = q.Effects().ForLiquidityPool(tt.Ctx, db2.PageQuery{ @@ -75,13 +74,13 @@ func TestEffectsForTrustlinesSponsorshipEmptyAssetType(t *testing.T) { defer tt.Finish() test.ResetHorizonDB(t, tt.HorizonDB) q := &Q{tt.HorizonSession()} + tt.Assert.NoError(q.Begin(tt.Ctx)) address := "GAQAA5L65LSYH7CQ3VTJ7F3HHLGCL3DSLAR2Y47263D56MNNGHSQSTVY" muxedAddres := "MAQAA5L65LSYH7CQ3VTJ7F3HHLGCL3DSLAR2Y47263D56MNNGHSQSAAAAAAAAAAE2LP26" - accountIDs, err := q.CreateAccounts(tt.Ctx, []string{address}, 1) - tt.Assert.NoError(err) + accountLoader := NewAccountLoader() - builder := q.NewEffectBatchInsertBuilder(1) + builder := q.NewEffectBatchInsertBuilder() sequence := int32(56) tests := []struct { effectType EffectType @@ -141,26 +140,24 @@ func TestEffectsForTrustlinesSponsorshipEmptyAssetType(t *testing.T) { for i, test := range tests { var bytes []byte - bytes, err = json.Marshal(test.details) + bytes, err := json.Marshal(test.details) tt.Require.NoError(err) - err = builder.Add(tt.Ctx, - accountIDs[address], + tt.Require.NoError(builder.Add( + accountLoader.GetFuture(address), null.StringFrom(muxedAddres), opID, uint32(i), test.effectType, bytes, - ) - tt.Require.NoError(err) + )) } - - err = builder.Exec(tt.Ctx) - tt.Require.NoError(err) + tt.Require.NoError(accountLoader.Exec(tt.Ctx, q)) + tt.Require.NoError(builder.Exec(tt.Ctx, q)) + tt.Assert.NoError(q.Commit()) var results []Effect - err = q.Effects().Select(tt.Ctx, &results) - tt.Require.NoError(err) + tt.Require.NoError(q.Effects().Select(tt.Ctx, &results)) tt.Require.Len(results, len(tests)) for i, test := range tests { diff --git a/services/horizon/internal/db2/history/fee_bump_scenario.go b/services/horizon/internal/db2/history/fee_bump_scenario.go index 7263e7aeb2..da6563c732 100644 --- a/services/horizon/internal/db2/history/fee_bump_scenario.go +++ b/services/horizon/internal/db2/history/fee_bump_scenario.go @@ -10,12 +10,13 @@ import ( sq "github.com/Masterminds/squirrel" "github.com/guregu/null" + "github.com/stretchr/testify/assert" + "github.com/stellar/go/ingest" "github.com/stellar/go/network" "github.com/stellar/go/services/horizon/internal/test" "github.com/stellar/go/toid" "github.com/stellar/go/xdr" - "github.com/stretchr/testify/assert" ) func ledgerToMap(ledger Ledger) map[string]interface{} { @@ -247,29 +248,31 @@ func FeeBumpScenario(tt *test.T, q *Q, successful bool) FeeBumpFixture { hash: "edba3051b2f2d9b713e8a08709d631eccb72c59864ff3c564c68792271bb24a7", }) ctx := context.Background() - insertBuilder := q.NewTransactionBatchInsertBuilder(2) - prefilterInsertBuilder := q.NewTransactionFilteredTmpBatchInsertBuilder(2) + tt.Assert.NoError(q.Begin(ctx)) + + insertBuilder := q.NewTransactionBatchInsertBuilder() + prefilterInsertBuilder := q.NewTransactionFilteredTmpBatchInsertBuilder() // include both fee bump and normal transaction in the same batch // to make sure both kinds of transactions can be inserted using a single exec statement - tt.Assert.NoError(insertBuilder.Add(ctx, feeBumpTransaction, sequence)) - tt.Assert.NoError(insertBuilder.Add(ctx, normalTransaction, sequence)) - tt.Assert.NoError(insertBuilder.Exec(ctx)) + tt.Assert.NoError(insertBuilder.Add(feeBumpTransaction, sequence)) + tt.Assert.NoError(insertBuilder.Add(normalTransaction, sequence)) + tt.Assert.NoError(insertBuilder.Exec(ctx, q)) - tt.Assert.NoError(prefilterInsertBuilder.Add(ctx, feeBumpTransaction, sequence)) - tt.Assert.NoError(prefilterInsertBuilder.Add(ctx, normalTransaction, sequence)) - tt.Assert.NoError(prefilterInsertBuilder.Exec(ctx)) + tt.Assert.NoError(prefilterInsertBuilder.Add(feeBumpTransaction, sequence)) + tt.Assert.NoError(prefilterInsertBuilder.Add(normalTransaction, sequence)) + tt.Assert.NoError(prefilterInsertBuilder.Exec(ctx, q)) account := fixture.Envelope.SourceAccount().ToAccountId() feeBumpAccount := fixture.Envelope.FeeBumpAccount().ToAccountId() - opBuilder := q.NewOperationBatchInsertBuilder(1) + opBuilder := q.NewOperationBatchInsertBuilder() details, err := json.Marshal(map[string]string{ "bump_to": "98", }) + tt.Assert.NoError(err) tt.Assert.NoError(opBuilder.Add( - ctx, toid.New(fixture.Ledger.Sequence, 1, 1).ToInt64(), toid.New(fixture.Ledger.Sequence, 1, 0).ToInt64(), 1, @@ -277,27 +280,30 @@ func FeeBumpScenario(tt *test.T, q *Q, successful bool) FeeBumpFixture { details, account.Address(), null.String{}, + false, )) - tt.Assert.NoError(opBuilder.Exec(ctx)) + tt.Assert.NoError(opBuilder.Exec(ctx, q)) - effectBuilder := q.NewEffectBatchInsertBuilder(2) + effectBuilder := q.NewEffectBatchInsertBuilder() details, err = json.Marshal(map[string]interface{}{"new_seq": 98}) tt.Assert.NoError(err) - accounIDs, err := q.CreateAccounts(ctx, []string{account.Address()}, 1) - tt.Assert.NoError(err) + accountLoader := NewAccountLoader() err = effectBuilder.Add( - ctx, - accounIDs[account.Address()], + accountLoader.GetFuture(account.Address()), null.String{}, toid.New(fixture.Ledger.Sequence, 1, 1).ToInt64(), 1, EffectSequenceBumped, details, ) + tt.Assert.NoError(err) - tt.Assert.NoError(effectBuilder.Exec(ctx)) + tt.Assert.NoError(accountLoader.Exec(ctx, q.SessionInterface)) + tt.Assert.NoError(effectBuilder.Exec(ctx, q.SessionInterface)) + + tt.Assert.NoError(q.Commit()) fixture.Transaction = Transaction{ TransactionWithoutLedger: TransactionWithoutLedger{ diff --git a/services/horizon/internal/db2/history/history_claimable_balances.go b/services/horizon/internal/db2/history/history_claimable_balances.go index b67294f4a6..5d2076f3fd 100644 --- a/services/horizon/internal/db2/history/history_claimable_balances.go +++ b/services/horizon/internal/db2/history/history_claimable_balances.go @@ -13,8 +13,8 @@ import ( // QHistoryClaimableBalances defines account related queries. type QHistoryClaimableBalances interface { CreateHistoryClaimableBalances(ctx context.Context, ids []string, batchSize int) (map[string]int64, error) - NewOperationClaimableBalanceBatchInsertBuilder(maxBatchSize int) OperationClaimableBalanceBatchInsertBuilder - NewTransactionClaimableBalanceBatchInsertBuilder(maxBatchSize int) TransactionClaimableBalanceBatchInsertBuilder + NewOperationClaimableBalanceBatchInsertBuilder() OperationClaimableBalanceBatchInsertBuilder + NewTransactionClaimableBalanceBatchInsertBuilder() TransactionClaimableBalanceBatchInsertBuilder } // CreateHistoryClaimableBalances creates rows in the history_claimable_balances table for a given list of ids. @@ -92,63 +92,61 @@ func (q *Q) ClaimableBalanceByID(ctx context.Context, id string) (dest HistoryCl } type OperationClaimableBalanceBatchInsertBuilder interface { - Add(ctx context.Context, operationID, internalID int64) error - Exec(ctx context.Context) error + Add(operationID int64, claimableBalance FutureClaimableBalanceID) error + Exec(ctx context.Context, session db.SessionInterface) error } type operationClaimableBalanceBatchInsertBuilder struct { - builder db.BatchInsertBuilder + table string + builder db.FastBatchInsertBuilder } -func (q *Q) NewOperationClaimableBalanceBatchInsertBuilder(maxBatchSize int) OperationClaimableBalanceBatchInsertBuilder { +func (q *Q) NewOperationClaimableBalanceBatchInsertBuilder() OperationClaimableBalanceBatchInsertBuilder { return &operationClaimableBalanceBatchInsertBuilder{ - builder: db.BatchInsertBuilder{ - Table: q.GetTable("history_operation_claimable_balances"), - MaxBatchSize: maxBatchSize, - }, + table: "history_operation_claimable_balances", + builder: db.FastBatchInsertBuilder{}, } } // Add adds a new operation claimable balance to the batch -func (i *operationClaimableBalanceBatchInsertBuilder) Add(ctx context.Context, operationID, internalID int64) error { - return i.builder.Row(ctx, map[string]interface{}{ +func (i *operationClaimableBalanceBatchInsertBuilder) Add(operationID int64, claimableBalance FutureClaimableBalanceID) error { + return i.builder.Row(map[string]interface{}{ "history_operation_id": operationID, - "history_claimable_balance_id": internalID, + "history_claimable_balance_id": claimableBalance, }) } // Exec flushes all pending operation claimable balances to the db -func (i *operationClaimableBalanceBatchInsertBuilder) Exec(ctx context.Context) error { - return i.builder.Exec(ctx) +func (i *operationClaimableBalanceBatchInsertBuilder) Exec(ctx context.Context, session db.SessionInterface) error { + return i.builder.Exec(ctx, session, i.table) } type TransactionClaimableBalanceBatchInsertBuilder interface { - Add(ctx context.Context, transactionID, internalID int64) error - Exec(ctx context.Context) error + Add(transactionID int64, claimableBalance FutureClaimableBalanceID) error + Exec(ctx context.Context, session db.SessionInterface) error } type transactionClaimableBalanceBatchInsertBuilder struct { - builder db.BatchInsertBuilder + table string + builder db.FastBatchInsertBuilder } -func (q *Q) NewTransactionClaimableBalanceBatchInsertBuilder(maxBatchSize int) TransactionClaimableBalanceBatchInsertBuilder { +func (q *Q) NewTransactionClaimableBalanceBatchInsertBuilder() TransactionClaimableBalanceBatchInsertBuilder { return &transactionClaimableBalanceBatchInsertBuilder{ - builder: db.BatchInsertBuilder{ - Table: q.GetTable("history_transaction_claimable_balances"), - MaxBatchSize: maxBatchSize, - }, + table: "history_transaction_claimable_balances", + builder: db.FastBatchInsertBuilder{}, } } // Add adds a new transaction claimable balance to the batch -func (i *transactionClaimableBalanceBatchInsertBuilder) Add(ctx context.Context, transactionID, internalID int64) error { - return i.builder.Row(ctx, map[string]interface{}{ +func (i *transactionClaimableBalanceBatchInsertBuilder) Add(transactionID int64, claimableBalance FutureClaimableBalanceID) error { + return i.builder.Row(map[string]interface{}{ "history_transaction_id": transactionID, - "history_claimable_balance_id": internalID, + "history_claimable_balance_id": claimableBalance, }) } // Exec flushes all pending transaction claimable balances to the db -func (i *transactionClaimableBalanceBatchInsertBuilder) Exec(ctx context.Context) error { - return i.builder.Exec(ctx) +func (i *transactionClaimableBalanceBatchInsertBuilder) Exec(ctx context.Context, session db.SessionInterface) error { + return i.builder.Exec(ctx, session, i.table) } diff --git a/services/horizon/internal/db2/history/history_liquidity_pools.go b/services/horizon/internal/db2/history/history_liquidity_pools.go index 0601d91be7..bb13ac59f9 100644 --- a/services/horizon/internal/db2/history/history_liquidity_pools.go +++ b/services/horizon/internal/db2/history/history_liquidity_pools.go @@ -5,6 +5,7 @@ import ( "sort" sq "github.com/Masterminds/squirrel" + "github.com/stellar/go/support/db" "github.com/stellar/go/support/errors" ) @@ -12,8 +13,8 @@ import ( // QHistoryLiquidityPools defines account related queries. type QHistoryLiquidityPools interface { CreateHistoryLiquidityPools(ctx context.Context, poolIDs []string, batchSize int) (map[string]int64, error) - NewOperationLiquidityPoolBatchInsertBuilder(maxBatchSize int) OperationLiquidityPoolBatchInsertBuilder - NewTransactionLiquidityPoolBatchInsertBuilder(maxBatchSize int) TransactionLiquidityPoolBatchInsertBuilder + NewOperationLiquidityPoolBatchInsertBuilder() OperationLiquidityPoolBatchInsertBuilder + NewTransactionLiquidityPoolBatchInsertBuilder() TransactionLiquidityPoolBatchInsertBuilder } // CreateHistoryLiquidityPools creates rows in the history_liquidity_pools table for a given list of ids. @@ -101,63 +102,61 @@ func (q *Q) LiquidityPoolByID(ctx context.Context, poolID string) (dest HistoryL } type OperationLiquidityPoolBatchInsertBuilder interface { - Add(ctx context.Context, operationID, internalID int64) error - Exec(ctx context.Context) error + Add(operationID int64, lp FutureLiquidityPoolID) error + Exec(ctx context.Context, session db.SessionInterface) error } type operationLiquidityPoolBatchInsertBuilder struct { - builder db.BatchInsertBuilder + table string + builder db.FastBatchInsertBuilder } -func (q *Q) NewOperationLiquidityPoolBatchInsertBuilder(maxBatchSize int) OperationLiquidityPoolBatchInsertBuilder { +func (q *Q) NewOperationLiquidityPoolBatchInsertBuilder() OperationLiquidityPoolBatchInsertBuilder { return &operationLiquidityPoolBatchInsertBuilder{ - builder: db.BatchInsertBuilder{ - Table: q.GetTable("history_operation_liquidity_pools"), - MaxBatchSize: maxBatchSize, - }, + table: "history_operation_liquidity_pools", + builder: db.FastBatchInsertBuilder{}, } } // Add adds a new operation claimable balance to the batch -func (i *operationLiquidityPoolBatchInsertBuilder) Add(ctx context.Context, operationID, internalID int64) error { - return i.builder.Row(ctx, map[string]interface{}{ +func (i *operationLiquidityPoolBatchInsertBuilder) Add(operationID int64, lp FutureLiquidityPoolID) error { + return i.builder.Row(map[string]interface{}{ "history_operation_id": operationID, - "history_liquidity_pool_id": internalID, + "history_liquidity_pool_id": lp, }) } // Exec flushes all pending operation claimable balances to the db -func (i *operationLiquidityPoolBatchInsertBuilder) Exec(ctx context.Context) error { - return i.builder.Exec(ctx) +func (i *operationLiquidityPoolBatchInsertBuilder) Exec(ctx context.Context, session db.SessionInterface) error { + return i.builder.Exec(ctx, session, i.table) } type TransactionLiquidityPoolBatchInsertBuilder interface { - Add(ctx context.Context, transactionID, internalID int64) error - Exec(ctx context.Context) error + Add(transactionID int64, lp FutureLiquidityPoolID) error + Exec(ctx context.Context, session db.SessionInterface) error } type transactionLiquidityPoolBatchInsertBuilder struct { - builder db.BatchInsertBuilder + table string + builder db.FastBatchInsertBuilder } -func (q *Q) NewTransactionLiquidityPoolBatchInsertBuilder(maxBatchSize int) TransactionLiquidityPoolBatchInsertBuilder { +func (q *Q) NewTransactionLiquidityPoolBatchInsertBuilder() TransactionLiquidityPoolBatchInsertBuilder { return &transactionLiquidityPoolBatchInsertBuilder{ - builder: db.BatchInsertBuilder{ - Table: q.GetTable("history_transaction_liquidity_pools"), - MaxBatchSize: maxBatchSize, - }, + table: "history_transaction_liquidity_pools", + builder: db.FastBatchInsertBuilder{}, } } // Add adds a new transaction claimable balance to the batch -func (i *transactionLiquidityPoolBatchInsertBuilder) Add(ctx context.Context, transactionID, internalID int64) error { - return i.builder.Row(ctx, map[string]interface{}{ +func (i *transactionLiquidityPoolBatchInsertBuilder) Add(transactionID int64, lp FutureLiquidityPoolID) error { + return i.builder.Row(map[string]interface{}{ "history_transaction_id": transactionID, - "history_liquidity_pool_id": internalID, + "history_liquidity_pool_id": lp, }) } // Exec flushes all pending transaction claimable balances to the db -func (i *transactionLiquidityPoolBatchInsertBuilder) Exec(ctx context.Context) error { - return i.builder.Exec(ctx) +func (i *transactionLiquidityPoolBatchInsertBuilder) Exec(ctx context.Context, session db.SessionInterface) error { + return i.builder.Exec(ctx, session, i.table) } diff --git a/services/horizon/internal/db2/history/ingestion.go b/services/horizon/internal/db2/history/ingestion.go index 518dfd86c4..d82188d83e 100644 --- a/services/horizon/internal/db2/history/ingestion.go +++ b/services/horizon/internal/db2/history/ingestion.go @@ -15,6 +15,7 @@ func (q *Q) TruncateIngestStateTables(ctx context.Context) error { "accounts_data", "accounts_signers", "claimable_balances", + "claimable_balance_claimants", "exp_asset_stats", "liquidity_pools", "offers", diff --git a/services/horizon/internal/db2/history/key_value.go b/services/horizon/internal/db2/history/key_value.go index c41fec77d9..a2a170a4b1 100644 --- a/services/horizon/internal/db2/history/key_value.go +++ b/services/horizon/internal/db2/history/key_value.go @@ -45,7 +45,7 @@ func (q *Q) GetLastLedgerIngestNonBlocking(ctx context.Context) (uint32, error) // GetLastLedgerIngest returns the last ledger ingested by ingest system // in Horizon. Returns ErrKeyNotFound error if no value has been previously set. // This is using `SELECT ... FOR UPDATE` what means it's blocking the row for all other -// transactions.This behaviour is critical in distributed ingestion so do not change +// transactions.This behavior is critical in distributed ingestion so do not change // it unless you know what you are doing. // The value can be set using UpdateLastLedgerIngest. func (q *Q) GetLastLedgerIngest(ctx context.Context) (uint32, error) { diff --git a/services/horizon/internal/db2/history/ledger.go b/services/horizon/internal/db2/history/ledger.go index 7d367a8464..ca89534702 100644 --- a/services/horizon/internal/db2/history/ledger.go +++ b/services/horizon/internal/db2/history/ledger.go @@ -10,6 +10,7 @@ import ( sq "github.com/Masterminds/squirrel" "github.com/guregu/null" "github.com/stellar/go/services/horizon/internal/db2" + "github.com/stellar/go/support/db" "github.com/stellar/go/support/errors" "github.com/stellar/go/support/ordered" "github.com/stellar/go/toid" @@ -90,27 +91,46 @@ func (q *LedgersQ) Select(ctx context.Context, dest interface{}) error { // QLedgers defines ingestion ledger related queries. type QLedgers interface { - InsertLedger( - ctx context.Context, + NewLedgerBatchInsertBuilder() LedgerBatchInsertBuilder +} + +// LedgerBatchInsertBuilder is used to insert ledgers into the +// history_ledgers table +type LedgerBatchInsertBuilder interface { + Add( ledger xdr.LedgerHeaderHistoryEntry, successTxsCount int, failedTxsCount int, opCount int, txSetOpCount int, ingestVersion int, - ) (int64, error) + ) error + Exec(ctx context.Context, session db.SessionInterface) error +} + +// ledgerBatchInsertBuilder is a simple wrapper around db.BatchInsertBuilder +type ledgerBatchInsertBuilder struct { + builder db.FastBatchInsertBuilder + table string +} + +// NewLedgerBatchInsertBuilder constructs a new EffectBatchInsertBuilder instance +func (q *Q) NewLedgerBatchInsertBuilder() LedgerBatchInsertBuilder { + return &ledgerBatchInsertBuilder{ + table: "history_ledgers", + builder: db.FastBatchInsertBuilder{}, + } } -// InsertLedger creates a row in the history_ledgers table. -// Returns number of rows affected and error. -func (q *Q) InsertLedger(ctx context.Context, +// Add adds a effect to the batch +func (i *ledgerBatchInsertBuilder) Add( ledger xdr.LedgerHeaderHistoryEntry, successTxsCount int, failedTxsCount int, opCount int, txSetOpCount int, ingestVersion int, -) (int64, error) { +) error { m, err := ledgerHeaderToMap( ledger, successTxsCount, @@ -120,16 +140,14 @@ func (q *Q) InsertLedger(ctx context.Context, ingestVersion, ) if err != nil { - return 0, err + return err } - sql := sq.Insert("history_ledgers").SetMap(m) - result, err := q.Exec(ctx, sql) - if err != nil { - return 0, err - } + return i.builder.Row(m) +} - return result.RowsAffected() +func (i *ledgerBatchInsertBuilder) Exec(ctx context.Context, session db.SessionInterface) error { + return i.builder.Exec(ctx, session, i.table) } // GetLedgerGaps obtains ingestion gaps in the history_ledgers table. diff --git a/services/horizon/internal/db2/history/ledger_test.go b/services/horizon/internal/db2/history/ledger_test.go index 4bf6d7b058..4fe9125fbe 100644 --- a/services/horizon/internal/db2/history/ledger_test.go +++ b/services/horizon/internal/db2/history/ledger_test.go @@ -119,7 +119,8 @@ func TestInsertLedger(t *testing.T) { tt.Assert.NoError(err) expectedLedger.LedgerHeaderXDR = null.NewString(ledgerHeaderBase64, true) - rowsAffected, err := q.InsertLedger(tt.Ctx, + ledgerBatch := q.NewLedgerBatchInsertBuilder() + err = ledgerBatch.Add( ledgerEntry, 12, 3, @@ -128,7 +129,9 @@ func TestInsertLedger(t *testing.T) { int(expectedLedger.ImporterVersion), ) tt.Assert.NoError(err) - tt.Assert.Equal(rowsAffected, int64(1)) + tt.Assert.NoError(q.Begin(tt.Ctx)) + tt.Assert.NoError(ledgerBatch.Exec(tt.Ctx, q.SessionInterface)) + tt.Assert.NoError(q.Commit()) err = q.LedgerBySequence(tt.Ctx, &ledgerFromDB, 69859) tt.Assert.NoError(err) @@ -204,7 +207,8 @@ func insertLedgerWithSequence(tt *test.T, q *Q, seq uint32) { ledgerHeaderBase64, err := xdr.MarshalBase64(ledgerEntry.Header) tt.Assert.NoError(err) expectedLedger.LedgerHeaderXDR = null.NewString(ledgerHeaderBase64, true) - rowsAffected, err := q.InsertLedger(tt.Ctx, + ledgerBatch := q.NewLedgerBatchInsertBuilder() + err = ledgerBatch.Add( ledgerEntry, 12, 3, @@ -213,7 +217,9 @@ func insertLedgerWithSequence(tt *test.T, q *Q, seq uint32) { int(expectedLedger.ImporterVersion), ) tt.Assert.NoError(err) - tt.Assert.Equal(rowsAffected, int64(1)) + tt.Assert.NoError(q.Begin(tt.Ctx)) + tt.Assert.NoError(ledgerBatch.Exec(tt.Ctx, q.SessionInterface)) + tt.Assert.NoError(q.Commit()) } func TestGetLedgerGaps(t *testing.T) { diff --git a/services/horizon/internal/db2/history/liquidity_pool_loader.go b/services/horizon/internal/db2/history/liquidity_pool_loader.go new file mode 100644 index 0000000000..cf89ae67b4 --- /dev/null +++ b/services/horizon/internal/db2/history/liquidity_pool_loader.go @@ -0,0 +1,165 @@ +package history + +import ( + "context" + "database/sql/driver" + "fmt" + "sort" + + "github.com/stellar/go/support/collections/set" + "github.com/stellar/go/support/db" + "github.com/stellar/go/support/errors" + "github.com/stellar/go/support/ordered" +) + +// FutureLiquidityPoolID represents a future history liquidity pool. +// A FutureLiquidityPoolID is created by an LiquidityPoolLoader and +// the liquidity pool id is available after calling Exec() on +// the LiquidityPoolLoader. +type FutureLiquidityPoolID struct { + id string + loader *LiquidityPoolLoader +} + +// Value implements the database/sql/driver Valuer interface. +func (a FutureLiquidityPoolID) Value() (driver.Value, error) { + return a.loader.GetNow(a.id) +} + +// LiquidityPoolLoader will map liquidity pools to their internal +// history ids. If there is no existing mapping for a given liquidity pool, +// the LiquidityPoolLoader will insert into the history_liquidity_pools table to +// establish a mapping. +type LiquidityPoolLoader struct { + sealed bool + set set.Set[string] + ids map[string]int64 +} + +// NewLiquidityPoolLoader will construct a new LiquidityPoolLoader instance. +func NewLiquidityPoolLoader() *LiquidityPoolLoader { + return &LiquidityPoolLoader{ + sealed: false, + set: set.Set[string]{}, + ids: map[string]int64{}, + } +} + +// GetFuture registers the given liquidity pool into the loader and +// returns a FutureLiquidityPoolID which will hold the internal history id for +// the liquidity pool after Exec() is called. +func (a *LiquidityPoolLoader) GetFuture(id string) FutureLiquidityPoolID { + if a.sealed { + panic(errSealed) + } + + a.set.Add(id) + return FutureLiquidityPoolID{ + id: id, + loader: a, + } +} + +// GetNow returns the internal history id for the given liquidity pool. +// GetNow should only be called on values which were registered by +// GetFuture() calls. Also, Exec() must be called before any GetNow +// call can succeed. +func (a *LiquidityPoolLoader) GetNow(id string) (int64, error) { + if !a.sealed { + return 0, fmt.Errorf(`invalid liquidity pool loader state, + Exec was not called yet to properly seal and resolve %v id`, id) + } + if internalID, ok := a.ids[id]; !ok { + return 0, fmt.Errorf(`liquidity pool loader id %q was not found`, id) + } else { + return internalID, nil + } +} + +func (a *LiquidityPoolLoader) lookupKeys(ctx context.Context, q *Q, ids []string) error { + for i := 0; i < len(ids); i += loaderLookupBatchSize { + end := ordered.Min(len(ids), i+loaderLookupBatchSize) + + lps, err := q.LiquidityPoolsByIDs(ctx, ids[i:end]) + if err != nil { + return errors.Wrap(err, "could not select accounts") + } + + for _, lp := range lps { + a.ids[lp.PoolID] = lp.InternalID + } + } + return nil +} + +// Exec will look up all the internal history ids for the liquidity pools registered in the loader. +// If there are no internal history ids for a given set of liquidity pools, Exec will insert rows +// into the history_liquidity_pools table. +func (a *LiquidityPoolLoader) Exec(ctx context.Context, session db.SessionInterface) error { + a.sealed = true + if len(a.set) == 0 { + return nil + } + q := &Q{session} + ids := make([]string, 0, len(a.set)) + for id := range a.set { + ids = append(ids, id) + } + + if err := a.lookupKeys(ctx, q, ids); err != nil { + return err + } + + insert := 0 + for _, id := range ids { + if _, ok := a.ids[id]; ok { + continue + } + ids[insert] = id + insert++ + } + if insert == 0 { + return nil + } + ids = ids[:insert] + // sort entries before inserting rows to prevent deadlocks on acquiring a ShareLock + // https://github.com/stellar/go/issues/2370 + sort.Strings(ids) + + err := bulkInsert( + ctx, + q, + "history_liquidity_pools", + []string{"liquidity_pool_id"}, + []bulkInsertField{ + { + name: "liquidity_pool_id", + dbType: "text", + objects: ids, + }, + }, + ) + if err != nil { + return err + } + + return a.lookupKeys(ctx, q, ids) +} + +// LiquidityPoolLoaderStub is a stub wrapper around LiquidityPoolLoader which allows +// you to manually configure the mapping of liquidity pools to history liquidity ppol ids +type LiquidityPoolLoaderStub struct { + Loader *LiquidityPoolLoader +} + +// NewLiquidityPoolLoaderStub returns a new LiquidityPoolLoader instance +func NewLiquidityPoolLoaderStub() LiquidityPoolLoaderStub { + return LiquidityPoolLoaderStub{Loader: NewLiquidityPoolLoader()} +} + +// Insert updates the wrapped LiquidityPoolLoader so that the given liquidity pool +// is mapped to the provided history liquidity pool id +func (a LiquidityPoolLoaderStub) Insert(lp string, id int64) { + a.Loader.sealed = true + a.Loader.ids[lp] = id +} diff --git a/services/horizon/internal/db2/history/liquidity_pool_loader_test.go b/services/horizon/internal/db2/history/liquidity_pool_loader_test.go new file mode 100644 index 0000000000..6e5b4addf7 --- /dev/null +++ b/services/horizon/internal/db2/history/liquidity_pool_loader_test.go @@ -0,0 +1,55 @@ +package history + +import ( + "context" + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/stellar/go/services/horizon/internal/test" + "github.com/stellar/go/xdr" +) + +func TestLiquidityPoolLoader(t *testing.T) { + tt := test.Start(t) + defer tt.Finish() + test.ResetHorizonDB(t, tt.HorizonDB) + session := tt.HorizonSession() + + var ids []string + for i := 0; i < 100; i++ { + poolID := xdr.PoolId{byte(i)} + id, err := xdr.MarshalHex(poolID) + tt.Assert.NoError(err) + ids = append(ids, id) + } + + loader := NewLiquidityPoolLoader() + for _, id := range ids { + future := loader.GetFuture(id) + _, err := future.Value() + assert.Error(t, err) + assert.Contains(t, err.Error(), `invalid liquidity pool loader state,`) + duplicateFuture := loader.GetFuture(id) + assert.Equal(t, future, duplicateFuture) + } + + assert.NoError(t, loader.Exec(context.Background(), session)) + assert.Panics(t, func() { + loader.GetFuture("not-present") + }) + + q := &Q{session} + for _, id := range ids { + internalID, err := loader.GetNow(id) + assert.NoError(t, err) + lp, err := q.LiquidityPoolByID(context.Background(), id) + assert.NoError(t, err) + assert.Equal(t, lp.PoolID, id) + assert.Equal(t, lp.InternalID, internalID) + } + + _, err := loader.GetNow("not present") + assert.Error(t, err) + assert.Contains(t, err.Error(), `was not found`) +} diff --git a/services/horizon/internal/db2/history/main.go b/services/horizon/internal/db2/history/main.go index 10eb423290..e3a8212731 100644 --- a/services/horizon/internal/db2/history/main.go +++ b/services/horizon/internal/db2/history/main.go @@ -3,6 +3,7 @@ package history import ( + "bytes" "context" "database/sql" "database/sql/driver" @@ -35,11 +36,20 @@ const ( // EffectAccountRemoved effects occur when one account is merged into another EffectAccountRemoved EffectType = 1 // from merge_account - // EffectAccountCredited effects occur when an account receives some currency - EffectAccountCredited EffectType = 2 // from create_account, payment, path_payment, merge_account + // EffectAccountCredited effects occur when an account receives some + // currency + // + // from create_account, payment, path_payment, merge_account, and SAC events + // involving transfers, mints, and burns. + EffectAccountCredited EffectType = 2 // EffectAccountDebited effects occur when an account sends some currency - EffectAccountDebited EffectType = 3 // from create_account, payment, path_payment, create_account + // + // from create_account, payment, path_payment, create_account, and SAC + // involving transfers, mints, and burns. + // + // https://github.com/stellar/rs-soroban-env/blob/5695440da452837555d8f7f259cc33341fdf07b0/soroban-env-host/src/native_contract/token/contract.rs#L51-L63 + EffectAccountDebited EffectType = 3 // EffectAccountThresholdsUpdated effects occur when an account changes its // multisig thresholds. @@ -208,6 +218,16 @@ const ( // EffectLiquidityPoolRevoked occurs when a liquidity pool is revoked EffectLiquidityPoolRevoked EffectType = 95 // from change_trust_line_flags and allow_trust + + // EffectContractCredited effects occur when a contract receives some + // currency from SAC events involving transfers, mints, and burns. + // https://github.com/stellar/rs-soroban-env/blob/5695440da452837555d8f7f259cc33341fdf07b0/soroban-env-host/src/native_contract/token/contract.rs#L51-L63 + EffectContractCredited EffectType = 96 + + // EffectContractDebited effects occur when a contract sends some currency + // from SAC events involving transfers, mints, and burns. + // https://github.com/stellar/rs-soroban-env/blob/5695440da452837555d8f7f259cc33341fdf07b0/soroban-env-host/src/native_contract/token/contract.rs#L51-L63 + EffectContractDebited EffectType = 97 ) // Account is a row of data from the `history_accounts` table @@ -255,11 +275,11 @@ type IngestionQ interface { // QParticipants // Copy the small interfaces with shared methods directly, otherwise error: // duplicate method CreateAccounts - NewTransactionParticipantsBatchInsertBuilder(maxBatchSize int) TransactionParticipantsBatchInsertBuilder - NewOperationParticipantBatchInsertBuilder(maxBatchSize int) OperationParticipantBatchInsertBuilder + NewTransactionParticipantsBatchInsertBuilder() TransactionParticipantsBatchInsertBuilder + NewOperationParticipantBatchInsertBuilder() OperationParticipantBatchInsertBuilder QSigners //QTrades - NewTradeBatchInsertBuilder(maxBatchSize int) TradeBatchInsertBuilder + NewTradeBatchInsertBuilder() TradeBatchInsertBuilder RebuildTradeAggregationTimes(ctx context.Context, from, to strtime.Millis, roundingSlippageFilter int) error RebuildTradeAggregationBuckets(ctx context.Context, fromLedger, toLedger uint32, roundingSlippageFilter int) error ReapLookupTables(ctx context.Context, offsets map[string]int64) (map[string]int64, map[string]int64, error) @@ -267,8 +287,8 @@ type IngestionQ interface { QTransactions QTrustLines - Begin() error - BeginTx(*sql.TxOptions) error + Begin(context.Context) error + BeginTx(context.Context, *sql.TxOptions) error Commit() error CloneIngestionQ() IngestionQ Close() error @@ -284,6 +304,7 @@ type IngestionQ interface { TruncateIngestStateTables(context.Context) error DeleteRangeAll(ctx context.Context, start, end int64) error DeleteTransactionsFilteredTmpOlderThan(ctx context.Context, howOldInSeconds uint64) (int64, error) + TryStateVerificationLock(ctx context.Context) (bool, error) } // QAccounts defines account related queries. @@ -291,6 +312,7 @@ type QAccounts interface { GetAccountsByIDs(ctx context.Context, ids []string) ([]AccountEntry, error) UpsertAccounts(ctx context.Context, accounts []AccountEntry) error RemoveAccounts(ctx context.Context, accountIDs []string) (int64, error) + NewAccountsBatchInsertBuilder() AccountsBatchInsertBuilder } // AccountSigner is a row of data from the `accounts_signers` table @@ -302,13 +324,15 @@ type AccountSigner struct { } type AccountSignersBatchInsertBuilder interface { - Add(ctx context.Context, signer AccountSigner) error + Add(signer AccountSigner) error Exec(ctx context.Context) error } // accountSignersBatchInsertBuilder is a simple wrapper around db.BatchInsertBuilder type accountSignersBatchInsertBuilder struct { - builder db.BatchInsertBuilder + builder db.FastBatchInsertBuilder + session db.SessionInterface + table string } // Data is a row of data from the `account_data` table @@ -333,6 +357,7 @@ type QData interface { GetAccountDataByKeys(ctx context.Context, keys []AccountDataKey) ([]Data, error) UpsertAccountData(ctx context.Context, data []Data) error RemoveAccountData(ctx context.Context, keys []AccountDataKey) (int64, error) + NewAccountDataBatchInsertBuilder() AccountDataBatchInsertBuilder } // Asset is a row of data from the `history_assets` table @@ -343,6 +368,54 @@ type Asset struct { Issuer string `db:"asset_issuer"` } +type ContractStat struct { + ActiveBalance string `json:"balance"` + ActiveHolders int32 `json:"holders"` + ArchivedBalance string `json:"archived_balance"` + ArchivedHolders int32 `json:"archived_holders"` +} + +func (c ContractStat) Value() (driver.Value, error) { + // Convert the byte array into a string as a workaround to bypass buggy encoding in the pq driver + // (More info about this bug here https://github.com/stellar/go/issues/5086#issuecomment-1773215436). + // By doing so, the data will be written as a string rather than hex encoded bytes. + val, err := json.Marshal(c) + return string(val), err +} + +func (c *ContractStat) Scan(src interface{}) error { + if src == nil { + c.ActiveBalance = "0" + c.ArchivedBalance = "0" + return nil + } + + source, ok := src.([]byte) + if !ok { + return errors.New("Type assertion .([]byte) failed.") + } + + err := json.Unmarshal(source, &c) + if err != nil { + return err + } + + // Sets zero values for empty balances + if c.ActiveBalance == "" { + c.ActiveBalance = "0" + } + if c.ArchivedBalance == "" { + c.ArchivedBalance = "0" + } + + return nil +} + +type AssetAndContractStat struct { + ExpAssetStat + Contracts ContractStat `db:"contracts"` +} + // ExpAssetStat is a row in the exp_asset_stats table representing the stats per Asset type ExpAssetStat struct { AssetType xdr.AssetType `db:"asset_type"` @@ -352,6 +425,8 @@ type ExpAssetStat struct { Balances ExpAssetStatBalances `db:"balances"` Amount string `db:"amount"` NumAccounts int32 `db:"num_accounts"` + ContractID *[]byte `db:"contract_id"` + // make sure to update Equals() when adding new fields to ExpAssetStat } // PagingToken returns a cursor for this asset stat @@ -374,7 +449,11 @@ type ExpAssetStatAccounts struct { } func (e ExpAssetStatAccounts) Value() (driver.Value, error) { - return json.Marshal(e) + // Convert the byte array into a string as a workaround to bypass buggy encoding in the pq driver + // (More info about this bug here https://github.com/stellar/go/issues/5086#issuecomment-1773215436). + // By doing so, the data will be written as a string rather than hex encoded bytes. + val, err := json.Marshal(e) + return string(val), err } func (e *ExpAssetStatAccounts) Scan(src interface{}) error { @@ -386,6 +465,39 @@ func (e *ExpAssetStatAccounts) Scan(src interface{}) error { return json.Unmarshal(source, &e) } +func (e *ExpAssetStat) Equals(o ExpAssetStat) bool { + if (e.ContractID == nil) != (o.ContractID == nil) { + return false + } + if e.ContractID != nil && !bytes.Equal(*e.ContractID, *o.ContractID) { + return false + } + + return e.AssetType == o.AssetType && + e.AssetCode == o.AssetCode && + e.AssetIssuer == o.AssetIssuer && + e.Accounts == o.Accounts && + e.Balances == o.Balances && + e.Amount == o.Amount && + e.NumAccounts == o.NumAccounts +} + +func (e *ExpAssetStat) GetContractID() ([32]byte, bool) { + var val [32]byte + if e.ContractID == nil { + return val, false + } + if size := copy(val[:], (*e.ContractID)[:]); size != 32 { + panic("contract id is not 32 bytes") + } + return val, true +} + +func (e *ExpAssetStat) SetContractID(contractID [32]byte) { + contractIDBytes := contractID[:] + e.ContractID = &contractIDBytes +} + func (a ExpAssetStatAccounts) Add(b ExpAssetStatAccounts) ExpAssetStatAccounts { return ExpAssetStatAccounts{ Authorized: a.Authorized + b.Authorized, @@ -410,8 +522,22 @@ type ExpAssetStatBalances struct { Unauthorized string `json:"unauthorized"` } +func (e ExpAssetStatBalances) IsZero() bool { + return e == ExpAssetStatBalances{ + Authorized: "0", + AuthorizedToMaintainLiabilities: "0", + ClaimableBalances: "0", + LiquidityPools: "0", + Unauthorized: "0", + } +} + func (e ExpAssetStatBalances) Value() (driver.Value, error) { - return json.Marshal(e) + // Convert the byte array into a string as a workaround to bypass buggy encoding in the pq driver + // (More info about this bug here https://github.com/stellar/go/issues/5086#issuecomment-1773215436). + // By doing so, the data will be written as a string rather than hex encoded bytes. + val, err := json.Marshal(e) + return string(val), err } func (e *ExpAssetStatBalances) Scan(src interface{}) error { @@ -447,12 +573,24 @@ func (e *ExpAssetStatBalances) Scan(src interface{}) error { // QAssetStats defines exp_asset_stats related queries. type QAssetStats interface { - InsertAssetStats(ctx context.Context, stats []ExpAssetStat, batchSize int) error + InsertContractAssetBalances(ctx context.Context, rows []ContractAssetBalance) error + RemoveContractAssetBalances(ctx context.Context, keys []xdr.Hash) error + UpdateContractAssetBalanceAmounts(ctx context.Context, keys []xdr.Hash, amounts []string) error + UpdateContractAssetBalanceExpirations(ctx context.Context, keys []xdr.Hash, expirationLedgers []uint32) error + GetContractAssetBalances(ctx context.Context, keys []xdr.Hash) ([]ContractAssetBalance, error) + GetContractAssetBalancesExpiringAt(ctx context.Context, ledger uint32) ([]ContractAssetBalance, error) + InsertAssetStats(ctx context.Context, stats []ExpAssetStat) error + InsertContractAssetStats(ctx context.Context, rows []ContractAssetStatRow) error InsertAssetStat(ctx context.Context, stat ExpAssetStat) (int64, error) + InsertContractAssetStat(ctx context.Context, row ContractAssetStatRow) (int64, error) UpdateAssetStat(ctx context.Context, stat ExpAssetStat) (int64, error) + UpdateContractAssetStat(ctx context.Context, row ContractAssetStatRow) (int64, error) GetAssetStat(ctx context.Context, assetType xdr.AssetType, assetCode, assetIssuer string) (ExpAssetStat, error) + GetAssetStatByContract(ctx context.Context, contractID xdr.Hash) (ExpAssetStat, error) + GetContractAssetStat(ctx context.Context, contractID []byte) (ContractAssetStatRow, error) RemoveAssetStat(ctx context.Context, assetType xdr.AssetType, assetCode, assetIssuer string) (int64, error) - GetAssetStats(ctx context.Context, assetCode, assetIssuer string, page db2.PageQuery) ([]ExpAssetStat, error) + RemoveAssetContractStat(ctx context.Context, contractID []byte) (int64, error) + GetAssetStats(ctx context.Context, assetCode, assetIssuer string, page db2.PageQuery) ([]AssetAndContractStat, error) CountTrustLines(ctx context.Context) (int, error) } @@ -609,6 +747,7 @@ type Operation struct { SourceAccount string `db:"source_account"` SourceAccountMuxed null.String `db:"source_account_muxed"` TransactionSuccessful bool `db:"transaction_successful"` + IsPayment bool `db:"is_payment"` } // ManageOffer is a struct of data from `operations.DetailsString` @@ -666,7 +805,7 @@ type QSigners interface { GetLastLedgerIngest(ctx context.Context) (uint32, error) UpdateLastLedgerIngest(ctx context.Context, ledgerSequence uint32) error AccountsForSigner(ctx context.Context, signer string, page db2.PageQuery) ([]AccountSigner, error) - NewAccountSignersBatchInsertBuilder(maxBatchSize int) AccountSignersBatchInsertBuilder + NewAccountSignersBatchInsertBuilder() AccountSignersBatchInsertBuilder CreateAccountSigner(ctx context.Context, account, signer string, weight int32, sponsor *string) (int64, error) RemoveAccountSigner(ctx context.Context, account, signer string) (int64, error) SignersForAccounts(ctx context.Context, accounts []string) ([]AccountSigner, error) @@ -768,14 +907,14 @@ type QTrustLines interface { GetTrustLinesByKeys(ctx context.Context, ledgerKeys []string) ([]TrustLine, error) UpsertTrustLines(ctx context.Context, trustlines []TrustLine) error RemoveTrustLines(ctx context.Context, ledgerKeys []string) (int64, error) + NewTrustLinesBatchInsertBuilder() TrustLinesBatchInsertBuilder } -func (q *Q) NewAccountSignersBatchInsertBuilder(maxBatchSize int) AccountSignersBatchInsertBuilder { +func (q *Q) NewAccountSignersBatchInsertBuilder() AccountSignersBatchInsertBuilder { return &accountSignersBatchInsertBuilder{ - builder: db.BatchInsertBuilder{ - Table: q.GetTable("accounts_signers"), - MaxBatchSize: maxBatchSize, - }, + session: q, + builder: db.FastBatchInsertBuilder{}, + table: "accounts_signers", } } @@ -879,6 +1018,24 @@ func (q Q) ReapLookupTables(ctx context.Context, offsets map[string]int64) ( objectField: "history_account_id", }, }, + "history_assets": { + { + name: "history_trades", + objectField: "base_asset_id", + }, + { + name: "history_trades", + objectField: "counter_asset_id", + }, + { + name: "history_trades_60000", + objectField: "base_asset_id", + }, + { + name: "history_trades_60000", + objectField: "counter_asset_id", + }, + }, "history_claimable_balances": { { name: "history_operation_claimable_balances", @@ -950,8 +1107,8 @@ func (q Q) ReapLookupTables(ctx context.Context, offsets map[string]int64) ( // from history_claimable_balances hcb where id > 1000 order by id limit 100) // as sub where c1 IS NULL and c2 IS NULL and 1=1); // -// In short it checks the 100 rows omiting 1000 row of history_claimable_balances -// and counts occurences of each row in corresponding history tables. +// In short it checks the 100 rows omitting 1000 row of history_claimable_balances +// and counts occurrences of each row in corresponding history tables. // If there are no history rows for a given id, the row in // history_claimable_balances is removed. // diff --git a/services/horizon/internal/db2/history/mock_account_data_batch_insert_builder.go b/services/horizon/internal/db2/history/mock_account_data_batch_insert_builder.go new file mode 100644 index 0000000000..aa5af10730 --- /dev/null +++ b/services/horizon/internal/db2/history/mock_account_data_batch_insert_builder.go @@ -0,0 +1,21 @@ +package history + +import ( + "context" + + "github.com/stretchr/testify/mock" +) + +type MockAccountDataBatchInsertBuilder struct { + mock.Mock +} + +func (m *MockAccountDataBatchInsertBuilder) Add(data Data) error { + a := m.Called(data) + return a.Error(0) +} + +func (m *MockAccountDataBatchInsertBuilder) Exec(ctx context.Context) error { + a := m.Called(ctx) + return a.Error(0) +} diff --git a/services/horizon/internal/db2/history/mock_account_signers_batch_insert_builder.go b/services/horizon/internal/db2/history/mock_account_signers_batch_insert_builder.go index 3f786f65ac..9ce4fd7d4c 100644 --- a/services/horizon/internal/db2/history/mock_account_signers_batch_insert_builder.go +++ b/services/horizon/internal/db2/history/mock_account_signers_batch_insert_builder.go @@ -9,8 +9,8 @@ type MockAccountSignersBatchInsertBuilder struct { mock.Mock } -func (m *MockAccountSignersBatchInsertBuilder) Add(ctx context.Context, signer AccountSigner) error { - a := m.Called(ctx, signer) +func (m *MockAccountSignersBatchInsertBuilder) Add(signer AccountSigner) error { + a := m.Called(signer) return a.Error(0) } diff --git a/services/horizon/internal/db2/history/mock_accounts_batch_insert_builder.go b/services/horizon/internal/db2/history/mock_accounts_batch_insert_builder.go new file mode 100644 index 0000000000..a200a15e15 --- /dev/null +++ b/services/horizon/internal/db2/history/mock_accounts_batch_insert_builder.go @@ -0,0 +1,21 @@ +package history + +import ( + "context" + + "github.com/stretchr/testify/mock" +) + +type MockAccountsBatchInsertBuilder struct { + mock.Mock +} + +func (m *MockAccountsBatchInsertBuilder) Add(account AccountEntry) error { + a := m.Called(account) + return a.Error(0) +} + +func (m *MockAccountsBatchInsertBuilder) Exec(ctx context.Context) error { + a := m.Called(ctx) + return a.Error(0) +} diff --git a/services/horizon/internal/db2/history/mock_claimable_balance_batch_insert_builder.go b/services/horizon/internal/db2/history/mock_claimable_balance_batch_insert_builder.go new file mode 100644 index 0000000000..0c1a1e7049 --- /dev/null +++ b/services/horizon/internal/db2/history/mock_claimable_balance_batch_insert_builder.go @@ -0,0 +1,21 @@ +package history + +import ( + "context" + + "github.com/stretchr/testify/mock" +) + +type MockClaimableBalanceBatchInsertBuilder struct { + mock.Mock +} + +func (m *MockClaimableBalanceBatchInsertBuilder) Add(claimableBalance ClaimableBalance) error { + a := m.Called(claimableBalance) + return a.Error(0) +} + +func (m *MockClaimableBalanceBatchInsertBuilder) Exec(ctx context.Context) error { + a := m.Called(ctx) + return a.Error(0) +} diff --git a/services/horizon/internal/db2/history/mock_claimable_balance_claimant_batch_insert_builder.go b/services/horizon/internal/db2/history/mock_claimable_balance_claimant_batch_insert_builder.go new file mode 100644 index 0000000000..3c8fb24d3c --- /dev/null +++ b/services/horizon/internal/db2/history/mock_claimable_balance_claimant_batch_insert_builder.go @@ -0,0 +1,20 @@ +package history + +import ( + "context" + "github.com/stretchr/testify/mock" +) + +type MockClaimableBalanceClaimantBatchInsertBuilder struct { + mock.Mock +} + +func (m *MockClaimableBalanceClaimantBatchInsertBuilder) Add(claimableBalanceClaimant ClaimableBalanceClaimant) error { + a := m.Called(claimableBalanceClaimant) + return a.Error(0) +} + +func (m *MockClaimableBalanceClaimantBatchInsertBuilder) Exec(ctx context.Context) error { + a := m.Called(ctx) + return a.Error(0) +} diff --git a/services/horizon/internal/db2/history/mock_effect_batch_insert_builder.go b/services/horizon/internal/db2/history/mock_effect_batch_insert_builder.go index 48ee96e306..35168a775a 100644 --- a/services/horizon/internal/db2/history/mock_effect_batch_insert_builder.go +++ b/services/horizon/internal/db2/history/mock_effect_batch_insert_builder.go @@ -3,6 +3,8 @@ package history import ( "context" + "github.com/stellar/go/support/db" + "github.com/guregu/null" "github.com/stretchr/testify/mock" ) @@ -13,15 +15,15 @@ type MockEffectBatchInsertBuilder struct { } // Add mock -func (m *MockEffectBatchInsertBuilder) Add(ctx context.Context, - accountID int64, +func (m *MockEffectBatchInsertBuilder) Add( + accountID FutureAccountID, muxedAccount null.String, operationID int64, order uint32, effectType EffectType, details []byte, ) error { - a := m.Called(ctx, + a := m.Called( accountID, muxedAccount, operationID, @@ -33,7 +35,7 @@ func (m *MockEffectBatchInsertBuilder) Add(ctx context.Context, } // Exec mock -func (m *MockEffectBatchInsertBuilder) Exec(ctx context.Context) error { - a := m.Called(ctx) +func (m *MockEffectBatchInsertBuilder) Exec(ctx context.Context, session db.SessionInterface) error { + a := m.Called(ctx, session) return a.Error(0) } diff --git a/services/horizon/internal/db2/history/mock_offers_batch_insert_builder.go b/services/horizon/internal/db2/history/mock_offers_batch_insert_builder.go new file mode 100644 index 0000000000..5caa81f008 --- /dev/null +++ b/services/horizon/internal/db2/history/mock_offers_batch_insert_builder.go @@ -0,0 +1,21 @@ +package history + +import ( + "context" + + "github.com/stretchr/testify/mock" +) + +type MockOffersBatchInsertBuilder struct { + mock.Mock +} + +func (m *MockOffersBatchInsertBuilder) Add(offer Offer) error { + a := m.Called(offer) + return a.Error(0) +} + +func (m *MockOffersBatchInsertBuilder) Exec(ctx context.Context) error { + a := m.Called(ctx) + return a.Error(0) +} diff --git a/services/horizon/internal/db2/history/mock_operation_participant_batch_insert_builder.go b/services/horizon/internal/db2/history/mock_operation_participant_batch_insert_builder.go index 014763f989..481a731043 100644 --- a/services/horizon/internal/db2/history/mock_operation_participant_batch_insert_builder.go +++ b/services/horizon/internal/db2/history/mock_operation_participant_batch_insert_builder.go @@ -2,6 +2,9 @@ package history import ( "context" + + "github.com/stellar/go/support/db" + "github.com/stretchr/testify/mock" ) @@ -11,13 +14,13 @@ type MockOperationParticipantBatchInsertBuilder struct { } // Add mock -func (m *MockOperationParticipantBatchInsertBuilder) Add(ctx context.Context, operationID int64, accountID int64) error { - a := m.Called(ctx, operationID, accountID) +func (m *MockOperationParticipantBatchInsertBuilder) Add(operationID int64, account FutureAccountID) error { + a := m.Called(operationID, account) return a.Error(0) } // Exec mock -func (m *MockOperationParticipantBatchInsertBuilder) Exec(ctx context.Context) error { - a := m.Called(ctx) +func (m *MockOperationParticipantBatchInsertBuilder) Exec(ctx context.Context, session db.SessionInterface) error { + a := m.Called(ctx, session) return a.Error(0) } diff --git a/services/horizon/internal/db2/history/mock_operations_batch_insert_builder.go b/services/horizon/internal/db2/history/mock_operations_batch_insert_builder.go index e57eb93db9..6a63efcdc1 100644 --- a/services/horizon/internal/db2/history/mock_operations_batch_insert_builder.go +++ b/services/horizon/internal/db2/history/mock_operations_batch_insert_builder.go @@ -4,6 +4,7 @@ import ( "context" "github.com/guregu/null" + "github.com/stellar/go/support/db" "github.com/stellar/go/xdr" "github.com/stretchr/testify/mock" ) @@ -14,7 +15,7 @@ type MockOperationsBatchInsertBuilder struct { } // Add mock -func (m *MockOperationsBatchInsertBuilder) Add(ctx context.Context, +func (m *MockOperationsBatchInsertBuilder) Add( id int64, transactionID int64, applicationOrder uint32, @@ -22,8 +23,9 @@ func (m *MockOperationsBatchInsertBuilder) Add(ctx context.Context, details []byte, sourceAccount string, sourceAccountMuxed null.String, + isPayment bool, ) error { - a := m.Called(ctx, + a := m.Called( id, transactionID, applicationOrder, @@ -31,12 +33,13 @@ func (m *MockOperationsBatchInsertBuilder) Add(ctx context.Context, details, sourceAccount, sourceAccountMuxed, + isPayment, ) return a.Error(0) } // Exec mock -func (m *MockOperationsBatchInsertBuilder) Exec(ctx context.Context) error { - a := m.Called(ctx) +func (m *MockOperationsBatchInsertBuilder) Exec(ctx context.Context, session db.SessionInterface) error { + a := m.Called(ctx, session) return a.Error(0) } diff --git a/services/horizon/internal/db2/history/mock_q_accounts.go b/services/horizon/internal/db2/history/mock_q_accounts.go index 99f793d147..6d60802d17 100644 --- a/services/horizon/internal/db2/history/mock_q_accounts.go +++ b/services/horizon/internal/db2/history/mock_q_accounts.go @@ -25,3 +25,8 @@ func (m *MockQAccounts) RemoveAccounts(ctx context.Context, accountIDs []string) a := m.Called(ctx, accountIDs) return a.Get(0).(int64), a.Error(1) } + +func (m *MockQAccounts) NewAccountsBatchInsertBuilder() AccountsBatchInsertBuilder { + a := m.Called() + return a.Get(0).(AccountsBatchInsertBuilder) +} diff --git a/services/horizon/internal/db2/history/mock_q_asset_stats.go b/services/horizon/internal/db2/history/mock_q_asset_stats.go index 17334039e8..84927b53ee 100644 --- a/services/horizon/internal/db2/history/mock_q_asset_stats.go +++ b/services/horizon/internal/db2/history/mock_q_asset_stats.go @@ -14,8 +14,63 @@ type MockQAssetStats struct { mock.Mock } -func (m *MockQAssetStats) InsertAssetStats(ctx context.Context, assetStats []ExpAssetStat, batchSize int) error { - a := m.Called(ctx, assetStats, batchSize) +func (m *MockQAssetStats) InsertContractAssetBalances(ctx context.Context, rows []ContractAssetBalance) error { + a := m.Called(ctx, rows) + return a.Error(0) +} + +func (m *MockQAssetStats) RemoveContractAssetBalances(ctx context.Context, keys []xdr.Hash) error { + a := m.Called(ctx, keys) + return a.Error(0) +} + +func (m *MockQAssetStats) UpdateContractAssetBalanceAmounts(ctx context.Context, keys []xdr.Hash, amounts []string) error { + a := m.Called(ctx, keys, amounts) + return a.Error(0) +} + +func (m *MockQAssetStats) UpdateContractAssetBalanceExpirations(ctx context.Context, keys []xdr.Hash, expirationLedgers []uint32) error { + a := m.Called(ctx, keys, expirationLedgers) + return a.Error(0) +} + +func (m *MockQAssetStats) GetContractAssetBalances(ctx context.Context, keys []xdr.Hash) ([]ContractAssetBalance, error) { + a := m.Called(ctx, keys) + return a.Get(0).([]ContractAssetBalance), a.Error(1) +} + +func (m *MockQAssetStats) GetContractAssetBalancesExpiringAt(ctx context.Context, ledger uint32) ([]ContractAssetBalance, error) { + a := m.Called(ctx, ledger) + return a.Get(0).([]ContractAssetBalance), a.Error(1) +} + +func (m *MockQAssetStats) InsertContractAssetStats(ctx context.Context, rows []ContractAssetStatRow) error { + a := m.Called(ctx, rows) + return a.Error(0) +} + +func (m *MockQAssetStats) InsertContractAssetStat(ctx context.Context, row ContractAssetStatRow) (int64, error) { + a := m.Called(ctx, row) + return a.Get(0).(int64), a.Error(1) +} + +func (m *MockQAssetStats) UpdateContractAssetStat(ctx context.Context, row ContractAssetStatRow) (int64, error) { + a := m.Called(ctx, row) + return a.Get(0).(int64), a.Error(1) +} + +func (m *MockQAssetStats) GetContractAssetStat(ctx context.Context, contractID []byte) (ContractAssetStatRow, error) { + a := m.Called(ctx, contractID) + return a.Get(0).(ContractAssetStatRow), a.Error(1) +} + +func (m *MockQAssetStats) RemoveAssetContractStat(ctx context.Context, contractID []byte) (int64, error) { + a := m.Called(ctx, contractID) + return a.Get(0).(int64), a.Error(1) +} + +func (m *MockQAssetStats) InsertAssetStats(ctx context.Context, assetStats []ExpAssetStat) error { + a := m.Called(ctx, assetStats) return a.Error(0) } @@ -34,13 +89,23 @@ func (m *MockQAssetStats) GetAssetStat(ctx context.Context, assetType xdr.AssetT return a.Get(0).(ExpAssetStat), a.Error(1) } +func (m *MockQAssetStats) GetAssetStatByContract(ctx context.Context, contractID xdr.Hash) (ExpAssetStat, error) { + a := m.Called(ctx, contractID) + return a.Get(0).(ExpAssetStat), a.Error(1) +} + func (m *MockQAssetStats) RemoveAssetStat(ctx context.Context, assetType xdr.AssetType, assetCode, assetIssuer string) (int64, error) { a := m.Called(ctx, assetType, assetCode, assetIssuer) return a.Get(0).(int64), a.Error(1) } -func (m *MockQAssetStats) GetAssetStats(ctx context.Context, assetCode, assetIssuer string, page db2.PageQuery) ([]ExpAssetStat, error) { +func (m *MockQAssetStats) GetAssetStats(ctx context.Context, assetCode, assetIssuer string, page db2.PageQuery) ([]AssetAndContractStat, error) { a := m.Called(ctx, assetCode, assetIssuer, page) + return a.Get(0).([]AssetAndContractStat), a.Error(1) +} + +func (m *MockQAssetStats) GetAssetStatByContracts(ctx context.Context, contractIDs []xdr.Hash) ([]ExpAssetStat, error) { + a := m.Called(ctx, contractIDs) return a.Get(0).([]ExpAssetStat), a.Error(1) } @@ -48,3 +113,8 @@ func (m *MockQAssetStats) CountTrustLines(ctx context.Context) (int, error) { a := m.Called(ctx) return a.Get(0).(int), a.Error(1) } + +func (m *MockQAssetStats) CountContractIDs(ctx context.Context) (int, error) { + a := m.Called(ctx) + return a.Get(0).(int), a.Error(1) +} diff --git a/services/horizon/internal/db2/history/mock_q_claimable_balances.go b/services/horizon/internal/db2/history/mock_q_claimable_balances.go index 9d1cdcdcb0..64b65cf1a3 100644 --- a/services/horizon/internal/db2/history/mock_q_claimable_balances.go +++ b/services/horizon/internal/db2/history/mock_q_claimable_balances.go @@ -21,12 +21,27 @@ func (m *MockQClaimableBalances) GetClaimableBalancesByID(ctx context.Context, i return a.Get(0).([]ClaimableBalance), a.Error(1) } -func (m *MockQClaimableBalances) UpsertClaimableBalances(ctx context.Context, cbs []ClaimableBalance) error { - a := m.Called(ctx, cbs) - return a.Error(0) +func (m *MockQClaimableBalances) RemoveClaimableBalances(ctx context.Context, ids []string) (int64, error) { + a := m.Called(ctx, ids) + return a.Get(0).(int64), a.Error(1) } -func (m *MockQClaimableBalances) RemoveClaimableBalances(ctx context.Context, ids []string) (int64, error) { +func (m *MockQClaimableBalances) RemoveClaimableBalanceClaimants(ctx context.Context, ids []string) (int64, error) { a := m.Called(ctx, ids) return a.Get(0).(int64), a.Error(1) } + +func (m *MockQClaimableBalances) NewClaimableBalanceClaimantBatchInsertBuilder() ClaimableBalanceClaimantBatchInsertBuilder { + a := m.Called() + return a.Get(0).(ClaimableBalanceClaimantBatchInsertBuilder) +} + +func (m *MockQClaimableBalances) NewClaimableBalanceBatchInsertBuilder() ClaimableBalanceBatchInsertBuilder { + a := m.Called() + return a.Get(0).(ClaimableBalanceBatchInsertBuilder) +} + +func (m *MockQClaimableBalances) GetClaimantsByClaimableBalances(ctx context.Context, ids []string) (map[string][]ClaimableBalanceClaimant, error) { + a := m.Called(ctx, ids) + return a.Get(0).(map[string][]ClaimableBalanceClaimant), a.Error(1) +} diff --git a/services/horizon/internal/db2/history/mock_q_data.go b/services/horizon/internal/db2/history/mock_q_data.go index 3316aaa51b..8d418e896e 100644 --- a/services/horizon/internal/db2/history/mock_q_data.go +++ b/services/horizon/internal/db2/history/mock_q_data.go @@ -30,3 +30,8 @@ func (m *MockQData) RemoveAccountData(ctx context.Context, keys []AccountDataKey a := m.Called(ctx, keys) return a.Get(0).(int64), a.Error(1) } + +func (m *MockQData) NewAccountDataBatchInsertBuilder() AccountDataBatchInsertBuilder { + a := m.Called() + return a.Get(0).(AccountDataBatchInsertBuilder) +} diff --git a/services/horizon/internal/db2/history/mock_q_effects.go b/services/horizon/internal/db2/history/mock_q_effects.go index d8bdd97765..615e4699fa 100644 --- a/services/horizon/internal/db2/history/mock_q_effects.go +++ b/services/horizon/internal/db2/history/mock_q_effects.go @@ -10,8 +10,8 @@ type MockQEffects struct { mock.Mock } -func (m *MockQEffects) NewEffectBatchInsertBuilder(maxBatchSize int) EffectBatchInsertBuilder { - a := m.Called(maxBatchSize) +func (m *MockQEffects) NewEffectBatchInsertBuilder() EffectBatchInsertBuilder { + a := m.Called() return a.Get(0).(EffectBatchInsertBuilder) } diff --git a/services/horizon/internal/db2/history/mock_q_history_claimable_balances.go b/services/horizon/internal/db2/history/mock_q_history_claimable_balances.go index 9b7fe1d3b6..6607456af2 100644 --- a/services/horizon/internal/db2/history/mock_q_history_claimable_balances.go +++ b/services/horizon/internal/db2/history/mock_q_history_claimable_balances.go @@ -3,6 +3,8 @@ package history import ( "context" + "github.com/stellar/go/support/db" + "github.com/stretchr/testify/mock" ) @@ -16,8 +18,8 @@ func (m *MockQHistoryClaimableBalances) CreateHistoryClaimableBalances(ctx conte return a.Get(0).(map[string]int64), a.Error(1) } -func (m *MockQHistoryClaimableBalances) NewTransactionClaimableBalanceBatchInsertBuilder(maxBatchSize int) TransactionClaimableBalanceBatchInsertBuilder { - a := m.Called(maxBatchSize) +func (m *MockQHistoryClaimableBalances) NewTransactionClaimableBalanceBatchInsertBuilder() TransactionClaimableBalanceBatchInsertBuilder { + a := m.Called() return a.Get(0).(TransactionClaimableBalanceBatchInsertBuilder) } @@ -27,19 +29,19 @@ type MockTransactionClaimableBalanceBatchInsertBuilder struct { mock.Mock } -func (m *MockTransactionClaimableBalanceBatchInsertBuilder) Add(ctx context.Context, transactionID, accountID int64) error { - a := m.Called(ctx, transactionID, accountID) +func (m *MockTransactionClaimableBalanceBatchInsertBuilder) Add(transactionID int64, claimableBalance FutureClaimableBalanceID) error { + a := m.Called(transactionID, claimableBalance) return a.Error(0) } -func (m *MockTransactionClaimableBalanceBatchInsertBuilder) Exec(ctx context.Context) error { - a := m.Called(ctx) +func (m *MockTransactionClaimableBalanceBatchInsertBuilder) Exec(ctx context.Context, session db.SessionInterface) error { + a := m.Called(ctx, session) return a.Error(0) } // NewOperationClaimableBalanceBatchInsertBuilder mock -func (m *MockQHistoryClaimableBalances) NewOperationClaimableBalanceBatchInsertBuilder(maxBatchSize int) OperationClaimableBalanceBatchInsertBuilder { - a := m.Called(maxBatchSize) +func (m *MockQHistoryClaimableBalances) NewOperationClaimableBalanceBatchInsertBuilder() OperationClaimableBalanceBatchInsertBuilder { + a := m.Called() return a.Get(0).(OperationClaimableBalanceBatchInsertBuilder) } @@ -49,12 +51,12 @@ type MockOperationClaimableBalanceBatchInsertBuilder struct { mock.Mock } -func (m *MockOperationClaimableBalanceBatchInsertBuilder) Add(ctx context.Context, transactionID, accountID int64) error { - a := m.Called(ctx, transactionID, accountID) +func (m *MockOperationClaimableBalanceBatchInsertBuilder) Add(operationID int64, claimableBalance FutureClaimableBalanceID) error { + a := m.Called(operationID, claimableBalance) return a.Error(0) } -func (m *MockOperationClaimableBalanceBatchInsertBuilder) Exec(ctx context.Context) error { - a := m.Called(ctx) +func (m *MockOperationClaimableBalanceBatchInsertBuilder) Exec(ctx context.Context, session db.SessionInterface) error { + a := m.Called(ctx, session) return a.Error(0) } diff --git a/services/horizon/internal/db2/history/mock_q_history_liquidity_pools.go b/services/horizon/internal/db2/history/mock_q_history_liquidity_pools.go index 08f4920de2..bf000a22e9 100644 --- a/services/horizon/internal/db2/history/mock_q_history_liquidity_pools.go +++ b/services/horizon/internal/db2/history/mock_q_history_liquidity_pools.go @@ -3,6 +3,8 @@ package history import ( "context" + "github.com/stellar/go/support/db" + "github.com/stretchr/testify/mock" ) @@ -16,8 +18,8 @@ func (m *MockQHistoryLiquidityPools) CreateHistoryLiquidityPools(ctx context.Con return a.Get(0).(map[string]int64), a.Error(1) } -func (m *MockQHistoryLiquidityPools) NewTransactionLiquidityPoolBatchInsertBuilder(maxBatchSize int) TransactionLiquidityPoolBatchInsertBuilder { - a := m.Called(maxBatchSize) +func (m *MockQHistoryLiquidityPools) NewTransactionLiquidityPoolBatchInsertBuilder() TransactionLiquidityPoolBatchInsertBuilder { + a := m.Called() return a.Get(0).(TransactionLiquidityPoolBatchInsertBuilder) } @@ -27,19 +29,19 @@ type MockTransactionLiquidityPoolBatchInsertBuilder struct { mock.Mock } -func (m *MockTransactionLiquidityPoolBatchInsertBuilder) Add(ctx context.Context, transactionID, accountID int64) error { - a := m.Called(ctx, transactionID, accountID) +func (m *MockTransactionLiquidityPoolBatchInsertBuilder) Add(transactionID int64, lp FutureLiquidityPoolID) error { + a := m.Called(transactionID, lp) return a.Error(0) } -func (m *MockTransactionLiquidityPoolBatchInsertBuilder) Exec(ctx context.Context) error { - a := m.Called(ctx) +func (m *MockTransactionLiquidityPoolBatchInsertBuilder) Exec(ctx context.Context, session db.SessionInterface) error { + a := m.Called(ctx, session) return a.Error(0) } // NewOperationLiquidityPoolBatchInsertBuilder mock -func (m *MockQHistoryLiquidityPools) NewOperationLiquidityPoolBatchInsertBuilder(maxBatchSize int) OperationLiquidityPoolBatchInsertBuilder { - a := m.Called(maxBatchSize) +func (m *MockQHistoryLiquidityPools) NewOperationLiquidityPoolBatchInsertBuilder() OperationLiquidityPoolBatchInsertBuilder { + a := m.Called() return a.Get(0).(OperationLiquidityPoolBatchInsertBuilder) } @@ -49,12 +51,12 @@ type MockOperationLiquidityPoolBatchInsertBuilder struct { mock.Mock } -func (m *MockOperationLiquidityPoolBatchInsertBuilder) Add(ctx context.Context, transactionID, accountID int64) error { - a := m.Called(ctx, transactionID, accountID) +func (m *MockOperationLiquidityPoolBatchInsertBuilder) Add(operationID int64, lp FutureLiquidityPoolID) error { + a := m.Called(operationID, lp) return a.Error(0) } -func (m *MockOperationLiquidityPoolBatchInsertBuilder) Exec(ctx context.Context) error { - a := m.Called(ctx) +func (m *MockOperationLiquidityPoolBatchInsertBuilder) Exec(ctx context.Context, session db.SessionInterface) error { + a := m.Called(ctx, session) return a.Error(0) } diff --git a/services/horizon/internal/db2/history/mock_q_ledgers.go b/services/horizon/internal/db2/history/mock_q_ledgers.go index 16d3ef5524..f02cd7517c 100644 --- a/services/horizon/internal/db2/history/mock_q_ledgers.go +++ b/services/horizon/internal/db2/history/mock_q_ledgers.go @@ -3,23 +3,38 @@ package history import ( "context" - "github.com/stretchr/testify/mock" - + "github.com/stellar/go/support/db" "github.com/stellar/go/xdr" + + "github.com/stretchr/testify/mock" ) type MockQLedgers struct { mock.Mock } -func (m *MockQLedgers) InsertLedger(ctx context.Context, +func (m *MockQLedgers) NewLedgerBatchInsertBuilder() LedgerBatchInsertBuilder { + a := m.Called() + return a.Get(0).(LedgerBatchInsertBuilder) +} + +type MockLedgersBatchInsertBuilder struct { + mock.Mock +} + +func (m *MockLedgersBatchInsertBuilder) Add( ledger xdr.LedgerHeaderHistoryEntry, successTxsCount int, failedTxsCount int, opCount int, txSetOpCount int, ingestVersion int, -) (int64, error) { - a := m.Called(ctx, ledger, successTxsCount, failedTxsCount, opCount, txSetOpCount, ingestVersion) - return a.Get(0).(int64), a.Error(1) +) error { + a := m.Called(ledger, successTxsCount, failedTxsCount, opCount, txSetOpCount, ingestVersion) + return a.Error(0) +} + +func (m *MockLedgersBatchInsertBuilder) Exec(ctx context.Context, session db.SessionInterface) error { + a := m.Called(ctx, session) + return a.Error(0) } diff --git a/services/horizon/internal/db2/history/mock_q_offers.go b/services/horizon/internal/db2/history/mock_q_offers.go index 0c4bc5e9bb..66ae502542 100644 --- a/services/horizon/internal/db2/history/mock_q_offers.go +++ b/services/horizon/internal/db2/history/mock_q_offers.go @@ -40,3 +40,8 @@ func (m *MockQOffers) CompactOffers(ctx context.Context, cutOffSequence uint32) a := m.Called(ctx, cutOffSequence) return a.Get(0).(int64), a.Error(1) } + +func (m *MockQOffers) NewOffersBatchInsertBuilder() OffersBatchInsertBuilder { + a := m.Called() + return a.Get(0).(OffersBatchInsertBuilder) +} diff --git a/services/horizon/internal/db2/history/mock_q_operations.go b/services/horizon/internal/db2/history/mock_q_operations.go index 08a97c6da9..6c2741ad3e 100644 --- a/services/horizon/internal/db2/history/mock_q_operations.go +++ b/services/horizon/internal/db2/history/mock_q_operations.go @@ -8,7 +8,7 @@ type MockQOperations struct { } // NewOperationBatchInsertBuilder mock -func (m *MockQOperations) NewOperationBatchInsertBuilder(maxBatchSize int) OperationBatchInsertBuilder { - a := m.Called(maxBatchSize) +func (m *MockQOperations) NewOperationBatchInsertBuilder() OperationBatchInsertBuilder { + a := m.Called() return a.Get(0).(OperationBatchInsertBuilder) } diff --git a/services/horizon/internal/db2/history/mock_q_participants.go b/services/horizon/internal/db2/history/mock_q_participants.go index 9365e06db3..b871199190 100644 --- a/services/horizon/internal/db2/history/mock_q_participants.go +++ b/services/horizon/internal/db2/history/mock_q_participants.go @@ -2,7 +2,10 @@ package history import ( "context" + "github.com/stretchr/testify/mock" + + "github.com/stellar/go/support/db" ) // MockQParticipants is a mock implementation of the QParticipants interface @@ -15,8 +18,8 @@ func (m *MockQParticipants) CreateAccounts(ctx context.Context, addresses []stri return a.Get(0).(map[string]int64), a.Error(1) } -func (m *MockQParticipants) NewTransactionParticipantsBatchInsertBuilder(maxBatchSize int) TransactionParticipantsBatchInsertBuilder { - a := m.Called(maxBatchSize) +func (m *MockQParticipants) NewTransactionParticipantsBatchInsertBuilder() TransactionParticipantsBatchInsertBuilder { + a := m.Called() return a.Get(0).(TransactionParticipantsBatchInsertBuilder) } @@ -26,18 +29,19 @@ type MockTransactionParticipantsBatchInsertBuilder struct { mock.Mock } -func (m *MockTransactionParticipantsBatchInsertBuilder) Add(ctx context.Context, transactionID, accountID int64) error { - a := m.Called(ctx, transactionID, accountID) +func (m *MockTransactionParticipantsBatchInsertBuilder) Add(transactionID int64, accountID FutureAccountID) error { + a := m.Called(transactionID, accountID) return a.Error(0) } -func (m *MockTransactionParticipantsBatchInsertBuilder) Exec(ctx context.Context) error { - a := m.Called(ctx) +func (m *MockTransactionParticipantsBatchInsertBuilder) Exec(ctx context.Context, session db.SessionInterface) error { + a := m.Called(ctx, session) return a.Error(0) } // NewOperationParticipantBatchInsertBuilder mock -func (m *MockQParticipants) NewOperationParticipantBatchInsertBuilder(maxBatchSize int) OperationParticipantBatchInsertBuilder { - a := m.Called(maxBatchSize) - return a.Get(0).(OperationParticipantBatchInsertBuilder) +func (m *MockQParticipants) NewOperationParticipantBatchInsertBuilder() OperationParticipantBatchInsertBuilder { + a := m.Called() + v := a.Get(0) + return v.(OperationParticipantBatchInsertBuilder) } diff --git a/services/horizon/internal/db2/history/mock_q_signers.go b/services/horizon/internal/db2/history/mock_q_signers.go index 81f56d9fd1..1b2a4864bc 100644 --- a/services/horizon/internal/db2/history/mock_q_signers.go +++ b/services/horizon/internal/db2/history/mock_q_signers.go @@ -32,8 +32,8 @@ func (m *MockQSigners) AccountsForSigner(ctx context.Context, signer string, pag return a.Get(0).([]AccountSigner), a.Error(1) } -func (m *MockQSigners) NewAccountSignersBatchInsertBuilder(maxBatchSize int) AccountSignersBatchInsertBuilder { - a := m.Called(maxBatchSize) +func (m *MockQSigners) NewAccountSignersBatchInsertBuilder() AccountSignersBatchInsertBuilder { + a := m.Called() return a.Get(0).(AccountSignersBatchInsertBuilder) } diff --git a/services/horizon/internal/db2/history/mock_q_trades.go b/services/horizon/internal/db2/history/mock_q_trades.go index d05e0e6a3d..2080f14a8d 100644 --- a/services/horizon/internal/db2/history/mock_q_trades.go +++ b/services/horizon/internal/db2/history/mock_q_trades.go @@ -3,6 +3,7 @@ package history import ( "context" + "github.com/stellar/go/support/db" "github.com/stellar/go/xdr" "github.com/stretchr/testify/mock" @@ -27,8 +28,8 @@ func (m *MockQTrades) CreateHistoryLiquidityPools(ctx context.Context, poolIDs [ return a.Get(0).(map[string]int64), a.Error(1) } -func (m *MockQTrades) NewTradeBatchInsertBuilder(maxBatchSize int) TradeBatchInsertBuilder { - a := m.Called(maxBatchSize) +func (m *MockQTrades) NewTradeBatchInsertBuilder() TradeBatchInsertBuilder { + a := m.Called() return a.Get(0).(TradeBatchInsertBuilder) } @@ -41,12 +42,12 @@ type MockTradeBatchInsertBuilder struct { mock.Mock } -func (m *MockTradeBatchInsertBuilder) Add(ctx context.Context, entries ...InsertTrade) error { - a := m.Called(ctx, entries) +func (m *MockTradeBatchInsertBuilder) Add(entries ...InsertTrade) error { + a := m.Called(entries) return a.Error(0) } -func (m *MockTradeBatchInsertBuilder) Exec(ctx context.Context) error { - a := m.Called(ctx) +func (m *MockTradeBatchInsertBuilder) Exec(ctx context.Context, session db.SessionInterface) error { + a := m.Called(ctx, session) return a.Error(0) } diff --git a/services/horizon/internal/db2/history/mock_q_transactions.go b/services/horizon/internal/db2/history/mock_q_transactions.go index 3bf308128f..064d0e34c4 100644 --- a/services/horizon/internal/db2/history/mock_q_transactions.go +++ b/services/horizon/internal/db2/history/mock_q_transactions.go @@ -7,12 +7,12 @@ type MockQTransactions struct { mock.Mock } -func (m *MockQTransactions) NewTransactionBatchInsertBuilder(maxBatchSize int) TransactionBatchInsertBuilder { - a := m.Called(maxBatchSize) +func (m *MockQTransactions) NewTransactionBatchInsertBuilder() TransactionBatchInsertBuilder { + a := m.Called() return a.Get(0).(TransactionBatchInsertBuilder) } -func (m *MockQTransactions) NewTransactionFilteredTmpBatchInsertBuilder(maxBatchSize int) TransactionBatchInsertBuilder { - a := m.Called(maxBatchSize) +func (m *MockQTransactions) NewTransactionFilteredTmpBatchInsertBuilder() TransactionBatchInsertBuilder { + a := m.Called() return a.Get(0).(TransactionBatchInsertBuilder) } diff --git a/services/horizon/internal/db2/history/mock_q_trust_lines.go b/services/horizon/internal/db2/history/mock_q_trust_lines.go index f6b5b53017..a074b0e7ef 100644 --- a/services/horizon/internal/db2/history/mock_q_trust_lines.go +++ b/services/horizon/internal/db2/history/mock_q_trust_lines.go @@ -25,3 +25,8 @@ func (m *MockQTrustLines) RemoveTrustLines(ctx context.Context, ledgerKeys []str a := m.Called(ctx, ledgerKeys) return a.Get(0).(int64), a.Error(1) } + +func (m *MockQTrustLines) NewTrustLinesBatchInsertBuilder() TrustLinesBatchInsertBuilder { + a := m.Called() + return a.Get(0).(TrustLinesBatchInsertBuilder) +} diff --git a/services/horizon/internal/db2/history/mock_transactions_batch_insert_builder.go b/services/horizon/internal/db2/history/mock_transactions_batch_insert_builder.go index 8e2608d553..db16097a03 100644 --- a/services/horizon/internal/db2/history/mock_transactions_batch_insert_builder.go +++ b/services/horizon/internal/db2/history/mock_transactions_batch_insert_builder.go @@ -6,18 +6,19 @@ import ( "github.com/stretchr/testify/mock" "github.com/stellar/go/ingest" + "github.com/stellar/go/support/db" ) type MockTransactionsBatchInsertBuilder struct { mock.Mock } -func (m *MockTransactionsBatchInsertBuilder) Add(ctx context.Context, transaction ingest.LedgerTransaction, sequence uint32) error { - a := m.Called(ctx, transaction, sequence) +func (m *MockTransactionsBatchInsertBuilder) Add(transaction ingest.LedgerTransaction, sequence uint32) error { + a := m.Called(transaction, sequence) return a.Error(0) } -func (m *MockTransactionsBatchInsertBuilder) Exec(ctx context.Context) error { - a := m.Called(ctx) +func (m *MockTransactionsBatchInsertBuilder) Exec(ctx context.Context, session db.SessionInterface) error { + a := m.Called(ctx, session) return a.Error(0) } diff --git a/services/horizon/internal/db2/history/mock_trust_lines_batch_insert_builder.go b/services/horizon/internal/db2/history/mock_trust_lines_batch_insert_builder.go new file mode 100644 index 0000000000..38e1b41db0 --- /dev/null +++ b/services/horizon/internal/db2/history/mock_trust_lines_batch_insert_builder.go @@ -0,0 +1,21 @@ +package history + +import ( + "context" + + "github.com/stretchr/testify/mock" +) + +type MockTrustLinesBatchInsertBuilder struct { + mock.Mock +} + +func (m *MockTrustLinesBatchInsertBuilder) Add(line TrustLine) error { + a := m.Called(line) + return a.Error(0) +} + +func (m *MockTrustLinesBatchInsertBuilder) Exec(ctx context.Context) error { + a := m.Called(ctx) + return a.Error(0) +} diff --git a/services/horizon/internal/db2/history/offers.go b/services/horizon/internal/db2/history/offers.go index c80d67c854..98a08fef87 100644 --- a/services/horizon/internal/db2/history/offers.go +++ b/services/horizon/internal/db2/history/offers.go @@ -20,6 +20,7 @@ type QOffers interface { GetUpdatedOffers(ctx context.Context, newerThanSequence uint32) ([]Offer, error) UpsertOffers(ctx context.Context, offers []Offer) error CompactOffers(ctx context.Context, cutOffSequence uint32) (int64, error) + NewOffersBatchInsertBuilder() OffersBatchInsertBuilder } func (q *Q) CountOffers(ctx context.Context) (int, error) { diff --git a/services/horizon/internal/db2/history/offers_batch_insert_builder.go b/services/horizon/internal/db2/history/offers_batch_insert_builder.go new file mode 100644 index 0000000000..8a345d08a5 --- /dev/null +++ b/services/horizon/internal/db2/history/offers_batch_insert_builder.go @@ -0,0 +1,39 @@ +package history + +import ( + "context" + + "github.com/stellar/go/support/db" +) + +// OffersBatchInsertBuilder is used to insert offers into the offers table +type OffersBatchInsertBuilder interface { + Add(offer Offer) error + Exec(ctx context.Context) error +} + +// OffersBatchInsertBuilder is a simple wrapper around db.FastBatchInsertBuilder +type offersBatchInsertBuilder struct { + session db.SessionInterface + builder db.FastBatchInsertBuilder + table string +} + +// NewOffersBatchInsertBuilder constructs a new OffersBatchInsertBuilder instance +func (q *Q) NewOffersBatchInsertBuilder() OffersBatchInsertBuilder { + return &offersBatchInsertBuilder{ + session: q, + builder: db.FastBatchInsertBuilder{}, + table: "offers", + } +} + +// Add adds a new offer to the batch +func (i *offersBatchInsertBuilder) Add(offer Offer) error { + return i.builder.RowStruct(offer) +} + +// Exec writes the batch of offers to the database. +func (i *offersBatchInsertBuilder) Exec(ctx context.Context) error { + return i.builder.Exec(ctx, i.session, i.table) +} diff --git a/services/horizon/internal/db2/history/offers_test.go b/services/horizon/internal/db2/history/offers_test.go index 86d93ff958..ebc31e94fa 100644 --- a/services/horizon/internal/db2/history/offers_test.go +++ b/services/horizon/internal/db2/history/offers_test.go @@ -109,7 +109,7 @@ func TestGetNonExistentOfferByID(t *testing.T) { } func streamAllOffersInTx(q *Q, ctx context.Context, f func(offer Offer) error) error { - err := q.BeginTx(&sql.TxOptions{ReadOnly: true, Isolation: sql.LevelRepeatableRead}) + err := q.BeginTx(ctx, &sql.TxOptions{ReadOnly: true, Isolation: sql.LevelRepeatableRead}) if err != nil { return err } @@ -128,7 +128,7 @@ func TestStreamAllOffersRequiresTx(t *testing.T) { }) assert.EqualError(t, err, "cannot be called outside of a transaction") - assert.NoError(t, q.Begin()) + assert.NoError(t, q.Begin(tt.Ctx)) defer q.Rollback() err = q.StreamAllOffers(tt.Ctx, func(offer Offer) error { return nil diff --git a/services/horizon/internal/db2/history/operation.go b/services/horizon/internal/db2/history/operation.go index af1741b0d0..04a6d00f50 100644 --- a/services/horizon/internal/db2/history/operation.go +++ b/services/horizon/internal/db2/history/operation.go @@ -8,6 +8,7 @@ import ( "text/template" sq "github.com/Masterminds/squirrel" + "github.com/stellar/go/services/horizon/internal/db2" "github.com/stellar/go/support/errors" "github.com/stellar/go/toid" @@ -49,7 +50,7 @@ func preprocessDetails(details string) ([]byte, error) { for k, v := range dest { if strings.HasSuffix(k, "_muxed_id") { if vNumber, ok := v.(json.Number); ok { - // transform it into a string so that _muxed_id unmarshalling works with `,string` tags + // transform it into a string so that _muxed_id unmarshaling works with `,string` tags // see https://github.com/stellar/go/pull/3716#issuecomment-867057436 dest[k] = vNumber.String() } @@ -235,16 +236,20 @@ func (q *OperationsQ) ForTransaction(ctx context.Context, hash string) *Operatio } // OnlyPayments filters the query being built to only include operations that -// are in the "payment" class of operations: CreateAccountOps, Payments, and -// PathPayments. +// are in the "payment" class of classic operations: CreateAccountOps, Payments, and +// PathPayments. OR also includes contract asset balance changes as expressed in 'is_payment' flag +// on the history operations table. func (q *OperationsQ) OnlyPayments() *OperationsQ { - q.sql = q.sql.Where(sq.Eq{"hop.type": []xdr.OperationType{ - xdr.OperationTypeCreateAccount, - xdr.OperationTypePayment, - xdr.OperationTypePathPaymentStrictReceive, - xdr.OperationTypePathPaymentStrictSend, - xdr.OperationTypeAccountMerge, - }}) + q.sql = q.sql.Where(sq.Or{ + sq.Eq{"hop.type": []xdr.OperationType{ + xdr.OperationTypeCreateAccount, + xdr.OperationTypePayment, + xdr.OperationTypePathPaymentStrictReceive, + xdr.OperationTypePathPaymentStrictSend, + xdr.OperationTypeAccountMerge, + }}, + sq.Eq{"hop.is_payment": true}}) + return q } @@ -379,7 +384,7 @@ func validateTransactionForOperation(transaction Transaction, operation Operatio // QOperations defines history_operation related queries. type QOperations interface { - NewOperationBatchInsertBuilder(maxBatchSize int) OperationBatchInsertBuilder + NewOperationBatchInsertBuilder() OperationBatchInsertBuilder } var selectOperation = sq.Select( @@ -390,6 +395,7 @@ var selectOperation = sq.Select( "hop.details, " + "hop.source_account, " + "hop.source_account_muxed, " + + "COALESCE(hop.is_payment, false) as is_payment, " + "ht.transaction_hash, " + "ht.tx_result, " + "COALESCE(ht.successful, true) as transaction_successful"). diff --git a/services/horizon/internal/db2/history/operation_batch_insert_builder.go b/services/horizon/internal/db2/history/operation_batch_insert_builder.go index a3baee8863..272a4171c4 100644 --- a/services/horizon/internal/db2/history/operation_batch_insert_builder.go +++ b/services/horizon/internal/db2/history/operation_batch_insert_builder.go @@ -4,6 +4,7 @@ import ( "context" "github.com/guregu/null" + "github.com/stellar/go/support/db" "github.com/stellar/go/xdr" ) @@ -12,7 +13,6 @@ import ( // history_operations table type OperationBatchInsertBuilder interface { Add( - ctx context.Context, id int64, transactionID int64, applicationOrder uint32, @@ -20,28 +20,27 @@ type OperationBatchInsertBuilder interface { details []byte, sourceAccount string, sourceAcccountMuxed null.String, + isPayment bool, ) error - Exec(ctx context.Context) error + Exec(ctx context.Context, session db.SessionInterface) error } // operationBatchInsertBuilder is a simple wrapper around db.BatchInsertBuilder type operationBatchInsertBuilder struct { - builder db.BatchInsertBuilder + builder db.FastBatchInsertBuilder + table string } // NewOperationBatchInsertBuilder constructs a new TransactionBatchInsertBuilder instance -func (q *Q) NewOperationBatchInsertBuilder(maxBatchSize int) OperationBatchInsertBuilder { +func (q *Q) NewOperationBatchInsertBuilder() OperationBatchInsertBuilder { return &operationBatchInsertBuilder{ - builder: db.BatchInsertBuilder{ - Table: q.GetTable("history_operations"), - MaxBatchSize: maxBatchSize, - }, + table: "history_operations", + builder: db.FastBatchInsertBuilder{}, } } // Add adds a transaction's operations to the batch func (i *operationBatchInsertBuilder) Add( - ctx context.Context, id int64, transactionID int64, applicationOrder uint32, @@ -49,19 +48,24 @@ func (i *operationBatchInsertBuilder) Add( details []byte, sourceAccount string, sourceAccountMuxed null.String, + isPayment bool, ) error { - return i.builder.Row(ctx, map[string]interface{}{ + row := map[string]interface{}{ "id": id, "transaction_id": transactionID, "application_order": applicationOrder, "type": operationType, - "details": details, + "details": string(details), "source_account": sourceAccount, "source_account_muxed": sourceAccountMuxed, - }) - + "is_payment": nil, + } + if isPayment { + row["is_payment"] = true + } + return i.builder.Row(row) } -func (i *operationBatchInsertBuilder) Exec(ctx context.Context) error { - return i.builder.Exec(ctx) +func (i *operationBatchInsertBuilder) Exec(ctx context.Context, session db.SessionInterface) error { + return i.builder.Exec(ctx, session, i.table) } diff --git a/services/horizon/internal/db2/history/operation_batch_insert_builder_test.go b/services/horizon/internal/db2/history/operation_batch_insert_builder_test.go index 18b4913a0a..0c06d545f3 100644 --- a/services/horizon/internal/db2/history/operation_batch_insert_builder_test.go +++ b/services/horizon/internal/db2/history/operation_batch_insert_builder_test.go @@ -16,9 +16,11 @@ func TestAddOperation(t *testing.T) { test.ResetHorizonDB(t, tt.HorizonDB) q := &Q{tt.HorizonSession()} - txBatch := q.NewTransactionBatchInsertBuilder(0) + tt.Assert.NoError(q.Begin(tt.Ctx)) - builder := q.NewOperationBatchInsertBuilder(1) + txBatch := q.NewTransactionBatchInsertBuilder() + + builder := q.NewOperationBatchInsertBuilder() transactionHash := "2a805712c6d10f9e74bb0ccf54ae92a2b4b1e586451fe8133a2433816f6b567c" transactionResult := "AAAAAAAAAGQAAAAAAAAAAQAAAAAAAAABAAAAAAAAAAA=" @@ -35,8 +37,8 @@ func TestAddOperation(t *testing.T) { ) sequence := int32(56) - tt.Assert.NoError(txBatch.Add(tt.Ctx, transaction, uint32(sequence))) - tt.Assert.NoError(txBatch.Exec(tt.Ctx)) + tt.Assert.NoError(txBatch.Add(transaction, uint32(sequence))) + tt.Assert.NoError(txBatch.Exec(tt.Ctx, q)) details, err := json.Marshal(map[string]string{ "to": "GANFZDRBCNTUXIODCJEYMACPMCSZEVE4WZGZ3CZDZ3P2SXK4KH75IK6Y", @@ -48,7 +50,7 @@ func TestAddOperation(t *testing.T) { sourceAccount := "GAQAA5L65LSYH7CQ3VTJ7F3HHLGCL3DSLAR2Y47263D56MNNGHSQSTVY" sourceAccountMuxed := "MAQAA5L65LSYH7CQ3VTJ7F3HHLGCL3DSLAR2Y47263D56MNNGHSQSAAAAAAAAAAE2LP26" - err = builder.Add(tt.Ctx, + err = builder.Add( toid.New(sequence, 1, 1).ToInt64(), toid.New(sequence, 1, 0).ToInt64(), 1, @@ -56,11 +58,13 @@ func TestAddOperation(t *testing.T) { details, sourceAccount, null.StringFrom(sourceAccountMuxed), + true, ) tt.Assert.NoError(err) - err = builder.Exec(tt.Ctx) + err = builder.Exec(tt.Ctx, q) tt.Assert.NoError(err) + tt.Assert.NoError(q.Commit()) ops := []Operation{} err = q.Select(tt.Ctx, &ops, selectOperation) diff --git a/services/horizon/internal/db2/history/operation_participant_batch_insert_builder.go b/services/horizon/internal/db2/history/operation_participant_batch_insert_builder.go index 6b2b3afb56..8882141426 100644 --- a/services/horizon/internal/db2/history/operation_participant_batch_insert_builder.go +++ b/services/horizon/internal/db2/history/operation_participant_batch_insert_builder.go @@ -10,40 +10,37 @@ import ( // history_operations table type OperationParticipantBatchInsertBuilder interface { Add( - ctx context.Context, operationID int64, - accountID int64, + accountID FutureAccountID, ) error - Exec(ctx context.Context) error + Exec(ctx context.Context, session db.SessionInterface) error } // operationParticipantBatchInsertBuilder is a simple wrapper around db.BatchInsertBuilder type operationParticipantBatchInsertBuilder struct { - builder db.BatchInsertBuilder + table string + builder db.FastBatchInsertBuilder } -// NewOperationParticipantBatchInsertBuilder constructs a new TransactionBatchInsertBuilder instance -func (q *Q) NewOperationParticipantBatchInsertBuilder(maxBatchSize int) OperationParticipantBatchInsertBuilder { +// NewOperationParticipantBatchInsertBuilder constructs a new OperationParticipantBatchInsertBuilder instance +func (q *Q) NewOperationParticipantBatchInsertBuilder() OperationParticipantBatchInsertBuilder { return &operationParticipantBatchInsertBuilder{ - builder: db.BatchInsertBuilder{ - Table: q.GetTable("history_operation_participants"), - MaxBatchSize: maxBatchSize, - }, + table: "history_operation_participants", + builder: db.FastBatchInsertBuilder{}, } } // Add adds an operation participant to the batch func (i *operationParticipantBatchInsertBuilder) Add( - ctx context.Context, operationID int64, - accountID int64, + accountID FutureAccountID, ) error { - return i.builder.Row(ctx, map[string]interface{}{ + return i.builder.Row(map[string]interface{}{ "history_operation_id": operationID, "history_account_id": accountID, }) } -func (i *operationParticipantBatchInsertBuilder) Exec(ctx context.Context) error { - return i.builder.Exec(ctx) +func (i *operationParticipantBatchInsertBuilder) Exec(ctx context.Context, session db.SessionInterface) error { + return i.builder.Exec(ctx, session, i.table) } diff --git a/services/horizon/internal/db2/history/operation_participant_batch_insert_builder_test.go b/services/horizon/internal/db2/history/operation_participant_batch_insert_builder_test.go index 51a0c4800d..7e823064f2 100644 --- a/services/horizon/internal/db2/history/operation_participant_batch_insert_builder_test.go +++ b/services/horizon/internal/db2/history/operation_participant_batch_insert_builder_test.go @@ -4,6 +4,8 @@ import ( "testing" sq "github.com/Masterminds/squirrel" + + "github.com/stellar/go/keypair" "github.com/stellar/go/services/horizon/internal/test" ) @@ -13,12 +15,16 @@ func TestAddOperationParticipants(t *testing.T) { test.ResetHorizonDB(t, tt.HorizonDB) q := &Q{tt.HorizonSession()} - builder := q.NewOperationParticipantBatchInsertBuilder(1) - err := builder.Add(tt.Ctx, 240518172673, 1) + accountLoader := NewAccountLoader() + address := keypair.MustRandom().Address() + tt.Assert.NoError(q.Begin(tt.Ctx)) + builder := q.NewOperationParticipantBatchInsertBuilder() + err := builder.Add(240518172673, accountLoader.GetFuture(address)) tt.Assert.NoError(err) - err = builder.Exec(tt.Ctx) - tt.Assert.NoError(err) + tt.Assert.NoError(accountLoader.Exec(tt.Ctx, q)) + tt.Assert.NoError(builder.Exec(tt.Ctx, q)) + tt.Assert.NoError(q.Commit()) type hop struct { OperationID int64 `db:"history_operation_id"` @@ -37,6 +43,8 @@ func TestAddOperationParticipants(t *testing.T) { op := ops[0] tt.Assert.Equal(int64(240518172673), op.OperationID) - tt.Assert.Equal(int64(1), op.AccountID) + val, err := accountLoader.GetNow(address) + tt.Assert.NoError(err) + tt.Assert.Equal(val, op.AccountID) } } diff --git a/services/horizon/internal/db2/history/operation_test.go b/services/horizon/internal/db2/history/operation_test.go index 6fadfde67a..1d20a9cb10 100644 --- a/services/horizon/internal/db2/history/operation_test.go +++ b/services/horizon/internal/db2/history/operation_test.go @@ -5,6 +5,7 @@ import ( sq "github.com/Masterminds/squirrel" "github.com/guregu/null" + "github.com/stellar/go/services/horizon/internal/db2" "github.com/stellar/go/services/horizon/internal/test" "github.com/stellar/go/toid" @@ -77,8 +78,10 @@ func TestOperationByLiquidityPool(t *testing.T) { opID1 := toid.New(sequence, txIndex, 1).ToInt64() opID2 := toid.New(sequence, txIndex, 2).ToInt64() + tt.Assert.NoError(q.Begin(tt.Ctx)) + // Insert a phony transaction - transactionBuilder := q.NewTransactionBatchInsertBuilder(2) + transactionBuilder := q.NewTransactionBatchInsertBuilder() firstTransaction := buildLedgerTransaction(tt.T, testTransaction{ index: uint32(txIndex), envelopeXDR: "AAAAACiSTRmpH6bHC6Ekna5e82oiGY5vKDEEUgkq9CB//t+rAAAAyAEXUhsAADDRAAAAAAAAAAAAAAABAAAAAAAAAAsBF1IbAABX4QAAAAAAAAAA", @@ -87,15 +90,14 @@ func TestOperationByLiquidityPool(t *testing.T) { metaXDR: "AAAAAQAAAAAAAAAA", hash: "19aaa18db88605aedec04659fb45e06f240b022eb2d429e05133e4d53cd945ba", }) - err := transactionBuilder.Add(tt.Ctx, firstTransaction, uint32(sequence)) + err := transactionBuilder.Add(firstTransaction, uint32(sequence)) tt.Assert.NoError(err) - err = transactionBuilder.Exec(tt.Ctx) + err = transactionBuilder.Exec(tt.Ctx, q) tt.Assert.NoError(err) // Insert a two phony operations - operationBuilder := q.NewOperationBatchInsertBuilder(2) + operationBuilder := q.NewOperationBatchInsertBuilder() err = operationBuilder.Add( - tt.Ctx, opID1, txID, 1, @@ -103,13 +105,11 @@ func TestOperationByLiquidityPool(t *testing.T) { []byte("{}"), "GAUJETIZVEP2NRYLUESJ3LS66NVCEGMON4UDCBCSBEVPIID773P2W6AY", null.String{}, + false, ) tt.Assert.NoError(err) - err = operationBuilder.Exec(tt.Ctx) - tt.Assert.NoError(err) err = operationBuilder.Add( - tt.Ctx, opID2, txID, 1, @@ -117,25 +117,23 @@ func TestOperationByLiquidityPool(t *testing.T) { []byte("{}"), "GAUJETIZVEP2NRYLUESJ3LS66NVCEGMON4UDCBCSBEVPIID773P2W6AY", null.String{}, + false, ) tt.Assert.NoError(err) - err = operationBuilder.Exec(tt.Ctx) + err = operationBuilder.Exec(tt.Ctx, q) tt.Assert.NoError(err) // Insert Liquidity Pool history liquidityPoolID := "a2f38836a839de008cf1d782c81f45e1253cc5d3dad9110b872965484fec0a49" - toInternalID, err := q.CreateHistoryLiquidityPools(tt.Ctx, []string{liquidityPoolID}, 2) - tt.Assert.NoError(err) - lpOperationBuilder := q.NewOperationLiquidityPoolBatchInsertBuilder(3) - tt.Assert.NoError(err) - internalID, ok := toInternalID[liquidityPoolID] - tt.Assert.True(ok) - err = lpOperationBuilder.Add(tt.Ctx, opID1, internalID) - tt.Assert.NoError(err) - err = lpOperationBuilder.Add(tt.Ctx, opID2, internalID) - tt.Assert.NoError(err) - err = lpOperationBuilder.Exec(tt.Ctx) - tt.Assert.NoError(err) + lpLoader := NewLiquidityPoolLoader() + + lpOperationBuilder := q.NewOperationLiquidityPoolBatchInsertBuilder() + tt.Assert.NoError(lpOperationBuilder.Add(opID1, lpLoader.GetFuture(liquidityPoolID))) + tt.Assert.NoError(lpOperationBuilder.Add(opID2, lpLoader.GetFuture(liquidityPoolID))) + tt.Assert.NoError(lpLoader.Exec(tt.Ctx, q)) + tt.Assert.NoError(lpOperationBuilder.Exec(tt.Ctx, q)) + + tt.Assert.NoError(q.Commit()) // Check ascending order pq := db2.PageQuery{ @@ -170,7 +168,7 @@ func TestOperationQueryBuilder(t *testing.T) { tt.Assert.NoError(err) // Operations for account queries will use hopp.history_operation_id in their predicates. - want := "SELECT hop.id, hop.transaction_id, hop.application_order, hop.type, hop.details, hop.source_account, hop.source_account_muxed, ht.transaction_hash, ht.tx_result, COALESCE(ht.successful, true) as transaction_successful FROM history_operations hop LEFT JOIN history_transactions ht ON ht.id = hop.transaction_id JOIN history_operation_participants hopp ON hopp.history_operation_id = hop.id WHERE hopp.history_account_id = ? AND hopp.history_operation_id > ? ORDER BY hopp.history_operation_id asc LIMIT 10" + want := "SELECT hop.id, hop.transaction_id, hop.application_order, hop.type, hop.details, hop.source_account, hop.source_account_muxed, COALESCE(hop.is_payment, false) as is_payment, ht.transaction_hash, ht.tx_result, COALESCE(ht.successful, true) as transaction_successful FROM history_operations hop LEFT JOIN history_transactions ht ON ht.id = hop.transaction_id JOIN history_operation_participants hopp ON hopp.history_operation_id = hop.id WHERE hopp.history_account_id = ? AND hopp.history_operation_id > ? ORDER BY hopp.history_operation_id asc LIMIT 10" tt.Assert.EqualValues(want, got) opsQ = q.Operations().ForLedger(tt.Ctx, 2).Page(db2.PageQuery{Cursor: "8589938689", Order: "asc", Limit: 10}) @@ -179,7 +177,7 @@ func TestOperationQueryBuilder(t *testing.T) { tt.Assert.NoError(err) // Other operation queries will use hop.id in their predicates. - want = "SELECT hop.id, hop.transaction_id, hop.application_order, hop.type, hop.details, hop.source_account, hop.source_account_muxed, ht.transaction_hash, ht.tx_result, COALESCE(ht.successful, true) as transaction_successful FROM history_operations hop LEFT JOIN history_transactions ht ON ht.id = hop.transaction_id WHERE hop.id >= ? AND hop.id < ? AND hop.id > ? ORDER BY hop.id asc LIMIT 10" + want = "SELECT hop.id, hop.transaction_id, hop.application_order, hop.type, hop.details, hop.source_account, hop.source_account_muxed, COALESCE(hop.is_payment, false) as is_payment, ht.transaction_hash, ht.tx_result, COALESCE(ht.successful, true) as transaction_successful FROM history_operations hop LEFT JOIN history_transactions ht ON ht.id = hop.transaction_id WHERE hop.id >= ? AND hop.id < ? AND hop.id > ? ORDER BY hop.id asc LIMIT 10" tt.Assert.EqualValues(want, got) } @@ -241,7 +239,7 @@ func TestOperationIncludeFailed(t *testing.T) { sql, _, err := query.sql.ToSql() tt.Assert.NoError(err) - tt.Assert.Equal("SELECT hop.id, hop.transaction_id, hop.application_order, hop.type, hop.details, hop.source_account, hop.source_account_muxed, ht.transaction_hash, ht.tx_result, COALESCE(ht.successful, true) as transaction_successful FROM history_operations hop LEFT JOIN history_transactions ht ON ht.id = hop.transaction_id JOIN history_operation_participants hopp ON hopp.history_operation_id = hop.id WHERE hopp.history_account_id = ?", sql) + tt.Assert.Equal("SELECT hop.id, hop.transaction_id, hop.application_order, hop.type, hop.details, hop.source_account, hop.source_account_muxed, COALESCE(hop.is_payment, false) as is_payment, ht.transaction_hash, ht.tx_result, COALESCE(ht.successful, true) as transaction_successful FROM history_operations hop LEFT JOIN history_transactions ht ON ht.id = hop.transaction_id JOIN history_operation_participants hopp ON hopp.history_operation_id = hop.id WHERE hopp.history_account_id = ?", sql) } // TestPaymentsSuccessfulOnly tests if default query returns payments in @@ -271,7 +269,7 @@ func TestPaymentsSuccessfulOnly(t *testing.T) { sql, _, err := query.sql.ToSql() tt.Assert.NoError(err) // Note: brackets around `(ht.successful = true OR ht.successful IS NULL)` are critical! - tt.Assert.Contains(sql, "WHERE hop.type IN (?,?,?,?,?) AND hopp.history_account_id = ? AND (ht.successful = true OR ht.successful IS NULL)") + tt.Assert.Contains(sql, "WHERE (hop.type IN (?,?,?,?,?) OR hop.is_payment = ?) AND hopp.history_account_id = ? AND (ht.successful = true OR ht.successful IS NULL)") } // TestPaymentsIncludeFailed tests `IncludeFailed` method. @@ -304,7 +302,7 @@ func TestPaymentsIncludeFailed(t *testing.T) { sql, _, err := query.sql.ToSql() tt.Assert.NoError(err) - tt.Assert.Equal("SELECT hop.id, hop.transaction_id, hop.application_order, hop.type, hop.details, hop.source_account, hop.source_account_muxed, ht.transaction_hash, ht.tx_result, COALESCE(ht.successful, true) as transaction_successful FROM history_operations hop LEFT JOIN history_transactions ht ON ht.id = hop.transaction_id JOIN history_operation_participants hopp ON hopp.history_operation_id = hop.id WHERE hop.type IN (?,?,?,?,?) AND hopp.history_account_id = ?", sql) + tt.Assert.Equal("SELECT hop.id, hop.transaction_id, hop.application_order, hop.type, hop.details, hop.source_account, hop.source_account_muxed, COALESCE(hop.is_payment, false) as is_payment, ht.transaction_hash, ht.tx_result, COALESCE(ht.successful, true) as transaction_successful FROM history_operations hop LEFT JOIN history_transactions ht ON ht.id = hop.transaction_id JOIN history_operation_participants hopp ON hopp.history_operation_id = hop.id WHERE (hop.type IN (?,?,?,?,?) OR hop.is_payment = ?) AND hopp.history_account_id = ?", sql) } func TestExtraChecksOperationsTransactionSuccessfulTrueResultFalse(t *testing.T) { diff --git a/services/horizon/internal/db2/history/orderbook.go b/services/horizon/internal/db2/history/orderbook.go index 3de321a4ac..ab3237795f 100644 --- a/services/horizon/internal/db2/history/orderbook.go +++ b/services/horizon/internal/db2/history/orderbook.go @@ -117,7 +117,7 @@ func (q *Q) GetOrderBookSummary(ctx context.Context, sellingAsset, buyingAsset x // we don't expect there to be any inconsistency between levels and offers because // this function should only be invoked in a repeatable read transaction if len(levels) != len(offers) { - return result, errors.Wrap(err, "price levels length does not match summaries length") + return result, errors.New("price levels length does not match summaries length") } for i, level := range levels { sum := offers[i] @@ -151,7 +151,7 @@ func (q *Q) GetOrderBookSummary(ctx context.Context, sellingAsset, buyingAsset x } else if sum.Type == "bid" { result.Bids = append(result.Bids, entry) } else { - return result, errors.Wrap(err, "invalid offer type") + return result, errors.New("invalid offer type") } } diff --git a/services/horizon/internal/db2/history/orderbook_test.go b/services/horizon/internal/db2/history/orderbook_test.go index b265d50c86..7ef36a74f8 100644 --- a/services/horizon/internal/db2/history/orderbook_test.go +++ b/services/horizon/internal/db2/history/orderbook_test.go @@ -18,7 +18,7 @@ func TestGetOrderBookSummaryRequiresTransaction(t *testing.T) { _, err := q.GetOrderBookSummary(tt.Ctx, nativeAsset, eurAsset, 10) assert.EqualError(t, err, "cannot be called outside of a transaction") - assert.NoError(t, q.Begin()) + assert.NoError(t, q.Begin(tt.Ctx)) defer q.Rollback() _, err = q.GetOrderBookSummary(tt.Ctx, nativeAsset, eurAsset, 10) @@ -215,7 +215,7 @@ func TestGetOrderBookSummary(t *testing.T) { assert.NoError(t, q.TruncateTables(tt.Ctx, []string{"offers"})) assert.NoError(t, q.UpsertOffers(tt.Ctx, testCase.offers)) - assert.NoError(t, q.BeginTx(&sql.TxOptions{ + assert.NoError(t, q.BeginTx(tt.Ctx, &sql.TxOptions{ Isolation: sql.LevelRepeatableRead, ReadOnly: true, })) @@ -257,7 +257,7 @@ func TestGetOrderBookSummaryExcludesRemovedOffers(t *testing.T) { assert.NoError(t, q.UpsertOffers(tt.Ctx, offers)) - assert.NoError(t, q.BeginTx(&sql.TxOptions{ + assert.NoError(t, q.BeginTx(tt.Ctx, &sql.TxOptions{ Isolation: sql.LevelRepeatableRead, ReadOnly: true, })) @@ -278,7 +278,7 @@ func TestGetOrderBookSummaryExcludesRemovedOffers(t *testing.T) { } assert.NoError(t, q.UpsertOffers(tt.Ctx, offersToDelete)) - assert.NoError(t, q.BeginTx(&sql.TxOptions{ + assert.NoError(t, q.BeginTx(tt.Ctx, &sql.TxOptions{ Isolation: sql.LevelRepeatableRead, ReadOnly: true, })) @@ -294,7 +294,7 @@ func TestGetOrderBookSummaryExcludesRemovedOffers(t *testing.T) { assert.NoError(t, err) assert.Equal(t, int64(len(offers)), count) - assert.NoError(t, q.BeginTx(&sql.TxOptions{ + assert.NoError(t, q.BeginTx(tt.Ctx, &sql.TxOptions{ Isolation: sql.LevelRepeatableRead, ReadOnly: true, })) diff --git a/services/horizon/internal/db2/history/participants.go b/services/horizon/internal/db2/history/participants.go index 658e877f78..f73b5ab577 100644 --- a/services/horizon/internal/db2/history/participants.go +++ b/services/horizon/internal/db2/history/participants.go @@ -9,40 +9,39 @@ import ( // QParticipants defines ingestion participant related queries. type QParticipants interface { QCreateAccountsHistory - NewTransactionParticipantsBatchInsertBuilder(maxBatchSize int) TransactionParticipantsBatchInsertBuilder - NewOperationParticipantBatchInsertBuilder(maxBatchSize int) OperationParticipantBatchInsertBuilder + NewTransactionParticipantsBatchInsertBuilder() TransactionParticipantsBatchInsertBuilder + NewOperationParticipantBatchInsertBuilder() OperationParticipantBatchInsertBuilder } // TransactionParticipantsBatchInsertBuilder is used to insert transaction participants into the // history_transaction_participants table type TransactionParticipantsBatchInsertBuilder interface { - Add(ctx context.Context, transactionID, accountID int64) error - Exec(ctx context.Context) error + Add(transactionID int64, accountID FutureAccountID) error + Exec(ctx context.Context, session db.SessionInterface) error } type transactionParticipantsBatchInsertBuilder struct { - builder db.BatchInsertBuilder + tableName string + builder db.FastBatchInsertBuilder } // NewTransactionParticipantsBatchInsertBuilder constructs a new TransactionParticipantsBatchInsertBuilder instance -func (q *Q) NewTransactionParticipantsBatchInsertBuilder(maxBatchSize int) TransactionParticipantsBatchInsertBuilder { +func (q *Q) NewTransactionParticipantsBatchInsertBuilder() TransactionParticipantsBatchInsertBuilder { return &transactionParticipantsBatchInsertBuilder{ - builder: db.BatchInsertBuilder{ - Table: q.GetTable("history_transaction_participants"), - MaxBatchSize: maxBatchSize, - }, + tableName: "history_transaction_participants", + builder: db.FastBatchInsertBuilder{}, } } // Add adds a new transaction participant to the batch -func (i *transactionParticipantsBatchInsertBuilder) Add(ctx context.Context, transactionID, accountID int64) error { - return i.builder.Row(ctx, map[string]interface{}{ +func (i *transactionParticipantsBatchInsertBuilder) Add(transactionID int64, accountID FutureAccountID) error { + return i.builder.Row(map[string]interface{}{ "history_transaction_id": transactionID, "history_account_id": accountID, }) } // Exec flushes all pending transaction participants to the db -func (i *transactionParticipantsBatchInsertBuilder) Exec(ctx context.Context) error { - return i.builder.Exec(ctx) +func (i *transactionParticipantsBatchInsertBuilder) Exec(ctx context.Context, session db.SessionInterface) error { + return i.builder.Exec(ctx, session, i.tableName) } diff --git a/services/horizon/internal/db2/history/participants_test.go b/services/horizon/internal/db2/history/participants_test.go index ee37f2b833..37f7654abb 100644 --- a/services/horizon/internal/db2/history/participants_test.go +++ b/services/horizon/internal/db2/history/participants_test.go @@ -4,6 +4,8 @@ import ( "testing" sq "github.com/Masterminds/squirrel" + + "github.com/stellar/go/keypair" "github.com/stellar/go/services/horizon/internal/test" ) @@ -32,27 +34,38 @@ func TestTransactionParticipantsBatch(t *testing.T) { test.ResetHorizonDB(t, tt.HorizonDB) q := &Q{tt.HorizonSession()} - batch := q.NewTransactionParticipantsBatchInsertBuilder(0) + batch := q.NewTransactionParticipantsBatchInsertBuilder() + accountLoader := NewAccountLoader() transactionID := int64(1) otherTransactionID := int64(2) - accountID := int64(100) - + var addresses []string for i := int64(0); i < 3; i++ { - tt.Assert.NoError(batch.Add(tt.Ctx, transactionID, accountID+i)) + address := keypair.MustRandom().Address() + addresses = append(addresses, address) + tt.Assert.NoError(batch.Add(transactionID, accountLoader.GetFuture(address))) } - tt.Assert.NoError(batch.Add(tt.Ctx, otherTransactionID, accountID)) - tt.Assert.NoError(batch.Exec(tt.Ctx)) + address := keypair.MustRandom().Address() + addresses = append(addresses, address) + tt.Assert.NoError(batch.Add(otherTransactionID, accountLoader.GetFuture(address))) + + tt.Assert.NoError(q.Begin(tt.Ctx)) + tt.Assert.NoError(accountLoader.Exec(tt.Ctx, q)) + tt.Assert.NoError(batch.Exec(tt.Ctx, q)) + tt.Assert.NoError(q.Commit()) participants := getTransactionParticipants(tt, q) - tt.Assert.Equal( - []transactionParticipant{ - transactionParticipant{TransactionID: 1, AccountID: 100}, - transactionParticipant{TransactionID: 1, AccountID: 101}, - transactionParticipant{TransactionID: 1, AccountID: 102}, - transactionParticipant{TransactionID: 2, AccountID: 100}, - }, - participants, - ) + expected := []transactionParticipant{ + {TransactionID: 1}, + {TransactionID: 1}, + {TransactionID: 1}, + {TransactionID: 2}, + } + for i := range expected { + val, err := accountLoader.GetNow(addresses[i]) + tt.Assert.NoError(err) + expected[i].AccountID = val + } + tt.Assert.ElementsMatch(expected, participants) } diff --git a/services/horizon/internal/db2/history/reap_test.go b/services/horizon/internal/db2/history/reap_test.go index 5e62dc606f..b6ed16c76b 100644 --- a/services/horizon/internal/db2/history/reap_test.go +++ b/services/horizon/internal/db2/history/reap_test.go @@ -22,6 +22,7 @@ func TestReapLookupTables(t *testing.T) { var ( prevLedgers, curLedgers int prevAccounts, curAccounts int + prevAssets, curAssets int prevClaimableBalances, curClaimableBalances int prevLiquidityPools, curLiquidityPools int ) @@ -32,6 +33,8 @@ func TestReapLookupTables(t *testing.T) { tt.Require.NoError(err) err = db.GetRaw(tt.Ctx, &prevAccounts, `SELECT COUNT(*) FROM history_accounts`) tt.Require.NoError(err) + err = db.GetRaw(tt.Ctx, &prevAssets, `SELECT COUNT(*) FROM history_assets`) + tt.Require.NoError(err) err = db.GetRaw(tt.Ctx, &prevClaimableBalances, `SELECT COUNT(*) FROM history_claimable_balances`) tt.Require.NoError(err) err = db.GetRaw(tt.Ctx, &prevLiquidityPools, `SELECT COUNT(*) FROM history_liquidity_pools`) @@ -45,7 +48,7 @@ func TestReapLookupTables(t *testing.T) { q := &history.Q{tt.HorizonSession()} - err = q.Begin() + err = q.Begin(tt.Ctx) tt.Require.NoError(err) deletedCount, newOffsets, err := q.ReapLookupTables(tt.Ctx, nil) @@ -60,6 +63,8 @@ func TestReapLookupTables(t *testing.T) { tt.Require.NoError(err) err = db.GetRaw(tt.Ctx, &curAccounts, `SELECT COUNT(*) FROM history_accounts`) tt.Require.NoError(err) + err = db.GetRaw(tt.Ctx, &curAssets, `SELECT COUNT(*) FROM history_assets`) + tt.Require.NoError(err) err = db.GetRaw(tt.Ctx, &curClaimableBalances, `SELECT COUNT(*) FROM history_claimable_balances`) tt.Require.NoError(err) err = db.GetRaw(tt.Ctx, &curLiquidityPools, `SELECT COUNT(*) FROM history_liquidity_pools`) @@ -73,6 +78,10 @@ func TestReapLookupTables(t *testing.T) { tt.Assert.Equal(1, curAccounts, "curAccounts") tt.Assert.Equal(int64(24), deletedCount["history_accounts"], `deletedCount["history_accounts"]`) + tt.Assert.Equal(7, prevAssets, "prevAssets") + tt.Assert.Equal(0, curAssets, "curAssets") + tt.Assert.Equal(int64(7), deletedCount["history_assets"], `deletedCount["history_assets"]`) + tt.Assert.Equal(1, prevClaimableBalances, "prevClaimableBalances") tt.Assert.Equal(0, curClaimableBalances, "curClaimableBalances") tt.Assert.Equal(int64(1), deletedCount["history_claimable_balances"], `deletedCount["history_claimable_balances"]`) @@ -81,8 +90,9 @@ func TestReapLookupTables(t *testing.T) { tt.Assert.Equal(0, curLiquidityPools, "curLiquidityPools") tt.Assert.Equal(int64(1), deletedCount["history_liquidity_pools"], `deletedCount["history_liquidity_pools"]`) - tt.Assert.Len(newOffsets, 3) + tt.Assert.Len(newOffsets, 4) tt.Assert.Equal(int64(0), newOffsets["history_accounts"]) + tt.Assert.Equal(int64(0), newOffsets["history_assets"]) tt.Assert.Equal(int64(0), newOffsets["history_claimable_balances"]) tt.Assert.Equal(int64(0), newOffsets["history_liquidity_pools"]) } diff --git a/services/horizon/internal/db2/history/trade.go b/services/horizon/internal/db2/history/trade.go index 65b6a1ce98..6d8a7fca56 100644 --- a/services/horizon/internal/db2/history/trade.go +++ b/services/horizon/internal/db2/history/trade.go @@ -348,7 +348,7 @@ func getCanonicalAssetOrder( type QTrades interface { QCreateAccountsHistory - NewTradeBatchInsertBuilder(maxBatchSize int) TradeBatchInsertBuilder + NewTradeBatchInsertBuilder() TradeBatchInsertBuilder RebuildTradeAggregationBuckets(ctx context.Context, fromledger, toLedger uint32, roundingSlippageFilter int) error CreateAssets(ctx context.Context, assets []xdr.Asset, maxBatchSize int) (map[string]Asset, error) CreateHistoryLiquidityPools(ctx context.Context, poolIDs []string, batchSize int) (map[string]int64, error) diff --git a/services/horizon/internal/db2/history/trade_batch_insert_builder.go b/services/horizon/internal/db2/history/trade_batch_insert_builder.go index 1f2d614424..8420fabd36 100644 --- a/services/horizon/internal/db2/history/trade_batch_insert_builder.go +++ b/services/horizon/internal/db2/history/trade_batch_insert_builder.go @@ -24,7 +24,7 @@ const ( // rows into the history_trades table type InsertTrade struct { HistoryOperationID int64 `db:"history_operation_id"` - Order int32 `db:"\"order\""` + Order int32 `db:"order"` LedgerCloseTime time.Time `db:"ledger_closed_at"` CounterAssetID int64 `db:"counter_asset_id"` @@ -55,36 +55,33 @@ type InsertTrade struct { // TradeBatchInsertBuilder is used to insert trades into the // history_trades table type TradeBatchInsertBuilder interface { - Add(ctx context.Context, entries ...InsertTrade) error - Exec(ctx context.Context) error + Add(entries ...InsertTrade) error + Exec(ctx context.Context, session db.SessionInterface) error } // tradeBatchInsertBuilder is a simple wrapper around db.BatchInsertBuilder type tradeBatchInsertBuilder struct { - builder db.BatchInsertBuilder - q *Q + builder db.FastBatchInsertBuilder + table string } // NewTradeBatchInsertBuilder constructs a new TradeBatchInsertBuilder instance -func (q *Q) NewTradeBatchInsertBuilder(maxBatchSize int) TradeBatchInsertBuilder { +func (q *Q) NewTradeBatchInsertBuilder() TradeBatchInsertBuilder { return &tradeBatchInsertBuilder{ - builder: db.BatchInsertBuilder{ - Table: q.GetTable("history_trades"), - MaxBatchSize: maxBatchSize, - }, - q: q, + table: "history_trades", + builder: db.FastBatchInsertBuilder{}, } } // Exec flushes all outstanding trades to the database -func (i *tradeBatchInsertBuilder) Exec(ctx context.Context) error { - return i.builder.Exec(ctx) +func (i *tradeBatchInsertBuilder) Exec(ctx context.Context, session db.SessionInterface) error { + return i.builder.Exec(ctx, session, i.table) } // Add adds a new trade to the batch -func (i *tradeBatchInsertBuilder) Add(ctx context.Context, entries ...InsertTrade) error { +func (i *tradeBatchInsertBuilder) Add(entries ...InsertTrade) error { for _, entry := range entries { - err := i.builder.RowStruct(ctx, entry) + err := i.builder.RowStruct(entry) if err != nil { return errors.Wrap(err, "failed to add trade") } diff --git a/services/horizon/internal/db2/history/trade_scenario.go b/services/horizon/internal/db2/history/trade_scenario.go index 22e1830277..7296238a35 100644 --- a/services/horizon/internal/db2/history/trade_scenario.go +++ b/services/horizon/internal/db2/history/trade_scenario.go @@ -199,7 +199,7 @@ func FilterTradesByType(trades []Trade, tradeType string) []Trade { // TradeScenario inserts trade rows into the Horizon DB func TradeScenario(tt *test.T, q *Q) TradeFixtures { - builder := q.NewTradeBatchInsertBuilder(0) + builder := q.NewTradeBatchInsertBuilder() addresses := []string{ "GB2QIYT2IAUFMRXKLSLLPRECC6OCOGJMADSPTRK7TGNT2SFR2YGWDARD", @@ -229,10 +229,12 @@ func TradeScenario(tt *test.T, q *Q) TradeFixtures { inserts := createInsertTrades(accountIDs, assetIDs, poolIDs, 3) + tt.Assert.NoError(q.Begin(tt.Ctx)) tt.Assert.NoError( - builder.Add(tt.Ctx, inserts...), + builder.Add(inserts...), ) - tt.Assert.NoError(builder.Exec(tt.Ctx)) + tt.Assert.NoError(builder.Exec(tt.Ctx, q)) + tt.Assert.NoError(q.Commit()) idToAccount := buildIDtoAccountMapping(addresses, accountIDs) idToAsset := buildIDtoAssetMapping(assets, assetIDs) diff --git a/services/horizon/internal/db2/history/transaction.go b/services/horizon/internal/db2/history/transaction.go index 0771a626b8..a308ab9ddc 100644 --- a/services/horizon/internal/db2/history/transaction.go +++ b/services/horizon/internal/db2/history/transaction.go @@ -232,8 +232,8 @@ func (q *TransactionsQ) Select(ctx context.Context, dest interface{}) error { // QTransactions defines transaction related queries. type QTransactions interface { - NewTransactionBatchInsertBuilder(maxBatchSize int) TransactionBatchInsertBuilder - NewTransactionFilteredTmpBatchInsertBuilder(maxBatchSize int) TransactionBatchInsertBuilder + NewTransactionBatchInsertBuilder() TransactionBatchInsertBuilder + NewTransactionFilteredTmpBatchInsertBuilder() TransactionBatchInsertBuilder } func selectTransaction(table string) sq.SelectBuilder { diff --git a/services/horizon/internal/db2/history/transaction_batch_insert_builder.go b/services/horizon/internal/db2/history/transaction_batch_insert_builder.go index 2ecb25dbe7..742621cec5 100644 --- a/services/horizon/internal/db2/history/transaction_batch_insert_builder.go +++ b/services/horizon/internal/db2/history/transaction_batch_insert_builder.go @@ -21,50 +21,47 @@ import ( // TransactionBatchInsertBuilder is used to insert transactions into the // history_transactions table type TransactionBatchInsertBuilder interface { - Add(ctx context.Context, transaction ingest.LedgerTransaction, sequence uint32) error - Exec(ctx context.Context) error + Add(transaction ingest.LedgerTransaction, sequence uint32) error + Exec(ctx context.Context, session db.SessionInterface) error } // transactionBatchInsertBuilder is a simple wrapper around db.BatchInsertBuilder type transactionBatchInsertBuilder struct { encodingBuffer *xdr.EncodingBuffer - builder db.BatchInsertBuilder + table string + builder db.FastBatchInsertBuilder } // NewTransactionBatchInsertBuilder constructs a new TransactionBatchInsertBuilder instance -func (q *Q) NewTransactionBatchInsertBuilder(maxBatchSize int) TransactionBatchInsertBuilder { +func (q *Q) NewTransactionBatchInsertBuilder() TransactionBatchInsertBuilder { return &transactionBatchInsertBuilder{ encodingBuffer: xdr.NewEncodingBuffer(), - builder: db.BatchInsertBuilder{ - Table: q.GetTable("history_transactions"), - MaxBatchSize: maxBatchSize, - }, + table: "history_transactions", + builder: db.FastBatchInsertBuilder{}, } } -// NewTransactionBatchInsertBuilder constructs a new TransactionBatchInsertBuilder instance -func (q *Q) NewTransactionFilteredTmpBatchInsertBuilder(maxBatchSize int) TransactionBatchInsertBuilder { +// NewTransactionFilteredTmpBatchInsertBuilder constructs a new TransactionBatchInsertBuilder instance +func (q *Q) NewTransactionFilteredTmpBatchInsertBuilder() TransactionBatchInsertBuilder { return &transactionBatchInsertBuilder{ encodingBuffer: xdr.NewEncodingBuffer(), - builder: db.BatchInsertBuilder{ - Table: q.GetTable("history_transactions_filtered_tmp"), - MaxBatchSize: maxBatchSize, - }, + table: "history_transactions_filtered_tmp", + builder: db.FastBatchInsertBuilder{}, } } // Add adds a new transaction to the batch -func (i *transactionBatchInsertBuilder) Add(ctx context.Context, transaction ingest.LedgerTransaction, sequence uint32) error { +func (i *transactionBatchInsertBuilder) Add(transaction ingest.LedgerTransaction, sequence uint32) error { row, err := transactionToRow(transaction, sequence, i.encodingBuffer) if err != nil { return err } - return i.builder.RowStruct(ctx, row) + return i.builder.RowStruct(row) } -func (i *transactionBatchInsertBuilder) Exec(ctx context.Context) error { - return i.builder.Exec(ctx) +func (i *transactionBatchInsertBuilder) Exec(ctx context.Context, session db.SessionInterface) error { + return i.builder.Exec(ctx, session, i.table) } func signatures(xdrSignatures []xdr.DecoratedSignature) pq.StringArray { diff --git a/services/horizon/internal/db2/history/transaction_test.go b/services/horizon/internal/db2/history/transaction_test.go index 0f3592c439..30c22c7660 100644 --- a/services/horizon/internal/db2/history/transaction_test.go +++ b/services/horizon/internal/db2/history/transaction_test.go @@ -8,6 +8,7 @@ import ( sq "github.com/Masterminds/squirrel" "github.com/guregu/null" + "github.com/stellar/go/xdr" "github.com/stellar/go/ingest" @@ -45,7 +46,8 @@ func TestTransactionByLiquidityPool(t *testing.T) { // Insert a phony ledger ledgerCloseTime := time.Now().Unix() - _, err := q.InsertLedger(tt.Ctx, xdr.LedgerHeaderHistoryEntry{ + ledgerBatch := q.NewLedgerBatchInsertBuilder() + err := ledgerBatch.Add(xdr.LedgerHeaderHistoryEntry{ Header: xdr.LedgerHeader{ LedgerSeq: xdr.Uint32(sequence), ScpValue: xdr.StellarValue{ @@ -55,8 +57,12 @@ func TestTransactionByLiquidityPool(t *testing.T) { }, 0, 0, 0, 0, 0) tt.Assert.NoError(err) + tt.Assert.NoError(q.Begin(tt.Ctx)) + + tt.Assert.NoError(ledgerBatch.Exec(tt.Ctx, q.SessionInterface)) + // Insert a phony transaction - transactionBuilder := q.NewTransactionBatchInsertBuilder(2) + transactionBuilder := q.NewTransactionBatchInsertBuilder() firstTransaction := buildLedgerTransaction(tt.T, testTransaction{ index: uint32(txIndex), envelopeXDR: "AAAAACiSTRmpH6bHC6Ekna5e82oiGY5vKDEEUgkq9CB//t+rAAAAyAEXUhsAADDRAAAAAAAAAAAAAAABAAAAAAAAAAsBF1IbAABX4QAAAAAAAAAA", @@ -65,27 +71,24 @@ func TestTransactionByLiquidityPool(t *testing.T) { metaXDR: "AAAAAQAAAAAAAAAA", hash: "19aaa18db88605aedec04659fb45e06f240b022eb2d429e05133e4d53cd945ba", }) - err = transactionBuilder.Add(tt.Ctx, firstTransaction, uint32(sequence)) + err = transactionBuilder.Add(firstTransaction, uint32(sequence)) tt.Assert.NoError(err) - err = transactionBuilder.Exec(tt.Ctx) + err = transactionBuilder.Exec(tt.Ctx, q) tt.Assert.NoError(err) // Insert Liquidity Pool history liquidityPoolID := "a2f38836a839de008cf1d782c81f45e1253cc5d3dad9110b872965484fec0a49" - toInternalID, err := q.CreateHistoryLiquidityPools(tt.Ctx, []string{liquidityPoolID}, 2) - tt.Assert.NoError(err) - lpTransactionBuilder := q.NewTransactionLiquidityPoolBatchInsertBuilder(2) - tt.Assert.NoError(err) - internalID, ok := toInternalID[liquidityPoolID] - tt.Assert.True(ok) - err = lpTransactionBuilder.Add(tt.Ctx, txID, internalID) - tt.Assert.NoError(err) - err = lpTransactionBuilder.Exec(tt.Ctx) - tt.Assert.NoError(err) + lpLoader := NewLiquidityPoolLoader() + lpTransactionBuilder := q.NewTransactionLiquidityPoolBatchInsertBuilder() + tt.Assert.NoError(lpTransactionBuilder.Add(txID, lpLoader.GetFuture(liquidityPoolID))) + tt.Assert.NoError(lpLoader.Exec(tt.Ctx, q)) + tt.Assert.NoError(lpTransactionBuilder.Exec(tt.Ctx, q)) + tt.Assert.NoError(q.Commit()) var records []Transaction - err = q.Transactions().ForLiquidityPool(tt.Ctx, liquidityPoolID).Select(tt.Ctx, &records) - tt.Assert.NoError(err) + tt.Assert.NoError( + q.Transactions().ForLiquidityPool(tt.Ctx, liquidityPoolID).Select(tt.Ctx, &records), + ) tt.Assert.Len(records, 1) } @@ -206,8 +209,10 @@ func TestInsertTransactionDoesNotAllowDuplicateIndex(t *testing.T) { test.ResetHorizonDB(t, tt.HorizonDB) q := &Q{tt.HorizonSession()} + tt.Assert.NoError(q.Begin(tt.Ctx)) + sequence := uint32(123) - insertBuilder := q.NewTransactionBatchInsertBuilder(0) + insertBuilder := q.NewTransactionBatchInsertBuilder() firstTransaction := buildLedgerTransaction(tt.T, testTransaction{ index: 1, @@ -226,16 +231,18 @@ func TestInsertTransactionDoesNotAllowDuplicateIndex(t *testing.T) { hash: "7e2def20d5a21a56be2a457b648f702ee1af889d3df65790e92a05081e9fabf1", }) - tt.Assert.NoError(insertBuilder.Add(tt.Ctx, firstTransaction, sequence)) - tt.Assert.NoError(insertBuilder.Exec(tt.Ctx)) + tt.Assert.NoError(insertBuilder.Add(firstTransaction, sequence)) + tt.Assert.NoError(insertBuilder.Exec(tt.Ctx, q)) + tt.Assert.NoError(q.Commit()) - tt.Assert.NoError(insertBuilder.Add(tt.Ctx, secondTransaction, sequence)) + tt.Assert.NoError(q.Begin(tt.Ctx)) + insertBuilder = q.NewTransactionBatchInsertBuilder() + tt.Assert.NoError(insertBuilder.Add(secondTransaction, sequence)) tt.Assert.EqualError( - insertBuilder.Exec(tt.Ctx), - "error adding values while inserting to history_transactions: "+ - "exec failed: pq: duplicate key value violates unique constraint "+ - "\"hs_transaction_by_id\"", + insertBuilder.Exec(tt.Ctx, q), + "pq: duplicate key value violates unique constraint \"hs_transaction_by_id\"", ) + tt.Assert.NoError(q.Rollback()) ledger := Ledger{ Sequence: int32(sequence), @@ -301,8 +308,6 @@ func TestInsertTransaction(t *testing.T) { _, err := q.Exec(tt.Ctx, sq.Insert("history_ledgers").SetMap(ledgerToMap(ledger))) tt.Assert.NoError(err) - insertBuilder := q.NewTransactionBatchInsertBuilder(0) - success := true emptySignatures := []string{} @@ -822,8 +827,11 @@ func TestInsertTransaction(t *testing.T) { }, } { t.Run(testCase.name, func(t *testing.T) { - tt.Assert.NoError(insertBuilder.Add(tt.Ctx, testCase.toInsert, sequence)) - tt.Assert.NoError(insertBuilder.Exec(tt.Ctx)) + insertBuilder := q.NewTransactionBatchInsertBuilder() + tt.Assert.NoError(q.Begin(tt.Ctx)) + tt.Assert.NoError(insertBuilder.Add(testCase.toInsert, sequence)) + tt.Assert.NoError(insertBuilder.Exec(tt.Ctx, q)) + tt.Assert.NoError(q.Commit()) var transactions []Transaction tt.Assert.NoError(q.Transactions().IncludeFailed().Select(tt.Ctx, &transactions)) diff --git a/services/horizon/internal/db2/history/trust_lines_batch_insert_builder.go b/services/horizon/internal/db2/history/trust_lines_batch_insert_builder.go new file mode 100644 index 0000000000..2c77469775 --- /dev/null +++ b/services/horizon/internal/db2/history/trust_lines_batch_insert_builder.go @@ -0,0 +1,39 @@ +package history + +import ( + "context" + + "github.com/stellar/go/support/db" +) + +// TrustLinesBatchInsertBuilder is used to insert trustlines into the trust_lines table +type TrustLinesBatchInsertBuilder interface { + Add(line TrustLine) error + Exec(ctx context.Context) error +} + +// trustLinesBatchInsertBuilder is a simple wrapper around db.FastBatchInsertBuilder +type trustLinesBatchInsertBuilder struct { + session db.SessionInterface + builder db.FastBatchInsertBuilder + table string +} + +// NewTrustLinesBatchInsertBuilder constructs a new TrustLinesBatchInsertBuilder instance +func (q *Q) NewTrustLinesBatchInsertBuilder() TrustLinesBatchInsertBuilder { + return &trustLinesBatchInsertBuilder{ + session: q, + builder: db.FastBatchInsertBuilder{}, + table: "trust_lines", + } +} + +// Add adds a new trustline to the batch +func (i *trustLinesBatchInsertBuilder) Add(line TrustLine) error { + return i.builder.RowStruct(line) +} + +// Exec writes the batch of trust lines to the database. +func (i *trustLinesBatchInsertBuilder) Exec(ctx context.Context) error { + return i.builder.Exec(ctx, i.session, i.table) +} diff --git a/services/horizon/internal/db2/history/verify_lock.go b/services/horizon/internal/db2/history/verify_lock.go new file mode 100644 index 0000000000..f56045e9b1 --- /dev/null +++ b/services/horizon/internal/db2/history/verify_lock.go @@ -0,0 +1,38 @@ +package history + +import ( + "context" + + "github.com/stellar/go/support/db" + "github.com/stellar/go/support/errors" +) + +// stateVerificationLockId is the objid for the advisory lock acquired during +// state verification. The value is arbitrary. The only requirement is that +// all ingesting nodes use the same value which is why it's hard coded here. +const stateVerificationLockId = 73897213 + +// TryStateVerificationLock attempts to acquire the state verification lock +// which gives the ingesting node exclusive access to perform state verification. +// TryStateVerificationLock returns true if the lock was acquired or false if the +// lock could not be acquired because it is held by another node. +func (q *Q) TryStateVerificationLock(ctx context.Context) (bool, error) { + if tx := q.GetTx(); tx == nil { + return false, errors.New("cannot be called outside of a transaction") + } + + var acquired []bool + err := q.SelectRaw( + context.WithValue(ctx, &db.QueryTypeContextKey, db.AdvisoryLockQueryType), + &acquired, + "SELECT pg_try_advisory_xact_lock(?)", + stateVerificationLockId, + ) + if err != nil { + return false, errors.Wrap(err, "error acquiring advisory lock for state verification") + } + if len(acquired) != 1 { + return false, errors.New("invalid response from advisory lock") + } + return acquired[0], nil +} diff --git a/services/horizon/internal/db2/history/verify_lock_test.go b/services/horizon/internal/db2/history/verify_lock_test.go new file mode 100644 index 0000000000..7368c4d40d --- /dev/null +++ b/services/horizon/internal/db2/history/verify_lock_test.go @@ -0,0 +1,47 @@ +package history + +import ( + "context" + "database/sql" + "testing" + + "github.com/stellar/go/services/horizon/internal/test" +) + +func TestTryStateVerificationLock(t *testing.T) { + tt := test.Start(t) + defer tt.Finish() + test.ResetHorizonDB(t, tt.HorizonDB) + q := &Q{tt.HorizonSession()} + otherQ := &Q{q.Clone()} + + _, err := q.TryStateVerificationLock(context.Background()) + tt.Assert.EqualError(err, "cannot be called outside of a transaction") + + tt.Assert.NoError(q.BeginTx(tt.Ctx, &sql.TxOptions{ + Isolation: sql.LevelRepeatableRead, + ReadOnly: true, + })) + ok, err := q.TryStateVerificationLock(context.Background()) + tt.Assert.NoError(err) + tt.Assert.True(ok) + + // lock is already held by q so we will not succeed + tt.Assert.NoError(otherQ.BeginTx(tt.Ctx, &sql.TxOptions{ + Isolation: sql.LevelRepeatableRead, + ReadOnly: true, + })) + ok, err = otherQ.TryStateVerificationLock(context.Background()) + tt.Assert.NoError(err) + tt.Assert.False(ok) + + // when q is rolled back that releases the lock + tt.Assert.NoError(q.Rollback()) + + // now otherQ is able to acquire the lock + ok, err = otherQ.TryStateVerificationLock(context.Background()) + tt.Assert.NoError(err) + tt.Assert.True(ok) + + tt.Assert.NoError(otherQ.Rollback()) +} diff --git a/services/horizon/internal/db2/schema/bindata.go b/services/horizon/internal/db2/schema/bindata.go index 1d6c2b7bde..eeee086b24 100644 --- a/services/horizon/internal/db2/schema/bindata.go +++ b/services/horizon/internal/db2/schema/bindata.go @@ -49,13 +49,21 @@ // migrations/51_remove_ht_unused_indexes.sql (321B) // migrations/52_add_trade_type_index.sql (424B) // migrations/53_add_trades_rounding_slippage.sql (274B) -// migrations/54_tx_preconditions_and_account_fields.sql (1.355kB) +// migrations/54_tx_preconditions_and_account_fields.sql (1.478kB) // migrations/55_filter_rules.sql (893B) // migrations/56_txsub_read_only.sql (784B) // migrations/57_trade_aggregation_autovac.sql (282B) // migrations/58_add_index_by_id_optimization.sql (868B) // migrations/59_remove_foreign_key_constraints.sql (981B) // migrations/5_create_trades_table.sql (1.1kB) +// migrations/60_add_asset_id_indexes.sql (289B) +// migrations/61_trust_lines_by_account_type_code_issuer.sql (383B) +// migrations/62_claimable_balance_claimants.sql (1.428kB) +// migrations/63_add_contract_id_to_asset_stats.sql (153B) +// migrations/64_add_payment_flag_history_ops.sql (145B) +// migrations/65_drop_payment_index.sql (260B) +// migrations/66_contract_asset_stats.sql (583B) +// migrations/67_remove_unused_indexes.sql (2.897kB) // migrations/6_create_assets_table.sql (366B) // migrations/7_modify_trades_table.sql (2.303kB) // migrations/8_add_aggregators.sql (907B) @@ -1109,7 +1117,7 @@ func migrations53_add_trades_rounding_slippageSql() (*asset, error) { return a, nil } -var _migrations54_tx_preconditions_and_account_fieldsSql = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xa4\x54\xcd\x6e\xda\x40\x10\xbe\xfb\x29\xe6\x96\x9f\xc6\x34\x4d\x29\xaa\x6a\xa9\x12\x09\x1c\x2a\xd1\x04\x25\x70\xa8\xaa\xca\x1a\xbc\xa3\x65\x5b\x7b\x96\xee\x8e\x03\xf4\xe9\xab\xb5\x81\x14\x8a\x55\xab\x70\x62\xed\x99\xf9\x7e\xf6\x1b\xc7\x31\xbc\x2a\x8c\x76\x28\x04\xd3\x45\xd4\x1f\x4d\x86\x8f\x30\xe9\xdf\x8e\x86\x30\x37\x5e\xac\x5b\xa7\xe2\x90\x3d\x66\x62\x2c\x7b\xe8\x0f\x06\x90\x93\xd2\xe4\xd2\x99\x2d\x59\x79\xf8\xfb\x67\x58\xde\x3b\x64\x4d\x49\x75\x8c\x63\x58\x29\xd7\x99\x1a\x96\xb7\x37\xbe\x1d\x44\x61\x38\xc5\x2c\xb3\x25\x4b\xea\xe9\x67\x49\x9c\xd1\x9f\x10\x33\xa3\x0d\x4b\xb2\x3d\x6e\x20\x9e\x36\x95\xf7\x65\x31\x23\x07\xf1\xc7\x40\xa5\xd7\xfd\x7f\xc8\x14\xf5\x0e\xf6\x19\x5d\x36\x47\x77\x7e\x73\x7d\x91\xbc\x40\x4e\x4c\x41\x63\x6b\x58\x02\x5a\x59\xc1\x85\x7f\xb9\x65\x4d\x5e\xb6\x4f\xb8\x22\x74\x02\x8f\x8d\xe5\x1a\x17\x0d\xd2\x3f\x05\x73\xdb\x01\xd0\x4a\x1c\xa6\xde\x68\x26\x77\xec\xfa\x84\x56\xf2\xf5\x5b\x12\xed\x4d\xdb\x30\xaa\x27\x1c\xd0\x0a\x2e\x93\x26\x97\xb4\xe8\x10\x53\xd0\x56\x42\x14\xc5\x31\xdc\xf5\xc7\x71\xf7\x1a\x2a\x3a\x0a\x16\xb8\xce\x2d\x2a\xf0\xe2\x7e\xd0\xda\x43\x86\x0c\x33\x82\x37\xbd\x77\x10\xcc\xc7\x4c\x02\xe7\xe0\xee\x15\x78\xa2\x30\xa0\x2e\x7d\x5d\xa0\xe1\x8e\xb6\x1f\x0a\x5c\x0d\x39\xb3\x8a\xd4\x93\xf9\x45\x1d\xb8\x2d\x05\x96\x74\x96\xe7\x50\x7a\xaa\xb4\xc1\x9c\x1c\x5d\x81\xb7\xb0\x24\x50\x96\xcf\x04\x98\x48\x81\xd8\x30\x0e\xd5\xf7\xd2\x0b\x18\x81\x4b\x7a\x26\x07\xa8\xd1\xf0\x65\xe7\xa8\xb4\xad\x89\x11\x40\xfd\xfa\xee\x61\x34\xfd\x7c\x5f\x8b\x71\x30\xf9\x32\x1e\x56\x88\xb5\xd2\xdd\x9e\x0d\xec\x92\xff\x7d\x55\x83\xc7\x87\xf1\xfe\xaa\x25\x2d\x9b\x8e\x25\xe8\x94\xde\xb0\x05\x27\xf5\xbf\xa4\xb7\xed\x98\xbd\x8c\x36\x45\xb1\xaa\x3c\x00\x69\xc8\xe0\x7e\x69\x08\x61\xc3\xd0\x36\x57\xba\x4b\x62\xf8\x26\xac\x0d\xeb\xf3\x5e\xf7\x22\x89\x7e\x07\x00\x00\xff\xff\x09\xc0\xc0\xa1\x4b\x05\x00\x00") +var _migrations54_tx_preconditions_and_account_fieldsSql = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xa4\x93\x51\x6f\xda\x40\x0c\xc7\xdf\xf3\x29\xfc\xd6\xd2\x35\xac\xed\x28\x9a\x16\x69\x12\x2d\x3c\x4c\x62\x2d\x6a\xe1\x61\x9a\xa6\xc8\x24\xde\xe5\xb6\xc4\xc7\xee\x9c\x06\xf6\xe9\xa7\x4b\x80\x8e\x0e\xb4\xa8\xe4\x29\x97\xd8\xfe\xff\xed\xfb\x39\x0c\xe1\x4d\xa1\x95\x45\x21\x98\x2d\x82\xc1\x78\x3a\x7a\x80\xe9\xe0\x66\x3c\x82\x4c\x3b\x31\x76\x15\x8b\x45\x76\x98\x88\x36\xec\x60\x30\x1c\x42\x4e\xa9\x22\x1b\xcf\x4d\xc9\xa9\x83\x7f\x1f\xcd\xf2\xde\x22\x2b\x8a\xea\x63\x18\xc2\x32\xb5\xdd\x99\x66\x79\x77\xe5\xda\x49\x14\x9a\x63\x4c\x12\x53\xb2\xc4\x8e\x7e\x95\xc4\x09\xfd\x2d\x31\xd7\x4a\xb3\x44\x9b\xe3\x5a\xe2\x71\x1d\x79\x57\x16\x73\xb2\x10\x7e\xf4\x56\xfa\xbd\xd7\x4b\xc6\xa8\xb6\xb2\x4f\x68\x93\x0c\xed\xe9\xd5\x45\x27\x7a\x96\x9c\xea\x82\x26\x46\xb3\x78\xb5\xb2\x96\xf3\x6f\xb9\x61\x45\x4e\x36\x5f\xb8\x36\x74\x84\x8f\xf5\xc8\x15\x2e\x0e\xb4\xfe\xc9\x0f\xb7\x9d\x00\x2d\xc5\x62\xec\xb4\x62\xb2\xfb\xae\x4f\x68\x29\x5f\xbf\x45\xc1\x4e\xb5\xb5\xa3\xa6\xc2\x0b\x5b\x7e\xca\xa4\xc8\x46\x2d\x32\x44\x17\xb4\x69\x21\x08\xc2\x10\x6e\x07\x93\xb0\x77\x01\xb5\x9d\x14\x16\xb8\xca\x0d\xa6\xe0\xc4\xfe\xa4\x95\x83\x04\x19\xe6\x04\x97\xfd\x6b\xf0\xc3\xc7\x44\xbc\x67\x3f\xdd\x73\x70\x44\xbe\x40\x13\xfa\xb6\x40\xcd\x5d\x65\x3e\x14\xb8\x1c\x71\x62\x52\x4a\x1f\xf5\x6f\xea\xc2\x4d\x29\x50\xd1\x49\x9e\x43\xe9\xa8\xee\x0d\x32\xb2\x74\x0e\xce\x40\x45\x90\x1a\x3e\x11\x60\xa2\x14\xc4\xf8\x72\x98\xfe\x28\x9d\x80\x16\x38\xa3\x27\xb2\x80\x0a\x35\x9f\x75\xf7\xb6\xb6\x19\x62\x00\xd0\xfc\xbe\xbd\x1f\xcf\x3e\xdf\x35\xcd\x58\x98\x7e\x99\x8c\x6a\xc5\xa6\xd3\xed\x9e\x0d\x4d\xc5\xff\xbf\xaa\xe1\xc3\xfd\x64\x77\xd5\xa2\x96\x49\xfb\x08\x3a\x26\xd7\x6f\xc1\x51\xf9\xcf\xf4\xb6\x2d\xb3\xc3\xe8\x21\x14\xeb\xc8\x17\x22\x07\x18\xdc\x0d\xf5\x10\x36\x77\x52\x91\x47\x8c\x8d\x80\x25\xef\x85\x40\x32\x02\x63\x3d\xa0\x98\x83\xac\x16\x04\xe6\xbb\xdf\xfd\x95\x66\x75\xda\xef\x75\x60\x4e\x09\xd6\x28\x79\x8c\xa0\xd0\x2a\x13\x8f\xa8\x33\x45\x8d\xa3\x35\x95\x83\x4a\x4b\x06\x9b\x0d\x93\x0c\x05\xd0\x97\x36\xa6\x46\xf7\xf5\x30\x6d\x77\x60\xeb\xe8\xb2\x7f\xdd\x89\x82\x3f\x01\x00\x00\xff\xff\xdf\x89\xd7\x33\xc6\x05\x00\x00") func migrations54_tx_preconditions_and_account_fieldsSqlBytes() ([]byte, error) { return bindataRead( @@ -1125,7 +1133,7 @@ func migrations54_tx_preconditions_and_account_fieldsSql() (*asset, error) { } info := bindataFileInfo{name: "migrations/54_tx_preconditions_and_account_fields.sql", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} - a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xa2, 0x72, 0xbe, 0x5c, 0xbd, 0xfb, 0xfd, 0x70, 0xf0, 0x2f, 0x4e, 0x76, 0x36, 0x7b, 0xb9, 0xd5, 0xfb, 0x25, 0xe8, 0x13, 0xb1, 0xf6, 0x59, 0x9d, 0xac, 0xec, 0xc3, 0x6b, 0xbe, 0x8f, 0xae, 0xb3}} + a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xfa, 0xa9, 0xea, 0xb6, 0x2e, 0x10, 0x1d, 0x6b, 0x53, 0x5d, 0xf7, 0x92, 0x50, 0x61, 0xcd, 0xab, 0x61, 0xa1, 0x1b, 0xbb, 0x24, 0xe3, 0x9e, 0xbe, 0x4d, 0x9d, 0x27, 0x52, 0xb2, 0x60, 0xb1, 0xc4}} return a, nil } @@ -1249,6 +1257,166 @@ func migrations5_create_trades_tableSql() (*asset, error) { return a, nil } +var _migrations60_add_asset_id_indexesSql = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xd2\xd5\x55\xd0\xce\xcd\x4c\x2f\x4a\x2c\x49\x55\x08\x2d\xe0\xe2\x72\x0e\x72\x75\x0c\x71\x55\xf0\xf4\x73\x71\x8d\x50\x50\xca\x28\x29\x4a\x89\x4f\xaa\x8c\x4f\xce\x2f\xcd\x2b\x49\x2d\x8a\x4f\x2c\x2e\x4e\x2d\x51\x52\xf0\xf7\x53\xc8\xc8\x2c\x2e\xc9\x2f\xaa\x8c\x2f\x29\x4a\x4c\x49\x2d\x56\x08\x0d\xf6\xf4\x73\x57\x48\x2a\x29\x4a\x4d\x55\xd0\x40\x51\x1d\x9f\x99\xa2\x69\x8d\xcd\xd8\xc4\xf4\x74\x82\xe6\xc6\x9b\x19\x18\x18\x18\x10\x34\x9d\x0b\xd9\x17\x2e\xf9\xe5\x79\x5c\x5c\x2e\x41\xfe\x01\xf8\x7d\x61\x8d\xa9\x06\xd3\x49\xd6\x5c\x80\x00\x00\x00\xff\xff\xda\xc9\x55\x1a\x21\x01\x00\x00") + +func migrations60_add_asset_id_indexesSqlBytes() ([]byte, error) { + return bindataRead( + _migrations60_add_asset_id_indexesSql, + "migrations/60_add_asset_id_indexes.sql", + ) +} + +func migrations60_add_asset_id_indexesSql() (*asset, error) { + bytes, err := migrations60_add_asset_id_indexesSqlBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "migrations/60_add_asset_id_indexes.sql", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} + a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xef, 0x83, 0xa, 0xf7, 0x61, 0x6c, 0x13, 0x30, 0x13, 0xa1, 0x1d, 0x1c, 0x82, 0xb2, 0xf9, 0x85, 0x64, 0x30, 0xfc, 0x78, 0x90, 0x47, 0xf3, 0x45, 0xc5, 0x94, 0x65, 0xad, 0x61, 0xea, 0x47, 0xb8}} + return a, nil +} + +var _migrations61_trust_lines_by_account_type_code_issuerSql = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xa4\x8f\xcf\xca\x82\x50\x10\x47\xf7\xf3\x14\x83\xab\x4f\x3e\x7d\x82\xbb\x8a\x94\x70\xa3\x61\x09\xed\x06\xff\x0c\x71\xa1\x54\xee\xcc\x25\x7c\xfb\x28\x2b\x5c\x26\xed\xce\x62\xe6\xf0\x3b\x71\x8c\xff\x57\x7b\x76\xb5\x32\x56\x23\xc0\xb6\x4c\x37\xc7\x14\xb3\x3c\x49\x4f\x18\xa8\xf3\xa2\x74\xb1\x3d\x0b\x35\x13\xe9\x34\x32\xb5\x43\xc7\x64\x45\x3c\x3b\xaa\xdb\x76\xf0\xbd\x06\x58\xe4\xb8\xb8\xc5\xea\x90\xe5\x3b\x6c\xd4\x31\xe3\x5f\x2d\xc2\xfa\xfc\x8d\x70\xe6\x87\xe2\xcd\xb3\x29\xc2\x97\x8a\x6c\x17\x1a\x48\xca\x62\xff\xe5\x86\xc0\x00\x2c\x23\x92\xe1\xd6\xc3\x1a\xc1\x27\xc2\xac\x8b\xff\x3d\x3a\x34\x70\x0f\x00\x00\xff\xff\xae\x55\x70\x5f\x7f\x01\x00\x00") + +func migrations61_trust_lines_by_account_type_code_issuerSqlBytes() ([]byte, error) { + return bindataRead( + _migrations61_trust_lines_by_account_type_code_issuerSql, + "migrations/61_trust_lines_by_account_type_code_issuer.sql", + ) +} + +func migrations61_trust_lines_by_account_type_code_issuerSql() (*asset, error) { + bytes, err := migrations61_trust_lines_by_account_type_code_issuerSqlBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "migrations/61_trust_lines_by_account_type_code_issuer.sql", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} + a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x6e, 0xc, 0x3a, 0xa, 0xcd, 0x1f, 0x39, 0x26, 0xd2, 0xd0, 0xe1, 0x22, 0xc3, 0x42, 0x7a, 0x79, 0xd6, 0x32, 0xf3, 0xf0, 0x8e, 0x86, 0x3e, 0xc6, 0xfc, 0x54, 0x3c, 0x40, 0x5a, 0x5e, 0x71, 0x9}} + return a, nil +} + +var _migrations62_claimable_balance_claimantsSql = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xbc\x94\xc1\x6f\xd3\x30\x18\xc5\xef\xf9\x2b\x9e\x72\x6a\x43\xab\x5e\x60\x97\x0a\xa1\x6e\x8d\x50\x45\x49\xa7\x2c\x95\xb6\x53\xf4\xc5\xfe\xd6\x59\x4a\xec\xc8\x36\x1b\xfd\xef\x51\xd2\x0e\x02\x6c\x4d\x0a\x88\x53\x24\xcb\xef\x7d\xef\xfd\xec\x78\x3a\xc5\x9b\x4a\xed\x2c\x79\xc6\xb6\x0e\x82\xab\x34\x5e\x64\x31\xb2\xc5\xe5\x3a\x86\x28\x49\x55\x54\x94\x9c\x17\x54\x92\x16\x9c\x1f\x56\xb4\x77\x18\x05\x00\xa0\x24\xb2\xf8\x36\x43\xb2\xc9\x90\x6c\xd7\xeb\x09\xa6\x53\x5c\x3d\xcb\x2e\x0f\xaa\xd5\x12\x4a\xa3\x20\xc7\x17\x6f\x5b\x95\x64\xe7\x95\x26\xaf\x8c\x86\x78\x20\x4b\xc2\xb3\xc5\x23\xd9\xbd\xd2\xbb\xd1\xbb\x8b\xf1\x0f\xbf\x76\x7f\x49\xce\xe7\x95\x91\xea\x5e\xb1\xcc\x4b\x96\x3b\xb6\x50\xda\x73\xf3\xfd\x79\xeb\x75\xba\xfa\xbc\x48\xef\xf0\x29\xbe\xc3\x48\xc9\x49\x77\xd6\x38\x18\xcf\xbf\x37\x5c\x25\xcb\xf8\x16\xe1\x89\x8a\x79\xb1\xcf\x3b\xea\xfc\xa5\x14\xb9\x92\x21\x36\xc9\x49\x52\xdb\x9b\x55\xf2\x11\x85\xb7\xcc\x18\x75\x0c\x27\x2f\xf6\x9a\x40\xc9\x26\xe6\x2c\xc2\xcd\x97\xba\x36\xd6\x3b\x84\x8e\x4b\x16\x1e\x11\xee\xad\xa9\x7e\x1f\xe6\xf0\xf4\xc0\x96\x41\xce\xb1\xc7\x7b\x7c\x80\xb1\x92\x2d\x8a\xfd\xab\x23\x42\x44\xb3\x3e\x14\x2d\x81\xd6\xf3\xbc\xee\xbf\x54\x6e\x1d\x4e\x96\x9d\x45\x48\xb9\x32\x8f\x0c\xa5\x25\x7f\x85\xe5\xba\x24\xc1\xb2\x29\x40\x45\xb3\x1e\xcd\x82\x65\xba\xb9\x1e\x10\x35\xfc\x43\x76\xae\x36\xda\x19\xfb\x8f\xe9\x1d\x5d\xff\x8a\xdf\xd1\xe3\x7f\x10\x3c\x8e\x6a\x18\x76\x1f\x86\xa5\x79\xd2\xc1\x41\xde\xff\x30\x08\x72\x82\x24\xf7\xff\x69\x9d\x33\x1b\x7c\x8d\xc6\xf3\xa1\xf7\xe0\x55\xe4\x03\x83\x3d\xa3\x38\xe3\x84\x06\x85\xeb\xbb\x11\xf3\x20\xf8\x16\x00\x00\xff\xff\x84\x8f\x50\xb2\x94\x05\x00\x00") + +func migrations62_claimable_balance_claimantsSqlBytes() ([]byte, error) { + return bindataRead( + _migrations62_claimable_balance_claimantsSql, + "migrations/62_claimable_balance_claimants.sql", + ) +} + +func migrations62_claimable_balance_claimantsSql() (*asset, error) { + bytes, err := migrations62_claimable_balance_claimantsSqlBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "migrations/62_claimable_balance_claimants.sql", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} + a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x88, 0x4b, 0xc2, 0xa2, 0x4c, 0x82, 0x68, 0xe8, 0xa8, 0x71, 0x70, 0x49, 0x44, 0x59, 0x8f, 0xd7, 0xa1, 0xc8, 0x31, 0x86, 0xf1, 0x5b, 0x30, 0x67, 0xdd, 0x15, 0x2c, 0x54, 0xfe, 0xe4, 0xe7, 0x3e}} + return a, nil +} + +var _migrations63_add_contract_id_to_asset_statsSql = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xd2\xd5\x55\xd0\xce\xcd\x4c\x2f\x4a\x2c\x49\x55\x08\x2d\xe0\xe2\x72\xf4\x09\x71\x0d\x52\x08\x71\x74\xf2\x71\x55\x48\xad\x28\x88\x4f\x2c\x2e\x4e\x2d\x89\x2f\x2e\x49\x2c\x29\x56\x70\x74\x71\x51\x70\xf6\xf7\x09\xf5\xf5\x53\x48\xce\xcf\x2b\x29\x4a\x4c\x2e\x89\xcf\x4c\x51\x70\x8a\x0c\x71\x75\x54\x08\xf5\xf3\x0c\x0c\x75\xb5\xe6\xe2\x42\x36\xd1\x25\xbf\x3c\x0f\xbf\x99\x2e\x41\xfe\x01\x58\x0c\xb5\xe6\x02\x04\x00\x00\xff\xff\xbd\x18\xbe\x65\x99\x00\x00\x00") + +func migrations63_add_contract_id_to_asset_statsSqlBytes() ([]byte, error) { + return bindataRead( + _migrations63_add_contract_id_to_asset_statsSql, + "migrations/63_add_contract_id_to_asset_stats.sql", + ) +} + +func migrations63_add_contract_id_to_asset_statsSql() (*asset, error) { + bytes, err := migrations63_add_contract_id_to_asset_statsSqlBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "migrations/63_add_contract_id_to_asset_stats.sql", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} + a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x90, 0x94, 0x67, 0x8, 0x3e, 0x54, 0xa5, 0x39, 0xb0, 0xc3, 0x25, 0xac, 0xfc, 0xfe, 0x8b, 0xa2, 0x5, 0xae, 0x8e, 0x79, 0xa9, 0x74, 0x65, 0x9f, 0xb4, 0xca, 0x55, 0xae, 0xf4, 0x4e, 0xc5, 0xbb}} + return a, nil +} + +var _migrations64_add_payment_flag_history_opsSql = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xd2\xd5\x55\xd0\xce\xcd\x4c\x2f\x4a\x2c\x49\x55\x08\x2d\xe0\xe2\x72\xf4\x09\x71\x0d\x52\x08\x71\x74\xf2\x71\x55\xc8\xc8\x2c\x2e\xc9\x2f\xaa\x8c\xcf\x2f\x48\x2d\x4a\x2c\xc9\xcc\xcf\x2b\x56\x70\x74\x71\x51\xc8\x2c\x8e\x2f\x48\xac\xcc\x4d\xcd\x2b\x51\x48\xca\xcf\xcf\x49\x4d\xcc\xb3\xe6\xe2\x42\x36\xc7\x25\xbf\x3c\x8f\xa0\x49\x2e\x41\xfe\x01\x0a\xce\xfe\x3e\xa1\xbe\x7e\x48\x26\x5a\x73\x01\x02\x00\x00\xff\xff\xcc\xf9\x34\xcb\x91\x00\x00\x00") + +func migrations64_add_payment_flag_history_opsSqlBytes() ([]byte, error) { + return bindataRead( + _migrations64_add_payment_flag_history_opsSql, + "migrations/64_add_payment_flag_history_ops.sql", + ) +} + +func migrations64_add_payment_flag_history_opsSql() (*asset, error) { + bytes, err := migrations64_add_payment_flag_history_opsSqlBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "migrations/64_add_payment_flag_history_ops.sql", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} + a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xa7, 0x6d, 0xb6, 0x2e, 0x50, 0x40, 0x71, 0x1f, 0x97, 0xd9, 0xd9, 0xfb, 0xcf, 0x45, 0x0, 0xd1, 0x93, 0x79, 0x5d, 0x70, 0xb3, 0x2e, 0x31, 0x44, 0x13, 0x63, 0xdf, 0x70, 0xd9, 0xc9, 0x6b, 0x43}} + return a, nil +} + +var _migrations65_drop_payment_indexSql = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x8c\xcf\xc1\x4a\xc3\x40\x10\xc6\xf1\x7b\x9e\xe2\xa3\x57\x8d\xeb\xc1\x0a\xea\x35\x15\x72\x51\xb1\x0a\xbd\x2d\xdb\x66\x48\x06\x9a\x99\x65\x67\x96\x9a\xb7\x17\x5b\xf0\xdc\x07\xf8\x7e\x7c\xff\xb6\xc5\xcd\xcc\x63\x49\x4e\xf8\xce\x4d\xd3\xb6\x60\x19\xe8\x27\x4e\x6c\xae\x65\x89\x9a\xa9\x24\x67\x15\x8b\x2a\x91\x2d\xe6\xb4\xcc\x24\x8e\x53\x32\xa4\x61\xa0\x01\x2c\xb8\x10\xac\x82\xc7\x07\xec\xab\x83\x1d\x5e\x8b\x18\xb4\xfa\x1f\xea\x13\x5d\xe0\xf3\x4e\xd4\x21\x74\x20\xb3\x54\x96\x5b\x18\x11\x26\xf7\x6c\xcf\x21\x8c\xec\x53\xdd\xdf\x1d\x74\x0e\xe6\x74\x3c\xa6\x12\x46\x0d\x6c\x56\xc9\xc2\xfa\x7e\xfd\xd4\x74\x9f\xef\x1f\xe8\xdf\xba\xcd\x0e\xfd\x2b\x36\xbb\x7e\xfb\xb5\xc5\xea\xba\xd7\xab\x97\x73\xe2\x7f\x72\xa7\x27\x69\x7e\x03\x00\x00\xff\xff\x15\xa3\x47\xcb\x04\x01\x00\x00") + +func migrations65_drop_payment_indexSqlBytes() ([]byte, error) { + return bindataRead( + _migrations65_drop_payment_indexSql, + "migrations/65_drop_payment_index.sql", + ) +} + +func migrations65_drop_payment_indexSql() (*asset, error) { + bytes, err := migrations65_drop_payment_indexSqlBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "migrations/65_drop_payment_index.sql", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} + a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xf2, 0xe4, 0xb0, 0xad, 0x98, 0x6a, 0x5, 0xb8, 0x1e, 0xbb, 0xf6, 0x3d, 0x63, 0x93, 0xd5, 0x45, 0x29, 0xd7, 0x23, 0x23, 0x9b, 0xfc, 0x27, 0xb5, 0x8f, 0x37, 0x20, 0x66, 0x6c, 0x97, 0x45, 0x4a}} + return a, nil +} + +var _migrations66_contract_asset_statsSql = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x7c\x91\x41\x6b\xf2\x40\x10\x86\xef\xf9\x15\x2f\x9e\x94\xcf\xc0\xd7\x7a\xa9\x78\x8a\x35\x14\x5b\x9b\x48\x8c\x50\x4f\xcb\x66\x33\xc6\xa1\xba\x91\xdd\x91\xd6\x7f\x5f\x24\x44\x0b\x56\xf7\x3a\xcf\xcc\xf3\xce\x4e\x18\xe2\xdf\x8e\x2b\xa7\x85\xb0\xdc\x07\xcf\x59\x1c\xe5\x31\xf2\x68\x3c\x8b\x61\x6a\x2b\x4e\x1b\x51\xda\x7b\x12\xe5\x45\x8b\x47\x37\xc0\xe9\x9d\x6b\x5c\x62\xbc\xca\xe3\x08\xf3\x6c\xfa\x1e\x65\x2b\xbc\xc5\xab\x7e\xc3\x9c\x1a\xd0\xbc\xd7\x45\x9a\x8c\x91\xa4\x39\x92\xe5\x6c\x16\xf4\x46\xc1\x5d\x55\xa1\xb7\xda\x1a\x3a\xdb\x3e\xe9\xa8\x36\xda\x6f\x6e\xaa\x9a\xb6\xeb\x50\xad\xb1\xc5\x76\xf5\xc1\xb6\x99\xec\x61\x47\x8e\x4d\x77\x30\xec\xff\xef\x5d\x48\x84\x21\x06\x43\x94\x5c\xb1\x78\xb0\x87\x3f\xac\xd7\x6c\x98\xac\x60\x5d\x3b\x68\x3c\x3c\x3e\xa1\x60\x01\x5b\xa1\x8a\x5c\x33\x9a\xbe\xf7\xec\xb4\x70\x6d\xd5\x96\xca\x8a\x5c\x5b\xfe\x73\xeb\x69\x32\x89\x3f\xd0\xb9\xb1\xb6\x2a\x8e\xea\x32\xaf\x83\x34\xb9\xf9\x41\xcb\xc5\x34\x79\x41\x21\x8e\x08\xdd\xab\x0c\x27\xe3\xef\x0b\x4f\xea\x2f\x1b\x4c\xb2\x74\x7e\xef\xc2\x46\x7b\xa3\x4b\x1a\xdd\x01\xcf\xfa\x96\xfd\x09\x00\x00\xff\xff\x78\xde\xe2\x11\x47\x02\x00\x00") + +func migrations66_contract_asset_statsSqlBytes() ([]byte, error) { + return bindataRead( + _migrations66_contract_asset_statsSql, + "migrations/66_contract_asset_stats.sql", + ) +} + +func migrations66_contract_asset_statsSql() (*asset, error) { + bytes, err := migrations66_contract_asset_statsSqlBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "migrations/66_contract_asset_stats.sql", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} + a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x2a, 0x9a, 0xab, 0xd3, 0x1d, 0x20, 0x82, 0x82, 0x64, 0xb1, 0x7e, 0x9f, 0xcb, 0xb5, 0xe6, 0x2b, 0xc2, 0x72, 0x8e, 0x1e, 0x58, 0x23, 0xc, 0xfd, 0x25, 0xb3, 0xe7, 0x9, 0x89, 0x43, 0x3e, 0x15}} + return a, nil +} + +var _migrations67_remove_unused_indexesSql = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xa4\x55\xc9\x6e\xdb\x30\x10\xbd\xe7\x2b\x78\x8b\x8d\xc6\xa7\xdc\x12\x34\x40\x5b\xab\xad\x2f\x76\xeb\x05\xcd\x8d\xa0\xc4\xb1\xc5\x46\xe2\x08\xe4\x28\x8d\xff\xbe\x90\xe5\x85\x92\x45\x2d\xc9\x4d\x10\xdf\x9b\x37\x9c\xe5\x71\x32\x61\x9f\x52\xb5\x33\x82\x80\x6d\x32\xa6\x91\x8c\xd0\x56\x44\xa4\x50\xdf\xdc\x4c\x97\x8b\x5f\x6c\x36\x9f\x06\xcf\x6c\xf6\x9d\x05\xcf\xb3\xd5\x7a\xc5\x44\x14\x61\xae\xc9\xf2\x18\x53\xe0\x12\x53\xa1\xf4\x63\x07\x54\xe9\x6d\x22\x8a\x98\x5c\x82\x25\xa5\x0f\xdf\x3e\x92\xb5\x40\x3c\xdc\x73\x65\x6d\x0e\xc6\x83\x8a\x12\xa1\x52\x11\x8a\x30\x01\x1e\x8a\x44\xe8\x08\x6c\x41\x2a\xff\x6b\xb2\x1e\x5e\x4c\x46\x72\x52\x29\xf0\x04\xf1\x25\xcf\x3c\x30\xa5\x25\xbc\xf1\x58\x59\x42\xb3\xe7\xb0\xdd\x42\x44\x96\xa3\xe6\xb4\xcf\xa0\x17\x27\x01\xb9\x03\x73\xe0\x44\x09\x5a\x90\x5c\xd0\x50\xa2\x4a\x33\x34\x04\x86\xbf\x82\xb1\xfe\x8a\x79\xf9\xe5\x27\x8f\x85\x8d\x87\x52\x33\x03\xaf\x0a\x73\x3b\x38\x06\x66\x60\xca\x56\x1f\x5b\xe4\x36\xa8\xb8\x93\xf4\xb5\xc6\x13\x67\x58\xd9\x9d\xf9\x1d\x9c\x00\x19\x21\xe1\xdc\xec\x70\xcf\xd1\x48\x30\x3c\x44\x7c\xf1\x32\x72\x4b\x3c\x51\xba\x1c\xbe\xd3\xc4\xde\xb8\x6b\x35\xc5\x7f\xba\xb6\x58\xdf\x96\xc1\x97\x75\x70\x89\x36\x5f\xac\xdb\xb6\x8b\x2d\xe6\xe7\xff\x6c\xb3\x9a\xcd\x7f\xb0\xaf\xeb\x65\x10\x8c\x1c\xcc\xf8\xb1\x57\xd4\xc6\x45\xf4\xc6\x6f\x44\x77\x28\x55\xb7\xb7\x08\x7d\x6a\xcd\xe1\xe8\x24\x10\x92\x01\x60\xa3\x12\x5e\x62\xdb\x03\x77\x2e\x7c\x21\x75\xdd\xf1\xa3\xdc\x4e\xe9\xd1\x05\xf9\xd7\xa2\x0e\x79\x26\x28\xe6\x98\xd9\x76\xdd\xba\x61\xb8\x37\x3a\x0c\x4c\xb5\x64\xc7\x75\x39\xaf\x7c\x7b\xf0\x56\x9b\x71\x95\x8e\x47\xd5\xe2\x15\xa0\x21\xf1\x9b\x2c\xc9\x15\x39\x9e\x57\x45\xde\x75\x93\x16\x0f\xeb\x14\xac\x13\x2e\xba\x9b\xf9\xec\xf7\x66\xa0\xbc\x63\x5f\x9d\xca\x0e\xf6\x63\xa2\x4d\xe6\xd9\xa9\xde\x44\x7a\x47\x1a\x3d\xfc\xd7\x4d\xa5\x0d\x5e\xcd\xef\x9a\xa1\x24\xbb\x3b\x07\xba\xa2\x73\x25\x87\x8c\xcc\xb5\xdf\x37\xa6\xd9\xba\x02\xbd\x8b\xd4\xeb\x95\xa8\x6d\x7a\x0b\xa1\xb9\x50\x2e\xe7\x83\xa5\x6a\x79\x99\x3a\x5d\x62\x34\x92\x40\x42\x25\x96\x4d\x9e\x9e\xd8\xad\xc5\x44\x96\x56\x7c\x28\xf2\xed\xc3\x03\xc1\x1b\x8d\xc7\x77\xcc\x0f\x8c\x50\xf6\x03\x96\x46\xee\x87\x86\x98\xef\x62\xea\x25\x5f\x81\xb6\x27\x50\x81\xd6\x52\x18\xb3\x3f\x3f\x83\x65\x50\x4e\x0a\xfb\xcc\xee\xef\xbb\x2a\xdd\xf0\xa2\x17\x35\x76\x0e\x2a\x86\x5f\x7b\xc1\xfe\x07\x00\x00\xff\xff\x6e\x06\xca\xb9\x51\x0b\x00\x00") + +func migrations67_remove_unused_indexesSqlBytes() ([]byte, error) { + return bindataRead( + _migrations67_remove_unused_indexesSql, + "migrations/67_remove_unused_indexes.sql", + ) +} + +func migrations67_remove_unused_indexesSql() (*asset, error) { + bytes, err := migrations67_remove_unused_indexesSqlBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "migrations/67_remove_unused_indexes.sql", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} + a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x99, 0x6, 0xc9, 0x3, 0x51, 0x52, 0x77, 0x87, 0x7f, 0x5, 0xe2, 0xdd, 0xd2, 0x49, 0xd0, 0xd1, 0x1b, 0x9a, 0x9, 0x2f, 0x10, 0xb7, 0x68, 0x44, 0xd1, 0x12, 0xce, 0x43, 0x50, 0x2e, 0xbd, 0xef}} + return a, nil +} + var _migrations6_create_assets_tableSql = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x6c\x90\x3d\x4f\xc3\x30\x18\x84\x77\xff\x8a\x1b\x1d\x91\x0e\x20\xe8\x92\xc9\x34\x16\x58\x18\xa7\xb8\x31\xa2\x53\xe5\x26\x16\x78\x80\x54\xb6\x11\xca\xbf\x47\xaa\x28\xf9\x50\xe6\x7b\xf4\xbc\xef\xdd\x6a\x85\xab\x4f\xff\x1e\x6c\x72\x30\x27\xb2\xd1\x9c\xd5\x1c\x35\xbb\x97\x1c\x1f\x3e\xa6\x2e\xf4\x07\x1b\xa3\x4b\x11\x94\x00\x80\x6f\xb1\xe3\x5a\x30\x89\xad\x16\xcf\x4c\xef\xf1\xc4\xf7\xc8\xcf\xd9\x19\x3c\xa4\xfe\xe4\xf0\xca\xf4\xe6\x91\x69\xba\xbe\xcd\xa0\xaa\x1a\xca\x48\x39\x86\x9a\xae\x1d\xa0\xeb\x9b\x65\xc8\xc7\xf8\xed\xc2\x3f\x76\xb7\x9e\x63\x46\x89\x17\xc3\xe9\xa0\xcc\x47\x3f\xe4\x13\x4b\x46\xb2\x82\x5c\xfa\x09\x55\xf2\xb7\xbf\xf8\xd8\x5f\xee\x54\x6a\x5e\xd9\xec\x84\x7a\xc0\x31\x05\xe7\x40\x27\xb6\x82\x90\xf1\x74\x65\xf7\xf3\x45\x4a\x5d\x6d\x97\xa7\x6b\x6c\x6c\x6c\xeb\x8a\xdf\x00\x00\x00\xff\xff\xfb\x53\x3e\x81\x6e\x01\x00\x00") func migrations6_create_assets_tableSqlBytes() ([]byte, error) { @@ -1496,6 +1664,14 @@ var _bindata = map[string]func() (*asset, error){ "migrations/58_add_index_by_id_optimization.sql": migrations58_add_index_by_id_optimizationSql, "migrations/59_remove_foreign_key_constraints.sql": migrations59_remove_foreign_key_constraintsSql, "migrations/5_create_trades_table.sql": migrations5_create_trades_tableSql, + "migrations/60_add_asset_id_indexes.sql": migrations60_add_asset_id_indexesSql, + "migrations/61_trust_lines_by_account_type_code_issuer.sql": migrations61_trust_lines_by_account_type_code_issuerSql, + "migrations/62_claimable_balance_claimants.sql": migrations62_claimable_balance_claimantsSql, + "migrations/63_add_contract_id_to_asset_stats.sql": migrations63_add_contract_id_to_asset_statsSql, + "migrations/64_add_payment_flag_history_ops.sql": migrations64_add_payment_flag_history_opsSql, + "migrations/65_drop_payment_index.sql": migrations65_drop_payment_indexSql, + "migrations/66_contract_asset_stats.sql": migrations66_contract_asset_statsSql, + "migrations/67_remove_unused_indexes.sql": migrations67_remove_unused_indexesSql, "migrations/6_create_assets_table.sql": migrations6_create_assets_tableSql, "migrations/7_modify_trades_table.sql": migrations7_modify_trades_tableSql, "migrations/8_add_aggregators.sql": migrations8_add_aggregatorsSql, @@ -1507,13 +1683,11 @@ var _bindata = map[string]func() (*asset, error){ // directory embedded in the file by go-bindata. // For example if you run go-bindata on data/... and data contains the // following hierarchy: -// -// data/ -// foo.txt -// img/ -// a.png -// b.png -// +// data/ +// foo.txt +// img/ +// a.png +// b.png // then AssetDir("data") would return []string{"foo.txt", "img"}, // AssetDir("data/img") would return []string{"a.png", "b.png"}, // AssetDir("foo.txt") and AssetDir("notexist") would return an error, and @@ -1603,6 +1777,14 @@ var _bintree = &bintree{nil, map[string]*bintree{ "58_add_index_by_id_optimization.sql": &bintree{migrations58_add_index_by_id_optimizationSql, map[string]*bintree{}}, "59_remove_foreign_key_constraints.sql": &bintree{migrations59_remove_foreign_key_constraintsSql, map[string]*bintree{}}, "5_create_trades_table.sql": &bintree{migrations5_create_trades_tableSql, map[string]*bintree{}}, + "60_add_asset_id_indexes.sql": &bintree{migrations60_add_asset_id_indexesSql, map[string]*bintree{}}, + "61_trust_lines_by_account_type_code_issuer.sql": &bintree{migrations61_trust_lines_by_account_type_code_issuerSql, map[string]*bintree{}}, + "62_claimable_balance_claimants.sql": &bintree{migrations62_claimable_balance_claimantsSql, map[string]*bintree{}}, + "63_add_contract_id_to_asset_stats.sql": &bintree{migrations63_add_contract_id_to_asset_statsSql, map[string]*bintree{}}, + "64_add_payment_flag_history_ops.sql": &bintree{migrations64_add_payment_flag_history_opsSql, map[string]*bintree{}}, + "65_drop_payment_index.sql": &bintree{migrations65_drop_payment_indexSql, map[string]*bintree{}}, + "66_contract_asset_stats.sql": &bintree{migrations66_contract_asset_statsSql, map[string]*bintree{}}, + "67_remove_unused_indexes.sql": &bintree{migrations67_remove_unused_indexesSql, map[string]*bintree{}}, "6_create_assets_table.sql": &bintree{migrations6_create_assets_tableSql, map[string]*bintree{}}, "7_modify_trades_table.sql": &bintree{migrations7_modify_trades_tableSql, map[string]*bintree{}}, "8_add_aggregators.sql": &bintree{migrations8_add_aggregatorsSql, map[string]*bintree{}}, diff --git a/services/horizon/internal/db2/schema/main.go b/services/horizon/internal/db2/schema/main.go index 80a4d992b8..0dce7540c8 100644 --- a/services/horizon/internal/db2/schema/main.go +++ b/services/horizon/internal/db2/schema/main.go @@ -2,14 +2,15 @@ package schema import ( "bytes" + "context" "database/sql" - "errors" "fmt" stdLog "log" "text/tabwriter" "time" migrate "github.com/rubenv/sql-migrate" + "github.com/stellar/go/support/errors" ) //go:generate go run github.com/kevinburke/go-bindata/go-bindata@v3.18.0+incompatible -nometadata -pkg schema -o bindata.go migrations/ @@ -46,6 +47,51 @@ var Migrations migrate.MigrationSource = &migrate.AssetMigrationSource{ // upward back to the current version at the start of the process. If count is // 0, a count of 1 will be assumed. func Migrate(db *sql.DB, dir MigrateDir, count int) (int, error) { + if dir == MigrateUp { + // The code below locks ingestion to apply DB migrations. This works + // for MigrateUp migrations only because it's possible that MigrateDown + // can remove `key_value_store` table and it will deadlock the process. + txConn, err := db.Conn(context.Background()) + if err != nil { + return 0, err + } + + defer txConn.Close() + + tx, err := txConn.BeginTx(context.Background(), nil) + if err != nil { + return 0, err + } + + // Unlock ingestion when done. DB migrations run in a separate DB connection + // so no need to Commit(). + defer tx.Rollback() + + // Check if table exists + row := tx.QueryRow(`select exists ( + select from information_schema.tables where table_schema = 'public' and table_name = 'key_value_store' + )`) + err = row.Err() + if err != nil { + return 0, err + } + + var tableExists bool + err = row.Scan(&tableExists) + if err != nil { + return 0, err + } + + if tableExists { + // Lock ingestion + row := tx.QueryRow("select value from key_value_store where key = 'exp_ingest_last_ledger' for update") + err = row.Err() + if err != nil { + return 0, err + } + } + } + switch dir { case MigrateUp: return migrate.ExecMax(db, "postgres", Migrations, migrate.Up, count) diff --git a/services/horizon/internal/db2/schema/migrations/54_tx_preconditions_and_account_fields.sql b/services/horizon/internal/db2/schema/migrations/54_tx_preconditions_and_account_fields.sql index 5c2a3da6ea..9ac5b03fb5 100644 --- a/services/horizon/internal/db2/schema/migrations/54_tx_preconditions_and_account_fields.sql +++ b/services/horizon/internal/db2/schema/migrations/54_tx_preconditions_and_account_fields.sql @@ -24,5 +24,7 @@ ALTER TABLE history_transactions DROP extra_signers; ALTER TABLE accounts DROP sequence_ledger; ALTER TABLE accounts DROP sequence_time; +-- we cannot restore the original type of varying(64) because there might be some +-- rows with signers that are too long. ALTER TABLE accounts_signers - ALTER COLUMN signer TYPE character varying(64); + ALTER COLUMN signer TYPE character varying(165); diff --git a/services/horizon/internal/db2/schema/migrations/60_add_asset_id_indexes.sql b/services/horizon/internal/db2/schema/migrations/60_add_asset_id_indexes.sql new file mode 100644 index 0000000000..7086c3fede --- /dev/null +++ b/services/horizon/internal/db2/schema/migrations/60_add_asset_id_indexes.sql @@ -0,0 +1,9 @@ +-- +migrate Up + +CREATE INDEX "htrd_by_counter_asset" ON history_trades USING btree (counter_asset_id); +CREATE INDEX "htrd_agg_counter_asset" ON history_trades_60000 USING btree (counter_asset_id); + +-- +migrate Down + +DROP INDEX "htrd_by_counter_asset"; +DROP INDEX "htrd_agg_counter_asset"; diff --git a/services/horizon/internal/db2/schema/migrations/61_trust_lines_by_account_type_code_issuer.sql b/services/horizon/internal/db2/schema/migrations/61_trust_lines_by_account_type_code_issuer.sql new file mode 100644 index 0000000000..91afe0ca00 --- /dev/null +++ b/services/horizon/internal/db2/schema/migrations/61_trust_lines_by_account_type_code_issuer.sql @@ -0,0 +1,9 @@ +-- +migrate Up + +CREATE INDEX "trust_lines_by_type_code_issuer_account" ON trust_lines USING btree (asset_type, asset_code, asset_issuer, account_id); +DROP INDEX "trust_lines_by_type_code_issuer"; + +-- +migrate Down + +DROP INDEX "trust_lines_by_type_code_issuer_account"; +CREATE INDEX "trust_lines_by_type_code_issuer" ON trust_lines USING btree (asset_type, asset_code, asset_issuer); diff --git a/services/horizon/internal/db2/schema/migrations/62_claimable_balance_claimants.sql b/services/horizon/internal/db2/schema/migrations/62_claimable_balance_claimants.sql new file mode 100644 index 0000000000..140a721575 --- /dev/null +++ b/services/horizon/internal/db2/schema/migrations/62_claimable_balance_claimants.sql @@ -0,0 +1,31 @@ +-- +migrate Up + +CREATE TABLE claimable_balance_claimants ( + id TEXT NOT NULL, -- ClaimableBalanceID in base64 + destination character varying(56) NOT NULL, + last_modified_ledger integer NOT NULL, + PRIMARY KEY (id, destination) +); + +CREATE INDEX "claimable_balance_claimants_by_destination_last_modified_ledger_id" ON claimable_balance_claimants USING btree (destination, last_modified_ledger, id); + +/* Supports "select * from claimable_balances where asset = ? order by last_modified_ledger, id" */ +CREATE INDEX "claimable_balances_by_asset_last_modified_ledger_id" ON claimable_balances USING btree (asset, last_modified_ledger, id); +/* Remove index replaced by above */ +DROP INDEX "claimable_balances_by_asset"; + +/* Supports "select * from claimable_balances where sponsor = ? order by last_modified_ledger, id" */ +CREATE INDEX "claimable_balances_by_sponsor_last_modified_ledger_id" ON claimable_balances USING btree (sponsor, last_modified_ledger, id); +/* Remove index replaced by above */ +DROP INDEX "claimable_balances_by_sponsor"; + +-- +migrate Down + +DROP TABLE claimable_balance_claimants cascade; + +CREATE INDEX "claimable_balances_by_asset" ON claimable_balances USING btree (asset); +DROP INDEX "claimable_balances_by_asset_last_modified_ledger_id"; + +CREATE INDEX "claimable_balances_by_sponsor" ON claimable_balances USING btree (sponsor); +DROP INDEX "claimable_balances_by_sponsor_last_modified_ledger_id"; + diff --git a/services/horizon/internal/db2/schema/migrations/63_add_contract_id_to_asset_stats.sql b/services/horizon/internal/db2/schema/migrations/63_add_contract_id_to_asset_stats.sql new file mode 100644 index 0000000000..d8bf83cd2c --- /dev/null +++ b/services/horizon/internal/db2/schema/migrations/63_add_contract_id_to_asset_stats.sql @@ -0,0 +1,7 @@ +-- +migrate Up + +ALTER TABLE exp_asset_stats ADD COLUMN contract_id BYTEA UNIQUE; + +-- +migrate Down + +ALTER TABLE exp_asset_stats DROP COLUMN contract_id; diff --git a/services/horizon/internal/db2/schema/migrations/64_add_payment_flag_history_ops.sql b/services/horizon/internal/db2/schema/migrations/64_add_payment_flag_history_ops.sql new file mode 100644 index 0000000000..ad19f441fe --- /dev/null +++ b/services/horizon/internal/db2/schema/migrations/64_add_payment_flag_history_ops.sql @@ -0,0 +1,7 @@ +-- +migrate Up + +ALTER TABLE history_operations ADD is_payment boolean; + +-- +migrate Down + +ALTER TABLE history_operations DROP COLUMN is_payment; diff --git a/services/horizon/internal/db2/schema/migrations/65_drop_payment_index.sql b/services/horizon/internal/db2/schema/migrations/65_drop_payment_index.sql new file mode 100644 index 0000000000..325719a284 --- /dev/null +++ b/services/horizon/internal/db2/schema/migrations/65_drop_payment_index.sql @@ -0,0 +1,7 @@ +-- +migrate Up + +-- index_history_operations_on_is_payment was added in migration 64 but it turns out +-- the index was not necessary, see https://github.com/stellar/go/issues/5059 +DROP INDEX IF EXISTS "index_history_operations_on_is_payment"; + +-- +migrate Down diff --git a/services/horizon/internal/db2/schema/migrations/66_contract_asset_stats.sql b/services/horizon/internal/db2/schema/migrations/66_contract_asset_stats.sql new file mode 100644 index 0000000000..c36b88dc71 --- /dev/null +++ b/services/horizon/internal/db2/schema/migrations/66_contract_asset_stats.sql @@ -0,0 +1,18 @@ +-- +migrate Up +CREATE TABLE contract_asset_stats ( + contract_id BYTEA PRIMARY KEY, + stat JSONB NOT NULL +); + +CREATE TABLE contract_asset_balances ( + key_hash BYTEA PRIMARY KEY, + asset_contract_id BYTEA NOT NULL, + amount numeric(39,0) NOT NULL, -- 39 digits is sufficient for a 128 bit integer + expiration_ledger integer NOT NULL +); + +CREATE INDEX "contract_asset_balances_by_expiration" ON contract_asset_balances USING btree (expiration_ledger); + +-- +migrate Down +DROP TABLE contract_asset_stats cascade; +DROP TABLE contract_asset_balances cascade; \ No newline at end of file diff --git a/services/horizon/internal/db2/schema/migrations/67_remove_unused_indexes.sql b/services/horizon/internal/db2/schema/migrations/67_remove_unused_indexes.sql new file mode 100644 index 0000000000..3b9584c7ab --- /dev/null +++ b/services/horizon/internal/db2/schema/migrations/67_remove_unused_indexes.sql @@ -0,0 +1,34 @@ +-- +migrate Up notransaction + +DROP INDEX IF EXISTS accounts_home_domain; +DROP INDEX IF EXISTS accounts_inflation_destination; +DROP INDEX IF EXISTS asset_by_issuer; +DROP INDEX IF EXISTS claimabable_balances_by_claimants; +DROP INDEX IF EXISTS htrd_time_lookup; +DROP INDEX IF EXISTS index_history_effects_on_type; +DROP INDEX IF EXISTS index_history_ledgers_on_closed_at; +DROP INDEX IF EXISTS index_history_ledgers_on_importer_version; +DROP INDEX IF EXISTS index_history_ledgers_on_ledger_hash; +DROP INDEX IF EXISTS index_history_ledgers_on_previous_ledger_hash; +DROP INDEX IF EXISTS index_history_operation_claimable_balances_on_ids; +DROP INDEX IF EXISTS index_history_operations_on_type; +DROP INDEX IF EXISTS index_history_transaction_claimable_balances_on_ids; +DROP INDEX IF EXISTS trade_effects_by_order_book; +DROP INDEX IF EXISTS trust_lines_by_issuer; + +-- +migrate Down notransaction +CREATE INDEX IF NOT EXISTS accounts_home_domain ON accounts USING BTREE(home_domain); +CREATE INDEX IF NOT EXISTS accounts_inflation_destination ON accounts USING BTREE(inflation_destination); +CREATE INDEX IF NOT EXISTS asset_by_issuer ON history_assets USING btree (asset_issuer); +CREATE INDEX IF NOT EXISTS claimabable_balances_by_claimants ON claimable_balances USING gin(claimants jsonb_path_ops); +CREATE INDEX IF NOT EXISTS htrd_time_lookup ON history_trades USING BTREE(ledger_closed_at); +CREATE INDEX IF NOT EXISTS index_history_effects_on_type ON history_effects USING btree (type); +CREATE INDEX IF NOT EXISTS index_history_ledgers_on_closed_at ON history_ledgers USING btree (closed_at); +CREATE INDEX IF NOT EXISTS index_history_ledgers_on_importer_version ON history_ledgers USING btree (importer_version); +CREATE UNIQUE INDEX IF NOT EXISTS index_history_ledgers_on_ledger_hash ON history_ledgers USING btree (ledger_hash); +CREATE UNIQUE INDEX IF NOT EXISTS index_history_ledgers_on_previous_ledger_hash ON history_ledgers USING btree (previous_ledger_hash); +CREATE UNIQUE INDEX IF NOT EXISTS index_history_operation_claimable_balances_on_ids ON history_operation_claimable_balances USING btree (history_operation_id , history_claimable_balance_id); +CREATE INDEX IF NOT EXISTS index_history_operations_on_type ON history_operations USING btree (type); +CREATE UNIQUE INDEX IF NOT EXISTS index_history_transaction_claimable_balances_on_ids ON history_transaction_claimable_balances USING btree (history_transaction_id , history_claimable_balance_id); +CREATE INDEX IF NOT EXISTS trade_effects_by_order_book ON history_effects USING btree (((details ->> 'sold_asset_type'::text)), ((details ->> 'sold_asset_code'::text)), ((details ->> 'sold_asset_issuer'::text)), ((details ->> 'bought_asset_type'::text)), ((details ->> 'bought_asset_code'::text)), ((details ->> 'bought_asset_issuer'::text))) WHERE (type = 33); +CREATE INDEX IF NOT EXISTS trust_lines_by_issuer ON trust_lines USING BTREE(asset_issuer); diff --git a/services/horizon/internal/docs/GUIDE_FOR_DEVELOPERS.md b/services/horizon/internal/docs/GUIDE_FOR_DEVELOPERS.md new file mode 100644 index 0000000000..8236551215 --- /dev/null +++ b/services/horizon/internal/docs/GUIDE_FOR_DEVELOPERS.md @@ -0,0 +1,241 @@ +# Horizon Development Guide + +This document describes how to build Horizon from source, so that you can test and edit the code locally to develop bug fixes and new features. + +## Dependencies +- A [Unix-like](https://en.wikipedia.org/wiki/Unix-like) operating system with the common core commands (cp, tar, mkdir, bash, etc.) +- Go (this repository is officially supported on the last [two releases of Go](https://go.dev/doc/devel/release)) +- [Git](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git) (to check out Horizon's source code) +- [mercurial](https://www.mercurial-scm.org/) (needed for `go-dep`) +- [Docker](https://www.docker.com/products/docker-desktop) + +## The Go Monorepo +All the code for Horizon resides in our Go monorepo. +```bash +git clone https://github.com/go.git +``` +If you want to contribute to the project, consider forking the repository and cloning the fork instead. + +## Getting Started with Running Horizon +The [start.sh](/services/horizon/docker/start.sh) script builds horizon from current source, and then runs docker-compose to start the docker containers with runtime configs for horizon, postgres, and optionally core if the optional `standalone` network parameter was included. +The script takes one optional parameter which configures the Stellar network used by the docker containers. If no parameter is supplied, the containers will run on the Stellar test network. Read more about the public and private networks in the [public documentation](https://developers.stellar.org/docs/fundamentals-and-concepts/testnet-and-pubnet#testnet) + +`./start.sh pubnet` will run the containers on the Stellar public network. + +`./start.sh standalone` will run the containers on a private standalone Stellar network. + +`./start.sh testnet` will run the containers on the Stellar test network. + +The following ports will be exposed: +- Horizon: **8000** +- Horizon-Postgres: **5432** +- Stellar-Core (If `standalone` specified): **11626** +- Stellar-Core-Postgres (If `standalone` specified): **5641** + +Note that when you switch between different networks you will need to clear the Stellar Core and Stellar Horizon databases. You can wipe out the databases by running `docker-compose down --remove-orphans -v`. + +This script is helpful to spin up the services quickly and play around with them. However, for code development it's important to build and install everything locally + +## Developing Horizon Locally +We will now configure a development environment to run Horizon service locally without Docker. + +### Building Stellar Core +Horizon requires an instance of stellar-core binary on the same host. This is referred to as the `Captive Core`. Since, we are running horizon for dev purposes, we recommend considering two approaches to get the stellar-core binary, if saving time is top priority and your development machine is on a linux debian o/s, then consider installing the debian package, otherwise the next option available is to compile the core source directly to binary on your machine, refer to [INSTALL.md](https://github.com/stellar/stellar-core/blob/master/INSTALL.md) file for the instructions on both approaches. + +### Building Horizon + +1. Change to the horizon services directory - `cd go/services/horizon/`. +2. Compile the Horizon binary: `go build -o stellar-horizon && go install`. You should see the resulting `stellar-horizon` executable in `go/services/horizon`. +3. Add the executable to your PATH in your `~/.bashrc` or equivalent, for easy access: `export PATH=$PATH:{absolute-path-to-horizon-folder}` + +Open a new terminal. Confirm everything worked by running `stellar-horizon --help` successfully. You should see an informative message listing the command line options supported by Horizon. + +### Database Setup + +Horizon uses a Postgres database backend to record information ingested from an associated Stellar Core. The unit and integration tests will also attempt to reference a Postgres db server at ``localhost:5432`` with trust auth method enabled by default for ``postgres`` user. You can either install the server locally or run any type of docker container that hosts the database server. We recommend using the [docker-compose.yml](/services/horizon/docker/docker-compose.yml) file in the ``docker`` folder: +```bash +docker-compose -f ./docker/docker-compose.yml up horizon-postgres +``` +This starts a Horizon Postgres docker container and exposes it on the port 5432. Note that while Horizon will run locally, it's PostgresQL db will run in docker. + +To shut down all docker containers and free up resources, run the following command: +```bash +docker-compose -f ./docker/docker-compose.yml down +``` + +### Run tests +At this point you should be able to run Horizon's unit tests: +```bash +cd go/services/horizon/ +go test ./... +``` + +To run the integration tests, you need to set some environment variables: + +```bash +export HORIZON_INTEGRATION_TESTS_ENABLED=true +export HORIZON_INTEGRATION_TESTS_CORE_MAX_SUPPORTED_PROTOCOL=19 +export HORIZON_INTEGRATION_TESTS_DOCKER_IMG=stellar/stellar-core:19.11.0-1323.7fb6d5e88.focal +go test -race -timeout 25m -v ./services/horizon/internal/integration/... +``` +Note that this will also require a Postgres instance running on port 5432 either locally or exposed through a docker container. Also note that the ``POSTGRES_HOST_AUTH_METHOD`` has been enabled. + +### Setup Debug Configuration in IDE + +#### Code Debug +Add a debug configuration in your IDE to attach a debugger to the local Horizon process and set breakpoints in your code. Here is an example configuration for VS Code: + +```json + { + "name": "Horizon Debugger", + "type": "go", + "request": "launch", + "mode": "debug", + "program": "${workspaceRoot}/services/horizon/main.go", + "env": { + "DATABASE_URL": "postgres://postgres@localhost:5432/horizon?sslmode=disable", + "CAPTIVE_CORE_CONFIG_APPEND_PATH": "./services/horizon/internal/configs/captive-core-testnet.cfg", + "HISTORY_ARCHIVE_URLS": "https://history.stellar.org/prd/core-testnet/core_testnet_001,https://history.stellar.org/prd/core-testnet/core_testnet_002", + "NETWORK_PASSPHRASE": "Test SDF Network ; September 2015", + "PER_HOUR_RATE_LIMIT": "0" + }, + "args": [] + } +``` +If all is well, you should see ingest logs written to standard out. You can read more about configuring the different environment variables in [Configuring](https://developers.stellar.org/docs/run-api-server/configuring) section of our public documentation. + +#### Test Debug +You can also use a similar configuration to debug the integration and unit tests. For e.g. here is a configuration for debugging the ```TestFilteringAccountWhiteList``` integration test. +```json +{ + "name": "Debug Test Function", + "type": "go", + "request": "launch", + "mode": "test", + "program": "${workspaceRoot}/services/horizon/internal/integration", + "env": { + "HORIZON_INTEGRATION_TESTS_ENABLED": "true", + "HORIZON_INTEGRATION_TESTS_CORE_MAX_SUPPORTED_PROTOCOL": "19", + "HORIZON_INTEGRATION_TESTS_DOCKER_IMG": "stellar/stellar-core:19.11.0-1323.7fb6d5e88.focal" + }, + "args": [ + "-test.run", + "TestFilteringAccountWhiteList", + "-test.timeout", + "5m", + "./..." + ], + "showLog": true +} +``` + +## Testing Horizon API using Stellar Laboratory + +You can test your Horizon instance with a query like: `http://localhost:8000/transactions?limit=10&order=asc`. However, it's much easier to use the [Stellar Laboratory](https://www.stellar.org/laboratory/) to craft other queries to try out. Select `Custom` Horizon URL and enter `http://localhost:8000`. + +Read about the available endpoints and see examples in the [Horizon API reference](https://www.stellar.org/developers/horizon/reference/). + +# **Notes for Developers** + +This section contains additional information related to the development of Horizon. + +## Configuring a Standalone Stellar-Core + +By default, the [docker-compose.yml](/services/horizon/docker/docker-compose.yml) will configure Horizon with captive core ingestion to use the test network. + +To run the containers on a private stand-alone network, run `./start.sh standalone`. +When you run Stellar Core on a stand-alone network, a root account will be created by default. It will have a balance of 100 billion Lumens and the following key pair: +``` +Root Public Key: GBZXN7PIRZGNMHGA7MUUUF4GWPY5AYPV6LY4UV2GL6VJGIQRXFDNMADI +Root Secret Key: SC5O7VZUXDJ6JBDSZ74DSERXL7W3Y5LTOAMRF7RQRL3TAGAPS7LUVG3L +``` +When running Horizon on a private stand-alone network, Horizon will not start ingesting until Stellar Core creates its first history archive snapshot. Stellar Core creates snapshots every 64 ledgers, which means ingestion will be delayed until ledger 64. + +### Accelerated network for testing + +You can increase the speed of tests by adding `ARTIFICIALLY_ACCELERATE_TIME_FOR_TESTING=true` in the [captive-core-standalone.cfg](/services/horizon/docker/captive-core-standalone.cfg). + +And finally setting the checkpoint frequency for horizon: +```bash +export CHECKPOINT_FREQUENCY=8 +``` + +This modification causes the standalone network to close ledgers every 1 second and create a checkpoint once every 8 ledgers, +deviating from the default timing of ledger closing after 5 seconds and creating a checkpoint once every 64 ledgers. Please note that +this customization is only applicable when running a standalone network, as it requires changes to the captive-core configuration. + +## Using a specific version of Stellar Core + +By default, the Docker Compose file is configured to use version 19 of Protocol and Stellar Core. You can specify optional environment variables from the command shell for stating version overrides for either the docker-compose or start.sh invocations. +```bash +export PROTOCOL_VERSION="19" +export CORE_IMAGE="stellar/stellar-core:19.11.0-1323.7fb6d5e88.focal" +export STELLAR_CORE_VERSION="19.11.0-1323.7fb6d5e88.focal" +``` + +Example: + +Runs Stellar Protocol and Core version 19, for any mode of testnet, standalone, pubnet +```bash +PROTOCOL_VERSION=19 CORE_IMAGE=stellar/stellar-core:19.11.0-1323.7fb6d5e88.focal STELLAR_CORE_VERSION=19.11.0-1323.7fb6d5e88.focal ./start.sh [standalone|pubnet] +``` + +## **Logging** + +All logging infrastructure is implemented using the `go/support/log` package. This package provides "level-based" logging: Each logging statement has a severity, one of "Debug", "Info", "Warn", "Error" or "Panic". The Horizon server has a configured level "filter", specified either using the `--log-level` command line flag or the `LOG_LEVEL` environment variable. When a logging statement is executed, the statements declared severity is checked against the filter and will only be emitted if the severity of the statement is equal or higher severity than the filter. + +In addition, the logging subsystem has support for fields: Arbitrary key-value pairs that will be associated with an entry to allow for filtering and additional contextual information. + +### **Making logging statements** + +Assuming that you've imported the log package, making a simple logging call is just: + +```go + +log.Info("my log line") +log.Infof("I take a %s", "format string") +``` + +Adding fields to a statement happens with a call to `WithField` or `WithFields` + +```go +log.WithField("pid", 1234).Warn("i'm scared") + +log.WithFields(log.F{ + "some_field": 123, + "second_field": "hello", +}).Debug("here") +``` + +The return value from `WithField` or `WithFields` is a `*log.Entry`, which you can save to emit multiple logging +statements that all share the same field. For example, the action system for Horizon attaches a log entry to `action.Log` on every request that can be used to emit log entries that have the request's id attached as a field. + +### **Logging and Context** + +The logging package in Go provides a default logger, but it may be necessary to include request-specific fields in log statements. This can be achieved by using a context parameter instead of passing a *http.Request to each subroutine. The context can be bound to a logger with log.Set and retrieved with log.Ctx(ctx) to enable logging on behalf of a server request. This approach allows for easier debugging by filtering log streams based on request IDs. The [Go blog](https://blog.golang.org/context) provides more information on using contexts. + +Here's an example of using context: + +```go + +// create a new sublogger +sub := log.WithField("val", 1) + +// bind it to a context +ctx := log.Set(context.Background(), sub) + +log.Info("no fields on this statement") +log.Ctx(ctx).Info("This statement will use the sub logger") +``` + +### **Adding migrations** +1. Add your migration to `go/services/horizon/internal/db2/schema/migrations/` using the same name nomenclature as other migrations. +2. After creating you migration, run `./gogenerate.sh` from the root folder to regenerate the code. + +### **Code Formatting** +Some basic code formatting is required for contributions. Run the following scripts included in this repo to perform these tasks. Some of this formatting can be done automatically by IDE's also: +```bash +./gofmt.sh +./govet.sh +./staticcheck.sh +``` diff --git a/services/horizon/internal/docs/HorizonWithCaptiveCore.png b/services/horizon/internal/docs/HorizonWithCaptiveCore.png deleted file mode 100644 index ef0e65aa1c..0000000000 Binary files a/services/horizon/internal/docs/HorizonWithCaptiveCore.png and /dev/null differ diff --git a/services/horizon/internal/docs/HorizonWithRemoteCaptiveCore.png b/services/horizon/internal/docs/HorizonWithRemoteCaptiveCore.png deleted file mode 100644 index ffa685cfc5..0000000000 Binary files a/services/horizon/internal/docs/HorizonWithRemoteCaptiveCore.png and /dev/null differ diff --git a/services/horizon/internal/docs/HorizonWithoutCaptiveCore.png b/services/horizon/internal/docs/HorizonWithoutCaptiveCore.png deleted file mode 100644 index 3e9cec413d..0000000000 Binary files a/services/horizon/internal/docs/HorizonWithoutCaptiveCore.png and /dev/null differ diff --git a/services/horizon/internal/docs/SDK_API_GUIDE.md b/services/horizon/internal/docs/SDK_API_GUIDE.md new file mode 100644 index 0000000000..bc8268ddb1 --- /dev/null +++ b/services/horizon/internal/docs/SDK_API_GUIDE.md @@ -0,0 +1,17 @@ +# **Horizon SDK and API Guide** + +Now, let's get familiar with Horizon's API, SDK and the tooling around them. The [API documentation](https://developers.stellar.org/api/) is particularly useful and you will find yourself consulting it often. + +Spend a few hours reading before getting your hands dirty writing code: + +- Skim through the [developer documentation](https://developers.stellar.org/docs/) in general. +- Try to understand what an [Account](https://developers.stellar.org/docs/glossary/accounts/) is. +- Try to understand what a [Ledger](https://developers.stellar.org/docs/glossary/ledger/), [Transaction](https://developers.stellar.org/docs/glossary/transactions/) and [Operation](https://developers.stellar.org/docs/glossary/operations/) is and their hierarchical nature. Make sure you understand how sequence numbers work. +- Go through the different [Operation](https://developers.stellar.org/docs/start/list-of-operations/) types. Take a look at the Go SDK machinery for the [Account Creation](https://godoc.org/github.com/stellar/go/txnbuild#CreateAccount) and [Payment](https://godoc.org/github.com/stellar/go/txnbuild#Payment) operations and read the documentation examples. +- You will use the Testnet network frequently during Horizon's development. Get familiar with [what it is and how it is useful](https://developers.stellar.org/docs/glossary/testnet/). Try to understand what [Friendbot](https://github.com/stellar/go/tree/master/services/friendbot) is. +- Read Horizon's API [introduction](https://developers.stellar.org/api/introduction/) and make sure you understand what's HAL and XDR. Also, make sure you understand how streaming responses work. +- Get familiar with Horizon's REST API endpoints. There are two type of endpoints: + - **Querying Endpoints**. They give you information about the network status. The output is based on the information obtained from Core or derived from it. These endpoints refer to resources. These resources can: + - Exist in the Stellar network. Take a look at the [endpoints associated with each resource](https://developers.stellar.org/api/resources/). + - Are abstractions which don't exist in the Stellar network but they are useful to the end user. Take a look at their [endpoints](https://developers.stellar.org/api/aggregations/). + - **Submission Endpoints**. There is only one, the [transaction submission endpoint](https://www.stellar.org/developers/horizon/reference/endpoints/transactions-create.html). You will be using it explicitly next. \ No newline at end of file diff --git a/services/horizon/TESTING_README.md b/services/horizon/internal/docs/TESTING_NOTES.md similarity index 80% rename from services/horizon/TESTING_README.md rename to services/horizon/internal/docs/TESTING_NOTES.md index c7747bccd3..42577173ce 100644 --- a/services/horizon/TESTING_README.md +++ b/services/horizon/internal/docs/TESTING_NOTES.md @@ -1,13 +1,38 @@ -# Writing effective test coverage for Horizon packages +# **Testing with Horizon** -Before discussing test development, just a brief mention of developer resoures: -- [Quickstart Guide](internal/docs/quickstart.md) -- [Developer Guide](internal/docs/developing.md) -- [Developer Notes](internal/docs/notes_for_developers.md) +Run all the Go monorepo unit tests like so (assuming you are at stellar/go, or run from stellar/go/services/horizon for just the Horizon subset): + +```bash +go test ./... +``` + +or run individual Horizon tests like so, providing the expected arguments: + +```bash +go test github.com/stellar/go/services/horizon/... +``` + +Before running integration tests, you also need to set some environment variables: +```bash +export HORIZON_INTEGRATION_TESTS_ENABLED=true +export HORIZON_INTEGRATION_TESTS_CORE_MAX_SUPPORTED_PROTOCOL=19 +export HORIZON_INTEGRATION_TESTS_DOCKER_IMG=stellar/stellar-core:19.11.0-1323.7fb6d5e88.focal +``` +Make sure to check [horizon.yml](/.github/workflows/horizon.yml) for the latest core image version. + +And then use the following command to run the Horizon integration tests: +```bash +go test -race -timeout 25m -v ./services/horizon/internal/integration/... +``` + +To run just one specific integration test, e.g. like `TestTxSub`: +```bash +go test -run TestTxsub -race -timeout 5m -v ./... +``` Authoring tests to assert coverage is key importance, to facilitate best experience for writing tests within Horizon packages, there are some conventions to be aware of: -## Best Practices +## **Best Practices** * For unit tests: * Adhere to [idiomatic go testing](https://go.dev/doc/tutorial/add-a-test) for baseline @@ -27,7 +52,7 @@ Authoring tests to assert coverage is key importance, to facilitate best experie * For integration tests, they should be located in services/horizon/integration package. Tests located in this package will only run when `HORIZON_INTEGRATION_TESTS_ENABLED=true` is present in environment. -## Leverage Scaffolding for Test Cases +## **Leverage Scaffolding for Test Cases** * Mocked DB unit tests that avoid needing a live db connection: * `db/mock_session.go` has pre-defined mocks of all standard SessionInterface. `services/horizon/internal/httpx/stream_handler_test.go` is good example of mocking out just low level db session interface where sql statements are executed. diff --git a/services/horizon/internal/docs/admin.md b/services/horizon/internal/docs/admin.md deleted file mode 100644 index f9585490c5..0000000000 --- a/services/horizon/internal/docs/admin.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -title: Horizon Administration Guide -replacement: https://developers.stellar.org/docs/run-api-server/ ---- - -Please refer to the [Developers' Documentation](https://developers.stellar.org/docs/run-api-server/) for the current deployment guide. diff --git a/services/horizon/internal/docs/captive_core.md b/services/horizon/internal/docs/captive_core.md deleted file mode 100644 index d455ff8fc5..0000000000 --- a/services/horizon/internal/docs/captive_core.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -title: Using Captive Core with Horizon -replacement: https://developers.stellar.org/docs/run-api-server/migrating/ ---- - -Please refer to the [Developers' Documentation](https://developers.stellar.org/docs/run-api-server/migrating/) for the current Captive Core migration guide. diff --git a/services/horizon/internal/docs/developing.md b/services/horizon/internal/docs/developing.md deleted file mode 100644 index 12f27eb674..0000000000 --- a/services/horizon/internal/docs/developing.md +++ /dev/null @@ -1,107 +0,0 @@ ---- -title: Horizon Development Guide ---- -## Horizon Development Guide - -This document describes how to build Horizon from source, so that you can test and edit the code locally to develop bug fixes and new features. - -If you are just starting with Horizon and want to try it out, consider the [Quickstart Guide](quickstart.md) instead. For information about administrating a Horizon instance in production, check out the [Administration Guide](admin.md). - -## Building Horizon -Building Horizon requires the following developer tools: - -- A [Unix-like](https://en.wikipedia.org/wiki/Unix-like) operating system with the common core commands (cp, tar, mkdir, bash, etc.) -- Go (this repository is officially supported on the last two releases of Go) -- [git](https://git-scm.com/) (to check out Horizon's source code) -- [mercurial](https://www.mercurial-scm.org/) (needed for `go-dep`) - -1. Set your [GOPATH](https://github.com/golang/go/wiki/GOPATH) environment variable, if you haven't already. The default `GOPATH` is `$HOME/go`. When building any Go package or application the binaries will be installed by default to `$GOPATH/bin`. -2. Clone the code into any directory you prefer: - ``` - git clone https://github.com/stellar/go - ``` - Or if you prefer to develop inside `GOPATH` check it out to `$GOPATH/src/github.com/stellar/go`: - ``` - git clone https://github.com/stellar/go $GOPATH/src/github.com/stellar/go - ``` - If developing inside `GOPATH` set the `GO111MODULE=on` environment variable to turn on Modules for managing dependencies. See the repository [README](../../../../README.md#dependencies) for more information. -3. Change to the directory where the repository is checked out. e.g. `cd go`, or if developing inside the `GOPATH`, `cd $GOPATH/src/github.com/stellar/go`. -4. Compile the Horizon binary: `go install ./services/horizon`. You should see the resulting `horizon` executable in `$GOPATH/bin`. -5. Add Go binaries to your PATH in your `bashrc` or equivalent, for easy access: `export PATH=${GOPATH//://bin:}/bin:$PATH` - -Open a new terminal. Confirm everything worked by running `horizon --help` successfully. You should see an informative message listing the command line options supported by Horizon. - -## Set up Horizon's database -Horizon uses a Postgres database backend to store test fixtures and record information ingested from an associated Stellar Core. To set this up: -1. Install [PostgreSQL](https://www.postgresql.org/). -2. Run `createdb horizon_dev` to initialise an empty database for Horizon's use. -3. Run `horizon db init --db-url postgres://localhost/horizon_dev` to install Horizon's database schema. - -### Database problems? -1. Depending on your installation's defaults, you may need to configure a Postgres DB user with appropriate permissions for Horizon to access the database you created. Refer to the [Postgres documentation](https://www.postgresql.org/docs/current/sql-createuser.html) for details. Note: Remember to restart the Postgres server after making any changes to `pg_hba.conf` (the Postgres configuration file), or your changes won't take effect! -2. Make sure you pass the appropriate database name and user (and port, if using something non-standard) to Horizon using `--db-url`. One way is to use a Postgres URI with the following form: `postgres://USERNAME:PASSWORD@localhost:PORT/DB_NAME`. -3. If you get the error `connect failed: pq: SSL is not enabled on the server`, add `?sslmode=disable` to the end of the Postgres URI to allow connecting without SSL. -If you get the error `zsh: no matches found: postgres://localhost/horizon_dev?sslmode=disable`, wrap the url with single quotes `horizon db init --db-url 'postgres://localhost/horizon_dev?sslmode=disable'` -4. If your server is responding strangely, and you've exhausted all other options, reboot the machine. On some systems `service postgresql restart` or equivalent may not fully reset the state of the server. - -## Run tests -At this point you should be able to run Horizon's unit tests: -```bash -cd $GOPATH/src/github.com/stellar/go/services/horizon -go test ./... -``` - -## Set up Stellar Core -Horizon provides an API to the Stellar network. It does this by ingesting data from an associated `stellar-core` instance. Thus, to run a full Horizon instance requires a `stellar-core` instance to be configured, up to date with the network state, and accessible to Horizon. Horizon accesses `stellar-core` through both an HTTP endpoint and by connecting directly to the `stellar-core` Postgres database. - -The simplest way to set up Stellar Core is using the [Stellar Quickstart Docker Image](https://github.com/stellar/docker-stellar-core-horizon). This is a Docker container that provides both `stellar-core` and `horizon`, pre-configured for testing. - -1. Install [Docker](https://www.docker.com/get-started). -2. Verify your Docker installation works: `docker run hello-world` -3. Create a local directory that the container can use to record state. This is helpful because it can take a few minutes to sync a new `stellar-core` with enough data for testing, and because it allows you to inspect and modify the configuration if needed. Here, we create a directory called `stellar` to use as the persistent volume: `cd $HOME; mkdir stellar` -4. Download and run the Stellar Quickstart container: - -```bash -docker run --rm -it -p "8000:8000" -p "11626:11626" -p "11625:11625" -p"8002:5432" -v $HOME/stellar:/opt/stellar --name stellar stellar/quickstart --testnet -``` - -In this example we run the container in interactive mode. We map the container's Horizon HTTP port (`8000`), the `stellar-core` HTTP port (`11626`), and the `stellar-core` peer node port (`11625`) from the container to the corresponding ports on `localhost`. Importantly, we map the container's `postgresql` port (`5432`) to a custom port (`8002`) on `localhost`, so that it doesn't clash with our local Postgres install. -The `-v` option mounts the `stellar` directory for use by the container. See the [Quickstart Image documentation](https://github.com/stellar/docker-stellar-core-horizon) for a detailed explanation of these options. - -5. The container is running both a `stellar-core` and a `horizon` instance. Log in to the container and stop Horizon: -```bash -docker exec -it stellar /bin/bash -supervisorctl -stop horizon -``` - -## Check Stellar Core status -Stellar Core takes some time to synchronise with the rest of the network. The default configuration will pull roughly a couple of day's worth of ledgers, and may take 15 - 30 minutes to catch up. Logs are stored in the container at `/var/log/supervisor`. You can check the progress by monitoring logs with `supervisorctl`: -```bash -docker exec -it stellar /bin/bash -supervisorctl tail -f stellar-core -``` - -You can also check status by looking at the HTTP endpoint, e.g. by visiting http://localhost:11626 in your browser. - -## Connect Horizon to Stellar Core -You can connect Horizon to `stellar-core` at any time, but Horizon will not begin ingesting data until `stellar-core` has completed its catch-up process. - -Now run your development version of Horizon (which is outside of the container), pointing it at the `stellar-core` running inside the container: - -```bash -horizon --db-url="postgres://localhost/horizon_dev" --stellar-core-db-url="postgres://stellar:postgres@localhost:8002/core" --stellar-core-url="http://localhost:11626" --port 8001 --network-passphrase "Test SDF Network ; September 2015" --ingest -``` - -If all is well, you should see ingest logs written to standard out. You can test your Horizon instance with a query like: http://localhost:8001/transactions?limit=10&order=asc. Use the [Stellar Laboratory](https://www.stellar.org/laboratory/) to craft other queries to try out, -and read about the available endpoints and see examples in the [Horizon API reference](https://www.stellar.org/developers/horizon/reference/). - -## The development cycle -Congratulations! You can now run the full development cycle to build and test your code. -1. Write code + tests -2. Run tests -3. Compile Horizon: `go install github.com/stellar/go/services/horizon` -4. Run Horizon (pointing at your running `stellar-core`) -5. Try Horizon queries - -Check out the [Stellar Contributing Guide](https://github.com/stellar/docs/blob/master/CONTRIBUTING.md) to see how to contribute your work to the Stellar repositories. Once you've got something that works, open a pull request, linking to the issue that you are resolving with your contribution. We'll get back to you as quickly as we can. diff --git a/services/horizon/internal/docs/notes_for_developers.md b/services/horizon/internal/docs/notes_for_developers.md deleted file mode 100644 index c5696a6f57..0000000000 --- a/services/horizon/internal/docs/notes_for_developers.md +++ /dev/null @@ -1,156 +0,0 @@ -## Notes for Developers - -This document contains additional information related to the development of Horizon. For a detailed discussion of how to build and develop against Horizon, see the [Horizon development guide](developing.md). - -- [Initial set up](#setup) -- [Regenerating generated code](#regen) -- [Writing tests](#author_tests) -- [Running tests](#tests) -- [Logging](#logging) -- [Adding migrations](#migrations) - - ---- -## Initial set up -Compile and install Horizon as described in the [Horizon development guide](developing.md). - -## Regenerating generated code - -Horizon uses two Go tools you'll need to install: -1. [go-bindata](github.com/kevinburke/go-bindata) is used to bundle test data - -After the above are installed, run `go generate github.com/stellar/go/services/horizon/...`. - -### Example recipe - -Here's an example of recipe file with comments: -```rb -# Define two accounts test accounts -account :scott, Stellar::KeyPair.from_seed("SBZWG33UOQQCAIBAEAQCAIBAEAQCAIBAEAQCAIBAEAQCAIBAEAQCAPSA") -account :bartek, Stellar::KeyPair.from_seed("SBRGC4TUMVVSAIBAEAQCAIBAEAQCAIBAEAQCAIBAEAQCAIBAEAQCBDHV") - -# use_manual_close causes scc to run a process with MANUAL_CLOSE=true -use_manual_close - -# Create 2 accounts `scott` and `bartek` -create_account :scott, :master, 100 -create_account :bartek, :master, 100 - -# Close ledger -close_ledger - -# Send 5 XLM from `scott` to `bartek` -payment :scott, :bartek, [:native, 5] -``` - -You can find more recipes in [`scc` examples](https://github.com/stellar/stellar_core_commander/tree/84d5ffb97202ecc3a0ed34a739c98e69536c0c2c/examples). - -### Deprecated Scenario sql files - -Scenarios are in [horizon test scenarios](https://github.com/stellar/go/tree/master/services/horizon/internal/test/scenarios). They are used by many different integration tests, however, they are deprecated and are not meant to be used or included in new development. They were manually maintained and have not been updated with more recent db schema changes and are not associated with db migrations. - -## Writing Tests - -When authoring tests, refer to [Testing Best Practices](../../TESTING_README.md) for context. - -## Running Tests - -Run all the Go monorepo unit tests like so (assuming you are at stellar/go, or run from stellar/go/services/horizon for just the Horizon subset): - -```bash -go test ./... -``` - -or run individual Horizon tests like so, providing the expected arguments: - -```bash -go test github.com/stellar/go/services/horizon/... -``` - -To run the integration tests, move to top folder of working copy of `go` repo to run all integration tests -or /services/horizon to run just Horizon integration tests: -``` -HORIZON_INTEGRATION_TESTS_ENABLED=true go test -race -timeout 25m -v ./... -``` - -To run just one specific integration test, e.g. like `TestTxSub`: -``` -HORIZON_INTEGRATION_TESTS_ENABLED=true go test -run TestTxsub -race -timeout 25m -v ./... -``` - -## Logging - -All logging infrastructure is in the `github.com/stellar/go/tree/master/services/horizon/internal/log` package. This package provides "level-based" logging: Each logging statement has a severity, one of "Debug", "Info", "Warn", "Error" or "Panic". The Horizon server has a configured level "filter", specified either using the `--log-level` command line flag or the `LOG_LEVEL` environment variable. When a logging statement is executed, the statements declared severity is checked against the filter and will only be emitted if the severity of the statement is equal or higher severity than the filter. - -In addition, the logging subsystem has support for fields: Arbitrary key-value pairs that will be associated with an entry to allow for filtering and additional contextual information. - -### Making logging statements - -Assuming that you've imports the log package, making a simple logging call is just: - -```go - -log.Info("my log line") -log.Infof("I take a %s", "format string") - -``` - -Adding fields to a statement happens with a call to `WithField` or `WithFields` - -```go -log.WithField("pid", 1234).Warn("i'm scared") - -log.WithFields(log.F{ - "some_field": 123, - "second_field": "hello", -}).Debug("here") -``` - -The return value from `WithField` or `WithFields` is a `*log.Entry`, which you can save to emit multiple logging -statements that all share the same field. For example, the action system for Horizon attaches a log entry to `action.Log` on every request that can be used to emit log entries that have the request's id attached as a field. - -### Logging and Context - -The logging package provides the root logger at `log.DefaultLogger` and the package level funcs such as `log.Info` operate against the default logger. However, often it is important to include request-specific fields in a logging statement that are not available in the local scope. For example, it is useful to include an http request's id in every log statement that is emitted by code running on behalf of the request. This allows for easier debugging, as an operator can filter the log stream to a specific request id and not have to wade through the entirety of the log. - -Unfortunately, it is not prudent to thread an `*http.Request` parameter to every downstream subroutine and so we need another way to make that information available. The idiomatic way to do this in Go is with a context parameter, as describe [on the Go blog](https://blog.golang.org/context). The logging provides a func to bind a logger to a context using `log.Set` and allows you to retrieve a bound logger using `log.Ctx(ctx)`. Functions that need to log on behalf of an server request should take a context parameter. - -Here's an example of using context: - -```go - -// create a new sublogger -sub := log.WithField("val", 1) - -// bind it to a context -ctx := log.Set(context.Background(), sub) - -log.Info("no fields on this statement") -log.Ctx(ctx).Info("This statement will use the sub logger") - -``` - -### Logging Best Practices - -It's recommended that you try to avoid contextual information in your logging messages. Instead, use fields to establish context and use a static string for your message. This practice allows Horizon operators to more easily filter log lines to provide better insight into the health of the server. Lets take an example: - -```go -// BAD -log.Infof("running initializer: %s", i.Name) - -//GOOD -log.WithField("init_name", i.Name).Info("running initializer") -``` - -With the "bad" form of the logging example above, an operator can filter on both the message as well as the initializer name independently. This gets more powerful when multiple fields are combined, allowing for all sorts of slicing and dicing. - - -## Enabling TLS on your local workstation - -Horizon support HTTP/2 when served using TLS. To enable TLS on your local workstation, you must generate a certificate and configure Horizon to use it. We've written a helper script at `tls/regen.sh` to make this simple. Run the script from your terminal, and simply choose all the default options. This will create two files: `tls/server.crt` and `tls/server.key`. - -Now you must configure Horizon to use them: You can simply add `--tls-cert tls/server.crt --tls-key tls/server.key` to your command line invocations of Horizon, or you may specify `TLS_CERT` and `TLS_KEY` environment variables. - -# Adding migrations -1. Add your migration to `services/horizon/internal/db2/schema/migrations/` using the same name nomenclature as other migrations. -2. After creating you migration, run `bash services/horizon/internal/scripts/rebuild_schema.bash` this script will create all the autogenerated code for migrations. diff --git a/services/horizon/internal/docs/quickstart.md b/services/horizon/internal/docs/quickstart.md deleted file mode 100644 index 0d7541d717..0000000000 --- a/services/horizon/internal/docs/quickstart.md +++ /dev/null @@ -1,42 +0,0 @@ ---- -title: Horizon Quickstart -replacement: https://developers.stellar.org/docs/run-api-server/quickstart/ ---- -## Horizon Quickstart -This document describes how to quickly set up a **test** Stellar Core + Horizon node, that you can play around with to get a feel for how a stellar node operates. **This configuration is not secure!** It is **not** intended as a guide for production administration. - -For detailed information about running Horizon and Stellar Core safely in production see the [Horizon Administration Guide](admin.md) and the [Stellar Core Administration Guide](https://www.stellar.org/developers/stellar-core/software/admin.html). - -If you're ready to roll up your sleeves and dig into the code, check out the [Developer Guide](developing.md). - -### Install and run the Quickstart Docker Image -The fastest way to get up and running is using the [Stellar Quickstart Docker Image](https://github.com/stellar/docker-stellar-core-horizon). This is a Docker container that provides both `stellar-core` and `horizon`, pre-configured for testing. - -1. Install [Docker](https://www.docker.com/get-started). -2. Verify your Docker installation works: `docker run hello-world` -3. Create a local directory that the container can use to record state. This is helpful because it can take a few minutes to sync a new `stellar-core` with enough data for testing, and because it allows you to inspect and modify the configuration if needed. Here, we create a directory called `stellar` to use as the persistent volume: -`cd $HOME; mkdir stellar` -4. Download and run the Stellar Quickstart container, replacing `USER` with your username: - -```bash -docker run --rm -it -p "8000:8000" -p "11626:11626" -p "11625:11625" -p"8002:5432" -v $HOME/stellar:/opt/stellar --name stellar stellar/quickstart --testnet -``` - -You can check out Stellar Core status by browsing to http://localhost:11626. - -You can check out your Horizon instance by browsing to http://localhost:8000. - -You can tail logs within the container to see what's going on behind the scenes: -```bash -docker exec -it stellar /bin/bash -supervisorctl tail -f stellar-core -supervisorctl tail -f horizon stderr -``` - -On a modern laptop this test setup takes about 15 minutes to synchronise with the last couple of days of testnet ledgers. At that point Horizon will be available for querying. - -See the [Quickstart Docker Image](https://github.com/stellar/docker-stellar-core-horizon) documentation for more details, and alternative ways to run the container. - -You can test your Horizon instance with a query like: http://localhost:8000/transactions?cursor=&limit=10&order=asc. Use the [Stellar Laboratory](https://www.stellar.org/laboratory/) to craft other queries to try out, -and read about the available endpoints and see examples in the [Horizon API reference](https://www.stellar.org/developers/horizon/reference/). - diff --git a/services/horizon/internal/docs/readme.md b/services/horizon/internal/docs/readme.md deleted file mode 100644 index 3ec0774e79..0000000000 --- a/services/horizon/internal/docs/readme.md +++ /dev/null @@ -1,25 +0,0 @@ ---- -title: Horizon -replacement: https://developers.stellar.org/docs/run-api-server/ ---- - -Horizon is the server for the client facing API for the Stellar ecosystem. It acts as the interface between [stellar-core](https://www.stellar.org/developers/software/#stellar-core) and applications that want to access the Stellar network. It allows you to submit transactions to the network, check the status of accounts, subscribe to event streams, etc. See [an overview of the Stellar ecosystem](https://www.stellar.org/developers/guides/) for more details. - -You can interact directly with horizon via curl or a web browser but SDF provides a [JavaScript SDK](https://www.stellar.org/developers/js-stellar-sdk/reference/) for clients to use to interact with Horizon. - -SDF runs a instance of Horizon that is connected to the test net [https://horizon-testnet.stellar.org/](https://horizon-testnet.stellar.org/). - -## Libraries - -SDF maintained libraries:
-- [JavaScript](https://github.com/stellar/js-stellar-sdk) -- [Go](https://github.com/stellar/go/tree/master/clients/horizonclient) -- [Java](https://github.com/stellar/java-stellar-sdk) - -Community maintained libraries for interacting with Horizon in other languages:
-- [Python](https://github.com/StellarCN/py-stellar-base) -- [C# .NET Core 2.x](https://github.com/elucidsoft/dotnetcore-stellar-sdk) -- [Ruby](https://github.com/astroband/ruby-stellar-sdk) -- [iOS and macOS](https://github.com/Soneso/stellar-ios-mac-sdk) -- [Scala SDK](https://github.com/synesso/scala-stellar-sdk) -- [C++ SDK](https://github.com/bnogalm/StellarQtSDK) diff --git a/services/horizon/internal/flags.go b/services/horizon/internal/flags.go index ffdeb697ed..e2783680fd 100644 --- a/services/horizon/internal/flags.go +++ b/services/horizon/internal/flags.go @@ -1,30 +1,34 @@ package horizon import ( + _ "embed" "fmt" "go/types" stdLog "log" "os" "os/exec" - "path/filepath" "strings" "github.com/sirupsen/logrus" "github.com/spf13/viper" + "github.com/stellar/throttled" + "github.com/stellar/go/ingest/ledgerbackend" "github.com/stellar/go/network" "github.com/stellar/go/services/horizon/internal/db2/schema" apkg "github.com/stellar/go/support/app" support "github.com/stellar/go/support/config" "github.com/stellar/go/support/db" + "github.com/stellar/go/support/errors" "github.com/stellar/go/support/log" - "github.com/stellar/throttled" ) const ( // DatabaseURLFlagName is the command line flag for configuring the Horizon postgres URL DatabaseURLFlagName = "db-url" + // IngestFlagName is the command line flag for enabling ingestion on the Horizon instance + IngestFlagName = "ingest" // StellarCoreDBURLFlagName is the command line flag for configuring the postgres Stellar Core URL StellarCoreDBURLFlagName = "stellar-core-db-url" // StellarCoreURLFlagName is the command line flag for configuring the URL fore Stellar Core HTTP endpoint @@ -36,10 +40,56 @@ const ( captiveCoreConfigAppendPathName = "captive-core-config-append-path" // CaptiveCoreConfigPathName is the command line flag for configuring the path to the captive core configuration file CaptiveCoreConfigPathName = "captive-core-config-path" - // captive-core-use-db is the command line flag for enabling captive core runtime to use an external db url connection rather than RAM for ledger states + // CaptiveCoreConfigUseDB is the command line flag for enabling captive core runtime to use an external db url + // connection rather than RAM for ledger states CaptiveCoreConfigUseDB = "captive-core-use-db" + // CaptiveCoreHTTPPortFlagName is the commandline flag for specifying captive core HTTP port + CaptiveCoreHTTPPortFlagName = "captive-core-http-port" + // EnableCaptiveCoreIngestionFlagName is the commandline flag for enabling captive core ingestion + EnableCaptiveCoreIngestionFlagName = "enable-captive-core-ingestion" + // NetworkPassphraseFlagName is the command line flag for specifying the network passphrase + NetworkPassphraseFlagName = "network-passphrase" + // HistoryArchiveURLsFlagName is the command line flag for specifying the history archive URLs + HistoryArchiveURLsFlagName = "history-archive-urls" + // NetworkFlagName is the command line flag for specifying the "network" + NetworkFlagName = "network" + // EnableIngestionFilteringFlagName is the command line flag for enabling the experimental ingestion filtering feature (now enabled by default) + EnableIngestionFilteringFlagName = "exp-enable-ingestion-filtering" + // DisableTxSubFlagName is the command line flag for disabling transaction submission feature of Horizon + DisableTxSubFlagName = "disable-tx-sub" + + // StellarPubnet is a constant representing the Stellar public network + StellarPubnet = "pubnet" + // StellarTestnet is a constant representing the Stellar test network + StellarTestnet = "testnet" + + defaultMaxHTTPRequestSize = uint(200 * 1024) +) - captiveCoreMigrationHint = "If you are migrating from Horizon 1.x.y, start with the Migration Guide here: https://developers.stellar.org/docs/run-api-server/migrating/" +var ( + IngestCmd = "ingest" + RecordMetricsCmd = "record-metrics" + DbCmd = "db" + ServeCmd = "serve" + HorizonCmd = "horizon" + + DbFillGapsCmd = "fill-gaps" + DbReingestCmd = "reingest" + IngestTriggerStateRebuild = "trigger-state-rebuild" + IngestInitGenesisStateCmd = "init-genesis-state" + IngestBuildStateCmd = "build-state" + IngestStressTestCmd = "stress-test" + IngestVerifyRangeCmd = "verify-range" + + ApiServerCommands = []string{HorizonCmd, ServeCmd} + IngestionCommands = append(ApiServerCommands, + IngestInitGenesisStateCmd, + IngestBuildStateCmd, + IngestStressTestCmd, + IngestVerifyRangeCmd, + DbFillGapsCmd, + DbReingestCmd) + DatabaseBoundCommands = append(ApiServerCommands, DbCmd, IngestCmd) ) // validateBothOrNeither ensures that both options are provided, if either is provided. @@ -105,35 +155,40 @@ func Flags() (*Config, support.ConfigOptions) { // Add a new entry here to connect a new field in the horizon.Config struct var flags = support.ConfigOptions{ &support.ConfigOption{ - Name: DatabaseURLFlagName, - EnvVar: "DATABASE_URL", - ConfigKey: &config.DatabaseURL, - OptType: types.String, - Required: true, - Usage: "horizon postgres database to connect with", + Name: DatabaseURLFlagName, + EnvVar: "DATABASE_URL", + ConfigKey: &config.DatabaseURL, + OptType: types.String, + Required: true, + Usage: "horizon postgres database to connect with", + UsedInCommands: DatabaseBoundCommands, }, &support.ConfigOption{ - Name: "ro-database-url", - ConfigKey: &config.RoDatabaseURL, - OptType: types.String, - Required: false, - Usage: "horizon postgres read-replica to connect with, when set it will return stale history error when replica is behind primary", + Name: "ro-database-url", + ConfigKey: &config.RoDatabaseURL, + OptType: types.String, + Required: false, + Usage: "horizon postgres read-replica to connect with, when set it will return stale history error when replica is behind primary", + UsedInCommands: IngestionCommands, }, &support.ConfigOption{ - Name: StellarCoreBinaryPathName, - OptType: types.String, - FlagDefault: "", - Required: false, - Usage: "path to stellar core binary (--remote-captive-core-url has higher precedence). If captive core is enabled, look for the stellar-core binary in $PATH by default.", - ConfigKey: &config.CaptiveCoreBinaryPath, + Name: StellarCoreBinaryPathName, + OptType: types.String, + FlagDefault: "", + Required: false, + Usage: "path to stellar core binary, look for the stellar-core binary in $PATH by default.", + ConfigKey: &config.CaptiveCoreBinaryPath, + UsedInCommands: IngestionCommands, }, &support.ConfigOption{ - Name: "remote-captive-core-url", - OptType: types.String, - FlagDefault: "", - Required: false, - Usage: "url to access the remote captive core server", - ConfigKey: &config.RemoteCaptiveCoreURL, + Name: DisableTxSubFlagName, + OptType: types.Bool, + FlagDefault: false, + Required: false, + Usage: "disables the transaction submission functionality of Horizon.", + ConfigKey: &config.DisableTxSub, + Hidden: false, + UsedInCommands: ApiServerCommands, }, &support.ConfigOption{ Name: captiveCoreConfigAppendPathName, @@ -157,6 +212,7 @@ func Flags() (*Config, support.ConfigOptions) { } return nil }, + UsedInCommands: IngestionCommands, }, &support.ConfigOption{ Name: CaptiveCoreConfigPathName, @@ -171,11 +227,12 @@ func Flags() (*Config, support.ConfigOptions) { } return nil }, + UsedInCommands: IngestionCommands, }, &support.ConfigOption{ Name: CaptiveCoreConfigUseDB, OptType: types.Bool, - FlagDefault: false, + FlagDefault: true, Required: false, Usage: `when enabled, Horizon ingestion will instruct the captive core invocation to use an external db url for ledger states rather than in memory(RAM).\n @@ -189,23 +246,49 @@ func Flags() (*Config, support.ConfigOptions) { } return nil }, - ConfigKey: &config.CaptiveCoreConfigUseDB, + ConfigKey: &config.CaptiveCoreConfigUseDB, + UsedInCommands: IngestionCommands, }, &support.ConfigOption{ - Name: "enable-captive-core-ingestion", - OptType: types.Bool, - FlagDefault: true, + Name: EnableCaptiveCoreIngestionFlagName, + OptType: types.String, + FlagDefault: "", Required: false, - Usage: "causes Horizon to ingest from a Captive Stellar Core process instead of a persistent Stellar Core database", - ConfigKey: &config.EnableCaptiveCoreIngestion, + Hidden: true, + CustomSetValue: func(opt *support.ConfigOption) error { + if val := viper.GetString(opt.Name); val != "" { + stdLog.Printf( + "DEPRECATED - The usage of the flag --enable-captive-core-ingestion has been deprecated. " + + "Horizon now uses Captive-Core ingestion by default and this flag will soon be removed in " + + "the future.", + ) + } + return nil + }, + UsedInCommands: IngestionCommands, }, &support.ConfigOption{ - Name: "exp-enable-ingestion-filtering", - OptType: types.Bool, - FlagDefault: false, + Name: EnableIngestionFilteringFlagName, + OptType: types.String, + FlagDefault: "", Required: false, - Usage: "causes Horizon to enable the experimental Ingestion Filtering and the ingestion admin HTTP endpoint at /ingestion/filter", ConfigKey: &config.EnableIngestionFiltering, + CustomSetValue: func(opt *support.ConfigOption) error { + + // Always enable ingestion filtering by default. + config.EnableIngestionFiltering = true + + if val := viper.GetString(opt.Name); val != "" { + stdLog.Printf( + "DEPRECATED - No ingestion filter rules are defined by default, which equates to " + + "no filtering of historical data. If you have never added filter rules to this deployment, then no further action is needed. " + + "If you have defined ingestion filter rules previously but disabled filtering overall by setting the env variable EXP_ENABLE_INGESTION_FILTERING=false, " + + "then you should now delete the filter rules using the Horizon Admin API to achieve the same no-filtering result. Remove usage of this variable in all cases.", + ) + } + return nil + }, + Hidden: true, }, &support.ConfigOption{ Name: "captive-core-http-port", @@ -215,6 +298,7 @@ func Flags() (*Config, support.ConfigOptions) { FlagDefault: uint(0), Usage: "HTTP port for Captive Core to listen on (0 disables the HTTP server)", ConfigKey: &config.CaptiveCoreTomlParams.HTTPPort, + UsedInCommands: IngestionCommands, }, &support.ConfigOption{ Name: "captive-core-storage-path", @@ -224,16 +308,17 @@ func Flags() (*Config, support.ConfigOptions) { if existingValue == "" || existingValue == "." { cwd, err := os.Getwd() if err != nil { - return fmt.Errorf("Unable to determine the current directory: %s", err) + return fmt.Errorf("unable to determine the current directory: %s", err) } existingValue = cwd } *opt.ConfigKey.(*string) = existingValue return nil }, - Required: false, - Usage: "Storage location for Captive Core bucket data", - ConfigKey: &config.CaptiveCoreStoragePath, + Required: false, + Usage: "Storage location for Captive Core bucket data. If not set, the current working directory is used as the default location.", + ConfigKey: &config.CaptiveCoreStoragePath, + UsedInCommands: IngestionCommands, }, &support.ConfigOption{ Name: "captive-core-peer-port", @@ -243,69 +328,91 @@ func Flags() (*Config, support.ConfigOptions) { Required: false, Usage: "port for Captive Core to bind to for connecting to the Stellar swarm (0 uses Stellar Core's default)", ConfigKey: &config.CaptiveCoreTomlParams.PeerPort, + UsedInCommands: IngestionCommands, }, &support.ConfigOption{ - Name: StellarCoreDBURLFlagName, - EnvVar: "STELLAR_CORE_DATABASE_URL", - ConfigKey: &config.StellarCoreDatabaseURL, - OptType: types.String, - Required: false, - Usage: "stellar-core postgres database to connect with", + Name: StellarCoreDBURLFlagName, + EnvVar: "STELLAR_CORE_DATABASE_URL", + OptType: types.String, + Required: false, + Hidden: true, + CustomSetValue: func(opt *support.ConfigOption) error { + if val := viper.GetString(opt.Name); val != "" { + stdLog.Printf( + "DEPRECATED - The usage of the flag --stellar-core-db-url has been deprecated. " + + "Horizon now uses Captive-Core ingestion by default and this flag will soon be removed in " + + "the future.", + ) + } + return nil + }, + UsedInCommands: IngestionCommands, }, &support.ConfigOption{ - Name: StellarCoreURLFlagName, - ConfigKey: &config.StellarCoreURL, - OptType: types.String, - Usage: "stellar-core to connect with (for http commands). If unset and the local Captive core is enabled, it will use http://localhost:", + Name: StellarCoreURLFlagName, + ConfigKey: &config.StellarCoreURL, + OptType: types.String, + Usage: "stellar-core to connect with (for http commands). If unset and the local Captive core is enabled, it will use http://localhost:", + UsedInCommands: IngestionCommands, }, &support.ConfigOption{ - Name: "history-archive-urls", - ConfigKey: &config.HistoryArchiveURLs, - OptType: types.String, - Required: false, - FlagDefault: "", + Name: HistoryArchiveURLsFlagName, + ConfigKey: &config.HistoryArchiveURLs, + OptType: types.String, + Required: false, CustomSetValue: func(co *support.ConfigOption) error { stringOfUrls := viper.GetString(co.Name) urlStrings := strings.Split(stringOfUrls, ",") - *(co.ConfigKey.(*[]string)) = urlStrings + //urlStrings contains a single empty value when stringOfUrls is empty + if len(urlStrings) == 1 && urlStrings[0] == "" { + *(co.ConfigKey.(*[]string)) = []string{} + } else { + *(co.ConfigKey.(*[]string)) = urlStrings + } return nil }, - Usage: "comma-separated list of stellar history archives to connect with", + Usage: "comma-separated list of stellar history archives to connect with", + UsedInCommands: IngestionCommands, }, &support.ConfigOption{ - Name: "port", - ConfigKey: &config.Port, - OptType: types.Uint, - FlagDefault: uint(8000), - Usage: "tcp port to listen on for http requests", + Name: "port", + ConfigKey: &config.Port, + OptType: types.Uint, + FlagDefault: uint(8000), + Usage: "tcp port to listen on for http requests", + UsedInCommands: ApiServerCommands, }, &support.ConfigOption{ - Name: "admin-port", - ConfigKey: &config.AdminPort, - OptType: types.Uint, - FlagDefault: uint(0), - Usage: "WARNING: this should not be accessible from the Internet and does not use TLS, tcp port to listen on for admin http requests, 0 (default) disables the admin server", + Name: "admin-port", + ConfigKey: &config.AdminPort, + OptType: types.Uint, + FlagDefault: uint(0), + Usage: "WARNING: this should not be accessible from the Internet and does not use TLS, tcp port to listen on for admin http requests, 0 (default) disables the admin server", + UsedInCommands: append(ApiServerCommands, RecordMetricsCmd), }, &support.ConfigOption{ - Name: "max-db-connections", - ConfigKey: &config.MaxDBConnections, - OptType: types.Int, - FlagDefault: 0, - Usage: "when set has a priority over horizon-db-max-open-connections, horizon-db-max-idle-connections. max horizon database open connections may need to be increased when responses are slow but DB CPU is normal", + Name: "max-db-connections", + ConfigKey: &config.MaxDBConnections, + OptType: types.Int, + FlagDefault: 0, + Usage: "when set has a priority over horizon-db-max-open-connections, horizon-db-max-idle-connections. max horizon database open connections may need to be increased when responses are slow but DB CPU is normal", + UsedInCommands: DatabaseBoundCommands, }, &support.ConfigOption{ - Name: "horizon-db-max-open-connections", - ConfigKey: &config.HorizonDBMaxOpenConnections, - OptType: types.Int, - FlagDefault: 20, - Usage: "max horizon database open connections. may need to be increased when responses are slow but DB CPU is normal", + Name: "horizon-db-max-open-connections", + ConfigKey: &config.HorizonDBMaxOpenConnections, + OptType: types.Int, + FlagDefault: 20, + Usage: "max horizon database open connections. may need to be increased when responses are slow but DB CPU is normal", + UsedInCommands: DatabaseBoundCommands, }, &support.ConfigOption{ - Name: "horizon-db-max-idle-connections", - ConfigKey: &config.HorizonDBMaxIdleConnections, - OptType: types.Int, - FlagDefault: 20, - Usage: "max horizon database idle connections. may need to be set to the same value as horizon-db-max-open-connections when responses are slow and DB CPU is normal, because it may indicate that a lot of time is spent closing/opening idle connections. This can happen in case of high variance in number of requests. must be equal or lower than max open connections", + Name: "horizon-db-max-idle-connections", + ConfigKey: &config.HorizonDBMaxIdleConnections, + OptType: types.Int, + FlagDefault: 20, + Usage: "max horizon database idle connections. may need to be set to the same value as horizon-db-max-open-connections when responses are slow and DB CPU is normal, because it may indicate that a lot of time is spent closing/opening idle connections. This can happen in case of high variance in number of requests. must be equal or lower than max open connections", + UsedInCommands: DatabaseBoundCommands, }, &support.ConfigOption{ Name: "sse-update-frequency", @@ -314,6 +421,7 @@ func Flags() (*Config, support.ConfigOptions) { FlagDefault: 5, CustomSetValue: support.SetDuration, Usage: "defines how often streams should check if there's a new ledger (in seconds), may need to increase in case of big number of streams", + UsedInCommands: ApiServerCommands, }, &support.ConfigOption{ Name: "connection-timeout", @@ -322,6 +430,15 @@ func Flags() (*Config, support.ConfigOptions) { FlagDefault: 55, CustomSetValue: support.SetDuration, Usage: "defines the timeout of connection after which 504 response will be sent or stream will be closed, if Horizon is behind a load balancer with idle connection timeout, this should be set to a few seconds less that idle timeout, does not apply to POST /transactions", + UsedInCommands: ApiServerCommands, + }, + &support.ConfigOption{ + Name: "max-http-request-size", + ConfigKey: &config.MaxHTTPRequestSize, + OptType: types.Uint, + FlagDefault: defaultMaxHTTPRequestSize, + Usage: "sets the limit on the maximum allowed http request payload size, default is 200kb, to disable the limit check, set to 0, only do so if you acknowledge the implications of accepting unbounded http request payload sizes.", + UsedInCommands: ApiServerCommands, }, &support.ConfigOption{ Name: "per-hour-rate-limit", @@ -340,7 +457,8 @@ func Flags() (*Config, support.ConfigOptions) { } return nil }, - Usage: "max count of requests allowed in a one hour period, by remote ip address", + Usage: "max count of requests allowed in a one hour period, by remote ip address", + UsedInCommands: ApiServerCommands, }, &support.ConfigOption{ Name: "friendbot-url", @@ -348,6 +466,7 @@ func Flags() (*Config, support.ConfigOptions) { OptType: types.String, CustomSetValue: support.SetURL, Usage: "friendbot service to redirect to", + UsedInCommands: ApiServerCommands, }, &support.ConfigOption{ Name: "log-level", @@ -357,7 +476,7 @@ func Flags() (*Config, support.ConfigOptions) { CustomSetValue: func(co *support.ConfigOption) error { ll, err := logrus.ParseLevel(viper.GetString(co.Name)) if err != nil { - return fmt.Errorf("Could not parse log-level: %v", viper.GetString(co.Name)) + return fmt.Errorf("could not parse log-level: %v", viper.GetString(co.Name)) } *(co.ConfigKey.(*logrus.Level)) = ll return nil @@ -377,36 +496,41 @@ func Flags() (*Config, support.ConfigOptions) { CustomSetValue: support.SetOptionalString, Required: false, Usage: "name of the path for Core logs (leave empty to log w/ Horizon only)", + UsedInCommands: IngestionCommands, }, &support.ConfigOption{ - Name: "max-path-length", - ConfigKey: &config.MaxPathLength, - OptType: types.Uint, - FlagDefault: uint(3), - Usage: "the maximum number of assets on the path in `/paths` endpoint, warning: increasing this value will increase /paths response time", + Name: "max-path-length", + ConfigKey: &config.MaxPathLength, + OptType: types.Uint, + FlagDefault: uint(3), + Usage: "the maximum number of assets on the path in `/paths` endpoint, warning: increasing this value will increase /paths response time", + UsedInCommands: ApiServerCommands, }, &support.ConfigOption{ - Name: "max-assets-per-path-request", - ConfigKey: &config.MaxAssetsPerPathRequest, - OptType: types.Int, - FlagDefault: int(15), - Usage: "the maximum number of assets in '/paths/strict-send' and '/paths/strict-recieve' endpoints", + Name: "max-assets-per-path-request", + ConfigKey: &config.MaxAssetsPerPathRequest, + OptType: types.Int, + FlagDefault: int(15), + Usage: "the maximum number of assets in '/paths/strict-send' and '/paths/strict-receive' endpoints", + UsedInCommands: ApiServerCommands, }, &support.ConfigOption{ - Name: "disable-pool-path-finding", - ConfigKey: &config.DisablePoolPathFinding, - OptType: types.Bool, - FlagDefault: false, - Required: false, - Usage: "excludes liquidity pools from consideration in the `/paths` endpoint", + Name: "disable-pool-path-finding", + ConfigKey: &config.DisablePoolPathFinding, + OptType: types.Bool, + FlagDefault: false, + Required: false, + Usage: "excludes liquidity pools from consideration in the `/paths` endpoint", + UsedInCommands: ApiServerCommands, }, &support.ConfigOption{ - Name: "disable-path-finding", - ConfigKey: &config.DisablePathFinding, - OptType: types.Bool, - FlagDefault: false, - Required: false, - Usage: "disables the path finding endpoints", + Name: "disable-path-finding", + ConfigKey: &config.DisablePathFinding, + OptType: types.Bool, + FlagDefault: false, + Required: false, + Usage: "disables the path finding endpoints", + UsedInCommands: ApiServerCommands, }, &support.ConfigOption{ Name: "max-path-finding-requests", @@ -416,19 +540,22 @@ func Flags() (*Config, support.ConfigOptions) { Required: false, Usage: "The maximum number of path finding requests per second horizon will allow." + " A value of zero (the default) disables the limit.", + UsedInCommands: ApiServerCommands, }, &support.ConfigOption{ - Name: "network-passphrase", - ConfigKey: &config.NetworkPassphrase, - OptType: types.String, - Required: true, - Usage: "Override the network passphrase", + Name: NetworkPassphraseFlagName, + ConfigKey: &config.NetworkPassphrase, + OptType: types.String, + Required: false, + Usage: "Override the network passphrase", + UsedInCommands: IngestionCommands, }, &support.ConfigOption{ - Name: "sentry-dsn", - ConfigKey: &config.SentryDSN, - OptType: types.String, - Usage: "Sentry URL to which panics and errors should be reported", + Name: "sentry-dsn", + ConfigKey: &config.SentryDSN, + OptType: types.String, + Usage: "Sentry URL to which panics and errors should be reported", + UsedInCommands: ApiServerCommands, }, &support.ConfigOption{ Name: "loggly-token", @@ -444,106 +571,160 @@ func Flags() (*Config, support.ConfigOptions) { Usage: "Tag to be added to every loggly log event", }, &support.ConfigOption{ - Name: "tls-cert", - ConfigKey: &config.TLSCert, - OptType: types.String, - Usage: "TLS certificate file to use for securing connections to horizon", + Name: "tls-cert", + ConfigKey: &config.TLSCert, + OptType: types.String, + Usage: "TLS certificate file to use for securing connections to horizon", + UsedInCommands: ApiServerCommands, }, &support.ConfigOption{ - Name: "tls-key", - ConfigKey: &config.TLSKey, - OptType: types.String, - Usage: "TLS private key file to use for securing connections to horizon", + Name: "tls-key", + ConfigKey: &config.TLSKey, + OptType: types.String, + Usage: "TLS private key file to use for securing connections to horizon", + UsedInCommands: ApiServerCommands, }, &support.ConfigOption{ - Name: "ingest", - ConfigKey: &config.Ingest, - OptType: types.Bool, - FlagDefault: true, - Usage: "causes this horizon process to ingest data from stellar-core into horizon's db", + Name: IngestFlagName, + ConfigKey: &config.Ingest, + OptType: types.Bool, + FlagDefault: true, + Usage: "causes this horizon process to ingest data from stellar-core into horizon's db", + UsedInCommands: ApiServerCommands, }, &support.ConfigOption{ - Name: "cursor-name", - EnvVar: "CURSOR_NAME", - ConfigKey: &config.CursorName, - OptType: types.String, - FlagDefault: "HORIZON", - Usage: "ingestor cursor used by horizon to ingest from stellar core. must be uppercase and unique for each horizon instance ingesting from that core instance.", + Name: "cursor-name", + EnvVar: "CURSOR_NAME", + ConfigKey: &config.CursorName, + OptType: types.String, + FlagDefault: "HORIZON", + Usage: "ingestor cursor used by horizon to ingest from stellar core. must be uppercase and unique for each horizon instance ingesting from that core instance.", + UsedInCommands: IngestionCommands, }, &support.ConfigOption{ - Name: "history-retention-count", - ConfigKey: &config.HistoryRetentionCount, - OptType: types.Uint, - FlagDefault: uint(0), - Usage: "the minimum number of ledgers to maintain within horizon's history tables. 0 signifies an unlimited number of ledgers will be retained", + Name: "history-retention-count", + ConfigKey: &config.HistoryRetentionCount, + OptType: types.Uint, + FlagDefault: uint(0), + Usage: "the minimum number of ledgers to maintain within horizon's history tables. 0 signifies an unlimited number of ledgers will be retained", + UsedInCommands: IngestionCommands, + }, + &support.ConfigOption{ + Name: "history-stale-threshold", + ConfigKey: &config.StaleThreshold, + OptType: types.Uint, + FlagDefault: uint(0), + Usage: "the maximum number of ledgers the history db is allowed to be out of date from the connected stellar-core db before horizon considers history stale", + UsedInCommands: IngestionCommands, + }, + &support.ConfigOption{ + Name: "skip-cursor-update", + ConfigKey: &config.SkipCursorUpdate, + OptType: types.Bool, + FlagDefault: false, + Usage: "causes the ingester to skip reporting the last imported ledger state to stellar-core", + UsedInCommands: IngestionCommands, + }, + &support.ConfigOption{ + Name: "ingest-disable-state-verification", + ConfigKey: &config.IngestDisableStateVerification, + OptType: types.Bool, + FlagDefault: false, + Usage: "disable periodic verification of ledger state in horizon db (not recommended)", + UsedInCommands: IngestionCommands, }, &support.ConfigOption{ - Name: "history-stale-threshold", - ConfigKey: &config.StaleThreshold, + Name: "ingest-state-verification-checkpoint-frequency", + ConfigKey: &config.IngestStateVerificationCheckpointFrequency, OptType: types.Uint, - FlagDefault: uint(0), - Usage: "the maximum number of ledgers the history db is allowed to be out of date from the connected stellar-core db before horizon considers history stale", + FlagDefault: uint(1), + Usage: "the frequency in units per checkpoint for how often state verification is executed. " + + "A value of 1 implies running state verification on every checkpoint. " + + "A value of 2 implies running state verification on every second checkpoint.", + UsedInCommands: IngestionCommands, }, &support.ConfigOption{ - Name: "skip-cursor-update", - ConfigKey: &config.SkipCursorUpdate, - OptType: types.Bool, - FlagDefault: false, - Usage: "causes the ingester to skip reporting the last imported ledger state to stellar-core", + Name: "ingest-state-verification-timeout", + ConfigKey: &config.IngestStateVerificationTimeout, + OptType: types.Int, + FlagDefault: 0, + CustomSetValue: support.SetDurationMinutes, + Usage: "defines an upper bound in minutes for on how long state verification is allowed to run. " + + "A value of 0 disables the timeout.", + UsedInCommands: IngestionCommands, }, &support.ConfigOption{ - Name: "ingest-disable-state-verification", - ConfigKey: &config.IngestDisableStateVerification, - OptType: types.Bool, - FlagDefault: false, - Usage: "ingestion system runs a verification routing to compare state in local database with history buckets, this can be disabled however it's not recommended", + Name: "ingest-enable-extended-log-ledger-stats", + ConfigKey: &config.IngestEnableExtendedLogLedgerStats, + OptType: types.Bool, + FlagDefault: false, + Usage: "enables extended ledger stats in the log (ledger entry changes and operations stats)", + UsedInCommands: IngestionCommands, }, &support.ConfigOption{ - Name: "ingest-enable-extended-log-ledger-stats", - ConfigKey: &config.IngestEnableExtendedLogLedgerStats, - OptType: types.Bool, - FlagDefault: false, - Usage: "enables extended ledger stats in the log (ledger entry changes and operations stats)", + Name: "apply-migrations", + ConfigKey: &config.ApplyMigrations, + OptType: types.Bool, + FlagDefault: false, + Required: false, + Usage: "applies pending migrations before starting horizon", + UsedInCommands: DatabaseBoundCommands, }, &support.ConfigOption{ - Name: "apply-migrations", - ConfigKey: &config.ApplyMigrations, - OptType: types.Bool, - FlagDefault: false, - Required: false, - Usage: "applies pending migrations before starting horizon", + Name: "checkpoint-frequency", + ConfigKey: &config.CheckpointFrequency, + OptType: types.Uint32, + FlagDefault: uint32(64), + Required: false, + Usage: "establishes how many ledgers exist between checkpoints, do NOT change this unless you really know what you are doing", + UsedInCommands: IngestionCommands, }, &support.ConfigOption{ - Name: "checkpoint-frequency", - ConfigKey: &config.CheckpointFrequency, - OptType: types.Uint32, - FlagDefault: uint32(64), - Required: false, - Usage: "establishes how many ledgers exist between checkpoints, do NOT change this unless you really know what you are doing", + Name: "behind-cloudflare", + ConfigKey: &config.BehindCloudflare, + OptType: types.Bool, + FlagDefault: false, + Required: false, + Usage: "determines if Horizon instance is behind Cloudflare, in such case client IP in the logs will be replaced with Cloudflare header (cannot be used with --behind-aws-load-balancer)", + UsedInCommands: ApiServerCommands, }, &support.ConfigOption{ - Name: "behind-cloudflare", - ConfigKey: &config.BehindCloudflare, - OptType: types.Bool, - FlagDefault: false, - Required: false, - Usage: "determines if Horizon instance is behind Cloudflare, in such case client IP in the logs will be replaced with Cloudflare header (cannot be used with --behind-aws-load-balancer)", + Name: "behind-aws-load-balancer", + ConfigKey: &config.BehindAWSLoadBalancer, + OptType: types.Bool, + FlagDefault: false, + Required: false, + Usage: "determines if Horizon instance is behind AWS load balances like ELB or ALB, in such case client IP in the logs will be replaced with the last IP in X-Forwarded-For header (cannot be used with --behind-cloudflare)", + UsedInCommands: ApiServerCommands, }, &support.ConfigOption{ - Name: "behind-aws-load-balancer", - ConfigKey: &config.BehindAWSLoadBalancer, - OptType: types.Bool, - FlagDefault: false, - Required: false, - Usage: "determines if Horizon instance is behind AWS load balances like ELB or ALB, in such case client IP in the logs will be replaced with the last IP in X-Forwarded-For header (cannot be used with --behind-cloudflare)", + Name: "rounding-slippage-filter", + ConfigKey: &config.RoundingSlippageFilter, + OptType: types.Int, + FlagDefault: 1000, + Required: false, + Usage: "excludes trades from /trade_aggregations unless their rounding slippage is 0 { + return defaultNetworkConfig, fmt.Errorf("invalid config: %s parameter not allowed with the %s parameter", + HistoryArchiveURLsFlagName, NetworkFlagName) + } + + switch config.Network { + case StellarPubnet: + defaultNetworkConfig = PubnetConf + case StellarTestnet: + defaultNetworkConfig = TestnetConf + default: + return defaultNetworkConfig, fmt.Errorf("no default configuration found for network %s", config.Network) + } + + return defaultNetworkConfig, nil +} + +// setCaptiveCoreConfiguration prepares configuration for the Captive Core +func setCaptiveCoreConfiguration(config *Config, options ApplyOptions) error { + stdLog.Println("Preparing captive core...") + + // If the user didn't specify a Stellar Core binary, we can check the + // $PATH and possibly fill it in for them. + if config.CaptiveCoreBinaryPath == "" { + var err error + if config.CaptiveCoreBinaryPath, err = getCaptiveCoreBinaryPath(); err != nil { + return fmt.Errorf("captive core requires %s", StellarCoreBinaryPathName) + } + } + + var defaultNetworkConfig networkConfig + if config.Network != "" { + var err error + defaultNetworkConfig, err = getCaptiveCoreConfigFromNetworkParameter(config) + if err != nil { + return err + } + config.NetworkPassphrase = defaultNetworkConfig.NetworkPassphrase + config.HistoryArchiveURLs = defaultNetworkConfig.HistoryArchiveURLs + } else { + if config.NetworkPassphrase == "" { + return fmt.Errorf("%s must be set", NetworkPassphraseFlagName) + } + + if len(config.HistoryArchiveURLs) == 0 { + return fmt.Errorf("%s must be set", HistoryArchiveURLsFlagName) + } + } + + config.CaptiveCoreTomlParams.CoreBinaryPath = config.CaptiveCoreBinaryPath + config.CaptiveCoreTomlParams.HistoryArchiveURLs = config.HistoryArchiveURLs + config.CaptiveCoreTomlParams.NetworkPassphrase = config.NetworkPassphrase + + var err error + if config.CaptiveCoreConfigPath != "" { + config.CaptiveCoreToml, err = ledgerbackend.NewCaptiveCoreTomlFromFile(config.CaptiveCoreConfigPath, + config.CaptiveCoreTomlParams) + if err != nil { + return errors.Wrap(err, "invalid captive core toml file") + } + } else if !options.RequireCaptiveCoreFullConfig { + // Creates a minimal captive-core config (without quorum information), just enough to run captive core. + // This is used by certain database commands, such as `reingest and fill-gaps, to reingest historical data. + config.CaptiveCoreToml, err = ledgerbackend.NewCaptiveCoreToml(config.CaptiveCoreTomlParams) + if err != nil { + return errors.Wrap(err, "invalid captive core toml file") + } + } else if len(defaultNetworkConfig.defaultConfig) != 0 { + config.CaptiveCoreToml, err = ledgerbackend.NewCaptiveCoreTomlFromData(defaultNetworkConfig.defaultConfig, + config.CaptiveCoreTomlParams) + if err != nil { + return errors.Wrap(err, "invalid captive core toml file") + } + } else { + return fmt.Errorf("invalid config: captive core requires that --%s is set or you can set the --%s "+ + "parameter to use the default captive core config", CaptiveCoreConfigPathName, NetworkFlagName) + } + + // If we don't supply an explicit core URL and running captive core process with the http port enabled, + // point to it. + if config.StellarCoreURL == "" && config.CaptiveCoreToml.HTTPPort != 0 { + config.StellarCoreURL = fmt.Sprintf("http://localhost:%d", config.CaptiveCoreToml.HTTPPort) + } + + return nil } // ApplyFlags applies the command line flags on the given Config instance func ApplyFlags(config *Config, flags support.ConfigOptions, options ApplyOptions) error { + // Check if the user has passed any flags and if so, print a DEPRECATED warning message. + flagsPassedByUser := flags.GetCommandLineFlagsPassedByUser() + if len(flagsPassedByUser) > 0 { + result := fmt.Sprintf("DEPRECATED - the use of command-line flags: [%s], has been deprecated in favor of environment variables. "+ + "Please consult our Configuring section in the developer documentation on how to use them - https://developers.stellar.org/docs/run-api-server/configuring", "--"+strings.Join(flagsPassedByUser, ",--")) + stdLog.Println(result) + } + // Verify required options and load the config struct if err := flags.RequireE(); err != nil { return err } + if err := flags.SetValues(); err != nil { return err } @@ -611,112 +930,9 @@ func ApplyFlags(config *Config, flags support.ConfigOptions, options ApplyOption return err } - // config.HistoryArchiveURLs contains a single empty value when empty so using - // viper.GetString is easier. - if len(config.HistoryArchiveURLs) == 1 && config.HistoryArchiveURLs[0] == "" { - return fmt.Errorf("--history-archive-urls must be set when --ingest is set") - } - - if config.EnableCaptiveCoreIngestion { - stdLog.Println("Preparing captive core...") - - binaryPath := viper.GetString(StellarCoreBinaryPathName) - - // If the user didn't specify a Stellar Core binary, we can check the - // $PATH and possibly fill it in for them. - if binaryPath == "" { - if result, err := exec.LookPath("stellar-core"); err == nil { - binaryPath = result - viper.Set(StellarCoreBinaryPathName, binaryPath) - config.CaptiveCoreBinaryPath = binaryPath - } - } - - // NOTE: If both of these are set (regardless of user- or PATH-supplied - // defaults for the binary path), the Remote Captive Core URL - // takes precedence. - if binaryPath == "" && config.RemoteCaptiveCoreURL == "" { - return fmt.Errorf("Invalid config: captive core requires that either --%s or --remote-captive-core-url is set. %s", - StellarCoreBinaryPathName, captiveCoreMigrationHint) - } - - if config.RemoteCaptiveCoreURL == "" && (binaryPath == "" || config.CaptiveCoreConfigPath == "") { - if options.RequireCaptiveCoreConfig { - var err error - errorMessage := fmt.Errorf( - "Invalid config: captive core requires that both --%s and --%s are set. %s", - StellarCoreBinaryPathName, CaptiveCoreConfigPathName, captiveCoreMigrationHint, - ) - - var configFileName string - // Default config files will be located along the binary in the release archive. - switch config.NetworkPassphrase { - case network.TestNetworkPassphrase: - configFileName = "captive-core-testnet.cfg" - config.HistoryArchiveURLs = []string{"https://history.stellar.org/prd/core-testnet/core_testnet_001/"} - case network.PublicNetworkPassphrase: - configFileName = "captive-core-pubnet.cfg" - config.HistoryArchiveURLs = []string{"https://history.stellar.org/prd/core-live/core_live_001/"} - config.UsingDefaultPubnetConfig = true - default: - return errorMessage - } - - executablePath, err := os.Executable() - if err != nil { - return errorMessage - } - - config.CaptiveCoreConfigPath = filepath.Join(filepath.Dir(executablePath), configFileName) - if _, err = os.Stat(config.CaptiveCoreConfigPath); os.IsNotExist(err) { - return errorMessage - } - - config.CaptiveCoreTomlParams.NetworkPassphrase = config.NetworkPassphrase - config.CaptiveCoreToml, err = ledgerbackend.NewCaptiveCoreTomlFromFile(config.CaptiveCoreConfigPath, config.CaptiveCoreTomlParams) - if err != nil { - return fmt.Errorf("Invalid captive core toml file %v", err) - } - } else { - var err error - config.CaptiveCoreTomlParams.HistoryArchiveURLs = config.HistoryArchiveURLs - config.CaptiveCoreTomlParams.NetworkPassphrase = config.NetworkPassphrase - config.CaptiveCoreToml, err = ledgerbackend.NewCaptiveCoreToml(config.CaptiveCoreTomlParams) - if err != nil { - return fmt.Errorf("Invalid captive core toml file %v", err) - } - } - } else if config.RemoteCaptiveCoreURL == "" { - var err error - config.CaptiveCoreTomlParams.HistoryArchiveURLs = config.HistoryArchiveURLs - config.CaptiveCoreTomlParams.NetworkPassphrase = config.NetworkPassphrase - config.CaptiveCoreToml, err = ledgerbackend.NewCaptiveCoreTomlFromFile(config.CaptiveCoreConfigPath, config.CaptiveCoreTomlParams) - if err != nil { - return fmt.Errorf("Invalid captive core toml file %v", err) - } - } - - // If we don't supply an explicit core URL and we are running a local - // captive core process with the http port enabled, point to it. - if config.StellarCoreURL == "" && config.RemoteCaptiveCoreURL == "" && config.CaptiveCoreToml.HTTPPort != 0 { - config.StellarCoreURL = fmt.Sprintf("http://localhost:%d", config.CaptiveCoreToml.HTTPPort) - viper.Set(StellarCoreURLFlagName, config.StellarCoreURL) - } - } - } else { - if config.EnableCaptiveCoreIngestion && (config.CaptiveCoreBinaryPath != "" || config.CaptiveCoreConfigPath != "") { - captiveCoreConfigFlag := captiveCoreConfigAppendPathName - if viper.GetString(CaptiveCoreConfigPathName) != "" { - captiveCoreConfigFlag = CaptiveCoreConfigPathName - } - return fmt.Errorf("Invalid config: one or more captive core params passed (--%s or --%s) but --ingest not set. "+captiveCoreMigrationHint, - StellarCoreBinaryPathName, captiveCoreConfigFlag) - } - if config.StellarCoreDatabaseURL != "" { - return fmt.Errorf("Invalid config: --%s passed but --ingest not set. ", StellarCoreDBURLFlagName) - } - if config.CaptiveCoreConfigUseDB { - return fmt.Errorf("Invalid config: --%s has been set, but --ingest not set. ", CaptiveCoreConfigUseDB) + err := setCaptiveCoreConfiguration(config, options) + if err != nil { + return errors.Wrap(err, "error generating captive core configuration") } } @@ -726,7 +942,7 @@ func ApplyFlags(config *Config, flags support.ConfigOptions, options ApplyOption if err == nil { log.DefaultLogger.SetOutput(logFile) } else { - return fmt.Errorf("Failed to open file to log: %s", err) + return fmt.Errorf("failed to open file to log: %s", err) } } @@ -741,7 +957,8 @@ func ApplyFlags(config *Config, flags support.ConfigOptions, options ApplyOption } if config.BehindCloudflare && config.BehindAWSLoadBalancer { - return fmt.Errorf("Invalid config: Only one option of --behind-cloudflare and --behind-aws-load-balancer is allowed. If Horizon is behind both, use --behind-cloudflare only.") + return fmt.Errorf("invalid config: Only one option of --behind-cloudflare and --behind-aws-load-balancer is allowed." + + " If Horizon is behind both, use --behind-cloudflare only") } return nil diff --git a/services/horizon/internal/flags_test.go b/services/horizon/internal/flags_test.go new file mode 100644 index 0000000000..b2e617bc00 --- /dev/null +++ b/services/horizon/internal/flags_test.go @@ -0,0 +1,261 @@ +package horizon + +import ( + "fmt" + "os" + "testing" + + "github.com/spf13/cobra" + "github.com/stellar/go/services/horizon/internal/test" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func Test_createCaptiveCoreDefaultConfig(t *testing.T) { + + var errorMsgDefaultConfig = "invalid config: %s parameter not allowed with the network parameter" + tests := []struct { + name string + config Config + networkPassphrase string + historyArchiveURLs []string + errStr string + }{ + { + name: "testnet default config", + config: Config{Network: StellarTestnet, + CaptiveCoreBinaryPath: "/path/to/captive-core/binary", + }, + networkPassphrase: TestnetConf.NetworkPassphrase, + historyArchiveURLs: TestnetConf.HistoryArchiveURLs, + }, + { + name: "pubnet default config", + config: Config{Network: StellarPubnet, + CaptiveCoreBinaryPath: "/path/to/captive-core/binary", + }, + networkPassphrase: PubnetConf.NetworkPassphrase, + historyArchiveURLs: PubnetConf.HistoryArchiveURLs, + }, + { + name: "testnet validation; history archive urls supplied", + config: Config{Network: StellarTestnet, + HistoryArchiveURLs: []string{"network history archive urls supplied"}, + CaptiveCoreBinaryPath: "/path/to/captive-core/binary", + }, + errStr: fmt.Sprintf(errorMsgDefaultConfig, HistoryArchiveURLsFlagName), + }, + { + name: "pubnet validation; history archive urls supplied", + config: Config{Network: StellarPubnet, + HistoryArchiveURLs: []string{"network history archive urls supplied"}, + CaptiveCoreBinaryPath: "/path/to/captive-core/binary", + }, + errStr: fmt.Sprintf(errorMsgDefaultConfig, HistoryArchiveURLsFlagName), + }, + { + name: "testnet validation; network passphrase supplied", + config: Config{Network: StellarTestnet, + NetworkPassphrase: "network passphrase supplied", + HistoryArchiveURLs: []string{}, + CaptiveCoreBinaryPath: "/path/to/captive-core/binary", + }, + errStr: fmt.Sprintf(errorMsgDefaultConfig, NetworkPassphraseFlagName), + }, + { + name: "pubnet validation; network passphrase supplied", + config: Config{Network: StellarPubnet, + NetworkPassphrase: "pubnet network passphrase supplied", + HistoryArchiveURLs: []string{}, + CaptiveCoreBinaryPath: "/path/to/captive-core/binary", + }, + errStr: fmt.Sprintf(errorMsgDefaultConfig, NetworkPassphraseFlagName), + }, + { + name: "unknown network specified", + config: Config{Network: "unknown", + NetworkPassphrase: "", + HistoryArchiveURLs: []string{}, + CaptiveCoreBinaryPath: "/path/to/captive-core/binary", + }, + errStr: "no default configuration found for network unknown", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + e := setCaptiveCoreConfiguration(&tt.config, + ApplyOptions{RequireCaptiveCoreFullConfig: true}) + if tt.errStr == "" { + assert.NoError(t, e) + assert.Equal(t, tt.networkPassphrase, tt.config.NetworkPassphrase) + assert.Equal(t, tt.historyArchiveURLs, tt.config.HistoryArchiveURLs) + assert.Equal(t, tt.networkPassphrase, tt.config.CaptiveCoreTomlParams.NetworkPassphrase) + assert.Equal(t, tt.historyArchiveURLs, tt.config.CaptiveCoreTomlParams.HistoryArchiveURLs) + } else { + assert.Equal(t, tt.errStr, e.Error()) + } + }) + } +} + +func Test_createCaptiveCoreConfig(t *testing.T) { + + var errorMsgConfig = "%s must be set" + tests := []struct { + name string + requireCaptiveCoreConfig bool + config Config + networkPassphrase string + historyArchiveURLs []string + errStr string + }{ + { + name: "no network specified; valid parameters", + requireCaptiveCoreConfig: true, + config: Config{ + NetworkPassphrase: PubnetConf.NetworkPassphrase, + HistoryArchiveURLs: PubnetConf.HistoryArchiveURLs, + CaptiveCoreConfigPath: "configs/captive-core-pubnet.cfg", + CaptiveCoreBinaryPath: "/path/to/captive-core/binary", + }, + networkPassphrase: PubnetConf.NetworkPassphrase, + historyArchiveURLs: PubnetConf.HistoryArchiveURLs, + }, + { + name: "no network specified; passphrase not supplied", + requireCaptiveCoreConfig: true, + config: Config{ + HistoryArchiveURLs: []string{"HistoryArchiveURLs"}, + CaptiveCoreBinaryPath: "/path/to/captive-core/binary", + }, + errStr: fmt.Sprintf(errorMsgConfig, NetworkPassphraseFlagName), + }, + { + name: "no network specified; history archive urls not supplied", + requireCaptiveCoreConfig: true, + config: Config{ + NetworkPassphrase: "NetworkPassphrase", + CaptiveCoreBinaryPath: "/path/to/captive-core/binary", + }, + errStr: fmt.Sprintf(errorMsgConfig, HistoryArchiveURLsFlagName), + }, + { + name: "no network specified; captive-core-config-path not supplied", + requireCaptiveCoreConfig: true, + config: Config{ + NetworkPassphrase: PubnetConf.NetworkPassphrase, + HistoryArchiveURLs: PubnetConf.HistoryArchiveURLs, + CaptiveCoreBinaryPath: "/path/to/captive-core/binary", + }, + errStr: fmt.Sprintf("invalid config: captive core requires that --%s is set or "+ + "you can set the --%s parameter to use the default captive core config", CaptiveCoreConfigPathName, NetworkFlagName), + }, + { + name: "no network specified; captive-core-config-path invalid file", + requireCaptiveCoreConfig: true, + config: Config{ + NetworkPassphrase: PubnetConf.NetworkPassphrase, + HistoryArchiveURLs: PubnetConf.HistoryArchiveURLs, + CaptiveCoreConfigPath: "xyz.cfg", + CaptiveCoreBinaryPath: "/path/to/captive-core/binary", + }, + errStr: "invalid captive core toml file: could not load toml path:" + + " open xyz.cfg: no such file or directory", + }, + { + name: "no network specified; captive-core-config-path incorrect config", + requireCaptiveCoreConfig: true, + config: Config{ + NetworkPassphrase: PubnetConf.NetworkPassphrase, + HistoryArchiveURLs: PubnetConf.HistoryArchiveURLs, + CaptiveCoreConfigPath: "configs/captive-core-testnet.cfg", + CaptiveCoreBinaryPath: "/path/to/captive-core/binary", + }, + errStr: fmt.Sprintf("invalid captive core toml file: invalid captive core toml: "+ + "NETWORK_PASSPHRASE in captive core config file: %s does not match Horizon "+ + "network-passphrase flag: %s", TestnetConf.NetworkPassphrase, PubnetConf.NetworkPassphrase), + }, + { + name: "no network specified; captive-core-config not required", + requireCaptiveCoreConfig: false, + config: Config{ + NetworkPassphrase: PubnetConf.NetworkPassphrase, + HistoryArchiveURLs: PubnetConf.HistoryArchiveURLs, + CaptiveCoreBinaryPath: "/path/to/captive-core/binary", + }, + networkPassphrase: PubnetConf.NetworkPassphrase, + historyArchiveURLs: PubnetConf.HistoryArchiveURLs, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + e := setCaptiveCoreConfiguration(&tt.config, + ApplyOptions{RequireCaptiveCoreFullConfig: tt.requireCaptiveCoreConfig}) + if tt.errStr == "" { + assert.NoError(t, e) + assert.Equal(t, tt.networkPassphrase, tt.config.NetworkPassphrase) + assert.Equal(t, tt.historyArchiveURLs, tt.config.HistoryArchiveURLs) + assert.Equal(t, tt.networkPassphrase, tt.config.CaptiveCoreTomlParams.NetworkPassphrase) + assert.Equal(t, tt.historyArchiveURLs, tt.config.CaptiveCoreTomlParams.HistoryArchiveURLs) + } else { + require.Error(t, e) + assert.Equal(t, tt.errStr, e.Error()) + } + }) + } +} + +func TestEnvironmentVariables(t *testing.T) { + environmentVars := map[string]string{ + "INGEST": "false", + "HISTORY_ARCHIVE_URLS": "http://localhost:1570", + "DATABASE_URL": "postgres://postgres@localhost/test_332cb65e6b00?sslmode=disable&timezone=UTC", + "STELLAR_CORE_URL": "http://localhost:11626", + "NETWORK_PASSPHRASE": "Standalone Network ; February 2017", + "APPLY_MIGRATIONS": "true", + "CHECKPOINT_FREQUENCY": "8", + "MAX_DB_CONNECTIONS": "50", + "ADMIN_PORT": "6060", + "PORT": "8001", + "CAPTIVE_CORE_BINARY_PATH": os.Getenv("HORIZON_INTEGRATION_TESTS_CAPTIVE_CORE_BIN"), + "CAPTIVE_CORE_CONFIG_PATH": "../docker/captive-core-classic-integration-tests.cfg", + "CAPTIVE_CORE_USE_DB": "true", + } + + envManager := test.NewEnvironmentManager() + defer func() { + envManager.Restore() + }() + if err := envManager.InitializeEnvironmentVariables(environmentVars); err != nil { + fmt.Println(err) + } + + config, flags := Flags() + horizonCmd := &cobra.Command{ + Use: "horizon", + Short: "Client-facing api server for the Stellar network", + SilenceErrors: true, + SilenceUsage: true, + Long: "Client-facing API server for the Stellar network.", + } + if err := flags.Init(horizonCmd); err != nil { + fmt.Println(err) + } + if err := ApplyFlags(config, flags, ApplyOptions{RequireCaptiveCoreFullConfig: true, AlwaysIngest: false}); err != nil { + fmt.Println(err) + } + assert.Equal(t, config.Ingest, false) + assert.Equal(t, config.HistoryArchiveURLs, []string{"http://localhost:1570"}) + assert.Equal(t, config.DatabaseURL, "postgres://postgres@localhost/test_332cb65e6b00?sslmode=disable&timezone=UTC") + assert.Equal(t, config.StellarCoreURL, "http://localhost:11626") + assert.Equal(t, config.NetworkPassphrase, "Standalone Network ; February 2017") + assert.Equal(t, config.ApplyMigrations, true) + assert.Equal(t, config.CheckpointFrequency, uint32(8)) + assert.Equal(t, config.MaxDBConnections, 50) + assert.Equal(t, config.AdminPort, uint(6060)) + assert.Equal(t, config.Port, uint(8001)) + assert.Equal(t, config.CaptiveCoreBinaryPath, os.Getenv("HORIZON_INTEGRATION_TESTS_CAPTIVE_CORE_BIN")) + assert.Equal(t, config.CaptiveCoreConfigPath, "../docker/captive-core-classic-integration-tests.cfg") + assert.Equal(t, config.CaptiveCoreConfigUseDB, true) +} diff --git a/services/horizon/internal/helpers_test.go b/services/horizon/internal/helpers_test.go index a5c1dfc0d2..9a78598430 100644 --- a/services/horizon/internal/helpers_test.go +++ b/services/horizon/internal/helpers_test.go @@ -8,7 +8,6 @@ import ( "github.com/stellar/go/network" "github.com/stellar/go/services/horizon/internal/test" - tdb "github.com/stellar/go/services/horizon/internal/test/db" supportLog "github.com/stellar/go/support/log" ) @@ -22,8 +21,7 @@ func NewTestApp(dsn string) *App { func NewTestConfig(dsn string) Config { return Config{ - DatabaseURL: dsn, - StellarCoreDatabaseURL: tdb.StellarCoreURL(), + DatabaseURL: dsn, RateQuota: &throttled.RateQuota{ MaxRate: throttled.PerHour(1000), MaxBurst: 100, diff --git a/services/horizon/internal/httpx/handler.go b/services/horizon/internal/httpx/handler.go index 39fd3c15f5..e17ecb987d 100644 --- a/services/horizon/internal/httpx/handler.go +++ b/services/horizon/internal/httpx/handler.go @@ -104,7 +104,7 @@ func repeatableReadStream( return func() ([]sse.Event, error) { if session != nil { - err := session.BeginTx(&sql.TxOptions{ + err := session.BeginTx(r.Context(), &sql.TxOptions{ Isolation: sql.LevelRepeatableRead, ReadOnly: true, }) diff --git a/services/horizon/internal/httpx/middleware.go b/services/horizon/internal/httpx/middleware.go index 53cc9feff8..cdcd7f4e3c 100644 --- a/services/horizon/internal/httpx/middleware.go +++ b/services/horizon/internal/httpx/middleware.go @@ -276,7 +276,7 @@ func (m *StateMiddleware) WrapFunc(h http.HandlerFunc) http.HandlerFunc { // Otherwise, because the ingestion system is running concurrently with this request, // it is possible to have one read fetch data from ledger N and another read // fetch data from ledger N+1 . - err := session.BeginTx(&sql.TxOptions{ + err := session.BeginTx(ctx, &sql.TxOptions{ Isolation: sql.LevelRepeatableRead, ReadOnly: true, }) diff --git a/services/horizon/internal/httpx/router.go b/services/horizon/internal/httpx/router.go index 24220a60b0..8fa57d0379 100644 --- a/services/horizon/internal/httpx/router.go +++ b/services/horizon/internal/httpx/router.go @@ -38,6 +38,7 @@ type RouterConfig struct { SSEUpdateFrequency time.Duration StaleThreshold uint ConnectionTimeout time.Duration + MaxHTTPRequestSize uint NetworkPassphrase string MaxPathLength uint MaxAssetsPerPathRequest int @@ -48,6 +49,7 @@ type RouterConfig struct { FriendbotURL *url.URL HealthCheck http.Handler EnableIngestionFiltering bool + DisableTxSub bool } type Router struct { @@ -88,13 +90,19 @@ func (r *Router) addMiddleware(config *RouterConfig, })) r.Use(loggerMiddleware(serverMetrics)) r.Use(timeoutMiddleware(config.ConnectionTimeout)) + if config.MaxHTTPRequestSize > 0 { + r.Use(func(handler http.Handler) http.Handler { + return http.MaxBytesHandler(handler, int64(config.MaxHTTPRequestSize)) + }) + } r.Use(recoverMiddleware) r.Use(chimiddleware.Compress(flate.DefaultCompression, "application/hal+json")) c := cors.New(cors.Options{ - AllowedOrigins: []string{"*"}, - AllowedHeaders: []string{"*"}, - ExposedHeaders: []string{"Date", "Latest-Ledger"}, + AllowedOrigins: []string{}, + AllowOriginRequestFunc: func(*http.Request, string) bool { return true }, + AllowedHeaders: []string{"*"}, + ExposedHeaders: []string{"Date", "Latest-Ledger"}, }) r.Use(c.Handler) @@ -319,6 +327,7 @@ func (r *Router) addRoutes(config *RouterConfig, rateLimiter *throttled.HTTPRate r.Method(http.MethodPost, "/transactions", ObjectActionHandler{actions.SubmitTransactionHandler{ Submitter: config.TxSubmitter, NetworkPassphrase: config.NetworkPassphrase, + DisableTxSub: config.DisableTxSub, CoreStateGetter: config.CoreGetter, }}) diff --git a/services/horizon/internal/httpx/server.go b/services/horizon/internal/httpx/server.go index 7d9dc5419f..65058c0ea5 100644 --- a/services/horizon/internal/httpx/server.go +++ b/services/horizon/internal/httpx/server.go @@ -15,7 +15,6 @@ import ( "github.com/stellar/go/services/horizon/internal/ledger" hProblem "github.com/stellar/go/services/horizon/internal/render/problem" "github.com/stellar/go/services/horizon/internal/render/sse" - "github.com/stellar/go/services/horizon/internal/txsub/sequence" "github.com/stellar/go/support/db" "github.com/stellar/go/support/log" "github.com/stellar/go/support/render/problem" @@ -49,7 +48,6 @@ func init() { // register problems problem.SetLogFilter(problem.LogUnknownErrors) problem.RegisterError(sql.ErrNoRows, problem.NotFound) - problem.RegisterError(sequence.ErrNoMoreRoom, hProblem.ServerOverCapacity) problem.RegisterError(db2.ErrInvalidCursor, problem.BadRequest) problem.RegisterError(db2.ErrInvalidLimit, problem.BadRequest) problem.RegisterError(db2.ErrInvalidOrder, problem.BadRequest) @@ -68,7 +66,8 @@ func NewServer(serverConfig ServerConfig, routerConfig RouterConfig, ledgerState RequestDurationSummary: prometheus.NewSummaryVec( prometheus.SummaryOpts{ Namespace: "horizon", Subsystem: "http", Name: "requests_duration_seconds", - Help: "HTTP requests durations, sliding window = 10m", + Help: "HTTP requests durations, sliding window = 10m", + Objectives: map[float64]float64{0.5: 0.05, 0.9: 0.01, 0.99: 0.001}, }, []string{"status", "route", "streaming", "method"}, ), diff --git a/services/horizon/internal/httpx/stream_handler_test.go b/services/horizon/internal/httpx/stream_handler_test.go index fa293ca479..d1b248f10a 100644 --- a/services/horizon/internal/httpx/stream_handler_test.go +++ b/services/horizon/internal/httpx/stream_handler_test.go @@ -13,6 +13,7 @@ import ( "testing" "github.com/go-chi/chi" + "github.com/stretchr/testify/mock" "github.com/stellar/go/services/horizon/internal/actions" horizonContext "github.com/stellar/go/services/horizon/internal/context" @@ -477,13 +478,13 @@ func TestRepeatableReadStream(t *testing.T) { } session := &db.MockSession{} - session.On("BeginTx", &sql.TxOptions{ + session.On("BeginTx", mock.AnythingOfType("*context.cancelCtx"), &sql.TxOptions{ Isolation: sql.LevelRepeatableRead, ReadOnly: true, }).Return(nil).Once() session.On("Rollback").Return(nil).Once() - session.On("BeginTx", &sql.TxOptions{ + session.On("BeginTx", mock.AnythingOfType("*context.cancelCtx"), &sql.TxOptions{ Isolation: sql.LevelRepeatableRead, ReadOnly: true, }).Return(nil).Once() @@ -516,13 +517,13 @@ func TestRepeatableReadStream(t *testing.T) { } session := &db.MockSession{} - session.On("BeginTx", &sql.TxOptions{ + session.On("BeginTx", mock.AnythingOfType("*context.cancelCtx"), &sql.TxOptions{ Isolation: sql.LevelRepeatableRead, ReadOnly: true, }).Return(nil).Once() session.On("Rollback").Return(nil).Once() - session.On("BeginTx", &sql.TxOptions{ + session.On("BeginTx", mock.AnythingOfType("*context.cancelCtx"), &sql.TxOptions{ Isolation: sql.LevelRepeatableRead, ReadOnly: true, }).Return(nil).Once() diff --git a/services/horizon/internal/ingest/docs.md b/services/horizon/internal/ingest/README.md similarity index 100% rename from services/horizon/internal/ingest/docs.md rename to services/horizon/internal/ingest/README.md diff --git a/services/horizon/internal/ingest/build_state_test.go b/services/horizon/internal/ingest/build_state_test.go index f7779f6f72..7e03818795 100644 --- a/services/horizon/internal/ingest/build_state_test.go +++ b/services/horizon/internal/ingest/build_state_test.go @@ -50,7 +50,7 @@ func (s *BuildStateTestSuite) SetupTest() { } s.system.initMetrics() - s.historyQ.On("Begin").Return(nil).Once() + s.historyQ.On("Begin", s.ctx).Return(nil).Once() s.historyQ.On("Rollback").Return(nil).Once() s.ledgerBackend.On("IsPrepared", s.ctx, ledgerbackend.UnboundedRange(63)).Return(false, nil).Once() @@ -136,7 +136,7 @@ func (s *BuildStateTestSuite) TestRangeNotPreparedSuccessPrepareGetLedgerFail() func (s *BuildStateTestSuite) TestBeginReturnsError() { // Recreate mock in this single test to remove assertions. *s.historyQ = mockDBQ{} - s.historyQ.On("Begin").Return(errors.New("my error")).Once() + s.historyQ.On("Begin", s.ctx).Return(errors.New("my error")).Once() next, err := buildState{checkpointLedger: s.checkpointLedger}.run(s.system) s.Assert().Error(err) @@ -232,7 +232,7 @@ func (s *BuildStateTestSuite) TestTruncateIngestStateTablesReturnsError() { func (s *BuildStateTestSuite) TestRunHistoryArchiveIngestionReturnsError() { s.mockCommonHistoryQ() s.runner. - On("RunHistoryArchiveIngestion", s.checkpointLedger, MaxSupportedProtocolVersion, xdr.Hash{1, 2, 3}). + On("RunHistoryArchiveIngestion", s.checkpointLedger, false, MaxSupportedProtocolVersion, xdr.Hash{1, 2, 3}). Return(ingest.StatsChangeProcessorResults{}, errors.New("my error")). Once() next, err := buildState{checkpointLedger: s.checkpointLedger}.run(s.system) @@ -272,7 +272,7 @@ func (s *BuildStateTestSuite) TestRunHistoryArchiveIngestionGenesisReturnsError( func (s *BuildStateTestSuite) TestUpdateLastLedgerIngestAfterIngestReturnsError() { s.mockCommonHistoryQ() s.runner. - On("RunHistoryArchiveIngestion", s.checkpointLedger, MaxSupportedProtocolVersion, xdr.Hash{1, 2, 3}). + On("RunHistoryArchiveIngestion", s.checkpointLedger, false, MaxSupportedProtocolVersion, xdr.Hash{1, 2, 3}). Return(ingest.StatsChangeProcessorResults{}, nil). Once() s.historyQ.On("UpdateIngestVersion", s.ctx, CurrentVersion). @@ -291,7 +291,7 @@ func (s *BuildStateTestSuite) TestUpdateLastLedgerIngestAfterIngestReturnsError( func (s *BuildStateTestSuite) TestUpdateIngestVersionIngestReturnsError() { s.mockCommonHistoryQ() s.runner. - On("RunHistoryArchiveIngestion", s.checkpointLedger, MaxSupportedProtocolVersion, xdr.Hash{1, 2, 3}). + On("RunHistoryArchiveIngestion", s.checkpointLedger, false, MaxSupportedProtocolVersion, xdr.Hash{1, 2, 3}). Return(ingest.StatsChangeProcessorResults{}, nil). Once() s.historyQ.On("UpdateIngestVersion", s.ctx, CurrentVersion). @@ -307,7 +307,7 @@ func (s *BuildStateTestSuite) TestUpdateIngestVersionIngestReturnsError() { func (s *BuildStateTestSuite) TestUpdateCommitReturnsError() { s.mockCommonHistoryQ() s.runner. - On("RunHistoryArchiveIngestion", s.checkpointLedger, MaxSupportedProtocolVersion, xdr.Hash{1, 2, 3}). + On("RunHistoryArchiveIngestion", s.checkpointLedger, false, MaxSupportedProtocolVersion, xdr.Hash{1, 2, 3}). Return(ingest.StatsChangeProcessorResults{}, nil). Once() s.historyQ.On("UpdateLastLedgerIngest", s.ctx, s.checkpointLedger). @@ -329,7 +329,7 @@ func (s *BuildStateTestSuite) TestUpdateCommitReturnsError() { func (s *BuildStateTestSuite) TestBuildStateSucceeds() { s.mockCommonHistoryQ() s.runner. - On("RunHistoryArchiveIngestion", s.checkpointLedger, MaxSupportedProtocolVersion, xdr.Hash{1, 2, 3}). + On("RunHistoryArchiveIngestion", s.checkpointLedger, false, MaxSupportedProtocolVersion, xdr.Hash{1, 2, 3}). Return(ingest.StatsChangeProcessorResults{}, nil). Once() s.historyQ.On("UpdateLastLedgerIngest", s.ctx, s.checkpointLedger). @@ -357,7 +357,7 @@ func (s *BuildStateTestSuite) TestBuildStateSucceeds() { func (s *BuildStateTestSuite) TestUpdateCommitReturnsErrorStop() { s.mockCommonHistoryQ() s.runner. - On("RunHistoryArchiveIngestion", s.checkpointLedger, MaxSupportedProtocolVersion, xdr.Hash{1, 2, 3}). + On("RunHistoryArchiveIngestion", s.checkpointLedger, false, MaxSupportedProtocolVersion, xdr.Hash{1, 2, 3}). Return(ingest.StatsChangeProcessorResults{}, nil). Once() s.historyQ.On("UpdateLastLedgerIngest", s.ctx, s.checkpointLedger). @@ -379,7 +379,7 @@ func (s *BuildStateTestSuite) TestUpdateCommitReturnsErrorStop() { func (s *BuildStateTestSuite) TestBuildStateSucceedStop() { s.mockCommonHistoryQ() s.runner. - On("RunHistoryArchiveIngestion", s.checkpointLedger, MaxSupportedProtocolVersion, xdr.Hash{1, 2, 3}). + On("RunHistoryArchiveIngestion", s.checkpointLedger, false, MaxSupportedProtocolVersion, xdr.Hash{1, 2, 3}). Return(ingest.StatsChangeProcessorResults{}, nil). Once() s.historyQ.On("UpdateLastLedgerIngest", s.ctx, s.checkpointLedger). diff --git a/services/horizon/internal/ingest/db_integration_test.go b/services/horizon/internal/ingest/db_integration_test.go index 2857a277ef..86576db137 100644 --- a/services/horizon/internal/ingest/db_integration_test.go +++ b/services/horizon/internal/ingest/db_integration_test.go @@ -83,7 +83,7 @@ func (s *DBTestSuite) SetupTest() { sIface, err := NewSystem(Config{ CoreSession: s.tt.CoreSession(), HistorySession: s.tt.HorizonSession(), - HistoryArchiveURL: "http://ignore.test", + HistoryArchiveURLs: []string{"http://ignore.test"}, DisableStateVerification: false, CheckpointFrequency: 64, }) diff --git a/services/horizon/internal/ingest/fsm.go b/services/horizon/internal/ingest/fsm.go index be71242c9d..f5b4f94456 100644 --- a/services/horizon/internal/ingest/fsm.go +++ b/services/horizon/internal/ingest/fsm.go @@ -12,7 +12,6 @@ import ( "github.com/stellar/go/ingest/ledgerbackend" "github.com/stellar/go/support/errors" logpkg "github.com/stellar/go/support/log" - "github.com/stellar/go/toid" "github.com/stellar/go/xdr" ) @@ -30,9 +29,25 @@ func (e ErrReingestRangeConflict) Error() string { return fmt.Sprintf("reingest range overlaps with horizon ingestion, supplied range shouldn't contain ledger %d", e.maximumLedgerSequence) } +type State int + +const ( + None State = iota + Start + Stop + Build + Resume + WaitForCheckpoint + StressTest + VerifyRange + HistoryRange + ReingestHistoryRange +) + type stateMachineNode interface { run(*system) (transition, error) String() string + GetState() State } type transition struct { @@ -105,6 +120,10 @@ func (stopState) String() string { return "stop" } +func (stopState) GetState() State { + return Stop +} + func (stopState) run(s *system) (transition, error) { return stop(), errors.New("Cannot run terminal state") } @@ -117,8 +136,12 @@ func (startState) String() string { return "start" } +func (startState) GetState() State { + return Start +} + func (state startState) run(s *system) (transition, error) { - if err := s.historyQ.Begin(); err != nil { + if err := s.historyQ.Begin(s.ctx); err != nil { return start(), errors.Wrap(err, "Error starting a transaction") } defer s.historyQ.Rollback() @@ -226,11 +249,16 @@ func (state startState) run(s *system) (transition, error) { type buildState struct { checkpointLedger uint32 + skipChecks bool stop bool } func (b buildState) String() string { - return fmt.Sprintf("buildFromCheckpoint(checkpointLedger=%d)", b.checkpointLedger) + return fmt.Sprintf("buildFromCheckpoint(checkpointLedger=%d, skipChecks=%t)", b.checkpointLedger, b.skipChecks) +} + +func (buildState) GetState() State { + return Build } func (b buildState) run(s *system) (transition, error) { @@ -248,8 +276,11 @@ func (b buildState) run(s *system) (transition, error) { // In the long term we should probably create artificial xdr.LedgerCloseMeta // for ledger #1 instead of using `ingest.GenesisChange` reader in // ProcessorRunner.RunHistoryArchiveIngestion(). - var ledgerCloseMeta xdr.LedgerCloseMeta - if b.checkpointLedger != 1 { + // We can also skip preparing range if `skipChecks` is `true` because we + // won't need bucket list hash and protocol version. + var protocolVersion uint32 + var bucketListHash xdr.Hash + if b.checkpointLedger != 1 && !b.skipChecks { err := s.maybePrepareRange(s.ctx, b.checkpointLedger) if err != nil { return nextFailState, err @@ -257,7 +288,7 @@ func (b buildState) run(s *system) (transition, error) { log.WithField("sequence", b.checkpointLedger).Info("Waiting for ledger to be available in the backend...") startTime := time.Now() - ledgerCloseMeta, err = s.ledgerBackend.GetLedger(s.ctx, b.checkpointLedger) + ledgerCloseMeta, err := s.ledgerBackend.GetLedger(s.ctx, b.checkpointLedger) if err != nil { return nextFailState, errors.Wrap(err, "error getting ledger blocking") } @@ -265,9 +296,12 @@ func (b buildState) run(s *system) (transition, error) { "sequence": b.checkpointLedger, "duration": time.Since(startTime).Seconds(), }).Info("Ledger returned from the backend") + + protocolVersion = ledgerCloseMeta.ProtocolVersion() + bucketListHash = ledgerCloseMeta.BucketListHash() } - if err := s.historyQ.Begin(); err != nil { + if err := s.historyQ.Begin(s.ctx); err != nil { return nextFailState, errors.Wrap(err, "Error starting a transaction") } defer s.historyQ.Rollback() @@ -328,9 +362,10 @@ func (b buildState) run(s *system) (transition, error) { stats, err = s.runner.RunGenesisStateIngestion() } else { stats, err = s.runner.RunHistoryArchiveIngestion( - ledgerCloseMeta.LedgerSequence(), - ledgerCloseMeta.ProtocolVersion(), - ledgerCloseMeta.BucketListHash(), + b.checkpointLedger, + b.skipChecks, + protocolVersion, + bucketListHash, ) } @@ -369,6 +404,10 @@ func (r resumeState) String() string { return fmt.Sprintf("resume(latestSuccessfullyProcessedLedger=%d)", r.latestSuccessfullyProcessedLedger) } +func (resumeState) GetState() State { + return Resume +} + func (r resumeState) run(s *system) (transition, error) { if r.latestSuccessfullyProcessedLedger == 0 { return start(), errors.New("unexpected latestSuccessfullyProcessedLedger value") @@ -395,9 +434,7 @@ func (r resumeState) run(s *system) (transition, error) { "duration": duration, }).Info("Ledger returned from the backend") - s.Metrics().LedgerFetchDurationSummary.Observe(float64(duration)) - - if err = s.historyQ.Begin(); err != nil { + if err = s.historyQ.Begin(s.ctx); err != nil { return retryResume(r), errors.Wrap(err, "Error starting a transaction") } @@ -419,13 +456,12 @@ func (r resumeState) run(s *system) (transition, error) { // Update cursor if there's more than one ingesting instance: either // Captive-Core or DB ingestion connected to another Stellar-Core. + // remove now? if err = s.updateCursor(lastIngestedLedger); err != nil { // Don't return updateCursor error. log.WithError(err).Warn("error updating stellar-core cursor") } - s.maybeVerifyState(ingestLedger) - // resume immediately so Captive-Core catchup is not slowed down return resumeImmediately(lastIngestedLedger), nil } @@ -477,7 +513,7 @@ func (r resumeState) run(s *system) (transition, error) { rebuildStart := time.Now() err = s.historyQ.RebuildTradeAggregationBuckets(s.ctx, ingestLedger, ingestLedger, s.config.RoundingSlippageFilter) if err != nil { - return stop(), errors.Wrap(err, "error rebuilding trade aggregations") + return retryResume(r), errors.Wrap(err, "error rebuilding trade aggregations") } rebuildDuration := time.Since(rebuildStart).Seconds() s.Metrics().LedgerIngestionTradeAggregationDuration.Observe(float64(rebuildDuration)) @@ -486,6 +522,7 @@ func (r resumeState) run(s *system) (transition, error) { return retryResume(r), err } + //TODO remove now? stellar-core-db-url is removed if err = s.updateCursor(ingestLedger); err != nil { // Don't return updateCursor error. log.WithError(err).Warn("error updating stellar-core cursor") @@ -547,286 +584,16 @@ func (r resumeState) addProcessorDurationsMetricFromMap(s *system, m map[string] } } -type historyRangeState struct { - fromLedger uint32 - toLedger uint32 -} - -func (h historyRangeState) String() string { - return fmt.Sprintf( - "historyRange(fromLedger=%d, toLedger=%d)", - h.fromLedger, - h.toLedger, - ) -} - -// historyRangeState is used when catching up history data -func (h historyRangeState) run(s *system) (transition, error) { - if h.fromLedger == 0 || h.toLedger == 0 || - h.fromLedger > h.toLedger { - return start(), errors.Errorf("invalid range: [%d, %d]", h.fromLedger, h.toLedger) - } - - err := s.maybePrepareRange(s.ctx, h.fromLedger) - if err != nil { - return start(), err - } - - if err = s.historyQ.Begin(); err != nil { - return start(), errors.Wrap(err, "Error starting a transaction") - } - defer s.historyQ.Rollback() - - // acquire distributed lock so no one else can perform ingestion operations. - if _, err = s.historyQ.GetLastLedgerIngest(s.ctx); err != nil { - return start(), errors.Wrap(err, getLastIngestedErrMsg) - } - - lastHistoryLedger, err := s.historyQ.GetLatestHistoryLedger(s.ctx) - if err != nil { - return start(), errors.Wrap(err, "could not get latest history ledger") - } - - // We should be ingesting the ledger which occurs after - // lastHistoryLedger. Otherwise, some other horizon node has - // already completed the ingest history range operation and - // we should go back to the init state - if lastHistoryLedger != h.fromLedger-1 { - return start(), nil - } - - for cur := h.fromLedger; cur <= h.toLedger; cur++ { - var ledgerCloseMeta xdr.LedgerCloseMeta - - log.WithField("sequence", cur).Info("Waiting for ledger to be available in the backend...") - startTime := time.Now() - - ledgerCloseMeta, err = s.ledgerBackend.GetLedger(s.ctx, cur) - if err != nil { - // Commit finished work in case of ledger backend error. - commitErr := s.historyQ.Commit() - if commitErr != nil { - log.WithError(commitErr).Error("Error commiting partial range results") - } else { - log.Info("Commited partial range results") - } - return start(), errors.Wrap(err, "error getting ledger") - } - - log.WithFields(logpkg.F{ - "sequence": cur, - "duration": time.Since(startTime).Seconds(), - }).Info("Ledger returned from the backend") - - if err = runTransactionProcessorsOnLedger(s, ledgerCloseMeta); err != nil { - return start(), err - } - } - - if err = s.historyQ.Commit(); err != nil { - return start(), errors.Wrap(err, commitErrMsg) - } - - return start(), nil -} - -func runTransactionProcessorsOnLedger(s *system, ledger xdr.LedgerCloseMeta) error { - log.WithFields(logpkg.F{ - "sequence": ledger.LedgerSequence(), - "state": false, - "ledger": true, - "commit": false, - }).Info("Processing ledger") - startTime := time.Now() - - ledgerTransactionStats, _, tradeStats, err := s.runner.RunTransactionProcessorsOnLedger(ledger) - if err != nil { - return errors.Wrap(err, fmt.Sprintf("error processing ledger sequence=%d", ledger.LedgerSequence())) - } - - log. - WithFields(ledgerTransactionStats.Map()). - WithFields(tradeStats.Map()). - WithFields(logpkg.F{ - "sequence": ledger.LedgerSequence(), - "duration": time.Since(startTime).Seconds(), - "state": false, - "ledger": true, - "commit": false, - }). - Info("Processed ledger") - return nil -} - -type reingestHistoryRangeState struct { - fromLedger uint32 - toLedger uint32 - force bool -} - -func (h reingestHistoryRangeState) String() string { - return fmt.Sprintf( - "reingestHistoryRange(fromLedger=%d, toLedger=%d, force=%t)", - h.fromLedger, - h.toLedger, - h.force, - ) -} - -func (h reingestHistoryRangeState) ingestRange(s *system, fromLedger, toLedger uint32) error { - if s.historyQ.GetTx() == nil { - return errors.New("expected transaction to be present") - } - - // Clear history data before ingesting - used in `reingest range` command. - start, end, err := toid.LedgerRangeInclusive( - int32(fromLedger), - int32(toLedger), - ) - if err != nil { - return errors.Wrap(err, "Invalid range") - } - - err = s.historyQ.DeleteRangeAll(s.ctx, start, end) - if err != nil { - return errors.Wrap(err, "error in DeleteRangeAll") - } - - for cur := fromLedger; cur <= toLedger; cur++ { - var ledgerCloseMeta xdr.LedgerCloseMeta - ledgerCloseMeta, err = s.ledgerBackend.GetLedger(s.ctx, cur) - if err != nil { - return errors.Wrap(err, "error getting ledger") - } - - if err = runTransactionProcessorsOnLedger(s, ledgerCloseMeta); err != nil { - return err - } - } - - return nil -} - -func (h reingestHistoryRangeState) prepareRange(s *system) (transition, error) { - log.WithFields(logpkg.F{ - "from": h.fromLedger, - "to": h.toLedger, - }).Info("Preparing ledger backend to retrieve range") - startTime := time.Now() - - err := s.ledgerBackend.PrepareRange(s.ctx, ledgerbackend.BoundedRange(h.fromLedger, h.toLedger)) - if err != nil { - return stop(), errors.Wrap(err, "error preparing range") - } - - log.WithFields(logpkg.F{ - "from": h.fromLedger, - "to": h.toLedger, - "duration": time.Since(startTime).Seconds(), - }).Info("Range ready") - - return transition{}, nil -} - -// reingestHistoryRangeState is used as a command to reingest historical data -func (h reingestHistoryRangeState) run(s *system) (transition, error) { - if h.fromLedger == 0 || h.toLedger == 0 || - h.fromLedger > h.toLedger { - return stop(), errors.Errorf("invalid range: [%d, %d]", h.fromLedger, h.toLedger) - } - - if h.fromLedger == 1 { - log.Warn("Ledger 1 is pregenerated and not available, starting from ledger 2.") - h.fromLedger = 2 - } - - var startTime time.Time - - if h.force { - if t, err := h.prepareRange(s); err != nil { - return t, err - } - startTime = time.Now() - - if err := s.historyQ.Begin(); err != nil { - return stop(), errors.Wrap(err, "Error starting a transaction") - } - defer s.historyQ.Rollback() - - // acquire distributed lock so no one else can perform ingestion operations. - if _, err := s.historyQ.GetLastLedgerIngest(s.ctx); err != nil { - return stop(), errors.Wrap(err, getLastIngestedErrMsg) - } - - if err := h.ingestRange(s, h.fromLedger, h.toLedger); err != nil { - return stop(), err - } - - if err := s.historyQ.Commit(); err != nil { - return stop(), errors.Wrap(err, commitErrMsg) - } - } else { - lastIngestedLedger, err := s.historyQ.GetLastLedgerIngestNonBlocking(s.ctx) - if err != nil { - return stop(), errors.Wrap(err, getLastIngestedErrMsg) - } - - if lastIngestedLedger > 0 && h.toLedger >= lastIngestedLedger { - return stop(), ErrReingestRangeConflict{lastIngestedLedger} - } - - // Only prepare the range after checking the bounds to enable an early error return - var t transition - if t, err = h.prepareRange(s); err != nil { - return t, err - } - startTime = time.Now() - - for cur := h.fromLedger; cur <= h.toLedger; cur++ { - err = func(ledger uint32) error { - if e := s.historyQ.Begin(); e != nil { - return errors.Wrap(e, "Error starting a transaction") - } - defer s.historyQ.Rollback() - - // ingest each ledger in a separate transaction to prevent deadlocks - // when acquiring ShareLocks from multiple parallel reingest range processes - if e := h.ingestRange(s, ledger, ledger); e != nil { - return e - } - - if e := s.historyQ.Commit(); e != nil { - return errors.Wrap(e, commitErrMsg) - } - - return nil - }(cur) - if err != nil { - return stop(), err - } - } - } - - err := s.historyQ.RebuildTradeAggregationBuckets(s.ctx, h.fromLedger, h.toLedger, s.config.RoundingSlippageFilter) - if err != nil { - return stop(), errors.Wrap(err, "Error rebuilding trade aggregations") - } - - log.WithFields(logpkg.F{ - "from": h.fromLedger, - "to": h.toLedger, - "duration": time.Since(startTime).Seconds(), - }).Info("Reingestion done") - - return stop(), nil -} - type waitForCheckpointState struct{} func (waitForCheckpointState) String() string { return "waitForCheckpoint" } +func (waitForCheckpointState) GetState() State { + return WaitForCheckpoint +} + func (waitForCheckpointState) run(*system) (transition, error) { log.Info("Waiting for the next checkpoint...") time.Sleep(10 * time.Second) @@ -848,13 +615,17 @@ func (v verifyRangeState) String() string { ) } +func (verifyRangeState) GetState() State { + return VerifyRange +} + func (v verifyRangeState) run(s *system) (transition, error) { if v.fromLedger == 0 || v.toLedger == 0 || v.fromLedger > v.toLedger { return stop(), errors.Errorf("invalid range: [%d, %d]", v.fromLedger, v.toLedger) } - if err := s.historyQ.Begin(); err != nil { + if err := s.historyQ.Begin(s.ctx); err != nil { err = errors.Wrap(err, "Error starting a transaction") return stop(), err } @@ -895,6 +666,7 @@ func (v verifyRangeState) run(s *system) (transition, error) { stats, err := s.runner.RunHistoryArchiveIngestion( ledgerCloseMeta.LedgerSequence(), + false, ledgerCloseMeta.ProtocolVersion(), ledgerCloseMeta.BucketListHash(), ) @@ -924,7 +696,7 @@ func (v verifyRangeState) run(s *system) (transition, error) { }).Info("Processing ledger") startTime := time.Now() - if err = s.historyQ.Begin(); err != nil { + if err = s.historyQ.Begin(s.ctx); err != nil { err = errors.Wrap(err, "Error starting a transaction") return stop(), err } @@ -978,8 +750,12 @@ func (stressTestState) String() string { return "stressTest" } +func (stressTestState) GetState() State { + return StressTest +} + func (stressTestState) run(s *system) (transition, error) { - if err := s.historyQ.Begin(); err != nil { + if err := s.historyQ.Begin(s.ctx); err != nil { err = errors.Wrap(err, "Error starting a transaction") return stop(), err } diff --git a/services/horizon/internal/ingest/fsm_history_range_state.go b/services/horizon/internal/ingest/fsm_history_range_state.go new file mode 100644 index 0000000000..0aa65795a9 --- /dev/null +++ b/services/horizon/internal/ingest/fsm_history_range_state.go @@ -0,0 +1,111 @@ +package ingest + +import ( + "fmt" + "time" + + "github.com/stellar/go/support/errors" + logpkg "github.com/stellar/go/support/log" + "github.com/stellar/go/xdr" +) + +type historyRangeState struct { + fromLedger uint32 + toLedger uint32 +} + +func (h historyRangeState) String() string { + return fmt.Sprintf( + "historyRange(fromLedger=%d, toLedger=%d)", + h.fromLedger, + h.toLedger, + ) +} + +func (historyRangeState) GetState() State { + return HistoryRange +} + +// historyRangeState is used when catching up history data +func (h historyRangeState) run(s *system) (transition, error) { + if h.fromLedger == 0 || h.toLedger == 0 || + h.fromLedger > h.toLedger { + return start(), errors.Errorf("invalid range: [%d, %d]", h.fromLedger, h.toLedger) + } + + if s.maxLedgerPerFlush < 1 { + return start(), errors.New("invalid maxLedgerPerFlush, must be greater than 0") + } + + err := s.maybePrepareRange(s.ctx, h.fromLedger) + if err != nil { + return start(), err + } + + if err = s.historyQ.Begin(s.ctx); err != nil { + return start(), errors.Wrap(err, "Error starting a transaction") + } + defer s.historyQ.Rollback() + + // acquire distributed lock so no one else can perform ingestion operations. + if _, err = s.historyQ.GetLastLedgerIngest(s.ctx); err != nil { + return start(), errors.Wrap(err, getLastIngestedErrMsg) + } + + lastHistoryLedger, err := s.historyQ.GetLatestHistoryLedger(s.ctx) + if err != nil { + return start(), errors.Wrap(err, "could not get latest history ledger") + } + + // We should be ingesting the ledger which occurs after + // lastHistoryLedger. Otherwise, some other horizon node has + // already completed the ingest history range operation and + // we should go back to the init state + if lastHistoryLedger != h.fromLedger-1 { + return start(), nil + } + + ledgers := make([]xdr.LedgerCloseMeta, 0, s.maxLedgerPerFlush) + for cur := h.fromLedger; cur <= h.toLedger; cur++ { + var ledgerCloseMeta xdr.LedgerCloseMeta + + log.WithField("sequence", cur).Info("Waiting for ledger to be available in the backend...") + startTime := time.Now() + + ledgerCloseMeta, err = s.ledgerBackend.GetLedger(s.ctx, cur) + if err != nil { + // Commit prior batches that have been flushed in case of ledger backend error. + commitErr := s.historyQ.Commit() + if commitErr != nil { + log.WithError(commitErr).Error("Error committing partial range results") + } else { + log.Info("Committed partial range results") + } + return start(), errors.Wrap(err, "error getting ledger") + } + + log.WithFields(logpkg.F{ + "sequence": cur, + "duration": time.Since(startTime).Seconds(), + }).Info("Ledger returned from the backend") + ledgers = append(ledgers, ledgerCloseMeta) + + if len(ledgers) == cap(ledgers) { + if err = s.runner.RunTransactionProcessorsOnLedgers(ledgers); err != nil { + return start(), errors.Wrapf(err, "error processing ledger range %d - %d", ledgers[0].LedgerSequence(), ledgers[len(ledgers)-1].LedgerSequence()) + } + ledgers = ledgers[0:0] + } + } + + if len(ledgers) > 0 { + if err = s.runner.RunTransactionProcessorsOnLedgers(ledgers); err != nil { + return start(), errors.Wrapf(err, "error processing ledger range %d - %d", ledgers[0].LedgerSequence(), ledgers[len(ledgers)-1].LedgerSequence()) + } + } + if err = s.historyQ.Commit(); err != nil { + return start(), errors.Wrap(err, commitErrMsg) + } + + return start(), nil +} diff --git a/services/horizon/internal/ingest/fsm_reingest_history_range_state.go b/services/horizon/internal/ingest/fsm_reingest_history_range_state.go new file mode 100644 index 0000000000..4e60f71cd1 --- /dev/null +++ b/services/horizon/internal/ingest/fsm_reingest_history_range_state.go @@ -0,0 +1,196 @@ +package ingest + +import ( + "fmt" + "time" + + "github.com/stellar/go/ingest/ledgerbackend" + "github.com/stellar/go/support/errors" + logpkg "github.com/stellar/go/support/log" + "github.com/stellar/go/toid" + "github.com/stellar/go/xdr" +) + +type reingestHistoryRangeState struct { + fromLedger uint32 + toLedger uint32 + force bool +} + +func (h reingestHistoryRangeState) String() string { + return fmt.Sprintf( + "reingestHistoryRange(fromLedger=%d, toLedger=%d, force=%t)", + h.fromLedger, + h.toLedger, + h.force, + ) +} + +func (reingestHistoryRangeState) GetState() State { + return ReingestHistoryRange +} + +func (h reingestHistoryRangeState) ingestRange(s *system, fromLedger, toLedger uint32) error { + if s.historyQ.GetTx() == nil { + return errors.New("expected transaction to be present") + } + + if s.maxLedgerPerFlush < 1 { + return errors.New("invalid maxLedgerPerFlush, must be greater than 0") + } + + // Clear history data before ingesting - used in `reingest range` command. + start, end, err := toid.LedgerRangeInclusive( + int32(fromLedger), + int32(toLedger), + ) + if err != nil { + return errors.Wrap(err, "Invalid range") + } + + err = s.historyQ.DeleteRangeAll(s.ctx, start, end) + if err != nil { + return errors.Wrap(err, "error in DeleteRangeAll") + } + + // s.maxLedgerPerFlush has been validated to be at least 1 + ledgers := make([]xdr.LedgerCloseMeta, 0, s.maxLedgerPerFlush) + + for cur := fromLedger; cur <= toLedger; cur++ { + var ledgerCloseMeta xdr.LedgerCloseMeta + + log.WithField("sequence", cur).Info("Waiting for ledger to be available in the backend...") + startTime := time.Now() + ledgerCloseMeta, err = s.ledgerBackend.GetLedger(s.ctx, cur) + + if err != nil { + return errors.Wrap(err, "error getting ledger") + } + + log.WithFields(logpkg.F{ + "sequence": cur, + "duration": time.Since(startTime).Seconds(), + }).Info("Ledger returned from the backend") + + ledgers = append(ledgers, ledgerCloseMeta) + + if len(ledgers)%int(s.maxLedgerPerFlush) == 0 { + if err = s.runner.RunTransactionProcessorsOnLedgers(ledgers); err != nil { + return errors.Wrapf(err, "error processing ledger range %d - %d", ledgers[0].LedgerSequence(), ledgers[len(ledgers)-1].LedgerSequence()) + } + ledgers = ledgers[0:0] + } + } + + if len(ledgers) > 0 { + if err = s.runner.RunTransactionProcessorsOnLedgers(ledgers); err != nil { + return errors.Wrapf(err, "error processing ledger range %d - %d", ledgers[0].LedgerSequence(), ledgers[len(ledgers)-1].LedgerSequence()) + } + } + + return nil +} + +func (h reingestHistoryRangeState) prepareRange(s *system) (transition, error) { + log.WithFields(logpkg.F{ + "from": h.fromLedger, + "to": h.toLedger, + }).Info("Preparing ledger backend to retrieve range") + startTime := time.Now() + + err := s.ledgerBackend.PrepareRange(s.ctx, ledgerbackend.BoundedRange(h.fromLedger, h.toLedger)) + if err != nil { + return stop(), errors.Wrap(err, "error preparing range") + } + + log.WithFields(logpkg.F{ + "from": h.fromLedger, + "to": h.toLedger, + "duration": time.Since(startTime).Seconds(), + }).Info("Range ready") + + return transition{}, nil +} + +// reingestHistoryRangeState is used as a command to reingest historical data +func (h reingestHistoryRangeState) run(s *system) (transition, error) { + if h.fromLedger == 0 || h.toLedger == 0 || + h.fromLedger > h.toLedger { + return stop(), errors.Errorf("invalid range: [%d, %d]", h.fromLedger, h.toLedger) + } + + if h.fromLedger == 1 { + log.Warn("Ledger 1 is pregenerated and not available, starting from ledger 2.") + h.fromLedger = 2 + } + + startTime := time.Now() + + if h.force { + if t, err := h.prepareRange(s); err != nil { + return t, err + } + + if err := s.historyQ.Begin(s.ctx); err != nil { + return stop(), errors.Wrap(err, "Error starting a transaction") + } + defer s.historyQ.Rollback() + + // acquire distributed lock so no one else can perform ingestion operations. + if _, err := s.historyQ.GetLastLedgerIngest(s.ctx); err != nil { + return stop(), errors.Wrap(err, getLastIngestedErrMsg) + } + + if ingestErr := h.ingestRange(s, h.fromLedger, h.toLedger); ingestErr != nil { + if err := s.historyQ.Commit(); err != nil { + return stop(), errors.Wrap(ingestErr, commitErrMsg) + } + return stop(), ingestErr + } + + if err := s.historyQ.Commit(); err != nil { + return stop(), errors.Wrap(err, commitErrMsg) + } + } else { + lastIngestedLedger, err := s.historyQ.GetLastLedgerIngestNonBlocking(s.ctx) + if err != nil { + return stop(), errors.Wrap(err, getLastIngestedErrMsg) + } + + if lastIngestedLedger > 0 && h.toLedger >= lastIngestedLedger { + return stop(), ErrReingestRangeConflict{lastIngestedLedger} + } + + // Only prepare the range after checking the bounds to enable an early error return + var t transition + if t, err = h.prepareRange(s); err != nil { + return t, err + } + + if err := s.historyQ.Begin(s.ctx); err != nil { + return stop(), errors.Wrap(err, "Error starting a transaction") + } + defer s.historyQ.Rollback() + + if e := h.ingestRange(s, h.fromLedger, h.toLedger); e != nil { + return stop(), e + } + + if e := s.historyQ.Commit(); e != nil { + return stop(), errors.Wrap(e, commitErrMsg) + } + } + + err := s.historyQ.RebuildTradeAggregationBuckets(s.ctx, h.fromLedger, h.toLedger, s.config.RoundingSlippageFilter) + if err != nil { + return stop(), errors.Wrap(err, "Error rebuilding trade aggregations") + } + + log.WithFields(logpkg.F{ + "from": h.fromLedger, + "to": h.toLedger, + "duration": time.Since(startTime).Seconds(), + }).Info("Reingestion done") + + return stop(), nil +} diff --git a/services/horizon/internal/ingest/group_processors.go b/services/horizon/internal/ingest/group_processors.go index 86622810b5..5af3d024ef 100644 --- a/services/horizon/internal/ingest/group_processors.go +++ b/services/horizon/internal/ingest/group_processors.go @@ -7,7 +7,9 @@ import ( "github.com/stellar/go/ingest" "github.com/stellar/go/services/horizon/internal/ingest/processors" + "github.com/stellar/go/support/db" "github.com/stellar/go/support/errors" + "github.com/stellar/go/xdr" ) type processorsRunDurations map[string]time.Duration @@ -51,21 +53,41 @@ func (g groupChangeProcessors) Commit(ctx context.Context) error { } type groupTransactionProcessors struct { - processors []horizonTransactionProcessor + processors []horizonTransactionProcessor + lazyLoaders []horizonLazyLoader processorsRunDurations + transactionStatsProcessor *processors.StatsLedgerTransactionProcessor + tradeProcessor *processors.TradeProcessor } -func newGroupTransactionProcessors(processors []horizonTransactionProcessor) *groupTransactionProcessors { +// build the group processor for all tx processors +// processors - list of processors this should include StatsLedgerTransactionProcessor and TradeProcessor +// transactionStatsProcessor - provide a direct reference to the stats processor that is in processors or nil, +// +// group processing will reset stats as needed +// +// tradeProcessor - provide a direct reference to the trades processor in processors or nil, +// +// so group processing will reset stats as needed +func newGroupTransactionProcessors(processors []horizonTransactionProcessor, + lazyLoaders []horizonLazyLoader, + transactionStatsProcessor *processors.StatsLedgerTransactionProcessor, + tradeProcessor *processors.TradeProcessor, +) *groupTransactionProcessors { + return &groupTransactionProcessors{ - processors: processors, - processorsRunDurations: make(map[string]time.Duration), + processors: processors, + processorsRunDurations: make(map[string]time.Duration), + lazyLoaders: lazyLoaders, + transactionStatsProcessor: transactionStatsProcessor, + tradeProcessor: tradeProcessor, } } -func (g groupTransactionProcessors) ProcessTransaction(ctx context.Context, tx ingest.LedgerTransaction) error { +func (g groupTransactionProcessors) ProcessTransaction(lcm xdr.LedgerCloseMeta, tx ingest.LedgerTransaction) error { for _, p := range g.processors { startTime := time.Now() - if err := p.ProcessTransaction(ctx, tx); err != nil { + if err := p.ProcessTransaction(lcm, tx); err != nil { return errors.Wrapf(err, "error in %T.ProcessTransaction", p) } g.AddRunDuration(fmt.Sprintf("%T", p), startTime) @@ -73,17 +95,37 @@ func (g groupTransactionProcessors) ProcessTransaction(ctx context.Context, tx i return nil } -func (g groupTransactionProcessors) Commit(ctx context.Context) error { +func (g groupTransactionProcessors) Flush(ctx context.Context, session db.SessionInterface) error { + // need to trigger all lazy loaders to now resolve their future placeholders + // with real db values first + for _, loader := range g.lazyLoaders { + if err := loader.Exec(ctx, session); err != nil { + return errors.Wrapf(err, "error during lazy loader resolution, %T.Exec", loader) + } + } + + // now flush each processor which may call loader.GetNow(), which + // required the prior loader.Exec() to have been called. for _, p := range g.processors { startTime := time.Now() - if err := p.Commit(ctx); err != nil { - return errors.Wrapf(err, "error in %T.Commit", p) + if err := p.Flush(ctx, session); err != nil { + return errors.Wrapf(err, "error in %T.Flush", p) } g.AddRunDuration(fmt.Sprintf("%T", p), startTime) } return nil } +func (g *groupTransactionProcessors) ResetStats() { + g.processorsRunDurations = make(map[string]time.Duration) + if g.tradeProcessor != nil { + g.tradeProcessor.ResetStats() + } + if g.transactionStatsProcessor != nil { + g.transactionStatsProcessor.ResetStats() + } +} + type groupTransactionFilterers struct { filterers []processors.LedgerTransactionFilterer processorsRunDurations @@ -113,3 +155,8 @@ func (g *groupTransactionFilterers) FilterTransaction(ctx context.Context, tx in } return true, nil } + +func (g *groupTransactionFilterers) ResetStats() { + g.droppedTransactions = 0 + g.processorsRunDurations = make(map[string]time.Duration) +} diff --git a/services/horizon/internal/ingest/group_processors_test.go b/services/horizon/internal/ingest/group_processors_test.go index 6848c24a66..71e50d3911 100644 --- a/services/horizon/internal/ingest/group_processors_test.go +++ b/services/horizon/internal/ingest/group_processors_test.go @@ -11,6 +11,10 @@ import ( "github.com/stretchr/testify/suite" "github.com/stellar/go/ingest" + "github.com/stellar/go/services/horizon/internal/db2/history" + "github.com/stellar/go/services/horizon/internal/ingest/processors" + "github.com/stellar/go/support/db" + "github.com/stellar/go/xdr" ) var _ horizonChangeProcessor = (*mockHorizonChangeProcessor)(nil) @@ -35,13 +39,13 @@ type mockHorizonTransactionProcessor struct { mock.Mock } -func (m *mockHorizonTransactionProcessor) ProcessTransaction(ctx context.Context, transaction ingest.LedgerTransaction) error { - args := m.Called(ctx, transaction) +func (m *mockHorizonTransactionProcessor) ProcessTransaction(lcm xdr.LedgerCloseMeta, transaction ingest.LedgerTransaction) error { + args := m.Called(lcm, transaction) return args.Error(0) } -func (m *mockHorizonTransactionProcessor) Commit(ctx context.Context) error { - args := m.Called(ctx) +func (m *mockHorizonTransactionProcessor) Flush(ctx context.Context, session db.SessionInterface) error { + args := m.Called(ctx, session) return args.Error(0) } @@ -124,6 +128,7 @@ type GroupTransactionProcessorsTestSuiteLedger struct { processors *groupTransactionProcessors processorA *mockHorizonTransactionProcessor processorB *mockHorizonTransactionProcessor + session db.SessionInterface } func TestGroupTransactionProcessorsTestSuiteLedger(t *testing.T) { @@ -132,12 +137,20 @@ func TestGroupTransactionProcessorsTestSuiteLedger(t *testing.T) { func (s *GroupTransactionProcessorsTestSuiteLedger) SetupTest() { s.ctx = context.Background() + statsProcessor := processors.NewStatsLedgerTransactionProcessor() + + tradesProcessor := processors.NewTradeProcessor(history.NewAccountLoaderStub().Loader, + history.NewLiquidityPoolLoaderStub().Loader, + history.NewAssetLoaderStub().Loader, + &history.MockTradeBatchInsertBuilder{}) + s.processorA = &mockHorizonTransactionProcessor{} s.processorB = &mockHorizonTransactionProcessor{} s.processors = newGroupTransactionProcessors([]horizonTransactionProcessor{ s.processorA, s.processorB, - }) + }, nil, statsProcessor, tradesProcessor) + s.session = &db.MockSession{} } func (s *GroupTransactionProcessorsTestSuiteLedger) TearDownTest() { @@ -147,46 +160,48 @@ func (s *GroupTransactionProcessorsTestSuiteLedger) TearDownTest() { func (s *GroupTransactionProcessorsTestSuiteLedger) TestProcessTransactionFails() { transaction := ingest.LedgerTransaction{} + closeMeta := xdr.LedgerCloseMeta{} s.processorA. - On("ProcessTransaction", s.ctx, transaction). + On("ProcessTransaction", closeMeta, transaction). Return(errors.New("transient error")).Once() - err := s.processors.ProcessTransaction(s.ctx, transaction) + err := s.processors.ProcessTransaction(closeMeta, transaction) s.Assert().Error(err) s.Assert().EqualError(err, "error in *ingest.mockHorizonTransactionProcessor.ProcessTransaction: transient error") } func (s *GroupTransactionProcessorsTestSuiteLedger) TestProcessTransactionSucceeds() { transaction := ingest.LedgerTransaction{} + closeMeta := xdr.LedgerCloseMeta{} s.processorA. - On("ProcessTransaction", s.ctx, transaction). + On("ProcessTransaction", closeMeta, transaction). Return(nil).Once() s.processorB. - On("ProcessTransaction", s.ctx, transaction). + On("ProcessTransaction", closeMeta, transaction). Return(nil).Once() - err := s.processors.ProcessTransaction(s.ctx, transaction) + err := s.processors.ProcessTransaction(closeMeta, transaction) s.Assert().NoError(err) } -func (s *GroupTransactionProcessorsTestSuiteLedger) TestCommitFails() { +func (s *GroupTransactionProcessorsTestSuiteLedger) TestFlushFails() { s.processorA. - On("Commit", s.ctx). + On("Flush", s.ctx, s.session). Return(errors.New("transient error")).Once() - err := s.processors.Commit(s.ctx) + err := s.processors.Flush(s.ctx, s.session) s.Assert().Error(err) - s.Assert().EqualError(err, "error in *ingest.mockHorizonTransactionProcessor.Commit: transient error") + s.Assert().EqualError(err, "error in *ingest.mockHorizonTransactionProcessor.Flush: transient error") } -func (s *GroupTransactionProcessorsTestSuiteLedger) TestCommitSucceeds() { +func (s *GroupTransactionProcessorsTestSuiteLedger) TestFlushSucceeds() { s.processorA. - On("Commit", s.ctx). + On("Flush", s.ctx, s.session). Return(nil).Once() s.processorB. - On("Commit", s.ctx). + On("Flush", s.ctx, s.session). Return(nil).Once() - err := s.processors.Commit(s.ctx) + err := s.processors.Flush(s.ctx, s.session) s.Assert().NoError(err) } diff --git a/services/horizon/internal/ingest/ingest_history_range_state_test.go b/services/horizon/internal/ingest/ingest_history_range_state_test.go index c60f21c43a..4598008eb8 100644 --- a/services/horizon/internal/ingest/ingest_history_range_state_test.go +++ b/services/horizon/internal/ingest/ingest_history_range_state_test.go @@ -11,7 +11,6 @@ import ( "github.com/stellar/go/ingest/ledgerbackend" "github.com/stellar/go/services/horizon/internal/db2/history" - "github.com/stellar/go/services/horizon/internal/ingest/processors" "github.com/stellar/go/support/errors" "github.com/stellar/go/toid" "github.com/stellar/go/xdr" @@ -38,16 +37,14 @@ func (s *IngestHistoryRangeStateTestSuite) SetupTest() { s.historyAdapter = &mockHistoryArchiveAdapter{} s.runner = &mockProcessorsRunner{} s.system = &system{ - ctx: s.ctx, - historyQ: s.historyQ, - historyAdapter: s.historyAdapter, - ledgerBackend: s.ledgerBackend, - runner: s.runner, + ctx: s.ctx, + historyQ: s.historyQ, + historyAdapter: s.historyAdapter, + ledgerBackend: s.ledgerBackend, + runner: s.runner, + maxLedgerPerFlush: 1, } s.system.initMetrics() - - s.historyQ.On("Rollback").Return(nil).Once() - s.ledgerBackend.On("IsPrepared", s.ctx, ledgerbackend.UnboundedRange(100)).Return(false, nil).Once() s.ledgerBackend.On("PrepareRange", s.ctx, ledgerbackend.UnboundedRange(100)).Return(nil).Once() } @@ -60,9 +57,7 @@ func (s *IngestHistoryRangeStateTestSuite) TearDownTest() { s.runner.AssertExpectations(t) } -func (s *IngestHistoryRangeStateTestSuite) TestInvalidRange() { - // Recreate mock in this single test to remove Rollback assertion. - *s.historyQ = mockDBQ{} +func (s *IngestHistoryRangeStateTestSuite) TestHistoryRangeInvalidRange() { *s.ledgerBackend = ledgerbackend.MockDatabaseBackend{} next, err := historyRangeState{fromLedger: 0, toLedger: 0}.run(s.system) @@ -86,11 +81,18 @@ func (s *IngestHistoryRangeStateTestSuite) TestInvalidRange() { s.Assert().Equal(transition{node: startState{}, sleepDuration: defaultSleep}, next) } -func (s *IngestHistoryRangeStateTestSuite) TestRangeNotPreparedFailPrepare() { - // Recreate mock in this single test to remove assertions. - *s.historyQ = mockDBQ{} +func (s *IngestHistoryRangeStateTestSuite) TestHistoryRangeInvalidMaxFlush() { *s.ledgerBackend = ledgerbackend.MockDatabaseBackend{} + s.system.maxLedgerPerFlush = 0 + next, err := historyRangeState{fromLedger: 100, toLedger: 200}.run(s.system) + s.Assert().Error(err) + s.Assert().EqualError(err, "invalid maxLedgerPerFlush, must be greater than 0") + s.Assert().Equal(transition{node: startState{}, sleepDuration: defaultSleep}, next) +} + +func (s *IngestHistoryRangeStateTestSuite) TestHistoryRangeFailPrepare() { + *s.ledgerBackend = ledgerbackend.MockDatabaseBackend{} s.ledgerBackend.On("IsPrepared", s.ctx, ledgerbackend.UnboundedRange(100)).Return(false, nil).Once() s.ledgerBackend.On("PrepareRange", s.ctx, ledgerbackend.UnboundedRange(100)).Return(errors.New("my error")).Once() @@ -100,11 +102,8 @@ func (s *IngestHistoryRangeStateTestSuite) TestRangeNotPreparedFailPrepare() { s.Assert().Equal(transition{node: startState{}, sleepDuration: defaultSleep}, next) } -func (s *IngestHistoryRangeStateTestSuite) TestBeginReturnsError() { - // Recreate mock in this single test to remove Rollback assertion. - *s.historyQ = mockDBQ{} - - s.historyQ.On("Begin").Return(errors.New("my error")).Once() +func (s *IngestHistoryRangeStateTestSuite) TestHistoryRangeBeginReturnsError() { + s.historyQ.On("Begin", s.ctx).Return(errors.New("my error")).Once() next, err := historyRangeState{fromLedger: 100, toLedger: 200}.run(s.system) s.Assert().Error(err) @@ -112,8 +111,9 @@ func (s *IngestHistoryRangeStateTestSuite) TestBeginReturnsError() { s.Assert().Equal(transition{node: startState{}, sleepDuration: defaultSleep}, next) } -func (s *IngestHistoryRangeStateTestSuite) TestGetLastLedgerIngestReturnsError() { - s.historyQ.On("Begin").Return(nil).Once() +func (s *IngestHistoryRangeStateTestSuite) TestHistoryRangeGetLastLedgerIngestReturnsError() { + s.historyQ.On("Begin", s.ctx).Return(nil).Once() + s.historyQ.On("Rollback").Return(nil).Once() s.historyQ.On("GetLastLedgerIngest", s.ctx).Return(uint32(0), errors.New("my error")).Once() next, err := historyRangeState{fromLedger: 100, toLedger: 200}.run(s.system) @@ -122,8 +122,9 @@ func (s *IngestHistoryRangeStateTestSuite) TestGetLastLedgerIngestReturnsError() s.Assert().Equal(transition{node: startState{}, sleepDuration: defaultSleep}, next) } -func (s *IngestHistoryRangeStateTestSuite) TestGetLatestLedgerReturnsError() { - s.historyQ.On("Begin").Return(nil).Once() +func (s *IngestHistoryRangeStateTestSuite) TestHistoryRangeGetLatestLedgerReturnsError() { + s.historyQ.On("Begin", s.ctx).Return(nil).Once() + s.historyQ.On("Rollback").Return(nil).Once() s.historyQ.On("GetLastLedgerIngest", s.ctx).Return(uint32(0), nil).Once() s.historyQ.On("GetLatestHistoryLedger", s.ctx).Return(uint32(0), errors.New("my error")).Once() @@ -135,8 +136,9 @@ func (s *IngestHistoryRangeStateTestSuite) TestGetLatestLedgerReturnsError() { // TestAnotherNodeIngested tests the case when another node has ingested the range. // In such case we go back to `init` state without processing. -func (s *IngestHistoryRangeStateTestSuite) TestAnotherNodeIngested() { - s.historyQ.On("Begin").Return(nil).Once() +func (s *IngestHistoryRangeStateTestSuite) TestHistoryRangeAnotherNodeIngested() { + s.historyQ.On("Begin", s.ctx).Return(nil).Once() + s.historyQ.On("Rollback").Return(nil).Once() s.historyQ.On("GetLastLedgerIngest", s.ctx).Return(uint32(0), nil).Once() s.historyQ.On("GetLatestHistoryLedger", s.ctx).Return(uint32(200), nil).Once() @@ -145,8 +147,9 @@ func (s *IngestHistoryRangeStateTestSuite) TestAnotherNodeIngested() { s.Assert().Equal(transition{node: startState{}, sleepDuration: defaultSleep}, next) } -func (s *IngestHistoryRangeStateTestSuite) TestRunTransactionProcessorsOnLedgerReturnsError() { - s.historyQ.On("Begin").Return(nil).Once() +func (s *IngestHistoryRangeStateTestSuite) TestHistoryRangeRunTransactionProcessorsReturnsError() { + s.historyQ.On("Begin", s.ctx).Return(nil).Once() + s.historyQ.On("Rollback").Return(nil).Once() s.historyQ.On("GetLastLedgerIngest", s.ctx).Return(uint32(0), nil).Once() s.historyQ.On("GetLatestHistoryLedger", s.ctx).Return(uint32(99), nil).Once() @@ -154,28 +157,24 @@ func (s *IngestHistoryRangeStateTestSuite) TestRunTransactionProcessorsOnLedgerR V0: &xdr.LedgerCloseMetaV0{ LedgerHeader: xdr.LedgerHeaderHistoryEntry{ Header: xdr.LedgerHeader{ - LedgerSeq: 100, + LedgerSeq: xdr.Uint32(100), }, }, }, } - s.ledgerBackend.On("GetLedger", s.ctx, uint32(100)).Return(meta, nil).Once() - s.runner.On("RunTransactionProcessorsOnLedger", meta).Return( - processors.StatsLedgerTransactionProcessorResults{}, - processorsRunDurations{}, - processors.TradeStats{}, - errors.New("my error"), - ).Once() + s.ledgerBackend.On("GetLedger", s.ctx, uint32(100)).Return(meta, nil).Once() + s.runner.On("RunTransactionProcessorsOnLedgers", []xdr.LedgerCloseMeta{meta}).Return(errors.New("my error")).Once() next, err := historyRangeState{fromLedger: 100, toLedger: 200}.run(s.system) s.Assert().Error(err) - s.Assert().EqualError(err, "error processing ledger sequence=100: my error") + s.Assert().EqualError(err, "error processing ledger range 100 - 100: my error") s.Assert().Equal(transition{node: startState{}, sleepDuration: defaultSleep}, next) } -func (s *IngestHistoryRangeStateTestSuite) TestSuccess() { - s.historyQ.On("Begin").Return(nil).Once() +func (s *IngestHistoryRangeStateTestSuite) TestHistoryRangeSuccess() { + s.historyQ.On("Begin", s.ctx).Return(nil).Once() + s.historyQ.On("Rollback").Return(nil).Once() s.historyQ.On("GetLastLedgerIngest", s.ctx).Return(uint32(0), nil).Once() s.historyQ.On("GetLatestHistoryLedger", s.ctx).Return(uint32(99), nil).Once() @@ -190,56 +189,58 @@ func (s *IngestHistoryRangeStateTestSuite) TestSuccess() { }, } s.ledgerBackend.On("GetLedger", s.ctx, uint32(i)).Return(meta, nil).Once() - - s.runner.On("RunTransactionProcessorsOnLedger", meta).Return( - processors.StatsLedgerTransactionProcessorResults{}, - processorsRunDurations{}, - processors.TradeStats{}, - nil, - ).Once() + s.runner.On("RunTransactionProcessorsOnLedgers", []xdr.LedgerCloseMeta{meta}).Return(nil).Once() } s.historyQ.On("Commit").Return(nil).Once() + // system.maxLedgerPerFlush has been set by default to 1 in test suite setup next, err := historyRangeState{fromLedger: 100, toLedger: 200}.run(s.system) s.Assert().NoError(err) s.Assert().Equal(transition{node: startState{}, sleepDuration: defaultSleep}, next) } -func (s *IngestHistoryRangeStateTestSuite) TestSuccessOneLedger() { - s.historyQ.On("Begin").Return(nil).Once() +func (s *IngestHistoryRangeStateTestSuite) TestHistoryRangeSuccessWithFlushMax() { + s.historyQ.On("Begin", s.ctx).Return(nil).Once() + s.historyQ.On("Rollback").Return(nil).Once() s.historyQ.On("GetLastLedgerIngest", s.ctx).Return(uint32(0), nil).Once() s.historyQ.On("GetLatestHistoryLedger", s.ctx).Return(uint32(99), nil).Once() + s.historyQ.On("Commit").Return(nil).Once() - meta := xdr.LedgerCloseMeta{ - V0: &xdr.LedgerCloseMetaV0{ - LedgerHeader: xdr.LedgerHeaderHistoryEntry{ - Header: xdr.LedgerHeader{ - LedgerSeq: xdr.Uint32(100), + firstLedgersBatch := []xdr.LedgerCloseMeta{} + secondLedgersBatch := []xdr.LedgerCloseMeta{} + for i := 100; i <= 200; i++ { + meta := xdr.LedgerCloseMeta{ + V0: &xdr.LedgerCloseMetaV0{ + LedgerHeader: xdr.LedgerHeaderHistoryEntry{ + Header: xdr.LedgerHeader{ + LedgerSeq: xdr.Uint32(i), + }, }, }, - }, + } + if i-60 < 100 { + firstLedgersBatch = append(firstLedgersBatch, meta) + } else { + secondLedgersBatch = append(secondLedgersBatch, meta) + } + s.ledgerBackend.On("GetLedger", s.ctx, uint32(i)).Return(meta, nil).Once() } - s.ledgerBackend.On("GetLedger", s.ctx, uint32(100)).Return(meta, nil).Once() - - s.runner.On("RunTransactionProcessorsOnLedger", meta).Return( - processors.StatsLedgerTransactionProcessorResults{}, - processorsRunDurations{}, - processors.TradeStats{}, - nil, - ).Once() - - s.historyQ.On("Commit").Return(nil).Once() + s.runner.On("RunTransactionProcessorsOnLedgers", firstLedgersBatch).Return(nil).Once() + s.runner.On("RunTransactionProcessorsOnLedgers", secondLedgersBatch).Return(nil).Once() - next, err := historyRangeState{fromLedger: 100, toLedger: 100}.run(s.system) + s.system.maxLedgerPerFlush = 60 + next, err := historyRangeState{fromLedger: 100, toLedger: 200}.run(s.system) s.Assert().NoError(err) s.Assert().Equal(transition{node: startState{}, sleepDuration: defaultSleep}, next) } -func (s *IngestHistoryRangeStateTestSuite) TestCommitsWorkOnLedgerBackendFailure() { - s.historyQ.On("Begin").Return(nil).Once() +func (s *IngestHistoryRangeStateTestSuite) TestHistoryRangeCommitsWorkOnLedgerBackendFailure() { + s.historyQ.On("Begin", s.ctx).Return(nil).Once() + s.historyQ.On("Rollback").Return(nil).Once() s.historyQ.On("GetLastLedgerIngest", s.ctx).Return(uint32(0), nil).Once() s.historyQ.On("GetLatestHistoryLedger", s.ctx).Return(uint32(99), nil).Once() + s.historyQ.On("Commit").Return(nil).Once() meta := xdr.LedgerCloseMeta{ V0: &xdr.LedgerCloseMetaV0{ @@ -251,19 +252,11 @@ func (s *IngestHistoryRangeStateTestSuite) TestCommitsWorkOnLedgerBackendFailure }, } s.ledgerBackend.On("GetLedger", s.ctx, uint32(100)).Return(meta, nil).Once() + s.runner.On("RunTransactionProcessorsOnLedgers", []xdr.LedgerCloseMeta{meta}).Return(nil).Once() s.ledgerBackend.On("GetLedger", s.ctx, uint32(101)). Return(xdr.LedgerCloseMeta{}, errors.New("my error")).Once() - s.runner.On("RunTransactionProcessorsOnLedger", meta).Return( - processors.StatsLedgerTransactionProcessorResults{}, - processorsRunDurations{}, - processors.TradeStats{}, - nil, - ).Once() - - s.historyQ.On("Commit").Return(nil).Once() - - next, err := historyRangeState{fromLedger: 100, toLedger: 102}.run(s.system) + next, err := historyRangeState{fromLedger: 100, toLedger: 200}.run(s.system) s.Assert().Error(err) s.Assert().EqualError(err, "error getting ledger: my error") s.Assert().Equal(transition{node: startState{}, sleepDuration: defaultSleep}, next) @@ -290,17 +283,14 @@ func (s *ReingestHistoryRangeStateTestSuite) SetupTest() { s.ledgerBackend = &mockLedgerBackend{} s.runner = &mockProcessorsRunner{} s.system = &system{ - ctx: s.ctx, - historyQ: s.historyQ, - historyAdapter: s.historyAdapter, - ledgerBackend: s.ledgerBackend, - runner: s.runner, + ctx: s.ctx, + historyQ: s.historyQ, + historyAdapter: s.historyAdapter, + ledgerBackend: s.ledgerBackend, + runner: s.runner, + maxLedgerPerFlush: 1, } - s.historyQ.On("GetTx").Return(nil).Once() - s.historyQ.On("Rollback").Return(nil).Once() - s.historyQ.On("Begin").Return(nil).Once() - s.ledgerBackend.On("PrepareRange", s.ctx, ledgerbackend.BoundedRange(100, 200)).Return(nil).Once() } @@ -311,10 +301,9 @@ func (s *ReingestHistoryRangeStateTestSuite) TearDownTest() { s.runner.AssertExpectations(t) } -func (s *ReingestHistoryRangeStateTestSuite) TestInvalidRange() { +func (s *ReingestHistoryRangeStateTestSuite) TestReingestHistoryRangeStateInvalidRange() { // Recreate mock in this single test to remove Rollback assertion. - *s.historyQ = mockDBQ{} - + s.historyQ = &mockDBQ{} err := s.system.ReingestRange([]history.LedgerRange{{0, 0}}, false) s.Assert().EqualError(err, "Invalid range: {0 0} genesis ledger starts at 1") @@ -328,76 +317,69 @@ func (s *ReingestHistoryRangeStateTestSuite) TestInvalidRange() { s.Assert().EqualError(err, "Invalid range: {100 99} from > to") } -func (s *ReingestHistoryRangeStateTestSuite) TestBeginReturnsError() { - // Recreate mock in this single test to remove Rollback assertion. - *s.historyQ = mockDBQ{} - s.historyQ.On("GetTx").Return(nil) +func (s *ReingestHistoryRangeStateTestSuite) TestReingestHistoryRangeStateInvalidMaxFlush() { s.historyQ.On("GetLastLedgerIngestNonBlocking", s.ctx).Return(uint32(0), nil).Once() + s.historyQ.On("Begin", s.ctx).Return(nil).Once() + s.historyQ.On("Rollback").Return(nil).Once() + s.historyQ.On("GetTx").Return(&sqlx.Tx{}).Once() + s.system.maxLedgerPerFlush = 0 + err := s.system.ReingestRange([]history.LedgerRange{{100, 200}}, false) + s.Assert().EqualError(err, "invalid maxLedgerPerFlush, must be greater than 0") +} - s.historyQ.On("Begin").Return(errors.New("my error")).Once() +func (s *ReingestHistoryRangeStateTestSuite) TestReingestHistoryRangeStateBeginReturnsError() { + // Recreate mock in this single test to remove Rollback assertion. + s.historyQ.On("GetLastLedgerIngestNonBlocking", s.ctx).Return(uint32(0), nil).Once() + s.historyQ.On("Begin", s.ctx).Return(errors.New("my error")).Once() err := s.system.ReingestRange([]history.LedgerRange{{100, 200}}, false) s.Assert().EqualError(err, "Error starting a transaction: my error") } -func (s *ReingestHistoryRangeStateTestSuite) TestGetLastLedgerIngestNonBlockingError() { - *s.historyQ = mockDBQ{} - s.historyQ.On("GetTx").Return(nil).Once() - +func (s *ReingestHistoryRangeStateTestSuite) TestReingestHistoryRangeStateGetLastLedgerIngestNonBlockingError() { s.historyQ.On("GetLastLedgerIngestNonBlocking", s.ctx).Return(uint32(0), errors.New("my error")).Once() err := s.system.ReingestRange([]history.LedgerRange{{100, 200}}, false) s.Assert().EqualError(err, "Error getting last ingested ledger: my error") } -func (s *ReingestHistoryRangeStateTestSuite) TestReingestRangeOverlaps() { - *s.historyQ = mockDBQ{} - s.historyQ.On("GetTx").Return(nil).Once() - +func (s *ReingestHistoryRangeStateTestSuite) TestReingestHistoryRangeStateRangeOverlaps() { s.historyQ.On("GetLastLedgerIngestNonBlocking", s.ctx).Return(uint32(190), nil).Once() err := s.system.ReingestRange([]history.LedgerRange{{100, 200}}, false) s.Assert().Equal(ErrReingestRangeConflict{190}, err) } -func (s *ReingestHistoryRangeStateTestSuite) TestReingestRangeOverlapsAtEnd() { - *s.historyQ = mockDBQ{} - s.historyQ.On("GetTx").Return(nil).Once() - +func (s *ReingestHistoryRangeStateTestSuite) TestReingestHistoryRangeStatRangeOverlapsAtEnd() { s.historyQ.On("GetLastLedgerIngestNonBlocking", s.ctx).Return(uint32(200), nil).Once() err := s.system.ReingestRange([]history.LedgerRange{{100, 200}}, false) s.Assert().Equal(ErrReingestRangeConflict{200}, err) } -func (s *ReingestHistoryRangeStateTestSuite) TestClearHistoryFails() { - *s.historyQ = mockDBQ{} - s.historyQ.On("GetTx").Return(nil).Once() +func (s *ReingestHistoryRangeStateTestSuite) TestReingestHistoryRangeStateClearHistoryFails() { s.historyQ.On("GetLastLedgerIngestNonBlocking", s.ctx).Return(uint32(0), nil).Once() - - s.historyQ.On("Begin").Return(nil).Once() + s.historyQ.On("Begin", s.ctx).Return(nil).Once() + s.historyQ.On("Rollback").Return(nil).Once() s.historyQ.On("GetTx").Return(&sqlx.Tx{}).Once() toidFrom := toid.New(100, 0, 0) - toidTo := toid.New(101, 0, 0) + // the state deletes range once, calc'd by toid.LedgerRangeInclusive(), which adjusts to = to + 1 + toidTo := toid.New(201, 0, 0) s.historyQ.On( "DeleteRangeAll", s.ctx, toidFrom.ToInt64(), toidTo.ToInt64(), ).Return(errors.New("my error")).Once() - s.historyQ.On("Rollback").Return(nil).Once() - err := s.system.ReingestRange([]history.LedgerRange{{100, 200}}, false) s.Assert().EqualError(err, "error in DeleteRangeAll: my error") } -func (s *ReingestHistoryRangeStateTestSuite) TestRunTransactionProcessorsOnLedgerReturnsError() { - *s.historyQ = mockDBQ{} - s.historyQ.On("GetTx").Return(nil).Once() +func (s *ReingestHistoryRangeStateTestSuite) TestReingestHistoryRangeStateRunTransactionProcessorsReturnsError() { s.historyQ.On("GetLastLedgerIngestNonBlocking", s.ctx).Return(uint32(0), nil).Once() - - s.historyQ.On("Begin").Return(nil).Once() + s.historyQ.On("Begin", s.ctx).Return(nil).Once() + s.historyQ.On("Rollback").Return(nil).Once() s.historyQ.On("GetTx").Return(&sqlx.Tx{}).Once() toidFrom := toid.New(100, 0, 0) - toidTo := toid.New(101, 0, 0) + toidTo := toid.New(201, 0, 0) s.historyQ.On( "DeleteRangeAll", s.ctx, toidFrom.ToInt64(), toidTo.ToInt64(), ).Return(nil).Once() @@ -411,74 +393,59 @@ func (s *ReingestHistoryRangeStateTestSuite) TestRunTransactionProcessorsOnLedge }, }, } - s.ledgerBackend.On("GetLedger", s.ctx, uint32(100)).Return(meta, nil).Once() - s.runner.On("RunTransactionProcessorsOnLedger", meta). - Return( - processors.StatsLedgerTransactionProcessorResults{}, - processorsRunDurations{}, - processors.TradeStats{}, - errors.New("my error"), - ).Once() - s.historyQ.On("Rollback").Return(nil).Once() + s.ledgerBackend.On("GetLedger", s.ctx, uint32(100)).Return(meta, nil).Once() + s.runner.On("RunTransactionProcessorsOnLedgers", []xdr.LedgerCloseMeta{meta}).Return(errors.New("my error")).Once() err := s.system.ReingestRange([]history.LedgerRange{{100, 200}}, false) - s.Assert().EqualError(err, "error processing ledger sequence=100: my error") + s.Assert().EqualError(err, "error processing ledger range 100 - 100: my error") } -func (s *ReingestHistoryRangeStateTestSuite) TestCommitFails() { - *s.historyQ = mockDBQ{} - s.historyQ.On("GetTx").Return(nil).Once() +func (s *ReingestHistoryRangeStateTestSuite) TestReingestHistoryRangeStateCommitFails() { s.historyQ.On("GetLastLedgerIngestNonBlocking", s.ctx).Return(uint32(0), nil).Once() - - s.historyQ.On("Begin").Return(nil).Once() + s.historyQ.On("Begin", s.ctx).Return(nil).Once() + s.historyQ.On("Rollback").Return(nil).Once() s.historyQ.On("GetTx").Return(&sqlx.Tx{}).Once() + s.historyQ.On("Commit").Return(errors.New("my error")).Once() + toidFrom := toid.New(100, 0, 0) - toidTo := toid.New(101, 0, 0) + toidTo := toid.New(201, 0, 0) s.historyQ.On( "DeleteRangeAll", s.ctx, toidFrom.ToInt64(), toidTo.ToInt64(), ).Return(nil).Once() - meta := xdr.LedgerCloseMeta{ - V0: &xdr.LedgerCloseMetaV0{ - LedgerHeader: xdr.LedgerHeaderHistoryEntry{ - Header: xdr.LedgerHeader{ - LedgerSeq: xdr.Uint32(100), + for i := uint32(100); i <= uint32(200); i++ { + meta := xdr.LedgerCloseMeta{ + V0: &xdr.LedgerCloseMetaV0{ + LedgerHeader: xdr.LedgerHeaderHistoryEntry{ + Header: xdr.LedgerHeader{ + LedgerSeq: xdr.Uint32(i), + }, }, }, - }, + } + s.ledgerBackend.On("GetLedger", s.ctx, uint32(i)).Return(meta, nil).Once() + s.runner.On("RunTransactionProcessorsOnLedgers", []xdr.LedgerCloseMeta{meta}).Return(nil).Once() } - s.ledgerBackend.On("GetLedger", s.ctx, uint32(100)).Return(meta, nil).Once() - - s.runner.On("RunTransactionProcessorsOnLedger", meta).Return( - processors.StatsLedgerTransactionProcessorResults{}, - processorsRunDurations{}, - processors.TradeStats{}, - nil, - ).Once() - - s.historyQ.On("Commit").Return(errors.New("my error")).Once() - s.historyQ.On("Rollback").Return(nil).Once() err := s.system.ReingestRange([]history.LedgerRange{{100, 200}}, false) s.Assert().EqualError(err, "Error committing db transaction: my error") } -func (s *ReingestHistoryRangeStateTestSuite) TestSuccess() { - *s.historyQ = mockDBQ{} - s.historyQ.On("GetTx").Return(nil).Once() +func (s *ReingestHistoryRangeStateTestSuite) TestReingestHistoryRangeStateSuccess() { s.historyQ.On("GetLastLedgerIngestNonBlocking", s.ctx).Return(uint32(0), nil).Once() + s.historyQ.On("Begin", s.ctx).Return(nil).Once() + s.historyQ.On("Rollback").Return(nil).Once() + s.historyQ.On("GetTx").Return(&sqlx.Tx{}).Once() + toidFrom := toid.New(100, 0, 0) + toidTo := toid.New(201, 0, 0) + s.historyQ.On( + "DeleteRangeAll", s.ctx, toidFrom.ToInt64(), toidTo.ToInt64(), + ).Return(nil).Once() + s.historyQ.On("Commit").Return(nil).Once() + s.historyQ.On("RebuildTradeAggregationBuckets", s.ctx, uint32(100), uint32(200), 0).Return(nil).Once() for i := uint32(100); i <= uint32(200); i++ { - s.historyQ.On("Begin").Return(nil).Once() - s.historyQ.On("GetTx").Return(&sqlx.Tx{}).Once() - - toidFrom := toid.New(int32(i), 0, 0) - toidTo := toid.New(int32(i+1), 0, 0) - s.historyQ.On( - "DeleteRangeAll", s.ctx, toidFrom.ToInt64(), toidTo.ToInt64(), - ).Return(nil).Once() - meta := xdr.LedgerCloseMeta{ V0: &xdr.LedgerCloseMetaV0{ LedgerHeader: xdr.LedgerHeaderHistoryEntry{ @@ -489,26 +456,64 @@ func (s *ReingestHistoryRangeStateTestSuite) TestSuccess() { }, } s.ledgerBackend.On("GetLedger", s.ctx, uint32(i)).Return(meta, nil).Once() + s.runner.On("RunTransactionProcessorsOnLedgers", []xdr.LedgerCloseMeta{meta}).Return(nil).Once() + } - s.runner.On("RunTransactionProcessorsOnLedger", meta).Return( - processors.StatsLedgerTransactionProcessorResults{}, - processorsRunDurations{}, - processors.TradeStats{}, - nil, - ).Once() + // system.maxLedgerPerFlush has been set by default to 1 in test suite setup + err := s.system.ReingestRange([]history.LedgerRange{{100, 200}}, false) + s.Assert().NoError(err) +} - s.historyQ.On("Commit").Return(nil).Once() - s.historyQ.On("Rollback").Return(nil).Once() - } +func (s *ReingestHistoryRangeStateTestSuite) TestReingestHistoryRangeStateSuccessWithFlushMax() { + s.historyQ.On("GetLastLedgerIngestNonBlocking", s.ctx).Return(uint32(0), nil).Once() + s.historyQ.On("Begin", s.ctx).Return(nil).Once() + s.historyQ.On("Rollback").Return(nil).Once() + s.historyQ.On("GetTx").Return(&sqlx.Tx{}).Once() + toidFrom := toid.New(100, 0, 0) + toidTo := toid.New(201, 0, 0) + s.historyQ.On( + "DeleteRangeAll", s.ctx, toidFrom.ToInt64(), toidTo.ToInt64(), + ).Return(nil).Once() + s.historyQ.On("Commit").Return(nil).Once() s.historyQ.On("RebuildTradeAggregationBuckets", s.ctx, uint32(100), uint32(200), 0).Return(nil).Once() + firstLedgersBatch := []xdr.LedgerCloseMeta{} + secondLedgersBatch := []xdr.LedgerCloseMeta{} + for i := uint32(100); i <= uint32(200); i++ { + meta := xdr.LedgerCloseMeta{ + V0: &xdr.LedgerCloseMetaV0{ + LedgerHeader: xdr.LedgerHeaderHistoryEntry{ + Header: xdr.LedgerHeader{ + LedgerSeq: xdr.Uint32(i), + }, + }, + }, + } + // triggers two flushes, one for max during loop and one for remainder + if i-60 < 100 { + firstLedgersBatch = append(firstLedgersBatch, meta) + } else { + secondLedgersBatch = append(secondLedgersBatch, meta) + } + s.ledgerBackend.On("GetLedger", s.ctx, uint32(i)).Return(meta, nil).Once() + } + s.runner.On("RunTransactionProcessorsOnLedgers", firstLedgersBatch).Return(nil).Once() + s.runner.On("RunTransactionProcessorsOnLedgers", secondLedgersBatch).Return(nil).Once() + s.system.maxLedgerPerFlush = 60 err := s.system.ReingestRange([]history.LedgerRange{{100, 200}}, false) s.Assert().NoError(err) } -func (s *ReingestHistoryRangeStateTestSuite) TestSuccessOneLedger() { +func (s *ReingestHistoryRangeStateTestSuite) TestReingestHistoryRangeStateSuccessOneLedger() { s.historyQ.On("GetLastLedgerIngestNonBlocking", s.ctx).Return(uint32(0), nil).Once() + s.historyQ.On("Begin", s.ctx).Return(nil).Once() + s.historyQ.On("Rollback").Return(nil).Once() s.historyQ.On("GetTx").Return(&sqlx.Tx{}).Once() + s.historyQ.On("Commit").Return(nil).Once() + s.historyQ.On("RebuildTradeAggregationBuckets", s.ctx, uint32(100), uint32(100), 0).Return(nil).Once() + // Recreate mock in this single ledger test to remove setup assertion on ledger range. + *s.ledgerBackend = mockLedgerBackend{} + s.ledgerBackend.On("PrepareRange", s.ctx, ledgerbackend.BoundedRange(100, 100)).Return(nil).Once() toidFrom := toid.New(100, 0, 0) toidTo := toid.New(101, 0, 0) @@ -526,35 +531,61 @@ func (s *ReingestHistoryRangeStateTestSuite) TestSuccessOneLedger() { }, } - s.runner.On("RunTransactionProcessorsOnLedger", meta).Return( - processors.StatsLedgerTransactionProcessorResults{}, - processorsRunDurations{}, - processors.TradeStats{}, - nil, - ).Once() - s.historyQ.On("Commit").Return(nil).Once() - s.historyQ.On("RebuildTradeAggregationBuckets", s.ctx, uint32(100), uint32(100), 0).Return(nil).Once() - - // Recreate mock in this single test to remove previous assertion. - *s.ledgerBackend = mockLedgerBackend{} - s.ledgerBackend.On("PrepareRange", s.ctx, ledgerbackend.BoundedRange(100, 100)).Return(nil).Once() s.ledgerBackend.On("GetLedger", s.ctx, uint32(100)).Return(meta, nil).Once() + s.runner.On("RunTransactionProcessorsOnLedgers", []xdr.LedgerCloseMeta{meta}).Return(nil).Once() err := s.system.ReingestRange([]history.LedgerRange{{100, 100}}, false) s.Assert().NoError(err) } -func (s *ReingestHistoryRangeStateTestSuite) TestGetLastLedgerIngestError() { +func (s *ReingestHistoryRangeStateTestSuite) TestReingestHistoryRangeStateForceGetLastLedgerIngestError() { + s.historyQ.On("Begin", s.ctx).Return(nil).Once() + s.historyQ.On("Rollback").Return(nil).Once() s.historyQ.On("GetLastLedgerIngest", s.ctx).Return(uint32(0), errors.New("my error")).Once() err := s.system.ReingestRange([]history.LedgerRange{{100, 200}}, true) s.Assert().EqualError(err, "Error getting last ingested ledger: my error") } -func (s *ReingestHistoryRangeStateTestSuite) TestReingestRangeForce() { +func (s *ReingestHistoryRangeStateTestSuite) TestReingestHistoryRangeStateForce() { + s.historyQ.On("Begin", s.ctx).Return(nil).Once() + s.historyQ.On("Rollback").Return(nil).Once() + s.historyQ.On("GetTx").Return(&sqlx.Tx{}).Once() s.historyQ.On("GetLastLedgerIngest", s.ctx).Return(uint32(190), nil).Once() + s.historyQ.On("Commit").Return(nil).Once() + s.historyQ.On("RebuildTradeAggregationBuckets", s.ctx, uint32(100), uint32(200), 0).Return(nil).Once() + + toidFrom := toid.New(100, 0, 0) + toidTo := toid.New(201, 0, 0) + s.historyQ.On( + "DeleteRangeAll", s.ctx, toidFrom.ToInt64(), toidTo.ToInt64(), + ).Return(nil).Once() + + for i := 100; i <= 200; i++ { + meta := xdr.LedgerCloseMeta{ + V0: &xdr.LedgerCloseMetaV0{ + LedgerHeader: xdr.LedgerHeaderHistoryEntry{ + Header: xdr.LedgerHeader{ + LedgerSeq: xdr.Uint32(i), + }, + }, + }, + } + s.ledgerBackend.On("GetLedger", s.ctx, uint32(i)).Return(meta, nil).Once() + s.runner.On("RunTransactionProcessorsOnLedgers", []xdr.LedgerCloseMeta{meta}).Return(nil).Once() + } + + // system.maxLedgerPerFlush has been set by default to 1 in test suite setup + err := s.system.ReingestRange([]history.LedgerRange{{100, 200}}, true) + s.Assert().NoError(err) +} +func (s *ReingestHistoryRangeStateTestSuite) TestReingestHistoryRangeStateForceLedgerRetrievalError() { + s.historyQ.On("Begin", s.ctx).Return(nil).Once() + s.historyQ.On("Rollback").Return(nil).Once() s.historyQ.On("GetTx").Return(&sqlx.Tx{}).Once() + s.historyQ.On("GetLastLedgerIngest", s.ctx).Return(uint32(190), nil).Once() + s.historyQ.On("Commit").Return(nil).Once() toidFrom := toid.New(100, 0, 0) toidTo := toid.New(201, 0, 0) @@ -562,7 +593,7 @@ func (s *ReingestHistoryRangeStateTestSuite) TestReingestRangeForce() { "DeleteRangeAll", s.ctx, toidFrom.ToInt64(), toidTo.ToInt64(), ).Return(nil).Once() - for i := 100; i <= 200; i++ { + for i := 100; i <= 105; i++ { meta := xdr.LedgerCloseMeta{ V0: &xdr.LedgerCloseMetaV0{ LedgerHeader: xdr.LedgerHeaderHistoryEntry{ @@ -573,19 +604,88 @@ func (s *ReingestHistoryRangeStateTestSuite) TestReingestRangeForce() { }, } s.ledgerBackend.On("GetLedger", s.ctx, uint32(i)).Return(meta, nil).Once() + s.runner.On("RunTransactionProcessorsOnLedgers", []xdr.LedgerCloseMeta{meta}).Return(nil).Once() + } - s.runner.On("RunTransactionProcessorsOnLedger", meta).Return( - processors.StatsLedgerTransactionProcessorResults{}, - processorsRunDurations{}, - processors.TradeStats{}, - nil, - ).Once() + s.ledgerBackend.On("GetLedger", s.ctx, uint32(106)).Return(xdr.LedgerCloseMeta{}, errors.New("my error")).Once() + + // system.maxLedgerPerFlush has been set by default to 1 in test suite setup + err := s.system.ReingestRange([]history.LedgerRange{{100, 200}}, true) + s.Assert().EqualError(err, "error getting ledger: my error") +} + +func (s *ReingestHistoryRangeStateTestSuite) TestReingestHistoryRangeStateForceLedgerRetrievalAndCommitError() { + s.historyQ.On("Begin", s.ctx).Return(nil).Once() + s.historyQ.On("Rollback").Return(nil).Once() + s.historyQ.On("GetTx").Return(&sqlx.Tx{}).Once() + s.historyQ.On("GetLastLedgerIngest", s.ctx).Return(uint32(190), nil).Once() + s.historyQ.On("Commit").Return(errors.New("commit error")).Once() + + toidFrom := toid.New(100, 0, 0) + toidTo := toid.New(201, 0, 0) + s.historyQ.On( + "DeleteRangeAll", s.ctx, toidFrom.ToInt64(), toidTo.ToInt64(), + ).Return(nil).Once() + + for i := 100; i <= 105; i++ { + meta := xdr.LedgerCloseMeta{ + V0: &xdr.LedgerCloseMetaV0{ + LedgerHeader: xdr.LedgerHeaderHistoryEntry{ + Header: xdr.LedgerHeader{ + LedgerSeq: xdr.Uint32(i), + }, + }, + }, + } + s.ledgerBackend.On("GetLedger", s.ctx, uint32(i)).Return(meta, nil).Once() + s.runner.On("RunTransactionProcessorsOnLedgers", []xdr.LedgerCloseMeta{meta}).Return(nil).Once() } - s.historyQ.On("Commit").Return(nil).Once() + s.ledgerBackend.On("GetLedger", s.ctx, uint32(106)).Return(xdr.LedgerCloseMeta{}, errors.New("my error")).Once() + + // system.maxLedgerPerFlush has been set by default to 1 in test suite setup + err := s.system.ReingestRange([]history.LedgerRange{{100, 200}}, true) + s.Assert().EqualError(err, "Error committing db transaction: error getting ledger: my error") +} +func (s *ReingestHistoryRangeStateTestSuite) TestReingestHistoryRangeStateForceWithFlushMax() { + s.historyQ.On("Begin", s.ctx).Return(nil).Once() + s.historyQ.On("Rollback").Return(nil).Once() + s.historyQ.On("GetTx").Return(&sqlx.Tx{}).Once() + s.historyQ.On("GetLastLedgerIngest", s.ctx).Return(uint32(190), nil).Once() + s.historyQ.On("Commit").Return(nil).Once() s.historyQ.On("RebuildTradeAggregationBuckets", s.ctx, uint32(100), uint32(200), 0).Return(nil).Once() + toidFrom := toid.New(100, 0, 0) + toidTo := toid.New(201, 0, 0) + s.historyQ.On( + "DeleteRangeAll", s.ctx, toidFrom.ToInt64(), toidTo.ToInt64(), + ).Return(nil).Once() + + firstLedgersBatch := []xdr.LedgerCloseMeta{} + secondLedgersBatch := []xdr.LedgerCloseMeta{} + for i := 100; i <= 200; i++ { + meta := xdr.LedgerCloseMeta{ + V0: &xdr.LedgerCloseMetaV0{ + LedgerHeader: xdr.LedgerHeaderHistoryEntry{ + Header: xdr.LedgerHeader{ + LedgerSeq: xdr.Uint32(i), + }, + }, + }, + } + // triggers two flushes, one for max during loop and one for remainder + if i-60 < 100 { + firstLedgersBatch = append(firstLedgersBatch, meta) + } else { + secondLedgersBatch = append(secondLedgersBatch, meta) + } + s.ledgerBackend.On("GetLedger", s.ctx, uint32(i)).Return(meta, nil).Once() + } + s.runner.On("RunTransactionProcessorsOnLedgers", firstLedgersBatch).Return(nil).Once() + s.runner.On("RunTransactionProcessorsOnLedgers", secondLedgersBatch).Return(nil).Once() + + s.system.maxLedgerPerFlush = 60 err := s.system.ReingestRange([]history.LedgerRange{{100, 200}}, true) s.Assert().NoError(err) } diff --git a/services/horizon/internal/ingest/init_state_test.go b/services/horizon/internal/ingest/init_state_test.go index b0ddfb146c..1707fd627c 100644 --- a/services/horizon/internal/ingest/init_state_test.go +++ b/services/horizon/internal/ingest/init_state_test.go @@ -45,7 +45,7 @@ func (s *InitStateTestSuite) TearDownTest() { func (s *InitStateTestSuite) TestBeginReturnsError() { // Recreate mock in this single test to remove Rollback assertion. *s.historyQ = mockDBQ{} - s.historyQ.On("Begin").Return(errors.New("my error")).Once() + s.historyQ.On("Begin", s.ctx).Return(errors.New("my error")).Once() next, err := startState{}.run(s.system) s.Assert().Error(err) @@ -54,7 +54,7 @@ func (s *InitStateTestSuite) TestBeginReturnsError() { } func (s *InitStateTestSuite) TestGetLastLedgerIngestReturnsError() { - s.historyQ.On("Begin").Return(nil).Once() + s.historyQ.On("Begin", s.ctx).Return(nil).Once() s.historyQ.On("GetLastLedgerIngest", s.ctx).Return(uint32(0), errors.New("my error")).Once() next, err := startState{}.run(s.system) @@ -64,7 +64,7 @@ func (s *InitStateTestSuite) TestGetLastLedgerIngestReturnsError() { } func (s *InitStateTestSuite) TestGetIngestVersionReturnsError() { - s.historyQ.On("Begin").Return(nil).Once() + s.historyQ.On("Begin", s.ctx).Return(nil).Once() s.historyQ.On("GetLastLedgerIngest", s.ctx).Return(uint32(0), nil).Once() s.historyQ.On("GetIngestVersion", s.ctx).Return(0, errors.New("my error")).Once() @@ -75,7 +75,7 @@ func (s *InitStateTestSuite) TestGetIngestVersionReturnsError() { } func (s *InitStateTestSuite) TestCurrentVersionIsOutdated() { - s.historyQ.On("Begin").Return(nil).Once() + s.historyQ.On("Begin", s.ctx).Return(nil).Once() s.historyQ.On("GetLastLedgerIngest", s.ctx).Return(uint32(1), nil).Once() s.historyQ.On("GetIngestVersion", s.ctx).Return(CurrentVersion+1, nil).Once() @@ -85,7 +85,7 @@ func (s *InitStateTestSuite) TestCurrentVersionIsOutdated() { } func (s *InitStateTestSuite) TestGetLatestLedgerReturnsError() { - s.historyQ.On("Begin").Return(nil).Once() + s.historyQ.On("Begin", s.ctx).Return(nil).Once() s.historyQ.On("GetLastLedgerIngest", s.ctx).Return(uint32(0), nil).Once() s.historyQ.On("GetIngestVersion", s.ctx).Return(0, nil).Once() s.historyQ.On("GetLatestHistoryLedger", s.ctx).Return(uint32(0), errors.New("my error")).Once() @@ -97,7 +97,7 @@ func (s *InitStateTestSuite) TestGetLatestLedgerReturnsError() { } func (s *InitStateTestSuite) TestBuildStateEmptyDatabase() { - s.historyQ.On("Begin").Return(nil).Once() + s.historyQ.On("Begin", s.ctx).Return(nil).Once() s.historyQ.On("GetLastLedgerIngest", s.ctx).Return(uint32(0), nil).Once() s.historyQ.On("GetIngestVersion", s.ctx).Return(0, nil).Once() s.historyQ.On("GetLatestHistoryLedger", s.ctx).Return(uint32(0), nil).Once() @@ -113,7 +113,7 @@ func (s *InitStateTestSuite) TestBuildStateEmptyDatabase() { } func (s *InitStateTestSuite) TestBuildStateEmptyDatabaseFromSuggestedCheckpoint() { - s.historyQ.On("Begin").Return(nil).Once() + s.historyQ.On("Begin", s.ctx).Return(nil).Once() s.historyQ.On("GetLastLedgerIngest", s.ctx).Return(uint32(0), nil).Once() s.historyQ.On("GetIngestVersion", s.ctx).Return(0, nil).Once() s.historyQ.On("GetLatestHistoryLedger", s.ctx).Return(uint32(0), nil).Once() @@ -130,7 +130,7 @@ func (s *InitStateTestSuite) TestBuildStateEmptyDatabaseFromSuggestedCheckpoint( // * the ingest system version has been incremented or no ingest ledger, // * the old system is in front of the latest checkpoint. func (s *InitStateTestSuite) TestBuildStateWait() { - s.historyQ.On("Begin").Return(nil).Once() + s.historyQ.On("Begin", s.ctx).Return(nil).Once() s.historyQ.On("GetLastLedgerIngest", s.ctx).Return(uint32(100), nil).Once() s.historyQ.On("GetIngestVersion", s.ctx).Return(0, nil).Once() s.historyQ.On("GetLatestHistoryLedger", s.ctx).Return(uint32(100), nil).Once() @@ -149,7 +149,7 @@ func (s *InitStateTestSuite) TestBuildStateWait() { // * the ingest system version has been incremented or no ingest ledger, // * the old system is behind the latest checkpoint. func (s *InitStateTestSuite) TestBuildStateCatchup() { - s.historyQ.On("Begin").Return(nil).Once() + s.historyQ.On("Begin", s.ctx).Return(nil).Once() s.historyQ.On("GetLastLedgerIngest", s.ctx).Return(uint32(100), nil).Once() s.historyQ.On("GetIngestVersion", s.ctx).Return(0, nil).Once() s.historyQ.On("GetLatestHistoryLedger", s.ctx).Return(uint32(100), nil).Once() @@ -171,7 +171,7 @@ func (s *InitStateTestSuite) TestBuildStateCatchup() { // * the ingest system version has been incremented or no ingest ledger, // * the old system latest ledger is equal to the latest checkpoint. func (s *InitStateTestSuite) TestBuildStateOldHistory() { - s.historyQ.On("Begin").Return(nil).Once() + s.historyQ.On("Begin", s.ctx).Return(nil).Once() s.historyQ.On("GetLastLedgerIngest", s.ctx).Return(uint32(127), nil).Once() s.historyQ.On("GetIngestVersion", s.ctx).Return(0, nil).Once() s.historyQ.On("GetLatestHistoryLedger", s.ctx).Return(uint32(127), nil).Once() @@ -193,7 +193,7 @@ func (s *InitStateTestSuite) TestBuildStateOldHistory() { // * state doesn't need to be rebuilt, // * history is in front of ingest. func (s *InitStateTestSuite) TestResumeStateInFront() { - s.historyQ.On("Begin").Return(nil).Once() + s.historyQ.On("Begin", s.ctx).Return(nil).Once() s.historyQ.On("GetLastLedgerIngest", s.ctx).Return(uint32(100), nil).Once() s.historyQ.On("GetIngestVersion", s.ctx).Return(CurrentVersion, nil).Once() s.historyQ.On("GetLatestHistoryLedger", s.ctx).Return(uint32(130), nil).Once() @@ -210,7 +210,7 @@ func (s *InitStateTestSuite) TestResumeStateInFront() { // * state doesn't need to be rebuilt, // * history is behind of ingest. func (s *InitStateTestSuite) TestResumeStateBehind() { - s.historyQ.On("Begin").Return(nil).Once() + s.historyQ.On("Begin", s.ctx).Return(nil).Once() s.historyQ.On("GetLastLedgerIngest", s.ctx).Return(uint32(130), nil).Once() s.historyQ.On("GetIngestVersion", s.ctx).Return(CurrentVersion, nil).Once() s.historyQ.On("GetLatestHistoryLedger", s.ctx).Return(uint32(100), nil).Once() @@ -231,7 +231,7 @@ func (s *InitStateTestSuite) TestResumeStateBehind() { // * there are no ledgers in history tables. // In such case we load offers and continue ingesting the next ledger. func (s *InitStateTestSuite) TestResumeStateBehindHistory0() { - s.historyQ.On("Begin").Return(nil).Once() + s.historyQ.On("Begin", s.ctx).Return(nil).Once() s.historyQ.On("GetLastLedgerIngest", s.ctx).Return(uint32(130), nil).Once() s.historyQ.On("GetIngestVersion", s.ctx).Return(CurrentVersion, nil).Once() s.historyQ.On("GetLatestHistoryLedger", s.ctx).Return(uint32(0), nil).Once() @@ -251,7 +251,7 @@ func (s *InitStateTestSuite) TestResumeStateBehindHistory0() { // * state doesn't need to be rebuilt, // * history is in sync with ingest. func (s *InitStateTestSuite) TestResumeStateSync() { - s.historyQ.On("Begin").Return(nil).Once() + s.historyQ.On("Begin", s.ctx).Return(nil).Once() s.historyQ.On("GetLastLedgerIngest", s.ctx).Return(uint32(130), nil).Once() s.historyQ.On("GetIngestVersion", s.ctx).Return(CurrentVersion, nil).Once() s.historyQ.On("GetLatestHistoryLedger", s.ctx).Return(uint32(130), nil).Once() diff --git a/services/horizon/internal/ingest/main.go b/services/horizon/internal/ingest/main.go index 64fb710ef3..788daa3d22 100644 --- a/services/horizon/internal/ingest/main.go +++ b/services/horizon/internal/ingest/main.go @@ -6,7 +6,6 @@ package ingest import ( "context" "fmt" - "net/http" "runtime" "sync" "time" @@ -29,7 +28,7 @@ import ( const ( // MaxSupportedProtocolVersion defines the maximum supported version of // the Stellar protocol. - MaxSupportedProtocolVersion uint32 = 19 + MaxSupportedProtocolVersion uint32 = 20 // CurrentVersion reflects the latest version of the ingestion // algorithm. This value is stored in KV store and is used to decide @@ -38,7 +37,7 @@ const ( // Version history: // - 1: Initial version // - 2: Added the orderbook, offers processors and distributed ingestion. - // - 3: Fixed a bug that could potentialy result in invalid state + // - 3: Fixed a bug that could potentially result in invalid state // (#1722). Update the version to clear the state. // - 4: Fixed a bug in AccountSignersChanged method. // - 5: Added trust lines. @@ -56,7 +55,13 @@ const ( // - 13: Trigger state rebuild to include more than just authorized assets. // - 14: Trigger state rebuild to include claimable balances in the asset stats processor. // - 15: Fixed bug in asset stat ingestion where clawback is enabled (#3846). - CurrentVersion = 15 + // - 16: Extract claimants to a separate table for better performance of + // claimable balances for claimant queries. + // - 17: Add contract_id column to exp_asset_stats table which is derived by ingesting + // contract data ledger entries. + // - 18: Ingest contract asset balances so we can keep track of expired / restore asset + // balances for asset stats. + CurrentVersion = 18 // MaxDBConnections is the size of the postgres connection pool dedicated to Horizon ingestion: // * Ledger ingestion, @@ -66,6 +71,10 @@ const ( defaultCoreCursorName = "HORIZON" stateVerificationErrorThreshold = 3 + + // 100 ledgers per flush has shown in stress tests + // to be best point on performance curve, default to that. + MaxLedgersPerFlush uint32 = 100 ) var log = logpkg.DefaultLogger.WithField("service", "ingest") @@ -74,7 +83,6 @@ type Config struct { CoreSession db.SessionInterface StellarCoreURL string StellarCoreCursor string - EnableCaptiveCore bool CaptiveCoreBinaryPath string CaptiveCoreStoragePath string CaptiveCoreToml *ledgerbackend.CaptiveCoreToml @@ -82,8 +90,8 @@ type Config struct { RemoteCaptiveCoreURL string NetworkPassphrase string - HistorySession db.SessionInterface - HistoryArchiveURL string + HistorySession db.SessionInterface + HistoryArchiveURLs []string DisableStateVerification bool EnableReapLookupTables bool @@ -94,11 +102,27 @@ type Config struct { ReingestRetryBackoffSeconds int // The checkpoint frequency will be 64 unless you are using an exotic test setup. - CheckpointFrequency uint32 + CheckpointFrequency uint32 + StateVerificationCheckpointFrequency uint32 + StateVerificationTimeout time.Duration RoundingSlippageFilter int EnableIngestionFiltering bool + MaxLedgerPerFlush uint32 +} + +// LocalCaptiveCoreEnabled returns true if configured to run +// a local captive core instance for ingestion. +func (c Config) LocalCaptiveCoreEnabled() bool { + // c.RemoteCaptiveCoreURL is always empty when running local captive core. + return c.RemoteCaptiveCoreURL == "" +} + +// RemoteCaptiveCoreEnabled returns true if configured to run +// a remote captive core instance for ingestion. +func (c Config) RemoteCaptiveCoreEnabled() bool { + return c.RemoteCaptiveCoreURL != "" } const ( @@ -149,23 +173,11 @@ type Metrics struct { LedgerStatsCounter *prometheus.CounterVec // ProcessorsRunDuration exposes processors run durations. - // Deprecated in favour of: ProcessorsRunDurationSummary. + // Deprecated in favor of: ProcessorsRunDurationSummary. ProcessorsRunDuration *prometheus.CounterVec // ProcessorsRunDurationSummary exposes processors run durations. ProcessorsRunDurationSummary *prometheus.SummaryVec - - // LedgerFetchDurationSummary exposes a summary of durations required to - // fetch data from ledger backend. - LedgerFetchDurationSummary prometheus.Summary - - // CaptiveStellarCoreSynced exposes synced status of Captive Stellar-Core. - // 1 if sync, 0 if not synced, -1 if unable to connect or HTTP server disabled. - CaptiveStellarCoreSynced prometheus.GaugeFunc - - // CaptiveCoreSupportedProtocolVersion exposes the maximum protocol version - // supported by the running Captive-Core. - CaptiveCoreSupportedProtocolVersion prometheus.GaugeFunc } type System interface { @@ -174,9 +186,11 @@ type System interface { Metrics() Metrics StressTest(numTransactions, changesPerTransaction int) error VerifyRange(fromLedger, toLedger uint32, verifyState bool) error + BuildState(sequence uint32, skipChecks bool) error ReingestRange(ledgerRanges []history.LedgerRange, force bool) error BuildGenesisState() error Shutdown() + GetCurrentState() State } type system struct { @@ -206,17 +220,22 @@ type system struct { stateVerificationRunning bool disableStateVerification bool - checkpointManager historyarchive.CheckpointManager + runStateVerificationOnLedger func(uint32) bool - reapOffsets map[string]int64 + reapOffsets map[string]int64 + maxLedgerPerFlush uint32 + + currentStateMutex sync.Mutex + currentState State } func NewSystem(config Config) (System, error) { ctx, cancel := context.WithCancel(context.Background()) - archive, err := historyarchive.Connect( - config.HistoryArchiveURL, + archive, err := historyarchive.NewArchivePool( + config.HistoryArchiveURLs, historyarchive.ArchiveOptions{ + Context: ctx, NetworkPassphrase: config.NetworkPassphrase, CheckpointFrequency: config.CheckpointFrequency, ConnectOptions: storage.ConnectOptions{ @@ -230,34 +249,32 @@ func NewSystem(config Config) (System, error) { } var ledgerBackend ledgerbackend.LedgerBackend - if config.EnableCaptiveCore { - if len(config.RemoteCaptiveCoreURL) > 0 { - ledgerBackend, err = ledgerbackend.NewRemoteCaptive(config.RemoteCaptiveCoreURL) - if err != nil { - cancel() - return nil, errors.Wrap(err, "error creating captive core backend") - } - } else { - logger := log.WithField("subservice", "stellar-core") - ledgerBackend, err = ledgerbackend.NewCaptive( - ledgerbackend.CaptiveCoreConfig{ - BinaryPath: config.CaptiveCoreBinaryPath, - StoragePath: config.CaptiveCoreStoragePath, - UseDB: config.CaptiveCoreConfigUseDB, - Toml: config.CaptiveCoreToml, - NetworkPassphrase: config.NetworkPassphrase, - HistoryArchiveURLs: []string{config.HistoryArchiveURL}, - CheckpointFrequency: config.CheckpointFrequency, - LedgerHashStore: ledgerbackend.NewHorizonDBLedgerHashStore(config.HistorySession), - Log: logger, - Context: ctx, - UserAgent: fmt.Sprintf("captivecore horizon/%s golang/%s", apkg.Version(), runtime.Version()), - }, - ) - if err != nil { - cancel() - return nil, errors.Wrap(err, "error creating captive core backend") - } + if config.RemoteCaptiveCoreEnabled() { + ledgerBackend, err = ledgerbackend.NewRemoteCaptive(config.RemoteCaptiveCoreURL) + if err != nil { + cancel() + return nil, errors.Wrap(err, "error creating captive core backend") + } + } else if config.LocalCaptiveCoreEnabled() { + logger := log.WithField("subservice", "stellar-core") + ledgerBackend, err = ledgerbackend.NewCaptive( + ledgerbackend.CaptiveCoreConfig{ + BinaryPath: config.CaptiveCoreBinaryPath, + StoragePath: config.CaptiveCoreStoragePath, + UseDB: config.CaptiveCoreConfigUseDB, + Toml: config.CaptiveCoreToml, + NetworkPassphrase: config.NetworkPassphrase, + HistoryArchiveURLs: config.HistoryArchiveURLs, + CheckpointFrequency: config.CheckpointFrequency, + LedgerHashStore: ledgerbackend.NewHorizonDBLedgerHashStore(config.HistorySession), + Log: logger, + Context: ctx, + UserAgent: fmt.Sprintf("captivecore horizon/%s golang/%s", apkg.Version(), runtime.Version()), + }, + ) + if err != nil { + cancel() + return nil, errors.Wrap(err, "error creating captive core backend") } } else { coreSession := config.CoreSession.Clone() @@ -272,10 +289,16 @@ func NewSystem(config Config) (System, error) { historyAdapter := newHistoryArchiveAdapter(archive) filters := filters.NewFilters() + maxLedgersPerFlush := config.MaxLedgerPerFlush + if maxLedgersPerFlush < 1 { + maxLedgersPerFlush = MaxLedgersPerFlush + } + system := &system{ cancel: cancel, config: config, ctx: ctx, + currentState: None, disableStateVerification: config.DisableStateVerification, historyAdapter: historyAdapter, historyQ: historyQ, @@ -289,16 +312,30 @@ func NewSystem(config Config) (System, error) { ctx: ctx, config: config, historyQ: historyQ, + session: historyQ, historyAdapter: historyAdapter, filters: filters, }, - checkpointManager: historyarchive.NewCheckpointManager(config.CheckpointFrequency), + runStateVerificationOnLedger: ledgerEligibleForStateVerification( + config.CheckpointFrequency, + config.StateVerificationCheckpointFrequency, + ), + maxLedgerPerFlush: maxLedgersPerFlush, } system.initMetrics() return system, nil } +func ledgerEligibleForStateVerification(checkpointFrequency, stateVerificationFrequency uint32) func(ledger uint32) bool { + stateVerificationCheckpointManager := historyarchive.NewCheckpointManager( + checkpointFrequency * stateVerificationFrequency, + ) + return func(ledger uint32) bool { + return stateVerificationCheckpointManager.IsCheckpoint(ledger) + } +} + func (s *system) initMetrics() { s.metrics.MaxSupportedProtocolVersion = prometheus.NewGauge(prometheus.GaugeOpts{ Namespace: "horizon", Subsystem: "ingest", Name: "max_supported_protocol_version", @@ -314,22 +351,26 @@ func (s *system) initMetrics() { s.metrics.LedgerIngestionDuration = prometheus.NewSummary(prometheus.SummaryOpts{ Namespace: "horizon", Subsystem: "ingest", Name: "ledger_ingestion_duration_seconds", - Help: "ledger ingestion durations, sliding window = 10m", + Help: "ledger ingestion durations, sliding window = 10m", + Objectives: map[float64]float64{0.5: 0.05, 0.9: 0.01, 0.99: 0.001}, }) s.metrics.LedgerIngestionTradeAggregationDuration = prometheus.NewSummary(prometheus.SummaryOpts{ Namespace: "horizon", Subsystem: "ingest", Name: "ledger_ingestion_trade_aggregation_duration_seconds", - Help: "ledger ingestion trade aggregation rebuild durations, sliding window = 10m", + Help: "ledger ingestion trade aggregation rebuild durations, sliding window = 10m", + Objectives: map[float64]float64{0.5: 0.05, 0.9: 0.01, 0.99: 0.001}, }) s.metrics.LedgerIngestionReapLookupTablesDuration = prometheus.NewSummary(prometheus.SummaryOpts{ Namespace: "horizon", Subsystem: "ingest", Name: "ledger_ingestion_reap_lookup_tables_duration_seconds", - Help: "ledger ingestion reap lookup tables durations, sliding window = 10m", + Help: "ledger ingestion reap lookup tables durations, sliding window = 10m", + Objectives: map[float64]float64{0.5: 0.05, 0.9: 0.01, 0.99: 0.001}, }) s.metrics.StateVerifyDuration = prometheus.NewSummary(prometheus.SummaryOpts{ Namespace: "horizon", Subsystem: "ingest", Name: "state_verify_duration_seconds", - Help: "state verification durations, sliding window = 10m", + Help: "state verification durations, sliding window = 10m", + Objectives: map[float64]float64{0.5: 0.05, 0.9: 0.01, 0.99: 0.001}, }) s.metrics.StateInvalidGauge = prometheus.NewGaugeFunc( @@ -378,75 +419,17 @@ func (s *system) initMetrics() { s.metrics.ProcessorsRunDurationSummary = prometheus.NewSummaryVec( prometheus.SummaryOpts{ Namespace: "horizon", Subsystem: "ingest", Name: "processor_run_duration_seconds", - Help: "run durations of ingestion processors, sliding window = 10m", + Help: "run durations of ingestion processors, sliding window = 10m", + Objectives: map[float64]float64{0.5: 0.05, 0.9: 0.01, 0.99: 0.001}, }, []string{"name"}, ) +} - s.metrics.LedgerFetchDurationSummary = prometheus.NewSummary( - prometheus.SummaryOpts{ - Namespace: "horizon", Subsystem: "ingest", Name: "ledger_fetch_duration_seconds", - Help: "duration of fetching ledgers from ledger backend, sliding window = 10m", - }, - ) - - s.metrics.CaptiveStellarCoreSynced = prometheus.NewGaugeFunc( - prometheus.GaugeOpts{ - Namespace: "horizon", Subsystem: "ingest", Name: "captive_stellar_core_synced", - Help: "1 if sync, 0 if not synced, -1 if unable to connect or HTTP server disabled.", - }, - func() float64 { - if !s.config.EnableCaptiveCore || (s.config.CaptiveCoreToml.HTTPPort == 0) { - return -1 - } - - client := stellarcore.Client{ - HTTP: &http.Client{ - Timeout: 2 * time.Second, - }, - URL: fmt.Sprintf("http://localhost:%d", s.config.CaptiveCoreToml.HTTPPort), - } - - info, err := client.Info(s.ctx) - if err != nil { - log.WithError(err).Error("Cannot connect to Captive Stellar-Core HTTP server") - return -1 - } - - if info.IsSynced() { - return 1 - } else { - return 0 - } - }, - ) - - s.metrics.CaptiveCoreSupportedProtocolVersion = prometheus.NewGaugeFunc( - prometheus.GaugeOpts{ - Namespace: "horizon", Subsystem: "ingest", Name: "captive_stellar_core_supported_protocol_version", - Help: "determines the supported version of the protocol by Captive-Core", - }, - func() float64 { - if !s.config.EnableCaptiveCore || (s.config.CaptiveCoreToml.HTTPPort == 0) { - return -1 - } - - client := stellarcore.Client{ - HTTP: &http.Client{ - Timeout: 2 * time.Second, - }, - URL: fmt.Sprintf("http://localhost:%d", s.config.CaptiveCoreToml.HTTPPort), - } - - info, err := client.Info(s.ctx) - if err != nil { - log.WithError(err).Error("Cannot connect to Captive Stellar-Core HTTP server") - return -1 - } - - return float64(info.Info.ProtocolVersion) - }, - ) +func (s *system) GetCurrentState() State { + s.currentStateMutex.Lock() + defer s.currentStateMutex.Unlock() + return s.currentState } func (s *system) Metrics() Metrics { @@ -465,10 +448,8 @@ func (s *system) RegisterMetrics(registry *prometheus.Registry) { registry.MustRegister(s.metrics.LedgerStatsCounter) registry.MustRegister(s.metrics.ProcessorsRunDuration) registry.MustRegister(s.metrics.ProcessorsRunDurationSummary) - registry.MustRegister(s.metrics.CaptiveStellarCoreSynced) - registry.MustRegister(s.metrics.CaptiveCoreSupportedProtocolVersion) - registry.MustRegister(s.metrics.LedgerFetchDurationSummary) registry.MustRegister(s.metrics.StateVerifyLedgerEntriesCount) + s.ledgerBackend = ledgerbackend.WithMetrics(s.ledgerBackend, registry, "horizon") } // Run starts ingestion system. Ingestion system supports distributed ingestion @@ -531,6 +512,16 @@ func (s *system) VerifyRange(fromLedger, toLedger uint32, verifyState bool) erro }) } +// BuildState runs the state ingestion on selected checkpoint ledger then exits. +// When skipChecks is true it skips bucket list hash verification and protocol version check. +func (s *system) BuildState(sequence uint32, skipChecks bool) error { + return s.runStateMachine(buildState{ + checkpointLedger: sequence, + skipChecks: skipChecks, + stop: true, + }) +} + func validateRanges(ledgerRanges []history.LedgerRange) error { for i, cur := range ledgerRanges { if cur.StartSequence > cur.EndSequence { @@ -604,6 +595,10 @@ func (s *system) runStateMachine(cur stateMachineNode) error { panic("unexpected transaction") } + s.currentStateMutex.Lock() + s.currentState = cur.GetState() + s.currentStateMutex.Unlock() + next, err := cur.run(s) if err != nil { logger := log.WithFields(logpkg.F{ @@ -611,7 +606,7 @@ func (s *system) runStateMachine(cur stateMachineNode) error { "current_state": cur, "next_state": next.node, }) - if isCancelledError(err) { + if isCancelledError(s.ctx, err) { // We only expect context.Canceled errors to occur when horizon is shutting down // so we log these errors using the info log level logger.Info("Error in ingestion state machine") @@ -644,7 +639,7 @@ func (s *system) runStateMachine(cur stateMachineNode) error { func (s *system) maybeVerifyState(lastIngestedLedger uint32) { stateInvalid, err := s.historyQ.GetExpStateInvalid(s.ctx) if err != nil { - if !isCancelledError(err) { + if !isCancelledError(s.ctx, err) { log.WithField("err", err).Error("Error getting state invalid value") } return @@ -653,14 +648,14 @@ func (s *system) maybeVerifyState(lastIngestedLedger uint32) { // Run verification routine only when... if !stateInvalid && // state has not been proved to be invalid... !s.disableStateVerification && // state verification is not disabled... - s.checkpointManager.IsCheckpoint(lastIngestedLedger) { // it's a checkpoint ledger. + s.runStateVerificationOnLedger(lastIngestedLedger) { // it's a ledger eligible for state verification. s.wg.Add(1) go func() { defer s.wg.Done() err := s.verifyState(true) if err != nil { - if isCancelledError(err) { + if isCancelledError(s.ctx, err) { return } @@ -699,7 +694,7 @@ func (s *system) maybeReapLookupTables(lastIngestedLedger uint32) { return } - err = s.historyQ.Begin() + err = s.historyQ.Begin(s.ctx) if err != nil { log.WithField("err", err).Error("Error starting a transaction") return @@ -727,7 +722,7 @@ func (s *system) maybeReapLookupTables(lastIngestedLedger uint32) { err = s.historyQ.Commit() if err != nil { - log.WithField("err", err).Error("Error commiting a transaction") + log.WithField("err", err).Error("Error committing a transaction") return } @@ -761,7 +756,7 @@ func (s *system) resetStateVerificationErrors() { } func (s *system) updateCursor(ledgerSequence uint32) error { - if s.stellarCoreClient == nil || s.config.EnableCaptiveCore { + if s.stellarCoreClient == nil { return nil } @@ -804,7 +799,8 @@ func markStateInvalid(ctx context.Context, historyQ history.IngestionQ, err erro } } -func isCancelledError(err error) bool { +func isCancelledError(ctx context.Context, err error) bool { cause := errors.Cause(err) - return cause == context.Canceled || cause == db.ErrCancelled + return cause == context.Canceled || cause == db.ErrCancelled || + (ctx.Err() == context.Canceled && cause == db.ErrAlreadyRolledback) } diff --git a/services/horizon/internal/ingest/main_test.go b/services/horizon/internal/ingest/main_test.go index 7b930e80a2..55860eeaff 100644 --- a/services/horizon/internal/ingest/main_test.go +++ b/services/horizon/internal/ingest/main_test.go @@ -5,13 +5,13 @@ import ( "context" "database/sql" "testing" + "time" "github.com/jmoiron/sqlx" "github.com/prometheus/client_golang/prometheus" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" - "github.com/stellar/go/historyarchive" "github.com/stellar/go/ingest" "github.com/stellar/go/ingest/ledgerbackend" "github.com/stellar/go/services/horizon/internal/db2/history" @@ -79,12 +79,21 @@ func TestCheckVerifyStateVersion(t *testing.T) { ) } +func TestLedgerEligibleForStateVerification(t *testing.T) { + checker := ledgerEligibleForStateVerification(64, 3) + for ledger := uint32(1); ledger < 64*6; ledger++ { + run := checker(ledger) + expected := (ledger+1)%(64*3) == 0 + assert.Equal(t, expected, run) + } +} + func TestNewSystem(t *testing.T) { config := Config{ CoreSession: &db.Session{DB: &sqlx.DB{}}, HistorySession: &db.Session{DB: &sqlx.DB{}}, DisableStateVerification: true, - HistoryArchiveURL: "https://history.stellar.org/prd/core-live/core_live_001", + HistoryArchiveURLs: []string{"https://history.stellar.org/prd/core-live/core_live_001"}, CheckpointFrequency: 64, } @@ -97,6 +106,7 @@ func TestNewSystem(t *testing.T) { assert.Equal(t, config, system.runner.(*ProcessorRunner).config) assert.Equal(t, system.ctx, system.runner.(*ProcessorRunner).ctx) + assert.Equal(t, system.maxLedgerPerFlush, MaxLedgersPerFlush) } func TestStateMachineRunReturnsUnexpectedTransaction(t *testing.T) { @@ -121,7 +131,7 @@ func TestStateMachineTransition(t *testing.T) { } historyQ.On("GetTx").Return(nil).Once() - historyQ.On("Begin").Return(errors.New("my error")).Once() + historyQ.On("Begin", mock.Anything).Return(errors.New("my error")).Once() historyQ.On("GetTx").Return(&sqlx.Tx{}).Once() assert.PanicsWithValue(t, "unexpected transaction", func() { @@ -138,7 +148,7 @@ func TestContextCancel(t *testing.T) { } historyQ.On("GetTx").Return(nil).Once() - historyQ.On("Begin").Return(errors.New("my error")).Once() + historyQ.On("Begin", mock.AnythingOfType("*context.cancelCtx")).Return(errors.New("my error")).Once() cancel() assert.NoError(t, system.runStateMachine(startState{})) @@ -165,9 +175,9 @@ func TestStateMachineRunReturnsErrorWhenNextStateIsShutdownWithError(t *testing. func TestMaybeVerifyStateGetExpStateInvalidError(t *testing.T) { historyQ := &mockDBQ{} system := &system{ - historyQ: historyQ, - ctx: context.Background(), - checkpointManager: historyarchive.NewCheckpointManager(64), + historyQ: historyQ, + ctx: context.Background(), + runStateVerificationOnLedger: ledgerEligibleForStateVerification(64, 1), } var out bytes.Buffer @@ -200,9 +210,9 @@ func TestMaybeVerifyStateGetExpStateInvalidError(t *testing.T) { func TestMaybeVerifyInternalDBErrCancelOrContextCanceled(t *testing.T) { historyQ := &mockDBQ{} system := &system{ - historyQ: historyQ, - ctx: context.Background(), - checkpointManager: historyarchive.NewCheckpointManager(64), + historyQ: historyQ, + ctx: context.Background(), + runStateVerificationOnLedger: ledgerEligibleForStateVerification(64, 1), } var out bytes.Buffer @@ -218,11 +228,11 @@ func TestMaybeVerifyInternalDBErrCancelOrContextCanceled(t *testing.T) { historyQ.On("Rollback").Return(nil).Twice() historyQ.On("CloneIngestionQ").Return(historyQ).Twice() - historyQ.On("BeginTx", mock.Anything).Return(db.ErrCancelled).Once() + historyQ.On("BeginTx", mock.Anything, mock.Anything).Return(db.ErrCancelled).Once() system.maybeVerifyState(63) system.wg.Wait() - historyQ.On("BeginTx", mock.Anything).Return(context.Canceled).Once() + historyQ.On("BeginTx", mock.Anything, mock.Anything).Return(context.Canceled).Once() system.maybeVerifyState(63) system.wg.Wait() @@ -234,6 +244,46 @@ func TestMaybeVerifyInternalDBErrCancelOrContextCanceled(t *testing.T) { historyQ.AssertExpectations(t) } +func TestCurrentStateRaceCondition(t *testing.T) { + historyQ := &mockDBQ{} + s := &system{ + historyQ: historyQ, + ctx: context.Background(), + } + + historyQ.On("GetTx").Return(nil) + historyQ.On("Begin", s.ctx).Return(nil) + historyQ.On("Rollback").Return(nil) + historyQ.On("GetLastLedgerIngest", s.ctx).Return(uint32(1), nil) + historyQ.On("GetIngestVersion", s.ctx).Return(CurrentVersion, nil) + + timer := time.NewTimer(2000 * time.Millisecond) + getCh := make(chan bool, 1) + doneCh := make(chan bool, 1) + go func() { + var state = buildState{checkpointLedger: 8, + skipChecks: true, + stop: true} + for range getCh { + _ = s.runStateMachine(state) + } + close(doneCh) + }() + +loop: + for { + s.GetCurrentState() + select { + case <-timer.C: + break loop + default: + } + getCh <- true + } + close(getCh) + <-doneCh +} + type mockDBQ struct { mock.Mock @@ -254,13 +304,13 @@ type mockDBQ struct { history.MockQTrustLines } -func (m *mockDBQ) Begin() error { - args := m.Called() +func (m *mockDBQ) Begin(ctx context.Context) error { + args := m.Called(ctx) return args.Error(0) } -func (m *mockDBQ) BeginTx(txOpts *sql.TxOptions) error { - args := m.Called(txOpts) +func (m *mockDBQ) BeginTx(ctx context.Context, txOpts *sql.TxOptions) error { + args := m.Called(ctx, txOpts) return args.Error(0) } @@ -284,6 +334,11 @@ func (m *mockDBQ) Rollback() error { return args.Error(0) } +func (m *mockDBQ) TryStateVerificationLock(ctx context.Context) (bool, error) { + args := m.Called(ctx) + return args.Get(0).(bool), args.Error(1) +} + func (m *mockDBQ) GetTx() *sqlx.Tx { args := m.Called() if args.Get(0) == nil { @@ -359,18 +414,18 @@ func (m *mockDBQ) DeleteRangeAll(ctx context.Context, start, end int64) error { // Methods from interfaces duplicating methods: -func (m *mockDBQ) NewTransactionParticipantsBatchInsertBuilder(maxBatchSize int) history.TransactionParticipantsBatchInsertBuilder { - args := m.Called(maxBatchSize) +func (m *mockDBQ) NewTransactionParticipantsBatchInsertBuilder() history.TransactionParticipantsBatchInsertBuilder { + args := m.Called() return args.Get(0).(history.TransactionParticipantsBatchInsertBuilder) } -func (m *mockDBQ) NewOperationParticipantBatchInsertBuilder(maxBatchSize int) history.OperationParticipantBatchInsertBuilder { - args := m.Called(maxBatchSize) - return args.Get(0).(history.TransactionParticipantsBatchInsertBuilder) +func (m *mockDBQ) NewOperationParticipantBatchInsertBuilder() history.OperationParticipantBatchInsertBuilder { + args := m.Called() + return args.Get(0).(history.OperationParticipantBatchInsertBuilder) } -func (m *mockDBQ) NewTradeBatchInsertBuilder(maxBatchSize int) history.TradeBatchInsertBuilder { - args := m.Called(maxBatchSize) +func (m *mockDBQ) NewTradeBatchInsertBuilder() history.TradeBatchInsertBuilder { + args := m.Called() return args.Get(0).(history.TradeBatchInsertBuilder) } @@ -458,10 +513,11 @@ func (m *mockProcessorsRunner) RunGenesisStateIngestion() (ingest.StatsChangePro func (m *mockProcessorsRunner) RunHistoryArchiveIngestion( checkpointLedger uint32, + skipChecks bool, ledgerProtocolVersion uint32, bucketListHash xdr.Hash, ) (ingest.StatsChangeProcessorResults, error) { - args := m.Called(checkpointLedger, ledgerProtocolVersion, bucketListHash) + args := m.Called(checkpointLedger, skipChecks, ledgerProtocolVersion, bucketListHash) return args.Get(0).(ingest.StatsChangeProcessorResults), args.Error(1) } @@ -487,6 +543,11 @@ func (m *mockProcessorsRunner) RunTransactionProcessorsOnLedger(ledger xdr.Ledge args.Error(3) } +func (m *mockProcessorsRunner) RunTransactionProcessorsOnLedgers(ledgers []xdr.LedgerCloseMeta) error { + args := m.Called(ledgers) + return args.Error(0) +} + var _ ProcessorRunnerInterface = (*mockProcessorsRunner)(nil) type mockStellarCoreClient struct { @@ -527,6 +588,11 @@ func (m *mockSystem) VerifyRange(fromLedger, toLedger uint32, verifyState bool) return args.Error(0) } +func (m *mockSystem) BuildState(sequence uint32, skipChecks bool) error { + args := m.Called(sequence, skipChecks) + return args.Error(0) +} + func (m *mockSystem) ReingestRange(ledgerRanges []history.LedgerRange, force bool) error { args := m.Called(ledgerRanges, force) return args.Error(0) @@ -537,6 +603,11 @@ func (m *mockSystem) BuildGenesisState() error { return args.Error(0) } +func (m *mockSystem) GetCurrentState() State { + args := m.Called() + return args.Get(0).(State) +} + func (m *mockSystem) Shutdown() { m.Called() } diff --git a/services/horizon/internal/ingest/orderbook.go b/services/horizon/internal/ingest/orderbook.go index e62cc7a8b6..3f8401cf1c 100644 --- a/services/horizon/internal/ingest/orderbook.go +++ b/services/horizon/internal/ingest/orderbook.go @@ -233,11 +233,11 @@ func (o *OrderBookStream) verifyAllOffers(ctx context.Context, offers []xdr.Offe offerRowXDR := offerToXDR(offerRow) offerEntryBase64, err := o.encodingBuffer.MarshalBase64(&offerEntry) if err != nil { - return false, errors.Wrap(err, "Error from marshalling offerEntry") + return false, errors.Wrap(err, "Error from marshaling offerEntry") } offerRowBase64, err := o.encodingBuffer.MarshalBase64(&offerRowXDR) if err != nil { - return false, errors.Wrap(err, "Error from marshalling offerRowXDR") + return false, errors.Wrap(err, "Error from marshaling offerRowXDR") } if offerEntryBase64 != offerRowBase64 { mismatch = true @@ -290,11 +290,11 @@ func (o *OrderBookStream) verifyAllLiquidityPools(ctx context.Context, liquidity } liquidityPoolEntryBase64, err = o.encodingBuffer.MarshalBase64(&liquidityPoolEntry) if err != nil { - return false, errors.Wrap(err, "Error from marshalling liquidityPoolEntry") + return false, errors.Wrap(err, "Error from marshaling liquidityPoolEntry") } liquidityPoolRowBase64, err = o.encodingBuffer.MarshalBase64(&liquidityPoolRowXDR) if err != nil { - return false, errors.Wrap(err, "Error from marshalling liquidityPoolRowXDR") + return false, errors.Wrap(err, "Error from marshaling liquidityPoolRowXDR") } if liquidityPoolEntryBase64 != liquidityPoolRowBase64 { mismatch = true @@ -318,7 +318,7 @@ func (o *OrderBookStream) verifyAllLiquidityPools(ctx context.Context, liquidity // After calling this function, the the in memory order book graph should be consistent with the // Horizon DB (assuming no error is returned). func (o *OrderBookStream) Update(ctx context.Context) error { - if err := o.historyQ.BeginTx(&sql.TxOptions{ReadOnly: true, Isolation: sql.LevelRepeatableRead}); err != nil { + if err := o.historyQ.BeginTx(ctx, &sql.TxOptions{ReadOnly: true, Isolation: sql.LevelRepeatableRead}); err != nil { return errors.Wrap(err, "Error starting repeatable read transaction") } defer o.historyQ.Rollback() @@ -353,7 +353,7 @@ func (o *OrderBookStream) Update(ctx context.Context) error { offersOk, err := o.verifyAllOffers(ctx, offers) if err != nil { - if !isCancelledError(err) { + if !isCancelledError(ctx, err) { log.WithError(err).Info("Could not verify offers") return nil } @@ -361,7 +361,7 @@ func (o *OrderBookStream) Update(ctx context.Context) error { liquidityPoolsOK, err := o.verifyAllLiquidityPools(ctx, pools) if err != nil { - if !isCancelledError(err) { + if !isCancelledError(ctx, err) { log.WithError(err).Info("Could not verify liquidity pools") return nil } @@ -383,7 +383,7 @@ func (o *OrderBookStream) Run(ctx context.Context) { for { select { case <-ticker.C: - if err := o.Update(ctx); err != nil && !isCancelledError(err) { + if err := o.Update(ctx); err != nil && !isCancelledError(ctx, err) { log.WithError(err).Error("could not apply updates from order book stream") } case <-ctx.Done(): diff --git a/services/horizon/internal/ingest/processor_runner.go b/services/horizon/internal/ingest/processor_runner.go index 2067688df9..ed066a20d2 100644 --- a/services/horizon/internal/ingest/processor_runner.go +++ b/services/horizon/internal/ingest/processor_runner.go @@ -10,7 +10,9 @@ import ( "github.com/stellar/go/services/horizon/internal/db2/history" "github.com/stellar/go/services/horizon/internal/ingest/filters" "github.com/stellar/go/services/horizon/internal/ingest/processors" + "github.com/stellar/go/support/db" "github.com/stellar/go/support/errors" + logpkg "github.com/stellar/go/support/log" "github.com/stellar/go/xdr" ) @@ -31,7 +33,10 @@ type horizonChangeProcessor interface { type horizonTransactionProcessor interface { processors.LedgerTransactionProcessor - Commit(context.Context) error +} + +type horizonLazyLoader interface { + Exec(ctx context.Context, session db.SessionInterface) error } type statsChangeProcessor struct { @@ -42,14 +47,6 @@ func (statsChangeProcessor) Commit(ctx context.Context) error { return nil } -type statsLedgerTransactionProcessor struct { - *processors.StatsLedgerTransactionProcessor -} - -func (statsLedgerTransactionProcessor) Commit(ctx context.Context) error { - return nil -} - type ledgerStats struct { changeStats ingest.StatsChangeProcessorResults changeDurations processorsRunDurations @@ -65,6 +62,7 @@ type ProcessorRunnerInterface interface { RunGenesisStateIngestion() (ingest.StatsChangeProcessorResults, error) RunHistoryArchiveIngestion( checkpointLedger uint32, + skipChecks bool, ledgerProtocolVersion uint32, bucketListHash xdr.Hash, ) (ingest.StatsChangeProcessorResults, error) @@ -74,6 +72,7 @@ type ProcessorRunnerInterface interface { tradeStats processors.TradeStats, err error, ) + RunTransactionProcessorsOnLedgers(ledgers []xdr.LedgerCloseMeta) error RunAllProcessorsOnLedger(ledger xdr.LedgerCloseMeta) ( stats ledgerStats, err error, @@ -87,6 +86,7 @@ type ProcessorRunner struct { ctx context.Context historyQ history.IngestionQ + session db.SessionInterface historyAdapter historyArchiveAdapterInterface logMemoryStats bool filters filters.Filters @@ -110,6 +110,7 @@ func buildChangeProcessor( changeStats *ingest.StatsChangeProcessor, source ingestionSource, ledgerSequence uint32, + networkPassphrase string, ) *groupChangeProcessors { statsChangeProcessor := &statsChangeProcessor{ StatsChangeProcessor: changeStats, @@ -121,7 +122,7 @@ func buildChangeProcessor( processors.NewAccountDataProcessor(historyQ), processors.NewAccountsProcessor(historyQ), processors.NewOffersProcessor(historyQ, ledgerSequence), - processors.NewAssetStatsProcessor(historyQ, useLedgerCache), + processors.NewAssetStatsProcessor(historyQ, networkPassphrase, source == historyArchiveSource, ledgerSequence), processors.NewSignersProcessor(historyQ, useLedgerCache), processors.NewTrustLinesProcessor(historyQ), processors.NewClaimableBalancesChangeProcessor(historyQ), @@ -129,27 +130,33 @@ func buildChangeProcessor( }) } -func (s *ProcessorRunner) buildTransactionProcessor( - ledgerTransactionStats *processors.StatsLedgerTransactionProcessor, - tradeProcessor *processors.TradeProcessor, - ledger xdr.LedgerHeaderHistoryEntry, -) *groupTransactionProcessors { - statsLedgerTransactionProcessor := &statsLedgerTransactionProcessor{ - StatsLedgerTransactionProcessor: ledgerTransactionStats, - } - *tradeProcessor = *processors.NewTradeProcessor(s.historyQ, ledger) - sequence := uint32(ledger.Header.LedgerSeq) - return newGroupTransactionProcessors([]horizonTransactionProcessor{ +func (s *ProcessorRunner) buildTransactionProcessor(ledgersProcessor *processors.LedgersProcessor) *groupTransactionProcessors { + accountLoader := history.NewAccountLoader() + assetLoader := history.NewAssetLoader() + lpLoader := history.NewLiquidityPoolLoader() + cbLoader := history.NewClaimableBalanceLoader() + + lazyLoaders := []horizonLazyLoader{accountLoader, assetLoader, lpLoader, cbLoader} + statsLedgerTransactionProcessor := processors.NewStatsLedgerTransactionProcessor() + + tradeProcessor := processors.NewTradeProcessor(accountLoader, + lpLoader, assetLoader, s.historyQ.NewTradeBatchInsertBuilder()) + + processors := []horizonTransactionProcessor{ statsLedgerTransactionProcessor, - processors.NewEffectProcessor(s.historyQ, sequence), - processors.NewLedgerProcessor(s.historyQ, ledger, CurrentVersion), - processors.NewOperationProcessor(s.historyQ, sequence), + processors.NewEffectProcessor(accountLoader, s.historyQ.NewEffectBatchInsertBuilder(), s.config.NetworkPassphrase), + ledgersProcessor, + processors.NewOperationProcessor(s.historyQ.NewOperationBatchInsertBuilder(), s.config.NetworkPassphrase), tradeProcessor, - processors.NewParticipantsProcessor(s.historyQ, sequence), - processors.NewTransactionProcessor(s.historyQ, sequence), - processors.NewClaimableBalancesTransactionProcessor(s.historyQ, sequence), - processors.NewLiquidityPoolsTransactionProcessor(s.historyQ, sequence), - }) + processors.NewParticipantsProcessor(accountLoader, + s.historyQ.NewTransactionParticipantsBatchInsertBuilder(), s.historyQ.NewOperationParticipantBatchInsertBuilder()), + processors.NewTransactionProcessor(s.historyQ.NewTransactionBatchInsertBuilder()), + processors.NewClaimableBalancesTransactionProcessor(cbLoader, + s.historyQ.NewTransactionClaimableBalanceBatchInsertBuilder(), s.historyQ.NewOperationClaimableBalanceBatchInsertBuilder()), + processors.NewLiquidityPoolsTransactionProcessor(lpLoader, + s.historyQ.NewTransactionLiquidityPoolBatchInsertBuilder(), s.historyQ.NewOperationLiquidityPoolBatchInsertBuilder())} + + return newGroupTransactionProcessors(processors, lazyLoaders, statsLedgerTransactionProcessor, tradeProcessor) } func (s *ProcessorRunner) buildTransactionFilterer() *groupTransactionFilterers { @@ -161,15 +168,15 @@ func (s *ProcessorRunner) buildTransactionFilterer() *groupTransactionFilterers return newGroupTransactionFilterers(f) } -func (s *ProcessorRunner) buildFilteredOutProcessor(ledger xdr.LedgerHeaderHistoryEntry) *groupTransactionProcessors { +func (s *ProcessorRunner) buildFilteredOutProcessor() *groupTransactionProcessors { // when in online mode, the submission result processor must always run (regardless of filtering) var p []horizonTransactionProcessor if s.config.EnableIngestionFiltering { - txSubProc := processors.NewTransactionFilteredTmpProcessor(s.historyQ, uint32(ledger.Header.LedgerSeq)) + txSubProc := processors.NewTransactionFilteredTmpProcessor(s.historyQ.NewTransactionFilteredTmpBatchInsertBuilder()) p = append(p, txSubProc) } - return newGroupTransactionProcessors(p) + return newGroupTransactionProcessors(p, nil, nil, nil) } // checkIfProtocolVersionSupported checks if this Horizon version supports the @@ -212,28 +219,37 @@ func (s *ProcessorRunner) validateBucketList(ledgerSequence uint32, ledgerBucket } func (s *ProcessorRunner) RunGenesisStateIngestion() (ingest.StatsChangeProcessorResults, error) { - return s.RunHistoryArchiveIngestion(1, 0, xdr.Hash{}) + return s.RunHistoryArchiveIngestion(1, false, 0, xdr.Hash{}) } func (s *ProcessorRunner) RunHistoryArchiveIngestion( checkpointLedger uint32, + skipChecks bool, ledgerProtocolVersion uint32, bucketListHash xdr.Hash, ) (ingest.StatsChangeProcessorResults, error) { changeStats := ingest.StatsChangeProcessor{} - changeProcessor := buildChangeProcessor(s.historyQ, &changeStats, historyArchiveSource, checkpointLedger) + changeProcessor := buildChangeProcessor( + s.historyQ, + &changeStats, + historyArchiveSource, + checkpointLedger, + s.config.NetworkPassphrase, + ) if checkpointLedger == 1 { if err := changeProcessor.ProcessChange(s.ctx, ingest.GenesisChange(s.config.NetworkPassphrase)); err != nil { return changeStats.GetResults(), errors.Wrap(err, "Error ingesting genesis ledger") } } else { - if err := s.checkIfProtocolVersionSupported(ledgerProtocolVersion); err != nil { - return changeStats.GetResults(), errors.Wrap(err, "Error while checking for supported protocol version") - } - - if err := s.validateBucketList(checkpointLedger, bucketListHash); err != nil { - return changeStats.GetResults(), errors.Wrap(err, "Error validating bucket list from HAS") + if !skipChecks { + if err := s.checkIfProtocolVersionSupported(ledgerProtocolVersion); err != nil { + return changeStats.GetResults(), errors.Wrap(err, "Error while checking for supported protocol version") + } + + if err := s.validateBucketList(checkpointLedger, bucketListHash); err != nil { + return changeStats.GetResults(), errors.Wrap(err, "Error validating bucket list from HAS") + } } changeReader, err := s.historyAdapter.GetState(s.ctx, checkpointLedger) @@ -259,7 +275,7 @@ func (s *ProcessorRunner) RunHistoryArchiveIngestion( } if err := changeProcessor.Commit(s.ctx); err != nil { - return changeStats.GetResults(), errors.Wrap(err, "Error commiting changes from processor") + return changeStats.GetResults(), errors.Wrap(err, "Error committing changes from processor") } return changeStats.GetResults(), nil @@ -287,69 +303,93 @@ func (s *ProcessorRunner) runChangeProcessorOnLedger( err = changeProcessor.Commit(s.ctx) if err != nil { - return errors.Wrap(err, "Error commiting changes from processor") + return errors.Wrap(err, "Error committing changes from processor") } return nil } -func (s *ProcessorRunner) RunTransactionProcessorsOnLedger(ledger xdr.LedgerCloseMeta) ( - transactionStats processors.StatsLedgerTransactionProcessorResults, - transactionDurations processorsRunDurations, - tradeStats processors.TradeStats, - err error, -) { +func (s *ProcessorRunner) streamLedger(ledger xdr.LedgerCloseMeta, + groupFilterers *groupTransactionFilterers, + groupFilteredOutProcessors *groupTransactionProcessors, + groupProcessors *groupTransactionProcessors) error { var ( - ledgerTransactionStats processors.StatsLedgerTransactionProcessor - tradeProcessor processors.TradeProcessor - transactionReader *ingest.LedgerTransactionReader + transactionReader *ingest.LedgerTransactionReader ) - transactionReader, err = ingest.NewLedgerTransactionReaderFromLedgerCloseMeta(s.config.NetworkPassphrase, ledger) + if err := s.checkIfProtocolVersionSupported(ledger.ProtocolVersion()); err != nil { + err = errors.Wrap(err, "Error while checking for supported protocol version") + return err + } + + startTime := time.Now() + transactionReader, err := ingest.NewLedgerTransactionReaderFromLedgerCloseMeta(s.config.NetworkPassphrase, ledger) if err != nil { err = errors.Wrap(err, "Error creating ledger reader") - return + return err } - if err = s.checkIfProtocolVersionSupported(ledger.ProtocolVersion()); err != nil { - err = errors.Wrap(err, "Error while checking for supported protocol version") - return + err = processors.StreamLedgerTransactions(s.ctx, + groupFilterers, + groupFilteredOutProcessors, + groupProcessors, + transactionReader, + ledger, + ) + if err != nil { + return errors.Wrap(err, "Error streaming changes from ledger") } - header := transactionReader.GetHeader() + + transactionStats := groupProcessors.transactionStatsProcessor.GetResults() + transactionStats.TransactionsFiltered = groupFilterers.droppedTransactions + + tradeStats := groupProcessors.tradeProcessor.GetStats() + + log.WithFields(transactionStats.Map()). + WithFields(tradeStats.Map()). + WithFields(logpkg.F{ + "sequence": ledger.LedgerSequence(), + "state": false, + "ledger": true, + "commit": false, + "duration": time.Since(startTime).Seconds(), + }).Info("Processed ledger") + + return nil +} + +func (s *ProcessorRunner) RunTransactionProcessorsOnLedger(ledger xdr.LedgerCloseMeta) ( + transactionStats processors.StatsLedgerTransactionProcessorResults, + transactionDurations processorsRunDurations, + tradeStats processors.TradeStats, + err error, +) { + // ensure capture of the ledger to history regardless of whether it has transactions. + ledgersProcessor := processors.NewLedgerProcessor(s.historyQ.NewLedgerBatchInsertBuilder(), CurrentVersion) + ledgersProcessor.ProcessLedger(ledger) + groupTransactionFilterers := s.buildTransactionFilterer() - groupFilteredOutProcessors := s.buildFilteredOutProcessor(header) - groupTransactionProcessors := s.buildTransactionProcessor( - &ledgerTransactionStats, &tradeProcessor, header) - err = processors.StreamLedgerTransactions(s.ctx, + groupFilteredOutProcessors := s.buildFilteredOutProcessor() + groupTransactionProcessors := s.buildTransactionProcessor(ledgersProcessor) + + err = s.streamLedger(ledger, groupTransactionFilterers, groupFilteredOutProcessors, groupTransactionProcessors, - transactionReader, ) if err != nil { err = errors.Wrap(err, "Error streaming changes from ledger") return } - if s.config.EnableIngestionFiltering { - err = groupFilteredOutProcessors.Commit(s.ctx) - if err != nil { - err = errors.Wrap(err, "Error committing filtered changes from processor") - return - } - if time.Since(s.lastTransactionsTmpGC) > transactionsFilteredTmpGCPeriod { - s.historyQ.DeleteTransactionsFilteredTmpOlderThan(s.ctx, uint64(transactionsFilteredTmpGCPeriod.Seconds())) - } - } - - err = groupTransactionProcessors.Commit(s.ctx) + err = s.flushProcessors(groupFilteredOutProcessors, groupTransactionProcessors) if err != nil { - err = errors.Wrap(err, "Error committing changes from processor") return } - transactionStats = ledgerTransactionStats.GetResults() + transactionStats = groupTransactionProcessors.transactionStatsProcessor.GetResults() transactionStats.TransactionsFiltered = groupTransactionFilterers.droppedTransactions + transactionDurations = groupTransactionProcessors.processorsRunDurations for key, duration := range groupFilteredOutProcessors.processorsRunDurations { transactionDurations[key] = duration @@ -358,7 +398,81 @@ func (s *ProcessorRunner) RunTransactionProcessorsOnLedger(ledger xdr.LedgerClos transactionDurations[key] = duration } - tradeStats = tradeProcessor.GetStats() + tradeStats = groupTransactionProcessors.tradeProcessor.GetStats() + + return +} + +func (s *ProcessorRunner) RunTransactionProcessorsOnLedgers(ledgers []xdr.LedgerCloseMeta) (err error) { + ledgersProcessor := processors.NewLedgerProcessor(s.historyQ.NewLedgerBatchInsertBuilder(), CurrentVersion) + + groupTransactionFilterers := s.buildTransactionFilterer() + groupFilteredOutProcessors := s.buildFilteredOutProcessor() + groupTransactionProcessors := s.buildTransactionProcessor(ledgersProcessor) + + startTime := time.Now() + curHeap, sysHeap := getMemStats() + log.WithFields(logpkg.F{ + "currentHeapSizeMB": curHeap, + "systemHeapSizeMB": sysHeap, + "ledgerBatchSize": len(ledgers), + "state": false, + "ledger": true, + "commit": false, + }).Infof("Running processors for batch of %v ledgers", len(ledgers)) + + for _, ledger := range ledgers { + // ensure capture of the ledger to history regardless of whether it has transactions. + ledgersProcessor.ProcessLedger(ledger) + + err = s.streamLedger(ledger, + groupTransactionFilterers, + groupFilteredOutProcessors, + groupTransactionProcessors, + ) + if err != nil { + err = errors.Wrap(err, "Error streaming changes during ledger batch") + return + } + groupTransactionProcessors.ResetStats() + groupFilteredOutProcessors.ResetStats() + groupTransactionFilterers.ResetStats() + } + + err = s.flushProcessors(groupFilteredOutProcessors, groupTransactionProcessors) + if err != nil { + return + } + curHeap, sysHeap = getMemStats() + log.WithFields(logpkg.F{ + "currentHeapSizeMB": curHeap, + "systemHeapSizeMB": sysHeap, + "ledgers": len(ledgers), + "state": false, + "ledger": true, + "commit": false, + "duration": time.Since(startTime).Seconds(), + }).Infof("Flushed processors for batch of %v ledgers", len(ledgers)) + + return nil +} + +func (s *ProcessorRunner) flushProcessors(groupFilteredOutProcessors *groupTransactionProcessors, groupTransactionProcessors *groupTransactionProcessors) (err error) { + if s.config.EnableIngestionFiltering { + err = groupFilteredOutProcessors.Flush(s.ctx, s.session) + if err != nil { + err = errors.Wrap(err, "Error flushing temp filtered tx from processor") + return + } + if time.Since(s.lastTransactionsTmpGC) > transactionsFilteredTmpGCPeriod { + s.historyQ.DeleteTransactionsFilteredTmpOlderThan(s.ctx, uint64(transactionsFilteredTmpGCPeriod.Seconds())) + } + } + + err = groupTransactionProcessors.Flush(s.ctx, s.session) + if err != nil { + err = errors.Wrap(err, "Error flushing changes from processor") + } return } @@ -373,20 +487,25 @@ func (s *ProcessorRunner) RunAllProcessorsOnLedger(ledger xdr.LedgerCloseMeta) ( return } - groupChangeProcessors := buildChangeProcessor(s.historyQ, &changeStatsProcessor, ledgerSource, ledger.LedgerSequence()) + groupChangeProcessors := buildChangeProcessor( + s.historyQ, + &changeStatsProcessor, + ledgerSource, + ledger.LedgerSequence(), + s.config.NetworkPassphrase, + ) err = s.runChangeProcessorOnLedger(groupChangeProcessors, ledger) if err != nil { return } + transactionStats, transactionDurations, tradeStats, err := s.RunTransactionProcessorsOnLedger(ledger) + stats.changeStats = changeStatsProcessor.GetResults() stats.changeDurations = groupChangeProcessors.processorsRunDurations - - stats.transactionStats, stats.transactionDurations, stats.tradeStats, err = - s.RunTransactionProcessorsOnLedger(ledger) - if err != nil { - return - } + stats.transactionStats = transactionStats + stats.transactionDurations = transactionDurations + stats.tradeStats = tradeStats return } diff --git a/services/horizon/internal/ingest/processor_runner_test.go b/services/horizon/internal/ingest/processor_runner_test.go index 5cae018ea5..eaeca95661 100644 --- a/services/horizon/internal/ingest/processor_runner_test.go +++ b/services/horizon/internal/ingest/processor_runner_test.go @@ -16,37 +16,37 @@ import ( "github.com/stellar/go/network" "github.com/stellar/go/services/horizon/internal/db2/history" "github.com/stellar/go/services/horizon/internal/ingest/processors" + "github.com/stellar/go/support/db" "github.com/stellar/go/xdr" ) func TestProcessorRunnerRunHistoryArchiveIngestionGenesis(t *testing.T) { ctx := context.Background() - maxBatchSize := 100000 + + mockSession := &db.MockSession{} q := &mockDBQ{} - q.MockQAccounts.On("UpsertAccounts", ctx, []history.AccountEntry{ - { - LastModifiedLedger: 1, - AccountID: "GAAZI4TCR3TY5OJHCTJC2A4QSY6CJWJH5IAJTGKIN2ER7LBNVKOCCWN7", - Balance: int64(1000000000000000000), - SequenceNumber: 0, - SequenceTime: zero.IntFrom(0), - MasterWeight: 1, - }, - }).Return(nil).Once() + batchBuilders := mockChangeProcessorBatchBuilders(q, ctx, true) + defer mock.AssertExpectationsForObjects(t, batchBuilders...) - mockAccountSignersBatchInsertBuilder := &history.MockAccountSignersBatchInsertBuilder{} - defer mock.AssertExpectationsForObjects(t, mockAccountSignersBatchInsertBuilder) - mockAccountSignersBatchInsertBuilder.On("Add", ctx, history.AccountSigner{ + assert.IsType(t, &history.MockAccountSignersBatchInsertBuilder{}, batchBuilders[0]) + batchBuilders[0].(*history.MockAccountSignersBatchInsertBuilder).On("Add", history.AccountSigner{ Account: "GAAZI4TCR3TY5OJHCTJC2A4QSY6CJWJH5IAJTGKIN2ER7LBNVKOCCWN7", Signer: "GAAZI4TCR3TY5OJHCTJC2A4QSY6CJWJH5IAJTGKIN2ER7LBNVKOCCWN7", Weight: 1, Sponsor: null.String{}, }).Return(nil).Once() - mockAccountSignersBatchInsertBuilder.On("Exec", ctx).Return(nil).Once() - q.MockQSigners.On("NewAccountSignersBatchInsertBuilder", maxBatchSize). - Return(mockAccountSignersBatchInsertBuilder).Once() + + assert.IsType(t, &history.MockAccountsBatchInsertBuilder{}, batchBuilders[1]) + batchBuilders[1].(*history.MockAccountsBatchInsertBuilder).On("Add", history.AccountEntry{ + LastModifiedLedger: 1, + AccountID: "GAAZI4TCR3TY5OJHCTJC2A4QSY6CJWJH5IAJTGKIN2ER7LBNVKOCCWN7", + Balance: int64(1000000000000000000), + SequenceNumber: 0, + SequenceTime: zero.IntFrom(0), + MasterWeight: 1, + }).Return(nil).Once() q.MockQAssetStats.On("InsertAssetStats", ctx, []history.ExpAssetStat{}, 100000). Return(nil) @@ -58,6 +58,7 @@ func TestProcessorRunnerRunHistoryArchiveIngestionGenesis(t *testing.T) { }, historyQ: q, filters: &MockFilters{}, + session: mockSession, } _, err := runner.RunGenesisStateIngestion() @@ -66,12 +67,12 @@ func TestProcessorRunnerRunHistoryArchiveIngestionGenesis(t *testing.T) { func TestProcessorRunnerRunHistoryArchiveIngestionHistoryArchive(t *testing.T) { ctx := context.Background() - maxBatchSize := 100000 config := Config{ NetworkPassphrase: network.PublicNetworkPassphrase, } + mockSession := &db.MockSession{} q := &mockDBQ{} defer mock.AssertExpectationsForObjects(t, q) historyAdapter := &mockHistoryArchiveAdapter{} @@ -92,26 +93,24 @@ func TestProcessorRunnerRunHistoryArchiveIngestionHistoryArchive(t *testing.T) { nil, ).Once() - q.MockQAccounts.On("UpsertAccounts", ctx, []history.AccountEntry{ - { - LastModifiedLedger: 1, - AccountID: "GAAZI4TCR3TY5OJHCTJC2A4QSY6CJWJH5IAJTGKIN2ER7LBNVKOCCWN7", - Balance: int64(1000000000000000000), - SequenceNumber: 0, - MasterWeight: 1, - }, - }).Return(nil).Once() + batchBuilders := mockChangeProcessorBatchBuilders(q, ctx, true) + defer mock.AssertExpectationsForObjects(t, batchBuilders...) - mockAccountSignersBatchInsertBuilder := &history.MockAccountSignersBatchInsertBuilder{} - defer mock.AssertExpectationsForObjects(t, mockAccountSignersBatchInsertBuilder) - mockAccountSignersBatchInsertBuilder.On("Add", ctx, history.AccountSigner{ + assert.IsType(t, &history.MockAccountSignersBatchInsertBuilder{}, batchBuilders[0]) + batchBuilders[0].(*history.MockAccountSignersBatchInsertBuilder).On("Add", history.AccountSigner{ Account: "GAAZI4TCR3TY5OJHCTJC2A4QSY6CJWJH5IAJTGKIN2ER7LBNVKOCCWN7", Signer: "GAAZI4TCR3TY5OJHCTJC2A4QSY6CJWJH5IAJTGKIN2ER7LBNVKOCCWN7", Weight: 1, }).Return(nil).Once() - mockAccountSignersBatchInsertBuilder.On("Exec", ctx).Return(nil).Once() - q.MockQSigners.On("NewAccountSignersBatchInsertBuilder", maxBatchSize). - Return(mockAccountSignersBatchInsertBuilder).Once() + + assert.IsType(t, &history.MockAccountsBatchInsertBuilder{}, batchBuilders[1]) + batchBuilders[1].(*history.MockAccountsBatchInsertBuilder).On("Add", history.AccountEntry{ + LastModifiedLedger: 1, + AccountID: "GAAZI4TCR3TY5OJHCTJC2A4QSY6CJWJH5IAJTGKIN2ER7LBNVKOCCWN7", + Balance: int64(1000000000000000000), + SequenceNumber: 0, + MasterWeight: 1, + }).Return(nil).Once() q.MockQAssetStats.On("InsertAssetStats", ctx, []history.ExpAssetStat{}, 100000). Return(nil) @@ -122,31 +121,28 @@ func TestProcessorRunnerRunHistoryArchiveIngestionHistoryArchive(t *testing.T) { historyQ: q, historyAdapter: historyAdapter, filters: &MockFilters{}, + session: mockSession, } - _, err := runner.RunHistoryArchiveIngestion(63, MaxSupportedProtocolVersion, bucketListHash) + _, err := runner.RunHistoryArchiveIngestion(63, false, MaxSupportedProtocolVersion, bucketListHash) assert.NoError(t, err) } func TestProcessorRunnerRunHistoryArchiveIngestionProtocolVersionNotSupported(t *testing.T) { ctx := context.Background() - maxBatchSize := 100000 config := Config{ NetworkPassphrase: network.PublicNetworkPassphrase, } + mockSession := &db.MockSession{} q := &mockDBQ{} defer mock.AssertExpectationsForObjects(t, q) historyAdapter := &mockHistoryArchiveAdapter{} defer mock.AssertExpectationsForObjects(t, historyAdapter) // Batches - - mockAccountSignersBatchInsertBuilder := &history.MockAccountSignersBatchInsertBuilder{} - defer mock.AssertExpectationsForObjects(t, mockAccountSignersBatchInsertBuilder) - q.MockQSigners.On("NewAccountSignersBatchInsertBuilder", maxBatchSize). - Return(mockAccountSignersBatchInsertBuilder).Once() + defer mock.AssertExpectationsForObjects(t, mockChangeProcessorBatchBuilders(q, ctx, false)...) q.MockQAssetStats.On("InsertAssetStats", ctx, []history.ExpAssetStat{}, 100000). Return(nil) @@ -157,9 +153,10 @@ func TestProcessorRunnerRunHistoryArchiveIngestionProtocolVersionNotSupported(t historyQ: q, historyAdapter: historyAdapter, filters: &MockFilters{}, + session: mockSession, } - _, err := runner.RunHistoryArchiveIngestion(100, 200, xdr.Hash{}) + _, err := runner.RunHistoryArchiveIngestion(100, false, 200, xdr.Hash{}) assert.EqualError(t, err, fmt.Sprintf( "Error while checking for supported protocol version: This Horizon version does not support protocol version 200. The latest supported protocol version is %d. Please upgrade to the latest Horizon version.", @@ -170,14 +167,12 @@ func TestProcessorRunnerRunHistoryArchiveIngestionProtocolVersionNotSupported(t func TestProcessorRunnerBuildChangeProcessor(t *testing.T) { ctx := context.Background() - maxBatchSize := 100000 q := &mockDBQ{} defer mock.AssertExpectationsForObjects(t, q) - // Twice = checking ledgerSource and historyArchiveSource - q.MockQSigners.On("NewAccountSignersBatchInsertBuilder", maxBatchSize). - Return(&history.MockAccountSignersBatchInsertBuilder{}).Twice() + defer mock.AssertExpectationsForObjects(t, mockChangeProcessorBatchBuilders(q, ctx, false)...) + runner := ProcessorRunner{ ctx: ctx, historyQ: q, @@ -185,7 +180,7 @@ func TestProcessorRunnerBuildChangeProcessor(t *testing.T) { } stats := &ingest.StatsChangeProcessor{} - processor := buildChangeProcessor(runner.historyQ, stats, ledgerSource, 123) + processor := buildChangeProcessor(runner.historyQ, stats, ledgerSource, 123, "") assert.IsType(t, &groupChangeProcessors{}, processor) assert.IsType(t, &statsChangeProcessor{}, processor.processors[0]) @@ -193,8 +188,8 @@ func TestProcessorRunnerBuildChangeProcessor(t *testing.T) { assert.IsType(t, &processors.AccountsProcessor{}, processor.processors[2]) assert.IsType(t, &processors.OffersProcessor{}, processor.processors[3]) assert.IsType(t, &processors.AssetStatsProcessor{}, processor.processors[4]) - assert.True(t, reflect.ValueOf(processor.processors[4]). - Elem().FieldByName("useLedgerEntryCache").Bool()) + assert.False(t, reflect.ValueOf(processor.processors[4]). + Elem().FieldByName("ingestFromHistoryArchive").Bool()) assert.IsType(t, &processors.SignersProcessor{}, processor.processors[5]) assert.True(t, reflect.ValueOf(processor.processors[5]). Elem().FieldByName("useLedgerEntryCache").Bool()) @@ -206,7 +201,7 @@ func TestProcessorRunnerBuildChangeProcessor(t *testing.T) { filters: &MockFilters{}, } - processor = buildChangeProcessor(runner.historyQ, stats, historyArchiveSource, 456) + processor = buildChangeProcessor(runner.historyQ, stats, historyArchiveSource, 456, "") assert.IsType(t, &groupChangeProcessors{}, processor) assert.IsType(t, &statsChangeProcessor{}, processor.processors[0]) @@ -214,8 +209,8 @@ func TestProcessorRunnerBuildChangeProcessor(t *testing.T) { assert.IsType(t, &processors.AccountsProcessor{}, processor.processors[2]) assert.IsType(t, &processors.OffersProcessor{}, processor.processors[3]) assert.IsType(t, &processors.AssetStatsProcessor{}, processor.processors[4]) - assert.False(t, reflect.ValueOf(processor.processors[4]). - Elem().FieldByName("useLedgerEntryCache").Bool()) + assert.True(t, reflect.ValueOf(processor.processors[4]). + Elem().FieldByName("ingestFromHistoryArchive").Bool()) assert.IsType(t, &processors.SignersProcessor{}, processor.processors[5]) assert.False(t, reflect.ValueOf(processor.processors[5]). Elem().FieldByName("useLedgerEntryCache").Bool()) @@ -224,15 +219,31 @@ func TestProcessorRunnerBuildChangeProcessor(t *testing.T) { func TestProcessorRunnerBuildTransactionProcessor(t *testing.T) { ctx := context.Background() - maxBatchSize := 100000 q := &mockDBQ{} defer mock.AssertExpectationsForObjects(t, q) - q.MockQOperations.On("NewOperationBatchInsertBuilder", maxBatchSize). - Return(&history.MockOperationsBatchInsertBuilder{}).Twice() // Twice = with/without failed - q.MockQTransactions.On("NewTransactionBatchInsertBuilder", maxBatchSize). - Return(&history.MockTransactionsBatchInsertBuilder{}).Twice() + q.MockQTransactions.On("NewTransactionBatchInsertBuilder"). + Return(&history.MockTransactionsBatchInsertBuilder{}) + q.On("NewTradeBatchInsertBuilder").Return(&history.MockTradeBatchInsertBuilder{}) + q.MockQLedgers.On("NewLedgerBatchInsertBuilder"). + Return(&history.MockLedgersBatchInsertBuilder{}) + q.MockQEffects.On("NewEffectBatchInsertBuilder"). + Return(&history.MockEffectBatchInsertBuilder{}) + q.MockQOperations.On("NewOperationBatchInsertBuilder"). + Return(&history.MockOperationsBatchInsertBuilder{}) + q.On("NewTransactionParticipantsBatchInsertBuilder"). + Return(&history.MockTransactionParticipantsBatchInsertBuilder{}) + q.On("NewOperationParticipantBatchInsertBuilder"). + Return(&history.MockOperationParticipantBatchInsertBuilder{}) + q.MockQHistoryClaimableBalances.On("NewTransactionClaimableBalanceBatchInsertBuilder"). + Return(&history.MockTransactionClaimableBalanceBatchInsertBuilder{}) + q.MockQHistoryClaimableBalances.On("NewOperationClaimableBalanceBatchInsertBuilder"). + Return(&history.MockOperationClaimableBalanceBatchInsertBuilder{}) + q.MockQHistoryLiquidityPools.On("NewTransactionLiquidityPoolBatchInsertBuilder"). + Return(&history.MockTransactionLiquidityPoolBatchInsertBuilder{}) + q.MockQHistoryLiquidityPools.On("NewOperationLiquidityPoolBatchInsertBuilder"). + Return(&history.MockOperationLiquidityPoolBatchInsertBuilder{}) runner := ProcessorRunner{ ctx: ctx, @@ -240,24 +251,22 @@ func TestProcessorRunnerBuildTransactionProcessor(t *testing.T) { historyQ: q, } - stats := &processors.StatsLedgerTransactionProcessor{} - trades := &processors.TradeProcessor{} - ledger := xdr.LedgerHeaderHistoryEntry{} - processor := runner.buildTransactionProcessor(stats, trades, ledger) - assert.IsType(t, &groupTransactionProcessors{}, processor) + ledgersProcessor := &processors.LedgersProcessor{} - assert.IsType(t, &statsLedgerTransactionProcessor{}, processor.processors[0]) + processor := runner.buildTransactionProcessor(ledgersProcessor) + assert.IsType(t, &groupTransactionProcessors{}, processor) + assert.IsType(t, &processors.StatsLedgerTransactionProcessor{}, processor.processors[0]) assert.IsType(t, &processors.EffectProcessor{}, processor.processors[1]) assert.IsType(t, &processors.LedgersProcessor{}, processor.processors[2]) assert.IsType(t, &processors.OperationProcessor{}, processor.processors[3]) assert.IsType(t, &processors.TradeProcessor{}, processor.processors[4]) assert.IsType(t, &processors.ParticipantsProcessor{}, processor.processors[5]) - assert.IsType(t, &processors.TransactionProcessor{}, processor.processors[6]) + assert.IsType(t, &processors.ClaimableBalancesTransactionProcessor{}, processor.processors[7]) + assert.IsType(t, &processors.LiquidityPoolsTransactionProcessor{}, processor.processors[8]) } func TestProcessorRunnerWithFilterEnabled(t *testing.T) { ctx := context.Background() - maxBatchSize := 100000 config := Config{ NetworkPassphrase: network.PublicNetworkPassphrase, @@ -265,6 +274,7 @@ func TestProcessorRunnerWithFilterEnabled(t *testing.T) { } q := &mockDBQ{} + mockSession := &db.MockSession{} defer mock.AssertExpectationsForObjects(t, q) ledger := xdr.LedgerCloseMeta{ @@ -272,43 +282,51 @@ func TestProcessorRunnerWithFilterEnabled(t *testing.T) { LedgerHeader: xdr.LedgerHeaderHistoryEntry{ Header: xdr.LedgerHeader{ BucketListHash: xdr.Hash([32]byte{0, 1, 2}), + LedgerSeq: 23, }, }, }, } - // Batches - mockAccountSignersBatchInsertBuilder := &history.MockAccountSignersBatchInsertBuilder{} - defer mock.AssertExpectationsForObjects(t, mockAccountSignersBatchInsertBuilder) - q.MockQSigners.On("NewAccountSignersBatchInsertBuilder", maxBatchSize). - Return(mockAccountSignersBatchInsertBuilder).Once() - - mockOperationsBatchInsertBuilder := &history.MockOperationsBatchInsertBuilder{} - defer mock.AssertExpectationsForObjects(t, mockOperationsBatchInsertBuilder) - mockOperationsBatchInsertBuilder.On("Exec", ctx).Return(nil).Once() - q.MockQOperations.On("NewOperationBatchInsertBuilder", maxBatchSize). - Return(mockOperationsBatchInsertBuilder).Twice() - - mockTransactionsBatchInsertBuilder := &history.MockTransactionsBatchInsertBuilder{} - defer mock.AssertExpectationsForObjects(t, mockTransactionsBatchInsertBuilder) - mockTransactionsBatchInsertBuilder.On("Exec", ctx).Return(nil).Twice() - - q.MockQTransactions.On("NewTransactionBatchInsertBuilder", maxBatchSize). - Return(mockTransactionsBatchInsertBuilder) - - q.MockQTransactions.On("NewTransactionFilteredTmpBatchInsertBuilder", maxBatchSize). - Return(mockTransactionsBatchInsertBuilder) - + mockTransactionsFilteredTmpBatchInsertBuilder := &history.MockTransactionsBatchInsertBuilder{} + defer mock.AssertExpectationsForObjects(t, mockTransactionsFilteredTmpBatchInsertBuilder) + mockTransactionsFilteredTmpBatchInsertBuilder.On("Exec", ctx, mockSession).Return(nil).Once() + q.MockQTransactions.On("NewTransactionFilteredTmpBatchInsertBuilder"). + Return(mockTransactionsFilteredTmpBatchInsertBuilder) q.On("DeleteTransactionsFilteredTmpOlderThan", ctx, mock.AnythingOfType("uint64")). Return(int64(0), nil) - q.MockQLedgers.On("InsertLedger", ctx, ledger.V0.LedgerHeader, 0, 0, 0, 0, CurrentVersion). - Return(int64(1), nil).Once() + defer mock.AssertExpectationsForObjects(t, mockTxProcessorBatchBuilders(q, mockSession, ctx)...) + defer mock.AssertExpectationsForObjects(t, mockChangeProcessorBatchBuilders(q, ctx, true)...) + + mockBatchInsertBuilder := &history.MockLedgersBatchInsertBuilder{} + q.MockQLedgers.On("NewLedgerBatchInsertBuilder").Return(mockBatchInsertBuilder) + mockBatchInsertBuilder.On( + "Add", + ledger.V0.LedgerHeader, 0, 0, 0, 0, CurrentVersion).Return(nil) + mockBatchInsertBuilder.On( + "Exec", + ctx, + mockSession, + ).Return(nil) + defer mock.AssertExpectationsForObjects(t, mockBatchInsertBuilder) + + q.MockQAssetStats.On("RemoveContractAssetBalances", ctx, []xdr.Hash(nil)). + Return(nil).Once() + q.MockQAssetStats.On("UpdateContractAssetBalanceAmounts", ctx, []xdr.Hash{}, []string{}). + Return(nil).Once() + q.MockQAssetStats.On("InsertContractAssetBalances", ctx, []history.ContractAssetBalance(nil)). + Return(nil).Once() + q.MockQAssetStats.On("UpdateContractAssetBalanceExpirations", ctx, []xdr.Hash{}, []uint32{}). + Return(nil).Once() + q.MockQAssetStats.On("GetContractAssetBalancesExpiringAt", ctx, uint32(22)). + Return([]history.ContractAssetBalance{}, nil).Once() runner := ProcessorRunner{ ctx: ctx, config: config, historyQ: q, + session: mockSession, filters: &MockFilters{}, } @@ -318,12 +336,12 @@ func TestProcessorRunnerWithFilterEnabled(t *testing.T) { func TestProcessorRunnerRunAllProcessorsOnLedger(t *testing.T) { ctx := context.Background() - maxBatchSize := 100000 config := Config{ NetworkPassphrase: network.PublicNetworkPassphrase, } + mockSession := &db.MockSession{} q := &mockDBQ{} defer mock.AssertExpectationsForObjects(t, q) @@ -332,40 +350,138 @@ func TestProcessorRunnerRunAllProcessorsOnLedger(t *testing.T) { LedgerHeader: xdr.LedgerHeaderHistoryEntry{ Header: xdr.LedgerHeader{ BucketListHash: xdr.Hash([32]byte{0, 1, 2}), + LedgerSeq: 23, }, }, }, } // Batches - mockAccountSignersBatchInsertBuilder := &history.MockAccountSignersBatchInsertBuilder{} - defer mock.AssertExpectationsForObjects(t, mockAccountSignersBatchInsertBuilder) - q.MockQSigners.On("NewAccountSignersBatchInsertBuilder", maxBatchSize). - Return(mockAccountSignersBatchInsertBuilder).Once() + defer mock.AssertExpectationsForObjects(t, mockTxProcessorBatchBuilders(q, mockSession, ctx)...) + defer mock.AssertExpectationsForObjects(t, mockChangeProcessorBatchBuilders(q, ctx, true)...) + + mockBatchInsertBuilder := &history.MockLedgersBatchInsertBuilder{} + q.MockQLedgers.On("NewLedgerBatchInsertBuilder").Return(mockBatchInsertBuilder) + mockBatchInsertBuilder.On( + "Add", + ledger.V0.LedgerHeader, 0, 0, 0, 0, CurrentVersion).Return(nil).Once() + mockBatchInsertBuilder.On( + "Exec", + ctx, + mockSession, + ).Return(nil).Once() + + defer mock.AssertExpectationsForObjects(t, mockBatchInsertBuilder) + + q.MockQAssetStats.On("RemoveContractAssetBalances", ctx, []xdr.Hash(nil)). + Return(nil).Once() + q.MockQAssetStats.On("UpdateContractAssetBalanceAmounts", ctx, []xdr.Hash{}, []string{}). + Return(nil).Once() + q.MockQAssetStats.On("InsertContractAssetBalances", ctx, []history.ContractAssetBalance(nil)). + Return(nil).Once() + q.MockQAssetStats.On("UpdateContractAssetBalanceExpirations", ctx, []xdr.Hash{}, []uint32{}). + Return(nil).Once() + q.MockQAssetStats.On("GetContractAssetBalancesExpiringAt", ctx, uint32(22)). + Return([]history.ContractAssetBalance{}, nil).Once() - mockOperationsBatchInsertBuilder := &history.MockOperationsBatchInsertBuilder{} - defer mock.AssertExpectationsForObjects(t, mockOperationsBatchInsertBuilder) - mockOperationsBatchInsertBuilder.On("Exec", ctx).Return(nil).Once() - q.MockQOperations.On("NewOperationBatchInsertBuilder", maxBatchSize). - Return(mockOperationsBatchInsertBuilder).Twice() + runner := ProcessorRunner{ + ctx: ctx, + config: config, + historyQ: q, + session: mockSession, + filters: &MockFilters{}, + } - mockTransactionsBatchInsertBuilder := &history.MockTransactionsBatchInsertBuilder{} - defer mock.AssertExpectationsForObjects(t, mockTransactionsBatchInsertBuilder) - mockTransactionsBatchInsertBuilder.On("Exec", ctx).Return(nil).Once() - q.MockQTransactions.On("NewTransactionBatchInsertBuilder", maxBatchSize). - Return(mockTransactionsBatchInsertBuilder).Twice() + _, err := runner.RunAllProcessorsOnLedger(ledger) + assert.NoError(t, err) +} - q.MockQLedgers.On("InsertLedger", ctx, ledger.V0.LedgerHeader, 0, 0, 0, 0, CurrentVersion). - Return(int64(1), nil).Once() +func TestProcessorRunnerRunTransactionsProcessorsOnLedgers(t *testing.T) { + ctx := context.Background() + + config := Config{ + NetworkPassphrase: network.PublicNetworkPassphrase, + } + + mockSession := &db.MockSession{} + q := &mockDBQ{} + defer mock.AssertExpectationsForObjects(t, q) + + ledgers := []xdr.LedgerCloseMeta{{ + V0: &xdr.LedgerCloseMetaV0{ + LedgerHeader: xdr.LedgerHeaderHistoryEntry{ + Header: xdr.LedgerHeader{ + BucketListHash: xdr.Hash([32]byte{0, 1, 2}), + LedgerSeq: xdr.Uint32(1), + }, + }, + }, + }, + { + V0: &xdr.LedgerCloseMetaV0{ + LedgerHeader: xdr.LedgerHeaderHistoryEntry{ + Header: xdr.LedgerHeader{ + BucketListHash: xdr.Hash([32]byte{3, 4, 5}), + LedgerSeq: xdr.Uint32(2), + }, + }, + }, + }, + { + V0: &xdr.LedgerCloseMetaV0{ + LedgerHeader: xdr.LedgerHeaderHistoryEntry{ + Header: xdr.LedgerHeader{ + BucketListHash: xdr.Hash([32]byte{6, 7, 8}), + LedgerSeq: xdr.Uint32(3), + }, + }, + }, + }, + } + + // Batches + defer mock.AssertExpectationsForObjects(t, mockTxProcessorBatchBuilders(q, mockSession, ctx)...) + + mockBatchInsertBuilder := &history.MockLedgersBatchInsertBuilder{} + q.MockQLedgers.On("NewLedgerBatchInsertBuilder").Return(mockBatchInsertBuilder) + mockBatchInsertBuilder.On( + "Add", + ledgers[0].V0.LedgerHeader, 0, 0, 0, 0, CurrentVersion).Return(nil).Once() + mockBatchInsertBuilder.On( + "Add", + ledgers[1].V0.LedgerHeader, 0, 0, 0, 0, CurrentVersion).Return(nil).Once() + mockBatchInsertBuilder.On( + "Add", + ledgers[2].V0.LedgerHeader, 0, 0, 0, 0, CurrentVersion).Return(nil).Once() + + mockBatchInsertBuilder.On( + "Exec", + ctx, + mockSession, + ).Return(nil).Once() + + defer mock.AssertExpectationsForObjects(t, mockBatchInsertBuilder) + + q.MockQAssetStats.On("RemoveContractAssetBalances", ctx, []xdr.Hash(nil)). + Return(nil).Once() + q.MockQAssetStats.On("UpdateContractAssetBalanceAmounts", ctx, []xdr.Hash{}, []string{}). + Return(nil).Once() + q.MockQAssetStats.On("InsertContractAssetBalances", ctx, []history.ContractAssetBalance(nil)). + Return(nil).Once() + q.MockQAssetStats.On("UpdateContractAssetBalanceExpirations", ctx, []xdr.Hash{}, []uint32{}). + Return(nil).Once() + q.MockQAssetStats.On("GetContractAssetBalancesExpiringAt", ctx, uint32(22)). + Return([]history.ContractAssetBalance{}, nil).Once() runner := ProcessorRunner{ ctx: ctx, config: config, historyQ: q, + session: mockSession, filters: &MockFilters{}, } - _, err := runner.RunAllProcessorsOnLedger(ledger) + err := runner.RunTransactionProcessorsOnLedgers(ledgers) assert.NoError(t, err) } @@ -391,21 +507,21 @@ func TestProcessorRunnerRunAllProcessorsOnLedgerProtocolVersionNotSupported(t *t } // Batches + mockTransactionsBatchInsertBuilder := &history.MockTransactionsBatchInsertBuilder{} + q.MockQTransactions.On("NewTransactionBatchInsertBuilder", maxBatchSize). + Return(mockTransactionsBatchInsertBuilder).Twice() mockAccountSignersBatchInsertBuilder := &history.MockAccountSignersBatchInsertBuilder{} - defer mock.AssertExpectationsForObjects(t, mockAccountSignersBatchInsertBuilder) - q.MockQSigners.On("NewAccountSignersBatchInsertBuilder", maxBatchSize). - Return(mockAccountSignersBatchInsertBuilder).Once() + q.MockQSigners.On("NewAccountSignersBatchInsertBuilder"). + Return(mockAccountSignersBatchInsertBuilder).Twice() mockOperationsBatchInsertBuilder := &history.MockOperationsBatchInsertBuilder{} - defer mock.AssertExpectationsForObjects(t, mockOperationsBatchInsertBuilder) - q.MockQOperations.On("NewOperationBatchInsertBuilder", maxBatchSize). + q.MockQOperations.On("NewOperationBatchInsertBuilder"). Return(mockOperationsBatchInsertBuilder).Twice() - mockTransactionsBatchInsertBuilder := &history.MockTransactionsBatchInsertBuilder{} - defer mock.AssertExpectationsForObjects(t, mockTransactionsBatchInsertBuilder) - q.MockQTransactions.On("NewTransactionBatchInsertBuilder", maxBatchSize). - Return(mockTransactionsBatchInsertBuilder).Twice() + defer mock.AssertExpectationsForObjects(t, mockTransactionsBatchInsertBuilder, + mockAccountSignersBatchInsertBuilder, + mockOperationsBatchInsertBuilder) runner := ProcessorRunner{ ctx: ctx, @@ -422,3 +538,128 @@ func TestProcessorRunnerRunAllProcessorsOnLedgerProtocolVersionNotSupported(t *t ), ) } + +func mockTxProcessorBatchBuilders(q *mockDBQ, mockSession *db.MockSession, ctx context.Context) []interface{} { + // no mocking of builder Add methods needed, the fake ledgers used in tests don't have any operations + // that would trigger the respective processors to invoke Add, each test locally decides to use + // MockLedgersBatchInsertBuilder with asserts on Add invocations, as those are fired once per ledger. + mockTradeBatchInsertBuilder := &history.MockTradeBatchInsertBuilder{} + q.On("NewTradeBatchInsertBuilder").Return(mockTradeBatchInsertBuilder).Once() + + mockTransactionsBatchInsertBuilder := &history.MockTransactionsBatchInsertBuilder{} + mockTransactionsBatchInsertBuilder.On("Exec", ctx, mockSession).Return(nil).Once() + q.MockQTransactions.On("NewTransactionBatchInsertBuilder"). + Return(mockTransactionsBatchInsertBuilder).Once() + + mockOperationsBatchInsertBuilder := &history.MockOperationsBatchInsertBuilder{} + mockOperationsBatchInsertBuilder.On("Exec", ctx, mockSession).Return(nil).Once() + q.MockQOperations.On("NewOperationBatchInsertBuilder"). + Return(mockOperationsBatchInsertBuilder).Once() + + mockEffectBatchInsertBuilder := &history.MockEffectBatchInsertBuilder{} + mockEffectBatchInsertBuilder.On("Exec", ctx, mockSession).Return(nil).Once() + q.MockQEffects.On("NewEffectBatchInsertBuilder"). + Return(mockEffectBatchInsertBuilder).Once() + + mockTransactionsParticipantsBatchInsertBuilder := &history.MockTransactionParticipantsBatchInsertBuilder{} + mockTransactionsParticipantsBatchInsertBuilder.On("Exec", ctx, mockSession).Return(nil).Once() + q.On("NewTransactionParticipantsBatchInsertBuilder"). + Return(mockTransactionsParticipantsBatchInsertBuilder).Once() + + mockOperationParticipantBatchInsertBuilder := &history.MockOperationParticipantBatchInsertBuilder{} + mockOperationParticipantBatchInsertBuilder.On("Exec", ctx, mockSession).Return(nil).Once() + q.On("NewOperationParticipantBatchInsertBuilder"). + Return(mockOperationParticipantBatchInsertBuilder).Once() + + mockTransactionClaimableBalanceBatchInsertBuilder := &history.MockTransactionClaimableBalanceBatchInsertBuilder{} + mockTransactionClaimableBalanceBatchInsertBuilder.On("Exec", ctx, mockSession).Return(nil).Once() + q.MockQHistoryClaimableBalances.On("NewTransactionClaimableBalanceBatchInsertBuilder"). + Return(mockTransactionClaimableBalanceBatchInsertBuilder).Once() + + mockOperationClaimableBalanceBatchInsertBuilder := &history.MockOperationClaimableBalanceBatchInsertBuilder{} + mockOperationClaimableBalanceBatchInsertBuilder.On("Exec", ctx, mockSession).Return(nil).Once() + q.MockQHistoryClaimableBalances.On("NewOperationClaimableBalanceBatchInsertBuilder"). + Return(mockOperationClaimableBalanceBatchInsertBuilder).Once() + + mockTransactionLiquidityPoolBatchInsertBuilder := &history.MockTransactionLiquidityPoolBatchInsertBuilder{} + mockTransactionLiquidityPoolBatchInsertBuilder.On("Exec", ctx, mockSession).Return(nil).Once() + q.MockQHistoryLiquidityPools.On("NewTransactionLiquidityPoolBatchInsertBuilder"). + Return(mockTransactionLiquidityPoolBatchInsertBuilder).Once() + + mockOperationLiquidityPoolBatchInsertBuilder := &history.MockOperationLiquidityPoolBatchInsertBuilder{} + mockOperationLiquidityPoolBatchInsertBuilder.On("Exec", ctx, mockSession).Return(nil).Once() + q.MockQHistoryLiquidityPools.On("NewOperationLiquidityPoolBatchInsertBuilder"). + Return(mockOperationLiquidityPoolBatchInsertBuilder).Once() + + return []interface{}{mockTradeBatchInsertBuilder, + mockTransactionsBatchInsertBuilder, + mockOperationsBatchInsertBuilder, + mockEffectBatchInsertBuilder, + mockTransactionsParticipantsBatchInsertBuilder, + mockOperationParticipantBatchInsertBuilder, + mockTransactionClaimableBalanceBatchInsertBuilder, + mockOperationClaimableBalanceBatchInsertBuilder, + mockTransactionLiquidityPoolBatchInsertBuilder, + mockOperationLiquidityPoolBatchInsertBuilder} +} + +func mockChangeProcessorBatchBuilders(q *mockDBQ, ctx context.Context, mockExec bool) []interface{} { + mockAccountSignersBatchInsertBuilder := &history.MockAccountSignersBatchInsertBuilder{} + if mockExec { + mockAccountSignersBatchInsertBuilder.On("Exec", ctx).Return(nil).Once() + } + q.MockQSigners.On("NewAccountSignersBatchInsertBuilder"). + Return(mockAccountSignersBatchInsertBuilder).Twice() + + mockAccountsBatchInsertBuilder := &history.MockAccountsBatchInsertBuilder{} + if mockExec { + mockAccountsBatchInsertBuilder.On("Exec", ctx).Return(nil).Once() + } + q.MockQAccounts.On("NewAccountsBatchInsertBuilder"). + Return(mockAccountsBatchInsertBuilder).Twice() + + mockClaimableBalanceClaimantBatchInsertBuilder := &history.MockClaimableBalanceClaimantBatchInsertBuilder{} + if mockExec { + mockClaimableBalanceClaimantBatchInsertBuilder.On("Exec", ctx). + Return(nil).Once() + } + q.MockQClaimableBalances.On("NewClaimableBalanceClaimantBatchInsertBuilder"). + Return(mockClaimableBalanceClaimantBatchInsertBuilder).Twice() + + mockClaimableBalanceBatchInsertBuilder := &history.MockClaimableBalanceBatchInsertBuilder{} + if mockExec { + mockClaimableBalanceBatchInsertBuilder.On("Exec", ctx).Return(nil).Once() + } + q.MockQClaimableBalances.On("NewClaimableBalanceBatchInsertBuilder"). + Return(mockClaimableBalanceBatchInsertBuilder).Twice() + + mockOfferBatchInsertBuilder := &history.MockOffersBatchInsertBuilder{} + if mockExec { + mockOfferBatchInsertBuilder.On("Exec", ctx).Return(nil).Once() + } + q.MockQOffers.On("NewOffersBatchInsertBuilder"). + Return(mockOfferBatchInsertBuilder).Twice() + + mockAccountDataBatchInsertBuilder := &history.MockAccountDataBatchInsertBuilder{} + if mockExec { + mockAccountDataBatchInsertBuilder.On("Exec", ctx).Return(nil).Once() + } + q.MockQData.On("NewAccountDataBatchInsertBuilder"). + Return(mockAccountDataBatchInsertBuilder).Twice() + + mockTrustLinesBatchInsertBuilder := &history.MockTrustLinesBatchInsertBuilder{} + if mockExec { + mockTrustLinesBatchInsertBuilder.On("Exec", ctx).Return(nil).Once() + } + q.MockQTrustLines.On("NewTrustLinesBatchInsertBuilder"). + Return(mockTrustLinesBatchInsertBuilder) + + return []interface{}{mockAccountSignersBatchInsertBuilder, + mockAccountsBatchInsertBuilder, + mockClaimableBalanceBatchInsertBuilder, + mockClaimableBalanceClaimantBatchInsertBuilder, + mockOfferBatchInsertBuilder, + mockAccountDataBatchInsertBuilder, + mockTrustLinesBatchInsertBuilder, + } +} diff --git a/services/horizon/internal/ingest/processors/account_data_processor.go b/services/horizon/internal/ingest/processors/account_data_processor.go index dfdbecb43e..f774700fbd 100644 --- a/services/horizon/internal/ingest/processors/account_data_processor.go +++ b/services/horizon/internal/ingest/processors/account_data_processor.go @@ -12,7 +12,8 @@ import ( type AccountDataProcessor struct { dataQ history.QData - cache *ingest.ChangeCompactor + cache *ingest.ChangeCompactor + batchInsertBuilder history.AccountDataBatchInsertBuilder } func NewAccountDataProcessor(dataQ history.QData) *AccountDataProcessor { @@ -23,6 +24,7 @@ func NewAccountDataProcessor(dataQ history.QData) *AccountDataProcessor { func (p *AccountDataProcessor) reset() { p.cache = ingest.NewChangeCompactor() + p.batchInsertBuilder = p.dataQ.NewAccountDataBatchInsertBuilder() } func (p *AccountDataProcessor) ProcessChange(ctx context.Context, change ingest.Change) error { @@ -41,13 +43,13 @@ func (p *AccountDataProcessor) ProcessChange(ctx context.Context, change ingest. if err != nil { return errors.Wrap(err, "error in Commit") } - p.reset() } return nil } func (p *AccountDataProcessor) Commit(ctx context.Context) error { + defer p.reset() var ( datasToUpsert []history.Data datasToDelete []history.AccountDataKey @@ -57,7 +59,10 @@ func (p *AccountDataProcessor) Commit(ctx context.Context) error { switch { case change.Pre == nil && change.Post != nil: // Created - datasToUpsert = append(datasToUpsert, p.ledgerEntryToRow(change.Post)) + err := p.batchInsertBuilder.Add(p.ledgerEntryToRow(change.Post)) + if err != nil { + return errors.Wrap(err, "Error adding to AccountDataBatchInsertBuilder") + } case change.Pre != nil && change.Post == nil: // Removed data := change.Pre.Data.MustData() @@ -72,6 +77,11 @@ func (p *AccountDataProcessor) Commit(ctx context.Context) error { } } + err := p.batchInsertBuilder.Exec(ctx) + if err != nil { + return errors.Wrap(err, "Error executing AccountDataBatchInsertBuilder") + } + if len(datasToUpsert) > 0 { if err := p.dataQ.UpsertAccountData(ctx, datasToUpsert); err != nil { return errors.Wrap(err, "error executing upsert") diff --git a/services/horizon/internal/ingest/processors/accounts_data_processor_test.go b/services/horizon/internal/ingest/processors/accounts_data_processor_test.go index 86ff1e13de..273cfcca4b 100644 --- a/services/horizon/internal/ingest/processors/accounts_data_processor_test.go +++ b/services/horizon/internal/ingest/processors/accounts_data_processor_test.go @@ -18,15 +18,21 @@ func TestAccountsDataProcessorTestSuiteState(t *testing.T) { type AccountsDataProcessorTestSuiteState struct { suite.Suite - ctx context.Context - processor *AccountDataProcessor - mockQ *history.MockQData + ctx context.Context + processor *AccountDataProcessor + mockQ *history.MockQData + mockAccountDataBatchInsertBuilder *history.MockAccountDataBatchInsertBuilder } func (s *AccountsDataProcessorTestSuiteState) SetupTest() { s.ctx = context.Background() s.mockQ = &history.MockQData{} + s.mockAccountDataBatchInsertBuilder = &history.MockAccountDataBatchInsertBuilder{} + s.mockQ.On("NewAccountDataBatchInsertBuilder"). + Return(s.mockAccountDataBatchInsertBuilder) + s.mockAccountDataBatchInsertBuilder.On("Exec", s.ctx).Return(nil) + s.processor = NewAccountDataProcessor(s.mockQ) } @@ -60,7 +66,7 @@ func (s *AccountsDataProcessorTestSuiteState) TestCreatesAccounts() { Value: history.AccountDataValue(data.DataValue), LastModifiedLedger: uint32(entry.LastModifiedLedgerSeq), } - s.mockQ.On("UpsertAccountData", s.ctx, []history.Data{historyData}).Return(nil).Once() + s.mockAccountDataBatchInsertBuilder.On("Add", historyData).Return(nil).Once() err := s.processor.ProcessChange(s.ctx, ingest.Change{ Type: xdr.LedgerEntryTypeData, @@ -76,15 +82,21 @@ func TestAccountsDataProcessorTestSuiteLedger(t *testing.T) { type AccountsDataProcessorTestSuiteLedger struct { suite.Suite - ctx context.Context - processor *AccountDataProcessor - mockQ *history.MockQData + ctx context.Context + processor *AccountDataProcessor + mockQ *history.MockQData + mockAccountDataBatchInsertBuilder *history.MockAccountDataBatchInsertBuilder } func (s *AccountsDataProcessorTestSuiteLedger) SetupTest() { s.ctx = context.Background() s.mockQ = &history.MockQData{} + s.mockAccountDataBatchInsertBuilder = &history.MockAccountDataBatchInsertBuilder{} + s.mockQ.On("NewAccountDataBatchInsertBuilder"). + Return(s.mockAccountDataBatchInsertBuilder) + s.mockAccountDataBatchInsertBuilder.On("Exec", s.ctx).Return(nil) + s.processor = NewAccountDataProcessor(s.mockQ) } @@ -152,7 +164,7 @@ func (s *AccountsDataProcessorTestSuiteLedger) TestNewAccountData() { Value: history.AccountDataValue(updatedData.DataValue), LastModifiedLedger: uint32(updatedEntry.LastModifiedLedgerSeq), } - s.mockQ.On("UpsertAccountData", s.ctx, []history.Data{historyData}).Return(nil).Once() + s.mockAccountDataBatchInsertBuilder.On("Add", historyData).Return(nil).Once() } func (s *AccountsDataProcessorTestSuiteLedger) TestUpdateAccountData() { @@ -196,6 +208,7 @@ func (s *AccountsDataProcessorTestSuiteLedger) TestUpdateAccountData() { Value: history.AccountDataValue(updatedData.DataValue), LastModifiedLedger: uint32(updatedEntry.LastModifiedLedgerSeq), } + s.mockAccountDataBatchInsertBuilder.On("Add", historyData).Return(nil).Once() s.mockQ.On("UpsertAccountData", s.ctx, []history.Data{historyData}).Return(nil).Once() } diff --git a/services/horizon/internal/ingest/processors/accounts_processor.go b/services/horizon/internal/ingest/processors/accounts_processor.go index 8130175ab6..681b7d3847 100644 --- a/services/horizon/internal/ingest/processors/accounts_processor.go +++ b/services/horizon/internal/ingest/processors/accounts_processor.go @@ -13,7 +13,8 @@ import ( type AccountsProcessor struct { accountsQ history.QAccounts - cache *ingest.ChangeCompactor + cache *ingest.ChangeCompactor + batchInsertBuilder history.AccountsBatchInsertBuilder } func NewAccountsProcessor(accountsQ history.QAccounts) *AccountsProcessor { @@ -24,6 +25,7 @@ func NewAccountsProcessor(accountsQ history.QAccounts) *AccountsProcessor { func (p *AccountsProcessor) reset() { p.cache = ingest.NewChangeCompactor() + p.batchInsertBuilder = p.accountsQ.NewAccountsBatchInsertBuilder() } func (p *AccountsProcessor) ProcessChange(ctx context.Context, change ingest.Change) error { @@ -41,13 +43,14 @@ func (p *AccountsProcessor) ProcessChange(ctx context.Context, change ingest.Cha if err != nil { return errors.Wrap(err, "error in Commit") } - p.reset() } return nil } func (p *AccountsProcessor) Commit(ctx context.Context) error { + defer p.reset() + batchUpsertAccounts := []history.AccountEntry{} removeBatch := []string{} @@ -63,8 +66,15 @@ func (p *AccountsProcessor) Commit(ctx context.Context) error { } switch { - case change.Post != nil: - // Created and updated + case change.Pre == nil && change.Post != nil: + // Created + row := p.ledgerEntryToRow(*change.Post) + err := p.batchInsertBuilder.Add(row) + if err != nil { + return errors.Wrap(err, "Error adding to AccountsBatchInsertBuilder") + } + case change.Pre != nil && change.Post != nil: + // Updated row := p.ledgerEntryToRow(*change.Post) batchUpsertAccounts = append(batchUpsertAccounts, row) case change.Pre != nil && change.Post == nil: @@ -77,6 +87,11 @@ func (p *AccountsProcessor) Commit(ctx context.Context) error { } } + err := p.batchInsertBuilder.Exec(ctx) + if err != nil { + return errors.Wrap(err, "Error executing AccountsBatchInsertBuilder") + } + // Upsert accounts if len(batchUpsertAccounts) > 0 { err := p.accountsQ.UpsertAccounts(ctx, batchUpsertAccounts) diff --git a/services/horizon/internal/ingest/processors/accounts_processor_test.go b/services/horizon/internal/ingest/processors/accounts_processor_test.go index 9b9c98d7b5..26f6af3487 100644 --- a/services/horizon/internal/ingest/processors/accounts_processor_test.go +++ b/services/horizon/internal/ingest/processors/accounts_processor_test.go @@ -19,15 +19,20 @@ func TestAccountsProcessorTestSuiteState(t *testing.T) { type AccountsProcessorTestSuiteState struct { suite.Suite - ctx context.Context - processor *AccountsProcessor - mockQ *history.MockQAccounts + ctx context.Context + processor *AccountsProcessor + mockQ *history.MockQAccounts + mockAccountsBatchInsertBuilder *history.MockAccountsBatchInsertBuilder } func (s *AccountsProcessorTestSuiteState) SetupTest() { s.ctx = context.Background() s.mockQ = &history.MockQAccounts{} + s.mockAccountsBatchInsertBuilder = &history.MockAccountsBatchInsertBuilder{} + s.mockQ.On("NewAccountsBatchInsertBuilder").Return(s.mockAccountsBatchInsertBuilder).Twice() + s.mockAccountsBatchInsertBuilder.On("Exec", s.ctx).Return(nil).Once() + s.processor = NewAccountsProcessor(s.mockQ) } @@ -42,19 +47,14 @@ func (s *AccountsProcessorTestSuiteState) TestNoEntries() { func (s *AccountsProcessorTestSuiteState) TestCreatesAccounts() { // We use LedgerEntryChangesCache so all changes are squashed - s.mockQ.On( - "UpsertAccounts", s.ctx, - []history.AccountEntry{ - { - LastModifiedLedger: 123, - AccountID: "GC3C4AKRBQLHOJ45U4XG35ESVWRDECWO5XLDGYADO6DPR3L7KIDVUMML", - MasterWeight: 1, - ThresholdLow: 1, - ThresholdMedium: 1, - ThresholdHigh: 1, - }, - }, - ).Return(nil).Once() + s.mockAccountsBatchInsertBuilder.On("Add", history.AccountEntry{ + LastModifiedLedger: 123, + AccountID: "GC3C4AKRBQLHOJ45U4XG35ESVWRDECWO5XLDGYADO6DPR3L7KIDVUMML", + MasterWeight: 1, + ThresholdLow: 1, + ThresholdMedium: 1, + ThresholdHigh: 1, + }).Return(nil).Once() err := s.processor.ProcessChange(s.ctx, ingest.Change{ Type: xdr.LedgerEntryTypeAccount, @@ -79,15 +79,20 @@ func TestAccountsProcessorTestSuiteLedger(t *testing.T) { type AccountsProcessorTestSuiteLedger struct { suite.Suite - ctx context.Context - processor *AccountsProcessor - mockQ *history.MockQAccounts + ctx context.Context + processor *AccountsProcessor + mockQ *history.MockQAccounts + mockAccountsBatchInsertBuilder *history.MockAccountsBatchInsertBuilder } func (s *AccountsProcessorTestSuiteLedger) SetupTest() { s.ctx = context.Background() s.mockQ = &history.MockQAccounts{} + s.mockAccountsBatchInsertBuilder = &history.MockAccountsBatchInsertBuilder{} + s.mockQ.On("NewAccountsBatchInsertBuilder").Return(s.mockAccountsBatchInsertBuilder).Twice() + s.mockAccountsBatchInsertBuilder.On("Exec", s.ctx).Return(nil).Once() + s.processor = NewAccountsProcessor(s.mockQ) } @@ -146,21 +151,15 @@ func (s *AccountsProcessorTestSuiteLedger) TestNewAccount() { s.Assert().NoError(err) // We use LedgerEntryChangesCache so all changes are squashed - s.mockQ.On( - "UpsertAccounts", - s.ctx, - []history.AccountEntry{ - { - AccountID: "GC3C4AKRBQLHOJ45U4XG35ESVWRDECWO5XLDGYADO6DPR3L7KIDVUMML", - MasterWeight: 0, - ThresholdLow: 1, - ThresholdMedium: 2, - ThresholdHigh: 3, - HomeDomain: "stellar.org", - LastModifiedLedger: uint32(123), - }, - }, - ).Return(nil).Once() + s.mockAccountsBatchInsertBuilder.On("Add", history.AccountEntry{ + AccountID: "GC3C4AKRBQLHOJ45U4XG35ESVWRDECWO5XLDGYADO6DPR3L7KIDVUMML", + MasterWeight: 0, + ThresholdLow: 1, + ThresholdMedium: 2, + ThresholdHigh: 3, + HomeDomain: "stellar.org", + LastModifiedLedger: uint32(123), + }).Return(nil).Once() } func (s *AccountsProcessorTestSuiteLedger) TestNewAccountUpgrade() { @@ -235,23 +234,17 @@ func (s *AccountsProcessorTestSuiteLedger) TestNewAccountUpgrade() { s.Assert().NoError(err) // We use LedgerEntryChangesCache so all changes are squashed - s.mockQ.On( - "UpsertAccounts", - s.ctx, - []history.AccountEntry{ - { - AccountID: "GC3C4AKRBQLHOJ45U4XG35ESVWRDECWO5XLDGYADO6DPR3L7KIDVUMML", - SequenceLedger: zero.IntFrom(2346), - SequenceTime: zero.IntFrom(1647265534), - MasterWeight: 0, - ThresholdLow: 1, - ThresholdMedium: 2, - ThresholdHigh: 3, - HomeDomain: "stellar.org", - LastModifiedLedger: uint32(123), - }, - }, - ).Return(nil).Once() + s.mockAccountsBatchInsertBuilder.On("Add", history.AccountEntry{ + AccountID: "GC3C4AKRBQLHOJ45U4XG35ESVWRDECWO5XLDGYADO6DPR3L7KIDVUMML", + SequenceLedger: zero.IntFrom(2346), + SequenceTime: zero.IntFrom(1647265534), + MasterWeight: 0, + ThresholdLow: 1, + ThresholdMedium: 2, + ThresholdHigh: 3, + HomeDomain: "stellar.org", + LastModifiedLedger: uint32(123), + }).Return(nil).Once() } func (s *AccountsProcessorTestSuiteLedger) TestRemoveAccount() { @@ -322,23 +315,17 @@ func (s *AccountsProcessorTestSuiteLedger) TestProcessUpgradeChange() { }) s.Assert().NoError(err) - s.mockQ.On( - "UpsertAccounts", - s.ctx, - []history.AccountEntry{ - { - LastModifiedLedger: uint32(lastModifiedLedgerSeq) + 1, - AccountID: "GC3C4AKRBQLHOJ45U4XG35ESVWRDECWO5XLDGYADO6DPR3L7KIDVUMML", - SequenceTime: zero.IntFrom(0), - SequenceLedger: zero.IntFrom(0), - MasterWeight: 0, - ThresholdLow: 1, - ThresholdMedium: 2, - ThresholdHigh: 3, - HomeDomain: "stellar.org", - }, - }, - ).Return(nil).Once() + s.mockAccountsBatchInsertBuilder.On("Add", history.AccountEntry{ + LastModifiedLedger: uint32(lastModifiedLedgerSeq) + 1, + AccountID: "GC3C4AKRBQLHOJ45U4XG35ESVWRDECWO5XLDGYADO6DPR3L7KIDVUMML", + SequenceTime: zero.IntFrom(0), + SequenceLedger: zero.IntFrom(0), + MasterWeight: 0, + ThresholdLow: 1, + ThresholdMedium: 2, + ThresholdHigh: 3, + HomeDomain: "stellar.org", + }).Return(nil).Once() } func (s *AccountsProcessorTestSuiteLedger) TestFeeProcessedBeforeEverythingElse() { diff --git a/services/horizon/internal/ingest/processors/asset_stats_processor.go b/services/horizon/internal/ingest/processors/asset_stats_processor.go index 098167bb5b..c3da42b730 100644 --- a/services/horizon/internal/ingest/processors/asset_stats_processor.go +++ b/services/horizon/internal/ingest/processors/asset_stats_processor.go @@ -3,6 +3,9 @@ package processors import ( "context" "database/sql" + "encoding/hex" + "fmt" + "math/big" "github.com/stellar/go/ingest" "github.com/stellar/go/services/horizon/internal/db2/history" @@ -11,109 +14,329 @@ import ( ) type AssetStatsProcessor struct { - assetStatsQ history.QAssetStats - - cache *ingest.ChangeCompactor - assetStatSet AssetStatSet - useLedgerEntryCache bool + assetStatsQ history.QAssetStats + cache *ingest.ChangeCompactor + currentLedger uint32 + removedExpirationEntries map[xdr.Hash]uint32 + createdExpirationEntries map[xdr.Hash]uint32 + updatedExpirationEntries map[xdr.Hash][2]uint32 + ingestFromHistoryArchive bool + networkPassphrase string } // NewAssetStatsProcessor constructs a new AssetStatsProcessor instance. -// If useLedgerEntryCache is false we don't use ledger cache and we just -// add trust lines to assetStatSet, then we insert all the stats in one -// insert query. This is done to make history buckets processing faster -// (batch inserting). func NewAssetStatsProcessor( assetStatsQ history.QAssetStats, - useLedgerEntryCache bool, + networkPassphrase string, + ingestFromHistoryArchive bool, + currentLedger uint32, ) *AssetStatsProcessor { p := &AssetStatsProcessor{ - assetStatsQ: assetStatsQ, - useLedgerEntryCache: useLedgerEntryCache, + currentLedger: currentLedger, + assetStatsQ: assetStatsQ, + ingestFromHistoryArchive: ingestFromHistoryArchive, + networkPassphrase: networkPassphrase, + cache: ingest.NewChangeCompactor(), + removedExpirationEntries: map[xdr.Hash]uint32{}, + createdExpirationEntries: map[xdr.Hash]uint32{}, + updatedExpirationEntries: map[xdr.Hash][2]uint32{}, } - p.reset() return p } -func (p *AssetStatsProcessor) reset() { - p.cache = ingest.NewChangeCompactor() - p.assetStatSet = AssetStatSet{} -} - func (p *AssetStatsProcessor) ProcessChange(ctx context.Context, change ingest.Change) error { if change.Type != xdr.LedgerEntryTypeLiquidityPool && change.Type != xdr.LedgerEntryTypeClaimableBalance && - change.Type != xdr.LedgerEntryTypeTrustline { + change.Type != xdr.LedgerEntryTypeTrustline && + change.Type != xdr.LedgerEntryTypeContractData && + change.Type != xdr.LedgerEntryTypeTtl { return nil } - if p.useLedgerEntryCache { - return p.addToCache(ctx, change) - } - if change.Pre != nil || change.Post == nil { - return errors.New("AssetStatsProcessor is in insert only mode") - } - - switch change.Type { - case xdr.LedgerEntryTypeLiquidityPool: - return p.assetStatSet.AddLiquidityPool(change) - case xdr.LedgerEntryTypeClaimableBalance: - return p.assetStatSet.AddClaimableBalance(change) - case xdr.LedgerEntryTypeTrustline: - return p.assetStatSet.AddTrustline(change) - default: - return nil + // only ingest contract data entries which could be relevant to + // asset stats + if change.Type == xdr.LedgerEntryTypeContractData { + ledgerEntry := change.Post + if ledgerEntry == nil { + ledgerEntry = change.Pre + } + asset := AssetFromContractData(*ledgerEntry, p.networkPassphrase) + _, _, balanceFound := ContractBalanceFromContractData(*ledgerEntry, p.networkPassphrase) + if asset == nil && !balanceFound { + return nil + } } -} - -func (p *AssetStatsProcessor) addToCache(ctx context.Context, change ingest.Change) error { - err := p.cache.AddChange(change) - if err != nil { + if err := p.cache.AddChange(change); err != nil { return errors.Wrap(err, "error adding to ledgerCache") } + return nil +} - if p.cache.Size() > maxBatchSize { - err = p.Commit(ctx) - if err != nil { - return errors.Wrap(err, "error in Commit") +func (p *AssetStatsProcessor) addExpirationChange(change ingest.Change) error { + switch { + case change.Pre == nil && change.Post != nil: // created + post := change.Post.Data.MustTtl() + p.createdExpirationEntries[post.KeyHash] = uint32(post.LiveUntilLedgerSeq) + case change.Pre != nil && change.Post == nil: // removed + pre := change.Pre.Data.MustTtl() + p.removedExpirationEntries[pre.KeyHash] = uint32(pre.LiveUntilLedgerSeq) + case change.Pre != nil && change.Post != nil: // updated + pre := change.Pre.Data.MustTtl() + post := change.Post.Data.MustTtl() + // it's unclear if core could emit a ledger entry change where the + // expiration ledger remains the same + if pre.LiveUntilLedgerSeq == post.LiveUntilLedgerSeq { + return nil + } + // but we expect that the expiration ledger will never decrease + if pre.LiveUntilLedgerSeq > post.LiveUntilLedgerSeq { + return errors.Errorf( + "unexpected change in expiration ledger Pre: %v Post: %v", + pre.LiveUntilLedgerSeq, + post.LiveUntilLedgerSeq, + ) + } + // also the new expiration ledger must always be greater than or equal + // to the current ledger + if uint32(post.LiveUntilLedgerSeq) < p.currentLedger { + return errors.Errorf( + "post expiration ledger is less than current ledger."+ + " Pre: %v Post: %v current ledger: %v", + pre.LiveUntilLedgerSeq, + post.LiveUntilLedgerSeq, + p.currentLedger, + ) } - p.reset() + p.updatedExpirationEntries[pre.KeyHash] = [2]uint32{ + uint32(pre.LiveUntilLedgerSeq), + uint32(post.LiveUntilLedgerSeq), + } + default: + return errors.Errorf("unexpected change Pre: %v Post: %v", change.Pre, change.Post) } return nil } func (p *AssetStatsProcessor) Commit(ctx context.Context) error { - if !p.useLedgerEntryCache { - assetStatsDeltas := p.assetStatSet.All() - if len(assetStatsDeltas) == 0 { - return nil - } - return p.assetStatsQ.InsertAssetStats(ctx, assetStatsDeltas, maxBatchSize) - } + assetStatSet := NewAssetStatSet() changes := p.cache.GetChanges() + var contractDataChanges []ingest.Change for _, change := range changes { var err error switch change.Type { case xdr.LedgerEntryTypeLiquidityPool: - err = p.assetStatSet.AddLiquidityPool(change) + err = assetStatSet.AddLiquidityPool(change) case xdr.LedgerEntryTypeClaimableBalance: - err = p.assetStatSet.AddClaimableBalance(change) + err = assetStatSet.AddClaimableBalance(change) case xdr.LedgerEntryTypeTrustline: - err = p.assetStatSet.AddTrustline(change) + err = assetStatSet.AddTrustline(change) + case xdr.LedgerEntryTypeContractData: + contractDataChanges = append(contractDataChanges, change) + case xdr.LedgerEntryTypeTtl: + err = p.addExpirationChange(change) default: return errors.Errorf("Change type %v is unexpected", change.Type) } - if err != nil { return errors.Wrap(err, "Error adjusting asset stat") } } - assetStatsDeltas := p.assetStatSet.All() + contractAssetStatSet := NewContractAssetStatSet( + p.assetStatsQ, + p.networkPassphrase, + p.removedExpirationEntries, + p.createdExpirationEntries, + p.updatedExpirationEntries, + p.currentLedger, + ) + for _, change := range contractDataChanges { + if err := contractAssetStatSet.AddContractData(ctx, change); err != nil { + return errors.Wrap(err, "Error ingesting contract data") + } + } + + return p.updateDB(ctx, assetStatSet, contractAssetStatSet) +} + +func (p *AssetStatsProcessor) updateDB( + ctx context.Context, + assetStatSet AssetStatSet, + contractAssetStatSet *ContractAssetStatSet, +) error { + if p.ingestFromHistoryArchive { + // When ingesting from the history archives we can take advantage of the fact + // that there are only created ledger entries. We don't need to execute any + // updates or removals on the asset stats tables. And we can also skip + // ingesting restored contract balances and expired contract balances. + assetStatsDeltas := assetStatSet.All() + if len(assetStatsDeltas) > 0 { + var err error + assetStatsDeltas, err = IncludeContractIDsInAssetStats( + p.networkPassphrase, + assetStatsDeltas, + contractAssetStatSet.contractToAsset, + ) + if err != nil { + return errors.Wrap(err, "Error extracting asset stat rows") + } + if err := p.assetStatsQ.InsertAssetStats(ctx, assetStatsDeltas); err != nil { + return errors.Wrap(err, "Error inserting asset stats") + } + } + + if rows := contractAssetStatSet.GetContractStats(); len(rows) > 0 { + if err := p.assetStatsQ.InsertContractAssetStats(ctx, rows); err != nil { + return errors.Wrap(err, "Error inserting asset contract stats") + } + } + + if len(contractAssetStatSet.createdBalances) > 0 { + if err := p.assetStatsQ.InsertContractAssetBalances(ctx, contractAssetStatSet.createdBalances); err != nil { + return errors.Wrap(err, "Error inserting asset contract stats") + } + } + return nil + } + + assetStatsDeltas := assetStatSet.All() + + if err := p.updateAssetStats(ctx, assetStatsDeltas, contractAssetStatSet.contractToAsset); err != nil { + return err + } + if err := p.updateContractIDs(ctx, contractAssetStatSet.contractToAsset); err != nil { + return err + } + + if err := p.assetStatsQ.RemoveContractAssetBalances(ctx, contractAssetStatSet.removedBalances); err != nil { + return errors.Wrap(err, "Error removing contract asset balances") + } + + if err := p.updateContractAssetBalanceAmounts(ctx, contractAssetStatSet.updatedBalances); err != nil { + return err + } + + if err := p.assetStatsQ.InsertContractAssetBalances(ctx, contractAssetStatSet.createdBalances); err != nil { + return errors.Wrap(err, "Error inserting contract asset balances") + } + + if err := contractAssetStatSet.ingestRestoredBalances(ctx); err != nil { + return err + } + + if err := p.updateContractAssetBalanceExpirations(ctx); err != nil { + return err + } + + if err := contractAssetStatSet.ingestExpiredBalances(ctx); err != nil { + return err + } + + return p.updateContractAssetStats(ctx, contractAssetStatSet.contractAssetStats) +} + +func (p *AssetStatsProcessor) updateContractAssetBalanceAmounts(ctx context.Context, updatedBalances map[xdr.Hash]*big.Int) error { + keys := make([]xdr.Hash, 0, len(updatedBalances)) + amounts := make([]string, 0, len(updatedBalances)) + for key, amount := range updatedBalances { + keys = append(keys, key) + amounts = append(amounts, amount.String()) + } + if err := p.assetStatsQ.UpdateContractAssetBalanceAmounts(ctx, keys, amounts); err != nil { + return errors.Wrap(err, "Error updating contract asset balance amounts") + } + return nil +} + +func (p *AssetStatsProcessor) updateContractAssetBalanceExpirations(ctx context.Context) error { + keys := make([]xdr.Hash, 0, len(p.updatedExpirationEntries)) + expirationLedgers := make([]uint32, 0, len(p.updatedExpirationEntries)) + for key, update := range p.updatedExpirationEntries { + keys = append(keys, key) + expirationLedgers = append(expirationLedgers, update[1]) + } + if err := p.assetStatsQ.UpdateContractAssetBalanceExpirations(ctx, keys, expirationLedgers); err != nil { + return errors.Wrap(err, "Error updating contract asset balance expirations") + } + return nil +} + +func IncludeContractIDsInAssetStats( + networkPassphrase string, + assetStatsDeltas []history.ExpAssetStat, + contractToAsset map[xdr.Hash]*xdr.Asset, +) ([]history.ExpAssetStat, error) { + included := map[xdr.Hash]bool{} + // modify the asset stat row to update the contract_id column whenever we encounter a + // contract data ledger entry with the Stellar asset metadata. + for i, assetStatDelta := range assetStatsDeltas { + // asset stats only supports non-native assets + asset := xdr.MustNewCreditAsset(assetStatDelta.AssetCode, assetStatDelta.AssetIssuer) + contractID, err := asset.ContractID(networkPassphrase) + if err != nil { + return nil, errors.Wrap(err, "cannot compute contract id for asset") + } + if asset, ok := contractToAsset[contractID]; ok && asset == nil { + return nil, ingest.NewStateError(fmt.Errorf( + "unexpected contract data removal in history archives: %s", + hex.EncodeToString(contractID[:]), + )) + } else if ok { + assetStatDelta.SetContractID(contractID) + included[contractID] = true + } + + assetStatsDeltas[i] = assetStatDelta + } + + // There is also a corner case where a Stellar Asset contract is initialized before there exists any + // trustlines / claimable balances for the Stellar Asset. In this case, when ingesting contract data + // ledger entries, there will be no existing asset stat row. We handle this case by inserting a row + // with zero stats just so we can populate the contract id. + for contractID, asset := range contractToAsset { + if included[contractID] { + continue + } + if asset == nil { + return nil, ingest.NewStateError(fmt.Errorf( + "unexpected contract data removal in history archives: %s", + hex.EncodeToString(contractID[:]), + )) + } + var assetType xdr.AssetType + var assetCode, assetIssuer string + asset.MustExtract(&assetType, &assetCode, &assetIssuer) + row := history.ExpAssetStat{ + AssetType: assetType, + AssetCode: assetCode, + AssetIssuer: assetIssuer, + Accounts: history.ExpAssetStatAccounts{}, + Balances: newAssetStatBalance().ConvertToHistoryObject(), + Amount: "0", + NumAccounts: 0, + } + row.SetContractID(contractID) + assetStatsDeltas = append(assetStatsDeltas, row) + } + + return assetStatsDeltas, nil +} + +func (p *AssetStatsProcessor) updateAssetStats( + ctx context.Context, + assetStatsDeltas []history.ExpAssetStat, + contractToAsset map[xdr.Hash]*xdr.Asset, +) error { for _, delta := range assetStatsDeltas { var rowsAffected int64 var stat history.ExpAssetStat var err error + // asset stats only supports non-native assets + asset := xdr.MustNewCreditAsset(delta.AssetCode, delta.AssetIssuer) + contractID, err := asset.ContractID(p.networkPassphrase) + if err != nil { + return errors.Wrap(err, "cannot compute contract id for asset") + } stat, err = p.assetStatsQ.GetAssetStat(ctx, delta.AssetType, @@ -124,6 +347,34 @@ func (p *AssetStatsProcessor) Commit(ctx context.Context) error { if !assetStatNotFound && err != nil { return errors.Wrap(err, "could not fetch asset stat from db") } + assetStatFound := !assetStatNotFound + if assetStatFound { + delta.ContractID = stat.ContractID + } + + if asset, ok := contractToAsset[contractID]; ok && asset == nil { + if assetStatFound && stat.ContractID == nil { + return ingest.NewStateError(errors.Errorf( + "row has no contract id to remove %s: %s %s %s", + hex.EncodeToString(contractID[:]), + stat.AssetType, + stat.AssetCode, + stat.AssetIssuer, + )) + } + delta.ContractID = nil + } else if ok { + if assetStatFound && stat.ContractID != nil { + return ingest.NewStateError(errors.Errorf( + "attempting to set contract id %s but row %s already has contract id set: %s", + hex.EncodeToString(contractID[:]), + asset.String(), + hex.EncodeToString((*stat.ContractID)[:]), + )) + } + delta.SetContractID(contractID) + } + delete(contractToAsset, contractID) if assetStatNotFound { // Safety checks @@ -172,19 +423,21 @@ func (p *AssetStatsProcessor) Commit(ctx context.Context) error { } } else { var statBalances assetStatBalances - if err = statBalances.Parse(&stat.Balances); err != nil { + if err = statBalances.Parse(stat.Balances); err != nil { return errors.Wrap(err, "Error parsing balances") } var deltaBalances assetStatBalances - if err = deltaBalances.Parse(&delta.Balances); err != nil { + if err = deltaBalances.Parse(delta.Balances); err != nil { return errors.Wrap(err, "Error parsing balances") } statBalances = statBalances.Add(deltaBalances) statAccounts := stat.Accounts.Add(delta.Accounts) - if statAccounts.IsZero() { + // only remove asset stat if the Metadata contract data ledger entry for the token contract + // has also been removed. + if statAccounts.IsZero() && delta.ContractID == nil { // Remove stats if !statBalances.IsZero() { return ingest.NewStateError(errors.Errorf( @@ -212,6 +465,7 @@ func (p *AssetStatsProcessor) Commit(ctx context.Context) error { Balances: statBalances.ConvertToHistoryObject(), Amount: statBalances.Authorized.String(), NumAccounts: statAccounts.Authorized, + ContractID: delta.ContractID, }) if err != nil { return errors.Wrap(err, "could not update asset stat") @@ -221,7 +475,7 @@ func (p *AssetStatsProcessor) Commit(ctx context.Context) error { if rowsAffected != 1 { return ingest.NewStateError(errors.Errorf( - "%d rows affected when adjusting asset stat for asset: %s %s %s", + "%d rows affected (expected exactly 1) when adjusting asset stat for asset: %s %s %s", rowsAffected, delta.AssetType, delta.AssetCode, @@ -229,6 +483,191 @@ func (p *AssetStatsProcessor) Commit(ctx context.Context) error { )) } } + return nil +} + +func (p *AssetStatsProcessor) updateContractIDs( + ctx context.Context, + contractToAsset map[xdr.Hash]*xdr.Asset, +) error { + for contractID, asset := range contractToAsset { + if err := p.updateContractID(ctx, contractID, asset); err != nil { + return err + } + } + return nil +} + +// updateContractID will update the asset stat row for the corresponding asset to either +// add or remove the given contract id +func (p *AssetStatsProcessor) updateContractID( + ctx context.Context, + contractID xdr.Hash, + asset *xdr.Asset, +) error { + var rowsAffected int64 + // asset is nil so we need to set the contract_id column to NULL + if asset == nil { + stat, err := p.assetStatsQ.GetAssetStatByContract(ctx, contractID) + if err == sql.ErrNoRows { + return ingest.NewStateError(errors.Errorf( + "row for asset with contract %s is missing", + hex.EncodeToString(contractID[:]), + )) + } + if err != nil { + return errors.Wrap(err, "error querying asset by contract id") + } + + if stat.Accounts.IsZero() { + if !stat.Balances.IsZero() { + return ingest.NewStateError(errors.Errorf( + "asset stat has 0 holders but non zero balance: %s", + hex.EncodeToString(contractID[:]), + )) + } + // the asset stat is empty so we can remove the row entirely + rowsAffected, err = p.assetStatsQ.RemoveAssetStat(ctx, + stat.AssetType, + stat.AssetCode, + stat.AssetIssuer, + ) + if err != nil { + return errors.Wrap(err, "could not remove asset stat") + } + } else { + // update the row to set the contract_id column to NULL + stat.ContractID = nil + rowsAffected, err = p.assetStatsQ.UpdateAssetStat(ctx, stat) + if err != nil { + return errors.Wrap(err, "could not update asset stat") + } + } + } else { // asset is non nil, so we need to populate the contract_id column + var assetType xdr.AssetType + var assetCode, assetIssuer string + asset.MustExtract(&assetType, &assetCode, &assetIssuer) + stat, err := p.assetStatsQ.GetAssetStat(ctx, assetType, assetCode, assetIssuer) + if err == sql.ErrNoRows { + // there is no asset stat for the given asset so we need to create a new row + row := history.ExpAssetStat{ + AssetType: assetType, + AssetCode: assetCode, + AssetIssuer: assetIssuer, + Accounts: history.ExpAssetStatAccounts{}, + Balances: newAssetStatBalance().ConvertToHistoryObject(), + Amount: "0", + NumAccounts: 0, + } + row.SetContractID(contractID) + + rowsAffected, err = p.assetStatsQ.InsertAssetStat(ctx, row) + if err != nil { + return errors.Wrap(err, "could not insert asset stat") + } + } else if err != nil { + return errors.Wrap(err, "error querying asset by asset code and issuer") + } else if dbContractID, ok := stat.GetContractID(); ok { + // the asset stat already has a column_id set which is unexpected (the column should be NULL) + return ingest.NewStateError(errors.Errorf( + "attempting to set contract id %s but row %s already has contract id set: %s", + hex.EncodeToString(contractID[:]), + asset.String(), + hex.EncodeToString(dbContractID[:]), + )) + } else { + // update the column_id column + stat.SetContractID(contractID) + rowsAffected, err = p.assetStatsQ.UpdateAssetStat(ctx, stat) + if err != nil { + return errors.Wrap(err, "could not update asset stat") + } + } + } + + if rowsAffected != 1 { + // assert that we have updated exactly one row + return ingest.NewStateError(errors.Errorf( + "%d rows affected (expected exactly 1) when adjusting asset stat for asset: %s", + rowsAffected, + asset.String(), + )) + } + return nil +} + +func (p *AssetStatsProcessor) addContractAssetStat(contractAssetStat assetContractStatValue, row *history.ContractAssetStatRow) error { + row.Stat.ActiveHolders += contractAssetStat.activeHolders + row.Stat.ArchivedHolders += contractAssetStat.archivedHolders + activeBalance, ok := new(big.Int).SetString(row.Stat.ActiveBalance, 10) + if !ok { + return errors.New("Error parsing: " + row.Stat.ActiveBalance) + } + row.Stat.ActiveBalance = activeBalance.Add(activeBalance, contractAssetStat.activeBalance).String() + archivedBalance, ok := new(big.Int).SetString(row.Stat.ArchivedBalance, 10) + if !ok { + return errors.New("Error parsing: " + row.Stat.ArchivedBalance) + } + row.Stat.ArchivedBalance = archivedBalance.Add(archivedBalance, contractAssetStat.archivedBalance).String() + return nil +} + +func (p *AssetStatsProcessor) updateContractAssetStats( + ctx context.Context, + contractAssetStats map[xdr.Hash]assetContractStatValue, +) error { + for contractID, contractAssetStat := range contractAssetStats { + if err := p.updateAssetContractStats(ctx, contractID, contractAssetStat); err != nil { + return err + } + } + return nil +} +// updateAssetContractStats will look up an asset contract stat by contract id and +// it will adjust the contract balance and holders based on assetContractStat +func (p *AssetStatsProcessor) updateAssetContractStats( + ctx context.Context, + contractID xdr.Hash, + assetContractStat assetContractStatValue, +) error { + var rowsAffected int64 + row, err := p.assetStatsQ.GetContractAssetStat(ctx, contractID[:]) + if err == sql.ErrNoRows { + rowsAffected, err = p.assetStatsQ.InsertContractAssetStat(ctx, assetContractStat.ConvertToHistoryObject()) + if err != nil { + return errors.Wrap(err, "error inserting asset contract stat") + } + } else if err != nil { + return errors.Wrap(err, "error querying asset by contract id") + } else { + if err = p.addContractAssetStat(assetContractStat, &row); err != nil { + return errors.Wrapf(err, "could not update asset stat with contract id %v with contract delta", contractID) + } + + if row.Stat == (history.ContractStat{ + ActiveBalance: "0", + ActiveHolders: 0, + ArchivedBalance: "0", + ArchivedHolders: 0, + }) { + rowsAffected, err = p.assetStatsQ.RemoveAssetContractStat(ctx, contractID[:]) + } else { + rowsAffected, err = p.assetStatsQ.UpdateContractAssetStat(ctx, row) + } + + if err != nil { + return errors.Wrap(err, "could not update asset stat") + } + } + + if rowsAffected != 1 { + // assert that we have updated exactly one row + return ingest.NewStateError(errors.Errorf( + "%d rows affected (expected exactly 1) when adjusting asset contract stat for contract: %s", + rowsAffected, + contractID, + )) + } return nil } diff --git a/services/horizon/internal/ingest/processors/asset_stats_processor_test.go b/services/horizon/internal/ingest/processors/asset_stats_processor_test.go index 409d83d489..a1fb68237c 100644 --- a/services/horizon/internal/ingest/processors/asset_stats_processor_test.go +++ b/services/horizon/internal/ingest/processors/asset_stats_processor_test.go @@ -3,13 +3,18 @@ package processors import ( + "bytes" "context" "database/sql" "testing" + "github.com/stretchr/testify/assert" + "github.com/stellar/go/ingest" "github.com/stellar/go/services/horizon/internal/db2/history" "github.com/stellar/go/xdr" + + "github.com/stretchr/testify/mock" "github.com/stretchr/testify/suite" ) @@ -27,7 +32,7 @@ type AssetStatsProcessorTestSuiteState struct { func (s *AssetStatsProcessorTestSuiteState) SetupTest() { s.ctx = context.Background() s.mockQ = &history.MockQAssetStats{} - s.processor = NewAssetStatsProcessor(s.mockQ, false) + s.processor = NewAssetStatsProcessor(s.mockQ, "", true, 123) } func (s *AssetStatsProcessorTestSuiteState) TearDownTest() { @@ -72,7 +77,7 @@ func (s *AssetStatsProcessorTestSuiteState) TestCreateTrustLine() { Amount: "0", NumAccounts: 1, }, - }, maxBatchSize).Return(nil).Once() + }).Return(nil).Once() } func (s *AssetStatsProcessorTestSuiteState) TestCreatePoolShareTrustLine() { @@ -139,7 +144,7 @@ func (s *AssetStatsProcessorTestSuiteState) TestCreateTrustLineWithClawback() { Amount: "0", NumAccounts: 1, }, - }, maxBatchSize).Return(nil).Once() + }).Return(nil).Once() } func (s *AssetStatsProcessorTestSuiteState) TestCreateTrustLineUnauthorized() { @@ -177,7 +182,7 @@ func (s *AssetStatsProcessorTestSuiteState) TestCreateTrustLineUnauthorized() { Amount: "0", NumAccounts: 0, }, - }, maxBatchSize).Return(nil).Once() + }).Return(nil).Once() } func TestAssetStatsProcessorTestSuiteLedger(t *testing.T) { @@ -195,7 +200,7 @@ func (s *AssetStatsProcessorTestSuiteLedger) SetupTest() { s.ctx = context.Background() s.mockQ = &history.MockQAssetStats{} - s.processor = NewAssetStatsProcessor(s.mockQ, true) + s.processor = NewAssetStatsProcessor(s.mockQ, "", false, 1235) } func (s *AssetStatsProcessorTestSuiteLedger) TearDownTest() { @@ -342,6 +347,17 @@ func (s *AssetStatsProcessorTestSuiteLedger) TestInsertClaimableBalance() { NumAccounts: 0, }).Return(int64(1), nil).Once() + s.mockQ.On("RemoveContractAssetBalances", s.ctx, []xdr.Hash(nil)). + Return(nil).Once() + s.mockQ.On("UpdateContractAssetBalanceAmounts", s.ctx, []xdr.Hash{}, []string{}). + Return(nil).Once() + s.mockQ.On("InsertContractAssetBalances", s.ctx, []history.ContractAssetBalance(nil)). + Return(nil).Once() + s.mockQ.On("UpdateContractAssetBalanceExpirations", s.ctx, []xdr.Hash{}, []uint32{}). + Return(nil).Once() + s.mockQ.On("GetContractAssetBalancesExpiringAt", s.ctx, uint32(1234)). + Return([]history.ContractAssetBalance{}, nil).Once() + s.Assert().NoError(s.processor.Commit(s.ctx)) } @@ -498,79 +514,68 @@ func (s *AssetStatsProcessorTestSuiteLedger) TestInsertTrustLine() { NumAccounts: 0, }).Return(int64(1), nil).Once() + s.mockQ.On("RemoveContractAssetBalances", s.ctx, []xdr.Hash(nil)). + Return(nil).Once() + s.mockQ.On("UpdateContractAssetBalanceAmounts", s.ctx, []xdr.Hash{}, []string{}). + Return(nil).Once() + s.mockQ.On("InsertContractAssetBalances", s.ctx, []history.ContractAssetBalance(nil)). + Return(nil).Once() + s.mockQ.On("UpdateContractAssetBalanceExpirations", s.ctx, []xdr.Hash{}, []uint32{}). + Return(nil).Once() + s.mockQ.On("GetContractAssetBalancesExpiringAt", s.ctx, uint32(1234)). + Return([]history.ContractAssetBalance{}, nil).Once() + s.Assert().NoError(s.processor.Commit(s.ctx)) } -func (s *AssetStatsProcessorTestSuiteLedger) TestInsertClaimableBalanceAndTrustlineAndLiquidityPool() { - liquidityPool := xdr.LiquidityPoolEntry{ - Body: xdr.LiquidityPoolEntryBody{ - Type: xdr.LiquidityPoolTypeLiquidityPoolConstantProduct, - ConstantProduct: &xdr.LiquidityPoolEntryConstantProduct{ - Params: xdr.LiquidityPoolConstantProductParameters{ - AssetA: xdr.MustNewCreditAsset("EUR", trustLineIssuer.Address()), - AssetB: xdr.MustNewNativeAsset(), - Fee: 20, - }, - ReserveA: 100, - ReserveB: 200, - TotalPoolShares: 1000, - PoolSharesTrustLineCount: 10, - }, - }, - } - - claimableBalance := xdr.ClaimableBalanceEntry{ - Asset: xdr.MustNewCreditAsset("EUR", trustLineIssuer.Address()), - Amount: 12, - BalanceId: xdr.ClaimableBalanceId{ - Type: 0, - V0: &xdr.Hash{1, 2, 3}, - }, - } - +func (s *AssetStatsProcessorTestSuiteLedger) TestInsertContractID() { + // add trust line trustLine := xdr.TrustLineEntry{ AccountId: xdr.MustAddress("GAOQJGUAB7NI7K7I62ORBXMN3J4SSWQUQ7FOEPSDJ322W2HMCNWPHXFB"), Asset: xdr.MustNewCreditAsset("EUR", trustLineIssuer.Address()).ToTrustLineAsset(), - Balance: 9, + Balance: 0, Flags: xdr.Uint32(xdr.TrustLineFlagsAuthorizedFlag), } - lastModifiedLedgerSeq := xdr.Uint32(1234) + eurID, err := trustLine.Asset.ToAsset().ContractID("") + s.Assert().NoError(err) + eurContractData, err := AssetToContractData(false, "EUR", trustLineIssuer.Address(), eurID) + s.Assert().NoError(err) - err := s.processor.ProcessChange(s.ctx, ingest.Change{ - Type: xdr.LedgerEntryTypeLiquidityPool, + usdID, err := xdr.MustNewCreditAsset("USD", trustLineIssuer.Address()).ContractID("") + s.Assert().NoError(err) + usdContractData, err := AssetToContractData(false, "USD", trustLineIssuer.Address(), usdID) + s.Assert().NoError(err) + + lastModifiedLedgerSeq := xdr.Uint32(1234) + err = s.processor.ProcessChange(s.ctx, ingest.Change{ + Type: xdr.LedgerEntryTypeTrustline, Pre: nil, Post: &xdr.LedgerEntry{ LastModifiedLedgerSeq: lastModifiedLedgerSeq, Data: xdr.LedgerEntryData{ - Type: xdr.LedgerEntryTypeLiquidityPool, - LiquidityPool: &liquidityPool, + Type: xdr.LedgerEntryTypeTrustline, + TrustLine: &trustLine, }, }, }) s.Assert().NoError(err) err = s.processor.ProcessChange(s.ctx, ingest.Change{ - Type: xdr.LedgerEntryTypeClaimableBalance, + Type: xdr.LedgerEntryTypeContractData, Pre: nil, Post: &xdr.LedgerEntry{ LastModifiedLedgerSeq: lastModifiedLedgerSeq, - Data: xdr.LedgerEntryData{ - Type: xdr.LedgerEntryTypeClaimableBalance, - ClaimableBalance: &claimableBalance, - }, + Data: eurContractData, }, }) s.Assert().NoError(err) err = s.processor.ProcessChange(s.ctx, ingest.Change{ - Type: xdr.LedgerEntryTypeTrustline, + Type: xdr.LedgerEntryTypeContractData, Pre: nil, Post: &xdr.LedgerEntry{ LastModifiedLedgerSeq: lastModifiedLedgerSeq, - Data: xdr.LedgerEntryData{ - Type: xdr.LedgerEntryTypeTrustline, - TrustLine: &trustLine, - }, + Data: usdContractData, }, }) s.Assert().NoError(err) @@ -580,119 +585,1131 @@ func (s *AssetStatsProcessorTestSuiteLedger) TestInsertClaimableBalanceAndTrustl "EUR", trustLineIssuer.Address(), ).Return(history.ExpAssetStat{}, sql.ErrNoRows).Once() - s.mockQ.On("InsertAssetStat", s.ctx, history.ExpAssetStat{ + eurAssetStat := history.ExpAssetStat{ AssetType: xdr.AssetTypeAssetTypeCreditAlphanum4, AssetIssuer: trustLineIssuer.Address(), AssetCode: "EUR", Accounts: history.ExpAssetStatAccounts{ - ClaimableBalances: 1, - Authorized: 1, - LiquidityPools: 1, + Authorized: 1, }, Balances: history.ExpAssetStatBalances{ - Authorized: "9", + Authorized: "0", AuthorizedToMaintainLiabilities: "0", Unauthorized: "0", - ClaimableBalances: "12", - LiquidityPools: "100", + ClaimableBalances: "0", + LiquidityPools: "0", }, - Amount: "9", + Amount: "0", NumAccounts: 1, - }).Return(int64(1), nil).Once() + } + eurAssetStat.SetContractID(eurID) + s.mockQ.On("InsertAssetStat", s.ctx, mock.MatchedBy(func(assetStat history.ExpAssetStat) bool { + return eurAssetStat.Equals(assetStat) + })).Return(int64(1), nil).Once() + + s.mockQ.On("GetAssetStat", s.ctx, + xdr.AssetTypeAssetTypeCreditAlphanum4, + "USD", + trustLineIssuer.Address(), + ).Return(history.ExpAssetStat{}, sql.ErrNoRows).Once() + + usdAssetStat := history.ExpAssetStat{ + AssetType: xdr.AssetTypeAssetTypeCreditAlphanum4, + AssetIssuer: trustLineIssuer.Address(), + AssetCode: "USD", + Accounts: history.ExpAssetStatAccounts{}, + Balances: history.ExpAssetStatBalances{ + Authorized: "0", + AuthorizedToMaintainLiabilities: "0", + Unauthorized: "0", + ClaimableBalances: "0", + LiquidityPools: "0", + }, + Amount: "0", + NumAccounts: 0, + } + usdAssetStat.SetContractID(usdID) + s.mockQ.On("InsertAssetStat", s.ctx, mock.MatchedBy(func(assetStat history.ExpAssetStat) bool { + return usdAssetStat.Equals(assetStat) + })).Return(int64(1), nil).Once() + + s.mockQ.On("RemoveContractAssetBalances", s.ctx, []xdr.Hash(nil)). + Return(nil).Once() + s.mockQ.On("UpdateContractAssetBalanceAmounts", s.ctx, []xdr.Hash{}, []string{}). + Return(nil).Once() + s.mockQ.On("InsertContractAssetBalances", s.ctx, []history.ContractAssetBalance(nil)). + Return(nil).Once() + s.mockQ.On("UpdateContractAssetBalanceExpirations", s.ctx, []xdr.Hash{}, []uint32{}). + Return(nil).Once() + s.mockQ.On("GetContractAssetBalancesExpiringAt", s.ctx, uint32(1234)). + Return([]history.ContractAssetBalance{}, nil).Once() s.Assert().NoError(s.processor.Commit(s.ctx)) } -func (s *AssetStatsProcessorTestSuiteLedger) TestUpdateTrustLine() { +func (s *AssetStatsProcessorTestSuiteLedger) TestInsertContractBalance() { + lastModifiedLedgerSeq := xdr.Uint32(1234) + usdID, err := xdr.MustNewCreditAsset("USD", trustLineIssuer.Address()).ContractID("") + s.Assert().NoError(err) + + s.Assert().NoError(s.processor.ProcessChange(s.ctx, ingest.Change{ + Type: xdr.LedgerEntryTypeContractData, + Post: &xdr.LedgerEntry{ + LastModifiedLedgerSeq: lastModifiedLedgerSeq, + Data: BalanceToContractData(usdID, [32]byte{1}, 200), + }, + })) + + keyHash := getKeyHashForBalance(s.T(), usdID, [32]byte{1}) + s.Assert().NoError(s.processor.ProcessChange(s.ctx, ingest.Change{ + Type: xdr.LedgerEntryTypeTtl, + Post: &xdr.LedgerEntry{ + LastModifiedLedgerSeq: lastModifiedLedgerSeq, + Data: xdr.LedgerEntryData{ + Type: xdr.LedgerEntryTypeTtl, + Ttl: &xdr.TtlEntry{ + KeyHash: keyHash, + LiveUntilLedgerSeq: 2234, + }, + }, + }, + })) + + s.mockQ.On("GetContractAssetStat", s.ctx, usdID[:]). + Return(history.ContractAssetStatRow{}, sql.ErrNoRows).Once() + + usdAssetContractStat := history.ContractAssetStatRow{ + ContractID: usdID[:], + Stat: history.ContractStat{ + ActiveBalance: "200", + ActiveHolders: 1, + ArchivedBalance: "0", + ArchivedHolders: 0, + }, + } + s.mockQ.On("InsertContractAssetStat", s.ctx, mock.MatchedBy(func(row history.ContractAssetStatRow) bool { + return bytes.Equal(usdID[:], row.ContractID) && + usdAssetContractStat.Stat == row.Stat + })).Return(int64(1), nil).Once() + + s.mockQ.On("RemoveContractAssetBalances", s.ctx, []xdr.Hash(nil)). + Return(nil).Once() + s.mockQ.On("UpdateContractAssetBalanceAmounts", s.ctx, []xdr.Hash{}, []string{}). + Return(nil).Once() + s.mockQ.On("InsertContractAssetBalances", s.ctx, []history.ContractAssetBalance{ + { + KeyHash: keyHash[:], + ContractID: usdID[:], + Amount: "200", + ExpirationLedger: 2234, + }, + }).Return(nil).Once() + s.mockQ.On("UpdateContractAssetBalanceExpirations", s.ctx, []xdr.Hash{}, []uint32{}). + Return(nil).Once() + s.mockQ.On("GetContractAssetBalancesExpiringAt", s.ctx, uint32(1234)). + Return([]history.ContractAssetBalance{}, nil).Once() + + s.Assert().NoError(s.processor.Commit(s.ctx)) +} + +func (s *AssetStatsProcessorTestSuiteLedger) TestUpdateContractBalance() { + lastModifiedLedgerSeq := xdr.Uint32(1234) + usdID, err := xdr.MustNewCreditAsset("USD", trustLineIssuer.Address()).ContractID("") + s.Assert().NoError(err) + + keyHash := getKeyHashForBalance(s.T(), usdID, [32]byte{1}) + s.Assert().NoError(s.processor.ProcessChange(s.ctx, ingest.Change{ + Type: xdr.LedgerEntryTypeContractData, + Pre: &xdr.LedgerEntry{ + LastModifiedLedgerSeq: lastModifiedLedgerSeq, + Data: BalanceToContractData(usdID, [32]byte{1}, 100), + }, + Post: &xdr.LedgerEntry{ + LastModifiedLedgerSeq: lastModifiedLedgerSeq, + Data: BalanceToContractData(usdID, [32]byte{1}, 300), + }, + })) + + usdAssetContractStat := history.ContractAssetStatRow{ + ContractID: usdID[:], + Stat: history.ContractStat{ + ActiveBalance: "150", + ActiveHolders: 1, + ArchivedBalance: "20", + ArchivedHolders: 2, + }, + } + s.mockQ.On("GetContractAssetStat", s.ctx, usdID[:]). + Return(usdAssetContractStat, nil).Once() + + s.mockQ.On("GetContractAssetBalances", s.ctx, []xdr.Hash{keyHash}). + Return([]history.ContractAssetBalance{ + { + KeyHash: keyHash[:], + ContractID: usdID[:], + Amount: "100", + ExpirationLedger: 2234, + }, + }, nil).Once() + + usdAssetContractStat.Stat.ActiveBalance = "350" + s.mockQ.On("UpdateContractAssetStat", s.ctx, mock.MatchedBy(func(row history.ContractAssetStatRow) bool { + return bytes.Equal(usdID[:], row.ContractID) && + usdAssetContractStat.Stat == row.Stat + })).Return(int64(1), nil).Once() + + s.mockQ.On("InsertContractAssetBalances", s.ctx, []history.ContractAssetBalance(nil)). + Return(nil).Once() + s.mockQ.On("RemoveContractAssetBalances", s.ctx, []xdr.Hash(nil)). + Return(nil).Once() + s.mockQ.On("UpdateContractAssetBalanceAmounts", s.ctx, []xdr.Hash{keyHash}, []string{"300"}). + Return(nil).Once() + s.mockQ.On("UpdateContractAssetBalanceExpirations", s.ctx, []xdr.Hash{}, []uint32{}). + Return(nil).Once() + s.mockQ.On("GetContractAssetBalancesExpiringAt", s.ctx, uint32(1234)). + Return([]history.ContractAssetBalance{}, nil).Once() + + s.Assert().NoError(s.processor.Commit(s.ctx)) +} + +func (s *AssetStatsProcessorTestSuiteLedger) TestRemoveContractBalance() { lastModifiedLedgerSeq := xdr.Uint32(1234) + usdID, err := xdr.MustNewCreditAsset("USD", trustLineIssuer.Address()).ContractID("") + s.Assert().NoError(err) + + s.Assert().NoError(s.processor.ProcessChange(s.ctx, ingest.Change{ + Type: xdr.LedgerEntryTypeContractData, + Pre: &xdr.LedgerEntry{ + LastModifiedLedgerSeq: lastModifiedLedgerSeq, + Data: BalanceToContractData(usdID, [32]byte{1}, 200), + }, + })) + + keyHash := getKeyHashForBalance(s.T(), usdID, [32]byte{1}) + s.Assert().NoError(s.processor.ProcessChange(s.ctx, ingest.Change{ + Type: xdr.LedgerEntryTypeTtl, + Pre: &xdr.LedgerEntry{ + LastModifiedLedgerSeq: lastModifiedLedgerSeq, + Data: xdr.LedgerEntryData{ + Type: xdr.LedgerEntryTypeTtl, + Ttl: &xdr.TtlEntry{ + KeyHash: keyHash, + LiveUntilLedgerSeq: 2234, + }, + }, + }, + })) + + usdAssetContractStat := history.ContractAssetStatRow{ + ContractID: usdID[:], + Stat: history.ContractStat{ + ActiveBalance: "200", + ActiveHolders: 1, + ArchivedHolders: 0, + ArchivedBalance: "0", + }, + } + s.mockQ.On("GetContractAssetStat", s.ctx, usdID[:]). + Return(usdAssetContractStat, nil).Once() + + usdAssetContractStat.Stat.ActiveHolders = 0 + usdAssetContractStat.Stat.ActiveBalance = "0" + s.mockQ.On("RemoveAssetContractStat", s.ctx, usdID[:]).Return(int64(1), nil).Once() + s.mockQ.On("RemoveContractAssetBalances", s.ctx, []xdr.Hash{keyHash}). + Return(nil).Once() + s.mockQ.On("UpdateContractAssetBalanceAmounts", s.ctx, []xdr.Hash{}, []string{}). + Return(nil).Once() + s.mockQ.On("InsertContractAssetBalances", s.ctx, []history.ContractAssetBalance(nil)). + Return(nil).Once() + s.mockQ.On("UpdateContractAssetBalanceExpirations", s.ctx, []xdr.Hash{}, []uint32{}). + Return(nil).Once() + s.mockQ.On("GetContractAssetBalancesExpiringAt", s.ctx, uint32(1234)). + Return([]history.ContractAssetBalance{}, nil).Once() + + s.Assert().NoError(s.processor.Commit(s.ctx)) +} +func (s *AssetStatsProcessorTestSuiteLedger) TestInsertContractIDWithBalance() { + // add trust line trustLine := xdr.TrustLineEntry{ AccountId: xdr.MustAddress("GAOQJGUAB7NI7K7I62ORBXMN3J4SSWQUQ7FOEPSDJ322W2HMCNWPHXFB"), Asset: xdr.MustNewCreditAsset("EUR", trustLineIssuer.Address()).ToTrustLineAsset(), Balance: 0, Flags: xdr.Uint32(xdr.TrustLineFlagsAuthorizedFlag), } - updatedTrustLine := xdr.TrustLineEntry{ - AccountId: xdr.MustAddress("GAOQJGUAB7NI7K7I62ORBXMN3J4SSWQUQ7FOEPSDJ322W2HMCNWPHXFB"), - Asset: xdr.MustNewCreditAsset("EUR", trustLineIssuer.Address()).ToTrustLineAsset(), - Balance: 10, - Flags: xdr.Uint32(xdr.TrustLineFlagsAuthorizedFlag), - } + eurID, err := trustLine.Asset.ToAsset().ContractID("") + s.Assert().NoError(err) + eurContractData, err := AssetToContractData(false, "EUR", trustLineIssuer.Address(), eurID) + s.Assert().NoError(err) - err := s.processor.ProcessChange(s.ctx, ingest.Change{ + usdID, err := xdr.MustNewCreditAsset("USD", trustLineIssuer.Address()).ContractID("") + s.Assert().NoError(err) + usdContractData, err := AssetToContractData(false, "USD", trustLineIssuer.Address(), usdID) + s.Assert().NoError(err) + + lastModifiedLedgerSeq := xdr.Uint32(1234) + err = s.processor.ProcessChange(s.ctx, ingest.Change{ Type: xdr.LedgerEntryTypeTrustline, - Pre: &xdr.LedgerEntry{ + Pre: nil, + Post: &xdr.LedgerEntry{ LastModifiedLedgerSeq: lastModifiedLedgerSeq, Data: xdr.LedgerEntryData{ Type: xdr.LedgerEntryTypeTrustline, TrustLine: &trustLine, }, }, + }) + s.Assert().NoError(err) + + err = s.processor.ProcessChange(s.ctx, ingest.Change{ + Type: xdr.LedgerEntryTypeContractData, + Pre: nil, + Post: &xdr.LedgerEntry{ + LastModifiedLedgerSeq: lastModifiedLedgerSeq, + Data: eurContractData, + }, + }) + s.Assert().NoError(err) + + err = s.processor.ProcessChange(s.ctx, ingest.Change{ + Type: xdr.LedgerEntryTypeContractData, + Pre: nil, Post: &xdr.LedgerEntry{ LastModifiedLedgerSeq: lastModifiedLedgerSeq, - Data: xdr.LedgerEntryData{ - Type: xdr.LedgerEntryTypeTrustline, - TrustLine: &updatedTrustLine, - }, + Data: usdContractData, }, }) s.Assert().NoError(err) + s.Assert().NoError(s.processor.ProcessChange(s.ctx, ingest.Change{ + Type: xdr.LedgerEntryTypeContractData, + Post: &xdr.LedgerEntry{ + LastModifiedLedgerSeq: lastModifiedLedgerSeq, + Data: BalanceToContractData(usdID, [32]byte{1}, 150), + }, + })) + + btcID := [32]byte{1, 2, 3} + s.Assert().NoError(s.processor.ProcessChange(s.ctx, ingest.Change{ + Type: xdr.LedgerEntryTypeContractData, + Post: &xdr.LedgerEntry{ + LastModifiedLedgerSeq: lastModifiedLedgerSeq, + Data: BalanceToContractData(btcID, [32]byte{1}, 20), + }, + })) + + keyHash := getKeyHashForBalance(s.T(), btcID, [32]byte{1}) + s.Assert().NoError(s.processor.ProcessChange(s.ctx, ingest.Change{ + Type: xdr.LedgerEntryTypeTtl, + Post: &xdr.LedgerEntry{ + LastModifiedLedgerSeq: lastModifiedLedgerSeq, + Data: xdr.LedgerEntryData{ + Type: xdr.LedgerEntryTypeTtl, + Ttl: &xdr.TtlEntry{ + KeyHash: keyHash, + LiveUntilLedgerSeq: 2234, + }, + }, + }, + })) + s.mockQ.On("GetAssetStat", s.ctx, xdr.AssetTypeAssetTypeCreditAlphanum4, "EUR", trustLineIssuer.Address(), - ).Return(history.ExpAssetStat{ + ).Return(history.ExpAssetStat{}, sql.ErrNoRows).Once() + eurAssetStat := history.ExpAssetStat{ AssetType: xdr.AssetTypeAssetTypeCreditAlphanum4, AssetIssuer: trustLineIssuer.Address(), AssetCode: "EUR", - Accounts: history.ExpAssetStatAccounts{Authorized: 1}, + Accounts: history.ExpAssetStatAccounts{ + Authorized: 1, + }, Balances: history.ExpAssetStatBalances{ - Authorized: "100", + Authorized: "0", AuthorizedToMaintainLiabilities: "0", Unauthorized: "0", ClaimableBalances: "0", LiquidityPools: "0", }, - Amount: "100", + Amount: "0", NumAccounts: 1, - }, nil).Once() - s.mockQ.On("UpdateAssetStat", s.ctx, history.ExpAssetStat{ + } + eurAssetStat.SetContractID(eurID) + s.mockQ.On("InsertAssetStat", s.ctx, mock.MatchedBy(func(assetStat history.ExpAssetStat) bool { + return eurAssetStat.Equals(assetStat) + })).Return(int64(1), nil).Once() + + s.mockQ.On("GetAssetStat", s.ctx, + xdr.AssetTypeAssetTypeCreditAlphanum4, + "USD", + trustLineIssuer.Address(), + ).Return(history.ExpAssetStat{}, sql.ErrNoRows).Once() + + s.mockQ.On("GetContractAssetStat", s.ctx, btcID[:]). + Return(history.ContractAssetStatRow{}, sql.ErrNoRows).Once() + btcAssetContractStat := history.ContractAssetStatRow{ + ContractID: btcID[:], + Stat: history.ContractStat{ + ActiveBalance: "20", + ActiveHolders: 1, + ArchivedBalance: "0", + ArchivedHolders: 0, + }, + } + s.mockQ.On("InsertContractAssetStat", s.ctx, mock.MatchedBy(func(row history.ContractAssetStatRow) bool { + return bytes.Equal(btcID[:], row.ContractID) && + btcAssetContractStat.Stat == row.Stat + })).Return(int64(1), nil).Once() + + usdAssetStat := history.ExpAssetStat{ AssetType: xdr.AssetTypeAssetTypeCreditAlphanum4, AssetIssuer: trustLineIssuer.Address(), - AssetCode: "EUR", - Accounts: history.ExpAssetStatAccounts{Authorized: 1}, + AssetCode: "USD", + Accounts: history.ExpAssetStatAccounts{}, Balances: history.ExpAssetStatBalances{ - Authorized: "110", + Authorized: "0", AuthorizedToMaintainLiabilities: "0", Unauthorized: "0", ClaimableBalances: "0", LiquidityPools: "0", }, - Amount: "110", - NumAccounts: 1, - }).Return(int64(1), nil).Once() + Amount: "0", + NumAccounts: 0, + } + usdAssetStat.SetContractID(usdID) + s.mockQ.On("InsertAssetStat", s.ctx, mock.MatchedBy(func(assetStat history.ExpAssetStat) bool { + return usdAssetStat.Equals(assetStat) + })).Return(int64(1), nil).Once() + + s.mockQ.On("RemoveContractAssetBalances", s.ctx, []xdr.Hash(nil)). + Return(nil).Once() + s.mockQ.On("UpdateContractAssetBalanceAmounts", s.ctx, []xdr.Hash{}, []string{}). + Return(nil).Once() + s.mockQ.On("InsertContractAssetBalances", s.ctx, []history.ContractAssetBalance{ + { + KeyHash: keyHash[:], + ContractID: btcID[:], + Amount: "20", + ExpirationLedger: 2234, + }, + }).Return(nil).Once() + s.mockQ.On("UpdateContractAssetBalanceExpirations", s.ctx, []xdr.Hash{}, []uint32{}). + Return(nil).Once() + s.mockQ.On("GetContractAssetBalancesExpiringAt", s.ctx, uint32(1234)). + Return([]history.ContractAssetBalance{}, nil).Once() s.Assert().NoError(s.processor.Commit(s.ctx)) } -func (s *AssetStatsProcessorTestSuiteLedger) TestUpdateTrustLineAuthorization() { - lastModifiedLedgerSeq := xdr.Uint32(1234) - - // EUR trustline: 100 unauthorized -> 10 authorized - eurTrustLine := xdr.TrustLineEntry{ - AccountId: xdr.MustAddress("GAOQJGUAB7NI7K7I62ORBXMN3J4SSWQUQ7FOEPSDJ322W2HMCNWPHXFB"), - Asset: xdr.MustNewCreditAsset("EUR", trustLineIssuer.Address()).ToTrustLineAsset(), - Balance: 100, - } - eurUpdatedTrustLine := xdr.TrustLineEntry{ - AccountId: xdr.MustAddress("GAOQJGUAB7NI7K7I62ORBXMN3J4SSWQUQ7FOEPSDJ322W2HMCNWPHXFB"), - Asset: xdr.MustNewCreditAsset("EUR", trustLineIssuer.Address()).ToTrustLineAsset(), - Balance: 10, - Flags: xdr.Uint32(xdr.TrustLineFlagsAuthorizedFlag), - } - - // USD trustline: 100 authorized -> 10 unauthorized +func (s *AssetStatsProcessorTestSuiteLedger) TestInsertClaimableBalanceAndTrustlineAndLiquidityPool() { + liquidityPool := xdr.LiquidityPoolEntry{ + Body: xdr.LiquidityPoolEntryBody{ + Type: xdr.LiquidityPoolTypeLiquidityPoolConstantProduct, + ConstantProduct: &xdr.LiquidityPoolEntryConstantProduct{ + Params: xdr.LiquidityPoolConstantProductParameters{ + AssetA: xdr.MustNewCreditAsset("EUR", trustLineIssuer.Address()), + AssetB: xdr.MustNewNativeAsset(), + Fee: 20, + }, + ReserveA: 100, + ReserveB: 200, + TotalPoolShares: 1000, + PoolSharesTrustLineCount: 10, + }, + }, + } + + claimableBalance := xdr.ClaimableBalanceEntry{ + Asset: xdr.MustNewCreditAsset("EUR", trustLineIssuer.Address()), + Amount: 12, + BalanceId: xdr.ClaimableBalanceId{ + Type: 0, + V0: &xdr.Hash{1, 2, 3}, + }, + } + + trustLine := xdr.TrustLineEntry{ + AccountId: xdr.MustAddress("GAOQJGUAB7NI7K7I62ORBXMN3J4SSWQUQ7FOEPSDJ322W2HMCNWPHXFB"), + Asset: xdr.MustNewCreditAsset("EUR", trustLineIssuer.Address()).ToTrustLineAsset(), + Balance: 9, + Flags: xdr.Uint32(xdr.TrustLineFlagsAuthorizedFlag), + } + lastModifiedLedgerSeq := xdr.Uint32(1234) + + err := s.processor.ProcessChange(s.ctx, ingest.Change{ + Type: xdr.LedgerEntryTypeLiquidityPool, + Pre: nil, + Post: &xdr.LedgerEntry{ + LastModifiedLedgerSeq: lastModifiedLedgerSeq, + Data: xdr.LedgerEntryData{ + Type: xdr.LedgerEntryTypeLiquidityPool, + LiquidityPool: &liquidityPool, + }, + }, + }) + s.Assert().NoError(err) + + err = s.processor.ProcessChange(s.ctx, ingest.Change{ + Type: xdr.LedgerEntryTypeClaimableBalance, + Pre: nil, + Post: &xdr.LedgerEntry{ + LastModifiedLedgerSeq: lastModifiedLedgerSeq, + Data: xdr.LedgerEntryData{ + Type: xdr.LedgerEntryTypeClaimableBalance, + ClaimableBalance: &claimableBalance, + }, + }, + }) + s.Assert().NoError(err) + + err = s.processor.ProcessChange(s.ctx, ingest.Change{ + Type: xdr.LedgerEntryTypeTrustline, + Pre: nil, + Post: &xdr.LedgerEntry{ + LastModifiedLedgerSeq: lastModifiedLedgerSeq, + Data: xdr.LedgerEntryData{ + Type: xdr.LedgerEntryTypeTrustline, + TrustLine: &trustLine, + }, + }, + }) + s.Assert().NoError(err) + + s.mockQ.On("GetAssetStat", s.ctx, + xdr.AssetTypeAssetTypeCreditAlphanum4, + "EUR", + trustLineIssuer.Address(), + ).Return(history.ExpAssetStat{}, sql.ErrNoRows).Once() + s.mockQ.On("InsertAssetStat", s.ctx, history.ExpAssetStat{ + AssetType: xdr.AssetTypeAssetTypeCreditAlphanum4, + AssetIssuer: trustLineIssuer.Address(), + AssetCode: "EUR", + Accounts: history.ExpAssetStatAccounts{ + ClaimableBalances: 1, + Authorized: 1, + LiquidityPools: 1, + }, + Balances: history.ExpAssetStatBalances{ + Authorized: "9", + AuthorizedToMaintainLiabilities: "0", + Unauthorized: "0", + ClaimableBalances: "12", + LiquidityPools: "100", + }, + Amount: "9", + NumAccounts: 1, + }).Return(int64(1), nil).Once() + + s.mockQ.On("RemoveContractAssetBalances", s.ctx, []xdr.Hash(nil)). + Return(nil).Once() + s.mockQ.On("UpdateContractAssetBalanceAmounts", s.ctx, []xdr.Hash{}, []string{}). + Return(nil).Once() + s.mockQ.On("InsertContractAssetBalances", s.ctx, []history.ContractAssetBalance(nil)). + Return(nil).Once() + s.mockQ.On("UpdateContractAssetBalanceExpirations", s.ctx, []xdr.Hash{}, []uint32{}). + Return(nil).Once() + s.mockQ.On("GetContractAssetBalancesExpiringAt", s.ctx, uint32(1234)). + Return([]history.ContractAssetBalance{}, nil).Once() + + s.Assert().NoError(s.processor.Commit(s.ctx)) +} + +func (s *AssetStatsProcessorTestSuiteLedger) TestUpdateContractID() { + lastModifiedLedgerSeq := xdr.Uint32(1234) + + eurID, err := xdr.MustNewCreditAsset("EUR", trustLineIssuer.Address()).ContractID("") + s.Assert().NoError(err) + eurContractData, err := AssetToContractData(false, "EUR", trustLineIssuer.Address(), eurID) + s.Assert().NoError(err) + + err = s.processor.ProcessChange(s.ctx, ingest.Change{ + Type: xdr.LedgerEntryTypeContractData, + Post: &xdr.LedgerEntry{ + LastModifiedLedgerSeq: lastModifiedLedgerSeq, + Data: eurContractData, + }, + }) + s.Assert().NoError(err) + + s.mockQ.On("GetAssetStat", s.ctx, + xdr.AssetTypeAssetTypeCreditAlphanum4, + "EUR", + trustLineIssuer.Address(), + ).Return(history.ExpAssetStat{ + AssetType: xdr.AssetTypeAssetTypeCreditAlphanum4, + AssetIssuer: trustLineIssuer.Address(), + AssetCode: "EUR", + Accounts: history.ExpAssetStatAccounts{Authorized: 1}, + Balances: history.ExpAssetStatBalances{ + Authorized: "100", + AuthorizedToMaintainLiabilities: "0", + Unauthorized: "0", + ClaimableBalances: "0", + LiquidityPools: "0", + }, + Amount: "100", + NumAccounts: 1, + }, nil).Once() + + eurAssetStat := history.ExpAssetStat{ + AssetType: xdr.AssetTypeAssetTypeCreditAlphanum4, + AssetIssuer: trustLineIssuer.Address(), + AssetCode: "EUR", + Accounts: history.ExpAssetStatAccounts{Authorized: 1}, + Balances: history.ExpAssetStatBalances{ + Authorized: "100", + AuthorizedToMaintainLiabilities: "0", + Unauthorized: "0", + ClaimableBalances: "0", + LiquidityPools: "0", + }, + Amount: "100", + NumAccounts: 1, + } + eurAssetStat.SetContractID(eurID) + s.mockQ.On("UpdateAssetStat", s.ctx, mock.MatchedBy(func(assetStat history.ExpAssetStat) bool { + return eurAssetStat.Equals(assetStat) + })).Return(int64(1), nil).Once() + + s.mockQ.On("RemoveContractAssetBalances", s.ctx, []xdr.Hash(nil)). + Return(nil).Once() + s.mockQ.On("UpdateContractAssetBalanceAmounts", s.ctx, []xdr.Hash{}, []string{}). + Return(nil).Once() + s.mockQ.On("InsertContractAssetBalances", s.ctx, []history.ContractAssetBalance(nil)). + Return(nil).Once() + s.mockQ.On("UpdateContractAssetBalanceExpirations", s.ctx, []xdr.Hash{}, []uint32{}). + Return(nil).Once() + s.mockQ.On("GetContractAssetBalancesExpiringAt", s.ctx, uint32(1234)). + Return([]history.ContractAssetBalance{}, nil).Once() + + s.Assert().NoError(s.processor.Commit(s.ctx)) +} + +func (s *AssetStatsProcessorTestSuiteLedger) TestExpirationLedgerCannotDecrease() { + lastModifiedLedgerSeq := xdr.Uint32(1234) + + eurID, err := xdr.MustNewCreditAsset("EUR", trustLineIssuer.Address()).ContractID("") + s.Assert().NoError(err) + + keyHash := getKeyHashForBalance(s.T(), eurID, [32]byte{1}) + s.Assert().NoError(s.processor.ProcessChange(s.ctx, ingest.Change{ + Type: xdr.LedgerEntryTypeTtl, + Pre: &xdr.LedgerEntry{ + LastModifiedLedgerSeq: lastModifiedLedgerSeq, + Data: xdr.LedgerEntryData{ + Type: xdr.LedgerEntryTypeTtl, + Ttl: &xdr.TtlEntry{ + KeyHash: keyHash, + LiveUntilLedgerSeq: 2235, + }, + }, + }, + Post: &xdr.LedgerEntry{ + LastModifiedLedgerSeq: lastModifiedLedgerSeq, + Data: xdr.LedgerEntryData{ + Type: xdr.LedgerEntryTypeTtl, + Ttl: &xdr.TtlEntry{ + KeyHash: keyHash, + LiveUntilLedgerSeq: 2234, + }, + }, + }, + })) + + s.Assert().EqualError( + s.processor.Commit(s.ctx), + "Error adjusting asset stat: unexpected change in expiration ledger Pre: 2235 Post: 2234", + ) +} + +func (s *AssetStatsProcessorTestSuiteLedger) TestExpirationLedgerCannotBeLessThanCurrentLedger() { + lastModifiedLedgerSeq := xdr.Uint32(1234) + + eurID, err := xdr.MustNewCreditAsset("EUR", trustLineIssuer.Address()).ContractID("") + s.Assert().NoError(err) + + keyHash := getKeyHashForBalance(s.T(), eurID, [32]byte{1}) + s.Assert().NoError(s.processor.ProcessChange(s.ctx, ingest.Change{ + Type: xdr.LedgerEntryTypeTtl, + Pre: &xdr.LedgerEntry{ + LastModifiedLedgerSeq: lastModifiedLedgerSeq, + Data: xdr.LedgerEntryData{ + Type: xdr.LedgerEntryTypeTtl, + Ttl: &xdr.TtlEntry{ + KeyHash: keyHash, + LiveUntilLedgerSeq: 1230, + }, + }, + }, + Post: &xdr.LedgerEntry{ + LastModifiedLedgerSeq: lastModifiedLedgerSeq, + Data: xdr.LedgerEntryData{ + Type: xdr.LedgerEntryTypeTtl, + Ttl: &xdr.TtlEntry{ + KeyHash: keyHash, + LiveUntilLedgerSeq: 1234, + }, + }, + }, + })) + + s.Assert().EqualError( + s.processor.Commit(s.ctx), + "Error adjusting asset stat: post expiration ledger is less than current ledger. Pre: 1230 Post: 1234 current ledger: 1235", + ) +} + +func (s *AssetStatsProcessorTestSuiteLedger) TestUpdateContractIDWithBalance() { + lastModifiedLedgerSeq := xdr.Uint32(1234) + + eurID, err := xdr.MustNewCreditAsset("EUR", trustLineIssuer.Address()).ContractID("") + s.Assert().NoError(err) + eurContractData, err := AssetToContractData(false, "EUR", trustLineIssuer.Address(), eurID) + s.Assert().NoError(err) + + err = s.processor.ProcessChange(s.ctx, ingest.Change{ + Type: xdr.LedgerEntryTypeContractData, + Post: &xdr.LedgerEntry{ + LastModifiedLedgerSeq: lastModifiedLedgerSeq, + Data: eurContractData, + }, + }) + s.Assert().NoError(err) + + s.Assert().NoError(s.processor.ProcessChange(s.ctx, ingest.Change{ + Type: xdr.LedgerEntryTypeContractData, + Post: &xdr.LedgerEntry{ + LastModifiedLedgerSeq: lastModifiedLedgerSeq, + Data: BalanceToContractData(eurID, [32]byte{1}, 150), + }, + })) + keyHash := getKeyHashForBalance(s.T(), eurID, [32]byte{1}) + s.Assert().NoError(s.processor.ProcessChange(s.ctx, ingest.Change{ + Type: xdr.LedgerEntryTypeTtl, + Post: &xdr.LedgerEntry{ + LastModifiedLedgerSeq: lastModifiedLedgerSeq, + Data: xdr.LedgerEntryData{ + Type: xdr.LedgerEntryTypeTtl, + Ttl: &xdr.TtlEntry{ + KeyHash: keyHash, + LiveUntilLedgerSeq: 2234, + }, + }, + }, + })) + + s.mockQ.On("GetAssetStat", s.ctx, + xdr.AssetTypeAssetTypeCreditAlphanum4, + "EUR", + trustLineIssuer.Address(), + ).Return(history.ExpAssetStat{ + AssetType: xdr.AssetTypeAssetTypeCreditAlphanum4, + AssetIssuer: trustLineIssuer.Address(), + AssetCode: "EUR", + Accounts: history.ExpAssetStatAccounts{Authorized: 1}, + Balances: history.ExpAssetStatBalances{ + Authorized: "100", + AuthorizedToMaintainLiabilities: "0", + Unauthorized: "0", + ClaimableBalances: "0", + LiquidityPools: "0", + }, + Amount: "100", + NumAccounts: 1, + }, nil).Once() + + eurAssetStat := history.ExpAssetStat{ + AssetType: xdr.AssetTypeAssetTypeCreditAlphanum4, + AssetIssuer: trustLineIssuer.Address(), + AssetCode: "EUR", + Accounts: history.ExpAssetStatAccounts{ + Authorized: 1, + }, + Balances: history.ExpAssetStatBalances{ + Authorized: "100", + AuthorizedToMaintainLiabilities: "0", + Unauthorized: "0", + ClaimableBalances: "0", + LiquidityPools: "0", + }, + Amount: "100", + NumAccounts: 1, + } + eurAssetStat.SetContractID(eurID) + s.mockQ.On("UpdateAssetStat", s.ctx, mock.MatchedBy(func(assetStat history.ExpAssetStat) bool { + return eurAssetStat.Equals(assetStat) + })).Return(int64(1), nil).Once() + + eurAssetContractStat := history.ContractAssetStatRow{ + ContractID: eurID[:], + Stat: history.ContractStat{ + ActiveBalance: "10", + ActiveHolders: 2, + ArchivedBalance: "0", + ArchivedHolders: 0, + }, + } + s.mockQ.On("GetContractAssetStat", s.ctx, eurID[:]). + Return(eurAssetContractStat, nil).Once() + + eurAssetContractStat.Stat.ActiveHolders++ + eurAssetContractStat.Stat.ActiveBalance = "160" + s.mockQ.On("UpdateContractAssetStat", s.ctx, mock.MatchedBy(func(row history.ContractAssetStatRow) bool { + return bytes.Equal(eurID[:], row.ContractID) && + eurAssetContractStat.Stat == row.Stat + })).Return(int64(1), nil).Once() + + s.mockQ.On("RemoveContractAssetBalances", s.ctx, []xdr.Hash(nil)). + Return(nil).Once() + s.mockQ.On("UpdateContractAssetBalanceAmounts", s.ctx, []xdr.Hash{}, []string{}). + Return(nil).Once() + s.mockQ.On("InsertContractAssetBalances", s.ctx, []history.ContractAssetBalance{ + { + KeyHash: keyHash[:], + ContractID: eurID[:], + Amount: "150", + ExpirationLedger: 2234, + }, + }). + Return(nil).Once() + s.mockQ.On("UpdateContractAssetBalanceExpirations", s.ctx, []xdr.Hash{}, []uint32{}). + Return(nil).Once() + s.mockQ.On("GetContractAssetBalancesExpiringAt", s.ctx, uint32(1234)). + Return([]history.ContractAssetBalance{}, nil).Once() + + s.Assert().NoError(s.processor.Commit(s.ctx)) +} + +func (s *AssetStatsProcessorTestSuiteLedger) TestUpdateContractIDError() { + lastModifiedLedgerSeq := xdr.Uint32(1234) + + usdID, err := xdr.MustNewCreditAsset("USD", trustLineIssuer.Address()).ContractID("") + s.Assert().NoError(err) + eurID, err := xdr.MustNewCreditAsset("EUR", trustLineIssuer.Address()).ContractID("") + s.Assert().NoError(err) + eurContractData, err := AssetToContractData(false, "EUR", trustLineIssuer.Address(), eurID) + s.Assert().NoError(err) + + err = s.processor.ProcessChange(s.ctx, ingest.Change{ + Type: xdr.LedgerEntryTypeContractData, + Post: &xdr.LedgerEntry{ + LastModifiedLedgerSeq: lastModifiedLedgerSeq, + Data: eurContractData, + }, + }) + s.Assert().NoError(err) + + eurAssetStat := history.ExpAssetStat{ + AssetType: xdr.AssetTypeAssetTypeCreditAlphanum4, + AssetIssuer: trustLineIssuer.Address(), + AssetCode: "EUR", + Accounts: history.ExpAssetStatAccounts{Authorized: 1}, + Balances: history.ExpAssetStatBalances{ + Authorized: "100", + AuthorizedToMaintainLiabilities: "0", + Unauthorized: "0", + ClaimableBalances: "0", + LiquidityPools: "0", + }, + Amount: "100", + NumAccounts: 1, + } + eurAssetStat.SetContractID(usdID) + s.mockQ.On("GetAssetStat", s.ctx, + xdr.AssetTypeAssetTypeCreditAlphanum4, + "EUR", + trustLineIssuer.Address(), + ).Return(eurAssetStat, nil).Once() + + s.Assert().EqualError( + s.processor.Commit(s.ctx), + "attempting to set contract id 67b1f192e30d8cd56dcb103c783cfee753588a434ad1092ef8a39375c9738bab but row credit_alphanum4/EUR/GBRPYHIL2CI3FNQ4BXLFMNDLFJUNPU2HY3ZMFSHONUCEOASW7QC7OX2H already has contract id set: c9cd6bbf712cfd4e086f0e25f90722c1af24416c0303728ad4527a6967ddc51b", + ) +} + +func (s *AssetStatsProcessorTestSuiteLedger) TestUpdateTrustlineAndContractIDError() { + lastModifiedLedgerSeq := xdr.Uint32(1234) + + usdID, err := xdr.MustNewCreditAsset("USD", trustLineIssuer.Address()).ContractID("") + s.Assert().NoError(err) + eurID, err := xdr.MustNewCreditAsset("EUR", trustLineIssuer.Address()).ContractID("") + s.Assert().NoError(err) + eurContractData, err := AssetToContractData(false, "EUR", trustLineIssuer.Address(), eurID) + s.Assert().NoError(err) + + err = s.processor.ProcessChange(s.ctx, ingest.Change{ + Type: xdr.LedgerEntryTypeContractData, + Post: &xdr.LedgerEntry{ + LastModifiedLedgerSeq: lastModifiedLedgerSeq, + Data: eurContractData, + }, + }) + s.Assert().NoError(err) + + trustLine := xdr.TrustLineEntry{ + AccountId: xdr.MustAddress("GAOQJGUAB7NI7K7I62ORBXMN3J4SSWQUQ7FOEPSDJ322W2HMCNWPHXFB"), + Asset: xdr.MustNewCreditAsset("EUR", trustLineIssuer.Address()).ToTrustLineAsset(), + Balance: 0, + Flags: xdr.Uint32(xdr.TrustLineFlagsAuthorizedFlag), + } + updatedTrustLine := xdr.TrustLineEntry{ + AccountId: xdr.MustAddress("GAOQJGUAB7NI7K7I62ORBXMN3J4SSWQUQ7FOEPSDJ322W2HMCNWPHXFB"), + Asset: xdr.MustNewCreditAsset("EUR", trustLineIssuer.Address()).ToTrustLineAsset(), + Balance: 10, + Flags: xdr.Uint32(xdr.TrustLineFlagsAuthorizedFlag), + } + + err = s.processor.ProcessChange(s.ctx, ingest.Change{ + Type: xdr.LedgerEntryTypeTrustline, + Pre: &xdr.LedgerEntry{ + LastModifiedLedgerSeq: lastModifiedLedgerSeq, + Data: xdr.LedgerEntryData{ + Type: xdr.LedgerEntryTypeTrustline, + TrustLine: &trustLine, + }, + }, + Post: &xdr.LedgerEntry{ + LastModifiedLedgerSeq: lastModifiedLedgerSeq, + Data: xdr.LedgerEntryData{ + Type: xdr.LedgerEntryTypeTrustline, + TrustLine: &updatedTrustLine, + }, + }, + }) + s.Assert().NoError(err) + + eurAssetStat := history.ExpAssetStat{ + AssetType: xdr.AssetTypeAssetTypeCreditAlphanum4, + AssetIssuer: trustLineIssuer.Address(), + AssetCode: "EUR", + Accounts: history.ExpAssetStatAccounts{Authorized: 1}, + Balances: history.ExpAssetStatBalances{ + Authorized: "100", + AuthorizedToMaintainLiabilities: "0", + Unauthorized: "0", + ClaimableBalances: "0", + LiquidityPools: "0", + }, + Amount: "100", + NumAccounts: 1, + } + eurAssetStat.SetContractID(usdID) + s.mockQ.On("GetAssetStat", s.ctx, + xdr.AssetTypeAssetTypeCreditAlphanum4, + "EUR", + trustLineIssuer.Address(), + ).Return(eurAssetStat, nil).Once() + + s.Assert().EqualError( + s.processor.Commit(s.ctx), + "attempting to set contract id 67b1f192e30d8cd56dcb103c783cfee753588a434ad1092ef8a39375c9738bab but row credit_alphanum4/EUR/GBRPYHIL2CI3FNQ4BXLFMNDLFJUNPU2HY3ZMFSHONUCEOASW7QC7OX2H already has contract id set: c9cd6bbf712cfd4e086f0e25f90722c1af24416c0303728ad4527a6967ddc51b", + ) +} + +func (s *AssetStatsProcessorTestSuiteLedger) TestRemoveContractIDError() { + lastModifiedLedgerSeq := xdr.Uint32(1234) + + eurID, err := xdr.MustNewCreditAsset("EUR", trustLineIssuer.Address()).ContractID("") + s.Assert().NoError(err) + eurContractData, err := AssetToContractData(false, "EUR", trustLineIssuer.Address(), eurID) + s.Assert().NoError(err) + + err = s.processor.ProcessChange(s.ctx, ingest.Change{ + Type: xdr.LedgerEntryTypeContractData, + Pre: &xdr.LedgerEntry{ + LastModifiedLedgerSeq: lastModifiedLedgerSeq, + Data: eurContractData, + }, + }) + s.Assert().NoError(err) + + s.mockQ.On("GetAssetStatByContract", s.ctx, xdr.Hash(eurID)). + Return(history.ExpAssetStat{}, sql.ErrNoRows).Once() + + s.Assert().EqualError( + s.processor.Commit(s.ctx), + "row for asset with contract 67b1f192e30d8cd56dcb103c783cfee753588a434ad1092ef8a39375c9738bab is missing", + ) +} + +func (s *AssetStatsProcessorTestSuiteLedger) TestUpdateTrustlineAndRemoveContractIDError() { + lastModifiedLedgerSeq := xdr.Uint32(1234) + + eurID, err := xdr.MustNewCreditAsset("EUR", trustLineIssuer.Address()).ContractID("") + s.Assert().NoError(err) + eurContractData, err := AssetToContractData(false, "EUR", trustLineIssuer.Address(), eurID) + s.Assert().NoError(err) + + err = s.processor.ProcessChange(s.ctx, ingest.Change{ + Type: xdr.LedgerEntryTypeContractData, + Pre: &xdr.LedgerEntry{ + LastModifiedLedgerSeq: lastModifiedLedgerSeq, + Data: eurContractData, + }, + }) + s.Assert().NoError(err) + + trustLine := xdr.TrustLineEntry{ + AccountId: xdr.MustAddress("GAOQJGUAB7NI7K7I62ORBXMN3J4SSWQUQ7FOEPSDJ322W2HMCNWPHXFB"), + Asset: xdr.MustNewCreditAsset("EUR", trustLineIssuer.Address()).ToTrustLineAsset(), + Balance: 0, + Flags: xdr.Uint32(xdr.TrustLineFlagsAuthorizedFlag), + } + updatedTrustLine := xdr.TrustLineEntry{ + AccountId: xdr.MustAddress("GAOQJGUAB7NI7K7I62ORBXMN3J4SSWQUQ7FOEPSDJ322W2HMCNWPHXFB"), + Asset: xdr.MustNewCreditAsset("EUR", trustLineIssuer.Address()).ToTrustLineAsset(), + Balance: 10, + Flags: xdr.Uint32(xdr.TrustLineFlagsAuthorizedFlag), + } + + err = s.processor.ProcessChange(s.ctx, ingest.Change{ + Type: xdr.LedgerEntryTypeTrustline, + Pre: &xdr.LedgerEntry{ + LastModifiedLedgerSeq: lastModifiedLedgerSeq, + Data: xdr.LedgerEntryData{ + Type: xdr.LedgerEntryTypeTrustline, + TrustLine: &trustLine, + }, + }, + Post: &xdr.LedgerEntry{ + LastModifiedLedgerSeq: lastModifiedLedgerSeq, + Data: xdr.LedgerEntryData{ + Type: xdr.LedgerEntryTypeTrustline, + TrustLine: &updatedTrustLine, + }, + }, + }) + s.Assert().NoError(err) + + eurAssetStat := history.ExpAssetStat{ + AssetType: xdr.AssetTypeAssetTypeCreditAlphanum4, + AssetIssuer: trustLineIssuer.Address(), + AssetCode: "EUR", + Accounts: history.ExpAssetStatAccounts{Authorized: 1}, + Balances: history.ExpAssetStatBalances{ + Authorized: "100", + AuthorizedToMaintainLiabilities: "0", + Unauthorized: "0", + ClaimableBalances: "0", + LiquidityPools: "0", + }, + Amount: "100", + NumAccounts: 1, + } + s.mockQ.On("GetAssetStat", s.ctx, + xdr.AssetTypeAssetTypeCreditAlphanum4, + "EUR", + trustLineIssuer.Address(), + ).Return(eurAssetStat, nil).Once() + + s.Assert().EqualError( + s.processor.Commit(s.ctx), + "row has no contract id to remove 67b1f192e30d8cd56dcb103c783cfee753588a434ad1092ef8a39375c9738bab: AssetTypeAssetTypeCreditAlphanum4 EUR GBRPYHIL2CI3FNQ4BXLFMNDLFJUNPU2HY3ZMFSHONUCEOASW7QC7OX2H", + ) +} + +func (s *AssetStatsProcessorTestSuiteLedger) TestUpdateTrustLine() { + lastModifiedLedgerSeq := xdr.Uint32(1234) + + trustLine := xdr.TrustLineEntry{ + AccountId: xdr.MustAddress("GAOQJGUAB7NI7K7I62ORBXMN3J4SSWQUQ7FOEPSDJ322W2HMCNWPHXFB"), + Asset: xdr.MustNewCreditAsset("EUR", trustLineIssuer.Address()).ToTrustLineAsset(), + Balance: 0, + Flags: xdr.Uint32(xdr.TrustLineFlagsAuthorizedFlag), + } + updatedTrustLine := xdr.TrustLineEntry{ + AccountId: xdr.MustAddress("GAOQJGUAB7NI7K7I62ORBXMN3J4SSWQUQ7FOEPSDJ322W2HMCNWPHXFB"), + Asset: xdr.MustNewCreditAsset("EUR", trustLineIssuer.Address()).ToTrustLineAsset(), + Balance: 10, + Flags: xdr.Uint32(xdr.TrustLineFlagsAuthorizedFlag), + } + + err := s.processor.ProcessChange(s.ctx, ingest.Change{ + Type: xdr.LedgerEntryTypeTrustline, + Pre: &xdr.LedgerEntry{ + LastModifiedLedgerSeq: lastModifiedLedgerSeq, + Data: xdr.LedgerEntryData{ + Type: xdr.LedgerEntryTypeTrustline, + TrustLine: &trustLine, + }, + }, + Post: &xdr.LedgerEntry{ + LastModifiedLedgerSeq: lastModifiedLedgerSeq, + Data: xdr.LedgerEntryData{ + Type: xdr.LedgerEntryTypeTrustline, + TrustLine: &updatedTrustLine, + }, + }, + }) + s.Assert().NoError(err) + + s.mockQ.On("GetAssetStat", s.ctx, + xdr.AssetTypeAssetTypeCreditAlphanum4, + "EUR", + trustLineIssuer.Address(), + ).Return(history.ExpAssetStat{ + AssetType: xdr.AssetTypeAssetTypeCreditAlphanum4, + AssetIssuer: trustLineIssuer.Address(), + AssetCode: "EUR", + Accounts: history.ExpAssetStatAccounts{Authorized: 1}, + Balances: history.ExpAssetStatBalances{ + Authorized: "100", + AuthorizedToMaintainLiabilities: "0", + Unauthorized: "0", + ClaimableBalances: "0", + LiquidityPools: "0", + }, + Amount: "100", + NumAccounts: 1, + }, nil).Once() + s.mockQ.On("UpdateAssetStat", s.ctx, history.ExpAssetStat{ + AssetType: xdr.AssetTypeAssetTypeCreditAlphanum4, + AssetIssuer: trustLineIssuer.Address(), + AssetCode: "EUR", + Accounts: history.ExpAssetStatAccounts{Authorized: 1}, + Balances: history.ExpAssetStatBalances{ + Authorized: "110", + AuthorizedToMaintainLiabilities: "0", + Unauthorized: "0", + ClaimableBalances: "0", + LiquidityPools: "0", + }, + Amount: "110", + NumAccounts: 1, + }).Return(int64(1), nil).Once() + + s.mockQ.On("RemoveContractAssetBalances", s.ctx, []xdr.Hash(nil)). + Return(nil).Once() + s.mockQ.On("UpdateContractAssetBalanceAmounts", s.ctx, []xdr.Hash{}, []string{}). + Return(nil).Once() + s.mockQ.On("InsertContractAssetBalances", s.ctx, []history.ContractAssetBalance(nil)). + Return(nil).Once() + s.mockQ.On("UpdateContractAssetBalanceExpirations", s.ctx, []xdr.Hash{}, []uint32{}). + Return(nil).Once() + s.mockQ.On("GetContractAssetBalancesExpiringAt", s.ctx, uint32(1234)). + Return([]history.ContractAssetBalance{}, nil).Once() + + s.Assert().NoError(s.processor.Commit(s.ctx)) +} + +func (s *AssetStatsProcessorTestSuiteLedger) TestUpdateTrustLineAuthorization() { + lastModifiedLedgerSeq := xdr.Uint32(1234) + + // EUR trustline: 100 unauthorized -> 10 authorized + eurTrustLine := xdr.TrustLineEntry{ + AccountId: xdr.MustAddress("GAOQJGUAB7NI7K7I62ORBXMN3J4SSWQUQ7FOEPSDJ322W2HMCNWPHXFB"), + Asset: xdr.MustNewCreditAsset("EUR", trustLineIssuer.Address()).ToTrustLineAsset(), + Balance: 100, + } + eurUpdatedTrustLine := xdr.TrustLineEntry{ + AccountId: xdr.MustAddress("GAOQJGUAB7NI7K7I62ORBXMN3J4SSWQUQ7FOEPSDJ322W2HMCNWPHXFB"), + Asset: xdr.MustNewCreditAsset("EUR", trustLineIssuer.Address()).ToTrustLineAsset(), + Balance: 10, + Flags: xdr.Uint32(xdr.TrustLineFlagsAuthorizedFlag), + } + + // USD trustline: 100 authorized -> 10 unauthorized usdTrustLine := xdr.TrustLineEntry{ AccountId: xdr.MustAddress("GAOQJGUAB7NI7K7I62ORBXMN3J4SSWQUQ7FOEPSDJ322W2HMCNWPHXFB"), Asset: xdr.MustNewCreditAsset("USD", trustLineIssuer.Address()).ToTrustLineAsset(), @@ -893,6 +1910,17 @@ func (s *AssetStatsProcessorTestSuiteLedger) TestUpdateTrustLineAuthorization() NumAccounts: 0, }).Return(int64(1), nil).Once() + s.mockQ.On("RemoveContractAssetBalances", s.ctx, []xdr.Hash(nil)). + Return(nil).Once() + s.mockQ.On("UpdateContractAssetBalanceAmounts", s.ctx, []xdr.Hash{}, []string{}). + Return(nil).Once() + s.mockQ.On("InsertContractAssetBalances", s.ctx, []history.ContractAssetBalance(nil)). + Return(nil).Once() + s.mockQ.On("UpdateContractAssetBalanceExpirations", s.ctx, []xdr.Hash{}, []uint32{}). + Return(nil).Once() + s.mockQ.On("GetContractAssetBalancesExpiringAt", s.ctx, uint32(1234)). + Return([]history.ContractAssetBalance{}, nil).Once() + s.Assert().NoError(s.processor.Commit(s.ctx)) } @@ -927,11 +1955,127 @@ func (s *AssetStatsProcessorTestSuiteLedger) TestRemoveClaimableBalance() { s.Assert().NoError(err) err = s.processor.ProcessChange(s.ctx, ingest.Change{ - Type: xdr.LedgerEntryTypeClaimableBalance, + Type: xdr.LedgerEntryTypeClaimableBalance, + Pre: &xdr.LedgerEntry{ + Data: xdr.LedgerEntryData{ + Type: xdr.LedgerEntryTypeClaimableBalance, + ClaimableBalance: &usdClaimableBalance, + }, + }, + Post: nil, + }) + s.Assert().NoError(err) + + s.mockQ.On("GetAssetStat", s.ctx, + xdr.AssetTypeAssetTypeCreditAlphanum4, + "EUR", + trustLineIssuer.Address(), + ).Return(history.ExpAssetStat{ + AssetType: xdr.AssetTypeAssetTypeCreditAlphanum4, + AssetIssuer: trustLineIssuer.Address(), + AssetCode: "EUR", + Accounts: history.ExpAssetStatAccounts{ + ClaimableBalances: 1, + }, + Balances: history.ExpAssetStatBalances{ + Authorized: "0", + AuthorizedToMaintainLiabilities: "0", + Unauthorized: "0", + ClaimableBalances: "12", + LiquidityPools: "0", + }, + Amount: "0", + NumAccounts: 0, + }, nil).Once() + s.mockQ.On("RemoveAssetStat", s.ctx, + xdr.AssetTypeAssetTypeCreditAlphanum4, + "EUR", + trustLineIssuer.Address(), + ).Return(int64(1), nil).Once() + + s.mockQ.On("GetAssetStat", s.ctx, + xdr.AssetTypeAssetTypeCreditAlphanum4, + "USD", + trustLineIssuer.Address(), + ).Return(history.ExpAssetStat{ + AssetType: xdr.AssetTypeAssetTypeCreditAlphanum4, + AssetIssuer: trustLineIssuer.Address(), + AssetCode: "USD", + Accounts: history.ExpAssetStatAccounts{ + Unauthorized: 1, + ClaimableBalances: 1, + }, + Balances: history.ExpAssetStatBalances{ + Authorized: "0", + AuthorizedToMaintainLiabilities: "0", + Unauthorized: "0", + ClaimableBalances: "21", + LiquidityPools: "0", + }, + Amount: "0", + NumAccounts: 0, + }, nil).Once() + s.mockQ.On("UpdateAssetStat", s.ctx, history.ExpAssetStat{ + AssetType: xdr.AssetTypeAssetTypeCreditAlphanum4, + AssetIssuer: trustLineIssuer.Address(), + AssetCode: "USD", + Accounts: history.ExpAssetStatAccounts{Unauthorized: 1}, + Balances: history.ExpAssetStatBalances{ + Authorized: "0", + AuthorizedToMaintainLiabilities: "0", + Unauthorized: "0", + ClaimableBalances: "0", + LiquidityPools: "0", + }, + Amount: "0", + NumAccounts: 0, + }).Return(int64(1), nil).Once() + + s.mockQ.On("RemoveContractAssetBalances", s.ctx, []xdr.Hash(nil)). + Return(nil).Once() + s.mockQ.On("UpdateContractAssetBalanceAmounts", s.ctx, []xdr.Hash{}, []string{}). + Return(nil).Once() + s.mockQ.On("InsertContractAssetBalances", s.ctx, []history.ContractAssetBalance(nil)). + Return(nil).Once() + s.mockQ.On("UpdateContractAssetBalanceExpirations", s.ctx, []xdr.Hash{}, []uint32{}). + Return(nil).Once() + s.mockQ.On("GetContractAssetBalancesExpiringAt", s.ctx, uint32(1234)). + Return([]history.ContractAssetBalance{}, nil).Once() + + s.Assert().NoError(s.processor.Commit(s.ctx)) +} + +func (s *AssetStatsProcessorTestSuiteLedger) TestRemoveTrustLine() { + authorizedTrustLine := xdr.TrustLineEntry{ + AccountId: xdr.MustAddress("GAOQJGUAB7NI7K7I62ORBXMN3J4SSWQUQ7FOEPSDJ322W2HMCNWPHXFB"), + Asset: xdr.MustNewCreditAsset("EUR", trustLineIssuer.Address()).ToTrustLineAsset(), + Balance: 0, + Flags: xdr.Uint32(xdr.TrustLineFlagsAuthorizedFlag), + } + unauthorizedTrustLine := xdr.TrustLineEntry{ + AccountId: xdr.MustAddress("GAOQJGUAB7NI7K7I62ORBXMN3J4SSWQUQ7FOEPSDJ322W2HMCNWPHXFB"), + Asset: xdr.MustNewCreditAsset("USD", trustLineIssuer.Address()).ToTrustLineAsset(), + Balance: 0, + } + + err := s.processor.ProcessChange(s.ctx, ingest.Change{ + Type: xdr.LedgerEntryTypeTrustline, + Pre: &xdr.LedgerEntry{ + Data: xdr.LedgerEntryData{ + Type: xdr.LedgerEntryTypeTrustline, + TrustLine: &authorizedTrustLine, + }, + }, + Post: nil, + }) + s.Assert().NoError(err) + + err = s.processor.ProcessChange(s.ctx, ingest.Change{ + Type: xdr.LedgerEntryTypeTrustline, Pre: &xdr.LedgerEntry{ Data: xdr.LedgerEntryData{ - Type: xdr.LedgerEntryTypeClaimableBalance, - ClaimableBalance: &usdClaimableBalance, + Type: xdr.LedgerEntryTypeTrustline, + TrustLine: &unauthorizedTrustLine, }, }, Post: nil, @@ -947,17 +2091,17 @@ func (s *AssetStatsProcessorTestSuiteLedger) TestRemoveClaimableBalance() { AssetIssuer: trustLineIssuer.Address(), AssetCode: "EUR", Accounts: history.ExpAssetStatAccounts{ - ClaimableBalances: 1, + Authorized: 1, }, Balances: history.ExpAssetStatBalances{ Authorized: "0", AuthorizedToMaintainLiabilities: "0", Unauthorized: "0", - ClaimableBalances: "12", + ClaimableBalances: "0", LiquidityPools: "0", }, Amount: "0", - NumAccounts: 0, + NumAccounts: 1, }, nil).Once() s.mockQ.On("RemoveAssetStat", s.ctx, xdr.AssetTypeAssetTypeCreditAlphanum4, @@ -974,86 +2118,219 @@ func (s *AssetStatsProcessorTestSuiteLedger) TestRemoveClaimableBalance() { AssetIssuer: trustLineIssuer.Address(), AssetCode: "USD", Accounts: history.ExpAssetStatAccounts{ - Unauthorized: 1, - ClaimableBalances: 1, + Unauthorized: 1, }, Balances: history.ExpAssetStatBalances{ Authorized: "0", AuthorizedToMaintainLiabilities: "0", Unauthorized: "0", - ClaimableBalances: "21", + ClaimableBalances: "0", LiquidityPools: "0", }, Amount: "0", NumAccounts: 0, }, nil).Once() - s.mockQ.On("UpdateAssetStat", s.ctx, history.ExpAssetStat{ + s.mockQ.On("RemoveAssetStat", s.ctx, + xdr.AssetTypeAssetTypeCreditAlphanum4, + "USD", + trustLineIssuer.Address(), + ).Return(int64(1), nil).Once() + + s.mockQ.On("RemoveContractAssetBalances", s.ctx, []xdr.Hash(nil)). + Return(nil).Once() + s.mockQ.On("UpdateContractAssetBalanceAmounts", s.ctx, []xdr.Hash{}, []string{}). + Return(nil).Once() + s.mockQ.On("InsertContractAssetBalances", s.ctx, []history.ContractAssetBalance(nil)). + Return(nil).Once() + s.mockQ.On("UpdateContractAssetBalanceExpirations", s.ctx, []xdr.Hash{}, []uint32{}). + Return(nil).Once() + s.mockQ.On("GetContractAssetBalancesExpiringAt", s.ctx, uint32(1234)). + Return([]history.ContractAssetBalance{}, nil).Once() + + s.Assert().NoError(s.processor.Commit(s.ctx)) +} + +func (s *AssetStatsProcessorTestSuiteLedger) TestRemoveContractID() { + lastModifiedLedgerSeq := xdr.Uint32(1234) + + eurID, err := xdr.MustNewCreditAsset("EUR", trustLineIssuer.Address()).ContractID("") + s.Assert().NoError(err) + eurContractData, err := AssetToContractData(false, "EUR", trustLineIssuer.Address(), eurID) + s.Assert().NoError(err) + + err = s.processor.ProcessChange(s.ctx, ingest.Change{ + Type: xdr.LedgerEntryTypeContractData, + Pre: &xdr.LedgerEntry{ + LastModifiedLedgerSeq: lastModifiedLedgerSeq, + Data: eurContractData, + }, + }) + s.Assert().NoError(err) + + eurAssetStat := history.ExpAssetStat{ AssetType: xdr.AssetTypeAssetTypeCreditAlphanum4, AssetIssuer: trustLineIssuer.Address(), - AssetCode: "USD", - Accounts: history.ExpAssetStatAccounts{Unauthorized: 1}, + AssetCode: "EUR", + Accounts: history.ExpAssetStatAccounts{Authorized: 1}, Balances: history.ExpAssetStatBalances{ - Authorized: "0", + Authorized: "100", AuthorizedToMaintainLiabilities: "0", Unauthorized: "0", ClaimableBalances: "0", LiquidityPools: "0", }, - Amount: "0", - NumAccounts: 0, - }).Return(int64(1), nil).Once() + Amount: "100", + NumAccounts: 1, + } + eurAssetStat.SetContractID(eurID) + s.mockQ.On("GetAssetStatByContract", s.ctx, xdr.Hash(eurID)). + Return(eurAssetStat, nil).Once() + + eurAssetStat.ContractID = nil + s.mockQ.On("UpdateAssetStat", s.ctx, mock.MatchedBy(func(assetStat history.ExpAssetStat) bool { + return eurAssetStat.Equals(assetStat) + })).Return(int64(1), nil).Once() + + s.mockQ.On("RemoveContractAssetBalances", s.ctx, []xdr.Hash(nil)). + Return(nil).Once() + s.mockQ.On("UpdateContractAssetBalanceAmounts", s.ctx, []xdr.Hash{}, []string{}). + Return(nil).Once() + s.mockQ.On("InsertContractAssetBalances", s.ctx, []history.ContractAssetBalance(nil)). + Return(nil).Once() + s.mockQ.On("UpdateContractAssetBalanceExpirations", s.ctx, []xdr.Hash{}, []uint32{}). + Return(nil).Once() + s.mockQ.On("GetContractAssetBalancesExpiringAt", s.ctx, uint32(1234)). + Return([]history.ContractAssetBalance{}, nil).Once() s.Assert().NoError(s.processor.Commit(s.ctx)) } -func (s *AssetStatsProcessorTestSuiteLedger) TestRemoveTrustLine() { - authorizedTrustLine := xdr.TrustLineEntry{ +func (s *AssetStatsProcessorTestSuiteLedger) TestUpdateTrustlineAndRemoveContractID() { + lastModifiedLedgerSeq := xdr.Uint32(1234) + + eurID, err := xdr.MustNewCreditAsset("EUR", trustLineIssuer.Address()).ContractID("") + s.Assert().NoError(err) + eurContractData, err := AssetToContractData(false, "EUR", trustLineIssuer.Address(), eurID) + s.Assert().NoError(err) + + err = s.processor.ProcessChange(s.ctx, ingest.Change{ + Type: xdr.LedgerEntryTypeContractData, + Pre: &xdr.LedgerEntry{ + LastModifiedLedgerSeq: lastModifiedLedgerSeq, + Data: eurContractData, + }, + }) + s.Assert().NoError(err) + + trustLine := xdr.TrustLineEntry{ AccountId: xdr.MustAddress("GAOQJGUAB7NI7K7I62ORBXMN3J4SSWQUQ7FOEPSDJ322W2HMCNWPHXFB"), Asset: xdr.MustNewCreditAsset("EUR", trustLineIssuer.Address()).ToTrustLineAsset(), Balance: 0, Flags: xdr.Uint32(xdr.TrustLineFlagsAuthorizedFlag), } - unauthorizedTrustLine := xdr.TrustLineEntry{ + updatedTrustLine := xdr.TrustLineEntry{ AccountId: xdr.MustAddress("GAOQJGUAB7NI7K7I62ORBXMN3J4SSWQUQ7FOEPSDJ322W2HMCNWPHXFB"), - Asset: xdr.MustNewCreditAsset("USD", trustLineIssuer.Address()).ToTrustLineAsset(), - Balance: 0, + Asset: xdr.MustNewCreditAsset("EUR", trustLineIssuer.Address()).ToTrustLineAsset(), + Balance: 10, + Flags: xdr.Uint32(xdr.TrustLineFlagsAuthorizedFlag), } - err := s.processor.ProcessChange(s.ctx, ingest.Change{ + err = s.processor.ProcessChange(s.ctx, ingest.Change{ Type: xdr.LedgerEntryTypeTrustline, Pre: &xdr.LedgerEntry{ + LastModifiedLedgerSeq: lastModifiedLedgerSeq, Data: xdr.LedgerEntryData{ Type: xdr.LedgerEntryTypeTrustline, - TrustLine: &authorizedTrustLine, + TrustLine: &trustLine, }, }, - Post: nil, - }) - s.Assert().NoError(err) - - err = s.processor.ProcessChange(s.ctx, ingest.Change{ - Type: xdr.LedgerEntryTypeTrustline, - Pre: &xdr.LedgerEntry{ + Post: &xdr.LedgerEntry{ + LastModifiedLedgerSeq: lastModifiedLedgerSeq, Data: xdr.LedgerEntryData{ Type: xdr.LedgerEntryTypeTrustline, - TrustLine: &unauthorizedTrustLine, + TrustLine: &updatedTrustLine, }, }, - Post: nil, }) s.Assert().NoError(err) + eurAssetStat := history.ExpAssetStat{ + AssetType: xdr.AssetTypeAssetTypeCreditAlphanum4, + AssetIssuer: trustLineIssuer.Address(), + AssetCode: "EUR", + Accounts: history.ExpAssetStatAccounts{Authorized: 1}, + Balances: history.ExpAssetStatBalances{ + Authorized: "100", + AuthorizedToMaintainLiabilities: "0", + Unauthorized: "0", + ClaimableBalances: "0", + LiquidityPools: "0", + }, + Amount: "100", + NumAccounts: 1, + } + eurAssetStat.SetContractID(eurID) s.mockQ.On("GetAssetStat", s.ctx, xdr.AssetTypeAssetTypeCreditAlphanum4, "EUR", trustLineIssuer.Address(), - ).Return(history.ExpAssetStat{ + ).Return(eurAssetStat, nil).Once() + + eurAssetStat = history.ExpAssetStat{ AssetType: xdr.AssetTypeAssetTypeCreditAlphanum4, AssetIssuer: trustLineIssuer.Address(), AssetCode: "EUR", - Accounts: history.ExpAssetStatAccounts{ - Authorized: 1, + Accounts: history.ExpAssetStatAccounts{Authorized: 1}, + Balances: history.ExpAssetStatBalances{ + Authorized: "110", + AuthorizedToMaintainLiabilities: "0", + Unauthorized: "0", + ClaimableBalances: "0", + LiquidityPools: "0", + }, + Amount: "110", + NumAccounts: 1, + } + s.mockQ.On("UpdateAssetStat", s.ctx, mock.MatchedBy(func(assetStat history.ExpAssetStat) bool { + return eurAssetStat.Equals(assetStat) + })).Return(int64(1), nil).Once() + + s.mockQ.On("RemoveContractAssetBalances", s.ctx, []xdr.Hash(nil)). + Return(nil).Once() + s.mockQ.On("UpdateContractAssetBalanceAmounts", s.ctx, []xdr.Hash{}, []string{}). + Return(nil).Once() + s.mockQ.On("InsertContractAssetBalances", s.ctx, []history.ContractAssetBalance(nil)). + Return(nil).Once() + s.mockQ.On("UpdateContractAssetBalanceExpirations", s.ctx, []xdr.Hash{}, []uint32{}). + Return(nil).Once() + s.mockQ.On("GetContractAssetBalancesExpiringAt", s.ctx, uint32(1234)). + Return([]history.ContractAssetBalance{}, nil).Once() + + s.Assert().NoError(s.processor.Commit(s.ctx)) +} + +func (s *AssetStatsProcessorTestSuiteLedger) TestRemoveContractIDFromZeroRow() { + lastModifiedLedgerSeq := xdr.Uint32(1234) + + eurID, err := xdr.MustNewCreditAsset("EUR", trustLineIssuer.Address()).ContractID("") + s.Assert().NoError(err) + eurContractData, err := AssetToContractData(false, "EUR", trustLineIssuer.Address(), eurID) + s.Assert().NoError(err) + + err = s.processor.ProcessChange(s.ctx, ingest.Change{ + Type: xdr.LedgerEntryTypeContractData, + Pre: &xdr.LedgerEntry{ + LastModifiedLedgerSeq: lastModifiedLedgerSeq, + Data: eurContractData, }, + }) + s.Assert().NoError(err) + + eurAssetStat := history.ExpAssetStat{ + AssetType: xdr.AssetTypeAssetTypeCreditAlphanum4, + AssetIssuer: trustLineIssuer.Address(), + AssetCode: "EUR", + Accounts: history.ExpAssetStatAccounts{}, Balances: history.ExpAssetStatBalances{ Authorized: "0", AuthorizedToMaintainLiabilities: "0", @@ -1062,24 +2339,189 @@ func (s *AssetStatsProcessorTestSuiteLedger) TestRemoveTrustLine() { LiquidityPools: "0", }, Amount: "0", - NumAccounts: 1, - }, nil).Once() + NumAccounts: 0, + } + eurAssetStat.SetContractID(eurID) + s.mockQ.On("GetAssetStatByContract", s.ctx, xdr.Hash(eurID)). + Return(eurAssetStat, nil).Once() + s.mockQ.On("RemoveAssetStat", s.ctx, xdr.AssetTypeAssetTypeCreditAlphanum4, "EUR", trustLineIssuer.Address(), ).Return(int64(1), nil).Once() - s.mockQ.On("GetAssetStat", s.ctx, + s.mockQ.On("RemoveContractAssetBalances", s.ctx, []xdr.Hash(nil)). + Return(nil).Once() + s.mockQ.On("UpdateContractAssetBalanceAmounts", s.ctx, []xdr.Hash{}, []string{}). + Return(nil).Once() + s.mockQ.On("InsertContractAssetBalances", s.ctx, []history.ContractAssetBalance(nil)). + Return(nil).Once() + s.mockQ.On("UpdateContractAssetBalanceExpirations", s.ctx, []xdr.Hash{}, []uint32{}). + Return(nil).Once() + s.mockQ.On("GetContractAssetBalancesExpiringAt", s.ctx, uint32(1234)). + Return([]history.ContractAssetBalance{}, nil).Once() + + s.Assert().NoError(s.processor.Commit(s.ctx)) +} + +func (s *AssetStatsProcessorTestSuiteLedger) TestRemoveContractIDAndBalanceZeroRow() { + lastModifiedLedgerSeq := xdr.Uint32(1234) + + eurID, err := xdr.MustNewCreditAsset("EUR", trustLineIssuer.Address()).ContractID("") + s.Assert().NoError(err) + eurContractData, err := AssetToContractData(false, "EUR", trustLineIssuer.Address(), eurID) + s.Assert().NoError(err) + + err = s.processor.ProcessChange(s.ctx, ingest.Change{ + Type: xdr.LedgerEntryTypeContractData, + Pre: &xdr.LedgerEntry{ + LastModifiedLedgerSeq: lastModifiedLedgerSeq, + Data: eurContractData, + }, + }) + s.Assert().NoError(err) + + s.Assert().NoError(s.processor.ProcessChange(s.ctx, ingest.Change{ + Type: xdr.LedgerEntryTypeContractData, + Pre: &xdr.LedgerEntry{ + LastModifiedLedgerSeq: lastModifiedLedgerSeq, + Data: BalanceToContractData(eurID, [32]byte{1}, 9), + }, + })) + keyHash := getKeyHashForBalance(s.T(), eurID, [32]byte{1}) + s.Assert().NoError(s.processor.ProcessChange(s.ctx, ingest.Change{ + Type: xdr.LedgerEntryTypeTtl, + Pre: &xdr.LedgerEntry{ + LastModifiedLedgerSeq: lastModifiedLedgerSeq, + Data: xdr.LedgerEntryData{ + Type: xdr.LedgerEntryTypeTtl, + Ttl: &xdr.TtlEntry{ + KeyHash: keyHash, + LiveUntilLedgerSeq: 2234, + }, + }, + }, + })) + + s.Assert().NoError(s.processor.ProcessChange(s.ctx, ingest.Change{ + Type: xdr.LedgerEntryTypeContractData, + Pre: &xdr.LedgerEntry{ + LastModifiedLedgerSeq: lastModifiedLedgerSeq, + Data: BalanceToContractData(eurID, [32]byte{2}, 1), + }, + })) + otherKeyHash := getKeyHashForBalance(s.T(), eurID, [32]byte{2}) + s.Assert().NoError(s.processor.ProcessChange(s.ctx, ingest.Change{ + Type: xdr.LedgerEntryTypeTtl, + Pre: &xdr.LedgerEntry{ + LastModifiedLedgerSeq: lastModifiedLedgerSeq, + Data: xdr.LedgerEntryData{ + Type: xdr.LedgerEntryTypeTtl, + Ttl: &xdr.TtlEntry{ + KeyHash: otherKeyHash, + LiveUntilLedgerSeq: 2234, + }, + }, + }, + })) + + eurAssetStat := history.ExpAssetStat{ + AssetType: xdr.AssetTypeAssetTypeCreditAlphanum4, + AssetIssuer: trustLineIssuer.Address(), + AssetCode: "EUR", + Accounts: history.ExpAssetStatAccounts{}, + Balances: history.ExpAssetStatBalances{ + Authorized: "0", + AuthorizedToMaintainLiabilities: "0", + Unauthorized: "0", + ClaimableBalances: "0", + LiquidityPools: "0", + }, + Amount: "0", + NumAccounts: 0, + } + eurAssetStat.SetContractID(eurID) + s.mockQ.On("GetAssetStatByContract", s.ctx, xdr.Hash(eurID)). + Return(eurAssetStat, nil).Once() + + s.mockQ.On("RemoveAssetStat", s.ctx, xdr.AssetTypeAssetTypeCreditAlphanum4, - "USD", + "EUR", trustLineIssuer.Address(), - ).Return(history.ExpAssetStat{ + ).Return(int64(1), nil).Once() + + eurAssetContractStat := history.ContractAssetStatRow{ + ContractID: eurID[:], + Stat: history.ContractStat{ + ActiveBalance: "10", + ActiveHolders: 2, + ArchivedBalance: "0", + ArchivedHolders: 0, + }, + } + s.mockQ.On("GetContractAssetStat", s.ctx, eurID[:]). + Return(eurAssetContractStat, nil).Once() + s.mockQ.On("RemoveAssetContractStat", s.ctx, eurID[:]). + Return(int64(1), nil).Once() + + s.mockQ.On("RemoveContractAssetBalances", s.ctx, mock.MatchedBy(func(keys []xdr.Hash) bool { + return assert.ElementsMatch(s.T(), []xdr.Hash{keyHash, otherKeyHash}, keys) + })). + Return(nil).Once() + s.mockQ.On("UpdateContractAssetBalanceAmounts", s.ctx, []xdr.Hash{}, []string{}). + Return(nil).Once() + s.mockQ.On("InsertContractAssetBalances", s.ctx, []history.ContractAssetBalance(nil)). + Return(nil).Once() + s.mockQ.On("UpdateContractAssetBalanceExpirations", s.ctx, []xdr.Hash{}, []uint32{}). + Return(nil).Once() + s.mockQ.On("GetContractAssetBalancesExpiringAt", s.ctx, uint32(1234)). + Return([]history.ContractAssetBalance{}, nil).Once() + + s.Assert().NoError(s.processor.Commit(s.ctx)) +} + +func (s *AssetStatsProcessorTestSuiteLedger) TestRemoveContractIDAndRow() { + lastModifiedLedgerSeq := xdr.Uint32(1234) + + eurID, err := xdr.MustNewCreditAsset("EUR", trustLineIssuer.Address()).ContractID("") + s.Assert().NoError(err) + eurContractData, err := AssetToContractData(false, "EUR", trustLineIssuer.Address(), eurID) + s.Assert().NoError(err) + + err = s.processor.ProcessChange(s.ctx, ingest.Change{ + Type: xdr.LedgerEntryTypeContractData, + Pre: &xdr.LedgerEntry{ + LastModifiedLedgerSeq: lastModifiedLedgerSeq, + Data: eurContractData, + }, + }) + s.Assert().NoError(err) + + authorizedTrustLine := xdr.TrustLineEntry{ + AccountId: xdr.MustAddress("GAOQJGUAB7NI7K7I62ORBXMN3J4SSWQUQ7FOEPSDJ322W2HMCNWPHXFB"), + Asset: xdr.MustNewCreditAsset("EUR", trustLineIssuer.Address()).ToTrustLineAsset(), + Balance: 0, + Flags: xdr.Uint32(xdr.TrustLineFlagsAuthorizedFlag), + } + err = s.processor.ProcessChange(s.ctx, ingest.Change{ + Type: xdr.LedgerEntryTypeTrustline, + Pre: &xdr.LedgerEntry{ + Data: xdr.LedgerEntryData{ + Type: xdr.LedgerEntryTypeTrustline, + TrustLine: &authorizedTrustLine, + }, + }, + Post: nil, + }) + s.Assert().NoError(err) + + eurAssetStat := history.ExpAssetStat{ AssetType: xdr.AssetTypeAssetTypeCreditAlphanum4, AssetIssuer: trustLineIssuer.Address(), - AssetCode: "USD", + AssetCode: "EUR", Accounts: history.ExpAssetStatAccounts{ - Unauthorized: 1, + Authorized: 1, }, Balances: history.ExpAssetStatBalances{ Authorized: "0", @@ -1089,14 +2531,32 @@ func (s *AssetStatsProcessorTestSuiteLedger) TestRemoveTrustLine() { LiquidityPools: "0", }, Amount: "0", - NumAccounts: 0, - }, nil).Once() + NumAccounts: 1, + } + eurAssetStat.SetContractID(eurID) + s.mockQ.On("GetAssetStat", s.ctx, + xdr.AssetTypeAssetTypeCreditAlphanum4, + "EUR", + trustLineIssuer.Address(), + ).Return(eurAssetStat, nil).Once() + s.mockQ.On("RemoveAssetStat", s.ctx, xdr.AssetTypeAssetTypeCreditAlphanum4, - "USD", + "EUR", trustLineIssuer.Address(), ).Return(int64(1), nil).Once() + s.mockQ.On("RemoveContractAssetBalances", s.ctx, []xdr.Hash(nil)). + Return(nil).Once() + s.mockQ.On("UpdateContractAssetBalanceAmounts", s.ctx, []xdr.Hash{}, []string{}). + Return(nil).Once() + s.mockQ.On("InsertContractAssetBalances", s.ctx, []history.ContractAssetBalance(nil)). + Return(nil).Once() + s.mockQ.On("UpdateContractAssetBalanceExpirations", s.ctx, []xdr.Hash{}, []uint32{}). + Return(nil).Once() + s.mockQ.On("GetContractAssetBalancesExpiringAt", s.ctx, uint32(1234)). + Return([]history.ContractAssetBalance{}, nil).Once() + s.Assert().NoError(s.processor.Commit(s.ctx)) } @@ -1170,5 +2630,17 @@ func (s *AssetStatsProcessorTestSuiteLedger) TestProcessUpgradeChange() { Amount: "10", NumAccounts: 1, }).Return(int64(1), nil).Once() + + s.mockQ.On("RemoveContractAssetBalances", s.ctx, []xdr.Hash(nil)). + Return(nil).Once() + s.mockQ.On("UpdateContractAssetBalanceAmounts", s.ctx, []xdr.Hash{}, []string{}). + Return(nil).Once() + s.mockQ.On("InsertContractAssetBalances", s.ctx, []history.ContractAssetBalance(nil)). + Return(nil).Once() + s.mockQ.On("UpdateContractAssetBalanceExpirations", s.ctx, []xdr.Hash{}, []uint32{}). + Return(nil).Once() + s.mockQ.On("GetContractAssetBalancesExpiringAt", s.ctx, uint32(1234)). + Return([]history.ContractAssetBalance{}, nil).Once() + s.Assert().NoError(s.processor.Commit(s.ctx)) } diff --git a/services/horizon/internal/ingest/processors/asset_stats_set.go b/services/horizon/internal/ingest/processors/asset_stats_set.go index 672e387e56..bc27c2a4ef 100644 --- a/services/horizon/internal/ingest/processors/asset_stats_set.go +++ b/services/horizon/internal/ingest/processors/asset_stats_set.go @@ -4,7 +4,6 @@ import ( "math/big" "github.com/stellar/go/ingest" - "github.com/stellar/go/services/horizon/internal/db2/history" "github.com/stellar/go/support/errors" "github.com/stellar/go/xdr" @@ -30,7 +29,17 @@ type assetStatBalances struct { Unauthorized *big.Int } -func (a *assetStatBalances) Parse(b *history.ExpAssetStatBalances) error { +func newAssetStatBalance() assetStatBalances { + return assetStatBalances{ + Authorized: big.NewInt(0), + AuthorizedToMaintainLiabilities: big.NewInt(0), + ClaimableBalances: big.NewInt(0), + LiquidityPools: big.NewInt(0), + Unauthorized: big.NewInt(0), + } +} + +func (a *assetStatBalances) Parse(b history.ExpAssetStatBalances) error { authorized, ok := new(big.Int).SetString(b.Authorized, 10) if !ok { return errors.New("Error parsing: " + b.Authorized) @@ -105,8 +114,19 @@ func (value assetStatValue) ConvertToHistoryObject() history.ExpAssetStat { } } -// AssetStatSet represents a collection of asset stats -type AssetStatSet map[assetStatKey]*assetStatValue +// AssetStatSet represents a collection of asset stats and a mapping +// of Soroban contract IDs to classic assets (which is unique to each +// network). +type AssetStatSet struct { + classicAssetStats map[assetStatKey]*assetStatValue +} + +// NewAssetStatSet constructs a new AssetStatSet instance +func NewAssetStatSet() AssetStatSet { + return AssetStatSet{ + classicAssetStats: map[assetStatKey]*assetStatValue{}, + } +} type delta struct { Authorized int64 @@ -142,16 +162,10 @@ func (s AssetStatSet) addDelta(asset xdr.Asset, deltaBalances, deltaAccounts del return errors.Wrap(err, "could not extract asset info from trustline") } - current, ok := s[key] + current, ok := s.classicAssetStats[key] if !ok { - current = &assetStatValue{assetStatKey: key, balances: assetStatBalances{ - Authorized: big.NewInt(0), - AuthorizedToMaintainLiabilities: big.NewInt(0), - ClaimableBalances: big.NewInt(0), - LiquidityPools: big.NewInt(0), - Unauthorized: big.NewInt(0), - }} - s[key] = current + current = &assetStatValue{assetStatKey: key, balances: newAssetStatBalance()} + s.classicAssetStats[key] = current } current.accounts.Authorized += int32(deltaAccounts.Authorized) @@ -171,7 +185,7 @@ func (s AssetStatSet) addDelta(asset xdr.Asset, deltaBalances, deltaAccounts del // OR // numAccounts == 0 && amount != 0 (ex. issuer issued an asset) if current.balances.IsZero() && current.accounts.IsZero() { - delete(s, key) + delete(s.classicAssetStats, key) } return nil @@ -206,7 +220,7 @@ func (s AssetStatSet) AddTrustline(change ingest.Change) error { deltaAccounts.addByFlags(post.Flags, 1) deltaBalances.addByFlags(post.Flags, int64(post.Balance)) } - if asset.Type == xdr.AssetTypeAssetTypePoolShare { + if asset.Type == xdr.AssetTypeAssetTypePoolShare || asset.Type == xdr.AssetTypeAssetTypeNative { return nil } @@ -325,23 +339,11 @@ func (s AssetStatSet) AddClaimableBalance(change ingest.Change) error { return nil } -// Remove deletes an asset stat from the set -func (s AssetStatSet) Remove(assetType xdr.AssetType, assetCode string, assetIssuer string) (history.ExpAssetStat, bool) { - key := assetStatKey{assetType: assetType, assetIssuer: assetIssuer, assetCode: assetCode} - value, ok := s[key] - if !ok { - return history.ExpAssetStat{}, false - } - - delete(s, key) - - return value.ConvertToHistoryObject(), true -} - // All returns a list of all `history.ExpAssetStat` contained within the set +// along with all contract id attribution changes in the set. func (s AssetStatSet) All() []history.ExpAssetStat { - assetStats := make([]history.ExpAssetStat, 0, len(s)) - for _, value := range s { + assetStats := make([]history.ExpAssetStat, 0, len(s.classicAssetStats)) + for _, value := range s.classicAssetStats { assetStats = append(assetStats, value.ConvertToHistoryObject()) } return assetStats diff --git a/services/horizon/internal/ingest/processors/asset_stats_set_test.go b/services/horizon/internal/ingest/processors/asset_stats_set_test.go index 0c247593d6..f9989fdc9e 100644 --- a/services/horizon/internal/ingest/processors/asset_stats_set_test.go +++ b/services/horizon/internal/ingest/processors/asset_stats_set_test.go @@ -13,34 +13,28 @@ import ( ) func TestEmptyAssetStatSet(t *testing.T) { - set := AssetStatSet{} - if all := set.All(); len(all) != 0 { - t.Fatalf("expected empty list but got %v", all) - } - - _, ok := set.Remove( - xdr.AssetTypeAssetTypeCreditAlphanum4, - "USD", - "GAOQJGUAB7NI7K7I62ORBXMN3J4SSWQUQ7FOEPSDJ322W2HMCNWPHXFB", - ) - if ok { - t.Fatal("expected remove to return false") - } + set := NewAssetStatSet() + all := set.All() + assert.Empty(t, all) } func assertAllEquals(t *testing.T, set AssetStatSet, expected []history.ExpAssetStat) { all := set.All() + assertAssetStatsAreEqual(t, all, expected) +} + +func assertAssetStatsAreEqual(t *testing.T, all []history.ExpAssetStat, expected []history.ExpAssetStat) { assert.Len(t, all, len(expected)) sort.Slice(all, func(i, j int) bool { return all[i].AssetCode < all[j].AssetCode }) for i, got := range all { - assert.Equal(t, expected[i], got) + assert.True(t, expected[i].Equals(got)) } } func TestAddNativeClaimableBalance(t *testing.T) { - set := AssetStatSet{} + set := NewAssetStatSet() claimableBalance := xdr.ClaimableBalanceEntry{ BalanceId: xdr.ClaimableBalanceId{}, Claimants: nil, @@ -56,7 +50,8 @@ func TestAddNativeClaimableBalance(t *testing.T) { }, }, )) - assert.Empty(t, set.All()) + all := set.All() + assert.Empty(t, all) } func trustlineChange(pre, post *xdr.TrustLineEntry) ingest.Change { @@ -79,7 +74,7 @@ func trustlineChange(pre, post *xdr.TrustLineEntry) ingest.Change { } func TestAddPoolShareTrustline(t *testing.T) { - set := AssetStatSet{} + set := NewAssetStatSet() assert.NoError( t, set.AddTrustline(trustlineChange(nil, &xdr.TrustLineEntry{ @@ -93,11 +88,12 @@ func TestAddPoolShareTrustline(t *testing.T) { }, )), ) - assert.Empty(t, set.All()) + all := set.All() + assert.Empty(t, all) } -func TestAddAndRemoveAssetStats(t *testing.T) { - set := AssetStatSet{} +func TestAddAssetStats(t *testing.T) { + set := NewAssetStatSet() eur := "EUR" eurAssetStat := history.ExpAssetStat{ AssetType: xdr.AssetTypeAssetTypeCreditAlphanum4, @@ -241,22 +237,10 @@ func TestAddAndRemoveAssetStats(t *testing.T) { }, } assertAllEquals(t, set, expected) - - for i, assetStat := range expected { - removed, ok := set.Remove(assetStat.AssetType, assetStat.AssetCode, assetStat.AssetIssuer) - if !ok { - t.Fatal("expected remove to return true") - } - if removed != assetStat { - t.Fatalf("expected removed asset stat to be %v but got %v", assetStat, removed) - } - - assertAllEquals(t, set, expected[i+1:]) - } } func TestOverflowAssetStatSet(t *testing.T) { - set := AssetStatSet{} + set := NewAssetStatSet() eur := "EUR" err := set.AddTrustline(trustlineChange(nil, &xdr.TrustLineEntry{ AccountId: xdr.MustAddress("GAOQJGUAB7NI7K7I62ORBXMN3J4SSWQUQ7FOEPSDJ322W2HMCNWPHXFB"), diff --git a/services/horizon/internal/ingest/processors/change_processors.go b/services/horizon/internal/ingest/processors/change_processors.go index 2e5b126d8f..ee9eb127f1 100644 --- a/services/horizon/internal/ingest/processors/change_processors.go +++ b/services/horizon/internal/ingest/processors/change_processors.go @@ -8,63 +8,6 @@ import ( "github.com/stellar/go/support/errors" ) -type ChangeProcessor interface { - ProcessChange(ctx context.Context, change ingest.Change) error -} - -type LedgerTransactionProcessor interface { - ProcessTransaction(ctx context.Context, transaction ingest.LedgerTransaction) error -} - -type LedgerTransactionFilterer interface { - FilterTransaction(ctx context.Context, transaction ingest.LedgerTransaction) (bool, error) -} - -func StreamLedgerTransactions( - ctx context.Context, - txFilterer LedgerTransactionFilterer, - filteredTxProcessor LedgerTransactionProcessor, - txProcessor LedgerTransactionProcessor, - reader *ingest.LedgerTransactionReader, -) error { - for { - tx, err := reader.Read() - if err == io.EOF { - return nil - } - if err != nil { - return errors.Wrap(err, "could not read transaction") - } - include, err := txFilterer.FilterTransaction(ctx, tx) - if err != nil { - return errors.Wrapf( - err, - "could not filter transaction %v", - tx.Index, - ) - } - if !include { - if err = filteredTxProcessor.ProcessTransaction(ctx, tx); err != nil { - return errors.Wrapf( - err, - "could not process transaction %v", - tx.Index, - ) - } - log.Debugf("Filters did not find match on transaction, dropping this tx with hash %v", tx.Result.TransactionHash.HexString()) - continue - } - - if err = txProcessor.ProcessTransaction(ctx, tx); err != nil { - return errors.Wrapf( - err, - "could not process transaction %v", - tx.Index, - ) - } - } -} - func StreamChanges( ctx context.Context, changeProcessor ChangeProcessor, diff --git a/services/horizon/internal/ingest/processors/claimable_balances_change_processor.go b/services/horizon/internal/ingest/processors/claimable_balances_change_processor.go index fae72f2c49..5d985e691e 100644 --- a/services/horizon/internal/ingest/processors/claimable_balances_change_processor.go +++ b/services/horizon/internal/ingest/processors/claimable_balances_change_processor.go @@ -2,6 +2,7 @@ package processors import ( "context" + "fmt" "github.com/stellar/go/ingest" "github.com/stellar/go/services/horizon/internal/db2/history" @@ -10,9 +11,11 @@ import ( ) type ClaimableBalancesChangeProcessor struct { - encodingBuffer *xdr.EncodingBuffer - qClaimableBalances history.QClaimableBalances - cache *ingest.ChangeCompactor + encodingBuffer *xdr.EncodingBuffer + qClaimableBalances history.QClaimableBalances + cache *ingest.ChangeCompactor + claimantsInsertBuilder history.ClaimableBalanceClaimantBatchInsertBuilder + claimableBalanceInsertBuilder history.ClaimableBalanceBatchInsertBuilder } func NewClaimableBalancesChangeProcessor(Q history.QClaimableBalances) *ClaimableBalancesChangeProcessor { @@ -26,6 +29,8 @@ func NewClaimableBalancesChangeProcessor(Q history.QClaimableBalances) *Claimabl func (p *ClaimableBalancesChangeProcessor) reset() { p.cache = ingest.NewChangeCompactor() + p.claimantsInsertBuilder = p.qClaimableBalances.NewClaimableBalanceClaimantBatchInsertBuilder() + p.claimableBalanceInsertBuilder = p.qClaimableBalances.NewClaimableBalanceBatchInsertBuilder() } func (p *ClaimableBalancesChangeProcessor) ProcessChange(ctx context.Context, change ingest.Change) error { @@ -43,15 +48,14 @@ func (p *ClaimableBalancesChangeProcessor) ProcessChange(ctx context.Context, ch if err != nil { return errors.Wrap(err, "error in Commit") } - p.reset() } return nil } func (p *ClaimableBalancesChangeProcessor) Commit(ctx context.Context) error { + defer p.reset() var ( - cbsToUpsert []history.ClaimableBalance cbIDsToDelete []string ) changes := p.cache.GetChanges() @@ -59,11 +63,27 @@ func (p *ClaimableBalancesChangeProcessor) Commit(ctx context.Context) error { switch { case change.Pre == nil && change.Post != nil: // Created - row, err := p.ledgerEntryToRow(change.Post) + cb, err := p.ledgerEntryToRow(change.Post) if err != nil { return err } - cbsToUpsert = append(cbsToUpsert, row) + // Add claimable balance + if err := p.claimableBalanceInsertBuilder.Add(cb); err != nil { + return errors.Wrap(err, "error adding to ClaimableBalanceBatchInsertBuilder") + } + + // Add claimants + for _, claimant := range cb.Claimants { + claimant := history.ClaimableBalanceClaimant{ + BalanceID: cb.BalanceID, + Destination: claimant.Destination, + LastModifiedLedger: cb.LastModifiedLedger, + } + + if err := p.claimantsInsertBuilder.Add(claimant); err != nil { + return errors.Wrap(err, "error adding to ClaimableBalanceClaimantBatchInsertBuilder") + } + } case change.Pre != nil && change.Post == nil: // Removed cBalance := change.Pre.Data.MustClaimableBalance() @@ -73,19 +93,19 @@ func (p *ClaimableBalancesChangeProcessor) Commit(ctx context.Context) error { } cbIDsToDelete = append(cbIDsToDelete, id) default: - // Updated - row, err := p.ledgerEntryToRow(change.Post) - if err != nil { - return err - } - cbsToUpsert = append(cbsToUpsert, row) + // claimable balance can only be created or removed + return fmt.Errorf("invalid change entry for a claimable balance was detected") } } - if len(cbsToUpsert) > 0 { - if err := p.qClaimableBalances.UpsertClaimableBalances(ctx, cbsToUpsert); err != nil { - return errors.Wrap(err, "error executing upsert") - } + err := p.claimantsInsertBuilder.Exec(ctx) + if err != nil { + return errors.Wrap(err, "error executing ClaimableBalanceClaimantBatchInsertBuilder") + } + + err = p.claimableBalanceInsertBuilder.Exec(ctx) + if err != nil { + return errors.Wrap(err, "error executing ClaimableBalanceBatchInsertBuilder") } if len(cbIDsToDelete) > 0 { @@ -100,6 +120,12 @@ func (p *ClaimableBalancesChangeProcessor) Commit(ctx context.Context) error { len(cbIDsToDelete), )) } + + // Remove ClaimableBalanceClaimants + _, err = p.qClaimableBalances.RemoveClaimableBalanceClaimants(ctx, cbIDsToDelete) + if err != nil { + return errors.Wrap(err, "error executing removal of claimants") + } } return nil diff --git a/services/horizon/internal/ingest/processors/claimable_balances_change_processor_test.go b/services/horizon/internal/ingest/processors/claimable_balances_change_processor_test.go index 0ece2661de..524de095f7 100644 --- a/services/horizon/internal/ingest/processors/claimable_balances_change_processor_test.go +++ b/services/horizon/internal/ingest/processors/claimable_balances_change_processor_test.go @@ -7,11 +7,11 @@ import ( "testing" "github.com/guregu/null" - "github.com/stretchr/testify/suite" "github.com/stellar/go/ingest" "github.com/stellar/go/services/horizon/internal/db2/history" "github.com/stellar/go/xdr" + "github.com/stretchr/testify/suite" ) func TestClaimableBalancesChangeProcessorTestSuiteState(t *testing.T) { @@ -20,14 +20,28 @@ func TestClaimableBalancesChangeProcessorTestSuiteState(t *testing.T) { type ClaimableBalancesChangeProcessorTestSuiteState struct { suite.Suite - ctx context.Context - processor *ClaimableBalancesChangeProcessor - mockQ *history.MockQClaimableBalances + ctx context.Context + processor *ClaimableBalancesChangeProcessor + mockQ *history.MockQClaimableBalances + mockClaimantsBatchInsertBuilder *history.MockClaimableBalanceClaimantBatchInsertBuilder + mockClaimableBalanceBatchInsertBuilder *history.MockClaimableBalanceBatchInsertBuilder } func (s *ClaimableBalancesChangeProcessorTestSuiteState) SetupTest() { s.ctx = context.Background() + s.mockClaimantsBatchInsertBuilder = &history.MockClaimableBalanceClaimantBatchInsertBuilder{} + s.mockClaimableBalanceBatchInsertBuilder = &history.MockClaimableBalanceBatchInsertBuilder{} + s.mockQ = &history.MockQClaimableBalances{} + s.mockQ. + On("NewClaimableBalanceClaimantBatchInsertBuilder"). + Return(s.mockClaimantsBatchInsertBuilder) + s.mockQ. + On("NewClaimableBalanceBatchInsertBuilder"). + Return(s.mockClaimableBalanceBatchInsertBuilder) + + s.mockClaimantsBatchInsertBuilder.On("Exec", s.ctx).Return(nil) + s.mockClaimableBalanceBatchInsertBuilder.On("Exec", s.ctx).Return(nil) s.processor = NewClaimableBalancesChangeProcessor(s.mockQ) } @@ -50,22 +64,40 @@ func (s *ClaimableBalancesChangeProcessorTestSuiteState) TestCreatesClaimableBal cBalance := xdr.ClaimableBalanceEntry{ BalanceId: balanceID, - Claimants: []xdr.Claimant{}, - Asset: xdr.MustNewCreditAsset("USD", "GC3C4AKRBQLHOJ45U4XG35ESVWRDECWO5XLDGYADO6DPR3L7KIDVUMML"), - Amount: 10, + Claimants: []xdr.Claimant{ + { + V0: &xdr.ClaimantV0{ + Destination: xdr.MustAddress("GC3C4AKRBQLHOJ45U4XG35ESVWRDECWO5XLDGYADO6DPR3L7KIDVUMML"), + }, + }, + }, + Asset: xdr.MustNewCreditAsset("USD", "GC3C4AKRBQLHOJ45U4XG35ESVWRDECWO5XLDGYADO6DPR3L7KIDVUMML"), + Amount: 10, } id, err := xdr.MarshalHex(balanceID) s.Assert().NoError(err) - s.mockQ.On("UpsertClaimableBalances", s.ctx, []history.ClaimableBalance{ - { - BalanceID: id, - Claimants: []history.Claimant{}, - Asset: cBalance.Asset, - Amount: cBalance.Amount, - LastModifiedLedger: uint32(lastModifiedLedgerSeq), + s.mockClaimableBalanceBatchInsertBuilder.On("Add", history.ClaimableBalance{ + BalanceID: id, + Claimants: []history.Claimant{ + { + Destination: "GC3C4AKRBQLHOJ45U4XG35ESVWRDECWO5XLDGYADO6DPR3L7KIDVUMML", + }, }, + Asset: cBalance.Asset, + Amount: cBalance.Amount, + LastModifiedLedger: uint32(lastModifiedLedgerSeq), }).Return(nil).Once() + s.mockClaimableBalanceBatchInsertBuilder.On("Exec", s.ctx).Return(nil).Once() + + s.mockClaimantsBatchInsertBuilder.On("Add", history.ClaimableBalanceClaimant{ + BalanceID: id, + Destination: "GC3C4AKRBQLHOJ45U4XG35ESVWRDECWO5XLDGYADO6DPR3L7KIDVUMML", + LastModifiedLedger: uint32(lastModifiedLedgerSeq), + }).Return(nil).Once() + + s.mockClaimantsBatchInsertBuilder.On("Exec", s.ctx).Return(nil).Once() + err = s.processor.ProcessChange(s.ctx, ingest.Change{ Type: xdr.LedgerEntryTypeClaimableBalance, Pre: nil, @@ -86,20 +118,34 @@ func TestClaimableBalancesChangeProcessorTestSuiteLedger(t *testing.T) { type ClaimableBalancesChangeProcessorTestSuiteLedger struct { suite.Suite - ctx context.Context - processor *ClaimableBalancesChangeProcessor - mockQ *history.MockQClaimableBalances + ctx context.Context + processor *ClaimableBalancesChangeProcessor + mockQ *history.MockQClaimableBalances + mockClaimantsBatchInsertBuilder *history.MockClaimableBalanceClaimantBatchInsertBuilder + mockClaimableBalanceBatchInsertBuilder *history.MockClaimableBalanceBatchInsertBuilder } func (s *ClaimableBalancesChangeProcessorTestSuiteLedger) SetupTest() { s.ctx = context.Background() + s.mockClaimantsBatchInsertBuilder = &history.MockClaimableBalanceClaimantBatchInsertBuilder{} + s.mockClaimableBalanceBatchInsertBuilder = &history.MockClaimableBalanceBatchInsertBuilder{} s.mockQ = &history.MockQClaimableBalances{} + s.mockQ. + On("NewClaimableBalanceClaimantBatchInsertBuilder"). + Return(s.mockClaimantsBatchInsertBuilder) + s.mockQ. + On("NewClaimableBalanceBatchInsertBuilder"). + Return(s.mockClaimableBalanceBatchInsertBuilder) + + s.mockClaimantsBatchInsertBuilder.On("Exec", s.ctx).Return(nil) + s.mockClaimableBalanceBatchInsertBuilder.On("Exec", s.ctx).Return(nil) s.processor = NewClaimableBalancesChangeProcessor(s.mockQ) } func (s *ClaimableBalancesChangeProcessorTestSuiteLedger) TearDownTest() { s.Assert().NoError(s.processor.Commit(s.ctx)) + s.processor.reset() s.mockQ.AssertExpectations(s.T()) } @@ -120,27 +166,6 @@ func (s *ClaimableBalancesChangeProcessorTestSuiteLedger) TestNewClaimableBalanc Amount: 10, } entry := xdr.LedgerEntry{ - Data: xdr.LedgerEntryData{ - Type: xdr.LedgerEntryTypeClaimableBalance, - ClaimableBalance: &cBalance, - }, - LastModifiedLedgerSeq: lastModifiedLedgerSeq, - Ext: xdr.LedgerEntryExt{ - V: 1, - V1: &xdr.LedgerEntryExtensionV1{ - SponsoringId: nil, - }, - }, - } - err := s.processor.ProcessChange(s.ctx, ingest.Change{ - Type: xdr.LedgerEntryTypeClaimableBalance, - Pre: nil, - Post: &entry, - }) - s.Assert().NoError(err) - - // add sponsor - updated := xdr.LedgerEntry{ Data: xdr.LedgerEntryData{ Type: xdr.LedgerEntryTypeClaimableBalance, ClaimableBalance: &cBalance, @@ -154,98 +179,28 @@ func (s *ClaimableBalancesChangeProcessorTestSuiteLedger) TestNewClaimableBalanc }, } - entry.LastModifiedLedgerSeq = entry.LastModifiedLedgerSeq - 1 - err = s.processor.ProcessChange(s.ctx, ingest.Change{ - Type: xdr.LedgerEntryTypeClaimableBalance, - Pre: &entry, - Post: &updated, - }) - s.Assert().NoError(err) - id, err := xdr.MarshalHex(balanceID) s.Assert().NoError(err) + // We use LedgerEntryChangesCache so all changes are squashed - s.mockQ.On( - "UpsertClaimableBalances", - s.ctx, - []history.ClaimableBalance{ - { - BalanceID: id, - Claimants: []history.Claimant{}, - Asset: cBalance.Asset, - Amount: cBalance.Amount, - LastModifiedLedger: uint32(lastModifiedLedgerSeq), - Sponsor: null.StringFrom("GC3C4AKRBQLHOJ45U4XG35ESVWRDECWO5XLDGYADO6DPR3L7KIDVUMML"), - }, + s.mockClaimableBalanceBatchInsertBuilder.On( + "Add", + history.ClaimableBalance{ + BalanceID: id, + Claimants: []history.Claimant{}, + Asset: cBalance.Asset, + Amount: cBalance.Amount, + LastModifiedLedger: uint32(lastModifiedLedgerSeq), + Sponsor: null.StringFrom("GC3C4AKRBQLHOJ45U4XG35ESVWRDECWO5XLDGYADO6DPR3L7KIDVUMML"), }, ).Return(nil).Once() -} -func (s *ClaimableBalancesChangeProcessorTestSuiteLedger) TestUpdateClaimableBalance() { - balanceID := xdr.ClaimableBalanceId{ - Type: xdr.ClaimableBalanceIdTypeClaimableBalanceIdTypeV0, - V0: &xdr.Hash{1, 2, 3}, - } - cBalance := xdr.ClaimableBalanceEntry{ - BalanceId: balanceID, - Claimants: []xdr.Claimant{}, - Asset: xdr.MustNewCreditAsset("USD", "GC3C4AKRBQLHOJ45U4XG35ESVWRDECWO5XLDGYADO6DPR3L7KIDVUMML"), - Amount: 10, - } - lastModifiedLedgerSeq := xdr.Uint32(123) - - pre := xdr.LedgerEntry{ - Data: xdr.LedgerEntryData{ - Type: xdr.LedgerEntryTypeClaimableBalance, - ClaimableBalance: &cBalance, - }, - LastModifiedLedgerSeq: lastModifiedLedgerSeq - 1, - Ext: xdr.LedgerEntryExt{ - V: 1, - V1: &xdr.LedgerEntryExtensionV1{ - SponsoringId: nil, - }, - }, - } - - // add sponsor - updated := xdr.LedgerEntry{ - Data: xdr.LedgerEntryData{ - Type: xdr.LedgerEntryTypeClaimableBalance, - ClaimableBalance: &cBalance, - }, - LastModifiedLedgerSeq: lastModifiedLedgerSeq, - Ext: xdr.LedgerEntryExt{ - V: 1, - V1: &xdr.LedgerEntryExtensionV1{ - SponsoringId: xdr.MustAddressPtr("GC3C4AKRBQLHOJ45U4XG35ESVWRDECWO5XLDGYADO6DPR3L7KIDVUMML"), - }, - }, - } - - err := s.processor.ProcessChange(s.ctx, ingest.Change{ + err = s.processor.ProcessChange(s.ctx, ingest.Change{ Type: xdr.LedgerEntryTypeClaimableBalance, - Pre: &pre, - Post: &updated, + Pre: nil, + Post: &entry, }) s.Assert().NoError(err) - - id, err := xdr.MarshalHex(balanceID) - s.Assert().NoError(err) - s.mockQ.On( - "UpsertClaimableBalances", - s.ctx, - []history.ClaimableBalance{ - { - BalanceID: id, - Claimants: []history.Claimant{}, - Asset: cBalance.Asset, - Amount: cBalance.Amount, - LastModifiedLedger: uint32(lastModifiedLedgerSeq), - Sponsor: null.StringFrom("GC3C4AKRBQLHOJ45U4XG35ESVWRDECWO5XLDGYADO6DPR3L7KIDVUMML"), - }, - }, - ).Return(nil).Once() } func (s *ClaimableBalancesChangeProcessorTestSuiteLedger) TestRemoveClaimableBalance() { @@ -287,4 +242,10 @@ func (s *ClaimableBalancesChangeProcessorTestSuiteLedger) TestRemoveClaimableBal s.ctx, []string{id}, ).Return(int64(1), nil).Once() + + s.mockQ.On( + "RemoveClaimableBalanceClaimants", + s.ctx, + []string{id}, + ).Return(int64(1), nil).Once() } diff --git a/services/horizon/internal/ingest/processors/claimable_balances_transaction_processor.go b/services/horizon/internal/ingest/processors/claimable_balances_transaction_processor.go index 33c8bfd9c6..394d2e0f9b 100644 --- a/services/horizon/internal/ingest/processors/claimable_balances_transaction_processor.go +++ b/services/horizon/internal/ingest/processors/claimable_balances_transaction_processor.go @@ -5,53 +5,39 @@ import ( "github.com/stellar/go/ingest" "github.com/stellar/go/services/horizon/internal/db2/history" - set "github.com/stellar/go/support/collections/set" + "github.com/stellar/go/support/db" "github.com/stellar/go/support/errors" "github.com/stellar/go/toid" "github.com/stellar/go/xdr" ) -type claimableBalance struct { - internalID int64 // Bigint auto-generated by postgres - transactionSet set.Set[int64] - operationSet set.Set[int64] -} - -func (b *claimableBalance) addTransactionID(id int64) { - if b.transactionSet == nil { - b.transactionSet = set.Set[int64]{} - } - b.transactionSet.Add(id) -} - -func (b *claimableBalance) addOperationID(id int64) { - if b.operationSet == nil { - b.operationSet = set.Set[int64]{} - } - b.operationSet.Add(id) -} - type ClaimableBalancesTransactionProcessor struct { - sequence uint32 - claimableBalanceSet map[string]claimableBalance - qClaimableBalances history.QHistoryClaimableBalances + cbLoader *history.ClaimableBalanceLoader + txBatch history.TransactionClaimableBalanceBatchInsertBuilder + opBatch history.OperationClaimableBalanceBatchInsertBuilder } -func NewClaimableBalancesTransactionProcessor(Q history.QHistoryClaimableBalances, sequence uint32) *ClaimableBalancesTransactionProcessor { +func NewClaimableBalancesTransactionProcessor( + cbLoader *history.ClaimableBalanceLoader, + txBatch history.TransactionClaimableBalanceBatchInsertBuilder, + opBatch history.OperationClaimableBalanceBatchInsertBuilder, +) *ClaimableBalancesTransactionProcessor { return &ClaimableBalancesTransactionProcessor{ - qClaimableBalances: Q, - sequence: sequence, - claimableBalanceSet: map[string]claimableBalance{}, + cbLoader: cbLoader, + txBatch: txBatch, + opBatch: opBatch, } } -func (p *ClaimableBalancesTransactionProcessor) ProcessTransaction(ctx context.Context, transaction ingest.LedgerTransaction) error { - err := p.addTransactionClaimableBalances(p.claimableBalanceSet, p.sequence, transaction) +func (p *ClaimableBalancesTransactionProcessor) ProcessTransaction( + lcm xdr.LedgerCloseMeta, transaction ingest.LedgerTransaction, +) error { + err := p.addTransactionClaimableBalances(lcm.LedgerSequence(), transaction) if err != nil { return err } - err = p.addOperationClaimableBalances(p.claimableBalanceSet, p.sequence, transaction) + err = p.addOperationClaimableBalances(lcm.LedgerSequence(), transaction) if err != nil { return err } @@ -59,27 +45,25 @@ func (p *ClaimableBalancesTransactionProcessor) ProcessTransaction(ctx context.C return nil } -func (p *ClaimableBalancesTransactionProcessor) addTransactionClaimableBalances(cbSet map[string]claimableBalance, sequence uint32, transaction ingest.LedgerTransaction) error { +func (p *ClaimableBalancesTransactionProcessor) addTransactionClaimableBalances( + sequence uint32, transaction ingest.LedgerTransaction, +) error { transactionID := toid.New(int32(sequence), int32(transaction.Index), 0).ToInt64() - transactionClaimableBalances, err := claimableBalancesForTransaction( - sequence, - transaction, - ) + transactionClaimableBalances, err := claimableBalancesForTransaction(transaction) if err != nil { return errors.Wrap(err, "Could not determine claimable balances for transaction") } - for _, cb := range transactionClaimableBalances { - entry := cbSet[cb] - entry.addTransactionID(transactionID) - cbSet[cb] = entry + for _, cb := range dedupeStrings(transactionClaimableBalances) { + if err = p.txBatch.Add(transactionID, p.cbLoader.GetFuture(cb)); err != nil { + return err + } } return nil } func claimableBalancesForTransaction( - sequence uint32, transaction ingest.LedgerTransaction, ) ([]string, error) { changes, err := transaction.GetChanges() @@ -90,19 +74,7 @@ func claimableBalancesForTransaction( if err != nil { return nil, errors.Wrapf(err, "reading transaction %v claimable balances", transaction.Index) } - return dedupeClaimableBalances(cbs) -} - -func dedupeClaimableBalances(in []string) (out []string, err error) { - set := set.Set[string]{} - for _, id := range in { - set.Add(id) - } - - for id := range set { - out = append(out, id) - } - return + return cbs, nil } func claimableBalancesForChanges( @@ -136,26 +108,9 @@ func claimableBalancesForChanges( return cbs, nil } -func (p *ClaimableBalancesTransactionProcessor) addOperationClaimableBalances(cbSet map[string]claimableBalance, sequence uint32, transaction ingest.LedgerTransaction) error { - claimableBalances, err := claimableBalancesForOperations(transaction, sequence) - if err != nil { - return errors.Wrap(err, "could not determine operation claimable balances") - } - - for operationID, cbs := range claimableBalances { - for _, cb := range cbs { - entry := cbSet[cb] - entry.addOperationID(operationID) - cbSet[cb] = entry - } - } - - return nil -} - -func claimableBalancesForOperations(transaction ingest.LedgerTransaction, sequence uint32) (map[int64][]string, error) { - cbs := map[int64][]string{} - +func (p *ClaimableBalancesTransactionProcessor) addOperationClaimableBalances( + sequence uint32, transaction ingest.LedgerTransaction, +) error { for opi, op := range transaction.Envelope.Operations() { operation := transactionOperationWrapper{ index: uint32(opi), @@ -166,92 +121,33 @@ func claimableBalancesForOperations(transaction ingest.LedgerTransaction, sequen changes, err := transaction.GetOperationChanges(uint32(opi)) if err != nil { - return cbs, err - } - c, err := claimableBalancesForChanges(changes) - if err != nil { - return cbs, errors.Wrapf(err, "reading operation %v claimable balances", operation.ID()) - } - cbs[operation.ID()] = c - } - - return cbs, nil -} - -func (p *ClaimableBalancesTransactionProcessor) Commit(ctx context.Context) error { - if len(p.claimableBalanceSet) > 0 { - if err := p.loadClaimableBalanceIDs(ctx, p.claimableBalanceSet); err != nil { return err } - - if err := p.insertDBTransactionClaimableBalances(ctx, p.claimableBalanceSet); err != nil { - return err + cbs, err := claimableBalancesForChanges(changes) + if err != nil { + return errors.Wrapf(err, "reading operation %v claimable balances", operation.ID()) } - if err := p.insertDBOperationsClaimableBalances(ctx, p.claimableBalanceSet); err != nil { - return err + for _, cb := range dedupeStrings(cbs) { + if err = p.opBatch.Add(operation.ID(), p.cbLoader.GetFuture(cb)); err != nil { + return err + } } } return nil } -func (p *ClaimableBalancesTransactionProcessor) loadClaimableBalanceIDs(ctx context.Context, claimableBalanceSet map[string]claimableBalance) error { - ids := make([]string, 0, len(claimableBalanceSet)) - for id := range claimableBalanceSet { - ids = append(ids, id) - } - - toInternalID, err := p.qClaimableBalances.CreateHistoryClaimableBalances(ctx, ids, maxBatchSize) +func (p *ClaimableBalancesTransactionProcessor) Flush(ctx context.Context, session db.SessionInterface) error { + err := p.txBatch.Exec(ctx, session) if err != nil { - return errors.Wrap(err, "Could not create claimable balance ids") - } - - for _, id := range ids { - internalID, ok := toInternalID[id] - if !ok { - // TODO: Figure out the right way to convert the id to a string here. %v will be nonsense. - return errors.Errorf("no internal id found for claimable balance %v", id) - } - - cb := claimableBalanceSet[id] - cb.internalID = internalID - claimableBalanceSet[id] = cb - } - - return nil -} - -func (p ClaimableBalancesTransactionProcessor) insertDBTransactionClaimableBalances(ctx context.Context, claimableBalanceSet map[string]claimableBalance) error { - batch := p.qClaimableBalances.NewTransactionClaimableBalanceBatchInsertBuilder(maxBatchSize) - - for _, entry := range claimableBalanceSet { - for transactionID := range entry.transactionSet { - if err := batch.Add(ctx, transactionID, entry.internalID); err != nil { - return errors.Wrap(err, "could not insert transaction claimable balance in db") - } - } - } - - if err := batch.Exec(ctx); err != nil { - return errors.Wrap(err, "could not flush transaction claimable balances to db") + return err } - return nil -} -func (p ClaimableBalancesTransactionProcessor) insertDBOperationsClaimableBalances(ctx context.Context, claimableBalanceSet map[string]claimableBalance) error { - batch := p.qClaimableBalances.NewOperationClaimableBalanceBatchInsertBuilder(maxBatchSize) - - for _, entry := range claimableBalanceSet { - for operationID := range entry.operationSet { - if err := batch.Add(ctx, operationID, entry.internalID); err != nil { - return errors.Wrap(err, "could not insert operation claimable balance in db") - } - } + err = p.opBatch.Exec(ctx, session) + if err != nil { + return err } - if err := batch.Exec(ctx); err != nil { - return errors.Wrap(err, "could not flush operation claimable balances to db") - } return nil } diff --git a/services/horizon/internal/ingest/processors/claimable_balances_transaction_processor_test.go b/services/horizon/internal/ingest/processors/claimable_balances_transaction_processor_test.go index abdaf5b070..11ce54505a 100644 --- a/services/horizon/internal/ingest/processors/claimable_balances_transaction_processor_test.go +++ b/services/horizon/internal/ingest/processors/claimable_balances_transaction_processor_test.go @@ -6,10 +6,10 @@ import ( "context" "testing" - "github.com/stretchr/testify/mock" "github.com/stretchr/testify/suite" "github.com/stellar/go/services/horizon/internal/db2/history" + "github.com/stellar/go/support/db" "github.com/stellar/go/toid" "github.com/stellar/go/xdr" ) @@ -18,11 +18,12 @@ type ClaimableBalancesTransactionProcessorTestSuiteLedger struct { suite.Suite ctx context.Context processor *ClaimableBalancesTransactionProcessor - mockQ *history.MockQHistoryClaimableBalances + mockSession *db.MockSession mockTransactionBatchInsertBuilder *history.MockTransactionClaimableBalanceBatchInsertBuilder mockOperationBatchInsertBuilder *history.MockOperationClaimableBalanceBatchInsertBuilder + cbLoader *history.ClaimableBalanceLoader - sequence uint32 + lcm xdr.LedgerCloseMeta } func TestClaimableBalancesTransactionProcessorTestSuiteLedger(t *testing.T) { @@ -31,40 +32,41 @@ func TestClaimableBalancesTransactionProcessorTestSuiteLedger(t *testing.T) { func (s *ClaimableBalancesTransactionProcessorTestSuiteLedger) SetupTest() { s.ctx = context.Background() - s.mockQ = &history.MockQHistoryClaimableBalances{} s.mockTransactionBatchInsertBuilder = &history.MockTransactionClaimableBalanceBatchInsertBuilder{} s.mockOperationBatchInsertBuilder = &history.MockOperationClaimableBalanceBatchInsertBuilder{} - s.sequence = 20 + sequence := uint32(20) + s.lcm = xdr.LedgerCloseMeta{ + V0: &xdr.LedgerCloseMetaV0{ + LedgerHeader: xdr.LedgerHeaderHistoryEntry{ + Header: xdr.LedgerHeader{ + LedgerSeq: xdr.Uint32(sequence), + }, + }, + }, + } + s.cbLoader = history.NewClaimableBalanceLoader() s.processor = NewClaimableBalancesTransactionProcessor( - s.mockQ, - s.sequence, + s.cbLoader, + s.mockTransactionBatchInsertBuilder, + s.mockOperationBatchInsertBuilder, ) } func (s *ClaimableBalancesTransactionProcessorTestSuiteLedger) TearDownTest() { - s.mockQ.AssertExpectations(s.T()) s.mockTransactionBatchInsertBuilder.AssertExpectations(s.T()) s.mockOperationBatchInsertBuilder.AssertExpectations(s.T()) } -func (s *ClaimableBalancesTransactionProcessorTestSuiteLedger) mockTransactionBatchAdd(transactionID, internalID int64, err error) { - s.mockTransactionBatchInsertBuilder.On("Add", s.ctx, transactionID, internalID).Return(err).Once() -} - -func (s *ClaimableBalancesTransactionProcessorTestSuiteLedger) mockOperationBatchAdd(operationID, internalID int64, err error) { - s.mockOperationBatchInsertBuilder.On("Add", s.ctx, operationID, internalID).Return(err).Once() -} - func (s *ClaimableBalancesTransactionProcessorTestSuiteLedger) TestEmptyClaimableBalances() { - // What is this expecting? Doesn't seem to assert anything meaningful... - err := s.processor.Commit(context.Background()) - s.Assert().NoError(err) + s.mockTransactionBatchInsertBuilder.On("Exec", s.ctx, s.mockSession).Return(nil).Once() + s.mockOperationBatchInsertBuilder.On("Exec", s.ctx, s.mockSession).Return(nil).Once() + + s.Assert().NoError(s.processor.Flush(s.ctx, s.mockSession)) } func (s *ClaimableBalancesTransactionProcessorTestSuiteLedger) testOperationInserts(balanceID xdr.ClaimableBalanceId, body xdr.OperationBody, change xdr.LedgerEntryChange) { // Setup the transaction - internalID := int64(1234) txn := createTransaction(true, 1) txn.Envelope.Operations()[0].Body = body txn.UnsafeMeta.V = 2 @@ -82,6 +84,20 @@ func (s *ClaimableBalancesTransactionProcessorTestSuiteLedger) testOperationInse }, }, change, + // add a duplicate change to test that the processor + // does not insert duplicate rows + { + Type: xdr.LedgerEntryChangeTypeLedgerEntryState, + State: &xdr.LedgerEntry{ + Data: xdr.LedgerEntryData{ + Type: xdr.LedgerEntryTypeClaimableBalance, + ClaimableBalance: &xdr.ClaimableBalanceEntry{ + BalanceId: balanceID, + }, + }, + }, + }, + change, }}, } @@ -101,46 +117,28 @@ func (s *ClaimableBalancesTransactionProcessorTestSuiteLedger) testOperationInse }, } } - txnID := toid.New(int32(s.sequence), int32(txn.Index), 0).ToInt64() + txnID := toid.New(int32(s.lcm.LedgerSequence()), int32(txn.Index), 0).ToInt64() opID := (&transactionOperationWrapper{ index: uint32(0), transaction: txn, operation: txn.Envelope.Operations()[0], - ledgerSequence: s.sequence, + ledgerSequence: s.lcm.LedgerSequence(), }).ID() - hexID, _ := xdr.MarshalHex(balanceID) + hexID, err := xdr.MarshalHex(balanceID) + s.Assert().NoError(err) - // Setup a q - s.mockQ.On("CreateHistoryClaimableBalances", s.ctx, mock.AnythingOfType("[]string"), maxBatchSize). - Run(func(args mock.Arguments) { - arg := args.Get(1).([]string) - s.Assert().ElementsMatch( - []string{ - hexID, - }, - arg, - ) - }).Return(map[string]int64{ - hexID: internalID, - }, nil).Once() - - // Prepare to process transactions successfully - s.mockQ.On("NewTransactionClaimableBalanceBatchInsertBuilder", maxBatchSize). - Return(s.mockTransactionBatchInsertBuilder).Once() - s.mockTransactionBatchAdd(txnID, internalID, nil) - s.mockTransactionBatchInsertBuilder.On("Exec", s.ctx).Return(nil).Once() + s.mockTransactionBatchInsertBuilder.On("Add", txnID, s.cbLoader.GetFuture(hexID)).Return(nil).Once() + s.mockTransactionBatchInsertBuilder.On("Exec", s.ctx, s.mockSession).Return(nil).Once() // Prepare to process operations successfully - s.mockQ.On("NewOperationClaimableBalanceBatchInsertBuilder", maxBatchSize). - Return(s.mockOperationBatchInsertBuilder).Once() - s.mockOperationBatchAdd(opID, internalID, nil) - s.mockOperationBatchInsertBuilder.On("Exec", s.ctx).Return(nil).Once() + s.mockOperationBatchInsertBuilder.On("Add", opID, s.cbLoader.GetFuture(hexID)).Return(nil).Once() + s.mockOperationBatchInsertBuilder.On("Exec", s.ctx, s.mockSession).Return(nil).Once() // Process the transaction - err := s.processor.ProcessTransaction(s.ctx, txn) + err = s.processor.ProcessTransaction(s.lcm, txn) s.Assert().NoError(err) - err = s.processor.Commit(s.ctx) + err = s.processor.Flush(s.ctx, s.mockSession) s.Assert().NoError(err) } diff --git a/services/horizon/internal/ingest/processors/contract_asset_stats.go b/services/horizon/internal/ingest/processors/contract_asset_stats.go new file mode 100644 index 0000000000..d39ceb6b6d --- /dev/null +++ b/services/horizon/internal/ingest/processors/contract_asset_stats.go @@ -0,0 +1,412 @@ +package processors + +import ( + "context" + "crypto/sha256" + "fmt" + "math/big" + + "github.com/stellar/go/ingest" + "github.com/stellar/go/services/horizon/internal/db2/history" + "github.com/stellar/go/support/errors" + "github.com/stellar/go/xdr" +) + +type assetContractStatValue struct { + contractID xdr.Hash + activeBalance *big.Int + activeHolders int32 + archivedBalance *big.Int + archivedHolders int32 +} + +func (v assetContractStatValue) ConvertToHistoryObject() history.ContractAssetStatRow { + return history.ContractAssetStatRow{ + ContractID: v.contractID[:], + Stat: history.ContractStat{ + ActiveBalance: v.activeBalance.String(), + ActiveHolders: v.activeHolders, + ArchivedBalance: v.archivedBalance.String(), + ArchivedHolders: v.archivedHolders, + }, + } +} + +type contractAssetBalancesQ interface { + GetContractAssetBalances(ctx context.Context, keys []xdr.Hash) ([]history.ContractAssetBalance, error) + GetContractAssetBalancesExpiringAt(ctx context.Context, ledger uint32) ([]history.ContractAssetBalance, error) +} + +// ContractAssetStatSet represents a collection of asset stats for +// contract asset holders +type ContractAssetStatSet struct { + contractToAsset map[xdr.Hash]*xdr.Asset + contractAssetStats map[xdr.Hash]assetContractStatValue + createdBalances []history.ContractAssetBalance + removedBalances []xdr.Hash + updatedBalances map[xdr.Hash]*big.Int + removedExpirationEntries map[xdr.Hash]uint32 + createdExpirationEntries map[xdr.Hash]uint32 + updatedExpirationEntries map[xdr.Hash][2]uint32 + networkPassphrase string + assetStatsQ contractAssetBalancesQ + currentLedger uint32 +} + +// NewContractAssetStatSet constructs a new ContractAssetStatSet instance +func NewContractAssetStatSet( + assetStatsQ contractAssetBalancesQ, + networkPassphrase string, + removedExpirationEntries map[xdr.Hash]uint32, + createdExpirationEntries map[xdr.Hash]uint32, + updatedExpirationEntries map[xdr.Hash][2]uint32, + currentLedger uint32, +) *ContractAssetStatSet { + return &ContractAssetStatSet{ + contractToAsset: map[xdr.Hash]*xdr.Asset{}, + contractAssetStats: map[xdr.Hash]assetContractStatValue{}, + networkPassphrase: networkPassphrase, + assetStatsQ: assetStatsQ, + removedExpirationEntries: removedExpirationEntries, + createdExpirationEntries: createdExpirationEntries, + updatedExpirationEntries: updatedExpirationEntries, + currentLedger: currentLedger, + updatedBalances: map[xdr.Hash]*big.Int{}, + } +} + +// AddContractData updates the set to account for how a given contract data entry has changed. +// change must be a xdr.LedgerEntryTypeContractData type. +func (s *ContractAssetStatSet) AddContractData(ctx context.Context, change ingest.Change) error { + // skip ingestion of contract asset balances if we find an asset contract metadata entry + // because a ledger entry cannot be both an asset contract metadata entry and a + // contract asset balance. + if found, err := s.ingestAssetContractMetadata(change); err != nil { + return err + } else if found { + return nil + } + return s.ingestContractAssetBalance(ctx, change) +} + +func (s *ContractAssetStatSet) GetContractStats() []history.ContractAssetStatRow { + var contractStats []history.ContractAssetStatRow + for _, contractStat := range s.contractAssetStats { + contractStats = append(contractStats, contractStat.ConvertToHistoryObject()) + } + return contractStats +} + +func (s *ContractAssetStatSet) GetCreatedBalances() []history.ContractAssetBalance { + return s.createdBalances +} + +func (s *ContractAssetStatSet) GetAssetToContractMap() map[xdr.Hash]*xdr.Asset { + return s.contractToAsset +} + +func (s *ContractAssetStatSet) ingestAssetContractMetadata(change ingest.Change) (bool, error) { + if change.Pre != nil { + asset := AssetFromContractData(*change.Pre, s.networkPassphrase) + if asset == nil { + return false, nil + } + pContractID := change.Pre.Data.MustContractData().Contract.ContractId + if pContractID == nil { + return false, nil + } + contractID := *pContractID + if change.Post == nil { + s.contractToAsset[contractID] = nil + return true, nil + } + // The contract id for any soroban contract should never change and + // therefore we return a fatal ingestion error if we encounter + // a stellar asset changing contract ids. + postAsset := AssetFromContractData(*change.Post, s.networkPassphrase) + if postAsset == nil || !(*postAsset).Equals(*asset) { + return false, ingest.NewStateError(fmt.Errorf("asset contract changed asset")) + } + return true, nil + } else if change.Post != nil { + asset := AssetFromContractData(*change.Post, s.networkPassphrase) + if asset == nil { + return false, nil + } + if pContactID := change.Post.Data.MustContractData().Contract.ContractId; pContactID != nil { + s.contractToAsset[*pContactID] = asset + return true, nil + } + } + return false, nil +} + +func getKeyHash(ledgerEntry xdr.LedgerEntry) (xdr.Hash, error) { + lk, err := ledgerEntry.LedgerKey() + if err != nil { + return xdr.Hash{}, errors.Wrap(err, "could not extract ledger key") + } + bin, err := lk.MarshalBinary() + if err != nil { + return xdr.Hash{}, errors.Wrap(err, "could not marshal key") + } + return sha256.Sum256(bin), nil +} + +func (s *ContractAssetStatSet) ingestContractAssetBalance(ctx context.Context, change ingest.Change) error { + switch { + case change.Pre == nil && change.Post != nil: // created + pContractID := change.Post.Data.MustContractData().Contract.ContractId + if pContractID == nil { + return nil + } + + _, postAmt, postOk := ContractBalanceFromContractData(*change.Post, s.networkPassphrase) + // we only ingest created ledger entries if we determine that they resemble the shape of + // a Stellar Asset Contract balance ledger entry + if !postOk { + return nil + } + + keyHash, err := getKeyHash(*change.Post) + if err != nil { + return err + } + expirationLedger, ok := s.createdExpirationEntries[keyHash] + if !ok { + return nil + } + s.createdBalances = append(s.createdBalances, history.ContractAssetBalance{ + KeyHash: keyHash[:], + ContractID: (*pContractID)[:], + Amount: postAmt.String(), + ExpirationLedger: expirationLedger, + }) + + stat := s.getContractAssetStat(*pContractID) + if expirationLedger >= s.currentLedger { + stat.activeHolders++ + stat.activeBalance.Add(stat.activeBalance, postAmt) + } else { + stat.archivedHolders++ + stat.archivedBalance.Add(stat.archivedBalance, postAmt) + } + s.maybeAddContractAssetStat(*pContractID, stat) + case change.Pre != nil && change.Post == nil: // removed + pContractID := change.Pre.Data.MustContractData().Contract.ContractId + if pContractID == nil { + return nil + } + + keyHash, err := getKeyHash(*change.Pre) + if err != nil { + return err + } + // We always include the key hash in s.removedBalances even + // if the ledger entry is not a valid balance ledger entry. + // It's possible that a contract is able to forge a created + // balance ledger entry which matches the Stellar Asset Contract + // and later on the ledger entry is updated to an invalid state. + // In such a scenario we still want to remove the balance ledger + // entry from our db when the entry is removed from the ledger. + s.removedBalances = append(s.removedBalances, keyHash) + + _, preAmt, ok := ContractBalanceFromContractData(*change.Pre, s.networkPassphrase) + if !ok { + return nil + } + + expirationLedger, ok := s.removedExpirationEntries[keyHash] + if !ok { + return nil + } + + stat := s.getContractAssetStat(*pContractID) + if expirationLedger >= s.currentLedger { + stat.activeHolders-- + stat.activeBalance = new(big.Int).Sub(stat.activeBalance, preAmt) + } else { + stat.archivedHolders-- + stat.archivedBalance = new(big.Int).Sub(stat.archivedBalance, preAmt) + } + s.maybeAddContractAssetStat(*pContractID, stat) + case change.Pre != nil && change.Post != nil: // updated + pContractID := change.Pre.Data.MustContractData().Contract.ContractId + if pContractID == nil { + return nil + } + + holder, amt, ok := ContractBalanceFromContractData(*change.Pre, s.networkPassphrase) + if !ok { + return nil + } + + // if the updated ledger entry is not in the expected format then this + // cannot be emitted by the stellar asset contract, so ignore it + postHolder, postAmt, postOk := ContractBalanceFromContractData(*change.Post, s.networkPassphrase) + if !postOk || postHolder != holder { + return nil + } + + amtDelta := new(big.Int).Sub(postAmt, amt) + if amtDelta.Cmp(big.NewInt(0)) == 0 { + return nil + } + + keyHash, err := getKeyHash(*change.Post) + if err != nil { + return err + } + + var preExpiration, postExpiration uint32 + if expirationUpdate, ok := s.updatedExpirationEntries[keyHash]; ok { + preExpiration, postExpiration = expirationUpdate[0], expirationUpdate[1] + } else { + rows, err := s.assetStatsQ.GetContractAssetBalances(ctx, []xdr.Hash{keyHash}) + if err != nil { + return errors.Wrapf(err, "could not query contract asset balance for %v", keyHash) + } + if len(rows) == 0 { + return nil + } + if len(rows) != 1 { + return errors.Wrapf( + err, + "expected 1 contract asset balance for %v but got %v", + keyHash, + len(rows), + ) + } + preExpiration = rows[0].ExpirationLedger + postExpiration = preExpiration + } + if postExpiration < s.currentLedger { + return errors.Errorf( + "contract balance has invalid expiration ledger keyhash %v expiration ledger %v", + keyHash, + postExpiration, + ) + } + + s.updatedBalances[keyHash] = postAmt + stat := s.getContractAssetStat(*pContractID) + if preExpiration+1 >= s.currentLedger { // active balance was updated + stat.activeBalance.Add(stat.activeBalance, amtDelta) + } else { // balance was restored + stat.activeHolders++ + stat.archivedHolders-- + stat.activeBalance.Add(stat.activeBalance, postAmt) + stat.archivedBalance.Sub(stat.archivedBalance, amt) + } + s.maybeAddContractAssetStat(*pContractID, stat) + default: + return errors.Errorf("unexpected change Pre: %v Post: %v", change.Pre, change.Post) + } + return nil +} + +func (s *ContractAssetStatSet) ingestRestoredBalances(ctx context.Context) error { + var keyHashes []xdr.Hash + for keyHash, expirationUpdate := range s.updatedExpirationEntries { + prevExpirationLedger := expirationUpdate[0] + // prevExpirationLedger+1 >= s.currentLedger indicates that this contract balance is still + // active in our DB and therefore don't need to restore it. + // s.updatedBalances[keyHash] != nil indicates that this contract balance was already ingested + // in ingestContractAssetBalance() so we don't need to ingest it again here. + if prevExpirationLedger+1 >= s.currentLedger || s.updatedBalances[keyHash] != nil { + continue + } + keyHashes = append(keyHashes, keyHash) + } + if len(keyHashes) == 0 { + return nil + } + + rows, err := s.assetStatsQ.GetContractAssetBalances(ctx, keyHashes) + if err != nil { + return errors.Wrap(err, "Error fetching contract asset balances") + } + + for _, row := range rows { + var contractID xdr.Hash + copy(contractID[:], row.ContractID) + stat := s.getContractAssetStat(contractID) + amt, ok := new(big.Int).SetString(row.Amount, 10) + if !ok { + return errors.Errorf( + "contract balance %v has invalid amount: %v", + row.KeyHash, + row.Amount, + ) + } + + stat.activeHolders++ + stat.activeBalance.Add(stat.activeBalance, amt) + stat.archivedHolders-- + stat.archivedBalance.Sub(stat.archivedBalance, amt) + s.maybeAddContractAssetStat(contractID, stat) + } + + return nil +} + +func (s *ContractAssetStatSet) ingestExpiredBalances(ctx context.Context) error { + rows, err := s.assetStatsQ.GetContractAssetBalancesExpiringAt(ctx, s.currentLedger-1) + if err != nil { + return errors.Wrap(err, "Error fetching contract asset balances") + } + + for _, row := range rows { + var keyHash, contractID xdr.Hash + copy(keyHash[:], row.KeyHash) + + if _, ok := s.updatedExpirationEntries[keyHash]; ok { + // the expiration of this contract balance was bumped, so we can + // skip this contract balance since it is still active + continue + } + + copy(contractID[:], row.ContractID) + stat := s.getContractAssetStat(contractID) + amt, ok := new(big.Int).SetString(row.Amount, 10) + if !ok { + return errors.Errorf( + "contract balance %v has invalid amount: %v", + row.KeyHash, + row.Amount, + ) + } + + stat.activeHolders-- + stat.activeBalance.Sub(stat.activeBalance, amt) + stat.archivedHolders++ + stat.archivedBalance.Add(stat.archivedBalance, amt) + s.maybeAddContractAssetStat(contractID, stat) + } + + return nil +} + +func (s *ContractAssetStatSet) maybeAddContractAssetStat(contractID xdr.Hash, stat assetContractStatValue) { + if stat.archivedHolders == 0 && stat.activeHolders == 0 && + stat.activeBalance.Cmp(big.NewInt(0)) == 0 && + stat.archivedBalance.Cmp(big.NewInt(0)) == 0 { + delete(s.contractAssetStats, contractID) + } else { + s.contractAssetStats[contractID] = stat + } +} + +func (s *ContractAssetStatSet) getContractAssetStat(contractID xdr.Hash) assetContractStatValue { + stat, ok := s.contractAssetStats[contractID] + if !ok { + stat = assetContractStatValue{ + contractID: contractID, + activeBalance: big.NewInt(0), + activeHolders: 0, + archivedBalance: big.NewInt(0), + archivedHolders: 0, + } + } + return stat +} diff --git a/services/horizon/internal/ingest/processors/contract_asset_stats_test.go b/services/horizon/internal/ingest/processors/contract_asset_stats_test.go new file mode 100644 index 0000000000..ce89920ecd --- /dev/null +++ b/services/horizon/internal/ingest/processors/contract_asset_stats_test.go @@ -0,0 +1,636 @@ +package processors + +import ( + "context" + "crypto/sha256" + "math/big" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/mock" + + "github.com/stellar/go/ingest" + "github.com/stellar/go/keypair" + "github.com/stellar/go/services/horizon/internal/db2/history" + "github.com/stellar/go/xdr" +) + +func getKeyHashForBalance(t *testing.T, assetContractId, holderID [32]byte) xdr.Hash { + ledgerKey := ContractBalanceLedgerKey(assetContractId, holderID) + bin, err := ledgerKey.MarshalBinary() + assert.NoError(t, err) + return sha256.Sum256(bin) +} + +func TestAddContractData(t *testing.T) { + xlmID, err := xdr.MustNewNativeAsset().ContractID("passphrase") + assert.NoError(t, err) + usdcIssuer := keypair.MustRandom().Address() + usdcAsset := xdr.MustNewCreditAsset("USDC", usdcIssuer) + usdcID, err := usdcAsset.ContractID("passphrase") + assert.NoError(t, err) + etherIssuer := keypair.MustRandom().Address() + etherAsset := xdr.MustNewCreditAsset("ETHER", etherIssuer) + etherID, err := etherAsset.ContractID("passphrase") + assert.NoError(t, err) + uniAsset := xdr.MustNewCreditAsset("UNI", etherIssuer) + uniID, err := uniAsset.ContractID("passphrase") + assert.NoError(t, err) + + set := NewContractAssetStatSet( + &history.MockQAssetStats{}, + "passphrase", + map[xdr.Hash]uint32{}, + map[xdr.Hash]uint32{}, + map[xdr.Hash][2]uint32{}, + 150, + ) + + xlmContractData, err := AssetToContractData(true, "", "", xlmID) + assert.NoError(t, err) + err = set.AddContractData(context.Background(), ingest.Change{ + Type: xdr.LedgerEntryTypeContractData, + Post: &xdr.LedgerEntry{ + Data: xlmContractData, + }, + }) + assert.NoError(t, err) + + xlmBalanceKeyHash := getKeyHashForBalance(t, xlmID, [32]byte{}) + assert.NoError(t, err) + set.createdExpirationEntries[xlmBalanceKeyHash] = 150 + err = set.AddContractData(context.Background(), ingest.Change{ + Type: xdr.LedgerEntryTypeContractData, + Post: &xdr.LedgerEntry{ + Data: BalanceToContractData(xlmID, [32]byte{}, 100), + }, + }) + assert.NoError(t, err) + + uniBalanceKeyHash := getKeyHashForBalance(t, uniID, [32]byte{}) + set.createdExpirationEntries[uniBalanceKeyHash] = 150 + err = set.AddContractData(context.Background(), ingest.Change{ + Type: xdr.LedgerEntryTypeContractData, + Post: &xdr.LedgerEntry{ + Data: BalanceToContractData(uniID, [32]byte{}, 0), + }, + }) + assert.NoError(t, err) + + usdcContractData, err := AssetToContractData(false, "USDC", usdcIssuer, usdcID) + assert.NoError(t, err) + err = set.AddContractData(context.Background(), ingest.Change{ + Type: xdr.LedgerEntryTypeContractData, + Post: &xdr.LedgerEntry{ + Data: usdcContractData, + }, + }) + assert.NoError(t, err) + + etherContractData, err := AssetToContractData(false, "ETHER", etherIssuer, etherID) + assert.NoError(t, err) + err = set.AddContractData(context.Background(), ingest.Change{ + Type: xdr.LedgerEntryTypeContractData, + Post: &xdr.LedgerEntry{ + Data: etherContractData, + }, + }) + assert.NoError(t, err) + + etherBalanceKeyHash := getKeyHashForBalance(t, etherID, [32]byte{}) + set.createdExpirationEntries[etherBalanceKeyHash] = 100 + err = set.AddContractData(context.Background(), ingest.Change{ + Type: xdr.LedgerEntryTypeContractData, + Post: &xdr.LedgerEntry{ + Data: BalanceToContractData(etherID, [32]byte{}, 50), + }, + }) + assert.NoError(t, err) + + otherEtherBalanceKeyHash := getKeyHashForBalance(t, etherID, [32]byte{1}) + set.createdExpirationEntries[otherEtherBalanceKeyHash] = 150 + err = set.AddContractData(context.Background(), ingest.Change{ + Type: xdr.LedgerEntryTypeContractData, + Post: &xdr.LedgerEntry{ + Data: BalanceToContractData(etherID, [32]byte{1}, 150), + }, + }) + assert.NoError(t, err) + + // negative balances will be ignored + err = set.AddContractData(context.Background(), ingest.Change{ + Type: xdr.LedgerEntryTypeContractData, + Post: &xdr.LedgerEntry{ + Data: balanceToContractData(etherID, [32]byte{1}, xdr.Int128Parts{Hi: -1, Lo: 0}), + }, + }) + assert.NoError(t, err) + + btcAsset := xdr.MustNewCreditAsset("BTC", etherIssuer) + btcID, err := btcAsset.ContractID("passphrase") + assert.NoError(t, err) + + err = set.AddContractData(context.Background(), ingest.Change{ + Type: xdr.LedgerEntryTypeContractData, + Post: &xdr.LedgerEntry{ + Data: BalanceToContractData(btcID, [32]byte{2}, 300), + }, + }) + assert.NoError(t, err) + + assert.Empty(t, set.updatedBalances) + assert.Empty(t, set.removedBalances) + assert.Len(t, set.contractToAsset, 2) + assert.True(t, set.contractToAsset[usdcID].Equals(usdcAsset)) + assert.True(t, set.contractToAsset[etherID].Equals(etherAsset)) + assert.Equal(t, []history.ContractAssetBalance{ + { + KeyHash: uniBalanceKeyHash[:], + ContractID: uniID[:], + Amount: "0", + ExpirationLedger: 150, + }, + { + KeyHash: etherBalanceKeyHash[:], + ContractID: etherID[:], + Amount: "50", + ExpirationLedger: 100, + }, + { + KeyHash: otherEtherBalanceKeyHash[:], + ContractID: etherID[:], + Amount: "150", + ExpirationLedger: 150, + }, + }, set.createdBalances) + assert.ElementsMatch(t, set.GetContractStats(), []history.ContractAssetStatRow{ + { + ContractID: uniID[:], + Stat: history.ContractStat{ + ActiveBalance: "0", + ArchivedBalance: "0", + ActiveHolders: 1, + ArchivedHolders: 0, + }, + }, + { + ContractID: etherID[:], + Stat: history.ContractStat{ + ActiveBalance: "150", + ArchivedBalance: "50", + ActiveHolders: 1, + ArchivedHolders: 1, + }, + }, + }) +} + +func TestUpdateContractBalance(t *testing.T) { + usdcIssuer := keypair.MustRandom().Address() + usdcAsset := xdr.MustNewCreditAsset("USDC", usdcIssuer) + usdcID, err := usdcAsset.ContractID("passphrase") + assert.NoError(t, err) + etherIssuer := keypair.MustRandom().Address() + etherAsset := xdr.MustNewCreditAsset("ETHER", etherIssuer) + etherID, err := etherAsset.ContractID("passphrase") + assert.NoError(t, err) + btcAsset := xdr.MustNewCreditAsset("BTC", etherIssuer) + btcID, err := btcAsset.ContractID("passphrase") + assert.NoError(t, err) + uniAsset := xdr.MustNewCreditAsset("UNI", etherIssuer) + uniID, err := uniAsset.ContractID("passphrase") + assert.NoError(t, err) + + mockQ := &history.MockQAssetStats{} + set := NewContractAssetStatSet( + mockQ, + "passphrase", + map[xdr.Hash]uint32{}, + map[xdr.Hash]uint32{}, + map[xdr.Hash][2]uint32{}, + 150, + ) + expectedBalances := map[xdr.Hash]string{} + + keyHash := getKeyHashForBalance(t, usdcID, [32]byte{}) + set.updatedExpirationEntries[keyHash] = [2]uint32{160, 170} + expectedBalances[keyHash] = "100" + err = set.AddContractData(context.Background(), ingest.Change{ + Type: xdr.LedgerEntryTypeContractData, + Pre: &xdr.LedgerEntry{ + Data: BalanceToContractData(usdcID, [32]byte{}, 50), + }, + Post: &xdr.LedgerEntry{ + Data: BalanceToContractData(usdcID, [32]byte{}, 100), + }, + }) + assert.NoError(t, err) + + keyHash = getKeyHashForBalance(t, usdcID, [32]byte{2}) + ctx := context.Background() + mockQ.On("GetContractAssetBalances", ctx, []xdr.Hash{keyHash}). + Return([]history.ContractAssetBalance{ + { + KeyHash: keyHash[:], + ContractID: usdcID[:], + Amount: "30", + ExpirationLedger: 180, + }, + }, nil).Once() + expectedBalances[keyHash] = "100" + err = set.AddContractData(context.Background(), ingest.Change{ + Type: xdr.LedgerEntryTypeContractData, + Pre: &xdr.LedgerEntry{ + Data: BalanceToContractData(usdcID, [32]byte{2}, 30), + }, + Post: &xdr.LedgerEntry{ + Data: BalanceToContractData(usdcID, [32]byte{2}, 100), + }, + }) + assert.NoError(t, err) + + keyHash = getKeyHashForBalance(t, usdcID, [32]byte{4}) + // balances which don't exist in the db will be ignored + mockQ.On("GetContractAssetBalances", ctx, []xdr.Hash{keyHash}). + Return([]history.ContractAssetBalance{}, nil).Once() + err = set.AddContractData(context.Background(), ingest.Change{ + Type: xdr.LedgerEntryTypeContractData, + Pre: &xdr.LedgerEntry{ + Data: BalanceToContractData(usdcID, [32]byte{4}, 0), + }, + Post: &xdr.LedgerEntry{ + Data: BalanceToContractData(usdcID, [32]byte{4}, 100), + }, + }) + assert.NoError(t, err) + + keyHash = getKeyHashForBalance(t, etherID, [32]byte{}) + mockQ.On("GetContractAssetBalances", ctx, []xdr.Hash{keyHash}). + Return([]history.ContractAssetBalance{ + { + KeyHash: keyHash[:], + ContractID: etherID[:], + Amount: "200", + ExpirationLedger: 200, + }, + }, nil).Once() + expectedBalances[keyHash] = "50" + err = set.AddContractData(context.Background(), ingest.Change{ + Type: xdr.LedgerEntryTypeContractData, + Pre: &xdr.LedgerEntry{ + Data: BalanceToContractData(etherID, [32]byte{}, 200), + }, + Post: &xdr.LedgerEntry{ + Data: BalanceToContractData(etherID, [32]byte{}, 50), + }, + }) + assert.NoError(t, err) + + // negative balances will be ignored + err = set.AddContractData(context.Background(), ingest.Change{ + Type: xdr.LedgerEntryTypeContractData, + Pre: &xdr.LedgerEntry{ + Data: BalanceToContractData(etherID, [32]byte{}, 200), + }, + Post: &xdr.LedgerEntry{ + Data: balanceToContractData(etherID, [32]byte{1}, xdr.Int128Parts{Hi: -1, Lo: 0}), + }, + }) + assert.NoError(t, err) + + // negative balances will be ignored + err = set.AddContractData(context.Background(), ingest.Change{ + Type: xdr.LedgerEntryTypeContractData, + Pre: &xdr.LedgerEntry{ + Data: balanceToContractData(etherID, [32]byte{1}, xdr.Int128Parts{Hi: -1, Lo: 0}), + }, + Post: &xdr.LedgerEntry{ + Data: BalanceToContractData(etherID, [32]byte{}, 200), + }, + }) + assert.NoError(t, err) + + // balances where the amount doesn't change will be ignored + err = set.AddContractData(context.Background(), ingest.Change{ + Type: xdr.LedgerEntryTypeContractData, + Pre: &xdr.LedgerEntry{ + Data: BalanceToContractData(btcID, [32]byte{2}, 300), + }, + Post: &xdr.LedgerEntry{ + Data: BalanceToContractData(btcID, [32]byte{2}, 300), + }, + }) + assert.NoError(t, err) + + keyHash = getKeyHashForBalance(t, btcID, [32]byte{5}) + mockQ.On("GetContractAssetBalances", ctx, []xdr.Hash{keyHash}). + Return([]history.ContractAssetBalance{ + { + KeyHash: keyHash[:], + ContractID: btcID[:], + Amount: "10", + ExpirationLedger: 20, + }, + }, nil).Once() + err = set.AddContractData(context.Background(), ingest.Change{ + Type: xdr.LedgerEntryTypeContractData, + Pre: &xdr.LedgerEntry{ + Data: BalanceToContractData(btcID, [32]byte{5}, 10), + }, + Post: &xdr.LedgerEntry{ + Data: BalanceToContractData(btcID, [32]byte{5}, 15), + }, + }) + assert.ErrorContains(t, err, "contract balance has invalid expiration ledger keyhash") + + keyHash = getKeyHashForBalance(t, btcID, [32]byte{6}) + set.updatedExpirationEntries[keyHash] = [2]uint32{100, 110} + err = set.AddContractData(context.Background(), ingest.Change{ + Type: xdr.LedgerEntryTypeContractData, + Pre: &xdr.LedgerEntry{ + Data: BalanceToContractData(btcID, [32]byte{6}, 120), + }, + Post: &xdr.LedgerEntry{ + Data: BalanceToContractData(btcID, [32]byte{6}, 135), + }, + }) + assert.ErrorContains(t, err, "contract balance has invalid expiration ledger keyhash") + + keyHash = getKeyHashForBalance(t, uniID, [32]byte{4}) + set.updatedExpirationEntries[keyHash] = [2]uint32{100, 170} + expectedBalances[keyHash] = "75" + err = set.AddContractData(context.Background(), ingest.Change{ + Type: xdr.LedgerEntryTypeContractData, + Pre: &xdr.LedgerEntry{ + Data: BalanceToContractData(uniID, [32]byte{4}, 50), + }, + Post: &xdr.LedgerEntry{ + Data: BalanceToContractData(uniID, [32]byte{4}, 75), + }, + }) + assert.NoError(t, err) + + assert.Empty(t, set.contractToAsset) + assert.Empty(t, set.removedBalances) + assert.Empty(t, set.createdExpirationEntries) + for key, amt := range set.updatedBalances { + assert.Equal(t, expectedBalances[key], amt.String()) + delete(expectedBalances, key) + } + assert.Empty(t, expectedBalances) + + assert.ElementsMatch(t, set.GetContractStats(), []history.ContractAssetStatRow{ + { + ContractID: usdcID[:], + Stat: history.ContractStat{ + ActiveBalance: "120", + ActiveHolders: 0, + ArchivedBalance: "0", + ArchivedHolders: 0, + }, + }, + { + ContractID: etherID[:], + Stat: history.ContractStat{ + ActiveBalance: "-150", + ActiveHolders: 0, + ArchivedBalance: "0", + ArchivedHolders: 0, + }, + }, + { + ContractID: uniID[:], + Stat: history.ContractStat{ + ActiveBalance: "75", + ActiveHolders: 1, + ArchivedBalance: "-50", + ArchivedHolders: -1, + }, + }, + }) + + mockQ.AssertExpectations(t) +} + +func TestRemoveContractData(t *testing.T) { + usdcIssuer := keypair.MustRandom().Address() + usdcAsset := xdr.MustNewCreditAsset("USDC", usdcIssuer) + usdcID, err := usdcAsset.ContractID("passphrase") + assert.NoError(t, err) + + set := NewContractAssetStatSet( + &history.MockQAssetStats{}, + "passphrase", + map[xdr.Hash]uint32{}, + map[xdr.Hash]uint32{}, + map[xdr.Hash][2]uint32{}, + 150, + ) + + usdcContractData, err := AssetToContractData(false, "USDC", usdcIssuer, usdcID) + assert.NoError(t, err) + err = set.AddContractData(context.Background(), ingest.Change{ + Type: xdr.LedgerEntryTypeContractData, + Pre: &xdr.LedgerEntry{ + Data: usdcContractData, + }, + }) + assert.NoError(t, err) + + keyHash := getKeyHashForBalance(t, usdcID, [32]byte{}) + set.removedExpirationEntries[keyHash] = 170 + err = set.AddContractData(context.Background(), ingest.Change{ + Type: xdr.LedgerEntryTypeContractData, + Pre: &xdr.LedgerEntry{ + Data: BalanceToContractData(usdcID, [32]byte{}, 50), + }, + }) + assert.NoError(t, err) + + keyHash1 := getKeyHashForBalance(t, usdcID, [32]byte{1}) + set.removedExpirationEntries[keyHash1] = 100 + err = set.AddContractData(context.Background(), ingest.Change{ + Type: xdr.LedgerEntryTypeContractData, + Pre: &xdr.LedgerEntry{ + Data: BalanceToContractData(usdcID, [32]byte{1}, 20), + }, + }) + assert.NoError(t, err) + + keyHash2 := getKeyHashForBalance(t, usdcID, [32]byte{2}) + err = set.AddContractData(context.Background(), ingest.Change{ + Type: xdr.LedgerEntryTypeContractData, + Pre: &xdr.LedgerEntry{ + Data: BalanceToContractData(usdcID, [32]byte{2}, 34), + }, + }) + assert.NoError(t, err) + + assert.Equal(t, []xdr.Hash{keyHash, keyHash1, keyHash2}, set.removedBalances) + assert.Len(t, set.contractToAsset, 1) + asset, ok := set.contractToAsset[usdcID] + assert.Nil(t, asset) + assert.True(t, ok) + + assert.ElementsMatch(t, set.GetContractStats(), []history.ContractAssetStatRow{ + { + ContractID: usdcID[:], + Stat: history.ContractStat{ + ActiveBalance: "-50", + ActiveHolders: -1, + ArchivedBalance: "-20", + ArchivedHolders: -1, + }, + }, + }) +} + +func TestIngestRestoredBalances(t *testing.T) { + usdcIssuer := keypair.MustRandom().Address() + usdcAsset := xdr.MustNewCreditAsset("USDC", usdcIssuer) + usdcID, err := usdcAsset.ContractID("passphrase") + assert.NoError(t, err) + + mockQ := &history.MockQAssetStats{} + set := NewContractAssetStatSet( + mockQ, + "passphrase", + map[xdr.Hash]uint32{}, + map[xdr.Hash]uint32{}, + map[xdr.Hash][2]uint32{}, + 150, + ) + + usdcKeyHash := getKeyHashForBalance(t, usdcID, [32]byte{}) + set.updatedBalances[usdcKeyHash] = big.NewInt(190) + set.updatedExpirationEntries[usdcKeyHash] = [2]uint32{120, 170} + + usdcKeyHash1 := getKeyHashForBalance(t, usdcID, [32]byte{1}) + set.updatedExpirationEntries[usdcKeyHash1] = [2]uint32{149, 190} + + usdcKeyHash2 := getKeyHashForBalance(t, usdcID, [32]byte{2}) + set.updatedExpirationEntries[usdcKeyHash2] = [2]uint32{100, 200} + + usdcKeyHash3 := getKeyHashForBalance(t, usdcID, [32]byte{3}) + set.updatedExpirationEntries[usdcKeyHash3] = [2]uint32{150, 210} + + usdcKeyHash4 := getKeyHashForBalance(t, usdcID, [32]byte{4}) + set.updatedExpirationEntries[usdcKeyHash4] = [2]uint32{170, 900} + + usdcKeyHash5 := getKeyHashForBalance(t, usdcID, [32]byte{5}) + set.updatedExpirationEntries[usdcKeyHash5] = [2]uint32{120, 600} + + ctx := context.Background() + + mockQ.On("GetContractAssetBalances", ctx, mock.MatchedBy(func(keys []xdr.Hash) bool { + return assert.ElementsMatch(t, []xdr.Hash{usdcKeyHash2, usdcKeyHash5}, keys) + })). + Return([]history.ContractAssetBalance{ + { + KeyHash: usdcKeyHash2[:], + ContractID: usdcID[:], + Amount: "67", + ExpirationLedger: 100, + }, + { + KeyHash: usdcKeyHash5[:], + ContractID: usdcID[:], + Amount: "200", + ExpirationLedger: 120, + }, + }, nil).Once() + + assert.NoError(t, set.ingestRestoredBalances(ctx)) + assert.ElementsMatch(t, set.GetContractStats(), []history.ContractAssetStatRow{ + { + ContractID: usdcID[:], + Stat: history.ContractStat{ + ActiveBalance: "267", + ActiveHolders: 2, + ArchivedBalance: "-267", + ArchivedHolders: -2, + }, + }, + }) + + mockQ.AssertExpectations(t) +} + +func TestIngestExpiredBalances(t *testing.T) { + usdcIssuer := keypair.MustRandom().Address() + usdcAsset := xdr.MustNewCreditAsset("USDC", usdcIssuer) + usdcID, err := usdcAsset.ContractID("passphrase") + assert.NoError(t, err) + + etherIssuer := keypair.MustRandom().Address() + etherAsset := xdr.MustNewCreditAsset("ETHER", etherIssuer) + etherID, err := etherAsset.ContractID("passphrase") + assert.NoError(t, err) + + mockQ := &history.MockQAssetStats{} + set := NewContractAssetStatSet( + mockQ, + "passphrase", + map[xdr.Hash]uint32{}, + map[xdr.Hash]uint32{}, + map[xdr.Hash][2]uint32{}, + 150, + ) + + usdcKeyHash := getKeyHashForBalance(t, usdcID, [32]byte{}) + usdcKeyHash1 := getKeyHashForBalance(t, usdcID, [32]byte{1}) + ethKeyHash := getKeyHashForBalance(t, etherID, [32]byte{}) + ethKeyHash1 := getKeyHashForBalance(t, etherID, [32]byte{1}) + set.updatedExpirationEntries[ethKeyHash1] = [2]uint32{149, 180} + ctx := context.Background() + mockQ.On("GetContractAssetBalancesExpiringAt", ctx, set.currentLedger-1). + Return([]history.ContractAssetBalance{ + { + KeyHash: usdcKeyHash[:], + ContractID: usdcID[:], + Amount: "67", + ExpirationLedger: 149, + }, + { + KeyHash: usdcKeyHash1[:], + ContractID: usdcID[:], + Amount: "200", + ExpirationLedger: 149, + }, + { + KeyHash: ethKeyHash[:], + ContractID: etherID[:], + Amount: "8", + ExpirationLedger: 149, + }, + { + KeyHash: ethKeyHash1[:], + ContractID: etherID[:], + Amount: "67", + ExpirationLedger: 149, + }, + }, nil).Once() + + assert.NoError(t, set.ingestExpiredBalances(ctx)) + assert.ElementsMatch(t, set.GetContractStats(), []history.ContractAssetStatRow{ + { + ContractID: usdcID[:], + Stat: history.ContractStat{ + ActiveBalance: "-267", + ActiveHolders: -2, + ArchivedBalance: "267", + ArchivedHolders: 2, + }, + }, + { + ContractID: etherID[:], + Stat: history.ContractStat{ + ActiveBalance: "-8", + ActiveHolders: -1, + ArchivedBalance: "8", + ArchivedHolders: 1, + }, + }, + }) + mockQ.AssertExpectations(t) +} diff --git a/services/horizon/internal/ingest/processors/contract_data.go b/services/horizon/internal/ingest/processors/contract_data.go new file mode 100644 index 0000000000..7b15bd9c5b --- /dev/null +++ b/services/horizon/internal/ingest/processors/contract_data.go @@ -0,0 +1,544 @@ +package processors + +import ( + "math/big" + + "github.com/stellar/go/strkey" + "github.com/stellar/go/xdr" +) + +const ( + scDecimalPrecision = 7 +) + +var ( + // https://github.com/stellar/rs-soroban-env/blob/v0.0.16/soroban-env-host/src/native_contract/token/public_types.rs#L22 + nativeAssetSym = xdr.ScSymbol("Native") + // these are storage DataKey enum + // https://github.com/stellar/rs-soroban-env/blob/v0.0.16/soroban-env-host/src/native_contract/token/storage_types.rs#L23 + balanceMetadataSym = xdr.ScSymbol("Balance") + metadataSym = xdr.ScSymbol("METADATA") + metadataNameSym = xdr.ScSymbol("name") + metadataSymbolSym = xdr.ScSymbol("symbol") + adminSym = xdr.ScSymbol("Admin") + issuerSym = xdr.ScSymbol("issuer") + assetCodeSym = xdr.ScSymbol("asset_code") + alphaNum4Sym = xdr.ScSymbol("AlphaNum4") + alphaNum12Sym = xdr.ScSymbol("AlphaNum12") + decimalSym = xdr.ScSymbol("decimal") + assetInfoSym = xdr.ScSymbol("AssetInfo") + decimalVal = xdr.Uint32(scDecimalPrecision) + assetInfoVec = &xdr.ScVec{ + xdr.ScVal{ + Type: xdr.ScValTypeScvSymbol, + Sym: &assetInfoSym, + }, + } + assetInfoKey = xdr.ScVal{ + Type: xdr.ScValTypeScvVec, + Vec: &assetInfoVec, + } +) + +// AssetFromContractData takes a ledger entry and verifies if the ledger entry +// corresponds to the asset info entry written to contract storage by the Stellar +// Asset Contract upon initialization. +// +// Note that AssetFromContractData will ignore forged asset info entries by +// deriving the Stellar Asset Contract ID from the asset info entry and comparing +// it to the contract ID found in the ledger entry. +// +// If the given ledger entry is a verified asset info entry, +// AssetFromContractData will return the corresponding Stellar asset. Otherwise, +// it returns nil. +// +// References: +// https://github.com/stellar/rs-soroban-env/blob/v0.0.16/soroban-env-host/src/native_contract/token/public_types.rs#L21 +// https://github.com/stellar/rs-soroban-env/blob/v0.0.16/soroban-env-host/src/native_contract/token/asset_info.rs#L6 +// https://github.com/stellar/rs-soroban-env/blob/v0.0.16/soroban-env-host/src/native_contract/token/contract.rs#L115 +// +// The asset info in `ContractData` entry takes the following form: +// +// - Instance storage - it's part of contract instance data storage +// +// - Key: a vector with one element, which is the symbol "AssetInfo" +// +// ScVal{ Vec: ScVec({ ScVal{ Sym: ScSymbol("AssetInfo") }})} +// +// - Value: a map with two key-value pairs: code and issuer +// +// ScVal{ Map: ScMap( +// { ScVal{ Sym: ScSymbol("asset_code") } -> ScVal{ Str: ScString(...) } }, +// { ScVal{ Sym: ScSymbol("issuer") } -> ScVal{ Bytes: ScBytes(...) } } +// )} +func AssetFromContractData(ledgerEntry xdr.LedgerEntry, passphrase string) *xdr.Asset { + contractData, ok := ledgerEntry.Data.GetContractData() + if !ok { + return nil + } + if contractData.Key.Type != xdr.ScValTypeScvLedgerKeyContractInstance { + return nil + } + contractInstanceData, ok := contractData.Val.GetInstance() + if !ok || contractInstanceData.Storage == nil { + return nil + } + + // we don't support asset stats for lumens + nativeAssetContractID, err := xdr.MustNewNativeAsset().ContractID(passphrase) + if err != nil || (contractData.Contract.ContractId != nil && (*contractData.Contract.ContractId) == nativeAssetContractID) { + return nil + } + + var assetInfo *xdr.ScVal + for _, mapEntry := range *contractInstanceData.Storage { + if mapEntry.Key.Equals(assetInfoKey) { + // clone the map entry to avoid reference to loop iterator + mapValXdr, cloneErr := mapEntry.Val.MarshalBinary() + if cloneErr != nil { + return nil + } + assetInfo = &xdr.ScVal{} + cloneErr = assetInfo.UnmarshalBinary(mapValXdr) + if cloneErr != nil { + return nil + } + break + } + } + + if assetInfo == nil { + return nil + } + + vecPtr, ok := assetInfo.GetVec() + if !ok || vecPtr == nil || len(*vecPtr) != 2 { + return nil + } + vec := *vecPtr + + sym, ok := vec[0].GetSym() + if !ok { + return nil + } + switch sym { + case "AlphaNum4": + case "AlphaNum12": + default: + return nil + } + + var assetCode, assetIssuer string + assetMapPtr, ok := vec[1].GetMap() + if !ok || assetMapPtr == nil || len(*assetMapPtr) != 2 { + return nil + } + assetMap := *assetMapPtr + + assetCodeEntry, assetIssuerEntry := assetMap[0], assetMap[1] + if sym, ok = assetCodeEntry.Key.GetSym(); !ok || sym != assetCodeSym { + return nil + } + assetCodeSc, ok := assetCodeEntry.Val.GetStr() + if !ok { + return nil + } + if assetCode = string(assetCodeSc); assetCode == "" { + return nil + } + + if sym, ok = assetIssuerEntry.Key.GetSym(); !ok || sym != issuerSym { + return nil + } + assetIssuerSc, ok := assetIssuerEntry.Val.GetBytes() + if !ok { + return nil + } + assetIssuer, err = strkey.Encode(strkey.VersionByteAccountID, assetIssuerSc) + if err != nil { + return nil + } + + asset, err := xdr.NewCreditAsset(assetCode, assetIssuer) + if err != nil { + return nil + } + + expectedID, err := asset.ContractID(passphrase) + if err != nil { + return nil + } + if contractData.Contract.ContractId == nil || expectedID != *(contractData.Contract.ContractId) { + return nil + } + + return &asset +} + +// ContractBalanceFromContractData takes a ledger entry and verifies that the +// ledger entry corresponds to the balance entry written to contract storage by +// the Stellar Asset Contract. +// +// Reference: +// +// https://github.com/stellar/rs-soroban-env/blob/da325551829d31dcbfa71427d51c18e71a121c5f/soroban-env-host/src/native_contract/token/storage_types.rs#L11-L24 +func ContractBalanceFromContractData(ledgerEntry xdr.LedgerEntry, passphrase string) ([32]byte, *big.Int, bool) { + contractData, ok := ledgerEntry.Data.GetContractData() + if !ok { + return [32]byte{}, nil, false + } + + // we don't support asset stats for lumens + nativeAssetContractID, err := xdr.MustNewNativeAsset().ContractID(passphrase) + if err != nil || (contractData.Contract.ContractId != nil && *contractData.Contract.ContractId == nativeAssetContractID) { + return [32]byte{}, nil, false + } + + keyEnumVecPtr, ok := contractData.Key.GetVec() + if !ok || keyEnumVecPtr == nil { + return [32]byte{}, nil, false + } + keyEnumVec := *keyEnumVecPtr + if len(keyEnumVec) != 2 || !keyEnumVec[0].Equals( + xdr.ScVal{ + Type: xdr.ScValTypeScvSymbol, + Sym: &balanceMetadataSym, + }, + ) { + return [32]byte{}, nil, false + } + + scAddress, ok := keyEnumVec[1].GetAddress() + if !ok { + return [32]byte{}, nil, false + } + + holder, ok := scAddress.GetContractId() + if !ok { + return [32]byte{}, nil, false + } + + balanceMapPtr, ok := contractData.Val.GetMap() + if !ok || balanceMapPtr == nil { + return [32]byte{}, nil, false + } + balanceMap := *balanceMapPtr + if !ok || len(balanceMap) != 3 { + return [32]byte{}, nil, false + } + + var keySym xdr.ScSymbol + if keySym, ok = balanceMap[0].Key.GetSym(); !ok || keySym != "amount" { + return [32]byte{}, nil, false + } + if keySym, ok = balanceMap[1].Key.GetSym(); !ok || keySym != "authorized" || + !balanceMap[1].Val.IsBool() { + return [32]byte{}, nil, false + } + if keySym, ok = balanceMap[2].Key.GetSym(); !ok || keySym != "clawback" || + !balanceMap[2].Val.IsBool() { + return [32]byte{}, nil, false + } + amount, ok := balanceMap[0].Val.GetI128() + if !ok { + return [32]byte{}, nil, false + } + + // amount cannot be negative + // https://github.com/stellar/rs-soroban-env/blob/a66f0815ba06a2f5328ac420950690fd1642f887/soroban-env-host/src/native_contract/token/balance.rs#L92-L93 + if int64(amount.Hi) < 0 { + return [32]byte{}, nil, false + } + amt := new(big.Int).Lsh(new(big.Int).SetInt64(int64(amount.Hi)), 64) + amt.Add(amt, new(big.Int).SetUint64(uint64(amount.Lo))) + return holder, amt, true +} + +func metadataObjFromAsset(isNative bool, code, issuer string) (*xdr.ScMap, error) { + assetInfoVecKey := &xdr.ScVec{ + xdr.ScVal{ + Type: xdr.ScValTypeScvSymbol, + Sym: &assetInfoSym, + }, + } + + if isNative { + nativeVec := &xdr.ScVec{ + xdr.ScVal{ + Type: xdr.ScValTypeScvSymbol, + Sym: &nativeAssetSym, + }, + } + return &xdr.ScMap{ + xdr.ScMapEntry{ + Key: xdr.ScVal{ + Type: xdr.ScValTypeScvVec, + Vec: &assetInfoVecKey, + }, + Val: xdr.ScVal{ + Type: xdr.ScValTypeScvVec, + Vec: &nativeVec, + }, + }, + }, nil + } + + nameVal := xdr.ScString(code + ":" + issuer) + symbolVal := xdr.ScString(code) + metaDataMap := &xdr.ScMap{ + xdr.ScMapEntry{ + Key: xdr.ScVal{ + Type: xdr.ScValTypeScvSymbol, + Sym: &decimalSym, + }, + Val: xdr.ScVal{ + Type: xdr.ScValTypeScvU32, + U32: &decimalVal, + }, + }, + xdr.ScMapEntry{ + Key: xdr.ScVal{ + Type: xdr.ScValTypeScvSymbol, + Sym: &metadataNameSym, + }, + Val: xdr.ScVal{ + Type: xdr.ScValTypeScvString, + Str: &nameVal, + }, + }, + xdr.ScMapEntry{ + Key: xdr.ScVal{ + Type: xdr.ScValTypeScvSymbol, + Sym: &metadataSymbolSym, + }, + Val: xdr.ScVal{ + Type: xdr.ScValTypeScvString, + Str: &symbolVal, + }, + }, + } + + adminVec := &xdr.ScVec{ + xdr.ScVal{ + Type: xdr.ScValTypeScvSymbol, + Sym: &adminSym, + }, + } + + adminAccountId := xdr.MustAddress(issuer) + assetCodeVal := xdr.ScString(code) + issuerBytes, err := strkey.Decode(strkey.VersionByteAccountID, issuer) + if err != nil { + return nil, err + } + + assetIssuerBytes := xdr.ScBytes(issuerBytes) + assetInfoMap := &xdr.ScMap{ + xdr.ScMapEntry{ + Key: xdr.ScVal{ + Type: xdr.ScValTypeScvSymbol, + Sym: &assetCodeSym, + }, + Val: xdr.ScVal{ + Type: xdr.ScValTypeScvString, + Str: &assetCodeVal, + }, + }, + xdr.ScMapEntry{ + Key: xdr.ScVal{ + Type: xdr.ScValTypeScvSymbol, + Sym: &issuerSym, + }, + Val: xdr.ScVal{ + Type: xdr.ScValTypeScvBytes, + Bytes: &assetIssuerBytes, + }, + }, + } + + alphaNumSym := alphaNum4Sym + if len(code) > 4 { + alphaNumSym = alphaNum12Sym + } + assetInfoVecVal := &xdr.ScVec{ + xdr.ScVal{ + Type: xdr.ScValTypeScvSymbol, + Sym: &alphaNumSym, + }, + xdr.ScVal{ + Type: xdr.ScValTypeScvMap, + Map: &assetInfoMap, + }, + } + + storageMap := &xdr.ScMap{ + xdr.ScMapEntry{ + Key: xdr.ScVal{ + Type: xdr.ScValTypeScvSymbol, + Sym: &metadataSym, + }, + Val: xdr.ScVal{ + Type: xdr.ScValTypeScvMap, + Map: &metaDataMap, + }, + }, + xdr.ScMapEntry{ + Key: xdr.ScVal{ + Type: xdr.ScValTypeScvVec, + Vec: &adminVec, + }, + Val: xdr.ScVal{ + Type: xdr.ScValTypeScvAddress, + Address: &xdr.ScAddress{ + AccountId: &adminAccountId, + }, + }, + }, + xdr.ScMapEntry{ + Key: xdr.ScVal{ + Type: xdr.ScValTypeScvVec, + Vec: &assetInfoVecKey, + }, + Val: xdr.ScVal{ + Type: xdr.ScValTypeScvVec, + Vec: &assetInfoVecVal, + }, + }, + } + + return storageMap, nil +} + +// AssetToContractData is the inverse of AssetFromContractData. It creates a +// ledger entry containing the asset info entry written to contract storage by the +// Stellar Asset Contract. +// +// Warning: Only for use in tests. This does not create the accompanied TTLEntry which would typically be created by core. +func AssetToContractData(isNative bool, code, issuer string, contractID [32]byte) (xdr.LedgerEntryData, error) { + storageMap, err := metadataObjFromAsset(isNative, code, issuer) + if err != nil { + return xdr.LedgerEntryData{}, err + } + var ContractIDHash xdr.Hash = contractID + + return xdr.LedgerEntryData{ + Type: xdr.LedgerEntryTypeContractData, + ContractData: &xdr.ContractDataEntry{ + Contract: xdr.ScAddress{ + Type: xdr.ScAddressTypeScAddressTypeContract, + AccountId: nil, + ContractId: &ContractIDHash, + }, + Key: xdr.ScVal{ + Type: xdr.ScValTypeScvLedgerKeyContractInstance, + }, + Durability: xdr.ContractDataDurabilityPersistent, + Val: xdr.ScVal{ + Type: xdr.ScValTypeScvContractInstance, + Instance: &xdr.ScContractInstance{ + Executable: xdr.ContractExecutable{ + Type: xdr.ContractExecutableTypeContractExecutableStellarAsset, + }, + Storage: storageMap, + }, + }, + }, + }, nil +} + +// BalanceToContractData is the inverse of ContractBalanceFromContractData. It +// creates a ledger entry containing the asset balance of a contract holder +// written to contract storage by the Stellar Asset Contract. +// +// Warning: Only for use in tests. This does not create the accompanied TTLEntry which would typically be created by core. +func BalanceToContractData(assetContractId, holderID [32]byte, amt uint64) xdr.LedgerEntryData { + return balanceToContractData(assetContractId, holderID, xdr.Int128Parts{ + Lo: xdr.Uint64(amt), + Hi: 0, + }) +} + +// ContractBalanceLedgerKey constructs the ledger key corresponding to the +// asset balance of a contract holder written to contract storage by the +// Stellar Asset Contract. +func ContractBalanceLedgerKey(assetContractId, holderID [32]byte) xdr.LedgerKey { + holder := xdr.Hash(holderID) + scAddress := &xdr.ScAddress{ + Type: xdr.ScAddressTypeScAddressTypeContract, + ContractId: &holder, + } + keyVec := &xdr.ScVec{ + xdr.ScVal{Type: xdr.ScValTypeScvSymbol, Sym: &balanceMetadataSym}, + xdr.ScVal{Type: xdr.ScValTypeScvAddress, Address: scAddress}, + } + var contractIDHash xdr.Hash = assetContractId + return xdr.LedgerKey{ + Type: xdr.LedgerEntryTypeContractData, + ContractData: &xdr.LedgerKeyContractData{ + Contract: xdr.ScAddress{ + Type: xdr.ScAddressTypeScAddressTypeContract, + ContractId: &contractIDHash, + }, + Key: xdr.ScVal{ + Type: xdr.ScValTypeScvVec, + Vec: &keyVec, + }, + Durability: xdr.ContractDataDurabilityPersistent, + }, + } +} + +func balanceToContractData(assetContractId, holderID [32]byte, amt xdr.Int128Parts) xdr.LedgerEntryData { + ledgerKey := ContractBalanceLedgerKey(assetContractId, holderID) + + amountSym := xdr.ScSymbol("amount") + authorizedSym := xdr.ScSymbol("authorized") + clawbackSym := xdr.ScSymbol("clawback") + trueIc := true + dataMap := &xdr.ScMap{ + xdr.ScMapEntry{ + Key: xdr.ScVal{ + Type: xdr.ScValTypeScvSymbol, + Sym: &amountSym, + }, + Val: xdr.ScVal{ + Type: xdr.ScValTypeScvI128, + I128: &amt, + }, + }, + xdr.ScMapEntry{ + Key: xdr.ScVal{ + Type: xdr.ScValTypeScvSymbol, + Sym: &authorizedSym, + }, + Val: xdr.ScVal{ + Type: xdr.ScValTypeScvBool, + B: &trueIc, + }, + }, + xdr.ScMapEntry{ + Key: xdr.ScVal{ + Type: xdr.ScValTypeScvSymbol, + Sym: &clawbackSym, + }, + Val: xdr.ScVal{ + Type: xdr.ScValTypeScvBool, + B: &trueIc, + }, + }, + } + + contractData := ledgerKey.MustContractData() + return xdr.LedgerEntryData{ + Type: xdr.LedgerEntryTypeContractData, + ContractData: &xdr.ContractDataEntry{ + Contract: contractData.Contract, + Key: contractData.Key, + Durability: contractData.Durability, + Val: xdr.ScVal{ + Type: xdr.ScValTypeScvMap, + Map: &dataMap, + }, + }, + } +} diff --git a/services/horizon/internal/ingest/processors/effects_processor.go b/services/horizon/internal/ingest/processors/effects_processor.go index 0bce813343..34e9f9169a 100644 --- a/services/horizon/internal/ingest/processors/effects_processor.go +++ b/services/horizon/internal/ingest/processors/effects_processor.go @@ -10,157 +10,69 @@ import ( "strconv" "github.com/guregu/null" + "github.com/stellar/go/amount" "github.com/stellar/go/ingest" "github.com/stellar/go/keypair" "github.com/stellar/go/protocols/horizon/base" "github.com/stellar/go/services/horizon/internal/db2/history" + "github.com/stellar/go/strkey" + "github.com/stellar/go/support/contractevents" + "github.com/stellar/go/support/db" "github.com/stellar/go/support/errors" "github.com/stellar/go/xdr" ) // EffectProcessor process effects type EffectProcessor struct { - effects []effect - effectsQ history.QEffects - sequence uint32 + accountLoader *history.AccountLoader + batch history.EffectBatchInsertBuilder + network string } -func NewEffectProcessor(effectsQ history.QEffects, sequence uint32) *EffectProcessor { +func NewEffectProcessor( + accountLoader *history.AccountLoader, + batch history.EffectBatchInsertBuilder, + network string, +) *EffectProcessor { return &EffectProcessor{ - effectsQ: effectsQ, - sequence: sequence, + accountLoader: accountLoader, + batch: batch, + network: network, } } -func (p *EffectProcessor) loadAccountIDs(ctx context.Context, accountSet map[string]int64) error { - addresses := make([]string, 0, len(accountSet)) - for address := range accountSet { - addresses = append(addresses, address) - } - - addressToID, err := p.effectsQ.CreateAccounts(ctx, addresses, maxBatchSize) - if err != nil { - return errors.Wrap(err, "Could not create account ids") - } - - for _, address := range addresses { - id, ok := addressToID[address] - if !ok { - return errors.Errorf("no id found for account address %s", address) - } - - accountSet[address] = id +func (p *EffectProcessor) ProcessTransaction( + lcm xdr.LedgerCloseMeta, transaction ingest.LedgerTransaction, +) error { + // Failed transactions don't have operation effects + if !transaction.Result.Successful() { + return nil } - return nil -} - -func operationsEffects(transaction ingest.LedgerTransaction, sequence uint32) ([]effect, error) { - effects := []effect{} - for opi, op := range transaction.Envelope.Operations() { operation := transactionOperationWrapper{ index: uint32(opi), transaction: transaction, operation: op, - ledgerSequence: sequence, + ledgerSequence: uint32(lcm.LedgerSequence()), + network: p.network, } - - p, err := operation.effects() - if err != nil { - return effects, errors.Wrapf(err, "reading operation %v effects", operation.ID()) + if err := operation.ingestEffects(p.accountLoader, p.batch); err != nil { + return errors.Wrapf(err, "reading operation %v effects", operation.ID()) } - effects = append(effects, p...) - } - - return effects, nil -} - -func (p *EffectProcessor) insertDBOperationsEffects(ctx context.Context, effects []effect, accountSet map[string]int64) error { - batch := p.effectsQ.NewEffectBatchInsertBuilder(maxBatchSize) - - for _, effect := range effects { - accountID, found := accountSet[effect.address] - - if !found { - return errors.Errorf("Error finding history_account_id for address %v", effect.address) - } - - var detailsJSON []byte - detailsJSON, err := json.Marshal(effect.details) - - if err != nil { - return errors.Wrapf(err, "Error marshaling details for operation effect %v", effect.operationID) - } - - if err := batch.Add(ctx, - accountID, - effect.addressMuxed, - effect.operationID, - effect.order, - effect.effectType, - detailsJSON, - ); err != nil { - return errors.Wrap(err, "could not insert operation effect in db") - } - } - - if err := batch.Exec(ctx); err != nil { - return errors.Wrap(err, "could not flush operation effects to db") } return nil } -func (p *EffectProcessor) ProcessTransaction(ctx context.Context, transaction ingest.LedgerTransaction) (err error) { - // Failed transactions don't have operation effects - if !transaction.Result.Successful() { - return nil - } - - var effectsForTx []effect - effectsForTx, err = operationsEffects(transaction, p.sequence) - if err != nil { - return err - } - p.effects = append(p.effects, effectsForTx...) - - return nil -} - -func (p *EffectProcessor) Commit(ctx context.Context) (err error) { - if len(p.effects) > 0 { - accountSet := map[string]int64{} - - for _, effect := range p.effects { - accountSet[effect.address] = 0 - } - - if err = p.loadAccountIDs(ctx, accountSet); err != nil { - return err - } - - if err = p.insertDBOperationsEffects(ctx, p.effects, accountSet); err != nil { - return err - } - } - - return err -} - -type effect struct { - address string - addressMuxed null.String - operationID int64 - details map[string]interface{} - effectType history.EffectType - order uint32 +func (p *EffectProcessor) Flush(ctx context.Context, session db.SessionInterface) (err error) { + return p.batch.Exec(ctx, session) } -// Effects returns the operation effects -func (operation *transactionOperationWrapper) effects() ([]effect, error) { +// ingestEffects adds effects from the operation to the given EffectBatchInsertBuilder +func (operation *transactionOperationWrapper) ingestEffects(accountLoader *history.AccountLoader, batch history.EffectBatchInsertBuilder) error { if !operation.transaction.Result.Successful() { - return []effect{}, nil + return nil } var ( op = operation.operation @@ -169,19 +81,21 @@ func (operation *transactionOperationWrapper) effects() ([]effect, error) { changes, err := operation.transaction.GetOperationChanges(operation.index) if err != nil { - return nil, err + return err } wrapper := &effectsWrapper{ - effects: []effect{}, - operation: operation, + accountLoader: accountLoader, + batch: batch, + order: 1, + operation: operation, } switch operation.OperationType() { case xdr.OperationTypeCreateAccount: - wrapper.addAccountCreatedEffects() + err = wrapper.addAccountCreatedEffects() case xdr.OperationTypePayment: - wrapper.addPaymentEffects() + err = wrapper.addPaymentEffects() case xdr.OperationTypePathPaymentStrictReceive: err = wrapper.pathPaymentStrictReceiveEffects() case xdr.OperationTypePathPaymentStrictSend: @@ -193,15 +107,15 @@ func (operation *transactionOperationWrapper) effects() ([]effect, error) { case xdr.OperationTypeCreatePassiveSellOffer: err = wrapper.addCreatePassiveSellOfferEffect() case xdr.OperationTypeSetOptions: - wrapper.addSetOptionsEffects() + err = wrapper.addSetOptionsEffects() case xdr.OperationTypeChangeTrust: err = wrapper.addChangeTrustEffects() case xdr.OperationTypeAllowTrust: err = wrapper.addAllowTrustEffects() case xdr.OperationTypeAccountMerge: - wrapper.addAccountMergeEffects() + err = wrapper.addAccountMergeEffects() case xdr.OperationTypeInflation: - wrapper.addInflationEffects() + err = wrapper.addInflationEffects() case xdr.OperationTypeManageData: err = wrapper.addManageDataEffects() case xdr.OperationTypeBumpSequence: @@ -210,8 +124,11 @@ func (operation *transactionOperationWrapper) effects() ([]effect, error) { err = wrapper.addCreateClaimableBalanceEffects(changes) case xdr.OperationTypeClaimClaimableBalance: err = wrapper.addClaimClaimableBalanceEffects(changes) - case xdr.OperationTypeBeginSponsoringFutureReserves, xdr.OperationTypeEndSponsoringFutureReserves, xdr.OperationTypeRevokeSponsorship: - // The effects of these operations are obtained indirectly from the ledger entries + case xdr.OperationTypeBeginSponsoringFutureReserves, + xdr.OperationTypeEndSponsoringFutureReserves, + xdr.OperationTypeRevokeSponsorship: + // The effects of these operations are obtained indirectly from the + // ledger entries case xdr.OperationTypeClawback: err = wrapper.addClawbackEffects() case xdr.OperationTypeClawbackClaimableBalance: @@ -222,11 +139,25 @@ func (operation *transactionOperationWrapper) effects() ([]effect, error) { err = wrapper.addLiquidityPoolDepositEffect() case xdr.OperationTypeLiquidityPoolWithdraw: err = wrapper.addLiquidityPoolWithdrawEffect() + case xdr.OperationTypeInvokeHostFunction: + // If there's an invokeHostFunction operation, there's definitely V3 + // meta in the transaction, which means this error is real. + diagnosticEvents, innerErr := operation.transaction.GetDiagnosticEvents() + if innerErr != nil { + return innerErr + } + + // For now, the only effects are related to the events themselves. + // Possible add'l work: https://github.com/stellar/go/issues/4585 + err = wrapper.addInvokeHostFunctionEffects(filterEvents(diagnosticEvents)) + case xdr.OperationTypeExtendFootprintTtl, xdr.OperationTypeRestoreFootprint: + // do not produce effects for these operations as horizon only provides + // limited visibility into soroban operations default: - return nil, fmt.Errorf("Unknown operation type: %s", op.Body.Type) + err = fmt.Errorf("Unknown operation type: %s", op.Body.Type) } if err != nil { - return nil, err + return err } // Effects generated for multiple operations. Keep the effect categories @@ -235,48 +166,75 @@ func (operation *transactionOperationWrapper) effects() ([]effect, error) { // Sponsorships for _, change := range changes { - if err = wrapper.addLedgerEntrySponsorshipEffects(change); err != nil { - return nil, err + if err := wrapper.addLedgerEntrySponsorshipEffects(change); err != nil { + return err + } + if err := wrapper.addSignerSponsorshipEffects(change); err != nil { + return err } - wrapper.addSignerSponsorshipEffects(change) } // Liquidity pools for _, change := range changes { + // Effects caused by ChangeTrust (creation), AllowTrust and SetTrustlineFlags (removal through revocation) - wrapper.addLedgerEntryLiquidityPoolEffects(change) + if err := wrapper.addLedgerEntryLiquidityPoolEffects(change); err != nil { + return err + } } - return wrapper.effects, nil + return nil +} + +func filterEvents(diagnosticEvents []xdr.DiagnosticEvent) []xdr.ContractEvent { + var filtered []xdr.ContractEvent + for _, diagnosticEvent := range diagnosticEvents { + if !diagnosticEvent.InSuccessfulContractCall || diagnosticEvent.Event.Type != xdr.ContractEventTypeContract { + continue + } + filtered = append(filtered, diagnosticEvent.Event) + } + return filtered } type effectsWrapper struct { - effects []effect - operation *transactionOperationWrapper + accountLoader *history.AccountLoader + batch history.EffectBatchInsertBuilder + order uint32 + operation *transactionOperationWrapper } -func (e *effectsWrapper) add(address string, addressMuxed null.String, effectType history.EffectType, details map[string]interface{}) { - e.effects = append(e.effects, effect{ - address: address, - addressMuxed: addressMuxed, - operationID: e.operation.ID(), - effectType: effectType, - order: uint32(len(e.effects) + 1), - details: details, - }) +func (e *effectsWrapper) add(address string, addressMuxed null.String, effectType history.EffectType, details map[string]interface{}) error { + detailsJSON, err := json.Marshal(details) + if err != nil { + return errors.Wrapf(err, "Error marshaling details for operation effect %v", e.operation.ID()) + } + + if err := e.batch.Add( + e.accountLoader.GetFuture(address), + addressMuxed, + e.operation.ID(), + e.order, + effectType, + detailsJSON, + ); err != nil { + return errors.Wrap(err, "could not insert operation effect in db") + } + e.order++ + return nil } -func (e *effectsWrapper) addUnmuxed(address *xdr.AccountId, effectType history.EffectType, details map[string]interface{}) { - e.add(address.Address(), null.String{}, effectType, details) +func (e *effectsWrapper) addUnmuxed(address *xdr.AccountId, effectType history.EffectType, details map[string]interface{}) error { + return e.add(address.Address(), null.String{}, effectType, details) } -func (e *effectsWrapper) addMuxed(address *xdr.MuxedAccount, effectType history.EffectType, details map[string]interface{}) { +func (e *effectsWrapper) addMuxed(address *xdr.MuxedAccount, effectType history.EffectType, details map[string]interface{}) error { var addressMuxed null.String if address.Type == xdr.CryptoKeyTypeKeyTypeMuxedEd25519 { addressMuxed = null.StringFrom(address.Address()) } accID := address.ToAccountId() - e.add(accID.Address(), addressMuxed, effectType, details) + return e.add(accID.Address(), addressMuxed, effectType, details) } var sponsoringEffectsTable = map[xdr.LedgerEntryType]struct { @@ -307,9 +265,9 @@ var sponsoringEffectsTable = map[xdr.LedgerEntryType]struct { // entries because we don't generate creation effects for them. } -func (e *effectsWrapper) addSignerSponsorshipEffects(change ingest.Change) { +func (e *effectsWrapper) addSignerSponsorshipEffects(change ingest.Change) error { if change.Type != xdr.LedgerEntryTypeAccount { - return + return nil } preSigners := map[string]xdr.AccountId{} @@ -347,12 +305,16 @@ func (e *effectsWrapper) addSignerSponsorshipEffects(change ingest.Change) { details["sponsor"] = post.Address() details["signer"] = signer srcAccount := change.Post.Data.MustAccount().AccountId - e.addUnmuxed(&srcAccount, history.EffectSignerSponsorshipCreated, details) + if err := e.addUnmuxed(&srcAccount, history.EffectSignerSponsorshipCreated, details); err != nil { + return err + } case !foundPost && foundPre: details["former_sponsor"] = pre.Address() details["signer"] = signer srcAccount := change.Pre.Data.MustAccount().AccountId - e.addUnmuxed(&srcAccount, history.EffectSignerSponsorshipRemoved, details) + if err := e.addUnmuxed(&srcAccount, history.EffectSignerSponsorshipRemoved, details); err != nil { + return err + } case foundPre && foundPost: formerSponsor := pre.Address() newSponsor := post.Address() @@ -364,9 +326,12 @@ func (e *effectsWrapper) addSignerSponsorshipEffects(change ingest.Change) { details["new_sponsor"] = newSponsor details["signer"] = signer srcAccount := change.Post.Data.MustAccount().AccountId - e.addUnmuxed(&srcAccount, history.EffectSignerSponsorshipUpdated, details) + if err := e.addUnmuxed(&srcAccount, history.EffectSignerSponsorshipUpdated, details); err != nil { + return err + } } } + return nil } func (e *effectsWrapper) addLedgerEntrySponsorshipEffects(change ingest.Change) error { @@ -444,9 +409,13 @@ func (e *effectsWrapper) addLedgerEntrySponsorshipEffects(change ingest.Change) } if accountID != nil { - e.addUnmuxed(accountID, effectType, details) + if err := e.addUnmuxed(accountID, effectType, details); err != nil { + return err + } } else { - e.addMuxed(muxedAccount, effectType, details) + if err := e.addMuxed(muxedAccount, effectType, details); err != nil { + return err + } } return nil @@ -474,55 +443,64 @@ func (e *effectsWrapper) addLedgerEntryLiquidityPoolEffects(change ingest.Change default: return nil } - e.addMuxed( + return e.addMuxed( e.operation.SourceAccount(), effectType, details, ) - - return nil } -func (e *effectsWrapper) addAccountCreatedEffects() { +func (e *effectsWrapper) addAccountCreatedEffects() error { op := e.operation.operation.Body.MustCreateAccountOp() - e.addUnmuxed( + if err := e.addUnmuxed( &op.Destination, history.EffectAccountCreated, map[string]interface{}{ "starting_balance": amount.String(op.StartingBalance), }, - ) - e.addMuxed( + ); err != nil { + return err + } + if err := e.addMuxed( e.operation.SourceAccount(), history.EffectAccountDebited, map[string]interface{}{ "asset_type": "native", "amount": amount.String(op.StartingBalance), }, - ) - e.addUnmuxed( + ); err != nil { + return err + } + if err := e.addUnmuxed( &op.Destination, history.EffectSignerCreated, map[string]interface{}{ "public_key": op.Destination.Address(), "weight": keypair.DefaultSignerWeight, }, - ) + ); err != nil { + return err + } + return nil } -func (e *effectsWrapper) addPaymentEffects() { +func (e *effectsWrapper) addPaymentEffects() error { op := e.operation.operation.Body.MustPaymentOp() details := map[string]interface{}{"amount": amount.String(op.Amount)} - addAssetDetails(details, op.Asset, "") + if err := addAssetDetails(details, op.Asset, ""); err != nil { + return err + } - e.addMuxed( + if err := e.addMuxed( &op.Destination, history.EffectAccountCredited, details, - ) - e.addMuxed( + ); err != nil { + return err + } + return e.addMuxed( e.operation.SourceAccount(), history.EffectAccountDebited, details, @@ -535,23 +513,31 @@ func (e *effectsWrapper) pathPaymentStrictReceiveEffects() error { source := e.operation.SourceAccount() details := map[string]interface{}{"amount": amount.String(op.DestAmount)} - addAssetDetails(details, op.DestAsset, "") + if err := addAssetDetails(details, op.DestAsset, ""); err != nil { + return err + } - e.addMuxed( + if err := e.addMuxed( &op.Destination, history.EffectAccountCredited, details, - ) + ); err != nil { + return err + } result := e.operation.OperationResult().MustPathPaymentStrictReceiveResult() details = map[string]interface{}{"amount": amount.String(result.SendAmount())} - addAssetDetails(details, op.SendAsset, "") + if err := addAssetDetails(details, op.SendAsset, ""); err != nil { + return err + } - e.addMuxed( + if err := e.addMuxed( source, history.EffectAccountDebited, details, - ) + ); err != nil { + return err + } return e.addIngestTradeEffects(*source, resultSuccess.Offers) } @@ -563,12 +549,20 @@ func (e *effectsWrapper) addPathPaymentStrictSendEffects() error { result := e.operation.OperationResult().MustPathPaymentStrictSendResult() details := map[string]interface{}{"amount": amount.String(result.DestAmount())} - addAssetDetails(details, op.DestAsset, "") - e.addMuxed(&op.Destination, history.EffectAccountCredited, details) + if err := addAssetDetails(details, op.DestAsset, ""); err != nil { + return err + } + if err := e.addMuxed(&op.Destination, history.EffectAccountCredited, details); err != nil { + return err + } details = map[string]interface{}{"amount": amount.String(op.SendAmount)} - addAssetDetails(details, op.SendAsset, "") - e.addMuxed(source, history.EffectAccountDebited, details) + if err := addAssetDetails(details, op.SendAsset, ""); err != nil { + return err + } + if err := e.addMuxed(source, history.EffectAccountDebited, details); err != nil { + return err + } return e.addIngestTradeEffects(*source, resultSuccess.Offers) } @@ -607,11 +601,13 @@ func (e *effectsWrapper) addSetOptionsEffects() error { op := e.operation.operation.Body.MustSetOptionsOp() if op.HomeDomain != nil { - e.addMuxed(source, history.EffectAccountHomeDomainUpdated, + if err := e.addMuxed(source, history.EffectAccountHomeDomainUpdated, map[string]interface{}{ "home_domain": string(*op.HomeDomain), }, - ) + ); err != nil { + return err + } } thresholdDetails := map[string]interface{}{} @@ -629,7 +625,9 @@ func (e *effectsWrapper) addSetOptionsEffects() error { } if len(thresholdDetails) > 0 { - e.addMuxed(source, history.EffectAccountThresholdsUpdated, thresholdDetails) + if err := e.addMuxed(source, history.EffectAccountThresholdsUpdated, thresholdDetails); err != nil { + return err + } } flagDetails := map[string]interface{}{} @@ -641,15 +639,19 @@ func (e *effectsWrapper) addSetOptionsEffects() error { } if len(flagDetails) > 0 { - e.addMuxed(source, history.EffectAccountFlagsUpdated, flagDetails) + if err := e.addMuxed(source, history.EffectAccountFlagsUpdated, flagDetails); err != nil { + return err + } } if op.InflationDest != nil { - e.addMuxed(source, history.EffectAccountInflationDestinationUpdated, + if err := e.addMuxed(source, history.EffectAccountInflationDestinationUpdated, map[string]interface{}{ "inflation_destination": op.InflationDest.Address(), }, - ) + ); err != nil { + return err + } } changes, err := e.operation.transaction.GetOperationChanges(e.operation.index) if err != nil { @@ -672,7 +674,7 @@ func (e *effectsWrapper) addSetOptionsEffects() error { continue } - beforeSortedSigners := []string{} + var beforeSortedSigners []string for signer := range before { beforeSortedSigners = append(beforeSortedSigners, signer) } @@ -681,21 +683,25 @@ func (e *effectsWrapper) addSetOptionsEffects() error { for _, addy := range beforeSortedSigners { weight, ok := after[addy] if !ok { - e.addMuxed(source, history.EffectSignerRemoved, map[string]interface{}{ + if err := e.addMuxed(source, history.EffectSignerRemoved, map[string]interface{}{ "public_key": addy, - }) + }); err != nil { + return err + } continue } if weight != before[addy] { - e.addMuxed(source, history.EffectSignerUpdated, map[string]interface{}{ + if err := e.addMuxed(source, history.EffectSignerUpdated, map[string]interface{}{ "public_key": addy, "weight": weight, - }) + }); err != nil { + return err + } } } - afterSortedSigners := []string{} + var afterSortedSigners []string for signer := range after { afterSortedSigners = append(afterSortedSigners, signer) } @@ -710,10 +716,12 @@ func (e *effectsWrapper) addSetOptionsEffects() error { continue } - e.addMuxed(source, history.EffectSignerCreated, map[string]interface{}{ + if err := e.addMuxed(source, history.EffectSignerCreated, map[string]interface{}{ "public_key": addy, "weight": weight, - }) + }); err != nil { + return err + } } } return nil @@ -769,10 +777,14 @@ func (e *effectsWrapper) addChangeTrustEffects() error { return err } } else { - addAssetDetails(details, op.Line.ToAsset(), "") + if err := addAssetDetails(details, op.Line.ToAsset(), ""); err != nil { + return err + } } - e.addMuxed(source, effect, details) + if err := e.addMuxed(source, effect, details); err != nil { + return err + } break } @@ -786,33 +798,47 @@ func (e *effectsWrapper) addAllowTrustEffects() error { details := map[string]interface{}{ "trustor": op.Trustor.Address(), } - addAssetDetails(details, asset, "") + if err := addAssetDetails(details, asset, ""); err != nil { + return err + } switch { case xdr.TrustLineFlags(op.Authorize).IsAuthorized(): - e.addMuxed(source, history.EffectTrustlineAuthorized, details) + if err := e.addMuxed(source, history.EffectTrustlineAuthorized, details); err != nil { + return err + } // Forward compatibility setFlags := xdr.Uint32(xdr.TrustLineFlagsAuthorizedFlag) - e.addTrustLineFlagsEffect(source, &op.Trustor, asset, &setFlags, nil) + if err := e.addTrustLineFlagsEffect(source, &op.Trustor, asset, &setFlags, nil); err != nil { + return err + } case xdr.TrustLineFlags(op.Authorize).IsAuthorizedToMaintainLiabilitiesFlag(): - e.addMuxed( + if err := e.addMuxed( source, history.EffectTrustlineAuthorizedToMaintainLiabilities, details, - ) + ); err != nil { + return err + } // Forward compatibility setFlags := xdr.Uint32(xdr.TrustLineFlagsAuthorizedToMaintainLiabilitiesFlag) - e.addTrustLineFlagsEffect(source, &op.Trustor, asset, &setFlags, nil) + if err := e.addTrustLineFlagsEffect(source, &op.Trustor, asset, &setFlags, nil); err != nil { + return err + } default: - e.addMuxed(source, history.EffectTrustlineDeauthorized, details) + if err := e.addMuxed(source, history.EffectTrustlineDeauthorized, details); err != nil { + return err + } // Forward compatibility, show both as cleared clearFlags := xdr.Uint32(xdr.TrustLineFlagsAuthorizedFlag | xdr.TrustLineFlagsAuthorizedToMaintainLiabilitiesFlag) - e.addTrustLineFlagsEffect(source, &op.Trustor, asset, nil, &clearFlags) + if err := e.addTrustLineFlagsEffect(source, &op.Trustor, asset, nil, &clearFlags); err != nil { + return err + } } return e.addLiquidityPoolRevokedEffect() } -func (e *effectsWrapper) addAccountMergeEffects() { +func (e *effectsWrapper) addAccountMergeEffects() error { source := e.operation.SourceAccount() dest := e.operation.operation.Body.MustDestination() @@ -822,21 +848,31 @@ func (e *effectsWrapper) addAccountMergeEffects() { "asset_type": "native", } - e.addMuxed(source, history.EffectAccountDebited, details) - e.addMuxed(&dest, history.EffectAccountCredited, details) - e.addMuxed(source, history.EffectAccountRemoved, map[string]interface{}{}) + if err := e.addMuxed(source, history.EffectAccountDebited, details); err != nil { + return err + } + if err := e.addMuxed(&dest, history.EffectAccountCredited, details); err != nil { + return err + } + if err := e.addMuxed(source, history.EffectAccountRemoved, map[string]interface{}{}); err != nil { + return err + } + return nil } -func (e *effectsWrapper) addInflationEffects() { +func (e *effectsWrapper) addInflationEffects() error { payouts := e.operation.OperationResult().MustInflationResult().MustPayouts() for _, payout := range payouts { - e.addUnmuxed(&payout.Destination, history.EffectAccountCredited, + if err := e.addUnmuxed(&payout.Destination, history.EffectAccountCredited, map[string]interface{}{ "amount": amount.String(payout.Amount), "asset_type": "native", }, - ) + ); err != nil { + return err + } } + return nil } func (e *effectsWrapper) addManageDataEffects() error { @@ -876,8 +912,7 @@ func (e *effectsWrapper) addManageDataEffects() error { break } - e.addMuxed(source, effect, details) - return nil + return e.addMuxed(source, effect, details) } func (e *effectsWrapper) addBumpSequenceEffects() error { @@ -900,7 +935,9 @@ func (e *effectsWrapper) addBumpSequenceEffects() error { if beforeAccount.SeqNum != afterAccount.SeqNum { details := map[string]interface{}{"new_seq": afterAccount.SeqNum} - e.addMuxed(source, history.EffectSequenceBumped, details) + if err := e.addMuxed(source, history.EffectSequenceBumped, details); err != nil { + return err + } } break } @@ -923,7 +960,9 @@ func (e *effectsWrapper) addCreateClaimableBalanceEffects(changes []ingest.Chang continue } cb = change.Post.Data.ClaimableBalance - e.addClaimableBalanceEntryCreatedEffects(source, cb) + if err := e.addClaimableBalanceEntryCreatedEffects(source, cb); err != nil { + return err + } break } if cb == nil { @@ -933,14 +972,14 @@ func (e *effectsWrapper) addCreateClaimableBalanceEffects(changes []ingest.Chang details := map[string]interface{}{ "amount": amount.String(cb.Amount), } - addAssetDetails(details, cb.Asset, "") - e.addMuxed( + if err := addAssetDetails(details, cb.Asset, ""); err != nil { + return err + } + return e.addMuxed( source, history.EffectAccountDebited, details, ) - - return nil } func (e *effectsWrapper) addClaimableBalanceEntryCreatedEffects(source *xdr.MuxedAccount, cb *xdr.ClaimableBalanceEntry) error { @@ -954,11 +993,13 @@ func (e *effectsWrapper) addClaimableBalanceEntryCreatedEffects(source *xdr.Muxe "asset": cb.Asset.StringCanonical(), } setClaimableBalanceFlagDetails(details, cb.Flags()) - e.addMuxed( + if err := e.addMuxed( source, history.EffectClaimableBalanceCreated, details, - ) + ); err != nil { + return err + } // EffectClaimableBalanceClaimantCreated can be generated by // `create_claimable_balance` operation but also by `liquidity_pool_withdraw` // operation causing a revocation. @@ -974,7 +1015,7 @@ func (e *effectsWrapper) addClaimableBalanceEntryCreatedEffects(source *xdr.Muxe } for _, c := range claimants { cv0 := c.MustV0() - e.addUnmuxed( + if err := e.addUnmuxed( &cv0.Destination, history.EffectClaimableBalanceClaimantCreated, map[string]interface{}{ @@ -983,9 +1024,11 @@ func (e *effectsWrapper) addClaimableBalanceEntryCreatedEffects(source *xdr.Muxe "predicate": cv0.Predicate, "asset": cb.Asset.StringCanonical(), }, - ) + ); err != nil { + return err + } } - return err + return nil } func (e *effectsWrapper) addClaimClaimableBalanceEffects(changes []ingest.Change) error { @@ -1028,23 +1071,25 @@ func (e *effectsWrapper) addClaimClaimableBalanceEffects(changes []ingest.Change } setClaimableBalanceFlagDetails(details, cBalance.Flags()) source := e.operation.SourceAccount() - e.addMuxed( + if err := e.addMuxed( source, history.EffectClaimableBalanceClaimed, details, - ) + ); err != nil { + return err + } details = map[string]interface{}{ "amount": amount.String(cBalance.Amount), } - addAssetDetails(details, cBalance.Asset, "") - e.addMuxed( + if err := addAssetDetails(details, cBalance.Asset, ""); err != nil { + return err + } + return e.addMuxed( source, history.EffectAccountCredited, details, ) - - return nil } func (e *effectsWrapper) addIngestTradeEffects(buyer xdr.MuxedAccount, claims []xdr.ClaimAtom) error { @@ -1058,23 +1103,30 @@ func (e *effectsWrapper) addIngestTradeEffects(buyer xdr.MuxedAccount, claims [] return err } default: - e.addClaimTradeEffects(buyer, claim) + if err := e.addClaimTradeEffects(buyer, claim); err != nil { + return err + } } } return nil } -func (e *effectsWrapper) addClaimTradeEffects(buyer xdr.MuxedAccount, claim xdr.ClaimAtom) { +func (e *effectsWrapper) addClaimTradeEffects(buyer xdr.MuxedAccount, claim xdr.ClaimAtom) error { seller := claim.SellerId() - bd, sd := tradeDetails(buyer, seller, claim) + bd, sd, err := tradeDetails(buyer, seller, claim) + if err != nil { + return err + } - e.addMuxed( + if err := e.addMuxed( &buyer, history.EffectTrade, bd, - ) + ); err != nil { + return err + } - e.addUnmuxed( + return e.addUnmuxed( &seller, history.EffectTrade, sd, @@ -1097,8 +1149,7 @@ func (e *effectsWrapper) addClaimLiquidityPoolTradeEffect(claim xdr.ClaimAtom) e "amount": amount.String(claim.LiquidityPool.AmountBought), }, } - e.addMuxed(e.operation.SourceAccount(), history.EffectLiquidityPoolTrade, details) - return nil + return e.addMuxed(e.operation.SourceAccount(), history.EffectLiquidityPoolTrade, details) } func (e *effectsWrapper) addClawbackEffects() error { @@ -1107,20 +1158,26 @@ func (e *effectsWrapper) addClawbackEffects() error { "amount": amount.String(op.Amount), } source := e.operation.SourceAccount() - addAssetDetails(details, op.Asset, "") + if err := addAssetDetails(details, op.Asset, ""); err != nil { + return err + } // The funds will be burned, but even with that, we generated an account credited effect - e.addMuxed( + if err := e.addMuxed( source, history.EffectAccountCredited, details, - ) + ); err != nil { + return err + } - e.addMuxed( + if err := e.addMuxed( &op.From, history.EffectAccountDebited, details, - ) + ); err != nil { + return err + } return nil } @@ -1135,23 +1192,29 @@ func (e *effectsWrapper) addClawbackClaimableBalanceEffects(changes []ingest.Cha "balance_id": balanceId, } source := e.operation.SourceAccount() - e.addMuxed( + if err := e.addMuxed( source, history.EffectClaimableBalanceClawedBack, details, - ) + ); err != nil { + return err + } // Generate the account credited effect (although the funds will be burned) for the asset issuer for _, c := range changes { if c.Type == xdr.LedgerEntryTypeClaimableBalance && c.Post == nil && c.Pre != nil { cb := c.Pre.Data.ClaimableBalance details = map[string]interface{}{"amount": amount.String(cb.Amount)} - addAssetDetails(details, cb.Asset, "") - e.addMuxed( + if err := addAssetDetails(details, cb.Asset, ""); err != nil { + return err + } + if err := e.addMuxed( source, history.EffectAccountCredited, details, - ) + ); err != nil { + return err + } break } } @@ -1162,7 +1225,9 @@ func (e *effectsWrapper) addClawbackClaimableBalanceEffects(changes []ingest.Cha func (e *effectsWrapper) addSetTrustLineFlagsEffects() error { source := e.operation.SourceAccount() op := e.operation.operation.Body.MustSetTrustLineFlagsOp() - e.addTrustLineFlagsEffect(source, &op.Trustor, op.Asset, &op.SetFlags, &op.ClearFlags) + if err := e.addTrustLineFlagsEffect(source, &op.Trustor, op.Asset, &op.SetFlags, &op.ClearFlags); err != nil { + return err + } return e.addLiquidityPoolRevokedEffect() } @@ -1171,11 +1236,13 @@ func (e *effectsWrapper) addTrustLineFlagsEffect( trustor *xdr.AccountId, asset xdr.Asset, setFlags *xdr.Uint32, - clearFlags *xdr.Uint32) { + clearFlags *xdr.Uint32) error { details := map[string]interface{}{ "trustor": trustor.Address(), } - addAssetDetails(details, asset, "") + if err := addAssetDetails(details, asset, ""); err != nil { + return err + } var flagDetailsAdded bool if setFlags != nil { @@ -1188,8 +1255,11 @@ func (e *effectsWrapper) addTrustLineFlagsEffect( } if flagDetailsAdded { - e.addMuxed(account, history.EffectTrustlineFlagsUpdated, details) + if err := e.addMuxed(account, history.EffectTrustlineFlagsUpdated, details); err != nil { + return err + } } + return nil } func setTrustLineFlagDetails(flagDetails map[string]interface{}, flags xdr.TrustLineFlags, setValue bool) { @@ -1204,12 +1274,6 @@ func setTrustLineFlagDetails(flagDetails map[string]interface{}, flags xdr.Trust } } -type sortableClaimableBalanceEntries []*xdr.ClaimableBalanceEntry - -func (s sortableClaimableBalanceEntries) Len() int { return len(s) } -func (s sortableClaimableBalanceEntries) Less(i, j int) bool { return s[i].Asset.LessThan(s[j].Asset) } -func (s sortableClaimableBalanceEntries) Swap(i, j int) { s[i], s[j] = s[j], s[i] } - func (e *effectsWrapper) addLiquidityPoolRevokedEffect() error { source := e.operation.SourceAccount() lp, delta, err := e.operation.getLiquidityPoolAndProductDelta(nil) @@ -1225,7 +1289,6 @@ func (e *effectsWrapper) addLiquidityPoolRevokedEffect() error { return err } assetToCBID := map[string]string{} - var cbs sortableClaimableBalanceEntries for _, change := range changes { if change.Type == xdr.LedgerEntryTypeClaimableBalance && change.Pre == nil && change.Post != nil { cb := change.Post.Data.ClaimableBalance @@ -1234,21 +1297,15 @@ func (e *effectsWrapper) addLiquidityPoolRevokedEffect() error { return err } assetToCBID[cb.Asset.StringCanonical()] = id - cbs = append(cbs, cb) + if err := e.addClaimableBalanceEntryCreatedEffects(source, cb); err != nil { + return err + } } } if len(assetToCBID) == 0 { // no claimable balances were created, and thus, no revocation happened return nil } - // Core's claimable balance metadata isn't ordered, so we order it ourselves - // so that effects are ordered consistently - sort.Sort(cbs) - for _, cb := range cbs { - if err := e.addClaimableBalanceEntryCreatedEffects(source, cb); err != nil { - return err - } - } reservesRevoked := make([]map[string]string, 0, 2) for _, aa := range []base.AssetAmount{ @@ -1275,8 +1332,8 @@ func (e *effectsWrapper) addLiquidityPoolRevokedEffect() error { "reserves_revoked": reservesRevoked, "shares_revoked": amount.String(-delta.TotalPoolShares), } - e.addMuxed(source, history.EffectLiquidityPoolRevoked, details) - return nil + + return e.addMuxed(source, history.EffectLiquidityPoolRevoked, details) } func setAuthFlagDetails(flagDetails map[string]interface{}, flags xdr.AccountFlags, setValue bool) { @@ -1294,15 +1351,19 @@ func setAuthFlagDetails(flagDetails map[string]interface{}, flags xdr.AccountFla } } -func tradeDetails(buyer xdr.MuxedAccount, seller xdr.AccountId, claim xdr.ClaimAtom) (bd map[string]interface{}, sd map[string]interface{}) { +func tradeDetails(buyer xdr.MuxedAccount, seller xdr.AccountId, claim xdr.ClaimAtom) (bd map[string]interface{}, sd map[string]interface{}, err error) { bd = map[string]interface{}{ "offer_id": claim.OfferId(), "seller": seller.Address(), "bought_amount": amount.String(claim.AmountSold()), "sold_amount": amount.String(claim.AmountBought()), } - addAssetDetails(bd, claim.AssetSold(), "bought_") - addAssetDetails(bd, claim.AssetBought(), "sold_") + if err = addAssetDetails(bd, claim.AssetSold(), "bought_"); err != nil { + return + } + if err = addAssetDetails(bd, claim.AssetBought(), "sold_"); err != nil { + return + } sd = map[string]interface{}{ "offer_id": claim.OfferId(), @@ -1310,9 +1371,12 @@ func tradeDetails(buyer xdr.MuxedAccount, seller xdr.AccountId, claim xdr.ClaimA "sold_amount": amount.String(claim.AmountSold()), } addAccountAndMuxedAccountDetails(sd, buyer, "seller") - addAssetDetails(sd, claim.AssetBought(), "bought_") - addAssetDetails(sd, claim.AssetSold(), "sold_") - + if err = addAssetDetails(sd, claim.AssetBought(), "bought_"); err != nil { + return + } + if err = addAssetDetails(sd, claim.AssetSold(), "sold_"); err != nil { + return + } return } @@ -1356,8 +1420,8 @@ func (e *effectsWrapper) addLiquidityPoolDepositEffect() error { }, "shares_received": amount.String(delta.TotalPoolShares), } - e.addMuxed(e.operation.SourceAccount(), history.EffectLiquidityPoolDeposited, details) - return nil + + return e.addMuxed(e.operation.SourceAccount(), history.EffectLiquidityPoolDeposited, details) } func (e *effectsWrapper) addLiquidityPoolWithdrawEffect() error { @@ -1380,6 +1444,130 @@ func (e *effectsWrapper) addLiquidityPoolWithdrawEffect() error { }, "shares_redeemed": amount.String(-delta.TotalPoolShares), } - e.addMuxed(e.operation.SourceAccount(), history.EffectLiquidityPoolWithdrew, details) + + return e.addMuxed(e.operation.SourceAccount(), history.EffectLiquidityPoolWithdrew, details) +} + +// addInvokeHostFunctionEffects iterates through the events and generates +// account_credited and account_debited effects when it sees events related to +// the Stellar Asset Contract corresponding to those effects. +func (e *effectsWrapper) addInvokeHostFunctionEffects(events []contractevents.Event) error { + if e.operation.network == "" { + return errors.New("invokeHostFunction effects cannot be determined unless network passphrase is set") + } + + source := e.operation.SourceAccount() + for _, event := range events { + evt, err := contractevents.NewStellarAssetContractEvent(&event, e.operation.network) + if err != nil { + continue // irrelevant or unsupported event + } + + details := make(map[string]interface{}, 4) + if err := addAssetDetails(details, evt.GetAsset(), ""); err != nil { + return errors.Wrapf(err, "invokeHostFunction asset details had an error") + } + + // + // Note: We ignore effects that involve contracts (until the day we have + // contract_debited/credited effects, may it never come :pray:) + // + + switch evt.GetType() { + // Transfer events generate an `account_debited` effect for the `from` + // (sender) and an `account_credited` effect for the `to` (recipient). + case contractevents.EventTypeTransfer: + transferEvent := evt.(*contractevents.TransferEvent) + details["amount"] = amount.String128(transferEvent.Amount) + toDetails := map[string]interface{}{} + for key, val := range details { + toDetails[key] = val + } + + if strkey.IsValidEd25519PublicKey(transferEvent.From) { + if err := e.add( + transferEvent.From, + null.String{}, + history.EffectAccountDebited, + details, + ); err != nil { + return errors.Wrapf(err, "invokeHostFunction asset details from contract xfr-from had an error") + } + } else { + details["contract"] = transferEvent.From + e.addMuxed(source, history.EffectContractDebited, details) + } + + if strkey.IsValidEd25519PublicKey(transferEvent.To) { + if err := e.add( + transferEvent.To, + null.String{}, + history.EffectAccountCredited, + toDetails, + ); err != nil { + return errors.Wrapf(err, "invokeHostFunction asset details from contract xfr-to had an error") + } + } else { + toDetails["contract"] = transferEvent.To + e.addMuxed(source, history.EffectContractCredited, toDetails) + } + + // Mint events imply a non-native asset, and it results in a credit to + // the `to` recipient. + case contractevents.EventTypeMint: + mintEvent := evt.(*contractevents.MintEvent) + details["amount"] = amount.String128(mintEvent.Amount) + if strkey.IsValidEd25519PublicKey(mintEvent.To) { + if err := e.add( + mintEvent.To, + null.String{}, + history.EffectAccountCredited, + details, + ); err != nil { + return errors.Wrapf(err, "invokeHostFunction asset details from contract mint had an error") + } + } else { + details["contract"] = mintEvent.To + e.addMuxed(source, history.EffectContractCredited, details) + } + + // Clawback events result in a debit to the `from` address, but acts + // like a burn to the recipient, so these are functionally equivalent + case contractevents.EventTypeClawback: + cbEvent := evt.(*contractevents.ClawbackEvent) + details["amount"] = amount.String128(cbEvent.Amount) + if strkey.IsValidEd25519PublicKey(cbEvent.From) { + if err := e.add( + cbEvent.From, + null.String{}, + history.EffectAccountDebited, + details, + ); err != nil { + return errors.Wrapf(err, "invokeHostFunction asset details from contract clawback had an error") + } + } else { + details["contract"] = cbEvent.From + e.addMuxed(source, history.EffectContractDebited, details) + } + + case contractevents.EventTypeBurn: + burnEvent := evt.(*contractevents.BurnEvent) + details["amount"] = amount.String128(burnEvent.Amount) + if strkey.IsValidEd25519PublicKey(burnEvent.From) { + if err := e.add( + burnEvent.From, + null.String{}, + history.EffectAccountDebited, + details, + ); err != nil { + return errors.Wrapf(err, "invokeHostFunction asset details from contract burn had an error") + } + } else { + details["contract"] = burnEvent.From + e.addMuxed(source, history.EffectContractDebited, details) + } + } + } + return nil } diff --git a/services/horizon/internal/ingest/processors/effects_processor_test.go b/services/horizon/internal/ingest/processors/effects_processor_test.go index 6bb77765e3..0243768fde 100644 --- a/services/horizon/internal/ingest/processors/effects_processor_test.go +++ b/services/horizon/internal/ingest/processors/effects_processor_test.go @@ -4,30 +4,45 @@ package processors import ( "context" + "crypto/rand" "encoding/hex" + "encoding/json" "testing" "github.com/guregu/null" + "math/big" + "strings" + + "github.com/stellar/go/keypair" "github.com/stellar/go/protocols/horizon/base" + "github.com/stellar/go/strkey" + "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/mock" "github.com/stretchr/testify/suite" "github.com/stellar/go/ingest" "github.com/stellar/go/services/horizon/internal/db2/history" . "github.com/stellar/go/services/horizon/internal/test/transactions" + "github.com/stellar/go/support/contractevents" + "github.com/stellar/go/support/db" "github.com/stellar/go/support/errors" "github.com/stellar/go/toid" "github.com/stellar/go/xdr" ) +const ( + networkPassphrase = "Arbitrary Testing Passphrase" +) + type EffectsProcessorTestSuiteLedger struct { suite.Suite ctx context.Context processor *EffectProcessor - mockQ *history.MockQEffects + mockSession *db.MockSession + accountLoader *history.AccountLoader mockBatchInsertBuilder *history.MockEffectBatchInsertBuilder + lcm xdr.LedgerCloseMeta firstTx ingest.LedgerTransaction secondTx ingest.LedgerTransaction thirdTx ingest.LedgerTransaction @@ -36,7 +51,6 @@ type EffectsProcessorTestSuiteLedger struct { secondTxID int64 thirdTxID int64 failedTxID int64 - sequence uint32 addresses []string addressToID map[string]int64 txs []ingest.LedgerTransaction @@ -48,11 +62,18 @@ func TestEffectsProcessorTestSuiteLedger(t *testing.T) { func (s *EffectsProcessorTestSuiteLedger) SetupTest() { s.ctx = context.Background() - s.mockQ = &history.MockQEffects{} + s.accountLoader = history.NewAccountLoader() s.mockBatchInsertBuilder = &history.MockEffectBatchInsertBuilder{} - s.sequence = uint32(20) - + s.lcm = xdr.LedgerCloseMeta{ + V0: &xdr.LedgerCloseMetaV0{ + LedgerHeader: xdr.LedgerHeaderHistoryEntry{ + Header: xdr.LedgerHeader{ + LedgerSeq: xdr.Uint32(20), + }, + }, + }, + } s.addresses = []string{ "GANFZDRBCNTUXIODCJEYMACPMCSZEVE4WZGZ3CZDZ3P2SXK4KH75IK6Y", "GBRPYHIL2CI3FNQ4BXLFMNDLFJUNPU2HY3ZMFSHONUCEOASW7QC7OX2H", @@ -70,7 +91,7 @@ func (s *EffectsProcessorTestSuiteLedger) SetupTest() { Hash: "829d53f2dceebe10af8007564b0aefde819b95734ad431df84270651e7ed8a90", }, ) - s.firstTxID = toid.New(int32(s.sequence), 1, 0).ToInt64() + s.firstTxID = toid.New(int32(s.lcm.LedgerSequence()), 1, 0).ToInt64() s.secondTx = BuildLedgerTransaction( s.Suite.T(), @@ -84,7 +105,7 @@ func (s *EffectsProcessorTestSuiteLedger) SetupTest() { }, ) - s.secondTxID = toid.New(int32(s.sequence), 2, 0).ToInt64() + s.secondTxID = toid.New(int32(s.lcm.LedgerSequence()), 2, 0).ToInt64() s.thirdTx = BuildLedgerTransaction( s.Suite.T(), @@ -97,7 +118,7 @@ func (s *EffectsProcessorTestSuiteLedger) SetupTest() { Hash: "2a805712c6d10f9e74bb0ccf54ae92a2b4b1e586451fe8133a2433816f6b567c", }, ) - s.thirdTxID = toid.New(int32(s.sequence), 3, 0).ToInt64() + s.thirdTxID = toid.New(int32(s.lcm.LedgerSequence()), 3, 0).ToInt64() s.failedTx = BuildLedgerTransaction( s.Suite.T(), @@ -110,7 +131,7 @@ func (s *EffectsProcessorTestSuiteLedger) SetupTest() { Hash: "24206737a02f7f855c46e367418e38c223f897792c76bbfb948e1b0dbd695f8b", }, ) - s.failedTxID = toid.New(int32(s.sequence), 4, 0).ToInt64() + s.failedTxID = toid.New(int32(s.lcm.LedgerSequence()), 4, 0).ToInt64() s.addressToID = map[string]int64{ s.addresses[0]: 2, @@ -119,8 +140,9 @@ func (s *EffectsProcessorTestSuiteLedger) SetupTest() { } s.processor = NewEffectProcessor( - s.mockQ, - 20, + s.accountLoader, + s.mockBatchInsertBuilder, + networkPassphrase, ) s.txs = []ingest.LedgerTransaction{ @@ -131,46 +153,42 @@ func (s *EffectsProcessorTestSuiteLedger) SetupTest() { } func (s *EffectsProcessorTestSuiteLedger) TearDownTest() { - s.mockQ.AssertExpectations(s.T()) + s.mockBatchInsertBuilder.AssertExpectations(s.T()) } func (s *EffectsProcessorTestSuiteLedger) mockSuccessfulEffectBatchAdds() { s.mockBatchInsertBuilder.On( "Add", - s.ctx, - s.addressToID[s.addresses[2]], + s.accountLoader.GetFuture(s.addresses[2]), null.String{}, - toid.New(int32(s.sequence), 1, 1).ToInt64(), + toid.New(int32(s.lcm.LedgerSequence()), 1, 1).ToInt64(), uint32(1), history.EffectSequenceBumped, []byte("{\"new_seq\":300000000000}"), ).Return(nil).Once() s.mockBatchInsertBuilder.On( "Add", - s.ctx, - s.addressToID[s.addresses[2]], + s.accountLoader.GetFuture(s.addresses[2]), null.String{}, - toid.New(int32(s.sequence), 2, 1).ToInt64(), + toid.New(int32(s.lcm.LedgerSequence()), 2, 1).ToInt64(), uint32(1), history.EffectAccountCreated, []byte("{\"starting_balance\":\"1000.0000000\"}"), ).Return(nil).Once() s.mockBatchInsertBuilder.On( "Add", - s.ctx, - s.addressToID[s.addresses[1]], + s.accountLoader.GetFuture(s.addresses[1]), null.String{}, - toid.New(int32(s.sequence), 2, 1).ToInt64(), + toid.New(int32(s.lcm.LedgerSequence()), 2, 1).ToInt64(), uint32(2), history.EffectAccountDebited, []byte("{\"amount\":\"1000.0000000\",\"asset_type\":\"native\"}"), ).Return(nil).Once() s.mockBatchInsertBuilder.On( "Add", - s.ctx, - s.addressToID[s.addresses[2]], + s.accountLoader.GetFuture(s.addresses[2]), null.String{}, - toid.New(int32(s.sequence), 2, 1).ToInt64(), + toid.New(int32(s.lcm.LedgerSequence()), 2, 1).ToInt64(), uint32(3), history.EffectSignerCreated, []byte("{\"public_key\":\"GCQZP3IU7XU6EJ63JZXKCQOYT2RNXN3HB5CNHENNUEUHSMA4VUJJJSEN\",\"weight\":1}"), @@ -178,10 +196,9 @@ func (s *EffectsProcessorTestSuiteLedger) mockSuccessfulEffectBatchAdds() { s.mockBatchInsertBuilder.On( "Add", - s.ctx, - s.addressToID[s.addresses[0]], + s.accountLoader.GetFuture(s.addresses[0]), null.String{}, - toid.New(int32(s.sequence), 3, 1).ToInt64(), + toid.New(int32(s.lcm.LedgerSequence()), 3, 1).ToInt64(), uint32(1), history.EffectAccountCredited, []byte("{\"amount\":\"10.0000000\",\"asset_type\":\"native\"}"), @@ -189,82 +206,45 @@ func (s *EffectsProcessorTestSuiteLedger) mockSuccessfulEffectBatchAdds() { s.mockBatchInsertBuilder.On( "Add", - s.ctx, - s.addressToID[s.addresses[0]], + s.accountLoader.GetFuture(s.addresses[0]), null.String{}, - toid.New(int32(s.sequence), 3, 1).ToInt64(), + toid.New(int32(s.lcm.LedgerSequence()), 3, 1).ToInt64(), uint32(2), history.EffectAccountDebited, []byte("{\"amount\":\"10.0000000\",\"asset_type\":\"native\"}"), ).Return(nil).Once() } -func (s *EffectsProcessorTestSuiteLedger) mockSuccessfulCreateAccounts() { - s.mockQ.On( - "CreateAccounts", - s.ctx, - mock.AnythingOfType("[]string"), - maxBatchSize, - ).Run(func(args mock.Arguments) { - arg := args.Get(1).([]string) - s.Assert().ElementsMatch(s.addresses, arg) - }).Return(s.addressToID, nil).Once() -} - func (s *EffectsProcessorTestSuiteLedger) TestEmptyEffects() { - err := s.processor.Commit(context.Background()) - s.Assert().NoError(err) + s.mockBatchInsertBuilder.On("Exec", s.ctx, s.mockSession).Return(nil).Once() + s.Assert().NoError(s.processor.Flush(s.ctx, s.mockSession)) } func (s *EffectsProcessorTestSuiteLedger) TestIngestEffectsSucceeds() { - s.mockSuccessfulCreateAccounts() - s.mockQ.On("NewEffectBatchInsertBuilder", maxBatchSize). - Return(s.mockBatchInsertBuilder).Once() - s.mockSuccessfulEffectBatchAdds() - - s.mockBatchInsertBuilder.On("Exec", s.ctx).Return(nil).Once() - for _, tx := range s.txs { - err := s.processor.ProcessTransaction(s.ctx, tx) - s.Assert().NoError(err) + s.Assert().NoError(s.processor.ProcessTransaction(s.lcm, tx)) } - err := s.processor.Commit(s.ctx) - s.Assert().NoError(err) -} - -func (s *EffectsProcessorTestSuiteLedger) TestCreateAccountsFails() { - s.mockQ.On("CreateAccounts", s.ctx, mock.AnythingOfType("[]string"), maxBatchSize). - Return(s.addressToID, errors.New("transient error")).Once() - for _, tx := range s.txs { - err := s.processor.ProcessTransaction(s.ctx, tx) - s.Assert().NoError(err) - } - err := s.processor.Commit(s.ctx) - s.Assert().EqualError(err, "Could not create account ids: transient error") + s.mockBatchInsertBuilder.On("Exec", s.ctx, s.mockSession).Return(nil).Once() + s.Assert().NoError(s.processor.Flush(s.ctx, s.mockSession)) } func (s *EffectsProcessorTestSuiteLedger) TestBatchAddFails() { - s.mockSuccessfulCreateAccounts() - s.mockQ.On("NewEffectBatchInsertBuilder", maxBatchSize). - Return(s.mockBatchInsertBuilder).Once() - s.mockBatchInsertBuilder.On( - "Add", s.ctx, - s.addressToID[s.addresses[2]], + "Add", + s.accountLoader.GetFuture(s.addresses[2]), null.String{}, - toid.New(int32(s.sequence), 1, 1).ToInt64(), + toid.New(int32(s.lcm.LedgerSequence()), 1, 1).ToInt64(), uint32(1), history.EffectSequenceBumped, []byte("{\"new_seq\":300000000000}"), ).Return(errors.New("transient error")).Once() - for _, tx := range s.txs { - err := s.processor.ProcessTransaction(s.ctx, tx) - s.Assert().NoError(err) - } - err := s.processor.Commit(s.ctx) - s.Assert().EqualError(err, "could not insert operation effect in db: transient error") + + s.Assert().EqualError( + s.processor.ProcessTransaction(s.lcm, s.txs[0]), + "reading operation 85899350017 effects: could not insert operation effect in db: transient error", + ) } func getRevokeSponsorshipMeta(t *testing.T) (string, []effect) { @@ -444,28 +424,29 @@ func TestEffectsCoversAllOperationTypes(t *testing.T) { }, } operation := transactionOperationWrapper{ - index: 0, + index: 0, + ledgerSequence: 1, transaction: ingest.LedgerTransaction{ UnsafeMeta: xdr.TransactionMeta{ V: 2, V2: &xdr.TransactionMetaV2{}, }, }, - operation: op, - ledgerSequence: 1, + operation: op, + network: "test passphrase", } - // calling effects should either panic (because the operation field is set to nil) - // or not error + // calling effects should either panic (because the operation field is + // set to nil) or not error func() { var err error defer func() { err2 := recover() if err != nil { - assert.NotContains(t, err.Error(), "Unknown operation type") + assert.NotContains(t, err.Error(), "unknown operation type") } assert.True(t, err2 != nil || err == nil, s) }() - _, err = operation.effects() + err = operation.ingestEffects(history.NewAccountLoader(), &history.MockEffectBatchInsertBuilder{}) }() } @@ -487,7 +468,7 @@ func TestEffectsCoversAllOperationTypes(t *testing.T) { ledgerSequence: 1, } // calling effects should error due to the unknown operation - _, err := operation.effects() + err := operation.ingestEffects(history.NewAccountLoader(), &history.MockEffectBatchInsertBuilder{}) assert.Contains(t, err.Error(), "Unknown operation type") } @@ -1549,7 +1530,6 @@ func TestOperationEffects(t *testing.T) { } for _, tc := range testCases { t.Run(tc.desc, func(t *testing.T) { - tt := assert.New(t) transaction := BuildLedgerTransaction( t, TestTransaction{ @@ -1569,15 +1549,12 @@ func TestOperationEffects(t *testing.T) { ledgerSequence: tc.sequence, } - effects, err := operation.effects() - tt.NoError(err) - tt.Equal(tc.expected, effects) + assertIngestEffects(t, operation, tc.expected) }) } } func TestOperationEffectsSetOptionsSignersOrder(t *testing.T) { - tt := assert.New(t) transaction := ingest.LedgerTransaction{ UnsafeMeta: createTransactionMeta([]xdr.OperationMeta{ { @@ -1659,8 +1636,6 @@ func TestOperationEffectsSetOptionsSignersOrder(t *testing.T) { ledgerSequence: 46, } - effects, err := operation.effects() - tt.NoError(err) expected := []effect{ { address: "GCBBDQLCTNASZJ3MTKAOYEOWRGSHDFAJVI7VPZUOP7KXNHYR3HP2BUKV", @@ -1703,12 +1678,11 @@ func TestOperationEffectsSetOptionsSignersOrder(t *testing.T) { order: uint32(4), }, } - tt.Equal(expected, effects) + assertIngestEffects(t, operation, expected) } // Regression for https://github.com/stellar/go/issues/2136 func TestOperationEffectsSetOptionsSignersNoUpdated(t *testing.T) { - tt := assert.New(t) transaction := ingest.LedgerTransaction{ UnsafeMeta: createTransactionMeta([]xdr.OperationMeta{ { @@ -1790,8 +1764,6 @@ func TestOperationEffectsSetOptionsSignersNoUpdated(t *testing.T) { ledgerSequence: 46, } - effects, err := operation.effects() - tt.NoError(err) expected := []effect{ { address: "GCBBDQLCTNASZJ3MTKAOYEOWRGSHDFAJVI7VPZUOP7KXNHYR3HP2BUKV", @@ -1823,11 +1795,10 @@ func TestOperationEffectsSetOptionsSignersNoUpdated(t *testing.T) { order: uint32(3), }, } - tt.Equal(expected, effects) + assertIngestEffects(t, operation, expected) } func TestOperationRegressionAccountTrustItself(t *testing.T) { - tt := assert.New(t) // NOTE: when an account trusts itself, the transaction is successful but // no ledger entries are actually modified. transaction := ingest.LedgerTransaction{ @@ -1856,9 +1827,7 @@ func TestOperationRegressionAccountTrustItself(t *testing.T) { ledgerSequence: 46, } - effects, err := operation.effects() - tt.NoError(err) - tt.Equal([]effect{}, effects) + assertIngestEffects(t, operation, []effect{}) } func TestOperationEffectsAllowTrustAuthorizedToMaintainLiabilities(t *testing.T) { @@ -1892,9 +1861,6 @@ func TestOperationEffectsAllowTrustAuthorizedToMaintainLiabilities(t *testing.T) ledgerSequence: 1, } - effects, err := operation.effects() - tt.NoError(err) - expected := []effect{ { address: "GDRW375MAYR46ODGF2WGANQC2RRZL7O246DYHHCGWTV2RE7IHE2QUQLD", @@ -1922,11 +1888,10 @@ func TestOperationEffectsAllowTrustAuthorizedToMaintainLiabilities(t *testing.T) order: uint32(2), }, } - tt.Equal(expected, effects) + assertIngestEffects(t, operation, expected) } func TestOperationEffectsClawback(t *testing.T) { - tt := assert.New(t) aid := xdr.MustAddress("GDRW375MAYR46ODGF2WGANQC2RRZL7O246DYHHCGWTV2RE7IHE2QUQLD") source := aid.ToMuxedAccount() op := xdr.Operation{ @@ -1953,9 +1918,6 @@ func TestOperationEffectsClawback(t *testing.T) { ledgerSequence: 1, } - effects, err := operation.effects() - tt.NoError(err) - expected := []effect{ { address: "GDRW375MAYR46ODGF2WGANQC2RRZL7O246DYHHCGWTV2RE7IHE2QUQLD", @@ -1982,11 +1944,10 @@ func TestOperationEffectsClawback(t *testing.T) { order: uint32(2), }, } - tt.Equal(expected, effects) + assertIngestEffects(t, operation, expected) } func TestOperationEffectsClawbackClaimableBalance(t *testing.T) { - tt := assert.New(t) aid := xdr.MustAddress("GDRW375MAYR46ODGF2WGANQC2RRZL7O246DYHHCGWTV2RE7IHE2QUQLD") source := aid.ToMuxedAccount() var balanceID xdr.ClaimableBalanceId @@ -2013,9 +1974,6 @@ func TestOperationEffectsClawbackClaimableBalance(t *testing.T) { ledgerSequence: 1, } - effects, err := operation.effects() - tt.NoError(err) - expected := []effect{ { address: "GDRW375MAYR46ODGF2WGANQC2RRZL7O246DYHHCGWTV2RE7IHE2QUQLD", @@ -2027,11 +1985,10 @@ func TestOperationEffectsClawbackClaimableBalance(t *testing.T) { order: uint32(1), }, } - tt.Equal(expected, effects) + assertIngestEffects(t, operation, expected) } func TestOperationEffectsSetTrustLineFlags(t *testing.T) { - tt := assert.New(t) aid := xdr.MustAddress("GDRW375MAYR46ODGF2WGANQC2RRZL7O246DYHHCGWTV2RE7IHE2QUQLD") source := aid.ToMuxedAccount() trustor := xdr.MustAddress("GAUJETIZVEP2NRYLUESJ3LS66NVCEGMON4UDCBCSBEVPIID773P2W6AY") @@ -2062,9 +2019,6 @@ func TestOperationEffectsSetTrustLineFlags(t *testing.T) { ledgerSequence: 1, } - effects, err := operation.effects() - tt.NoError(err) - expected := []effect{ { address: "GDRW375MAYR46ODGF2WGANQC2RRZL7O246DYHHCGWTV2RE7IHE2QUQLD", @@ -2082,7 +2036,7 @@ func TestOperationEffectsSetTrustLineFlags(t *testing.T) { order: uint32(1), }, } - tt.Equal(expected, effects) + assertIngestEffects(t, operation, expected) } type CreateClaimableBalanceEffectsTestSuite struct { @@ -2331,9 +2285,7 @@ func (s *CreateClaimableBalanceEffectsTestSuite) TestEffects() { ledgerSequence: 1, } - effects, err := operation.effects() - s.Assert().NoError(err) - s.Assert().Equal(tc.expected, effects) + assertIngestEffects(t, operation, tc.expected) }) } } @@ -2591,18 +2543,47 @@ func (s *ClaimClaimableBalanceEffectsTestSuite) TestEffects() { ledgerSequence: 1, } - effects, err := operation.effects() - s.Assert().NoError(err) - s.Assert().Equal(tc.expected, effects) + assertIngestEffects(t, operation, tc.expected) }) } } +type effect struct { + address string + addressMuxed null.String + operationID int64 + details map[string]interface{} + effectType history.EffectType + order uint32 +} + +func assertIngestEffects(t *testing.T, operation transactionOperationWrapper, expected []effect) { + accountLoader := history.NewAccountLoader() + mockBatchInsertBuilder := &history.MockEffectBatchInsertBuilder{} + + for _, expectedEffect := range expected { + detailsJSON, err := json.Marshal(expectedEffect.details) + assert.NoError(t, err) + mockBatchInsertBuilder.On( + "Add", + accountLoader.GetFuture(expectedEffect.address), + expectedEffect.addressMuxed, + expectedEffect.operationID, + expectedEffect.order, + expectedEffect.effectType, + detailsJSON, + ).Return(nil).Once() + } + + assert.NoError(t, operation.ingestEffects(accountLoader, mockBatchInsertBuilder)) + mockBatchInsertBuilder.AssertExpectations(t) +} + func TestClaimClaimableBalanceEffectsTestSuite(t *testing.T) { suite.Run(t, new(ClaimClaimableBalanceEffectsTestSuite)) } -func TestTrustlineSponsorhipEffects(t *testing.T) { +func TestTrustlineSponsorshipEffects(t *testing.T) { source := xdr.MustMuxedAddress("GAUJETIZVEP2NRYLUESJ3LS66NVCEGMON4UDCBCSBEVPIID773P2W6AY") usdAsset := xdr.MustNewCreditAsset("USD", "GAUJETIZVEP2NRYLUESJ3LS66NVCEGMON4UDCBCSBEVPIID773P2W6AY") poolIDStr := "19cc788419412926a11049b9fb1f87906b8f02bc6bf8f73d8fd347ede0b79fa5" @@ -2814,10 +2795,7 @@ func TestTrustlineSponsorhipEffects(t *testing.T) { ledgerSequence: 1, } - effects, err := operation.effects() - assert.NoError(t, err) - assert.Equal(t, expected, effects) - + assertIngestEffects(t, operation, expected) } func TestLiquidityPoolEffects(t *testing.T) { @@ -3448,10 +3426,379 @@ func TestLiquidityPoolEffects(t *testing.T) { ledgerSequence: 1, } - effects, err := operation.effects() - assert.NoError(t, err) - assert.Equal(t, tc.expected, effects) + assertIngestEffects(t, operation, tc.expected) + }) + } +} + +func TestInvokeHostFunctionEffects(t *testing.T) { + randAddr := func() string { + return keypair.MustRandom().Address() + } + + admin := randAddr() + asset := xdr.MustNewCreditAsset("TESTER", admin) + nativeAsset := xdr.MustNewNativeAsset() + from, to := randAddr(), randAddr() + fromContractBytes, toContractBytes := xdr.Hash{}, xdr.Hash{1} + fromContract := strkey.MustEncode(strkey.VersionByteContract, fromContractBytes[:]) + toContract := strkey.MustEncode(strkey.VersionByteContract, toContractBytes[:]) + amount := big.NewInt(12345) + + rawContractId := [64]byte{} + rand.Read(rawContractId[:]) + + testCases := []struct { + desc string + asset xdr.Asset + from, to string + eventType contractevents.EventType + expected []effect + }{ + { + desc: "transfer", + asset: asset, + eventType: contractevents.EventTypeTransfer, + expected: []effect{ + { + order: 1, + address: from, + effectType: history.EffectAccountDebited, + operationID: toid.New(1, 0, 1).ToInt64(), + details: map[string]interface{}{ + "amount": "0.0012345", + "asset_code": strings.Trim(asset.GetCode(), "\x00"), + "asset_issuer": asset.GetIssuer(), + "asset_type": "credit_alphanum12", + }, + }, { + order: 2, + address: to, + effectType: history.EffectAccountCredited, + operationID: toid.New(1, 0, 1).ToInt64(), + details: map[string]interface{}{ + "amount": "0.0012345", + "asset_code": strings.Trim(asset.GetCode(), "\x00"), + "asset_issuer": asset.GetIssuer(), + "asset_type": "credit_alphanum12", + }, + }, + }, + }, { + desc: "transfer between contracts", + asset: asset, + eventType: contractevents.EventTypeTransfer, + from: fromContract, + to: toContract, + expected: []effect{ + { + order: 1, + address: admin, + effectType: history.EffectContractDebited, + operationID: toid.New(1, 0, 1).ToInt64(), + details: map[string]interface{}{ + "amount": "0.0012345", + "asset_code": strings.Trim(asset.GetCode(), "\x00"), + "asset_issuer": asset.GetIssuer(), + "asset_type": "credit_alphanum12", + "contract": fromContract, + }, + }, { + order: 2, + address: admin, + effectType: history.EffectContractCredited, + operationID: toid.New(1, 0, 1).ToInt64(), + details: map[string]interface{}{ + "amount": "0.0012345", + "asset_code": strings.Trim(asset.GetCode(), "\x00"), + "asset_issuer": asset.GetIssuer(), + "asset_type": "credit_alphanum12", + "contract": toContract, + }, + }, + }, + }, { + desc: "mint", + asset: asset, + eventType: contractevents.EventTypeMint, + expected: []effect{ + { + order: 1, + address: to, + effectType: history.EffectAccountCredited, + operationID: toid.New(1, 0, 1).ToInt64(), + details: map[string]interface{}{ + "amount": "0.0012345", + "asset_code": strings.Trim(asset.GetCode(), "\x00"), + "asset_issuer": asset.GetIssuer(), + "asset_type": "credit_alphanum12", + }, + }, + }, + }, { + desc: "burn", + asset: asset, + eventType: contractevents.EventTypeBurn, + expected: []effect{ + { + order: 1, + address: from, + effectType: history.EffectAccountDebited, + operationID: toid.New(1, 0, 1).ToInt64(), + details: map[string]interface{}{ + "amount": "0.0012345", + "asset_code": strings.Trim(asset.GetCode(), "\x00"), + "asset_issuer": asset.GetIssuer(), + "asset_type": "credit_alphanum12", + }, + }, + }, + }, { + desc: "burn from contract", + asset: asset, + eventType: contractevents.EventTypeBurn, + from: fromContract, + expected: []effect{ + { + order: 1, + address: admin, + effectType: history.EffectContractDebited, + operationID: toid.New(1, 0, 1).ToInt64(), + details: map[string]interface{}{ + "amount": "0.0012345", + "asset_code": strings.Trim(asset.GetCode(), "\x00"), + "asset_issuer": asset.GetIssuer(), + "asset_type": "credit_alphanum12", + "contract": fromContract, + }, + }, + }, + }, { + desc: "clawback", + asset: asset, + eventType: contractevents.EventTypeClawback, + expected: []effect{ + { + order: 1, + address: from, + effectType: history.EffectAccountDebited, + operationID: toid.New(1, 0, 1).ToInt64(), + details: map[string]interface{}{ + "amount": "0.0012345", + "asset_code": strings.Trim(asset.GetCode(), "\x00"), + "asset_issuer": asset.GetIssuer(), + "asset_type": "credit_alphanum12", + }, + }, + }, + }, { + desc: "clawback from contract", + asset: asset, + eventType: contractevents.EventTypeClawback, + from: fromContract, + expected: []effect{ + { + order: 1, + address: admin, + effectType: history.EffectContractDebited, + operationID: toid.New(1, 0, 1).ToInt64(), + details: map[string]interface{}{ + "amount": "0.0012345", + "asset_code": strings.Trim(asset.GetCode(), "\x00"), + "asset_issuer": asset.GetIssuer(), + "asset_type": "credit_alphanum12", + "contract": fromContract, + }, + }, + }, + }, { + desc: "transfer native", + asset: nativeAsset, + eventType: contractevents.EventTypeTransfer, + expected: []effect{ + { + order: 1, + address: from, + effectType: history.EffectAccountDebited, + operationID: toid.New(1, 0, 1).ToInt64(), + details: map[string]interface{}{ + "amount": "0.0012345", + "asset_type": "native", + }, + }, { + order: 2, + address: to, + effectType: history.EffectAccountCredited, + operationID: toid.New(1, 0, 1).ToInt64(), + details: map[string]interface{}{ + "amount": "0.0012345", + "asset_type": "native", + }, + }, + }, + }, { + desc: "transfer into contract", + asset: asset, + to: toContract, + eventType: contractevents.EventTypeTransfer, + expected: []effect{ + { + order: 1, + address: from, + effectType: history.EffectAccountDebited, + operationID: toid.New(1, 0, 1).ToInt64(), + details: map[string]interface{}{ + "amount": "0.0012345", + "asset_code": strings.Trim(asset.GetCode(), "\x00"), + "asset_issuer": asset.GetIssuer(), + "asset_type": "credit_alphanum12", + }, + }, { + order: 2, + address: admin, + effectType: history.EffectContractCredited, + operationID: toid.New(1, 0, 1).ToInt64(), + details: map[string]interface{}{ + "amount": "0.0012345", + "asset_code": strings.Trim(asset.GetCode(), "\x00"), + "asset_issuer": asset.GetIssuer(), + "asset_type": "credit_alphanum12", + "contract": toContract, + }, + }, + }, + }, { + desc: "transfer out of contract", + asset: asset, + from: fromContract, + eventType: contractevents.EventTypeTransfer, + expected: []effect{ + { + order: 1, + address: admin, + effectType: history.EffectContractDebited, + operationID: toid.New(1, 0, 1).ToInt64(), + details: map[string]interface{}{ + "amount": "0.0012345", + "asset_code": strings.Trim(asset.GetCode(), "\x00"), + "asset_issuer": asset.GetIssuer(), + "asset_type": "credit_alphanum12", + "contract": fromContract, + }, + }, { + order: 2, + address: to, + effectType: history.EffectAccountCredited, + operationID: toid.New(1, 0, 1).ToInt64(), + details: map[string]interface{}{ + "amount": "0.0012345", + "asset_code": strings.Trim(asset.GetCode(), "\x00"), + "asset_issuer": asset.GetIssuer(), + "asset_type": "credit_alphanum12", + }, + }, + }, + }, + } + + for _, testCase := range testCases { + t.Run(testCase.desc, func(t *testing.T) { + var tx ingest.LedgerTransaction + + fromAddr := from + if testCase.from != "" { + fromAddr = testCase.from + } + + toAddr := to + if testCase.to != "" { + toAddr = testCase.to + } + + tx = makeInvocationTransaction( + fromAddr, toAddr, + admin, + testCase.asset, + amount, + testCase.eventType, + ) + assert.True(t, tx.Result.Successful()) // sanity check + + operation := transactionOperationWrapper{ + index: 0, + transaction: tx, + operation: tx.Envelope.Operations()[0], + ledgerSequence: 1, + network: networkPassphrase, + } + + assertIngestEffects(t, operation, testCase.expected) }) } +} + +// makeInvocationTransaction returns a single transaction containing a single +// invokeHostFunction operation that generates the specified Stellar Asset +// Contract events in its txmeta. +func makeInvocationTransaction( + from, to, admin string, + asset xdr.Asset, + amount *big.Int, + types ...contractevents.EventType, +) ingest.LedgerTransaction { + meta := xdr.TransactionMetaV3{ + // irrelevant for contract invocations: only events are inspected + Operations: []xdr.OperationMeta{}, + SorobanMeta: &xdr.SorobanTransactionMeta{ + Events: make([]xdr.ContractEvent, len(types)), + }, + } + + for idx, type_ := range types { + event := contractevents.GenerateEvent( + type_, + from, to, admin, + asset, + amount, + networkPassphrase, + ) + meta.SorobanMeta.Events[idx] = event + } + + envelope := xdr.TransactionV1Envelope{ + Tx: xdr.Transaction{ + // the rest doesn't matter for effect ingestion + Operations: []xdr.Operation{ + { + SourceAccount: xdr.MustMuxedAddressPtr(admin), + Body: xdr.OperationBody{ + Type: xdr.OperationTypeInvokeHostFunction, + // contents of the op are irrelevant as they aren't + // parsed by anyone yet, e.g. effects are generated + // purely from events + InvokeHostFunctionOp: &xdr.InvokeHostFunctionOp{}, + }, + }, + }, + }, + } + return ingest.LedgerTransaction{ + Index: 0, + Envelope: xdr.TransactionEnvelope{ + Type: xdr.EnvelopeTypeEnvelopeTypeTx, + V1: &envelope, + }, + // the result just needs enough to look successful + Result: xdr.TransactionResultPair{ + TransactionHash: xdr.Hash([32]byte{}), + Result: xdr.TransactionResult{ + FeeCharged: 1234, + Result: xdr.TransactionResultResult{ + Code: xdr.TransactionResultCodeTxSuccess, + }, + }, + }, + UnsafeMeta: xdr.TransactionMeta{V: 3, V3: &meta}, + } } diff --git a/services/horizon/internal/ingest/processors/ledgers_processor.go b/services/horizon/internal/ingest/processors/ledgers_processor.go index 01c29b43d9..5ecfb2ad7f 100644 --- a/services/horizon/internal/ingest/processors/ledgers_processor.go +++ b/services/horizon/internal/ingest/processors/ledgers_processor.go @@ -5,69 +5,84 @@ import ( "github.com/stellar/go/ingest" "github.com/stellar/go/services/horizon/internal/db2/history" + "github.com/stellar/go/support/db" "github.com/stellar/go/support/errors" "github.com/stellar/go/xdr" ) -type LedgersProcessor struct { - ledgersQ history.QLedgers - ledger xdr.LedgerHeaderHistoryEntry - ingestVersion int +type ledgerInfo struct { + header xdr.LedgerHeaderHistoryEntry successTxCount int failedTxCount int opCount int txSetOpCount int } -func NewLedgerProcessor( - ledgerQ history.QLedgers, - ledger xdr.LedgerHeaderHistoryEntry, - ingestVersion int, -) *LedgersProcessor { +type LedgersProcessor struct { + batch history.LedgerBatchInsertBuilder + ledgers map[uint32]*ledgerInfo + ingestVersion int +} + +func NewLedgerProcessor(batch history.LedgerBatchInsertBuilder, ingestVersion int) *LedgersProcessor { return &LedgersProcessor{ - ledger: ledger, - ledgersQ: ledgerQ, + batch: batch, + ledgers: map[uint32]*ledgerInfo{}, ingestVersion: ingestVersion, } } -func (p *LedgersProcessor) ProcessTransaction(ctx context.Context, transaction ingest.LedgerTransaction) (err error) { +func (p *LedgersProcessor) ProcessLedger(lcm xdr.LedgerCloseMeta) *ledgerInfo { + sequence := lcm.LedgerSequence() + entry, ok := p.ledgers[sequence] + if !ok { + entry = &ledgerInfo{header: lcm.LedgerHeaderHistoryEntry()} + p.ledgers[sequence] = entry + } + return entry +} + +func (p *LedgersProcessor) ProcessTransaction(lcm xdr.LedgerCloseMeta, transaction ingest.LedgerTransaction) error { + entry := p.ProcessLedger(lcm) opCount := len(transaction.Envelope.Operations()) - p.txSetOpCount += opCount + entry.txSetOpCount += opCount if transaction.Result.Successful() { - p.successTxCount++ - p.opCount += opCount + entry.successTxCount++ + entry.opCount += opCount } else { - p.failedTxCount++ + entry.failedTxCount++ } return nil } -func (p *LedgersProcessor) Commit(ctx context.Context) error { - rowsAffected, err := p.ledgersQ.InsertLedger(ctx, - p.ledger, - p.successTxCount, - p.failedTxCount, - p.opCount, - p.txSetOpCount, - p.ingestVersion, - ) - - if err != nil { - return errors.Wrap(err, "Could not insert ledger") +func (p *LedgersProcessor) Flush(ctx context.Context, session db.SessionInterface) error { + if len(p.ledgers) == 0 { + return nil } - - sequence := uint32(p.ledger.Header.LedgerSeq) - - if rowsAffected != 1 { - log.WithField("rowsAffected", rowsAffected). - WithField("sequence", sequence). - Error("Invalid number of rows affected when ingesting new ledger") - return errors.Errorf( - "0 rows affected when ingesting new ledger: %v", - sequence, + var min, max uint32 + for ledger, entry := range p.ledgers { + err := p.batch.Add( + entry.header, + entry.successTxCount, + entry.failedTxCount, + entry.opCount, + entry.txSetOpCount, + p.ingestVersion, ) + if err != nil { + return errors.Wrapf(err, "error adding ledger %d to batch", ledger) + } + if min == 0 || ledger < min { + min = ledger + } + if max == 0 || ledger > max { + max = ledger + } + } + + if err := p.batch.Exec(ctx, session); err != nil { + return errors.Wrapf(err, "error flushing ledgers %d - %d", min, max) } return nil diff --git a/services/horizon/internal/ingest/processors/ledgers_processor_test.go b/services/horizon/internal/ingest/processors/ledgers_processor_test.go index 05bd2c3c3b..1df6640266 100644 --- a/services/horizon/internal/ingest/processors/ledgers_processor_test.go +++ b/services/horizon/internal/ingest/processors/ledgers_processor_test.go @@ -8,6 +8,7 @@ import ( "github.com/stellar/go/ingest" "github.com/stellar/go/services/horizon/internal/db2/history" + "github.com/stellar/go/support/db" "github.com/stellar/go/support/errors" "github.com/stellar/go/xdr" "github.com/stretchr/testify/mock" @@ -16,15 +17,16 @@ import ( type LedgersProcessorTestSuiteLedger struct { suite.Suite - processor *LedgersProcessor - mockQ *history.MockQLedgers - header xdr.LedgerHeaderHistoryEntry - successCount int - failedCount int - opCount int - ingestVersion int - txs []ingest.LedgerTransaction - txSetOpCount int + processor *LedgersProcessor + mockSession *db.MockSession + mockBatchInsertBuilder *history.MockLedgersBatchInsertBuilder + header xdr.LedgerHeaderHistoryEntry + successCount int + failedCount int + opCount int + ingestVersion int + txs []ingest.LedgerTransaction + txSetOpCount int } func TestLedgersProcessorTestSuiteLedger(t *testing.T) { @@ -78,16 +80,16 @@ func createTransaction(successful bool, numOps int) ingest.LedgerTransaction { } func (s *LedgersProcessorTestSuiteLedger) SetupTest() { - s.mockQ = &history.MockQLedgers{} + s.mockBatchInsertBuilder = &history.MockLedgersBatchInsertBuilder{} s.ingestVersion = 100 s.header = xdr.LedgerHeaderHistoryEntry{ Header: xdr.LedgerHeader{ LedgerSeq: xdr.Uint32(20), }, } + s.processor = NewLedgerProcessor( - s.mockQ, - s.header, + s.mockBatchInsertBuilder, s.ingestVersion, ) @@ -104,63 +106,120 @@ func (s *LedgersProcessorTestSuiteLedger) SetupTest() { } func (s *LedgersProcessorTestSuiteLedger) TearDownTest() { - s.mockQ.AssertExpectations(s.T()) + s.mockBatchInsertBuilder.AssertExpectations(s.T()) } func (s *LedgersProcessorTestSuiteLedger) TestInsertLedgerSucceeds() { ctx := context.Background() - s.mockQ.On( - "InsertLedger", - ctx, + + for _, tx := range s.txs { + err := s.processor.ProcessTransaction(xdr.LedgerCloseMeta{ + V0: &xdr.LedgerCloseMetaV0{ + LedgerHeader: s.header, + }, + }, tx) + s.Assert().NoError(err) + } + + nextHeader := xdr.LedgerHeaderHistoryEntry{ + Header: xdr.LedgerHeader{ + LedgerSeq: xdr.Uint32(21), + }, + } + nextTransactions := []ingest.LedgerTransaction{ + createTransaction(true, 1), + createTransaction(false, 2), + } + for _, tx := range nextTransactions { + err := s.processor.ProcessTransaction(xdr.LedgerCloseMeta{ + V0: &xdr.LedgerCloseMetaV0{ + LedgerHeader: nextHeader, + }, + }, tx) + s.Assert().NoError(err) + } + + s.mockBatchInsertBuilder.On( + "Add", s.header, s.successCount, s.failedCount, s.opCount, s.txSetOpCount, s.ingestVersion, - ).Return(int64(1), nil) + ).Return(nil) + + s.mockBatchInsertBuilder.On( + "Add", + nextHeader, + 1, + 1, + 1, + 3, + s.ingestVersion, + ).Return(nil) - for _, tx := range s.txs { - err := s.processor.ProcessTransaction(ctx, tx) - s.Assert().NoError(err) - } + s.mockBatchInsertBuilder.On( + "Exec", + ctx, + s.mockSession, + ).Return(nil) - err := s.processor.Commit(ctx) + err := s.processor.Flush(ctx, s.mockSession) s.Assert().NoError(err) } func (s *LedgersProcessorTestSuiteLedger) TestInsertLedgerReturnsError() { - ctx := context.Background() - s.mockQ.On( - "InsertLedger", - ctx, + s.mockBatchInsertBuilder.On( + "Add", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, - ).Return(int64(0), errors.New("transient error")) + ).Return(errors.New("transient error")) + + err := s.processor.ProcessTransaction(xdr.LedgerCloseMeta{ + V0: &xdr.LedgerCloseMetaV0{ + LedgerHeader: s.header, + }, + }, s.txs[0]) + s.Assert().NoError(err) - err := s.processor.Commit(ctx) - s.Assert().Error(err) - s.Assert().EqualError(err, "Could not insert ledger: transient error") + s.Assert().EqualError(s.processor.Flush( + context.Background(), s.mockSession), + "error adding ledger 20 to batch: transient error", + ) } -func (s *LedgersProcessorTestSuiteLedger) TestInsertLedgerNoRowsAffected() { +func (s *LedgersProcessorTestSuiteLedger) TestExecFails() { ctx := context.Background() - s.mockQ.On( - "InsertLedger", - ctx, + s.mockBatchInsertBuilder.On( + "Add", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, - ).Return(int64(0), nil) + ).Return(nil) + + s.mockBatchInsertBuilder.On( + "Exec", + ctx, + s.mockSession, + ).Return(errors.New("transient exec error")) - err := s.processor.Commit(ctx) - s.Assert().Error(err) - s.Assert().EqualError(err, "0 rows affected when ingesting new ledger: 20") + err := s.processor.ProcessTransaction(xdr.LedgerCloseMeta{ + V0: &xdr.LedgerCloseMetaV0{ + LedgerHeader: s.header, + }, + }, s.txs[0]) + s.Assert().NoError(err) + + s.Assert().EqualError(s.processor.Flush( + context.Background(), s.mockSession), + "error flushing ledgers 20 - 20: transient exec error", + ) } diff --git a/services/horizon/internal/ingest/processors/liquidity_pools_transaction_processor.go b/services/horizon/internal/ingest/processors/liquidity_pools_transaction_processor.go index 38010ddb51..c721f9e4ba 100644 --- a/services/horizon/internal/ingest/processors/liquidity_pools_transaction_processor.go +++ b/services/horizon/internal/ingest/processors/liquidity_pools_transaction_processor.go @@ -2,56 +2,41 @@ package processors import ( "context" + "sort" "github.com/stellar/go/ingest" "github.com/stellar/go/services/horizon/internal/db2/history" - set "github.com/stellar/go/support/collections/set" + "github.com/stellar/go/support/db" "github.com/stellar/go/support/errors" "github.com/stellar/go/toid" "github.com/stellar/go/xdr" ) -type liquidityPool struct { - internalID int64 // Bigint auto-generated by postgres - transactionSet set.Set[int64] - operationSet set.Set[int64] -} - -func (b *liquidityPool) addTransactionID(id int64) { - if b.transactionSet == nil { - b.transactionSet = set.Set[int64]{} - } - b.transactionSet.Add(id) -} - -func (b *liquidityPool) addOperationID(id int64) { - if b.operationSet == nil { - b.operationSet = set.Set[int64]{} - } - b.operationSet.Add(id) -} - type LiquidityPoolsTransactionProcessor struct { - sequence uint32 - liquidityPoolSet map[string]liquidityPool - qLiquidityPools history.QHistoryLiquidityPools + lpLoader *history.LiquidityPoolLoader + txBatch history.TransactionLiquidityPoolBatchInsertBuilder + opBatch history.OperationLiquidityPoolBatchInsertBuilder } -func NewLiquidityPoolsTransactionProcessor(Q history.QHistoryLiquidityPools, sequence uint32) *LiquidityPoolsTransactionProcessor { +func NewLiquidityPoolsTransactionProcessor( + lpLoader *history.LiquidityPoolLoader, + txBatch history.TransactionLiquidityPoolBatchInsertBuilder, + opBatch history.OperationLiquidityPoolBatchInsertBuilder, +) *LiquidityPoolsTransactionProcessor { return &LiquidityPoolsTransactionProcessor{ - qLiquidityPools: Q, - sequence: sequence, - liquidityPoolSet: map[string]liquidityPool{}, + lpLoader: lpLoader, + txBatch: txBatch, + opBatch: opBatch, } } -func (p *LiquidityPoolsTransactionProcessor) ProcessTransaction(ctx context.Context, transaction ingest.LedgerTransaction) error { - err := p.addTransactionLiquidityPools(p.liquidityPoolSet, p.sequence, transaction) +func (p *LiquidityPoolsTransactionProcessor) ProcessTransaction(lcm xdr.LedgerCloseMeta, transaction ingest.LedgerTransaction) error { + err := p.addTransactionLiquidityPools(lcm.LedgerSequence(), transaction) if err != nil { return err } - err = p.addOperationLiquidityPools(p.liquidityPoolSet, p.sequence, transaction) + err = p.addOperationLiquidityPools(lcm.LedgerSequence(), transaction) if err != nil { return err } @@ -59,29 +44,23 @@ func (p *LiquidityPoolsTransactionProcessor) ProcessTransaction(ctx context.Cont return nil } -func (p *LiquidityPoolsTransactionProcessor) addTransactionLiquidityPools(lpSet map[string]liquidityPool, sequence uint32, transaction ingest.LedgerTransaction) error { +func (p *LiquidityPoolsTransactionProcessor) addTransactionLiquidityPools(sequence uint32, transaction ingest.LedgerTransaction) error { transactionID := toid.New(int32(sequence), int32(transaction.Index), 0).ToInt64() - transactionLiquidityPools, err := liquidityPoolsForTransaction( - sequence, - transaction, - ) + lps, err := liquidityPoolsForTransaction(transaction) if err != nil { return errors.Wrap(err, "Could not determine liquidity pools for transaction") } - for _, lp := range transactionLiquidityPools { - entry := lpSet[lp] - entry.addTransactionID(transactionID) - lpSet[lp] = entry + for _, lp := range dedupeStrings(lps) { + if err = p.txBatch.Add(transactionID, p.lpLoader.GetFuture(lp)); err != nil { + return err + } } return nil } -func liquidityPoolsForTransaction( - sequence uint32, - transaction ingest.LedgerTransaction, -) ([]string, error) { +func liquidityPoolsForTransaction(transaction ingest.LedgerTransaction) ([]string, error) { changes, err := transaction.GetChanges() if err != nil { return nil, err @@ -90,19 +69,25 @@ func liquidityPoolsForTransaction( if err != nil { return nil, errors.Wrapf(err, "reading transaction %v liquidity pools", transaction.Index) } - return dedupeLiquidityPools(lps) + return lps, nil } -func dedupeLiquidityPools(in []string) (out []string, err error) { - set := set.Set[string]{} - for _, id := range in { - set.Add(id) +func dedupeStrings(in []string) []string { + if len(in) <= 1 { + return in } - - for id := range set { - out = append(out, id) + sort.Strings(in) + insert := 1 + for cur := 1; cur < len(in); cur++ { + if in[cur] == in[cur-1] { + continue + } + if insert != cur { + in[insert] = in[cur] + } + insert++ } - return + return in[:insert] } func liquidityPoolsForChanges( @@ -132,26 +117,7 @@ func liquidityPoolsForChanges( return lps, nil } -func (p *LiquidityPoolsTransactionProcessor) addOperationLiquidityPools(lpSet map[string]liquidityPool, sequence uint32, transaction ingest.LedgerTransaction) error { - liquidityPools, err := liquidityPoolsForOperations(transaction, sequence) - if err != nil { - return errors.Wrap(err, "could not determine operation liquidity pools") - } - - for operationID, lps := range liquidityPools { - for _, lp := range lps { - entry := lpSet[lp] - entry.addOperationID(operationID) - lpSet[lp] = entry - } - } - - return nil -} - -func liquidityPoolsForOperations(transaction ingest.LedgerTransaction, sequence uint32) (map[int64][]string, error) { - lps := map[int64][]string{} - +func (p *LiquidityPoolsTransactionProcessor) addOperationLiquidityPools(sequence uint32, transaction ingest.LedgerTransaction) error { for opi, op := range transaction.Envelope.Operations() { operation := transactionOperationWrapper{ index: uint32(opi), @@ -162,91 +128,29 @@ func liquidityPoolsForOperations(transaction ingest.LedgerTransaction, sequence changes, err := transaction.GetOperationChanges(uint32(opi)) if err != nil { - return lps, err - } - c, err := liquidityPoolsForChanges(changes) - if err != nil { - return lps, errors.Wrapf(err, "reading operation %v liquidity pools", operation.ID()) - } - lps[operation.ID()] = c - } - - return lps, nil -} - -func (p *LiquidityPoolsTransactionProcessor) Commit(ctx context.Context) error { - if len(p.liquidityPoolSet) > 0 { - if err := p.loadLiquidityPoolIDs(ctx, p.liquidityPoolSet); err != nil { - return err - } - - if err := p.insertDBTransactionLiquidityPools(ctx, p.liquidityPoolSet); err != nil { - return err - } - - if err := p.insertDBOperationsLiquidityPools(ctx, p.liquidityPoolSet); err != nil { return err } - } - - return nil -} - -func (p *LiquidityPoolsTransactionProcessor) loadLiquidityPoolIDs(ctx context.Context, liquidityPoolSet map[string]liquidityPool) error { - ids := make([]string, 0, len(liquidityPoolSet)) - for id := range liquidityPoolSet { - ids = append(ids, id) - } - - toInternalID, err := p.qLiquidityPools.CreateHistoryLiquidityPools(ctx, ids, maxBatchSize) - if err != nil { - return errors.Wrap(err, "Could not create liquidity pool ids") - } - - for _, id := range ids { - internalID, ok := toInternalID[id] - if !ok { - return errors.Errorf("no internal id found for liquidity pool %s", id) + lps, err := liquidityPoolsForChanges(changes) + if err != nil { + return errors.Wrapf(err, "reading operation %v liquidity pools", operation.ID()) } - - lp := liquidityPoolSet[id] - lp.internalID = internalID - liquidityPoolSet[id] = lp - } - - return nil -} - -func (p LiquidityPoolsTransactionProcessor) insertDBTransactionLiquidityPools(ctx context.Context, liquidityPoolSet map[string]liquidityPool) error { - batch := p.qLiquidityPools.NewTransactionLiquidityPoolBatchInsertBuilder(maxBatchSize) - - for _, entry := range liquidityPoolSet { - for transactionID := range entry.transactionSet { - if err := batch.Add(ctx, transactionID, entry.internalID); err != nil { - return errors.Wrap(err, "could not insert transaction liquidity pool in db") + for _, lp := range dedupeStrings(lps) { + if err := p.opBatch.Add(operation.ID(), p.lpLoader.GetFuture(lp)); err != nil { + return err } } } - if err := batch.Exec(ctx); err != nil { - return errors.Wrap(err, "could not flush transaction liquidity pools to db") - } return nil } -func (p LiquidityPoolsTransactionProcessor) insertDBOperationsLiquidityPools(ctx context.Context, liquidityPoolSet map[string]liquidityPool) error { - batch := p.qLiquidityPools.NewOperationLiquidityPoolBatchInsertBuilder(maxBatchSize) - - for _, entry := range liquidityPoolSet { - for operationID := range entry.operationSet { - if err := batch.Add(ctx, operationID, entry.internalID); err != nil { - return errors.Wrap(err, "could not insert operation liquidity pool in db") - } - } +func (p *LiquidityPoolsTransactionProcessor) Flush(ctx context.Context, session db.SessionInterface) error { + if err := p.txBatch.Exec(ctx, session); err != nil { + return errors.Wrap(err, "Could not flush transaction liquidity pools to db") } - - if err := batch.Exec(ctx); err != nil { - return errors.Wrap(err, "could not flush operation liquidity pools to db") + if err := p.opBatch.Exec(ctx, session); err != nil { + return errors.Wrap(err, "Could not flush operation liquidity pools to db") } + return nil } diff --git a/services/horizon/internal/ingest/processors/liquidity_pools_transaction_processor_test.go b/services/horizon/internal/ingest/processors/liquidity_pools_transaction_processor_test.go index bd80ca09cb..485d890dca 100644 --- a/services/horizon/internal/ingest/processors/liquidity_pools_transaction_processor_test.go +++ b/services/horizon/internal/ingest/processors/liquidity_pools_transaction_processor_test.go @@ -6,10 +6,10 @@ import ( "context" "testing" - "github.com/stretchr/testify/mock" "github.com/stretchr/testify/suite" "github.com/stellar/go/services/horizon/internal/db2/history" + "github.com/stellar/go/support/db" "github.com/stellar/go/toid" "github.com/stellar/go/xdr" ) @@ -18,11 +18,12 @@ type LiquidityPoolsTransactionProcessorTestSuiteLedger struct { suite.Suite ctx context.Context processor *LiquidityPoolsTransactionProcessor - mockQ *history.MockQHistoryLiquidityPools + mockSession *db.MockSession + lpLoader *history.LiquidityPoolLoader mockTransactionBatchInsertBuilder *history.MockTransactionLiquidityPoolBatchInsertBuilder mockOperationBatchInsertBuilder *history.MockOperationLiquidityPoolBatchInsertBuilder - sequence uint32 + lcm xdr.LedgerCloseMeta } func TestLiquidityPoolsTransactionProcessorTestSuiteLedger(t *testing.T) { @@ -31,40 +32,42 @@ func TestLiquidityPoolsTransactionProcessorTestSuiteLedger(t *testing.T) { func (s *LiquidityPoolsTransactionProcessorTestSuiteLedger) SetupTest() { s.ctx = context.Background() - s.mockQ = &history.MockQHistoryLiquidityPools{} s.mockTransactionBatchInsertBuilder = &history.MockTransactionLiquidityPoolBatchInsertBuilder{} s.mockOperationBatchInsertBuilder = &history.MockOperationLiquidityPoolBatchInsertBuilder{} - s.sequence = 20 + sequence := uint32(20) + s.lcm = xdr.LedgerCloseMeta{ + V0: &xdr.LedgerCloseMetaV0{ + LedgerHeader: xdr.LedgerHeaderHistoryEntry{ + Header: xdr.LedgerHeader{ + LedgerSeq: xdr.Uint32(sequence), + }, + }, + }, + } + s.lpLoader = history.NewLiquidityPoolLoader() s.processor = NewLiquidityPoolsTransactionProcessor( - s.mockQ, - s.sequence, + s.lpLoader, + s.mockTransactionBatchInsertBuilder, + s.mockOperationBatchInsertBuilder, ) } func (s *LiquidityPoolsTransactionProcessorTestSuiteLedger) TearDownTest() { - s.mockQ.AssertExpectations(s.T()) s.mockTransactionBatchInsertBuilder.AssertExpectations(s.T()) s.mockOperationBatchInsertBuilder.AssertExpectations(s.T()) } -func (s *LiquidityPoolsTransactionProcessorTestSuiteLedger) mockTransactionBatchAdd(transactionID, internalID int64, err error) { - s.mockTransactionBatchInsertBuilder.On("Add", s.ctx, transactionID, internalID).Return(err).Once() -} - -func (s *LiquidityPoolsTransactionProcessorTestSuiteLedger) mockOperationBatchAdd(operationID, internalID int64, err error) { - s.mockOperationBatchInsertBuilder.On("Add", s.ctx, operationID, internalID).Return(err).Once() -} - func (s *LiquidityPoolsTransactionProcessorTestSuiteLedger) TestEmptyLiquidityPools() { - // What is this expecting? Doesn't seem to assert anything meaningful... - err := s.processor.Commit(context.Background()) + s.mockTransactionBatchInsertBuilder.On("Exec", s.ctx, s.mockSession).Return(nil).Once() + s.mockOperationBatchInsertBuilder.On("Exec", s.ctx, s.mockSession).Return(nil).Once() + + err := s.processor.Flush(context.Background(), s.mockSession) s.Assert().NoError(err) } func (s *LiquidityPoolsTransactionProcessorTestSuiteLedger) testOperationInserts(poolID xdr.PoolId, body xdr.OperationBody, change xdr.LedgerEntryChange) { // Setup the transaction - internalID := int64(1234) txn := createTransaction(true, 1) txn.Envelope.Operations()[0].Body = body txn.UnsafeMeta.V = 2 @@ -82,6 +85,20 @@ func (s *LiquidityPoolsTransactionProcessorTestSuiteLedger) testOperationInserts }, }, change, + // add a duplicate change to test that the processor + // does not insert duplicate rows + { + Type: xdr.LedgerEntryChangeTypeLedgerEntryState, + State: &xdr.LedgerEntry{ + Data: xdr.LedgerEntryData{ + Type: xdr.LedgerEntryTypeLiquidityPool, + LiquidityPool: &xdr.LiquidityPoolEntry{ + LiquidityPoolId: poolID, + }, + }, + }, + }, + change, }}, } @@ -100,44 +117,28 @@ func (s *LiquidityPoolsTransactionProcessorTestSuiteLedger) testOperationInserts }, } } - txnID := toid.New(int32(s.sequence), int32(txn.Index), 0).ToInt64() + txnID := toid.New(int32(s.lcm.LedgerSequence()), int32(txn.Index), 0).ToInt64() opID := (&transactionOperationWrapper{ index: uint32(0), transaction: txn, operation: txn.Envelope.Operations()[0], - ledgerSequence: s.sequence, + ledgerSequence: s.lcm.LedgerSequence(), }).ID() hexID := PoolIDToString(poolID) - // Setup a q - s.mockQ.On("CreateHistoryLiquidityPools", s.ctx, mock.AnythingOfType("[]string"), maxBatchSize). - Run(func(args mock.Arguments) { - arg := args.Get(1).([]string) - s.Assert().ElementsMatch( - []string{hexID}, - arg, - ) - }).Return(map[string]int64{ - hexID: internalID, - }, nil).Once() - // Prepare to process transactions successfully - s.mockQ.On("NewTransactionLiquidityPoolBatchInsertBuilder", maxBatchSize). - Return(s.mockTransactionBatchInsertBuilder).Once() - s.mockTransactionBatchAdd(txnID, internalID, nil) - s.mockTransactionBatchInsertBuilder.On("Exec", s.ctx).Return(nil).Once() + s.mockTransactionBatchInsertBuilder.On("Add", txnID, s.lpLoader.GetFuture(hexID)).Return(nil).Once() + s.mockTransactionBatchInsertBuilder.On("Exec", s.ctx, s.mockSession).Return(nil).Once() // Prepare to process operations successfully - s.mockQ.On("NewOperationLiquidityPoolBatchInsertBuilder", maxBatchSize). - Return(s.mockOperationBatchInsertBuilder).Once() - s.mockOperationBatchAdd(opID, internalID, nil) - s.mockOperationBatchInsertBuilder.On("Exec", s.ctx).Return(nil).Once() + s.mockOperationBatchInsertBuilder.On("Add", opID, s.lpLoader.GetFuture(hexID)).Return(nil).Once() + s.mockOperationBatchInsertBuilder.On("Exec", s.ctx, s.mockSession).Return(nil).Once() // Process the transaction - err := s.processor.ProcessTransaction(s.ctx, txn) + err := s.processor.ProcessTransaction(s.lcm, txn) s.Assert().NoError(err) - err = s.processor.Commit(s.ctx) + err = s.processor.Flush(s.ctx, s.mockSession) s.Assert().NoError(err) } diff --git a/services/horizon/internal/ingest/processors/main.go b/services/horizon/internal/ingest/processors/main.go index 5088dd97aa..94f83f3fa9 100644 --- a/services/horizon/internal/ingest/processors/main.go +++ b/services/horizon/internal/ingest/processors/main.go @@ -1,7 +1,13 @@ package processors import ( + "context" + "io" + "github.com/guregu/null" + "github.com/stellar/go/ingest" + "github.com/stellar/go/support/db" + "github.com/stellar/go/support/errors" logpkg "github.com/stellar/go/support/log" "github.com/stellar/go/xdr" ) @@ -10,6 +16,65 @@ var log = logpkg.DefaultLogger.WithField("service", "ingest") const maxBatchSize = 100000 +type ChangeProcessor interface { + ProcessChange(ctx context.Context, change ingest.Change) error +} + +type LedgerTransactionProcessor interface { + ProcessTransaction(lcm xdr.LedgerCloseMeta, transaction ingest.LedgerTransaction) error + Flush(ctx context.Context, session db.SessionInterface) error +} + +type LedgerTransactionFilterer interface { + FilterTransaction(ctx context.Context, transaction ingest.LedgerTransaction) (bool, error) +} + +func StreamLedgerTransactions( + ctx context.Context, + txFilterer LedgerTransactionFilterer, + filteredTxProcessor LedgerTransactionProcessor, + txProcessor LedgerTransactionProcessor, + reader *ingest.LedgerTransactionReader, + ledger xdr.LedgerCloseMeta, +) error { + for { + tx, err := reader.Read() + if err == io.EOF { + return nil + } + if err != nil { + return errors.Wrap(err, "could not read transaction") + } + include, err := txFilterer.FilterTransaction(ctx, tx) + if err != nil { + return errors.Wrapf( + err, + "could not filter transaction %v", + tx.Index, + ) + } + if !include { + if err = filteredTxProcessor.ProcessTransaction(ledger, tx); err != nil { + return errors.Wrapf( + err, + "could not process transaction %v", + tx.Index, + ) + } + log.Debugf("Filters did not find match on transaction, dropping this tx with hash %v", tx.Result.TransactionHash.HexString()) + continue + } + + if err = txProcessor.ProcessTransaction(ledger, tx); err != nil { + return errors.Wrapf( + err, + "could not process transaction %v", + tx.Index, + ) + } + } +} + func ledgerEntrySponsorToNullString(entry xdr.LedgerEntry) null.String { sponsoringID := entry.SponsoringID() diff --git a/services/horizon/internal/ingest/processors/offers_processor.go b/services/horizon/internal/ingest/processors/offers_processor.go index af1d80693e..13ee130d9e 100644 --- a/services/horizon/internal/ingest/processors/offers_processor.go +++ b/services/horizon/internal/ingest/processors/offers_processor.go @@ -17,7 +17,8 @@ type OffersProcessor struct { offersQ history.QOffers sequence uint32 - cache *ingest.ChangeCompactor + cache *ingest.ChangeCompactor + insertBatchBuilder history.OffersBatchInsertBuilder } func NewOffersProcessor(offersQ history.QOffers, sequence uint32) *OffersProcessor { @@ -28,6 +29,7 @@ func NewOffersProcessor(offersQ history.QOffers, sequence uint32) *OffersProcess func (p *OffersProcessor) reset() { p.cache = ingest.NewChangeCompactor() + p.insertBatchBuilder = p.offersQ.NewOffersBatchInsertBuilder() } func (p *OffersProcessor) ProcessChange(ctx context.Context, change ingest.Change) error { @@ -43,7 +45,6 @@ func (p *OffersProcessor) ProcessChange(ctx context.Context, change ingest.Chang if err := p.flushCache(ctx); err != nil { return errors.Wrap(err, "error in Commit") } - p.reset() } return nil @@ -67,12 +68,20 @@ func (p *OffersProcessor) ledgerEntryToRow(entry *xdr.LedgerEntry) history.Offer } func (p *OffersProcessor) flushCache(ctx context.Context) error { + defer p.reset() + var batchUpsertOffers []history.Offer changes := p.cache.GetChanges() for _, change := range changes { switch { - case change.Post != nil: - // Created and updated + case change.Pre == nil && change.Post != nil: + // Created + err := p.insertBatchBuilder.Add(p.ledgerEntryToRow(change.Post)) + if err != nil { + return errors.New("Error adding to OffersBatchInsertBuilder") + } + case change.Pre != nil && change.Post != nil: + // Updated row := p.ledgerEntryToRow(change.Post) batchUpsertOffers = append(batchUpsertOffers, row) case change.Pre != nil && change.Post == nil: @@ -86,6 +95,11 @@ func (p *OffersProcessor) flushCache(ctx context.Context) error { } } + err := p.insertBatchBuilder.Exec(ctx) + if err != nil { + return errors.New("Error executing OffersBatchInsertBuilder") + } + if len(batchUpsertOffers) > 0 { err := p.offersQ.UpsertOffers(ctx, batchUpsertOffers) if err != nil { diff --git a/services/horizon/internal/ingest/processors/offers_processor_test.go b/services/horizon/internal/ingest/processors/offers_processor_test.go index 21905dc1df..77128a1b0f 100644 --- a/services/horizon/internal/ingest/processors/offers_processor_test.go +++ b/services/horizon/internal/ingest/processors/offers_processor_test.go @@ -21,16 +21,21 @@ func TestOffersProcessorTestSuiteState(t *testing.T) { type OffersProcessorTestSuiteState struct { suite.Suite - ctx context.Context - processor *OffersProcessor - mockQ *history.MockQOffers - sequence uint32 + ctx context.Context + processor *OffersProcessor + mockQ *history.MockQOffers + sequence uint32 + mockOffersBatchInsertBuilder *history.MockOffersBatchInsertBuilder } func (s *OffersProcessorTestSuiteState) SetupTest() { s.ctx = context.Background() s.mockQ = &history.MockQOffers{} + s.mockOffersBatchInsertBuilder = &history.MockOffersBatchInsertBuilder{} + s.mockQ.On("NewOffersBatchInsertBuilder").Return(s.mockOffersBatchInsertBuilder).Twice() + s.mockOffersBatchInsertBuilder.On("Exec", s.ctx).Return(nil).Once() + s.sequence = 456 s.processor = NewOffersProcessor(s.mockQ, s.sequence) } @@ -57,15 +62,13 @@ func (s *OffersProcessorTestSuiteState) TestCreateOffer() { LastModifiedLedgerSeq: lastModifiedLedgerSeq, } - s.mockQ.On("UpsertOffers", s.ctx, []history.Offer{ - { - SellerID: "GC3C4AKRBQLHOJ45U4XG35ESVWRDECWO5XLDGYADO6DPR3L7KIDVUMML", - OfferID: 1, - Pricen: int32(1), - Priced: int32(2), - Price: float64(0.5), - LastModifiedLedger: uint32(lastModifiedLedgerSeq), - }, + s.mockOffersBatchInsertBuilder.On("Add", history.Offer{ + SellerID: "GC3C4AKRBQLHOJ45U4XG35ESVWRDECWO5XLDGYADO6DPR3L7KIDVUMML", + OfferID: 1, + Pricen: int32(1), + Priced: int32(2), + Price: float64(0.5), + LastModifiedLedger: uint32(lastModifiedLedgerSeq), }).Return(nil).Once() err := s.processor.ProcessChange(s.ctx, ingest.Change{ @@ -82,16 +85,21 @@ func TestOffersProcessorTestSuiteLedger(t *testing.T) { type OffersProcessorTestSuiteLedger struct { suite.Suite - ctx context.Context - processor *OffersProcessor - mockQ *history.MockQOffers - sequence uint32 + ctx context.Context + processor *OffersProcessor + mockQ *history.MockQOffers + sequence uint32 + mockOffersBatchInsertBuilder *history.MockOffersBatchInsertBuilder } func (s *OffersProcessorTestSuiteLedger) SetupTest() { s.ctx = context.Background() s.mockQ = &history.MockQOffers{} + s.mockOffersBatchInsertBuilder = &history.MockOffersBatchInsertBuilder{} + s.mockQ.On("NewOffersBatchInsertBuilder").Return(s.mockOffersBatchInsertBuilder).Twice() + s.mockOffersBatchInsertBuilder.On("Exec", s.ctx).Return(nil).Once() + s.sequence = 456 s.processor = NewOffersProcessor(s.mockQ, s.sequence) } @@ -166,15 +174,13 @@ func (s *OffersProcessorTestSuiteLedger) setupInsertOffer() { s.Assert().NoError(err) // We use LedgerEntryChangesCache so all changes are squashed - s.mockQ.On("UpsertOffers", s.ctx, []history.Offer{ - { - SellerID: "GC3C4AKRBQLHOJ45U4XG35ESVWRDECWO5XLDGYADO6DPR3L7KIDVUMML", - OfferID: 2, - Pricen: int32(1), - Priced: int32(6), - Price: float64(1) / float64(6), - LastModifiedLedger: uint32(lastModifiedLedgerSeq), - }, + s.mockOffersBatchInsertBuilder.On("Add", history.Offer{ + SellerID: "GC3C4AKRBQLHOJ45U4XG35ESVWRDECWO5XLDGYADO6DPR3L7KIDVUMML", + OfferID: 2, + Pricen: int32(1), + Priced: int32(6), + Price: float64(1) / float64(6), + LastModifiedLedger: uint32(lastModifiedLedgerSeq), }).Return(nil).Once() } @@ -223,6 +229,12 @@ func (s *OffersProcessorTestSuiteLedger) TestUpsertManyOffers() { Price: xdr.Price{2, 3}, } + yetAnotherOffer := xdr.OfferEntry{ + SellerId: xdr.MustAddress("GBRPYHIL2CI3FNQ4BXLFMNDLFJUNPU2HY3ZMFSHONUCEOASW7QC7OX2H"), + OfferId: xdr.Int64(4), + Price: xdr.Price{2, 6}, + } + updatedEntry := xdr.LedgerEntry{ LastModifiedLedgerSeq: lastModifiedLedgerSeq, Data: xdr.LedgerEntryData{ @@ -257,6 +269,37 @@ func (s *OffersProcessorTestSuiteLedger) TestUpsertManyOffers() { }) s.Assert().NoError(err) + err = s.processor.ProcessChange(s.ctx, ingest.Change{ + Type: xdr.LedgerEntryTypeOffer, + Pre: nil, + Post: &xdr.LedgerEntry{ + LastModifiedLedgerSeq: lastModifiedLedgerSeq, + Data: xdr.LedgerEntryData{ + Type: xdr.LedgerEntryTypeOffer, + Offer: &yetAnotherOffer, + }, + }, + }) + s.Assert().NoError(err) + + s.mockOffersBatchInsertBuilder.On("Add", history.Offer{ + SellerID: "GDMUVYVYPYZYBDXNJWKFT3X2GCZCICTL3GSVP6AWBGB4ZZG7ZRDA746P", + OfferID: 3, + Pricen: int32(2), + Priced: int32(3), + Price: float64(2) / float64(3), + LastModifiedLedger: uint32(lastModifiedLedgerSeq), + }).Return(nil).Once() + + s.mockOffersBatchInsertBuilder.On("Add", history.Offer{ + SellerID: "GBRPYHIL2CI3FNQ4BXLFMNDLFJUNPU2HY3ZMFSHONUCEOASW7QC7OX2H", + OfferID: 4, + Pricen: int32(2), + Priced: int32(6), + Price: float64(2) / float64(6), + LastModifiedLedger: uint32(lastModifiedLedgerSeq), + }).Return(nil).Once() + s.mockQ.On("UpsertOffers", s.ctx, mock.Anything).Run(func(args mock.Arguments) { // To fix order issue due to using ChangeCompactor offers := args.Get(1).([]history.Offer) @@ -271,14 +314,6 @@ func (s *OffersProcessorTestSuiteLedger) TestUpsertManyOffers() { Price: float64(1) / float64(6), LastModifiedLedger: uint32(lastModifiedLedgerSeq), }, - { - SellerID: "GDMUVYVYPYZYBDXNJWKFT3X2GCZCICTL3GSVP6AWBGB4ZZG7ZRDA746P", - OfferID: 3, - Pricen: int32(2), - Priced: int32(3), - Price: float64(2) / float64(3), - LastModifiedLedger: uint32(lastModifiedLedgerSeq), - }, }, ) }).Return(nil).Once() @@ -367,15 +402,13 @@ func (s *OffersProcessorTestSuiteLedger) TestProcessUpgradeChange() { s.Assert().NoError(err) // We use LedgerEntryChangesCache so all changes are squashed - s.mockQ.On("UpsertOffers", s.ctx, []history.Offer{ - { - SellerID: "GC3C4AKRBQLHOJ45U4XG35ESVWRDECWO5XLDGYADO6DPR3L7KIDVUMML", - OfferID: 2, - Pricen: 1, - Priced: 6, - Price: float64(1) / float64(6), - LastModifiedLedger: uint32(lastModifiedLedgerSeq), - }, + s.mockOffersBatchInsertBuilder.On("Add", history.Offer{ + SellerID: "GC3C4AKRBQLHOJ45U4XG35ESVWRDECWO5XLDGYADO6DPR3L7KIDVUMML", + OfferID: 2, + Pricen: 1, + Priced: 6, + Price: float64(1) / float64(6), + LastModifiedLedger: uint32(lastModifiedLedgerSeq), }).Return(nil).Once() s.mockQ.On("CompactOffers", s.ctx, s.sequence-100).Return(int64(0), nil).Once() diff --git a/services/horizon/internal/ingest/processors/operations_processor.go b/services/horizon/internal/ingest/processors/operations_processor.go index 648c448ea4..8ad023145c 100644 --- a/services/horizon/internal/ingest/processors/operations_processor.go +++ b/services/horizon/internal/ingest/processors/operations_processor.go @@ -5,12 +5,16 @@ import ( "encoding/base64" "encoding/json" "fmt" + "sort" "github.com/guregu/null" + "github.com/stellar/go/amount" "github.com/stellar/go/ingest" "github.com/stellar/go/protocols/horizon/base" "github.com/stellar/go/services/horizon/internal/db2/history" + "github.com/stellar/go/support/contractevents" + "github.com/stellar/go/support/db" "github.com/stellar/go/support/errors" "github.com/stellar/go/toid" "github.com/stellar/go/xdr" @@ -18,28 +22,26 @@ import ( // OperationProcessor operations processor type OperationProcessor struct { - operationsQ history.QOperations - - sequence uint32 - batch history.OperationBatchInsertBuilder + batch history.OperationBatchInsertBuilder + network string } -func NewOperationProcessor(operationsQ history.QOperations, sequence uint32) *OperationProcessor { +func NewOperationProcessor(batch history.OperationBatchInsertBuilder, network string) *OperationProcessor { return &OperationProcessor{ - operationsQ: operationsQ, - sequence: sequence, - batch: operationsQ.NewOperationBatchInsertBuilder(maxBatchSize), + batch: batch, + network: network, } } // ProcessTransaction process the given transaction -func (p *OperationProcessor) ProcessTransaction(ctx context.Context, transaction ingest.LedgerTransaction) error { +func (p *OperationProcessor) ProcessTransaction(lcm xdr.LedgerCloseMeta, transaction ingest.LedgerTransaction) error { for i, op := range transaction.Envelope.Operations() { operation := transactionOperationWrapper{ index: uint32(i), transaction: transaction, operation: op, - ledgerSequence: p.sequence, + ledgerSequence: lcm.LedgerSequence(), + network: p.network, } details, err := operation.Details() if err != nil { @@ -57,7 +59,7 @@ func (p *OperationProcessor) ProcessTransaction(ctx context.Context, transaction if source.Type == xdr.CryptoKeyTypeKeyTypeMuxedEd25519 { sourceAccountMuxed = null.StringFrom(source.Address()) } - if err := p.batch.Add(ctx, + if err := p.batch.Add( operation.ID(), operation.TransactionID(), operation.Order(), @@ -65,6 +67,7 @@ func (p *OperationProcessor) ProcessTransaction(ctx context.Context, transaction detailsJSON, acID.Address(), sourceAccountMuxed, + operation.IsPayment(), ); err != nil { return errors.Wrap(err, "Error batch inserting operation rows") } @@ -73,8 +76,8 @@ func (p *OperationProcessor) ProcessTransaction(ctx context.Context, transaction return nil } -func (p *OperationProcessor) Commit(ctx context.Context) error { - return p.batch.Exec(ctx) +func (p *OperationProcessor) Flush(ctx context.Context, session db.SessionInterface) error { + return p.batch.Exec(ctx, session) } // transactionOperationWrapper represents the data for a single operation within a transaction @@ -83,6 +86,7 @@ type transactionOperationWrapper struct { transaction ingest.LedgerTransaction operation xdr.Operation ledgerSequence uint32 + network string } // ID returns the ID for the operation. @@ -248,6 +252,45 @@ func (operation *transactionOperationWrapper) OperationResult() *xdr.OperationRe return &tr } +// Determines if an operation is qualified to represent a payment in horizon terms. +func (operation *transactionOperationWrapper) IsPayment() bool { + switch operation.OperationType() { + case xdr.OperationTypeCreateAccount: + return true + case xdr.OperationTypePayment: + return true + case xdr.OperationTypePathPaymentStrictReceive: + return true + case xdr.OperationTypePathPaymentStrictSend: + return true + case xdr.OperationTypeAccountMerge: + return true + case xdr.OperationTypeInvokeHostFunction: + diagnosticEvents, err := operation.transaction.GetDiagnosticEvents() + if err != nil { + return false + } + // scan all the contract events for at least one SAC event, qualified to be a payment + // in horizon + for _, contractEvent := range filterEvents(diagnosticEvents) { + if sacEvent, err := contractevents.NewStellarAssetContractEvent(&contractEvent, operation.network); err == nil { + switch sacEvent.GetType() { + case contractevents.EventTypeTransfer: + return true + case contractevents.EventTypeMint: + return true + case contractevents.EventTypeClawback: + return true + case contractevents.EventTypeBurn: + return true + } + } + } + } + + return false +} + func (operation *transactionOperationWrapper) findInitatingBeginSponsoringOp() *transactionOperationWrapper { if !operation.transaction.Result.Successful() { // Failed transactions may not have a compliant sandwich structure @@ -297,7 +340,9 @@ func (operation *transactionOperationWrapper) Details() (map[string]interface{}, addAccountAndMuxedAccountDetails(details, *source, "from") addAccountAndMuxedAccountDetails(details, op.Destination, "to") details["amount"] = amount.String(op.Amount) - addAssetDetails(details, op.Asset, "") + if err := addAssetDetails(details, op.Asset, ""); err != nil { + return nil, err + } case xdr.OperationTypePathPaymentStrictReceive: op := operation.operation.Body.MustPathPaymentStrictReceiveOp() addAccountAndMuxedAccountDetails(details, *source, "from") @@ -306,8 +351,12 @@ func (operation *transactionOperationWrapper) Details() (map[string]interface{}, details["amount"] = amount.String(op.DestAmount) details["source_amount"] = amount.String(0) details["source_max"] = amount.String(op.SendMax) - addAssetDetails(details, op.DestAsset, "") - addAssetDetails(details, op.SendAsset, "source_") + if err := addAssetDetails(details, op.DestAsset, ""); err != nil { + return nil, err + } + if err := addAssetDetails(details, op.SendAsset, "source_"); err != nil { + return nil, err + } if operation.transaction.Result.Successful() { result := operation.OperationResult().MustPathPaymentStrictReceiveResult() @@ -317,7 +366,9 @@ func (operation *transactionOperationWrapper) Details() (map[string]interface{}, var path = make([]map[string]interface{}, len(op.Path)) for i := range op.Path { path[i] = make(map[string]interface{}) - addAssetDetails(path[i], op.Path[i], "") + if err := addAssetDetails(path[i], op.Path[i], ""); err != nil { + return nil, err + } } details["path"] = path @@ -329,8 +380,12 @@ func (operation *transactionOperationWrapper) Details() (map[string]interface{}, details["amount"] = amount.String(0) details["source_amount"] = amount.String(op.SendAmount) details["destination_min"] = amount.String(op.DestMin) - addAssetDetails(details, op.DestAsset, "") - addAssetDetails(details, op.SendAsset, "source_") + if err := addAssetDetails(details, op.DestAsset, ""); err != nil { + return nil, err + } + if err := addAssetDetails(details, op.SendAsset, "source_"); err != nil { + return nil, err + } if operation.transaction.Result.Successful() { result := operation.OperationResult().MustPathPaymentStrictSendResult() @@ -340,7 +395,9 @@ func (operation *transactionOperationWrapper) Details() (map[string]interface{}, var path = make([]map[string]interface{}, len(op.Path)) for i := range op.Path { path[i] = make(map[string]interface{}) - addAssetDetails(path[i], op.Path[i], "") + if err := addAssetDetails(path[i], op.Path[i], ""); err != nil { + return nil, err + } } details["path"] = path case xdr.OperationTypeManageBuyOffer: @@ -352,8 +409,12 @@ func (operation *transactionOperationWrapper) Details() (map[string]interface{}, "n": op.Price.N, "d": op.Price.D, } - addAssetDetails(details, op.Buying, "buying_") - addAssetDetails(details, op.Selling, "selling_") + if err := addAssetDetails(details, op.Buying, "buying_"); err != nil { + return nil, err + } + if err := addAssetDetails(details, op.Selling, "selling_"); err != nil { + return nil, err + } case xdr.OperationTypeManageSellOffer: op := operation.operation.Body.MustManageSellOfferOp() details["offer_id"] = op.OfferId @@ -363,8 +424,12 @@ func (operation *transactionOperationWrapper) Details() (map[string]interface{}, "n": op.Price.N, "d": op.Price.D, } - addAssetDetails(details, op.Buying, "buying_") - addAssetDetails(details, op.Selling, "selling_") + if err := addAssetDetails(details, op.Buying, "buying_"); err != nil { + return nil, err + } + if err := addAssetDetails(details, op.Selling, "selling_"); err != nil { + return nil, err + } case xdr.OperationTypeCreatePassiveSellOffer: op := operation.operation.Body.MustCreatePassiveSellOfferOp() details["amount"] = amount.String(op.Amount) @@ -373,8 +438,12 @@ func (operation *transactionOperationWrapper) Details() (map[string]interface{}, "n": op.Price.N, "d": op.Price.D, } - addAssetDetails(details, op.Buying, "buying_") - addAssetDetails(details, op.Selling, "selling_") + if err := addAssetDetails(details, op.Buying, "buying_"); err != nil { + return nil, err + } + if err := addAssetDetails(details, op.Selling, "selling_"); err != nil { + return nil, err + } case xdr.OperationTypeSetOptions: op := operation.operation.Body.MustSetOptionsOp() @@ -421,14 +490,18 @@ func (operation *transactionOperationWrapper) Details() (map[string]interface{}, return nil, err } } else { - addAssetDetails(details, op.Line.ToAsset(), "") + if err := addAssetDetails(details, op.Line.ToAsset(), ""); err != nil { + return nil, err + } details["trustee"] = details["asset_issuer"] } addAccountAndMuxedAccountDetails(details, *source, "trustor") details["limit"] = amount.String(op.Limit) case xdr.OperationTypeAllowTrust: op := operation.operation.Body.MustAllowTrustOp() - addAssetDetails(details, op.Asset.ToAsset(source.ToAccountId()), "") + if err := addAssetDetails(details, op.Asset.ToAsset(source.ToAccountId()), ""); err != nil { + return nil, err + } addAccountAndMuxedAccountDetails(details, *source, "trustee") details["trustor"] = op.Trustor.Address() details["authorize"] = xdr.TrustLineFlags(op.Authorize).IsAuthorized() @@ -499,7 +572,9 @@ func (operation *transactionOperationWrapper) Details() (map[string]interface{}, } case xdr.OperationTypeClawback: op := operation.operation.Body.MustClawbackOp() - addAssetDetails(details, op.Asset, "") + if err := addAssetDetails(details, op.Asset, ""); err != nil { + return nil, err + } addAccountAndMuxedAccountDetails(details, op.From, "from") details["amount"] = amount.String(op.Amount) case xdr.OperationTypeClawbackClaimableBalance: @@ -512,7 +587,9 @@ func (operation *transactionOperationWrapper) Details() (map[string]interface{}, case xdr.OperationTypeSetTrustLineFlags: op := operation.operation.Body.MustSetTrustLineFlagsOp() details["trustor"] = op.Trustor.Address() - addAssetDetails(details, op.Asset, "") + if err := addAssetDetails(details, op.Asset, ""); err != nil { + return nil, err + } if op.SetFlags > 0 { addTrustLineFlagDetails(details, xdr.TrustLineFlags(op.SetFlags), "set") } @@ -584,9 +661,68 @@ func (operation *transactionOperationWrapper) Details() (map[string]interface{}, {Asset: assetA, Amount: amount.String(receivedA)}, {Asset: assetB, Amount: amount.String(receivedB)}, } + case xdr.OperationTypeInvokeHostFunction: + op := operation.operation.Body.MustInvokeHostFunctionOp() + details["function"] = op.HostFunction.Type.String() + + switch op.HostFunction.Type { + case xdr.HostFunctionTypeHostFunctionTypeInvokeContract: + invokeArgs := op.HostFunction.MustInvokeContract() + args := make([]xdr.ScVal, 0, len(invokeArgs.Args)+2) + args = append(args, xdr.ScVal{Type: xdr.ScValTypeScvAddress, Address: &invokeArgs.ContractAddress}) + args = append(args, xdr.ScVal{Type: xdr.ScValTypeScvSymbol, Sym: &invokeArgs.FunctionName}) + args = append(args, invokeArgs.Args...) + params := make([]map[string]string, 0, len(args)) + + for _, param := range args { + serializedParam := map[string]string{} + serializedParam["value"] = "n/a" + serializedParam["type"] = "n/a" + + if scValTypeName, ok := param.ArmForSwitch(int32(param.Type)); ok { + serializedParam["type"] = scValTypeName + if raw, err := param.MarshalBinary(); err == nil { + serializedParam["value"] = base64.StdEncoding.EncodeToString(raw) + } + } + params = append(params, serializedParam) + } + details["parameters"] = params + if balanceChanges, err := operation.parseAssetBalanceChangesFromContractEvents(); err != nil { + return nil, err + } else { + details["asset_balance_changes"] = balanceChanges + } + + case xdr.HostFunctionTypeHostFunctionTypeCreateContract: + args := op.HostFunction.MustCreateContract() + switch args.ContractIdPreimage.Type { + case xdr.ContractIdPreimageTypeContractIdPreimageFromAddress: + fromAddress := args.ContractIdPreimage.MustFromAddress() + address, err := fromAddress.Address.String() + if err != nil { + panic(fmt.Errorf("error obtaining address for: %s", args.ContractIdPreimage.Type)) + } + details["from"] = "address" + details["address"] = address + details["salt"] = fromAddress.Salt.String() + case xdr.ContractIdPreimageTypeContractIdPreimageFromAsset: + details["from"] = "asset" + details["asset"] = args.ContractIdPreimage.MustFromAsset().StringCanonical() + default: + panic(fmt.Errorf("unknown contract id type: %s", args.ContractIdPreimage.Type)) + } + case xdr.HostFunctionTypeHostFunctionTypeUploadContractWasm: + default: + panic(fmt.Errorf("unknown host function type: %s", op.HostFunction.Type)) + } + case xdr.OperationTypeExtendFootprintTtl: + op := operation.operation.Body.MustExtendFootprintTtlOp() + details["extend_to"] = op.ExtendTo + case xdr.OperationTypeRestoreFootprint: default: - panic(fmt.Errorf("Unknown operation type: %s", operation.OperationType())) + panic(fmt.Errorf("unknown operation type: %s", operation.OperationType())) } sponsor, err := operation.getSponsor() @@ -600,10 +736,78 @@ func (operation *transactionOperationWrapper) Details() (map[string]interface{}, return details, nil } +// Searches an operation for SAC events that are of a type which represent +// asset balances having changed. +// +// SAC events have a one-to-one association to SAC contract fn invocations. +// i.e. invoke the 'mint' function, will trigger one Mint Event to be emitted capturing the fn args. +// +// SAC events that involve asset balance changes follow some standard data formats. +// The 'amount' in the event is expressed as Int128Parts, which carries a sign, however it's expected +// that value will not be signed as it represents a absolute delta, the event type can provide the +// context of whether an amount was considered incremental or decremental, i.e. credit or debit to a balance. +func (operation *transactionOperationWrapper) parseAssetBalanceChangesFromContractEvents() ([]map[string]interface{}, error) { + balanceChanges := []map[string]interface{}{} + + diagnosticEvents, err := operation.transaction.GetDiagnosticEvents() + if err != nil { + // this operation in this context must be an InvokeHostFunctionOp, therefore V3Meta should be present + // as it's in same soroban model, so if any err, it's real, + return nil, err + } + + for _, contractEvent := range filterEvents(diagnosticEvents) { + // Parse the xdr contract event to contractevents.StellarAssetContractEvent model + + // has some convenience like to/from attributes are expressed in strkey format for accounts(G...) and contracts(C...) + if sacEvent, err := contractevents.NewStellarAssetContractEvent(&contractEvent, operation.network); err == nil { + switch sacEvent.GetType() { + case contractevents.EventTypeTransfer: + transferEvt := sacEvent.(*contractevents.TransferEvent) + balanceChanges = append(balanceChanges, createSACBalanceChangeEntry(transferEvt.From, transferEvt.To, transferEvt.Amount, transferEvt.Asset, "transfer")) + case contractevents.EventTypeMint: + mintEvt := sacEvent.(*contractevents.MintEvent) + balanceChanges = append(balanceChanges, createSACBalanceChangeEntry("", mintEvt.To, mintEvt.Amount, mintEvt.Asset, "mint")) + case contractevents.EventTypeClawback: + clawbackEvt := sacEvent.(*contractevents.ClawbackEvent) + balanceChanges = append(balanceChanges, createSACBalanceChangeEntry(clawbackEvt.From, "", clawbackEvt.Amount, clawbackEvt.Asset, "clawback")) + case contractevents.EventTypeBurn: + burnEvt := sacEvent.(*contractevents.BurnEvent) + balanceChanges = append(balanceChanges, createSACBalanceChangeEntry(burnEvt.From, "", burnEvt.Amount, burnEvt.Asset, "burn")) + } + } + } + + return balanceChanges, nil +} + +// fromAccount - strkey format of contract or address +// toAccount - strkey format of contract or address, or nillable +// amountChanged - absolute value that asset balance changed +// asset - the fully qualified issuer:code for asset that had balance change +// changeType - the type of source sac event that triggered this change +// +// return - a balance changed record expressed as map of key/value's +func createSACBalanceChangeEntry(fromAccount string, toAccount string, amountChanged xdr.Int128Parts, asset xdr.Asset, changeType string) map[string]interface{} { + balanceChange := map[string]interface{}{} + + if fromAccount != "" { + balanceChange["from"] = fromAccount + } + if toAccount != "" { + balanceChange["to"] = toAccount + } + + balanceChange["type"] = changeType + balanceChange["amount"] = amount.String128(amountChanged) + addAssetDetails(balanceChange, asset, "") + return balanceChange +} + func addLiquidityPoolAssetDetails(result map[string]interface{}, lpp xdr.LiquidityPoolParameters) error { result["asset_type"] = "liquidity_pool_shares" if lpp.Type != xdr.LiquidityPoolTypeLiquidityPoolConstantProduct { - return fmt.Errorf("unkown liquidity pool type %d", lpp.Type) + return fmt.Errorf("unknown liquidity pool type %d", lpp.Type) } cp := lpp.ConstantProduct poolID, err := xdr.NewPoolId(cp.AssetA, cp.AssetB, cp.Fee) @@ -809,8 +1013,14 @@ func (operation *transactionOperationWrapper) Participants() ([]xdr.AccountId, e // the only direct participant is the source_account case xdr.OperationTypeLiquidityPoolWithdraw: // the only direct participant is the source_account + case xdr.OperationTypeInvokeHostFunction: + // the only direct participant is the source_account + case xdr.OperationTypeExtendFootprintTtl: + // the only direct participant is the source_account + case xdr.OperationTypeRestoreFootprint: + // the only direct participant is the source_account default: - return participants, fmt.Errorf("Unknown operation type: %s", op.Body.Type) + return participants, fmt.Errorf("unknown operation type: %s", op.Body.Type) } sponsor, err := operation.getSponsor() @@ -825,16 +1035,25 @@ func (operation *transactionOperationWrapper) Participants() ([]xdr.AccountId, e } // dedupeParticipants remove any duplicate ids from `in` -func dedupeParticipants(in []xdr.AccountId) (out []xdr.AccountId) { - set := map[string]xdr.AccountId{} - for _, id := range in { - set[id.Address()] = id +func dedupeParticipants(in []xdr.AccountId) []xdr.AccountId { + if len(in) <= 1 { + return in } - - for _, id := range set { - out = append(out, id) + sort.Slice(in, func(i, j int) bool { + return in[i].Address() < in[j].Address() + }) + insert := 1 + for cur := 1; cur < len(in); cur++ { + if in[cur].Equals(in[cur-1]) { + continue + } + if insert != cur { + in[insert] = in[cur] + } + insert++ } - return + return in[:insert] + } // OperationsParticipants returns a map with all participants per operation diff --git a/services/horizon/internal/ingest/processors/operations_processor_test.go b/services/horizon/internal/ingest/processors/operations_processor_test.go index 79b94b1f7f..4b5fb376cd 100644 --- a/services/horizon/internal/ingest/processors/operations_processor_test.go +++ b/services/horizon/internal/ingest/processors/operations_processor_test.go @@ -4,7 +4,9 @@ package processors import ( "context" + "encoding/base64" "encoding/json" + "math/big" "testing" "github.com/guregu/null" @@ -12,7 +14,11 @@ import ( "github.com/stretchr/testify/suite" "github.com/stellar/go/ingest" + "github.com/stellar/go/keypair" "github.com/stellar/go/services/horizon/internal/db2/history" + "github.com/stellar/go/strkey" + "github.com/stellar/go/support/contractevents" + "github.com/stellar/go/support/db" "github.com/stellar/go/support/errors" "github.com/stellar/go/xdr" ) @@ -21,7 +27,7 @@ type OperationsProcessorTestSuiteLedger struct { suite.Suite ctx context.Context processor *OperationProcessor - mockQ *history.MockQOperations + mockSession *db.MockSession mockBatchInsertBuilder *history.MockOperationsBatchInsertBuilder } @@ -31,20 +37,15 @@ func TestOperationProcessorTestSuiteLedger(t *testing.T) { func (s *OperationsProcessorTestSuiteLedger) SetupTest() { s.ctx = context.Background() - s.mockQ = &history.MockQOperations{} s.mockBatchInsertBuilder = &history.MockOperationsBatchInsertBuilder{} - s.mockQ. - On("NewOperationBatchInsertBuilder", maxBatchSize). - Return(s.mockBatchInsertBuilder).Once() s.processor = NewOperationProcessor( - s.mockQ, - 56, + s.mockBatchInsertBuilder, + "test network", ) } func (s *OperationsProcessorTestSuiteLedger) TearDownTest() { - s.mockQ.AssertExpectations(s.T()) s.mockBatchInsertBuilder.AssertExpectations(s.T()) } @@ -74,7 +75,6 @@ func (s *OperationsProcessorTestSuiteLedger) mockBatchInsertAdds(txs []ingest.Le } s.mockBatchInsertBuilder.On( "Add", - s.ctx, expected.ID(), expected.TransactionID(), expected.Order(), @@ -82,6 +82,7 @@ func (s *OperationsProcessorTestSuiteLedger) mockBatchInsertAdds(txs []ingest.Le detailsJSON, acID.Address(), muxedAccount, + mock.Anything, ).Return(nil).Once() } } @@ -89,7 +90,315 @@ func (s *OperationsProcessorTestSuiteLedger) mockBatchInsertAdds(txs []ingest.Le return nil } +func (s *OperationsProcessorTestSuiteLedger) TestOperationTypeInvokeHostFunctionDetails() { + sourceAddress := "GAUJETIZVEP2NRYLUESJ3LS66NVCEGMON4UDCBCSBEVPIID773P2W6AY" + source := xdr.MustMuxedAddress(sourceAddress) + + contractParamVal0 := xdr.ScAddress{ + Type: xdr.ScAddressTypeScAddressTypeContract, + ContractId: &xdr.Hash{0x1, 0x2}, + } + contractParamVal1 := xdr.ScSymbol("func1") + contractParamVal2 := xdr.Int32(-5) + contractParamVal3 := xdr.Uint32(6) + contractParamVal4 := xdr.Uint64(3) + contractParamVal5 := xdr.ScBytes([]byte{0, 1, 2}) + contractParamVal6 := true + + accountId := xdr.MustAddress("GB7BDSZU2Y27LYNLALKKALB52WS2IZWYBDGY6EQBLEED3TJOCVMZRH7H") + wasm := []byte("Some contract code") + + tx := ingest.LedgerTransaction{ + UnsafeMeta: xdr.TransactionMeta{ + V: 2, + V2: &xdr.TransactionMetaV2{}, + }, + } + + s.T().Run("InvokeContract", func(t *testing.T) { + wrapper := transactionOperationWrapper{ + transaction: tx, + operation: xdr.Operation{ + SourceAccount: &source, + Body: xdr.OperationBody{ + Type: xdr.OperationTypeInvokeHostFunction, + InvokeHostFunctionOp: &xdr.InvokeHostFunctionOp{ + HostFunction: xdr.HostFunction{ + Type: xdr.HostFunctionTypeHostFunctionTypeInvokeContract, + InvokeContract: &xdr.InvokeContractArgs{ + ContractAddress: contractParamVal0, + FunctionName: contractParamVal1, + Args: xdr.ScVec{ + { + Type: xdr.ScValTypeScvI32, + I32: &contractParamVal2, + }, + { + Type: xdr.ScValTypeScvU32, + U32: &contractParamVal3, + }, + { + Type: xdr.ScValTypeScvU64, + U64: &contractParamVal4, + }, + { + Type: xdr.ScValTypeScvBytes, + Bytes: &contractParamVal5, + }, + { + Type: xdr.ScValTypeScvBool, + B: &contractParamVal6, + }, + { + // invalid ScVal + Type: 5555, + }, + }, + }, + }, + }, + }, + }, + } + + details, err := wrapper.Details() + s.Assert().NoError(err) + + args := []xdr.ScVal{ + { + Type: xdr.ScValTypeScvAddress, + Address: &contractParamVal0, + }, + { + Type: xdr.ScValTypeScvSymbol, + Sym: &contractParamVal1, + }, + } + args = append(args, wrapper.operation.Body.InvokeHostFunctionOp.HostFunction.InvokeContract.Args...) + detailsFunctionParams := details["parameters"].([]map[string]string) + s.Assert().Equal(details["function"], "HostFunctionTypeHostFunctionTypeInvokeContract") + s.assertInvokeHostFunctionParameter(detailsFunctionParams, 0, "Address", args[0]) + s.assertInvokeHostFunctionParameter(detailsFunctionParams, 1, "Sym", args[1]) + s.assertInvokeHostFunctionParameter(detailsFunctionParams, 2, "I32", args[2]) + s.assertInvokeHostFunctionParameter(detailsFunctionParams, 3, "U32", args[3]) + s.assertInvokeHostFunctionParameter(detailsFunctionParams, 4, "U64", args[4]) + s.assertInvokeHostFunctionParameter(detailsFunctionParams, 5, "Bytes", args[5]) + s.assertInvokeHostFunctionParameter(detailsFunctionParams, 6, "B", args[6]) + s.assertInvokeHostFunctionParameter(detailsFunctionParams, 7, "n/a", args[7]) + }) + + s.T().Run("CreateContractFromAsset", func(t *testing.T) { + wrapper := transactionOperationWrapper{ + transaction: tx, + operation: xdr.Operation{ + SourceAccount: &source, + Body: xdr.OperationBody{ + Type: xdr.OperationTypeInvokeHostFunction, + InvokeHostFunctionOp: &xdr.InvokeHostFunctionOp{ + HostFunction: xdr.HostFunction{ + Type: xdr.HostFunctionTypeHostFunctionTypeCreateContract, + CreateContract: &xdr.CreateContractArgs{ + ContractIdPreimage: xdr.ContractIdPreimage{ + Type: xdr.ContractIdPreimageTypeContractIdPreimageFromAsset, + FromAsset: &xdr.Asset{ + Type: 1, + AlphaNum4: &xdr.AlphaNum4{ + AssetCode: xdr.AssetCode4{65, 82, 83, 0}, + Issuer: xdr.MustAddress("GCXI6Q73J7F6EUSBZTPW4G4OUGVDHABPYF2U4KO7MVEX52OH5VMVUCRF"), + }, + }, + }, + Executable: xdr.ContractExecutable{ + Type: xdr.ContractExecutableTypeContractExecutableStellarAsset, + }, + }, + }, + }, + }, + }, + } + + details, err := wrapper.Details() + s.Assert().NoError(err) + + s.Assert().Equal(details["function"], "HostFunctionTypeHostFunctionTypeCreateContract") + s.Assert().Equal(details["from"], "asset") + s.Assert().Equal(details["asset"], "ARS:GCXI6Q73J7F6EUSBZTPW4G4OUGVDHABPYF2U4KO7MVEX52OH5VMVUCRF") + }) + + s.T().Run("CreateContractFromAddress", func(t *testing.T) { + wrapper := transactionOperationWrapper{ + transaction: tx, + operation: xdr.Operation{ + SourceAccount: &source, + Body: xdr.OperationBody{ + Type: xdr.OperationTypeInvokeHostFunction, + InvokeHostFunctionOp: &xdr.InvokeHostFunctionOp{ + HostFunction: xdr.HostFunction{ + Type: xdr.HostFunctionTypeHostFunctionTypeCreateContract, + CreateContract: &xdr.CreateContractArgs{ + ContractIdPreimage: xdr.ContractIdPreimage{ + Type: xdr.ContractIdPreimageTypeContractIdPreimageFromAddress, + FromAddress: &xdr.ContractIdPreimageFromAddress{ + Address: xdr.ScAddress{ + Type: xdr.ScAddressTypeScAddressTypeAccount, + AccountId: &accountId, + }, + Salt: xdr.Uint256{1}, + }, + }, + Executable: xdr.ContractExecutable{}, + }, + }, + }, + }, + }, + } + + details, err := wrapper.Details() + s.Assert().NoError(err) + + s.Assert().Equal(details["function"], "HostFunctionTypeHostFunctionTypeCreateContract") + s.Assert().Equal(details["from"], "address") + s.Assert().Equal(details["address"], "GB7BDSZU2Y27LYNLALKKALB52WS2IZWYBDGY6EQBLEED3TJOCVMZRH7H") + s.Assert().Equal(details["salt"], xdr.Uint256{1}.String()) + }) + + s.T().Run("UploadContractWasm", func(t *testing.T) { + wrapper := transactionOperationWrapper{ + transaction: tx, + operation: xdr.Operation{ + SourceAccount: &source, + Body: xdr.OperationBody{ + Type: xdr.OperationTypeInvokeHostFunction, + InvokeHostFunctionOp: &xdr.InvokeHostFunctionOp{ + HostFunction: xdr.HostFunction{ + Type: xdr.HostFunctionTypeHostFunctionTypeUploadContractWasm, + Wasm: &wasm, + }, + }, + }, + }, + } + + details, err := wrapper.Details() + s.Assert().NoError(err) + s.Assert().Equal(details["function"], "HostFunctionTypeHostFunctionTypeUploadContractWasm") + }) + + s.T().Run("InvokeContractWithSACEventsInDetails", func(t *testing.T) { + randomIssuer := keypair.MustRandom() + randomAsset := xdr.MustNewCreditAsset("TESTING", randomIssuer.Address()) + passphrase := "passphrase" + randomAccount := keypair.MustRandom().Address() + contractId := [32]byte{} + zeroContractStrKey, err := strkey.Encode(strkey.VersionByteContract, contractId[:]) + s.Assert().NoError(err) + + transferContractEvent := contractevents.GenerateEvent(contractevents.EventTypeTransfer, randomAccount, zeroContractStrKey, "", randomAsset, big.NewInt(10000000), passphrase) + burnContractEvent := contractevents.GenerateEvent(contractevents.EventTypeBurn, zeroContractStrKey, "", "", randomAsset, big.NewInt(10000000), passphrase) + mintContractEvent := contractevents.GenerateEvent(contractevents.EventTypeMint, "", zeroContractStrKey, randomAccount, randomAsset, big.NewInt(10000000), passphrase) + clawbackContractEvent := contractevents.GenerateEvent(contractevents.EventTypeClawback, zeroContractStrKey, "", randomAccount, randomAsset, big.NewInt(10000000), passphrase) + + tx = ingest.LedgerTransaction{ + UnsafeMeta: xdr.TransactionMeta{ + V: 3, + V3: &xdr.TransactionMetaV3{ + SorobanMeta: &xdr.SorobanTransactionMeta{ + Events: []xdr.ContractEvent{ + transferContractEvent, + burnContractEvent, + mintContractEvent, + clawbackContractEvent, + }, + }, + }, + }, + } + wrapper := transactionOperationWrapper{ + transaction: tx, + operation: xdr.Operation{ + SourceAccount: &source, + Body: xdr.OperationBody{ + Type: xdr.OperationTypeInvokeHostFunction, + InvokeHostFunctionOp: &xdr.InvokeHostFunctionOp{ + HostFunction: xdr.HostFunction{ + Type: xdr.HostFunctionTypeHostFunctionTypeInvokeContract, + InvokeContract: &xdr.InvokeContractArgs{ + ContractAddress: xdr.ScAddress{ + Type: xdr.ScAddressTypeScAddressTypeContract, + ContractId: &xdr.Hash{0x1, 0x2}, + }, + FunctionName: "foo", + Args: xdr.ScVec{}, + }, + }, + }, + }, + }, + network: passphrase, + } + + details, err := wrapper.Details() + s.Assert().NoError(err) + s.Assert().Len(details["asset_balance_changes"], 4) + + found := 0 + for _, assetBalanceChanged := range details["asset_balance_changes"].([]map[string]interface{}) { + if assetBalanceChanged["type"] == "transfer" { + s.Assert().Equal(assetBalanceChanged["from"], randomAccount) + s.Assert().Equal(assetBalanceChanged["to"], zeroContractStrKey) + s.Assert().Equal(assetBalanceChanged["amount"], "1.0000000") + found++ + } + + if assetBalanceChanged["type"] == "burn" { + s.Assert().Equal(assetBalanceChanged["from"], zeroContractStrKey) + s.Assert().NotContains(assetBalanceChanged, "to") + s.Assert().Equal(assetBalanceChanged["amount"], "1.0000000") + found++ + } + + if assetBalanceChanged["type"] == "mint" { + s.Assert().NotContains(assetBalanceChanged, "from") + s.Assert().Equal(assetBalanceChanged["to"], zeroContractStrKey) + s.Assert().Equal(assetBalanceChanged["amount"], "1.0000000") + found++ + } + + if assetBalanceChanged["type"] == "clawback" { + s.Assert().Equal(assetBalanceChanged["from"], zeroContractStrKey) + s.Assert().NotContains(assetBalanceChanged, "to") + s.Assert().Equal(assetBalanceChanged["amount"], "1.0000000") + found++ + } + } + s.Assert().Equal(found, 4, "should have one balance changed record for each of mint, burn, clawback, transfer") + }) +} + +func (s *OperationsProcessorTestSuiteLedger) assertInvokeHostFunctionParameter(parameters []map[string]string, paramPosition int, expectedType string, expectedVal xdr.ScVal) { + serializedParam := parameters[paramPosition] + s.Assert().Equal(serializedParam["type"], expectedType) + if expectedSerializedXdr, err := expectedVal.MarshalBinary(); err == nil { + s.Assert().Equal(serializedParam["value"], base64.StdEncoding.EncodeToString(expectedSerializedXdr)) + } else { + s.Assert().Equal(serializedParam["value"], "n/a") + } +} + func (s *OperationsProcessorTestSuiteLedger) TestAddOperationSucceeds() { + sequence := uint32(56) + lcm := xdr.LedgerCloseMeta{ + V0: &xdr.LedgerCloseMetaV0{ + LedgerHeader: xdr.LedgerHeaderHistoryEntry{ + Header: xdr.LedgerHeader{ + LedgerSeq: xdr.Uint32(sequence), + }, + }, + }, + } + unmuxed := xdr.MustAddress("GA5WBPYA5Y4WAEHXWR2UKO2UO4BUGHUQ74EUPKON2QHV4WRHOIRNKKH2") muxed := xdr.MuxedAccount{ Type: xdr.CryptoKeyTypeKeyTypeMuxedEd25519, @@ -120,23 +429,34 @@ func (s *OperationsProcessorTestSuiteLedger) TestAddOperationSucceeds() { var err error - err = s.mockBatchInsertAdds(txs, uint32(56)) + err = s.mockBatchInsertAdds(txs, sequence) s.Assert().NoError(err) - s.mockBatchInsertBuilder.On("Exec", s.ctx).Return(nil).Once() - s.Assert().NoError(s.processor.Commit(s.ctx)) + s.mockBatchInsertBuilder.On("Exec", s.ctx, s.mockSession).Return(nil).Once() for _, tx := range txs { - err = s.processor.ProcessTransaction(s.ctx, tx) + err = s.processor.ProcessTransaction(lcm, tx) s.Assert().NoError(err) } + s.Assert().NoError(s.processor.Flush(s.ctx, s.mockSession)) } func (s *OperationsProcessorTestSuiteLedger) TestAddOperationFails() { + sequence := uint32(56) + lcm := xdr.LedgerCloseMeta{ + V0: &xdr.LedgerCloseMetaV0{ + LedgerHeader: xdr.LedgerHeaderHistoryEntry{ + Header: xdr.LedgerHeader{ + LedgerSeq: xdr.Uint32(sequence), + }, + }, + }, + } tx := createTransaction(true, 1) s.mockBatchInsertBuilder. On( - "Add", s.ctx, + "Add", + mock.Anything, mock.Anything, mock.Anything, mock.Anything, @@ -146,14 +466,40 @@ func (s *OperationsProcessorTestSuiteLedger) TestAddOperationFails() { mock.Anything, ).Return(errors.New("transient error")).Once() - err := s.processor.ProcessTransaction(s.ctx, tx) + err := s.processor.ProcessTransaction(lcm, tx) s.Assert().Error(err) s.Assert().EqualError(err, "Error batch inserting operation rows: transient error") } func (s *OperationsProcessorTestSuiteLedger) TestExecFails() { - s.mockBatchInsertBuilder.On("Exec", s.ctx).Return(errors.New("transient error")).Once() - err := s.processor.Commit(s.ctx) + sequence := uint32(56) + lcm := xdr.LedgerCloseMeta{ + V0: &xdr.LedgerCloseMetaV0{ + LedgerHeader: xdr.LedgerHeaderHistoryEntry{ + Header: xdr.LedgerHeader{ + LedgerSeq: xdr.Uint32(sequence), + }, + }, + }, + } + tx := createTransaction(true, 1) + + s.mockBatchInsertBuilder. + On( + "Add", + mock.Anything, + mock.Anything, + mock.Anything, + mock.Anything, + mock.Anything, + mock.Anything, + mock.Anything, + mock.Anything, + ).Return(nil).Once() + s.Assert().NoError(s.processor.ProcessTransaction(lcm, tx)) + + s.mockBatchInsertBuilder.On("Exec", s.ctx, s.mockSession).Return(errors.New("transient error")).Once() + err := s.processor.Flush(s.ctx, s.mockSession) s.Assert().Error(err) s.Assert().EqualError(err, "transient error") } diff --git a/services/horizon/internal/ingest/processors/participants_processor.go b/services/horizon/internal/ingest/processors/participants_processor.go index d908f9ac69..7d4ae7fe39 100644 --- a/services/horizon/internal/ingest/processors/participants_processor.go +++ b/services/horizon/internal/ingest/processors/participants_processor.go @@ -7,7 +7,7 @@ import ( "github.com/stellar/go/ingest" "github.com/stellar/go/services/horizon/internal/db2/history" - set "github.com/stellar/go/support/collections/set" + "github.com/stellar/go/support/db" "github.com/stellar/go/support/errors" "github.com/stellar/go/toid" "github.com/stellar/go/xdr" @@ -16,64 +16,23 @@ import ( // ParticipantsProcessor is a processor which ingests various participants // from different sources (transactions, operations, etc) type ParticipantsProcessor struct { - participantsQ history.QParticipants - sequence uint32 - participantSet map[string]participant + accountLoader *history.AccountLoader + txBatch history.TransactionParticipantsBatchInsertBuilder + opBatch history.OperationParticipantBatchInsertBuilder } -func NewParticipantsProcessor(participantsQ history.QParticipants, sequence uint32) *ParticipantsProcessor { +func NewParticipantsProcessor( + accountLoader *history.AccountLoader, + txBatch history.TransactionParticipantsBatchInsertBuilder, + opBatch history.OperationParticipantBatchInsertBuilder, +) *ParticipantsProcessor { return &ParticipantsProcessor{ - participantsQ: participantsQ, - sequence: sequence, - participantSet: map[string]participant{}, + accountLoader: accountLoader, + txBatch: txBatch, + opBatch: opBatch, } } -type participant struct { - accountID int64 - transactionSet set.Set[int64] - operationSet set.Set[int64] -} - -func (p *participant) addTransactionID(id int64) { - if p.transactionSet == nil { - p.transactionSet = set.Set[int64]{} - } - p.transactionSet.Add(id) -} - -func (p *participant) addOperationID(id int64) { - if p.operationSet == nil { - p.operationSet = set.Set[int64]{} - } - p.operationSet.Add(id) -} - -func (p *ParticipantsProcessor) loadAccountIDs(ctx context.Context, participantSet map[string]participant) error { - addresses := make([]string, 0, len(participantSet)) - for address := range participantSet { - addresses = append(addresses, address) - } - - addressToID, err := p.participantsQ.CreateAccounts(ctx, addresses, maxBatchSize) - if err != nil { - return errors.Wrap(err, "Could not create account ids") - } - - for _, address := range addresses { - id, ok := addressToID[address] - if !ok { - return errors.Errorf("no id found for account address %s", address) - } - - participantForAddress := participantSet[address] - participantForAddress.accountID = id - participantSet[address] = participantForAddress - } - - return nil -} - func participantsForChanges( changes xdr.LedgerEntryChanges, ) ([]xdr.AccountId, error) { @@ -141,7 +100,6 @@ func participantsForMeta( } func (p *ParticipantsProcessor) addTransactionParticipants( - participantSet map[string]participant, sequence uint32, transaction ingest.LedgerTransaction, ) error { @@ -155,17 +113,15 @@ func (p *ParticipantsProcessor) addTransactionParticipants( } for _, participant := range transactionParticipants { - address := participant.Address() - entry := participantSet[address] - entry.addTransactionID(transactionID) - participantSet[address] = entry + if err := p.txBatch.Add(transactionID, p.accountLoader.GetFuture(participant.Address())); err != nil { + return err + } } return nil } func (p *ParticipantsProcessor) addOperationsParticipants( - participantSet map[string]participant, sequence uint32, transaction ingest.LedgerTransaction, ) error { @@ -174,82 +130,39 @@ func (p *ParticipantsProcessor) addOperationsParticipants( return errors.Wrap(err, "could not determine operation participants") } - for operationID, p := range participants { - for _, participant := range p { + for operationID, addresses := range participants { + for _, participant := range addresses { address := participant.Address() - entry := participantSet[address] - entry.addOperationID(operationID) - participantSet[address] = entry - } - } - - return nil -} - -func (p *ParticipantsProcessor) insertDBTransactionParticipants(ctx context.Context, participantSet map[string]participant) error { - batch := p.participantsQ.NewTransactionParticipantsBatchInsertBuilder(maxBatchSize) - - for _, entry := range participantSet { - for transactionID := range entry.transactionSet { - if err := batch.Add(ctx, transactionID, entry.accountID); err != nil { - return errors.Wrap(err, "Could not insert transaction participant in db") + if err := p.opBatch.Add(operationID, p.accountLoader.GetFuture(address)); err != nil { + return err } } } - if err := batch.Exec(ctx); err != nil { - return errors.Wrap(err, "Could not flush transaction participants to db") - } return nil } -func (p *ParticipantsProcessor) insertDBOperationsParticipants(ctx context.Context, participantSet map[string]participant) error { - batch := p.participantsQ.NewOperationParticipantBatchInsertBuilder(maxBatchSize) +func (p *ParticipantsProcessor) ProcessTransaction(lcm xdr.LedgerCloseMeta, transaction ingest.LedgerTransaction) error { - for _, entry := range participantSet { - for operationID := range entry.operationSet { - if err := batch.Add(ctx, operationID, entry.accountID); err != nil { - return errors.Wrap(err, "could not insert operation participant in db") - } - } - } - - if err := batch.Exec(ctx); err != nil { - return errors.Wrap(err, "could not flush operation participants to db") - } - return nil -} - -func (p *ParticipantsProcessor) ProcessTransaction(ctx context.Context, transaction ingest.LedgerTransaction) (err error) { - err = p.addTransactionParticipants(p.participantSet, p.sequence, transaction) - if err != nil { + if err := p.addTransactionParticipants(lcm.LedgerSequence(), transaction); err != nil { return err } - err = p.addOperationsParticipants(p.participantSet, p.sequence, transaction) - if err != nil { + if err := p.addOperationsParticipants(lcm.LedgerSequence(), transaction); err != nil { return err } return nil } -func (p *ParticipantsProcessor) Commit(ctx context.Context) (err error) { - if len(p.participantSet) > 0 { - if err = p.loadAccountIDs(ctx, p.participantSet); err != nil { - return err - } - - if err = p.insertDBTransactionParticipants(ctx, p.participantSet); err != nil { - return err - } - - if err = p.insertDBOperationsParticipants(ctx, p.participantSet); err != nil { - return err - } +func (p *ParticipantsProcessor) Flush(ctx context.Context, session db.SessionInterface) error { + if err := p.txBatch.Exec(ctx, session); err != nil { + return errors.Wrap(err, "Could not flush transaction participants to db") } - - return err + if err := p.opBatch.Exec(ctx, session); err != nil { + return errors.Wrap(err, "Could not flush operation participants to db") + } + return nil } func ParticipantsForTransaction( diff --git a/services/horizon/internal/ingest/processors/participants_processor_test.go b/services/horizon/internal/ingest/processors/participants_processor_test.go index 4780c2709c..2348b79eaf 100644 --- a/services/horizon/internal/ingest/processors/participants_processor_test.go +++ b/services/horizon/internal/ingest/processors/participants_processor_test.go @@ -6,11 +6,11 @@ import ( "context" "testing" - "github.com/stretchr/testify/mock" "github.com/stretchr/testify/suite" "github.com/stellar/go/ingest" "github.com/stellar/go/services/horizon/internal/db2/history" + "github.com/stellar/go/support/db" "github.com/stellar/go/support/errors" "github.com/stellar/go/toid" "github.com/stellar/go/xdr" @@ -20,19 +20,21 @@ type ParticipantsProcessorTestSuiteLedger struct { suite.Suite ctx context.Context processor *ParticipantsProcessor - mockQ *history.MockQParticipants + mockSession *db.MockSession mockBatchInsertBuilder *history.MockTransactionParticipantsBatchInsertBuilder mockOperationsBatchInsertBuilder *history.MockOperationParticipantBatchInsertBuilder - - firstTx ingest.LedgerTransaction - secondTx ingest.LedgerTransaction - thirdTx ingest.LedgerTransaction - firstTxID int64 - secondTxID int64 - thirdTxID int64 - addresses []string - addressToID map[string]int64 - txs []ingest.LedgerTransaction + accountLoader *history.AccountLoader + + lcm xdr.LedgerCloseMeta + firstTx ingest.LedgerTransaction + secondTx ingest.LedgerTransaction + thirdTx ingest.LedgerTransaction + firstTxID int64 + secondTxID int64 + thirdTxID int64 + addresses []string + addressToFuture map[string]history.FutureAccountID + txs []ingest.LedgerTransaction } func TestParticipantsProcessorTestSuiteLedger(t *testing.T) { @@ -41,10 +43,18 @@ func TestParticipantsProcessorTestSuiteLedger(t *testing.T) { func (s *ParticipantsProcessorTestSuiteLedger) SetupTest() { s.ctx = context.Background() - s.mockQ = &history.MockQParticipants{} s.mockBatchInsertBuilder = &history.MockTransactionParticipantsBatchInsertBuilder{} s.mockOperationsBatchInsertBuilder = &history.MockOperationParticipantBatchInsertBuilder{} sequence := uint32(20) + s.lcm = xdr.LedgerCloseMeta{ + V0: &xdr.LedgerCloseMetaV0{ + LedgerHeader: xdr.LedgerHeaderHistoryEntry{ + Header: xdr.LedgerHeader{ + LedgerSeq: xdr.Uint32(sequence), + }, + }, + }, + } s.addresses = []string{ "GA5WBPYA5Y4WAEHXWR2UKO2UO4BUGHUQ74EUPKON2QHV4WRHOIRNKKH2", @@ -76,15 +86,16 @@ func (s *ParticipantsProcessorTestSuiteLedger) SetupTest() { s.thirdTx.Envelope.V1.Tx.SourceAccount = aid.ToMuxedAccount() s.thirdTxID = toid.New(int32(sequence), 3, 0).ToInt64() - s.addressToID = map[string]int64{ - s.addresses[0]: 2, - s.addresses[1]: 20, - s.addresses[2]: 200, + s.accountLoader = history.NewAccountLoader() + s.addressToFuture = map[string]history.FutureAccountID{} + for _, address := range s.addresses { + s.addressToFuture[address] = s.accountLoader.GetFuture(address) } s.processor = NewParticipantsProcessor( - s.mockQ, - sequence, + s.accountLoader, + s.mockBatchInsertBuilder, + s.mockOperationsBatchInsertBuilder, ) s.txs = []ingest.LedgerTransaction{ @@ -95,44 +106,46 @@ func (s *ParticipantsProcessorTestSuiteLedger) SetupTest() { } func (s *ParticipantsProcessorTestSuiteLedger) TearDownTest() { - s.mockQ.AssertExpectations(s.T()) s.mockBatchInsertBuilder.AssertExpectations(s.T()) s.mockOperationsBatchInsertBuilder.AssertExpectations(s.T()) } func (s *ParticipantsProcessorTestSuiteLedger) mockSuccessfulTransactionBatchAdds() { s.mockBatchInsertBuilder.On( - "Add", s.ctx, s.firstTxID, s.addressToID[s.addresses[0]], + "Add", s.firstTxID, s.addressToFuture[s.addresses[0]], ).Return(nil).Once() s.mockBatchInsertBuilder.On( - "Add", s.ctx, s.secondTxID, s.addressToID[s.addresses[1]], + "Add", s.secondTxID, s.addressToFuture[s.addresses[1]], ).Return(nil).Once() s.mockBatchInsertBuilder.On( - "Add", s.ctx, s.secondTxID, s.addressToID[s.addresses[2]], + "Add", s.secondTxID, s.addressToFuture[s.addresses[2]], ).Return(nil).Once() s.mockBatchInsertBuilder.On( - "Add", s.ctx, s.thirdTxID, s.addressToID[s.addresses[0]], + "Add", s.thirdTxID, s.addressToFuture[s.addresses[0]], ).Return(nil).Once() } func (s *ParticipantsProcessorTestSuiteLedger) mockSuccessfulOperationBatchAdds() { s.mockOperationsBatchInsertBuilder.On( - "Add", s.ctx, s.firstTxID+1, s.addressToID[s.addresses[0]], + "Add", s.firstTxID+1, s.addressToFuture[s.addresses[0]], ).Return(nil).Once() s.mockOperationsBatchInsertBuilder.On( - "Add", s.ctx, s.secondTxID+1, s.addressToID[s.addresses[1]], + "Add", s.secondTxID+1, s.addressToFuture[s.addresses[1]], ).Return(nil).Once() s.mockOperationsBatchInsertBuilder.On( - "Add", s.ctx, s.secondTxID+1, s.addressToID[s.addresses[2]], + "Add", s.secondTxID+1, s.addressToFuture[s.addresses[2]], ).Return(nil).Once() s.mockOperationsBatchInsertBuilder.On( - "Add", s.ctx, s.thirdTxID+1, s.addressToID[s.addresses[0]], + "Add", s.thirdTxID+1, s.addressToFuture[s.addresses[0]], ).Return(nil).Once() } func (s *ParticipantsProcessorTestSuiteLedger) TestEmptyParticipants() { - err := s.processor.Commit(s.ctx) + s.mockBatchInsertBuilder.On("Exec", s.ctx, s.mockSession).Return(nil).Once() + s.mockOperationsBatchInsertBuilder.On("Exec", s.ctx, s.mockSession).Return(nil).Once() + + err := s.processor.Flush(s.ctx, s.mockSession) s.Assert().NoError(err) } @@ -166,198 +179,82 @@ func (s *ParticipantsProcessorTestSuiteLedger) TestFeeBumptransaction() { feeBumpTx.Result.Result.Result.Results = nil feeBumpTxID := toid.New(20, 1, 0).ToInt64() - addresses := s.addresses[:2] - addressToID := map[string]int64{ - addresses[0]: s.addressToID[addresses[0]], - addresses[1]: s.addressToID[addresses[1]], - } - s.mockQ.On("CreateAccounts", s.ctx, mock.AnythingOfType("[]string"), maxBatchSize). - Run(func(args mock.Arguments) { - arg := args.Get(1).([]string) - s.Assert().ElementsMatch( - addresses, - arg, - ) - }).Return(addressToID, nil).Once() - s.mockQ.On("NewTransactionParticipantsBatchInsertBuilder", maxBatchSize). - Return(s.mockBatchInsertBuilder).Once() - s.mockQ.On("NewOperationParticipantBatchInsertBuilder", maxBatchSize). - Return(s.mockOperationsBatchInsertBuilder).Once() - s.mockBatchInsertBuilder.On( - "Add", s.ctx, feeBumpTxID, addressToID[addresses[0]], + "Add", feeBumpTxID, s.addressToFuture[s.addresses[0]], ).Return(nil).Once() s.mockBatchInsertBuilder.On( - "Add", s.ctx, feeBumpTxID, addressToID[addresses[1]], + "Add", feeBumpTxID, s.addressToFuture[s.addresses[1]], ).Return(nil).Once() - s.mockBatchInsertBuilder.On("Exec", s.ctx).Return(nil).Once() - s.mockOperationsBatchInsertBuilder.On("Exec", s.ctx).Return(nil).Once() + s.mockBatchInsertBuilder.On("Exec", s.ctx, s.mockSession).Return(nil).Once() + s.mockOperationsBatchInsertBuilder.On("Exec", s.ctx, s.mockSession).Return(nil).Once() - s.Assert().NoError(s.processor.ProcessTransaction(s.ctx, feeBumpTx)) - s.Assert().NoError(s.processor.Commit(s.ctx)) + s.Assert().NoError(s.processor.ProcessTransaction(s.lcm, feeBumpTx)) + s.Assert().NoError(s.processor.Flush(s.ctx, s.mockSession)) } func (s *ParticipantsProcessorTestSuiteLedger) TestIngestParticipantsSucceeds() { - s.mockQ.On("CreateAccounts", s.ctx, mock.AnythingOfType("[]string"), maxBatchSize). - Run(func(args mock.Arguments) { - arg := args.Get(1).([]string) - s.Assert().ElementsMatch( - s.addresses, - arg, - ) - }).Return(s.addressToID, nil).Once() - s.mockQ.On("NewTransactionParticipantsBatchInsertBuilder", maxBatchSize). - Return(s.mockBatchInsertBuilder).Once() - s.mockQ.On("NewOperationParticipantBatchInsertBuilder", maxBatchSize). - Return(s.mockOperationsBatchInsertBuilder).Once() - s.mockSuccessfulTransactionBatchAdds() s.mockSuccessfulOperationBatchAdds() - s.mockBatchInsertBuilder.On("Exec", s.ctx).Return(nil).Once() - s.mockOperationsBatchInsertBuilder.On("Exec", s.ctx).Return(nil).Once() + s.mockBatchInsertBuilder.On("Exec", s.ctx, s.mockSession).Return(nil).Once() + s.mockOperationsBatchInsertBuilder.On("Exec", s.ctx, s.mockSession).Return(nil).Once() for _, tx := range s.txs { - err := s.processor.ProcessTransaction(s.ctx, tx) + err := s.processor.ProcessTransaction(s.lcm, tx) s.Assert().NoError(err) } - err := s.processor.Commit(s.ctx) + err := s.processor.Flush(s.ctx, s.mockSession) s.Assert().NoError(err) } -func (s *ParticipantsProcessorTestSuiteLedger) TestCreateAccountsFails() { - s.mockQ.On("CreateAccounts", s.ctx, mock.AnythingOfType("[]string"), maxBatchSize). - Return(s.addressToID, errors.New("transient error")).Once() - for _, tx := range s.txs { - err := s.processor.ProcessTransaction(s.ctx, tx) - s.Assert().NoError(err) - } - err := s.processor.Commit(s.ctx) - s.Assert().EqualError(err, "Could not create account ids: transient error") -} - func (s *ParticipantsProcessorTestSuiteLedger) TestBatchAddFails() { - s.mockQ.On("CreateAccounts", s.ctx, mock.AnythingOfType("[]string"), maxBatchSize). - Run(func(args mock.Arguments) { - arg := args.Get(1).([]string) - s.Assert().ElementsMatch( - s.addresses, - arg, - ) - }).Return(s.addressToID, nil).Once() - s.mockQ.On("NewTransactionParticipantsBatchInsertBuilder", maxBatchSize). - Return(s.mockBatchInsertBuilder).Once() - s.mockBatchInsertBuilder.On( - "Add", s.ctx, s.firstTxID, s.addressToID[s.addresses[0]], + "Add", s.firstTxID, s.addressToFuture[s.addresses[0]], ).Return(errors.New("transient error")).Once() - s.mockBatchInsertBuilder.On( - "Add", s.ctx, s.secondTxID, s.addressToID[s.addresses[1]], - ).Return(nil).Maybe() - s.mockBatchInsertBuilder.On( - "Add", s.ctx, s.secondTxID, s.addressToID[s.addresses[2]], - ).Return(nil).Maybe() - - s.mockBatchInsertBuilder.On( - "Add", s.ctx, s.thirdTxID, s.addressToID[s.addresses[0]], - ).Return(nil).Maybe() - for _, tx := range s.txs { - err := s.processor.ProcessTransaction(s.ctx, tx) - s.Assert().NoError(err) - } - err := s.processor.Commit(s.ctx) - s.Assert().EqualError(err, "Could not insert transaction participant in db: transient error") + err := s.processor.ProcessTransaction(s.lcm, s.txs[0]) + s.Assert().EqualError(err, "transient error") } func (s *ParticipantsProcessorTestSuiteLedger) TestOperationParticipantsBatchAddFails() { - s.mockQ.On("CreateAccounts", s.ctx, mock.AnythingOfType("[]string"), maxBatchSize). - Run(func(args mock.Arguments) { - arg := args.Get(1).([]string) - s.Assert().ElementsMatch( - s.addresses, - arg, - ) - }).Return(s.addressToID, nil).Once() - s.mockQ.On("NewTransactionParticipantsBatchInsertBuilder", maxBatchSize). - Return(s.mockBatchInsertBuilder).Once() - s.mockQ.On("NewOperationParticipantBatchInsertBuilder", maxBatchSize). - Return(s.mockOperationsBatchInsertBuilder).Once() - - s.mockSuccessfulTransactionBatchAdds() + s.mockBatchInsertBuilder.On( + "Add", s.firstTxID, s.addressToFuture[s.addresses[0]], + ).Return(nil).Once() s.mockOperationsBatchInsertBuilder.On( - "Add", s.ctx, s.firstTxID+1, s.addressToID[s.addresses[0]], + "Add", s.firstTxID+1, s.addressToFuture[s.addresses[0]], ).Return(errors.New("transient error")).Once() - s.mockOperationsBatchInsertBuilder.On( - "Add", s.ctx, s.secondTxID+1, s.addressToID[s.addresses[1]], - ).Return(nil).Maybe() - s.mockOperationsBatchInsertBuilder.On( - "Add", s.ctx, s.secondTxID+1, s.addressToID[s.addresses[2]], - ).Return(nil).Maybe() - s.mockOperationsBatchInsertBuilder.On( - "Add", s.ctx, s.thirdTxID+1, s.addressToID[s.addresses[0]], - ).Return(nil).Maybe() - - s.mockBatchInsertBuilder.On("Exec", s.ctx).Return(nil).Once() - for _, tx := range s.txs { - err := s.processor.ProcessTransaction(s.ctx, tx) - s.Assert().NoError(err) - } - err := s.processor.Commit(s.ctx) - s.Assert().EqualError(err, "could not insert operation participant in db: transient error") + err := s.processor.ProcessTransaction(s.lcm, s.txs[0]) + s.Assert().EqualError(err, "transient error") } func (s *ParticipantsProcessorTestSuiteLedger) TestBatchAddExecFails() { - s.mockQ.On("CreateAccounts", s.ctx, mock.AnythingOfType("[]string"), maxBatchSize). - Run(func(args mock.Arguments) { - arg := args.Get(1).([]string) - s.Assert().ElementsMatch( - s.addresses, - arg, - ) - }).Return(s.addressToID, nil).Once() - s.mockQ.On("NewTransactionParticipantsBatchInsertBuilder", maxBatchSize). - Return(s.mockBatchInsertBuilder).Once() - s.mockSuccessfulTransactionBatchAdds() + s.mockSuccessfulOperationBatchAdds() - s.mockBatchInsertBuilder.On("Exec", s.ctx).Return(errors.New("transient error")).Once() + s.mockBatchInsertBuilder.On("Exec", s.ctx, s.mockSession).Return(errors.New("transient error")).Once() for _, tx := range s.txs { - err := s.processor.ProcessTransaction(s.ctx, tx) + err := s.processor.ProcessTransaction(s.lcm, tx) s.Assert().NoError(err) } - err := s.processor.Commit(s.ctx) + err := s.processor.Flush(s.ctx, s.mockSession) s.Assert().EqualError(err, "Could not flush transaction participants to db: transient error") } -func (s *ParticipantsProcessorTestSuiteLedger) TestOpeartionBatchAddExecFails() { - s.mockQ.On("CreateAccounts", s.ctx, mock.AnythingOfType("[]string"), maxBatchSize). - Run(func(args mock.Arguments) { - arg := args.Get(1).([]string) - s.Assert().ElementsMatch( - s.addresses, - arg, - ) - }).Return(s.addressToID, nil).Once() - s.mockQ.On("NewTransactionParticipantsBatchInsertBuilder", maxBatchSize). - Return(s.mockBatchInsertBuilder).Once() - s.mockQ.On("NewOperationParticipantBatchInsertBuilder", maxBatchSize). - Return(s.mockOperationsBatchInsertBuilder).Once() - +func (s *ParticipantsProcessorTestSuiteLedger) TestOperationBatchAddExecFails() { s.mockSuccessfulTransactionBatchAdds() s.mockSuccessfulOperationBatchAdds() - s.mockBatchInsertBuilder.On("Exec", s.ctx).Return(nil).Once() - s.mockOperationsBatchInsertBuilder.On("Exec", s.ctx).Return(errors.New("transient error")).Once() + s.mockBatchInsertBuilder.On("Exec", s.ctx, s.mockSession).Return(nil).Once() + s.mockOperationsBatchInsertBuilder.On("Exec", s.ctx, s.mockSession).Return(errors.New("transient error")).Once() for _, tx := range s.txs { - err := s.processor.ProcessTransaction(s.ctx, tx) + err := s.processor.ProcessTransaction(s.lcm, tx) s.Assert().NoError(err) } - err := s.processor.Commit(s.ctx) - s.Assert().EqualError(err, "could not flush operation participants to db: transient error") + err := s.processor.Flush(s.ctx, s.mockSession) + s.Assert().EqualError(err, "Could not flush operation participants to db: transient error") } diff --git a/services/horizon/internal/ingest/processors/signer_processor_test.go b/services/horizon/internal/ingest/processors/signer_processor_test.go index de5c70bddc..5b4d147f15 100644 --- a/services/horizon/internal/ingest/processors/signer_processor_test.go +++ b/services/horizon/internal/ingest/processors/signer_processor_test.go @@ -33,14 +33,14 @@ func (s *AccountsSignerProcessorTestSuiteState) SetupTest() { s.mockBatchInsertBuilder = &history.MockAccountSignersBatchInsertBuilder{} s.mockQ. - On("NewAccountSignersBatchInsertBuilder", maxBatchSize). - Return(s.mockBatchInsertBuilder).Once() + On("NewAccountSignersBatchInsertBuilder"). + Return(s.mockBatchInsertBuilder).Twice() + s.mockBatchInsertBuilder.On("Exec", s.ctx).Return(nil) s.processor = NewSignersProcessor(s.mockQ, false) } func (s *AccountsSignerProcessorTestSuiteState) TearDownTest() { - s.mockBatchInsertBuilder.On("Exec", s.ctx).Return(nil).Once() s.Assert().NoError(s.processor.Commit(s.ctx)) s.mockQ.AssertExpectations(s.T()) @@ -53,7 +53,7 @@ func (s *AccountsSignerProcessorTestSuiteState) TestNoEntries() { func (s *AccountsSignerProcessorTestSuiteState) TestCreatesSigners() { s.mockBatchInsertBuilder. - On("Add", s.ctx, history.AccountSigner{ + On("Add", history.AccountSigner{ Account: "GC3C4AKRBQLHOJ45U4XG35ESVWRDECWO5XLDGYADO6DPR3L7KIDVUMML", Signer: "GC3C4AKRBQLHOJ45U4XG35ESVWRDECWO5XLDGYADO6DPR3L7KIDVUMML", Weight: int32(1), @@ -75,7 +75,7 @@ func (s *AccountsSignerProcessorTestSuiteState) TestCreatesSigners() { s.Assert().NoError(err) s.mockBatchInsertBuilder. - On("Add", s.ctx, history.AccountSigner{ + On("Add", history.AccountSigner{ Account: "GCCCU34WDY2RATQTOOQKY6SZWU6J5DONY42SWGW2CIXGW4LICAGNRZKX", Signer: "GC3C4AKRBQLHOJ45U4XG35ESVWRDECWO5XLDGYADO6DPR3L7KIDVUMML", Weight: int32(10), @@ -105,7 +105,7 @@ func (s *AccountsSignerProcessorTestSuiteState) TestCreatesSigners() { func (s *AccountsSignerProcessorTestSuiteState) TestCreatesSignerWithSponsor() { s.mockBatchInsertBuilder. - On("Add", s.ctx, history.AccountSigner{ + On("Add", history.AccountSigner{ Account: "GCCCU34WDY2RATQTOOQKY6SZWU6J5DONY42SWGW2CIXGW4LICAGNRZKX", Signer: "GC3C4AKRBQLHOJ45U4XG35ESVWRDECWO5XLDGYADO6DPR3L7KIDVUMML", Weight: int32(10), @@ -156,17 +156,20 @@ func TestAccountsSignerProcessorTestSuiteLedger(t *testing.T) { type AccountsSignerProcessorTestSuiteLedger struct { suite.Suite - ctx context.Context - processor *SignersProcessor - mockQ *history.MockQSigners + ctx context.Context + processor *SignersProcessor + mockQ *history.MockQSigners + mockAccountSignersBatchInsertBuilder *history.MockAccountSignersBatchInsertBuilder } func (s *AccountsSignerProcessorTestSuiteLedger) SetupTest() { s.ctx = context.Background() s.mockQ = &history.MockQSigners{} + s.mockAccountSignersBatchInsertBuilder = &history.MockAccountSignersBatchInsertBuilder{} s.mockQ. - On("NewAccountSignersBatchInsertBuilder", maxBatchSize). - Return(&history.MockAccountSignersBatchInsertBuilder{}).Once() + On("NewAccountSignersBatchInsertBuilder"). + Return(s.mockAccountSignersBatchInsertBuilder).Twice() + s.mockAccountSignersBatchInsertBuilder.On("Exec", s.ctx).Return(nil) s.processor = NewSignersProcessor(s.mockQ, true) } @@ -181,16 +184,17 @@ func (s *AccountsSignerProcessorTestSuiteLedger) TestNoTransactions() { } func (s *AccountsSignerProcessorTestSuiteLedger) TestNewAccount() { - s.mockQ. + s.mockAccountSignersBatchInsertBuilder. On( - "CreateAccountSigner", - s.ctx, - "GC3C4AKRBQLHOJ45U4XG35ESVWRDECWO5XLDGYADO6DPR3L7KIDVUMML", - "GC3C4AKRBQLHOJ45U4XG35ESVWRDECWO5XLDGYADO6DPR3L7KIDVUMML", - int32(1), - (*string)(nil), + "Add", + history.AccountSigner{ + "GC3C4AKRBQLHOJ45U4XG35ESVWRDECWO5XLDGYADO6DPR3L7KIDVUMML", + "GC3C4AKRBQLHOJ45U4XG35ESVWRDECWO5XLDGYADO6DPR3L7KIDVUMML", + int32(1), + null.String{}, + }, ). - Return(int64(1), nil).Once() + Return(nil).Once() err := s.processor.ProcessChange(s.ctx, ingest.Change{ Type: xdr.LedgerEntryTypeAccount, @@ -247,27 +251,28 @@ func (s *AccountsSignerProcessorTestSuiteLedger) TestNewSigner() { Return(int64(1), nil).Once() // Create new and old signer - s.mockQ. + s.mockAccountSignersBatchInsertBuilder. On( - "CreateAccountSigner", - s.ctx, - "GC3C4AKRBQLHOJ45U4XG35ESVWRDECWO5XLDGYADO6DPR3L7KIDVUMML", - "GCBBDQLCTNASZJ3MTKAOYEOWRGSHDFAJVI7VPZUOP7KXNHYR3HP2BUKV", - int32(10), - (*string)(nil), + "Add", + history.AccountSigner{ + "GC3C4AKRBQLHOJ45U4XG35ESVWRDECWO5XLDGYADO6DPR3L7KIDVUMML", + "GCBBDQLCTNASZJ3MTKAOYEOWRGSHDFAJVI7VPZUOP7KXNHYR3HP2BUKV", + int32(10), + null.String{}, + }, ). - Return(int64(1), nil).Once() + Return(nil).Once() - s.mockQ. + s.mockAccountSignersBatchInsertBuilder. On( - "CreateAccountSigner", - s.ctx, - "GC3C4AKRBQLHOJ45U4XG35ESVWRDECWO5XLDGYADO6DPR3L7KIDVUMML", - "GCAHY6JSXQFKWKP6R7U5JPXDVNV4DJWOWRFLY3Y6YPBF64QRL4BPFDNS", - int32(15), - (*string)(nil), + "Add", + history.AccountSigner{ + "GC3C4AKRBQLHOJ45U4XG35ESVWRDECWO5XLDGYADO6DPR3L7KIDVUMML", + "GCAHY6JSXQFKWKP6R7U5JPXDVNV4DJWOWRFLY3Y6YPBF64QRL4BPFDNS", + int32(15), + null.StringFromPtr(nil)}, ). - Return(int64(1), nil).Once() + Return(nil).Once() err := s.processor.ProcessChange(s.ctx, ingest.Change{ Type: xdr.LedgerEntryTypeAccount, @@ -329,16 +334,17 @@ func (s *AccountsSignerProcessorTestSuiteLedger) TestSignerRemoved() { Return(int64(1), nil).Once() // Create new signer - s.mockQ. + s.mockAccountSignersBatchInsertBuilder. On( - "CreateAccountSigner", - s.ctx, - "GC3C4AKRBQLHOJ45U4XG35ESVWRDECWO5XLDGYADO6DPR3L7KIDVUMML", - "GCAHY6JSXQFKWKP6R7U5JPXDVNV4DJWOWRFLY3Y6YPBF64QRL4BPFDNS", - int32(15), - (*string)(nil), + "Add", + history.AccountSigner{ + "GC3C4AKRBQLHOJ45U4XG35ESVWRDECWO5XLDGYADO6DPR3L7KIDVUMML", + "GCAHY6JSXQFKWKP6R7U5JPXDVNV4DJWOWRFLY3Y6YPBF64QRL4BPFDNS", + int32(15), + null.String{}, + }, ). - Return(int64(1), nil).Once() + Return(nil).Once() err := s.processor.ProcessChange(s.ctx, ingest.Change{ Type: xdr.LedgerEntryTypeAccount, @@ -402,16 +408,17 @@ func (s *AccountsSignerProcessorTestSuiteLedger) TestSignerPreAuthTxRemovedTxFai Return(int64(1), nil).Once() // Create new signer - s.mockQ. + s.mockAccountSignersBatchInsertBuilder. On( - "CreateAccountSigner", - s.ctx, - "GC3C4AKRBQLHOJ45U4XG35ESVWRDECWO5XLDGYADO6DPR3L7KIDVUMML", - "GCBBDQLCTNASZJ3MTKAOYEOWRGSHDFAJVI7VPZUOP7KXNHYR3HP2BUKV", - int32(10), - (*string)(nil), + "Add", + history.AccountSigner{ + "GC3C4AKRBQLHOJ45U4XG35ESVWRDECWO5XLDGYADO6DPR3L7KIDVUMML", + "GCBBDQLCTNASZJ3MTKAOYEOWRGSHDFAJVI7VPZUOP7KXNHYR3HP2BUKV", + int32(10), + null.String{}, + }, ). - Return(int64(1), nil).Once() + Return(nil).Once() err := s.processor.ProcessChange(s.ctx, ingest.Change{ Type: xdr.LedgerEntryTypeAccount, @@ -479,44 +486,6 @@ func (s *AccountsSignerProcessorTestSuiteLedger) TestRemoveAccount() { s.Assert().NoError(s.processor.Commit(s.ctx)) } -func (s *AccountsSignerProcessorTestSuiteLedger) TestNewAccountNoRowsAffected() { - s.mockQ. - On( - "CreateAccountSigner", - s.ctx, - "GC3C4AKRBQLHOJ45U4XG35ESVWRDECWO5XLDGYADO6DPR3L7KIDVUMML", - "GC3C4AKRBQLHOJ45U4XG35ESVWRDECWO5XLDGYADO6DPR3L7KIDVUMML", - int32(1), - (*string)(nil), - ). - Return(int64(0), nil).Once() - - err := s.processor.ProcessChange(s.ctx, ingest.Change{ - Type: xdr.LedgerEntryTypeAccount, - Pre: nil, - Post: &xdr.LedgerEntry{ - Data: xdr.LedgerEntryData{ - Type: xdr.LedgerEntryTypeAccount, - Account: &xdr.AccountEntry{ - AccountId: xdr.MustAddress("GC3C4AKRBQLHOJ45U4XG35ESVWRDECWO5XLDGYADO6DPR3L7KIDVUMML"), - Thresholds: [4]byte{1, 1, 1, 1}, - }, - }, - }, - }) - s.Assert().NoError(err) - - err = s.processor.Commit(s.ctx) - s.Assert().Error(err) - s.Assert().IsType(ingest.StateError{}, errors.Cause(err)) - s.Assert().EqualError( - err, - "0 rows affected when inserting "+ - "account=GC3C4AKRBQLHOJ45U4XG35ESVWRDECWO5XLDGYADO6DPR3L7KIDVUMML "+ - "signer=GC3C4AKRBQLHOJ45U4XG35ESVWRDECWO5XLDGYADO6DPR3L7KIDVUMML to database", - ) -} - func (s *AccountsSignerProcessorTestSuiteLedger) TestRemoveAccountNoRowsAffected() { s.mockQ. On( @@ -566,27 +535,28 @@ func (s *AccountsSignerProcessorTestSuiteLedger) TestProcessUpgradeChange() { Return(int64(1), nil).Once() // Create new and old (updated) signer - s.mockQ. + s.mockAccountSignersBatchInsertBuilder. On( - "CreateAccountSigner", - s.ctx, - "GC3C4AKRBQLHOJ45U4XG35ESVWRDECWO5XLDGYADO6DPR3L7KIDVUMML", - "GCBBDQLCTNASZJ3MTKAOYEOWRGSHDFAJVI7VPZUOP7KXNHYR3HP2BUKV", - int32(12), - (*string)(nil), + "Add", + history.AccountSigner{ + "GC3C4AKRBQLHOJ45U4XG35ESVWRDECWO5XLDGYADO6DPR3L7KIDVUMML", + "GCBBDQLCTNASZJ3MTKAOYEOWRGSHDFAJVI7VPZUOP7KXNHYR3HP2BUKV", + int32(12), + null.String{}, + }, ). - Return(int64(1), nil).Once() + Return(nil).Once() - s.mockQ. + s.mockAccountSignersBatchInsertBuilder. On( - "CreateAccountSigner", - s.ctx, - "GC3C4AKRBQLHOJ45U4XG35ESVWRDECWO5XLDGYADO6DPR3L7KIDVUMML", - "GCAHY6JSXQFKWKP6R7U5JPXDVNV4DJWOWRFLY3Y6YPBF64QRL4BPFDNS", - int32(15), - (*string)(nil), - ). - Return(int64(1), nil).Once() + "Add", + history.AccountSigner{ + "GC3C4AKRBQLHOJ45U4XG35ESVWRDECWO5XLDGYADO6DPR3L7KIDVUMML", + "GCAHY6JSXQFKWKP6R7U5JPXDVNV4DJWOWRFLY3Y6YPBF64QRL4BPFDNS", + int32(15), + null.String{}, + }, + ).Return(nil).Once() err := s.processor.ProcessChange(s.ctx, ingest.Change{ Type: xdr.LedgerEntryTypeAccount, diff --git a/services/horizon/internal/ingest/processors/signers_processor.go b/services/horizon/internal/ingest/processors/signers_processor.go index d165110b18..b72867522d 100644 --- a/services/horizon/internal/ingest/processors/signers_processor.go +++ b/services/horizon/internal/ingest/processors/signers_processor.go @@ -14,8 +14,8 @@ import ( type SignersProcessor struct { signersQ history.QSigners - cache *ingest.ChangeCompactor - batch history.AccountSignersBatchInsertBuilder + cache *ingest.ChangeCompactor + batchInsertBuilder history.AccountSignersBatchInsertBuilder // insertOnlyMode is a mode in which we don't use ledger cache and we just // add signers to a batch, then we Exec all signers in one insert query. // This is done to make history buckets processing faster (batch inserting). @@ -31,7 +31,7 @@ func NewSignersProcessor( } func (p *SignersProcessor) reset() { - p.batch = p.signersQ.NewAccountSignersBatchInsertBuilder(maxBatchSize) + p.batchInsertBuilder = p.signersQ.NewAccountSignersBatchInsertBuilder() p.cache = ingest.NewChangeCompactor() } @@ -51,107 +51,95 @@ func (p *SignersProcessor) ProcessChange(ctx context.Context, change ingest.Chan if err != nil { return errors.Wrap(err, "error in Commit") } - p.reset() } return nil } - if !(change.Pre == nil && change.Post != nil) { - return errors.New("AssetStatsProSignersProcessorcessor is in insert only mode") - } - - accountEntry := change.Post.Data.MustAccount() - account := accountEntry.AccountId.Address() - - sponsors := accountEntry.SponsorPerSigner() - for signer, weight := range accountEntry.SignerSummary() { - var sponsor null.String - if sponsorDesc, isSponsored := sponsors[signer]; isSponsored { - sponsor = null.StringFrom(sponsorDesc.Address()) - } - - err := p.batch.Add(ctx, history.AccountSigner{ - Account: account, - Signer: signer, - Weight: weight, - Sponsor: sponsor, - }) - if err != nil { - return errors.Wrap(err, "Error adding row to accountSignerBatch") + if change.Pre == nil && change.Post != nil { + postAccountEntry := change.Post.Data.MustAccount() + if err := p.addAccountSigners(postAccountEntry); err != nil { + return err } + } else { + return errors.New("SignersProcessor is in insert only mode") } return nil } func (p *SignersProcessor) Commit(ctx context.Context) error { - if !p.useLedgerEntryCache { - return p.batch.Exec(ctx) - } + defer p.reset() - changes := p.cache.GetChanges() - for _, change := range changes { - if !change.AccountSignersChanged() { - continue - } + if p.useLedgerEntryCache { + changes := p.cache.GetChanges() + for _, change := range changes { + if !change.AccountSignersChanged() { + continue + } - // The code below removes all Pre signers adds Post signers but - // can be improved by finding a diff (check performance first). - if change.Pre != nil { - preAccountEntry := change.Pre.Data.MustAccount() - for signer := range preAccountEntry.SignerSummary() { - rowsAffected, err := p.signersQ.RemoveAccountSigner(ctx, preAccountEntry.AccountId.Address(), signer) - if err != nil { - return errors.Wrap(err, "Error removing a signer") + // The code below removes all Pre signers adds Post signers but + // can be improved by finding a diff (check performance first). + if change.Pre != nil { + if err := p.removeAccountSigners(ctx, change.Pre.Data.MustAccount()); err != nil { + return err } + } - if rowsAffected != 1 { - return ingest.NewStateError(errors.Errorf( - "Expected account=%s signer=%s in database but not found when removing (rows affected = %d)", - preAccountEntry.AccountId.Address(), - signer, - rowsAffected, - )) + if change.Post != nil { + if err := p.addAccountSigners(change.Post.Data.MustAccount()); err != nil { + return err } } } + } - if change.Post != nil { - postAccountEntry := change.Post.Data.MustAccount() - sponsorsPerSigner := postAccountEntry.SponsorPerSigner() - for signer, weight := range postAccountEntry.SignerSummary() { - - // Ignore master key - var sponsor *string - if signer != postAccountEntry.AccountId.Address() { - if s, ok := sponsorsPerSigner[signer]; ok { - a := s.Address() - sponsor = &a - } - } + err := p.batchInsertBuilder.Exec(ctx) + if err != nil { + return errors.Wrap(err, "error executing AccountSignersBatchInsertBuilder") + } - rowsAffected, err := p.signersQ.CreateAccountSigner(ctx, - postAccountEntry.AccountId.Address(), - signer, - weight, - sponsor, - ) - if err != nil { - return errors.Wrapf(err, "Error inserting a signer (%s)", signer) - } + return nil +} - if rowsAffected != 1 { - return ingest.NewStateError(errors.Errorf( - "%d rows affected when inserting account=%s signer=%s to database", - rowsAffected, - postAccountEntry.AccountId.Address(), - signer, - )) - } - } +func (p *SignersProcessor) removeAccountSigners(ctx context.Context, accountEntry xdr.AccountEntry) error { + for signer := range accountEntry.SignerSummary() { + rowsAffected, err := p.signersQ.RemoveAccountSigner(ctx, accountEntry.AccountId.Address(), signer) + if err != nil { + return errors.Wrap(err, "Error removing a signer") + } + + if rowsAffected != 1 { + return ingest.NewStateError(errors.Errorf( + "Expected account=%s signer=%s in database but not found when removing (rows affected = %d)", + accountEntry.AccountId.Address(), + signer, + rowsAffected, + )) } } + return nil +} +func (p *SignersProcessor) addAccountSigners(accountEntry xdr.AccountEntry) error { + sponsorsPerSigner := accountEntry.SponsorPerSigner() + for signer, weight := range accountEntry.SignerSummary() { + // Ignore master key + var sponsor null.String + if signer != accountEntry.AccountId.Address() { + if sponsorDesc, isSponsored := sponsorsPerSigner[signer]; isSponsored { + sponsor = null.StringFrom(sponsorDesc.Address()) + } + } + + if err := p.batchInsertBuilder.Add(history.AccountSigner{ + Account: accountEntry.AccountId.Address(), + Signer: signer, + Weight: weight, + Sponsor: sponsor, + }); err != nil { + return errors.Wrapf(err, "Error adding signer (%s) to AccountSignersBatchInsertBuilder", signer) + } + } return nil } diff --git a/services/horizon/internal/ingest/processors/stats_ledger_transaction_processor.go b/services/horizon/internal/ingest/processors/stats_ledger_transaction_processor.go index 4853152199..83188e02f8 100644 --- a/services/horizon/internal/ingest/processors/stats_ledger_transaction_processor.go +++ b/services/horizon/internal/ingest/processors/stats_ledger_transaction_processor.go @@ -5,6 +5,7 @@ import ( "fmt" "github.com/stellar/go/ingest" + "github.com/stellar/go/support/db" "github.com/stellar/go/xdr" ) @@ -14,6 +15,10 @@ type StatsLedgerTransactionProcessor struct { results StatsLedgerTransactionProcessorResults } +func NewStatsLedgerTransactionProcessor() *StatsLedgerTransactionProcessor { + return &StatsLedgerTransactionProcessor{} +} + // StatsLedgerTransactionProcessorResults contains results after running StatsLedgerTransactionProcessor. type StatsLedgerTransactionProcessorResults struct { Transactions int64 @@ -49,9 +54,16 @@ type StatsLedgerTransactionProcessorResults struct { OperationsSetTrustLineFlags int64 OperationsLiquidityPoolDeposit int64 OperationsLiquidityPoolWithdraw int64 + OperationsInvokeHostFunction int64 + OperationsExtendFootprintTtl int64 + OperationsRestoreFootprint int64 } -func (p *StatsLedgerTransactionProcessor) ProcessTransaction(ctx context.Context, transaction ingest.LedgerTransaction) error { +func (p *StatsLedgerTransactionProcessor) Flush(ctx context.Context, session db.SessionInterface) error { + return nil +} + +func (p *StatsLedgerTransactionProcessor) ProcessTransaction(lcm xdr.LedgerCloseMeta, transaction ingest.LedgerTransaction) error { p.results.Transactions++ ops := int64(len(transaction.Envelope.Operations())) p.results.Operations += ops @@ -115,8 +127,14 @@ func (p *StatsLedgerTransactionProcessor) ProcessTransaction(ctx context.Context p.results.OperationsLiquidityPoolDeposit++ case xdr.OperationTypeLiquidityPoolWithdraw: p.results.OperationsLiquidityPoolWithdraw++ + case xdr.OperationTypeInvokeHostFunction: + p.results.OperationsInvokeHostFunction++ + case xdr.OperationTypeExtendFootprintTtl: + p.results.OperationsExtendFootprintTtl++ + case xdr.OperationTypeRestoreFootprint: + p.results.OperationsRestoreFootprint++ default: - panic(fmt.Sprintf("Unkown operation type: %d", op.Body.Type)) + panic(fmt.Sprintf("Unknown operation type: %d", op.Body.Type)) } } @@ -161,8 +179,13 @@ func (stats *StatsLedgerTransactionProcessorResults) Map() map[string]interface{ "stats_operations_clawback_claimable_balance": stats.OperationsClawbackClaimableBalance, "stats_operations_liquidity_pool_deposit": stats.OperationsLiquidityPoolDeposit, "stats_operations_liquidity_pool_withdraw": stats.OperationsLiquidityPoolWithdraw, + "stats_operations_invoke_host_function": stats.OperationsInvokeHostFunction, } } +func (p *StatsLedgerTransactionProcessor) ResetStats() { + p.results = StatsLedgerTransactionProcessorResults{} +} + // Ensure the StatsChangeProcessor conforms to the ChangeProcessor interface. var _ LedgerTransactionProcessor = (*StatsLedgerTransactionProcessor)(nil) diff --git a/services/horizon/internal/ingest/processors/stats_ledger_transaction_processor_test.go b/services/horizon/internal/ingest/processors/stats_ledger_transaction_processor_test.go index f2bc2a5040..1f2f8c370e 100644 --- a/services/horizon/internal/ingest/processors/stats_ledger_transaction_processor_test.go +++ b/services/horizon/internal/ingest/processors/stats_ledger_transaction_processor_test.go @@ -1,7 +1,6 @@ package processors import ( - "context" "testing" "github.com/stretchr/testify/assert" @@ -23,12 +22,14 @@ func TestStatsLedgerTransactionProcessoAllOpTypesCovered(t *testing.T) { }, }, } + lcm := xdr.LedgerCloseMeta{} + for typ, s := range xdr.OperationTypeToStringMap { tx := txTemplate txTemplate.Envelope.V1.Tx.Operations[0].Body.Type = xdr.OperationType(typ) f := func() { var p StatsLedgerTransactionProcessor - p.ProcessTransaction(context.Background(), tx) + p.ProcessTransaction(lcm, tx) } assert.NotPanics(t, f, s) } @@ -38,16 +39,47 @@ func TestStatsLedgerTransactionProcessoAllOpTypesCovered(t *testing.T) { txTemplate.Envelope.V1.Tx.Operations[0].Body.Type = 20000 f := func() { var p StatsLedgerTransactionProcessor - p.ProcessTransaction(context.Background(), tx) + p.ProcessTransaction(lcm, tx) } assert.Panics(t, f) } +func TestStatsLedgerTransactionProcessorReset(t *testing.T) { + processor := NewStatsLedgerTransactionProcessor() + lcm := xdr.LedgerCloseMeta{} + + assert.NoError(t, processor.ProcessTransaction(lcm, ingest.LedgerTransaction{ + Result: xdr.TransactionResultPair{ + Result: xdr.TransactionResult{ + Result: xdr.TransactionResultResult{ + Code: xdr.TransactionResultCodeTxSuccess, + }, + }, + }, + Envelope: xdr.TransactionEnvelope{ + Type: xdr.EnvelopeTypeEnvelopeTypeTx, + V1: &xdr.TransactionV1Envelope{ + Tx: xdr.Transaction{ + Operations: []xdr.Operation{ + {Body: xdr.OperationBody{Type: xdr.OperationTypeCreateAccount}}, + {Body: xdr.OperationBody{Type: xdr.OperationTypePayment}}, + }, + }, + }, + }, + })) + + assert.Equal(t, processor.GetResults().Operations, int64(2)) + processor.ResetStats() + assert.Equal(t, processor.GetResults().Operations, int64(0)) +} + func TestStatsLedgerTransactionProcessor(t *testing.T) { - processor := &StatsLedgerTransactionProcessor{} + processor := NewStatsLedgerTransactionProcessor() + lcm := xdr.LedgerCloseMeta{} // Successful - assert.NoError(t, processor.ProcessTransaction(context.Background(), ingest.LedgerTransaction{ + assert.NoError(t, processor.ProcessTransaction(lcm, ingest.LedgerTransaction{ Result: xdr.TransactionResultPair{ Result: xdr.TransactionResult{ Result: xdr.TransactionResultResult{ @@ -88,7 +120,7 @@ func TestStatsLedgerTransactionProcessor(t *testing.T) { })) // Failed - assert.NoError(t, processor.ProcessTransaction(context.Background(), ingest.LedgerTransaction{ + assert.NoError(t, processor.ProcessTransaction(lcm, ingest.LedgerTransaction{ Result: xdr.TransactionResultPair{ Result: xdr.TransactionResult{ Result: xdr.TransactionResultResult{ diff --git a/services/horizon/internal/ingest/processors/trades_processor.go b/services/horizon/internal/ingest/processors/trades_processor.go index 2a95a994c7..66c6aeb8d3 100644 --- a/services/horizon/internal/ingest/processors/trades_processor.go +++ b/services/horizon/internal/ingest/processors/trades_processor.go @@ -11,6 +11,7 @@ import ( "github.com/stellar/go/exp/orderbook" "github.com/stellar/go/ingest" "github.com/stellar/go/services/horizon/internal/db2/history" + "github.com/stellar/go/support/db" "github.com/stellar/go/support/errors" "github.com/stellar/go/toid" "github.com/stellar/go/xdr" @@ -18,16 +19,25 @@ import ( // TradeProcessor operations processor type TradeProcessor struct { - tradesQ history.QTrades - ledger xdr.LedgerHeaderHistoryEntry - trades []ingestTrade - stats TradeStats + accountLoader *history.AccountLoader + lpLoader *history.LiquidityPoolLoader + assetLoader *history.AssetLoader + batch history.TradeBatchInsertBuilder + trades []ingestTrade + stats TradeStats } -func NewTradeProcessor(tradesQ history.QTrades, ledger xdr.LedgerHeaderHistoryEntry) *TradeProcessor { +func NewTradeProcessor( + accountLoader *history.AccountLoader, + lpLoader *history.LiquidityPoolLoader, + assetLoader *history.AssetLoader, + batch history.TradeBatchInsertBuilder, +) *TradeProcessor { return &TradeProcessor{ - tradesQ: tradesQ, - ledger: ledger, + accountLoader: accountLoader, + lpLoader: lpLoader, + assetLoader: assetLoader, + batch: batch, } } @@ -38,6 +48,7 @@ type TradeStats struct { func (p *TradeProcessor) GetStats() TradeStats { return p.stats } + func (stats *TradeStats) Map() map[string]interface{} { return map[string]interface{}{ "stats_count": stats.count, @@ -45,79 +56,75 @@ func (stats *TradeStats) Map() map[string]interface{} { } // ProcessTransaction process the given transaction -func (p *TradeProcessor) ProcessTransaction(ctx context.Context, transaction ingest.LedgerTransaction) (err error) { +func (p *TradeProcessor) ProcessTransaction(lcm xdr.LedgerCloseMeta, transaction ingest.LedgerTransaction) (err error) { if !transaction.Result.Successful() { return nil } - trades, err := p.extractTrades(p.ledger, transaction) + trades, err := p.extractTrades(lcm.LedgerHeaderHistoryEntry(), transaction) if err != nil { return err } + for _, trade := range trades { + if trade.buyerAccount != "" { + p.accountLoader.GetFuture(trade.buyerAccount) + } + if trade.sellerAccount != "" { + p.accountLoader.GetFuture(trade.sellerAccount) + } + if trade.liquidityPoolID != "" { + p.lpLoader.GetFuture(trade.liquidityPoolID) + } + p.assetLoader.GetFuture(history.AssetKeyFromXDR(trade.boughtAsset)) + p.assetLoader.GetFuture(history.AssetKeyFromXDR(trade.soldAsset)) + } + p.trades = append(p.trades, trades...) p.stats.count += int64(len(trades)) return nil } -func (p *TradeProcessor) Commit(ctx context.Context) error { +func (p *TradeProcessor) Flush(ctx context.Context, session db.SessionInterface) error { if len(p.trades) == 0 { return nil } - batch := p.tradesQ.NewTradeBatchInsertBuilder(maxBatchSize) - var poolIDs, accounts []string - var assets []xdr.Asset for _, trade := range p.trades { - if trade.buyerAccount != "" { - accounts = append(accounts, trade.buyerAccount) - } + row := trade.row if trade.sellerAccount != "" { - accounts = append(accounts, trade.sellerAccount) + val, err := p.accountLoader.GetNow(trade.sellerAccount) + if err != nil { + return err + } + row.BaseAccountID = null.IntFrom(val) + } + if trade.buyerAccount != "" { + val, err := p.accountLoader.GetNow(trade.buyerAccount) + if err != nil { + return err + } + row.CounterAccountID = null.IntFrom(val) } if trade.liquidityPoolID != "" { - poolIDs = append(poolIDs, trade.liquidityPoolID) + val, err := p.lpLoader.GetNow(trade.liquidityPoolID) + if err != nil { + return err + } + row.BaseLiquidityPoolID = null.IntFrom(val) } - assets = append(assets, trade.boughtAsset) - assets = append(assets, trade.soldAsset) - } - accountSet, err := p.tradesQ.CreateAccounts(ctx, accounts, maxBatchSize) - if err != nil { - return errors.Wrap(err, "Error creating account ids") - } - - var assetMap map[string]history.Asset - assetMap, err = p.tradesQ.CreateAssets(ctx, assets, maxBatchSize) - if err != nil { - return errors.Wrap(err, "Error creating asset ids") - } - - var poolMap map[string]int64 - poolMap, err = p.tradesQ.CreateHistoryLiquidityPools(ctx, poolIDs, maxBatchSize) - if err != nil { - return errors.Wrap(err, "Error creating pool ids") - } - - for _, trade := range p.trades { - row := trade.row - if id, ok := accountSet[trade.sellerAccount]; ok { - row.BaseAccountID = null.IntFrom(id) - } else if len(trade.sellerAccount) > 0 { - return errors.Errorf("Could not find history account id for %s", trade.sellerAccount) - } - if id, ok := accountSet[trade.buyerAccount]; ok { - row.CounterAccountID = null.IntFrom(id) - } else if len(trade.buyerAccount) > 0 { - return errors.Errorf("Could not find history account id for %s", trade.buyerAccount) + val, err := p.assetLoader.GetNow(history.AssetKeyFromXDR(trade.soldAsset)) + if err != nil { + return err } - if id, ok := poolMap[trade.liquidityPoolID]; ok { - row.BaseLiquidityPoolID = null.IntFrom(id) - } else if len(trade.liquidityPoolID) > 0 { - return errors.Errorf("Could not find history liquidity pool id for %s", trade.liquidityPoolID) + row.BaseAssetID = val + + val, err = p.assetLoader.GetNow(history.AssetKeyFromXDR(trade.boughtAsset)) + if err != nil { + return err } - row.BaseAssetID = assetMap[trade.soldAsset.String()].ID - row.CounterAssetID = assetMap[trade.boughtAsset.String()].ID + row.CounterAssetID = val if row.BaseAssetID > row.CounterAssetID { row.BaseIsSeller = false @@ -133,12 +140,12 @@ func (p *TradeProcessor) Commit(ctx context.Context) error { } } - if err = batch.Add(ctx, row); err != nil { + if err := p.batch.Add(row); err != nil { return errors.Wrap(err, "Error adding trade to batch") } } - if err = batch.Exec(ctx); err != nil { + if err := p.batch.Exec(ctx, session); err != nil { return errors.Wrap(err, "Error flushing operation batch") } return nil @@ -175,8 +182,14 @@ func (p *TradeProcessor) findOperationChange(tx ingest.LedgerTransaction, opidx var change ingest.Change for i := len(changes) - 1; i >= 0; i-- { change = changes[i] - if change.Pre != nil && key.Equals(change.Pre.LedgerKey()) { - return change, nil + if change.Pre != nil { + preKey, err := change.Pre.LedgerKey() + if err != nil { + return ingest.Change{}, errors.Wrap(err, "could not determine ledger key for change") + } + if key.Equals(preKey) { + return change, nil + } } } return ingest.Change{}, errors.Errorf("could not find operation for key %v", key) @@ -245,8 +258,8 @@ func (p *TradeProcessor) roundingSlippage( ) if !ok { // Temporary workaround for https://github.com/stellar/go/issues/4203 - // Give strict receives that would underflow here, maximum slippage so - // they get excluded. + // Given strict receives that would underflow here, set maximum + // slippage so they get excluded. roundingSlippageBips = xdr.Int64(math.MaxInt64) } return null.IntFrom(int64(roundingSlippageBips)), nil @@ -260,7 +273,10 @@ func (p *TradeProcessor) roundingSlippage( true, ) if !ok { - return null.Int{}, errors.New("Liquidity pool overflows from this exchange") + // Temporary workaround for https://github.com/stellar/go/issues/4203 + // Given strict sends that would overflow here, set maximum slippage + // so they get excluded. + roundingSlippageBips = xdr.Int64(math.MaxInt64) } return null.IntFrom(int64(roundingSlippageBips)), nil default: @@ -445,3 +461,7 @@ func (p *TradeProcessor) extractTrades( return result, nil } + +func (p *TradeProcessor) ResetStats() { + p.stats = TradeStats{} +} diff --git a/services/horizon/internal/ingest/processors/trades_processor_test.go b/services/horizon/internal/ingest/processors/trades_processor_test.go index e11fdf370f..8a7733f4d1 100644 --- a/services/horizon/internal/ingest/processors/trades_processor_test.go +++ b/services/horizon/internal/ingest/processors/trades_processor_test.go @@ -10,18 +10,23 @@ import ( "github.com/guregu/null" + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/suite" + "github.com/stellar/go/ingest" "github.com/stellar/go/services/horizon/internal/db2/history" + "github.com/stellar/go/support/db" "github.com/stellar/go/toid" "github.com/stellar/go/xdr" - "github.com/stretchr/testify/mock" - "github.com/stretchr/testify/suite" ) type TradeProcessorTestSuiteLedger struct { suite.Suite processor *TradeProcessor - mockQ *history.MockQTrades + mockSession *db.MockSession + accountLoader history.AccountLoaderStub + lpLoader history.LiquidityPoolLoaderStub + assetLoader history.AssetLoaderStub mockBatchInsertBuilder *history.MockTradeBatchInsertBuilder unmuxedSourceAccount xdr.AccountId @@ -43,9 +48,10 @@ type TradeProcessorTestSuiteLedger struct { lpToID map[xdr.PoolId]int64 unmuxedAccountToID map[string]int64 - assetToID map[string]history.Asset + assetToID map[history.AssetKey]history.Asset txs []ingest.LedgerTransaction + lcm xdr.LedgerCloseMeta } func TestTradeProcessorTestSuiteLedger(t *testing.T) { @@ -53,7 +59,6 @@ func TestTradeProcessorTestSuiteLedger(t *testing.T) { } func (s *TradeProcessorTestSuiteLedger) SetupTest() { - s.mockQ = &history.MockQTrades{} s.mockBatchInsertBuilder = &history.MockTradeBatchInsertBuilder{} s.unmuxedSourceAccount = xdr.MustAddress("GAUJETIZVEP2NRYLUESJ3LS66NVCEGMON4UDCBCSBEVPIID773P2W6AY") @@ -163,7 +168,7 @@ func (s *TradeProcessorTestSuiteLedger) SetupTest() { s.unmuxedSourceAccount.Address(): 1000, s.unmuxedOpSourceAccount.Address(): 1001, } - s.assetToID = map[string]history.Asset{} + s.assetToID = map[history.AssetKey]history.Asset{} s.allTrades = []xdr.ClaimAtom{ s.strictReceiveTrade, s.strictSendTrade, @@ -188,42 +193,51 @@ func (s *TradeProcessorTestSuiteLedger) SetupTest() { s.sellPrices = append(s.sellPrices, xdr.Price{N: xdr.Int32(trade.AmountBought()), D: xdr.Int32(trade.AmountSold())}) } if i%2 == 0 { - s.assetToID[trade.AssetSold().String()] = history.Asset{ID: int64(10000 + i)} - s.assetToID[trade.AssetBought().String()] = history.Asset{ID: int64(100 + i)} + s.assetToID[history.AssetKeyFromXDR(trade.AssetSold())] = history.Asset{ID: int64(10000 + i)} + s.assetToID[history.AssetKeyFromXDR(trade.AssetBought())] = history.Asset{ID: int64(100 + i)} } else { - s.assetToID[trade.AssetSold().String()] = history.Asset{ID: int64(100 + i)} - s.assetToID[trade.AssetBought().String()] = history.Asset{ID: int64(10000 + i)} + s.assetToID[history.AssetKeyFromXDR(trade.AssetSold())] = history.Asset{ID: int64(100 + i)} + s.assetToID[history.AssetKeyFromXDR(trade.AssetBought())] = history.Asset{ID: int64(10000 + i)} } s.assets = append(s.assets, trade.AssetSold(), trade.AssetBought()) } - s.processor = NewTradeProcessor( - s.mockQ, - xdr.LedgerHeaderHistoryEntry{ - Header: xdr.LedgerHeader{ - LedgerSeq: 100, + s.lcm = xdr.LedgerCloseMeta{ + V0: &xdr.LedgerCloseMetaV0{ + LedgerHeader: xdr.LedgerHeaderHistoryEntry{ + Header: xdr.LedgerHeader{ + LedgerSeq: xdr.Uint32(100), + }, }, }, + } + + s.accountLoader = history.NewAccountLoaderStub() + s.assetLoader = history.NewAssetLoaderStub() + s.lpLoader = history.NewLiquidityPoolLoaderStub() + s.processor = NewTradeProcessor( + s.accountLoader.Loader, + s.lpLoader.Loader, + s.assetLoader.Loader, + s.mockBatchInsertBuilder, ) } func (s *TradeProcessorTestSuiteLedger) TearDownTest() { - s.mockQ.AssertExpectations(s.T()) s.mockBatchInsertBuilder.AssertExpectations(s.T()) } func (s *TradeProcessorTestSuiteLedger) TestIgnoreFailedTransactions() { ctx := context.Background() - err := s.processor.ProcessTransaction(ctx, createTransaction(false, 1)) + err := s.processor.ProcessTransaction(s.lcm, createTransaction(false, 1)) s.Assert().NoError(err) - err = s.processor.Commit(ctx) + err = s.processor.Flush(ctx, s.mockSession) s.Assert().NoError(err) } -func (s *TradeProcessorTestSuiteLedger) mockReadTradeTransactions( - ledger xdr.LedgerHeaderHistoryEntry, -) []history.InsertTrade { +func (s *TradeProcessorTestSuiteLedger) mockReadTradeTransactions() []history.InsertTrade { + ledger := s.lcm.LedgerHeaderHistoryEntry() closeTime := time.Unix(int64(ledger.Header.ScpValue.CloseTime), 0).UTC() inserts := []history.InsertTrade{ { @@ -232,11 +246,11 @@ func (s *TradeProcessorTestSuiteLedger) mockReadTradeTransactions( LedgerCloseTime: closeTime, BaseAmount: int64(s.strictReceiveTrade.AmountBought()), BaseAccountID: null.IntFrom(s.unmuxedAccountToID[s.unmuxedOpSourceAccount.Address()]), - BaseAssetID: s.assetToID[s.strictReceiveTrade.AssetBought().String()].ID, + BaseAssetID: s.assetToID[history.AssetKeyFromXDR(s.strictReceiveTrade.AssetBought())].ID, BaseOfferID: null.IntFrom(EncodeOfferId(uint64(toid.New(int32(ledger.Header.LedgerSeq), 1, 2).ToInt64()), TOIDType)), CounterAmount: int64(s.strictReceiveTrade.AmountSold()), CounterAccountID: null.IntFrom(s.unmuxedAccountToID[s.strictReceiveTrade.SellerId().Address()]), - CounterAssetID: s.assetToID[s.strictReceiveTrade.AssetSold().String()].ID, + CounterAssetID: s.assetToID[history.AssetKeyFromXDR(s.strictReceiveTrade.AssetSold())].ID, CounterOfferID: null.IntFrom(int64(s.strictReceiveTrade.OfferId())), BaseIsSeller: false, BaseIsExact: null.BoolFrom(false), @@ -250,11 +264,11 @@ func (s *TradeProcessorTestSuiteLedger) mockReadTradeTransactions( LedgerCloseTime: closeTime, CounterAmount: int64(s.strictSendTrade.AmountBought()), CounterAccountID: null.IntFrom(s.unmuxedAccountToID[s.unmuxedOpSourceAccount.Address()]), - CounterAssetID: s.assetToID[s.strictSendTrade.AssetBought().String()].ID, + CounterAssetID: s.assetToID[history.AssetKeyFromXDR(s.strictSendTrade.AssetBought())].ID, CounterOfferID: null.IntFrom(EncodeOfferId(uint64(toid.New(int32(ledger.Header.LedgerSeq), 1, 3).ToInt64()), TOIDType)), BaseAmount: int64(s.strictSendTrade.AmountSold()), BaseAccountID: null.IntFrom(s.unmuxedAccountToID[s.strictSendTrade.SellerId().Address()]), - BaseAssetID: s.assetToID[s.strictSendTrade.AssetSold().String()].ID, + BaseAssetID: s.assetToID[history.AssetKeyFromXDR(s.strictSendTrade.AssetSold())].ID, BaseIsSeller: true, BaseIsExact: null.BoolFrom(false), BaseOfferID: null.IntFrom(int64(s.strictSendTrade.OfferId())), @@ -269,10 +283,10 @@ func (s *TradeProcessorTestSuiteLedger) mockReadTradeTransactions( BaseOfferID: null.IntFrom(879136), BaseAmount: int64(s.buyOfferTrade.AmountBought()), BaseAccountID: null.IntFrom(s.unmuxedAccountToID[s.unmuxedOpSourceAccount.Address()]), - BaseAssetID: s.assetToID[s.buyOfferTrade.AssetBought().String()].ID, + BaseAssetID: s.assetToID[history.AssetKeyFromXDR(s.buyOfferTrade.AssetBought())].ID, CounterAmount: int64(s.buyOfferTrade.AmountSold()), CounterAccountID: null.IntFrom(s.unmuxedAccountToID[s.buyOfferTrade.SellerId().Address()]), - CounterAssetID: s.assetToID[s.buyOfferTrade.AssetSold().String()].ID, + CounterAssetID: s.assetToID[history.AssetKeyFromXDR(s.buyOfferTrade.AssetSold())].ID, BaseIsSeller: false, CounterOfferID: null.IntFrom(int64(s.buyOfferTrade.OfferId())), PriceN: int64(s.sellPrices[2].D), @@ -284,12 +298,12 @@ func (s *TradeProcessorTestSuiteLedger) mockReadTradeTransactions( Order: 2, LedgerCloseTime: closeTime, CounterAmount: int64(s.sellOfferTrade.AmountBought()), - CounterAssetID: s.assetToID[s.sellOfferTrade.AssetBought().String()].ID, + CounterAssetID: s.assetToID[history.AssetKeyFromXDR(s.sellOfferTrade.AssetBought())].ID, CounterAccountID: null.IntFrom(s.unmuxedAccountToID[s.unmuxedOpSourceAccount.Address()]), CounterOfferID: null.IntFrom(EncodeOfferId(uint64(toid.New(int32(ledger.Header.LedgerSeq), 1, 5).ToInt64()), TOIDType)), BaseAmount: int64(s.sellOfferTrade.AmountSold()), BaseAccountID: null.IntFrom(s.unmuxedAccountToID[s.sellOfferTrade.SellerId().Address()]), - BaseAssetID: s.assetToID[s.sellOfferTrade.AssetSold().String()].ID, + BaseAssetID: s.assetToID[history.AssetKeyFromXDR(s.sellOfferTrade.AssetSold())].ID, BaseIsSeller: true, BaseOfferID: null.IntFrom(int64(s.sellOfferTrade.OfferId())), PriceN: int64(s.sellPrices[3].N), @@ -301,12 +315,12 @@ func (s *TradeProcessorTestSuiteLedger) mockReadTradeTransactions( Order: 0, LedgerCloseTime: closeTime, BaseAmount: int64(s.passiveSellOfferTrade.AmountBought()), - BaseAssetID: s.assetToID[s.passiveSellOfferTrade.AssetBought().String()].ID, + BaseAssetID: s.assetToID[history.AssetKeyFromXDR(s.passiveSellOfferTrade.AssetBought())].ID, BaseAccountID: null.IntFrom(s.unmuxedAccountToID[s.unmuxedSourceAccount.Address()]), BaseOfferID: null.IntFrom(EncodeOfferId(uint64(toid.New(int32(ledger.Header.LedgerSeq), 1, 6).ToInt64()), TOIDType)), CounterAmount: int64(s.passiveSellOfferTrade.AmountSold()), CounterAccountID: null.IntFrom(s.unmuxedAccountToID[s.passiveSellOfferTrade.SellerId().Address()]), - CounterAssetID: s.assetToID[s.passiveSellOfferTrade.AssetSold().String()].ID, + CounterAssetID: s.assetToID[history.AssetKeyFromXDR(s.passiveSellOfferTrade.AssetSold())].ID, BaseIsSeller: false, CounterOfferID: null.IntFrom(int64(s.passiveSellOfferTrade.OfferId())), PriceN: int64(s.sellPrices[4].D), @@ -320,12 +334,12 @@ func (s *TradeProcessorTestSuiteLedger) mockReadTradeTransactions( LedgerCloseTime: closeTime, CounterAmount: int64(s.otherPassiveSellOfferTrade.AmountBought()), - CounterAssetID: s.assetToID[s.otherPassiveSellOfferTrade.AssetBought().String()].ID, + CounterAssetID: s.assetToID[history.AssetKeyFromXDR(s.otherPassiveSellOfferTrade.AssetBought())].ID, CounterAccountID: null.IntFrom(s.unmuxedAccountToID[s.unmuxedOpSourceAccount.Address()]), CounterOfferID: null.IntFrom(EncodeOfferId(uint64(toid.New(int32(ledger.Header.LedgerSeq), 1, 7).ToInt64()), TOIDType)), BaseAmount: int64(s.otherPassiveSellOfferTrade.AmountSold()), BaseAccountID: null.IntFrom(s.unmuxedAccountToID[s.otherPassiveSellOfferTrade.SellerId().Address()]), - BaseAssetID: s.assetToID[s.otherPassiveSellOfferTrade.AssetSold().String()].ID, + BaseAssetID: s.assetToID[history.AssetKeyFromXDR(s.otherPassiveSellOfferTrade.AssetSold())].ID, BaseIsSeller: true, BaseOfferID: null.IntFrom(int64(s.otherPassiveSellOfferTrade.OfferId())), PriceN: int64(s.sellPrices[5].N), @@ -337,12 +351,12 @@ func (s *TradeProcessorTestSuiteLedger) mockReadTradeTransactions( Order: 1, LedgerCloseTime: closeTime, BaseAmount: int64(s.strictReceiveTradeLP.AmountBought()), - BaseAssetID: s.assetToID[s.strictReceiveTradeLP.AssetBought().String()].ID, + BaseAssetID: s.assetToID[history.AssetKeyFromXDR(s.strictReceiveTradeLP.AssetBought())].ID, BaseAccountID: null.IntFrom(s.unmuxedAccountToID[s.unmuxedOpSourceAccount.Address()]), BaseOfferID: null.IntFrom(EncodeOfferId(uint64(toid.New(int32(ledger.Header.LedgerSeq), 1, 8).ToInt64()), TOIDType)), CounterAmount: int64(s.strictReceiveTradeLP.AmountSold()), CounterLiquidityPoolID: null.IntFrom(s.lpToID[s.strictReceiveTradeLP.MustLiquidityPool().LiquidityPoolId]), - CounterAssetID: s.assetToID[s.strictReceiveTradeLP.AssetSold().String()].ID, + CounterAssetID: s.assetToID[history.AssetKeyFromXDR(s.strictReceiveTradeLP.AssetSold())].ID, BaseIsSeller: false, BaseIsExact: null.BoolFrom(false), LiquidityPoolFee: null.IntFrom(int64(xdr.LiquidityPoolFeeV18)), @@ -356,12 +370,12 @@ func (s *TradeProcessorTestSuiteLedger) mockReadTradeTransactions( Order: 0, LedgerCloseTime: closeTime, CounterAmount: int64(s.strictSendTradeLP.AmountBought()), - CounterAssetID: s.assetToID[s.strictSendTradeLP.AssetBought().String()].ID, + CounterAssetID: s.assetToID[history.AssetKeyFromXDR(s.strictSendTradeLP.AssetBought())].ID, CounterAccountID: null.IntFrom(s.unmuxedAccountToID[s.unmuxedOpSourceAccount.Address()]), CounterOfferID: null.IntFrom(EncodeOfferId(uint64(toid.New(int32(ledger.Header.LedgerSeq), 1, 9).ToInt64()), TOIDType)), BaseAmount: int64(s.strictSendTradeLP.AmountSold()), BaseLiquidityPoolID: null.IntFrom(s.lpToID[s.strictSendTradeLP.MustLiquidityPool().LiquidityPoolId]), - BaseAssetID: s.assetToID[s.strictSendTradeLP.AssetSold().String()].ID, + BaseAssetID: s.assetToID[history.AssetKeyFromXDR(s.strictSendTradeLP.AssetSold())].ID, BaseIsSeller: true, BaseIsExact: null.BoolFrom(false), LiquidityPoolFee: null.IntFrom(int64(xdr.LiquidityPoolFeeV18)), @@ -709,243 +723,78 @@ func (s *TradeProcessorTestSuiteLedger) mockReadTradeTransactions( tx, } - s.mockQ.On("NewTradeBatchInsertBuilder", maxBatchSize). - Return(s.mockBatchInsertBuilder).Once() - return inserts } -func mapKeysToList(set map[string]int64) []string { - keys := make([]string, 0, len(set)) - for key := range set { - keys = append(keys, key) +func (s *TradeProcessorTestSuiteLedger) stubLoaders() { + for key, id := range s.unmuxedAccountToID { + s.accountLoader.Insert(key, id) } - return keys -} - -func uniq(list []string) []string { - var deduped []string - set := map[string]bool{} - for _, s := range list { - if set[s] { - continue - } - deduped = append(deduped, s) - set[s] = true + for key, id := range s.assetToID { + s.assetLoader.Insert(key, id.ID) + } + for key, id := range s.lpToID { + s.lpLoader.Insert(PoolIDToString(key), id) } - return deduped } func (s *TradeProcessorTestSuiteLedger) TestIngestTradesSucceeds() { ctx := context.Background() - inserts := s.mockReadTradeTransactions(s.processor.ledger) - - s.mockCreateAccounts(ctx) - - s.mockCreateAssets(ctx) + inserts := s.mockReadTradeTransactions() - s.mockCreateHistoryLiquidityPools(ctx) + for _, tx := range s.txs { + err := s.processor.ProcessTransaction(s.lcm, tx) + s.Assert().NoError(err) + } for _, insert := range inserts { - s.mockBatchInsertBuilder.On("Add", ctx, []history.InsertTrade{ + s.mockBatchInsertBuilder.On("Add", []history.InsertTrade{ insert, }).Return(nil).Once() } + s.mockBatchInsertBuilder.On("Exec", ctx, s.mockSession).Return(nil).Once() + s.stubLoaders() - s.mockBatchInsertBuilder.On("Exec", ctx).Return(nil).Once() - - for _, tx := range s.txs { - err := s.processor.ProcessTransaction(ctx, tx) - s.Assert().NoError(err) - } - - err := s.processor.Commit(ctx) + err := s.processor.Flush(ctx, s.mockSession) s.Assert().NoError(err) + s.Assert().Equal(s.processor.GetStats().count, int64(8)) + s.processor.ResetStats() + s.Assert().Equal(s.processor.GetStats().count, int64(0)) } -func (s *TradeProcessorTestSuiteLedger) mockCreateHistoryLiquidityPools(ctx context.Context) { - lpIDs, lpStrToID := s.extractLpIDs() - s.mockQ.On("CreateHistoryLiquidityPools", ctx, mock.AnythingOfType("[]string"), maxBatchSize). - Run(func(args mock.Arguments) { - arg := args.Get(1).([]string) - s.Assert().ElementsMatch( - lpIDs, - arg, - ) - }).Return(lpStrToID, nil).Once() -} - -func (s *TradeProcessorTestSuiteLedger) extractLpIDs() ([]string, map[string]int64) { - var lpIDs []string - lpStrToID := map[string]int64{} - for lpID, id := range s.lpToID { - lpIDStr := PoolIDToString(lpID) - lpIDs = append(lpIDs, lpIDStr) - lpStrToID[lpIDStr] = id - } - return lpIDs, lpStrToID -} - -func (s *TradeProcessorTestSuiteLedger) TestCreateAccountsError() { - ctx := context.Background() - s.mockReadTradeTransactions(s.processor.ledger) - - s.mockQ.On("CreateAccounts", ctx, mock.AnythingOfType("[]string"), maxBatchSize). - Run(func(args mock.Arguments) { - arg := args.Get(1).([]string) - s.Assert().ElementsMatch( - mapKeysToList(s.unmuxedAccountToID), - uniq(arg), - ) - }).Return(map[string]int64{}, fmt.Errorf("create accounts error")).Once() - - for _, tx := range s.txs { - err := s.processor.ProcessTransaction(ctx, tx) - s.Assert().NoError(err) - } - - err := s.processor.Commit(ctx) - - s.Assert().EqualError(err, "Error creating account ids: create accounts error") -} - -func (s *TradeProcessorTestSuiteLedger) TestCreateAssetsError() { - ctx := context.Background() - s.mockReadTradeTransactions(s.processor.ledger) - - s.mockCreateAccounts(ctx) - - s.mockQ.On("CreateAssets", ctx, mock.AnythingOfType("[]xdr.Asset"), maxBatchSize). - Run(func(args mock.Arguments) { - arg := args.Get(1).([]xdr.Asset) - s.Assert().ElementsMatch( - s.assets, - arg, - ) - }).Return(s.assetToID, fmt.Errorf("create assets error")).Once() - - for _, tx := range s.txs { - err := s.processor.ProcessTransaction(ctx, tx) - s.Assert().NoError(err) - } - - err := s.processor.Commit(ctx) - s.Assert().EqualError(err, "Error creating asset ids: create assets error") -} - -func (s *TradeProcessorTestSuiteLedger) TestCreateHistoryLiquidityPoolsError() { +func (s *TradeProcessorTestSuiteLedger) TestBatchAddError() { ctx := context.Background() - s.mockReadTradeTransactions(s.processor.ledger) - - s.mockCreateAccounts(ctx) - - s.mockCreateAssets(ctx) - - lpIDs, lpStrToID := s.extractLpIDs() - s.mockQ.On("CreateHistoryLiquidityPools", ctx, mock.AnythingOfType("[]string"), maxBatchSize). - Run(func(args mock.Arguments) { - arg := args.Get(1).([]string) - s.Assert().ElementsMatch( - lpIDs, - arg, - ) - }).Return(lpStrToID, fmt.Errorf("create liqudity pool id error")).Once() + s.mockReadTradeTransactions() for _, tx := range s.txs { - err := s.processor.ProcessTransaction(ctx, tx) + err := s.processor.ProcessTransaction(s.lcm, tx) s.Assert().NoError(err) } - err := s.processor.Commit(ctx) - s.Assert().EqualError(err, "Error creating pool ids: create liqudity pool id error") -} - -func (s *TradeProcessorTestSuiteLedger) mockCreateAssets(ctx context.Context) { - s.mockQ.On("CreateAssets", ctx, mock.AnythingOfType("[]xdr.Asset"), maxBatchSize). - Run(func(args mock.Arguments) { - arg := args.Get(1).([]xdr.Asset) - s.Assert().ElementsMatch( - s.assets, - arg, - ) - }).Return(s.assetToID, nil).Once() -} - -func (s *TradeProcessorTestSuiteLedger) mockCreateAccounts(ctx context.Context) { - s.mockQ.On("CreateAccounts", ctx, mock.AnythingOfType("[]string"), maxBatchSize). - Run(func(args mock.Arguments) { - arg := args.Get(1).([]string) - s.Assert().ElementsMatch( - mapKeysToList(s.unmuxedAccountToID), - uniq(arg), - ) - }).Return(s.unmuxedAccountToID, nil).Once() -} - -func (s *TradeProcessorTestSuiteLedger) TestBatchAddError() { - ctx := context.Background() - s.mockReadTradeTransactions(s.processor.ledger) - - s.mockCreateAccounts(ctx) - - s.mockCreateAssets(ctx) - - s.mockCreateHistoryLiquidityPools(ctx) - - s.mockBatchInsertBuilder.On("Add", ctx, mock.AnythingOfType("[]history.InsertTrade")). + s.stubLoaders() + s.mockBatchInsertBuilder.On("Add", mock.AnythingOfType("[]history.InsertTrade")). Return(fmt.Errorf("batch add error")).Once() - for _, tx := range s.txs { - err := s.processor.ProcessTransaction(ctx, tx) - s.Assert().NoError(err) - } - - err := s.processor.Commit(ctx) + err := s.processor.Flush(ctx, s.mockSession) s.Assert().EqualError(err, "Error adding trade to batch: batch add error") } func (s *TradeProcessorTestSuiteLedger) TestBatchExecError() { ctx := context.Background() - insert := s.mockReadTradeTransactions(s.processor.ledger) - - s.mockCreateAccounts(ctx) - - s.mockCreateAssets(ctx) + insert := s.mockReadTradeTransactions() - s.mockCreateHistoryLiquidityPools(ctx) - - s.mockBatchInsertBuilder.On("Add", ctx, mock.AnythingOfType("[]history.InsertTrade")). - Return(nil).Times(len(insert)) - s.mockBatchInsertBuilder.On("Exec", ctx).Return(fmt.Errorf("exec error")).Once() for _, tx := range s.txs { - err := s.processor.ProcessTransaction(ctx, tx) + err := s.processor.ProcessTransaction(s.lcm, tx) s.Assert().NoError(err) } - err := s.processor.Commit(ctx) - s.Assert().EqualError(err, "Error flushing operation batch: exec error") -} - -func (s *TradeProcessorTestSuiteLedger) TestIgnoreCheckIfSmallLedger() { - ctx := context.Background() - insert := s.mockReadTradeTransactions(s.processor.ledger) - - s.mockCreateAccounts(ctx) - - s.mockCreateAssets(ctx) - - s.mockCreateHistoryLiquidityPools(ctx) - s.mockBatchInsertBuilder.On("Add", ctx, mock.AnythingOfType("[]history.InsertTrade")). + s.stubLoaders() + s.mockBatchInsertBuilder.On("Add", mock.AnythingOfType("[]history.InsertTrade")). Return(nil).Times(len(insert)) - s.mockBatchInsertBuilder.On("Exec", ctx).Return(nil).Once() - - for _, tx := range s.txs { - err := s.processor.ProcessTransaction(ctx, tx) - s.Assert().NoError(err) - } + s.mockBatchInsertBuilder.On("Exec", ctx, s.mockSession).Return(fmt.Errorf("exec error")).Once() - err := s.processor.Commit(ctx) - s.Assert().NoError(err) + err := s.processor.Flush(ctx, s.mockSession) + s.Assert().EqualError(err, "Error flushing operation batch: exec error") } func TestTradeProcessor_ProcessTransaction_MuxedAccount(t *testing.T) { @@ -973,7 +822,7 @@ func TestTradeProcessor_RoundingSlippage_Big(t *testing.T) { s := &TradeProcessorTestSuiteLedger{} s.SetT(t) s.SetupTest() - s.mockReadTradeTransactions(s.processor.ledger) + s.mockReadTradeTransactions() assetDeposited := xdr.MustNewCreditAsset("MAD", s.unmuxedSourceAccount.Address()) assetDisbursed := xdr.MustNewCreditAsset("GRE", s.unmuxedSourceAccount.Address()) @@ -1005,7 +854,7 @@ func TestTradeProcessor_RoundingSlippage_Small(t *testing.T) { s := &TradeProcessorTestSuiteLedger{} s.SetT(t) s.SetupTest() - s.mockReadTradeTransactions(s.processor.ledger) + s.mockReadTradeTransactions() assetDeposited := xdr.MustNewCreditAsset("MAD", s.unmuxedSourceAccount.Address()) assetDisbursed := xdr.MustNewCreditAsset("GRE", s.unmuxedSourceAccount.Address()) diff --git a/services/horizon/internal/ingest/processors/transaction_operation_wrapper_test.go b/services/horizon/internal/ingest/processors/transaction_operation_wrapper_test.go index 32e67d8b5b..97b83f8f1b 100644 --- a/services/horizon/internal/ingest/processors/transaction_operation_wrapper_test.go +++ b/services/horizon/internal/ingest/processors/transaction_operation_wrapper_test.go @@ -5,10 +5,11 @@ package processors import ( "testing" - "github.com/stellar/go/protocols/horizon/base" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/suite" + "github.com/stellar/go/protocols/horizon/base" + "github.com/stellar/go/ingest" "github.com/stellar/go/services/horizon/internal/db2/history" . "github.com/stellar/go/services/horizon/internal/test/transactions" @@ -1521,6 +1522,13 @@ func getSponsoredSandwichWrappers() []*transactionOperationWrapper { { Type: xdr.LedgerEntryChangeTypeLedgerEntryCreated, Created: &xdr.LedgerEntry{ + Data: xdr.LedgerEntryData{ + Type: xdr.LedgerEntryTypeAccount, + Account: &xdr.AccountEntry{ + AccountId: xdr.MustAddress("GAUJETIZVEP2NRYLUESJ3LS66NVCEGMON4UDCBCSBEVPIID773P2W6AY"), + Balance: 100, + }, + }, LastModifiedLedgerSeq: xdr.Uint32(ledgerSeq), Ext: xdr.LedgerEntryExt{ V: 1, @@ -1850,7 +1858,7 @@ func TestLiquidityPoolDepositDetails(t *testing.T) { UnsafeMeta: xdr.TransactionMeta{ V: 2, V2: &xdr.TransactionMetaV2{ - Operations: []xdr.OperationMeta{{entryChanges}}, + Operations: []xdr.OperationMeta{{Changes: entryChanges}}, }, }}, operation: xdr.Operation{ @@ -1874,22 +1882,22 @@ func TestLiquidityPoolDepositDetails(t *testing.T) { }, "reserves_deposited": []base.AssetAmount{ { - "USD:GAUJETIZVEP2NRYLUESJ3LS66NVCEGMON4UDCBCSBEVPIID773P2W6AY", - "0.0000060", + Asset: "USD:GAUJETIZVEP2NRYLUESJ3LS66NVCEGMON4UDCBCSBEVPIID773P2W6AY", + Amount: "0.0000060", }, { - "native", - "0.0000050", + Asset: "native", + Amount: "0.0000050", }, }, "reserves_max": []base.AssetAmount{ { - "USD:GAUJETIZVEP2NRYLUESJ3LS66NVCEGMON4UDCBCSBEVPIID773P2W6AY", - "0.0000100", + Asset: "USD:GAUJETIZVEP2NRYLUESJ3LS66NVCEGMON4UDCBCSBEVPIID773P2W6AY", + Amount: "0.0000100", }, { - "native", - "0.0000200", + Asset: "native", + Amount: "0.0000200", }, }, "shares_received": "0.0000010", @@ -1957,22 +1965,22 @@ func TestFailedLiquidityPoolDepositDetails(t *testing.T) { }, "reserves_deposited": []base.AssetAmount{ { - "", - "0.0000000", + Asset: "", + Amount: "0.0000000", }, { - "", - "0.0000000", + Asset: "", + Amount: "0.0000000", }, }, "reserves_max": []base.AssetAmount{ { - "", - "0.0000100", + Asset: "", + Amount: "0.0000100", }, { - "", - "0.0000200", + Asset: "", + Amount: "0.0000200", }, }, "shares_received": "0.0000000", @@ -2055,7 +2063,7 @@ func TestLiquidityPoolWithdrawDetails(t *testing.T) { UnsafeMeta: xdr.TransactionMeta{ V: 2, V2: &xdr.TransactionMetaV2{ - Operations: []xdr.OperationMeta{{entryChanges}}, + Operations: []xdr.OperationMeta{{Changes: entryChanges}}, }, }}, operation: xdr.Operation{ @@ -2069,22 +2077,22 @@ func TestLiquidityPoolWithdrawDetails(t *testing.T) { "liquidity_pool_id": "cafebabe00000000000000000000000000000000000000000000000000000000", "reserves_received": []base.AssetAmount{ { - "USD:GAUJETIZVEP2NRYLUESJ3LS66NVCEGMON4UDCBCSBEVPIID773P2W6AY", - "0.0000060", + Asset: "USD:GAUJETIZVEP2NRYLUESJ3LS66NVCEGMON4UDCBCSBEVPIID773P2W6AY", + Amount: "0.0000060", }, { - "native", - "0.0000050", + Asset: "native", + Amount: "0.0000050", }, }, "reserves_min": []base.AssetAmount{ { - "USD:GAUJETIZVEP2NRYLUESJ3LS66NVCEGMON4UDCBCSBEVPIID773P2W6AY", - "0.0000005", + Asset: "USD:GAUJETIZVEP2NRYLUESJ3LS66NVCEGMON4UDCBCSBEVPIID773P2W6AY", + Amount: "0.0000005", }, { - "native", - "0.0000010", + Asset: "native", + Amount: "0.0000010", }, }, "shares": "0.0000010", @@ -2135,22 +2143,22 @@ func TestFailedLiquidityPoolWithdrawDetails(t *testing.T) { "liquidity_pool_id": "cafebabe00000000000000000000000000000000000000000000000000000000", "reserves_received": []base.AssetAmount{ { - "", - "0.0000000", + Asset: "", + Amount: "0.0000000", }, { - "", - "0.0000000", + Asset: "", + Amount: "0.0000000", }, }, "reserves_min": []base.AssetAmount{ { - "", - "0.0000005", + Asset: "", + Amount: "0.0000005", }, { - "", - "0.0000010", + Asset: "", + Amount: "0.0000010", }, }, "shares": "0.0000010", @@ -2216,7 +2224,7 @@ func TestParticipantsCoversAllOperationTypes(t *testing.T) { } // calling Participants should error due to the unknown operation _, err := operation.Participants() - assert.Contains(t, err.Error(), "Unknown operation type") + assert.Contains(t, err.Error(), "unknown operation type") } func TestDetailsCoversAllOperationTypes(t *testing.T) { @@ -2278,5 +2286,5 @@ func TestDetailsCoversAllOperationTypes(t *testing.T) { f := func() { operation.Details() } - assert.PanicsWithError(t, "Unknown operation type: ", f) + assert.PanicsWithError(t, "unknown operation type: ", f) } diff --git a/services/horizon/internal/ingest/processors/transactions_processor.go b/services/horizon/internal/ingest/processors/transactions_processor.go index e2a880f296..871c72624a 100644 --- a/services/horizon/internal/ingest/processors/transactions_processor.go +++ b/services/horizon/internal/ingest/processors/transactions_processor.go @@ -5,43 +5,35 @@ import ( "github.com/stellar/go/ingest" "github.com/stellar/go/services/horizon/internal/db2/history" + "github.com/stellar/go/support/db" "github.com/stellar/go/support/errors" + "github.com/stellar/go/xdr" ) type TransactionProcessor struct { - transactionsQ history.QTransactions - sequence uint32 - batch history.TransactionBatchInsertBuilder + batch history.TransactionBatchInsertBuilder } -func NewTransactionFilteredTmpProcessor(transactionsQ history.QTransactions, sequence uint32) *TransactionProcessor { +func NewTransactionFilteredTmpProcessor(batch history.TransactionBatchInsertBuilder) *TransactionProcessor { return &TransactionProcessor{ - transactionsQ: transactionsQ, - sequence: sequence, - batch: transactionsQ.NewTransactionFilteredTmpBatchInsertBuilder(maxBatchSize), + batch: batch, } } -func NewTransactionProcessor(transactionsQ history.QTransactions, sequence uint32) *TransactionProcessor { +func NewTransactionProcessor(batch history.TransactionBatchInsertBuilder) *TransactionProcessor { return &TransactionProcessor{ - transactionsQ: transactionsQ, - sequence: sequence, - batch: transactionsQ.NewTransactionBatchInsertBuilder(maxBatchSize), + batch: batch, } } -func (p *TransactionProcessor) ProcessTransaction(ctx context.Context, transaction ingest.LedgerTransaction) error { - if err := p.batch.Add(ctx, transaction, p.sequence); err != nil { +func (p *TransactionProcessor) ProcessTransaction(lcm xdr.LedgerCloseMeta, transaction ingest.LedgerTransaction) error { + if err := p.batch.Add(transaction, lcm.LedgerSequence()); err != nil { return errors.Wrap(err, "Error batch inserting transaction rows") } return nil } -func (p *TransactionProcessor) Commit(ctx context.Context) error { - if err := p.batch.Exec(ctx); err != nil { - return errors.Wrap(err, "Error flushing transaction batch") - } - - return nil +func (p *TransactionProcessor) Flush(ctx context.Context, session db.SessionInterface) error { + return p.batch.Exec(ctx, session) } diff --git a/services/horizon/internal/ingest/processors/transactions_processor_test.go b/services/horizon/internal/ingest/processors/transactions_processor_test.go index ec1cf105e5..987e8ce6f9 100644 --- a/services/horizon/internal/ingest/processors/transactions_processor_test.go +++ b/services/horizon/internal/ingest/processors/transactions_processor_test.go @@ -7,7 +7,10 @@ import ( "testing" "github.com/stellar/go/services/horizon/internal/db2/history" + "github.com/stellar/go/support/db" "github.com/stellar/go/support/errors" + "github.com/stellar/go/xdr" + "github.com/stretchr/testify/suite" ) @@ -15,7 +18,7 @@ type TransactionsProcessorTestSuiteLedger struct { suite.Suite ctx context.Context processor *TransactionProcessor - mockQ *history.MockQTransactions + mockSession *db.MockSession mockBatchInsertBuilder *history.MockTransactionsBatchInsertBuilder } @@ -25,66 +28,81 @@ func TestTransactionsProcessorTestSuiteLedger(t *testing.T) { func (s *TransactionsProcessorTestSuiteLedger) SetupTest() { s.ctx = context.Background() - s.mockQ = &history.MockQTransactions{} s.mockBatchInsertBuilder = &history.MockTransactionsBatchInsertBuilder{} - - s.mockQ. - On("NewTransactionBatchInsertBuilder", maxBatchSize). - Return(s.mockBatchInsertBuilder).Once() - - s.processor = NewTransactionProcessor(s.mockQ, 20) + s.processor = NewTransactionProcessor(s.mockBatchInsertBuilder) } func (s *TransactionsProcessorTestSuiteLedger) TearDownTest() { - s.mockQ.AssertExpectations(s.T()) s.mockBatchInsertBuilder.AssertExpectations(s.T()) } func (s *TransactionsProcessorTestSuiteLedger) TestAddTransactionsSucceeds() { sequence := uint32(20) - + lcm := xdr.LedgerCloseMeta{ + V0: &xdr.LedgerCloseMetaV0{ + LedgerHeader: xdr.LedgerHeaderHistoryEntry{ + Header: xdr.LedgerHeader{ + LedgerSeq: xdr.Uint32(sequence), + }, + }, + }, + } firstTx := createTransaction(true, 1) secondTx := createTransaction(false, 3) thirdTx := createTransaction(true, 4) - s.mockBatchInsertBuilder.On("Add", s.ctx, firstTx, sequence).Return(nil).Once() - s.mockBatchInsertBuilder.On("Add", s.ctx, secondTx, sequence).Return(nil).Once() - s.mockBatchInsertBuilder.On("Add", s.ctx, thirdTx, sequence).Return(nil).Once() - s.mockBatchInsertBuilder.On("Exec", s.ctx).Return(nil).Once() - s.Assert().NoError(s.processor.Commit(s.ctx)) - - err := s.processor.ProcessTransaction(s.ctx, firstTx) - s.Assert().NoError(err) + s.mockBatchInsertBuilder.On("Add", firstTx, sequence).Return(nil).Once() + s.mockBatchInsertBuilder.On("Add", secondTx, sequence).Return(nil).Once() + s.mockBatchInsertBuilder.On("Add", thirdTx, sequence+1).Return(nil).Once() + s.mockBatchInsertBuilder.On("Exec", s.ctx, s.mockSession).Return(nil).Once() - err = s.processor.ProcessTransaction(s.ctx, secondTx) - s.Assert().NoError(err) + s.Assert().NoError(s.processor.ProcessTransaction(lcm, firstTx)) + s.Assert().NoError(s.processor.ProcessTransaction(lcm, secondTx)) + lcm.V0.LedgerHeader.Header.LedgerSeq++ + s.Assert().NoError(s.processor.ProcessTransaction(lcm, thirdTx)) - err = s.processor.ProcessTransaction(s.ctx, thirdTx) - s.Assert().NoError(err) + s.Assert().NoError(s.processor.Flush(s.ctx, s.mockSession)) } func (s *TransactionsProcessorTestSuiteLedger) TestAddTransactionsFails() { sequence := uint32(20) + lcm := xdr.LedgerCloseMeta{ + V0: &xdr.LedgerCloseMetaV0{ + LedgerHeader: xdr.LedgerHeaderHistoryEntry{ + Header: xdr.LedgerHeader{ + LedgerSeq: xdr.Uint32(sequence), + }, + }, + }, + } firstTx := createTransaction(true, 1) - s.mockBatchInsertBuilder.On("Add", s.ctx, firstTx, sequence). + s.mockBatchInsertBuilder.On("Add", firstTx, sequence). Return(errors.New("transient error")).Once() - err := s.processor.ProcessTransaction(s.ctx, firstTx) + err := s.processor.ProcessTransaction(lcm, firstTx) s.Assert().Error(err) s.Assert().EqualError(err, "Error batch inserting transaction rows: transient error") } func (s *TransactionsProcessorTestSuiteLedger) TestExecFails() { sequence := uint32(20) + lcm := xdr.LedgerCloseMeta{ + V0: &xdr.LedgerCloseMetaV0{ + LedgerHeader: xdr.LedgerHeaderHistoryEntry{ + Header: xdr.LedgerHeader{ + LedgerSeq: xdr.Uint32(sequence), + }, + }, + }, + } firstTx := createTransaction(true, 1) - s.mockBatchInsertBuilder.On("Add", s.ctx, firstTx, sequence).Return(nil).Once() - s.mockBatchInsertBuilder.On("Exec", s.ctx).Return(errors.New("transient error")).Once() + s.mockBatchInsertBuilder.On("Add", firstTx, sequence).Return(nil).Once() + s.mockBatchInsertBuilder.On("Exec", s.ctx, s.mockSession).Return(errors.New("transient error")).Once() - err := s.processor.ProcessTransaction(s.ctx, firstTx) - s.Assert().NoError(err) + s.Assert().NoError(s.processor.ProcessTransaction(lcm, firstTx)) - err = s.processor.Commit(s.ctx) + err := s.processor.Flush(s.ctx, s.mockSession) s.Assert().Error(err) - s.Assert().EqualError(err, "Error flushing transaction batch: transient error") + s.Assert().EqualError(err, "transient error") } diff --git a/services/horizon/internal/ingest/processors/trust_lines_processor.go b/services/horizon/internal/ingest/processors/trust_lines_processor.go index f161e8a20f..3152ef0db7 100644 --- a/services/horizon/internal/ingest/processors/trust_lines_processor.go +++ b/services/horizon/internal/ingest/processors/trust_lines_processor.go @@ -12,7 +12,8 @@ import ( type TrustLinesProcessor struct { trustLinesQ history.QTrustLines - cache *ingest.ChangeCompactor + cache *ingest.ChangeCompactor + batchInsertBuilder history.TrustLinesBatchInsertBuilder } func NewTrustLinesProcessor(trustLinesQ history.QTrustLines) *TrustLinesProcessor { @@ -23,6 +24,7 @@ func NewTrustLinesProcessor(trustLinesQ history.QTrustLines) *TrustLinesProcesso func (p *TrustLinesProcessor) reset() { p.cache = ingest.NewChangeCompactor() + p.batchInsertBuilder = p.trustLinesQ.NewTrustLinesBatchInsertBuilder() } func (p *TrustLinesProcessor) ProcessChange(ctx context.Context, change ingest.Change) error { @@ -40,7 +42,6 @@ func (p *TrustLinesProcessor) ProcessChange(ctx context.Context, change ingest.C if err != nil { return errors.Wrap(err, "error in Commit") } - p.reset() } return nil @@ -56,7 +57,7 @@ func trustLineLedgerKey(trustLineEntry xdr.TrustLineEntry) (string, error) { } ledgerKeyString, err = ledgerKey.MarshalBinaryBase64() if err != nil { - return "", errors.Wrap(err, "Error marshalling ledger key") + return "", errors.Wrap(err, "Error marshaling ledger key") } return ledgerKeyString, nil } @@ -97,18 +98,31 @@ func xdrToTrustline(ledgerEntry xdr.LedgerEntry) (history.TrustLine, error) { } func (p *TrustLinesProcessor) Commit(ctx context.Context) error { + defer p.reset() + var batchUpsertTrustLines []history.TrustLine var batchRemoveTrustLineKeys []string changes := p.cache.GetChanges() for _, change := range changes { switch { - case change.Post != nil: - tl, err := xdrToTrustline(*change.Post) + case change.Pre == nil && change.Post != nil: + // Created + line, err := xdrToTrustline(*change.Post) if err != nil { return errors.Wrap(err, "Error extracting trustline") } + err = p.batchInsertBuilder.Add(line) + if err != nil { + return errors.Wrap(err, "Error adding to TrustLinesBatchInsertBuilder") + } + case change.Pre != nil && change.Post != nil: + // Updated + tl, err := xdrToTrustline(*change.Post) + if err != nil { + return errors.Wrap(err, "Error extracting trustline") + } batchUpsertTrustLines = append(batchUpsertTrustLines, tl) case change.Pre != nil && change.Post == nil: // Removed @@ -124,6 +138,11 @@ func (p *TrustLinesProcessor) Commit(ctx context.Context) error { } } + err := p.batchInsertBuilder.Exec(ctx) + if err != nil { + return errors.Wrap(err, "Error executing TrustLinesBatchInsertBuilder") + } + if len(batchUpsertTrustLines) > 0 { err := p.trustLinesQ.UpsertTrustLines(ctx, batchUpsertTrustLines) if err != nil { diff --git a/services/horizon/internal/ingest/processors/trust_lines_processor_test.go b/services/horizon/internal/ingest/processors/trust_lines_processor_test.go index 2e3d092f5a..07990a0658 100644 --- a/services/horizon/internal/ingest/processors/trust_lines_processor_test.go +++ b/services/horizon/internal/ingest/processors/trust_lines_processor_test.go @@ -24,14 +24,20 @@ func TestTrustLinesProcessorTestSuiteState(t *testing.T) { type TrustLinesProcessorTestSuiteState struct { suite.Suite - ctx context.Context - processor *TrustLinesProcessor - mockQ *history.MockQTrustLines + ctx context.Context + processor *TrustLinesProcessor + mockQ *history.MockQTrustLines + mockTrustLinesBatchInsertBuilder *history.MockTrustLinesBatchInsertBuilder } func (s *TrustLinesProcessorTestSuiteState) SetupTest() { s.ctx = context.Background() s.mockQ = &history.MockQTrustLines{} + + s.mockTrustLinesBatchInsertBuilder = &history.MockTrustLinesBatchInsertBuilder{} + s.mockQ.On("NewTrustLinesBatchInsertBuilder").Return(s.mockTrustLinesBatchInsertBuilder).Twice() + s.mockTrustLinesBatchInsertBuilder.On("Exec", s.ctx).Return(nil).Once() + s.processor = NewTrustLinesProcessor(s.mockQ) } @@ -85,42 +91,33 @@ func (s *TrustLinesProcessorTestSuiteState) TestCreateTrustLine() { }) s.Assert().NoError(err) - s.mockQ.On( - "UpsertTrustLines", - s.ctx, - mock.AnythingOfType("[]history.TrustLine"), - ).Run(func(args mock.Arguments) { - arg := args.Get(1).([]history.TrustLine) - s.Assert().ElementsMatch( - []history.TrustLine{ - { - AccountID: trustLine.AccountId.Address(), - AssetType: xdr.AssetTypeAssetTypeCreditAlphanum4, - AssetIssuer: trustLineIssuer.Address(), - AssetCode: "EUR", - Balance: int64(trustLine.Balance), - LedgerKey: "AAAAAQAAAAAdBJqAD9qPq+j2nRDdjdp5KVoUh8riPkNO9ato7BNs8wAAAAFFVVIAAAAAAGL8HQvQkbK2HA3WVjRrKmjX00fG8sLI7m0ERwJW/AX3", - Limit: int64(trustLine.Limit), - LiquidityPoolID: "", - BuyingLiabilities: int64(trustLine.Liabilities().Buying), - SellingLiabilities: int64(trustLine.Liabilities().Selling), - Flags: uint32(trustLine.Flags), - LastModifiedLedger: uint32(lastModifiedLedgerSeq), - Sponsor: null.String{}, - }, - { - AccountID: poolShareTrustLine.AccountId.Address(), - AssetType: xdr.AssetTypeAssetTypePoolShare, - Balance: int64(poolShareTrustLine.Balance), - LedgerKey: "AAAAAQAAAAC2LgFRDBZ3J52nLm30kq2iMgrO7dYzYAN3hvjtf1IHWgAAAAMBAgMEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==", - Limit: int64(poolShareTrustLine.Limit), - LiquidityPoolID: "0102030400000000000000000000000000000000000000000000000000000000", - Flags: uint32(poolShareTrustLine.Flags), - LastModifiedLedger: uint32(lastModifiedLedgerSeq), - }, - }, - arg) + s.mockTrustLinesBatchInsertBuilder.On("Add", history.TrustLine{ + AccountID: trustLine.AccountId.Address(), + AssetType: xdr.AssetTypeAssetTypeCreditAlphanum4, + AssetIssuer: trustLineIssuer.Address(), + AssetCode: "EUR", + Balance: int64(trustLine.Balance), + LedgerKey: "AAAAAQAAAAAdBJqAD9qPq+j2nRDdjdp5KVoUh8riPkNO9ato7BNs8wAAAAFFVVIAAAAAAGL8HQvQkbK2HA3WVjRrKmjX00fG8sLI7m0ERwJW/AX3", + Limit: int64(trustLine.Limit), + LiquidityPoolID: "", + BuyingLiabilities: int64(trustLine.Liabilities().Buying), + SellingLiabilities: int64(trustLine.Liabilities().Selling), + Flags: uint32(trustLine.Flags), + LastModifiedLedger: uint32(lastModifiedLedgerSeq), + Sponsor: null.String{}, }).Return(nil).Once() + + s.mockTrustLinesBatchInsertBuilder.On("Add", history.TrustLine{ + AccountID: poolShareTrustLine.AccountId.Address(), + AssetType: xdr.AssetTypeAssetTypePoolShare, + Balance: int64(poolShareTrustLine.Balance), + LedgerKey: "AAAAAQAAAAC2LgFRDBZ3J52nLm30kq2iMgrO7dYzYAN3hvjtf1IHWgAAAAMBAgMEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==", + Limit: int64(poolShareTrustLine.Limit), + LiquidityPoolID: "0102030400000000000000000000000000000000000000000000000000000000", + Flags: uint32(poolShareTrustLine.Flags), + LastModifiedLedger: uint32(lastModifiedLedgerSeq), + }).Return(nil).Once() + } func (s *TrustLinesProcessorTestSuiteState) TestCreateTrustLineUnauthorized() { @@ -142,27 +139,21 @@ func (s *TrustLinesProcessorTestSuiteState) TestCreateTrustLineUnauthorized() { }) s.Assert().NoError(err) - s.mockQ.On( - "UpsertTrustLines", - s.ctx, - []history.TrustLine{ - { - AccountID: trustLine.AccountId.Address(), - AssetType: xdr.AssetTypeAssetTypeCreditAlphanum4, - AssetIssuer: trustLineIssuer.Address(), - AssetCode: "EUR", - Balance: int64(trustLine.Balance), - LedgerKey: "AAAAAQAAAAAdBJqAD9qPq+j2nRDdjdp5KVoUh8riPkNO9ato7BNs8wAAAAFFVVIAAAAAAGL8HQvQkbK2HA3WVjRrKmjX00fG8sLI7m0ERwJW/AX3", - Limit: int64(trustLine.Limit), - LiquidityPoolID: "", - BuyingLiabilities: int64(trustLine.Liabilities().Buying), - SellingLiabilities: int64(trustLine.Liabilities().Selling), - Flags: uint32(trustLine.Flags), - LastModifiedLedger: uint32(lastModifiedLedgerSeq), - Sponsor: null.String{}, - }, - }, - ).Return(nil).Once() + s.mockTrustLinesBatchInsertBuilder.On("Add", history.TrustLine{ + AccountID: trustLine.AccountId.Address(), + AssetType: xdr.AssetTypeAssetTypeCreditAlphanum4, + AssetIssuer: trustLineIssuer.Address(), + AssetCode: "EUR", + Balance: int64(trustLine.Balance), + LedgerKey: "AAAAAQAAAAAdBJqAD9qPq+j2nRDdjdp5KVoUh8riPkNO9ato7BNs8wAAAAFFVVIAAAAAAGL8HQvQkbK2HA3WVjRrKmjX00fG8sLI7m0ERwJW/AX3", + Limit: int64(trustLine.Limit), + LiquidityPoolID: "", + BuyingLiabilities: int64(trustLine.Liabilities().Buying), + SellingLiabilities: int64(trustLine.Liabilities().Selling), + Flags: uint32(trustLine.Flags), + LastModifiedLedger: uint32(lastModifiedLedgerSeq), + Sponsor: null.String{}, + }).Return(nil).Once() } func TestTrustLinesProcessorTestSuiteLedger(t *testing.T) { @@ -171,14 +162,20 @@ func TestTrustLinesProcessorTestSuiteLedger(t *testing.T) { type TrustLinesProcessorTestSuiteLedger struct { suite.Suite - ctx context.Context - processor *TrustLinesProcessor - mockQ *history.MockQTrustLines + ctx context.Context + processor *TrustLinesProcessor + mockQ *history.MockQTrustLines + mockTrustLinesBatchInsertBuilder *history.MockTrustLinesBatchInsertBuilder } func (s *TrustLinesProcessorTestSuiteLedger) SetupTest() { s.ctx = context.Background() s.mockQ = &history.MockQTrustLines{} + + s.mockTrustLinesBatchInsertBuilder = &history.MockTrustLinesBatchInsertBuilder{} + s.mockQ.On("NewTrustLinesBatchInsertBuilder").Return(s.mockTrustLinesBatchInsertBuilder).Twice() + s.mockTrustLinesBatchInsertBuilder.On("Exec", s.ctx).Return(nil).Once() + s.processor = NewTrustLinesProcessor(s.mockQ) } @@ -298,47 +295,36 @@ func (s *TrustLinesProcessorTestSuiteLedger) TestInsertTrustLine() { }) s.Assert().NoError(err) - s.mockQ.On( - "UpsertTrustLines", - s.ctx, - mock.AnythingOfType("[]history.TrustLine"), - ).Run(func(args mock.Arguments) { - arg := args.Get(1).([]history.TrustLine) - s.Assert().ElementsMatch( - []history.TrustLine{ - { - AccountID: updatedTrustLine.AccountId.Address(), - AssetType: updatedTrustLine.Asset.Type, - AssetIssuer: trustLineIssuer.Address(), - AssetCode: "EUR", - Balance: int64(updatedTrustLine.Balance), - LedgerKey: "AAAAAQAAAAAdBJqAD9qPq+j2nRDdjdp5KVoUh8riPkNO9ato7BNs8wAAAAFFVVIAAAAAAGL8HQvQkbK2HA3WVjRrKmjX00fG8sLI7m0ERwJW/AX3", - Limit: int64(updatedTrustLine.Limit), - LiquidityPoolID: "", - BuyingLiabilities: int64(updatedTrustLine.Liabilities().Buying), - SellingLiabilities: int64(updatedTrustLine.Liabilities().Selling), - Flags: uint32(updatedTrustLine.Flags), - LastModifiedLedger: uint32(lastModifiedLedgerSeq), - Sponsor: null.String{}, - }, - { - AccountID: updatedUnauthorizedTrustline.AccountId.Address(), - AssetType: updatedUnauthorizedTrustline.Asset.Type, - AssetIssuer: trustLineIssuer.Address(), - AssetCode: "USD", - Balance: int64(updatedUnauthorizedTrustline.Balance), - LedgerKey: "AAAAAQAAAAC2LgFRDBZ3J52nLm30kq2iMgrO7dYzYAN3hvjtf1IHWgAAAAFVU0QAAAAAAGL8HQvQkbK2HA3WVjRrKmjX00fG8sLI7m0ERwJW/AX3", - Limit: int64(updatedUnauthorizedTrustline.Limit), - LiquidityPoolID: "", - BuyingLiabilities: int64(updatedUnauthorizedTrustline.Liabilities().Buying), - SellingLiabilities: int64(updatedUnauthorizedTrustline.Liabilities().Selling), - Flags: uint32(updatedUnauthorizedTrustline.Flags), - LastModifiedLedger: uint32(lastModifiedLedgerSeq), - Sponsor: null.String{}, - }, - }, - arg, - ) + s.mockTrustLinesBatchInsertBuilder.On("Add", history.TrustLine{ + AccountID: updatedTrustLine.AccountId.Address(), + AssetType: updatedTrustLine.Asset.Type, + AssetIssuer: trustLineIssuer.Address(), + AssetCode: "EUR", + Balance: int64(updatedTrustLine.Balance), + LedgerKey: "AAAAAQAAAAAdBJqAD9qPq+j2nRDdjdp5KVoUh8riPkNO9ato7BNs8wAAAAFFVVIAAAAAAGL8HQvQkbK2HA3WVjRrKmjX00fG8sLI7m0ERwJW/AX3", + Limit: int64(updatedTrustLine.Limit), + LiquidityPoolID: "", + BuyingLiabilities: int64(updatedTrustLine.Liabilities().Buying), + SellingLiabilities: int64(updatedTrustLine.Liabilities().Selling), + Flags: uint32(updatedTrustLine.Flags), + LastModifiedLedger: uint32(lastModifiedLedgerSeq), + Sponsor: null.String{}, + }).Return(nil).Once() + + s.mockTrustLinesBatchInsertBuilder.On("Add", history.TrustLine{ + AccountID: updatedUnauthorizedTrustline.AccountId.Address(), + AssetType: updatedUnauthorizedTrustline.Asset.Type, + AssetIssuer: trustLineIssuer.Address(), + AssetCode: "USD", + Balance: int64(updatedUnauthorizedTrustline.Balance), + LedgerKey: "AAAAAQAAAAC2LgFRDBZ3J52nLm30kq2iMgrO7dYzYAN3hvjtf1IHWgAAAAFVU0QAAAAAAGL8HQvQkbK2HA3WVjRrKmjX00fG8sLI7m0ERwJW/AX3", + Limit: int64(updatedUnauthorizedTrustline.Limit), + LiquidityPoolID: "", + BuyingLiabilities: int64(updatedUnauthorizedTrustline.Liabilities().Buying), + SellingLiabilities: int64(updatedUnauthorizedTrustline.Liabilities().Selling), + Flags: uint32(updatedUnauthorizedTrustline.Flags), + LastModifiedLedger: uint32(lastModifiedLedgerSeq), + Sponsor: null.String{}, }).Return(nil).Once() s.Assert().NoError(s.processor.Commit(s.ctx)) } @@ -626,26 +612,22 @@ func (s *TrustLinesProcessorTestSuiteLedger) TestProcessUpgradeChange() { }) s.Assert().NoError(err) - s.mockQ.On( - "UpsertTrustLines", s.ctx, - []history.TrustLine{ - { - AccountID: updatedTrustLine.AccountId.Address(), - AssetType: updatedTrustLine.Asset.Type, - AssetIssuer: trustLineIssuer.Address(), - AssetCode: "EUR", - Balance: int64(updatedTrustLine.Balance), - LedgerKey: "AAAAAQAAAAAdBJqAD9qPq+j2nRDdjdp5KVoUh8riPkNO9ato7BNs8wAAAAFFVVIAAAAAAGL8HQvQkbK2HA3WVjRrKmjX00fG8sLI7m0ERwJW/AX3", - Limit: int64(updatedTrustLine.Limit), - LiquidityPoolID: "", - BuyingLiabilities: int64(updatedTrustLine.Liabilities().Buying), - SellingLiabilities: int64(updatedTrustLine.Liabilities().Selling), - Flags: uint32(updatedTrustLine.Flags), - LastModifiedLedger: uint32(lastModifiedLedgerSeq), - Sponsor: null.String{}, - }, - }, - ).Return(nil).Once() + s.mockTrustLinesBatchInsertBuilder.On("Add", history.TrustLine{ + AccountID: updatedTrustLine.AccountId.Address(), + AssetType: updatedTrustLine.Asset.Type, + AssetIssuer: trustLineIssuer.Address(), + AssetCode: "EUR", + Balance: int64(updatedTrustLine.Balance), + LedgerKey: "AAAAAQAAAAAdBJqAD9qPq+j2nRDdjdp5KVoUh8riPkNO9ato7BNs8wAAAAFFVVIAAAAAAGL8HQvQkbK2HA3WVjRrKmjX00fG8sLI7m0ERwJW/AX3", + Limit: int64(updatedTrustLine.Limit), + LiquidityPoolID: "", + BuyingLiabilities: int64(updatedTrustLine.Liabilities().Buying), + SellingLiabilities: int64(updatedTrustLine.Liabilities().Selling), + Flags: uint32(updatedTrustLine.Flags), + LastModifiedLedger: uint32(lastModifiedLedgerSeq), + Sponsor: null.String{}, + }).Return(nil).Once() + s.Assert().NoError(s.processor.Commit(s.ctx)) } diff --git a/services/horizon/internal/ingest/resume_state_test.go b/services/horizon/internal/ingest/resume_state_test.go index 7f336a79ae..82a7869d4b 100644 --- a/services/horizon/internal/ingest/resume_state_test.go +++ b/services/horizon/internal/ingest/resume_state_test.go @@ -9,7 +9,6 @@ import ( "github.com/stretchr/testify/mock" "github.com/stretchr/testify/suite" - "github.com/stellar/go/historyarchive" "github.com/stellar/go/ingest/ledgerbackend" "github.com/stellar/go/support/errors" "github.com/stellar/go/xdr" @@ -38,13 +37,13 @@ func (s *ResumeTestTestSuite) SetupTest() { s.runner = &mockProcessorsRunner{} s.stellarCoreClient = &mockStellarCoreClient{} s.system = &system{ - ctx: s.ctx, - historyQ: s.historyQ, - historyAdapter: s.historyAdapter, - runner: s.runner, - ledgerBackend: s.ledgerBackend, - stellarCoreClient: s.stellarCoreClient, - checkpointManager: historyarchive.NewCheckpointManager(64), + ctx: s.ctx, + historyQ: s.historyQ, + historyAdapter: s.historyAdapter, + runner: s.runner, + ledgerBackend: s.ledgerBackend, + stellarCoreClient: s.stellarCoreClient, + runStateVerificationOnLedger: ledgerEligibleForStateVerification(64, 1), } s.system.initMetrics() @@ -124,7 +123,7 @@ func (s *ResumeTestTestSuite) TestBeginReturnsError() { // Recreate mock in this single test to remove Rollback assertion. *s.historyQ = mockDBQ{} - s.historyQ.On("Begin").Return(errors.New("my error")).Once() + s.historyQ.On("Begin", s.ctx).Return(errors.New("my error")).Once() next, err := resumeState{latestSuccessfullyProcessedLedger: 100}.run(s.system) s.Assert().Error(err) @@ -139,7 +138,7 @@ func (s *ResumeTestTestSuite) TestBeginReturnsError() { } func (s *ResumeTestTestSuite) TestGetLastLedgerIngestReturnsError() { - s.historyQ.On("Begin").Return(nil).Once() + s.historyQ.On("Begin", s.ctx).Return(nil).Once() s.historyQ.On("GetLastLedgerIngest", s.ctx).Return(uint32(0), errors.New("my error")).Once() next, err := resumeState{latestSuccessfullyProcessedLedger: 100}.run(s.system) @@ -155,7 +154,7 @@ func (s *ResumeTestTestSuite) TestGetLastLedgerIngestReturnsError() { } func (s *ResumeTestTestSuite) TestGetLatestLedgerLessThanCurrent() { - s.historyQ.On("Begin").Return(nil).Once() + s.historyQ.On("Begin", s.ctx).Return(nil).Once() s.historyQ.On("GetLastLedgerIngest", s.ctx).Return(uint32(99), nil).Once() next, err := resumeState{latestSuccessfullyProcessedLedger: 100}.run(s.system) @@ -168,7 +167,7 @@ func (s *ResumeTestTestSuite) TestGetLatestLedgerLessThanCurrent() { } func (s *ResumeTestTestSuite) TestGetIngestionVersionError() { - s.historyQ.On("Begin").Return(nil).Once() + s.historyQ.On("Begin", s.ctx).Return(nil).Once() s.historyQ.On("GetLastLedgerIngest", s.ctx).Return(uint32(100), nil).Once() s.historyQ.On("GetIngestVersion", s.ctx).Return(0, errors.New("my error")).Once() @@ -185,7 +184,7 @@ func (s *ResumeTestTestSuite) TestGetIngestionVersionError() { } func (s *ResumeTestTestSuite) TestIngestionVersionLessThanCurrentVersion() { - s.historyQ.On("Begin").Return(nil).Once() + s.historyQ.On("Begin", s.ctx).Return(nil).Once() s.historyQ.On("GetLastLedgerIngest", s.ctx).Return(uint32(100), nil).Once() s.historyQ.On("GetIngestVersion", s.ctx).Return(CurrentVersion-1, nil).Once() @@ -198,7 +197,7 @@ func (s *ResumeTestTestSuite) TestIngestionVersionLessThanCurrentVersion() { } func (s *ResumeTestTestSuite) TestIngestionVersionGreaterThanCurrentVersion() { - s.historyQ.On("Begin").Return(nil).Once() + s.historyQ.On("Begin", s.ctx).Return(nil).Once() s.historyQ.On("GetLastLedgerIngest", s.ctx).Return(uint32(100), nil).Once() s.historyQ.On("GetIngestVersion", s.ctx).Return(CurrentVersion+1, nil).Once() @@ -211,7 +210,7 @@ func (s *ResumeTestTestSuite) TestIngestionVersionGreaterThanCurrentVersion() { } func (s *ResumeTestTestSuite) TestGetLatestLedgerError() { - s.historyQ.On("Begin").Return(nil).Once() + s.historyQ.On("Begin", s.ctx).Return(nil).Once() s.historyQ.On("GetLastLedgerIngest", s.ctx).Return(uint32(100), nil).Once() s.historyQ.On("GetIngestVersion", s.ctx).Return(CurrentVersion, nil).Once() s.historyQ.On("GetLatestHistoryLedger", s.ctx).Return(uint32(0), errors.New("my error")) @@ -229,7 +228,7 @@ func (s *ResumeTestTestSuite) TestGetLatestLedgerError() { } func (s *ResumeTestTestSuite) TestLatestHistoryLedgerLessThanIngestLedger() { - s.historyQ.On("Begin").Return(nil).Once() + s.historyQ.On("Begin", s.ctx).Return(nil).Once() s.historyQ.On("GetLastLedgerIngest", s.ctx).Return(uint32(100), nil).Once() s.historyQ.On("GetIngestVersion", s.ctx).Return(CurrentVersion, nil).Once() s.historyQ.On("GetLatestHistoryLedger", s.ctx).Return(uint32(99), nil) @@ -243,7 +242,7 @@ func (s *ResumeTestTestSuite) TestLatestHistoryLedgerLessThanIngestLedger() { } func (s *ResumeTestTestSuite) TestLatestHistoryLedgerGreaterThanIngestLedger() { - s.historyQ.On("Begin").Return(nil).Once() + s.historyQ.On("Begin", s.ctx).Return(nil).Once() s.historyQ.On("GetLastLedgerIngest", s.ctx).Return(uint32(100), nil).Once() s.historyQ.On("GetIngestVersion", s.ctx).Return(CurrentVersion, nil).Once() s.historyQ.On("GetLatestHistoryLedger", s.ctx).Return(uint32(101), nil) @@ -257,7 +256,7 @@ func (s *ResumeTestTestSuite) TestLatestHistoryLedgerGreaterThanIngestLedger() { } func (s *ResumeTestTestSuite) mockSuccessfulIngestion() { - s.historyQ.On("Begin").Return(nil).Once() + s.historyQ.On("Begin", s.ctx).Return(nil).Once() s.historyQ.On("GetLastLedgerIngest", s.ctx).Return(uint32(100), nil).Once() s.historyQ.On("GetIngestVersion", s.ctx).Return(CurrentVersion, nil).Once() s.historyQ.On("GetLatestHistoryLedger", s.ctx).Return(uint32(100), nil) @@ -301,7 +300,7 @@ func (s *ResumeTestTestSuite) TestBumpIngestLedger() { }, }, nil).Once() - s.historyQ.On("Begin").Return(nil).Once() + s.historyQ.On("Begin", s.ctx).Return(nil).Once() s.historyQ.On("GetLastLedgerIngest", s.ctx).Return(uint32(101), nil).Once() s.stellarCoreClient.On( @@ -311,9 +310,6 @@ func (s *ResumeTestTestSuite) TestBumpIngestLedger() { int32(101), ).Return(errors.New("my error")).Once() - // Skips state verification but ensures maybeVerifyState called - s.historyQ.On("GetExpStateInvalid", s.ctx).Return(true, nil).Once() - next, err := resumeState{latestSuccessfullyProcessedLedger: 99}.run(s.system) s.Assert().NoError(err) s.Assert().Equal( @@ -340,7 +336,7 @@ func (s *ResumeTestTestSuite) TestIngestAllMasterNode() { } func (s *ResumeTestTestSuite) TestErrorSettingCursorIgnored() { - s.historyQ.On("Begin").Return(nil).Once() + s.historyQ.On("Begin", s.ctx).Return(nil).Once() s.historyQ.On("GetLastLedgerIngest", s.ctx).Return(uint32(100), nil).Once() s.historyQ.On("GetIngestVersion", s.ctx).Return(CurrentVersion, nil).Once() s.historyQ.On("GetLatestHistoryLedger", s.ctx).Return(uint32(100), nil) @@ -378,8 +374,38 @@ func (s *ResumeTestTestSuite) TestErrorSettingCursorIgnored() { ) } +func (s *ResumeTestTestSuite) TestRebuildTradeAggregationBucketsError() { + s.historyQ.On("Begin", s.ctx).Return(nil).Once() + s.historyQ.On("GetLastLedgerIngest", s.ctx).Return(uint32(100), nil).Once() + s.historyQ.On("GetIngestVersion", s.ctx).Return(CurrentVersion, nil).Once() + s.historyQ.On("GetLatestHistoryLedger", s.ctx).Return(uint32(100), nil) + + s.runner.On("RunAllProcessorsOnLedger", mock.AnythingOfType("xdr.LedgerCloseMeta")). + Run(func(args mock.Arguments) { + meta := args.Get(0).(xdr.LedgerCloseMeta) + s.Assert().Equal(uint32(101), meta.LedgerSequence()) + }). + Return( + ledgerStats{}, + nil, + ).Once() + + s.historyQ.On("RebuildTradeAggregationBuckets", s.ctx, uint32(101), uint32(101), 0). + Return(errors.New("transient error")).Once() + + next, err := resumeState{latestSuccessfullyProcessedLedger: 100}.run(s.system) + s.Assert().EqualError(err, "error rebuilding trade aggregations: transient error") + s.Assert().Equal( + transition{ + node: resumeState{latestSuccessfullyProcessedLedger: 100}, + sleepDuration: defaultSleep, + }, + next, + ) +} + func (s *ResumeTestTestSuite) TestReapingObjectsDisabled() { - s.historyQ.On("Begin").Return(nil).Once() + s.historyQ.On("Begin", s.ctx).Return(nil).Once() s.historyQ.On("GetLastLedgerIngest", s.ctx).Return(uint32(100), nil).Once() s.historyQ.On("GetIngestVersion", s.ctx).Return(CurrentVersion, nil).Once() s.historyQ.On("GetLatestHistoryLedger", s.ctx).Return(uint32(100), nil) @@ -423,7 +449,7 @@ func (s *ResumeTestTestSuite) TestErrorReapingObjectsIgnored() { defer func() { s.system.config.EnableReapLookupTables = false }() - s.historyQ.On("Begin").Return(nil).Once() + s.historyQ.On("Begin", s.ctx).Return(nil).Once() s.historyQ.On("GetLastLedgerIngest", s.ctx).Return(uint32(100), nil).Once() s.historyQ.On("GetIngestVersion", s.ctx).Return(CurrentVersion, nil).Once() s.historyQ.On("GetLatestHistoryLedger", s.ctx).Return(uint32(100), nil) @@ -451,7 +477,7 @@ func (s *ResumeTestTestSuite) TestErrorReapingObjectsIgnored() { s.historyQ.On("RebuildTradeAggregationBuckets", s.ctx, uint32(101), uint32(101), 0).Return(nil).Once() // Reap lookup tables: s.ledgerBackend.On("GetLatestLedgerSequence", s.ctx).Return(uint32(101), nil) - s.historyQ.On("Begin").Return(nil).Once() + s.historyQ.On("Begin", s.ctx).Return(nil).Once() s.historyQ.On("GetLastLedgerIngest", s.ctx).Return(uint32(100), nil).Once() s.historyQ.On("ReapLookupTables", mock.AnythingOfType("*context.timerCtx"), mock.Anything).Return(nil, nil, errors.New("error reaping objects")).Once() s.historyQ.On("Rollback").Return(nil).Once() diff --git a/services/horizon/internal/ingest/stress_test.go b/services/horizon/internal/ingest/stress_test.go index 337e96acc5..3661ad2e82 100644 --- a/services/horizon/internal/ingest/stress_test.go +++ b/services/horizon/internal/ingest/stress_test.go @@ -67,14 +67,14 @@ func (s *StressTestStateTestSuite) TestBounds() { func (s *StressTestStateTestSuite) TestBeginReturnsError() { *s.historyQ = mockDBQ{} s.historyQ.On("GetTx").Return(nil).Once() - s.historyQ.On("Begin").Return(errors.New("my error")).Once() + s.historyQ.On("Begin", s.ctx).Return(errors.New("my error")).Once() err := s.system.StressTest(10, 4) s.Assert().EqualError(err, "Error starting a transaction: my error") } func (s *StressTestStateTestSuite) TestGetLastLedgerIngestReturnsError() { - s.historyQ.On("Begin").Return(nil).Once() + s.historyQ.On("Begin", s.ctx).Return(nil).Once() s.historyQ.On("GetLastLedgerIngest", s.ctx).Return(uint32(0), errors.New("my error")).Once() err := s.system.StressTest(10, 4) @@ -82,7 +82,7 @@ func (s *StressTestStateTestSuite) TestGetLastLedgerIngestReturnsError() { } func (s *StressTestStateTestSuite) TestGetLastLedgerIngestNonEmpty() { - s.historyQ.On("Begin").Return(nil).Once() + s.historyQ.On("Begin", s.ctx).Return(nil).Once() s.historyQ.On("GetLastLedgerIngest", s.ctx).Return(uint32(100), nil).Once() err := s.system.StressTest(10, 4) @@ -90,7 +90,7 @@ func (s *StressTestStateTestSuite) TestGetLastLedgerIngestNonEmpty() { } func (s *StressTestStateTestSuite) TestRunAllProcessorsOnLedgerReturnsError() { - s.historyQ.On("Begin").Return(nil).Once() + s.historyQ.On("Begin", s.ctx).Return(nil).Once() s.historyQ.On("GetLastLedgerIngest", s.ctx).Return(uint32(0), nil).Once() s.runner.On("RunAllProcessorsOnLedger", mock.AnythingOfType("xdr.LedgerCloseMeta")).Return( @@ -103,7 +103,7 @@ func (s *StressTestStateTestSuite) TestRunAllProcessorsOnLedgerReturnsError() { } func (s *StressTestStateTestSuite) TestUpdateLastLedgerIngestReturnsError() { - s.historyQ.On("Begin").Return(nil).Once() + s.historyQ.On("Begin", s.ctx).Return(nil).Once() s.historyQ.On("GetLastLedgerIngest", s.ctx).Return(uint32(0), nil).Once() s.runner.On("RunAllProcessorsOnLedger", mock.AnythingOfType("xdr.LedgerCloseMeta")).Return( ledgerStats{}, @@ -116,7 +116,7 @@ func (s *StressTestStateTestSuite) TestUpdateLastLedgerIngestReturnsError() { } func (s *StressTestStateTestSuite) TestCommitReturnsError() { - s.historyQ.On("Begin").Return(nil).Once() + s.historyQ.On("Begin", s.ctx).Return(nil).Once() s.historyQ.On("GetLastLedgerIngest", s.ctx).Return(uint32(0), nil).Once() s.runner.On("RunAllProcessorsOnLedger", mock.AnythingOfType("xdr.LedgerCloseMeta")).Return( ledgerStats{}, @@ -130,7 +130,7 @@ func (s *StressTestStateTestSuite) TestCommitReturnsError() { } func (s *StressTestStateTestSuite) TestSucceeds() { - s.historyQ.On("Begin").Return(nil).Once() + s.historyQ.On("Begin", s.ctx).Return(nil).Once() s.historyQ.On("GetLastLedgerIngest", s.ctx).Return(uint32(0), nil).Once() s.runner.On("RunAllProcessorsOnLedger", mock.AnythingOfType("xdr.LedgerCloseMeta")).Return( ledgerStats{}, diff --git a/services/horizon/internal/ingest/verify.go b/services/horizon/internal/ingest/verify.go index ff8d047252..bf1ddbe5b5 100644 --- a/services/horizon/internal/ingest/verify.go +++ b/services/horizon/internal/ingest/verify.go @@ -1,6 +1,7 @@ package ingest import ( + "bytes" "context" "database/sql" "encoding/hex" @@ -11,10 +12,10 @@ import ( "github.com/prometheus/client_golang/prometheus" "github.com/stellar/go/ingest" + "github.com/stellar/go/ingest/verify" "github.com/stellar/go/services/horizon/internal/db2" "github.com/stellar/go/services/horizon/internal/db2/history" "github.com/stellar/go/services/horizon/internal/ingest/processors" - "github.com/stellar/go/services/horizon/internal/ingest/verify" "github.com/stellar/go/support/errors" logpkg "github.com/stellar/go/support/log" "github.com/stellar/go/xdr" @@ -29,7 +30,7 @@ const assetStatsBatchSize = 500 // check them. // There is a test that checks it, to fix it: update the actual `verifyState` // method instead of just updating this value! -const stateVerifierExpectedIngestionVersion = 15 +const stateVerifierExpectedIngestionVersion = 18 // verifyState is called as a go routine from pipeline post hook every 64 // ledgers. It checks if the state is correct. If another go routine is already @@ -62,7 +63,7 @@ func (s *system) verifyState(verifyAgainstLatestCheckpoint bool) error { historyQ := s.historyQ.CloneIngestionQ() defer historyQ.Rollback() - err := historyQ.BeginTx(&sql.TxOptions{ + err := historyQ.BeginTx(s.ctx, &sql.TxOptions{ Isolation: sql.LevelRepeatableRead, ReadOnly: true, }) @@ -70,8 +71,15 @@ func (s *system) verifyState(verifyAgainstLatestCheckpoint bool) error { return errors.Wrap(err, "Error starting transaction") } + ctx := s.ctx + if s.config.StateVerificationTimeout > 0 { + var cancel context.CancelFunc + ctx, cancel = context.WithTimeout(s.ctx, s.config.StateVerificationTimeout) + defer cancel() + } + // Ensure the ledger is a checkpoint ledger - ledgerSequence, err := historyQ.GetLastLedgerIngestNonBlocking(s.ctx) + ledgerSequence, err := historyQ.GetLastLedgerIngestNonBlocking(ctx) if err != nil { return errors.Wrap(err, "Error running historyQ.GetLastLedgerIngestNonBlocking") } @@ -81,8 +89,17 @@ func (s *system) verifyState(verifyAgainstLatestCheckpoint bool) error { "sequence": ledgerSequence, }) - if !s.checkpointManager.IsCheckpoint(ledgerSequence) { - localLog.Info("Current ledger is not a checkpoint ledger. Cancelling...") + if !s.runStateVerificationOnLedger(ledgerSequence) { + localLog.Info("Current ledger is not eligible for state verification. Canceling...") + return nil + } + + ok, err := historyQ.TryStateVerificationLock(ctx) + if err != nil { + return errors.Wrap(err, "Error acquiring state verification lock") + } + if !ok { + localLog.Info("State verification is already in progress. Canceling...") return nil } @@ -101,7 +118,7 @@ func (s *system) verifyState(verifyAgainstLatestCheckpoint bool) error { } if ledgerSequence < historyLatestSequence { - localLog.Info("Current ledger is old. Cancelling...") + localLog.Info("Current ledger is old. Canceling...") return nil } @@ -111,14 +128,14 @@ func (s *system) verifyState(verifyAgainstLatestCheckpoint bool) error { localLog.Info("Waiting for stellar-core to publish HAS...") select { - case <-s.ctx.Done(): + case <-ctx.Done(): localLog.Info("State verifier shut down...") return nil case <-time.After(5 * time.Second): // Wait for stellar-core to publish HAS retries++ if retries == 12 { - localLog.Info("Checkpoint not published. Cancelling...") + localLog.Info("Checkpoint not published. Canceling...") return nil } } @@ -131,8 +148,8 @@ func (s *system) verifyState(verifyAgainstLatestCheckpoint bool) error { defer func() { duration := time.Since(startTime).Seconds() if updateMetrics { - // Don't update metrics if context cancelled. - if s.ctx.Err() != context.Canceled { + // Don't update metrics if context canceled. + if ctx.Err() != context.Canceled { s.Metrics().StateVerifyDuration.Observe(float64(duration)) for typ, tot := range totalByType { s.Metrics().StateVerifyLedgerEntriesCount. @@ -146,24 +163,36 @@ func (s *system) verifyState(verifyAgainstLatestCheckpoint bool) error { localLog.Info("Creating state reader...") - stateReader, err := s.historyAdapter.GetState(s.ctx, ledgerSequence) + stateReader, err := s.historyAdapter.GetState(ctx, ledgerSequence) if err != nil { return errors.Wrap(err, "Error running GetState") } defer stateReader.Close() - verifier := verify.NewStateVerifier(stateReader, nil) + verifier := verify.NewStateVerifier(stateReader, func(entry xdr.LedgerEntry) (bool, xdr.LedgerEntry) { + entryType := entry.Data.Type + // Won't be persisting protocol 20 ContractData ledger entries (except for Stellar Asset Contract + // ledger entries) to the history db, therefore must not allow it + // to be counted in history state-verifier accumulators. + if entryType == xdr.LedgerEntryTypeConfigSetting || entryType == xdr.LedgerEntryTypeContractCode { + return true, entry + } + + return false, entry + }) - assetStats := processors.AssetStatSet{} + assetStats := processors.NewAssetStatSet() + createdExpirationEntries := map[xdr.Hash]uint32{} + var contractDataEntries []xdr.LedgerEntry total := int64(0) for { - var keys []xdr.LedgerKey - keys, err = verifier.GetLedgerKeys(verifyBatchSize) + var entries []xdr.LedgerEntry + entries, err = verifier.GetLedgerEntries(verifyBatchSize) if err != nil { - return errors.Wrap(err, "verifier.GetLedgerKeys") + return errors.Wrap(err, "verifier.GetLedgerEntries") } - if len(keys) == 0 { + if len(entries) == 0 { break } @@ -173,103 +202,151 @@ func (s *system) verifyState(verifyAgainstLatestCheckpoint bool) error { trustLines := make([]xdr.LedgerKeyTrustLine, 0, verifyBatchSize) cBalances := make([]xdr.ClaimableBalanceId, 0, verifyBatchSize) lPools := make([]xdr.PoolId, 0, verifyBatchSize) - for _, key := range keys { - switch key.Type { + for _, entry := range entries { + switch entry.Data.Type { case xdr.LedgerEntryTypeAccount: - accounts = append(accounts, key.Account.AccountId.Address()) + accounts = append(accounts, entry.Data.MustAccount().AccountId.Address()) totalByType["accounts"]++ case xdr.LedgerEntryTypeData: + key, keyErr := entry.LedgerKey() + if keyErr != nil { + return errors.Wrap(keyErr, "entry.LedgerKey") + } data = append(data, *key.Data) totalByType["data"]++ case xdr.LedgerEntryTypeOffer: - offers = append(offers, int64(key.Offer.OfferId)) + offers = append(offers, int64(entry.Data.MustOffer().OfferId)) totalByType["offers"]++ case xdr.LedgerEntryTypeTrustline: - trustLines = append(trustLines, *key.TrustLine) + key, keyErr := entry.LedgerKey() + if keyErr != nil { + return errors.Wrap(keyErr, "TrustlineEntry.LedgerKey") + } + trustLines = append(trustLines, key.MustTrustLine()) totalByType["trust_lines"]++ case xdr.LedgerEntryTypeClaimableBalance: - cBalances = append(cBalances, key.ClaimableBalance.BalanceId) + cBalances = append(cBalances, entry.Data.MustClaimableBalance().BalanceId) totalByType["claimable_balances"]++ case xdr.LedgerEntryTypeLiquidityPool: - lPools = append(lPools, key.LiquidityPool.LiquidityPoolId) + lPools = append(lPools, entry.Data.MustLiquidityPool().LiquidityPoolId) totalByType["liquidity_pools"]++ + case xdr.LedgerEntryTypeContractData: + // contract data is a special case. + // we don't store contract data entries in the db, + // however, we ingest contract data entries for asset stats. + if err = verifier.Write(entry); err != nil { + return err + } + contractDataEntries = append(contractDataEntries, entry) + totalByType["contract_data"]++ + case xdr.LedgerEntryTypeTtl: + // we don't store all expiration entries in the db, + // we will only verify expiration of contract balances in the horizon db. + if err = verifier.Write(entry); err != nil { + return err + } + totalByType["ttl"]++ + ttl := entry.Data.MustTtl() + createdExpirationEntries[ttl.KeyHash] = uint32(ttl.LiveUntilLedgerSeq) + totalByType["expiration"]++ default: - return errors.New("GetLedgerKeys return unexpected type") + return errors.New("GetLedgerEntries return unexpected type") } } - err = addAccountsToStateVerifier(s.ctx, verifier, historyQ, accounts) + err = addAccountsToStateVerifier(ctx, verifier, historyQ, accounts) if err != nil { return errors.Wrap(err, "addAccountsToStateVerifier failed") } - err = addDataToStateVerifier(s.ctx, verifier, historyQ, data) + err = addDataToStateVerifier(ctx, verifier, historyQ, data) if err != nil { return errors.Wrap(err, "addDataToStateVerifier failed") } - err = addOffersToStateVerifier(s.ctx, verifier, historyQ, offers) + err = addOffersToStateVerifier(ctx, verifier, historyQ, offers) if err != nil { return errors.Wrap(err, "addOffersToStateVerifier failed") } - err = addTrustLinesToStateVerifier(s.ctx, verifier, assetStats, historyQ, trustLines) + err = addTrustLinesToStateVerifier(ctx, verifier, assetStats, historyQ, trustLines) if err != nil { return errors.Wrap(err, "addTrustLinesToStateVerifier failed") } - err = addClaimableBalanceToStateVerifier(s.ctx, verifier, assetStats, historyQ, cBalances) + err = addClaimableBalanceToStateVerifier(ctx, verifier, assetStats, historyQ, cBalances) if err != nil { return errors.Wrap(err, "addClaimableBalanceToStateVerifier failed") } - err = addLiquidityPoolsToStateVerifier(s.ctx, verifier, assetStats, historyQ, lPools) + err = addLiquidityPoolsToStateVerifier(ctx, verifier, assetStats, historyQ, lPools) if err != nil { return errors.Wrap(err, "addLiquidityPoolsToStateVerifier failed") } - total += int64(len(keys)) + total += int64(len(entries)) localLog.WithField("total", total).Info("Batch added to StateVerifier") } + contractAssetStatSet := processors.NewContractAssetStatSet( + historyQ, + s.config.NetworkPassphrase, + map[xdr.Hash]uint32{}, + createdExpirationEntries, + map[xdr.Hash][2]uint32{}, + ledgerSequence, + ) + for i := range contractDataEntries { + entry := contractDataEntries[i] + if err = contractAssetStatSet.AddContractData(ctx, ingest.Change{ + Type: xdr.LedgerEntryTypeContractData, + Post: &entry, + }); err != nil { + return errors.Wrap(err, "Error ingesting contract data") + } + } + localLog.WithField("total", total).Info("Finished writing to StateVerifier") - countAccounts, err := historyQ.CountAccounts(s.ctx) + countAccounts, err := historyQ.CountAccounts(ctx) if err != nil { return errors.Wrap(err, "Error running historyQ.CountAccounts") } - countData, err := historyQ.CountAccountsData(s.ctx) + countData, err := historyQ.CountAccountsData(ctx) if err != nil { return errors.Wrap(err, "Error running historyQ.CountData") } - countOffers, err := historyQ.CountOffers(s.ctx) + countOffers, err := historyQ.CountOffers(ctx) if err != nil { return errors.Wrap(err, "Error running historyQ.CountOffers") } - countTrustLines, err := historyQ.CountTrustLines(s.ctx) + countTrustLines, err := historyQ.CountTrustLines(ctx) if err != nil { return errors.Wrap(err, "Error running historyQ.CountTrustLines") } - countClaimableBalances, err := historyQ.CountClaimableBalances(s.ctx) + countClaimableBalances, err := historyQ.CountClaimableBalances(ctx) if err != nil { return errors.Wrap(err, "Error running historyQ.CountClaimableBalances") } - countLiquidityPools, err := historyQ.CountLiquidityPools(s.ctx) + countLiquidityPools, err := historyQ.CountLiquidityPools(ctx) if err != nil { return errors.Wrap(err, "Error running historyQ.CountLiquidityPools") } - err = verifier.Verify(countAccounts + countData + countOffers + countTrustLines + countClaimableBalances + countLiquidityPools) + err = verifier.Verify( + countAccounts + countData + countOffers + countTrustLines + countClaimableBalances + + countLiquidityPools + int(totalByType["contract_data"]) + int(totalByType["ttl"]), + ) if err != nil { return errors.Wrap(err, "verifier.Verify failed") } - err = checkAssetStats(s.ctx, assetStats, historyQ) + err = checkAssetStats(ctx, assetStats, contractAssetStatSet, historyQ, s.config.NetworkPassphrase) if err != nil { return errors.Wrap(err, "checkAssetStats failed") } @@ -279,12 +356,51 @@ func (s *system) verifyState(verifyAgainstLatestCheckpoint bool) error { return nil } -func checkAssetStats(ctx context.Context, set processors.AssetStatSet, q history.IngestionQ) error { +func checkAssetStats( + ctx context.Context, + set processors.AssetStatSet, + contractAssetStatSet *processors.ContractAssetStatSet, + q history.IngestionQ, + networkPassphrase string, +) error { page := db2.PageQuery{ Order: "asc", Limit: assetStatsBatchSize, } + contractToAsset := contractAssetStatSet.GetAssetToContractMap() + assetStats := set.All() + var err error + assetStats, err = processors.IncludeContractIDsInAssetStats(networkPassphrase, assetStats, contractToAsset) + if err != nil { + return err + } + + all := map[string]history.ExpAssetStat{} + for _, assetStat := range assetStats { + // no need to handle the native asset because asset stats only + // include non-native assets. + all[assetStat.AssetCode+":"+assetStat.AssetIssuer] = assetStat + } + + contractToStats := map[xdr.Hash]history.ContractAssetStatRow{} + for _, row := range contractAssetStatSet.GetContractStats() { + var contractID xdr.Hash + copy(contractID[:], row.ContractID) + contractToStats[contractID] = row + } + + // only check contract asset balances which belong to stellar asset contracts + // because other balances may be forged. + var filteredBalances []history.ContractAssetBalance + for _, balance := range contractAssetStatSet.GetCreatedBalances() { + var contractID xdr.Hash + copy(contractID[:], balance.ContractID) + if _, ok := contractToAsset[contractID]; ok { + filteredBalances = append(filteredBalances, balance) + } + } + for { assetStats, err := q.GetAssetStats(ctx, "", "", page) if err != nil { @@ -295,8 +411,9 @@ func checkAssetStats(ctx context.Context, set processors.AssetStatSet, q history } for _, assetStat := range assetStats { - fromSet, removed := set.Remove(assetStat.AssetType, assetStat.AssetCode, assetStat.AssetIssuer) - if !removed { + key := assetStat.AssetCode + ":" + assetStat.AssetIssuer + fromSet, ok := all[key] + if !ok { return ingest.NewStateError( fmt.Errorf( "db contains asset stat with code %s issuer %s which is missing from HAS", @@ -304,8 +421,9 @@ func checkAssetStats(ctx context.Context, set processors.AssetStatSet, q history ), ) } + delete(all, key) - if fromSet != assetStat { + if !fromSet.Equals(assetStat.ExpAssetStat) { return ingest.NewStateError( fmt.Errorf( "db asset stat with code %s issuer %s does not match asset stat from HAS: expected=%v actual=%v", @@ -313,19 +431,155 @@ func checkAssetStats(ctx context.Context, set processors.AssetStatSet, q history ), ) } + + if contractID, ok := assetStat.GetContractID(); ok { + asset := contractToAsset[contractID] + if asset == nil { + return ingest.NewStateError( + fmt.Errorf( + "asset %v has contract id %v in db but contract id is not in HAS", + key, + contractID, + ), + ) + } + + var assetType xdr.AssetType + var code, issuer string + if err := asset.Extract(&assetType, &code, &issuer); err != nil { + return ingest.NewStateError( + fmt.Errorf( + "could not parse asset %v", + asset, + ), + ) + } + + if assetType != assetStat.AssetType || + assetStat.AssetCode != code || + assetStat.AssetIssuer != issuer { + return ingest.NewStateError( + fmt.Errorf( + "contract id %v mapped to asset %v in db does not match HAS %v", + contractID, + key, + code+":"+issuer, + ), + ) + } + + entry, ok := contractToStats[contractID] + if !ok { + entry = history.ContractAssetStatRow{ + ContractID: contractID[:], + Stat: history.ContractStat{ + ActiveBalance: "0", + ActiveHolders: 0, + ArchivedBalance: "0", + ArchivedHolders: 0, + }, + } + } + if assetStat.Contracts != entry.Stat { + return ingest.NewStateError( + fmt.Errorf( + "contract stats for contract id %v in db %v does not match HAS %v", + contractID, + assetStat.Contracts, + entry.Stat, + ), + ) + } + + delete(contractToAsset, contractID) + } } page.Cursor = assetStats[len(assetStats)-1].PagingToken() } - if len(set) > 0 { + if len(all) > 0 { return ingest.NewStateError( fmt.Errorf( "HAS contains %d more asset stats than db", - len(set), + len(all), ), ) } + + if err := checkContractBalances(ctx, filteredBalances, q); err != nil { + return err + } + return nil +} + +func checkContractBalances( + ctx context.Context, + balances []history.ContractAssetBalance, + q history.IngestionQ, +) error { + for i := 0; i < len(balances); { + end := i + assetStatsBatchSize + if end > len(balances) { + end = len(balances) + } + + subset := balances[i:end] + var keys []xdr.Hash + byKey := map[xdr.Hash]history.ContractAssetBalance{} + for _, balance := range subset { + var key xdr.Hash + copy(key[:], balance.KeyHash) + keys = append(keys, key) + byKey[key] = balance + } + + rows, err := q.GetContractAssetBalances(ctx, keys) + if err != nil { + return err + } + + for _, row := range rows { + var key xdr.Hash + copy(key[:], row.KeyHash) + expected := byKey[key] + + if !bytes.Equal(row.ContractID, expected.ContractID) { + return ingest.NewStateError( + fmt.Errorf( + "contract balance %v has contract %v in HAS but is %v in db", + key, + expected.ContractID, + row.ContractID, + ), + ) + } + + if row.ExpirationLedger != expected.ExpirationLedger { + return ingest.NewStateError( + fmt.Errorf( + "contract balance %v has expiration %v in HAS but is %v in db", + key, + expected.ExpirationLedger, + row.ExpirationLedger, + ), + ) + } + + if row.Amount != expected.Amount { + return ingest.NewStateError( + fmt.Errorf( + "contract balance %v has amount %v in HAS but is %v in db", + key, + expected.Amount, + row.Amount, + ), + ) + } + } + + i = end + } return nil } @@ -672,6 +926,11 @@ func addClaimableBalanceToStateVerifier( return errors.Wrap(err, "Error running history.Q.GetClaimableBalancesByID") } + cBalancesClaimants, err := q.GetClaimantsByClaimableBalances(ctx, idStrings) + if err != nil { + return errors.Wrap(err, "Error running history.Q.GetClaimantsByClaimableBalances") + } + for _, row := range cBalances { claimants := []xdr.Claimant{} for _, claimant := range row.Claimants { @@ -684,6 +943,31 @@ func addClaimableBalanceToStateVerifier( }) } claimants = xdr.SortClaimantsByDestination(claimants) + + // Check if balances in claimable_balance_claimants table match. + if len(claimants) != len(cBalancesClaimants[row.BalanceID]) { + return ingest.NewStateError( + fmt.Errorf( + "claimable_balance_claimants length (%d) for claimants doesn't match claimable_balance table (%d)", + len(cBalancesClaimants[row.BalanceID]), len(claimants), + ), + ) + } + + for i, claimant := range claimants { + if claimant.MustV0().Destination.Address() != cBalancesClaimants[row.BalanceID][i].Destination || + row.LastModifiedLedger != cBalancesClaimants[row.BalanceID][i].LastModifiedLedger { + return fmt.Errorf( + "claimable_balance_claimants table for balance %s does not match. expectedDestination=%s actualDestination=%s, expectedLastModifiedLedger=%d actualLastModifiedLedger=%d", + row.BalanceID, + claimant.MustV0().Destination.Address(), + cBalancesClaimants[row.BalanceID][i].Destination, + row.LastModifiedLedger, + cBalancesClaimants[row.BalanceID][i].LastModifiedLedger, + ) + } + } + var balanceID xdr.ClaimableBalanceId if err := xdr.SafeUnmarshalHex(row.BalanceID, &balanceID); err != nil { return err diff --git a/services/horizon/internal/ingest/verify_range_state_test.go b/services/horizon/internal/ingest/verify_range_state_test.go index 49a4e4175d..7440f7dce0 100644 --- a/services/horizon/internal/ingest/verify_range_state_test.go +++ b/services/horizon/internal/ingest/verify_range_state_test.go @@ -15,7 +15,6 @@ import ( "github.com/stretchr/testify/mock" "github.com/stretchr/testify/suite" - "github.com/stellar/go/historyarchive" "github.com/stellar/go/ingest" "github.com/stellar/go/ingest/ledgerbackend" "github.com/stellar/go/keypair" @@ -47,12 +46,12 @@ func (s *VerifyRangeStateTestSuite) SetupTest() { s.historyAdapter = &mockHistoryArchiveAdapter{} s.runner = &mockProcessorsRunner{} s.system = &system{ - ctx: s.ctx, - historyQ: s.historyQ, - historyAdapter: s.historyAdapter, - ledgerBackend: s.ledgerBackend, - runner: s.runner, - checkpointManager: historyarchive.NewCheckpointManager(64), + ctx: s.ctx, + historyQ: s.historyQ, + historyAdapter: s.historyAdapter, + ledgerBackend: s.ledgerBackend, + runner: s.runner, + runStateVerificationOnLedger: ledgerEligibleForStateVerification(64, 1), } s.system.initMetrics() @@ -106,7 +105,7 @@ func (s *VerifyRangeStateTestSuite) TestInvalidRange() { func (s *VerifyRangeStateTestSuite) TestBeginReturnsError() { // Recreate mock in this single test to remove Rollback assertion. *s.historyQ = mockDBQ{} - s.historyQ.On("Begin").Return(errors.New("my error")).Once() + s.historyQ.On("Begin", s.ctx).Return(errors.New("my error")).Once() next, err := verifyRangeState{fromLedger: 100, toLedger: 200}.run(s.system) s.Assert().Error(err) @@ -118,7 +117,7 @@ func (s *VerifyRangeStateTestSuite) TestBeginReturnsError() { } func (s *VerifyRangeStateTestSuite) TestGetLastLedgerIngestReturnsError() { - s.historyQ.On("Begin").Return(nil).Once() + s.historyQ.On("Begin", s.ctx).Return(nil).Once() s.historyQ.On("GetLastLedgerIngest", s.ctx).Return(uint32(0), errors.New("my error")).Once() next, err := verifyRangeState{fromLedger: 100, toLedger: 200}.run(s.system) @@ -131,7 +130,7 @@ func (s *VerifyRangeStateTestSuite) TestGetLastLedgerIngestReturnsError() { } func (s *VerifyRangeStateTestSuite) TestGetLastLedgerIngestNonEmpty() { - s.historyQ.On("Begin").Return(nil).Once() + s.historyQ.On("Begin", s.ctx).Return(nil).Once() s.historyQ.On("GetLastLedgerIngest", s.ctx).Return(uint32(100), nil).Once() next, err := verifyRangeState{fromLedger: 100, toLedger: 200}.run(s.system) @@ -144,7 +143,7 @@ func (s *VerifyRangeStateTestSuite) TestGetLastLedgerIngestNonEmpty() { } func (s *VerifyRangeStateTestSuite) TestRunHistoryArchiveIngestionReturnsError() { - s.historyQ.On("Begin").Return(nil).Once() + s.historyQ.On("Begin", s.ctx).Return(nil).Once() s.historyQ.On("GetLastLedgerIngest", s.ctx).Return(uint32(0), nil).Once() s.ledgerBackend.On("PrepareRange", s.ctx, ledgerbackend.BoundedRange(100, 200)).Return(nil).Once() @@ -160,7 +159,7 @@ func (s *VerifyRangeStateTestSuite) TestRunHistoryArchiveIngestionReturnsError() }, } s.ledgerBackend.On("GetLedger", s.ctx, uint32(100)).Return(meta, nil).Once() - s.runner.On("RunHistoryArchiveIngestion", uint32(100), MaxSupportedProtocolVersion, xdr.Hash{1, 2, 3}).Return(ingest.StatsChangeProcessorResults{}, errors.New("my error")).Once() + s.runner.On("RunHistoryArchiveIngestion", uint32(100), false, MaxSupportedProtocolVersion, xdr.Hash{1, 2, 3}).Return(ingest.StatsChangeProcessorResults{}, errors.New("my error")).Once() next, err := verifyRangeState{fromLedger: 100, toLedger: 200}.run(s.system) s.Assert().Error(err) @@ -172,7 +171,7 @@ func (s *VerifyRangeStateTestSuite) TestRunHistoryArchiveIngestionReturnsError() } func (s *VerifyRangeStateTestSuite) TestSuccess() { - s.historyQ.On("Begin").Return(nil).Once() + s.historyQ.On("Begin", s.ctx).Return(nil).Once() s.historyQ.On("GetLastLedgerIngest", s.ctx).Return(uint32(0), nil).Once() s.ledgerBackend.On("PrepareRange", s.ctx, ledgerbackend.BoundedRange(100, 200)).Return(nil).Once() @@ -188,13 +187,13 @@ func (s *VerifyRangeStateTestSuite) TestSuccess() { }, } s.ledgerBackend.On("GetLedger", s.ctx, uint32(100)).Return(meta, nil).Once() - s.runner.On("RunHistoryArchiveIngestion", uint32(100), MaxSupportedProtocolVersion, xdr.Hash{1, 2, 3}).Return(ingest.StatsChangeProcessorResults{}, nil).Once() + s.runner.On("RunHistoryArchiveIngestion", uint32(100), false, MaxSupportedProtocolVersion, xdr.Hash{1, 2, 3}).Return(ingest.StatsChangeProcessorResults{}, nil).Once() s.historyQ.On("UpdateLastLedgerIngest", s.ctx, uint32(100)).Return(nil).Once() s.historyQ.On("Commit").Return(nil).Once() for i := uint32(101); i <= 200; i++ { - s.historyQ.On("Begin").Return(nil).Once() + s.historyQ.On("Begin", s.ctx).Return(nil).Once() meta := xdr.LedgerCloseMeta{ V0: &xdr.LedgerCloseMetaV0{ @@ -228,7 +227,7 @@ func (s *VerifyRangeStateTestSuite) TestSuccess() { // Bartek: looks like this test really tests the state verifier. Instead, I think we should just ensure // data is passed so a single account would be enough to test if the FSM state works correctly. func (s *VerifyRangeStateTestSuite) TestSuccessWithVerify() { - s.historyQ.On("Begin").Return(nil).Once() + s.historyQ.On("Begin", s.ctx).Return(nil).Once() s.historyQ.On("GetLastLedgerIngest", s.ctx).Return(uint32(0), nil).Once() s.ledgerBackend.On("PrepareRange", s.ctx, ledgerbackend.BoundedRange(100, 110)).Return(nil).Once() @@ -244,13 +243,13 @@ func (s *VerifyRangeStateTestSuite) TestSuccessWithVerify() { }, } s.ledgerBackend.On("GetLedger", s.ctx, uint32(100)).Return(meta, nil).Once() - s.runner.On("RunHistoryArchiveIngestion", uint32(100), MaxSupportedProtocolVersion, xdr.Hash{1, 2, 3}).Return(ingest.StatsChangeProcessorResults{}, nil).Once() + s.runner.On("RunHistoryArchiveIngestion", uint32(100), false, MaxSupportedProtocolVersion, xdr.Hash{1, 2, 3}).Return(ingest.StatsChangeProcessorResults{}, nil).Once() s.historyQ.On("UpdateLastLedgerIngest", s.ctx, uint32(100)).Return(nil).Once() s.historyQ.On("Commit").Return(nil).Once() for i := uint32(101); i <= 110; i++ { - s.historyQ.On("Begin").Return(nil).Once() + s.historyQ.On("Begin", s.ctx).Return(nil).Once() meta := xdr.LedgerCloseMeta{ V0: &xdr.LedgerCloseMetaV0{ @@ -276,13 +275,14 @@ func (s *VerifyRangeStateTestSuite) TestSuccessWithVerify() { clonedQ := &mockDBQ{} s.historyQ.On("CloneIngestionQ").Return(clonedQ).Once() - clonedQ.On("BeginTx", mock.AnythingOfType("*sql.TxOptions")).Run(func(args mock.Arguments) { - arg := args.Get(0).(*sql.TxOptions) + clonedQ.On("BeginTx", s.ctx, mock.AnythingOfType("*sql.TxOptions")).Run(func(args mock.Arguments) { + arg := args.Get(1).(*sql.TxOptions) s.Assert().Equal(sql.LevelRepeatableRead, arg.Isolation) s.Assert().True(arg.ReadOnly) }).Return(nil).Once() clonedQ.On("Rollback").Return(nil).Once() clonedQ.On("GetLastLedgerIngestNonBlocking", s.ctx).Return(uint32(63), nil).Once() + clonedQ.On("TryStateVerificationLock", s.ctx).Return(true, nil).Once() mockChangeReader := &ingest.MockChangeReader{} mockChangeReader.On("Close").Return(nil).Once() mockAccountID := "GACMZD5VJXTRLKVET72CETCYKELPNCOTTBDC6DHFEUPLG5DHEK534JQX" @@ -541,38 +541,54 @@ func (s *VerifyRangeStateTestSuite) TestSuccessWithVerify() { // TODO: add accounts data, trustlines and asset stats clonedQ.MockQData.On("CountAccountsData", s.ctx).Return(0, nil).Once() clonedQ.MockQAssetStats.On("CountTrustLines", s.ctx).Return(0, nil).Once() + clonedQ.MockQAssetStats.On("CountContractIDs", s.ctx).Return(0, nil).Once() clonedQ.MockQAssetStats.On("GetAssetStats", s.ctx, "", "", db2.PageQuery{ Order: "asc", Limit: assetStatsBatchSize, - }).Return([]history.ExpAssetStat{ + }).Return([]history.AssetAndContractStat{ // Created by liquidity pool: { - AssetType: xdr.AssetTypeAssetTypeCreditAlphanum4, - AssetCode: "USD", - AssetIssuer: "GC3C4AKRBQLHOJ45U4XG35ESVWRDECWO5XLDGYADO6DPR3L7KIDVUMML", - Accounts: history.ExpAssetStatAccounts{ - LiquidityPools: 1, - }, - Balances: history.ExpAssetStatBalances{ - Authorized: "0", - AuthorizedToMaintainLiabilities: "0", - ClaimableBalances: "0", - LiquidityPools: "450", - Unauthorized: "0", + ExpAssetStat: history.ExpAssetStat{ + AssetType: xdr.AssetTypeAssetTypeCreditAlphanum4, + AssetCode: "USD", + AssetIssuer: "GC3C4AKRBQLHOJ45U4XG35ESVWRDECWO5XLDGYADO6DPR3L7KIDVUMML", + Accounts: history.ExpAssetStatAccounts{ + LiquidityPools: 1, + }, + Balances: history.ExpAssetStatBalances{ + Authorized: "0", + AuthorizedToMaintainLiabilities: "0", + ClaimableBalances: "0", + LiquidityPools: "450", + Unauthorized: "0", + }, + Amount: "0", }, - Amount: "0", - }}, nil).Once() + }, + }, nil).Once() clonedQ.MockQAssetStats.On("GetAssetStats", s.ctx, "", "", db2.PageQuery{ Cursor: "USD_GC3C4AKRBQLHOJ45U4XG35ESVWRDECWO5XLDGYADO6DPR3L7KIDVUMML_credit_alphanum4", Order: "asc", Limit: assetStatsBatchSize, - }).Return([]history.ExpAssetStat{}, nil).Once() + }).Return([]history.AssetAndContractStat{}, nil).Once() clonedQ.MockQClaimableBalances.On("CountClaimableBalances", s.ctx).Return(1, nil).Once() clonedQ.MockQClaimableBalances. On("GetClaimableBalancesByID", s.ctx, []string{balanceIDStr}). Return([]history.ClaimableBalance{claimableBalance}, nil).Once() + clonedQ.MockQClaimableBalances. + On("GetClaimantsByClaimableBalances", s.ctx, []string{balanceIDStr}). + Return(map[string][]history.ClaimableBalanceClaimant{ + claimableBalance.BalanceID: { + { + BalanceID: claimableBalance.BalanceID, + Destination: claimableBalance.Claimants[0].Destination, + LastModifiedLedger: claimableBalance.LastModifiedLedger, + }, + }, + }, nil).Once() + clonedQ.MockQLiquidityPools.On("CountLiquidityPools", s.ctx).Return(1, nil).Once() clonedQ.MockQLiquidityPools. On("GetLiquidityPoolsByID", s.ctx, []string{liquidityPool.PoolID}). @@ -590,7 +606,15 @@ func (s *VerifyRangeStateTestSuite) TestSuccessWithVerify() { } func (s *VerifyRangeStateTestSuite) TestVerifyFailsWhenAssetStatsMismatch() { - set := processors.AssetStatSet{} + set := processors.NewAssetStatSet() + contractAssetStatsSet := processors.NewContractAssetStatSet( + s.historyQ, + s.system.config.NetworkPassphrase, + map[xdr.Hash]uint32{}, + map[xdr.Hash]uint32{}, + map[xdr.Hash][2]uint32{}, + 100, + ) trustLineIssuer := xdr.MustAddress("GBRPYHIL2CI3FNQ4BXLFMNDLFJUNPU2HY3ZMFSHONUCEOASW7QC7OX2H") set.AddTrustline( @@ -608,33 +632,35 @@ func (s *VerifyRangeStateTestSuite) TestVerifyFailsWhenAssetStatsMismatch() { }, ) - stat := history.ExpAssetStat{ - AssetType: xdr.AssetTypeAssetTypeCreditAlphanum4, - AssetCode: "EUR", - AssetIssuer: trustLineIssuer.Address(), - Accounts: history.ExpAssetStatAccounts{ - Unauthorized: 1, - }, - Balances: history.ExpAssetStatBalances{ - Authorized: "0", - AuthorizedToMaintainLiabilities: "0", - Unauthorized: "123", + stat := history.AssetAndContractStat{ + ExpAssetStat: history.ExpAssetStat{ + AssetType: xdr.AssetTypeAssetTypeCreditAlphanum4, + AssetCode: "EUR", + AssetIssuer: trustLineIssuer.Address(), + Accounts: history.ExpAssetStatAccounts{ + Unauthorized: 1, + }, + Balances: history.ExpAssetStatBalances{ + Authorized: "0", + AuthorizedToMaintainLiabilities: "0", + Unauthorized: "123", + }, + Amount: "0", + NumAccounts: 0, }, - Amount: "0", - NumAccounts: 0, } s.historyQ.MockQAssetStats.On("GetAssetStats", s.ctx, "", "", db2.PageQuery{ Order: "asc", Limit: assetStatsBatchSize, - }).Return([]history.ExpAssetStat{stat}, nil).Once() + }).Return([]history.AssetAndContractStat{stat}, nil).Once() s.historyQ.MockQAssetStats.On("GetAssetStats", s.ctx, "", "", db2.PageQuery{ Cursor: stat.PagingToken(), Order: "asc", Limit: assetStatsBatchSize, - }).Return([]history.ExpAssetStat{}, nil).Once() + }).Return([]history.AssetAndContractStat{}, nil).Once() - err := checkAssetStats(s.ctx, set, s.historyQ) + err := checkAssetStats(s.ctx, set, contractAssetStatsSet, s.historyQ, s.system.config.NetworkPassphrase) s.Assert().Contains(err.Error(), fmt.Sprintf("db asset stat with code EUR issuer %s does not match asset stat from HAS", trustLineIssuer.Address())) // Satisfy the mock diff --git a/services/horizon/internal/ingest/verify_test.go b/services/horizon/internal/ingest/verify_test.go index 0b2b4d6761..901f21a0ca 100644 --- a/services/horizon/internal/ingest/verify_test.go +++ b/services/horizon/internal/ingest/verify_test.go @@ -1,16 +1,21 @@ package ingest import ( + "crypto/sha256" + "database/sql" "io" "math/rand" "regexp" "testing" + "time" + + "github.com/stretchr/testify/mock" "github.com/stellar/go/gxdr" - "github.com/stellar/go/historyarchive" "github.com/stellar/go/ingest" "github.com/stellar/go/randxdr" "github.com/stellar/go/services/horizon/internal/db2/history" + "github.com/stellar/go/services/horizon/internal/ingest/processors" "github.com/stellar/go/services/horizon/internal/test" "github.com/stellar/go/support/db" "github.com/stellar/go/xdr" @@ -108,24 +113,23 @@ func genLiquidityPool(tt *test.T, gen randxdr.Generator) xdr.LedgerEntryChange { return change } -func genTrustLine(tt *test.T, gen randxdr.Generator) xdr.LedgerEntryChange { +func genTrustLine(tt *test.T, gen randxdr.Generator, extra ...randxdr.Preset) xdr.LedgerEntryChange { change := xdr.LedgerEntryChange{} shape := &gxdr.LedgerEntryChange{} - gen.Next( - shape, - []randxdr.Preset{ - {randxdr.FieldEquals("type"), randxdr.SetU32(gxdr.LEDGER_ENTRY_CREATED.GetU32())}, - {randxdr.FieldEquals("created.lastModifiedLedgerSeq"), randxdr.SetPositiveNum32}, - {randxdr.FieldEquals("created.data.type"), randxdr.SetU32(gxdr.TRUSTLINE.GetU32())}, - {randxdr.FieldEquals("created.data.trustLine.flags"), randxdr.SetPositiveNum32}, - {randxdr.FieldEquals("created.data.trustLine.asset.alphaNum4.assetCode"), randxdr.SetAssetCode}, - {randxdr.FieldEquals("created.data.trustLine.asset.alphaNum12.assetCode"), randxdr.SetAssetCode}, - {randxdr.FieldEquals("created.data.trustLine.balance"), randxdr.SetPositiveNum64}, - {randxdr.FieldEquals("created.data.trustLine.limit"), randxdr.SetPositiveNum64}, - {randxdr.FieldEquals("created.data.trustLine.ext.v1.liabilities.selling"), randxdr.SetPositiveNum64}, - {randxdr.FieldEquals("created.data.trustLine.ext.v1.liabilities.buying"), randxdr.SetPositiveNum64}, - }, - ) + presets := []randxdr.Preset{ + {randxdr.FieldEquals("type"), randxdr.SetU32(gxdr.LEDGER_ENTRY_CREATED.GetU32())}, + {randxdr.FieldEquals("created.lastModifiedLedgerSeq"), randxdr.SetPositiveNum32}, + {randxdr.FieldEquals("created.data.type"), randxdr.SetU32(gxdr.TRUSTLINE.GetU32())}, + {randxdr.FieldEquals("created.data.trustLine.flags"), randxdr.SetPositiveNum32}, + {randxdr.FieldEquals("created.data.trustLine.asset.alphaNum4.assetCode"), randxdr.SetAssetCode}, + {randxdr.FieldEquals("created.data.trustLine.asset.alphaNum12.assetCode"), randxdr.SetAssetCode}, + {randxdr.FieldEquals("created.data.trustLine.balance"), randxdr.SetPositiveNum64}, + {randxdr.FieldEquals("created.data.trustLine.limit"), randxdr.SetPositiveNum64}, + {randxdr.FieldEquals("created.data.trustLine.ext.v1.liabilities.selling"), randxdr.SetPositiveNum64}, + {randxdr.FieldEquals("created.data.trustLine.ext.v1.liabilities.buying"), randxdr.SetPositiveNum64}, + } + presets = append(presets, extra...) + gen.Next(shape, presets) tt.Assert.NoError(gxdr.Convert(shape, &change)) return change } @@ -156,14 +160,197 @@ func genClaimableBalance(tt *test.T, gen randxdr.Generator) xdr.LedgerEntryChang return change } -func TestStateVerifier(t *testing.T) { +func genContractCode(tt *test.T, gen randxdr.Generator) xdr.LedgerEntryChange { + change := xdr.LedgerEntryChange{} + shape := &gxdr.LedgerEntryChange{} + gen.Next( + shape, + []randxdr.Preset{ + {randxdr.FieldEquals("type"), randxdr.SetU32(gxdr.LEDGER_ENTRY_CREATED.GetU32())}, + {randxdr.FieldEquals("created.data.type"), randxdr.SetU32(gxdr.CONTRACT_CODE.GetU32())}, + }, + ) + tt.Assert.NoError(gxdr.Convert(shape, &change)) + return change +} + +func genTTL(tt *test.T, gen randxdr.Generator) xdr.LedgerEntryChange { + change := xdr.LedgerEntryChange{} + shape := &gxdr.LedgerEntryChange{} + gen.Next( + shape, + []randxdr.Preset{ + {randxdr.FieldEquals("type"), randxdr.SetU32(gxdr.LEDGER_ENTRY_CREATED.GetU32())}, + {randxdr.FieldEquals("created.data.type"), randxdr.SetU32(gxdr.TTL.GetU32())}, + {randxdr.FieldEquals("created.lastModifiedLedgerSeq"), randxdr.SetPositiveNum32}, + {randxdr.FieldEquals("created.data.ttl.liveUntilLedgerSeq"), randxdr.SetPositiveNum32}, + }, + ) + tt.Assert.NoError(gxdr.Convert(shape, &change)) + return change +} + +func genConfigSetting(tt *test.T, gen randxdr.Generator) xdr.LedgerEntryChange { + change := xdr.LedgerEntryChange{} + shape := &gxdr.LedgerEntryChange{} + gen.Next( + shape, + []randxdr.Preset{ + {randxdr.FieldEquals("type"), randxdr.SetU32(gxdr.LEDGER_ENTRY_CREATED.GetU32())}, + {randxdr.FieldEquals("created.data.type"), randxdr.SetU32(gxdr.CONFIG_SETTING.GetU32())}, + }, + ) + tt.Assert.NoError(gxdr.Convert(shape, &change)) + return change +} + +func genAssetContractMetadata(tt *test.T, gen randxdr.Generator) []xdr.LedgerEntryChange { + assetPreset := randxdr.Preset{ + randxdr.FieldEquals("created.data.trustLine.asset.type"), + randxdr.SetU32( + gxdr.ASSET_TYPE_CREDIT_ALPHANUM4.GetU32(), + gxdr.ASSET_TYPE_CREDIT_ALPHANUM12.GetU32(), + ), + } + trustline := genTrustLine(tt, gen, assetPreset) + assetContractMetadata := assetContractMetadataFromTrustline(tt, trustline) + + otherTrustline := genTrustLine(tt, gen, assetPreset) + otherAssetContractMetadata := assetContractMetadataFromTrustline(tt, otherTrustline) + + balance := balanceContractDataFromTrustline(tt, trustline) + otherBalance := balanceContractDataFromTrustline(tt, otherTrustline) + return []xdr.LedgerEntryChange{ + assetContractMetadata, + trustline, + balance, + ttlForContractData(tt, gen, balance), + otherAssetContractMetadata, + otherBalance, + ttlForContractData(tt, gen, otherBalance), + balanceContractDataFromTrustline(tt, genTrustLine(tt, gen, assetPreset)), + } +} + +func assetContractMetadataFromTrustline(tt *test.T, trustline xdr.LedgerEntryChange) xdr.LedgerEntryChange { + contractID, err := trustline.Created.Data.MustTrustLine().Asset.ToAsset().ContractID("") + tt.Assert.NoError(err) + var assetType xdr.AssetType + var code, issuer string + tt.Assert.NoError( + trustline.Created.Data.MustTrustLine().Asset.Extract(&assetType, &code, &issuer), + ) + ledgerData, err := processors.AssetToContractData(assetType == xdr.AssetTypeAssetTypeNative, code, issuer, contractID) + tt.Assert.NoError(err) + assetContractMetadata := xdr.LedgerEntryChange{ + Type: xdr.LedgerEntryChangeTypeLedgerEntryCreated, + Created: &xdr.LedgerEntry{ + LastModifiedLedgerSeq: trustline.Created.LastModifiedLedgerSeq, + Data: ledgerData, + }, + } + return assetContractMetadata +} + +func balanceContractDataFromTrustline(tt *test.T, trustline xdr.LedgerEntryChange) xdr.LedgerEntryChange { + contractID, err := trustline.Created.Data.MustTrustLine().Asset.ToAsset().ContractID("") + tt.Assert.NoError(err) + var assetType xdr.AssetType + var code, issuer string + trustlineData := trustline.Created.Data.MustTrustLine() + tt.Assert.NoError( + trustlineData.Asset.Extract(&assetType, &code, &issuer), + ) + assetContractMetadata := xdr.LedgerEntryChange{ + Type: xdr.LedgerEntryChangeTypeLedgerEntryCreated, + Created: &xdr.LedgerEntry{ + LastModifiedLedgerSeq: trustline.Created.LastModifiedLedgerSeq, + Data: processors.BalanceToContractData(contractID, *trustlineData.AccountId.Ed25519, uint64(trustlineData.Balance)), + }, + } + return assetContractMetadata +} + +func ttlForContractData(tt *test.T, gen randxdr.Generator, contractData xdr.LedgerEntryChange) xdr.LedgerEntryChange { + ledgerEntry := contractData.MustCreated() + lk, err := ledgerEntry.LedgerKey() + tt.Assert.NoError(err) + bin, err := lk.MarshalBinary() + tt.Assert.NoError(err) + keyHash := sha256.Sum256(bin) + ttl := genTTL(tt, gen) + ttl.Created.Data.Ttl.KeyHash = keyHash + return ttl +} + +func TestStateVerifierLockBusy(t *testing.T) { tt := test.Start(t) defer tt.Finish() test.ResetHorizonDB(t, tt.HorizonDB) q := &history.Q{&db.Session{DB: tt.HorizonDB}} + tt.Assert.NoError(q.BeginTx(tt.Ctx, &sql.TxOptions{})) + checkpointLedger := uint32(63) - changeProcessor := buildChangeProcessor(q, &ingest.StatsChangeProcessor{}, ledgerSource, checkpointLedger) + changeProcessor := buildChangeProcessor(q, &ingest.StatsChangeProcessor{}, ledgerSource, checkpointLedger, "") + + gen := randxdr.NewGenerator() + var changes []xdr.LedgerEntryChange + for i := 0; i < 10; i++ { + changes = append(changes, + genLiquidityPool(tt, gen), + genClaimableBalance(tt, gen), + genOffer(tt, gen), + genTrustLine(tt, gen), + genAccount(tt, gen), + genAccountData(tt, gen), + ) + } + for _, change := range ingest.GetChangesFromLedgerEntryChanges(changes) { + tt.Assert.NoError(changeProcessor.ProcessChange(tt.Ctx, change)) + } + tt.Assert.NoError(changeProcessor.Commit(tt.Ctx)) + + tt.Assert.NoError(q.Commit()) + + q.UpdateLastLedgerIngest(tt.Ctx, checkpointLedger) + + mockHistoryAdapter := &mockHistoryArchiveAdapter{} + sys := &system{ + ctx: tt.Ctx, + historyQ: q, + historyAdapter: mockHistoryAdapter, + runStateVerificationOnLedger: ledgerEligibleForStateVerification(64, 1), + config: Config{StateVerificationTimeout: time.Hour}, + } + sys.initMetrics() + + otherQ := &history.Q{q.Clone()} + tt.Assert.NoError(otherQ.BeginTx(tt.Ctx, &sql.TxOptions{ + Isolation: sql.LevelRepeatableRead, + ReadOnly: true, + })) + ok, err := otherQ.TryStateVerificationLock(tt.Ctx) + tt.Assert.NoError(err) + tt.Assert.True(ok) + + tt.Assert.NoError(sys.verifyState(false)) + mockHistoryAdapter.AssertExpectations(t) + + tt.Assert.NoError(otherQ.Rollback()) +} + +func TestStateVerifier(t *testing.T) { + tt := test.Start(t) + defer tt.Finish() + test.ResetHorizonDB(t, tt.HorizonDB) + q := &history.Q{&db.Session{DB: tt.HorizonDB}} + + tt.Assert.NoError(q.BeginTx(tt.Ctx, &sql.TxOptions{})) + + ledger := rand.Int31() + checkpointLedger := uint32(ledger - (ledger % 64) - 1) + changeProcessor := buildChangeProcessor(q, &ingest.StatsChangeProcessor{}, ledgerSource, checkpointLedger, "") mockChangeReader := &ingest.MockChangeReader{} gen := randxdr.NewGenerator() @@ -176,13 +363,23 @@ func TestStateVerifier(t *testing.T) { genTrustLine(tt, gen), genAccount(tt, gen), genAccountData(tt, gen), + genContractCode(tt, gen), + genConfigSetting(tt, gen), + genTTL(tt, gen), ) + changes = append(changes, genAssetContractMetadata(tt, gen)...) } + + coverage := map[xdr.LedgerEntryType]int{} for _, change := range ingest.GetChangesFromLedgerEntryChanges(changes) { mockChangeReader.On("Read").Return(change, nil).Once() tt.Assert.NoError(changeProcessor.ProcessChange(tt.Ctx, change)) + coverage[change.Type]++ } tt.Assert.NoError(changeProcessor.Commit(tt.Ctx)) + tt.Assert.Equal(len(xdr.LedgerEntryTypeMap), len(coverage)) + + tt.Assert.NoError(q.Commit()) q.UpdateLastLedgerIngest(tt.Ctx, checkpointLedger) @@ -190,13 +387,14 @@ func TestStateVerifier(t *testing.T) { mockChangeReader.On("Close").Return(nil).Once() mockHistoryAdapter := &mockHistoryArchiveAdapter{} - mockHistoryAdapter.On("GetState", tt.Ctx, uint32(checkpointLedger)).Return(mockChangeReader, nil).Once() + mockHistoryAdapter.On("GetState", mock.AnythingOfType("*context.timerCtx"), uint32(checkpointLedger)).Return(mockChangeReader, nil).Once() sys := &system{ - ctx: tt.Ctx, - historyQ: q, - historyAdapter: mockHistoryAdapter, - checkpointManager: historyarchive.NewCheckpointManager(64), + ctx: tt.Ctx, + historyQ: q, + historyAdapter: mockHistoryAdapter, + runStateVerificationOnLedger: ledgerEligibleForStateVerification(64, 1), + config: Config{StateVerificationTimeout: time.Hour}, } sys.initMetrics() diff --git a/services/horizon/internal/init.go b/services/horizon/internal/init.go index 4150a1e2a7..5d38c86ccf 100644 --- a/services/horizon/internal/init.go +++ b/services/horizon/internal/init.go @@ -5,16 +5,15 @@ import ( "net/http" "runtime" - "github.com/stellar/go/services/horizon/internal/paths" - "github.com/getsentry/raven-go" "github.com/prometheus/client_golang/prometheus" + "github.com/stellar/go/exp/orderbook" "github.com/stellar/go/services/horizon/internal/db2/history" "github.com/stellar/go/services/horizon/internal/ingest" + "github.com/stellar/go/services/horizon/internal/paths" "github.com/stellar/go/services/horizon/internal/simplepath" "github.com/stellar/go/services/horizon/internal/txsub" - "github.com/stellar/go/services/horizon/internal/txsub/sequence" "github.com/stellar/go/support/db" "github.com/stellar/go/support/log" ) @@ -93,34 +92,28 @@ func mustInitHorizonDB(app *App) { func initIngester(app *App) { var err error var coreSession db.SessionInterface - if !app.config.EnableCaptiveCoreIngestion { - coreSession = mustNewDBSession( - db.CoreSubservice, app.config.StellarCoreDatabaseURL, ingest.MaxDBConnections, ingest.MaxDBConnections, app.prometheusRegistry) - } app.ingester, err = ingest.NewSystem(ingest.Config{ CoreSession: coreSession, HistorySession: mustNewDBSession( db.IngestSubservice, app.config.DatabaseURL, ingest.MaxDBConnections, ingest.MaxDBConnections, app.prometheusRegistry, ), - NetworkPassphrase: app.config.NetworkPassphrase, - // TODO: - // Use the first archive for now. We don't have a mechanism to - // use multiple archives at the same time currently. - HistoryArchiveURL: app.config.HistoryArchiveURLs[0], - CheckpointFrequency: app.config.CheckpointFrequency, - StellarCoreURL: app.config.StellarCoreURL, - StellarCoreCursor: app.config.CursorName, - CaptiveCoreBinaryPath: app.config.CaptiveCoreBinaryPath, - CaptiveCoreStoragePath: app.config.CaptiveCoreStoragePath, - CaptiveCoreConfigUseDB: app.config.CaptiveCoreConfigUseDB, - CaptiveCoreToml: app.config.CaptiveCoreToml, - RemoteCaptiveCoreURL: app.config.RemoteCaptiveCoreURL, - EnableCaptiveCore: app.config.EnableCaptiveCoreIngestion, - DisableStateVerification: app.config.IngestDisableStateVerification, - EnableReapLookupTables: app.config.HistoryRetentionCount > 0, - EnableExtendedLogLedgerStats: app.config.IngestEnableExtendedLogLedgerStats, - RoundingSlippageFilter: app.config.RoundingSlippageFilter, - EnableIngestionFiltering: app.config.EnableIngestionFiltering, + NetworkPassphrase: app.config.NetworkPassphrase, + HistoryArchiveURLs: app.config.HistoryArchiveURLs, + CheckpointFrequency: app.config.CheckpointFrequency, + StellarCoreURL: app.config.StellarCoreURL, + StellarCoreCursor: app.config.CursorName, + CaptiveCoreBinaryPath: app.config.CaptiveCoreBinaryPath, + CaptiveCoreStoragePath: app.config.CaptiveCoreStoragePath, + CaptiveCoreConfigUseDB: app.config.CaptiveCoreConfigUseDB, + CaptiveCoreToml: app.config.CaptiveCoreToml, + RemoteCaptiveCoreURL: app.config.RemoteCaptiveCoreURL, + DisableStateVerification: app.config.IngestDisableStateVerification, + StateVerificationCheckpointFrequency: uint32(app.config.IngestStateVerificationCheckpointFrequency), + StateVerificationTimeout: app.config.IngestStateVerificationTimeout, + EnableReapLookupTables: app.config.HistoryRetentionCount > 0, + EnableExtendedLogLedgerStats: app.config.IngestEnableExtendedLogLedgerStats, + RoundingSlippageFilter: app.config.RoundingSlippageFilter, + EnableIngestionFiltering: app.config.EnableIngestionFiltering, }) if err != nil { @@ -240,9 +233,8 @@ func initWebMetrics(app *App) { func initSubmissionSystem(app *App) { app.submitter = &txsub.System{ - Pending: txsub.NewDefaultSubmissionList(), - Submitter: txsub.NewDefaultSubmitter(http.DefaultClient, app.config.StellarCoreURL), - SubmissionQueue: sequence.NewManager(), + Pending: txsub.NewDefaultSubmissionList(), + Submitter: txsub.NewDefaultSubmitter(http.DefaultClient, app.config.StellarCoreURL), DB: func(ctx context.Context) txsub.HorizonDB { return &history.Q{SessionInterface: app.HorizonSession()} }, diff --git a/services/horizon/internal/integration/clawback_test.go b/services/horizon/internal/integration/clawback_test.go index c41d2af465..67dbdf756c 100644 --- a/services/horizon/internal/integration/clawback_test.go +++ b/services/horizon/internal/integration/clawback_test.go @@ -23,7 +23,7 @@ func TestHappyClawbackAccount(t *testing.T) { asset, fromKey, _ := setupClawbackAccountTest(tt, itest, master) - // Clawback all of the asset + // Clawback all the asset submissionResp := itest.MustSubmitOperations(itest.MasterAccount(), master, &txnbuild.Clawback{ From: fromKey.Address(), Amount: "10", @@ -93,7 +93,7 @@ func TestHappyClawbackAccountSellingLiabilities(t *testing.T) { Buying: txnbuild.NativeAsset{}, Selling: asset, Amount: "5", - Price: xdr.Price{1, 1}, + Price: xdr.Price{N: 1, D: 1}, SourceAccount: fromAccount.GetAccountID(), }) tt.True(submissionResp.Successful) @@ -148,7 +148,7 @@ func TestSadClawbackAccountSufficientFundsSellingLiabilities(t *testing.T) { Buying: txnbuild.NativeAsset{}, Selling: asset, Amount: "5", - Price: xdr.Price{1, 1}, + Price: xdr.Price{N: 1, D: 1}, SourceAccount: fromAccount.GetAccountID(), }) diff --git a/services/horizon/internal/integration/contracts/.gitignore b/services/horizon/internal/integration/contracts/.gitignore new file mode 100644 index 0000000000..1de565933b --- /dev/null +++ b/services/horizon/internal/integration/contracts/.gitignore @@ -0,0 +1 @@ +target \ No newline at end of file diff --git a/services/horizon/internal/integration/contracts/Cargo.lock b/services/horizon/internal/integration/contracts/Cargo.lock new file mode 100644 index 0000000000..e80d7d5d28 --- /dev/null +++ b/services/horizon/internal/integration/contracts/Cargo.lock @@ -0,0 +1,1429 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "addr2line" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[package]] +name = "android-tzdata" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + +[[package]] +name = "arbitrary" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d5a26814d8dcb93b0e5a0ff3c6d80a8843bafb21b39e8e18a6f05471870e110" +dependencies = [ + "derive_arbitrary", +] + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "backtrace" +version = "0.3.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + +[[package]] +name = "base16ct" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" + +[[package]] +name = "base32" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23ce669cd6c8588f79e15cf450314f9638f967fc5770ff1c7c1deb0925ea7cfa" + +[[package]] +name = "base64" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" + +[[package]] +name = "base64" +version = "0.21.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35636a1494ede3b646cc98f74f8e62c773a38a659ebc777a2cf26b9b74171df9" + +[[package]] +name = "base64ct" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "bumpalo" +version = "3.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" + +[[package]] +name = "bytes-lit" +version = "0.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0adabf37211a5276e46335feabcbb1530c95eb3fdf85f324c7db942770aa025d" +dependencies = [ + "num-bigint", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "cc" +version = "1.0.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" +dependencies = [ + "libc", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "chrono" +version = "0.4.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f2c685bad3eb3d45a01354cedb7d5faa66194d1d58ba6e267a8de788f79db38" +dependencies = [ + "android-tzdata", + "iana-time-zone", + "num-traits", + "serde", + "windows-targets", +] + +[[package]] +name = "const-oid" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28c122c3980598d243d63d9a704629a2d748d101f278052ff068be5a4423ab6f" + +[[package]] +name = "core-foundation-sys" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" + +[[package]] +name = "cpufeatures" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce420fe07aecd3e67c5f910618fe65e94158f6dcc0adf44e00d69ce2bdfe0fd0" +dependencies = [ + "libc", +] + +[[package]] +name = "crate-git-revision" +version = "0.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c521bf1f43d31ed2f73441775ed31935d77901cb3451e44b38a1c1612fcbaf98" +dependencies = [ + "serde", + "serde_derive", + "serde_json", +] + +[[package]] +name = "crypto-bigint" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" +dependencies = [ + "generic-array", + "rand_core", + "subtle", + "zeroize", +] + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "ctor" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37e366bff8cd32dd8754b0991fb66b279dc48f598c3a18914852a6673deef583" +dependencies = [ + "quote", + "syn", +] + +[[package]] +name = "curve25519-dalek" +version = "4.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e89b8c6a2e4b1f45971ad09761aafb85514a84744b67a95e32c3cc1352d1f65c" +dependencies = [ + "cfg-if", + "cpufeatures", + "curve25519-dalek-derive", + "digest", + "fiat-crypto", + "platforms", + "rustc_version", + "subtle", + "zeroize", +] + +[[package]] +name = "curve25519-dalek-derive" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "darling" +version = "0.20.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0209d94da627ab5605dcccf08bb18afa5009cfbef48d8a8b7d7bdbc79be25c5e" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.20.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "177e3443818124b357d8e76f53be906d60937f0d3a90773a664fa63fa253e621" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn", +] + +[[package]] +name = "darling_macro" +version = "0.20.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "836a9bbc7ad63342d6d6e7b815ccab164bc77a2d95d84bc3117a8c0d5c98e2d5" +dependencies = [ + "darling_core", + "quote", + "syn", +] + +[[package]] +name = "der" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fffa369a668c8af7dbf8b5e56c9f744fbd399949ed171606040001947de40b1c" +dependencies = [ + "const-oid", + "zeroize", +] + +[[package]] +name = "deranged" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f32d04922c60427da6f9fef14d042d9edddef64cb9d4ce0d64d0685fbeb1fd3" +dependencies = [ + "powerfmt", + "serde", +] + +[[package]] +name = "derive_arbitrary" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67e77553c4162a157adbf834ebae5b415acbecbeafc7a74b0e886657506a7611" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "const-oid", + "crypto-common", + "subtle", +] + +[[package]] +name = "downcast-rs" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650" + +[[package]] +name = "ecdsa" +version = "0.16.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" +dependencies = [ + "der", + "digest", + "elliptic-curve", + "rfc6979", + "signature", + "spki", +] + +[[package]] +name = "ed25519" +version = "2.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53" +dependencies = [ + "pkcs8", + "signature", +] + +[[package]] +name = "ed25519-dalek" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f628eaec48bfd21b865dc2950cfa014450c01d2fa2b69a86c2fd5844ec523c0" +dependencies = [ + "curve25519-dalek", + "ed25519", + "rand_core", + "serde", + "sha2", + "subtle", + "zeroize", +] + +[[package]] +name = "either" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" + +[[package]] +name = "elliptic-curve" +version = "0.13.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" +dependencies = [ + "base16ct", + "crypto-bigint", + "digest", + "ff", + "generic-array", + "group", + "pkcs8", + "rand_core", + "sec1", + "subtle", + "zeroize", +] + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "ethnum" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b90ca2580b73ab6a1f724b76ca11ab632df820fd6040c336200d2c1df7b3c82c" + +[[package]] +name = "ff" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449" +dependencies = [ + "rand_core", + "subtle", +] + +[[package]] +name = "fiat-crypto" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27573eac26f4dd11e2b1916c3fe1baa56407c83c71a773a8ba17ec0bca03b6b7" + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", + "zeroize", +] + +[[package]] +name = "getrandom" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe9006bed769170c11f845cf00c7c1e9092aeb3f268e007c3e760ac68008070f" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "wasi", + "wasm-bindgen", +] + +[[package]] +name = "gimli" +version = "0.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" + +[[package]] +name = "group" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" +dependencies = [ + "ff", + "rand_core", + "subtle", +] + +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + +[[package]] +name = "hashbrown" +version = "0.14.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" + +[[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 = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest", +] + +[[package]] +name = "iana-time-zone" +version = "0.1.58" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8326b86b6cff230b97d0d312a6c40a60726df3332e721f72a1b035f451663b20" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "wasm-bindgen", + "windows-core", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[package]] +name = "indexmap" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown 0.12.3", + "serde", +] + +[[package]] +name = "indexmap" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f" +dependencies = [ + "equivalent", + "hashbrown 0.14.3", + "serde", +] + +[[package]] +name = "indexmap-nostd" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e04e2fd2b8188ea827b32ef11de88377086d690286ab35747ef7f9bf3ccb590" + +[[package]] +name = "itertools" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" + +[[package]] +name = "js-sys" +version = "0.3.66" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cee9c64da59eae3b50095c18d3e74f8b73c0b86d2792824ff01bbce68ba229ca" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "k256" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f01b677d82ef7a676aa37e099defd83a28e15687112cafdd112d60236b6115b" +dependencies = [ + "cfg-if", + "ecdsa", + "elliptic-curve", + "once_cell", + "sha2", + "signature", +] + +[[package]] +name = "keccak" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f6d5ed8676d904364de097082f4e7d240b571b67989ced0240f08b7f966f940" +dependencies = [ + "cpufeatures", +] + +[[package]] +name = "libc" +version = "0.2.150" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c" + +[[package]] +name = "libm" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" + +[[package]] +name = "log" +version = "0.4.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" + +[[package]] +name = "memchr" +version = "2.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" + +[[package]] +name = "miniz_oxide" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" +dependencies = [ + "adler", +] + +[[package]] +name = "num-bigint" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "608e7659b5c3d7cba262d894801b9ec9d00de989e8a82bd4bef91d08da45cdc0" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-derive" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfb77679af88f8b125209d354a202862602672222e7f2313fdd6dc349bad4712" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "num-integer" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" +dependencies = [ + "autocfg", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" +dependencies = [ + "autocfg", +] + +[[package]] +name = "object" +version = "0.32.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0" +dependencies = [ + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" + +[[package]] +name = "paste" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" + +[[package]] +name = "pkcs8" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" +dependencies = [ + "der", + "spki", +] + +[[package]] +name = "platforms" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14e6ab3f592e6fb464fc9712d8d6e6912de6473954635fd76a589d832cffcbb0" + +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + +[[package]] +name = "ppv-lite86" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" + +[[package]] +name = "prettyplease" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae005bd773ab59b4725093fd7df83fd7892f7d8eafb48dbd7de6e024e4215f9d" +dependencies = [ + "proc-macro2", + "syn", +] + +[[package]] +name = "proc-macro2" +version = "1.0.70" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39278fbbf5fb4f646ce651690877f89d1c5811a3d4acb27700c1cb3cdb78fd3b" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "rfc6979" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" +dependencies = [ + "hmac", + "subtle", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" + +[[package]] +name = "rustc_version" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +dependencies = [ + "semver", +] + +[[package]] +name = "ryu" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" + +[[package]] +name = "sec1" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" +dependencies = [ + "base16ct", + "der", + "generic-array", + "pkcs8", + "subtle", + "zeroize", +] + +[[package]] +name = "semver" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "836fa6a3e1e547f9a2c4040802ec865b5d85f4014efe00555d7090a3dcaa1090" + +[[package]] +name = "serde" +version = "1.0.193" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.193" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.108" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "serde_with" +version = "3.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64cd236ccc1b7a29e7e2739f27c0b2dd199804abc4290e32f59f3b68d6405c23" +dependencies = [ + "base64 0.21.5", + "chrono", + "hex", + "indexmap 1.9.3", + "indexmap 2.1.0", + "serde", + "serde_json", + "serde_with_macros", + "time", +] + +[[package]] +name = "serde_with_macros" +version = "3.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93634eb5f75a2323b16de4748022ac4297f9e76b6dced2be287a099f41b5e788" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "sha2" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "sha3" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60" +dependencies = [ + "digest", + "keccak", +] + +[[package]] +name = "signature" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" +dependencies = [ + "digest", + "rand_core", +] + +[[package]] +name = "smallvec" +version = "1.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970" + +[[package]] +name = "soroban-builtin-sdk-macros" +version = "20.0.0-rc2" +source = "git+https://github.com/stellar/rs-soroban-env?rev=be04cf31e925ba5bacd9b22db7caf7b4f6dd8372#be04cf31e925ba5bacd9b22db7caf7b4f6dd8372" +dependencies = [ + "itertools", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "soroban-env-common" +version = "20.0.0-rc2" +source = "git+https://github.com/stellar/rs-soroban-env?rev=be04cf31e925ba5bacd9b22db7caf7b4f6dd8372#be04cf31e925ba5bacd9b22db7caf7b4f6dd8372" +dependencies = [ + "arbitrary", + "crate-git-revision", + "ethnum", + "num-derive", + "num-traits", + "serde", + "soroban-env-macros", + "soroban-wasmi", + "static_assertions", + "stellar-xdr", +] + +[[package]] +name = "soroban-env-guest" +version = "20.0.0-rc2" +source = "git+https://github.com/stellar/rs-soroban-env?rev=be04cf31e925ba5bacd9b22db7caf7b4f6dd8372#be04cf31e925ba5bacd9b22db7caf7b4f6dd8372" +dependencies = [ + "soroban-env-common", + "static_assertions", +] + +[[package]] +name = "soroban-env-host" +version = "20.0.0-rc2" +source = "git+https://github.com/stellar/rs-soroban-env?rev=be04cf31e925ba5bacd9b22db7caf7b4f6dd8372#be04cf31e925ba5bacd9b22db7caf7b4f6dd8372" +dependencies = [ + "backtrace", + "curve25519-dalek", + "ed25519-dalek", + "getrandom", + "hex-literal", + "hmac", + "k256", + "num-derive", + "num-integer", + "num-traits", + "rand", + "rand_chacha", + "sha2", + "sha3", + "soroban-builtin-sdk-macros", + "soroban-env-common", + "soroban-wasmi", + "static_assertions", + "stellar-strkey", +] + +[[package]] +name = "soroban-env-macros" +version = "20.0.0-rc2" +source = "git+https://github.com/stellar/rs-soroban-env?rev=be04cf31e925ba5bacd9b22db7caf7b4f6dd8372#be04cf31e925ba5bacd9b22db7caf7b4f6dd8372" +dependencies = [ + "itertools", + "proc-macro2", + "quote", + "serde", + "serde_json", + "stellar-xdr", + "syn", +] + +[[package]] +name = "soroban-increment-contract" +version = "0.0.0" +dependencies = [ + "soroban-sdk", +] + +[[package]] +name = "soroban-ledger-snapshot" +version = "20.0.0-rc2" +source = "git+https://github.com/stellar/rs-soroban-sdk?rev=e35bace9de5addae7c32f405cdc11bb459cb1d61#e35bace9de5addae7c32f405cdc11bb459cb1d61" +dependencies = [ + "serde", + "serde_json", + "serde_with", + "soroban-env-common", + "soroban-env-host", + "thiserror", +] + +[[package]] +name = "soroban-sac-test" +version = "0.0.0" +dependencies = [ + "soroban-sdk", +] + +[[package]] +name = "soroban-sdk" +version = "20.0.0-rc2" +source = "git+https://github.com/stellar/rs-soroban-sdk?rev=e35bace9de5addae7c32f405cdc11bb459cb1d61#e35bace9de5addae7c32f405cdc11bb459cb1d61" +dependencies = [ + "arbitrary", + "bytes-lit", + "ctor", + "ed25519-dalek", + "rand", + "serde", + "serde_json", + "soroban-env-guest", + "soroban-env-host", + "soroban-ledger-snapshot", + "soroban-sdk-macros", + "stellar-strkey", +] + +[[package]] +name = "soroban-sdk-macros" +version = "20.0.0-rc2" +source = "git+https://github.com/stellar/rs-soroban-sdk?rev=e35bace9de5addae7c32f405cdc11bb459cb1d61#e35bace9de5addae7c32f405cdc11bb459cb1d61" +dependencies = [ + "crate-git-revision", + "darling", + "itertools", + "proc-macro2", + "quote", + "rustc_version", + "sha2", + "soroban-env-common", + "soroban-spec", + "soroban-spec-rust", + "stellar-xdr", + "syn", +] + +[[package]] +name = "soroban-spec" +version = "20.0.0-rc2" +source = "git+https://github.com/stellar/rs-soroban-sdk?rev=e35bace9de5addae7c32f405cdc11bb459cb1d61#e35bace9de5addae7c32f405cdc11bb459cb1d61" +dependencies = [ + "base64 0.13.1", + "stellar-xdr", + "thiserror", + "wasmparser", +] + +[[package]] +name = "soroban-spec-rust" +version = "20.0.0-rc2" +source = "git+https://github.com/stellar/rs-soroban-sdk?rev=e35bace9de5addae7c32f405cdc11bb459cb1d61#e35bace9de5addae7c32f405cdc11bb459cb1d61" +dependencies = [ + "prettyplease", + "proc-macro2", + "quote", + "sha2", + "soroban-spec", + "stellar-xdr", + "syn", + "thiserror", +] + +[[package]] +name = "soroban-store" +version = "0.0.0" +dependencies = [ + "soroban-sdk", +] + +[[package]] +name = "soroban-wasmi" +version = "0.31.0-soroban1" +source = "git+https://github.com/stellar/wasmi?rev=7e63b4c9e08c4163f417d118d81f7ea34789d0be#7e63b4c9e08c4163f417d118d81f7ea34789d0be" +dependencies = [ + "smallvec", + "spin", + "wasmi_arena", + "wasmi_core", + "wasmparser-nostd", +] + +[[package]] +name = "soroban_add_u64" +version = "0.0.0" +dependencies = [ + "soroban-sdk", +] + +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" + +[[package]] +name = "spki" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" +dependencies = [ + "base64ct", + "der", +] + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "stellar-strkey" +version = "0.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12d2bf45e114117ea91d820a846fd1afbe3ba7d717988fee094ce8227a3bf8bd" +dependencies = [ + "base32", + "crate-git-revision", + "thiserror", +] + +[[package]] +name = "stellar-xdr" +version = "20.0.0-rc1" +source = "git+https://github.com/stellar/rs-stellar-xdr?rev=d6f8ece2c89809d5e2800b9df64ae60787ee492b#d6f8ece2c89809d5e2800b9df64ae60787ee492b" +dependencies = [ + "arbitrary", + "base64 0.13.1", + "crate-git-revision", + "hex", + "serde", + "serde_with", + "stellar-strkey", +] + +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + +[[package]] +name = "subtle" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" + +[[package]] +name = "syn" +version = "2.0.39" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23e78b90f2fcf45d3e842032ce32e3f2d1545ba6636271dcbf24fa306d87be7a" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "thiserror" +version = "1.0.50" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9a7210f5c9a7156bb50aa36aed4c95afb51df0df00713949448cf9e97d382d2" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.50" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "time" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4a34ab300f2dee6e562c10a046fc05e358b29f9bf92277f30c3c8d82275f6f5" +dependencies = [ + "deranged", + "itoa", + "powerfmt", + "serde", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" + +[[package]] +name = "time-macros" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ad70d68dba9e1f8aceda7aa6711965dfec1cac869f311a51bd08b3a2ccbce20" +dependencies = [ + "time-core", +] + +[[package]] +name = "typenum" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasm-bindgen" +version = "0.2.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ed0d4f68a3015cc185aff4db9506a015f4b96f95303897bfa23f846db54064e" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b56f625e64f3a1084ded111c4d5f477df9f8c92df113852fa5a374dbda78826" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0162dbf37223cd2afce98f3d0785506dcb8d266223983e4b5b525859e6e182b2" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0eb82fcb7930ae6219a7ecfd55b217f5f0893484b7a13022ebb2b2bf20b5283" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ab9b36309365056cd639da3134bf87fa8f3d86008abf99e612384a6eecd459f" + +[[package]] +name = "wasmi_arena" +version = "0.4.0" +source = "git+https://github.com/stellar/wasmi?rev=7e63b4c9e08c4163f417d118d81f7ea34789d0be#7e63b4c9e08c4163f417d118d81f7ea34789d0be" + +[[package]] +name = "wasmi_core" +version = "0.13.0" +source = "git+https://github.com/stellar/wasmi?rev=7e63b4c9e08c4163f417d118d81f7ea34789d0be#7e63b4c9e08c4163f417d118d81f7ea34789d0be" +dependencies = [ + "downcast-rs", + "libm", + "num-traits", + "paste", +] + +[[package]] +name = "wasmparser" +version = "0.88.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb8cf7dd82407fe68161bedcd57fde15596f32ebf6e9b3bdbf3ae1da20e38e5e" +dependencies = [ + "indexmap 1.9.3", +] + +[[package]] +name = "wasmparser-nostd" +version = "0.100.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9157cab83003221bfd385833ab587a039f5d6fa7304854042ba358a3b09e0724" +dependencies = [ + "indexmap-nostd", +] + +[[package]] +name = "windows-core" +version = "0.51.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1f8cf84f35d2db49a46868f947758c7a1138116f7fac3bc844f43ade1292e64" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + +[[package]] +name = "zeroize" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" diff --git a/services/horizon/internal/integration/contracts/Cargo.toml b/services/horizon/internal/integration/contracts/Cargo.toml new file mode 100644 index 0000000000..72ada87404 --- /dev/null +++ b/services/horizon/internal/integration/contracts/Cargo.toml @@ -0,0 +1,28 @@ +[workspace] +resolver = "2" + +members = [ + "sac_test", + "increment", + "add_u64", + "store", +] + +[profile.release-with-logs] +inherits = "release" +debug-assertions = true + +[profile.release] +opt-level = "z" +overflow-checks = true +debug = 0 +strip = "symbols" +debug-assertions = false +panic = "abort" +codegen-units = 1 +lto = true + +[workspace.dependencies.soroban-sdk] +version = "20.0.0-rc2" +git = "https://github.com/stellar/rs-soroban-sdk" +rev = "e35bace9de5addae7c32f405cdc11bb459cb1d61" diff --git a/services/horizon/internal/integration/contracts/README.md b/services/horizon/internal/integration/contracts/README.md new file mode 100644 index 0000000000..6c2861d5ec --- /dev/null +++ b/services/horizon/internal/integration/contracts/README.md @@ -0,0 +1,35 @@ +### Contract integration tests use rpc preflight +The contract integration tests depend on soroban rpc for preflight requests, two additional environment variables must be set to enable soroban rpc server to be launced in a separate docker container: +``` +HORIZON_INTEGRATION_TESTS_SOROBAN_RPC_DOCKER_IMG=stellar/soroban-rpc +HORIZON_INTEGRATION_TESTS_ENABLE_SOROBAN_RPC=true +``` + +The `stellar/soroban-rpc` refers to an image built from soroban-tools/cmd/soroban-rpc/docker/Dockerfile and published on public `docker.io` so it is referrable in any build environment. Images are published to `docker.io/stellar/soroban-rpc` on a release basis, if you need more recent build, can build interim images from soroban-tools/cmd/soroban-rpc/docker/Dockerfile, example: + +``` +docker build --platform linux/amd64 --build-arg STELLAR_CORE_VERSION=19.11.1-1373.875f47e24.focal~soroban -t stellar-soroban-rpc:test -f cmd/soroban-rpc/docker/Dockerfile . +``` + +`STELLAR_CORE_VERSION` should be set to a debian package version for `stellar-core`. + +### Contract test fixture source code + +The existing integeration tests refer to .wasm files from the `testdata/` directory location. + +#### Any time contract code changes, follow these steps to rebuild the test WASM fixtures: + +1. First install latest rust toolchain: +https://www.rust-lang.org/tools/install + +2. Update the [`Cargo.toml file`](./Cargo.toml) to have latest git refs to +[`rs-soroban-sdk`](https://github.com/stellar/rs-soroban-sdk) for the `soroban-sdk` and `soroban-auth` dependencies. + +3. Compile the contract source code to WASM and copy it to `testdata/`: + +```bash +cd ./services/horizon/internal/integration/contracts +cargo update +cargo build --target wasm32-unknown-unknown --release +cp target/wasm32-unknown-unknown/release/*.wasm ../testdata/ +``` diff --git a/services/horizon/internal/integration/contracts/add_u64/Cargo.toml b/services/horizon/internal/integration/contracts/add_u64/Cargo.toml new file mode 100644 index 0000000000..e4485c1bee --- /dev/null +++ b/services/horizon/internal/integration/contracts/add_u64/Cargo.toml @@ -0,0 +1,17 @@ +[package] +version = "0.0.0" +name = "soroban_add_u64" +authors = ["Stellar Development Foundation "] +license = "Apache-2.0" +edition = "2021" +publish = false + +[lib] +crate-type = ["cdylib"] +doctest = false + +[dependencies] +soroban-sdk = { workspace = true } + +[dev_dependencies] +soroban-sdk = { workspace = true, features = ["testutils"] } \ No newline at end of file diff --git a/services/horizon/internal/integration/contracts/add_u64/src/lib.rs b/services/horizon/internal/integration/contracts/add_u64/src/lib.rs new file mode 100644 index 0000000000..8c8fccbfe0 --- /dev/null +++ b/services/horizon/internal/integration/contracts/add_u64/src/lib.rs @@ -0,0 +1,33 @@ +#![no_std] +use soroban_sdk::{contract, contractimpl}; + +#[contract] +pub struct Contract; + +#[contractimpl] +impl Contract { + pub fn add(a: u64, b: u64) -> u64 { + a + b + } +} + +#[cfg(test)] +mod test { + use soroban_sdk::{BytesN, Env, Address}; + + use crate::{Contract, ContractClient}; + + #[test] + fn test_add() { + let e = Env::default(); + let contract_id= Address::from_contract_id(&BytesN::from_array(&e, &[0; 32])); + + e.register_contract(&contract_id, Contract); + let client = ContractClient::new(&e, &contract_id); + + let x = 10u64; + let y = 12u64; + let z = client.add(&x, &y); + assert!(z == 22); + } +} diff --git a/services/horizon/internal/integration/contracts/increment/Cargo.toml b/services/horizon/internal/integration/contracts/increment/Cargo.toml new file mode 100644 index 0000000000..bf3517b15a --- /dev/null +++ b/services/horizon/internal/integration/contracts/increment/Cargo.toml @@ -0,0 +1,17 @@ +[package] +version = "0.0.0" +name = "soroban-increment-contract" +authors = ["Stellar Development Foundation "] +license = "Apache-2.0" +edition = "2021" +publish = false + +[lib] +crate-type = ["cdylib"] +doctest = false + +[dependencies] +soroban-sdk = { workspace = true } + +[dev_dependencies] +soroban-sdk = { workspace = true, features = ["testutils"] } diff --git a/services/horizon/internal/integration/contracts/increment/src/lib.rs b/services/horizon/internal/integration/contracts/increment/src/lib.rs new file mode 100644 index 0000000000..2dde51f6c7 --- /dev/null +++ b/services/horizon/internal/integration/contracts/increment/src/lib.rs @@ -0,0 +1,37 @@ +#![no_std] +use soroban_sdk::{contract, contractimpl, log, Env, Symbol, symbol_short}; + +const COUNTER: Symbol = symbol_short!("COUNTER"); + +#[contract] +pub struct IncrementContract; + +#[contractimpl] +impl IncrementContract { + /// Increment increments an internal counter, and returns the value. + pub fn increment(env: Env) -> u32 { + let mut count: u32 = 0; + + // Get the current count. + if env.storage().persistent().has(&COUNTER) { + count = env + .storage() + .persistent() + .get(&COUNTER) + .unwrap(); // Panic if the value of COUNTER is not u32. + } + log!(&env, "count: {}", count); + + + // Increment the count. + count += 1; + + // Save the count. + env.storage().persistent().set(&COUNTER, &count); + + // Return the count to the caller. + count + } +} + +mod test; diff --git a/services/horizon/internal/integration/contracts/increment/src/test.rs b/services/horizon/internal/integration/contracts/increment/src/test.rs new file mode 100644 index 0000000000..29ec9dcb5d --- /dev/null +++ b/services/horizon/internal/integration/contracts/increment/src/test.rs @@ -0,0 +1,19 @@ +#![cfg(test)] + +use super::{IncrementContract, IncrementContractClient}; +use soroban_sdk::{testutils::Logs, Env}; + +extern crate std; + +#[test] +fn test() { + let env = Env::default(); + let contract_id = env.register_contract(None, IncrementContract); + let client = IncrementContractClient::new(&env, &contract_id); + + assert_eq!(client.increment(), 1); + assert_eq!(client.increment(), 2); + assert_eq!(client.increment(), 3); + + std::println!("{}", env.logs().all().join("\n")); +} diff --git a/services/horizon/internal/integration/contracts/sac_test/Cargo.toml b/services/horizon/internal/integration/contracts/sac_test/Cargo.toml new file mode 100644 index 0000000000..d02f344871 --- /dev/null +++ b/services/horizon/internal/integration/contracts/sac_test/Cargo.toml @@ -0,0 +1,17 @@ +[package] +version = "0.0.0" +name = "soroban-sac-test" +authors = ["Stellar Development Foundation "] +license = "Apache-2.0" +edition = "2021" +publish = false + +[lib] +crate-type = ["cdylib"] +doctest = false + +[dependencies] +soroban-sdk = { workspace = true } + +[dev_dependencies] +soroban-sdk = { workspace = true, features = ["testutils"] } \ No newline at end of file diff --git a/services/horizon/internal/integration/contracts/sac_test/src/lib.rs b/services/horizon/internal/integration/contracts/sac_test/src/lib.rs new file mode 100644 index 0000000000..71ecc80286 --- /dev/null +++ b/services/horizon/internal/integration/contracts/sac_test/src/lib.rs @@ -0,0 +1,67 @@ +#![no_std] +use soroban_sdk::{ + contract, contractimpl, contracttype, token, Address, Env, +}; + +#[contracttype] +pub enum DataKey { + Token, +} + +fn get_token(e: &Env) -> Address { + e.storage().persistent().get(&DataKey::Token).unwrap() +} + +#[contract] +pub struct SACTest; + +#[contractimpl] +impl SACTest { + + pub fn init(e: Env, contract: Address) { + e.storage().persistent().set(&DataKey::Token, &contract); + } + + pub fn get_token(e: Env) -> Address { + get_token(&e) + } + + pub fn burn_self(env: Env, amount: i128) { + let client = token::Client::new(&env, &get_token(&env)); + client.burn(&env.current_contract_address(), &amount); + } + + pub fn transfer(env: Env, to: Address, amount: i128) { + let client = token::Client::new(&env, &get_token(&env)); + client.transfer(&env.current_contract_address(), &to, &amount); + } +} + +#[test] +fn test() { + use soroban_sdk::testutils::Address as _; + + let env = Env::default(); + env.mock_all_auths(); + let admin = Address::random(&env); + let token_contract_id = env.register_stellar_asset_contract(admin.clone()); + + let contract_address = env.register_contract(None, SACTest); + let contract = SACTestClient::new(&env, &contract_address); + + contract.init(&token_contract_id); + + let token = token::Client::new(&env, &contract.get_token()); + let token_admin = token::AdminClient::new(&env, &contract.get_token()); + assert_eq!(token.decimals(), 7); + + token_admin.mint(&contract_address, &1000); + + contract.burn_self(&400); + assert_eq!(token.balance(&contract_address), 600); + + let user = Address::random(&env); + contract.transfer(&user, &100); + assert_eq!(token.balance(&contract_address), 500); + assert_eq!(token.balance(&user), 100); +} diff --git a/services/horizon/internal/integration/contracts/store/Cargo.toml b/services/horizon/internal/integration/contracts/store/Cargo.toml new file mode 100644 index 0000000000..080ae44abd --- /dev/null +++ b/services/horizon/internal/integration/contracts/store/Cargo.toml @@ -0,0 +1,17 @@ +[package] +version = "0.0.0" +name = "soroban-store" +authors = ["Stellar Development Foundation "] +license = "Apache-2.0" +edition = "2021" +publish = false + +[lib] +crate-type = ["cdylib"] +doctest = false + +[dependencies] +soroban-sdk = { workspace = true } + +[dev_dependencies] +soroban-sdk = { workspace = true, features = ["testutils"] } \ No newline at end of file diff --git a/services/horizon/internal/integration/contracts/store/src/lib.rs b/services/horizon/internal/integration/contracts/store/src/lib.rs new file mode 100644 index 0000000000..3a80d77ed7 --- /dev/null +++ b/services/horizon/internal/integration/contracts/store/src/lib.rs @@ -0,0 +1,16 @@ +#![no_std] +use soroban_sdk::{contract, contractimpl, Env, Val}; + +#[contract] +pub struct Contract; + +#[contractimpl] +impl Contract { + pub fn set(e: Env, key: Val, val: Val) { + e.storage().persistent().set(&key, &val) + } + + pub fn remove(e: Env, key: Val) { + e.storage().persistent().remove(&key) + } +} \ No newline at end of file diff --git a/services/horizon/internal/integration/db_test.go b/services/horizon/internal/integration/db_test.go index 6f3c33160a..f6c32f8cc7 100644 --- a/services/horizon/internal/integration/db_test.go +++ b/services/horizon/internal/integration/db_test.go @@ -3,7 +3,6 @@ package integration import ( "context" "fmt" - "os" "path/filepath" "strconv" "testing" @@ -13,6 +12,7 @@ import ( "github.com/stellar/go/clients/horizonclient" "github.com/stellar/go/historyarchive" + "github.com/stellar/go/ingest/ledgerbackend" "github.com/stellar/go/keypair" horizoncmd "github.com/stellar/go/services/horizon/cmd" horizon "github.com/stellar/go/services/horizon/internal" @@ -79,8 +79,8 @@ func submitLiquidityPoolOps(itest *integration.Test, tt *assert.Assertions) (sub LiquidityPoolID: [32]byte(poolID), MaxAmountA: "400", MaxAmountB: "777", - MinPrice: xdr.Price{1, 2}, - MaxPrice: xdr.Price{2, 1}, + MinPrice: xdr.Price{N: 1, D: 2}, + MaxPrice: xdr.Price{N: 2, D: 1}, } allOps = append(allOps, op) itest.MustSubmitOperations(shareAccount, shareKeys, op) @@ -162,6 +162,25 @@ func submitPaymentOps(itest *integration.Test, tt *assert.Assertions) (submitted return ops, txResp.Ledger } +//lint:ignore U1000 Ignore unused function temporarily until fees/preflight are working in test +func submitSorobanOps(itest *integration.Test, tt *assert.Assertions) (submittedOperations []txnbuild.Operation, lastLedger int32) { + installContractOp := assembleInstallContractCodeOp(itest.CurrentTest(), itest.Master().Address(), add_u64_contract) + itest.MustSubmitOperations(itest.MasterAccount(), itest.Master(), installContractOp) + + extendFootprintTtlOp := &txnbuild.ExtendFootprintTtl{ + ExtendTo: 100, + SourceAccount: itest.Master().Address(), + } + itest.MustSubmitOperations(itest.MasterAccount(), itest.Master(), extendFootprintTtlOp) + + restoreFootprintOp := &txnbuild.RestoreFootprint{ + SourceAccount: itest.Master().Address(), + } + txResp := itest.MustSubmitOperations(itest.MasterAccount(), itest.Master(), restoreFootprintOp) + + return []txnbuild.Operation{installContractOp, extendFootprintTtlOp, restoreFootprintOp}, txResp.Ledger +} + func submitSponsorshipOps(itest *integration.Test, tt *assert.Assertions) (submittedOperations []txnbuild.Operation, lastLedger int32) { keys, accounts := itest.CreateAccounts(1, "1000") sponsor, sponsorPair := accounts[0], keys[0] @@ -313,21 +332,21 @@ func submitOfferAndTrustlineOps(itest *integration.Test, tt *assert.Assertions) Selling: txnbuild.NativeAsset{}, Buying: pesetasAsset, Amount: "10", - Price: xdr.Price{1, 1}, + Price: xdr.Price{N: 1, D: 1}, OfferID: 0, }, &txnbuild.ManageBuyOffer{ Selling: txnbuild.NativeAsset{}, Buying: pesetasAsset, Amount: "10", - Price: xdr.Price{1, 1}, + Price: xdr.Price{N: 1, D: 1}, OfferID: 0, }, &txnbuild.CreatePassiveSellOffer{ Selling: txnbuild.NativeAsset{}, Buying: pesetasAsset, Amount: "10", - Price: xdr.Price{1, 1}, + Price: xdr.Price{N: 1, D: 1}, }, } allOps := ops @@ -396,34 +415,49 @@ func submitAccountOps(itest *integration.Test, tt *assert.Assertions) (submitted return allOps, txResp.Ledger } -func initializeDBIntegrationTest(t *testing.T) (itest *integration.Test, reachedLedger int32) { - itest = integration.NewTest(t, integration.Config{}) +func initializeDBIntegrationTest(t *testing.T) (*integration.Test, int32) { + itest := integration.NewTest(t, integration.Config{}) tt := assert.New(t) - // submit all possible operations - ops, _ := submitAccountOps(itest, tt) - submittedOps := ops - ops, _ = submitPaymentOps(itest, tt) - submittedOps = append(submittedOps, ops...) - ops, _ = submitOfferAndTrustlineOps(itest, tt) - submittedOps = append(submittedOps, ops...) - ops, _ = submitSponsorshipOps(itest, tt) - submittedOps = append(submittedOps, ops...) - ops, _ = submitClaimableBalanceOps(itest, tt) - submittedOps = append(submittedOps, ops...) - ops, _ = submitClawbackOps(itest, tt) - submittedOps = append(submittedOps, ops...) - ops, reachedLedger = submitLiquidityPoolOps(itest, tt) - submittedOps = append(submittedOps, ops...) - // Make sure all possible operations are covered by reingestion allOpTypes := set.Set[xdr.OperationType]{} for typ := range xdr.OperationTypeToStringMap { allOpTypes.Add(xdr.OperationType(typ)) } + + submitters := []func(*integration.Test, *assert.Assertions) ([]txnbuild.Operation, int32){ + submitAccountOps, + submitPaymentOps, + submitOfferAndTrustlineOps, + submitSponsorshipOps, + submitClaimableBalanceOps, + submitClawbackOps, + submitLiquidityPoolOps, + } + + // TODO - re-enable invoke host function 'submitSorobanOps' test + // once fees/footprint from preflight are working in test + if false && integration.GetCoreMaxSupportedProtocol() > 19 { + submitters = append(submitters, submitSorobanOps) + } else { + delete(allOpTypes, xdr.OperationTypeInvokeHostFunction) + delete(allOpTypes, xdr.OperationTypeExtendFootprintTtl) + delete(allOpTypes, xdr.OperationTypeRestoreFootprint) + } + // Inflation is not supported delete(allOpTypes, xdr.OperationTypeInflation) + var submittedOps []txnbuild.Operation + var ledgerOfLastSubmittedTx int32 + // submit all possible operations + for i, f := range submitters { + var ops []txnbuild.Operation + ops, ledgerOfLastSubmittedTx = f(itest, tt) + t.Logf("%v ledgerOfLastSubmittedTx %v", i, ledgerOfLastSubmittedTx) + submittedOps = append(submittedOps, ops...) + } + for _, op := range submittedOps { opXDR, err := op.BuildXDR() tt.NoError(err) @@ -431,11 +465,14 @@ func initializeDBIntegrationTest(t *testing.T) (itest *integration.Test, reached } tt.Empty(allOpTypes) - root, err := itest.Client().Root() - tt.NoError(err) - tt.LessOrEqual(reachedLedger, root.HorizonSequence) + reachedLedger := func() bool { + root, err := itest.Client().Root() + tt.NoError(err) + return root.HorizonSequence >= ledgerOfLastSubmittedTx + } + tt.Eventually(reachedLedger, 15*time.Second, 5*time.Second) - return + return itest, ledgerOfLastSubmittedTx } func TestReingestDB(t *testing.T) { @@ -444,7 +481,7 @@ func TestReingestDB(t *testing.T) { horizonConfig := itest.GetHorizonIngestConfig() t.Run("validate parallel range", func(t *testing.T) { - horizoncmd.RootCmd.SetArgs(command(horizonConfig, + horizoncmd.RootCmd.SetArgs(command(t, horizonConfig, "db", "reingest", "range", @@ -456,8 +493,10 @@ func TestReingestDB(t *testing.T) { assert.EqualError(t, horizoncmd.RootCmd.Execute(), "Invalid range: {10 2} from > to") }) + t.Logf("reached ledger is %v", reachedLedger) // cap reachedLedger to the nearest checkpoint ledger because reingest range - // cannot ingest past the most recent checkpoint ledger when using captive core + // cannot ingest past the most recent checkpoint ledger when using captive + // core toLedger := uint32(reachedLedger) archive, err := historyarchive.Connect( horizonConfig.HistoryArchiveURLs[0], @@ -471,7 +510,10 @@ func TestReingestDB(t *testing.T) { var latestCheckpoint uint32 publishedFirstCheckpoint := func() bool { has, requestErr := archive.GetRootHAS() - tt.NoError(requestErr) + if requestErr != nil { + t.Logf("request to fetch checkpoint failed: %v", requestErr) + return false + } latestCheckpoint = has.CurrentLedger return latestCheckpoint > 1 } @@ -488,10 +530,10 @@ func TestReingestDB(t *testing.T) { horizonConfig.CaptiveCoreConfigPath = filepath.Join( filepath.Dir(horizonConfig.CaptiveCoreConfigPath), - "captive-core-reingest-range-integration-tests.cfg", + getCoreConfigFile(itest), ) - horizoncmd.RootCmd.SetArgs(command(horizonConfig, "db", + horizoncmd.RootCmd.SetArgs(command(t, horizonConfig, "db", "reingest", "range", "--parallel-workers=1", @@ -503,7 +545,15 @@ func TestReingestDB(t *testing.T) { tt.NoError(horizoncmd.RootCmd.Execute(), "Repeat the same reingest range against db, should not have errors.") } -func command(horizonConfig horizon.Config, args ...string) []string { +func getCoreConfigFile(itest *integration.Test) string { + coreConfigFile := "captive-core-reingest-range-classic-integration-tests.cfg" + if itest.Config().ProtocolVersion >= ledgerbackend.MinimalSorobanProtocolSupport { + coreConfigFile = "captive-core-reingest-range-integration-tests.cfg" + } + return coreConfigFile +} + +func command(t *testing.T, horizonConfig horizon.Config, args ...string) []string { return append([]string{ "--stellar-core-url", horizonConfig.StellarCoreURL, @@ -511,15 +561,12 @@ func command(horizonConfig horizon.Config, args ...string) []string { horizonConfig.HistoryArchiveURLs[0], "--db-url", horizonConfig.DatabaseURL, - "--stellar-core-db-url", - horizonConfig.StellarCoreDatabaseURL, "--stellar-core-binary-path", horizonConfig.CaptiveCoreBinaryPath, "--captive-core-config-path", horizonConfig.CaptiveCoreConfigPath, "--captive-core-use-db=" + strconv.FormatBool(horizonConfig.CaptiveCoreConfigUseDB), - "--enable-captive-core-ingestion=" + strconv.FormatBool(horizonConfig.EnableCaptiveCoreIngestion), "--network-passphrase", horizonConfig.NetworkPassphrase, // due to ARTIFICIALLY_ACCELERATE_TIME_FOR_TESTING @@ -527,10 +574,52 @@ func command(horizonConfig horizon.Config, args ...string) []string { "8", // Create the storage directory outside of the source repo, // otherwise it will break Golang test caching. - "--captive-core-storage-path=" + os.TempDir(), + "--captive-core-storage-path=" + t.TempDir(), }, args...) } +func TestMigrateIngestIsTrueByDefault(t *testing.T) { + tt := assert.New(t) + // Create a fresh Horizon database + newDB := dbtest.Postgres(t) + freshHorizonPostgresURL := newDB.DSN + + horizoncmd.RootCmd.SetArgs([]string{ + // ingest is set to true by default + "--db-url", freshHorizonPostgresURL, + "db", "migrate", "up", + }) + tt.NoError(horizoncmd.RootCmd.Execute()) + + dbConn, err := db.Open("postgres", freshHorizonPostgresURL) + tt.NoError(err) + + status, err := schema.Status(dbConn.DB.DB) + tt.NoError(err) + tt.NotContains(status, "1_initial_schema.sql\t\t\t\t\t\tno") +} + +func TestMigrateChecksIngestFlag(t *testing.T) { + tt := assert.New(t) + // Create a fresh Horizon database + newDB := dbtest.Postgres(t) + freshHorizonPostgresURL := newDB.DSN + + horizoncmd.RootCmd.SetArgs([]string{ + "--ingest=false", + "--db-url", freshHorizonPostgresURL, + "db", "migrate", "up", + }) + tt.NoError(horizoncmd.RootCmd.Execute()) + + dbConn, err := db.Open("postgres", freshHorizonPostgresURL) + tt.NoError(err) + + status, err := schema.Status(dbConn.DB.DB) + tt.NoError(err) + tt.Contains(status, "1_initial_schema.sql\t\t\t\t\t\tno") +} + func TestFillGaps(t *testing.T) { itest, reachedLedger := initializeDBIntegrationTest(t) tt := assert.New(t) @@ -543,7 +632,7 @@ func TestFillGaps(t *testing.T) { // Initialize the DB schema dbConn, err := db.Open("postgres", freshHorizonPostgresURL) tt.NoError(err) - historyQ := history.Q{dbConn} + historyQ := history.Q{SessionInterface: dbConn} defer func() { historyQ.Close() newDB.Close() @@ -564,7 +653,7 @@ func TestFillGaps(t *testing.T) { tt.NoError(err) t.Run("validate parallel range", func(t *testing.T) { - horizoncmd.RootCmd.SetArgs(command(horizonConfig, + horizoncmd.RootCmd.SetArgs(command(t, horizonConfig, "db", "fill-gaps", "--parallel-workers=2", @@ -601,22 +690,22 @@ func TestFillGaps(t *testing.T) { horizonConfig.CaptiveCoreConfigPath = filepath.Join( filepath.Dir(horizonConfig.CaptiveCoreConfigPath), - "captive-core-reingest-range-integration-tests.cfg", + getCoreConfigFile(itest), ) - horizoncmd.RootCmd.SetArgs(command(horizonConfig, "db", "fill-gaps", "--parallel-workers=1")) + horizoncmd.RootCmd.SetArgs(command(t, horizonConfig, "db", "fill-gaps", "--parallel-workers=1")) tt.NoError(horizoncmd.RootCmd.Execute()) tt.NoError(historyQ.LatestLedger(context.Background(), &latestLedger)) tt.Equal(int64(0), latestLedger) - horizoncmd.RootCmd.SetArgs(command(horizonConfig, "db", "fill-gaps", "3", "4")) + horizoncmd.RootCmd.SetArgs(command(t, horizonConfig, "db", "fill-gaps", "3", "4")) tt.NoError(horizoncmd.RootCmd.Execute()) tt.NoError(historyQ.LatestLedger(context.Background(), &latestLedger)) tt.NoError(historyQ.ElderLedger(context.Background(), &oldestLedger)) tt.Equal(int64(3), oldestLedger) tt.Equal(int64(4), latestLedger) - horizoncmd.RootCmd.SetArgs(command(horizonConfig, "db", "fill-gaps", "6", "7")) + horizoncmd.RootCmd.SetArgs(command(t, horizonConfig, "db", "fill-gaps", "6", "7")) tt.NoError(horizoncmd.RootCmd.Execute()) tt.NoError(historyQ.LatestLedger(context.Background(), &latestLedger)) tt.NoError(historyQ.ElderLedger(context.Background(), &oldestLedger)) @@ -627,7 +716,7 @@ func TestFillGaps(t *testing.T) { tt.NoError(err) tt.Equal([]history.LedgerRange{{StartSequence: 5, EndSequence: 5}}, gaps) - horizoncmd.RootCmd.SetArgs(command(horizonConfig, "db", "fill-gaps")) + horizoncmd.RootCmd.SetArgs(command(t, horizonConfig, "db", "fill-gaps")) tt.NoError(horizoncmd.RootCmd.Execute()) tt.NoError(historyQ.LatestLedger(context.Background(), &latestLedger)) tt.NoError(historyQ.ElderLedger(context.Background(), &oldestLedger)) @@ -637,7 +726,7 @@ func TestFillGaps(t *testing.T) { tt.NoError(err) tt.Empty(gaps) - horizoncmd.RootCmd.SetArgs(command(horizonConfig, "db", "fill-gaps", "2", "8")) + horizoncmd.RootCmd.SetArgs(command(t, horizonConfig, "db", "fill-gaps", "2", "8")) tt.NoError(horizoncmd.RootCmd.Execute()) tt.NoError(historyQ.LatestLedger(context.Background(), &latestLedger)) tt.NoError(historyQ.ElderLedger(context.Background(), &oldestLedger)) diff --git a/services/horizon/internal/integration/extend_footprint_ttl_test.go b/services/horizon/internal/integration/extend_footprint_ttl_test.go new file mode 100644 index 0000000000..e280184b65 --- /dev/null +++ b/services/horizon/internal/integration/extend_footprint_ttl_test.go @@ -0,0 +1,50 @@ +package integration + +import ( + "testing" + + "github.com/stretchr/testify/require" + + "github.com/stellar/go/clients/horizonclient" + "github.com/stellar/go/protocols/horizon/operations" + "github.com/stellar/go/services/horizon/internal/test/integration" + "github.com/stellar/go/txnbuild" +) + +func TestExtendFootprintTtl(t *testing.T) { + if integration.GetCoreMaxSupportedProtocol() < 20 { + t.Skip("This test run does not support less than Protocol 20") + } + + itest := integration.NewTest(t, integration.Config{ + ProtocolVersion: 20, + EnableSorobanRPC: true, + }) + + // establish which account will be contract owner, and load it's current seq + sourceAccount, err := itest.Client().AccountDetail(horizonclient.AccountRequest{ + AccountID: itest.Master().Address(), + }) + require.NoError(t, err) + + installContractOp := assembleInstallContractCodeOp(t, itest.Master().Address(), add_u64_contract) + preFlightOp, minFee := itest.PreflightHostFunctions(&sourceAccount, *installContractOp) + tx := itest.MustSubmitOperationsWithFee(&sourceAccount, itest.Master(), minFee+txnbuild.MinBaseFee, &preFlightOp) + + _, err = itest.Client().TransactionDetail(tx.Hash) + require.NoError(t, err) + + sourceAccount, bumpFootPrint, minFee := itest.PreflightExtendExpiration( + itest.Master().Address(), + preFlightOp.Ext.SorobanData.Resources.Footprint.ReadWrite, + 10000, + ) + tx = itest.MustSubmitOperationsWithFee(&sourceAccount, itest.Master(), minFee+txnbuild.MinBaseFee, &bumpFootPrint) + + ops, err := itest.Client().Operations(horizonclient.OperationRequest{ForTransaction: tx.Hash}) + require.NoError(t, err) + require.Len(t, ops.Embedded.Records, 1) + + op := ops.Embedded.Records[0].(operations.ExtendFootprintTtl) + require.Equal(t, uint32(10000), op.ExtendTo) +} diff --git a/services/horizon/internal/integration/ingestion_filtering_test.go b/services/horizon/internal/integration/ingestion_filtering_test.go index 47cfc1ccbc..6d0bcee69e 100644 --- a/services/horizon/internal/integration/ingestion_filtering_test.go +++ b/services/horizon/internal/integration/ingestion_filtering_test.go @@ -13,29 +13,24 @@ import ( "github.com/stretchr/testify/assert" ) -func TestFilteringAccountWhiteList(t *testing.T) { +func TestFilteringWithNoFilters(t *testing.T) { tt := assert.New(t) const adminPort uint16 = 6000 itest := integration.NewTest(t, integration.Config{ HorizonIngestParameters: map[string]string{ - "admin-port": strconv.Itoa(int(adminPort)), - "exp-enable-ingestion-filtering": "true", + "admin-port": strconv.Itoa(int(adminPort)), }, }) fullKeys, accounts := itest.CreateAccounts(2, "10000") - whitelistedAccount := accounts[0] - whitelistedAccountKey := fullKeys[0] nonWhitelistedAccount := accounts[1] nonWhitelistedAccountKey := fullKeys[1] - enabled := true // all assets are allowed by default because the asset filter config is empty. defaultAllowedAsset := txnbuild.CreditAsset{Code: "PTS", Issuer: itest.Master().Address()} - itest.MustEstablishTrustline(whitelistedAccountKey, whitelistedAccount, defaultAllowedAsset) itest.MustEstablishTrustline(nonWhitelistedAccountKey, nonWhitelistedAccount, defaultAllowedAsset) - // assert that by system default, filters with no rules yet, allow all first + // Assert that by default, the system allows all the accounts. txResp := itest.MustSubmitOperations(itest.MasterAccount(), itest.Master(), &txnbuild.Payment{ Destination: nonWhitelistedAccount.GetAccountID(), @@ -43,9 +38,30 @@ func TestFilteringAccountWhiteList(t *testing.T) { Asset: defaultAllowedAsset, }, ) - txResp, err := itest.Client().TransactionDetail(txResp.Hash) tt.NoError(err) +} + +func TestFilteringAccountWhiteList(t *testing.T) { + tt := assert.New(t) + const adminPort uint16 = 6000 + itest := integration.NewTest(t, integration.Config{ + HorizonIngestParameters: map[string]string{ + "admin-port": strconv.Itoa(int(adminPort)), + }, + }) + + fullKeys, accounts := itest.CreateAccounts(2, "10000") + whitelistedAccount := accounts[0] + whitelistedAccountKey := fullKeys[0] + nonWhitelistedAccount := accounts[1] + nonWhitelistedAccountKey := fullKeys[1] + enabled := true + + // all assets are allowed by default because the asset filter config is empty. + defaultAllowedAsset := txnbuild.CreditAsset{Code: "PTS", Issuer: itest.Master().Address()} + itest.MustEstablishTrustline(whitelistedAccountKey, whitelistedAccount, defaultAllowedAsset) + itest.MustEstablishTrustline(nonWhitelistedAccountKey, nonWhitelistedAccount, defaultAllowedAsset) // Setup a whitelisted account rule, force refresh of filter configs to be quick filters.SetFilterConfigCheckIntervalSeconds(1) @@ -54,7 +70,7 @@ func TestFilteringAccountWhiteList(t *testing.T) { Whitelist: []string{whitelistedAccount.GetAccountID()}, Enabled: &enabled, } - err = itest.AdminClient().SetIngestionAccountFilter(expectedAccountFilter) + err := itest.AdminClient().SetIngestionAccountFilter(expectedAccountFilter) tt.NoError(err) accountFilter, err := itest.AdminClient().GetIngestionAccountFilter() @@ -67,7 +83,7 @@ func TestFilteringAccountWhiteList(t *testing.T) { time.Sleep(time.Duration(filters.GetFilterConfigCheckIntervalSeconds()) * time.Second) // Make sure that when using a non-whitelisted account, the transaction is not stored - txResp = itest.MustSubmitOperations(itest.MasterAccount(), itest.Master(), + txResp := itest.MustSubmitOperations(itest.MasterAccount(), itest.Master(), &txnbuild.Payment{ Destination: nonWhitelistedAccount.GetAccountID(), Amount: "10", @@ -94,8 +110,7 @@ func TestFilteringAssetWhiteList(t *testing.T) { const adminPort uint16 = 6000 itest := integration.NewTest(t, integration.Config{ HorizonIngestParameters: map[string]string{ - "admin-port": strconv.Itoa(int(adminPort)), - "exp-enable-ingestion-filtering": "true", + "admin-port": strconv.Itoa(int(adminPort)), }, }) @@ -110,18 +125,6 @@ func TestFilteringAssetWhiteList(t *testing.T) { itest.MustEstablishTrustline(defaultAllowedAccountKey, defaultAllowedAccount, nonWhitelistedAsset) enabled := true - // assert that by system default, filters with no rules yet, allow all first - txResp := itest.MustSubmitOperations(itest.MasterAccount(), itest.Master(), - &txnbuild.Payment{ - Destination: defaultAllowedAccount.GetAccountID(), - Amount: "10", - Asset: nonWhitelistedAsset, - }, - ) - - _, err := itest.Client().TransactionDetail(txResp.Hash) - tt.NoError(err) - // Setup a whitelisted asset rule, force refresh of filters to be quick filters.SetFilterConfigCheckIntervalSeconds(1) @@ -144,7 +147,7 @@ func TestFilteringAssetWhiteList(t *testing.T) { time.Sleep(time.Duration(filters.GetFilterConfigCheckIntervalSeconds()) * time.Second) // Make sure that when using a non-whitelisted asset, the transaction is not stored - txResp = itest.MustSubmitOperations(itest.MasterAccount(), itest.Master(), + txResp := itest.MustSubmitOperations(itest.MasterAccount(), itest.Master(), &txnbuild.Payment{ Destination: defaultAllowedAccount.GetAccountID(), Amount: "10", diff --git a/services/horizon/internal/integration/invokehostfunction_test.go b/services/horizon/internal/integration/invokehostfunction_test.go new file mode 100644 index 0000000000..275f0de23b --- /dev/null +++ b/services/horizon/internal/integration/invokehostfunction_test.go @@ -0,0 +1,386 @@ +package integration + +import ( + "crypto/sha256" + "encoding/hex" + "os" + "path/filepath" + "testing" + + "github.com/stellar/go/clients/horizonclient" + "github.com/stellar/go/protocols/horizon/operations" + "github.com/stellar/go/services/horizon/internal/test/integration" + "github.com/stellar/go/txnbuild" + "github.com/stellar/go/xdr" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +const add_u64_contract = "soroban_add_u64.wasm" +const increment_contract = "soroban_increment_contract.wasm" + +// Tests use precompiled wasm bin files that are added to the testdata directory. +// Refer to ./services/horizon/internal/integration/contracts/README.md on how to recompile +// contract code if needed to new wasm. + +func TestContractInvokeHostFunctionInstallContract(t *testing.T) { + if integration.GetCoreMaxSupportedProtocol() < 20 { + t.Skip("This test run does not support less than Protocol 20") + } + + itest := integration.NewTest(t, integration.Config{ + ProtocolVersion: 20, + EnableSorobanRPC: true, + }) + + // establish which account will be contract owner, and load it's current seq + sourceAccount, err := itest.Client().AccountDetail(horizonclient.AccountRequest{ + AccountID: itest.Master().Address(), + }) + require.NoError(t, err) + + installContractOp := assembleInstallContractCodeOp(t, itest.Master().Address(), add_u64_contract) + preFlightOp, minFee := itest.PreflightHostFunctions(&sourceAccount, *installContractOp) + tx := itest.MustSubmitOperationsWithFee(&sourceAccount, itest.Master(), minFee+txnbuild.MinBaseFee, &preFlightOp) + + clientTx, err := itest.Client().TransactionDetail(tx.Hash) + require.NoError(t, err) + + assert.Equal(t, tx.Hash, clientTx.Hash) + var txResult xdr.TransactionResult + err = xdr.SafeUnmarshalBase64(clientTx.ResultXdr, &txResult) + require.NoError(t, err) + + var txEnv xdr.TransactionEnvelope + err = xdr.SafeUnmarshalBase64(clientTx.EnvelopeXdr, &txEnv) + require.NoError(t, err) + + opResults, ok := txResult.OperationResults() + assert.True(t, ok) + assert.Equal(t, len(opResults), 1) + invokeHostFunctionResult, ok := opResults[0].MustTr().GetInvokeHostFunctionResult() + assert.True(t, ok) + assert.Equal(t, invokeHostFunctionResult.Code, xdr.InvokeHostFunctionResultCodeInvokeHostFunctionSuccess) + + clientInvokeOp, err := itest.Client().Operations(horizonclient.OperationRequest{ + ForTransaction: tx.Hash, + }) + require.NoError(t, err) + + invokeHostFunctionOpJson, ok := clientInvokeOp.Embedded.Records[0].(operations.InvokeHostFunction) + assert.True(t, ok) + assert.Equal(t, invokeHostFunctionOpJson.Function, "HostFunctionTypeHostFunctionTypeUploadContractWasm") + +} + +func TestContractInvokeHostFunctionCreateContractByAddress(t *testing.T) { + if integration.GetCoreMaxSupportedProtocol() < 20 { + t.Skip("This test run does not support less than Protocol 20") + } + + itest := integration.NewTest(t, integration.Config{ + ProtocolVersion: 20, + EnableSorobanRPC: true, + }) + + // establish which account will be contract owner, and load it's current seq + sourceAccount, err := itest.Client().AccountDetail(horizonclient.AccountRequest{ + AccountID: itest.Master().Address(), + }) + require.NoError(t, err) + + // Install the contract + installContractOp := assembleInstallContractCodeOp(t, itest.Master().Address(), add_u64_contract) + preFlightOp, minFee := itest.PreflightHostFunctions(&sourceAccount, *installContractOp) + itest.MustSubmitOperationsWithFee(&sourceAccount, itest.Master(), minFee+txnbuild.MinBaseFee, &preFlightOp) + + // Create the contract + createContractOp := assembleCreateContractOp(t, itest.Master().Address(), add_u64_contract, "a1", itest.GetPassPhrase()) + preFlightOp, minFee = itest.PreflightHostFunctions(&sourceAccount, *createContractOp) + tx, err := itest.SubmitOperationsWithFee(&sourceAccount, itest.Master(), minFee+txnbuild.MinBaseFee, &preFlightOp) + require.NoError(t, err) + + clientTx, err := itest.Client().TransactionDetail(tx.Hash) + require.NoError(t, err) + + assert.Equal(t, tx.Hash, clientTx.Hash) + var txResult xdr.TransactionResult + err = xdr.SafeUnmarshalBase64(clientTx.ResultXdr, &txResult) + require.NoError(t, err) + + opResults, ok := txResult.OperationResults() + assert.True(t, ok) + assert.Equal(t, len(opResults), 1) + invokeHostFunctionResult, ok := opResults[0].MustTr().GetInvokeHostFunctionResult() + assert.True(t, ok) + assert.Equal(t, invokeHostFunctionResult.Code, xdr.InvokeHostFunctionResultCodeInvokeHostFunctionSuccess) + + clientInvokeOp, err := itest.Client().Operations(horizonclient.OperationRequest{ + ForTransaction: tx.Hash, + }) + require.NoError(t, err) + + invokeHostFunctionOpJson, ok := clientInvokeOp.Embedded.Records[0].(operations.InvokeHostFunction) + assert.True(t, ok) + assert.Equal(t, invokeHostFunctionOpJson.Function, "HostFunctionTypeHostFunctionTypeCreateContract") + assert.Equal(t, invokeHostFunctionOpJson.Address, sourceAccount.AccountID) + assert.Equal(t, invokeHostFunctionOpJson.Salt, "110986164698320180327942133831752629430491002266485370052238869825166557303060") +} + +func TestContractInvokeHostFunctionInvokeStatelessContractFn(t *testing.T) { + if integration.GetCoreMaxSupportedProtocol() < 20 { + t.Skip("This test run does not support less than Protocol 20") + } + + itest := integration.NewTest(t, integration.Config{ + ProtocolVersion: 20, + EnableSorobanRPC: true, + }) + + // establish which account will be contract owner + sourceAccount, err := itest.Client().AccountDetail(horizonclient.AccountRequest{ + AccountID: itest.Master().Address(), + }) + require.NoError(t, err) + + // Install the contract + installContractOp := assembleInstallContractCodeOp(t, itest.Master().Address(), add_u64_contract) + preFlightOp, minFee := itest.PreflightHostFunctions(&sourceAccount, *installContractOp) + itest.MustSubmitOperationsWithFee(&sourceAccount, itest.Master(), minFee+txnbuild.MinBaseFee, &preFlightOp) + + // Create the contract + createContractOp := assembleCreateContractOp(t, itest.Master().Address(), add_u64_contract, "a1", itest.GetPassPhrase()) + preFlightOp, minFee = itest.PreflightHostFunctions(&sourceAccount, *createContractOp) + tx, err := itest.SubmitOperationsWithFee(&sourceAccount, itest.Master(), minFee+txnbuild.MinBaseFee, &preFlightOp) + require.NoError(t, err) + + // contract has been deployed, now invoke a simple 'add' fn on the contract + contractID := preFlightOp.Ext.SorobanData.Resources.Footprint.ReadWrite[0].MustContractData().Contract.ContractId + require.NotNil(t, contractID) + + contractIDAddress := xdr.ScAddress{ + Type: xdr.ScAddressTypeScAddressTypeContract, + ContractId: contractID, + } + firstParamValue := xdr.Uint64(4) + secondParamValue := xdr.Uint64(5) + + firstParamScVal := xdr.ScVal{ + Type: xdr.ScValTypeScvU64, + U64: &firstParamValue, + } + secondParamScVal := xdr.ScVal{ + Type: xdr.ScValTypeScvU64, + U64: &secondParamValue, + } + + invokeHostFunctionOp := &txnbuild.InvokeHostFunction{ + HostFunction: xdr.HostFunction{ + Type: xdr.HostFunctionTypeHostFunctionTypeInvokeContract, + InvokeContract: &xdr.InvokeContractArgs{ + ContractAddress: contractIDAddress, + FunctionName: "add", + Args: xdr.ScVec{ + firstParamScVal, + secondParamScVal, + }, + }, + }, + SourceAccount: sourceAccount.AccountID, + } + + preFlightOp, minFee = itest.PreflightHostFunctions(&sourceAccount, *invokeHostFunctionOp) + tx, err = itest.SubmitOperationsWithFee(&sourceAccount, itest.Master(), minFee+txnbuild.MinBaseFee, &preFlightOp) + require.NoError(t, err) + + clientTx, err := itest.Client().TransactionDetail(tx.Hash) + require.NoError(t, err) + + assert.Equal(t, tx.Hash, clientTx.Hash) + var txResult xdr.TransactionResult + err = xdr.SafeUnmarshalBase64(clientTx.ResultXdr, &txResult) + require.NoError(t, err) + + opResults, ok := txResult.OperationResults() + assert.True(t, ok) + assert.Equal(t, len(opResults), 1) + invokeHostFunctionResult, ok := opResults[0].MustTr().GetInvokeHostFunctionResult() + assert.True(t, ok) + assert.Equal(t, invokeHostFunctionResult.Code, xdr.InvokeHostFunctionResultCodeInvokeHostFunctionSuccess) + + // check the function response, should have summed the two input numbers + invokeResult := xdr.Uint64(9) + expectedScVal := xdr.ScVal{Type: xdr.ScValTypeScvU64, U64: &invokeResult} + var transactionMeta xdr.TransactionMeta + assert.NoError(t, xdr.SafeUnmarshalBase64(tx.ResultMetaXdr, &transactionMeta)) + assert.True(t, expectedScVal.Equals(transactionMeta.V3.SorobanMeta.ReturnValue)) + + clientInvokeOp, err := itest.Client().Operations(horizonclient.OperationRequest{ + ForTransaction: tx.Hash, + }) + require.NoError(t, err) + + invokeHostFunctionOpJson, ok := clientInvokeOp.Embedded.Records[0].(operations.InvokeHostFunction) + assert.True(t, ok) + assert.Len(t, invokeHostFunctionOpJson.Parameters, 4) + assert.Equal(t, invokeHostFunctionOpJson.Function, "HostFunctionTypeHostFunctionTypeInvokeContract") + addressParam, err := xdr.MarshalBase64(xdr.ScVal{Type: xdr.ScValTypeScvAddress, Address: &contractIDAddress}) + require.NoError(t, err) + assert.Equal(t, invokeHostFunctionOpJson.Parameters[0].Value, addressParam) + assert.Equal(t, invokeHostFunctionOpJson.Parameters[0].Type, "Address") + assert.Equal(t, invokeHostFunctionOpJson.Parameters[1].Value, "AAAADwAAAANhZGQA") + assert.Equal(t, invokeHostFunctionOpJson.Parameters[1].Type, "Sym") + assert.Equal(t, invokeHostFunctionOpJson.Parameters[2].Value, "AAAABQAAAAAAAAAE") + assert.Equal(t, invokeHostFunctionOpJson.Parameters[2].Type, "U64") + assert.Equal(t, invokeHostFunctionOpJson.Parameters[3].Value, "AAAABQAAAAAAAAAF") + assert.Equal(t, invokeHostFunctionOpJson.Parameters[3].Type, "U64") +} + +func TestContractInvokeHostFunctionInvokeStatefulContractFn(t *testing.T) { + if integration.GetCoreMaxSupportedProtocol() < 20 { + t.Skip("This test run does not support less than Protocol 20") + } + + itest := integration.NewTest(t, integration.Config{ + ProtocolVersion: 20, + EnableSorobanRPC: true, + }) + + // establish which account will be contract owner + sourceAccount, err := itest.Client().AccountDetail(horizonclient.AccountRequest{ + AccountID: itest.Master().Address(), + }) + require.NoError(t, err) + + // Install the contract + + installContractOp := assembleInstallContractCodeOp(t, itest.Master().Address(), increment_contract) + preFlightOp, minFee := itest.PreflightHostFunctions(&sourceAccount, *installContractOp) + itest.MustSubmitOperationsWithFee(&sourceAccount, itest.Master(), minFee+txnbuild.MinBaseFee, &preFlightOp) + + // Create the contract + + createContractOp := assembleCreateContractOp(t, itest.Master().Address(), increment_contract, "a1", itest.GetPassPhrase()) + preFlightOp, minFee = itest.PreflightHostFunctions(&sourceAccount, *createContractOp) + tx, err := itest.SubmitOperationsWithFee(&sourceAccount, itest.Master(), minFee+txnbuild.MinBaseFee, &preFlightOp) + require.NoError(t, err) + + // contract has been deployed, now invoke a simple 'add' fn on the contract + contractID := preFlightOp.Ext.SorobanData.Resources.Footprint.ReadWrite[0].MustContractData().Contract.ContractId + require.NotNil(t, contractID) + contractIDAddress := xdr.ScAddress{ + Type: xdr.ScAddressTypeScAddressTypeContract, + ContractId: contractID, + } + + invokeHostFunctionOp := &txnbuild.InvokeHostFunction{ + HostFunction: xdr.HostFunction{ + Type: xdr.HostFunctionTypeHostFunctionTypeInvokeContract, + InvokeContract: &xdr.InvokeContractArgs{ + ContractAddress: contractIDAddress, + FunctionName: "increment", + Args: nil, + }, + }, + SourceAccount: sourceAccount.AccountID, + } + + preFlightOp, minFee = itest.PreflightHostFunctions(&sourceAccount, *invokeHostFunctionOp) + tx, err = itest.SubmitOperationsWithFee(&sourceAccount, itest.Master(), minFee+txnbuild.MinBaseFee, &preFlightOp) + require.NoError(t, err) + + clientTx, err := itest.Client().TransactionDetail(tx.Hash) + require.NoError(t, err) + + assert.Equal(t, tx.Hash, clientTx.Hash) + var txResult xdr.TransactionResult + err = xdr.SafeUnmarshalBase64(clientTx.ResultXdr, &txResult) + require.NoError(t, err) + + opResults, ok := txResult.OperationResults() + assert.True(t, ok) + assert.Equal(t, len(opResults), 1) + invokeHostFunctionResult, ok := opResults[0].MustTr().GetInvokeHostFunctionResult() + assert.True(t, ok) + assert.Equal(t, invokeHostFunctionResult.Code, xdr.InvokeHostFunctionResultCodeInvokeHostFunctionSuccess) + + // check the function response, should have incremented state from 0 to 1 + invokeResult := xdr.Uint32(1) + expectedScVal := xdr.ScVal{Type: xdr.ScValTypeScvU32, U32: &invokeResult} + var transactionMeta xdr.TransactionMeta + assert.NoError(t, xdr.SafeUnmarshalBase64(clientTx.ResultMetaXdr, &transactionMeta)) + assert.True(t, expectedScVal.Equals(transactionMeta.V3.SorobanMeta.ReturnValue)) + + clientInvokeOp, err := itest.Client().Operations(horizonclient.OperationRequest{ + ForTransaction: tx.Hash, + }) + require.NoError(t, err) + + invokeHostFunctionOpJson, ok := clientInvokeOp.Embedded.Records[0].(operations.InvokeHostFunction) + assert.True(t, ok) + assert.Len(t, invokeHostFunctionOpJson.Parameters, 2) + assert.Equal(t, invokeHostFunctionOpJson.Function, "HostFunctionTypeHostFunctionTypeInvokeContract") + addressParam, err := xdr.MarshalBase64(xdr.ScVal{Type: xdr.ScValTypeScvAddress, Address: &contractIDAddress}) + require.NoError(t, err) + assert.Equal(t, invokeHostFunctionOpJson.Parameters[0].Value, addressParam) + assert.Equal(t, invokeHostFunctionOpJson.Parameters[0].Type, "Address") + assert.Equal(t, invokeHostFunctionOpJson.Parameters[1].Value, "AAAADwAAAAlpbmNyZW1lbnQAAAA=") + assert.Equal(t, invokeHostFunctionOpJson.Parameters[1].Type, "Sym") +} + +func assembleInstallContractCodeOp(t *testing.T, sourceAccount string, wasmFileName string) *txnbuild.InvokeHostFunction { + // Assemble the InvokeHostFunction UploadContractWasm operation: + // CAP-0047 - https://github.com/stellar/stellar-protocol/blob/master/core/cap-0047.md#creating-a-contract-using-invokehostfunctionop + + contract, err := os.ReadFile(filepath.Join("testdata", wasmFileName)) + require.NoError(t, err) + t.Logf("Contract File Contents: %v", hex.EncodeToString(contract)) + + return &txnbuild.InvokeHostFunction{ + HostFunction: xdr.HostFunction{ + Type: xdr.HostFunctionTypeHostFunctionTypeUploadContractWasm, + Wasm: &contract, + }, + SourceAccount: sourceAccount, + } +} + +func assembleCreateContractOp(t *testing.T, sourceAccount string, wasmFileName string, contractSalt string, passPhrase string) *txnbuild.InvokeHostFunction { + // Assemble the InvokeHostFunction CreateContract operation: + // CAP-0047 - https://github.com/stellar/stellar-protocol/blob/master/core/cap-0047.md#creating-a-contract-using-invokehostfunctionop + + contract, err := os.ReadFile(filepath.Join("testdata", wasmFileName)) + require.NoError(t, err) + + salt := sha256.Sum256([]byte(contractSalt)) + t.Logf("Salt hash: %v", hex.EncodeToString(salt[:])) + saltParameter := xdr.Uint256(salt) + + accountId := xdr.MustAddress(sourceAccount) + require.NoError(t, err) + contractHash := xdr.Hash(sha256.Sum256(contract)) + + return &txnbuild.InvokeHostFunction{ + HostFunction: xdr.HostFunction{ + Type: xdr.HostFunctionTypeHostFunctionTypeCreateContract, + CreateContract: &xdr.CreateContractArgs{ + ContractIdPreimage: xdr.ContractIdPreimage{ + Type: xdr.ContractIdPreimageTypeContractIdPreimageFromAddress, + FromAddress: &xdr.ContractIdPreimageFromAddress{ + Address: xdr.ScAddress{ + Type: xdr.ScAddressTypeScAddressTypeAccount, + AccountId: &accountId, + }, + Salt: saltParameter, + }, + }, + Executable: xdr.ContractExecutable{ + Type: xdr.ContractExecutableTypeContractExecutableWasm, + WasmHash: &contractHash, + }, + }, + }, + SourceAccount: sourceAccount, + } +} diff --git a/services/horizon/internal/integration/liquidity_pool_test.go b/services/horizon/internal/integration/liquidity_pool_test.go index 3b8770ed2b..9106003179 100644 --- a/services/horizon/internal/integration/liquidity_pool_test.go +++ b/services/horizon/internal/integration/liquidity_pool_test.go @@ -88,8 +88,8 @@ func TestLiquidityPoolHappyPath(t *testing.T) { LiquidityPoolID: [32]byte(poolID), MaxAmountA: "400", MaxAmountB: "777", - MinPrice: xdr.Price{1, 2}, - MaxPrice: xdr.Price{2, 1}, + MinPrice: xdr.Price{N: 1, D: 2}, + MaxPrice: xdr.Price{N: 2, D: 1}, }, ) @@ -475,8 +475,8 @@ func TestLiquidityPoolRevoke(t *testing.T) { LiquidityPoolID: [32]byte(poolID), MaxAmountA: "400", MaxAmountB: "777", - MinPrice: xdr.Price{1, 2}, - MaxPrice: xdr.Price{2, 1}, + MinPrice: xdr.Price{N: 1, D: 2}, + MaxPrice: xdr.Price{N: 2, D: 1}, }, &txnbuild.SetTrustLineFlags{ SourceAccount: master.Address(), @@ -606,27 +606,45 @@ func TestLiquidityPoolRevoke(t *testing.T) { tt.Equal(master.Address(), ef4.Asset.Issuer) tt.Equal(shareAccount.GetAccountID(), ef4.Trustor) + // the ordering of the claimable_balance_created effects depends on + // the ids of the claimable balances which can vary between test runs. + // we assert that there will be two claimable balances created, + // one holding 777 usd and another holding 400 xlm but + // we don't know the ordering since it depends on the claimable + // balance ids which we don't know ahead of time. + usdAsset := fmt.Sprintf("USD:%s", master.Address()) + expectedAmount := map[string]string{ + usdAsset: "777.0000000", + "native": "400.0000000", + } ef5 := (effs.Embedded.Records[4]).(effects.ClaimableBalanceCreated) tt.Equal("claimable_balance_created", ef5.Type) - tt.Equal("native", ef5.Asset) - tt.Equal("400.0000000", ef5.Amount) + var expectedNextAsset string + if ef5.Asset == usdAsset { + expectedNextAsset = "native" + } else if ef5.Asset == "native" { + expectedNextAsset = usdAsset + } else { + tt.Failf("unexpected asset %v", ef5.Asset) + } + tt.Equal(expectedAmount[ef5.Asset], ef5.Amount) ef6 := (effs.Embedded.Records[5]).(effects.ClaimableBalanceClaimantCreated) tt.Equal("claimable_balance_claimant_created", ef6.Type) - tt.Equal("native", ef6.Asset) - tt.Equal("400.0000000", ef6.Amount) + tt.Equal(ef5.Asset, ef6.Asset) + tt.Equal(ef5.Amount, ef6.Amount) tt.Equal(shareKeys.Address(), ef6.Account) tt.Equal(xdr.ClaimPredicateTypeClaimPredicateUnconditional, ef6.Predicate.Type) ef7 := (effs.Embedded.Records[6]).(effects.ClaimableBalanceCreated) tt.Equal("claimable_balance_created", ef7.Type) - tt.Equal(fmt.Sprintf("USD:%s", master.Address()), ef7.Asset) - tt.Equal("777.0000000", ef7.Amount) + tt.Equal(expectedNextAsset, ef7.Asset) + tt.Equal(expectedAmount[ef7.Asset], ef7.Amount) ef8 := (effs.Embedded.Records[7]).(effects.ClaimableBalanceClaimantCreated) tt.Equal("claimable_balance_claimant_created", ef8.Type) - tt.Equal(fmt.Sprintf("USD:%s", master.Address()), ef8.Asset) - tt.Equal("777.0000000", ef8.Amount) + tt.Equal(ef7.Asset, ef8.Asset) + tt.Equal(ef7.Amount, ef8.Amount) tt.Equal(shareKeys.Address(), ef8.Account) tt.Equal(xdr.ClaimPredicateTypeClaimPredicateUnconditional, ef8.Predicate.Type) @@ -667,8 +685,8 @@ func TestLiquidityPoolFailedDepositAndWithdraw(t *testing.T) { LiquidityPoolID: nonExistentPoolID, MaxAmountA: "400", MaxAmountB: "777", - MinPrice: xdr.Price{1, 2}, - MaxPrice: xdr.Price{2, 1}, + MinPrice: xdr.Price{N: 1, D: 2}, + MaxPrice: xdr.Price{N: 2, D: 1}, }, ) _, err = itest.Client().SubmitTransaction(tx) diff --git a/services/horizon/internal/integration/muxed_operations_test.go b/services/horizon/internal/integration/muxed_operations_test.go index 092b4152ee..53d9fbf23c 100644 --- a/services/horizon/internal/integration/muxed_operations_test.go +++ b/services/horizon/internal/integration/muxed_operations_test.go @@ -42,23 +42,23 @@ func TestMuxedOperations(t *testing.T) { }, &txnbuild.ChangeTrust{ SourceAccount: sponsoredMuxed.Address(), - Line: txnbuild.CreditAsset{"ABCD", master.Address()}.MustToChangeTrustAsset(), + Line: txnbuild.CreditAsset{Code: "ABCD", Issuer: master.Address()}.MustToChangeTrustAsset(), Limit: txnbuild.MaxTrustlineLimit, }, &txnbuild.ManageSellOffer{ SourceAccount: sponsoredMuxed.Address(), Selling: txnbuild.NativeAsset{}, - Buying: txnbuild.CreditAsset{"ABCD", master.Address()}, + Buying: txnbuild.CreditAsset{Code: "ABCD", Issuer: master.Address()}, Amount: "3", - Price: xdr.Price{1, 1}, + Price: xdr.Price{N: 1, D: 1}, }, // This will generate a trade effect: &txnbuild.ManageSellOffer{ SourceAccount: masterMuxed.Address(), - Selling: txnbuild.CreditAsset{"ABCD", master.Address()}, + Selling: txnbuild.CreditAsset{Code: "ABCD", Issuer: master.Address()}, Buying: txnbuild.NativeAsset{}, Amount: "3", - Price: xdr.Price{1, 1}, + Price: xdr.Price{N: 1, D: 1}, }, &txnbuild.ManageData{ SourceAccount: sponsoredMuxed.Address(), @@ -93,11 +93,11 @@ func TestMuxedOperations(t *testing.T) { SourceAccount: sponsoredMuxed.Address(), Destination: master.Address(), Amount: "3", - Asset: txnbuild.CreditAsset{"ABCD", master.Address()}, + Asset: txnbuild.CreditAsset{Code: "ABCD", Issuer: master.Address()}, }, &txnbuild.ChangeTrust{ SourceAccount: sponsoredMuxed.Address(), - Line: txnbuild.CreditAsset{"ABCD", master.Address()}.MustToChangeTrustAsset(), + Line: txnbuild.CreditAsset{Code: "ABCD", Issuer: master.Address()}.MustToChangeTrustAsset(), Limit: "0", }, &txnbuild.ManageData{ diff --git a/services/horizon/internal/integration/parameters_test.go b/services/horizon/internal/integration/parameters_test.go index f33be9b2ab..97fab268bc 100644 --- a/services/horizon/internal/integration/parameters_test.go +++ b/services/horizon/internal/integration/parameters_test.go @@ -2,31 +2,45 @@ package integration import ( + "bytes" + "fmt" + "io" "io/ioutil" + stdLog "log" "os" - "os/exec" "path" "strings" + "sync" "testing" + "time" + "github.com/spf13/cobra" "github.com/stellar/go/services/horizon/internal/paths" "github.com/stellar/go/services/horizon/internal/simplepath" + horizoncmd "github.com/stellar/go/services/horizon/cmd" horizon "github.com/stellar/go/services/horizon/internal" "github.com/stellar/go/services/horizon/internal/test/integration" "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/suite" ) var defaultCaptiveCoreParameters = map[string]string{ horizon.StellarCoreBinaryPathName: os.Getenv("CAPTIVE_CORE_BIN"), horizon.StellarCoreURLFlagName: "", - horizon.StellarCoreDBURLFlagName: "", +} + +var networkParamArgs = map[string]string{ + horizon.CaptiveCoreConfigPathName: "", + horizon.CaptiveCoreHTTPPortFlagName: "", + horizon.StellarCoreBinaryPathName: "", + horizon.StellarCoreURLFlagName: "", + horizon.HistoryArchiveURLsFlagName: "", + horizon.NetworkPassphraseFlagName: "", } const ( - SIMPLE_CAPTIVE_CORE_TOML = ` + SimpleCaptiveCoreToml = ` PEER_PORT=11725 ARTIFICIALLY_ACCELERATE_TIME_FOR_TESTING=true @@ -39,101 +53,244 @@ const ( PUBLIC_KEY="GD5KD2KEZJIGTC63IGW6UMUSMVUVG5IHG64HUTFWCHVZH2N2IBOQN7PS" ADDRESS="localhost" QUALITY="MEDIUM"` -) -func NewParameterTest(t *testing.T, params map[string]string) *integration.Test { - return NewParameterTestWithEnv(t, params, map[string]string{}) -} - -func NewParameterTestWithEnv(t *testing.T, params, envvars map[string]string) *integration.Test { - config := integration.Config{ - ProtocolVersion: 17, - SkipHorizonStart: true, - HorizonIngestParameters: params, - HorizonEnvironment: envvars, - } - return integration.NewTest(t, config) -} + StellarCoreURL = "http://localhost:11626" +) -func TestFatalScenarios(t *testing.T) { - suite.Run(t, new(FatalTestCase)) -} +var ( + CaptiveCoreConfigErrMsg = "error generating captive core configuration: invalid config: " +) // Ensures that BUCKET_DIR_PATH is not an allowed value for Captive Core. -func (suite *FatalTestCase) TestBucketDirDisallowed() { +func TestBucketDirDisallowed(t *testing.T) { // This is a bit of a hacky workaround. // // In CI, we run our integration tests twice: once with Captive Core // enabled, and once without. *These* tests only run with Captive Core // configured properly (specifically, w/ the CAPTIVE_CORE_BIN envvar set). if !integration.RunWithCaptiveCore { - suite.T().Skip() + t.Skip() } config := `BUCKET_DIR_PATH="/tmp" - ` + SIMPLE_CAPTIVE_CORE_TOML + ` + SimpleCaptiveCoreToml confName, _, cleanup := createCaptiveCoreConfig(config) defer cleanup() - - test := NewParameterTest(suite.T(), map[string]string{ + testConfig := integration.GetTestConfig() + testConfig.HorizonIngestParameters = map[string]string{ horizon.CaptiveCoreConfigPathName: confName, horizon.StellarCoreBinaryPathName: os.Getenv("CAPTIVE_CORE_BIN"), - }) - - suite.Exits(func() { test.StartHorizon() }) + } + test := integration.NewTest(t, *testConfig) + err := test.StartHorizon() + assert.Equal(t, err.Error(), integration.HorizonInitErrStr+": error generating captive core configuration:"+ + " invalid captive core toml file: could not unmarshal captive core toml: setting BUCKET_DIR_PATH is disallowed"+ + " for Captive Core, use CAPTIVE_CORE_STORAGE_PATH instead") + time.Sleep(1 * time.Second) + test.StopHorizon() + test.Shutdown() } -func (suite *FatalTestCase) TestEnvironmentPreserved() { +func TestEnvironmentPreserved(t *testing.T) { // Who tests the tests? This test. // // It ensures that the global OS environmental variables are preserved after // running an integration test. - t := suite.T() // Note that we ALSO need to make sure we don't modify parent env state. - if value, isSet := os.LookupEnv("CAPTIVE_CORE_CONFIG_PATH"); isSet { - defer func() { - os.Setenv("CAPTIVE_CORE_CONFIG_PATH", value) - }() - } - - err := os.Setenv("CAPTIVE_CORE_CONFIG_PATH", "original value") + value, isSet := os.LookupEnv("STELLAR_CORE_URL") + defer func() { + if isSet { + _ = os.Setenv("STELLAR_CORE_URL", value) + } else { + _ = os.Unsetenv("STELLAR_CORE_URL") + } + }() + + err := os.Setenv("STELLAR_CORE_URL", "original value") assert.NoError(t, err) - confName, _, cleanup := createCaptiveCoreConfig(SIMPLE_CAPTIVE_CORE_TOML) - defer cleanup() - test := NewParameterTestWithEnv(t, map[string]string{}, map[string]string{ - "CAPTIVE_CORE_CONFIG_PATH": confName, - }) + testConfig := integration.GetTestConfig() + testConfig.HorizonEnvironment = map[string]string{ + "STELLAR_CORE_URL": StellarCoreURL, + } + test := integration.NewTest(t, *testConfig) err = test.StartHorizon() assert.NoError(t, err) test.WaitForHorizon() - envValue := os.Getenv("CAPTIVE_CORE_CONFIG_PATH") - assert.Equal(t, confName, envValue) + envValue := os.Getenv("STELLAR_CORE_URL") + assert.Equal(t, StellarCoreURL, envValue) test.Shutdown() - envValue = os.Getenv("CAPTIVE_CORE_CONFIG_PATH") + envValue = os.Getenv("STELLAR_CORE_URL") assert.Equal(t, "original value", envValue) } +// TestInvalidNetworkParameters Ensure that Horizon returns an error when +// using NETWORK environment variables, history archive urls or network passphrase +// parameters are also set. +func TestInvalidNetworkParameters(t *testing.T) { + if !integration.RunWithCaptiveCore { + t.Skip() + } + + var captiveCoreConfigErrMsg = integration.HorizonInitErrStr + ": error generating captive " + + "core configuration: invalid config: %s parameter not allowed with the %s parameter" + testCases := []struct { + name string + errMsg string + networkValue string + param string + }{ + { + name: "history archive urls validation", + errMsg: fmt.Sprintf(captiveCoreConfigErrMsg, horizon.HistoryArchiveURLsFlagName, + horizon.NetworkFlagName), + networkValue: horizon.StellarPubnet, + param: horizon.HistoryArchiveURLsFlagName, + }, + { + name: "network-passphrase validation", + errMsg: fmt.Sprintf(captiveCoreConfigErrMsg, horizon.NetworkPassphraseFlagName, + horizon.NetworkFlagName), + networkValue: horizon.StellarTestnet, + param: horizon.NetworkPassphraseFlagName, + }, + } + + for _, testCase := range testCases { + t.Run(testCase.name, func(t *testing.T) { + localParams := integration.MergeMaps(networkParamArgs, map[string]string{ + horizon.NetworkFlagName: testCase.networkValue, + testCase.param: testCase.param, // set any value + }) + testConfig := integration.GetTestConfig() + testConfig.SkipCoreContainerCreation = true + testConfig.HorizonIngestParameters = localParams + test := integration.NewTest(t, *testConfig) + err := test.StartHorizon() + // Adding sleep as a workaround for the race condition in the ingestion system. + // https://github.com/stellar/go/issues/5005 + time.Sleep(2 * time.Second) + assert.Equal(t, testCase.errMsg, err.Error()) + test.Shutdown() + }) + } +} + +// TestNetworkParameter Ensure that Horizon successfully starts the captive-core +// subprocess using the default configuration when --network [testnet|pubnet] +// commandline parameter. +// +// In integration tests, we start Horizon and stellar-core containers in standalone mode +// simultaneously. We usually wait for Horizon to begin ingesting to verify the test's +// success. However, for "pubnet" or "testnet," we can not wait for Horizon to catch up, +// so we skip starting stellar-core containers. +func TestNetworkParameter(t *testing.T) { + if !integration.RunWithCaptiveCore { + t.Skip() + } + testCases := []struct { + networkValue string + networkPassphrase string + historyArchiveURLs []string + }{ + { + networkValue: horizon.StellarTestnet, + networkPassphrase: horizon.TestnetConf.NetworkPassphrase, + historyArchiveURLs: horizon.TestnetConf.HistoryArchiveURLs, + }, + { + networkValue: horizon.StellarPubnet, + networkPassphrase: horizon.PubnetConf.NetworkPassphrase, + historyArchiveURLs: horizon.PubnetConf.HistoryArchiveURLs, + }, + } + for _, tt := range testCases { + t.Run(fmt.Sprintf("NETWORK parameter %s", tt.networkValue), func(t *testing.T) { + localParams := integration.MergeMaps(networkParamArgs, map[string]string{ + horizon.NetworkFlagName: tt.networkValue, + }) + testConfig := integration.GetTestConfig() + testConfig.SkipCoreContainerCreation = true + testConfig.HorizonIngestParameters = localParams + test := integration.NewTest(t, *testConfig) + err := test.StartHorizon() + // Adding sleep as a workaround for the race condition in the ingestion system. + // https://github.com/stellar/go/issues/5005 + time.Sleep(2 * time.Second) + assert.NoError(t, err) + assert.Equal(t, test.GetHorizonIngestConfig().HistoryArchiveURLs, tt.historyArchiveURLs) + assert.Equal(t, test.GetHorizonIngestConfig().NetworkPassphrase, tt.networkPassphrase) + + test.Shutdown() + }) + } +} + +// TestNetworkEnvironmentVariable Ensure that Horizon successfully starts the captive-core +// subprocess using the default configuration when the NETWORK environment variable is set +// to either pubnet or testnet. +// +// In integration tests, we start Horizon and stellar-core containers in standalone mode +// simultaneously. We usually wait for Horizon to begin ingesting to verify the test's +// success. However, for "pubnet" or "testnet," we can not wait for Horizon to catch up, +// so we skip starting stellar-core containers. +func TestNetworkEnvironmentVariable(t *testing.T) { + if !integration.RunWithCaptiveCore { + t.Skip() + } + testCases := []string{ + horizon.StellarPubnet, + horizon.StellarTestnet, + } + + for _, networkValue := range testCases { + t.Run(fmt.Sprintf("NETWORK environment variable %s", networkValue), func(t *testing.T) { + value, isSet := os.LookupEnv("NETWORK") + defer func() { + if isSet { + _ = os.Setenv("NETWORK", value) + } else { + _ = os.Unsetenv("NETWORK") + } + }() + + testConfig := integration.GetTestConfig() + testConfig.SkipCoreContainerCreation = true + testConfig.HorizonIngestParameters = networkParamArgs + testConfig.HorizonEnvironment = map[string]string{"NETWORK": networkValue} + test := integration.NewTest(t, *testConfig) + err := test.StartHorizon() + // Adding sleep here as a workaround for the race condition in the ingestion system. + // More details can be found at https://github.com/stellar/go/issues/5005 + time.Sleep(2 * time.Second) + assert.NoError(t, err) + test.Shutdown() + }) + } +} + // Ensures that the filesystem ends up in the correct state with Captive Core. func TestCaptiveCoreConfigFilesystemState(t *testing.T) { if !integration.RunWithCaptiveCore { t.Skip() // explained above } - confName, storagePath, cleanup := createCaptiveCoreConfig(SIMPLE_CAPTIVE_CORE_TOML) + confName, storagePath, cleanup := createCaptiveCoreConfig(SimpleCaptiveCoreToml) defer cleanup() localParams := integration.MergeMaps(defaultCaptiveCoreParameters, map[string]string{ "captive-core-storage-path": storagePath, horizon.CaptiveCoreConfigPathName: confName, }) - test := NewParameterTest(t, localParams) + testConfig := integration.GetTestConfig() + testConfig.HorizonIngestParameters = localParams + test := integration.NewTest(t, *testConfig) err := test.StartHorizon() assert.NoError(t, err) @@ -150,7 +307,7 @@ func TestCaptiveCoreConfigFilesystemState(t *testing.T) { func TestMaxAssetsForPathRequests(t *testing.T) { t.Run("default", func(t *testing.T) { - test := NewParameterTest(t, map[string]string{}) + test := integration.NewTest(t, *integration.GetTestConfig()) err := test.StartHorizon() assert.NoError(t, err) test.WaitForHorizon() @@ -158,7 +315,9 @@ func TestMaxAssetsForPathRequests(t *testing.T) { test.Shutdown() }) t.Run("set to 2", func(t *testing.T) { - test := NewParameterTest(t, map[string]string{"max-assets-per-path-request": "2"}) + testConfig := integration.GetTestConfig() + testConfig.HorizonIngestParameters = map[string]string{"max-assets-per-path-request": "2"} + test := integration.NewTest(t, *testConfig) err := test.StartHorizon() assert.NoError(t, err) test.WaitForHorizon() @@ -169,7 +328,7 @@ func TestMaxAssetsForPathRequests(t *testing.T) { func TestMaxPathFindingRequests(t *testing.T) { t.Run("default", func(t *testing.T) { - test := NewParameterTest(t, map[string]string{}) + test := integration.NewTest(t, *integration.GetTestConfig()) err := test.StartHorizon() assert.NoError(t, err) test.WaitForHorizon() @@ -179,7 +338,9 @@ func TestMaxPathFindingRequests(t *testing.T) { test.Shutdown() }) t.Run("set to 5", func(t *testing.T) { - test := NewParameterTest(t, map[string]string{"max-path-finding-requests": "5"}) + testConfig := integration.GetTestConfig() + testConfig.HorizonIngestParameters = map[string]string{"max-path-finding-requests": "5"} + test := integration.NewTest(t, *testConfig) err := test.StartHorizon() assert.NoError(t, err) test.WaitForHorizon() @@ -193,7 +354,7 @@ func TestMaxPathFindingRequests(t *testing.T) { func TestDisablePathFinding(t *testing.T) { t.Run("default", func(t *testing.T) { - test := NewParameterTest(t, map[string]string{}) + test := integration.NewTest(t, *integration.GetTestConfig()) err := test.StartHorizon() assert.NoError(t, err) test.WaitForHorizon() @@ -203,7 +364,9 @@ func TestDisablePathFinding(t *testing.T) { test.Shutdown() }) t.Run("set to true", func(t *testing.T) { - test := NewParameterTest(t, map[string]string{"disable-path-finding": "true"}) + testConfig := integration.GetTestConfig() + testConfig.HorizonIngestParameters = map[string]string{"disable-path-finding": "true"} + test := integration.NewTest(t, *testConfig) err := test.StartHorizon() assert.NoError(t, err) test.WaitForHorizon() @@ -212,34 +375,369 @@ func TestDisablePathFinding(t *testing.T) { }) } -// Pattern taken from testify issue: -// https://github.com/stretchr/testify/issues/858#issuecomment-600491003 -// -// This lets us run test cases that are *expected* to fail from a fatal error. -// -// For our purposes, if you *want* `StartHorizon()` to fail, you should wrap it -// in a lambda and pass it to `suite.Exits(...)`. -type FatalTestCase struct { - suite.Suite +func TestIngestionFilteringAlwaysDefaultingToTrue(t *testing.T) { + t.Run("ingestion filtering flag set to default value", func(t *testing.T) { + test := integration.NewTest(t, *integration.GetTestConfig()) + err := test.StartHorizon() + assert.NoError(t, err) + test.WaitForHorizon() + assert.Equal(t, test.HorizonIngest().Config().EnableIngestionFiltering, true) + test.Shutdown() + }) + t.Run("ingestion filtering flag set to false", func(t *testing.T) { + testConfig := integration.GetTestConfig() + testConfig.HorizonIngestParameters = map[string]string{"exp-enable-ingestion-filtering": "false"} + test := integration.NewTest(t, *testConfig) + err := test.StartHorizon() + assert.NoError(t, err) + test.WaitForHorizon() + assert.Equal(t, test.HorizonIngest().Config().EnableIngestionFiltering, true) + test.Shutdown() + }) } -func (t *FatalTestCase) Exits(subprocess func()) { - testName := t.T().Name() - if os.Getenv("ASSERT_EXISTS_"+testName) == "1" { - subprocess() - return - } +func TestDisableTxSub(t *testing.T) { + t.Run("require stellar-core-url when both DISABLE_TX_SUB=false and INGEST=false", func(t *testing.T) { + localParams := integration.MergeMaps(networkParamArgs, map[string]string{ + horizon.NetworkFlagName: "testnet", + horizon.IngestFlagName: "false", + horizon.DisableTxSubFlagName: "false", + }) + testConfig := integration.GetTestConfig() + testConfig.HorizonIngestParameters = localParams + testConfig.SkipCoreContainerCreation = true + test := integration.NewTest(t, *testConfig) + err := test.StartHorizon() + assert.ErrorContains(t, err, "cannot initialize Horizon: flag --stellar-core-url cannot be empty") + test.Shutdown() + }) + t.Run("horizon starts successfully when DISABLE_TX_SUB=false, INGEST=false and stellar-core-url is provided", func(t *testing.T) { + localParams := integration.MergeMaps(networkParamArgs, map[string]string{ + horizon.NetworkFlagName: "testnet", + horizon.IngestFlagName: "false", + horizon.DisableTxSubFlagName: "false", + horizon.StellarCoreURLFlagName: "http://localhost:11626", + }) + testConfig := integration.GetTestConfig() + testConfig.HorizonIngestParameters = localParams + testConfig.SkipCoreContainerCreation = true + test := integration.NewTest(t, *testConfig) + err := test.StartHorizon() + assert.NoError(t, err) + test.Shutdown() + }) + t.Run("horizon starts successfully when DISABLE_TX_SUB=true and INGEST=true", func(t *testing.T) { + testConfig := integration.GetTestConfig() + testConfig.HorizonIngestParameters = map[string]string{ + "disable-tx-sub": "true", + "ingest": "true", + } + test := integration.NewTest(t, *testConfig) + err := test.StartHorizon() + assert.NoError(t, err) + test.WaitForHorizon() + test.Shutdown() + }) + t.Run("do not require stellar-core-url when both DISABLE_TX_SUB=true and INGEST=false", func(t *testing.T) { + localParams := integration.MergeMaps(networkParamArgs, map[string]string{ + horizon.NetworkFlagName: "testnet", + horizon.IngestFlagName: "false", + horizon.DisableTxSubFlagName: "true", + }) + testConfig := integration.GetTestConfig() + testConfig.HorizonIngestParameters = localParams + testConfig.SkipCoreContainerCreation = true + test := integration.NewTest(t, *testConfig) + err := test.StartHorizon() + assert.NoError(t, err) + test.Shutdown() + }) +} - cmd := exec.Command(os.Args[0], "-test.run="+testName) - cmd.Env = append(os.Environ(), "ASSERT_EXISTS_"+testName+"=1") - err := cmd.Run() +func TestDeprecatedOutputs(t *testing.T) { + t.Run("deprecated output for ingestion filtering", func(t *testing.T) { + originalStderr := os.Stderr + r, w, _ := os.Pipe() + os.Stderr = w + stdLog.SetOutput(os.Stderr) - t.T().Log("Result:", err) - if e, ok := err.(*exec.ExitError); ok && !e.Success() { - return - } + testConfig := integration.GetTestConfig() + testConfig.HorizonIngestParameters = map[string]string{"exp-enable-ingestion-filtering": "false"} + test := integration.NewTest(t, *testConfig) + err := test.StartHorizon() + assert.NoError(t, err) + test.WaitForHorizon() - t.Fail("expecting unsuccessful exit, got", err) + // Use a wait group to wait for the goroutine to finish before proceeding + var wg sync.WaitGroup + wg.Add(1) + go func() { + defer wg.Done() + if err := w.Close(); err != nil { + t.Errorf("Failed to close Stdout") + return + } + }() + + outputBytes, _ := io.ReadAll(r) + wg.Wait() // Wait for the goroutine to finish before proceeding + _ = r.Close() + os.Stderr = originalStderr + + assert.Contains(t, string(outputBytes), "DEPRECATED - No ingestion filter rules are defined by default, which equates to "+ + "no filtering of historical data. If you have never added filter rules to this deployment, then no further action is needed. "+ + "If you have defined ingestion filter rules previously but disabled filtering overall by setting the env variable EXP_ENABLE_INGESTION_FILTERING=false, "+ + "then you should now delete the filter rules using the Horizon Admin API to achieve the same no-filtering result. Remove usage of this variable in all cases.") + }) + t.Run("deprecated output for command-line flags", func(t *testing.T) { + originalStderr := os.Stderr + r, w, _ := os.Pipe() + os.Stderr = w + stdLog.SetOutput(os.Stderr) + + config, flags := horizon.Flags() + + horizonCmd := &cobra.Command{ + Use: "horizon", + Short: "Client-facing api server for the Stellar network", + SilenceErrors: true, + SilenceUsage: true, + Long: "Client-facing API server for the Stellar network.", + RunE: func(cmd *cobra.Command, args []string) error { + _, err := horizon.NewAppFromFlags(config, flags) + if err != nil { + return err + } + return nil + }, + } + + horizonCmd.SetArgs([]string{"--disable-tx-sub=true"}) + if err := flags.Init(horizonCmd); err != nil { + fmt.Println(err) + } + if err := horizonCmd.Execute(); err != nil { + fmt.Println(err) + } + + // Use a wait group to wait for the goroutine to finish before proceeding + var wg sync.WaitGroup + wg.Add(1) + go func() { + defer wg.Done() + if err := w.Close(); err != nil { + t.Errorf("Failed to close Stdout") + return + } + }() + + outputBytes, _ := io.ReadAll(r) + wg.Wait() // Wait for the goroutine to finish before proceeding + _ = r.Close() + os.Stderr = originalStderr + + assert.Contains(t, string(outputBytes), "DEPRECATED - the use of command-line flags: "+ + "[--disable-tx-sub], has been deprecated in favor of environment variables. Please consult our "+ + "Configuring section in the developer documentation on how to use them - "+ + "https://developers.stellar.org/docs/run-api-server/configuring") + }) + t.Run("deprecated output for --stellar-core-db-url and --enable-captive-core-ingestion", func(t *testing.T) { + originalStderr := os.Stderr + r, w, _ := os.Pipe() + os.Stderr = w + stdLog.SetOutput(os.Stderr) + + testConfig := integration.GetTestConfig() + testConfig.HorizonIngestParameters = map[string]string{ + "stellar-core-db-url": "temp-url", + "enable-captive-core-ingestion": "true", + } + test := integration.NewTest(t, *testConfig) + err := test.StartHorizon() + assert.NoError(t, err) + test.WaitForHorizon() + + // Use a wait group to wait for the goroutine to finish before proceeding + var wg sync.WaitGroup + wg.Add(1) + go func() { + defer wg.Done() + if err := w.Close(); err != nil { + t.Errorf("Failed to close Stdout") + return + } + }() + + outputBytes, _ := io.ReadAll(r) + wg.Wait() // Wait for the goroutine to finish before proceeding + _ = r.Close() + os.Stderr = originalStderr + + assert.Contains(t, string(outputBytes), "DEPRECATED - The usage of the flag --stellar-core-db-url has been deprecated. "+ + "Horizon now uses Captive-Core ingestion by default and this flag will soon be removed in "+ + "the future.") + assert.Contains(t, string(outputBytes), "DEPRECATED - The usage of the flag --enable-captive-core-ingestion has been deprecated. "+ + "Horizon now uses Captive-Core ingestion by default and this flag will soon be removed in "+ + "the future.") + }) + t.Run("deprecated output for env vars STELLAR_CORE_DATABASE_URL and ENABLE_CAPTIVE_CORE_INGESTION", func(t *testing.T) { + originalStderr := os.Stderr + r, w, _ := os.Pipe() + os.Stderr = w + stdLog.SetOutput(os.Stderr) + + testConfig := integration.GetTestConfig() + testConfig.HorizonEnvironment = map[string]string{ + "STELLAR_CORE_DATABASE_URL": "temp-url", + "ENABLE_CAPTIVE_CORE_INGESTION": "true", + } + test := integration.NewTest(t, *testConfig) + err := test.StartHorizon() + assert.NoError(t, err) + test.WaitForHorizon() + + // Use a wait group to wait for the goroutine to finish before proceeding + var wg sync.WaitGroup + wg.Add(1) + go func() { + defer wg.Done() + if err := w.Close(); err != nil { + t.Errorf("Failed to close Stdout") + return + } + }() + + outputBytes, _ := io.ReadAll(r) + wg.Wait() // Wait for the goroutine to finish before proceeding + _ = r.Close() + os.Stderr = originalStderr + + assert.Contains(t, string(outputBytes), "DEPRECATED - The usage of the flag --stellar-core-db-url has been deprecated. "+ + "Horizon now uses Captive-Core ingestion by default and this flag will soon be removed in "+ + "the future.") + assert.Contains(t, string(outputBytes), "DEPRECATED - The usage of the flag --enable-captive-core-ingestion has been deprecated. "+ + "Horizon now uses Captive-Core ingestion by default and this flag will soon be removed in "+ + "the future.") + }) +} + +func TestGlobalFlagsOutput(t *testing.T) { + + // verify Help and Usage output from cli, both help and usage output follow the same + // output rules of no globals when sub-comands exist, and only relevant globals + // when down to leaf node command. + + dbParams := []string{"--max-db-connections", "--db-url"} + // the space after '--ingest' is intentional to ensure correct matching behavior to + // help output, as other flags also start with same prefix. + apiParams := []string{"--port ", "--per-hour-rate-limit", "--ingest ", "sentry-dsn"} + ingestionParams := []string{"--stellar-core-binary-path", "--history-archive-urls", "--ingest-state-verification-checkpoint-frequency"} + allParams := append(apiParams, append(dbParams, ingestionParams...)...) + + testCases := []struct { + horizonHelpCommand []string + helpPrintedGlobalParams []string + helpPrintedSubCommandParams []string + helpSkippedGlobalParams []string + }{ + { + horizonHelpCommand: []string{"ingest", "trigger-state-rebuild", "-h"}, + helpPrintedGlobalParams: dbParams, + helpPrintedSubCommandParams: []string{}, + helpSkippedGlobalParams: append(apiParams, ingestionParams...), + }, + { + horizonHelpCommand: []string{"ingest", "verify-range", "-h"}, + helpPrintedGlobalParams: append(dbParams, ingestionParams...), + helpPrintedSubCommandParams: []string{"--verify-state", "--from"}, + helpSkippedGlobalParams: apiParams, + }, + { + horizonHelpCommand: []string{"db", "reingest", "range", "-h"}, + helpPrintedGlobalParams: append(dbParams, ingestionParams...), + helpPrintedSubCommandParams: []string{"--parallel-workers", "--force"}, + helpSkippedGlobalParams: apiParams, + }, + { + horizonHelpCommand: []string{"db", "reingest", "range"}, + helpPrintedGlobalParams: append(dbParams, ingestionParams...), + helpPrintedSubCommandParams: []string{"--parallel-workers", "--force"}, + helpSkippedGlobalParams: apiParams, + }, + { + horizonHelpCommand: []string{"db", "fill-gaps", "-h"}, + helpPrintedGlobalParams: append(dbParams, ingestionParams...), + helpPrintedSubCommandParams: []string{"--parallel-workers", "--force"}, + helpSkippedGlobalParams: apiParams, + }, + { + horizonHelpCommand: []string{"db", "migrate", "up", "-h"}, + helpPrintedGlobalParams: dbParams, + helpPrintedSubCommandParams: []string{}, + helpSkippedGlobalParams: append(apiParams, ingestionParams...), + }, + { + horizonHelpCommand: []string{"db", "-h"}, + helpPrintedGlobalParams: []string{}, + helpPrintedSubCommandParams: []string{}, + helpSkippedGlobalParams: allParams, + }, + { + horizonHelpCommand: []string{"db"}, + helpPrintedGlobalParams: []string{}, + helpPrintedSubCommandParams: []string{}, + helpSkippedGlobalParams: allParams, + }, + { + horizonHelpCommand: []string{"-h"}, + helpPrintedGlobalParams: []string{}, + helpPrintedSubCommandParams: []string{}, + helpSkippedGlobalParams: allParams, + }, + { + horizonHelpCommand: []string{"db", "reingest", "-h"}, + helpPrintedGlobalParams: []string{}, + helpPrintedSubCommandParams: []string{}, + helpSkippedGlobalParams: apiParams, + }, + { + horizonHelpCommand: []string{"db", "reingest"}, + helpPrintedGlobalParams: []string{}, + helpPrintedSubCommandParams: []string{}, + helpSkippedGlobalParams: apiParams, + }, + { + horizonHelpCommand: []string{"serve", "-h"}, + helpPrintedGlobalParams: allParams, + helpPrintedSubCommandParams: []string{}, + helpSkippedGlobalParams: []string{}, + }, + { + horizonHelpCommand: []string{"record-metrics", "-h"}, + helpPrintedGlobalParams: []string{"--admin-port"}, + helpPrintedSubCommandParams: []string{}, + helpSkippedGlobalParams: allParams, + }, + } + for _, testCase := range testCases { + t.Run(fmt.Sprintf("Horizon command line parameter %v", testCase.horizonHelpCommand), func(t *testing.T) { + horizoncmd.RootCmd.SetArgs(testCase.horizonHelpCommand) + var writer io.Writer = &bytes.Buffer{} + horizoncmd.RootCmd.SetOutput(writer) + horizoncmd.RootCmd.Execute() + + output := writer.(*bytes.Buffer).String() + for _, requiredParam := range testCase.helpPrintedSubCommandParams { + assert.Contains(t, output, requiredParam, testCase.horizonHelpCommand) + } + for _, requiredParam := range testCase.helpPrintedGlobalParams { + assert.Contains(t, output, requiredParam, testCase.horizonHelpCommand) + } + for _, skippedParam := range testCase.helpSkippedGlobalParams { + assert.NotContains(t, output, skippedParam, testCase.horizonHelpCommand) + } + }) + } } // validateNoBucketDirPath ensures the Stellar Core auto-generated configuration diff --git a/services/horizon/internal/integration/protocol_19_upgrade_test.go b/services/horizon/internal/integration/protocol_19_upgrade_test.go index 1205260f59..66c7163053 100644 --- a/services/horizon/internal/integration/protocol_19_upgrade_test.go +++ b/services/horizon/internal/integration/protocol_19_upgrade_test.go @@ -45,7 +45,7 @@ func TestProtocol19Upgrade(t *testing.T) { }, Preconditions: txnbuild.Preconditions{ TimeBounds: txnbuild.NewInfiniteTimeout(), - LedgerBounds: &txnbuild.LedgerBounds{0, 100}, + LedgerBounds: &txnbuild.LedgerBounds{MinLedger: 0, MaxLedger: 100}, }, } _, err := itest.SubmitTransaction(master, txParams) diff --git a/services/horizon/internal/integration/sac_test.go b/services/horizon/internal/integration/sac_test.go new file mode 100644 index 0000000000..64c772b44c --- /dev/null +++ b/services/horizon/internal/integration/sac_test.go @@ -0,0 +1,1462 @@ +package integration + +import ( + "context" + "math" + "math/big" + "strings" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/stellar/go/amount" + "github.com/stellar/go/clients/horizonclient" + "github.com/stellar/go/keypair" + "github.com/stellar/go/protocols/horizon/effects" + "github.com/stellar/go/protocols/horizon/operations" + "github.com/stellar/go/services/horizon/internal/db2/history" + "github.com/stellar/go/services/horizon/internal/ingest/processors" + "github.com/stellar/go/services/horizon/internal/test/integration" + "github.com/stellar/go/strkey" + "github.com/stellar/go/txnbuild" + "github.com/stellar/go/xdr" +) + +const sac_contract = "soroban_sac_test.wasm" + +// LongTermTTL is used to extend the lifetime of ledger entries by 10000 ledgers. +// This will ensure that the ledger entries never expire during the execution +// of the integration tests. +const LongTermTTL = 10000 + +// Tests use precompiled wasm bin files that are added to the testdata directory. +// Refer to ./services/horizon/internal/integration/contracts/README.md on how to recompile +// contract code if needed to new wasm. + +func TestContractMintToAccount(t *testing.T) { + if integration.GetCoreMaxSupportedProtocol() < 20 { + t.Skip("This test run does not support less than Protocol 20") + } + + itest := integration.NewTest(t, integration.Config{ + ProtocolVersion: 20, + HorizonEnvironment: map[string]string{"INGEST_DISABLE_STATE_VERIFICATION": "true", "CONNECTION_TIMEOUT": "360000"}, + EnableSorobanRPC: true, + }) + + issuer := itest.Master().Address() + code := "USD" + asset := xdr.MustNewCreditAsset(code, issuer) + + createSAC(itest, asset) + + recipientKp, recipient := itest.CreateAccount("100") + itest.MustEstablishTrustline(recipientKp, recipient, txnbuild.MustAssetFromXDR(asset)) + + _, mintTx, _ := assertInvokeHostFnSucceeds( + itest, + itest.Master(), + mint(itest, issuer, asset, "20", accountAddressParam(recipient.GetAccountID())), + ) + + assertContainsBalance(itest, recipientKp, issuer, code, amount.MustParse("20")) + assertAssetStats(itest, assetStats{ + code: code, + issuer: issuer, + numAccounts: 1, + balanceAccounts: amount.MustParse("20"), + balanceArchivedContracts: big.NewInt(0), + numArchivedContracts: 0, + numContracts: 0, + balanceContracts: big.NewInt(0), + contractID: stellarAssetContractID(itest, asset), + }) + + fx := getTxEffects(itest, mintTx, asset) + require.Len(t, fx, 1) + creditEffect := assertContainsEffect(t, fx, + effects.EffectAccountCredited)[0].(effects.AccountCredited) + assert.Equal(t, recipientKp.Address(), creditEffect.Account) + assert.Equal(t, issuer, creditEffect.Asset.Issuer) + assert.Equal(t, code, creditEffect.Asset.Code) + assert.Equal(t, "20.0000000", creditEffect.Amount) + assertEventPayments(itest, mintTx, asset, "", recipient.GetAccountID(), "mint", "20.0000000") + + otherRecipientKp, otherRecipient := itest.CreateAccount("100") + itest.MustEstablishTrustline(otherRecipientKp, otherRecipient, txnbuild.MustAssetFromXDR(asset)) + + // calling transfer from the issuer account will also mint the asset + _, transferTx, _ := assertInvokeHostFnSucceeds( + itest, + itest.Master(), + transfer(itest, issuer, asset, "30", accountAddressParam(otherRecipient.GetAccountID())), + ) + assertContainsBalance(itest, recipientKp, issuer, code, amount.MustParse("20")) + assertContainsBalance(itest, otherRecipientKp, issuer, code, amount.MustParse("30")) + + fx = getTxEffects(itest, transferTx, asset) + assert.Len(t, fx, 2) + assertContainsEffect(t, fx, + effects.EffectAccountCredited, + effects.EffectAccountDebited) + assertAssetStats(itest, assetStats{ + code: code, + issuer: issuer, + numAccounts: 2, + balanceArchivedContracts: big.NewInt(0), + numArchivedContracts: 0, + balanceAccounts: amount.MustParse("50"), + numContracts: 0, + balanceContracts: big.NewInt(0), + contractID: stellarAssetContractID(itest, asset), + }) +} + +func createSAC(itest *integration.Test, asset xdr.Asset) { + invokeHostFunction := &txnbuild.InvokeHostFunction{ + HostFunction: xdr.HostFunction{ + Type: xdr.HostFunctionTypeHostFunctionTypeCreateContract, + CreateContract: &xdr.CreateContractArgs{ + ContractIdPreimage: xdr.ContractIdPreimage{ + Type: xdr.ContractIdPreimageTypeContractIdPreimageFromAsset, + FromAsset: &asset, + }, + Executable: xdr.ContractExecutable{ + Type: xdr.ContractExecutableTypeContractExecutableStellarAsset, + WasmHash: nil, + }, + }, + }, + SourceAccount: itest.Master().Address(), + } + _, _, preFlightOp := assertInvokeHostFnSucceeds(itest, itest.Master(), invokeHostFunction) + sourceAccount, extendTTLOp, minFee := itest.PreflightExtendExpiration( + itest.Master().Address(), + preFlightOp.Ext.SorobanData.Resources.Footprint.ReadWrite, + LongTermTTL, + ) + itest.MustSubmitOperationsWithFee(&sourceAccount, itest.Master(), minFee+txnbuild.MinBaseFee, &extendTTLOp) +} + +func TestContractMintToContract(t *testing.T) { + if integration.GetCoreMaxSupportedProtocol() < 20 { + t.Skip("This test run does not support less than Protocol 20") + } + + itest := integration.NewTest(t, integration.Config{ + ProtocolVersion: 20, + EnableSorobanRPC: true, + }) + + issuer := itest.Master().Address() + code := "USD" + asset := xdr.MustNewCreditAsset(code, issuer) + + createSAC(itest, asset) + + // Create recipient contract + recipientContractID, _ := mustCreateAndInstallContract(itest, itest.Master(), "a1", add_u64_contract) + strkeyRecipientContractID, err := strkey.Encode(strkey.VersionByteContract, recipientContractID[:]) + assert.NoError(t, err) + + mintAmount := xdr.Int128Parts{Lo: math.MaxUint64 - 3, Hi: math.MaxInt64} + _, mintTx, _ := assertInvokeHostFnSucceeds( + itest, + itest.Master(), + mintWithAmt( + itest, + issuer, asset, + i128Param(int64(mintAmount.Hi), uint64(mintAmount.Lo)), + contractAddressParam(recipientContractID)), + ) + assertContainsEffect(t, getTxEffects(itest, mintTx, asset), + effects.EffectContractCredited) + + balanceAmount, _, _ := assertInvokeHostFnSucceeds( + itest, + itest.Master(), + contractBalance(itest, issuer, asset, recipientContractID), + ) + assert.Equal(itest.CurrentTest(), xdr.ScValTypeScvI128, balanceAmount.Type) + assert.Equal(itest.CurrentTest(), xdr.Uint64(math.MaxUint64-3), (*balanceAmount.I128).Lo) + assert.Equal(itest.CurrentTest(), xdr.Int64(math.MaxInt64), (*balanceAmount.I128).Hi) + assertEventPayments(itest, mintTx, asset, "", strkeyRecipientContractID, "mint", amount.String128(mintAmount)) + + // calling transfer from the issuer account will also mint the asset + _, transferTx, _ := assertInvokeHostFnSucceeds( + itest, + itest.Master(), + transferWithAmount(itest, issuer, asset, i128Param(0, 3), contractAddressParam(recipientContractID)), + ) + + assertContainsEffect(t, getTxEffects(itest, transferTx, asset), + effects.EffectAccountDebited, + effects.EffectContractCredited) + + balanceAmount, _, _ = assertInvokeHostFnSucceeds( + itest, + itest.Master(), + contractBalance(itest, issuer, asset, recipientContractID), + ) + assert.Equal(itest.CurrentTest(), xdr.ScValTypeScvI128, balanceAmount.Type) + assert.Equal(itest.CurrentTest(), xdr.Uint64(math.MaxUint64), (*balanceAmount.I128).Lo) + assert.Equal(itest.CurrentTest(), xdr.Int64(math.MaxInt64), (*balanceAmount.I128).Hi) + + // 2^127 - 1 + balanceContracts := new(big.Int).Lsh(big.NewInt(1), 127) + balanceContracts.Sub(balanceContracts, big.NewInt(1)) + assertAssetStats(itest, assetStats{ + code: code, + issuer: issuer, + numAccounts: 0, + balanceAccounts: 0, + balanceArchivedContracts: big.NewInt(0), + numArchivedContracts: 0, + numContracts: 1, + balanceContracts: balanceContracts, + contractID: stellarAssetContractID(itest, asset), + }) +} + +func TestExpirationAndRestoration(t *testing.T) { + if integration.GetCoreMaxSupportedProtocol() < 20 { + t.Skip("This test run does not support less than Protocol 20") + } + + itest := integration.NewTest(t, integration.Config{ + ProtocolVersion: 20, + EnableSorobanRPC: true, + HorizonIngestParameters: map[string]string{ + // disable state verification because we will insert + // a fake asset contract in the horizon db and we don't + // want state verification to detect this + "ingest-disable-state-verification": "true", + }, + }) + + issuer := itest.Master().Address() + code := "USD" + + // Create contract to store synthetic asset balances + storeContractID, _ := mustCreateAndInstallContract( + itest, + itest.Master(), + "a1", + "soroban_store.wasm", + ) + syntheticAssetStat := history.ExpAssetStat{ + AssetType: xdr.AssetTypeAssetTypeCreditAlphanum4, + AssetCode: code, + AssetIssuer: issuer, + Accounts: history.ExpAssetStatAccounts{ + Authorized: 0, + AuthorizedToMaintainLiabilities: 0, + ClaimableBalances: 0, + LiquidityPools: 0, + Unauthorized: 0, + }, + Balances: history.ExpAssetStatBalances{ + Authorized: "0", + AuthorizedToMaintainLiabilities: "0", + ClaimableBalances: "0", + LiquidityPools: "0", + Unauthorized: "0", + }, + Amount: "0", + NumAccounts: 0, + ContractID: nil, + } + syntheticAssetStat.SetContractID(storeContractID) + _, err := itest.HorizonIngest().HistoryQ().InsertAssetStat( + context.Background(), + syntheticAssetStat, + ) + assert.NoError(t, err) + + // create active balance + _, _, setOp := assertInvokeHostFnSucceeds( + itest, + itest.Master(), + invokeStoreSet( + itest, + storeContractID, + processors.BalanceToContractData( + storeContractID, + [32]byte{1}, + 23, + ), + ), + ) + sourceAccount, extendTTLOp, minFee := itest.PreflightExtendExpiration( + itest.Master().Address(), + setOp.Ext.SorobanData.Resources.Footprint.ReadWrite, + LongTermTTL, + ) + itest.MustSubmitOperationsWithFee(&sourceAccount, itest.Master(), minFee+txnbuild.MinBaseFee, &extendTTLOp) + assertAssetStats(itest, assetStats{ + code: code, + issuer: issuer, + numAccounts: 0, + balanceAccounts: 0, + balanceArchivedContracts: big.NewInt(0), + numArchivedContracts: 0, + numContracts: 1, + balanceContracts: big.NewInt(23), + contractID: storeContractID, + }) + + // create balance which we will expire + balanceToExpire := processors.BalanceToContractData( + storeContractID, + [32]byte{2}, + 37, + ) + assertInvokeHostFnSucceeds( + itest, + itest.Master(), + invokeStoreSet( + itest, + storeContractID, + balanceToExpire, + ), + ) + assertAssetStats(itest, assetStats{ + code: code, + issuer: issuer, + numAccounts: 0, + balanceAccounts: 0, + balanceArchivedContracts: big.NewInt(0), + numArchivedContracts: 0, + numContracts: 2, + balanceContracts: big.NewInt(60), + contractID: storeContractID, + }) + + balanceToExpireLedgerKey := xdr.LedgerKey{ + Type: xdr.LedgerEntryTypeContractData, + ContractData: &xdr.LedgerKeyContractData{ + Contract: balanceToExpire.ContractData.Contract, + Key: balanceToExpire.ContractData.Key, + Durability: balanceToExpire.ContractData.Durability, + }, + } + // The TESTING_MINIMUM_PERSISTENT_ENTRY_LIFETIME=10 configuration in stellar-core + // will ensure that the ledger entry expires after 10 ledgers. + // Because ARTIFICIALLY_ACCELERATE_TIME_FOR_TESTING is set to true, 10 ledgers + // should elapse in 10 seconds + itest.WaitUntilLedgerEntryTTL(balanceToExpireLedgerKey) + assertAssetStats(itest, assetStats{ + code: code, + issuer: issuer, + numAccounts: 0, + balanceAccounts: 0, + balanceArchivedContracts: big.NewInt(37), + numArchivedContracts: 1, + numContracts: 1, + balanceContracts: big.NewInt(23), + contractID: storeContractID, + }) + + // increase active balance from 23 to 50 + assertInvokeHostFnSucceeds( + itest, + itest.Master(), + invokeStoreSet( + itest, + storeContractID, + processors.BalanceToContractData( + storeContractID, + [32]byte{1}, + 50, + ), + ), + ) + assertAssetStats(itest, assetStats{ + code: code, + issuer: issuer, + numAccounts: 0, + balanceAccounts: 0, + balanceArchivedContracts: big.NewInt(37), + numArchivedContracts: 1, + numContracts: 1, + balanceContracts: big.NewInt(50), + contractID: storeContractID, + }) + + // restore expired balance + sourceAccount, restoreFootprint, minFee := itest.RestoreFootprint( + itest.Master().Address(), + balanceToExpireLedgerKey, + ) + itest.MustSubmitOperationsWithFee(&sourceAccount, itest.Master(), minFee+txnbuild.MinBaseFee, &restoreFootprint) + assertAssetStats(itest, assetStats{ + code: code, + issuer: issuer, + numAccounts: 0, + balanceAccounts: 0, + balanceArchivedContracts: big.NewInt(0), + numArchivedContracts: 0, + numContracts: 2, + balanceContracts: big.NewInt(87), + contractID: storeContractID, + }) + + // expire the balance again + itest.WaitUntilLedgerEntryTTL(balanceToExpireLedgerKey) + + // decrease active balance from 50 to 3 + assertInvokeHostFnSucceeds( + itest, + itest.Master(), + invokeStoreSet( + itest, + storeContractID, + processors.BalanceToContractData( + storeContractID, + [32]byte{1}, + 3, + ), + ), + ) + assertAssetStats(itest, assetStats{ + code: code, + issuer: issuer, + numAccounts: 0, + balanceAccounts: 0, + balanceArchivedContracts: big.NewInt(37), + numArchivedContracts: 1, + numContracts: 1, + balanceContracts: big.NewInt(3), + contractID: storeContractID, + }) + + // remove active balance + assertInvokeHostFnSucceeds( + itest, + itest.Master(), + invokeStoreRemove( + itest, + storeContractID, + processors.ContractBalanceLedgerKey( + storeContractID, + [32]byte{1}, + ), + ), + ) + assertAssetStats(itest, assetStats{ + code: code, + issuer: issuer, + numAccounts: 0, + balanceAccounts: 0, + balanceArchivedContracts: big.NewInt(37), + numArchivedContracts: 1, + numContracts: 0, + balanceContracts: big.NewInt(0), + contractID: storeContractID, + }) +} + +func invokeStoreSet( + itest *integration.Test, + storeContractID xdr.Hash, + ledgerEntryData xdr.LedgerEntryData, +) *txnbuild.InvokeHostFunction { + key := ledgerEntryData.MustContractData().Key + val := ledgerEntryData.MustContractData().Val + return &txnbuild.InvokeHostFunction{ + HostFunction: xdr.HostFunction{ + Type: xdr.HostFunctionTypeHostFunctionTypeInvokeContract, + InvokeContract: &xdr.InvokeContractArgs{ + ContractAddress: contractIDParam(storeContractID), + FunctionName: "set", + Args: xdr.ScVec{ + key, + val, + }, + }, + }, + SourceAccount: itest.Master().Address(), + } +} + +func invokeStoreRemove( + itest *integration.Test, + storeContractID xdr.Hash, + ledgerKey xdr.LedgerKey, +) *txnbuild.InvokeHostFunction { + return &txnbuild.InvokeHostFunction{ + HostFunction: xdr.HostFunction{ + Type: xdr.HostFunctionTypeHostFunctionTypeInvokeContract, + InvokeContract: &xdr.InvokeContractArgs{ + ContractAddress: contractIDParam(storeContractID), + FunctionName: "remove", + Args: xdr.ScVec{ + ledgerKey.MustContractData().Key, + }, + }, + }, + SourceAccount: itest.Master().Address(), + } +} + +func TestContractTransferBetweenAccounts(t *testing.T) { + if integration.GetCoreMaxSupportedProtocol() < 20 { + t.Skip("This test run does not support less than Protocol 20") + } + + itest := integration.NewTest(t, integration.Config{ + ProtocolVersion: 20, + EnableSorobanRPC: true, + }) + + issuer := itest.Master().Address() + code := "USD" + asset := xdr.MustNewCreditAsset(code, issuer) + + createSAC(itest, asset) + + recipientKp, recipient := itest.CreateAccount("100") + itest.MustEstablishTrustline(recipientKp, recipient, txnbuild.MustAssetFromXDR(asset)) + + itest.MustSubmitOperations( + itest.MasterAccount(), + itest.Master(), + &txnbuild.Payment{ + SourceAccount: issuer, + Destination: recipient.GetAccountID(), + Asset: txnbuild.CreditAsset{ + Code: code, + Issuer: issuer, + }, + Amount: "1000", + }, + ) + + assertContainsBalance(itest, recipientKp, issuer, code, amount.MustParse("1000")) + assertAssetStats(itest, assetStats{ + code: code, + issuer: issuer, + numAccounts: 1, + balanceAccounts: amount.MustParse("1000"), + balanceArchivedContracts: big.NewInt(0), + numArchivedContracts: 0, + numContracts: 0, + balanceContracts: big.NewInt(0), + contractID: stellarAssetContractID(itest, asset), + }) + + otherRecipientKp, otherRecipient := itest.CreateAccount("100") + itest.MustEstablishTrustline(otherRecipientKp, otherRecipient, txnbuild.MustAssetFromXDR(asset)) + + _, transferTx, _ := assertInvokeHostFnSucceeds( + itest, + recipientKp, + transfer(itest, recipientKp.Address(), asset, "30", accountAddressParam(otherRecipient.GetAccountID())), + ) + + assertContainsBalance(itest, recipientKp, issuer, code, amount.MustParse("970")) + assertContainsBalance(itest, otherRecipientKp, issuer, code, amount.MustParse("30")) + + fx := getTxEffects(itest, transferTx, asset) + assert.NotEmpty(t, fx) + assertContainsEffect(t, fx, effects.EffectAccountCredited, effects.EffectAccountDebited) + assertAssetStats(itest, assetStats{ + code: code, + issuer: issuer, + numAccounts: 2, + balanceAccounts: amount.MustParse("1000"), + balanceArchivedContracts: big.NewInt(0), + numArchivedContracts: 0, + numContracts: 0, + balanceContracts: big.NewInt(0), + contractID: stellarAssetContractID(itest, asset), + }) + assertEventPayments(itest, transferTx, asset, recipientKp.Address(), otherRecipient.GetAccountID(), "transfer", "30.0000000") +} + +func TestContractTransferBetweenAccountAndContract(t *testing.T) { + if integration.GetCoreMaxSupportedProtocol() < 20 { + t.Skip("This test run does not support less than Protocol 20") + } + + itest := integration.NewTest(t, integration.Config{ + ProtocolVersion: 20, + EnableSorobanRPC: true, + }) + + issuer := itest.Master().Address() + code := "USDLONG" + asset := xdr.MustNewCreditAsset(code, issuer) + + createSAC(itest, asset) + + recipientKp, recipient := itest.CreateAccount("100") + itest.MustEstablishTrustline(recipientKp, recipient, txnbuild.MustAssetFromXDR(asset)) + + itest.MustSubmitOperations( + itest.MasterAccount(), + itest.Master(), + &txnbuild.Payment{ + SourceAccount: issuer, + Destination: recipient.GetAccountID(), + Asset: txnbuild.CreditAsset{ + Code: code, + Issuer: issuer, + }, + Amount: "1000", + }, + ) + + // Create recipient contract + recipientContractID, recipientContractHash := mustCreateAndInstallContract(itest, itest.Master(), "a1", sac_contract) + strkeyRecipientContractID, err := strkey.Encode(strkey.VersionByteContract, recipientContractID[:]) + assert.NoError(t, err) + + // init recipient contract with the asset contract id + assertInvokeHostFnSucceeds( + itest, + itest.Master(), + initAssetContract(itest, issuer, asset, recipientContractID, recipientContractHash), + ) + + // Add funds to recipient contract + _, mintTx, _ := assertInvokeHostFnSucceeds( + itest, + itest.Master(), + mint(itest, issuer, asset, "1000", contractAddressParam(recipientContractID)), + ) + assertContainsBalance(itest, recipientKp, issuer, code, amount.MustParse("1000")) + assertContainsEffect(t, getTxEffects(itest, mintTx, asset), + effects.EffectContractCredited) + + assertAssetStats(itest, assetStats{ + code: code, + issuer: issuer, + numAccounts: 1, + balanceAccounts: amount.MustParse("1000"), + balanceArchivedContracts: big.NewInt(0), + numArchivedContracts: 0, + numContracts: 1, + balanceContracts: big.NewInt(int64(amount.MustParse("1000"))), + contractID: stellarAssetContractID(itest, asset), + }) + + // transfer from account to contract + _, transferTx, _ := assertInvokeHostFnSucceeds( + itest, + recipientKp, + transfer(itest, recipientKp.Address(), asset, "30", contractAddressParam(recipientContractID)), + ) + assertContainsBalance(itest, recipientKp, issuer, code, amount.MustParse("970")) + assertContainsEffect(t, getTxEffects(itest, transferTx, asset), + effects.EffectAccountDebited, effects.EffectContractCredited) + assertAssetStats(itest, assetStats{ + code: code, + issuer: issuer, + numAccounts: 1, + balanceAccounts: amount.MustParse("970"), + balanceArchivedContracts: big.NewInt(0), + numArchivedContracts: 0, + numContracts: 1, + balanceContracts: big.NewInt(int64(amount.MustParse("1030"))), + contractID: stellarAssetContractID(itest, asset), + }) + assertEventPayments(itest, transferTx, asset, recipientKp.Address(), strkeyRecipientContractID, "transfer", "30.0000000") + + // transfer from contract to account + _, transferTx, _ = assertInvokeHostFnSucceeds( + itest, + recipientKp, + transferFromContract(itest, recipientKp.Address(), asset, recipientContractID, recipientContractHash, "500", accountAddressParam(recipient.GetAccountID())), + ) + assertContainsEffect(t, getTxEffects(itest, transferTx, asset), + effects.EffectContractDebited, effects.EffectAccountCredited) + assertContainsBalance(itest, recipientKp, issuer, code, amount.MustParse("1470")) + assertAssetStats(itest, assetStats{ + code: code, + issuer: issuer, + numAccounts: 1, + balanceAccounts: amount.MustParse("1470"), + balanceArchivedContracts: big.NewInt(0), + numArchivedContracts: 0, + numContracts: 1, + balanceContracts: big.NewInt(int64(amount.MustParse("530"))), + contractID: stellarAssetContractID(itest, asset), + }) + assertEventPayments(itest, transferTx, asset, strkeyRecipientContractID, recipientKp.Address(), "transfer", "500.0000000") + + balanceAmount, _, _ := assertInvokeHostFnSucceeds( + itest, + itest.Master(), + contractBalance(itest, issuer, asset, recipientContractID), + ) + assert.Equal(itest.CurrentTest(), xdr.ScValTypeScvI128, balanceAmount.Type) + assert.Equal(itest.CurrentTest(), xdr.Uint64(5300000000), (*balanceAmount.I128).Lo) + assert.Equal(itest.CurrentTest(), xdr.Int64(0), (*balanceAmount.I128).Hi) +} + +func TestContractTransferBetweenContracts(t *testing.T) { + if integration.GetCoreMaxSupportedProtocol() < 20 { + t.Skip("This test run does not support less than Protocol 20") + } + + itest := integration.NewTest(t, integration.Config{ + ProtocolVersion: 20, + EnableSorobanRPC: true, + }) + + issuer := itest.Master().Address() + code := "USD" + asset := xdr.MustNewCreditAsset(code, issuer) + + createSAC(itest, asset) + + // Create recipient contract + recipientContractID, _ := mustCreateAndInstallContract(itest, itest.Master(), "a1", sac_contract) + strkeyRecipientContractID, err := strkey.Encode(strkey.VersionByteContract, recipientContractID[:]) + assert.NoError(t, err) + + // Create emitter contract + emitterContractID, emitterContractHash := mustCreateAndInstallContract(itest, itest.Master(), "a2", sac_contract) + strkeyEmitterContractID, err := strkey.Encode(strkey.VersionByteContract, emitterContractID[:]) + assert.NoError(t, err) + + // init emitter contract with the asset contract id + assertInvokeHostFnSucceeds( + itest, + itest.Master(), + initAssetContract(itest, issuer, asset, emitterContractID, emitterContractHash), + ) + + // Add funds to emitter contract + assertInvokeHostFnSucceeds( + itest, + itest.Master(), + mint(itest, issuer, asset, "1000", contractAddressParam(emitterContractID)), + ) + + // Transfer funds from emitter to recipient + _, transferTx, _ := assertInvokeHostFnSucceeds( + itest, + itest.Master(), + transferFromContract(itest, issuer, asset, emitterContractID, emitterContractHash, "10", contractAddressParam(recipientContractID)), + ) + assertContainsEffect(t, getTxEffects(itest, transferTx, asset), + effects.EffectContractCredited, effects.EffectContractDebited) + + // Check balances of emitter and recipient + emitterBalanceAmount, _, _ := assertInvokeHostFnSucceeds( + itest, + itest.Master(), + contractBalance(itest, issuer, asset, emitterContractID), + ) + assert.Equal(itest.CurrentTest(), xdr.ScValTypeScvI128, emitterBalanceAmount.Type) + assert.Equal(itest.CurrentTest(), xdr.Uint64(9900000000), (*emitterBalanceAmount.I128).Lo) + assert.Equal(itest.CurrentTest(), xdr.Int64(0), (*emitterBalanceAmount.I128).Hi) + + recipientBalanceAmount, _, _ := assertInvokeHostFnSucceeds( + itest, + itest.Master(), + contractBalance(itest, issuer, asset, recipientContractID), + ) + assert.Equal(itest.CurrentTest(), xdr.ScValTypeScvI128, recipientBalanceAmount.Type) + assert.Equal(itest.CurrentTest(), xdr.Uint64(100000000), (*recipientBalanceAmount.I128).Lo) + assert.Equal(itest.CurrentTest(), xdr.Int64(0), (*recipientBalanceAmount.I128).Hi) + + assertAssetStats(itest, assetStats{ + code: code, + issuer: issuer, + numAccounts: 0, + balanceAccounts: 0, + balanceArchivedContracts: big.NewInt(0), + numArchivedContracts: 0, + numContracts: 2, + balanceContracts: big.NewInt(int64(amount.MustParse("1000"))), + contractID: stellarAssetContractID(itest, asset), + }) + assertEventPayments(itest, transferTx, asset, strkeyEmitterContractID, strkeyRecipientContractID, "transfer", "10.0000000") +} + +func TestContractBurnFromAccount(t *testing.T) { + if integration.GetCoreMaxSupportedProtocol() < 20 { + t.Skip("This test run does not support less than Protocol 20") + } + + itest := integration.NewTest(t, integration.Config{ + ProtocolVersion: 20, + EnableSorobanRPC: true, + }) + + issuer := itest.Master().Address() + code := "USD" + asset := xdr.MustNewCreditAsset(code, issuer) + + createSAC(itest, asset) + + recipientKp, recipient := itest.CreateAccount("100") + itest.MustEstablishTrustline(recipientKp, recipient, txnbuild.MustAssetFromXDR(asset)) + + itest.MustSubmitOperations( + itest.MasterAccount(), + itest.Master(), + &txnbuild.Payment{ + SourceAccount: issuer, + Destination: recipient.GetAccountID(), + Asset: txnbuild.CreditAsset{ + Code: code, + Issuer: issuer, + }, + Amount: "1000", + }, + ) + + assertContainsBalance(itest, recipientKp, issuer, code, amount.MustParse("1000")) + assertAssetStats(itest, assetStats{ + code: code, + issuer: issuer, + numAccounts: 1, + balanceAccounts: amount.MustParse("1000"), + numContracts: 0, + balanceArchivedContracts: big.NewInt(0), + numArchivedContracts: 0, + balanceContracts: big.NewInt(0), + contractID: stellarAssetContractID(itest, asset), + }) + + _, burnTx, _ := assertInvokeHostFnSucceeds( + itest, + recipientKp, + burn(itest, recipientKp.Address(), asset, "500"), + ) + + fx := getTxEffects(itest, burnTx, asset) + require.Len(t, fx, 1) + assetEffects := assertContainsEffect(t, fx, effects.EffectAccountDebited) + require.GreaterOrEqual(t, len(assetEffects), 1) + burnEffect := assetEffects[0].(effects.AccountDebited) + + assert.Equal(t, issuer, burnEffect.Asset.Issuer) + assert.Equal(t, code, burnEffect.Asset.Code) + assert.Equal(t, "500.0000000", burnEffect.Amount) + assert.Equal(t, recipientKp.Address(), burnEffect.Account) + assertAssetStats(itest, assetStats{ + code: code, + issuer: issuer, + numAccounts: 1, + balanceAccounts: amount.MustParse("500"), + numContracts: 0, + balanceArchivedContracts: big.NewInt(0), + numArchivedContracts: 0, + balanceContracts: big.NewInt(0), + contractID: stellarAssetContractID(itest, asset), + }) + assertEventPayments(itest, burnTx, asset, recipientKp.Address(), "", "burn", "500.0000000") +} + +func TestContractBurnFromContract(t *testing.T) { + if integration.GetCoreMaxSupportedProtocol() < 20 { + t.Skip("This test run does not support less than Protocol 20") + } + + itest := integration.NewTest(t, integration.Config{ + ProtocolVersion: 20, + EnableSorobanRPC: true, + }) + + issuer := itest.Master().Address() + code := "USD" + asset := xdr.MustNewCreditAsset(code, issuer) + + createSAC(itest, asset) + + // Create recipient contract + recipientContractID, recipientContractHash := mustCreateAndInstallContract(itest, itest.Master(), "a1", sac_contract) + strkeyRecipientContractID, err := strkey.Encode(strkey.VersionByteContract, recipientContractID[:]) + assert.NoError(t, err) + // init contract with asset contract id + assertInvokeHostFnSucceeds( + itest, + itest.Master(), + initAssetContract(itest, issuer, asset, recipientContractID, recipientContractHash), + ) + + // Add funds to recipient contract + assertInvokeHostFnSucceeds( + itest, + itest.Master(), + mint(itest, issuer, asset, "1000", contractAddressParam(recipientContractID)), + ) + + // Burn funds + _, burnTx, _ := assertInvokeHostFnSucceeds( + itest, + itest.Master(), + burnSelf(itest, issuer, asset, recipientContractID, recipientContractHash, "10"), + ) + + balanceAmount, _, _ := assertInvokeHostFnSucceeds( + itest, + itest.Master(), + contractBalance(itest, issuer, asset, recipientContractID), + ) + + assert.Equal(itest.CurrentTest(), xdr.ScValTypeScvI128, balanceAmount.Type) + assert.Equal(itest.CurrentTest(), xdr.Uint64(9900000000), (*balanceAmount.I128).Lo) + assert.Equal(itest.CurrentTest(), xdr.Int64(0), (*balanceAmount.I128).Hi) + + assertContainsEffect(t, getTxEffects(itest, burnTx, asset), + effects.EffectContractDebited) + + assertAssetStats(itest, assetStats{ + code: code, + issuer: issuer, + numAccounts: 0, + balanceAccounts: 0, + balanceArchivedContracts: big.NewInt(0), + numArchivedContracts: 0, + numContracts: 1, + balanceContracts: big.NewInt(int64(amount.MustParse("990"))), + contractID: stellarAssetContractID(itest, asset), + }) + assertEventPayments(itest, burnTx, asset, strkeyRecipientContractID, "", "burn", "10.0000000") +} + +func TestContractClawbackFromAccount(t *testing.T) { + if integration.GetCoreMaxSupportedProtocol() < 20 { + t.Skip("This test run does not support less than Protocol 20") + } + + itest := integration.NewTest(t, integration.Config{ + ProtocolVersion: 20, + EnableSorobanRPC: true, + }) + + // Give the master account the revocable flag (needed to set the clawback flag) + // and the clawback flag + setRevocableFlag := txnbuild.SetOptions{ + SetFlags: []txnbuild.AccountFlag{ + txnbuild.AuthRevocable, + txnbuild.AuthClawbackEnabled, + }, + } + itest.MustSubmitOperations(itest.MasterAccount(), itest.Master(), &setRevocableFlag) + + issuer := itest.Master().Address() + code := "USD" + asset := xdr.MustNewCreditAsset(code, issuer) + + createSAC(itest, asset) + + recipientKp, recipient := itest.CreateAccount("100") + itest.MustEstablishTrustline(recipientKp, recipient, txnbuild.MustAssetFromXDR(asset)) + + itest.MustSubmitOperations( + itest.MasterAccount(), + itest.Master(), + &txnbuild.Payment{ + SourceAccount: issuer, + Destination: recipient.GetAccountID(), + Asset: txnbuild.CreditAsset{ + Code: code, + Issuer: issuer, + }, + Amount: "1000", + }, + ) + + assertContainsBalance(itest, recipientKp, issuer, code, amount.MustParse("1000")) + assertAssetStats(itest, assetStats{ + code: code, + issuer: issuer, + numAccounts: 1, + balanceAccounts: amount.MustParse("1000"), + numContracts: 0, + balanceArchivedContracts: big.NewInt(0), + numArchivedContracts: 0, + balanceContracts: big.NewInt(0), + contractID: stellarAssetContractID(itest, asset), + }) + + _, clawTx, _ := assertInvokeHostFnSucceeds( + itest, + itest.Master(), + clawback(itest, issuer, asset, "1000", accountAddressParam(recipientKp.Address())), + ) + + assertContainsEffect(t, getTxEffects(itest, clawTx, asset), effects.EffectAccountDebited) + assertContainsBalance(itest, recipientKp, issuer, code, 0) + assertAssetStats(itest, assetStats{ + code: code, + issuer: issuer, + numAccounts: 1, + balanceAccounts: 0, + balanceArchivedContracts: big.NewInt(0), + numArchivedContracts: 0, + numContracts: 0, + balanceContracts: big.NewInt(0), + contractID: stellarAssetContractID(itest, asset), + }) + assertEventPayments(itest, clawTx, asset, recipientKp.Address(), "", "clawback", "1000.0000000") +} + +func TestContractClawbackFromContract(t *testing.T) { + if integration.GetCoreMaxSupportedProtocol() < 20 { + t.Skip("This test run does not support less than Protocol 20") + } + + itest := integration.NewTest(t, integration.Config{ + ProtocolVersion: 20, + EnableSorobanRPC: true, + }) + + // Give the master account the revocable flag (needed to set the clawback flag) + // and the clawback flag + setRevocableFlag := txnbuild.SetOptions{ + SetFlags: []txnbuild.AccountFlag{ + txnbuild.AuthRevocable, + txnbuild.AuthClawbackEnabled, + }, + } + itest.MustSubmitOperations(itest.MasterAccount(), itest.Master(), &setRevocableFlag) + + issuer := itest.Master().Address() + code := "USD" + asset := xdr.MustNewCreditAsset(code, issuer) + + createSAC(itest, asset) + + // Create recipient contract + recipientContractID, _ := mustCreateAndInstallContract(itest, itest.Master(), "a2", sac_contract) + strkeyRecipientContractID, err := strkey.Encode(strkey.VersionByteContract, recipientContractID[:]) + assert.NoError(itest.CurrentTest(), err) + + // Add funds to recipient contract + assertInvokeHostFnSucceeds( + itest, + itest.Master(), + mint(itest, issuer, asset, "1000", contractAddressParam(recipientContractID)), + ) + + // Clawback funds + _, clawTx, _ := assertInvokeHostFnSucceeds( + itest, + itest.Master(), + clawback(itest, issuer, asset, "10", contractAddressParam(recipientContractID)), + ) + + balanceAmount, _, _ := assertInvokeHostFnSucceeds( + itest, + itest.Master(), + contractBalance(itest, issuer, asset, recipientContractID), + ) + assert.Equal(itest.CurrentTest(), xdr.ScValTypeScvI128, balanceAmount.Type) + assert.Equal(itest.CurrentTest(), xdr.Uint64(9900000000), (*balanceAmount.I128).Lo) + assert.Equal(itest.CurrentTest(), xdr.Int64(0), (*balanceAmount.I128).Hi) + + assertContainsEffect(t, getTxEffects(itest, clawTx, asset), + effects.EffectContractDebited) + + assertAssetStats(itest, assetStats{ + code: code, + issuer: issuer, + numAccounts: 0, + balanceAccounts: 0, + balanceArchivedContracts: big.NewInt(0), + numArchivedContracts: 0, + numContracts: 1, + balanceContracts: big.NewInt(int64(amount.MustParse("990"))), + contractID: stellarAssetContractID(itest, asset), + }) + assertEventPayments(itest, clawTx, asset, strkeyRecipientContractID, "", "clawback", "10.0000000") +} + +func assertContainsBalance(itest *integration.Test, acct *keypair.Full, issuer, code string, amt xdr.Int64) { + accountResponse := itest.MustGetAccount(acct) + if issuer == "" && code == "" { + xlmBalance, err := accountResponse.GetNativeBalance() + assert.NoError(itest.CurrentTest(), err) + assert.Equal(itest.CurrentTest(), amt, amount.MustParse(xlmBalance)) + } else { + assetBalance := accountResponse.GetCreditBalance(code, issuer) + assert.Equal(itest.CurrentTest(), amt, amount.MustParse(assetBalance)) + } +} + +type assetStats struct { + code string + issuer string + numAccounts int32 + balanceAccounts xdr.Int64 + numContracts int32 + numArchivedContracts int32 + balanceContracts *big.Int + balanceArchivedContracts *big.Int + contractID [32]byte +} + +func assertAssetStats(itest *integration.Test, expected assetStats) { + assets, err := itest.Client().Assets(horizonclient.AssetRequest{ + ForAssetCode: expected.code, + ForAssetIssuer: expected.issuer, + Limit: 1, + }) + assert.NoError(itest.CurrentTest(), err) + + if expected.numContracts == 0 && expected.numAccounts == 0 && expected.numArchivedContracts == 0 && + expected.balanceArchivedContracts.Cmp(big.NewInt(0)) == 0 && + expected.balanceContracts.Cmp(big.NewInt(0)) == 0 && expected.balanceAccounts == 0 { + assert.Empty(itest.CurrentTest(), assets) + return + } + + assert.Len(itest.CurrentTest(), assets.Embedded.Records, 1) + asset := assets.Embedded.Records[0] + assert.Equal(itest.CurrentTest(), expected.code, asset.Code) + assert.Equal(itest.CurrentTest(), expected.issuer, asset.Issuer) + assert.Equal(itest.CurrentTest(), expected.numAccounts, asset.NumAccounts) + assert.Equal(itest.CurrentTest(), expected.numAccounts, asset.Accounts.Authorized) + assert.Equal(itest.CurrentTest(), expected.balanceAccounts, amount.MustParse(asset.Amount)) + assert.Equal(itest.CurrentTest(), expected.numContracts, asset.NumContracts) + assert.Equal(itest.CurrentTest(), expected.numArchivedContracts, asset.NumArchivedContracts) + assert.Equal(itest.CurrentTest(), expected.balanceContracts.String(), parseBalance(itest, asset.ContractsAmount).String()) + assert.Equal(itest.CurrentTest(), expected.balanceArchivedContracts.String(), parseBalance(itest, asset.ArchivedContractsAmount).String()) + assert.Equal(itest.CurrentTest(), strkey.MustEncode(strkey.VersionByteContract, expected.contractID[:]), asset.ContractID) +} + +func parseBalance(itest *integration.Test, balance string) *big.Int { + parts := strings.Split(balance, ".") + assert.Len(itest.CurrentTest(), parts, 2) + contractsAmount, ok := new(big.Int).SetString(parts[0]+parts[1], 10) + assert.True(itest.CurrentTest(), ok) + return contractsAmount +} + +// assertContainsEffect checks that the list of json effects contains the given +// effect type(s) by name (no other details are checked). It returns the last +// effect matching each given type. +func assertContainsEffect(t *testing.T, fx []effects.Effect, effectTypes ...effects.EffectType) []effects.Effect { + found := map[string]int{} + for idx, effect := range fx { + found[effect.GetType()] = idx + } + + for _, type_ := range effectTypes { + assert.Containsf(t, found, effects.EffectTypeNames[type_], "effects: %v", fx) + } + + var rv []effects.Effect + for _, i := range found { + rv = append(rv, fx[i]) + } + + return rv +} + +// getTxEffects returns a transaction's effects, limited to 2 because it's to be +// used for checking SAC effects. +func getTxEffects(itest *integration.Test, txHash string, asset xdr.Asset) []effects.Effect { + t := itest.CurrentTest() + effects, err := itest.Client().Effects(horizonclient.EffectRequest{ + ForTransaction: txHash, + Order: horizonclient.OrderDesc, + }) + assert.NoError(t, err) + result := effects.Embedded.Records + + assert.LessOrEqualf(t, len(result), 2, "txhash: %s", txHash) + return result +} + +func assertEventPayments(itest *integration.Test, txHash string, asset xdr.Asset, from string, to string, evtType string, amount string) { + ops, err := itest.Client().Operations(horizonclient.OperationRequest{ + ForTransaction: txHash, + Limit: 1, + }) + assert.NoError(itest.CurrentTest(), err) + assert.Equal(itest.CurrentTest(), 1, len(ops.Embedded.Records)) + assert.Equal(itest.CurrentTest(), ops.Embedded.Records[0].GetType(), operations.TypeNames[xdr.OperationTypeInvokeHostFunction]) + + invokeHostFn := ops.Embedded.Records[0].(operations.InvokeHostFunction) + assert.Equal(itest.CurrentTest(), invokeHostFn.Function, "HostFunctionTypeHostFunctionTypeInvokeContract") + require.Equal(itest.CurrentTest(), 1, len(invokeHostFn.AssetBalanceChanges)) + assetBalanceChange := invokeHostFn.AssetBalanceChanges[0] + assert.Equal(itest.CurrentTest(), assetBalanceChange.Amount, amount) + assert.Equal(itest.CurrentTest(), assetBalanceChange.From, from) + assert.Equal(itest.CurrentTest(), assetBalanceChange.To, to) + assert.Equal(itest.CurrentTest(), assetBalanceChange.Type, evtType) + assert.Equal(itest.CurrentTest(), assetBalanceChange.Asset.Code, strings.TrimRight(asset.GetCode(), "\x00")) + assert.Equal(itest.CurrentTest(), assetBalanceChange.Asset.Issuer, asset.GetIssuer()) +} + +func contractIDParam(contractID xdr.Hash) xdr.ScAddress { + return xdr.ScAddress{ + Type: xdr.ScAddressTypeScAddressTypeContract, + ContractId: &contractID, + } +} + +func accountAddressParam(accountID string) xdr.ScVal { + address := xdr.ScAddress{ + Type: xdr.ScAddressTypeScAddressTypeAccount, + AccountId: xdr.MustAddressPtr(accountID), + } + return xdr.ScVal{ + Type: xdr.ScValTypeScvAddress, + Address: &address, + } +} + +func contractAddressParam(contractID xdr.Hash) xdr.ScVal { + address := xdr.ScAddress{ + Type: xdr.ScAddressTypeScAddressTypeContract, + ContractId: &contractID, + } + return xdr.ScVal{ + Type: xdr.ScValTypeScvAddress, + Address: &address, + } +} + +func i128Param(hi int64, lo uint64) xdr.ScVal { + i128 := &xdr.Int128Parts{ + Hi: xdr.Int64(hi), + Lo: xdr.Uint64(lo), + } + return xdr.ScVal{ + Type: xdr.ScValTypeScvI128, + I128: i128, + } +} + +func mint(itest *integration.Test, sourceAccount string, asset xdr.Asset, assetAmount string, recipient xdr.ScVal) *txnbuild.InvokeHostFunction { + return mintWithAmt(itest, sourceAccount, asset, i128Param(0, uint64(amount.MustParse(assetAmount))), recipient) +} + +func mintWithAmt(itest *integration.Test, sourceAccount string, asset xdr.Asset, assetAmount xdr.ScVal, recipient xdr.ScVal) *txnbuild.InvokeHostFunction { + invokeHostFn := &txnbuild.InvokeHostFunction{ + HostFunction: xdr.HostFunction{ + Type: xdr.HostFunctionTypeHostFunctionTypeInvokeContract, + InvokeContract: &xdr.InvokeContractArgs{ + ContractAddress: contractIDParam(stellarAssetContractID(itest, asset)), + FunctionName: "mint", + Args: xdr.ScVec{ + recipient, + assetAmount, + }, + }, + }, + SourceAccount: sourceAccount, + } + + return invokeHostFn +} + +func initAssetContract(itest *integration.Test, sourceAccount string, asset xdr.Asset, sacTestcontractID, sacTestcontractHash xdr.Hash) *txnbuild.InvokeHostFunction { + targetContract := contractIDParam(stellarAssetContractID(itest, asset)) + invokeHostFn := &txnbuild.InvokeHostFunction{ + HostFunction: xdr.HostFunction{ + Type: xdr.HostFunctionTypeHostFunctionTypeInvokeContract, + InvokeContract: &xdr.InvokeContractArgs{ + ContractAddress: contractIDParam(sacTestcontractID), + FunctionName: "init", + Args: xdr.ScVec{ + { + Type: xdr.ScValTypeScvAddress, + Address: &targetContract, + }, + }, + }, + }, + SourceAccount: sourceAccount, + } + + return invokeHostFn +} + +func clawback(itest *integration.Test, sourceAccount string, asset xdr.Asset, assetAmount string, recipient xdr.ScVal) *txnbuild.InvokeHostFunction { + invokeHostFn := &txnbuild.InvokeHostFunction{ + HostFunction: xdr.HostFunction{ + Type: xdr.HostFunctionTypeHostFunctionTypeInvokeContract, + InvokeContract: &xdr.InvokeContractArgs{ + ContractAddress: contractIDParam(stellarAssetContractID(itest, asset)), + FunctionName: "clawback", + Args: xdr.ScVec{ + recipient, + i128Param(0, uint64(amount.MustParse(assetAmount))), + }, + }, + }, + SourceAccount: sourceAccount, + } + + return invokeHostFn +} + +func contractBalance(itest *integration.Test, sourceAccount string, asset xdr.Asset, sacTestcontractID xdr.Hash) *txnbuild.InvokeHostFunction { + invokeHostFn := &txnbuild.InvokeHostFunction{ + HostFunction: xdr.HostFunction{ + Type: xdr.HostFunctionTypeHostFunctionTypeInvokeContract, + InvokeContract: &xdr.InvokeContractArgs{ + ContractAddress: contractIDParam(stellarAssetContractID(itest, asset)), + FunctionName: "balance", + Args: xdr.ScVec{contractAddressParam(sacTestcontractID)}, + }, + }, + SourceAccount: sourceAccount, + } + + return invokeHostFn +} + +func transfer(itest *integration.Test, sourceAccount string, asset xdr.Asset, assetAmount string, recipient xdr.ScVal) *txnbuild.InvokeHostFunction { + return transferWithAmount(itest, sourceAccount, asset, i128Param(0, uint64(amount.MustParse(assetAmount))), recipient) +} + +func transferWithAmount(itest *integration.Test, sourceAccount string, asset xdr.Asset, assetAmount xdr.ScVal, recipient xdr.ScVal) *txnbuild.InvokeHostFunction { + invokeHostFn := &txnbuild.InvokeHostFunction{ + HostFunction: xdr.HostFunction{ + Type: xdr.HostFunctionTypeHostFunctionTypeInvokeContract, + InvokeContract: &xdr.InvokeContractArgs{ + ContractAddress: contractIDParam(stellarAssetContractID(itest, asset)), + FunctionName: "transfer", + Args: xdr.ScVec{ + accountAddressParam(sourceAccount), + recipient, + assetAmount, + }, + }, + }, + SourceAccount: sourceAccount, + } + + return invokeHostFn +} + +func transferFromContract(itest *integration.Test, sourceAccount string, asset xdr.Asset, sacTestcontractID xdr.Hash, sacTestContractHash xdr.Hash, assetAmount string, recipient xdr.ScVal) *txnbuild.InvokeHostFunction { + invokeHostFn := &txnbuild.InvokeHostFunction{ + HostFunction: xdr.HostFunction{ + Type: xdr.HostFunctionTypeHostFunctionTypeInvokeContract, + InvokeContract: &xdr.InvokeContractArgs{ + ContractAddress: contractIDParam(sacTestcontractID), + FunctionName: "transfer", + Args: xdr.ScVec{ + recipient, + i128Param(0, uint64(amount.MustParse(assetAmount))), + }, + }, + }, + SourceAccount: sourceAccount, + } + + return invokeHostFn +} + +// Invokes burn_self from the sac_test contract (which just burns assets from itself) +func burnSelf(itest *integration.Test, sourceAccount string, asset xdr.Asset, sacTestcontractID xdr.Hash, sacTestContractHash xdr.Hash, assetAmount string) *txnbuild.InvokeHostFunction { + invokeHostFn := &txnbuild.InvokeHostFunction{ + HostFunction: xdr.HostFunction{ + Type: xdr.HostFunctionTypeHostFunctionTypeInvokeContract, + InvokeContract: &xdr.InvokeContractArgs{ + ContractAddress: contractIDParam(sacTestcontractID), + FunctionName: "burn_self", + Args: xdr.ScVec{ + i128Param(0, uint64(amount.MustParse(assetAmount))), + }, + }, + }, + SourceAccount: sourceAccount, + } + + return invokeHostFn +} + +func burn(itest *integration.Test, sourceAccount string, asset xdr.Asset, assetAmount string) *txnbuild.InvokeHostFunction { + invokeHostFn := &txnbuild.InvokeHostFunction{ + HostFunction: xdr.HostFunction{ + Type: xdr.HostFunctionTypeHostFunctionTypeInvokeContract, + InvokeContract: &xdr.InvokeContractArgs{ + ContractAddress: contractIDParam(stellarAssetContractID(itest, asset)), + FunctionName: "burn", + Args: xdr.ScVec{ + accountAddressParam(sourceAccount), + i128Param(0, uint64(amount.MustParse(assetAmount))), + }, + }, + }, + SourceAccount: sourceAccount, + } + + return invokeHostFn +} + +func assertInvokeHostFnSucceeds(itest *integration.Test, signer *keypair.Full, op *txnbuild.InvokeHostFunction) (*xdr.ScVal, string, *txnbuild.InvokeHostFunction) { + acc := itest.MustGetAccount(signer) + preFlightOp, minFee := itest.PreflightHostFunctions(&acc, *op) + clientTx, err := itest.SubmitOperationsWithFee(&acc, signer, minFee+txnbuild.MinBaseFee, &preFlightOp) + require.NoError(itest.CurrentTest(), err) + + var txResult xdr.TransactionResult + err = xdr.SafeUnmarshalBase64(clientTx.ResultXdr, &txResult) + require.NoError(itest.CurrentTest(), err) + + var txMetaResult xdr.TransactionMeta + err = xdr.SafeUnmarshalBase64(clientTx.ResultMetaXdr, &txMetaResult) + require.NoError(itest.CurrentTest(), err) + + opResults, ok := txResult.OperationResults() + assert.True(itest.CurrentTest(), ok) + assert.Equal(itest.CurrentTest(), len(opResults), 1) + invokeHostFunctionResult, ok := opResults[0].MustTr().GetInvokeHostFunctionResult() + assert.True(itest.CurrentTest(), ok) + assert.Equal(itest.CurrentTest(), invokeHostFunctionResult.Code, xdr.InvokeHostFunctionResultCodeInvokeHostFunctionSuccess) + + returnValue := txMetaResult.MustV3().SorobanMeta.ReturnValue + + return &returnValue, clientTx.Hash, &preFlightOp +} + +func stellarAssetContractID(itest *integration.Test, asset xdr.Asset) xdr.Hash { + contractID, err := asset.ContractID(itest.GetPassPhrase()) + require.NoError(itest.CurrentTest(), err) + return contractID +} + +func mustCreateAndInstallContract(itest *integration.Test, signer *keypair.Full, contractSalt string, wasmFileName string) (xdr.Hash, xdr.Hash) { + _, _, installContractOp := assertInvokeHostFnSucceeds( + itest, + signer, + assembleInstallContractCodeOp( + itest.CurrentTest(), + itest.Master().Address(), + wasmFileName, + ), + ) + _, _, createContractOp := assertInvokeHostFnSucceeds( + itest, + signer, + assembleCreateContractOp( + itest.CurrentTest(), + itest.Master().Address(), + wasmFileName, + contractSalt, + itest.GetPassPhrase(), + ), + ) + + keys := append( + installContractOp.Ext.SorobanData.Resources.Footprint.ReadWrite, + createContractOp.Ext.SorobanData.Resources.Footprint.ReadWrite..., + ) + + sourceAccount, extendTTLOp, minFee := itest.PreflightExtendExpiration( + itest.Master().Address(), + keys, + LongTermTTL, + ) + itest.MustSubmitOperationsWithFee(&sourceAccount, itest.Master(), minFee+txnbuild.MinBaseFee, &extendTTLOp) + + contractHash := createContractOp.Ext.SorobanData.Resources.Footprint.ReadOnly[0].MustContractCode().Hash + contractID := createContractOp.Ext.SorobanData.Resources.Footprint.ReadWrite[0].MustContractData().Contract.ContractId + return *contractID, contractHash +} diff --git a/services/horizon/internal/integration/sponsorship_test.go b/services/horizon/internal/integration/sponsorship_test.go index d1f3c25d91..fac8c499e7 100644 --- a/services/horizon/internal/integration/sponsorship_test.go +++ b/services/horizon/internal/integration/sponsorship_test.go @@ -516,7 +516,7 @@ func TestSponsorships(t *testing.T) { Selling: txnbuild.NativeAsset{}, Buying: asset, Amount: "3", - Price: xdr.Price{1, 1}, + Price: xdr.Price{N: 1, D: 1}, }) signers := []*keypair.Full{sponsorPair, newAccountPair} diff --git a/services/horizon/internal/integration/state_verifier_test.go b/services/horizon/internal/integration/state_verifier_test.go index 5045edb3bf..552bcf28e3 100644 --- a/services/horizon/internal/integration/state_verifier_test.go +++ b/services/horizon/internal/integration/state_verifier_test.go @@ -43,7 +43,7 @@ func TestStateVerifier(t *testing.T) { }, &txnbuild.ChangeTrust{ SourceAccount: sponsoredSource.AccountID, - Line: txnbuild.CreditAsset{"ABCD", master.Address()}.MustToChangeTrustAsset(), + Line: txnbuild.CreditAsset{Code: "ABCD", Issuer: master.Address()}.MustToChangeTrustAsset(), Limit: txnbuild.MaxTrustlineLimit, }, &txnbuild.ChangeTrust{ @@ -62,9 +62,9 @@ func TestStateVerifier(t *testing.T) { &txnbuild.ManageSellOffer{ SourceAccount: sponsoredSource.AccountID, Selling: txnbuild.NativeAsset{}, - Buying: txnbuild.CreditAsset{"ABCD", master.Address()}, + Buying: txnbuild.CreditAsset{Code: "ABCD", Issuer: master.Address()}, Amount: "3", - Price: xdr.Price{1, 1}, + Price: xdr.Price{N: 1, D: 1}, }, &txnbuild.ManageData{ SourceAccount: sponsoredSource.AccountID, @@ -121,8 +121,8 @@ func TestStateVerifier(t *testing.T) { // Trigger state rebuild to check if ingesting from history archive works session := itest.HorizonIngest().HistoryQ().Clone() - q := &history.Q{session} - err = q.Begin() + q := &history.Q{SessionInterface: session} + err = q.Begin(context.Background()) assert.NoError(t, err) _, err = q.GetLastLedgerIngest(context.Background()) assert.NoError(t, err) diff --git a/services/horizon/internal/integration/testdata/soroban_add_u64.wasm b/services/horizon/internal/integration/testdata/soroban_add_u64.wasm new file mode 100755 index 0000000000..9ffd8622b7 Binary files /dev/null and b/services/horizon/internal/integration/testdata/soroban_add_u64.wasm differ diff --git a/services/horizon/internal/integration/testdata/soroban_increment_contract.wasm b/services/horizon/internal/integration/testdata/soroban_increment_contract.wasm new file mode 100755 index 0000000000..b975e5ccd5 Binary files /dev/null and b/services/horizon/internal/integration/testdata/soroban_increment_contract.wasm differ diff --git a/services/horizon/internal/integration/testdata/soroban_sac_test.wasm b/services/horizon/internal/integration/testdata/soroban_sac_test.wasm new file mode 100755 index 0000000000..9424da50fd Binary files /dev/null and b/services/horizon/internal/integration/testdata/soroban_sac_test.wasm differ diff --git a/services/horizon/internal/integration/testdata/soroban_store.wasm b/services/horizon/internal/integration/testdata/soroban_store.wasm new file mode 100755 index 0000000000..7f839bd208 Binary files /dev/null and b/services/horizon/internal/integration/testdata/soroban_store.wasm differ diff --git a/services/horizon/internal/integration/trade_aggregations_test.go b/services/horizon/internal/integration/trade_aggregations_test.go index ae9c675875..ff3837444f 100644 --- a/services/horizon/internal/integration/trade_aggregations_test.go +++ b/services/horizon/internal/integration/trade_aggregations_test.go @@ -272,14 +272,14 @@ func TestTradeAggregations(t *testing.T) { for _, scenario := range scenarios { t.Run(scenario.name, func(t *testing.T) { // Run each in a txn so the ids don't conflict. - assert.NoError(t, historyQ.Begin()) + assert.NoError(t, historyQ.Begin(ctx)) defer func() { assert.NoError(t, historyQ.Rollback()) }() - batch := historyQ.NewTradeBatchInsertBuilder(1000) - batch.Add(ctx, scenario.trades...) - assert.NoError(t, batch.Exec(ctx)) + batch := historyQ.NewTradeBatchInsertBuilder() + assert.NoError(t, batch.Add(scenario.trades...)) + assert.NoError(t, batch.Exec(ctx, historyQ)) // Rebuild the aggregates. for _, trade := range scenario.trades { diff --git a/services/horizon/internal/integration/transaction_preconditions_test.go b/services/horizon/internal/integration/transaction_preconditions_test.go index 44a6baac82..e3aff9e0da 100644 --- a/services/horizon/internal/integration/transaction_preconditions_test.go +++ b/services/horizon/internal/integration/transaction_preconditions_test.go @@ -5,89 +5,18 @@ import ( "encoding/base64" "math" "strconv" - "sync" "testing" "time" sdk "github.com/stellar/go/clients/horizonclient" "github.com/stellar/go/keypair" "github.com/stellar/go/network" - "github.com/stellar/go/protocols/horizon" "github.com/stellar/go/services/horizon/internal/test/integration" "github.com/stellar/go/txnbuild" "github.com/stellar/go/xdr" "github.com/stretchr/testify/assert" ) -func TestTransactionPreconditionsMinSeq(t *testing.T) { - tt := assert.New(t) - itest := integration.NewTest(t, integration.Config{}) - if itest.GetEffectiveProtocolVersion() < 19 { - t.Skip("Can't run with protocol < 19") - } - master := itest.Master() - masterAccount := itest.MasterAccount() - currentAccountSeq, err := masterAccount.GetSequenceNumber() - tt.NoError(err) - - // Ensure that the minSequence of the transaction is enough - // but the sequence isn't - txParams := buildTXParams(master, masterAccount, currentAccountSeq+100) - - // this errors because the tx.seqNum is more than +1 from sourceAccoubnt.seqNum - _, err = itest.SubmitTransaction(master, txParams) - tt.Error(err) - - // Now the transaction should be submitted without problems - txParams.Preconditions.MinSequenceNumber = ¤tAccountSeq - tx := itest.MustSubmitTransaction(master, txParams) - - txHistory, err := itest.Client().TransactionDetail(tx.Hash) - assert.NoError(t, err) - assert.Equal(t, txHistory.Preconditions.MinAccountSequence, strconv.FormatInt(*txParams.Preconditions.MinSequenceNumber, 10)) - - // Test the transaction submission queue by sending transactions out of order - // and making sure they are all executed properly - masterAccount = itest.MasterAccount() - currentAccountSeq, err = masterAccount.GetSequenceNumber() - tt.NoError(err) - - seqs := []struct { - minSeq int64 - seq int64 - }{ - {0, currentAccountSeq + 9}, // sent first, executed second - {0, currentAccountSeq + 10}, // sent second, executed third - {currentAccountSeq, currentAccountSeq + 8}, // sent third, executed first - } - - // Send the transactions in parallel since otherwise they are admitted sequentially - var results []horizon.Transaction - var resultsMx sync.Mutex - var wg sync.WaitGroup - wg.Add(len(seqs)) - for _, s := range seqs { - sLocal := s - go func() { - params := buildTXParams(master, masterAccount, sLocal.seq) - if sLocal.minSeq > 0 { - params.Preconditions.MinSequenceNumber = &sLocal.minSeq - } - result := itest.MustSubmitTransaction(master, params) - resultsMx.Lock() - results = append(results, result) - resultsMx.Unlock() - wg.Done() - }() - // Space out requests to ensure the queue receives the transactions - // in the planned order - time.Sleep(time.Millisecond * 50) - } - wg.Wait() - - tt.Len(results, len(seqs)) -} - func TestTransactionPreconditionsTimeBounds(t *testing.T) { tt := assert.New(t) itest := integration.NewTest(t, integration.Config{}) @@ -289,7 +218,7 @@ func TestTransactionPreconditionsMinSequenceNumberLedgerGap(t *testing.T) { txParams := buildTXParams(master, masterAccount, currentAccountSeq+1) // this txsub will error because the tx preconditions require a min sequence gap - // which has been set 10000 sequnce numbers greater than the current difference between + // which has been set 10000 sequence numbers greater than the current difference between // network ledger sequence and account sequnece numbers txParams.Preconditions.MinSequenceNumberLedgerGap = uint32(int64(networkLedger) - currentAccountSeq + 10000) _, err = itest.SubmitMultiSigTransaction([]*keypair.Full{master}, txParams) @@ -383,11 +312,11 @@ func TestTransactionPreconditionsEdgeCases(t *testing.T) { maxMinSeq := int64(math.MaxInt64) preconditionTests := []txnbuild.Preconditions{ - {LedgerBounds: &txnbuild.LedgerBounds{1, 0}}, - {LedgerBounds: &txnbuild.LedgerBounds{0, math.MaxUint32}}, - {LedgerBounds: &txnbuild.LedgerBounds{math.MaxUint32, 1}}, + {LedgerBounds: &txnbuild.LedgerBounds{MinLedger: 1, MaxLedger: 0}}, + {LedgerBounds: &txnbuild.LedgerBounds{MinLedger: 0, MaxLedger: math.MaxUint32}}, + {LedgerBounds: &txnbuild.LedgerBounds{MinLedger: math.MaxUint32, MaxLedger: 1}}, { - LedgerBounds: &txnbuild.LedgerBounds{math.MaxUint32, 1}, + LedgerBounds: &txnbuild.LedgerBounds{MinLedger: math.MaxUint32, MaxLedger: 1}, ExtraSigners: []string{}, }, { diff --git a/services/horizon/internal/integration/txsub_test.go b/services/horizon/internal/integration/txsub_test.go index 60b8717b18..2f6b98e905 100644 --- a/services/horizon/internal/integration/txsub_test.go +++ b/services/horizon/internal/integration/txsub_test.go @@ -1,68 +1,94 @@ package integration import ( - "sync" "testing" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/stellar/go/clients/horizonclient" "github.com/stellar/go/services/horizon/internal/test/integration" "github.com/stellar/go/txnbuild" - "github.com/stretchr/testify/assert" ) -func TestTxsub(t *testing.T) { +func TestTxSub(t *testing.T) { tt := assert.New(t) - itest := integration.NewTest(t, integration.Config{}) - master := itest.Master() - - // Sanity check: create 20 accounts and submit 2 txs from each of them as - // a source at the same time. Then check if the results are correct. - t.Run("Sanity", func(t *testing.T) { - testAccounts := 20 - subsPerAccont := 2 - keys, accounts := itest.CreateAccounts(testAccounts, "1000") - - var wg sync.WaitGroup - - for i := 0; i < testAccounts; i++ { - for j := 0; j < subsPerAccont; j++ { - wg.Add(1) - - seq, err := accounts[i].GetSequenceNumber() - assert.NoError(t, err) - - var account txnbuild.SimpleAccount - if j == 0 { - account = txnbuild.SimpleAccount{ - AccountID: keys[i].Address(), - Sequence: seq, - } - } else { - account = txnbuild.SimpleAccount{ - AccountID: keys[i].Address(), - Sequence: seq + 1, - } - } - - go func(i int, j int, account txnbuild.SimpleAccount) { - defer wg.Done() - - op := txnbuild.Payment{ - Destination: master.Address(), - Amount: "10", - Asset: txnbuild.NativeAsset{}, - } - - txResp := itest.MustSubmitOperations(&account, keys[i], &op) - - tt.Equal(accounts[i].GetAccountID(), txResp.Account) - seq, err := account.GetSequenceNumber() - assert.NoError(t, err) - tt.Equal(seq, txResp.AccountSequence) - t.Logf("%d/%d done", i, j) - }(i, j, account) - } + + t.Run("transaction submission is successful when DISABLE_TX_SUB=false", func(t *testing.T) { + itest := integration.NewTest(t, integration.Config{}) + master := itest.Master() + + op := txnbuild.Payment{ + Destination: master.Address(), + Amount: "10", + Asset: txnbuild.NativeAsset{}, + } + + txResp, err := itest.SubmitOperations(itest.MasterAccount(), master, &op) + assert.NoError(t, err) + + var seq int64 + tt.Equal(itest.MasterAccount().GetAccountID(), txResp.Account) + seq, err = itest.MasterAccount().GetSequenceNumber() + assert.NoError(t, err) + tt.Equal(seq, txResp.AccountSequence) + t.Logf("Done") + }) + + t.Run("transaction submission is not successful when DISABLE_TX_SUB=true", func(t *testing.T) { + itest := integration.NewTest(t, integration.Config{ + HorizonEnvironment: map[string]string{ + "DISABLE_TX_SUB": "true", + }, + }) + master := itest.Master() + + op := txnbuild.Payment{ + Destination: master.Address(), + Amount: "10", + Asset: txnbuild.NativeAsset{}, } - wg.Wait() + _, err := itest.SubmitOperations(itest.MasterAccount(), master, &op) + assert.Error(t, err) }) } + +func TestTxSubLimitsBodySize(t *testing.T) { + if integration.GetCoreMaxSupportedProtocol() < 20 { + t.Skip("This test run does not support less than Protocol 20") + } + + itest := integration.NewTest(t, integration.Config{ + ProtocolVersion: 20, + EnableSorobanRPC: true, + HorizonEnvironment: map[string]string{ + "MAX_HTTP_REQUEST_SIZE": "1800", + }, + }) + + // establish which account will be contract owner, and load it's current seq + sourceAccount, err := itest.Client().AccountDetail(horizonclient.AccountRequest{ + AccountID: itest.Master().Address(), + }) + require.NoError(t, err) + + installContractOp := assembleInstallContractCodeOp(t, itest.Master().Address(), "soroban_sac_test.wasm") + preFlightOp, minFee := itest.PreflightHostFunctions(&sourceAccount, *installContractOp) + _, err = itest.SubmitOperationsWithFee(&sourceAccount, itest.Master(), minFee+txnbuild.MinBaseFee, &preFlightOp) + assert.EqualError( + t, err, + "horizon error: \"Transaction Malformed\" - check horizon.Error.Problem for more information", + ) + + sourceAccount, err = itest.Client().AccountDetail(horizonclient.AccountRequest{ + AccountID: itest.Master().Address(), + }) + require.NoError(t, err) + + installContractOp = assembleInstallContractCodeOp(t, itest.Master().Address(), "soroban_add_u64.wasm") + preFlightOp, minFee = itest.PreflightHostFunctions(&sourceAccount, *installContractOp) + tx, err := itest.SubmitOperationsWithFee(&sourceAccount, itest.Master(), minFee+txnbuild.MinBaseFee, &preFlightOp) + require.NoError(t, err) + require.True(t, tx.Successful) +} diff --git a/services/horizon/internal/middleware_test.go b/services/horizon/internal/middleware_test.go index 08b90465f3..40a74ea69e 100644 --- a/services/horizon/internal/middleware_test.go +++ b/services/horizon/internal/middleware_test.go @@ -284,7 +284,10 @@ func TestStateMiddleware(t *testing.T) { t.Run(testCase.name, func(t *testing.T) { stateMiddleware.NoStateVerification = testCase.noStateVerification tt.Assert.NoError(q.UpdateExpStateInvalid(context.Background(), testCase.stateInvalid)) - _, err = q.InsertLedger(context.Background(), xdr.LedgerHeaderHistoryEntry{ + + tt.Assert.NoError(q.Begin(tt.Ctx)) + ledgerBatch := q.NewLedgerBatchInsertBuilder() + err = ledgerBatch.Add(xdr.LedgerHeaderHistoryEntry{ Hash: xdr.Hash{byte(i)}, Header: xdr.LedgerHeader{ LedgerSeq: testCase.latestHistoryLedger, @@ -292,6 +295,9 @@ func TestStateMiddleware(t *testing.T) { }, }, 0, 0, 0, 0, 0) tt.Assert.NoError(err) + tt.Assert.NoError(ledgerBatch.Exec(tt.Ctx, q)) + tt.Assert.NoError(q.Commit()) + tt.Assert.NoError(q.UpdateLastLedgerIngest(context.Background(), testCase.lastIngestedLedger)) tt.Assert.NoError(q.UpdateIngestVersion(context.Background(), testCase.ingestionVersion)) diff --git a/services/horizon/internal/paths/main.go b/services/horizon/internal/paths/main.go index d5baaf25d8..f7cae1b697 100644 --- a/services/horizon/internal/paths/main.go +++ b/services/horizon/internal/paths/main.go @@ -35,7 +35,7 @@ type Finder interface { Find(ctx context.Context, q Query, maxLength uint) ([]Path, uint32, error) // FindFixedPaths return a list of payment paths the most recent ledger // Each of the payment paths start by spending `amountToSpend` of `sourceAsset` and end - // with delivering a postive amount of `destinationAsset`. + // with delivering a positive amount of `destinationAsset`. // The payment paths are accurate and consistent with the returned ledger sequence number FindFixedPaths( ctx context.Context, diff --git a/services/horizon/internal/reap/system.go b/services/horizon/internal/reap/system.go index 54a97102d3..e5eeb5cd43 100644 --- a/services/horizon/internal/reap/system.go +++ b/services/horizon/internal/reap/system.go @@ -95,7 +95,7 @@ func (r *System) clearBefore(ctx context.Context, startSeq, endSeq int32) error return err } - err = r.HistoryQ.Begin() + err = r.HistoryQ.Begin(ctx) if err != nil { return errors.Wrap(err, "Error in begin") } diff --git a/services/horizon/internal/render/sse/stream_test.go b/services/horizon/internal/render/sse/stream_test.go index 48cff6bb12..23f74d8b37 100644 --- a/services/horizon/internal/render/sse/stream_test.go +++ b/services/horizon/internal/render/sse/stream_test.go @@ -101,7 +101,7 @@ func (suite *StreamTestSuite) TestStream_ErrRegisterError() { suite.stream.Send(Event{}) suite.stream.Err(context.DeadlineExceeded) suite.checkHeadersAndPreamble() - assert.Contains(suite.T(), suite.w.Body.String(), "event: error\ndata: problem: timeout\n\n") + assert.Contains(suite.T(), suite.w.Body.String(), "event: error\ndata: problem: timeout") assert.True(suite.T(), suite.stream.IsDone()) } @@ -116,7 +116,7 @@ func (suite *StreamTestSuite) TestStream_ErrNoRows() { suite.stream.Send(Event{}) suite.stream.Err(sql.ErrNoRows) suite.checkHeadersAndPreamble() - assert.Contains(suite.T(), suite.w.Body.String(), "event: error\ndata: problem: not_found\n\n") + assert.Contains(suite.T(), suite.w.Body.String(), "event: error\ndata: problem: not_found") assert.True(suite.T(), suite.stream.IsDone()) } diff --git a/services/horizon/internal/resourceadapter/asset_stat.go b/services/horizon/internal/resourceadapter/asset_stat.go index 9ae61fb4ac..994cce99a0 100644 --- a/services/horizon/internal/resourceadapter/asset_stat.go +++ b/services/horizon/internal/resourceadapter/asset_stat.go @@ -7,6 +7,7 @@ import ( "github.com/stellar/go/amount" protocol "github.com/stellar/go/protocols/horizon" "github.com/stellar/go/services/horizon/internal/db2/history" + "github.com/stellar/go/strkey" "github.com/stellar/go/support/errors" "github.com/stellar/go/support/render/hal" "github.com/stellar/go/xdr" @@ -17,9 +18,15 @@ import ( func PopulateAssetStat( ctx context.Context, res *protocol.AssetStat, - row history.ExpAssetStat, + row history.AssetAndContractStat, issuer history.AccountEntry, ) (err error) { + if row.ContractID != nil { + res.ContractID, err = strkey.Encode(strkey.VersionByteContract, *row.ContractID) + if err != nil { + return + } + } res.Asset.Type = xdr.AssetTypeToString[row.AssetType] res.Asset.Code = row.AssetCode res.Asset.Issuer = row.AssetIssuer @@ -30,8 +37,10 @@ func PopulateAssetStat( } res.NumClaimableBalances = row.Accounts.ClaimableBalances res.NumLiquidityPools = row.Accounts.LiquidityPools + res.NumContracts = row.Contracts.ActiveHolders + res.NumArchivedContracts = row.Contracts.ArchivedHolders res.NumAccounts = row.NumAccounts - err = populateAssetStatBalances(res, row.Balances) + err = populateAssetStatBalances(res, row) if err != nil { return err } @@ -53,35 +62,45 @@ func PopulateAssetStat( return } -func populateAssetStatBalances(res *protocol.AssetStat, row history.ExpAssetStatBalances) (err error) { - res.Amount, err = amount.IntStringToAmount(row.Authorized) +func populateAssetStatBalances(res *protocol.AssetStat, row history.AssetAndContractStat) (err error) { + res.Amount, err = amount.IntStringToAmount(row.Balances.Authorized) if err != nil { return errors.Wrap(err, "Invalid amount in PopulateAssetStat") } - res.Balances.Authorized, err = amount.IntStringToAmount(row.Authorized) + res.Balances.Authorized, err = amount.IntStringToAmount(row.Balances.Authorized) + if err != nil { + return errors.Wrapf(err, "Invalid amount in PopulateAssetStatBalances: %q", row.Balances.Authorized) + } + + res.Balances.AuthorizedToMaintainLiabilities, err = amount.IntStringToAmount(row.Balances.AuthorizedToMaintainLiabilities) + if err != nil { + return errors.Wrapf(err, "Invalid amount in PopulateAssetStatBalances: %q", row.Balances.AuthorizedToMaintainLiabilities) + } + + res.Balances.Unauthorized, err = amount.IntStringToAmount(row.Balances.Unauthorized) if err != nil { - return errors.Wrapf(err, "Invalid amount in PopulateAssetStatBalances: %q", row.Authorized) + return errors.Wrapf(err, "Invalid amount in PopulateAssetStatBalances: %q", row.Balances.Unauthorized) } - res.Balances.AuthorizedToMaintainLiabilities, err = amount.IntStringToAmount(row.AuthorizedToMaintainLiabilities) + res.ClaimableBalancesAmount, err = amount.IntStringToAmount(row.Balances.ClaimableBalances) if err != nil { - return errors.Wrapf(err, "Invalid amount in PopulateAssetStatBalances: %q", row.AuthorizedToMaintainLiabilities) + return errors.Wrapf(err, "Invalid amount in PopulateAssetStatBalances: %q", row.Balances.ClaimableBalances) } - res.Balances.Unauthorized, err = amount.IntStringToAmount(row.Unauthorized) + res.LiquidityPoolsAmount, err = amount.IntStringToAmount(row.Balances.LiquidityPools) if err != nil { - return errors.Wrapf(err, "Invalid amount in PopulateAssetStatBalances: %q", row.Unauthorized) + return errors.Wrapf(err, "Invalid amount in PopulateAssetStatBalances: %q", row.Balances.LiquidityPools) } - res.ClaimableBalancesAmount, err = amount.IntStringToAmount(row.ClaimableBalances) + res.ContractsAmount, err = amount.IntStringToAmount(row.Contracts.ActiveBalance) if err != nil { - return errors.Wrapf(err, "Invalid amount in PopulateAssetStatBalances: %q", row.ClaimableBalances) + return errors.Wrapf(err, "Invalid amount in PopulateAssetStatBalances: %q", row.Contracts.ActiveBalance) } - res.LiquidityPoolsAmount, err = amount.IntStringToAmount(row.LiquidityPools) + res.ArchivedContractsAmount, err = amount.IntStringToAmount(row.Contracts.ArchivedBalance) if err != nil { - return errors.Wrapf(err, "Invalid amount in PopulateAssetStatBalances: %q", row.LiquidityPools) + return errors.Wrapf(err, "Invalid amount in PopulateAssetStatBalances: %q", row.Contracts.ArchivedBalance) } return nil diff --git a/services/horizon/internal/resourceadapter/asset_stat_test.go b/services/horizon/internal/resourceadapter/asset_stat_test.go index cd598f4b01..d3b14d62e6 100644 --- a/services/horizon/internal/resourceadapter/asset_stat_test.go +++ b/services/horizon/internal/resourceadapter/asset_stat_test.go @@ -4,33 +4,42 @@ import ( "context" "testing" + "github.com/stretchr/testify/assert" + "github.com/stellar/go/protocols/horizon" protocol "github.com/stellar/go/protocols/horizon" "github.com/stellar/go/services/horizon/internal/db2/history" "github.com/stellar/go/xdr" - "github.com/stretchr/testify/assert" ) func TestPopulateExpAssetStat(t *testing.T) { - row := history.ExpAssetStat{ - AssetType: xdr.AssetTypeAssetTypeCreditAlphanum4, - AssetCode: "XIM", - AssetIssuer: "GBZ35ZJRIKJGYH5PBKLKOZ5L6EXCNTO7BKIL7DAVVDFQ2ODJEEHHJXIM", - Accounts: history.ExpAssetStatAccounts{ - Authorized: 429, - AuthorizedToMaintainLiabilities: 214, - Unauthorized: 107, - ClaimableBalances: 12, + row := history.AssetAndContractStat{ + ExpAssetStat: history.ExpAssetStat{ + AssetType: xdr.AssetTypeAssetTypeCreditAlphanum4, + AssetCode: "XIM", + AssetIssuer: "GBZ35ZJRIKJGYH5PBKLKOZ5L6EXCNTO7BKIL7DAVVDFQ2ODJEEHHJXIM", + Accounts: history.ExpAssetStatAccounts{ + Authorized: 429, + AuthorizedToMaintainLiabilities: 214, + Unauthorized: 107, + ClaimableBalances: 12, + }, + Balances: history.ExpAssetStatBalances{ + Authorized: "100000000000000000000", + AuthorizedToMaintainLiabilities: "50000000000000000000", + Unauthorized: "2500000000000000000", + ClaimableBalances: "1200000000000000000", + LiquidityPools: "7700000000000000000", + }, + Amount: "100000000000000000000", // 10T + NumAccounts: 429, }, - Balances: history.ExpAssetStatBalances{ - Authorized: "100000000000000000000", - AuthorizedToMaintainLiabilities: "50000000000000000000", - Unauthorized: "2500000000000000000", - ClaimableBalances: "1200000000000000000", - LiquidityPools: "7700000000000000000", + Contracts: history.ContractStat{ + ActiveBalance: "900000000000000000", + ActiveHolders: 6, + ArchivedBalance: "700000000000000000", + ArchivedHolders: 3, }, - Amount: "100000000000000000000", // 10T - NumAccounts: 429, } issuer := history.AccountEntry{ AccountID: "GBZ35ZJRIKJGYH5PBKLKOZ5L6EXCNTO7BKIL7DAVVDFQ2ODJEEHHJXIM", @@ -49,17 +58,27 @@ func TestPopulateExpAssetStat(t *testing.T) { assert.Equal(t, int32(214), res.Accounts.AuthorizedToMaintainLiabilities) assert.Equal(t, int32(107), res.Accounts.Unauthorized) assert.Equal(t, int32(12), res.NumClaimableBalances) + assert.Equal(t, int32(6), res.NumContracts) + assert.Equal(t, int32(3), res.NumArchivedContracts) assert.Equal(t, "10000000000000.0000000", res.Balances.Authorized) assert.Equal(t, "5000000000000.0000000", res.Balances.AuthorizedToMaintainLiabilities) assert.Equal(t, "250000000000.0000000", res.Balances.Unauthorized) assert.Equal(t, "120000000000.0000000", res.ClaimableBalancesAmount) assert.Equal(t, "770000000000.0000000", res.LiquidityPoolsAmount) + assert.Equal(t, "90000000000.0000000", res.ContractsAmount) + assert.Equal(t, "70000000000.0000000", res.ArchivedContractsAmount) assert.Equal(t, "10000000000000.0000000", res.Amount) assert.Equal(t, int32(429), res.NumAccounts) assert.Equal(t, horizon.AccountFlags{}, res.Flags) assert.Equal(t, "https://xim.com/.well-known/stellar.toml", res.Links.Toml.Href) + assert.Equal(t, "", res.ContractID) assert.Equal(t, row.PagingToken(), res.PagingToken()) + contractID := [32]byte{} + row.SetContractID(contractID) + assert.NoError(t, PopulateAssetStat(context.Background(), &res, row, issuer)) + assert.Equal(t, "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABSC4", res.ContractID) + issuer.HomeDomain = "" issuer.Flags = uint32(xdr.AccountFlagsAuthRequiredFlag) | uint32(xdr.AccountFlagsAuthImmutableFlag) | diff --git a/services/horizon/internal/resourceadapter/effects.go b/services/horizon/internal/resourceadapter/effects.go index 1f197b123b..cad64d6965 100644 --- a/services/horizon/internal/resourceadapter/effects.go +++ b/services/horizon/internal/resourceadapter/effects.go @@ -64,6 +64,8 @@ var EffectTypeNames = map[history.EffectType]string{ history.EffectLiquidityPoolCreated: "liquidity_pool_created", history.EffectLiquidityPoolRemoved: "liquidity_pool_removed", history.EffectLiquidityPoolRevoked: "liquidity_pool_revoked", + history.EffectContractCredited: "contract_credited", + history.EffectContractDebited: "contract_debited", } // NewEffect creates a new effect resource from the provided database representation @@ -281,6 +283,14 @@ func NewEffect( e := effects.LiquidityPoolRevoked{Base: basev} err = row.UnmarshalDetails(&e) result = e + case history.EffectContractCredited: + e := effects.ContractCredited{Base: basev} + err = row.UnmarshalDetails(&e) + result = e + case history.EffectContractDebited: + e := effects.ContractDebited{Base: basev} + err = row.UnmarshalDetails(&e) + result = e case history.EffectAccountRemoved: // there is no explicit data structure for account removed fallthrough diff --git a/services/horizon/internal/resourceadapter/effects_test.go b/services/horizon/internal/resourceadapter/effects_test.go index f0ef2f4912..c9154da41f 100644 --- a/services/horizon/internal/resourceadapter/effects_test.go +++ b/services/horizon/internal/resourceadapter/effects_test.go @@ -11,6 +11,7 @@ import ( "github.com/stellar/go/support/render/hal" "github.com/stellar/go/support/test" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestNewEffectAllEffectsCovered(t *testing.T) { @@ -42,13 +43,13 @@ func TestNewEffectAllEffectsCovered(t *testing.T) { func TestEffectTypeNamesAreConsistentWithAdapterTypeNames(t *testing.T) { for typ, s := range EffectTypeNames { s2, ok := effects.EffectTypeNames[effects.EffectType(typ)] - assert.True(t, ok, s) - assert.Equal(t, s, s2) + require.True(t, ok, s) + require.Equal(t, s, s2) } for typ, s := range effects.EffectTypeNames { s2, ok := EffectTypeNames[history.EffectType(typ)] - assert.True(t, ok, s) - assert.Equal(t, s, s2) + require.True(t, ok, s) + require.Equal(t, s, s2) } } diff --git a/services/horizon/internal/resourceadapter/operations.go b/services/horizon/internal/resourceadapter/operations.go index 95101fb474..2f995fb395 100644 --- a/services/horizon/internal/resourceadapter/operations.go +++ b/services/horizon/internal/resourceadapter/operations.go @@ -146,6 +146,18 @@ func NewOperation( e := operations.LiquidityPoolWithdraw{Base: base} err = operationRow.UnmarshalDetails(&e) result = e + case xdr.OperationTypeInvokeHostFunction: + e := operations.InvokeHostFunction{Base: base} + err = operationRow.UnmarshalDetails(&e) + result = e + case xdr.OperationTypeExtendFootprintTtl: + e := operations.ExtendFootprintTtl{Base: base} + err = operationRow.UnmarshalDetails(&e) + result = e + case xdr.OperationTypeRestoreFootprint: + e := operations.RestoreFootprint{Base: base} + err = operationRow.UnmarshalDetails(&e) + result = e default: result = base } diff --git a/services/horizon/internal/resourceadapter/root.go b/services/horizon/internal/resourceadapter/root.go index eb2656605d..91a72616ea 100644 --- a/services/horizon/internal/resourceadapter/root.go +++ b/services/horizon/internal/resourceadapter/root.go @@ -46,7 +46,7 @@ func PopulateRoot( dest.Links.AccountTransactions = lb.PagedLink("/accounts/{account_id}/transactions") dest.Links.Assets = lb.Link("/assets{?asset_code,asset_issuer,cursor,limit,order}") dest.Links.Effects = lb.Link("/effects{?cursor,limit,order}") - dest.Links.Ledger = lb.Link("/ledger/{sequence}") + dest.Links.Ledger = lb.Link("/ledgers/{sequence}") dest.Links.Ledgers = lb.Link("/ledgers{?cursor,limit,order}") dest.Links.FeeStats = lb.Link("/fee_stats") dest.Links.Operation = lb.Link("/operations/{id}") diff --git a/services/horizon/internal/scripts/check_release_hash/Dockerfile b/services/horizon/internal/scripts/check_release_hash/Dockerfile index 431f813462..6a054aab34 100644 --- a/services/horizon/internal/scripts/check_release_hash/Dockerfile +++ b/services/horizon/internal/scripts/check_release_hash/Dockerfile @@ -1,5 +1,5 @@ # Change to Go version used in CI or rebuild with --build-arg. -ARG GO_IMAGE=golang:1.18 +ARG GO_IMAGE=golang:1.20-bullseye FROM $GO_IMAGE WORKDIR /go/src/github.com/stellar/go @@ -8,8 +8,8 @@ ENV DEBIAN_FRONTEND=noninteractive # ca-certificates are required to make tls connections RUN apt-get update && apt-get install -y --no-install-recommends ca-certificates curl wget gnupg apt-utils git zip unzip apt-transport-https ca-certificates RUN wget -qO - https://apt.stellar.org/SDF.asc | APT_KEY_DONT_WARN_ON_DANGEROUS_USAGE=true apt-key add - -RUN echo "deb https://apt.stellar.org xenial stable" >/etc/apt/sources.list.d/SDF.list -RUN echo "deb https://apt.stellar.org xenial testing" >/etc/apt/sources.list.d/SDF-testing.list +RUN echo "deb https://apt.stellar.org focal stable" >/etc/apt/sources.list.d/SDF.list +RUN echo "deb https://apt.stellar.org focal testing" >/etc/apt/sources.list.d/SDF-testing.list RUN git clone https://github.com/stellar/go.git /go/src/github.com/stellar/go # Fetch dependencies and prebuild binaries. Not necessary but will make check faster. diff --git a/services/horizon/internal/scripts/check_release_hash/check.sh b/services/horizon/internal/scripts/check_release_hash/check.sh index b1377d9810..c4fba80cd9 100644 --- a/services/horizon/internal/scripts/check_release_hash/check.sh +++ b/services/horizon/internal/scripts/check_release_hash/check.sh @@ -20,6 +20,14 @@ unzip $TAG-windows-amd64.zip cd - +# Since Go 1.18 vcs (git) info is added to the binary. One of the values is: +# vcs.modified which determines if git working dir is clean. We need to +# specifically add the files below to .gitignore to make git ignore them. +touch ~/.gitignore +echo -e "check.sh\n" >> ~/.gitignore +echo -e "released/\n" >> ~/.gitignore +git config --global core.excludesFile '~/.gitignore' + git pull origin --tags git checkout $TAG # -keep: artifact directories are not removed after packaging diff --git a/services/horizon/internal/test/environment.go b/services/horizon/internal/test/environment.go new file mode 100644 index 0000000000..8019c92208 --- /dev/null +++ b/services/horizon/internal/test/environment.go @@ -0,0 +1,65 @@ +package test + +import ( + "fmt" + "os" + "strings" + + "github.com/stellar/go/support/errors" +) + +type EnvironmentManager struct { + oldEnvironment, newEnvironment map[string]string +} + +func NewEnvironmentManager() *EnvironmentManager { + env := &EnvironmentManager{} + env.oldEnvironment = make(map[string]string) + env.newEnvironment = make(map[string]string) + return env +} + +func (envManager *EnvironmentManager) InitializeEnvironmentVariables(environmentVars map[string]string) error { + var env strings.Builder + for key, value := range environmentVars { + env.WriteString(fmt.Sprintf("%s=%s ", key, value)) + } + + // prepare env + for key, value := range environmentVars { + innerErr := envManager.Add(key, value) + if innerErr != nil { + return errors.Wrap(innerErr, fmt.Sprintf( + "failed to set envvar (%s=%s)", key, value)) + } + } + return nil +} + +// Add sets a new environment variable, saving the original value (if any). +func (envManager *EnvironmentManager) Add(key, value string) error { + // If someone pushes an environmental variable more than once, we don't want + // to lose the *original* value, so we're being careful here. + if _, ok := envManager.newEnvironment[key]; !ok { + if oldValue, ok := os.LookupEnv(key); ok { + envManager.oldEnvironment[key] = oldValue + } + } + + envManager.newEnvironment[key] = value + return os.Setenv(key, value) +} + +// Restore restores the environment prior to any modifications. +// +// You should probably use this alongside `defer` to ensure the global +// environment isn't modified for longer than you intend. +func (envManager *EnvironmentManager) Restore() { + for key := range envManager.newEnvironment { + if oldValue, ok := envManager.oldEnvironment[key]; ok { + os.Setenv(key, oldValue) + } else { + os.Unsetenv(key) + } + } +} diff --git a/services/horizon/internal/test/integration/environment.go b/services/horizon/internal/test/integration/environment.go deleted file mode 100644 index 9a3d7c09d2..0000000000 --- a/services/horizon/internal/test/integration/environment.go +++ /dev/null @@ -1,45 +0,0 @@ -//lint:file-ignore U1001 Ignore all unused code, this is only used in tests. -package integration - -import ( - "os" -) - -type EnvironmentManager struct { - oldEnvironment, newEnvironment map[string]string -} - -func NewEnvironmentManager() *EnvironmentManager { - env := &EnvironmentManager{} - env.oldEnvironment = make(map[string]string) - env.newEnvironment = make(map[string]string) - return env -} - -// Add sets a new environment variable, saving the original value (if any). -func (envmgr *EnvironmentManager) Add(key, value string) error { - // If someone pushes an environmental variable more than once, we don't want - // to lose the *original* value, so we're being careful here. - if _, ok := envmgr.newEnvironment[key]; !ok { - if oldValue, ok := os.LookupEnv(key); ok { - envmgr.oldEnvironment[key] = oldValue - } - } - - envmgr.newEnvironment[key] = value - return os.Setenv(key, value) -} - -// Restore restores the environment prior to any modifications. -// -// You should probably use this alongside `defer` to ensure the global -// environment isn't modified for longer than you intend. -func (envmgr *EnvironmentManager) Restore() { - for key := range envmgr.newEnvironment { - if oldValue, ok := envmgr.oldEnvironment[key]; ok { - os.Setenv(key, oldValue) - } else { - os.Unsetenv(key) - } - } -} diff --git a/services/horizon/internal/test/integration/integration.go b/services/horizon/internal/test/integration/integration.go index 99c61bd68d..87718d5a67 100644 --- a/services/horizon/internal/test/integration/integration.go +++ b/services/horizon/internal/test/integration/integration.go @@ -16,15 +16,22 @@ import ( "testing" "time" + "github.com/stellar/go/services/horizon/internal/test" + + "github.com/2opremio/pretty" + "github.com/creachadair/jrpc2" + "github.com/creachadair/jrpc2/jhttp" "github.com/spf13/cobra" - "github.com/stellar/go/services/horizon/internal/ingest" "github.com/stretchr/testify/assert" sdk "github.com/stellar/go/clients/horizonclient" "github.com/stellar/go/clients/stellarcore" + "github.com/stellar/go/ingest/ledgerbackend" "github.com/stellar/go/keypair" proto "github.com/stellar/go/protocols/horizon" horizon "github.com/stellar/go/services/horizon/internal" + "github.com/stellar/go/services/horizon/internal/ingest" + "github.com/stellar/go/support/config" "github.com/stellar/go/support/db/dbtest" "github.com/stellar/go/support/errors" "github.com/stellar/go/txnbuild" @@ -34,21 +41,27 @@ import ( const ( StandaloneNetworkPassphrase = "Standalone Network ; February 2017" stellarCorePostgresPassword = "mysecretpassword" + horizonDefaultPort = "8000" adminPort = 6060 stellarCorePort = 11626 stellarCorePostgresPort = 5641 historyArchivePort = 1570 + sorobanRPCPort = 8080 ) var ( + HorizonInitErrStr = "cannot initialize Horizon" RunWithCaptiveCore = os.Getenv("HORIZON_INTEGRATION_TESTS_ENABLE_CAPTIVE_CORE") != "" + RunWithSorobanRPC = os.Getenv("HORIZON_INTEGRATION_TESTS_ENABLE_SOROBAN_RPC") != "" RunWithCaptiveCoreUseDB = os.Getenv("HORIZON_INTEGRATION_TESTS_CAPTIVE_CORE_USE_DB") != "" ) type Config struct { - ProtocolVersion uint32 - SkipContainerCreation bool - CoreDockerImage string + ProtocolVersion uint32 + EnableSorobanRPC bool + SkipCoreContainerCreation bool + CoreDockerImage string + SorobanRPCDockerImage string // Weird naming here because bools default to false, but we want to start // Horizon by default. @@ -69,9 +82,10 @@ type Config struct { } type CaptiveConfig struct { - binaryPath string - configPath string - useDB bool + binaryPath string + configPath string + storagePath string + useDB bool } type Test struct { @@ -82,7 +96,7 @@ type Test struct { config Config coreConfig CaptiveConfig horizonIngestConfig horizon.Config - environment *EnvironmentManager + environment *test.EnvironmentManager horizonClient *sdk.Client horizonAdminClient *sdk.AdminClient @@ -97,18 +111,14 @@ type Test struct { passPhrase string } -func NewTestForRemoteHorizon(t *testing.T, horizonURL string, passPhrase string, masterKey *keypair.Full) *Test { - adminClient, err := sdk.NewAdminClient(0, "", 0) - if err != nil { - t.Fatal(err) - } - - return &Test{ - t: t, - horizonClient: &sdk.Client{HorizonURL: horizonURL}, - horizonAdminClient: adminClient, - masterKey: masterKey, - passPhrase: passPhrase, +// GetTestConfig returns the default test Config required to run NewTest. +func GetTestConfig() *Config { + return &Config{ + ProtocolVersion: 17, + SkipHorizonStart: true, + SkipCoreContainerCreation: false, + HorizonIngestParameters: map[string]string{}, + HorizonEnvironment: map[string]string{}, } } @@ -133,23 +143,36 @@ func NewTest(t *testing.T, config Config) *Test { config.ProtocolVersion = maxSupportedCoreProtocolFromEnv } } - - composePath := findDockerComposePath() - i := &Test{ - t: t, - config: config, - composePath: composePath, - passPhrase: StandaloneNetworkPassphrase, - environment: NewEnvironmentManager(), + var i *Test + if !config.SkipCoreContainerCreation { + composePath := findDockerComposePath() + i = &Test{ + t: t, + config: config, + composePath: composePath, + passPhrase: StandaloneNetworkPassphrase, + environment: test.NewEnvironmentManager(), + } + i.configureCaptiveCore() + // Only run Stellar Core container and its dependencies. + i.runComposeCommand("up", "--detach", "--quiet-pull", "--no-color", "core") + } else { + i = &Test{ + t: t, + config: config, + environment: test.NewEnvironmentManager(), + } } - i.configureCaptiveCore() - - // Only run Stellar Core container and its dependencies. - i.runComposeCommand("up", "--detach", "--quiet-pull", "--no-color", "core") i.prepareShutdownHandlers() i.coreClient = &stellarcore.Client{URL: "http://localhost:" + strconv.Itoa(stellarCorePort)} - i.waitForCore() + if !config.SkipCoreContainerCreation { + i.waitForCore() + if RunWithSorobanRPC && i.config.EnableSorobanRPC { + i.runComposeCommand("up", "--detach", "--quiet-pull", "--no-color", "soroban-rpc") + i.waitForSorobanRPC() + } + } if !config.SkipHorizonStart { if innerErr := i.StartHorizon(); innerErr != nil { @@ -168,7 +191,12 @@ func (i *Test) configureCaptiveCore() { if RunWithCaptiveCore { composePath := findDockerComposePath() i.coreConfig.binaryPath = os.Getenv("HORIZON_INTEGRATION_TESTS_CAPTIVE_CORE_BIN") - i.coreConfig.configPath = filepath.Join(composePath, "captive-core-integration-tests.cfg") + coreConfigFile := "captive-core-classic-integration-tests.cfg" + if i.config.ProtocolVersion >= ledgerbackend.MinimalSorobanProtocolSupport { + coreConfigFile = "captive-core-integration-tests.cfg" + } + i.coreConfig.configPath = filepath.Join(composePath, coreConfigFile) + i.coreConfig.storagePath = i.CurrentTest().TempDir() if RunWithCaptiveCoreUseDB { i.coreConfig.useDB = true } @@ -201,8 +229,13 @@ func (i *Test) getIngestParameter(argName, envName string) string { // Runs a docker-compose command applied to the above configs func (i *Test) runComposeCommand(args ...string) { integrationYaml := filepath.Join(i.composePath, "docker-compose.integration-tests.yml") + integrationSorobanRPCYaml := filepath.Join(i.composePath, "docker-compose.integration-tests.soroban-rpc.yml") - cmdline := append([]string{"-f", integrationYaml}, args...) + cmdline := args + if RunWithSorobanRPC { + cmdline = append([]string{"-f", integrationSorobanRPCYaml}, cmdline...) + } + cmdline = append([]string{"-f", integrationYaml}, cmdline...) cmd := exec.Command("docker-compose", cmdline...) coreImageOverride := "" if i.config.CoreDockerImage != "" { @@ -210,16 +243,40 @@ func (i *Test) runComposeCommand(args ...string) { } else if img := os.Getenv("HORIZON_INTEGRATION_TESTS_DOCKER_IMG"); img != "" { coreImageOverride = img } + + cmd.Env = os.Environ() if coreImageOverride != "" { cmd.Env = append( - os.Environ(), + cmd.Environ(), fmt.Sprintf("CORE_IMAGE=%s", coreImageOverride), ) } - i.t.Log("Running", cmd.Env, cmd.Args) + sorobanRPCOverride := "" + if i.config.SorobanRPCDockerImage != "" { + sorobanRPCOverride = i.config.CoreDockerImage + } else if img := os.Getenv("HORIZON_INTEGRATION_TESTS_SOROBAN_RPC_DOCKER_IMG"); img != "" { + sorobanRPCOverride = img + } + if sorobanRPCOverride != "" { + cmd.Env = append( + cmd.Environ(), + fmt.Sprintf("SOROBAN_RPC_IMAGE=%s", sorobanRPCOverride), + ) + } + + if i.config.ProtocolVersion < ledgerbackend.MinimalSorobanProtocolSupport { + cmd.Env = append( + cmd.Environ(), + "CORE_CONFIG_FILE=stellar-core-classic-integration-tests.cfg", + ) + } + + i.t.Log("Running", cmd.Args) out, innerErr := cmd.Output() - if exitErr, ok := innerErr.(*exec.ExitError); ok { + if len(out) > 0 { fmt.Printf("stdout:\n%s\n", string(out)) + } + if exitErr, ok := innerErr.(*exec.ExitError); ok { fmt.Printf("stderr:\n%s\n", string(exitErr.Stderr)) } @@ -237,8 +294,14 @@ func (i *Test) prepareShutdownHandlers() { if i.ingestNode != nil { i.ingestNode.Close() } - i.runComposeCommand("rm", "-fvs", "core") - i.runComposeCommand("rm", "-fvs", "core-postgres") + if !i.config.SkipCoreContainerCreation { + i.runComposeCommand("rm", "-fvs", "core") + i.runComposeCommand("rm", "-fvs", "core-postgres") + if os.Getenv("HORIZON_INTEGRATION_TESTS_ENABLE_SOROBAN_RPC") != "" { + i.runComposeCommand("logs", "soroban-rpc") + i.runComposeCommand("rm", "-fvs", "soroban-rpc") + } + } }, i.environment.Restore, ) @@ -284,6 +347,7 @@ func (i *Test) Shutdown() { }) } +// StartHorizon initializes and starts the Horizon client-facing API server and the ingest server. func (i *Test) StartHorizon() error { postgres := dbtest.Postgres(i.t) i.shutdownCalls = append(i.shutdownCalls, func() { @@ -291,8 +355,103 @@ func (i *Test) StartHorizon() error { postgres.Close() }) + // To facilitate custom runs of Horizon, we merge a default set of + // parameters with the tester-supplied ones (if any). + mergedWebArgs := MergeMaps(i.getDefaultWebArgs(postgres), i.config.HorizonWebParameters) + webArgs := mapToFlags(mergedWebArgs) + i.t.Log("Horizon command line webArgs:", webArgs) + + mergedIngestArgs := MergeMaps(i.getDefaultIngestArgs(postgres), i.config.HorizonIngestParameters) + ingestArgs := mapToFlags(mergedIngestArgs) + i.t.Log("Horizon command line ingestArgs:", ingestArgs) + + // setup Horizon web command + var err error webConfig, webConfigOpts := horizon.Flags() + webCmd := i.createWebCommand(webConfig, webConfigOpts) + webCmd.SetArgs(webArgs) + if err = webConfigOpts.Init(webCmd); err != nil { + return errors.Wrap(err, "cannot initialize params") + } + + // setup Horizon ingest command ingestConfig, ingestConfigOpts := horizon.Flags() + ingestCmd := i.createIngestCommand(ingestConfig, ingestConfigOpts) + ingestCmd.SetArgs(ingestArgs) + if err = ingestConfigOpts.Init(ingestCmd); err != nil { + return errors.Wrap(err, "cannot initialize params") + } + + if err = i.initializeEnvironmentVariables(); err != nil { + return err + } + + if err = ingestCmd.Execute(); err != nil { + return errors.Wrap(err, HorizonInitErrStr) + } + + if err = webCmd.Execute(); err != nil { + return errors.Wrap(err, HorizonInitErrStr) + } + + // Set up Horizon clients + i.setupHorizonClient(mergedWebArgs) + if err = i.setupHorizonAdminClient(mergedIngestArgs); err != nil { + return err + } + + i.horizonIngestConfig = *ingestConfig + + i.appStopped = &sync.WaitGroup{} + i.appStopped.Add(2) + go func() { + _ = i.ingestNode.Serve() + i.appStopped.Done() + }() + go func() { + _ = i.webNode.Serve() + i.appStopped.Done() + }() + + return nil +} + +func (i *Test) getDefaultArgs(postgres *dbtest.DB) map[string]string { + // TODO: Ideally, we'd be pulling host/port information from the Docker + // Compose YAML file itself rather than hardcoding it. + return map[string]string{ + "ingest": "false", + "history-archive-urls": fmt.Sprintf("http://%s:%d", "localhost", historyArchivePort), + "db-url": postgres.RO_DSN, + "stellar-core-url": i.coreClient.URL, + "network-passphrase": i.passPhrase, + "apply-migrations": "true", + "port": horizonDefaultPort, + // due to ARTIFICIALLY_ACCELERATE_TIME_FOR_TESTING + "checkpoint-frequency": "8", + "per-hour-rate-limit": "0", // disable rate limiting + "max-db-connections": "50", // the postgres container supports 100 connections, be conservative + } +} + +func (i *Test) getDefaultWebArgs(postgres *dbtest.DB) map[string]string { + return MergeMaps(i.getDefaultArgs(postgres), map[string]string{"admin-port": "0"}) +} + +func (i *Test) getDefaultIngestArgs(postgres *dbtest.DB) map[string]string { + return MergeMaps(i.getDefaultArgs(postgres), map[string]string{ + "admin-port": strconv.Itoa(i.AdminPort()), + "port": "8001", + "db-url": postgres.DSN, + "stellar-core-binary-path": i.coreConfig.binaryPath, + "captive-core-config-path": i.coreConfig.configPath, + "captive-core-http-port": "21626", + "captive-core-use-db": strconv.FormatBool(i.coreConfig.useDB), + "captive-core-storage-path": i.coreConfig.storagePath, + "ingest": "true"}) +} + +func (i *Test) createWebCommand(webConfig *horizon.Config, webConfigOpts config.ConfigOptions) *cobra.Command { webCmd := &cobra.Command{ Use: "horizon", Short: "Client-facing API server for the Stellar network", @@ -307,81 +466,33 @@ func (i *Test) StartHorizon() error { } }, } + return webCmd +} +func (i *Test) createIngestCommand(ingestConfig *horizon.Config, ingestConfigOpts config.ConfigOptions) *cobra.Command { ingestCmd := &cobra.Command{ Use: "horizon", Short: "Ingest of Stellar network", Long: "Ingest of Stellar network.", - Run: func(cmd *cobra.Command, args []string) { + RunE: func(cmd *cobra.Command, args []string) error { var err error i.ingestNode, err = horizon.NewAppFromFlags(ingestConfig, ingestConfigOpts) if err != nil { - // Explicitly exit here as that's how these tests are structured for now. fmt.Println(err) - os.Exit(1) } + return err }, } + return ingestCmd +} - // To facilitate custom runs of Horizon, we merge a default set of - // parameters with the tester-supplied ones (if any). - // - // TODO: Ideally, we'd be pulling host/port information from the Docker - // Compose YAML file itself rather than hardcoding it. - hostname := "localhost" - coreBinaryPath := i.coreConfig.binaryPath - captiveCoreConfigPath := i.coreConfig.configPath - captiveCoreUseDB := strconv.FormatBool(i.coreConfig.useDB) - - defaultArgs := map[string]string{ - "ingest": "false", - "history-archive-urls": fmt.Sprintf("http://%s:%d", hostname, historyArchivePort), - "db-url": postgres.RO_DSN, - "stellar-core-url": i.coreClient.URL, - "network-passphrase": i.passPhrase, - "apply-migrations": "true", - "enable-captive-core-ingestion": "false", - "port": "8000", - // due to ARTIFICIALLY_ACCELERATE_TIME_FOR_TESTING - "checkpoint-frequency": "8", - "per-hour-rate-limit": "0", // disable rate limiting - "max-db-connections": "50", // the postgres container supports 100 connections, be conservative - } - - merged := MergeMaps(defaultArgs, i.config.HorizonWebParameters, map[string]string{"admin-port": "0"}) - webArgs := mapToFlags(merged) - mergedIngest := MergeMaps(defaultArgs, - map[string]string{ - "admin-port": strconv.Itoa(i.AdminPort()), - "port": "8001", - "enable-captive-core-ingestion": strconv.FormatBool(len(coreBinaryPath) > 0), - "db-url": postgres.DSN, - "stellar-core-db-url": fmt.Sprintf( - "postgres://postgres:%s@%s:%d/stellar?sslmode=disable", - stellarCorePostgresPassword, - hostname, - stellarCorePostgresPort, - ), - "stellar-core-binary-path": coreBinaryPath, - "captive-core-config-path": captiveCoreConfigPath, - "captive-core-http-port": "21626", - "captive-core-use-db": captiveCoreUseDB, - "captive-core-storage-path": os.TempDir(), - "ingest": "true"}, - i.config.HorizonIngestParameters) - ingestArgs := mapToFlags(mergedIngest) - - // initialize core arguments - i.t.Log("Horizon command line:", webArgs) +func (i *Test) initializeEnvironmentVariables() error { var env strings.Builder for key, value := range i.config.HorizonEnvironment { env.WriteString(fmt.Sprintf("%s=%s ", key, value)) } i.t.Logf("Horizon environmental variables: %s\n", env.String()) - webCmd.SetArgs(webArgs) - ingestCmd.SetArgs(ingestArgs) - // prepare env for key, value := range i.config.HorizonEnvironment { innerErr := i.environment.Add(key, value) @@ -390,66 +501,56 @@ func (i *Test) StartHorizon() error { "failed to set envvar (%s=%s)", key, value)) } } + return nil +} - var err error - if err = webConfigOpts.Init(webCmd); err != nil { - return errors.Wrap(err, "cannot initialize params") - } - if err = ingestConfigOpts.Init(ingestCmd); err != nil { - return errors.Wrap(err, "cannot initialize params") - } - - if err = ingestCmd.Execute(); err != nil { - return errors.Wrap(err, "cannot initialize Horizon") - } - - if err = webCmd.Execute(); err != nil { - return errors.Wrap(err, "cannot initialize Horizon") - } - - horizonPort := "8000" - if port, ok := merged["port"]; ok { - horizonPort = port - } +func (i *Test) setupHorizonAdminClient(ingestArgs map[string]string) error { adminPort := uint16(i.AdminPort()) - if port, ok := mergedIngest["admin-port"]; ok { + if port, ok := ingestArgs["admin-port"]; ok { if cmdAdminPort, parseErr := strconv.ParseInt(port, 0, 16); parseErr == nil { adminPort = uint16(cmdAdminPort) } } - i.horizonIngestConfig = *ingestConfig - i.horizonClient = &sdk.Client{ - HorizonURL: fmt.Sprintf("http://%s:%s", hostname, horizonPort), - } + + var err error i.horizonAdminClient, err = sdk.NewAdminClient(adminPort, "", 0) if err != nil { return errors.Wrap(err, "cannot initialize Horizon admin client") } + return nil +} - i.appStopped = &sync.WaitGroup{} - i.appStopped.Add(2) - go func() { - i.ingestNode.Serve() - i.appStopped.Done() - }() - go func() { - i.webNode.Serve() - i.appStopped.Done() - }() +func (i *Test) setupHorizonClient(webArgs map[string]string) { + hostname := "localhost" + horizonPort := horizonDefaultPort + if port, ok := webArgs["port"]; ok { + horizonPort = port + } - return nil + i.horizonClient = &sdk.Client{ + HorizonURL: fmt.Sprintf("http://%s:%s", hostname, horizonPort), + } } +const maxWaitForCoreStartup = 30 * time.Second +const maxWaitForCoreUpgrade = 5 * time.Second +const coreStartupPingInterval = time.Second + // Wait for core to be up and manually close the first ledger func (i *Test) waitForCore() { i.t.Log("Waiting for core to be up...") - for t := 30 * time.Second; t >= 0; t -= time.Second { + startTime := time.Now() + for time.Since(startTime) < maxWaitForCoreStartup { ctx, cancel := context.WithTimeout(context.Background(), time.Second) + infoTime := time.Now() _, err := i.coreClient.Info(ctx) cancel() if err != nil { i.t.Logf("could not obtain info response: %v", err) - time.Sleep(time.Second) + // sleep up to a second between consecutive calls. + if durationSince := time.Since(infoTime); durationSince < coreStartupPingInterval { + time.Sleep(coreStartupPingInterval - durationSince) + } continue } break @@ -457,19 +558,250 @@ func (i *Test) waitForCore() { i.UpgradeProtocol(i.config.ProtocolVersion) - for t := 0; t < 5; t++ { + startTime = time.Now() + for time.Since(startTime) < maxWaitForCoreUpgrade { ctx, cancel := context.WithTimeout(context.Background(), time.Second) + infoTime := time.Now() info, err := i.coreClient.Info(ctx) cancel() if err != nil || !info.IsSynced() { i.t.Logf("Core is still not synced: %v %v", err, info) - time.Sleep(time.Second) + // sleep up to a second between consecutive calls. + if durationSince := time.Since(infoTime); durationSince < coreStartupPingInterval { + time.Sleep(coreStartupPingInterval - durationSince) + } continue } i.t.Log("Core is up.") return } - i.t.Fatal("Core could not sync after 30s") + i.t.Fatalf("Core could not sync after %v + %v", maxWaitForCoreStartup, maxWaitForCoreUpgrade) +} + +const sorobanRPCInitTime = 20 * time.Second +const sorobanRPCHealthCheckInterval = time.Second + +// Wait for SorobanRPC to be up +func (i *Test) waitForSorobanRPC() { + i.t.Log("Waiting for Soroban RPC to be up...") + + start := time.Now() + for time.Since(start) < sorobanRPCInitTime { + ctx, cancel := context.WithTimeout(context.Background(), sorobanRPCHealthCheckInterval) + // TODO: soroban-tools should be exporting a proper Go client + ch := jhttp.NewChannel("http://localhost:"+strconv.Itoa(sorobanRPCPort), nil) + sorobanRPCClient := jrpc2.NewClient(ch, nil) + callTime := time.Now() + _, err := sorobanRPCClient.Call(ctx, "getHealth", nil) + cancel() + if err != nil { + i.t.Logf("SorobanRPC is unhealthy: %v", err) + // sleep up to a second between consecutive calls. + if durationSince := time.Since(callTime); durationSince < sorobanRPCHealthCheckInterval { + time.Sleep(sorobanRPCHealthCheckInterval - durationSince) + } + continue + } + i.t.Log("SorobanRPC is up.") + return + } + + i.t.Fatalf("SorobanRPC unhealthy after %v", time.Since(start)) +} + +type RPCSimulateHostFunctionResult struct { + Auth []string `json:"auth"` + XDR string `json:"xdr"` +} + +type RPCSimulateTxResponse struct { + Error string `json:"error,omitempty"` + TransactionData string `json:"transactionData"` + Results []RPCSimulateHostFunctionResult `json:"results"` + MinResourceFee int64 `json:"minResourceFee,string"` +} + +func (i *Test) PreflightHostFunctions( + sourceAccount txnbuild.Account, function txnbuild.InvokeHostFunction, +) (txnbuild.InvokeHostFunction, int64) { + if function.HostFunction.Type == xdr.HostFunctionTypeHostFunctionTypeInvokeContract { + fmt.Printf("Preflighting function call to: %s\n", string(function.HostFunction.InvokeContract.FunctionName)) + } + result, transactionData := i.simulateTransaction(sourceAccount, &function) + function.Ext = xdr.TransactionExt{ + V: 1, + SorobanData: &transactionData, + } + var funAuth []xdr.SorobanAuthorizationEntry + for _, res := range result.Results { + var decodedRes xdr.ScVal + err := xdr.SafeUnmarshalBase64(res.XDR, &decodedRes) + assert.NoError(i.t, err) + fmt.Printf("Result:\n\n%# +v\n\n", pretty.Formatter(decodedRes)) + for _, authBase64 := range res.Auth { + var authEntry xdr.SorobanAuthorizationEntry + err = xdr.SafeUnmarshalBase64(authBase64, &authEntry) + assert.NoError(i.t, err) + fmt.Printf("Auth:\n\n%# +v\n\n", pretty.Formatter(authEntry)) + funAuth = append(funAuth, authEntry) + } + } + function.Auth = funAuth + + return function, result.MinResourceFee +} + +func (i *Test) simulateTransaction( + sourceAccount txnbuild.Account, op txnbuild.Operation, +) (RPCSimulateTxResponse, xdr.SorobanTransactionData) { + // Before preflighting, make sure soroban-rpc is in sync with Horizon + root, err := i.horizonClient.Root() + assert.NoError(i.t, err) + i.syncWithSorobanRPC(uint32(root.HorizonSequence)) + + // TODO: soroban-tools should be exporting a proper Go client + ch := jhttp.NewChannel("http://localhost:"+strconv.Itoa(sorobanRPCPort), nil) + sorobanRPCClient := jrpc2.NewClient(ch, nil) + txParams := GetBaseTransactionParamsWithFee(sourceAccount, txnbuild.MinBaseFee, op) + txParams.IncrementSequenceNum = false + tx, err := txnbuild.NewTransaction(txParams) + assert.NoError(i.t, err) + base64, err := tx.Base64() + assert.NoError(i.t, err) + result := RPCSimulateTxResponse{} + fmt.Printf("Preflight TX:\n\n%v \n\n", base64) + err = sorobanRPCClient.CallResult(context.Background(), "simulateTransaction", struct { + Transaction string `json:"transaction"` + }{base64}, &result) + assert.NoError(i.t, err) + assert.Empty(i.t, result.Error) + var transactionData xdr.SorobanTransactionData + err = xdr.SafeUnmarshalBase64(result.TransactionData, &transactionData) + assert.NoError(i.t, err) + fmt.Printf("Transaction Data:\n\n%# +v\n\n", pretty.Formatter(transactionData)) + return result, transactionData +} + +func (i *Test) syncWithSorobanRPC(ledgerToWaitFor uint32) { + for j := 0; j < 20; j++ { + result := struct { + Sequence uint32 `json:"sequence"` + }{} + ch := jhttp.NewChannel("http://localhost:"+strconv.Itoa(sorobanRPCPort), nil) + sorobanRPCClient := jrpc2.NewClient(ch, nil) + err := sorobanRPCClient.CallResult(context.Background(), "getLatestLedger", nil, &result) + assert.NoError(i.t, err) + if result.Sequence >= ledgerToWaitFor { + return + } + time.Sleep(500 * time.Millisecond) + } + i.t.Fatal("Time out waiting for soroban-rpc to sync") +} + +func (i *Test) WaitUntilLedgerEntryTTL(ledgerKey xdr.LedgerKey) { + ch := jhttp.NewChannel("http://localhost:"+strconv.Itoa(sorobanRPCPort), nil) + client := jrpc2.NewClient(ch, nil) + + keyB64, err := xdr.MarshalBase64(ledgerKey) + assert.NoError(i.t, err) + request := struct { + Keys []string `json:"keys"` + }{ + Keys: []string{keyB64}, + } + ttled := false + for attempt := 0; attempt < 50; attempt++ { + var result struct { + Entries []struct { + LiveUntilLedgerSeq *uint32 `json:"liveUntilLedgerSeq,omitempty"` + } `json:"entries"` + } + err := client.CallResult(context.Background(), "getLedgerEntries", request, &result) + assert.NoError(i.t, err) + if len(result.Entries) > 0 { + liveUntilLedgerSeq := *result.Entries[0].LiveUntilLedgerSeq + + root, err := i.horizonClient.Root() + assert.NoError(i.t, err) + if uint32(root.HorizonSequence) > liveUntilLedgerSeq { + ttled = true + i.t.Logf("ledger entry ttl'ed") + break + } + i.t.Log("waiting for ledger entry to ttl at ledger", liveUntilLedgerSeq) + } else { + i.t.Log("waiting for soroban-rpc to ingest the ledger entries") + } + time.Sleep(time.Second) + } + assert.True(i.t, ttled) +} + +func (i *Test) PreflightExtendExpiration( + account string, ledgerKeys []xdr.LedgerKey, extendAmt uint32, +) (proto.Account, txnbuild.ExtendFootprintTtl, int64) { + sourceAccount, err := i.Client().AccountDetail(sdk.AccountRequest{ + AccountID: account, + }) + assert.NoError(i.t, err) + + bumpFootprint := txnbuild.ExtendFootprintTtl{ + ExtendTo: extendAmt, + SourceAccount: "", + Ext: xdr.TransactionExt{ + V: 1, + SorobanData: &xdr.SorobanTransactionData{ + Ext: xdr.ExtensionPoint{}, + Resources: xdr.SorobanResources{ + Footprint: xdr.LedgerFootprint{ + ReadOnly: ledgerKeys, + ReadWrite: nil, + }, + }, + ResourceFee: 0, + }, + }, + } + result, transactionData := i.simulateTransaction(&sourceAccount, &bumpFootprint) + bumpFootprint.Ext = xdr.TransactionExt{ + V: 1, + SorobanData: &transactionData, + } + + return sourceAccount, bumpFootprint, result.MinResourceFee +} + +func (i *Test) RestoreFootprint( + account string, ledgerKey xdr.LedgerKey, +) (proto.Account, txnbuild.RestoreFootprint, int64) { + sourceAccount, err := i.Client().AccountDetail(sdk.AccountRequest{ + AccountID: account, + }) + assert.NoError(i.t, err) + + restoreFootprint := txnbuild.RestoreFootprint{ + SourceAccount: "", + Ext: xdr.TransactionExt{ + V: 1, + SorobanData: &xdr.SorobanTransactionData{ + Ext: xdr.ExtensionPoint{}, + Resources: xdr.SorobanResources{ + Footprint: xdr.LedgerFootprint{ + ReadWrite: []xdr.LedgerKey{ledgerKey}, + }, + }, + ResourceFee: 0, + }, + }, + } + result, transactionData := i.simulateTransaction(&sourceAccount, &restoreFootprint) + restoreFootprint.Ext = xdr.TransactionExt{ + V: 1, + SorobanData: &transactionData, + } + + return sourceAccount, restoreFootprint, result.MinResourceFee } // UpgradeProtocol arms Core with upgrade and blocks until protocol is upgraded. @@ -528,17 +860,27 @@ func (i *Test) WaitForHorizon() { i.t.Fatal("Horizon not ingesting...") } +// Config returns the testing configuration for the current integration test run. +func (i *Test) Config() Config { + return i.config +} + +// CoreClient returns a stellar core client connected to the Stellar Core instance. +func (i *Test) CoreClient() *stellarcore.Client { + return i.coreClient +} + // Client returns horizon.Client connected to started Horizon instance. func (i *Test) Client() *sdk.Client { return i.horizonClient } -// Client returns horizon.Client connected to started Horizon instance. +// AdminClient returns horizon.Client connected to started Horizon instance. func (i *Test) AdminClient() *sdk.AdminClient { return i.horizonAdminClient } -// Horizon returns the horizon.App instance for the current integration test +// HorizonWeb returns the horizon.App instance for the current integration test func (i *Test) HorizonWeb() *horizon.App { return i.webNode } @@ -557,8 +899,9 @@ func (i *Test) StopHorizon() { } // Wait for Horizon to shut down completely. - i.appStopped.Wait() - + if i.appStopped != nil { + i.appStopped.Wait() + } i.webNode = nil i.ingestNode = nil } @@ -655,6 +998,12 @@ func (i *Test) CreateAccounts(count int, initialBalance string) ([]*keypair.Full return pairs, accounts } +// CreateAccount creates a new account via the master account. +func (i *Test) CreateAccount(initialBalance string) (*keypair.Full, txnbuild.Account) { + kps, accts := i.CreateAccounts(1, initialBalance) + return kps[0], accts[0] +} + // Panics on any error establishing a trustline. func (i *Test) MustEstablishTrustline( truster *keypair.Full, account txnbuild.Account, asset txnbuild.Asset, @@ -732,7 +1081,13 @@ func (i *Test) MustGetAccount(source *keypair.Full) proto.Account { func (i *Test) MustSubmitOperations( source txnbuild.Account, signer *keypair.Full, ops ...txnbuild.Operation, ) proto.Transaction { - tx, err := i.SubmitOperations(source, signer, ops...) + return i.MustSubmitOperationsWithFee(source, signer, txnbuild.MinBaseFee, ops...) +} + +func (i *Test) MustSubmitOperationsWithFee( + source txnbuild.Account, signer *keypair.Full, fee int64, ops ...txnbuild.Operation, +) proto.Transaction { + tx, err := i.SubmitOperationsWithFee(source, signer, fee, ops...) panicIf(err) return tx } @@ -746,7 +1101,19 @@ func (i *Test) SubmitOperations( func (i *Test) SubmitMultiSigOperations( source txnbuild.Account, signers []*keypair.Full, ops ...txnbuild.Operation, ) (proto.Transaction, error) { - tx, err := i.CreateSignedTransactionFromOps(source, signers, ops...) + return i.SubmitMultiSigOperationsWithFee(source, signers, txnbuild.MinBaseFee, ops...) +} + +func (i *Test) SubmitOperationsWithFee( + source txnbuild.Account, signer *keypair.Full, fee int64, ops ...txnbuild.Operation, +) (proto.Transaction, error) { + return i.SubmitMultiSigOperationsWithFee(source, []*keypair.Full{signer}, fee, ops...) +} + +func (i *Test) SubmitMultiSigOperationsWithFee( + source txnbuild.Account, signers []*keypair.Full, fee int64, ops ...txnbuild.Operation, +) (proto.Transaction, error) { + tx, err := i.CreateSignedTransactionFromOpsWithFee(source, signers, fee, ops...) if err != nil { return proto.Transaction{}, err } @@ -812,15 +1179,31 @@ func (i *Test) CreateSignedTransaction(signers []*keypair.Full, txParams txnbuil func (i *Test) CreateSignedTransactionFromOps( source txnbuild.Account, signers []*keypair.Full, ops ...txnbuild.Operation, ) (*txnbuild.Transaction, error) { - txParams := txnbuild.TransactionParams{ + return i.CreateSignedTransactionFromOpsWithFee(source, signers, txnbuild.MinBaseFee, ops...) +} + +func (i *Test) CreateSignedTransactionFromOpsWithFee( + source txnbuild.Account, signers []*keypair.Full, fee int64, ops ...txnbuild.Operation, +) (*txnbuild.Transaction, error) { + txParams := GetBaseTransactionParamsWithFee(source, fee, ops...) + return i.CreateSignedTransaction(signers, txParams) +} + +func GetBaseTransactionParamsWithFee(source txnbuild.Account, fee int64, ops ...txnbuild.Operation) txnbuild.TransactionParams { + return txnbuild.TransactionParams{ SourceAccount: source, Operations: ops, - BaseFee: txnbuild.MinBaseFee, + BaseFee: fee, Preconditions: txnbuild.Preconditions{TimeBounds: txnbuild.NewInfiniteTimeout()}, IncrementSequenceNum: true, } +} - return i.CreateSignedTransaction(signers, txParams) +func (i *Test) CreateUnsignedTransaction( + source txnbuild.Account, ops ...txnbuild.Operation, +) (*txnbuild.Transaction, error) { + txParams := GetBaseTransactionParamsWithFee(source, txnbuild.MinBaseFee, ops...) + return txnbuild.NewTransaction(txParams) } func (i *Test) GetCurrentCoreLedgerSequence() (int, error) { @@ -846,7 +1229,7 @@ func (i *Test) LogFailedTx(txResponse proto.Transaction, horizonResult error) { var txResult xdr.TransactionResult err := xdr.SafeUnmarshalBase64(txResponse.ResultXdr, &txResult) - assert.NoErrorf(t, err, "Unmarshalling transaction failed.") + assert.NoErrorf(t, err, "Unmarshaling transaction failed.") assert.Equalf(t, xdr.TransactionResultCodeTxSuccess, txResult.Result.Code, "Transaction did not succeed: %d", txResult.Result.Code) } diff --git a/services/horizon/internal/test/scenarios/account_merge-horizon.sql b/services/horizon/internal/test/scenarios/account_merge-horizon.sql index 220c927f7d..7afc2cf440 100644 --- a/services/horizon/internal/test/scenarios/account_merge-horizon.sql +++ b/services/horizon/internal/test/scenarios/account_merge-horizon.sql @@ -357,7 +357,8 @@ CREATE TABLE history_operations ( application_order integer NOT NULL, type integer NOT NULL, details jsonb, - source_account character varying(64) DEFAULT ''::character varying NOT NULL + source_account character varying(64) DEFAULT ''::character varying NOT NULL, + is_payment boolean ); @@ -579,9 +580,9 @@ SELECT pg_catalog.setval('history_operation_participants_id_seq', 6, true); -- Data for Name: history_operations; Type: TABLE DATA; Schema: public; Owner: - -- -INSERT INTO history_operations VALUES (12884905985, 12884905984, 1, 8, '{"into": "GA5WBPYA5Y4WAEHXWR2UKO2UO4BUGHUQ74EUPKON2QHV4WRHOIRNKKH2", "account": "GCXKG6RN4ONIEPCMNFB732A436Z5PNDSRLGWK7GBLCMQLIFO4S7EYWVU"}', 'GCXKG6RN4ONIEPCMNFB732A436Z5PNDSRLGWK7GBLCMQLIFO4S7EYWVU'); -INSERT INTO history_operations VALUES (8589938689, 8589938688, 1, 0, '{"funder": "GBRPYHIL2CI3FNQ4BXLFMNDLFJUNPU2HY3ZMFSHONUCEOASW7QC7OX2H", "account": "GCXKG6RN4ONIEPCMNFB732A436Z5PNDSRLGWK7GBLCMQLIFO4S7EYWVU", "starting_balance": "1000.0000000"}', 'GBRPYHIL2CI3FNQ4BXLFMNDLFJUNPU2HY3ZMFSHONUCEOASW7QC7OX2H'); -INSERT INTO history_operations VALUES (8589942785, 8589942784, 1, 0, '{"funder": "GBRPYHIL2CI3FNQ4BXLFMNDLFJUNPU2HY3ZMFSHONUCEOASW7QC7OX2H", "account": "GA5WBPYA5Y4WAEHXWR2UKO2UO4BUGHUQ74EUPKON2QHV4WRHOIRNKKH2", "starting_balance": "1000.0000000"}', 'GBRPYHIL2CI3FNQ4BXLFMNDLFJUNPU2HY3ZMFSHONUCEOASW7QC7OX2H'); +INSERT INTO history_operations VALUES (12884905985, 12884905984, 1, 8, '{"into": "GA5WBPYA5Y4WAEHXWR2UKO2UO4BUGHUQ74EUPKON2QHV4WRHOIRNKKH2", "account": "GCXKG6RN4ONIEPCMNFB732A436Z5PNDSRLGWK7GBLCMQLIFO4S7EYWVU"}', 'GCXKG6RN4ONIEPCMNFB732A436Z5PNDSRLGWK7GBLCMQLIFO4S7EYWVU', true); +INSERT INTO history_operations VALUES (8589938689, 8589938688, 1, 0, '{"funder": "GBRPYHIL2CI3FNQ4BXLFMNDLFJUNPU2HY3ZMFSHONUCEOASW7QC7OX2H", "account": "GCXKG6RN4ONIEPCMNFB732A436Z5PNDSRLGWK7GBLCMQLIFO4S7EYWVU", "starting_balance": "1000.0000000"}', 'GBRPYHIL2CI3FNQ4BXLFMNDLFJUNPU2HY3ZMFSHONUCEOASW7QC7OX2H', true); +INSERT INTO history_operations VALUES (8589942785, 8589942784, 1, 0, '{"funder": "GBRPYHIL2CI3FNQ4BXLFMNDLFJUNPU2HY3ZMFSHONUCEOASW7QC7OX2H", "account": "GA5WBPYA5Y4WAEHXWR2UKO2UO4BUGHUQ74EUPKON2QHV4WRHOIRNKKH2", "starting_balance": "1000.0000000"}', 'GBRPYHIL2CI3FNQ4BXLFMNDLFJUNPU2HY3ZMFSHONUCEOASW7QC7OX2H', true); -- diff --git a/services/horizon/internal/test/scenarios/base-horizon.sql b/services/horizon/internal/test/scenarios/base-horizon.sql index c7d09da040..95637fa88e 100644 --- a/services/horizon/internal/test/scenarios/base-horizon.sql +++ b/services/horizon/internal/test/scenarios/base-horizon.sql @@ -488,6 +488,7 @@ ALTER SEQUENCE history_operation_participants_id_seq OWNED BY history_operation_ -- -- Name: history_operations; Type: TABLE; Schema: public; Owner: - -- +-- added is_payment=false default to schema, rather than change insert lines CREATE TABLE history_operations ( id bigint NOT NULL, @@ -495,7 +496,8 @@ CREATE TABLE history_operations ( application_order integer NOT NULL, type integer NOT NULL, details jsonb, - source_account character varying(64) DEFAULT ''::character varying NOT NULL + source_account character varying(64) DEFAULT ''::character varying NOT NULL, + is_payment boolean default false ); diff --git a/services/horizon/internal/test/scenarios/bindata.go b/services/horizon/internal/test/scenarios/bindata.go index ad319285e8..81fff1ae09 100644 --- a/services/horizon/internal/test/scenarios/bindata.go +++ b/services/horizon/internal/test/scenarios/bindata.go @@ -1,27 +1,27 @@ // Code generated by go-bindata. DO NOT EDIT. // sources: // account_merge-core.sql (26.849kB) -// account_merge-horizon.sql (36.967kB) +// account_merge-horizon.sql (37.009kB) // base-core.sql (29.682kB) -// base-horizon.sql (62.267kB) +// base-horizon.sql (62.382kB) // failed_transactions-core.sql (38.723kB) -// failed_transactions-horizon.sql (61.962kB) +// failed_transactions-horizon.sql (62.077kB) // ingest_asset_stats-core.sql (61.38kB) -// ingest_asset_stats-horizon.sql (88.329kB) +// ingest_asset_stats-horizon.sql (88.443kB) // kahuna-core.sql (232.639kB) -// kahuna-horizon.sql (323.101kB) +// kahuna-horizon.sql (323.216kB) // offer_ids-core.sql (61.677kB) -// offer_ids-horizon.sql (86.231kB) +// offer_ids-horizon.sql (86.345kB) // operation_fee_stats_1-core.sql (48.276kB) -// operation_fee_stats_1-horizon.sql (66.24kB) +// operation_fee_stats_1-horizon.sql (66.355kB) // operation_fee_stats_2-core.sql (26.671kB) -// operation_fee_stats_2-horizon.sql (32.237kB) +// operation_fee_stats_2-horizon.sql (32.352kB) // operation_fee_stats_3-core.sql (45.051kB) -// operation_fee_stats_3-horizon.sql (58.999kB) +// operation_fee_stats_3-horizon.sql (59.114kB) // pathed_payment-core.sql (52.308kB) -// pathed_payment-horizon.sql (76.986kB) +// pathed_payment-horizon.sql (77.101kB) // paths_strict_send-core.sql (70.821kB) -// paths_strict_send-horizon.sql (93.747kB) +// paths_strict_send-horizon.sql (93.862kB) package scenarios @@ -110,7 +110,7 @@ func account_mergeCoreSql() (*asset, error) { return a, nil } -var _account_mergeHorizonSql = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xd4\x5d\x79\x6f\xe2\x48\xd3\xff\x7f\x3e\x85\x35\x5a\x29\x33\x4a\x66\xe2\xdb\x38\xf3\xcc\x4a\x06\xcc\x11\xc0\xdc\x81\x64\xb5\xb2\x7c\xb4\xc1\x89\xb1\x89\x6d\x12\xc8\xea\xf9\xee\xaf\x7c\x81\x6d\x7c\x02\x33\xfb\xbc\x28\x8a\x00\x57\x57\xfd\xaa\xba\xba\xab\xab\xbb\xe9\xfe\xf6\xed\xd3\xb7\x6f\xd0\xc0\xb0\xec\x85\x09\xc6\xc3\x2e\x24\x0b\xb6\x20\x0a\x16\x80\xe4\xcd\x6a\xfd\xe9\xdb\xb7\x4f\xce\xf3\xfa\x66\xb5\x06\x32\xa4\x98\xc6\xea\x40\xf0\x06\x4c\x4b\x35\x74\x88\xfe\x4e\x7e\x47\x42\x54\xe2\x0e\x5a\x2f\x78\xa7\x78\x8c\xe4\xd3\x98\x9d\x40\x96\x2d\xd8\x60\x05\x74\x9b\xb7\xd5\x15\x30\x36\x36\xf4\x13\x82\x7f\xb8\x8f\x34\x43\x7a\x39\xfe\x56\xd2\x54\x87\x1a\xe8\x92\x21\xab\xfa\x02\xfa\x09\x5d\x4d\x27\x8d\xca\xd5\x8f\x80\x9d\x2e\x0b\xa6\xcc\x4b\x86\xae\x18\xe6\x4a\xd5\x17\xbc\x65\x9b\xaa\xbe\xb0\xa0\x9f\x90\xa1\xfb\x3c\x96\x40\x7a\xe1\x95\x8d\x2e\xd9\xaa\xa1\xf3\xa2\x21\xab\xc0\x79\xae\x08\x9a\x05\x22\x62\x56\xaa\xce\xaf\x80\x65\x09\x0b\x97\xe0\x5d\x30\x75\x55\x5f\xfc\xf0\xb1\x03\xc1\x94\x96\xfc\x5a\xb0\x97\xd0\x4f\x68\xbd\x11\x35\x55\xba\x71\x94\x95\x04\x5b\xd0\x0c\x87\x8c\xe9\x4e\xd8\x11\x34\x61\xaa\x5d\x16\x6a\x37\x20\x76\xde\x1e\x4f\xc6\x50\x9f\xeb\x3e\xfa\xf4\xdf\x97\xaa\x65\x1b\xe6\x8e\xb7\x4d\x41\x06\x16\x54\x1f\xf5\x07\x50\xad\xcf\x8d\x27\x23\xa6\xcd\x4d\x42\x85\xa2\x84\xbc\x64\x6c\x74\x1b\x98\xbc\x60\x59\xc0\xe6\x55\x99\x57\x5e\xc0\xee\xc7\xef\x10\x28\xb9\xef\x7e\x87\x48\xc7\xaf\x7e\x9f\x82\x9e\xb4\xf2\xda\x79\x00\x1d\x47\xce\x12\x16\xa2\x3a\x30\x77\xc9\xdb\x5c\x9d\x9d\x87\x28\x7d\xb6\x2e\x2a\x1e\x28\x0a\x90\x6c\x8b\x17\x77\xbc\x61\xca\xc0\xe4\x45\xc3\x78\xc9\x2e\xa8\xea\x32\xd8\xf2\x21\xe5\x74\x4b\x70\x1d\xdd\xe2\x0d\x9d\x57\xe5\x32\xa5\x8d\x35\x30\x85\x7d\x59\x7b\xb7\x06\x67\x94\x3e\x20\x39\x0b\x45\xb9\xb2\x1a\x90\x17\xc0\x74\x0b\x5a\xe0\x75\x03\x74\xa9\x94\x0a\xa1\xe2\x6b\x13\xbc\xa9\xc6\xc6\xf2\xbf\xe3\x97\x82\xb5\x3c\x91\xd5\xf9\x1c\xd4\xd5\xda\x30\x9d\xe6\xe8\xf7\xa9\xa7\xb2\x39\xd5\x96\x92\x66\x58\x40\xe6\x05\xbb\x4c\xf9\xc0\x99\x4f\x70\x25\xbf\x5d\x9e\x00\x3a\x5c\x52\x90\x65\x13\x58\x56\x76\xf1\xa5\x6d\xca\x6e\xdc\xe1\x35\xc3\x78\xd9\xac\x0b\x50\xaf\xf3\x20\x79\x54\x82\x6a\x96\x64\x1c\x74\xba\x85\x0b\x38\xfd\x84\xa2\x00\xb3\x18\x69\xc0\xfe\x84\x22\xbe\x59\x8b\x15\x72\xbb\xd6\x12\x42\xc2\x5d\x71\x5e\x89\xb5\x53\x60\x69\xe7\xd6\x80\x15\xe9\x80\xc4\x5d\xae\x1b\x2d\xf7\x2d\xbd\x08\xb1\xe1\xe1\x30\x72\x09\x55\xcb\xe6\xed\x2d\xbf\xce\x67\xe9\x50\x1a\xeb\xa2\x94\xa0\x28\x59\x10\x4a\xb2\x89\xc5\xa0\xb9\xe7\x92\xe5\xf7\x62\xe2\xae\x58\x65\x7a\x31\xd2\xb1\xb6\x65\x6d\xf2\x24\xef\x89\x25\x43\x06\x25\xc7\x05\x7b\x37\x58\x0b\xa6\xad\x4a\xea\x5a\xd0\x33\x83\x77\x5e\x51\x7e\x5d\x72\x6c\xb2\x8f\x68\x65\x11\x24\x17\x2c\x2d\xdf\x35\x5e\x11\x79\x1e\xe1\x2f\xe7\xef\x55\xa6\x53\x93\xfe\x5b\x27\x3e\x04\x43\x3f\xd7\x19\xf8\x82\x08\x16\x86\xb9\xe6\x57\xea\xc2\x1f\x30\x64\x40\x88\x51\x16\xd6\xb1\xfc\x78\x2f\x8b\x73\x51\xe7\xf4\x4a\xd7\xfa\xdd\x69\x8f\x83\x54\xd9\x93\x5c\x67\x1b\xcc\xb4\x3b\x29\xc8\x3b\xc5\xe9\x2e\xc0\xd9\xaf\xee\x6c\x4e\xee\xa7\xe2\xea\x07\x51\x7a\xcc\x0e\xa7\x2c\x57\x3b\xc1\x66\xce\x38\xdb\x02\xaf\xa5\x25\x47\x98\x14\x2e\x2d\x83\x82\xb4\x87\xd1\x6c\x61\x0d\x53\x5a\x7d\x19\xfd\x92\x59\x14\x2b\xeb\x8f\xfb\x8a\x11\xfb\x83\xbc\xc2\xba\xf9\x3d\x40\x19\x5d\xbc\x22\x05\x69\xfd\xe1\x5f\x71\x3c\xc1\x78\xb1\x08\xa2\x58\x1f\x92\x4d\x1c\xea\x12\x7c\x42\xa6\xd9\x1c\xb1\x4d\x66\x92\x40\xbc\x52\x9d\x8c\x43\x95\xc0\x17\x7d\xb3\x02\xa6\x2a\xfd\xf5\xf7\xd7\x02\xa5\x84\xed\x09\xa5\x34\xc1\xb2\xbf\x08\xfa\x0e\x68\xee\x54\x4c\x81\x12\x8a\x6a\x26\x16\x69\x4c\xb9\xda\xa4\xdd\xe7\x32\xf4\xe1\x85\xc5\xe2\x80\xee\x06\x3a\x02\x9a\xc1\x23\xd0\xee\x0c\x1e\x8e\xae\x6e\xf1\x03\xf8\x1b\xa8\x8c\x22\xae\xea\x05\x38\xb0\xf3\x09\xcb\x8d\x63\x2c\xb4\xf5\xc2\x7a\xd5\x02\x5f\xac\xb5\xd8\x1e\x73\x24\xe1\xc7\x27\x6f\x16\x8e\x13\x56\xe0\x2e\xf8\x0e\x9a\xec\xd6\xe0\xce\x2f\xf2\x03\x1a\x4b\x4b\xb0\x12\xee\xa0\x6f\x3f\xa0\xfe\xbb\x0e\xcc\x3b\xe8\x9b\x3b\x39\x57\x1b\xb1\x4e\x7d\xf9\x9c\x03\x7e\x9f\x22\x1c\xa3\x0f\x7d\xc6\xb5\x7e\xaf\xc7\x72\x93\x0c\xce\x1e\x01\xd4\xe7\xa2\x0c\xa0\xf6\x18\xba\x0a\xa6\xdd\x82\xef\x2c\x97\xc9\x55\x5c\x72\xa0\xbe\x2f\x73\x6f\xa1\x5c\x7d\x22\xb6\xe4\xfa\x93\x98\x3d\xa1\x59\x7b\xd2\xda\xc3\x0a\xcf\xbf\x45\xc4\x1f\xb8\xc4\x80\x94\x51\xfe\x88\x89\x6b\x80\x41\xf7\x76\xbd\x18\x0f\xbb\xd0\xda\x34\x24\x20\x6f\x4c\x41\x83\x34\x41\x5f\x6c\x84\x05\x70\xcd\x50\x70\xbe\x30\x0c\x37\xdf\xd1\x7c\xf8\x81\xaf\x1e\xf0\x07\x75\x9b\x64\xcb\xbd\x67\xe7\xf2\x87\x46\xec\x64\x3a\xe2\xc6\xa1\xef\x3e\x41\x10\x04\x75\x19\xae\x39\x65\x9a\x2c\xe4\x6a\xdf\xeb\x4d\xbd\xfe\x6e\x3c\x19\xb5\x6b\x13\x97\x82\x19\x43\x7f\xf0\x7f\x40\x63\xb6\xcb\xd6\x26\xd0\x1f\x88\xf3\x29\x5e\x1b\xb9\x0d\xf1\x3c\xed\xf2\xd8\x5f\x4c\x39\x34\x49\xb9\x22\x3d\xd5\x79\xfa\x15\x90\xb0\x57\x71\xff\xd5\x49\x1a\x7e\xf9\x04\x41\x35\x66\xcc\x42\xb3\x16\xcb\x41\x7f\x20\x7f\x21\x7f\xdf\xfe\x81\xfc\x85\xfe\xfd\xe7\x1f\xa8\xfb\x1e\xfd\x0b\xfd\x1b\x9a\x78\x0f\x21\xb6\x3b\x66\x1d\xa3\xb0\x5c\xfd\x6b\xa2\x65\x0a\xc4\x81\x33\x2d\x93\x2f\xe1\x57\x5b\xe6\x3f\xa7\x58\xe6\x38\xa6\xfa\x76\xd8\xc7\xe1\x62\x86\x38\x84\xed\x23\x8e\x2e\x62\x08\x1a\x3b\xb6\x82\x7e\x1e\x7a\x80\x1b\xef\xeb\xc9\xe3\x80\x85\x7e\x86\x5b\xc4\xd7\xa4\x56\x7b\x51\x8c\x71\x86\x31\x88\x41\x33\x2e\x8e\x30\x71\x08\x74\x2e\xca\x24\xa6\x31\xa4\x91\x06\x19\x85\x7b\xf0\xb2\x63\xb4\x49\xc3\xbc\xb3\xd1\x26\x30\x8d\xa3\x0d\x37\x92\x4c\xb4\x4e\xe4\x92\x81\x22\x6c\x34\x9b\xb7\x05\x51\x03\xd6\x5a\x90\x00\xf4\x13\xba\xba\xfa\x11\x7d\xfa\xae\xda\x4b\xde\x50\xe5\xd0\x52\x5a\x44\xd7\xf0\xf8\xd7\x57\xd1\x6d\x60\xc5\xd4\xf3\xda\x62\x38\xf9\xf6\x34\x52\x65\x48\x54\x17\xaa\x6e\xbb\x03\x03\x6e\xda\xed\x7a\xea\x08\x2b\x67\x18\x0f\x49\x4b\xc1\x14\x24\x1b\x98\xd0\x9b\x60\xee\x54\x7d\x11\x23\xd3\x37\xab\xfd\x90\x1f\x52\x75\x1b\x2c\x80\x19\x23\x51\x34\x61\x61\x41\xd6\x4a\xd0\xb4\x63\x31\xb6\xb1\xd2\x8e\x85\x7c\x41\x09\xe2\xeb\x9e\xf2\xb8\xda\xe3\x79\xc3\xa9\xe6\x88\xcf\x76\xec\x4d\x62\x83\xed\x91\x41\xd6\x6b\x4d\x75\xe7\xec\x21\x5b\x5d\x01\xcb\x16\x56\x6b\xc8\xa9\x33\xf7\x23\xf4\x61\xe8\xe0\x18\x68\x5a\x56\x14\x8c\x47\xfd\x74\xaa\x18\xe6\x7d\xf2\x95\xc2\xd5\x77\x43\x66\x34\xf1\x46\x74\x88\xfb\x45\x9b\xab\x8d\x58\x77\xf8\x55\x7d\xf4\xbf\xe2\xfa\x50\xaf\xcd\x3d\x30\xdd\x29\xbb\xff\xcc\xcc\x0f\x9f\x6b\x4c\xad\xc5\x42\x48\x9e\x32\x27\x9b\x3d\xce\xe8\xc8\x15\xfd\x49\x0f\x48\x07\x5b\xfb\x4d\xd0\xbe\x5c\xa5\x68\x7c\x75\x77\x67\x82\x85\xa4\x09\x96\xf5\x35\x5e\x5d\xde\x5a\x45\x82\x6f\x91\xf8\xd7\x8c\x8a\xf2\x72\xe3\xb3\x35\xf3\x66\x74\xf6\x7a\x25\xb7\x8c\xc3\x5c\x5d\x32\xcc\x44\x72\xc9\x90\x93\xc8\x11\x34\x99\xdc\x9b\xfe\x4b\x28\x40\x90\x59\x2d\x2c\x79\x7a\xe1\x42\x6e\x1b\xe6\xf9\xdb\x9c\x36\x4b\x11\xa8\x3f\xe3\xd8\x3a\x54\x7d\xcc\xd1\xc8\x9b\xa1\xcb\x56\x68\xcf\x2b\xf6\xf8\xbb\x2a\xa7\x61\x0b\xe6\x7c\xce\xf5\x3a\x9f\x8f\xef\x76\xb1\x36\xc3\xa7\xf5\xf4\xc7\x53\x5c\x69\x94\x9f\xdd\x85\x8f\xcf\x29\xde\xec\xfa\x71\xf2\x23\x19\xd8\x82\xaa\x59\xd0\xb3\x65\xe8\x62\xba\xb3\x05\x13\x65\xe7\xda\xc1\xe7\xe3\xdb\x21\x58\xb7\x4e\xc1\x16\x5a\x4c\x2e\xd4\x0a\x93\xd6\xb1\x93\x0b\xfa\x66\x09\xcd\x8c\xba\x15\xb1\xc7\x11\xf4\x72\x70\x4c\xc2\xa1\x22\x8a\xd1\xef\x17\x93\x63\x81\xc9\xd8\xd8\x87\xd8\x14\x2f\x63\x02\xc1\xce\x2d\xe4\xd1\x6e\xd6\x72\x61\xda\xbd\xeb\xf8\x1f\x63\xeb\xec\x47\xba\x20\x47\xe3\x01\x5b\xd0\x78\xc9\x50\x75\x2b\xd9\x07\x15\x00\xf8\xb5\x61\x68\xc9\x4f\xdd\x95\x4f\x05\xa4\xd5\xb5\xfb\xd8\x04\x16\x30\xdf\xd2\x48\x9c\x71\xa8\xbd\xe5\xdd\x61\x92\xfa\x91\x46\xb5\x36\x0d\xdb\x90\x0c\x2d\x55\xaf\x78\x1d\x05\xce\x02\x04\x19\x98\xee\xf0\xc2\xfb\xde\xda\x48\x12\xb0\x2c\x65\xa3\xf1\xa9\x8e\xe2\x2b\x2e\xa8\x1a\x90\xd3\xa9\xd2\x9b\x55\xca\xdc\xf5\xb9\xad\x2c\x65\x3d\x24\x27\xe6\x15\xef\x6d\xf2\xfb\xaf\xb2\x2a\x5f\x36\x8c\x65\xca\xf8\x5d\x61\xad\x94\xa2\x67\x86\xb9\x4c\x59\xc7\x61\x2f\x99\x3c\x23\x0c\x86\x56\x76\x2e\xe6\x9b\x79\x69\x4e\x74\x57\x55\x4a\x2a\xe4\x8c\xfc\x25\x4f\x15\x37\x02\x9e\x19\x00\xfd\x96\x6f\x6c\x4c\x69\xbf\x4d\x23\x25\xf4\x04\xdd\xc9\xd5\xd5\xdd\x5d\x7a\x2a\x96\xde\x0e\xfc\x85\xb5\x73\xcd\xe9\xef\x05\xfc\x72\xd1\xf1\x82\xdf\x25\x9e\x12\xbd\xdc\xbd\x30\xa9\x62\x63\x3b\x11\xb3\x88\xfc\xcd\x91\x59\x24\x5e\x1e\x9c\x48\x70\xbc\xa7\x33\x87\x2e\x53\xdc\x9e\x2a\x43\xa2\x0b\x49\xb5\x78\x0b\x68\x1a\x30\x21\xd1\x30\x34\x20\xe8\x41\x4c\x52\x25\xc0\xeb\x91\xf8\xeb\x7d\x17\x8d\xc9\x87\xdd\x44\x7c\x2c\x5a\x47\xf6\x33\xc5\x1f\x9a\xc6\x46\x97\xdd\x0d\xc1\x9a\xba\x5e\x0b\x0b\x70\xcc\x54\xb5\x78\xb0\x15\x24\x3b\x8a\x2b\xb4\xbe\x9f\xb8\x65\xd4\x55\x97\x77\x37\x15\x43\xb5\x16\x5b\xeb\x40\x5f\xbe\x84\x4d\xff\x27\x04\x7f\xfd\x9a\xc7\x2a\xa9\x78\x60\xed\xff\x1c\x55\x40\x01\x7e\x91\xca\x88\xb1\x8f\xd5\x94\x0b\x30\xb3\x0d\x26\x2f\x8d\x5f\xa0\x55\x26\x6f\x76\x28\x18\x82\x8b\xf4\x7d\xe7\x04\xe1\xbc\x8d\x05\x97\x09\xc3\x39\x52\x7e\x57\x20\x2e\xa9\xec\x99\xa1\x38\x47\xda\x71\x30\x4e\x2b\x90\x11\x8e\x23\x9b\x49\x2e\xe8\xab\x81\x7f\x86\x21\x15\xce\xbe\xfc\xa0\x91\x93\xd3\x15\x8d\xd8\xd9\xc1\x37\x91\xf6\x20\x3a\xb1\xbd\x38\xe9\x43\x7a\xfe\x91\x96\xd9\xfd\x2b\xb9\x99\xbd\xe5\x81\xfe\x06\x34\x63\x0d\x92\xe6\x3b\xed\xad\x93\x29\x6d\x34\x3b\xe5\xe1\x0a\xd8\x42\xca\x23\x27\x47\x4b\x7b\x6c\xa9\x0b\x5d\xb0\x37\x26\x48\x9a\x9a\xa3\xc9\xaf\x7f\xfd\x7d\x18\xf4\xfc\xf3\xdf\xa4\x61\xcf\x5f\x7f\xc7\x6d\x0e\x56\x46\xca\x2c\xda\x81\x97\x6e\xe8\x20\x73\x10\x75\xe0\x75\xcc\xc6\xd7\x4c\x5d\x01\x5e\x74\xc2\xa0\x3b\xd5\x5d\x31\x05\x7d\x01\x22\x6e\x99\xfc\x70\xa5\xea\x7c\x8a\xf7\xa4\x13\xf0\xf1\x08\x9b\x48\xe4\xcb\x5d\x08\xeb\x08\x2d\xd8\xda\xa6\xc0\x3b\xa6\x06\xa6\xe5\xd6\xc2\x5f\x7f\xc7\xf3\xcd\x68\x90\x76\xaa\xcc\x51\x7b\x01\xe4\xfc\x84\xd2\x9f\xdd\x54\xe5\xa0\x5b\x08\x36\xa9\x15\xe9\xcb\xbc\x7e\xc1\xdd\x11\x98\xb3\xff\x6d\xcc\x4e\x32\x66\x82\xc3\x73\x6e\xe1\x79\xe0\x72\x99\xd2\xe5\x94\x28\xb8\x3d\x30\x53\xa9\xcc\x0c\xab\x88\x92\xa9\x43\x82\x8b\xa9\x59\x78\x87\x65\xa6\xa2\x39\xf1\x2b\x59\xd5\xba\x60\x0b\x90\x62\x98\x39\xeb\x61\x50\x9d\x99\x30\x39\xea\xa5\xb0\xcc\x5a\x57\x2a\xc2\xb6\xcd\x8d\xd9\xd1\x04\x6a\x73\x93\xfe\xd1\xda\x92\x3b\x92\x18\x43\x5f\xae\x10\x5e\xd5\x55\x5b\x15\x34\xde\xdb\xe7\xf3\xdd\x7a\xd5\xae\x6e\xa0\x2b\x14\x46\xe8\x6f\x30\xf9\x0d\xc6\x20\xa4\x72\x87\x56\xee\x70\xea\x3b\x8c\xa1\x38\x4d\x5e\xc3\xe8\xd5\xd7\x1f\xc5\xb8\xa3\xbc\xf7\xfb\x8d\x88\x55\xc5\x1d\x6f\x1b\xaa\x9c\x2d\x89\x26\x09\xaa\x8c\x24\x8c\xdf\x58\xe0\xd0\x15\xa9\xfa\xd1\x6f\x46\x32\xe5\xe1\x38\x8c\x57\xca\xc8\xc3\x79\x41\x96\xf9\xf8\xcc\x5b\xa6\x0c\x02\x27\x30\xb4\x8c\x0c\x82\xf7\x82\x6f\x90\x06\xb8\x2b\xb6\x99\x22\x48\x0c\x46\x4b\xa9\x41\x06\x22\xfc\x1e\xac\x80\x88\x0a\x8e\x10\x65\x44\x50\xfc\xca\x90\x55\x65\x57\x5c\x8b\x0a\x42\xa2\xa5\x44\x54\x22\x5a\xf8\x1b\xb5\x0b\xc8\xa1\x70\x12\x2b\x27\xc7\xa9\x74\x61\xb1\x30\xc1\x42\xb0\x0d\x33\xdb\xa7\x68\x18\x81\xe9\x32\xec\x69\x97\xbd\x37\x2b\xcb\x6f\x65\x33\x9b\x3b\x4a\x21\xa5\xaa\x1a\x81\x5d\xf6\x7e\x2d\xb8\xb9\x78\xb6\x00\x82\xa6\x4a\x59\x07\x41\xc2\x02\xf6\x39\x9a\xd3\x01\x64\x0b\xa2\x49\xba\x9c\x26\x68\xa4\xa2\xfd\xac\xd8\xfb\x69\x70\x96\x24\x04\xa6\x08\xbc\x54\x8d\x20\x98\xa7\xce\x7e\x12\x22\xb3\xc6\x11\x04\xa5\xc8\x72\x9a\xe0\xbc\xa2\x6e\x83\x9f\x49\x18\x2b\x8d\x57\x54\xa0\x65\x76\x8d\x08\x42\x20\x48\xa9\x4e\x18\x21\x82\x91\x59\x30\x6b\xbf\xcd\x51\x83\xa4\xca\x75\xf3\x08\xc9\xab\xfa\x02\x58\x36\x7f\xbc\x2e\x90\x23\x8a\xa2\x2b\xe5\x6a\x84\x8a\x84\x6b\x77\x01\x46\xc8\x0e\x26\x08\x0a\xc3\x18\xee\x0b\x49\x89\xb5\x99\xbb\x09\xca\x06\xdb\xa3\x1d\x05\x01\x7a\xe4\x06\xba\x6a\xd6\xe6\x9d\x26\x39\xe2\xf0\x3e\xd7\x66\x07\xb5\x1e\xd7\xa8\x52\x18\xca\xe0\x18\xf9\x44\x0c\xb8\xfa\x78\xd4\x6d\xce\x3a\x54\xb3\xda\xad\xf5\x86\xdd\x76\xa3\x8f\x8f\x29\xf6\x71\xf6\x30\x8d\x5b\x28\x55\x08\xea\x08\x61\x88\x59\x75\xf0\xc8\x10\x8f\xf8\x8c\x61\x5b\xf3\xd9\x08\x9d\x76\xfa\xe8\xb4\x8f\x57\xa7\xcd\xd6\x74\x48\xe1\xec\x74\xd0\xe9\x73\xe8\xb0\xf5\x80\xcf\x46\xad\x7e\x7b\xc4\x75\x3a\xad\xa3\x6a\x48\x15\x82\x39\x42\xaa\xa3\xc1\x63\xab\xdd\x45\x6b\x6d\xac\xc1\x0d\xf1\xea\xbc\xdb\xe8\x71\xf5\x6e\xe3\x7e\xca\x0d\xa6\x68\xeb\x11\x7b\xea\x35\xc6\xad\x3e\x37\xad\xb1\x7d\x66\x3c\xa3\x86\x35\xaa\x3f\x47\x5b\x57\xa7\x6e\x4c\x71\x46\x71\x39\xd5\xe0\x6f\xe6\x3b\xec\xc3\xfd\x6e\x81\xec\x4d\x1b\x37\x10\x76\x03\xd9\xe6\x06\x14\x70\x8e\xe3\xed\x18\x65\x86\x77\x65\xb6\x00\x5c\x44\xd3\x48\x52\x72\x03\x21\x37\xde\x4e\xae\x7c\x45\x93\xb6\x00\x9c\xda\x08\x82\x6d\x00\xa1\x36\x80\xa0\x95\x0a\x4e\xc3\x04\x5d\x21\x5c\x54\x8e\x33\xfd\xf3\xd9\xeb\xc6\x3f\xdf\x41\x9f\x69\x9a\xfe\x4e\x3b\x2f\x18\xfe\x7c\x03\x7d\x3e\x6c\x4c\x71\x1e\xea\x82\xad\xbe\x81\xcf\xff\x4d\x73\xd5\xb8\x3c\x34\x26\x0f\x75\xff\x7e\x9d\xbc\xb8\x7e\x98\xab\xe2\xd5\x3f\x65\x18\x54\x88\x0a\x4d\x63\x15\xb2\x42\xbb\x85\x61\x17\xaf\x65\x3b\x83\x68\x7d\xc1\x8b\x82\x26\xe8\x92\x0b\x0e\x81\x61\xf8\x3b\xec\xbd\x8a\x43\xc4\xa2\x12\xd0\xe3\x1a\x88\xf0\xbd\x84\x49\xc2\xf2\x1c\x8b\x78\x2a\xbd\x03\x75\xb1\x74\x04\x22\x37\xd0\x67\xcf\xa3\xf8\x17\xb0\x73\x64\x9c\xda\x4d\x96\x72\x0c\x17\x15\x8e\x52\xbe\x1f\xfe\x2a\x3b\xfb\x12\x7e\xb9\x9d\x63\x1a\x15\xb3\xf3\x89\x91\xc2\x43\x95\xd3\x8f\x24\x6d\xa1\x39\xb5\x1f\x09\xb6\xd1\x84\x23\x10\x2a\x57\x08\x09\xc7\x49\x4c\x44\x05\x92\x46\x51\x0a\x50\x32\x85\x21\x94\xa2\x10\x04\x4a\x89\x80\x94\x11\x8c\xa0\x2a\x04\xc0\x15\x58\x14\x14\x8a\x24\x28\x1a\xe0\x0a\xaa\xc8\x32\x86\x88\x02\xe1\x8c\x18\x60\x4a\x12\x70\x20\x89\x28\x5e\x11\x14\x54\xc1\x48\x5a\x42\x05\x4c\xa8\xd0\x14\x46\x02\x9c\x04\x02\x8a\xc3\x18\x21\x2b\xb8\x0c\x44\x44\xa1\x71\x5a\x96\x30\x04\x93\x69\x42\x21\x05\x4a\x22\x24\xaf\x63\x45\x62\x63\x0f\xf2\x0e\x23\xee\x50\x24\x3e\x24\xf1\xbe\x46\xbf\xd3\x15\x0a\x46\xa8\xdc\xa7\x7e\x47\x82\x54\x2a\x95\x1b\x08\x21\x9d\xfa\x3c\x7a\xdd\x40\x98\xf3\x0f\xf1\xff\x05\x5f\x22\xfb\x37\x0e\x34\x86\x61\x98\xda\xbb\xd2\x99\x58\xd6\x8b\xfa\xd6\xfd\x10\xa4\xce\xf3\xeb\xbd\x84\x12\x4d\x52\x1d\xd6\xe7\xca\x04\x58\x8a\x76\x8f\xd5\x59\x5a\x53\x04\x7d\x2b\x89\x04\x83\xe1\xaf\x6f\xad\xca\x75\x73\xf7\xb6\xa9\xca\xda\x58\xea\x01\x6b\x71\x6f\xae\xb9\xd1\xbb\x25\xd2\xaf\xf4\xa4\xc7\xa0\xb8\xa4\xbe\xc2\x0e\x6b\x66\x3e\x78\xe8\x8d\x87\xcc\xfe\xa5\x61\x0a\xf7\xa6\x3c\xc9\x8f\xd5\xed\xa0\x59\xab\x90\xcf\xaf\x98\xdc\x26\x3a\x9d\xe9\xf6\x49\x32\xd6\xa8\x38\xff\xb8\xed\xb4\x1e\xa9\xfe\xf6\x76\xd4\x97\x5e\x99\x55\x7f\x64\xb4\x57\x3d\xf4\xfe\xa9\x4a\xbc\xbe\x4e\xc7\x04\xf7\x52\x79\x46\x3a\xe8\xf5\x72\x82\x55\x24\xbd\xdf\x9d\x73\x60\x83\xbd\x3b\x9c\x7b\x1c\xde\x15\x3e\xd6\x68\x48\x18\xc3\x5a\x4c\xc2\xeb\x89\x99\x23\xf8\x90\x61\xea\xf0\x7d\xd2\xe3\xff\xe9\x97\xe7\x54\x70\x4a\xbb\x8f\x37\x05\xf4\x32\x6e\x7c\x45\x62\x32\x5d\x51\x08\x8c\x04\x80\xac\xc8\x88\x88\x52\x22\x21\x56\x68\x05\xc5\x04\x85\xc0\x10\x44\xa4\x08\x92\x16\x50\x5c\x11\x14\x04\x87\x31\x41\x86\x45\x02\x15\x49\x0c\x13\x61\x4a\x04\x34\x7d\xb5\x8f\xae\xc7\x5e\x0d\x27\x3b\x3b\xf6\x1d\x86\x31\x8a\x4e\x69\x0a\xa1\xa7\x5e\x00\xc1\x09\x1a\xcd\x68\x09\x68\xc1\x96\x80\x0e\x9e\x9e\x11\x6e\x43\x18\xb0\x78\x4f\xcd\x70\x7d\xd7\x7f\x9b\x6e\x9b\xd8\xc3\xda\x78\xb9\x7e\x6b\x30\x7d\xbb\x86\x74\xd0\x1e\x55\xa5\xc8\xa7\x29\x68\xcc\x96\xd8\x75\xf7\x11\x7b\x9c\xb4\x5e\x96\x22\x69\x5f\xcf\xd5\x97\x09\x5e\x61\x3a\x0f\x53\x73\x79\xdd\xe6\x34\xac\xf7\x48\x73\x9c\x3d\x75\x6b\xce\x6d\x09\xee\xbb\xf6\xfe\x1f\xe3\x3a\xab\x75\xf8\xfc\xce\x0c\x86\x2f\x5e\x4d\xbf\xcf\xb8\x27\xa5\x4d\xcc\x76\x8d\xd9\x16\x5d\x51\x13\x83\x1b\xd6\x96\x8f\x4f\xc4\xc7\x6b\xc3\x7c\x37\x16\xe8\x33\xfc\x32\x7f\x1d\x72\x5d\xc6\xb4\x39\x74\xd2\x47\xbb\x0d\x86\x9e\xe8\xcd\x37\x7b\x3c\xff\x78\x98\x0f\x9a\x16\xdb\xe1\x9e\x3f\xc8\x0e\xe8\x2d\xef\xfb\x8c\x26\xcc\x67\x32\xfe\xe6\xb6\x94\x76\x42\x4b\xa9\xb7\x93\xbc\xed\xff\x79\x4b\x41\x8b\xb7\x14\xe4\x32\x5e\xee\xae\xd0\x38\xc3\x05\x27\xbc\x22\x34\x05\x7f\x83\x91\x6f\x30\x02\xc1\xf0\x9d\xfb\x97\xea\xcd\x08\x85\x90\x99\x0f\x9d\x88\x81\xa3\x34\x4e\x93\x14\x4a\x93\x19\xae\x9e\xec\xe8\x1e\xa2\x7f\xbb\x4e\xd2\x5f\xd5\x79\x47\xc5\x77\xb7\xbb\x71\xa7\x4a\xd5\xf5\x3a\xdd\x42\xe1\xed\x73\xf5\xda\x82\x17\xb6\xf5\xde\x7e\xff\x40\xe6\xf2\x78\xf6\x28\x54\xef\x85\xc6\xc2\xa1\x67\x13\x7c\x38\xf9\x15\xf8\x30\xc3\x54\x5f\x7e\x83\x22\x17\x7d\x5d\x79\xbe\x94\x3f\x9e\x2a\xb0\x77\xf2\xd4\xe1\x55\xca\x82\x51\x6a\xd6\x96\xd2\xe0\x72\xd8\x1c\x25\x63\xa7\xb1\x89\x25\x30\xd8\x69\x5c\xf0\x58\xa2\x75\x1a\x17\x22\x36\xe8\x3e\x8d\x0b\x19\x4b\x15\x2e\xb3\x97\xf4\x22\xd3\x08\xd9\xcb\x80\x37\x10\x59\x74\xfa\x24\x65\x47\xe5\xd9\x1e\x1b\xf2\xd2\x88\x8b\xee\x3f\xe0\xee\x68\xaa\xe2\xa6\x42\xaa\x6e\x1b\x67\xe5\x3d\x4e\x96\xe6\x4d\x21\x9d\x99\xa6\xfe\x82\xb9\xc0\x04\x93\x84\x3d\x7c\xff\xbe\x12\x4a\x77\x95\x8d\x2e\x03\xd3\xd5\xe5\xc4\xf9\xbc\x4b\x99\xe4\x06\x2a\x92\x7b\x9f\x39\xf1\x58\xc6\x6c\x7e\x63\xdc\xbf\xc7\x7f\xa9\xd9\xce\x70\xc8\x5f\x6f\xb6\x9c\xa6\x9d\xb0\xb3\xf7\x8c\x85\xef\x52\x7b\x15\x4f\xed\x3e\x52\xb7\x0e\x24\x86\x3c\x3c\x3d\x3e\xe4\x32\x42\x63\x8c\xd2\x82\x5e\x2e\x23\x2c\xda\x84\xd3\x42\x4d\x2e\x1f\x3c\xd6\x15\x9c\xca\x27\xd6\x36\x4e\xc6\x43\x46\xf9\xa4\x07\xbf\xb2\xdb\x1a\x2f\x11\xfe\xf2\x36\x87\x94\x08\x80\xa9\x7b\x18\x2f\xe0\xc3\xe1\x05\x77\x0c\x17\x01\x8d\x53\x24\x2a\xcb\xb8\x48\x29\x74\x45\x21\x71\x5c\x06\x28\x4c\xa1\x14\xa6\x20\x02\x82\xd1\x0a\x81\x09\x40\x91\x50\x01\x01\x40\x24\x91\x4a\x85\x44\x90\x8a\x24\x50\x15\x94\x52\xae\xf6\x93\xd6\x27\xc7\xa7\x50\xbe\x8e\x05\x89\x4a\xfa\x64\x17\x8a\x60\x19\x53\x61\xde\xd3\x48\x0b\xf2\x32\x9c\x0e\xf9\x0c\x54\xec\x79\x65\xb4\x2b\x93\xa6\x56\xbf\x05\x0b\x09\xa3\x06\x73\xbb\xd5\xe9\x7c\xcc\x1e\x2a\xef\x0f\xea\x53\x55\xa8\x6d\x88\x2e\xd1\x63\xdc\x0c\x81\x09\x12\xf0\x6a\x6c\x00\x1e\xfa\xec\xa6\x1d\x4c\x1f\xad\xdd\x32\x7d\x9c\x78\xac\xd6\x31\xbb\xf5\xd0\xe8\x23\x23\x8c\x81\x7b\xe0\x65\x50\xb9\x1f\x91\x3a\x87\x30\x34\x98\xa9\xf2\xae\xed\x67\xfd\xee\x4b\xa0\x5e\xde\x5e\xde\x5d\x76\xbd\xdb\xfa\xa6\x41\xa3\x96\x3d\x34\xe0\xe7\xa1\x62\x9b\xec\xe6\x6d\x34\x32\xd1\xc6\xa3\x2d\x54\x16\xb7\x75\x7a\x26\xae\x66\xd3\xfb\x0f\x75\x5a\x79\xa6\x9e\x6e\xc7\x1d\xb4\xb9\xbc\xbd\x35\x17\x00\x7e\x86\xe7\xc3\xca\xee\x45\xc4\xea\x95\xae\x4e\x7f\x28\x6b\x73\xd0\xa1\x26\xd7\xd3\xdd\x07\x33\xfc\xf9\xf3\x2a\x9c\xdd\x35\x43\x59\xd1\xe1\x6d\x28\xc3\xbf\x9f\xd6\xae\xfb\x92\xf7\x3e\x54\x76\xb8\x27\xab\xbb\x9f\xdf\x0f\x25\xcc\x57\x8e\xec\x82\xbe\xb0\x78\xde\xf6\x84\xe9\x80\x26\xab\x1f\x8a\x45\x03\x58\x32\x4c\xee\x69\xfe\x51\x9d\xdd\xbf\x34\x8c\x4e\xa0\x27\x53\x7b\x60\xde\x9e\xf5\xb8\xd8\xa3\x17\x9b\xf6\xa0\x7a\x61\xf9\xf1\x7a\x2d\x24\xdf\x2b\xe4\xba\x48\x2d\xf4\x8c\x7a\xec\x56\x18\xea\x59\x5b\xb0\x03\x00\xcb\xd3\x29\xf5\xd0\x92\xea\xc3\x2d\x39\xbc\x7d\xd7\x5a\xaf\x12\x36\xad\x23\x84\x70\x8f\xb5\x55\xc4\xb5\xa7\x63\x6b\xbf\x12\x16\x19\xa6\x48\x4d\x64\x5d\x8c\xf5\xd3\xe5\x8f\x8d\x46\x05\x48\xa7\xcb\xef\xc5\xe4\xd7\x36\x06\x66\xd8\x38\xf1\x5a\x1b\xb0\xdb\xf5\xf0\x16\x33\x5a\xdc\xf5\x07\x42\x8d\x76\xaa\x85\x68\x4a\xaf\xf1\xb8\x1a\xce\x16\xe6\x66\x7c\x3d\x61\x98\xa8\xaf\x2d\x98\x74\x9b\xa7\xca\x0f\xf9\x4f\x89\x76\xbd\xf7\xe9\x05\x93\x50\x87\xa7\xe8\x70\xc9\x3a\x3c\xd7\x86\x65\xe4\x7b\xed\xfb\x9f\x5f\xd5\xf1\xb8\x03\x48\x77\xd7\x72\x30\xfb\x55\xe4\xbf\x13\x16\xdd\xee\x3f\x7f\x64\x10\x8a\x5f\x22\x2a\xa0\x28\x25\x61\xb4\x44\xe2\x02\x8e\x2b\x12\x25\x88\x32\x2e\xd1\x64\x05\xa1\x71\x82\x54\x60\x8c\xa6\x69\x98\x94\x11\x54\xc2\x29\x52\xa6\x60\x11\x87\x51\x51\x91\x45\x94\x26\x65\x52\xc0\xbc\x29\x41\xe4\x9c\x11\xaf\xb7\xa6\x93\x1e\xb6\xdc\x89\x69\x1a\x4b\x9f\xcb\x73\x9e\x1e\xa6\xad\xbd\x71\x96\xe7\xa9\xcd\x6e\xa5\x35\x7c\x1b\xbe\x88\x1d\xb4\xc5\x60\xb3\x87\xe7\x91\xd9\x59\x3d\xcf\x61\x58\x69\x56\xac\x6e\x9b\x5a\xc1\xec\xe8\xfd\x7e\x76\xcb\xcc\x31\x66\x1f\xb5\xdc\x57\x46\xd4\xf2\x5e\x27\xf4\x9e\xe1\xb9\xb2\xea\xc3\xdb\x7b\x83\x76\x1e\xb1\x75\x1b\xeb\xbc\xaf\x84\xc1\x66\x20\x37\xc6\xd3\xad\xcc\x34\x80\x48\xf6\x87\xc0\xde\x0d\x3b\xed\x99\xf0\xa1\x89\xe3\x5e\x6f\xb9\x6a\x75\xb8\x6e\x1d\xb7\x5e\x97\xec\xeb\xf4\x49\x1a\x0e\x60\xed\x7a\x7e\xdb\x5f\x5f\x1b\xd6\x6c\xc5\x91\xd7\x8d\xe9\xa3\x68\x7d\x50\xc4\x10\x7d\x6e\xe2\x6f\xbd\x5e\x81\xe8\x15\x71\xe9\x68\xc4\x0a\xe9\xec\xad\x04\x31\xd1\xd6\x5e\x55\x6f\xab\x70\x17\xbe\x6f\xee\xec\xe5\x3b\x87\x68\x8f\xb0\xb0\x5b\x1b\x08\xcd\xb5\xb6\x6f\xdd\xda\xae\x4f\xd8\x55\x56\xaa\x79\x3a\x62\x0b\xdb\xec\xeb\x8f\xb7\x15\xfc\x50\x3e\x25\x82\x65\xb7\xf6\x33\xe4\x37\x26\xb3\xaa\x75\x86\x7c\x86\xf9\xf7\x7a\xbb\xd0\x68\xe2\xd0\xf3\x56\x4f\xb7\x45\x5f\x7f\xca\x54\x33\xcf\x16\xe7\xd6\x85\xe3\x0b\xd7\x52\x8c\x5f\x29\x5b\xfc\x43\xc9\x3b\xeb\x7e\xf5\x4c\x3d\x63\xa3\xa9\xd6\x9b\x0f\xab\xf3\xd5\xf5\xf3\x4b\xcb\x94\x5e\x6a\x6a\x63\x65\x11\x33\xf8\xb9\xde\x7e\x5a\xee\x9e\xc7\xef\xd7\xdd\x8e\x31\xea\x68\xcd\x39\x5b\xa7\xef\x15\xed\xf6\xe3\x55\x79\xed\x36\xd6\xcf\xe0\x6d\xf9\xd0\x6c\x52\xbd\xeb\xeb\x29\x67\x6c\x37\xdd\x8f\x3a\xf3\x7b\x7b\x5e\x8c\x14\x01\x05\x2b\x22\x45\x55\x50\x85\xae\xc0\x88\x24\x4b\x40\x96\x10\x14\x26\x01\x8a\x28\x34\x8d\xd2\x98\x44\xd3\x15\x12\x16\x10\x02\xe0\x38\xa2\xe0\x14\x4e\x53\x38\x25\xc0\x02\x46\x09\xe2\x61\x01\xf0\x8c\x9e\x17\xcd\xed\x79\x71\x04\xa1\xd3\x7b\x5e\xff\x69\x38\xa3\x3c\xb7\xe7\xad\xc5\xaa\xfc\xa8\xe7\x2d\x99\x2f\x64\xf4\xbc\x0c\xb6\x9d\x89\xdb\x41\x5f\xd4\x9f\x7a\x6a\xb5\xd9\xe8\x74\xef\x87\x1b\xe5\xbe\xbb\xd8\x4c\xac\xd6\xfd\x76\xc7\x58\x83\x01\xd1\xa0\x9f\x9e\x09\x12\x11\xe6\xfa\x1b\x77\xdb\x7a\x18\xdd\x8b\x0d\x8b\x95\x54\xbb\x29\x2e\x54\x5a\x9e\x3d\xc8\x9d\xd1\xe3\xdb\xea\x61\x56\x53\x3f\xda\xf2\xaa\xdb\xae\xff\x6f\xf5\xbc\xe7\xf6\x7c\x67\xb6\xf6\x57\xea\x76\x52\x97\x2e\xd8\xf3\xfe\xce\x5c\x21\xb1\xe7\xfd\x97\x7a\x3e\xe6\x42\x3d\xef\xa9\x51\xd8\xef\x79\xb9\xca\xc3\xaa\x32\xf9\x58\x11\xe8\xa4\xbd\x18\x2d\xc7\xea\x6e\xda\xd5\x77\x63\xbc\xfb\x42\x55\x77\x92\xb4\xe8\xd6\x3f\xae\x47\xca\xec\xf1\x1a\xd8\x33\x8d\xa0\x3e\x94\x2d\x32\x1d\xcf\xb6\x62\xb5\xd5\x36\x47\x2b\xbc\xfd\x36\x7f\xd0\xe6\xe3\x97\x59\x97\xd0\x1e\x16\x86\xb5\x6b\x3d\xa9\x3b\xe6\xfd\x12\x3d\x6f\xea\x91\x79\xc7\x27\xca\xef\x4f\xaf\x0d\x7e\x03\x5e\xf6\x27\x51\x21\x8e\xde\xe9\x96\xf5\x7a\xf8\x17\xe5\x71\x81\xd0\x60\xd4\xee\x31\xa3\x47\xa8\xc3\x3e\x42\x5f\x54\x39\xef\x54\xbb\xe4\x13\xf6\xcf\x46\x1d\xe3\x9a\x84\x3c\x49\x70\x2e\xfa\xd8\x8f\xf9\x4e\xbb\xa1\xe0\x6c\xed\xa2\x62\x93\x94\x3b\x09\x18\x34\xe5\xda\xc3\x29\x0b\x7d\x39\x90\xdf\x84\x8e\x6f\xbb\x89\x1c\xb6\x56\xd2\x34\x97\xa9\xd6\xd2\x8a\x97\xaa\xd4\x94\xb5\xd4\x9c\x05\xcb\xcb\x6a\x96\x2c\x24\x4b\xd3\x0c\x58\x85\x35\x4f\x9d\x4a\xcf\x9d\xad\xbe\xac\xf6\x69\x62\xb2\xf4\xcf\x84\x96\x6b\x81\xe8\x0d\x31\xbe\x22\xee\x6d\x32\xc5\x0e\x00\xf0\x2e\x9e\x89\x70\x81\xfa\x5c\xbc\x31\x4c\xc7\x6d\xae\x09\x89\xb6\x09\x40\xb8\x75\xa5\xa3\xf1\x2f\xb7\x39\x1b\x8f\x7f\x30\x62\x21\x44\x29\xed\x3a\x74\x31\xcf\xa9\x70\x0e\x2c\xc2\x48\x22\xb9\x42\x14\x8f\x47\x7c\x73\x74\x1c\x41\x12\x38\xf7\x6a\xa1\x33\x90\xb9\xa7\x32\x14\x82\x15\x3f\xcb\x21\x09\x8d\x7f\x1f\xd2\x19\x78\x3c\x0e\xc5\x10\xc5\x0e\x8a\xb8\x39\x3e\x13\x22\xb1\xc9\x87\x2f\x78\x2a\x8f\xd4\x8f\x12\x1e\xe0\x18\xbb\x30\xec\x60\x1b\x79\x04\x71\xd2\xb9\x4a\x37\xc1\x19\x4a\x69\x60\x0f\xbf\xeb\x3e\x13\xa6\x2a\x17\x06\x78\x38\x0b\xe6\x26\xf1\x30\xa8\x1c\xd0\xc1\x9d\x5c\x97\xc0\xed\xf3\x0a\x43\x4f\x09\x55\x27\x69\x92\xac\x40\x70\xfd\xd8\x25\x14\xf0\x79\xa5\xf8\xf4\x89\x2a\x44\x0f\xf6\x39\x56\x22\x74\xd9\xda\xa9\xad\x31\xc4\xe3\x54\xe3\x67\x1b\x3a\x76\x7b\xdc\xb9\xb6\x8e\xb2\x0b\x43\x0e\x36\xac\x46\x30\x26\x23\x3a\xbe\x01\xef\x7c\x58\x47\x3c\x8b\x75\x6f\x49\x00\x43\x77\xf9\x9d\x5c\xad\x07\x1e\xa7\xbb\x64\x9e\xfb\x25\xdd\x52\x78\x3a\xe0\x63\x66\x31\xe4\x32\x88\xe1\x8c\x9d\x0f\x97\x0d\xd0\xbb\x76\xf1\x22\xf0\x5c\x56\x85\xc0\x05\xbf\x7d\x4e\x85\x16\xbf\x46\xf2\x5c\x7c\x31\x7e\x79\x20\x8f\x0f\xbe\xcb\x45\x7a\x19\x3b\x46\xb8\x15\x45\x99\x6b\xcd\xcb\x60\x2b\x84\x29\x1b\x4b\xec\xbe\xd2\xb3\x10\x45\x79\x15\xae\xd1\xe0\x84\xbc\x44\x7c\x47\x57\xb0\x9e\x85\x30\xce\xad\x58\xbb\xf5\x01\xde\x1c\x1d\xea\x77\x73\x74\xa2\x64\x8a\x12\x17\xe8\xb7\x7d\x3e\x79\x88\x4b\x8e\x8e\xe2\x37\xe7\x9e\x65\xdd\x12\x86\xcd\xb5\x5b\xfe\x95\xc0\x67\x1a\x34\x57\x40\x24\x4f\x0b\x7e\x1a\x1f\xcd\x8c\x3c\xc2\x12\xd8\xcf\xf7\x83\x2c\xde\xf9\x88\x13\x5a\x59\xf6\x85\xcf\xa7\xfa\x43\x26\xd7\xdc\x61\xbf\x43\x94\x03\x34\xf1\x66\xeb\xcb\xa0\x4d\x62\x9d\x3b\x7c\x2b\xea\xc9\xd1\xab\xbc\x2f\xea\x0c\x11\xd6\xa7\x8c\x37\x8b\xdf\x5d\x7e\x71\x43\x1f\x9d\xda\x9e\x0b\x3f\x56\xa0\xb8\x32\xe1\xab\xdc\x7f\x95\xfd\xc3\x07\xf5\xe7\x69\x12\xa2\x2d\xae\x44\xe2\xd5\xf6\xbf\x4a\x9b\xc4\xfb\x07\xf2\xd4\x4a\x2a\x54\x5c\xbf\xfd\xcd\xff\xbf\x4a\xa7\xfd\xa9\x88\x79\x7a\xa4\xce\x76\x45\x59\x1f\x7e\x5e\xf0\x2b\x9a\x76\x9c\x7b\x62\x02\x5c\xb6\x81\x47\x99\x46\x53\xa8\x0b\xb5\xf0\x2c\x11\x45\x74\xc8\xc9\xeb\x32\x85\x5d\x2e\x7c\x1d\x33\x2e\x84\x3d\x3f\x88\x85\x93\xed\x5f\xe1\x36\xc7\xfc\x4f\x4e\xf5\xbd\x13\xb2\x82\x40\x1e\xcc\x30\xf2\xa2\x61\xbc\x9c\x6c\xe5\x0c\x9e\xb9\x43\x84\x2f\x5f\x82\x03\xee\xbf\xfd\xf9\x27\x74\x65\x19\x9a\x1c\x5a\x4d\xbb\xba\xbb\xb3\xc1\xd6\xfe\xfa\xf5\x06\x4a\x27\x94\x0c\xb9\x18\xa1\x37\x17\x9f\x4e\x2a\x1a\x9b\xc5\xd2\x2e\x24\x3e\x42\x9a\x0d\x20\x42\x1a\x83\xf0\x15\x9a\xb5\xd8\x11\xeb\x39\x19\xf4\x13\xc2\xb0\xc2\x0b\xd1\xaa\xcc\x2b\xa1\x65\xa2\x46\xe7\xf7\x2c\x47\xfb\x62\xa1\x46\x7f\xc4\xb6\x9b\xdc\x7e\x09\x08\x1a\xb1\x0d\x76\xc4\x72\x35\x36\x7e\xc5\xbc\xfb\xb4\xcf\x41\xd3\x41\xdd\x71\x99\x11\xeb\xdd\xea\xe8\x7c\x55\x67\xbb\xec\x84\x85\x6a\xcc\xb8\xc6\xd4\xd9\xec\x9b\x08\x62\x1f\xf9\xd8\x54\xcc\xe5\x8c\x11\x95\x93\xb3\x48\x96\x86\x24\x6a\x9f\xf8\xb4\x51\xa2\xb1\xfc\x81\x7e\xce\x8a\x62\xaa\x25\xfc\x54\xf6\x5f\xb7\x43\x18\x47\x92\x15\x82\x59\x82\x6c\x87\x29\x67\x81\xe3\x49\xa5\x7f\xd1\x0c\x29\x60\xa2\xb6\x48\x98\x06\xbb\xac\x53\xc4\xa7\x38\xfe\x17\x0c\x92\xee\x1a\x47\x73\x48\x45\xbc\x03\x12\x64\x19\xc8\xd0\x4a\xd0\x37\x82\xa6\xed\x22\x48\x13\x63\xa3\x03\x33\x30\xf8\x6a\xb3\x05\x32\xf4\x26\x98\xd2\x52\x30\xbf\x90\xf4\x57\x7f\x47\x90\x43\xa3\x80\x43\x6b\x4d\xa6\xfb\x91\x28\x2c\x34\x82\x70\xd8\x44\xaf\x69\x29\xc5\x29\x08\x95\x2e\x62\x6f\x76\x22\xb5\xbc\xef\x14\x03\xc3\xb2\x17\x26\x18\x0f\xbb\x90\x2c\xd8\x82\xd3\xd8\x20\x79\xb3\x5a\x43\x92\xb1\x5a\x6b\xc0\x06\x6e\x6d\xfe\x5f\x00\x00\x00\xff\xff\x5e\xe5\x5f\x23\x67\x90\x00\x00") +var _account_mergeHorizonSql = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xd4\x3d\x79\x6f\xe2\xc8\xf2\xff\xcf\xa7\xb0\x46\x2b\x65\x46\xc9\x4c\x7c\x1b\x67\xde\xac\x64\xc0\x1c\x01\xcc\x1d\x48\x56\x2b\xcb\x47\x1b\x9c\x18\x9b\xd8\x26\x81\xac\xde\x77\xff\xc9\x17\xd8\xc6\x27\x30\xb3\xef\x87\xa2\x08\x70\x75\x5d\x5d\x5d\xd5\x55\xdd\x74\x7f\xfb\xf6\xe9\xdb\x37\x68\x60\x58\xf6\xc2\x04\xe3\x61\x17\x92\x05\x5b\x10\x05\x0b\x40\xf2\x66\xb5\xfe\xf4\xed\xdb\x27\xe7\x79\x7d\xb3\x5a\x03\x19\x52\x4c\x63\x75\x00\x78\x03\xa6\xa5\x1a\x3a\x44\x7f\x27\xbf\x23\x21\x28\x71\x07\xad\x17\xbc\xd3\x3c\x06\xf2\x69\xcc\x4e\x20\xcb\x16\x6c\xb0\x02\xba\xcd\xdb\xea\x0a\x18\x1b\x1b\xfa\x09\xc1\x3f\xdc\x47\x9a\x21\xbd\x1c\x7f\x2b\x69\xaa\x03\x0d\x74\xc9\x90\x55\x7d\x01\xfd\x84\xae\xa6\x93\x46\xe5\xea\x47\x80\x4e\x97\x05\x53\xe6\x25\x43\x57\x0c\x73\xa5\xea\x0b\xde\xb2\x4d\x55\x5f\x58\xd0\x4f\xc8\xd0\x7d\x1c\x4b\x20\xbd\xf0\xca\x46\x97\x6c\xd5\xd0\x79\xd1\x90\x55\xe0\x3c\x57\x04\xcd\x02\x11\x32\x2b\x55\xe7\x57\xc0\xb2\x84\x85\x0b\xf0\x2e\x98\xba\xaa\x2f\x7e\xf8\xbc\x03\xc1\x94\x96\xfc\x5a\xb0\x97\xd0\x4f\x68\xbd\x11\x35\x55\xba\x71\x84\x95\x04\x5b\xd0\x0c\x07\x8c\xe9\x4e\xd8\x11\x34\x61\xaa\x5d\x16\x6a\x37\x20\x76\xde\x1e\x4f\xc6\x50\x9f\xeb\x3e\xfa\xf0\xdf\x97\xaa\x65\x1b\xe6\x8e\xb7\x4d\x41\x06\x16\x54\x1f\xf5\x07\x50\xad\xcf\x8d\x27\x23\xa6\xcd\x4d\x42\x8d\xa2\x80\xbc\x64\x6c\x74\x1b\x98\xbc\x60\x59\xc0\xe6\x55\x99\x57\x5e\xc0\xee\xc7\xef\x20\x28\xb9\xef\x7e\x07\x49\xc7\xae\x7e\x9f\x80\x1e\xb5\xf2\xd2\x79\x0c\x3a\x86\x9c\x45\x2c\x04\x75\x40\xee\x82\xb7\xb9\x3a\x3b\x0f\x41\xfa\x68\x5d\xae\x78\xa0\x28\x40\xb2\x2d\x5e\xdc\xf1\x86\x29\x03\x93\x17\x0d\xe3\x25\xbb\xa1\xaa\xcb\x60\xcb\x87\x84\xd3\x2d\xc1\x35\x74\x8b\x37\x74\x5e\x95\xcb\xb4\x36\xd6\xc0\x14\xf6\x6d\xed\xdd\x1a\x9c\xd1\xfa\xc0\xc9\x59\x5c\x94\x6b\xab\x01\x79\x01\x4c\xb7\xa1\x05\x5e\x37\x40\x97\x4a\x89\x10\x6a\xbe\x36\xc1\x9b\x6a\x6c\x2c\xff\x3b\x7e\x29\x58\xcb\x13\x51\x9d\x8f\x41\x5d\xad\x0d\xd3\x19\x8e\xbe\x4f\x3d\x15\xcd\xa9\xba\x94\x34\xc3\x02\x32\x2f\xd8\x65\xda\x07\xc6\x7c\x82\x29\xf9\xe3\xf2\x04\xa6\xc3\x2d\x05\x59\x36\x81\x65\x65\x37\x5f\xda\xa6\xec\xc6\x1d\x5e\x33\x8c\x97\xcd\xba\x00\xf4\x3a\x8f\x25\x0f\x4a\x50\xcd\x92\x88\x03\xa7\x5b\xb8\x81\xe3\x27\x14\x05\x98\xc5\x40\x03\xf4\x27\x34\xf1\xd5\x5a\xac\x91\xeb\x5a\x4b\x10\x09\xbb\xe2\xbc\x16\x6b\xa7\xc1\xd2\xce\xed\x01\x2b\xe2\x80\xc4\x5d\xae\x19\x2d\xf7\x23\xbd\x08\xb0\xe1\xf1\x61\xe4\x02\xaa\x96\xcd\xdb\x5b\x7e\x9d\x8f\xd2\x81\x34\xd6\x45\x21\x41\x51\xb0\x20\x94\x64\x03\x8b\xc1\x70\xcf\x05\xcb\xf7\x62\xe2\xae\x58\x67\x7a\x31\xd2\xd1\xb6\x65\x6d\xf2\x28\xef\x81\x25\x43\x06\x25\xe7\x05\x7b\x33\x58\x0b\xa6\xad\x4a\xea\x5a\xd0\x33\x83\x77\x5e\x53\x7e\x5d\x72\x6e\xb2\x8f\x68\x65\x39\x48\x6e\x58\x9a\xbe\xab\xbc\x22\xf4\x3c\xc0\x5f\x8e\xdf\xeb\x4c\xa7\x27\xfd\xb7\x4e\x7c\x08\xa6\x7e\xae\x31\xf0\x05\x39\x58\x18\xe6\x9a\x5f\xa9\x0b\x7f\xc2\x90\xc1\x42\x0c\xb2\xb0\x8c\xe5\xe7\x7b\x59\x98\x8b\x1a\xa7\xd7\xba\xd6\xef\x4e\x7b\x1c\xa4\xca\x1e\xe5\x3a\xdb\x60\xa6\xdd\x49\x41\xdc\x29\x46\x77\x01\xcc\x7e\x77\x67\x63\x72\x3f\x15\x17\x3f\x88\xd2\x63\x76\x38\x65\xb9\xda\x09\x3a\x73\xe6\xd9\x16\x78\x2d\x4d\x39\x82\xa4\x70\x6b\x19\x14\x84\x3d\xcc\x66\x0b\x4b\x98\x32\xea\xcb\xc8\x97\x8c\xa2\x58\x5b\x7f\xde\x57\x0c\xd8\x9f\xe4\x15\x96\xcd\xf7\x00\x65\x64\xf1\x9a\x14\x84\xf5\xa7\x7f\xc5\xf9\x09\xe6\x8b\x45\x38\x8a\xf9\x90\x6c\xe0\x90\x4b\xf0\x01\x99\x66\x73\xc4\x36\x99\x49\x02\xf0\x4a\x75\x32\x0e\x55\x02\x5f\xf4\xcd\x0a\x98\xaa\xf4\xd7\xdf\x5f\x0b\xb4\x12\xb6\x27\xb4\xd2\x04\xcb\xfe\x22\xe8\x3b\xa0\xb9\xa5\x98\x02\x2d\x14\xd5\x4c\x6c\xd2\x98\x72\xb5\x49\xbb\xcf\x65\xc8\xc3\x0b\x8b\xc5\x81\xbb\x1b\xe8\x88\xd1\x0c\x1c\x81\x74\x67\xe0\x70\x64\x75\x9b\x1f\x98\xbf\x81\xca\x08\xe2\x8a\x5e\x00\x03\x3b\x9f\xb0\xdc\x38\x86\x42\x5b\x2f\xac\x57\x2d\xb0\xc5\x5a\x8b\xed\x31\x47\x14\x7e\x7c\xf2\xaa\x70\x9c\xb0\x02\x77\xc1\x77\xd0\x64\xb7\x06\x77\x7e\x93\x1f\xd0\x58\x5a\x82\x95\x70\x07\x7d\xfb\x01\xf5\xdf\x75\x60\xde\x41\xdf\xdc\xe2\x5c\x6d\xc4\x3a\xfd\xe5\x63\x0e\xf0\x7d\x8a\x60\x8c\x3e\xf4\x11\xd7\xfa\xbd\x1e\xcb\x4d\x32\x30\x7b\x00\x50\x9f\x8b\x22\x80\xda\x63\xe8\x2a\x28\xbb\x05\xdf\x59\x2e\x92\xab\x38\xe5\x40\x7c\x9f\xe6\x5e\x43\xb9\xf2\x44\x74\xc9\xf5\x27\x31\x7d\x42\xb3\xf6\xa4\xb5\x67\x2b\x5c\x7f\x8b\x90\x3f\x60\x89\x31\x52\x46\xf8\x23\x24\xae\x02\x06\xdd\xdb\xf5\x62\x3c\xec\x42\x6b\xd3\x90\x80\xbc\x31\x05\x0d\xd2\x04\x7d\xb1\x11\x16\xc0\x55\x43\xc1\x7a\x61\x98\xdd\x7c\x43\xf3\xd9\x0f\x6c\xf5\xc0\x7f\xd0\xb7\x49\xba\xdc\x5b\x76\x2e\x7e\x68\xc4\x4e\xa6\x23\x6e\x1c\xfa\xee\x13\x04\x41\x50\x97\xe1\x9a\x53\xa6\xc9\x42\xae\xf4\xbd\xde\xd4\xf3\x77\xe3\xc9\xa8\x5d\x9b\xb8\x10\xcc\x18\xfa\x83\xff\x03\x1a\xb3\x5d\xb6\x36\x81\xfe\x40\x9c\x4f\xf1\xde\xc8\x1d\x88\xe7\x49\x97\x87\xfe\x62\xc2\xa1\x49\xc2\x15\xf1\x54\xe7\xc9\x57\x80\xc2\x5e\xc4\xfd\x57\x27\x49\xf8\xe5\x13\x04\xd5\x98\x31\x0b\xcd\x5a\x2c\x07\xfd\x81\xfc\x85\xfc\x7d\xfb\x07\xf2\x17\xfa\xf7\x9f\x7f\xa0\xee\x7b\xf4\x2f\xf4\x6f\x68\xe2\x3d\x84\xd8\xee\x98\x75\x94\xc2\x72\xf5\xaf\x89\x9a\x29\x10\x07\xce\xd4\x4c\x3e\x85\x5f\xad\x99\xff\x9c\xa2\x99\xe3\x98\xea\xeb\x61\x1f\x87\x8b\x29\xe2\x10\xb6\x8f\x30\xba\x1c\x43\xd0\xd8\xd1\x15\xf4\xf3\xe0\x01\x6e\xbc\xaf\x27\x8f\x03\x16\xfa\x19\x1e\x11\x5f\x93\x46\xed\x45\x79\x8c\x23\x8c\xb1\x18\x0c\xe3\xe2\x1c\x26\x4e\x81\xce\xe5\x32\x09\x69\x8c\xd3\xc8\x80\x8c\xb2\x7b\xb0\xb2\x63\x6e\x93\xa6\x79\x67\x73\x9b\x80\x34\xce\x6d\x78\x90\x64\x72\xeb\x44\x2e\x19\x28\xc2\x46\xb3\x79\x5b\x10\x35\x60\xad\x05\x09\x40\x3f\xa1\xab\xab\x1f\xd1\xa7\xef\xaa\xbd\xe4\x0d\x55\x0e\x2d\xa5\x45\x64\x0d\xcf\x7f\x7d\x11\xdd\x01\x56\x4c\x3c\x6f\x2c\x86\x93\x6f\x4f\x22\x55\x86\x44\x75\xa1\xea\xb6\x3b\x31\xe0\xa6\xdd\xae\x27\x8e\xb0\x72\xa6\xf1\x90\xb4\x14\x4c\x41\xb2\x81\x09\xbd\x09\xe6\x4e\xd5\x17\x31\x30\x7d\xb3\xda\x4f\xf9\x21\x55\xb7\xc1\x02\x98\x31\x10\x45\x13\x16\x16\x64\xad\x04\x4d\x3b\x26\x63\x1b\x2b\xed\x98\xc8\x17\x94\x20\xbe\xee\x21\x8f\xbb\x3d\x9e\x37\x9c\xaa\x8e\x78\xb5\x63\xaf\x12\x1b\x6c\x8f\x14\xb2\x5e\x6b\xaa\x5b\xb3\x87\x6c\x75\x05\x2c\x5b\x58\xad\x21\xa7\xcf\xdc\x8f\xd0\x87\xa1\x83\x63\x46\xd3\xb2\xa2\x60\x3e\xea\xa7\x53\xc5\x78\xde\x27\x5f\x29\x58\x7d\x33\x64\x46\x13\x6f\x46\x87\xb8\x5f\xb4\xb9\xda\x88\x75\xa7\x5f\xd5\x47\xff\x2b\xae\x0f\xf5\xda\xdc\x03\xd3\x9d\xb2\xfb\xcf\xcc\xfc\xf0\xb9\xc6\xd4\x5a\x2c\x84\xe4\x09\x73\xb2\xda\xe3\x88\x8e\x4c\xd1\x2f\x7a\x40\x3a\xd8\xda\x6f\x82\xf6\xe5\x2a\x45\xe2\xab\xbb\x3b\x13\x2c\x24\x4d\xb0\xac\xaf\xf1\xee\xf2\xd6\x2a\x12\x6c\x8b\xc4\xbf\x66\x74\x94\x97\x1b\x9f\x2d\x99\x57\xd1\xd9\xcb\x95\x3c\x32\x0e\xb5\xba\x64\x36\x13\xc1\x25\x43\x4e\x02\x47\xd0\x64\x70\xaf\xfc\x97\xd0\x80\x20\xb3\x46\x58\x72\x79\xe1\x42\x66\x1b\xc6\xf9\xdb\x8c\x36\x4b\x10\xa8\x3f\xe3\xd8\x3a\x54\x7d\xcc\x91\xc8\xab\xd0\x65\x0b\xb4\xc7\x15\x7b\xfc\x5d\x95\xd3\x78\x0b\x6a\x3e\xe7\x5a\x9d\x8f\xc7\x37\xbb\xd8\x98\xe1\xd3\x3c\xfd\x71\x89\x2b\x0d\xf2\xb3\xbb\xf0\xf1\x39\xc5\x9a\x5d\x3b\x4e\x7e\x24\x03\x5b\x50\x35\x0b\x7a\xb6\x0c\x5d\x4c\x37\xb6\xa0\x50\x76\xae\x1e\x7c\x3c\xbe\x1e\x82\x75\xeb\x14\xde\x42\x8b\xc9\x85\x46\x61\xd2\x3a\x76\x72\x43\x5f\x2d\xa1\xca\xa8\xdb\x11\x7b\x3e\x02\x2f\x07\xc7\x28\x1c\x3a\xa2\x18\xfc\x7e\x31\x39\x16\x98\x8c\x8d\x7d\x88\x4d\xf1\x36\x26\x10\xec\xdc\x46\x1e\xec\x66\x2d\x17\x86\xdd\x9b\x8e\xff\x31\xb6\xce\x7e\x24\x0b\x72\x34\x1f\xb0\x05\x8d\x97\x0c\x55\xb7\x92\x6d\x50\x01\x80\x5f\x1b\x86\x96\xfc\xd4\x5d\xf9\x54\x40\x5a\x5f\xbb\x8f\x4d\x60\x01\xf3\x2d\x0d\xc4\x99\x87\xda\x5b\xde\x9d\x26\xa9\x1f\x69\x50\x6b\xd3\xb0\x0d\xc9\xd0\x52\xe5\x8a\xf7\x51\x60\x2c\x40\x90\x81\xe9\x4e\x2f\xbc\xef\xad\x8d\x24\x01\xcb\x52\x36\x1a\x9f\x6a\x28\xbe\xe0\x82\xaa\x01\x39\x1d\x2a\x7d\x58\xa5\xd4\xae\xcf\x1d\x65\x29\xeb\x21\x39\x31\xaf\xb8\xb7\xc9\xf7\x5f\x65\x45\xbe\x6c\x18\xcb\xa4\xf1\xbb\xc2\x5a\x29\x41\xcf\x0c\x73\x99\xb4\x8e\xc3\x5e\x32\x78\x46\x18\x0c\xad\xec\x5c\xcc\x36\xf3\xd2\x9c\xe8\xae\xaa\x94\x54\xc8\x99\xf9\x4b\x9e\x28\x6e\x04\x3c\x33\x00\xfa\x23\xdf\xd8\x98\xd2\x7e\x9b\x46\x4a\xe8\x09\xdc\xc9\xd5\xd5\xdd\x5d\x5e\x2a\xa6\x5a\xfc\x5a\xd8\x39\x59\x3d\x24\x1a\x86\x06\x04\x3d\x7d\x7c\xf8\x0b\x6e\xe7\xaa\xd9\xdf\x23\xf8\xe5\xa2\xf3\x08\xdf\x55\x9e\x12\xd5\xdc\x3d\x32\xa9\x64\x63\x3b\x14\xb3\x80\xfc\x4d\x93\x59\x20\x5e\x7e\x9c\x08\x70\xbc\xd7\x33\x07\x2e\x93\xdc\x1e\x2a\x83\xa2\xcb\x92\x6a\xf1\x16\xd0\x34\x60\x06\xfd\x1f\xc4\x2a\x55\x02\xbc\x1e\x89\xcb\xde\x77\xd1\x58\x7d\xd8\x65\xc4\xc7\xa2\x78\x64\x9f\x53\xfc\xa1\x69\x6c\x74\xd9\xdd\x28\xac\xa9\xeb\xb5\xb0\x00\xc7\x48\x55\x8b\x07\x5b\x41\xb2\xa3\x7c\x85\xd6\xfd\x13\xb7\x92\xba\xe2\xf2\xee\x66\x63\xa8\xd6\x62\x6b\x1d\xe8\xcb\x97\xb0\xea\xff\x84\xe0\xaf\x5f\xf3\x50\x25\x35\x0f\xb4\xfd\x9f\xa3\x0e\x28\x80\x2f\xd2\x19\x31\xf4\xb1\x9e\x72\x19\xcc\x1c\x83\xc9\x4b\xe6\x17\x18\x95\xc9\x9b\x20\x0a\x86\xe6\x22\x3e\xf1\x9c\xe0\x9c\xb7\xe1\xe0\x32\xe1\x39\x87\xca\xef\x0a\xd0\x25\x85\x3d\x33\x44\xe7\x50\x3b\x0e\xd2\x69\x0d\x32\xc2\x74\x64\x93\xc9\x05\x6d\x35\xb0\xcf\x30\x4b\x85\xb3\x32\x3f\x68\xe4\xe4\x7a\x45\x23\x79\x76\x50\x4e\x84\x3d\x90\x4e\x1c\x2f\x4e\x5a\x91\x9e\x97\xa4\x65\x7c\xff\x4a\xce\x66\x6f\x79\xa0\xbf\x01\xcd\x58\x83\xa4\x3a\xa8\xbd\x75\x32\xa8\x8d\x66\xa7\x3c\x5c\x01\x5b\x48\x79\xe4\xe4\x6e\x69\x8f\x2d\x75\xa1\x0b\xf6\xc6\x04\x49\x25\x3b\x9a\xfc\xfa\xd7\xdf\x87\xc9\xd0\x3f\xff\x4d\x9a\x0e\xfd\xf5\x77\x5c\xe7\x60\x65\xa4\x54\xd7\x0e\xb8\x74\x43\x07\x05\x26\x57\x0e\xae\x63\x34\xbe\x64\xea\x0a\xf0\xa2\x13\x06\xdd\x12\x78\xc5\x14\xf4\x05\x88\x98\x65\xf2\xc3\x95\xaa\xf3\x29\xd6\x93\x0e\xc0\xc7\x23\x6c\x22\x90\x4f\x77\x21\xac\x23\xb0\x60\x6b\x9b\x02\xef\xa8\x1a\x98\x96\xdb\x0b\x7f\xfd\x1d\xcf\x43\xa3\x41\xda\xe9\x32\x47\xec\x05\x90\xf3\x13\x4d\xbf\xea\xa9\xca\x81\x5b\x08\x36\xaf\x15\xf1\x65\x9e\x5f\x70\x77\x0a\xe6\xec\x8b\x1b\xb3\x93\x8c\x0a\x71\xb8\x16\x17\xae\x0f\x97\xcb\xa0\x2e\x27\x44\xc1\x6d\x83\x99\x42\x65\x66\x5e\x45\x84\x4c\x9d\x12\x5c\x4c\xcc\xc2\x3b\x2f\x33\x05\xcd\x89\x5f\xc9\xa2\xd6\x05\x5b\x80\x14\xc3\xcc\x59\x27\x83\xea\xcc\x84\xc9\x11\x2f\x05\x65\xd6\x7a\x53\x11\xb4\x6d\x6e\xcc\x8e\x26\x50\x9b\x9b\xf4\x8f\xd6\x9c\xdc\x99\xc4\x18\xfa\x72\x85\xf0\xaa\xae\xda\xaa\xa0\xf1\xde\xfe\x9f\xef\xd6\xab\x76\x75\x03\x5d\xa1\x30\x42\x7f\x83\xc9\x6f\x30\x06\x21\x95\x3b\xb4\x72\x87\x53\xdf\x61\x0c\xc5\x69\xf2\x1a\x46\xaf\xbe\xfe\x28\x86\x1d\xe5\xbd\xdf\x75\x44\xb4\x2a\xee\x78\xdb\x50\xe5\x6c\x4a\x34\x49\x50\x65\x28\x61\xfc\xc6\x02\x07\x57\xa4\xea\x47\xbf\x25\xc9\xa4\x87\xe3\x30\x5e\x29\x43\x0f\xe7\x05\x59\xe6\xe3\x15\xb9\x4c\x1a\x04\x4e\x60\x68\x19\x1a\x04\xef\x05\xdf\x20\x0d\x70\x57\x72\x33\x49\x90\x18\x8c\x96\x12\x83\x0c\x48\xf8\x1e\xac\x00\x89\x0a\x8e\x10\x65\x48\x50\xfc\xca\x90\x55\x65\x57\x5c\x8a\x0a\x42\xa2\xa5\x48\x54\x22\x52\xf8\x1b\xb8\x0b\xd0\xa1\x70\x12\x2b\x47\xc7\xe9\x74\x61\xb1\x30\xc1\x42\xb0\x0d\x33\xdb\xa6\x68\x18\x81\xe9\x32\xe8\x69\x17\xbd\x57\xad\xe5\xb7\xb2\x99\x8d\x1d\xa5\x90\x52\x5d\x8d\xc0\x2e\x7a\xbf\x17\xdc\x5c\x3c\x9b\x00\x41\x53\xa5\xb4\x83\x20\x61\x02\xfb\x1c\xcd\x71\x00\xd9\x84\x68\x92\x2e\x27\x09\x1a\xe9\x68\x3f\x2b\xf6\x7e\x32\x9c\x45\x09\x81\x29\x02\x2f\xd5\x23\x08\xe6\x89\xb3\x2f\x42\x64\xf6\x38\x82\xa0\x14\x59\x4e\x12\x9c\x57\xd4\x6d\xf0\xf3\x09\x63\xa5\xf1\x8a\x0a\xb4\x4c\xd7\x88\x20\x04\x82\x94\x72\xc2\x08\x11\xcc\xcc\x82\x6a\xfe\x36\x47\x0c\x92\x2a\xe7\xe6\x11\x92\x57\xf5\x05\xb0\x6c\xfe\x78\xbd\x20\x87\x14\x45\x57\xca\xf5\x08\x15\x09\xd7\xee\xc2\x8c\x90\x1d\x4c\x10\x14\x86\x31\xdc\x27\x92\x12\x6b\x33\x77\x19\x94\x0d\xb6\x47\x3b\x0d\x02\xee\x91\x1b\xe8\xaa\x59\x9b\x77\x9a\xe4\x88\xc3\xfb\x5c\x9b\x1d\xd4\x7a\x5c\xa3\x4a\x61\x28\x83\x63\xe4\x13\x31\xe0\xea\xe3\x51\xb7\x39\xeb\x50\xcd\x6a\xb7\xd6\x1b\x76\xdb\x8d\x3e\x3e\xa6\xd8\xc7\xd9\xc3\x34\xae\xa1\x54\x22\xa8\x43\x84\x21\x66\xd5\xc1\x23\x43\x3c\xe2\x33\x86\x6d\xcd\x67\x23\x74\xda\xe9\xa3\xd3\x3e\x5e\x9d\x36\x5b\xd3\x21\x85\xb3\xd3\x41\xa7\xcf\xa1\xc3\xd6\x03\x3e\x1b\xb5\xfa\xed\x11\xd7\xe9\xb4\x8e\xba\x21\x95\x08\xe6\x10\xa9\x8e\x06\x8f\xad\x76\x17\xad\xb5\xb1\x06\x37\xc4\xab\xf3\x6e\xa3\xc7\xd5\xbb\x8d\xfb\x29\x37\x98\xa2\xad\x47\xec\xa9\xd7\x18\xb7\xfa\xdc\xb4\xc6\xf6\x99\xf1\x8c\x1a\xd6\xa8\xfe\x1c\x6d\x5d\x9d\xba\x61\xc5\x99\xc5\xe5\x74\x83\xbf\xc9\xef\xb0\x3f\xf7\xbb\x05\xb2\x37\x73\xdc\x40\xd8\x0d\x64\x9b\x1b\x50\xc0\x38\x8e\xb7\x69\x94\x99\xde\x95\xd9\x1a\x70\x11\x49\x23\x49\xc9\x0d\x84\xdc\x78\x3b\xbc\xf2\x05\x4d\xda\x1a\x70\xea\x20\x08\xb6\x07\x84\xc6\x00\x82\x56\x2a\x38\x0d\x13\x74\x85\x70\xb9\x72\x8c\xe9\x9f\xcf\x9e\x1b\xff\x7c\x07\x7d\xa6\x69\xfa\x3b\xed\xbc\x60\xf8\xf3\x0d\xf4\xf9\xb0\x61\xc5\x79\xa8\x0b\xb6\xfa\x06\x3e\xff\x37\xcd\x54\xe3\xf4\xd0\x18\x3d\xd4\xfd\xfb\x75\xf4\xe2\xf2\x61\xae\x88\x57\xff\x94\x41\x50\x21\x2a\x34\x8d\x55\xc8\x0a\xed\x36\x86\x5d\x7e\x2d\xdb\x99\x44\xeb\x0b\x5e\x14\x34\x41\x97\x5c\xe6\x10\x18\x86\xbf\xc3\xde\xab\x38\x8b\x58\x94\x02\x7a\xdc\x03\x11\xbc\x97\x50\x49\x98\x9e\xa3\x11\x4f\xa4\x77\xa0\x2e\x96\x0e\x41\xe4\x06\xfa\xec\x59\x14\xff\x02\x76\x0e\x8d\x53\xdd\x64\x29\xc3\x70\xb9\xc2\x51\xca\xb7\xc3\x5f\xa5\x67\x9f\xc2\x2f\xd7\x73\x4c\xa2\x62\x7a\x3e\x31\x52\x78\x5c\xe5\xf8\x91\xa4\xad\x35\xa7\xfa\x91\x60\x7b\x4d\x38\x02\xa1\x72\x85\x90\x70\x9c\xc4\x44\x54\x20\x69\x14\xa5\x00\x25\x53\x18\x42\x29\x0a\x41\xa0\x94\x08\x48\x19\xc1\x08\xaa\x42\x00\x5c\x81\x45\x41\xa1\x48\x82\xa2\x01\xae\xa0\x8a\x2c\x63\x88\x28\x10\xce\x8c\x01\xa6\x24\x01\x07\x92\x88\xe2\x15\x41\x41\x15\x8c\xa4\x25\x54\xc0\x84\x0a\x4d\x61\x24\xc0\x49\x20\xa0\x38\x8c\x11\xb2\x82\xcb\x40\x44\x14\x1a\xa7\x65\x09\x43\x30\x99\x26\x14\x52\xa0\x24\x42\xf2\x1c\x2b\x12\x9b\x7b\x90\x77\x18\x71\x87\x22\xf1\x29\x89\xf7\x35\xfa\x9d\xae\x50\x30\x42\xe5\x3e\xf5\x1d\x09\x52\xa9\x54\x6e\x20\x84\x74\xfa\xf3\xe8\x75\x03\x61\xce\x3f\xc4\xff\x17\x7c\x89\xec\xdf\x38\xac\x31\x0c\xc3\xd4\xde\x95\xce\xc4\xb2\x5e\xd4\xb7\xee\x87\x20\x75\x9e\x5f\xef\x25\x94\x68\x92\xea\xb0\x3e\x57\x26\xc0\x52\xb4\x7b\xac\xce\xd2\x9a\x22\xe8\x5b\x49\x24\x18\x0c\x7f\x7d\x6b\x55\xae\x9b\xbb\xb7\x4d\x55\xd6\xc6\x52\x0f\x58\x8b\x7b\x73\xcd\x8d\xde\x2d\x91\x7e\xa5\x27\x3d\x06\xc5\x25\xf5\x15\x76\x50\x33\xf3\xc1\x43\x6f\x3c\x64\xf6\x2f\x0d\x53\xb8\x37\xe5\x49\x7e\xac\x6e\x07\xcd\x5a\x85\x7c\x7e\xc5\xe4\x36\xd1\xe9\x4c\xb7\x4f\x92\xb1\x46\xc5\xf9\xc7\x6d\xa7\xf5\x48\xf5\xb7\xb7\xa3\xbe\xf4\xca\xac\xfa\x23\xa3\xbd\xea\xa1\xf7\x4f\x55\xe2\xf5\x75\x3a\x26\xb8\x97\xca\x33\xd2\x41\xaf\x97\x13\xac\x22\xe9\xfd\xee\x9c\x03\x1b\xec\xdd\xc1\xdc\xe3\xf0\xae\xf0\xb1\x46\x43\xc4\x18\xd6\x62\x12\x5e\x4f\xcc\x1c\xc1\x87\x0c\x53\x87\xef\x93\x1e\xff\x4f\xbf\x3c\xa3\x82\x53\xc6\x7d\x7c\x28\xa0\x97\x31\xe3\x2b\x12\x93\xe9\x8a\x42\x60\x24\x00\x64\x45\x46\x44\x94\x12\x09\xb1\x42\x2b\x28\x26\x28\x04\x86\x20\x22\x45\x90\xb4\x80\xe2\x8a\xa0\x20\x38\x8c\x09\x32\x2c\x12\xa8\x48\x62\x98\x08\x53\x22\xa0\xe9\xab\x7d\x74\x3d\xb6\x6a\x38\xd9\xd8\xb1\xef\x30\x8c\x51\x74\xca\x50\x08\x3d\xf5\x02\x08\x4e\xd0\x68\xc6\x48\x40\x0b\x8e\x04\x74\xf0\xf4\x8c\x70\x1b\xc2\x80\xc5\x7b\x6a\x86\xeb\xbb\xfe\xdb\x74\xdb\xc4\x1e\xd6\xc6\xcb\xf5\x5b\x83\xe9\xdb\x35\xa4\x83\xf6\xa8\x2a\x45\x3e\x4d\x41\x63\xb6\xc4\xae\xbb\x8f\xd8\xe3\xa4\xf5\xb2\x14\x49\xfb\x7a\xae\xbe\x4c\xf0\x0a\xd3\x79\x98\x9a\xcb\xeb\x36\xa7\x61\xbd\x47\x9a\xe3\xec\xa9\xdb\x73\xee\x48\x70\xdf\xb5\xf7\xff\x18\xd7\x58\xad\xc3\xe7\x77\x66\x30\x7c\xf1\x7a\xfa\x7d\xc6\x3d\x29\x6d\x62\xb6\x6b\xcc\xb6\xe8\x8a\x9a\x18\xdc\xb0\xb6\x7c\x7c\x22\x3e\x5e\x1b\xe6\xbb\xb1\x40\x9f\xe1\x97\xf9\xeb\x90\xeb\x32\xa6\xcd\xa1\x93\x3e\xda\x6d\x30\xf4\x44\x6f\xbe\xd9\xe3\xf9\xc7\xc3\x7c\xd0\xb4\xd8\x0e\xf7\xfc\x41\x76\x40\x6f\x79\xdf\x67\x34\x61\x3e\x93\xf1\x37\x77\xa4\xb4\x13\x46\x4a\xbd\x9d\x64\x6d\xff\xcf\x47\x0a\x5a\x7c\xa4\x20\x97\xb1\x72\x77\x85\xc6\x99\x2e\x38\xe1\x15\xa1\x29\xf8\x1b\x8c\x7c\x83\x11\x08\x86\xef\xdc\xbf\x54\x6b\x46\x28\x84\xcc\x7c\xe8\x44\x0c\x1c\xa5\x71\x9a\xa4\x50\x9a\xcc\x30\xf5\x64\x43\xf7\x38\xfa\xb7\xfb\x24\xfd\x55\x9d\x77\x54\x7c\x77\xbb\x1b\x77\xaa\x54\x5d\xaf\xd3\x2d\x14\xde\x3e\x57\xaf\x2d\x78\x61\x5b\xef\xed\xf7\x0f\x64\x2e\x8f\x67\x8f\x42\xf5\x5e\x68\x2c\x1c\x78\x36\xc1\x86\x93\x5f\x81\x0d\x33\x4c\xf5\xe5\x37\x08\x72\xd1\xd7\x95\x67\x4b\xf9\xf3\xa9\x02\x7b\x2a\x4f\x9d\x5e\xa5\x2c\x18\xa5\x66\x6d\x29\x03\x2e\x07\xcd\x51\x32\x76\x1a\x9a\x58\x02\x83\x9d\x86\x05\x8f\x25\x5a\xa7\x61\x21\x62\x93\xee\xd3\xb0\x90\xb1\x54\xe1\x32\x7b\x4c\x2f\x52\x46\xc8\x5e\x06\xbc\x81\xc8\xa2\xe5\x93\x94\x9d\x96\x67\x5b\x6c\xc8\x4a\x23\x26\xba\xff\x80\xbb\xb3\xa9\x8a\x9b\x0a\xa9\xba\x6d\x9c\x95\xf7\x38\x59\x9a\x57\x42\x3a\x33\x4d\x3d\xa7\x16\xb8\x57\x79\x41\xc5\x84\xed\x7c\xff\xbe\x12\x4a\x7a\x95\x8d\x2e\x03\xd3\x95\xe8\xc4\xaa\xde\xa5\x14\x73\x03\x15\xc9\xc0\xcf\x29\x3f\x9e\xa4\x3c\x7f\x60\xee\xdf\xe3\xbf\x54\x79\x67\x18\xe7\xef\x52\x5e\xce\x60\x4f\xd8\xeb\x7b\xc6\x52\x78\xa9\xdd\x8b\xa7\x3a\x94\xd4\xcd\x04\x89\x41\x10\x4f\x8f\x18\xb9\x88\xd0\x18\xa2\xb4\x30\x98\x8b\x08\x8b\x0e\xe7\xb4\xe0\x93\x8b\x07\x8f\xb9\x85\x53\xf1\xc4\x46\xc8\xc9\xfc\x90\x51\x3c\xe9\xe1\xb0\xec\x46\xc7\x4b\x04\xc4\xbc\xed\x22\x25\x42\x62\xea\xae\xc6\x0b\xd8\x70\x78\x09\x1e\xc3\x45\x40\xe3\x14\x89\xca\x32\x2e\x52\x0a\x5d\x51\x48\x1c\x97\x01\x0a\x53\x28\x85\x29\x88\x80\x60\xb4\x42\x60\x02\x50\x24\x54\x40\x00\x10\x49\xa4\x52\x21\x11\xa4\x22\x09\x54\x05\xa5\x94\xab\x7d\x19\xfb\x8c\x88\xb5\xcf\xe0\xb1\x20\x75\x49\x2f\x7f\xa1\x08\x96\x51\x1c\xf3\x9e\x46\x46\x90\x97\xf3\x74\xc8\x67\xa0\x62\xcf\x2b\xa3\x5d\x99\x34\xb5\xfa\x2d\x58\x48\x18\x35\x98\xdb\xad\x4e\xe7\x63\xf6\x50\x79\x7f\x50\x9f\xaa\x42\x6d\x43\x74\x89\x1e\xe3\xe6\x0c\x4c\x90\x92\x57\x63\x53\xf2\xd0\x67\x37\x11\x61\xfa\x68\xed\x96\xe9\xe3\xc4\x63\xb5\x8e\xd9\xad\x87\x46\x1f\x19\x61\x0c\xdc\x03\x2f\x83\xca\xfd\x88\xd4\x39\x84\xa1\xc1\x4c\x95\x77\x6d\xbf\x0e\xe0\xbe\x04\xea\xe5\xed\xe5\xdd\x45\xd7\xbb\xad\x6f\x1a\x34\x6a\xd9\x43\x03\x7e\x1e\x2a\xb6\xc9\x6e\xde\x46\x23\x13\x6d\x3c\xda\x42\x65\x71\x5b\xa7\x67\xe2\x6a\x36\xbd\xff\x50\xa7\x95\x67\xea\xe9\x76\xdc\x41\x9b\xcb\xdb\x5b\x73\x01\xe0\x67\x78\x3e\xac\xec\x5e\x44\xac\x5e\xe9\xea\xf4\x87\xb2\x36\x07\x1d\x6a\x72\x3d\xdd\x7d\x30\xc3\x9f\x3f\xaf\xc2\xf9\x5e\x33\x94\x27\x1d\xde\x86\x72\xfe\xfb\x69\xed\xba\x2f\x79\xef\x43\x6d\x87\x7b\xb0\xba\xfb\xf9\xfd\xd0\xc2\x7c\xe5\xc8\x2e\xe8\x0b\x8b\xe7\x6d\x4f\x98\x0e\x68\xb2\xfa\xa1\x58\x34\x80\x25\xc3\xe4\x9e\xe6\x1f\xd5\xd9\xfd\x4b\xc3\xe8\x04\x72\x32\xb5\x07\xe6\xed\x59\x8f\x93\x3d\x7a\xb1\x69\x0f\xaa\x17\xa6\x1f\xef\xd7\x42\xf4\xbd\x46\xae\x89\xd4\x42\xcf\xa8\xc7\x6e\x85\xa1\x9e\xb5\x05\x3b\x00\xb0\x3c\x9d\x52\x0f\x2d\xa9\x3e\xdc\x92\xc3\xdb\x77\xad\xf5\x2a\x61\xd3\x3a\x42\x08\xf7\x58\x5b\x45\x5c\x7d\x3a\xba\xf6\x3b\x61\x91\xa1\x8a\xd4\xd4\xd6\xe5\xb1\x7e\x3a\xfd\xb1\xd1\xa8\x00\xe9\x74\xfa\xbd\x18\xfd\xda\xc6\xc0\x0c\x1b\x27\x5e\x6b\x03\x76\xbb\x1e\xde\x62\x46\x8b\xbb\xfe\x40\xa8\xd1\x4e\xb5\x10\x4d\xe9\x35\x1e\x57\xc3\xd9\xc2\xdc\x8c\xaf\x27\x0c\x13\xb5\xb5\x05\x93\xae\xf3\x54\xfa\x21\xfb\x29\x31\xae\xf7\x36\xbd\x60\x12\xfa\xf0\x14\x19\x2e\xd9\x87\xe7\xea\xb0\x0c\x7d\x6f\x7c\xff\xf3\xab\x1c\x8f\x3b\x8d\x74\xf7\x31\x07\xf5\xb0\x22\xff\x9d\xb0\xe8\xba\xff\xfc\x99\x41\x28\x7e\x89\xa8\x80\xa2\x94\x84\xd1\x12\x89\x0b\x38\xae\x48\x94\x20\xca\xb8\x44\x93\x15\x84\xc6\x09\x52\x81\x31\x9a\xa6\x61\x52\x46\x50\x09\xa7\x48\x99\x82\x45\x1c\x46\x45\x45\x16\x51\x9a\x94\x49\x01\xf3\x8a\x84\xc8\x79\xf3\x5e\x24\x33\x6c\xb9\xa5\x6a\x1a\x4b\xaf\xee\x39\x4f\x0f\x85\x6c\x6f\x9e\xe5\x59\x6a\xb3\x5b\x69\x0d\xdf\x86\x2f\x62\x07\x6d\x31\xd8\xec\xe1\x79\x64\x76\x56\xcf\x73\x18\x56\x9a\x15\xab\xdb\xa6\x56\x30\x3b\x7a\xbf\x9f\xdd\x32\x73\x8c\xd9\x47\x2d\xf7\x95\x11\xb5\xbc\xd7\x09\xde\x33\x5c\x3d\xab\x3e\xbc\xbd\x37\x68\xe7\x11\x5b\xb7\xb1\xce\xfb\x4a\x18\x6c\x06\x72\x63\x3c\xdd\xca\x4c\x03\x88\x64\x7f\x08\xec\xdd\xb0\xd3\x9e\x09\x1f\x9a\x38\xee\xf5\x96\xab\x56\x87\xeb\xd6\x71\xeb\x75\xc9\xbe\x4e\x9f\xa4\xe1\x00\xd6\xae\xe7\xb7\xfd\xf5\xb5\x61\xcd\x56\x1c\x79\xdd\x98\x3e\x8a\xd6\x07\x45\x0c\xd1\xe7\x26\xfe\xd6\xeb\x15\x88\x5e\x11\x93\x8e\x46\xac\x90\xcc\xde\xda\x10\x13\x1d\xed\x55\xf5\xb6\x0a\x77\xe1\xfb\xe6\xce\x5e\xbe\x73\x88\xf6\x08\x0b\xbb\xb5\x81\xd0\x5c\x6b\xfb\xd6\xad\xed\xfa\x84\x5d\x65\xa5\x9a\x27\x23\xb6\xb0\xcd\xbe\xfe\x78\x5b\xc1\x0f\xed\x53\x22\x58\xf6\x68\x3f\x83\x7e\x63\x32\xab\x5a\x67\xd0\x67\x98\x7f\xcf\xdb\x85\x66\x13\x07\xcf\x5b\x3d\x5d\x17\x7d\xfd\x29\x53\xcc\x3c\x5d\x9c\xdb\x17\x8e\x2d\x5c\x4b\x31\x7c\xa5\x74\xf1\x0f\x25\xef\xac\xfb\xd5\x33\xf5\x8c\x8d\xa6\x5a\x6f\x3e\xac\xce\x57\xd7\xcf\x2f\x2d\x53\x7a\xa9\xa9\x8d\x95\x45\xcc\xe0\xe7\x7a\xfb\x69\xb9\x7b\x1e\xbf\x5f\x77\x3b\xc6\xa8\xa3\x35\xe7\x6c\x9d\xbe\x57\xb4\xdb\x8f\x57\xe5\xb5\xdb\x58\x3f\x83\xb7\xe5\x43\xb3\x49\xf5\xae\xaf\xa7\x9c\xb1\xdd\x74\x3f\xea\xcc\xef\xf5\xbc\x18\x29\x02\x0a\x56\x44\x8a\xaa\xa0\x0a\x5d\x81\x11\x49\x96\x80\x2c\x21\x28\x4c\x02\x14\x51\x68\x1a\xa5\x31\x89\xa6\x2b\x24\x2c\x20\x04\xc0\x71\x44\xc1\x29\x9c\xa6\x70\x4a\x80\x05\x8c\x12\xc4\xc3\x92\xe0\x19\x9e\x17\xcd\xf5\xbc\x38\x82\xd0\xe9\x9e\xd7\x7f\x1a\xce\x28\xcf\xf5\xbc\xb5\x58\x97\x1f\x79\xde\x92\xf9\x42\x86\xe7\x65\xb0\xed\x4c\xdc\x0e\xfa\xa2\xfe\xd4\x53\xab\xcd\x46\xa7\x7b\x3f\xdc\x28\xf7\xdd\xc5\x66\x62\xb5\xee\xb7\x3b\xc6\x1a\x0c\x88\x06\xfd\xf4\x4c\x90\x88\x30\xd7\xdf\xb8\xdb\xd6\xc3\xe8\x5e\x6c\x58\xac\xa4\xda\x4d\x71\xa1\xd2\xf2\xec\x41\xee\x8c\x1e\xdf\x56\x0f\xb3\x9a\xfa\xd1\x96\x57\xdd\x76\xfd\x7f\xcb\xf3\x9e\xeb\xf9\xce\x1c\xed\xaf\xd4\xed\xa4\x2e\x5d\xd0\xf3\xfe\xce\x5c\x21\xd1\xf3\xfe\x4b\x9e\x8f\xb9\x90\xe7\x3d\x35\x0a\xfb\x9e\x97\xab\x3c\xac\x2a\x93\x8f\x15\x81\x4e\xda\x8b\xd1\x72\xac\xee\xa6\x5d\x7d\x37\xc6\xbb\x2f\x54\x75\x27\x49\x8b\x6e\xfd\xe3\x7a\xa4\xcc\x1e\xaf\x81\x3d\xd3\x08\xea\x43\xd9\x22\xd3\xf1\x6c\x2b\x56\x5b\x6d\x73\xb4\xc2\xdb\x6f\xf3\x07\x6d\x3e\x7e\x99\x75\x09\xed\x61\x61\x58\xbb\xd6\x93\xba\x63\xde\x2f\xe1\x79\x53\x0f\xd7\x3b\x3e\x7b\x7e\x7f\xce\x6d\xf0\xab\xf0\xb2\x3f\x92\x0a\x61\xf4\xce\xc1\xac\xd7\xc3\xbf\x31\x8f\x13\x84\x06\xa3\x76\x8f\x19\x3d\x42\x1d\xf6\x11\xfa\xa2\xca\x79\xe7\xdf\x25\x9f\xc5\x7f\x36\xd7\x31\xac\x49\x9c\x27\x11\xce\xe5\x3e\xf6\xf3\xbe\xd3\xee\x32\x38\x5b\xba\x28\xd9\x24\xe1\x4e\x62\x0c\x9a\x72\xed\xe1\x94\x85\xbe\x1c\xc0\x6f\x42\x07\xbd\xdd\x44\x8e\x65\x2b\xa9\x9a\xcb\x74\x6b\x69\xc1\x4b\x75\x6a\xca\xea\x6a\xce\x12\xe6\x65\x25\x4b\x26\x92\x25\x69\x06\x5b\x85\x25\x4f\x2d\xa5\xe7\x56\xab\x2f\x2b\x7d\x1a\x99\x2c\xf9\x33\x59\xcb\xd5\x40\xf4\x2e\x19\x5f\x10\xf7\xde\x99\x62\x47\x02\x78\x57\xd4\x44\xb0\x40\x7d\x2e\x3e\x18\xa6\xe3\x36\xd7\x84\x44\xdb\x04\x20\x3c\xba\xd2\xb9\xf1\xaf\xc1\x39\x9b\x1f\xff\x08\xc5\x42\x1c\xa5\x8c\xeb\xd0\x15\x3e\xa7\xb2\x73\x40\x11\xe6\x24\x92\x2b\x44\xf9\xf1\x80\x6f\x8e\x0e\x28\x48\x62\xce\xbd\x84\xe8\x0c\xce\xdc\x73\x1a\x0a\xb1\x15\x3f\xdd\x21\x89\x1b\xff\xe6\xa4\x33\xf8\xf1\x30\x14\xe3\x28\x76\x74\xc4\xcd\xf1\x29\x11\x89\x43\x3e\x7c\x15\x54\x79\x4e\xfd\x28\xe1\x31\x1c\x43\x17\x66\x3b\xd8\x58\x1e\xe1\x38\xe9\xa4\xa5\x9b\xe0\x54\xa5\x34\x66\x0f\xbf\xf4\x3e\x93\x4d\x55\x2e\xcc\xe0\xe1\x74\x98\x9b\xc4\xe3\xa1\x72\x98\x0e\x6e\xef\xba\x04\xdf\x3e\xae\x30\xeb\x29\xa1\xea\x24\x49\x92\x05\x08\x2e\x2a\xbb\x84\x00\x3e\xae\x14\x9b\x3e\x51\x84\xe8\x51\x3f\xc7\x42\x84\xae\x65\x3b\x75\x34\x86\x70\x9c\xaa\xfc\x6c\x45\xc7\xee\x99\x3b\x57\xd7\x51\x74\x61\x96\x83\x2d\xac\x11\x1e\x93\x39\x3a\xbe\x2b\xef\x7c\xb6\x8e\x70\x16\x73\x6f\x49\x0c\x86\x6e\xfd\x3b\xb9\x5b\x0f\x38\x4e\x37\xc9\x3c\xf3\x4b\xba\xcf\xf0\x74\x86\x8f\x91\xc5\x38\x97\x41\x8c\xcf\xd8\x89\x71\xd9\x0c\x7a\x17\x34\x5e\x84\x3d\x17\x55\x21\xe6\x82\x5f\x43\xa7\xb2\x16\xbf\x70\xf2\x5c\xfe\x62\xf8\xf2\x98\x3c\x3e\x0a\x2f\x97\xd3\xcb\xe8\x31\x82\xad\x28\x97\xb9\xda\xbc\x0c\x6f\x85\x78\xca\xe6\x25\x76\xb3\xe9\x59\x1c\x45\x71\x15\xee\xd1\xe0\xcc\xbc\x44\xfe\x8e\x2e\x6b\x3d\x8b\xc3\x38\xb6\x62\xe3\xd6\x67\xf0\xe6\xe8\x98\xbf\x9b\xa3\x33\x26\x53\x84\xb8\x80\xdf\xf6\xf1\xe4\x71\x5c\x72\x76\x14\xbf\x63\xf7\x2c\xed\x96\x50\x6c\xae\xde\xf2\x2f\x0f\x3e\x53\xa1\xb9\x04\x22\x79\x5a\xf0\x63\xf9\x68\x66\xe4\x01\x96\xe0\xfd\x7c\x3b\xc8\xc2\x9d\xcf\x71\xc2\x28\xcb\xbe\x1a\xfa\x54\x7b\xc8\xc4\x9a\x3b\xed\x77\x80\x72\x18\x4d\xbc\x03\xfb\x32\xdc\x26\xa1\xce\x9d\xbe\x15\xb5\xe4\xe8\xa5\xdf\x17\x35\x86\x08\xea\x53\xe6\x9b\xc5\x6f\x39\xbf\xb8\xa2\x8f\xce\x77\xcf\x65\x3f\xd6\xa0\xb8\x30\xe1\x4b\xdf\x7f\x95\xfe\xc3\x47\xfa\xe7\x49\x12\x82\x2d\x2e\x44\xe2\x25\xf8\xbf\x4a\x9a\xc4\x9b\x0a\xf2\xc4\x4a\x6a\x54\x5c\xbe\xa0\x88\xf2\xcb\x64\xda\x9f\x93\x98\x27\x47\x6a\xb5\x2b\x8a\xfa\xf0\x23\x83\x5f\x31\xb4\xe3\xd8\x13\x13\xe0\xb2\x03\x3c\x8a\x34\x9a\x42\x5d\x68\x84\x67\x91\x28\x22\x43\x4e\x5e\x97\x49\xec\x72\xe1\xeb\x18\x71\x21\xde\xf3\x83\x58\x38\xd9\xfe\x15\x66\x73\x8c\xff\xe4\x54\xdf\x3b\x33\x2b\x08\xe4\x41\x85\x91\x17\x0d\xe3\xe5\x64\x2d\x67\xe0\xcc\x9d\x22\x7c\xf9\x12\x1c\x85\xff\xed\xcf\x3f\xa1\x2b\xcb\xd0\xe4\xd0\x6a\xda\xd5\xdd\x9d\x0d\xb6\xf6\xd7\xaf\x37\x50\x3a\xa0\x64\xc8\xc5\x00\xbd\x5a\x7c\x3a\xa8\x68\x6c\x16\x4b\xbb\x10\xf9\x08\x68\x36\x03\x11\xd0\x18\x0b\x5f\xa1\x59\x8b\x1d\xb1\x9e\x91\x41\x3f\x21\x0c\x2b\xbc\x10\xad\xca\xbc\x12\x5a\x26\x6a\x74\x7e\xcf\x72\xb4\x4f\x16\x6a\xf4\x47\x6c\xbb\xc9\xed\x97\x80\xa0\x11\xdb\x60\x47\x2c\x57\x63\xe3\x97\xd1\xbb\x4f\xfb\x1c\x34\x1d\xd4\x1d\x93\x19\xb1\xde\xfd\x8f\xce\x57\x75\xb6\xcb\x4e\x58\xa8\xc6\x8c\x6b\x4c\x9d\xcd\xbe\x9b\x20\xf6\x91\x8f\x95\x62\x2e\xa7\x8c\x28\x9d\x9c\x45\xb2\x34\x4e\xa2\xfa\x89\x97\x8d\x12\x95\xe5\x4f\xf4\x73\x56\x14\x53\x35\xe1\xa7\xb2\xff\xba\x1e\xc2\x7c\x24\x69\x21\xa8\x12\x64\x1b\x4c\x39\x0d\x1c\x17\x95\xfe\x45\x35\xa4\x30\x13\xd5\x45\x42\x19\xec\xb2\x46\x11\x2f\x71\xfc\x2f\x28\x24\xdd\x34\x8e\x6a\x48\x45\xac\x03\x12\x64\x19\xc8\xd0\x4a\xd0\x37\x82\xa6\xed\x22\x9c\x26\xc6\x46\x87\xcd\x40\xe1\xab\xcd\x16\xc8\xd0\x9b\x60\x4a\x4b\xc1\xfc\x42\xd2\x5f\xfd\x1d\x41\x0e\x8c\x02\x0e\xa3\x35\x19\xee\x47\x22\xb1\xd0\x0c\xc2\x41\x13\xbd\xd0\xa5\x14\xa6\x20\x54\xba\x1c\x7b\xd5\x89\xd4\xf6\xbe\x51\x0c\x0c\xcb\x5e\x98\x60\x3c\xec\x42\xb2\x60\x0b\xce\x60\x83\xe4\xcd\x6a\x0d\x49\xc6\x6a\xad\x01\x1b\xb8\xbd\xf9\x7f\x01\x00\x00\xff\xff\x26\x92\x5a\x0a\x91\x90\x00\x00") func account_mergeHorizonSqlBytes() ([]byte, error) { return bindataRead( @@ -126,7 +126,7 @@ func account_mergeHorizonSql() (*asset, error) { } info := bindataFileInfo{name: "account_merge-horizon.sql", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} - a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x18, 0xca, 0x3, 0x19, 0xf1, 0x1, 0xa2, 0x8e, 0x1e, 0xde, 0xda, 0x93, 0xb5, 0xf9, 0x23, 0xce, 0xed, 0xbc, 0xbe, 0x70, 0xd5, 0x14, 0x0, 0xc6, 0xd1, 0x3, 0xd2, 0x9, 0xb2, 0x1a, 0x86, 0xe5}} + a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x70, 0x9e, 0x44, 0x23, 0x76, 0x51, 0x66, 0xae, 0xb0, 0xae, 0x26, 0xac, 0x5a, 0x20, 0xad, 0xf0, 0xf2, 0x54, 0x1f, 0x1d, 0x9c, 0xa8, 0xf5, 0x5d, 0x8c, 0xf1, 0xd0, 0xf8, 0x95, 0x51, 0x1a, 0x56}} return a, nil } @@ -150,7 +150,7 @@ func baseCoreSql() (*asset, error) { return a, nil } -var _baseHorizonSql = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\x7d\xf9\x6f\xe2\xc8\xf2\xf8\xef\xf3\x57\xb4\x46\x2b\x25\x79\x93\x99\xf8\xc6\x64\x3e\xf3\x24\x03\x26\x90\x70\x85\x23\xd7\x6a\x65\xb5\xed\x36\x38\x31\x36\xb1\x4d\x80\x59\xbd\xff\xfd\x2b\x5f\x60\x1b\x9f\xc0\xcc\xdb\xaf\xf4\xd0\x6a\x36\xe0\xea\xba\xba\xba\xba\xab\xba\xba\xfd\xf5\xeb\xa7\xaf\x5f\xc1\xc0\xb0\xec\xa9\x89\x46\xf7\x1d\x20\x43\x1b\x8a\xd0\x42\x40\x5e\xce\x17\x9f\xbe\x7e\xfd\xe4\x3c\x6f\x2c\xe7\x0b\x24\x03\xc5\x34\xe6\x3b\x80\x0f\x64\x5a\xaa\xa1\x83\xea\x37\xe6\x1b\x1e\x82\x12\x37\x60\x31\x15\x9c\xe6\x31\x90\x4f\x23\x7e\x0c\x2c\x1b\xda\x68\x8e\x74\x5b\xb0\xd5\x39\x32\x96\x36\xf8\x01\xb0\xef\xee\x23\xcd\x90\xde\xf6\x7f\x95\x34\xd5\x81\x46\xba\x64\xc8\xaa\x3e\x05\x3f\xc0\xd9\x64\xdc\x64\xcf\xbe\x07\xe8\x74\x19\x9a\xb2\x20\x19\xba\x62\x98\x73\x55\x9f\x0a\x96\x6d\xaa\xfa\xd4\x02\x3f\x80\xa1\xfb\x38\x66\x48\x7a\x13\x94\xa5\x2e\xd9\xaa\xa1\x0b\xa2\x21\xab\xc8\x79\xae\x40\xcd\x42\x11\x32\x73\x55\x17\xe6\xc8\xb2\xe0\xd4\x05\x58\x41\x53\x57\xf5\xe9\x77\x9f\x77\x04\x4d\x69\x26\x2c\xa0\x3d\x03\x3f\xc0\x62\x29\x6a\xaa\x74\xe9\x08\x2b\x41\x1b\x6a\x86\x03\xc6\x75\xc6\xfc\x10\x8c\xb9\x5a\x87\x07\xed\x26\xe0\x9f\xda\xa3\xf1\x08\xf4\x7b\x9d\x67\x1f\xfe\xdb\x4c\xb5\x6c\xc3\xdc\x08\xb6\x09\x65\x64\x81\xc6\xb0\x3f\x00\xf5\x7e\x6f\x34\x1e\x72\xed\xde\x38\xd4\x28\x0a\x28\x48\xc6\x52\xb7\x91\x29\x40\xcb\x42\xb6\xa0\xca\x82\xf2\x86\x36\xdf\x7f\x07\x41\xc9\xfd\xeb\x77\x90\x74\xec\xea\xf7\x09\xe8\x51\x2b\x2f\x9d\xc7\xa0\x63\xc8\x59\xc4\x42\x50\x3b\xe4\x2e\x78\xbb\xd7\xe0\x9f\x42\x90\x3e\x5a\xdb\x5c\x5a\xb6\xa0\xa9\xba\xc3\xda\x46\xb0\x37\x0b\x24\x48\x86\x8c\x04\xd5\xb2\x96\xc8\x2c\xd5\xf8\x80\x26\x3b\x45\xe4\x35\x83\x32\x12\x90\xa2\x20\xc9\x76\x1b\x1a\xa6\x8c\x4c\x41\x34\x8c\xb7\xec\x86\x96\x3a\xd5\x91\x19\xa6\x95\x0d\x6f\x28\x8a\x0f\x6e\x21\x4d\x73\x06\xb6\xab\xd2\x32\x8d\xf2\x54\xb0\x83\xd6\xa0\x65\x0b\x73\x43\x56\x15\x15\xc9\x82\x86\xe4\x69\xf1\xb6\xe2\x72\x53\x90\x3b\x55\x97\xd1\x5a\x08\x99\xa1\x6e\x41\xd7\x25\x59\x82\xa1\xe7\x6a\x3e\xda\xda\x58\x20\x13\x6e\xdb\x3a\xd6\x72\x44\xeb\x1d\x27\x47\x71\x51\xae\xad\xa7\x65\xb7\xa1\x85\xde\x97\x48\x97\x4a\x89\x10\x6a\xbe\x30\xd1\x87\x6a\x2c\x2d\xff\x37\x61\x06\xad\xd9\x81\xa8\x8e\xc7\xa0\xce\x17\x86\xe9\x38\x4e\x7f\xf6\x3b\x14\xcd\xa1\xba\x94\x34\xc3\x42\xb2\x00\x4b\xd9\x62\x30\x9e\x0f\x30\x25\x7f\x30\x1f\xc0\x74\xb8\x25\x94\x65\x13\x59\x56\x76\xf3\x99\x6d\xca\xee\x0a\x41\xd0\x0c\xe3\x6d\xb9\x28\x00\xbd\xc8\x63\xc9\x83\x82\xaa\x59\x12\x71\x30\x3d\x16\x6e\xe0\xb8\x4a\xc7\x67\x14\x03\x0d\xd0\x1f\xd0\xa4\x90\x77\x0d\x1a\xb9\x93\x60\x09\x22\xe1\x49\x33\xaf\xc5\xc2\x69\x30\xb3\x73\x7b\xc0\x8a\x38\x20\x67\xfa\xca\x6f\xe1\x8f\xd3\x22\xc0\x86\xc7\x87\x91\x0b\xa8\x5a\xb6\x60\xaf\x85\x45\x3e\x4a\x07\xd2\x58\x14\x85\x44\x45\xc1\x82\xd9\x34\x1b\x18\xad\x17\x42\x78\x75\x51\x70\xbe\x4f\x68\xe6\x2c\x2f\xb2\x1b\x89\x9b\x42\x93\xa1\xa3\xdf\x5c\x8f\x59\x74\xe2\xf7\x98\x2c\x28\xd5\x16\x38\x5f\x96\xad\xbb\x51\x75\x45\x73\x27\x2d\x41\x46\x96\xad\xea\xee\xdf\x05\xdb\xce\x8c\x39\x12\x64\x63\x0e\xd5\xa2\x2d\x9c\x80\x29\xbc\xcc\xd4\xe1\x1c\x15\x59\x66\x86\xd6\x67\x19\xcb\xcc\xf0\x2a\x6e\x51\x70\x01\xeb\x2d\x5d\x32\x90\xfa\x6b\x9b\xa2\xf8\xde\xd0\x46\xf8\x80\xda\x12\x09\x8e\x5f\x47\x19\x88\x63\x90\x85\x29\x24\x2c\x99\x84\x05\x34\x6d\x55\x52\x17\x50\xcf\x5c\x87\xe7\x35\x2d\xcd\xc3\x76\xc9\x53\x96\x83\xe4\x86\xa5\xe9\xbb\x16\x5f\x84\x9e\x07\xf8\xcb\xf1\x7b\x23\xd0\x8d\x54\xbc\x3f\xdd\xc8\xc5\x8f\xe2\xdc\x11\x2c\x14\xe4\x60\x6a\x98\x0b\x61\xae\x4e\xfd\x15\x65\x06\x0b\x31\xc8\xc2\x32\xc6\x7c\x60\x06\x85\xb8\xb7\x2c\x4a\xa1\x7c\x70\x58\x18\x73\xe0\x50\xfc\x40\x2a\x0b\x7d\x0c\xb4\x34\x8d\x22\xb8\x4b\xf3\xed\x38\xc2\x22\x88\x5d\x87\x99\x85\xbd\xa8\x53\xf0\x5a\xd7\xfb\x9d\x49\xb7\x07\x54\xd9\xa3\xdd\xe0\x9b\xdc\xa4\x33\x2e\x88\x3b\x65\xb0\x9f\x00\xb3\x3f\xcc\xb2\x31\xb9\xdf\x52\x10\x85\x3c\x7f\x36\xa0\xe7\xcd\xb3\x61\x62\x8e\x39\x1b\x38\x29\x80\xf5\x5b\x8c\xf8\xfb\x09\xdf\xab\x1f\xd0\x5b\xce\xd4\x68\xa1\xf7\xd2\x94\x23\x48\x0a\xb7\x96\x51\x91\x50\x03\x4e\xa7\x8e\x05\x6c\xa3\x42\x3b\x7f\x0d\x19\x34\x13\x97\xd2\x1b\xb2\xa3\xd1\x41\x21\xb6\x04\x06\xc3\x30\xcc\x6f\xd1\x9c\xf4\xea\xe3\x76\xbf\x97\xd0\xfb\x86\x30\x57\x35\x4d\xb5\xce\x9d\xb0\xc5\xb2\xe1\x7c\x01\x56\xaa\x3d\x03\xce\x57\xf0\xd3\xd0\xd1\x25\xd0\x97\x73\x64\xaa\xd2\xc5\xc1\xc8\x8c\xa5\x9d\x81\xaf\xe8\xd0\x29\x6e\x1b\x29\x33\x64\x19\xcb\x48\x46\x51\xac\xad\x1f\x44\x17\x03\xf6\x23\xe6\xc2\xb2\xf9\xb3\x65\x19\x59\xbc\x26\x05\x61\x7d\xef\x59\x9c\x9f\xed\x6a\xb8\x00\x47\xb1\xf9\x36\x1b\x38\x36\x75\x66\x03\x17\x07\x8c\xcd\x69\x05\xa1\x9d\xc9\xa4\x18\xa8\x0f\xc5\xdd\xdc\x0c\xf9\x1b\x6e\x9c\x00\x39\x57\x75\x61\x61\xaa\x12\x3a\xf7\x47\xc2\x9f\x7f\x5d\x14\x68\x05\xd7\x07\xb4\xd2\xa0\x65\x9f\x43\x7d\x83\x34\x77\xb7\xa4\x40\x0b\x45\x35\x13\x9b\xa4\x0f\xfb\xad\x3c\x8e\xc7\xda\x71\xb7\x1d\xe8\x3b\x46\x33\x70\x04\xd2\x1d\x81\xc3\x4d\xbe\x3a\xcd\x77\xcc\x5f\x82\x32\x82\xb8\xa2\x17\xc0\xc0\x3f\x8d\xf9\xde\x28\x86\x42\x5b\x4c\xad\x77\x2d\x18\x37\xf5\x16\xdf\xe5\xf6\x28\x7c\xff\xe4\x6d\x94\xf5\xe0\x1c\x5d\x07\xbf\x81\xf1\x66\x81\xae\xfd\x26\xdf\xc1\x48\x9a\xa1\x39\xbc\x06\x5f\xbf\x83\xfe\x4a\x47\xe6\x35\xf8\xea\xee\x9f\xd5\x87\xbc\xd3\x5f\x3e\xe6\x00\xdf\xa7\x08\xc6\xe8\x43\x1f\x71\xbd\xdf\xed\xf2\xbd\x71\x06\x66\x0f\x00\xf4\x7b\x51\x04\xa0\x3d\x02\x67\xc1\xce\x58\xf0\x9b\xe5\x22\x39\x8b\x53\x0e\xc4\xf7\x69\x6e\x35\x94\x2b\x4f\x44\x97\xbd\xfe\x38\xa6\x4f\xf0\xd8\x1e\xb7\xb6\x6c\x85\xb7\xc8\x22\xe4\x77\x58\x62\x8c\x94\x11\x7e\x0f\x89\xab\x80\x41\xe7\x6a\x31\x1d\xdd\x77\xc0\xc2\x34\x24\x24\x2f\x4d\xa8\x01\x0d\xea\xd3\x25\x9c\x22\x57\x0d\x05\xb7\xf4\xc2\xec\xe6\x1b\x9a\xcf\x7e\x60\xab\x3b\xfe\x83\xbe\x4d\xd2\xe5\xd6\xb2\x73\xf1\x83\x21\x3f\x9e\x0c\x7b\xa3\xd0\x6f\x9f\x00\x00\xa0\xc3\xf5\x6e\x26\xdc\x0d\x0f\x5c\xe9\xbb\xdd\x89\xe7\xec\x46\xe3\x61\xbb\x3e\x76\x21\xb8\x11\xf8\x43\xf8\x03\x8c\xf8\x0e\x5f\x1f\x83\x3f\x70\xe7\x5b\xbc\x37\x72\x07\xe2\x71\xd2\xe5\xa1\x3f\x99\x70\x44\x92\x70\x45\x3c\xd5\x71\xf2\x15\xa0\xb0\x15\x71\xfb\xd3\x41\x12\x9e\x7f\x02\xa0\xce\x8d\x78\xf0\xd8\xe2\x7b\xe0\x0f\xfc\x4f\xfc\xaf\xab\x3f\xf0\x3f\x89\xbf\xfe\xfd\x07\xe1\xfe\x4d\xfc\x49\xfc\x05\xc6\xde\x43\xc0\x77\x46\xbc\xa3\x14\xbe\xd7\xb8\x48\xd4\x4c\x81\x79\xe0\x48\xcd\xe4\x53\xf8\xd5\x9a\xf9\xbf\x43\x34\xb3\x3f\xa7\xfa\x7a\xd8\xce\xc3\xc5\x14\xb1\x9b\xb6\xf7\x30\xba\x1c\x03\x30\x72\x74\x05\x7e\xec\x3c\xc0\xa5\xf7\xf3\xf8\x79\xc0\x83\x1f\xe1\x11\x71\x91\x34\x6a\x4f\xca\x63\x1c\x61\x8c\xc5\x60\x18\x17\xe7\x30\x71\x09\x74\x2c\x97\x49\x48\x63\x9c\x46\x06\x64\x94\xdd\x9d\x95\xed\x73\x9b\xb4\xcc\x3b\x9a\xdb\x04\xa4\x71\x6e\xc3\x83\x24\x93\x5b\x67\xe6\x92\x91\x02\x97\x9a\x2d\xd8\x50\xd4\x90\xb5\x80\x12\x02\x3f\xc0\xd9\xd9\xf7\xe8\x53\x27\x8a\x13\x0c\x55\x0e\x55\xbb\x44\x64\xdd\x2e\x7e\x7d\xf9\xdc\xd1\x55\x4c\x36\x6f\x20\x6e\x33\x46\x9e\x2c\xbb\x3c\x37\x90\x66\xd0\x84\x92\x8d\x4c\xf0\x01\xcd\x8d\xaa\x4f\xcf\x69\xe6\xc2\x5d\x29\xf4\x26\x9d\x8e\x27\x9f\x08\x35\xa8\x4b\x08\x88\xea\x54\xd5\xed\xf8\x43\x6f\x5f\x5d\x53\xa1\xa8\x6a\xaa\xad\x22\x2b\x19\x2e\x28\x0f\x28\x00\xe8\xed\x32\x0b\xfa\x72\x2e\x22\x33\x19\x48\x5f\xce\x05\x6b\x29\x22\xdd\x36\x1d\x44\xaa\x6e\xa3\x29\x32\x63\x40\x89\x3b\x08\x85\x24\x56\x34\x38\x4d\xc3\x1a\xda\x5b\x48\xc0\x45\x12\x71\x5c\x73\x68\xd9\xc8\x14\x56\x48\x9d\xce\x6c\x60\xcd\xa1\xa3\x87\xb8\x3c\xf6\xcc\x44\xd6\xcc\xd0\x64\x41\x33\x56\xf9\x40\x73\x24\xab\xcb\x79\x3e\xdc\x4c\x9d\xce\xd2\xa0\x92\x8a\x29\xf6\x44\xde\x1f\x77\xd1\x98\xed\x58\x83\xf4\xd2\x8d\x9e\x55\xfa\xe9\x9b\x37\xb4\x49\xd0\x2b\x4e\x63\x71\xc5\x96\xb4\x62\x1d\xce\x51\x02\x20\x43\xc5\x01\xdd\x0c\x5b\x02\x64\x75\x8f\x83\x63\x55\x18\x04\xc9\x47\x6b\x31\x48\x36\x17\x18\xde\xfb\xf2\x7a\x8d\x81\x8d\xd6\x71\x13\xf1\x6d\x36\x79\x1c\x58\x0b\x43\xb7\x0c\x33\x59\xf7\xae\xd0\x3e\xaf\x5e\x12\x6e\x2f\xdb\x2d\x6e\x84\x00\x45\xbf\xb7\x2f\xca\x64\xd4\xee\xdd\x80\xda\x78\xc8\xf3\xe7\x3e\xdc\xbe\x22\x43\x69\x89\x83\x75\x18\xda\x0a\xf0\xd4\xa7\xca\xc9\x3e\x07\xce\x1d\x0e\xf7\xe5\x4d\x70\x4d\x5b\x7f\x9b\xac\x3a\xcf\xbd\xa4\x8d\x5e\x63\xae\x25\x28\x95\xa0\xe9\x8b\x0c\x9b\x8a\xa7\x73\x0e\x55\x47\x7c\xef\xc5\xb7\xa8\xed\x96\x51\x8a\x44\xbb\xed\xa5\xa4\xb1\xbb\xe7\x13\xc3\xfb\x4e\x85\x06\xaf\xaf\xfb\x04\x1b\xcd\x54\xf7\xbe\x9e\xe2\x39\xb2\x43\xf5\x14\xdf\x05\xdb\x9a\x4e\x02\x8b\x70\xb1\xd0\x54\xb7\xd8\x07\xa4\xa5\x81\xf7\x19\x4d\xcb\x00\x06\xf9\x0c\x3f\x75\x58\x8c\xe7\x6d\xa2\x31\x05\xab\xbf\x8c\xe1\x86\x63\x2f\x23\x80\xbb\x3f\xb4\x7b\xf5\x21\xef\x86\xef\xb5\x67\xff\xa7\x5e\x1f\x74\xdb\xbd\x07\xae\x33\xe1\xb7\xdf\xb9\xa7\xdd\xf7\x3a\x57\x6f\xf1\x00\xcf\x13\xe6\x60\xb5\xc7\x11\xed\x0d\x59\x7f\x53\x06\xe8\x68\x6d\x7f\x40\xed\xfc\x2c\x45\xe2\xb3\xeb\x6b\x13\x4d\x25\x0d\x5a\xd6\x9e\xad\x79\x45\x4e\xc9\xbe\x33\xe8\xa8\x2d\x27\x92\x06\xd5\xb9\xb3\xba\x13\xfc\x65\x92\x05\xce\xe7\x50\x5f\x42\x4d\xdb\x38\xa8\x90\x7c\x91\xda\x0b\xfb\x6d\x7f\x5d\x7f\x24\xaa\x31\x89\xf9\x14\x1f\x98\xae\xd9\x54\x29\xc2\x3a\xf6\x54\xbb\x07\x2a\xc4\x47\x4c\x78\xe2\x98\xf4\xda\xf7\x93\x60\xfe\xf8\x1c\xad\x4a\x4b\x20\xea\x56\xb6\x7d\x76\x26\x93\x0c\xf1\xbc\x69\x45\xb4\x4d\x84\xc0\xb9\x2a\x5f\x7c\x3f\x9c\x58\x92\x30\xa5\xc8\x27\x21\xb8\x48\xeb\xaa\xdd\x96\x49\x6a\xa7\xed\x83\xa6\x4d\x65\xa9\x1c\x26\xb4\x28\xda\x23\x59\x0c\x7a\x7d\x63\x45\xb4\x93\x29\x50\x44\x4f\x89\x72\x5d\x66\x0a\xb1\xeb\xd7\x83\x78\x0d\x53\x3a\x21\xd3\x47\x72\x75\x34\x2f\xa5\x0c\x2e\xbc\x7b\x9b\x6b\x72\xd1\xda\xe4\xdf\x67\x74\xd9\x4c\x26\x99\x5d\x8e\x58\x89\x7a\x8b\x49\x77\x94\xe9\xe5\x73\x1c\xa5\x76\x62\xe6\x8f\xe6\xee\x04\x1c\xa5\x99\xe1\xa7\x76\x6f\xc4\x0f\xc7\xa0\xdd\x1b\xf7\xb3\x9c\xa8\x3b\xbd\x8d\xc0\x39\x7e\x09\xce\x30\xff\x83\x57\x58\x96\x60\x14\x51\x41\x24\x59\x45\xb8\x42\x4b\x34\x49\xe1\x15\x89\x51\x90\xac\x20\x42\xc2\x68\xc4\x8a\x48\xc2\x29\x12\x23\x71\x8a\x44\x12\xc5\x88\x24\x5b\x65\x71\x11\xab\x4a\xa4\x52\x3d\xbb\xf8\xfe\xc9\x4f\x4e\xee\xf6\x15\xbe\x59\xa8\xe8\x54\x77\x09\xf0\x4b\x60\x9b\x4b\x74\xf1\xdd\x59\x1d\x8c\x67\x08\xec\xb6\xd6\xaf\xc2\x35\x18\x00\x9a\x08\x4c\x0d\x27\x70\xb0\x0d\x20\x22\xb0\xd4\x4d\xa4\x41\x1b\xc9\xce\xf7\x2d\x85\x20\xeb\x62\x5d\x02\x71\x69\x03\xd5\x06\xb2\x81\x2c\xfd\xcc\x06\x73\x68\x3b\x8b\x12\xc5\x70\x62\x36\xcb\x56\xf5\x69\xa2\xe2\x32\xdd\xc3\x56\x85\x04\xcb\x52\x55\x8c\xae\xb2\xf4\x25\xc0\x2f\xbe\x1f\x8e\x89\xa5\xd9\x6a\x95\x64\x19\xb6\x9a\x8e\x28\xc7\x58\xf6\x99\xa2\x8e\xc6\xb5\x65\x8b\xf5\x50\x25\x2f\x4b\xbd\x2d\xfc\xa3\x17\xa5\x5e\xb1\xd0\x76\x05\x95\x15\x2a\xb9\xb1\x54\x91\xe8\xfc\xd7\x45\x56\x19\x31\x47\xa4\x0a\xe2\x44\x11\x47\x18\xe7\x6f\x8b\x37\xb2\x04\x01\xfd\xc7\x1e\xdf\x00\xb5\xe7\x1c\x89\xbc\xe2\xaf\x6c\x81\xb6\xb8\x62\x8f\xbf\xa9\x72\x1a\x6f\x41\x69\xca\xb1\x56\xe7\xe3\x89\x4d\xc8\xa1\x1c\x50\xe6\x64\x9c\xbf\x56\xfc\xec\x16\xbb\x7f\x4e\xb1\xe6\x8c\x9c\x80\x8c\x6c\xa8\x6a\x16\x78\xb5\x0c\x5d\x4c\x37\xb6\xa0\x9e\xe7\x58\x3d\xf8\x78\x7c\x3d\x04\x59\xe4\x14\xde\x42\x07\x88\x0a\x8d\xc2\xa4\xb3\x4b\xc9\x0d\x7d\xb5\x84\xbd\x93\x9b\xba\x08\xf8\x08\xc2\x28\x2c\x46\x21\xe4\x64\x0b\xc1\x6f\x0f\x10\x81\x8c\x6a\xb0\x78\x1b\x13\x39\xf3\x4c\x4e\x23\x0f\x76\xb9\x90\x0b\xc3\x6e\x4d\xc7\xff\x1a\x3b\x5b\xb5\x27\x0b\xbe\x97\xf2\xb2\xa1\x26\x48\x86\xaa\xa7\xec\x09\x28\x08\x09\x0b\xc3\xd0\x52\xb6\x20\xa0\x85\x04\x05\xa5\xf5\xb5\xfb\xd8\x44\x16\x32\x3f\xd2\x40\xe6\x70\x2d\xd8\x6b\xc1\x4d\x7b\xa9\x3f\xd3\xa0\x16\xa6\x61\x1b\x92\xa1\xa5\xca\x15\xef\xa3\xc0\x58\x10\x94\xfd\x04\xab\x9f\x3a\x5d\x4a\x12\xb2\x2c\x65\xa9\x09\xa9\x86\xe2\x0b\x0e\x55\x0d\xc9\x79\x50\x3e\xeb\x29\x26\x94\x3e\xf4\x52\xca\xf0\x8e\x1d\x89\x29\xe5\xb8\x39\xf3\x62\xf9\xe8\x35\xdd\xc7\x95\x15\xf9\xb4\x53\x5d\x26\x8d\xdf\x35\xf5\x95\x12\xf4\xc8\xa9\x30\x93\xd6\xfe\xd4\x98\x0c\x9e\x31\x55\x86\x8a\x54\x4f\x66\x9b\x79\xd9\xfe\x22\x11\xad\x9b\xd8\x95\x3c\x51\xdc\x59\xf2\xc8\x49\xd2\xf7\x0e\xc6\xd2\x94\xb6\xc7\xf7\x52\xa6\xa7\xc0\xe5\x9c\x9d\x5d\x5f\xa7\xef\x48\xa4\x8f\x03\xbf\xba\xfa\x58\x75\xfa\xa7\xf9\xcb\xe6\x9f\xb2\xd7\x14\xbe\xdb\x3c\x64\x86\x73\xab\xe8\x53\xc9\xc6\xee\x12\xc8\x02\xf2\xaf\x37\xc8\x02\xf1\xb6\x24\x12\x01\xf6\x6f\x65\xc8\x81\xcb\x24\xb7\x85\xca\xa0\xe8\xb2\xa4\x5a\xfe\x81\x7a\x20\x1a\x86\x86\xa0\x1e\xcc\x5b\xaa\x84\x04\x3d\x32\x47\x7b\xbf\x45\xe7\xed\xdd\x29\x53\x21\x36\xa3\x47\xce\xb9\xc6\x1f\x9a\xc6\x52\x97\xdd\x2b\x3d\x34\x75\xb1\x80\x53\xb4\x8f\x54\xb5\x04\xb4\x86\x92\x1d\xe5\x2b\x74\xc0\x24\xf1\xd2\x07\x57\x5c\xc1\xbd\x16\x04\xd4\x5b\x7c\xfd\x0e\x9c\x9f\x87\x55\xff\xef\x1f\x00\xbb\xb8\xc8\xc3\x95\xd4\x3e\x50\xf7\xff\xed\xf5\x40\x01\x7c\x91\xde\x88\xa1\x8f\x75\x95\xc7\xe1\xa7\xb4\xb8\xf3\xa4\x83\xd0\x3b\x92\xe0\x0e\xc5\xdd\x78\xf1\x6d\x45\x37\x6c\xa0\x2f\x35\xcd\x91\x2d\xd1\xbe\xc3\x00\x69\x46\xb9\x07\xb3\x1d\xbe\x7b\xe8\x3f\x0c\x6d\x39\x47\x41\x41\x4c\x22\xf6\x0c\x10\xf8\x31\x4d\xfc\x7d\xa6\x4e\x67\x82\x9e\xfe\x48\x4e\x7c\xa4\x19\xab\x94\x46\xce\x93\xe4\x36\xf1\xe3\x24\x49\x2a\x70\x61\x92\x11\xbb\x8f\x92\x31\xbb\x4e\x2d\x0f\xb5\x07\x94\x8c\xdb\x7b\x96\x84\xfc\x13\x00\x83\x61\xbb\xcb\x0d\x9f\xc1\x1d\xff\x1c\xb5\xf4\xcb\xbd\x5e\xbd\xdc\x59\x49\x64\xb7\xbe\x3f\x04\x43\x7e\xd0\xe1\xea\xa1\xc2\xc0\xd0\xc9\x93\xcc\x60\x00\xd8\xe6\x72\xc7\xf5\x76\xb5\x7f\xf1\x09\x6c\xeb\x06\x7d\x69\xb9\x11\xf8\xe3\x8f\x4f\x00\xd4\xf8\x9b\x76\xcf\x1d\x70\x1e\x00\x90\xd5\x8f\x73\x09\x5a\xf6\xf9\x39\x5a\xdb\xce\xac\x76\x8e\x16\x86\x34\xf3\x6e\x35\xb2\x2f\xc0\xbf\x00\xee\x58\xf9\x05\x80\x41\xa8\x70\xe1\x91\xbd\xf8\x97\xf3\xef\xf7\x4f\x00\xf0\xbd\xc6\xf7\x4f\x7f\xfc\xb1\x2b\x4a\xdc\xd6\x1b\x07\x85\x89\x87\x4a\x7b\x5a\x51\x43\x74\xae\xaf\xb7\x84\x7c\x69\xca\x0a\xe2\x65\x73\x93\x0f\x36\xc5\xf2\xb5\x32\xb2\x3e\x81\x68\x66\x76\xc7\x4a\x7c\xee\xbd\x04\x67\xae\x5f\x39\xbb\xbe\x0e\x0e\x16\xed\x95\x76\xa4\x9e\xc2\xda\x27\xec\x3b\xa9\x08\xf1\x78\xab\xac\x35\x4b\xf2\x79\xb2\x13\x38\xd0\xe4\xb3\x89\x05\x43\x96\x32\xbb\x1f\x87\x04\x2d\x79\xa7\xf1\x4e\x13\xb6\xe4\x50\xf9\x5d\x81\x4b\x49\x61\x8f\x0c\x5d\x72\xa8\xed\x07\x2f\x69\x0d\x32\xc2\x97\xc8\x09\xcc\x43\x6d\x35\xe3\x54\xa7\x6f\xa6\x61\xce\x0a\x27\xb6\xfc\x71\x97\x93\x2e\x2b\x1a\xe8\x64\xc7\x2c\xc9\xe5\x7b\x5b\xd2\x89\xc3\x66\x0e\xd7\x19\xa9\x9d\xb4\xa4\xd9\x7f\x25\xed\x65\xaf\x05\xa4\x7f\x20\xcd\x58\xa0\xa4\x2a\x20\x7b\x2d\x98\xc8\x5a\x6a\x89\x55\x4c\xf6\x5a\x98\x23\x1b\xa6\x3c\x52\x10\x4a\x7d\x6c\xa9\x53\x1d\xda\x4b\x13\x25\x15\xac\x54\x99\x8b\x3f\xff\xda\xc5\x8a\x7f\xff\x27\x29\x5a\xfc\xf3\xaf\xb8\xce\xd1\xdc\x48\xd9\xa0\xd8\xe1\xd2\x0d\x1d\x65\xc6\x9e\x3b\x5c\xfb\x68\x7c\xc9\xd4\x39\x12\x44\x27\x7a\x70\x2b\xb7\x58\x13\xea\x53\x14\x31\xcb\xe4\x87\x73\x55\x17\x52\xac\x27\x1d\x40\x88\x07\x26\x89\x40\x3e\xdd\x29\x5c\x44\x60\xdd\xb5\xc8\xb6\x34\xd1\xe9\x85\x3f\xff\x8a\xa7\xf2\xa2\xb1\x8d\xd3\x65\x8e\xd8\x53\x14\xcb\x8d\xea\xba\x33\xcd\x15\x1a\xaa\x3b\x4c\x99\xe3\x2a\x8c\x38\xdf\x1a\xfc\xaa\x39\xb4\x12\x82\xa1\xe5\xb1\xb7\x17\xa4\xc4\x0f\x9b\x1f\xea\xb8\xe2\xf7\x8e\x78\xce\x2a\xb9\xca\x37\x52\xe4\x98\x5d\x8d\x9b\x53\x0f\xe9\x1f\xa7\x3f\x94\x69\xff\xf2\x95\x60\x2f\xc1\x89\xa9\x8b\xd6\x19\x67\xa7\x20\x22\xb7\xe4\x25\x8d\xe7\xf0\x3d\x75\x89\xc5\x84\x19\x49\x00\x37\xa8\xd7\x53\xb3\xd7\xaa\x84\xd2\x56\x32\xee\x43\x20\x1b\x4b\x51\x43\x60\x61\x22\x49\x75\x13\xdc\xc5\xab\xe2\x0f\x2c\x85\x0e\x5f\x8f\x70\x68\x5f\x85\xaf\xe0\xf9\x2d\x95\xe4\x05\xab\x61\xcb\x94\xb7\x96\xdb\xe4\xcd\x3c\x90\xb1\x53\x87\xa0\xa9\x73\x35\x2d\x5f\x74\xea\x63\x1b\xbf\xc0\x38\x62\xfb\xea\xaa\x1c\x98\x48\x70\xf3\x46\x91\x15\x9f\x67\x23\xee\x55\x27\x39\x97\x7a\x8c\xf8\x71\x46\xf9\x68\x78\xb7\x37\x5c\xd8\x58\x2e\xff\x7e\x3a\x21\x0a\xde\x79\x92\x29\x54\x66\xde\xbe\x88\x90\xa9\x81\xd3\xc9\xc4\x2c\x7c\x6d\x4c\xa6\xa0\x39\xab\xfc\x64\x51\x1b\xd0\x86\x6e\x95\x4d\xc6\x21\x2c\xd0\xe0\xc6\x5c\x8e\x6c\x39\xf8\xf6\x0f\xd2\x9c\x02\x69\xd2\xd1\x92\x63\xf0\xa6\x1c\x2d\x38\x02\x65\xd6\x89\x85\x23\xd0\x66\x15\xf8\x17\x41\x1b\xae\x35\x8a\x17\xf9\x07\x45\x45\x67\xb8\xa0\xea\xaa\xad\x42\x4d\xf0\x0e\xec\x7f\xb3\xde\xb5\xb3\x4b\x70\x46\x60\x78\xf5\x2b\x8e\x7d\x25\x71\x80\x53\xd7\x78\xf5\x9a\xaa\x7e\xc3\x48\x96\x24\xbf\x60\xf8\x59\xac\x90\x29\x15\x39\x21\x78\x35\x79\x11\x43\x15\x37\x6e\x6e\x24\x93\x10\x45\x30\x95\x32\x84\x48\x61\x69\xa1\xdd\xda\x57\xd5\xf7\xee\xfc\xcc\x26\x47\x57\x09\xa6\x0c\x3d\x4a\x80\xb2\x2c\xc4\x77\xd1\x33\x69\xd0\x14\x4e\x95\x92\x89\x16\xbc\x68\x2f\xc8\x37\xb9\x07\x2f\x33\x49\x30\x38\x8b\x51\x65\x48\x30\x01\x09\x7f\x4e\x28\x40\xa2\x82\x55\x4b\x99\x40\xc5\x9b\x2d\x37\xc5\xa5\x60\x71\xac\x9c\xa2\x58\xb7\x33\xe0\x74\x6a\xa2\x29\xb4\x0d\x33\xbb\xaf\x59\x1a\x27\xd8\x72\xe8\xc3\x4a\xf2\x2f\x51\x2b\x20\x46\x95\xae\x94\xea\x8c\xaa\x2b\x86\x57\x61\x21\xac\x65\x33\x13\x7b\x95\x20\x99\x52\x16\x8b\x63\x2e\x7a\xbf\x17\xdc\x45\x72\x36\x01\x9a\xa9\xe0\xa5\x08\xe0\x61\x02\xdb\x75\xa8\x33\xfe\xb3\x09\x55\x09\xb6\x5a\x8a\x10\x11\xe9\x09\x7f\xf3\xca\xbb\x84\x3f\x8b\x12\x8e\xd1\x55\xa6\x9c\x48\xa4\x27\xce\x76\xb3\x30\xd3\xb2\x70\x1c\xaf\xd0\xa5\x0c\x17\xa7\x04\x45\x5d\x07\xb7\x18\x1a\x73\x4d\x50\x54\xa4\x65\x7a\x46\x1c\x27\x2b\x64\xb9\x8e\xa7\x83\x54\x40\x50\x81\xb3\xce\x11\x83\xa6\x2b\xa5\x06\x08\xce\x08\xaa\x3e\x45\x96\x2d\xec\xd7\xf8\xe4\x90\x62\xaa\xe5\xc6\x22\x5e\x89\x2c\x80\xdc\x62\x2a\x98\x3d\x97\xe0\x38\x4b\x33\x44\x29\x22\xec\xd6\x7c\x15\xc3\x0c\xd6\x1f\x99\x34\x08\x92\x25\xe9\x52\x34\xaa\x9e\x51\x65\xa3\x25\x49\x1c\x2b\x65\x51\x04\x96\xc0\x7a\xfe\x20\xc4\x49\x9a\xaa\x96\x1a\x84\x04\x1e\x8c\x74\x13\xcd\x8d\x0f\x24\xfc\x44\xa6\xb1\xdd\x48\x36\x74\xcb\x36\xa1\x9a\x33\xed\xe2\x24\x8b\x91\xa5\x06\x24\x41\x08\xa1\x10\x39\x13\x37\x45\x55\xb0\x52\xa6\x45\x90\x42\x6c\x1d\x97\x89\x9f\x26\x88\x52\x46\x45\x50\x85\x96\x22\x38\x83\xb1\x54\xa9\x69\x83\xa0\x1d\xbe\xfd\x01\x68\x22\x1d\xce\x91\x20\x19\xda\x72\x9e\x33\xf6\x18\xb2\x82\x97\x5b\x63\x91\x41\x5f\x2f\xf5\xa5\x85\x62\x83\x0e\xff\x4a\x62\x00\xc7\xc2\xd8\x4b\xa9\x9f\xa4\xdc\xd1\x2c\x2e\xe7\x8b\x0c\xff\xe1\x51\xc1\x0f\xa7\x42\x0b\xb2\x69\x2c\xc2\x0b\x52\x21\xee\x3e\x3c\x1a\x61\x3d\x95\xf3\x51\x64\xc5\x9b\x08\x13\x2b\x19\x05\xdb\x08\xca\x7b\x93\xa8\x12\x07\x53\xa5\xbc\xe9\xd7\x3f\x5f\xee\x90\x71\xdf\x7c\xe3\x5f\xd7\x91\x44\x8b\x3c\x58\x8b\x14\xed\xd2\x4a\x38\x42\xe2\xaf\xba\xf3\x14\x5a\x92\x1c\xe3\x92\x9b\x2f\xd7\x48\x4e\x19\x44\xc4\xb1\x24\x2a\xc2\xc2\x44\x92\x31\x5f\x2c\x83\x05\xf7\x76\x41\xb9\x6f\x85\x09\xd4\x4a\x39\x4f\x8a\x15\x4c\x24\x2e\x55\x4d\xce\x24\x45\xe0\x0e\x29\x8c\x00\x18\x7e\x4d\x92\xd7\x24\xf9\x8d\x22\x58\xca\x21\x85\x15\x27\xe5\xad\x2a\x45\x53\xd5\xfd\x58\xac\x24\x45\x92\x70\x56\xb1\xc5\x09\xd2\x98\xa0\xa9\xef\x4b\x55\x56\xed\x8d\x5b\xe8\x9c\x8d\xbe\x82\xb3\x4e\x3c\x51\x02\x3f\x1e\x78\xa1\x99\xed\x3b\x22\x4f\x30\x94\x43\xa8\x8a\x95\xa3\x43\xec\x96\xb3\xde\x0d\xd3\xb1\x59\xf4\x14\x34\xc8\xf0\x92\x79\xaf\xf8\xec\xb4\xb4\x28\xf7\x55\x03\x8e\x91\xeb\xb2\xea\x3e\x14\xa0\x2e\xef\x96\x0b\xce\xca\xf3\xc4\x2a\xa4\x05\x45\xd5\x6c\x64\x0a\xe6\x32\xe2\x83\x08\xe2\x2b\x86\x1f\x89\x9b\x71\xd6\xb1\x4b\x51\x30\x11\x94\x05\x43\xd7\x36\x45\xd1\xa7\x24\x5b\x32\xcf\xf5\x97\xcd\xb6\xec\x9d\xed\x0f\x9f\xf3\xbb\xa9\x3f\xdd\xdd\x30\xc3\x1e\xd5\xef\xb5\xf9\x41\xbd\xdb\x6b\xd6\x2a\x24\xc1\x51\x24\xf3\x42\x0f\x7a\x8d\xd1\xb0\x73\xf3\x78\x57\xb9\xa9\x75\xea\xdd\xfb\x4e\xbb\xd9\xa7\x46\x15\xfe\xf9\xf1\x61\x12\xd7\x4d\x2a\x11\xc2\x21\x52\x7b\xba\xb9\xbf\x7d\x7c\xe8\x3c\xf6\x9f\x5b\xcd\xce\xc3\xf8\xee\xf1\x81\x6e\xde\xb4\x38\xb2\xd3\x7b\x7e\x26\x6e\xef\xef\xba\x95\x3e\x77\xcb\x4d\xf8\xfb\xe6\x84\xe9\x0c\xea\x23\xbe\xf9\xf0\xd4\xef\x15\x26\x42\xba\x44\x86\x83\xe7\x56\xbb\x43\xd4\xdb\x64\xb3\x77\x4f\xd5\x9e\x3a\xcd\x6e\xaf\xd1\x69\xde\x4e\x7a\x83\x09\xd1\x7a\x26\x5f\xba\xcd\x51\xab\xdf\x9b\xd4\xf9\x3e\x37\x7a\xac\xdc\xd7\x2b\xfd\x27\xa2\x55\x98\x08\xe5\x10\xe1\xe8\xc7\xda\xe0\x99\xa3\x9f\xa9\x47\x8e\x6f\x3d\x3d\x0e\x89\xc9\x5d\x9f\x98\xf4\xa9\xda\xe4\xa6\x35\xb9\xaf\x50\xfc\x64\x70\xd7\xef\x11\xf7\xad\x07\xea\x71\xd8\xea\xb7\x87\xbd\xbb\xbb\x16\x71\x76\xe8\x3d\x14\x60\xc4\xe7\xe5\x78\xf3\x8f\x57\xc6\xef\x68\xb8\x04\xd4\xf6\x50\x65\x9e\x05\xee\x1f\xe1\x2b\x93\x44\x2c\x73\x6c\xec\x24\x92\x46\xb6\x13\xdc\xc3\xa3\xee\xc5\x5f\xf9\x82\x26\x1d\x1b\x3b\x74\xa4\x05\x47\xc7\x42\x63\x20\x7a\x20\xf4\x12\x38\xc3\xe2\xef\xcf\x5e\x88\xf2\xf9\x1a\x7c\xa6\xbf\xf9\x07\x6e\x3f\x5f\x82\xcf\xbb\x8d\x30\xe7\x91\x0e\x6d\xf5\x03\x7d\xfe\x4f\x9a\xa1\xc6\xa9\xe1\x31\x6a\xc4\x25\x20\x7f\x29\xb5\xc8\x11\xd5\x4b\x80\xb9\xc4\x2c\xdb\x59\xd5\xea\xd3\x60\x39\xe6\xe0\xc6\x31\x6c\x4b\xb8\x30\x01\x32\x4a\x20\x41\x9a\x30\xda\x53\xcb\x43\x5e\x02\xdc\x13\xc8\xbb\xb4\xe9\xf3\xb5\x23\xe2\x67\xcf\x14\x84\x37\xb4\x71\x68\x1c\xea\x44\x8b\x73\x45\xf9\x5c\x51\x44\xc5\x37\xa0\x5f\xa4\x65\x9f\xc0\xaf\xd6\x72\x4c\x9e\x62\x5a\x3e\xd0\xf7\x16\xe7\x8a\x08\xb8\x62\x58\x16\xff\xa5\x5a\xf6\x08\xfc\x6a\x2d\xc7\xe4\x29\xa6\xe5\x03\xe7\x6a\x8f\xab\x1c\x27\x9b\x74\x26\xf5\x50\x27\x1b\x9c\x4b\x0d\xaf\x01\x68\x1a\x56\x71\x91\x66\x18\x56\xa2\x10\xac\xd2\xa2\x54\x55\x30\x05\xa3\x28\x28\x2a\x84\x44\x62\x12\xc9\x32\x50\x96\xd9\x4a\x85\xc4\x90\x88\x68\x86\x12\x65\x9a\x96\xb1\x2a\x64\x64\xa5\x82\x2b\xce\x92\xad\x2a\x56\x24\x56\x54\x20\x0e\xab\x12\x4d\xe2\xb8\xc8\x12\x0c\x86\x55\x94\x2a\xa6\x88\x15\x9a\x81\x12\x46\x91\x48\xc6\x29\x82\x80\xa4\x44\x54\x09\x8c\x65\x25\x82\xc4\x21\x43\x60\x0c\x62\x18\xcc\x9b\x75\xf0\x58\xa6\xc3\x8b\x6f\x99\x78\x02\x24\x08\x7b\xc9\x2a\xc5\x32\x54\xee\x53\xdf\xaf\xe3\xac\x7b\xec\x9e\xb9\x74\x8b\xb6\x63\x9f\x4b\x40\x39\xff\xe0\xfe\x3f\xc1\x8f\xf8\xf6\x0f\x67\xea\xe1\x38\x8e\x6b\xdc\xda\xac\x7a\x65\x40\xbd\xd9\x1d\x2e\xeb\xcf\x9c\x42\x37\x2a\xf2\xa3\xc9\xdd\x7f\xc1\x26\xed\xf7\x41\xfd\x6d\xaa\x76\xdb\xeb\x85\x5a\x5b\xbe\x4c\x47\x03\x1c\x76\x8d\xc1\xf3\x82\x7c\xaf\x8f\xea\xca\x0b\x5e\x7b\x7d\x7c\x5c\xeb\x1b\xcb\x56\xcc\x8d\x79\xaf\xf7\x68\x05\xb1\xcf\x2f\x2f\xf8\x5a\x72\x50\x73\x4f\xa2\xa9\x48\x53\xe7\xaf\xf6\xf6\x1f\xee\xde\xf9\x67\xb5\xfb\xbe\xe2\x06\xf7\x6f\xee\x5f\x5c\xb3\x7b\x77\xfb\x01\x99\xfb\x79\x5f\x6b\x74\x6c\xf4\xfa\x2c\xce\x16\xcf\xed\xca\x68\x72\xd7\x57\xd0\xad\xd8\x96\xdf\xde\x5f\xab\xab\x3e\xce\xd9\xe6\x95\xc2\x76\x79\xd1\x68\xab\xd2\x8a\xaa\xd7\xb8\x0d\xce\xd8\x73\xfb\xf1\xa6\x29\xb6\x5a\x4b\xb8\xe2\x2b\xb3\x27\xb6\xcd\x93\xcd\x9f\x4f\xaa\x4b\xbf\xdb\xa3\x3a\xf0\xe7\x82\xb8\xe7\x76\x9f\x9b\xf0\x97\xed\xe7\x85\x7b\xc2\xa9\x7b\x8e\x6b\x60\xb7\x49\x8f\xff\xd1\x9f\xb3\xc0\x5b\xf5\x26\x9d\x4e\x8a\x77\x88\x0f\x18\xe2\x34\xc6\x7e\xc6\x90\x72\x95\x55\x68\x92\x41\x88\x61\x65\x5c\x24\x2a\x22\x2d\xb2\x55\x85\x20\xa1\xe2\xe2\xac\xd0\x4c\x15\x12\x94\x02\x15\x9c\xc2\x48\x28\x63\x22\x4d\x88\x0c\x49\x8a\x58\x45\x44\xd5\xea\x99\xeb\x99\xc8\x44\xdb\xa7\xd3\x86\x04\x85\x55\x19\x8c\xcc\x7d\xea\x4d\xe5\x14\x5d\x25\x32\xc6\x0b\x99\x32\x5e\x3c\xf7\xef\xea\xf7\x66\xf0\xf2\x8a\xf7\x96\xb4\x81\x89\xb7\x95\x47\x4a\xdf\xf4\x3f\x26\xeb\x1b\xf2\x61\x61\xbc\x7d\xf9\x68\x72\x7d\xbb\x8e\xdf\x11\xdd\x4a\xad\xc2\xbc\x68\x73\x5e\xee\x2f\x1e\xea\x5d\xba\xd5\x31\xab\xcd\xde\x2b\x4d\xbf\x43\x66\x45\xb4\xee\xba\xf6\xfb\x78\xd0\xec\x7c\xdc\xb0\x9b\xc1\xe4\x0a\x72\x86\x8b\xda\x1d\x2a\x21\x83\x1c\x4e\xb8\x87\xf5\xed\x1c\xd7\x1a\xdd\xd5\xea\x7d\xf9\x7a\x27\x6d\xee\x7f\x5a\xd5\x4a\xf3\x8a\xe3\xc7\x6a\x7d\x7a\x3f\x30\x57\x0c\xb9\x7a\x87\x83\x9b\xbe\xfd\x8a\x3d\xbc\xa3\xd7\xfa\xf0\x46\x67\x39\xea\x6e\x75\xab\xab\x15\xfd\x1d\xc1\xe5\x15\xc6\xcf\x66\x57\x37\x6f\xec\x86\x6f\xcc\x2b\x7a\xcb\x1b\x8a\x09\x43\x81\xb7\x92\xcc\x29\x18\x0a\x1c\x57\x7b\xfb\xa5\x76\xfb\x0b\x3e\x9e\x39\x95\x1b\x0a\xf8\x69\xcc\xd8\xad\xcc\x02\xbe\xdd\xe0\xd5\x0a\xe6\x86\xfe\x38\xc0\xb0\x6b\xf7\xbf\x54\x73\x25\x70\x86\x20\x72\x9f\x52\x44\x95\xaa\x32\x15\xa2\xca\x64\x18\x73\xae\x29\xff\x23\x3f\xb5\xa7\x3b\x95\xda\x5c\x6d\x46\x77\xb5\x4a\x43\x6f\x54\x5b\x04\xb6\x7e\xad\x7d\xb1\xb0\xa9\x6d\xad\xda\xab\x9f\xf8\x93\x3c\x7a\x7c\x86\xb5\x5b\xd8\x74\x4d\x99\x4f\x30\xe5\xe4\xcf\xff\xe7\xa6\x8c\x85\x4d\x39\x67\x75\x55\xe0\xda\x81\x43\x17\x5b\x29\x55\x71\x69\x21\x67\xfe\x8d\x47\x89\x68\xe2\x71\x32\x71\x18\x9a\x58\xc4\x48\x1e\x86\x85\x8a\x05\xb6\x87\x61\xa1\x63\x81\xce\x61\x58\x98\x28\x16\xea\x30\x2c\x95\x58\x38\x70\x18\x16\x36\x16\xc3\x9c\xe6\x4a\x88\x93\x64\x7f\xb2\xeb\x2e\x2f\x01\x5b\x34\xeb\x95\x72\x31\xc2\xd1\xa3\x27\xed\x82\xb0\xc8\xc5\x5c\x5e\xf0\xf0\xf7\x67\xdb\x38\x2a\x1e\xbb\x04\x9f\x15\xd3\x98\x1f\x95\x9f\x70\x22\xd0\x52\x49\xa3\x5f\x90\x51\x4e\x50\x5e\x78\x5c\x46\x2e\x22\x0b\x02\x76\x65\xa9\xcb\xc8\xf4\xd4\x77\x58\x56\xd8\x95\xd1\x4b\x9b\x1e\xab\xc1\xfc\xec\xc1\x2f\xc8\x5e\xa7\x69\xcd\xf7\x20\xdb\xbf\xa9\x5f\xaa\xb5\x43\x33\x36\xff\x38\xad\x79\xbe\x6e\xfb\x37\xf6\x4b\xb5\x76\xc4\x88\xff\xe5\x5a\xcb\x71\x9c\x09\x37\x2f\x1c\x51\x73\x5c\xea\x80\xf2\xa1\xce\x39\xb5\x12\x3e\x71\x71\x53\xf0\xe6\xc4\xfc\xe5\x0d\x95\xbe\xbc\xc9\x45\x44\x46\xdd\x5e\xda\x44\x9e\x8b\x87\x8a\xb9\xcf\x43\xf1\xc4\x1c\xca\xc1\xfc\x30\x51\x3c\x69\xcb\x9c\x5c\x3c\x95\xe8\x50\x3d\x98\x1f\x36\x8a\x27\x7d\xa9\x53\xf6\x6c\xf5\x29\x16\x3b\x79\x67\x2f\x4a\x2c\x77\x52\x0f\x52\x9f\x60\x4c\x85\xb6\xc9\x25\x24\x8a\x6c\x85\x86\x18\xa6\x28\x0c\xc2\x49\x96\x84\x48\xc1\x14\x99\xa0\x71\x58\x61\x14\x82\x90\x70\xa5\x0a\x45\x02\x12\xb2\xa2\x48\x22\x56\xa9\xb0\x34\x5d\x21\x19\x28\x23\x82\xa1\xab\xd0\x8b\xec\x8f\xda\xb5\x0e\x65\x84\xc8\x20\x50\x4e\x4d\xba\xd2\x18\x9e\x91\xb0\xf5\x9f\x46\x46\xb4\x17\x61\xdf\x31\xaf\x48\x25\x5f\xe7\x46\x9b\x1d\xdf\x68\x8d\x2b\x34\x95\xc8\xca\xe0\xc9\x6e\xdd\xdd\xfd\x7c\x7c\x60\x57\x0f\xea\x4b\x0d\xd6\x97\x74\x87\xee\x72\x6e\x84\xca\x05\x29\xd1\x5a\x2c\x00\x0c\x7d\xe7\xdd\x7f\xc5\xf9\x74\x8e\x3f\x10\xf2\x94\x7e\xc0\xe7\xef\x38\xd2\xba\xd2\x0d\x6e\xaf\x5f\x47\xcf\x77\x2f\xd5\x15\x3f\x35\x46\x35\x88\x1e\xd9\x89\xda\x34\x42\x68\x3a\x0c\xdb\x0e\x7d\x85\x95\xb7\x8f\xb7\x95\x8b\xbe\x3a\x58\x56\x17\xaf\x9b\x37\x69\x38\x62\x30\xed\xbd\xdf\x79\xef\xb1\xcd\xd6\x4f\x82\xa2\xee\x07\xac\x08\x9f\x7b\x68\x3c\xbe\x7d\x69\x6b\x26\x39\x12\x87\x75\x9c\x7c\xe7\xcd\xea\x72\x40\xf5\x87\x8d\xe9\xa6\x5e\xbb\x9a\x4a\xcb\x29\x71\x73\x67\x36\xba\xcb\x3b\x6c\x34\x26\xef\xfb\xf0\x6e\x52\x5b\xfd\xf8\x71\x16\xce\x36\x84\xd3\xad\xf7\x49\xb2\x71\x3b\xf8\xd8\x73\x0f\xc8\x55\x53\x3d\xa4\x96\x25\xac\x8b\x0f\x4f\x2f\x44\x43\x7b\x7a\x84\xe6\x03\x33\x59\xaf\xc4\x47\xf2\xa6\x77\x3b\x5d\xe8\x24\x37\xaa\xcf\xda\xcd\x05\x2d\xae\x47\xed\x47\x37\x5b\xc0\x55\xe6\x96\xaf\x8f\x69\x46\xb8\x9d\x9a\x4c\x70\x75\xdf\x38\x82\xfe\x17\x4d\x7c\x3f\x82\x7e\x37\x46\xbf\xbe\x34\x48\xc3\xa6\xe8\xf7\xfa\x80\x5f\x2f\xee\xaf\x48\xa3\xd5\xfb\xf2\x13\xaf\x0c\x37\xaa\x85\x6b\x4a\xb7\xf9\x3c\xbf\x7f\x9c\x9a\xcb\xd1\x97\x31\x17\xc8\x3f\x97\x76\xf4\xf9\x23\xe5\x2f\x4d\x9f\xd2\xab\x6f\x07\xd2\x0f\xd9\xd2\x94\x4b\xb0\x85\x43\x74\x71\x4a\x5b\xf8\x9d\x7d\xe1\xe9\xe2\xef\x5f\x35\x68\xdd\xc5\xa1\x7b\xff\x40\x90\xca\x2c\xf2\xaf\x33\xc5\xb8\xae\x34\x7f\x96\x8d\x14\x38\x57\x28\xe4\x38\xe2\xaa\x58\x45\x4a\x45\x16\x61\x15\xd2\xb2\x48\x92\x64\x55\xac\xb0\x8a\x0c\x59\x85\xa4\x2a\x95\x8a\x88\x43\x85\x24\x45\x48\x31\x2c\x94\x69\x09\x93\x95\x2a\xc5\xc8\x94\x7c\xe6\xee\x9e\xe2\xc7\xac\x66\xbd\x50\x3b\x6b\x0a\xa0\xb0\x6a\x05\x4f\xdd\x95\xdb\x3e\x0d\xaf\xa1\xfc\xed\x82\x0e\xdb\xba\xff\xb8\x7f\x13\xef\x88\x16\x47\x3e\x3e\xbc\x0e\xcd\xbb\xf9\xeb\x13\x86\x29\x37\xac\xd5\x69\x57\xe6\x18\x3f\x5c\xdd\x3e\x5e\x71\x4f\x24\xb7\x9d\x01\xdc\x4f\xc6\x0c\xe0\x7d\xcc\xf7\x1e\xd3\x41\x7d\x38\x7d\x5d\x77\xe1\x64\x50\x65\x6a\x3f\x15\xab\x8a\x30\xc9\x30\x7b\x2f\x4f\x3f\x6b\x8f\xb7\x6f\x4d\xe3\x2e\xf0\xf0\x1c\xd7\xa7\xcd\xbb\x30\xbe\x87\x8f\x55\xb3\xea\x3c\xe2\xeb\x8d\x9f\xef\x1f\x6f\xf7\xb5\x7b\xa3\xc7\xdd\xaa\xca\x60\xf8\xd4\x30\x3a\xb3\x0f\x7b\x23\x8d\x49\xad\x39\xa8\xdf\xd3\xf8\xf4\x4d\xb6\x9a\x2d\x58\xeb\x3d\xae\x30\x7a\x74\xf5\x30\x7b\xc4\x9e\xa6\x6f\x26\x56\xaf\x0d\x78\xaa\x07\x9b\x0f\xc4\xdd\x5c\xb2\xc8\x97\x55\x67\xae\x8a\xd4\x78\x68\x76\x3b\x05\x3c\x7f\xc4\xa4\xd3\x3c\xbf\xb7\x51\xb8\xe7\xf9\xd5\xab\x1a\xd6\xc1\x6e\x6f\x36\xf6\x6c\xd5\xc3\xb5\x67\x0c\x6e\x16\x06\x5e\xed\xb5\xd6\x1f\x9d\xfa\xa6\x4f\xdb\x35\x5e\xaa\x7b\x32\x92\x53\xdb\xec\xeb\xcf\x57\x95\xc9\xae\x7d\x37\x91\x89\x9c\xd1\x7e\x04\xfd\x9e\xb9\x19\x8f\x8f\xa0\xcf\x71\xff\x3d\x6f\x97\xe8\x79\x6b\x87\xeb\xa2\xaf\xbf\x64\x8a\x99\xa7\x8b\x63\xfb\xc2\xb1\x85\x2f\x52\x0c\x5f\x29\x5d\xfc\x3d\x65\x19\x93\xe6\xb9\xc9\x5d\xe3\xbe\xfe\xac\xff\xc4\x1e\x56\x4c\x9d\x12\x2b\x92\xce\x57\xe9\xe1\x78\xf5\xd6\x97\x9f\x6f\x5b\x62\x6d\x48\x4c\xc7\x0f\x56\xaf\x3f\xf9\xc0\x9f\x1f\xec\x26\x75\x7b\x57\xe5\xa6\xe3\x75\xbf\xf1\x38\x7b\x90\xd5\x85\xde\xe9\x11\x52\x9d\x36\xe6\x5f\x78\x0c\xfe\xac\xff\x66\xcf\x8b\x33\x14\xa4\x31\x86\x42\x22\x64\x28\x85\x90\x64\x11\xca\x22\x4b\x33\xa2\x42\x52\x14\x4b\xb1\xb4\x22\x31\x04\x43\x50\x15\x28\x43\x12\xc9\x64\x55\x92\x65\x05\x53\x98\x2a\x46\xe0\x24\x29\x32\x9e\xe7\x25\x8e\xf3\xbc\x44\xbe\xe7\x65\xc9\x6a\x86\xe7\xf5\x9e\x86\xa3\xc5\x63\x3d\x6f\x3d\xd6\xe5\x7b\x9e\xb7\x4f\xd4\xaf\xb8\x3e\x45\x3f\xd7\x1a\xa4\xdd\x7a\x68\xf6\xf1\x21\xc9\x61\x5d\xf4\x36\x60\x6f\x87\x8c\xde\xc3\xb9\x2a\x7a\x54\xe5\x4d\xdb\xf6\x06\x7c\xba\xe7\xe5\x46\xfc\x8b\xfa\x22\xa2\xe6\xaa\x6e\x99\x77\x35\xfd\xae\xbd\xb4\xae\x30\xfa\xc1\xbe\x6d\xd4\xcc\xa9\x61\x2d\x67\x9d\xfb\xab\x09\xf3\x34\x79\xa5\xec\xd5\xe3\x66\x66\x55\x26\xf6\x88\xaa\x77\xd1\xba\xdf\x65\x6e\xdf\x25\xe5\xfd\xf6\x0e\xc7\x1e\xb5\xda\xdb\xdb\x4a\xa7\xa6\xec\xa0\xad\xbc\xb6\x6f\xfe\x59\x9e\xf7\x58\xcf\x77\xec\x68\xef\xae\x3a\x73\xf3\x84\x9e\x97\xab\x3c\x77\x58\xae\xf2\xaa\x4d\xf9\x01\xc2\xe4\xc9\xa4\xf2\xd0\x92\x1a\xf7\x6b\xe6\xfe\x6a\xa5\xb5\xde\x25\x72\xd2\xc0\x69\x78\x4b\xb6\x55\xdc\xc3\x79\x6a\xcf\xfb\x5f\xf2\x7c\xdc\x89\x3c\x2f\x4b\xed\xda\xb7\x4b\xeb\xe2\x6f\x7e\x76\xf3\x3c\x7f\x24\x67\x12\x67\xde\x6d\xa6\x2f\x1b\xb5\x63\x0e\xaa\xfd\x07\x71\x74\xbf\x82\xd4\x5d\xa7\x63\x8c\xb0\x01\xde\xd7\xf0\xf6\x97\x8e\xd4\xb4\x0c\xb1\x8f\x77\x26\x4b\xee\xb5\x65\x8d\x5f\xfb\x2a\xd4\x5b\x8c\x3a\xb2\xe5\xe6\xe2\xfe\xe5\xb6\x7b\xfb\xa5\x3d\x68\x6c\x5a\xd4\xa6\x36\xfd\xcd\x6b\x5e\x91\x40\x2c\x21\x8b\x50\x14\x31\x82\x12\x89\x0a\xc4\x24\x12\xa7\x30\x09\x56\x70\x99\x85\x52\x55\x94\x2a\x38\x4b\xe2\x4a\x55\xa1\x21\x29\xca\x4c\x15\x49\x90\x94\x59\x56\x11\x31\x24\xd1\xd2\xd9\xb6\x62\xf0\x08\xcf\x9b\x97\xf6\xa0\xb0\x6a\x95\xce\x2a\xac\xf1\x9e\x86\xf3\x62\xc7\x7a\xde\x46\xac\xcb\xf7\x3c\x6f\xd9\xac\x47\xba\xe7\x6d\xdc\x2e\x35\xdc\xee\xdc\x74\x9a\xd4\xc3\x7a\x65\x63\x72\xa3\xfe\xc0\x2b\x8c\x2d\xd2\x1a\x25\x6e\xba\xe6\xcd\xb4\xbe\xf8\xa2\x3d\xbc\x74\xe7\x6b\xc9\xa6\x29\xb5\xa7\x10\xf3\xb5\xfd\xba\x66\xba\x32\xfd\x72\x4b\xf1\x54\x43\x93\x2c\x85\x62\x78\x6e\x56\xbb\x19\x4d\x06\x96\xce\x2a\xcf\x8d\x7f\x96\xe7\x3d\xd6\xf3\x1d\x3b\xda\x3b\xd8\x1b\xd3\x38\xa1\xe7\xfd\x9d\xd9\x9e\x5f\xe1\x79\x0f\xf5\x7c\xdc\x89\x3c\xef\xa1\xf1\x8f\xef\x79\x37\xe2\x42\x16\x47\x6b\x75\x8d\x9a\x92\xd4\x91\x5b\xf7\x2b\x6d\xd8\xfa\x62\x3e\x7e\x79\x41\x37\xec\xeb\xdd\xda\xe0\xde\x95\xc5\xc3\xe3\xf8\xd6\x7a\xea\x20\xd4\x7e\x7d\xaa\x2e\x2c\xf1\x99\x45\xaf\x2d\xf4\x38\x42\xb5\x3e\x47\x3f\x75\x5a\x5f\xfa\x33\xae\x7d\x3f\x7c\xd3\x1a\x95\xdb\xab\x16\xc1\x9d\x64\xcd\x9b\x92\xd5\xce\xba\x60\xaf\x6c\x42\x3b\x7e\xc9\xde\xd6\x97\xa3\xf5\x22\xb8\x67\xc0\xbd\x85\xcb\xab\x28\x73\x44\xca\x3a\xd7\x95\x70\x7b\xde\x11\xdb\x63\x69\x97\xbc\x95\x3f\xa0\x13\x7d\x6d\x78\xe4\x9b\xb0\x78\x43\x9b\x00\xfd\xee\xf6\xf6\xb2\xf7\x4e\x45\x70\xba\x97\x97\x71\x8d\x46\xf8\x36\xf8\x7d\xa2\xe1\x5b\xb7\xc1\xf9\xee\xee\xb9\xd4\xf7\x7e\xef\x70\x9c\x96\xe7\x4c\x76\xf7\x39\xdd\xdd\x7a\x97\xfb\x86\xf2\xfd\xb7\x77\x9f\x58\xdb\x3e\xda\x4c\x09\xc2\xa4\xa3\x92\x78\x4f\x2e\x41\x96\x44\xa1\x77\x5a\x87\x2f\x42\x39\x91\x1c\x3b\x8c\x89\x22\xc4\x08\x46\xb9\x4f\xe0\x36\xfe\x16\xee\xd8\xf7\x13\x71\x1d\xc3\x9a\xc4\x79\x12\xe1\x98\x15\x6d\xaf\x2e\xbc\x8c\xdc\x7b\x78\x19\xba\x26\x31\xef\x2d\xdc\xf1\xef\x27\x92\x2f\x86\x35\x49\xbe\x24\xc2\xb9\xbd\x13\xbb\x47\x30\x76\xa6\x6f\xa7\x10\x61\xa7\x01\x21\xac\x1a\xe1\x24\xd2\x45\xc9\x26\x09\x77\x10\x63\xc1\xeb\x56\x13\x3a\xd6\x81\x8f\x76\x72\x49\xd5\x9c\xa6\x5b\x4b\x0b\x5e\xaa\x53\x53\xaa\x0a\x73\x4a\xf7\x4e\x2b\x59\x32\x91\x2c\x49\x33\xd8\x2a\x2c\x79\x6a\x99\x41\xee\x4e\xfe\x69\xa5\x4f\x23\x93\x25\x7f\x26\x6b\xb9\x1a\x88\xaf\x9e\x62\xdf\x4f\x24\x5f\x0c\x6b\x92\x38\x49\x84\xa3\xdc\x27\xad\x2b\xfc\xcb\x8a\xbd\xff\x9d\x88\x59\x0f\x59\x12\x8f\x21\x32\x51\xd6\x82\xfb\xbe\xb2\x2e\xf9\x0d\xff\x7d\x22\x4e\x43\x18\x93\xd8\x8d\x13\x2c\xbd\x5a\xf3\x16\x7a\xbb\xa5\x85\xa0\xc3\xf9\x76\xb1\xee\xbe\x00\xa3\xd8\x65\xc5\x91\xd7\x58\x67\x22\x07\xfd\x5e\x6c\xa5\x1b\x79\x5f\xc6\x0e\xfa\x12\x38\xe0\xe9\x9c\xcf\x8c\x39\x12\x64\x63\x0e\x55\xfd\x00\x86\x63\x9c\x86\x90\x85\x19\x8c\xbd\xe2\x79\x07\x94\xce\x96\xaa\x2b\x9a\xe7\xac\x64\xf7\xfd\xc5\xee\xdf\xc7\x33\x98\x88\x36\x9d\xd5\x44\xf0\x94\x75\xa3\xb8\x71\x27\xc2\xc3\x79\x0c\x63\x09\xbf\x15\xc5\x9f\x27\xa3\xfd\xbb\x9d\x78\xd3\xb9\xf1\xa6\xdf\xe3\xf9\xf1\xef\xa8\x2e\xc4\x51\xca\x94\x2f\x6e\xef\x6d\x38\x98\x9d\x1d\x8a\x94\x57\x8b\xc7\xf9\xf1\x80\x2f\xf7\xde\x21\x91\xc4\x5c\xe8\xfe\xfc\x62\x0c\x2e\x0c\xcb\x9e\x9a\xc8\x4a\xe4\x33\x7c\x1b\x7f\x21\x5e\x43\x0d\x2e\xc0\x63\x8b\x1f\xf2\x91\x1b\xfd\xdb\xa3\xed\x05\xd8\xdf\xf7\x58\x9f\x41\x6b\x76\x02\x9e\xdd\x37\x0c\xf4\x7b\x99\xaf\x10\x89\xbe\x0e\x28\xf6\x7a\x82\x24\xb5\x7a\xef\x1b\x38\x11\x87\x3b\x64\xc5\x94\x9a\xfc\x16\x85\x40\xbf\x29\xef\x58\xc8\x54\xb5\x37\x11\x1c\x63\xc1\xfe\xb5\xe6\x85\xf8\x8f\xbd\x75\xe5\x72\xff\x05\x2b\x79\x21\xe1\xd1\x2e\x29\x05\x9f\xc3\x7f\x3c\xfa\x2c\xea\x9d\x12\x50\x1e\xe9\xa7\x52\x31\x16\x64\x33\x23\x4a\x11\x90\x83\xcd\xd5\xf5\xb1\x93\x79\x0c\x5d\xd8\x04\x82\x9b\x0e\xa2\x93\x64\xc2\x7b\x32\x2f\x83\x77\x62\xa6\x31\xbb\xbb\x51\xfd\x48\x36\xa3\xaf\xe5\xca\x64\x30\xbc\xd2\x38\x80\x69\x63\x21\x2c\x4e\xc5\xb7\x8f\x2b\xcc\x7a\x4a\xa4\x76\x90\x24\xc9\x02\xd8\xeb\xd3\x09\xe0\xe3\x4a\xf1\x0f\x07\x8a\x10\x7d\xf1\xd8\xbe\x10\xc6\xc2\xb1\xca\x99\x71\x90\x0c\x3e\xf3\x3b\x1c\x87\x2a\x3f\x5b\xd1\xdb\x77\xaa\x3b\x83\xfb\x78\x5d\x47\xd1\x85\x59\x0e\x0e\x53\x47\x67\x92\x44\x8e\xc2\x7a\x3d\x15\x5b\x7b\x38\x0b\x4e\x75\x09\x0c\xda\x5e\x97\xd8\xc7\x74\xeb\x0e\xc7\xe1\x26\x99\x67\x7e\xb6\x29\x3b\x44\xc2\xaf\xdd\x3d\x82\xe1\x7d\x64\xfb\xef\x17\x8c\xf2\x19\x7b\xdf\x6f\x36\x83\x6e\xf8\x7a\x1a\xf6\x5c\x54\x85\x98\x4b\x8d\x99\x03\x7c\xb1\x37\x09\x1f\xcd\x5f\x0c\x5f\x1e\x93\xfb\x2f\x32\xce\xe5\xf4\x34\x7a\x8c\x60\x2b\xca\x65\xae\x36\x4f\xc3\x5b\x21\x9e\xb2\x79\x09\x38\xf6\x5e\xd0\x79\x1c\x47\x51\x5c\x85\x7b\x34\x78\xe1\x71\x22\x7f\x0b\xa8\x9a\x82\xfb\x7e\xb6\x53\x70\x18\xc7\x56\x6c\xdc\x66\xbc\xba\x36\xfe\x96\xd2\x14\x21\x4e\xe0\xb7\x7d\x3c\x79\x1c\x97\x5c\x1d\x39\x58\x4f\xa6\xdd\x12\x8a\xcd\xd5\x9b\x77\xdb\xed\xde\x7d\x8c\x86\x2e\x40\x59\x36\x91\x65\x1d\xab\xd0\x5c\x02\x91\x5c\x44\x62\xe2\xc6\x07\x2c\xc1\xfb\xf1\x76\x90\x85\x3b\x9f\xe3\x84\x51\x16\x45\xe8\xaf\xc2\x1d\x7c\xf6\x66\x71\x78\x50\x97\x89\x35\x77\xd9\x9f\xb8\x55\x17\x45\xe9\xaf\xa1\x1c\x94\x5b\x23\x3a\x11\xb7\x49\xa8\x73\x97\x6f\x45\x2d\x39\x84\xfc\xd4\xc6\x10\x41\x7d\xc8\x7a\x33\x1d\xdd\x7c\x61\x98\xee\xbb\xd2\xbd\x37\xe5\x9c\x5e\xd1\x71\x0a\xf9\xec\xc7\x1a\x14\x17\xc6\x77\x3d\xc5\x13\x46\x07\xe8\x3f\x44\x23\x57\x92\x10\x6c\x71\x21\x16\x26\xfa\x50\x8d\xa5\xf5\x5b\xa4\x49\x22\x96\x2b\x56\x52\xa3\xe2\xf2\x05\x09\xa9\x5f\x26\xd3\xf6\x75\xad\x79\x72\xa4\x66\x74\xa3\xa8\x77\x17\x21\xfc\x8a\xa1\x1d\xc7\x9e\x18\x00\x97\x1d\xe0\x51\xa4\xd1\x10\xea\x44\x23\x3c\x8b\x44\x11\x19\x72\xe2\xba\x4c\x62\xa7\x9b\xbe\xf6\x11\x17\xe2\x3d\x7f\x12\x0b\x07\xdb\xbf\xc2\x6c\xf6\xf1\x1f\x1c\xea\xfb\x9b\xad\x4e\x60\x19\x7a\x2f\xec\xc1\x0a\x4e\x46\xe7\x70\xe7\xef\x21\x47\x97\xe1\x21\x98\x0c\xce\x92\xde\xee\x79\x02\x0e\x13\x5f\x1a\x9a\xc2\x69\x12\x6c\x06\xc7\xde\x0b\x7d\x4f\xc0\xa3\x87\x28\x8d\xab\xed\x7b\x83\x73\x58\x39\x65\xbf\x46\xdf\x2f\x9c\xc1\x58\x7a\xcf\x06\x75\x76\x27\xd8\xd8\xdb\x47\x15\xd9\xdb\x0e\xaa\x0b\x53\xb6\xb7\x13\x0a\x09\xa0\x8c\xb6\xcb\xda\x20\xdf\x2e\x88\x86\xf1\x76\x30\x8b\x19\x38\x73\x17\xcc\xe7\xe7\x32\xb2\xa1\xaa\x59\xe0\xeb\xbf\xff\x0d\xce\x2c\x43\x93\x43\xa5\x55\x67\xd7\xd7\x36\x5a\xdb\x17\x17\x97\x20\x1d\x50\x32\xe4\x62\x80\xde\x56\x46\x3a\xa8\x68\x2c\xa7\x33\xbb\x10\xf9\x08\x68\x36\x03\x11\xd0\x18\x0b\xc1\x76\x9b\xeb\x72\xc1\x0f\x40\x92\x59\x95\x1f\x21\x1b\x38\x66\xa2\x4b\xc5\xe8\x74\x56\xb8\xd0\xa4\xb8\x4d\x45\x10\x1e\xb9\x61\x95\x88\x2d\x9b\xb5\xac\x8d\xaa\x18\x3a\xb7\x60\xcf\x2d\xe0\x3b\x2d\x9b\x71\xbc\x05\x18\x0e\xd7\x02\xee\x17\x7f\x16\x2e\xbf\x55\x65\x41\x09\x55\x01\x35\xef\x7e\x4f\x11\xae\x4f\x16\x34\xfb\x43\xbe\x7d\xd3\xdb\x16\x86\x81\x21\xdf\xe4\x87\x7c\xaf\xce\x8f\x62\x05\x11\xee\xd3\x7e\x0f\x4c\x06\x0d\x47\x8d\x43\x7e\x34\x1e\xb6\xeb\x63\xe7\xa7\x06\xdf\xe1\xc7\x3c\xa8\x73\xa3\x3a\xd7\xe0\x33\xaa\xeb\x64\x64\xc5\xbe\x0a\xb1\x0c\xf5\xe9\x94\x11\xa5\x93\x53\x3a\x97\xc6\x49\x54\x3f\xf1\x6c\x7a\xa2\xb2\x7c\xd7\x9e\x53\x67\x98\xaa\x09\x3f\xc3\xf7\x5f\xd7\x43\x98\x8f\x24\x2d\x04\xc9\xd3\x6c\x83\x29\xa7\x81\xfd\x5c\xfb\x7f\x51\x0d\x29\xcc\x44\x75\x91\xb0\x3b\x70\x5a\xa3\x88\x67\x7e\xff\x09\x0a\x49\x37\x8d\xbd\xd4\x7a\xae\x75\x78\x9a\x18\xcf\x10\x50\x0c\x4d\x33\x56\xaa\x3e\x05\x8d\x46\x07\xa8\x16\x10\xa1\xa5\x4a\x50\xd3\x36\x00\xea\x1b\x30\x87\xba\xba\x58\x6a\x7e\xc0\x63\xcf\xa0\x0d\x66\x70\xb1\x40\x3a\xb0\x0d\x60\xcf\x10\xf0\xde\x43\x0d\x2c\xd5\x09\xae\xb7\x05\xed\x80\xaa\x7c\x03\x6d\x05\x6c\x8c\x25\xd0\x11\x92\x1d\x68\x55\x97\xb4\xa5\x8c\x1c\xc2\x50\x07\xcb\x85\x0c\x6d\x04\x0c\x25\xc0\xa0\x18\x26\xb0\x67\xaa\x05\x2c\x09\xe9\xd0\x54\x0d\xb7\x38\x05\xe9\xb2\x4b\xe6\x6c\xb9\x38\x03\x0b\xc3\x74\x91\x2b\xa6\x31\x07\x3a\x5a\x21\xcb\x0e\x91\x84\x36\x70\xa0\x67\xc8\x44\x97\xc0\xb0\x67\xc8\x5c\xa9\x16\xba\x04\x36\xb2\x6c\xcb\xa1\xba\x52\x35\x0d\x98\x4b\x1d\xa8\xba\x6d\x80\x85\x61\x23\xdd\x56\xa1\x06\x90\x69\x1a\xa6\x05\x56\x33\x47\x2a\xe7\x1f\x59\x0c\xa1\x5d\x2e\xae\x64\x63\xa5\x5b\x00\x9a\xc8\x6d\x0d\x97\xb6\x31\x87\xb6\xaf\x24\x71\xe3\xf2\xe7\x12\xf9\xe6\x50\x89\x74\xf9\x36\x2d\xeb\xf4\xb1\xff\xb6\x3f\x30\xe6\x9f\xc6\xdf\x53\x6a\x09\x9d\x95\xb4\x0f\xb6\x5f\x40\x58\x1b\x0f\x79\xfe\xdc\x7f\xee\x74\x63\x12\x29\xaf\x70\xb3\x28\x3d\xb7\x0c\x34\x99\x68\xb8\x02\x34\x93\x72\x78\xc6\xce\xa1\x1b\x9b\xff\x43\x54\xf7\xa7\xfd\x4c\x9a\x7e\x74\x91\x43\x2e\x14\x9e\xec\x28\x45\x02\x93\x4c\x22\x05\xca\xe2\x1b\xc3\xfe\x00\xd4\xfb\x9d\x49\xb7\x07\x54\x39\xa5\x7d\x66\x61\xf9\x1e\x06\xf7\x07\xbf\x4f\x43\xab\x17\x09\x5a\x12\x94\x51\x00\x90\x59\x4c\x15\x05\xca\x4d\x42\x64\x40\x47\xf3\xd7\x11\xc0\x68\x85\x6a\xae\xe4\x5e\x67\x05\x1e\xdb\x7d\x3d\x24\xf8\x80\xa6\x34\x83\xe6\x39\x53\xbd\xf0\x8f\x2f\x3a\x30\xa1\x32\xc5\x14\xb8\xef\xd9\xdd\xe4\xdb\x85\xb1\x34\xa5\xc3\x30\x05\x41\x97\xcb\xb1\xb7\xeb\x93\xda\xde\x71\xa6\x60\x3e\x55\x03\xc7\x57\x05\x51\x1b\x6c\x37\xdd\xea\x3f\xfe\xa9\x3d\x1a\x8f\xbc\x8d\x33\x38\x9d\xba\x9b\x67\x96\x0d\xe7\x0b\xf7\x6d\x8f\xfb\xfb\x67\x02\x83\x61\x18\x16\xac\x80\x4d\x55\x3f\xdf\xb6\xf0\x1c\x78\x88\x26\x8d\x05\x24\x3d\x31\x62\xaf\x74\x04\xe7\xae\xa1\xa9\x32\x70\xe2\xa7\x6d\x2d\xe2\x25\xf8\xfa\x15\xcc\xd0\xfa\x2b\xd2\x9d\x1e\x94\xc1\xc0\x30\xb4\x76\xc3\x85\x75\x23\x2b\x6b\x0e\x9d\x70\x3d\xd4\xc2\x7d\xa6\x20\xe4\x78\x50\x34\x45\x66\xec\x89\x3b\x86\x9d\x21\xec\x4d\x5a\x40\x54\xa7\xe1\xe6\xa0\xde\xe2\xeb\x77\xe0\x3c\x0e\xf6\x6f\x80\x5d\x78\x08\xac\x19\x34\xd3\x1a\x37\xf8\x26\x37\xe9\x8c\x01\xe6\xa1\x39\x0f\xc3\xfe\xfb\xc7\x16\x85\x67\x95\x26\xb2\x90\xf9\x81\x2c\xf0\x6a\x19\xba\x18\x63\x33\x31\xc1\x93\x2c\x91\x8c\x34\x64\x23\x19\x88\x86\xa1\x21\xa8\xef\x73\xe3\xbe\x3c\xcd\x83\x8d\x1f\xf6\xf8\xe4\xf4\x53\xc4\x14\x62\xfd\xe2\xc6\x91\x51\x76\xfb\xbd\xbd\xce\xf3\x2c\x60\xaa\xea\xe7\x49\xa2\x09\x0b\x68\xcf\x04\x63\x61\x5d\x7c\x8f\xd3\xfa\x40\xf1\x77\x7b\xa6\xa3\x77\xdd\x20\x38\xf7\xc5\xbd\x4c\x54\x51\x48\x9c\xed\x3d\x9d\x5b\x37\x11\x93\xcc\xbb\x62\xd3\x55\xcb\x68\xcc\x0d\xc7\xe0\xb1\x3d\x6e\x01\xdc\xfd\xa1\xdd\xab\x0f\xf9\x2e\xdf\x1b\x83\xda\xb3\xff\x53\xaf\x0f\xba\xed\x9e\x7b\x76\x78\xfb\x9d\x7b\xda\x7d\xaf\x73\xf5\x16\x0f\xf0\x1d\x03\xd1\xe1\x9a\x6a\xef\x69\x36\xa4\xa3\x75\xf4\xae\xd0\x64\xfe\xcf\xae\xaf\x4d\x34\x95\x34\x68\x59\xbe\x75\x45\xe1\x84\xf8\x90\x0a\x77\x79\xd6\xbe\x44\x8c\xda\xfe\x0e\x5e\x62\x27\x85\xb3\xb5\x07\x11\xd9\xe7\xbe\x28\xcd\xbd\x96\x17\x69\x7d\xb1\x9b\x2b\x93\x7b\x25\xa9\x60\x21\xde\x4f\x97\x11\xc8\x7d\xae\x63\xe0\x05\xb5\x9e\xca\x99\xa7\x7f\x2b\xb9\xca\x30\x53\x2d\x89\xc2\x5c\xa6\x73\x1e\x1f\xa4\x25\x18\x8c\x90\x38\x0d\xa7\x47\x70\x73\x14\x0f\xc5\x8d\x29\xbc\x70\xca\x36\xa7\xd8\x5e\xd3\x6f\x31\xa8\x0c\xee\x12\x4c\x2a\x4b\x96\x02\x45\x8e\x87\x9b\x55\x0e\x9b\xe9\xbb\x74\x47\x72\x7c\x14\x57\x47\x72\x92\x68\x62\x59\x31\x4b\xb2\x63\xcf\x8e\x5e\x12\xdd\x69\x5a\x1c\x93\xc8\x51\x68\x35\x1d\xad\x14\xdc\x7b\x12\xab\xdb\x4b\x5d\x6d\xcb\xc8\xf2\x22\x8a\xa0\x0c\xd0\x33\xfd\x94\x8f\x87\x24\x96\x5f\xf3\xda\x47\x87\x4e\x66\xfb\xfd\x6c\x4c\x19\x14\x8d\x86\xc7\x40\xda\xa8\xcc\x6d\xbd\x55\xcd\xa1\x08\x62\x0d\xfd\xf5\x6d\x7c\xf1\x16\x29\xb4\xcd\x9c\x49\x23\x05\x70\x5e\xef\x27\x37\x8a\x8f\x90\x78\x0d\x6a\x59\x2a\xa9\xed\x82\x88\x61\x9b\xd4\xa0\xf1\xb0\x85\xb5\x9b\x41\x78\x12\xda\x7a\x4b\x05\x08\x9f\x6b\x8b\xa3\x25\xb2\xec\xd2\xd1\xf5\xee\x0d\xed\xbb\xf0\x22\x58\x95\xe1\xfe\xca\x3e\x04\xe3\x84\x06\xdf\x3f\xf9\xb9\xef\x18\xba\x11\x3f\x0e\xa3\xfb\x01\x08\x7f\x5f\x28\xa5\x87\x42\xc7\xb0\x40\x7f\x98\x61\x36\x91\xf3\x5a\x89\x1d\x14\x22\x9b\xdd\x23\x3b\xc0\x02\x07\x59\xa2\xaa\xa4\x92\xd3\x3b\x5e\x68\xeb\x17\xa9\xc4\x82\x97\xef\x05\x5a\x38\x51\xa4\x3f\x30\x3c\x92\x50\x7e\x5d\x5a\x36\x50\x6d\xf0\x2f\xf4\x81\x4c\x00\xa7\x50\xd5\xff\xf5\x2d\x39\xb7\x14\xb9\x2e\xc5\x05\xf0\x33\x17\xde\x03\x30\x7e\x1e\xf0\xbe\xe7\x8c\x89\x43\xc7\xa6\xf8\xdd\x9b\xec\x77\xef\x9c\xf7\xe7\xf4\xfc\x0f\xd2\xa1\xa8\xf9\x61\xd9\xae\x53\x65\xa4\xc0\xa5\x66\x87\x63\xb2\xfc\xcf\x6a\xa6\xda\x48\x53\x2d\x3b\x08\xed\xff\xfc\xab\x98\xe3\x0a\x7d\x22\xd1\x52\xd6\x62\x22\x9c\xd5\x39\x40\xf0\x93\x89\x7d\xbc\xd0\xf9\x22\x7f\xfd\x0a\x54\xdd\x42\xa6\xed\xe6\x47\x03\x26\x65\xd5\xf2\x64\xb0\x6c\x68\x23\x37\xe9\x8b\xa0\x34\x03\xd6\x72\xe1\x16\xf8\xc9\xc0\xd3\x0b\x50\xe7\x0b\x0d\xcd\x91\x6e\xbb\xf6\x13\xb9\x73\x2a\xd1\x74\x82\x8b\xa7\x3c\x2d\x80\xb3\xbf\xff\x73\x76\x09\xe2\xd7\x0f\x26\x68\x3e\xb5\x5d\xcc\x7e\x2b\xf9\x4b\x54\xcb\xc7\x8c\x64\xc1\x9e\x2f\x00\x37\x02\x9f\x00\xb0\x90\x86\x24\x1b\xfc\x0b\x34\x87\xfd\x6e\x62\xab\x4f\xc0\xf7\x5b\xb1\xc3\x99\xae\x1f\xf2\x52\x4c\x79\x57\x28\x46\x09\xff\xef\x0e\xf1\xff\xdd\x21\x1e\xbd\xa8\xee\x7f\x77\x88\xff\xef\x0e\xf1\x62\xba\xf8\xdf\x1d\xe2\x59\xf7\x29\x7a\xdb\xa6\x03\xef\x46\x81\xd1\x7d\x07\xc8\xd0\x86\xce\x72\x13\xc8\xcb\xf9\x02\x48\x86\x33\x69\xd9\xc8\x81\xfb\x7f\x01\x00\x00\xff\xff\xe1\x3e\xae\xb2\x3b\xf3\x00\x00") +var _baseHorizonSql = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\x7d\xf9\x6f\xe2\xc8\xf2\xf8\xef\xf3\x57\xb4\x46\x2b\x25\x79\x93\x99\xf8\x06\x32\x9f\x79\x92\x01\x13\x48\xb8\xc2\x91\x6b\xb5\xb2\xda\x76\x1b\x9c\x18\xdb\xb1\x4d\x80\x59\xbd\xff\xfd\x2b\x5f\x60\x1b\x9f\xc0\xcc\xdb\xaf\xf4\xd0\x6a\x36\xe0\xea\xba\xba\xba\xba\xab\xba\xba\xfd\xf5\xeb\xa7\xaf\x5f\xc1\x50\xb7\xec\x99\x89\xc6\xf7\x5d\x20\x41\x1b\x0a\xd0\x42\x40\x5a\x2e\x8c\x4f\x5f\xbf\x7e\x72\x9e\x37\x97\x0b\x03\x49\x40\x36\xf5\xc5\x0e\xe0\x03\x99\x96\xa2\x6b\xa0\xf6\x8d\xf9\x86\x87\xa0\x84\x0d\x30\x66\xbc\xd3\x3c\x06\xf2\x69\xcc\x4d\x80\x65\x43\x1b\x2d\x90\x66\xf3\xb6\xb2\x40\xfa\xd2\x06\x3f\x00\xf6\xdd\x7d\xa4\xea\xe2\xdb\xfe\xaf\xa2\xaa\x38\xd0\x48\x13\x75\x49\xd1\x66\xe0\x07\x38\x9b\x4e\x5a\xd5\xb3\xef\x01\x3a\x4d\x82\xa6\xc4\x8b\xba\x26\xeb\xe6\x42\xd1\x66\xbc\x65\x9b\x8a\x36\xb3\xc0\x0f\xa0\x6b\x3e\x8e\x39\x12\xdf\x78\x79\xa9\x89\xb6\xa2\x6b\xbc\xa0\x4b\x0a\x72\x9e\xcb\x50\xb5\x50\x84\xcc\x42\xd1\xf8\x05\xb2\x2c\x38\x73\x01\x56\xd0\xd4\x14\x6d\xf6\xdd\xe7\x1d\x41\x53\x9c\xf3\x06\xb4\xe7\xe0\x07\x30\x96\x82\xaa\x88\x97\x8e\xb0\x22\xb4\xa1\xaa\x3b\x60\x6c\x77\xc2\x8d\xc0\x84\xad\x77\x39\xd0\x69\x01\xee\xa9\x33\x9e\x8c\xc1\xa0\xdf\x7d\xf6\xe1\xbf\xcd\x15\xcb\xd6\xcd\x0d\x6f\x9b\x50\x42\x16\x68\x8e\x06\x43\xd0\x18\xf4\xc7\x93\x11\xdb\xe9\x4f\x42\x8d\xa2\x80\xbc\xa8\x2f\x35\x1b\x99\x3c\xb4\x2c\x64\xf3\x8a\xc4\xcb\x6f\x68\xf3\xfd\x77\x10\x14\xdd\xbf\x7e\x07\x49\xc7\xae\x7e\x9f\x80\x1e\xb5\xf2\xd2\x79\x0c\x3a\x86\x9c\x45\x2c\x04\xb5\x43\xee\x82\x77\xfa\x4d\xee\x29\x04\xe9\xa3\xb5\xcd\xa5\x65\xf3\xaa\xa2\x39\xac\x6d\x78\x7b\x63\x20\x5e\xd4\x25\xc4\x2b\x96\xb5\x44\x66\xa9\xc6\x07\x34\xd9\x29\x22\xaf\x19\x94\x10\x8f\x64\x19\x89\xb6\xdb\x50\x37\x25\x64\xf2\x82\xae\xbf\x65\x37\xb4\x94\x99\x86\xcc\x30\xad\x6c\x78\x5d\x96\x7d\x70\x0b\xa9\xaa\x33\xb0\x5d\x95\x96\x69\x94\xa7\x82\x1d\xb4\x0a\x2d\x9b\x5f\xe8\x92\x22\x2b\x48\xe2\x55\x24\xcd\x8a\xb7\x15\x96\x9b\x82\xdc\x29\x9a\x84\xd6\x7c\xc8\x0c\x35\x0b\xba\x2e\xc9\xe2\x75\x2d\x57\xf3\xd1\xd6\xba\x81\x4c\xb8\x6d\xeb\x58\xcb\x11\xad\x77\x9c\x1c\xc5\x45\xb9\xb6\x9e\x96\xdd\x86\x16\x7a\x5f\x22\x4d\x2c\x25\x42\xa8\xb9\x61\xa2\x0f\x45\x5f\x5a\xfe\x6f\xfc\x1c\x5a\xf3\x03\x51\x1d\x8f\x41\x59\x18\xba\xe9\x38\x4e\x7f\xf6\x3b\x14\xcd\xa1\xba\x14\x55\xdd\x42\x12\x0f\x4b\xd9\x62\x30\x9e\x0f\x30\x25\x7f\x30\x1f\xc0\x74\xb8\x25\x94\x24\x13\x59\x56\x76\xf3\xb9\x6d\x4a\xee\x0a\x81\x57\x75\xfd\x6d\x69\x14\x80\x36\xf2\x58\xf2\xa0\xa0\x62\x96\x44\x1c\x4c\x8f\x85\x1b\x38\xae\xd2\xf1\x19\xc5\x40\x03\xf4\x07\x34\x29\xe4\x5d\x83\x46\xee\x24\x58\x82\x48\x78\xd2\xcc\x6b\x61\x38\x0d\xe6\x76\x6e\x0f\x58\x11\x07\xe4\x4c\x5f\xf9\x2d\xfc\x71\x5a\x04\x58\xf7\xf8\xd0\x73\x01\x15\xcb\xe6\xed\x35\x6f\xe4\xa3\x74\x20\x75\xa3\x28\x24\x2a\x0a\x16\xcc\xa6\xd9\xc0\x68\x6d\xf0\xe1\xd5\x45\xc1\xf9\x3e\xa1\x99\xb3\xbc\xc8\x6e\x24\x6c\x0a\x4d\x86\x8e\x7e\x73\x3d\x66\xd1\x89\xdf\x63\xb2\xa0\x54\x5b\xe0\x7c\x59\xb6\xee\x46\xd1\x64\xd5\x9d\xb4\x78\x09\x59\xb6\xa2\xb9\x7f\x17\x6c\x3b\xd7\x17\x88\x97\xf4\x05\x54\x8a\xb6\x70\x02\xa6\xf0\x32\x53\x83\x0b\x54\x64\x99\x19\x5a\x9f\x65\x2c\x33\xc3\xab\x38\xa3\xe0\x02\xd6\x5b\xba\x64\x20\xf5\xd7\x36\x45\xf1\xbd\xa1\x0d\xff\x01\xd5\x25\xe2\x1d\xbf\x8e\x32\x10\xc7\x20\x0b\x53\x48\x58\x32\xf1\x06\x34\x6d\x45\x54\x0c\xa8\x65\xae\xc3\xf3\x9a\x96\xe6\x61\xbb\xe4\x29\xcb\x41\x72\xc3\xd2\xf4\x5d\x8b\x2f\x42\xcf\x03\xfc\xe5\xf8\xbd\x11\xe8\x46\x2a\xde\x9f\x6e\xe4\xe2\x47\x71\xee\x08\xe6\x0b\x72\x30\xd3\x4d\x83\x5f\x28\x33\x7f\x45\x99\xc1\x42\x0c\xb2\xb0\x8c\x31\x1f\x98\x41\x21\xee\x2d\x8b\x52\x28\x1f\x1c\x16\xc6\x1c\x38\x14\x3f\x90\xca\x42\x1f\x03\x2d\x4d\xa3\x08\xee\xd2\x7c\x3b\x8e\xb0\x08\x62\xd7\x61\x66\x61\x2f\xea\x14\xbc\xd6\x8d\x41\x77\xda\xeb\x03\x45\xf2\x68\x37\xb9\x16\x3b\xed\x4e\x0a\xe2\x4e\x19\xec\x27\xc0\xec\x0f\xb3\x6c\x4c\xee\xb7\x14\x44\x21\xcf\x9f\x0d\xe8\x79\xf3\x6c\x98\x98\x63\xce\x06\x4e\x0a\x60\xfd\x16\x63\xee\x7e\xca\xf5\x1b\x07\xf4\x96\x33\x35\x5a\xe8\xbd\x34\xe5\x08\x92\xc2\xad\x25\x54\x24\xd4\x80\xb3\x99\x63\x01\xdb\xa8\xd0\xce\x5f\x43\x06\xcd\x84\xa5\xf8\x86\xec\x68\x74\x50\x88\x2d\x9e\xc1\x30\x0c\xf3\x5b\xb4\xa6\xfd\xc6\xa4\x33\xe8\x27\xf4\xbe\xce\x2f\x14\x55\x55\xac\x73\x27\x6c\xb1\x6c\xb8\x30\xc0\x4a\xb1\xe7\xc0\xf9\x0a\x7e\xea\x1a\xba\x04\xda\x72\x81\x4c\x45\xbc\x38\x18\x99\xbe\xb4\x33\xf0\x15\x1d\x3a\xc5\x6d\x23\x65\x86\x2c\x63\x19\xc9\x28\x8a\xb5\xf5\x83\xe8\x62\xc0\x7e\xc4\x5c\x58\x36\x7f\xb6\x2c\x23\x8b\xd7\xa4\x20\xac\xef\x3d\x8b\xf3\xb3\x5d\x0d\x17\xe0\x28\x36\xdf\x66\x03\xc7\xa6\xce\x6c\xe0\xe2\x80\xb1\x39\xad\x20\xb4\x33\x99\x14\x03\xf5\xa1\xd8\x9b\x9b\x11\x77\xc3\x4e\x12\x20\x17\x8a\xc6\x1b\xa6\x22\xa2\x73\x7f\x24\xfc\xf9\xd7\x45\x81\x56\x70\x7d\x40\x2b\x15\x5a\xf6\x39\xd4\x36\x48\x75\x77\x4b\x0a\xb4\x90\x15\x33\xb1\x49\xfa\xb0\xdf\xca\xe3\x78\xac\x1d\x77\xdb\x81\xbe\x63\x34\x03\x47\x20\xdd\x11\x38\xdc\xe4\xab\xd3\x7c\xc7\xfc\x25\x28\x23\x88\x2b\x7a\x01\x0c\xdc\xd3\x84\xeb\x8f\x63\x28\x54\x63\x66\xbd\xab\xc1\xb8\x69\xb4\xb9\x1e\xbb\x47\xe1\xfb\x27\x6f\xa3\xac\x0f\x17\xe8\x3a\xf8\x0d\x4c\x36\x06\xba\xf6\x9b\x7c\x07\x63\x71\x8e\x16\xf0\x1a\x7c\xfd\x0e\x06\x2b\x0d\x99\xd7\xe0\xab\xbb\x7f\xd6\x18\x71\x4e\x7f\xf9\x98\x03\x7c\x9f\x22\x18\xa3\x0f\x7d\xc4\x8d\x41\xaf\xc7\xf5\x27\x19\x98\x3d\x00\x30\xe8\x47\x11\x80\xce\x18\x9c\x05\x3b\x63\xc1\x6f\x96\x8b\xe4\x2c\x4e\x39\x10\xdf\xa7\xb9\xd5\x50\xae\x3c\x11\x5d\xf6\x07\x93\x98\x3e\xc1\x63\x67\xd2\xde\xb2\x15\xde\x22\x8b\x90\xdf\x61\x89\x31\x52\x46\xf8\x3d\x24\xae\x02\x86\xdd\x2b\x63\x36\xbe\xef\x02\xc3\xd4\x45\x24\x2d\x4d\xa8\x02\x15\x6a\xb3\x25\x9c\x21\x57\x0d\x05\xb7\xf4\xc2\xec\xe6\x1b\x9a\xcf\x7e\x60\xab\x3b\xfe\x83\xbe\x4d\xd2\xe5\xd6\xb2\x73\xf1\x83\x11\x37\x99\x8e\xfa\xe3\xd0\x6f\x9f\x00\x00\xa0\xcb\xf6\x6f\xa6\xec\x0d\x07\x5c\xe9\x7b\xbd\xa9\xe7\xec\xc6\x93\x51\xa7\x31\x71\x21\xd8\x31\xf8\x83\xff\x03\x8c\xb9\x2e\xd7\x98\x80\x3f\x70\xe7\x5b\xbc\x37\x72\x07\xe2\x71\xd2\xe5\xa1\x3f\x99\x70\x44\x92\x70\x45\x3c\xd5\x71\xf2\x15\xa0\xb0\x15\x71\xfb\xd3\x41\x12\x9e\x7f\x02\xa0\xc1\x8e\x39\xf0\xd8\xe6\xfa\xe0\x0f\xfc\x4f\xfc\xaf\xab\x3f\xf0\x3f\x89\xbf\xfe\xfd\x07\xe1\xfe\x4d\xfc\x49\xfc\x05\x26\xde\x43\xc0\x75\xc7\x9c\xa3\x14\xae\xdf\xbc\x48\xd4\x4c\x81\x79\xe0\x48\xcd\xe4\x53\xf8\xd5\x9a\xf9\xbf\x43\x34\xb3\x3f\xa7\xfa\x7a\xd8\xce\xc3\xc5\x14\xb1\x9b\xb6\xf7\x30\xba\x1c\x03\x30\x76\x74\x05\x7e\xec\x3c\xc0\xa5\xf7\xf3\xe4\x79\xc8\x81\x1f\xe1\x11\x71\x91\x34\x6a\x4f\xca\x63\x1c\x61\x8c\xc5\x60\x18\x17\xe7\x30\x71\x09\x74\x2c\x97\x49\x48\x63\x9c\x46\x06\x64\x94\xdd\x9d\x95\xed\x73\x9b\xb4\xcc\x3b\x9a\xdb\x04\xa4\x71\x6e\xc3\x83\x24\x93\x5b\x67\xe6\x92\x90\x0c\x97\xaa\xcd\xdb\x50\x50\x91\x65\x40\x11\x81\x1f\xe0\xec\xec\x7b\xf4\xa9\x13\xc5\xf1\xba\x22\x85\xaa\x5d\x22\xb2\x6e\x17\xbf\xbe\x7c\xee\xe8\x2a\x26\x9b\x37\x10\xb7\x19\x23\x4f\x96\x5d\x9e\x1b\x88\x73\x68\x42\xd1\x46\x26\xf8\x80\xe6\x46\xd1\x66\xe7\x34\x73\xe1\xae\x14\xfa\xd3\x6e\xd7\x93\x4f\x80\x2a\xd4\x44\x04\x04\x65\xa6\x68\x76\xfc\xa1\xb7\xaf\xae\x2a\x50\x50\x54\xc5\x56\x90\x95\x0c\x17\x94\x07\x14\x00\xf4\x76\x99\x79\x6d\xb9\x10\x90\x99\x0c\xa4\x2d\x17\xbc\xb5\x14\x90\x66\x9b\x0e\x22\x45\xb3\xd1\x0c\x99\x31\xa0\xc4\x1d\x84\x42\x12\xcb\x2a\x9c\xa5\x61\x0d\xed\x2d\x24\xe0\x22\x89\x38\xae\x05\xb4\x6c\x64\xf2\x2b\xa4\xcc\xe6\x36\xb0\x16\xd0\xd1\x43\x5c\x1e\x7b\x6e\x22\x6b\xae\xab\x12\xaf\xea\xab\x7c\xa0\x05\x92\x94\xe5\x22\x1f\x6e\xae\xcc\xe6\x69\x50\x49\xc5\x14\x7b\x22\xef\x8f\xbb\x68\xcc\x76\xac\x41\x7a\xe9\x46\xcf\x2a\xfd\xf4\xcd\x1b\xda\x24\xe8\x15\xa7\xb1\xb8\x62\x4b\x5a\xb1\x06\x17\x28\x01\x90\xa1\xe2\x80\x6e\x86\x2d\x01\xb2\xb6\xc7\xc1\xb1\x2a\x0c\x82\xe4\xa3\xb5\x18\x24\x9b\x0b\x0c\xef\x7d\x79\xbd\xc6\xc0\x46\xeb\xb8\x89\xf8\x36\x9b\x3c\x0e\x2c\x43\xd7\x2c\xdd\x4c\xd6\xbd\x2b\xb4\xcf\xab\x97\x84\xdb\xcb\x76\x0b\x1b\x3e\x40\x31\xe8\xef\x8b\x32\x1d\x77\xfa\x37\xa0\x3e\x19\x71\xdc\xb9\x0f\xb7\xaf\xc8\x50\x5a\xe2\x60\x1d\x86\xb6\x02\x3c\xf5\x29\x52\xb2\xcf\x81\x0b\x87\xc3\x7d\x79\x13\x5c\xd3\xd6\xdf\x26\xab\xce\x73\x2f\x69\xa3\x57\x5f\xa8\x09\x4a\x25\x68\xfa\x22\xc3\xa6\xe2\xe9\x9c\x43\xd5\x11\xdf\x7b\xf1\x2d\x6a\xbb\x65\x94\x22\xd1\x6e\x7b\x29\x69\xec\xee\xf9\xc4\xf0\xbe\x53\xa1\xc1\xeb\xeb\x3e\xc1\x46\x33\xd5\xbd\xaf\xa7\x78\x8e\xec\x50\x3d\xc5\x77\xc1\xb6\xa6\x93\xc0\x22\x34\x0c\x55\x71\x8b\x7d\x40\x5a\x1a\x78\x9f\xd1\xb4\x0c\x60\x90\xcf\xf0\x53\x87\xc5\x78\xde\x26\x1a\x53\xb0\xfa\xcb\x18\x76\x34\xf1\x32\x02\xb8\xfb\x43\xa7\xdf\x18\x71\x6e\xf8\x5e\x7f\xf6\x7f\xea\x0f\x40\xaf\xd3\x7f\x60\xbb\x53\x6e\xfb\x9d\x7d\xda\x7d\x6f\xb0\x8d\x36\x07\xf0\x3c\x61\x0e\x56\x7b\x1c\xd1\xde\x90\xf5\x37\x65\x80\x86\xd6\xf6\x07\x54\xcf\xcf\x52\x24\x3e\xbb\xbe\x36\xd1\x4c\x54\xa1\x65\xed\xd9\x9a\x57\xe4\x94\xec\x3b\x83\x8e\xda\x72\x22\xaa\x50\x59\x38\xab\x3b\xde\x5f\x26\x59\xe0\x7c\x01\xb5\x25\x54\xd5\x8d\x83\x0a\x49\x17\xa9\xbd\xb0\xdf\xf6\xd7\xf5\x47\xa2\x1a\x93\x98\x4f\xf1\x81\xe9\x9a\x4d\x95\x22\xac\x63\x4f\xb5\x7b\xa0\x7c\x7c\xc4\x84\x27\x8e\x69\xbf\x73\x3f\x0d\xe6\x8f\xcf\xd1\xaa\xb4\x04\xa2\x6e\x65\xdb\x67\x67\x32\xc9\x10\xcf\x9b\x56\x04\xdb\x44\x08\x9c\x2b\xd2\xc5\xf7\xc3\x89\x25\x09\x53\x8a\x7c\x12\x82\x8b\xb4\xae\xda\x6d\x99\xa4\x76\xda\x3e\x68\xda\x54\x96\xca\x61\x42\x8b\xa2\x3d\x92\xc5\xa0\xd7\x37\x56\x44\x3b\x99\x02\x45\xf4\x94\x28\xd7\x65\xa6\x10\xbb\x7e\x3d\x88\xd7\x30\xa5\x13\x32\x7d\x24\x57\x47\xf3\x52\xca\xe0\xc2\xbb\xb7\xb9\x26\x17\xad\x4d\xfe\x7d\x46\x97\xcd\x64\x92\xd9\xe5\x88\x95\xa8\xb7\x98\x74\x47\x99\x5e\x3e\xc7\x51\x6a\x27\x66\xfe\x68\xee\x4e\xc0\x51\x9a\x19\x7e\xea\xf4\xc7\xdc\x68\x02\x3a\xfd\xc9\x20\xcb\x89\xba\xd3\xdb\x18\x9c\xe3\x97\xe0\x0c\xf3\x3f\x78\xa5\x5a\x25\x18\x59\x90\x11\x49\xd6\x10\x2e\xd3\x22\x4d\x52\x78\x45\x64\x64\x24\xc9\x88\x10\x31\x1a\x55\x05\x24\xe2\x14\x89\x91\x38\x45\x22\x91\x62\x04\xb2\x5a\xab\xe2\x02\x56\x13\x49\xb9\x76\x76\xf1\xfd\x93\x9f\x9c\xdc\xed\x2b\x7c\xb3\x50\xd1\xa9\xee\x12\xe0\x97\xc0\x36\x97\xe8\xe2\xbb\xb3\x3a\x98\xcc\x11\xd8\x6d\xad\x5f\x85\x6b\x30\x00\x34\x11\x98\xe9\x4e\xe0\x60\xeb\x40\x40\x60\xa9\x99\x48\x85\x36\x92\x9c\xef\x5b\x0a\x41\xd6\xc5\xba\x04\xc2\xd2\x06\x8a\x0d\x24\x1d\x59\xda\x99\x0d\x16\xd0\x76\x16\x25\xb2\xee\xc4\x6c\x96\xad\x68\xb3\x44\xc5\x65\xba\x87\xad\x0a\x89\x6a\x95\xaa\x61\x74\xad\x4a\x5f\x02\xfc\xe2\xfb\xe1\x98\xaa\x74\xb5\x56\x23\xab\x4c\xb5\x96\x8e\x28\xc7\x58\xf6\x99\xa2\x8e\xc6\xb5\x65\xab\xea\xa1\x4a\x5e\x96\x7a\x5b\xf8\x47\x2f\x4a\xbd\x62\xa1\xed\x0a\x2a\x2b\x54\x72\x63\xa9\x22\xd1\xf9\xaf\x8b\xac\x32\x62\x8e\x48\x15\xc4\x89\x22\x8e\x30\xce\xdf\x16\x6f\x64\x09\x02\x06\x8f\x7d\xae\x09\xea\xcf\x39\x12\x79\xc5\x5f\xd9\x02\x6d\x71\xc5\x1e\x7f\x53\xa4\x34\xde\x82\xd2\x94\x63\xad\xce\xc7\x13\x9b\x90\x43\x39\xa0\xcc\xc9\x38\x7f\xad\xf8\xd9\x2d\x76\xff\x9c\x62\xcd\x19\x39\x01\x09\xd9\x50\x51\x2d\xf0\x6a\xe9\x9a\x90\x6e\x6c\x41\x3d\xcf\xb1\x7a\xf0\xf1\xf8\x7a\x08\xb2\xc8\x29\xbc\x85\x0e\x10\x15\x1a\x85\x49\x67\x97\x92\x1b\xfa\x6a\x09\x7b\x27\x37\x75\x11\xf0\x11\x84\x51\x58\x8c\x42\xc8\xc9\x16\x82\xdf\x1e\x20\x02\x19\xd5\x60\xf1\x36\x26\x72\xe6\x99\x9c\x46\x1e\xec\xd2\x90\x0a\xc3\x6e\x4d\xc7\xff\x1a\x3b\x5b\xb5\x27\x0b\xbe\x97\xf2\xb2\xa1\xca\x8b\xba\xa2\xa5\xec\x09\xc8\x08\xf1\x86\xae\xab\x29\x5b\x10\xd0\x42\xbc\x8c\xd2\xfa\xda\x7d\x6c\x22\x0b\x99\x1f\x69\x20\x0b\xb8\xe6\xed\x35\xef\xa6\xbd\x94\x9f\x69\x50\x86\xa9\xdb\xba\xa8\xab\xa9\x72\xc5\xfb\x28\x30\x16\x04\x25\x3f\xc1\xea\xa7\x4e\x97\xa2\x88\x2c\x4b\x5e\xaa\x7c\xaa\xa1\xf8\x82\x43\x45\x45\x52\x1e\x94\xcf\x7a\x8a\x09\xa5\x0f\xbd\x94\x32\xbc\x63\x47\x62\x4a\x39\x6e\xce\xbc\x58\x3e\x7a\x4d\xf7\x71\x65\x45\x3e\xed\x54\x97\x49\xe3\x77\x4d\x7d\xa5\x04\x3d\x72\x2a\xcc\xa4\xb5\x3f\x35\x26\x83\x67\x4c\x95\xa1\x22\xd5\xe2\xb6\xf9\xf5\xab\x97\x7e\x03\x8a\xc5\x1b\x70\xb3\x40\x9a\xfd\xc3\xdd\x5c\x0d\xb6\x5d\x9d\xe5\xb6\x57\x6f\x75\x09\x4c\x68\xcf\x9d\x21\x3a\x87\xee\xa6\x9e\x36\x73\x7c\x80\x85\x4c\x1b\xb8\xa5\xdb\x79\x86\x9e\xb7\x75\x50\x24\x3c\x76\xb3\xc4\xa2\xa7\x17\x77\xca\x3d\x72\xc6\xf5\x5d\x8d\xbe\x34\xc5\xed\x59\xc0\x94\xb9\x2e\xf0\x5f\x67\x67\xd7\xd7\x79\xdb\x1b\x3b\x6d\x02\x41\xd7\x55\x04\xb5\xad\x3e\x5d\xed\xa6\x0f\x3d\xbf\xa0\xfb\x58\xef\xe2\x5f\x20\x50\x36\xe5\x95\xbd\x8c\xf1\x3d\xf5\x21\x93\xaa\x5b\xb8\x9f\x4a\x36\x76\x7d\x41\x16\x90\x7f\xa3\x42\x16\x88\xb7\x0b\x92\x08\xb0\x7f\x11\x44\x0e\x5c\x26\xb9\x2d\x54\x06\x45\x97\x25\xc5\xf2\xcf\xf0\x07\xd6\x10\x4c\x95\x8a\x88\x78\x2d\xb2\x2c\xf0\x7e\x8b\x2e\x15\x76\x07\x5b\xf9\xd8\x22\x22\x72\xb4\x36\xfe\xd0\xd4\x97\x9a\xe4\xde\x22\xa2\x2a\x86\x01\x67\x68\x1f\xa9\x62\xf1\x68\x0d\x45\x3b\xca\x57\xe8\x4c\x4b\xe2\x3d\x13\xae\xb8\xbc\x7b\x13\x09\x68\xb4\xb9\xc6\x1d\x38\x3f\x0f\xab\xfe\xdf\x3f\x00\x76\x71\x91\x87\x2b\xa9\x7d\xa0\xee\xff\xdb\xeb\x81\x02\xf8\x22\xbd\x11\x43\x1f\xeb\x2a\x8f\xc3\x4f\x69\xa1\xee\x49\x07\xa1\x77\x0a\xc2\x1d\x8a\xbb\xf1\xe2\xdb\x8a\xa6\xdb\x40\x5b\xaa\xaa\x23\x5b\xa2\x7d\x87\x01\xd2\x8c\x72\x0f\x66\x3b\x7c\xf7\xd0\x7f\xe8\xea\x72\x81\x82\x1a\x9c\x44\xec\x19\x20\xf0\x63\x96\xf8\xfb\x5c\x99\xcd\x79\x2d\xfd\x91\x94\xf8\x48\xd5\x57\x29\x8d\x9c\x27\xc9\x6d\xe2\x27\x58\x92\x54\xe0\xc2\x24\x23\x76\x1f\x25\x63\x76\x9d\x5a\x1e\x6a\x0f\x28\x19\xb7\xf7\x2c\x09\xf9\x27\x00\x86\xa3\x4e\x8f\x1d\x3d\x83\x3b\xee\x39\x6a\xe9\x97\x7b\xbd\x7a\xb9\xb3\x92\x48\x81\xc0\x60\x04\x46\xdc\xb0\xcb\x36\x42\xb5\x88\xa1\xc3\x2e\x99\xf1\x07\xb0\xcd\xe5\x8e\xeb\x6d\x80\x71\xf1\x09\x6c\x4b\x15\x7d\x69\xd9\x31\xf8\xe3\x8f\x4f\x00\xd4\xb9\x9b\x4e\xdf\x1d\x70\x1e\x00\x90\x94\x8f\x73\x11\x5a\xf6\xf9\x39\x5a\xdb\xce\xdc\x77\x8e\x0c\x5d\x9c\x7b\x17\x29\xd9\x17\xe0\x5f\x00\x77\xac\xfc\x02\xc0\x20\x3a\xb9\xf0\xc8\x5e\xfc\xcb\xf9\xf7\xfb\x27\x00\xb8\x7e\xf3\xfb\xa7\x3f\xfe\xd8\xd5\x41\x6e\x4b\x9c\x83\x5a\xc8\x43\xa5\x3d\xad\xa8\x21\x3a\xd7\xd7\x5b\x42\xbe\x34\x65\x05\xf1\x12\xc8\xc9\x67\xa9\x62\x29\x62\x09\x59\x9f\x40\x34\x19\xbc\x63\x25\x3e\xf7\x5e\x82\x33\xd7\xaf\x9c\x5d\x5f\x07\x67\x99\xf6\xaa\x49\x52\x0f\x7e\xed\x13\xf6\x9d\x54\x84\x78\xbc\x55\xd6\x9a\x25\xf9\x08\xdb\x09\x1c\x68\xf2\x71\xc8\x82\x51\x52\x99\x0d\x97\x43\xe2\xa4\xbc\x03\x80\xa7\x89\x94\x72\xa8\xfc\xae\x58\xa9\xa4\xb0\x47\x46\x4b\x39\xd4\xf6\xe3\xa5\xb4\x06\x19\x11\x53\xe4\xd0\xe7\xa1\xb6\x9a\x71\x90\xd4\x37\xd3\x30\x67\x85\x73\x69\xfe\xb8\xcb\xc9\xd0\x15\x0d\x87\xb2\x23\x9b\xe4\x8a\xc1\x2d\xe9\xc4\x61\xb3\x80\xeb\x8c\x6c\x52\x5a\x9e\xee\xbf\x92\x69\xb3\xd7\x3c\xd2\x3e\x90\xaa\x1b\x28\xa9\xf0\xc8\x5e\xf3\x26\xb2\xdc\x50\x37\xf1\xe1\x02\xd9\x30\xe5\x91\x8c\x50\xea\x63\x4b\x99\x69\xd0\x5e\x9a\x28\xa9\x46\xa6\xc6\x5c\xfc\xf9\xd7\x2e\xa2\xfc\xfb\x3f\x49\x31\xe5\x9f\x7f\xc5\x75\x8e\x16\x7a\xca\x9e\xc8\x0e\x97\xa6\x6b\xa8\x40\x84\xea\xe0\xda\x47\xe3\x4b\xa6\x2c\x10\x2f\x38\xd1\x83\x5b\x2c\x56\x35\x9d\x50\x3f\x62\x96\xc9\x0f\x17\x8a\xc6\xa7\x58\x4f\x3a\x00\x1f\x0f\x4c\x12\x81\x7c\xba\x33\x68\x44\x60\xdd\xb5\xc8\xb6\x1a\xd2\xe9\x85\x3f\xff\x8a\x67\x0f\xa3\xb1\x8d\xd3\x65\x8e\xd8\x33\x14\x4b\xc7\x6a\x9a\x33\xcd\x15\x1a\xaa\x3b\x4c\x99\xe3\x2a\x8c\x38\xdf\x1a\xfc\x42\x3d\xb4\xe2\x83\xa1\xe5\xb1\xb7\x17\xa4\xc4\xcf\xb7\x1f\xea\xb8\xe2\x57\x9d\x78\xce\x2a\xb9\xb0\x38\x52\x57\x99\x5d\x00\x9c\x53\x82\xe9\x9f\xe0\x3f\x94\x69\xff\xbe\x97\x60\xfb\xc2\x89\xa9\x8b\x96\x36\x67\xa7\x20\x22\x17\xf3\x25\x8d\xe7\xf0\xd5\x78\x89\xf5\x8b\x19\x49\x00\x37\xa8\xd7\x52\x13\xe6\x8a\x88\xd2\x56\x32\xee\x43\x20\xe9\x4b\x41\x45\xc0\x30\x91\xa8\xb8\x39\xf5\xe2\x85\xf8\x07\x56\x5f\x87\x6f\x64\x38\xb4\xaf\xc2\xb7\xfe\xfc\x96\xe2\xf5\x82\x05\xb8\x65\x2a\x6a\xcb\xed\x2b\x67\x9e\x01\xd9\xa9\x83\x57\x95\x85\x92\x96\x2f\x3a\xf5\x49\x91\x5f\x60\x1c\xb1\xad\x7c\x45\x0a\x4c\x24\xb8\xec\xa3\xc8\x8a\xcf\xb3\x11\xf7\x76\x95\x9c\x7b\x44\xc6\xdc\x24\xa3\x62\x35\xbc\xc1\x1c\xae\xa5\x2c\x97\xf2\x3f\x9d\x10\x05\xaf\x59\xc9\x14\x2a\x73\xab\xa0\x88\x90\xa9\x81\xd3\xc9\xc4\x2c\x7c\x53\x4d\xa6\xa0\x39\xab\xfc\x64\x51\x9b\xd0\x86\x6e\x61\x4f\xc6\xb9\x2f\xd0\x64\x27\x6c\x8e\x6c\x39\xf8\xf6\xcf\xee\x9c\x02\x69\xd2\x69\x96\x63\xf0\xa6\x9c\x66\x38\x02\x65\xd6\x21\x89\x23\xd0\x66\x9d\x29\x28\x82\x36\x5c\xde\x14\x3f\x57\x10\xd4\x31\x9d\xe1\xbc\xa2\x29\xb6\x02\x55\xde\xdb\xb3\xfa\x66\xbd\xab\x67\x97\xe0\x8c\xc0\xf0\xda\x57\x1c\xfb\x4a\xe2\x00\xa7\xae\xf1\xda\x35\x55\xfb\x86\x91\x55\x92\xfc\x82\xe1\x67\xb1\xda\xa9\x54\xe4\x04\xef\x95\x01\x46\x0c\x55\xd8\xb8\xb9\x91\x4c\x42\x14\xc1\x54\xca\x10\x22\xf9\xa5\x85\x76\x6b\x5f\x45\xdb\xbb\x66\x34\x9b\x1c\x5d\x23\x98\x32\xf4\x28\x1e\x4a\x12\x1f\xdf\xb8\xcf\xa4\x41\x53\x38\x55\x4a\x26\x9a\xf7\xa2\xbd\x20\xdf\xe4\x9e\xf5\xcc\x24\xc1\xe0\x55\x8c\x2a\x43\x82\x09\x48\xf8\x73\x42\x01\x12\x15\xac\x56\xca\x04\x2a\xde\x6c\xb9\x29\x2e\x45\x15\xc7\xca\x29\xaa\xea\x76\x06\x9c\xcd\x4c\x34\x83\xb6\x6e\x66\xf7\x75\x95\xc6\x89\x6a\x39\xf4\x61\x25\xf9\xf7\xb6\x15\x10\xa3\x46\x57\x4a\x75\x46\xcd\x15\xc3\x2b\xea\xe0\xd7\x92\x99\x89\xbd\x46\x90\x4c\x29\x8b\xc5\x31\x17\xbd\xdf\x0b\xee\x22\x39\x9b\x00\xcd\x54\xf0\x52\x04\xf0\x30\x81\xed\x3a\xd4\x19\xff\xd9\x84\x6a\x44\xb5\x56\x8a\x10\x11\xe9\x09\x7f\xf3\xca\xbb\xf7\x3f\x8b\x12\x8e\xd1\x35\xa6\x9c\x48\xa4\x27\xce\x76\xb3\x30\xd3\xb2\x70\x1c\xaf\xd0\xa5\x0c\x17\xa7\x78\x59\x59\x07\x17\x27\xea\x0b\x95\x97\x15\xa4\x66\x7a\x46\x1c\x27\x2b\x64\xb9\x8e\xa7\x83\x54\x40\x50\xf4\xb3\xce\x11\x83\xa6\x2b\xa5\x06\x08\xce\xf0\x8a\x36\x43\x96\xcd\xef\x97\x15\xe5\x90\x62\x6a\xe5\xc6\x22\x5e\x89\x2c\x80\xdc\xfa\x2d\x98\x3d\x97\xe0\x78\x95\x66\x88\x52\x44\xaa\x5b\xf3\x95\x75\x33\x58\x7f\x64\xd2\x20\xc8\x2a\x49\x97\xa2\x51\xf3\x8c\x2a\x1b\x2d\x49\xe2\x58\x29\x8b\x22\xb0\x04\xd6\xf3\x07\x21\x4e\xd2\x54\xad\xd4\x20\x24\xf0\x60\xa4\x9b\x68\xa1\x7f\x20\xfe\x27\x32\xf5\xed\x46\xb2\xae\x59\xb6\x09\x95\x9c\x69\x17\x27\xab\x18\x59\x6a\x40\x12\x04\x1f\x0a\x91\x33\x71\x53\x54\x05\x2b\x65\x5a\x04\xc9\xc7\xd6\x71\x99\xf8\x69\x82\x28\x65\x54\x04\x55\x68\x29\x82\x33\x58\x95\x2a\x35\x6d\x10\xb4\xc3\xb7\x3f\x00\x4d\xa4\xc1\x05\xe2\x45\x5d\x5d\x2e\x72\xc6\x1e\x43\x56\xf0\x72\x6b\x2c\x32\xe8\xeb\xa5\xb6\xb4\x50\x6c\xd0\xe1\x5f\x49\x0c\xe0\x58\x18\x7b\x29\xf5\x93\x94\x3b\x9a\x85\xe5\xc2\xc8\xf0\x1f\x1e\x15\xfc\x70\x2a\x34\x2f\x99\xba\x11\x5e\x90\xf2\x71\xf7\xe1\xd1\x08\xeb\xa9\x9c\x8f\x22\x2b\xde\x44\x98\x58\x3c\xc9\xdb\x7a\x50\x51\x9c\x44\x95\x38\x98\x2a\xe5\x4d\xbf\xfe\x91\x76\x87\x8c\xfb\xb2\x1d\xff\x86\x90\x24\x5a\xe4\xc1\x5a\xa4\x68\x97\x56\xc2\xa9\x15\x7f\xd5\x9d\xa7\xd0\x92\xe4\x18\x97\xdc\x62\xb9\x46\x52\xca\x20\x22\x8e\x25\x51\xe1\x0d\x13\x89\xfa\xc2\x58\x06\x0b\xee\xed\x82\x72\xdf\x0a\x13\xa8\x95\x72\x9e\x54\x95\x37\x91\xb0\x54\x54\x29\x93\x14\x81\x3b\xa4\x30\x02\x60\xf8\x35\x49\x5e\x93\xe4\x37\x8a\xa8\x52\x0e\x29\xac\x38\x29\x6f\x55\x29\x98\x8a\xe6\xc7\x62\x25\x29\x92\x84\xb3\x8a\x2d\x4e\x90\xc6\x78\x55\x79\x5f\x2a\x92\x62\x6f\xdc\xda\xea\x6c\xf4\x15\xbc\xea\xc4\x13\x25\xf0\xe3\x81\x17\x9a\xdb\xbe\x23\xf2\x04\x43\x39\x84\x6a\x58\x39\x3a\xc4\x6e\x39\xeb\x5d\x6a\x1d\x9b\x45\x4f\x41\x83\x0c\x2f\x99\xf7\x8a\xcf\x4e\x4b\x8b\x72\xdf\x6e\xe0\x18\xb9\x26\x29\xee\x43\x1e\x6a\xd2\x6e\xb9\xe0\xac\x3c\x4f\xac\x42\x9a\x97\x15\xd5\x46\x26\x6f\x2e\x23\x3e\x88\x20\xbe\x62\xf8\x91\xb8\x19\x67\x1d\xbb\x14\x78\x13\x41\x89\xd7\x35\x75\x53\x14\x7d\x4a\xb2\x25\xf3\x2a\x81\xb2\xd9\x96\xbd\xeb\x04\xc2\x47\x0b\x6f\x1a\x4f\x77\x37\xcc\xa8\x4f\x0d\xfa\x1d\x6e\xd8\xe8\xf5\x5b\xf5\x0a\x49\xb0\x14\xc9\xbc\xd0\xc3\x7e\x73\x3c\xea\xde\x3c\xde\x55\x6e\xea\xdd\x46\xef\xbe\xdb\x69\x0d\xa8\x71\x85\x7b\x7e\x7c\x98\xc6\x75\x93\x4a\x84\x70\x88\xd4\x9f\x6e\xee\x6f\x1f\x1f\xba\x8f\x83\xe7\x76\xab\xfb\x30\xb9\x7b\x7c\xa0\x5b\x37\x6d\x96\xec\xf6\x9f\x9f\x89\xdb\xfb\xbb\x5e\x65\xc0\xde\xb2\x53\xee\xbe\x35\x65\xba\xc3\xc6\x98\x6b\x3d\x3c\x0d\xfa\x85\x89\x90\x2e\x91\xd1\xf0\xb9\xdd\xe9\x12\x8d\x0e\xd9\xea\xdf\x53\xf5\xa7\x6e\xab\xd7\x6f\x76\x5b\xb7\xd3\xfe\x70\x4a\xb4\x9f\xc9\x97\x5e\x6b\xdc\x1e\xf4\xa7\x0d\x6e\xc0\x8e\x1f\x2b\xf7\x8d\xca\xe0\x89\x68\x17\x26\x42\x39\x44\x58\xfa\xb1\x3e\x7c\x66\xe9\x67\xea\x91\xe5\xda\x4f\x8f\x23\x62\x7a\x37\x20\xa6\x03\xaa\x3e\xbd\x69\x4f\xef\x2b\x14\x37\x1d\xde\x0d\xfa\xc4\x7d\xfb\x81\x7a\x1c\xb5\x07\x9d\x51\xff\xee\xae\x4d\x9c\x1d\x7a\xf5\x05\x18\x73\x79\x39\xde\xfc\x13\x9d\xf1\x6b\x21\x2e\x01\xb5\x3d\xc7\x99\x67\x81\xfb\xa7\x06\xcb\x24\x11\xcb\x9c\x54\x3b\x89\xa4\x91\xed\x04\xf7\xbc\xaa\x5b\xb0\x9d\x2f\x68\xd2\x49\xb5\x43\x47\x5a\x70\x5a\x2d\x34\x06\xa2\x67\x50\x2f\x81\x33\x2c\xfe\xfe\xec\x85\x28\x9f\xaf\xc1\x67\xfa\x9b\x7f\xc6\xf7\xf3\x25\xf8\xbc\xdb\x08\x73\x1e\x69\xd0\x56\x3e\xd0\xe7\xff\xa4\x19\x6a\x9c\x1a\x1e\xa3\x46\x5c\x02\xf2\x97\x52\x8b\x9c\x8a\xbd\x04\x98\x4b\xcc\xb2\x9d\x55\xad\x36\x0b\x96\x63\x0e\x6e\x1c\xc3\xb6\x84\x0b\x13\x20\xa3\x04\x12\xa4\x09\xa3\x3d\xb5\x3c\xe4\x25\xc0\x3d\x81\xbc\x7b\xa2\x3e\x5f\x3b\x22\x7e\xf6\x4c\x81\x7f\x43\x1b\x87\xc6\xa1\x4e\xb4\x38\x57\x94\xcf\x15\x45\x54\x7c\x03\xfa\x45\x5a\xf6\x09\xfc\x6a\x2d\xc7\xe4\x29\xa6\xe5\x03\x7d\x6f\x71\xae\x88\x80\x2b\xa6\x5a\xc5\x7f\xa9\x96\x3d\x02\xbf\x5a\xcb\x31\x79\x8a\x69\xf9\xc0\xb9\xda\xe3\x2a\xc7\xc9\x26\x1d\x83\x3d\xd4\xc9\x06\x47\x61\xc3\x6b\x00\x9a\x86\x35\x5c\xa0\x19\xa6\x2a\x52\x08\xd6\x68\x41\xac\xc9\x98\x8c\x51\x14\x14\x64\x42\x24\x31\x91\xac\x32\x50\x92\xaa\x95\x0a\x89\x21\x01\xd1\x0c\x25\x48\x34\x2d\x61\x35\xc8\x48\x72\x05\x97\x9d\x25\x5b\x4d\xa8\x88\x55\x41\x86\x38\xac\x89\x34\x89\xe3\x42\x95\x60\x30\xac\x22\xd7\x30\x59\xa8\xd0\x0c\x14\x31\x8a\x44\x12\x4e\x11\x04\x24\x45\xa2\x46\x60\xd5\xaa\x48\x90\x38\x64\x08\x8c\x41\x0c\x83\x79\xb3\x0e\x1e\xcb\x74\x78\xf1\x2d\x13\x4f\x80\x04\x61\x2f\x59\xa3\xaa\x0c\x95\xfb\xd4\xf7\xeb\x78\xd5\x3d\xe9\xcf\x5c\xba\x45\xdb\xb1\xcf\x25\xa0\x9c\x7f\x70\xff\x9f\xe0\x47\x7c\xfb\x87\x33\xf5\xb0\x2c\xcb\x36\x6f\xed\xaa\x72\xa5\x43\xad\xd5\x1b\x2d\x1b\xcf\xac\x4c\x37\x2b\xd2\xa3\xc9\xde\x7f\xc1\xa6\x9d\xf7\x61\xe3\x6d\xa6\xf4\x3a\x6b\x43\xa9\x2f\x5f\x66\xe3\x21\x0e\x7b\xfa\xf0\xd9\x20\xdf\x1b\xe3\x86\xfc\x82\xd7\x5f\x1f\x1f\xd7\xda\xc6\xb2\x65\x73\x63\xde\x6b\x7d\x5a\x46\xd5\xe7\x97\x17\x7c\x2d\x3a\xa8\xd9\x27\xc1\x94\xc5\x99\xf3\x57\x67\xfb\x0f\x7b\xef\xfc\xb3\xda\x7d\x5f\xb1\xc3\xfb\x37\xf7\x2f\xb6\xd5\xbb\xbb\xfd\x80\xcc\xfd\x62\xa0\x36\xbb\x36\x7a\x7d\x16\xe6\xc6\x73\xa7\x32\x9e\xde\x0d\x64\x74\x2b\x74\xa4\xb7\xf7\xd7\xda\x6a\x80\xb3\xb6\x79\x25\x57\x7b\x9c\xa0\x77\x14\x71\x45\x35\xea\xec\x06\x67\xec\x85\xfd\x78\xd3\x12\xda\xed\x25\x5c\x71\x95\xf9\x53\xb5\xc3\x91\xad\x9f\x4f\x8a\x4b\xbf\xd7\xa7\xba\xf0\xa7\x41\xdc\xb3\xbb\xcf\x4d\xf8\xcb\xf6\xf3\xc2\x3e\xe1\xd4\x3d\xcb\x36\xb1\xdb\xa4\xc7\xff\xe8\xcf\x59\xe0\xad\xfa\xd3\x6e\x37\xc5\x3b\xc4\x07\x0c\x71\x1a\x63\x3f\x63\x48\xa9\x56\x95\x69\x92\x41\x88\xa9\x4a\xb8\x40\x54\x04\x5a\xa8\xd6\x64\x82\x84\xb2\x8b\xb3\x42\x33\x35\x48\x50\x32\x94\x71\x0a\x23\xa1\x84\x09\x34\x21\x30\x24\x29\x60\x15\x01\xd5\x6a\x67\xae\x67\x22\x13\x6d\x9f\x4e\x1b\x12\x14\x56\x63\x30\x32\xf7\xa9\x37\x95\x53\x74\x8d\xc8\x18\x2f\x64\xca\x78\xf1\xdc\xbf\xab\xdf\x9b\xe1\xcb\x2b\xde\x5f\xd2\x3a\x26\xdc\x56\x1e\x29\x6d\x33\xf8\x98\xae\x6f\xc8\x07\x43\x7f\xfb\xf2\xd1\x62\x07\x76\x03\xbf\x23\x7a\x95\x7a\x85\x79\x51\x17\x9c\x34\x30\x1e\x1a\x3d\xba\xdd\x35\x6b\xad\xfe\x2b\x4d\xbf\x43\x66\x45\xb4\xef\x7a\xf6\xfb\x64\xd8\xea\x7e\xdc\x54\x37\xc3\xe9\x15\x64\x75\x17\xb5\x3b\x54\x42\x06\x39\x9a\xb2\x0f\xeb\xdb\x05\xae\x36\x7b\xab\xd5\xfb\xf2\xf5\x4e\xdc\xdc\xff\xb4\x6a\x95\xd6\x15\xcb\x4d\x94\xc6\xec\x7e\x68\xae\x18\x72\xf5\x0e\x87\x37\x03\xfb\x15\x7b\x78\x47\xaf\x8d\xd1\x8d\x56\x65\xa9\xbb\xd5\xad\xa6\x54\xb4\x77\x04\x97\x57\x18\x37\x9f\x5f\xdd\xbc\x55\x37\x5c\x73\x51\xd1\xda\xde\x50\x4c\x18\x0a\x9c\x95\x64\x4e\xc1\x50\x60\xd9\xfa\xdb\x2f\xb5\xdb\x5f\xf0\xf1\xcc\xa9\xdc\x50\xc0\x4f\x63\xc6\x6e\x65\x16\xf0\xed\x06\xaf\x55\x30\x37\xf4\xc7\x01\x86\x5d\xbb\xff\xa5\x9a\x2b\x81\x33\x04\x91\xfb\x94\x22\x6a\x54\x8d\xa9\x10\x35\x26\xc3\x98\x73\x4d\xf9\x1f\xf9\xa9\x3f\xdd\x29\xd4\xe6\x6a\x33\xbe\xab\x57\x9a\x5a\xb3\xd6\x26\xb0\xf5\x6b\xfd\x8b\x85\xcd\x6c\x6b\xd5\x59\xfd\xc4\x9f\xa4\xf1\xe3\x33\xac\xdf\xc2\x96\x6b\xca\x5c\x82\x29\x27\x7f\xfe\x3f\x37\x65\x2c\x6c\xca\x39\xab\xab\x02\x37\x1d\x1c\xba\xd8\x4a\xa9\x8a\x4b\x0b\x39\xf3\x2f\x59\x4a\x44\x13\x8f\x93\x89\xc3\xd0\xc4\x22\x46\xf2\x30\x2c\x54\x2c\xb0\x3d\x0c\x0b\x1d\x0b\x74\x0e\xc3\xc2\x44\xb1\x50\x87\x61\xa9\xc4\xc2\x81\xc3\xb0\x54\x63\x31\xcc\x69\x6e\xa1\x38\x49\xf6\x27\xbb\xee\xf2\x12\x54\x8b\x66\xbd\x52\xee\x62\x38\x7a\xf4\xa4\xdd\x49\x16\xb9\x0b\xcc\x0b\x1e\xfe\xfe\x6c\xeb\x47\xc5\x63\x97\xe0\xb3\x6c\xea\x8b\xa3\xf2\x13\x4e\x04\x5a\x2a\x69\xf4\x0b\x32\xca\x09\xca\x0b\x8f\xcb\xc8\xdd\x67\x41\xc0\x2e\x2f\x35\x09\x99\x9e\xfa\x0e\xcb\x0a\xbb\x32\x7a\x69\xd3\x63\x35\x98\x9f\x3d\xf8\x05\xd9\xeb\x34\xad\xf9\x1e\x64\xfb\x37\xf5\x4b\xb5\x76\x68\xc6\xe6\x1f\xa7\x35\xcf\xd7\x6d\xff\xc6\x7e\xa9\xd6\x8e\x18\xf1\xbf\x5c\x6b\x39\x8e\x33\xe1\xe6\x85\x23\x6a\x8e\x4b\x1d\x50\x3e\xd4\x39\xa7\x56\xc2\x27\x2e\x6e\x0a\x5e\xd6\x98\xbf\xbc\xa1\xd2\x97\x37\xb9\x88\xc8\xa8\xdb\x4b\x9b\xc8\x73\xf1\x50\x31\xf7\x79\x28\x9e\x98\x43\x39\x98\x1f\x26\x8a\x27\x6d\x99\x93\x8b\xa7\x12\x1d\xaa\x07\xf3\x53\x8d\xe2\x49\x5f\xea\x94\x3d\x5b\x7d\x8a\xc5\x4e\xde\xd9\x8b\x12\xcb\x9d\xd4\x83\xd4\x27\x18\x53\xa1\x6d\x72\x11\x09\x42\xb5\x42\x43\x0c\x93\x65\x06\xe1\x64\x95\x84\x48\xc6\x64\x89\xa0\x71\x58\x61\x64\x82\x10\x71\xb9\x06\x05\x02\x12\x92\x2c\x8b\x02\x56\xa9\x54\x69\xba\x42\x32\x50\x42\x04\x43\xd7\xa0\x17\xd9\x1f\xb5\x6b\x1d\xca\x08\x91\x41\xa0\x9c\x9a\x74\xa5\x31\x3c\x23\x61\xeb\x3f\x8d\x8c\x68\x2f\xc2\xbe\x63\x5e\x91\x42\xbe\x2e\xf4\x4e\x75\x72\xa3\x36\xaf\xd0\x4c\x24\x2b\xc3\x27\xbb\x7d\x77\xf7\xf3\xf1\xa1\xba\x7a\x50\x5e\xea\xb0\xb1\xa4\xbb\x74\x8f\x75\x23\x54\x36\x48\x89\xd6\x63\x01\x60\xe8\x3b\xe7\xfe\x2b\x2c\x66\x0b\xfc\x81\x90\x66\xf4\x03\xbe\x78\xc7\x91\xda\x13\x6f\x70\x7b\xfd\x3a\x7e\xbe\x7b\xa9\xad\xb8\x99\x3e\xae\x43\xf4\x58\x9d\x2a\x2d\x3d\x84\xa6\xcb\x54\x3b\xa1\xaf\xb0\xf2\xf6\xf1\xb6\x72\xd1\xd7\x86\xcb\x9a\xf1\xba\x79\x13\x47\x63\x06\x53\xdf\x07\xdd\xf7\x7e\xb5\xd5\xfe\x49\x50\xd4\xfd\xb0\x2a\xc0\xe7\x3e\x9a\x4c\x6e\x5f\x3a\xaa\x49\x8e\x85\x51\x03\x27\xdf\x39\xb3\xb6\x1c\x52\x83\x51\x73\xb6\x69\xd4\xaf\x66\xe2\x72\x46\xdc\xdc\x99\xcd\xde\xf2\x0e\x1b\x4f\xc8\xfb\x01\xbc\x9b\xd6\x57\x3f\x7e\x9c\x85\xb3\x0d\xe1\x74\xeb\x7d\x92\x6c\xec\x0e\x3e\xf6\xdc\x03\x72\xd5\xd4\x08\xa9\x65\x09\x1b\xc2\xc3\xd3\x0b\xd1\x54\x9f\x1e\xa1\xf9\xc0\x4c\xd7\x2b\xe1\x91\xbc\xe9\xdf\xce\x0c\x8d\x64\xc7\x8d\x79\xa7\x65\xd0\xc2\x7a\xdc\x79\x74\xb3\x05\x6c\x65\x61\xf9\xfa\x98\x65\x84\xdb\xa9\xc9\x04\x57\xf7\xcd\x23\xe8\x7f\x51\x85\xf7\x23\xe8\xf7\x62\xf4\x1b\x4b\x9d\xd4\x6d\x8a\x7e\x6f\x0c\xb9\xb5\x71\x7f\x45\xea\xed\xfe\x97\x9f\x78\x65\xb4\x51\x2c\x5c\x95\x7b\xad\xe7\xc5\xfd\xe3\xcc\x5c\x8e\xbf\x4c\xd8\x40\xfe\x85\xb8\xa3\xcf\x1d\x29\x7f\x69\xfa\x94\x56\x7b\x3b\x90\x7e\xc8\x96\x66\x6c\x82\x2d\x1c\xa2\x8b\x53\xda\xc2\xef\xec\x0b\x4f\x17\x7f\xff\xaa\x41\xeb\x2e\x0e\xdd\xfb\x07\x82\x54\x66\x91\x7f\x9d\x29\xc6\x75\xa5\xf9\xb3\x6c\xa4\xc0\xb9\x42\x21\xc7\x11\xd7\x84\x1a\x92\x2b\x92\x00\x6b\x90\x96\x04\x92\x24\x6b\x42\xa5\x2a\x4b\xb0\x2a\x93\x54\xa5\x52\x11\x70\x28\x93\xa4\x00\x29\xa6\x0a\x25\x5a\xc4\x24\xb9\x46\x31\x12\x25\x9d\xb9\xbb\xa7\xf8\x31\xab\x59\x2f\xd4\xce\x9a\x02\x28\xac\x56\xc1\x53\x77\xe5\xb6\x4f\xc3\x6b\x28\x7f\xbb\xa0\x5b\x6d\xdf\x7f\xdc\xbf\x09\x77\x44\x9b\x25\x1f\x1f\x5e\x47\xe6\xdd\xe2\xf5\x09\xc3\xe4\x9b\xaa\xd5\xed\x54\x16\x18\x37\x5a\xdd\x3e\x5e\xb1\x4f\x24\xbb\x9d\x01\xdc\x4f\xc6\x0c\xe0\x7d\xcc\xf7\x3e\xd3\x45\x03\x38\x7b\x5d\xf7\xe0\x74\x58\x63\xea\x3f\x65\xab\x86\x30\x51\x37\xfb\x2f\x4f\x3f\xeb\x8f\xb7\x6f\x2d\xfd\x2e\xf0\xf0\x2c\x3b\xa0\xcd\xbb\x30\xbe\x87\x8f\x55\xab\xe6\x3c\xe2\x1a\xcd\x9f\xef\x1f\x6f\xf7\xf5\x7b\xbd\xcf\xde\x2a\xf2\x70\xf4\xd4\xd4\xbb\xf3\x0f\x7b\x23\x4e\x48\xb5\x35\x6c\xdc\xd3\xf8\xec\x4d\xb2\x5a\x6d\x58\xef\x3f\xae\x30\x7a\x7c\xf5\x30\x7f\xc4\x9e\x66\x6f\x26\xd6\xa8\x0f\x39\xaa\x0f\x5b\x0f\xc4\xdd\x42\xb4\xc8\x97\x55\x77\xa1\x08\xd4\x64\x64\xf6\xba\x05\x3c\x7f\xc4\xa4\xd3\x3c\xbf\xb7\x51\xb8\xe7\xf9\x95\xab\x3a\xd6\xc5\x6e\x6f\x36\xf6\x7c\xd5\xc7\xd5\x67\x0c\x6e\x0c\x1d\xaf\xf5\xdb\xeb\x8f\x6e\x63\x33\xa0\xed\x3a\x27\x36\x3c\x19\xc9\x99\x6d\x0e\xb4\xe7\xab\xca\x74\xd7\xbe\x97\xc8\x44\xce\x68\x3f\x82\x7e\xdf\xdc\x4c\x26\x47\xd0\x67\xd9\xff\x9e\xb7\x4b\xf4\xbc\xf5\xc3\x75\x31\xd0\x5e\x32\xc5\xcc\xd3\xc5\xb1\x7d\xe1\xd8\xc2\x17\x31\x86\xaf\x94\x2e\xfe\x9e\x55\x19\x93\xe6\xd8\xe9\x5d\xf3\xbe\xf1\xac\xfd\xc4\x1e\x56\x4c\x83\x12\x2a\xa2\xc6\xd5\xe8\xd1\x64\xf5\x36\x90\x9e\x6f\xdb\x42\x7d\x44\xcc\x26\x0f\x56\x7f\x30\xfd\xc0\x9f\x1f\xec\x16\x75\x7b\x57\x63\x67\x93\xf5\xa0\xf9\x38\x7f\x90\x14\x43\xeb\xf6\x09\xb1\x41\xeb\x8b\x2f\x1c\x06\x7f\x36\x7e\xb3\xe7\xc5\x19\x0a\xd2\x18\x43\x21\x01\x32\x94\x4c\x88\x92\x00\x25\xa1\x4a\x33\x82\x4c\x52\x54\x95\xaa\xd2\xb2\xc8\x10\x0c\x41\x55\xa0\x04\x49\x24\x91\x35\x51\x92\x64\x4c\x66\x6a\x18\x81\x93\xa4\xc0\x78\x9e\x97\x38\xce\xf3\x12\xf9\x9e\xb7\x4a\xd6\x32\x3c\xaf\xf7\x34\x1c\x2d\x1e\xeb\x79\x1b\xb1\x2e\xdf\xf3\xbc\x03\xa2\x71\xc5\x0e\x28\xfa\xb9\xde\x24\xed\xf6\x43\x6b\x80\x8f\x48\x16\xeb\xa1\xb7\x61\xf5\x76\xc4\x68\x7d\x9c\xad\xa1\x47\x45\xda\x74\x6c\x6f\xc0\xa7\x7b\x5e\x76\xcc\xbd\x28\x2f\x02\x6a\xad\x1a\x96\x79\x57\xd7\xee\x3a\x4b\xeb\x0a\xa3\x1f\xec\xdb\x66\xdd\x9c\xe9\xd6\x72\xde\xbd\xbf\x9a\x32\x4f\xd3\x57\xca\x5e\x3d\x6e\xe6\x56\x65\x6a\x8f\xa9\x46\x0f\xad\x07\x3d\xe6\xf6\x5d\x94\xdf\x6f\xef\x70\xec\x51\xad\xbf\xbd\xad\x34\x6a\x56\x1d\x76\xe4\xd7\xce\xcd\x3f\xcb\xf3\x1e\xeb\xf9\x8e\x1d\xed\xbd\x55\x77\x61\x9e\xd0\xf3\xb2\x95\xe7\x6e\x95\xad\xbc\xaa\x33\x6e\x88\x30\x69\x3a\xad\x3c\xb4\xc5\xe6\xfd\x9a\xb9\xbf\x5a\xa9\xed\x77\x91\x9c\x36\x71\x1a\xde\x92\x1d\x05\xf7\x70\x9e\xda\xf3\xfe\x97\x3c\x1f\x7b\x22\xcf\x5b\xa5\x76\xed\x3b\xa5\x75\xf1\x37\x37\xbf\x79\x5e\x3c\x92\x73\x91\x35\xef\x36\xb3\x97\x8d\xd2\x35\x87\xb5\xc1\x83\x30\xbe\x5f\x41\xea\xae\xdb\xd5\xc7\xd8\x10\x1f\xa8\x78\xe7\x4b\x57\x6c\x59\xba\x30\xc0\xbb\xd3\x25\xfb\xda\xb6\x26\xaf\x03\x05\x6a\x6d\x46\x19\xdb\x52\xcb\xb8\x7f\xb9\xed\xdd\x7e\xe9\x0c\x9b\x9b\x36\xb5\xa9\xcf\x7e\xf3\x9a\x57\x20\x50\x95\x90\x04\x28\x08\x18\x41\x09\x44\x05\x62\x22\x89\x53\x98\x08\x2b\xb8\x54\x85\x62\x4d\x10\x2b\x78\x95\xc4\xe5\x9a\x4c\x43\x52\x90\x98\x1a\x12\x21\x29\x55\xab\xb2\x80\x21\x91\x16\xcf\xb6\x15\x83\x47\x78\xde\xbc\xb4\x07\x85\xd5\x6a\x74\x56\x61\x8d\xf7\x34\x9c\x17\x3b\xd6\xf3\x36\x63\x5d\xbe\xe7\x79\xcb\x66\x3d\xd2\x3d\x6f\xf3\x76\xa9\xe2\x76\xf7\xa6\xdb\xa2\x1e\xd6\x2b\x1b\x93\x9a\x8d\x07\x4e\x66\x6c\x81\x56\x29\x61\xd3\x33\x6f\x66\x0d\xe3\x8b\xfa\xf0\xd2\x5b\xac\x45\x9b\xa6\x94\xbe\x4c\x2c\xd6\xf6\xeb\x9a\xe9\x49\xf4\xcb\x2d\xc5\x51\x4d\x55\xb4\x64\x8a\xe1\xd8\x79\xfd\x66\x3c\x1d\x5a\x5a\x55\x7e\x6e\xfe\xb3\x3c\xef\xb1\x9e\xef\xd8\xd1\xde\xc5\xde\x98\xe6\x09\x3d\xef\xef\xcc\xf6\xfc\x0a\xcf\x7b\xa8\xe7\x63\x4f\xe4\x79\x0f\x8d\x7f\x7c\xcf\xbb\x11\x0c\x49\x18\xaf\x95\x35\x6a\x89\x62\x57\x6a\xdf\xaf\xd4\x51\xfb\x8b\xf9\xf8\xe5\x05\xdd\x54\x5f\xef\xd6\x3a\xfb\x2e\x1b\x0f\x8f\x93\x5b\xeb\xa9\x8b\x50\xe7\xf5\xa9\x66\x58\xc2\x73\x15\xbd\xb6\xd1\xe3\x18\xd5\x07\x2c\xfd\xd4\x6d\x7f\x19\xcc\xd9\xce\xfd\xe8\x4d\x6d\x56\x6e\xaf\xda\x04\x7b\x92\x35\x6f\x4a\x56\x3b\xeb\x82\xbd\xb2\x09\xed\xf8\x25\x7b\x5b\x5f\x8e\xd6\x46\x70\xcf\x80\x7b\x0b\x97\x57\x51\xe6\x88\x94\x75\xae\x2b\xe1\xf6\xbc\x23\xb6\xc7\xd2\x2e\x79\x2b\x7f\x40\x27\xfa\xa6\xf2\xc8\x37\xde\x78\x43\x9b\x00\xfd\xee\xf6\xf6\xb2\xf7\x4e\x45\x70\xba\x97\x97\xb1\xcd\x66\xf8\x36\xf8\x7d\xa2\xe1\x5b\xb7\xc1\xf9\xee\xee\xb9\xd4\x57\x8d\xef\x70\x9c\x96\xe7\x4c\x76\xf7\x39\xdd\xdd\x7a\x97\xfb\x52\xf4\xfd\x17\x86\x9f\x58\xdb\x3e\xda\x4c\x09\xc2\xa4\xa3\x92\x78\x4f\x2e\x41\x96\x44\xa1\xd7\x68\x87\x2f\x42\x39\x91\x1c\x3b\x8c\x89\x22\xc4\x08\x46\xb9\x4f\xe0\x36\xfe\xe2\xef\xd8\xf7\x13\x71\x1d\xc3\x9a\xc4\x79\x12\xe1\x98\x15\x6d\xaf\x2e\xbc\x8c\xdc\x7b\x78\x19\xba\x26\x31\xef\xc5\xdf\xf1\xef\x27\x92\x2f\x86\x35\x49\xbe\x24\xc2\xb9\xbd\x13\xbb\x47\x30\x76\xa6\x6f\xa7\x10\x7e\xa7\x01\x3e\xac\x1a\xfe\x24\xd2\x45\xc9\x26\x09\x77\x10\x63\xc1\x1b\x5e\x13\x3a\xd6\x81\x8f\x76\x72\x49\xd5\x9c\xa6\x5b\x4b\x0b\x5e\xaa\x53\x53\xaa\x0a\x73\x4a\xf7\x4e\x2b\x59\x32\x91\x2c\x49\x33\xd8\x2a\x2c\x79\x6a\x99\x41\xee\x4e\xfe\x69\xa5\x4f\x23\x93\x25\x7f\x26\x6b\xb9\x1a\x88\xaf\x9e\x62\xdf\x4f\x24\x5f\x0c\x6b\x92\x38\x49\x84\xa3\xdc\x27\xad\x2b\xfc\xcb\x8a\xbd\xff\x9d\x88\x59\x0f\x59\x12\x8f\x21\x32\x51\xd6\x82\xfb\xbe\xb2\x2e\xf9\x0d\xff\x7d\x22\x4e\x43\x18\x93\xd8\x8d\x13\x2c\xbd\x5a\xf3\x16\x7a\xbb\xa5\x05\xaf\xc1\xc5\x76\xb1\xee\xbe\x00\xa3\xd8\x65\xc5\x91\x37\x67\x67\x22\x07\x83\x7e\x6c\xa5\x1b\x79\x5f\xc6\x0e\xfa\x12\x38\xe0\xe9\x9c\xcf\xf5\x05\xe2\x25\x7d\x01\x15\xed\x00\x86\x63\x9c\x86\x90\x85\x19\x8c\xbd\x55\x7a\x07\x94\xce\x96\xa2\xc9\xaa\xe7\xac\x24\xf7\x95\xc9\xee\xdf\xc7\x33\x98\x88\x36\x9d\xd5\x44\xf0\x94\x75\xa3\xb0\x71\x27\xc2\xc3\x79\x0c\x63\x09\xbf\x15\xc5\x9f\x27\xa3\xfd\xbb\x9d\x78\xd3\xb9\xf1\xa6\xdf\xe3\xf9\xf1\xef\xa8\x2e\xc4\x51\xca\x94\x2f\x6c\xef\x6d\x38\x98\x9d\x1d\x8a\x94\xb7\x99\xc7\xf9\xf1\x80\x2f\xf7\xde\x21\x91\xc4\x5c\xe8\xfe\xfc\x62\x0c\x1a\xba\x65\xcf\x4c\x64\x25\xf2\x19\xbe\x8d\xbf\x10\xaf\xa1\x06\x17\xe0\xb1\xcd\x8d\xb8\xc8\x8d\xfe\x9d\xf1\xf6\x02\xec\xef\x7b\xac\xcf\xa1\x35\x3f\x01\xcf\xee\x1b\x06\x06\xfd\xcc\x57\x88\x44\x5f\x07\x14\x7b\x3d\x41\x92\x5a\xbd\xf7\x0d\x9c\x88\xc3\x1d\xb2\x62\x4a\x4d\x7e\x8b\x42\xa0\xdf\x94\x77\x2c\x64\xaa\xda\x9b\x08\x8e\xb1\x60\xff\x5a\xf3\x42\xfc\xc7\xde\xba\x72\xb9\xff\x82\x95\xbc\x90\xf0\x68\x97\x94\x82\xcf\xe1\x3f\x1e\x7d\x16\xf5\x4e\x09\x28\x8f\xf4\x53\xa9\x18\x0b\xb2\x99\x11\xa5\xf0\xc8\xc1\xe6\xea\xfa\xd8\xc9\x3c\x86\x2e\x6c\x02\xc1\x4d\x07\xd1\x49\x32\xe1\x3d\x99\x97\xc1\x3b\x31\xd3\x98\xdd\xdd\xa8\x7e\x24\x9b\xd1\xd7\x72\x65\x32\x18\x5e\x69\x1c\xc0\xb4\x6e\xf0\xc6\xa9\xf8\xf6\x71\x85\x59\x4f\x89\xd4\x0e\x92\x24\x59\x00\x7b\x7d\x3a\x01\x7c\x5c\x29\xfe\xe1\x40\x11\xa2\x2f\x1e\xdb\x17\x42\x37\x1c\xab\x9c\xeb\x07\xc9\xe0\x33\xbf\xc3\x71\xa8\xf2\xb3\x15\xbd\x7d\x8d\xbb\x33\xb8\x8f\xd7\x75\x14\x5d\x98\xe5\xe0\x30\x75\x74\x26\x49\xe4\x28\xac\xd7\x53\xb1\xb5\x87\xb3\xe0\x54\x97\xc0\xa0\xed\x75\x89\x7d\x4c\xb7\xee\x70\x1c\x6e\x92\x79\xe6\x67\x9b\x92\x43\x24\xfc\xda\xdd\x23\x18\xde\x47\xb6\xff\x7e\xc1\x28\x9f\xb1\xf7\xfd\x66\x33\xe8\x86\xaf\xa7\x61\xcf\x45\x55\x88\xb9\xd4\x98\x39\xc0\x17\x7b\x93\xf0\xd1\xfc\xc5\xf0\xe5\x31\xb9\xff\x22\xe3\x5c\x4e\x4f\xa3\xc7\x08\xb6\xa2\x5c\xe6\x6a\xf3\x34\xbc\x15\xe2\x29\x9b\x97\x80\x63\xef\x05\x9d\xc7\x71\x14\xc5\x55\xb8\x47\x83\x17\x1e\x27\xf2\x67\x40\xc5\xe4\xdd\xf7\xb3\x9d\x82\xc3\x38\xb6\x62\xe3\x36\xe3\xd5\xb5\xf1\xb7\x94\xa6\x08\x71\x02\xbf\xed\xe3\xc9\xe3\xb8\xe4\xea\xc8\xc1\x7a\x32\xed\x96\x50\x6c\xae\xde\xbc\xdb\x6e\xf7\xee\x63\xd4\x35\x1e\x4a\x92\x89\x2c\xeb\x58\x85\xe6\x12\x88\xe4\x22\x12\x13\x37\x3e\x60\x09\xde\x8f\xb7\x83\x2c\xdc\xf9\x1c\x27\x8c\xb2\x28\x42\x7f\x15\xee\xe0\xb3\x37\xc6\xe1\x41\x5d\x26\xd6\xdc\x65\x7f\xe2\x56\x5d\x14\xa5\xbf\x86\x72\x50\x6e\x8d\xe8\x44\xdc\x26\xa1\xce\x5d\xbe\x15\xb5\xe4\x10\xf2\x53\x1b\x43\x04\xf5\x21\xeb\xcd\x74\x74\x0b\x43\x37\xdd\x77\xa5\x7b\x6f\xca\x39\xbd\xa2\xe3\x14\xf2\xd9\x8f\x35\x28\x2e\x8c\xef\x7a\x8a\x27\x8c\x0e\xd0\x7f\x88\x46\xae\x24\x21\xd8\xe2\x42\x18\x26\xfa\x50\xf4\xa5\xf5\x5b\xa4\x49\x22\x96\x2b\x56\x52\xa3\xe2\xf2\x05\x09\xa9\x5f\x26\xd3\xf6\x75\xad\x79\x72\xa4\x66\x74\xa3\xa8\x77\x17\x21\xfc\x8a\xa1\x1d\xc7\x9e\x18\x00\x97\x1d\xe0\x51\xa4\xd1\x10\xea\x44\x23\x3c\x8b\x44\x11\x19\x72\xe2\xba\x4c\x62\xa7\x9b\xbe\xf6\x11\x17\xe2\x3d\x7f\x12\x0b\x07\xdb\xbf\xc2\x6c\xf6\xf1\x1f\x1c\xea\xfb\x9b\xad\x4e\x60\x19\x7a\x2f\xec\xc1\x0a\x4e\x46\xe7\x70\xe7\xef\x21\x47\x97\xe1\x21\x98\x0c\xce\x92\xde\xee\x79\x02\x0e\x13\x5f\x1a\x9a\xc2\x69\x12\x6c\x06\xc7\xde\x0b\x7d\x4f\xc0\xa3\x87\x28\x8d\xab\xed\x7b\x83\x73\x58\x39\x65\xbf\x46\xdf\x2f\x9c\xc1\x58\x7a\xcf\x06\x75\x76\x27\xd8\xd8\xdb\x47\x15\xd9\xdb\x0e\xaa\x0b\x53\xb6\xb7\x13\x0a\x09\xa0\x84\xb6\xcb\xda\x20\xdf\xce\x0b\xba\xfe\x76\x30\x8b\x19\x38\x73\x17\xcc\xe7\xe7\x12\xb2\xa1\xa2\x5a\xe0\xeb\xbf\xff\x0d\xce\x2c\x5d\x95\x42\xa5\x55\x67\xd7\xd7\x36\x5a\xdb\x17\x17\x97\x20\x1d\x50\xd4\xa5\x62\x80\xde\x56\x46\x3a\xa8\xa0\x2f\x67\x73\xbb\x10\xf9\x08\x68\x36\x03\x11\xd0\x18\x0b\xc1\x76\x9b\xeb\x72\xc1\x0f\x40\x92\x59\x95\x1f\x21\x1b\x38\x66\xa2\x4b\xc5\xe8\x74\x56\xb8\xd0\xa4\xb8\x4d\x45\x10\x1e\xb9\x61\x95\x88\x2d\x9b\xb5\xac\x8d\xaa\x18\x3a\xb7\x60\xcf\x2d\xe0\x3b\x2d\x9b\x71\xbc\x05\x18\x0e\xd7\x02\xee\x17\x7f\x16\x2e\xbf\x55\x24\x5e\x0e\x55\x01\xb5\xee\x7e\x4f\x11\xae\x4f\x16\xb4\x06\x23\xae\x73\xd3\xdf\x16\x86\x81\x11\xd7\xe2\x46\x5c\xbf\xc1\x8d\x63\x05\x11\xee\xd3\x41\x1f\x4c\x87\x4d\x47\x8d\x23\x6e\x3c\x19\x75\x1a\x13\xe7\xa7\x26\xd7\xe5\x26\x1c\x68\xb0\xe3\x06\xdb\xe4\x32\xaa\xeb\x24\x64\xc5\xbe\xf2\xb1\x0c\xf5\xe9\x94\x11\xa5\x93\x53\x3a\x97\xc6\x49\x54\x3f\xf1\x6c\x7a\xa2\xb2\x7c\xd7\x9e\x53\x67\x98\xaa\x09\x3f\xc3\xf7\x5f\xd7\x43\x98\x8f\x24\x2d\x04\xc9\xd3\x6c\x83\x29\xa7\x81\xfd\x5c\xfb\x7f\x51\x0d\x29\xcc\x44\x75\x91\xb0\x3b\x70\x5a\xa3\x88\x67\x7e\xff\x09\x0a\x49\x37\x8d\xbd\xd4\x7a\xae\x75\x78\x9a\x98\xcc\x11\x90\x75\x55\xd5\x57\x8a\x36\x03\xcd\x66\x17\x28\x16\x10\xa0\xa5\x88\x50\x55\x37\x00\x6a\x1b\xb0\x80\x9a\x62\x2c\x55\x3f\xe0\xb1\xe7\xd0\x06\x73\x68\x18\x48\x03\xb6\x0e\xec\x39\x02\xde\x7b\xa8\x81\xa5\x38\xc1\xf5\xb6\xa0\x1d\x50\x95\x6f\xa0\x23\x83\x8d\xbe\x04\x1a\x42\x92\x03\xad\x68\xa2\xba\x94\x90\x43\x18\x6a\x60\x69\x48\xd0\x46\x40\x97\x03\x0c\xb2\x6e\x02\x7b\xae\x58\xc0\x12\x91\x06\x4d\x45\x77\x8b\x53\x90\x26\xb9\x64\xce\x96\xc6\x19\x30\x74\xd3\x45\x2e\x9b\xfa\x02\x68\x68\x85\x2c\x3b\x44\x12\xda\xc0\x81\x9e\x23\x13\x5d\x02\xdd\x9e\x23\x73\xa5\x58\xe8\x12\xd8\xc8\xb2\x2d\x87\xea\x4a\x51\x55\x60\x2e\x35\xa0\x68\xb6\x0e\x0c\xdd\x46\x9a\xad\x40\x15\x20\xd3\xd4\x4d\x0b\xac\xe6\x8e\x54\xce\x3f\x92\x10\x42\xbb\x34\xae\x24\x7d\xa5\x59\x00\x9a\xc8\x6d\x0d\x97\xb6\xbe\x80\xb6\xaf\x24\x61\xe3\xf2\xe7\x12\xf9\xe6\x50\x89\x74\xf9\x36\x2d\xeb\xf4\xb1\xff\xb6\x3f\x30\xe1\x9e\x26\xdf\x53\x6a\x09\x9d\x95\xb4\x0f\xb6\x5f\x40\x58\x9f\x8c\x38\xee\xdc\x7f\xee\x74\x63\x12\x29\xaf\x70\xb3\x28\x3d\xb7\x0c\x34\x99\x68\xb8\x02\x34\x93\x72\x78\xc6\xce\xa1\x1b\x9b\xff\x43\x54\xf7\xa7\xfd\x4c\x9a\x7e\x74\x91\x43\x2e\x14\x9e\xec\x28\x45\x02\x93\x4c\x22\x05\xca\xe2\x9b\xa3\xc1\x10\x34\x06\xdd\x69\xaf\x0f\x14\x29\xa5\x7d\x66\x61\xf9\x1e\x06\xf7\x07\xbf\x4f\x43\xab\x17\x11\x5a\x22\x94\x50\x00\x90\x59\x4c\x15\x05\xca\x4d\x42\x64\x40\x47\xf3\xd7\x11\xc0\x68\x85\x6a\xae\xe4\x5e\x67\x05\x1e\xdb\x7d\x3d\x24\xf8\x80\xa6\x38\x87\xe6\x39\x53\xbb\xf0\x8f\x2f\x3a\x30\xa1\x32\xc5\x14\xb8\xef\xd9\xdd\xe4\xdb\x85\xbe\x34\xc5\xc3\x30\x05\x41\x97\xcb\xb1\xb7\xeb\x93\xda\xde\x71\xa6\x60\x31\x53\x02\xc7\x57\x03\x51\x1b\xec\xb4\xdc\xea\x3f\xee\xa9\x33\x9e\x8c\xbd\x8d\x33\x38\x9b\xb9\x9b\x67\x96\x0d\x17\x86\xfb\xb6\xc7\xfd\xfd\x33\x9e\xc1\x30\x0c\x0b\x56\xc0\xa6\xa2\x9d\x6f\x5b\x78\x0e\x3c\x44\x93\xc6\x02\x92\x9e\x18\xb1\x57\x3a\x82\x73\xd7\xd0\x14\x09\x38\xf1\xd3\xb6\x16\xf1\x12\x7c\xfd\x0a\xe6\x68\xfd\x15\x69\x4e\x0f\x4a\x60\xa8\xeb\x6a\xa7\xe9\xc2\xba\x91\x95\xb5\x80\x4e\xb8\x1e\x6a\xe1\x3e\x93\x11\x72\x3c\x28\x9a\x21\x33\xf6\xc4\x1d\xc3\xce\x10\xf6\x26\x2d\x20\x28\xb3\x70\x73\xd0\x68\x73\x8d\x3b\x70\x1e\x07\xfb\x37\xc0\x2e\x3c\x04\xd6\x1c\x9a\x69\x8d\x9b\x5c\x8b\x9d\x76\x27\x00\xf3\xd0\x9c\x87\x61\xff\xfd\x63\x8b\xc2\xb3\x4a\x13\x59\xc8\xfc\x40\x16\x78\xb5\x74\x4d\x88\xb1\x99\x98\xe0\x49\x96\x48\x42\x2a\xb2\x91\x04\x04\x5d\x57\x11\xd4\xf6\xb9\x71\x5f\x9e\xe6\xc1\xc6\x0f\x7b\x7c\x72\xfa\x29\x62\x0a\xb1\x7e\x71\xe3\xc8\x28\xbb\x83\xfe\x5e\xe7\x79\x16\x30\x53\xb4\xf3\x24\xd1\x78\x03\xda\x73\x5e\x37\xac\x8b\xef\x71\x5a\x1f\x28\xfe\x6e\xcf\x74\xf4\xae\x1b\x04\xe7\xbe\xb8\x97\x89\x2a\x0a\x89\xb3\xbd\xa7\x73\xeb\x26\x62\x92\x79\x57\x6c\xba\x6a\x19\x4f\xd8\xd1\x04\x3c\x76\x26\x6d\x80\xbb\x3f\x74\xfa\x8d\x11\xd7\xe3\xfa\x13\x50\x7f\xf6\x7f\xea\x0f\x40\xaf\xd3\x77\xcf\x0e\x6f\xbf\xb3\x4f\xbb\xef\x0d\xb6\xd1\xe6\x00\xbe\x63\x20\x3a\x5c\x53\xed\x3d\xcd\x86\x34\xb4\x8e\xde\x15\x9a\xcc\xff\xd9\xf5\xb5\x89\x66\xa2\x0a\x2d\xcb\xb7\xae\x28\x1c\x1f\x1f\x52\xe1\x2e\xcf\xda\x97\x88\x51\xdb\xdf\xc1\x4b\xec\xa4\x70\xb6\xf6\x20\x22\xfb\xdc\x17\xa5\xb9\xd7\xf2\x22\xad\x2f\x76\x73\x65\x72\xaf\x24\x15\x2c\xc4\xfb\xe9\x32\x02\xb9\xcf\x75\x0c\xbc\xa0\xd6\x53\x39\xf3\xf4\x6f\x25\x57\x19\x66\xaa\x25\x51\x98\xcb\x74\xce\xe3\x83\xb4\x04\x83\x11\x12\xa7\xe1\xf4\x08\x6e\x8e\xe2\xa1\xb8\x31\x85\x17\x4e\xd9\xe6\x14\xdb\x6b\xfa\x2d\x06\x95\xc1\x5d\x82\x49\x65\xc9\x52\xa0\xc8\xf1\x70\xb3\xca\x61\x33\x7d\x97\xee\x48\x8e\x8f\xe2\xea\x48\x4e\x12\x4d\x2c\x2b\x66\x49\x76\xec\xd9\xd1\x4b\xa2\x3b\x4d\x8b\x63\x12\x39\x0a\xad\xa6\xa3\x95\x82\x7b\x4f\x62\x75\x7b\xa9\xab\x6d\x09\x59\x5e\x44\x11\x94\x01\x7a\xa6\x9f\xf2\xf1\x90\xc4\xf2\x6b\x5e\xfb\xe8\xd0\xc9\x6c\xbf\x9f\x8d\x29\x83\xa2\xd9\xf4\x18\x48\x1b\x95\xb9\xad\xb7\xaa\x39\x14\x41\xac\xa1\xbf\xbe\x8d\x2f\xde\x22\x85\xb6\x99\x33\x69\xa4\x00\xce\xeb\xfd\xe4\x46\xf1\x11\x12\xaf\x41\x2d\x4b\x25\xb5\x5d\x10\x31\x6c\x93\x1a\x34\x1e\xb6\xb0\x4e\x2b\x08\x4f\x42\x5b\x6f\xa9\x00\xe1\x73\x6d\x71\xb4\x44\x96\x5d\x3a\xba\xde\xbd\xa1\x7d\x17\x5e\x04\xab\x32\xdc\x5f\xd9\x87\x60\x9c\xd0\xe0\xfb\x27\x3f\xf7\x1d\x43\x37\xe6\x26\x61\x74\x3f\x00\xe1\xef\x0b\xa5\xf4\x50\xe8\x18\x16\x18\x8c\x32\xcc\x26\x72\x5e\x2b\xb1\x83\x42\x64\xb3\x7b\x64\x07\x58\xe0\x20\x4b\x54\x95\x54\x72\x7a\xc7\x0b\x6d\xfd\x22\x95\x58\xf0\xf2\xbd\x40\x0b\x27\x8a\xf4\x07\x86\x47\x12\x4a\xaf\x4b\xcb\x06\x8a\x0d\xfe\x85\x3e\x90\x09\xe0\x0c\x2a\xda\xbf\xbe\x25\xe7\x96\x22\xd7\xa5\xb8\x00\x7e\xe6\xc2\x7b\x00\x26\xcf\x43\xce\xf7\x9c\x31\x71\xe8\xd8\x14\xbf\x7b\x93\xfd\xee\x9d\xf3\xfe\x9c\x9e\xff\x41\x1a\x14\x54\x3f\x2c\xdb\x75\xaa\x84\x64\xb8\x54\xed\x70\x4c\x96\xff\x59\xcd\x15\x1b\xa9\x8a\x65\x07\xa1\xfd\x9f\x7f\x15\x73\x5c\xa1\x4f\x24\x5a\xca\x5a\x4c\x84\xb3\x3a\x07\x08\x7e\x32\xb1\x8f\x17\x3a\x5f\xe4\xaf\x5f\x81\xa2\x59\xc8\xb4\xdd\xfc\x68\xc0\xa4\xa4\x58\x9e\x0c\x96\x0d\x6d\xe4\x26\x7d\x11\x14\xe7\xc0\x5a\x1a\x6e\x81\x9f\x04\x3c\xbd\x00\x65\x61\xa8\x68\x81\x34\xdb\xb5\x9f\xc8\x9d\x53\x89\xa6\x13\x5c\x3c\xe5\x69\x01\x9c\xfd\xfd\x9f\xb3\x4b\x10\xbf\x7e\x30\x41\xf3\xa9\xed\x62\xf6\x5b\xc9\x5f\xa2\x5a\x3e\x66\x24\xf1\xf6\xc2\x00\xec\x18\x7c\x02\xc0\x42\x2a\x12\x6d\xf0\x2f\xd0\x1a\x0d\x7a\x89\xad\x3e\x01\xdf\x6f\xc5\x0e\x67\xba\x7e\xc8\x4b\x31\xe5\x5d\xa1\x18\x25\xfc\xbf\x3b\xc4\xff\x77\x87\x78\xf4\xa2\xba\xff\xdd\x21\xfe\xbf\x3b\xc4\x8b\xe9\xe2\x7f\x77\x88\x67\xdd\xa7\xe8\x6d\x9b\x0e\xbd\x1b\x05\xc6\xf7\x5d\x20\x41\x1b\x3a\xcb\x4d\x20\x2d\x17\x06\x10\x75\x67\xd2\xb2\x91\x03\xf7\xff\x02\x00\x00\xff\xff\xd9\x0e\x0e\xc9\xae\xf3\x00\x00") func baseHorizonSqlBytes() ([]byte, error) { return bindataRead( @@ -166,7 +166,7 @@ func baseHorizonSql() (*asset, error) { } info := bindataFileInfo{name: "base-horizon.sql", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} - a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x60, 0xb7, 0xfd, 0x8c, 0xcc, 0xb0, 0x6d, 0x86, 0x11, 0xc3, 0x5c, 0x57, 0x59, 0xd8, 0xf4, 0x41, 0x8d, 0xfc, 0x95, 0xf2, 0x23, 0x5a, 0xcd, 0x38, 0xc3, 0x6c, 0xc2, 0xf0, 0x5f, 0xba, 0xa7, 0x33}} + a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x4e, 0x8e, 0x45, 0xa, 0x44, 0x0, 0x7, 0x7a, 0x9c, 0x13, 0xf4, 0x57, 0x52, 0x36, 0x78, 0x60, 0xb0, 0x65, 0xf4, 0x9a, 0x30, 0xf6, 0x4, 0x7d, 0xa5, 0xee, 0x9, 0x1d, 0x5a, 0xf9, 0xda, 0x74}} return a, nil } @@ -190,7 +190,7 @@ func failed_transactionsCoreSql() (*asset, error) { return a, nil } -var _failed_transactionsHorizonSql = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\x7d\xf9\x6e\xe2\xc8\xf6\xf0\xff\xfd\x14\x56\xeb\x4a\xe9\xfe\x25\xdd\x78\x5f\x7a\xbe\xbe\x92\xd9\x09\x60\x76\x08\x19\x8d\x50\xd9\x2e\x1b\x07\x2f\xc4\x36\x01\x72\x75\xdf\xfd\x93\x17\xc0\x18\x1b\xcc\xd2\x99\x99\xab\xb1\x5a\xad\x80\xab\xce\x56\x67\xab\x53\xc7\xf8\xdb\xb7\x4f\xdf\xbe\x21\x6d\xcb\x71\x55\x1b\xf6\x3a\x0d\x44\x06\x2e\x10\x81\x03\x11\x79\x61\xcc\x3f\x7d\xfb\xf6\xc9\xbb\x5f\x5c\x18\x73\x28\x23\x8a\x6d\x19\xbb\x01\x6f\xd0\x76\x34\xcb\x44\xb8\xef\xf4\x77\x2c\x32\x4a\x5c\x23\x73\x75\xe2\x4d\x8f\x0d\xf9\xd4\x2b\xf5\x11\xc7\x05\x2e\x34\xa0\xe9\x4e\x5c\xcd\x80\xd6\xc2\x45\x7e\x22\xe8\x6f\xfe\x2d\xdd\x92\x66\x87\xdf\x4a\xba\xe6\x8d\x86\xa6\x64\xc9\x9a\xa9\x22\x3f\x91\xbb\x41\xbf\xcc\xde\xfd\xb6\x01\x67\xca\xc0\x96\x27\x92\x65\x2a\x96\x6d\x68\xa6\x3a\x71\x5c\x5b\x33\x55\x07\xf9\x89\x58\x66\x08\x63\x0a\xa5\xd9\x44\x59\x98\x92\xab\x59\xe6\x44\xb4\x64\x0d\x7a\xf7\x15\xa0\x3b\x70\x0f\x8d\xa1\x99\x13\x03\x3a\x0e\x50\xfd\x01\x4b\x60\x9b\x9a\xa9\xfe\x16\xd2\x0e\x81\x2d\x4d\x27\x73\xe0\x4e\x91\x9f\xc8\x7c\x21\xea\x9a\xf4\xe0\x31\x2b\x01\x17\xe8\x96\x37\x8c\x6f\xf4\x4b\x5d\xa4\xcf\xe7\x1b\x25\xa4\x56\x46\x4a\x4f\xb5\x5e\xbf\x87\xb4\x84\xc6\x38\x1c\xff\x7d\xaa\x39\xae\x65\xaf\x27\xae\x0d\x64\xe8\x20\xc5\x6e\xab\x8d\x14\x5a\x42\xaf\xdf\xe5\x6b\x42\x3f\x32\x69\x7f\xe0\x44\xb2\x16\xa6\x0b\xed\x09\x70\x1c\xe8\x4e\x34\x79\xa2\xcc\xe0\xfa\xb7\x8f\x40\x28\xf9\x7f\x7d\x04\x4a\x4f\xaf\x3e\x8e\xc1\x00\xdb\xf9\xdc\x05\x04\x7a\x8a\x7c\x0c\x59\x64\xd4\x0e\xb8\x3f\xbc\x26\x14\x4b\x4f\x91\x91\x21\x58\x9f\xaa\x09\x54\x14\x28\xb9\xce\x44\x5c\x4f\x2c\x5b\x86\xf6\x44\xb4\xac\xd9\xf1\x89\x9a\x29\xc3\xd5\x24\xc2\x9c\xe9\x00\x5f\xd1\x9d\x89\x65\x4e\x34\xf9\x9c\xd9\xd6\x1c\xda\x60\x3b\xd7\x5d\xcf\xe1\x15\xb3\x77\x94\x5c\x45\xc5\x79\x73\x75\x28\xab\xd0\xf6\x27\x3a\xf0\x75\x01\x4d\xe9\x2c\x16\x22\xd3\xe7\x36\x7c\xd3\xac\x85\x13\x7e\x37\x99\x02\x67\x7a\x21\xa8\xeb\x21\x68\xc6\xdc\xb2\x3d\x73\x0c\x7d\xea\xa5\x60\x2e\x95\xa5\xa4\x5b\x0e\x94\x27\xc0\x3d\x67\xfe\x46\x99\x2f\x50\xa5\xd0\x2e\x2f\x20\x3a\x3a\x13\xc8\xb2\x0d\x1d\xe7\xf8\xf4\xa9\x6b\xcb\x7e\xdc\x99\xe8\x96\x35\x5b\xcc\x33\x8c\x9e\x9f\x22\x29\x18\x05\x34\xfb\x4c\xc0\x1b\xa7\x9b\x79\x82\xe7\x27\x14\x05\xda\xd9\x86\x6e\xc0\x5f\x30\x25\x14\x6b\xb6\x49\xbe\x6b\x3d\x03\x49\xd4\x15\x9f\x9a\x31\xf7\x26\x4c\xdd\x93\x2b\xe0\xec\x39\x20\x71\x7d\x52\x8d\xa6\x5b\x4b\xcf\x32\xd8\x0a\xe8\xb0\x4e\x0e\xd4\x1c\x77\xe2\xae\x26\xf3\xd3\x20\xbd\x91\xd6\x3c\xeb\x48\x98\x75\xd8\x26\x94\x1c\x1f\x2c\x6e\xcc\xfd\xe4\xb0\xd3\x5e\x4c\x5c\x67\x5b\xcc\x20\x46\x7a\xd2\x76\x9c\xc5\x29\xcc\xdb\xc1\x92\x25\xc3\x33\xf3\x82\xad\x1a\xcc\x81\xed\x6a\x92\x36\x07\xe6\xd1\xe0\x7d\x6a\xea\x64\x7e\x66\x6e\xb2\x8d\x68\xe7\x52\x90\x3c\xf1\x6c\xfc\xbe\xf0\xb2\xe0\x0b\x06\xfe\x72\xf8\xc1\x62\x7a\x2b\x19\xfe\xe9\xc5\x87\x4d\xea\xe7\x2b\xc3\x24\x23\x05\xaa\x65\xcf\x27\x86\xa6\x86\x09\xc3\x11\x12\x62\x23\x33\xf3\x78\x7e\xbe\x77\x0c\x72\x56\xe5\x0c\x66\x17\x5a\x8d\x41\x53\x40\x34\x39\xc0\x5c\x2c\x95\xf9\x41\xa3\x9f\x11\x76\x8a\xd2\xdd\x00\x72\xb8\xdc\xc7\x21\xf9\x9f\xb2\xb3\xbf\x89\xd2\xbd\x52\x67\x50\x12\x0a\x17\xc8\xcc\xcb\xb3\x1d\xf8\x7a\x36\xe6\x3d\x20\x99\x67\xcb\x30\xe3\xd8\x5d\x36\x9b\x99\xc3\x14\xab\x3f\x87\xbf\x64\x10\xd9\xe6\x86\x79\x5f\xb6\xc1\x61\x92\x97\x99\xb7\xd0\x03\x9c\xc3\x4b\x30\x25\xe3\xd8\x30\xfd\xcb\x4e\xcf\x26\x5f\xcc\x42\x51\xcc\x87\x1c\x1f\x1c\x71\x09\xe1\x40\xbe\x52\xe9\x96\x2a\x7c\x3f\x61\xb0\xa1\x79\x3b\x0e\x4d\x82\x5f\xcc\x85\x01\x6d\x4d\xfa\xfd\x8f\xaf\x19\x66\x81\xd5\x05\xb3\x74\xe0\xb8\x5f\x80\xb9\x86\xba\x5f\x8a\xc9\x30\x43\xd1\xec\xc4\x29\xe5\x81\x50\xe8\xd7\x5a\xc2\x11\x7e\x26\x40\x55\x77\xd4\x3d\x20\x07\x84\x1e\x81\xb1\xe1\xee\x0a\x18\x1e\xaf\xfe\xf4\x1d\xf1\x0f\xc8\x39\x8c\xf8\xac\x67\x80\x50\x7a\xea\x97\x84\x5e\x0c\x84\x3e\x57\x9d\x57\x7d\xa3\x8b\x85\x6a\xa9\xc9\x1f\x60\xf8\xed\x53\x50\x85\x13\x80\x01\x7f\x6c\xbe\x43\xfa\xeb\x39\xfc\x11\x4e\xf9\x0d\xe9\x49\x53\x68\x80\x1f\xc8\xb7\xdf\x90\xd6\xd2\x84\xf6\x0f\xe4\x9b\x5f\x9c\x2b\x74\x4b\xde\x7a\x85\x90\x37\xf0\x3e\xed\x41\xdc\xbf\x19\x02\x2e\xb4\x9a\xcd\x92\xd0\x3f\x02\x39\x18\x80\xb4\x84\x7d\x00\x48\xad\x87\xdc\x6d\xca\x6e\x9b\xef\x1c\x1f\xc8\x5d\x1c\xf3\x86\xfd\x10\xe7\x56\x42\x27\xf9\xd9\x93\xa5\xd0\xea\xc7\xe4\x89\x8c\x6a\xfd\xea\x96\xac\x68\xfd\x6d\x0f\xfd\x0e\x4a\x8c\x90\x73\x98\x3f\x00\xe2\x0b\xa0\xdd\xc8\xcd\xd5\x5e\xa7\x81\xcc\x6d\x4b\x82\xf2\xc2\x06\x3a\xa2\x03\x53\x5d\x00\x15\xfa\x62\xc8\x58\x2f\x8c\x92\x7b\x5a\xd1\x42\xf2\x37\xba\xba\xa3\x7f\xb3\xb6\x49\xb2\xdc\x6a\xf6\x49\xf8\x48\xb7\xd4\x1f\x74\x85\x5e\xe4\xbb\x4f\x08\x82\x20\x0d\x5e\xa8\x0c\xf8\x4a\x09\xf1\xb9\x6f\x36\x07\x81\xbf\xeb\xf5\xbb\xb5\x42\xdf\x1f\xc1\xf7\x90\x7f\x4d\xfe\x85\xf4\x4a\x8d\x52\xa1\x8f\xfc\x0b\xf3\x3e\xc5\x57\xe3\xa4\x21\x5e\xc7\xdd\x29\xf0\x37\x63\x0e\x4f\x62\x2e\x8b\xa7\xba\x8e\xbf\x0c\x18\xb6\x2c\x6e\xbf\xba\x88\xc3\x2f\x9f\x10\xa4\xc0\xf7\x4a\xc8\xa8\x5a\x12\x90\x7f\x61\xbf\x63\x7f\xe4\xfe\x85\xfd\x8e\xff\xf1\xef\x7f\xe1\xfe\xdf\xf8\xef\xf8\x1f\x48\x3f\xb8\x89\x94\x1a\xbd\x92\x27\x94\x92\x50\xfc\x9a\x28\x99\x0c\x71\xe0\x4a\xc9\x9c\xc6\xf0\xab\x25\xf3\xff\x2e\x91\xcc\x61\x4c\x0d\xe5\xb0\x8d\xc3\xd9\x04\xb1\x0b\xdb\x07\x10\x7d\x8a\x11\xa4\xe7\xc9\x0a\xf9\xb9\xf3\x00\x0f\xc1\xd7\xfd\x71\xbb\x84\xfc\x8c\x5a\xc4\xd7\x24\xab\xbd\x29\x8d\x71\x80\x31\x12\x37\x66\x9c\x9d\xc2\xc4\x14\xe8\x5a\x2a\x93\x80\xc6\x28\xdd\x33\xc8\x7d\x72\x77\x5a\x76\x48\x6d\x52\x9a\x77\x35\xb5\x09\x40\xe3\xd4\x46\x8d\xe4\x28\xb5\x5e\xe4\x92\xa1\x02\x16\xba\x3b\x71\x81\xa8\x43\x67\x0e\x24\x88\xfc\x44\xee\xee\x7e\xdb\xbf\xbb\xd4\xdc\xe9\xc4\xd2\xe4\xc8\x51\xda\x1e\xaf\xd1\xfc\x37\x64\xd1\x37\xb0\x6c\xec\x05\xb6\x18\xdd\x7c\x07\x1c\x69\x32\x22\x6a\xaa\x66\xba\x7e\x62\x20\x0c\x1a\x8d\x80\x1d\x60\x78\x69\x3c\x22\x4d\x81\x0d\x24\x17\xda\xc8\x1b\xb0\xd7\x9a\xa9\xc6\x86\x99\x0b\x63\x9b\xf2\x23\x9a\xe9\x42\x15\xda\xb1\x21\x8a\x0e\x54\x07\x71\x0c\xa0\xeb\x87\x68\x5c\xcb\xd0\x0f\x91\x7c\xc1\x29\xea\xeb\x76\xe4\xe1\xb2\xc7\xf7\x0d\x97\x8a\x23\x5e\xed\xd8\x8a\xc4\x85\xab\x03\x81\xcc\xe7\xba\xe6\xd7\xec\x11\x57\x33\xa0\xe3\x02\x63\x8e\x78\x6b\xe6\x7f\x44\xde\x2d\x13\x1e\x12\x9a\xb6\x2b\xda\xe4\xa3\xe1\x76\x2a\x1b\xcd\xdb\xcd\x57\x0a\xd4\x50\x0d\xf9\x6e\x3f\xc8\xe8\x30\xff\x8b\x9a\x50\xe8\x96\xfc\xf4\x2b\x3f\x0e\xbf\x12\x5a\x48\xb3\x26\x0c\xf9\xc6\xa0\xb4\xfd\xcc\x3f\xed\x3e\x17\xf8\x42\xb5\x84\x60\xa7\x98\xb9\x58\xec\x71\x40\x07\xaa\x18\x16\x3d\x10\x13\xae\xdc\x37\xa0\x7f\xb9\x4b\xe1\xf8\xee\xc7\x0f\x1b\xaa\x92\x0e\x1c\xe7\x6b\x7c\xb9\x82\xb3\x8a\x04\xdd\xa2\xc9\xaf\x47\x16\x2a\xd8\x1b\x5f\xcd\x59\x50\xd1\xd9\xf2\x95\x6c\x19\xbb\x5a\x5d\x32\x99\x89\xc3\x25\x4b\x4e\x1a\x8e\xe1\xc9\xc3\x83\xf2\x5f\xc2\x04\x8a\x3e\x66\x61\xc9\xe5\x85\x1b\xa9\x6d\x14\xe6\x87\x29\xed\x31\x46\x90\xd6\x48\x28\x15\x91\xfc\xf8\x04\x47\x41\x85\xee\x38\x43\x5b\x58\xb1\xdb\xdf\x35\x39\x8d\xb6\x4d\xcd\xe7\x5a\xad\x0b\xe1\x84\x6a\x17\xb3\x99\x49\x9a\xa7\x3f\x2c\x71\xa5\x8d\xfc\xec\x1f\x7c\x7c\x4e\xd1\x66\x5f\x8f\x93\x6f\xc9\xd0\x05\x9a\xee\x20\x2f\x8e\x65\x8a\xe9\xca\xb6\x29\x94\x5d\x2b\x87\x10\x4e\x28\x87\xcd\xb9\x75\x0a\x6d\x91\xc3\xe4\x4c\x56\x98\x74\x8e\x9d\x3c\x31\x14\x4b\xa4\x32\xea\x2f\xc4\x96\x8e\x8d\x97\x43\x63\x18\x76\x0b\x91\x6d\xfc\xf6\x30\x39\x16\x98\xac\x85\xbb\x8b\x4d\xf1\x39\x36\x04\xee\xc9\x49\xc1\xd8\xc5\x5c\xce\x3c\x76\xab\x3a\xe1\xc7\xd8\x39\xfb\x01\x2f\xd8\x41\x3e\xe0\x02\x7d\x22\x59\x9a\xe9\x24\xeb\xa0\x02\xe1\x64\x6e\x59\x7a\xf2\x5d\xff\xe4\x53\x81\x69\x6b\xed\xdf\xb6\xa1\x03\xed\xb7\xb4\x21\x5e\x1e\xea\xae\x26\x7e\x9a\xa4\xbd\xa7\x8d\x9a\xdb\x96\x6b\x49\x96\x9e\xca\x57\x7c\x8d\x36\xca\x02\x81\x0c\x6d\x3f\xbd\x08\xbe\x77\x16\x92\x04\x1d\x47\x59\xe8\x93\x54\x45\x09\x19\x07\x9a\x0e\xe5\x53\xa3\x42\xd2\x53\x54\x28\xdd\xf4\x52\xea\xdb\xd7\x5a\x62\xca\x99\xc9\x89\xb8\x98\xdd\x23\x9d\xf6\x71\xe7\xb2\x7c\xdb\x50\x77\x14\xc7\x47\x85\xbe\xb3\x18\xbd\x32\x14\x1e\xc5\x75\x18\x1a\x93\x87\x1f\x09\x95\x91\xd3\x9f\x9b\xe9\xe6\xa9\xad\xd0\x7e\xe7\x55\xca\x76\xc9\xdb\x1d\x48\x01\x2b\x7e\x94\xbc\x32\x48\x86\xde\xc1\x5a\xd8\xd2\xb6\x95\x23\x25\x3c\x6d\x5c\xce\xdd\xdd\x8f\x1f\xe9\xdb\xb5\x74\x3b\x08\x0f\xdf\xae\x15\x67\xd8\x2f\xf8\xe5\xa6\x39\x45\xe8\x36\x2f\x89\x70\x7e\xbf\x4c\x2a\xda\x58\xb7\xe2\xb1\x41\x61\x03\xe5\xb1\x21\xc1\x5e\x39\x71\xc0\x61\xdf\xe7\x89\x71\x47\xd1\x6d\x47\x1d\xc1\xe8\x93\xa4\x39\x13\x07\xea\x3a\xb4\x11\xd1\xb2\x74\x08\xcc\x4d\xdc\xd2\x24\x38\x31\xf7\x62\x74\xf0\xdd\x7e\xdc\xde\x75\x1c\x4d\x62\x11\x7d\xaf\xe7\x29\x7e\xd3\xb6\x16\xa6\xec\x37\x0d\xeb\xda\x7c\x0e\x54\x78\x08\x54\x73\x26\x70\x05\x24\x77\x9f\xae\x48\x0f\x40\x62\x5b\xa9\xcf\xee\xc4\x6f\x3c\x46\x0a\xd5\x52\xa1\x8e\x7c\xf9\x12\x15\xfd\xbf\x11\xf4\xeb\xd7\x53\xa0\x92\xa6\x6f\xa4\xfd\xff\x0e\x16\x20\x03\xbc\xbd\xc5\x88\x81\x8f\xad\x94\x4f\xe0\x51\x1b\x4c\x3e\x3e\xbf\x81\x55\x26\x37\x44\x64\x0c\xc1\x59\x7c\xdf\x35\x41\xf8\x54\xf3\xc1\x6d\xc2\xf0\x09\x2c\x1f\x15\x88\xcf\x64\xf6\xca\x50\x7c\x02\xdb\x61\x30\x4e\x9b\x70\x24\x1c\xef\x35\x9c\xdc\x50\x57\x37\xfa\x19\x25\x29\xf3\x0e\x2d\x0c\x1a\x27\xf6\x7d\x59\x23\xf6\xf1\xe0\x9b\x38\x76\x87\x3a\xd1\x5e\xbc\x2d\x46\xfa\x1e\x25\x6d\xf7\xf7\xa7\xec\xdf\xdc\xd5\x04\x9a\x6f\x50\xb7\xe6\x30\xa9\x26\xea\xae\xbc\xdd\xd4\x42\x77\x53\x6e\x1a\xd0\x05\x29\xb7\xbc\x7d\x5c\xda\x6d\x47\x53\x4d\xe0\x2e\x6c\x98\x54\xbe\xe3\xe8\xaf\xbf\xff\xb1\x4b\x7a\xfe\xf3\xdf\xa4\xb4\xe7\xf7\x3f\xe2\x32\x87\x86\x95\x52\x69\xdb\xc1\x32\x2d\x13\x1e\x4d\xa2\x76\xb0\x0e\xc1\x84\x9c\x69\x06\x9c\x88\x5e\x18\xf4\xcb\xe1\xac\x0d\x4c\x15\xee\xa9\x65\xf2\x4d\x43\x33\x27\x29\xda\x93\x3e\x60\x12\x8f\xb0\x89\x83\x42\xbc\x2a\x98\xef\x8d\x85\x2b\xd7\x06\x13\x4f\xd4\xd0\x76\xfc\x55\xf8\xfd\x8f\xf8\x9e\x74\x3f\x48\x7b\x4b\xe6\xb1\xad\xc2\xd8\x26\xdf\x34\xa1\x3d\xc9\x66\xaa\x3b\x48\x47\xed\x2a\x0a\xf8\xb4\x36\x84\x47\x11\x70\x39\xd9\x98\x56\x40\xde\xa9\xb2\x26\xa2\xc9\x1b\xa7\xb5\x69\xb3\xcb\xe2\x69\x03\xaf\xe5\xf7\x34\x9e\xe8\xe0\xeb\x95\xfa\x47\x6a\xd9\xd1\xaa\x61\xb4\x92\x7d\xde\x3e\xee\x76\x4c\x64\x6c\x70\x3c\xca\xd4\xd1\xfd\x5f\x16\x26\x53\x13\x96\x9b\xb1\x99\xb9\x47\xf4\x28\xa3\x27\xa2\x6b\x32\xab\x45\xe0\x02\x44\xb1\xec\x13\x27\x7a\x48\x91\xef\xf3\x27\xd8\xab\x09\xbd\x52\xb7\x8f\xd4\x84\x7e\x6b\xef\x54\xcf\x4f\x46\x7a\xc8\x17\xec\x01\xb9\xc3\xd1\xcd\x75\xf7\x80\xe0\x0f\x08\xfa\x80\xdc\xdd\xa5\x93\x73\xec\x54\xed\x5c\x92\xe2\x27\x6b\x1b\xb2\xee\xb0\x89\x66\x6a\xae\x06\xf4\x49\xd0\xe5\xf4\xdd\x79\xd5\xef\x7c\x5a\x31\xee\x1b\x4a\x7f\x43\x09\x04\x63\x7f\xe0\xec\x0f\x92\xf9\x8e\x12\x38\xc9\xd1\xf7\x28\xee\x11\x9d\x09\x3a\x3e\x09\x9e\x5e\xd9\x5b\x11\x71\x3d\x71\x2d\x4d\x3e\x8e\x89\xa3\x29\xe6\x1c\x4c\xc4\x64\xe1\xc0\x9d\x93\xd5\xcc\x83\x27\x66\x8e\xe2\x23\x49\x94\x64\xcf\xc1\x47\x4e\x80\x2c\x4f\xe2\x75\xc7\xa3\x38\x28\x92\x22\xf0\x73\x70\x50\x93\x20\xad\xd8\x6c\x70\xfc\xf3\xea\xa3\x28\x68\x02\xc5\xcf\x62\x83\xde\xa0\x08\xbd\x5f\x06\x14\x2c\x89\x51\xe7\xa0\x60\x26\x86\x25\x6b\xca\x3a\x3b\x17\x2c\x46\xe3\x67\xa1\x60\xf7\xb8\x08\xdb\xd4\x33\xe0\x61\x48\x9a\x38\x0f\x8f\xb7\xe8\x40\x55\x6d\xa8\x02\xd7\xb2\x8f\xeb\x14\x87\x62\x28\x77\x0e\x78\xce\x07\x1f\xd4\xa4\x27\x2b\xd9\x3e\x0e\x1d\x67\xb0\xb3\x96\x1a\x43\x7d\xf0\xe1\x2a\xf8\x55\x86\xe3\x08\x28\x8e\x39\x4b\x3a\x18\x16\x45\xb0\xdd\x7d\x7a\x0e\xe0\x38\x22\x8e\xe6\xce\xe3\x04\xdf\x5b\xe8\x70\xbf\x1f\x3c\x18\x7d\x0c\x13\x86\x32\x14\x79\xd6\x8a\x60\x44\xc0\xce\xb6\xbc\x72\x74\xc5\x31\x0c\x67\xe8\xf3\x38\x21\x27\x8a\xb6\xda\x3c\x24\x62\x19\xfa\x44\xd1\xa0\x7e\xd4\x35\x62\x18\x85\x61\x67\x39\x61\x8c\xda\xe4\x9c\x9b\x33\x8b\xd5\x09\x36\x68\xe6\x3c\x37\x8f\xd1\x13\xcd\x54\xa1\xe3\x4e\x0e\x4f\x45\x4e\xa0\x62\x38\xf6\xbc\x15\x61\xf6\x42\xbd\x7f\xfc\x04\x8e\x07\x13\x0c\x47\x51\x82\x3c\x0b\x09\xbb\x55\x5f\xc5\xb2\x37\x49\xf9\x1e\x0e\x0c\xfd\x46\x60\x08\x46\xfe\xc0\xb8\x1f\x24\xf7\x1d\xc3\x09\x96\xa0\xee\x51\x2c\x7b\x68\x24\x93\x23\xd3\xd5\x80\x09\xd2\x97\x8a\xb8\x30\xe6\xe9\xeb\x70\x3d\x16\x26\x30\xf6\xc4\xf3\xad\x89\x6b\x6d\x0e\x7d\x6f\x8b\x95\xa4\x7d\xac\xc6\x62\xe5\xed\x9f\x7f\x89\xf8\x28\x22\xea\xc5\x0e\x2a\xa8\x37\x46\x46\xfa\x0f\x4f\xda\x50\xb2\x4c\x59\x0b\x1e\xdc\x02\xa6\xbc\xd3\x3e\xcf\x1b\xdc\x9a\x41\x6a\xa2\x68\xba\x0b\xed\x89\xbd\xd0\xe1\xad\x81\xd3\x9e\x77\x59\x88\x13\x1b\x02\x79\x62\x99\xfa\x7a\x07\x1f\xc7\xbf\xa1\xd8\x37\x14\x47\x50\xec\x07\x41\xfc\x20\x88\xef\x24\xc3\xa1\xc4\x3d\x8a\xfa\x49\x70\x62\x0e\x7c\xb4\xc7\xe9\xdc\x24\xf8\xa0\xcf\x29\x9a\x9c\x57\xf2\x4f\x95\xce\xe3\x68\xd8\x18\xb5\xc6\xd5\x72\x63\xd8\xaf\x8f\x86\x54\xb9\x52\xe5\x89\x86\x30\x1e\xe3\x8f\x9d\x7a\x93\x69\xf1\x8f\xfc\xa0\xd4\x29\x0f\xe8\x46\xbb\xd0\x2b\x95\x87\x4f\x2d\x21\x2e\x9a\x54\x24\xb8\x87\x84\xa7\x46\xf9\xf6\x98\xa7\xc6\xe4\x88\x2f\x55\x9f\x46\x5d\x7c\x50\x6f\xe1\x83\x16\x99\x1f\x54\xaa\x83\x0e\x43\x96\x06\xed\x7a\x4b\xc0\x3b\xd5\x21\x39\xea\x56\x5b\xb5\xae\x50\xaf\x57\x0f\x3c\x57\x2a\x12\xc2\x43\x52\x78\xaa\x57\xe8\xae\x40\xb6\x84\x5a\xa9\x5d\x68\x0a\xe5\x3c\x43\xe0\x3c\x49\xd0\xcf\x54\x5b\x28\xf6\xba\x8d\xca\xa8\xce\x54\xf2\x8d\x42\xb3\xd3\xa8\x95\x5b\x64\x8f\x29\x8d\x47\xc3\x41\x66\x24\xa4\x2f\xae\x6e\x7b\x5c\xad\x35\xf0\x42\x8d\x28\x0b\x1d\x32\xff\xd4\x28\x37\x85\x62\xa3\xfc\x38\x10\xda\x03\xbc\x3a\x26\x9e\x9b\xe5\x5e\xb5\x25\x0c\x0a\xa5\x16\xdf\x1b\x31\x9d\x02\xd3\x7a\xc2\xab\x77\x97\xf6\xe4\x79\xdb\xbf\x13\x6b\x1d\xf6\x31\xef\x1e\x41\xf8\xee\xc0\xe3\xfd\x6a\x0f\x08\xf9\x80\xb8\xf6\x02\xa6\xef\xc2\x8e\x74\xa2\x5d\xac\x7f\x41\x75\x22\xaa\x7d\x92\x0d\x65\xcd\x9d\x00\x7d\x3e\x05\xe6\xc2\x20\x3d\x8b\x19\xf4\x8a\x77\x57\x2e\xe7\x25\xbd\x57\x37\x91\xf3\x5e\x2d\xe5\x01\xc1\xb2\x4a\x39\xa9\xf5\xea\x52\x31\x6f\xda\xaf\x22\x72\xc6\x18\x2f\xe1\x60\x08\x9c\xc5\x7c\xa2\x3c\x9b\xfc\xcf\xe7\x20\x81\xfc\xfc\x03\xf9\x8c\xa1\xe8\xf7\x70\x8b\xfe\xf9\x01\xf9\xbc\xeb\xf0\xf3\x6e\x0e\x7a\xc5\xdd\x97\xee\x7a\xee\x7f\x19\x5f\xb8\xdd\x88\xa0\xd3\xcf\x1b\x73\xe9\x0a\x7e\xfe\x6f\x9a\x49\xc6\x59\x23\x62\xac\xe1\x0f\x08\xf1\x3f\xc2\x1a\xbe\x65\x8d\x21\x18\xe6\x7f\x74\xd5\x02\xd6\xfe\xc7\x56\x0d\x67\x59\x92\x43\x29\x8e\xa5\x82\x55\x43\x7d\xde\x74\xcd\xd0\x7c\xd6\x38\x1c\x27\x08\x06\x47\x09\x9a\xa5\xbe\x93\x0c\x43\xb1\x28\xf3\xb7\xe2\x11\xdb\xf0\x88\xa1\xe8\xc6\x9f\xfc\xaf\xf1\x48\x3c\x20\x2c\xc5\x72\x1c\xc1\xd2\x2c\xe7\xb3\x18\x70\xe8\xb8\xc0\x76\xbd\xbc\x58\x04\x3a\x30\x25\x18\xea\xea\x4e\x59\x33\x63\x20\xf7\x31\x24\xdb\x40\x82\x11\x6c\xe4\x64\x02\x57\x7b\x83\x17\x73\xe4\xd9\x60\xc0\xd2\x12\x6a\xea\xd4\x43\x88\x3d\x20\x9f\x83\x20\x33\x99\xc1\xf5\x87\xe9\x92\x4f\x15\x89\x33\xa1\xb9\xfc\x2a\x39\x87\x18\x7e\xb9\x9c\x63\x1c\x65\x93\xf3\x85\x39\xf8\x59\x7e\x29\xa0\x8a\x66\x43\x93\xfd\x65\x72\x0e\x30\xfc\x72\x39\xc7\x38\xca\x26\xe7\x0b\xb7\x21\x01\x55\x27\x52\xb8\xa4\xae\xf1\x4b\x53\xb8\x4d\xe7\xf8\x86\x59\xea\x01\xb9\xa3\x69\x89\x15\x09\x82\xe2\x64\xc0\x40\x45\x96\x69\x4c\xa1\x14\x5c\x24\x18\x94\xc6\x39\x8c\xc6\x29\x52\xa2\x49\x8c\xa5\x09\x42\x92\x71\x0c\xc7\x48\x82\x21\x51\x89\x91\x64\x54\x84\x28\x4b\x51\x5e\x4e\x2d\x2a\x18\xc7\xd2\x12\x2e\x8a\x8a\x2c\xe2\x12\x4b\x33\xa4\x4c\x90\x22\x07\x21\x46\xa0\x8c\xa8\x28\xa4\x84\x4a\x18\x10\x45\x94\xc2\x21\xa7\x30\x40\x01\xa8\xcc\xd0\x12\x94\x08\x5c\xa4\x14\xf6\xce\xd7\x1b\x34\x56\x70\xa2\x7f\x10\xe4\x0f\x82\x8b\xd7\xa1\xc2\xaf\xbf\x53\x18\x41\x72\xd4\xc9\xbb\x38\x46\x32\x24\x4b\xd0\x24\x8b\x3e\x20\x18\xed\xad\xe7\xc1\xf5\x80\x70\xde\x7f\x58\xf8\xdf\xe6\x4b\x6c\xfb\x87\xb7\xa7\xe0\x79\x9e\x2f\x30\xec\xf3\xd4\xa9\x33\x39\xb1\x51\x7b\x46\x51\x74\x01\xc9\x7e\x9e\xc9\xa1\xcb\x66\xc5\x76\xca\x8d\x39\x47\xdf\xab\x18\xfe\xee\x34\xed\x27\xf2\xd5\x5a\x09\xf6\xea\x05\x33\xcb\xec\xfd\xa0\x56\xa3\x47\xc2\xac\xf8\xae\xbf\x74\xbb\xd0\x26\x86\x8b\xee\xec\xbd\xf7\xf8\xcc\x77\x3a\x24\xd3\xef\x78\xa0\xf9\xa7\xf6\xb0\x59\x5d\xf2\xdb\x0b\xca\x8d\xb2\xc1\x15\xd4\xa7\x21\xc3\xf1\x8b\x67\x81\x03\x6a\x59\x58\xd9\xcf\xc5\x8e\x3a\x24\x44\x45\xaf\xf0\xaf\x6d\xe6\x7e\x55\x53\x9e\x0b\xfd\xd1\x3a\x3f\x97\x7b\x03\xb2\xc2\x8e\xe7\xae\x2c\x57\xeb\x4b\xfd\xad\xed\xe4\xa5\xf1\x68\x25\xd7\x66\xeb\xde\xa3\xfa\x22\x53\xeb\x65\xb3\xac\x7a\x90\x07\x02\xd9\x00\xef\x73\xbc\xb3\x43\xc6\xb7\x4a\xfc\xfe\x95\xf7\xfe\x7b\xe6\x9f\x30\xb2\xc3\xf3\x45\xf4\x91\xff\xbb\x5d\x81\x52\x61\x0f\x7e\x6b\x43\x8a\xf5\xc7\x0d\x82\xbc\x8d\x32\xdf\x01\x9c\xe4\x70\x99\xe3\x18\x20\x61\x04\xa1\x70\x28\x46\x40\x45\xc2\x29\x56\x11\x29\x51\xa2\x08\x11\x2a\x28\xc7\x8a\x0a\xc7\xb1\xb2\x44\xb1\x92\x48\xa1\x8a\x44\x2b\x2c\x2b\x32\x0a\x60\xfd\x03\x4d\x22\xf0\x74\x87\xba\xcd\xa6\xaa\x3c\x81\xd2\x44\xba\x41\x6c\xee\x06\x39\x32\xcd\x61\x2c\x79\xc4\x20\xd8\x8c\x06\x41\x3f\x3e\x36\x9e\x75\x7a\xd9\x6f\x53\x7c\x9f\x61\x1f\xc7\xf7\xd8\x5b\xb9\x75\xcf\x3e\x6a\x39\x63\x4c\x94\x5f\x1a\x83\xf6\xea\x4d\x6b\x28\xb4\xca\x0f\xf4\xc6\xc2\xc6\xb4\xa7\x4a\xd5\x18\x0f\xa8\x9e\xd1\xad\xca\x4a\xb9\xc3\xad\x5b\xc5\x57\x4e\x2f\x37\xd7\xe5\x57\x12\xa5\x1f\x1d\x91\x79\x0a\xac\xc0\x37\x08\x75\xb7\xa0\x39\xfb\xb5\xff\x52\x6b\x8c\xfa\x6f\x72\xe9\x1e\x47\x45\xf7\x5d\x06\x80\x23\x4a\x6d\x77\x30\x2b\x93\xa3\x5e\x8b\xad\xd7\xba\xfc\x9a\xab\xd5\x0a\xec\x23\x8e\x0f\x1d\x40\x70\x8b\x9e\xeb\x12\x64\x91\xeb\x58\xcd\x97\x3e\x95\x23\xd5\x81\x58\x06\x6e\xae\xa6\x8f\x80\xa0\xca\x3a\x55\xf5\x6d\xa0\x93\x60\x10\x4d\x35\xa6\x4f\xff\x0b\x06\x41\xf8\x36\x71\x86\x41\x10\xb7\x51\xe6\x3b\x86\x42\x69\x56\x02\x12\xae\x60\x90\x06\xa8\x88\x4b\x40\x01\xb8\x4c\xc9\xa2\x28\x49\x12\x25\x61\x1c\xcd\x60\x8c\x42\x2b\x8a\xc2\x32\x1c\x27\x49\x04\x10\x69\x40\x73\x94\x88\x32\x22\x87\x81\xe0\x84\x1f\x4f\xd4\x6d\x26\x55\xe5\x49\x9c\xc6\xd3\xcd\xc5\xbb\xeb\x45\x97\x70\x67\x85\xb1\x2c\x7b\xc4\x20\xa8\x8c\x06\x41\x0c\x2a\x2f\xf5\xe5\x5b\xd5\xb0\x1a\x8d\xfa\xbd\x86\xc9\x0b\xf6\xbd\xbc\x7c\x7e\x5e\x29\x78\x2e\x37\xa5\xcc\x66\xcb\x06\x86\x2e\xe6\x99\x19\x10\xdf\xdf\xd0\x4e\xa5\x3d\xab\x3c\xf5\x24\x5c\x52\xf3\x85\xe2\xdc\xd2\xb4\x52\xa5\x4b\x2a\xb8\x61\xa3\xf3\x3c\x57\x01\xcc\x58\xbd\x7f\x12\x6b\xfe\x02\xfa\x06\x11\xd1\xd1\x5e\xb7\x31\x18\x54\x9d\x7c\x2e\xf7\x5e\x75\x5e\xaa\xbc\x85\x3d\xf3\x83\xfc\xcc\x62\x57\x64\xaf\xfb\x24\xac\x81\xe2\x3e\xbf\x0e\xcd\x32\xd5\xac\xbe\xb8\xcf\x96\xfe\xa8\xac\x80\xd2\x02\xcb\x5c\x9f\x20\x06\x83\xa5\xfe\xde\x94\x5b\xad\xfa\x93\x0a\x85\x62\x1e\xeb\xc3\xd7\x52\x91\xb3\xc6\x3e\xfc\x66\x82\x41\x54\xd1\x24\xa5\xfa\x9b\x1b\x04\x7e\xae\x41\xe0\xb7\x51\xe6\x3b\x9a\x90\x39\x56\xa1\x08\x1a\x42\x9a\x95\x31\x11\x67\x44\x4a\x64\x39\x05\x27\x80\x42\x11\x18\x26\x32\x14\xcd\x01\x9c\x54\x80\x82\x91\x28\x01\x64\x54\xa4\x70\x91\x26\x08\x0f\x06\xe4\xb8\x63\x11\x82\x4e\x55\x79\x8a\x64\xc8\xf4\x84\x8a\x22\x19\x2f\x40\x04\xfb\x39\x92\xe2\xf0\x23\xe6\x40\x64\x34\x07\xbc\xfd\xfc\x82\x09\x0b\xca\x42\xc5\x47\x66\x44\x9a\xeb\xd6\xdb\x60\x55\x21\x86\x73\x6b\x76\xff\x56\xe6\x5b\x6e\x01\xab\xe3\x4d\x26\xcf\xd0\xcf\xb9\x26\x55\xeb\x15\x5e\xbb\xc4\xfd\xfc\xbd\x3c\xaa\x77\x5a\xef\x25\x55\x53\x75\x97\x7c\xec\xf1\xb0\xc8\x8c\x6d\xcb\x29\x81\x46\x8e\xaa\x35\x82\x5c\xc5\x37\x07\xff\xaf\xda\xf6\x3f\xde\xd7\x58\x67\xf7\x79\xc9\xb7\x3b\xb3\x60\xb9\xd1\x61\x87\x5d\x18\xf3\x66\xeb\xbe\xfb\x98\x2b\xbc\xd7\xd0\xe1\xf3\x23\xbc\xa7\xe0\x74\x99\x9b\x91\x7d\x52\x9e\x2e\xdb\x9d\xe5\xb2\x34\x64\x18\xc3\x7c\x06\xf4\x74\xd8\x68\x0c\xf2\xa5\x2a\x58\xe4\xe0\xea\x91\x9e\x09\xcd\xda\xfb\x7b\x7b\xf8\x86\x3d\xb5\x38\xb8\x9c\x57\x57\x4f\x43\xbe\xdc\xf6\xa3\x44\x2d\xc1\x5c\x4a\x4e\x92\xca\xfd\xcd\xcd\xe5\xec\xf8\x81\xdd\x46\xd5\xfd\xee\xd4\xcd\x1e\x01\xe3\x18\xd4\x3f\xfa\xc2\x10\x14\xfd\xe1\xff\x4b\x55\x69\x9a\x65\xa8\xf4\xf8\xe0\xdd\xf5\xe2\x03\x89\x73\x24\x47\x33\x38\x47\x1f\xd1\xf8\x64\x7d\x0f\x48\xfa\xb3\x97\x26\xfd\xca\x3f\xd5\x35\x72\x9d\x5b\xf7\xea\x79\xa6\x68\x16\xb9\x2a\x8e\xae\x5e\xf2\xf7\x0e\xaa\xba\xce\xb2\xb6\x7c\xc7\x9e\xe4\xde\x68\x0c\xf2\x8f\x20\xd8\x1b\x94\x12\x54\x39\xf9\xda\xa8\x32\xcf\xe7\x67\x1f\xc0\xc8\x4d\xaf\xed\x86\x33\x54\xe5\x13\x7b\xf0\x0c\x8f\x8f\x5e\xba\x25\x4f\xe9\x4a\x8d\xd8\x4f\xb0\x81\x25\x51\xca\x2f\xd7\xa7\xd8\xdd\x09\x30\x78\x0c\x0c\x7e\x19\x98\xf8\xb9\x08\x71\x19\x18\x32\x7e\x72\x74\x19\x18\x2a\x56\xef\xbf\x90\x1a\x3a\x7e\x6c\x70\x19\x18\x66\x03\x86\xc5\x48\x86\xb8\x98\x1a\x36\x56\xe9\xbf\x90\x1a\x2e\x5e\x4c\xbf\x0c\x0c\x86\xee\x97\x77\xc9\x0b\xc1\x60\xb1\x2a\xf1\x85\x60\xf0\xfd\x22\xe8\xa5\xd4\x10\xb1\xea\xf0\x85\x60\x62\xa5\xc9\x4b\xa9\xa1\x62\x15\xce\xdb\x3c\xd1\x7d\x93\x73\xe7\xe3\xed\xee\x0f\x88\x47\x7b\xb6\x83\xe8\x94\x07\x9b\xaf\xf6\x9a\x11\x17\xb7\xe7\xdf\xb6\x1f\x68\xbf\x04\x84\xf9\x25\x5c\xd7\xba\xaa\x5a\xfb\x80\x7c\x56\x6c\xcb\xb8\xaa\xb2\xfe\x80\x44\x2a\xd7\xf8\x5f\xed\x34\xf2\x17\xf4\xed\x24\xac\xd4\xbe\xef\xdf\x7e\x40\x0f\x57\xea\x0a\x29\x6f\x57\xea\x52\x69\xec\xad\xd4\x5f\xee\xdc\xf8\x17\xf4\x25\xa5\xaf\x54\xd8\x29\xb0\xfd\xf0\x8b\x6c\xea\x9f\x95\xba\x76\xa5\xc2\xd4\x63\xf7\x01\xf7\x97\x29\x38\x31\xf3\x5b\xd4\x3d\x66\xd0\xef\x54\x44\x40\x5b\xc9\x91\xfb\x92\x0b\x9e\x9b\xf7\xb8\xff\xcf\x67\xf9\xf3\x0f\x04\x7f\x40\x3e\x9b\x9f\x7f\x20\xd8\x7f\x1f\x90\xcf\x9b\xfe\xed\xcf\x3f\xbc\x24\xfa\xb3\xb8\x58\x6b\xa6\x3a\x49\x14\xf6\xde\xbd\x63\x32\x77\xa0\xae\x1f\x8e\x0c\xcf\xef\xe2\x80\xfe\x4e\x4b\xb3\xd7\xb8\xb1\xfd\x40\xfa\x4b\x43\x67\x6b\x70\x70\xed\x85\xe3\x42\x78\xad\x99\xf8\x60\x2c\xfb\x5a\x8b\xfd\x6b\x18\xd5\x8d\x7b\x3f\x53\x57\x6e\x93\x41\x6f\x3f\xa0\x7f\xf2\xca\x5d\x93\x7b\xfc\x25\x56\xee\xd7\xa7\x18\xd1\xcd\xc6\xf6\x6f\x36\xd2\xa0\xa0\x2c\x4c\x39\xe4\xe5\xc2\xce\x5b\x5f\x2e\x41\xff\xeb\xb5\x8b\x9b\xa1\x5b\xe2\xca\x16\xe1\x73\xc4\x16\xee\x8a\xb6\x7f\x93\xbf\x54\x6c\x57\x28\xf3\x5f\x4c\x6c\xc1\xf6\x6d\xfb\x37\xfa\x4b\xc5\x76\x85\xf7\xfe\xf5\x62\x3b\xb1\x17\x4c\xf8\x45\xa6\x2c\xfb\xc0\xd3\x50\x4f\xff\xc6\xcc\xa5\xfb\xcd\xd4\x87\xaa\x13\xeb\x74\x74\x7a\x4d\xe1\x24\x20\x3c\x06\x28\xad\xfe\x73\x12\x10\x11\xdb\x5b\xa5\xd5\x5c\x4e\x02\x22\xe3\x9b\xb4\x4b\x01\x51\xb1\x3d\xc4\xc5\x14\xd1\x31\x40\x17\xcb\x88\x89\xe5\xca\x17\x53\xc4\xc6\x32\xbb\x8b\x29\xe2\xe2\x89\xc6\xa5\x80\xf6\x2a\x77\x6c\x7a\x75\xea\x34\x20\x6c\x1f\xd0\xc5\x32\xda\xab\xde\x91\xd7\x50\x44\xc4\xa2\xd3\xc5\x80\xc8\x7d\x7f\x7d\x39\x45\xd4\x3e\xa0\xf4\x1a\xde\xb9\xbf\x91\x74\x8b\x2a\xde\xa9\xdf\x72\x38\xa7\x8e\x97\xfa\x8b\x48\x37\xf0\xac\x91\xe7\xde\x00\xc0\x68\x56\xc1\x70\x0c\x27\x45\x46\xc2\x38\x5a\x42\x81\x0c\x20\x64\x24\x86\x00\x34\x29\x13\x8c\xe2\x2d\x3f\x2b\x01\x49\xa4\x38\xc0\x61\x8a\x42\xb0\x1c\x8d\xd3\x2c\x49\x41\x46\x52\xee\x1e\x90\xa0\xed\xf7\xf2\x64\x33\x72\x0e\x4e\x6e\x4e\xfe\xd2\x7b\x0d\x69\xe2\x48\x23\xa2\x7f\x73\xcf\xab\x07\x07\x86\x15\xca\x7a\x74\x87\xb2\x39\x6e\x0d\xe5\xe7\x57\xf7\x69\xde\xaf\xe6\x5d\x51\x1a\xa3\x46\xc1\x50\xa4\x7c\xad\x5e\x52\x47\xa6\xfe\x56\xae\x4d\x01\xef\x1f\xb8\xf1\x9b\x63\xed\x42\xec\x3c\x2b\xbf\xfb\x33\x38\x1b\x6f\xe1\x85\x1c\xdf\x22\xa9\x71\xbe\x48\xb8\xd5\x61\xb9\x85\x75\x09\x1e\x6d\xc2\x59\x9b\x7d\xec\xd2\xa6\x80\xf1\x1c\x1c\x69\xf2\xba\xe6\x0e\xfc\xf9\xc3\xa1\x10\x36\x00\x16\x16\x16\x61\xb9\x24\xf5\x5a\x68\x97\x56\xf3\x4e\x8e\xb0\xaa\xc2\xfd\x3b\xc6\x74\xd7\x9a\x83\xe9\x4a\xb3\x3c\x36\x3a\x23\xd5\x5e\xf4\xee\xfb\x01\x6a\x42\x78\x8e\x1e\x16\x96\xb7\xf4\x76\xea\x52\xa5\xc7\xb5\x9c\xa1\x39\xac\x16\x86\xb5\x2a\x4a\x16\xb8\xe7\xfa\xfb\x7b\x7d\x9c\xef\xca\x05\x63\x7d\xff\xb8\x34\xde\x75\x99\xe9\x48\x7c\xa3\xb5\x7a\x1e\x48\xbc\x3a\x5b\x54\x14\xab\x27\xbf\x3d\xcd\xab\x04\x6b\x08\x6f\xf6\x6b\x47\x03\x4d\xa7\x27\x18\xfd\xc7\xd1\xb8\xfb\x5e\x7d\x53\xad\x9f\x77\xd1\x03\xd7\x4a\x3f\xe7\x5d\xfe\xdf\x3b\x32\xf2\xfe\x97\x41\x07\xd7\x6e\x7c\x67\x2b\xbf\xa2\x3f\x28\x42\xb6\x68\xa8\x06\x36\xc4\x65\x95\x1a\x62\xc6\x2b\x06\xf5\xa6\x54\xc1\xdc\xd5\x4b\x6f\x5c\x7f\xe6\x96\x25\xd5\xea\xe5\x01\x1c\xb1\x03\xad\x6c\xf9\x42\x1a\xf2\x6f\x2f\xad\xdd\x7a\xe4\x63\xf8\xf7\xd6\x22\xe1\xca\xdf\x18\x7f\xe1\x4c\xfc\xfc\x56\x26\xbe\x8c\x9a\x5b\x99\x84\xe4\x2d\x40\x41\x1c\x3e\x3d\xe3\x45\xfd\x69\x04\xec\x21\x3d\x58\x2d\xc5\x11\x51\x11\x1e\xd5\xb9\x49\xf0\xbd\xc2\xb4\x56\x9e\x53\xe2\xaa\x57\x1b\xf9\xf3\x1f\x07\x85\xfb\x96\xb4\x83\x57\xe2\xf7\x75\x32\xbc\x52\xcf\x94\xfd\xf1\xe5\xeb\xf0\x37\xc9\xcb\xf0\xff\xf4\xf5\xe3\x3f\xf3\xe5\x73\x03\xa5\x57\x23\x79\x20\x3d\x0e\x54\xa5\xaf\x36\xb0\x99\xdd\x6e\xce\xd5\x72\x19\xad\x8b\x0d\xd2\x2c\x88\xad\x21\xe1\xe6\x97\xbc\xc3\x94\xf5\xee\xb2\x50\xe8\x91\xcf\xf7\xd3\x47\x9c\x83\x33\x45\x59\x8f\xf1\xfb\xc5\xbc\xf0\x68\xad\x57\x35\xfc\xb9\xa9\x3f\x4f\xab\x4d\x78\x5f\x50\x7f\xfe\xf4\x93\x69\xff\x97\xb7\x36\x5d\x0c\x59\xfe\xf7\x5f\x90\xe1\x7b\x9d\xd3\x21\x69\xef\x71\x61\x48\xe0\x18\x8d\x92\x94\x4c\x31\x9c\x08\x01\x89\x2a\xb8\x4c\x50\x00\xe5\x48\x94\x96\x21\x01\x58\x8e\x84\x92\x48\x89\x90\x41\x65\x51\x06\x14\x94\x38\x09\x25\x71\x06\xa0\x32\x05\xb0\xe0\x01\x4e\xec\x9a\xba\x58\xc4\x6d\x12\xa7\xdc\x26\x81\x32\x1c\x76\xa4\x5f\x35\xb8\xbb\x97\x7c\x06\x4a\x5b\xa7\x5f\xa0\x46\xbc\x18\x56\x8d\xed\x57\xf4\x62\x0e\xaa\x12\xc1\xb4\x9f\xdc\x6a\xbd\xfe\x3e\x1a\xb2\xcb\xa1\xf6\x9c\x07\x85\x05\xd5\xa0\x7c\xcd\x8e\x38\xce\xb8\x52\x1c\x38\xce\x33\x0d\xf1\x0a\xc7\xc9\x33\x86\x63\x45\x48\xa9\x6c\xe9\xed\x94\xcc\x7a\x51\x2c\x8e\xdf\xea\xb3\xc7\x97\x71\x1d\x05\xf6\xdb\xb4\xac\x9b\xf7\x95\x3a\x7a\xcf\xf0\x6b\x5a\x45\xc1\x3d\x36\x7d\xe9\x76\xa1\x5e\xe2\x21\xb9\x34\x5e\xe0\xab\x20\x75\x55\xdc\x20\x0b\x26\xe3\x92\xfc\xcb\xe3\x3b\xef\x14\x3b\x35\x54\x7b\x02\xd3\x8a\x68\x3d\xb6\x6b\x02\xbf\x8c\x39\xce\x4e\x92\x61\x44\xe5\x93\xee\x38\x23\x83\xec\x57\x81\x6e\xc0\x16\x50\x5f\x56\x4d\x30\x68\x73\x74\xfe\x5d\x71\x38\x88\x4a\x96\x2d\x3c\x3f\xbd\xe7\x47\x8f\xb3\xb2\x55\x67\x66\x6f\x33\xbf\xa9\xd7\x73\x5c\x1a\xb6\x5b\x8f\x94\xeb\x84\xe3\xbc\x1d\xfe\x43\x27\x91\x01\xff\x81\xd3\x0c\xba\x60\xce\x74\x5a\xe5\xe1\x00\x0d\x05\x7f\xa6\x3e\x87\xa4\xe4\xb6\xd7\x32\x89\xe6\xd2\xee\xcb\x8f\xa6\xaf\xb8\x00\x6b\xf5\x18\x7d\x3f\x7f\x26\x04\xa0\x48\x52\x73\xae\x2d\x79\x01\x20\xa4\x35\xde\xb6\x1d\xbd\x8e\x07\xa0\xd2\x75\xf8\xa3\x01\xf0\x1c\xfc\x61\x00\xea\x49\x96\xe0\x08\x1a\xfb\xda\x31\x04\xd5\xee\xbe\x2e\xee\x4b\xa3\x91\x42\x8e\xed\x3e\xe3\x14\x1b\xaf\xc5\xae\xcd\x8c\x2a\x42\xb9\x4c\x0f\x3a\x79\xe6\xa5\x00\x04\xda\xc2\x56\x95\x22\x10\xd5\xba\xb2\x20\xd4\x42\xd3\x6c\x16\x96\x02\xff\xd2\x7b\x94\x5f\x4b\xcf\x0b\x75\xc6\xaa\x68\x91\xbf\x34\x00\x79\xbb\x81\xf3\xe3\x0f\x26\x91\x14\x49\x13\x28\x4e\x33\x00\xb0\x0c\xcd\x40\x89\x95\x58\x48\xa0\x24\x85\x4a\x10\xd0\x22\xa0\x69\x14\x23\x29\xc8\x49\x1c\x4e\x02\x51\x64\x28\x99\x01\x34\x4d\x73\x22\x2d\xe1\x2c\x08\xe2\x0f\x7e\xa3\xf8\x73\x32\x6d\x27\x50\x2e\xbd\x19\x36\xbc\xb9\x57\x68\xb8\x36\xfa\xfc\x85\xd2\xf6\x23\xd1\xa7\x38\xaf\xcd\xb8\x57\x02\x75\xdf\x95\xce\x6c\xde\x59\x14\x96\x65\x46\x03\x6d\x42\x14\xe8\x62\xb7\x30\xbb\x5f\x0e\x88\x21\x4b\x33\xee\xeb\xac\xd1\x19\x12\x35\x99\xa4\xf0\x91\x53\x1f\x8c\xe7\xed\x8e\x2d\xb0\xf0\x85\x56\x66\xe8\x62\x05\xa1\x91\x17\x9c\x77\x4c\xa0\x86\x4d\x87\x53\xc7\x7f\xc5\xe8\x73\x91\xf7\xbf\x21\xfe\xb8\x3e\x64\xc2\x9f\x1c\x7d\x78\x66\xdc\x60\x79\xe6\x45\x57\x4b\x6d\x88\xca\x83\x01\x33\xac\x4a\xc5\xce\x8a\xee\xe4\x96\x7a\xf5\x55\x22\x06\x45\x8c\x02\x8f\x44\x4d\xc3\xfc\xf1\x1f\x1d\x7d\x3e\x90\xbe\xcb\xa2\xcf\x9f\xe4\xfd\xf9\x1b\x45\x9f\xe8\xf6\xe7\x1c\xfc\x61\xf4\x69\xcd\xb4\x3e\x6e\x2b\x3d\x42\xe0\x0a\x3d\xbd\x40\x36\xf8\xa7\xc5\xa3\x95\x93\x1d\xc2\x12\x4a\xf5\x3e\x93\xef\xcb\x4f\xef\xf6\x02\x7f\xed\xb8\xf9\x27\x69\x4a\xbc\x98\xcf\x60\x39\xef\x6a\x33\xae\xe0\x10\x2b\xba\x3d\xbf\xef\xf7\x98\x32\x45\x8f\x4b\xf8\x7b\x7b\x40\xe8\x83\xf5\x3b\x9e\xbf\x78\xfb\x73\x59\xf4\xe1\xa0\x08\xa1\x0c\x45\x89\xc2\x65\x40\x60\xac\x4c\x8b\x32\x41\x91\x34\x49\x12\x1c\xc1\x31\xa8\x2c\x33\x14\x4a\x8b\x22\x2b\x2a\x80\xa5\x15\x9a\x90\x58\x4e\xa2\x68\x86\x95\x50\x46\xa2\xfc\xe7\x22\xc8\xa0\x59\xe2\x16\xd1\x87\x3a\x19\x7d\x30\x8c\x39\xf2\x2c\x5f\x78\x77\xaf\x3e\x7d\x6d\xfc\x29\xc6\x16\x3f\xe2\xca\x22\xa6\x3d\x1c\xf6\xbb\xe1\x9f\x67\xfa\xb7\x48\x50\xf1\xd5\x39\xd9\xbf\x81\xcd\xf8\x3c\xff\xe6\x2c\x28\xe5\xfe\x8d\x19\xda\x8f\xc5\x6a\x7d\x81\xb3\xa3\x65\x09\x7f\x5f\x16\x3b\x94\xde\x1c\x99\x05\xa6\x6c\xa9\x3d\xbd\x9f\x13\x5e\x56\x6a\x75\x55\x64\x66\xb3\xe7\x6a\x73\x84\xeb\xb3\x97\xf1\x2a\xc7\xf5\x48\xca\xa9\x3d\x56\x0a\x2d\xf2\xed\x85\xbe\x57\x6b\x6f\xab\xaa\xbd\xa4\xf5\x7c\xd4\xbe\xf9\xd4\x58\x13\x97\x05\x7f\x89\x6c\x23\xbc\xfe\x72\xd9\x7d\x40\x3c\xbc\x28\x1e\xdd\x10\x7f\xf2\x9a\x9c\x8a\x87\x3e\xa8\x5b\xf8\xf0\x86\x9f\x54\x45\x62\xc2\xe1\xf5\x4b\x7d\xf8\x01\xfe\x53\x25\xac\x83\xfb\xb1\xa4\x2e\x3e\x31\x58\xdf\xbf\x83\x8e\xdf\x2c\x2e\x5f\x1a\x17\xf9\x5f\xb0\xa6\xe7\xe0\x0f\xe3\xf2\xaf\x72\x90\x1f\x19\x97\x29\x0c\x03\x98\x82\x53\x10\x53\x28\x08\x70\x59\x42\x45\x14\xe3\x70\x02\x53\x20\xc3\xe1\x0c\xa1\x48\x12\xce\x90\x0c\x2e\xe1\x04\x2d\x51\x1c\x8b\x2a\x12\x27\x4b\xb2\x4c\xcb\x1c\x46\x41\x3c\x7c\x18\x1e\xbb\xa6\xe7\xeb\x9c\xaa\x24\x89\xb3\x24\x7e\xe4\xa1\xe1\xe0\xee\xde\x71\x6f\xa0\xb3\x45\x57\x7d\x5b\x16\x17\xad\x11\xdf\xe1\x98\x2e\xd6\xed\xbb\x03\x79\x29\x14\xab\xf3\x62\xae\x30\x80\xf3\x77\xb9\xd3\x7e\xd2\x2d\x53\xd2\x1a\x43\x3e\x73\x55\x72\xcc\x5f\xbc\xcf\xab\xee\x52\xe0\x88\x4e\x6f\xf1\x77\xaa\x25\x6c\x7e\x4f\xb9\xf9\xf6\x2b\x3b\x1f\x58\x15\xfe\xe9\xb5\xc5\xf5\x18\xb0\xa4\x5a\x9c\x68\xb2\x4c\x77\xdd\x5e\xa2\x4f\x98\x5c\x47\x65\x66\xda\xeb\xd2\xcc\xa2\x92\x9b\x4d\xf9\x75\x81\xb0\xb8\xbe\xdd\xee\xd3\xef\x9c\xfc\x3c\x9b\x1a\x4f\x39\x81\x9f\xb1\xe6\xca\xe0\xa6\xfa\xb8\x53\xca\x12\x7b\x2b\x51\x45\x4f\x8b\x6b\x7c\xe4\xb7\x30\xce\xdc\x17\xfb\xc7\x23\xe6\x4e\xbe\x29\x57\x96\xb8\x72\x13\xfc\x97\x55\x19\x77\x71\x2d\x1a\x17\xcf\xdc\x47\x25\x1e\xcd\x1c\x5e\xc7\x7d\xe0\xad\xf1\x9f\x71\x34\xc4\xf3\x7f\xdd\x7d\xee\xa9\x2a\xe6\x25\xb2\xba\xba\x8a\x79\xc3\xb5\x3a\x07\x7f\x18\xaf\xa4\xfe\xc8\x64\x0c\xb4\x74\x6f\xaf\xf5\x9e\x3a\xce\x43\x8b\xc1\x1a\xae\x5d\x9c\x31\xd8\x42\x79\x77\xab\xb5\x5c\xb1\xab\x0c\x51\xbb\x4b\x2c\xca\x8f\x55\x7b\x41\x8a\xf7\xbd\x52\xb1\xd6\x80\x2f\x58\xcb\xe1\xda\x76\x1b\xc3\x8c\x5e\xe5\x59\x61\xd1\x42\x7f\xad\x54\x44\xbc\x32\x9c\xf2\x9d\x8f\x8d\x57\x00\x97\x81\xa8\x90\x90\x93\x31\x9a\xc4\x19\x1c\xa7\x51\x1c\x67\x70\x88\x31\x2c\x20\x18\x89\x63\x08\x89\xc3\x18\x46\xe4\x28\x46\x06\x2c\x8d\x71\x38\xe0\x38\x91\x80\x9c\x42\x00\x0e\x00\x32\x88\x57\xf8\x8d\x9a\x0f\x4e\xc7\x2b\x02\x43\xd3\x4f\xd1\x36\x77\xf7\xba\x8a\xae\x6d\x3f\xf8\xc0\x78\x15\x69\x27\xa8\x6a\x8d\x79\x49\x18\x31\xc4\x8b\xd4\xc7\x7a\xf2\x4c\xc9\x41\xb0\x7a\xe9\x35\x2a\xfd\x4e\x41\xad\x99\x10\x75\x09\x12\xd4\xe0\x5a\x9e\xce\xf5\xa1\x3b\xe2\x56\xc5\x0e\x3d\xe5\xfb\x04\x5b\xe1\x66\x9a\x5d\xaf\x77\x6b\x6b\xab\xbe\x98\x59\x03\x41\x98\xf2\x4b\x79\xb4\xce\xb5\x5f\x3a\xd2\x2f\x89\x57\x97\x1c\xe7\xdf\x32\x5e\x5d\x89\xff\x86\xf1\xea\x26\xad\x04\x87\x57\x66\x1f\xf8\xd1\xad\x0c\x3c\xff\xd7\x3d\x15\x3c\x15\xaf\x2e\x91\xd5\x2d\xe3\xd5\xb5\x6b\x75\x0e\xfe\x30\x5e\xc1\xda\x62\xd6\xc1\xc4\x37\x28\xac\xda\xc3\x47\xbc\x9b\xe3\x28\xbb\x22\xd4\x9c\x67\x81\xaf\xf3\x9a\xcc\xf4\x08\x65\x6a\x4d\x99\x47\xbc\x62\x0c\x47\x98\x48\x94\x84\xe2\x6b\x29\xdf\x56\x96\x22\xde\xab\x3b\xd6\xbc\xf4\x52\x57\x5f\xe9\xde\xb4\x83\xe2\xa5\x62\x1e\x13\x1b\xec\xbd\x90\x5f\x7e\x6c\xbc\x12\x71\x80\xe3\x8c\x44\x70\x12\x4d\x02\x92\x54\x24\x06\x88\x32\x29\x71\x34\x8b\x71\x24\x45\x2b\x28\xc1\x71\x1c\x4a\xcb\x18\x2e\x91\x0c\x2d\x33\xa8\x48\xa2\xb8\xff\xe3\x66\x1c\x2d\xd3\x80\x08\x7e\x06\x07\xbb\xa6\xe9\x3b\x78\x20\xf0\x68\x98\xa2\x48\x0e\x4d\x6f\x92\xdb\xdc\x8d\x76\x9a\x86\x51\xaa\xc1\x56\x3b\x6f\x9d\x99\x58\xc7\xab\x3c\x31\x1a\xbe\x74\xed\xba\xf1\xf2\x84\xa2\x4a\x85\x75\x1a\x35\x2f\xd9\xe8\x2e\x1f\x47\x39\xfe\x89\xe0\xb7\x51\x2a\x50\xa7\xd8\x92\x1f\x58\xf1\x05\xd5\xaa\xe8\x2f\x5d\xe4\x87\x6f\xcb\x32\xe7\xdd\x2a\x15\x5d\xa2\xbe\x34\x40\x7b\xd1\x96\xcb\xbd\xc1\x4a\xe6\xcb\x50\xa4\x5b\x1d\xe8\xae\x3b\xf5\xda\x08\xbc\xeb\x62\xaf\xd9\x9c\x1a\xd5\xba\xd0\x28\x92\xce\xeb\xb4\xf4\x3a\x78\x96\x3a\x6d\x54\xbf\x7f\xca\xb5\xe6\xf7\x96\x33\x32\x04\xfa\xbe\x3c\x18\x8b\xce\x3b\x43\x75\xf0\x97\x0a\xf9\xd6\x6c\x66\x88\x4c\x7b\x2a\xbd\x1f\x99\x22\x3c\xef\x3c\x73\xd4\xda\xb5\x5c\x1e\x6d\xa0\x8f\x95\xb5\x3b\x5d\x0a\x98\x3e\x46\xc1\x7a\x6e\x61\x9c\x50\x5d\xbd\x35\x0a\xeb\x16\xe5\xe6\x4b\x52\x21\xe0\x91\x50\x5d\xbb\x65\x8e\x73\xcc\x60\x37\xff\xa2\x0a\xd9\x15\xf8\xcb\xfd\x51\xde\xbe\x02\x3f\xcf\xff\x79\x3d\x06\x89\x9e\x37\x7f\xb9\x2c\x5a\xe6\xf3\x51\x36\x4f\xc9\xe2\xda\xb5\xf0\x74\xe1\x5e\x8a\xc1\x3b\x4b\x16\xff\x61\xe4\xb5\xf3\x68\xbc\x30\x2f\x44\x77\xa0\x37\x9f\x3a\xf9\x27\xe3\xfe\x65\x56\xb5\xa5\x59\x41\x2b\x1b\x0e\x35\x42\x5f\x8a\xb5\xe7\xe9\xfa\xa5\xb7\xbc\x6f\xd4\xad\x6e\x5d\xaf\x3c\x95\x8a\xdc\xa3\xa2\xe7\xde\x5f\x95\xd7\x46\x79\xfe\x02\xdf\xa6\xc3\x4a\x85\x69\xde\xdf\x0f\x04\x6b\xb5\x68\xbc\x7f\x74\xbf\x03\x29\x13\x24\x24\x49\x14\xa3\x28\x42\xa1\x49\x40\x73\x12\xa0\x09\x16\x27\x29\x8e\x55\x48\x99\x53\x50\x80\x73\x22\xaa\x40\x42\x82\x04\x2b\x91\x90\x94\x19\x94\x44\x65\xa0\x28\x18\xae\x28\xca\xee\x57\xed\xae\xf0\xbc\xf8\x49\xcf\x4b\x61\x47\x7e\x34\x72\x73\x37\xda\x51\x7f\xad\xe7\x3d\xd2\xe7\x10\x5c\x17\xe4\xa7\x29\x9e\xb7\x20\x17\xdd\x0a\xbe\x32\xd4\x4e\xae\xc9\xbb\xaf\xaf\x8a\xa2\xe6\x9b\xf7\x03\xe5\x79\x58\x7d\xe7\xac\xe2\xca\x7d\x2f\x0b\x32\xc5\xce\x72\x06\x2e\xea\xed\x8a\x59\x13\xc5\x05\x04\x86\x3b\xef\xbc\x15\x38\xd2\xee\x4e\xc1\x32\x57\x75\xf2\x25\x05\x00\xee\xf5\xe5\x79\xc9\x8c\xe7\xc3\x59\xe5\xaf\xe5\x79\xaf\xf5\x7c\x57\x5a\xfb\x2b\x93\xeb\x17\xc5\x1b\x7a\xde\x8f\xcc\x33\x4f\xe6\xbc\x1f\xe8\xf9\xf8\x1b\x79\x5e\x96\xdc\xcd\x4f\xd9\x2f\x1e\xf3\xbc\x66\x87\xe9\xba\xce\xb3\x55\x6a\xbf\xf3\x0d\xf0\x6a\x12\x24\xdf\x6f\xeb\x55\x7c\xd8\x65\x73\x80\x67\x45\x69\xd5\x7f\x82\xca\x63\x9b\x72\x0d\xaa\xbf\x9a\xaf\x2b\x38\x63\x1a\x73\x1b\x0c\x1a\xcb\x37\x58\x47\xc7\x23\xa7\xbd\x62\xf8\x6e\x15\x37\xde\x80\x85\x4b\x2d\xbc\x3e\x7c\xfe\xe8\xb3\x7e\x06\xa7\x18\x8a\x16\x31\x45\x94\x15\x96\x10\x51\x16\xc3\x19\x85\x60\x29\xa8\x40\x59\x41\x39\x94\x93\x24\x16\x47\x45\x5a\x92\x20\x83\x29\x98\x84\xb2\x1c\x23\x63\x14\x89\x33\x92\x48\x01\x59\xbe\xdb\xfe\x94\xf8\x15\x9e\xf7\x64\x69\x86\xa2\xf0\xf4\x1f\x9f\x0b\x6f\x46\x9f\x1b\xba\xd6\xef\x1e\x39\xdf\x0f\xae\x0b\xea\xd8\x29\x7e\x37\xff\x42\xaa\xf9\x4e\x2e\xcf\x8b\xea\xab\xc2\xbc\xb6\x2c\x17\xb8\xea\xf3\xa0\xfa\x52\xd4\x9d\x96\x5b\x14\xe4\x39\x03\xf4\xe7\x2e\x95\x2b\xcf\x38\xa5\xf2\x72\xaf\xaf\x4a\x6b\x95\x7f\x1e\xbd\x8f\x99\x5c\x63\x8c\x3d\x13\xbd\x32\x2d\xa1\xaf\x0e\xc6\xe0\x8d\x29\x3f\x9b\xbd\x0d\xd9\x39\xfa\xd7\xca\x78\xaf\xf6\x7b\xd7\xfa\xdd\xb5\xdd\x29\x37\x6e\xe8\x77\x3f\xb2\x1e\xfd\x2b\xfc\xee\xa5\x7e\x8f\xbf\x91\xdf\xbd\x74\xf7\x13\xfa\xdd\xf1\x7d\x8d\x1f\xb4\x97\x9d\x0a\x59\x37\xef\xe9\x97\xd7\xc6\xc8\x1e\x57\x86\x79\x72\x49\x89\x45\xbb\xf3\xfe\x04\x20\x3e\x1f\x0d\xa0\xb2\x7a\x6e\x3f\xad\xac\xdc\x5c\xea\x36\x2d\xbe\x32\x74\xf0\x56\x6e\x8d\x0b\x23\x19\x9d\x42\x53\xa8\xdb\x02\xe4\x34\xb2\xf3\xf8\xd8\xc0\x94\xba\x7c\x9b\x8c\x77\xff\x59\xc5\xe8\xfb\x96\xa3\x2f\x06\x9d\xcf\xe0\x7a\xf3\xcc\x5f\xa1\x25\xf4\xfa\x5d\xbe\x26\x9c\xfd\x9e\xea\x08\x44\xff\xbd\xe6\x7c\xb1\x18\x81\x76\x80\x10\x69\x77\x6b\x4d\xbe\x3b\x46\xea\xa5\x31\xf2\x45\x93\x0f\xa8\x8d\xbf\x3b\x2f\xf6\xf9\x46\x54\xc7\xa0\x26\x51\x9e\x84\xf8\x24\xf5\xb1\x77\x98\xc5\x5e\xf8\xb5\xfb\xb9\x8e\xc8\xaf\xe2\xec\xfd\x02\xce\xe4\x26\xdc\xed\xa3\x4d\x62\xee\x22\xc2\x90\x81\x50\xeb\x0c\x4a\xc8\x97\xdd\xf0\x07\x64\x37\x7e\xf3\x77\x30\xe1\x4c\xd1\xdc\x66\x59\xcf\x66\xfc\xac\x45\x4d\xf9\xe5\xbf\x13\xbf\xae\x77\x5b\xce\x92\x91\x1c\xe3\xf4\x08\x59\x99\x39\x4f\x7d\x62\xfa\xe4\x33\xc9\xb7\xe5\x3e\x0d\xcd\x31\xfe\x8f\x92\x76\x52\x02\x81\x4a\x8b\x6b\x5f\xdb\x37\x8c\xd4\x84\x62\xe9\xe9\x04\x0f\x85\x6e\x89\xef\x97\x82\xa1\xfb\x50\x90\x96\x10\x37\x86\x41\xaf\x26\x54\x10\xd1\xb5\x21\x8c\x5a\x57\x3a\x35\x81\x8d\x5d\x4f\x4f\x00\x27\x1b\x45\x29\x76\x2d\x6e\xdf\x1b\x79\x31\x39\x3b\x10\x51\x4a\xf6\x76\x0a\xfb\xf4\x04\x83\x1f\x90\xcd\x8b\x60\x37\x2f\xb6\x4f\x22\x4e\x81\xf0\x3c\x02\xe7\x96\xe3\xaa\x36\x74\x12\xe9\x8c\x40\xcb\x46\x6b\x64\xc2\x57\x64\x54\x2d\x75\x4b\x48\x14\x46\xad\x87\x08\xad\xbe\x1f\xc3\x7f\x3b\x20\x7d\x0a\x9c\xe9\x0d\x68\xf6\xc0\x64\x23\x36\x6a\x2b\xde\xac\x24\x79\x6a\xa6\x09\xed\x5b\x91\xb6\x03\x96\x8d\xc0\x60\xfc\x01\x99\xa1\x60\x93\xef\x1e\x97\x71\xf0\x0b\xe7\xd7\xa8\x6e\x00\x21\x1b\xfd\xe1\x9b\xc6\x37\xfa\xfa\x80\x80\xf9\x5c\xd7\xa4\xc0\x3f\x5b\xb6\x9c\x12\x37\x27\xd0\x33\x56\xff\xfe\x05\x94\x86\x61\x3b\x20\x38\x06\x2e\x4a\xf6\xe6\xdd\x59\x7b\x14\x1f\x86\x11\x4d\x7e\x40\x3e\xfb\x93\x3f\xa7\x11\xab\xc9\x37\x22\x53\x93\x33\x13\xb8\x7d\xa3\xbe\xfc\x90\x10\xfb\x4e\x12\x6d\xcd\x27\xf3\x5b\xd1\x1d\xc2\x8a\x92\x9e\x92\x3b\x5c\xc4\x49\x32\x03\xee\xea\x76\x0c\x84\xb0\x52\x74\xfa\x42\x16\xa2\x10\x92\x98\xb0\xe6\x9e\x56\x4e\xad\x8b\x78\x08\x89\xdf\xc1\xb8\x54\xf8\xc7\x05\xed\x84\xd6\xee\xc7\xce\xeb\x65\xbd\x0f\x2e\x4a\xf2\xe6\xc5\x0b\xfb\xde\x2f\x91\xa2\xa8\x5c\x6f\x45\xd6\x01\xcc\x8c\xee\x39\x81\x40\x37\x58\x12\xf7\x9a\x65\xdd\xc1\xb8\x5c\x25\x4f\xa9\x9f\x6b\xcb\x1e\x12\x11\x38\x67\xe6\x0b\x89\x04\x1f\x02\x8b\x51\x2e\xc3\x18\x9d\xd1\xb1\x27\x09\xf4\x7f\xb0\xf5\x36\xe4\xf9\xa0\x32\x11\xb7\xf9\x95\xd8\x54\xd2\x7c\xda\xa1\x7d\x33\xf1\xc5\xe0\x9d\x22\x32\x36\x3c\x0b\xa5\xb7\x91\xe3\x1e\xb4\xac\x54\x9e\x94\xe6\x6d\x68\xcb\x44\xd3\x71\x5a\x36\x14\xeb\x96\x35\x5b\xcc\xaf\xa3\x68\x1f\x56\xe6\x15\x0d\x36\x20\x29\xf4\xcd\x81\x66\x4f\x5c\xcd\x80\x37\xa1\x30\x0e\x2d\x9b\xdd\x86\x04\x3e\x20\x71\x92\x1f\x90\xd0\xc5\x4b\xba\xe5\x40\x79\x02\xdc\x14\x26\x6e\xe0\xb7\x43\x38\xa7\x28\x3e\x33\x3b\xf2\xa0\xde\x4c\xba\x67\x08\xf6\xa4\xdc\x34\x53\x86\xab\x49\x2c\xe5\x70\x26\x96\x39\x01\xb2\x6c\x43\xc7\xb9\x56\xa0\x27\x11\xec\x6d\x9c\xc3\xdb\xb1\xad\x6a\x30\xf0\x0c\xda\xaf\xd7\x83\x63\xb0\x4f\x53\x9c\x60\x65\xfb\x00\xc3\x2c\xdc\x83\xe7\xae\xe7\x97\x17\x45\x8e\x42\x3d\x99\xf6\x7b\x83\x4e\x10\x1a\xe6\x50\x1e\xc8\xad\x12\xdd\x88\xda\x24\xd0\x27\xd3\xb7\xac\x9a\x1c\x01\x7e\x6b\x65\xd8\x03\x7d\x49\xbe\x99\x0e\xce\x98\x5b\xb6\xe7\xf8\xde\xa0\xed\x68\x96\x79\x7b\x41\xc7\x31\x9c\x26\x3f\x36\x21\x3b\x33\xa1\xeb\xc9\x5e\xe4\xb8\x40\xfe\x11\x1c\x27\x39\x89\x8c\xcd\xce\xc4\xdc\x86\x6f\x9a\xb5\x70\x3e\x84\x9b\x24\x64\x27\xd9\x4a\x9a\x94\x9d\xbf\x4d\x11\xe5\x97\xf1\xb4\x41\x70\x92\x8f\xd4\xf2\xe3\x3e\xe8\xdd\x4f\x4d\xff\x0a\xd3\x8e\x43\x4f\xdc\x00\x9f\x6b\xe0\xfb\x40\xf7\xb7\x50\x37\xb2\xf0\x63\x28\xb2\xf0\x70\x62\x5f\x77\x14\xd9\xed\xc2\xd7\x21\xe0\x4c\xb4\x9f\x0e\x62\xd1\xcd\xf6\xaf\x50\x9b\x43\xf8\x17\x6f\xf5\xfd\x24\x6e\x1b\xc8\x37\x15\xc6\x89\x68\x59\xb3\x8b\xa5\x7c\x04\xe6\xc9\x14\xe1\xcb\x17\x19\xba\x40\xd3\x1d\xe4\xdb\xbf\xff\x8d\xdc\x39\x96\x2e\x47\x8e\x37\xef\x7e\xfc\x70\xe1\xca\xfd\xfa\xf5\x01\x49\x1f\x28\x59\x72\xb6\x81\xc1\xe1\x48\xfa\x50\xd1\x5a\xa8\x53\x37\x13\xfa\xbd\xa1\xc7\x09\xd8\x1b\x1a\x23\x61\x53\x14\xf7\x95\x0c\xf9\x89\x10\x44\xe6\xce\x00\x4d\x9e\x28\x91\x73\xbb\x72\xfd\x63\xfa\x03\x42\xb4\x48\xb9\xd5\x2d\xd5\x2a\xc2\xf6\x4c\x0e\xe9\x96\xca\xa5\x6e\x49\x28\x94\x7a\xb1\x63\x2a\xff\x6e\x4b\x40\x06\xed\xa2\xa7\x32\xdd\x52\xaf\xdf\xad\x15\xfa\xde\x57\xc5\x52\xa3\xd4\x2f\x21\x05\xbe\x57\xe0\x8b\xa5\x23\x07\x9b\xde\xbe\x63\xff\xe3\x24\x56\x8a\xb9\x9d\x30\xf6\xf1\x9c\x38\xb5\x4c\xa3\x64\x5f\x3e\xf1\xb2\x51\xa2\xb0\xc2\x44\xff\xc4\x11\x6f\xaa\x24\xc2\xad\xec\x9f\x2e\x87\x28\x1d\x49\x52\xd8\x54\x09\x8e\x2b\xcc\x79\x12\x38\x2c\x2a\xfd\x89\x62\x48\x21\x66\x5f\x16\x09\x65\xb0\xdb\x2a\x45\xbc\xc4\xf1\x57\x10\x48\xba\x6a\x1c\xd4\x90\xb2\x68\x07\x02\x64\x19\xca\x88\x01\xcc\x05\xd0\xf5\xf5\x1e\xa5\xb5\x32\x52\x7a\xaa\xf5\xfa\xbd\x80\xe6\x80\xb3\xef\x33\xb8\x9e\xbc\x01\x7d\x01\x27\x1e\x44\x88\x14\xbb\xad\x76\x94\xf0\xdd\xac\xd8\xc8\xa0\x45\xe2\x93\x3f\x3e\x8e\x20\x19\xf6\x6f\x9b\x10\x19\x0c\x8f\x63\xfe\xe2\xcb\xed\xe8\xe5\x09\x49\x9a\x02\x1b\x48\x2e\xb4\x91\x37\x60\xaf\x35\x53\xfd\x82\x53\xd4\xd7\xed\x49\xe9\xc3\x69\x28\x3e\xd2\x53\x70\x3e\xc5\xfa\x80\xe3\xd4\x6e\x5b\x80\xe1\x6a\x3e\xd1\x4c\x15\x3a\xee\x44\x07\xde\x7f\x7e\xa6\x7d\xf7\x80\xdc\xa1\x77\x5f\x7f\x3b\xd4\x95\x18\xa0\x24\x65\x49\x92\xf4\x7e\xc7\xc7\x0c\xae\xbd\x15\xdf\x93\xe7\xb6\x60\xe2\x68\xaa\xe9\xe5\xfa\x19\x04\xba\x99\x94\x20\x0d\x9a\xfc\x9a\x41\x96\x48\x80\x0c\xf1\x62\x77\x96\xe1\x4b\xa8\xa9\x53\x17\xd1\x4c\x17\xaa\xd0\x8e\xad\xda\xb7\x6f\xc8\x12\x22\x4b\x4d\xd7\x91\xd7\x05\xb4\xd7\x88\xb8\xde\xc0\x77\x2c\xc4\x9d\x02\x17\xd1\x1c\x64\x39\xdd\x7e\xab\x39\x88\x3b\x85\x88\xa2\xd9\x8e\x8b\x68\x2e\x34\x10\xcd\xf4\xbf\x91\x2c\x63\x6e\x39\x9a\x0b\x3d\x59\x66\x20\x6b\x4f\xb8\x01\xf0\x6d\x97\xc6\xd7\x4f\xb1\x65\x4c\x4c\x32\xbd\x25\xdc\x78\x2e\x63\xb1\x82\xb2\x27\x48\x4f\xaa\x5f\x68\xee\x6b\xd8\xeb\xe8\x8d\x89\x34\x51\xa4\x8c\x4b\x46\x16\x49\xc5\x3d\x30\x8e\xb5\xb0\xa5\xcb\x20\x6d\x72\x4e\x9f\xe2\xa0\xcc\x97\x3a\xdf\x73\x29\xdb\x5e\x42\x04\x27\x3f\xa5\xe8\xdc\x51\x5d\xdb\x39\xf4\x04\x35\xa3\xe8\x6c\xb6\x1b\xbe\x25\x08\x11\x35\x55\x33\xdd\x6c\x53\x82\x37\xf5\xe9\x1a\x10\x35\x5d\x73\x35\xe8\x9c\x33\x7b\xf3\x1e\xc0\x8b\xa7\x07\x7b\xeb\x89\xb9\x30\x44\x68\x9f\x33\xd5\x5c\x18\x13\x67\x21\x42\xd3\xb5\x3d\xa4\xc9\xb6\x92\x7c\x69\xa6\xa2\x07\xa5\x71\x19\x3a\xae\x66\x06\xeb\x76\xb9\xd4\x15\x1d\xa8\xe7\x51\x30\xb5\x0c\x38\x91\x2d\x03\x68\x49\x78\x09\x3c\x1b\x5e\x03\x38\x5e\xec\x0b\xbd\x85\x63\x00\x6f\x2d\xb2\x49\xcf\x9d\xda\xd0\x99\x7a\x3b\x1c\xdd\x5a\x5e\x3a\xd5\x80\xb2\xb6\x30\x2e\x9d\x3d\xd5\xd4\xe9\x79\x73\xfd\xc8\x61\x58\xb2\xa6\x68\x50\xde\x74\xe6\xc4\xc5\xfe\x29\xdd\xe5\xcb\xc0\x05\xa1\x0d\x7e\xfb\xb6\x39\xb9\xf1\xa2\x86\xe6\x20\x00\x69\xf8\x9f\xeb\x70\x8d\x18\xc0\x76\xa6\x40\x87\x32\xb2\x70\x34\x53\x45\x9a\xc1\xe7\xbc\x66\x02\x7b\xbd\x99\x0e\x4c\x19\xf1\x12\x53\x9a\xfc\x06\x4d\x6f\x23\xe7\x8d\x86\x32\xe2\x5a\x88\x68\x59\x8e\x8b\xcc\xa1\xad\x58\x86\x6f\x8e\x96\x82\x38\x96\x01\x7d\x7f\xad\x41\xe7\xfb\x29\x5f\x1b\x21\xed\x50\x3b\x30\x0a\x3d\x23\x90\xdf\xc4\xad\xf8\x97\x09\x8c\xa4\x7c\x80\x26\xcf\x80\x91\x96\x54\x70\x51\x96\x3c\xe9\xc6\x24\x4b\x93\x88\xb8\x76\xc3\xa4\xf1\x98\xe0\x92\x34\xc4\x4b\x16\x32\x53\xb8\x17\xe3\x76\xeb\xe0\x87\xb7\x7d\x3f\x4f\xb0\xb1\x2f\x28\x72\x3f\xe9\xdd\xba\x7d\x3f\x14\x6d\x3c\xdd\xbe\xda\xfe\x96\x61\x86\xab\x19\x1b\x8f\x1e\xd0\x50\xe0\xdb\xdf\x48\x34\x08\xef\x32\x32\x07\x6b\xdd\x02\x32\xe2\xb8\xf6\x0c\xae\x1d\x44\x02\x26\x22\x42\x04\xa3\xa9\x9d\xa0\x1d\x44\xb7\x4c\xf5\x01\x71\x20\xf4\x00\x04\x43\x73\x9e\xfb\xf9\xae\x5a\x3f\x0c\xb0\x2a\x05\x82\xee\x69\xef\xf0\x3b\x92\x5f\xb8\xc8\x12\xde\xe9\xba\xa7\xd1\x7e\xd2\x82\x4c\xa1\x0d\x1f\xbc\xfc\x62\x09\x11\xd9\x32\xef\x5c\xc4\x84\xbe\xb2\x07\xe9\xf4\xcb\xc2\x4f\x2d\x90\xff\x83\x6f\xd0\x46\x80\x0a\x34\xf3\xff\xbe\x27\xb2\xb6\xc9\xbb\x82\x8c\xce\x1f\x50\x68\x35\x06\x4d\x61\x93\xad\xf4\xc7\xed\x92\x8f\x33\x2e\x6f\x8a\x4a\xb6\xeb\x89\xa2\xe9\x9e\x1b\xb4\x17\x3a\xcc\x96\xce\x79\x17\x34\x81\xe8\x59\xb8\x68\x59\xfa\x56\x3b\x10\x19\x2a\x60\xa1\xbb\xe1\x2b\x3d\x32\x82\x5a\x4e\x35\x17\xea\x9a\xe3\x6e\x52\x83\xdf\xff\x38\x27\xd1\xf6\xaf\x3d\xc5\x8d\x87\xc1\x04\x97\xe6\x6f\x77\x2e\x60\xfc\x66\x6c\x5f\xcf\xf4\x69\x96\xf7\x97\x9f\xd9\x17\x41\x62\x89\x33\x90\x08\x94\x27\xae\x31\x47\xf8\x1e\xf2\xc9\xcf\x50\xa0\xe4\x22\xff\x87\x94\xbb\xad\x66\xe2\xac\x4f\x41\x29\x2d\xd6\xbd\xe9\x37\x96\x6e\xd3\x3b\xcd\x74\xa0\xed\xfa\x59\xf3\x46\x58\xb2\xe6\x04\xb2\x74\x5c\xe0\x42\xff\xf5\x5b\x10\x48\x53\xc4\x59\xcc\xfd\x93\x29\x19\x09\xa8\x41\x34\x63\xae\x43\x03\x9a\xae\xcf\xc8\xde\x7e\x29\x51\x85\x37\x9b\xa6\xf0\xbd\x32\x77\xff\xf9\xef\xdd\x03\x12\x7f\xe2\x32\x41\x03\x52\xe7\x9d\x7c\x54\x73\x5f\x6e\xff\xbc\xd8\xeb\x9f\x17\x7b\xfd\xf3\x62\xaf\x7f\x5e\xec\xf5\xcf\x8b\xbd\xce\x79\xb1\x57\x8a\x0f\xfd\xe7\x2d\x5f\xff\xbc\xe5\xeb\x9f\xb7\x7c\xfd\xf3\x96\xaf\x1d\x0f\xff\xbc\xe5\x2b\x7a\xfd\xf3\x96\xaf\x8b\x7e\x03\x20\x38\xcf\x6b\x07\x4f\xdf\xf5\x3a\x0d\x44\x06\x2e\x10\x81\x03\x11\x79\x61\xcc\xfd\xca\xbe\x0e\x5d\xe8\x1f\xc4\xfd\xff\x00\x00\x00\xff\xff\x5f\x65\x45\xe7\x0a\xf2\x00\x00") +var _failed_transactionsHorizonSql = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\x7d\xf9\x6e\xe2\xc8\xf6\xf0\xff\xfd\x14\x56\xeb\x4a\xe9\xfe\x25\xdd\x78\x5f\x7a\xbe\xbe\x92\xd9\x09\x60\x76\x08\x19\x8d\x50\xd9\x2e\x1b\x07\x2f\xc4\x36\x01\x72\x75\xdf\xfd\x93\x17\xc0\x18\x1b\xcc\xd2\x99\x99\xab\xb1\x5a\xad\x80\xab\xce\x56\x67\xab\x53\xc7\xf8\xdb\xb7\x4f\xdf\xbe\x21\x6d\xcb\x71\x55\x1b\xf6\x3a\x0d\x44\x06\x2e\x10\x81\x03\x11\x79\x61\xcc\x3f\x7d\xfb\xf6\xc9\xbb\x5f\x5c\x18\x73\x28\x23\x8a\x6d\x19\xbb\x01\x6f\xd0\x76\x34\xcb\x44\xb8\xef\xf4\x77\x2c\x32\x4a\x5c\x23\x73\x75\xe2\x4d\x8f\x0d\xf9\xd4\x2b\xf5\x11\xc7\x05\x2e\x34\xa0\xe9\x4e\x5c\xcd\x80\xd6\xc2\x45\x7e\x22\xe8\x6f\xfe\x2d\xdd\x92\x66\x87\xdf\x4a\xba\xe6\x8d\x86\xa6\x64\xc9\x9a\xa9\x22\x3f\x91\xbb\x41\xbf\xcc\xde\xfd\xb6\x01\x67\xca\xc0\x96\x27\x92\x65\x2a\x96\x6d\x68\xa6\x3a\x71\x5c\x5b\x33\x55\x07\xf9\x89\x58\x66\x08\x63\x0a\xa5\xd9\x44\x59\x98\x92\xab\x59\xe6\x44\xb4\x64\x0d\x7a\xf7\x15\xa0\x3b\x70\x0f\x8d\xa1\x99\x13\x03\x3a\x0e\x50\xfd\x01\x4b\x60\x9b\x9a\xa9\xfe\x16\xd2\x0e\x81\x2d\x4d\x27\x73\xe0\x4e\x91\x9f\xc8\x7c\x21\xea\x9a\xf4\xe0\x31\x2b\x01\x17\xe8\x96\x37\x8c\x6f\xf4\x4b\x5d\xa4\xcf\xe7\x1b\x25\xa4\x56\x46\x4a\x4f\xb5\x5e\xbf\x87\xb4\x84\xc6\x38\x1c\xff\x7d\xaa\x39\xae\x65\xaf\x27\xae\x0d\x64\xe8\x20\xc5\x6e\xab\x8d\x14\x5a\x42\xaf\xdf\xe5\x6b\x42\x3f\x32\x69\x7f\xe0\x44\xb2\x16\xa6\x0b\xed\x09\x70\x1c\xe8\x4e\x34\x79\xa2\xcc\xe0\xfa\xb7\x8f\x40\x28\xf9\x7f\x7d\x04\x4a\x4f\xaf\x3e\x8e\xc1\x00\xdb\xf9\xdc\x05\x04\x7a\x8a\x7c\x0c\x59\x64\xd4\x0e\xb8\x3f\xbc\x26\x14\x4b\x4f\x91\x91\x21\x58\x9f\xaa\x09\x54\x14\x28\xb9\xce\x44\x5c\x4f\x2c\x5b\x86\xf6\x44\xb4\xac\xd9\xf1\x89\x9a\x29\xc3\xd5\x24\xc2\x9c\xe9\x00\x5f\xd1\x9d\x89\x65\x4e\x34\xf9\x9c\xd9\xd6\x1c\xda\x60\x3b\xd7\x5d\xcf\xe1\x15\xb3\x77\x94\x5c\x45\xc5\x79\x73\x75\x28\xab\xd0\xf6\x27\x3a\xf0\x75\x01\x4d\xe9\x2c\x16\x22\xd3\xe7\x36\x7c\xd3\xac\x85\x13\x7e\x37\x99\x02\x67\x7a\x21\xa8\xeb\x21\x68\xc6\xdc\xb2\x3d\x73\x0c\x7d\xea\xa5\x60\x2e\x95\xa5\xa4\x5b\x0e\x94\x27\xc0\x3d\x67\xfe\x46\x99\x2f\x50\xa5\xd0\x2e\x2f\x20\x3a\x3a\x13\xc8\xb2\x0d\x1d\xe7\xf8\xf4\xa9\x6b\xcb\x7e\xdc\x99\xe8\x96\x35\x5b\xcc\x33\x8c\x9e\x9f\x22\x29\x18\x05\x34\xfb\x4c\xc0\x1b\xa7\x9b\x79\x82\xe7\x27\x14\x05\xda\xd9\x86\x6e\xc0\x5f\x30\x25\x14\x6b\xb6\x49\xbe\x6b\x3d\x03\x49\xd4\x15\x9f\x9a\x31\xf7\x26\x4c\xdd\x93\x2b\xe0\xec\x39\x20\x71\x7d\x52\x8d\xa6\x5b\x4b\xcf\x32\xd8\x0a\xe8\xb0\x4e\x0e\xd4\x1c\x77\xe2\xae\x26\xf3\xd3\x20\xbd\x91\xd6\x3c\xeb\x48\x98\x75\xd8\x26\x94\x1c\x1f\x2c\x6e\xcc\xfd\xe4\xb0\xd3\x5e\x4c\x5c\x67\x5b\xcc\x20\x46\x7a\xd2\x76\x9c\xc5\x29\xcc\xdb\xc1\x92\x25\xc3\x33\xf3\x82\xad\x1a\xcc\x81\xed\x6a\x92\x36\x07\xe6\xd1\xe0\x7d\x6a\xea\x64\x7e\x66\x6e\xb2\x8d\x68\xe7\x52\x90\x3c\xf1\x6c\xfc\xbe\xf0\xb2\xe0\x0b\x06\xfe\x72\xf8\xc1\x62\x7a\x2b\x19\xfe\xe9\xc5\x87\x4d\xea\xe7\x2b\xc3\x24\x23\x05\xaa\x65\xcf\x27\x86\xa6\x86\x09\xc3\x11\x12\x62\x23\x33\xf3\x78\x7e\xbe\x77\x0c\x72\x56\xe5\x0c\x66\x17\x5a\x8d\x41\x53\x40\x34\x39\xc0\x5c\x2c\x95\xf9\x41\xa3\x9f\x11\x76\x8a\xd2\xdd\x00\x72\xb8\xdc\xc7\x21\xf9\x9f\xb2\xb3\xbf\x89\xd2\xbd\x52\x67\x50\x12\x0a\x17\xc8\xcc\xcb\xb3\x1d\xf8\x7a\x36\xe6\x3d\x20\x99\x67\xcb\x30\xe3\xd8\x5d\x36\x9b\x99\xc3\x14\xab\x3f\x87\xbf\x64\x10\xd9\xe6\x86\x79\x5f\xb6\xc1\x61\x92\x97\x99\xb7\xd0\x03\x9c\xc3\x4b\x30\x25\xe3\xd8\x30\xfd\xcb\x4e\xcf\x26\x5f\xcc\x42\x51\xcc\x87\x1c\x1f\x1c\x71\x09\xe1\x40\xbe\x52\xe9\x96\x2a\x7c\x3f\x61\xb0\xa1\x79\x3b\x0e\x4d\x82\x5f\xcc\x85\x01\x6d\x4d\xfa\xfd\x8f\xaf\x19\x66\x81\xd5\x05\xb3\x74\xe0\xb8\x5f\x80\xb9\x86\xba\x5f\x8a\xc9\x30\x43\xd1\xec\xc4\x29\xe5\x81\x50\xe8\xd7\x5a\xc2\x11\x7e\x26\x40\x55\x77\xd4\x3d\x20\x07\x84\x1e\x81\xb1\xe1\xee\x0a\x18\x1e\xaf\xfe\xf4\x1d\xf1\x0f\xc8\x39\x8c\xf8\xac\x67\x80\x50\x7a\xea\x97\x84\x5e\x0c\x84\x3e\x57\x9d\x57\x7d\xa3\x8b\x85\x6a\xa9\xc9\x1f\x60\xf8\xed\x53\x50\x85\x13\x80\x01\x7f\x6c\xbe\x43\xfa\xeb\x39\xfc\x11\x4e\xf9\x0d\xe9\x49\x53\x68\x80\x1f\xc8\xb7\xdf\x90\xd6\xd2\x84\xf6\x0f\xe4\x9b\x5f\x9c\x2b\x74\x4b\xde\x7a\x85\x90\x37\xf0\x3e\xed\x41\xdc\xbf\x19\x02\x2e\xb4\x9a\xcd\x92\xd0\x3f\x02\x39\x18\x80\xb4\x84\x7d\x00\x48\xad\x87\xdc\x6d\xca\x6e\x9b\xef\x1c\x1f\xc8\x5d\x1c\xf3\x86\xfd\x10\xe7\x56\x42\x27\xf9\xd9\x93\xa5\xd0\xea\xc7\xe4\x89\x8c\x6a\xfd\xea\x96\xac\x68\xfd\x6d\x0f\xfd\x0e\x4a\x8c\x90\x73\x98\x3f\x00\xe2\x0b\xa0\xdd\xc8\xcd\xd5\x5e\xa7\x81\xcc\x6d\x4b\x82\xf2\xc2\x06\x3a\xa2\x03\x53\x5d\x00\x15\xfa\x62\xc8\x58\x2f\x8c\x92\x7b\x5a\xd1\x42\xf2\x37\xba\xba\xa3\x7f\xb3\xb6\x49\xb2\xdc\x6a\xf6\x49\xf8\x48\xb7\xd4\x1f\x74\x85\x5e\xe4\xbb\x4f\x08\x82\x20\x0d\x5e\xa8\x0c\xf8\x4a\x09\xf1\xb9\x6f\x36\x07\x81\xbf\xeb\xf5\xbb\xb5\x42\xdf\x1f\xc1\xf7\x90\x7f\x4d\xfe\x85\xf4\x4a\x8d\x52\xa1\x8f\xfc\x0b\xf3\x3e\xc5\x57\xe3\xa4\x21\x5e\xc7\xdd\x29\xf0\x37\x63\x0e\x4f\x62\x2e\x8b\xa7\xba\x8e\xbf\x0c\x18\xb6\x2c\x6e\xbf\xba\x88\xc3\x2f\x9f\x10\xa4\xc0\xf7\x4a\xc8\xa8\x5a\x12\x90\x7f\x61\xbf\x63\x7f\xe4\xfe\x85\xfd\x8e\xff\xf1\xef\x7f\xe1\xfe\xdf\xf8\xef\xf8\x1f\x48\x3f\xb8\x89\x94\x1a\xbd\x92\x27\x94\x92\x50\xfc\x9a\x28\x99\x0c\x71\xe0\x4a\xc9\x9c\xc6\xf0\xab\x25\xf3\xff\x2e\x91\xcc\x61\x4c\x0d\xe5\xb0\x8d\xc3\xd9\x04\xb1\x0b\xdb\x07\x10\x7d\x8a\x11\xa4\xe7\xc9\x0a\xf9\xb9\xf3\x00\x0f\xc1\xd7\xfd\x71\xbb\x84\xfc\x8c\x5a\xc4\xd7\x24\xab\xbd\x29\x8d\x71\x80\x31\x12\x37\x66\x9c\x9d\xc2\xc4\x14\xe8\x5a\x2a\x93\x80\xc6\x28\xdd\x33\xc8\x7d\x72\x77\x5a\x76\x48\x6d\x52\x9a\x77\x35\xb5\x09\x40\xe3\xd4\x46\x8d\xe4\x28\xb5\x5e\xe4\x92\xa1\x02\x16\xba\x3b\x71\x81\xa8\x43\x67\x0e\x24\x88\xfc\x44\xee\xee\x7e\xdb\xbf\xbb\xd4\xdc\xe9\xc4\xd2\xe4\xc8\x51\xda\x1e\xaf\xd1\xfc\x37\x64\xd1\x37\xb0\x6c\xec\x05\xb6\x18\xdd\x7c\x07\x1c\x69\x32\x22\x6a\xaa\x66\xba\x7e\x62\x20\x0c\x1a\x8d\x80\x1d\x60\x78\x69\x3c\x22\x4d\x81\x0d\x24\x17\xda\xc8\x1b\xb0\xd7\x9a\xa9\xc6\x86\x99\x0b\x63\x9b\xf2\x23\x9a\xe9\x42\x15\xda\xb1\x21\x8a\x0e\x54\x07\x71\x0c\xa0\xeb\x87\x68\x5c\xcb\xd0\x0f\x91\x7c\xc1\x29\xea\xeb\x76\xe4\xe1\xb2\xc7\xf7\x0d\x97\x8a\x23\x5e\xed\xd8\x8a\xc4\x85\xab\x03\x81\xcc\xe7\xba\xe6\xd7\xec\x11\x57\x33\xa0\xe3\x02\x63\x8e\x78\x6b\xe6\x7f\x44\xde\x2d\x13\x1e\x12\x9a\xb6\x2b\xda\xe4\xa3\xe1\x76\x2a\x1b\xcd\xdb\xcd\x57\x0a\xd4\x50\x0d\xf9\x6e\x3f\xc8\xe8\x30\xff\x8b\x9a\x50\xe8\x96\xfc\xf4\x2b\x3f\x0e\xbf\x12\x5a\x48\xb3\x26\x0c\xf9\xc6\xa0\xb4\xfd\xcc\x3f\xed\x3e\x17\xf8\x42\xb5\x84\x60\xa7\x98\xb9\x58\xec\x71\x40\x07\xaa\x18\x16\x3d\x10\x13\xae\xdc\x37\xa0\x7f\xb9\x4b\xe1\xf8\xee\xc7\x0f\x1b\xaa\x92\x0e\x1c\xe7\x6b\x7c\xb9\x82\xb3\x8a\x04\xdd\xa2\xc9\xaf\x47\x16\x2a\xd8\x1b\x5f\xcd\x59\x50\xd1\xd9\xf2\x95\x6c\x19\xbb\x5a\x5d\x32\x99\x89\xc3\x25\x4b\x4e\x1a\x8e\xe1\xc9\xc3\x83\xf2\x5f\xc2\x04\x8a\x3e\x66\x61\xc9\xe5\x85\x1b\xa9\x6d\x14\xe6\x87\x29\xed\x31\x46\x90\xd6\x48\x28\x15\x91\xfc\xf8\x04\x47\x41\x85\xee\x38\x43\x5b\x58\xb1\xdb\xdf\x35\x39\x8d\xb6\x4d\xcd\xe7\x5a\xad\x0b\xe1\x84\x6a\x17\xb3\x99\x49\x9a\xa7\x3f\x2c\x71\xa5\x8d\xfc\xec\x1f\x7c\x7c\x4e\xd1\x66\x5f\x8f\x93\x6f\xc9\xd0\x05\x9a\xee\x20\x2f\x8e\x65\x8a\xe9\xca\xb6\x29\x94\x5d\x2b\x87\x10\x4e\x28\x87\xcd\xb9\x75\x0a\x6d\x91\xc3\xe4\x4c\x56\x98\x74\x8e\x9d\x3c\x31\x14\x4b\xa4\x32\xea\x2f\xc4\x96\x8e\x8d\x97\x43\x63\x18\x76\x0b\x91\x6d\xfc\xf6\x30\x39\x16\x98\xac\x85\xbb\x8b\x4d\xf1\x39\x36\x04\xee\xc9\x49\xc1\xd8\xc5\x5c\xce\x3c\x76\xab\x3a\xe1\xc7\xd8\x39\xfb\x01\x2f\xd8\x41\x3e\xe0\x02\x7d\x22\x59\x9a\xe9\x24\xeb\xa0\x02\xe1\x64\x6e\x59\x7a\xf2\x5d\xff\xe4\x53\x81\x69\x6b\xed\xdf\xb6\xa1\x03\xed\xb7\xb4\x21\x5e\x1e\xea\xae\x26\x7e\x9a\xa4\xbd\xa7\x8d\x9a\xdb\x96\x6b\x49\x96\x9e\xca\x57\x7c\x8d\x36\xca\x02\x81\x0c\x6d\x3f\xbd\x08\xbe\x77\x16\x92\x04\x1d\x47\x59\xe8\x93\x54\x45\x09\x19\x07\x9a\x0e\xe5\x53\xa3\x42\xd2\x53\x54\x28\xdd\xf4\x52\xea\xdb\xd7\x5a\x62\xca\x99\xc9\x89\xb8\x98\xdd\x23\x9d\xf6\x71\xe7\xb2\x7c\xdb\x50\x77\x14\xc7\x47\x85\xbe\xb3\x18\xbd\x32\x14\x1e\xc5\x75\x18\x1a\x93\x87\x1f\x09\x95\x91\xd3\x9f\xec\xba\xf9\xed\x9b\x97\x0e\x42\x19\xd1\x9c\xc9\x1c\xac\xbd\x8d\xef\x4f\x7f\x87\xb5\xd9\x7b\x21\xae\x15\x16\x5d\x1f\x10\x1b\xb8\x53\xcf\x44\xa7\xc0\xf4\xdc\xba\xa9\x7a\x3e\xc0\x81\xb6\x8b\xe8\x9a\x09\x9d\x53\x8a\x7e\x6a\x5f\xb5\xdf\xc6\x95\xb2\xf7\xf2\xb6\x1a\x52\x20\x17\x3f\xe4\x5e\x19\x71\x43\x57\x63\x2d\x6c\x69\xdb\x17\x92\x12\xeb\x36\xfe\xeb\xee\xee\xc7\x8f\x53\x7b\xbf\x9d\x34\x11\xd1\xb2\x74\x08\xcc\xad\x3c\x7d\xe9\xa6\x9b\x5e\x78\xde\x77\xad\x77\x09\x5b\x14\xbf\xdc\x34\x8d\x09\x3d\xf5\x25\x41\xd5\x6f\xd1\x49\x45\x1b\x6b\x90\x3c\x36\x28\xec\xd9\x3c\x36\x24\xd8\x9e\x27\x0e\x38\x6c\x35\x3d\x31\xee\x28\xba\xed\xa8\x23\x18\x7d\x92\x34\x67\xe2\x40\x5d\x87\xf6\x46\x1b\x36\xa1\x52\x93\xe0\xc4\xdc\x4b\x0b\x82\xef\xf6\x53\x85\x5d\x93\xd3\x24\x96\x44\xec\xb5\x59\xc5\x6f\xda\xd6\xc2\x94\xfd\x3e\x65\x5d\x9b\xcf\x81\x0a\x0f\x81\x6a\xce\x04\xae\x80\xe4\xee\xd3\x15\x69\x3b\x48\xec\x64\xf5\xd9\x9d\xf8\xbd\xce\x48\xa1\x5a\x2a\xd4\x91\x2f\x5f\xa2\xa2\xff\x37\x82\x7e\xfd\x7a\x0a\x54\xd2\xf4\x8d\xb4\xff\xdf\xc1\x02\x64\x80\xb7\xb7\x18\x31\xf0\xb1\x95\xf2\x09\x3c\x6a\x83\xc9\x27\xf6\x37\xb0\xca\xe4\x1e\x8c\x8c\x51\x3f\x8b\x87\xbc\x26\xee\x9f\xea\x77\xb8\x4d\xe4\x3f\x81\xe5\xa3\x62\xff\x99\xcc\x5e\x19\xfd\x4f\x60\x3b\x8c\xff\x69\x13\x8e\x64\x00\x7b\x3d\x2e\x37\xd4\xd5\x8d\x7e\x46\x49\xca\xbc\x29\x0c\x83\xc6\x89\xad\x66\xd6\xb8\x7e\x3c\x44\x27\x8e\xdd\xa1\x4e\xb4\x17\x6f\x57\x93\xbe\x2d\x4a\xdb\x70\xfe\x29\x5b\x46\x77\x35\x81\xe6\x1b\xd4\xad\x39\x4c\x2a\xc3\xba\x2b\x6f\x03\xe7\xe7\x6c\x89\x37\x0d\xe8\x82\x94\x5b\xde\xd6\x31\xed\xb6\xa3\xa9\x26\x70\x17\x36\x4c\xaa\x18\x72\xf4\xd7\xdf\xff\xd8\xa5\x46\xff\xf9\x6f\x52\x72\xf4\xfb\x1f\x71\x99\x43\xc3\x4a\x29\xee\xed\x60\x99\x96\x09\x33\xa4\x5a\x1e\xac\x43\x30\x21\x67\x9a\x01\x27\xa2\x17\x06\xfd\x0a\x3c\x6b\x7b\x39\xeb\x9e\x5a\x26\xdf\x34\x34\x73\x92\xa2\x3d\xe9\x03\x26\xf1\x08\x9b\x38\x28\xc4\xab\x82\xf9\xde\x58\xb8\x72\x6d\x30\xf1\x44\x0d\x6d\xc7\x5f\x85\xdf\xff\x88\x6f\x83\xf7\x83\xb4\xb7\x64\x1e\xdb\x2a\x8c\xd5\x15\x4c\x13\xda\x93\x6c\xa6\xba\x83\x74\xd4\xae\xa2\x80\x4f\x6b\x43\x78\xfa\x01\x97\x93\x8d\x69\x05\xe4\x9d\xaa\xa4\x22\x9a\xbc\x71\x5a\x9b\xce\xbe\x2c\x9e\x36\xf0\x5a\x7e\x1b\xe5\x89\xa6\xc1\x5e\xa9\x7f\xa4\x7c\x1e\x2d\x54\x46\x8b\xe7\xe7\x6d\x1d\x6f\xc7\x44\xc6\x9e\xca\xa3\x4c\x1d\xdd\x72\x66\x61\x32\x35\x61\xb9\x19\x9b\x99\xdb\x52\x8f\x32\x7a\x22\xba\x26\xb3\x5a\x04\x2e\x40\x14\xcb\x3e\x71\x88\x88\x14\xf9\x3e\x7f\x82\xbd\x9a\xd0\x2b\x75\xfb\x48\x4d\xe8\xb7\xf6\x0e\x12\xfd\x64\xa4\x87\x7c\xc1\x1e\x90\x3b\x1c\xdd\x5c\x77\x0f\x08\xfe\x80\xa0\x0f\xc8\xdd\x5d\x3a\x39\xc7\x0e\xf2\xce\x25\x29\x7e\x98\xb7\x21\xeb\x0e\x9b\x68\xa6\xe6\x6a\x40\x9f\x04\x7b\xfc\xef\xce\xab\x7e\xe7\xd3\x8a\x71\xdf\x50\xfa\x1b\x4a\x20\x18\xfb\x03\x67\x7f\x90\xcc\x77\x94\xc0\x49\x8e\xbe\x47\x71\x8f\xe8\x4c\xd0\xf1\x49\xf0\xc0\xcc\xde\x8a\x88\xeb\x89\x6b\x69\xf2\x71\x4c\x1c\x4d\x31\xe7\x60\x22\x26\x0b\x07\xee\x9c\xac\x66\x1e\x3c\xa4\x73\x14\x1f\x49\xa2\x24\x7b\x0e\x3e\x72\x02\x64\x79\x12\x2f\x75\x1e\xc5\x41\x91\x14\x81\x9f\x83\x83\x9a\x04\x69\xc5\x66\x83\xe3\x1f\x91\x1f\x45\x41\x13\x28\x7e\x16\x1b\xf4\x06\x45\xe8\xfd\x32\xa0\x60\x49\x8c\x3a\x07\x05\x33\x31\x2c\x59\x53\xd6\xd9\xb9\x60\x31\x1a\x3f\x0b\x05\xbb\xc7\x45\xd8\x19\x9f\x01\x0f\x43\xd2\xc4\x79\x78\xbc\x45\x07\xaa\x6a\x43\x15\xb8\x96\x7d\x5c\xa7\x38\x14\x43\xb9\x73\xc0\x73\x3e\xf8\xa0\x0c\x3e\x59\xc9\xf6\x71\xe8\x38\x83\x9d\xb5\xd4\x18\xea\x83\x0f\x57\xc1\xaf\x32\x1c\x47\x40\x71\xcc\x59\xd2\xc1\xb0\x28\x82\xed\xee\xd3\x73\x00\xc7\x11\x71\x34\x77\x1e\x27\xf8\xde\x42\x87\xfb\xfd\xe0\x59\xec\x63\x98\x30\x94\xa1\xc8\xb3\x56\x04\x23\x02\x76\xb6\xe5\x95\xa3\x2b\x8e\x61\x38\x43\x9f\xc7\x09\x39\x51\xb4\xd5\xe6\xb9\x14\xcb\xd0\x27\x8a\x06\xf5\xa3\xae\x11\xc3\x28\x0c\x3b\xcb\x09\x63\xd4\x26\xe7\xdc\x1c\x93\xac\x4e\xb0\x41\x33\xe7\xb9\x79\x8c\x9e\x68\xa6\x0a\x1d\x77\x72\x78\x10\x73\x02\x15\xc3\xb1\xe7\xad\x08\xb3\x17\xea\xfd\x13\x2f\x70\x3c\x98\x60\x38\x8a\x12\xe4\x59\x48\xd8\xad\xfa\x2a\x96\xbd\x49\xca\xf7\x70\x60\xe8\x37\x02\x43\x30\xf2\x07\xc6\xfd\x20\xb9\xef\x18\x4e\xb0\x04\x75\x8f\x62\xd9\x43\x23\x99\x1c\x99\xae\x06\x4c\x90\xbe\x54\xc4\x85\x31\x4f\x5f\x87\xeb\xb1\x30\x81\xb1\x27\x1e\xa9\x4d\x5c\x6b\x73\xce\x7c\x5b\xac\x24\xed\x63\x35\x16\x2b\x6f\xff\xfc\x4b\xc4\x47\x11\x51\x2f\x76\x50\x41\xbd\x31\x32\xd2\x7f\x5e\xd3\x86\x92\x65\xca\x5a\xf0\xac\x18\x30\xe5\x9d\xf6\x79\xde\xe0\xd6\x0c\x52\x13\x45\xd3\x5d\x68\x4f\xec\x85\x0e\x6f\x0d\x9c\xf6\xbc\xcb\x42\x9c\xd8\x10\xc8\x13\xcb\xd4\xd7\x3b\xf8\x38\xfe\x0d\xc5\xbe\xa1\x38\x82\x62\x3f\x08\xe2\x07\x41\x7c\x27\x19\x0e\x25\xee\x51\xd4\x4f\x82\x13\x73\xe0\xa3\x6d\x55\xe7\x26\xc1\x07\xad\x55\xd1\xe4\xbc\x92\x7f\xaa\x74\x1e\x47\xc3\xc6\xa8\x35\xae\x96\x1b\xc3\x7e\x7d\x34\xa4\xca\x95\x2a\x4f\x34\x84\xf1\x18\x7f\xec\xd4\x9b\x4c\x8b\x7f\xe4\x07\xa5\x4e\x79\x40\x37\xda\x85\x5e\xa9\x3c\x7c\x6a\x09\x71\xd1\xa4\x22\xc1\x3d\x24\x3c\x35\xca\xb7\xc7\x3c\x35\x26\x47\x7c\xa9\xfa\x34\xea\xe2\x83\x7a\x0b\x1f\xb4\xc8\xfc\xa0\x52\x1d\x74\x18\xb2\x34\x68\xd7\x5b\x02\xde\xa9\x0e\xc9\x51\xb7\xda\xaa\x75\x85\x7a\xbd\x7a\xe0\xb9\x52\x91\x10\x1e\x92\xc2\x53\xbd\x42\x77\x05\xb2\x25\xd4\x4a\xed\x42\x53\x28\xe7\x19\x02\xe7\x49\x82\x7e\xa6\xda\x42\xb1\xd7\x6d\x54\x46\x75\xa6\x92\x6f\x14\x9a\x9d\x46\xad\xdc\x22\x7b\x4c\x69\x3c\x1a\x0e\x32\x23\x21\x7d\x71\x75\xdb\xe3\x6a\xad\x81\x17\x6a\x44\x59\xe8\x90\xf9\xa7\x46\xb9\x29\x14\x1b\xe5\xc7\x81\xd0\x1e\xe0\xd5\x31\xf1\xdc\x2c\xf7\xaa\x2d\x61\x50\x28\xb5\xf8\xde\x88\xe9\x14\x98\xd6\x13\x5e\xbd\xbb\xb4\x0d\xd0\xdb\xfe\x9d\x58\xeb\xb0\x75\x7a\xf7\xd4\xc3\x77\x07\x1e\x6f\x91\x7b\x40\xc8\x07\xc4\xb5\x17\x30\x7d\x17\x76\xa4\xf9\xed\x62\xfd\x0b\xaa\x13\x51\xed\x93\x6c\x28\x6b\xee\x04\xe8\xf3\x29\x30\x17\x06\xe9\x59\xcc\xa0\x57\xbc\xbb\x72\x39\x2f\x69\xf7\xba\x89\x9c\xf7\x6a\x29\x0f\x08\x96\x55\xca\x49\xdd\x5e\x97\x8a\x79\xd3\xf1\x15\x91\x33\xc6\x78\x09\x07\x43\xe0\x2c\xe6\x13\xe5\xd9\xe4\x7f\x3e\x07\x09\xe4\xe7\x1f\xc8\x67\x0c\x45\xbf\x87\x5b\xf4\xcf\x0f\xc8\xe7\x5d\x53\xa1\x77\x73\xd0\x2b\xee\xbe\x74\xd7\x73\xff\xcb\xf8\xc2\xed\x46\x04\xcd\x85\xde\x98\x4b\x57\xf0\xf3\x7f\xd3\x4c\x32\xce\x1a\x11\x63\x0d\x7f\x40\x88\xff\x11\xd6\xf0\x2d\x6b\x0c\xc1\x30\xff\xa3\xab\x16\xb0\xf6\x3f\xb6\x6a\x38\xcb\x92\x1c\x4a\x71\x2c\x15\xac\x1a\xea\xf3\xa6\x6b\x86\xe6\xb3\xc6\xe1\x38\x41\x30\x38\x4a\xd0\x2c\xf5\x9d\x64\x18\x8a\x45\x99\xbf\x15\x8f\xd8\x86\x47\x0c\x45\x37\xfe\xe4\x7f\x8d\x47\xe2\x01\x61\x29\x96\xe3\x08\x96\x66\x39\x9f\xc5\x80\x43\xc7\x05\xb6\xeb\xe5\xc5\x22\xd0\x81\x29\xc1\x50\x57\x77\xca\x9a\x19\x03\xb9\x8f\x21\xd9\x06\x12\x8c\x60\x23\x27\x13\xb8\xda\x1b\xbc\x98\x23\xcf\x06\x03\x96\x96\x50\x53\xa7\x1e\x42\xec\x01\xf9\x1c\x04\x99\xc9\x0c\xae\x3f\x4c\x97\x7c\xaa\x48\x9c\x09\xcd\xe5\x57\xc9\x39\xc4\xf0\xcb\xe5\x1c\xe3\x28\x9b\x9c\x2f\xcc\xc1\xcf\xf2\x4b\x01\x55\x34\x1b\x9a\xec\x2f\x93\x73\x80\xe1\x97\xcb\x39\xc6\x51\x36\x39\x5f\xb8\x0d\x09\xa8\x3a\x91\xc2\x25\x35\xaa\x5f\x9a\xc2\x6d\x9a\xd5\x37\xcc\x52\x0f\xc8\x1d\x4d\x4b\xac\x48\x10\x14\x27\x03\x06\x2a\xb2\x4c\x63\x0a\xa5\xe0\x22\xc1\xa0\x34\xce\x61\x34\x4e\x91\x12\x4d\x62\x2c\x4d\x10\x92\x8c\x63\x38\x46\x12\x0c\x89\x4a\x8c\x24\xa3\x22\x44\x59\x8a\xf2\x72\x6a\x51\xc1\x38\x96\x96\x70\x51\x54\x64\x11\x97\x58\x9a\x21\x65\x82\x14\x39\x08\x31\x02\x65\x44\x45\x21\x25\x54\xc2\x80\x28\xa2\x14\x0e\x39\x85\x01\x0a\x40\x65\x86\x96\xa0\x44\xe0\x22\xa5\xb0\x77\xbe\xde\xa0\xb1\x82\x13\xfd\x83\x20\x7f\x10\x5c\xbc\x0e\x15\x7e\xfd\x9d\xc2\x08\x92\xa3\x4e\xde\xc5\x31\x92\x21\x59\x82\x26\x59\xf4\x01\xc1\x68\x6f\x3d\x0f\xae\x07\x84\xf3\xfe\xc3\xc2\xff\x36\x5f\x62\xdb\x3f\xbc\x3d\x05\xcf\xf3\x7c\x81\x61\x9f\xa7\x4e\x9d\xc9\x89\x8d\xda\x33\x8a\xa2\x0b\x48\xf6\xf3\x4c\x0e\x5d\x36\x2b\xb6\x53\x6e\xcc\x39\xfa\x5e\xc5\xf0\x77\xa7\x69\x3f\x91\xaf\xd6\x4a\xb0\x57\x2f\x98\x59\x66\xef\x07\xb5\x1a\x3d\x12\x66\xc5\x77\xfd\xa5\xdb\x85\x36\x31\x5c\x74\x67\xef\xbd\xc7\x67\xbe\xd3\x21\x99\x7e\xc7\x03\xcd\x3f\xb5\x87\xcd\xea\x92\xdf\x5e\x50\x6e\x94\x0d\xae\xa0\x3e\x0d\x19\x8e\x5f\x3c\x0b\x1c\x50\xcb\xc2\xca\x7e\x2e\x76\xd4\x21\x21\x2a\x7a\x85\x7f\x6d\x33\xf7\xab\x9a\xf2\x5c\xe8\x8f\xd6\xf9\xb9\xdc\x1b\x90\x15\x76\x3c\x77\x65\xb9\x5a\x5f\xea\x6f\x6d\x27\x2f\x8d\x47\x2b\xb9\x36\x5b\xf7\x1e\xd5\x17\x99\x5a\x2f\x9b\x65\xd5\x83\x3c\x10\xc8\x06\x78\x9f\xe3\x9d\x1d\x32\xbe\x55\xe2\xf7\xaf\xbc\xf7\xdf\x33\xff\x84\x91\x1d\x9e\x2f\xa2\x8f\xfc\xdf\xed\x0a\x94\x0a\x7b\xf0\x5b\x1b\x52\xac\x3f\x6e\x10\xe4\x6d\x94\xf9\x0e\xe0\x24\x87\xcb\x1c\xc7\x00\x09\x23\x08\x85\x43\x31\x02\x2a\x12\x4e\xb1\x8a\x48\x89\x12\x45\x88\x50\x41\x39\x56\x54\x38\x8e\x95\x25\x8a\x95\x44\x0a\x55\x24\x5a\x61\x59\x91\x51\x00\xeb\x1f\x68\x12\x81\xa7\x3b\xd4\x6d\x36\x55\xe5\x09\x94\x26\xd2\x0d\x62\x73\x37\xc8\x91\x69\x0e\x63\xc9\x23\x06\xc1\x66\x34\x08\xfa\xf1\xb1\xf1\xac\xd3\xcb\x7e\x9b\xe2\xfb\x0c\xfb\x38\xbe\xc7\xde\xca\xad\x7b\xf6\x51\xcb\x19\x63\xa2\xfc\xd2\x18\xb4\x57\x6f\x5a\x43\xa1\x55\x7e\xa0\x37\x16\x36\xa6\x3d\x55\xaa\xc6\x78\x40\xf5\x8c\x6e\x55\x56\xca\x1d\x6e\xdd\x2a\xbe\x72\x7a\xb9\xb9\x2e\xbf\x92\x28\xfd\xe8\x88\xcc\x53\x60\x05\xbe\x41\xa8\xbb\x05\xcd\xd9\xaf\xfd\x97\x5a\x63\xd4\x7f\x93\x4b\xf7\x38\x2a\xba\xef\x32\x00\x1c\x51\x6a\xbb\x83\x59\x99\x1c\xf5\x5a\x6c\xbd\xd6\xe5\xd7\x5c\xad\x56\x60\x1f\x71\x7c\xe8\x00\x82\x5b\xf4\x5c\x97\x20\x8b\x5c\xc7\x6a\xbe\xf4\xa9\x1c\xa9\x0e\xc4\x32\x70\x73\x35\x7d\x04\x04\x55\xd6\xa9\xaa\x6f\x03\x9d\x04\x83\x68\xaa\x31\x7d\xfa\x5f\x30\x08\xc2\xb7\x89\x33\x0c\x82\xb8\x8d\x32\xdf\x31\x14\x4a\xb3\x12\x90\x70\x05\x83\x34\x40\x45\x5c\x02\x0a\xc0\x65\x4a\x16\x45\x49\x92\x28\x09\xe3\x68\x06\x63\x14\x5a\x51\x14\x96\xe1\x38\x49\x22\x80\x48\x03\x9a\xa3\x44\x94\x11\x39\x0c\x04\x27\xfc\x78\xa2\x6e\x33\xa9\x2a\x4f\xe2\x34\x9e\x6e\x2e\xde\x5d\x2f\xba\x84\x3b\x2b\x8c\x65\xd9\x23\x06\x41\x65\x34\x08\x62\x50\x79\xa9\x2f\xdf\xaa\x86\xd5\x68\xd4\xef\x35\x4c\x5e\xb0\xef\xe5\xe5\xf3\xf3\x4a\xc1\x73\xb9\x29\x65\x36\x5b\x36\x30\x74\x31\xcf\xcc\x80\xf8\xfe\x86\x76\x2a\xed\x59\xe5\xa9\x27\xe1\x92\x9a\x2f\x14\xe7\x96\xa6\x95\x2a\x5d\x52\xc1\x0d\x1b\x9d\xe7\xb9\x0a\x60\xc6\xea\xfd\x93\x58\xf3\x17\xd0\x37\x88\x88\x8e\xf6\xba\x8d\xc1\xa0\xea\xe4\x73\xb9\xf7\xaa\xf3\x52\xe5\x2d\xec\x99\x1f\xe4\x67\x16\xbb\x22\x7b\xdd\x27\x61\x0d\x14\xf7\xf9\x75\x68\x96\xa9\x66\xf5\xc5\x7d\xb6\xf4\x47\x65\x05\x94\x16\x58\xe6\xfa\x04\x31\x18\x2c\xf5\xf7\xa6\xdc\x6a\xd5\x9f\x54\x28\x14\xf3\x58\x1f\xbe\x96\x8a\x9c\x35\xf6\xe1\x37\x13\x0c\xa2\x8a\x26\x29\xd5\xdf\xdc\x20\xf0\x73\x0d\x02\xbf\x8d\x32\xdf\xd1\x84\xcc\xb1\x0a\x45\xd0\x10\xd2\xac\x8c\x89\x38\x23\x52\x22\xcb\x29\x38\x01\x14\x8a\xc0\x30\x91\xa1\x68\x0e\xe0\xa4\x02\x14\x8c\x44\x09\x20\xa3\x22\x85\x8b\x34\x41\x78\x30\x20\xc7\x1d\x8b\x10\x74\xaa\xca\x53\x24\x43\xa6\x27\x54\x14\xc9\x78\x01\x22\xd8\xcf\x91\x14\x87\x1f\x31\x07\x22\xa3\x39\xe0\xed\xe7\x17\x4c\x58\x50\x16\x2a\x3e\x32\x23\xd2\x5c\xb7\xde\x06\xab\x0a\x31\x9c\x5b\xb3\xfb\xb7\x32\xdf\x72\x0b\x58\x1d\x6f\x32\x79\x86\x7e\xce\x35\xa9\x5a\xaf\xf0\xda\x25\xee\xe7\xef\xe5\x51\xbd\xd3\x7a\x2f\xa9\x9a\xaa\xbb\xe4\x63\x8f\x87\x45\x66\x6c\x5b\x4e\x09\x34\x72\x54\xad\x11\xe4\x2a\xbe\x39\xf8\x7f\xd5\xb6\xff\xf1\xbe\xc6\x3a\xbb\xcf\x4b\xbe\xdd\x99\x05\xcb\x8d\x0e\x3b\xec\xc2\x98\x37\x5b\xf7\xdd\xc7\x5c\xe1\xbd\x86\x0e\x9f\x1f\xe1\x3d\x05\xa7\xcb\xdc\x8c\xec\x93\xf2\x74\xd9\xee\x2c\x97\xa5\x21\xc3\x18\xe6\x33\xa0\xa7\xc3\x46\x63\x90\x2f\x55\xc1\x22\x07\x57\x8f\xf4\x4c\x68\xd6\xde\xdf\xdb\xc3\x37\xec\xa9\xc5\xc1\xe5\xbc\xba\x7a\x1a\xf2\xe5\xb6\x1f\x25\x6a\x09\xe6\x52\x72\x92\x54\xee\x6f\x6e\x2e\x67\xc7\x0f\xec\x36\xaa\xee\x77\xa7\x6e\xf6\x08\x18\xc7\xa0\xfe\xd1\x17\x86\xa0\xe8\x0f\xff\x5f\xaa\x4a\xd3\x2c\x43\xa5\xc7\x07\xef\xae\x17\x1f\x48\x9c\x23\x39\x9a\xc1\x39\xfa\x88\xc6\x27\xeb\x7b\x40\xd2\x9f\xbd\x34\xe9\x57\xfe\xa9\xae\x91\xeb\xdc\xba\x57\xcf\x33\x45\xb3\xc8\x55\x71\x74\xf5\x92\xbf\x77\x50\xd5\x75\x96\xb5\xe5\x3b\xf6\x24\xf7\x46\x63\x90\x7f\x04\xc1\xde\xa0\x94\xa0\xca\xc9\xd7\x46\x95\x79\x3e\x3f\xfb\x00\x46\x6e\x7a\x6d\x37\x9c\xa1\x2a\x9f\xd8\x83\x67\x78\x62\xf5\xd2\x2d\x79\x4a\x57\x6a\xc4\x7e\x82\x0d\x2c\x89\x52\x7e\xb9\x3e\xc5\xee\x4e\x80\xc1\x63\x60\xf0\xcb\xc0\xc4\xcf\x45\x88\xcb\xc0\x90\xf1\x93\xa3\xcb\xc0\x50\xb1\x7a\xff\x85\xd4\xd0\xf1\x63\x83\xcb\xc0\x30\x1b\x30\x2c\x46\x32\xc4\xc5\xd4\xb0\xb1\x4a\xff\x85\xd4\x70\xf1\x62\xfa\x65\x60\x30\x74\xbf\xbc\x4b\x5e\x08\x06\x8b\x55\x89\x2f\x04\x83\xef\x17\x41\x2f\xa5\x86\x88\x55\x87\x2f\x04\x13\x2b\x4d\x5e\x4a\x0d\x15\xab\x70\xde\xe6\x21\xf2\x9b\x9c\x3b\x1f\x6f\x77\x7f\x40\x3c\xda\xb3\x1d\x44\xa7\x3c\x4b\x7d\xb5\xd7\x8c\xb8\xb8\x3d\xff\xb6\xfd\x40\xfb\x25\x20\xcc\x2f\xe1\xba\xd6\x55\xd5\xda\x07\xe4\xb3\x62\x5b\xc6\x55\x95\xf5\x07\x24\x52\xb9\xc6\xff\x6a\xa7\x91\xbf\xa0\x6f\x27\x61\xa5\xf6\x7d\xff\xf6\x03\x7a\xb8\x52\x57\x48\x79\xbb\x52\x97\x4a\x63\x6f\xa5\xfe\x72\xe7\xc6\xbf\xa0\x2f\x29\x7d\xa5\xc2\x4e\x81\xed\x87\x5f\x64\x53\xff\xac\xd4\xb5\x2b\x15\xa6\x1e\xbb\x0f\xb8\xbf\x4c\xc1\x89\x99\xdf\xa2\xee\x31\x83\x7e\xa7\x22\x02\xda\x4a\x8e\xdc\x97\x5c\xf0\xdc\xbc\xc7\xfd\x7f\x3e\xcb\x9f\x7f\x20\xf8\x03\xf2\xd9\xfc\xfc\x03\xc1\xfe\xfb\x80\x7c\xde\xf4\x6f\x7f\xfe\xe1\x25\xd1\x9f\xc5\xc5\x5a\x33\xd5\x49\xa2\xb0\xf7\xee\x1d\x93\xb9\x03\x75\xfd\x70\x64\x78\x7e\x17\x07\xf4\x77\x5a\x9a\xbd\xc6\x8d\xed\x07\xd2\x5f\x1a\x3a\x5b\x83\x83\x6b\x2f\x1c\x17\xc2\x6b\xcd\xc4\x07\x63\xd9\xd7\x5a\xec\x5f\xc3\xa8\x6e\xdc\xfb\x99\xba\x72\x9b\x0c\x7a\xfb\x01\xfd\x93\x57\xee\x9a\xdc\xe3\x2f\xb1\x72\xbf\x3e\xc5\x88\x6e\x36\xb6\x7f\xb3\x91\x06\x05\x65\x61\xca\x21\x2f\x17\x76\xde\xfa\x72\x09\xfa\x5f\xaf\x5d\xdc\x0c\xdd\x12\x57\xb6\x08\x9f\x23\xb6\x70\x57\xb4\xfd\x9b\xfc\xa5\x62\xbb\x42\x99\xff\x62\x62\x0b\xb6\x6f\xdb\xbf\xd1\x5f\x2a\xb6\x2b\xbc\xf7\xaf\x17\xdb\x89\xbd\x60\xc2\x2f\x32\x65\xd9\x07\x9e\x86\x7a\xfa\x37\x66\x2e\xdd\x6f\xa6\x3e\x54\x9d\x58\xa7\xa3\xd3\x6b\x0a\x27\x01\xe1\x31\x40\x69\xf5\x9f\x93\x80\x88\xd8\xde\x2a\xad\xe6\x72\x12\x10\x19\xdf\xa4\x5d\x0a\x88\x8a\xed\x21\x2e\xa6\x88\x8e\x01\xba\x58\x46\x4c\x2c\x57\xbe\x98\x22\x36\x96\xd9\x5d\x4c\x11\x17\x4f\x34\x2e\x05\xb4\x57\xb9\x63\xd3\xab\x53\xa7\x01\x61\xfb\x80\x2e\x96\xd1\x5e\xf5\x8e\xbc\x86\x22\x22\x16\x9d\x2e\x06\x44\xee\xfb\xeb\xcb\x29\xa2\xf6\x01\xa5\xd7\xf0\xce\xfd\x8d\xa4\x5b\x54\xf1\x4e\xfd\x96\xc3\x39\x75\xbc\xd4\x5f\x44\xba\x81\x67\x8d\x3c\xf7\x06\x00\x46\xb3\x0a\x86\x63\x38\x29\x32\x12\xc6\xd1\x12\x0a\x64\x00\x21\x23\x31\x04\xa0\x49\x99\x60\x14\x6f\xf9\x59\x09\x48\x22\xc5\x01\x0e\x53\x14\x82\xe5\x68\x9c\x66\x49\x0a\x32\x92\x72\xf7\x80\x04\x6d\xbf\x97\x27\x9b\x91\x73\x70\x72\x73\xf2\x97\xde\x6b\x48\x13\x47\x1a\x11\xfd\x9b\x7b\x5e\x3d\x38\x30\xac\x50\xd6\xa3\x3b\x94\xcd\x71\x6b\x28\x3f\xbf\xba\x4f\xf3\x7e\x35\xef\x8a\xd2\x18\x35\x0a\x86\x22\xe5\x6b\xf5\x92\x3a\x32\xf5\xb7\x72\x6d\x0a\x78\xff\xc0\x8d\xdf\x1c\x6b\x17\x62\xe7\x59\xf9\xdd\x9f\xc1\xd9\x78\x0b\x2f\xe4\xf8\x16\x49\x8d\xf3\x45\xc2\xad\x0e\xcb\x2d\xac\x4b\xf0\x68\x13\xce\xda\xec\x63\x97\x36\x05\x8c\xe7\xe0\x48\x93\xd7\x35\x77\xe0\xcf\x1f\x0e\x85\xb0\x01\xb0\xb0\xb0\x08\xcb\x25\xa9\xd7\x42\xbb\xb4\x9a\x77\x72\x84\x55\x15\xee\xdf\x31\xa6\xbb\xd6\x1c\x4c\x57\x9a\xe5\xb1\xd1\x19\xa9\xf6\xa2\x77\xdf\x0f\x50\x13\xc2\x73\xf4\xb0\xb0\xbc\xa5\xb7\x53\x97\x2a\x3d\xae\xe5\x0c\xcd\x61\xb5\x30\xac\x55\x51\xb2\xc0\x3d\xd7\xdf\xdf\xeb\xe3\x7c\x57\x2e\x18\xeb\xfb\xc7\xa5\xf1\xae\xcb\x4c\x47\xe2\x1b\xad\xd5\xf3\x40\xe2\xd5\xd9\xa2\xa2\x58\x3d\xf9\xed\x69\x5e\x25\x58\x43\x78\xb3\x5f\x3b\x1a\x68\x3a\x3d\xc1\xe8\x3f\x8e\xc6\xdd\xf7\xea\x9b\x6a\xfd\xbc\x8b\x1e\xb8\x56\xfa\x39\xef\xf2\xff\xde\x91\x91\xf7\xbf\x0c\x3a\xb8\x76\xe3\x3b\x5b\xf9\x15\xfd\x41\x11\xb2\x45\x43\x35\xb0\x21\x2e\xab\xd4\x10\x33\x5e\x31\xa8\x37\xa5\x0a\xe6\xae\x5e\x7a\xe3\xfa\x33\xb7\x2c\xa9\x56\x2f\x0f\xe0\x88\x1d\x68\x65\xcb\x17\xd2\x90\x7f\x7b\x69\xed\xd6\x23\x1f\xc3\xbf\xb7\x16\x09\x57\xfe\xc6\xf8\x0b\x67\xe2\xe7\xb7\x32\xf1\x65\xd4\xdc\xca\x24\x24\x6f\x01\x0a\xe2\xf0\xe9\x19\x2f\xea\x4f\x23\x60\x0f\xe9\xc1\x6a\x29\x8e\x88\x8a\xf0\xa8\xce\x4d\x82\xef\x15\xa6\xb5\xf2\x9c\x12\x57\xbd\xda\xc8\x9f\xff\x38\x28\xdc\xb7\xa4\x1d\xbc\x12\xbf\xaf\x93\xe1\x95\x7a\xa6\xec\x8f\x2f\x5f\x87\xbf\x49\x5e\x86\xff\xa7\xaf\x1f\xff\x99\x2f\x9f\x1b\x28\xbd\x1a\xc9\x03\xe9\x71\xa0\x2a\x7d\xb5\x81\xcd\xec\x76\x73\xae\x96\xcb\x68\x5d\x6c\x90\x66\x41\x6c\x0d\x09\x37\xbf\xe4\x1d\xa6\xac\x77\x97\x85\x42\x8f\x7c\xbe\x9f\x3e\xe2\x1c\x9c\x29\xca\x7a\x8c\xdf\x2f\xe6\x85\x47\x6b\xbd\xaa\xe1\xcf\x4d\xfd\x79\x5a\x6d\xc2\xfb\x82\xfa\xf3\xa7\x9f\x4c\xfb\xbf\xbc\xb5\xe9\x62\xc8\xf2\xbf\xff\x9b\xa6\xbe\xd7\x39\x1d\x92\xf6\x1e\x17\x86\x04\x8e\xd1\x28\x49\xc9\x14\xc3\x89\x10\x90\xa8\x82\xcb\x04\x05\x50\x8e\x44\x69\x19\x12\x80\xe5\x48\x28\x89\x94\x08\x19\x54\x16\x65\x40\x41\x89\x93\x50\x12\x67\x00\x2a\x53\x00\x0b\x1e\xe0\xc4\xae\xa9\x8b\x45\xdc\x26\x71\xca\x6d\x12\x28\xc3\x61\x47\xfa\x55\x83\xbb\x7b\xc9\x67\xa0\xb4\x75\xfa\x05\x6a\xc4\x8b\x61\xd5\xd8\x7e\x45\x2f\xe6\xa0\x2a\x11\x4c\xfb\xc9\xad\xd6\xeb\xef\xa3\x21\xbb\x1c\x6a\xcf\x79\x50\x58\x50\x0d\xca\xd7\xec\x88\xe3\x8c\x2b\xc5\x81\xe3\x3c\xd3\x10\xaf\x70\x9c\x3c\x63\x38\x56\x84\x94\xca\x96\xde\x4e\xc9\xac\x17\xc5\xe2\xf8\xad\x3e\x7b\x7c\x19\xd7\x51\x60\xbf\x4d\xcb\xba\x79\x5f\xa9\xa3\xf7\x0c\xbf\xa6\x55\x14\xdc\x63\xd3\x97\x6e\x17\xea\x25\x1e\x92\x4b\xe3\x05\xbe\x0a\x52\x57\xc5\x0d\xb2\x60\x32\x2e\xc9\xbf\x3c\xbe\xf3\x4e\xb1\x53\x43\xb5\x27\x30\xad\x88\xd6\x63\xbb\x26\xf0\xcb\x98\xe3\xec\x24\x19\x46\x54\x3e\xe9\x8e\x33\x32\xc8\x7e\x15\xe8\x06\x6c\x01\xf5\x65\xd5\x04\x83\x36\x47\xe7\xdf\x15\x87\x83\xa8\x64\xd9\xc2\xf3\xd3\x7b\x7e\xf4\x38\x2b\x5b\x75\x66\xf6\x36\xf3\x9b\x7a\x3d\xc7\xa5\x61\xbb\xf5\x48\xb9\x4e\x38\xce\xdb\xe1\x3f\x74\x12\x19\xf0\x1f\x38\xcd\xa0\x0b\xe6\x4c\xa7\x55\x1e\x0e\xd0\x50\xf0\x67\xea\x73\x48\x4a\x6e\x7b\x2d\x93\x68\x2e\xed\xbe\xfc\x68\xfa\x8a\x0b\xb0\x56\x8f\xd1\xf7\xf3\x67\x42\x00\x8a\x24\x35\xe7\xda\x92\x17\x00\x42\x5a\xe3\x6d\xdb\xd1\xeb\x78\x00\x2a\x5d\x87\x3f\x1a\x00\xcf\xc1\x1f\x06\xa0\x9e\x64\x09\x8e\xa0\xb1\xaf\x1d\x43\x50\xed\xee\xeb\xe2\xbe\x34\x1a\x29\xe4\xd8\xee\x33\x4e\xb1\xf1\x5a\xec\xda\xcc\xa8\x22\x94\xcb\xf4\xa0\x93\x67\x5e\x0a\x40\xa0\x2d\x6c\x55\x29\x02\x51\xad\x2b\x0b\x42\x2d\x34\xcd\x66\x61\x29\xf0\x2f\xbd\x47\xf9\xb5\xf4\xbc\x50\x67\xac\x8a\x16\xf9\x4b\x03\x90\xb7\x1b\x38\x3f\xfe\x60\x12\x49\x91\x34\x81\xe2\x34\x03\x00\xcb\xd0\x0c\x94\x58\x89\x85\x04\x4a\x52\xa8\x04\x01\x2d\x02\x9a\x46\x31\x92\x82\x9c\xc4\xe1\x24\x10\x45\x86\x92\x19\x40\xd3\x34\x27\xd2\x12\xce\x82\x20\xfe\xe0\x37\x8a\x3f\x27\xd3\x76\x02\xe5\xd2\x9b\x61\xc3\x9b\x7b\x85\x86\x6b\xa3\xcf\x5f\x28\x6d\x3f\x12\x7d\x8a\xf3\xda\x8c\x7b\x25\x50\xf7\x5d\xe9\xcc\xe6\x9d\x45\x61\x59\x66\x34\xd0\x26\x44\x81\x2e\x76\x0b\xb3\xfb\xe5\x80\x18\xb2\x34\xe3\xbe\xce\x1a\x9d\x21\x51\x93\x49\x0a\x1f\x39\xf5\xc1\x78\xde\xee\xd8\x02\x0b\x5f\x68\x65\x86\x2e\x56\x10\x1a\x79\xc1\x79\xc7\x04\x6a\xd8\x74\x38\x75\xfc\x57\x8c\x3e\x17\x79\xff\x1b\xe2\x8f\xeb\x43\x26\xfc\xc9\xd1\x87\x67\xc6\x0d\x96\x67\x5e\x74\xb5\xd4\x86\xa8\x3c\x18\x30\xc3\xaa\x54\xec\xac\xe8\x4e\x6e\xa9\x57\x5f\x25\x62\x50\xc4\x28\xf0\x48\xd4\x34\xcc\x1f\xff\xd1\xd1\xe7\x03\xe9\xbb\x2c\xfa\xfc\x49\xde\x9f\xbf\x51\xf4\x89\x6e\x7f\xce\xc1\x1f\x46\x9f\xd6\x4c\xeb\xe3\xb6\xd2\x23\x04\xae\xd0\xd3\x0b\x64\x83\x7f\x5a\x3c\x5a\x39\xd9\x21\x2c\xa1\x54\xef\x33\xf9\xbe\xfc\xf4\x6e\x2f\xf0\xd7\x8e\x9b\x7f\x92\xa6\xc4\x8b\xf9\x0c\x96\xf3\xae\x36\xe3\x0a\x0e\xb1\xa2\xdb\xf3\xfb\x7e\x8f\x29\x53\xf4\xb8\x84\xbf\xb7\x07\x84\x3e\x58\xbf\xe3\xf9\x8b\xb7\x3f\x97\x45\x1f\x0e\x8a\x10\xca\x50\x94\x28\x5c\x06\x04\xc6\xca\xb4\x28\x13\x14\x49\x93\x24\xc1\x11\x1c\x83\xca\x32\x43\xa1\xb4\x28\xb2\xa2\x02\x58\x5a\xa1\x09\x89\xe5\x24\x8a\x66\x58\x09\x65\x24\xca\x7f\x2e\x82\x0c\x9a\x25\x6e\x11\x7d\xa8\x93\xd1\x07\xc3\x98\x23\xcf\xf2\x85\x77\xf7\xea\xd3\xd7\xc6\x9f\x62\x6c\xf1\x23\xae\x2c\x62\xda\xc3\x61\xbf\x1b\xfe\x79\xa6\x7f\x8b\x04\x15\x5f\x9d\x93\xfd\x1b\xd8\x8c\xcf\xf3\x6f\xce\x82\x52\xee\xdf\x98\xa1\xfd\x58\xac\xd6\x17\x38\x3b\x5a\x96\xf0\xf7\x65\xb1\x43\xe9\xcd\x91\x59\x60\xca\x96\xda\xd3\xfb\x39\xe1\x65\xa5\x56\x57\x45\x66\x36\x7b\xae\x36\x47\xb8\x3e\x7b\x19\xaf\x72\x5c\x8f\xa4\x9c\xda\x63\xa5\xd0\x22\xdf\x5e\xe8\x7b\xb5\xf6\xb6\xaa\xda\x4b\x5a\xcf\x47\xed\x9b\x4f\x8d\x35\x71\x59\xf0\x97\xc8\x36\xc2\xeb\x2f\x97\xdd\x07\xc4\xc3\x8b\xe2\xd1\x0d\xf1\x27\xaf\xc9\xa9\x78\xe8\x83\xba\x85\x0f\x6f\xf8\x49\x55\x24\x26\x1c\x5e\xbf\xd4\x87\x1f\xe0\x3f\x55\xc2\x3a\xb8\x1f\x4b\xea\xe2\x13\x83\xf5\xfd\x3b\xe8\xf8\xcd\xe2\xf2\xa5\x71\x91\xff\x05\x6b\x7a\x0e\xfe\x30\x2e\xff\x2a\x07\xf9\x91\x71\x99\xc2\x30\x80\x29\x38\x05\x31\x85\x82\x00\x97\x25\x54\x44\x31\x0e\x27\x30\x05\x32\x1c\xce\x10\x8a\x24\xe1\x0c\xc9\xe0\x12\x4e\xd0\x12\xc5\xb1\xa8\x22\x71\xb2\x24\xcb\xb4\xcc\x61\x14\xc4\xc3\x87\xe1\xb1\x6b\x7a\xbe\xce\xa9\x4a\x92\x38\x4b\xe2\x47\x1e\x1a\x0e\xee\xee\x1d\xf7\x06\x3a\x5b\x74\xd5\xb7\x65\x71\xd1\x1a\xf1\x1d\x8e\xe9\x62\xdd\xbe\x3b\x90\x97\x42\xb1\x3a\x2f\xe6\x0a\x03\x38\x7f\x97\x3b\xed\x27\xdd\x32\x25\xad\x31\xe4\x33\x57\x25\xc7\xfc\xc5\xfb\xbc\xea\x2e\x05\x8e\xe8\xf4\x16\x7f\xa7\x5a\xc2\xe6\xf7\x94\x9b\x6f\xbf\xb2\xf3\x81\x55\xe1\x9f\x5e\x5b\x5c\x8f\x01\x4b\xaa\xc5\x89\x26\xcb\x74\xd7\xed\x25\xfa\x84\xc9\x75\x54\x66\xa6\xbd\x2e\xcd\x2c\x2a\xb9\xd9\x94\x5f\x17\x08\x8b\xeb\xdb\xed\x3e\xfd\xce\xc9\xcf\xb3\xa9\xf1\x94\x13\xf8\x19\x6b\xae\x0c\x6e\xaa\x8f\x3b\xa5\x2c\xb1\xb7\x12\x55\xf4\xb4\xb8\xc6\x47\x7e\x0b\xe3\xcc\x7d\xb1\x7f\x3c\x62\xee\xe4\x9b\x72\x65\x89\x2b\x37\xc1\x7f\x59\x95\x71\x17\xd7\xa2\x71\xf1\xcc\x7d\x54\xe2\xd1\xcc\xe1\x75\xdc\x07\xde\x1a\xff\x19\x47\x43\x3c\xff\xd7\xdd\xe7\x9e\xaa\x62\x5e\x22\xab\xab\xab\x98\x37\x5c\xab\x73\xf0\x87\xf1\x4a\xea\x8f\x4c\xc6\x40\x4b\xf7\xf6\x5a\xef\xa9\xe3\x3c\xb4\x18\xac\xe1\xda\xc5\x19\x83\x2d\x94\x77\xb7\x5a\xcb\x15\xbb\xca\x10\xb5\xbb\xc4\xa2\xfc\x58\xb5\x17\xa4\x78\xdf\x2b\x15\x6b\x0d\xf8\x82\xb5\x1c\xae\x6d\xb7\x31\xcc\xe8\x55\x9e\x15\x16\x2d\xf4\xd7\x4a\x45\xc4\x2b\xc3\x29\xdf\xf9\xd8\x78\x05\x70\x19\x88\x0a\x09\x39\x19\xa3\x49\x9c\xc1\x71\x1a\xc5\x71\x06\x87\x18\xc3\x02\x82\x91\x38\x86\x90\x38\x8c\x61\x44\x8e\x62\x64\xc0\xd2\x18\x87\x03\x8e\x13\x09\xc8\x29\x04\xe0\x00\x20\x83\x78\x85\xdf\xa8\xf9\xe0\x74\xbc\x22\x30\x34\xfd\x14\x6d\x73\x77\xaf\xab\xe8\xda\xf6\x83\x0f\x8c\x57\x91\x76\x82\xaa\xd6\x98\x97\x84\x11\x43\xbc\x48\x7d\xac\x27\xcf\x94\x1c\x04\xab\x97\x5e\xa3\xd2\xef\x14\xd4\x9a\x09\x51\x97\x20\x41\x0d\xae\xe5\xe9\x5c\x1f\xba\x23\x6e\x55\xec\xd0\x53\xbe\x4f\xb0\x15\x6e\xa6\xd9\xf5\x7a\xb7\xb6\xb6\xea\x8b\x99\x35\x10\x84\x29\xbf\x94\x47\xeb\x5c\xfb\xa5\x23\xfd\x92\x78\x75\xc9\x71\xfe\x2d\xe3\xd5\x95\xf8\x6f\x18\xaf\x6e\xd2\x4a\x70\x78\x65\xf6\x81\x1f\xdd\xca\xc0\xf3\x7f\xdd\x53\xc1\x53\xf1\xea\x12\x59\xdd\x32\x5e\x5d\xbb\x56\xe7\xe0\x0f\xe3\x15\xac\x2d\x66\x1d\x4c\x7c\x83\xc2\xaa\x3d\x7c\xc4\xbb\x39\x8e\xb2\x2b\x42\xcd\x79\x16\xf8\x3a\xaf\xc9\x4c\x8f\x50\xa6\xd6\x94\x79\xc4\x2b\xc6\x70\x84\x89\x44\x49\x28\xbe\x96\xf2\x6d\x65\x29\xe2\xbd\xba\x63\xcd\x4b\x2f\x75\xf5\x95\xee\x4d\x3b\x28\x5e\x2a\xe6\x31\xb1\xc1\xde\x0b\xf9\xe5\xc7\xc6\x2b\x11\x07\x38\xce\x48\x04\x27\xd1\x24\x20\x49\x45\x62\x80\x28\x93\x12\x47\xb3\x18\x47\x52\xb4\x82\x12\x1c\xc7\xa1\xb4\x8c\xe1\x12\xc9\xd0\x32\x83\x8a\x24\x8a\xfb\x3f\x6e\xc6\xd1\x32\x0d\x88\xe0\x67\x70\xb0\x6b\x9a\xbe\x83\x07\x02\x8f\x86\x29\x8a\xe4\xd0\xf4\x26\xb9\xcd\xdd\x68\xa7\x69\x18\xa5\x1a\x6c\xb5\xf3\xd6\x99\x89\x75\xbc\xca\x13\xa3\xe1\x4b\xd7\xae\x1b\x2f\x4f\x28\xaa\x54\x58\xa7\x51\xf3\x92\x8d\xee\xf2\x71\x94\xe3\x9f\x08\x7e\x1b\xa5\x02\x75\x8a\x2d\xf9\x81\x15\x5f\x50\xad\x8a\xfe\xd2\x45\x7e\xf8\xb6\x2c\x73\xde\xad\x52\xd1\x25\xea\x4b\x03\xb4\x17\x6d\xb9\xdc\x1b\xac\x64\xbe\x0c\x45\xba\xd5\x81\xee\xba\x53\xaf\x8d\xc0\xbb\x2e\xf6\x9a\xcd\xa9\x51\xad\x0b\x8d\x22\xe9\xbc\x4e\x4b\xaf\x83\x67\xa9\xd3\x46\xf5\xfb\xa7\x5c\x6b\x7e\x6f\x39\x23\x43\xa0\xef\xcb\x83\xb1\xe8\xbc\x33\x54\x07\x7f\xa9\x90\x6f\xcd\x66\x86\xc8\xb4\xa7\xd2\xfb\x91\x29\xc2\xf3\xce\x33\x47\xad\x5d\xcb\xe5\xd1\x06\xfa\x58\x59\xbb\xd3\xa5\x80\xe9\x63\x14\xac\xe7\x16\xc6\x09\xd5\xd5\x5b\xa3\xb0\x6e\x51\x6e\xbe\x24\x15\x02\x1e\x09\xd5\xb5\x5b\xe6\x38\xc7\x0c\x76\xf3\x2f\xaa\x90\x5d\x81\xbf\xdc\x1f\xe5\xed\x2b\xf0\xf3\xfc\x9f\xd7\x63\x90\xe8\x79\xf3\x97\xcb\xa2\x65\x3e\x1f\x65\xf3\x94\x2c\xae\x5d\x0b\x4f\x17\xee\xa5\x18\xbc\xb3\x64\xf1\x1f\x46\x5e\x3b\x8f\xc6\x0b\xf3\x42\x74\x07\x7a\xf3\xa9\x93\x7f\x32\xee\x5f\x66\x55\x5b\x9a\x15\xb4\xb2\xe1\x50\x23\xf4\xa5\x58\x7b\x9e\xae\x5f\x7a\xcb\xfb\x46\xdd\xea\xd6\xf5\xca\x53\xa9\xc8\x3d\x2a\x7a\xee\xfd\x55\x79\x6d\x94\xe7\x2f\xf0\x6d\x3a\xac\x54\x98\xe6\xfd\xfd\x40\xb0\x56\x8b\xc6\xfb\x47\xf7\x3b\x90\x32\x41\x42\x92\x44\x31\x8a\x22\x14\x9a\x04\x34\x27\x01\x9a\x60\x71\x92\xe2\x58\x85\x94\x39\x05\x05\x38\x27\xa2\x0a\x24\x24\x48\xb0\x12\x09\x49\x99\x41\x49\x54\x06\x8a\x82\xe1\x8a\xa2\xec\x7e\xd5\xee\x0a\xcf\x8b\x9f\xf4\xbc\x14\x76\xe4\x47\x23\x37\x77\xa3\x1d\xf5\xd7\x7a\xde\x23\x7d\x0e\xc1\x75\x41\x7e\x9a\xe2\x79\x0b\x72\xd1\xad\xe0\x2b\x43\xed\xe4\x9a\xbc\xfb\xfa\xaa\x28\x6a\xbe\x79\x3f\x50\x9e\x87\xd5\x77\xce\x2a\xae\xdc\xf7\xb2\x20\x53\xec\x2c\x67\xe0\xa2\xde\xae\x98\x35\x51\x5c\x40\x60\xb8\xf3\xce\x5b\x81\x23\xed\xee\x14\x2c\x73\x55\x27\x5f\x52\x00\xe0\x5e\x5f\x9e\x97\xcc\x78\x3e\x9c\x55\xfe\x5a\x9e\xf7\x5a\xcf\x77\xa5\xb5\xbf\x32\xb9\x7e\x51\xbc\xa1\xe7\xfd\xc8\x3c\xf3\x64\xce\xfb\x81\x9e\x8f\xbf\x91\xe7\x65\xc9\xdd\xfc\x94\xfd\xe2\x31\xcf\x6b\x76\x98\xae\xeb\x3c\x5b\xa5\xf6\x3b\xdf\x00\xaf\x26\x41\xf2\xfd\xb6\x5e\xc5\x87\x5d\x36\x07\x78\x56\x94\x56\xfd\x27\xa8\x3c\xb6\x29\xd7\xa0\xfa\xab\xf9\xba\x82\x33\xa6\x31\xb7\xc1\xa0\xb1\x7c\x83\x75\x74\x3c\x72\xda\x2b\x86\xef\x56\x71\xe3\x0d\x58\xb8\xd4\xc2\xeb\xc3\xe7\x8f\x3e\xeb\x67\x70\x8a\xa1\x68\x11\x53\x44\x59\x61\x09\x11\x65\x31\x9c\x51\x08\x96\x82\x0a\x94\x15\x94\x43\x39\x49\x62\x71\x54\xa4\x25\x09\x32\x98\x82\x49\x28\xcb\x31\x32\x46\x91\x38\x23\x89\x14\x90\xe5\xbb\xed\x4f\x89\x5f\xe1\x79\x4f\x96\x66\x28\x0a\x4f\xff\xf1\xb9\xf0\x66\xf4\xb9\xa1\x6b\xfd\xee\x91\xf3\xfd\xe0\xba\xa0\x8e\x9d\xe2\x77\xf3\x2f\xa4\x9a\xef\xe4\xf2\xbc\xa8\xbe\x2a\xcc\x6b\xcb\x72\x81\xab\x3e\x0f\xaa\x2f\x45\xdd\x69\xb9\x45\x41\x9e\x33\x40\x7f\xee\x52\xb9\xf2\x8c\x53\x2a\x2f\xf7\xfa\xaa\xb4\x56\xf9\xe7\xd1\xfb\x98\xc9\x35\xc6\xd8\x33\xd1\x2b\xd3\x12\xfa\xea\x60\x0c\xde\x98\xf2\xb3\xd9\xdb\x90\x9d\xa3\x7f\xad\x8c\xf7\x6a\xbf\x77\xad\xdf\x5d\xdb\x9d\x72\xe3\x86\x7e\xf7\x23\xeb\xd1\xbf\xc2\xef\x5e\xea\xf7\xf8\x1b\xf9\xdd\x4b\x77\x3f\xa1\xdf\x1d\xdf\xd7\xf8\x41\x7b\xd9\xa9\x90\x75\xf3\x9e\x7e\x79\x6d\x8c\xec\x71\x65\x98\x27\x97\x94\x58\xb4\x3b\xef\x4f\x00\xe2\xf3\xd1\x00\x2a\xab\xe7\xf6\xd3\xca\xca\xcd\xa5\x6e\xd3\xe2\x2b\x43\x07\x6f\xe5\xd6\xb8\x30\x92\xd1\x29\x34\x85\xba\x2d\x40\x4e\x23\x3b\x8f\x8f\x0d\x4c\xa9\xcb\xb7\xc9\x78\xf7\x9f\x55\x8c\xbe\x6f\x39\xfa\x62\xd0\xf9\x0c\xae\x37\xcf\xfc\x15\x5a\x42\xaf\xdf\xe5\x6b\xc2\xd9\xef\xa9\x8e\x40\xf4\xdf\x6b\xce\x17\x8b\x11\x68\x07\x08\x91\x76\xb7\xd6\xe4\xbb\x63\xa4\x5e\x1a\x23\x5f\x34\xf9\x80\xda\xf8\xbb\xf3\x62\x9f\x6f\x44\x75\x0c\x6a\x12\xe5\x49\x88\x4f\x52\x1f\x7b\x87\x59\xec\x85\x5f\xbb\x9f\xeb\x88\xfc\x2a\xce\xde\x2f\xe0\x4c\x6e\xc2\xdd\x3e\xda\x24\xe6\x2e\x22\x0c\x19\x08\xb5\xce\xa0\x84\x7c\xd9\x0d\x7f\x40\x76\xe3\x37\x7f\x07\x13\xce\x14\xcd\x6d\x96\xf5\x6c\xc6\xcf\x5a\xd4\x94\x5f\xfe\x3b\xf1\xeb\x7a\xb7\xe5\x2c\x19\xc9\x31\x4e\x8f\x90\x95\x99\xf3\xd4\x27\xa6\x4f\x3e\x93\x7c\x5b\xee\xd3\xd0\x1c\xe3\xff\x28\x69\x27\x25\x10\xa8\xb4\xb8\xf6\xb5\x7d\xc3\x48\x4d\x28\x96\x9e\x4e\xf0\x50\xe8\x96\xf8\x7e\x29\x18\xba\x0f\x05\x69\x09\x71\x63\x18\xf4\x6a\x42\x05\x11\x5d\x1b\xc2\xa8\x75\xa5\x53\x13\xd8\xd8\xf5\xf4\x04\x70\xb2\x51\x94\x62\xd7\xe2\xf6\xbd\x91\x17\x93\xb3\x03\x11\xa5\x64\x6f\xa7\xb0\x4f\x4f\x30\xf8\x01\xd9\xbc\x08\x76\xf3\x62\xfb\x24\xe2\x14\x08\xcf\x23\x70\x6e\x39\xae\x6a\x43\x27\x91\xce\x08\xb4\x6c\xb4\x46\x26\x7c\x45\x46\xd5\x52\xb7\x84\x44\x61\xd4\x7a\x88\xd0\xea\xfb\x31\xfc\xb7\x03\xd2\xa7\xc0\x99\xde\x80\x66\x0f\x4c\x36\x62\xa3\xb6\xe2\xcd\x4a\x92\xa7\x66\x9a\xd0\xbe\x15\x69\x3b\x60\xd9\x08\x0c\xc6\x1f\x90\x19\x0a\x36\xf9\xee\x71\x19\x07\xbf\x70\x7e\x8d\xea\x06\x10\xb2\xd1\x1f\xbe\x69\x7c\xa3\xaf\x0f\x08\x98\xcf\x75\x4d\x0a\xfc\xb3\x65\xcb\x29\x71\x73\x02\x3d\x63\xf5\xef\x5f\x40\x69\x18\xb6\x03\x82\x63\xe0\xa2\x64\x6f\xde\x9d\xb5\x47\xf1\x61\x18\xd1\xe4\x07\xe4\xb3\x3f\xf9\x73\x1a\xb1\x9a\x7c\x23\x32\x35\x39\x33\x81\xdb\x37\xea\xcb\x0f\x09\xb1\xef\x24\xd1\xd6\x7c\x32\xbf\x15\xdd\x21\xac\x28\xe9\x29\xb9\xc3\x45\x9c\x24\x33\xe0\xae\x6e\xc7\x40\x08\x2b\x45\xa7\x2f\x64\x21\x0a\x21\x89\x09\x6b\xee\x69\xe5\xd4\xba\x88\x87\x90\xf8\x1d\x8c\x4b\x85\x7f\x5c\xd0\x4e\x68\xed\x7e\xec\xbc\x5e\xd6\xfb\xe0\xa2\x24\x6f\x5e\xbc\xb0\xef\xfd\x12\x29\x8a\xca\xf5\x56\x64\x1d\xc0\xcc\xe8\x9e\x13\x08\x74\x83\x25\x71\xaf\x59\xd6\x1d\x8c\xcb\x55\xf2\x94\xfa\xb9\xb6\xec\x21\x11\x81\x73\x66\xbe\x90\x48\xf0\x21\xb0\x18\xe5\x32\x8c\xd1\x19\x1d\x7b\x92\x40\xff\x07\x5b\x6f\x43\x9e\x0f\x2a\x13\x71\x9b\x5f\x89\x4d\x25\xcd\xa7\x1d\xda\x37\x13\x5f\x0c\xde\x29\x22\x63\xc3\xb3\x50\x7a\x1b\x39\xee\x41\xcb\x4a\xe5\x49\x69\xde\x86\xb6\x4c\x34\x1d\xa7\x65\x43\xb1\x6e\x59\xb3\xc5\xfc\x3a\x8a\xf6\x61\x65\x5e\xd1\x60\x03\x92\x42\xdf\x1c\x68\xf6\xc4\xd5\x0c\x78\x13\x0a\xe3\xd0\xb2\xd9\x6d\x48\xe0\x03\x12\x27\xf9\x01\x09\x5d\xbc\xa4\x5b\x0e\x94\x27\xc0\x4d\x61\xe2\x06\x7e\x3b\x84\x73\x8a\xe2\x33\xb3\x23\x0f\xea\xcd\xa4\x7b\x86\x60\x4f\xca\x4d\x33\x65\xb8\x9a\xc4\x52\x0e\x67\x62\x99\x13\x20\xcb\x36\x74\x9c\x6b\x05\x7a\x12\xc1\xde\xc6\x39\xbc\x1d\xdb\xaa\x06\x03\xcf\xa0\xfd\x7a\x3d\x38\x06\xfb\x34\xc5\x09\x56\xb6\x0f\x30\xcc\xc2\x3d\x78\xee\x7a\x7e\x79\x51\xe4\x28\xd4\x93\x69\xbf\x37\xe8\x04\xa1\x61\x0e\xe5\x81\xdc\x2a\xd1\x8d\xa8\x4d\x02\x7d\x32\x7d\xcb\xaa\xc9\x11\xe0\xb7\x56\x86\x3d\xd0\x97\xe4\x9b\xe9\xe0\x8c\xb9\x65\x7b\x8e\xef\x0d\xda\x8e\x66\x99\xb7\x17\x74\x1c\xc3\x69\xf2\x63\x13\xb2\x33\x13\xba\x9e\xec\x45\x8e\x0b\xe4\x1f\xc1\x71\x92\x93\xc8\xd8\xec\x4c\xcc\x6d\xf8\xa6\x59\x0b\xe7\x43\xb8\x49\x42\x76\x92\xad\xa4\x49\xd9\xf9\xdb\x14\x51\x7e\x19\x4f\x1b\x04\x27\xf9\x48\x2d\x3f\xee\x83\xde\xfd\xd4\xf4\xaf\x30\xed\x38\xf4\xc4\x0d\xf0\xb9\x06\xbe\x0f\x74\x7f\x0b\x75\x23\x0b\x3f\x86\x22\x0b\x0f\x27\xf6\x75\x47\x91\xdd\x2e\x7c\x1d\x02\xce\x44\xfb\xe9\x20\x16\xdd\x6c\xff\x0a\xb5\x39\x84\x7f\xf1\x56\xdf\x4f\xe2\xb6\x81\x7c\x53\x61\x9c\x88\x96\x35\xbb\x58\xca\x47\x60\x9e\x4c\x11\xbe\x7c\x91\xa1\x0b\x34\xdd\x41\xbe\xfd\xfb\xdf\xc8\x9d\x63\xe9\x72\xe4\x78\xf3\xee\xc7\x0f\x17\xae\xdc\xaf\x5f\x1f\x90\xf4\x81\x92\x25\x67\x1b\x18\x1c\x8e\xa4\x0f\x15\xad\x85\x3a\x75\x33\xa1\xdf\x1b\x7a\x9c\x80\xbd\xa1\x31\x12\x36\x45\x71\x5f\xc9\x90\x9f\x08\x41\x64\xee\x0c\xd0\xe4\x89\x12\x39\xb7\x2b\xd7\x3f\xa6\x3f\x20\x44\x8b\x94\x5b\xdd\x52\xad\x22\x6c\xcf\xe4\x90\x6e\xa9\x5c\xea\x96\x84\x42\xa9\x17\x3b\xa6\xf2\xef\xb6\x04\x64\xd0\x2e\x7a\x2a\xd3\x2d\xf5\xfa\xdd\x5a\xa1\xef\x7d\x55\x2c\x35\x4a\xfd\x12\x52\xe0\x7b\x05\xbe\x58\x3a\x72\xb0\xe9\xed\x3b\xf6\x3f\x4e\x62\xa5\x98\xdb\x09\x63\x1f\xcf\x89\x53\xcb\x34\x4a\xf6\xe5\x13\x2f\x1b\x25\x0a\x2b\x4c\xf4\x4f\x1c\xf1\xa6\x4a\x22\xdc\xca\xfe\xe9\x72\x88\xd2\x91\x24\x85\x4d\x95\xe0\xb8\xc2\x9c\x27\x81\xc3\xa2\xd2\x9f\x28\x86\x14\x62\xf6\x65\x91\x50\x06\xbb\xad\x52\xc4\x4b\x1c\x7f\x05\x81\xa4\xab\xc6\x41\x0d\x29\x8b\x76\x20\x40\x96\xa1\x8c\x18\xc0\x5c\x00\x5d\x5f\xef\x51\x5a\x2b\x23\xa5\xa7\x5a\xaf\xdf\x0b\x68\x0e\x38\xfb\x3e\x83\xeb\xc9\x1b\xd0\x17\x70\xe2\x41\x84\x48\xb1\xdb\x6a\x47\x09\xdf\xcd\x8a\x8d\x0c\x5a\x24\x3e\xf9\xe3\xe3\x08\x92\x61\xff\xb6\x09\x91\xc1\xf0\x38\xe6\x2f\xbe\xdc\x8e\x5e\x9e\x90\xa4\x29\xb0\x81\xe4\x42\x1b\x79\x03\xf6\x5a\x33\xd5\x2f\x38\x45\x7d\xdd\x9e\x94\x3e\x9c\x86\xe2\x23\x3d\x05\xe7\x53\xac\x0f\x38\x4e\xed\xb6\x05\x18\xae\xe6\x13\xcd\x54\xa1\xe3\x4e\x74\xe0\xfd\xe7\x67\xda\x77\x0f\xc8\x1d\x7a\xf7\xf5\xb7\x43\x5d\x89\x01\x4a\x52\x96\x24\x49\xef\x77\x7c\xcc\xe0\xda\x5b\xf1\x3d\x79\x6e\x0b\x26\x8e\xa6\x9a\x5e\xae\x9f\x41\xa0\x9b\x49\x09\xd2\xa0\xc9\xaf\x19\x64\x89\x04\xc8\x10\x2f\x76\x67\x19\xbe\x84\x9a\x3a\x75\x11\xcd\x74\xa1\x0a\xed\xd8\xaa\x7d\xfb\x86\x2c\x21\xb2\xd4\x74\x1d\x79\x5d\x40\x7b\x8d\x88\xeb\x0d\x7c\xc7\x42\xdc\x29\x70\x11\xcd\x41\x96\xd3\xed\xb7\x9a\x83\xb8\x53\x88\x28\x9a\xed\xb8\x88\xe6\x42\x03\xd1\x4c\xff\x1b\xc9\x32\xe6\x96\xa3\xb9\xd0\x93\x65\x06\xb2\xf6\x84\x1b\x00\xdf\x76\x69\x7c\xfd\x14\x5b\xc6\xc4\x24\xd3\x5b\xc2\x8d\xe7\x32\x16\x2b\x28\x7b\x82\xf4\xa4\xfa\x85\xe6\xbe\x86\xbd\x8e\xde\x98\x48\x13\x45\xca\xb8\x64\x64\x91\x54\xdc\x03\xe3\x58\x0b\x5b\xba\x0c\xd2\x26\xe7\xf4\x29\x0e\xca\x7c\xa9\xf3\x3d\x97\xb2\xed\x25\x44\x70\xf2\x53\x8a\xce\x1d\xd5\xb5\x9d\x43\x4f\x50\x33\x8a\xce\x66\xbb\xe1\x5b\x82\x10\x51\x53\x35\xd3\xcd\x36\x25\x78\x53\x9f\xae\x01\x51\xd3\x35\x57\x83\xce\x39\xb3\x37\xef\x01\xbc\x78\x7a\xb0\xb7\x9e\x98\x0b\x43\x84\xf6\x39\x53\xcd\x85\x31\x71\x16\x22\x34\x5d\xdb\x43\x9a\x6c\x2b\xc9\x97\x66\x2a\x7a\x50\x1a\x97\xa1\xe3\x6a\x66\xb0\x6e\x97\x4b\x5d\xd1\x81\x7a\x1e\x05\x53\xcb\x80\x13\xd9\x32\x80\x96\x84\x97\xc0\xb3\xe1\x35\x80\xe3\xc5\xbe\xd0\x5b\x38\x06\xf0\xd6\x22\x9b\xf4\xdc\xa9\x0d\x9d\xa9\xb7\xc3\xd1\xad\xe5\xa5\x53\x0d\x28\x6b\x0b\xe3\xd2\xd9\x53\x4d\x9d\x9e\x37\xd7\x8f\x1c\x86\x25\x6b\x8a\x06\xe5\x4d\x67\x4e\x5c\xec\x9f\xd2\x5d\xbe\x0c\x5c\x10\xda\xe0\xb7\x6f\x9b\x93\x1b\x2f\x6a\x68\x0e\x02\x90\x86\xff\xb9\x0e\xd7\x88\x01\x6c\x67\x0a\x74\x28\x23\x0b\x47\x33\x55\xa4\x19\x7c\xce\x6b\x26\xb0\xd7\x9b\xe9\xc0\x94\x11\x2f\x31\xa5\xc9\x6f\xd0\xf4\x36\x72\xde\x68\x28\x23\xae\x85\x88\x96\xe5\xb8\xc8\x1c\xda\x8a\x65\xf8\xe6\x68\x29\x88\x63\x19\xd0\xf7\xd7\x1a\x74\xbe\x9f\xf2\xb5\x11\xd2\x0e\xb5\x03\xa3\xd0\x33\x02\xf9\x4d\xdc\x8a\x7f\x99\xc0\x48\xca\x07\x68\xf2\x0c\x18\x69\x49\x05\x17\x65\xc9\x93\x6e\x4c\xb2\x34\x89\x88\x6b\x37\x4c\x1a\x8f\x09\x2e\x49\x43\xbc\x64\x21\x33\x85\x7b\x31\x6e\xb7\x0e\x7e\x78\xdb\xf7\xf3\x04\x1b\xfb\x82\x22\xf7\x93\xde\xad\xdb\xf7\x43\xd1\xc6\xd3\xed\xab\xed\x6f\x19\x66\xb8\x9a\xb1\xf1\xe8\x01\x0d\x05\xbe\xfd\x8d\x44\x83\xf0\x2e\x23\x73\xb0\xd6\x2d\x20\x23\x8e\x6b\xcf\xe0\xda\x41\x24\x60\x22\x22\x44\x30\x9a\xda\x09\xda\x41\x74\xcb\x54\x1f\x10\x07\x42\x0f\x40\x30\x34\xe7\xb9\x9f\xef\xaa\xf5\xc3\x00\xab\x52\x20\xe8\x9e\xf6\x0e\xbf\x23\xf9\x85\x8b\x2c\xe1\x9d\xae\x7b\x1a\xed\x27\x2d\xc8\x14\xda\xf0\xc1\xcb\x2f\x96\x10\x91\x2d\xf3\xce\x45\x4c\xe8\x2b\x7b\x90\x4e\xbf\x2c\xfc\xd4\x02\xf9\x3f\xf8\x06\x6d\x04\xa8\x40\x33\xff\xef\x7b\x22\x6b\x9b\xbc\x2b\xc8\xe8\xfc\x01\x85\x56\x63\xd0\x14\x36\xd9\x4a\x7f\xdc\x2e\xf9\x38\xe3\xf2\xa6\xa8\x64\xbb\x9e\x28\x9a\xee\xb9\x41\x7b\xa1\xc3\x6c\xe9\x9c\x77\x41\x13\x88\x9e\x85\x8b\x96\xa5\x6f\xb5\x03\x91\xa1\x02\x16\xba\x1b\xbe\xd2\x23\x23\xa8\xe5\x54\x73\xa1\xae\x39\xee\x26\x35\xf8\xfd\x8f\x73\x12\x6d\xff\xda\x53\xdc\x78\x18\x4c\x70\x69\xfe\x76\xe7\x02\xc6\x6f\xc6\xf6\xf5\x4c\x9f\x66\x79\x7f\xf9\x99\x7d\x11\x24\x96\x38\x03\x89\x40\x79\xe2\x1a\x73\x84\xef\x21\x9f\xfc\x0c\x05\x4a\x2e\xf2\x7f\x48\xb9\xdb\x6a\x26\xce\xfa\x14\x94\xd2\x62\xdd\x9b\x7e\x63\xe9\x36\xbd\xd3\x4c\x07\xda\xae\x9f\x35\x6f\x84\x25\x6b\x4e\x20\x4b\xc7\x05\x2e\xf4\x5f\xbf\x05\x81\x34\x45\x9c\xc5\xdc\x3f\x99\x92\x91\x80\x1a\x44\x33\xe6\x3a\x34\xa0\xe9\xfa\x8c\xec\xed\x97\x12\x55\x78\xb3\x69\x0a\xdf\x2b\x73\xf7\x9f\xff\xde\x3d\x20\xf1\x27\x2e\x13\x34\x20\x75\xde\xc9\x47\x35\xf7\xe5\xf6\xcf\x8b\xbd\xfe\x79\xb1\xd7\x3f\x2f\xf6\xfa\xe7\xc5\x5e\xff\xbc\xd8\xeb\x9c\x17\x7b\xa5\xf8\xd0\x7f\xde\xf2\xf5\xcf\x5b\xbe\xfe\x79\xcb\xd7\x3f\x6f\xf9\xda\xf1\xf0\xcf\x5b\xbe\xa2\xd7\x3f\x6f\xf9\xba\xe8\x37\x00\x82\xf3\xbc\x76\xf0\xf4\x5d\xaf\xd3\x40\x64\xe0\x02\x11\x38\x10\x91\x17\xc6\xdc\xaf\xec\xeb\xd0\x85\xfe\x41\xdc\xff\x0f\x00\x00\xff\xff\xae\x0d\x0b\x98\x7d\xf2\x00\x00") func failed_transactionsHorizonSqlBytes() ([]byte, error) { return bindataRead( @@ -206,7 +206,7 @@ func failed_transactionsHorizonSql() (*asset, error) { } info := bindataFileInfo{name: "failed_transactions-horizon.sql", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} - a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x82, 0x77, 0xfd, 0x12, 0xd7, 0x88, 0xba, 0x7e, 0xb5, 0x5e, 0x82, 0x4b, 0x3a, 0xdc, 0xd4, 0xd0, 0xfb, 0xcc, 0xce, 0x75, 0x97, 0xe1, 0x39, 0x1a, 0x55, 0xcf, 0x65, 0x52, 0xd5, 0x17, 0x5a, 0x77}} + a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x88, 0x98, 0x8c, 0x2f, 0xe6, 0x6d, 0xfe, 0xce, 0xd0, 0x81, 0x7e, 0x67, 0xb2, 0x3c, 0xe, 0x52, 0xfa, 0xe2, 0x50, 0x71, 0x47, 0x52, 0x47, 0xaf, 0xb8, 0xf2, 0x6, 0xc, 0xea, 0x38, 0xcd, 0x39}} return a, nil } @@ -230,7 +230,7 @@ func ingest_asset_statsCoreSql() (*asset, error) { return a, nil } -var _ingest_asset_statsHorizonSql = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xe4\x7d\x79\x8f\xe2\xb8\xd6\xf7\xff\xf3\x29\xa2\xd1\x95\x6a\x46\x74\x37\x76\x36\x27\x3d\xef\x3c\x52\x80\xb0\xef\x3b\x5c\x8d\x90\x93\x38\x10\x96\x04\x92\xb0\x5e\x3d\xdf\xfd\x15\x84\x35\xc5\x1a\xa8\xea\xee\xfb\xa0\x51\x4f\x85\x38\x67\xf3\xb1\x7f\x3e\xc7\xc7\xe1\xeb\xd7\xdf\xbe\x7e\xa5\x8a\x96\xe3\x76\x6d\x52\x29\x65\x29\x0d\xbb\x58\xc1\x0e\xa1\xb4\xe9\x68\xfc\xdb\xd7\xaf\xbf\xad\xef\xc7\xa6\xa3\x31\xd1\x28\xdd\xb6\x46\x87\x06\x33\x62\x3b\x86\x65\x52\xe2\x37\xfe\x1b\x3c\x6a\xa5\x2c\xa9\x71\xb7\xb3\x7e\xdc\xd7\xe4\xb7\x8a\x5c\xa5\x1c\x17\xbb\x64\x44\x4c\xb7\xe3\x1a\x23\x62\x4d\x5d\xea\x6f\x0a\xfc\xb5\xb9\x35\xb4\xd4\xc1\xfb\x6f\xd5\xa1\xb1\x6e\x4d\x4c\xd5\xd2\x0c\xb3\x4b\xfd\x4d\xbd\xd5\xaa\x71\xe1\xed\xaf\x1d\x39\x53\xc3\xb6\xd6\x51\x2d\x53\xb7\xec\x91\x61\x76\x3b\x8e\x6b\x1b\x66\xd7\xa1\xfe\xa6\x2c\x73\x4b\xa3\x47\xd4\x41\x47\x9f\x9a\xaa\x6b\x58\x66\x47\xb1\x34\x83\xac\xef\xeb\x78\xe8\x90\x13\x36\x23\xc3\xec\x8c\x88\xe3\xe0\xee\xa6\xc1\x1c\xdb\xa6\x61\x76\xff\xda\xca\x4e\xb0\xad\xf6\x3a\x63\xec\xf6\xa8\xbf\xa9\xf1\x54\x19\x1a\xea\x97\xb5\xb2\x2a\x76\xf1\xd0\x5a\x37\x93\xb2\x55\xb9\x4c\x55\xa5\x48\x56\xa6\x52\x71\x4a\x6e\xa6\x2a\xd5\x0a\x55\xc8\x67\x5b\xdb\xf6\xdf\x7a\x86\xe3\x5a\xf6\xb2\xe3\xda\x58\x23\x0e\x15\x2b\x17\x8a\x54\xb4\x90\xaf\x54\xcb\x52\x2a\x5f\x3d\x7a\xe8\xb4\x61\x47\xb5\xa6\xa6\x4b\xec\x0e\x76\x1c\xe2\x76\x0c\xad\xa3\x0f\xc8\xf2\xaf\xcf\x60\xa8\x6e\xfe\xfa\x0c\x96\x6b\xbf\xfa\x3c\x05\x3d\x6e\x8f\x6b\xe7\x09\xb8\x76\xe4\x6b\xcc\x8e\x5a\x1d\x88\x6f\x9a\xa7\xf2\x31\xb9\x79\xd4\x72\x4b\x76\x23\x55\x87\xe8\x3a\x51\x5d\xa7\xa3\x2c\x3b\x96\xad\x11\xbb\xa3\x58\xd6\xe0\xfa\x83\x86\xa9\x91\x45\xe7\x48\x39\xd3\xc1\x1b\x47\x77\x3a\x96\xd9\x31\xb4\x47\x9e\xb6\xc6\xc4\xc6\xfb\x67\xdd\xe5\x98\x3c\xf1\xf4\x41\x92\xa7\xa4\x78\xec\xd9\x21\xd1\xba\xc4\xde\x3c\xe8\x90\xc9\x94\x98\xea\x43\x2a\x1c\x3d\x3e\xb6\xc9\xcc\xb0\xa6\xce\xf6\xbb\x4e\x0f\x3b\xbd\x80\xa4\x9e\xa7\x60\x8c\xc6\x96\xbd\x1e\x8e\xdb\x39\x35\x28\x99\xa0\xb6\x54\x87\x96\x43\xb4\x0e\x76\x1f\x79\x7e\xe7\xcc\x01\x5c\x69\x3b\x2e\x03\x08\x7d\xfc\x24\xd6\x34\x9b\x38\xce\xf5\xc7\x7b\xae\xad\x6d\x70\xa7\x33\xb4\xac\xc1\x74\x7c\x47\xeb\xf1\x2d\x91\xbc\x56\xd8\xb0\x1f\x24\xbc\x9b\x74\xef\x7e\x60\x3d\x4f\xe8\x3a\xb1\xef\x6b\xba\x23\x1f\xe0\x91\xad\x59\xef\x7b\x68\x33\xb5\x3e\xc0\xe4\x78\x2a\xbe\xf5\xc4\x78\xfd\x40\xcf\xbd\xd9\x03\xce\xc9\x04\xa4\x2c\x6f\xba\x51\x6f\x3f\xd2\xef\x69\x6c\x79\x72\x58\x37\x1b\x1a\x8e\xdb\x71\x17\x9d\xf1\x6d\x92\xeb\x96\xd6\xf8\xde\x96\xe4\xde\x66\x3b\x28\xb9\xde\x58\xd9\x0d\xf7\x9b\xcd\x6e\xcf\x62\xca\xf2\xbe\xce\xf4\x30\x72\x6d\x6d\xc7\x99\xde\xe2\xbc\x6f\xac\x5a\x1a\x79\x70\x5d\xb0\x77\x83\x31\xb6\x5d\x43\x35\xc6\xd8\xbc\x0a\xde\xb7\x1e\xed\x8c\x1f\x5c\x9b\xec\x11\xed\x51\x09\xce\x3f\xf8\x30\xff\x8d\xf1\xee\xe1\xe7\x35\xfc\x70\xfa\x5e\x67\xae\x7b\x72\xfb\xe7\x1a\x1f\x76\x4b\xbf\x8d\x33\x74\xee\x94\xa0\x6b\xd9\xe3\xce\xc8\xe8\x6e\x17\x0c\x57\x44\xf0\xb5\xbc\x5b\xc7\xc7\xd7\x7b\xd7\x28\xdf\xeb\x9c\xde\xd3\xd1\x42\xb6\x96\xcb\x53\x86\xe6\x71\x8e\xc9\x71\xa9\x96\xad\xde\x49\xfb\x82\xd3\xbd\x80\xf2\xb6\xbb\xaf\x53\xda\x5c\xdd\xaf\xfe\x0e\xa5\x2b\x72\xa9\x26\xe7\xa3\x01\x6c\xb6\x5e\x67\x3b\x64\xf2\x30\xe7\x13\x22\x77\x3f\xad\x91\x3b\xdb\x1e\x56\xb3\x77\x6b\x78\x61\xd4\x3f\xa2\xdf\x79\x12\xf7\x3d\xbb\x5d\xf7\xdd\xd7\x78\xbb\xc8\xbb\x5b\xb7\xed\x0c\xf0\x88\x2e\xde\x23\x77\xb6\xdd\x2e\xff\xee\x97\x67\xb7\x5e\xbc\x47\x22\xdf\x1c\x72\xbd\xf1\xd1\x94\xb0\x6d\x28\x25\x12\x65\x39\x21\x55\xcf\x34\x1e\x19\xeb\x88\xc3\x50\xc9\x1f\xe6\x74\x44\x6c\x43\xfd\xf7\x3f\x7f\xde\xf1\x14\x5e\x04\x78\x6a\x88\x1d\xf7\x0f\x6c\x2e\xc9\x70\x93\x8a\xb9\xe3\x09\xdd\xb0\xcf\x3e\x12\xaf\xe5\xa3\xd5\x54\x21\x7f\x45\x9f\x0e\xee\x76\x0f\xd2\x7d\xa1\xde\x09\x7a\x85\xc6\x4e\xbb\x27\x68\xac\x75\xdd\x3c\x7e\x10\xfe\x0b\xf5\x88\x22\x1b\xd5\xef\xa0\x20\x37\xab\x72\xbe\xe2\x23\x31\x1c\x77\x9d\xc9\x70\xe7\x8b\xd1\xa4\x9c\x93\xde\x71\xf8\xeb\x37\x2f\x0b\x97\xc7\x23\xf2\x7d\xf7\x1d\x55\x5d\x8e\xc9\xf7\xed\x23\x7f\x51\x15\xb5\x47\x46\xf8\x3b\xf5\xf5\x2f\xaa\x30\x37\x89\xfd\x9d\xfa\xba\x49\xce\x45\xcb\xf2\xba\xbf\xb6\x94\x77\xf4\x7e\x3b\xa1\x78\x7a\x73\x4b\x38\x5a\xc8\xe5\xe4\x7c\xf5\x0a\x65\xaf\x01\x55\xc8\x9f\x12\xa0\x52\x15\xea\x6d\x97\x76\xdb\x7d\xe7\x6c\x88\xbc\xf9\x39\xef\xd4\xdf\xf2\xdc\x5b\xe8\xa6\x3e\x27\xb6\xcc\x17\xaa\x3e\x7b\x52\x8d\x54\x35\xb9\x17\xeb\x38\xff\x76\xc2\xfe\x40\xc5\x27\xc8\x23\xca\xbf\x23\xb2\x31\x40\x31\x1b\x1e\x77\x2b\xa5\x2c\x35\xb6\x2d\x95\x68\x53\x1b\x0f\xa9\x21\x36\xbb\x53\xdc\x25\x1b\x33\xdc\x99\x2f\x3c\x16\xf7\xb6\xa3\x6d\xc5\xdf\xf9\xea\x41\xfe\x5d\xdf\x9e\xb3\xe5\xde\xb3\x6f\xd2\xa7\xca\x72\xb5\x56\xce\x57\x8e\xbe\xfb\x8d\xa2\x28\x2a\x2b\xe5\x13\x35\x29\x21\x53\x1b\xed\x73\xb9\x9a\x37\xdf\x55\xaa\xe5\x54\xb4\xba\x69\x21\x55\xa8\x7f\x75\xfe\x45\x55\xe4\xac\x1c\xad\x52\xff\x82\xeb\x2b\x7f\x6f\xdc\x1c\x88\xcf\x69\x77\x8b\xfc\xcb\x94\xa3\xcf\x29\x77\xcf\x4c\xf5\x9c\x7e\x77\x70\xd8\xab\xb8\xff\x2a\x90\x86\x7f\xfc\x46\x51\x51\xa9\x22\x53\x8d\xa4\x9c\xa7\xfe\x05\xff\x0d\xff\x09\xff\x0b\xfe\x9b\xfe\xe7\x7f\xfe\x45\x6f\xfe\xa6\xff\x4d\xff\x43\x55\xbd\x9b\x94\x9c\xad\xc8\x6b\xa3\xc8\xf9\xd8\x9f\x67\x2d\x73\x07\x0e\x3c\x69\x99\xdb\x1c\x3e\xda\x32\xff\x2f\x88\x65\xde\x63\xea\xd6\x0e\x7b\x1c\xbe\xcf\x10\x07\xd8\x7e\x47\x71\x23\x31\x45\x55\xd6\xb6\xa2\xfe\x3e\xcc\x00\x5f\xbc\xaf\xab\xad\xa2\x4c\xfd\x7d\x3c\x22\xfe\x3c\x37\x6a\x5f\x2a\xa3\x9f\xa0\x4f\xc4\xdd\x30\xbe\x5f\xc2\xb3\x4b\xa0\x67\xa5\x3c\x47\xd4\x27\xe9\xc9\x80\x3c\x15\xf7\xe0\x65\xef\xa5\x3d\xb7\xcc\x7b\x5a\xda\x33\x44\xfd\xd2\x1e\x0f\x92\xab\xd2\xae\x91\x4b\x23\x3a\x9e\x0e\xdd\x8e\x8b\x95\x21\x71\xc6\x58\x25\xd4\xdf\xd4\xdb\xdb\x5f\xa7\x77\xe7\x86\xdb\xeb\x58\x86\x76\xb4\x95\x76\xa2\xeb\xf1\xfa\x77\xab\xe2\x66\x80\xdd\xa7\x9e\x37\x16\x8f\x83\x6f\x4f\x23\x43\xa3\x14\xa3\x6b\x98\xee\x66\x61\x90\xaf\x65\xb3\x9e\x3a\x78\xb4\x5e\xc6\x53\x6a\x0f\xdb\x58\x75\x89\x4d\xcd\xb0\xbd\x34\xcc\xae\xaf\x99\x39\x1d\xed\x97\xfc\x94\x61\xba\xa4\x4b\x6c\x5f\x13\x7d\x88\xbb\x0e\xe5\x8c\xf0\x70\xf8\x9e\x8d\x6b\x8d\x86\xef\x99\xfc\x41\x73\xdc\x9f\xfb\x96\xef\xbb\xdd\x1f\x37\x04\x35\x87\x3f\xdb\xb1\x37\x89\x4b\x16\xef\x0c\x32\x1e\x0f\x8d\x4d\xce\x9e\x72\x8d\x11\x71\x5c\x3c\x1a\x53\xeb\x3e\xdb\x5c\x52\x2b\xcb\x24\xef\x05\xbd\x14\x15\xed\xd6\xa3\xdb\x70\xea\x3e\x99\xf7\xc1\xd7\x05\xaa\x5b\x37\x94\xca\x55\x6f\x45\x07\x37\x5f\xa4\xf2\xd1\xb2\xbc\x59\x7e\x45\x5a\xdb\xaf\xf2\x05\x2a\x97\xca\xd7\xa5\x6c\x4d\xde\x5f\x4b\xcd\xc3\x75\x54\x8a\x26\x65\x0a\xde\x52\x26\xb0\xd9\xfd\x84\xde\xb9\xe2\x36\xe9\x41\x99\x64\xe1\xce\xf0\xf0\x8f\xb7\x0b\x1a\xbf\x7d\xff\x6e\x93\xae\x3a\xc4\x8e\xf3\xa7\xbf\xbb\xbc\xbd\x8a\x33\xbe\xc5\xb3\x7f\x5e\xe9\x28\x2f\x36\x7e\x5a\x33\x2f\xa3\xb3\xd7\xeb\xfc\xc8\x38\xe4\xea\xce\x8b\x79\xb6\xb9\x6a\x69\xe7\x9a\x43\xfa\x7c\x73\x2f\xfd\x77\xe6\x01\x8e\xbf\x36\xc2\xce\xa7\x17\x5e\xe4\xb6\xc7\x34\x3f\xcd\x69\xaf\x29\x42\x15\x1a\x79\x39\x46\x45\x5a\x37\x34\xf2\x32\x74\xd7\x15\xda\xd3\xf2\xdd\xfe\x66\x68\x97\x64\xdb\xe5\x7c\x9e\xf5\xba\x2d\x9d\xad\xdb\xf9\xc6\x4c\xe7\xd2\x4c\xff\x3e\xc5\x75\xa9\xe5\xef\x9b\x8d\x8f\xdf\x2f\x78\xf3\xc6\x8f\xcf\xdf\xd2\x88\x8b\x8d\xa1\x43\xf5\x1d\xcb\x54\x2e\x3b\xdb\x2e\x51\xf6\xac\x1d\xb6\x74\xb6\x76\xd8\xed\x5b\x5f\x90\xed\x68\x33\xf9\xae\x51\x78\x6e\x1f\xfb\xfc\x83\x5b\xb3\x1c\x65\x46\x37\x1d\xb1\x97\x63\x37\xcb\x01\x1f\x87\x43\x47\xdc\xd7\x7e\xbf\x99\xec\x03\x26\x6b\xea\x1e\xb0\xc9\xff\x8c\x4d\xb0\x7b\xf3\x21\xaf\xed\x74\xac\xdd\xdd\x76\xef\x3a\xdb\x4b\xdf\x3e\xfb\x3b\x5d\xe0\xbb\xf5\x80\x8b\x87\x1d\xd5\x32\x4c\xe7\xbc\x0f\xea\x84\x74\xc6\x96\x35\x3c\x7f\x77\xb3\xf3\xa9\x93\x4b\x7d\xbd\xb9\x6d\x13\x87\xd8\xb3\x4b\x4d\xd6\xeb\x50\x77\xd1\xd9\x2c\x93\x8c\xd5\xa5\x56\x63\xdb\x72\x2d\xd5\x1a\x5e\xd4\xcb\xdf\x47\x3b\x67\x21\x58\x23\xf6\x66\x79\xe1\x7d\xef\x4c\x55\x95\x38\x8e\x3e\x1d\x76\x2e\x3a\xca\x56\x71\x6c\x0c\x89\x76\xb9\xd5\xe5\x61\x75\x21\x77\xfd\xec\x28\xbb\xb0\x1f\x72\x03\xf3\xee\x9f\x6d\x6e\xcf\x5f\x8f\xaa\xfc\x5a\x18\xbb\xca\xe3\xb3\x60\xed\x21\x45\x9f\x84\xb9\xab\xbc\xde\xc3\xde\xf9\xe6\x57\x60\xf0\x68\x67\xe7\x65\xbe\x79\x2b\xcc\x39\xad\xaa\xba\x10\x0a\xad\x57\xfe\xaa\xa7\xca\x06\x01\x9f\x04\xc0\xed\xc8\xb7\xa6\xb6\xba\x2f\xd3\xb8\x00\x3d\xbb\xe9\xe4\xed\xed\xfb\xf7\xcb\xa1\xd8\xe5\x71\xb0\xdd\x58\x7b\xd6\x9c\xdb\x5a\xc0\x3f\x5e\xba\x5e\xd8\x4e\x89\x41\xd0\x6b\x53\x0b\x73\x91\xad\xaf\x12\xf1\x5a\xa3\x6d\x71\xe4\xb5\x26\x5e\x1c\x7c\xb6\xc1\xfb\x9a\xce\x1b\xed\xae\xb2\xdb\xb7\xba\xc2\x71\x23\x92\xe1\x74\x1c\x32\x1c\x12\x9b\x52\x2c\x6b\x48\xb0\xb9\xc3\x24\x43\x25\x1d\xf3\x04\x7f\xbd\xef\x4e\x31\xf9\x50\x4d\xd4\xf1\xa1\xf5\x49\x3d\x93\xff\xa6\x6d\x4d\x4d\x6d\x53\x10\x3c\x34\xc6\x63\xdc\x25\xef\x89\x1a\x4e\x87\x2c\xb0\xea\x9e\xca\x75\xb4\xbf\x7f\xb6\x64\x74\xa3\x6e\x67\x53\x54\x4c\x45\x93\x72\x34\x43\xfd\xf1\xc7\xb1\xe9\xff\x87\x02\x7f\xfe\x79\x8b\xd4\xb9\xc7\x77\xd6\xfe\x7f\xef\x3a\xe0\x0e\x7a\x27\x9d\xe1\x23\xef\xeb\xa9\x8d\x80\x57\xc7\xe0\xf9\xad\xf1\x17\x8c\xca\xf3\xc5\x0e\x77\x42\xf0\x3d\x73\xdf\x33\x20\x7c\xab\xb0\xe0\x35\x30\x7c\x83\xcb\x67\x01\xf1\x83\xca\x3e\x09\xc5\x37\xb8\xbd\x07\xe3\x4b\x0f\x5c\x81\xe3\x93\x62\x92\x17\xfa\xea\xce\x3f\x8f\x45\xba\x3b\xfa\xda\x82\xc6\x8d\x98\xee\x5e\xc4\xbe\x0e\xbe\x67\xdb\x1e\x58\x9f\x1d\x2f\xeb\xf0\xe1\x72\xfc\x71\x29\xb2\xfb\x21\xb1\x99\xbb\xe8\x10\x73\x46\x86\xd6\x98\x9c\xcb\x77\xba\x8b\x75\xa4\x34\x1d\xba\x17\x6e\x8e\x88\x8b\x2f\xdc\x5a\xc7\x68\x97\x6e\x3b\x46\xd7\xc4\xee\xd4\x26\xe7\x52\x73\x22\xff\xe7\xbf\xff\x39\x2c\x7a\xfe\xf3\xbf\xe7\x96\x3d\xff\xfe\xc7\x6f\x73\x32\xb2\x2e\x64\xd1\x0e\xb4\x4c\xcb\x24\x57\x17\x51\x07\x5a\xef\xc9\x6c\x35\x33\x46\xa4\xa3\xac\x61\x70\x93\xea\x16\x6c\x6c\x76\xc9\x89\x5b\x9e\xbf\x39\x32\xcc\xce\x05\xef\xb9\xdc\xa0\xe3\x47\xd8\xb3\x8d\xb6\x7c\xbb\x78\x7c\xd2\x96\x2c\x5c\x1b\x77\xd6\xa6\x26\xb6\xb3\xe9\x85\x7f\xff\xe3\x8f\x37\x4f\x41\x7a\xdd\x65\x6b\xb5\xbb\x44\xbb\x1d\x50\x6e\xb3\x9b\x86\xb6\x9b\x16\x76\x45\x6a\xf7\xcc\x65\xde\xbc\xb0\xa9\x08\xbc\x51\xff\x56\x91\xab\x57\x32\xc1\xc7\x39\xb7\xe3\x3c\xf0\x63\x91\xd2\xeb\x94\xb8\xb3\x3c\xf0\xaa\x52\x57\x23\xac\x7b\x94\xbc\xb8\x24\x78\x99\x9a\x77\x57\x58\x5e\x55\xf4\x06\x7e\x9d\x57\x35\x86\x5d\x4c\xe9\x96\x7d\x63\x3f\x8c\x8a\x49\x55\xe9\x86\x7a\xa9\x7c\x45\x2e\x57\xa9\x54\xbe\x5a\x38\xd9\x13\xdb\xc0\x7d\x85\xfa\x03\x7e\xa1\xde\x20\x00\xa2\x80\x78\x00\xc0\xdb\x17\x0a\x6e\xfe\x7b\xeb\xb9\xee\xd8\xf9\x1e\x0e\xbb\xc4\x71\xbf\xa9\xd6\x28\xfc\x6d\x4e\x86\xc3\xaf\x03\xd3\x9a\x9b\x61\xc7\x25\xc3\x21\xb6\xbf\xb9\xd6\x68\xf8\xf6\xe7\x5f\x37\x99\xd0\x5f\xa8\x37\x06\x00\x00\x20\x60\x19\xd6\xe3\x43\x7f\x00\x1f\xc6\x53\x66\xf7\xf1\xb4\x59\x33\x7f\xbb\x6c\xdc\x6b\x3b\x6c\x8f\x1a\xd8\xbf\xcb\xb6\x93\xeb\x0d\x76\x0c\xd3\x70\x0d\x3c\xec\x78\x15\x4f\xdf\x9c\xc9\xf0\xed\x0b\xf5\x46\x03\x28\x7e\x05\xfc\x57\xc0\x50\x50\xf8\x4e\x0b\xdf\x59\xf4\x0d\x30\x34\x2b\xf2\x21\x40\xfb\x35\xbe\x48\x9d\xee\x78\x27\x59\x4e\xfc\x4b\x59\x76\x5c\xcb\xd0\xae\x73\x12\x79\x0e\x3d\xc2\x89\xe9\x4c\x1d\x72\x98\x94\x0d\xf3\xdd\xe9\x99\xab\xfc\x58\x16\xb0\xc2\x23\xfc\xd8\x0e\xd6\xb4\x8e\x3f\x07\x79\x95\x07\xc7\x72\x0c\xfd\x08\x0f\xae\xe3\x2d\x43\x76\x01\xd1\x66\xef\xfa\x2a\x0b\x9e\x01\xf4\x43\x6a\xf0\x3b\x16\xdb\xb9\xfc\x0e\x16\x02\x0b\xb9\x47\x58\xa0\xce\xc8\xd2\x0c\x7d\x79\xbf\x16\x02\xe4\xe9\x87\x58\x08\x27\x5a\x6c\x4b\xd6\xef\xe0\x83\x58\x9e\x79\x8c\xcf\xba\xd3\x71\xb7\x6b\x93\x2e\x76\x2d\xfb\xba\x4f\x89\x00\x02\xf1\x11\xf2\xe2\x86\xbc\x97\x9f\xee\x2c\x34\xfb\x3a\x75\x1a\xc1\x87\xba\x1a\x82\x0d\xf9\x6d\x2f\x6c\xb2\x12\xd7\x19\x70\x22\x7a\xc8\x3a\x10\x1e\x33\xd8\x47\xab\xeb\x09\xe0\x3a\x23\x91\x17\x1f\xd3\x84\x3e\xe9\xe8\x6d\x7e\xc0\x3b\x24\x7d\x8d\x13\x04\x88\x63\x1f\xea\x11\xc8\x78\xea\xec\xd3\x31\x57\x7b\x1c\x42\x1a\xf1\x8f\x69\xc2\x76\x74\x63\xb1\x3b\x30\x62\x8d\x86\x1d\xdd\x20\xc3\xab\x53\x23\x84\x1c\x84\x0f\x4d\xc2\x90\xdb\xad\x51\x77\xfb\x17\x8b\x1b\x6a\xf0\xe8\xb1\x69\x1e\xf2\x1d\xc3\xec\x12\xc7\xed\xbc\xdf\x21\xb9\xc1\x0a\x89\xc2\x63\x3d\x82\x4e\x16\x2e\x9b\xad\x28\x7c\x1d\x4c\x20\x0d\x00\xc3\x6e\x99\x5c\xc0\xda\xab\x75\x15\x8f\x82\xed\xbb\xda\x8a\xe3\x25\x4d\x22\xda\xcc\x24\xf8\x72\x9e\x2d\xe4\x53\x72\x31\x9a\xcb\xc7\x23\x88\xa1\x25\x96\xe1\xdb\x5c\x31\x1f\xab\x94\xb3\x89\x46\x06\x25\x22\xd9\x68\xae\x94\x4d\xc5\x0b\x6c\x05\xc9\xad\x46\xbd\xe6\xb7\xd0\x45\x26\xeb\x55\x45\x42\xe2\x1a\x91\x62\x4b\xe2\x5a\x6c\x43\x92\x93\xcd\x46\x99\xae\x65\x0a\x74\xad\xc0\x46\x6a\x89\x64\xad\x84\x58\xb9\x56\xcc\x14\xf2\x74\x29\x59\x67\x1b\xe5\x64\x21\x55\xce\x67\x32\xc9\x77\xdd\x70\x91\x09\xb3\xd1\x84\x66\x4a\x71\x3a\x59\x93\x39\x5a\xca\x35\x6b\xf1\x5a\x92\x91\x5a\x69\xa9\xd9\x4c\x34\x9b\x75\xba\x9e\x6c\xb6\x5a\x65\x5e\x6e\x35\xe5\x6a\x31\x13\x6b\xb6\x2b\x52\x83\x47\xcd\x02\x7b\x37\x13\x76\xcd\x24\x52\x2e\xb6\x92\xa9\x2c\x1d\x4d\x31\xf1\x7c\x89\x8d\x34\xb3\xf1\x5c\x3e\x96\x8d\xa7\x6b\xf9\x62\x8d\x4e\xb6\x98\x76\x2e\x5e\x49\x16\xf2\xb5\xa8\x5c\x90\x2a\x0d\x54\x8a\xa2\x42\x93\x4e\xbe\x05\xad\x03\x5a\x2f\x9a\x6f\xf4\xf5\xb6\x76\xf2\x50\xf6\xfc\xcd\x21\xd7\x6b\x64\xbe\x50\xec\x17\xca\xb5\xa7\xe4\x0e\x0f\x7c\x5f\xfd\x12\xd8\xff\xbc\x98\xee\xd8\xfb\x54\x9b\x68\x86\xdb\xc1\xc3\x71\x0f\x9b\xd3\x11\xbb\x1e\x33\x91\x6a\xf4\xed\x23\xba\xf3\x94\x3b\x7d\x81\x7b\xad\x12\xfb\x04\xee\xcc\x05\xee\x95\x68\xa1\xfa\xf6\xe4\xa8\x0c\x52\xec\xf2\x12\x27\x3b\x09\xbf\xbf\x50\xcc\xbd\x2e\x76\xae\xd6\x25\xa8\x8f\xed\xea\x5d\x8e\x9c\x8c\x61\x19\x4e\x44\x2c\xcd\xf2\xdc\x3e\xcc\xf9\xcf\xef\x1e\x4a\xff\xfe\x9d\xfa\x1d\x7e\x63\x78\x7a\x1d\x74\xfd\xfe\x85\xfa\xfd\x50\x50\xb5\xbe\x55\xab\xc4\x0e\x5f\xba\xcb\xf1\xe6\x4b\x7f\xbf\x1d\x5a\x78\x85\x55\xeb\x36\x41\xdd\xe7\xf7\xff\xbd\xe4\x40\x7e\xc5\x68\x9f\x62\xf4\xc6\xe0\xff\x55\x8a\xf1\x1c\x0f\xcf\xf6\x18\x03\xbf\xf1\x1c\x42\xbc\xf0\x6b\x69\x06\x7d\x9a\x9d\xe9\xb2\x5f\x54\xb3\xb5\x26\x00\xf0\x2c\x42\x1c\xe4\x45\xaf\xcf\xbc\x4e\x1b\x1a\x23\xc3\x73\xc6\x7d\xb2\xe1\xdb\xf6\xff\xbf\xa8\x86\x22\x7d\x61\x1e\x11\xc4\x6f\x22\xf7\xeb\x69\x06\x7d\x9a\x9d\xf1\xca\x5f\x54\x33\xfa\x0b\x45\x73\x88\x17\x05\x80\x04\xc4\x9c\x9f\xfb\xaf\xfa\xe3\x1a\x8d\x83\x2a\x17\x0c\xbf\x1f\xea\xb6\x13\xe5\xce\xcd\xff\xbf\xbe\x72\x10\x8a\xbb\xf9\xe4\x8c\x72\x00\x6c\x82\xa9\x5f\xcd\x2f\x19\x9f\x76\x17\xba\xee\x17\xd5\xee\xd0\x77\x3c\xb8\xb4\xe2\x02\xe0\xdb\x36\x8f\xfe\x5e\xb5\x48\x35\xfa\xb3\xaa\xc6\xf8\x54\x3b\xdf\x71\xbf\xa4\x6a\xfb\xb9\x92\x06\xf0\xc2\xaa\xcb\xf3\xc5\x6f\x22\xbd\xd9\x98\xf8\xa5\x7c\x92\xf1\x69\x77\xa6\xe3\x7e\x71\xed\x20\x8b\x58\x81\x05\x1c\x42\x5e\xdf\x79\xea\xb9\xf6\x74\xfd\xc8\x53\x93\xf6\xaf\x69\x09\x96\xdf\x21\xfe\x07\x5a\xe2\x27\x1e\xcf\x07\x4b\x08\x68\x87\xa0\xef\x2d\x11\x30\x2d\xf7\x4b\xf9\x04\xfd\x85\x82\x08\x22\x51\x40\x0c\x2d\x6c\x67\x36\x70\x1a\x9b\x88\x34\xcd\x30\x88\x06\x0c\x2f\x70\xdf\xd6\x41\x8c\x00\xd0\x2f\xa5\x23\xdc\xeb\x88\x98\xdd\x0c\xf0\x5f\xab\xa3\x00\xd9\xdd\xd8\x0e\xa4\xe3\x4f\x3c\x6a\xf7\xbe\x2a\x70\xdc\x6e\xd4\x06\xd2\xf1\x27\x5f\xdc\x43\x5a\x10\x58\x11\x70\xa2\xe0\x2d\x10\x79\x0f\x8c\xa7\x6e\xaf\x63\x93\x99\xa5\x62\x65\x48\x3a\xfa\x10\x77\x7f\xff\xbe\xc9\x21\x3e\x32\xed\x79\xb4\x21\x00\xdb\xc1\xce\x6d\x68\xf7\xac\x11\xe9\x68\xd6\x08\x1b\xe6\x5a\xcb\x5d\x11\xc5\x43\x13\xea\x96\x32\x0b\xb7\x43\xec\x44\xea\xc9\xd4\xb0\x89\x16\x54\x68\x81\x13\x44\x91\x11\x78\xc1\xeb\x74\xaf\xcf\x1d\x17\xdb\xae\x61\x76\x3b\x0a\x1e\x62\x53\x25\xef\x62\xba\xbb\x39\xb0\xa7\x1c\xee\x8e\x15\x77\x8e\x63\x62\xd7\x98\x91\x87\x8c\x75\xcc\x6f\x6d\x3b\x4f\xa5\x39\x31\xba\xbd\x35\x43\xf8\x85\xfa\xdd\x4b\xea\x76\x06\x64\xf9\x69\x33\xc8\x46\x2a\x96\x46\x5b\xbf\xfb\x28\x3b\x6f\x39\x7c\xb8\x9d\x7d\x1a\xdd\x69\xe7\x8f\x1e\xe0\xf4\x4e\x2a\x5e\xd8\x8e\xc1\x0f\xb3\xb3\xc7\xe1\xc3\xed\xec\xd3\xe8\x3e\x3b\x07\x5d\x5c\xfd\xef\x1d\xfb\xc2\xe7\x8e\xc5\x06\xdd\x32\xd9\x1d\x8d\xdd\x29\x2b\x7c\xa1\xde\x14\x48\xf3\x1c\x82\x58\x57\xb1\x0e\x45\xc8\x21\x85\x67\x44\x9d\x23\x0a\x16\x04\x48\x68\x4e\x64\x80\x26\xb2\x98\x41\x98\xa3\x05\xc8\x69\x0a\x84\x02\x14\x55\x55\xe3\x18\x16\x28\xe2\x66\x2f\x0b\xb2\x22\xd4\x75\x5e\x55\x74\x05\x01\x5a\x61\x04\x00\x81\x42\x74\x85\xd7\x01\xe6\x59\x8d\xa7\x69\x91\x51\x54\x00\x38\x46\x54\x69\x16\xb3\xaa\x4e\x18\xc0\x08\x8a\x8e\x20\x62\x19\x46\xf4\x4a\xdf\x68\xdf\x2e\x3a\xff\x9d\x41\xdf\x59\xe4\xdf\x5c\xf7\xbe\xe6\xbe\x01\x80\x78\xe6\xf6\x5d\x2f\x0f\xcf\x08\x0c\x2f\x7c\xa1\x20\xbf\xee\xcf\x77\x9f\xf5\x0a\x7a\xfd\xef\xee\x9f\xdd\xb7\x70\xff\x07\xfc\x42\xbd\x49\x92\x24\x45\x17\x95\x72\x98\x5e\x86\xdd\x79\x66\xd5\x8d\x44\x43\x21\x5a\xc8\xb4\xf3\x2d\x63\x80\xe6\x52\x8d\x9b\x0f\xc6\xb9\x70\x5f\x62\x67\x4c\x1c\xe4\xb8\x8a\x6d\x36\xb3\x74\x51\x18\x56\x56\x16\x9f\xaa\xc7\x46\x6e\x0b\xb6\x65\x25\x1d\xa9\x86\x63\x83\x4c\xbd\x1e\xe3\xd3\x92\xd6\x06\x3d\x75\xe4\xac\x49\x4b\xcd\x62\x3d\x47\xcf\xa5\xfd\xa7\xbd\xd0\x4a\x0d\x3d\x96\x83\xb9\x45\x2d\x3a\x25\xba\x34\x22\x61\xa5\x3f\x29\xa8\xbd\xd5\x20\x29\x0b\x62\xc1\xa9\x0e\x2c\x8e\x57\xd9\x14\x6b\x48\xaa\xda\x8c\x54\xaa\x21\x1d\x44\x4d\xb0\x88\xf7\x0a\x8b\xb1\x5c\x86\xe6\xb0\x37\xe9\x1b\xa9\x94\x93\x6b\x9a\x98\xae\x27\x86\xf3\xec\x86\x72\x37\xcf\x66\xf1\x6a\x4c\x97\x0e\xcc\xa4\x2e\x90\xce\x7c\xda\x52\x13\xb2\x25\x49\x8a\x81\xf4\xb9\xdb\x3f\xf5\xc7\xf3\x2a\x70\x61\xe0\xfb\xc7\x02\x7a\x8d\x1f\xbf\x11\x56\x50\x75\x5a\x27\x1a\x47\x18\x45\xd0\xd7\xf7\x38\xcc\x42\x41\x17\x69\x5d\x80\x8a\xc0\xf0\xb4\x2a\x08\x80\xd5\x55\x86\x61\x09\x62\x34\x4e\x54\x44\xa2\x8a\x22\x21\x2c\x4d\xb3\xca\xb5\xb1\xc0\x5f\xf4\x76\x06\x20\x00\xaf\xde\xa5\xdf\xf6\xd9\x7f\x08\x10\x7d\x65\x2c\x40\xf1\xce\xb1\x10\xaa\xe4\x84\x19\xaa\xb3\xa8\x8f\xc4\x45\x63\x90\x28\x0e\x66\x5d\xa5\x4b\x67\x53\x5d\x39\x1c\xcb\x17\x54\xb1\xa1\x98\xce\x88\x70\xd1\x74\xb6\x0a\x98\x42\xd7\x88\x84\x43\xb9\x42\xac\x5c\x2c\xe9\x58\xcf\x89\xf3\x05\x3d\x66\x81\x38\x2e\xcd\x70\x5b\xeb\xc3\x02\x8f\x2a\xad\x4c\xda\x73\xc3\xcd\x58\xe8\x1e\xfa\x72\xcc\x37\x59\x0c\xf5\x52\xa3\x9c\x87\x7a\x95\x2d\xf4\x30\xac\x4b\x0a\xcd\xd8\x8b\xbe\x8d\xf5\x5e\x37\x2c\xcc\xfb\xcb\x42\xb1\xc4\x92\xa1\xd2\xc8\x65\x84\x8c\xce\xd9\x76\x04\xe4\xea\x2e\x6f\xc5\xe8\xea\x90\x9f\x0b\xb3\xa8\x11\xd2\xd9\x2e\x28\x74\xf9\x4a\x2a\x5f\x6d\xc9\xb1\x8d\xfb\xab\x67\xc6\x82\xe6\x9c\xf3\xa7\xff\x3b\x63\x81\x7f\x8d\x1f\xbf\x31\x0c\x43\x54\x8e\x88\x44\x13\x81\xa2\x10\x45\xe1\x44\x88\x68\x91\x16\x81\x42\xb3\x50\xc1\x3c\xc7\x00\x4d\xd3\x45\x9d\x87\x80\x26\x80\x66\x59\x9d\x26\x9c\x82\x44\x44\x43\x15\x12\xd6\xab\x5e\x61\xcf\xbb\xf5\x45\x6f\x67\x19\x46\xb8\x3c\x16\x76\x77\xb7\x5b\x2a\x0c\x42\xfc\xb5\xb1\x80\xee\x1c\x0b\xab\x5c\x68\x41\x4c\x77\x90\x9d\xd9\x6e\x3b\xbe\x1c\x8c\xa3\xcb\x92\x32\x1e\xe6\xf2\x0c\x27\xf6\xa4\xa9\x34\xa8\x2e\x39\x85\x34\x53\x6a\x72\x30\x15\xda\x7a\xd8\x88\x39\xa3\x71\xcd\x5d\xf5\x6a\xbd\x59\x74\xd0\x5e\x24\x66\xc3\x5e\x84\x13\x1a\xe9\x42\xc5\x0d\x35\xda\x19\x93\x27\x8b\x68\x6d\xd3\x77\x9b\xb1\x70\xe4\x9e\x4d\x25\x6b\xaf\xfa\xcb\x9e\x0a\xc4\x42\xae\x0c\xec\x44\x4a\xcd\x0f\xd3\xcb\x59\x0d\x3b\x1c\x22\xec\x8a\xae\x8e\x6b\xbd\x61\x76\x9e\x88\xd8\x59\xbd\x37\xcd\x30\xa9\x4a\xce\x89\x4e\xeb\xe9\x61\xcc\xc4\xd2\x08\x2d\x7b\x65\xd0\x2d\x2b\xd8\xc0\xe1\x06\x26\x59\xb9\x24\x0e\xea\xc2\x66\xac\xb5\xce\x8c\x05\x3c\x38\xe7\x4f\xbf\xf8\x58\x60\xef\x1f\x0b\xdc\x6b\xfc\xf8\x4d\x05\xbc\x86\x01\xd2\x44\x4d\x67\x20\x50\x54\x5d\x67\x81\xc2\xe9\x1a\xd4\x79\x86\x63\x20\xcf\xd1\x3c\x66\x38\x8c\x69\x88\x00\xa2\x81\x86\x08\xc2\x3a\x8f\x21\xcd\x40\x45\x15\x04\xd1\x2b\xb3\x61\xce\xba\x35\x7b\xd1\xdb\x79\xc0\x5e\x1e\x0a\xdb\x9b\x5e\xf6\x90\xe1\x59\x01\x5c\x1b\x09\xcc\x9d\x23\x41\x88\xb8\x56\x92\xd6\x84\x45\x54\x08\x83\x28\x0c\x97\xc5\x7e\x6d\xd1\xae\xe0\x7e\x63\x92\x6a\x46\x96\xb1\x26\xc7\x8b\x13\xb9\x9f\x10\x8c\xb4\x92\xc9\x65\x14\x41\x50\x32\xf3\x7e\x3c\xec\xea\x5c\x84\x76\xec\xc9\x30\x02\x1b\x2e\x9c\x8f\x27\xb9\x76\x6c\x11\xe3\xcc\x28\x58\xb9\x74\x6b\xd3\x73\x9b\x91\x70\xdc\x95\xb3\x6a\xc3\x92\xda\x82\xa3\x30\xa6\xb8\x4a\xe5\x63\x12\xec\x4d\x2c\x6c\x36\x8d\x7c\x78\xac\xf6\x75\xd9\xcd\x64\x63\xf6\xaa\x3e\x8b\xe5\xa7\x5a\xc4\x62\x7b\x22\x4e\x6a\xae\xde\x68\x56\x9d\x6e\xba\x96\x60\x85\x4c\xbc\xea\xb0\xc5\x6a\xa3\x6a\x95\x9b\xd3\x70\x3d\x5b\xd7\x4a\xdc\x66\x05\x56\x3b\x33\x12\x6a\xb5\x73\xde\xf4\x8b\x8f\x04\xe6\xfe\x91\xc0\xbe\xc6\x8b\xdf\x10\xa3\xb1\x9c\x06\x10\x51\x74\x16\x31\xaa\xc6\x60\x1e\x13\x5a\x63\x31\xe6\x75\x8e\xd7\x00\xd4\x79\x5d\xd7\x10\xd4\x90\xc2\x70\x3c\xc2\xba\xc6\x01\x1e\x28\xbc\xae\x8a\x34\x54\x38\xfe\x1a\x2a\x30\x17\x9d\x1d\xd1\x02\xba\x1c\x2d\xec\xee\x7a\x39\x39\x5e\x84\x02\x7b\x6d\x2c\x80\x3b\xc7\x02\x53\xac\x35\x4b\xba\x2d\x26\x8b\xf9\xc2\xc8\x36\x60\x66\x3c\xab\xbb\x92\xae\x84\xe1\x02\xa2\x7c\x83\xcc\x60\xa9\x95\x55\x84\x41\xcf\x6d\xd8\x21\xb5\x07\x14\x73\x9c\xcf\x26\x4b\xa2\x95\xe9\x75\x85\x42\x4c\x6a\xa5\x20\x97\x33\xa7\x6a\x39\x22\x4e\x9a\xb9\x85\x9b\x9c\x85\x43\x40\xdd\xf4\xdd\x7a\x2c\xc0\xa3\x68\xa1\xcb\x2a\xb1\xec\xa8\x18\x41\xf9\x69\xb1\xa7\xc6\xf3\x53\x86\x29\xf6\x2b\x56\x5f\x2d\x5a\x74\x35\x09\x16\xdc\x32\x9b\x9d\x2a\xbd\x49\xae\xbf\x4a\xcf\x22\x2d\xae\x28\xa5\x66\xc9\x4a\x66\x39\x85\x16\x61\x42\x42\x7a\x9a\x09\x67\xcd\xe4\xb2\x5c\xc7\x7a\x9d\xa1\x49\xa1\x26\x40\x7d\xb8\xa1\x5c\x3a\x33\x16\x8a\xd6\x39\x7f\xfa\xc5\xc7\xc2\x03\xa8\xc0\xbc\xc6\x8f\xdf\x58\xcc\x2a\x50\xd7\x69\xc8\xaa\xac\x00\x91\xae\xd1\x80\x11\x04\x4e\xd7\x74\x8e\x63\x55\x41\x13\x78\x1a\x41\x8d\x47\x82\xc0\x43\x9e\xe3\x39\xc8\x01\x0d\x69\x04\x71\x3c\xaf\x6b\xba\x28\x5c\x43\x05\xfa\xa2\xb7\x0b\x1c\x12\x2f\xc3\xc2\xfa\xee\xfa\xd9\x6d\xea\x16\x0a\xc2\xb5\xc8\x99\xbf\x73\x28\x80\x71\x36\x19\x4e\xd5\x16\xa9\x78\x18\x74\x0b\xa9\xa6\x28\xd6\xab\x29\x3a\x91\x5e\x40\xd3\x48\xc4\x87\xed\x72\x2d\xaf\x13\xad\xa1\x88\xa1\x96\xe1\x8c\x23\xe5\x56\x3f\x3d\xe8\x8f\xed\xa1\x29\x37\x4b\xa4\xd4\xa3\x17\xed\xc5\x98\xed\xcf\x1a\xc3\x50\x7f\xd2\x5c\x2d\x66\xb3\xbc\x59\x6f\x7b\x6b\x93\xcd\x50\x38\x0a\x16\x56\x2c\x01\x6a\xde\xaa\xd8\x95\x65\x5a\x31\x6a\xe2\x7c\xce\x36\x57\xe1\x28\x8b\xcc\x78\x3d\x15\x91\x93\x83\x32\x84\x83\xee\x88\x84\x62\xab\x38\xac\x35\xc3\x6e\xa6\x11\xce\x1b\x8b\x74\x77\xb1\xcc\x5a\xbc\x90\x75\xe6\xcb\x51\x81\x1f\x5a\x03\xae\x98\x49\xb8\x09\x71\x36\xc2\x6d\x7b\xe3\xfd\xb9\x33\x43\x21\xdd\x3a\xe7\x4e\xbf\xf8\x50\x78\x00\x16\xe8\xd7\xb8\xf1\x1b\xcf\x68\xa2\xa0\x73\x0c\x4f\x08\x2f\x68\x50\xa1\x91\xc2\x29\x82\xa8\xd3\x0c\xd6\x39\x06\x42\x05\x71\xbc\x88\x69\x56\xc7\x3a\x64\x01\x83\x35\xa0\x70\xb4\xc2\x33\x8c\x02\x90\x42\xc4\xab\x0b\xa4\x8b\xce\x0e\x01\xa0\x2f\x62\xc6\xee\xa6\x97\xe0\x66\x39\xf1\x5a\xd4\x7c\xef\xf2\x88\x2e\xb6\xfb\x30\x3f\xe5\x2c\xa0\xa4\x51\x83\x35\x97\x85\x59\x6d\x91\x60\xea\x63\x6b\x10\x9a\xc5\xa5\x82\x1b\x85\x19\x3a\x87\x22\x88\x6f\x8b\x89\x79\x93\x9f\x08\x99\xd5\xa2\x59\x8b\x0d\x98\x90\xae\xb5\x9d\x9e\xb3\x8a\x36\x9a\x74\x45\x99\x4a\x66\x3a\x9f\x33\x2a\xd6\x74\x18\x5d\x1e\x8d\x83\x8d\x6b\xa6\xf6\xff\x48\x9b\x6b\xe7\x70\x3d\x97\x8a\xa5\xed\x92\x3e\xba\x1c\x84\x49\x23\x21\xb5\xe4\x42\x6f\x88\xc5\xca\xa2\x9d\xec\x0f\x16\x89\x54\x89\x87\xe3\x94\xd1\x1f\x15\xe3\x62\xaf\x3e\x86\xa5\x19\x67\xbb\x85\xa6\x33\x1a\x94\xd3\xea\xb2\x39\x1a\x12\xba\x9d\x89\xf7\x57\xbd\xea\x00\x4c\x19\xa8\xb5\xad\xd4\xa0\xc9\xc1\xa9\x65\xaa\x7a\x91\xdd\x40\x52\xea\xcc\x38\x91\xff\x1b\x83\xea\x07\xc6\x09\x7c\x8d\x8f\x6f\xde\x56\x40\x01\x2f\xd3\x0e\x45\x04\xbe\x02\xf8\x15\x40\x0a\x80\xef\x9b\xff\x2e\x3a\x33\x84\x80\x16\xae\xde\x5d\x93\x67\x69\x91\x15\x79\x44\x8b\xd7\xa2\xe2\xf3\x9e\xee\x89\xf4\xa3\x3b\xe5\xf2\x27\xd2\xcc\x18\xec\x32\xbc\xac\x64\x22\x28\x66\xc6\xc4\x24\x0d\x16\xfd\x48\xc8\x01\x5d\xd7\x99\xa7\xe6\x2b\xd8\xd4\x2a\x8d\x16\x8e\xa4\x71\x7c\x03\x26\xf2\x19\x27\x3e\xff\xd9\x39\xb1\x24\x45\xce\x46\xcb\x3f\xf3\xe7\xcd\x73\xa6\xdb\x1b\x11\x77\xbc\x48\x30\xe8\xbe\xc4\x85\xb7\x27\x5c\x3a\xd9\x41\x5f\x18\x71\x37\xc8\xf8\xcf\x51\xc0\x60\x64\x18\xff\xa9\x85\x60\x64\x58\xff\x11\x81\x60\x64\x38\x5f\x3d\x7e\x40\x32\xbc\xbf\x34\x3c\x18\x19\xe4\xaf\x9d\x0f\x46\x46\xf0\x97\x73\x07\x23\x23\xfa\x0b\xa7\x83\x91\x81\xc0\x57\xc5\xcb\x04\xa4\xf3\xae\xd6\x39\x20\x1d\xda\x57\x9c\x1a\x54\x1e\x7f\x91\x6b\x50\x79\x58\x5f\xcd\x65\x50\x79\x38\x7f\xed\x66\x40\x3a\xbc\xaf\x4a\x32\xa8\x3c\xc8\x5f\x6d\x19\x90\x8e\xe0\xab\x55\x0c\x2a\x8f\xe8\xaf\x79\x0c\x38\x0f\x02\x5f\xc5\x60\x40\x79\x68\xe8\xa3\x13\x74\x5e\xf6\xd7\xed\x05\xa5\xc3\xf8\x6b\xe3\x02\xd2\x61\xfd\xf5\x67\x01\xe9\x70\xbe\x1a\xaf\xa0\x7a\xf1\xfe\x32\xaa\x80\x74\x90\xaf\x64\x2a\x68\xbf\x0b\xbe\x02\xa9\xa0\x74\xc4\xd3\xda\x21\x36\x20\x1e\x03\x5f\x09\x52\x40\x32\xbe\x0a\x9b\xa0\xd2\xd0\xbe\xd2\xa3\x80\x64\x98\xd3\x3a\x94\xa0\xd2\xf8\xcb\x67\x5e\xf3\xce\xe4\x97\x1c\x22\xbe\xfe\xba\xab\xf5\xea\xe8\xde\x53\xc5\x17\x5e\x1d\xfc\xf4\x6a\xf4\xd8\x8e\x47\xeb\xc6\xc3\x05\xbb\x7f\x35\xd4\x7f\x7e\x77\xad\x67\x2b\xce\x75\xdb\x1a\x3d\x5d\xab\xfd\xb3\x1e\x09\xfe\x80\x57\x43\x5c\xee\x27\x6f\x45\x7d\xb8\x00\xef\xfb\xe9\x09\x1b\xef\xfb\xe9\x99\xd3\x05\x3f\xed\x39\xe0\x0f\x78\x51\xc8\xb9\x8e\x3a\x8e\x59\x0e\x17\xc2\x51\xb5\xed\x8d\xf3\xc4\x9b\xc3\x0d\x84\x3c\xa5\xed\x8e\xcc\x7f\xc3\x19\x89\x4f\x1a\x60\xc7\xd1\xdd\xe1\xe2\xcc\x44\xf8\xd3\x0c\xb0\x9f\xed\x48\xf3\xe7\x0c\xb0\xd3\xc0\x77\x7f\x41\xff\xc4\x1d\xf5\x13\x1e\x62\xfe\xcc\xbe\xda\x1d\x11\xde\x5f\x08\x1f\xb3\xba\x78\x62\xb2\xfc\xb9\x4f\x2d\x7f\xc0\xbb\x7c\x2e\x77\xd6\xf6\x58\xf0\xfe\xe2\x83\x96\x82\xaf\xea\xac\x9f\xeb\xa4\xf2\x67\xf6\xd4\x2e\x97\xb4\xbf\xf8\xa8\xc5\xe0\x2b\x7a\xea\x67\x3c\x9a\xfc\x49\x9d\x75\x9c\x68\x3b\x5c\xf0\x9b\x9e\x42\x87\xe3\xac\xaf\x5d\xf1\x3d\x83\x5b\x53\xb7\x67\xd9\xc6\x8a\x6c\xcf\x80\xfd\xdf\xeb\x2b\x2f\x09\x79\xb8\xa0\x7f\xdd\xbe\xfa\x2f\x9e\x04\x4f\x12\xb4\xfb\x0b\xe1\x63\xfb\xea\x99\x48\xea\xff\xee\xb8\x3a\x3d\xbc\xbe\xbf\x00\xe7\x82\xe2\x4b\x87\x83\x7f\xb2\xce\xfc\x29\x7a\xee\xe3\xc3\xe2\xd3\x6d\x87\xfd\x05\xff\x83\x7b\xee\x97\x7e\x11\xc8\xe7\xc4\x5e\xa7\x1b\x3d\xfb\x0b\xfa\xbf\xa5\xe7\x7e\x18\xb2\x7d\x56\xcf\x6d\x5f\x9f\xb0\xbf\x38\x9b\x42\xbc\xab\xe7\x82\x9b\xfc\x43\x66\xcb\x1f\x96\xf0\xf8\x84\xe9\xf2\x64\x37\x73\x7f\xc1\x1e\xbd\xc5\x61\xad\xd1\xe6\xb7\xe3\x7f\xff\x4e\xfd\x9b\xfe\xe7\x0b\x75\xf8\xa6\xb3\xf9\xce\xf7\x0e\x89\xdf\xff\xf9\x34\xbf\x3b\x79\xeb\xc4\xfe\x02\xdc\xf5\x0a\x8a\x4f\x5a\x48\x9c\xbc\xbe\x62\x7f\xc1\x5f\xb2\x2f\xbc\x62\x5f\xef\x6d\x17\x7b\xf3\x7e\xb8\xec\xc7\x5b\xb9\xfb\xbf\x85\xa3\x77\x0b\xe8\x53\x53\xdb\xfa\x79\xc0\x37\x74\x6f\xc6\x8c\xf7\x9e\xec\x67\xe7\xec\x3b\x5e\x74\xf0\xe4\xab\xc4\x1f\x31\xdb\x76\xcf\x79\xff\x37\xfb\xb1\x66\x0b\x3e\x61\xfe\x64\x66\xf3\x36\xc7\xf7\x7f\x83\x0f\x35\xdb\x13\x00\xf1\xf1\x66\xbb\xb1\xd3\x7e\xe6\x17\x65\xef\xd9\x65\xbf\x4d\xf5\xf6\x6f\x64\x06\xdd\xcd\xbf\xf8\x93\x55\x67\xab\x4b\xd9\xcb\x55\x3a\x37\x09\xd1\xfe\xd2\x80\xa0\x84\x18\xff\xde\x75\x50\x42\xac\x8f\x50\x60\xd5\x38\xdf\x26\x6d\x60\x42\xbc\x7f\xd7\x30\x28\x21\xe4\x23\x14\x58\x22\xc1\xbf\x3d\x16\x94\x90\xe8\x23\x14\x58\xa2\xd3\x7a\x53\xe1\x72\x45\xd3\x6d\x4a\xd0\xbf\x9f\x14\x98\x12\xed\xdf\xec\x08\x4c\x89\xf1\x51\x0a\xae\x1d\xeb\x4b\xeb\x07\xa7\xc4\xf9\x28\x05\xef\x3b\xde\x97\xbd\x0e\x2e\xd3\xbb\x3c\x78\x60\x4a\x82\x2f\x4b\x1b\x5c\x26\xd1\x9f\xef\x0d\x3c\x57\x02\x5f\x36\x32\xf8\xac\x0b\x7d\x94\x02\x6b\x77\x5a\x87\xfa\x8c\x17\x9c\x56\xa2\x3e\xd3\x77\xa7\xb5\xa8\x4f\x59\x9c\xf3\x45\xc9\xc1\xb5\xe3\xfd\x41\x5b\x60\x4a\xc8\x17\x41\x05\xef\x3b\xc1\x17\xe8\x04\xa7\xe4\x8b\x3b\x2e\x55\x5e\xde\x46\x71\x70\x4a\x28\xb0\x44\x27\x95\xa9\xec\x33\x12\xd1\xbe\xd8\x20\x30\x21\xe6\x74\xb5\x1c\xd8\x95\x4e\xea\x53\x81\xa7\xda\x6b\x7e\x61\xfb\x15\x15\xaa\xb7\x7e\xa7\xf4\x91\x1a\xd5\x8b\xbf\xa7\xfd\x82\x75\xed\xc1\x9e\x6f\x90\xa5\x35\x46\x53\x08\x27\xb2\x02\x51\x18\x51\x53\xa0\xae\xf1\xb4\x26\x42\x5a\x25\x3c\x82\x0c\x54\xa0\xc2\x00\x80\x35\x05\x40\x0e\xab\x3a\xd0\x21\xd2\x44\x88\x01\x87\x58\x5a\xd4\xde\xbe\x50\x5e\xac\x1d\x3c\x0d\x74\x74\x5e\x96\xdf\x9d\x13\xbc\xfc\x92\x36\x91\xbe\xfc\x52\xab\xdd\xdd\x93\x55\xb5\x77\xc0\x30\xe6\x76\x67\xf3\xd8\xb4\xd0\x90\x4a\x22\x2a\xc3\x72\xd5\xad\x69\xf3\x7c\x2c\x39\x8e\x85\xa3\x35\x32\x5e\x69\xa5\x62\x73\x68\x99\xaa\x91\xad\x4b\x9b\x03\x7a\xd2\xee\x00\xac\xec\x3b\xff\x16\x39\xfc\xe9\xdd\xb2\x27\x79\x3e\x4b\x0a\xb8\xdb\x5f\xe4\x70\xad\x28\xf2\x91\x95\xee\x88\x04\xa8\x96\x9d\x6f\x37\x57\x91\x46\x7a\x10\xb7\x32\x68\x30\x1b\x6c\x8e\xba\x46\xea\xf5\xfc\x96\x66\x14\x4e\x23\x5a\xd2\xaa\x4e\xbb\xb9\x59\xc9\x8d\xa1\x48\x2f\x95\x65\xf2\x44\xd4\xea\x45\x3d\x91\x0a\xa5\x0d\x2e\x3d\xab\x15\x42\x6d\xc9\x45\xdb\x17\x37\xac\x44\x74\x74\x7a\x5c\xde\xcb\x5b\x4a\x2a\xa3\x61\x71\x52\x57\x17\x56\x6a\xb2\x4a\xc7\xf1\x52\xd3\xd2\xf3\x44\x39\x27\xd4\x17\x23\x10\x69\x0d\xa7\x06\x93\xad\x4f\x45\x2d\x6c\x46\xe8\x9e\x12\x76\x9d\x5a\xa3\x5b\x6b\x67\xa3\x35\x33\x3f\x0b\x47\x8b\x7d\x27\x57\x95\xf2\x74\x76\x54\x1f\xb4\x0a\x39\x37\xaa\xb5\xd4\x50\xbe\x24\xfc\xfd\x76\x7c\x40\x33\x71\x74\xb0\xb1\x74\xce\x1e\xd2\xa1\xfd\xe1\x54\x71\x6c\xa3\xe9\x51\xa3\x02\x1d\x0d\x4b\x05\x96\x6b\x45\x62\x8c\x9b\xac\xc7\x0b\xb0\xcc\x48\x20\x47\x06\x45\x21\x5d\xe6\xcd\x3c\x94\x44\xd2\x30\xb4\x65\xca\xdd\xbc\x3f\x25\x5a\x97\x66\x86\x2a\x9d\xd2\x93\xba\xfe\x63\x89\xfe\x6e\x3a\x95\xef\x85\xfc\xe5\x20\xfc\x3d\x23\xe5\xd6\xff\x24\x0f\xf6\x89\x4e\x2d\xc6\x72\x59\x6e\x12\x2d\xca\x8b\x71\x29\xcc\x58\xc9\x7c\x68\x05\x51\x79\x69\x38\x70\xa8\xe7\xe2\xad\x51\xa9\xd1\xb5\xa7\x95\x50\x75\xf3\x50\xbc\x5e\x03\x5b\xc3\x67\x1b\x6c\x1c\x90\x5e\x81\x97\x96\x62\x14\x14\x9d\x84\xdc\x9d\xa9\x10\x41\x58\x13\x85\x56\x9f\x1d\x65\x07\x23\xb1\x84\xb8\x41\x94\x99\xad\x9b\xf3\x69\x01\xc7\xf9\x48\x78\xff\x99\x9f\x93\x59\x96\x4e\x4f\x81\x7f\xa6\x7c\xe1\xb1\x68\xf6\x6e\xc8\xe7\xb7\x9f\x84\x5a\x59\x41\x42\xfd\x61\x57\x2e\x12\xa0\xd5\x6a\xa8\x9e\x54\x63\xa5\x05\x5f\x0a\xcf\x87\xc9\x89\xca\xd4\x62\x90\xc3\x69\x26\x65\x78\xa7\xdc\x03\xcb\x17\x01\x9a\x08\xaa\x7d\x49\x4a\xb1\xca\x52\x11\xe4\x0b\x7d\xee\xb7\xdf\x67\xca\xc7\x0f\x14\xd8\xbd\x22\xdf\xdf\x87\xb1\xd9\xf5\xd9\x52\x0a\x22\x6b\xba\x16\x0d\x65\x6b\x3e\x7a\xd1\x77\xde\x7f\xf1\x2c\xf4\x91\xad\x02\xf3\x4f\xcf\x83\xf1\xf7\x6c\xf1\x1f\x6d\x8a\x6b\xa1\x71\x7d\x95\xe8\x1a\x76\x6e\x50\xb7\xd3\x10\x98\x52\x5b\x5e\x2d\x9a\x09\xa5\x14\x37\x1a\x7c\x56\x75\x1b\x08\x32\x21\x35\x89\xe3\xb3\x10\xbd\x28\xe3\x48\x79\xe0\xa4\x2b\x2a\x1d\x16\x52\xa1\xc2\x7c\x91\x93\x98\xd6\xb4\xdd\x28\x77\xd9\x25\x48\xc3\xde\x8a\x85\xb1\xf9\xdf\x7f\x6f\x92\x6a\xa6\x65\x92\xfd\xe9\xfb\x7b\xfe\xf5\x6a\x17\x20\xb8\xf4\x7a\x80\xf3\xf8\xcd\x30\x3c\xad\x8a\x0a\xe2\x35\x81\xc3\x02\xcb\xaa\x88\x11\x15\x86\x11\x34\x85\xe8\x2c\x0d\x19\x95\xf0\x2c\x51\x31\x54\x89\xc2\xab\x40\x43\x80\x08\x48\x10\x11\x87\x15\xc8\x22\xa4\x40\x0f\xbf\xe9\x67\x76\x42\x8e\xf0\x5b\xb8\x89\xdf\x02\xc3\x5c\x7e\xe5\xd2\xfa\x2e\xfb\xe6\xcb\x41\x79\x3e\x9b\xe1\xfb\xc4\x60\xfa\x23\x2b\x25\x54\x13\xc3\x58\x98\x74\x55\x06\x15\x9b\x6e\x32\x93\x59\x35\xea\xc2\xbc\x6e\xb4\x23\x38\x3a\xe5\xb2\xdc\xc6\x11\x8e\xf0\x3b\xe1\xeb\xfc\x77\xf8\xfd\x20\x1e\x3c\x83\xdf\x15\x66\x4c\x8e\x3c\x32\xb1\x97\xb7\x94\x31\xfb\xb8\x51\xe1\xcb\x03\x1e\x22\x73\x30\x87\xe1\xcc\x34\xaa\xeb\x98\xe4\x61\x6e\x39\x9a\xae\x84\x91\x18\xb1\x47\xa0\x9c\x86\xa9\x56\x3e\xa3\x99\x53\xad\x1e\x42\x74\xd2\x89\xe6\x60\xdd\xd4\xcd\x55\x38\x64\x44\x78\xb9\x1c\x5f\x14\x1c\x79\x0c\x47\x91\xe4\xb8\x96\x2b\xcd\x07\x1f\x82\xdf\x0f\xae\x77\xd6\xf8\xd9\x9b\x1c\xfa\x23\x7e\x18\xb3\xd2\x11\xe9\xfb\xf1\xfb\x49\xfe\x89\x20\xfc\x8f\xf0\xfb\x27\x9d\xdf\xa5\x1f\x8b\x3f\x7a\x22\x16\x99\xde\x92\xcf\x6f\xbf\x9f\x6d\x7d\xf1\x03\xd7\x3f\x29\x90\x6d\x4e\xaf\xc9\x77\x0b\xbf\x1f\x95\x75\x8d\x9f\xa9\xdc\x81\x9e\xb7\xd6\x3d\xd0\xdb\x42\xf3\xdd\xf8\x1d\x84\x7f\xc2\x0a\xc6\x7f\x8b\xdf\x13\x92\x1f\xb7\xb3\xe3\x44\xd5\x6e\x4e\x49\x35\xd6\x14\x26\x6c\x5a\x14\xc7\x2c\x53\x5b\x65\x30\x2a\x2e\x15\x90\x98\x2a\x65\xd9\xac\xf5\xba\x60\x4c\x13\x0e\x36\xd1\xac\x45\xe6\xa9\x55\xbd\xa1\x85\xf4\x62\x98\x4f\x25\xad\xb2\xdc\x94\xf9\x79\xc5\x6c\xb4\x64\x32\x2c\x2d\x62\xd1\xd2\xe7\xe2\xb7\x8e\x21\xd2\x91\x0a\x04\x46\xd7\x34\x95\x63\x88\x40\x68\x41\x10\x38\x85\x88\x0c\x4b\xa0\xa8\xe8\x3c\x83\x08\x2d\x20\x15\x8a\x1c\x54\x08\x27\x40\x4d\x03\x9c\x0a\xd6\x0d\xbc\x77\xc2\xa1\xd7\xc5\xdf\xdc\x2d\xfc\x66\x80\x70\xed\x9d\xd2\x9b\x9b\x27\x1b\x3f\xcf\x46\xdf\x31\x5f\xd7\x1f\xa1\xd5\x26\x10\x0e\x8a\xc6\xfd\xde\x2c\x3d\x9b\x9f\x78\xd7\x51\x34\x9d\x4f\x09\x95\xa6\x52\x8b\x34\xd2\x46\x78\xa1\x0b\x4a\xc3\x8d\x44\x32\x96\x39\x9f\x8b\xad\xb1\x92\x55\x07\x30\x4c\x8b\xdc\x64\xd1\x2e\xb4\xf2\xdc\xac\x1f\x8f\xb5\x4a\x59\x9c\x60\x14\x88\x13\x8d\xc9\xaa\xd1\x9e\x60\x31\x9e\x4b\x0e\xd2\xb4\x2b\xc9\xb1\x62\x5f\x4e\xa6\x72\x83\x95\x34\xbf\x07\x8d\x8f\x57\x2b\x17\xd1\x38\x72\xf4\x1a\xc7\x20\xd1\x2c\x3c\xd8\x37\x7a\x18\x81\x27\xb6\x38\x37\xec\xf6\xf6\x7f\x21\xff\x40\xd1\xfc\xd1\x0c\x98\x38\xb2\xdf\xe7\xa1\x1d\x36\x9b\x91\xe1\x5d\xd1\xf4\x8f\x89\x56\x37\xf2\x5d\x8b\x56\xcf\xa2\xc9\x71\x83\x00\xd1\x58\x8e\x3d\xd0\x3b\xf2\xad\xe3\xcf\x75\x34\x79\x61\x34\xfa\x08\xff\x2d\x9a\x80\xfe\x22\xad\xb9\xa5\x78\x6b\x94\x0d\xc7\xc3\x0b\x17\x03\x59\x9e\x18\x7a\x2c\x06\x8d\xa1\xe3\x2e\xab\xcd\xb0\xc2\x8c\xec\xf8\x80\xeb\x32\xa3\x50\xae\x96\xef\x49\xae\xa5\x68\xb3\xba\xd5\xc6\x76\xbe\x3d\x1a\xdb\xa0\x36\x27\x25\x13\x03\xa9\x94\x0b\xe5\x4a\x6a\x77\x59\xcd\xc5\xa4\xcf\x45\x13\x95\xa5\x55\x51\x10\x30\xa2\xb1\x2a\x60\xa2\x31\x8a\x22\x62\xa4\x20\x4d\x57\x44\x5e\x11\x01\x47\x18\x46\x83\x1c\xe0\x75\x96\xf0\x3c\xc3\xf0\x00\x32\x1c\xe1\x55\x9e\x40\xc8\x01\x24\x78\x68\xf2\xaa\x68\x10\xdd\x44\x13\xe8\xf1\xbc\x7e\xf7\x64\xdb\xfe\xd9\x68\x30\xee\xeb\xfc\x1f\x19\x0d\x42\xb3\xa6\x1f\xcd\x7c\x47\xd1\xa0\x94\x68\x2d\xcd\xf8\x92\x8e\x66\xf4\x4c\x7b\xd9\x1b\x35\x72\x59\xbd\x3b\xea\x69\x69\x37\x9d\x6c\x36\x90\xd5\xad\x6a\xcb\x36\xc2\x33\x43\x8e\x16\x92\xad\x74\xa5\x94\x29\x0e\x54\x33\x67\x25\xd8\x3c\xe2\x8d\xf1\x60\x5a\x4f\xf2\xbd\xfe\x74\x11\x4b\x46\xd2\x02\x13\x4a\x9a\xcb\x9e\x22\x95\x5e\x16\x0d\x1e\xcf\xff\x01\xa2\x31\x23\x76\xe8\x0f\x7f\x36\xf5\xbe\x68\xec\x75\xfc\x03\x45\xa3\xe7\xb3\xb9\x3f\xd3\xfc\x2e\xfd\x58\xfc\xb9\x2b\x5b\xea\xc7\xef\x4f\x8c\xb6\xf2\x15\xa6\xc9\x3e\x8a\xdf\x3f\x53\xb6\xfe\x2c\x7e\x1f\xad\x1d\x83\x44\x63\xc7\xd9\x54\x4f\xe1\x03\xbd\xbb\xa2\xc1\x17\x46\xa3\x8f\xf0\xdf\xe2\xb7\xd4\xee\x67\xd4\x66\xb6\x95\x1a\x0b\x63\x33\x93\x68\xb7\xe6\x6e\x28\x8a\xe3\x60\x04\x06\x9a\xa6\x4c\x8d\x48\x9e\x49\x9b\xee\x24\x94\x2a\xa5\x58\xad\x3b\x4c\x4b\x56\xa8\xbc\x54\x97\x5d\xa5\xcb\xcc\x26\x99\x51\x85\xab\xe9\x93\x44\x01\xc9\x39\x55\x36\x57\x3a\x4b\xf4\x4c\xdc\x89\x7c\x36\x7e\xeb\x40\xe7\x74\x55\xdb\x14\x98\xb2\x9c\xa0\x60\x9e\x66\x74\x91\xf0\x04\xa9\x1c\xcd\x0a\xa2\xc6\x2a\x1a\x23\x22\x11\xb3\x50\xe4\x05\x28\x0a\x02\xad\x28\x3c\xcd\x02\x85\x25\x02\xc7\xbd\x6d\x0e\x32\xc0\x17\xe1\xf7\xcd\xdd\x58\x96\xe1\xae\xbc\x40\x7f\x77\xf7\xa4\xc8\xed\x59\xfc\xbe\xb9\x1b\xfb\x28\x7e\xd7\x40\xbe\x58\x0f\xec\xb3\xc7\x0e\x79\x84\xdf\xd9\x4a\xab\x14\x8d\xc2\x50\x2c\x51\x12\x1c\x3b\x99\x5d\x18\x7c\x45\x37\xf3\x61\xcd\x14\x5c\x34\x92\xd4\xe6\x30\x66\x1a\x35\x26\x1d\xd2\x78\x79\xd5\x85\x35\x7e\xd8\x15\x0d\xd0\x6f\x14\x1c\x1d\x8f\x0c\xab\x55\x57\xd2\xa2\x26\x19\xa5\x48\x7b\x99\x72\x4c\x54\x8d\x70\x6a\x76\x7e\x57\xfc\x78\x1f\x7e\x1f\xad\x3a\x82\xe0\xe7\x95\xdd\xd8\xfb\xf0\xf3\x75\xfc\x03\xad\x1f\xde\xc5\x3c\xc1\xf0\xb1\x5a\x02\xa2\x17\x73\x3c\xe8\xcf\x5b\x51\xee\xc1\x9f\x67\xe2\xdb\xe0\xf2\x0d\x4b\x59\xee\xaa\x7c\xb7\xe2\xc7\x20\x63\xe9\xda\x6e\xe2\x5d\xf8\xf3\x42\xfc\x7b\x84\xff\x16\x7f\xdc\x74\x4f\x4a\x65\x9b\x6c\xae\x1d\x5b\x2e\x1d\x75\x96\xc8\x8e\xd3\x21\x95\x11\x69\x7d\xc9\x4c\x5b\x91\x05\xa9\x15\x48\xba\xaa\x9a\x1c\x63\x55\x0b\xb1\x7a\x75\xd2\x88\xd1\xd9\x4a\xbe\xc5\x2f\xc4\x09\xce\xf4\x7a\x75\xc7\x84\x20\x9a\x96\xe2\x66\xca\x58\xea\x6e\x2e\x39\x9c\xcf\x3e\x3b\x7e\xa4\xd7\xb1\x16\x00\x34\x2b\xe8\x02\x0b\x55\x8d\xd3\x39\x40\x23\x5e\x57\xa1\x40\x14\xc8\x2b\xea\x3a\xb6\x64\x58\x82\x30\x2d\x02\x9d\x16\x10\x56\x18\x4c\x63\x2c\xd2\xbc\xc0\x0a\x9b\xda\x1b\x7e\x17\x3f\x06\x3c\xf8\xf3\xc8\x6e\x22\xcb\x20\x20\x5e\xc1\x1f\x74\xf8\xdd\xae\x6d\x3d\xb3\xe7\xb2\x0f\x2e\xc7\x1e\xd9\x4c\xfc\xb4\x62\xa0\x42\xbf\xe6\xc2\xd0\x91\x28\xc9\xbd\xbc\xa5\xd4\x64\xcc\x94\xf5\x22\x9c\x92\x08\xa8\x96\xd3\xe5\x56\xd3\xc4\x56\x68\x30\xd2\x08\x1b\x89\xf5\x84\x09\x90\xc7\x68\x02\xd9\x92\x60\x95\xf3\x0b\x58\x16\xa7\xae\xa9\xea\x63\xab\x69\xa3\x74\x41\x9d\x18\x73\xb7\x8b\xed\xaa\x38\xe0\x33\xa3\xdc\xb2\xaf\x61\x11\x25\xb9\x72\x37\xf7\x21\xf0\xe3\x2a\xdd\x66\x99\x97\x91\x15\xcb\x82\x6c\x29\x34\x6f\x55\xa2\xe2\xaa\x39\x6b\xd6\xab\xcc\xc2\x28\x1a\xad\x69\x45\x81\xb1\xd9\xa8\x94\x25\x82\xb4\x9d\xfe\xbb\xec\xa1\x3f\xce\x86\xf3\xd1\x64\x79\xa8\x32\xa5\x69\x8b\x16\xdd\x07\xa6\x8c\x07\xc3\xf7\xf5\x94\x11\xf3\x34\xf1\x7e\x0b\xed\x1c\xfd\x94\x96\xa8\xaf\xb4\x28\xd7\x57\x68\x10\xb9\x24\xc9\x3b\xfb\x94\xa4\x1f\x52\x5c\xb6\xfe\xe8\xfb\x39\x5f\xf0\xf7\xa7\x74\x0a\xdf\x3f\xc6\xdf\xaf\xc8\x77\x0e\x92\xe2\xcf\xf5\xef\xbb\x0d\xb2\x27\xfa\xf7\xc8\x3f\x1e\x9c\x7f\xd6\x70\xcc\xe2\x8d\x10\xd1\x83\x7f\xf8\xe9\xf7\x40\xbb\x99\x07\xd9\x51\x7e\xa6\x94\xce\x2e\x7f\x3c\x98\x32\x26\xa6\x16\x17\xc2\x0d\x8e\x4d\x96\xf3\xf2\x30\xde\x23\xda\xa4\xcf\x57\xda\x10\x75\xe5\x42\x72\x69\x97\x2a\xe6\xd4\x6e\xf6\x62\xcb\x9e\xcc\x24\xeb\x49\x9a\xa7\xb5\x45\x68\xd4\x23\x33\x67\xc0\x2d\x27\xd9\x28\x1d\x99\xb8\x45\xba\x6a\x4d\x5a\xab\x4c\x1e\xda\x8c\xa3\x0f\x13\xd2\x27\x17\xbd\x70\x98\x15\xb0\x00\x21\x51\x05\xc4\xea\xaa\xa8\x72\x1a\x42\x2a\x52\x31\x51\x04\xac\xa8\x04\x03\xc4\xab\x50\xc1\x98\x83\x0a\xe2\x38\x85\xc6\x02\x12\x18\x11\x62\x20\x88\x2a\xd2\xa0\x07\x53\xcc\x8b\x60\x4a\xbc\x0d\x53\xc2\x95\x5f\x62\xdd\xdd\x3d\x39\xe3\xf2\x2c\x4e\x25\xcf\x8d\xdb\x23\xbf\x7d\x78\xdc\x96\x86\xe5\x58\xb0\x71\x24\x09\xb9\xe6\xfc\x68\xc6\x3f\xc2\xa9\x84\xdc\x9c\x8c\x65\xb1\x90\x29\x2c\x70\x8f\xb7\x22\xbd\xb2\xc8\x71\x12\x1b\x69\x8d\x0a\xa1\xe5\x34\x9b\xcf\xe5\x5c\x55\xca\x0e\xb3\x4e\xa6\x4f\xe7\x20\x11\x4b\xd5\x61\x64\x26\xad\xa6\xf3\x41\x57\x8e\xce\xba\xb4\x31\x17\x26\xcd\x76\x84\x1e\x24\x5d\xd2\x9a\x0b\x13\xcb\x5a\xa9\x25\xe9\x67\xc4\xa9\xb3\xeb\x86\x1f\x83\x53\xea\x39\xfa\x9f\x8e\x53\x4f\xf8\xd3\xe6\xf3\xd1\x38\xf5\xac\xbf\x3f\x88\x53\x4f\xf6\xef\xbb\x42\x8a\x27\xfa\xf7\x49\x9c\xaa\x1d\x52\x77\x4f\xe1\x54\xab\x4c\x26\x83\x2a\x60\x2d\x14\x9f\x24\x27\xdd\x44\x3c\xc9\x98\x83\x58\x37\x6e\xb4\x10\xca\xb0\x0e\x98\x2f\xe1\x5c\x9a\xd6\xa6\xf3\x49\xb1\xb5\xaa\x23\x18\x29\xd4\x12\x42\xac\x80\xa2\x15\xa9\x94\x09\xc5\x70\x36\xb6\x1c\x6b\x83\x24\x2e\x11\xc8\xf5\x63\xcb\x89\xd1\xcf\x2f\xa4\x4f\x0e\xa7\x58\xc2\x22\x24\xea\x40\xe3\x45\x4d\xe1\x20\x51\x59\x1d\x29\x88\x61\x04\xa4\xf0\x40\xa5\x19\x91\x65\x18\x01\xb0\x1a\x8d\x58\xa4\x11\x9d\x86\x0a\x42\x08\x12\x51\x41\x50\x43\x9c\x42\x3c\x9c\x62\x5f\x82\x53\x47\x3f\xbb\x77\x19\x89\xc4\x2b\xbf\x78\xb9\xbb\x7b\x72\xee\xf1\x59\x9c\x4a\xf9\xfa\xfe\xc7\x6d\xc7\x69\x89\x31\x9c\xb7\x8f\x3c\xf6\x08\xa7\x92\xa5\x78\xaf\xa0\x66\xf8\x74\xae\xd8\x5a\xe8\xe5\x46\x24\xb4\x28\x40\x46\x1e\x14\x63\x93\xc1\x6c\x56\x4c\x84\x93\x63\x41\x6e\xc4\xaa\xa9\x5c\x75\x9c\x4c\x1a\x6c\x6e\x62\x33\xe1\x8a\x4d\xd2\xd9\xda\xa2\x60\x30\x93\x44\x65\xd2\x8a\xa7\x93\x86\x64\x65\x78\xce\x8e\xb7\x4a\xb8\x28\xbf\x72\x3b\xee\x75\x38\x75\x76\xdd\xf0\x63\x70\xca\x5f\x13\xf2\x1a\x9c\xfa\xc4\xed\xdd\xcd\xe7\x51\x9c\xfa\x6c\x7f\xff\x5c\x9c\x8a\x1f\xa5\x6b\x7f\x30\x4e\x15\x3c\x25\xa4\x67\x71\x4a\x93\x1a\x32\x37\xb7\xad\xc1\x5c\xec\xc7\xc5\x78\x2b\x89\x64\xd4\x54\x2b\x25\xa1\x30\xa9\x84\x04\x41\x11\x88\x39\x2f\xb7\xf2\xb9\xee\xa2\x30\x50\x49\xb6\xbb\x9c\xcc\x74\x31\xe3\xb2\x03\xb7\x2a\xf3\x59\x62\xb5\x33\xe3\x6e\x6d\x40\x52\xd1\xae\x6d\x8f\x9c\x7a\x2f\x62\x09\xa5\xcf\xde\x76\x62\x14\x9e\xe7\x31\xcd\x31\x0c\x64\x74\x15\x61\xa0\xd1\x2c\x24\x84\x16\x00\xcf\x12\xa2\x22\x01\x63\xcc\x11\x45\x03\x18\xa9\x00\x13\xa4\x0b\x1c\xcd\x89\x44\x00\x3a\xd6\x00\x2d\xea\x6f\x9b\x97\x04\xc1\x17\xc5\x53\x37\x8b\x10\x79\xc0\xf3\x97\xb7\x9d\x76\x77\x4f\xce\xc2\x3f\x8b\x53\x57\xca\x10\xbd\xf5\x74\xf0\x3c\xc8\x91\x6f\xe9\xbb\x79\x39\x22\x65\x79\x75\xd5\x8a\xcf\x2a\x91\x9e\x56\x27\x31\x56\x57\x9a\x85\xe4\xb4\x19\xc7\x74\x34\x36\xc9\x8e\xe3\xba\x1a\x2a\xa5\x4d\xcb\x28\x66\xdd\x30\xcd\xb4\xea\x46\xad\x9c\xc8\x2e\xf5\x2e\x23\x08\xf1\x4c\x2e\xe3\x28\xf9\xb4\xdc\x1d\xc5\x9d\x68\xba\xef\x76\x87\x8c\xde\x47\x73\x3b\xbc\x0e\xd3\xef\xc0\x9c\xa4\xdf\xc7\x0f\xf7\xfd\x73\xaa\xf7\x09\x80\x39\xc7\x25\x18\xfe\x32\xad\x47\x31\xe7\x85\x39\x9e\xdc\x39\xfa\xc1\x30\xe7\xf0\xfc\x8f\xce\xe1\xf9\x3f\x11\xe9\xe7\xcd\x31\x9e\xc3\x9c\xd8\x73\xfd\xfb\xae\x2c\xf1\x89\xfe\x3d\xc2\xac\x20\x98\xe3\x1e\x95\x35\xf8\x97\x37\x8f\x60\xce\x47\x4d\x0e\x9f\x89\x39\x9a\xa8\xf1\x8a\x00\x79\x0c\x30\xa3\xf2\x2c\xe0\x19\xa4\xb1\x82\x4e\x18\x46\xc7\x00\xe8\x22\xd1\x21\xe4\x21\x60\x54\x1a\xb0\x02\xc3\x62\xa8\x42\x01\x8b\x88\xe7\x04\xc0\xe8\x1a\xa7\x79\x98\xf3\xaa\xad\xa6\x9b\xa5\x0e\x6b\x51\x2e\xc7\x46\xbb\xbb\x27\xef\x3a\x79\x16\x73\xae\x94\x3a\x04\xc3\x9c\x43\x4e\xe3\x3c\xe6\xe4\x52\x11\xc1\xc9\x90\xe1\xa2\x3a\x89\x17\xb2\xc5\x54\xb6\x1f\x01\x66\xca\x55\x75\x3b\x61\x47\xe7\x53\xdb\x49\xf5\x9c\x5e\x9d\x64\x92\x95\x39\x9d\x8a\xb2\xe3\x51\x94\x74\x51\x26\x11\x2b\x64\xc7\x7a\x2d\x9a\x55\x69\xc6\xe4\x92\xa4\xea\x2c\xd2\x8e\x12\x8e\xda\xc9\x74\x3c\xdc\x8c\x95\x7e\x4a\xcc\x39\x8b\xe7\x3f\x06\x73\xfc\x8c\x7e\x0c\xe6\xbc\x38\x1f\xe7\xff\x3c\x8d\x39\x1f\x98\x2f\xfc\x80\x7d\xa3\x77\xa5\xe8\x4f\xf4\xef\x93\x98\x63\x7a\x4a\x1c\xe4\xf1\xd3\xbf\x13\x73\x3e\x6a\x72\xf8\x4c\xcc\xe1\xf1\x3a\xd0\xe1\x05\x82\x69\x01\x40\x8d\xf0\x18\xd1\x8c\xa8\x8a\xac\xc6\xb2\x84\xd3\x58\xa8\x33\x3c\x14\x20\xcd\x03\x84\x58\x01\xd2\x9c\x86\x19\x44\x2b\x34\x52\x78\x5e\xd5\x18\xd5\xc3\x9c\x57\xed\x1b\xdd\x2c\x8f\xe7\x21\xc3\x5d\xc3\x1c\xef\xee\xc9\xbb\xac\x9e\xc5\x9c\x2b\xe5\xf1\x1e\xe6\x04\xcf\x4f\x9c\xc7\x1c\x24\xd4\xdb\xe3\x99\xd0\x16\x31\xd3\xcc\x89\xdd\x19\xdf\x5b\xe6\xb2\x2e\xad\x44\xec\x36\xe7\x64\x9c\x78\xb9\xc6\x26\x32\xcd\x96\xbb\x68\xd1\xb9\x81\xe4\x8a\x69\x51\xce\xdb\x95\x72\xdb\x84\x39\xd0\x1f\x2e\xc4\x78\x3c\xe1\x46\x67\x6e\x3c\xde\x36\x84\x58\x6f\x31\x9b\xc4\x96\x38\xf2\x73\x62\xce\x59\x3c\xff\x31\x98\xf3\x6c\xee\xe5\x3c\xe6\xfc\xe0\xdc\x9a\xff\xf3\x0e\x73\x7e\xa2\xdc\xdf\x07\x60\xce\x71\xf9\xda\x0f\xc6\x9c\xae\x57\xaa\x79\x90\xc7\x4f\xff\x4e\xcc\xf9\xa8\xc9\xe1\x33\x31\x07\x00\xac\x88\xaa\xae\x12\x5a\x61\x55\x16\xb2\x50\x13\x14\x85\x47\xbc\xa0\x69\x40\x64\x15\x4d\x51\xa0\x8a\x58\xc0\x23\x08\x34\x45\x61\x14\x0c\x88\x2e\x0a\x02\x02\x3a\xcf\x60\x86\x5d\x23\x06\xfb\xba\x03\xbe\xcc\x2d\xcc\x41\x0c\xa0\xe9\x8b\x98\xb3\xbb\x7b\xf2\xd6\xc3\x67\x8f\xf8\x9e\xcd\x89\x7b\x9f\x27\x8e\xf8\x32\x87\xea\xd5\xa3\x71\x70\x38\xe2\x9b\xad\x2b\xa9\x54\x08\x66\x89\xb1\x5a\x74\x4d\x35\x96\x62\xf9\x4c\x72\x19\x71\x01\x17\x4a\x8a\xb4\x09\x43\x65\x86\x16\xd2\xe2\x2a\x3f\xa4\xf5\x6e\xba\x41\x9b\xba\xc9\xc4\x53\x56\xb6\xee\xd0\x93\x3a\x0c\x45\x6b\x63\x1b\xd2\x10\xd3\x11\x24\xe5\xf8\x64\xc6\x66\xcd\x48\x56\x4a\xbd\xee\x88\xef\x51\xa3\x00\x47\x6c\xfb\x85\x83\x7d\x2f\x7c\xee\x39\xe2\xf4\x12\xfe\x17\xe6\x9a\x1b\x25\xda\x9b\x29\xe4\xd5\xc7\x52\x2f\xf0\xbc\x8e\xbb\xaf\xe6\xff\xde\x1e\x17\xf9\x1f\x84\xf8\xe4\x23\x5c\xbb\xae\xf0\x95\x80\x1f\x7f\xce\x96\x80\x47\x9f\xb3\xd5\x56\xd6\x77\xc7\xc1\xef\xb1\xd5\x2b\xfa\xaa\xa0\x06\xe3\xbf\x2b\x01\xaf\x3b\xdd\x3e\xaa\xb9\x7c\xb6\x98\x88\x6a\xf3\x5c\xbf\x6f\x59\x7a\x2a\xc1\x54\x4d\x56\x67\xb0\xde\xe4\x92\xba\x32\x37\x99\x1c\xdd\x6c\x87\xa4\xa1\x82\xb5\x90\xae\xd6\x8c\xae\xdb\x58\xe1\x71\xb3\xc9\xa6\x2b\xa3\x59\x53\xa9\xdb\xad\xa4\x23\xad\x2c\x75\x32\x33\x54\xd9\x91\xba\x9f\x5c\xb3\xc0\x0a\x3c\x2d\x0a\x04\xb0\xba\xae\xac\x03\x22\x1a\xa8\x1c\x0d\x75\x01\x62\x4d\xe1\x68\x80\x74\x4e\x83\xb4\x4a\x43\x05\x08\x18\x20\x9e\x13\x44\x8d\x56\x08\xa3\x09\x1a\x26\xde\x81\x1f\xf6\x75\x47\x88\xd9\xdb\x78\x45\x83\xcb\x7b\x41\xbb\xbb\x27\xef\xd6\x7d\xf6\x08\xd2\xd9\xfd\x0a\xef\xf3\x6a\xbc\x3a\x3a\x52\x14\x1f\x0b\xb6\x13\x63\xa5\x29\xb4\x48\x7b\x10\xa9\xc2\x72\x32\x95\x2e\x2f\x17\x0d\xbc\xc4\x53\x46\xe7\x6a\x7d\x22\x81\x39\x1b\x02\xd9\x55\x3f\x2b\x2f\x0d\xd1\x4c\xe4\x1c\x81\x0c\xa5\x24\x3b\x8c\xf5\x7a\xb1\xf4\x22\x9a\x16\x92\xbd\x85\x92\x08\x35\xab\x61\x75\x54\x72\xa6\xf0\xbe\x5a\xb9\x87\xf1\x2a\xc8\x91\x9e\xa3\x57\x42\xf8\xe7\xc7\x07\x8e\xe4\xbe\x84\xbf\xbf\x7f\xef\x3b\x52\x74\x16\xaf\x9e\x3d\x06\xe3\xc7\xef\xbb\x8e\xc1\xbc\x9a\x7f\xe4\x7e\xfe\x47\x86\xfa\xe4\x23\xb3\xdb\xae\x78\x14\xaf\x62\xcf\xd9\xea\x18\x2f\xfc\xfe\xf1\x19\x7d\x75\x6d\x6d\x73\xc7\x91\xa5\x86\xb9\x9c\xce\x8b\xdd\x28\x6a\xf4\xb8\x51\x29\x5e\xac\xcb\x6a\x77\x98\xcc\xc6\xdb\x76\x7a\x82\xb4\xf0\xb0\x92\x67\x63\xd5\x58\x1f\x95\x66\x85\x9c\x53\xcd\x64\x69\xb5\xb5\x5c\x2d\xf8\x9a\xa4\x1b\xb5\x42\x42\xce\x99\x72\xca\x9c\x93\x64\xdc\x51\x38\xad\x28\x2e\xdb\xd1\x25\xaa\x7f\x76\x8d\x1d\xd4\x78\x06\x08\x9a\xca\x13\x91\x87\x48\x21\x84\x11\x31\x2f\xea\xbc\x00\x11\xaf\xea\xbc\xce\x60\x45\xd5\x59\x8d\xe1\x21\xd2\x14\x46\x45\x3c\xcf\xb3\x48\xd1\xa0\x28\x60\x8e\xb0\x2c\xed\xe1\x15\xf3\x22\xbc\xba\x59\xbb\x80\xbc\x37\x1c\x5e\xbd\x79\xf2\xfe\xf6\x67\xd1\xea\xe6\x0b\x94\x02\x65\xd6\x6f\xa1\x55\x56\x5e\x26\x87\x95\x12\xd7\x55\x58\x5c\x42\x64\x56\x18\xb2\xa3\x36\x3f\xac\x54\x53\x71\x34\xa8\xf4\x96\x8e\x15\x36\x96\x45\x30\x5d\x31\xc6\x38\x69\xa9\x1a\x23\x84\xb5\xac\x31\x45\xc3\xfa\x2c\x97\x68\xce\x2d\x7e\x39\x4a\xa3\x91\xb1\xd0\x62\xd3\x7c\x36\xd5\x30\x52\x62\x55\x29\x7d\x4c\x74\xf5\x12\xb4\x38\xf0\xff\x6c\xb4\x8a\x05\xe1\xff\x31\x68\x95\x93\x1e\x43\x8b\x57\xa3\xd5\xa3\x87\x46\x8f\x0c\x15\x0c\xad\xa2\x75\x79\x5b\x31\xf2\x39\x68\xf5\x83\xd0\x42\xfa\x80\xbe\x0a\x80\x56\x4e\x35\x45\xea\xe9\xd8\x28\x32\xeb\x8d\x63\x2e\x2f\xf0\x4d\xa3\x6d\x4e\xea\xe9\x5c\xb7\x39\x2d\x67\x92\x99\x65\x3f\x94\x4d\x85\x2b\xa8\x48\x32\x03\xd2\x5b\x30\xfa\x4a\x04\xd3\x0c\x9a\xd6\x1b\xc2\xbc\xad\x47\xfb\x76\xa6\x65\x4e\x71\x36\x0e\x0a\x2c\x70\x7a\x38\xd5\x87\x79\xf7\xb3\xa3\x2b\x9e\x45\x04\x2b\x18\xe9\x8c\xa2\x72\x88\xe6\x35\x15\x02\x16\x72\x1c\xa3\x13\x16\xb1\x90\x63\x69\xa2\x01\x4c\x63\x9d\xd6\x80\x28\x68\x22\xa3\x00\x05\xab\x9c\xc2\xeb\x8c\xca\xd3\xac\xea\xa1\x15\xfb\xa2\x6c\xe0\x1d\xd1\x15\x8b\xae\x65\x03\xbd\xbb\x27\xbf\x12\xf2\x6c\x36\xf0\x66\x74\x15\xe8\x85\x0d\xc9\x1b\xd9\xc0\x64\xb5\x96\x21\x6d\xdc\x6e\x86\x97\x96\x59\xd2\x56\x76\xa2\x05\x06\xc3\xf6\x64\xde\xab\xb5\x35\x64\x99\x6e\x4d\xe9\x8f\x4b\xa3\xec\x20\xd4\x2c\xb7\x84\x69\xcb\x72\x42\x52\x8a\x6e\x33\x93\x49\x8d\x29\xc5\x69\x24\xd7\xd9\x7a\xd9\xa9\xab\xb5\xda\x6c\x66\x72\x48\x9f\xc4\xb5\x55\xf7\xae\x0a\xef\xcf\xce\x06\x46\xce\x8f\xb3\x4f\xcb\x06\xfa\xf1\xf2\x2e\xfe\x1f\x93\x0d\xbc\x90\x9d\xfc\xb4\x6c\xe0\xa3\x2f\xc9\x3b\x32\xd4\x4f\xf7\xc2\x8a\x8f\x78\xa1\x60\xd0\x6c\x9c\xf4\x01\x7d\xf5\x08\xff\xdd\xeb\xe5\xf3\xa5\x31\x37\x1c\x0f\xf5\x70\xc6\xd0\x22\x4c\xc1\x69\xf7\x2b\x95\xfa\xc8\x8e\xc6\xcb\x43\x66\x6a\x10\x58\x9e\x16\x86\xd1\xd6\xb4\xca\x69\xf1\xfe\x92\x33\x8c\x15\x2b\xf5\xdb\x26\x99\x8c\xab\x9a\xd4\x54\x9c\x72\xb3\x57\x4f\x2c\xea\x8b\x72\x25\x14\xd2\x4d\x37\x64\xd5\x99\xc2\x67\x57\x86\x2b\x1a\x0f\x78\x01\x60\xc8\x20\x41\xd7\x89\x8a\x18\x91\x40\x5d\xc7\xb4\xa6\xb0\xaa\xc6\x41\x9d\x13\x14\xac\xe8\x0a\x82\x2c\x01\x2c\xe6\x68\x45\xa3\x15\x9e\x53\x74\x01\x33\x50\x61\xf5\xb7\x4d\x68\xf5\xaa\x17\x12\xdd\xdc\xbd\x12\x78\x20\x72\x17\xf1\x6a\x7d\x97\x7f\xf3\xfd\x16\xd5\xb3\xf1\xd5\x95\xdd\xab\xda\x39\x3f\x89\xdc\xf4\x29\x1f\xbd\xfd\x1a\x4a\x8e\x0c\x56\xdc\xb4\xdc\xad\x71\xf1\xc5\xa4\x30\x15\x5a\x78\x80\x22\x8a\xa6\x82\x88\xdb\x9d\xc9\x69\x10\xef\x4f\xed\xf6\x2a\x9c\xed\x26\xe6\x55\x5a\x6e\x8a\xb0\x25\xc0\x96\xad\x55\xea\x53\x3a\x5f\x2c\x83\xa1\xd2\xab\x48\x96\x9b\x28\x0d\x67\x95\x62\x4b\x5e\x72\xb3\x3c\x8f\xc6\x6c\xf4\x0e\x8c\x3a\xae\x0a\xb9\x88\x51\xd2\x73\x2f\xe5\xeb\x9b\x07\x9b\x5e\xf8\xdc\x83\x11\x2f\xe1\x1f\x6c\xc7\xea\x53\xb2\x4a\xdb\xcf\xf5\x79\xef\x07\x65\xb5\x6e\xed\x08\x3d\xf1\x82\xad\xe0\x18\xf0\x42\x5b\x3c\xc2\x7f\x8b\x01\xed\x5c\x48\x19\xb4\xe2\x85\xb2\x8a\xfb\xf6\x2c\x91\x18\x17\xe6\x0d\xa6\x99\x97\x94\x56\x76\x11\xd5\x22\x2d\x34\xa1\xd5\xf0\x92\x8d\x38\xb2\xd8\x8b\x87\xb5\x46\x31\xdf\xc8\x30\xb5\xa1\xe2\xf6\xab\x40\x4b\x37\xd8\x5a\x37\x93\x2d\x0f\xd2\x0a\xe8\xd3\x91\xdc\x54\x59\x91\x29\x4f\x3e\x3b\x66\x51\x91\x00\x38\x5e\x54\x59\x40\xab\xb4\x28\x28\x48\xe1\x74\x46\x87\x98\xc7\x34\xc0\x2a\xa4\xa1\x88\x01\xaf\xe9\x8c\x88\x91\xa0\x2b\x0c\x56\x79\x4d\x64\x54\xcc\x31\x58\x63\x09\x47\x34\x0f\x03\x5e\x55\xa9\x7d\x07\x06\x30\xf0\x72\xcc\xb2\xbb\x7b\xf2\x2b\x82\xcf\x56\xcd\x05\xc3\x80\xcb\x9f\xf7\x95\x61\xbe\xfb\xfb\xca\x1f\x39\x92\x9c\x0f\xda\xea\x32\xd5\x18\xe1\xe2\x4c\x76\x63\xc3\xb2\x20\x6b\xac\x16\x83\x39\x32\xa6\xfb\xd3\xac\x9b\x8c\x33\x26\x57\x4e\x80\xfe\xd4\x4e\xf7\x32\x93\x30\x93\x8b\xc0\x55\x99\x57\x62\x49\x3b\x34\xb7\xe6\x0c\x67\xf4\x33\x22\x6d\xf4\xfa\xc9\xc6\xa4\xba\xe8\xaf\x32\xb1\xde\xa0\xf0\x11\x98\x10\xa0\x7a\xee\xe9\x2a\x86\x17\xf2\x7f\x25\x26\x3c\x79\x8a\xe5\x69\x4c\xf8\x08\xfe\x37\xab\xcb\x6e\x60\x43\x00\x99\x5e\x8a\x0d\x01\xf8\x3f\x89\x0d\x65\x21\x9d\x68\xe6\x8c\xf8\x78\xd4\x47\x8b\x6c\x89\xab\xe9\x91\x24\x49\x96\xc4\x6a\x72\xa2\x59\xc8\x40\xe5\x85\xc6\x85\x6a\x65\x37\x85\x26\xcb\x56\x65\x32\x13\x57\x92\xa6\x02\x32\x9a\x2f\xf8\xb0\x93\xc9\xe5\x43\x2d\x6b\x39\xd3\x2c\xab\xb5\x80\x93\x81\xd0\x12\x96\x5d\xb6\x1d\xfb\x64\x6c\xa0\x35\x06\x22\x4d\x25\xba\xc0\xd3\x3c\xe1\x19\x51\x51\x31\x56\x58\xcc\x2a\x50\xc5\x90\x08\x84\xe7\x59\x44\x14\x96\xd7\x78\x4e\xc5\x82\x26\x0a\x90\x41\xaa\x26\x0a\x44\x81\x00\x13\xe4\x61\xc3\xab\x2a\xaa\x6f\xe6\xb3\x04\x9e\x15\xe1\x15\x6c\xf0\xee\x9e\xfc\x2e\xec\xb3\xd8\x70\x25\x9f\x75\x05\x1b\xae\xe7\x00\x4e\xe8\x1d\x61\x81\x30\xe1\x0a\x7a\x28\x21\x01\x82\xb5\x79\xa8\x57\xb5\xab\xd1\x94\x64\x11\x2d\xb3\x8c\x77\x49\x38\x33\x0b\x95\x6b\x79\x67\x82\x9c\x19\x1a\x57\xac\xac\x54\x8a\x37\x26\xf3\x78\x6a\xb6\x88\x26\x22\xd3\x21\x68\xf6\x2a\x8b\x82\x35\x4a\x84\xbb\x8d\xee\x28\x65\xcc\xfb\x3c\x86\x5d\x2b\xf7\x13\x62\xc1\xd9\xf9\xe5\x81\x4a\xea\x0f\x3c\x51\xe8\x09\x19\xa4\x92\xfa\x85\xf6\x79\x9f\x53\xfa\x69\xec\x73\x5f\x25\xf2\xeb\x4f\x81\x3e\x9d\x4b\x7a\xa1\x4d\x1e\xe1\xbf\xc5\x0a\x3d\x33\xad\x9a\xe1\x5e\x37\x9f\x1c\x99\x6a\xd1\xaa\xf1\x60\x6e\x48\x99\xa4\x59\x71\x7a\xad\xe4\x6c\x69\x87\x07\xf5\x98\x92\x99\xa2\x6c\x88\xaf\x4d\xa2\x73\x39\x52\x9f\x38\x91\x4a\x56\x28\xf5\xba\xca\x58\x8b\xb3\x35\xa7\x3a\x49\xf7\x66\x6c\xdc\x4a\x1b\x29\x27\x15\x1a\xb9\xad\xcc\x67\xbf\x5c\x54\x53\x98\xf5\xbc\xcf\x62\x22\x88\x88\xe3\x19\x9a\xe3\x59\x46\xc5\x1a\x0d\x55\x91\x25\x90\x51\x74\x15\x20\x56\x61\x68\x86\x10\x81\x21\x90\x85\x8a\x8e\x00\xc4\x9c\x26\x02\x56\x87\xca\xdb\x26\x88\xd8\xe4\x92\x22\xe5\x62\x2b\x99\xca\xd2\xd1\x14\x13\xcf\x97\xd8\x48\x33\x1b\xcf\xe5\x63\xd9\x78\xba\x96\x2f\xd6\xe8\x64\x8b\x69\xe7\xe2\x95\x64\x21\x5f\x8b\xca\x05\xa9\xd2\x40\xa5\x28\x2a\x34\xe9\xe4\xdb\xe6\xf1\xab\x10\x01\x01\x60\x2f\x6e\xd0\xef\x6e\x1e\xff\x4a\xb7\xe7\xa7\x89\xac\x90\x2c\xcd\x4a\x03\x25\x43\x27\x25\xa6\x51\xef\x97\xed\xcc\xa8\xdf\x04\x40\x4f\x08\x4e\x36\x85\x46\x40\x2e\xcf\xd3\x8d\xb0\xd4\x64\xa4\x3d\x3e\x6c\x3e\x57\x62\x07\xef\x13\x60\x2e\x18\x1c\xd3\xab\xcf\xe6\x71\x71\x83\x0f\x52\xab\x5f\x52\x8b\x55\x3a\xc1\xf5\x26\x66\x64\xd4\x4d\x24\x48\x57\x4c\x0b\x43\x56\x85\xb2\x59\x1b\x2e\x06\x43\x79\x98\x14\x9d\x49\xdb\x06\x22\x82\x71\xbe\x90\x6d\xe8\x24\x3c\x62\x07\xe3\xb8\x9b\x0a\x39\x29\x60\xc0\x49\xd6\x70\x39\x09\xa4\x97\x0d\x53\xe9\xb5\xb2\x0d\xce\x8a\xdd\x81\x0f\x27\x0e\x7d\x8a\x0f\x47\x3a\x1f\x72\xfc\x47\xf3\x57\xc4\x08\x47\x40\x16\xa4\x13\x4b\xb7\x37\xcf\xc3\x61\x0b\xe0\xe5\xd8\x82\x62\x3e\xb9\x98\x65\xa3\xcb\x02\xe7\x46\x64\x35\xea\xe9\xc8\x74\x5d\xbb\x60\xb6\xc2\xe8\x08\x58\xfd\x27\xfa\xaf\xca\xb6\x1b\xeb\x4f\xf0\x8f\x57\x1b\x11\xfb\x09\xfe\x92\xf4\xe3\xd6\xc5\x67\xf3\x37\x91\xe0\xb6\x28\x98\xed\xab\x6a\xde\xb2\xc5\xb3\x7d\xb1\xf6\x85\x90\xea\xa3\xf7\x90\x2d\xfe\x93\x48\x81\x64\x0c\x88\xbd\x69\x0b\x8f\xe7\x6d\x2b\xd2\x33\xad\x62\x45\x4f\x93\x64\xbe\x9c\x86\x69\xb5\x9d\x2e\xa7\xcb\x61\x25\x33\xc2\x62\x91\x88\x65\xd2\x37\xa0\xc9\xcc\xb8\x69\x3a\x53\x56\x2a\x45\x3b\x9a\x4f\xb9\xd8\x60\x6d\x52\xca\x47\xd5\xe1\x98\x66\x1b\x51\x38\xc5\x9f\x7d\xd2\x5e\x17\x91\x8a\x75\x1d\x2b\x82\x0a\x79\x40\x33\x98\x41\x82\xc0\x42\x9e\x53\x15\xa0\x30\xba\x0e\x31\xa6\x35\xac\xb3\x00\x00\x9d\xe8\xac\xa8\xd1\x90\xe8\xaa\xc0\x22\x4d\x53\x74\x85\x60\x6f\xde\xa5\x9f\x9b\x77\xe9\xdb\xf3\xee\xe5\x77\xba\xec\x6e\x7a\xbf\xfc\x4f\xa3\x43\xde\x3e\xf8\xbc\x7b\x65\x5d\xee\x7d\x02\xe4\x90\x2f\xcc\xbb\x91\x51\x66\x5c\xe9\xce\xec\x79\xa6\x40\x83\x66\xb4\xa0\xb7\xf4\xa6\x93\x90\xe5\x9a\x3b\x6f\x61\x2c\xeb\x93\xca\x94\x5f\x8e\xd2\xa3\x61\x6c\x84\x43\xa9\x26\x9f\x42\xa9\x6e\x57\xa9\xb5\x73\x96\x5a\xd2\xda\x22\x9b\xca\x49\x7a\x46\x2b\x49\xf9\x49\x53\x49\x15\xd0\xd2\x99\x13\x92\xbb\x27\x6f\x7f\xe2\xd0\x1f\x3b\xef\x3e\x3b\xef\x3d\x39\xd6\x27\x28\x5c\x8d\x29\xaf\x9c\x77\x3f\x31\x57\x7d\x2b\x6f\xfe\x99\xf3\x9e\xf4\xa2\x79\x57\x60\x0f\xcf\x5f\xc8\xdf\x5d\xcd\x9b\x1b\x93\x9a\x95\xe5\x85\x68\xdf\x75\xe3\xf3\xbe\x49\x27\x21\x8a\xf4\x22\xf1\xac\x9a\x48\x8c\x7a\x49\x7e\x60\x4f\x9d\xb1\xd1\x1e\x97\xb8\xd1\xcc\x88\x87\x8c\xc2\x32\x95\x4a\xc0\x44\x35\x93\x94\x93\x0d\x9d\x44\x63\x52\x72\x69\xd6\xa4\x18\x1e\xd2\xcb\xd8\x54\xb0\x73\x49\xb3\xff\xd9\x79\x73\x44\x73\x88\xe3\x15\xa8\x2b\x9a\x2e\x30\x0a\x10\x20\x8d\x74\x46\xe0\x88\x4e\x34\x1d\x88\x40\x54\x55\x81\x06\x0a\xaf\xaa\x04\x41\x1d\xaa\x40\x10\x91\x06\x39\x96\x46\xaa\xc2\x61\x4d\xf3\x66\x4d\xe6\xb9\x79\xf7\x56\xba\x1c\x02\x80\x98\x8b\xef\xd0\x5f\xdf\xdd\x2f\x78\x59\x5e\x38\x24\xcb\x83\x4f\xbc\x57\x0a\x52\xbd\x4f\x80\x02\x93\x4b\x13\x6f\x9f\xed\x46\x4a\xe1\x88\xa4\x74\x27\x3a\x9a\x14\x2c\x17\xbb\xdd\x76\x2d\xd9\x8f\x0d\x9d\x82\x1b\xcb\x6b\x63\x84\x87\xed\x32\x17\x8e\x0f\x44\x3d\xd1\x0f\x0d\x17\xf2\xb2\x2b\xb5\x1b\xab\x16\x0a\x67\x5b\xb0\xcd\x54\xe2\xbc\x0a\x26\x0e\x44\x74\xb6\x27\x0d\x06\xb3\xba\x30\x06\xf7\x24\x44\x4e\x3c\xfa\x43\x27\xde\xa7\x27\xbe\x67\x27\xde\xa5\x5d\x8a\x67\x5f\x38\xf1\x7e\xe6\xb1\xb1\x8f\x98\x78\x83\x4e\x7c\xd2\x8b\x26\xde\xa0\xc1\xcf\x76\xe2\x6d\x85\x52\x52\xad\x38\x2f\x25\xd8\x8c\x19\xe2\xfb\x93\x6c\xc3\x6e\x25\xea\x11\x76\xce\x29\x31\xbb\xb4\x6a\x62\x42\x8f\x1b\x35\xa2\x2f\xda\xc5\xe6\xc2\x0a\x8f\xd5\x72\xce\x92\x12\x75\x87\x2e\x84\x97\x74\xbe\xa1\x81\x1e\x31\xf3\x19\x3b\x4f\x44\x83\x2d\xa5\xd3\x59\xa8\x67\xb4\xd7\x24\x1a\x7e\xfb\xed\xeb\xd7\xdf\xbe\x7e\xa5\xf2\x78\x44\xbe\x53\xd8\x71\x88\xdb\x71\x5c\xec\x3a\xc7\x7f\x77\xc6\x03\xb2\xfc\x8b\xaa\x2e\xc7\xe4\x3b\x15\x2d\xe4\x2b\xd5\xb2\x94\xca\x57\xff\xa2\x2a\x6a\x8f\x8c\xf0\x77\x6a\x3c\x55\x86\x86\xfa\x17\x55\x98\x9b\xc4\xfe\x4e\xad\x29\xfe\xf6\x9b\x94\xad\xca\x65\xaa\x2a\x45\xb2\x32\x55\xc8\x67\x5b\xc7\x14\x7f\xa3\x28\x8a\x92\x62\xb1\x23\x6a\xef\x18\x52\xc5\x72\x2a\x27\x95\x5b\x54\x46\x6e\x51\x7f\x18\xda\x3b\x69\xbb\x96\x3d\xee\x8c\x8c\xae\x8d\x3d\x8c\xf0\x5d\xbf\x48\x6a\x1f\xd5\x73\x92\x9f\x63\x7c\x53\xfa\x1d\xcc\x6d\xd4\x76\x7c\x97\xde\xff\x3a\xaa\xa5\x91\xed\x9f\xee\x72\xbc\xfb\xd3\x70\x9c\x29\xb1\x3b\x2f\xd1\xee\x94\xed\x39\xe5\x02\x09\x46\xd5\xf2\xa9\x52\x4d\xa6\xfe\x38\x34\xff\x42\x1d\xda\xef\xfe\xf6\x1e\x78\xd0\x34\xaf\xe9\xd6\x87\x15\x7f\xa8\x53\xad\x31\xf1\x9c\xa1\x33\xc6\xb6\x6b\xa8\xc6\x18\x9b\x47\x9a\x9c\xbf\xfd\x62\xcd\xce\x33\xb9\xa6\xe9\x15\xb1\xee\xd6\xfc\x68\xd5\x76\x5e\xf7\x4b\x0d\x5e\xac\xfd\x25\x36\xd7\xf4\xbf\x2a\xda\x4d\x0b\x78\x2e\xad\x2c\x37\xde\xbe\x53\x24\x95\x8f\xc9\xcd\x1b\x3a\x44\xcb\xb2\x54\x95\xbd\xa6\xa7\x54\xa8\x42\xde\x3f\x18\x6a\x95\x54\x3e\x41\x29\xae\x4d\xc8\xf1\xe8\xba\x2c\x8d\x37\xc6\x9e\x97\xc7\xa3\x73\x9f\x44\x17\xc6\xb5\xb2\xec\x60\x55\xb5\xa6\xa6\x1b\x58\x9c\x03\x89\x63\x49\x4e\x42\x85\x53\x79\xbc\xc6\x5f\xa8\xed\x1f\x1d\x87\x4c\xa6\xc4\x54\xdf\x1b\x4c\x59\x76\x7a\xd8\xe9\x3d\x23\xd9\xfa\xf9\xfb\xc4\x3a\xf6\xb4\xf5\x53\xe7\xa4\x19\x12\xad\xfb\x44\xc7\xed\x29\xdc\x27\x91\xd7\x76\x6f\x9e\x2f\x14\x1e\x8f\x87\x86\xea\x4d\x07\x96\xad\x5d\x98\xa6\x3b\x64\xed\x1b\x9b\xfb\x01\x24\xdd\xa2\x84\x27\xb0\x8f\xdc\xb1\xd8\x44\xd7\x89\xea\x77\xb5\xf7\xb3\x96\xa1\x7d\xa1\x7e\xdf\x3c\xfc\xfb\x25\x61\x0d\xed\x45\x62\x1a\xda\xdd\x02\xee\x5c\x6f\x2d\x5e\x00\xa1\xad\x71\x67\xfc\x2a\xb9\xb7\xb4\x8e\x45\xbf\x00\x55\x81\x34\x39\xaf\x80\xbb\x78\x9d\x02\x5b\x5a\x17\x7c\x3a\xa0\x0a\xc7\x14\xce\x29\x61\x8d\xd7\x5e\xd9\xb3\x02\xe9\xb0\x15\xfe\x40\x23\xa8\xf1\xaf\x1b\xda\xd9\x8e\xf6\xcd\x54\xfd\xbc\xad\x4f\xc9\x1d\x8b\xec\x7d\xef\x93\xf1\xbc\x44\xc7\x76\x7d\x95\x58\xef\x68\xde\x37\xbd\x9d\x13\xd0\xf5\xba\xc4\x7d\xa6\x5b\x0f\x34\x82\xbb\xe4\x2d\xf7\x73\x6d\x6d\xcd\x44\xc1\x0e\x79\x1a\x3f\xcf\x11\xf3\x49\xae\x11\x9f\x9c\xc7\x6d\x6f\x0a\x68\xe9\xfa\x13\xa0\xf5\x9e\xd4\x5d\xc2\x6d\x5a\x5e\x13\x6d\x23\x3b\xb1\x5f\x66\x3e\x1f\xbd\x5b\x42\xfa\x9a\xdf\x23\xe9\x6b\xec\x78\x42\xed\x5e\x29\x6f\x5a\xf3\x35\xb2\xdd\x25\xd3\x75\x59\x76\x12\x0f\x2d\x6b\x30\x1d\x3f\x27\xd1\x29\xad\xbb\x7b\xd4\x5b\xef\x5e\x90\x6f\x8c\x0d\xbb\xe3\x1a\x23\xf2\x12\x09\xfd\xd4\xee\x1b\xb7\x5b\x01\xbf\x50\x7e\x91\xbf\x50\xdb\x29\x5e\x1d\x5a\x0e\xd1\x3a\xd8\xbd\xa0\xc4\x0b\xe6\xed\x2d\x9d\x5b\x12\x3f\xb8\x3a\x5a\x53\x7d\x99\x75\x1f\x30\xec\x4d\xbb\x19\xa6\x46\x16\x1d\xdf\x92\xc3\xe9\x58\x66\x07\x6b\x9a\x4d\x1c\xe7\x59\x83\xde\x64\x70\x12\xa7\x6d\x6f\xfb\x22\x23\xaf\xe1\x03\xb2\x3f\xef\x07\xd7\x68\xdf\x96\xf8\xcc\x28\x3b\x25\xb8\x5d\x85\xaf\xe9\xb9\xcb\x71\xf0\x18\xfc\x2a\xd5\x9b\xcb\xfe\x75\xa3\x1b\x82\x6e\xd7\x50\x6b\x92\x7b\x27\x7a\x91\xb4\xe7\x48\xdf\x5c\xbe\xdd\xeb\xc9\x47\xc4\x5f\xed\x0c\x27\xa4\x83\xac\x37\x2f\x93\x1b\x8d\x2d\x7b\x3d\xf1\xcd\x88\xed\x18\x96\xf9\x7a\x43\xfb\x39\xdc\x16\xdf\xf7\xc0\xfd\xca\x6c\xa7\x9e\x80\x99\x8a\xfb\xec\x7f\xc4\xe3\xa6\x26\x47\x6d\xef\x57\x62\x6c\x93\x99\x61\x4d\x9d\x4f\xd1\xe6\x1c\xb3\x9b\x6a\x9d\x7b\xe8\x7e\xfd\x76\x49\x94\x0f\xd3\x69\xc7\xe0\xa6\x1e\x17\xb3\x5d\xa7\xa4\xf7\x78\xfb\x21\x43\xdb\x4f\xfd\x6c\x00\xfc\xe8\x00\x3f\x25\x7a\x1a\x42\xbd\x68\x84\x5f\x63\x71\x8f\x0e\x37\xe2\xba\xab\xcc\x5e\x07\x5f\xef\x09\xdf\x25\xfb\x6d\x10\x3b\x0e\xb6\x3f\xc2\x6d\xde\xd3\x0f\x1c\xea\x6f\x16\x71\x7b\x20\xdf\x65\x18\x3b\x8a\x65\x0d\x02\x5b\xf9\x0a\xcd\x9b\x4b\x84\x3f\xfe\xd0\x88\x8b\x8d\xa1\x43\x7d\xfd\x9f\xff\xa1\xde\x1c\x6b\xa8\x1d\xed\xa6\xbd\x7d\xff\xee\x92\x85\xfb\xe7\x9f\x5f\xa8\xcb\x0d\x55\x4b\xbb\xaf\xa1\x97\x8b\xbf\xdc\x54\xb1\xa6\xdd\x9e\x7b\x17\xfb\x93\xa6\xd7\x05\x38\x69\xea\x13\xe1\x4f\xaa\x91\x94\xcb\xb2\xe7\x64\xd4\xdf\x14\xc3\xdc\xbd\x11\x6d\x68\x1d\xfd\x68\x9b\x28\x9e\xf9\x9c\xed\xe8\x2d\x5b\x2a\x5e\x28\xcb\xa9\x44\x7e\xbf\x05\x44\x95\xe5\xb8\x5c\x96\xf3\x51\xb9\xe2\xdb\x15\xd9\xdc\x2d\xe4\xa9\x5a\x31\xb6\x76\x99\xb2\x5c\xa9\x96\x53\xd1\xea\xfa\xab\x98\x9c\x95\xab\x32\x15\x95\x2a\x51\x29\x26\x5f\xd9\x47\x5b\xc7\x1d\xa7\x97\x1d\x5f\x2a\xe6\x75\xc6\x38\xe5\x73\x63\x93\xec\x92\x24\xa7\xf6\xf1\xa7\x8d\xce\x1a\x6b\xbb\xd0\xbf\xb1\xa3\x78\xd1\x12\xdb\x50\xf6\x87\xdb\xe1\x58\x8e\x73\x56\xd8\x65\x09\xae\x3b\xcc\x63\x16\x78\x9f\x54\xfa\x81\x66\xb8\x20\xcc\xa9\x2d\xce\xa4\xc1\x5e\xeb\x14\xfe\x14\xc7\xcf\x60\x90\xcb\xae\xf1\x2e\x87\x74\xaf\x77\x14\x2d\xc7\xed\xda\xa4\x52\xca\x52\x1a\x76\xf1\xda\xc5\x28\x6d\x3a\x1a\x53\xaa\x35\x1a\x0f\x89\x4b\x36\x3a\xfc\xff\x00\x00\x00\xff\xff\x96\x8e\x51\x63\x09\x59\x01\x00") +var _ingest_asset_statsHorizonSql = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xe4\x7d\x79\x8f\xe2\xb8\xd6\xf7\xff\xf3\x29\xa2\xd1\x95\x6a\x46\x74\x37\x76\x36\x27\x3d\xef\x3c\x52\x80\xb0\xef\x3b\x5c\x8d\x90\x93\x38\x10\x96\x04\x92\xb0\x5e\x3d\xdf\xfd\x15\x84\x35\xc5\x1a\xa8\xea\xee\xfb\xa0\x51\x4f\x85\x38\x67\xf3\xb1\x7f\x3e\xc7\xc7\xe1\xeb\xd7\xdf\xbe\x7e\xa5\x8a\x96\xe3\x76\x6d\x52\x29\x65\x29\x0d\xbb\x58\xc1\x0e\xa1\xb4\xe9\x68\xfc\xdb\xd7\xaf\xbf\xad\xef\xc7\xa6\xa3\x31\xd1\x28\xdd\xb6\x46\x87\x06\x33\x62\x3b\x86\x65\x52\xe2\x37\xfe\x1b\x3c\x6a\xa5\x2c\xa9\x71\xb7\xb3\x7e\xdc\xd7\xe4\xb7\x8a\x5c\xa5\x1c\x17\xbb\x64\x44\x4c\xb7\xe3\x1a\x23\x62\x4d\x5d\xea\x6f\x0a\xfc\xb5\xb9\x35\xb4\xd4\xc1\xfb\x6f\xd5\xa1\xb1\x6e\x4d\x4c\xd5\xd2\x0c\xb3\x4b\xfd\x4d\xbd\xd5\xaa\x71\xe1\xed\xaf\x1d\x39\x53\xc3\xb6\xd6\x51\x2d\x53\xb7\xec\x91\x61\x76\x3b\x8e\x6b\x1b\x66\xd7\xa1\xfe\xa6\x2c\x73\x4b\xa3\x47\xd4\x41\x47\x9f\x9a\xaa\x6b\x58\x66\x47\xb1\x34\x83\xac\xef\xeb\x78\xe8\x90\x13\x36\x23\xc3\xec\x8c\x88\xe3\xe0\xee\xa6\xc1\x1c\xdb\xa6\x61\x76\xff\xda\xca\x4e\xb0\xad\xf6\x3a\x63\xec\xf6\xa8\xbf\xa9\xf1\x54\x19\x1a\xea\x97\xb5\xb2\x2a\x76\xf1\xd0\x5a\x37\x93\xb2\x55\xb9\x4c\x55\xa5\x48\x56\xa6\x52\x71\x4a\x6e\xa6\x2a\xd5\x0a\x55\xc8\x67\x5b\xdb\xf6\xdf\x7a\x86\xe3\x5a\xf6\xb2\xe3\xda\x58\x23\x0e\x15\x2b\x17\x8a\x54\xb4\x90\xaf\x54\xcb\x52\x2a\x5f\x3d\x7a\xe8\xb4\x61\x47\xb5\xa6\xa6\x4b\xec\x0e\x76\x1c\xe2\x76\x0c\xad\xa3\x0f\xc8\xf2\xaf\xcf\x60\xa8\x6e\xfe\xfa\x0c\x96\x6b\xbf\xfa\x3c\x05\x3d\x6e\x8f\x6b\xe7\x09\xb8\x76\xe4\x6b\xcc\x8e\x5a\x1d\x88\x6f\x9a\xa7\xf2\x31\xb9\x79\xd4\x72\x4b\x76\x23\x55\x87\xe8\x3a\x51\x5d\xa7\xa3\x2c\x3b\x96\xad\x11\xbb\xa3\x58\xd6\xe0\xfa\x83\x86\xa9\x91\x45\xe7\x48\x39\xd3\xc1\x1b\x47\x77\x3a\x96\xd9\x31\xb4\x47\x9e\xb6\xc6\xc4\xc6\xfb\x67\xdd\xe5\x98\x3c\xf1\xf4\x41\x92\xa7\xa4\x78\xec\xd9\x21\xd1\xba\xc4\xde\x3c\xe8\x90\xc9\x94\x98\xea\x43\x2a\x1c\x3d\x3e\xb6\xc9\xcc\xb0\xa6\xce\xf6\xbb\x4e\x0f\x3b\xbd\x80\xa4\x9e\xa7\x60\x8c\xc6\x96\xbd\x1e\x8e\xdb\x39\x35\x28\x99\xa0\xb6\x54\x87\x96\x43\xb4\x0e\x76\x1f\x79\x7e\xe7\xcc\x01\x5c\x69\x3b\x2e\x03\x08\x7d\xfc\x24\xd6\x34\x9b\x38\xce\xf5\xc7\x7b\xae\xad\x6d\x70\xa7\x33\xb4\xac\xc1\x74\x7c\x47\xeb\xf1\x2d\x91\xbc\x56\xd8\xb0\x1f\x24\xbc\x9b\x74\xef\x7e\x60\x3d\x4f\xe8\x3a\xb1\xef\x6b\xba\x23\x1f\xe0\x91\xad\x59\xef\x7b\x68\x33\xb5\x3e\xc0\xe4\x78\x2a\xbe\xf5\xc4\x78\xfd\x40\xcf\xbd\xd9\x03\xce\xc9\x04\xa4\x2c\x6f\xba\x51\x6f\x3f\xd2\xef\x69\x6c\x79\x72\x58\x37\x1b\x1a\x8e\xdb\x71\x17\x9d\xf1\x6d\x92\xeb\x96\xd6\xf8\xde\x96\xe4\xde\x66\x3b\x28\xb9\xde\x58\xd9\x0d\xf7\x9b\xcd\x6e\xcf\x62\xca\xf2\xbe\xce\xf4\x30\x72\x6d\x6d\xc7\x99\xde\xe2\xbc\x6f\xac\x5a\x1a\x79\x70\x5d\xb0\x77\x83\x31\xb6\x5d\x43\x35\xc6\xd8\xbc\x0a\xde\xb7\x1e\xed\x8c\x1f\x5c\x9b\xec\x11\xed\x51\x09\xce\x3f\xf8\x30\xff\x8d\xf1\xee\xe1\xe7\x35\xfc\x70\xfa\x5e\x67\xae\x7b\x72\xfb\xe7\x1a\x1f\x76\x4b\xbf\x8d\x33\x74\xee\x94\xa0\x6b\xd9\xe3\xce\xc8\xe8\x6e\x17\x0c\x57\x44\xf0\xb5\xbc\x5b\xc7\xc7\xd7\x7b\xd7\x28\xdf\xeb\x9c\xde\xd3\xd1\x42\xb6\x96\xcb\x53\x86\xe6\x71\x8e\xc9\x71\xa9\x96\xad\xde\x49\xfb\x82\xd3\xbd\x80\xf2\xb6\xbb\xaf\x53\xda\x5c\xdd\xaf\xfe\x0e\xa5\x2b\x72\xa9\x26\xe7\xa3\x01\x6c\xb6\x5e\x67\x3b\x64\xf2\x30\xe7\x13\x22\x77\x3f\xad\x91\x3b\xdb\x1e\x56\xb3\x77\x6b\x78\x61\xd4\x3f\xa2\xdf\x79\x12\xf7\x3d\xbb\x5d\xf7\xdd\xd7\x78\xbb\xc8\xbb\x5b\xb7\xed\x0c\xf0\x88\x2e\xde\x23\x77\xb6\xdd\x2e\xff\xee\x97\x67\xb7\x5e\xbc\x47\x22\xdf\x1c\x72\xbd\xf1\xd1\x94\xb0\x6d\x28\x25\x12\x65\x39\x21\x55\xcf\x34\x1e\x19\xeb\x88\xc3\x50\xc9\x1f\xe6\x74\x44\x6c\x43\xfd\xf7\x3f\x7f\xde\xf1\x14\x5e\x04\x78\x6a\x88\x1d\xf7\x0f\x6c\x2e\xc9\x70\x93\x8a\xb9\xe3\x09\xdd\xb0\xcf\x3e\x12\xaf\xe5\xa3\xd5\x54\x21\x7f\x45\x9f\x0e\xee\x76\x0f\xd2\x7d\xa1\xde\x09\x7a\x85\xc6\x4e\xbb\x27\x68\xac\x75\xdd\x3c\x7e\x10\xfe\x0b\xf5\x88\x22\x1b\xd5\xef\xa0\x20\x37\xab\x72\xbe\xe2\x23\x31\x1c\x77\x9d\xc9\x70\xe7\x8b\xd1\xa4\x9c\x93\xde\x71\xf8\xeb\x37\x2f\x0b\x97\xc7\x23\xf2\x7d\xf7\x1d\x55\x5d\x8e\xc9\xf7\xed\x23\x7f\x51\x15\xb5\x47\x46\xf8\x3b\xf5\xf5\x2f\xaa\x30\x37\x89\xfd\x9d\xfa\xba\x49\xce\x45\xcb\xf2\xba\xbf\xb6\x94\x77\xf4\x7e\x3b\xa1\x78\x7a\x73\x4b\x38\x5a\xc8\xe5\xe4\x7c\xf5\x0a\x65\xaf\x01\x55\xc8\x9f\x12\xa0\x52\x15\xea\x6d\x97\x76\xdb\x7d\xe7\x6c\x88\xbc\xf9\x39\xef\xd4\xdf\xf2\xdc\x5b\xe8\xa6\x3e\x27\xb6\xcc\x17\xaa\x3e\x7b\x52\x8d\x54\x35\xb9\x17\xeb\x38\xff\x76\xc2\xfe\x40\xc5\x27\xc8\x23\xca\xbf\x23\xb2\x31\x40\x31\x1b\x1e\x77\x2b\xa5\x2c\x35\xb6\x2d\x95\x68\x53\x1b\x0f\xa9\x21\x36\xbb\x53\xdc\x25\x1b\x33\xdc\x99\x2f\x3c\x16\xf7\xb6\xa3\x6d\xc5\xdf\xf9\xea\x41\xfe\x5d\xdf\x9e\xb3\xe5\xde\xb3\x6f\xd2\xa7\xca\x72\xb5\x56\xce\x57\x8e\xbe\xfb\x8d\xa2\x28\x2a\x2b\xe5\x13\x35\x29\x21\x53\x1b\xed\x73\xb9\x9a\x37\xdf\x55\xaa\xe5\x54\xb4\xba\x69\x21\x55\xa8\x7f\x75\xfe\x45\x55\xe4\xac\x1c\xad\x52\xff\x82\xeb\x2b\x7f\x6f\xdc\x1c\x88\xcf\x69\x77\x8b\xfc\xcb\x94\xa3\xcf\x29\x77\xcf\x4c\xf5\x9c\x7e\x77\x70\xd8\xab\xb8\xff\x2a\x90\x86\x7f\xfc\x46\x51\x51\xa9\x22\x53\x8d\xa4\x9c\xa7\xfe\x05\xff\x0d\xff\x09\xff\x0b\xfe\x9b\xfe\xe7\x7f\xfe\x45\x6f\xfe\xa6\xff\x4d\xff\x43\x55\xbd\x9b\x94\x9c\xad\xc8\x6b\xa3\xc8\xf9\xd8\x9f\x67\x2d\x73\x07\x0e\x3c\x69\x99\xdb\x1c\x3e\xda\x32\xff\x2f\x88\x65\xde\x63\xea\xd6\x0e\x7b\x1c\xbe\xcf\x10\x07\xd8\x7e\x47\x71\x23\x31\x45\x55\xd6\xb6\xa2\xfe\x3e\xcc\x00\x5f\xbc\xaf\xab\xad\xa2\x4c\xfd\x7d\x3c\x22\xfe\x3c\x37\x6a\x5f\x2a\xa3\x9f\xa0\x4f\xc4\xdd\x30\xbe\x5f\xc2\xb3\x4b\xa0\x67\xa5\x3c\x47\xd4\x27\xe9\xc9\x80\x3c\x15\xf7\xe0\x65\xef\xa5\x3d\xb7\xcc\x7b\x5a\xda\x33\x44\xfd\xd2\x1e\x0f\x92\xab\xd2\xae\x91\x4b\x23\x3a\x9e\x0e\xdd\x8e\x8b\x95\x21\x71\xc6\x58\x25\xd4\xdf\xd4\xdb\xdb\x5f\xa7\x77\xe7\x86\xdb\xeb\x58\x86\x76\xb4\x95\x76\xa2\xeb\xf1\xfa\x77\xab\xe2\x66\x80\xdd\xa7\x9e\x37\x16\x8f\x83\x6f\x4f\x23\x43\xa3\x14\xa3\x6b\x98\xee\x66\x61\x90\xaf\x65\xb3\x9e\x3a\x78\xb4\x5e\xc6\x53\x6a\x0f\xdb\x58\x75\x89\x4d\xcd\xb0\xbd\x34\xcc\xae\xaf\x99\x39\x1d\xed\x97\xfc\x94\x61\xba\xa4\x4b\x6c\x5f\x13\x7d\x88\xbb\x0e\xe5\x8c\xf0\x70\xf8\x9e\x8d\x6b\x8d\x86\xef\x99\xfc\x41\x73\xdc\x9f\xfb\x96\xef\xbb\xdd\x1f\x37\x04\x35\x87\x3f\xdb\xb1\x37\x89\x4b\x16\xef\x0c\x32\x1e\x0f\x8d\x4d\xce\x9e\x72\x8d\x11\x71\x5c\x3c\x1a\x53\xeb\x3e\xdb\x5c\x52\x2b\xcb\x24\xef\x05\xbd\x14\x15\xed\xd6\xa3\xdb\x70\xea\x3e\x99\xf7\xc1\xd7\x05\xaa\x5b\x37\x94\xca\x55\x6f\x45\x07\x37\x5f\xa4\xf2\xd1\xb2\xbc\x59\x7e\x45\x5a\xdb\xaf\xf2\x05\x2a\x97\xca\xd7\xa5\x6c\x4d\xde\x5f\x4b\xcd\xc3\x75\x54\x8a\x26\x65\x0a\xde\x52\x26\xb0\xd9\xfd\x84\xde\xb9\xe2\x36\xe9\x41\x99\x64\xe1\xce\xf0\xf0\x8f\xb7\x0b\x1a\xbf\x7d\xff\x6e\x93\xae\x3a\xc4\x8e\xf3\xa7\xbf\xbb\xbc\xbd\x8a\x33\xbe\xc5\xb3\x7f\x5e\xe9\x28\x2f\x36\x7e\x5a\x33\x2f\xa3\xb3\xd7\xeb\xfc\xc8\x38\xe4\xea\xce\x8b\x79\xb6\xb9\x6a\x69\xe7\x9a\x43\xfa\x7c\x73\x2f\xfd\x77\xe6\x01\x8e\xbf\x36\xc2\xce\xa7\x17\x5e\xe4\xb6\xc7\x34\x3f\xcd\x69\xaf\x29\x42\x15\x1a\x79\x39\x46\x45\x5a\x37\x34\xf2\x32\x74\xd7\x15\xda\xd3\xf2\xdd\xfe\x66\x68\x97\x64\xdb\xe5\x7c\x9e\xf5\xba\x2d\x9d\xad\xdb\xf9\xc6\x4c\xe7\xd2\x4c\xff\x3e\xc5\x75\xa9\xe5\xef\x9b\x8d\x8f\xdf\x2f\x78\xf3\xc6\x8f\xcf\xdf\xd2\x88\x8b\x8d\xa1\x43\xf5\x1d\xcb\x54\x2e\x3b\xdb\x2e\x51\xf6\xac\x1d\xb6\x74\xb6\x76\xd8\xed\x5b\x5f\x90\xed\x68\x33\xf9\xae\x51\x78\x6e\x1f\xfb\xfc\x83\x5b\xb3\x1c\x65\x46\x37\x1d\xb1\x97\x63\x37\xcb\x01\x1f\x87\x43\x47\xdc\xd7\x7e\xbf\x99\xec\x03\x26\x6b\xea\x1e\xb0\xc9\xff\x8c\x4d\xb0\x7b\xf3\x21\xaf\xed\x74\xac\xdd\xdd\x76\xef\x3a\xdb\x4b\xdf\x3e\xfb\x3b\x5d\xe0\xbb\xf5\x80\x8b\x87\x1d\xd5\x32\x4c\xe7\xbc\x0f\xea\x84\x74\xc6\x96\x35\x3c\x7f\x77\xb3\xf3\xa9\x93\x4b\x7d\xbd\xb9\x6d\x13\x87\xd8\xb3\x4b\x4d\xd6\xeb\x50\x77\xd1\xd9\x2c\x93\x8c\xd5\xa5\x56\x63\xdb\x72\x2d\xd5\x1a\x5e\xd4\xcb\xdf\x47\x3b\x67\x21\x58\x23\xf6\x66\x79\xe1\x7d\xef\x4c\x55\x95\x38\x8e\x3e\x1d\x76\x2e\x3a\xca\x56\x71\x6c\x0c\x89\x76\xb9\xd5\xe5\x61\x75\x21\x77\xfd\xec\x28\xbb\xb0\x1f\x72\x03\xf3\xee\x9f\x6d\x6e\xcf\x5f\x8f\xaa\xfc\x5a\x18\xbb\xca\xe3\xb3\x60\xed\x21\x45\x9f\x84\xb9\xab\xbc\xde\xc3\xde\xf9\xe6\x57\x60\xf0\x68\x67\xe7\x7e\xdf\xfc\xfa\x75\xbd\xd4\x23\x1a\x65\x38\x9d\x31\x5e\xae\x83\xda\xbf\x37\xd1\xd3\x2e\xae\xa2\x5c\x6b\x9b\x50\xfd\x42\xd9\xd8\xed\xad\x87\x5f\x0f\x9b\xeb\x29\xdb\xec\xae\xc7\xb7\x43\x6c\x97\x1a\x1a\x26\x71\x6e\x39\xfa\xad\x98\xe9\xb4\x44\xeb\x42\x5c\xb5\x0e\x23\x54\xcf\x2e\x1b\x38\x7d\x12\x4d\xb7\xd3\x88\x35\xb5\xd5\x7d\xcd\xc7\x05\x1c\xdb\xcd\x4d\x6f\x6f\xdf\xbf\xdf\x8a\xeb\x0e\xd6\xa4\x14\xcb\x1a\x12\x6c\xee\xed\xb9\xb1\xee\x66\xe8\x9d\xeb\xc4\xed\x56\xde\xb3\x93\xcb\xb6\xfa\xf0\x8f\x97\xae\x50\xb6\x93\x70\x10\xbc\xdc\x54\xdf\x5c\x64\xeb\xab\x7d\xbc\xd6\x68\x5b\x8e\x79\xad\x89\x17\x79\x9f\x6d\xf0\xbe\x8a\xf4\x46\xbb\xab\xec\xf6\xad\xae\x70\xdc\x88\x64\x38\x1d\x87\x0c\x87\xc4\xde\x39\xc3\x0e\x05\x0d\x95\x74\xcc\x13\xc4\xf7\xbe\x3b\x5d\x05\x1c\xea\x97\x3a\xbe\xf5\xc1\x49\x05\x95\xff\xa6\x6d\x4d\x4d\x6d\x53\x82\x3c\x34\xc6\x63\xdc\x25\xef\x89\x1a\x4e\x87\x2c\xb0\xea\x9e\xca\x75\x54\x51\x70\xb6\x48\x75\xa3\x6e\x67\x53\xc6\x4c\x45\x93\x72\x34\x43\xfd\xf1\xc7\xb1\xe9\xff\x87\x02\x7f\xfe\x79\x8b\xd4\xb9\xc7\x77\xd6\xfe\x7f\xef\x3a\xe0\x0e\x7a\x27\x9d\xe1\x23\xef\xeb\xa9\x8d\x80\x97\xd1\xef\xe2\x66\xfc\x0b\x46\xe5\xf9\xf2\x8a\x3b\x41\xff\x9e\x09\xf2\x19\xd8\xbf\x55\xca\xf0\x1a\xe0\xbf\xc1\xe5\xb3\xa0\xff\x41\x65\x9f\x04\xff\x1b\xdc\xde\xc3\xff\xa5\x07\xae\x2c\x00\x4e\xca\x57\x5e\xe8\xab\x3b\xff\x3c\x16\xe9\xee\x78\x6f\x0b\x1a\x37\xa2\xc8\x7b\x61\xfd\x3a\x42\x9f\x6d\x7b\x60\x7d\x76\xbc\xac\x03\x96\xcb\x11\xcf\xa5\x58\xf2\x87\x44\x83\xee\xa2\x43\xcc\x19\x19\x5a\x63\x72\x2e\xc3\xea\x2e\xd6\xb1\xd9\x66\xc9\x76\xf6\xe6\x88\xb8\xf8\xc2\xad\x75\x54\x78\xe9\xb6\x63\x74\x4d\xec\x4e\x6d\x72\x2e\x19\x28\xf2\x7f\xfe\xfb\x9f\xc3\xca\xe8\x3f\xff\x7b\x6e\x6d\xf4\xef\x7f\xfc\x36\x27\x23\xeb\x42\xde\xee\x40\xcb\xb4\x4c\x72\xc7\x4a\x6b\x4d\xeb\x3d\x99\xad\x66\xc6\x88\x74\x94\x35\x0c\x6e\x92\xeb\x82\xbd\x5e\xb2\x9e\xb8\xe5\xf9\x9b\x23\xc3\xec\x5c\xf0\x9e\xcb\x0d\x3a\x7e\x84\x3d\xdb\x68\xcb\xb7\x8b\xc7\x27\x6d\xc9\xc2\xb5\x71\x67\x6d\x6a\x62\x3b\x9b\x5e\xf8\xf7\x3f\xfe\x08\xf7\x14\xa4\xd7\x5d\xb6\x56\xbb\x4b\xb4\xdb\x21\xec\x36\x9f\x6a\x68\xbb\x69\x61\x57\x16\x77\xcf\x5c\xe6\xcd\x0b\x9b\x1a\xc4\x1b\x15\x77\x15\xb9\x7a\x25\xf7\x7c\x9c\xe5\x3b\xce\x3c\x3f\x16\x9b\xbd\x4e\x89\x3b\x0b\x12\xaf\x2a\x75\x35\xa6\xbb\x47\xc9\x8b\x4b\x82\x97\xa9\x79\x77\x4d\xe7\x55\x45\x6f\xe0\xd7\x79\x55\x63\xd8\xc5\x94\x6e\xd9\x37\x76\xe0\xa8\x98\x54\x95\x6e\xa8\x97\xca\x57\xe4\x72\x95\x4a\xe5\xab\x85\x93\x5d\xb8\x0d\xdc\x57\xa8\x3f\xe0\x17\xea\x0d\x02\x20\x0a\x88\x07\x00\xbc\x7d\xa1\xe0\xe6\xbf\xb7\x9e\xeb\x8e\x9d\xef\xe1\xb0\x4b\x1c\xf7\x9b\x6a\x8d\xc2\xdf\xe6\x64\x38\xfc\x3a\x30\xad\xb9\x19\x76\x5c\x32\x1c\x62\xfb\x9b\x6b\x8d\x86\x6f\x7f\xfe\x75\x93\x09\xfd\x85\x7a\x63\x00\x00\x00\x02\x96\x61\x3d\x3e\xf4\x07\xf0\x61\x3c\x65\x76\x1f\x4f\x9b\x35\xf3\xb7\xcb\xc6\xbd\xb6\xa7\xf7\xa8\x81\xfd\xfb\x7a\x3b\xb9\xde\x60\xc7\x30\x0d\xd7\xc0\xc3\x8e\x97\x12\xf8\xe6\x4c\x86\x6f\x5f\xa8\x37\x1a\x40\xf1\x2b\xe0\xbf\x02\x86\x82\xc2\x77\x5a\xf8\xce\xa2\x6f\x80\xa1\x59\x91\x0f\x01\xda\xaf\xf1\x45\xea\x74\xc7\x3b\x3b\x73\xe2\x5f\xca\xb2\xe3\x5a\x86\x76\x9d\x93\xc8\x73\xe8\x11\x4e\x4c\x67\xea\x90\xc3\xa4\x6c\x98\xef\xce\xeb\x5c\xe5\xc7\xb2\x80\x15\x1e\xe1\xc7\x76\xb0\xa6\x75\xfc\x59\xcf\xab\x3c\x38\x96\x63\xe8\x47\x78\x70\x1d\x6f\x19\xb2\x0b\x88\x36\xbb\xe5\x57\x59\xf0\x0c\xa0\x1f\x52\x83\xdf\xb1\xd8\xce\xe5\x77\xb0\x10\x58\xc8\x3d\xc2\x02\x75\x46\x96\x66\xe8\xcb\xfb\xb5\x10\x20\x4f\x3f\xc4\x42\x38\xd1\x62\x5b\x24\x7f\x07\x1f\xc4\xf2\xcc\x63\x7c\xd6\x9d\x8e\xbb\x5d\x9b\x74\xb1\x6b\xd9\xd7\x7d\x4a\x04\x10\x88\x8f\x90\x17\x37\xe4\xbd\x8c\x78\x67\xa1\xd9\xd7\xa9\xd3\x08\x3e\xd4\xd5\x10\x6c\xc8\x6f\x7b\x61\x93\x95\xb8\xce\x80\x13\xd1\x43\xd6\x81\xf0\x98\xc1\x3e\x5a\x5d\x4f\x00\xd7\x19\x89\xbc\xf8\x98\x26\xf4\x49\x47\x6f\xf3\x03\xde\xb1\xec\x6b\x9c\x20\x40\x1c\xfb\x50\x8f\x40\xc6\x53\x67\x9f\x8e\xb9\xda\xe3\x10\xd2\x88\x7f\x4c\x13\xb6\xa3\x1b\x8b\xdd\x11\x15\x6b\x34\xec\xe8\x06\x19\x5e\x9d\x1a\x21\xe4\x20\x7c\x68\x12\x86\xdc\x6e\x8d\xba\xdb\x31\x59\xdc\x50\x83\x47\x8f\x4d\xf3\x90\xef\x18\x66\x97\x38\x6e\xe7\xfd\x9e\xcc\x0d\x56\x48\x14\x1e\xeb\x11\x74\xb2\x70\xd9\x6c\x7e\xe1\xeb\x60\x02\x69\x00\x18\x76\xcb\xe4\x02\xd6\x5e\xad\xe4\x78\x14\x6c\xdf\x55\x73\x1c\x2f\x69\x12\xd1\x66\x26\xc1\x97\xf3\x6c\x21\x9f\x92\x8b\xd1\x5c\x3e\x1e\x41\x0c\x2d\xb1\x0c\xdf\xe6\x8a\xf9\x58\xa5\x9c\x4d\x34\x32\x28\x11\xc9\x46\x73\xa5\x6c\x2a\x5e\x60\x2b\x48\x6e\x35\xea\x35\xbf\x85\x2e\x32\x59\xaf\x2a\x12\x12\xd7\x88\x14\x5b\x12\xd7\x62\x1b\x92\x9c\x6c\x36\xca\x74\x2d\x53\xa0\x6b\x05\x36\x52\x4b\x24\x6b\x25\xc4\xca\xb5\x62\xa6\x90\xa7\x4b\xc9\x3a\xdb\x28\x27\x0b\xa9\x72\x3e\x93\x49\xbe\xeb\x86\x8b\x4c\x98\x8d\x26\x34\x53\x8a\xd3\xc9\x9a\xcc\xd1\x52\xae\x59\x8b\xd7\x92\x8c\xd4\x4a\x4b\xcd\x66\xa2\xd9\xac\xd3\xf5\x64\xb3\xd5\x2a\xf3\x72\xab\x29\x57\x8b\x99\x58\xb3\x5d\x91\x1a\x3c\x6a\x16\xd8\xbb\x99\xb0\x6b\x26\x91\x72\xb1\x95\x4c\x65\xe9\x68\x8a\x89\xe7\x4b\x6c\xa4\x99\x8d\xe7\xf2\xb1\x6c\x3c\x5d\xcb\x17\x6b\x74\xb2\xc5\xb4\x73\xf1\x4a\xb2\x90\xaf\x45\xe5\x82\x54\x69\xa0\x52\x14\x15\x9a\x74\xf2\x2d\x68\xe5\xd1\x7a\xd1\x7c\xa3\xaf\xb7\xd5\x9a\x87\x42\xeb\x6f\x0e\xb9\x5e\x95\xf3\x85\x62\xbf\x50\xae\x3d\x25\x77\x78\xe0\xfb\x7a\x9b\xc0\xfe\xe7\xc5\x74\xc7\xde\xa7\xda\x44\x33\xdc\x0e\x1e\x8e\x7b\xd8\x9c\x8e\xd8\xf5\x98\x89\x54\xa3\x6f\x1f\xd1\x9d\xa7\xdc\xe9\x0b\xdc\x6b\x95\xd8\x27\x70\x67\x2e\x70\xaf\x44\x0b\xd5\xb7\x27\x47\x65\x90\xf2\x9a\x97\x38\xd9\x49\xf8\xfd\x85\x62\xee\x75\xb1\x73\xd5\x35\x41\x7d\x6c\x57\x61\x73\xe4\x64\x0c\xcb\x70\x22\x62\x69\x96\xe7\xf6\x61\xce\x7f\x7e\xf7\x50\xfa\xf7\xef\xd4\xef\xf0\x1b\xc3\xd3\xeb\xa0\xeb\xf7\x2f\xd4\xef\x87\x12\xae\xf5\xad\x5a\x25\x76\xf8\xd2\x5d\x8e\x37\x5f\xfa\xfb\xed\xd0\xc2\x2b\xe5\x5a\xb7\x09\xea\x3e\xbf\xff\xef\x25\x07\xf2\x2b\x46\xfb\x14\xa3\x37\x06\xff\xaf\x52\x8c\xe7\x78\x78\xb6\xc7\x18\xf8\x8d\xe7\x10\xe2\x85\x5f\x4b\x33\xe8\xd3\xec\x4c\x97\xfd\xa2\x9a\xad\x35\x01\x80\x67\x11\xe2\x20\x2f\x7a\x7d\xe6\x75\xda\xd0\x18\x19\x9e\x33\xee\x93\x0d\xdf\xb6\xff\xff\x45\x35\x14\xe9\x0b\xf3\x88\x20\x7e\x13\xb9\x5f\x4f\x33\xe8\xd3\xec\x8c\x57\xfe\xa2\x9a\xd1\x5f\x28\x9a\x43\xbc\x28\x00\x24\x20\xe6\xfc\xdc\x7f\xd5\x1f\xd7\x68\x1c\x54\xb9\x60\xf8\xfd\x50\xb7\x9d\x28\x77\x6e\xfe\xff\xf5\x95\x83\x50\xdc\xcd\x27\x67\x94\x03\x60\x13\x4c\xfd\x6a\x7e\xc9\xf8\xb4\xbb\xd0\x75\xbf\xa8\x76\x87\xbe\xe3\xc1\xa5\x15\x17\x00\xdf\xb6\x79\xf4\xf7\xaa\x45\xaa\xd1\x9f\x55\x35\xc6\xa7\xda\xf9\x8e\xfb\x25\x55\xdb\xcf\x95\x34\x80\x17\x56\x5d\x9e\x2f\x7e\x13\xe9\xcd\xc6\xc4\x2f\xe5\x93\x8c\x4f\xbb\x33\x1d\xf7\x8b\x6b\x07\x59\xc4\x0a\x2c\xe0\x10\xf2\xfa\xce\x53\xcf\xb5\xa7\xeb\x47\x9e\x9a\xb4\x7f\x4d\x4b\xb0\xfc\x0e\xf1\x3f\xd0\x12\x3f\xf1\x78\x3e\x58\x42\x40\x3b\x04\x7d\x6f\x89\x80\x69\xb9\x5f\xca\x27\xe8\x2f\x14\x44\x10\x89\x02\x62\x68\x61\x3b\xb3\x81\xd3\xd8\x44\xa4\x69\x86\x41\x34\x60\x78\x81\xfb\xb6\x0e\x62\x04\x80\x7e\x29\x1d\xe1\x5e\x47\xc4\xec\x66\x80\xff\x5a\x1d\x05\xc8\xee\xc6\x76\x20\x1d\x7f\xe2\x51\xbb\xf7\x55\x81\xe3\x76\xa3\x36\x90\x8e\x3f\xf9\xe2\x1e\xd2\x82\xc0\x8a\x80\x13\x05\x6f\x81\xc8\x7b\x60\x3c\x75\x7b\x1d\x9b\xcc\x2c\x15\x2b\x43\xd2\xd1\x87\xb8\xfb\xfb\xf7\x4d\x0e\xf1\x91\x69\xcf\xa3\x0d\x01\xd8\x0e\x76\x6e\x43\xbb\x67\x8d\x48\x47\xb3\x46\xd8\x30\xd7\x5a\xee\x8a\x28\x1e\x9a\x50\xb7\x94\x59\xb8\x1d\x62\x27\x52\x4f\xa6\x86\x4d\xb4\xa0\x42\x0b\x9c\x20\x8a\x8c\xc0\x0b\x5e\xa7\x7b\x7d\xee\xb8\xd8\x76\x0d\xb3\xdb\x51\xf0\x10\x9b\x2a\x79\x17\xd3\xdd\xcd\x81\x3d\xe5\x70\x77\xac\xb8\x73\x1c\x13\xbb\xc6\x8c\x3c\x64\xac\x63\x7e\x6b\xdb\x79\x2a\xcd\x89\xd1\xed\xad\x19\xc2\x2f\xd4\xef\x5e\x52\xb7\x33\x20\xcb\x4f\x9b\x41\x36\x52\xb1\x34\xda\xfa\xdd\x47\xd9\x79\xcb\xe1\xc3\xed\xec\xd3\xe8\x4e\x3b\x7f\xf4\x00\xa7\x77\x52\xf1\xc2\x76\x0c\x7e\x98\x9d\x3d\x0e\x1f\x6e\x67\x9f\x46\xf7\xd9\x39\xe8\xe2\xea\x7f\xef\xd8\x17\x3e\x77\x10\x37\xe8\x96\xc9\xee\x30\xee\x4e\x59\xe1\x0b\xf5\xa6\x40\x9a\xe7\x10\xc4\xba\x8a\x75\x28\x42\x0e\x29\x3c\x23\xea\x1c\x51\xb0\x20\x40\x42\x73\x22\x03\x34\x91\xc5\x0c\xc2\x1c\x2d\x40\x4e\x53\x20\x14\xa0\xa8\xaa\x1a\xc7\xb0\x40\x11\x37\x7b\x59\x90\x15\xa1\xae\xf3\xaa\xa2\x2b\x08\xd0\x0a\x23\x00\x08\x14\xa2\x2b\xbc\x0e\x30\xcf\x6a\x3c\x4d\x8b\x8c\xa2\x02\xc0\x31\xa2\x4a\xb3\x98\x55\x75\xc2\x00\x46\x50\x74\x04\x11\xcb\x30\xa2\x57\xfa\x46\xfb\x76\xd1\xf9\xef\x0c\xfa\xce\x22\xff\xe6\xba\xf7\x35\xf7\x0d\x00\xc4\x33\xb7\xef\x7a\x79\x78\x46\x60\x78\xe1\x0b\x05\xf9\x75\x7f\xbe\xfb\xac\x57\xd0\xeb\x7f\x77\xff\xec\xbe\x85\xfb\x3f\xe0\x17\xea\x4d\x92\x24\x29\xba\xa8\x94\xc3\xf4\x32\xec\xce\x33\xab\x6e\x24\x1a\x0a\xd1\x42\xa6\x9d\x6f\x19\x03\x34\x97\x6a\xdc\x7c\x30\xce\x85\xfb\x12\x3b\x63\xe2\x20\xc7\x55\x6c\xb3\x99\xa5\x8b\xc2\xb0\xb2\xb2\xf8\x54\x3d\x36\x72\x5b\xb0\x2d\x2b\xe9\x48\x35\x1c\x1b\x64\xea\xf5\x18\x9f\x96\xb4\x36\xe8\xa9\x23\x67\x4d\x5a\x6a\x16\xeb\x39\x7a\x2e\xed\x3f\xed\x85\x56\x6a\xe8\xb1\x1c\xcc\x2d\x6a\xd1\x29\xd1\xa5\x11\x09\x2b\xfd\x49\x41\xed\xad\x06\x49\x59\x10\x0b\x4e\x75\x60\x71\xbc\xca\xa6\x58\x43\x52\xd5\x66\xa4\x52\x0d\xe9\x20\x6a\x82\x45\xbc\x57\x58\x8c\xe5\x32\x34\x87\xbd\x49\xdf\x48\xa5\x9c\x5c\xd3\xc4\x74\x3d\x31\x9c\x67\x37\x94\xbb\x79\x36\x8b\x57\x63\xba\x74\x60\x26\x75\x81\x74\xe6\xd3\x96\x9a\x90\x2d\x49\x52\x0c\xa4\xcf\xdd\xfe\xa9\x3f\x9e\x57\x81\x0b\x03\xdf\x3f\x16\xd0\x6b\xfc\xf8\x8d\xb0\x82\xaa\xd3\x3a\xd1\x38\xc2\x28\x82\xbe\xbe\xc7\x61\x16\x0a\xba\x48\xeb\x02\x54\x04\x86\xa7\x55\x41\x00\xac\xae\x32\x0c\x4b\x10\xa3\x71\xa2\x22\x12\x55\x14\x09\x61\x69\x9a\x55\xae\x8d\x05\xfe\xa2\xb7\x33\x00\x01\x78\xf5\x2e\xfd\xb6\xcf\xfe\x43\x80\xe8\x2b\x63\x01\x8a\x77\x8e\x85\x50\x25\x27\xcc\x50\x9d\x45\x7d\x24\x2e\x1a\x83\x44\x71\x30\xeb\x2a\x5d\x3a\x9b\xea\xca\xe1\x58\xbe\xa0\x8a\x0d\xc5\x74\x46\x84\x8b\xa6\xb3\x55\xc0\x14\xba\x46\x24\x1c\xca\x15\x62\xe5\x62\x49\xc7\x7a\x4e\x9c\x2f\xe8\x31\x0b\xc4\x71\x69\x86\xdb\x5a\x1f\x16\x78\x54\x69\x65\xd2\x9e\x1b\x6e\xc6\x42\xf7\xd0\x97\x63\xbe\xc9\x62\xa8\x97\x1a\xe5\x3c\xd4\xab\x6c\xa1\x87\x61\x5d\x52\x68\xc6\x5e\xf4\x6d\xac\xf7\xba\x61\x61\xde\x5f\x16\x8a\x25\x96\x0c\x95\x46\x2e\x23\x64\x74\xce\xb6\x23\x20\x57\x77\x79\x2b\x46\x57\x87\xfc\x5c\x98\x45\x8d\x90\xce\x76\x41\xa1\xcb\x57\x52\xf9\x6a\x4b\x8e\x6d\xdc\x5f\x3d\x33\x16\x34\xe7\x9c\x3f\xfd\xdf\x19\x0b\xfc\x6b\xfc\xf8\x8d\x61\x18\xa2\x72\x44\x24\x9a\x08\x14\x85\x28\x0a\x27\x42\x44\x8b\xb4\x08\x14\x9a\x85\x0a\xe6\x39\x06\x68\x9a\x2e\xea\x3c\x04\x34\x01\x34\xcb\xea\x34\xe1\x14\x24\x22\x1a\xaa\x90\xb0\x5e\xf5\x0a\x7b\xde\xad\x2f\x7a\x3b\xcb\x30\xc2\xe5\xb1\xb0\xbb\xbb\xdd\x52\x61\x10\xe2\xaf\x8d\x05\x74\xe7\x58\x58\xe5\x42\x0b\x62\xba\x83\xec\xcc\x76\xdb\xf1\xe5\x60\x1c\x5d\x96\x94\xf1\x30\x97\x67\x38\xb1\x27\x4d\xa5\x41\x75\xc9\x29\xa4\x99\x52\x93\x83\xa9\xd0\xd6\xc3\x46\xcc\x19\x8d\x6b\xee\xaa\x57\xeb\xcd\xa2\x83\xf6\x22\x31\x1b\xf6\x22\x9c\xd0\x48\x17\x2a\x6e\xa8\xd1\xce\x98\x3c\x59\x44\x6b\x9b\xbe\xdb\x8c\x85\x23\xf7\x6c\x2a\x59\x7b\xd5\x5f\xf6\x54\x20\x16\x72\x65\x60\x27\x52\x6a\x7e\x98\x5e\xce\x6a\xd8\xe1\x10\x61\x57\x74\x75\x5c\xeb\x0d\xb3\xf3\x44\xc4\xce\xea\xbd\x69\x86\x49\x55\x72\x4e\x74\x5a\x4f\x0f\x63\x26\x96\x46\x68\xd9\x2b\x83\x6e\x59\xc1\x06\x0e\x37\x30\xc9\xca\x25\x71\x50\x17\x36\x63\xad\x75\x66\x2c\xe0\xc1\x39\x7f\xfa\xc5\xc7\x02\x7b\xff\x58\xe0\x5e\xe3\xc7\x6f\x2a\xe0\x35\x0c\x90\x26\x6a\x3a\x03\x81\xa2\xea\x3a\x0b\x14\x4e\xd7\xa0\xce\x33\x1c\x03\x79\x8e\xe6\x31\xc3\x61\x4c\x43\x04\x10\x0d\x34\x44\x10\xd6\x79\x0c\x69\x06\x2a\xaa\x20\x88\x5e\x99\x0d\x73\xd6\xad\xd9\x8b\xde\xce\x03\xf6\xf2\x50\xd8\xde\xf4\xb2\x87\x0c\xcf\x0a\xe0\xda\x48\x60\xee\x1c\x09\x42\xc4\xb5\x92\xb4\x26\x2c\xa2\x42\x18\x44\x61\xb8\x2c\xf6\x6b\x8b\x76\x05\xf7\x1b\x93\x54\x33\xb2\x8c\x35\x39\x5e\x9c\xc8\xfd\x84\x60\xa4\x95\x4c\x2e\xa3\x08\x82\x92\x99\xf7\xe3\x61\x57\xe7\x22\xb4\x63\x4f\x86\x11\xd8\x70\xe1\x7c\x3c\xc9\xb5\x63\x8b\x18\x67\x46\xc1\xca\xa5\x5b\x9b\x9e\xdb\x8c\x84\xe3\xae\x9c\x55\x1b\x96\xd4\x16\x1c\x85\x31\xc5\x55\x2a\x1f\x93\x60\x6f\x62\x61\xb3\x69\xe4\xc3\x63\xb5\xaf\xcb\x6e\x26\x1b\xb3\x57\xf5\x59\x2c\x3f\xd5\x22\x16\xdb\x13\x71\x52\x73\xf5\x46\xb3\xea\x74\xd3\xb5\x04\x2b\x64\xe2\x55\x87\x2d\x56\x1b\x55\xab\xdc\x9c\x86\xeb\xd9\xba\x56\xe2\x36\x2b\xb0\xda\x99\x91\x50\xab\x9d\xf3\xa6\x5f\x7c\x24\x30\xf7\x8f\x04\xf6\x35\x5e\xfc\x86\x18\x8d\xe5\x34\x80\x88\xa2\xb3\x88\x51\x35\x06\xf3\x98\xd0\x1a\x8b\x31\xaf\x73\xbc\x06\xa0\xce\xeb\xba\x86\xa0\x86\x14\x86\xe3\x11\xd6\x35\x0e\xf0\x40\xe1\x75\x55\xa4\xa1\xc2\xf1\xd7\x50\x81\xb9\xe8\xec\x88\x16\xd0\xe5\x68\x61\x77\xd7\xcb\xc9\xf1\x22\x14\xd8\x6b\x63\x01\xdc\x39\x16\x98\x62\xad\x59\xd2\x6d\x31\x59\xcc\x17\x46\xb6\x01\x33\xe3\x59\xdd\x95\x74\x25\x0c\x17\x10\xe5\x1b\x64\x06\x4b\xad\xac\x22\x0c\x7a\x6e\xc3\x0e\xa9\x3d\xa0\x98\xe3\x7c\x36\x59\x12\xad\x4c\xaf\x2b\x14\x62\x52\x2b\x05\xb9\x9c\x39\x55\xcb\x11\x71\xd2\xcc\x2d\xdc\xe4\x2c\x1c\x02\xea\xa6\xef\xd6\x63\x01\x1e\x45\x0b\x5d\x56\x89\x65\x47\xc5\x08\xca\x4f\x8b\x3d\x35\x9e\x9f\x32\x4c\xb1\x5f\xb1\xfa\x6a\xd1\xa2\xab\x49\xb0\xe0\x96\xd9\xec\x54\xe9\x4d\x72\xfd\x55\x7a\x16\x69\x71\x45\x29\x35\x4b\x56\x32\xcb\x29\xb4\x08\x13\x12\xd2\xd3\x4c\x38\x6b\x26\x97\xe5\x3a\xd6\xeb\x0c\x4d\x0a\x35\x01\xea\xc3\x0d\xe5\xd2\x99\xb1\x50\xb4\xce\xf9\xd3\x2f\x3e\x16\x1e\x40\x05\xe6\x35\x7e\xfc\xc6\x62\x56\x81\xba\x4e\x43\x56\x65\x05\x88\x74\x8d\x06\x8c\x20\x70\xba\xa6\x73\x1c\xab\x0a\x9a\xc0\xd3\x08\x6a\x3c\x12\x04\x1e\xf2\x1c\xcf\x41\x0e\x68\x48\x23\x88\xe3\x79\x5d\xd3\x45\xe1\x1a\x2a\xd0\x17\xbd\x5d\xe0\x90\x78\x19\x16\xd6\x77\xd7\xcf\x6e\x53\xb7\x50\x10\xae\x45\xce\xfc\x9d\x43\x01\x8c\xb3\xc9\x70\xaa\xb6\x48\xc5\xc3\xa0\x5b\x48\x35\x45\xb1\x5e\x4d\xd1\x89\xf4\x02\x9a\x46\x22\x3e\x6c\x97\x6b\x79\x9d\x68\x0d\x45\x0c\xb5\x0c\x67\x1c\x29\xb7\xfa\xe9\x41\x7f\x6c\x0f\x4d\xb9\x59\x22\xa5\x1e\xbd\x68\x2f\xc6\x6c\x7f\xd6\x18\x86\xfa\x93\xe6\x6a\x31\x9b\xe5\xcd\x7a\xdb\x5b\x9b\x6c\x86\xc2\x51\xb0\xb0\x62\x09\x50\xf3\x56\xc5\xae\x2c\xd3\x8a\x51\x13\xe7\x73\xb6\xb9\x0a\x47\x59\x64\xc6\xeb\xa9\x88\x9c\x1c\x94\x21\x1c\x74\x47\x24\x14\x5b\xc5\x61\xad\x19\x76\x33\x8d\x70\xde\x58\xa4\xbb\x8b\x65\xd6\xe2\x85\xac\x33\x5f\x8e\x0a\xfc\xd0\x1a\x70\xc5\x4c\xc2\x4d\x88\xb3\x11\x6e\xdb\x1b\xef\xcf\x9d\x19\x0a\xe9\xd6\x39\x77\xfa\xc5\x87\xc2\x03\xb0\x40\xbf\xc6\x8d\xdf\x78\x46\x13\x05\x9d\x63\x78\x42\x78\x41\x83\x0a\x8d\x14\x4e\x11\x44\x9d\x66\xb0\xce\x31\x10\x2a\x88\xe3\x45\x4c\xb3\x3a\xd6\x21\x0b\x18\xac\x01\x85\xa3\x15\x9e\x61\x14\x80\x14\x22\x5e\x5d\x20\x5d\x74\x76\x08\x00\x7d\x11\x33\x76\x37\xbd\x04\x37\xcb\x89\xd7\xa2\xe6\x7b\x97\x47\x74\xb1\xdd\x87\xf9\x29\x67\x01\x25\x8d\x1a\xac\xb9\x2c\xcc\x6a\x8b\x04\x53\x1f\x5b\x83\xd0\x2c\x2e\x15\xdc\x28\xcc\xd0\x39\x14\x41\x7c\x5b\x4c\xcc\x9b\xfc\x44\xc8\xac\x16\xcd\x5a\x6c\xc0\x84\x74\xad\xed\xf4\x9c\x55\xb4\xd1\xa4\x2b\xca\x54\x32\xd3\xf9\x9c\x51\xb1\xa6\xc3\xe8\xf2\x68\x1c\x6c\x5c\x33\xb5\xff\x47\xda\x5c\x3b\x87\xeb\xb9\x54\x2c\x6d\x97\xf4\xd1\xe5\x20\x4c\x1a\x09\xa9\x25\x17\x7a\x43\x2c\x56\x16\xed\x64\x7f\xb0\x48\xa4\x4a\x3c\x1c\xa7\x8c\xfe\xa8\x18\x17\x7b\xf5\x31\x2c\xcd\x38\xdb\x2d\x34\x9d\xd1\xa0\x9c\x56\x97\xcd\xd1\x90\xd0\xed\x4c\xbc\xbf\xea\x55\x07\x60\xca\x40\xad\x6d\xa5\x06\x4d\x0e\x4e\x2d\x53\xd5\x8b\xec\x06\x92\x52\x67\xc6\x89\xfc\xdf\x18\x54\x3f\x30\x4e\xe0\x6b\x7c\x7c\xf3\xb6\x02\x0a\x78\x99\x76\x28\x22\xf0\x15\xc0\xaf\x00\x52\x00\x7c\xdf\xfc\x77\xd1\x99\x21\x04\xb4\x70\xf5\xee\x9a\x3c\x4b\x8b\xac\xc8\x23\x5a\xbc\x16\x15\x9f\xf7\x74\x4f\xa4\x1f\xdd\x29\x97\x3f\x91\x66\xc6\x60\x97\xe1\x65\x25\x13\x41\x31\x33\x26\x26\x69\xb0\xe8\x47\x42\x0e\xe8\xba\xce\x3c\x35\x5f\xc1\xa6\x56\x69\xb4\x70\x24\x8d\xe3\x1b\x30\x91\xcf\x38\xf1\xf9\xcf\xce\x89\x25\x29\x72\x36\x5a\xfe\x99\x3f\x6f\x9e\x33\xdd\xde\x88\xb8\xe3\xd5\x85\x41\xf7\x25\x2e\xbc\x3d\xe1\xd2\xc9\x0e\xfa\xc2\x88\xbb\x41\xc6\x7f\x8e\x02\x06\x23\xc3\xf8\x4f\x2d\x04\x23\xc3\xfa\x8f\x08\x04\x23\xc3\xf9\xea\xf1\x03\x92\xe1\xfd\xa5\xe1\xc1\xc8\x20\x7f\xed\x7c\x30\x32\x82\xbf\x9c\x3b\x18\x19\xd1\x5f\x38\x1d\x8c\x0c\x04\xbe\x2a\x5e\x26\x20\x9d\x77\xb5\xce\x01\xe9\xd0\xbe\xe2\xd4\xa0\xf2\xf8\x8b\x5c\x83\xca\xc3\xfa\x6a\x2e\x83\xca\xc3\xf9\x6b\x37\x03\xd2\xe1\x7d\x55\x92\x41\xe5\x41\xfe\x6a\xcb\x80\x74\x04\x5f\xad\x62\x50\x79\x44\x7f\xcd\x63\xc0\x79\x10\xf8\x2a\x06\x03\xca\x43\x43\x1f\x9d\xa0\xf3\xb2\xbf\x6e\x2f\x28\x1d\xc6\x5f\x1b\x17\x90\x0e\xeb\xaf\x3f\x0b\x48\x87\xf3\xd5\x78\x05\xd5\x8b\xf7\x97\x51\x05\xa4\x83\x7c\x25\x53\x41\xfb\x5d\xf0\x15\x48\x05\xa5\x23\x9e\xd6\x0e\xb1\x01\xf1\x18\xf8\x4a\x90\x02\x92\xf1\x55\xd8\x04\x95\x86\xf6\x95\x1e\x05\x24\xc3\x9c\xd6\xa1\x04\x95\xc6\x5f\x3e\xf3\x9a\xb7\x34\xbf\xe4\x10\xf1\xf5\xd7\x5d\xad\x57\x47\xf7\x9e\x2a\xbe\xf0\xb2\xe2\xa7\x57\xa3\xc7\x76\x3c\x5a\x37\x1e\x2e\xd8\xfd\xab\xa1\xfe\xf3\xbb\x6b\x3d\x5b\x71\xae\xdb\xd6\xe8\xe9\x5a\xed\x9f\xf5\x48\xf0\x07\xbc\x1a\xe2\x72\x3f\x79\x2b\xea\xc3\x05\x78\xdf\x4f\x4f\xd8\x78\xdf\x4f\xcf\x9c\x2e\xf8\x69\xcf\x01\x7f\xc0\x8b\x42\xce\x75\xd4\x71\xcc\x72\xb8\x10\x8e\xaa\x6d\x6f\x9c\x27\xde\x1c\x6e\x20\xe4\x29\x6d\x77\x64\xfe\x1b\xce\x48\x7c\xd2\x00\x3b\x8e\xee\x0e\x17\x67\x26\xc2\x9f\x66\x80\xfd\x6c\x47\x9a\x3f\x67\x80\x9d\x06\xbe\xfb\x0b\xfa\x27\xee\xa8\x9f\xf0\x10\xf3\x67\xf6\xd5\xee\x88\xf0\xfe\x42\xf8\x98\xd5\xc5\x13\x93\xe5\xcf\x7d\x6a\xf9\x03\xde\xe5\x73\xb9\xb3\xb6\xc7\x82\xf7\x17\x1f\xb4\x14\x7c\x55\x67\xfd\x5c\x27\x95\x3f\xb3\xa7\x76\xb9\xa4\xfd\xc5\x47\x2d\x06\x5f\xd1\x53\x3f\xe3\xd1\xe4\x4f\xea\xac\xe3\x44\xdb\xe1\x82\xdf\xf4\x14\x3a\x1c\x67\x7d\xed\x8a\xef\x19\xdc\x9a\xba\x3d\xcb\x36\x56\x64\x7b\x06\xec\xff\x5e\x5f\x79\x49\xc8\xc3\x05\xfd\xeb\xf6\xd5\x7f\xf1\x24\x78\x92\xa0\xdd\x5f\x08\x1f\xdb\x57\xcf\x44\x52\xff\x77\xc7\xd5\xe9\xe1\xf5\xfd\x05\x38\x17\x14\x5f\x3a\x1c\xfc\x93\x75\xe6\x4f\xd1\x73\x1f\x1f\x16\x9f\x6e\x3b\xec\x2f\xf8\x1f\xdc\x73\xbf\xf4\x8b\x40\x3e\x27\xf6\x3a\xdd\xe8\xd9\x5f\xd0\xff\x2d\x3d\xf7\xc3\x90\xed\xb3\x7a\x6e\xfb\xfa\x84\xfd\xc5\xd9\x14\xe2\x5d\x3d\x17\xdc\xe4\x1f\x32\x5b\xfe\xb0\x84\xc7\x27\x4c\x97\x27\xbb\x99\xfb\x0b\xf6\xe8\x2d\x0e\x6b\x8d\x36\xbf\x56\xff\xfb\x77\xea\xdf\xf4\x3f\x5f\xa8\xc3\x37\x9d\xcd\x77\xbe\x77\x48\xfc\xfe\xcf\xa7\xf9\xdd\xc9\x5b\x27\xf6\x17\xe0\xae\x57\x50\x7c\xd2\x42\xe2\xe4\xf5\x15\xfb\x0b\xfe\x92\x7d\xe1\x15\xfb\x7a\x6f\xbb\xd8\x9b\xf7\xc3\x65\x3f\xde\xca\xdd\xff\x2d\x1c\xbd\x5b\x40\x9f\x9a\xda\xd6\xcf\x03\xbe\xa1\x7b\x33\x66\xbc\xf7\x64\x3f\x3b\x67\xdf\xf1\xa2\x83\x27\x5f\x25\xfe\x88\xd9\xb6\x7b\xce\xfb\xbf\xd9\x8f\x35\x5b\xf0\x09\xf3\x27\x33\x9b\xb7\x39\xbe\xff\x1b\x7c\xa8\xd9\x9e\x00\x88\x8f\x37\xdb\x8d\x9d\xf6\x33\xbf\x28\x7b\xcf\x2e\xfb\x6d\xaa\xb7\x7f\x23\x33\xe8\x6e\xfe\xc5\x9f\xac\x3a\x5b\x5d\xca\x5e\xae\xd2\xb9\x49\x88\xf6\x97\x06\x04\x25\xc4\xf8\xf7\xae\x83\x12\x62\x7d\x84\x02\xab\xc6\xf9\x36\x69\x03\x13\xe2\xfd\xbb\x86\x41\x09\x21\x1f\xa1\xc0\x12\x09\xfe\xed\xb1\xa0\x84\x44\x1f\xa1\xc0\x12\x9d\xd6\x9b\x0a\x97\x2b\x9a\x6e\x53\x82\xfe\xfd\xa4\xc0\x94\x68\xff\x66\x47\x60\x4a\x8c\x8f\x52\x70\xed\x58\x5f\x5a\x3f\x38\x25\xce\x47\x29\x78\xdf\xf1\xbe\xec\x75\x70\x99\xde\xe5\xc1\x03\x53\x12\x7c\x59\xda\xe0\x32\x89\xfe\x7c\x6f\xe0\xb9\x12\xf8\xb2\x91\xc1\x67\x5d\xe8\xa3\x14\x58\xbb\xd3\x3a\xd4\x67\xbc\xe0\xb4\x12\xf5\x99\xbe\x3b\xad\x45\x7d\xca\xe2\x9c\x2f\x4a\x0e\xae\x1d\xef\x0f\xda\x02\x53\x42\xbe\x08\x2a\x78\xdf\x09\xbe\x40\x27\x38\x25\x5f\xdc\x71\xa9\xf2\xf2\x36\x8a\x83\x53\x42\x81\x25\x3a\xa9\x4c\x65\x9f\x91\x88\xf6\xc5\x06\x81\x09\x31\xa7\xab\xe5\xc0\xae\x74\x52\x9f\x0a\x3c\xd5\x5e\xf3\x0b\xdb\xaf\xa8\x50\xbd\xf5\x3b\xa5\x8f\xd4\xa8\x5e\xfc\x3d\xed\x17\xac\x6b\x0f\xf6\x7c\x83\x2c\xad\x31\x9a\x42\x38\x91\x15\x88\xc2\x88\x9a\x02\x75\x8d\xa7\x35\x11\xd2\x2a\xe1\x11\x64\xa0\x02\x15\x06\x00\xac\x29\x00\x72\x58\xd5\x81\x0e\x91\x26\x42\x0c\x38\xc4\xd2\xa2\xf6\xf6\x85\xf2\x62\xed\xe0\x69\xa0\xa3\xf3\xb2\xfc\xee\x9c\xe0\xe5\x97\xb4\x89\xf4\xe5\x97\x5a\xed\xee\x9e\xac\xaa\xbd\x03\x86\x31\xb7\x3b\x9b\xc7\xa6\x85\x86\x54\x12\x51\x19\x96\xab\x6e\x4d\x9b\xe7\x63\xc9\x71\x2c\x1c\xad\x91\xf1\x4a\x2b\x15\x9b\x43\xcb\x54\x8d\x6c\x5d\xda\x1c\xd0\x93\x76\x07\x60\x65\xdf\xf9\xb7\xc8\xe1\x4f\xef\x96\x3d\xc9\xf3\x59\x52\xc0\xdd\xfe\x22\x87\x6b\x45\x91\x8f\xac\x74\x47\x24\x40\xb5\xec\x7c\xbb\xb9\x8a\x34\xd2\x83\xb8\x95\x41\x83\xd9\x60\x73\xd4\x35\x52\xaf\xe7\xb7\x34\xa3\x70\x1a\xd1\x92\x56\x75\xda\xcd\xcd\x4a\x6e\x0c\x45\x7a\xa9\x2c\x93\x27\xa2\x56\x2f\xea\x89\x54\x28\x6d\x70\xe9\x59\xad\x10\x6a\x4b\x2e\xda\xbe\xb8\x61\x25\xa2\xa3\xd3\xe3\xf2\x5e\xde\x52\x52\x19\x0d\x8b\x93\xba\xba\xb0\x52\x93\x55\x3a\x8e\x97\x9a\x96\x9e\x27\xca\x39\xa1\xbe\x18\x81\x48\x6b\x38\x35\x98\x6c\x7d\x2a\x6a\x61\x33\x42\xf7\x94\xb0\xeb\xd4\x1a\xdd\x5a\x3b\x1b\xad\x99\xf9\x59\x38\x5a\xec\x3b\xb9\xaa\x94\xa7\xb3\xa3\xfa\xa0\x55\xc8\xb9\x51\xad\xa5\x86\xf2\x25\xe1\xef\xb7\xe3\x03\x9a\x89\xa3\x83\x8d\xa5\x73\xf6\x90\x0e\xed\x0f\xa7\x8a\x63\x1b\x4d\x8f\x1a\x15\xe8\x68\x58\x2a\xb0\x5c\x2b\x12\x63\xdc\x64\x3d\x5e\x80\x65\x46\x02\x39\x32\x28\x0a\xe9\x32\x6f\xe6\xa1\x24\x92\x86\xa1\x2d\x53\xee\xe6\xfd\x29\xd1\xba\x34\x33\x54\xe9\x94\x9e\xd4\xf5\x1f\x4b\xf4\x77\xd3\xa9\x7c\x2f\xe4\x2f\x07\xe1\xef\x19\x29\xb7\xfe\x27\x79\xb0\x4f\x74\x6a\x31\x96\xcb\x72\x93\x68\x51\x5e\x8c\x4b\x61\xc6\x4a\xe6\x43\x2b\x88\xca\x4b\xc3\x81\x43\x3d\x17\x6f\x8d\x4a\x8d\xae\x3d\xad\x84\xaa\x9b\x87\xe2\xf5\x1a\xd8\x1a\x3e\xdb\x60\xe3\x80\xf4\x0a\xbc\xb4\x14\xa3\xa0\xe8\x24\xe4\xee\x4c\x85\x08\xc2\x9a\x28\xb4\xfa\xec\x28\x3b\x18\x89\x25\xc4\x0d\xa2\xcc\x6c\xdd\x9c\x4f\x0b\x38\xce\x47\xc2\xfb\xcf\xfc\x9c\xcc\xb2\x74\x7a\x0a\xfc\x33\xe5\x0b\x8f\x45\xb3\x77\x43\x3e\xbf\xfd\x24\xd4\xca\x0a\x12\xea\x0f\xbb\x72\x91\x00\xad\x56\x43\xf5\xa4\x1a\x2b\x2d\xf8\x52\x78\x3e\x4c\x4e\x54\xa6\x16\x83\x1c\x4e\x33\x29\xc3\x3b\xe5\x1e\x58\xbe\x08\xd0\x44\x50\xed\x4b\x52\x8a\x55\x96\x8a\x20\x5f\xe8\x73\xbf\xfd\x3e\x53\x3e\x7e\xa0\xc0\xee\x15\xf9\xfe\x3e\x8c\xcd\xae\xcf\x96\x52\x10\x59\xd3\xb5\x68\x28\x5b\xf3\xd1\x8b\xbe\xf3\xfe\x8b\x67\xa1\x8f\x6c\x15\x98\x7f\x7a\x1e\x8c\xbf\x67\x8b\xff\x68\x53\x5c\x0b\x8d\xeb\xab\x44\xd7\xb0\x73\x83\xba\x9d\x86\xc0\x94\xda\xf2\x6a\xd1\x4c\x28\xa5\xb8\xd1\xe0\xb3\xaa\xdb\x40\x90\x09\xa9\x49\x1c\x9f\x85\xe8\x45\x19\x47\xca\x03\x27\x5d\x51\xe9\xb0\x90\x0a\x15\xe6\x8b\x9c\xc4\xb4\xa6\xed\x46\xb9\xcb\x2e\x41\x1a\xf6\x56\x2c\x8c\xcd\xff\xfe\x7b\x93\x54\x33\x2d\x93\xec\x4f\xdf\xdf\xf3\xaf\x57\xbb\x00\xc1\xa5\xd7\x03\x9c\xc7\x6f\x86\xe1\x69\x55\x54\x10\xaf\x09\x1c\x16\x58\x56\x45\x8c\xa8\x30\x8c\xa0\x29\x44\x67\x69\xc8\xa8\x84\x67\x89\x8a\xa1\x4a\x14\x5e\x05\x1a\x02\x44\x40\x82\x88\x38\xac\x40\x16\x21\x05\x7a\xf8\x4d\x3f\xb3\x13\x72\x84\xdf\xc2\x4d\xfc\x16\x18\xe6\xf2\x2b\x97\xd6\x77\xd9\x37\x5f\x0e\xca\xf3\xd9\x0c\xdf\x27\x06\xd3\x1f\x59\x29\xa1\x9a\x18\xc6\xc2\xa4\xab\x32\xa8\xd8\x74\x93\x99\xcc\xaa\x51\x17\xe6\x75\xa3\x1d\xc1\xd1\x29\x97\xe5\x36\x8e\x70\x84\xdf\x09\x5f\xe7\xbf\xc3\xef\x07\xf1\xe0\x19\xfc\xae\x30\x63\x72\xe4\x91\x89\xbd\xbc\xa5\x8c\xd9\xc7\x8d\x0a\x5f\x1e\xf0\x10\x99\x83\x39\x0c\x67\xa6\x51\x5d\xc7\x24\x0f\x73\xcb\xd1\x74\x25\x8c\xc4\x88\x3d\x02\xe5\x34\x4c\xb5\xf2\x19\xcd\x9c\x6a\xf5\x10\xa2\x93\x4e\x34\x07\xeb\xa6\x6e\xae\xc2\x21\x23\xc2\xcb\xe5\xf8\xa2\xe0\xc8\x63\x38\x8a\x24\xc7\xb5\x5c\x69\x3e\xf8\x10\xfc\x7e\x70\xbd\xb3\xc6\xcf\xde\xe4\xd0\x1f\xf1\xc3\x98\x95\x8e\x48\xdf\x8f\xdf\x4f\xf2\x4f\x04\xe1\x7f\x84\xdf\x3f\xe9\xfc\x2e\xfd\x58\xfc\xd1\x13\xb1\xc8\xf4\x96\x7c\x7e\xfb\xfd\x6c\xeb\x8b\x1f\xb8\xfe\x49\x81\x6c\x73\x7a\x4d\xbe\x5b\xf8\xfd\xa8\xac\x6b\xfc\x4c\xe5\x0e\xf4\xbc\xb5\xee\x81\xde\x16\x9a\xef\xc6\xef\x20\xfc\x13\x56\x30\xfe\x5b\xfc\x9e\x90\xfc\xb8\x9d\x1d\x27\xaa\x76\x73\x4a\xaa\xb1\xa6\x30\x61\xd3\xa2\x38\x66\x99\xda\x2a\x83\x51\x71\xa9\x80\xc4\x54\x29\xcb\x66\xad\xd7\x05\x63\x9a\x70\xb0\x89\x66\x2d\x32\x4f\xad\xea\x0d\x2d\xa4\x17\xc3\x7c\x2a\x69\x95\xe5\xa6\xcc\xcf\x2b\x66\xa3\x25\x93\x61\x69\x11\x8b\x96\x3e\x17\xbf\x75\x0c\x91\x8e\x54\x20\x30\xba\xa6\xa9\x1c\x43\x04\x42\x0b\x82\xc0\x29\x44\x64\x58\x02\x45\x45\xe7\x19\x44\x68\x01\xa9\x50\xe4\xa0\x42\x38\x01\x6a\x1a\xe0\x54\xb0\x6e\xe0\xbd\x13\x0e\xbd\x2e\xfe\xe6\x6e\xe1\x37\x03\x84\x6b\xef\x94\xde\xdc\x3c\xd9\xf8\x79\x36\xfa\x8e\xf9\xba\xfe\x08\xad\x36\x81\x70\x50\x34\xee\xf7\x66\xe9\xd9\xfc\xc4\xbb\x8e\xa2\xe9\x7c\x4a\xa8\x34\x95\x5a\xa4\x91\x36\xc2\x0b\x5d\x50\x1a\x6e\x24\x92\xb1\xcc\xf9\x5c\x6c\x8d\x95\xac\x3a\x80\x61\x5a\xe4\x26\x8b\x76\xa1\x95\xe7\x66\xfd\x78\xac\x55\xca\xe2\x04\xa3\x40\x9c\x68\x4c\x56\x8d\xf6\x04\x8b\xf1\x5c\x72\x90\xa6\x5d\x49\x8e\x15\xfb\x72\x32\x95\x1b\xac\xa4\xf9\x3d\x68\x7c\xbc\x5a\xb9\x88\xc6\x91\xa3\xd7\x38\x06\x89\x66\xe1\xc1\xbe\xd1\xc3\x08\x3c\xb1\xc5\xb9\x61\xb7\xb7\xff\x0b\xf9\x07\x8a\xe6\x8f\x66\xc0\xc4\x91\xfd\x3e\x0f\xed\xb0\xd9\x8c\x0c\xef\x8a\xa6\x7f\x4c\xb4\xba\x91\xef\x5a\xb4\x7a\x16\x4d\x8e\x1b\x04\x88\xc6\x72\xec\x81\xde\x91\x6f\x1d\x7f\xae\xa3\xc9\x0b\xa3\xd1\x47\xf8\x6f\xd1\x04\xf4\x17\x69\xcd\x2d\xc5\x5b\xa3\x6c\x38\x1e\x5e\xb8\x18\xc8\xf2\xc4\xd0\x63\x31\x68\x0c\x1d\x77\x59\x6d\x86\x15\x66\x64\xc7\x07\x5c\x97\x19\x85\x72\xb5\x7c\x4f\x72\x2d\x45\x9b\xd5\xad\x36\xb6\xf3\xed\xd1\xd8\x06\xb5\x39\x29\x99\x18\x48\xa5\x5c\x28\x57\x52\xbb\xcb\x6a\x2e\x26\x7d\x2e\x9a\xa8\x2c\xad\x8a\x82\x80\x11\x8d\x55\x01\x13\x8d\x51\x14\x11\x23\x05\x69\xba\x22\xf2\x8a\x08\x38\xc2\x30\x1a\xe4\x00\xaf\xb3\x84\xe7\x19\x86\x07\x90\xe1\x08\xaf\xf2\x04\x42\x0e\x20\xc1\x43\x93\x57\x45\x83\xe8\x26\x9a\x40\x8f\xe7\xf5\xbb\x27\xdb\xf6\xcf\x46\x83\x71\x5f\xe7\xff\xc8\x68\x10\x9a\x35\xfd\x68\xe6\x3b\x8a\x06\xa5\x44\x6b\x69\xc6\x97\x74\x34\xa3\x67\xda\xcb\xde\xa8\x91\xcb\xea\xdd\x51\x4f\x4b\xbb\xe9\x64\xb3\x81\xac\x6e\x55\x5b\xb6\x11\x9e\x19\x72\xb4\x90\x6c\xa5\x2b\xa5\x4c\x71\xa0\x9a\x39\x2b\xc1\xe6\x11\x6f\x8c\x07\xd3\x7a\x92\xef\xf5\xa7\x8b\x58\x32\x92\x16\x98\x50\xd2\x5c\xf6\x14\xa9\xf4\xb2\x68\xf0\x78\xfe\x0f\x10\x8d\x19\xb1\x43\x7f\xf8\xb3\xa9\xf7\x45\x63\xaf\xe3\x1f\x28\x1a\x3d\x9f\xcd\xfd\x99\xe6\x77\xe9\xc7\xe2\xcf\x5d\xd9\x52\x3f\x7e\x7f\x62\xb4\x95\xaf\x30\x4d\xf6\x51\xfc\xfe\x99\xb2\xf5\x67\xf1\xfb\x68\xed\x18\x24\x1a\x3b\xce\xa6\x7a\x0a\x1f\xe8\xdd\x15\x0d\xbe\x30\x1a\x7d\x84\xff\x16\xbf\xa5\x76\x3f\xa3\x36\xb3\xad\xd4\x58\x18\x9b\x99\x44\xbb\x35\x77\x43\x51\x1c\x07\x23\x30\xd0\x34\x65\x6a\x44\xf2\x4c\xda\x74\x27\xa1\x54\x29\xc5\x6a\xdd\x61\x5a\xb2\x42\xe5\xa5\xba\xec\x2a\x5d\x66\x36\xc9\x8c\x2a\x5c\x4d\x9f\x24\x0a\x48\xce\xa9\xb2\xb9\xd2\x59\xa2\x67\xe2\x4e\xe4\xb3\xf1\x5b\x07\x3a\xa7\xab\xda\xa6\xc0\x94\xe5\x04\x05\xf3\x34\xa3\x8b\x84\x27\x48\xe5\x68\x56\x10\x35\x56\xd1\x18\x11\x89\x98\x85\x22\x2f\x40\x51\x10\x68\x45\xe1\x69\x16\x28\x2c\x11\x38\xee\x6d\x73\x90\x01\xbe\x08\xbf\x6f\xee\xc6\xb2\x0c\x77\xe5\x05\xfa\xbb\xbb\x27\x45\x6e\xcf\xe2\xf7\xcd\xdd\xd8\x47\xf1\xbb\x06\xf2\xc5\x7a\x60\x9f\x3d\x76\xc8\x23\xfc\xce\x56\x5a\xa5\x68\x14\x86\x62\x89\x92\xe0\xd8\xc9\xec\xc2\xe0\x2b\xba\x99\x0f\x6b\xa6\xe0\xa2\x91\xa4\x36\x87\x31\xd3\xa8\x31\xe9\x90\xc6\xcb\xab\x2e\xac\xf1\xc3\xae\x68\x80\x7e\xa3\xe0\xe8\x78\x64\x58\xad\xba\x92\x16\x35\xc9\x28\x45\xda\xcb\x94\x63\xa2\x6a\x84\x53\xb3\xf3\xbb\xe2\xc7\xfb\xf0\xfb\x68\xd5\x11\x04\x3f\xaf\xec\xc6\xde\x87\x9f\xaf\xe3\x1f\x68\xfd\xf0\x2e\xe6\x09\x86\x8f\xd5\x12\x10\xbd\x98\xe3\x41\x7f\xde\x8a\x72\x0f\xfe\x3c\x13\xdf\x06\x97\x6f\x58\xca\x72\x57\xe5\xbb\x15\x3f\x06\x19\x4b\xd7\x76\x13\xef\xc2\x9f\x17\xe2\xdf\x23\xfc\xb7\xf8\xe3\xa6\x7b\x52\x2a\xdb\x64\x73\xed\xd8\x72\xe9\xa8\xb3\x44\x76\x9c\x0e\xa9\x8c\x48\xeb\x4b\x66\xda\x8a\x2c\x48\xad\x40\xd2\x55\xd5\xe4\x18\xab\x5a\x88\xd5\xab\x93\x46\x8c\xce\x56\xf2\x2d\x7e\x21\x4e\x70\xa6\xd7\xab\x3b\x26\x04\xd1\xb4\x14\x37\x53\xc6\x52\x77\x73\xc9\xe1\x7c\xf6\xd9\xf1\x23\xbd\x8e\xb5\x00\xa0\x59\x41\x17\x58\xa8\x6a\x9c\xce\x01\x1a\xf1\xba\x0a\x05\xa2\x40\x5e\x51\xd7\xb1\x25\xc3\x12\x84\x69\x11\xe8\xb4\x80\xb0\xc2\x60\x1a\x63\x91\xe6\x05\x56\xd8\xd4\xde\xf0\xbb\xf8\x31\xe0\xc1\x9f\x47\x76\x13\x59\x06\x01\xf1\x0a\xfe\xa0\xc3\xef\x76\x6d\xeb\x99\x3d\x97\x7d\x70\x39\xf6\xc8\x66\xe2\xa7\x15\x03\x15\xfa\x35\x17\x86\x8e\x44\x49\xee\xe5\x2d\xa5\x26\x63\xa6\xac\x17\xe1\x94\x44\x40\xb5\x9c\x2e\xb7\x9a\x26\xb6\x42\x83\x91\x46\xd8\x48\xac\x27\x4c\x80\x3c\x46\x13\xc8\x96\x04\xab\x9c\x5f\xc0\xb2\x38\x75\x4d\x55\x1f\x5b\x4d\x1b\xa5\x0b\xea\xc4\x98\xbb\x5d\x6c\x57\xc5\x01\x9f\x19\xe5\x96\x7d\x0d\x8b\x28\xc9\x95\xbb\xb9\x0f\x81\x1f\x57\xe9\x36\xcb\xbc\x8c\xac\x58\x16\x64\x4b\xa1\x79\xab\x12\x15\x57\xcd\x59\xb3\x5e\x65\x16\x46\xd1\x68\x4d\x2b\x0a\x8c\xcd\x46\xa5\x2c\x11\xa4\xed\xf4\xdf\x65\x0f\xfd\x71\x36\x9c\x8f\x26\xcb\x43\x95\x29\x4d\x5b\xb4\xe8\x3e\x30\x65\x3c\x18\xbe\xaf\xa7\x8c\x98\xa7\x89\xf7\x5b\x68\xe7\xe8\xa7\xb4\x44\x7d\xa5\x45\xb9\xbe\x42\x83\xc8\x25\x49\xde\xd9\xa7\x24\xfd\x90\xe2\xb2\xf5\x47\xdf\xcf\xf9\x82\xbf\x3f\xa5\x53\xf8\xfe\x31\xfe\x7e\x45\xbe\x73\x90\x14\x7f\xae\x7f\xdf\x6d\x90\x3d\xd1\xbf\x47\xfe\xf1\xe0\xfc\xb3\x86\x63\x16\x6f\x84\x88\x1e\xfc\xc3\x4f\xbf\x07\xda\xcd\x3c\xc8\x8e\xf2\x33\xa5\x74\x76\xf9\xe3\xc1\x94\x31\x31\xb5\xb8\x10\x6e\x70\x6c\xb2\x9c\x97\x87\xf1\x1e\xd1\x26\x7d\xbe\xd2\x86\xa8\x2b\x17\x92\x4b\xbb\x54\x31\xa7\x76\xb3\x17\x5b\xf6\x64\x26\x59\x4f\xd2\x3c\xad\x2d\x42\xa3\x1e\x99\x39\x03\x6e\x39\xc9\x46\xe9\xc8\xc4\x2d\xd2\x55\x6b\xd2\x5a\x65\xf2\xd0\x66\x1c\x7d\x98\x90\x3e\xb9\xe8\x85\xc3\xac\x80\x05\x08\x89\x2a\x20\x56\x57\x45\x95\xd3\x10\x52\x91\x8a\x89\x22\x60\x45\x25\x18\x20\x5e\x85\x0a\xc6\x1c\x54\x10\xc7\x29\x34\x16\x90\xc0\x88\x10\x03\x41\x54\x91\x06\x3d\x98\x62\x5e\x04\x53\xe2\x6d\x98\x12\xae\xfc\x12\xeb\xee\xee\xc9\x19\x97\x67\x71\x2a\x79\x6e\xdc\x1e\xf9\xed\xc3\xe3\xb6\x34\x2c\xc7\x82\x8d\x23\x49\xc8\x35\xe7\x47\x33\xfe\x11\x4e\x25\xe4\xe6\x64\x2c\x8b\x85\x4c\x61\x81\x7b\xbc\x15\xe9\x95\x45\x8e\x93\xd8\x48\x6b\x54\x08\x2d\xa7\xd9\x7c\x2e\xe7\xaa\x52\x76\x98\x75\x32\x7d\x3a\x07\x89\x58\xaa\x0e\x23\x33\x69\x35\x9d\x0f\xba\x72\x74\xd6\xa5\x8d\xb9\x30\x69\xb6\x23\xf4\x20\xe9\x92\xd6\x5c\x98\x58\xd6\x4a\x2d\x49\x3f\x23\x4e\x9d\x5d\x37\xfc\x18\x9c\x52\xcf\xd1\xff\x74\x9c\x7a\xc2\x9f\x36\x9f\x8f\xc6\xa9\x67\xfd\xfd\x41\x9c\x7a\xb2\x7f\xdf\x15\x52\x3c\xd1\xbf\x4f\xe2\x54\xed\x90\xba\x7b\x0a\xa7\x5a\x65\x32\x19\x54\x01\x6b\xa1\xf8\x24\x39\xe9\x26\xe2\x49\xc6\x1c\xc4\xba\x71\xa3\x85\x50\x86\x75\xc0\x7c\x09\xe7\xd2\xb4\x36\x9d\x4f\x8a\xad\x55\x1d\xc1\x48\xa1\x96\x10\x62\x05\x14\xad\x48\xa5\x4c\x28\x86\xb3\xb1\xe5\x58\x1b\x24\x71\x89\x40\xae\x1f\x5b\x4e\x8c\x7e\x7e\x21\x7d\x72\x38\xc5\x12\x16\x21\x51\x07\x1a\x2f\x6a\x0a\x07\x89\xca\xea\x48\x41\x0c\x23\x20\x85\x07\x2a\xcd\x88\x2c\xc3\x08\x80\xd5\x68\xc4\x22\x8d\xe8\x34\x54\x10\x42\x90\x88\x0a\x82\x1a\xe2\x14\xe2\xe1\x14\xfb\x12\x9c\x3a\xfa\xd9\xbd\xcb\x48\x24\x5e\xf9\xc5\xcb\xdd\xdd\x93\x73\x8f\xcf\xe2\x54\xca\xd7\xf7\x3f\x6e\x3b\x4e\x4b\x8c\xe1\xbc\x7d\xe4\xb1\x47\x38\x95\x2c\xc5\x7b\x05\x35\xc3\xa7\x73\xc5\xd6\x42\x2f\x37\x22\xa1\x45\x01\x32\xf2\xa0\x18\x9b\x0c\x66\xb3\x62\x22\x9c\x1c\x0b\x72\x23\x56\x4d\xe5\xaa\xe3\x64\xd2\x60\x73\x13\x9b\x09\x57\x6c\x92\xce\xd6\x16\x05\x83\x99\x24\x2a\x93\x56\x3c\x9d\x34\x24\x2b\xc3\x73\x76\xbc\x55\xc2\x45\xf9\x95\xdb\x71\xaf\xc3\xa9\xb3\xeb\x86\x1f\x83\x53\xfe\x9a\x90\xd7\xe0\xd4\x27\x6e\xef\x6e\x3e\x8f\xe2\xd4\x67\xfb\xfb\xe7\xe2\x54\xfc\x28\x5d\xfb\x83\x71\xaa\xe0\x29\x21\x3d\x8b\x53\x9a\xd4\x90\xb9\xb9\x6d\x0d\xe6\x62\x3f\x2e\xc6\x5b\x49\x24\xa3\xa6\x5a\x29\x09\x85\x49\x25\x24\x08\x8a\x40\xcc\x79\xb9\x95\xcf\x75\x17\x85\x81\x4a\xb2\xdd\xe5\x64\xa6\x8b\x19\x97\x1d\xb8\x55\x99\xcf\x12\xab\x9d\x19\x77\x6b\x03\x92\x8a\x76\x6d\x7b\xe4\xd4\x7b\x11\x4b\x28\x7d\xf6\xb6\x13\xa3\xf0\x3c\x8f\x69\x8e\x61\x20\xa3\xab\x08\x03\x8d\x66\x21\x21\xb4\x00\x78\x96\x10\x15\x09\x18\x63\x8e\x28\x1a\xc0\x48\x05\x98\x20\x5d\xe0\x68\x4e\x24\x02\xd0\xb1\x06\x68\x51\x7f\xdb\xbc\x24\x08\xbe\x28\x9e\xba\x59\x84\xc8\x03\x9e\xbf\xbc\xed\xb4\xbb\x7b\x72\x16\xfe\x59\x9c\xba\x52\x86\xe8\xad\xa7\x83\xe7\x41\x8e\x7c\x4b\xdf\xcd\xcb\x11\x29\xcb\xab\xab\x56\x7c\x56\x89\xf4\xb4\x3a\x89\xb1\xba\xd2\x2c\x24\xa7\xcd\x38\xa6\xa3\xb1\x49\x76\x1c\xd7\xd5\x50\x29\x6d\x5a\x46\x31\xeb\x86\x69\xa6\x55\x37\x6a\xe5\x44\x76\xa9\x77\x19\x41\x88\x67\x72\x19\x47\xc9\xa7\xe5\xee\x28\xee\x44\xd3\x7d\xb7\x3b\x64\xf4\x3e\x9a\xdb\xe1\x75\x98\x7e\x07\xe6\x24\xfd\x3e\x7e\xb8\xef\x9f\x53\xbd\x4f\x00\xcc\x39\x2e\xc1\xf0\x97\x69\x3d\x8a\x39\x2f\xcc\xf1\xe4\xce\xd1\x0f\x86\x39\x87\xe7\x7f\x74\x0e\xcf\xff\x89\x48\x3f\x6f\x8e\xf1\x1c\xe6\xc4\x9e\xeb\xdf\x77\x65\x89\x4f\xf4\xef\x11\x66\x05\xc1\x1c\xf7\xa8\xac\xc1\xbf\xbc\x79\x04\x73\x3e\x6a\x72\xf8\x4c\xcc\xd1\x44\x8d\x57\x04\xc8\x63\x80\x19\x95\x67\x01\xcf\x20\x8d\x15\x74\xc2\x30\x3a\x06\x40\x17\x89\x0e\x21\x0f\x01\xa3\xd2\x80\x15\x18\x16\x43\x15\x0a\x58\x44\x3c\x27\x00\x46\xd7\x38\xcd\xc3\x9c\x57\x6d\x35\xdd\x2c\x75\x58\x8b\x72\x39\x36\xda\xdd\x3d\x79\xd7\xc9\xb3\x98\x73\xa5\xd4\x21\x18\xe6\x1c\x72\x1a\xe7\x31\x27\x97\x8a\x08\x4e\x86\x0c\x17\xd5\x49\xbc\x90\x2d\xa6\xb2\xfd\x08\x30\x53\xae\xaa\xdb\x09\x3b\x3a\x9f\xda\x4e\xaa\xe7\xf4\xea\x24\x93\xac\xcc\xe9\x54\x94\x1d\x8f\xa2\xa4\x8b\x32\x89\x58\x21\x3b\xd6\x6b\xd1\xac\x4a\x33\x26\x97\x24\x55\x67\x91\x76\x94\x70\xd4\x4e\xa6\xe3\xe1\x66\xac\xf4\x53\x62\xce\x59\x3c\xff\x31\x98\xe3\x67\xf4\x63\x30\xe7\xc5\xf9\x38\xff\xe7\x69\xcc\xf9\xc0\x7c\xe1\x07\xec\x1b\xbd\x2b\x45\x7f\xa2\x7f\x9f\xc4\x1c\xd3\x53\xe2\x20\x8f\x9f\xfe\x9d\x98\xf3\x51\x93\xc3\x67\x62\x0e\x8f\xd7\x81\x0e\x2f\x10\x4c\x0b\x00\x6a\x84\xc7\x88\x66\x44\x55\x64\x35\x96\x25\x9c\xc6\x42\x9d\xe1\xa1\x00\x69\x1e\x20\xc4\x0a\x90\xe6\x34\xcc\x20\x5a\xa1\x91\xc2\xf3\xaa\xc6\xa8\x1e\xe6\xbc\x6a\xdf\xe8\x66\x79\x3c\x0f\x19\xee\x1a\xe6\x78\x77\x4f\xde\x65\xf5\x2c\xe6\x5c\x29\x8f\xf7\x30\x27\x78\x7e\xe2\x3c\xe6\x20\xa1\xde\x1e\xcf\x84\xb6\x88\x99\x66\x4e\xec\xce\xf8\xde\x32\x97\x75\x69\x25\x62\xb7\x39\x27\xe3\xc4\xcb\x35\x36\x91\x69\xb6\xdc\x45\x8b\xce\x0d\x24\x57\x4c\x8b\x72\xde\xae\x94\xdb\x26\xcc\x81\xfe\x70\x21\xc6\xe3\x09\x37\x3a\x73\xe3\xf1\xb6\x21\xc4\x7a\x8b\xd9\x24\xb6\xc4\x91\x9f\x13\x73\xce\xe2\xf9\x8f\xc1\x9c\x67\x73\x2f\xe7\x31\xe7\x07\xe7\xd6\xfc\x9f\x77\x98\xf3\x13\xe5\xfe\x3e\x00\x73\x8e\xcb\xd7\x7e\x30\xe6\x74\xbd\x52\xcd\x83\x3c\x7e\xfa\x77\x62\xce\x47\x4d\x0e\x9f\x89\x39\x00\x60\x45\x54\x75\x95\xd0\x0a\xab\xb2\x90\x85\x9a\xa0\x28\x3c\xe2\x05\x4d\x03\x22\xab\x68\x8a\x02\x55\xc4\x02\x1e\x41\xa0\x29\x0a\xa3\x60\x40\x74\x51\x10\x10\xd0\x79\x06\x33\xec\x1a\x31\xd8\xd7\x1d\xf0\x65\x6e\x61\x0e\x62\x00\x4d\x5f\xc4\x9c\xdd\xdd\x93\xb7\x1e\x3e\x7b\xc4\xf7\x6c\x4e\xdc\xfb\x3c\x71\xc4\x97\x39\x54\xaf\x1e\x8d\x83\xc3\x11\xdf\x6c\x5d\x49\xa5\x42\x30\x4b\x8c\xd5\xa2\x6b\xaa\xb1\x14\xcb\x67\x92\xcb\x88\x0b\xb8\x50\x52\xa4\x4d\x18\x2a\x33\xb4\x90\x16\x57\xf9\x21\xad\x77\xd3\x0d\xda\xd4\x4d\x26\x9e\xb2\xb2\x75\x87\x9e\xd4\x61\x28\x5a\x1b\xdb\x90\x86\x98\x8e\x20\x29\xc7\x27\x33\x36\x6b\x46\xb2\x52\xea\x75\x47\x7c\x8f\x1a\x05\x38\x62\xdb\x2f\x1c\xec\x7b\xe1\x73\xcf\x11\xa7\x97\xf0\xbf\x30\xd7\xdc\x28\xd1\xde\x4c\x21\xaf\x3e\x96\x7a\x81\xe7\x75\xdc\x7d\x35\xff\xf7\xf6\xb8\xc8\xff\x20\xc4\x27\x1f\xe1\xda\x75\x85\xaf\x04\xfc\xf8\x73\xb6\x04\x3c\xfa\x9c\xad\xb6\xb2\xbe\x3b\x0e\x7e\x8f\xad\x5e\xd1\x57\x05\x35\x18\xff\x5d\x09\x78\xdd\xe9\xf6\x51\xcd\xe5\xb3\xc5\x44\x54\x9b\xe7\xfa\x7d\xcb\xd2\x53\x09\xa6\x6a\xb2\x3a\x83\xf5\x26\x97\xd4\x95\xb9\xc9\xe4\xe8\x66\x3b\x24\x0d\x15\xac\x85\x74\xb5\x66\x74\xdd\xc6\x0a\x8f\x9b\x4d\x36\x5d\x19\xcd\x9a\x4a\xdd\x6e\x25\x1d\x69\x65\xa9\x93\x99\xa1\xca\x8e\xd4\xfd\xe4\x9a\x05\x56\xe0\x69\x51\x20\x80\xd5\x75\x65\x1d\x10\xd1\x40\xe5\x68\xa8\x0b\x10\x6b\x0a\x47\x03\xa4\x73\x1a\xa4\x55\x1a\x2a\x40\xc0\x00\xf1\x9c\x20\x6a\xb4\x42\x18\x4d\xd0\x30\xf1\x0e\xfc\xb0\xaf\x3b\x42\xcc\xde\xc6\x2b\x1a\x5c\xde\x0b\xda\xdd\x3d\x79\xb7\xee\xb3\x47\x90\xce\xee\x57\x78\x9f\x57\xe3\xd5\xd1\x91\xa2\xf8\x58\xb0\x9d\x18\x2b\x4d\xa1\x45\xda\x83\x48\x15\x96\x93\xa9\x74\x79\xb9\x68\xe0\x25\x9e\x32\x3a\x57\xeb\x13\x09\xcc\xd9\x10\xc8\xae\xfa\x59\x79\x69\x88\x66\x22\xe7\x08\x64\x28\x25\xd9\x61\xac\xd7\x8b\xa5\x17\xd1\xb4\x90\xec\x2d\x94\x44\xa8\x59\x0d\xab\xa3\x92\x33\x85\xf7\xd5\xca\x3d\x8c\x57\x41\x8e\xf4\x1c\xbd\x12\xc2\x3f\x3f\x3e\x70\x24\xf7\x25\xfc\xfd\xfd\x7b\xdf\x91\xa2\xb3\x78\xf5\xec\x31\x18\x3f\x7e\xdf\x75\x0c\xe6\xd5\xfc\x23\xf7\xf3\x3f\x32\xd4\x27\x1f\x99\xdd\x76\xc5\xa3\x78\x15\x7b\xce\x56\xc7\x78\xe1\xf7\x8f\xcf\xe8\xab\x6b\x6b\x9b\x3b\x8e\x2c\x35\xcc\xe5\x74\x5e\xec\x46\x51\xa3\xc7\x8d\x4a\xf1\x62\x5d\x56\xbb\xc3\x64\x36\xde\xb6\xd3\x13\xa4\x85\x87\x95\x3c\x1b\xab\xc6\xfa\xa8\x34\x2b\xe4\x9c\x6a\x26\x4b\xab\xad\xe5\x6a\xc1\xd7\x24\xdd\xa8\x15\x12\x72\xce\x94\x53\xe6\x9c\x24\xe3\x8e\xc2\x69\x45\x71\xd9\x8e\x2e\x51\xfd\xb3\x6b\xec\xa0\xc6\x33\x40\xd0\x54\x9e\x88\x3c\x44\x0a\x21\x8c\x88\x79\x51\xe7\x05\x88\x78\x55\xe7\x75\x06\x2b\xaa\xce\x6a\x0c\x0f\x91\xa6\x30\x2a\xe2\x79\x9e\x45\x8a\x06\x45\x01\x73\x84\x65\x69\x0f\xaf\x98\x17\xe1\xd5\xcd\xda\x05\xe4\xbd\xe1\xf0\xea\xcd\x93\xf7\xb7\x3f\x8b\x56\x37\x5f\xa0\x14\x28\xb3\x7e\x0b\xad\xb2\xf2\x32\x39\xac\x94\xb8\xae\xc2\xe2\x12\x22\xb3\xc2\x90\x1d\xb5\xf9\x61\xa5\x9a\x8a\xa3\x41\xa5\xb7\x74\xac\xb0\xb1\x2c\x82\xe9\x8a\x31\xc6\x49\x4b\xd5\x18\x21\xac\x65\x8d\x29\x1a\xd6\x67\xb9\x44\x73\x6e\xf1\xcb\x51\x1a\x8d\x8c\x85\x16\x9b\xe6\xb3\xa9\x86\x91\x12\xab\x4a\xe9\x63\xa2\xab\x97\xa0\xc5\x81\xff\x67\xa3\x55\x2c\x08\xff\x8f\x41\xab\x9c\xf4\x18\x5a\xbc\x1a\xad\x1e\x3d\x34\x7a\x64\xa8\x60\x68\x15\xad\xcb\xdb\x8a\x91\xcf\x41\xab\x1f\x84\x16\xd2\x07\xf4\x55\x00\xb4\x72\xaa\x29\x52\x4f\xc7\x46\x91\x59\x6f\x1c\x73\x79\x81\x6f\x1a\x6d\x73\x52\x4f\xe7\xba\xcd\x69\x39\x93\xcc\x2c\xfb\xa1\x6c\x2a\x5c\x41\x45\x92\x19\x90\xde\x82\xd1\x57\x22\x98\x66\xd0\xb4\xde\x10\xe6\x6d\x3d\xda\xb7\x33\x2d\x73\x8a\xb3\x71\x50\x60\x81\xd3\xc3\xa9\x3e\xcc\xbb\x9f\x1d\x5d\xf1\x2c\x22\x58\xc1\x48\x67\x14\x95\x43\x34\xaf\xa9\x10\xb0\x90\xe3\x18\x9d\xb0\x88\x85\x1c\x4b\x13\x0d\x60\x1a\xeb\xb4\x06\x44\x41\x13\x19\x05\x28\x58\xe5\x14\x5e\x67\x54\x9e\x66\x55\x0f\xad\xd8\x17\x65\x03\xef\x88\xae\x58\x74\x2d\x1b\xe8\xdd\x3d\xf9\x95\x90\x67\xb3\x81\x37\xa3\xab\x40\x2f\x6c\x48\xde\xc8\x06\x26\xab\xb5\x0c\x69\xe3\x76\x33\xbc\xb4\xcc\x92\xb6\xb2\x13\x2d\x30\x18\xb6\x27\xf3\x5e\xad\xad\x21\xcb\x74\x6b\x4a\x7f\x5c\x1a\x65\x07\xa1\x66\xb9\x25\x4c\x5b\x96\x13\x92\x52\x74\x9b\x99\x4c\x6a\x4c\x29\x4e\x23\xb9\xce\xd6\xcb\x4e\x5d\xad\xd5\x66\x33\x93\x43\xfa\x24\xae\xad\xba\x77\x55\x78\x7f\x76\x36\x30\x72\x7e\x9c\x7d\x5a\x36\xd0\x8f\x97\x77\xf1\xff\x98\x6c\xe0\x85\xec\xe4\xa7\x65\x03\x1f\x7d\x49\xde\x91\xa1\x7e\xba\x17\x56\x7c\xc4\x0b\x05\x83\x66\xe3\xa4\x0f\xe8\xab\x47\xf8\xef\x5e\x2f\x9f\x2f\x8d\xb9\xe1\x78\xa8\x87\x33\x86\x16\x61\x0a\x4e\xbb\x5f\xa9\xd4\x47\x76\x34\x5e\x1e\x32\x53\x83\xc0\xf2\xb4\x30\x8c\xb6\xa6\x55\x4e\x8b\xf7\x97\x9c\x61\xac\x58\xa9\xdf\x36\xc9\x64\x5c\xd5\xa4\xa6\xe2\x94\x9b\xbd\x7a\x62\x51\x5f\x94\x2b\xa1\x90\x6e\xba\x21\xab\xce\x14\x3e\xbb\x32\x5c\xd1\x78\xc0\x0b\x00\x43\x06\x09\xba\x4e\x54\xc4\x88\x04\xea\x3a\xa6\x35\x85\x55\x35\x0e\xea\x9c\xa0\x60\x45\x57\x10\x64\x09\x60\x31\x47\x2b\x1a\xad\xf0\x9c\xa2\x0b\x98\x81\x0a\xab\xbf\x6d\x42\xab\x57\xbd\x90\xe8\xe6\xee\x95\xc0\x03\x91\xbb\x88\x57\xeb\xbb\xfc\x9b\xef\xb7\xa8\x9e\x8d\xaf\xae\xec\x5e\xd5\xce\xf9\x49\xe4\xa6\x4f\xf9\xe8\xed\xd7\x50\x72\x64\xb0\xe2\xa6\xe5\x6e\x8d\x8b\x2f\x26\x85\xa9\xd0\xc2\x03\x14\x51\x34\x15\x44\xdc\xee\x4c\x4e\x83\x78\x7f\x6a\xb7\x57\xe1\x6c\x37\x31\xaf\xd2\x72\x53\x84\x2d\x01\xb6\x6c\xad\x52\x9f\xd2\xf9\x62\x19\x0c\x95\x5e\x45\xb2\xdc\x44\x69\x38\xab\x14\x5b\xf2\x92\x9b\xe5\x79\x34\x66\xa3\x77\x60\xd4\x71\x55\xc8\x45\x8c\x92\x9e\x7b\x29\x5f\xdf\x3c\xd8\xf4\xc2\xe7\x1e\x8c\x78\x09\xff\x60\x3b\x56\x9f\x92\x55\xda\x7e\xae\xcf\x7b\x3f\x28\xab\x75\x6b\x47\xe8\x89\x17\x6c\x05\xc7\x80\x17\xda\xe2\x11\xfe\x5b\x0c\x68\xe7\x42\xca\xa0\x15\x2f\x94\x55\xdc\xb7\x67\x89\xc4\xb8\x30\x6f\x30\xcd\xbc\xa4\xb4\xb2\x8b\xa8\x16\x69\xa1\x09\xad\x86\x97\x6c\xc4\x91\xc5\x5e\x3c\xac\x35\x8a\xf9\x46\x86\xa9\x0d\x15\xb7\x5f\x05\x5a\xba\xc1\xd6\xba\x99\x6c\x79\x90\x56\x40\x9f\x8e\xe4\xa6\xca\x8a\x4c\x79\xf2\xd9\x31\x8b\x8a\x04\xc0\xf1\xa2\xca\x02\x5a\xa5\x45\x41\x41\x0a\xa7\x33\x3a\xc4\x3c\xa6\x01\x56\x21\x0d\x45\x0c\x78\x4d\x67\x44\x8c\x04\x5d\x61\xb0\xca\x6b\x22\xa3\x62\x8e\xc1\x1a\x4b\x38\xa2\x79\x18\xf0\xaa\x4a\xed\x3b\x30\x80\x81\x97\x63\x96\xdd\xdd\x93\x5f\x11\x7c\xb6\x6a\x2e\x18\x06\x5c\xfe\xbc\xaf\x0c\xf3\xdd\xdf\x57\xfe\xc8\x91\xe4\x7c\xd0\x56\x97\xa9\xc6\x08\x17\x67\xb2\x1b\x1b\x96\x05\x59\x63\xb5\x18\xcc\x91\x31\xdd\x9f\x66\xdd\x64\x9c\x31\xb9\x72\x02\xf4\xa7\x76\xba\x97\x99\x84\x99\x5c\x04\xae\xca\xbc\x12\x4b\xda\xa1\xb9\x35\x67\x38\xa3\x9f\x11\x69\xa3\xd7\x4f\x36\x26\xd5\x45\x7f\x95\x89\xf5\x06\x85\x8f\xc0\x84\x00\xd5\x73\x4f\x57\x31\xbc\x90\xff\x2b\x31\xe1\xc9\x53\x2c\x4f\x63\xc2\x47\xf0\xbf\x59\x5d\x76\x03\x1b\x02\xc8\xf4\x52\x6c\x08\xc0\xff\x49\x6c\x28\x0b\xe9\x44\x33\x67\xc4\xc7\xa3\x3e\x5a\x64\x4b\x5c\x4d\x8f\x24\x49\xb2\x24\x56\x93\x13\xcd\x42\x06\x2a\x2f\x34\x2e\x54\x2b\xbb\x29\x34\x59\xb6\x2a\x93\x99\xb8\x92\x34\x15\x90\xd1\x7c\xc1\x87\x9d\x4c\x2e\x1f\x6a\x59\xcb\x99\x66\x59\xad\x05\x9c\x0c\x84\x96\xb0\xec\xb2\xed\xd8\x27\x63\x03\xad\x31\x10\x69\x2a\xd1\x05\x9e\xe6\x09\xcf\x88\x8a\x8a\xb1\xc2\x62\x56\x81\x2a\x86\x44\x20\x3c\xcf\x22\xa2\xb0\xbc\xc6\x73\x2a\x16\x34\x51\x80\x0c\x52\x35\x51\x20\x0a\x04\x98\x20\x0f\x1b\x5e\x55\x51\x7d\x33\x9f\x25\xf0\xac\x08\xaf\x60\x83\x77\xf7\xe4\x77\x61\x9f\xc5\x86\x2b\xf9\xac\x2b\xd8\x70\x3d\x07\x70\x42\xef\x08\x0b\x84\x09\x57\xd0\x43\x09\x09\x10\xac\xcd\x43\xbd\xaa\x5d\x8d\xa6\x24\x8b\x68\x99\x65\xbc\x4b\xc2\x99\x59\xa8\x5c\xcb\x3b\x13\xe4\xcc\xd0\xb8\x62\x65\xa5\x52\xbc\x31\x99\xc7\x53\xb3\x45\x34\x11\x99\x0e\x41\xb3\x57\x59\x14\xac\x51\x22\xdc\x6d\x74\x47\x29\x63\xde\xe7\x31\xec\x5a\xb9\x9f\x10\x0b\xce\xce\x2f\x0f\x54\x52\x7f\xe0\x89\x42\x4f\xc8\x20\x95\xd4\x2f\xb4\xcf\xfb\x9c\xd2\x4f\x63\x9f\xfb\x2a\x91\x5f\x7f\x0a\xf4\xe9\x5c\xd2\x0b\x6d\xf2\x08\xff\x2d\x56\xe8\x99\x69\xd5\x0c\xf7\xba\xf9\xe4\xc8\x54\x8b\x56\x8d\x07\x73\x43\xca\x24\xcd\x8a\xd3\x6b\x25\x67\x4b\x3b\x3c\xa8\xc7\x94\xcc\x14\x65\x43\x7c\x6d\x12\x9d\xcb\x91\xfa\xc4\x89\x54\xb2\x42\xa9\xd7\x55\xc6\x5a\x9c\xad\x39\xd5\x49\xba\x37\x63\xe3\x56\xda\x48\x39\xa9\xd0\xc8\x6d\x65\x3e\xfb\xe5\xa2\x9a\xc2\xac\xe7\x7d\x16\x13\x41\x44\x1c\xcf\xd0\x1c\xcf\x32\x2a\xd6\x68\xa8\x8a\x2c\x81\x8c\xa2\xab\x00\xb1\x0a\x43\x33\x84\x08\x0c\x81\x2c\x54\x74\x04\x20\xe6\x34\x11\xb0\x3a\x54\xde\x36\x41\xc4\x26\x97\x14\x29\x17\x5b\xc9\x54\x96\x8e\xa6\x98\x78\xbe\xc4\x46\x9a\xd9\x78\x2e\x1f\xcb\xc6\xd3\xb5\x7c\xb1\x46\x27\x5b\x4c\x3b\x17\xaf\x24\x0b\xf9\x5a\x54\x2e\x48\x95\x06\x2a\x45\x51\xa1\x49\x27\xdf\x36\x8f\x5f\x85\x08\x08\x00\x7b\x71\x83\x7e\x77\xf3\xf8\x57\xba\x3d\x3f\x4d\x64\x85\x64\x69\x56\x1a\x28\x19\x3a\x29\x31\x8d\x7a\xbf\x6c\x67\x46\xfd\x26\x00\x7a\x42\x70\xb2\x29\x34\x02\x72\x79\x9e\x6e\x84\xa5\x26\x23\xed\xf1\x61\xf3\xb9\x12\x3b\x78\x9f\x00\x73\xc1\xe0\x98\x5e\x7d\x36\x8f\x8b\x1b\x7c\x90\x5a\xfd\x92\x5a\xac\xd2\x09\xae\x37\x31\x23\xa3\x6e\x22\x41\xba\x62\x5a\x18\xb2\x2a\x94\xcd\xda\x70\x31\x18\xca\xc3\xa4\xe8\x4c\xda\x36\x10\x11\x8c\xf3\x85\x6c\x43\x27\xe1\x11\x3b\x18\xc7\xdd\x54\xc8\x49\x01\x03\x4e\xb2\x86\xcb\x49\x20\xbd\x6c\x98\x4a\xaf\x95\x6d\x70\x56\xec\x0e\x7c\x38\x71\xe8\x53\x7c\x38\xd2\xf9\x90\xe3\x3f\x9a\xbf\x22\x46\x38\x02\xb2\x20\x9d\x58\xba\xbd\x79\x1e\x0e\x5b\x00\x2f\xc7\x16\x14\xf3\xc9\xc5\x2c\x1b\x5d\x16\x38\x37\x22\xab\x51\x4f\x47\xa6\xeb\xda\x05\xb3\x15\x46\x47\xc0\xea\x3f\xd1\x7f\x55\xb6\xdd\x58\x7f\x82\x7f\xbc\xda\x88\xd8\x4f\xf0\x97\xa4\x1f\xb7\x2e\x3e\x9b\xbf\x89\x04\xb7\x45\xc1\x6c\x5f\x55\xf3\x96\x2d\x9e\xed\x8b\xb5\x2f\x84\x54\x1f\xbd\x87\x6c\xf1\x9f\x44\x0a\x24\x63\x40\xec\x4d\x5b\x78\x3c\x6f\x5b\x91\x9e\x69\x15\x2b\x7a\x9a\x24\xf3\xe5\x34\x4c\xab\xed\x74\x39\x5d\x0e\x2b\x99\x11\x16\x8b\x44\x2c\x93\xbe\x01\x4d\x66\xc6\x4d\xd3\x99\xb2\x52\x29\xda\xd1\x7c\xca\xc5\x06\x6b\x93\x52\x3e\xaa\x0e\xc7\x34\xdb\x88\xc2\x29\xfe\xec\x93\xf6\xba\x88\x54\xac\xeb\x58\x11\x54\xc8\x03\x9a\xc1\x0c\x12\x04\x16\xf2\x9c\xaa\x00\x85\xd1\x75\x88\x31\xad\x61\x9d\x05\x00\xe8\x44\x67\x45\x8d\x86\x44\x57\x05\x16\x69\x9a\xa2\x2b\x04\x7b\xf3\x2e\xfd\xdc\xbc\x4b\xdf\x9e\x77\x2f\xbf\xd3\x65\x77\xd3\xfb\xe5\x7f\x1a\x1d\xf2\xf6\xc1\xe7\xdd\x2b\xeb\x72\xef\x13\x20\x87\x7c\x61\xde\x8d\x8c\x32\xe3\x4a\x77\x66\xcf\x33\x05\x1a\x34\xa3\x05\xbd\xa5\x37\x9d\x84\x2c\xd7\xdc\x79\x0b\x63\x59\x9f\x54\xa6\xfc\x72\x94\x1e\x0d\x63\x23\x1c\x4a\x35\xf9\x14\x4a\x75\xbb\x4a\xad\x9d\xb3\xd4\x92\xd6\x16\xd9\x54\x4e\xd2\x33\x5a\x49\xca\x4f\x9a\x4a\xaa\x80\x96\xce\x9c\x90\xdc\x3d\x79\xfb\x13\x87\xfe\xd8\x79\xf7\xd9\x79\xef\xc9\xb1\x3e\x41\xe1\x6a\x4c\x79\xe5\xbc\xfb\x89\xb9\xea\x5b\x79\xf3\xcf\x9c\xf7\xa4\x17\xcd\xbb\x02\x7b\x78\xfe\x42\xfe\xee\x6a\xde\xdc\x98\xd4\xac\x2c\x2f\x44\xfb\xae\x1b\x9f\xf7\x4d\x3a\x09\x51\xa4\x17\x89\x67\xd5\x44\x62\xd4\x4b\xf2\x03\x7b\xea\x8c\x8d\xf6\xb8\xc4\x8d\x66\x46\x3c\x64\x14\x96\xa9\x54\x02\x26\xaa\x99\xa4\x9c\x6c\xe8\x24\x1a\x93\x92\x4b\xb3\x26\xc5\xf0\x90\x5e\xc6\xa6\x82\x9d\x4b\x9a\xfd\xcf\xce\x9b\x23\x9a\x43\x1c\xaf\x40\x5d\xd1\x74\x81\x51\x80\x00\x69\xa4\x33\x02\x47\x74\xa2\xe9\x40\x04\xa2\xaa\x0a\x34\x50\x78\x55\x25\x08\xea\x50\x05\x82\x88\x34\xc8\xb1\x34\x52\x15\x0e\x6b\x9a\x37\x6b\x32\xcf\xcd\xbb\xb7\xd2\xe5\x10\x00\xc4\x5c\x7c\x87\xfe\xfa\xee\x7e\xc1\xcb\xf2\xc2\x21\x59\x1e\x7c\xe2\xbd\x52\x90\xea\x7d\x02\x14\x98\x5c\x9a\x78\xfb\x6c\x37\x52\x0a\x47\x24\xa5\x3b\xd1\xd1\xa4\x60\xb9\xd8\xed\xb6\x6b\xc9\x7e\x6c\xe8\x14\xdc\x58\x5e\x1b\x23\x3c\x6c\x97\xb9\x70\x7c\x20\xea\x89\x7e\x68\xb8\x90\x97\x5d\xa9\xdd\x58\xb5\x50\x38\xdb\x82\x6d\xa6\x12\xe7\x55\x30\x71\x20\xa2\xb3\x3d\x69\x30\x98\xd5\x85\x31\xb8\x27\x21\x72\xe2\xd1\x1f\x3a\xf1\x3e\x3d\xf1\x3d\x3b\xf1\x2e\xed\x52\x3c\xfb\xc2\x89\xf7\x33\x8f\x8d\x7d\xc4\xc4\x1b\x74\xe2\x93\x5e\x34\xf1\x06\x0d\x7e\xb6\x13\x6f\x2b\x94\x92\x6a\xc5\x79\x29\xc1\x66\xcc\x10\xdf\x9f\x64\x1b\x76\x2b\x51\x8f\xb0\x73\x4e\x89\xd9\xa5\x55\x13\x13\x7a\xdc\xa8\x11\x7d\xd1\x2e\x36\x17\x56\x78\xac\x96\x73\x96\x94\xa8\x3b\x74\x21\xbc\xa4\xf3\x0d\x0d\xf4\x88\x99\xcf\xd8\x79\x22\x1a\x6c\x29\x9d\xce\x42\x3d\xa3\xbd\x26\xd1\xf0\xdb\x6f\x5f\xbf\xfe\xf6\xf5\x2b\x95\xc7\x23\xf2\x9d\xc2\x8e\x43\xdc\x8e\xe3\x62\xd7\x39\xfe\xbb\x33\x1e\x90\xe5\x5f\x54\x75\x39\x26\xdf\xa9\x68\x21\x5f\xa9\x96\xa5\x54\xbe\xfa\x17\x55\x51\x7b\x64\x84\xbf\x53\xe3\xa9\x32\x34\xd4\xbf\xa8\xc2\xdc\x24\xf6\x77\x6a\x4d\xf1\xb7\xdf\xa4\x6c\x55\x2e\x53\x55\x29\x92\x95\xa9\x42\x3e\xdb\x3a\xa6\xf8\x1b\x45\x51\x94\x14\x8b\x1d\x51\x7b\xc7\x90\x2a\x96\x53\x39\xa9\xdc\xa2\x32\x72\x8b\xfa\xc3\xd0\xde\x49\xdb\xb5\xec\x71\x67\x64\x74\x6d\xec\x61\x84\xef\xfa\x45\x52\xfb\xa8\x9e\x93\xfc\x1c\xe3\x9b\xd2\xef\x60\x6e\xa3\xb6\xe3\xbb\xf4\xfe\xd7\x51\x2d\x8d\x6c\xff\x74\x97\xe3\xdd\x9f\x86\xe3\x4c\x89\xdd\x79\x89\x76\xa7\x6c\xcf\x29\x17\x48\x30\xaa\x96\x4f\x95\x6a\x32\xf5\xc7\xa1\xf9\x17\xea\xd0\x7e\xf7\xb7\xf7\xc0\x83\xa6\x79\x4d\xb7\x3e\xac\xf8\x43\x9d\x6a\x8d\x89\xe7\x0c\x9d\x31\xb6\x5d\x43\x35\xc6\xd8\x3c\xd2\xe4\xfc\xed\x17\x6b\x76\x9e\xc9\x35\x4d\xaf\x88\x75\xb7\xe6\x47\xab\xb6\xf3\xba\x5f\x6a\xf0\x62\xed\x2f\xb1\xb9\xa6\xff\x55\xd1\x6e\x5a\xc0\x73\x69\x65\xb9\xf1\xf6\x9d\x22\xa9\x7c\x4c\x6e\xde\xd0\x21\x5a\x96\xa5\xaa\xec\x35\x3d\xa5\x42\x15\xf2\xfe\xc1\x50\xab\xa4\xf2\x09\x4a\x71\x6d\x42\x8e\x47\xd7\x65\x69\xbc\x31\xf6\xbc\x3c\x1e\x9d\xfb\x24\xba\x30\xae\x95\x65\x07\xab\xaa\x35\x35\xdd\xc0\xe2\x1c\x48\x1c\x4b\x72\x12\x2a\x9c\xca\xe3\x35\xfe\x42\x6d\xff\xe8\x38\x64\x32\x25\xa6\xfa\xde\x60\xca\xb2\xd3\xc3\x4e\xef\x19\xc9\xd6\xcf\xdf\x27\xd6\xb1\xa7\xad\x9f\x3a\x27\xcd\x90\x68\xdd\x27\x3a\x6e\x4f\xe1\x3e\x89\xbc\xb6\x7b\xf3\x7c\xa1\xf0\x78\x3c\x34\x54\x6f\x3a\xb0\x6c\xed\xc2\x34\xdd\x21\x6b\xdf\xd8\xdc\x0f\x20\xe9\x16\x25\x3c\x81\x7d\xe4\x8e\xc5\x26\xba\x4e\x54\xbf\xab\xbd\x9f\xb5\x0c\xed\x0b\xf5\xfb\xe6\xe1\xdf\x2f\x09\x6b\x68\x2f\x12\xd3\xd0\xee\x16\x70\xe7\x7a\x6b\xf1\x02\x08\x6d\x8d\x3b\xe3\x57\xc9\xbd\xa5\x75\x2c\xfa\x05\xa8\x0a\xa4\xc9\x79\x05\xdc\xc5\xeb\x14\xd8\xd2\xba\xe0\xd3\x01\x55\x38\xa6\x70\x4e\x09\x6b\xbc\xf6\xca\x9e\x15\x48\x87\xad\xf0\x07\x1a\x41\x8d\x7f\xdd\xd0\xce\x76\xb4\x6f\xa6\xea\xe7\x6d\x7d\x4a\xee\x58\x64\xef\x7b\x9f\x8c\xe7\x25\x3a\xb6\xeb\xab\xc4\x7a\x47\xf3\xbe\xe9\xed\x9c\x80\xae\xd7\x25\xee\x33\xdd\x7a\xa0\x11\xdc\x25\x6f\xb9\x9f\x6b\x6b\x6b\x26\x0a\x76\xc8\xd3\xf8\x79\x8e\x98\x4f\x72\x8d\xf8\xe4\x3c\x6e\x7b\x53\x40\x4b\xd7\x9f\x00\xad\xf7\xa4\xee\x12\x6e\xd3\xf2\x9a\x68\x1b\xd9\x89\xfd\x32\xf3\xf9\xe8\xdd\x12\xd2\xd7\xfc\x1e\x49\x5f\x63\xc7\x13\x6a\xf7\x4a\x79\xd3\x9a\xaf\x91\xed\x2e\x99\xae\xcb\xb2\x93\x78\x68\x59\x83\xe9\xf8\x39\x89\x4e\x69\xdd\xdd\xa3\xde\x7a\xf7\x82\x7c\x63\x6c\xd8\x1d\xd7\x18\x91\x97\x48\xe8\xa7\x76\xdf\xb8\xdd\x0a\xf8\x85\xf2\x8b\xfc\x85\xda\x4e\xf1\xea\xd0\x72\x88\xd6\xc1\xee\x05\x25\x5e\x30\x6f\x6f\xe9\xdc\x92\xf8\xc1\xd5\xd1\x9a\xea\xcb\xac\xfb\x80\x61\x6f\xda\xcd\x30\x35\xb2\xe8\xf8\x96\x1c\x4e\xc7\x32\x3b\x58\xd3\x6c\xe2\x38\xcf\x1a\xf4\x26\x83\x93\x38\x6d\x7b\xdb\x17\x19\x79\x0d\x1f\x90\xfd\x79\x3f\xb8\x46\xfb\xb6\xc4\x67\x46\xd9\x29\xc1\xed\x2a\x7c\x4d\xcf\x5d\x8e\x83\xc7\xe0\x57\xa9\xde\x5c\xf6\xaf\x1b\xdd\x10\x74\xbb\x86\x5a\x93\xdc\x3b\xd1\x8b\xa4\x3d\x47\xfa\xe6\xf2\xed\x5e\x4f\x3e\x22\xfe\x6a\x67\x38\x21\x1d\x64\xbd\x79\x99\xdc\x68\x6c\xd9\xeb\x89\x6f\x46\x6c\xc7\xb0\xcc\xd7\x1b\xda\xcf\xe1\xb6\xf8\xbe\x07\xee\x57\x66\x3b\xf5\x04\xcc\x54\xdc\x67\xff\x23\x1e\x37\x35\x39\x6a\x7b\xbf\x12\x63\x9b\xcc\x0c\x6b\xea\x7c\x8a\x36\xe7\x98\xdd\x54\xeb\xdc\x43\xf7\xeb\xb7\x4b\xa2\x7c\x98\x4e\x3b\x06\x37\xf5\xb8\x98\xed\x3a\x25\xbd\xc7\xdb\x0f\x19\xda\x7e\xea\x67\x03\xe0\x47\x07\xf8\x29\xd1\xd3\x10\xea\x45\x23\xfc\x1a\x8b\x7b\x74\xb8\x11\xd7\x5d\x65\xf6\x3a\xf8\x7a\x4f\xf8\x2e\xd9\x6f\x83\xd8\x71\xb0\xfd\x11\x6e\xf3\x9e\x7e\xe0\x50\x7f\xb3\x88\xdb\x03\xf9\x2e\xc3\xd8\x51\x2c\x6b\x10\xd8\xca\x57\x68\xde\x5c\x22\xfc\xf1\x87\x46\x5c\x6c\x0c\x1d\xea\xeb\xff\xfc\x0f\xf5\xe6\x58\x43\xed\x68\x37\xed\xed\xfb\x77\x97\x2c\xdc\x3f\xff\xfc\x42\x5d\x6e\xa8\x5a\xda\x7d\x0d\xbd\x5c\xfc\xe5\xa6\x8a\x35\xed\xf6\xdc\xbb\xd8\x9f\x34\xbd\x2e\xc0\x49\x53\x9f\x08\x7f\x52\x8d\xa4\x5c\x96\x3d\x27\xa3\xfe\xa6\x18\xe6\xee\x8d\x68\x43\xeb\xe8\x47\xdb\x44\xf1\xcc\xe7\x6c\x47\x6f\xd9\x52\xf1\x42\x59\x4e\x25\xf2\xfb\x2d\x20\xaa\x2c\xc7\xe5\xb2\x9c\x8f\xca\x15\xdf\xae\xc8\xe6\x6e\x21\x4f\xd5\x8a\xb1\xb5\xcb\x94\xe5\x4a\xb5\x9c\x8a\x56\xd7\x5f\xc5\xe4\xac\x5c\x95\xa9\xa8\x54\x89\x4a\x31\xf9\xca\x3e\xda\x3a\xee\x38\xbd\xec\xf8\x52\x31\xaf\x33\xc6\x29\x9f\x1b\x9b\x64\x97\x24\x39\xb5\x8f\x3f\x6d\x74\xd6\x58\xdb\x85\xfe\x8d\x1d\xc5\x8b\x96\xd8\x86\xb2\x3f\xdc\x0e\xc7\x72\x9c\xb3\xc2\x2e\x4b\x70\xdd\x61\x1e\xb3\xc0\xfb\xa4\xd2\x0f\x34\xc3\x05\x61\x4e\x6d\x71\x26\x0d\xf6\x5a\xa7\xf0\xa7\x38\x7e\x06\x83\x5c\x76\x8d\x77\x39\xa4\x7b\xbd\xa3\x68\x39\x6e\xd7\x26\x95\x52\x96\xd2\xb0\x8b\xd7\x2e\x46\x69\xd3\xd1\x98\x52\xad\xd1\x78\x48\x5c\xb2\xd1\xe1\xff\x07\x00\x00\xff\xff\x57\x06\xc5\x82\x7b\x59\x01\x00") func ingest_asset_statsHorizonSqlBytes() ([]byte, error) { return bindataRead( @@ -246,7 +246,7 @@ func ingest_asset_statsHorizonSql() (*asset, error) { } info := bindataFileInfo{name: "ingest_asset_stats-horizon.sql", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} - a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x71, 0xae, 0x8, 0x80, 0x74, 0x4, 0xa8, 0xe, 0x59, 0x48, 0x69, 0x48, 0x47, 0x9b, 0xce, 0x9a, 0xa2, 0x36, 0xe2, 0x4d, 0xed, 0x66, 0x34, 0x50, 0x65, 0xb5, 0x65, 0x27, 0x6f, 0x2, 0x4, 0xae}} + a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x30, 0x2, 0xb5, 0xea, 0xc6, 0xae, 0xf3, 0x71, 0x59, 0x9a, 0xb0, 0xc, 0xe7, 0xc2, 0xd2, 0xe1, 0x65, 0xaa, 0x62, 0xd3, 0x95, 0x20, 0xa2, 0x4, 0xda, 0x19, 0x68, 0x25, 0x2b, 0xf7, 0x97, 0x6f}} return a, nil } @@ -270,7 +270,7 @@ func kahunaCoreSql() (*asset, error) { return a, nil } -var _kahunaHorizonSql = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\x7d\xf7\x8e\x22\x49\xd6\xef\xff\xf3\x14\x68\x34\x52\x4d\x5f\x7a\x86\xf0\xa6\xe7\xce\x95\x30\x89\x27\x81\xc4\xb3\x5a\xa1\x34\x91\x90\xb8\xc4\xbb\xd5\xf7\xee\x57\x98\xaa\xa2\x28\xa0\xa0\xba\xaa\x77\x77\xe6\x2b\xed\x8e\x68\x22\xe2\xb8\x38\xbf\x38\x71\xc2\xf1\xdb\x6f\x3f\xfd\xf6\x5b\xa0\xe0\x4f\x67\xed\x89\x2a\x15\xb3\x01\xc7\x9c\x99\x96\x39\x55\x01\x67\x3e\x18\xfd\xf4\xdb\x6f\x3f\x6d\xcb\x63\xf3\xc1\x48\x39\x01\x77\xe2\x0f\x9e\x2b\x2c\xd4\x64\xea\xf9\xc3\x80\xfc\x9d\xfd\x0e\x8f\x6a\x59\xeb\xc0\xa8\xdd\xda\x36\x3f\xa9\xf2\x53\x49\x2b\x07\xa6\x33\x73\xa6\x06\x6a\x38\x6b\xcd\xbc\x81\xf2\xe7\xb3\xc0\x9f\x01\xf0\xc7\xae\xa8\xef\xdb\xbd\xd7\xdf\xda\x7d\x6f\x5b\x5b\x0d\x6d\xdf\xf1\x86\xed\xc0\x9f\x81\x87\x4a\x39\x2e\x1e\xfe\x78\x24\x37\x74\xcc\x89\xd3\xb2\xfd\xa1\xeb\x4f\x06\xde\xb0\xdd\x9a\xce\x26\xde\xb0\x3d\x0d\xfc\x19\xf0\x87\x07\x1a\x1d\x65\xf7\x5a\xee\x7c\x68\xcf\x3c\x7f\xd8\xb2\x7c\xc7\x53\xdb\x72\xd7\xec\x4f\xd5\x0b\x36\x03\x6f\xd8\x1a\xa8\xe9\xd4\x6c\xef\x2a\x2c\xcd\xc9\xd0\x1b\xb6\xff\x38\xc8\xae\xcc\x89\xdd\x69\x8d\xcc\x59\x27\xf0\x67\x60\x34\xb7\xfa\x9e\xfd\x75\xab\xac\x6d\xce\xcc\xbe\xbf\xad\x16\xce\x96\x35\x23\x50\x0e\x47\xb2\x5a\x20\x15\x0f\x68\xf5\x54\xa9\x5c\x0a\xe4\xf5\x6c\xe3\x50\xff\xf7\x8e\x37\x9d\xf9\x93\x75\x6b\x36\x31\x1d\x35\x0d\xc4\x8c\x7c\x21\x10\xcd\xeb\xa5\xb2\x11\x4e\xe9\xe5\xa3\x46\x2f\x2b\xb6\x6c\x7f\x3e\x9c\xa9\x49\xcb\x9c\x4e\xd5\xac\xe5\x39\x2d\xb7\xa7\xd6\x7f\xfc\x08\x86\xf6\xee\xd3\x8f\x60\xb9\xf5\xab\x1f\xa7\xe0\x9e\xdb\xfd\xda\xed\x05\xdc\x3a\xf2\x35\x66\x47\xb5\x9e\x89\xef\xaa\xa7\xf4\x98\x56\x3f\xaa\x79\x20\x3b\x9b\xcc\xa7\xb3\x56\xdf\x1b\x6e\x45\x5b\xb7\x66\xeb\x91\x6a\xd9\xbe\xa3\x5a\xde\x74\x3a\x57\x93\xbb\x1a\xbf\xa3\xc9\xb3\x21\xde\x6a\x66\x3a\xaa\xa5\x5c\x57\xd9\xb3\x5d\x43\x7f\xe2\xa8\x49\xcb\xf2\xfd\xde\xf5\x86\x53\xaf\x3d\x54\x93\x63\x5e\xd7\xeb\xfb\xae\x7b\xa8\x3e\x55\xfd\xfe\x16\xd8\x3b\x93\xde\xd3\xe8\x2d\x13\x3c\xd7\xee\x9b\xd3\x59\x6b\xe0\x3b\x9e\xeb\x29\xa7\xd5\x57\x4e\xfb\xf6\xb6\xd6\x7c\x7d\xa3\x74\xde\xd0\x51\xab\xd6\x91\x1b\x0e\xa7\xe6\x6e\x48\x9a\xb6\xfc\xe1\x9b\x96\x7f\xd9\xda\x1f\xa9\x89\xf9\xd4\x76\xeb\x2d\xdf\xd1\xfa\x59\x92\xef\x92\xe2\xbe\xb6\x7b\x2b\xef\x1a\x4e\xd5\x78\xae\x86\xf6\x5d\x2a\x1c\x35\x1f\x4d\xd4\xc2\xf3\xe7\xd3\xc3\x77\xad\x8e\x39\xed\xbc\x93\xd4\xf7\x53\xf0\x06\x23\x7f\xb2\x1d\x38\x0f\xd1\xef\xbd\x64\xde\x6b\x4b\xbb\xef\x4f\x95\xd3\x32\xef\xf2\xc5\x47\x3c\xbf\xc3\x95\x0e\x60\x7e\x87\xd0\xc7\x2d\x4d\xc7\x99\xa8\xe9\xf4\x7a\xf3\xce\x6c\xe2\xec\x66\x08\xad\xbe\xef\xf7\xe6\xa3\x1b\x6a\x8f\xde\x12\x69\x5f\xcb\xf4\x26\x77\x12\x7e\x0c\x8f\x37\x37\xd8\x0e\x95\xdb\x31\xe3\xb6\xaa\x8f\xe4\xdf\xd1\xe4\xa6\xd1\xf5\xb1\xd1\x2e\x08\xde\xc1\xe4\x38\x68\xbe\xd5\x62\xb4\x6d\xd0\x99\xbd\xd9\x03\xd3\x17\x03\xd0\x36\x7c\xbd\xdd\xe2\x80\xd3\x5b\x2a\xfb\x7b\x39\xfc\x37\x2b\x7a\xd3\x59\x6b\xb6\x6a\x8d\xde\x26\xb9\xad\xe9\x8f\x6e\xad\xa9\x6e\xad\xf6\x18\x4d\xaf\x57\x56\xab\x51\xeb\x78\x76\x71\x63\xbc\x3f\xd3\x6c\x3b\xbd\xb8\xde\xc8\x5a\xdf\x14\x0c\xb7\xf6\x7d\x73\xc4\xbc\x35\xf0\xef\x85\xbc\x51\xab\xa7\xca\x6f\xeb\xf2\x34\xdc\x78\x43\xb7\xbf\x0b\x5a\x2d\x47\x4d\x67\xde\x70\xf7\xf9\xc6\xb6\x1d\x7f\xa0\x5a\x8e\x3f\x30\xbd\x5b\x5b\x6c\x13\xa6\xe3\x69\xe6\xd0\x1c\xa8\x5b\xa6\x99\x47\xf3\xb3\x2b\xd3\xcc\xe3\x59\xdc\xe8\xc6\x09\xec\x7e\xea\x72\x85\xe8\x61\x6e\x73\x2b\xbd\x9e\x5a\xb7\x16\x66\x7f\xae\x5a\xdb\x71\x5d\x5d\x21\x7c\x52\xf3\x66\x0e\x67\xa6\x4c\xad\x91\x39\x99\x79\xb6\x37\x32\x87\x57\xe7\xe1\x6f\x35\xbd\x5b\x86\xa7\x29\xcf\xbd\x12\x9c\x6f\x78\x37\xff\x9d\xc7\xdf\xc2\x6f\x5f\xf1\xd3\xe9\xef\x11\xb8\xcb\x54\xf6\x1f\x77\x99\xcb\x21\x8b\xdb\x21\xb8\x75\xa3\x04\x6d\x7f\x32\x6a\x0d\xbc\xf6\x61\x46\x79\x45\x84\x93\x9a\x37\xeb\x78\x32\x06\x5e\xe1\x70\x3a\x5a\xde\xca\xe1\xfe\xe4\xf0\x66\xca\x8f\x03\xca\x21\x91\xba\x46\xfe\xa4\xea\xdd\x3c\x6e\xa1\x7d\xb7\xdc\xdb\x81\xf0\x16\xc2\xbb\x01\xf3\x1a\xf5\x5b\x07\x85\x7d\xeb\x68\x3e\x5b\xc9\xe9\x01\xcf\xd9\xf3\x8e\x69\xf1\x70\x25\x5b\xbe\x91\xf6\x05\xb0\x7f\x00\xe5\x03\xcc\xae\x53\xda\xfd\xeb\x02\xa1\xa3\x91\xff\x7a\xc5\xfd\x68\x7e\xbd\xce\xc9\xc0\x7c\xbd\xf2\xb9\x04\xf6\xd0\xa2\xa4\x15\x2b\x9a\x1e\x7d\x47\x6f\x6d\x43\xe3\x54\x8d\xef\xe6\xfc\x82\xc8\xcd\xad\x1d\x75\x4b\xaa\x61\xb6\xdb\x5b\x0f\x78\xca\x0a\x67\x6f\xcf\x21\x1f\x9b\x59\x73\xbb\xa7\x66\x2f\xb3\x83\x9b\xc4\x6a\x31\x00\x00\x38\xb4\x88\x57\xf4\x68\x39\x95\xd7\xcf\xf4\xbe\xdf\x1a\x78\xfd\xbe\x37\xfd\x75\x9b\xb6\x4c\x67\xe6\x60\x14\x58\x7a\xb3\x4e\x60\xfb\xcf\xc0\xc6\x1f\xaa\xaf\x81\xe1\x7c\xa0\x26\x9e\xfd\xe5\xdd\xc4\xfc\xf9\xec\x0a\xbd\x5b\xa1\x73\xbb\x6f\x5c\x88\x90\xf7\x78\xc6\x79\x12\xb7\xb5\x3d\x24\xd1\xb7\x55\x3e\x64\xcc\x37\xeb\x76\x88\x96\xf7\xe8\xb2\x6f\x72\x63\xdd\xc3\xe8\x79\xbb\x3c\x4f\xb3\xe1\x1b\x24\x3a\x89\xb7\xd7\x2b\x9f\x84\xce\xeb\x95\x6f\xaf\x78\x12\xd3\x6e\xac\xbd\x0d\x26\xb7\x55\xbd\xd7\xbf\xfa\xde\x78\xee\x39\xde\x6c\xdd\x1a\xf9\x7e\xff\xf6\xa1\xe7\x69\xe0\x3a\x4f\x20\x9c\x48\x18\x5a\x22\x5c\x3e\x43\x64\xe0\x0d\x5b\xa3\x89\x67\xab\x5f\x0f\x48\xfc\xc7\x3f\xbf\xdc\xd0\xca\x5c\xbd\xa3\x55\xdf\x9c\xce\x7e\x35\x87\x6b\xd5\xdf\xed\xd6\xdc\xd0\xc2\xf5\x26\x67\x9b\x5c\x1e\x76\x9e\xf4\xd9\x8e\x98\xcf\xd2\x3d\x0d\x34\xcf\x82\x5e\xa1\xf1\xa8\xdd\x77\xd0\xd8\x2d\xfe\x6e\x9b\x3f\x0b\xff\x35\x70\x8f\x22\x3b\xd5\x6f\xa0\xa0\xd5\xcb\x9a\x5e\x3a\x21\xd1\x1f\xb5\xa7\xe3\xfe\x23\x6e\xa3\x49\x2d\x17\x7e\xc5\xe1\x8f\x9f\xf6\x1b\x75\xba\x39\x50\xdf\x1e\xbf\x0b\x94\xd7\x23\xf5\xed\xd0\xe4\x8f\x40\xc9\xee\xa8\x81\xf9\x2d\xf0\xdb\x1f\x81\xfc\x72\xa8\x26\xdf\x02\xbf\xed\xf6\xef\xa2\x86\xb6\xed\xaf\x03\xe5\x47\x7a\x3f\xbd\xa0\xf8\xb2\xf0\x40\x38\x9a\xcf\xe5\x34\xbd\x7c\x85\xf2\xbe\x42\x20\xaf\xbf\x24\x10\x48\x95\x02\x0f\x8f\x3b\x73\x8f\xdf\x4d\x77\x44\x1e\x4e\x39\x3f\xaa\x7f\xe0\xf9\x64\xa1\x37\xf5\x79\x61\x4b\x3d\x5f\x3e\xb1\x67\xa0\x96\x2a\x27\x9f\xc4\x3a\xde\xa2\x7b\xc1\xfe\x99\xca\x89\x20\xf7\x28\xff\x8a\xc8\xce\x00\x85\x6c\x68\xd4\x2e\x15\xb3\x81\xd1\xc4\xb7\x95\x33\x9f\x98\xfd\x40\xdf\x1c\xb6\xe7\x66\x5b\xed\xcc\x70\xe3\x96\xe2\xb1\xb8\x6f\x3b\xda\x41\xfc\x47\x5f\x7d\x96\xff\xb1\x6f\xcf\xd9\xf2\xc9\xb3\xdf\xa4\x1f\x30\xb4\x72\xc5\xd0\x4b\x47\xdf\xfd\x14\x08\x04\x02\xd9\xb0\x9e\xa8\x84\x13\x5a\x60\xa7\x7d\x2e\x57\xd9\x8f\x83\xa5\xb2\x91\x8a\x96\x77\x35\xc2\xa5\xc0\x2f\xad\x5f\x02\x25\x2d\xab\x45\xcb\x81\x5f\xe0\xf6\x5f\xa7\xbd\xf1\x26\x10\xbf\x4f\xbb\xb7\xc8\x7f\x98\x72\xe8\x9c\x72\xb7\x8c\x54\xdf\xa7\xdf\x0d\x1c\x9e\x54\x7c\xfa\xea\x5d\x1a\xfe\xfa\x53\x20\x10\x0d\x97\xb4\x40\x2d\xa9\xe9\x81\x5f\xe0\x3f\xe0\x3f\x43\xbf\xc0\x7f\xa0\x7f\xfe\xbf\x5f\xd0\xee\x33\xfa\x07\xfa\x67\xa0\xbc\x2f\x0c\x68\xd9\x92\xb6\x35\x8a\xa6\xc7\xbe\x9c\xb5\xcc\x0d\x71\xe0\x3b\x2d\xf3\x36\x87\xcf\xb6\xcc\xff\x7d\x8f\x65\x5e\xc7\xd4\x83\x1d\x9e\xe2\xf0\x6d\x86\x78\x0e\xdb\xaf\x28\xee\x24\x0e\x04\x4a\x5b\x5b\x05\xfe\x7c\x1e\x01\xbe\xee\xbf\x2e\x37\x0a\x5a\xe0\xcf\x63\x44\x7c\x39\x87\xda\x0f\x95\xf1\x94\xe0\x89\x88\x8f\x30\xbe\x5d\xc2\xb3\x53\xa0\xef\x95\xf2\x1c\xd1\x13\x49\x5f\x00\xf2\xa5\xb8\xcf\x5e\xf6\x5a\xda\x73\xd3\xbc\xef\x96\xf6\x0c\xd1\x53\x69\x8f\x41\x72\x55\xda\x6d\xe4\x72\x94\x6b\xce\xfb\xb3\xd6\xcc\xb4\xfa\x6a\x3a\x32\x6d\x15\xf8\x33\xf0\xf0\xf0\xc7\xcb\xd2\x6d\x16\xd9\xf2\x3d\xe7\xe8\xb4\xcd\x0b\x5d\x9f\x26\xdf\x07\xfd\x76\xe8\xba\x4d\xb7\x3d\x10\x9f\x56\xac\xf6\xba\x3c\xaf\xb3\x07\xec\x8e\x39\x31\xed\x99\x9a\x04\x16\xe6\x64\xed\x0d\xdb\xbf\x52\xf6\x65\x37\x53\xd0\x2b\xd9\xec\x5e\x3f\xcb\xec\x9b\x43\x5b\x05\x2c\xaf\xed\x0d\x67\xa7\x85\xfb\x7d\xfd\xbe\x67\x5a\x5e\xdf\x9b\x79\x6a\x7a\xbe\xde\xe3\xf1\x84\x1b\x2a\xee\x77\xb9\x5b\xc3\xf9\xc0\x52\x93\xf3\x95\x86\xf3\x41\x6b\x3a\xb7\xd4\x70\x36\xd9\x12\xf2\x86\x33\xd5\x56\x93\x93\x4a\x67\x77\x30\x6e\xd2\xd8\xed\x9b\xed\x4b\x54\x8f\xf6\x36\xce\xd0\xc2\xe8\x94\xd6\xc0\x9c\xce\xd4\xa4\xb5\x54\x5e\xbb\x33\x0b\x4c\x07\xe6\xd6\x0e\xa7\xfa\xcc\x3a\x13\x35\xed\xf8\x7d\xa7\xd5\xf7\x97\x6f\x57\x1a\x28\xc7\x9b\x0f\xde\xae\xd7\xf1\xda\x9d\x4b\xb5\xce\x1d\xe6\x78\xa5\xf2\x6b\xdc\xbd\xcc\x19\xbf\xd7\x21\xf7\xcb\x9d\x7b\xaf\x3c\x2c\x1f\xf5\xd4\xfa\x8c\x5d\x21\x05\xa7\x86\xbd\xd3\x8b\x87\xe6\x40\x9d\xa9\xc8\xc8\x69\xc5\xdd\x0a\xdf\x99\x9a\xf2\x95\x04\xdf\x6b\xc2\xc7\x24\xfd\xbb\xad\xf8\xb8\xd8\x7d\x03\xbc\x5f\xeb\xbb\x6f\x1c\x98\xa9\xd5\xa9\x8b\x1c\x7c\xf6\x3c\x0e\xa6\x23\x7f\x38\xf5\x27\xe7\x6d\xbf\x53\xfa\x20\xeb\x7e\x11\xf0\xd5\x6a\xbb\xb5\x6e\x3d\x92\xc8\xeb\xaf\x55\xa9\x94\x52\x7a\x22\x10\x29\x1b\x9a\xf6\xeb\xa1\xde\x6b\x43\x1e\x2d\x8b\xbc\xdb\x86\x47\x5b\x11\x7b\xf3\x79\xce\xf9\x31\xc7\x1c\x6c\x25\x7c\xad\xef\x99\xa1\xe9\x69\xbc\x3d\x6f\xba\xfd\xf0\x72\x09\xbd\xfe\xa0\x7f\xc6\xa8\x88\xd2\x2f\x57\x7c\xea\x74\x39\xe9\xbd\xe6\x38\xdd\xfb\x39\x78\xd4\xd3\x96\xd5\x05\x8d\x9e\xb7\xb7\xce\x61\xf7\xd5\x98\x78\xbc\xef\x75\x13\x78\x0f\xb6\x3f\xe3\xa3\x57\xcd\xfd\xda\x4e\xa7\x6b\x74\xef\xb5\xd3\xe9\x2e\xdc\x93\xeb\x9c\x11\xd1\x1c\x8d\xfa\xde\xee\xb0\x51\xe0\xd2\x32\xf4\x6b\x41\x2f\xad\x40\x3e\xae\x67\x1c\x96\x2e\x6f\x93\xf9\x69\xa1\xf3\x02\xd5\xc3\x34\x26\x6c\x94\xf7\x2b\x02\x70\xf7\x45\x4a\x8f\x1a\xda\x2e\x7d\x8f\x34\x0e\x5f\xe9\xf9\x40\x2e\xa5\x57\xc3\xd9\x8a\xf6\xf4\xef\x70\xfd\xf9\xdf\xd1\x70\x34\xa9\x05\xe0\x5b\xca\xbc\xdb\xec\xa7\x84\x5e\x41\xf6\xb0\x29\x14\x18\xaa\xd5\x6c\x61\xf6\x7f\x7d\xb8\xa0\xf1\xc3\xb7\x6f\x13\xd5\xb6\xfb\xe6\x74\xfa\xca\xd7\xf6\x87\xac\xce\x8f\x9d\x8f\x1d\xf5\x24\x89\xdd\x37\xbd\xc1\x76\x76\xd7\x3a\x4c\x93\xa6\x81\x5f\x07\xe6\x70\x6e\xf6\xfb\xeb\x2d\x29\xe5\x7c\xb9\xd8\x0b\xaf\xdb\x7e\x5e\x7f\x9c\x35\xe3\x39\xe1\x2f\x8c\x81\x97\x2d\x7b\x51\x8b\x63\x1b\xef\x4d\xfb\xaa\x6a\xeb\x14\x31\xc7\x81\xa3\xa2\xa7\x8a\x95\xc7\xf8\xf1\xf3\xcb\x53\x71\x67\x98\xee\x4e\xd6\xfd\xbc\x0d\x26\x57\xd4\xdb\x87\x15\x6b\x36\x51\x2a\xf0\xab\xe7\x7c\xf9\xe3\xfd\xcc\xce\x29\x73\x17\xfb\x73\x04\xbe\x5c\xea\xaa\xe7\x25\xf5\x8b\x9d\xf6\xba\xea\xa5\x50\x76\x51\xc2\x33\x2d\x6e\xed\x91\x6b\x02\xee\xfb\x66\xfa\xc2\x3a\x57\x15\x7a\x61\xa7\xb3\x7a\x7d\xbd\xaa\xc4\x73\xbf\xbe\x4b\xd6\x63\x4e\x1f\x28\xf4\x77\x4a\xf5\xdd\xb2\xdc\xe5\x70\xc7\x9b\x30\x6f\xba\xdc\xcb\xb3\xd1\x3f\xce\xe9\xae\x0b\x79\xce\xed\xde\x50\xeb\xac\xdd\x4e\xb4\xfb\x2e\xd7\x7b\x5b\xe2\x97\xdc\x3e\x58\xf8\xef\x96\xee\x03\x24\xba\xe4\x86\x29\xbd\xa4\x19\xe5\x40\x4a\x2f\xe7\xaf\x8d\xa1\xbb\xe8\x56\x0a\xfc\x0a\xbf\x06\x1e\xc0\xe1\x0f\x72\x21\x10\x73\x2d\x57\x61\x2c\x15\x74\xa9\x4d\x31\x81\xdc\x66\xae\x72\x5c\x85\x6c\x40\x95\xb0\x94\x0d\x09\x06\x18\x12\xac\x6c\xc2\x2c\x2c\xa4\x80\x16\x90\x36\x76\xe5\xc3\x97\x3f\x7e\x3a\xac\x4d\x3e\x6f\x2b\xfc\x3e\x55\xb7\x46\xba\xaf\x01\xf8\x35\x30\x9b\xcc\xd5\x97\x3f\xb6\x93\x83\x72\x47\x05\x9e\x77\xf6\x43\xc7\x47\x40\x02\xe6\x44\x05\xda\xfe\x36\x6f\x98\xf9\x01\x4b\x05\xe6\xc3\x89\xea\x9b\x33\xe5\x6c\xff\xfd\xc4\xe1\x71\xd1\x65\xfa\x35\x60\xcd\x67\x01\x6f\x16\x70\x7c\x35\x1d\x3e\xcc\x02\x03\x73\xb6\x9d\x93\xb8\xfe\x36\x65\x9b\xce\xbc\x61\xfb\xac\xe1\xae\x8e\x0e\x4f\x26\x44\x42\x10\x09\xa8\x14\xf4\x6b\x00\x7e\xf9\xe3\xfd\x94\x04\x15\x52\x62\xc1\x84\xbc\x4c\xe8\x0d\x5f\x79\x2d\x14\xf9\x6e\x5a\x4f\x62\x89\x3d\xa9\xf3\xb3\xd2\xfd\x09\x82\xef\x9e\x93\xee\xcf\x2a\x3d\x4d\xa0\xae\x65\x4a\xbb\x54\xea\x96\xe4\xfc\xf3\x12\xab\x2b\x29\xc7\x8b\x43\x18\x1f\x94\x70\x1c\xd3\xfc\x61\xe9\xc6\x35\x45\x02\xf9\x9a\xae\xc5\x02\x91\xc6\x1b\x1a\xed\xcf\x9e\x5d\x57\xe8\x89\xd6\x49\xf1\xef\x9e\x73\x49\xb6\xc7\x93\x31\xdf\xeb\x75\x07\x3a\x27\xf1\xf8\x68\x09\xe8\x6a\x2c\x7e\x7b\xaa\xf8\xf3\xee\xac\xfd\xcf\x17\xbc\xf9\xca\x92\x80\xa3\x66\xa6\xd7\x9f\x06\xba\x53\x7f\x68\x5d\x76\xb6\xc7\xe3\x44\xdf\x6b\x87\x03\x9d\x83\x1d\x1e\x17\x91\x2f\xc8\x76\x74\x7f\xe9\x26\x14\x9e\xbb\x3a\x75\xbe\xe1\xc1\x2c\xc7\xa3\xd3\x6e\xe5\xe2\x51\x8e\xc7\x2c\x0a\x9c\x70\x38\x1a\x64\x6f\xaa\xff\x74\x7f\x29\x70\xe5\x30\xda\x69\x9b\x89\xda\xc6\x99\x37\x1a\xed\xeb\xce\x47\xce\xcd\x75\x9f\x5c\xe7\xf0\xcf\x93\xab\x5d\xaf\x74\x81\xaf\x56\xbc\x66\x66\xbf\x65\xfb\xde\xf0\xc2\x96\x80\xab\xd4\xee\xf4\xcf\x85\x1d\x08\x73\xaa\x5a\xae\xba\xd4\xd7\xbb\xe2\x89\x9a\xaa\xc9\xe2\x52\x95\x81\xb9\x6a\xcd\x56\xad\xdd\xaa\x97\xb7\xb9\x54\x6b\x34\xf1\x67\xbe\xed\xf7\x2f\xea\x75\xda\x47\x8f\xce\xa2\x4c\xe7\xb0\xbe\x7a\x58\x39\x9d\xdb\xb6\x9a\x4e\xdd\x79\xbf\x75\xd1\x51\x0e\x8a\x9b\x5e\x5f\x39\x6f\xd5\x3a\x88\x7e\xc1\x85\x2e\x43\xef\xc2\x29\xc0\xef\x45\xe2\x85\xd3\xc0\x6f\xc4\xc5\xfb\x93\xd7\xcb\x63\xdc\xbd\x2a\x7f\x6c\xa8\xbb\xca\xe3\x47\x85\xbe\xbb\x14\xfd\xce\x50\x78\x95\xd7\xeb\xd0\x78\xbe\xfa\x95\x50\x79\x74\x46\xf6\xc3\x7c\xf3\xad\xc5\xfe\x5b\x12\xda\xdd\xba\xae\xbd\x57\x65\x17\x25\xbf\x33\x48\x1e\x46\x07\x7f\x3e\xb1\x9f\x6e\x0f\x5e\x08\x4f\x8f\x43\xce\xc3\xc3\xb7\x6f\x97\x37\x24\x2e\xe3\xe0\x70\xb8\xfb\x7b\xcd\x79\x78\x4c\xe0\xde\xe5\xa7\xeb\x73\x8a\xc3\xb0\xf9\x9e\x08\xb7\x3b\xc4\x7f\x91\xed\xc9\x53\x06\xd7\x2a\x1d\x5e\x57\xb8\x56\x65\xbf\x23\x71\xb6\xc2\xeb\x47\x21\xde\xa8\x77\x95\xdd\x53\xad\x2b\x1c\x77\x22\x79\xd3\xc3\x7d\xfe\x80\xe5\xfb\x7d\x65\x0e\x1f\xe3\x96\x67\xab\xd6\xf0\x45\x8c\xde\x7f\xf7\x32\x6e\x3f\x5f\x72\x6d\x9d\x44\xf4\x17\xd7\x6c\x4f\x0b\x27\xfe\x7c\xe8\xec\x5e\x14\xe9\x7b\xa3\x91\xd9\x56\xaf\x89\x7a\xd3\x96\x5a\x99\xf6\xec\xa5\x5c\x47\xf7\x5b\xce\xbe\x39\xb1\x53\xb7\xb5\x7b\x95\x24\x10\x4d\x6a\xd1\x4c\xe0\xd7\x5f\x8f\x4d\xff\xff\xfe\x0c\x80\x2f\x5f\xde\xa2\x75\xae\xfd\xa3\xb9\xff\xef\xab\x1e\xb8\x81\xde\x8b\xde\x38\x21\x7f\xd2\x55\x7b\x09\x7f\xba\x94\x77\x7e\x28\x08\xf7\x37\x22\x76\x50\x7c\xc6\xcb\xc1\x57\x86\xfe\x2c\x30\x9c\xf7\xfb\x5b\xdd\xce\xfa\xf7\x71\x85\x4b\x4e\xf9\xaa\xce\x13\x7c\x5f\x91\x5f\xf8\xfd\xf9\x40\x3d\x9e\x87\x39\x4b\xfd\x4a\x15\x73\xd1\x3e\xfb\x7d\xc7\x6b\x77\x5a\xc3\xcb\x45\xce\xd9\xa2\xbe\xbf\xbc\xd0\x68\x5b\x72\xbe\xcd\xe9\x6d\x96\x73\x26\xd8\xd5\x39\x4f\x78\x57\x74\x9e\xf2\x6e\x50\x7b\x8b\xf4\xbe\xd2\x79\xda\xfb\xb2\x73\xc4\x7f\x0a\x04\x0a\x46\x2a\x17\x36\x1a\x81\x8c\xd6\x78\xe9\xe9\x5f\x5f\xf5\xea\xd7\x67\x2f\x79\xb1\x59\x9f\x37\x02\x86\x56\xc8\x86\xa3\x47\xe7\x02\x8f\x2e\xbe\x5c\x4d\x06\x02\xb3\xc9\xfc\x59\xea\xa7\xd9\xfe\x97\x9f\x02\x4f\xc7\x06\x0f\xda\x86\x4b\x81\x5f\x7e\xf9\x29\x10\x88\x68\x89\x94\xbe\x03\xdc\xbe\x42\xc0\xf1\x16\xbf\xda\xe6\x74\xf6\xeb\xaf\x6a\x35\xdb\x46\xb5\x5f\xd5\xc8\xb7\x3b\xfb\x47\x95\x66\x5f\x02\xff\x27\x00\xb7\x5e\xfe\x25\x60\x3e\xa6\x0a\x5f\xf6\x6c\xbf\xfc\x9f\xed\x7f\xff\xf8\x29\x10\xd0\xf4\xd8\x1f\x3f\xfd\xf2\xcb\xf3\x99\xc4\xa7\xe3\xc6\x8f\xe7\x12\xdf\xab\xed\xc7\xaa\x7a\xc4\xe7\xdb\xb7\x27\x46\x07\x6d\xee\x55\x64\xbf\x98\x7b\xfe\x5e\xd5\xc9\x72\xad\xa3\xa6\x3f\x05\x5e\x2e\xcc\x3e\x8b\x72\x1a\x7b\xbf\x06\x1e\x76\xe3\xca\xc3\xb7\x6f\x8f\xf7\x9a\x5e\x9d\xec\xb8\x78\x09\xec\x35\xe3\xc3\x20\xf5\x82\xf9\x69\xab\x6b\x73\x96\xf3\xd7\xd9\x3e\x60\x00\x3d\x7f\x35\xf2\xc6\x94\xe5\x9e\xcd\x8f\xf7\x24\x2d\x6f\x5d\x06\xfc\x98\xb4\xe5\x0d\x2e\x3f\x2a\x71\xb9\x53\xd9\xef\x4c\x5d\xde\xe0\xf6\x3a\x79\xb9\xd4\xe0\x4a\xfa\xf2\xe2\x02\xe8\x7b\x7d\xf5\xca\xa5\xd2\x83\x9b\x1e\x4b\x76\xf3\xc2\xd6\x01\x77\x6f\x2c\x97\xdd\x9a\xe8\x5c\xcf\x59\xce\x9f\xde\x7b\x62\x7d\x16\x36\x03\x73\x75\x65\x69\xe7\xd2\xa2\xd9\xbf\x65\xd9\x6b\xb6\x6a\xa9\xe1\x42\xf5\xfd\x91\x3a\x77\x08\x68\xb6\x6a\x4d\xd4\x74\xde\x3f\x7b\x88\x69\xb6\x6a\x0d\xd4\xcc\xbc\x50\xe4\x2a\x75\xb1\x78\xea\xb5\x87\xe6\x6c\x3e\x51\xe7\xce\xab\x48\xf6\xe5\x1f\xff\x7c\xce\x15\xff\xf5\x3f\xe7\xb2\xc5\x7f\xfc\xf3\xd4\xe6\x6a\xe0\x5f\xd8\xa0\x78\xa6\x35\xf4\x87\xea\x6a\xee\xf9\x4c\xeb\x35\x99\x83\x66\xde\x40\xb5\xac\x6d\xf6\xb0\x3b\xb8\x25\x26\xe6\xb0\xad\x5e\xb8\xe5\xf9\xc2\x81\x37\x6c\x5d\xf0\x9e\xcb\x15\x5a\xa7\x89\xc9\xd9\x4a\x07\xbe\x6d\x73\xf4\xa2\xee\x6e\x2e\xf2\x74\x32\x71\xdb\x0b\xff\xf8\xe7\xe9\x52\xde\xcb\xdc\x66\xdb\x65\x5b\xb5\xdb\xea\x64\x6d\x74\x38\xdc\x86\xb9\x9b\xa0\xfa\x4c\xe9\x2a\xae\x8e\x09\xbf\xed\x0d\x87\x43\x73\x6a\xd9\x7a\x84\xd6\x5e\xbc\x57\x49\xca\xe9\x5d\xf7\xf7\x0e\x5c\xa7\xcf\x9e\xec\x07\xab\xf3\x87\x7c\x5f\x9c\x71\xbc\x7e\x18\xf7\x8d\xe3\x90\x87\xdb\xfc\xef\x15\xfa\xf0\xf6\xcb\xe3\x5e\xc2\x36\xa7\xbe\xf5\x98\xf1\xf5\x25\x88\x17\x8f\xf4\x9d\xc3\xf3\xf1\x33\x79\x67\xcf\x12\x5e\x59\x04\xd8\x25\xf5\xc3\x8b\xab\xd7\x9e\xad\x2e\xcd\x64\x76\x85\x01\xc7\x9f\x5b\x7d\x15\x18\x4d\x94\xed\xed\x16\xb8\x6f\x3f\x14\xff\xce\x93\xd0\xc7\xaf\x33\xbc\xb7\xaf\x8e\x5f\x00\xfa\x21\x07\xc9\x6f\x3c\x0c\x7b\xcf\xe9\xd6\xfb\x36\x79\xaf\xde\xc7\x78\x36\x47\xab\xef\x0d\xbc\x4b\xeb\x45\x1f\x7d\x6b\xe3\x63\x9c\xe3\xf2\x26\x6e\xc0\x73\x1e\x3d\xe4\xf1\xdd\x8f\x5b\x26\x7c\x7b\x17\xd9\x3d\xb4\xf2\xc6\x93\x22\x25\xad\x7c\xe5\xf0\xe8\xf1\x66\xef\xf1\xb1\xc6\xfb\x96\xdf\x3f\x4e\x89\x1b\x5f\x5c\xb9\xaa\xd4\xd5\x65\xfb\x5b\x94\xbc\x98\x37\x7d\x98\x9a\x37\x3f\x5a\x73\x55\xd1\x37\x26\xf9\xe7\x55\x8d\x99\x33\x73\x77\xc8\xe6\xca\x15\xac\x40\x2c\x5c\x0e\xbf\xa1\xdb\x1b\xf4\x5e\x5f\xa3\xf9\x08\xa2\xe7\x2e\x96\x7c\x0f\xdd\x0b\x17\x0b\x6e\x21\x79\x7c\x78\xe7\xf8\x62\xc1\xf1\x29\x2e\xf4\x78\x8c\x6b\x7f\x8e\x0a\x7c\x0d\x3c\x3c\x9c\x9c\xfb\x39\xd7\x14\x7d\x0d\x3c\xdc\xd9\x04\x1f\x9a\x80\xaf\x01\x7c\x63\x13\xf2\x35\xf0\x80\xc1\xfb\x24\xa4\xcf\x12\xde\xca\x8e\x7d\x0d\x3c\xc0\xf3\xdc\x2e\xf4\xce\xb5\x2b\x0d\xf7\xf6\xd0\xe9\xb5\x86\x47\xa9\x1e\x60\xcb\x1b\x7a\x33\xcf\xec\xb7\xf6\x4f\x14\xfc\x3e\x1d\xf7\x1f\x76\x5d\x07\xe5\x6f\x10\xfc\x86\x61\x00\x92\x6f\x50\x7e\x23\xf2\x77\x80\x05\xc6\x41\x00\x4f\xd5\xbd\x48\x1c\xb5\xf6\xa7\x10\x5f\x80\xd3\x5a\xef\x96\x83\xae\x32\x22\x88\xf1\x7b\x18\xe1\xd6\x7c\xaa\x9e\xa7\xfb\xde\xf0\xd5\x2b\xab\xd7\xd9\x51\x89\xd8\x3d\xfc\x48\xcb\x74\x9c\xd6\xe9\xc1\x81\xab\x3c\x28\x81\xe4\x2e\x9d\x68\x6b\x9f\xe0\x3e\x2e\xb1\xed\xae\x9a\x5e\x65\xc1\xa0\x00\xe4\x1e\x16\xec\x91\xc5\x21\x0e\xde\xc0\x82\x03\x79\x97\x0b\xf0\xfd\x04\x61\x7d\xbb\x16\x02\x82\xfb\x0c\x25\x76\x9d\x61\xb6\xdb\x13\xd5\x36\x67\xfe\xe4\x7a\x5f\x0b\x0a\x91\xb8\x8f\xfc\xb1\x91\x0e\xcf\xd6\xdd\xa0\x86\xa4\xfc\xae\xce\x90\x3b\x35\xf6\x87\x4a\x5a\x2b\x67\x72\x95\xba\x44\x98\xdd\xe5\xb1\x10\xec\xc8\x1f\x7a\x61\x97\x17\x5c\x67\x40\x19\x87\x77\x31\x80\xc7\x0c\x9e\xa6\xde\x5b\xfc\x5f\x67\x24\x91\x90\x77\x31\x42\x2f\x7a\xe2\xb0\x5f\xb7\xff\xd9\x83\x6b\x9c\x20\xa0\x92\xdd\xa7\x12\xde\xab\xf3\xb4\x3f\x7a\xd5\xb3\x20\x84\x9c\xde\xe5\xb8\x90\xb4\x5c\x6f\xf5\xf8\x6e\xa4\x3f\xe8\xb7\x5c\x4f\xf5\xaf\x8e\x8c\x10\x62\x8e\xef\xeb\x78\xfa\xb8\xfa\xf1\x78\xe8\x68\xf5\x86\x1a\x94\xf2\xbb\x00\x02\x59\xcb\x1b\xb6\xd5\x74\xd6\x7a\x7d\xac\xe9\x0d\x56\x4c\xde\x87\x45\xc8\x5f\x4c\xfa\x76\xe7\xc7\xcc\xeb\xb1\x04\x42\x41\x19\xba\x8b\x89\x78\x72\x5f\xd7\x9f\x3c\xce\xb9\xae\xf2\x40\x58\x60\x7a\x17\x0f\xb9\x77\xaa\xeb\x64\x31\x86\xe0\x2e\x8f\x42\xe0\x8c\xe8\x6f\x83\x10\x62\x4a\xe4\x5d\x20\x44\xf0\x11\xe9\x13\x35\xf0\x17\xaa\xb5\x51\x13\xff\x69\xef\xdc\x1f\x4e\x67\x13\xd3\x7b\x23\xec\x42\x2c\x00\xbe\x0b\x90\x08\xb5\x8e\x56\x05\xae\xd2\x26\x84\x83\xbb\x5c\x0b\xe1\xd6\xc9\x1d\xd9\xab\xf4\x29\x42\x77\x39\x15\x22\x37\x4d\x45\x20\x03\x82\xdc\x15\x36\x10\xdd\xca\x7d\x00\xe0\x44\x0d\xcd\x81\x6a\xd9\x7e\x7f\x3e\x78\x03\x7b\x0c\x73\x78\xdf\x1c\x0b\x3f\xf6\xf5\x7c\x38\x9f\xaa\x13\xd0\xc1\xdf\x30\x08\x40\x70\x4c\xfd\x2e\xf3\x63\xb2\x43\xb3\x35\x1f\x8c\xae\x8c\x1f\x7b\x2e\xf0\xfd\x5c\x68\xcb\x99\xf8\xa3\xe3\x09\x69\xeb\x74\xf8\xd8\xf3\x38\xb6\xd3\x7d\x63\x14\xe6\xfb\x40\x78\xf6\xf0\x66\x6b\xe6\x3f\x9e\x68\x3e\xc7\x15\xbd\x9b\x2b\xd9\x87\xdf\xc3\x8d\xfa\x2d\x9b\xdd\x6f\x0d\x1d\x1e\x28\x39\xc7\x0b\xbf\xdb\x8a\x84\xee\x78\x9d\xb9\x35\x73\x98\x75\xbf\x65\xd0\x3b\xd9\xb1\x1d\xbb\xc1\x7c\xa5\x9c\x0b\x20\x42\xdf\xcb\x82\xb7\x46\x13\x65\xfb\x83\xd1\xfc\x71\xc2\xfd\x34\xa1\x7c\xed\x85\x67\xb8\xdd\x35\x78\x12\xd1\x9a\x28\x6b\xee\xf5\x9d\xab\xac\x10\xdc\xb2\x02\x28\x00\xe0\x37\x8c\xbf\x61\xfc\x3b\x41\x82\x6c\x59\x81\xdb\x59\xed\x67\x95\xd6\xc4\x1b\x1e\x72\xb1\x3b\x39\x62\xb4\x9d\xc5\xde\xce\x90\x82\xd3\x97\x1d\xaf\x92\xe7\x50\x6c\xf3\x89\x3b\xe8\xc3\xc7\x51\xa8\x33\x3b\x0c\x44\x7b\xc5\xd4\x1b\x8c\x24\x78\xe4\x73\x21\xdd\xbe\x7a\x97\xfd\xde\x7c\xfb\xd5\x7d\xf6\xe3\x65\x91\x44\xb4\xd8\x2c\xe0\x54\x85\xd7\x2b\x4c\x4b\x33\x9c\x6e\xd6\x33\xd1\x62\xbe\x51\x46\x86\x5e\xd7\x71\x32\x42\xa3\x7a\x52\xd3\xf5\x8a\x56\x49\x96\x72\x61\x52\xad\xa4\xd3\xe9\x92\xa6\x9f\x1a\xe9\x22\x13\xb4\x65\x12\x31\x0a\x8d\x64\x2a\x8b\xa2\x29\x1c\xd7\x8b\x24\x52\xcf\xc6\x73\x7a\x2c\x1b\x4f\x57\xf4\x42\x05\x25\x1b\xb8\x99\x8b\x97\x92\x79\xbd\x12\xd5\xf2\xe1\x52\x8d\x17\xa3\x3c\x5f\x47\xc9\x9b\x99\xe0\x2d\x93\xb0\x1e\x6f\xc6\x8c\x48\x54\x2f\x57\xea\xa9\x7c\x2c\x9a\xd6\x1a\xb9\x70\xb4\x90\x8b\x96\x9a\x5a\x55\x23\xb5\x66\xa2\x89\xa3\xcd\x58\x13\x17\x50\xa9\x9e\x21\x99\x24\xa7\xa9\x0c\x6b\xdc\xcc\x84\xec\x98\x44\xd3\x05\x8d\x34\x2a\x06\x42\xd5\x02\x89\xe6\x50\x24\x16\x8f\x85\x93\x0d\x1c\xcb\x6a\x71\x9c\xe4\xba\xa6\x67\x2a\x45\x8a\x63\x65\x5a\xd6\x52\x28\x11\x4e\x96\xa9\x4e\xea\x37\x33\xa1\x3b\x26\x8d\x52\x34\x97\x29\x36\x98\xd6\xc8\xd6\xf3\x85\x72\x99\xa5\x0b\x85\x7c\x3d\x96\xab\xea\x91\x5a\xaa\x5c\x28\x97\x9a\xa9\x6a\xad\x46\xb2\xb5\xb0\x51\x8d\xe4\xcb\x49\x6a\x94\xb3\xe1\xd8\xcd\x4c\xd8\x96\x49\xcc\xa0\xb8\x16\xd6\x52\x99\x7c\x05\x37\x33\x3a\x26\xd1\x52\x32\x5c\x4b\xf2\x64\x95\x65\x18\x8e\x46\xd2\x46\xa5\x5c\xab\xc4\x22\xf1\x52\xae\xc1\x0d\xa3\x98\xc1\xa5\x42\x26\x5f\xba\x99\x09\xdf\x79\x57\xb2\x50\x4f\x54\x63\x99\x42\x9c\x66\xca\x24\xaa\x87\xcb\xbc\xce\x79\xbe\xde\x68\xf2\x46\x55\x23\xe9\x64\x26\x1e\xab\x24\xa3\x89\x68\xb5\x16\xcd\x92\x0c\x29\x14\x19\xcf\x64\x9a\x37\x33\x11\x3b\x4d\x48\x29\x97\xd7\x70\xb5\x50\x8a\xf3\xa6\x81\xa3\x65\xad\x88\x0b\xb4\xa2\x97\x23\x39\x2d\x1d\x0b\xa3\x44\xb6\x5e\x4e\x1a\x3c\x97\x0b\x1b\x61\x3d\x93\x49\xc7\x9a\xdc\x28\x24\xe2\x37\x33\x91\x3b\x4d\xaa\x35\x9a\x8d\x1a\xcd\x78\x81\x17\x34\xbd\x5e\x0e\x27\xf2\xd5\x54\xb1\x1e\x8e\xc5\xf4\x4a\xbd\xde\x4c\x47\xf5\x4c\x9c\x54\x8b\x11\x94\xca\xf0\x1a\xca\x16\xd2\xb5\x38\xc7\x95\xc4\xcd\x4c\x20\xd8\x71\x49\x67\xd2\xf5\x42\x26\x12\x4f\x25\xf3\x79\x4c\x28\xad\xd5\x6b\x09\x1a\x8d\x45\x9a\xf5\xa2\xde\x88\x1b\x46\x22\x15\x6d\xe4\x0a\x95\x22\xa6\xd1\x42\x91\xd4\xaa\x25\x9c\x69\x66\xef\xe0\xb2\xc7\x7c\x2a\x1e\x37\x8a\x99\x64\x2e\xc9\xd2\x31\x1e\xcd\xd0\x7c\x8a\xd4\xab\xd1\x46\x34\xa7\x1b\x7a\x9c\x15\x1a\x61\x9e\x2e\x47\x0d\x1c\x2f\x24\x0b\xe9\x66\xb1\xdc\x68\xc4\x23\x54\xbb\xbd\xeb\xe1\x1e\xf4\x2c\xa1\xe3\x6c\xba\x52\x63\xe9\x86\xc1\xb5\x58\x3e\x4d\x78\x35\x92\xe4\x31\x42\x73\x24\x5d\x4b\xd6\x13\x19\x96\x4d\xa6\x8d\xb0\x96\xa2\xe9\x48\x49\x47\xb1\x48\xb1\xc1\x8b\xb7\x73\xd9\xa1\x3e\x92\xcf\xf0\x48\xbe\x52\xca\xd7\x0a\xc9\x48\x58\x8f\x34\x72\x2c\x97\x32\x1a\xcd\x74\x2a\x96\x2a\x54\x1a\xe9\x42\x3d\x59\x4e\x86\x63\x71\x4e\x2b\x5a\x35\x55\x6d\xd4\x92\xc9\xbc\x5e\x8c\xde\xce\x65\x07\xfb\x08\x2a\xa6\x1a\x65\x94\x0a\x57\xe2\x39\xa3\x9e\xc9\x96\xb2\xd9\x82\xa1\x45\xa3\x2c\x1f\xcd\x27\xd2\xb9\x70\xac\x54\x28\x1b\x19\x5e\x4e\xe8\x65\x54\x8a\x1b\xa8\x91\xa8\xc5\xc2\xc6\xed\x88\x84\x7b\xdc\xd7\x73\x71\x82\xcb\x89\x66\xb2\x86\x8b\x3a\x36\xb4\x7c\x25\x8c\x2a\xb4\x50\xa3\x91\x72\xd8\xa8\x27\x12\x8d\x34\x4e\xa7\xe2\xc9\x1a\x6e\x94\x59\xd1\xc8\x18\x59\x1c\x2d\x14\x2a\xb7\x73\x39\x00\xbf\x86\x39\xcd\x85\x1b\x06\x61\xf9\x58\x22\x8e\x6a\x89\xb0\x5e\x8c\x22\xc3\x68\x66\x79\x1e\x11\x16\x6b\x24\x93\xd1\x44\xad\x5c\x45\x86\xc6\x53\x49\x0d\x15\x2b\xc5\xec\x1d\xba\xf0\xfd\x40\x19\x36\x50\x58\x6b\x68\x99\x54\x59\x43\xd9\x4c\x8a\x1a\xb9\x7a\x9c\xe6\x52\xd5\x26\x2b\xf2\x7a\x2a\x6b\xe4\x13\xb1\x32\x42\x79\x9e\xae\x93\x58\xa9\x16\x2f\xf1\x78\x2c\x56\xb8\x9d\x8b\xd8\x8f\xf9\xcd\x44\x21\xd3\xa0\xb5\x52\xb2\x96\xa0\x8d\x7c\x33\xa7\x27\x28\x4a\x44\x33\xb4\x14\x4d\x93\x46\xa2\x52\xcb\xa5\xd3\xd5\x44\xb3\x94\x41\xf1\x02\x89\xa4\x50\x3a\x95\xd6\xd1\x1d\xbd\xbf\xc7\x7e\x32\x4a\x62\x28\x5a\x22\x34\x9a\x36\x74\x9d\x14\xc3\xc9\x32\xca\xc6\x9b\xe1\x74\xaa\x42\x0b\x61\x9e\xa4\x38\x83\xab\xf9\x02\xab\x69\x69\x56\xaf\x25\xf5\x92\xde\xcc\x14\x6f\x47\x25\xda\x63\x3f\xc2\xe3\x85\x46\x22\x9b\x65\x46\x1a\xf3\x64\xc6\x08\x37\x6a\xb4\x1c\xae\xe5\xe2\x91\x44\x22\x9e\xc8\x91\x54\x8e\x69\x46\x24\xda\xac\xa7\x50\xa4\x49\xf2\xf9\x7c\x1d\x55\xc2\xb7\xc7\x2f\xb4\xc3\x7e\x2c\x5a\x2d\x47\x12\x25\x4d\xab\xf0\x4c\xb6\x5e\xc9\x25\x73\xa5\x7a\x24\x9c\xad\xa7\x51\x99\xa4\x50\x26\x5f\xa8\xd7\x50\x89\x96\x8d\x6c\x26\x66\xa4\xc2\xf5\x18\xad\xc4\x92\xe1\x46\xfe\x76\x2e\x3b\xec\x87\x13\x14\x95\x6b\xac\x18\x8e\xb0\x72\x42\xcf\xe5\xcb\x59\x8c\x1a\x24\x87\x2b\xc5\x62\x56\xd7\xf5\x64\x41\x4b\x36\xc2\xa9\x86\x51\x60\xa5\x78\x9c\x35\xc3\x55\x23\x4e\x9b\xc5\x3b\x74\xd9\x47\x7c\xc2\xaa\x46\x26\x12\xcd\xa6\x50\x9d\xc5\xea\xd9\x3a\x0f\xa7\xb4\xaa\x11\xcf\x26\x71\x25\xcc\xeb\x11\x0d\xeb\x09\xbd\xc0\xf2\x9c\x24\x8b\x34\x5b\x4f\xe6\x12\xe5\x2a\x4a\x47\x6e\xe7\xb2\xc3\x7e\xac\x1e\x0f\x27\xd2\xd1\x52\x34\x45\xa2\x19\xd4\x48\x66\x58\xc3\xc8\x86\x59\x39\xa3\xd5\xe3\x46\x9d\x47\x72\x89\x6a\xae\x98\x8f\xe4\xb2\x29\xad\x92\x36\xd2\xb4\x51\xd4\xb3\xb9\xd4\x1d\x5c\x0e\xd8\x4f\x61\x5c\x89\x66\x8b\xe5\x68\x26\x87\xf4\x9c\x11\x29\xf1\x7a\x23\x62\x50\x4c\xb3\x59\xad\x1a\x4e\x66\x69\x23\xa2\x93\x78\x39\x1a\x21\xc9\x66\xb2\xcc\x9b\x61\x1a\xad\x66\x1e\xde\xfb\xa8\x53\xa0\xa4\xbd\xb5\x65\xfa\xf6\x63\x05\xa7\x0f\x1e\x7d\x0d\x6c\x95\x39\xbc\x51\xf0\xd6\xdc\xf6\xf5\x8d\xf8\x77\xcf\x6c\xf7\xdb\xed\xc7\xf3\x5a\x7b\xa2\x1c\x6f\xd6\x32\xfb\xa3\x8e\x39\x9c\x0f\xc8\x76\x32\x5e\x29\xc5\x1e\x3e\x63\x30\x7f\xc9\x1d\xbd\xc1\xfd\xa3\x07\xf9\x97\xdc\xf1\x05\xee\x5a\xc5\x78\xf8\x8c\xb9\xd2\x4b\xee\xe4\x0d\xee\x9f\xab\x3b\x7d\xc3\xf2\x9f\xab\x3b\x7b\x83\xfb\x47\x07\x91\x97\xdc\xb7\x31\x77\x68\xce\xbc\x85\xda\x32\x7b\x38\xd9\xcd\xbd\xe7\xc9\x82\x0f\x19\x17\x5e\x9c\x65\xf9\x1a\xe0\xb7\x0e\x0a\xe7\x5e\x2c\x78\xef\xa8\xf0\xf8\x6a\xc1\xd1\xb0\x80\x88\x84\x40\x40\xc0\x11\xa3\xbb\x6d\x6f\xb2\xc5\xcb\xbf\x7e\x1e\xaa\xe5\x56\xd2\x9f\xbf\x05\x9e\x77\xe1\x01\xf8\x9f\x4b\xb6\x3f\x4b\x99\x08\x88\x21\x96\x92\xc9\xa7\x0d\xf5\x7f\xfd\x3c\x9d\x99\x93\x99\x37\x6c\x3f\x2e\x4b\xfd\xfc\x2d\xf0\x33\x04\x00\xfc\x7e\x60\xf1\xf3\xcd\x3c\xd0\x29\x0f\xb4\xdf\xef\xff\xd7\xcf\xfb\x95\xee\x57\x94\xbf\x06\x7e\x7e\x3e\x45\xb6\x2d\xdd\xbb\xc7\xed\x1c\x5f\x69\x85\xbf\x06\xe0\x5e\xad\xfd\xa3\x9d\x3f\x7f\xdb\x2a\xfa\xf3\xbe\x43\x5a\x3d\xb5\xde\x72\x79\xef\x82\xc2\xed\x72\xe1\xad\x5c\x80\x42\x01\x39\x62\x1c\xef\xac\x8d\x5e\x59\xe2\xe3\xec\xf0\x8a\xdf\x59\xcb\x7f\x2c\x3f\xcc\x10\xc2\x08\x50\xcc\xf9\xa7\x79\xd3\x0b\x1e\x9f\xee\x4d\xaf\xb4\xba\xcd\x9b\xde\xb9\xa8\x73\xbb\x5c\x64\x2b\x17\x94\x48\x20\x2c\x80\x80\x9f\xee\x4d\xe8\x94\xdf\x27\x7b\xd3\x4b\x7e\xe8\xd3\xf5\x23\xa7\xfc\x3e\x59\xbf\x2d\x3f\xc4\x19\xc6\x88\x03\x2e\xe8\xa7\xa1\xe5\x05\x8f\x4f\x47\xcb\x2b\xad\x6e\x44\xcb\xfb\x56\x27\x6f\x97\x6b\xab\x3b\xc2\x18\x0b\x0c\x30\x11\xfb\x48\x47\xf6\xee\x34\x34\x07\x07\x55\x07\x0a\x6e\x2d\xb0\x3b\x56\xbf\xfd\x26\x17\x0b\x2f\x73\xe1\x3f\xff\xbc\x8f\x0d\x94\x80\x60\x8c\x19\x94\xf8\x46\x36\xe5\xd4\x46\xbf\x9f\x0d\xe1\x44\x60\x26\x84\xdc\x8f\xb4\x04\xbe\x62\x83\xee\xa4\x08\x08\xc5\x04\x40\x06\xf6\xa3\x09\x01\x9f\x23\xf8\x9e\x0d\x65\x8f\x82\xbf\x66\x83\x5e\xb0\xd1\xcb\x0d\x9c\x7f\x2f\x1b\xc9\x1f\xbb\xe1\x35\x9b\xc0\x0b\x36\x66\xdd\xd8\xa4\x12\xce\xc2\x89\x46\x36\x76\x22\xde\x6d\xd6\x73\x9d\xfb\x58\x02\x06\xa9\x20\x98\x60\xf0\x79\x70\x7e\xc1\xe3\xd3\xe1\xfc\x4a\xab\x1b\xe1\xfc\xbe\x7d\x80\x3b\x2d\x01\x05\xc3\x84\x71\x00\xe4\xf9\xe0\x40\x11\xe5\x8c\xb3\xdf\x25\xc5\x0c\x48\xf4\xfd\xd6\x60\xa7\x5c\xd1\x6b\xae\x58\x40\x42\xd0\xae\x0b\x20\x81\xf2\x43\x98\x42\xc9\x29\x13\x44\x4a\x0e\xf7\xbe\xcc\x77\x4c\xcf\xfe\x84\xc3\xce\xfe\xef\xdc\x22\xb9\xcb\xfe\x7b\xa1\x28\xc0\xe2\x60\xff\xb7\x84\x7a\xe7\x5e\xda\x9d\x96\xc2\x88\x63\x8a\x11\x81\x6f\xcd\x3f\xd1\x73\xbe\xf4\x2e\x24\xbe\x64\x75\x06\x89\xe7\x18\x7c\x8c\x37\x1c\x33\xbe\x0d\x90\x9f\xee\x10\x5b\x6b\x6f\x43\x91\xa0\x8c\x42\x04\x9f\x4e\x75\x1f\x1b\x44\x4a\xf9\xbb\xdc\xfe\x7d\xd0\xf4\xf0\x25\xc3\x33\x58\xfc\x50\x86\xaf\x34\xdc\x43\xf1\xe1\x5f\xf7\x51\x20\x4c\x60\x2a\xb9\x40\x9f\x16\x22\x5e\xf2\xf8\xf4\x10\xf1\x4a\xab\x1b\xb3\xed\xf7\x6d\xb0\xde\x2e\x97\xd8\xca\x05\xb0\x10\x0c\x03\x8a\x0e\x21\x82\xec\xe4\xda\x9d\x7f\xf3\x27\x7b\x39\xde\xb7\x3d\xfa\x6c\x37\xdb\x77\x76\x76\xd3\x2a\xc6\x6b\x63\x9e\xae\xab\x3d\xd7\xd8\xdf\x80\xdb\x83\xf3\x7d\xcb\x7b\xf7\x99\x82\x33\x20\x31\x63\x18\xe1\xc3\xc2\x03\xfe\x3c\x53\x54\x4a\xb1\xff\x02\x53\x70\xfc\xe8\x15\x9f\x68\x8a\xff\x60\xaf\xd8\x2a\xcf\x21\x97\x82\x49\x2a\xf1\x3e\x5c\xa2\x3d\x70\x77\x97\x23\x77\x23\xe8\x36\x69\xe2\x08\x60\x26\xe8\xef\x84\x73\x2a\x00\xff\xaf\xea\xef\x27\x25\x39\x00\xe0\xd1\xf5\xdf\xa5\xe4\x7f\x70\x4f\x6e\x9d\x9a\x71\x0a\x30\x47\x82\x91\x7d\xf0\x65\xfb\x41\x7f\x3e\xeb\xb4\x26\x6a\x3c\xf7\x26\xca\x69\xb9\x7d\xb3\xfd\xf3\xee\x62\xb1\xda\xca\xb9\x2f\x5b\xf8\xf6\xee\xfc\xe1\x51\xe1\x5d\xd6\x65\x18\x01\xc1\x19\xc4\xe4\xf3\x22\xda\x0b\x1e\x9f\x1e\xd1\x5e\x69\x75\x63\x44\x7b\xe7\x98\x71\x5f\x37\xef\xe5\xa2\xe4\xd0\xcd\x9f\x68\xed\x3d\x8f\x4f\xb7\xf6\x2b\xad\x6e\x9c\xd1\x7e\x36\xa8\xb6\x32\x40\x2a\x24\xc4\x5c\x12\x40\x0e\xa1\x02\xbe\x1c\x3a\xce\xd8\xe1\xfb\x07\xc5\x4f\x4f\x94\xf6\xaa\x11\x06\x85\x40\x8c\xd3\xc3\xa8\x88\x5e\xaa\x06\xcf\x75\xf2\x7f\x8d\x72\x00\x23\x2c\xa8\x24\x94\xff\xf5\x94\x23\x0c\x20\x21\x24\x82\x0c\xfe\x5b\x82\xf6\x0f\xd2\x12\x72\x8c\x25\x22\x82\x7d\x5e\x5c\x79\xc1\xe3\xf3\xf7\x25\x5f\xa9\x75\x63\x60\x79\xdf\xd9\xca\x3b\x04\xdb\xfa\x11\xe6\x04\x0b\x49\x39\x3d\xec\x03\x5f\x99\x40\xec\x7e\x86\xf5\xe2\x0c\x62\x57\xfa\x1e\xde\x0c\xb2\x43\x5f\x43\xf4\xd2\x28\xe8\x8c\x51\xde\x77\x14\xf4\x5d\x46\x39\x08\xb6\xf5\x98\xfd\xf8\x7f\x22\x4b\x84\xa5\x71\x2d\x9f\xcd\x34\x8a\x1a\xcb\x54\x63\x4d\x2d\x4c\xd2\xb1\x5c\xbc\x5c\xce\xeb\x95\x46\x01\x17\x2a\x49\x3d\xa6\x37\x8d\x5a\x2a\x13\x66\xe9\x62\x2d\x95\x4b\x37\xc3\xe5\xb8\x76\xaf\x2c\x18\x12\x2c\x25\x40\x87\xad\xe3\xff\x1c\x23\x1d\x0b\x86\x5e\x0b\x46\x5f\x0b\xf6\x63\x2c\x86\x00\xa2\x12\x08\x81\x0f\xdb\x6b\xff\xf6\x15\xca\x23\xa9\xb6\x43\xc0\x4d\x33\xf5\x77\x11\x67\xf4\xb0\xff\xfe\x82\xf8\xf7\x4c\xf5\x9f\xa9\x43\x00\xd8\x7f\x9a\x0b\x1e\x04\x23\xfc\x30\x78\xed\xd7\x79\xfa\xfe\xb2\xf5\xf4\x7b\xbf\x3f\x7f\xdb\x86\x90\x9f\x07\xca\x79\xf1\xdd\x56\xe4\xdd\x0b\xb9\x2f\xbe\x7c\x17\x77\xf1\x18\xaa\xe8\x8e\xfb\xd1\x6f\x21\x6f\x2d\xa1\x56\xe6\x60\xd4\x57\xbf\xdb\xfe\xe0\x5d\xca\x41\x24\x0f\xf1\xfe\x3f\xcc\xea\x07\xc1\xd0\x4d\xb1\xec\xc7\x00\x1f\x52\xc9\x08\x44\x10\x88\x4f\x3b\xd3\xf4\x92\xc7\xe7\xcf\x1d\x5e\xa9\x75\xe3\xdc\xe1\xd3\x1d\x61\xd7\xef\x1c\x73\x02\x05\x23\xf2\xd3\x4e\xfd\xbc\xe4\xf1\xf9\xf6\x7e\xc5\xf2\x36\x7b\xbf\xf3\xee\xc8\x1d\x82\x91\xad\x1c\x18\x70\x89\xa0\x44\x87\x9d\x7a\xbc\x37\xc6\xfe\x31\xbe\xbd\x1c\xef\xbb\x5d\xb2\x35\xdc\xe3\x43\x0d\x3f\x7f\xdb\xea\xfc\xf3\xd4\xef\x3b\xad\xe3\x5d\xad\x63\x23\x5b\xfe\xbc\xdd\x99\x5d\x2c\xde\xb7\x3d\x97\x76\x1c\x95\x5c\xcb\x3d\x1e\xe9\x9f\xeb\xcb\x97\x54\x8e\xf3\x93\xf7\x1d\x93\xbe\xa3\x0f\xf0\x69\x1f\xa0\xb3\x7d\xf0\x4e\x39\x3e\xad\x0f\x5e\x1b\xf0\x85\x7d\x4f\xba\xe8\xac\xed\xdf\xec\xa4\x1f\xdd\x0f\x92\x10\x21\x91\x20\xec\xf1\x14\xc0\x8f\x4e\x86\x7f\x88\x92\x00\x4a\x82\x21\xc7\x87\xfd\xff\x4f\x18\x5f\x5f\xb0\xf8\xfc\xe1\xf5\x54\xa9\x1b\x47\xd7\x77\x8e\x6a\x77\x8d\xae\x7b\xb9\x10\x24\xe0\xd3\x26\x0f\x2f\x58\x7c\xbe\xb1\x4f\x95\xba\xd1\xd8\x9f\xee\xd9\xfc\x6b\x60\xff\x1b\x94\x14\x80\xc3\x79\x8d\xd7\x27\x3c\xaf\x2c\xd4\xbd\x7f\x4b\xe6\x9d\xf7\x39\xee\xd0\x8d\x9d\xe8\x76\xbe\x97\x3f\xb0\x93\x4f\x19\xe2\x73\x21\xe9\xbd\x7a\xbf\x0c\x49\xe8\x75\x48\x3a\xd1\xe5\x55\x4c\x3a\x29\xbf\x3f\x28\x1d\xfa\xfa\xbb\x83\xd2\xe7\xf7\x3c\x3d\xe9\x08\x72\xae\x23\xde\x79\x97\xf5\x33\x3b\xe2\xc4\xd2\x9f\x39\x43\xfb\xfc\x4e\xd8\x0e\x2d\x90\x01\x82\x05\xe2\xe8\xfc\xe1\x78\xf4\xdf\x3c\xb4\x1c\xeb\x76\xeb\xd0\xf2\xfd\x93\x9d\x1f\xaf\xdb\x27\x8e\x62\xf0\x7e\xf0\xa0\x37\xc1\xf3\x03\xd2\x9b\x1f\x33\x82\x1d\x77\xc2\x27\x8e\x60\x67\x3a\x01\x7d\x76\x28\xf9\xa8\xfc\xe6\xc7\xa3\x81\xfe\xd0\x98\xfe\x56\x47\x5c\x46\xc3\x5f\x32\xa6\x1f\x77\x04\xfb\xa1\x31\xfd\xfd\x1d\xf1\x97\x8a\xe9\xec\x6b\x80\x73\x0c\x24\x81\x94\x1c\x8e\xcf\xde\x95\x2e\xfc\x27\xc7\x3d\x7a\xa2\xdb\x5f\x2c\xa6\x73\x0c\x20\x21\x44\x40\xf4\xef\x59\xa5\xf9\x21\x13\xce\xbd\x92\x14\xa1\x47\xe7\xfc\xc1\xe7\x0c\x7f\x48\x4f\x32\xc1\xa1\x24\x02\x08\xfc\x69\x4b\x51\x2f\x58\x7c\xfe\xea\xc8\xa9\x52\xb7\xde\xa8\x78\xdf\x60\x7f\x97\x47\x1d\xe4\x22\x12\x7d\xda\x52\xd4\x0b\x16\x9f\x6f\xec\x53\xa5\x6e\xbd\x1e\xfa\xae\x37\x99\xee\x1b\x7f\x0f\x72\x49\xf0\x79\x57\x33\x5e\xb0\xf8\x7c\x63\x9f\x2a\x75\xa3\xb1\x3f\x7d\x18\x11\x5f\x03\x8c\x10\x44\x28\xc4\x14\x5f\x5a\xf7\xfb\x8c\x58\xf7\xce\xa7\x4c\xee\x50\x4d\x9e\xa8\x76\xe3\x25\xf2\xff\x06\xd5\xb6\xbd\x06\x20\x92\x94\x30\x44\x3e\xff\xbd\x81\x9d\x29\x8f\xf9\x7d\xf2\x7d\xfc\x67\xfd\x28\xc0\xff\xa6\xeb\x10\x3f\xc4\x3f\x29\x15\x98\x50\x2e\xe4\xe7\x1d\xd8\x7f\xc1\xe2\xf3\xc7\xb9\x53\xa5\x6e\xbd\x81\xf6\x03\x10\xb3\x97\x4b\x60\xf0\x79\xe7\xf5\x5f\xb0\xf8\x7c\x63\x9f\x2a\x75\xeb\x73\x28\xef\x7a\xef\xf0\x0e\x43\x80\xaf\x01\x0a\x29\x96\x0c\x42\x46\xde\x9a\x2e\xd1\xf7\x98\x1a\x9e\x70\x38\x63\x6b\xfa\x91\x0f\xa0\x9c\x6a\x74\xa3\x5b\xbf\xef\x35\xc6\xfb\xec\x40\x38\x22\x84\x11\x82\xe9\xa7\x65\x01\x2f\x58\x7c\xba\x5b\xbf\x52\xea\xc6\x2c\xe0\x7d\x8f\x52\xde\x67\x08\x24\x89\x64\x9c\x03\x7a\xfb\x54\xe9\xdd\x66\x38\xe5\xf7\xf9\x8f\xfc\x3c\xb3\x13\x3f\x58\x3d\xf1\xf9\xea\x6d\xe9\x0b\x46\x09\x07\x92\xb3\x4f\x8b\x00\x2f\x58\x7c\x3e\x54\x4e\x39\xde\x18\x01\xde\xf7\xb2\xea\x7d\x86\x20\x98\x4a\x4e\x10\x61\x17\x96\x07\x3f\xd0\x0a\xf8\x84\xdd\x39\xbb\x7f\x28\x50\x0e\xdc\x18\x65\x17\x26\xdf\x9f\xa2\xdc\x9e\xdd\x0f\x52\x8e\x02\x76\x69\x90\xfb\x0c\xe5\x0e\xec\x7e\x94\x72\xe4\xe9\xaa\xdd\x0f\x51\x6e\xcf\xee\x93\x95\xdb\xb2\x03\x80\x6d\x73\x21\xf8\x79\x0f\x48\xbe\x60\xf1\xf9\x03\xdc\xa9\x52\x37\x0e\x70\xef\x7b\xd4\xf9\x0e\xb9\xc8\xd7\x00\xa2\x9c\x49\x01\xb8\xb8\xfd\x06\xc6\x3b\x9f\x81\xfe\x0e\xb9\xce\xdc\x01\x3a\x37\x77\xc2\x1a\x4f\x66\x72\x86\x5e\x66\xc9\x44\x24\x91\x8c\x94\x59\x8a\xa5\x35\xa2\xa3\x12\xa9\xd1\x4c\x13\x11\x56\x4e\xa4\x49\xa6\x58\xaa\xa7\x51\x81\x44\xea\xd1\x4a\xa1\x98\xbb\x63\x51\x6f\x27\xd7\xee\x99\x34\x42\x2e\xdd\x58\x39\x27\xd7\x0f\xb1\xd7\xb1\x5c\xb7\x5d\x9d\xf8\x91\xf6\x12\xd7\x2f\xd2\xa0\x8f\xbf\x48\xb3\x65\x7e\x78\xa9\x01\x23\xf1\x79\x97\xdb\x8f\x59\x7c\xfe\x48\x72\xaa\xd4\x8d\x59\xc5\xa7\x7b\xe0\x76\x7a\x84\x84\x20\x12\x50\xf9\x79\x6f\x4f\xbe\x60\xf1\xf9\xc6\x3e\x55\xea\xd6\xe5\xee\x77\xbd\x5f\xbf\x97\xeb\x8d\x57\xa1\x0f\xbf\x52\xf6\x21\xaf\x42\x1f\x68\x3d\xbf\x04\x06\xbf\x06\x1e\x38\xb1\x99\xe3\x3a\x58\xd8\xcc\xb2\x89\x05\x81\xa3\x1c\xc7\x52\xc8\x75\x1c\x6a\x42\x82\x4d\x01\x39\xa3\x10\x61\xc5\x94\xc5\x30\x22\x8e\xab\x5c\xe0\xd8\x0e\x31\x29\x75\x2d\xf8\xf0\x35\xf0\xe0\xda\x82\x60\x07\x41\x82\x6d\xce\x2c\x07\x49\x65\x61\x0b\xba\xae\xe3\xd8\xd8\x21\xc2\x61\xc0\xe6\x26\x74\x6c\xd7\x84\xd8\x74\x84\x80\x12\x3a\x26\xc0\x1c\x48\xe4\x42\xe4\x1c\x7e\x87\x19\x3e\xfe\xb2\x17\x60\xbf\x01\x1c\x80\xec\x1b\x66\xdf\x10\x7f\x78\xfd\x35\xfd\x86\xf1\xef\xbb\xb7\x99\xd1\x9b\xa5\x88\x41\x29\x31\x00\x14\x50\xf6\x35\x00\xb7\xff\x07\x00\x40\x09\x38\x7a\xfa\x1d\x68\xb0\x8d\xd6\x84\x43\xb4\xbb\xec\xb5\xfd\x27\x7c\x2e\x81\x4f\x1f\xb6\x02\x86\xc3\xe1\x70\x34\xb4\xd6\x0a\xa5\x78\x6c\x85\x16\xa5\xe1\x24\xbf\x0a\x49\x1c\x83\x29\xd8\x5e\xb1\xa4\x1d\xec\xe4\x67\x5e\xa4\xe7\xf8\x31\x3b\x9d\x5d\x65\x8b\xcb\xa1\xe5\xc7\x9a\xeb\x7c\xdb\x5e\xbb\x16\xe9\x29\xba\x4c\xe1\x92\x3f\xad\x36\x59\xa3\x38\x5f\xa5\x86\x3a\xaa\x30\x27\xe2\x10\xd9\x69\x6c\x49\x87\xeb\x85\x6a\xce\x5b\x86\x9f\xfe\xfc\xa9\xd6\x59\x18\xe5\xe8\xc2\x74\x52\xa1\xb4\x9c\x04\x45\x2f\x12\xec\x37\xc2\x2c\x3f\xea\x94\xbb\xc9\x64\x88\xfa\x28\xe8\xf5\xfa\x29\x52\x20\x93\x45\x21\x19\x5e\x61\x73\xea\x41\x9f\xf0\x5c\x01\xa2\x89\x1e\x2d\x96\x52\x95\x6a\xac\x0b\xab\x13\x67\x2e\x60\x70\x96\xcf\xc6\xdc\x2d\xfd\x18\xd0\x49\xad\x38\xaa\xe9\xdd\xcc\x81\x55\x04\x14\x0c\xba\xfb\x54\x7c\x62\x9f\xd8\xfe\xa7\x19\xae\x43\x52\xdc\x36\x49\x87\x33\x0c\x8d\xdd\x6e\xa2\x1e\x5b\x77\x83\x70\x54\x2f\x67\xc3\x6a\xca\x42\xa1\x82\xe3\x25\x73\xa9\x3e\x6d\x27\xf3\xbd\x72\x57\xd5\xf3\xa1\x25\x08\xff\x27\xfc\x3d\xfd\xc4\xb7\x5e\xc9\x66\x2f\x0c\x03\xaf\x70\x01\x3e\xc6\xa7\x1f\x04\x55\x1c\x31\x46\x6c\x07\x0a\x4c\x11\x62\x48\x30\xe6\x02\x8a\x29\x25\x00\x62\x86\x2c\x53\xd8\xca\x64\x26\x72\x09\x57\x88\x43\x46\x38\x34\x2d\x01\x1c\x6e\x0a\x04\xc4\x35\x5c\xb0\x8b\x9e\x8f\x29\x41\xf0\xcd\xd2\xc3\x74\x0b\x73\xbe\x55\xf7\x3a\x2e\xe0\x8d\xb8\x20\xf5\x61\x7a\x50\xd6\x13\xb1\x8a\xd7\xf0\x9b\x8b\x48\xb9\x5a\x09\x97\x1b\x93\x71\x8e\x0d\xfc\x85\x11\x4c\xaf\x9a\xc9\xc4\xa4\xad\x2b\x3f\x95\xa2\xc2\xad\x2e\xfa\x93\x72\xc7\xce\x4e\x8d\x4e\x33\x94\xab\x75\x72\x39\x37\x54\x69\x4c\x50\x7e\xd3\x33\x7a\xe5\x4c\xbc\xd1\x8c\x25\x8a\x54\xed\xc1\xb0\xc3\x45\xfb\xb9\x5f\x9b\x11\x54\xe7\x7d\x3b\x6a\x71\x8e\xfa\x05\x5e\xec\xcf\x52\x4b\x97\x87\xdd\xa0\x56\xf2\xa6\x99\xa9\x1f\x1f\x55\xa0\x1d\x69\x2e\x4a\x36\xb7\x3b\x56\x1c\x17\x3a\xaa\x5e\x08\x6e\x78\x70\x36\x4d\x53\x8b\x26\x1a\xd3\x9a\x66\xae\x59\xcc\x63\xd1\x5e\xaf\x67\x3a\xe9\x41\xbc\x87\xb7\x84\x63\xcb\x33\xb8\x28\x56\x77\x9f\xfe\xe6\xb8\xa0\xf2\x63\x7c\xfa\x01\x28\x09\x19\x43\x0e\x83\x96\xc5\x2d\x24\x5c\xd3\xa5\x9c\x5a\xd2\xc4\x14\x50\xce\x5c\x9b\x00\x17\x32\x85\x05\x82\x9c\x63\x08\x24\x23\x58\x12\xcb\x42\xc8\x51\x8c\x0a\xeb\x1a\x2e\xe8\x45\xcf\x27\x0c\xb0\xeb\xa5\x6c\x87\x0b\x4c\x00\x06\x1c\x10\x46\xde\xc2\x05\xb8\x11\x17\x4b\x66\x34\x3d\xd8\x99\xe3\xa9\x1f\x5c\x54\xe1\xdc\xd4\x8b\x55\x14\xd2\x62\x2b\xab\xdb\xee\x38\x1b\x2d\xdd\x8c\xf5\xb3\x53\x0f\x0f\x6a\xd9\x60\x2a\x3a\xc4\x91\x6c\xb1\x6e\x4c\xb9\xdb\x27\x53\xaf\x16\x8f\xa2\xbe\x13\x53\x41\x0e\x1d\xb7\x19\xcc\xcf\x58\x69\x33\x37\x32\x96\xbf\xef\xc7\x1d\x2e\x9e\xfd\x32\xdc\xd7\x73\xcb\x48\xac\xa2\x8d\x67\x9e\x56\x1e\x54\x82\xe6\xbc\xdf\xcb\x4d\x62\xf3\xea\x2c\xe2\xba\x59\x31\xad\xaa\xf1\x00\xac\x06\xc1\x75\x7c\x33\x4b\xba\x5d\x5a\x17\xd1\x6c\xd5\x2f\x29\x03\xb5\x47\x22\x1c\xf5\xb5\x75\x4a\x95\x66\x3a\xc9\xd3\xc9\x8c\x8f\x4b\x25\x73\xb5\xea\xcc\x77\xf1\x62\x7a\x06\x17\xf9\xd5\xee\xd3\xdf\x1d\x17\xe2\x63\x7c\xfa\x81\xb8\xcc\x91\xa6\x29\x5c\x60\x23\x13\x58\x16\x67\x08\x41\x8c\x20\x86\xc8\x02\x84\x48\x8e\x80\x02\x84\x5b\xb6\x4d\xb8\x29\x1c\xc2\x15\x16\x82\x32\x04\xb1\x64\x8e\xc2\xe8\x1a\x2e\xc8\x45\xcf\xa7\x1c\xd1\xcb\xf3\xa8\xc7\xd2\xc7\xdf\x0f\xc1\x90\x89\x37\x70\x01\xe4\x8d\xb8\x00\x72\x36\x18\x77\x97\xcb\x71\x94\x3b\x5e\xaa\x9c\x2a\x6b\x93\x88\xd6\x5f\xc7\xda\x06\xdf\x68\xca\x87\x49\x42\x3a\xb5\x54\xb9\x3f\x23\x6b\xda\x37\x4d\xb5\x6a\x7a\x38\xa2\xfc\xb4\x15\x69\x64\xb4\x64\xd5\x30\xeb\xc5\xc8\xa6\xb9\xa9\xc7\xba\x13\x6f\x33\x88\x34\xcd\x04\x12\xb5\x3d\x30\x76\xb8\x38\xea\xd7\x44\xce\x2d\x46\xe2\xa1\xc6\xb8\xa1\x1c\xad\xa2\x0f\x8b\x73\xaf\xbf\x99\xf7\x36\xd9\x74\x41\x55\x27\x86\x4c\xb1\x31\xb6\x4c\x3d\x21\xf0\x50\xf4\x9c\x9a\x51\x18\x1b\xae\xc3\xa6\xbd\x7c\xd9\x49\x77\x70\x7b\x09\xa3\xd9\x75\xb8\xe9\xf6\x41\x66\x3a\x5a\x28\xb3\x17\xaa\x57\x22\x93\x2d\xe1\x98\x7f\x06\x17\xba\xbe\xfb\xf4\x77\xc7\x05\xff\x18\x9f\x7e\x20\x44\x12\x6c\x9a\x36\x03\x2e\xc7\x5c\x20\x64\x5b\x96\x50\x0e\x90\x8e\xe9\x60\xd3\x76\x5d\x06\x5c\x29\x20\x74\x2c\x69\xdb\x94\x29\x77\x9b\xbe\x30\x20\x90\x72\x38\x74\xad\xab\xf9\x05\xbe\xe8\xf9\x4c\x10\x72\xbd\x94\x3c\x3c\xff\x4e\x0c\x15\x1c\xbd\x85\x0b\x71\x2b\x2e\x4a\x95\xfc\x78\xd5\x96\x1b\x15\xcd\x66\xe7\x79\x90\x46\xb3\xfc\x34\x84\x62\xb4\x6d\x20\xba\x89\x5b\x0b\xb2\x80\xed\xf6\x1c\xae\x82\xcb\x52\x53\x9b\xab\x6a\x71\x54\x9d\x38\x75\xe2\x07\x33\xb9\x39\xa3\x4d\x16\x1e\x17\xb4\x62\x1b\x77\x62\xed\x5c\xa2\x5e\xdd\xd4\x1c\xb7\x4d\x9e\xf3\x8b\xce\x51\x7e\x01\xc9\x34\x9e\x32\xe6\xdd\xda\xb2\x2d\x33\xa3\x1a\x5e\xd9\x85\x72\x24\x9c\x50\xf3\x08\x8b\x4e\x87\xa5\x5c\x79\x54\x10\xa5\x6e\x69\xea\x48\xbf\x2b\xfb\xa2\x18\xb2\xf2\x50\xd4\x46\x2a\xb9\xca\xc3\x72\x27\x53\x4e\x58\xe1\x59\x6a\x40\x8d\x28\x59\x8f\x67\x75\x92\xc9\x9a\x46\x32\xb4\xf5\xfb\x58\xef\x0c\x2e\xb2\xa3\xdd\xa7\xbf\x3b\x2e\xd8\xc7\xf8\xf4\x83\x74\x15\x13\x82\x43\x62\x99\x84\x21\xcb\x42\x96\xe9\x58\x14\x21\x13\x09\x97\x60\xca\xb8\xb0\x6d\x6c\x3a\x58\x60\xc7\x26\xa6\xeb\x48\x68\x0a\x1b\x42\x85\xa9\x89\x1d\x8e\xe9\x35\x5c\x5c\x8e\x08\x02\x10\x79\x39\x9a\x6c\x4b\xe9\xc3\xd3\xef\x06\x31\x41\xf9\x5b\x79\x37\xe0\x37\xe2\x82\x86\x06\x5e\x32\x9e\x1d\x25\x32\x3c\xc3\x10\x4c\x8d\x33\x85\x22\x6c\x92\x4d\x6c\x52\x6e\xcb\x55\x26\xd4\x4c\xf8\x4b\x83\x40\x5f\xda\x30\xec\x4e\xe6\x1a\x4c\xe9\xb6\x1e\x34\x8d\x45\x2f\xdc\xcf\x15\x6c\x84\x9c\x72\xbb\xdd\xf6\x5c\xb6\xec\xfb\xb9\x59\x91\xf0\x6e\x7a\x6c\xa4\x76\xfd\xb8\xc3\xc5\x51\x7e\x31\x77\x16\xa9\x8c\xe5\xc4\x8b\x79\x66\x0f\xc7\x91\xbe\x1b\x2e\x82\xf1\xd2\x5b\x88\x72\xc8\xf2\x97\xa1\x5a\xa1\x9c\x0a\xeb\x7e\x48\x33\x0c\x6d\x5c\x24\xd1\xa5\xa9\x92\xcd\xf8\x20\x08\xe6\x09\xbf\x69\x0d\x1a\x8e\x1f\x59\x86\xcd\x41\x9c\x2e\x20\xd0\x06\xc3\xaa\x4b\xe6\xab\x24\xdb\xd2\x8f\xb5\xcf\xe0\x22\x13\xdf\x7d\xfa\xbb\xe3\x82\x7e\x8c\x4f\x3f\x58\x42\x02\xdb\x75\x38\x46\x0c\x08\x6c\x3a\x94\x4b\x13\x52\xc8\x98\x44\x10\xb9\x14\x22\x8e\x6d\x20\x80\x42\x16\xe3\x26\x66\x8c\x28\x8b\xdb\x96\x6d\x49\x17\x72\x0e\xc9\xd5\x78\x71\x39\xb3\x96\x88\xb0\xeb\xa5\xbb\x79\xd4\xe1\x97\xa0\x20\x12\x6f\xe5\xdd\x80\xdd\x88\x0b\xee\x15\x37\xd2\x5e\x37\x52\xf9\x59\x95\xfa\xd5\xf8\xa0\xd7\xc9\x42\x6d\x58\x08\xb7\xf3\x19\xa4\xba\xcd\x1e\xc3\x6b\x31\x77\xe3\x38\x1e\x4e\x68\x2a\xa1\xc9\x08\x9e\xf5\xb9\x2f\xa3\x6e\x66\x56\xa8\xe6\x48\x4c\xd5\xac\x8a\x1b\x8a\xf8\x58\xda\xb1\x64\x79\xa2\xa5\xcc\xa1\x7d\x14\x2f\x8e\xf2\x8b\x64\x7e\x0e\x22\x46\x10\xd1\x72\x6c\x6d\x37\xb8\x63\xeb\xa5\x75\xd5\xee\xc1\xe1\xba\x19\x89\xf6\xc2\x91\x78\xb3\xbe\xec\xf6\x3c\x9b\xa2\x12\x2d\x20\xd4\x1c\x54\x82\xed\x6e\x21\x96\xea\x76\xc2\xb5\x76\x33\x52\xdb\x34\x9b\x60\x69\x74\xf8\x3a\x6f\x4c\xe4\xd0\xeb\x8e\x22\x78\x59\xdb\xe5\x17\xf6\x19\x5c\xa4\x3a\xbb\x4f\x7f\x77\x5c\x90\x8f\xf1\xe9\x07\x22\x18\xa1\xa6\x23\x08\x06\x8a\x4a\x8a\x28\xc5\xb6\xc3\x24\x65\xd2\xa4\x1c\x42\xcb\xb4\x25\x26\x0c\x5a\xd0\x96\x36\xc0\xc0\x62\xc0\x02\x0c\xb9\x44\x50\x6c\x31\x0b\x92\x87\xa7\xbd\xe7\xd7\xb8\x00\x97\x3c\x9f\x00\x2a\xe0\xc5\x68\xf2\x54\xfa\xf8\xcb\x59\x58\x8a\xb7\xf2\x6e\x40\x6f\x9d\x47\x75\x7a\xb5\x59\x27\x16\xeb\xf7\x4b\xd5\xf2\xa6\xd6\xaf\x0d\xfa\xb6\x31\x9f\xf6\x40\xc3\x4a\xa6\x97\xb1\x28\x8a\x2e\x1b\x8b\x52\x3c\x8f\xa6\x15\x27\xbc\x19\x0d\x9a\xa4\x3a\xf0\xd2\xe1\x44\xaa\x33\x84\x51\x11\x65\x74\x1d\xee\x0d\x66\x11\x3b\xda\x8b\xd7\x93\xb1\x65\xaf\x5c\xf0\x1b\xbd\xe7\xf5\xa8\xce\x51\xbf\xba\xf5\xaa\x5b\x28\xc9\x6e\x64\xdc\x29\xbb\x1b\x92\xf5\x16\x8d\x46\x41\x5a\xb3\xe1\x3c\x38\x5e\xba\xa1\xf1\xa8\xda\xc8\xf2\x64\xdb\x0a\xe7\x10\xcd\x3b\xd9\x24\xc9\xd6\xe7\xcb\xa1\x2e\x63\xa3\x79\x3a\xdf\x13\x11\xcd\x26\x29\xcf\xf6\xba\x46\x37\x3c\x59\x36\x3c\xbb\x8a\x7b\x64\xb5\x9b\x47\x35\xce\xe0\x22\x21\x77\x9f\xfe\xee\xb8\xc0\x1f\xe3\xd3\x0f\x96\xc3\x2d\x82\xa4\x63\x39\xc2\x15\xca\x75\xa0\x45\x99\x72\x38\x40\x96\x0b\x05\x56\x84\x63\x0c\xa9\x42\x2e\x20\x08\x39\x16\xa5\x52\x52\x22\x6c\x02\x88\xad\xd4\x61\xd9\xe8\x52\xbc\x80\xf2\xa2\xe7\x23\x80\xa4\x78\xb3\xf4\xf0\x5b\x68\x8c\x31\xf1\x66\xde\x8d\x6f\x8d\x17\x90\x17\x47\x48\x76\x09\x97\x09\x68\xcd\xec\xe8\x62\xd5\x0e\x1a\x9b\x5c\x95\x2c\x22\xd1\xac\x55\x6d\xf6\x2b\x5d\x2d\x92\xe3\x83\xc8\x20\xb6\x30\x3c\x4c\xe6\xd4\x68\x6b\xe1\x98\x67\x8d\xec\x3c\xb1\x69\x3e\x62\x65\x53\x34\x19\xaf\xad\xe0\x6c\x03\xf3\x91\xe5\x8a\xa7\x72\xcf\xf1\xa2\x7d\x94\x5f\x34\x04\x30\xa7\x2b\x3f\x59\x4d\x39\x1c\xac\x7a\x92\x66\x3b\x53\x43\xef\x79\x78\x5e\x6a\x74\xda\xe9\xc9\x22\x37\xda\xb0\xa2\xc2\x74\x59\x64\x39\xb9\x0e\x8e\x42\xa3\x99\xde\x64\x9b\x08\x1a\x7b\x6c\x34\x5e\x26\xe3\x6b\xea\x86\x9c\x5c\x1f\x93\x38\x1c\xad\xdc\x65\x7b\x11\x71\x76\xf1\xa2\x72\x06\x17\x31\xb8\xfb\xf4\x77\xc7\x05\xfa\x18\x9f\x7e\x90\x80\x62\x82\x29\x70\xb1\xab\x4c\x60\x32\x93\x52\xe9\x28\x04\x38\x93\x54\x21\x81\x94\x90\x42\x02\x49\x09\x11\x08\x9b\x36\xb5\x39\x00\xc0\xe5\xcc\xb4\x4c\xc7\x06\x42\x5d\xc3\xc5\x65\xcf\xc7\x80\x83\x8b\xf3\xa8\xa7\xd2\xfd\x6f\xf1\x21\x29\xb1\x7c\x33\xef\xbe\x75\x5f\x8f\x46\xca\x45\x18\xdb\x84\xc6\xd1\xc1\xa8\x3a\x54\xa9\xa4\x59\x25\x7e\xd6\x1f\xa4\xa3\x55\x23\x95\x62\x2b\xdb\x0e\xc7\xb0\x39\x99\xd8\xd1\xfc\x46\xc5\x35\x13\x75\xd9\x2c\x91\x10\x6d\x2b\x17\x82\x39\x43\x98\xe1\x48\x23\x54\x58\xcd\xf3\xb2\xb9\x41\x53\x39\x58\x25\x86\xd9\xaa\xbf\x77\xc6\x1d\x2e\x8e\xf2\x0b\x27\x3e\x05\xf3\x85\xd3\x9b\x23\x05\x49\x33\xdb\xd4\x1b\x21\x6f\xd8\x8b\x81\x54\x3b\x21\x07\x41\xd9\x01\x22\x61\xf5\x86\xcd\xa9\xd4\x36\xcd\xcd\x7c\x14\xae\x7b\x1b\x37\x52\x1f\x74\xa4\x1c\x26\xcb\x73\x5e\xa3\x49\xb8\x59\x8c\x7a\xb5\x12\x8a\xc6\xe1\x6c\x1c\xd1\x32\xcb\x79\x74\x17\x2f\x8a\x67\x70\x11\x35\x76\x9f\xfe\xee\xb8\x80\x1f\xe3\xd3\x0f\x16\xb4\xb9\xc3\xa1\xa9\x2c\x53\x70\x60\x41\x86\x2c\x80\x90\x8d\xa1\xe9\x28\x0b\x31\x06\x89\x62\x5b\x3f\x95\x48\x30\xc2\x4d\x68\x49\x9b\x59\x36\x85\xa6\x65\x0a\xec\x00\xe7\x1a\x2e\x2e\xee\x77\x93\xad\xd4\x97\xa3\xc9\x63\xe9\xe3\x8f\x47\x22\x20\xdf\xcc\xbb\x6f\xdd\xd7\xe3\xc9\x24\x5c\x4d\x26\xe3\x64\x74\xd5\x98\x84\xbd\xe5\x6a\xa2\xa6\x83\x46\x85\x76\x23\xcb\x9e\xdf\x4c\xfa\xd6\x30\xb1\x88\x27\x26\xe3\x18\xd0\x67\x68\x91\x2e\x27\xa7\x99\x75\x2e\xe9\x54\xa3\xc9\x50\x7b\x0a\x6c\x5c\x09\xa9\x62\x66\x6c\xd6\x0c\xa5\x05\x49\x77\x8d\xda\xb3\xe0\xfc\x68\x1e\xd5\x3e\xca\x2f\x12\x32\xbb\x50\xbe\xc8\xe4\x73\x91\xe9\xbc\x5c\x5f\xad\xcc\x89\xe9\x36\x8a\x9b\x64\xa6\x3f\x5e\x76\xea\xb5\x99\x6d\x74\x47\x83\x72\xde\x0e\xe6\x23\xc1\x91\x9a\xeb\x85\x69\xa3\xef\xaa\x94\x1e\x8a\x14\x71\x70\x95\x2f\x36\xb9\x13\xb2\xaa\xa1\xd9\x30\xdd\xce\x6a\xa3\xba\x3b\x2c\x0d\xc8\x0e\x17\xb9\x33\xb8\x08\xcf\x76\x9f\xfe\xee\xb8\x00\x1f\xe3\xd3\x0f\xc0\xb1\x05\x83\x40\xd9\x8c\x48\xc5\xa1\x70\x08\x05\x02\x5b\x4c\x42\x40\x21\xc5\x16\x65\x42\x5a\xca\x66\x9c\x20\x6e\x72\x04\xa8\xb0\x24\xa6\x5c\x29\x0b\x98\xb6\x32\xed\x6b\xb8\xb8\xb8\xdf\x4d\x28\x87\xf4\x32\x6a\x1e\x4b\x1f\x7f\xed\x94\x08\xf0\x66\xde\x7d\xf3\xbe\x1e\x4e\x35\x8a\x3c\x51\x52\x76\x03\xc6\xa3\xb1\xd9\x48\x8b\xc7\xcb\xb3\x9a\x67\xf1\x84\x13\x55\xc3\x54\xdc\xa3\x7a\x9d\x4f\xa2\x53\x36\xf5\x80\x55\x9e\x46\xac\x92\x13\xcb\xc7\xfd\x4e\x70\x4d\x5d\x61\xf7\xf1\x2c\x38\xc8\x36\xdd\xcd\xa4\x93\x4c\x84\x98\xb5\x8a\xf4\x0d\x98\x3b\xc2\xc5\x51\xbf\x2a\xb4\xc9\x55\x6a\x55\xe4\xbb\xab\x55\x29\x5d\x71\x40\xa7\xad\x8d\x6a\x41\xa7\x17\xcc\x51\x80\x2b\x7a\x67\x3a\xae\x67\x33\x59\x50\xce\xb5\x27\x13\x73\x14\xcc\x35\xed\x42\xa6\xc0\x6b\x7d\x27\x37\x8d\xb0\xcd\x24\x24\x24\x4a\xd9\x4b\xaf\x3e\x08\xdb\xcc\xc8\xeb\xd4\xe6\xa1\xd8\x0e\x17\xa9\xd7\xb8\xc8\x87\xd2\xbb\x4f\x7f\x73\x5c\x10\xf9\x31\x3e\xfd\x40\xa0\x45\xa1\x50\x16\xa6\x1c\x43\x86\x1c\xcb\xc4\x92\x08\xe9\x50\xc5\xa5\x0d\x6d\x40\x94\x62\x36\x73\x80\xb0\xa1\xc4\x10\x5a\xd4\x72\xb9\x23\x2d\xe1\x4a\xd3\x84\xdc\xd9\xba\xfe\xfe\x3e\xd1\x19\x5c\x5c\xdc\xd1\x26\x1c\x01\xfc\x76\xe9\xfe\x57\x6e\xb1\xe4\x14\xbc\x91\x77\x33\x79\xf3\xbe\x5e\x02\x26\xf2\x53\x68\xaf\x1a\xb3\x79\xb7\x9f\x1a\x56\x29\x5d\xda\x91\x3c\x9d\x5a\xc5\x6e\xa4\xb7\x4a\xc0\x05\x46\x56\x97\x8e\x3b\x6e\x4d\x55\x8d\x78\x30\xee\xd5\x60\xb1\x6f\x07\xf1\x1c\x0e\x22\x76\x53\x90\x4a\xd6\x70\x7c\x1c\xb4\xcb\x3e\xa1\x0d\x23\x1d\xcb\x07\x0b\x25\xb2\xeb\xc7\x2d\x2e\xdc\xa3\xfc\x62\x5a\xca\x67\x23\xc1\x78\x87\x17\x52\x30\xe2\x0c\xc2\xc1\x61\x7f\x45\x63\x8e\xaa\x97\xc2\xcd\x06\xcf\x0f\xd7\x49\x7b\xbe\x56\x39\x6d\x90\x0e\x63\xab\x47\xe0\x72\x36\x59\xe7\x42\xb8\xdf\xee\x0c\xc3\xe1\xea\xb0\x10\xf2\x22\x5b\xc5\xc0\x38\x35\x8b\xb9\x83\xe0\xac\x9f\xaf\xe9\xe6\x0e\x17\xda\x19\x5c\xc8\xfe\xee\xd3\x15\x5c\xfc\xb7\xfd\xed\x5d\xeb\x4e\x5c\x88\x8f\xf1\xe9\x07\x8b\x48\x65\x02\x65\x41\x57\x31\x24\x5d\x1b\xd9\xd2\x71\x91\x2d\x39\xb3\x6c\x29\x39\x74\x95\xc3\x5c\x47\x38\x88\x72\x65\x2b\x8e\x85\x22\xd4\xc6\xae\x90\x8c\x3b\x90\x32\x79\x2d\x5e\x5c\xdc\xa1\x20\x02\x11\x74\x79\x1e\x25\xd0\x6e\xd3\xef\xf1\x37\x8b\x01\x02\x6f\xa4\xdd\x4c\xde\xbc\x4c\x5b\x52\x7e\x7e\xea\x52\x6f\x28\xb2\x69\xbc\x5e\xd7\x4d\x31\xa8\x27\x83\x70\x81\xf4\x74\x9d\xe7\x6d\x42\xe3\xcb\x90\x57\x73\x8d\xea\x88\x99\xb1\x1a\xce\x16\xac\x5a\x71\xd8\x2b\x8e\xc3\x6b\xbd\xd9\x4c\xf7\x63\x35\xb3\x1a\xce\xca\xc4\xa0\x9a\xe9\xe7\xaa\x56\xd2\x37\xc3\xe5\xf5\x73\xb8\x70\x8f\xe2\x45\x51\x6f\x13\x7b\x42\x62\x3e\x1f\xcf\xeb\x18\xfb\x64\x62\x99\x75\x93\x07\x23\x31\x27\x69\x8b\x82\x55\xd6\xea\x11\x7b\x5e\xd4\xca\x05\x31\x29\xb7\x6d\x8b\x0f\x71\xa5\xae\x25\x80\xb9\x10\xde\x7c\xd1\x59\xd5\xfa\xd1\x66\xda\x65\x24\x17\x4d\x06\x67\xab\x46\xbb\x58\xcf\xd4\x0a\x5b\xc2\xb1\xf0\x19\x58\x90\x37\x8f\x0d\xfe\xb7\xfd\xbd\x2b\x5c\xf0\x8f\x71\xe9\x07\x0e\x98\x23\x89\x30\x19\x35\x01\xa4\x54\xda\x18\x23\x46\x20\x13\x4a\x42\xec\x12\x8b\x48\x00\x30\x91\x04\xb9\x5c\x9a\xca\x94\xcc\x65\x90\x99\x00\x2b\x29\x90\xe4\x36\xbe\x06\x8b\x8b\x1b\xda\x44\x52\xc8\x2e\x27\xe5\xdb\xd2\x5d\x7a\x71\xf8\xf5\x6a\x24\xe1\x1b\x69\x37\x93\xb7\x2e\xd3\xe2\xc8\xac\x9f\x1a\xf5\xfd\x48\xb5\xb9\xdc\xa4\x7b\x71\x9f\x19\x05\x30\x4b\x87\x63\xa5\x4a\x16\x0f\xe6\xe3\x9a\xec\x98\xed\xc2\xa8\x3d\x72\x63\x50\xab\x32\x58\xa0\xbe\x96\x80\xdd\xd1\x82\xa4\xcc\x50\xb2\xd2\x4e\x44\x47\x99\x65\xb9\x48\x9a\xa3\x7e\xb2\x33\xe3\x3e\x1f\x85\x39\xdc\x83\x61\x87\x8b\xa3\xf4\x42\xe4\x73\x3c\xaa\x77\xfb\xfe\xaa\x36\x5e\xf6\x4d\x73\x38\x88\x98\x13\x63\x33\x30\xb5\x70\xb7\x04\x8d\x72\x99\xc7\x72\x91\x4a\x27\x94\x4f\x7a\x8b\x5c\xbd\xe3\x41\xd1\x49\xac\xc2\x0d\xce\x3d\x16\x8e\x96\xb5\xb1\xb9\x8c\x89\x45\xbd\xb7\xa8\x67\xbb\x91\x8d\x52\x8d\x58\x3b\x5a\x28\x6f\xe9\x47\xc5\x19\x5c\xe0\x37\x8f\x0d\xfe\xb7\xfd\xbd\x0b\x17\xec\x63\x7c\xfa\x81\x49\x41\x80\x12\xd0\x55\x5c\x51\x41\x4c\xd3\x01\x2e\x42\x8e\x6b\x0a\xa9\x14\x67\xdc\x76\x30\x45\x84\x48\x4e\x19\x56\x84\x43\xd3\x15\xa6\xcb\xb8\x45\xb1\x2b\x1c\xc2\x77\xab\x46\x17\xb6\x2f\x2e\x6f\x50\x50\xc0\x28\xb9\x98\x7c\x3c\x95\x3e\xfe\xc0\x3a\x65\xf0\x28\xed\x3e\xf9\xfb\x1a\xe0\x8f\x18\x78\x0b\x13\x68\xa0\xc5\xfc\x64\xd0\xed\x77\x32\x93\xa2\xf0\x30\xf3\x14\x45\xae\xae\x97\x8c\xb4\x53\x2b\xf4\x6c\x33\x98\x91\xc3\x59\x39\xa8\x1b\xab\x70\xbb\x9c\x2a\x64\x13\xf9\xf5\x70\x5e\x6c\xe7\xeb\x9b\x41\xbd\xd8\x9c\x64\xd7\x89\x72\x38\x91\x8a\xd5\xf2\xc9\xb4\x51\x4c\x8f\x2b\xae\x15\xf6\x2a\xbb\x3e\xdc\x61\xe2\xa8\x4f\x3b\xbd\x46\xbb\xdc\xa8\xc6\x5d\x4f\x5f\xad\x97\xcd\xf8\x3a\x53\xe9\xb2\x49\x45\x19\x04\x95\x8c\x8d\xbe\xc9\x0f\xcd\x69\xbb\x1a\xaa\xcd\x63\x8b\xd9\x52\xef\x99\x96\x53\x0c\xce\xda\x4d\x45\x70\x72\x56\xd7\xa6\x51\xab\x28\xdb\xb5\xfc\xdc\xa8\xb3\x2c\xb5\x17\x79\xd1\x5c\x46\x8c\xd1\x0e\x13\x44\x27\x59\x73\x33\x42\x47\x00\x8c\xcc\x1a\x27\x2e\xf5\x57\xc0\x04\xba\x1b\x13\xf4\x63\xfc\xf9\x81\x2a\xe5\x42\xc0\xb8\x09\x5c\xcb\xb1\x08\xc4\x08\x2a\xc2\x91\x09\x6d\x48\x5c\xe5\xd8\x94\x62\x07\x62\x8a\xb7\xe3\xb7\xa3\x4c\xe2\x3a\x0e\x86\xd2\x01\xb6\xc9\x1d\x64\xba\xd7\x8e\x98\xc3\x8b\x8b\xb0\x14\x0a\x4a\x2e\xa6\xdc\x4f\xa5\x87\x9f\x99\x47\x02\x23\x70\x05\x13\x4c\xdc\x88\x09\xc8\x17\x5a\x42\xb5\x83\x72\x16\xc9\x75\x68\x32\xd3\x59\x56\x42\xb3\x55\xb5\x60\xe8\xe5\xbe\x61\xa9\x51\x01\x97\x13\x4e\x2c\xe3\x96\x26\xa4\x97\x88\x26\x93\xc3\x30\xcb\xe4\x1d\xbf\x60\x97\x16\x23\x66\xac\x3a\x3d\xd4\xa9\x18\xfd\x44\x1c\x56\x0b\xc8\x2f\x55\xf5\x48\x2f\x96\x92\xf6\xae\x0f\xb7\x98\x50\x47\x69\x05\x9a\x06\x1b\x0e\x66\x89\x4a\x64\x10\x9f\x44\x87\x62\xb8\xda\x18\x38\xc1\x13\x2c\xd2\xaf\x2d\x63\xdd\x5a\x6a\x51\x9a\x17\x57\x89\x5c\x2a\xda\x90\xc8\xe8\xd6\x69\xcc\xca\xaf\x1a\x9d\x74\x2e\x17\xd2\x8a\x36\xf4\xc7\x89\x25\x68\x4f\xe3\xd6\x6c\x3c\xcd\xd7\x23\xdd\x6c\xb6\x2a\xb5\xfa\x4e\x09\x70\x06\x13\xe3\xe2\x89\x4b\xfd\x15\x30\x71\x7f\x9c\x20\x1f\xe3\xcf\x0f\x84\x00\x69\x0a\x0e\x1d\xba\x1d\x9e\x81\xc5\x4c\x60\x32\x0c\x20\x66\x4a\x00\xdb\x41\x54\x9a\x18\x63\xdb\xa4\x14\x01\xec\x58\x90\x12\xe1\x60\x48\x5d\x28\x95\x4b\x4c\x7a\x75\x19\xea\xe2\x36\x37\x45\x42\x5e\x41\xcc\x63\x29\x14\x42\x72\x41\x19\x04\x88\x5c\xc3\x04\xbf\x11\x13\xa0\x98\x1e\x27\x93\xd5\x4a\xa2\x92\x35\xdb\xa3\x6e\xb8\x6c\xf9\x31\x3d\xdd\xf4\x37\x85\x4c\xb5\x14\x96\xd3\x6a\x49\xcf\x55\x45\x93\x83\x91\x3d\xf1\x97\x15\x27\x63\x6c\xc2\xa1\xa6\xd1\x73\x94\x2f\x12\x73\x34\xae\x92\x72\xa7\x02\x99\x23\x47\x42\xe7\x24\x69\x0e\xe7\xb4\x32\x9d\xee\xfa\x70\x87\x89\xa3\x9c\xa2\x56\xb3\xe1\xa8\xd1\xa9\xd6\x0c\x5f\x4b\x9b\x2c\x61\x27\x53\x53\xb3\x0b\xd7\xd3\x55\x8a\x44\x8b\xc1\x88\x9d\x1e\x7b\x89\x1a\x5e\x76\x07\xe9\xe0\xc2\x8d\x1b\x59\x8f\xa6\x91\x17\xcb\xd5\xf5\x72\x6d\xac\x0f\x86\xee\x4c\x6c\x92\xf1\x3c\x61\xa4\xd1\x4e\x37\xcb\x7c\x6e\x81\xf1\x64\x17\x27\x96\x67\x30\xe1\x4f\x4f\x5c\xea\xef\x89\x09\xfc\x31\xfe\xfc\x60\x4a\x66\x5b\xae\x74\xb1\x8d\x1c\x6c\x53\x66\x39\x90\x58\x04\x50\x80\x08\x33\xa9\xc2\x52\x51\x89\x80\x89\x00\x54\xd2\x61\xcc\x26\xc0\xb2\xa9\x69\x32\xc1\x05\x72\x15\xbd\x96\x53\x5c\xde\x94\xa0\x04\xa2\x2b\x73\xa7\xc7\x52\x28\x08\x13\x98\x4a\xcc\x91\xb8\x86\x09\x76\x23\x26\x58\x7f\xba\xa0\x42\x64\xcb\xab\xda\xc2\x28\x81\x48\x31\x9d\x18\xa9\xbc\xaa\x95\xa2\x5e\x58\x0d\x6b\x96\x16\x15\xb5\xb1\x99\x6c\x2f\x68\xb9\xa9\x97\xd6\x9d\x7a\xcc\xcd\x68\xeb\x0a\xeb\xf6\xc0\x40\x0c\x57\x61\x8d\x15\xa2\x69\x33\xb1\x0a\xfb\xf9\xe5\x78\x61\x87\x4b\xb9\x69\xe5\x68\xf9\x49\x1d\xb9\xa9\xcc\xa2\xe5\x38\x62\x0e\xc4\x6a\xc5\xb4\x5c\xbf\x08\x55\xc8\xe0\xe9\x42\xa7\x37\x4d\x8f\xe3\x7e\x33\x36\xc8\xc4\xed\x78\x64\xe9\xe2\x55\x74\x69\xa3\x74\xb6\xef\xa7\x36\xa3\x59\xa3\xe3\xeb\x51\x9e\x04\xf9\x4c\x4c\xc5\xa4\xbf\x6c\x86\x7b\x34\x65\x0e\x87\x13\xd5\x9d\x80\x7c\x78\x1b\x87\xa2\xd3\x33\x98\x18\xa6\x4e\x5c\xea\xef\x89\x09\xf4\x31\xfe\xfc\x80\x90\x05\x98\x45\x80\x24\x84\xd9\xd0\x05\x36\xe2\xc2\x74\x81\xad\x20\x35\x1d\x29\x19\xdd\x46\x21\x17\x41\xc9\x4c\x6a\xb9\xca\x51\x0e\x65\x0e\x93\x0e\x66\x9c\x4b\x5b\x5e\xdb\xc6\x03\x17\x33\x69\x4a\x91\xb8\x9c\x85\x3f\x95\x42\x01\xb0\x10\x0c\x31\x82\xd1\x35\x4c\xd0\x1b\x31\xb1\xce\x2c\x4d\x10\xad\x18\xd3\xe4\x72\x39\xf4\x16\xb1\x7c\xdc\x44\xcd\x66\xdd\x2f\x88\x4e\x7f\x5c\x0b\x71\x05\x6b\x70\x04\x90\x43\xd7\x4e\x0a\x6e\x92\xe6\x2c\x58\x4e\x96\xbc\x84\x88\x7b\xe9\x46\xa7\x8e\x52\xdd\xb1\xad\x96\xb9\xf5\x78\xc4\x55\x2a\x6b\xcc\xb2\xab\xfe\x38\x5c\xdd\x2f\xed\xef\x30\x71\xd4\xa7\x64\x50\x5c\xcd\x53\xeb\x44\x2f\x37\xac\xe8\xa3\xc9\xca\x87\x73\x66\x61\x3d\x9f\x69\x97\x42\xd1\xb1\x61\x80\x9e\xf4\x73\xc5\x42\xb6\x36\x15\xc1\x2a\x13\xe3\x61\xd4\x8c\xc7\xb5\x15\xc9\xc0\xb6\x5f\x33\xb1\x11\x4b\x8a\x54\x73\xda\xe0\x1e\x8a\xd4\x6b\xa5\x68\xae\x36\xde\x8c\x56\xdb\x38\x14\xf5\xcf\x60\xa2\xdf\x3b\x71\xa9\xbf\x27\x26\xe0\xc7\xf8\xf3\x83\xc9\x5c\x6a\xd9\x9c\x38\xa6\x24\x4c\x72\x20\x89\xb4\x6d\x61\x52\x61\x71\xd7\x06\xb6\x49\x91\x29\x19\xe2\xae\x09\x4d\x42\x5d\xdb\x76\x29\xe3\x26\x33\x1d\xe4\x62\x08\x4d\x09\xae\xe4\xd8\xe0\x72\xc6\xc0\x88\xbc\x7c\x35\xef\xa9\x14\x72\x06\x24\x66\x54\x42\x7c\x2d\xc7\x66\xe4\xd6\x38\x61\xc1\x45\xb2\x6c\xf6\x13\xfd\x65\x3f\xbd\x49\x8d\x1a\xb3\xd0\x32\x37\x2a\x8d\x6b\xe9\x90\x6f\x1a\xee\xa6\x50\x1d\x8e\xc6\x60\x91\x33\xc6\xc5\x8c\xbe\x6e\x58\xf9\x65\x96\x1b\x96\x67\x76\x53\xa9\xa1\x5c\xfa\xb0\x9e\x1a\xaf\x26\xab\x4c\xbd\x53\xb2\x4b\xe9\xe6\x7c\xda\x69\x0f\x61\x45\xec\xfa\x70\x8b\x09\xe7\x28\x9f\xc0\x33\xb5\x4a\xd6\x7a\xaa\xde\x9f\x76\xc4\xba\x4f\x51\x7a\xa3\xc1\x1c\x1f\x85\xc4\x7c\xd3\xc3\x2c\xe6\xf4\xad\xc5\xd2\x19\xd7\x96\xb0\x01\x78\x39\x39\xf5\xb5\x69\x84\x87\x96\xc2\x28\x76\xd3\x04\xf4\x47\x39\x9a\x81\x9a\xe5\x47\x55\x59\xac\x43\xdd\x50\x28\xd4\xc5\x61\x73\x87\x89\xde\x19\x4c\x9c\x42\xe2\x2f\x81\x89\xfb\x73\x6c\xf0\x31\xfe\xfc\x60\xd9\xd8\xa4\xa6\xa4\x58\x10\xe1\x2a\x64\x5b\x84\x29\x87\x53\x65\x2b\x4b\x31\xcb\x04\xd2\x16\x94\x39\x84\x3b\xcc\x55\x26\x40\x14\x21\x2c\xa8\x70\x84\x63\x73\xd3\x74\xf6\xb7\x21\x2e\x61\xe2\xf2\xec\x48\x00\x7c\x79\xd3\xfb\xa9\x74\xff\x36\x08\x93\x50\x90\xab\x39\x36\xba\x11\x13\x7c\xc9\x6a\xa3\x0a\x29\x15\xc8\x74\x96\xe0\xf5\xfa\x94\x05\x4d\x16\xb5\x3b\x35\x98\x84\x0b\xd6\x4e\x97\x52\xa4\xa6\x77\x6d\x35\x46\xd5\x90\x37\x4c\xa9\x44\x3a\x3e\xa9\x42\xa3\x5a\x09\xae\x46\x93\x54\xd3\x48\x8a\x4c\xd5\x4c\x71\xd2\x0f\x95\xc3\xb3\x60\x68\x92\x56\xc9\x34\x7d\x8e\x13\xce\x71\x3e\x91\xee\xfb\x92\x4f\xdc\x62\xb7\x9b\xd2\xe7\x61\xad\xa7\xa2\x79\x0b\x1b\xcb\x3e\xd3\x1b\x95\x9e\xa4\x75\x93\x61\xdd\x06\x95\xe8\x02\x82\x0a\x9e\x8e\xf4\x62\x54\x0c\x68\xb1\x6a\xf6\x51\xae\x86\x78\xd1\x17\xf9\x65\x24\x3c\x4c\xce\x3b\x62\xa9\xd5\x32\xb9\x4e\x63\x96\xda\x91\x8f\xb6\xcf\x60\xa2\x4d\x4e\x5c\xea\x6f\x89\x09\x2c\x3f\xc6\x9f\x1f\x2c\x81\x24\x33\x05\xb4\x2d\x6c\x13\x26\x6c\xc2\x5d\x08\x00\x63\xc8\xb4\x2d\x8c\xb9\x82\x4c\x08\x06\x39\x46\xb6\x42\x10\x3a\x8e\x63\x62\x80\xa0\x00\x52\x28\x01\x98\x7d\xed\x68\x20\xb8\x1c\x09\x24\xe2\xe4\x72\xb6\xf1\x58\x0a\x19\xa7\x00\x73\x44\x28\xb9\x9a\x63\xdf\xba\x16\xcb\xdb\x23\xd3\x4f\x66\x0b\x9a\x99\x33\x42\x5a\xb8\xe9\x4d\xb2\x39\x4c\x6a\x5e\x22\xbe\xc9\xe6\x53\x06\x76\xfc\x65\xaa\x11\x6d\xb0\xb0\x95\x4f\x7a\x8b\xec\x6a\x5d\x10\xa9\x20\xeb\x91\xf4\x28\x42\xc2\xb8\xb0\xca\x67\xa6\x86\xd6\xac\xe4\x86\x9b\x46\xc4\x0f\x0f\xdb\xa2\x39\xd7\xf6\x17\x44\xf7\x98\x38\x72\xd3\x92\x4a\x46\x26\xf3\x58\x5b\x2f\xa4\x2d\xd9\x73\xed\x74\x35\xb7\x8e\xb6\xd9\x40\x59\xa0\xe7\x2f\xa8\x53\x93\xf9\x9e\xd0\x34\x35\x42\x96\x06\xcb\x5d\x6e\x8c\x63\x30\x04\x8a\x2c\x98\x04\xf3\x5c\x2f\x57\xcd\x2f\x6b\xb5\x49\x39\xae\xbb\xb8\x21\xec\xea\x46\xfa\xdd\x68\x1a\xee\x72\x6c\xfb\x0c\x26\x8e\x23\xd4\xee\xef\xaf\x80\x89\xbb\xe7\x4e\x58\x7c\x8c\x3f\x3f\xb8\x58\x4a\x06\x15\x77\x14\xc5\x00\x60\x67\x9b\xb4\x0b\xc4\x39\x26\x18\x48\x68\x33\xa0\xa0\x32\x1d\xe5\x5a\x26\xc6\x08\x20\x4b\x01\x81\x31\xb1\x4d\xc5\xb8\xe0\x96\x72\xaf\xc5\x89\x8b\xdb\xd9\x0c\x60\x7a\x31\x4c\x3c\x16\x42\x86\x11\x10\x9c\x72\x44\xae\x65\xd8\x54\xde\x88\x88\x50\xbe\xd9\x50\xae\xaa\x2c\xc3\x72\xe0\xab\xa8\xb3\x29\x2e\x7b\x76\x23\x9f\x1c\xe3\xc5\xbc\x9b\x6b\x67\x82\xd1\x98\x9e\x9b\x0c\x54\x72\xb1\x58\x38\xf9\x5c\xdd\x6e\x16\x17\xc8\x8d\xe6\x8a\xc3\x6a\xae\xe2\x66\x22\x69\x5e\x2f\xc5\x6b\x56\x3b\x12\x5a\x6a\x38\x32\xe5\x6a\x22\xf8\x7c\xdf\x83\x3b\x44\x1c\xf5\xa8\x1e\x0a\x3a\xd1\x69\xbd\x54\xb5\xbd\x51\x3a\x5b\xa7\x6e\xa9\xda\x0f\x39\xb3\x98\x18\xc5\x55\xd0\x6b\x0e\xdd\xa1\xde\x44\x6d\xbe\xa8\x77\x43\x9a\xe5\x8d\xc0\x3a\xbb\xa8\x19\xa2\xc9\xe7\x23\xbb\xa0\x4f\xc6\xb1\xba\xca\x2e\xaa\xab\xa6\xb7\x89\x10\xd0\xf1\x50\x2f\xe5\x75\x86\xc3\xdd\xcc\xa9\x71\x06\x11\x76\xee\xc4\xa1\xfe\x0a\x88\xb8\x3f\x4a\xf0\x8f\xf1\xe6\x07\x57\x32\xea\x52\xc5\x99\x42\x8e\xcb\x25\x91\x9c\xaa\xed\xb8\x2c\x30\xb4\x24\xb5\x04\x53\xb6\x2d\x39\x84\x2e\xb7\xb8\x6b\x41\x42\x1c\x57\x5a\xb6\x69\x63\x5b\x98\xdc\x44\xe6\xb5\x28\x71\x31\x87\x66\x90\x52\x79\x71\x25\xf6\xa9\x14\x52\x21\x21\xe6\x42\x4a\x7a\x2d\xc3\xa6\xb7\xae\xc4\x86\xfa\x7d\xa9\x9c\x79\xd6\x55\x95\x3e\xa4\x6b\xa3\x91\xb3\xfa\x56\x67\xbe\x49\xdb\x86\xe4\x2e\x8f\x6b\x98\x2e\x32\x4b\xe1\x0d\xfd\x71\x57\xd5\xdd\x29\x35\xcc\x68\x68\x54\xb2\x72\x45\x50\xe9\xe9\xed\x7c\x72\xcc\x32\xf1\x51\x7c\x30\xa6\xa1\x55\xa1\xd3\x31\x43\xe3\xd4\xc4\xdb\xcf\xe4\xb7\x98\xb0\x8f\xc6\xea\x42\xde\xb0\xe6\x8b\xa4\xae\xc7\xdd\x69\xa9\x34\x70\x9c\xf1\xa0\x52\x10\xf1\x9e\xf0\x6a\x32\x6d\xc1\x75\x31\x1b\x9a\x6b\xeb\x46\xc2\x46\xf3\x54\xc3\x77\x2c\xbd\x98\x28\x27\xc2\xd3\x6c\x19\x2f\xab\xf1\xe9\x66\x5e\x8c\xac\xeb\xfa\xa8\x90\x41\xd3\xa2\x00\xed\x4c\x3b\xec\x33\x63\x77\x48\x36\x5a\x39\x83\x89\xa6\x76\xe2\x52\x7f\x05\x4c\xdc\x1f\x25\xd8\xc7\xf8\xf3\x83\x0b\x24\x60\x94\xba\xc0\xa1\xb6\x52\x54\x60\x84\xb8\x03\x80\x10\xb6\xc5\x4d\x17\x59\x5c\x00\x97\xb9\x8e\x84\x4a\x60\x66\x12\x08\xb9\x69\x59\x10\x3a\x84\x4b\x8b\xda\x0a\x5e\xc3\xc4\xc5\x5d\x6c\x86\x29\x15\x17\x67\x4e\xdb\xd2\xdd\xc4\x89\x12\x06\x85\x40\x88\xd1\x6b\x09\x36\xbd\x75\x21\x36\x14\x2d\x36\xab\x42\xaf\xe7\x69\x23\xe7\xb9\xc5\x68\x6a\x8d\x27\xeb\x19\x89\xa1\x50\x33\xe9\xeb\xe3\xa2\xa1\x26\x53\x03\x26\x07\x70\xd3\x99\x11\x60\x8f\x16\xcc\x8c\xea\x83\x66\xdd\xee\x77\x41\x62\x04\xdb\x22\x54\x2c\x5b\xc1\x89\x36\xdd\xf0\x3c\x2b\x1a\x6a\xa1\x8d\xf8\xe8\x08\x12\x47\xc9\x44\x6c\xc5\xe7\xb8\x3c\x13\x12\xc4\x62\xd1\x70\x03\x15\x2a\x3e\xee\x67\xbc\x0a\xce\xe1\xe1\xba\x6f\x4f\xc6\x83\x45\xae\x1f\xcf\x96\x82\xae\x36\x5c\xb9\x5a\xad\xdb\xb7\x62\x2a\xe5\x38\xb1\xba\x8a\x66\xca\x5c\x76\x7d\xe2\x2e\xd7\x55\xb0\x1e\x14\xc2\x1b\x16\x82\x61\x49\xe2\xbb\x4b\x76\xd1\xe2\x19\x48\xd4\xdb\x27\x1e\xf5\xf7\x84\x04\xfd\x18\x77\x7e\x50\x40\x02\x6a\x39\x0c\x32\xc9\x05\xa4\x8a\x3b\x8e\x00\x26\x73\xb9\xe9\x08\x25\x30\xe0\xdc\xa4\x18\x10\xd3\x02\x4c\x40\x81\xa8\xa2\xa6\x40\xc0\x72\x2d\xdb\x86\xc8\xb1\xae\x2e\xc4\x5e\x0e\x04\x84\xc2\xcb\xaf\x0b\x3e\x95\x42\x0a\xf0\x36\xff\xa1\x98\x5d\x4b\xb0\xe9\xad\x0b\xb1\xc1\x68\xb1\x26\x1b\xb5\x3e\x89\x2b\xd7\x69\x67\x2c\x3c\x69\xb0\x58\x04\x8f\xca\x91\xcc\x34\xd1\x6e\xa4\x55\xcd\x4f\x65\x83\x62\x59\x42\xb2\x3c\xa9\x55\x1c\x96\xe7\x39\x52\x02\xae\x12\x15\xcd\x76\x3a\x7d\x7b\xd0\xb0\xd7\x0e\x08\xfa\x56\xdb\x74\x8a\xdd\x46\x33\x1c\xaa\x64\x9e\x37\x27\xec\x23\x37\xad\xe0\x7e\xad\x20\xdd\x72\x29\x3d\x30\x86\x3a\x2f\x8c\xf4\x88\xd9\x34\x1b\x1b\x2f\xd1\x91\xf5\x1e\x4a\xa1\xfe\x3a\xdc\x6e\x54\x1c\x7d\xba\x5c\x15\xcb\xb3\x94\x9e\xa4\x15\xd5\x1e\x39\x79\x80\x7a\x4d\x7f\x93\x77\xa7\x2c\xd4\x6d\x18\xf1\xd1\x2a\x3a\x6a\xb4\xb5\xf2\x86\x95\x14\xdf\x4d\x9d\x72\x67\x30\x51\x15\x27\x2e\xf5\xf7\xc4\x04\xf9\x18\x7f\x7e\xa0\x88\x63\x07\x21\xe6\x62\xd3\x91\x84\x38\x16\x17\x8a\x13\xe0\x20\xe5\x42\x8e\x99\x20\x14\x4a\x6e\x02\x29\x5c\x61\x23\x64\x23\x13\x9a\x04\x22\x81\x85\x83\x5c\xc4\xf9\xb5\x37\x0c\xc0\xc5\x4d\x6c\x46\x99\xb8\xbc\x89\xfd\x54\x0a\x09\x03\x48\x08\x21\x00\xbb\x96\x60\xd3\x5b\x17\x62\x61\x7a\x03\x3c\x6b\x33\x69\x1a\xfa\x8c\x50\x10\x2b\xf1\x95\x8d\x3a\xf1\x44\xdd\x4f\x77\xc9\xd2\x5b\x8e\x13\x3d\xcd\xcf\xeb\xd9\xb5\xb3\x5c\xcf\xf4\x74\x7a\x9e\x21\x73\x63\x14\x19\xeb\x1a\x8b\x85\x43\xb3\x65\x74\x36\x5d\xe7\x96\xf5\x50\x44\xef\x96\x33\xa8\x0b\xc3\xc8\xce\x8e\x9e\xdf\xf5\xb0\x8f\xfa\x34\x64\x69\xc1\x82\x2a\x1a\x96\x9d\x5b\x94\x52\x6e\x71\x6d\xd6\x4b\xb5\xba\xd6\xde\x44\xb8\x69\x2d\x27\x4a\xaf\x16\x55\xa3\x91\xea\x2c\xbd\x26\x68\x8e\x57\xb6\xbd\x5e\x3b\xcb\x8c\xd7\x9e\x57\xd3\x8e\x95\x4a\x34\xb5\x44\x29\xd7\x94\xb2\x52\xcc\xd6\xa4\x91\x5a\x17\x7c\xdb\xf6\xca\x3b\x25\x52\x67\x30\x51\xf9\x2b\x1e\x76\xba\x1f\x13\xf8\x63\xfc\xf9\x01\x50\xc5\xb9\x6d\x49\x06\x18\xb0\x2d\x68\x51\x82\x39\xa1\xae\x10\xae\xc2\x4c\x61\x44\x98\x45\xa8\x85\x98\x29\x95\xa2\x92\xbb\x50\x12\xd7\x71\xb7\xf9\x89\x84\xd4\xb4\x2f\xdf\xd3\xa6\xdf\xe8\xe5\xc9\x11\xa3\x94\x5e\xdc\xce\x7b\x2a\x85\x04\x72\x8c\x25\x02\x9c\x5d\x4d\xb1\xf1\x8d\x98\x58\xd6\x87\x6e\xb6\xdf\x6e\xe4\xa6\x56\x35\xe6\xc4\x83\xa9\x50\xd7\xea\xa6\x13\xb3\xf8\x74\x30\x56\xb4\xe9\xae\xfa\x05\xcc\x72\xeb\x5e\x75\x92\x98\xab\x5c\x62\x99\xa9\xac\xf1\xc6\x89\xa6\x35\xcb\x1e\x66\x87\x2b\xbf\xa9\x55\x70\x95\x4a\xb3\x31\xe1\xc1\xb1\xe5\xe6\x3c\x10\x5b\x0e\x9f\x0f\xc5\x5a\x47\xe9\x44\xd2\x29\x88\x59\x24\x32\x1b\xa9\x75\x56\x48\x39\xcb\x16\x86\xba\x63\x8e\x2b\x7e\xd2\xa8\x0d\x92\x99\x6e\x46\x0c\x7c\x6b\x42\x20\x5a\x6a\x29\xa7\x5b\xb5\x93\x16\xae\xa6\x3b\xc5\xf0\x6c\x3e\xd4\x0b\xdd\xce\xa8\xd3\x2b\xb9\x9d\x60\xa7\x47\x7a\x76\x64\xd9\x23\x33\xb7\x20\x3d\xb6\xdb\xc4\xd6\xce\x60\xa2\x74\x7a\x21\xe8\xef\x89\x09\xf4\x31\xfe\xfc\xe0\x2a\x88\x31\x63\x36\xb1\x29\xb6\x01\x31\x19\x55\x36\xa1\x8a\x3a\x0e\xa7\x04\x38\x18\x23\x53\xd8\x58\x10\xca\x5c\x0e\x4d\xc2\x2c\x61\x6f\x81\x26\x5c\x06\x19\x24\x16\xbe\xb8\xe8\x44\xbf\x5d\xf1\x7a\xce\x11\xbf\x9c\x80\x3f\x96\x42\xcc\x09\x16\x92\x62\xc2\xaf\xa6\xd8\xb7\x6e\x4e\x84\x48\x59\x1f\xac\x72\x15\x11\xc9\x34\xd5\x2a\x4e\x1d\x08\x8b\x7a\x6e\x3d\xce\xe5\xb5\xea\xc2\x36\x8d\x49\x37\xd2\x67\x5d\x14\xef\x94\x36\x96\xb3\x5a\x59\x6e\x3c\x56\x0d\x4e\x3d\x16\x4e\x18\x8b\x2c\x9d\x06\xfd\xaa\x3d\x6d\x88\xe6\xb2\x17\xa7\xbd\xac\xd4\x22\xeb\x91\xc7\x7b\xcf\x1b\x76\xd6\xd1\xac\x1e\x6d\x62\x94\x3b\xc8\xaf\x2c\x51\x96\x0d\xe6\x93\xd9\x20\xe4\x2b\x14\xeb\xb2\xf8\x7c\x13\xa9\x0f\xab\x03\xde\xe7\x49\x3f\x36\xcd\x55\x36\xfa\xb8\x61\x35\x55\xb7\x36\x58\x2c\x0d\x42\xe2\xd5\x62\xc1\xca\xa5\x9c\x39\xb2\xba\x49\xd6\xab\xe3\x54\x9a\x47\x3b\x1e\x69\x0c\xda\xf3\xdd\xdc\x29\x7c\x06\x13\xc6\x5f\xf1\x00\xe0\xfd\xcb\x4e\xf0\x63\xfc\xf9\x81\x53\xe0\x2a\xc7\xdd\x3d\xca\x8c\x15\x05\x82\x20\xee\x70\x9b\xb9\xd0\xc4\xd0\x05\x18\xd9\xae\xeb\x08\x8b\x42\xac\x4c\x0b\xb9\xb6\x89\x6d\x22\x10\x27\xd8\x96\x48\x41\x76\xf9\x00\x20\xfd\x76\xf9\xa6\x29\x93\xdb\x08\xf0\x66\x29\xc4\x18\x12\x2c\x05\x83\xfc\x6a\x8e\x7d\xeb\xe6\x04\xae\x14\xb8\xeb\x45\x7a\x65\x5a\xec\x44\xdd\xfa\x6a\x91\xe8\x26\x97\xb9\x69\x48\x7a\x50\x0b\x8e\xd7\xa1\x4c\x41\x6b\x0f\x8b\xa2\x37\x8f\x4f\xed\xd4\xb8\x3a\xe8\xae\x17\xe3\x54\xdf\x8a\x3b\x83\x41\x74\x6a\x97\x93\xcb\x79\x1c\xae\xdc\x10\x44\x22\x33\xf0\x47\x91\x6c\xae\x58\xd3\xc7\xcf\x97\x8a\xac\xe3\xcb\x13\x89\x41\x13\x0d\x3a\x89\x5a\x21\x6a\xd7\xc2\x0e\x1c\x55\x64\x29\x92\xae\xbb\xaa\x3b\x8b\xf1\x78\x5e\xf3\xb3\x31\xe6\xc7\xa7\xe5\xfc\x82\xe4\x32\xb5\x94\xbe\xa8\x6c\x7a\x31\x4f\xd3\x87\x9b\x5c\x78\x0a\xfb\x8b\xa4\xd0\x3c\xad\x96\x36\x8d\xe5\x24\x6d\x2c\x74\xd0\x98\x1b\x8b\xcd\x96\x70\x44\x9c\xc1\x44\xfe\x7f\x0f\x3b\x6d\x31\x01\x3e\xc6\x9f\x1f\x24\x66\x36\x54\xd0\x05\x96\x0b\x4d\x57\x32\x2c\x80\xb2\x80\x54\x54\x2a\x8a\xa0\x43\x15\x76\x1c\x07\x73\xe0\x20\xe8\xba\xc4\x75\xa0\x09\xa4\x69\x41\x84\x4d\x62\xbb\x96\x79\x79\x29\x96\x7e\xbb\xbc\xff\xc0\x81\x20\xe2\x62\x3e\xf1\x54\x7a\xf8\xcd\x05\xb8\xcd\x28\xae\x60\x82\xdc\xba\x3d\x41\xf5\x69\xb2\x23\xb2\xc2\x0c\xd6\xf2\x61\xb6\x1c\xf6\x87\xfd\x94\x53\xef\x62\x47\x5f\x82\x4e\x08\x84\x0c\x3f\x3d\x5e\xa5\x58\xb9\x30\x1f\xf7\x36\xf9\xfa\x86\x0e\x5c\x94\x6d\x37\x86\xa6\x1f\x9e\xd5\x57\x7a\x33\xdb\x0b\x56\xdc\xb2\x68\x18\x12\x15\x2d\xd9\xe4\x8d\x82\x95\xc5\xfb\x9d\x81\x1d\x26\x8e\xfa\x14\x76\xeb\x59\xd3\xcf\x84\x52\xf9\x71\x46\xaf\xf6\x3c\x0b\xd9\x7a\x76\xd2\xed\x6b\xe5\x64\x7d\xd4\xec\xdb\x69\x12\x89\x37\xf2\xc2\xca\xe1\x81\xb1\x19\x8f\x6a\x6e\x7b\xb1\xe2\x43\x97\x0a\xee\xac\xba\xe9\x46\x55\x1f\xb4\x8d\xbe\xeb\xa6\xb5\x4d\x2d\x16\x69\x2f\x3b\x6e\x7a\xd0\xae\x6c\xe1\x17\x39\x77\x79\x22\xf7\xbf\x87\x9d\x4a\x81\x5f\x91\xfc\x18\x7f\x7e\xb0\x21\x21\x54\x52\x84\x5c\x45\x90\x42\x0e\x04\x16\x92\x26\xe6\xc0\xb2\x94\x65\x6e\xe1\x44\x4c\xa5\x08\x92\x48\x20\xc7\x52\x84\x08\x82\x04\xa6\x0e\xb4\x08\xc1\x8c\x5d\x3e\x14\x4b\xbf\xd1\x8b\x9b\xd8\x1c\x0a\x42\x2e\x2e\xd4\x3e\x95\x42\x44\x28\x25\x80\x42\x2a\xae\xe5\xd8\xe4\xd6\xcb\x13\x22\xae\xd5\xaa\xa9\x05\x8d\x92\x99\x96\xcd\x98\xfa\x72\x1e\x9c\xf7\xb5\x60\x69\x4e\xa3\x3d\x3f\x6b\x51\xad\x13\x6d\x43\x60\x19\xb1\x66\x37\x97\x8c\x4d\x07\x69\xbf\x3c\x5a\xbb\xb9\x09\x18\xf2\xa6\xd1\x85\x85\x59\xb5\x61\x7b\xcb\x12\x8d\x23\x1a\x52\x56\x95\x66\x06\x85\xe4\xfa\x39\xc7\x36\x8f\xf2\x09\xcb\x8c\xc6\x88\x61\xb9\xda\xb8\x34\x49\x05\xc7\xa3\xd4\x7a\xb3\xa9\x54\x82\x56\xa3\x91\x4b\x4f\x8d\x25\x1e\x25\xed\x41\x72\x59\x9c\x2c\xcc\xb0\x97\xac\x6c\xb4\x92\xc5\x07\xab\x5a\xdb\x62\x93\x98\xf4\x82\xd6\xa2\x61\x3a\xdd\xce\x2a\x67\x24\x42\x6a\xe5\xc7\x6a\x23\x11\xf2\x2b\xbb\x67\x11\x22\xe7\x2e\x4f\x64\x4f\x5d\xea\xef\x89\x09\xf1\x31\xfe\xfc\x20\x01\xb2\x80\x4b\x15\x54\x8a\x02\x66\x49\x57\x3a\x4c\x08\x45\x18\x61\x1c\x5b\x8e\x89\x5c\xd3\x04\x94\x09\xce\x6c\xc7\x55\xc0\xb4\x11\x05\xca\xa5\xb6\x74\x5c\x60\x0a\x73\x1b\x0a\xf8\xee\x7f\x67\x30\x71\x71\x13\x9b\x23\x79\xe5\xed\xcc\xa7\x52\x88\x00\xa2\x72\x1b\xfe\xc4\xb5\x1c\x9b\xdc\xba\x65\x47\xc3\x93\x18\x24\x8a\x16\x4d\x1a\x74\xcc\x14\x4d\x18\xc3\xbc\xf4\x17\xe3\x76\xd5\x77\xa6\x38\x18\x9d\xa6\x8b\x1c\xae\x1d\x91\xf1\x06\x43\x3d\xb6\xcc\x36\x92\x8a\xb7\x53\xc9\x46\x6e\xbd\x6a\x78\xb5\x42\x96\x85\x9d\x51\x7e\x90\x4f\x44\x8d\x94\x3e\x28\xd8\xda\x62\x10\x19\xd2\xe7\xf7\xc7\xcd\xe3\xf7\x9e\x8a\xa1\x32\x59\xa7\xf5\xcc\x50\x76\xbc\xb4\x5f\x9e\xaf\x62\x53\xdd\x72\xa4\x67\x19\x35\x17\x75\xf4\x64\xba\x33\xf5\xc6\x91\x4c\x2d\x06\xad\x59\x7f\xea\xd5\xc2\xfa\x6a\xac\x35\x71\x25\x92\x41\xa9\xe9\xbc\x11\xcf\x11\x93\x89\x49\xde\x28\x2e\xe7\x8e\x6a\x4e\x23\x19\x38\xaf\x6e\x61\x10\x39\x77\x79\x22\x6d\x9f\xb8\xd4\x5f\x01\x13\xfc\x6e\x4c\xf0\x8f\xf1\xe7\x07\x89\xa8\x22\xc2\x55\xc2\xc6\x50\x2a\x84\x2d\x41\x01\x24\x8e\xe3\x32\x85\x99\x14\x8e\x65\x2a\x0b\x52\xcb\x11\x44\x01\x45\x08\xa6\x0c\x12\x17\x43\x44\x1d\x41\xb8\x32\xdd\x6b\x71\xe2\x62\xc6\xc0\x29\xc3\x97\x2f\xd9\xed\x4a\x77\xeb\x4e\x90\x4a\x46\x20\x64\x52\x5e\xcb\xb1\xc9\xad\xf9\x04\x4d\xab\x52\x81\xe5\x72\x4d\xd2\x9d\xc7\xc3\x15\xec\x5a\x5d\xb3\x81\x18\x5b\xd5\x64\x27\x1f\xeb\x15\x61\xa3\x22\x56\x69\xa7\x93\x64\x8b\xe2\xda\x49\xa7\xea\x5a\x78\x0a\xe7\xf9\x18\x4b\xf5\x2a\xb9\xa9\x48\xf4\x87\xeb\x42\xac\xbc\x32\xc6\xbe\x91\xa9\x91\xd0\xb2\xdd\x6c\x9a\xfa\x73\x3e\x61\x1e\xb9\x69\x6f\xa4\xea\x8e\x5e\x77\x07\x1d\xa8\x0d\x2b\xdd\x68\x23\x95\x53\x96\xb3\xa9\x8a\x42\xbf\x1d\x55\x2c\xcd\x54\x7a\x2c\x72\x16\x29\xd5\x1b\xe5\x5c\x45\x1a\x74\x64\xc5\x8b\x91\xd0\xa8\xa3\x8d\x56\x5e\xc2\xb3\xcb\xbd\x7e\x44\xab\x57\x4a\xc5\x9a\xa8\x4f\x66\x55\x90\x94\x11\x3d\xb8\x25\x1c\x39\x73\x79\x22\x1c\xfc\xdf\x3d\xbb\x2d\x26\xd8\xc7\xf8\xf3\x83\x4b\x89\x0d\x80\xe4\x0e\x21\xd0\x75\x39\xb3\x89\xe0\x0e\x51\x96\x05\x85\x4b\x15\x75\x29\xb2\xa9\x49\xa1\x6d\x4a\x26\x00\xb0\x5c\x69\x09\x28\x90\xa4\x5c\x02\x13\x73\x2e\xae\xad\x3b\x5d\x9e\x1d\x31\x2e\xc8\xe5\x99\xd5\x63\x29\x84\x90\x31\x09\x89\x64\xf2\x5a\x8e\x8d\x6f\x3e\xee\x54\xcd\x85\xd3\x6e\xa5\xe8\x4a\xb4\x4a\xb9\x15\xc6\x13\x85\x7a\x5f\x96\x56\x66\xc5\x1e\xd7\xda\xe1\x05\x9d\x47\xda\xa3\x2a\x8d\x76\x1d\x92\xb7\x22\x63\x5b\x4d\xc5\xa6\xde\x0c\x77\xdd\x6c\xc2\x34\x82\x39\x07\xb4\x93\xcb\x42\x95\x64\x83\xfa\xdc\x29\xb4\x4b\xc5\xb4\x33\xd5\xe8\xf3\xba\x93\x79\xd4\xa7\x89\x72\xc6\xee\x3a\x74\x36\xb5\xfb\x71\x5c\x08\x8e\x66\x31\x2f\xe7\x54\x6a\x23\x81\x67\xf3\x46\x3c\xb8\xe9\x87\x63\xa3\x60\x3d\xd8\x9e\x05\x55\xa4\x0f\x07\xcd\x76\x11\xf5\x22\xed\x7c\x3f\x16\xc5\xeb\x1c\xe9\xc1\x7a\xbc\xd4\x6b\x8b\xe1\x4c\x55\xd3\xb9\x51\x28\xd3\x19\xe7\xd7\x35\xb4\x9b\x3b\x9d\xb9\x3c\x11\x16\x7f\xc5\x3d\xbb\xbb\xd7\x9d\x10\xfd\x18\x7f\x7e\x70\x38\xb4\x20\x42\x96\x6b\x41\xa0\x20\x94\x98\x4a\x6e\xda\x2e\xe1\x4c\xba\x52\x5a\x1c\x32\xc5\xa5\xe2\x0e\x54\xa6\x6d\xbb\x08\x51\xd3\x71\xa9\xeb\x30\x6a\x5b\x4a\x29\xcc\xaf\xc5\x89\xcb\xb3\x23\x2e\xf9\xe5\xe3\x81\x4f\xa5\x10\x70\xcc\x09\x14\x88\x80\x6b\x39\x36\xbe\x75\xee\x24\x6d\x4b\xf3\x16\x5c\xcb\x6b\x4d\xbd\xa9\xa6\x32\x69\xba\x03\xcb\xae\x51\x4a\x65\x72\xbc\x29\xa4\xfa\x13\xb7\x2e\x9b\xf6\x62\x4e\x70\x94\x3a\xdd\xc6\x52\x45\x7b\xee\xdc\x52\x0d\x6f\x3d\x09\x2f\x56\xfd\xc2\x60\x5e\x49\xb6\x57\x56\x2f\x38\xea\xd5\x09\x05\x7d\xcb\xab\x44\x9e\xf3\x89\xe6\x51\x3e\x91\x93\xed\x6c\x35\xb6\xe8\x2e\x73\xf3\x6a\x33\x38\xec\x1a\xdd\xc5\x22\xb7\xea\x77\x7c\xc7\x68\x87\xaa\xe9\xd1\xdc\x1c\x79\x51\x0b\xac\x65\x29\x36\xad\xa5\x34\xd0\x6c\xd6\xa3\x69\x8e\x72\x53\x33\xc4\x2a\x93\x8a\x53\x8e\xf5\x82\x83\xb1\x9e\x1b\xa3\x8c\x6a\x56\x33\x91\xae\x33\xdb\xef\x7f\x44\xce\x5c\x9e\x08\xd3\xd3\xfd\x89\xdd\xf1\xa7\xff\x72\x4c\xdc\x1f\x27\xc8\xc7\xf8\xf3\x83\x03\xa4\x8d\x38\xa5\xca\xc4\x10\x02\xc9\x19\x77\x98\xb9\xfd\x1f\x87\x94\xda\xae\x0b\x2d\x86\x81\x72\x2c\x86\x99\x30\x89\x85\x04\xf8\xff\xec\xbd\x69\x8f\xe2\xc8\xb2\x37\xfe\xfe\x7e\x8a\xd6\xbc\xe9\x47\x62\xce\x21\xf7\x65\x1e\xdd\x17\xc6\x18\x6c\x83\xc1\x80\x59\xcc\xa3\xab\x91\x57\xf6\x7d\xe7\xe8\xff\xdd\xff\x82\x5a\x58\xaa\xa8\xee\x32\x55\x35\x3d\xe7\x5c\xd4\x6a\x55\x96\x8b\x9f\x23\x23\x23\x23\x32\x32\x23\x22\x7d\x9f\x89\x30\x42\x24\x40\x91\xef\x93\xb7\xe6\xc4\xcd\x73\x6c\x2e\x21\xc4\x37\x4f\xf4\x9e\x9f\x42\x80\x01\x97\x08\x52\x08\xde\xf2\xb1\xf1\xcf\xc6\x3b\x49\x35\x30\x61\x6b\x66\x55\xd5\x56\x5b\x7a\x4b\x6f\x19\x34\x5a\xb6\xf0\xdd\x0d\xf7\x5d\xd4\x1b\x2c\x26\x2a\xf7\x4a\x64\xb0\x59\xad\x00\xee\x5a\x2c\x60\xb5\xdd\x46\xa9\xd6\xc6\xb6\x8f\x83\x65\x8e\xc5\x93\x46\xe8\x77\x76\xdb\xee\x34\x5d\x25\xe9\x45\xaa\xa9\xa5\x96\xd1\x43\x69\xa5\x87\x39\x71\xb6\x82\x81\xfb\x9e\xee\xf5\x57\x7e\x76\xde\x87\xc6\x8a\x6a\x15\xe1\xb6\x33\x88\xa8\xfb\x11\x92\x8a\x69\x87\x9e\x39\x5e\xb4\x70\x4a\x49\xc5\x0d\x5c\x88\xc3\xa8\x37\x33\x67\xbb\x5d\x37\x1e\xa4\xf8\x68\xd3\xac\x67\xc0\xdc\xf7\xd7\x4b\xb6\x63\x04\x74\x8b\x69\x7f\x3c\xb1\xad\xb6\xec\x1c\x13\x25\x5e\x99\x13\xe4\xfa\x7c\xe2\x3f\x73\x4e\xe0\x8f\x91\xe7\xef\xbe\x08\x05\xf4\x24\x09\x02\xe9\x05\x30\x0c\xc2\x63\x20\x21\xf5\xbd\x08\x30\x01\x3c\x4e\x58\x4c\xa0\xe7\x4b\x84\xc3\x48\xfa\x4c\x30\x0a\x08\x42\x00\xcb\x58\x84\x31\xe1\x6f\xed\xc5\xde\x4e\x8f\x10\x90\xa2\xdb\x7b\xb1\xc7\xa7\x87\x75\x97\x14\x5c\x10\x44\xb8\x00\x6f\xb9\xd8\xf8\x67\xc3\x9d\x78\xdf\xcd\x4f\x1d\x6b\xb4\xd0\x03\x68\x86\x51\x93\x91\x7c\xa7\x10\xe6\x65\x66\x46\x0d\xc9\x7c\x2f\x5f\xd7\x8c\x4e\x39\xee\xc7\x55\x56\xb6\x3b\x54\x99\xf4\x72\xf5\xce\x12\xe7\xf3\xa0\x59\x36\xe7\x44\xc5\xa6\x57\xd1\x47\xdc\xb2\x33\x95\xde\x22\x54\x49\x77\xb0\xdf\xd6\x4e\x4b\xa7\xf6\x99\x60\x46\x2b\xd6\x2e\xee\x53\xa9\xa8\xbc\x6b\xe2\xb4\x6e\xbb\x0c\xb2\x75\x6a\x92\x43\x2d\x4e\x59\x53\x75\x44\x5e\x62\x65\x1a\xea\xbd\x78\xb2\xa8\x97\xa7\xaa\x9f\x5a\x94\xfd\x60\xba\xd8\xdb\x4b\x5b\xa6\xf4\x1d\xb0\xf4\xd1\x7e\xdb\x9d\xee\x15\x3b\xbd\x70\x14\x27\xa8\x4c\xc7\x85\xe3\x94\x78\x25\x77\x42\x41\xd7\xf5\x09\xb2\xca\x7f\xe2\x94\x40\x1f\x23\xce\xdf\x61\xc4\x31\x62\xcc\x97\x01\x0c\x59\x14\x0a\x1a\x85\x08\x20\x0e\x8e\x75\xfb\x09\x10\x90\x10\x1a\xd2\x18\x01\x08\x85\xf4\x23\xdf\xa7\x1c\xc1\x40\xfa\x88\x32\x1a\x3f\xa6\xfd\xdc\x9a\x12\x37\x8f\xb1\x05\xe2\xe4\x76\xb8\xd3\xf3\x53\x49\x88\x90\x48\x00\x0a\xdf\xf2\xb0\xf1\xcf\x46\x3b\x6d\xe9\xde\x1c\xad\x02\xbd\xc9\xdd\xd6\xd2\x50\x83\xa2\x6e\x6e\x95\x4e\xbd\x1a\xb6\x76\x4a\xb5\xe7\x33\xde\xd8\xe9\xe6\x62\xd8\x8e\x43\x93\x64\xf7\xfb\x75\x23\xb6\xfb\x11\x5d\xab\x2c\xe8\x74\xd5\x5c\x3c\x6f\x6f\x2c\xdd\xd2\xb2\x56\x0e\x4e\xbb\x9b\x69\x7a\x60\xf4\x57\x69\x7e\x36\x25\xce\x86\x14\x28\x56\x6f\xe7\x10\x75\x97\x2d\x16\xd7\xde\xae\x06\x94\x91\x2d\x79\x37\x1a\xcb\x3e\x9c\x0f\x8c\xc5\xc4\x8d\x4a\xa0\x57\x99\xf7\x57\x53\xe0\xd9\xb9\x70\xd5\x30\x16\x66\x6a\x1c\xef\xa5\x51\x52\xcd\xda\x9c\x8a\x52\xd9\xde\xda\xa5\x8a\x53\x68\xcf\x1c\xc7\xdd\xd7\x68\xaa\x7c\x5c\x39\xbd\x92\x3c\xa1\xc0\xeb\x13\x3b\x55\xf9\x4f\x9c\x12\xf0\x63\xc4\xf9\x7b\x04\x02\x29\x3c\xc0\x22\x1c\x06\x84\x43\x81\x3d\x22\x00\x8e\x25\xe1\x41\x08\x80\x17\x47\x98\x87\xc2\x97\x24\x0c\x30\x09\x23\x82\xa4\x17\x86\x04\xc4\x1e\x0f\xa0\x0c\x18\x7c\xcb\xc3\xbe\xbd\xaf\x24\xb0\x80\x6f\x4c\x98\xa7\xa7\x12\x40\x49\x30\xc4\xe8\xcd\x6a\x67\xf8\x67\x83\x9d\x52\x59\xb3\xd7\xf1\xfb\x58\x0b\xdc\xf2\xa0\x93\x4d\xd5\xe3\x92\x52\x48\xf7\x63\x77\x55\xc7\x59\x27\xaa\x4c\xe7\x61\xc5\x9e\x8a\x7c\xe0\xba\xb9\x09\x4f\xe5\x87\xde\x02\xf5\x7b\xd3\x49\x7e\xe8\xc9\xf5\xbc\x58\x2c\x80\xc9\x44\xe9\x59\x06\xcd\x57\xa2\xf2\xa0\xd8\x48\xaf\xfa\x32\x38\x39\x13\xee\x79\x26\x76\x51\x19\x97\xfa\xb5\xcd\xa8\x38\x21\x9c\x4c\xfa\x13\xbd\xb3\x5b\xc4\x83\xd6\x28\x8a\x32\x46\x2b\xec\x34\xfd\x5d\xd9\xdc\xf8\xe3\xc5\x36\x55\xa9\x87\x5e\xc1\x8e\x95\x96\xdb\xdd\xad\x07\xfb\x42\xa5\xa0\xa5\x1c\xd7\xef\xe2\xd0\xea\x8b\xa0\x05\x3a\xcb\x18\xa4\xca\x13\x67\x79\xbc\x20\x35\xf3\x4a\xee\x84\xb2\xbf\x3e\xb0\xfb\x77\x98\x12\xef\x77\xb0\xc1\xc7\x88\xf3\xf7\x20\x82\x41\xc8\x3d\xcf\x07\x11\x42\x1e\x8c\x04\x0c\x84\xf4\x43\xc8\x61\x08\xfc\xd0\xa3\xa1\x08\xa3\x00\x09\x81\x08\x24\x18\x20\x1a\xb3\x18\x84\x90\x7a\x30\xe4\x5e\x10\xc0\xdb\xd5\xce\xe8\x1f\xb7\xeb\xd4\x88\xe3\x62\xe8\x87\x4f\x05\x15\x52\x62\x42\xe5\x9b\xc5\xce\x30\xfc\xd9\xf3\x3a\x12\x40\x36\xdb\x90\xde\x24\xea\x04\x3d\x1f\xb4\xf4\xca\xda\x6b\xb9\x78\x51\x30\xcc\x4c\x65\x63\xc6\xfe\x06\x34\x26\x61\xb4\xd8\xb8\xa9\x78\xb2\x59\x14\x83\xc2\x9e\x9b\x30\xd4\x30\xed\x14\xc6\x6e\xd5\xf2\xd0\x5e\xc1\xc1\x2c\x5e\x4d\x4a\x75\x0b\xc6\x51\xaf\x6d\xaf\x4e\x56\xc2\x3d\xf3\x25\xb6\xe9\xee\xd6\xd3\x9a\xa8\x55\x32\x33\xb8\x97\x8d\x11\x8e\xdc\x38\x1f\x6c\x82\x8a\x60\x68\x5a\x5b\xf2\xb2\xc9\x72\x39\x08\x84\xe1\xa5\xd5\xee\xae\x17\xce\xe2\x45\x94\xf6\x30\xcf\xf5\xe2\xa2\x32\xcc\x16\x52\xda\xaa\x82\xb7\xf9\x9d\x37\x53\x6b\xd4\x2a\x0e\x9a\x95\xfa\x31\x43\x22\xf3\x4a\xee\x84\xb2\xb9\x3e\x9b\xf8\x77\x98\x12\xef\xb6\x12\x50\x7e\x8c\x38\x7f\x8f\x58\x4c\x49\xe4\xd1\x30\x88\x3d\x89\x58\x4c\x23\xc2\xc2\x10\x50\xc6\x24\x88\x7d\x80\x61\x18\x60\x89\x38\xe4\x61\x00\x62\xdf\x0b\x80\x8f\x62\x02\x61\x24\x88\x64\x14\xc1\xdb\x71\xe2\xf4\x8f\xdb\x3b\xad\x82\xbd\x11\x12\xfb\xf4\x50\x40\x06\x08\xe6\x82\xbd\x59\xe9\x0c\xff\xec\xc1\x44\xca\x87\xce\xac\x15\xa4\xa6\xe6\xba\x35\xf0\xc3\x4c\xd3\xab\xa4\x36\x56\xb8\xa1\xe6\x36\x0e\xb2\x7c\xae\x2c\xd6\x95\x2a\xd3\x86\x43\xa3\xe2\xb9\xb2\x66\x2c\xb6\x29\x34\xda\x0f\xfd\x41\x2a\x96\x35\x6d\xb2\x8e\xc6\xd3\xe2\x24\x5d\x34\x77\x75\xbb\xcb\x94\x54\x27\xd5\xc8\x89\xe9\x29\x71\xc2\x3d\x93\x51\x77\xaf\x32\x12\x8f\x9a\xfd\x76\x79\x39\xd3\x88\xd9\x5f\x14\x66\x9b\x68\x1e\x8e\xf7\x25\xb6\xdb\x8c\xcd\xda\x3a\x5c\x64\x9b\x39\x3b\x58\xe1\xa9\x99\x5b\x5a\x23\x7d\x34\x5d\xa0\x40\xd9\x4e\x2a\x83\xf4\x6c\x1f\x8b\xca\xa4\x54\xce\xf4\x32\x46\x5e\xd1\x98\x88\x74\xb9\xad\xee\x8e\x07\x1f\x99\x57\x12\x27\x94\xd5\x75\x65\x82\xff\xcc\x09\x21\x3e\x46\x98\xbf\x0b\x2f\x8e\x01\x40\x8c\xc6\xbe\x14\x04\x22\x09\x50\x18\xcb\x90\x06\x18\x44\x50\x12\x0f\x40\x2f\xf4\x43\x2e\x11\x91\x20\x8a\xa9\x10\x98\x11\x2e\x42\x5f\x86\x22\xc2\x90\xde\x2e\xb6\x4f\xff\x20\x37\xb7\x59\x85\xc0\xf2\x76\xdd\x82\xe3\xd3\xe3\xc9\x38\xc7\x40\x12\x08\xf1\x9b\x85\xce\xd0\xcf\x9e\x4b\x90\x79\x5a\x51\xdb\xf1\xca\xad\xd4\x06\x2a\xa6\x30\xb0\xca\xf9\xfa\x24\x33\xf7\x21\x35\xcd\xec\xba\x69\x94\x06\x51\x69\x15\xf6\xfb\xb9\xe6\x94\xeb\xbd\xd4\x20\x9b\xd1\x8a\x41\xdd\x1d\x96\xd3\x8d\xc8\x9c\xae\x8b\x6c\x4d\x27\x46\xa5\xd3\x8f\x33\xba\x5c\xa2\xc6\xc2\xad\x83\xf5\xe9\x1e\xaf\xf3\xe4\x85\x52\x61\xbb\x53\xac\xc9\xce\x4a\x77\xc6\x54\x76\x33\xee\xbe\xb8\xf5\xeb\x48\x34\xfd\xde\x16\x57\xf4\x1d\x5f\x00\xc1\xd6\xd3\x9a\x4b\xc2\x45\xbc\xe8\x42\xb0\x9b\x46\x73\x7f\x64\xc4\x85\xba\xb7\x99\x4c\x6c\xb7\x34\x2b\xa5\x2b\x19\xd4\x2f\x90\xd9\x0a\x2d\x95\x56\x6a\x69\x1c\x63\x46\x32\xaf\xe4\x4d\x28\xcb\xfa\x95\x44\xfd\x3b\x4c\x89\x77\xd7\xd9\x87\xfc\x63\xc4\xf9\x3b\x8b\x89\xcf\x03\x49\xb9\x47\x90\x87\x51\x18\x0a\x0c\x42\x82\x11\x44\x21\xf5\x7d\x2f\x8e\x7c\x89\x10\xa4\x58\x44\x04\x40\xe0\x11\x84\x09\xa5\x18\x83\x30\xf4\x81\xf4\x91\xff\x96\x27\x71\xf3\xfc\x5a\x48\x2e\x6f\x97\x55\x7e\x7e\xca\x31\x80\x84\x10\x02\xde\xac\x73\x86\x7e\x76\x0b\x16\xc9\x62\x6c\x36\x58\x65\x66\x2d\x51\x36\x5b\xb7\xba\xc5\xc6\x8a\xa5\xe7\x83\x5e\xce\xe9\x0f\x94\xca\x54\x2d\xe5\xea\xfb\x6c\xb8\x30\x17\xf3\x5d\x50\xc6\x66\x5a\x9f\xa2\x40\x5b\xcf\x09\xc6\x79\x3b\x9a\xe1\xd6\xd2\xd4\xed\x86\x48\xed\x5b\xe1\xb6\x58\xad\xd6\xb7\x90\x55\xba\x0f\x09\xd0\x87\x29\xd1\x3a\xf3\x24\x66\x7a\xb3\x9c\xab\x86\xcd\xec\x26\x2a\x90\xb6\xa1\x65\x5c\xc7\x2d\x0f\xf6\x9b\x1e\x9a\x89\x9e\x31\xc9\xc8\x6d\x6e\xaf\x94\x67\x76\x2d\x1d\xc7\x7d\xbb\xe8\x69\xd5\x7c\xb6\x38\x77\x55\xbe\x6c\xbb\x8d\x2a\x1f\x3b\x8e\x53\xe7\xce\x18\x90\x52\x80\x9d\xf2\x02\xe2\xce\x42\x85\xc7\x29\xf1\x4a\xda\x84\x32\x99\xbc\x26\x56\x7f\xf3\x29\xf1\x6e\x4f\xe2\x20\x20\x1f\x21\xce\xdf\x85\x87\x24\xc2\x48\x4a\x14\x32\xe9\xfb\x0c\xc6\x84\xf2\x80\x33\xe1\x71\x42\x7d\x16\xfb\x28\x14\x30\xf4\x42\x5f\x84\x8c\x0b\x10\x13\xc9\x80\x2f\xa3\x08\x0b\x14\x48\x2f\xa4\x6f\x59\x89\x9b\x42\x2f\x21\xa0\xe4\xe6\x7e\xd3\xf3\x53\x26\x38\x94\x84\x33\xfe\x66\x99\x33\xf4\xb3\xfb\x4d\x64\x32\x35\x76\xa3\x1a\x9c\xae\x90\x0e\x1a\x22\x9c\x4c\x41\x13\xa5\x76\x28\x83\x96\xab\x52\x9b\x64\xc1\xb0\xb3\x8a\x08\x29\x9a\xf3\x86\x0b\x3b\x4a\xbd\x99\xc9\x6f\x2a\x15\xdb\x9a\xb9\xcc\xb6\x45\x2e\xb7\x9b\x4e\x07\xfa\x64\x51\xa8\x12\x27\x0b\x37\x0b\x37\x4c\xa7\x8d\xd4\xa9\x6c\xf2\x79\x2e\xb4\x5b\x98\xac\x78\x66\x60\x2f\x2b\xcb\x51\x96\x94\x29\x49\x3b\xce\xa4\xde\xc9\x28\x8d\xba\x3a\x52\x87\xe9\x72\x4a\x3a\x9d\x19\xea\x96\xf4\xfd\xb0\xe0\xca\x4a\x87\xaa\x8a\xb1\x0d\xab\x2d\x7f\x91\x6e\x05\x8d\xb1\xe6\x63\xd3\x35\xe3\x74\x76\x20\x0b\xa0\x64\x4d\x9a\xb4\x2c\x9c\xe3\x94\x78\x25\x6b\x42\x19\x5e\x47\x74\x1c\x3f\x7f\xf3\x29\xf1\x7e\x2b\x41\x3f\x46\x9c\xbf\x7b\x8c\x78\x31\x0c\x80\x88\x7d\x1a\x22\xe1\xf9\x41\x08\xe3\x40\x86\x5e\x24\x82\xc0\x87\x7e\x1c\x48\xdf\x8f\x02\xe8\x73\x9f\x70\x1e\x41\x12\x07\x1e\x0a\x7c\x2f\x0c\x3c\x22\x01\x7f\x2b\x6b\xe2\x0d\xa1\x47\x80\xbd\x31\x61\x9e\x9e\x32\x42\x10\xa1\x40\x92\x37\xab\x9c\xa1\x9f\x75\xae\x59\xbb\x20\x02\xd5\x5e\x86\x85\xc2\xba\xa4\x8b\xb1\xc7\xac\xdd\x76\x2d\x46\x9c\x67\x96\xbc\x8a\x49\x3d\x5d\x28\x16\xe7\xc1\xd4\xcc\x88\x10\x75\x42\x4f\x7a\xad\x7e\x75\x0b\x46\x5e\x6a\x95\xa7\xc6\x38\x6b\x6b\x5a\xd3\xc7\x3c\xee\xb7\x77\xa5\xca\xce\xde\xd8\xbd\x8a\xb6\x3e\xb3\x12\xe7\x49\xd8\x8b\x7e\x7d\xd8\x34\xf7\xad\x7d\x2b\x9b\xd7\x56\xbc\xdd\x12\x25\x8b\xe4\x71\xb7\x65\x99\x1d\x67\x36\x82\x13\x32\x5b\x6b\x56\xec\xb3\xbc\xae\x56\x07\x8d\xde\x38\x13\x4c\xa3\xce\x86\xfa\xdd\xb5\x6b\x4d\x37\x26\xf2\xc3\x83\x46\xc3\x43\xe8\xd7\x32\x76\xa3\x9e\xed\x6f\xe6\x47\xc1\x7f\x25\x69\x42\xe9\xbc\x7a\xdb\xd6\xdf\x7c\x4a\xbc\xdf\x97\x20\x1f\x23\xce\xdf\x41\x00\x89\x47\x18\x8d\x19\x00\x00\x62\x80\x3d\xca\x58\x1c\x05\x90\xc6\x28\xf0\x83\xd0\x43\xdc\xf3\x03\x4c\x22\x19\x08\x9f\x42\x5f\x08\x49\x89\x87\x62\xe9\x63\x10\x33\xff\xf6\x8d\x13\xf4\x0f\x72\xf3\xf0\x5a\x62\x0c\xe5\xcd\xdd\xa8\xe7\xa7\x0c\x40\x24\x29\x41\xf0\xcd\x22\x67\xe8\x67\xdd\xeb\xcd\xa6\x3e\xcd\xb7\x90\xa2\x68\x9b\xf2\xb0\xbd\xe6\x99\xd6\x6e\x27\x50\x2f\x9a\x6f\x00\x0b\x7a\x30\x4f\x7a\x8d\x5a\x2f\xe5\x5b\xb6\xb7\x5d\xd3\x60\xe9\x86\x81\x55\xd3\x46\x02\x2f\x6a\xeb\xc9\x60\x8a\x91\x0a\x6b\x69\xc5\xe8\xf8\x7e\xb0\x6c\x37\xbd\xe6\xba\xbe\x2d\x21\xe5\x94\x33\xd1\x3a\x1b\xd2\xa1\x88\x2c\x7f\x5d\x34\x97\xe5\xcc\xc4\x51\xd7\x93\xf9\x50\x2b\x6c\xcb\xac\x33\x1d\x2f\xd4\x68\xd1\x1f\xa7\xa0\x0a\xd3\x7a\x1e\xac\xe1\x3c\x44\x7c\x52\xe6\xa9\x46\xb3\xa6\xe5\xc5\x5c\xc4\x41\x39\xe7\x16\xc4\x00\xb7\xc3\xe9\xb0\xee\xef\x8d\x30\x36\xb6\x83\x92\x97\xf1\x0a\xc7\x59\xf0\x4a\xce\x84\x12\x5f\x9f\x5d\x1f\x3f\x7f\xf3\x29\xf1\xfe\x85\x13\xfe\x18\x71\xfe\x0e\xb0\x0c\x25\x06\x38\x40\x20\x90\x1e\x15\x40\xa0\x18\xd2\x98\x08\x4e\x23\x41\x8e\x65\x67\x23\x12\x06\x08\x44\x1e\xc2\x5c\x30\x16\x50\x19\x52\xc9\x83\x00\x13\xe9\xc1\xf0\x8d\x29\x71\x3b\x62\x43\x12\x21\x6f\x7a\xd7\x4f\x0f\x29\x15\x98\x50\x4e\xc4\x9b\x35\xce\xe0\xcf\x26\x4c\x6c\xca\xe1\x60\x63\xab\x59\x73\xea\xaa\xaa\x68\x48\x23\x8c\xba\x96\xbe\xd9\x0f\xb0\x9a\x9d\x19\xb8\x3b\xda\xb6\x61\x3b\xb6\x4a\xe6\x24\xcc\xc5\xeb\x70\xbf\xdc\xce\x5d\xdd\x96\xdb\x7d\x38\xf3\xd3\x72\x1a\x14\x26\x5d\xa3\xd5\x73\xc6\xcb\xe6\x3e\x55\xdb\xda\x68\xb2\xa3\x19\x7c\xaa\xac\xdf\x3c\xf3\x24\x72\x83\x66\xbd\xb4\xcb\xa5\x36\x8c\x57\xe9\x38\xa5\x77\xb2\xa5\xc8\x1f\xd2\xc5\xb8\x81\xdc\x61\x66\xb1\xc7\xdb\xa2\x33\xcb\x58\x95\x45\x45\x5b\xa6\xf2\x4d\x4b\xd6\x97\x5a\x38\x1f\xb8\xa3\x91\x41\x1b\xba\x3b\x59\x39\x78\x6f\x0f\xdd\x69\x51\x2d\xef\x86\xb3\xfe\x0c\x05\xbd\xea\x31\x98\x43\x79\x25\x61\x42\x09\xae\x8f\xe9\x8e\x9f\xff\xb8\x09\x81\x3e\x46\x98\xbf\xd3\x88\x46\x42\x62\x1f\xc4\x12\x70\xe1\x71\xce\x00\x8e\x19\x60\x42\x12\x40\x43\x44\x42\x44\x10\xe1\xe1\xc1\x5b\xf7\x01\x88\x05\xa4\x21\x82\xc8\x8f\x62\x5f\x40\xc9\xe8\x5b\x45\x09\xf0\xcd\x3d\x56\xc9\x00\xe4\xb7\xa7\xcb\xd3\x53\x0a\x29\x96\x0c\x70\xfa\x66\x89\x33\xf8\xb3\xce\x35\xa4\x51\xcf\x59\xd8\x03\xbd\x37\x0e\x3b\x36\xca\x4c\x86\x4a\xab\xe6\xd4\x2a\x83\xb8\x42\xda\x0b\x25\x95\x69\xd5\xb4\x39\xe7\x9d\x76\xbb\x99\xab\xe9\xbb\xa0\xa7\xd8\x91\x31\x02\x8a\x17\x75\x67\xa9\xd6\xbc\xea\xc7\x99\x18\xb9\xcd\x25\x9a\x8c\xf6\x71\x65\x6c\xd5\xc6\x96\x37\x3d\x79\x12\xcd\xb3\xf5\x7c\x40\x6c\x3c\x49\x65\xcc\x9e\xb9\x6e\xb5\x8c\xb8\x9f\x8e\x1a\x15\x3b\x07\xab\x55\x63\x3e\xd6\xd0\x38\x6e\x01\x8f\x98\xbc\x99\xdb\xd5\xe6\x59\x67\xdf\x98\x79\xc5\x54\xb8\xc9\xcf\x97\xb0\xaf\xd6\x66\x6d\x1e\x0e\xec\xa8\x9e\x95\xc2\xab\x15\x8a\xed\x12\x0c\x2b\xba\x3b\xa9\x74\x8f\xb3\xe0\x95\x7c\x09\xa5\xfd\xaa\x58\xfd\xcd\xa7\xc4\xfb\x97\x4d\xf0\x63\xc4\xf9\x3b\x43\x5e\x48\x7c\xec\x79\x7e\x80\x3c\x89\xa3\xe3\x9e\xa7\x90\x4c\x44\x0c\x42\x12\xc2\x08\x52\x2f\x86\x61\xec\x73\x8a\x63\xea\x73\x40\x44\x00\xa0\x1f\xd1\xd8\xc7\x91\xf4\xdf\x0a\xe6\xc0\x37\x4f\xae\x25\x87\xec\x27\x9e\x12\x8e\x08\x61\x04\xa0\x37\x4b\x9c\xc1\x9f\x8d\x6f\x42\x85\x65\x6d\x3f\x9b\x6f\x66\x83\x94\x5a\xd7\xdc\xe1\x84\x76\x73\x25\xbd\xdb\x5c\xeb\xf1\x12\xda\x70\xb9\xa9\x59\x8a\x4f\xe3\x45\x6a\x44\x39\xb7\x72\xd4\x87\x46\xd4\xc3\x7b\x3d\x27\x35\x65\xb4\x28\x3a\x82\x0c\xb9\xeb\x2b\xf5\x9a\x9e\xe6\xb9\xf4\x66\x37\xaa\xce\xa4\x38\x5d\x19\xdf\x3c\x93\xd2\xa9\xb1\x9d\x7a\x8e\xad\x94\xcc\x1a\x6e\xc5\xcb\x7c\x2b\x57\x73\xe7\x9a\x09\xac\x6e\x5c\x62\xf9\x12\x2c\x47\x34\xe5\x6a\x36\x03\x32\xb5\x84\x23\xa2\x66\x3d\xdf\xcf\x35\xd4\xcd\xd6\x73\x60\xc3\x58\xab\xa4\xa9\xa6\xd9\x98\x8d\xe6\xf3\x72\x6d\x3d\x49\x97\x7d\x3a\x1a\x1c\x6b\xc3\x2a\xaf\xa5\x4b\xb4\xae\x8f\xe9\x8e\x9f\xff\xb8\x29\x01\x3e\x46\x9c\xbf\x33\x19\x23\x1e\x71\xe4\x4b\x1e\xf3\xc0\xe7\x7e\x1c\x1e\x7e\x08\x01\x80\xc8\xe7\xbe\x07\x04\x08\x71\x18\x05\x50\x40\x26\x84\x20\x82\x21\xe6\xc3\x08\xfa\x5e\x88\x68\xe4\xd1\x07\xe2\x5f\x5f\x36\xdd\xf6\x15\x04\x78\xcc\xea\x7b\xf3\x29\x41\x92\x48\xc6\x91\x7c\xb3\xc2\x19\xfc\xd9\xfd\x26\x34\xde\xc5\xe3\x02\x8d\xf1\x0e\xaf\x65\x8c\xf7\x15\xa5\xb6\xe4\x13\x23\xeb\xe0\x45\x3e\xe3\x19\x5d\xc3\x1d\x2d\xa2\x3c\x03\x43\x36\x9c\xca\x3a\x65\xd5\xda\x24\xa8\x92\xf6\xb4\xd5\x6a\x2f\xd2\x9d\x61\x30\xce\x37\x74\xad\xd6\xc8\xe5\xea\xac\xd8\x2b\xc8\x78\x13\x15\x8b\xee\xa9\xea\x5f\xf3\x6c\x48\x65\xaa\xdf\x5f\x34\x0b\x6c\xcd\x3a\xa0\xec\x5a\xb9\xad\x33\x81\x29\x77\xd2\xe9\xa1\x5d\xb6\xd6\x6f\x75\x4d\xc1\x4a\x50\xd9\x9a\xe5\xb5\x16\xc0\xe1\xb6\x84\x86\x53\x43\xd4\xa2\x4e\xde\x65\xcb\xb5\xe2\x2d\xa6\x2b\x12\xea\xdb\x51\xb1\x11\xce\xb5\x41\xbf\x36\x34\xdc\x75\xfc\x50\x55\xf0\xb5\x6c\x89\xc6\xf5\x41\xdd\xf1\xf3\x9f\x36\x25\xe4\xc7\x48\xf3\x77\xe6\xc5\x21\xc4\xd8\x8b\x39\x8e\x63\x3f\xe4\x51\x48\x59\x80\x18\x0d\x59\x88\x7d\x1e\x61\x4e\x7c\x10\x42\x0e\x28\x0c\x42\x18\xc4\x22\x92\x51\xe8\x73\xe6\x47\x71\x10\xfa\x84\xfb\x6f\x19\x89\xdb\xbe\x82\x90\xe2\xad\x19\xf1\xf8\x14\x0b\x46\x09\x07\x94\xbd\x59\xdf\x0c\xfe\x6c\xdd\x1a\x34\x97\xda\x7e\x8e\xed\xf4\xba\xc5\x1b\xbe\xda\x0e\x7d\x67\x99\x2a\x81\x45\x29\xb7\xa9\x07\x20\x48\x95\xc7\xcb\x25\x5a\xaf\xf7\x7e\x95\x1b\xd0\x2b\xd7\x53\xfa\x72\xbf\x86\xee\x6e\x52\x6e\xa6\x4a\xf5\xd6\x64\xd1\xd7\x36\xac\xda\xce\x75\x37\xcb\x32\xb4\xad\xb1\x52\x55\x96\xab\xd3\x8c\x68\x9c\xe7\x5e\xb7\x2a\xc5\xe6\xaa\x83\x8c\x36\xca\x93\xea\x78\x53\x9f\xab\xce\xda\xd8\x94\x99\x63\x4d\x57\x08\xa6\x6a\xa8\xde\xea\xce\x8a\x85\xa6\xa3\xe7\x95\x4d\x8b\xee\x40\xae\x51\xd7\xfa\xd9\x90\xba\xd9\x9e\xcf\x37\xdd\xb4\x5f\xaa\x6d\xdb\x0c\x30\xd7\x02\x59\x6a\xcb\x75\xaf\x53\x3b\xce\x88\xd7\x72\x25\x6a\xd7\x05\xc4\x8f\x9f\xff\xb4\x19\x21\x3e\x46\x9a\xbf\x83\xc0\xf7\x68\xc8\x88\x60\x3e\x10\x20\x40\x40\x12\x12\x8a\x08\x01\x2e\x42\x0f\x50\x41\x49\xe4\x93\x90\x09\x1f\x04\x84\x78\xdc\xe3\x20\x06\x2c\x8c\x7d\x1f\x89\x00\x88\xe3\x35\x5c\xe4\xf8\xef\x15\xe1\xbe\x79\x72\x2d\xa5\xa4\xb7\xef\x5e\x79\x7e\x8a\x09\xa6\x92\x63\x81\xdf\xac\x6e\x06\x7f\x76\x03\x76\xb3\x63\xad\x66\x2d\xbf\x30\xb2\xaa\x5a\x77\x5c\xd2\x89\x4a\x93\x5c\xb7\xce\x00\x9c\x2c\xac\x6a\x21\x1a\x67\x37\x7e\xbc\xda\xf5\x95\x8e\xd9\x4e\x77\x1a\x7a\x97\x68\xf9\x49\xb5\xd5\xdf\x66\x86\x66\xab\x13\xfa\x6c\x42\x69\x44\x8b\x76\x46\xa4\xe7\xc6\xb2\x95\xea\x65\xac\x51\xe7\x74\xcd\x44\xe3\xcc\x93\xa0\x71\x17\x64\xab\xed\x54\x39\x8e\x14\xd2\xd3\x71\xde\xb1\xfc\x3c\x0b\x66\x66\x5e\xdb\x82\x99\x4a\x39\x82\x4c\xf7\x9d\x4d\xc5\xae\x83\xee\xbe\x5c\x01\x4b\x6d\x33\x09\x41\xb3\x90\xcf\xd2\x81\xc5\x8a\x9b\x86\x5e\x2c\xf8\x46\x79\x9f\x19\xf9\x69\x59\x33\x36\xda\x84\x64\x8e\x72\xff\x5a\xa6\x44\xf5\xba\x80\xf8\xf1\xf3\x37\x9f\x11\xe4\xbd\x33\x82\x7f\x8c\x34\x7f\x8f\x28\xf3\x25\x96\x28\x06\x92\x48\x14\x13\x20\x08\x17\xd2\x63\x31\x8f\x22\x0f\x23\x4e\x42\x26\x25\x0c\x24\x14\xa1\xa4\x40\x32\x00\x64\x24\x05\x8d\xfd\x88\x05\x20\x04\x6f\x3a\x12\x37\xac\x00\xf9\x27\x80\x90\x88\x1b\x9e\xf7\xd9\x53\x0c\x00\x23\x9c\x43\xf0\x66\x6d\xb3\x9f\x4d\xa7\x4b\x35\xe6\x03\x5a\xdc\x0c\xcd\x22\x50\xb5\xc8\x9c\xae\xe3\xd5\x64\x17\x96\xbc\xb6\x6e\xe6\x4b\xc3\xca\xb0\xa3\x46\xa3\x5c\x2a\xe5\x2b\xc0\x9c\xd7\x51\x66\x4c\x3c\xa7\xef\x5a\xc5\x69\x36\x8e\x63\x23\x1d\x31\x3d\x8b\xf3\xb5\xaa\xaa\x99\x13\xa2\xcc\xdd\x65\x4f\x92\x72\x73\x76\x0a\xe5\x68\x9c\xa7\x5d\x53\xbd\x5c\x99\x62\x47\x35\x76\xe5\x7a\x5f\x34\x46\xa5\xfc\xbc\xbb\x40\x6a\xca\x68\xf5\x25\x41\xd3\x31\x9e\xd9\x0d\x43\x69\xb5\xb6\xcc\xc5\x5c\xcc\xed\xde\xa2\x92\xb6\x9b\xd5\xa2\xb7\xdf\x5a\xea\xb0\xb8\x11\x45\x54\x1f\x18\xa1\x9c\x30\x12\x19\xd3\xa1\xd7\x18\x88\x87\xeb\xb6\x5f\xcb\x93\x28\x5c\xa7\x98\x1e\x3f\x7f\xf3\x09\xf1\x6e\x13\xc1\x3e\x46\x98\xbf\xc7\x34\x96\x01\x8c\x03\x0e\x00\xe5\x30\xf4\x68\x18\x83\x90\x45\x20\x0a\xa2\xd0\xf3\xb9\x88\x23\x01\x23\x16\x33\x06\x28\x89\x08\xa6\x28\x96\xdc\xc3\x31\x08\x62\x1c\xd2\xf8\xcd\x0c\x53\x7c\xe3\x14\x8e\xfc\x13\x20\x78\x7b\x3a\x3c\x3c\x43\x94\x33\x29\x00\xe6\x6f\x16\x35\xfb\xe9\xba\xe1\x2d\xba\x89\xb7\x9b\x4c\x4b\xf7\x5a\x71\xb6\x49\xca\xfb\xe5\x0c\xf7\x53\x9d\xc8\x47\x6e\xce\x19\x94\x6a\xa9\xd6\x24\x9d\xb5\xed\x86\xc0\xa5\x9d\xe4\x83\x34\xc8\x21\xa5\xa9\x23\xdb\x66\xfd\xcc\x76\x12\x1a\x2d\xab\xd3\x1f\x55\x8b\xe6\xa6\x9b\x5d\x96\xc5\xb2\xd2\xee\xc4\xe2\xb4\xf5\xda\x38\x1b\xcc\x92\xa8\x20\x65\xa9\xaa\x8b\x68\x48\x74\x63\x51\x20\xab\x70\xd6\xda\x15\x2b\xb3\x60\xee\xe5\xfb\x81\xa2\x37\x6a\xf5\x92\x80\xb4\x33\xcf\x6d\x5a\xc1\x78\xa5\xd7\xe1\xaa\x3e\xcd\xcf\x9c\xfa\xd2\x37\xd2\xbb\xb6\x0d\x77\xee\xba\xa2\x8d\x7b\xca\xca\x8a\x51\xb7\xb7\xe9\x79\xcb\x63\x3d\x58\xe5\xb5\x0c\x09\xf3\xba\x1e\xec\xf1\xf3\x9f\x36\x19\xe8\xc7\x08\xf2\xf7\x00\x31\x00\x25\x84\x28\xe2\x21\xf4\x30\xe0\x3e\xf7\x99\x27\x08\xf6\x42\xca\xe2\x90\x63\x9f\xc2\xd8\x0f\x03\x14\x31\x4c\xe3\x88\xfb\x20\x0e\x02\xe1\x7b\x11\x61\x91\x24\x90\xbf\x11\xc3\x81\x6f\x1c\x58\x93\x7f\x02\x4c\xdf\x30\x0e\x87\x87\xc7\x53\x3f\x48\x38\x11\x98\x91\x37\x0b\x9a\xfd\xec\x26\x93\x30\x3b\xf9\xaa\xb6\x8a\xab\x93\x4d\x84\x97\xb3\x6e\x76\xde\xf0\x65\xc0\xeb\xf1\x3a\x28\x8e\x4a\x31\xe5\x59\xb1\x2b\xce\x07\xfe\xb4\xd2\xda\xed\x65\xcf\x45\x73\xbd\xbb\x59\xd5\xd7\xe5\xdc\xaa\xa8\xb1\x51\x66\xed\x94\x09\xeb\x1a\xa9\xd6\xb6\x80\x4c\x1a\xc0\xe5\xaa\xb8\x38\xbb\x0c\xbe\x7e\xb6\x8a\x1f\xb0\x75\x39\x5d\xa8\x6e\x37\x6d\xb0\x1b\x9b\x96\x35\x2f\xd4\xa7\xe5\x5a\x4c\x9b\x5d\x3f\x1c\x94\x06\xa0\x68\x94\xd3\xfb\xf6\x36\x93\x9a\x45\x2d\xee\xb9\x79\xb0\xc7\xad\x51\x6e\xb3\x1d\xcd\x31\xb1\xe7\xdb\x6e\x63\x27\x6a\xd5\xfd\xb0\x6e\xe5\xfb\x5d\xa7\xd8\x8c\x70\x2f\x35\x7c\x90\xea\xd7\xd2\x23\xf4\x7f\xc7\xe3\xea\x77\x47\x70\x90\x8f\x91\xe5\xef\x98\xc0\x38\x96\x01\x91\xc2\x97\x80\xb3\x58\xc4\x08\x7a\x91\xc7\x85\x87\xb1\x1f\x80\x80\x61\xe9\xf9\x34\x88\xa5\x60\x5e\xe8\x07\x28\x14\x21\x20\xa1\x44\x3e\xf5\x64\xc8\xc2\xb7\xca\xd4\xe0\x1b\xa7\xd5\xe4\x9f\x80\x22\x7e\xeb\x6c\xee\xec\xe9\xd9\x3d\x75\x6f\x9f\x56\xff\xd4\x84\xd8\x57\xe2\x54\x50\x73\x57\x95\x70\xdd\xdf\xe5\x57\x53\x32\xd9\xaf\x95\x6d\x7f\x34\x6f\xd9\xa3\xfc\xdc\xdf\x2c\xfb\x15\xa7\x5d\x80\xb3\xd0\x8f\x6b\xa9\x56\x14\x93\x5c\xab\x65\x38\x68\x10\xc0\x56\x10\xef\xc7\x65\xa8\xb8\xb6\x34\x4b\xab\xac\x6a\x40\x33\xd7\xd2\xa7\xe3\xba\x34\x4e\x06\xa2\x7e\xe6\x3e\x18\x22\x17\xe9\xda\xde\x04\x69\x92\x2b\x8b\x74\x29\x9f\x26\x78\xe3\x68\xe3\x1d\x54\x9b\xe9\x75\xa0\xa3\x7e\x30\xaf\x0c\xf6\xbe\x1f\xf4\x53\xb9\x98\x65\xe3\xce\x98\xe4\x2a\x4e\xde\x6c\x0d\xf1\x22\xb5\xcd\xcc\x76\x99\x71\x6a\xb5\xd6\x6c\xcd\xdd\xcc\xe6\xb6\x33\xb7\xb5\xf4\x83\x01\x7a\x2d\x39\x22\xfb\xef\x78\x36\xf7\xfe\xa2\x97\x1f\x23\xcc\xdf\xe3\x50\x22\x26\x42\xc8\x42\x4e\x01\xf4\x59\xe4\x73\x49\x99\xcf\x38\x65\x3e\x12\x71\x44\x70\x10\x51\x8f\x01\x08\x7c\xce\x22\xce\x59\x28\x61\xcc\x40\x44\xa3\x28\xe4\xfe\x1b\xd7\x0f\xd1\x3f\xd0\x8d\xc3\x37\xf2\x4f\xc0\x28\xe4\x37\xdc\xed\xc7\xa7\xf4\xb2\xe6\xe5\x5b\x0e\xf5\xcf\xae\x98\x50\xcd\x2b\xe5\x96\x61\x25\x8f\x18\x1e\x36\x97\xe3\xc6\xbc\x60\xd3\xec\x7e\x38\xed\x68\xc5\x70\x15\x22\x54\x95\x1d\x1a\xf1\xd6\x62\x96\x6d\xe7\x2b\x19\x0d\xba\x8b\xc9\xd2\x98\x57\x5b\x83\x0d\xdf\xb2\x74\x50\xb0\x43\xb4\x2f\xab\x99\xd5\x9e\xeb\xa8\x3a\xac\x4e\x6a\x79\xf7\x14\xd0\x54\x3f\x93\x51\x6a\x8f\xd7\xda\xda\x2a\x6b\x62\xb0\xcb\x2e\x70\xde\x5f\xc1\xee\x64\x25\x82\xd1\x64\xb3\x81\x06\xdf\xce\xdc\x7c\xd9\x5f\x82\xf6\x04\x4c\xda\x4a\x21\x4b\xeb\xb0\xba\x2d\xed\xc4\x64\xdd\x4f\x91\x72\xdf\x22\x73\x23\x03\xec\xb4\x8a\x83\x4a\xaa\xab\x16\x95\xb9\x45\x64\xe7\x58\xb5\x49\x79\x2d\x39\xe2\xe5\x5d\xa6\xca\x7f\xe0\x84\x40\x1f\x23\xcc\xdf\x19\x0e\xa5\x88\x29\x66\x51\x74\x80\xf2\x11\xf7\xa9\x2f\x64\x8c\xb0\x17\x53\x0c\xa1\xcf\x29\x93\x1e\x22\xb1\x17\x43\x02\xb0\x17\x02\x9f\x22\x9f\x61\xec\x03\xee\x47\xf2\x20\xf3\xe0\xf8\xef\x95\x09\x71\x7b\x51\xc4\x19\xba\x75\x1f\xd7\xd9\xd3\x53\xfe\xdc\x1b\xf3\xe1\x27\xf7\x5b\xed\x76\x1f\x96\x56\x74\x02\x7c\x93\x37\xc9\x78\x57\x5e\xd7\xb7\x79\xdc\x98\x4e\x06\xa9\x75\x4e\x29\x2f\x55\x58\x40\x16\xcf\x70\xd6\x5e\xb5\xab\xfa\x5c\xd6\xc3\x56\xc1\x77\x0a\xbd\x60\x18\x97\xfb\x3b\x8e\xdc\x76\xce\xac\x0f\x4c\xbb\x11\x14\x1c\xda\x5d\xae\x27\xf3\x11\x3c\x1d\xca\x3d\xac\x9c\x8c\xe7\xff\x94\x87\x43\xb4\x53\x7b\xa3\xd8\x95\x47\xb9\xc5\x7b\xd9\x1d\x29\xb5\x69\x51\x2e\x95\xc6\x76\xb0\xdc\x66\x71\xab\x56\x9e\xe2\xde\x72\x5b\x5b\x6b\x23\x8b\x29\xf5\xc1\x26\x53\x23\x5a\x75\xbc\x4e\x15\x97\xcb\xf4\x2e\xd8\xa7\xb7\x22\x9d\x1a\xe6\x32\x02\xcc\xc7\x8d\x2d\xef\x23\x6b\x3e\x42\x52\x9b\xae\x16\xf5\x6a\xaa\xb3\x96\x0f\xa7\xd5\xaf\xe5\x4d\xbc\xfe\xf9\x9b\xcf\x16\xf0\xee\x43\xbb\x8f\x91\xf4\xc3\x1b\x9f\xe5\x1d\x4a\x0e\xfe\x01\xe0\x3f\x00\xfc\x06\xc0\x1f\xc7\x7f\x37\x25\x5a\x20\xc6\x6e\xcf\x86\xa7\xa7\xa7\x53\xb7\x77\xcb\xfb\x03\x49\x7f\xf5\xd0\xdc\xfe\x64\x5a\x85\x1e\xd9\xa5\x77\xb5\x42\x86\x67\xc7\x59\xa9\x23\xb0\xed\x67\x52\x0b\xd0\x59\x2e\x36\xc6\x66\x0f\x5b\x61\xad\xe9\x7a\x19\xd3\xcb\x1d\x57\x5a\xaf\xe5\x3b\xbc\xfe\x79\x12\xe5\x5b\x86\xe1\x57\xfe\x5c\x8b\xf2\x7f\xfd\xd7\x3f\xfe\xf1\x5f\xff\xf8\xc7\xb7\xac\xb7\xf4\xbe\xc5\x93\xf9\xb7\x92\x37\x8a\xfe\x78\x96\xea\xc9\x34\x9a\x7b\xcb\xde\x64\xfc\xe7\xd4\x9b\x2f\x7b\x41\x6f\xea\x8d\x97\x8b\xff\xfb\xcd\xd9\x4d\xa3\x3f\xbe\x39\x4a\xa6\xa8\x7d\xcb\x2a\x8e\xf2\x7f\xbf\xd5\x82\x6e\x34\xf2\xfe\xf8\x36\x5d\xf9\xc3\x5e\xf0\x7f\xbf\x95\x37\xe3\x68\xfe\xc7\xb7\x03\xf8\x7f\xbd\x3a\x61\x5e\x87\x3e\x9f\x3f\x88\x41\x29\x31\x00\x12\x52\xfc\xfb\x37\x78\x63\xe2\xfd\x00\x07\x3d\xef\x0b\x11\x28\x28\x4f\x8c\x83\x0f\x38\x98\x00\x0c\x38\xa1\x0c\x26\xc6\x21\xbf\x7f\x43\x44\x42\x20\x20\xe0\x88\xd1\xc4\x38\xf4\x80\x43\x04\xc4\x10\x4b\xc9\x64\x62\x1c\x76\x8d\x83\x92\xe1\xf0\x63\x32\x08\x85\x02\x72\xc4\x38\xfe\xfd\x1b\x4e\x86\x23\x7e\xff\x86\x30\x43\x08\x23\x40\x31\xe7\x89\xe9\x91\xd7\x38\x09\xe9\x81\x07\x8f\x10\x43\x89\x04\xc2\x02\x08\x98\x98\xa0\xc3\xca\xe0\x12\x88\x24\x04\x42\x17\x40\x28\x39\x10\xbe\x06\x4a\xda\xb5\x83\x50\x23\xce\x30\x46\x1c\x70\x41\x93\x03\xd1\x6b\xa0\xa4\x5d\x3b\x88\x35\xc2\x18\x0b\x0c\x30\x11\xf2\xf7\x6f\x34\x21\xd0\x41\x02\xa1\x04\x04\x63\xcc\xa0\xc4\xc9\x81\xc4\x69\x43\x4e\x08\xc9\x93\x03\xc9\x63\x8e\x09\x39\x28\x23\xc8\x00\x4c\x0c\x84\xc0\x09\x88\xb2\x3b\x28\x42\xf0\x04\x24\xf9\x1d\x3c\x42\x07\x11\x04\x0c\x52\x41\x30\xc1\x20\xb9\x1c\x21\x7c\x0d\x94\x94\xa2\x83\x64\x03\x28\x18\x26\x8c\x03\x90\x5c\x3d\xa2\x83\xa6\x97\x9c\x32\x41\xa4\xe4\x87\x99\xc7\x12\x02\xb1\x27\x20\x0a\xb0\xb8\x87\xa2\x83\x2d\x94\x18\x71\x4c\x31\x22\x07\x39\x4f\x4a\x91\xb8\x06\x4a\x4a\xd1\xc1\x8a\x1d\xe6\x86\xa0\x8c\x42\x94\x5c\xd5\x62\x70\x0d\xc4\x13\x02\x1d\xec\xbc\x20\x4c\x60\x2a\xb9\x38\x8c\x61\x52\x20\x74\x0d\x94\xb4\x6b\xf8\x98\x3d\x80\x85\x60\x18\xd0\x03\xc7\x44\x42\x20\x72\x0d\x24\x13\x02\x1d\x24\x9b\x33\x20\x31\x63\x18\x1d\xe8\x4b\x4a\x11\xbb\x06\x4a\x4a\x11\x3f\x01\x71\x7c\x0f\x8f\xc4\x35\x50\x52\x8a\xe4\x69\xf3\x99\xca\x03\x7d\x09\x81\x8e\x99\x87\x47\x20\x0e\x00\xb8\x83\x47\xe4\x20\xd9\x8c\x53\x80\x39\x12\xec\xd0\x4a\xc8\x23\x82\x9e\x6f\xf6\x67\x10\x93\xe4\x92\x4d\xf0\x35\x50\xd2\xae\x91\x13\x10\x25\x24\xb9\x1a\x39\xd0\x70\x09\x94\x94\x47\xec\xf9\xa6\x77\x49\x00\x39\x08\x03\x48\x88\xc4\x4f\x17\x64\x33\x7e\x74\x8b\x92\x22\x89\xd3\xb5\xc2\x92\x1c\x1d\xa3\xa4\x48\xf2\xf9\x32\x56\x89\xe0\xd1\x35\x4a\x88\x44\xc1\xe9\x0a\x4b\x22\x58\x72\x59\xa2\xf0\x1a\x28\x31\x49\xe8\x74\x83\x20\xa7\x47\x3f\x2b\xa9\xc3\x86\x9f\x91\x18\x64\x47\x9a\x92\x22\x91\xe7\x1b\xdc\x24\x40\x07\x5f\x2b\x31\x12\x7d\x3e\x03\x40\x48\x1e\xbc\xa4\xc4\x48\xec\x74\x5b\x10\x65\x07\xef\x26\x31\x12\x3f\xdd\xb1\x22\xb0\xb8\x87\x4f\xe2\x19\xe9\x20\x06\xf7\xd0\x24\x4f\x48\x8c\xde\xc3\x27\x06\x9e\x90\x20\x00\xec\x9e\xb1\x3b\x4e\xb4\x47\x24\xc2\xef\x91\x4c\x86\x4e\x48\x42\xdc\x23\x99\x0c\x3f\x23\x41\x24\xd9\x1d\x1c\x3f\xc6\x3c\x3f\xdc\x2a\x82\x20\x10\xc9\x97\xb9\x0f\xdd\x39\x07\x4a\x4c\x12\x7b\xbe\xd4\x81\xe2\xa3\x9b\x03\x93\xd2\xc4\x4f\x48\x5c\x1c\x69\x4a\x8a\x24\x4e\x45\xf5\x19\x91\xc9\xd7\xde\x47\xf9\xb9\x00\x4a\x4a\x12\x07\xa7\x9a\xe6\x12\x81\xa3\x26\x4e\x88\x04\x9f\x2a\x41\x53\x28\x0f\x4e\x1c\x4c\xb8\x87\xc3\xd1\x73\xfd\x5c\xc2\x0e\x2e\x53\x62\x20\xfc\x5c\x75\x94\xe3\xe3\xf6\x49\x42\x1c\x72\x85\x93\x98\x20\xfa\x04\x84\x20\xb9\xc3\x19\xe4\xec\x0a\x27\xf1\x98\xf1\xa7\x43\x34\x0a\xc0\xc1\x17\x84\x09\xbd\x4a\x2e\xae\x81\x12\xba\x5e\x5c\x3e\x55\x01\x14\x88\x23\x98\x9c\x22\x01\xae\x81\x12\x52\x74\xb0\x44\x8f\x45\xd8\x28\x39\x6e\x0c\x24\xdc\x9d\x10\xe8\x1a\x28\x69\xd7\xf0\x33\x90\xa4\xc7\xae\x25\xa5\x88\x3c\x01\x21\xcc\x8e\xa3\x96\x14\x88\x3e\x57\xe5\x12\xf0\xb8\x31\x90\xb4\x6b\xec\x09\x88\x22\x74\xe4\x51\xd2\x51\xe3\x4f\x45\x91\x04\x10\x38\xf9\xdc\x17\xe2\x0a\x27\x71\xcf\xe4\x33\x10\x91\x28\xf9\xdc\x97\xe0\x0a\x27\x29\x87\x24\x7c\x06\x92\xe0\x8e\x3d\x0e\x89\xae\x70\x92\x0a\xd1\xc1\x46\x3f\x14\xed\x81\x98\x1e\x77\x05\x12\xba\x94\x92\x5c\x03\x25\xf4\x04\x25\x7d\xae\x99\xc2\xd0\xd1\x07\x4f\x4a\x11\xbb\x06\x4a\x4a\x11\x7f\x02\xa2\x00\xdf\xd5\x35\xf1\x5c\xfd\x42\xc8\x3b\xf6\x01\xa4\xbc\xc2\x49\xca\xa2\xe3\x19\xf5\x03\x92\xc0\xe0\x8e\x7d\x00\x78\xdc\x64\x3f\x07\x4a\xca\x23\x08\xd0\x53\x3d\x04\x08\x19\x39\xee\xe4\x27\x45\xc2\xd7\x48\x09\x3d\xdc\xe3\xb5\x33\x8f\x09\xe9\x04\xd3\xe4\x8a\x0d\x1e\x96\x68\x97\x40\x89\x3b\xc7\x9e\x43\x13\x38\x38\x38\x84\x28\x31\x4d\xfc\x1a\x29\x29\x90\x38\x07\x12\xf7\x90\x24\xaf\x91\x92\x1e\x28\x82\xe7\x24\x51\xc9\xd9\x3d\x27\x93\xf0\x1a\x28\x31\x12\x7a\xca\xd2\x23\x88\x1c\x37\x70\x92\x1e\xbb\x1e\x56\xc5\x97\x48\x49\x81\xc8\x33\x10\x3b\x1e\xdc\x27\x27\x89\x5e\x23\x25\x05\x62\x4f\x40\x14\xb0\xa3\x50\x26\x26\x89\x5f\x23\x25\x05\x12\xcf\x40\xe4\xb8\xaf\x98\x9c\x24\x79\x8d\x94\xf4\x98\x1b\x3c\xe7\xb7\x51\x78\x47\x64\xc2\xf1\x00\xe8\x12\x28\x69\xdf\xd0\x29\x9a\x84\x8b\x83\x33\x88\x12\x9f\xe1\xe3\xa7\xe3\x60\x02\x8e\x1b\x4a\xc9\x91\xc8\x33\x12\x61\xf7\xd1\x44\x9f\x91\xc4\x71\x43\x29\x39\x12\x7b\x3e\xa6\xc0\xe8\x18\x33\x91\x18\x89\x5f\x23\x25\x05\x12\xcf\x5b\x9d\x54\xde\x13\xa2\x70\x5c\x21\x5f\x00\xd1\xb3\x38\xaa\x9f\x09\x9f\xfa\xb3\x17\xfe\xb9\x88\x66\x4f\x51\x54\x35\xad\x52\xd7\x4a\xaa\xf6\xad\xa6\x39\x3f\x88\xa3\xaa\x69\x45\x4d\x75\xbe\x4d\x3b\x7f\x06\xde\xd2\x1b\x4e\x3a\xff\x5c\x44\xcb\xb5\x37\xfc\x3f\xdf\x7f\xea\x8d\xc7\x88\x6f\xf9\xfb\xb7\xe5\x7c\x15\xbd\x23\xf6\xeb\x83\xe3\xbd\xce\xcf\xb2\xcf\x03\xbc\xce\x5a\xe8\x21\xe6\x1d\xfe\xfe\xed\xfb\xbf\x7e\xf3\x57\xa3\xe9\x9f\xcb\xc9\x6f\x7f\x7c\xfb\x0d\x9f\xc2\x12\xf1\x6f\xff\xdf\xf7\xdf\xbf\x7d\xcf\xab\x95\xb6\x8d\x8d\x3a\x6f\xd5\x99\x66\x32\x6c\xb6\x5b\x05\xb5\x52\x76\x1d\x54\x2d\xb5\x4a\x58\xcf\x50\xb5\xa4\x6b\xa5\x52\x5d\xab\xeb\x35\x4b\x21\x8d\xba\x69\x9a\x35\xad\xf4\xfd\x47\xa3\x7f\x7e\x74\x7f\x1e\x3e\x76\xd6\x62\x3f\xa6\x12\x7e\x21\x95\xe7\xc1\x69\x67\x2d\x70\x83\x4a\x08\xc0\xd7\x11\x77\x11\xf1\x76\xd6\x22\x3f\x66\xe1\x57\x52\x79\x11\x07\x77\x6a\x89\xa7\x68\xf9\xef\xff\xfa\x2d\x5e\x8d\xc3\x68\x7e\xa0\x31\x9f\xa9\xda\xae\x6e\x14\x91\x6a\xe0\x5c\xa9\x42\x32\xad\x62\xce\x2a\x65\x8b\x39\xb3\x5e\xb2\xeb\x48\x77\x71\xdb\xca\xd5\xf4\x72\xa9\xae\x6a\x65\xa5\xd6\xe4\x15\x95\x97\x5b\x48\xff\xed\xf7\x6f\xbf\x79\x41\x30\x59\x8d\x97\x47\x98\x84\x1d\x3b\xc0\x2c\x96\x87\x49\x3e\xee\xfc\xe9\x7b\x43\x6f\x1c\x44\x8f\xe3\x0a\xfe\x79\xc9\xba\x84\x84\xbe\x8b\x75\xe7\xa1\x7f\x67\x2d\xf4\x9c\xbd\xf2\xaf\xdf\x1e\x86\x36\xaf\x94\x72\xed\x6c\x35\xa3\x96\x9c\x7a\xcb\x28\x67\x55\x53\x73\x2d\x45\xb5\x2d\xb5\xd6\xd6\x1a\x1a\x69\xb6\xf3\x6d\xac\xb6\xb3\x6d\x6c\xa3\x5a\xab\x40\x0a\x3a\xa7\x46\x81\xb9\x87\xfe\xc6\xf3\xc9\xe8\x5e\x0c\x6f\xf4\xc4\x79\x78\xe2\xd3\xe1\xf7\x8b\x45\xb4\xfc\x73\xb9\x9b\x1e\xb9\x38\xf6\x96\xbd\x75\xf4\xc8\xbf\x84\x6f\x7b\x0f\xff\x2e\x43\x1e\x4f\x2d\xf6\xa9\xa2\x77\x07\x1b\x7f\x1d\xd1\xbb\x0c\xce\x3c\xb5\xc0\x2b\xa2\xa7\x9a\xb6\x46\xdc\x7a\x15\xa1\x86\x4d\x54\x0b\x65\xb2\xb9\xac\xa2\xbb\x38\x5b\xd4\x72\x58\xe7\x25\xad\x54\xa8\x57\x28\xce\x3a\xd4\xd1\x0c\x94\x57\x74\x87\x96\x48\xeb\x42\xf4\xee\x61\xfd\xfb\x45\xef\x4b\xf9\x87\xae\xf9\x87\xae\xf8\x77\x47\xdf\x4f\x53\x37\xf9\x18\x24\x99\xba\xc9\xde\xf6\x1e\xfe\x5d\x06\xbe\x9e\x5a\xe4\x73\xa7\x6e\x72\x36\xfe\x3a\x53\xf7\x22\x42\xf7\xac\xf5\x60\x70\xe1\x03\xef\xc6\xde\xe8\x71\x5c\x47\x11\x3c\xd0\xbf\xf6\x86\xab\xe3\x6f\xac\xac\xb2\xb1\x94\xff\xfe\xef\xa7\xb1\x76\x6b\xaa\x55\xa8\xb8\x4c\x73\x8b\xad\xb2\xed\x38\xcc\xb4\xed\x72\x2b\x6b\x35\x4a\x99\xa6\xe1\xd8\x4e\xad\x6d\x34\x9a\x4d\x52\x6c\x2a\xd5\x46\xa6\xec\xe8\xb4\xea\x14\x95\xec\x7b\x08\xbe\x88\x04\x3e\x6b\xa1\x9f\x24\xd8\x31\xf6\xa5\xaf\x25\xf8\x3c\xe2\xf8\xac\xc5\x6e\x11\x8c\xce\x09\x1e\xaf\x86\xc3\xaf\x23\xf5\x3c\xa6\xf9\xac\x05\x7e\x59\xde\x9e\xc7\x4e\x9f\xb5\x7e\x8e\xb7\xbf\x95\x1c\x17\x97\xff\x0a\x82\x1f\x62\xb4\xcf\x5a\x37\xa5\xf7\xdb\x05\xc1\x5e\xab\xba\x37\xf2\xe1\x3a\x54\x33\xfb\x20\x9f\xeb\xb7\x5b\x56\xf7\xeb\x88\xbf\x8c\x0b\x3f\xb5\x3e\x59\xcd\x26\xeb\xd8\xaf\xa5\x66\x2f\x03\xd8\x4f\xad\x07\x35\x2b\x0f\xac\xfb\x2a\x5a\x2e\x63\xe0\xcf\x5a\x0f\x32\x48\x8f\xc3\xd8\x1b\xc7\xc3\x87\x4d\x8c\x30\x5a\x3c\x8c\x43\xb6\x4a\x71\x53\xd1\x8c\x42\xb9\x8e\xdb\x85\x12\x26\x6a\x4d\x57\x9a\x3a\xd7\x1b\xac\xc0\xb0\x9a\x31\xab\x75\xa7\x59\xcf\x66\x72\x35\xcb\xe5\xd5\x6a\xa5\x80\x6b\x76\xa1\x5c\x7b\xe4\x71\xc2\x6f\xbf\xbb\x5f\x4f\x21\xf9\x67\x2d\xf1\x76\xbf\x92\x8a\xe9\xd7\x8d\xd7\x79\x60\xff\x59\xeb\x73\x1d\x93\xa4\xc3\x7d\x63\xda\xa1\xd3\x6e\xc2\x97\xcf\xbe\xcb\x44\x84\xb3\xd6\x83\x5d\x13\x8f\x92\x71\xff\x0a\xfb\x62\x4f\x41\xb7\x5b\xf9\x46\xb6\x60\xe7\x68\xc1\x21\x6a\x49\x71\x78\x8b\xf3\x72\xcb\x6d\x73\xb7\xa1\x11\x53\x2f\xe4\xb2\x75\x5d\xcd\xab\x8d\xa6\x5a\x24\x05\x62\x57\x18\x2f\x14\xda\x4f\x5b\x2d\xc9\xbe\xfd\x2e\xa6\x9c\xe7\x42\x9c\xb5\x3e\x57\x9b\x27\x65\xcb\xaf\xa4\xcd\x2f\x93\x36\xce\x5a\x0f\x9a\x86\x3f\xf8\x6b\xf3\xd5\x62\x19\x45\x0f\x73\x89\xd4\xac\xb2\x86\x1b\x76\x2d\xc7\xdb\x55\xac\x3a\x5a\x05\xdb\xb4\x5e\x72\x32\x96\x66\x66\x15\x94\x2f\xb6\x1c\xbd\xca\x2d\x4b\xa9\x2a\xa5\x42\xc1\xcc\xb6\x79\xd5\xce\xe7\x0e\x9d\x3e\xc2\x4c\x1e\x86\x40\x6d\x34\x69\x51\xad\xb6\x73\x36\xb7\xb5\x52\xcb\x51\xf2\xe5\x86\x51\x69\x29\xd9\x6c\xa9\xde\x6a\xb5\x4d\xb5\x54\xc8\x91\x46\x25\x83\x8c\x02\x6f\xa2\xa2\x6d\x36\x73\x1c\xd7\xf3\xc7\x21\x58\x2d\xbb\x93\x79\x6f\x7f\xa0\x27\xf6\x86\x8b\xe8\xd9\x67\x0b\x26\xe1\x91\x48\xad\x5e\x7d\xe9\xc8\x05\xf3\x28\xec\x2d\xff\xf4\x86\xd3\xae\x37\x5e\x8d\xc8\xe9\x2f\x7a\x8b\xc5\xea\x51\x32\x92\xf6\xee\xd1\x30\x24\xfb\xf6\x7b\x86\xeb\x22\xa3\xe5\xac\x85\xfe\x16\xc3\xb5\x9c\xaf\x5e\x8e\x56\xbd\x96\xfd\x37\x1f\xad\x87\x6c\x9f\xb3\xd6\xdf\x63\x72\xbd\x3a\x5a\xff\xce\x73\xeb\x3c\xa5\xea\xac\xf5\xb0\x38\x61\xc7\xd1\x1a\xf6\x46\xbd\xa3\xf6\x97\x08\x61\xcc\x11\xc0\x4c\xd0\x7f\x12\xce\xa9\x00\xfc\x79\x1c\x7e\x9d\xe1\xfc\x25\x66\x5a\xc2\x0e\xbc\x7b\xec\x9e\xb2\xd8\xce\x5a\xe8\xdf\x65\xec\xfe\xaa\x79\xf7\x05\x63\x77\x91\x38\x78\xd6\x02\x67\xce\xce\xa1\x4f\xf1\xd0\xeb\x2c\x7e\xfb\xe3\xdb\xff\x83\xbf\x7f\x43\xff\x73\x58\x45\x3d\xfd\xf2\xcf\xe3\xaf\x8f\xca\xeb\xcf\x79\x34\x5b\xf5\xe6\x51\xf8\xa4\xcd\xfe\x9c\x47\xeb\x49\xe0\xf9\xc3\xe8\xb7\xff\xf9\x32\x55\x72\x91\x79\x78\xd6\xfa\xe4\x05\x69\x72\x61\xfb\x75\x16\xa4\x17\x29\x92\x67\x2d\xf0\xb9\x2e\x62\xf2\xe9\xfe\xeb\xb0\xee\x32\x29\xf4\xd4\x12\xaf\x29\xc1\x8b\x33\x8f\x73\xcd\x77\x07\x47\x2f\x34\x9f\x59\x30\x5b\x76\x21\x93\x33\xf4\x72\x19\x13\x4a\x9b\xad\x66\x9e\xaa\xd9\x4c\xbb\x55\x29\xb9\xb9\x6a\x35\x6f\xa8\xae\x65\xd7\x2b\x98\xaa\x76\x85\x34\x1b\x35\x5c\x68\x17\x3f\xd4\x6a\xdd\xb7\x1d\x92\xb0\x03\xef\x1a\xb0\x8b\xdc\xdb\x53\xeb\x55\xab\x05\xc1\xff\x0e\xd9\x2f\x30\x64\x17\x49\xce\xa7\xd6\xab\x8b\xc4\xff\x1d\xb2\x5f\x61\xc8\x2e\xb3\xc9\x4f\x2d\x90\x74\x6d\xf8\xbf\x63\xf7\x75\x63\x77\x91\x76\x7f\x6a\x7d\xf2\x42\x2a\xf9\xc8\xfc\x3a\xab\x81\xcb\x3a\x03\xa7\xd6\xf9\x19\x42\x30\x8c\xbc\xf9\xcb\x85\xf5\xd9\xaf\xdf\xb7\xb4\x56\x8d\x5c\xae\x5a\x29\xe8\x96\xce\xcc\x2c\x57\x0b\xb4\x6c\x90\x56\x43\x75\x55\xab\x54\x2d\xe5\x98\xed\x2a\xdc\x74\xd4\x2a\xce\xd9\xba\x6d\xb6\x2b\x8e\xeb\xe6\x32\x54\x7b\xd7\xd1\xc8\x65\xd1\x83\x53\x8b\x9c\x7b\x0b\xbd\xce\x38\x9a\xff\x39\x88\x76\x0f\x52\xc1\x4c\xdc\x2c\x17\x0b\x6e\x45\x63\x85\x46\xb6\xad\x29\xc4\xcc\x5a\x39\xc7\x29\x97\xea\xae\x8d\xed\xba\x5e\xca\x96\xda\xd5\xa6\x51\x50\x98\x59\x69\x1a\x96\xd9\x56\x9c\x9c\x76\x1c\xce\x07\xa4\x4d\xd4\xeb\x74\x0f\xb2\x01\xbe\xae\x9f\x17\x25\x19\x4e\x2d\xf4\x25\xfd\xa4\x5f\xd6\xcf\xcb\x82\x11\xa7\x16\xfb\x92\x7e\xc2\xaf\xeb\xe7\x45\x39\x8b\x53\xeb\xdc\xcb\x1d\x79\x8b\xe5\x43\x3f\x4f\x14\xa2\xaf\xa3\xf0\xa2\x4c\xc6\xa9\x45\x3e\xf3\xd0\xf1\xcb\xfa\xf5\x54\xb4\xe3\xd4\xba\xbd\xbf\xf0\xe3\xcd\x85\xaf\xd3\x77\x97\x85\x42\x4e\x2d\x76\x8b\xfa\xb7\xb6\x46\xbe\x5e\x5d\x5f\x56\x27\x39\xb5\xd0\xaf\x25\xf6\xcf\x55\x4f\x4e\xad\x73\x3b\x39\x9c\x6c\xfe\x5c\x76\xe7\xd1\xa2\x3b\x19\x86\x07\x33\xf0\xfb\xb7\xdf\x46\x51\x78\xf1\x3b\xf4\xfb\xb7\xdf\xba\xbd\x4e\xf7\xf2\x97\x5f\xdd\x8d\xc7\x92\x2b\xa7\xd6\xf9\xec\xed\x4e\x46\xd1\x9f\xe1\x64\xe4\xf5\xc6\x87\xa9\x1b\x6d\xbd\xd1\x74\x18\xfd\x33\x98\x8c\xbe\x78\x36\x3e\x17\x74\x39\xb5\xc0\xbf\x99\xbe\xbf\xaa\x12\xf3\xdc\xfa\xe4\xf0\xff\x64\x1d\xfb\xb5\x56\xae\x97\x65\x71\x4e\xad\x07\x9d\x41\x8e\xac\x9b\xce\x7b\x8f\x24\x5e\xc4\xee\x3e\xc7\xf4\xa2\x4b\xd7\xfb\xf8\xe7\x7f\x1e\x58\xfd\xaf\xdf\x0e\xf3\x12\xfe\xfe\xed\xb7\xf1\x51\x1e\x7e\xff\xf6\x9b\xbf\xda\x1d\xfa\xfd\x6a\xe0\xef\x51\x97\x0e\x87\xa7\xe7\x57\x4e\xd7\xe5\xc3\xb7\x9c\xaf\xcb\xbf\x3c\x77\xc2\x58\xbe\x84\x8b\x66\xbd\xc9\x4c\xb7\xca\xb5\x6c\xd9\x24\xbc\x91\xd1\x79\x96\x50\x8b\x98\x4d\xbd\x95\x2f\xb0\xa2\x6e\x56\x15\xcd\xa0\x66\xa6\x56\x42\xd9\x4c\xc5\xe5\x95\xa7\xf1\x48\xf6\xed\x04\xe3\xf1\x58\x5c\xe8\xd4\x12\x5f\x31\x1e\x57\xfc\x7e\x75\xac\x7e\xcc\xee\x97\xa3\x7a\x01\xf4\x77\x1a\x8d\xcb\xba\x4a\xa7\xd6\xe7\xc6\x50\x25\x65\xcb\x2f\xa5\x58\x2e\x0b\x49\x9d\x5a\x0f\xb6\x07\xff\x94\x20\xe3\x9f\x97\xe3\x49\x1c\x47\xf3\x3f\x7b\x4f\x0b\x86\xbf\x5a\xcd\xa0\x8a\xe1\x3a\xc8\x50\xea\x39\xab\xda\x2a\x14\x6b\xc5\xa2\x5d\xd5\x54\x95\x95\xd5\x72\xde\xb4\x94\x6c\xcd\x76\xaa\x05\xee\xe4\x4b\x0e\xaa\xe5\xaa\xc8\xcd\x37\xb3\x4a\x35\xfb\x34\x3a\xc9\xbe\xfd\x8e\xd1\xb9\x28\xce\x75\x6a\x90\x77\x8c\x0d\xfa\x98\xb1\xf9\x72\x95\x73\xdf\xc8\x94\x0b\x3c\x53\xae\xd7\xca\x4d\x5b\xcf\x28\xa5\x8c\x6b\x31\xcb\xa8\xba\x6d\xd3\xc8\x1a\x76\xdd\x35\xed\x96\xee\xe8\x4a\x36\xc7\x69\x5d\x6b\x18\x0d\xb7\xa9\xeb\xe5\x52\x45\x7d\xcf\xc8\x9c\x57\x3b\x3b\x35\x5e\x3d\x56\xfa\xa9\xfd\xd3\x84\xfd\xbd\xda\x3f\x4d\xd8\xf1\x0f\xdd\x3f\xfd\xd5\x47\xee\xbc\x2c\xdc\xa9\x81\x3e\xd7\x54\x24\x1f\x97\x5f\xc6\x54\x5c\x94\xaf\x3b\x35\x3e\x77\xf1\x7e\xc7\xbc\xf8\x65\x18\x77\x51\x65\xef\xd4\x78\x58\x9c\xa0\xcb\xf4\x49\xa5\x8a\x14\xcd\xd5\x0a\x86\xa3\xa1\x62\xc1\xa0\x55\xab\x95\xa3\x96\xd1\x68\xb3\x0a\x6f\x19\xc5\x6a\x39\x9f\x75\x10\x2a\x73\xb3\x45\xb2\xb5\x66\xae\xc6\x73\xd9\xac\x7d\x91\xfe\x97\xad\x36\x31\xa7\x96\xe2\x56\x09\x2b\x67\xf3\x39\xd4\xcc\x2b\xa5\x8a\x8a\xaa\xd5\x76\x91\x97\x11\x61\x59\x57\xd7\xd5\x7c\xd3\x69\xa0\xaa\xc6\x0d\x5d\x43\x95\x7a\xa5\x78\xe4\xd8\xd4\x5b\x76\x7f\xfb\xe3\xdb\xff\xfb\x9f\xab\x54\xc0\x57\x72\x01\xdf\x1d\x83\xb3\x98\xac\xe6\x41\xf4\xe7\xc8\xdb\xde\xc4\x3c\x53\x22\x4a\xcb\xca\x11\xec\xe4\xdb\x7a\x13\x57\x4a\xb8\xaa\x95\xeb\x0a\xaa\x53\xbb\x49\x33\x8e\x52\x6d\xe5\xf3\xae\x89\x4d\x23\xa7\x37\xb1\xeb\xb0\x4a\xb5\x50\x2d\x62\xd5\xb6\xeb\x67\x2f\xba\x49\xff\xd3\xf3\xdb\x29\x8d\x09\x39\xf8\x1e\x89\x38\xaf\x72\x78\x6a\x80\x5f\x56\x22\xfe\x75\x23\x05\xf4\x7f\xde\x72\x68\xfe\xad\x24\xe5\x7a\xf1\xf9\x9a\x14\xbd\xd1\x9b\x0f\xa3\xfb\xab\x44\xf4\xa2\xec\xe5\xa9\x41\x5e\xe6\x7c\xdf\x21\x5e\xa7\x9c\xe5\xe4\xa3\xf8\x93\x8a\x2a\xf9\x82\xe6\xbe\x91\x4a\xf8\xed\xf7\x8f\xd4\x43\x5d\xd1\x53\xe3\x55\x07\x0e\xfc\x93\xbe\xe6\x24\x90\xb7\x77\x22\xd0\xaf\xea\x25\xfc\x3d\x86\xe6\xb1\x52\xeb\xa9\xc1\xde\xe5\x5b\x7f\xad\x73\xfd\xa8\xa6\x3f\xc0\xb9\xfe\xe5\x07\xe7\xbc\xfa\xed\xa9\x91\xd8\x85\xbb\x43\x87\x9d\xbb\x70\x77\xa8\xd3\x5f\x43\xe3\x7d\x81\x6d\x3a\x2f\x37\x7c\x6a\x90\xbf\x78\xe4\xee\x58\xab\x7d\x54\x60\xfb\x9d\x73\x2e\x59\x07\xde\x31\x72\x17\x75\x99\x4f\x8d\xcf\x75\xbe\xef\x98\x51\xbf\x8c\x0f\x79\x51\x3f\xfa\xd4\xf8\x5c\xe7\xfb\x0e\x81\xfe\xd5\x18\xf7\x50\xe7\xfa\xd4\xf8\xe4\xa2\x06\x77\x38\x25\xbf\x0c\xe3\xce\xcb\x71\x9f\x1a\xec\xb5\x7a\x63\xed\xbc\x5d\x70\x69\xb3\xa6\x37\xf3\xd4\x2d\xb7\xad\x52\x9e\xa2\xbc\x5a\xa0\x35\xd5\x24\x6e\xbe\xde\xb4\x4c\xb3\x91\x6f\xd7\x0a\x28\x67\x93\x8c\x81\x4c\xc3\x2c\x21\xf5\xc2\x01\x50\x75\x95\x64\x91\x5a\x23\x54\x35\xab\xa5\x12\xa9\x28\xba\x83\x8a\xb9\xb6\x62\x1a\x75\x6a\x2b\x5c\xa7\xb8\x80\x1b\x65\x9b\x35\x35\x93\xb5\x9a\x7a\xa9\x56\x6a\x17\x2a\xf9\x6b\x07\xe0\x33\xd6\xff\x49\x49\x7b\x4a\xf5\x4e\xf4\xed\xf7\x0c\xd4\x79\x95\xf2\x53\xe3\xb5\xea\x5c\xbf\xf2\x40\xbd\xba\x15\xf3\x55\xdc\x7b\x2c\xcd\x7e\x6a\x24\x4e\x70\xbc\x83\x3f\x17\x6b\x89\xe4\x43\xf5\x6b\xc8\x7d\xc2\x0e\xbc\x63\xe4\x2e\x6a\xd8\x9f\x1a\x9f\x5d\xe0\x20\xf1\xf0\xfe\x32\x9a\xfd\xa2\xd2\xfe\xa9\xf1\xb9\xd9\x64\x77\x08\xf4\xaf\xc3\xb8\xf3\xeb\x00\x4e\x8d\x1b\x8b\xb0\xac\xda\x70\x32\xf9\x9a\xa6\xd5\x79\xa1\xd8\xaa\x5b\xba\x55\x6b\x65\x94\x62\xcb\x44\x0e\x31\x50\xa1\x6c\xb7\x9a\xa8\x46\x9d\x6a\xb1\x90\xad\x1a\x4a\x2b\x4b\xeb\x59\x5d\x71\xcb\x2f\x24\x2e\xc3\x73\xb6\x9b\x2f\x16\x59\xd5\xc4\x5c\x2f\x54\x15\xb7\x49\x1d\xa5\x69\xe5\x32\xf9\x7c\x2e\x6f\x11\xc3\x62\x5a\x35\xa3\xb6\x5b\x06\xca\xb4\x49\xb9\x5c\x6e\xa1\xba\x72\xb3\x84\x24\xbd\x66\x5b\x42\x32\xdf\xc1\xb6\x8b\x2b\x0b\x4e\x8d\x4f\x5e\xf4\x27\xe7\xfe\x2f\x23\x6f\x17\xf7\x2a\x9c\x1a\xaf\x2c\xc1\x3e\xa4\x6e\x64\x9e\x22\xa7\xc9\x2a\x4a\x86\x39\xf9\x92\x55\x76\x8a\x18\xb9\xc4\xc2\xf5\x4a\xa5\x58\x2a\x95\x74\x5b\xd3\x5d\xc5\x70\xab\x36\xab\xe5\x72\xac\xad\x34\xaa\x39\xda\xae\x24\x2e\xf9\x9a\xec\x6d\x89\xb8\x27\xae\xb8\xf7\x29\x55\x37\xff\xcd\xb8\x77\x71\x5d\xc5\xa9\xf1\xc9\x46\x22\x39\x13\x7f\x99\x49\x7b\x71\xa7\xc6\xa9\xf1\xca\xc1\xc9\x87\x88\x1d\x61\x8d\x6a\x21\xa3\x16\x0d\xd4\x62\xd9\x56\xb1\xc5\x15\x43\x6b\x54\x73\x45\x1d\xd7\x15\xde\xca\x68\xb8\x94\x2f\xd9\xac\xcc\x89\x5e\xa1\xc5\x96\x6e\xe5\x9d\x06\x32\x33\x57\x62\xf7\xb3\x52\x97\xec\x65\xef\x67\xde\xc3\xed\x1f\xa7\xc6\x2b\xbe\xcc\xff\x32\xef\x06\xf3\x1e\xef\x29\x39\x35\x3e\xcb\x5c\xfc\x5b\x32\xef\xe1\x46\x95\x53\xe3\x95\xf2\xea\xff\xcb\xbc\x97\xcc\x3b\xbf\xfc\xe5\xd4\xf8\xe4\xdd\xc9\xe4\x3c\xfc\x65\x8c\xc5\xe5\x5d\x37\xcf\x8d\x9f\xcc\x04\xca\xb6\x72\x4a\xde\x54\x6b\xaa\x41\xd4\x02\x72\xf5\x02\x73\xab\x45\x85\x39\x05\xad\x95\xab\xb6\x78\xc6\xca\x37\xac\x4a\x39\x63\x15\x0d\xad\x6e\x56\x4d\xea\x56\x4a\x45\xcb\x78\xcf\xc0\x5e\xde\xa0\xf3\xdc\x60\x3f\xa0\x0f\x7e\x31\x7d\x8f\xf7\xf2\x3c\x37\xde\x48\x08\xcd\x62\x8d\xeb\x05\xab\x5a\x72\x98\x9e\xcf\xe4\xf5\x8c\xc3\x0c\x66\x6a\xa4\x84\x6a\xa4\x49\x0b\x6d\x44\x98\x93\x37\x49\xa1\x52\x6b\x99\xc8\x26\x99\x96\x5a\xb7\x2b\x96\xfd\x46\xe2\xcc\x97\xf5\xf2\xf1\xce\xa0\xe7\xc6\x5b\xd9\x58\xe8\x9d\xd9\x58\x9f\xdf\x89\x8b\x4b\x86\x4e\x8d\x4f\xae\x61\x93\xac\x5b\xbf\x94\x8e\xb8\xb8\x0b\xe9\xd4\xf8\xec\x13\x0c\x03\xe3\xba\x5a\xac\x38\x6a\xc1\x42\x25\xab\x9a\xa9\xf1\x96\x9b\xa9\x52\x4c\x8b\x45\xad\xa1\xe8\x45\xea\x66\x4a\x24\xe7\xa8\x19\xa2\xb7\x75\x87\xb7\x15\xaa\x36\x0a\x5f\xc3\xb8\x1f\xdc\xab\xb4\x9c\x7b\x61\xf4\x31\x77\x2a\x3d\x40\xdd\xc8\x96\x38\xf0\x1e\x01\x28\xff\x01\xd8\x3f\x00\xfe\x06\xd9\x1f\x98\xfe\x41\xc1\xf7\x63\x68\x07\x7c\x18\x9f\xe7\xc2\xb8\xbf\x7f\x83\xf8\x58\xdf\xf0\xec\x37\x8f\xa5\x3a\xe1\x53\xce\xd0\xad\x5b\xd3\xae\xa8\xb8\x88\x27\x7d\x95\x08\xc2\xbe\x3f\x78\xb9\xf4\x88\x0b\xc1\x19\x15\xec\x48\xc5\xf9\xaf\x1e\x8a\x1a\xc2\xa7\xe0\x43\xc2\x20\x64\x82\x41\x40\x30\x62\x1c\x1f\xfa\xfb\x93\x74\x9d\x47\x35\xbe\x4e\x17\xfd\xfe\xf0\xa2\x47\x27\xfc\x9c\x2e\x7a\xc9\x9d\x13\x7b\x1e\x53\xdc\x9e\xa8\x02\x00\x43\xce\x01\x3b\xd6\xb5\x4d\x40\x18\xbc\x49\xd8\x89\x61\xe8\x25\xc3\xd0\x4f\x30\xec\x44\xda\x4f\x09\xe9\x78\xe1\x05\x2f\x6e\x12\xfb\x28\xb1\x7d\x15\xfc\x24\xc8\x2f\x6e\x03\xbb\xcd\xc9\xb7\x91\xd0\x8b\x1b\xbb\x92\x22\xe1\x17\xb7\x6a\x25\x45\x22\x2f\xae\xc0\x4a\x8a\x44\xaf\xaf\xa9\xba\x75\xa9\xdd\x0f\x91\xd8\x8b\x0b\xaf\x92\x22\xf1\xeb\xfb\x9f\xde\x50\x1b\x6f\x23\x89\xeb\x9b\x90\x12\xf7\x4e\x5e\x23\x25\xa6\x09\x82\x17\x77\xe4\x24\x86\x7a\x71\x5d\xd1\xad\x4b\x12\x7f\x0c\x85\xae\x6f\x9e\x49\x4e\x15\xbe\x86\x4a\x4e\x15\xb9\xbe\xd4\xe5\xd6\x3d\xde\x3f\x86\xa2\xd7\xd7\xad\x24\x87\x62\xd7\x17\xa1\x24\x87\xe2\xd7\x17\x95\x24\x87\x12\xd7\x57\x88\x24\x87\x92\xd7\x97\x7b\x24\x86\x42\xe0\xfa\xaa\x8d\xc4\x72\x85\xe0\x35\x54\x72\xaa\xd0\xf5\x2d\x16\xc9\xa9\x7a\x71\x09\xc5\xad\xcb\xf8\x7f\x0c\x45\xae\xef\x7d\x48\x4e\x15\xbd\xbe\x6a\x21\x39\x14\xbb\x86\x4a\xde\x41\x7e\x7d\x7d\x01\x4f\x0c\x25\xae\xa1\x92\x77\x50\x5e\xdf\x1f\x90\x18\x0a\x83\x6b\xa8\xc4\x1d\xc4\xf0\xba\x34\xff\xad\x1b\xe3\x7f\x0c\x85\xae\xa1\x6e\xdd\x87\xff\x63\xa8\x17\x15\xe8\x93\x53\x45\xae\xa1\x92\x53\x45\xaf\x2b\xad\x27\x87\x62\xd7\x50\xc9\x3b\xf8\xa2\xa2\x78\x72\xaa\xc4\x75\x81\xeb\xe4\x50\xf2\xba\xde\x72\xe2\x0e\x1e\x03\x2a\x2e\xea\x1c\x27\x9e\x38\xe7\x75\x7f\x1f\xa0\x12\x77\x90\xa0\xeb\x12\xc2\xc9\x3b\x88\xaf\xa1\x92\x77\x90\xbc\xa8\xce\x0b\x12\x63\xd1\x17\x85\x63\x93\x63\xb1\x17\x15\x4d\x93\x63\xf1\x17\xa5\x36\x93\x63\x89\xeb\xd2\x8f\xc9\x59\x2f\x5f\x54\x91\x4c\x4c\x16\x05\x2f\xca\x2a\x26\x77\xbd\xe0\x8b\x5a\x86\xc9\xb1\xd0\x8b\x7a\x81\xc9\xb1\xf0\x8b\x9a\x7c\xc9\xb1\xc8\x8b\xba\x77\xc9\xb1\x5e\x56\xa8\x4b\x8e\xc5\x5e\x54\x85\x4b\x8e\xf5\xb2\x46\x5b\x72\x2c\xf1\xa2\x60\x5a\x72\xac\x97\xa5\xcd\x12\x63\x1d\x27\xf3\x65\x7d\xb1\xe4\x58\x2f\x6b\x80\x25\xc7\x42\x2f\xea\x6c\x25\xc7\xc2\xd7\x58\xc9\xf7\x42\xc8\x8b\x1a\x56\xc9\xb1\xe8\x8b\xfa\x4b\xc9\xb1\xd8\x75\xf5\xa0\xe4\x50\x2f\x0b\x11\x25\xc7\x12\x2f\x2a\xf3\x24\xde\x32\x60\xf2\xba\x90\x4c\xe2\x9d\x1a\x0e\xae\x2b\x9f\x24\x87\x82\x57\xa5\x38\x12\xf3\xea\xa0\x13\x2e\x8b\x7a\x24\x27\x0a\x5f\x95\xb9\x48\x4e\x14\xb9\x2e\x98\x91\x78\xfc\x38\xbd\x2e\x21\x91\xd8\xdd\x3c\xa8\xe2\x4b\xa8\xc4\xde\x18\xe7\xd7\x65\x0c\x92\x53\x25\xae\xa1\x92\x53\x25\xaf\x33\xd7\x13\xef\x88\x1c\x4c\xe0\x25\x54\xe2\x0e\x8a\x17\x59\xda\xc9\xa9\x42\xd7\x59\xc5\xc9\xa1\xf0\x75\x0e\x6c\xf2\x0e\x92\xeb\xa4\xcc\xc4\x23\x28\xe8\x55\x96\x60\xe2\x29\x28\xd8\x75\xbe\x61\xf2\xfe\xf1\xeb\x0c\xbc\xe4\xfd\x13\x57\x50\xc9\xfb\x27\xaf\xb2\xdb\x92\x6f\xe5\x83\xeb\x3c\xb9\xc4\x42\x25\xe1\x75\xe6\x58\x62\xb7\xf5\xb0\x48\xb8\x84\x4a\xec\xb6\x4a\x7c\x9d\x26\x95\x9c\x2a\x72\x0d\x95\x9c\x2a\x7a\x9d\x7e\x94\x1c\x8a\x5d\xe5\xc3\x24\x97\x05\x7e\x9d\x59\x93\x9c\x55\xe2\x2a\xd7\x24\x39\x51\xf2\x3a\x6b\x25\x31\xa7\xe0\xf1\x48\xe1\x3c\x91\xe3\xad\xb3\xee\x1f\x61\xc1\x6b\xac\xc4\x7e\x34\x04\xe8\x2a\x53\x22\xf9\x71\x13\xb8\x4e\xba\xb8\xa7\x8b\xe4\x3a\x92\xfe\x0e\xba\xe8\x35\x56\x72\x28\x76\x15\xa2\x7e\x07\x14\xbf\x86\xba\x03\x4b\x5c\x05\x80\xa3\x3b\x4e\x45\xe5\x35\x56\xf2\x53\x51\x70\x15\x5a\x7d\x07\x59\xf0\x3a\x4c\xfb\x0e\xb2\xd0\x55\xd0\xf2\x3d\x64\xe1\x6b\xac\xe4\x50\xe4\x2a\x1c\xf8\x1e\xb2\xe8\x35\x56\x72\x28\x76\x15\x68\x7b\x07\x14\xbf\x86\xba\xa3\x87\xe2\x2a\x8c\x15\x25\x3f\xdc\x86\xf2\x2a\xe4\xf4\x0e\xac\xe3\x09\xd8\x79\x78\xe8\x3d\x58\xf0\x2a\x08\xf3\x1e\x2c\x74\x15\x0b\x99\x7c\x18\x11\xbe\x86\xba\x83\x2c\x72\x15\x69\x78\x07\x59\xd7\x41\x8b\x17\xc1\x51\x3f\x17\x13\xf5\x67\x2f\xfc\x73\x11\xcd\x9e\x42\xa3\x6a\x5a\xa5\xae\x95\x54\xed\x5b\x4d\x73\x7e\x10\x1c\x55\xd3\x8a\x9a\xea\x7c\x9b\x76\xfe\x0c\xbc\xa5\x37\x9c\x74\xfe\xb9\x88\x96\x6b\x6f\xf8\x7f\xbe\xff\xe4\x3b\xbf\x1f\xa8\xa7\x0f\x21\x5f\xef\x0a\xea\xfa\xf0\x40\xae\x13\x4f\xbf\xfb\x01\x84\x3e\x0d\x08\x0c\x23\x2e\x21\x66\x32\x0e\x05\x8d\x3d\x18\x04\x31\x80\x01\xa6\x01\x02\x61\x4c\x63\x29\xe2\x18\xc5\x9c\x86\x00\x45\x5e\xc8\xa0\x1f\x87\x14\x81\x08\xc1\xef\xbf\x7f\x63\x8f\x91\x70\x79\xb5\xd2\xb6\xb1\x51\xe7\xad\x3a\xd3\x4c\x86\xcd\x76\xab\xa0\x56\xca\xae\x83\xaa\xa5\x56\x09\xeb\x19\xaa\x96\x74\xad\x54\xaa\x6b\x75\xbd\x66\x29\xa4\x51\x37\x4d\xb3\xa6\x95\xbe\x1f\x75\xc6\xd3\x07\x1f\x63\xf9\x6e\xc4\xd6\x61\xfc\x4f\x0c\x09\x02\x87\xd7\xbe\xfd\xf4\x32\x24\xed\xbb\x72\xf8\x14\xf2\x2d\x5e\x75\x24\x8b\x8c\x31\x02\x74\x35\xa9\xeb\xee\x78\x56\xf4\x97\x28\xb0\xab\xa5\x72\x75\xee\x69\x93\xc8\x51\x82\x79\xb5\x50\x3f\xfc\x79\xfb\xf0\x9f\xd6\x6a\xb7\x8b\x9d\xac\x72\xf9\xc9\x9c\x7e\x5c\x1c\x9a\x39\xd4\xac\x11\x65\x73\x7a\xae\x17\x40\x6d\x78\xfc\xbe\x1a\x18\x2c\xda\x82\xec\x8c\xb9\x4a\x97\x79\x05\x48\xfa\xfa\x76\xa5\xac\xbb\xeb\x42\x1e\xa5\x4a\xab\xbd\x3f\x51\x0a\xf3\xd8\x55\x3d\x15\xb6\x6b\x15\xce\x33\xae\x9e\xa6\x56\xa7\x6b\xb7\x24\x37\xcb\xb2\xd9\x6a\x40\x1e\x75\x4b\x05\x1e\x82\xd5\x68\x9b\xe9\x78\x66\x5f\x28\xdf\x9f\xfa\x74\xf8\xe4\x2b\x27\x72\x4e\x3f\x16\xcf\xe8\xfd\xef\xe7\xbf\x3f\x3e\x37\x0e\xff\x1d\xfb\x64\x9f\x7d\x75\xd2\x8e\x97\x39\x1b\x4f\x49\x2f\xf6\x9d\x11\xeb\x56\xc2\x5e\x34\x59\xae\x70\x7b\x23\x35\x40\xf3\xcb\x49\xad\x4b\xad\xcc\x6e\xa9\x4d\x8f\x5f\x52\x1b\xca\xba\x17\x9c\x78\xa4\x2a\xaf\x7e\xb4\xd7\x7f\xfd\xc8\xc3\x0f\x7c\xff\xf5\x18\xfd\xd4\xfb\x15\xe5\xbf\x4f\xbc\xe9\x1c\xfe\xb3\x0e\xff\x89\xd3\x9f\xa9\xdd\x61\x0a\xd4\xd3\xd1\xb8\x67\xca\x65\xd9\x9f\xe5\x32\xc8\x64\x3d\xc4\xc3\x71\x16\x38\xce\xc0\x43\xdd\x82\x3e\xd8\x3c\x8f\xb7\x62\xd6\xd5\x54\xf1\x28\x3f\xd5\x70\x38\x58\x3d\xf0\xfa\xe5\xa7\x72\x8b\xac\x23\xbd\xf2\xbe\xf7\x9b\x9b\x64\xef\x7f\xe0\xc5\xbf\xc6\x6a\x79\xbc\x08\x15\xb6\x1a\x29\x46\x34\xea\x2d\x23\x63\x2b\xfc\x4e\x91\xf8\xbb\xee\x72\xdd\xf7\x17\x88\x29\xea\x0c\x23\x65\xd4\x59\x36\xeb\x83\x72\x6a\xd3\xcc\xa4\x53\x8e\x61\x38\x30\x1d\xed\x9c\x75\x63\x08\xc3\x08\x4f\x9c\xda\x0a\x87\xc5\xe9\xa2\xe2\xe6\x7b\x6e\xfa\x00\x7e\x0c\xd6\x1e\x4f\xc6\xd1\xf7\xdf\xbf\x95\xea\xc5\xe2\xcf\xfd\xff\x18\x21\x0b\x7e\xc2\x03\x3a\xd3\x6b\x81\x80\x18\xf9\x92\x06\x00\x30\x1c\x78\x71\x88\x80\x8f\x58\x88\x78\x0c\x58\x00\x51\xc4\x84\x60\x40\x86\x28\x94\x21\xe6\x88\xf8\x82\x00\x81\x60\x24\x18\x14\x1c\xf8\xe2\x40\xe2\x63\xaa\xe0\x07\xe9\x35\xf4\x23\xbd\x86\x0f\x8e\xe8\x4d\xbd\x76\x78\x4a\xbe\x5f\x07\xc8\xde\xab\xd7\xae\xe7\xec\xeb\x7a\xed\x24\x2b\xe7\x7a\x8d\xe8\xdc\xc9\x8e\x97\xe5\x7a\x2b\x6b\x75\x88\x15\x4f\x54\x7b\xe8\x17\xab\x95\xb6\xce\x1b\x9b\xd2\xb4\xae\x5b\xeb\xe5\xb8\xda\x9c\x35\x8d\x9e\x9b\x9e\x8d\x5d\x77\x05\xfc\x75\xc7\xad\x37\x96\x93\x5c\xb9\x1c\xcd\xb4\x61\xb5\x50\x74\x67\xcb\x72\x13\xe7\xf6\xb2\x57\x18\x82\x66\xc5\xfc\x30\xbd\x76\xf6\x47\x49\xf4\x0a\x3c\xf1\x28\xf3\xfa\x04\xfa\x81\x5e\xfb\xb8\xf7\x27\xd2\xab\x37\xf4\x1a\x3f\xfd\x59\x12\xbd\x62\x11\xe5\x59\xaf\xdc\x78\xff\xdb\x7a\xed\x03\xf5\xea\x7b\xde\xff\xa8\xd7\x56\x99\x14\xd8\x50\xee\x0c\x73\x9b\xbd\x51\xce\xea\x4c\xe9\xd3\xe6\x0e\xd4\xf3\xd5\x14\x0c\xb2\x5e\x23\xb3\x2f\xf2\x36\x68\xcc\x86\x3d\x63\x64\xb3\x29\xca\x17\x97\x79\x4e\xf2\xb9\x9c\xef\x65\x9c\xfe\x78\xd6\x35\xeb\xb5\x1e\x2a\xcc\x9d\xe1\x72\x1b\xa4\xdd\xde\x34\xcc\x0d\xd4\xca\xd7\xea\x35\x4e\x7c\x86\x42\x8a\x30\x84\x91\x87\x63\xc2\x31\x95\x31\x27\xfc\xb0\x24\xa6\x98\xe0\x58\x72\xe6\xc5\x1e\x89\x43\x0c\x58\xe0\x79\x51\x1c\x45\x34\x8a\x43\xdf\xf7\x21\x20\x71\xfc\xfd\xf7\x6f\xc7\xd3\xea\x0f\xd3\x6b\xf0\x47\x7a\x8d\x30\x44\xf9\x4d\xbd\xf6\xf4\xf4\x32\x5c\xff\x5e\xbd\x76\x3d\x67\xaf\xf4\xda\xc3\xa7\x7d\xf6\xfc\xa4\xd7\x94\xf2\x7c\xdd\xae\xe5\xc6\x0e\x36\xd7\x23\x07\xda\x74\x68\xa6\x87\x9d\xce\xb4\x1d\x91\xf1\x56\xa7\xcd\xb5\x29\x0b\xe9\x5a\xb1\x9c\x25\x72\x13\xcf\x66\x82\x2c\x56\xe3\x60\xd2\x36\xc6\xd8\x50\x62\x60\x6b\x5b\x6b\x83\xa3\xe5\x8a\xe6\x7a\xd9\xc6\x06\x07\xb8\xef\xba\x5d\xa5\xf8\x51\x7a\xad\x7c\x5a\x63\x26\xd1\x2b\xfd\xf2\x89\x47\xaf\xcf\x9f\x1f\xe8\x95\x0f\x7c\x7f\x22\xbd\x7a\x43\xaf\xb1\xd3\x9f\x25\xd1\x2b\xe5\xe3\x32\xf2\x41\xaf\xdc\xf8\xbc\xad\xd7\x3e\x50\xaf\xbe\xe7\xfd\x8f\x7a\x2d\x3b\xe3\xa8\xde\x6d\x03\xb9\xf3\xe9\x40\x3a\xa9\x76\x2d\xa6\xae\x51\x68\xb6\x56\xa6\xa8\xa6\x1a\xf3\x5d\x5c\x5b\x83\xde\xbe\x93\xb2\x03\x9d\xcd\xd6\xe5\x62\x71\x8a\x0b\xf9\x9a\x29\x77\x8a\x2e\xb3\x5b\xcb\xb1\x4a\x78\xee\xaf\xaa\x6e\x07\x06\x25\x5c\x22\x28\x6f\x54\xd4\xcd\xd7\xea\x35\x81\x64\x48\x71\x8c\xc2\x20\x8a\xfc\x08\x02\x2f\x16\x00\x70\xca\x88\x0f\xbc\x28\x0e\x23\x01\xa5\x2f\x29\xc7\xc4\x0b\x09\x86\x61\x2c\x08\xe2\x80\x51\x18\xf1\x28\x14\x9e\x04\x07\xbd\x26\xee\xd6\x6b\x4f\x69\x35\xf4\x98\x44\xfd\xb6\x5e\xa3\x1c\x4b\x79\x53\xaf\x3d\x3d\xbd\x4c\x1e\x4a\xae\xd7\xb2\x03\xe5\x52\x8f\x29\xca\xcd\xf5\xda\xd9\xf3\x93\x5e\xcb\xce\x80\xd9\xe8\x16\x4a\xc6\x4c\x7a\x1d\xb0\xa8\xa6\xaa\xe9\x60\x8d\x43\xb9\xd4\x56\x9e\xab\x8d\x50\xc6\xdb\x1b\x7b\xa3\x58\x0d\xf3\x7d\xe9\x0d\xbd\x86\xd5\xce\x74\xb7\x13\x13\xb7\x8d\xa9\x8d\xe7\x73\x4f\x35\xf7\xbb\x49\xa1\x5d\x4e\x4d\xa9\x9e\x69\x1c\x46\x08\xa5\xea\xf9\x0f\xd3\x6b\x67\xea\x28\x89\x5e\x19\x9f\x78\x74\xe3\xf3\x03\xbd\xf6\x71\xef\x4f\xa6\xd7\x3e\x58\x97\x95\x2b\x6f\xbc\xf3\x6d\x5d\xf6\x17\xe9\xd2\x57\xf5\x3a\xbd\x8f\x96\x87\x17\x95\x6f\xf6\xf7\x6b\x78\xf1\xfe\xf7\x3f\xea\x75\xb6\x54\x1b\x6e\xad\x5f\x2b\xac\x9b\x93\x52\x51\x8b\x07\x31\x2e\x4a\x1c\xfb\xd5\xe2\x68\x94\x31\x97\x9d\xe6\x62\x67\xed\x54\xd0\xaa\x4e\xd2\xcd\x69\x73\xe8\xe4\x2b\x6e\xe0\xa9\x21\xaa\x15\x1c\xc9\x18\xea\xf4\x02\x31\x53\x47\xce\x7a\x16\x55\x37\x8d\xd6\x32\xcc\x2f\xd7\xc3\x4c\xe7\x6b\xf5\x3a\x88\xa8\x1f\x62\x8c\x90\x84\x11\x06\x52\x44\x44\x0a\xc1\xc2\x18\x05\xa1\x2f\x7d\x8a\x99\xf4\x68\x2c\x23\xe0\x49\xc9\x71\x0c\x42\x19\x41\x4f\x12\x21\x03\x46\x05\xf4\x3d\x74\xd0\xeb\xfc\x51\xaf\x27\x4d\xf3\xfe\xfd\xdb\x31\xb3\xe6\x4d\x6d\xce\x04\x03\xb7\xbd\xef\xa7\xa7\x97\x69\x97\x0f\xd2\x9a\x2f\x0a\xbd\xb2\xae\x0c\xfc\x02\xd2\x15\xdc\x6c\xf4\xab\xf3\xc2\xa8\xdf\x02\x20\xce\x8b\x45\xd1\xe0\x23\xa0\x55\x37\x66\x33\xad\xb4\xb0\x72\xb9\xea\xf4\xae\x86\xfd\x85\xe6\x48\xa0\x89\xce\x55\x60\xa6\xb1\xde\xe4\xe4\xe6\xa8\xfd\xf5\xba\xa4\x9a\xdc\x6c\x3b\x9a\x93\x15\xce\x6c\x5b\x9f\x0f\x3a\x2a\x48\xf3\x96\xbe\x2b\x65\x97\x0b\x56\xa1\xdd\x55\x55\x8f\xb3\xd5\x5d\x35\x98\xe8\xe1\x9a\x7b\xd6\x34\xbd\xb0\xd7\x2a\xae\xda\x83\x56\xbf\x6c\xf5\x3b\x7e\xc1\xac\xb7\x78\xad\xa3\x6d\xeb\x91\x9b\xa1\xb1\xc8\xfd\x84\xf6\xbf\x10\xeb\x9b\xda\xff\xec\xef\xdd\xf5\x26\x54\xa5\x5a\x5d\xcc\xdd\x20\x1b\xb6\x9b\xa5\xfc\x62\xe6\x95\x62\xa7\x2a\xfc\xdd\x66\xd1\x5f\xf9\x95\xaa\xae\x0c\x7d\x91\x89\x83\x62\x7e\xde\x76\x65\xd8\xde\xfa\xa7\xaf\x9f\xb1\x57\x7b\x2f\x9e\x72\xfd\xdd\x57\x3e\x99\x0f\xa6\xd7\xfb\x0a\x7a\x1f\x76\xa6\xaf\x35\x6a\xa6\x97\xce\x80\x22\x30\xf3\xbb\x65\x77\x53\x82\x43\x17\x78\xbb\xe9\x04\xca\x92\xbe\x5d\x17\xd5\x5d\x99\x2e\x33\x5a\xa0\x3e\xc8\xd0\xc2\x5b\x0e\xfb\x10\x8e\x73\x27\xf7\x29\x33\x39\x41\x55\xde\x8b\xa7\x5c\x7d\xf7\xb5\x8f\x76\x27\xbd\x5e\x77\x37\x81\x5f\x48\xaf\xa2\xfc\x75\x16\xeb\x55\xeb\x89\x93\xf3\xee\x30\xd6\xfa\xd9\xbe\xdf\xe0\x93\x79\x77\xef\x58\x5f\xcb\xe6\x67\xd2\xfb\x68\x9d\xb7\xd0\x8e\xaa\x76\x60\xb9\x19\x6d\x93\xd6\xd8\xa2\x51\xa0\x86\xb2\xb4\x53\x70\x2b\xfa\x15\xee\x97\x07\x65\xd7\x1f\x54\xf1\x06\x04\x83\x56\x21\x83\xfd\x14\xea\x17\x62\x9e\xe5\x9b\x25\x70\x68\x8e\xec\xfb\x06\xc9\xef\x7a\x8d\x5c\x0a\x4c\x32\x56\x43\x1f\x29\x51\x2b\x9d\xf9\xe2\xdd\x24\xe4\x09\x40\x39\x44\x01\x0b\x21\x88\x65\xc4\x89\xef\x83\x20\x88\x29\xf1\x22\x89\x3c\xe4\x13\x1f\x46\x54\x30\x42\x61\x1c\x09\x88\xb1\x87\x08\xc6\x02\xb2\x98\xf9\x94\xf1\xe0\x60\x9d\xd9\xa3\x75\x56\x4a\xb9\x76\xb6\x9a\x51\x4b\x4e\xbd\x65\x94\xb3\xaa\xa9\xb9\x96\xa2\xda\x96\x5a\x6b\x6b\x0d\x8d\x34\xdb\xf9\x36\x56\xdb\xd9\x36\xb6\x51\xad\x55\x20\x05\x9d\x53\xa3\xc0\xdc\xef\xa7\x74\x7f\xf8\x50\xcf\xe7\x4d\x3b\x2d\x00\x13\xe2\xa6\x9d\x7e\x7a\x7a\x59\xd4\xe0\x61\x5e\x64\xa6\x41\xbf\xa7\x39\x6d\xb0\xea\x6e\xb6\xa6\xd9\xed\x64\x6c\xb7\xd0\xac\x35\xcc\x1d\x72\xda\xa8\x68\x08\x1e\xcf\x1a\x30\xa8\xc7\xe9\x33\xaf\xeb\xa8\x63\xdf\xf0\xba\x1e\xf4\x6e\x7e\xb8\x2b\x1b\xd5\xd2\xb8\xc6\xf4\xac\x36\x18\xe5\x15\x4d\x76\xa6\x6d\xb3\x3e\x2e\xb6\x4b\x63\x77\xd1\xdf\x2f\x53\xd3\x56\x63\x5b\x4d\xcb\x73\x81\x6a\x41\x72\xde\x7c\x7e\x9e\x51\x0a\x6c\x1a\xb4\x5c\x6b\xaf\x68\x23\x1d\x08\xb5\x0d\x8b\xcd\xd1\x7a\x59\xca\x16\xbc\x55\x77\x9b\x2a\x1b\xa3\xa5\x9d\x2e\x0e\x48\xb7\xe1\x58\x66\xb5\x91\x29\x47\x7e\x63\x41\x9b\x9a\xdd\x97\xbd\xda\xbc\x93\x77\x80\xb6\xd8\xac\xb2\x6a\x1b\xf5\xa8\xa2\xed\x37\x9d\xfc\x24\x96\x4a\xe7\x4c\x47\x28\x37\xed\xf5\x79\x5f\x6f\xdb\xeb\xb3\x3f\x7a\x67\xdf\xcf\xbc\xa5\xe0\xb5\xc9\x75\xc1\xd7\x57\x3e\x99\x0f\x7e\xff\x47\xee\x42\x9d\xe9\x5b\xc5\x6b\x19\xa4\xab\xa1\xb0\x38\x09\xac\x5a\xcd\x75\x15\x07\xa9\xc3\xc1\xb0\x16\x2c\x07\x28\xec\xed\xec\x32\x66\xc3\xb0\x95\xd3\xd3\xc7\x9d\xfe\x33\xdd\x5f\xda\xbc\xc1\x96\xb7\xf5\x27\xb9\xef\xfd\x0f\xde\xca\xfb\xdf\xff\xa8\x0f\x3f\x4b\x68\xbf\x52\x1f\x52\xdf\xf7\xa3\x30\xf6\x29\x8a\xe2\x10\x86\x34\x94\x1c\x47\x08\x51\x02\x00\x21\x1e\xe2\xbe\x80\x90\x72\x8e\x30\x24\x48\xe2\x08\xfb\x9e\xf0\x61\xec\x43\x14\x31\x1c\x78\xe8\x40\xe2\x31\x77\xee\x4e\x6f\x85\xfe\x48\x0b\x4a\xc4\xdf\xf0\x56\x9e\x9e\x5e\x96\x51\xb9\xd7\x5b\x69\x5f\x0d\xfb\x8b\x99\x93\x60\x26\xde\xf0\x56\x32\xaa\x65\xf5\x5b\x72\x5b\xc6\xad\xc2\xb4\xc2\x56\xb5\x74\x1d\x66\x66\xe1\xbe\xda\xad\x65\xdc\x0a\xa6\xbd\xf5\xa8\xbd\xb5\x33\x9d\x78\x56\x59\x38\xd9\x91\x07\x33\xfb\xf2\x62\x96\xf6\x47\xba\x49\xec\x54\x3c\x70\xcd\xaa\x59\x0f\xdb\x6d\x6f\xdf\x32\x2d\xd4\x23\xa3\x1c\x1f\xd7\xf5\x8f\xf2\x56\xce\x67\xc8\x3b\x57\xff\x7e\x2d\x32\x1b\xe0\xec\xeb\xa7\x1f\x3f\x6f\xf5\xff\x81\xf4\x7e\x89\x77\x75\xe6\xad\xdc\xb1\x82\x5d\x9a\x64\xd8\xfa\xea\x15\xec\xdf\x68\xc5\xad\x28\x7f\x9d\xc5\x7a\xd5\x7a\xa2\xe4\xbc\x3b\x8c\xb5\x7b\x12\xd3\x4c\xe7\x93\x79\x77\xef\x58\x5f\xcb\xe6\x67\xd2\xfb\x68\x9d\x2b\xfd\xac\x01\xd3\x81\xb3\x84\xbb\x59\xbd\x3c\x1f\xac\x61\xa9\xe2\x8d\x03\xe0\xd6\x3b\x4d\xad\x94\x72\xe7\x74\x14\x38\x1b\x57\x67\x83\xa2\xb6\xa1\xa3\x65\x25\xd8\xcf\x0b\x6b\x44\xbb\xbb\x28\x9b\x1e\xd3\xbc\x5a\xaf\x35\xf4\x66\xb3\xb9\x80\x3b\xa7\x34\x59\x99\xdd\x88\xc2\xcc\x57\x9f\x11\x51\xdf\x0f\x91\x4f\xa9\xa0\x0c\x53\x28\x3c\x2c\x22\xe9\x73\x22\xfd\x90\xf8\x22\x88\x42\x06\x7c\x19\xfb\xbe\xcf\x3d\xe6\x23\x81\x23\x48\xbd\x48\x0a\x4a\x04\x06\xc8\x0b\xc8\xc1\x3a\x93\xfb\xad\xf3\x43\x51\xbf\x87\xcb\x95\x5f\xb3\xbf\x04\x30\x80\x6e\xfa\x28\xcf\x4f\x2f\xcb\x89\x25\xb2\xce\xbb\xd3\x30\xbb\x57\xc3\xae\x5e\x49\xab\x92\x31\x23\x67\x54\xa8\xc2\xd9\x3c\xa5\xb6\x27\xc6\xae\xaf\xc4\xf9\xed\xdc\x68\xb5\xd3\x4b\x03\x36\x8c\x10\x95\xe3\xf6\xa0\x3a\xd9\x64\xf7\xe7\xcb\xc8\x67\x1f\xe5\xd1\xda\xd7\x5a\x03\xda\x1b\x84\xde\x2c\xdd\x19\x79\xaa\x35\xd9\xe8\xdb\x85\xb7\xcb\xa1\x98\xd7\x4a\x8d\x9a\x1e\xf6\xc7\xa8\xad\x79\x96\x22\x52\xf7\x4a\x73\x26\x6e\x75\xcf\xfb\x73\xb6\x97\x59\xad\x36\x37\xd6\x3c\x2c\xce\xbb\xe3\x61\x2a\x67\xd8\x29\x0e\x97\x8e\x9e\xa1\xf3\xe1\x5e\x5d\xd8\x8d\x5d\x7e\x5c\xc5\x8b\x60\x6d\x64\x65\x69\x64\x14\x71\xb1\xad\x4d\xa4\x44\x2b\x67\x9d\x35\x64\xa5\xb8\x5b\x50\x5f\x45\xbb\x6a\x80\x9b\x6e\x15\xac\x73\xbd\x76\x75\x41\x80\x91\xef\x2b\xb6\xdd\x39\xe2\xb7\xfc\x56\xb3\x11\xee\x47\x25\x56\x6a\x66\xfa\x6e\x9d\x96\xd7\x19\x8c\x9b\x4e\xdd\xf3\xd0\x26\xdb\x6e\xe1\xea\x28\xe7\xb4\x2b\x95\x74\x8a\x9b\x6b\x3b\xf4\x87\xd6\xb2\xa4\x6e\x27\xc2\x28\xbb\x91\x5d\xe9\x48\x50\xf5\xfa\x0d\x39\xcf\xa4\x06\xc2\x4e\xd5\xb4\xa9\xad\xab\x57\xab\x0f\xeb\x6c\xc6\x9f\x7e\x7c\xc3\xcf\x7c\x63\x35\x72\x06\x95\xc0\xba\x37\x4b\x67\x83\x7d\x2d\x33\x9f\xb2\x1a\xf9\x38\x7a\x3f\x7b\xf5\xa4\x9e\x06\xe1\x68\xa1\xe0\xf9\x97\x86\xb4\xec\x4e\xf5\xe6\x6c\x4d\xcc\x51\xa7\x5f\xb0\x32\xc2\xcf\x2f\xba\xe1\x38\x05\xfa\x8d\x7a\x17\xbb\x54\x8e\xaa\xcf\x32\x75\x6e\x2d\x93\x9f\x46\xa1\x3b\xde\xef\x29\x41\xfd\x8e\xf7\xff\x2d\x2d\xf4\x3d\xf4\x66\xb9\x5e\xff\x42\x7a\x8f\x0f\xee\x9e\xcf\x95\xd4\x16\x7e\xe1\xfc\xf8\xbb\xcd\xe7\x17\xfc\x7d\xa7\x4d\x54\x9b\x1d\x3d\xf7\x80\x54\xbf\xf5\x8e\x77\xf1\xeb\xbd\xef\x7f\xf6\x98\xdf\xff\xfe\xd7\x56\xdc\x67\xfa\x2c\xc9\x7c\xf6\x4f\xd1\x9c\x99\x33\xfe\xff\x9a\xf3\xf9\x4a\xff\x7c\x26\xbd\x8f\x2b\x6e\x50\x6f\x2c\xb2\x05\x5c\x63\xa4\x4d\xe3\x6e\x2d\x9b\x5e\x49\xbf\xbe\xdd\x44\x1e\x0d\x36\xf3\x2c\x0c\xba\x53\x10\x72\xbd\xb8\x53\xd2\x4e\xbb\xa7\xca\x1d\xaa\x16\xec\x38\x9c\x0f\xf8\x66\x67\xd7\x55\x31\x2f\x37\x37\xcb\xc5\xa0\x55\x82\x23\x2d\x2c\x6e\xdd\x51\xdd\x2f\x97\x54\xe5\xbf\xff\xfb\x77\x88\x20\x1c\xb6\x02\xda\x8f\xfa\x8d\x8e\x8b\x72\x65\x67\xbe\x09\x25\x1c\xc0\xfc\x68\xb9\x50\x50\x43\x82\x76\xb7\x8e\xea\x9a\x9d\x5e\xed\xfc\x3d\x6e\x52\xa7\xe8\x54\x16\x9e\xad\x66\x47\x7a\x1f\x18\x76\xa8\x35\x27\x30\xf6\x36\xf1\xd4\xce\xa6\x07\xdd\x82\xb3\xdd\x0c\xef\x5d\xca\xa3\x77\x2e\xe5\xc3\x98\xc6\x20\x12\x3e\xf6\x29\xc6\x61\x28\x83\xd0\x03\x71\xcc\x29\x01\x7e\x14\xe3\x48\x46\x50\x62\x26\x01\x03\xb1\xf0\x88\x0f\x08\x24\x3e\x88\x70\x00\x7d\x82\x21\xf5\xe1\xf1\xe0\x01\xdf\xbf\x94\xff\x51\x90\x17\x41\x80\x50\x74\x73\x29\xff\xf4\xf4\xb2\x06\xef\xbd\x1b\x6d\xad\x2b\x79\x7a\xb1\xd1\x96\x58\x6d\x3c\x7e\xfd\x6c\x29\xbd\xd3\x37\xdd\xa6\xcc\xb7\x2a\x8d\x56\x1e\xce\x7a\xbe\x1f\xcd\x6a\xfd\xad\xbb\xef\xae\xa9\xa1\x02\x51\x40\xeb\xda\x60\xbb\x77\x9d\x8d\xb9\x1b\xac\x2b\x62\x08\x52\x11\xb1\x48\x17\x75\x56\x93\x82\x90\x0b\xa1\xd7\x63\x63\x66\x94\xf7\xd9\xd1\x24\xbf\x28\x39\x5e\x31\x70\x7f\x2a\x28\xec\x62\xbe\xdc\x5c\xda\x26\x3f\x66\x0f\xc7\x11\x61\xe9\xd3\xd7\x9b\xa7\x1f\x3f\xd1\x14\x7e\x1c\xbd\x5f\xb2\x14\x3f\xdb\x68\xbb\xc3\x14\xa0\x90\xf7\xe7\x5f\x6d\x0a\xfe\x46\xa6\x4b\x51\xfe\x3a\xd7\xe1\xd5\x8d\xb6\x4d\x72\xde\x1d\xc6\x7a\x79\xe6\xb0\xba\x9f\xcc\xbb\x7b\xc7\xfa\x5a\x36\x3f\x93\xde\x47\xb3\x2f\xba\xc2\x68\xac\xab\x43\x90\x6b\x6c\x97\xde\x64\x84\xf0\x6c\x30\x11\x4d\x8b\xf8\xa9\x9a\xb2\xb4\xd5\xe5\x1c\x4c\xad\x00\x69\x42\x0d\xa6\x45\x60\x9b\xa1\x3d\x5e\x65\xcb\x46\x38\x29\xce\xd4\xb5\xed\xdb\x19\xa8\xef\x0a\xbd\xec\x62\x43\x67\x99\x79\xb6\x8e\x7a\x38\x9f\xfb\xea\xa0\xbd\x40\x78\x48\xc4\x3e\xa2\x21\xe1\x82\xc4\x98\x7b\xdc\x03\x5c\x44\x30\x8e\xa2\x18\x44\x3e\x06\x81\xc7\x48\x24\x25\xe1\xc7\x04\x0e\x2f\x20\x91\x07\x18\x0f\x02\x86\x20\x61\xc7\x8d\x36\xf4\x14\x16\xe0\xd6\x54\xab\x50\x71\x99\xe6\x16\x5b\x65\xdb\x71\x98\x69\xdb\xe5\x56\xd6\x6a\x94\x32\x4d\xc3\xb1\x9d\x5a\xdb\x68\x34\x9b\xa4\xd8\x54\xaa\x8d\x4c\xd9\xd1\x69\xd5\x29\x2a\xd9\xef\xa7\x0a\xe4\x00\x41\xf2\x23\x3b\x8d\x81\xa0\x37\x0f\xc4\x8e\x4f\x8f\xc9\x73\x17\x05\xee\x1f\xe6\x45\x56\xeb\x5a\x8d\xac\xde\x73\x5b\xe1\x9e\xee\xc5\x90\xe3\x56\x7e\x37\xaf\xa0\x6a\x49\xd0\x76\xb5\x09\x57\xc5\x85\x5a\xaa\xac\x46\xf1\xe2\x68\xa2\x1f\xc2\x02\x8e\xdf\xcc\x5f\x09\xc0\x99\x9d\x3e\x86\x1a\xe5\xfc\x51\x6e\xd9\x76\xb4\x8b\xe7\x99\xac\xb2\xb1\xce\x53\x55\x6b\xac\x9d\xda\x0e\x8e\x8f\xb1\xb6\x35\x4b\x3a\x97\x9b\x7c\xad\xea\xb6\xa3\xb9\x6d\xc3\xbd\xe5\x0e\xa3\xa9\xb5\x58\x75\x27\x66\x8e\xae\xf5\x31\xea\xa8\x0b\x7d\x94\x9d\x36\xe3\x4e\x59\x34\x0a\x2a\xce\x54\x8d\x51\x39\x35\x8e\xe4\x62\x5a\x6f\x0d\x1b\xba\xd5\xd7\x56\xdd\xb2\x3e\xb1\xbb\x43\xd8\x9d\x5b\xea\xcf\x1d\xfb\x17\xce\x05\xf9\xa6\x3d\x3e\xfb\x23\xab\xa6\x6d\xeb\x56\x64\x76\x43\x6c\x8f\xed\x5d\x6b\x1d\x06\x7e\x61\x99\x6d\x6b\x78\x3f\x1c\xe6\xfc\x26\x59\x6d\x0c\xa8\x3e\xf5\xed\xb8\x06\xe9\xce\x4e\xbc\x7b\x70\xa3\x5e\xe4\xa0\xfc\xc0\xbe\x7e\xdc\xfb\xf3\x49\xde\x7f\xa6\x43\xf7\xc7\xf6\x83\x4e\xd8\x1a\x4e\xae\xb2\x25\xa3\x1c\x0e\x52\x41\xda\x8c\x24\xdc\x2e\x66\xa0\x34\x70\xe2\x72\xb3\xde\x58\xfa\x3d\xae\xf4\xeb\xc5\xe9\x98\x3f\xb0\xbe\xb1\x72\x9b\x70\x68\x3d\xf3\xbe\xb2\xb5\xfa\x16\xb8\xdd\x5f\x2b\x49\x7f\xaf\x65\x4f\xb3\x0e\x72\x77\xf6\x82\x57\xec\xc2\xfe\xec\xf1\x3b\xfb\x74\xb0\x51\x86\x75\xa2\xf6\xe8\x9e\xbe\x4c\x5c\x7c\x5b\xcf\x83\xfb\xde\x9f\x9f\x24\x7b\xff\xa3\xde\xfe\xac\xc9\xf7\x95\x7a\x1b\x86\x5c\x60\x1c\x90\xd8\xf3\x7c\x20\x22\x86\x18\x90\x5e\x10\x63\x0e\x49\x08\x7d\xcf\x8f\x10\x67\x08\x7a\xc8\xc7\x48\x44\x61\x8c\x39\x61\x34\x92\xd2\xf3\x62\x2c\x64\xe0\xf9\x07\xbd\x0d\x3f\x52\x6f\xff\xd0\xbf\x22\x98\xa3\xdb\x7a\xfb\xf0\xf4\xa8\xb7\x2f\x6e\x13\xb9\x57\x6f\xe7\xae\x04\xe0\x27\xf5\xb6\xb6\xb3\xf6\x67\x02\x74\xa6\xb7\x8d\x26\xd9\xcd\x73\xe1\x80\xb1\xb8\x93\xcd\xf6\xe6\xdc\xcd\x29\x8e\x16\xa2\xe1\xb0\xbc\xf2\xf7\xdb\x74\xcf\x33\x03\x0b\x6d\x06\x39\x3c\x59\xcd\xcc\x4a\x29\xa5\xec\x7b\x3b\x34\x6f\x2c\x0b\x54\x99\xec\xa6\xdd\xc9\xa0\xb7\x59\xb8\xad\xb5\x5e\x63\xf5\x9c\xb4\xba\xe1\xb8\xae\x64\x2b\x1f\xa7\xb7\xad\xb3\xb5\x4b\x02\xbd\xd9\xcb\x9e\x78\xf7\xc0\x94\x77\xea\xcd\x0f\x7c\x7f\x22\xbb\x71\xa6\xe3\xb6\xc7\xf6\x27\xeb\x6d\xeb\xe4\x57\xdd\xaf\xb7\x1d\x63\x7f\x6e\xf7\x5e\xd1\xdb\x67\xa7\x80\x49\xf4\xa6\x79\x46\xed\x43\x60\xce\x0b\x2e\xbe\xad\xb7\x3f\xd0\x6e\xbc\xe7\xfd\x8f\x7a\xfb\xb3\x26\xdf\x57\xea\x6d\x06\x59\xc0\x80\x04\x84\x47\xb1\x88\x65\xe0\x49\x20\x3c\xc2\x0f\xff\x3c\xe2\xfb\x00\x0a\x42\x64\x40\x99\xa4\x44\x7a\x21\x0a\x3c\x06\xa8\x04\x9e\xe7\x73\x82\x18\x8f\xc4\x41\x6f\x83\x8f\xd4\xdb\x3f\x2a\x56\x41\x28\xc7\x80\xde\xd4\xdb\x4f\x4f\x2f\xaf\x6e\xba\x57\x6f\x5f\x4f\xf2\x1b\x7a\xfb\xb5\x82\x27\xda\x33\x5e\x45\x71\xab\xed\x92\xdd\x35\x55\x67\xd3\x37\x3b\x8a\x29\xfd\x48\xc3\xed\x72\x5a\xc7\x03\xd7\xec\xba\xa3\x06\x9c\xaa\xa3\x1d\x0f\x44\x7b\x8e\x16\x85\xb0\x50\x1e\x79\xc5\x31\x89\x47\x0a\x9d\x79\xc5\xd4\xb0\x62\x15\x36\xe5\x5a\x77\xd9\xdf\x0c\xda\xc2\xd4\xb7\x76\x3d\x14\x79\x65\xf0\x71\xba\xfa\x4c\xb7\x25\xd1\x95\xc1\x89\x5f\x0f\xff\xbf\x08\xce\xf9\x81\xae\xfe\xb8\xf7\x6b\x49\xde\x7f\x76\xdc\x7a\xbf\xae\x7e\xee\x4b\x05\x96\xfa\x01\xb9\x7a\x9f\xfa\x71\xf8\x9f\xa2\x87\x5f\x16\x34\x7a\x5b\x0f\xff\x45\x76\xe0\xd5\x3d\xa6\xed\x7d\xb4\x3c\x14\xfa\xb0\x4e\xbc\xfd\x0b\x79\xf1\x9e\xf7\x3f\xda\xa4\x4c\x37\x37\x00\x29\x6d\x60\xda\xaa\x35\x52\x94\x31\x5c\x12\x27\x1c\x70\x11\x47\xd5\xce\x28\xd7\x6b\xb7\x9a\x83\x82\x5f\x5c\xee\xb7\xa3\xb5\xb7\x99\x82\x09\x6b\x4f\x56\x71\x37\xe5\x66\x47\xd3\xc9\x9a\x35\x94\xcd\x5c\xa1\x85\x3c\xb2\xd5\xea\x78\x33\x88\x35\x59\xc5\x1b\xf7\xab\x0b\x8d\xc8\x38\x8e\x19\x94\x90\x71\xc8\x62\x1f\x51\x0a\x00\xc1\xb1\x17\x48\x26\xbc\x80\x05\x10\x0b\x80\xbc\x98\x42\xce\x3c\x08\xe2\x00\x49\x08\x44\x1c\xc4\x01\x21\x34\x8a\x29\x3c\x2c\xea\x89\xfc\x40\x9b\x04\xe4\x8f\x6c\x12\x47\xf0\x76\x01\xa5\xe7\xa7\x97\x77\x00\xde\x6b\x93\xde\x08\xd9\x49\xe6\x4b\x6c\x0b\x3d\xdd\x75\x4b\x45\xb3\xd7\xc4\x73\x9a\x1a\xa8\xe6\x48\xac\x02\x6f\xd2\xe0\x99\x60\xae\x8d\x2b\xad\x9c\x8f\x17\xb0\xba\xab\xee\xea\xbe\x32\xc8\x0e\x3d\x75\xad\xa5\xaa\x85\x8d\xd5\x9e\x94\xea\xb1\x3f\xa8\xd4\xf3\xf3\xc9\x6a\xd7\x28\xec\x60\x7b\x5a\x8f\x82\x20\xb3\x9b\x65\x3f\x70\x0f\xc8\x3a\xfb\x6a\x12\xfb\x00\x5f\x9f\x4d\x67\x9f\x1f\xd8\xa7\x8f\x7b\x7f\xb2\xd4\x8f\x93\x66\xf8\x40\x1d\x97\x28\x51\xff\xa3\xdf\xff\x92\x1f\x6f\x9f\x69\x7c\xa6\x2f\xf5\x83\x73\x8b\x24\xfd\x7d\x78\x99\xf5\x56\x8f\x3e\x95\xdf\x0f\xe9\x35\xef\x7f\xff\x53\xba\xe1\x27\x29\x86\xaf\xb4\x29\x11\x61\x40\x42\x01\x38\x85\x11\xe7\x00\x11\xc6\x3c\x21\x08\x15\x94\x87\x31\xc1\x11\x09\x21\x25\x51\x20\x88\xcf\x7c\x2f\x64\x28\x88\x28\xe0\x71\x04\x51\x0c\x43\x2f\x3e\xd6\x53\x39\xd8\x14\xf4\x61\x7e\x0e\xf8\xb1\x4d\xc1\x6f\xec\x4f\x1d\x9e\x92\xef\xd7\x97\xc1\xde\x6b\x53\xde\x28\xca\xf7\xaa\x9f\xf3\x68\x53\xea\xa8\xb4\x3f\x5b\xbc\x9f\xd9\x94\xfe\xb6\x33\x76\xaa\x19\xd5\x03\x63\x18\xc5\xed\x49\xb0\x9d\x6a\xfd\x56\x64\x38\x15\xba\xd0\x5c\xa7\x11\xca\x78\xb2\x59\x2d\x27\x68\x60\x6f\x68\x94\xdb\x74\x1a\xe3\x3d\x2b\xcf\x0b\xe6\x46\xad\x2e\x69\x51\xec\x86\xa3\x66\x4f\x71\x5a\x0d\x03\xb7\x77\x71\x0f\xef\x9c\xc2\x2c\xa3\xfc\x92\x36\x25\xf3\xfa\x3c\xfa\x32\x9b\xa2\x26\x79\xff\xe7\xd8\x14\x43\x79\x9f\x4e\xff\x68\x9b\x62\x28\xef\xdb\x4b\x52\x94\x4f\xf6\xf9\x3e\xc1\x4f\x49\xaa\xd3\x95\x0f\xe2\xf7\x43\xe1\xb0\xc4\x36\xe5\xb3\x14\xc3\x57\xda\x14\x22\x08\xa4\x41\x08\xe2\xd0\x93\x7e\x20\xbd\xc8\x87\x31\xf0\x09\x94\x7e\xec\x23\x29\x79\xcc\x3d\xe4\x79\xd0\x87\x51\x8c\x22\x0a\x3d\xc0\x00\x0a\x18\x84\x80\xc4\x01\xc2\x41\xf0\x68\x53\xf0\x87\xd9\x94\x1f\xa5\xb0\x13\x8e\x08\x66\x6f\xd8\x94\x87\xa7\x97\xb7\x82\xdf\x6b\x53\xde\x28\x60\x7d\x66\x53\x6a\x97\xcf\xb3\x68\x08\x82\x5d\x66\xec\xe3\x4a\x27\xc0\x99\xae\x8b\x1a\x7b\xe3\x5c\x9e\xce\x6c\x4c\x69\xe4\x76\x7a\x63\xb7\xdb\x4a\xb1\x86\xb2\x18\x42\x73\x35\x8a\xb7\x83\x0c\xe5\x3b\x54\xd4\xe7\x5e\x33\x5b\x1f\x54\x53\x85\xec\xb6\xd9\x14\x43\x3a\x8d\x9d\x46\xaf\xb8\xdd\x72\x53\xd0\xc2\xbc\xdc\x00\xb3\x92\xea\x92\x6a\xec\x2d\x3a\xb3\x6d\x0e\xe4\x54\xac\xcd\xdd\x20\x52\x3f\xf2\x0c\xe4\xa3\x75\xfc\x7b\xcf\x40\x3e\xee\xfd\xd9\x24\xef\xff\x1c\x1b\x63\x29\x09\xce\x0b\xfe\xc2\xbd\x21\x45\xf9\x08\x1b\x73\xda\x61\x96\xd3\x50\xb7\x3a\x6d\x24\x81\xa1\x97\x36\x6e\xb3\x34\x0c\x76\x17\xe3\xf0\x09\x36\x27\xa9\xce\x57\x3e\x81\xff\xef\x79\xff\xa3\xcd\xf9\x2c\x45\xf1\xa5\x7e\x8c\x2f\xa8\x60\x81\x84\x9c\x05\x24\x88\x51\x24\x18\xf1\x11\x45\x50\x12\xe1\x49\x8e\x42\x9f\x22\x4e\xc2\x08\x11\xc6\x31\x63\x92\x30\x1c\x81\x80\x0b\x44\x82\x28\x02\xf4\xa0\xde\x89\xb8\x3f\x7a\xf9\x87\xa7\x34\x02\x51\x71\xb3\xf4\xee\xf3\xd3\x27\xdb\x45\x30\xf8\x80\xe8\xe5\xe6\xd5\xb0\xbf\x58\x81\x26\xd0\x7e\x37\xa2\x97\x55\xc5\x2a\x8f\x59\x9e\xf4\x57\x8b\xce\x34\xae\x4d\xf4\xcd\x78\xa9\x57\x06\xae\x91\xdd\x1a\xe9\xc6\x78\xa7\xa7\x67\x46\x2f\xe5\x87\x56\x73\xdf\x83\x0e\x6b\x0e\x37\xe3\x72\x6a\x67\x38\x9d\x11\x4a\x8d\xca\x5e\x33\x60\xfb\xc6\x6a\xdb\x2b\xf6\xf5\xe1\x70\x9f\x89\x2a\xe9\x6d\x61\x5d\x29\x7d\x54\xf4\xf2\xf9\x0c\x79\x67\x34\x70\x2c\xe2\x49\x7c\x16\xab\xd8\x38\xfd\xf8\x79\xd1\xc0\x1f\x48\xef\x97\x44\x5b\x9f\x59\xb4\x3b\x22\x5a\xd3\xdb\x54\x57\x7e\x75\x44\xeb\xdf\x28\x02\x57\x51\xfe\xba\x9d\xb7\x57\x4f\x96\xd6\xc9\x79\x77\x18\xeb\xf4\x49\xa8\x32\xf5\x4f\xe6\xdd\xbd\x63\x7d\x2d\x9b\x9f\x49\xef\xa3\x75\xee\x64\xb3\xd3\x54\x77\x65\xf0\xb9\x51\x68\x81\x59\x46\x98\xbc\x0a\xcc\xbc\xaa\x88\x9a\x0d\xdb\xa2\x9b\x66\x3d\x63\x3d\xc2\x4e\x6e\x41\x96\xf5\xd4\x70\x1a\x98\xfb\xf5\xa2\xa7\x11\x73\xb9\x9e\xf6\x47\xc3\x71\x79\x01\xfd\x85\xdb\x23\x5b\xda\x0e\x36\xad\x81\x2d\x6a\x73\xf0\xd5\xd1\x14\x91\x27\x71\x14\x87\x22\x40\x31\x89\x08\x0d\x00\x86\x22\x60\x32\x0a\x24\x15\x0c\x61\x0f\x44\x04\x73\x12\x13\x10\x52\x26\xa3\x28\x80\x88\x84\x04\x07\xc2\xa3\x24\x64\xe8\xc1\x3a\x7f\x40\xc9\xd1\x1f\xfa\x81\x92\x12\x78\x3b\xb7\xe8\xf0\xf4\x78\x5e\x05\xa0\x60\x98\x30\x0e\xc0\x07\x94\x1c\x6d\x5c\x0d\xfb\x99\x75\x3e\x33\xb2\x8d\x27\x4d\x9c\x51\x32\x75\x7d\xd5\x72\x53\x96\xd3\x69\xa6\x37\xd9\x35\x4d\x95\xb2\x8d\xae\x8c\x37\x64\x14\x2d\xf6\xdb\xa8\x55\x96\x42\xd7\x2a\x71\xa7\xd5\x88\xd4\x36\x8f\xca\xbe\x6a\xa0\xc9\xbc\x96\xaf\x97\x94\x74\xad\xc0\xf4\x86\x4c\xaf\x9c\x46\x6d\x6b\x54\x2a\x4d\x63\x31\x81\x95\xc9\x56\xcf\xfc\x9c\x5f\x67\x9e\x7e\xf9\xb0\xe2\x7e\x97\x15\x31\xe6\x5a\x5f\x75\x37\x0f\x89\x34\xd9\x3e\x0e\x3b\x5a\x65\x0a\x4b\xb4\x8e\xe3\x4c\xad\xac\x6e\xd3\xe3\x39\x6d\x2d\x7b\xea\xa8\x64\xa2\x89\x65\xb6\xad\x6d\xca\x72\x0b\xd8\xdc\x3c\x7c\x35\x0e\xa2\xe2\xf9\xcc\x38\xd1\x76\xb2\xf0\xc5\xa4\x85\x75\x7a\x2b\xbf\x1d\xda\xeb\xb3\xda\x9f\x67\x53\xfb\xf3\x2c\xe6\x07\xd2\xfb\x25\x2b\x92\xb3\x58\x90\xc4\x5a\xbf\x40\x97\x43\x90\x92\xa7\xda\x9f\x5f\xa3\xf5\xff\x46\x56\xea\xc8\xdf\xb3\x5a\xdd\xef\x99\x2b\xc5\x7c\x6f\xad\x72\x2d\x9d\x3a\x0e\x6a\xb1\xa2\x5c\x8e\x69\xe5\xbd\x78\x49\xf8\xfb\x3e\x7a\xe7\x9e\x1e\x0d\x82\x60\xfc\x35\xf4\xbe\xba\x82\x39\xe3\x75\x12\x59\x4e\x9f\x16\x52\x99\x6b\xbd\xf9\x6b\xc9\xf2\xcb\xb9\xf7\x99\xf4\x3e\xc5\xde\x7c\x92\xc1\xfa\xd2\x4b\x7e\x10\xe0\x61\x44\x7d\x4e\x11\xc1\x11\xf0\x01\x43\x01\x16\x18\xc7\x54\x70\x80\x99\xcf\x23\x19\x33\x42\x28\xf6\x23\x22\xe3\x98\x82\x18\xc7\x38\x0e\x03\x4e\x21\x8b\x02\xe6\x1f\x56\x30\x4f\x65\x59\xb3\x55\x8a\x9b\x8a\x66\x14\xca\x75\xdc\x2e\x94\x30\x51\x6b\xba\xd2\xd4\xb9\xde\x60\x05\x86\xd5\x8c\x59\xad\x3b\xcd\x7a\x36\x93\xab\x59\x2e\xaf\x56\x2b\x05\x5c\xb3\x0b\xe5\xda\xf7\xdf\xbf\x41\x89\x11\xc7\x14\x09\xfc\xc3\xb5\x0c\x05\x8c\xc9\x9b\xe7\xa4\xcf\x4f\xa1\xe4\x94\x09\x22\x25\x87\xcf\x7b\xda\x65\x3b\x44\x4a\x55\x1d\xd7\xf1\xd0\x09\x45\xce\x20\x45\x3d\x15\xad\x87\x11\x32\x0a\x2e\x18\x7b\x9d\xcd\x70\xb0\xd7\xc9\xb6\x33\x7f\x98\xb3\xc7\xb5\x8c\x7a\x0c\x15\x78\x23\xf6\xa6\x7e\x6a\xbf\x13\xff\x46\x29\xd4\x9f\xf9\x64\x9e\x75\x82\xa6\x94\x07\xf9\xb2\xed\x94\x33\xd9\x5a\x85\x8f\x9b\xa8\x3d\x4e\xf9\xc3\x05\xb2\xb3\xf5\xc8\x1f\xa0\xf4\x00\xa7\x3b\x33\xbd\x50\x11\x91\x5b\xce\x2d\xb2\x6c\x9c\x89\xb4\xf5\xce\xca\x0a\x2a\xd6\x13\x9a\xf1\xfc\x7e\x65\x93\x91\xbd\x71\x5f\xc9\x18\x96\x88\x16\xd9\x2e\xf7\xb5\x81\xfa\x13\x6b\xa6\xf3\xdc\x86\xdb\xeb\x96\xb3\xbd\x63\x22\xb1\x9b\xd1\x0a\xa1\x13\x35\x4a\x78\x53\xef\x77\x16\x31\x65\xa9\x06\x77\x3b\xd3\x7e\x2d\x9c\x65\xd5\xa6\x63\xc5\xfd\xbc\xba\xdc\x05\xea\x76\x32\xdf\xac\xb6\x76\x7a\x7c\x1a\x83\x1b\x9f\x1f\xac\x43\x3e\xee\xfd\xf7\x5e\xb6\xf1\x39\x76\xef\xfc\xf3\xb6\x6e\xfd\x9b\xd8\xdd\x57\xed\xd8\xf2\x1e\xda\x9f\x04\xb5\xf8\xd6\xce\xc3\x97\xf1\xee\x3d\xef\x7f\xba\x74\x69\x9a\xe9\xf7\xc1\xbe\x53\x01\x83\x32\x85\xcb\x51\x3b\x3d\xa2\x7e\xa9\xbf\x81\xfa\x88\x96\xd6\xb4\x94\x26\x85\xee\x6e\x60\xeb\xa3\x6c\xd7\x57\x52\xd3\x4d\xab\x5b\x14\x7d\x25\x5d\x8e\x8b\xac\x5c\x69\x8e\x08\xb0\x94\xd8\x9d\x92\x8d\x52\xcb\xda\xfa\x5c\x21\x11\xda\x9a\x5f\x5d\xee\x36\x44\x24\x26\x82\xf9\x21\x47\x28\x0e\xa1\xe0\xd4\x17\x04\x0b\x2c\x23\x21\x80\x1f\x46\x91\x87\x11\x89\x10\x0d\x7d\x0e\x98\x87\x98\x17\xd3\x88\x84\x9e\x27\x02\x0a\x38\x8c\x9e\xec\x0c\xba\xd3\x53\xfe\x51\x14\x0e\x05\x4c\xd0\x9b\x27\xa6\xcf\x4f\x1f\xac\x0b\x05\x58\x7c\x84\xa7\x7c\x5d\x61\xe7\x75\xeb\xf2\x4e\xfc\x7b\xac\xcb\x59\x79\x5c\xd7\x00\x8e\x55\x69\x34\xed\xf5\x58\x45\x05\xdb\xcf\x4e\xbb\xd2\xda\xed\x69\xdd\x5a\x65\xaa\x86\xbb\x44\x6e\x25\x5c\x0e\x6d\x57\x25\x75\xdd\x1b\xb9\x63\x7d\x61\x75\xba\x53\xc3\x8a\xbd\x1a\xb7\x9a\xa1\xbe\xca\xbb\x02\xa6\x72\x99\xc9\xbe\xbc\xf8\xff\xc9\x3b\x8f\xe5\xc6\x75\xe5\xe1\xbf\xca\x7f\x77\x17\xba\x55\x42\x0e\x8b\x6f\x41\x31\x29\x4b\x54\xa6\x76\x24\x08\x2a\xe7\xac\xa7\xff\x6a\x24\xdb\xe2\xf1\x38\x29\xd8\x33\xb7\x0e\x16\xa7\x8e\x07\x92\x1a\x04\xc0\xfe\x75\x03\x8d\x46\x3d\x95\xce\xba\xb3\xbe\x67\x7d\x07\x5d\x6e\xf1\x32\x13\xc7\x89\x1a\x6f\x77\xc5\xd7\xe9\x72\xa7\xfc\x77\xb2\x2c\xdd\x42\x97\x07\x5a\xfa\xc9\xf2\x65\x0d\xf9\x37\x7b\x1a\x9f\xd1\xe5\x86\xb6\xa7\x93\x97\x71\xbf\xb3\xf2\xfc\x63\x7d\x77\x8d\xfc\x27\xba\xb4\xcd\xb2\x7d\xb4\x9d\xd6\x90\xd3\xdd\x7a\x30\x44\x3b\xe6\xc7\x8d\xd2\x2a\xd5\xb2\x8a\xbd\x66\xdd\x2d\x46\x13\x3b\x1b\x76\x1b\xc8\xd8\x38\x19\x34\x9f\xe4\xf7\xdc\xca\xe5\x82\xba\x95\x45\xa3\xcd\xd1\x99\xd6\x78\x7f\x52\x2d\xc7\x7d\x2f\x28\x1d\x97\xf6\x76\xbb\xdf\x2f\x72\x4d\xe3\x87\xd3\xb5\xd2\x90\x20\xc5\x39\x20\x28\x06\x24\x8c\x39\x64\x8c\xca\x00\x50\xcd\xd5\xe9\xe6\x52\x80\x83\x18\x60\x11\xf0\x28\xe0\x34\x84\x20\x14\x14\x0b\x0e\xb8\x92\x71\x0c\x39\x8a\x7f\xd1\xe5\xfe\x64\xea\xf0\xb3\x73\x03\x14\x0a\xce\xdf\xbd\xc8\xef\x57\xad\xb8\x38\x43\x18\x11\xf8\x80\x5c\xea\xaf\x15\xdb\x6f\x30\xb8\xde\x2c\xfe\xc7\x6c\x4a\x6e\x92\xba\xe6\xb8\xa6\xab\xca\xb0\xf7\x5e\xba\x5d\x58\xce\x66\x38\x8d\xa3\x58\xf5\xab\xe9\x43\x4e\x34\x6a\xd6\x72\x39\x5c\xa7\x55\xbf\x2b\x70\xb3\x38\x68\x28\x4a\xc6\x74\xa7\x8e\xd0\x18\x85\xc5\x80\x99\x46\x30\x8f\xea\xee\xbc\xd9\xee\x8c\xe8\x68\xd5\x58\x58\x9d\xe2\x94\x18\x5f\xb9\x7f\xfe\x1f\xb3\xfa\x5d\x58\x24\x3e\x7f\x85\xb2\x2e\x93\x62\x50\xca\x55\xe2\x64\x4a\x83\xfa\x9b\x92\x3f\x83\xc5\xe3\xe4\xdf\x04\xab\xc4\x26\xe6\x8d\x0a\x0f\xf7\xd6\xb3\x5d\x8f\xde\xaf\xf0\xfe\xa0\xc2\x35\x8c\x3f\xe7\x4e\xbc\x09\x9f\xd5\x6d\x7d\xf1\x3c\x16\xe6\xc5\x70\xc8\xdc\x74\xff\xff\x03\xe7\xc2\x0d\xf7\xff\xf7\x7b\xf3\x66\x67\x88\x8d\x4c\xa9\x59\x85\x83\x05\x2b\x94\xd3\x12\x77\x70\xae\x91\x16\x83\xaa\x0d\x3c\xc6\x08\x8f\x71\xae\x1d\x97\xa1\x49\x46\xb8\xa2\xf3\x5a\x65\x4b\xd2\xcb\xbb\x07\xb4\xe9\xf5\xdc\x45\xa7\xd9\x5f\xb4\x9c\x31\xad\x74\x8b\x36\xeb\xc1\x03\x4d\x19\x3f\x7d\xff\xbf\x06\x9c\xe3\x08\xf0\x20\x0c\x10\x8e\x20\xd4\x2c\x00\x2c\x04\x08\x32\x81\x90\x24\xa1\x86\xb1\x8c\x11\x40\x01\x92\x88\x09\xc4\x01\x42\x14\x4b\xc6\x90\xd2\x48\xf1\xf8\x14\x16\xfa\x9c\x2b\xdc\xcc\x56\x3b\x6e\xcb\x2a\x54\x1d\x5a\x68\x10\xb3\x6c\x34\x78\x87\xf3\x4a\xc7\xef\x72\xbf\x65\x93\x7c\xb6\xe0\x58\xcd\xac\xe9\x9a\xad\xb6\x59\x24\x05\x52\xf5\x18\x2f\x14\xba\xbf\xa8\x21\x08\x13\x98\x4a\xcc\xd1\xa7\x18\x42\x12\xd0\x77\x8f\x54\xbf\xd4\x42\x21\x24\x17\x94\x51\x88\x5e\x8e\xaf\xe5\x38\x9f\x2c\xca\x8d\x83\x6c\x55\x7b\x93\xde\x34\x95\x4e\x6f\xb6\xc3\xaa\x68\xe5\xf7\x79\xe8\x64\x3d\x32\x34\x97\x7e\x3d\x55\x20\xa9\xec\x69\x29\xf7\xbc\x84\x76\x9a\xe2\x1f\x2c\xa1\x9d\xad\xe8\x9b\xb6\x75\xfc\xe5\x90\x68\x71\x4e\x69\x34\xcc\xf3\x5d\x66\x59\x9b\xaf\x96\x6a\xba\xc8\x78\xed\xe1\xe1\xb8\xdb\xb6\x8e\x68\x4b\x9b\x79\xca\x5c\x06\x72\xfd\xde\x2a\x68\x7b\x4e\x3d\x4e\xf1\xd9\x84\x30\x54\x68\xcc\x54\x2a\x9b\x47\x3c\x28\xb6\x2a\x9e\xc0\x91\xdb\x87\x83\xed\x3c\xd5\xca\x6d\x6a\x76\x7e\x91\xae\x67\x76\x5f\xda\x3e\x4c\x4c\xfc\x4b\xa8\xf6\x87\xdb\x79\x89\x8e\x18\x6e\x37\xc1\x0c\x56\x8b\xb0\x99\x32\x03\x33\xe6\xe9\x14\x4b\x95\xd2\xfb\xe6\xd4\x9e\x36\x9b\x91\x35\x28\x15\xd6\xfd\x22\x79\x7e\xce\xc4\xad\x42\xe6\xea\xed\xf7\xed\x54\x3e\x61\xd1\xe3\xe4\xdf\xb4\x2c\x96\xd8\x6e\x5b\x26\xaa\xae\xd4\x3f\xd3\x12\x36\x12\x29\xe4\x6f\xd3\x7f\x7f\x50\xff\xbe\xd6\xff\x66\x25\x45\x17\xc3\xa6\xd8\xb6\x1a\x24\x3f\xcb\xa7\xb7\x69\xbe\x24\xc7\xb4\x53\x57\xf5\xa8\x56\x03\x95\xdc\x6e\x81\xec\xed\x60\x53\xed\xf3\x93\xd6\xbd\xcc\xb5\xc2\xce\xb8\x61\x59\x30\xd1\xde\x2b\xde\xeb\x37\x18\xb6\xbc\xef\x19\xce\x0d\x2c\xdc\x7e\x1b\xd5\x03\xfb\xf0\x1a\xf9\xcf\xe9\x9c\xbe\x49\xf1\xfc\xe8\x11\x6c\x42\x43\x06\x39\x8c\x34\x27\x3c\x08\x31\xc2\x21\x56\x51\x40\x11\x92\x40\x62\x1c\xc5\x58\xea\x28\xe2\x80\xc1\x98\x69\xc4\x00\x67\x88\x31\xac\x63\x45\x61\xa8\x54\x08\x7e\x31\xec\xfe\x24\xb9\x50\x7c\x46\x2e\x02\x31\x7f\x37\xcc\xf4\xa5\xf6\x99\x85\x5c\xa0\x07\x84\x99\xbe\xb6\xf6\x7f\xd3\x78\x37\x68\xd0\xf7\x6e\xa3\x72\xc2\x3a\x52\x74\xb9\xf4\xcb\xee\x6a\x5c\x6e\xad\xc6\x8d\x6c\x56\x0c\xc5\x1e\xf4\x7a\x7a\x07\x75\x36\x5b\x69\x36\xca\xc1\xb0\x54\x3d\x08\xd7\x9f\x52\x54\xab\xef\x6a\x53\xb5\xdb\x6d\xb7\x50\x0f\xed\xd8\x48\xf5\xd2\x93\x46\xa7\x34\xef\x2c\x33\x15\x41\xb8\x49\x58\x61\xf6\x30\x0f\xaa\x70\x5b\x50\xc7\x8b\x07\x93\xba\x7c\xbd\xf6\xa6\xe4\x4f\xa8\xf1\x40\xf9\x37\x79\x70\x09\x0f\xea\x0e\x6a\xfd\xa2\x86\x75\x2f\xb5\xfe\x20\x35\x0d\xe3\xcf\x69\xfc\x37\x3d\xa8\xc9\xed\x7d\xf1\x6b\x2c\x9c\x8b\x39\x99\xb9\x69\x63\xed\x81\x73\xe1\x1a\xf9\x4f\xf4\xa9\xb5\xc1\x7a\x5a\x09\x18\xb2\x6a\xcb\x7c\xa3\x15\xe6\x9b\xfb\x7d\x3a\x97\x2e\x45\xb9\x5c\x76\x55\xee\xf4\xf7\xc7\xb1\x7d\x6c\xcf\x8e\x96\xd8\x66\x26\xf9\x54\x34\x6a\xae\xec\x2e\x2e\x95\x8a\x5c\x76\x66\xfb\xec\xae\x3a\xab\xd2\x11\x3c\x16\x5a\x6c\xd7\xd8\x56\x2a\xbb\x4d\x65\xb0\xf8\x69\x0f\x2a\x62\x5c\xc5\x21\xe2\x30\x10\x42\x6a\x2e\x28\x89\xe3\x88\xc1\x10\x08\x1d\xa8\x48\x73\x16\x51\xa6\x39\x15\x84\xb1\x58\x61\x1e\x08\xad\x15\x8a\x70\x40\x80\x8e\x45\x08\xc9\x2f\xfa\x3c\x27\x81\xb5\x48\xbd\x54\xb1\x71\xab\x5a\x77\x78\xb7\x86\xcd\x86\xed\xe1\x2a\x6d\x96\x1b\x99\x92\x9d\xb7\x0c\xe4\x16\x3b\x8d\x6c\x8d\x97\x4a\x46\xcd\x28\x17\x0a\x79\xab\xcb\x6b\x55\xd7\xf9\x45\x0d\x86\x11\x10\x9c\x72\x44\x3f\x3b\xee\x40\x29\x92\xec\x7d\x0f\xea\xb9\x16\x0a\x80\x85\x60\x18\x50\xf4\xb2\x4d\x54\x1d\x4d\x2a\xf9\xcd\x92\x3a\xe9\x49\x65\xdf\xc8\x5b\x61\x0a\x84\xa5\xa2\x99\x77\xad\xda\x18\x4f\x74\x15\x95\x32\xb6\xd5\x2a\xd4\xab\xd5\xd3\xbc\x38\x7b\x50\xbe\xf1\x71\x52\xaa\xf3\x14\x5e\x20\xb6\x6a\xaa\x71\x2c\xa9\x8b\x27\xc6\x71\x31\xeb\x2b\x63\xbf\x9e\xeb\x54\x73\x10\xcc\xb6\x85\x9d\x35\x37\xb7\x08\xac\x59\xe8\x9c\x38\x94\xa9\xb5\x5a\xbf\xeb\xc1\xe6\x3c\x27\xd2\xbd\xd3\xcf\xdb\xd5\x82\xf2\x26\x46\xc3\x9d\xeb\xed\x72\x3d\x36\x54\x77\x5a\xce\xa5\xdd\x61\x5c\x2c\x7a\xf6\x5c\x06\x15\xcb\x75\x6b\x4e\x2b\x85\x4c\xd2\xac\x88\xa8\x99\x6a\x1a\xa5\xc6\xc8\xac\x77\xbc\xa2\x95\xda\x57\x83\x9a\xb7\x3f\xee\x24\xae\x2b\x7b\x36\x62\xee\xd1\x37\xd7\x6b\x9e\xf9\x5a\x82\x90\x6c\x72\xa2\xbf\xcb\xa3\xc4\xf6\x4b\xaa\xee\x93\x09\xdb\x8e\x3a\x29\x9f\x3b\xa5\x51\x79\xcb\x6b\xab\xdd\x2a\x37\xf2\xcb\x6e\x47\x77\x49\xda\xdf\xd9\x5e\xf9\xe5\xd9\x12\x09\xa4\xce\x7d\xfb\xfa\x60\xd7\xd3\xdf\x9f\xf0\xe8\x71\xf2\x5f\x0b\xfa\x92\xfc\x84\x0e\x9c\x5f\xfa\xc7\x5c\x86\x8b\x7d\xed\xd0\x4a\xe3\x51\xa8\x7d\xab\xb2\x18\x38\x3b\xcb\x45\x63\x4e\xeb\xf9\xc5\x40\x2c\x8d\xca\xa8\x90\x0e\xeb\x78\xbe\xea\x9c\xf4\xaf\xe3\xb4\x5a\x4f\x0c\xb8\x72\x6e\x3e\x35\x25\xfd\x52\xde\xf4\x42\x4e\x7f\x2f\xfe\x9e\xf6\x25\xcb\x9b\x3c\x99\x27\x86\x81\xe6\x87\x83\x70\x91\xaa\xc5\x74\xb8\x6a\x1e\x3c\x94\x5e\xbb\x47\x73\x37\xa8\xf5\x40\x37\xa2\xd3\xa1\x1c\x1a\x35\x03\xd6\x47\xc3\xe3\xd9\xb6\xb8\x1c\x5a\xcb\x5f\x7e\x2f\x51\x9e\xfe\xfe\x98\x27\x8b\xfb\xe4\x9f\x43\x2c\xae\x97\xff\xc4\x93\xef\x7a\xe9\x7f\x34\xc9\x61\x84\x34\x06\x71\x44\x39\x91\x28\x8c\x91\x46\x21\xc4\x48\xc3\x50\x49\x18\x50\x22\x02\xcc\x24\x14\x32\xd4\x61\xcc\xb9\x0e\x51\x88\x23\x81\x24\x44\x30\x90\x11\x52\xf4\xe4\xcd\xc0\x47\xf2\xe4\xd3\xb0\x03\x46\xe1\x29\x97\xf9\xc7\xb5\x90\x33\x20\x31\x63\x18\x61\x74\x3f\x4f\x3e\x48\xfe\x71\x1b\x4f\x5a\xad\xb2\x9d\x98\xc7\xe7\x92\xe0\x09\xab\xa0\x58\xc3\x9e\x97\xd9\xcd\x2a\x20\x2e\x95\xcb\x76\xb3\x90\x05\x5e\xd4\xea\xb4\x86\x76\x3b\x2c\xd3\x56\x91\x42\x6b\x52\x6b\xea\xc8\x2f\x95\x3a\xeb\xb0\x43\xf3\x85\x56\xfd\x38\x0e\xd0\x28\xe7\x6e\xdb\xbd\xf1\x0a\x46\x9d\x4d\x27\xdb\xf5\xd3\xb9\xca\x38\x28\x00\xb8\xfc\x62\x80\xff\xd7\x78\x92\xf8\xea\x2d\xfa\x1c\x5e\xfa\xf6\xb5\x8f\xf8\x35\x9e\x3c\x4e\xfe\xeb\xb1\xbd\x96\x27\xb3\x4b\xff\x5c\xad\xaf\x5b\x4d\xf0\xf4\x20\x0f\xd7\xd7\x2f\xcf\x70\x0f\xef\x1e\xdc\xbe\x64\x9f\xbe\xc9\x93\x69\x62\x18\x6e\xd0\xe7\xe7\xd5\xa9\xb3\x3e\x7f\x3d\x7e\x5f\xe2\xc9\x9d\x3c\x3b\x1f\x02\xbf\x5e\xfe\x13\x4f\xbe\xeb\xa5\xff\x49\x9e\x04\x02\xa3\x38\x66\x1c\x08\xaa\x42\xa9\x43\x16\x43\x45\x42\x4e\x40\xcc\x34\xc0\x38\x0c\x64\x48\x81\x08\x62\x8e\x68\x1c\xc6\x08\x60\xc2\x24\x47\x32\x60\x24\x80\x52\xc6\xf1\x13\x4f\xd0\xc3\x78\xf2\x69\x90\x34\xa3\xe4\xfd\x7b\x61\x4f\xb5\x32\xc1\x13\x8e\x1f\xe1\x9f\x7c\x90\xf8\xe3\x5e\xff\xe4\x6d\x9e\x40\x4f\x8b\x69\x6f\x67\x94\x8f\x24\x2e\x2e\x7c\xb3\xbf\xab\x0d\x6b\x74\x3f\xed\x31\x95\x5b\x34\x69\x3b\xb3\x1e\x8e\xba\x3d\x87\x6c\x7a\xad\xfe\x40\xe4\xd9\xa8\x31\x37\xcc\xed\x74\xdb\x59\xcd\x70\xae\x75\x98\xb0\x5a\x1c\xb1\x7c\xe4\xb5\x85\xa7\x8a\x23\xa7\xd1\x81\x25\xf7\x8b\x97\x58\xfc\x34\x4f\x6e\xd2\xe7\x0f\x94\x7f\x93\x7f\xf4\x20\x9e\x7c\xa3\xfd\x6f\x3c\x82\x27\xdf\xe8\x3f\x7d\x87\x7f\x72\xab\x3e\x37\x1e\xc4\x93\xa4\x7f\x74\x03\x4f\xbe\xeb\xa5\xff\x51\xff\x24\x0e\x08\xe3\x21\xc5\x31\xc5\x82\x45\x9c\x07\x11\xa6\x0a\x51\x80\x74\x84\x54\x84\xa3\x48\x84\x84\x81\x80\x86\x1a\xa1\x90\x85\x48\x40\x11\x0a\x18\xaa\x08\xeb\x08\x45\xc1\x2f\x9e\x3c\x27\x61\x37\x5b\x6d\x5a\x34\x6b\x5d\xa7\xca\xab\x76\xb9\xd3\x30\xdc\x4a\x2b\xe7\x75\x0c\xcb\x2a\x37\x3b\x9d\x6e\xde\x2c\x17\x1c\xd2\xf2\x32\x28\x57\xe0\x6d\x54\xac\xe6\xdb\x0e\xc7\xa7\x8b\xf3\x2e\x3c\x21\x9f\x46\x0c\x08\x40\xc4\xfb\xeb\x5d\xcf\xb5\x90\x43\x2e\x05\x93\x54\xe2\x97\xc8\xb5\xc2\x7a\xb3\x74\xb2\xf9\x4e\x5a\xd7\xd6\xb4\x57\x62\x8b\x5c\xc7\x28\x85\x41\x67\x3b\xce\x4d\x16\xc5\xc3\xca\x60\xde\x52\xae\x8b\x7a\xb2\x8f\x8d\x7f\xf2\xe4\x83\x88\x81\x73\xfd\xc5\xdf\xb8\x62\x1e\x66\x2f\xaf\xdb\xe5\xf7\x9c\x17\xf9\x5e\xa1\x2c\x8a\xf1\xda\x08\x62\x3d\x33\xdc\xc9\x76\xbe\xb2\x67\xa3\xc5\x84\xf0\xa1\xb1\x59\xec\x48\x0f\x36\xdb\xc3\x49\x11\x0c\x99\x57\x9d\xc0\xe1\x7e\x16\x8c\x8f\xd6\xce\xaa\xe3\x76\xaa\x8c\xb2\x95\x6c\x34\xac\xe7\xc7\xb6\x17\x34\xf6\x6e\x26\xf6\x0a\xd9\xfe\x92\x4d\xcb\xab\x24\x23\x8c\x77\x99\x92\xbc\xe4\xe9\x7d\xa6\x24\x3e\x74\x25\x4f\x4f\x3b\xf7\x95\x4b\xff\xbe\x53\x3e\x61\xca\xe3\xe4\xdf\x9b\x14\xf7\x72\xd8\xef\x6a\x9d\xfd\x99\x1e\x7c\x2a\x1f\xeb\xc1\x47\xcb\xbf\x36\x29\xee\x5f\xea\xa3\x7d\xb6\x47\x73\x4b\x5f\x9d\xdb\x9a\xff\x2d\x11\xd9\x57\xfa\xea\x11\x63\x95\xf4\xc1\xae\x91\xff\xc4\xac\x19\xde\xad\x53\x20\x33\x97\xac\x67\x04\x41\x6a\xb2\xab\x0f\xea\x8b\x70\xb8\x29\x99\x6c\x69\x0d\xac\x56\x2d\xa8\xf8\xdb\x7a\x75\x6e\xa4\xc2\x76\xd5\xed\x2f\x3a\xa5\xaa\x51\x2e\x46\x21\xc1\xbe\x22\x11\x2a\xe7\x26\xcd\x5a\x66\x5e\xb5\x7d\x47\x1a\x33\xed\x6e\x17\x0a\xed\x7e\x7a\x8f\x06\x84\x2a\x64\x3c\x08\x30\xa3\x84\xb0\x38\x42\x84\xc4\x5a\xc5\x31\x0e\x80\xc2\x92\xc7\x02\xc6\x38\x90\x21\xc4\x04\x89\xd3\x2d\x1c\x54\x73\xce\x22\x42\xb8\x02\x21\xd4\xcf\xcc\x42\x8f\x62\xd6\xe7\x6b\x6a\x02\x7c\xb0\xa4\xf6\x54\x79\x26\x16\x07\x00\x5c\x56\xd4\x6e\x27\xd6\x07\x2b\x6a\x67\x8d\x77\xf1\x68\x1e\x48\xac\x52\xb5\xd5\xf3\xe3\xd4\x0e\xc8\x48\xcf\xad\xfa\xbe\xa4\xf2\xd3\x61\xab\x9b\x35\x90\x33\x1e\x65\x26\xfd\xea\x64\x00\xca\x8c\x39\x9b\xbe\x71\x6c\xe8\x51\x5b\x99\x95\x52\x64\xe6\x80\x6a\xaa\xd4\x3e\xdf\x3f\xec\x8a\x9d\x7a\x69\x50\x30\xd8\xae\xca\x0a\x92\x94\x6b\x63\x67\xec\xd9\x7f\x23\xb1\x6e\x4a\xb9\xfb\x40\xf9\xf7\xa6\xdc\x7d\x20\x31\x6e\x4a\xb9\xfb\x68\xf9\xd7\xa6\xdc\xfd\x4b\xbd\xc0\x37\x89\xf5\x87\x88\x61\x7c\xc3\x58\x5d\x23\xff\x89\x58\x3b\xd9\xce\xf4\xd3\xdc\x6a\x40\xc8\x46\xe5\xa2\xbd\xdf\x4d\x74\xb9\x35\x52\x96\xdf\x6e\x7b\x6e\x60\xa7\x82\xa2\x87\x97\xb3\x36\xb3\xad\x72\x99\xd5\xba\xbb\x1c\xd9\x83\xdc\xb0\xb6\xaf\x1d\xb9\x3d\xc9\x16\x8d\x75\x94\x3b\xe4\x66\xd6\xd2\x48\xcf\x96\xb8\x07\xdd\x66\xbb\x65\xfc\xf0\xaa\x1d\x84\x1c\xd0\x58\x12\x15\x31\x1a\xf1\x90\x71\x1c\x40\x44\x02\x41\x95\xc6\x4c\x28\x01\x62\x41\xa8\x88\xe3\x40\x47\x71\xcc\xa1\xc4\x80\x44\x22\x16\x44\x52\x4c\x43\xa2\xc1\x7f\xfe\xfb\x7f\x58\x3e\x70\x17\xe8\x73\x2f\x4b\xa2\xf7\x0f\x07\x9d\xeb\x20\xe3\x14\x60\x8e\x04\x23\xe0\xfe\x15\xbb\xcf\xd2\x1a\xbc\x9e\x27\x09\x7d\xf6\xa5\x92\x79\xf1\xfc\x6d\xf3\x30\xb4\x02\xa8\x53\xc3\x75\x67\x33\x6a\x2c\xb3\xe3\x4d\x85\xef\x41\x69\xcf\xdb\x43\x32\xa9\xcd\x4a\xa4\x4e\x9b\x86\x33\xa9\xb5\x52\x68\xd9\x9a\xed\x87\xa5\xdd\xc2\xc9\xf7\xd7\xfe\xd4\x36\x9a\x2d\x28\x53\x26\x3d\xa8\x39\x1d\x56\x8a\xc5\x79\x7b\xbf\x34\x75\xad\x90\xf7\xbe\x74\xfd\xfb\x97\x0e\x92\x26\x8f\xa5\xdf\xb0\x52\xf6\x14\x0f\x7d\xbb\x57\xf5\x40\xf9\xf7\xa6\x29\xf8\xc6\xdd\x8a\xa7\xf2\xb1\xde\xfb\x43\xbb\x25\x9f\x79\x2d\xb7\xb4\xe5\x6e\xaf\xe5\x81\x7d\x71\x8d\xfc\x27\x06\xac\x66\x3b\xb4\xee\x6c\x67\xbc\xc5\xe7\x36\xdb\xd3\x70\xb8\x11\x91\x55\xd2\x70\x96\xca\x8f\x02\xab\x62\x6f\x5a\x46\xa6\x3b\x6a\xc5\xeb\x05\x0c\x4a\xfe\xb1\x54\xe8\xd7\xfd\xb0\x9d\xdf\x1b\x8e\x13\xc5\x71\x6f\xa3\xa6\x05\xed\x1f\x07\x07\xd6\x5a\x05\xbb\xe9\xa8\x3e\x68\xfe\xf8\xf5\xe2\x41\xac\x43\x01\x04\xa0\x08\xe9\x30\xe0\x50\x05\x18\x09\x84\x68\x18\xaa\x98\x63\x08\x90\xd4\x91\x8a\x03\x44\x89\x12\x88\x2b\x42\x43\x4d\x05\x08\x03\x2d\xa9\xe2\x08\xc3\x5f\x0c\xb8\x3f\x7d\x2e\x64\x9f\x68\x7e\x06\x30\x17\xf0\x3d\xdd\xff\x52\xfb\xc4\x12\x06\x31\x79\x40\x5c\xf3\xeb\xb1\xff\x4d\x73\xdc\x60\x2d\xbf\x13\xd7\x6c\x4d\x8f\xdb\x72\xcf\xf6\x33\x70\x83\x33\x6e\x23\xeb\x58\xe3\x5c\x7b\x3a\x02\x6e\x65\xc1\x33\xa5\x79\xac\x0e\x7a\x97\xaf\xad\xf2\x05\x39\x6e\x90\x6c\xa3\x64\xef\x4a\x1e\x1a\xd6\xf3\x87\x65\x7b\x92\xe1\xfb\x28\xb3\xcf\x16\x82\x72\xa9\xe3\x05\x46\x6e\xcf\xcc\x7a\xbf\xd8\x99\x7b\xd9\x47\xc5\x35\xe7\x6f\x3b\xc6\x5f\x26\xc5\xc0\x3b\x54\x53\xb4\x73\xf9\x7a\xf5\x4d\xc9\x9f\x69\xff\xc7\xc9\x7f\x47\x9f\x7c\xd9\x43\xb9\x3d\x96\x76\x6e\xe5\xd2\x7c\xac\x5e\xfd\xf2\xef\xe5\x63\x8d\x77\x47\x2c\x2f\x05\x42\xb6\xee\x90\x6f\x18\x7f\x6e\x9d\xea\x4d\xfa\xf4\x6f\xee\x8b\xd3\x58\xcc\x12\xef\xa2\xb8\xb2\x2f\xee\x1c\x8b\x93\xfc\x04\xbc\xae\x92\xff\x44\x1f\x2a\xf8\xd1\xcf\xb8\x46\x14\xae\x77\xb5\xd1\x7e\xef\xd1\xba\x33\xa7\xe5\xcc\x70\xb1\xd9\x35\x0a\x1d\x5c\x9a\xae\xcc\x66\x68\xd6\xb7\xdd\x66\x2a\x03\x8e\x99\x92\x65\x97\x67\x60\xa0\x16\x70\xde\xd3\xa2\xe3\xa9\xda\x61\x32\x6c\x38\xc0\xed\x99\x25\xdd\x1b\xcd\xea\x90\x35\x7f\xfa\x54\x0d\xc2\x94\x44\xb1\x00\x08\x42\x48\xa0\x08\xa4\x94\x1a\x43\x85\x24\x23\x11\x64\xa1\xd0\xb1\x16\x9a\x48\x14\xf2\x88\x93\x48\x53\x22\xb1\x14\x88\x42\x09\x34\x04\x04\xc6\x4f\xf4\xb9\x33\xe9\x0d\xe4\x9f\xd3\x47\xca\x77\x77\x77\x5e\x6a\x9f\xe9\x43\xc9\xc5\xf7\xb8\x9d\x3e\xaf\x4f\x80\xfc\xf6\xbe\xde\x60\x07\xbf\x47\x1f\x8b\xb5\xb7\x86\x5f\x84\xbb\xc1\x78\x15\xf1\xa3\x6f\xe5\xd7\x60\xe0\x54\xd2\xe3\xf9\xdc\x63\x6e\x3e\x3f\x4d\x1b\xa2\x99\x1f\xcb\x61\x63\x58\x2a\x57\x86\x1b\xaf\x9a\x59\x1b\x3c\xae\xef\x6b\xb4\xd0\x00\x99\x6e\x31\x5c\x7b\x07\xb1\x70\xc6\x87\x15\xc8\xb1\xb8\xa1\xd3\x6a\x57\xf9\x0b\xe8\x53\x89\xaa\xd5\xd6\xbd\xda\xff\x81\xf2\x6f\x3a\xd5\xf3\x10\xfa\xfc\xa6\xfd\x6f\xf2\x3d\xfe\xe0\x49\x12\xc3\xf8\x73\xfe\xc6\x83\x4f\xd5\xdc\xa5\xfd\x8d\x07\xd1\x27\x61\x89\xdc\x42\x9f\x5d\x6a\xbc\xdc\xb9\xa6\x54\xb9\x79\x98\xd5\x02\x19\x87\x30\xca\xf5\x1b\x5b\x1a\x04\xcd\x4a\x7f\x50\xef\xa6\x77\x55\xc7\xec\xc6\x3e\x20\x47\xab\x31\xe3\x23\x6b\x17\x7a\x15\x0c\x56\x4d\x5d\x1f\x49\xa3\x5d\x47\xbc\x59\xda\x16\xfa\x5d\xb5\x2c\x9b\x95\x29\xc0\x5b\x5c\xfa\xe9\x2b\x10\x29\xc2\x42\x04\x52\x68\xa2\x31\x53\x90\x73\x22\x03\x49\x30\x27\x88\x03\xa5\x18\x0d\xa3\x90\x23\x0e\x55\x48\x21\xe2\x3c\x06\x92\x06\x41\x20\x62\xa8\x02\x19\x61\x84\xd4\x2f\xfa\x3c\x27\x27\x37\xf3\x85\x7c\xa7\x5a\xc8\x38\xb9\x6c\xa5\x82\x09\xa5\xed\x4e\xdb\xa5\xa6\x95\xe9\x76\xbc\xb2\xef\xd4\x6a\x6e\xce\xf4\x4b\xd5\xa6\x87\xa9\x59\xf5\x48\xbb\x55\xc7\x85\x6e\xf1\xb4\x63\x43\x20\xc7\x58\x22\xc0\xf9\x67\xa7\x6a\x18\xa4\x02\xbe\xef\x05\x3d\xd7\x42\x2a\x24\xc4\x5c\x12\x40\x5e\xa2\xd6\xf2\x85\x11\xd6\xb3\x7c\x33\xab\x78\x5c\x91\x6b\xbd\xdf\x0c\xdc\x6c\x99\x94\x77\xed\x52\x23\xe7\xf4\x87\xcc\xc3\xa0\x41\xd4\xba\xdd\x3e\x05\x35\x9d\xd7\xc0\x6c\xe3\xe3\x53\x35\xaf\xa3\x0c\x6e\x4c\x44\x75\x99\xd7\x2f\xf2\xbd\x12\xad\x9b\xb3\x36\x04\x76\x7e\x56\xc8\x64\x76\xbb\xd2\x06\xb4\x76\xa9\x38\x15\x7a\xc0\x1d\x7a\xd2\xa9\xb0\x1d\x1e\x4b\x2f\xed\xe4\xd4\x7a\x22\x38\x22\x62\x2d\x87\x9d\x46\x38\x06\xb5\x88\x94\x7b\xae\x9a\x4d\xc0\x61\xe6\xee\x7b\x2a\x3f\xb0\x6b\xbb\xae\x9b\x29\x75\x3c\xf5\xb0\x3d\x9b\x7c\xe2\xab\xa3\x45\x23\x62\xbd\xb1\x17\x1d\xd7\x82\x23\xc8\x5d\x96\xf3\x15\xee\xe1\x8c\xbf\x2f\xf5\xda\x6e\x75\x6e\xc5\xb5\x6a\xff\x00\xbb\xe1\x69\xcd\x30\x71\xb2\xc5\x7e\xf9\xbd\x6b\xf7\x4c\x1e\x28\xdf\xbe\x45\x7e\x22\x3f\xc1\xe8\xf2\x7d\xb3\x3e\x2f\xe3\x85\xd9\xca\xe0\x0a\x3e\x6e\xc3\xce\x2a\x9c\xf5\xfb\x47\x6d\x29\x67\x68\x1f\x32\xbe\x9f\x1a\x95\xa5\x9d\xca\x16\x5b\xe3\xf5\xe9\xf3\x89\x5d\xf6\x6b\x93\xf7\x25\x4a\x85\x2e\x0b\x6f\xb7\x39\xb1\x07\x74\xe5\xfc\x37\x5a\xad\xc6\x33\xac\xaf\xcc\xbb\xf1\xe8\xf9\x71\xd3\xf8\x3c\x5c\xfe\x6f\xe5\xcd\x7f\x7e\x8b\x93\x09\x9b\xf3\xda\xf9\x71\x89\x86\x3b\x5f\x75\x57\x32\x6e\xd8\xd3\x1b\xdf\x27\xff\xbc\xf2\x7c\xbd\xfc\x27\x4e\x1e\xc7\xb9\x42\x3f\xec\x78\xde\xa4\x37\xb3\xb3\x96\x71\xe0\xb5\x8e\x45\xd3\x74\x6d\x79\x41\xd9\x02\x4d\xbe\xb4\x74\x07\x5a\xa2\xd9\x3f\xa0\xf0\xb8\x0d\x87\x07\x8c\xca\x51\x79\xd3\xa9\x39\xb8\x87\x8c\xee\x61\x10\x36\x0a\xbd\xd0\xcd\xec\x26\xb9\x5a\x36\x33\xf2\xed\x7d\xf4\xd3\x5e\x1a\x21\x2a\x64\x4a\xe8\x88\x44\xa1\x56\x94\xa0\x20\x86\x41\x10\x21\x0c\x00\x8c\x22\x19\x31\x2e\x54\x0c\xa5\x12\x8a\x30\x18\x30\x8a\x35\x67\x28\xe0\x88\x62\x1d\xe9\x48\xa0\x5f\x9c\x64\x8f\xe4\xe4\x67\xd1\xdd\x0c\x53\x4e\xdf\x4d\x81\xfd\x52\x0b\x29\x61\x50\x08\xc4\x38\x45\xf7\x73\xf2\x83\xe8\xee\xbb\x39\xc9\x27\xab\x59\x72\x5e\x5f\x38\x59\x49\xe9\x46\xae\xda\x69\x76\x47\x29\xd7\x58\xf0\x0a\xcb\x8a\x08\xa6\xdb\x0d\x1a\x6e\x66\x20\x98\x0f\x8b\x7d\xb7\xb7\xce\xe8\xfa\x61\x8c\x79\xb3\xc5\x8b\xe6\xbc\x1b\x9b\x53\x66\xf9\x2d\xc5\xc7\x5e\xa5\x55\x6e\xf7\x33\x8a\x17\x2c\x83\x97\xb5\xc0\x46\x8d\xc0\x91\x6f\x8c\x1e\xc7\xc9\xc4\x87\x6e\xd1\x43\xf0\xd2\xbf\x37\xc5\x16\x3c\x50\xfe\x4d\x9c\x4e\xe8\xc1\xe1\xe5\xfb\x7f\x1b\x27\x4f\x7f\xff\xa5\x1c\x7f\xd3\xf7\x1a\x5e\xea\x6f\xd1\xe9\xe7\xbd\xff\xdc\x65\xae\x5e\xcb\x94\x07\x32\xed\x1a\xf9\x4f\x4c\xe1\x94\x96\x7a\x32\xaa\x4d\x1a\xc4\x37\x97\x2b\x3e\x8b\xf7\xb8\x23\xbb\xd5\xf1\x86\x0d\x6b\x8b\x49\x69\x63\x07\x26\x70\x68\xb1\xd0\x89\xd7\xb5\xce\x6a\x55\x18\x8f\x45\x21\x9e\x95\xfb\xad\xe3\xa6\x65\xd0\x26\x0c\x6c\xe7\xb8\x9a\x95\xac\x15\xe4\x47\x95\xc9\x0e\xdb\xb5\xde\x4f\x5f\xdb\x48\x34\x22\x04\xc5\x1a\x69\x11\x45\x42\x31\xc1\x28\x07\x4a\xc6\x14\xf3\x40\x85\x28\xa6\x00\x52\x1c\x48\x21\x70\x2c\x22\x28\x65\xc8\x62\xc2\x01\xd4\x21\x12\x32\xc4\xc1\x29\xf6\x80\x3e\x92\x29\x9f\x45\xcb\x31\x42\x11\x7b\x9f\x29\xcf\xb5\x90\x02\x8c\xb0\xa0\x92\x50\x76\x3f\x53\x3e\x8d\x97\xfb\x16\xa6\x94\x37\xbd\x45\x2a\x83\xc1\x3c\x0a\x8f\xdb\x56\xcb\x3d\xca\x5a\x05\xa7\xac\x92\xae\x45\xed\x85\x4a\x77\x56\x11\x2a\xfb\x51\x8f\x95\x33\x1b\xae\x57\xdb\x4a\xd4\x68\x7b\x78\xba\x9d\x65\xec\xfc\x41\xbb\x47\x61\xdb\xf2\x58\xf3\x06\xf5\xc1\x62\xb6\xdc\x65\xc7\x93\x94\xe1\xc6\xbb\xdc\xc3\x98\x92\x4b\xf8\x8e\x37\xe8\xf4\xa7\x78\xb5\x44\x44\xf1\x95\x3a\xfd\x81\xf2\x6f\x8b\x97\xbb\xe8\xc1\xc1\xe5\xfb\x3f\xad\xb3\xbf\x94\xd5\xe0\x2f\x65\xde\x9b\x4c\x19\x5c\xea\x6f\xd1\xe9\xe7\x58\x82\xb3\x4e\xbf\x36\x5a\x3d\xd1\x57\x37\xcb\x4f\x32\xed\x1a\xf9\x4f\x4c\x41\xcc\x5c\x92\x6c\x5c\x1f\xc3\x6d\x45\xb6\x9a\x61\x15\xda\x3c\x26\xa5\x3d\x75\x60\x30\x3f\x4a\xbd\xc7\x3e\xec\x23\x6b\x06\x5c\xbe\x66\x07\x41\x61\xb9\x6b\x69\x9d\xea\xd9\xde\x34\x4f\xc2\xea\xce\x6b\xe0\xb2\x63\xe6\x0b\x85\xc5\x60\x6b\xe8\x76\x48\x8c\x6e\xfa\xa7\xaf\x50\x08\x00\x8d\x82\x40\x23\x0c\x42\x18\x73\x82\x09\x27\x5a\xe0\x20\x64\x11\x11\x90\x47\x31\x8c\x71\xcc\x39\x63\x30\xe0\x91\x80\x34\xe6\x0c\x01\xa5\x35\x0a\xa4\x00\x92\x88\x13\x53\xc8\x03\x99\xc2\x3e\x8b\x67\x63\x94\xc9\xf7\x4f\x0d\xbd\xd4\x42\xc2\x00\x12\x42\x22\xc8\xc0\xfd\x4c\xb9\xe2\xd4\xd0\x15\x4c\xc1\x6f\xc5\x60\x27\x98\x92\xf1\x9b\xd3\x16\xce\xc1\x0a\xa6\xb6\x71\x08\x0e\x60\xb2\x1a\xf6\x70\xe9\xd8\x8d\x83\xa9\xb9\xde\x06\xe3\x82\xeb\xa6\x24\x99\x6b\x56\xdb\xf7\xec\xf4\xc8\x1c\xa1\x51\xa3\x21\xb3\x9d\x5e\x67\x18\x2e\x83\x45\x3a\xed\xa5\xc1\x36\x0f\x8c\x99\x69\x74\xea\xba\x01\x45\x73\xd8\x7b\x9c\x9f\x92\x4b\xec\x09\xdc\xa2\xd3\xa7\x97\xfe\x7d\xa7\x7c\xc2\x94\xc7\xc9\xbf\xf7\xd4\xd0\xa3\xf5\xe0\xef\xe5\x63\x3d\xf8\x07\xf5\xb0\x61\xfc\xbd\x4c\xfd\x2c\x02\xe2\x96\xbe\x3a\xb7\x35\xf7\x51\x7f\xfc\xd8\x58\x5d\x23\xff\x89\x59\x4e\xbf\x1e\x75\xd4\xb0\xc9\xe3\x91\x67\xe5\x97\xc5\x7a\x70\xa8\x58\xea\x58\x1e\xcb\x85\x2a\x20\xb9\x68\xce\xfc\x90\xe3\xc1\x98\xcf\xb3\xae\xd1\x48\x79\x85\x46\x50\x2b\x57\x41\xa4\x33\xba\xbc\x59\x2f\x96\x69\x69\xa5\xeb\x62\xea\x99\xbd\x5c\x26\xca\xd3\x6a\x67\x5f\xaf\xfc\xb4\x1f\xc4\x22\x2e\x62\xc8\xe3\x20\x0e\x10\x86\x3c\x62\x41\xcc\xb8\xd4\x50\x53\x82\x40\x8c\x29\x44\x80\xc7\x31\x83\x2a\x8a\x63\x04\x15\x03\x40\x07\x22\x16\x14\x52\x1a\x62\x1d\x9c\xe2\xef\x1e\x90\x57\x94\x7e\x46\x2a\x46\xf9\xfb\x17\xe4\xbe\xd4\x3e\xb3\x8f\x08\xf6\x80\xf8\xbb\xd7\xb1\x62\xbf\xbd\xc9\x37\x68\xca\xf7\xae\xaf\x4f\x4d\x7a\x85\xdc\xb1\xbb\x88\xc7\x5e\xae\x90\x5b\xb4\xa7\xb2\xb8\x54\x83\xcd\xc1\xde\xf3\x4e\x35\xee\xb8\xcd\xfe\xf6\xe0\xe1\x55\xce\xcb\x4c\xdd\xa8\xd2\xee\x8f\x2a\x6b\xca\x9b\xcd\x34\xa7\xc5\x75\xf3\x40\x96\x5a\x35\x52\xc3\xa5\x8f\x54\xb6\xd0\x1d\x62\x3c\xdf\x6c\xb4\x70\x1e\x15\x01\x91\x7c\x43\xae\x8c\x40\x68\x64\xbd\x8d\x4e\xac\x82\x55\xde\x94\xfc\x19\x9d\x1e\x27\xff\xa6\xf8\xbf\x04\x9d\xee\x88\xf9\x2a\x45\x26\x25\xf7\xc6\x7c\xfd\xc1\x98\x33\xc3\xf8\x73\x1a\xff\x4d\xfa\x84\xb7\xf7\xc5\xaf\xb1\x60\x89\xc4\xaa\xe4\xca\xbe\xb8\x77\x2c\x5e\xcf\x85\x6b\xe4\x3f\xd1\x67\x3b\x9f\x99\x83\x12\x0a\xa6\xb4\x69\x9a\x83\xc2\x78\x9e\xae\x33\x9c\x5b\xae\xfa\x25\x0d\x8f\x18\xee\xc7\xb9\x50\x8c\xca\xdc\xb4\x8d\xee\x7e\xda\x18\xcf\xba\xd6\x52\x6b\xe8\x54\x53\xa9\x3a\x6f\x95\x36\x05\x3c\xb5\xd3\x33\x86\xca\xd3\xcc\x61\xe2\x4b\xc9\xc2\xe5\x74\xfb\xd3\x79\x7b\xc2\x50\x46\x8c\x51\x02\x21\x8c\x03\x4d\x01\xa4\x92\x10\x00\x22\x25\x01\x54\x1c\x44\x84\x13\x21\x03\xc6\x21\xc3\x11\x0a\x30\x89\x65\x88\x35\x46\x81\x44\x30\xa0\x20\x3a\x45\x40\x3c\xe7\x15\x35\x73\x8e\x53\xf3\x0a\xd9\x52\x96\xe5\x2d\x6e\x16\x68\x25\x47\x3a\x2d\xd3\x37\x4b\xe5\x5a\xd9\x61\x55\xdf\xe0\xf9\x86\x59\xc3\x4e\x35\x5b\xcd\x77\xbd\x86\xef\x3b\x19\x6a\x9f\x2e\x37\x85\x54\x32\x02\x21\x07\x00\x7f\xc6\x21\xce\x09\x7e\xf7\xfa\xb9\x97\x5a\x88\x39\xc1\x42\x52\x4e\xd9\x25\x02\x22\x53\xdf\xf7\x66\xdc\x4a\xd5\xab\x64\x1c\xa9\xe1\x98\x0d\x76\xf9\xa1\xbf\x2e\xd2\x94\x11\x37\x4a\xcd\x68\xac\x23\xa6\x76\xd3\xe1\xf9\x7e\xad\x13\x87\x32\xa7\xc4\xe9\xc5\x57\x13\xe0\x83\x53\x40\xef\xec\x10\x7e\x5c\x32\xa5\x3c\xd9\x9d\x7e\xc9\x36\x9c\xc3\xba\xb9\x1f\xee\xcb\x24\x9c\xe6\x4b\x4b\x3b\x3f\xaa\xcf\x97\x53\xbb\x2e\x07\xee\xbc\xb2\x37\x56\xe5\x8a\xe3\x2f\x1b\xd5\xf4\x7e\xed\xb6\x46\xe9\x6a\x17\xcd\x1a\xfd\x66\x3b\x95\xee\x17\x6b\xb9\x51\xaa\xef\xfb\x76\xcf\x41\xd0\x8d\xa9\x28\xa7\x83\x30\x5f\x70\xe6\x8b\xf1\x2a\xf7\xa8\x53\x40\xc9\x4c\xc8\x23\xa7\xe8\x9a\xc3\x55\x95\xe6\xd2\x83\x16\x3c\x54\x3a\x8b\xa2\x31\x29\x0f\xc0\x76\x4a\x32\xb2\xb4\xaf\xa1\x16\xc5\xf3\xa3\xa9\x4b\xe7\x5f\xfe\xc5\xde\xb8\x79\xe9\xd3\xc2\xe5\xf7\xcf\xba\xff\x96\x5d\x76\x13\xb5\x88\xdf\x86\xbb\xd0\x6d\x6e\x7c\x24\xd7\xa7\x16\xf6\x12\x2b\xea\xd9\x43\x84\xd4\xba\x9d\xb3\xc5\x62\x26\x46\x99\x7d\x0e\x39\xd3\xf2\x31\xf0\xe3\xb5\xb4\xd6\x2e\x2e\x85\xb9\xa6\x75\xf0\xdb\xde\xbe\x72\x6a\xc9\x6f\x37\xbb\x79\xaf\xd6\x60\xaf\x9c\x43\xc6\xd8\x2b\xe2\x73\x3c\xc1\x49\x57\x9a\x17\xab\xfe\xb6\x2b\x0b\x4f\xdf\x5f\x8f\xb5\xeb\xac\x95\xbb\x1f\x17\x27\xe5\x6d\xe8\xfd\x6a\x61\x2e\xb1\x92\x98\x11\xd3\x68\x5a\x6c\x0d\x32\xd5\xc2\xa2\x9a\x37\x54\xbd\xdc\xef\x1e\x15\x9a\x64\x79\xec\xf1\xda\xfa\xe8\x1e\x1c\x43\x4c\x9c\x51\xa9\x71\x56\x80\xaf\x6f\xd6\x4b\xac\x4c\xee\xfe\xb5\xcf\x9f\xf0\xc7\x4d\xaf\xb9\xf2\x0b\x95\x5d\x7a\x34\x4c\xe5\x3b\x9d\x1c\xd5\xb3\x95\xe9\xa3\x62\x3d\x15\xf7\xb2\xe0\xe8\x64\xbb\x9d\xa9\x9e\xbe\xbc\xc3\xbf\x38\x2b\xe5\xa9\x25\xee\xa9\xbd\x89\x5b\x40\xce\xed\xbb\x25\x4a\xaa\xd8\xed\xf4\xfb\x61\x27\xb3\xea\xd6\xe9\x30\x44\xe0\x57\x0b\x4d\x23\x71\x8a\x2b\xce\xe3\xee\x01\xfa\xbd\xc6\x61\x31\x3c\x78\x59\x7b\xe8\xb7\x15\x2e\xcf\xfb\x29\x0c\x2a\x20\x54\xfb\x55\xdf\xab\xe6\xfb\x5d\xcb\xa6\xa7\x8f\xbf\xfd\xbe\x5f\xd8\x1e\xdf\xf5\xfc\xa9\xf3\x52\xd2\xf9\xf9\x67\x77\x3e\x7f\xe9\xbb\x9f\xff\xa5\x7d\xf7\xea\xb7\xd3\x55\x51\xff\x23\xfa\xed\x7c\x41\xbb\x5a\xb6\x4a\xbe\x68\x68\x97\x1e\x1a\x85\xbd\xd9\xb5\x17\x01\xdd\xdb\x5b\xbf\xbf\x68\xac\xbc\xa2\xd5\xe8\xb7\x0b\xe0\x98\x16\x61\x6d\xdc\xad\x1e\x51\xb4\xb0\x49\xcb\xd9\x6e\x49\x1d\xd4\xf3\xd5\x59\xdb\xcd\xe4\x32\xd1\xba\x36\x4d\xc5\x56\x8c\x26\x87\x7a\x3f\x08\xe6\xa1\xf9\xc3\x79\x37\x58\x88\x85\x8a\x22\xaa\x20\x8f\x62\x04\x20\x8e\x68\x40\x35\x82\x50\x91\x10\x23\x04\x45\xc8\x42\x2d\x21\x40\x14\x43\x16\xc2\x20\x08\x91\x08\x15\x44\x18\x32\x06\x69\x44\x9f\x6c\x18\xf4\x30\x1b\x86\x7c\x6e\xc3\xb0\xf7\x6f\x97\x3a\xd5\x26\x6c\x18\x06\xd9\xc5\x97\xbe\xdd\x86\x79\x9d\xe8\xf8\x6b\x27\x99\x3f\x2b\x37\xe9\xdb\x44\x69\x3c\xbf\x3f\x19\xa3\x12\x82\x85\xdb\x9e\x8e\x60\x7b\x59\x6f\x76\xea\x6c\xe0\x39\x33\x15\xe4\x2a\x7e\x3a\x63\x4d\x7a\x2e\x3c\x36\x26\xe3\xea\xa1\x07\xc2\x59\x7d\x10\xe1\x61\x23\x53\xc0\x47\xd9\x14\xa9\x5c\xd5\x35\x2a\x76\xb1\x5c\xec\x8d\xbc\xec\xba\xe7\xfa\x4e\xcf\x71\x4b\x83\x19\xdc\xfb\xa9\x2f\xe6\xbe\xfd\x69\xdb\xa7\x78\xf9\xfd\x9b\x74\xc3\xf9\x47\xff\xc7\x6c\x9f\x73\xf8\xcc\x1d\xec\x3f\x95\xff\x5d\xdb\xe7\x7f\xe8\xf9\x1f\x68\xfb\xec\xfe\x39\x9f\x1e\x6e\xfb\x24\xcb\x9b\x6b\x14\x77\x3e\x4b\x0a\x18\xff\x42\x3b\xe6\x7f\xc9\x4f\x3b\xd9\x31\xdf\x05\x8f\x1f\x3d\x0b\x29\x65\xa4\x18\xc3\x30\xa2\x82\x06\x94\x06\x1a\x33\x80\x62\xc6\x80\x56\x34\xa4\x01\x00\x42\x44\x88\x04\x90\x84\x98\x10\xc5\x91\x56\x4a\xa1\x80\xa1\x48\x06\x42\x62\xf1\xcb\x8e\x81\x8f\x5c\x8b\xf9\xf4\x34\x8a\x24\x98\xbe\x9b\x8f\xe5\xa5\x16\x62\x0c\x09\x96\x12\x20\x8e\xee\xb7\x63\x0a\x6f\xcd\xf7\x73\xf9\x69\x3b\x26\x21\x2f\x61\xc7\x80\xdd\x72\xa0\x97\xd3\xfa\x32\x45\xab\xc8\x33\xf5\x6c\x0a\x37\x43\x3a\x59\x56\x8a\xe5\x46\x65\x59\xf5\xab\xd5\x01\x5d\x0e\x54\x71\xd3\x4b\x4f\x97\xda\x6e\xf6\x57\xbd\x7a\x7a\x84\xc7\x86\xcc\xbb\xf3\x56\x18\xa5\xd6\x81\x2a\xd9\x85\x49\xa7\x30\x71\xf6\x59\xd3\x2e\x0d\xdb\xd5\x2f\xde\x09\xf3\x25\x3b\x26\x9b\x8c\x5e\xba\x5e\x37\xf4\xdc\xcb\x58\xe4\x2f\xbf\xff\xf7\xe8\x86\xdf\xd6\x6c\xbd\xd3\xd0\x5e\xfe\xbe\x81\xe3\x24\x73\x52\xd0\xe7\x35\x8c\xd7\xf9\x28\xff\x8a\x35\x8c\x37\xa3\xaf\x2e\x76\xcc\xbf\xf3\xf9\xff\x4d\x6b\x18\x6f\xd9\x3e\xfa\xbe\xe7\x3f\x4f\x9a\xf3\xf3\x8f\xfe\xc6\xe7\x7f\x33\x92\xe9\xdf\xa4\xdf\x4e\xb6\xcf\x77\x01\xe7\x27\x6d\x1f\x85\x55\x44\x78\x80\x21\xd4\x00\x9d\xd2\xa7\x72\xa4\x28\x20\x88\x85\x34\xa4\x84\x10\x4d\x11\x83\x04\xc3\x58\x51\xce\x80\x16\x9a\x72\xc2\xb8\x12\x5c\x45\x44\x9e\x6e\x08\xc7\xe0\x91\xb6\xcf\x67\x27\x8c\x38\x10\xfc\xfd\x7d\xa8\x53\xed\xe9\x9e\x55\x24\x04\x91\x00\x21\xc9\xd9\xfd\xb6\x4f\xfe\xad\xf9\x7e\x2e\x3f\x6d\xfb\x24\xf4\x6d\xc2\xf6\xe1\xdd\x52\x61\x21\xc0\x46\x79\xf5\x75\x8a\xd2\x45\x8a\xb5\xbc\xa5\x8b\xb3\xcb\x2d\x3b\x66\xd7\x95\xe2\x6e\x14\x1b\xfb\xfd\xaa\x1b\xf9\xd5\xdc\x66\xc4\xf7\xdd\x55\x2f\x3c\xf4\x2b\x66\xab\x33\xec\xeb\x8a\x27\x0f\x3d\xa3\x0d\xb7\xeb\x43\x18\x75\x5c\x02\x8d\x7d\xdd\xa9\xad\x8d\x47\xda\x3e\xc9\x28\xbb\x1b\x74\x43\x7c\x19\x8b\xdc\xe5\xf7\xff\x4e\xdd\xf0\xf2\x77\x26\xb1\xb7\x7d\x0b\xfb\xcf\x0a\xf5\xcc\xfe\xd7\x51\x75\x7f\x2f\xfb\x13\xb6\xcf\xbf\xf2\xf9\xff\x4d\xec\x7f\xcb\xf6\x89\xee\x7b\x7e\xab\x77\x79\xfe\xde\xdf\xfe\xfc\x2f\x7f\xff\x9b\xf4\xdb\xf9\x24\xdc\x37\x01\xe7\x47\xf7\xaf\x64\xcc\x48\xa0\x41\x2c\x80\x0c\x81\x90\x92\x29\x18\x63\x49\xb4\xe6\x92\x02\x00\x03\x02\xb4\xd6\x4c\x06\x51\xc8\x38\x0d\x42\x86\xc3\x38\x82\x12\xa3\x08\x07\x41\x1c\xa2\xff\xfc\xf7\xff\x90\x7c\xa4\xed\xf3\xd9\x49\x38\x0e\x05\x7b\x3f\x0b\xc9\xa9\xf6\x14\x0b\x8a\x08\xa5\x04\x50\xca\x04\xb8\xdf\xf6\x79\x7d\x09\xf7\x15\xb6\xcf\x9b\x27\xe9\xde\x2e\x09\x5b\x66\xc0\xe4\xc2\xca\xaa\x71\xab\x2e\x0d\xe1\x1a\xc1\xe2\x30\x62\xb3\xdc\x7e\x50\x32\x51\xa1\xd3\xb1\xa7\xda\x19\x0c\xe3\x7d\x96\xb6\x0e\x45\x37\xe7\x75\xcb\xc6\xbe\x52\x51\x66\x75\x9e\x0b\xc6\x4d\x56\x85\x73\xbf\xd6\xc1\x05\x52\x19\x17\xb2\x5d\xd2\xcf\x45\xfb\xfc\xd1\x62\x8f\xdc\x8f\xca\x26\xbe\x7a\xcb\xbb\x4e\x2e\x7d\x9b\xbd\xfc\xfe\xdf\xf9\xae\xbf\xfc\x9d\x01\x97\xbf\x6f\x61\xf9\x39\xfa\x35\xbc\x4c\x88\xff\x09\x96\x27\x6c\x99\x7f\xe5\xf3\xff\x9b\x58\xfe\x96\x2d\xa3\xee\x7b\x7e\xc7\xbe\x3c\xbf\xfa\xdb\x9f\xff\xe5\xef\x7f\x93\x7e\x3b\xd9\x32\xdf\x05\x9c\x9f\xb4\x65\x62\x8d\x39\xe0\x71\x18\x51\x25\x08\xc1\x92\x2a\x2a\x45\x8c\x61\xa4\x38\x94\x8a\x41\x04\x45\x44\x94\x0e\x88\x16\x51\x14\x9d\x2c\x1a\x8c\x63\x22\x18\x03\x42\x42\x00\x7e\xd9\x32\xe2\x61\xb6\x0c\x93\xf2\xb3\x78\x62\x8e\x24\x63\xef\xee\x61\xbd\xd4\x42\x04\x10\x95\x40\x08\x2c\x1e\x10\x8b\xf3\xd9\xad\x02\xb7\xe9\xe3\x6b\xd7\x7d\x12\xf2\x13\xf1\xc7\x69\x37\xd7\xb3\xe5\xca\xaf\xba\xbb\xd0\x1c\xe4\xa2\x62\xd4\x9f\xd9\x1b\x44\xcd\x43\x06\x74\x0d\x35\x19\x7a\xb3\xa9\x97\x5b\x6f\x58\xdd\x06\xbd\xa0\x9e\x69\x35\xd2\x63\x8d\x29\x35\xd2\xd1\x0e\x96\xab\xc1\xac\xe3\xcb\x6a\x7a\x03\x66\x1b\x69\xf1\x3e\x6d\x85\x30\x56\x85\x87\xd9\x3c\x89\x0f\xdd\xa0\x13\xfa\xb5\xcb\x18\xbc\x53\x3e\x3e\x87\xf2\x40\xf9\xf7\xde\x42\xf0\x40\x26\xdc\x74\x4a\xf3\x7b\xe4\xdf\x1e\x23\x72\xe3\xb9\x95\x5b\xda\x7e\x16\xe4\x7e\x74\xcb\xc7\xb7\xf6\xdd\xf9\xd4\xe4\xf5\xf2\x9f\xce\xad\x54\xf7\x83\x5c\xa6\x1a\xba\xd6\x7e\xe5\xee\x66\x83\x6c\x1d\xfb\x41\xa6\xb8\xde\x78\xab\x5e\xe4\x7a\xd9\xfc\x0c\x14\xf2\xc0\x2c\x86\x9b\x51\xbf\x9c\x73\x47\xbd\x56\x33\x4d\x3b\xeb\x94\xf6\xaa\x58\x95\x1b\x0d\xb4\x70\x50\xb5\x91\xe6\xeb\x42\x71\xeb\xa5\x88\x6e\xb5\x65\x07\xff\xf4\xfd\xa0\x98\x50\x1d\xf3\x58\x50\xc5\x74\x80\x24\xd7\x38\x96\x92\xc4\x5a\xc7\x88\xcb\x90\x61\x01\x11\x43\x82\x09\x18\x46\x90\xe3\x00\xc6\x0c\x52\x28\x68\x40\x30\x13\x9a\x9c\x32\x92\x21\xf1\xb0\x98\x4f\x26\xe5\x67\x31\x9f\x1c\x49\x21\xde\xbd\x6c\xed\xa5\xf6\x89\x33\x12\x91\x47\xf8\xcc\x1f\x64\x8f\xf9\xc0\x67\xfe\xf8\xfc\xd9\x3f\x7e\xef\xc2\x0d\xcb\xdf\x2f\xf0\x71\x1e\x38\x39\x13\xe5\xd5\x26\xdf\x0c\x97\x1e\x2e\x39\x9d\xe3\x62\xbb\x49\x51\x97\x77\x9a\x03\x52\x9e\x66\xc7\x71\x58\xdc\xac\xa7\x9c\x1d\xc6\x9e\x1a\x6e\x76\xc5\x5e\xd8\x74\xd1\x78\xa1\xbc\x78\xcc\x69\x34\xab\x36\xbb\x87\xcd\xb2\xb0\x76\xaa\x70\x39\x2a\x7d\x25\x83\xf4\x4f\x73\xe3\xf5\xba\xc2\x4d\xb1\x9b\x3f\xc8\x19\xf3\x27\xda\xfb\x3d\x5c\x4a\x2c\xf9\x3c\x9c\x0b\xc6\x37\x70\xec\xde\xf6\xda\x1f\xb4\xf7\x4d\x8e\xfd\x21\x8e\x3c\xaa\xef\xce\x19\x6b\x6e\xe6\x18\x2a\x05\x6b\xc1\xda\xfd\xba\xb1\x1e\x74\x8a\x83\x96\xcb\x40\xf9\x98\x69\x09\xb6\xe4\xdb\x4d\x6d\x03\x61\x6e\x63\x75\xf7\xb4\x83\x0e\x7c\xd9\x4d\xa5\x56\xf3\x66\x36\xc7\x57\x26\x71\x61\x66\x3d\x0f\xa6\x76\x96\xea\x54\x27\xb0\xa0\xab\x96\x8b\xc3\xb2\xd6\x90\x01\xb5\x7e\x3a\x03\x35\x0a\x20\xe1\x98\x46\x3c\x04\x14\x02\x89\xa9\x24\x84\x04\x2a\x8a\x04\xd7\x3c\xd6\x12\x29\x29\xb4\x44\x92\x46\x28\x0c\x18\x0c\x01\xd5\x88\x46\x30\xe6\x5a\x43\x10\x47\xf8\x89\x63\xf8\x61\x1c\xfb\x2c\x0f\x00\xc7\x00\x7c\xe0\x2f\x61\x00\x78\x02\x63\x8c\x3e\x62\xdb\xfb\x83\xc4\x9a\x1f\x60\xec\xa3\x24\xef\xaf\x7e\x2f\xe1\xfe\x14\x36\x1e\xd4\xfb\xd2\x46\xf4\xa3\x58\x44\x95\xaa\x6e\x16\x3b\xc8\x72\xf9\xaf\x99\xd4\x6e\xe7\x9a\x4e\xb6\x93\x2f\xb5\x5d\x57\x16\x26\xad\xa5\x37\xeb\x5a\x6b\x54\x67\x41\x1a\x6e\x7c\xbb\x95\x9f\x6e\xb7\x7e\xda\x9e\xe5\x4b\xb4\x36\x6f\x0d\xfb\xa8\x6b\xae\x30\x68\xf9\xc6\x5f\x88\xb1\x7b\xb1\x90\x49\x7e\xf7\xad\x3e\x7d\x70\x7b\xad\x9f\x68\xef\xf7\x60\x2c\x71\xf2\xe6\xe1\x58\x30\xbe\x01\x63\xf7\xb6\xf7\xea\x4b\xe4\xfe\x10\x46\x1e\xd5\x77\xe7\x64\x9e\x37\x63\xcc\x5c\x8e\xca\x9d\x55\xa3\xb8\xcd\x75\x3a\xe9\x6c\x63\x88\xc7\x26\x94\xbd\xfd\x66\x87\x94\x6e\x8d\x07\x4e\xa6\x06\x0f\x0d\xa7\xdf\xdf\xd6\xe7\xe3\x00\x14\x5c\x8f\x47\xa3\xcd\x64\x2b\xc3\x49\xc6\xa9\x77\x39\x47\xd5\x7d\xc1\x6c\x54\x9a\x41\xcb\x27\xd1\xc4\x5b\x96\xa5\xd3\xfe\xe9\xab\xaf\x49\x2c\xa9\x14\x08\xb0\x20\x84\x5c\xc5\x88\x87\x54\x61\x1d\x4a\x2d\x01\x8b\x18\xd6\xa1\xd6\x88\xa1\x73\xa2\x01\xa4\x83\x30\x8a\x50\xa8\x34\x0f\x63\x88\x94\x52\xf1\xb3\x3b\x46\x1e\x86\xb1\xcf\xae\x93\xe3\x18\x20\xfa\x7e\xf8\xd6\x73\xed\x99\x63\x10\x00\xf6\x88\xd0\xf5\x0f\x2e\x52\xf8\x9e\x2d\x4c\x23\x62\xa5\x63\xd6\x1a\x36\xa3\xda\x3a\x3b\x3b\x1e\xad\xa9\x85\x87\x79\x23\xb5\xa9\x59\x66\xb0\xc4\x55\x6f\xbd\xc9\xa6\x09\x9e\x4f\x6b\x95\xe3\x08\x66\x47\xb3\x6d\xbe\xea\x41\xff\x70\x54\xf3\x4a\x98\x2e\xeb\x4d\x33\x5d\x2c\x94\x8f\x2b\x5d\x04\xd5\x7c\x39\x58\xb5\x3a\x70\x6c\x3c\x72\x0b\x33\xf1\xa1\x3f\xcc\x07\x2b\xf9\xdd\x37\xca\xa3\x79\x66\xff\x44\x7b\xbf\x87\x67\xaf\xc7\xfb\x91\x7c\x30\xbe\x81\x67\x0f\x6a\xef\x9b\xf6\xe4\x77\xf0\xec\x56\x9e\x3c\xaa\xef\xce\x17\x1e\xdc\xcc\xb3\xef\x52\x3a\x3f\xc9\x33\x41\x51\x18\x20\xaa\x81\x26\x41\x00\x89\x0c\x10\x8a\x14\x94\x38\x54\x21\x23\x34\xd0\x52\x87\x01\xc2\x9a\xc7\x9c\x60\xc4\x01\x8f\x71\x28\x21\x20\x9c\x68\x19\xb2\x80\x86\x4f\x3c\xa3\x0f\xe3\xd9\x67\x17\xd4\x71\xfc\x4b\xfa\x07\x3c\x3b\xd7\x3e\xf3\x8c\xf0\x47\xa4\xc5\x79\xf3\xe8\xe1\xb9\x7c\x29\x1c\xf9\x6d\xbe\x5d\x18\xf1\xba\x24\xfd\xb4\xa9\x73\x54\x6c\xb4\xd8\xe9\x43\xae\x48\x1a\xc7\x9c\x15\x2e\x53\xc2\x6d\x56\x5c\x77\x05\xdb\x74\xa8\x3a\x74\x50\x2f\xef\x88\xa5\x67\xd3\xa3\x67\xd4\xc6\x7a\xe8\xe7\x65\xb9\x32\x4d\x77\x46\x4b\x35\x33\x65\x76\x1b\x89\xbe\xa2\xe3\xf2\x3e\x05\xfb\x52\x42\x77\x9f\x6f\xe6\xff\x42\xae\x3d\x88\x13\x6f\xf6\xa7\xf1\x0d\x5c\x73\x7e\xa2\xbd\xdf\xc3\xb5\xd7\x73\xf6\x91\x9c\x30\xbe\x81\x6b\x0f\x6b\xef\x57\x8f\x52\xff\x21\xae\x3c\xaa\xef\x72\xa5\xdb\xe4\x3f\x71\x2d\xbf\x57\xb8\x32\x2f\xac\xb2\xab\x81\x99\xb2\xc5\xc1\x40\x2c\xbd\xcd\x8c\xad\x7e\x7f\x59\x6e\x6d\x7c\xec\xa4\xfc\xd1\x50\x55\x0c\xbc\xc8\x0b\x60\xd8\xdd\xce\x0c\x99\x71\xa3\x31\x4f\x43\x5a\xc0\x05\x63\x5b\xe3\x38\xce\x75\x2a\xdd\x86\x8a\xd7\x7e\x1c\x47\xb5\x55\xbd\xf5\xd3\xc9\x46\x85\x52\x0a\x28\x24\x14\xd6\x52\x06\x0c\x2b\x45\x65\x18\x44\x3c\xd2\x0a\xc7\x54\x51\xa6\x43\x2c\x09\x52\x94\x08\xad\x22\x02\x42\x85\xa5\xa2\x40\x46\x2c\x04\x02\x46\xe4\x89\x6b\xec\x61\x5c\x13\x9f\x73\x8d\xbd\x7f\xe9\xc2\xa9\x36\xc9\x35\x21\x1e\x91\x2a\xc5\x7d\x35\x01\xee\x3d\x66\x73\xaa\xff\x3d\x7c\xe8\x55\x49\xf8\x6d\xa3\x9c\xc5\xcc\x51\x26\x5b\x95\x7a\xb6\x2d\x7a\x9d\x51\xc9\xcb\x73\x6f\x64\xb3\x72\x7b\x3c\x89\x0a\xee\xa4\xb8\x0f\x06\x39\xe8\x07\xad\x42\x37\x28\xe4\xf7\x47\x5a\x15\x74\x9f\x62\xbb\xe3\xdc\xdf\xef\xc3\x15\xcb\x44\x68\x4c\x16\xfb\xd6\xb0\xce\x3d\xcc\xac\x5d\x6d\xb0\xc8\x18\x7f\xa5\xdf\xf6\x38\x5e\xf4\xde\xb6\x19\x1e\xdc\x5e\xf7\x27\xda\xfb\x3d\x7c\xf3\x5f\x8d\xf7\x23\x79\x61\x7c\x03\xdf\x1e\xd2\xde\x7b\x52\x87\xfc\x21\xde\x3c\xaa\x2f\xdd\xd9\x6d\xf2\x9f\x78\xf7\x5d\x4a\xe8\x47\x79\x87\x11\x80\x00\x12\x21\x00\xe0\x38\x16\x3a\x8e\x59\x8c\x60\xa0\x39\xd3\x14\x2a\xa4\x48\x1c\xc4\x14\x63\x4d\x29\xd0\x2a\xc2\x0a\x21\x40\x43\x22\x02\x20\x91\x64\x20\x78\xe2\x1d\x7f\x18\xef\x3e\xbb\x10\x82\x63\x20\xc9\x47\xdb\x6b\xe7\x7b\xc6\xcf\xb8\x83\xbf\xda\x78\x3f\xee\xb2\xaf\xc6\xff\xaf\x3b\x55\xba\xf6\xd7\xe3\xd5\xa2\x54\xd3\xde\x0c\x36\x67\x4d\xe4\xfa\xc3\x10\xf7\x29\xda\xd9\x85\xed\x74\xb6\x31\xeb\x15\x56\xf4\x2a\x70\x3f\x49\x1b\xcb\xfe\xda\xab\xa4\x57\x1d\xba\xc0\xb4\xbe\x16\x99\x61\xe0\xb7\xed\x81\x33\x9d\xa7\xea\xde\x10\x39\x5d\x53\xc8\xca\x6a\x67\x8e\x23\x63\xf7\x57\xe2\xf0\x21\x78\xf9\x20\x52\xf9\x75\x79\x34\x1e\xb3\x7f\xa2\xfd\xdf\x18\x29\x9f\x98\x0f\xdf\x89\x1f\xe3\x1b\xf0\xf9\xd7\x47\xfa\x7f\x03\x72\x6f\x45\xde\x77\xf4\xff\x35\xf2\x9f\x90\xfb\x5d\x8a\xee\x27\x91\xcb\x01\x88\x03\x42\xc2\x90\x00\xcd\x82\x08\x29\x2a\x84\x60\x94\xa9\x08\x69\x1e\x8a\x48\xb0\x48\xe3\x08\x53\xca\x43\x46\x71\xa0\x99\xe0\x84\x30\x06\x39\x8d\x18\x91\x88\xff\x42\x2e\xbf\xff\x3e\x8b\x4f\xe3\x31\x29\xa3\xe4\xdd\xfb\x2c\x4e\xb5\xf8\x82\x6e\xf4\xcb\xb5\xbc\xff\x3e\x8b\xd7\x77\x2f\xfc\x7e\x9f\xc5\xf5\xda\xf7\x9d\xfb\x2c\x32\x0b\xec\x56\xad\x96\xae\x55\xe3\xdd\x62\xdd\x26\xd4\xed\x96\x07\xcd\xc8\x93\x43\x66\xcb\xf2\xea\x98\x1e\x97\xfc\xb6\x6a\x5b\x6d\xd7\xec\x1a\x56\x7d\x65\x0f\xec\x59\x27\x58\xc2\x6c\xdb\x29\xb0\x68\x39\x5f\xaf\x5c\x7b\x2c\xab\x2c\x27\x63\x6e\x22\x37\x53\x08\x89\xef\x95\x1e\x75\x9f\x45\xf2\x0d\xb9\xf2\x3e\x89\x96\xaa\x69\x33\x71\xed\x4c\xf9\x4d\xc9\x9f\x6c\x8c\x3d\x50\xfe\x4d\xf7\x69\x24\xee\xb3\xb8\xe3\x0e\x85\xd6\xde\x21\x85\x7b\xef\x50\xf8\x83\x77\x38\x18\xc6\x9f\x8b\xc5\x7f\xd3\xe1\xeb\xde\xde\x17\xbf\xc6\xa2\x98\x38\x58\x02\xae\xec\x8b\x7b\xc7\xe2\xf5\x5c\xb8\x46\xfe\x13\x7d\x82\xf5\x7e\xb8\x83\x9d\x51\x03\x8b\xc2\xb2\xb5\xa9\xd4\x26\x0d\x7f\x9c\x6d\x56\xfd\x54\xbf\xda\x08\x4b\x69\xda\x70\x9d\xa9\xd3\x83\xfd\xde\xc4\x33\xc0\x32\x93\xeb\x17\x1c\xb4\x90\x35\xd8\xaf\x6f\xa6\x01\x0b\xc3\x4c\x3f\x1f\x37\x52\x83\x6a\x27\xb5\x5b\xf7\x7b\xf5\x49\xca\xb5\xad\x1f\x76\xf8\x02\xce\x34\x40\x0c\xc4\x2c\x14\x58\x31\x1d\x48\x1c\x53\x42\x23\xc8\x23\xcd\x11\x54\x80\xcb\x48\x61\xa8\x05\xd4\x9a\xea\x48\x11\x18\x43\x2a\xb5\xa2\x71\x48\x04\x39\xa9\x7c\xf4\x7c\x53\x79\x86\xb9\x65\x5c\xcc\x37\xdb\x2c\xef\xd7\xb8\x6d\x55\xf2\x84\xb7\x32\x59\x6e\x11\x5a\x22\xf9\x76\xb6\xe3\x16\x58\x31\x9b\xaf\x19\x76\x8e\xe6\x33\xf5\x32\xb2\x32\x9e\xcf\xbd\x5f\xd4\x00\x1c\x73\x02\x05\x22\x9f\xe7\x11\x62\xe2\x83\xfb\x2c\x4e\xb5\xa7\x80\x4a\x08\x19\x93\x90\x62\x2e\x5f\x02\x51\xb2\xfb\x09\x6f\x4f\xc6\xdb\xfc\x3e\x4b\x33\x9b\xc6\x51\x7a\xd3\x54\x75\xda\x56\x0d\x5f\x1e\x0b\x62\xc5\xfc\x5e\x6e\xb8\xf0\x0e\xe1\xcc\xf7\x5f\x26\x77\x26\x91\xcb\x23\x31\xd9\x5e\x4d\x90\xe4\x0d\x80\xa2\xbb\x81\xf3\x79\x78\x50\xb5\x94\x17\x8e\x44\xba\x99\x4f\x0f\x29\x9c\xda\xa8\xaa\x0e\xdb\x62\x65\x92\x33\x73\x6c\x54\x9a\x30\x37\xb9\x6a\x1a\x1d\xdb\xcd\xc4\xbc\x4e\x6e\xf4\xbd\xb4\xc7\xcb\x2c\x8e\xa6\x6f\x6d\x8a\xfe\x34\x3d\xec\xf4\x63\xbb\xb5\xb7\xdd\x41\xaf\x64\xe6\xdd\x59\x25\x63\x16\x24\x1a\x37\x43\xdc\x9c\x40\x5a\xed\xed\xea\x79\x86\xd7\xe5\x71\xca\x99\x67\x45\xea\x40\x55\x6a\x62\xae\xd2\xcb\xa3\xda\x46\x87\x99\xdc\x74\xa2\x59\x14\x91\x62\xa7\x3d\xf0\x7a\x5f\xf1\xea\x5e\x07\x94\x1a\xb7\xf4\xe7\xb9\x34\xbf\xaf\xbf\x5e\x9d\x0f\xbd\xfc\x5b\x82\xa3\x09\x4f\x22\x76\xc3\x75\x10\xb4\xc5\xd4\x8e\x47\x2e\xad\x56\xa1\x19\x93\x54\xd4\xdd\x97\x87\xb8\xb4\x3c\x1c\xe7\x03\x63\x50\x99\x5b\xf9\x4d\xbf\x7f\xfa\xd2\xe5\x26\xda\xcc\x6f\x59\xb9\x13\xe5\x13\x8e\x3e\x4e\xfe\xbd\xb7\x16\x06\x89\xaa\x2b\xc7\x20\x11\x44\xe8\x7d\x20\xf3\x63\xdd\xfd\x68\xf9\x9f\xdd\x5a\xf8\x74\xe6\x58\xc1\xf1\x7b\xcd\x7a\xf9\xe4\xc9\x29\x3a\x6f\xae\xff\x2f\xcc\xf1\xb7\x79\x7c\x43\x9f\x3e\xd9\x06\x1f\xd9\x1f\xdf\x3a\xa6\x4f\xe7\x2b\xae\x96\xff\xc4\x63\x77\x59\xca\xf7\x2a\x64\x3d\x88\x53\x65\xed\x88\x5a\xc7\xf6\x82\x82\xb1\xcb\x8d\x82\x1e\xb1\x73\x4b\x1c\xb4\x6a\xdb\xa8\x1e\x76\x46\x29\x2b\x93\x9b\x2e\x35\x40\x1d\xd2\x1e\xc5\x47\x5e\x1c\x1f\x99\x5f\x38\xa6\xb6\xe5\x83\xc4\x85\x21\xa2\x11\xea\x43\xdc\x5b\x47\x41\xfe\xa7\xef\x66\x90\x28\x60\x94\x28\xce\x24\x63\x81\x62\x30\x50\x4a\x46\x31\x08\x39\x8d\x25\x54\x61\xa4\x71\x48\x29\x54\x52\x4b\xce\x18\xc7\x40\x20\x1e\xc4\x04\x45\x50\x23\xc2\x95\x7a\xe6\x31\x7a\x18\x8f\x3f\xcb\x69\xcc\x99\x04\x1f\xe0\xf8\x5c\xf9\x4c\x63\x2e\x2e\x5e\xe1\xed\x34\xfe\xe0\x94\x5e\x62\x7a\xb4\x5a\x8d\xda\xd3\xff\x5e\xa9\x69\xbf\x48\xe3\xd0\x96\x0d\x3e\xcb\x14\x66\x65\x90\xae\x63\xa3\xc5\xdd\x59\xbd\xa6\x53\xfb\x06\x97\xf5\x71\xbb\x6c\xfa\xf6\xba\x08\x6b\x55\x7b\x5f\x14\x4e\xb1\xbf\xa3\xb6\xb5\xea\x14\x67\xc6\x36\x97\x09\x33\xdb\x6c\x6e\x29\xcb\x05\x55\x5d\xb7\xad\x43\x5f\x65\xc7\xb9\x4d\xd0\x2d\xe4\x7a\xe2\x87\x69\xec\x7f\x5f\x7f\xfd\x2c\x8d\xbf\x76\x2f\xfd\xd9\x58\xc3\xe5\xee\x47\x2a\xe6\xd1\x74\x4a\x64\xbc\xf8\xad\x2d\x17\x21\xa7\xff\x7e\x46\xa7\xd3\x77\x4a\xdf\xd1\x7f\x5f\xbb\x57\xff\xcf\xf5\xdf\xef\xa1\xdc\x9f\xf4\xdf\x65\x4e\xbe\x2a\x77\xd3\xfd\x87\xdf\x99\x0b\xdd\xff\x10\x5d\x8d\x6f\x18\xd3\x6b\xe4\x3f\xdf\x5d\xbc\x6a\xc0\xea\xa6\x67\x2f\x7a\xb8\x21\x8b\x2a\xd3\x59\x05\xfd\xbc\xc3\xb9\x53\xdd\xc2\x42\xcb\x07\xf9\x5e\x1d\x6c\x5b\xb6\x68\xd8\xdb\x5d\x73\x93\xb5\x46\x5e\x65\xaf\x36\x3d\x53\xf4\x9c\x95\x2b\xd4\x60\x0b\xc0\x7c\x97\x82\x7e\xb5\xe0\xec\x74\x73\x40\xe7\xa3\xd9\xc0\xfa\xe1\xb5\x5e\x0a\x18\x55\x11\x57\x92\xab\x38\x64\x71\x18\xf3\x28\x10\x44\xe2\x50\xeb\x88\x70\x1d\x21\xc5\x75\x1c\xe2\x10\x80\x90\xf3\x80\x28\x89\x98\x44\x3a\x22\x82\xc7\xa1\x60\xc1\x29\x9c\x88\xde\xbf\xd6\xfb\x69\x8e\x17\x2e\xc5\x07\x9b\xaa\xcf\xb5\xcf\x56\x02\x23\x92\xdd\xbf\xd6\xfb\x7a\x5d\xf2\x37\x8d\x79\x83\x86\x7b\x6f\xad\x77\xdd\xdf\x35\x70\xde\xec\xd1\x5c\x77\x54\xa8\x95\x0b\x78\x9e\xcd\x04\x69\xed\x8a\xe3\x42\x18\xb1\xec\x39\xd5\xf6\xd8\xdf\xda\x51\x6d\xc6\x86\x47\x83\x5a\x32\xf6\x2b\xca\x9a\x17\x2c\x1c\xd9\xc6\xa6\x5a\x2c\x97\x8d\xec\x50\xae\xcb\x61\xb7\x99\x37\xf0\x72\xb7\x2f\x4b\x92\x79\xd8\x5a\x6f\xe2\xf3\x57\xae\xb5\x76\xf6\xf5\xf2\x84\x5f\xbe\xfe\xfa\x0e\xab\xa7\xf2\x89\x8f\xfa\x38\xf9\x37\xad\x35\x27\x7c\xd4\x3b\xd6\x17\x63\x27\x87\xc2\x7b\xd7\x17\xff\xe0\xfa\xa6\xf1\x5a\xfe\x0f\xfa\x73\x6f\xae\xf5\xb6\x6e\xef\x8b\x5f\x63\x11\x25\x24\xbd\xb3\xf8\xfc\x6d\x63\xf1\x7a\x2e\x5c\x23\xff\x89\x3e\xa1\xaf\x6c\x79\xf0\x66\x95\xba\xdb\x35\x47\x8d\xfa\x9a\xd5\x76\xed\x2d\xee\x6f\x4b\x6c\x6b\x64\xd3\x7e\xa6\x01\xe7\xed\xe2\x3e\xdb\x0c\x2a\x33\xb1\xab\x78\xe9\x0e\xb2\xa6\x06\xab\xf7\x24\xae\x19\xc5\xe1\xe1\xd8\xf0\x32\x24\x1d\x36\xda\xa8\x65\x7a\x65\x26\x4a\x8d\x58\xff\xf4\x21\x0d\x00\x31\x61\x91\x86\x2a\xc0\x40\x69\x80\x21\x91\x91\x8c\x29\x91\x84\x4a\xca\x02\x84\x62\xa9\x42\x1d\xe1\x48\xc0\x58\x40\xc5\x50\x18\x52\xa9\x62\xa1\xa2\x48\x84\x42\x9e\x7c\x4b\xf2\x4c\x1f\xe4\xe5\xfc\x06\xca\x19\x4d\xa7\x54\xeb\x14\x8a\xf5\x62\xb1\x5a\xb3\x4d\x93\x55\xcc\x8a\x9b\x2f\x19\x56\xbd\xda\xa8\x15\x78\xc3\x2d\x37\x50\xdd\xa9\x21\xdf\x6d\x5b\x46\xcd\xfa\xcf\x7f\xff\x4f\x02\x28\x09\x86\x18\xc1\x4f\xcf\x68\x48\xf8\x01\x85\x9e\x2a\x21\xc0\x80\x4b\x04\x25\x02\x2f\xa1\x3d\xd9\xa6\xed\x4f\xe7\x46\xc1\xe9\xba\x6c\x7c\x68\xaf\x45\xdd\x74\xe8\x6e\xea\xd6\x77\x06\xad\x4e\x9d\x0e\x9d\x84\xd5\xe6\x60\x0f\x7b\xb0\xff\x32\xb3\x32\x89\x44\x62\x89\x99\x76\xf9\xdf\xf3\x45\xc5\x89\x45\x1d\x98\x71\xf3\xcc\x33\xfb\xed\xda\x66\xae\xc6\xcb\xd8\xee\xf5\xb5\xca\xef\x47\x2b\xa3\xd2\xa0\xfb\x56\xaa\x3b\x39\xc2\xdc\x2a\xf2\xcb\x7e\x62\x62\xd9\xda\x1d\x26\x26\xf5\xdb\x8b\x78\x61\xb6\x6d\xb5\xed\x53\x35\x28\xa6\x98\xb4\x60\x7f\x3f\x3f\xac\x8d\x51\x87\xa9\x6d\x75\x90\xd9\x54\x04\x58\x8c\x45\xdd\x2b\x74\x21\xad\x56\x5a\xfb\xbd\xdc\xf9\x63\x36\xe9\x2e\x8b\x29\xd6\x6c\xbb\x41\x98\x4e\xb1\x69\x0f\x95\x52\x01\x92\x36\xaf\x94\x53\x9d\x15\x61\xbe\x2c\x95\x17\x8d\xbe\x84\x5f\x3c\x91\xf8\xdb\x09\xc1\x4e\x21\xe5\xc0\x7c\x65\x25\x88\x57\xb6\xfa\xd3\x49\x6e\x38\x2c\x34\x2d\x2f\x35\xb1\xb7\x1b\xdd\xdd\x59\xc5\xf4\xda\x6c\xd5\x3a\xce\x70\xaa\xde\x7c\xd7\xcc\xd4\xf6\xc9\x8c\x77\x5a\x4d\xf0\x24\xe8\xca\xb1\x32\x8c\xed\x72\x97\x0c\x07\xb9\xfa\xfb\xc6\x5b\x8b\xf6\x37\x8d\x65\x26\xee\xf4\x3f\x1a\xcb\x77\x01\x9f\xf8\x4c\xe4\xd5\x06\x7a\x64\xcc\x5a\xa3\x70\xd1\xc9\x07\x78\x9f\xcb\x75\xa6\xa6\xea\x16\x0d\x6b\x94\x52\xad\x78\xd2\x5d\xc9\x7a\xf1\x79\x3e\x9c\xdd\xb6\xa9\xf1\x32\x5f\xdf\x29\x9f\x00\xfe\x71\xf2\x6f\x5a\x84\x36\x2f\x6e\x6c\xe7\xf4\xaf\xe7\x1c\xa3\x6a\x49\x3a\xcd\x11\x3b\x1e\xfb\x06\xa8\xb8\xda\x1f\x54\x4a\x73\xaf\x6c\x31\xbf\x9e\xa2\x74\x6a\x94\xb6\x29\x90\x6f\x39\xaa\x5d\x89\x2e\x73\x2a\x31\x47\x1f\x32\xa7\x3e\x48\xe8\x94\x70\x43\x9d\xc3\xb6\x1f\xd5\x1b\xcb\x6a\xc5\xb6\x3c\xd2\xa5\x83\x1c\x39\x8c\x0d\x50\x9d\xf7\x8b\x7c\x3a\x51\xc6\x21\xcd\xbd\x71\xb3\xb5\xf7\x69\xe2\x22\xc2\x8b\xdb\xee\x24\xb2\x14\x5c\xf9\x4e\xdd\x3d\x67\xe3\xf4\x73\x11\xaf\x9f\xb7\xc8\xc4\xbb\xa7\x88\x9e\xdb\xeb\x5f\x3e\x7f\xed\x78\xdd\x3b\x3e\x99\x97\x96\xa7\x5f\x5f\x8a\xfd\x59\x39\x25\x02\x4e\xe8\xa4\x6b\xc7\x6f\xec\x15\xc9\xf1\x34\x41\xce\x46\x50\xcf\x78\xeb\xc4\x55\xe6\x8d\xfe\x4a\x96\xb7\xfa\xf7\xb7\xf7\xf1\xca\xf9\x60\xd6\x4d\xa3\x7f\x5e\xc6\x39\xbd\x8f\x57\x2c\xe3\x7c\xa9\x9c\xc7\xfb\xfc\x7e\xde\x32\xdf\xce\x82\x13\xcb\x24\x57\xea\x9b\xe7\x5e\x81\xc4\xbb\xf4\xd7\xdb\xed\x2f\x19\xff\x5c\x9b\xb9\xb6\xbd\x97\x25\x12\xe7\xf6\x4d\xad\x7b\xe4\xc7\x92\xb5\x5f\xcb\xff\xda\xb2\xe1\xa5\x7f\x7e\x2b\x9f\x18\xf2\x37\xf4\xd1\x59\x90\x73\xfb\x32\xd2\x03\xc7\xe8\x1a\xf9\x4f\x86\xfc\x77\x19\x54\x3f\x69\xc8\x47\x22\x44\x14\x08\x88\x30\xa3\x2c\x84\x51\x0c\xb5\x86\x5c\x21\xce\xb8\x40\x32\x54\x08\x05\x21\x81\x92\xca\x20\x42\x54\x33\xa5\x14\x45\x40\x0b\x22\x29\x64\x71\x18\xc0\x5f\x86\x3c\x7e\x36\xe4\x2b\x05\x9e\xa9\x34\xeb\x95\x76\x35\x9b\x31\xca\x19\xbf\xc4\x4a\xb9\x9a\xdf\xcd\xe7\xac\x5c\xb5\xe9\xe7\xab\x9d\x6c\x23\x6b\x58\x0e\xa7\x4d\xbb\x95\x6b\xf9\xed\x6c\xb6\x52\xf6\xcc\x7f\x18\xf2\x9f\x1d\x4a\x13\x90\x52\xf1\xee\x26\xd1\x4b\xad\x14\x5c\x10\x44\xa1\x04\x2f\x67\xd2\xae\xd4\xd4\x09\x4b\xfe\x83\x4d\xa2\xc4\xaa\xc8\x1d\x9a\xe9\x62\xcd\x7e\x40\xa2\x17\x4d\x9d\x31\x1a\x35\x22\xf6\xfe\xa0\x10\x6e\x84\x51\x99\x75\x9c\xdd\x56\x6d\x73\xc5\x2e\x48\xcf\xbd\x51\xec\x6e\x76\x3b\x63\x96\xeb\x96\x75\xbc\xe4\x87\x28\xb7\x1b\xab\x4d\x91\x90\x4e\xb5\xc4\xe7\xf9\x34\x1b\x5a\xf5\x70\x91\xd9\x44\x8d\x72\x3b\xb2\x51\xbe\x36\xdc\x2c\x78\x36\xc7\x73\xc6\xd7\xce\xa8\xbd\xbd\x61\x74\xbb\x15\xf3\xed\x7d\xf7\x9e\xe5\xec\x24\xbc\x89\x6b\x49\x79\xd9\xf0\x48\x58\xae\x9f\x91\xf2\x52\x32\x0f\x96\xff\x35\x52\xbf\x92\x9f\x79\x6d\x39\x9f\xab\xae\xb4\xc4\x2e\x8b\xf1\xce\xd7\x37\xa8\x5e\xb7\xf1\xd1\xf2\xbf\xb6\xc1\x93\x28\x97\x39\xf4\xba\xa7\x94\xf1\x00\x4b\xfd\x5c\xbe\x5b\x3f\x9c\x2c\x53\xff\x52\x7f\x6d\x7b\xef\xb5\xac\xb2\x17\xa3\xfa\x8d\x3e\x7f\xba\x42\x44\xfd\x65\xed\x7b\xdd\xbf\xbf\x95\xb7\x96\x2f\xdb\xc9\x09\x72\xfd\x7c\xfd\xcd\x32\xfc\x83\xef\xcb\x35\xf2\x9f\xac\x9e\xef\x82\xcf\x4f\x5a\x3d\xa1\x06\x54\x93\x30\x92\x8c\x45\x54\x30\x21\x35\x0c\x59\x1c\x68\x00\xb1\xa6\x41\xc0\x79\x18\x69\xca\x34\x0b\x54\x84\xa2\x50\x86\x92\x09\x0e\x34\xd5\x9c\xb0\x80\x04\xe1\xe9\xa0\x04\x7a\xa0\xd5\xf3\xd9\xf2\xa5\x40\x9c\xf2\x77\x4f\x4c\xbc\xd4\x4a\x42\x84\x44\x82\x30\x20\xee\xb7\x7a\x3e\x58\xbf\x3c\x6b\x99\x9b\xd6\x0f\x3a\xaf\xde\xc2\xf3\xac\x7e\x91\xef\x59\x25\xb3\x1d\x9b\x40\xbb\xe5\xfc\xc6\xcf\x75\xf0\x8a\x1a\xcd\x72\x51\x2f\xa7\x73\x95\x6d\x4c\x45\x85\x1d\x7a\x8b\x74\x79\x87\xeb\x74\x3b\x3d\xa4\xdb\x04\x55\xa8\x4b\x5c\xd6\x5c\x0d\xfa\xad\x26\xdc\x47\x34\xac\x91\xc1\x04\xa5\x5a\x47\x6f\xec\xf9\x5e\x5f\x83\x61\x7f\xf7\xa5\xc0\xd4\xa4\xeb\xfc\xee\x86\x9a\x93\x58\x2f\xbc\x85\xda\xf7\xae\xb7\x3d\x50\xfe\xbd\x41\x9f\x8f\xd6\x82\xbf\x97\x8f\xb5\xe0\x1f\xd4\xc2\xc6\x45\xfe\x8f\xaf\x5f\x9d\xe4\xbd\xb5\x7e\xf5\x54\x3e\xdd\x70\xbb\xa1\xaf\xee\xf6\xd3\x1f\x38\x56\xd7\xc8\x7f\x22\x56\x69\x97\xef\x8a\x62\x8d\xf8\x60\x42\x7b\xfd\x58\x1f\x47\x19\x0f\xac\xd9\x46\x8f\x77\x51\x25\xde\xf1\x65\xc1\x5c\x0a\x6c\x45\xc5\x49\x2a\x2e\xca\x70\xe8\xf3\x51\xd8\x0b\xe7\xf5\x43\xc1\x69\x35\x3a\x0e\x1e\xaf\xb3\x83\x42\x18\xd2\x4e\xd9\x6c\x65\xfa\xa6\xc3\xeb\x95\xec\x4f\x07\x73\xa2\x80\x49\xc1\x03\x26\x31\xd0\x41\xc8\x35\x0e\xb5\x0a\x54\x2c\x43\xce\x74\xc4\x03\xc0\x04\x40\x8c\x09\x05\x63\xa8\x43\x10\x0b\x14\x53\xc6\x21\x80\x24\x24\x21\xc3\xec\x74\x9a\x1e\xde\x1f\xee\xf1\xd9\x91\x0a\x81\x05\x06\xef\xe6\x8c\x79\xa9\x7d\x22\x1f\xc7\x10\xdd\x1f\xed\x51\x7c\x35\xea\xbf\xbd\xc8\x37\x28\xca\x77\xa2\x3d\xac\x78\xde\xd4\xab\x90\x8c\xbc\x74\x2d\xce\xec\x61\x73\xbf\x28\x57\xd6\x5d\x94\x22\x35\x52\x07\x9d\xfd\xb1\xd7\xab\xd6\xa0\x89\xfd\x43\xbf\x6b\x2c\xd3\x05\x51\x38\x74\xcd\x1e\xd1\x43\xab\xe1\x4c\xfb\x1b\xb9\x30\xfa\xc4\x2d\x76\x8b\xa3\x30\xb3\x0c\xdc\xa9\x6a\x48\x4b\xf9\xce\xa3\xa2\x3d\x9c\xdb\xa3\x2d\x54\xd8\x58\x6d\x13\x58\x2a\xbc\x29\xf9\x33\x38\x3d\x4e\xfe\xeb\x31\xfd\x92\xfc\x04\x9c\xee\x88\x30\xd8\xaf\x2b\x07\x99\x78\x92\x77\x6e\x2c\xfa\x58\xe1\xdd\x21\x7f\xd6\x2d\x82\xf5\x1d\xf2\x8d\xd7\xf2\x7f\x50\xe1\xbf\x09\x1f\xef\xf6\xbe\xd8\xaf\x2b\xc7\xe4\x22\xef\xec\xca\xbe\xb8\x77\x2c\x7e\xcd\x85\x14\xb8\x4d\xfe\x13\x7c\x30\x6b\x65\x97\x6e\x2a\x6f\x57\x41\x67\xa7\xa2\x56\x29\x18\x36\x96\xed\x68\xbb\xb1\xb5\xbd\x76\x84\x22\x39\x0b\x44\xde\x1a\x95\x66\x6d\xaf\x90\x3e\x6c\xcd\xd5\xc4\x9b\x55\xb2\xb3\x1d\xd8\x77\x49\xb8\x0d\x7a\x39\x9d\x19\xa0\x3a\x75\x77\x01\xea\xcf\xb1\x9d\xf6\xb0\xfb\xd3\x37\xcb\x49\x46\x20\x0d\x14\x8c\x50\xcc\x25\x43\x30\x44\x2c\x84\x94\x89\x58\x32\x1c\x47\x22\x8a\x98\xa2\x40\x21\x10\x20\xa4\x38\x41\x42\xe9\x38\x8c\xb5\x8c\xb4\x16\x8c\x53\x21\x9e\xe0\x83\xee\x84\xcf\x67\xe7\x07\x04\x16\x84\xbd\x7b\x37\xee\x4b\xed\x19\x3e\x08\x12\xf0\x80\x63\xe5\xaf\xc3\xe2\x7e\x83\xcf\x0d\xbb\xe2\xef\xc1\x27\xca\xbb\xd1\x36\xea\xa2\x3a\xf1\x66\x9d\xa8\x92\xaa\x44\x6b\xd1\xad\x45\xba\xb5\xe1\x93\xcc\x76\xc1\x9d\x75\x55\xce\x46\x8b\xa5\x14\x73\xd7\x4a\x0f\xeb\xc6\x32\x18\x8d\xbd\x6d\x50\x9b\x98\x87\x92\x51\xcc\x95\x2c\x34\x72\x45\x0d\x15\x86\xfd\xc2\xf6\xc0\x67\xb9\x22\xcb\x3d\x2c\xd4\xf0\x0e\xe5\x1f\xb8\x75\x59\xbc\x57\xf9\x3f\x50\xfe\x4d\xa1\x8e\x8f\x81\xcf\x6b\xe5\x7f\x53\x78\xdb\x1f\x0c\xaf\x33\x5e\xcb\xff\xc1\x5d\xc1\x47\x87\x1a\xde\xa3\xfc\x8d\x07\xc1\x27\x69\x88\xdc\x02\x9f\x7a\x6d\x1a\xe2\x76\x34\xda\xd8\x05\x07\x37\xb6\xc3\x69\x18\xbb\xcd\x4e\x67\x1c\x6e\x68\x2f\x64\x9b\x7d\xd8\x48\x07\xf9\xc2\x22\x1d\x17\x6a\xbd\x34\x01\xbd\x02\x9a\xe7\x9b\x45\x34\xea\xf6\x56\x43\xc3\x3c\x58\x86\x9c\x67\xb6\x76\x34\x98\x91\xfa\x52\x6c\x98\x69\xa6\x06\x3f\xbd\x43\x19\x03\x11\x29\x18\x6b\x05\x29\x88\x11\x67\x94\x21\xc1\x98\xd2\x24\xa6\x88\xa3\x98\x51\xa1\x62\x10\x46\x32\x8e\x84\x82\x91\x64\xbf\x20\x04\x25\x0b\x35\xd2\x30\x44\xf4\xe4\xf9\x3c\x41\xc3\xb5\x6a\x6d\xcc\x69\xc9\xf0\x6b\x84\x55\x2c\xd7\x41\x6d\xd7\x28\x7b\x26\xaa\xd5\xba\x45\x5e\x41\x84\x59\x7e\x36\x6b\xba\xed\x46\x0b\xd5\x6c\x9e\xcb\xda\xc8\x6b\x7a\x45\xeb\x3f\xff\xfd\x3f\x26\x38\x94\x84\x33\x8e\x3f\x4b\x23\x26\x88\x80\xf8\xfd\xb5\xba\xe7\x5a\x41\x85\x94\x98\x02\x00\x5f\x02\xde\x2b\xe5\x75\x9a\xed\xdc\x9c\x10\xa4\x3b\x60\x2b\xdf\xf2\x4d\xe8\x56\x5a\xe9\x68\x39\xed\x93\x8a\xaa\x2d\x1b\xcb\x45\xbe\x3a\xab\x34\x9a\x27\xf3\xfc\xbc\x56\x77\xfa\xe6\x07\xb7\xf4\x24\xe2\x44\xac\x4d\x70\xe8\x3d\x7f\x60\x38\xcb\x94\xec\xe6\xa0\x5b\x2e\x36\x87\xab\x76\xa7\x08\x07\x05\x2a\x2d\x09\x8a\x03\xb2\xa3\x0c\x70\x16\x8a\x6c\x61\xdf\x8d\xcf\x3b\x3a\xb5\x56\xab\xfe\xf4\x2b\x9b\xdd\xb6\x7c\x2c\x8f\xe4\x7a\x17\x6e\xf2\xd9\x66\x66\x31\xed\x20\xe6\xfa\x39\x5c\x0a\xcd\x68\xee\x35\xe5\x9a\x4c\x99\xdd\xaa\x75\x56\xe7\x99\xc9\x27\xab\xdf\x66\x6e\x86\x59\x23\x68\xf6\x4e\x01\xf4\x29\x3e\xdc\xeb\x55\xa6\x50\x58\x3a\x98\xe0\xd9\xf4\x70\x50\xc3\x39\x5a\x0f\xbc\x62\x77\xe0\x66\x91\xdd\x18\xa7\x64\xbc\xa9\x2c\x66\xeb\xad\xf6\xd1\x32\xd7\xdb\xae\xe5\xb4\x97\xf2\xf2\x28\xb0\xaa\x38\x55\x9d\x5a\x2b\xdf\x0e\x64\xb7\x19\x18\xa9\xee\x54\xa3\x69\xce\xed\xd9\x5f\xa0\xda\x6f\xb7\xf0\x14\x57\xc5\xa3\x3a\x76\xab\xa1\x72\xf9\xa0\x06\x8d\x60\x0e\xe5\xa6\x3f\x31\xcb\x47\x77\x37\x0d\x9a\x4e\x35\xd4\xf9\x54\xdf\x69\xb6\x78\x82\x04\xa7\xfe\x74\x9c\x56\xeb\xa9\x9f\x4d\x6e\x0a\x5c\x42\x0d\x84\x33\x1b\x32\x8a\x3c\x77\x11\xc5\xe1\xac\xdb\x1b\xaa\xfd\x2a\x8f\xc6\x99\x06\xc2\x83\x78\x56\x6b\x39\x7a\xff\x7a\x4c\xfe\x8e\x31\xfa\x7f\xef\x13\x3e\xd1\x4c\x82\x70\x7a\x69\xf8\xc3\xe3\xb1\x3f\x29\x2e\xf6\xbd\x72\xaf\xd8\xf4\x69\x47\xa2\x8d\xce\xf6\xe8\xde\x5d\x57\x36\xb3\x51\xaa\x47\xcb\xde\xf9\x88\x54\xcb\xd8\x0e\xe0\x65\x66\xde\xb4\x63\xf9\x40\xf9\xd6\x2d\xf2\xcf\x8d\x3e\x51\xa5\x91\xf8\xbe\x6d\x56\x7a\xf6\xae\x56\xcf\x8f\xc0\xba\x5e\xd9\x77\xd5\xb6\x9d\x5b\x4e\x41\x15\x7b\x9b\xe2\xd0\x9a\x2e\x1b\xdb\xf9\x76\xa7\x96\xce\x58\xdc\x3b\x57\x4e\x47\xd2\x3e\x5a\xfb\x7b\xf9\xbb\xf9\x47\xda\x57\x2c\x7a\x9d\xb7\x63\xeb\x12\x25\xd1\x7f\xe7\x79\x7e\xed\x5c\xbd\x0c\x45\xb3\xd5\x6a\x3e\xbd\x2b\x37\xbd\xbb\x97\x77\xed\x6b\xb1\x9a\xd7\xf6\xc7\xe5\xfb\x8f\x7e\x7f\x6e\x9a\xbf\xf7\xc8\x77\xb3\xb6\x7f\x87\xfc\xd3\xe7\xed\x84\x31\x79\xe5\x78\xbd\xfd\xfc\xbf\xa5\xf2\x7b\x33\x36\xf1\xa2\xdb\xde\x3c\x12\x9b\x78\x5f\xce\xe5\xca\xf9\x58\xa8\xce\x17\xc7\xe6\x45\x7a\xc9\xf8\x7a\xac\xdd\xa5\xbc\x3e\x62\xfa\x86\x25\xdb\x48\x74\xe7\x30\x8c\x53\xab\xcc\xa0\x5a\xad\xb8\xfe\x66\xe9\x1a\xc8\x58\xd7\x86\xe3\x18\x07\x94\x68\x6b\x6a\x07\x80\xb1\x41\xe3\x85\xb1\x89\x5d\xdf\x73\x1b\x6f\x8a\xd2\x68\xde\x27\xbf\xd8\xbc\x4d\xfe\x93\x25\x1b\x6f\x88\xe8\x2c\x8d\xfa\x60\xb1\x8f\x52\x65\x96\x17\xab\x69\x8e\x45\x4b\x7f\x64\x22\xbf\xdf\x97\x7d\x9b\xc6\xdb\x0e\x1f\x2e\x16\xc5\x10\x4f\xca\x8b\x43\xae\xc8\xe3\x2e\xa9\x8e\xcc\x68\xd2\x3b\xca\xf4\x90\xee\xb8\x9b\x71\xb7\xed\x96\xdb\xab\x4e\xba\x78\x3d\x3f\x64\x66\x3f\x9d\x11\x17\x4a\x21\x08\x51\x22\x24\x1c\x45\x41\xa0\x14\x0d\x39\xe4\x4c\xd2\x80\xa8\x00\xb2\x40\x71\x29\x03\x88\xe3\x10\xa9\x98\x40\x8a\x22\x28\x35\x82\x90\x07\x1a\x2a\xca\x4e\x09\x19\xa0\x7c\xa0\x25\xfb\x69\xac\x1d\xa3\x92\xf1\x77\x2d\xd9\xe7\x5a\x01\x19\x20\x58\x20\x8e\xc0\xfd\x96\xec\x07\xb1\x76\xe7\x59\x73\xd9\x75\xbe\xc7\xca\xf1\x72\xcc\x68\x64\x9c\xdc\xa4\x51\x87\x39\xee\x8c\x0f\xd2\x1f\x6c\x62\x2f\x1d\x99\x64\x53\xaa\xe8\x75\x25\x35\x49\x67\x0e\xab\x76\xe7\x70\xfa\xf8\x1d\xa4\x79\x75\x38\x3b\x51\xb2\x2f\xcf\xef\x95\x56\x72\x5b\xee\x52\x28\x66\x7e\xb3\x34\xc7\xa2\x11\x8c\x66\xdb\x76\x3a\x6d\x59\x8d\x70\x95\x96\xb3\xea\x10\xd6\x8c\xc1\x9e\xda\x63\x33\x1d\xf1\x5e\xd8\x0e\x82\x72\x39\xbf\x2f\x78\x35\xae\x4b\xe5\x0a\x5b\x66\x52\xd3\xb5\xbb\xd0\x9a\xb4\x37\xcb\x46\xbe\x67\x90\x11\xda\xad\xbe\xb2\xeb\x6d\xbe\xea\xdf\xdb\x48\x9a\xf8\xe9\xcb\xf3\x26\x76\x39\xef\xb0\x8a\xff\x88\x55\xfe\x9a\x14\x89\xbf\x7f\xce\x2a\x4f\x26\x47\x78\xdf\x2a\x4f\x52\xf5\x06\xab\xe2\x29\x8e\xd0\x30\x6e\x8d\x63\x7c\xa0\xfc\x9b\xbc\x02\xf3\x42\xc8\x5a\xe2\xfb\x3f\x67\xf5\x9e\x9b\xf2\x15\xab\xfc\x2f\xf6\x1a\x4e\xfd\x57\xbf\xb4\xef\x5a\xc2\xdf\xfb\xae\x5f\xdb\x7f\x3f\xd8\xbe\x2f\x8d\x6f\xa2\xff\xfe\xb4\x57\x73\xf2\xc2\xce\x8d\x4e\xcc\xb7\xf7\xfb\xf3\x4f\xb7\xf7\x4b\x5e\x58\xa2\x7f\x8d\x5b\xda\xfb\xda\x02\x2d\x19\x5f\x8e\x13\xbe\xf4\xe7\x9b\x4b\x59\xe7\xb8\xd6\xc4\x96\xc1\xb5\xf3\x6b\xec\x15\xc9\x79\xc9\xff\x2c\xfd\xf5\x75\xf6\xc9\xb6\xbc\x94\xf3\x53\x54\xe8\xf2\x69\xa3\xfe\xcd\x44\x3a\x67\x3e\x24\x4e\x98\xdd\xc9\xf6\x3b\x6c\xaf\x04\xd0\xbd\x37\x9f\xcf\xf8\x27\x4f\xfe\x74\x7b\x13\xfd\xf9\x76\x7b\xdf\xda\x6b\xa8\x25\xba\xfe\x06\x0f\xe9\x1c\xe5\x64\x5f\xc6\xf7\x5a\x0f\xed\x81\x1e\xe2\x0d\x71\xc1\x87\x23\x12\x70\x3a\xed\x1c\xfa\x7d\xef\x30\x8d\xf7\xe5\x45\x7d\x20\xc3\xb4\x28\x95\xcb\x9b\x63\x1a\xf5\x52\xd5\x96\x6d\x16\xb3\xa3\x7a\xb3\x28\xf1\x26\xb3\xee\xce\x67\x00\x4c\xed\x79\x26\xbb\x26\x3b\xc0\x17\xab\x2c\xd3\x20\x98\x53\xde\x0f\xd8\xba\x34\x31\xac\x41\x23\x34\x7f\x38\xa9\x8e\x04\x28\x94\x40\x21\x8c\x50\x28\x35\x0b\x31\xa6\x9a\x53\x82\xb1\x90\x01\x27\x84\x85\x82\x69\x0c\xb0\xd4\x61\x4c\xa5\x56\x8c\x45\x71\x1c\x52\xa0\x03\xad\x40\xa4\xc4\xe9\x7e\x10\xf1\xe4\xa1\x19\x9d\x92\x43\x70\xc3\xed\x66\xdb\xd8\x2b\xe3\x9a\x5d\x69\x1a\xa8\x49\xab\x6d\x9a\x69\x18\xb5\x8e\xeb\xfa\x79\x9c\xcf\x39\xd9\x36\xf6\x1b\xcc\xab\x15\x6a\x45\x6c\x56\xab\xcd\x7f\x78\x68\x9f\xc6\x05\x0b\x02\xe4\xfb\x1e\xda\x73\x2d\x3f\x5d\x6d\x02\x29\x41\x2f\xa7\xa1\xae\xd4\x52\x09\x0f\xed\xb3\x9b\x24\xaf\xb5\x02\x1f\xe4\xd1\x9d\xe4\xbf\xb4\xd7\x33\x65\x07\xe5\x70\xf7\x08\xf7\xd8\xf0\x4a\x8b\x22\xe9\x98\x47\x5d\x6d\x8c\x77\xd3\xd9\x68\x8b\x32\xde\xb4\xed\x4e\x1a\x00\xf0\x59\x96\xca\x5e\x30\xc0\xba\xbc\xe1\xe9\x76\x6b\x96\x5d\xb7\x45\x7f\xd5\xcb\x0e\x57\x70\xd2\x2d\x70\x20\x9d\xe3\xb1\xe6\x20\x15\x5a\x68\xed\xd9\x5f\xf1\xa8\xde\xbe\x66\xe1\xb5\xd5\x9e\x58\xbb\xba\x73\x2d\xec\x9d\xf2\x89\xd5\xfe\x38\xf9\xb7\xc5\x11\xbf\x69\xb5\xff\x6d\x56\xdd\xe9\xef\xbf\xd4\x2a\xfe\x2c\xd4\xea\x16\x0b\xc9\xfb\x78\xe4\x5e\x4b\x78\xaf\xaf\x6e\x96\x9f\x24\xe0\x35\xf2\x9f\x08\x54\x84\xb1\x3f\x8c\xa6\xd5\x4e\x56\x65\x8c\xc3\x6c\xdb\x57\xc5\x32\x91\x95\x8e\xa9\x07\xf5\xb4\xef\x98\x91\x1f\x74\xab\x8d\xc6\xa6\x17\x4f\x51\x66\x51\x8c\x08\xe2\x5b\xd9\x6d\xf7\x34\x0c\x0f\xee\xc1\xd0\x95\x63\xbb\x3b\x5a\x6e\x1b\xa0\x53\x2d\xdb\x9d\xee\x7e\x55\x0d\x7e\xfc\x3c\xae\x0a\x38\x65\x11\xa4\x50\x2a\x1d\x05\x5c\xc6\x82\x23\x04\x08\x0a\x21\x52\x3a\xe0\x61\x00\x00\x51\x38\x8c\x24\x83\x41\x14\x32\x14\x52\x19\x0b\x11\x08\xc6\x63\xc1\x74\x88\x9f\x08\x84\x1e\x45\xa0\x4f\xd7\x08\x05\xc1\x9c\x7e\x40\x20\xcc\xd9\x85\x40\x92\x5e\xd6\x08\x6f\x27\xd0\xd5\xe7\x71\xaf\xb5\x23\x2f\x58\xb1\xdf\x92\x77\x2e\xb5\xe7\xcf\x67\x8c\xe2\x26\x18\x50\x6f\xaf\xb4\x13\xae\x8d\x81\x49\xa7\xa3\xe9\xba\xdc\x9a\x6e\xeb\x55\xdd\xae\xa5\xcc\x94\xd3\x9b\x8f\xab\x46\x54\xeb\xd5\xea\xa9\x6a\xd5\xae\xcf\x9b\x83\xba\x79\xd8\x0c\x76\x9b\xfe\x64\xbb\xb1\x76\x7c\xb4\xdb\x4f\x53\x06\xb3\x41\x89\xa8\x00\xae\xd0\xe2\x58\x32\x7a\x77\x9c\xc7\xbd\x49\x1b\xda\x3f\xd2\x77\x3f\x40\xc4\x9b\x88\xf4\x40\xf9\xef\x9c\x25\xfc\x72\xfc\xd8\x03\xfd\xdc\x77\xb2\xb0\x7c\xab\x16\xbf\x7a\xa7\xe7\xb7\xfa\x37\xfd\xec\xd3\x27\xef\xdd\x8d\xfd\xe1\x39\x7e\x21\xf3\x1f\x22\xa3\xf1\xa0\x31\x4d\xfa\x86\xd7\xc8\x7f\x26\xf3\x37\x29\xc8\x9f\x24\x33\xe6\x61\xc8\x65\xcc\x24\x95\x0a\x68\xa1\x65\x88\x23\x0c\x63\xa6\x24\x06\x22\x12\x11\x10\x24\x92\x8a\x71\x82\x54\x1c\x50\xa6\x02\x20\x89\x8a\x03\xa6\x03\x2d\x25\x41\xcf\x64\xc6\x8f\x22\xf3\xa7\x71\x68\x82\xf0\x0f\xce\x8c\x3e\xd7\x9e\xc9\x8c\x30\xbb\xc4\xa1\xdd\x4e\xe6\x0f\xe2\xd0\xce\xfb\xe2\x77\xc4\x28\x9d\xca\x6a\x9d\xd1\x89\x59\xfd\x4e\xa6\x8c\x0b\x99\x97\xc7\xb9\x74\xf6\xfb\xc5\x38\x75\x98\x1d\x56\xbd\xb1\x35\xec\x4c\x64\x6a\xb9\xca\xeb\x72\x07\xb9\xab\x7a\xc0\x1b\x95\x03\x36\x8e\xd9\xca\x86\xf8\xb4\x2b\x72\xe6\x9e\x22\x4f\x08\xda\xf3\x5c\xaf\x5d\x5a\xdb\x55\xb0\x63\x87\xbe\xc0\x11\x4b\xcd\xd8\x68\x68\xa6\xdb\x9b\x9f\x27\xf3\xdd\xf1\x5d\x5f\xea\xbb\x1f\x20\xf3\x6d\x39\xa5\x2e\xcb\x9c\xaf\xbf\xf3\xe8\x15\xe1\xc7\x90\xca\x33\xfe\x91\xa3\xed\x81\xfd\xf7\xb5\xb8\x9b\x3f\xd7\x7f\x8f\x59\x51\x37\x1e\x41\xfa\x1f\x7e\x67\x1e\x46\xfa\x5b\x49\x6b\x7c\xc3\x98\x5e\x23\xff\x89\xf4\xdf\xa5\x70\x7f\xd4\x07\x8f\x74\x4c\x68\xf4\xcb\xc7\x8e\xa8\xc4\x9c\x62\x0a\x75\xc0\xa3\x88\xeb\x98\x11\x48\xe2\x98\x48\xcc\x61\x80\x31\xe5\x08\x6b\x41\xa2\x20\x0e\x94\x0e\xa0\x86\x98\xb1\x53\xc4\x39\xe4\x0f\x8c\xd3\xf9\x74\x15\x58\x0a\xc0\xdf\x5f\x05\x7e\xae\xe5\x18\x40\x42\x88\x80\x48\xdc\x1f\xa7\x73\x45\x76\x88\x2b\x66\xe1\x9b\xd9\x21\x12\x71\x32\xb9\x61\x71\xa1\xfc\x8e\x2d\x6c\x63\x95\x65\xd6\x1e\xf5\x77\xd5\xe1\xc0\x8e\xb3\x6e\x97\x0c\x57\xa5\x72\xb7\xab\x78\xf5\x30\x2d\x0f\xf2\x03\x39\x72\x3a\xc3\x78\xbb\x2d\x5a\xe3\xf6\xe0\xe8\x1a\x4b\x94\x91\x25\xc7\x5a\xc6\x56\xcd\xda\x0e\xa7\x99\x7d\xa1\xd0\xcf\x0f\x62\x5b\x79\xa5\x87\x65\x87\xb0\x13\x5f\xbd\x25\x16\x62\xfa\x56\xcf\xfe\xa3\x7c\xe2\xc3\x3e\x4e\xfe\xbd\xd9\x21\x1e\xbd\x17\xf6\x7b\xf9\x58\x0b\xfe\xc1\xbd\x38\xc3\xf8\x7b\x57\xb5\x3f\x5b\x35\xbe\xa5\xaf\xee\x5e\x35\x7e\xe0\x58\x5d\x23\xff\x89\x58\x83\xd2\x66\xbe\xef\xab\xc6\xce\x33\x77\xf1\xac\x9a\x0d\xb2\x46\xaa\x92\xab\x09\xd5\x9d\x0e\x2a\xbb\x1d\x1c\x8f\x8f\xab\x74\x41\xa1\xdc\xa4\x88\xbc\x96\x2e\xa7\x52\x62\x55\x69\x05\xc5\x92\x6f\x6e\xfd\x2c\xd8\x35\x2b\x6b\x51\xb6\x2b\xa9\x8a\xca\xda\xb3\x85\x3d\xc9\x8b\xda\xfe\xa7\x2f\x7e\x8e\x60\x4c\x25\xd6\x21\xd5\x90\xc4\x92\x03\xc4\x43\xc5\xa5\x40\x30\x0e\x08\x63\x48\x28\x08\x38\xc0\x24\x0e\x03\x19\xd0\x40\xe9\x98\x05\x32\x0a\xb8\xd4\x80\x42\xad\x39\x7e\x22\xd6\x79\xd5\xd8\x34\x6a\xc8\xb0\x7d\xbb\x90\x6b\xd8\xa8\x58\xc8\xd1\x5a\xa9\xe3\xd0\x52\xae\xd5\x65\x1e\xef\xe4\x8a\xb5\x8a\x6b\x35\x10\xaa\xf0\x7c\x87\x58\xf5\xb6\x53\xe7\x8e\x65\x55\xaf\x25\x16\xfa\xc0\x37\xfd\x55\x8b\x5f\x88\x45\x11\xba\xec\x5b\x5e\x19\xb9\x79\x0d\xb1\x6e\xb2\x15\xdf\x24\x96\xf3\x22\xdf\xcb\xf1\x7e\xb8\xeb\x2a\x98\x2a\xb4\xe3\xbe\x6e\x4d\x7d\x63\x41\x1b\x1d\xa7\x23\x83\xa9\xca\xe6\x27\xf9\x05\xd8\xb5\x80\x92\x95\x72\x2e\x76\x59\x53\xac\x97\xfd\x5c\x4b\xb7\x66\x03\xdb\x42\xba\xe9\x38\x93\xfe\x3e\x15\x66\xd6\x8e\x6c\x54\xeb\xdb\x41\xec\xa4\x27\xb1\x35\xf6\x46\xdf\x42\xac\x2b\x23\x1b\x1f\x4e\xac\x3b\xe5\x3f\x90\x58\xd7\x46\xe7\x3d\x9a\x58\x0f\x91\x7f\x07\xb1\xfe\xa6\xe8\xc9\x4f\xf7\x39\x6f\xe8\xab\x47\x12\xeb\xde\xb1\xba\x46\xfe\x13\xb1\x86\x1b\x67\x9b\x19\x1f\x3b\x64\xde\x4d\x39\xb4\x1d\xf5\xcc\xe5\xb8\xac\x5a\x31\x5c\x44\x3b\x35\xf1\x27\xcb\x46\xa6\x53\x3b\x02\x02\xfa\x22\x9c\x37\x0e\x68\x63\xf7\x5b\xb4\x3d\xc8\x79\xd5\x2e\xf5\x9a\xed\x20\x9b\xa5\x2b\x17\x74\x60\x49\x16\x52\x79\xd1\x49\x75\x45\xa5\x65\xfe\xf0\x3e\x67\x40\x03\xa9\xb1\x0a\x18\xd6\x52\x29\x48\x29\xa6\x52\x49\x8e\x31\x0f\x55\x08\x09\x61\x44\xa9\x80\xb2\x10\x61\x10\x90\x08\x28\x1e\x23\x4e\x05\x62\x84\x44\x90\x09\x70\xba\xae\x83\xdd\x9d\xcf\xe8\xb3\xdd\x4d\x09\x01\x3b\xa5\xaf\xf8\xb8\xf6\x0c\x3e\x01\x04\x7e\x40\x3a\xa3\xd7\x5b\x36\xbf\xbd\xc7\x37\x58\xf6\xef\x5d\x5e\xd5\x77\xac\x74\xe8\x07\x8d\x6e\x37\x8f\x5b\x79\xb9\xcf\x2f\x3a\xb3\x36\xd5\xba\x58\x00\x86\x76\x02\xa3\x91\xc9\x4a\xa4\x6a\xf1\x1e\xb4\x9b\x0d\x67\x31\x67\xcb\xce\x9e\xf0\xb8\x94\x69\xee\x47\x6d\x7f\x21\x42\x23\x5b\x8a\x7d\xb3\x4e\x3b\x9d\x6a\xad\x27\xd8\xca\x70\x9b\x85\x47\x65\x94\x48\xbe\x1f\x57\x66\x74\x18\x06\x2d\xae\x12\x00\xcc\xbe\x29\xf9\x33\x36\x3d\x4e\xfe\x3b\xdb\x70\x5f\x66\x53\x92\x92\xd7\x65\x11\x58\x94\xe7\x9d\xf5\x2e\x91\x42\xe7\xb7\x43\x73\xe7\xf2\xb1\xbe\xbb\x43\xbe\xdd\x6a\x6e\x7b\x77\xc8\x7f\x5d\xfb\x93\x1e\xca\x9b\xec\x29\xdf\xde\x17\xbf\xc6\x02\x26\x9a\xa1\xae\xec\x8b\x7b\xc7\xe2\x97\xfc\x63\xef\x36\xf9\x4f\xec\xf1\x6b\x5e\x1a\x21\x77\x84\xda\xf5\x08\xd6\x63\x55\x0f\xc6\xcc\xd9\x74\xa6\x83\xc3\xda\xc8\xf6\xdb\xbf\x48\x98\x8e\xa6\x76\x47\x44\xce\xd8\xde\x07\x0b\xbd\x80\x42\x57\xf0\xd1\x68\x95\xba\xce\xa4\xb0\x75\x77\x99\x63\x16\x19\xa3\x4d\x0b\x1e\x81\x5f\xad\x2c\x8d\xcc\xd8\xfc\xe1\xf5\x3d\x16\x00\xca\xa0\x90\x21\xa1\x9c\x01\xc5\x00\xd7\x18\x43\x25\x81\xa2\x81\x08\x89\x8a\x38\x02\x92\xc1\x28\x16\xa1\x12\x4a\xab\x38\x22\x41\x80\x85\x08\x29\xe7\x01\x53\xe1\x13\x7b\xee\x4c\x67\xf4\xd9\xfe\x9d\x84\x40\x90\x77\x23\x6b\x5e\x6a\x9f\xd8\x43\x24\x7a\x40\x36\xa3\xfc\xab\x41\xff\x8d\x3d\x37\xd8\xe8\xef\xb0\xc7\xd8\x9b\x54\x8d\xf9\x7a\x34\xf4\x72\x40\xc5\x4e\xb7\x31\xc8\x39\xd6\x66\x06\xea\xbb\x83\x3f\x2d\x2f\x1a\xcd\x2c\xea\xef\xad\xcc\x7a\xc2\xfb\xe9\x6d\x73\x94\x71\xb1\xea\xed\xdc\x4e\x5d\xf0\xe9\x60\xda\x1a\xf5\x27\xdb\x28\x37\x6f\xb4\x63\x9d\xd3\xee\x60\xc7\x47\x3d\x1d\x37\x8d\xbf\x80\x3d\x7d\xa7\x55\x24\xf7\xea\xfe\x07\xca\x7f\x3d\xa6\x5f\x92\xff\x18\xf6\xbc\xd6\xfd\xa3\xb7\x25\x7e\x97\xbe\x9b\xf3\x4c\x6d\xef\xdd\x21\xff\xb7\xda\x1f\xf4\x35\x1e\x9c\x4a\xef\x2e\xdd\x6f\x3c\x88\x3d\x7b\x71\x9b\xfc\xe7\x3c\xae\xde\xa6\x93\xd7\xbc\x9b\x03\x66\x39\x9b\xdd\xb7\x9b\x64\x90\xf1\xf8\xa2\x6c\xaf\x4a\x93\xfc\x31\x18\xc1\x8c\x9c\x29\x6f\x17\x76\x37\x24\xe6\x30\x6f\xd4\xd6\x38\x57\xca\x8c\xc1\xb6\x42\xc9\x1c\x76\x73\xdd\x25\xae\x17\x9a\x70\x8a\x07\xd9\xfe\x6c\x55\xa1\xb9\xec\x14\xfe\x74\xe6\x71\x28\xc2\x98\x29\xa5\x11\x50\x71\x18\x82\x58\x02\x2e\x15\x09\x05\x17\x98\x43\x21\x89\x8c\x20\x0e\x23\x88\x22\xc8\x71\xc0\x00\x66\x38\x42\xa1\xd0\x38\x00\x5c\xc7\x3a\x88\x9e\xd8\x83\xef\x4c\xa5\x07\x3e\x87\x8f\x64\x1f\x39\x3e\xe7\xda\x27\xf8\x48\x70\x59\xa0\xbb\x1d\x3e\xaf\xf7\xa8\x7f\x83\xcf\x0d\x9b\xe7\xef\xc0\xc7\x4c\xd7\x5a\xeb\x19\x3b\xac\x8d\x45\x76\x1e\xb1\xae\xd3\x1e\xee\x3a\xde\xa1\x33\x9b\x17\x2a\xb5\xa3\xf0\xea\xdb\x23\x88\x44\x6d\x56\x5d\x56\xec\x4c\xaf\x6c\x6f\x8c\xa1\x48\x8d\xc2\x43\xbf\xce\xbd\x81\xae\x2c\x76\xe1\x20\xbf\xac\x03\xa3\x29\xfc\x76\x90\xf1\x3c\x72\x54\xa9\x5d\xf1\x2f\x80\x8f\xde\x35\x55\xf3\x5e\xe5\xff\x40\xf9\x37\xe5\x91\x7d\x08\x7c\x7e\x53\xfe\x37\xa5\x6f\xbb\x43\xfe\xbd\xb9\x4b\x7f\xab\xfd\xc1\x80\xfe\xef\x80\xcf\xad\xca\xdf\x78\x10\x7c\x92\x4e\xf0\x0d\xf0\xd9\x82\x56\x18\x54\x56\x4b\xaf\xd0\x67\x1d\x3d\xa9\xb5\x66\xc2\x01\xa5\x31\x2b\xd4\x87\x23\x95\xb6\xed\xa5\x90\xd9\xd8\x0e\x2c\x76\xec\x1b\xbe\x55\x2b\xf6\x72\xe9\xea\xdc\x15\xb3\xe6\x06\xe4\xa6\xc3\xc5\xca\x25\x83\x00\xac\x0d\xa7\xea\x3a\x93\x5e\xd3\xae\x94\x70\x75\xf5\xd3\xc7\xdb\x20\x41\x4a\x0a\x11\xc2\x98\x71\x29\x48\xcc\x49\x00\xa9\x80\x91\x96\x2a\xd0\x2a\x26\x52\x6a\x06\x62\xa8\x81\xd6\x11\x91\x8c\x31\x18\x04\x48\x51\x2a\x11\x16\x9c\x11\xf5\x8b\x1c\xcf\x77\xc6\x9b\x59\x93\x58\xc8\xac\x13\x6a\xe6\x6b\xe5\x32\xf1\x8c\x6c\x03\x15\x9d\xae\x91\xcf\x35\x69\xd5\xe0\x59\x8a\x0b\xb8\x55\xa9\xb2\xb6\x9d\x67\x9d\x76\xb6\x5c\x2f\x77\x0b\x9e\xfb\x9f\xff\xfe\x1f\xa5\x02\x13\xca\x89\xa0\x9f\x52\x08\x01\x01\xc8\xbb\x14\x7a\xae\x65\x84\x20\x42\x21\xa6\xf8\x25\x84\x31\x47\x36\x16\x28\x74\x2a\x83\x86\xb3\xd4\x9e\xa1\xf5\x78\x7c\xc8\x14\x0a\x91\xb6\x68\x8a\xb7\x36\xcb\x69\x6a\x55\xab\x2e\x51\x05\x35\x4e\x53\xe1\x4c\xa1\x53\xae\xc7\x0f\x0e\x17\x9c\xdf\x23\x97\x96\x64\xbb\x82\x46\x7a\xbf\x21\xd1\x78\xd8\x88\x80\x5f\xdf\x1c\xec\xe9\xc4\x6a\xae\xf6\x85\x60\x72\xcc\xb7\x07\x5b\xe2\xb8\xa3\xd9\xf9\x24\xe9\x25\x10\xc2\xac\x14\x7b\xd2\x1c\x1f\x67\xa3\x7d\x80\x47\x46\x76\x3a\xef\xaa\x5e\x7d\x30\xed\xf4\x52\xf1\x06\x86\x0b\x9a\x5e\xda\x0d\x26\x87\xeb\xd1\xd3\x0d\x42\x8e\xd4\xc9\x77\x37\xfb\xd2\x5e\x2f\x9f\x69\xee\xe9\xba\x1d\x0f\x8d\x5d\x67\x1f\x84\xb2\x49\xb3\x95\x61\x77\x9b\xa9\x6d\xf1\x46\xd2\x61\x27\x3c\x1c\x37\x0b\xdd\x4d\x8f\x86\xab\x43\x69\xd5\x04\xc3\x4a\xba\x07\x70\x2d\x86\xc7\x9e\x56\x6b\xd8\x1f\x92\xbe\xe5\xbb\x65\x31\x69\x93\x99\x3d\x5b\x83\x55\xbd\xd1\xed\xed\x1e\x76\xbc\xcd\x4a\x24\x85\x18\x0e\x48\xd5\x9b\x2b\x96\x2f\xb5\xd7\xd4\xc8\x50\xd6\xee\xe4\xec\xd9\x1c\x92\xea\x94\xaf\xdb\x6c\x13\xb3\xbd\x9d\xda\xfa\xbc\x5b\x3e\x7d\xc9\x6c\xf4\x7d\xb3\x72\x19\x8f\x9b\xb6\x75\x1e\x28\xff\xb6\x60\xfe\x8b\xd6\xac\x24\xfa\x2f\x1c\x1d\xa1\xcf\x83\x1a\x77\x79\x1f\xb5\xcb\x65\x5c\xeb\x17\x78\xae\xae\xfd\x72\xfd\x68\xcf\x17\x61\x69\x1c\x14\xd2\xbd\x66\x50\x3f\xdf\xf5\x90\x08\x04\xb8\x72\x3e\x3f\x35\xe5\x2b\xc7\xdb\xaa\x7f\xa6\x7d\x1d\x48\xbc\xab\xb7\x7d\x2a\x97\xfa\x6b\xdf\xa5\x7c\xc5\xe9\x15\x4e\xb2\x2d\xef\x83\xf1\xfb\x98\x40\xd5\xfb\xe4\xe7\xc8\x6d\xf2\x9f\x08\x34\x72\x1a\xd9\x09\xec\xa6\x4a\x56\x26\x76\xe6\x5b\xd8\x18\x29\x56\x9e\x08\xc7\x4d\x6b\x8e\x27\xe5\x68\x5b\xac\xb0\x39\x9d\xa6\xea\x95\x63\xee\xb0\x6f\xd4\x4b\x3c\x65\x35\x22\x27\xdd\xa9\x64\xe8\x01\xb7\xdd\xea\xc0\x2e\xf7\x7c\x7c\xe8\x86\x83\x5e\x7d\x80\xeb\xfb\x7c\x79\x62\xfd\xb0\xfb\x83\x81\x10\x20\x8a\x08\x8a\x84\x26\x00\x05\x18\x44\x22\xc0\x14\xf1\x90\x32\x05\x35\xc6\x1a\x0a\x2d\xb8\x22\x4c\x43\x8c\x91\x0e\xa8\x8a\x15\xe4\x08\xc6\x91\xe0\x2a\x3e\x2d\xbd\x91\xc7\x11\x88\x7c\xba\x08\x87\x31\x43\xef\x13\xe8\xb9\x96\x01\x88\x24\x25\x0c\x11\x70\x3f\x81\x3e\x3d\x60\x7d\x25\x81\x9e\xca\xab\x8b\x5d\xe3\x67\x8d\x97\x31\x06\xba\x5b\xaf\x6f\x2a\xdd\xc5\x78\xb7\x3e\x0c\xa7\x43\x1a\xa5\xeb\xc0\x6d\xd6\xdd\x81\xb7\x3d\x80\xc1\xbc\x5a\x3c\x4c\xe7\x63\xd2\xdc\x56\xc4\x42\x71\xd3\x3a\xe2\xed\xaa\x58\xab\x8c\xcb\xa8\x47\xc1\xa2\x33\x58\x1e\xa2\x7a\x25\x0a\x66\x94\xf5\xb7\xb5\xfe\xd2\x8e\x6b\x2b\xd7\xfc\xda\x75\x92\x5f\xa3\x49\x62\xd9\xe2\x5a\x6d\xfe\x12\x24\x60\x80\xb7\xdf\xb8\x44\xbf\xbe\x51\x32\x0f\x96\x7f\x13\xcd\xce\x5f\x7a\xad\x01\xaf\xd5\xd6\x97\x8d\x67\xeb\x23\x9f\xe3\x63\x0d\x78\x8f\xfc\xc0\x50\xf5\x3b\xe4\xdf\x4d\x80\x57\xcf\x7f\x13\x01\xfe\x10\x81\x3e\xdb\x88\xba\xa5\x2f\xce\x82\x1e\x33\x17\xee\x1d\x8b\x6b\xe4\x3f\x87\xed\x7d\x93\xd2\xfa\xd1\xb0\xbd\x30\x92\x8c\xc4\x2a\x8e\x42\x8c\x59\x80\x41\x8c\xa0\x42\x04\xc4\x71\x1c\x05\x31\xc7\x11\x57\x9c\x0a\x01\x74\x04\x43\x29\x31\xa7\x8a\xa1\x58\x10\x8d\x35\x95\x88\x72\xf0\x44\xc3\x73\xd8\x5e\xb9\xeb\x56\x0b\x3e\x6d\xd7\xb3\x6d\x97\xfa\x95\x6e\xa9\xec\x52\xe4\x9a\x05\x5a\x37\xf3\xc4\x77\x9b\xed\x52\x3e\xdf\x72\xbb\xf5\x02\x72\xaa\x24\x93\x43\xf9\x5c\xbe\x8c\xcc\x2b\x69\x48\x00\x7e\xf7\x76\xa7\x97\xda\x33\x0d\x29\xc0\x17\x7f\x2c\xb3\x69\x54\x5b\xc3\xf5\x3c\xbb\x0a\x37\xd9\xae\x0f\x70\xe4\xda\xcb\x55\x3f\x4f\x7b\xb0\x58\xaa\x4f\xe6\xab\x43\x6b\xb6\x4c\x65\x6a\xf3\xc2\x69\x6a\x7d\x8d\x86\xaf\x03\xcd\xaf\x98\x85\xaf\x2f\x03\x3d\x15\xf7\x45\xbe\xe7\x5a\x46\x2b\x4d\x2b\x73\x64\x4d\x9c\x66\x55\x90\x68\x72\x68\x50\x37\xdd\xdb\x4f\x61\xfb\xd8\x8b\x4a\xcb\x51\xbd\xde\xe4\xbb\x78\xbe\xc1\xf2\xa0\x16\x98\xd5\x7b\xa9\xde\x0a\x1d\xe6\xb5\xe1\x8e\xf6\xf7\x7b\x5d\x6a\x0e\xd3\x6e\xcb\x2e\x0c\xe6\xca\x72\xa7\x91\x1e\x60\x61\x7c\xc9\xbf\xfa\x52\xd8\x5e\x92\x48\x57\x5a\x03\x66\xbb\x97\xb5\x1f\x49\xc4\x3b\xe5\xdf\x1b\xb6\xf7\x40\x22\xdd\x4b\x84\x87\xc8\xbf\x36\x6c\xef\x2f\xf5\x2f\x3f\x23\xd6\x2d\xd6\xcb\x23\x89\xf5\x93\xd6\xd3\x73\xe8\x44\x29\xd3\x49\x8f\xd8\xd4\xaf\xf8\x2d\x2f\x7d\xec\xa3\x30\x5f\x1d\x85\x29\xcb\x8d\x5b\x61\x25\x03\x0e\x9b\x5a\x3e\xdf\xd8\x66\x52\x13\x1e\xe3\xfc\x61\x19\xcf\x0b\x16\x33\x8f\x61\x61\xec\x56\xad\x49\x36\xeb\x90\x7d\xbd\x2a\xba\x4d\x6f\x51\x18\xef\x4a\x41\x04\x59\x31\xde\xfd\xb4\xff\xa6\x22\x11\x08\x2d\x75\x48\x71\x1c\x21\x26\x22\x88\x24\xd1\x08\x09\x29\xa9\x42\x3c\x26\x08\x45\x12\x70\x81\x15\x01\x94\x68\x42\x82\x10\x00\x24\x62\x05\xa3\x00\x41\x70\x3a\x1a\x85\xef\x0e\xdb\x63\x9f\x71\x8a\x48\x88\xd9\xbb\x9c\xfa\x55\xcb\x2f\xe0\x13\x92\x3c\x60\xf7\xca\x7d\x35\xe8\xbf\xbd\xc7\x37\x78\x0e\xef\x85\x4e\x34\xd7\x91\xdf\x3e\x2c\x19\x39\x6c\xd3\xcb\x42\x75\x09\xd2\xdb\x16\xd9\xfa\x87\xd9\x34\x5e\xb5\xf7\xf3\x7d\x76\x35\xf0\x8b\xd9\x42\x1e\x87\x13\x36\x4a\x1d\xe6\x03\x23\x73\x50\x62\x0d\x0a\x29\x1e\x1e\xf7\xf5\x62\x75\x38\x19\x16\x0a\x65\x5a\x5d\xee\xb8\x11\xe9\xe9\xd8\xe4\xa5\x87\x5d\x04\x95\x7c\x3f\xae\xdc\x3d\x9a\xd9\x9d\x60\x9c\x88\xad\x75\xde\x94\xfc\x19\x9b\x1e\x27\xff\xf5\x98\x7e\x49\x7e\x82\x4d\x77\x84\x8a\xf5\x6a\xd1\xa2\x95\x10\xe4\xbf\x2d\xf1\x63\x7d\x77\x87\xfc\xb6\x0c\x56\xce\x1d\xf2\x0d\xe3\xcf\x79\x28\x6f\xb2\xa7\xf8\xff\xa9\xfb\xd2\x26\x47\x71\xe4\xef\xf7\xf3\x29\x1c\xff\x37\xdd\x1d\xee\x59\x0b\x01\x02\x66\x62\x37\x02\x6c\x7c\xdf\xe0\x03\x3f\x2f\x2a\x38\x84\x8d\x0f\xc0\x80\xcf\xfd\xf2\x4f\xf8\x28\x17\xc6\xc6\x76\x61\x57\xf7\x2c\x11\x13\xd3\x2e\x44\x66\x2a\x25\xe5\x4f\x99\x4a\x49\xc9\x75\xb1\x6b\x0b\x25\x74\xb2\x50\xcc\xf5\xcd\x5f\xd6\x16\x3b\xfe\x3d\x27\x19\xff\x23\xf6\xe4\xab\xfd\x5e\xde\x9f\xa7\x17\x35\x2f\x83\x36\x63\xc4\x35\x19\x02\x57\x61\x6d\x5e\x26\x99\xbc\xaf\xea\x6d\xa6\x34\xcb\xae\x37\x96\x01\xe9\x85\xdb\xf4\xe7\xca\x90\xd7\xed\x66\xd5\xc8\x2e\x17\x90\x65\x3b\xd6\x96\xa2\x9d\x8d\x35\xc6\x32\x62\x1b\xab\x62\xdf\xa5\x5b\x8b\xed\xaf\x3e\x1a\x4b\x33\x35\x83\xc6\x1c\x45\x33\x06\x43\x30\x9a\x6e\xb2\x14\x03\x39\x42\x45\x3a\xa4\x34\x46\x37\x58\x43\xa3\x4c\x93\x61\x29\xac\x1b\x14\xcd\x41\x0d\x93\xc0\x00\x2c\x41\x21\x1d\xe8\x10\x51\x47\xec\x79\x32\x6d\xef\xde\xd6\x26\x8e\xe2\x48\x2a\xf6\x12\xc2\xd3\xdb\x03\xf6\xb0\x24\xf8\x88\x18\x26\xc7\x9e\x68\x7a\xf3\x05\xf6\x7c\x76\x8e\x7e\xe3\x12\x42\x85\x90\xad\xda\x38\x3d\x1f\xb3\xe9\xad\xa2\xc1\xae\x86\xc0\x28\x3d\xef\xad\x07\x41\xde\x94\x0a\x2b\x0d\x4c\x96\x95\x20\x90\xf2\x7c\xb1\x35\x2a\x34\xc6\x25\xc3\xb0\xba\x2d\xc7\x5d\x73\xd5\x5c\xbb\x81\x3a\xc3\xe6\xac\x5a\x5d\xe7\x97\x2d\xb7\xb4\xc5\x05\x5b\x1d\x8e\xc8\x65\x2b\xf7\x0f\xc0\x9e\xe9\xb2\xe7\x09\xcf\xda\xfe\x17\xf2\x4f\x94\xb2\xfe\x1a\xec\x89\xda\xfe\x44\xab\xf5\xbf\x31\x4d\x9a\xe7\x7f\x9f\xaf\xf1\xea\x94\xf1\x67\x6c\x3f\xff\x22\xec\x09\xcf\x43\x12\x60\x0f\xac\x77\xa8\x71\x29\x33\x77\x32\x4d\x1f\x16\xb8\x69\x2f\x1d\x94\xcc\xf9\xd4\xef\x69\xed\x3e\x18\xf9\x05\xae\x5c\xdd\x78\x5a\x67\xd4\x12\x40\xa9\x3d\x76\x36\xc5\xbe\x32\xed\x54\x2a\xba\x29\xad\x80\xbc\x98\x96\x72\xb4\xb5\x61\xdb\x1a\xa8\x48\x35\x72\xe4\x42\xa7\x64\x30\xe0\x57\x6f\xb0\x05\x98\x80\x2c\xa2\x18\x0d\x6a\x1c\xc9\xb0\x48\x43\x1a\x83\x30\xc1\x42\x43\x37\x54\x40\x30\x24\x43\x33\x00\x21\x93\xd5\x55\x13\xd0\x90\x34\x08\x4d\x25\x35\x8a\x31\x0d\x64\x32\x10\x18\xef\xd7\xd7\xee\x8f\x84\xc8\x76\x65\xa1\x20\x89\x62\x87\xa9\x54\xfb\x9d\x5a\xb1\x26\xf5\x05\xbe\xda\x2f\x43\x99\x2a\xc1\x4a\xa3\xd9\xef\x41\x89\x96\xdb\xd5\x4a\xae\x5d\xe2\xfb\x39\xba\x93\x2b\xf2\x4a\xe3\xdb\xcf\x14\xc5\x40\x8a\x42\x14\x80\xf4\x5d\x14\x42\x80\x44\x5c\x2c\x0a\xbd\xbf\xa5\x09\x9a\xe4\x10\x41\x20\xea\x94\x3c\x5e\xeb\x0e\x46\xf5\xd2\xa8\x62\x76\x16\x5c\xa1\x38\xa8\x50\xad\xea\xc2\xee\xa4\x4b\xc0\xdd\x32\x90\xa8\xfa\x94\xd7\x69\x54\xf8\x7e\x11\x0e\xb7\xfc\x09\x85\xf6\x77\x54\xdf\x88\xd4\x1d\x9e\x61\xa6\x92\x11\xa6\x1e\x97\x6f\x64\xec\xae\x58\xa8\x1a\xb3\xec\x36\x3b\xaa\x29\xee\x4c\x6f\x6d\xd7\xa5\x51\x7e\x86\xea\xc2\x76\xbd\xb5\xfb\x87\xc8\x54\xe4\x16\x0e\x21\xbf\xe6\x9c\xda\x61\xe3\xd2\x4a\xe1\x8a\x2d\xbe\x0d\xa5\x5a\x13\x93\xe5\xe6\x72\x26\x08\x81\x30\x81\x63\xd3\x19\x82\x42\x5e\xcc\x2b\x93\x6a\x3d\xbf\x6d\xd5\xe7\x4b\x65\xca\x58\x03\x2b\x98\x35\xe8\x7c\x6b\x36\xa9\x4c\x97\x99\x7a\x83\x1e\xe8\x6a\x4f\x98\xf7\xf5\xe2\xa8\xd1\x72\x27\xc0\x87\x7d\x49\x68\xbd\xec\x1e\xf6\xf0\xc9\x4f\xeb\xee\x4c\x04\x96\xe8\x72\x12\x03\x14\x63\xe2\x8d\xf8\x05\x32\x64\x6a\x2c\xd9\xcd\xa5\xd6\x59\x6c\xad\xa0\x45\x39\x82\x6e\xaa\xb9\xc3\x01\x3a\x1f\xeb\x45\x31\xf7\x7e\xef\x9f\x3b\x28\xf4\x3a\xfe\xcf\x46\xe7\x42\xb3\xe6\x5c\xbe\xa7\xc8\x52\x49\xb2\x89\xea\xb2\x3d\x82\xd2\x42\xcc\x32\x2e\xd1\xb4\xea\x15\x3d\xcd\x05\x12\xd3\xa8\x10\x39\x6b\x78\x6a\xe3\x50\xc4\x25\x7b\x35\x7b\xe1\xf8\xdc\xb6\x7c\x4f\xf0\x2f\xc1\xa6\x8d\x9e\xe0\xcf\x47\xf8\x67\x73\xac\xc7\x16\x7a\x4b\xd0\x61\xd2\x46\xa7\xa5\x04\x50\xa9\xd6\x2a\xe2\xda\x9a\x0d\xd6\xb9\xa6\x68\x89\x3d\xcd\x01\xc5\x66\xb1\x61\x98\x07\x9a\xa7\x9b\x74\xae\x9f\x24\x76\x8b\xff\x3d\x0f\x28\x49\x5b\x1c\x18\x65\x63\x6e\x04\xbe\xad\x8b\x67\xdb\x22\xda\x17\x3e\xaf\x8b\xff\xea\x85\x66\x1b\xf0\xa2\x31\x19\xe7\xc8\x60\x23\x33\xf4\xb0\xa5\xb5\x06\x75\x87\x44\xa5\xba\x30\x6a\x0b\xbd\x72\x76\xdb\xd6\x41\x4e\xf5\x60\x19\x53\x33\xc5\x1b\x8c\x17\xed\x4e\xd9\xcd\xba\x5a\x66\x2b\x2f\x7a\xfd\xc2\x74\xa8\x4e\x49\x81\x92\x27\x95\x41\xbd\x5a\x9f\x82\x61\xe7\x57\xdf\xc3\x8e\x18\x04\x08\x15\xea\x2a\x24\xa0\xc6\x52\x80\x83\x2a\x63\x90\x3a\x0d\x09\x82\x81\x1a\x62\x4c\x4a\xe3\x48\x83\x81\x1a\x03\x91\x0a\x90\x4e\x53\x80\x23\x18\x03\xaa\x1a\x4b\xea\x84\xba\xf3\x3b\x08\xe2\xe9\xe8\x1b\x7d\x0f\x7b\x18\x22\xfe\x34\xa2\xf7\x97\x47\x28\xa3\x48\xfa\x05\x5b\x66\xa3\x71\xa2\x0b\xab\x95\xc0\x0a\xc6\x6d\x99\x2d\x56\x27\x0e\xca\xc8\xda\x12\x2c\x33\x74\xb6\x57\x9c\x58\xeb\xbe\xad\x6d\x9c\x0e\x9a\xb7\xd0\x06\xaf\x06\x85\x79\xb3\x98\x97\xb6\xf5\x75\xcd\x5c\x18\x2c\xc2\x4a\x61\x52\x07\x63\x6a\xe6\xd7\xb2\x7d\xb3\xca\x3b\x0b\xc6\xaa\x34\xba\x36\xa8\xf5\x36\xdb\xa9\xbb\x54\xda\x3c\x78\x59\xec\x2d\x3c\x3a\x3e\xe9\x7f\xcc\x07\x4a\xa5\x12\xb2\x34\x31\xe6\xee\xb6\xe5\x7f\x21\xff\x44\xb1\xbf\x10\xf2\x3c\x11\xef\x71\xa7\x43\xc7\x79\x36\xde\xf3\x1b\xe3\x4d\x3c\xff\xfb\xac\xfd\x55\xe4\xa9\x24\xd7\xc5\xae\x2d\xdc\xd5\xdd\x4a\x7f\x59\x5b\x44\xfb\xc2\x67\xf8\x1f\x91\xa7\xbd\xa1\x2b\x8d\x25\x80\x0c\x57\xcd\xa4\x5b\xd3\x11\x5d\xf2\xbb\x34\x64\xe7\xf9\xc6\x7c\xd2\xf0\x6d\xbf\xd0\x9e\x8f\xd7\xeb\x8e\xbf\xd5\xe5\x22\x63\x9b\x0d\x7b\x26\xb8\x39\xa3\x94\x2e\x7b\x39\x7e\x4a\x6e\x56\x95\xea\x82\xb2\xc6\xd3\x01\x97\xcb\xfb\x3e\xad\x6a\x50\x6c\xd5\x7f\xf9\x25\xec\x86\x86\x38\xa4\x32\x1c\xa3\x31\x88\x23\x18\xa4\x6b\x2a\x36\x48\x95\x06\x98\x52\x91\xca\x22\x86\x20\x08\x0e\x41\xc2\x44\xb4\x4a\x9a\x1c\x4d\xa9\xa4\xa6\x9b\x04\x00\x3a\x83\x4d\xa0\xbf\xef\x39\xda\x67\x2a\x14\x68\x28\xf7\x50\x8b\x17\x90\x5c\xa8\xd7\x1a\x72\x95\x84\x0a\x55\x23\x3b\xad\x56\xb5\x5e\xaf\x17\x9b\x62\x51\xe1\x4b\x4a\xbb\x89\xa4\x7c\x1e\x0d\xf8\x6e\x3b\x4f\x0f\x5a\xca\xb7\x9f\x29\x92\x45\x34\xc5\x00\x1a\x21\xfa\x67\x0a\xee\x30\x08\xc6\xc1\x0c\x0b\x58\x3a\xde\xff\x79\x7f\x4b\x41\x8e\xe2\x10\xb3\x23\x79\xb2\xc0\xa4\x21\x07\x88\xe7\xd3\xb3\x81\x57\x94\xfb\xcb\x5e\xa3\x46\x4a\x62\x3e\x50\x01\xb3\x29\xae\x84\x42\x69\xc9\x95\x5c\x73\x20\xf4\xca\xfb\x83\x21\x0f\xf7\x43\xee\xc1\x22\x8a\x3a\x17\x17\x8c\x7f\xc2\x22\x86\xc8\x44\xf2\xf6\x5a\x9f\xed\xc5\xa1\xbe\x6f\xf6\x47\x21\x4a\x02\x6c\x75\xad\xfd\x41\x9c\x22\xbf\xde\x4c\xe9\xe1\x32\x9b\xcd\x65\x99\x29\x70\xe7\x9c\x96\x11\x02\x83\xd4\x1b\x9d\x8e\xae\x70\xed\x25\xe0\xab\xeb\xee\x78\x31\xa5\xc4\xae\x54\x25\xba\x9b\xa1\x47\x00\xa6\x30\xce\x39\x04\x91\x56\xfc\x95\x31\x9b\x66\x17\x3d\x93\xa9\x94\x82\x0e\xd0\x47\x53\x67\xe8\xda\x3e\x75\xbe\x1f\xaa\x16\x4a\x19\xf8\xf8\xe7\x2d\x9f\x31\x1e\xe5\x42\xa4\x72\x06\xd1\x20\x1d\x3e\x87\x06\x33\xdf\xa8\x63\x4e\xa1\xb6\x46\xa9\xd5\x23\x3c\x79\x59\x32\x79\x51\xb1\x32\xc0\x9a\x72\x93\xbc\x32\xdd\x27\xdf\x7e\x5c\x39\x18\xb7\x19\x34\xd4\x5e\x57\x1e\xe1\xc5\xfc\x3f\xeb\x5f\x65\xf9\xf3\x7c\xc0\xd0\xfe\xae\x4f\x5b\xb6\xc1\xd4\x1f\x3d\x6b\x59\x9f\xb1\xec\xe6\xb8\x32\x7d\x82\x7f\x14\x59\xf8\x3a\xd9\x61\xf0\x90\x6f\xba\x33\x75\x0d\x08\x86\x18\x8f\xeb\x60\x24\x68\xbd\xa0\xc1\x8e\x58\xbe\x6d\x55\x33\x52\xa5\x7f\xea\xf3\xa1\xc3\x56\xb3\xc9\xb3\x3f\x9e\xe1\x7f\xca\x08\x4f\xc6\x7f\xff\xe2\x62\x3c\x7c\x76\xd6\xd5\xa7\x36\xae\x1e\xa9\x54\x4c\x5d\xaf\x3d\x17\xe3\x21\xc9\xac\xef\x09\xfe\x4f\xdb\x83\x8f\xdd\x1e\x89\xc6\xe3\xd3\xf6\x40\xca\xf2\xa3\x84\xfc\xaf\xcd\xb4\xc2\xfb\x3d\x13\x8c\x87\xe3\xac\x2f\x79\x86\xcd\x0b\xc7\xe3\x67\xf8\xbf\x6f\x10\xd7\x5d\xac\x54\x57\xc3\xe1\x6a\x41\x1b\x15\x75\xd9\xcb\xac\xb4\xbe\x41\xe6\xa6\xf9\x62\xa1\xd9\xd1\x38\x3e\xcb\x76\x15\xc6\xc5\x42\xbe\x63\x71\x5d\xdd\xa9\x70\x46\x63\xed\xac\x50\xdd\x30\x67\xd5\x5a\x71\xe0\xb6\xbc\xa9\x9d\xde\x58\xd5\x6e\xbd\x58\x1a\xa8\xa5\xca\x80\x69\x3c\xbb\x47\x0f\x7e\xd6\xc7\x47\x3a\x64\x75\xa0\xeb\x06\xad\x42\x4c\x31\x00\x22\x55\xd5\x55\x53\x85\x58\xdf\xf9\xfa\x80\x30\x31\x6d\x60\x92\xe2\xb0\x49\x32\x48\x07\x26\xab\x9a\x1a\xcb\x91\x3a\xa3\x69\x34\x6d\x1c\x4f\x16\x79\xce\xc5\xa7\xee\xb9\xf8\x2c\xc7\xc5\xdf\x3b\x77\x7a\x7b\x9c\xaf\x71\x0c\x7a\xc1\x22\x67\x74\x0c\x5c\x0c\x95\x04\x50\x1c\x97\x60\xd3\xce\xa1\x5a\xb7\x37\x14\x79\x69\xe1\x9b\x23\x0f\x95\x8d\x3c\x57\x21\xdb\x16\x86\xfd\x6c\xbb\x5c\x99\x66\xea\x4e\x65\x53\xd6\x3d\x83\x98\x14\x7c\x72\x33\x74\x5d\x9a\x5e\x2f\x58\xa0\x4c\xf3\xab\x61\xbd\x2b\x7a\x83\x8c\x2e\xf2\x45\xa5\x31\x07\x28\xbb\xaa\x9b\xb6\x08\xfd\xec\xcb\x9c\xfc\xe4\x8b\x8c\xbe\xa7\x56\xfc\x90\xb9\x8d\x89\x2c\xde\x31\x77\xaf\xe3\x9f\x08\x6e\x42\x4e\xfe\x13\xd3\x9f\x4d\xe0\xcc\xd7\xcf\x4e\x7f\x7e\xe3\xf4\x8b\xe7\x7f\x9f\xb9\xbf\xea\xe4\x97\x92\xeb\x62\xd7\x16\xdb\x50\x94\xa3\xf6\x49\x5d\x3c\xdb\x16\xd1\xbe\xf0\x19\xfe\x47\xe8\x11\x5b\xe9\x71\xbe\xeb\x08\xbc\xe8\x79\x45\x4a\x4d\x5b\xfd\xb6\x29\x05\x40\xb1\x83\xe9\x6a\x22\x49\xae\xb9\x55\xb3\xbe\xd5\xaf\x90\xc6\x40\xf0\xea\xac\x53\x51\x31\xd6\xb5\x65\xbd\x50\x6e\xeb\xa5\x5c\xb7\x5d\x81\x26\x29\xf0\x02\xcc\xcd\x83\xc6\xd0\xcf\xf5\xe9\x75\xdd\xfb\xd5\xe7\xde\x1b\x06\x43\x61\x8c\x21\xa3\xd2\x1c\x4b\x91\x1a\x64\x55\x40\xab\x06\x60\x55\xcd\x44\x34\x56\x55\x48\x12\x1a\x63\x60\x0d\x53\x06\xa0\x69\x1a\xe8\x40\x65\x54\x0a\xee\x8f\x6a\xe4\x20\x77\x3c\x50\x71\xef\xe3\x53\xa8\xdb\xae\x08\xd9\x6a\x09\xf6\x51\xae\x5f\xed\x33\x7c\x49\xec\xb6\xf3\xd5\x22\xd9\xe1\x99\xbe\x20\x92\xf5\x42\xbd\x89\x1a\x0c\x55\x6c\xd1\xd5\x7e\xb1\x56\x90\xbb\xb0\x2c\xec\x30\x03\x00\x44\x31\x0c\x01\x18\xf2\x1e\x08\x71\x1c\x73\x63\x6f\xde\xee\x2d\xbd\x23\x48\x91\x34\xc7\x50\x90\x42\xa7\x2c\xcf\x9c\x3d\x5f\x77\x44\x09\xa8\x4b\xca\x20\xc8\xb4\x20\x54\xd6\x15\x3f\x8d\xf8\x8c\x5e\xae\x07\x35\x22\x63\x9b\x14\x2e\x76\xc9\xc6\x0a\x20\xfe\x04\x42\x7b\xb3\x15\x02\x9d\x8f\xfe\x8e\xa3\xeb\x43\x4f\xf8\xe8\x7c\xd9\xea\x85\xa6\x93\x82\xb1\xf5\xeb\x8d\xbd\x8f\x2e\x8c\x27\xb4\x98\x9f\x77\xd9\x82\x55\xe5\xd6\x1d\x04\x1b\x9d\x6c\x05\x4b\x7a\x7f\x5d\xa8\xc9\xb5\x79\xd9\xc9\x31\xde\xc6\x2a\x98\xf4\xb8\xda\x1c\x94\xdb\x92\x3b\xd2\x7a\x59\x72\xb0\xd1\x8b\x62\xda\xcd\x2d\x16\x19\x24\x56\xa4\xb9\x5e\xef\x78\x16\xcd\xf7\xb7\xad\x59\x2d\x5d\x50\x1e\x89\x3c\x3f\xe6\x93\x87\x0a\x35\xb0\x97\x6f\xb5\xab\xed\x79\x66\x44\xf6\x4d\x4a\x14\x3d\x71\xbe\x65\x9c\x1c\xb7\x9a\x40\xb0\xed\xa7\x8d\xcc\x88\x32\xfa\x3a\x93\x93\x4f\x07\x54\x5a\xfa\x87\x8e\x63\x9e\x3b\xa0\xf4\x3a\xfe\xcf\xee\xd1\x0b\x65\xee\x7c\xda\x10\x79\xad\x7c\xf5\x59\x43\xf8\x8c\x21\xf6\x60\x63\xfa\x04\xff\x28\x10\xf0\x34\xf2\xbb\x82\x18\x14\xbc\x74\xd1\x30\x32\xc3\x96\xe4\x4b\x5e\x73\x31\x6c\x92\x59\x59\x93\xeb\x26\x4d\xa6\x8b\x23\xe2\xd4\xc7\xf7\xa0\x54\xde\x8f\x06\x21\xf9\x9a\xef\x33\xfc\x65\x1d\x2c\x13\xf2\xbf\x0a\x8a\xc5\xe7\x74\x71\x60\x24\x24\x5f\x73\x7d\xb2\x2d\x0e\x6b\xae\x9f\xe7\xff\xbe\xe3\x81\x6e\xb4\x05\x75\x6a\x0a\x8e\x95\xd1\xbb\x8d\x60\x3c\xe5\x2d\x7b\x62\xe7\xd9\xf6\x58\xdc\x56\x2c\x95\x4f\x23\xd6\x19\xd9\x69\x65\xb3\x85\x52\xa7\x33\x57\x7a\xc4\x30\x80\xba\x2d\xac\x9b\xf3\x16\xe3\x2d\xd3\xa3\xec\x64\x6e\xe7\xba\x15\x6a\xd1\xca\xb3\xa0\x3c\x6e\x8e\x66\xa7\xc8\xb7\xb5\x73\x75\xbe\x11\xfb\x8b\xd5\xbe\x0e\x13\x21\x4d\x13\x98\x41\x2a\xa9\x63\x8a\x65\x09\x8d\xd1\x74\x86\x34\x0d\xd3\x60\x39\x03\x31\xc0\xa0\x89\xfd\xd5\x30\x14\xa6\x11\x41\x23\x48\x43\x8d\x26\x18\x86\x01\x90\x84\x00\x1a\x98\x39\x60\x22\x7c\x15\x26\xde\x76\xcc\xa8\x7f\x81\xdd\x13\xb3\x43\xef\xf8\x96\xfa\xc0\x44\x44\x7f\x38\x66\xc9\x31\x31\x1a\xe7\xce\xab\x85\xae\xaf\x15\x4e\xc7\xfd\x5c\xec\x5f\x4f\x16\x07\xcf\x2a\xd3\xf0\x11\x4a\x27\xfb\x2d\xf0\x12\x4c\xd7\xd4\x26\xcf\x70\xfc\x38\x07\x04\x66\x3e\x9e\x82\xb9\xb8\x05\x75\x94\x9d\xe4\x66\x8e\x44\x4d\x86\x76\x7f\x3c\x30\xb5\xa5\xa1\x73\xa5\xc9\xbc\x3e\x03\x52\x7a\x59\x11\xea\xc3\x2e\x0b\x5c\xc9\xb4\xd6\x0a\x41\x31\xd5\xf4\x78\x29\x65\x86\xaa\xed\x2c\xe7\x5a\xd5\xda\x75\xb3\x7f\x02\x36\x76\xc8\x7a\x95\xfd\xd0\x75\xb2\xf8\xd4\xeb\xf8\x27\x3a\x0d\x25\x84\x8d\xbf\x11\x9b\x9e\xc6\x46\x5f\xef\x67\x7e\x27\x36\x46\xb0\x29\xd1\xd5\xae\xcf\xf0\x97\xa0\xd7\x4d\xc8\xff\x9e\xc3\xf8\x2b\xb1\xe9\x25\xba\x38\xc5\x2a\x13\x63\xe3\x57\x19\xad\x3d\x36\x06\x78\x1d\xec\xfe\x3f\xc2\xd3\xa9\xf3\xa5\xf8\x48\x6a\x24\xc2\xba\xa9\xe9\x3a\x54\x0d\x0d\xe8\xa6\x69\x02\x56\xc5\x2c\x22\x38\xce\x44\x14\x26\x20\xc7\x52\x26\x60\x29\x4d\x03\xa4\x86\x39\x4d\x83\x14\x87\x08\xc2\x30\x59\x48\x42\xa8\x1d\xf0\x91\x7c\x15\x3e\xde\xce\x4d\xda\x23\x20\x24\x62\x76\x06\x86\xde\x1e\xf0\x91\x06\xe8\x63\x5d\x38\x39\x3e\x86\x82\x6c\x35\x81\x6f\x89\x0f\xfe\xc7\xff\x02\x9f\x32\x97\xe5\x46\xb5\xa0\xa6\x0c\xd0\x48\x5b\x13\x16\x6f\xf4\xed\x61\x5b\xcf\x2a\xad\x99\xc9\xe2\x05\xb5\xd5\x05\x4e\xaa\x16\x21\xc7\xb1\x41\x57\xd1\x55\xd4\x52\xac\x21\x9d\xf3\x87\x1b\xe8\x64\x6b\x39\xa2\xcc\x4c\x46\xa5\x2a\x37\xde\x66\xba\xbd\xb1\xde\x1c\x2d\xe5\xee\x32\xcb\x3e\x72\x0e\xe6\xd7\xe3\x66\x30\x27\x42\x3e\x5d\x22\xdc\x7a\x21\xff\x44\x81\xd6\x17\xe1\xe6\x93\xb8\xf5\x34\x6e\x06\xd9\xd1\xe0\x77\xe2\x66\x04\xb7\x9e\xad\xff\xe7\xf9\xb7\x46\x4c\x42\xfe\x5f\x81\x9b\x49\x71\xeb\x25\xba\x38\x5d\x30\x9a\x18\x37\x57\x4b\x45\xae\xca\x85\x02\x76\x7a\xac\xa1\x0c\x8b\x5d\x9a\x12\xfb\xfc\x4c\x2c\xdb\x99\xa2\xb7\xa8\x91\xbc\xd9\xb1\xd6\xdc\xd2\x34\xab\xdd\x5e\xb1\xb0\x98\x14\x4a\x4e\xa3\xc5\x94\x6a\xc1\x9c\x1f\xf3\x9c\x84\xe9\x92\x94\xcd\x28\x6c\x86\xe8\x3a\x64\x8e\xd2\x00\xa1\xad\x96\xa7\x35\xbe\x91\xea\x8f\xf6\x1a\x7f\xd8\x4a\x8b\xff\xfe\x52\x78\xc5\x04\xc5\xb2\xb4\xae\x21\xa4\x9a\xb4\xc9\x98\x34\xe6\x38\x42\x03\x04\x85\xb1\x4e\x31\xb4\x8e\x08\x5d\x67\x49\x02\x72\x50\x37\x69\x1a\x22\xdd\x30\x80\x6e\xa8\x04\x45\x93\x00\xb0\xe4\xd1\xfd\xa4\x5e\x05\xaf\xb7\x37\xde\xef\x01\x94\x22\x62\x36\x3f\x86\xde\x1e\xe1\x95\x62\x3e\x92\x7f\x93\xc3\x6b\x18\x23\xb3\xfc\xb0\xf4\xe0\x7f\xd1\x4f\xf9\xaf\x08\xd9\x36\xcc\x39\xd7\x6c\xb1\x62\x41\x77\xc7\xed\x9e\xa8\xce\x0b\xeb\xe5\x48\x18\x4b\xdd\xc5\x04\x55\x68\x1e\x7a\xc1\xa8\xaa\x14\xed\x19\xdf\x9f\xb5\x88\xf2\xb8\x9c\x23\x45\xc3\x18\x5b\xa2\x44\x6a\xcd\x41\x27\x4f\x63\xb3\xd0\x5a\xb6\xc7\x8e\x58\x19\x5a\x02\x34\x3a\xa4\x09\x57\x8f\x6c\x53\xf9\x7a\x78\x9d\x94\x70\xc8\x2d\x4c\xb6\x8e\xf8\x3a\xfe\x89\xd6\x11\x5f\x04\xaf\x4f\xc2\xdb\xf3\xf0\xfa\xdc\xda\xd9\xf3\xf0\x7a\x0e\x6f\x89\xd6\x51\x9f\xe1\xdf\x9e\x2b\xa3\x84\xfc\xbf\x02\x5e\x93\xc2\xdb\x4b\x74\x11\x09\x9f\x7f\x86\xff\x11\x5e\x65\x1b\x2d\x65\xd0\x14\x04\xbb\xa2\x80\xee\xa8\x30\x1f\xf9\x1a\xd5\x52\xc0\x54\x73\x1b\xd6\xa2\x55\x9f\x33\x8a\x04\x05\x9a\x1e\xe6\xe9\x49\x5d\x52\x36\x2d\x6e\x5d\xec\x2b\xd4\x48\x0c\xe0\x16\x76\x05\xdc\xb7\xd7\x93\x2a\x50\x90\x90\x75\x4a\x43\xc3\xee\xd6\x49\xce\x3f\x6d\x93\xf1\x70\xb0\xf0\xec\xbd\xce\x1f\xb6\xd3\xa5\xaf\x05\x58\x60\x6a\x9c\x0e\x31\x04\x1c\x85\x20\x84\x1a\x24\x31\x61\x10\x06\x42\xc0\xc0\x9c\xc1\x50\x34\x83\x74\x8a\xd0\x4d\x83\xd3\x76\x1e\x2d\x67\xd0\x88\x56\x01\x41\xea\x04\x36\x59\x4e\x57\x8f\x27\x02\x3c\x97\x6e\x73\x7b\xa5\x93\xfa\x17\x20\x08\xc4\xc6\x5c\x97\x1a\x7a\x7b\xc4\x69\x9a\x40\x2f\xb8\x0a\x28\x6a\xd2\x2f\x22\x8f\x09\x56\xd9\xe2\xce\x14\x60\x83\x52\x7e\xe3\x0c\xb9\x06\xce\xce\x2d\x55\xa8\x9b\xeb\xbc\xc1\x4f\x6d\x5c\x57\x64\x73\xec\xd4\x3b\xb5\x8a\x85\xf2\xe5\xac\x42\x0b\x73\x3c\xb3\x73\xc2\xba\xe0\xac\xc9\x71\x45\xca\xac\xd7\xd4\xd6\x5d\xf3\xb2\x23\xe6\x5d\x52\x81\xb5\x74\xbd\x5d\x2e\x75\xa8\x61\xa6\x08\xca\xaf\x4a\xb7\x11\x92\xef\x69\x59\x64\xc0\x0a\x12\x1f\x9f\x27\x8b\x9e\xbe\x8e\x7f\x22\x98\x0e\xa5\xdb\x3c\xb1\xb2\xc9\x64\xe4\x9c\xf6\x2c\x4c\xfe\xc6\x95\x55\x9e\xff\x7d\xab\x79\x57\x61\x4a\x4c\xae\x8b\x5d\x5b\xe8\xd4\xc7\xf7\x89\x22\xc9\x2f\xec\x0b\x9f\x8f\x24\xff\x37\x53\x95\x04\x7d\x5e\x6a\xca\xf6\x70\xee\xcc\x86\x72\x9f\x6d\xf7\x5b\xe5\x01\x39\xee\x89\x24\x85\x72\xdd\x5c\xd6\x59\x8c\xa4\xd6\xac\xd1\x52\x6d\xd7\x5d\xad\xf4\xf6\xbc\x66\x50\x9b\xc9\x92\xd5\x71\x0d\xe9\x2d\x11\x09\x82\x6a\xc0\xfa\xb8\x39\xee\x48\x52\xbe\x51\x6a\xae\xb9\x5f\x7e\x05\x2a\x07\x58\x1a\x13\xa4\xa9\x61\xce\x64\x29\x0c\x18\x4c\x42\xa0\x02\x83\xa2\x68\x9a\x44\x06\x26\x54\x53\x87\xba\x69\xb0\x3a\x83\x29\x82\x45\x88\x65\x58\xc0\x60\xc3\x80\x1a\xc5\xee\x13\x2c\xdf\x6f\x40\xcd\xf5\xf3\x7c\xa1\x9c\x95\xb2\x25\x2a\x5b\x81\x4a\xb1\x82\x94\x76\x95\x47\x72\x45\xec\xe7\xdb\x7d\x46\xa8\x15\xba\xb5\x56\x43\xa8\x55\x4b\x62\xa7\xdc\x2e\xd3\x4a\xab\x5e\xad\x95\x84\xfd\xb5\xdf\x04\xc3\xb1\x88\x23\xd8\xdb\x77\xa1\x52\xff\x02\x90\xe0\x50\x3c\x08\xbd\xbf\x85\x34\x83\x38\x16\x30\x2c\x73\xf2\xed\x1a\x74\xab\x20\x55\x5a\x13\x5d\xf4\x7a\xb9\x39\x67\x55\x56\x78\xe6\x4c\x37\xeb\x25\x5b\xcd\x75\x07\xc2\xaa\x57\x6d\x49\x96\xe2\x32\x56\xae\xcb\x9f\x40\xe8\x6a\x4e\x7c\x08\x84\x3a\xd7\x3a\x4a\x74\xa9\x31\xc6\xe0\x46\x1e\xcb\x5e\x94\xea\x9d\xfd\xe7\x54\xb3\xcd\x63\x80\xed\x0c\xa0\x07\x45\x38\xc5\x59\x2c\x37\xfc\xb5\x26\x03\xbd\xb3\x20\x57\xc3\x8e\xd5\xeb\xe8\x8b\xdc\x84\xda\xa8\x6c\x21\x33\x2c\x71\x60\x34\xed\x22\x77\xdb\x50\x36\xbc\x80\x06\x01\x6d\xd6\x19\xb7\xed\x35\xdb\xd5\x4c\x20\x4f\xed\xf1\xb0\xc3\x8f\x55\x61\xb9\xaa\xaf\x3b\xfa\x9e\x7e\x7e\x66\x14\xda\xa8\x3c\x58\x4c\x2a\xe5\x4e\x96\xec\x7a\x50\x11\xcb\x19\x48\x15\xc8\x00\xfb\x73\x79\x49\xe9\x5d\xba\xa3\xf3\xce\xb6\x3d\x92\x60\x7a\x05\x9a\x4a\xb7\x3b\xc7\x4c\x4b\x9e\x35\x6a\x75\xa9\xd0\xcf\x64\xc9\xea\xba\x49\x04\xd2\xd2\xed\x1b\x9d\x4c\x63\xa4\xf8\x8d\xdc\xea\xa1\xa5\xca\xf0\x86\xca\x78\xb0\x0b\x39\xb2\xcc\x94\x1f\x94\xdc\x6c\x7b\x25\x05\x4a\xc3\x83\x25\x4f\x40\xaa\xd5\xaf\x16\x32\x2b\xbf\xde\x9d\x14\x05\x25\x10\x2a\xe5\x93\xee\xc2\x69\x34\x1f\x5b\x13\x2e\x07\xb1\xb8\x9b\xd3\x7d\xb4\x55\x73\xd0\xb4\x3b\x9b\xea\x20\xdd\x50\xca\xe3\x91\x4d\x17\x27\x13\x8a\xec\x2c\x7a\xc8\x6b\x2c\xf0\x6c\xd0\xcc\xb7\xa6\x46\xc3\x66\x73\x7a\xb7\x78\x95\xde\xfe\x77\xe8\x70\xb2\x4f\xf6\x35\x7e\xda\xaa\x52\xf6\x47\x87\x11\x3e\xfe\x19\x7e\x84\xfd\x5c\xf4\xa3\x6a\x50\xa6\x89\x9a\x05\xcd\xf1\x2c\xab\x50\x83\x74\x9b\x2e\x37\xea\x44\x75\xba\x98\x6f\x3d\xdb\x9d\xc9\xeb\x4e\xb9\x2f\xbb\x19\x9e\xcc\xb7\xe3\x2f\x5e\x38\xd0\x5b\xfd\xcf\xca\x1f\x3a\x20\x29\xb7\xe8\x08\x13\x6b\x52\x2e\x0a\x15\x62\x88\x96\x8a\xe5\x17\xdd\x79\x59\xf7\xb5\x4c\x76\x45\xf4\x5a\x7a\xde\x02\xa2\x33\xab\x60\x6a\x48\xec\xf9\x87\xfc\x94\x0f\xa1\x2e\x97\xb6\x23\x71\x1a\x6e\x92\x36\xe4\x52\x60\x53\xf4\x70\xd6\x28\x98\x13\x2c\xc9\x63\x43\xa2\xb5\xb9\x8f\x68\x34\x98\xb0\xdd\x6c\x17\x20\xf3\x7d\xac\xc5\xc4\x40\x3e\x00\x34\xff\x9c\xfc\x47\x3f\x8f\x3f\xd1\xbb\x72\x70\xeb\xcb\xe4\x3f\xfd\xfe\x5f\x1a\x9f\x7b\xa0\xfe\x12\x83\x3a\xfc\xf7\xbf\x7f\x7e\x95\x25\xfd\x95\x33\x00\xcc\x19\x84\x4a\x02\x00\x54\xac\x92\x88\xa1\x48\x82\x82\x26\xc4\x06\x26\x00\x32\x48\x5d\x23\x19\x9d\x34\x18\xcc\xb2\x34\x60\x31\x69\x42\x42\xa3\x38\x44\x32\x40\xa3\x59\x44\xb2\x34\x7b\x3c\x8c\xe1\x55\x33\x80\xbb\x8b\xa7\xf1\x77\x61\x7c\xbc\x84\x04\xc5\x50\x2c\x05\x68\x06\x3d\x8f\xff\x37\xb6\x87\x3e\x84\xff\x31\xe9\x32\x91\x47\xfa\xc0\x7f\x69\x0b\xf8\x60\x80\xeb\xdb\xbe\xd4\x9f\x8c\x9b\x93\x4a\xd9\x6c\x88\xac\xda\x91\xf9\x45\xb3\x8d\xdc\x75\xad\xa6\xe5\x49\x92\x59\xad\x45\x72\xb5\x6d\xc8\x39\xb5\xab\xe7\x5a\xb0\x4e\x37\x49\x91\xab\x55\xf4\xb4\xa9\x69\xf9\xd1\x80\xab\xa4\x01\x93\x2e\x83\x55\xad\x30\x0d\xda\xc2\x63\x57\x61\x3c\x86\xcf\xa1\x4f\x93\x8c\x7f\x22\xc2\xf4\xf2\xb9\xe3\x8c\xbe\x8e\x7f\xb2\xa3\x85\xbe\xc4\x7e\x27\x4a\x33\xfd\x4d\xfc\xef\x39\x83\x49\x64\x69\x85\x14\x1c\xf3\x7c\xa9\x2e\x1a\xb7\x72\xdb\xee\xea\xe2\xbf\x5f\x35\x68\x7f\x25\x14\x70\x1c\xad\x71\x10\x71\x26\x67\x72\x3a\xa5\x13\x58\xd5\x31\x43\xd3\x80\x20\x58\x96\x41\xc8\x40\x98\x55\x31\x05\x74\x9a\x22\x48\x02\x02\x96\x20\x54\x1a\x50\x24\x83\x58\x52\xd7\x98\xfd\xd5\x7c\xf4\x31\xcf\xf4\x15\x50\x70\x77\xa1\x8f\x44\x34\x17\x9f\x67\xfa\xfe\xf6\x08\x06\x14\x7a\x85\x33\x78\xe3\x66\xbe\x7b\x60\x70\xaf\x63\x3d\x31\x21\x0e\x81\x47\xce\x9d\xd4\x6a\x3a\x33\x99\x4c\x94\x71\xce\x69\xae\xcc\xce\xb4\x21\x72\x41\x55\x59\xf6\x8a\xa5\xcc\x2c\x2d\x08\x38\x33\xcc\x56\xea\x84\xde\x5d\x8a\x79\xa2\x23\x74\x71\x36\xbb\x28\x08\xf2\x78\xe1\x6d\x28\x79\xee\xac\xdd\x69\x65\x4a\xd5\x07\xc5\xb2\x24\xd3\x99\x86\xe7\x51\xfd\x07\xef\x51\xfa\xd5\xe0\x91\x6c\x8f\xc4\xeb\xf8\x3f\x7b\x2b\xdf\x0b\x8d\x77\xa2\xe8\xd9\xab\xf9\xdf\xb8\x35\xe2\x9f\xe8\x3c\x25\x35\xf8\xaf\xd2\xdf\x31\x07\xe6\xd3\xfc\x8f\x80\xf3\x55\x03\xfd\x97\x9e\xe8\xc3\xb0\x86\xae\x72\x10\x51\x34\x4d\x33\x9c\x46\xa9\x14\x09\x00\x67\x9a\x98\xa4\x55\x00\x21\xa7\x22\x43\xa5\x34\x6c\x90\xd0\x20\x75\x8e\xe3\x0c\x46\x05\x48\x35\x20\x42\x80\x56\xf7\x3b\xeb\xe8\x63\xe2\xe6\x2b\x00\xe7\xf6\x81\xa6\x7b\x48\xe1\x50\x7c\xe2\xe6\xfb\xdb\x23\xe0\xb0\xcc\xc7\x12\x58\x72\xc0\xb9\xb1\x04\xf6\x10\xe0\x84\x8c\x4e\x28\xe2\xf3\x61\x94\xa3\x8f\x70\xea\xa4\x62\x6e\x38\x6d\xb7\x37\xb3\xa0\x3a\x5e\xa5\x4b\xb3\x59\x61\x25\x5b\x82\x5c\x11\x99\x3e\x93\x86\xd9\xcd\x6a\x5a\x5c\xb1\x73\x6c\xa4\x03\x1a\x02\x49\xe3\x87\x43\x7d\xae\x39\x1b\xba\xd2\x2f\xab\x62\x93\x26\x32\xab\xb6\x54\x5b\x07\x83\xce\x30\xd7\xc8\x9b\x6a\xce\xe6\x72\x26\xa0\x44\xfe\x1f\x08\x24\xd9\x08\xff\xe3\x23\x9e\xeb\xf0\x25\x51\xc2\x50\x9b\x25\x89\xb2\x05\xa1\x88\xf4\xf5\xcd\x61\xc2\x39\xbf\x57\x47\x09\xff\x27\xe5\xff\x5f\x8a\xb2\x7d\x01\xd0\x25\x05\x9a\xaf\xd0\xdf\x67\xf8\x1f\x81\x8e\x2a\x77\x3a\xba\xeb\x49\x14\xdb\xb4\xca\xee\xc8\x17\xa9\x61\x67\x33\x6a\x10\xe9\x4c\x30\xf4\xfd\x72\x9b\x6d\x56\x6c\xdb\xf4\xb0\x11\x88\xb3\x55\xa9\x54\xac\xcc\x50\x6d\x21\x4d\x37\xbd\x51\x2e\x6d\x98\xac\xd8\x19\xd7\xb4\x5e\xb7\xc4\x6f\x47\x7d\x38\xa4\x33\x2d\x92\x6b\x08\xfc\x2f\x06\x3a\x84\x30\x64\x4c\x0d\xb2\x2c\x03\x74\x8d\x86\x34\xc2\x2a\x07\x19\x44\x69\xba\x06\x21\x54\x0d\x4d\x53\x55\xda\xc4\x3a\x34\x58\x4e\x45\x50\xe5\x54\x95\xd5\x39\x9d\xc5\x10\x63\x0e\x73\xc7\xe3\x50\x9e\xcb\xf0\x80\xf7\xe0\x8d\x86\xdc\x0d\x7f\x6a\xf7\x96\x3a\xe1\x25\x43\x42\xf6\x05\x07\xaa\xdc\xf0\xa7\x0e\x4f\x02\xd3\x1e\x93\xe1\x91\xe5\x3b\x6e\x23\x3d\x5a\x5b\x43\x35\xa3\x0c\xdb\x7e\x97\xf4\xf2\xae\x50\xde\x18\xc3\xc6\xc6\x06\x72\xb3\x34\x2b\x67\xd5\x56\xb6\x66\x4d\x26\x56\x21\xed\xd7\xfb\x5e\x4b\xf0\x95\xfe\xb8\xec\x4d\x1b\x56\x61\x5c\xf0\x3b\xa4\x37\xa1\x16\xcb\xc2\x94\xa5\x79\xcf\x52\x72\x5c\xb3\xae\x14\x5f\x96\xe1\x11\x2a\xf4\xc9\x0c\x8b\x75\x87\x18\x6a\x8d\x1b\x3a\x3c\x3c\x8f\x24\x22\xbe\x84\x7f\x32\xbf\xe8\x23\xc3\x23\x79\x56\x81\x97\x97\x7b\x82\xff\x6c\x56\xc1\x6f\xcc\x6a\xe0\xf9\xdf\x17\x48\xbb\x1a\xd4\xcb\x25\xd6\xc5\xbe\x2d\x16\xf7\xcf\xd9\xf9\xaa\xb6\xb8\xe8\x0b\x9f\x0f\x70\xfe\x77\x98\xaf\xc8\x4b\x47\x57\x9c\xc2\x12\x96\x44\x2d\x6f\xa0\xb5\xda\x92\x74\x5b\xc9\xf9\x2e\x27\x6e\x37\x65\xab\x35\x9b\xf0\xe3\x92\x5b\x2e\x8d\x96\x5e\xae\x8b\x00\xaf\x15\xf2\xd4\x46\xa5\x65\x67\xe4\xac\xbd\x7c\x1d\xd1\x8d\xaa\xb7\x76\xcd\x46\xab\x42\xcd\xf8\x8c\xbc\xed\x09\xbf\x78\x7d\x87\x42\x34\x63\x32\xaa\x06\x4d\x83\x85\x2a\x86\x80\x34\x01\x65\x40\xc0\x61\xa4\x1a\x58\x07\x18\x69\x3a\x65\x02\x8e\x25\x35\xca\xd4\x49\x53\x45\x0c\xc7\x42\x80\x0d\x8a\xc1\x90\x33\x98\x63\x6a\xe0\x73\xd0\x43\xdc\x83\x1e\x44\x93\x6c\xfc\xb2\xce\xfb\x5b\x02\xb2\x2c\xc5\x01\x9a\x63\x5f\x70\x59\x9e\x70\xde\xfc\xc2\x01\x36\xf2\x54\x15\x2c\x6f\x74\x8f\x2c\xaa\x33\x4e\x59\x2f\x5b\x9d\xad\xdc\x6b\xe7\xaa\x1c\x2b\x8c\x49\xb3\xeb\x95\x3b\x02\xc1\xad\xf2\xcb\xec\x56\x2c\x8e\x58\xdb\xce\x94\x0e\x16\x71\xda\xaa\xd2\xe1\xef\xbb\xef\x5b\xca\x05\x9e\xcd\x6e\xc6\x5b\xb1\xdf\xef\xca\xb5\x95\x3d\x90\x79\xad\x68\x96\xf1\x1c\x16\xb3\xf9\x2d\xdf\x9b\x74\x38\xd6\xf0\xe1\xa0\x9f\x9f\x8f\xfb\x6d\x4a\xb4\xea\x40\xc9\x49\xbc\x96\x71\xcb\xab\xbe\x0e\xe4\x71\x4d\xcd\x64\x24\xab\xcf\x92\x9d\x65\x27\x2f\xcd\xab\x2a\x3b\x6a\xf4\x4b\xd9\xc7\xb6\x8c\x9f\xf5\xf5\x38\x48\xe2\x93\x27\xfd\x6d\x5d\xd8\xcc\xd8\x57\xd9\x85\x9f\x47\x20\xe1\x25\xfc\x9f\xbd\x42\xe2\x09\x33\xd8\xb0\x95\x4c\xfa\x59\x33\xf8\x1b\xcd\x30\x1f\xe1\xcf\x2f\xc6\x18\x65\xfb\x59\x65\x5a\x03\xc4\xa4\xb5\xc9\x98\xbc\xc2\x91\x84\xba\xe9\xf2\x86\xa9\x0b\xda\xca\x5f\x0b\x94\x59\xa6\x33\x9b\x5c\x24\xe9\x90\x7f\x4d\xd2\xa1\x90\x5c\x17\x0d\x7b\x70\xb3\x9a\xf7\x74\xf1\x6c\x5b\x44\xfb\xc2\xe7\x75\xf1\xdf\xaf\x32\x1a\x97\x90\xf4\xed\xff\xed\x4c\x36\x41\x33\x0c\x4b\x92\x10\x80\x1f\x77\xc1\x2a\x0c\x50\x7f\xfc\xf1\xe7\x9f\x7f\xfc\xf9\x67\xaa\xae\xce\xf0\x5f\x29\xd5\xf7\x71\xf0\xe6\x07\x6a\xe0\x87\xff\xfd\xe6\x4e\xf0\xe6\xef\x94\xbc\x71\xf1\x5f\xa9\x6c\xa3\x2e\xc9\x6d\xbe\x54\x97\xff\x4e\x49\xfa\x08\xcf\xd4\xbf\x52\xee\x42\x9b\x5a\xfa\xdf\xa9\xc6\xca\xc6\xde\x5f\xa9\x1d\xc5\x3f\xfe\xe0\xab\xb2\xd8\x4e\xc9\xbc\x50\x15\x53\x8d\x7a\x55\x09\x53\xfc\x23\x95\x4a\xa5\xf8\x5c\x2e\x44\xed\x82\x61\xaa\xd9\x2e\xd5\xf8\xb6\x92\xaa\x88\x4a\xea\xbb\x65\x5c\x48\x8b\xd7\xee\x5b\x58\xe2\xc8\xef\x17\x49\x1d\xa1\x7a\x4d\xf2\x6b\x8c\xcf\xa5\x3f\xbc\xd5\x1d\x03\xff\x3c\xd6\xd3\xf2\xfd\x05\xf6\xde\x7f\x05\x1b\x17\x5f\xd4\x6f\xe8\x78\xee\xdb\xcc\x1a\x7a\xea\x61\xae\x10\xf9\xfd\xa2\xfa\x45\xa8\x5e\xab\xdf\x35\xc6\x77\x5b\xe7\x7d\xba\xb3\xaf\xa0\x1f\xf9\xf9\xf6\xa1\x90\xb7\x0f\x0d\xbc\x85\x55\xf3\xf6\x92\xda\x9d\xb3\xbd\x56\xb9\x44\x82\xa5\x3a\xf5\x52\xab\x23\x5e\x6b\xd8\x5d\xf9\xf3\x46\xfe\xa4\x6a\x5e\xd3\xac\x9f\xae\xf8\xa7\x1a\xd5\x71\xf1\xa1\x33\xbc\xb9\xaa\x17\x58\xba\xe5\xaa\x76\xa8\x26\xd7\x5f\xbf\xb8\x66\xd7\x99\xdc\xaa\xe9\x0d\xb1\x1e\xae\x79\x68\xf6\x7e\xbd\xee\x71\x05\x5e\x5c\xfb\x38\x36\xb7\xea\x7f\x53\xb4\xbb\x1a\x98\xe0\xcd\xdb\x52\x9d\x2e\xf0\xdb\x8e\x1a\x8e\xfe\x7e\x51\xfd\x22\x54\xaf\x55\xe7\x1a\xe3\x73\xe9\x27\x78\x73\x21\xbe\x63\x9a\xd8\xf3\x8f\xff\x7b\x91\xb0\x07\x62\xd7\x64\x0c\xb1\x39\x17\x6d\xff\xe2\xed\x8a\x7a\x03\x6f\xe1\x07\x6f\x53\xcb\xc6\x7e\xf8\xdf\x2f\x92\x34\x44\xf1\x9a\xb8\x51\x86\xe7\x32\x4f\xb1\x31\x3c\xd8\xbd\xcb\x19\x83\xae\x3b\x8b\x5d\x17\x32\xd4\x40\x7d\x3b\xfe\x7a\xb3\x8c\x37\x5b\x9d\xe1\x77\xb1\x4b\xf5\x9c\xd8\xbf\x23\x71\xb6\x2d\xf2\xb2\xf8\x6e\x57\xf7\x5f\xdc\x26\x9e\x6a\xd4\xcf\x0b\xa4\x3a\x52\xa9\x5e\x48\x69\x81\x87\x71\xea\xfb\x47\xe9\x9f\xa9\x5d\xf1\x78\xc9\x47\xce\x0c\xbf\x19\xce\x4c\xb5\xec\x04\x02\x47\x24\x0d\x11\x0b\x0b\x78\x2e\x5b\xa8\x50\xbc\x58\x96\x6d\x4e\x0f\xc6\xca\xc0\x7e\x60\xd9\xfb\x7f\x3f\x2f\xe0\x55\xb2\xf1\xa2\x5e\x2d\x1e\x33\x6f\xd4\x36\x7b\x20\x4c\x2e\x63\x98\xca\x4e\xa4\x08\x4e\x9e\xb7\xef\x09\x78\xe3\xa5\x39\xc0\xef\xf3\xf2\x1c\xe8\x3c\x26\x51\x0c\xe4\x6b\x9b\xf7\xfe\x9b\x58\x9c\x0f\x12\x61\x49\xce\xa2\x49\xd7\x46\xc0\xcf\xf7\x96\x7d\xf3\xf1\x7c\x81\x6d\xfd\x52\x61\xda\xe6\xcd\xc4\xf8\x73\x02\xba\x8e\x1f\x0c\x3d\xec\x5f\x95\x33\x44\xed\x31\x59\x43\x1f\xfc\x48\xf5\x8a\x62\x5b\x4c\x85\x69\x94\xa4\x54\xbd\x21\xef\xdd\x97\xbf\x2f\x44\x1f\xa9\xfe\xe8\x05\x32\xef\xc8\xec\x84\x3d\x7c\xf3\xaf\xfb\x32\x87\xd1\x74\xf7\xf1\x35\xb5\x5a\xb6\x8d\xbd\x57\x49\xf8\x41\xec\x31\xa5\x1e\xca\x5f\x88\x79\xd4\xef\xf5\xb7\xb7\x55\x7d\x00\x82\x67\x7a\xf0\x81\xc2\x63\xf2\x1f\x61\xe7\xbd\xdb\xfe\x4c\xa9\xae\x3b\xb5\xf4\x83\x39\x72\x3c\xe3\xca\x30\x8b\x7a\x62\xcf\x9a\xa4\x18\x7a\x3b\xf9\xa3\xde\xe7\xa3\xd6\xe9\x0a\xc9\x27\xed\x54\x2c\xc5\x07\xc5\xbc\xe1\xa5\xbc\xe1\x1d\xb5\xbd\xae\x9f\x05\xf3\x08\xb9\x70\x17\xc0\xa6\x89\xf5\x0b\x90\xbc\x98\xb4\xef\xa0\xfc\xff\xf6\x1f\xff\x5f\x9c\xb0\x96\xf1\x22\x31\x2d\xe3\x61\x01\xc3\x33\x8d\x04\x42\x3b\xee\x9b\xfb\x2a\xb9\x8f\xb4\xc2\xa2\xc7\x78\x6a\x89\x6a\x72\xbd\x02\xc1\xfa\x75\x15\x38\xd2\x8a\xb1\x0f\x09\xab\x10\xa6\x70\xad\x12\x8e\xbb\xeb\x95\x23\x27\x51\x1d\x8e\xc2\x7f\xd0\x48\xaa\xfc\xdb\x8a\xf6\x8f\x96\x73\x3f\xb8\x9f\xd7\xf5\x39\xb9\xb0\xc8\x87\xbf\x47\x91\xe4\xaa\x44\x61\xbd\xbe\x4a\xac\x0b\x9a\x0f\x42\xdd\x15\x01\x83\x43\x93\x04\xcf\x34\xeb\x07\x8d\xe4\x5d\xf2\x5e\xf7\x0b\x3c\x63\xc7\x44\x53\xfd\x4f\x4e\xc1\xae\x0a\x7c\x49\x2c\x22\xb9\x81\x23\x72\x86\xcb\xde\x15\x70\xef\xbe\xbe\x46\xbc\x3d\xa9\x87\x84\x8b\xf5\x99\xdf\xe9\xed\x65\xc7\xde\xcb\xd4\x17\xa1\x77\x4f\xc8\x48\xf1\x47\x24\x7d\x8d\x1e\xcf\xa8\x3d\x2a\xe5\x5d\x6d\xbe\x46\xb6\x87\x64\xba\x2d\xcb\xbb\xc4\x53\xc7\x99\x2c\xdc\xe7\x24\x3a\xa7\xf5\x70\x8b\x1e\x26\x48\x31\xf2\xb9\xaa\xe5\xbd\x05\xd6\x0c\xbf\x44\xc2\x28\xb5\xc7\xc6\xed\x51\xc0\x9f\xa9\xa8\xc8\x3f\x53\x47\x13\xaf\x4f\x1d\x1f\x1b\x6f\x6a\x10\x53\x89\x17\xd8\xed\x23\x9d\x7b\x12\x7f\x72\x76\xb4\xa3\xfa\x32\xed\x7e\x42\xb1\x77\xf5\x66\xd9\x06\x5e\xbf\x45\xa6\x1c\xfe\x9b\x63\xbf\xa9\x86\xe1\x61\xdf\x7f\x56\xa1\x77\x19\x9c\xc5\x22\xae\x06\x6e\x8e\x05\x3f\x21\xfb\xf3\xfd\xe0\x16\xed\xfb\x12\x5f\x19\x65\xe7\x04\x8f\xb3\xf0\x1d\xbd\x60\xe3\x26\x77\xea\x6e\x52\xbd\x3b\xed\xbf\xba\x54\x77\x4e\xf2\x38\x87\xda\x91\x3c\x75\xa2\x17\x49\x7b\x8d\xf4\xdd\xe9\xdb\xa3\x3d\x39\x44\xfc\xd5\x9d\xe1\x8c\x74\x92\xf9\x66\x3c\xb9\x99\xeb\x78\x3b\xc3\xb7\xc4\x9e\xff\x4c\x88\xf4\x61\x0e\xf7\xc5\x8f\x7c\xf0\x78\x65\x8e\xa6\xe7\xf1\x80\x51\x02\xfd\x87\x78\xdc\xad\x49\xa8\xec\xe3\x95\x70\x3d\xbc\xb4\x9c\x85\xff\x4b\x6a\x73\x8d\xd9\xdd\x6a\x5d\xfb\xe8\xf1\xfa\xbd\x07\xa4\xbe\xac\x4e\xef\x0c\xee\xd6\x23\x36\xa2\x7b\x4e\xfa\x84\xb7\x5f\x32\xb4\xa3\xd4\xaf\x3a\xc0\x9f\x1d\xe0\xe7\x44\xcf\x5d\xa8\x17\x8d\xf0\x5b\x2c\x1e\xa9\xc3\x1d\xbf\xee\x26\xb3\xd7\xc1\xd7\x25\xe1\x87\x64\xbf\x0f\x62\x61\x67\xfb\x2b\xba\xcd\x25\xfd\xc4\xae\xfe\x71\xb1\x75\xe7\x58\x2e\x36\x96\x3d\x3c\xcc\x81\x13\x2b\xf8\x3a\xb9\x9d\x74\xc7\x35\xe4\xf3\x69\x78\xa8\xcc\x0d\xc9\xa6\xaa\x1f\xbc\xcd\x1c\xc3\x32\x2d\x6c\x3c\x1b\x48\xbf\x4d\x36\x4e\xd2\x6b\x65\x6f\x48\xec\xe3\xe9\xf4\x25\x32\x1e\x08\xc5\x49\x75\x78\x7b\x6d\x04\x9d\x53\x78\x65\xbb\x9e\xd1\xbb\x25\x58\x7c\xcb\xfa\xd6\xd0\x3e\x52\x7b\x36\xea\x70\x49\xea\x6c\x6d\xfb\xf8\x3a\x6e\x79\xfb\x4a\x22\x81\x6a\xe0\xd3\xb4\xf6\x3d\xde\xfe\xa6\x39\xce\x24\xb1\x88\x37\x68\xde\x9d\x30\x7f\xff\x6e\xe0\x40\xb5\xa6\x7e\xea\xcf\xff\xfc\x27\xf5\xcd\x77\xa6\x46\x28\xb5\xea\xdb\x5f\x7f\x05\x78\x1d\xfc\xf8\xf1\x33\x15\x5f\x50\x77\x8c\xc7\x0a\x1e\x96\x32\xe2\x8b\x6a\xce\x62\x38\x0a\x1e\x62\x7f\x56\xf4\xb6\x00\x67\x45\x23\x22\xbc\x2f\xb7\xed\x4d\x6e\xea\xdf\x29\x92\xbc\x95\xf9\x11\xea\x03\xcf\x00\x5d\x2c\xc5\x5d\x63\x85\x13\x4d\x1e\xef\x53\x67\x04\x9f\x5c\xb0\xba\x4a\xed\xb6\x68\xb7\x16\xaa\x22\xe4\xf6\x09\x7b\xfb\x04\xbe\xd7\x8a\x19\xa5\xfb\x80\xc0\xe1\x5c\xc0\xcb\xe4\xcf\x87\xd3\x6f\x2d\xe3\xcd\x0c\x65\x01\xe5\x2b\xbf\x26\x09\xf7\xc8\x36\x95\x6f\xb4\xc5\x52\xa1\x7e\x4a\x0c\x4b\xb5\xc5\xbc\xd8\x16\xeb\x59\x51\x8a\x24\x44\xec\xdf\x36\xea\xa9\x4e\x33\xb7\x53\x63\x5b\x94\xe4\x76\x29\x2b\xef\xfe\x94\x13\xab\xa2\x2c\xa6\xb2\xbc\x94\xe5\x73\xe2\x8d\xec\x3a\x03\xfb\x91\x9f\x6f\x91\x08\xf5\xeb\x94\x71\xce\xe7\x4e\xea\x5c\x9c\x24\xe7\xfa\x89\x46\xd3\xaf\x2a\xeb\x68\xda\xef\xe4\x19\xc6\x6a\xe2\x18\xe1\xfb\xed\x7a\x08\xcb\x71\x4d\x0b\xef\xc1\xd3\xdb\x1d\xe6\x73\x1a\xb8\x8c\xb5\xff\x46\x35\xc4\x08\x73\xae\x8b\x2b\xab\x03\xaf\xed\x14\xd1\xc8\xef\x3f\x41\x21\xf1\x5d\xe3\x22\xb4\xfe\x48\xef\x48\xd9\x18\x1b\xd8\x48\x99\x8e\x97\x0a\x65\xc4\x07\x4e\x6a\xe5\x78\x93\x33\xc1\x4f\xc1\xc5\x9d\xa4\xbe\xeb\xd8\xbe\xe3\xa5\x64\xb1\x2f\xff\x1d\x93\x11\xb7\x9b\x0f\x1e\x8b\x5d\xa6\xc1\x09\x72\x5b\x14\xbf\x1f\xdf\xef\x84\xb9\xc6\xea\x90\x7e\xf8\x28\xbf\x7d\x32\xe3\x75\xa6\xe1\x3c\xc6\x9b\x9c\xc3\xb8\x73\x87\x6f\x04\xc5\x42\x5c\x2f\xc1\xeb\x26\xcf\xe3\x1c\xf9\x0e\xbb\xd0\x24\xfb\x83\xd3\xd9\xf4\xfa\x26\x93\x07\x92\xbb\x73\xed\x46\x33\x95\x6d\x54\x3b\xb5\x7a\xca\x32\x62\xbe\xbf\x99\x1e\x7d\x41\x61\xff\x87\x63\x9b\x86\x30\x58\x57\x7d\x5d\x35\xf0\x7b\x81\x9b\x29\x41\xe7\x85\xee\xba\xd2\x37\x4a\x9f\x47\x61\xcf\x0a\x9e\xe7\x59\xde\xad\xf9\xa1\xb1\xde\xed\xce\x6c\xb1\xc6\x46\x6a\xa9\x7a\xfa\x48\xf5\xbe\x23\xee\xc7\x71\x3b\xd0\xae\x4c\x28\xd9\x2e\xa6\xdc\xdf\xb7\x9b\xe9\xd8\x2f\x9c\x85\xa7\x27\xa3\xf4\xee\x3a\xec\x25\x3e\xac\x5d\xc4\x7e\xbf\xb7\x08\x14\x77\xde\xf1\x4a\xf9\x7d\xe2\x9a\xd8\x2f\x49\xb2\x74\x58\xf3\x51\x87\xc3\xfd\xba\x8f\x1f\xa8\x33\xf7\x4d\xf3\x2c\xfb\x72\xe9\xe7\x0d\x01\x00\xc0\xfb\xe4\xcd\xb3\xec\xef\xa7\x2f\x7e\xec\x13\xe0\x52\x34\x78\x67\x74\x90\x78\x6a\xcd\x17\x96\x61\x05\x9b\x37\xd7\x71\xa6\x7e\xea\xfb\xbe\x4f\x59\x46\x6a\x37\xe1\x3f\x25\xcf\xfd\x4c\xfd\xf9\x67\x6a\x84\xd7\x7f\x62\x7b\xd7\x58\x46\xaa\xe9\x38\xd3\x52\x6e\x5f\x76\xef\x0a\xf8\x33\x75\xe7\x5f\x86\xbe\xd8\xbf\x33\x31\x4e\x59\x76\x80\x77\x7e\xfc\xf9\x9b\xfd\x70\xdd\x8d\xd6\x83\x95\x4d\x69\xd6\x30\xfc\x79\x2a\x5b\x14\xb3\x95\xd4\xf7\x68\xb1\xff\xa4\xc0\x8f\x03\x01\x7f\xa4\x7a\x71\x1f\xe7\xc4\x3c\xdf\xa9\xca\x29\x70\x20\xf3\x3d\x5c\xf6\x3f\xff\x3e\x91\x38\x74\x40\x0f\xfb\xd8\x5b\x62\x3f\x35\xf6\x1d\x5b\x8b\x88\x79\x35\x22\x71\xbd\x46\x06\x9e\xe2\x00\x1b\x29\xcd\x71\xa6\x58\xb5\x2f\xa5\x31\xd5\xa9\x8f\x0f\x65\xa3\xbb\x13\xfe\xd8\xb5\xce\x59\x07\x88\xb4\xcb\xde\xf1\x39\x17\xb7\x51\xbf\x68\xbc\x43\xbb\x0f\x2d\xfb\xfb\xb5\xaa\xbd\xb9\x6a\x30\x7a\x73\x5c\xff\xc7\xdf\x51\x5e\x4b\xfc\x16\xa5\x15\x4b\x7e\x6f\xf1\x52\xdf\x8f\xd5\xfd\x79\x55\x45\xa1\xea\x48\x62\xab\xb3\x83\xc3\x8f\xd8\x6f\xa4\x66\x96\xf1\xe6\xe3\xf9\x5e\x2d\x92\xcc\xb7\xe5\x54\xaf\x24\x17\x53\xc4\xfe\x0f\xa5\x7a\xb6\x2d\xd6\xc4\xba\x9c\x12\x94\xe3\x9f\xea\x8d\x54\xad\x54\xdf\xef\x34\x3f\xfd\xe6\xfb\x1f\xbf\xb3\x7c\xb6\x28\xa6\x88\x0f\x01\xce\x47\x66\x6c\x7f\x8f\xeb\x43\x36\x5e\x07\x4b\x75\xfa\xfd\xdb\x6d\xf9\xbf\xfd\xf5\x97\x87\x87\xfa\x54\xf5\xfd\x63\xef\x3a\x2f\xf7\x16\x1d\x52\xe1\x26\xbf\x15\x48\x8f\x70\xbb\x5c\x72\xba\xda\x48\xe1\xf0\x62\x22\x26\x97\xd2\x3f\xca\xf3\xe2\xcb\x1f\x71\x6d\xf1\x01\x8b\xd7\x5b\xe5\xda\x0a\x7b\xb4\x9d\x7e\x9e\x95\xbc\x94\x3a\x52\xfc\x41\xad\xc7\x4a\x76\xd0\xbf\x7f\x3d\x2d\xee\xa6\x5a\xae\x56\xe6\x67\xbc\xe4\xd1\x41\xfa\x09\x01\xcf\x58\xbc\x46\xd2\x27\xa4\x79\x4a\x86\xc7\x3b\x53\x78\x8e\x74\xbb\x3b\x45\x16\x47\x7e\x49\x87\xba\x21\xdd\x95\x2e\x75\xab\x2e\x0f\x64\xe5\x25\xef\x56\x77\xc4\x8c\x5f\x56\x7a\x52\xe2\xa7\xa4\x7a\x52\x92\xab\x5d\xec\xda\x51\x27\x51\x6a\xef\xa7\x9d\x10\x3f\x53\xdf\x00\x20\x10\x36\x68\x93\x41\x26\xd6\x38\x93\x02\x8c\x4a\x22\x06\x69\x98\xd4\x39\x44\x51\xac\x4e\x51\x18\x11\x90\x63\x31\x8b\x69\x4d\x05\x26\x24\x01\x41\x90\x34\x80\x04\x34\x75\x02\x7d\xfb\xf1\xf7\x1f\x92\x58\x15\xb3\x72\xca\x1d\xbe\xe9\x6a\xa0\x4e\x9d\xe1\xbf\x7c\xfc\x10\xf4\xec\x8f\x38\x09\xbc\x05\xfe\xf1\xf7\x6e\x8a\x27\x8f\x70\xea\x63\x2a\x9b\x39\x9b\x42\xab\x1e\x4e\x0d\x1d\xcb\x1e\xee\xbc\x4d\x0d\xa7\x16\xb6\x87\xa7\xea\x6e\xda\x12\x38\x1f\x88\x95\xda\x93\xff\x99\xd2\x16\x41\xca\x0a\x52\x86\x83\x7d\xfb\x5b\x90\x9a\xa9\x41\x80\xbd\xbd\xdb\x1a\xec\xf7\x4f\x0d\xaf\xea\x29\x7e\x88\x9f\x34\x76\x3a\x52\x85\xfe\x99\x22\x62\x4e\x96\xb9\x4f\x86\xa5\x59\x8e\x23\x59\xc4\x72\xf1\x54\x6e\x75\x87\x4b\x71\xa8\xe7\x08\x9d\x04\x62\x0f\x74\x6e\x7a\xb9\xd7\xe7\x07\xb7\xfd\xdd\xab\xa8\x1c\xe7\xf9\x5e\xed\xd8\x21\xff\xeb\x3c\x43\xf2\xe2\x4d\x24\x5f\x31\xd6\x3f\x33\xb0\x7f\xf0\x41\xdf\xd3\x1f\x0f\x16\x34\xe6\x39\x10\x89\xc4\x15\x0f\xdf\x9f\x5b\xe0\x9b\xdf\x5f\x46\xa1\x3e\x43\x22\x97\x3b\x08\x10\x67\xdc\xef\x7e\x7d\x52\x4d\x52\x02\x91\x0f\x8f\x6e\x52\xd4\x07\x38\x4b\x30\xbe\x39\x21\x3b\x4b\xfc\x3b\xb4\xfe\xf5\x8f\xa2\x86\x36\x9a\x7b\xfb\x59\x2e\xb1\xdf\xbd\xbb\x9b\x44\xb8\x5f\x95\xf2\xef\x1e\x6d\x68\xa1\x31\xb6\x40\x78\x17\xdf\x7b\x04\xb1\x79\xd8\x52\x26\xb5\xaa\x29\x43\x0d\xd4\x5d\x25\x53\xc6\x62\xe6\xa6\x74\x67\xe6\xee\x1c\x92\x5d\xb9\xff\x1f\x00\x00\xff\xff\x47\x9e\x7d\x1a\x1d\xee\x04\x00") +var _kahunaHorizonSql = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\x7d\xf7\x8e\x22\x49\xd6\xef\xff\xf3\x14\x68\x34\x52\x4d\x5f\x7a\x86\xf0\xa6\xe7\xce\x95\x30\x89\x27\x81\xc4\xb3\x5a\xa1\x34\x91\x90\xb8\xc4\xbb\xd5\xf7\xee\x57\x98\xaa\xa2\x28\xa0\xa0\xba\xaa\x77\x77\xe6\x2b\xed\x8e\x68\x22\xe2\xb8\x38\xbf\x38\x71\xc2\xf1\xdb\x6f\x3f\xfd\xf6\x5b\xa0\xe0\x4f\x67\xed\x89\x2a\x15\xb3\x01\xc7\x9c\x99\x96\x39\x55\x01\x67\x3e\x18\xfd\xf4\xdb\x6f\x3f\x6d\xcb\x63\xf3\xc1\x48\x39\x01\x77\xe2\x0f\x9e\x2b\x2c\xd4\x64\xea\xf9\xc3\x80\xfc\x9d\xfd\x0e\x8f\x6a\x59\xeb\xc0\xa8\xdd\xda\x36\x3f\xa9\xf2\x53\x49\x2b\x07\xa6\x33\x73\xa6\x06\x6a\x38\x6b\xcd\xbc\x81\xf2\xe7\xb3\xc0\x9f\x01\xf0\xc7\xae\xa8\xef\xdb\xbd\xd7\xdf\xda\x7d\x6f\x5b\x5b\x0d\x6d\xdf\xf1\x86\xed\xc0\x9f\x81\x87\x4a\x39\x2e\x1e\xfe\x78\x24\x37\x74\xcc\x89\xd3\xb2\xfd\xa1\xeb\x4f\x06\xde\xb0\xdd\x9a\xce\x26\xde\xb0\x3d\x0d\xfc\x19\xf0\x87\x07\x1a\x1d\x65\xf7\x5a\xee\x7c\x68\xcf\x3c\x7f\xd8\xb2\x7c\xc7\x53\xdb\x72\xd7\xec\x4f\xd5\x0b\x36\x03\x6f\xd8\x1a\xa8\xe9\xd4\x6c\xef\x2a\x2c\xcd\xc9\xd0\x1b\xb6\xff\x38\xc8\xae\xcc\x89\xdd\x69\x8d\xcc\x59\x27\xf0\x67\x60\x34\xb7\xfa\x9e\xfd\x75\xab\xac\x6d\xce\xcc\xbe\xbf\xad\x16\xce\x96\x35\x23\x50\x0e\x47\xb2\x5a\x20\x15\x0f\x68\xf5\x54\xa9\x5c\x0a\xe4\xf5\x6c\xe3\x50\xff\xf7\x8e\x37\x9d\xf9\x93\x75\x6b\x36\x31\x1d\x35\x0d\xc4\x8c\x7c\x21\x10\xcd\xeb\xa5\xb2\x11\x4e\xe9\xe5\xa3\x46\x2f\x2b\xb6\x6c\x7f\x3e\x9c\xa9\x49\xcb\x9c\x4e\xd5\xac\xe5\x39\x2d\xb7\xa7\xd6\x7f\xfc\x08\x86\xf6\xee\xd3\x8f\x60\xb9\xf5\xab\x1f\xa7\xe0\x9e\xdb\xfd\xda\xed\x05\xdc\x3a\xf2\x35\x66\x47\xb5\x9e\x89\xef\xaa\xa7\xf4\x98\x56\x3f\xaa\x79\x20\x3b\x9b\xcc\xa7\xb3\x56\xdf\x1b\x6e\x45\x5b\xb7\x66\xeb\x91\x6a\xd9\xbe\xa3\x5a\xde\x74\x3a\x57\x93\xbb\x1a\xbf\xa3\xc9\xb3\x21\xde\x6a\x66\x3a\xaa\xa5\x5c\x57\xd9\xb3\x5d\x43\x7f\xe2\xa8\x49\xcb\xf2\xfd\xde\xf5\x86\x53\xaf\x3d\x54\x93\x63\x5e\xd7\xeb\xfb\xae\x7b\xa8\x3e\x55\xfd\xfe\x16\xd8\x3b\x93\xde\xd3\xe8\x2d\x13\x3c\xd7\xee\x9b\xd3\x59\x6b\xe0\x3b\x9e\xeb\x29\xa7\xd5\x57\x4e\xfb\xf6\xb6\xd6\x7c\x7d\xa3\x74\xde\xd0\x51\xab\xd6\x91\x1b\x0e\xa7\xe6\x6e\x48\x9a\xb6\xfc\xe1\x9b\x96\x7f\xd9\xda\x1f\xa9\x89\xf9\xd4\x76\xeb\x2d\xdf\xd1\xfa\x59\x92\xef\x92\xe2\xbe\xb6\x7b\x2b\xef\x1a\x4e\xd5\x78\xae\x86\xf6\x5d\x2a\x1c\x35\x1f\x4d\xd4\xc2\xf3\xe7\xd3\xc3\x77\xad\x8e\x39\xed\xbc\x93\xd4\xf7\x53\xf0\x06\x23\x7f\xb2\x1d\x38\x0f\xd1\xef\xbd\x64\xde\x6b\x4b\xbb\xef\x4f\x95\xd3\x32\xef\xf2\xc5\x47\x3c\xbf\xc3\x95\x0e\x60\x7e\x87\xd0\xc7\x2d\x4d\xc7\x99\xa8\xe9\xf4\x7a\xf3\xce\x6c\xe2\xec\x66\x08\xad\xbe\xef\xf7\xe6\xa3\x1b\x6a\x8f\xde\x12\x69\x5f\xcb\xf4\x26\x77\x12\x7e\x0c\x8f\x37\x37\xd8\x0e\x95\xdb\x31\xe3\xb6\xaa\x8f\xe4\xdf\xd1\xe4\xa6\xd1\xf5\xb1\xd1\x2e\x08\xde\xc1\xe4\x38\x68\xbe\xd5\x62\xb4\x6d\xd0\x99\xbd\xd9\x03\xd3\x17\x03\xd0\x36\x7c\xbd\xdd\xe2\x80\xd3\x5b\x2a\xfb\x7b\x39\xfc\x37\x2b\x7a\xd3\x59\x6b\xb6\x6a\x8d\xde\x26\xb9\xad\xe9\x8f\x6e\xad\xa9\x6e\xad\xf6\x18\x4d\xaf\x57\x56\xab\x51\xeb\x78\x76\x71\x63\xbc\x3f\xd3\x6c\x3b\xbd\xb8\xde\xc8\x5a\xdf\x14\x0c\xb7\xf6\x7d\x73\xc4\xbc\x35\xf0\xef\x85\xbc\x51\xab\xa7\xca\x6f\xeb\xf2\x34\xdc\x78\x43\xb7\xbf\x0b\x5a\x2d\x47\x4d\x67\xde\x70\xf7\xf9\xc6\xb6\x1d\x7f\xa0\x5a\x8e\x3f\x30\xbd\x5b\x5b\x6c\x13\xa6\xe3\x69\xe6\xd0\x1c\xa8\x5b\xa6\x99\x47\xf3\xb3\x2b\xd3\xcc\xe3\x59\xdc\xe8\xc6\x09\xec\x7e\xea\x72\x85\xe8\x61\x6e\x73\x2b\xbd\x9e\x5a\xb7\x16\x66\x7f\xae\x5a\xdb\x71\x5d\x5d\x21\x7c\x52\xf3\x66\x0e\x67\xa6\x4c\xad\x91\x39\x99\x79\xb6\x37\x32\x87\x57\xe7\xe1\x6f\x35\xbd\x5b\x86\xa7\x29\xcf\xbd\x12\x9c\x6f\x78\x37\xff\x9d\xc7\xdf\xc2\x6f\x5f\xf1\xd3\xe9\xef\x11\xb8\xcb\x54\xf6\x1f\x77\x99\xcb\x21\x8b\xdb\x21\xb8\x75\xa3\x04\x6d\x7f\x32\x6a\x0d\xbc\xf6\x61\x46\x79\x45\x84\x93\x9a\x37\xeb\x78\x32\x06\x5e\xe1\x70\x3a\x5a\xde\xca\xe1\xfe\xe4\xf0\x66\xca\x8f\x03\xca\x21\x91\xba\x46\xfe\xa4\xea\xdd\x3c\x6e\xa1\x7d\xb7\xdc\xdb\x81\xf0\x16\xc2\xbb\x01\xf3\x1a\xf5\x5b\x07\x85\x7d\xeb\x68\x3e\x5b\xc9\xe9\x01\xcf\xd9\xf3\x8e\x69\xf1\x70\x25\x5b\xbe\x91\xf6\x05\xb0\x7f\x00\xe5\x03\xcc\xae\x53\xda\xfd\xeb\x02\xa1\xa3\x91\xff\x7a\xc5\xfd\x68\x7e\xbd\xce\xc9\xc0\x7c\xbd\xf2\xb9\x04\xf6\xd0\xa2\xa4\x15\x2b\x9a\x1e\x7d\x47\x6f\x6d\x43\xe3\x54\x8d\xef\xe6\xfc\x82\xc8\xcd\xad\x1d\x75\x4b\xaa\x61\xb6\xdb\x5b\x0f\x78\xca\x0a\x67\x6f\xcf\x21\x1f\x9b\x59\x73\xbb\xa7\x66\x2f\xb3\x83\x9b\xc4\x6a\x31\x00\x00\x38\xb4\x88\x57\xf4\x68\x39\x95\xd7\xcf\xf4\xbe\xdf\x1a\x78\xfd\xbe\x37\xfd\x75\x9b\xb6\x4c\x67\xe6\x60\x14\x58\x7a\xb3\x4e\x60\xfb\xcf\xc0\xc6\x1f\xaa\xaf\x81\xe1\x7c\xa0\x26\x9e\xfd\xe5\xdd\xc4\xfc\xf9\xec\x0a\xbd\x5b\xa1\x73\xbb\x6f\x5c\x88\x90\xf7\x78\xc6\x79\x12\xb7\xb5\x3d\x24\xd1\xb7\x55\x3e\x64\xcc\x37\xeb\x76\x88\x96\xf7\xe8\xb2\x6f\x72\x63\xdd\xc3\xe8\x79\xbb\x3c\x4f\xb3\xe1\x1b\x24\x3a\x89\xb7\xd7\x2b\x9f\x84\xce\xeb\x95\x6f\xaf\x78\x12\xd3\x6e\xac\xbd\x0d\x26\xb7\x55\xbd\xd7\xbf\xfa\xde\x78\xee\x39\xde\x6c\xdd\x1a\xf9\x7e\xff\xf6\xa1\xe7\x69\xe0\x3a\x4f\x20\x9c\x48\x18\x5a\x22\x5c\x3e\x43\x64\xe0\x0d\x5b\xa3\x89\x67\xab\x5f\x0f\x48\xfc\xc7\x3f\xbf\xdc\xd0\xca\x5c\xbd\xa3\x55\xdf\x9c\xce\x7e\x35\x87\x6b\xd5\xdf\xed\xd6\xdc\xd0\xc2\xf5\x26\x67\x9b\x5c\x1e\x76\x9e\xf4\xd9\x8e\x98\xcf\xd2\x3d\x0d\x34\xcf\x82\x5e\xa1\xf1\xa8\xdd\x77\xd0\xd8\x2d\xfe\x6e\x9b\x3f\x0b\xff\x35\x70\x8f\x22\x3b\xd5\x6f\xa0\xa0\xd5\xcb\x9a\x5e\x3a\x21\xd1\x1f\xb5\xa7\xe3\xfe\x23\x6e\xa3\x49\x2d\x17\x7e\xc5\xe1\x8f\x9f\xf6\x1b\x75\xba\x39\x50\xdf\x1e\xbf\x0b\x94\xd7\x23\xf5\xed\xd0\xe4\x8f\x40\xc9\xee\xa8\x81\xf9\x2d\xf0\xdb\x1f\x81\xfc\x72\xa8\x26\xdf\x02\xbf\xed\xf6\xef\xa2\x86\xb6\xed\xaf\x03\xe5\x47\x7a\x3f\xbd\xa0\xf8\xb2\xf0\x40\x38\x9a\xcf\xe5\x34\xbd\x7c\x85\xf2\xbe\x42\x20\xaf\xbf\x24\x10\x48\x95\x02\x0f\x8f\x3b\x73\x8f\xdf\x4d\x77\x44\x1e\x4e\x39\x3f\xaa\x7f\xe0\xf9\x64\xa1\x37\xf5\x79\x61\x4b\x3d\x5f\x3e\xb1\x67\xa0\x96\x2a\x27\x9f\xc4\x3a\xde\xa2\x7b\xc1\xfe\x99\xca\x89\x20\xf7\x28\xff\x8a\xc8\xce\x00\x85\x6c\x68\xd4\x2e\x15\xb3\x81\xd1\xc4\xb7\x95\x33\x9f\x98\xfd\x40\xdf\x1c\xb6\xe7\x66\x5b\xed\xcc\x70\xe3\x96\xe2\xb1\xb8\x6f\x3b\xda\x41\xfc\x47\x5f\x7d\x96\xff\xb1\x6f\xcf\xd9\xf2\xc9\xb3\xdf\xa4\x1f\x30\xb4\x72\xc5\xd0\x4b\x47\xdf\xfd\x14\x08\x04\x02\xd9\xb0\x9e\xa8\x84\x13\x5a\x60\xa7\x7d\x2e\x57\xd9\x8f\x83\xa5\xb2\x91\x8a\x96\x77\x35\xc2\xa5\xc0\x2f\xad\x5f\x02\x25\x2d\xab\x45\xcb\x81\x5f\xe0\xf6\x5f\xa7\xbd\xf1\x26\x10\xbf\x4f\xbb\xb7\xc8\x7f\x98\x72\xe8\x9c\x72\xb7\x8c\x54\xdf\xa7\xdf\x0d\x1c\x9e\x54\x7c\xfa\xea\x5d\x1a\xfe\xfa\x53\x20\x10\x0d\x97\xb4\x40\x2d\xa9\xe9\x81\x5f\xe0\x3f\xe0\x3f\x43\xbf\xc0\x7f\xa0\x7f\xfe\xbf\x5f\xd0\xee\x33\xfa\x07\xfa\x67\xa0\xbc\x2f\x0c\x68\xd9\x92\xb6\x35\x8a\xa6\xc7\xbe\x9c\xb5\xcc\x0d\x71\xe0\x3b\x2d\xf3\x36\x87\xcf\xb6\xcc\xff\x7d\x8f\x65\x5e\xc7\xd4\x83\x1d\x9e\xe2\xf0\x6d\x86\x78\x0e\xdb\xaf\x28\xee\x24\x0e\x04\x4a\x5b\x5b\x05\xfe\x7c\x1e\x01\xbe\xee\xbf\x2e\x37\x0a\x5a\xe0\xcf\x63\x44\x7c\x39\x87\xda\x0f\x95\xf1\x94\xe0\x89\x88\x8f\x30\xbe\x5d\xc2\xb3\x53\xa0\xef\x95\xf2\x1c\xd1\x13\x49\x5f\x00\xf2\xa5\xb8\xcf\x5e\xf6\x5a\xda\x73\xd3\xbc\xef\x96\xf6\x0c\xd1\x53\x69\x8f\x41\x72\x55\xda\x6d\xe4\x72\x94\x6b\xce\xfb\xb3\xd6\xcc\xb4\xfa\x6a\x3a\x32\x6d\x15\xf8\x33\xf0\xf0\xf0\xc7\xcb\xd2\x6d\x16\xd9\xf2\x3d\xe7\xe8\xb4\xcd\x0b\x5d\x9f\x26\xdf\x07\xfd\x76\xe8\xba\x4d\xb7\x3d\x10\x9f\x56\xac\xf6\xba\x3c\xaf\xb3\x07\xec\x8e\x39\x31\xed\x99\x9a\x04\x16\xe6\x64\xed\x0d\xdb\xbf\x52\xf6\x65\x37\x53\xd0\x2b\xd9\xec\x5e\x3f\xcb\xec\x9b\x43\x5b\x05\x2c\xaf\xed\x0d\x67\xa7\x85\xfb\x7d\xfd\xbe\x67\x5a\x5e\xdf\x9b\x79\x6a\x7a\xbe\xde\xe3\xf1\x84\x1b\x2a\xee\x77\xb9\x5b\xc3\xf9\xc0\x52\x93\xf3\x95\x86\xf3\x41\x6b\x3a\xb7\xd4\x70\x36\xd9\x12\xf2\x86\x33\xd5\x56\x93\x93\x4a\x67\x77\x30\x6e\xd2\xd8\xed\x9b\xed\x4b\x54\x8f\xf6\x36\xce\xd0\xc2\xe8\x94\xd6\xc0\x9c\xce\xd4\xa4\xb5\x54\x5e\xbb\x33\x0b\x4c\x07\xe6\xd6\x0e\xa7\xfa\xcc\x3a\x13\x35\xed\xf8\x7d\xa7\xd5\xf7\x97\x6f\x57\x1a\x28\xc7\x9b\x0f\xde\xae\xd7\xf1\xda\x9d\x4b\xb5\xce\x1d\xe6\x78\xa5\xf2\x6b\xdc\xbd\xcc\x19\xbf\xd7\x21\xf7\xcb\x9d\x7b\xaf\x3c\x2c\x1f\xf5\xd4\xfa\x8c\x5d\x21\x05\xa7\x86\xbd\xd3\x8b\x87\xe6\x40\x9d\xa9\xc8\xc8\x69\xc5\xdd\x0a\xdf\x99\x9a\xf2\x95\x04\xdf\x6b\xc2\xc7\x24\xfd\xbb\xad\xf8\xb8\xd8\x7d\x03\xbc\x5f\xeb\xbb\x6f\x1c\x98\xa9\xd5\xa9\x8b\x1c\x7c\xf6\x3c\x0e\xa6\x23\x7f\x38\xf5\x27\xe7\x6d\xbf\x53\xfa\x20\xeb\x7e\x11\xf0\xd5\x6a\xbb\xb5\x6e\x3d\x92\xc8\xeb\xaf\x55\xa9\x94\x52\x7a\x22\x10\x29\x1b\x9a\xf6\xeb\xa1\xde\x6b\x43\x1e\x2d\x8b\xbc\xdb\x86\x47\x5b\x11\x7b\xf3\x79\xce\xf9\x31\xc7\x1c\x6c\x25\x7c\xad\xef\x99\xa1\xe9\x69\xbc\x3d\x6f\xba\xfd\xf0\x72\x09\xbd\xfe\xa0\x7f\xc6\xa8\x88\xd2\x2f\x57\x7c\xea\x74\x39\xe9\xbd\xe6\x38\xdd\xfb\x39\x78\xd4\xd3\x96\xd5\x05\x8d\x9e\xb7\xb7\xce\x61\xf7\xd5\x98\x78\xbc\xef\x75\x13\x78\x0f\xb6\x3f\xe3\xa3\x57\xcd\xfd\xda\x4e\xa7\x6b\x74\xef\xb5\xd3\xe9\x2e\xdc\x93\xeb\x9c\x11\xd1\x1c\x8d\xfa\xde\xee\xb0\x51\xe0\xd2\x32\xf4\x6b\x41\x2f\xad\x40\x3e\xae\x67\x1c\x96\x2e\x6f\x93\xf9\x69\xa1\xf3\x02\xd5\xc3\x34\x26\x6c\x94\xf7\x2b\x02\x70\xf7\x45\x4a\x8f\x1a\xda\x2e\x7d\x8f\x34\x0e\x5f\xe9\xf9\x40\x2e\xa5\x57\xc3\xd9\x8a\xf6\xf4\xef\x70\xfd\xf9\xdf\xd1\x70\x34\xa9\x05\xe0\x5b\xca\xbc\xdb\xec\xa7\x84\x5e\x41\xf6\xb0\x29\x14\x18\xaa\xd5\x6c\x61\xf6\x7f\x7d\xb8\xa0\xf1\xc3\xb7\x6f\x13\xd5\xb6\xfb\xe6\x74\xfa\xca\xd7\xf6\x87\xac\xce\x8f\x9d\x8f\x1d\xf5\x24\x89\xdd\x37\xbd\xc1\x76\x76\xd7\x3a\x4c\x93\xa6\x81\x5f\x07\xe6\x70\x6e\xf6\xfb\xeb\x2d\x29\xe5\x7c\xb9\xd8\x0b\xaf\xdb\x7e\x5e\x7f\x9c\x35\xe3\x39\xe1\x2f\x8c\x81\x97\x2d\x7b\x51\x8b\x63\x1b\xef\x4d\xfb\xaa\x6a\xeb\x14\x31\xc7\x81\xa3\xa2\xa7\x8a\x95\xc7\xf8\xf1\xf3\xcb\x53\x71\x67\x98\xee\x4e\xd6\xfd\xbc\x0d\x26\x57\xd4\xdb\x87\x15\x6b\x36\x51\x2a\xf0\xab\xe7\x7c\xf9\xe3\xfd\xcc\xce\x29\x73\x17\xfb\x73\x04\xbe\x5c\xea\xaa\xe7\x25\xf5\x8b\x9d\xf6\xba\xea\xa5\x50\x76\x51\xc2\x33\x2d\x6e\xed\x91\x6b\x02\xee\xfb\x66\xfa\xc2\x3a\x57\x15\x7a\x61\xa7\xb3\x7a\x7d\xbd\xaa\xc4\x73\xbf\xbe\x4b\xd6\x63\x4e\x1f\x28\xf4\x77\x4a\xf5\xdd\xb2\xdc\xe5\x70\xc7\x9b\x30\x6f\xba\xdc\xcb\xb3\xd1\x3f\xce\xe9\xae\x0b\x79\xce\xed\xde\x50\xeb\xac\xdd\x4e\xb4\xfb\x2e\xd7\x7b\x5b\xe2\x97\xdc\x3e\x58\xf8\xef\x96\xee\x03\x24\xba\xe4\x86\x29\xbd\xa4\x19\xe5\x40\x4a\x2f\xe7\xaf\x8d\xa1\xbb\xe8\x56\x0a\xfc\x0a\xbf\x06\x1e\xc0\xe1\x0f\x72\x21\x10\x73\x2d\x57\x61\x2c\x15\x74\xa9\x4d\x31\x81\xdc\x66\xae\x72\x5c\x85\x6c\x40\x95\xb0\x94\x0d\x09\x06\x18\x12\xac\x6c\xc2\x2c\x2c\xa4\x80\x16\x90\x36\x76\xe5\xc3\x97\x3f\x7e\x3a\xac\x4d\x3e\x6f\x2b\xfc\x3e\x55\xb7\x46\xba\xaf\x01\xf8\x35\x30\x9b\xcc\xd5\x97\x3f\xb6\x93\x83\x72\x47\x05\x9e\x77\xf6\x43\xc7\x47\x40\x02\xe6\x44\x05\xda\xfe\x36\x6f\x98\xf9\x01\x4b\x05\xe6\xc3\x89\xea\x9b\x33\xe5\x6c\xff\xfd\xc4\xe1\x71\xd1\x65\xfa\x35\x60\xcd\x67\x01\x6f\x16\x70\x7c\x35\x1d\x3e\xcc\x02\x03\x73\xb6\x9d\x93\xb8\xfe\x36\x65\x9b\xce\xbc\x61\xfb\xac\xe1\xae\x8e\x0e\x4f\x26\x44\x42\x10\x09\xa8\x14\xf4\x6b\x00\x7e\xf9\xe3\xfd\x94\x04\x15\x52\x62\xc1\x84\xbc\x4c\xe8\x0d\x5f\x79\x2d\x14\xf9\x6e\x5a\x4f\x62\x89\x3d\xa9\xf3\xb3\xd2\xfd\x09\x82\xef\x9e\x93\xee\xcf\x2a\x3d\x4d\xa0\xae\x65\x4a\xbb\x54\xea\x96\xe4\xfc\xf3\x12\xab\x2b\x29\xc7\x8b\x43\x18\x1f\x94\x70\x1c\xd3\xfc\x61\xe9\xc6\x35\x45\x02\xf9\x9a\xae\xc5\x02\x91\xc6\x1b\x1a\xed\xcf\x9e\x5d\x57\xe8\x89\xd6\x49\xf1\xef\x9e\x73\x49\xb6\xc7\x93\x31\xdf\xeb\x75\x07\x3a\x27\xf1\xf8\x68\x09\xe8\x6a\x2c\x7e\x7b\xaa\xf8\xf3\xee\xac\xfd\xcf\x17\xbc\xf9\xca\x92\x80\xa3\x66\xa6\xd7\x9f\x06\xba\x53\x7f\x68\x5d\x76\xb6\xc7\xe3\x44\xdf\x6b\x87\x03\x9d\x83\x1d\x1e\x17\x91\x2f\xc8\x76\x74\x7f\xe9\x26\x14\x9e\xbb\x3a\x75\xbe\xe1\xc1\x2c\xc7\xa3\xd3\x6e\xe5\xe2\x51\x8e\xc7\x2c\x0a\x9c\x70\x38\x1a\x64\x6f\xaa\xff\x74\x7f\x29\x70\xe5\x30\xda\x69\x9b\x89\xda\xc6\x99\x37\x1a\xed\xeb\xce\x47\xce\xcd\x75\x9f\x5c\xe7\xf0\xcf\x93\xab\x5d\xaf\x74\x81\xaf\x56\xbc\x66\x66\xbf\x65\xfb\xde\xf0\xc2\x96\x80\xab\xd4\xee\xf4\xcf\x85\x1d\x08\x73\xaa\x5a\xae\xba\xd4\xd7\xbb\xe2\x89\x9a\xaa\xc9\xe2\x52\x95\x81\xb9\x6a\xcd\x56\xad\xdd\xaa\x97\xb7\xb9\x54\x6b\x34\xf1\x67\xbe\xed\xf7\x2f\xea\x75\xda\x47\x8f\xce\xa2\x4c\xe7\xb0\xbe\x7a\x58\x39\x9d\xdb\xb6\x9a\x4e\xdd\x79\xbf\x75\xd1\x51\x0e\x8a\x9b\x5e\x5f\x39\x6f\xd5\x3a\x88\x7e\xc1\x85\x2e\x43\xef\xc2\x29\xc0\xef\x45\xe2\x85\xd3\xc0\x6f\xc4\xc5\xfb\x93\xd7\xcb\x63\xdc\xbd\x2a\x7f\x6c\xa8\xbb\xca\xe3\x47\x85\xbe\xbb\x14\xfd\xce\x50\x78\x95\xd7\xeb\xd0\x78\xbe\xfa\x95\x50\x79\x74\x46\xf6\x76\xdf\xfc\xed\xb7\xfd\xea\x5b\xc0\x9b\xb6\x46\xe6\x7a\xa0\x86\xb3\x3f\x77\x7b\xab\x8f\xbb\xae\xdb\xe9\xf6\xfe\xb8\xd5\xd7\xc0\xc4\x9c\x75\xb6\x10\xed\x98\xbb\x3d\xbd\x61\x7b\x3b\x06\x4c\xd5\x64\x16\xd8\x9d\x1c\x7f\xcb\xd1\xdf\xda\x39\xb8\x25\x3b\xde\x2d\x12\xdb\x7b\xbb\xec\x42\xee\x77\x46\xdc\xc3\x50\xe3\xcf\x27\xf6\xd3\x55\xc4\x0b\xb1\xee\x71\xfc\x7a\x78\xf8\xf6\xed\xad\xdd\x8d\x67\x6b\x06\x2c\xdf\xef\x2b\x73\xf8\x64\xcf\x9d\x75\x2f\x43\xef\x70\x9e\xfc\x7b\x47\x97\xc3\xfb\x05\xf7\xae\x78\x5d\x9f\xc6\x1c\x46\xea\xf7\x04\xd5\xdd\xbd\x81\x8b\x6c\x4f\x5e\x4f\xb8\x56\xe9\xf0\xa0\xc3\xb5\x2a\xfb\x4d\x90\xb3\x15\x5e\xbf\x43\xf1\x46\xbd\xab\xec\x9e\x6a\x5d\xe1\xb8\x13\xc9\x9b\x1e\x9e\x10\x78\xf4\x86\xc7\x50\xe9\xd9\xaa\x35\x7c\x31\x2d\xd8\x7f\xf7\x72\xaa\xf0\x7c\xaf\xb6\x75\x32\x89\x78\x71\xb3\xf7\xb4\x70\xe2\xcf\x87\xce\xee\x11\x93\xbe\x37\x1a\x99\x6d\xf5\x9a\xa8\x37\x6d\xa9\x95\x69\xcf\x5e\xca\x75\x74\xa5\xe6\xec\x33\x17\x3b\x75\x5b\xbb\x87\x50\x02\xd1\xa4\x16\xcd\x04\x7e\xfd\xf5\xd8\xf4\xff\xef\xcf\x00\xf8\xf2\xe5\x2d\x5a\xe7\xda\x3f\x9a\xfb\xff\xbe\xea\x81\x1b\xe8\xbd\xe8\x8d\x13\xf2\x27\x5d\xb5\x97\xf0\xa7\x4b\xa9\xee\x87\x82\x70\x7f\x09\x63\x07\xc5\x67\xbc\x1c\x7c\x65\xe8\xcf\x02\xc3\x79\xbf\xbf\xd5\xed\xac\x7f\x1f\x57\xb8\xe4\x94\xaf\xea\x3c\xc1\xf7\x15\xf9\x85\xdf\x9f\x0f\xd4\xe3\x11\x9c\xb3\xd4\xaf\x54\x31\x17\xed\xb3\xdf\x77\xbc\x76\xa7\x35\xbc\x5c\xe4\x9c\x2d\xea\xfb\xcb\x0b\x8d\xb6\x25\xe7\xdb\x9c\x5e\xa0\x39\x67\x82\x5d\x9d\xf3\x84\x77\x45\xe7\x29\xef\x06\xb5\xb7\x48\xef\x2b\x9d\xa7\xbd\x2f\x3b\x47\xfc\xa7\x40\xa0\x60\xa4\x72\x61\xa3\x11\xc8\x68\x8d\x97\x9e\xfe\xf5\x55\xaf\x7e\x7d\xf6\x92\x17\xe7\x03\xf2\x46\xc0\xd0\x0a\xd9\x70\xf4\xe8\x28\xe2\xd1\x5d\x9b\xab\xf9\x47\x60\x36\x99\x3f\x4b\xfd\x94\x60\x7c\xf9\x29\xf0\x74\x52\xf1\xa0\x6d\xb8\x14\xf8\xe5\x97\x9f\x02\x81\x88\x96\x48\xe9\x3b\xc0\xed\x2b\x04\x1c\x6f\xf1\xab\x6d\x4e\x67\xbf\xfe\xaa\x56\xb3\x6d\xec\xfb\x55\x8d\x7c\xbb\xb3\x7f\xc7\x69\xf6\x25\xf0\x7f\x02\x70\xeb\xe5\x5f\x02\xe6\x63\x76\xf2\x65\xcf\xf6\xcb\xff\xd9\xfe\xf7\x8f\x9f\x02\x01\x4d\x8f\xfd\xf1\xd3\x2f\xbf\x3c\x1f\x83\x7c\x3a\xe1\xfc\x78\x14\xf2\xbd\xda\x7e\xac\xaa\x47\x7c\xbe\x7d\x7b\x62\x74\xd0\xe6\x5e\x45\xf6\xeb\xc7\xe7\xaf\x72\x9d\xac\x10\x3b\x6a\xfa\x53\xe0\xe5\x5a\xf0\xb3\x28\xa7\xb1\xf7\x6b\xe0\x61\x37\xae\x3c\x7c\xfb\xf6\x78\x95\xea\xd5\x61\x92\x8b\xf7\xce\x5e\x33\x3e\x0c\x52\x2f\x98\x9f\xb6\xba\x36\x67\x39\x7f\x83\xee\x03\x06\xd0\xf3\xb7\x31\x6f\xcc\x92\xee\xd9\x6f\x79\x4f\x9e\xf4\xd6\xfd\xc3\x8f\xc9\x94\xde\xe0\xf2\xa3\x72\xa5\x3b\x95\xfd\xce\x6c\xe9\x0d\x6e\xaf\xf3\xa5\x4b\x0d\xae\x64\x4c\x2f\xee\x9c\xbe\xd7\x57\xaf\xdc\x63\x3d\xb8\xe9\xb1\x64\x37\xaf\xa5\x1d\x70\xf7\xc6\x0a\xdd\xad\xe9\xd0\xf5\xcc\xe6\xfc\x81\xc1\x27\xd6\x67\x61\x33\x30\x57\x57\x56\x93\x2e\xad\xd3\xfd\x5b\x56\xda\x66\xab\x96\x1a\x2e\x54\xdf\x1f\xa9\x73\xe7\x8e\x66\xab\xd6\x44\x4d\x77\xa9\xee\xd9\xc2\x81\x9a\x99\x17\x8a\x5c\xa5\x2e\x16\x4f\xbd\xf6\xd0\x9c\xcd\x27\xea\xdc\x11\x19\xc9\xbe\xfc\xe3\x9f\xcf\x19\xe5\xbf\xfe\xe7\x5c\x4e\xf9\x8f\x7f\x9e\xda\x5c\x0d\xfc\x0b\x7b\x22\xcf\xb4\x86\xfe\x50\xdd\x90\xa1\x6e\x69\xbd\x26\x73\xd0\xcc\x1b\xa8\x96\xb5\xcd\x1e\x76\x67\xc5\xc4\x64\x9b\xea\xbf\x70\xcb\xf3\x85\x03\x6f\xd8\xba\xe0\x3d\x97\x2b\xb4\x4e\x13\x93\xb3\x95\x0e\x7c\xdb\xe6\xe8\x45\xdd\xdd\x5c\xe4\xe9\x30\xe4\xb6\x17\xfe\xf1\xcf\xd3\xd5\xc3\x97\xb9\xcd\xb6\xcb\xb6\x6a\xb7\xd5\xc9\x72\xec\x70\xb8\x0d\x73\x37\x41\xf5\x99\xd2\x55\x5c\x1d\x13\x7e\xdb\x1b\x0e\xe7\xf4\xd4\xb2\xf5\x08\xad\xbd\x78\xaf\x92\x94\xd3\xeb\xf5\xef\x1d\xb8\x4e\x5f\x5a\xd9\x0f\x56\xe7\xcf\x15\xbf\x38\x56\x79\xfd\xfc\xef\x1b\x27\x30\x0f\x0f\x08\xbc\x57\xe8\xc3\x73\x33\x8f\xdb\x17\xdb\x9c\xfa\xd6\x93\xcd\xd7\x97\x20\x5e\xbc\x0b\x78\x0e\xcf\xc7\x2f\xf3\x9d\x3d\xbe\x78\x65\x11\x60\x97\xd4\x0f\x2f\x2e\x98\x7b\xb6\xba\x34\x93\xd9\x15\x06\x1c\x7f\x6e\xf5\x55\x60\x34\x51\xb6\xb7\x5b\x53\xbf\xfd\x1c\xfe\x3b\x0f\x5f\x1f\x3f\x08\xf1\xde\xbe\x3a\x7e\x74\xe8\x87\x9c\x5d\xbf\xf1\xfc\xed\x3d\x07\x6a\xef\xdb\x57\xbe\x7a\x05\xe4\xd9\x1c\xad\xbe\x37\xf0\x2e\xad\x17\x7d\xf4\x45\x91\x8f\x71\x8e\xcb\xfb\xc6\x01\xcf\x79\xf4\x90\xc7\xa7\x46\x6e\x99\xf0\xed\x5d\x64\xf7\xb6\xcb\x1b\xaf\x98\x94\xb4\xf2\x95\xf3\xaa\xc7\xfb\xcb\xc7\x27\x29\xef\x5b\xf1\xff\x38\x25\x6e\x7c\xe4\xe5\xaa\x52\x57\x77\x0a\x6e\x51\xf2\x62\xde\xf4\x61\x6a\xde\xfc\x4e\xce\x55\x45\xdf\x98\xe4\x9f\x57\x35\x66\xce\xcc\xdd\xb9\x9e\x2b\xb7\xbe\x02\xb1\x70\x39\xfc\x86\x6e\x6f\xd0\x7b\x7d\x73\xe7\x23\x88\x9e\xbb\xcb\xf2\x3d\x74\x2f\xdc\x65\xb8\x85\xe4\xf1\x79\xa1\xe3\xbb\x0c\xc7\x07\xc7\xd0\xe3\xc9\xb1\xfd\xd1\x2d\xf0\x35\xf0\xf0\x70\x72\xd4\xe8\x5c\x53\xf4\x35\xf0\x70\x67\x13\x7c\x68\x02\xbe\x06\xf0\x8d\x4d\xc8\xd7\xc0\x03\x06\xef\x93\x90\x3e\x4b\x78\x2b\x3b\xf6\x35\xf0\x00\xcf\x73\xbb\xd0\x3b\xd7\x6e\x51\xdc\xdb\x43\xa7\x37\x29\x1e\xa5\x7a\x80\x2d\x6f\xe8\xcd\x3c\xb3\xdf\xda\x6f\xd3\xfd\x3e\x1d\xf7\x1f\x76\x5d\x07\xe5\x6f\x10\xfc\x86\x61\x00\x92\x6f\x50\x7e\x23\xf2\x77\x80\x05\xc6\x41\x00\x4f\xd5\xbd\x48\x1c\xb5\xf6\x07\x1f\x5f\x80\xd3\x5a\xef\x96\x83\xae\x32\x22\x88\xf1\x7b\x18\xe1\xd6\x7c\xaa\x9e\xa7\xfb\xde\xf0\xd5\xc3\xae\xd7\xd9\x51\x89\xd8\x3d\xfc\x48\xcb\x74\x9c\xd6\xe9\x59\x85\xab\x3c\x28\x81\xe4\x2e\x9d\x68\x6b\x9f\xe0\x3e\x2e\xb1\xed\x6e\xb7\x5e\x65\xc1\xa0\x00\xe4\x1e\x16\xec\x91\xc5\x21\x0e\xde\xc0\x82\x03\x79\x97\x0b\xf0\xfd\x04\x61\x7d\xbb\x16\x02\x82\xfb\x0c\x25\x76\x9d\x61\xb6\xdb\x13\xd5\x36\x67\xfe\xe4\x7a\x5f\x0b\x0a\x91\xb8\x8f\xfc\xb1\x91\x0e\x2f\xe5\xdd\xa0\x86\xa4\xfc\xae\xce\x90\x3b\x35\xf6\xe7\x58\x5a\x2b\x67\x72\x95\xba\x44\x98\xdd\xe5\xb1\x10\xec\xc8\x1f\x7a\x61\x97\x17\x5c\x67\x40\x19\x87\x77\x31\x80\xc7\x0c\x9e\xa6\xde\x5b\xfc\x5f\x67\x24\x91\x90\x77\x31\x42\x2f\x7a\xe2\xb0\x5f\xb7\xff\xa5\x85\x6b\x9c\x20\xa0\x92\xdd\xa7\x12\xde\xab\xf3\xb4\x3f\x7a\xd5\xb3\x20\x84\x9c\xde\xe5\xb8\x90\xb4\x5c\x6f\xf5\xf8\x54\xa5\x3f\xe8\xb7\x5c\x4f\xf5\xaf\x8e\x8c\x10\x62\x8e\xef\xeb\x78\xfa\xb8\xfa\xf1\x78\xce\x69\xf5\x86\x1a\x94\xf2\xbb\x00\x02\x59\xcb\x1b\xb6\xd5\x74\xd6\x7a\x7d\x92\xea\x0d\x56\x4c\xde\x87\x45\xc8\x5f\x4c\xfa\x76\x47\xd6\xcc\xeb\xb1\x04\x42\x41\x19\xba\x8b\x89\x78\x72\x5f\xd7\x9f\x3c\xce\xb9\xae\xf2\x40\x58\x60\x7a\x17\x0f\xb9\x77\xaa\xeb\x64\x31\x86\xe0\x2e\x8f\x42\xe0\x8c\xe8\x6f\x83\x10\x62\x4a\xe4\x5d\x20\x44\xf0\x11\xe9\x13\x35\xf0\x17\xaa\xb5\x51\x13\xff\x69\xef\xdc\x1f\x4e\x67\x13\xd3\x7b\x23\xec\x42\x2c\x00\xbe\x0b\x90\x08\xb5\x8e\x56\x05\xae\xd2\x26\x84\x83\xbb\x5c\x0b\xe1\xd6\xc9\xb5\xdc\xab\xf4\x29\x42\x77\x39\x15\x22\x37\x4d\x45\x20\x03\x82\xdc\x15\x36\x10\xdd\xca\x7d\x00\xe0\x44\x0d\xcd\x81\x6a\xd9\x7e\x7f\x3e\x78\x03\x7b\x0c\x73\x78\xdf\x1c\x0b\x3f\xf6\xf5\x7c\x38\x9f\xaa\x13\xd0\xc1\xdf\x30\x08\x40\x70\x4c\xfd\x2e\xf3\x63\xb2\x43\xb3\x35\x1f\x8c\xae\x8c\x1f\x7b\x2e\xf0\xfd\x5c\x68\xcb\x99\xf8\xa3\xe3\x09\x69\xeb\x74\xf8\xd8\xf3\x38\xb6\xd3\x7d\x63\x14\xe6\xfb\x40\x78\xf6\xbc\x68\x6b\xe6\x3f\x1e\xa2\x3e\xc7\x15\xbd\x9b\x2b\xd9\x87\xdf\xc3\x25\xfe\x2d\x9b\xdd\xcf\x1b\x1d\xde\x44\x39\xc7\x0b\xbf\xdb\x8a\x84\xee\x78\x9d\xb9\xa8\x73\x98\x75\xbf\x65\xd0\x3b\xd9\xb1\x1d\xbb\xc1\x7c\xa5\x9c\x0b\x20\x42\xdf\xcb\x82\xb7\x46\x13\x65\xfb\x83\xd1\xfc\x71\xc2\xfd\x34\xa1\x7c\xed\x85\x67\xb8\xdd\x35\x78\x12\xd1\x9a\x28\x6b\xee\xf5\x9d\xab\xac\x10\xdc\xb2\x02\x28\x00\xe0\x37\x8c\xbf\x61\xfc\x3b\x41\x82\x6c\x59\x81\xdb\x59\xed\x67\x95\xd6\xc4\x1b\x1e\x72\xb1\x3b\x39\x62\xb4\x9d\xc5\xde\xce\x90\x82\xd3\xc7\x24\xaf\x92\xe7\x50\x6c\xf3\x89\x3b\xe8\xc3\xc7\x51\xa8\x33\x3b\x0c\x44\x7b\xc5\xd4\x1b\x8c\x24\x78\xe4\x73\x21\xdd\xbe\x7a\x7d\xfe\xde\x7c\xfb\xd5\x15\xfa\xe3\x65\x91\x44\xb4\xd8\x2c\xe0\x54\x85\xd7\x2b\x4c\x4b\x33\x9c\x6e\xd6\x33\xd1\x62\xbe\x51\x46\x86\x5e\xd7\x71\x32\x42\xa3\x7a\x52\xd3\xf5\x8a\x56\x49\x96\x72\x61\x52\xad\xa4\xd3\xe9\x92\xa6\x9f\x1a\xe9\x22\x13\xb4\x65\x12\x31\x0a\x8d\x64\x2a\x8b\xa2\x29\x1c\xd7\x8b\x24\x52\xcf\xc6\x73\x7a\x2c\x1b\x4f\x57\xf4\x42\x05\x25\x1b\xb8\x99\x8b\x97\x92\x79\xbd\x12\xd5\xf2\xe1\x52\x8d\x17\xa3\x3c\x5f\x47\xc9\x9b\x99\xe0\x2d\x93\xb0\x1e\x6f\xc6\x8c\x48\x54\x2f\x57\xea\xa9\x7c\x2c\x9a\xd6\x1a\xb9\x70\xb4\x90\x8b\x96\x9a\x5a\x55\x23\xb5\x66\xa2\x89\xa3\xcd\x58\x13\x17\x50\xa9\x9e\x21\x99\x24\xa7\xa9\x0c\x6b\xdc\xcc\x84\xec\x98\x44\xd3\x05\x8d\x34\x2a\x06\x42\xd5\x02\x89\xe6\x50\x24\x16\x8f\x85\x93\x0d\x1c\xcb\x6a\x71\x9c\xe4\xba\xa6\x67\x2a\x45\x8a\x63\x65\x5a\xd6\x52\x28\x11\x4e\x96\xa9\x4e\xea\x37\x33\xa1\x3b\x26\x8d\x52\x34\x97\x29\x36\x98\xd6\xc8\xd6\xf3\x85\x72\x99\xa5\x0b\x85\x7c\x3d\x96\xab\xea\x91\x5a\xaa\x5c\x28\x97\x9a\xa9\x6a\xad\x46\xb2\xb5\xb0\x51\x8d\xe4\xcb\x49\x6a\x94\xb3\xe1\xd8\xcd\x4c\xd8\x96\x49\xcc\xa0\xb8\x16\xd6\x52\x99\x7c\x05\x37\x33\x3a\x26\xd1\x52\x32\x5c\x4b\xf2\x64\x95\x65\x18\x8e\x46\xd2\x46\xa5\x5c\xab\xc4\x22\xf1\x52\xae\xc1\x0d\xa3\x98\xc1\xa5\x42\x26\x5f\xba\x99\x09\xdf\x79\x57\xb2\x50\x4f\x54\x63\x99\x42\x9c\x66\xca\x24\xaa\x87\xcb\xbc\xce\x79\xbe\xde\x68\xf2\x46\x55\x23\xe9\x64\x26\x1e\xab\x24\xa3\x89\x68\xb5\x16\xcd\x92\x0c\x29\x14\x19\xcf\x64\x9a\x37\x33\x11\x3b\x4d\x48\x29\x97\xd7\x70\xb5\x50\x8a\xf3\xa6\x81\xa3\x65\xad\x88\x0b\xb4\xa2\x97\x23\x39\x2d\x1d\x0b\xa3\x44\xb6\x5e\x4e\x1a\x3c\x97\x0b\x1b\x61\x3d\x93\x49\xc7\x9a\xdc\x28\x24\xe2\x37\x33\x91\x3b\x4d\xaa\x35\x9a\x8d\x1a\xcd\x78\x81\x17\x34\xbd\x5e\x0e\x27\xf2\xd5\x54\xb1\x1e\x8e\xc5\xf4\x4a\xbd\xde\x4c\x47\xf5\x4c\x9c\x54\x8b\x11\x94\xca\xf0\x1a\xca\x16\xd2\xb5\x38\xc7\x95\xc4\xcd\x4c\x20\xd8\x71\x49\x67\xd2\xf5\x42\x26\x12\x4f\x25\xf3\x79\x4c\x28\xad\xd5\x6b\x09\x1a\x8d\x45\x9a\xf5\xa2\xde\x88\x1b\x46\x22\x15\x6d\xe4\x0a\x95\x22\xa6\xd1\x42\x91\xd4\xaa\x25\x9c\x69\x66\xef\xe0\xb2\xc7\x7c\x2a\x1e\x37\x8a\x99\x64\x2e\xc9\xd2\x31\x1e\xcd\xd0\x7c\x8a\xd4\xab\xd1\x46\x34\xa7\x1b\x7a\x9c\x15\x1a\x61\x9e\x2e\x47\x0d\x1c\x2f\x24\x0b\xe9\x66\xb1\xdc\x68\xc4\x23\x54\xbb\xbd\xeb\xe1\x1e\xf4\x2c\xa1\xe3\x6c\xba\x52\x63\xe9\x86\xc1\xb5\x58\x3e\x4d\x78\x35\x92\xe4\x31\x42\x73\x24\x5d\x4b\xd6\x13\x19\x96\x4d\xa6\x8d\xb0\x96\xa2\xe9\x48\x49\x47\xb1\x48\xb1\xc1\x8b\xb7\x73\xd9\xa1\x3e\x92\xcf\xf0\x48\xbe\x52\xca\xd7\x0a\xc9\x48\x58\x8f\x34\x72\x2c\x97\x32\x1a\xcd\x74\x2a\x96\x2a\x54\x1a\xe9\x42\x3d\x59\x4e\x86\x63\x71\x4e\x2b\x5a\x35\x55\x6d\xd4\x92\xc9\xbc\x5e\x8c\xde\xce\x65\x07\xfb\x08\x2a\xa6\x1a\x65\x94\x0a\x57\xe2\x39\xa3\x9e\xc9\x96\xb2\xd9\x82\xa1\x45\xa3\x2c\x1f\xcd\x27\xd2\xb9\x70\xac\x54\x28\x1b\x19\x5e\x4e\xe8\x65\x54\x8a\x1b\xa8\x91\xa8\xc5\xc2\xc6\xed\x88\x84\x7b\xdc\xd7\x73\x71\x82\xcb\x89\x66\xb2\x86\x8b\x3a\x36\xb4\x7c\x25\x8c\x2a\xb4\x50\xa3\x91\x72\xd8\xa8\x27\x12\x8d\x34\x4e\xa7\xe2\xc9\x1a\x6e\x94\x59\xd1\xc8\x18\x59\x1c\x2d\x14\x2a\xb7\x73\x39\x00\xbf\x86\x39\xcd\x85\x1b\x06\x61\xf9\x58\x22\x8e\x6a\x89\xb0\x5e\x8c\x22\xc3\x68\x66\x79\x1e\x11\x16\x6b\x24\x93\xd1\x44\xad\x5c\x45\x86\xc6\x53\x49\x0d\x15\x2b\xc5\xec\x1d\xba\xf0\xfd\x40\x19\x36\x50\x58\x6b\x68\x99\x54\x59\x43\xd9\x4c\x8a\x1a\xb9\x7a\x9c\xe6\x52\xd5\x26\x2b\xf2\x7a\x2a\x6b\xe4\x13\xb1\x32\x42\x79\x9e\xae\x93\x58\xa9\x16\x2f\xf1\x78\x2c\x56\xb8\x9d\x8b\xd8\x8f\xf9\xcd\x44\x21\xd3\xa0\xb5\x52\xb2\x96\xa0\x8d\x7c\x33\xa7\x27\x28\x4a\x44\x33\xb4\x14\x4d\x93\x46\xa2\x52\xcb\xa5\xd3\xd5\x44\xb3\x94\x41\xf1\x02\x89\xa4\x50\x3a\x95\xd6\xd1\x1d\xbd\xbf\xc7\x7e\x32\x4a\x62\x28\x5a\x22\x34\x9a\x36\x74\x9d\x14\xc3\xc9\x32\xca\xc6\x9b\xe1\x74\xaa\x42\x0b\x61\x9e\xa4\x38\x83\xab\xf9\x02\xab\x69\x69\x56\xaf\x25\xf5\x92\xde\xcc\x14\x6f\x47\x25\xda\x63\x3f\xc2\xe3\x85\x46\x22\x9b\x65\x46\x1a\xf3\x64\xc6\x08\x37\x6a\xb4\x1c\xae\xe5\xe2\x91\x44\x22\x9e\xc8\x91\x54\x8e\x69\x46\x24\xda\xac\xa7\x50\xa4\x49\xf2\xf9\x7c\x1d\x55\xc2\xb7\xc7\x2f\xb4\xc3\x7e\x2c\x5a\x2d\x47\x12\x25\x4d\xab\xf0\x4c\xb6\x5e\xc9\x25\x73\xa5\x7a\x24\x9c\xad\xa7\x51\x99\xa4\x50\x26\x5f\xa8\xd7\x50\x89\x96\x8d\x6c\x26\x66\xa4\xc2\xf5\x18\xad\xc4\x92\xe1\x46\xfe\x76\x2e\x3b\xec\x87\x13\x14\x95\x6b\xac\x18\x8e\xb0\x72\x42\xcf\xe5\xcb\x59\x8c\x1a\x24\x87\x2b\xc5\x62\x56\xd7\xf5\x64\x41\x4b\x36\xc2\xa9\x86\x51\x60\xa5\x78\x9c\x35\xc3\x55\x23\x4e\x9b\xc5\x3b\x74\xd9\x47\x7c\xc2\xaa\x46\x26\x12\xcd\xa6\x50\x9d\xc5\xea\xd9\x3a\x0f\xa7\xb4\xaa\x11\xcf\x26\x71\x25\xcc\xeb\x11\x0d\xeb\x09\xbd\xc0\xf2\x9c\x24\x8b\x34\x5b\x4f\xe6\x12\xe5\x2a\x4a\x47\x6e\xe7\xb2\xc3\x7e\xac\x1e\x0f\x27\xd2\xd1\x52\x34\x45\xa2\x19\xd4\x48\x66\x58\xc3\xc8\x86\x59\x39\xa3\xd5\xe3\x46\x9d\x47\x72\x89\x6a\xae\x98\x8f\xe4\xb2\x29\xad\x92\x36\xd2\xb4\x51\xd4\xb3\xb9\xd4\x1d\x5c\x0e\xd8\x4f\x61\x5c\x89\x66\x8b\xe5\x68\x26\x87\xf4\x9c\x11\x29\xf1\x7a\x23\x62\x50\x4c\xb3\x59\xad\x1a\x4e\x66\x69\x23\xa2\x93\x78\x39\x1a\x21\xc9\x66\xb2\xcc\x9b\x61\x1a\xad\x66\x1e\xde\xfb\x8e\x54\xa0\xa4\xbd\xb5\x65\xfa\xf6\xfb\x08\xa7\x6f\x2c\x7d\x0d\x6c\x95\x39\x3c\x8b\xf0\xd6\xdc\xf6\xf5\x25\xfc\x77\xcf\x6c\xf7\xdb\xed\xc7\xf3\x5a\x7b\xa2\x1c\x6f\xd6\x32\xfb\xa3\x8e\x39\x9c\x0f\xc8\x76\x32\x5e\x29\xc5\x1e\x3e\x63\x30\x7f\xc9\x1d\xbd\xc1\xfd\xa3\x07\xf9\x97\xdc\xf1\x05\xee\x5a\xc5\x78\xf8\x8c\xb9\xd2\x4b\xee\xe4\x0d\xee\x9f\xab\x3b\x7d\xc3\xf2\x9f\xab\x3b\x7b\x83\xfb\x47\x07\x91\x97\xdc\xb7\x31\x77\x68\xce\xbc\x85\xda\x32\x7b\x38\xd9\xcd\xbd\xe7\x95\x84\x0f\x19\x17\x5e\x9c\x65\xf9\x1a\xe0\xb7\x0e\x0a\xe7\x1e\x49\x78\xef\xa8\xf0\xf8\x50\xc2\xd1\xb0\x80\x88\x84\x40\x40\xc0\x11\xa3\xbb\x6d\x6f\xb2\xc5\xcb\xbf\x7e\x1e\xaa\xe5\x56\xd2\x9f\xbf\x05\x9e\x77\xe1\x01\xf8\x9f\x4b\xb6\x3f\x4b\x99\x08\x88\x21\x96\x92\xc9\xa7\x0d\xf5\x7f\xfd\x3c\x9d\x99\x93\x99\x37\x6c\x3f\x2e\x4b\xfd\xfc\x2d\xf0\x33\x04\x00\xfc\x7e\x60\xf1\xf3\xcd\x3c\xd0\x29\x0f\xb4\xdf\xef\xff\xd7\xcf\xfb\x95\xee\x57\x94\xbf\x06\x7e\x7e\x3e\x45\xb6\x2d\xdd\xbb\xc7\xed\x1c\x5f\x69\x85\xbf\x06\xe0\x5e\xad\xfd\x3b\xa1\x3f\x7f\xdb\x2a\xfa\xf3\xbe\x43\x5a\x3d\xb5\xde\x72\x79\xef\x82\xc2\xed\x72\xe1\xad\x5c\x80\x42\x01\x39\x62\x1c\xef\xac\x8d\x5e\x59\xe2\xe3\xec\xf0\x8a\xdf\x59\xcb\x7f\x2c\x3f\xcc\x10\xc2\x08\x50\xcc\xf9\xa7\x79\xd3\x0b\x1e\x9f\xee\x4d\xaf\xb4\xba\xcd\x9b\xde\xb9\xa8\x73\xbb\x5c\x64\x2b\x17\x94\x48\x20\x2c\x80\x80\x9f\xee\x4d\xe8\x94\xdf\x27\x7b\xd3\x4b\x7e\xe8\xd3\xf5\x23\xa7\xfc\x3e\x59\xbf\x2d\x3f\xc4\x19\xc6\x88\x03\x2e\xe8\xa7\xa1\xe5\x05\x8f\x4f\x47\xcb\x2b\xad\x6e\x44\xcb\xfb\x56\x27\x6f\x97\x6b\xab\x3b\xc2\x18\x0b\x0c\x30\x11\xfb\x48\x47\xf6\xee\x34\x34\x07\x07\x55\x07\x0a\x6e\x2d\xb0\x3b\x56\xbf\xfd\x26\x17\x0b\x2f\x73\xe1\x3f\xff\xbc\x8f\x0d\x94\x80\x60\x8c\x19\x94\xf8\x46\x36\xe5\xd4\x46\xbf\x9f\x0d\xe1\x44\x60\x26\x84\xdc\x8f\xb4\x04\xbe\x62\x83\xee\xa4\x08\x08\xc5\x04\x40\x06\xf6\xa3\x09\x01\x9f\x23\xf8\x9e\x0d\x65\x8f\x82\xbf\x66\x83\x5e\xb0\xd1\xcb\x0d\x9c\x7f\x2f\x1b\xc9\x1f\xbb\xe1\x35\x9b\xc0\x0b\x36\x66\xdd\xd8\xa4\x12\xce\xc2\x89\x46\x36\x76\x22\xde\x6d\xd6\x73\x9d\xfb\x58\x02\x06\xa9\x20\x98\x60\xf0\x79\x70\x7e\xc1\xe3\xd3\xe1\xfc\x4a\xab\x1b\xe1\xfc\xbe\x7d\x80\x3b\x2d\x01\x05\xc3\x84\x71\x00\xe4\xf9\xe0\x40\x11\xe5\x8c\xb3\xdf\x25\xc5\x0c\x48\xf4\xfd\xd6\x60\xa7\x5c\xd1\x6b\xae\x58\x40\x42\xd0\xae\x0b\x20\x81\xf2\x43\x98\x42\xc9\x29\x13\x44\x4a\x0e\xf7\xbe\xcc\x77\x4c\xcf\xfe\x6a\xc4\xce\xfe\xef\xdc\x22\xb9\xcb\xfe\x7b\xa1\x28\xc0\xe2\x60\xff\xb7\x84\x7a\xe7\x5e\xda\x9d\x96\xc2\x88\x63\x8a\x11\x81\x6f\xcd\x3f\xd1\x73\xbe\xf4\x2e\x24\xbe\x64\x75\x06\x89\xe7\x18\x7c\x8c\x37\x1c\x33\xbe\x0d\x90\x9f\xee\x10\x5b\x6b\x6f\x43\x91\xa0\x8c\x42\x04\x9f\x4e\x75\x1f\x1b\x44\x4a\xf9\xbb\xdc\xfe\x7d\xd0\xf4\xf0\x25\xc3\x33\x58\xfc\x50\x86\xaf\x34\xdc\x43\xf1\xe1\x5f\xf7\x51\x20\x4c\x60\x2a\xb9\x40\x9f\x16\x22\x5e\xf2\xf8\xf4\x10\xf1\x4a\xab\x1b\xb3\xed\xf7\x6d\xb0\xde\x2e\x97\xd8\xca\x05\xb0\x10\x0c\x03\x8a\x0e\x21\x82\xec\xe4\xda\x9d\x7f\xf3\x27\x7b\x39\xde\xb7\x3d\xfa\x6c\x37\xdb\x77\x76\x76\xd3\x2a\xc6\x6b\x63\x9e\xae\xab\x3d\xd7\xd8\xdf\x80\xdb\x83\xf3\x7d\xcb\x7b\xf7\x99\x82\x33\x20\x31\x63\x18\xe1\xc3\xc2\x03\xfe\x3c\x53\x54\x4a\xb1\xff\x02\x53\x70\xfc\xe8\x15\x9f\x68\x8a\xff\x60\xaf\xd8\x2a\xcf\x21\x97\x82\x49\x2a\xf1\x3e\x5c\xa2\x3d\x70\x77\x97\x23\x77\x23\xe8\x36\x69\xe2\x08\x60\x26\xe8\xef\x84\x73\x2a\x00\xff\xaf\xea\xef\x27\x25\x39\x00\xe0\xd1\xf5\xdf\xa5\xe4\x7f\x70\x4f\x6e\x9d\x9a\x71\x0a\x30\x47\x82\x91\x7d\xf0\x65\xfb\x41\x7f\x3e\xeb\xb4\x26\x6a\x3c\xf7\x26\xca\x69\xb9\x7d\xb3\xfd\xf3\xee\x62\xb1\xda\xca\xb9\x2f\x5b\xf8\xf6\xee\xfc\xe1\x51\xe1\x5d\xd6\x65\x18\x01\xc1\x19\xc4\xe4\xf3\x22\xda\x0b\x1e\x9f\x1e\xd1\x5e\x69\x75\x63\x44\x7b\xe7\x98\x71\x5f\x37\xef\xe5\xa2\xe4\xd0\xcd\x9f\x68\xed\x3d\x8f\x4f\xb7\xf6\x2b\xad\x6e\x9c\xd1\x7e\x36\xa8\xb6\x32\x40\x2a\x24\xc4\x5c\x12\x40\x0e\xa1\x02\xbe\x1c\x3a\xce\xd8\xe1\xfb\x07\xc5\x4f\x4f\x94\xf6\xaa\x11\x06\x85\x40\x8c\xd3\xc3\xa8\x88\x5e\xaa\x06\xcf\x75\xf2\x7f\x8d\x72\x00\x23\x2c\xa8\x24\x94\xff\xf5\x94\x23\x0c\x20\x21\x24\x82\x0c\xfe\x5b\x82\xf6\x0f\xd2\x12\x72\x8c\x25\x22\x82\x7d\x5e\x5c\x79\xc1\xe3\xf3\xf7\x25\x5f\xa9\x75\x63\x60\x79\xdf\xd9\xca\x3b\x04\xdb\xfa\x11\xe6\x04\x0b\x49\x39\x3d\xec\x03\x5f\x99\x40\xec\xde\xcf\xbd\x38\x83\xd8\x95\xbe\x87\x37\x83\xec\xd0\xd7\x10\xbd\x34\x0a\x3a\x63\x94\xf7\x1d\x05\x7d\x97\x51\x0e\x82\x6d\x3d\x66\x3f\xfe\x9f\xc8\x12\x61\x69\x5c\xcb\x67\x33\x8d\xa2\xc6\x32\xd5\x58\x53\x0b\x93\x74\x2c\x17\x2f\x97\xf3\x7a\xa5\x51\xc0\x85\x4a\x52\x8f\xe9\x4d\xa3\x96\xca\x84\x59\xba\x58\x4b\xe5\xd2\xcd\x70\x39\xae\xdd\x2b\x0b\x86\x04\x4b\x09\xd0\x61\xeb\xf8\x3f\xc7\x48\xc7\x82\xa1\xd7\x82\xd1\xd7\x82\xfd\x18\x8b\x21\x80\xa8\x04\x42\xe0\xc3\xf6\xda\xbf\x7d\x85\xf2\x48\xaa\xed\x10\x70\xd3\x4c\xfd\x5d\xc4\x19\x3d\xec\xbf\xbf\x20\xfe\x3d\x53\xfd\x67\xea\x10\x00\xf6\x9f\xe6\x82\x07\xc1\x08\x3f\x0c\x5e\xfb\x75\x9e\xbe\xbf\x6c\x3d\xfd\xc4\xf0\xcf\xdf\xb6\x21\xe4\xe7\x81\x72\x5e\x7c\xb7\x15\x79\xf7\x42\xee\x8b\x2f\xdf\xc5\x5d\x3c\x86\x2a\xba\xe3\x7e\xf4\xf3\xcb\x5b\x4b\xa8\x95\x39\x18\xf5\xd5\xef\xb6\x3f\x78\x97\x72\x10\xc9\x43\xbc\xff\x0f\xb3\xfa\x41\x30\x74\x53\x2c\xfb\x31\xc0\x87\x54\x32\x02\x11\x04\xe2\xd3\xce\x34\xbd\xe4\xf1\xf9\x73\x87\x57\x6a\xdd\x38\x77\xf8\x74\x47\xd8\xf5\x3b\xc7\x9c\x40\xc1\x88\xfc\xb4\x53\x3f\x2f\x79\x7c\xbe\xbd\x5f\xb1\xbc\xcd\xde\xef\xbc\x3b\x72\x87\x60\x64\x2b\x07\x06\x5c\x22\x28\xd1\x61\xa7\x1e\xef\x8d\xb1\x7f\x8c\x6f\x2f\xc7\xfb\x6e\x97\x6c\x0d\xf7\xf8\x50\xc3\xcf\xdf\xb6\x3a\xff\x3c\xf5\xfb\x4e\xeb\x78\x57\xeb\xd8\xc8\x96\x3f\x6f\x77\x66\x17\x8b\xf7\x6d\xcf\xa5\x1d\x47\x25\xd7\x72\x8f\x47\xfa\xe7\xfa\xf2\x25\x95\xe3\xfc\xe4\x7d\xc7\xa4\xef\xe8\x03\x7c\xda\x07\xe8\x6c\x1f\xbc\x53\x8e\x4f\xeb\x83\xd7\x06\x7c\x61\xdf\x93\x2e\x3a\x6b\xfb\x37\x3b\xe9\x47\xf7\x83\x24\x44\x48\x24\x08\x7b\x3c\x05\xf0\xa3\x93\xe1\x1f\xa2\x24\x80\x92\x60\xc8\xf1\x61\xff\xff\x13\xc6\xd7\x17\x2c\x3e\x7f\x78\x3d\x55\xea\xc6\xd1\xf5\x9d\xa3\xda\x5d\xa3\xeb\x5e\x2e\x04\x09\xf8\xb4\xc9\xc3\x0b\x16\x9f\x6f\xec\x53\xa5\x6e\x34\xf6\xa7\x7b\x36\xff\x1a\xd8\xff\xec\x25\x05\xe0\x70\x5e\xe3\xf5\x09\xcf\x2b\x0b\x75\xef\xdf\x92\x79\xe7\x7d\x8e\x3b\x74\x63\x27\xba\x9d\xef\xe5\x0f\xec\xe4\x53\x86\xf8\x5c\x48\x7a\xaf\xde\x2f\x43\x12\x7a\x1d\x92\x4e\x74\x79\x15\x93\x4e\xca\xef\x0f\x4a\x87\xbe\xfe\xee\xa0\xf4\xf9\x3d\x4f\x4f\x3a\x82\x9c\xeb\x88\x77\xde\x65\xfd\xcc\x8e\x38\xb1\xf4\x67\xce\xd0\x3e\xbf\x13\xb6\x43\x0b\x64\x80\x60\x81\x38\x3a\x7f\x38\x1e\xfd\x37\x0f\x2d\xc7\xba\xdd\x3a\xb4\x7c\xff\x64\xe7\xc7\xeb\xf6\x89\xa3\x18\xbc\x1f\x3c\xe8\x4d\xf0\xfc\x80\xf4\xe6\xc7\x8c\x60\xc7\x9d\xf0\x89\x23\xd8\x99\x4e\x40\x9f\x1d\x4a\x3e\x2a\xbf\xf9\xf1\x68\xa0\x3f\x34\xa6\xbf\xd5\x11\x97\xd1\xf0\x97\x8c\xe9\xc7\x1d\xc1\x7e\x68\x4c\x7f\x7f\x47\xfc\xa5\x62\x3a\xfb\x1a\xe0\x1c\x03\x49\x20\x25\x87\xe3\xb3\x77\xa5\x0b\xff\xc9\x71\x8f\x9e\xe8\xf6\x17\x8b\xe9\x1c\x03\x48\x08\x11\x10\xfd\x7b\x56\x69\x7e\xc8\x84\x73\xaf\x24\x45\xe8\xd1\x39\x7f\xf0\x39\xc3\x1f\xd2\x93\x4c\x70\x28\x89\x00\x02\x7f\xda\x52\xd4\x0b\x16\x9f\xbf\x3a\x72\xaa\xd4\xad\x37\x2a\xde\x37\xd8\xdf\xe5\x51\x07\xb9\x88\x44\x9f\xb6\x14\xf5\x82\xc5\xe7\x1b\xfb\x54\xa9\x5b\xaf\x87\xbe\xeb\x4d\xa6\xfb\xc6\xdf\x83\x5c\x12\x7c\xde\xd5\x8c\x17\x2c\x3e\xdf\xd8\xa7\x4a\xdd\x68\xec\x4f\x1f\x46\xc4\xd7\x00\x23\x04\x11\x0a\x31\xc5\x97\xd6\xfd\x3e\x23\xd6\xbd\xf3\x29\x93\x3b\x54\x93\x27\xaa\xdd\x78\x89\xfc\xbf\x41\xb5\x6d\xaf\x01\x88\x24\x25\x0c\x91\xcf\x7f\x6f\x60\x67\xca\x63\x7e\x9f\x7c\x1f\xff\x59\x3f\x0a\xf0\xbf\xe9\x3a\xc4\x0f\xf1\x4f\x4a\x05\x26\x94\x0b\xf9\x79\x07\xf6\x5f\xb0\xf8\xfc\x71\xee\x54\xa9\x5b\x6f\xa0\xfd\x00\xc4\xec\xe5\x12\x18\x7c\xde\x79\xfd\x17\x2c\x3e\xdf\xd8\xa7\x4a\xdd\xfa\x1c\xca\xbb\xde\x3b\xbc\xc3\x10\xe0\x6b\x80\x42\x8a\x25\x83\x90\x91\xb7\xa6\x4b\xf4\x3d\xa6\x86\x27\x1c\xce\xd8\x9a\x7e\xe4\x03\x28\xa7\x1a\xdd\xe8\xd6\xef\x7b\x8d\xf1\x3e\x3b\x10\x8e\x08\x61\x84\x60\xfa\x69\x59\xc0\x0b\x16\x9f\xee\xd6\xaf\x94\xba\x31\x0b\x78\xdf\xa3\x94\xf7\x19\x02\x49\x22\x19\xe7\x80\xde\x3e\x55\x7a\xb7\x19\x4e\xf9\x7d\xfe\x23\x3f\xcf\xec\xc4\x0f\x56\x4f\x7c\xbe\x7a\x5b\xfa\x82\x51\xc2\x81\xe4\xec\xd3\x22\xc0\x0b\x16\x9f\x0f\x95\x53\x8e\x37\x46\x80\xf7\xbd\xac\x7a\x9f\x21\x08\xa6\x92\x13\x44\xd8\x85\xe5\xc1\x0f\xb4\x02\x3e\x61\x77\xce\xee\x1f\x0a\x94\x03\x37\x46\xd9\x85\xc9\xf7\xa7\x28\xb7\x67\xf7\x83\x94\xa3\x80\x5d\x1a\xe4\x3e\x43\xb9\x03\xbb\x1f\xa5\x1c\x79\xba\x6a\xf7\x43\x94\xdb\xb3\xfb\x64\xe5\xb6\xec\x00\x60\xdb\x5c\x08\x7e\xde\x03\x92\x2f\x58\x7c\xfe\x00\x77\xaa\xd4\x8d\x03\xdc\xfb\x1e\x75\xbe\x43\x2e\xf2\x35\x80\x28\x67\x52\x00\x2e\x6e\xbf\x81\xf1\xce\x67\xa0\xbf\x43\xae\x33\x77\x80\xce\xcd\x9d\xb0\xc6\x93\x99\x9c\xa1\x97\x59\x32\x11\x49\x24\x23\x65\x96\x62\x69\x8d\xe8\xa8\x44\x6a\x34\xd3\x44\x84\x95\x13\x69\x92\x29\x96\xea\x69\x54\x20\x91\x7a\xb4\x52\x28\xe6\xee\x58\xd4\xdb\xc9\xb5\x7b\x26\x8d\x90\x4b\x37\x56\xce\xc9\xf5\x43\xec\x75\x2c\xd7\x6d\x57\x27\x7e\xa4\xbd\xc4\xf5\x8b\x34\xe8\xe3\x2f\xd2\x6c\x99\x1f\x5e\x6a\xc0\x48\x7c\xde\xe5\xf6\x63\x16\x9f\x3f\x92\x9c\x2a\x75\x63\x56\xf1\xe9\x1e\xb8\x9d\x1e\x21\x21\x88\x04\x54\x7e\xde\xdb\x93\x2f\x58\x7c\xbe\xb1\x4f\x95\xba\x75\xb9\xfb\x5d\xef\xd7\xef\xe5\x7a\xe3\x55\xe8\xc3\xaf\x94\x7d\xc8\xab\xd0\x07\x5a\xcf\x2f\x81\xc1\xaf\x81\x07\x4e\x6c\xe6\xb8\x0e\x16\x36\xb3\x6c\x62\x41\xe0\x28\xc7\xb1\x14\x72\x1d\x87\x9a\x90\x60\x53\x40\xce\x28\x44\x58\x31\x65\x31\x8c\x88\xe3\x2a\x17\x38\xb6\x43\x4c\x4a\x5d\x0b\x3e\x7c\x0d\x3c\xb8\xb6\x20\xd8\x41\x90\x60\x9b\x33\xcb\x41\x52\x59\xd8\x82\xae\xeb\x38\x36\x76\x88\x70\x18\xb0\xb9\x09\x1d\xdb\x35\x21\x36\x1d\x21\xa0\x84\x8e\x09\x30\x07\x12\xb9\x10\x39\x87\xdf\x61\x86\x8f\xbf\xec\x05\xd8\x6f\x00\x07\x20\xfb\x86\xd9\x37\xc4\x1f\x5e\x7f\x4d\xbf\x61\xfc\xfb\xee\x6d\x66\xf4\x66\x29\x62\x50\x4a\x0c\x00\x05\x94\x7d\x0d\xc0\xed\xff\x01\x00\x50\x02\x8e\x9e\x7e\x07\x1a\x6c\xa3\x35\xe1\x10\xed\x2e\x7b\x6d\xff\x09\x9f\x4b\xe0\xd3\x87\xad\x80\xe1\x70\x38\x1c\x0d\xad\xb5\x42\x29\x1e\x5b\xa1\x45\x69\x38\xc9\xaf\x42\x12\xc7\x60\x0a\xb6\x57\x2c\x69\x07\x3b\xf9\x99\x17\xe9\x39\x7e\xcc\x4e\x67\x57\xd9\xe2\x72\x68\xf9\xb1\xe6\x3a\xdf\xb6\xd7\xae\x45\x7a\x8a\x2e\x53\xb8\xe4\x4f\xab\x4d\xd6\x28\xce\x57\xa9\xa1\x8e\x2a\xcc\x89\x38\x44\x76\x1a\x5b\xd2\xe1\x7a\xa1\x9a\xf3\x96\xe1\xa7\x3f\x7f\xaa\x75\x16\x46\x39\xba\x30\x9d\x54\x28\x2d\x27\x41\xd1\x8b\x04\xfb\x8d\x30\xcb\x8f\x3a\xe5\x6e\x32\x19\xa2\x3e\x0a\x7a\xbd\x7e\x8a\x14\xc8\x64\x51\x48\x86\x57\xd8\x9c\x7a\xd0\x27\x3c\x57\x80\x68\xa2\x47\x8b\xa5\x54\xa5\x1a\xeb\xc2\xea\xc4\x99\x0b\x18\x9c\xe5\xb3\x31\x77\x4b\x3f\x06\x74\x52\x2b\x8e\x6a\x7a\x37\x73\x60\x15\x01\x05\x83\xee\x3e\x15\x9f\xd8\x27\xb6\xff\x69\x86\xeb\x90\x14\xb7\x4d\xd2\xe1\x0c\x43\x63\xb7\x9b\xa8\xc7\xd6\xdd\x20\x1c\xd5\xcb\xd9\xb0\x9a\xb2\x50\xa8\xe0\x78\xc9\x5c\xaa\x4f\xdb\xc9\x7c\xaf\xdc\x55\xf5\x7c\x68\x09\xc2\xff\x09\x7f\x4f\x3f\xf1\xad\x57\xb2\xd9\x0b\xc3\xc0\x2b\x5c\x80\x8f\xf1\xe9\x07\x41\x15\x47\x8c\x11\xdb\x81\x02\x53\x84\x18\x12\x8c\xb9\x80\x62\x4a\x09\x80\x98\x21\xcb\x14\xb6\x32\x99\x89\x5c\xc2\x15\xe2\x90\x11\x0e\x4d\x4b\x00\x87\x9b\x02\x01\x71\x0d\x17\xec\xa2\xe7\x63\x4a\x10\x7c\xb3\xf4\x30\xdd\xc2\x9c\x6f\xd5\xbd\x8e\x0b\x78\x23\x2e\x48\x7d\x98\x1e\x94\xf5\x44\xac\xe2\x35\xfc\xe6\x22\x52\xae\x56\xc2\xe5\xc6\x64\x9c\x63\x03\x7f\x61\x04\xd3\xab\x66\x32\x31\x69\xeb\xca\x4f\xa5\xa8\x70\xab\x8b\xfe\xa4\xdc\xb1\xb3\x53\xa3\xd3\x0c\xe5\x6a\x9d\x5c\xce\x0d\x55\x1a\x13\x94\xdf\xf4\x8c\x5e\x39\x13\x6f\x34\x63\x89\x22\x55\x7b\x30\xec\x70\xd1\x7e\xee\xd7\x66\x04\xd5\x79\xdf\x8e\x5a\x9c\xa3\x7e\x81\x17\xfb\xb3\xd4\xd2\xe5\x61\x37\xa8\x95\xbc\x69\x66\xea\xc7\x47\x15\x68\x47\x9a\x8b\x92\xcd\xed\x8e\x15\xc7\x85\x8e\xaa\x17\x82\x1b\x1e\x9c\x4d\xd3\xd4\xa2\x89\xc6\xb4\xa6\x99\x6b\x16\xf3\x58\xb4\xd7\xeb\x99\x4e\x7a\x10\xef\xe1\x2d\xe1\xd8\xf2\x0c\x2e\x8a\xd5\xdd\xa7\xbf\x39\x2e\xa8\xfc\x18\x9f\x7e\x00\x4a\x42\xc6\x90\xc3\xa0\x65\x71\x0b\x09\xd7\x74\x29\xa7\x96\x34\x31\x05\x94\x33\xd7\x26\xc0\x85\x4c\x61\x81\x20\xe7\x18\x02\xc9\x08\x96\xc4\xb2\x10\x72\x14\xa3\xc2\xba\x86\x0b\x7a\xd1\xf3\x09\x03\xec\x7a\x29\xdb\xe1\x02\x13\x80\x01\x07\x84\x91\xb7\x70\x01\x6e\xc4\xc5\x92\x19\x4d\x0f\x76\xe6\x78\xea\x07\x17\x55\x38\x37\xf5\x62\x15\x85\xb4\xd8\xca\xea\xb6\x3b\xce\x46\x4b\x37\x63\xfd\xec\xd4\xc3\x83\x5a\x36\x98\x8a\x0e\x71\x24\x5b\xac\x1b\x53\xee\xf6\xc9\xd4\xab\xc5\xa3\xa8\xef\xc4\x54\x90\x43\xc7\x6d\x06\xf3\x33\x56\xda\xcc\x8d\x8c\xe5\xef\xfb\x71\x87\x8b\x67\xbf\x0c\xf7\xf5\xdc\x32\x12\xab\x68\xe3\x99\xa7\x95\x07\x95\xa0\x39\xef\xf7\x72\x93\xd8\xbc\x3a\x8b\xb8\x6e\x56\x4c\xab\x6a\x3c\x00\xab\x41\x70\x1d\xdf\xcc\x92\x6e\x97\xd6\x45\x34\x5b\xf5\x4b\xca\x40\xed\x91\x08\x47\x7d\x6d\x9d\x52\xa5\x99\x4e\xf2\x74\x32\xe3\xe3\x52\xc9\x5c\xad\x3a\xf3\x5d\xbc\x98\x9e\xc1\x45\x7e\xb5\xfb\xf4\x77\xc7\x85\xf8\x18\x9f\x7e\x20\x2e\x73\xa4\x69\x0a\x17\xd8\xc8\x04\x96\xc5\x19\x42\x10\x23\x88\x21\xb2\x00\x21\x92\x23\xa0\x00\xe1\x96\x6d\x13\x6e\x0a\x87\x70\x85\x85\xa0\x0c\x41\x2c\x99\xa3\x30\xba\x86\x0b\x72\xd1\xf3\x29\x47\xf4\xf2\x3c\xea\xb1\xf4\xf1\xf7\x43\x30\x64\xe2\x0d\x5c\x00\x79\x23\x2e\x80\x9c\x0d\xc6\xdd\xe5\x72\x1c\xe5\x8e\x97\x2a\xa7\xca\xda\x24\xa2\xf5\xd7\xb1\xb6\xc1\x37\x9a\xf2\x61\x92\x90\x4e\x2d\x55\xee\xcf\xc8\x9a\xf6\x4d\x53\xad\x9a\x1e\x8e\x28\x3f\x6d\x45\x1a\x19\x2d\x59\x35\xcc\x7a\x31\xb2\x69\x6e\xea\xb1\xee\xc4\xdb\x0c\x22\x4d\x33\x81\x44\x6d\x0f\x8c\x1d\x2e\x8e\xfa\x35\x91\x73\x8b\x91\x78\xa8\x31\x6e\x28\x47\xab\xe8\xc3\xe2\xdc\xeb\x6f\xe6\xbd\x4d\x36\x5d\x50\xd5\x89\x21\x53\x6c\x8c\x2d\x53\x4f\x08\x3c\x14\x3d\xa7\x66\x14\xc6\x86\xeb\xb0\x69\x2f\x5f\x76\xd2\x1d\xdc\x5e\xc2\x68\x76\x1d\x6e\xba\x7d\x90\x99\x8e\x16\xca\xec\x85\xea\x95\xc8\x64\x4b\x38\xe6\x9f\xc1\x85\xae\xef\x3e\xfd\xdd\x71\xc1\x3f\xc6\xa7\x1f\x08\x91\x04\x9b\xa6\xcd\x80\xcb\x31\x17\x08\xd9\x96\x25\x94\x03\xa4\x63\x3a\xd8\xb4\x5d\x97\x01\x57\x0a\x08\x1d\x4b\xda\x36\x65\xca\xdd\xa6\x2f\x0c\x08\xa4\x1c\x0e\x5d\xeb\x6a\x7e\x81\x2f\x7a\x3e\x13\x84\x5c\x2f\x25\x0f\xcf\xbf\x13\x43\x05\x47\x6f\xe1\x42\xdc\x8a\x8b\x52\x25\x3f\x5e\xb5\xe5\x46\x45\xb3\xd9\x79\x1e\xa4\xd1\x2c\x3f\x0d\xa1\x18\x6d\x1b\x88\x6e\xe2\xd6\x82\x2c\x60\xbb\x3d\x87\xab\xe0\xb2\xd4\xd4\xe6\xaa\x5a\x1c\x55\x27\x4e\x9d\xf8\xc1\x4c\x6e\xce\x68\x93\x85\xc7\x05\xad\xd8\xc6\x9d\x58\x3b\x97\xa8\x57\x37\x35\xc7\x6d\x93\xe7\xfc\xa2\x73\x94\x5f\x40\x32\x8d\xa7\x8c\x79\xb7\xb6\x6c\xcb\xcc\xa8\x86\x57\x76\xa1\x1c\x09\x27\xd4\x3c\xc2\xa2\xd3\x61\x29\x57\x1e\x15\x44\xa9\x5b\x9a\x3a\xd2\xef\xca\xbe\x28\x86\xac\x3c\x14\xb5\x91\x4a\xae\xf2\xb0\xdc\xc9\x94\x13\x56\x78\x96\x1a\x50\x23\x4a\xd6\xe3\x59\x9d\x64\xb2\xa6\x91\x0c\x6d\xfd\x3e\xd6\x3b\x83\x8b\xec\x68\xf7\xe9\xef\x8e\x0b\xf6\x31\x3e\xfd\x20\x5d\xc5\x84\xe0\x90\x58\x26\x61\xc8\xb2\x90\x65\x3a\x16\x45\xc8\x44\xc2\x25\x98\x32\x2e\x6c\x1b\x9b\x0e\x16\xd8\xb1\x89\xe9\x3a\x12\x9a\xc2\x86\x50\x61\x6a\x62\x87\x63\x7a\x0d\x17\x97\x23\x82\x00\x44\x5e\x8e\x26\xdb\x52\xfa\xf0\xf4\xbb\x41\x4c\x50\xfe\x56\xde\x0d\xf8\x8d\xb8\xa0\xa1\x81\x97\x8c\x67\x47\x89\x0c\xcf\x30\x04\x53\xe3\x4c\xa1\x08\x9b\x64\x13\x9b\x94\xdb\x72\x95\x09\x35\x13\xfe\xd2\x20\xd0\x97\x36\x0c\xbb\x93\xb9\x06\x53\xba\xad\x07\x4d\x63\xd1\x0b\xf7\x73\x05\x1b\x21\xa7\xdc\x6e\xb7\x3d\x97\x2d\xfb\x7e\x6e\x56\x24\xbc\x9b\x1e\x1b\xa9\x5d\x3f\xee\x70\x71\x94\x5f\xcc\x9d\x45\x2a\x63\x39\xf1\x62\x9e\xd9\xc3\x71\xa4\xef\x86\x8b\x60\xbc\xf4\x16\xa2\x1c\xb2\xfc\x65\xa8\x56\x28\xa7\xc2\xba\x1f\xd2\x0c\x43\x1b\x17\x49\x74\x69\xaa\x64\x33\x3e\x08\x82\x79\xc2\x6f\x5a\x83\x86\xe3\x47\x96\x61\x73\x10\xa7\x0b\x08\xb4\xc1\xb0\xea\x92\xf9\x2a\xc9\xb6\xf4\x63\xed\x33\xb8\xc8\xc4\x77\x9f\xfe\xee\xb8\xa0\x1f\xe3\xd3\x0f\x96\x90\xc0\x76\x1d\x8e\x11\x03\x02\x9b\x0e\xe5\xd2\x84\x14\x32\x26\x11\x44\x2e\x85\x88\x63\x1b\x08\xa0\x90\xc5\xb8\x89\x19\x23\xca\xe2\xb6\x65\x5b\xd2\x85\x9c\x43\x72\x35\x5e\x5c\xce\xac\x25\x22\xec\x7a\xe9\x6e\x1e\x75\xf8\x25\x28\x88\xc4\x5b\x79\x37\x60\x37\xe2\x82\x7b\xc5\x8d\xb4\xd7\x8d\x54\x7e\x56\xa5\x7e\x35\x3e\xe8\x75\xb2\x50\x1b\x16\xc2\xed\x7c\x06\xa9\x6e\xb3\xc7\xf0\x5a\xcc\xdd\x38\x8e\x87\x13\x9a\x4a\x68\x32\x82\x67\x7d\xee\xcb\xa8\x9b\x99\x15\xaa\x39\x12\x53\x35\xab\xe2\x86\x22\x3e\x96\x76\x2c\x59\x9e\x68\x29\x73\x68\x1f\xc5\x8b\xa3\xfc\x22\x99\x9f\x83\x88\x11\x44\xb4\x1c\x5b\xdb\x0d\xee\xd8\x7a\x69\x5d\xb5\x7b\x70\xb8\x6e\x46\xa2\xbd\x70\x24\xde\xac\x2f\xbb\x3d\xcf\xa6\xa8\x44\x0b\x08\x35\x07\x95\x60\xbb\x5b\x88\xa5\xba\x9d\x70\xad\xdd\x8c\xd4\x36\xcd\x26\x58\x1a\x1d\xbe\xce\x1b\x13\x39\xf4\xba\xa3\x08\x5e\xd6\x76\xf9\x85\x7d\x06\x17\xa9\xce\xee\xd3\xdf\x1d\x17\xe4\x63\x7c\xfa\x81\x08\x46\xa8\xe9\x08\x82\x81\xa2\x92\x22\x4a\xb1\xed\x30\x49\x99\x34\x29\x87\xd0\x32\x6d\x89\x09\x83\x16\xb4\xa5\x0d\x30\xb0\x18\xb0\x00\x43\x2e\x11\x14\x5b\xcc\x82\xe4\xe1\x69\xef\xf9\x35\x2e\xc0\x25\xcf\x27\x80\x0a\x78\x31\x9a\x3c\x95\x3e\xfe\x72\x16\x96\xe2\xad\xbc\x1b\xd0\x5b\xe7\x51\x9d\x5e\x6d\xd6\x89\xc5\xfa\xfd\x52\xb5\xbc\xa9\xf5\x6b\x83\xbe\x6d\xcc\xa7\x3d\xd0\xb0\x92\xe9\x65\x2c\x8a\xa2\xcb\xc6\xa2\x14\xcf\xa3\x69\xc5\x09\x6f\x46\x83\x26\xa9\x0e\xbc\x74\x38\x91\xea\x0c\x61\x54\x44\x19\x5d\x87\x7b\x83\x59\xc4\x8e\xf6\xe2\xf5\x64\x6c\xd9\x2b\x17\xfc\x46\xef\x79\x3d\xaa\x73\xd4\xaf\x6e\xbd\xea\x16\x4a\xb2\x1b\x19\x77\xca\xee\x86\x64\xbd\x45\xa3\x51\x90\xd6\x6c\x38\x0f\x8e\x97\x6e\x68\x3c\xaa\x36\xb2\x3c\xd9\xb6\xc2\x39\x44\xf3\x4e\x36\x49\xb2\xf5\xf9\x72\xa8\xcb\xd8\x68\x9e\xce\xf7\x44\x44\xb3\x49\xca\xb3\xbd\xae\xd1\x0d\x4f\x96\x0d\xcf\xae\xe2\x1e\x59\xed\xe6\x51\x8d\x33\xb8\x48\xc8\xdd\xa7\xbf\x3b\x2e\xf0\xc7\xf8\xf4\x83\xe5\x70\x8b\x20\xe9\x58\x8e\x70\x85\x72\x1d\x68\x51\xa6\x1c\x0e\x90\xe5\x42\x81\x15\xe1\x18\x43\xaa\x90\x0b\x08\x42\x8e\x45\xa9\x94\x94\x08\x9b\x00\x62\x2b\x75\x58\x36\xba\x14\x2f\xa0\xbc\xe8\xf9\x08\x20\x29\xde\x2c\x3d\xfc\x16\x1a\x63\x4c\xbc\x99\x77\xe3\x5b\xe3\x05\xe4\xc5\x11\x92\x5d\xc2\x65\x02\x5a\x33\x3b\xba\x58\xb5\x83\xc6\x26\x57\x25\x8b\x48\x34\x6b\x55\x9b\xfd\x4a\x57\x8b\xe4\xf8\x20\x32\x88\x2d\x0c\x0f\x93\x39\x35\xda\x5a\x38\xe6\x59\x23\x3b\x4f\x6c\x9a\x8f\x58\xd9\x14\x4d\xc6\x6b\x2b\x38\xdb\xc0\x7c\x64\xb9\xe2\xa9\xdc\x73\xbc\x68\x1f\xe5\x17\x0d\x01\xcc\xe9\xca\x4f\x56\x53\x0e\x07\xab\x9e\xa4\xd9\xce\xd4\xd0\x7b\x1e\x9e\x97\x1a\x9d\x76\x7a\xb2\xc8\x8d\x36\xac\xa8\x30\x5d\x16\x59\x4e\xae\x83\xa3\xd0\x68\xa6\x37\xd9\x26\x82\xc6\x1e\x1b\x8d\x97\xc9\xf8\x9a\xba\x21\x27\xd7\xc7\x24\x0e\x47\x2b\x77\xd9\x5e\x44\x9c\x5d\xbc\xa8\x9c\xc1\x45\x0c\xee\x3e\xfd\xdd\x71\x81\x3e\xc6\xa7\x1f\x24\xa0\x98\x60\x0a\x5c\xec\x2a\x13\x98\xcc\xa4\x54\x3a\x0a\x01\xce\x24\x55\x48\x20\x25\xa4\x90\x40\x52\x42\x04\xc2\xa6\x4d\x6d\x0e\x00\x70\x39\x33\x2d\xd3\xb1\x81\x50\xd7\x70\x71\xd9\xf3\x31\xe0\xe0\xe2\x3c\xea\xa9\x74\xff\x5b\x7c\x48\x4a\x2c\xdf\xcc\xbb\x6f\xdd\xd7\xa3\x91\x72\x11\xc6\x36\xa1\x71\x74\x30\xaa\x0e\x55\x2a\x69\x56\x89\x9f\xf5\x07\xe9\x68\xd5\x48\xa5\xd8\xca\xb6\xc3\x31\x6c\x4e\x26\x76\x34\xbf\x51\x71\xcd\x44\x5d\x36\x4b\x24\x44\xdb\xca\x85\x60\xce\x10\x66\x38\xd2\x08\x15\x56\xf3\xbc\x6c\x6e\xd0\x54\x0e\x56\x89\x61\xb6\xea\xef\x9d\x71\x87\x8b\xa3\xfc\xc2\x89\x4f\xc1\x7c\xe1\xf4\xe6\x48\x41\xd2\xcc\x36\xf5\x46\xc8\x1b\xf6\x62\x20\xd5\x4e\xc8\x41\x50\x76\x80\x48\x58\xbd\x61\x73\x2a\xb5\x4d\x73\x33\x1f\x85\xeb\xde\xc6\x8d\xd4\x07\x1d\x29\x87\xc9\xf2\x9c\xd7\x68\x12\x6e\x16\xa3\x5e\xad\x84\xa2\x71\x38\x1b\x47\xb4\xcc\x72\x1e\xdd\xc5\x8b\xe2\x19\x5c\x44\x8d\xdd\xa7\xbf\x3b\x2e\xe0\xc7\xf8\xf4\x83\x05\x6d\xee\x70\x68\x2a\xcb\x14\x1c\x58\x90\x21\x0b\x20\x64\x63\x68\x3a\xca\x42\x8c\x41\xa2\xd8\xd6\x4f\x25\x12\x8c\x70\x13\x5a\xd2\x66\x96\x4d\xa1\x69\x99\x02\x3b\xc0\xb9\x86\x8b\x8b\xfb\xdd\x64\x2b\xf5\xe5\x68\xf2\x58\xfa\xf8\xe3\x91\x08\xc8\x37\xf3\xee\x5b\xf7\xf5\x78\x32\x09\x57\x93\xc9\x38\x19\x5d\x35\x26\x61\x6f\xb9\x9a\xa8\xe9\xa0\x51\xa1\xdd\xc8\xb2\xe7\x37\x93\xbe\x35\x4c\x2c\xe2\x89\xc9\x38\x06\xf4\x19\x5a\xa4\xcb\xc9\x69\x66\x9d\x4b\x3a\xd5\x68\x32\xd4\x9e\x02\x1b\x57\x42\xaa\x98\x19\x9b\x35\x43\x69\x41\xd2\x5d\xa3\xf6\x2c\x38\x3f\x9a\x47\xb5\x8f\xf2\x8b\x84\xcc\x2e\x94\x2f\x32\xf9\x5c\x64\x3a\x2f\xd7\x57\x2b\x73\x62\xba\x8d\xe2\x26\x99\xe9\x8f\x97\x9d\x7a\x6d\x66\x1b\xdd\xd1\xa0\x9c\xb7\x83\xf9\x48\x70\xa4\xe6\x7a\x61\xda\xe8\xbb\x2a\xa5\x87\x22\x45\x1c\x5c\xe5\x8b\x4d\xee\x84\xac\x6a\x68\x36\x4c\xb7\xb3\xda\xa8\xee\x0e\x4b\x03\xb2\xc3\x45\xee\x0c\x2e\xc2\xb3\xdd\xa7\xbf\x3b\x2e\xc0\xc7\xf8\xf4\x03\x70\x6c\xc1\x20\x50\x36\x23\x52\x71\x28\x1c\x42\x81\xc0\x16\x93\x10\x50\x48\xb1\x45\x99\x90\x96\xb2\x19\x27\x88\x9b\x1c\x01\x2a\x2c\x89\x29\x57\xca\x02\xa6\xad\x4c\xfb\x1a\x2e\x2e\xee\x77\x13\xca\x21\xbd\x8c\x9a\xc7\xd2\xc7\x5f\x3b\x25\x02\xbc\x99\x77\xdf\xbc\xaf\x87\x53\x8d\x22\x4f\x94\x94\xdd\x80\xf1\x68\x6c\x36\xd2\xe2\xf1\xf2\xac\xe6\x59\x3c\xe1\x44\xd5\x30\x15\xf7\xa8\x5e\xe7\x93\xe8\x94\x4d\x3d\x60\x95\xa7\x11\xab\xe4\xc4\xf2\x71\xbf\x13\x5c\x53\x57\xd8\x7d\x3c\x0b\x0e\xb2\x4d\x77\x33\xe9\x24\x13\x21\x66\xad\x22\x7d\x03\xe6\x8e\x70\x71\xd4\xaf\x0a\x6d\x72\x95\x5a\x15\xf9\xee\x6a\x55\x4a\x57\x1c\xd0\x69\x6b\xa3\x5a\xd0\xe9\x05\x73\x14\xe0\x8a\xde\x99\x8e\xeb\xd9\x4c\x16\x94\x73\xed\xc9\xc4\x1c\x05\x73\x4d\xbb\x90\x29\xf0\x5a\xdf\xc9\x4d\x23\x6c\x33\x09\x09\x89\x52\xf6\xd2\xab\x0f\xc2\x36\x33\xf2\x3a\xb5\x79\x28\xb6\xc3\x45\xea\x35\x2e\xf2\xa1\xf4\xee\xd3\xdf\x1c\x17\x44\x7e\x8c\x4f\x3f\x10\x68\x51\x28\x94\x85\x29\xc7\x90\x21\xc7\x32\xb1\x24\x42\x3a\x54\x71\x69\x43\x1b\x10\xa5\x98\xcd\x1c\x20\x6c\x28\x31\x84\x16\xb5\x5c\xee\x48\x4b\xb8\xd2\x34\x21\x77\xb6\xae\xbf\xbf\x4f\x74\x06\x17\x17\x77\xb4\x09\x47\x00\xbf\x5d\xba\xff\x95\x5b\x2c\x39\x05\x6f\xe4\xdd\x4c\xde\xbc\xaf\x97\x80\x89\xfc\x14\xda\xab\xc6\x6c\xde\xed\xa7\x86\x55\x4a\x97\x76\x24\x4f\xa7\x56\xb1\x1b\xe9\xad\x12\x70\x81\x91\xd5\xa5\xe3\x8e\x5b\x53\x55\x23\x1e\x8c\x7b\x35\x58\xec\xdb\x41\x3c\x87\x83\x88\xdd\x14\xa4\x92\x35\x1c\x1f\x07\xed\xb2\x4f\x68\xc3\x48\xc7\xf2\xc1\x42\x89\xec\xfa\x71\x8b\x0b\xf7\x28\xbf\x98\x96\xf2\xd9\x48\x30\xde\xe1\x85\x14\x8c\x38\x83\x70\x70\xd8\x5f\xd1\x98\xa3\xea\xa5\x70\xb3\xc1\xf3\xc3\x75\xd2\x9e\xaf\x55\x4e\x1b\xa4\xc3\xd8\xea\x11\xb8\x9c\x4d\xd6\xb9\x10\xee\xb7\x3b\xc3\x70\xb8\x3a\x2c\x84\xbc\xc8\x56\x31\x30\x4e\xcd\x62\xee\x20\x38\xeb\xe7\x6b\xba\xb9\xc3\x85\x76\x06\x17\xb2\xbf\xfb\x74\x05\x17\xff\x6d\x7f\x7b\xd7\xba\x13\x17\xe2\x63\x7c\xfa\xc1\x22\x52\x99\x40\x59\xd0\x55\x0c\x49\xd7\x46\xb6\x74\x5c\x64\x4b\xce\x2c\x5b\x4a\x0e\x5d\xe5\x30\xd7\x11\x0e\xa2\x5c\xd9\x8a\x63\xa1\x08\xb5\xb1\x2b\x24\xe3\x0e\xa4\x4c\x5e\x8b\x17\x17\x77\x28\x88\x40\x04\x5d\x9e\x47\x09\xb4\xdb\xf4\x7b\xfc\xcd\x62\x80\xc0\x1b\x69\x37\x93\x37\x2f\xd3\x96\x94\x9f\x9f\xba\xd4\x1b\x8a\x6c\x1a\xaf\xd7\x75\x53\x0c\xea\xc9\x20\x5c\x20\x3d\x5d\xe7\x79\x9b\xd0\xf8\x32\xe4\xd5\x5c\xa3\x3a\x62\x66\xac\x86\xb3\x05\xab\x56\x1c\xf6\x8a\xe3\xf0\x5a\x6f\x36\xd3\xfd\x58\xcd\xac\x86\xb3\x32\x31\xa8\x66\xfa\xb9\xaa\x95\xf4\xcd\x70\x79\xfd\x1c\x2e\xdc\xa3\x78\x51\xd4\xdb\xc4\x9e\x90\x98\xcf\xc7\xf3\x3a\xc6\x3e\x99\x58\x66\xdd\xe4\xc1\x48\xcc\x49\xda\xa2\x60\x95\xb5\x7a\xc4\x9e\x17\xb5\x72\x41\x4c\xca\x6d\xdb\xe2\x43\x5c\xa9\x6b\x09\x60\x2e\x84\x37\x5f\x74\x56\xb5\x7e\xb4\x99\x76\x19\xc9\x45\x93\xc1\xd9\xaa\xd1\x2e\xd6\x33\xb5\xc2\x96\x70\x2c\x7c\x06\x16\xe4\xcd\x63\x83\xff\x6d\x7f\xef\x0a\x17\xfc\x63\x5c\xfa\x81\x03\xe6\x48\x22\x4c\x46\x4d\x00\x29\x95\x36\xc6\x88\x11\xc8\x84\x92\x10\xbb\xc4\x22\x12\x00\x4c\x24\x41\x2e\x97\xa6\x32\x25\x73\x19\x64\x26\xc0\x4a\x0a\x24\xb9\x8d\xaf\xc1\xe2\xe2\x86\x36\x91\x14\xb2\xcb\x49\xf9\xb6\x74\x97\x5e\x1c\x7e\xbd\x1a\x49\xf8\x46\xda\xcd\xe4\xad\xcb\xb4\x38\x32\xeb\xa7\x46\x7d\x3f\x52\x6d\x2e\x37\xe9\x5e\xdc\x67\x46\x01\xcc\xd2\xe1\x58\xa9\x92\xc5\x83\xf9\xb8\x26\x3b\x66\xbb\x30\x6a\x8f\xdc\x18\xd4\xaa\x0c\x16\xa8\xaf\x25\x60\x77\xb4\x20\x29\x33\x94\xac\xb4\x13\xd1\x51\x66\x59\x2e\x92\xe6\xa8\x9f\xec\xcc\xb8\xcf\x47\x61\x0e\xf7\x60\xd8\xe1\xe2\x28\xbd\x10\xf9\x1c\x8f\xea\xdd\xbe\xbf\xaa\x8d\x97\x7d\xd3\x1c\x0e\x22\xe6\xc4\xd8\x0c\x4c\x2d\xdc\x2d\x41\xa3\x5c\xe6\xb1\x5c\xa4\xd2\x09\xe5\x93\xde\x22\x57\xef\x78\x50\x74\x12\xab\x70\x83\x73\x8f\x85\xa3\x65\x6d\x6c\x2e\x63\x62\x51\xef\x2d\xea\xd9\x6e\x64\xa3\x54\x23\xd6\x8e\x16\xca\x5b\xfa\x51\x71\x06\x17\xf8\xcd\x63\x83\xff\x6d\x7f\xef\xc2\x05\xfb\x18\x9f\x7e\x60\x52\x10\xa0\x04\x74\x15\x57\x54\x10\xd3\x74\x80\x8b\x90\xe3\x9a\x42\x2a\xc5\x19\xb7\x1d\x4c\x11\x21\x92\x53\x86\x15\xe1\xd0\x74\x85\xe9\x32\x6e\x51\xec\x0a\x87\xf0\xdd\xaa\xd1\x85\xed\x8b\xcb\x1b\x14\x14\x30\x4a\x2e\x26\x1f\x4f\xa5\x8f\x3f\xb0\x4e\x19\x3c\x4a\xbb\x4f\xfe\xbe\x06\xf8\x23\x06\xde\xc2\x04\x1a\x68\x31\x3f\x19\x74\xfb\x9d\xcc\xa4\x28\x3c\xcc\x3c\x45\x91\xab\xeb\x25\x23\xed\xd4\x0a\x3d\xdb\x0c\x66\xe4\x70\x56\x0e\xea\xc6\x2a\xdc\x2e\xa7\x0a\xd9\x44\x7e\x3d\x9c\x17\xdb\xf9\xfa\x66\x50\x2f\x36\x27\xd9\x75\xa2\x1c\x4e\xa4\x62\xb5\x7c\x32\x6d\x14\xd3\xe3\x8a\x6b\x85\xbd\xca\xae\x0f\x77\x98\x38\xea\xd3\x4e\xaf\xd1\x2e\x37\xaa\x71\xd7\xd3\x57\xeb\x65\x33\xbe\xce\x54\xba\x6c\x52\x51\x06\x41\x25\x63\xa3\x6f\xf2\x43\x73\xda\xae\x86\x6a\xf3\xd8\x62\xb6\xd4\x7b\xa6\xe5\x14\x83\xb3\x76\x53\x11\x9c\x9c\xd5\xb5\x69\xd4\x2a\xca\x76\x2d\x3f\x37\xea\x2c\x4b\xed\x45\x5e\x34\x97\x11\x63\xb4\xc3\x04\xd1\x49\xd6\xdc\x8c\xd0\x11\x00\x23\xb3\xc6\x89\x4b\xfd\x15\x30\x81\xee\xc6\x04\xfd\x18\x7f\x7e\xa0\x4a\xb9\x10\x30\x6e\x02\xd7\x72\x2c\x02\x31\x82\x8a\x70\x64\x42\x1b\x12\x57\x39\x36\xa5\xd8\x81\x98\xe2\xed\xf8\xed\x28\x93\xb8\x8e\x83\xa1\x74\x80\x6d\x72\x07\x99\xee\xb5\x23\xe6\xf0\xe2\x22\x2c\x85\x82\x92\x8b\x29\xf7\x53\xe9\xe1\x67\xe6\x91\xc0\x08\x5c\xc1\x04\x13\x37\x62\x02\xf2\x85\x96\x50\xed\xa0\x9c\x45\x72\x1d\x9a\xcc\x74\x96\x95\xd0\x6c\x55\x2d\x18\x7a\xb9\x6f\x58\x6a\x54\xc0\xe5\x84\x13\xcb\xb8\xa5\x09\xe9\x25\xa2\xc9\xe4\x30\xcc\x32\x79\xc7\x2f\xd8\xa5\xc5\x88\x19\xab\x4e\x0f\x75\x2a\x46\x3f\x11\x87\xd5\x02\xf2\x4b\x55\x3d\xd2\x8b\xa5\xa4\xbd\xeb\xc3\x2d\x26\xd4\x51\x5a\x81\xa6\xc1\x86\x83\x59\xa2\x12\x19\xc4\x27\xd1\xa1\x18\xae\x36\x06\x4e\xf0\x04\x8b\xf4\x6b\xcb\x58\xb7\x96\x5a\x94\xe6\xc5\x55\x22\x97\x8a\x36\x24\x32\xba\x75\x1a\xb3\xf2\xab\x46\x27\x9d\xcb\x85\xb4\xa2\x0d\xfd\x71\x62\x09\xda\xd3\xb8\x35\x1b\x4f\xf3\xf5\x48\x37\x9b\xad\x4a\xad\xbe\x53\x02\x9c\xc1\xc4\xb8\x78\xe2\x52\x7f\x05\x4c\xdc\x1f\x27\xc8\xc7\xf8\xf3\x03\x21\x40\x9a\x82\x43\x87\x6e\x87\x67\x60\x31\x13\x98\x0c\x03\x88\x99\x12\xc0\x76\x10\x95\x26\xc6\xd8\x36\x29\x45\x00\x3b\x16\xa4\x44\x38\x18\x52\x17\x4a\xe5\x12\x93\x5e\x5d\x86\xba\xb8\xcd\x4d\x91\x90\x57\x10\xf3\x58\x0a\x85\x90\x5c\x50\x06\x01\x22\xd7\x30\xc1\x6f\xc4\x04\x28\xa6\xc7\xc9\x64\xb5\x92\xa8\x64\xcd\xf6\xa8\x1b\x2e\x5b\x7e\x4c\x4f\x37\xfd\x4d\x21\x53\x2d\x85\xe5\xb4\x5a\xd2\x73\x55\xd1\xe4\x60\x64\x4f\xfc\x65\xc5\xc9\x18\x9b\x70\xa8\x69\xf4\x1c\xe5\x8b\xc4\x1c\x8d\xab\xa4\xdc\xa9\x40\xe6\xc8\x91\xd0\x39\x49\x9a\xc3\x39\xad\x4c\xa7\xbb\x3e\xdc\x61\xe2\x28\xa7\xa8\xd5\x6c\x38\x6a\x74\xaa\x35\xc3\xd7\xd2\x26\x4b\xd8\xc9\xd4\xd4\xec\xc2\xf5\x74\x95\x22\xd1\x62\x30\x62\xa7\xc7\x5e\xa2\x86\x97\xdd\x41\x3a\xb8\x70\xe3\x46\xd6\xa3\x69\xe4\xc5\x72\x75\xbd\x5c\x1b\xeb\x83\xa1\x3b\x13\x9b\x64\x3c\x4f\x18\x69\xb4\xd3\xcd\x32\x9f\x5b\x60\x3c\xd9\xc5\x89\xe5\x19\x4c\xf8\xd3\x13\x97\xfa\x7b\x62\x02\x7f\x8c\x3f\x3f\x98\x92\xd9\x96\x2b\x5d\x6c\x23\x07\xdb\x94\x59\x0e\x24\x16\x01\x14\x20\xc2\x4c\xaa\xb0\x54\x54\x22\x60\x22\x00\x95\x74\x18\xb3\x09\xb0\x6c\x6a\x9a\x4c\x70\x81\x5c\x45\xaf\xe5\x14\x97\x37\x25\x28\x81\xe8\xca\xdc\xe9\xb1\x14\x0a\xc2\x04\xa6\x12\x73\x24\xae\x61\x82\xdd\x88\x09\xd6\x9f\x2e\xa8\x10\xd9\xf2\xaa\xb6\x30\x4a\x20\x52\x4c\x27\x46\x2a\xaf\x6a\xa5\xa8\x17\x56\xc3\x9a\xa5\x45\x45\x6d\x6c\x26\xdb\x0b\x5a\x6e\xea\xa5\x75\xa7\x1e\x73\x33\xda\xba\xc2\xba\x3d\x30\x10\xc3\x55\x58\x63\x85\x68\xda\x4c\xac\xc2\x7e\x7e\x39\x5e\xd8\xe1\x52\x6e\x5a\x39\x5a\x7e\x52\x47\x6e\x2a\xb3\x68\x39\x8e\x98\x03\xb1\x5a\x31\x2d\xd7\x2f\x42\x15\x32\x78\xba\xd0\xe9\x4d\xd3\xe3\xb8\xdf\x8c\x0d\x32\x71\x3b\x1e\x59\xba\x78\x15\x5d\xda\x28\x9d\xed\xfb\xa9\xcd\x68\xd6\xe8\xf8\x7a\x94\x27\x41\x3e\x13\x53\x31\xe9\x2f\x9b\xe1\x1e\x4d\x99\xc3\xe1\x44\x75\x27\x20\x1f\xde\xc6\xa1\xe8\xf4\x0c\x26\x86\xa9\x13\x97\xfa\x7b\x62\x02\x7d\x8c\x3f\x3f\x20\x64\x01\x66\x11\x20\x09\x61\x36\x74\x81\x8d\xb8\x30\x5d\x60\x2b\x48\x4d\x47\x4a\x46\xb7\x51\xc8\x45\x50\x32\x93\x5a\xae\x72\x94\x43\x99\xc3\xa4\x83\x19\xe7\xd2\x96\xd7\xb6\xf1\xc0\xc5\x4c\x9a\x52\x24\x2e\x67\xe1\x4f\xa5\x50\x00\x2c\x04\x43\x8c\x60\x74\x0d\x13\xf4\x46\x4c\xac\x33\x4b\x13\x44\x2b\xc6\x34\xb9\x5c\x0e\xbd\x45\x2c\x1f\x37\x51\xb3\x59\xf7\x0b\xa2\xd3\x1f\xd7\x42\x5c\xc1\x1a\x1c\x01\xe4\xd0\xb5\x93\x82\x9b\xa4\x39\x0b\x96\x93\x25\x2f\x21\xe2\x5e\xba\xd1\xa9\xa3\x54\x77\x6c\xab\x65\x6e\x3d\x1e\x71\x95\xca\x1a\xb3\xec\xaa\x3f\x0e\x57\xf7\x4b\xfb\x3b\x4c\x1c\xf5\x29\x19\x14\x57\xf3\xd4\x3a\xd1\xcb\x0d\x2b\xfa\x68\xb2\xf2\xe1\x9c\x59\x58\xcf\x67\xda\xa5\x50\x74\x6c\x18\xa0\x27\xfd\x5c\xb1\x90\xad\x4d\x45\xb0\xca\xc4\x78\x18\x35\xe3\x71\x6d\x45\x32\xb0\xed\xd7\x4c\x6c\xc4\x92\x22\xd5\x9c\x36\xb8\x87\x22\xf5\x5a\x29\x9a\xab\x8d\x37\xa3\xd5\x36\x0e\x45\xfd\x33\x98\xe8\xf7\x4e\x5c\xea\xef\x89\x09\xf8\x31\xfe\xfc\x60\x32\x97\x5a\x36\x27\x8e\x29\x09\x93\x1c\x48\x22\x6d\x5b\x98\x54\x58\xdc\xb5\x81\x6d\x52\x64\x4a\x86\xb8\x6b\x42\x93\x50\xd7\xb6\x5d\xca\xb8\xc9\x4c\x07\xb9\x18\x42\x53\x82\x2b\x39\x36\xb8\x9c\x31\x30\x22\x2f\x5f\xcd\x7b\x2a\x85\x9c\x01\x89\x19\x95\x10\x5f\xcb\xb1\x19\xb9\x35\x4e\x58\x70\x91\x2c\x9b\xfd\x44\x7f\xd9\x4f\x6f\x52\xa3\xc6\x2c\xb4\xcc\x8d\x4a\xe3\x5a\x3a\xe4\x9b\x86\xbb\x29\x54\x87\xa3\x31\x58\xe4\x8c\x71\x31\xa3\xaf\x1b\x56\x7e\x99\xe5\x86\xe5\x99\xdd\x54\x6a\x28\x97\x3e\xac\xa7\xc6\xab\xc9\x2a\x53\xef\x94\xec\x52\xba\x39\x9f\x76\xda\x43\x58\x11\xbb\x3e\xdc\x62\xc2\x39\xca\x27\xf0\x4c\xad\x92\xb5\x9e\xaa\xf7\xa7\x1d\xb1\xee\x53\x94\xde\x68\x30\xc7\x47\x21\x31\xdf\xf4\x30\x8b\x39\x7d\x6b\xb1\x74\xc6\xb5\x25\x6c\x00\x5e\x4e\x4e\x7d\x6d\x1a\xe1\xa1\xa5\x30\x8a\xdd\x34\x01\xfd\x51\x8e\x66\xa0\x66\xf9\x51\x55\x16\xeb\x50\x37\x14\x0a\x75\x71\xd8\xdc\x61\xa2\x77\x06\x13\xa7\x90\xf8\x4b\x60\xe2\xfe\x1c\x1b\x7c\x8c\x3f\x3f\x58\x36\x36\xa9\x29\x29\x16\x44\xb8\x0a\xd9\x16\x61\xca\xe1\x54\xd9\xca\x52\xcc\x32\x81\xb4\x05\x65\x0e\xe1\x0e\x73\x95\x09\x10\x45\x08\x0b\x2a\x1c\xe1\xd8\xdc\x34\x9d\xfd\x6d\x88\x4b\x98\xb8\x3c\x3b\x12\x00\x5f\xde\xf4\x7e\x2a\xdd\xbf\x0d\xc2\x24\x14\xe4\x6a\x8e\x8d\x6e\xc4\x04\x5f\xb2\xda\xa8\x42\x4a\x05\x32\x9d\x25\x78\xbd\x3e\x65\x41\x93\x45\xed\x4e\x0d\x26\xe1\x82\xb5\xd3\xa5\x14\xa9\xe9\x5d\x5b\x8d\x51\x35\xe4\x0d\x53\x2a\x91\x8e\x4f\xaa\xd0\xa8\x56\x82\xab\xd1\x24\xd5\x34\x92\x22\x53\x35\x53\x9c\xf4\x43\xe5\xf0\x2c\x18\x9a\xa4\x55\x32\x4d\x9f\xe3\x84\x73\x9c\x4f\xa4\xfb\xbe\xe4\x13\xb7\xd8\xed\xa6\xf4\x79\x58\xeb\xa9\x68\xde\xc2\xc6\xb2\xcf\xf4\x46\xa5\x27\x69\xdd\x64\x58\xb7\x41\x25\xba\x80\xa0\x82\xa7\x23\xbd\x18\x15\x03\x5a\xac\x9a\x7d\x94\xab\x21\x5e\xf4\x45\x7e\x19\x09\x0f\x93\xf3\x8e\x58\x6a\xb5\x4c\xae\xd3\x98\xa5\x76\xe4\xa3\xed\x33\x98\x68\x93\x13\x97\xfa\x5b\x62\x02\xcb\x8f\xf1\xe7\x07\x4b\x20\xc9\x4c\x01\x6d\x0b\xdb\x84\x09\x9b\x70\x17\x02\xc0\x18\x32\x6d\x0b\x63\xae\x20\x13\x82\x41\x8e\x91\xad\x10\x84\x8e\xe3\x98\x18\x20\x28\x80\x14\x4a\x00\x66\x5f\x3b\x1a\x08\x2e\x47\x02\x89\x38\xb9\x9c\x6d\x3c\x96\x42\xc6\x29\xc0\x1c\x11\x4a\xae\xe6\xd8\xb7\xae\xc5\xf2\xf6\xc8\xf4\x93\xd9\x82\x66\xe6\x8c\x90\x16\x6e\x7a\x93\x6c\x0e\x93\x9a\x97\x88\x6f\xb2\xf9\x94\x81\x1d\x7f\x99\x6a\x44\x1b\x2c\x6c\xe5\x93\xde\x22\xbb\x5a\x17\x44\x2a\xc8\x7a\x24\x3d\x8a\x90\x30\x2e\xac\xf2\x99\xa9\xa1\x35\x2b\xb9\xe1\xa6\x11\xf1\xc3\xc3\xb6\x68\xce\xb5\xfd\x05\xd1\x3d\x26\x8e\xdc\xb4\xa4\x92\x91\xc9\x3c\xd6\xd6\x0b\x69\x4b\xf6\x5c\x3b\x5d\xcd\xad\xa3\x6d\x36\x50\x16\xe8\xf9\x0b\xea\xd4\x64\xbe\x27\x34\x4d\x8d\x90\xa5\xc1\x72\x97\x1b\xe3\x18\x0c\x81\x22\x0b\x26\xc1\x3c\xd7\xcb\x55\xf3\xcb\x5a\x6d\x52\x8e\xeb\x2e\x6e\x08\xbb\xba\x91\x7e\x37\x9a\x86\xbb\x1c\xdb\x3e\x83\x89\xe3\x08\xb5\xfb\xfb\x2b\x60\xe2\xee\xb9\x13\x16\x1f\xe3\xcf\x0f\x2e\x96\x92\x41\xc5\x1d\x45\x31\x00\xd8\xd9\x26\xed\x02\x71\x8e\x09\x06\x12\xda\x0c\x28\xa8\x4c\x47\xb9\x96\x89\x31\x02\xc8\x52\x40\x60\x4c\x6c\x53\x31\x2e\xb8\xa5\xdc\x6b\x71\xe2\xe2\x76\x36\x03\x98\x5e\x0c\x13\x8f\x85\x90\x61\x04\x04\xa7\x1c\x91\x6b\x19\x36\x95\x37\x22\x22\x94\x6f\x36\x94\xab\x2a\xcb\xb0\x1c\xf8\x2a\xea\x6c\x8a\xcb\x9e\xdd\xc8\x27\xc7\x78\x31\xef\xe6\xda\x99\x60\x34\xa6\xe7\x26\x03\x95\x5c\x2c\x16\x4e\x3e\x57\xb7\x9b\xc5\x05\x72\xa3\xb9\xe2\xb0\x9a\xab\xb8\x99\x48\x9a\xd7\x4b\xf1\x9a\xd5\x8e\x84\x96\x1a\x8e\x4c\xb9\x9a\x08\x3e\xdf\xf7\xe0\x0e\x11\x47\x3d\xaa\x87\x82\x4e\x74\x5a\x2f\x55\x6d\x6f\x94\xce\xd6\xa9\x5b\xaa\xf6\x43\xce\x2c\x26\x46\x71\x15\xf4\x9a\x43\x77\xa8\x37\x51\x9b\x2f\xea\xdd\x90\x66\x79\x23\xb0\xce\x2e\x6a\x86\x68\xf2\xf9\xc8\x2e\xe8\x93\x71\xac\xae\xb2\x8b\xea\xaa\xe9\x6d\x22\x04\x74\x3c\xd4\x4b\x79\x9d\xe1\x70\x37\x73\x6a\x9c\x41\x84\x9d\x3b\x71\xa8\xbf\x02\x22\xee\x8f\x12\xfc\x63\xbc\xf9\xc1\x95\x8c\xba\x54\x71\xa6\x90\xe3\x72\x49\x24\xa7\x6a\x3b\x2e\x0b\x0c\x2d\x49\x2d\xc1\x94\x6d\x4b\x0e\xa1\xcb\x2d\xee\x5a\x90\x10\xc7\x95\x96\x6d\xda\xd8\x16\x26\x37\x91\x79\x2d\x4a\x5c\xcc\xa1\x19\xa4\x54\x5e\x5c\x89\x7d\x2a\x85\x54\x48\x88\xb9\x90\x92\x5e\xcb\xb0\xe9\xad\x2b\xb1\xa1\x7e\x5f\x2a\x67\x9e\x75\x55\xa5\x0f\xe9\xda\x68\xe4\xac\xbe\xd5\x99\x6f\xd2\xb6\x21\xb9\xcb\xe3\x1a\xa6\x8b\xcc\x52\x78\x43\x7f\xdc\x55\x75\x77\x4a\x0d\x33\x1a\x1a\x95\xac\x5c\x11\x54\x7a\x7a\x3b\x9f\x1c\xb3\x4c\x7c\x14\x1f\x8c\x69\x68\x55\xe8\x74\xcc\xd0\x38\x35\xf1\xf6\x33\xf9\x2d\x26\xec\xa3\xb1\xba\x90\x37\xac\xf9\x22\xa9\xeb\x71\x77\x5a\x2a\x0d\x1c\x67\x3c\xa8\x14\x44\xbc\x27\xbc\x9a\x4c\x5b\x70\x5d\xcc\x86\xe6\xda\xba\x91\xb0\xd1\x3c\xd5\xf0\x1d\x4b\x2f\x26\xca\x89\xf0\x34\x5b\xc6\xcb\x6a\x7c\xba\x99\x17\x23\xeb\xba\x3e\x2a\x64\xd0\xb4\x28\x40\x3b\xd3\x0e\xfb\xcc\xd8\x1d\x92\x8d\x56\xce\x60\xa2\xa9\x9d\xb8\xd4\x5f\x01\x13\xf7\x47\x09\xf6\x31\xfe\xfc\xe0\x02\x09\x18\xa5\x2e\x70\xa8\xad\x14\x15\x18\x21\xee\x00\x20\x84\x6d\x71\xd3\x45\x16\x17\xc0\x65\xae\x23\xa1\x12\x98\x99\x04\x42\x6e\x5a\x16\x84\x0e\xe1\xd2\xa2\xb6\x82\xd7\x30\x71\x71\x17\x9b\x61\x4a\xc5\xc5\x99\xd3\xb6\x74\x37\x71\xa2\x84\x41\x21\x10\x62\xf4\x5a\x82\x4d\x6f\x5d\x88\x0d\x45\x8b\xcd\xaa\xd0\xeb\x79\xda\xc8\x79\x6e\x31\x9a\x5a\xe3\xc9\x7a\x46\x62\x28\xd4\x4c\xfa\xfa\xb8\x68\xa8\xc9\xd4\x80\xc9\x01\xdc\x74\x66\x04\xd8\xa3\x05\x33\xa3\xfa\xa0\x59\xb7\xfb\x5d\x90\x18\xc1\xb6\x08\x15\xcb\x56\x70\xa2\x4d\x37\x3c\xcf\x8a\x86\x5a\x68\x23\x3e\x3a\x82\xc4\x51\x32\x11\x5b\xf1\x39\x2e\xcf\x84\x04\xb1\x58\x34\xdc\x40\x85\x8a\x8f\xfb\x19\xaf\x82\x73\x78\xb8\xee\xdb\x93\xf1\x60\x91\xeb\xc7\xb3\xa5\xa0\xab\x0d\x57\xae\x56\xeb\xf6\xad\x98\x4a\x39\x4e\xac\xae\xa2\x99\x32\x97\x5d\x9f\xb8\xcb\x75\x15\xac\x07\x85\xf0\x86\x85\x60\x58\x92\xf8\xee\x92\x5d\xb4\x78\x06\x12\xf5\xf6\x89\x47\xfd\x3d\x21\x41\x3f\xc6\x9d\x1f\x14\x90\x80\x5a\x0e\x83\x4c\x72\x01\xa9\xe2\x8e\x23\x80\xc9\x5c\x6e\x3a\x42\x09\x0c\x38\x37\x29\x06\xc4\xb4\x00\x13\x50\x20\xaa\xa8\x29\x10\xb0\x5c\xcb\xb6\x21\x72\xac\xab\x0b\xb1\x97\x03\x01\xa1\xf0\xf2\xeb\x82\x4f\xa5\x90\x02\xbc\xcd\x7f\x28\x66\xd7\x12\x6c\x7a\xeb\x42\x6c\x30\x5a\xac\xc9\x46\xad\x4f\xe2\xca\x75\xda\x19\x0b\x4f\x1a\x2c\x16\xc1\xa3\x72\x24\x33\x4d\xb4\x1b\x69\x55\xf3\x53\xd9\xa0\x58\x96\x90\x2c\x4f\x6a\x15\x87\xe5\x79\x8e\x94\x80\xab\x44\x45\xb3\x9d\x4e\xdf\x1e\x34\xec\xb5\x03\x82\xbe\xd5\x36\x9d\x62\xb7\xd1\x0c\x87\x2a\x99\xe7\xcd\x09\xfb\xc8\x4d\x2b\xb8\x5f\x2b\x48\xb7\x5c\x4a\x0f\x8c\xa1\xce\x0b\x23\x3d\x62\x36\xcd\xc6\xc6\x4b\x74\x64\xbd\x87\x52\xa8\xbf\x0e\xb7\x1b\x15\x47\x9f\x2e\x57\xc5\xf2\x2c\xa5\x27\x69\x45\xb5\x47\x4e\x1e\xa0\x5e\xd3\xdf\xe4\xdd\x29\x0b\x75\x1b\x46\x7c\xb4\x8a\x8e\x1a\x6d\xad\xbc\x61\x25\xc5\x77\x53\xa7\xdc\x19\x4c\x54\xc5\x89\x4b\xfd\x3d\x31\x41\x3e\xc6\x9f\x1f\x28\xe2\xd8\x41\x88\xb9\xd8\x74\x24\x21\x8e\xc5\x85\xe2\x04\x38\x48\xb9\x90\x63\x26\x08\x85\x92\x9b\x40\x0a\x57\xd8\x08\xd9\xc8\x84\x26\x81\x48\x60\xe1\x20\x17\x71\x7e\xed\x0d\x03\x70\x71\x13\x9b\x51\x26\x2e\x6f\x62\x3f\x95\x42\xc2\x00\x12\x42\x08\xc0\xae\x25\xd8\xf4\xd6\x85\x58\x98\xde\x00\xcf\xda\x4c\x9a\x86\x3e\x23\x14\xc4\x4a\x7c\x65\xa3\x4e\x3c\x51\xf7\xd3\x5d\xb2\xf4\x96\xe3\x44\x4f\xf3\xf3\x7a\x76\xed\x2c\xd7\x33\x3d\x9d\x9e\x67\xc8\xdc\x18\x45\xc6\xba\xc6\x62\xe1\xd0\x6c\x19\x9d\x4d\xd7\xb9\x65\x3d\x14\xd1\xbb\xe5\x0c\xea\xc2\x30\xb2\xb3\xa3\xe7\x77\x3d\xec\xa3\x3e\x0d\x59\x5a\xb0\xa0\x8a\x86\x65\xe7\x16\xa5\x94\x5b\x5c\x9b\xf5\x52\xad\xae\xb5\x37\x11\x6e\x5a\xcb\x89\xd2\xab\x45\xd5\x68\xa4\x3a\x4b\xaf\x09\x9a\xe3\x95\x6d\xaf\xd7\xce\x32\xe3\xb5\xe7\xd5\xb4\x63\xa5\x12\x4d\x2d\x51\xca\x35\xa5\xac\x14\xb3\x35\x69\xa4\xd6\x05\xdf\xb6\xbd\xf2\x4e\x89\xd4\x19\x4c\x54\xfe\x8a\x87\x9d\xee\xc7\x04\xfe\x18\x7f\x7e\x00\x54\x71\x6e\x5b\x92\x01\x06\x6c\x0b\x5a\x94\x60\x4e\xa8\x2b\x84\xab\x30\x53\x18\x11\x66\x11\x6a\x21\x66\x4a\xa5\xa8\xe4\x2e\x94\xc4\x75\xdc\x6d\x7e\x22\x21\x35\xed\xcb\xf7\xb4\xe9\x37\x7a\x79\x72\xc4\x28\xa5\x17\xb7\xf3\x9e\x4a\x21\x81\x1c\x63\x89\x00\x67\x57\x53\x6c\x7c\x23\x26\x96\xf5\xa1\x9b\xed\xb7\x1b\xb9\xa9\x55\x8d\x39\xf1\x60\x2a\xd4\xb5\xba\xe9\xc4\x2c\x3e\x1d\x8c\x15\x6d\xba\xab\x7e\x01\xb3\xdc\xba\x57\x9d\x24\xe6\x2a\x97\x58\x66\x2a\x6b\xbc\x71\xa2\x69\xcd\xb2\x87\xd9\xe1\xca\x6f\x6a\x15\x5c\xa5\xd2\x6c\x4c\x78\x70\x6c\xb9\x39\x0f\xc4\x96\xc3\xe7\x43\xb1\xd6\x51\x3a\x91\x74\x0a\x62\x16\x89\xcc\x46\x6a\x9d\x15\x52\xce\xb2\x85\xa1\xee\x98\xe3\x8a\x9f\x34\x6a\x83\x64\xa6\x9b\x11\x03\xdf\x9a\x10\x88\x96\x5a\xca\xe9\x56\xed\xa4\x85\xab\xe9\x4e\x31\x3c\x9b\x0f\xf5\x42\xb7\x33\xea\xf4\x4a\x6e\x27\xd8\xe9\x91\x9e\x1d\x59\xf6\xc8\xcc\x2d\x48\x8f\xed\x36\xb1\xb5\x33\x98\x28\x9d\x5e\x08\xfa\x7b\x62\x02\x7d\x8c\x3f\x3f\xb8\x0a\x62\xcc\x98\x4d\x6c\x8a\x6d\x40\x4c\x46\x95\x4d\xa8\xa2\x8e\xc3\x29\x01\x0e\xc6\xc8\x14\x36\x16\x84\x32\x97\x43\x93\x30\x4b\xd8\x5b\xa0\x09\x97\x41\x06\x89\x85\x2f\x2e\x3a\xd1\x6f\x57\xbc\x9e\x73\xc4\x2f\x27\xe0\x8f\xa5\x10\x73\x82\x85\xa4\x98\xf0\xab\x29\xf6\xad\x9b\x13\x21\x52\xd6\x07\xab\x5c\x45\x44\x32\x4d\xb5\x8a\x53\x07\xc2\xa2\x9e\x5b\x8f\x73\x79\xad\xba\xb0\x4d\x63\xd2\x8d\xf4\x59\x17\xc5\x3b\xa5\x8d\xe5\xac\x56\x96\x1b\x8f\x55\x83\x53\x8f\x85\x13\xc6\x22\x4b\xa7\x41\xbf\x6a\x4f\x1b\xa2\xb9\xec\xc5\x69\x2f\x2b\xb5\xc8\x7a\xe4\xf1\xde\xf3\x86\x9d\x75\x34\xab\x47\x9b\x18\xe5\x0e\xf2\x2b\x4b\x94\x65\x83\xf9\x64\x36\x08\xf9\x0a\xc5\xba\x2c\x3e\xdf\x44\xea\xc3\xea\x80\xf7\x79\xd2\x8f\x4d\x73\x95\x8d\x3e\x6e\x58\x4d\xd5\xad\x0d\x16\x4b\x83\x90\x78\xb5\x58\xb0\x72\x29\x67\x8e\xac\x6e\x92\xf5\xea\x38\x95\xe6\xd1\x8e\x47\x1a\x83\xf6\x7c\x37\x77\x0a\x9f\xc1\x84\xf1\x57\x3c\x00\x78\xff\xb2\x13\xfc\x18\x7f\x7e\xe0\x14\xb8\xca\x71\x77\x8f\x32\x63\x45\x81\x20\x88\x3b\xdc\x66\x2e\x34\x31\x74\x01\x46\xb6\xeb\x3a\xc2\xa2\x10\x2b\xd3\x42\xae\x6d\x62\x9b\x08\xc4\x09\xb6\x25\x52\x90\x5d\x3e\x00\x48\xbf\x5d\xbe\x69\xca\xe4\x36\x02\xbc\x59\x0a\x31\x86\x04\x4b\xc1\x20\xbf\x9a\x63\xdf\xba\x39\x81\x2b\x05\xee\x7a\x91\x5e\x99\x16\x3b\x51\xb7\xbe\x5a\x24\xba\xc9\x65\x6e\x1a\x92\x1e\xd4\x82\xe3\x75\x28\x53\xd0\xda\xc3\xa2\xe8\xcd\xe3\x53\x3b\x35\xae\x0e\xba\xeb\xc5\x38\xd5\xb7\xe2\xce\x60\x10\x9d\xda\xe5\xe4\x72\x1e\x87\x2b\x37\x04\x91\xc8\x0c\xfc\x51\x24\x9b\x2b\xd6\xf4\xf1\xf3\xa5\x22\xeb\xf8\xf2\x44\x62\xd0\x44\x83\x4e\xa2\x56\x88\xda\xb5\xb0\x03\x47\x15\x59\x8a\xa4\xeb\xae\xea\xce\x62\x3c\x9e\xd7\xfc\x6c\x8c\xf9\xf1\x69\x39\xbf\x20\xb9\x4c\x2d\xa5\x2f\x2a\x9b\x5e\xcc\xd3\xf4\xe1\x26\x17\x9e\xc2\xfe\x22\x29\x34\x4f\xab\xa5\x4d\x63\x39\x49\x1b\x0b\x1d\x34\xe6\xc6\x62\xb3\x25\x1c\x11\x67\x30\x91\xff\xdf\xc3\x4e\x5b\x4c\x80\x8f\xf1\xe7\x07\x89\x99\x0d\x15\x74\x81\xe5\x42\xd3\x95\x0c\x0b\xa0\x2c\x20\x15\x95\x8a\x22\xe8\x50\x85\x1d\xc7\xc1\x1c\x38\x08\xba\x2e\x71\x1d\x68\x02\x69\x5a\x10\x61\x93\xd8\xae\x65\x5e\x5e\x8a\xa5\xdf\x2e\xef\x3f\x70\x20\x88\xb8\x98\x4f\x3c\x95\x1e\x7e\x73\x01\x6e\x33\x8a\x2b\x98\x20\xb7\x6e\x4f\x50\x7d\x9a\xec\x88\xac\x30\x83\xb5\x7c\x98\x2d\x87\xfd\x61\x3f\xe5\xd4\xbb\xd8\xd1\x97\xa0\x13\x02\x21\xc3\x4f\x8f\x57\x29\x56\x2e\xcc\xc7\xbd\x4d\xbe\xbe\xa1\x03\x17\x65\xdb\x8d\xa1\xe9\x87\x67\xf5\x95\xde\xcc\xf6\x82\x15\xb7\x2c\x1a\x86\x44\x45\x4b\x36\x79\xa3\x60\x65\xf1\x7e\x67\x60\x87\x89\xa3\x3e\x85\xdd\x7a\xd6\xf4\x33\xa1\x54\x7e\x9c\xd1\xab\x3d\xcf\x42\xb6\x9e\x9d\x74\xfb\x5a\x39\x59\x1f\x35\xfb\x76\x9a\x44\xe2\x8d\xbc\xb0\x72\x78\x60\x6c\xc6\xa3\x9a\xdb\x5e\xac\xf8\xd0\xa5\x82\x3b\xab\x6e\xba\x51\xd5\x07\x6d\xa3\xef\xba\x69\x6d\x53\x8b\x45\xda\xcb\x8e\x9b\x1e\xb4\x2b\x5b\xf8\x45\xce\x5d\x9e\xc8\xfd\xef\x61\xa7\x52\xe0\x57\x24\x3f\xc6\x9f\x1f\x6c\x48\x08\x95\x14\x21\x57\x11\xa4\x90\x03\x81\x85\xa4\x89\x39\xb0\x2c\x65\x99\x5b\x38\x11\x53\x29\x82\x24\x12\xc8\xb1\x14\x21\x82\x20\x81\xa9\x03\x2d\x42\x30\x63\x97\x0f\xc5\xd2\x6f\xf4\xe2\x26\x36\x87\x82\x90\x8b\x0b\xb5\x4f\xa5\x10\x11\x4a\x09\xa0\x90\x8a\x6b\x39\x36\xb9\xf5\xf2\x84\x88\x6b\xb5\x6a\x6a\x41\xa3\x64\xa6\x65\x33\xa6\xbe\x9c\x07\xe7\x7d\x2d\x58\x9a\xd3\x68\xcf\xcf\x5a\x54\xeb\x44\xdb\x10\x58\x46\xac\xd9\xcd\x25\x63\xd3\x41\xda\x2f\x8f\xd6\x6e\x6e\x02\x86\xbc\x69\x74\x61\x61\x56\x6d\xd8\xde\xb2\x44\xe3\x88\x86\x94\x55\xa5\x99\x41\x21\xb9\x7e\xce\xb1\xcd\xa3\x7c\xc2\x32\xa3\x31\x62\x58\xae\x36\x2e\x4d\x52\xc1\xf1\x28\xb5\xde\x6c\x2a\x95\xa0\xd5\x68\xe4\xd2\x53\x63\x89\x47\x49\x7b\x90\x5c\x16\x27\x0b\x33\xec\x25\x2b\x1b\xad\x64\xf1\xc1\xaa\xd6\xb6\xd8\x24\x26\xbd\xa0\xb5\x68\x98\x4e\xb7\xb3\xca\x19\x89\x90\x5a\xf9\xb1\xda\x48\x84\xfc\xca\xee\x59\x84\xc8\xb9\xcb\x13\xd9\x53\x97\xfa\x7b\x62\x42\x7c\x8c\x3f\x3f\x48\x80\x2c\xe0\x52\x05\x95\xa2\x80\x59\xd2\x95\x0e\x13\x42\x11\x46\x18\xc7\x96\x63\x22\xd7\x34\x01\x65\x82\x33\xdb\x71\x15\x30\x6d\x44\x81\x72\xa9\x2d\x1d\x17\x98\xc2\xdc\x86\x02\xbe\xfb\xdf\x19\x4c\x5c\xdc\xc4\xe6\x48\x5e\x79\x3b\xf3\xa9\x14\x22\x80\xa8\xdc\x86\x3f\x71\x2d\xc7\x26\xb7\x6e\xd9\xd1\xf0\x24\x06\x89\xa2\x45\x93\x06\x1d\x33\x45\x13\xc6\x30\x2f\xfd\xc5\xb8\x5d\xf5\x9d\x29\x0e\x46\xa7\xe9\x22\x87\x6b\x47\x64\xbc\xc1\x50\x8f\x2d\xb3\x8d\xa4\xe2\xed\x54\xb2\x91\x5b\xaf\x1a\x5e\xad\x90\x65\x61\x67\x94\x1f\xe4\x13\x51\x23\xa5\x0f\x0a\xb6\xb6\x18\x44\x86\xf4\xf9\xfd\x71\xf3\xf8\xbd\xa7\x62\xa8\x4c\xd6\x69\x3d\x33\x94\x1d\x2f\xed\x97\xe7\xab\xd8\x54\xb7\x1c\xe9\x59\x46\xcd\x45\x1d\x3d\x99\xee\x4c\xbd\x71\x24\x53\x8b\x41\x6b\xd6\x9f\x7a\xb5\xb0\xbe\x1a\x6b\x4d\x5c\x89\x64\x50\x6a\x3a\x6f\xc4\x73\xc4\x64\x62\x92\x37\x8a\xcb\xb9\xa3\x9a\xd3\x48\x06\xce\xab\x5b\x18\x44\xce\x5d\x9e\x48\xdb\x27\x2e\xf5\x57\xc0\x04\xbf\x1b\x13\xfc\x63\xfc\xf9\x41\x22\xaa\x88\x70\x95\xb0\x31\x94\x0a\x61\x4b\x50\x00\x89\xe3\xb8\x4c\x61\x26\x85\x63\x99\xca\x82\xd4\x72\x04\x51\x40\x11\x82\x29\x83\xc4\xc5\x10\x51\x47\x10\xae\x4c\xf7\x5a\x9c\xb8\x98\x31\x70\xca\xf0\xe5\x4b\x76\xbb\xd2\xdd\xba\x13\xa4\x92\x11\x08\x99\x94\xd7\x72\x6c\x72\x6b\x3e\x41\xd3\xaa\x54\x60\xb9\x5c\x93\x74\xe7\xf1\x70\x05\xbb\x56\xd7\x6c\x20\xc6\x56\x35\xd9\xc9\xc7\x7a\x45\xd8\xa8\x88\x55\xda\xe9\x24\xd9\xa2\xb8\x76\xd2\xa9\xba\x16\x9e\xc2\x79\x3e\xc6\x52\xbd\x4a\x6e\x2a\x12\xfd\xe1\xba\x10\x2b\xaf\x8c\xb1\x6f\x64\x6a\x24\xb4\x6c\x37\x9b\xa6\xfe\x9c\x4f\x98\x47\x6e\xda\x1b\xa9\xba\xa3\xd7\xdd\x41\x07\x6a\xc3\x4a\x37\xda\x48\xe5\x94\xe5\x6c\xaa\xa2\xd0\x6f\x47\x15\x4b\x33\x95\x1e\x8b\x9c\x45\x4a\xf5\x46\x39\x57\x91\x06\x1d\x59\xf1\x62\x24\x34\xea\x68\xa3\x95\x97\xf0\xec\x72\xaf\x1f\xd1\xea\x95\x52\xb1\x26\xea\x93\x59\x15\x24\x65\x44\x0f\x6e\x09\x47\xce\x5c\x9e\x08\x07\xff\x77\xcf\x6e\x8b\x09\xf6\x31\xfe\xfc\xe0\x52\x62\x03\x20\xb9\x43\x08\x74\x5d\xce\x6c\x22\xb8\x43\x94\x65\x41\xe1\x52\x45\x5d\x8a\x6c\x6a\x52\x68\x9b\x92\x09\x00\x2c\x57\x5a\x02\x0a\x24\x29\x97\xc0\xc4\x9c\x8b\x6b\xeb\x4e\x97\x67\x47\x8c\x0b\x72\x79\x66\xf5\x58\x0a\x21\x64\x4c\x42\x22\x99\xbc\x96\x63\xe3\x9b\x8f\x3b\x55\x73\xe1\xb4\x5b\x29\xba\x12\xad\x52\x6e\x85\xf1\x44\xa1\xde\x97\xa5\x95\x59\xb1\xc7\xb5\x76\x78\x41\xe7\x91\xf6\xa8\x4a\xa3\x5d\x87\xe4\xad\xc8\xd8\x56\x53\xb1\xa9\x37\xc3\x5d\x37\x9b\x30\x8d\x60\xce\x01\xed\xe4\xb2\x50\x25\xd9\xa0\x3e\x77\x0a\xed\x52\x31\xed\x4c\x35\xfa\xbc\xee\x64\x1e\xf5\x69\xa2\x9c\xb1\xbb\x0e\x9d\x4d\xed\x7e\x1c\x17\x82\xa3\x59\xcc\xcb\x39\x95\xda\x48\xe0\xd9\xbc\x11\x0f\x6e\xfa\xe1\xd8\x28\x58\x0f\xb6\x67\x41\x15\xe9\xc3\x41\xb3\x5d\x44\xbd\x48\x3b\xdf\x8f\x45\xf1\x3a\x47\x7a\xb0\x1e\x2f\xf5\xda\x62\x38\x53\xd5\x74\x6e\x14\xca\x74\xc6\xf9\x75\x0d\xed\xe6\x4e\x67\x2e\x4f\x84\xc5\x5f\x71\xcf\xee\xee\x75\x27\x44\x3f\xc6\x9f\x1f\x1c\x0e\x2d\x88\x90\xe5\x5a\x10\x28\x08\x25\xa6\x92\x9b\xb6\x4b\x38\x93\xae\x94\x16\x87\x4c\x71\xa9\xb8\x03\x95\x69\xdb\x2e\x42\xd4\x74\x5c\xea\x3a\x8c\xda\x96\x52\x0a\xf3\x6b\x71\xe2\xf2\xec\x88\x4b\x7e\xf9\x78\xe0\x53\x29\x04\x1c\x73\x02\x05\x22\xe0\x5a\x8e\x8d\x6f\x9d\x3b\x49\xdb\xd2\xbc\x05\xd7\xf2\x5a\x53\x6f\xaa\xa9\x4c\x9a\xee\xc0\xb2\x6b\x94\x52\x99\x1c\x6f\x0a\xa9\xfe\xc4\xad\xcb\xa6\xbd\x98\x13\x1c\xa5\x4e\xb7\xb1\x54\xd1\x9e\x3b\xb7\x54\xc3\x5b\x4f\xc2\x8b\x55\xbf\x30\x98\x57\x92\xed\x95\xd5\x0b\x8e\x7a\x75\x42\x41\xdf\xf2\x2a\x91\xe7\x7c\xa2\x79\x94\x4f\xe4\x64\x3b\x5b\x8d\x2d\xba\xcb\xdc\xbc\xda\x0c\x0e\xbb\x46\x77\xb1\xc8\xad\xfa\x1d\xdf\x31\xda\xa1\x6a\x7a\x34\x37\x47\x5e\xd4\x02\x6b\x59\x8a\x4d\x6b\x29\x0d\x34\x9b\xf5\x68\x9a\xa3\xdc\xd4\x0c\xb1\xca\xa4\xe2\x94\x63\xbd\xe0\x60\xac\xe7\xc6\x28\xa3\x9a\xd5\x4c\xa4\xeb\xcc\xf6\xfb\x1f\x91\x33\x97\x27\xc2\xf4\x74\x7f\x62\x77\xfc\xe9\xbf\x1c\x13\xf7\xc7\x09\xf2\x31\xfe\xfc\xe0\x00\x69\x23\x4e\xa9\x32\xf1\xff\x67\xef\x4d\x7b\x14\x47\x96\xbd\xf1\xf7\xf7\x53\xb4\xe6\x4d\x3f\x12\x73\x0e\xb9\x2f\xf3\xe8\xbe\x30\xc6\x60\x9b\xcd\x80\x01\x9b\x47\x57\x23\xaf\xec\xfb\xce\xd1\xff\xbb\xff\x05\xb5\xb0\x54\x51\xdd\x65\xaa\x6a\x7a\xce\xb9\xa8\xd5\xaa\x2c\x17\x3f\x47\x46\x46\x46\x64\x64\x46\x44\x42\x08\x24\x67\x3c\x64\xde\xe1\x1f\x87\x94\x06\x71\x0c\x7d\x86\x41\x14\xfa\x0c\x33\xe1\x11\x1f\x09\xe0\xfb\x4c\x84\x11\x22\x01\x8a\x7c\x9f\xbc\x35\x27\x6e\x9e\x63\x73\x09\x21\xbe\x79\xa2\xf7\xfc\x14\x02\x0c\xb8\x44\x90\x42\xf0\x96\x8f\x8d\x7f\x36\xde\x49\xaa\x81\x09\x9d\x59\xa9\xa6\x3a\x6d\xe9\x2d\xbd\x65\xd0\x74\x2c\xe1\xbb\x1b\xee\xbb\xa8\x37\x58\x4c\x54\xee\x95\xc9\x60\xb3\x5a\x01\xdc\x2d\xb1\x80\xd5\x77\x1b\xa5\x56\x1f\x5b\x3e\x0e\x96\x39\x16\x4f\x9a\xa1\xdf\xd9\x6d\xbb\xd3\x74\x8d\xa4\x17\xa9\x96\x96\x5a\x46\x0f\xa5\x95\x1e\xe6\xc4\xd9\x0a\x06\xee\x7b\xba\xd7\x5f\xf9\xd9\x79\x1f\x1a\x2b\xaa\x55\x85\xdb\xce\x20\xa2\xee\x47\x48\x2a\xa6\x15\x7a\xe6\x78\xe1\xe0\x94\x92\x8a\x9b\xb8\x10\x87\x51\x6f\x66\xce\x76\xbb\x6e\x3c\x48\xf1\xd1\xa6\xd5\xc8\x80\xb9\xef\xaf\x97\x6c\xc7\x08\xe8\x16\xd3\xfe\x78\x62\x95\xda\xb2\x73\x4c\x94\x78\x65\x4e\x90\xeb\xf3\x89\xff\xcc\x39\x81\x3f\x46\x9e\xbf\xfb\x22\x14\xd0\x93\x24\x08\xa4\x17\xc0\x30\x08\x8f\x81\x84\xd4\xf7\x22\xc0\x04\xf0\x38\x61\x31\x81\x9e\x2f\x11\x0e\x23\xe9\x33\xc1\x28\x20\x08\x01\x2c\x63\x11\xc6\x84\xbf\xb5\x17\x7b\x3b\x3d\x42\x40\x8a\x6e\xef\xc5\x1e\x9f\x1e\xd6\x5d\x52\x70\x41\x10\xe1\x02\xbc\xe5\x62\xe3\x9f\x0d\x77\xe2\x7d\x37\x3f\xb5\x4b\xa3\x85\x1e\x40\x33\x8c\x5a\x8c\xe4\x3b\x85\x30\x2f\x33\x33\x6a\x48\xe6\x7b\xf9\x86\x66\x74\x2a\x71\x3f\xae\xb1\x8a\xd5\xa1\xca\xa4\x97\x6b\x74\x96\x38\x9f\x07\xad\x8a\x39\x27\x2a\x36\xbd\xaa\x3e\xe2\x25\x2b\x53\xed\x2d\x42\x95\x74\x07\xfb\x6d\xfd\xb4\x74\x6a\x9f\x09\x66\xb4\x62\xed\xe2\x3e\x95\x8a\x2a\xbb\x16\x4e\xeb\x96\xcb\x20\x5b\xa7\x26\x39\xe4\x70\xca\x5a\xaa\x2d\xf2\x12\x2b\xd3\x50\xef\xc5\x93\x45\xa3\x32\x55\xfd\xd4\xa2\xe2\x07\xd3\xc5\xde\x5a\x5a\x32\xa5\xef\x40\x49\x1f\xed\xb7\xdd\xe9\x5e\xb1\xd2\x0b\x5b\xb1\x83\xea\x74\x5c\x38\x4e\x89\x57\x72\x27\x14\x74\x5d\x9f\x20\xab\xfc\x27\x4e\x09\xf4\x31\xe2\xfc\x1d\x46\x1c\x23\xc6\x7c\x19\xc0\x90\x45\xa1\xa0\x51\x88\x00\xe2\xe0\x58\xb7\x9f\x00\x01\x09\xa1\x21\x8d\x11\x80\x50\x48\x3f\xf2\x7d\xca\x11\x0c\xa4\x8f\x28\xa3\xf1\x63\xda\xcf\xad\x29\x71\xf3\x18\x5b\x20\x4e\x6e\x87\x3b\x3d\x3f\x95\x84\x08\x89\x04\xa0\xf0\x2d\x0f\x1b\xff\x6c\xb4\xd3\x96\xee\xcd\xd1\x2a\xd0\x5b\xdc\x75\x96\x86\x1a\x14\x75\x73\xab\x74\x1a\xb5\xd0\xd9\x29\xb5\x9e\xcf\x78\x73\xa7\x9b\x8b\x61\x3b\x0e\x4d\x92\xdd\xef\xd7\xcd\xd8\xea\x47\x74\xad\xb2\xa0\xd3\x55\x73\xf1\xbc\xbd\x29\xe9\x25\x2d\x5b\xca\xc1\x69\x77\x33\x4d\x0f\x8c\xfe\x2a\xcd\xcf\xa6\xc4\xd9\x90\x02\xa5\xd4\xdb\xd9\x44\xdd\x65\x8b\xc5\xb5\xb7\xab\x03\x65\x64\x49\xde\x8d\xc6\xb2\x0f\xe7\x03\x63\x31\x71\xa3\x32\xe8\x55\xe7\xfd\xd5\x14\x78\x56\x2e\x5c\x35\x8d\x85\x99\x1a\xc7\x7b\x69\x94\x55\xb3\x3e\xa7\xa2\x5c\xb1\xb6\x56\xb9\x6a\x17\xda\x33\xdb\x76\xf7\x75\x9a\xaa\x1c\x57\x4e\xaf\x24\x4f\x28\xf0\xfa\xc4\x4e\x55\xfe\x13\xa7\x04\xfc\x18\x71\xfe\x1e\x81\x40\x0a\x0f\xb0\x08\x87\x01\xe1\x50\x60\x8f\x08\x80\x63\x49\x78\x10\x02\xe0\xc5\x11\xe6\xa1\xf0\x25\x09\x03\x4c\xc2\x88\x20\xe9\x85\x21\x01\xb1\xc7\x03\x28\x03\x06\xdf\xf2\xb0\x6f\xef\x2b\x09\x2c\xe0\x1b\x13\xe6\xe9\xa9\x04\x50\x12\x0c\x31\x7a\xb3\xda\x19\xfe\xd9\x60\xa7\x54\xd6\xec\x75\xfc\x3e\xd6\x02\xb7\x32\xe8\x64\x53\x8d\xb8\xac\x14\xd2\xfd\xd8\x5d\x35\x70\xd6\x8e\xaa\xd3\x79\x58\xb5\xa6\x22\x1f\xb8\x6e\x6e\xc2\x53\xf9\xa1\xb7\x40\xfd\xde\x74\x92\x1f\x7a\x72\x3d\x2f\x16\x0b\x60\x32\x51\x7a\x25\x83\xe6\xab\x51\x65\x50\x6c\xa6\x57\x7d\x19\x9c\x9c\x09\xf7\x3c\x13\xbb\xa8\x8c\xcb\xfd\xfa\x66\x54\x9c\x10\x4e\x26\xfd\x89\xde\xd9\x2d\xe2\x81\x33\x8a\xa2\x8c\xe1\x84\x9d\x96\xbf\xab\x98\x1b\x7f\xbc\xd8\xa6\xaa\x8d\xd0\x2b\x58\xb1\xe2\xb8\xdd\xdd\x7a\xb0\x2f\x54\x0b\x5a\xca\x76\xfd\x2e\x0e\x4b\x7d\x11\x38\xa0\xb3\x8c\x41\xaa\x32\xb1\x97\xc7\x0b\x52\x33\xaf\xe4\x4e\x28\xfb\xeb\x03\xbb\x7f\x87\x29\xf1\x7e\x07\x1b\x7c\x8c\x38\x7f\x0f\x22\x18\x84\xdc\xf3\x7c\x10\x21\xe4\xc1\x48\xc0\x40\x48\x3f\x84\x1c\x86\xc0\x0f\x3d\x1a\x8a\x30\x0a\x90\x10\x88\x40\x82\x01\xa2\x31\x8b\x41\x08\xa9\x07\x43\xee\x05\x01\xbc\x5d\xed\x8c\xfe\x71\xbb\x4e\x8d\x38\x2e\x86\x7e\xf8\x54\x50\x21\x25\x26\x54\xbe\x59\xec\x0c\xc3\x9f\x3d\xaf\x23\x01\x64\xb3\x0d\xe9\x4d\xa2\x4e\xd0\xf3\x81\xa3\x57\xd7\x9e\xe3\xe2\x45\xc1\x30\x33\xd5\x8d\x19\xfb\x1b\xd0\x9c\x84\xd1\x62\xe3\xa6\xe2\xc9\x66\x51\x0c\x0a\x7b\x6e\xc2\x50\xc3\xb4\x53\x18\xbb\xb5\x92\x87\xf6\x0a\x0e\x66\xf1\x6a\x52\x6e\x94\x60\x1c\xf5\xda\xd6\xea\x64\x25\xdc\x33\x5f\x62\x9b\xee\x6e\x3d\xad\x85\x9c\xb2\x99\xc1\xbd\x6c\x8c\x70\xe4\xc6\xf9\x60\x13\x54\x05\x43\xd3\xfa\x92\x57\x4c\x96\xcb\x41\x20\x0c\x2f\xad\x76\x77\xbd\x70\x16\x2f\xa2\xb4\x87\x79\xae\x17\x17\x95\x61\xb6\x90\xd2\x56\x55\xbc\xcd\xef\xbc\x99\x5a\xa7\xa5\xe2\xa0\x55\x6d\x1c\x33\x24\x32\xaf\xe4\x4e\x28\x9b\xeb\xb3\x89\x7f\x87\x29\xf1\x6e\x2b\x01\xe5\xc7\x88\xf3\xf7\x88\xc5\x94\x44\x1e\x0d\x83\xd8\x93\x88\xc5\x34\x22\x2c\x0c\x01\x65\x4c\x82\xd8\x07\x18\x86\x01\x96\x88\x43\x1e\x06\x20\xf6\xbd\x00\xf8\x28\x26\x10\x46\x82\x48\x46\x11\xbc\x1d\x27\x4e\xff\xb8\xbd\xd3\x2a\xd8\x1b\x21\xb1\x4f\x0f\x05\x64\x80\x60\x2e\xd8\x9b\x95\xce\xf0\xcf\x1e\x4c\xa4\x7c\x68\xcf\x9c\x20\x35\x35\xd7\xce\xc0\x0f\x33\x2d\xaf\x9a\xda\x94\xc2\x0d\x35\xb7\x71\x90\xe5\x73\x65\xb1\xae\xd6\x98\x36\x1c\x1a\x55\xcf\x95\x75\x63\xb1\x4d\xa1\xd1\x7e\xe8\x0f\x52\xb1\xac\x6b\x93\x75\x34\x9e\x16\x27\xe9\xa2\xb9\x6b\x58\x5d\xa6\xa4\x3a\xa9\x66\x4e\x4c\x4f\x89\x13\xee\x99\x8c\xba\x7b\x95\x91\x78\xd4\xea\xb7\x2b\xcb\x99\x46\xcc\xfe\xa2\x30\xdb\x44\xf3\x70\xbc\x2f\xb3\xdd\x66\x6c\xd6\xd7\xe1\x22\xdb\xca\x59\xc1\x0a\x4f\xcd\xdc\xb2\x34\xd2\x47\xd3\x05\x0a\x94\xed\xa4\x3a\x48\xcf\xf6\xb1\xa8\x4e\xca\x95\x4c\x2f\x63\xe4\x15\x8d\x89\x48\x97\xdb\xda\xee\x78\xf0\x91\x79\x25\x71\x42\x59\x5d\x57\x26\xf8\xcf\x9c\x10\xe2\x63\x84\xf9\xbb\xf0\xe2\x18\x00\xc4\x68\xec\x4b\x41\x20\x92\x00\x85\xb1\x0c\x69\x80\x41\x04\x25\xf1\x00\xf4\x42\x3f\xe4\x12\x11\x09\xa2\x98\x0a\x81\x19\xe1\x22\xf4\x65\x28\x22\x0c\xe9\xed\x62\xfb\xf4\x0f\x72\x73\x9b\x55\x08\x2c\x6f\xd7\x2d\x38\x3e\x3d\x9e\x8c\x73\x0c\x24\x81\x10\xbf\x59\xe8\x0c\xfd\xec\xb9\x04\x99\xa7\x15\xb5\x1d\xaf\xdc\x6a\x7d\xa0\x62\x0a\x83\x52\x25\xdf\x98\x64\xe6\x3e\xa4\xa6\x99\x5d\xb7\x8c\xf2\x20\x2a\xaf\xc2\x7e\x3f\xd7\x9a\x72\xbd\x97\x1a\x64\x33\x5a\x31\x68\xb8\xc3\x4a\xba\x19\x99\xd3\x75\x91\xad\xe9\xc4\xa8\x76\xfa\x71\x46\x97\x4b\xd4\x5c\xb8\x0d\xb0\x3e\xdd\xe3\x75\x9e\xbc\x50\x2e\x6c\x77\x4a\x69\xb2\x2b\xa5\x3b\x63\x2a\xbb\x19\x77\x5f\xdc\xfa\x0d\x24\x5a\x7e\x6f\x8b\xab\xfa\x8e\x2f\x80\x60\xeb\x69\xdd\x25\xe1\x22\x5e\x74\x21\xd8\x4d\xa3\xb9\x3f\x32\xe2\x42\xc3\xdb\x4c\x26\x96\x5b\x9e\x95\xd3\xd5\x0c\xea\x17\xc8\x6c\x85\x96\x8a\x93\x5a\x1a\xc7\x98\x91\xcc\x2b\x79\x13\xca\xb2\x71\x25\x51\xff\x0e\x53\xe2\xdd\x75\xf6\x21\xff\x18\x71\xfe\xce\x62\xe2\xf3\x40\x52\xee\x11\xe4\x61\x14\x86\x02\x83\x90\x60\x04\x51\x48\x7d\xdf\x8b\x23\x5f\x22\x04\x29\x16\x11\x01\x10\x78\x04\x61\x42\x29\xc6\x20\x0c\x7d\x20\x7d\xe4\xbf\xe5\x49\xdc\x3c\xbf\x16\x92\xcb\xdb\x65\x95\x9f\x9f\x72\x0c\x20\x21\x84\x80\x37\xeb\x9c\xa1\x9f\xdd\x82\x45\xb2\x18\x9b\x4d\x56\x9d\x95\x96\x28\x9b\x6d\x94\xba\xc5\xe6\x8a\xa5\xe7\x83\x5e\xce\xee\x0f\x94\xea\x54\x2d\xe7\x1a\xfb\x6c\xb8\x30\x17\xf3\x5d\x50\xc1\x66\x5a\x9f\xa2\x40\x5b\xcf\x09\xc6\x79\x2b\x9a\x61\x67\x69\xea\x56\x53\xa4\xf6\x4e\xb8\x2d\xd6\x6a\x8d\x2d\x64\xd5\xee\x43\x02\xf4\x61\x4a\x38\x67\x9e\xc4\x4c\x6f\x55\x72\xb5\xb0\x95\xdd\x44\x05\xd2\x36\xb4\x8c\x6b\xbb\x95\xc1\x7e\xd3\x43\x33\xd1\x33\x26\x19\xb9\xcd\xed\x95\xca\xcc\xaa\xa7\xe3\xb8\x6f\x15\x3d\xad\x96\xcf\x16\xe7\xae\xca\x97\x6d\xb7\x59\xe3\x63\xdb\xb6\x1b\xdc\x1e\x03\x52\x0e\xb0\x5d\x59\x40\xdc\x59\xa8\xf0\x38\x25\x5e\x49\x9b\x50\x26\x93\xd7\xc4\xea\x6f\x3e\x25\xde\xed\x49\x1c\x04\xe4\x23\xc4\xf9\xbb\xf0\x90\x44\x18\x49\x89\x42\x26\x7d\x9f\xc1\x98\x50\x1e\x70\x26\x3c\x4e\xa8\xcf\x62\x1f\x85\x02\x86\x5e\xe8\x8b\x90\x71\x01\x62\x22\x19\xf0\x65\x14\x61\x81\x02\xe9\x85\xf4\x2d\x2b\x71\x53\xe8\x25\x04\x94\xdc\xdc\x6f\x7a\x7e\xca\x04\x87\x92\x70\xc6\xdf\x2c\x73\x86\x7e\x76\xbf\x89\x4c\xa6\xc6\x6e\x54\x87\xd3\x15\xd2\x41\x53\x84\x93\x29\x68\xa1\xd4\x0e\x65\xd0\x72\x55\x6e\x93\x2c\x18\x76\x56\x11\x21\x45\x73\xde\x74\x61\x47\x69\xb4\x32\xf9\x4d\xb5\x6a\x95\x66\x2e\xb3\x2c\x91\xcb\xed\xa6\xd3\x81\x3e\x59\x14\x6a\xc4\xce\xc2\xcd\xc2\x0d\xd3\x69\x23\x75\x2a\x9b\x7c\x9e\x0b\xed\x16\x26\x2b\x9e\x19\x58\xcb\xea\x72\x94\x25\x15\x4a\xd2\xb6\x3d\x69\x74\x32\x4a\xb3\xa1\x8e\xd4\x61\xba\x92\x92\x76\x67\x86\xba\x65\x7d\x3f\x2c\xb8\xb2\xda\xa1\xaa\x62\x6c\xc3\x9a\xe3\x2f\xd2\x4e\xd0\x1c\x6b\x3e\x36\x5d\x33\x4e\x67\x07\xb2\x00\xca\xa5\x49\x8b\x56\x84\x7d\x9c\x12\xaf\x64\x4d\x28\xc3\xeb\x88\x8e\xe3\xe7\x6f\x3e\x25\xde\x6f\x25\xe8\xc7\x88\xf3\x77\x8f\x11\x2f\x86\x01\x10\xb1\x4f\x43\x24\x3c\x3f\x08\x61\x1c\xc8\xd0\x8b\x44\x10\xf8\xd0\x8f\x03\xe9\xfb\x51\x00\x7d\xee\x13\xce\x23\x48\xe2\xc0\x43\x81\xef\x85\x81\x47\x24\xe0\x6f\x65\x4d\xbc\x21\xf4\x08\xb0\x37\x26\xcc\xd3\x53\x46\x08\x22\x14\x48\xf2\x66\x95\x33\xf4\xb3\xce\x35\x6b\x17\x44\xa0\x5a\xcb\xb0\x50\x58\x97\x75\x31\xf6\x58\x69\xb7\x5d\x8b\x11\xe7\x99\x25\xaf\x61\xd2\x48\x17\x8a\xc5\x79\x30\x35\x33\x22\x44\x9d\xd0\x93\x9e\xd3\xaf\x6d\xc1\xc8\x4b\xad\xf2\xd4\x18\x67\x2d\x4d\x6b\xf9\x98\xc7\xfd\xf6\xae\x5c\xdd\x59\x1b\xab\x57\xd5\xd6\x67\x56\xe2\x3c\x09\x7b\xd1\x6f\x0c\x5b\xe6\xde\xd9\x3b\xd9\xbc\xb6\xe2\x6d\x47\x94\x4b\x24\x8f\xbb\x4e\xc9\xec\xd8\xb3\x11\x9c\x90\xd9\x5a\x2b\xc5\x3e\xcb\xeb\x6a\x6d\xd0\xec\x8d\x33\xc1\x34\xea\x6c\xa8\xdf\x5d\xbb\xa5\xe9\xc6\x44\x7e\x78\xd0\x68\x78\x08\xfd\x7a\xc6\x6a\x36\xb2\xfd\xcd\xfc\x28\xf8\xaf\x24\x4d\x28\x9d\x57\x6f\xdb\xfa\x9b\x4f\x89\xf7\xfb\x12\xe4\x63\xc4\xf9\x3b\x08\x20\xf1\x08\xa3\x31\x03\x00\x40\x0c\xb0\x47\x19\x8b\xa3\x00\xd2\x18\x05\x7e\x10\x7a\x88\x7b\x7e\x80\x49\x24\x03\xe1\x53\xe8\x0b\x21\x29\xf1\x50\x2c\x7d\x0c\x62\xe6\xdf\xbe\x71\x82\xfe\x41\x6e\x1e\x5e\x4b\x8c\xa1\xbc\xb9\x1b\xf5\xfc\x94\x01\x88\x24\x25\x08\xbe\x59\xe4\x0c\xfd\xac\x7b\xbd\xd9\x34\xa6\x79\x07\x29\x8a\xb6\xa9\x0c\xdb\x6b\x9e\x71\x76\x3b\x81\x7a\xd1\x7c\x03\x58\xd0\x83\x79\xd2\x6b\xd6\x7b\x29\xbf\x64\x79\xdb\x35\x0d\x96\x6e\x18\x94\xea\xda\x48\xe0\x45\x7d\x3d\x19\x4c\x31\x52\x61\x3d\xad\x18\x1d\xdf\x0f\x96\xed\x96\xd7\x5a\x37\xb6\x65\xa4\x9c\x72\x26\x9c\xb3\x21\x1d\x8a\xa8\xe4\xaf\x8b\xe6\xb2\x92\x99\xd8\xea\x7a\x32\x1f\x6a\x85\x6d\x85\x75\xa6\xe3\x85\x1a\x2d\xfa\xe3\x14\x54\x61\x5a\xcf\x83\x35\x9c\x87\x88\x4f\x2a\x3c\xd5\x6c\xd5\xb5\xbc\x98\x8b\x38\xa8\xe4\xdc\x82\x18\xe0\x76\x38\x1d\x36\xfc\xbd\x11\xc6\xc6\x76\x50\xf6\x32\x5e\xe1\x38\x0b\x5e\xc9\x99\x50\xe2\xeb\xb3\xeb\xe3\xe7\x6f\x3e\x25\xde\xbf\x70\xc2\x1f\x23\xce\xdf\x01\x96\xa1\xc4\x00\x07\x08\x04\xd2\xa3\x02\x08\x14\x43\x1a\x13\xc1\x69\x24\xc8\xb1\xec\x6c\x44\xc2\x00\x81\xc8\x43\x98\x0b\xc6\x02\x2a\x43\x2a\x79\x10\x60\x22\x3d\x18\xbe\x31\x25\x6e\x47\x6c\x48\x22\xe4\x4d\xef\xfa\xe9\x21\xa5\x02\x13\xca\x89\x78\xb3\xc6\x19\xfc\xd9\x84\x89\x4d\x25\x1c\x6c\x2c\x35\x6b\x4e\x5d\x55\x15\x4d\x69\x84\x51\xb7\xa4\x6f\xf6\x03\xac\x66\x67\x06\xee\x8e\xb6\x6d\xd8\x8e\x4b\x65\x73\x12\xe6\xe2\x75\xb8\x5f\x6e\xe7\xae\x6e\xc9\xed\x3e\x9c\xf9\x69\x39\x0d\x0a\x93\xae\xe1\xf4\xec\xf1\xb2\xb5\x4f\xd5\xb7\x16\x9a\xec\x68\x06\x9f\x2a\xeb\xb7\xce\x3c\x89\xdc\xa0\xd5\x28\xef\x72\xa9\x0d\xe3\x35\x3a\x4e\xe9\x9d\x6c\x39\xf2\x87\x74\x31\x6e\x22\x77\x98\x59\xec\xf1\xb6\x68\xcf\x32\xa5\xea\xa2\xaa\x2d\x53\xf9\x56\x49\x36\x96\x5a\x38\x1f\xb8\xa3\x91\x41\x9b\xba\x3b\x59\xd9\x78\x6f\x0d\xdd\x69\x51\xad\xec\x86\xb3\xfe\x0c\x05\xbd\xda\x31\x98\x43\x79\x25\x61\x42\x09\xae\x8f\xe9\x8e\x9f\xff\xb8\x09\x81\x3e\x46\x98\xbf\xd3\x88\x46\x42\x62\x1f\xc4\x12\x70\xe1\x71\xce\x00\x8e\x19\x60\x42\x12\x40\x43\x44\x42\x44\x10\xe1\xe1\xc1\x5b\xf7\x01\x88\x05\xa4\x21\x82\xc8\x8f\x62\x5f\x40\xc9\xe8\x5b\x45\x09\xf0\xcd\x3d\x56\xc9\x00\xe4\xb7\xa7\xcb\xd3\x53\x0a\x29\x96\x0c\x70\xfa\x66\x89\x33\xf8\xb3\xce\x35\xa4\x51\xcf\x5e\x58\x03\xbd\x37\x0e\x3b\x16\xca\x4c\x86\x8a\x53\xb7\xeb\xd5\x41\x5c\x25\xed\x85\x92\xca\x38\x75\x6d\xce\x79\xa7\xdd\x6e\xe5\xea\xfa\x2e\xe8\x29\x56\x64\x8c\x80\xe2\x45\xdd\x59\xca\x99\xd7\xfc\x38\x13\x23\xb7\xb5\x44\x93\xd1\x3e\xae\x8e\x4b\xf5\x71\xc9\x9b\x9e\x3c\x89\xd6\xd9\x7a\x3e\x20\x16\x9e\xa4\x32\x66\xcf\x5c\x3b\x8e\x11\xf7\xd3\x51\xb3\x6a\xe5\x60\xad\x66\xcc\xc7\x1a\x1a\xc7\x0e\xf0\x88\xc9\x5b\xb9\x5d\x7d\x9e\xb5\xf7\xcd\x99\x57\x4c\x85\x9b\xfc\x7c\x09\xfb\x6a\x7d\xd6\xe6\xe1\xc0\x8a\x1a\x59\x29\xbc\x7a\xa1\xd8\x2e\xc3\xb0\xaa\xbb\x93\x6a\xf7\x38\x0b\x5e\xc9\x97\x50\xda\xaf\x8a\xd5\xdf\x7c\x4a\xbc\x7f\xd9\x04\x3f\x46\x9c\xbf\x33\xe4\x85\xc4\xc7\x9e\xe7\x07\xc8\x93\x38\x3a\xee\x79\x0a\xc9\x44\xc4\x20\x24\x21\x8c\x20\xf5\x62\x18\xc6\x3e\xa7\x38\xa6\x3e\x07\x44\x04\x00\xfa\x11\x8d\x7d\x1c\x49\xff\xad\x60\x0e\x7c\xf3\xe4\x5a\x72\xc8\x7e\xe2\x29\xe1\x88\x10\x46\x00\x7a\xb3\xc4\x19\xfc\xd9\xf8\x26\x54\x58\xd6\xf7\xb3\xf9\x66\x36\x48\xa9\x0d\xcd\x1d\x4e\x68\x37\x57\xd6\xbb\xad\xb5\x1e\x2f\xa1\x05\x97\x9b\x7a\x49\xf1\x69\xbc\x48\x8d\x28\xe7\xa5\x1c\xf5\xa1\x11\xf5\xf0\x5e\xcf\x49\x4d\x19\x2d\x8a\xb6\x20\x43\xee\xfa\x4a\xa3\xae\xa7\x79\x2e\xbd\xd9\x8d\x6a\x33\x29\x4e\x57\xc6\xb7\xce\xa4\x74\x6a\x6c\xa7\x9e\x6d\x29\x65\xb3\x8e\x9d\x78\x99\x77\x72\x75\x77\xae\x99\xa0\xd4\x8d\xcb\x2c\x5f\x86\x95\x88\xa6\x5c\xcd\x62\x40\xa6\x96\x70\x44\xd4\xac\xe7\xfb\xb9\xa6\xba\xd9\x7a\x36\x6c\x1a\x6b\x95\xb4\xd4\x34\x1b\xb3\xd1\x7c\x5e\xa9\xaf\x27\xe9\x8a\x4f\x47\x83\x63\x6d\x58\xe5\xb5\x74\x09\xe7\xfa\x98\xee\xf8\xf9\x8f\x9b\x12\xe0\x63\xc4\xf9\x3b\x93\x31\xe2\x11\x47\xbe\xe4\x31\x0f\x7c\xee\xc7\xe1\xe1\x87\x10\x00\x88\x7c\xee\x7b\x40\x80\x10\x87\x51\x00\x05\x64\x42\x08\x22\x18\x62\x3e\x8c\xa0\xef\x85\x88\x46\x1e\x7d\x20\xfe\xf5\x65\xd3\x6d\x5f\x41\x80\xc7\xac\xbe\x37\x9f\x12\x24\x89\x64\x1c\xc9\x37\x2b\x9c\xc1\x9f\xdd\x6f\x42\xe3\x5d\x3c\x2e\xd0\x18\xef\xf0\x5a\xc6\x78\x5f\x55\xea\x4b\x3e\x31\xb2\x36\x5e\xe4\x33\x9e\xd1\x35\xdc\xd1\x22\xca\x33\x30\x64\xc3\xa9\x6c\x50\x56\xab\x4f\x82\x1a\x69\x4f\x1d\xa7\xbd\x48\x77\x86\xc1\x38\xdf\xd4\xb5\x7a\x33\x97\x6b\xb0\x62\xaf\x20\xe3\x4d\x54\x2c\xba\xa7\xaa\x7f\xad\xb3\x21\x95\xa9\x7e\x7f\xd1\x2a\xb0\x35\xeb\x80\x8a\x5b\xca\x6d\xed\x09\x4c\xb9\x93\x4e\x0f\xed\xb2\xf5\xbe\xd3\x35\x05\x2b\x43\x65\x6b\x56\xd6\x5a\x00\x87\xdb\x32\x1a\x4e\x0d\x51\x8f\x3a\x79\x97\x2d\xd7\x8a\xb7\x98\xae\x48\xa8\x6f\x47\xc5\x66\x38\xd7\x06\xfd\xfa\xd0\x70\xd7\xf1\x43\x55\xc1\xd7\xb2\x25\x9a\xd7\x07\x75\xc7\xcf\x7f\xda\x94\x90\x1f\x23\xcd\xdf\x99\x17\x87\x10\x63\x2f\xe6\x38\x8e\xfd\x90\x47\x21\x65\x01\x62\x34\x64\x21\xf6\x79\x84\x39\xf1\x41\x08\x39\xa0\x30\x08\x61\x10\x8b\x48\x46\xa1\xcf\x99\x1f\xc5\x41\xe8\x13\xee\xbf\x65\x24\x6e\xfb\x0a\x42\x8a\xb7\x66\xc4\xe3\x53\x2c\x18\x25\x1c\x50\xf6\x66\x7d\x33\xf8\xb3\x75\x6b\xd0\x5c\x6a\xfb\x39\xb6\xd2\x6b\x87\x37\x7d\xb5\x1d\xfa\xf6\x32\x55\x06\x8b\x72\x6e\xd3\x08\x40\x90\xaa\x8c\x97\x4b\xb4\x5e\xef\xfd\x1a\x37\xa0\x57\x69\xa4\xf4\xe5\x7e\x0d\xdd\xdd\xa4\xd2\x4a\x95\x1b\xce\x64\xd1\xd7\x36\xac\xd6\xce\x75\x37\xcb\x0a\xb4\x4a\x63\xa5\xa6\x2c\x57\xa7\x19\xd1\x3c\xcf\xbd\x76\xaa\xc5\xd6\xaa\x83\x8c\x36\xca\x93\xda\x78\xd3\x98\xab\xf6\xda\xd8\x54\x98\x5d\x9a\xae\x10\x4c\xd5\x51\xc3\xe9\xce\x8a\x85\x96\xad\xe7\x95\x8d\x43\x77\x20\xd7\x6c\x68\xfd\x6c\x48\xdd\x6c\xcf\xe7\x9b\x6e\xda\x2f\xd7\xb7\x6d\x06\x98\x5b\x02\x59\x6a\xc9\x75\xaf\x53\x3f\xce\x88\xd7\x72\x25\xea\xd7\x05\xc4\x8f\x9f\xff\xb4\x19\x21\x3e\x46\x9a\xbf\x83\xc0\xf7\x68\xc8\x88\x60\x3e\x10\x20\x40\x40\x12\x12\x8a\x08\x01\x2e\x42\x0f\x50\x41\x49\xe4\x93\x90\x09\x1f\x04\x84\x78\xdc\xe3\x20\x06\x2c\x8c\x7d\x1f\x89\x00\x88\xe3\x35\x5c\xe4\xf8\xef\x15\xe1\xbe\x79\x72\x2d\xa5\xa4\xb7\xef\x5e\x79\x7e\x8a\x09\xa6\x92\x63\x81\xdf\xac\x6e\x06\x7f\x76\x03\x76\xb3\x63\x4e\xab\x9e\x5f\x18\x59\x55\x6d\xd8\x2e\xe9\x44\xe5\x49\xae\xdb\x60\x00\x4e\x16\xa5\x5a\x21\x1a\x67\x37\x7e\xbc\xda\xf5\x95\x8e\xd9\x4e\x77\x9a\x7a\x97\x68\xf9\x49\xcd\xe9\x6f\x33\x43\xd3\xe9\x84\x3e\x9b\x50\x1a\xd1\xa2\x95\x11\xe9\xb9\xb1\x74\x52\xbd\x4c\x69\xd4\x39\x5d\x33\xd1\x3c\xf3\x24\x68\xdc\x05\xd9\x5a\x3b\x55\x89\x23\x85\xf4\x74\x9c\xb7\x4b\x7e\x9e\x05\x33\x33\xaf\x6d\xc1\x4c\xa5\x1c\x41\xa6\xfb\xf6\xa6\x6a\x35\x40\x77\x5f\xa9\x82\xa5\xb6\x99\x84\xa0\x55\xc8\x67\xe9\xa0\xc4\x8a\x9b\xa6\x5e\x2c\xf8\x46\x65\x9f\x19\xf9\x69\x59\x37\x36\xda\x84\x64\x8e\x72\xff\x5a\xa6\x44\xed\xba\x80\xf8\xf1\xf3\x37\x9f\x11\xe4\xbd\x33\x82\x7f\x8c\x34\x7f\x8f\x28\xf3\x25\x96\x28\x06\x92\x48\x14\x13\x20\x08\x17\xd2\x63\x31\x8f\x22\x0f\x23\x4e\x42\x26\x25\x0c\x24\x14\xa1\xa4\x40\x32\x00\x64\x24\x05\x8d\xfd\x88\x05\x20\x04\x6f\x3a\x12\x37\xac\x00\xf9\x27\x80\x90\x88\x1b\x9e\xf7\xd9\x53\x0c\x00\x23\x9c\x43\xf0\x66\x6d\xb3\x9f\x4d\xa7\x4b\x35\xe7\x03\x5a\xdc\x0c\xcd\x22\x50\xb5\xc8\x9c\xae\xe3\xd5\x64\x17\x96\xbd\xb6\x6e\xe6\xcb\xc3\xea\xb0\xa3\x46\xa3\x5c\x2a\xe5\x2b\xc0\x9c\x37\x50\x66\x4c\x3c\xbb\xef\x96\x8a\xd3\x6c\x1c\xc7\x46\x3a\x62\x7a\x16\xe7\xeb\x35\x55\x33\x27\x44\x99\xbb\xcb\x9e\x24\x95\xd6\xec\x14\xca\xd1\x3c\x4f\xbb\xa6\x7a\xa5\x3a\xc5\xb6\x6a\xec\x2a\x8d\xbe\x68\x8e\xca\xf9\x79\x77\x81\xd4\x94\xe1\xf4\x25\x41\xd3\x31\x9e\x59\x4d\x43\x71\x9c\x2d\x73\x31\x17\x73\xab\xb7\xa8\xa6\xad\x56\xad\xe8\xed\xb7\x25\x75\x58\xdc\x88\x22\x6a\x0c\x8c\x50\x4e\x18\x89\x8c\xe9\xd0\x6b\x0e\xc4\xc3\x75\xdb\xaf\xe5\x49\x14\xae\x53\x4c\x8f\x9f\xbf\xf9\x84\x78\xb7\x89\x60\x1f\x23\xcc\xdf\x63\x1a\xcb\x00\xc6\x01\x07\x80\x72\x18\x7a\x34\x8c\x41\xc8\x22\x10\x05\x51\xe8\xf9\x5c\xc4\x91\x80\x11\x8b\x19\x03\x94\x44\x04\x53\x14\x4b\xee\xe1\x18\x04\x31\x0e\x69\xfc\x66\x86\x29\xbe\x71\x0a\x47\xfe\x09\x10\xbc\x3d\x1d\x1e\x9e\x21\xca\x99\x14\x00\xf3\x37\x8b\x9a\xfd\x74\xdd\x70\x87\x6e\xe2\xed\x26\xe3\xe8\x9e\x13\x67\x5b\xa4\xb2\x5f\xce\x70\x3f\xd5\x89\x7c\xe4\xe6\xec\x41\xb9\x9e\x72\x26\xe9\xac\x65\x35\x05\x2e\xef\x24\x1f\xa4\x41\x0e\x29\x2d\x1d\x59\x16\xeb\x67\xb6\x93\xd0\x70\x4a\x9d\xfe\xa8\x56\x34\x37\xdd\xec\xb2\x22\x96\xd5\x76\x27\x16\xa7\xad\xd7\xe6\xd9\x60\x96\x45\x15\x29\x4b\x55\x5d\x44\x43\xa2\x1b\x8b\x02\x59\x85\x33\x67\x57\xac\xce\x82\xb9\x97\xef\x07\x8a\xde\xac\x37\xca\x02\xd2\xce\x3c\xb7\x71\x82\xf1\x4a\x6f\xc0\x55\x63\x9a\x9f\xd9\x8d\xa5\x6f\xa4\x77\x6d\x0b\xee\xdc\x75\x55\x1b\xf7\x94\x55\x29\x46\xdd\xde\xa6\xe7\x2d\x8f\xf5\x60\x95\xd7\x32\x24\xcc\xeb\x7a\xb0\xc7\xcf\x7f\xda\x64\xa0\x1f\x23\xc8\xdf\x03\xc4\x00\x94\x10\xa2\x88\x87\xd0\xc3\x80\xfb\xdc\x67\x9e\x20\xd8\x0b\x29\x8b\x43\x8e\x7d\x0a\x63\x3f\x0c\x50\xc4\x30\x8d\x23\xee\x83\x38\x08\x84\xef\x45\x84\x45\x92\x40\xfe\x46\x0c\x07\xbe\x71\x60\x4d\xfe\x09\x30\x7d\xc3\x38\x1c\x1e\x1e\x4f\xfd\x20\xe1\x44\x60\x46\xde\x2c\x68\xf6\xb3\x9b\x4c\xc2\xec\xe4\x6b\xda\x2a\xae\x4d\x36\x11\x5e\xce\xba\xd9\x79\xd3\x97\x01\x6f\xc4\xeb\xa0\x38\x2a\xc7\x94\x67\xc5\xae\x38\x1f\xf8\xd3\xaa\xb3\xdb\xcb\x9e\x8b\xe6\x7a\x77\xb3\x6a\xac\x2b\xb9\x55\x51\x63\xa3\xcc\xda\xae\x10\xd6\x35\x52\xce\xb6\x80\x4c\x1a\xc0\xe5\xaa\xb8\x38\xbb\x0c\xbe\x71\xb6\x8a\x1f\xb0\x75\x25\x5d\xa8\x6d\x37\x6d\xb0\x1b\x9b\xa5\xd2\xbc\xd0\x98\x56\xea\x31\x6d\x75\xfd\x70\x50\x1e\x80\xa2\x51\x49\xef\xdb\xdb\x4c\x6a\x16\x39\xdc\x73\xf3\x60\x8f\x9d\x51\x6e\xb3\x1d\xcd\x31\xb1\xe6\xdb\x6e\x73\x27\xea\xb5\xfd\xb0\x51\xca\xf7\xbb\x76\xb1\x15\xe1\x5e\x6a\xf8\x20\xd5\xaf\xa5\x47\xe8\xff\x8e\xc7\xd5\xef\x8e\xe0\x20\x1f\x23\xcb\xdf\x31\x81\x71\x2c\x03\x22\x85\x2f\x01\x67\xb1\x88\x11\xf4\x22\x8f\x0b\x0f\x63\x3f\x00\x01\xc3\xd2\xf3\x69\x10\x4b\xc1\xbc\xd0\x0f\x50\x28\x42\x40\x42\x89\x7c\xea\xc9\x90\x85\x6f\x95\xa9\xc1\x37\x4e\xab\xc9\x3f\x01\x45\xfc\xd6\xd9\xdc\xd9\xd3\xb3\x7b\xea\xde\x3e\xad\xfe\xa9\x09\xb1\xaf\xc6\xa9\xa0\xee\xae\xaa\xe1\xba\xbf\xcb\xaf\xa6\x64\xb2\x5f\x2b\xdb\xfe\x68\xee\x58\xa3\xfc\xdc\xdf\x2c\xfb\x55\xbb\x5d\x80\xb3\xd0\x8f\xeb\x29\x27\x8a\x49\xce\x71\x0c\x1b\x0d\x02\xe8\x04\xf1\x7e\x5c\x81\x8a\x6b\x49\xb3\xbc\xca\xaa\x06\x34\x73\x8e\x3e\x1d\x37\xa4\x71\x32\x10\x8d\x33\xf7\xc1\x10\xb9\x48\xd7\xf6\x26\x48\x93\x5c\x45\xa4\xcb\xf9\x34\xc1\x1b\x5b\x1b\xef\xa0\xda\x4a\xaf\x03\x1d\xf5\x83\x79\x75\xb0\xf7\xfd\xa0\x9f\xca\xc5\x2c\x1b\x77\xc6\x24\x57\xb5\xf3\xa6\x33\xc4\x8b\xd4\x36\x33\xdb\x65\xc6\xa9\xd5\x5a\xb3\x34\x77\x33\x9b\x5b\xf6\xdc\xd2\xd2\x0f\x06\xe8\xb5\xe4\x88\xec\xbf\xe3\xd9\xdc\xfb\x8b\x5e\x7e\x8c\x30\x7f\x8f\x43\x89\x98\x08\x21\x0b\x39\x05\xd0\x67\x91\xcf\x25\x65\x3e\xe3\x94\xf9\x48\xc4\x11\xc1\x41\x44\x3d\x06\x20\xf0\x39\x8b\x38\x67\xa1\x84\x31\x03\x11\x8d\xa2\x90\xfb\x6f\x5c\x3f\x44\xff\x40\x37\x0e\xdf\xc8\x3f\x01\xa3\x90\xdf\x70\xb7\x1f\x9f\xd2\xcb\x9a\x97\x6f\x39\xd4\x3f\xbb\x62\x42\x75\xaf\x9c\x5b\x86\xd5\x3c\x62\x78\xd8\x5a\x8e\x9b\xf3\x82\x45\xb3\xfb\xe1\xb4\xa3\x15\xc3\x55\x88\x50\x4d\x76\x68\xc4\x9d\xc5\x2c\xdb\xce\x57\x33\x1a\x74\x17\x93\xa5\x31\xaf\x39\x83\x0d\xdf\xb2\x74\x50\xb0\x42\xb4\xaf\xa8\x99\xd5\x9e\xeb\xa8\x36\xac\x4d\xea\x79\xf7\x14\xd0\xd4\x38\x93\x51\x6a\x8d\xd7\xda\xba\x54\xd1\xc4\x60\x97\x5d\xe0\xbc\xbf\x82\xdd\xc9\x4a\x04\xa3\xc9\x66\x03\x0d\xbe\x9d\xb9\xf9\x8a\xbf\x04\xed\x09\x98\xb4\x95\x42\x96\x36\x60\x6d\x5b\xde\x89\xc9\xba\x9f\x22\x95\x7e\x89\xcc\x8d\x0c\xb0\xd2\x2a\x0e\xaa\xa9\xae\x5a\x54\xe6\x25\x22\x3b\xc7\xaa\x4d\xca\x6b\xc9\x11\x2f\xef\x32\x55\xfe\x03\x27\x04\xfa\x18\x61\xfe\xce\x70\x28\x45\x4c\x31\x8b\xa2\x03\x94\x8f\xb8\x4f\x7d\x21\x63\x84\xbd\x98\x62\x08\x7d\x4e\x99\xf4\x10\x89\xbd\x18\x12\x80\xbd\x10\xf8\x14\xf9\x0c\x63\x1f\x70\x3f\x92\x07\x99\x07\xc7\x7f\xaf\x4c\x88\xdb\x8b\x22\xce\xd0\xad\xfb\xb8\xce\x9e\x9e\xf2\xe7\xde\x98\x0f\x3f\xb9\xdf\x6a\xb5\xfb\xb0\xbc\xa2\x13\xe0\x9b\xbc\x45\xc6\xbb\xca\xba\xb1\xcd\xe3\xe6\x74\x32\x48\xad\x73\x4a\x65\xa9\xc2\x02\x2a\xf1\x0c\x67\xed\x55\xbb\xa6\xcf\x65\x23\x74\x0a\xbe\x5d\xe8\x05\xc3\xb8\xd2\xdf\x71\xe4\xb6\x73\x66\x63\x60\x5a\xcd\xa0\x60\xd3\xee\x72\x3d\x99\x8f\xe0\xe9\x50\xee\x61\xe5\x64\x3c\xff\xa7\x3c\x1c\xa2\x9d\xda\x1b\xc5\xaa\x3e\xca\x2d\xde\xcb\xee\x48\xa9\x4f\x8b\x72\xa9\x34\xb7\x83\xe5\x36\x8b\x9d\x7a\x65\x8a\x7b\xcb\x6d\x7d\xad\x8d\x4a\x4c\x69\x0c\x36\x99\x3a\xd1\x6a\xe3\x75\xaa\xb8\x5c\xa6\x77\xc1\x3e\xbd\x15\xe9\xd4\x30\x97\x11\x60\x3e\x6e\x6e\x79\x1f\x95\xe6\x23\x24\xb5\xe9\x6a\xd1\xa8\xa5\x3a\x6b\xf9\x70\x5a\xfd\x5a\xde\xc4\xeb\x9f\xbf\xf9\x6c\x01\xef\x3e\xb4\xfb\x18\x49\x3f\xbc\xf1\x59\xde\xa1\xe4\xe0\x1f\x00\xfe\x03\xc0\x6f\x00\xfc\x71\xfc\x77\x53\xa2\x05\x62\xec\xf6\x6c\x78\x7a\x7a\x3a\x75\x7b\xb7\xbc\x3f\x90\xf4\x57\x0f\xcd\xed\x4f\xc6\x29\xf4\xc8\x2e\xbd\xab\x17\x32\x3c\x3b\xce\x4a\x1d\x81\x6d\x3f\x93\x5a\x80\xce\x72\xb1\x31\x36\x7b\xe8\x84\xf5\x96\xeb\x65\x4c\x2f\x77\x5c\x69\xbd\x96\xef\xf0\xfa\xe7\x49\x94\x6f\x19\x86\x5f\xf9\x73\x2d\xca\xff\xf5\x5f\xff\xf8\xc7\x7f\xfd\xe3\x1f\xdf\xb2\xde\xd2\xfb\x16\x4f\xe6\xdf\xca\xde\x28\xfa\xe3\x59\xaa\x27\xd3\x68\xee\x2d\x7b\x93\xf1\x9f\x53\x6f\xbe\xec\x05\xbd\xa9\x37\x5e\x2e\xfe\xef\x37\x7b\x37\x8d\xfe\xf8\x66\x2b\x99\xa2\xf6\x2d\xab\xd8\xca\xff\xfd\x56\x0f\xba\xd1\xc8\xfb\xe3\xdb\x74\xe5\x0f\x7b\xc1\xff\xfd\x56\xd9\x8c\xa3\xf9\x1f\xdf\x0e\xe0\xff\xf5\xea\x84\x79\x1d\xfa\x7c\xfe\x20\x06\xa5\xc4\x00\x48\x48\xf1\xef\xdf\xe0\x8d\x89\xf7\x03\x1c\xf4\xbc\x2f\x44\xa0\xa0\x3c\x31\x0e\x3e\xe0\x60\x02\x30\xe0\x84\x32\x98\x18\x87\xfc\xfe\x0d\x11\x09\x81\x80\x80\x23\x46\x13\xe3\xd0\x03\x0e\x11\x10\x43\x2c\x25\x93\x89\x71\xd8\x35\x0e\x4a\x86\xc3\x8f\xc9\x20\x14\x0a\xc8\x11\xe3\xf8\xf7\x6f\x38\x19\x8e\xf8\xfd\x1b\xc2\x0c\x21\x8c\x00\xc5\x9c\x27\xa6\x47\x5e\xe3\x24\xa4\x07\x1e\x3c\x42\x0c\x25\x12\x08\x0b\x20\x60\x62\x82\x0e\x2b\x83\x4b\x20\x92\x10\x08\x5d\x00\xa1\xe4\x40\xf8\x1a\x28\x69\xd7\x0e\x42\x8d\x38\xc3\x18\x71\xc0\x05\x4d\x0e\x44\xaf\x81\x92\x76\xed\x20\xd6\x08\x63\x2c\x30\xc0\x44\xc8\xdf\xbf\xd1\x84\x40\x07\x09\x84\x12\x10\x8c\x31\x83\x12\x27\x07\x12\xa7\x0d\x39\x21\x24\x4f\x0e\x24\x8f\x39\x26\xe4\xa0\x8c\x20\x03\x30\x31\x10\x02\x27\x20\xca\xee\xa0\x08\xc1\x13\x90\xe4\x77\xf0\x08\x1d\x44\x10\x30\x48\x05\xc1\x04\x83\xe4\x72\x84\xf0\x35\x50\x52\x8a\x0e\x92\x0d\xa0\x60\x98\x30\x0e\x40\x72\xf5\x88\x0e\x9a\x5e\x72\xca\x04\x91\x92\x1f\x66\x1e\x4b\x08\xc4\x9e\x80\x28\xc0\xe2\x1e\x8a\x0e\xb6\x50\x62\xc4\x31\xc5\x88\x1c\xe4\x3c\x29\x45\xe2\x1a\x28\x29\x45\x07\x2b\x76\x98\x1b\x82\x32\x0a\x51\x72\x55\x8b\xc1\x35\x10\x4f\x08\x74\xb0\xf3\x82\x30\x81\xa9\xe4\xe2\x30\x86\x49\x81\xd0\x35\x50\xd2\xae\xe1\x63\xf6\x00\x16\x82\x61\x40\x0f\x1c\x13\x09\x81\xc8\x35\x90\x4c\x08\x74\x90\x6c\xce\x80\xc4\x8c\x61\x74\xa0\x2f\x29\x45\xec\x1a\x28\x29\x45\xfc\x04\xc4\xf1\x3d\x3c\x12\xd7\x40\x49\x29\x92\xa7\xcd\x67\x2a\x0f\xf4\x25\x04\x3a\x66\x1e\x1e\x81\x38\x00\xe0\x0e\x1e\x91\x83\x64\x33\x4e\x01\xe6\x48\xb0\x43\x2b\x21\x8f\x08\x7a\xbe\xd9\x9f\x41\x4c\x92\x4b\x36\xc1\xd7\x40\x49\xbb\x46\x4e\x40\x94\x90\xe4\x6a\xe4\x40\xc3\x25\x50\x52\x1e\xb1\xe7\x9b\xde\x25\x01\xe4\x20\x0c\x20\x21\x12\x3f\x5d\x90\xcd\xf8\xd1\x2d\x4a\x8a\x24\x4e\xd7\x0a\x4b\x72\x74\x8c\x92\x22\xc9\xe7\xcb\x58\x25\x82\x47\xd7\x28\x21\x12\x05\xa7\x2b\x2c\x89\x60\xc9\x65\x89\xc2\x6b\xa0\xc4\x24\xa1\xd3\x0d\x82\x9c\x1e\xfd\xac\xa4\x0e\x1b\x7e\x46\x62\x90\x1d\x69\x4a\x8a\x44\x9e\x6f\x70\x93\x00\x1d\x7c\xad\xc4\x48\xf4\xf9\x0c\x00\x21\x79\xf0\x92\x12\x23\xb1\xd3\x6d\x41\x94\x1d\xbc\x9b\xc4\x48\xfc\x74\xc7\x8a\xc0\xe2\x1e\x3e\x89\x67\xa4\x83\x18\xdc\x43\x93\x3c\x21\x31\x7a\x0f\x9f\x18\x78\x42\x82\x00\xb0\x7b\xc6\xee\x38\xd1\x1e\x91\x08\xbf\x47\x32\x19\x3a\x21\x09\x71\x8f\x64\x32\xfc\x8c\x04\x91\x64\x77\x70\xfc\x18\xf3\xfc\x70\xab\x08\x82\x40\x24\x5f\xe6\x3e\x74\xe7\x1c\x28\x31\x49\xec\xf9\x52\x07\x8a\x8f\x6e\x0e\x4c\x4a\x13\x3f\x21\x71\x71\xa4\x29\x29\x92\x38\x15\xd5\x67\x44\x26\x5f\x7b\x1f\xe5\xe7\x02\x28\x29\x49\x1c\x9c\x6a\x9a\x4b\x04\x8e\x9a\x38\x21\x12\x7c\xaa\x04\x4d\xa1\x3c\x38\x71\x30\xe1\x1e\x0e\x47\xcf\xf5\x73\x09\x3b\xb8\x4c\x89\x81\xf0\x73\xd5\x51\x8e\x8f\xdb\x27\x09\x71\xc8\x15\x4e\x62\x82\xe8\x13\x10\x82\xe4\x0e\x67\x90\xb3\x2b\x9c\xc4\x63\xc6\x9f\x0e\xd1\x28\x00\x07\x5f\x10\x26\xf4\x2a\xb9\xb8\x06\x4a\xe8\x7a\x71\xf9\x54\x05\x50\x20\x8e\x60\x72\x8a\x04\xb8\x06\x4a\x48\xd1\xc1\x12\x3d\x16\x61\xa3\xe4\xb8\x31\x90\x70\x77\x42\xa0\x6b\xa0\xa4\x5d\xc3\xcf\x40\x92\x1e\xbb\x96\x94\x22\xf2\x04\x84\x30\x3b\x8e\x5a\x52\x20\xfa\x5c\x95\x4b\xc0\xe3\xc6\x40\xd2\xae\xb1\x27\x20\x8a\xd0\x91\x47\x49\x47\x8d\x3f\x15\x45\x12\x40\xe0\xe4\x73\x5f\x88\x2b\x9c\xc4\x3d\x93\xcf\x40\x44\xa2\xe4\x73\x5f\x82\x2b\x9c\xa4\x1c\x92\xf0\x19\x48\x82\x3b\xf6\x38\x24\xba\xc2\x49\x2a\x44\x07\x1b\xfd\x50\xb4\x07\x62\x7a\xdc\x15\x48\xe8\x52\x4a\x72\x0d\x94\xd0\x13\x94\xf4\xb9\x66\x0a\x43\x47\x1f\x3c\x29\x45\xec\x1a\x28\x29\x45\xfc\x09\x88\x02\x7c\x57\xd7\xc4\x73\xf5\x0b\x21\xef\xd8\x07\x90\xf2\x0a\x27\x29\x8b\x8e\x67\xd4\x0f\x48\x02\x83\x3b\xf6\x01\xe0\x71\x93\xfd\x1c\x28\x29\x8f\x20\x40\x4f\xf5\x10\x20\x64\xe4\xb8\x93\x9f\x14\x09\x5f\x23\x25\xf4\x70\x8f\xd7\xce\x3c\x26\xa4\x13\x4c\x93\x2b\x36\x78\x58\xa2\x5d\x02\x25\xee\x1c\x7b\x0e\x4d\xe0\xe0\xe0\x10\xa2\xc4\x34\xf1\x6b\xa4\xa4\x40\xe2\x1c\x48\xdc\x43\x92\xbc\x46\x4a\x7a\xa0\x08\x9e\x93\x44\x25\x67\xf7\x9c\x4c\xc2\x6b\xa0\xc4\x48\xe8\x29\x4b\x8f\x20\x72\xdc\xc0\x49\x7a\xec\x7a\x58\x15\x5f\x22\x25\x05\x22\xcf\x40\xec\x78\x70\x9f\x9c\x24\x7a\x8d\x94\x14\x88\x3d\x01\x51\xc0\x8e\x42\x99\x98\x24\x7e\x8d\x94\x14\x48\x3c\x03\x91\xe3\xbe\x62\x72\x92\xe4\x35\x52\xd2\x63\x6e\xf0\x9c\xdf\x46\xe1\x1d\x91\x09\xc7\x03\xa0\x4b\xa0\xa4\x7d\x43\xa7\x68\x12\x2e\x0e\xce\x20\x4a\x7c\x86\x8f\x9f\x8e\x83\x09\x38\x6e\x28\x25\x47\x22\xcf\x48\x84\xdd\x47\x13\x7d\x46\x12\xc7\x0d\xa5\xe4\x48\xec\xf9\x98\x02\xa3\x63\xcc\x44\x62\x24\x7e\x8d\x94\x14\x48\x3c\x6f\x75\x52\x79\x4f\x88\xc2\x71\x85\x7c\x01\x44\xcf\xe2\xa8\x7e\x26\x7c\xea\xcf\x5e\xf8\xe7\x22\x9a\x3d\x45\x51\xd5\xb5\x6a\x43\x2b\xab\xda\xb7\xba\x66\xff\x20\x8e\xaa\xae\x15\x35\xd5\xfe\x36\xed\xfc\x19\x78\x4b\x6f\x38\xe9\xfc\x73\x11\x2d\xd7\xde\xf0\xff\x7c\xff\xa9\x37\x1e\x23\xbe\xe5\xef\xdf\x96\xf3\x55\xf4\x8e\xd8\xaf\x0f\x8e\xf7\x3a\x3f\xcb\x3e\x0f\xf0\x3a\x6b\xa1\x87\x98\x77\xf8\xfb\xb7\xef\xff\xfa\xcd\x5f\x8d\xa6\x7f\x2e\x27\xbf\xfd\xf1\xed\x37\x7c\x0a\x4b\xc4\xbf\xfd\x7f\xdf\x7f\xff\xf6\x3d\xaf\x56\xdb\x16\x36\x1a\xdc\x69\x30\xcd\x64\xd8\x6c\x3b\x05\xb5\x5a\x71\x6d\x54\x2b\x3b\x65\xac\x67\xa8\x5a\xd6\xb5\x72\xb9\xa1\x35\xf4\x7a\x49\x21\xcd\x86\x69\x9a\x75\xad\xfc\xfd\x47\xa3\x7f\x7e\x74\x7f\x1e\x3e\x76\xd6\x62\x3f\xa6\x12\x7e\x21\x95\xe7\xc1\x69\x67\x2d\x70\x83\x4a\x08\xc0\xd7\x11\x77\x11\xf1\x76\xd6\x22\x3f\x66\xe1\x57\x52\x79\x11\x07\x77\x6a\x89\xa7\x68\xf9\xef\xff\xfa\x2d\x5e\x8d\xc3\x68\x7e\xa0\x31\x9f\xa9\x59\xae\x6e\x14\x91\x6a\xe0\x5c\xb9\x4a\x32\x4e\x31\x57\x2a\x67\x8b\x39\xb3\x51\xb6\x1a\x48\x77\x71\xbb\x94\xab\xeb\x95\x72\x43\xd5\x2a\x4a\xbd\xc5\xab\x2a\xaf\x38\x48\xff\xed\xf7\x6f\xbf\x79\x41\x30\x59\x8d\x97\x47\x98\x84\x1d\x3b\xc0\x2c\x96\x87\x49\x3e\xee\xfc\xe9\x7b\x43\x6f\x1c\x44\x8f\xe3\x0a\xfe\x79\xc9\xba\x84\x84\xbe\x8b\x75\xe7\xa1\x7f\x67\x2d\xf4\x9c\xbd\xf2\xaf\xdf\x1e\x86\x36\xaf\x94\x73\xed\x6c\x2d\xa3\x96\xed\x86\x63\x54\xb2\xaa\xa9\xb9\x25\x45\xb5\x4a\x6a\xbd\xad\x35\x35\xd2\x6a\xe7\xdb\x58\x6d\x67\xdb\xd8\x42\x75\xa7\x40\x0a\x3a\xa7\x46\x81\xb9\x87\xfe\xc6\xf3\xc9\xe8\x5e\x0c\x6f\xf4\xc4\x79\x78\xe2\xd3\xe1\xf7\x8b\x45\xb4\xfc\x73\xb9\x9b\x1e\xb9\x38\xf6\x96\xbd\x75\xf4\xc8\xbf\x84\x6f\x7b\x0f\xff\x2e\x43\x1e\x4f\x2d\xf6\xa9\xa2\x77\x07\x1b\x7f\x1d\xd1\xbb\x0c\xce\x3c\xb5\xc0\x2b\xa2\xa7\x9a\x96\x46\xdc\x46\x0d\xa1\xa6\x45\xd4\x12\xca\x64\x73\x59\x45\x77\x71\xb6\xa8\xe5\xb0\xce\xcb\x5a\xb9\xd0\xa8\x52\x9c\xb5\xa9\xad\x19\x28\xaf\xe8\x36\x2d\x13\xe7\x42\xf4\xee\x61\xfd\xfb\x45\xef\x4b\xf9\x87\xae\xf9\x87\xae\xf8\x77\x47\xdf\x4f\x53\x37\xf9\x18\x24\x99\xba\xc9\xde\xf6\x1e\xfe\x5d\x06\xbe\x9e\x5a\xe4\x73\xa7\x6e\x72\x36\xfe\x3a\x53\xf7\x22\x42\xf7\xac\xf5\x60\x70\xe1\x03\xef\xc6\xde\xe8\x71\x5c\x47\x11\x3c\xd0\xbf\xf6\x86\xab\xe3\x6f\x4a\x59\x65\x53\x52\xfe\xfb\xbf\x9f\xc6\xda\xad\xab\xa5\x42\xd5\x65\x9a\x5b\x74\x2a\x96\x6d\x33\xd3\xb2\x2a\x4e\xb6\xd4\x2c\x67\x5a\x86\x6d\xd9\xf5\xb6\xd1\x6c\xb5\x48\xb1\xa5\xd4\x9a\x99\x8a\xad\xd3\x9a\x5d\x54\xb2\xef\x21\xf8\x22\x12\xf8\xac\x85\x7e\x92\x60\xdb\xd8\x97\xbf\x96\xe0\xf3\x88\xe3\xb3\x16\xbb\x45\x30\x3a\x27\x78\xbc\x1a\x0e\xbf\x8e\xd4\xf3\x98\xe6\xb3\x16\xf8\x65\x79\x7b\x1e\x3b\x7d\xd6\xfa\x39\xde\xfe\x56\xb6\x5d\x5c\xf9\x2b\x08\x7e\x88\xd1\x3e\x6b\xdd\x94\xde\x6f\x17\x04\x7b\x4e\x6d\x6f\xe4\xc3\x75\xa8\x66\xf6\x41\x3e\xd7\x6f\x3b\xa5\xee\xd7\x11\x7f\x19\x17\x7e\x6a\x7d\xb2\x9a\x4d\xd6\xb1\x5f\x4b\xcd\x5e\x06\xb0\x9f\x5a\x0f\x6a\x56\x1e\x58\xf7\x55\xb4\x5c\xc6\xc0\x9f\xb5\x1e\x64\x90\x1e\x87\xb1\x37\x8e\x87\x0f\x9b\x18\x61\xb4\x78\x18\x87\x6c\x8d\xe2\x96\xa2\x19\x85\x4a\x03\xb7\x0b\x65\x4c\xd4\xba\xae\xb4\x74\xae\x37\x59\x81\x61\x35\x63\xd6\x1a\x76\xab\x91\xcd\xe4\xea\x25\x97\xd7\x6a\xd5\x02\xae\x5b\x85\x4a\xfd\x91\xc7\x09\xbf\xfd\xee\x7e\x3d\x85\xe4\x9f\xb5\xc4\xdb\xfd\x4a\x2a\xa6\x5f\x37\x5e\xe7\x81\xfd\x67\xad\xcf\x75\x4c\x92\x0e\xf7\x8d\x69\x87\x4e\xbb\x09\x5f\x3e\xfb\x2e\x13\x11\xce\x5a\x0f\x76\x4d\x3c\x4a\xc6\xfd\x2b\xec\x8b\x3d\x05\xdd\x72\xf2\xcd\x6c\xc1\xca\xd1\x82\x4d\xd4\xb2\x62\x73\x87\xf3\x8a\xe3\xb6\xb9\xdb\xd4\x88\xa9\x17\x72\xd9\x86\xae\xe6\xd5\x66\x4b\x2d\x92\x02\xb1\xaa\x8c\x17\x0a\xed\xa7\xad\x96\x64\xdf\x7e\x17\x53\xce\x73\x21\xce\x5a\x9f\xab\xcd\x93\xb2\xe5\x57\xd2\xe6\x97\x49\x1b\x67\xad\x07\x4d\xc3\x1f\xfc\xb5\xf9\x6a\xb1\x8c\xa2\x87\xb9\x44\xea\xa5\x8a\x86\x9b\x56\x3d\xc7\xdb\x35\xac\xda\x5a\x15\x5b\xb4\x51\xb6\x33\x25\xcd\xcc\x2a\x28\x5f\x74\x6c\xbd\xc6\x4b\x25\xa5\xa6\x94\x0b\x05\x33\xdb\xe6\x35\x2b\x9f\x3b\x74\xfa\x08\x33\x79\x18\x02\xb5\xd9\xa2\x45\xb5\xd6\xce\x59\xdc\xd2\xca\x8e\xad\xe4\x2b\x4d\xa3\xea\x28\xd9\x6c\xb9\xe1\x38\x6d\x53\x2d\x17\x72\xa4\x59\xcd\x20\xa3\xc0\x5b\xa8\x68\x99\xad\x1c\xc7\x8d\xfc\x71\x08\x56\xcb\xee\x64\xde\xdb\x1f\xe8\x89\xbd\xe1\x22\x7a\xf6\xd9\x82\x49\x78\x24\x52\x6b\xd4\x5e\x3a\x72\xc1\x3c\x0a\x7b\xcb\x3f\xbd\xe1\xb4\xeb\x8d\x57\x23\x72\xfa\x8b\xde\x62\xb1\x7a\x94\x8c\xa4\xbd\x7b\x34\x0c\xc9\xbe\xfd\x9e\xe1\xba\xc8\x68\x39\x6b\xa1\xbf\xc5\x70\x2d\xe7\xab\x97\xa3\xd5\xa8\x67\xff\xcd\x47\xeb\x21\xdb\xe7\xac\xf5\xf7\x98\x5c\xaf\x8e\xd6\xbf\xf3\xdc\x3a\x4f\xa9\x3a\x6b\x3d\x2c\x4e\xd8\x71\xb4\x86\xbd\x51\xef\xa8\xfd\x25\x42\x18\x73\x04\x30\x13\xf4\x9f\x84\x73\x2a\x00\x7f\x1e\x87\x5f\x67\x38\x7f\x89\x99\x96\xb0\x03\xef\x1e\xbb\xa7\x2c\xb6\xb3\x16\xfa\x77\x19\xbb\xbf\x6a\xde\x7d\xc1\xd8\x5d\x24\x0e\x9e\xb5\xc0\x99\xb3\x73\xe8\x53\x3c\xf4\x3a\x8b\xdf\xfe\xf8\xf6\xff\xe0\xef\xdf\xd0\xff\x1c\x56\x51\x4f\xbf\xfc\xf3\xf8\xeb\xa3\xf2\xfa\x73\x1e\xcd\x56\xbd\x79\x14\x3e\x69\xb3\x3f\xe7\xd1\x7a\x12\x78\xfe\x30\xfa\xed\x7f\xbe\x4c\x95\x5c\x64\x1e\x9e\xb5\x3e\x79\x41\x9a\x5c\xd8\x7e\x9d\x05\xe9\x45\x8a\xe4\x59\x0b\x7c\xae\x8b\x98\x7c\xba\xff\x3a\xac\xbb\x4c\x0a\x3d\xb5\xc4\x6b\x4a\xf0\xe2\xcc\xe3\x5c\xf3\xdd\xc1\xd1\x0b\xcd\x67\x16\x4c\xc7\x2a\x64\x72\x86\x5e\xa9\x60\x42\x69\xcb\x69\xe5\xa9\x9a\xcd\xb4\x9d\x6a\xd9\xcd\xd5\x6a\x79\x43\x75\x4b\x56\xa3\x8a\xa9\x6a\x55\x49\xab\x59\xc7\x85\x76\xf1\x43\xad\xd6\x7d\xdb\x21\x09\x3b\xf0\xae\x01\xbb\xc8\xbd\x3d\xb5\x5e\xb5\x5a\x10\xfc\xef\x90\xfd\x02\x43\x76\x91\xe4\x7c\x6a\xbd\xba\x48\xfc\xdf\x21\xfb\x15\x86\xec\x32\x9b\xfc\xd4\x02\x49\xd7\x86\xff\x3b\x76\x5f\x37\x76\x17\x69\xf7\xa7\xd6\x27\x2f\xa4\x92\x8f\xcc\xaf\xb3\x1a\xb8\xac\x33\x70\x6a\x9d\x9f\x21\x04\xc3\xc8\x9b\xbf\x5c\x58\x9f\xfd\xfa\x7d\x4b\x6b\xd5\xc8\xe5\x6a\xd5\x82\x5e\xd2\x99\x99\xe5\x6a\x81\x56\x0c\xe2\x34\x55\x57\x2d\x95\x6b\xe5\x1c\xb3\x5c\x85\x9b\xb6\x5a\xc3\x39\x4b\xb7\xcc\x76\xd5\x76\xdd\x5c\x86\x6a\xef\x3a\x1a\xb9\x2c\x7a\x70\x6a\x91\x73\x6f\xa1\xd7\x19\x47\xf3\x3f\x07\xd1\xee\x41\x2a\x98\x89\x5b\x95\x62\xc1\xad\x6a\xac\xd0\xcc\xb6\x35\x85\x98\xd9\x52\xce\xb6\x2b\xe5\x86\x6b\x61\xab\xa1\x97\xb3\xe5\x76\xad\x65\x14\x14\x66\x56\x5b\x46\xc9\x6c\x2b\x76\x4e\x3b\x0e\xe7\x03\xd2\x26\xea\x75\xba\x07\xd9\x00\x5f\xd7\xcf\x8b\x92\x0c\xa7\x16\xfa\x92\x7e\xd2\x2f\xeb\xe7\x65\xc1\x88\x53\x8b\x7d\x49\x3f\xe1\xd7\xf5\xf3\xa2\x9c\xc5\xa9\x75\xee\xe5\x8e\xbc\xc5\xf2\xa1\x9f\x27\x0a\xd1\xd7\x51\x78\x51\x26\xe3\xd4\x22\x9f\x79\xe8\xf8\x65\xfd\x7a\x2a\xda\x71\x6a\xdd\xde\x5f\xf8\xf1\xe6\xc2\xd7\xe9\xbb\xcb\x42\x21\xa7\x16\xbb\x45\xfd\x5b\x5b\x23\x5f\xaf\xae\x2f\xab\x93\x9c\x5a\xe8\xd7\x12\xfb\xe7\xaa\x27\xa7\xd6\xb9\x9d\x1c\x4e\x36\x7f\x2e\xbb\xf3\x68\xd1\x9d\x0c\xc3\x83\x19\xf8\xfd\xdb\x6f\xa3\x28\xbc\xf8\x1d\xfa\xfd\xdb\x6f\xdd\x5e\xa7\x7b\xf9\xcb\xaf\xee\xc6\x63\xc9\x95\x53\xeb\x7c\xf6\x76\x27\xa3\xe8\xcf\x70\x32\xf2\x7a\xe3\xc3\xd4\x8d\xb6\xde\x68\x3a\x8c\xfe\x19\x4c\x46\x5f\x3c\x1b\x9f\x0b\xba\x9c\x5a\xe0\xdf\x4c\xdf\x5f\x55\x89\x79\x6e\x7d\x72\xf8\x7f\xb2\x8e\xfd\x5a\x2b\xd7\xcb\xb2\x38\xa7\xd6\x83\xce\x20\x47\xd6\x4d\xe7\xbd\x47\x12\x2f\x62\x77\x9f\x63\x7a\xd1\xa5\xeb\x7d\xfc\xf3\x3f\x0f\xac\xfe\xd7\x6f\x87\x79\x09\x7f\xff\xf6\xdb\xf8\x28\x0f\xbf\x7f\xfb\xcd\x5f\xed\x0e\xfd\x7e\x35\xf0\xf7\xa8\x4b\x87\xc3\xd3\xf3\x2b\xa7\xeb\xf2\xe1\x5b\xce\xd7\xe5\x5f\x9e\x3b\x61\x2c\x5f\xc6\x45\xb3\xd1\x62\xa6\x5b\xe3\x5a\xb6\x62\x12\xde\xcc\xe8\x3c\x4b\x68\x89\x98\x2d\xdd\xc9\x17\x58\x51\x37\x6b\x8a\x66\x50\x33\x53\x2f\xa3\x6c\xa6\xea\xf2\xea\xd3\x78\x24\xfb\x76\x82\xf1\x78\x2c\x2e\x74\x6a\x89\xaf\x18\x8f\x2b\x7e\xbf\x3a\x56\x3f\x66\xf7\xcb\x51\xbd\x00\xfa\x3b\x8d\xc6\x65\x5d\xa5\x53\xeb\x73\x63\xa8\x92\xb2\xe5\x97\x52\x2c\x97\x85\xa4\x4e\xad\x07\xdb\x83\x7f\x4a\x90\xf1\xcf\xcb\xf1\x24\x8e\xa3\xf9\x9f\xbd\xa7\x05\xc3\x5f\xad\x66\x50\xd5\x70\x6d\x64\x28\x8d\x5c\xa9\xe6\x14\x8a\xf5\x62\xd1\xaa\x69\xaa\xca\x2a\x6a\x25\x6f\x96\x94\x6c\xdd\xb2\x6b\x05\x6e\xe7\xcb\x36\xaa\xe7\x6a\xc8\xcd\xb7\xb2\x4a\x2d\xfb\x34\x3a\xc9\xbe\xfd\x8e\xd1\xb9\x28\xce\x75\x6a\x90\x77\x8c\x0d\xfa\x98\xb1\xf9\x72\x95\x73\xdf\xc8\x54\x0a\x3c\x53\x69\xd4\x2b\x2d\x4b\xcf\x28\xe5\x8c\x5b\x62\x25\xa3\xe6\xb6\x4d\x23\x6b\x58\x0d\xd7\xb4\x1c\xdd\xd6\x95\x6c\x8e\xd3\x86\xd6\x34\x9a\x6e\x4b\xd7\x2b\xe5\xaa\xfa\x9e\x91\x39\xaf\x76\x76\x6a\xbc\x7a\xac\xf4\x53\xfb\xa7\x09\xfb\x7b\xb5\x7f\x9a\xb0\xe3\x1f\xba\x7f\xfa\xab\x8f\xdc\x79\x59\xb8\x53\x03\x7d\xae\xa9\x48\x3e\x2e\xbf\x8c\xa9\xb8\x28\x5f\x77\x6a\x7c\xee\xe2\xfd\x8e\x79\xf1\xcb\x30\xee\xa2\xca\xde\xa9\xf1\xb0\x38\x41\x97\xe9\x93\x4a\x0d\x29\x9a\xab\x15\x0c\x5b\x43\xc5\x82\x41\x6b\x25\x27\x47\x4b\x46\xb3\xcd\xaa\xdc\x31\x8a\xb5\x4a\x3e\x6b\x23\x54\xe1\xa6\x43\xb2\xf5\x56\xae\xce\x73\xd9\xac\x75\x91\xfe\x97\xad\xb5\x30\xa7\x25\xc5\xad\x11\x56\xc9\xe6\x73\xa8\x95\x57\xca\x55\x15\xd5\x6a\xed\x22\xaf\x20\xc2\xb2\xae\xae\xab\xf9\x96\xdd\x44\x35\x8d\x1b\xba\x86\xaa\x8d\x6a\xf1\xc8\xb1\xa9\xb7\xec\xfe\xf6\xc7\xb7\xff\xf7\x3f\x57\xa9\x80\xaf\xe4\x02\xbe\x3b\x06\x67\x31\x59\xcd\x83\xe8\xcf\x91\xb7\xbd\x89\x79\xa6\x44\x14\xa7\x94\x23\xd8\xce\xb7\xf5\x16\xae\x96\x71\x4d\xab\x34\x14\xd4\xa0\x56\x8b\x66\x6c\xa5\xe6\xe4\xf3\xae\x89\x4d\x23\xa7\xb7\xb0\x6b\xb3\x6a\xad\x50\x2b\x62\xd5\xb2\x1a\x67\x2f\xba\x49\xff\xd3\xf3\xdb\x29\x8d\x09\x39\xf8\x1e\x89\x38\xaf\x72\x78\x6a\x80\x5f\x56\x22\xfe\x75\x23\x05\xf4\x7f\xde\x72\x68\xfe\xad\x24\xe5\x7a\xf1\xf9\x9a\x14\xbd\xd1\x9b\x0f\xa3\xfb\xab\x44\xf4\xa2\xec\xe5\xa9\x41\x5e\xe6\x7c\xdf\x21\x5e\xa7\x9c\xe5\xe4\xa3\xf8\x93\x8a\x2a\xf9\x82\xe6\xbe\x91\x4a\xf8\xed\xf7\x8f\xd4\x43\x5d\xd1\x53\xe3\x55\x07\x0e\xfc\x93\xbe\xe6\x24\x90\xb7\x77\x22\xd0\xaf\xea\x25\xfc\x3d\x86\xe6\xb1\x52\xeb\xa9\xc1\xde\xe5\x5b\x7f\xad\x73\xfd\xa8\xa6\x3f\xc0\xb9\xfe\xe5\x07\xe7\xbc\xfa\xed\xa9\x91\xd8\x85\xbb\x43\x87\x9d\xbb\x70\x77\xa8\xd3\x5f\x43\xe3\x7d\x81\x6d\x3a\x2f\x37\x7c\x6a\x90\xbf\x78\xe4\xee\x58\xab\x7d\x54\x60\xfb\x9d\x73\x2e\x59\x07\xde\x31\x72\x17\x75\x99\x4f\x8d\xcf\x75\xbe\xef\x98\x51\xbf\x8c\x0f\x79\x51\x3f\xfa\xd4\xf8\x5c\xe7\xfb\x0e\x81\xfe\xd5\x18\xf7\x50\xe7\xfa\xd4\xf8\xe4\xa2\x06\x77\x38\x25\xbf\x0c\xe3\xce\xcb\x71\x9f\x1a\xec\xb5\x7a\x63\xed\xbc\x55\x70\x69\xab\xae\xb7\xf2\xd4\xad\xb4\x4b\xe5\x3c\x45\x79\xb5\x40\xeb\xaa\x49\xdc\x7c\xa3\x55\x32\xcd\x66\xbe\x5d\x2f\xa0\x9c\x45\x32\x06\x32\x0d\xb3\x8c\xd4\x0b\x07\x40\xd5\x55\x92\x45\x6a\x9d\x50\xd5\xac\x95\xcb\xa4\xaa\xe8\x36\x2a\xe6\xda\x8a\x69\x34\xa8\xa5\x70\x9d\xe2\x02\x6e\x56\x2c\xd6\xd2\x4c\xe6\xb4\xf4\x72\xbd\xdc\x2e\x54\xf3\xd7\x0e\xc0\x67\xac\xff\x93\x92\xf6\x94\xea\x9d\xe8\xdb\xef\x19\xa8\xf3\x2a\xe5\xa7\xc6\x6b\xd5\xb9\x7e\xe5\x81\x7a\x75\x2b\xe6\xab\xb8\xf7\x58\x9a\xfd\xd4\x48\x9c\xe0\x78\x07\x7f\x2e\xd6\x12\xc9\x87\xea\xd7\x90\xfb\x84\x1d\x78\xc7\xc8\x5d\xd4\xb0\x3f\x35\x3e\xbb\xc0\x41\xe2\xe1\xfd\x65\x34\xfb\x45\xa5\xfd\x53\xe3\x73\xb3\xc9\xee\x10\xe8\x5f\x87\x71\xe7\xd7\x01\x9c\x1a\x37\x16\x61\x59\xb5\x69\x67\xf2\x75\x4d\x6b\xf0\x42\xd1\x69\x94\xf4\x52\xdd\xc9\x28\x45\xc7\x44\x36\x31\x50\xa1\x62\x39\x2d\x54\xa7\x76\xad\x58\xc8\xd6\x0c\xc5\xc9\xd2\x46\x56\x57\xdc\xca\x0b\x89\xcb\xf0\x9c\xe5\xe6\x8b\x45\x56\x33\x31\xd7\x0b\x35\xc5\x6d\x51\x5b\x69\x95\x72\x99\x7c\x3e\x97\x2f\x11\xa3\xc4\xb4\x5a\x46\x6d\x3b\x06\xca\xb4\x49\xa5\x52\x71\x50\x43\xb9\x59\x42\x92\x5e\xb3\x2d\x21\x99\xef\x60\xdb\xc5\x95\x05\xa7\xc6\x27\x2f\xfa\x93\x73\xff\x97\x91\xb7\x8b\x7b\x15\x4e\x8d\x57\x96\x60\x1f\x52\x37\x32\x4f\x91\xdd\x62\x55\x25\xc3\xec\x7c\xb9\x54\xb1\x8b\x18\xb9\xa4\x84\x1b\xd5\x6a\xb1\x5c\x2e\xeb\x96\xa6\xbb\x8a\xe1\xd6\x2c\x56\xcf\xe5\x58\x5b\x69\xd6\x72\xb4\x5d\x4d\x5c\xf2\x35\xd9\xdb\x12\x71\x4f\x5c\x71\xef\x53\xaa\x6e\xfe\x9b\x71\xef\xe2\xba\x8a\x53\xe3\x93\x8d\x44\x72\x26\xfe\x32\x93\xf6\xe2\x4e\x8d\x53\xe3\x95\x83\x93\x0f\x11\x3b\xc2\x9a\xb5\x42\x46\x2d\x1a\xc8\x61\x59\xa7\xe8\x70\xc5\xd0\x9a\xb5\x5c\x51\xc7\x0d\x85\x3b\x19\x0d\x97\xf3\x65\x8b\x55\x38\xd1\xab\xb4\xe8\xe8\xa5\xbc\xdd\x44\x66\xe6\x4a\xec\x7e\x56\xea\x92\xbd\xec\xfd\xcc\x7b\xb8\xfd\xe3\xd4\x78\xc5\x97\xf9\x5f\xe6\xdd\x60\xde\xe3\x3d\x25\xa7\xc6\x67\x99\x8b\x7f\x4b\xe6\x3d\xdc\xa8\x72\x6a\xbc\x52\x5e\xfd\x7f\x99\xf7\x92\x79\xe7\x97\xbf\x9c\x1a\x9f\xbc\x3b\x99\x9c\x87\xbf\x8c\xb1\xb8\xbc\xeb\xe6\xb9\xf1\x93\x99\x40\x59\x27\xa7\xe4\x4d\xb5\xae\x1a\x44\x2d\x20\x57\x2f\x30\xb7\x56\x54\x98\x5d\xd0\x9c\x5c\xcd\xe1\x99\x52\xbe\x59\xaa\x56\x32\xa5\xa2\xa1\x35\xcc\x9a\x49\xdd\x6a\xb9\x58\x32\xde\x33\xb0\x97\x37\xe8\x3c\x37\xd8\x0f\xe8\x83\x5f\x4c\xdf\xe3\xbd\x3c\xcf\x8d\x37\x12\x42\xb3\x58\xe3\x7a\xa1\x54\x2b\xdb\x4c\xcf\x67\xf2\x7a\xc6\x66\x06\x33\x35\x52\x46\x75\xd2\xa2\x85\x36\x22\xcc\xce\x9b\xa4\x50\xad\x3b\x26\xb2\x48\xc6\x51\x1b\x56\xb5\x64\xbd\x91\x38\xf3\x65\xbd\x7c\xbc\x33\xe8\xb9\xf1\x56\x36\x16\x7a\x67\x36\xd6\xe7\x77\xe2\xe2\x92\xa1\x53\xe3\x93\x6b\xd8\x24\xeb\xd6\x2f\xa5\x23\x2e\xee\x42\x3a\x35\x3e\xfb\x04\xc3\xc0\xb8\xa1\x16\xab\xb6\x5a\x28\xa1\x72\xa9\x96\xa9\x73\xc7\xcd\xd4\x28\xa6\xc5\xa2\xd6\x54\xf4\x22\x75\x33\x65\x92\xb3\xd5\x0c\xd1\xdb\xba\xcd\xdb\x0a\x55\x9b\x85\xaf\x61\xdc\x0f\xee\x55\x5a\xce\xbd\x30\xfa\x98\x3b\x95\x1e\xa0\x6e\x64\x4b\x1c\x78\x8f\x00\x94\xff\x00\xec\x1f\x00\x7f\x83\xec\x0f\x4c\xff\xa0\xe0\xfb\x31\xb4\x03\x3e\x8c\xcf\x73\x61\xdc\xdf\xbf\x41\x7c\xac\x6f\x78\xf6\x9b\xc7\x52\x9d\xf0\x29\x67\xe8\xd6\xad\x69\x57\x54\x5c\xc4\x93\xbe\x4a\x04\x61\xdf\x1f\xbc\x5c\x7a\xc4\x85\xe0\x8c\x0a\x76\xa4\xe2\xfc\x57\x0f\x45\x0d\xe1\x53\xf0\x21\x61\x10\x32\xc1\x20\x20\x18\x31\x8e\x0f\xfd\xfd\x49\xba\xce\xa3\x1a\x5f\xa7\x8b\x7e\x7f\x78\xd1\xa3\x13\x7e\x4e\x17\xbd\xe4\xce\x89\x3d\x8f\x29\x6e\x4f\x54\x01\x80\x21\xe7\x80\x1d\xeb\xda\x26\x20\x0c\xde\x24\xec\xc4\x30\xf4\x92\x61\xe8\x27\x18\x76\x22\xed\xa7\x84\x74\xbc\xf0\x82\x17\x37\x89\x7d\x94\xd8\xbe\x0a\x7e\x12\xe4\x17\xb7\x81\xdd\xe6\xe4\xdb\x48\xe8\xc5\x8d\x5d\x49\x91\xf0\x8b\x5b\xb5\x92\x22\x91\x17\x57\x60\x25\x45\xa2\xd7\xd7\x54\xdd\xba\xd4\xee\x87\x48\xec\xc5\x85\x57\x49\x91\xf8\xf5\xfd\x4f\x6f\xa8\x8d\xb7\x91\xc4\xf5\x4d\x48\x89\x7b\x27\xaf\x91\x12\xd3\x04\xc1\x8b\x3b\x72\x12\x43\xbd\xb8\xae\xe8\xd6\x25\x89\x3f\x86\x42\xd7\x37\xcf\x24\xa7\x0a\x5f\x43\x25\xa7\x8a\x5c\x5f\xea\x72\xeb\x1e\xef\x1f\x43\xd1\xeb\xeb\x56\x92\x43\xb1\xeb\x8b\x50\x92\x43\xf1\xeb\x8b\x4a\x92\x43\x89\xeb\x2b\x44\x92\x43\xc9\xeb\xcb\x3d\x12\x43\x21\x70\x7d\xd5\x46\x62\xb9\x42\xf0\x1a\x2a\x39\x55\xe8\xfa\x16\x8b\xe4\x54\xbd\xb8\x84\xe2\xd6\x65\xfc\x3f\x86\x22\xd7\xf7\x3e\x24\xa7\x8a\x5e\x5f\xb5\x90\x1c\x8a\x5d\x43\x25\xef\x20\xbf\xbe\xbe\x80\x27\x86\x12\xd7\x50\xc9\x3b\x28\xaf\xef\x0f\x48\x0c\x85\xc1\x35\x54\xe2\x0e\x62\x78\x5d\x9a\xff\xd6\x8d\xf1\x3f\x86\x42\xd7\x50\xb7\xee\xc3\xff\x31\xd4\x8b\x0a\xf4\xc9\xa9\x22\xd7\x50\xc9\xa9\xa2\xd7\x95\xd6\x93\x43\xb1\x6b\xa8\xe4\x1d\x7c\x51\x51\x3c\x39\x55\xe2\xba\xc0\x75\x72\x28\x79\x5d\x6f\x39\x71\x07\x8f\x01\x15\x17\x75\x8e\x13\x4f\x9c\xf3\xba\xbf\x0f\x50\x89\x3b\x48\xd0\x75\x09\xe1\xe4\x1d\xc4\xd7\x50\xc9\x3b\x48\x5e\x54\xe7\x05\x89\xb1\xe8\x8b\xc2\xb1\xc9\xb1\xd8\x8b\x8a\xa6\xc9\xb1\xf8\x8b\x52\x9b\xc9\xb1\xc4\x75\xe9\xc7\xe4\xac\x97\x2f\xaa\x48\x26\x26\x8b\x82\x17\x65\x15\x93\xbb\x5e\xf0\x45\x2d\xc3\xe4\x58\xe8\x45\xbd\xc0\xe4\x58\xf8\x45\x4d\xbe\xe4\x58\xe4\x45\xdd\xbb\xe4\x58\x2f\x2b\xd4\x25\xc7\x62\x2f\xaa\xc2\x25\xc7\x7a\x59\xa3\x2d\x39\x96\x78\x51\x30\x2d\x39\xd6\xcb\xd2\x66\x89\xb1\x8e\x93\xf9\xb2\xbe\x58\x72\xac\x97\x35\xc0\x92\x63\xa1\x17\x75\xb6\x92\x63\xe1\x6b\xac\xe4\x7b\x21\xe4\x45\x0d\xab\xe4\x58\xf4\x45\xfd\xa5\xe4\x58\xec\xba\x7a\x50\x72\xa8\x97\x85\x88\x92\x63\x89\x17\x95\x79\x12\x6f\x19\x30\x79\x5d\x48\x26\xf1\x4e\x0d\x07\xd7\x95\x4f\x92\x43\xc1\xab\x52\x1c\x89\x79\x75\xd0\x09\x97\x45\x3d\x92\x13\x85\xaf\xca\x5c\x24\x27\x8a\x5c\x17\xcc\x48\x3c\x7e\x9c\x5e\x97\x90\x48\xec\x6e\x1e\x54\xf1\x25\x54\x62\x6f\x8c\xf3\xeb\x32\x06\xc9\xa9\x12\xd7\x50\xc9\xa9\x92\xd7\x99\xeb\x89\x77\x44\x0e\x26\xf0\x12\x2a\x71\x07\xc5\x8b\x2c\xed\xe4\x54\xa1\xeb\xac\xe2\xe4\x50\xf8\x3a\x07\x36\x79\x07\xc9\x75\x52\x66\xe2\x11\x14\xf4\x2a\x4b\x30\xf1\x14\x14\xec\x3a\xdf\x30\x79\xff\xf8\x75\x06\x5e\xf2\xfe\x89\x2b\xa8\xe4\xfd\x93\x57\xd9\x6d\xc9\xb7\xf2\xc1\x75\x9e\x5c\x62\xa1\x92\xf0\x3a\x73\x2c\xb1\xdb\x7a\x58\x24\x5c\x42\x25\x76\x5b\x25\xbe\x4e\x93\x4a\x4e\x15\xb9\x86\x4a\x4e\x15\xbd\x4e\x3f\x4a\x0e\xc5\xae\xf2\x61\x92\xcb\x02\xbf\xce\xac\x49\xce\x2a\x71\x95\x6b\x92\x9c\x28\x79\x9d\xb5\x92\x98\x53\xf0\x78\xa4\x70\x9e\xc8\xf1\xd6\x59\xf7\x8f\xb0\xe0\x35\x56\x62\x3f\x1a\x02\x74\x95\x29\x91\xfc\xb8\x09\x5c\x27\x5d\xdc\xd3\x45\x72\x1d\x49\x7f\x07\x5d\xf4\x1a\x2b\x39\x14\xbb\x0a\x51\xbf\x03\x8a\x5f\x43\xdd\x81\x25\xae\x02\xc0\xd1\x1d\xa7\xa2\xf2\x1a\x2b\xf9\xa9\x28\xb8\x0a\xad\xbe\x83\x2c\x78\x1d\xa6\x7d\x07\x59\xe8\x2a\x68\xf9\x1e\xb2\xf0\x35\x56\x72\x28\x72\x15\x0e\x7c\x0f\x59\xf4\x1a\x2b\x39\x14\xbb\x0a\xb4\xbd\x03\x8a\x5f\x43\xdd\xd1\x43\x71\x15\xc6\x8a\x92\x1f\x6e\x43\x79\x15\x72\x7a\x07\xd6\xf1\x04\xec\x3c\x3c\xf4\x1e\x2c\x78\x15\x84\x79\x0f\x16\xba\x8a\x85\x4c\x3e\x8c\x08\x5f\x43\xdd\x41\x16\xb9\x8a\x34\xbc\x83\xac\xeb\xa0\xc5\x8b\xe0\xa8\x9f\x8b\x89\xfa\xb3\x17\xfe\xb9\x88\x66\x4f\xa1\x51\x75\xad\xda\xd0\xca\xaa\xf6\xad\xae\xd9\x3f\x08\x8e\xaa\x6b\x45\x4d\xb5\xbf\x4d\x3b\x7f\x06\xde\xd2\x1b\x4e\x3a\xff\x5c\x44\xcb\xb5\x37\xfc\x3f\xdf\x7f\xf2\x9d\xdf\x0f\xd4\xd3\x87\x90\xaf\x77\x05\x75\x7d\x78\x20\xd7\x89\xa7\xdf\xfd\x00\x42\x9f\x06\x04\x86\x11\x97\x10\x33\x19\x87\x82\xc6\x1e\x0c\x82\x18\xc0\x00\xd3\x00\x81\x30\xa6\xb1\x14\x71\x8c\x62\x4e\x43\x80\x22\x2f\x64\xd0\x8f\x43\x8a\x40\x84\xe0\xf7\xdf\xbf\xb1\xc7\x48\xb8\xbc\x5a\x6d\x5b\xd8\x68\x70\xa7\xc1\x34\x93\x61\xb3\xed\x14\xd4\x6a\xc5\xb5\x51\xad\xec\x94\xb1\x9e\xa1\x6a\x59\xd7\xca\xe5\x86\xd6\xd0\xeb\x25\x85\x34\x1b\xa6\x69\xd6\xb5\xf2\xf7\xa3\xce\x78\xfa\xe0\x63\x2c\xdf\x8d\xd8\x3a\x8c\xff\x89\x21\x41\xe0\xf0\xda\xb7\x9f\x5e\x86\xa4\x7d\x57\x0e\x9f\x42\xde\xe1\x35\x5b\xb2\xc8\x18\x23\x40\x57\x93\x86\xee\x8e\x67\x45\x7f\x89\x02\xab\x56\xae\xd4\xe6\x9e\x36\x89\x6c\x25\x98\xd7\x0a\x8d\xc3\x9f\xb7\x0f\xff\x69\x4e\xbb\x5d\xec\x64\x95\xcb\x4f\xe6\xf4\xe3\xe2\xd0\xcc\xa1\x56\x9d\x28\x9b\xd3\x73\xbd\x00\xea\xc3\xe3\xf7\xd5\xc0\x60\xd1\x16\x64\x67\xcc\x55\xba\xcc\x2b\x40\xd2\xd7\xb7\x2b\x65\xdd\x5d\x17\xf2\x28\x55\x5e\xed\xfd\x89\x52\x98\xc7\xae\xea\xa9\xb0\x5d\xaf\x72\x9e\x71\xf5\x34\x2d\x75\xba\x96\x23\xb9\x59\x91\x2d\xa7\x09\x79\xd4\x2d\x17\x78\x08\x56\xa3\x6d\xa6\xe3\x99\x7d\xa1\x7c\x7f\xea\xd3\xe1\x93\xaf\x9e\xc8\x39\xfd\x58\x3c\xa3\xf7\xbf\x9f\xff\xfe\xf8\xdc\x38\xfc\x77\xec\x93\x75\xf6\xd5\x49\x3b\x5e\xe6\x2c\x3c\x25\xbd\xd8\xb7\x47\xac\x5b\x0d\x7b\xd1\x64\xb9\xc2\xed\x8d\xd4\x00\xcd\x2f\x27\xf5\x2e\x2d\x65\x76\x4b\x6d\x7a\xfc\x92\xda\x54\xd6\xbd\xe0\xc4\x23\x55\x79\xf5\xa3\xbd\xfe\xeb\x47\x1e\x7e\xe0\xfb\xaf\xc7\xe8\xa7\xde\xaf\x28\xff\x7d\xe2\x4d\xe7\xf0\x5f\xe9\xf0\x9f\x38\xfd\x99\xda\x1d\xa6\x40\x23\x1d\x8d\x7b\xa6\x5c\x56\xfc\x59\x2e\x83\x4c\xd6\x43\x3c\x1c\x67\x81\x6d\x0f\x3c\xd4\x2d\xe8\x83\xcd\xf3\x78\x2b\x66\x43\x4d\x15\x8f\xf2\x53\x0b\x87\x83\xd5\x03\xaf\x5f\x7e\xaa\xb7\xc8\x3a\xd2\x2b\xef\x7b\xbf\xb9\x49\xf6\xfe\x07\x5e\xfc\x6b\xac\x56\xc6\x8b\x50\x61\xab\x91\x62\x44\xa3\xde\x32\x32\xb6\xc2\xef\x14\x89\xbf\xeb\x2e\xd7\x7d\x7f\x81\x98\xa2\xce\x30\x52\x46\x9d\x65\xab\x31\xa8\xa4\x36\xad\x4c\x3a\x65\x1b\x86\x0d\xd3\xd1\xce\x5e\x37\x87\x30\x8c\xf0\xc4\xae\xaf\x70\x58\x9c\x2e\xaa\x6e\xbe\xe7\xa6\x0f\xe0\xc7\x60\xed\xf1\x64\x1c\x7d\xff\xfd\x5b\xb9\x51\x2c\xfe\xdc\xff\x8f\x11\xb2\xe0\x27\x3c\xa0\x33\xbd\x16\x08\x88\x91\x2f\x69\x00\x00\xc3\x81\x17\x87\x08\xf8\x88\x85\x88\xc7\x80\x05\x10\x45\x4c\x08\x06\x64\x88\x42\x19\x62\x8e\x88\x2f\x08\x10\x08\x46\x82\x41\xc1\x81\x2f\x0e\x24\x3e\xa6\x0a\x7e\x90\x5e\x43\x3f\xd2\x6b\xf8\xe0\x88\xde\xd4\x6b\x87\xa7\xe4\xfb\x75\x80\xec\xbd\x7a\xed\x7a\xce\xbe\xae\xd7\x4e\xb2\x72\xae\xd7\x88\xce\xed\xec\x78\x59\x69\x38\xd9\x52\x87\x94\xe2\x89\x6a\x0d\xfd\x62\xad\xda\xd6\x79\x73\x53\x9e\x36\xf4\xd2\x7a\x39\xae\xb5\x66\x2d\xa3\xe7\xa6\x67\x63\xd7\x5d\x01\x7f\xdd\x71\x1b\xcd\xe5\x24\x57\xa9\x44\x33\x6d\x58\x2b\x14\xdd\xd9\xb2\xd2\xc2\xb9\xbd\xec\x15\x86\xa0\x55\x35\x3f\x4c\xaf\x9d\xfd\x51\x12\xbd\x02\x4f\x3c\xca\xbc\x3e\x81\x7e\xa0\xd7\x3e\xee\xfd\x89\xf4\xea\x0d\xbd\xc6\x4f\x7f\x96\x44\xaf\x94\x88\xf2\xac\x57\x6e\xbc\xff\x6d\xbd\xf6\x81\x7a\xf5\x3d\xef\x7f\xd4\x6b\xab\x4c\x0a\x6c\x28\xb7\x87\xb9\xcd\xde\xa8\x64\x75\xa6\xf4\x69\x6b\x07\x1a\xf9\x5a\x0a\x06\x59\xaf\x99\xd9\x17\x79\x1b\x34\x67\xc3\x9e\x31\xb2\xd8\x14\xe5\x8b\xcb\x3c\x27\xf9\x5c\xce\xf7\x32\x76\x7f\x3c\xeb\x9a\x8d\x7a\x0f\x15\xe6\xf6\x70\xb9\x0d\xd2\x6e\x6f\x1a\xe6\x06\x6a\xf5\x6b\xf5\x1a\x27\x3e\x43\x21\x45\x18\xc2\xc8\xc3\x31\xe1\x98\xca\x98\x13\x7e\x58\x12\x53\x4c\x70\x2c\x39\xf3\x62\x8f\xc4\x21\x06\x2c\xf0\xbc\x28\x8e\x22\x1a\xc5\xa1\xef\xfb\x10\x90\x38\xfe\xfe\xfb\xb7\xe3\x69\xf5\x87\xe9\x35\xf8\x23\xbd\x46\x18\xa2\xfc\xa6\x5e\x7b\x7a\x7a\x19\xae\x7f\xaf\x5e\xbb\x9e\xb3\x57\x7a\xed\xe1\xd3\x3e\x7b\x7e\xd2\x6b\x4a\x65\xbe\x6e\xd7\x73\x63\x1b\x9b\xeb\x91\x0d\x2d\x3a\x34\xd3\xc3\x4e\x67\xda\x8e\xc8\x78\xab\xd3\xd6\xda\x94\x85\x74\xbd\x58\xc9\x12\xb9\x89\x67\x33\x41\x16\xab\x71\x30\x69\x1b\x63\x6c\x28\x31\xb0\xb4\x6d\x69\x83\xa3\xe5\x8a\xe6\x7a\xd9\xe6\x06\x07\xb8\xef\xba\x5d\xa5\xf8\x51\x7a\xad\x72\x5a\x63\x26\xd1\x2b\xfd\xca\x89\x47\xaf\xcf\x9f\x1f\xe8\x95\x0f\x7c\x7f\x22\xbd\x7a\x43\xaf\xb1\xd3\x9f\x25\xd1\x2b\x95\xe3\x32\xf2\x41\xaf\xdc\xf8\xbc\xad\xd7\x3e\x50\xaf\xbe\xe7\xfd\x8f\x7a\x2d\x3b\xe3\xa8\xd1\x6d\x03\xb9\xf3\xe9\x40\xda\xa9\x76\x3d\xa6\xae\x51\x68\x39\x2b\x53\xd4\x52\xcd\xf9\x2e\xae\xaf\x41\x6f\xdf\x49\x59\x81\xce\x66\xeb\x4a\xb1\x38\xc5\x85\x7c\xdd\x94\x3b\x45\x97\xd9\x6d\xc9\x2e\x95\xf1\xdc\x5f\xd5\xdc\x0e\x0c\xca\xb8\x4c\x50\xde\xa8\xaa\x9b\xaf\xd5\x6b\x02\xc9\x90\xe2\x18\x85\x41\x14\xf9\x11\x04\x5e\x2c\x00\xe0\x94\x11\x1f\x78\x51\x1c\x46\x02\x4a\x5f\x52\x8e\x89\x17\x12\x0c\xc3\x58\x10\xc4\x01\xa3\x30\xe2\x51\x28\x3c\x09\x0e\x7a\x4d\xdc\xad\xd7\x9e\xd2\x6a\xe8\x31\x89\xfa\x6d\xbd\x46\x39\x96\xf2\xa6\x5e\x7b\x7a\x7a\x99\x3c\x94\x5c\xaf\x65\x07\xca\xa5\x1e\x53\x94\x9b\xeb\xb5\xb3\xe7\x27\xbd\x96\x9d\x01\xb3\xd9\x2d\x94\x8d\x99\xf4\x3a\x60\x51\x4b\xd5\xd2\xc1\x1a\x87\x72\xa9\xad\x3c\x57\x1b\xa1\x8c\xb7\x37\xf6\x46\xb1\x16\xe6\xfb\xd2\x1b\x7a\xcd\x52\x3b\xd3\xdd\x4e\x4c\xdc\x36\xa6\x16\x9e\xcf\x3d\xd5\xdc\xef\x26\x85\x76\x25\x35\xa5\x7a\xa6\x79\x18\x21\x94\x6a\xe4\x3f\x4c\xaf\x9d\xa9\xa3\x24\x7a\x65\x7c\xe2\xd1\x8d\xcf\x0f\xf4\xda\xc7\xbd\x3f\x99\x5e\xfb\x60\x5d\x56\xa9\xbe\xf1\xce\xb7\x75\xd9\x5f\xa4\x4b\x5f\xd5\xeb\xf4\x3e\x5a\x1e\x5e\x54\xb9\xd9\xdf\xaf\xe1\xc5\xfb\xdf\xff\xa8\xd7\xd9\x52\x6d\xba\xf5\x7e\xbd\xb0\x6e\x4d\xca\x45\x2d\x1e\xc4\xb8\x28\x71\xec\xd7\x8a\xa3\x51\xc6\x5c\x76\x5a\x8b\x5d\x69\xa7\x02\xa7\x36\x49\xb7\xa6\xad\xa1\x9d\xaf\xba\x81\xa7\x86\xa8\x5e\xb0\x25\x63\xa8\xd3\x0b\xc4\x4c\x1d\xd9\xeb\x59\x54\xdb\x34\x9d\x65\x98\x5f\xae\x87\x99\xce\xd7\xea\x75\x10\x51\x3f\xc4\x18\x21\x09\x23\x0c\xa4\x88\x88\x14\x82\x85\x31\x0a\x42\x5f\xfa\x14\x33\xe9\xd1\x58\x46\xc0\x93\x92\xe3\x18\x84\x32\x82\x9e\x24\x42\x06\x8c\x0a\xe8\x7b\xe8\xa0\xd7\xf9\xa3\x5e\x4f\x9a\xe6\xfd\xfb\xb7\x63\x66\xcd\x9b\xda\x9c\x09\x06\x6e\x7b\xdf\x4f\x4f\x2f\xd3\x2e\x1f\xa4\x35\x5f\x14\x7a\x75\x5d\x1d\xf8\x05\xa4\x2b\xb8\xd5\xec\xd7\xe6\x85\x51\xdf\x01\x20\xce\x8b\x45\xd1\xe0\x23\xa0\xd5\x36\x66\x2b\xad\x38\x58\xb9\x5c\x75\x7a\x57\xc3\xfe\x42\x73\x24\xd0\x44\xe7\x2a\x30\xd3\x5c\x6f\x72\x72\x73\xd4\xfe\x7a\x43\x52\x4d\x6e\xb6\x1d\xcd\xce\x0a\x7b\xb6\x6d\xcc\x07\x1d\x15\xa4\xb9\xa3\xef\xca\xd9\xe5\x82\x55\x69\x77\x55\xd3\xe3\x6c\x6d\x57\x0b\x26\x7a\xb8\xe6\x5e\x69\x9a\x5e\x58\x6b\x15\xd7\xac\x81\xd3\xaf\x94\xfa\x1d\xbf\x60\x36\x1c\x5e\xef\x68\xdb\x46\xe4\x66\x68\x2c\x72\x3f\xa1\xfd\x2f\xc4\xfa\xa6\xf6\x3f\xfb\x7b\x77\xbd\x09\x55\xa9\xd6\x16\x73\x37\xc8\x86\xed\x56\x39\xbf\x98\x79\xe5\xd8\xae\x09\x7f\xb7\x59\xf4\x57\x7e\xb5\xa6\x2b\x43\x5f\x64\xe2\xa0\x98\x9f\xb7\x5d\x19\xb6\xb7\xfe\xe9\xeb\x67\xec\xd5\xde\x8b\xa7\x5c\x7f\xf7\x95\x4f\xe6\x83\xe9\xf5\xbe\x82\xde\x87\x9d\xe9\x6b\x8d\x9a\xe9\xa5\x33\xa0\x08\xcc\xfc\x6e\xd9\xdd\x94\xe1\xd0\x05\xde\x6e\x3a\x81\xb2\xac\x6f\xd7\x45\x75\x57\xa1\xcb\x8c\x16\xa8\x0f\x32\xb4\xf0\x96\xc3\x3e\x84\xe3\xdc\xc9\x7d\xca\x4c\x4e\x50\xd5\xf7\xe2\x29\x57\xdf\x7d\xed\xa3\xdd\x49\xaf\xd7\xdd\x4d\xe0\x17\xd2\xab\x28\x7f\x9d\xc5\x7a\xd5\x7a\xe2\xe4\xbc\x3b\x8c\xb5\x7e\xb6\xef\x37\xf8\x64\xde\xdd\x3b\xd6\xd7\xb2\xf9\x99\xf4\x3e\x5a\xe7\x2d\xb4\xa2\x9a\x15\x94\xdc\x8c\xb6\x49\x6b\x6c\xd1\x2c\x50\x43\x59\x5a\x29\xb8\x15\xfd\x2a\xf7\x2b\x83\x8a\xeb\x0f\x6a\x78\x03\x82\x81\x53\xc8\x60\x3f\x85\xfa\x85\x98\x67\xf9\x66\x09\x6c\x9a\x23\xfb\xbe\x41\xf2\xbb\x5e\x33\x97\x02\x93\x4c\xa9\xa9\x8f\x94\xc8\x49\x67\xbe\x78\x37\x09\x79\x02\x50\x0e\x51\xc0\x42\x08\x62\x19\x71\xe2\xfb\x20\x08\x62\x4a\xbc\x48\x22\x0f\xf9\xc4\x87\x11\x15\x8c\x50\x18\x47\x02\x62\xec\x21\x82\xb1\x80\x2c\x66\x3e\x65\x3c\x38\x58\x67\xf6\x68\x9d\x95\x72\xae\x9d\xad\x65\xd4\xb2\xdd\x70\x8c\x4a\x56\x35\x35\xb7\xa4\xa8\x56\x49\xad\xb7\xb5\xa6\x46\x5a\xed\x7c\x1b\xab\xed\x6c\x1b\x5b\xa8\xee\x14\x48\x41\xe7\xd4\x28\x30\xf7\xfb\x29\xdd\x1f\x3e\xd4\xf3\x79\xd3\x4e\x0b\xc0\x84\xb8\x69\xa7\x9f\x9e\x5e\x16\x35\x78\x98\x17\x99\x69\xd0\xef\x69\x76\x1b\xac\xba\x9b\xad\x69\x76\x3b\x19\xcb\x2d\xb4\xea\x4d\x73\x87\xec\x36\x2a\x1a\x82\xc7\xb3\x26\x0c\x1a\x71\xfa\xcc\xeb\x3a\xea\xd8\x37\xbc\xae\x07\xbd\x9b\x1f\xee\x2a\x46\xad\x3c\xae\x33\x3d\xab\x0d\x46\x79\x45\x93\x9d\x69\xdb\x6c\x8c\x8b\xed\xf2\xd8\x5d\xf4\xf7\xcb\xd4\xd4\x69\x6e\x6b\x69\x79\x2e\x50\x0e\x24\xe7\xcd\xe7\xe7\x19\xa5\xc0\xa6\x81\xe3\x96\xf6\x8a\x36\xd2\x81\x50\xdb\xb0\xd8\x1a\xad\x97\xe5\x6c\xc1\x5b\x75\xb7\xa9\x8a\x31\x5a\x5a\xe9\xe2\x80\x74\x9b\x76\xc9\xac\x35\x33\x95\xc8\x6f\x2e\x68\x4b\xb3\xfa\xb2\x57\x9f\x77\xf2\x36\xd0\x16\x9b\x55\x56\x6d\xa3\x1e\x55\xb4\xfd\xa6\x93\x9f\xc4\x52\xe9\x9c\xe9\x08\xe5\xa6\xbd\x3e\xef\xeb\x6d\x7b\x7d\xf6\x47\xef\xec\xfb\x99\xb7\x14\xbc\x36\xb9\x2e\xf8\xfa\xca\x27\xf3\xc1\xef\xff\xc8\x5d\xa8\x33\x7d\xab\x78\x8e\x41\xba\x1a\x0a\x8b\x93\xa0\x54\xaf\xbb\xae\x62\x23\x75\x38\x18\xd6\x83\xe5\x00\x85\xbd\x9d\x55\xc1\x6c\x18\x3a\x39\x3d\x7d\xdc\xe9\x3f\xd3\xfd\xe5\xcd\x1b\x6c\x79\x5b\x7f\x92\xfb\xde\xff\xe0\xad\xbc\xff\xfd\x8f\xfa\xf0\xb3\x84\xf6\x2b\xf5\x21\xf5\x7d\x3f\x0a\x63\x9f\xa2\x28\x0e\x61\x48\x43\xc9\x71\x84\x10\x25\x00\x10\xe2\x21\xee\x0b\x08\x29\xe7\x08\x43\x82\x24\x8e\xb0\xef\x09\x1f\xc6\x3e\x44\x11\xc3\x81\x87\x0e\x24\x1e\x73\xe7\xee\xf4\x56\xe8\x8f\xb4\xa0\x44\xfc\x0d\x6f\xe5\xe9\xe9\x65\x19\x95\x7b\xbd\x95\xf6\xd5\xb0\xbf\x98\x39\x09\x66\xe2\x0d\x6f\x25\xa3\x96\x4a\x7d\x47\x6e\x2b\xd8\x29\x4c\xab\x6c\x55\x4f\x37\x60\x66\x16\xee\x6b\xdd\x7a\xc6\xad\x62\xda\x5b\x8f\xda\x5b\x2b\xd3\x89\x67\xd5\x85\x9d\x1d\x79\x30\xb3\xaf\x2c\x66\x69\x7f\xa4\x9b\xc4\x4a\xc5\x03\xd7\xac\x99\x8d\xb0\xdd\xf6\xf6\x8e\x59\x42\x3d\x32\xca\xf1\x71\x43\xff\x28\x6f\xe5\x7c\x86\xbc\x73\xf5\xef\xd7\x23\xb3\x09\xce\xbe\x7e\xfa\xf1\xf3\x56\xff\x1f\x48\xef\x97\x78\x57\x67\xde\xca\x1d\x2b\xd8\xa5\x49\x86\xce\x57\xaf\x60\xff\x46\x2b\x6e\x45\xf9\xeb\x2c\xd6\xab\xd6\x13\x25\xe7\xdd\x61\xac\xdd\x93\x98\x66\x3a\x9f\xcc\xbb\x7b\xc7\xfa\x5a\x36\x3f\x93\xde\x47\xeb\x5c\xed\x67\x0d\x98\x0e\xec\x25\xdc\xcd\x1a\x95\xf9\x60\x0d\xcb\x55\x6f\x1c\x00\xb7\xd1\x69\x69\xe5\x94\x3b\xa7\xa3\xc0\xde\xb8\x3a\x1b\x14\xb5\x0d\x1d\x2d\xab\xc1\x7e\x5e\x58\x23\xda\xdd\x45\xd9\xf4\x98\xe6\xd5\x46\xbd\xa9\xb7\x5a\xad\x05\xdc\xd9\xe5\xc9\xca\xec\x46\x14\x66\xbe\xfa\x8c\x88\xfa\x7e\x88\x7c\x4a\x05\x65\x98\x42\xe1\x61\x11\x49\x9f\x13\xe9\x87\xc4\x17\x41\x14\x32\xe0\xcb\xd8\xf7\x7d\xee\x31\x1f\x09\x1c\x41\xea\x45\x52\x50\x22\x30\x40\x5e\x40\x0e\xd6\x99\xdc\x6f\x9d\x1f\x8a\xfa\x3d\x5c\xae\xfc\x9a\xfd\x25\x80\x01\x74\xd3\x47\x79\x7e\x7a\x59\x4e\x2c\x91\x75\xde\x9d\x86\xd9\xbd\x1a\x76\xf5\x4a\x5a\x95\x8c\x19\xd9\xa3\x42\x0d\xce\xe6\x29\xb5\x3d\x31\x76\x7d\x25\xce\x6f\xe7\x86\xd3\x4e\x2f\x0d\xd8\x34\x42\x54\x89\xdb\x83\xda\x64\x93\xdd\x9f\x2f\x23\x9f\x7d\x94\x47\x6b\x5f\x77\x06\xb4\x37\x08\xbd\x59\xba\x33\xf2\xd4\xd2\x64\xa3\x6f\x17\xde\x2e\x87\x62\x5e\x2f\x37\xeb\x7a\xd8\x1f\xa3\xb6\xe6\x95\x14\x91\xba\x57\x9a\x33\xb1\xd3\x3d\xef\xcf\xd9\x5e\x66\xad\xd6\xda\x94\xe6\x61\x71\xde\x1d\x0f\x53\x39\xc3\x4a\x71\xb8\xb4\xf5\x0c\x9d\x0f\xf7\xea\xc2\x6a\xee\xf2\xe3\x1a\x5e\x04\x6b\x23\x2b\xcb\x23\xa3\x88\x8b\x6d\x6d\x22\x25\x5a\xd9\xeb\xac\x21\xab\xc5\xdd\x82\xfa\x2a\xda\xd5\x02\xdc\x72\x6b\x60\x9d\xeb\xb5\x6b\x0b\x02\x8c\x7c\x5f\xb1\xac\xce\x11\xdf\xf1\x9d\x56\x33\xdc\x8f\xca\xac\xdc\xca\xf4\xdd\x06\xad\xac\x33\x18\xb7\xec\x86\xe7\xa1\x4d\xb6\xed\xe0\xda\x28\x67\xb7\xab\xd5\x74\x8a\x9b\x6b\x2b\xf4\x87\xa5\x65\x59\xdd\x4e\x84\x51\x71\x23\xab\xda\x91\xa0\xe6\xf5\x9b\x72\x9e\x49\x0d\x84\x95\xaa\x6b\x53\x4b\x57\xaf\x56\x1f\xa5\xb3\x19\x7f\xfa\xf1\x0d\x3f\xf3\x8d\xd5\xc8\x19\x54\x02\xeb\xde\x2a\x9f\x0d\xf6\xb5\xcc\x7c\xca\x6a\xe4\xe3\xe8\xfd\xec\xd5\x93\x7a\x1a\x84\xa3\x85\x82\xe7\x5f\x1a\xd2\x8a\x3b\xd5\x5b\xb3\x35\x31\x47\x9d\x7e\xa1\x94\x11\x7e\x7e\xd1\x0d\xc7\x29\xd0\x6f\x36\xba\xd8\xa5\x72\x54\x7b\x96\xa9\x73\x6b\x99\xfc\x34\x0a\xdd\xf1\x7e\x4f\x09\x1a\x77\xbc\xff\x6f\x69\xa1\xef\xa1\x37\xcb\xf5\xc6\x17\xd2\x7b\x7c\x70\xf7\x7c\xae\xa6\xb6\xf0\x0b\xe7\xc7\xdf\x6d\x3e\xbf\xe0\xef\x3b\x6d\xa2\xda\xea\xe8\xb9\x07\xa4\xc6\xad\x77\xbc\x8b\x5f\xef\x7d\xff\xb3\xc7\xfc\xfe\xf7\xbf\xb6\xe2\x3e\xd3\x67\x49\xe6\xb3\x7f\x8a\xe6\xcc\x9c\xf1\xff\xd7\x9c\xcf\x57\xfa\xe7\x33\xe9\x7d\x5c\x71\x83\x46\x73\x91\x2d\xe0\x3a\x23\x6d\x1a\x77\xeb\xd9\xf4\x4a\xfa\x8d\xed\x26\xf2\x68\xb0\x99\x67\x61\xd0\x9d\x82\x90\xeb\xc5\x9d\x92\xb6\xdb\x3d\x55\xee\x50\xad\x60\xc5\xe1\x7c\xc0\x37\x3b\xab\xa1\x8a\x79\xa5\xb5\x59\x2e\x06\x4e\x19\x8e\xb4\xb0\xb8\x75\x47\x0d\xbf\x52\x56\x95\xff\xfe\xef\xdf\x21\x82\x70\xe8\x04\xb4\x1f\xf5\x9b\x1d\x17\xe5\x2a\xf6\x7c\x13\x4a\x38\x80\xf9\xd1\x72\xa1\xa0\xa6\x04\xed\x6e\x03\x35\x34\x2b\xbd\xda\xf9\x7b\xdc\xa2\x76\xd1\xae\x2e\x3c\x4b\xcd\x8e\xf4\x3e\x30\xac\x50\x6b\x4d\x60\xec\x6d\xe2\xa9\x95\x4d\x0f\xba\x05\x7b\xbb\x19\xde\xbb\x94\x47\xef\x5c\xca\x87\x31\x8d\x41\x24\x7c\xec\x53\x8c\xc3\x50\x06\xa1\x07\xe2\x98\x53\x02\xfc\x28\xc6\x91\x8c\xa0\xc4\x4c\x02\x06\x62\xe1\x11\x1f\x10\x48\x7c\x10\xe1\x00\xfa\x04\x43\xea\xc3\xe3\xc1\x03\xbe\x7f\x29\xff\xa3\x20\x2f\x82\x00\xa1\xe8\xe6\x52\xfe\xe9\xe9\x65\x0d\xde\x7b\x37\xda\x9c\x2b\x79\x7a\xb1\xd1\x96\x58\x6d\x3c\x7e\xfd\x6c\x29\xbd\xd3\x37\xdd\x96\xcc\x3b\xd5\xa6\x93\x87\xb3\x9e\xef\x47\xb3\x7a\x7f\xeb\xee\xbb\x6b\x6a\xa8\x40\x14\xd0\xba\x3e\xd8\xee\x5d\x7b\x63\xee\x06\xeb\xaa\x18\x82\x54\x44\x4a\xa4\x8b\x3a\xab\x49\x41\xc8\x85\xd0\x1b\xb1\x31\x33\x2a\xfb\xec\x68\x92\x5f\x94\x6d\xaf\x18\xb8\x3f\x15\x14\x76\x31\x5f\x6e\x2e\x6d\x93\x1f\xb3\x87\xe3\x88\xb0\xf4\xe9\xeb\xad\xd3\x8f\x9f\x68\x0a\x3f\x8e\xde\x2f\x59\x8a\x9f\x6d\xb4\xdd\x61\x0a\x50\xc8\xfb\xf3\xaf\x36\x05\x7f\x23\xd3\xa5\x28\x7f\x9d\xeb\xf0\xea\x46\xdb\x26\x39\xef\x0e\x63\xbd\x3c\x73\x58\xdd\x4f\xe6\xdd\xbd\x63\x7d\x2d\x9b\x9f\x49\xef\xa3\xd9\x17\x5d\x61\x34\xd7\xb5\x21\xc8\x35\xb7\x4b\x6f\x32\x42\x78\x36\x98\x88\x56\x89\xf8\xa9\xba\xb2\xb4\xd4\xe5\x1c\x4c\x4b\x01\xd2\x84\x1a\x4c\x8b\xc0\x32\x43\x6b\xbc\xca\x56\x8c\x70\x52\x9c\xa9\x6b\xcb\xb7\x32\x50\xdf\x15\x7a\xd9\xc5\x86\xce\x32\xf3\x6c\x03\xf5\x70\x3e\xf7\xd5\x41\x7b\x81\xf0\x90\x88\x7d\x44\x43\xc2\x05\x89\x31\xf7\xb8\x07\xb8\x88\x60\x1c\x45\x31\x88\x7c\x0c\x02\x8f\x91\x48\x4a\xc2\x8f\x09\x1c\x5e\x40\x22\x0f\x30\x1e\x04\x0c\x41\xc2\x8e\x1b\x6d\xe8\x29\x2c\xc0\xad\xab\xa5\x42\xd5\x65\x9a\x5b\x74\x2a\x96\x6d\x33\xd3\xb2\x2a\x4e\xb6\xd4\x2c\x67\x5a\x86\x6d\xd9\xf5\xb6\xd1\x6c\xb5\x48\xb1\xa5\xd4\x9a\x99\x8a\xad\xd3\x9a\x5d\x54\xb2\xdf\x4f\x15\xc8\x01\x82\xe4\x47\x76\x1a\x03\x41\x6f\x1e\x88\x1d\x9f\x1e\x93\xe7\x2e\x0a\xdc\x3f\xcc\x8b\xac\xd6\x2d\x35\xb3\x7a\xcf\x75\xc2\x3d\xdd\x8b\x21\xc7\x4e\x7e\x37\xaf\xa2\x5a\x59\xd0\x76\xad\x05\x57\xc5\x85\x5a\xae\xae\x46\xf1\xe2\x68\xa2\x1f\xc2\x02\x8e\xdf\xcc\x5f\x09\xc0\x99\x9d\x3e\x86\x1a\xe5\xfc\x51\x6e\xd9\xb6\xb5\x8b\xe7\x99\xac\xb2\x29\x9d\xa7\xaa\xd6\x59\x3b\xb5\x1d\x1c\x1f\x63\x6d\x6b\x96\x75\x2e\x37\xf9\x7a\xcd\x6d\x47\x73\xcb\x82\xfb\x92\x3b\x8c\xa6\xa5\xc5\xaa\x3b\x31\x73\x74\xad\x8f\x51\x47\x5d\xe8\xa3\xec\xb4\x15\x77\x2a\xa2\x59\x50\x71\xa6\x66\x8c\x2a\xa9\x71\x24\x17\xd3\x86\x33\x6c\xea\xa5\xbe\xb6\xea\x56\xf4\x89\xd5\x1d\xc2\xee\xbc\xa4\xfe\xdc\xb1\x7f\xe1\x5c\x90\x6f\xda\xe3\xb3\x3f\x2a\xd5\xb5\x6d\xa3\x14\x99\xdd\x10\x5b\x63\x6b\xe7\xac\xc3\xc0\x2f\x2c\xb3\x6d\x0d\xef\x87\xc3\x9c\xdf\x22\xab\x8d\x01\xd5\xa7\xbe\x1d\xd7\x20\xdd\xd9\x89\x77\x0f\x6e\xd4\x8b\x1c\x94\x1f\xd8\xd7\x8f\x7b\x7f\x3e\xc9\xfb\xcf\x74\xe8\xfe\xd8\x7e\xd0\x09\x5b\xc3\xce\x55\xb7\x64\x94\xc3\x41\x2a\x48\x9b\x91\x84\xdb\xc5\x0c\x94\x07\x76\x5c\x69\x35\x9a\x4b\xbf\xc7\x95\x7e\xa3\x38\x1d\xf3\x07\xd6\x37\x57\x6e\x0b\x0e\x4b\xcf\xbc\xaf\x6e\x4b\xfd\x12\xb8\xdd\xdf\x52\x92\xfe\x5e\xcb\x9e\x56\x3a\xc8\xdd\xd9\x0b\x5e\xb1\x0b\xfb\xb3\xc7\xef\xec\xd3\xc1\x46\x19\xa5\x13\xb5\x47\xf7\xf4\x65\xe2\xe2\xdb\x7a\x1e\xdc\xf7\xfe\xfc\x24\xd9\xfb\x1f\xf5\xf6\x67\x4d\xbe\xaf\xd4\xdb\x30\xe4\x02\xe3\x80\xc4\x9e\xe7\x03\x11\x31\xc4\x80\xf4\x82\x18\x73\x48\x42\xe8\x7b\x7e\x84\x38\x43\xd0\x43\x3e\x46\x22\x0a\x63\xcc\x09\xa3\x91\x94\x9e\x17\x63\x21\x03\xcf\x3f\xe8\x6d\xf8\x91\x7a\xfb\x87\xfe\x15\xc1\x1c\xdd\xd6\xdb\x87\xa7\x47\xbd\x7d\x71\x9b\xc8\xbd\x7a\x3b\x77\x25\x00\x3f\xa9\xb7\xb5\x5d\x69\x7f\x26\x40\x67\x7a\xdb\x68\x91\xdd\x3c\x17\x0e\x18\x8b\x3b\xd9\x6c\x6f\xce\xdd\x9c\x62\x6b\x21\x1a\x0e\x2b\x2b\x7f\xbf\x4d\xf7\x3c\x33\x28\xa1\xcd\x20\x87\x27\xab\x99\x59\x2d\xa7\x94\x7d\x6f\x87\xe6\xcd\x65\x81\x2a\x93\xdd\xb4\x3b\x19\xf4\x36\x0b\xd7\x59\xeb\x75\xd6\xc8\xc9\x52\x37\x1c\x37\x94\x6c\xf5\xe3\xf4\x76\xe9\x6c\xed\x92\x40\x6f\xf6\xb2\x27\xde\x3d\x30\xe5\x9d\x7a\xf3\x03\xdf\x9f\xc8\x6e\x9c\xe9\xb8\xed\xb1\xfd\xc9\x7a\xbb\x74\xf2\xab\xee\xd7\xdb\xb6\xb1\x3f\xb7\x7b\xaf\xe8\xed\xb3\x53\xc0\x24\x7a\xd3\x3c\xa3\xf6\x21\x30\xe7\x05\x17\xdf\xd6\xdb\x1f\x68\x37\xde\xf3\xfe\x47\xbd\xfd\x59\x93\xef\x2b\xf5\x36\x83\x2c\x60\x40\x02\xc2\xa3\x58\xc4\x32\xf0\x24\x10\x1e\xe1\x87\x7f\x1e\xf1\x7d\x00\x05\x21\x32\xa0\x4c\x52\x22\xbd\x10\x05\x1e\x03\x54\x02\xcf\xf3\x39\x41\x8c\x47\xe2\xa0\xb7\xc1\x47\xea\xed\x1f\x15\xab\x20\x94\x63\x40\x6f\xea\xed\xa7\xa7\x97\x57\x37\xdd\xab\xb7\xaf\x27\xf9\x0d\xbd\xfd\x5a\xc1\x13\xed\x19\xaf\xaa\xb8\xb5\x76\xd9\xea\x9a\xaa\xbd\xe9\x9b\x1d\xc5\x94\x7e\xa4\xe1\x76\x25\xad\xe3\x81\x6b\x76\xdd\x51\x13\x4e\xd5\xd1\x8e\x07\xa2\x3d\x47\x8b\x42\x58\xa8\x8c\xbc\xe2\x98\xc4\x23\x85\xce\xbc\x62\x6a\x58\x2d\x15\x36\x95\x7a\x77\xd9\xdf\x0c\xda\xc2\xd4\xb7\x56\x23\x14\x79\x65\xf0\x71\xba\xfa\x4c\xb7\x25\xd1\x95\xc1\x89\x5f\x0f\xff\xbf\x08\xce\xf9\x81\xae\xfe\xb8\xf7\x6b\x49\xde\x7f\x76\xdc\x7a\xbf\xae\x7e\xee\x4b\x15\x96\xfb\x01\xb9\x7a\x9f\xfa\x71\xf8\x9f\xa2\x87\x5f\x16\x34\x7a\x5b\x0f\xff\x45\x76\xe0\xd5\x3d\xa6\xed\x7d\xb4\x3c\x14\xfa\x28\x9d\x78\xfb\x17\xf2\xe2\x3d\xef\x7f\xb4\x49\x99\x6e\x6e\x00\x52\xda\xc0\xb4\xd4\xd2\x48\x51\xc6\x70\x49\xec\x70\xc0\x45\x1c\xd5\x3a\xa3\x5c\xaf\xed\xb4\x06\x05\xbf\xb8\xdc\x6f\x47\x6b\x6f\x33\x05\x13\xd6\x9e\xac\xe2\x6e\xca\xcd\x8e\xa6\x93\x35\x6b\x2a\x9b\xb9\x42\x0b\x79\x64\xa9\xb5\xf1\x66\x10\x6b\xb2\x86\x37\xee\x57\x17\x1a\x91\x71\x1c\x33\x28\x21\xe3\x90\xc5\x3e\xa2\x14\x00\x82\x63\x2f\x90\x4c\x78\x01\x0b\x20\x16\x00\x79\x31\x85\x9c\x79\x10\xc4\x01\x92\x10\x88\x38\x88\x03\x42\x68\x14\x53\x78\x58\xd4\x13\xf9\x81\x36\x09\xc8\x1f\xd9\x24\x8e\xe0\xed\x02\x4a\xcf\x4f\x2f\xef\x00\xbc\xd7\x26\xbd\x11\xb2\x93\xcc\x97\xd8\x16\x7a\xba\xeb\x96\x8b\x66\xaf\x85\xe7\x34\x35\x50\xcd\x91\x58\x05\xde\xa4\xc9\x33\xc1\x5c\x1b\x57\x9d\x9c\x8f\x17\xb0\xb6\xab\xed\x1a\xbe\x32\xc8\x0e\x3d\x75\xad\xa5\x6a\x85\x4d\xa9\x3d\x29\x37\x62\x7f\x50\x6d\xe4\xe7\x93\xd5\xae\x59\xd8\xc1\xf6\xb4\x11\x05\x41\x66\x37\xcb\x7e\xe0\x1e\x50\xe9\xec\xab\x49\xec\x03\x7c\x7d\x36\x9d\x7d\x7e\x60\x9f\x3e\xee\xfd\xc9\x52\x3f\x4e\x9a\xe1\x03\x75\x5c\xa2\x44\xfd\x8f\x7e\xff\x4b\x7e\xbc\x7d\xa6\xf1\x99\xbe\xd4\x0f\xce\x2d\x92\xf4\xf7\xe1\x65\xa5\xb7\x7a\xf4\xa9\xfc\x7e\x48\xaf\x79\xff\xfb\x9f\xd2\x0d\x3f\x49\x31\x7c\xa5\x4d\x89\x08\x03\x12\x0a\xc0\x29\x8c\x38\x07\x88\x30\xe6\x09\x41\xa8\xa0\x3c\x8c\x09\x8e\x48\x08\x29\x89\x02\x41\x7c\xe6\x7b\x21\x43\x41\x44\x01\x8f\x23\x88\x62\x18\x7a\xf1\xb1\x9e\xca\xc1\xa6\xa0\x0f\xf3\x73\xc0\x8f\x6d\x0a\x7e\x63\x7f\xea\xf0\x94\x7c\xbf\xbe\x0c\xf6\x5e\x9b\xf2\x46\x51\xbe\x57\xfd\x9c\x47\x9b\xd2\x40\xe5\xfd\xd9\xe2\xfd\xcc\xa6\xf4\xb7\x9d\xb1\x5d\xcb\xa8\x1e\x18\xc3\x28\x6e\x4f\x82\xed\x54\xeb\x3b\x91\x61\x57\xe9\x42\x73\xed\x66\x28\xe3\xc9\x66\xb5\x9c\xa0\x81\xb5\xa1\x51\x6e\xd3\x69\x8e\xf7\xac\x32\x2f\x98\x1b\xb5\xb6\xa4\x45\xb1\x1b\x8e\x5a\x3d\xc5\x76\x9a\x06\x6e\xef\xe2\x1e\xde\xd9\x85\x59\x46\xf9\x25\x6d\x4a\xe6\xf5\x79\xf4\x65\x36\x45\x4d\xf2\xfe\xcf\xb1\x29\x86\xf2\x3e\x9d\xfe\xd1\x36\xc5\x50\xde\xb7\x97\xa4\x28\x9f\xec\xf3\x7d\x82\x9f\x92\x54\xa7\x2b\x1f\xc4\xef\x87\xc2\x61\x89\x6d\xca\x67\x29\x86\xaf\xb4\x29\x44\x10\x48\x83\x10\xc4\xa1\x27\xfd\x40\x7a\x91\x0f\x63\xe0\x13\x28\xfd\xd8\x47\x52\xf2\x98\x7b\xc8\xf3\xa0\x0f\xa3\x18\x45\x14\x7a\x80\x01\x14\x30\x08\x01\x89\x03\x84\x83\xe0\xd1\xa6\xe0\x0f\xb3\x29\x3f\x4a\x61\x27\x1c\x11\xcc\xde\xb0\x29\x0f\x4f\x2f\x6f\x05\xbf\xd7\xa6\xbc\x51\xc0\xfa\xcc\xa6\xd4\x2f\x9f\x67\xd1\x10\x04\xbb\xcc\xd8\xc7\xd5\x4e\x80\x33\x5d\x17\x35\xf7\xc6\xb9\x3c\x9d\xd9\x98\xf2\xc8\xed\xf4\xc6\x6e\xd7\x49\xb1\xa6\xb2\x18\x42\x73\x35\x8a\xb7\x83\x0c\xe5\x3b\x54\xd4\xe7\x5e\x2b\xdb\x18\xd4\x52\x85\xec\xb6\xd5\x12\x43\x3a\x8d\xed\x66\xaf\xb8\xdd\x72\x53\xd0\xc2\xbc\xd2\x04\xb3\xb2\xea\x92\x5a\xec\x2d\x3a\xb3\x6d\x0e\xe4\x54\xac\xcd\xdd\x20\x52\x3f\xf2\x0c\xe4\xa3\x75\xfc\x7b\xcf\x40\x3e\xee\xfd\xd9\x24\xef\xff\x1c\x1b\x53\x52\x12\x9c\x17\xfc\x85\x7b\x43\x8a\xf2\x11\x36\xe6\xb4\xc3\x2c\xa7\xa1\x5e\xea\xb4\x91\x04\x86\x5e\xde\xb8\xad\xf2\x30\xd8\x5d\x8c\xc3\x27\xd8\x9c\xa4\x3a\x5f\xf9\x04\xfe\xbf\xe7\xfd\x8f\x36\xe7\xb3\x14\xc5\x97\xfa\x31\xbe\xa0\x82\x05\x12\x72\x16\x90\x20\x46\x91\x60\xc4\x47\x14\x41\x49\x84\x27\x39\x0a\x7d\x8a\x38\x09\x23\x44\x18\xc7\x8c\x49\xc2\x70\x04\x02\x2e\x10\x09\xa2\x08\xd0\x83\x7a\x27\xe2\xfe\xe8\xe5\x1f\x9e\xd2\x08\x44\xc5\xcd\xd2\xbb\xcf\x4f\x9f\x6c\x17\xc1\xe0\x03\xa2\x97\x5b\x57\xc3\xfe\x62\x05\x9a\x40\xfb\xdd\x88\x5e\x56\x95\x52\x65\xcc\xf2\xa4\xbf\x5a\x74\xa6\x71\x7d\xa2\x6f\xc6\x4b\xbd\x3a\x70\x8d\xec\xd6\x48\x37\xc7\x3b\x3d\x3d\x33\x7a\x29\x3f\x2c\xb5\xf6\x3d\x68\xb3\xd6\x70\x33\xae\xa4\x76\x86\xdd\x19\xa1\xd4\xa8\xe2\xb5\x02\xb6\x6f\xae\xb6\xbd\x62\x5f\x1f\x0e\xf7\x99\xa8\x9a\xde\x16\xd6\xd5\xf2\x47\x45\x2f\x9f\xcf\x90\x77\x46\x03\xc7\x22\x9e\xc4\x67\xb1\x8a\xcd\xd3\x8f\x9f\x17\x0d\xfc\x81\xf4\x7e\x49\xb4\xf5\x99\x45\xbb\x23\xa2\x35\xbd\x4d\x75\xe5\x57\x47\xb4\xfe\x8d\x22\x70\x15\xe5\xaf\xdb\x79\x7b\xf5\x64\x69\x9d\x9c\x77\x87\xb1\x4e\x9f\x84\x2a\xd3\xf8\x64\xde\xdd\x3b\xd6\xd7\xb2\xf9\x99\xf4\x3e\x5a\xe7\x4e\x36\x3b\x4d\x75\x57\x06\x9f\x1b\x05\x07\xcc\x32\xc2\xe4\x35\x60\xe6\x55\x45\xd4\x2d\xd8\x16\xdd\x34\xeb\x19\xeb\x11\xb6\x73\x0b\xb2\x6c\xa4\x86\xd3\xc0\xdc\xaf\x17\x3d\x8d\x98\xcb\xf5\xb4\x3f\x1a\x8e\x2b\x0b\xe8\x2f\xdc\x1e\xd9\xd2\x76\xb0\x71\x06\x96\xa8\xcf\xc1\x57\x47\x53\x44\x9e\xc4\x51\x1c\x8a\x00\xc5\x24\x22\x34\x00\x18\x8a\x80\xc9\x28\x90\x54\x30\x84\x3d\x10\x11\xcc\x49\x4c\x40\x48\x99\x8c\xa2\x00\x22\x12\x12\x1c\x08\x8f\x92\x90\xa1\x07\xeb\xfc\x01\x25\x47\x7f\xe8\x07\x4a\x4a\xe0\xed\xdc\xa2\xc3\xd3\xe3\x79\x15\x80\x82\x61\xc2\x38\x00\x1f\x50\x72\xb4\x79\x35\xec\x67\xd6\xf9\xcc\xc8\x36\x9f\x34\x71\x46\xc9\x34\xf4\x95\xe3\xa6\x4a\x76\xa7\x95\xde\x64\xd7\x34\x55\xce\x36\xbb\x32\xde\x90\x51\xb4\xd8\x6f\x23\xa7\x22\x85\xae\x55\xe3\x8e\xd3\x8c\xd4\x36\x8f\x2a\xbe\x6a\xa0\xc9\xbc\x9e\x6f\x94\x95\x74\xbd\xc0\xf4\xa6\x4c\xaf\xec\x66\x7d\x6b\x54\xab\x2d\x63\x31\x81\xd5\xc9\x56\xcf\xfc\x9c\x5f\x67\x9e\x7e\xf9\xb0\xe2\x7e\x97\x15\x31\xe6\x5a\x5f\x75\x37\x0f\x89\x34\xd9\x3e\x0e\x3b\x5a\x75\x0a\xcb\xb4\x81\xe3\x4c\xbd\xa2\x6e\xd3\xe3\x39\x75\x96\x3d\x75\x54\x36\xd1\xa4\x64\xb6\x4b\xdb\x54\xc9\x2d\x60\x73\xf3\xf0\xd5\x38\x88\x8a\xe7\x33\xe3\x44\xdb\xc9\xc2\x17\x93\x16\xd6\xe9\xad\xfc\x76\x68\xad\xcf\x6a\x7f\x9e\x4d\xed\xcf\xb3\x98\x1f\x48\xef\x97\xac\x48\xce\x62\x41\x12\x6b\xfd\x02\x5d\x0e\x41\x4a\x9e\x6a\x7f\x7e\x8d\xd6\xff\x1b\x59\xa9\x23\x7f\xcf\x6a\x75\xbf\x67\xae\x14\xf3\xbd\xb5\xca\xb5\x74\xea\x38\xa8\xc5\xaa\x72\x39\xa6\xd5\xf7\xe2\x25\xe1\xef\xfb\xe8\x9d\x7b\x7a\x34\x08\x82\xf1\xd7\xd0\xfb\xea\x0a\xe6\x8c\xd7\x49\x64\x39\x7d\x5a\x48\x65\xae\xf5\xe6\xaf\x25\xcb\x2f\xe7\xde\x67\xd2\xfb\x14\x7b\xf3\x49\x06\xeb\x4b\x2f\xf9\x41\x80\x87\x11\xf5\x39\x45\x04\x47\xc0\x07\x0c\x05\x58\x60\x1c\x53\xc1\x01\x66\x3e\x8f\x64\xcc\x08\xa1\xd8\x8f\x88\x8c\x63\x0a\x62\x1c\xe3\x38\x0c\x38\x85\x2c\x0a\x98\x7f\x58\xc1\x3c\x95\x65\xcd\xd6\x28\x6e\x29\x9a\x51\xa8\x34\x70\xbb\x50\xc6\x44\xad\xeb\x4a\x4b\xe7\x7a\x93\x15\x18\x56\x33\x66\xad\x61\xb7\x1a\xd9\x4c\xae\x5e\x72\x79\xad\x56\x2d\xe0\xba\x55\xa8\xd4\xbf\xff\xfe\x0d\x4a\x8c\x38\xa6\x48\xe0\x1f\xae\x65\x28\x60\x4c\xde\x3c\x27\x7d\x7e\x0a\x25\xa7\x4c\x10\x29\x39\x7c\xde\xd3\xae\x58\x21\x52\x6a\xea\xb8\x81\x87\x76\x28\x72\x06\x29\xea\xa9\x68\x3d\x8c\x90\x51\x70\xc1\xd8\xeb\x6c\x86\x83\xbd\x4e\xb6\x9d\xf9\xc3\x9c\x3d\xae\x65\xd4\x63\xa8\xc0\x1b\xb1\x37\x8d\x53\xfb\x9d\xf8\x37\x4a\xa1\xfe\xcc\x27\xf3\xac\x13\x34\xa5\x32\xc8\x57\x2c\xbb\x92\xc9\xd6\xab\x7c\xdc\x42\xed\x71\xca\x1f\x2e\x90\x95\x6d\x44\xfe\x00\xa5\x07\x38\xdd\x99\xe9\x85\xaa\x88\xdc\x4a\x6e\x91\x65\xe3\x4c\xa4\xad\x77\xa5\xac\xa0\x62\x3d\xa1\x19\xcf\xef\x57\x37\x19\xd9\x1b\xf7\x95\x8c\x51\x12\xd1\x22\xdb\xe5\xbe\x36\x50\x7f\x62\xcd\x74\x9e\xdb\x70\x7b\xdd\x72\xb6\x77\x4c\x24\x76\x33\x5a\x21\xb4\xa3\x66\x19\x6f\x1a\xfd\xce\x22\xa6\x2c\xd5\xe4\x6e\x67\xda\xaf\x87\xb3\xac\xda\xb2\x4b\x71\x3f\xaf\x2e\x77\x81\xba\x9d\xcc\x37\xab\xad\x95\x1e\x9f\xc6\xe0\xc6\xe7\x07\xeb\x90\x8f\x7b\xff\xbd\x97\x6d\x7c\x8e\xdd\x3b\xff\xbc\xad\x5b\xff\x26\x76\xf7\x55\x3b\xb6\xbc\x87\xf6\x27\x41\x2d\xbe\xb5\xf3\xf0\x65\xbc\x7b\xcf\xfb\x9f\x2e\x5d\x9a\x66\xfa\x7d\xb0\xef\x54\xc1\xa0\x42\xe1\x72\xd4\x4e\x8f\xa8\x5f\xee\x6f\xa0\x3e\xa2\xe5\x35\x2d\xa7\x49\xa1\xbb\x1b\x58\xfa\x28\xdb\xf5\x95\xd4\x74\xe3\x74\x8b\xa2\xaf\xa4\x2b\x71\x91\x55\xaa\xad\x11\x01\x25\x25\x76\xa7\x64\xa3\xd4\xb3\x96\x3e\x57\x48\x84\xb6\xe6\x57\x97\xbb\x0d\x11\x89\x89\x60\x7e\xc8\x11\x8a\x43\x28\x38\xf5\x05\xc1\x02\xcb\x48\x08\xe0\x87\x51\xe4\x61\x44\x22\x44\x43\x9f\x03\xe6\x21\xe6\xc5\x34\x22\xa1\xe7\x89\x80\x02\x0e\xa3\x27\x3b\x83\xee\xf4\x94\x7f\x14\x85\x43\x01\x13\xf4\xe6\x89\xe9\xf3\xd3\x07\xeb\x42\x01\x16\x1f\xe1\x29\x5f\x57\xd8\x79\xdd\xba\xbc\x13\xff\x1e\xeb\x72\x56\x1e\xd7\x35\x80\x5d\xaa\x36\x5b\xd6\x7a\xac\xa2\x82\xe5\x67\xa7\x5d\x59\xda\xed\x69\xa3\xb4\xca\xd4\x0c\x77\x89\xdc\x6a\xb8\x1c\x5a\xee\xff\x4f\xde\x79\x2c\x37\xae\x2b\x0f\xff\x55\xfe\xbb\xbb\xd0\xad\x12\x72\x58\x7c\x0b\x8a\x49\x59\xa2\x32\xb5\x23\x41\x50\x39\x67\x3d\xfd\x57\x23\xd9\x16\x8f\xc7\x49\xc1\x9e\xb9\x75\xb0\x38\x75\x3c\x90\xd4\x20\x00\xf6\xaf\x1b\x68\x34\x4c\xd2\xcc\x06\x13\x7f\x9a\x5d\x95\x7a\xfd\x79\xae\x14\x07\x75\x5e\x6a\x47\xd9\x8d\xeb\x0b\x98\x72\x32\xb3\x63\x65\x55\x4f\xa5\xb3\xee\xac\xef\x59\xdf\x41\x97\x5b\xbc\xcc\xc4\x71\xa2\xc6\xdb\x5d\xf1\x75\xba\xdc\x29\xff\x9d\x2c\x4b\xb7\xd0\xe5\x81\x96\x7e\xb2\x7c\x59\x43\xfe\xcd\x9e\xc6\x67\x74\xb9\xa1\xed\xe9\xe4\x65\xdc\xef\xac\x3c\xff\x58\xdf\x5d\x23\xff\x89\x2e\x6d\xb3\x6c\x1f\x6d\xa7\x35\xe4\x74\xb7\x1e\x0c\xd1\x8e\xf9\x71\xa3\xb4\x4a\xb5\xac\x62\xaf\x59\x77\x8b\xd1\xc4\xce\x86\xdd\x06\x32\x36\x4e\x06\xcd\x27\xf9\x3d\xb7\x72\xb9\xa0\x6e\x65\xd1\x68\x73\x74\xa6\x35\xde\x9f\x54\xcb\x71\xdf\x0b\x4a\xc7\xa5\xbd\xdd\xee\xf7\x8b\x5c\xd3\xf8\xe1\x74\xad\x34\x24\x48\x71\x0e\x08\x8a\x01\x09\x63\x0e\x19\xa3\x32\x00\x54\x73\x75\xba\xb9\x14\xe0\x20\x06\x58\x04\x3c\x0a\x38\x0d\x21\x08\x05\xc5\x82\x03\xae\x64\x1c\x43\x8e\xe2\x5f\x74\xb9\x3f\x99\x3a\xfc\xec\xdc\x00\x85\x82\xf3\x77\x2f\xf2\xfb\x55\x2b\x2e\xce\x10\x46\x04\x3e\x20\x97\xfa\x6b\xc5\xf6\x1b\x0c\xae\x37\x8b\xff\x31\x9b\x92\x9b\xa4\xae\x39\xae\xe9\xaa\x32\xec\xbd\x97\x6e\x17\x96\xb3\x19\x4e\xe3\x28\x56\xfd\x6a\xfa\x90\x13\x8d\x9a\xb5\x5c\x0e\xd7\x69\xd5\xef\x0a\xdc\x2c\x0e\x1a\x8a\x92\x31\xdd\xa9\x23\x34\x46\x61\x31\x60\xa6\x11\xcc\xa3\xba\x3b\x6f\xb6\x3b\x23\x3a\x5a\x35\x16\x56\xa7\x38\x25\xc6\x57\xee\x9f\xff\xc7\xac\x7e\x17\x16\x89\xcf\x5f\xa1\xac\xcb\xa4\x18\x94\x72\x95\x38\x99\xd2\xa0\xfe\xa6\xe4\xcf\x60\xf1\x38\xf9\x37\xc1\x2a\xb1\x89\x79\xa3\xc2\xc3\xbd\xf5\x6c\xd7\xa3\xf7\x2b\xbc\x3f\xa8\x70\x0d\xe3\xcf\xb9\x13\x6f\xc2\x67\x75\x5b\x5f\x3c\x8f\x85\x79\x31\x1c\x32\x37\xdd\xff\xff\xc0\xb9\x70\xc3\xfd\xff\xfd\xde\xbc\xd9\x19\x62\x23\x53\x6a\x56\xe1\x60\xc1\x0a\xe5\xb4\xc4\x1d\x9c\x6b\xa4\xc5\xa0\x6a\x03\x8f\x31\xc2\x63\x9c\x6b\xc7\x65\x68\x92\x11\xae\xe8\xbc\x56\xd9\x92\xf4\xf2\xee\x01\x6d\x7a\x3d\x77\xd1\x69\xf6\x17\x2d\x67\x4c\x2b\xdd\xa2\xcd\x7a\xf0\x40\x53\xc6\x4f\xdf\xff\xaf\x01\xe7\x38\x02\x3c\x08\x03\x84\x23\x08\x35\x0b\x00\x0b\x01\x82\x4c\x20\x24\x49\xa8\x61\x2c\x63\x04\x50\x80\x24\x62\x02\x71\x80\x10\xc5\x92\x31\xa4\x34\x52\x3c\x3e\x85\x85\x3e\xe7\x0a\x37\xb3\xd5\x8e\xdb\xb2\x0a\x55\x87\x16\x1a\xc4\x2c\x1b\x0d\xde\xe1\xbc\xd2\xf1\xbb\xdc\x6f\xd9\x24\x9f\x2d\x38\x56\x33\x6b\xba\x66\xab\x6d\x16\x49\x81\x54\x3d\xc6\x0b\x85\xee\x2f\x6a\x08\xc2\x04\xa6\x12\x73\xf4\x29\x86\x90\x04\xf4\xdd\x23\xd5\x2f\xb5\x50\x08\xc9\x05\x65\x14\xa2\x97\xe3\x6b\x39\xce\x27\x8b\x72\xe3\x20\x5b\xd5\xde\xa4\x37\x4d\xa5\xd3\x9b\xed\xb0\x2a\x5a\xf9\x7d\x1e\x3a\x59\x8f\x0c\xcd\xa5\x5f\x4f\x15\x48\x2a\x7b\x5a\xca\x3d\x2f\xa1\x9d\xa6\xf8\x07\x4b\x68\x67\x2b\xfa\xa6\x6d\x1d\x7f\x39\x24\x5a\x9c\x53\x1a\x0d\xf3\x7c\x97\x59\xd6\xe6\xab\xa5\x9a\x2e\x32\x5e\x7b\x78\x38\xee\xb6\xad\x23\xda\xd2\x66\x9e\x32\x97\x81\x5c\xbf\xb7\x0a\xda\x9e\x53\x8f\x53\x7c\x36\x21\x0c\x15\x1a\x33\x95\xca\xe6\x11\x0f\x8a\xad\x8a\x27\x70\xe4\xf6\xe1\x60\x3b\x4f\xb5\x72\x9b\x9a\x9d\x5f\xa4\xeb\x99\xdd\x97\xb6\x0f\x13\x13\xff\x12\xaa\xfd\xe1\x76\x5e\xa2\x23\x86\xdb\x4d\x30\x83\xd5\x22\x6c\xa6\xcc\xc0\x8c\x79\x3a\xc5\x52\xa5\xf4\xbe\x39\xb5\xa7\xcd\x66\x64\x0d\x4a\x85\x75\xbf\x48\x9e\x9f\x33\x71\xab\x90\xb9\x7a\xfb\x7d\x3b\x95\x4f\x58\xf4\x38\xf9\x37\x2d\x8b\x25\xb6\xdb\x96\x89\xaa\x2b\xf5\xcf\xb4\x84\x8d\x44\x0a\xf9\xdb\xf4\xdf\x1f\xd4\xbf\xaf\xf5\xbf\x59\x49\xd1\xc5\xb0\x29\xb6\xad\x06\xc9\xcf\xf2\xe9\x6d\x9a\x2f\xc9\x31\xed\xd4\x55\x3d\xaa\xd5\x40\x25\xb7\x5b\x20\x7b\x3b\xd8\x54\xfb\xfc\xa4\x75\x2f\x73\xad\xb0\x33\x6e\x58\x16\x4c\xb4\xf7\x8a\xf7\xfa\x0d\x86\x2d\xef\x7b\x86\x73\x03\x0b\xb7\xdf\x46\xf5\xc0\x3e\xbc\x46\xfe\x73\x3a\xa7\x6f\x52\x3c\x3f\x7a\x04\x9b\xd0\x90\x41\x0e\x23\xcd\x09\x0f\x42\x8c\x70\x88\x55\x14\x50\x84\x24\x90\x18\x47\x31\x96\x3a\x8a\x38\x60\x30\x66\x1a\x31\xc0\x19\x62\x0c\xeb\x58\x51\x18\x2a\x15\x82\x5f\x0c\xbb\x3f\x49\x2e\x14\x9f\x91\x8b\x40\xcc\xdf\x0d\x33\x7d\xa9\x7d\x66\x21\x17\xe8\x01\x61\xa6\xaf\xad\xfd\xdf\x34\xde\x0d\x1a\xf4\xbd\xdb\xa8\x9c\xb0\x8e\x14\x5d\x2e\xfd\xb2\xbb\x1a\x97\x5b\xab\x71\x23\x9b\x15\x43\xb1\x07\xbd\x9e\xde\x41\x9d\xcd\x56\x9a\x8d\x72\x30\x2c\x55\x0f\xc2\xf5\xa7\x14\xd5\xea\xbb\xda\x54\xed\x76\xdb\x2d\xd4\x43\x3b\x36\x52\xbd\xf4\xa4\xd1\x29\xcd\x3b\xcb\x4c\x45\x10\x6e\x12\x56\x98\x3d\xcc\x83\x2a\xdc\x16\xd4\xf1\xe2\xc1\xa4\x2e\x5f\xaf\xbd\x29\xf9\x13\x6a\x3c\x50\xfe\x4d\x1e\x5c\xc2\x83\xba\x83\x5a\xbf\xa8\x61\xdd\x4b\xad\x3f\x48\x4d\xc3\xf8\x73\x1a\xff\x4d\x0f\x6a\x72\x7b\x5f\xfc\x1a\x0b\xe7\x62\x4e\x66\x6e\xda\x58\x7b\xe0\x5c\xb8\x46\xfe\x13\x7d\x6a\x6d\xb0\x9e\x56\x02\x86\xac\xda\x32\xdf\x68\x85\xf9\xe6\x7e\x9f\xce\xa5\x4b\x51\x2e\x97\x5d\x95\x3b\xfd\xfd\x71\x6c\x1f\xdb\xb3\xa3\x25\xb6\x99\x49\x3e\x15\x8d\x9a\x2b\xbb\x8b\x4b\xa5\x22\x97\x9d\xd9\x3e\xbb\xab\xce\xaa\x74\x04\x8f\x85\x16\xdb\x35\xb6\x95\xca\x6e\x53\x19\x2c\x7e\xda\x83\x8a\x18\x57\x71\x88\x38\x0c\x84\x90\x9a\x0b\x4a\xe2\x38\x62\x30\x04\x42\x07\x2a\xd2\x9c\x45\x94\x69\x4e\x05\x61\x2c\x56\x98\x07\x42\x6b\x85\x22\x1c\x10\xa0\x63\x11\x42\xf2\x8b\x3e\xcf\x49\x60\x2d\x52\x2f\x55\x6c\xdc\xaa\xd6\x1d\xde\xad\x61\xb3\x61\x7b\xb8\x4a\x9b\xe5\x46\xa6\x64\xe7\x2d\x03\xb9\xc5\x4e\x23\x5b\xe3\xa5\x92\x51\x33\xca\x85\x42\xde\xea\xf2\x5a\xd5\x75\x7e\x51\x83\x61\x04\x04\xa7\x1c\xd1\xcf\x8e\x3b\x50\x8a\x24\x7b\xdf\x83\x7a\xae\x85\x02\x60\x21\x18\x06\x14\xbd\x6c\x13\x55\x47\x93\x4a\x7e\xb3\xa4\x4e\x7a\x52\xd9\x37\xf2\x56\x98\x02\x61\xa9\x68\xe6\x5d\xab\x36\xc6\x13\x5d\x45\xa5\x8c\x6d\xb5\x0a\xf5\x6a\xf5\x34\x2f\xce\x1e\x94\x6f\x7c\x9c\x94\xea\x3c\x85\x17\x88\xad\x9a\x6a\x1c\x4b\xea\xe2\x89\x71\x5c\xcc\xfa\xca\xd8\xaf\xe7\x3a\xd5\x1c\x04\xb3\x6d\x61\x67\xcd\xcd\x2d\x02\x6b\x16\x3a\x27\x0e\x65\x6a\xad\xd6\xef\x7a\xb0\x39\xcf\x89\x74\xef\xf4\xf3\x76\xb5\xa0\xbc\x89\xd1\x70\xe7\x7a\xbb\x5c\x8f\x0d\xd5\x9d\x96\x73\x69\x77\x18\x17\x8b\x9e\x3d\x97\x41\xc5\x72\xdd\x9a\xd3\x4a\x21\x93\x34\x2b\x22\x6a\xa6\x9a\x46\xa9\x31\x32\xeb\x1d\xaf\x68\xa5\xf6\xd5\xa0\xe6\xed\x8f\x3b\x89\xeb\xca\x9e\x8d\x98\x7b\xf4\xcd\xf5\x9a\x67\xbe\x96\x20\x24\x9b\x9c\xe8\xef\xf2\x28\xb1\xfd\x92\xaa\xfb\x64\xc2\xb6\xa3\x4e\xca\xe7\x4e\x69\x54\xde\xf2\xda\x6a\xb7\xca\x8d\xfc\xb2\xdb\xd1\x5d\x92\xf6\x77\xb6\x57\x7e\x79\xb6\x44\x02\xa9\x73\xdf\xbe\x3e\xd8\xf5\xf4\xf7\x27\x3c\x7a\x9c\xfc\xd7\x82\xbe\x24\x3f\xa1\x03\xe7\x97\xfe\x31\x97\xe1\x62\x5f\x3b\xb4\xd2\x78\x14\x6a\xdf\xaa\x2c\x06\xce\xce\x72\xd1\x98\xd3\x7a\x7e\x31\x10\x4b\xa3\x32\x2a\xa4\xc3\x3a\x9e\xaf\x3a\x27\xfd\xeb\x38\xad\xd6\x13\x03\xae\x9c\x9b\x4f\x4d\x49\xbf\x94\x37\xbd\x90\xd3\xdf\x8b\xbf\xa7\x7d\xc9\xf2\x26\x4f\xe6\x89\x61\xa0\xf9\xe1\x20\x5c\xa4\x6a\x31\x1d\xae\x9a\x07\x0f\xa5\xd7\xee\xd1\xdc\x0d\x6a\x3d\xd0\x8d\xe8\x74\x28\x87\x46\xcd\x80\xf5\xd1\xf0\x78\xb6\x2d\x2e\x87\xd6\xf2\x97\xdf\x4b\x94\xa7\xbf\x3f\xe6\xc9\xe2\x3e\xf9\xe7\x10\x8b\xeb\xe5\x3f\xf1\xe4\xbb\x5e\xfa\x1f\x4d\x72\x18\x21\x8d\x41\x1c\x51\x4e\x24\x0a\x63\xa4\x51\x08\x31\xd2\x30\x54\x12\x06\x94\x88\x00\x33\x09\x85\x0c\x75\x18\x73\xae\x43\x14\xe2\x48\x20\x09\x11\x0c\x64\x84\x14\x3d\x79\x33\xf0\x91\x3c\xf9\x34\xec\x80\x51\x78\xca\x65\xfe\x71\x2d\xe4\x0c\x48\xcc\x18\x46\x18\xdd\xcf\x93\x0f\x92\x7f\xdc\xc6\x93\x56\xab\x6c\x27\xe6\xf1\xb9\x24\x78\xc2\x2a\x28\xd6\xb0\xe7\x65\x76\xb3\x0a\x88\x4b\xe5\xb2\xdd\x2c\x64\x81\x17\xb5\x3a\xad\xa1\xdd\x0e\xcb\xb4\x55\xa4\xd0\x9a\xd4\x9a\x3a\xf2\x4b\xa5\xce\x3a\xec\xd0\x7c\xa1\x55\x3f\x8e\x03\x34\xca\xb9\xdb\x76\x6f\xbc\x82\x51\x67\xd3\xc9\x76\xfd\x74\xae\x32\x0e\x0a\x00\x2e\xbf\x18\xe0\xff\x35\x9e\x24\xbe\x7a\x8b\x3e\x87\x97\xbe\x7d\xed\x23\x7e\x8d\x27\x8f\x93\xff\x7a\x6c\xaf\xe5\xc9\xec\xd2\x3f\x57\xeb\xeb\x56\x13\x3c\x3d\xc8\xc3\xf5\xf5\xcb\x33\xdc\xc3\xbb\x07\xb7\x2f\xd9\xa7\x6f\xf2\x64\x9a\x18\x86\x1b\xf4\xf9\x79\x75\xea\xac\xcf\x5f\x8f\xdf\x97\x78\x72\x27\xcf\xce\x87\xc0\xaf\x97\xff\xc4\x93\xef\x7a\xe9\x7f\x92\x27\x81\xc0\x28\x8e\x19\x07\x82\xaa\x50\xea\x90\xc5\x50\x91\x90\x13\x10\x33\x0d\x30\x0e\x03\x19\x52\x20\x82\x98\x23\x1a\x87\x31\x02\x98\x30\xc9\x91\x0c\x18\x09\xa0\x94\x71\xfc\xc4\x13\xf4\x30\x9e\x7c\x1a\x24\xcd\x28\x79\xff\x5e\xd8\x53\xad\x4c\xf0\x84\xe3\x47\xf8\x27\x1f\x24\xfe\xb8\xd7\x3f\x79\x9b\x27\xd0\xd3\x62\xda\xdb\x19\xe5\x23\x89\x8b\x0b\xdf\xec\xef\x6a\xc3\x1a\xdd\x4f\x7b\x4c\xe5\x16\x4d\xda\xce\xac\x87\xa3\x6e\xcf\x21\x9b\x5e\xab\x3f\x10\x79\x36\x6a\xcc\x0d\x73\x3b\xdd\x76\x56\x33\x9c\x6b\x1d\x26\xac\x16\x47\x2c\x1f\x79\x6d\xe1\xa9\xe2\xc8\x69\x74\x60\xc9\xfd\xe2\x25\x16\x3f\xcd\x93\x9b\xf4\xf9\x03\xe5\xdf\xe4\x1f\x3d\x88\x27\xdf\x68\xff\x1b\x8f\xe0\xc9\x37\xfa\x4f\xdf\xe1\x9f\xdc\xaa\xcf\x8d\x07\xf1\x24\xe9\x1f\xdd\xc0\x93\xef\x7a\xe9\x7f\xd4\x3f\x89\x03\xc2\x78\x48\x71\x4c\xb1\x60\x11\xe7\x41\x84\xa9\x42\x14\x20\x1d\x21\x15\xe1\x28\x12\x21\x61\x20\xa0\xa1\x46\x28\x64\x21\x12\x50\x84\x02\x86\x2a\xc2\x3a\x42\x51\xf0\x8b\x27\xcf\x49\xd8\xcd\x56\x9b\x16\xcd\x5a\xd7\xa9\xf2\xaa\x5d\xee\x34\x0c\xb7\xd2\xca\x79\x1d\xc3\xb2\xca\xcd\x4e\xa7\x9b\x37\xcb\x05\x87\xb4\xbc\x0c\xca\x15\x78\x1b\x15\xab\xf9\xb6\xc3\xf1\xe9\xe2\xbc\x0b\x4f\xc8\xa7\x11\x03\x02\x10\xf1\xfe\x7a\xd7\x73\x2d\xe4\x90\x4b\xc1\x24\x95\xf8\x25\x72\xad\xb0\xde\x2c\x9d\x6c\xbe\x93\xd6\xb5\x35\xed\x95\xd8\x22\xd7\x31\x4a\x61\xd0\xd9\x8e\x73\x93\x45\xf1\xb0\x32\x98\xb7\x94\xeb\xa2\x9e\xec\x63\xe3\x9f\x3c\xf9\x20\x62\xe0\x5c\x7f\xf1\x37\xae\x98\x87\xd9\xcb\xeb\x76\xf9\x3d\xe7\x45\xbe\x57\x28\x8b\x62\xbc\x36\x82\x58\xcf\x0c\x77\xb2\x9d\xaf\xec\xd9\x68\x31\x21\x7c\x68\x6c\x16\x3b\xd2\x83\xcd\xf6\x70\x52\x04\x43\xe6\x55\x27\x70\xb8\x9f\x05\xe3\xa3\xb5\xb3\xea\xb8\x9d\x2a\xa3\x6c\x25\x1b\x0d\xeb\xf9\xb1\xed\x05\x8d\xbd\x9b\x89\xbd\x42\xb6\xbf\x64\xd3\xf2\x2a\xc9\x08\xe3\x5d\xa6\x24\x2f\x79\x7a\x9f\x29\x89\x0f\x5d\xc9\xd3\xd3\xce\x7d\xe5\xd2\xbf\xef\x94\x4f\x98\xf2\x38\xf9\xf7\x26\xc5\xbd\x1c\xf6\xbb\x5a\x67\x7f\xa6\x07\x9f\xca\xc7\x7a\xf0\xd1\xf2\xaf\x4d\x8a\xfb\x97\xfa\x68\x9f\xed\xd1\xdc\xd2\x57\xe7\xb6\xe6\x7f\x4b\x44\xf6\x95\xbe\x7a\xc4\x58\x25\x7d\xb0\x6b\xe4\x3f\x31\x6b\x86\x77\xeb\x14\xc8\xcc\x25\xeb\x19\x41\x90\x9a\xec\xea\x83\xfa\x22\x1c\x6e\x4a\x26\x5b\x5a\x03\xab\x55\x0b\x2a\xfe\xb6\x5e\x9d\x1b\xa9\xb0\x5d\x75\xfb\x8b\x4e\xa9\x6a\x94\x8b\x51\x48\xb0\xaf\x48\x84\xca\xb9\x49\xb3\x96\x99\x57\x6d\xdf\x91\xc6\x4c\xbb\xdb\x85\x42\xbb\x9f\xde\xa3\x01\xa1\x0a\x19\x0f\x02\xcc\x28\x21\x2c\x8e\x10\x21\xb1\x56\x71\x8c\x03\xa0\xb0\xe4\xb1\x80\x31\x0e\x64\x08\x31\x41\xe2\x74\x0b\x07\xd5\x9c\xb3\x88\x10\xae\x40\x08\xf5\x33\xb3\xd0\xa3\x98\xf5\xf9\x9a\x9a\x00\x1f\x2c\xa9\x3d\x55\x9e\x89\xc5\x01\x00\x97\x15\xb5\xdb\x89\xf5\xc1\x8a\xda\x59\xe3\x5d\x3c\x9a\x07\x12\xab\x54\x6d\xf5\xfc\x38\xb5\x03\x32\xd2\x73\xab\xbe\x2f\xa9\xfc\x74\xd8\xea\x66\x0d\xe4\x8c\x47\x99\x49\xbf\x3a\x19\x80\x32\x63\xce\xa6\x6f\x1c\x1b\x7a\xd4\x56\x66\xa5\x14\x99\x39\xa0\x9a\x2a\xb5\xcf\xf7\x0f\xbb\x62\xa7\x5e\x1a\x14\x0c\xb6\xab\xb2\x82\x24\xe5\xda\xd8\x19\x7b\xf6\xdf\x48\xac\x9b\x52\xee\x3e\x50\xfe\xbd\x29\x77\x1f\x48\x8c\x9b\x52\xee\x3e\x5a\xfe\xb5\x29\x77\xff\x52\x2f\xf0\x4d\x62\xfd\x21\x62\x18\xdf\x30\x56\xd7\xc8\x7f\x22\xd6\x4e\xb6\x33\xfd\x34\xb7\x1a\x10\xb2\x51\xb9\x68\xef\x77\x13\x5d\x6e\x8d\x94\xe5\xb7\xdb\x9e\x1b\xd8\xa9\xa0\xe8\xe1\xe5\xac\xcd\x6c\xab\x5c\x66\xb5\xee\x2e\x47\xf6\x20\x37\xac\xed\x6b\x47\x6e\x4f\xb2\x45\x63\x1d\xe5\x0e\xb9\x99\xb5\x34\xd2\xb3\x25\xee\x41\xb7\xd9\x6e\x19\x3f\xbc\x6a\x07\x21\x07\x34\x96\x44\x45\x8c\x46\x3c\x64\x1c\x07\x10\x91\x40\x50\xa5\x31\x13\x4a\x80\x58\x10\x2a\xe2\x38\xd0\x51\x1c\x73\x28\x31\x20\x91\x88\x05\x91\x14\xd3\x90\x68\xf0\x9f\xff\xfe\x1f\x96\x0f\xdc\x05\xfa\xdc\xcb\x92\xe8\xfd\xc3\x41\xe7\x3a\xc8\x38\x05\x98\x23\xc1\x08\xb8\x7f\xc5\xee\xb3\xb4\x06\xaf\xe7\x49\x42\x9f\x7d\xa9\x64\x5e\x3c\x7f\xdb\x3c\x0c\xad\x00\xea\xd4\x70\xdd\xd9\x8c\x1a\xcb\xec\x78\x53\xe1\x7b\x50\xda\xf3\xf6\x90\x4c\x6a\xb3\x12\xa9\xd3\xa6\xe1\x4c\x6a\xad\x14\x5a\xb6\x66\xfb\x61\x69\xb7\x70\xf2\xfd\xb5\x3f\xb5\x8d\x66\x0b\xca\x94\x49\x0f\x6a\x4e\x87\x95\x62\x71\xde\xde\x2f\x4d\x5d\x2b\xe4\xbd\x2f\x5d\xff\xfe\xa5\x83\xa4\xc9\x63\xe9\x37\xac\x94\x3d\xc5\x43\xdf\xee\x55\x3d\x50\xfe\xbd\x69\x0a\xbe\x71\xb7\xe2\xa9\x7c\xac\xf7\xfe\xd0\x6e\xc9\x67\x5e\xcb\x2d\x6d\xb9\xdb\x6b\x79\x60\x5f\x5c\x23\xff\x89\x01\xab\xd9\x0e\xad\x3b\xdb\x19\x6f\xf1\xb9\xcd\xf6\x34\x1c\x6e\x44\x64\x95\x34\x9c\xa5\xf2\xa3\xc0\xaa\xd8\x9b\x96\x91\xe9\x8e\x5a\xf1\x7a\x01\x83\x92\x7f\x2c\x15\xfa\x75\x3f\x6c\xe7\xf7\x86\xe3\x44\x71\xdc\xdb\xa8\x69\x41\xfb\xc7\xc1\x81\xb5\x56\xc1\x6e\x3a\xaa\x0f\x9a\x3f\x7e\xbd\x78\x10\xeb\x50\x00\x01\x28\x42\x3a\x0c\x38\x54\x01\x46\x02\x21\x1a\x86\x2a\xe6\x18\x02\x24\x75\xa4\xe2\x00\x51\xa2\x04\xe2\x8a\xd0\x50\x53\x01\xc2\x40\x4b\xaa\x38\xc2\xf0\x17\x03\xee\x4f\x9f\x0b\xd9\x27\x9a\x9f\x01\xcc\x05\x7c\x4f\xf7\xbf\xd4\x3e\xb1\x84\x41\x4c\x1e\x10\xd7\xfc\x7a\xec\x7f\xd3\x1c\x37\x58\xcb\xef\xc4\x35\x5b\xd3\xe3\xb6\xdc\xb3\xfd\x0c\xdc\xe0\x8c\xdb\xc8\x3a\xd6\x38\xd7\x9e\x8e\x80\x5b\x59\xf0\x4c\x69\x1e\xab\x83\xde\xe5\x6b\xab\x7c\x41\x8e\x1b\x24\xdb\x28\xd9\xbb\x92\x87\x86\xf5\xfc\x61\xd9\x9e\x64\xf8\x3e\xca\xec\xb3\x85\xa0\x5c\xea\x78\x81\x91\xdb\x33\xb3\xde\x2f\x76\xe6\x5e\xf6\x51\x71\xcd\xf9\xdb\x8e\xf1\x97\x49\x31\xf0\x0e\xd5\x14\xed\x5c\xbe\x5e\x7d\x53\xf2\x67\xda\xff\x71\xf2\xdf\xd1\x27\x5f\xf6\x50\x6e\x8f\xa5\x9d\x5b\xb9\x34\x1f\xab\x57\xbf\xfc\x7b\xf9\x58\xe3\xdd\x11\xcb\x4b\x81\x90\xad\x3b\xe4\x1b\xc6\x9f\x5b\xa7\x7a\x93\x3e\xfd\x9b\xfb\xe2\x34\x16\xb3\xc4\xbb\x28\xae\xec\x8b\x3b\xc7\xe2\x24\x3f\x01\xaf\xab\xe4\x3f\xd1\x87\x0a\x7e\xf4\x33\xae\x11\x85\xeb\x5d\x6d\xb4\xdf\x7b\xb4\xee\xcc\x69\x39\x33\x5c\x6c\x76\x8d\x42\x07\x97\xa6\x2b\xb3\x19\x9a\xf5\x6d\xb7\x99\xca\x80\x63\xa6\x64\xd9\xe5\x19\x18\xa8\x05\x9c\xf7\xb4\xe8\x78\xaa\x76\x98\x0c\x1b\x0e\x70\x7b\x66\x49\xf7\x46\xb3\x3a\x64\xcd\x9f\x3e\x55\x83\x30\x25\x51\x2c\x00\x82\x10\x12\x28\x02\x29\xa5\xc6\x50\x21\xc9\x48\x04\x59\x28\x74\xac\x85\x26\x12\x85\x3c\xe2\x24\xd2\x94\x48\x2c\x05\xa2\x50\x02\x0d\x01\x81\xf1\x13\x7d\xee\x4c\x7a\x03\xf9\xe7\xf4\x91\xf2\xdd\xdd\x9d\x97\xda\x67\xfa\x50\x72\xf1\x3d\x6e\xa7\xcf\xeb\x13\x20\xbf\xbd\xaf\x37\xd8\xc1\xef\xd1\xc7\x62\xed\xad\xe1\x17\xe1\x6e\x30\x5e\x45\xfc\xe8\x5b\xf9\x35\x18\x38\x95\xf4\x78\x3e\xf7\x98\x9b\xcf\x4f\xd3\x86\x68\xe6\xc7\x72\xd8\x18\x96\xca\x95\xe1\xc6\xab\x66\xd6\x06\x8f\xeb\xfb\x1a\x2d\x34\x40\xa6\x5b\x0c\xd7\xde\x41\x2c\x9c\xf1\x61\x05\x72\x2c\x6e\xe8\xb4\xda\x55\xfe\x02\xfa\x54\xa2\x6a\xb5\x75\xaf\xf6\x7f\xa0\xfc\x9b\x4e\xf5\x3c\x84\x3e\xbf\x69\xff\x9b\x7c\x8f\x3f\x78\x92\xc4\x30\xfe\x9c\xbf\xf1\xe0\x53\x35\x77\x69\x7f\xe3\x41\xf4\x49\x58\x22\xb7\xd0\x67\x97\x1a\x2f\x77\xae\x29\x55\x6e\x1e\x66\xb5\x40\xc6\x21\x8c\x72\xfd\xc6\x96\x06\x41\xb3\xd2\x1f\xd4\xbb\xe9\x5d\xd5\x31\xbb\xb1\x0f\xc8\xd1\x6a\xcc\xf8\xc8\xda\x85\x5e\x05\x83\x55\x53\xd7\x47\xd2\x68\xd7\x11\x6f\x96\xb6\x85\x7e\x57\x2d\xcb\x66\x65\x0a\xf0\x16\x97\x7e\xfa\x0a\x44\x8a\xb0\x10\x81\x14\x9a\x68\xcc\x14\xe4\x9c\xc8\x40\x12\xcc\x09\xe2\x40\x29\x46\xc3\x28\xe4\x88\x43\x15\x52\x88\x38\x8f\x81\xa4\x41\x10\x88\x18\xaa\x40\x46\x18\x21\xf5\x8b\x3e\xcf\xc9\xc9\xcd\x7c\x21\xdf\xa9\x16\x32\x4e\x2e\x5b\xa9\x60\x42\x69\xbb\xd3\x76\xa9\x69\x65\xba\x1d\xaf\xec\x3b\xb5\x9a\x9b\x33\xfd\x52\xb5\xe9\x61\x6a\x56\x3d\xd2\x6e\xd5\x71\xa1\x5b\x3c\xed\xd8\x10\xc8\x31\x96\x08\x70\xfe\xd9\xa9\x1a\x06\xa9\x80\xef\x7b\x41\xcf\xb5\x90\x0a\x09\x31\x97\x04\x90\x97\xa8\xb5\x7c\x61\x84\xf5\x2c\xdf\xcc\x2a\x1e\x57\xe4\x5a\xef\x37\x03\x37\x5b\x26\xe5\x5d\xbb\xd4\xc8\x39\xfd\x21\xf3\x30\x68\x10\xb5\x6e\xb7\x4f\x41\x4d\xe7\x35\x30\xdb\xf8\xf8\x54\xcd\xeb\x28\x83\x1b\x13\x51\x5d\xe6\xf5\x8b\x7c\xaf\x44\xeb\xe6\xac\x0d\x81\x9d\x9f\x15\x32\x99\xdd\xae\xb4\x01\xad\x5d\x2a\x4e\x85\x1e\x70\x87\x9e\x74\x2a\x6c\x87\xc7\xd2\x4b\x3b\x39\xb5\x9e\x08\x8e\x88\x58\xcb\x61\xa7\x11\x8e\x41\x2d\x22\xe5\x9e\xab\x66\x13\x70\x98\xb9\xfb\x9e\xca\x0f\xec\xda\xae\xeb\x66\x4a\x1d\x4f\x3d\x6c\xcf\x26\x9f\xf8\xea\x68\xd1\x88\x58\x6f\xec\x45\xc7\xb5\xe0\x08\x72\x97\xe5\x7c\x85\x7b\x38\xe3\xef\x4b\xbd\xb6\x5b\x9d\x5b\x71\xad\xda\x3f\xc0\x6e\x78\x5a\x33\x4c\x9c\x6c\xb1\x5f\x7e\xef\xda\x3d\x93\x07\xca\xb7\x6f\x91\x9f\xc8\x4f\x30\xba\x7c\xdf\xac\xcf\xcb\x78\x61\xb6\x32\xb8\x82\x8f\xdb\xb0\xb3\x0a\x67\xfd\xfe\x51\x5b\xca\x19\xda\x87\x8c\xef\xa7\x46\x65\x69\xa7\xb2\xc5\xd6\x78\x7d\xfa\x7c\x62\x97\xfd\xda\xe4\x7d\x89\x52\xa1\xcb\xc2\xdb\x6d\x4e\xec\x01\x5d\x39\xff\x8d\x56\xab\xf1\x0c\xeb\x2b\xf3\x6e\x3c\x7a\x7e\xdc\x34\x3e\x0f\x97\xff\x5b\x79\xf3\x9f\xdf\xe2\x64\xc2\xe6\xbc\x76\x7e\x5c\xa2\xe1\xce\x57\xdd\x95\x8c\x1b\xf6\xf4\xc6\xf7\xc9\x3f\xaf\x3c\x5f\x2f\xff\x89\x93\xc7\x71\xae\xd0\x0f\x3b\x9e\x37\xe9\xcd\xec\xac\x65\x1c\x78\xad\x63\xd1\x34\x5d\x5b\x5e\x50\xb6\x40\x93\x2f\x2d\xdd\x81\x96\x68\xf6\x0f\x28\x3c\x6e\xc3\xe1\x01\xa3\x72\x54\xde\x74\x6a\x0e\xee\x21\xa3\x7b\x18\x84\x8d\x42\x2f\x74\x33\xbb\x49\xae\x96\xcd\x8c\x7c\x7b\x1f\xfd\xb4\x97\x46\x88\x0a\x99\x12\x3a\x22\x51\xa8\x15\x25\x28\x88\x61\x10\x44\x08\x03\x00\xa3\x48\x46\x8c\x0b\x15\x43\xa9\x84\x22\x0c\x06\x8c\x62\xcd\x19\x0a\x38\xa2\x58\x47\x3a\x12\xe8\x17\x27\xd9\x23\x39\xf9\x59\x74\x37\xc3\x94\xd3\x77\x53\x60\xbf\xd4\x42\x4a\x18\x14\x02\x31\x4e\xd1\xfd\x9c\xfc\x20\xba\xfb\x6e\x4e\xf2\xc9\x6a\x96\x9c\xd7\x17\x4e\x56\x52\xba\x91\xab\x76\x9a\xdd\x51\xca\x35\x16\xbc\xc2\xb2\x22\x82\xe9\x76\x83\x86\x9b\x19\x08\xe6\xc3\x62\xdf\xed\xad\x33\xba\x7e\x18\x63\xde\x6c\xf1\xa2\x39\xef\xc6\xe6\x94\x59\x7e\x4b\xf1\xb1\x57\x69\x95\xdb\xfd\x8c\xe2\x05\xcb\xe0\x65\x2d\xb0\x51\x23\x70\xe4\x1b\xa3\xc7\x71\x32\xf1\xa1\x5b\xf4\x10\xbc\xf4\xef\x4d\xb1\x05\x0f\x94\x7f\x13\xa7\x13\x7a\x70\x78\xf9\xfe\xdf\xc6\xc9\xd3\xdf\x7f\x29\xc7\xdf\xf4\xbd\x86\x97\xfa\x5b\x74\xfa\x79\xef\x3f\x77\x99\xab\xd7\x32\xe5\x81\x4c\xbb\x46\xfe\x13\x53\x38\xa5\xa5\x9e\x8c\x6a\x93\x06\xf1\xcd\xe5\x8a\xcf\xe2\x3d\xee\xc8\x6e\x75\xbc\x61\xc3\xda\x62\x52\xda\xd8\x81\x09\x1c\x5a\x2c\x74\xe2\x75\xad\xb3\x5a\x15\xc6\x63\x51\x88\x67\xe5\x7e\xeb\xb8\x69\x19\xb4\x09\x03\xdb\x39\xae\x66\x25\x6b\x05\xf9\x51\x65\xb2\xc3\x76\xad\xf7\xd3\xd7\x36\x12\x8d\x08\x41\xb1\x46\x5a\x44\x91\x50\x4c\x30\xca\x81\x92\x31\xc5\x3c\x50\x21\x8a\x29\x80\x14\x07\x52\x08\x1c\x8b\x08\x4a\x19\xb2\x98\x70\x00\x75\x88\x84\x0c\x71\x70\x8a\x3d\xa0\x8f\x64\xca\x67\xd1\x72\x8c\x50\xc4\xde\x67\xca\x73\x2d\xa4\x00\x23\x2c\xa8\x24\x94\xdd\xcf\x94\x4f\xe3\xe5\xbe\x85\x29\xe5\x4d\x6f\x91\xca\x60\x30\x8f\xc2\xe3\xb6\xd5\x72\x8f\xb2\x56\xc1\x29\xab\xa4\x6b\x51\x7b\xa1\xd2\x9d\x55\x84\xca\x7e\xd4\x63\xe5\xcc\x86\xeb\xd5\xb6\x12\x35\xda\x1e\x9e\x6e\x67\x19\x3b\x7f\xd0\xee\x51\xd8\xb6\x3c\xd6\xbc\x41\x7d\xb0\x98\x2d\x77\xd9\xf1\x24\x65\xb8\xf1\x2e\xf7\x30\xa6\xe4\x12\xbe\xe3\x0d\x3a\xfd\x29\x5e\x2d\x11\x51\x7c\xa5\x4e\x7f\xa0\xfc\xdb\xe2\xe5\x2e\x7a\x70\x70\xf9\xfe\x4f\xeb\xec\x2f\x65\x35\xf8\x4b\x99\xf7\x26\x53\x06\x97\xfa\x5b\x74\xfa\x39\x96\xe0\xac\xd3\xaf\x8d\x56\x4f\xf4\xd5\xcd\xf2\x93\x4c\xbb\x46\xfe\x13\x53\x10\x33\x97\x24\x1b\xd7\xc7\x70\x5b\x91\xad\x66\x58\x85\x36\x8f\x49\x69\x4f\x1d\x18\xcc\x8f\x52\xef\xb1\x0f\xfb\xc8\x9a\x01\x97\xaf\xd9\x41\x50\x58\xee\x5a\x5a\xa7\x7a\xb6\x37\xcd\x93\xb0\xba\xf3\x1a\xb8\xec\x98\xf9\x42\x61\x31\xd8\x1a\xba\x1d\x12\xa3\x9b\xfe\xe9\x2b\x14\x02\x40\xa3\x20\xd0\x08\x83\x10\xc6\x9c\x60\xc2\x89\x16\x38\x08\x59\x44\x04\xe4\x51\x0c\x63\x1c\x73\xce\x18\x0c\x78\x24\x20\x8d\x39\x43\x40\x69\x8d\x02\x29\x80\x24\xe2\xc4\x14\xf2\x40\xa6\xb0\xcf\xe2\xd9\x18\x65\xf2\xfd\x53\x43\x2f\xb5\x90\x30\x80\x84\x90\x08\x32\x70\x3f\x53\xae\x38\x35\x74\x05\x53\xf0\x5b\x31\xd8\x09\xa6\x64\xfc\xe6\xb4\x85\x73\xb0\x82\xa9\x6d\x1c\x82\x03\x98\xac\x86\x3d\x5c\x3a\x76\xe3\x60\x6a\xae\xb7\xc1\xb8\xe0\xba\x29\x49\xe6\x9a\xd5\xf6\x3d\x3b\x3d\x32\x47\x68\xd4\x68\xc8\x6c\xa7\xd7\x19\x86\xcb\x60\x91\x4e\x7b\x69\xb0\xcd\x03\x63\x66\x1a\x9d\xba\x6e\x40\xd1\x1c\xf6\x1e\xe7\xa7\xe4\x12\x7b\x02\xb7\xe8\xf4\xe9\xa5\x7f\xdf\x29\x9f\x30\xe5\x71\xf2\xef\x3d\x35\xf4\x68\x3d\xf8\x7b\xf9\x58\x0f\xfe\x41\x3d\x6c\x18\x7f\x2f\x53\x3f\x8b\x80\xb8\xa5\xaf\xce\x6d\xcd\x7d\xd4\x1f\x3f\x36\x56\xd7\xc8\x7f\x62\x96\xd3\xaf\x47\x1d\x35\x6c\xf2\x78\xe4\x59\xf9\x65\xb1\x1e\x1c\x2a\x96\x3a\x96\xc7\x72\xa1\x0a\x48\x2e\x9a\x33\x3f\xe4\x78\x30\xe6\xf3\xac\x6b\x34\x52\x5e\xa1\x11\xd4\xca\x55\x10\xe9\x8c\x2e\x6f\xd6\x8b\x65\x5a\x5a\xe9\xba\x98\x7a\x66\x2f\x97\x89\xf2\xb4\xda\xd9\xd7\x2b\x3f\xed\x07\xb1\x88\x8b\x18\xf2\x38\x88\x03\x84\x21\x8f\x58\x10\x33\x2e\x35\xd4\x94\x20\x10\x63\x0a\x11\xe0\x71\xcc\xa0\x8a\xe2\x18\x41\xc5\x00\xd0\x81\x88\x05\x85\x94\x86\x58\x07\xa7\xf8\xbb\x07\xe4\x15\xa5\x9f\x91\x8a\x51\xfe\xfe\x05\xb9\x2f\xb5\xcf\xec\x23\x82\x3d\x20\xfe\xee\x75\xac\xd8\x6f\x6f\xf2\x0d\x9a\xf2\xbd\xeb\xeb\x53\x93\x5e\x21\x77\xec\x2e\xe2\xb1\x97\x2b\xe4\x16\xed\xa9\x2c\x2e\xd5\x60\x73\xb0\xf7\xbc\x53\x8d\x3b\x6e\xb3\xbf\x3d\x78\x78\x95\xf3\x32\x53\x37\xaa\xb4\xfb\xa3\xca\x9a\xf2\x66\x33\xcd\x69\x71\xdd\x3c\x90\xa5\x56\x8d\xd4\x70\xe9\x23\x95\x2d\x74\x87\x18\xcf\x37\x1b\x2d\x9c\x47\x45\x40\x24\xdf\x90\x2b\x23\x10\x1a\x59\x6f\xa3\x13\xab\x60\x95\x37\x25\x7f\x46\xa7\xc7\xc9\xbf\x29\xfe\x2f\x41\xa7\x3b\x62\xbe\x4a\x91\x49\xc9\xbd\x31\x5f\x7f\x30\xe6\xcc\x30\xfe\x9c\xc6\x7f\x93\x3e\xe1\xed\x7d\xf1\x6b\x2c\x58\x22\xb1\x2a\xb9\xb2\x2f\xee\x1d\x8b\xd7\x73\xe1\x1a\xf9\x4f\xf4\xd9\xce\x67\xe6\xa0\x84\x82\x29\x6d\x9a\xe6\xa0\x30\x9e\xa7\xeb\x0c\xe7\x96\xab\x7e\x49\xc3\x23\x86\xfb\x71\x2e\x14\xa3\x32\x37\x6d\xa3\xbb\x9f\x36\xc6\xb3\xae\xb5\xd4\x1a\x3a\xd5\x54\xaa\xce\x5b\xa5\x4d\x01\x4f\xed\xf4\x8c\xa1\xf2\x34\x73\x98\xf8\x52\xb2\x70\x39\xdd\xfe\x74\xde\x9e\x30\x94\x11\x63\x94\x40\x08\xe3\x40\x53\x00\xa9\x24\x04\x80\x48\x49\x00\x15\x07\x11\xe1\x44\xc8\x80\x71\xc8\x70\x84\x02\x4c\x62\x19\x62\x8d\x51\x20\x11\x0c\x28\x88\x4e\x11\x10\xcf\x79\x45\xcd\x9c\xe3\xd4\xbc\x42\xb6\x94\x65\x79\x8b\x9b\x05\x5a\xc9\x91\x4e\xcb\xf4\xcd\x52\xb9\x56\x76\x58\xd5\x37\x78\xbe\x61\xd6\xb0\x53\xcd\x56\xf3\x5d\xaf\xe1\xfb\x4e\x86\xda\xa7\xcb\x4d\x21\x95\x8c\x40\xc8\x01\xc0\x9f\x71\x88\x73\x82\xdf\xbd\x7e\xee\xa5\x16\x62\x4e\xb0\x90\x94\x53\x76\x89\x80\xc8\xd4\xf7\xbd\x19\xb7\x52\xf5\x2a\x19\x47\x6a\x38\x66\x83\x5d\x7e\xe8\xaf\x8b\x34\x65\xc4\x8d\x52\x33\x1a\xeb\x88\xa9\xdd\x74\x78\xbe\x5f\xeb\xc4\xa1\xcc\x29\x71\x7a\xf1\xd5\x04\xf8\xe0\x14\xd0\x3b\x3b\x84\x1f\x97\x4c\x29\x4f\x76\xa7\x5f\xb2\x0d\xe7\xb0\x6e\xee\x87\xfb\x32\x09\xa7\xf9\xd2\xd2\xce\x8f\xea\xf3\xe5\xd4\xae\xcb\x81\x3b\xaf\xec\x8d\x55\xb9\xe2\xf8\xcb\x46\x35\xbd\x5f\xbb\xad\x51\xba\xda\x45\xb3\x46\xbf\xd9\x4e\xa5\xfb\xc5\x5a\x6e\x94\xea\xfb\xbe\xdd\x73\x10\x74\x63\x2a\xca\xe9\x20\xcc\x17\x9c\xf9\x62\xbc\xca\x3d\xea\x14\x50\x32\x13\xf2\xc8\x29\xba\xe6\x70\x55\xa5\xb9\xf4\xa0\x05\x0f\x95\xce\xa2\x68\x4c\xca\x03\xb0\x9d\x92\x8c\x2c\xed\x6b\xa8\x45\xf1\xfc\x68\xea\xd2\xf9\x97\x7f\xb1\x37\x6e\x5e\xfa\xb4\x70\xf9\xfd\xb3\xee\xbf\x65\x97\xdd\x44\x2d\xe2\xb7\xe1\x2e\x74\x9b\x1b\x1f\xc9\xf5\xa9\x85\xbd\xc4\x8a\x7a\xf6\x10\x21\xb5\x6e\xe7\x6c\xb1\x98\x89\x51\x66\x9f\x43\xce\xb4\x7c\x0c\xfc\x78\x2d\xad\xb5\x8b\x4b\x61\xae\x69\x1d\xfc\xb6\xb7\xaf\x9c\x5a\xf2\xdb\xcd\x6e\xde\xab\x35\xd8\x2b\xe7\x90\x31\xf6\x8a\xf8\x1c\x4f\x70\xd2\x95\xe6\xc5\xaa\xbf\xed\xca\xc2\xd3\xf7\xd7\x63\xed\x3a\x6b\xe5\xee\xc7\xc5\x49\x79\x1b\x7a\xbf\x5a\x98\x4b\xac\x24\x66\xc4\x34\x9a\x16\x5b\x83\x4c\xb5\xb0\xa8\xe6\x0d\x55\x2f\xf7\xbb\x47\x85\x26\x59\x1e\x7b\xbc\xb6\x3e\xba\x07\xc7\x10\x13\x67\x54\x6a\x9c\x15\xe0\xeb\x9b\xf5\x12\x2b\x93\xbb\x7f\xed\xf3\x27\xfc\x71\xd3\x6b\xae\xfc\x42\x65\x97\x1e\x0d\x53\xf9\x4e\x27\x47\xf5\x6c\x65\xfa\xa8\x58\x4f\xc5\xbd\x2c\x38\x3a\xd9\x6e\x67\xaa\xa7\x2f\xef\xf0\x2f\xce\x4a\x79\x6a\x89\x7b\x6a\x6f\xe2\x16\x90\x73\xfb\x6e\x89\x92\x2a\x76\x3b\xfd\x7e\xd8\xc9\xac\xba\x75\x3a\x0c\x11\xf8\xd5\x42\xd3\x48\x9c\xe2\x8a\xf3\xb8\x7b\x80\x7e\xaf\x71\x58\x0c\x0f\x5e\xd6\x1e\xfa\x6d\x85\xcb\xf3\x7e\x0a\x83\x0a\x08\xd5\x7e\xd5\xf7\xaa\xf9\x7e\xd7\xb2\xe9\xe9\xe3\x6f\xbf\xef\x17\xb6\xc7\x77\x3d\x7f\xea\xbc\x94\x74\x7e\xfe\xd9\x9d\xcf\x5f\xfa\xee\xe7\x7f\x69\xdf\xbd\xfa\xed\x74\x55\xd4\xff\x88\x7e\x3b\x5f\xd0\xae\x96\xad\x92\x2f\x1a\xda\xa5\x87\x46\x61\x6f\x76\xed\x45\x40\xf7\xf6\xd6\xef\x2f\x1a\x2b\xaf\x68\x35\xfa\xed\x02\x38\xa6\x45\x58\x1b\x77\xab\x47\x14\x2d\x6c\xd2\x72\xb6\x5b\x52\x07\xf5\x7c\x75\xd6\x76\x33\xb9\x4c\xb4\xae\x4d\x53\xb1\x15\xa3\xc9\xa1\xde\x0f\x82\x79\x68\xfe\x70\xde\x0d\x16\x62\xa1\xa2\x88\x2a\xc8\xa3\x18\x01\x88\x23\x1a\x50\x8d\x20\x54\x24\xc4\x08\x41\x11\xb2\x50\x4b\x08\x10\xc5\x90\x85\x30\x08\x42\x24\x42\x05\x11\x86\x8c\x41\x1a\xd1\x27\x1b\x06\x3d\xcc\x86\x21\x9f\xdb\x30\xec\xfd\xdb\xa5\x4e\xb5\x09\x1b\x86\x41\x76\xf1\xa5\x6f\xb7\x61\x5e\x27\x3a\xfe\xda\x49\xe6\xcf\xca\x4d\xfa\x36\x51\x1a\xcf\xef\x4f\xc6\xa8\x84\x60\xe1\xb6\xa7\x23\xd8\x5e\xd6\x9b\x9d\x3a\x1b\x78\xce\x4c\x05\xb9\x8a\x9f\xce\x58\x93\x9e\x0b\x8f\x8d\xc9\xb8\x7a\xe8\x81\x70\x56\x1f\x44\x78\xd8\xc8\x14\xf0\x51\x36\x45\x2a\x57\x75\x8d\x8a\x5d\x2c\x17\x7b\x23\x2f\xbb\xee\xb9\xbe\xd3\x73\xdc\xd2\x60\x06\xf7\x7e\xea\x8b\xb9\x6f\x7f\xda\xf6\x29\x5e\x7e\xff\x26\xdd\x70\xfe\xd1\xff\x31\xdb\xe7\x1c\x3e\x73\x07\xfb\x4f\xe5\x7f\xd7\xf6\xf9\x1f\x7a\xfe\x07\xda\x3e\xbb\x7f\xce\xa7\x87\xdb\x3e\xc9\xf2\xe6\x1a\xc5\x9d\xcf\x92\x02\xc6\xbf\xd0\x8e\xf9\x5f\xf2\xd3\x4e\x76\xcc\x77\xc1\xe3\x47\xcf\x42\x4a\x19\x29\xc6\x30\x8c\xa8\xa0\x01\xa5\x81\xc6\x0c\xa0\x98\x31\xa0\x15\x0d\x69\x00\x80\x10\x11\x22\x01\x24\x21\x26\x44\x71\xa4\x95\x52\x28\x60\x28\x92\x81\x90\x58\xfc\xb2\x63\xe0\x23\xd7\x62\x3e\x3d\x8d\x22\x09\xa6\xef\xe6\x63\x79\xa9\x85\x18\x43\x82\xa5\x04\x88\xa3\xfb\xed\x98\xc2\x5b\xf3\xfd\x5c\x7e\xda\x8e\x49\xc8\x4b\xd8\x31\x60\xb7\x1c\xe8\xe5\xb4\xbe\x4c\xd1\x2a\xf2\x4c\x3d\x9b\xc2\xcd\x90\x4e\x96\x95\x62\xb9\x51\x59\x56\xfd\x6a\x75\x40\x97\x03\x55\xdc\xf4\xd2\xd3\xa5\xb6\x9b\xfd\x55\xaf\x9e\x1e\xe1\xb1\x21\xf3\xee\xbc\x15\x46\xa9\x75\xa0\x4a\x76\x61\xd2\x29\x4c\x9c\x7d\xd6\xb4\x4b\xc3\x76\xf5\x8b\x77\xc2\x7c\xc9\x8e\xc9\x26\xa3\x97\xae\xd7\x0d\x3d\xf7\x32\x16\xf9\xcb\xef\xff\x3d\xba\xe1\xb7\x35\x5b\xef\x34\xb4\x97\xbf\x6f\xe0\x38\xc9\x9c\x14\xf4\x79\x0d\xe3\x75\x3e\xca\xbf\x62\x0d\xe3\xcd\xe8\xab\x8b\x1d\xf3\xef\x7c\xfe\x7f\xd3\x1a\xc6\x5b\xb6\x8f\xbe\xef\xf9\xcf\x93\xe6\xfc\xfc\xa3\xbf\xf1\xf9\xdf\x8c\x64\xfa\x37\xe9\xb7\x93\xed\xf3\x5d\xc0\xf9\x49\xdb\x47\x61\x15\x11\x1e\x60\x08\x35\x40\xa7\xf4\xa9\x1c\x29\x0a\x08\x62\x21\x0d\x29\x21\x44\x53\xc4\x20\xc1\x30\x56\x94\x33\xa0\x85\xa6\x9c\x30\xae\x04\x57\x11\x91\xa7\x1b\xc2\x31\x78\xa4\xed\xf3\xd9\x09\x23\x0e\x04\x7f\x7f\x1f\xea\x54\x7b\xba\x67\x15\x09\x41\x24\x40\x48\x72\x76\xbf\xed\x93\x7f\x6b\xbe\x9f\xcb\x4f\xdb\x3e\x09\x7d\x9b\xb0\x7d\x78\xb7\x54\x58\x08\xb0\x51\x5e\x7d\x9d\xa2\x74\x91\x62\x2d\x6f\xe9\xe2\xec\x72\xcb\x8e\xd9\x75\xa5\xb8\x1b\xc5\xc6\x7e\xbf\xea\x46\x7e\x35\xb7\x19\xf1\x7d\x77\xd5\x0b\x0f\xfd\x8a\xd9\xea\x0c\xfb\xba\xe2\xc9\x43\xcf\x68\xc3\xed\xfa\x10\x46\x1d\x97\x40\x63\x5f\x77\x6a\x6b\xe3\x91\xb6\x4f\x32\xca\xee\x06\xdd\x10\x5f\xc6\x22\x77\xf9\xfd\xbf\x53\x37\xbc\xfc\x9d\x49\xec\x6d\xdf\xc2\xfe\xb3\x42\x3d\xb3\xff\x75\x54\xdd\xdf\xcb\xfe\x84\xed\xf3\xaf\x7c\xfe\x7f\x13\xfb\xdf\xb2\x7d\xa2\xfb\x9e\xdf\xea\x5d\x9e\xbf\xf7\xb7\x3f\xff\xcb\xdf\xff\x26\xfd\x76\x3e\x09\xf7\x4d\xc0\xf9\xd1\xfd\x2b\x19\x33\x12\x68\x10\x0b\x20\x43\x20\xa4\x64\x0a\xc6\x58\x12\xad\xb9\xa4\x00\xc0\x80\x00\xad\x35\x93\x41\x14\x32\x4e\x83\x90\xe1\x30\x8e\xa0\xc4\x28\xc2\x41\x10\x87\xe8\x3f\xff\xfd\x3f\x24\x1f\x69\xfb\x7c\x76\x12\x8e\x43\xc1\xde\xcf\x42\x72\xaa\x3d\xc5\x82\x22\x42\x29\x01\x94\x32\x01\xee\xb7\x7d\x5e\x5f\xc2\x7d\x85\xed\xf3\xe6\x49\xba\xb7\x4b\xc2\x96\x19\x30\xb9\xb0\xb2\x6a\xdc\xaa\x4b\x43\xb8\x46\xb0\x38\x8c\xd8\x2c\xb7\x1f\x94\x4c\x54\xe8\x74\xec\xa9\x76\x06\xc3\x78\x9f\xa5\xad\x43\xd1\xcd\x79\xdd\xb2\xb1\xaf\x54\x94\x59\x9d\xe7\x82\x71\x93\x55\xe1\xdc\xaf\x75\x70\x81\x54\xc6\x85\x6c\x97\xf4\x73\xd1\x3e\x7f\xb4\xd8\x23\xf7\xa3\xb2\x89\xaf\xde\xf2\xae\x93\x4b\xdf\x66\x2f\xbf\xff\x77\xbe\xeb\x2f\x7f\x67\xc0\xe5\xef\x5b\x58\x7e\x8e\x7e\x0d\x2f\x13\xe2\x7f\x82\xe5\x09\x5b\xe6\x5f\xf9\xfc\xff\x26\x96\xbf\x65\xcb\xa8\xfb\x9e\xdf\xb1\x2f\xcf\xaf\xfe\xf6\xe7\x7f\xf9\xfb\xdf\xa4\xdf\x4e\xb6\xcc\x77\x01\xe7\x27\x6d\x99\x58\x63\x0e\x78\x1c\x46\x54\x09\x42\xb0\xa4\x8a\x4a\x11\x63\x18\x29\x0e\xa5\x62\x10\x41\x11\x11\xa5\x03\xa2\x45\x14\x45\x27\x8b\x06\xe3\x98\x08\xc6\x80\x90\x10\x80\x5f\xb6\x8c\x78\x98\x2d\xc3\xa4\xfc\x2c\x9e\x98\x23\xc9\xd8\xbb\x7b\x58\x2f\xb5\x10\x01\x44\x25\x10\x02\x8b\x07\xc4\xe2\x7c\x76\xab\xc0\x6d\xfa\xf8\xda\x75\x9f\x84\xfc\x44\xfc\x71\xda\xcd\xf5\x6c\xb9\xf2\xab\xee\x2e\x34\x07\xb9\xa8\x18\xf5\x67\xf6\x06\x51\xf3\x90\x01\x5d\x43\x4d\x86\xde\x6c\xea\xe5\xd6\x1b\x56\xb7\x41\x2f\xa8\x67\x5a\x8d\xf4\x58\x63\x4a\x8d\x74\xb4\x83\xe5\x6a\x30\xeb\xf8\xb2\x9a\xde\x80\xd9\x46\x5a\xbc\x4f\x5b\x21\x8c\x55\xe1\x61\x36\x4f\xe2\x43\x37\xe8\x84\x7e\xed\x32\x06\xef\x94\x8f\xcf\xa1\x3c\x50\xfe\xbd\xb7\x10\x3c\x90\x09\x37\x9d\xd2\xfc\x1e\xf9\xb7\xc7\x88\xdc\x78\x6e\xe5\x96\xb6\x9f\x05\xb9\x1f\xdd\xf2\xf1\xad\x7d\x77\x3e\x35\x79\xbd\xfc\xa7\x73\x2b\xd5\xfd\x20\x97\xa9\x86\xae\xb5\x5f\xb9\xbb\xd9\x20\x5b\xc7\x7e\x90\x29\xae\x37\xde\xaa\x17\xb9\x5e\x36\x3f\x03\x85\x3c\x30\x8b\xe1\x66\xd4\x2f\xe7\xdc\x51\xaf\xd5\x4c\xd3\xce\x3a\xa5\xbd\x2a\x56\xe5\x46\x03\x2d\x1c\x54\x6d\xa4\xf9\xba\x50\xdc\x7a\x29\xa2\x5b\x6d\xd9\xc1\x3f\x7d\x3f\x28\x26\x54\xc7\x3c\x16\x54\x31\x1d\x20\xc9\x35\x8e\xa5\x24\xb1\xd6\x31\xe2\x32\x64\x58\x40\xc4\x90\x60\x02\x86\x11\xe4\x38\x80\x31\x83\x14\x0a\x1a\x10\xcc\x84\x26\xa7\x8c\x64\x48\x3c\x2c\xe6\x93\x49\xf9\x59\xcc\x27\x47\x52\x88\x77\x2f\x5b\x7b\xa9\x7d\xe2\x8c\x44\xe4\x11\x3e\xf3\x07\xd9\x63\x3e\xf0\x99\x3f\x3e\x7f\xf6\x8f\xdf\xbb\x70\xc3\xf2\xf7\x0b\x7c\x9c\x07\x4e\xce\x44\x79\xb5\xc9\x37\xc3\xa5\x87\x4b\x4e\xe7\xb8\xd8\x6e\x52\xd4\xe5\x9d\xe6\x80\x94\xa7\xd9\x71\x1c\x16\x37\xeb\x29\x67\x87\xb1\xa7\x86\x9b\x5d\xb1\x17\x36\x5d\x34\x5e\x28\x2f\x1e\x73\x1a\xcd\xaa\xcd\xee\x61\xb3\x2c\xac\x9d\x2a\x5c\x8e\x4a\x5f\xc9\x20\xfd\xd3\xdc\x78\xbd\xae\x70\x53\xec\xe6\x0f\x72\xc6\xfc\x89\xf6\x7e\x0f\x97\x12\x4b\x3e\x0f\xe7\x82\xf1\x0d\x1c\xbb\xb7\xbd\xf6\x07\xed\x7d\x93\x63\x7f\x88\x23\x8f\xea\xbb\x73\xc6\x9a\x9b\x39\x86\x4a\xc1\x5a\xb0\x76\xbf\x6e\xac\x07\x9d\xe2\xa0\xe5\x32\x50\x3e\x66\x5a\x82\x2d\xf9\x76\x53\xdb\x40\x98\xdb\x58\xdd\x3d\xed\xa0\x03\x5f\x76\x53\xa9\xd5\xbc\x99\xcd\xf1\x95\x49\x5c\x98\x59\xcf\x83\xa9\x9d\xa5\x3a\xd5\x09\x2c\xe8\xaa\xe5\xe2\xb0\xac\x35\x64\x40\xad\x9f\xce\x40\x8d\x02\x48\x38\xa6\x11\x0f\x01\x85\x40\x62\x2a\x09\x21\x81\x8a\x22\xc1\x35\x8f\xb5\x44\x4a\x0a\x2d\x91\xa4\x11\x0a\x03\x06\x43\x40\x35\xa2\x11\x8c\xb9\xd6\x10\xc4\x11\x7e\xe2\x18\x7e\x18\xc7\x3e\xcb\x03\xc0\x31\x00\x1f\xf8\x4b\x18\x00\x9e\xc0\x18\xa3\x8f\xd8\xf6\xfe\x20\xb1\xe6\x07\x18\xfb\x28\xc9\xfb\xab\xdf\x4b\xb8\x3f\x85\x8d\x07\xf5\xbe\xb4\x11\xfd\x28\x16\x51\xa5\xaa\x9b\xc5\x0e\xb2\x5c\xfe\x6b\x26\xb5\xdb\xb9\xa6\x93\xed\xe4\x4b\x6d\xd7\x95\x85\x49\x6b\xe9\xcd\xba\xd6\x1a\xd5\x59\x90\x86\x1b\xdf\x6e\xe5\xa7\xdb\xad\x9f\xb6\x67\xf9\x12\xad\xcd\x5b\xc3\x3e\xea\x9a\x2b\x0c\x5a\xbe\xf1\x17\x62\xec\x5e\x2c\x64\x92\xdf\x7d\xab\x4f\x1f\xdc\x5e\xeb\x27\xda\xfb\x3d\x18\x4b\x9c\xbc\x79\x38\x16\x8c\x6f\xc0\xd8\xbd\xed\xbd\xfa\x12\xb9\x3f\x84\x91\x47\xf5\xdd\x39\x99\xe7\xcd\x18\x33\x97\xa3\x72\x67\xd5\x28\x6e\x73\x9d\x4e\x3a\xdb\x18\xe2\xb1\x09\x65\x6f\xbf\xd9\x21\xa5\x5b\xe3\x81\x93\xa9\xc1\x43\xc3\xe9\xf7\xb7\xf5\xf9\x38\x00\x05\xd7\xe3\xd1\x68\x33\xd9\xca\x70\x92\x71\xea\x5d\xce\x51\x75\x5f\x30\x1b\x95\x66\xd0\xf2\x49\x34\xf1\x96\x65\xe9\xb4\x7f\xfa\xea\x6b\x12\x4b\x2a\x05\x02\x2c\x08\x21\x57\x31\xe2\x21\x55\x58\x87\x52\x4b\xc0\x22\x86\x75\xa8\x35\x62\xe8\x9c\x68\x00\xe9\x20\x8c\x22\x14\x2a\xcd\xc3\x18\x22\xa5\x54\xfc\xec\x8e\x91\x87\x61\xec\xb3\xeb\xe4\x38\x06\x88\xbe\x1f\xbe\xf5\x5c\x7b\xe6\x18\x04\x80\x3d\x22\x74\xfd\x83\x8b\x14\xbe\x67\x0b\xd3\x88\x58\xe9\x98\xb5\x86\xcd\xa8\xb6\xce\xce\x8e\x47\x6b\x6a\xe1\x61\xde\x48\x6d\x6a\x96\x19\x2c\x71\xd5\x5b\x6f\xb2\x69\x82\xe7\xd3\x5a\xe5\x38\x82\xd9\xd1\x6c\x9b\xaf\x7a\xd0\x3f\x1c\xd5\xbc\x12\xa6\xcb\x7a\xd3\x4c\x17\x0b\xe5\xe3\x4a\x17\x41\x35\x5f\x0e\x56\xad\x0e\x1c\x1b\x8f\xdc\xc2\x4c\x7c\xe8\x0f\xf3\xc1\x4a\x7e\xf7\x8d\xf2\x68\x9e\xd9\x3f\xd1\xde\xef\xe1\xd9\xeb\xf1\x7e\x24\x1f\x8c\x6f\xe0\xd9\x83\xda\xfb\xa6\x3d\xf9\x1d\x3c\xbb\x95\x27\x8f\xea\xbb\xf3\x85\x07\x37\xf3\xec\xbb\x94\xce\x4f\xf2\x4c\x50\x14\x06\x88\x6a\xa0\x49\x10\x40\x22\x03\x84\x22\x05\x25\x0e\x55\xc8\x08\x0d\xb4\xd4\x61\x80\xb0\xe6\x31\x27\x18\x71\xc0\x63\x1c\x4a\x08\x08\x27\x5a\x86\x2c\xa0\xe1\x13\xcf\xe8\xc3\x78\xf6\xd9\x05\x75\x1c\xff\x92\xfe\x01\xcf\xce\xb5\xcf\x3c\x23\xfc\x11\x69\x71\xde\x3c\x7a\x78\x2e\x5f\x0a\x47\x7e\x9b\x6f\x17\x46\xbc\x2e\x49\x3f\x6d\xea\x1c\x15\x1b\x2d\x76\xfa\x90\x2b\x92\xc6\x31\x67\x85\xcb\x94\x70\x9b\x15\xd7\x5d\xc1\x36\x1d\xaa\x0e\x1d\xd4\xcb\x3b\x62\xe9\xd9\xf4\xe8\x19\xb5\xb1\x1e\xfa\x79\x59\xae\x4c\xd3\x9d\xd1\x52\xcd\x4c\x99\xdd\x46\xa2\xaf\xe8\xb8\xbc\x4f\xc1\xbe\x94\xd0\xdd\xe7\x9b\xf9\xbf\x90\x6b\x0f\xe2\xc4\x9b\xfd\x69\x7c\x03\xd7\x9c\x9f\x68\xef\xf7\x70\xed\xf5\x9c\x7d\x24\x27\x8c\x6f\xe0\xda\xc3\xda\xfb\xd5\xa3\xd4\x7f\x88\x2b\x8f\xea\xbb\x5c\xe9\x36\xf9\x4f\x5c\xcb\xef\x15\xae\xcc\x0b\xab\xec\x6a\x60\xa6\x6c\x71\x30\x10\x4b\x6f\x33\x63\xab\xdf\x5f\x96\x5b\x1b\x1f\x3b\x29\x7f\x34\x54\x15\x03\x2f\xf2\x02\x18\x76\xb7\x33\x43\x66\xdc\x68\xcc\xd3\x90\x16\x70\xc1\xd8\xd6\x38\x8e\x73\x9d\x4a\xb7\xa1\xe2\xb5\x1f\xc7\x51\x6d\x55\x6f\xfd\x74\xb2\x51\xa1\x94\x02\x0a\x09\x85\xb5\x94\x01\xc3\x4a\x51\x19\x06\x11\x8f\xb4\xc2\x31\x55\x94\xe9\x10\x4b\x82\x14\x25\x42\xab\x88\x80\x50\x61\xa9\x28\x90\x11\x0b\x81\x80\x11\x79\xe2\x1a\x7b\x18\xd7\xc4\xe7\x5c\x63\xef\x5f\xba\x70\xaa\x4d\x72\x4d\x88\x47\xa4\x4a\x71\x5f\x4d\x80\x7b\x8f\xd9\x9c\xea\x7f\x0f\x1f\x7a\x55\x12\x7e\xdb\x28\x67\x31\x73\x94\xc9\x56\xa5\x9e\x6d\x8b\x5e\x67\x54\xf2\xf2\xdc\x1b\xd9\xac\xdc\x1e\x4f\xa2\x82\x3b\x29\xee\x83\x41\x0e\xfa\x41\xab\xd0\x0d\x0a\xf9\xfd\x91\x56\x05\xdd\xa7\xd8\xee\x38\xf7\xf7\xfb\x70\xc5\x32\x11\x1a\x93\xc5\xbe\x35\xac\x73\x0f\x33\x6b\x57\x1b\x2c\x32\xc6\x5f\xe9\xb7\x3d\x8e\x17\xbd\xb7\x6d\x86\x07\xb7\xd7\xfd\x89\xf6\x7e\x0f\xdf\xfc\x57\xe3\xfd\x48\x5e\x18\xdf\xc0\xb7\x87\xb4\xf7\x9e\xd4\x21\x7f\x88\x37\x8f\xea\x4b\x77\x76\x9b\xfc\x27\xde\x7d\x97\x12\xfa\x51\xde\x61\x04\x20\x80\x44\x08\x00\x38\x8e\x85\x8e\x63\x16\x23\x18\x68\xce\x34\x85\x0a\x29\x12\x07\x31\xc5\x58\x53\x0a\xb4\x8a\xb0\x42\x08\xd0\x90\x88\x00\x48\x24\x19\x08\x9e\x78\xc7\x1f\xc6\xbb\xcf\x2e\x84\xe0\x18\x48\xf2\xd1\xf6\xda\xf9\x9e\xf1\x33\xee\xe0\xaf\x36\xde\x8f\xbb\xec\xab\xf1\xff\xeb\x4e\x95\xae\xfd\xf5\x78\xb5\x28\xd5\xb4\x37\x83\xcd\x59\x13\xb9\xfe\x30\xc4\x7d\x8a\x76\x76\x61\x3b\x9d\x6d\xcc\x7a\x85\x15\xbd\x0a\xdc\x4f\xd2\xc6\xb2\xbf\xf6\x2a\xe9\x55\x87\x2e\x30\xad\xaf\x45\x66\x18\xf8\x6d\x7b\xe0\x4c\xe7\xa9\xba\x37\x44\x4e\xd7\x14\xb2\xb2\xda\x99\xe3\xc8\xd8\xfd\x95\x38\x7c\x08\x5e\x3e\x88\x54\x7e\x5d\x1e\x8d\xc7\xec\x9f\x68\xff\x37\x46\xca\x27\xe6\xc3\x77\xe2\xc7\xf8\x06\x7c\xfe\xf5\x91\xfe\xdf\x80\xdc\x5b\x91\xf7\x1d\xfd\x7f\x8d\xfc\x27\xe4\x7e\x97\xa2\xfb\x49\xe4\x72\x00\xe2\x80\x90\x30\x24\x40\xb3\x20\x42\x8a\x0a\x21\x18\x65\x2a\x42\x9a\x87\x22\x12\x2c\xd2\x38\xc2\x94\xf2\x90\x51\x1c\x68\x26\x38\x21\x8c\x41\x4e\x23\x46\x24\xe2\xbf\x90\xcb\xef\xbf\xcf\xe2\xd3\x78\x4c\xca\x28\x79\xf7\x3e\x8b\x53\x2d\xbe\xa0\x1b\xfd\x72\x2d\xef\xbf\xcf\xe2\xf5\xdd\x0b\xbf\xdf\x67\x71\xbd\xf6\x7d\xe7\x3e\x8b\xcc\x02\xbb\x55\xab\xa5\x6b\xd5\x78\xb7\x58\xb7\x09\x75\xbb\xe5\x41\x33\xf2\xe4\x90\xd9\xb2\xbc\x3a\xa6\xc7\x25\xbf\xad\xda\x56\xdb\x35\xbb\x86\x55\x5f\xd9\x03\x7b\xd6\x09\x96\x30\xdb\x76\x0a\x2c\x5a\xce\xd7\x2b\xd7\x1e\xcb\x2a\xcb\xc9\x98\x9b\xc8\xcd\x14\x42\xe2\x7b\xa5\x47\xdd\x67\x91\x7c\x43\xae\xbc\x4f\xa2\xa5\x6a\xda\x4c\x5c\x3b\x53\x7e\x53\xf2\x27\x1b\x63\x0f\x94\x7f\xd3\x7d\x1a\x89\xfb\x2c\xee\xb8\x43\xa1\xb5\x77\x48\xe1\xde\x3b\x14\xfe\xe0\x1d\x0e\x86\xf1\xe7\x62\xf1\xdf\x74\xf8\xba\xb7\xf7\xc5\xaf\xb1\x28\x26\x0e\x96\x80\x2b\xfb\xe2\xde\xb1\x78\x3d\x17\xae\x91\xff\x44\x9f\x60\xbd\x1f\xee\x60\x67\xd4\xc0\xa2\xb0\x6c\x6d\x2a\xb5\x49\xc3\x1f\x67\x9b\x55\x3f\xd5\xaf\x36\xc2\x52\x9a\x36\x5c\x67\xea\xf4\x60\xbf\x37\xf1\x0c\xb0\xcc\xe4\xfa\x05\x07\x2d\x64\x0d\xf6\xeb\x9b\x69\xc0\xc2\x30\xd3\xcf\xc7\x8d\xd4\xa0\xda\x49\xed\xd6\xfd\x5e\x7d\x92\x72\x6d\xeb\x87\x1d\xbe\x80\x33\x0d\x10\x03\x31\x0b\x05\x56\x4c\x07\x12\xc7\x94\xd0\x08\xf2\x48\x73\x04\x15\xe0\x32\x52\x18\x6a\x01\xb5\xa6\x3a\x52\x04\xc6\x90\x4a\xad\x68\x1c\x12\x41\x4e\x2a\x1f\x3d\xdf\x54\x9e\x61\x6e\x19\x17\xf3\xcd\x36\xcb\xfb\x35\x6e\x5b\x95\x3c\xe1\xad\x4c\x96\x5b\x84\x96\x48\xbe\x9d\xed\xb8\x05\x56\xcc\xe6\x6b\x86\x9d\xa3\xf9\x4c\xbd\x8c\xac\x8c\xe7\x73\xef\x17\x35\x00\xc7\x9c\x40\x81\xc8\xe7\x79\x84\x98\xf8\xe0\x3e\x8b\x53\xed\x29\xa0\x12\x42\xc6\x24\xa4\x98\xcb\x97\x40\x94\xec\x7e\xc2\xdb\x93\xf1\x36\xbf\xcf\xd2\xcc\xa6\x71\x94\xde\x34\x55\x9d\xb6\x55\xc3\x97\xc7\x82\x58\x31\xbf\x97\x1b\x2e\xbc\x43\x38\xf3\xfd\x97\xc9\x9d\x49\xe4\xf2\x48\x4c\xb6\x57\x13\x24\x79\x03\xa0\xe8\x6e\xe0\x7c\x1e\x1e\x54\x2d\xe5\x85\x23\x91\x6e\xe6\xd3\x43\x0a\xa7\x36\xaa\xaa\xc3\xb6\x58\x99\xe4\xcc\x1c\x1b\x95\x26\xcc\x4d\xae\x9a\x46\xc7\x76\x33\x31\xaf\x93\x1b\x7d\x2f\xed\xf1\x32\x8b\xa3\xe9\x5b\x9b\xa2\x3f\x4d\x0f\x3b\xfd\xd8\x6e\xed\x6d\x77\xd0\x2b\x99\x79\x77\x56\xc9\x98\x05\x89\xc6\xcd\x10\x37\x27\x90\x56\x7b\xbb\x7a\x9e\xe1\x75\x79\x9c\x72\xe6\x59\x91\x3a\x50\x95\x9a\x98\xab\xf4\xf2\xa8\xb6\xd1\x61\x26\x37\x9d\x68\x16\x45\xa4\xd8\x69\x0f\xbc\xde\x57\xbc\xba\xd7\x01\xa5\xc6\x2d\xfd\x79\x2e\xcd\xef\xeb\xaf\x57\xe7\x43\x2f\xff\x96\xe0\x68\xc2\x93\x88\xdd\x70\x1d\x04\x6d\x31\xb5\xe3\x91\x4b\xab\x55\x68\xc6\x24\x15\x75\xf7\xe5\x21\x2e\x2d\x0f\xc7\xf9\xc0\x18\x54\xe6\x56\x7e\xd3\xef\x9f\xbe\x74\xb9\x89\x36\xf3\x5b\x56\xee\x44\xf9\x84\xa3\x8f\x93\x7f\xef\xad\x85\x41\xa2\xea\xca\x31\x48\x04\x11\x7a\x1f\xc8\xfc\x58\x77\x3f\x5a\xfe\x67\xb7\x16\x3e\x9d\x39\x56\x70\xfc\x5e\xb3\x5e\x3e\x79\x72\x8a\xce\x9b\xeb\xff\x0b\x73\xfc\x6d\x1e\xdf\xd0\xa7\x4f\xb6\xc1\x47\xf6\xc7\xb7\x8e\xe9\xd3\xf9\x8a\xab\xe5\x3f\xf1\xd8\x5d\x96\xf2\xbd\x0a\x59\x0f\xe2\x54\x59\x3b\xa2\xd6\xb1\xbd\xa0\x60\xec\x72\xa3\xa0\x47\xec\xdc\x12\x07\xad\xda\x36\xaa\x87\x9d\x51\xca\xca\xe4\xa6\x4b\x0d\x50\x87\xb4\x47\xf1\x91\x17\xc7\x47\xe6\x17\x8e\xa9\x6d\xf9\x20\x71\x61\x88\x68\x84\xfa\x10\xf7\xd6\x51\x90\xff\xe9\xbb\x19\x24\x0a\x18\x25\x8a\x33\xc9\x58\xa0\x18\x0c\x94\x92\x51\x0c\x42\x4e\x63\x09\x55\x18\x69\x1c\x52\x0a\x95\xd4\x92\x33\xc6\x31\x10\x88\x07\x31\x41\x11\xd4\x88\x70\xa5\x9e\x79\x8c\x1e\xc6\xe3\xcf\x72\x1a\x73\x26\xc1\x07\x38\x3e\x57\x3e\xd3\x98\x8b\x8b\x57\x78\x3b\x8d\x3f\x38\xa5\x97\x98\x1e\xad\x56\xa3\xf6\xf4\xbf\x57\x6a\xda\x2f\xd2\x38\xb4\x65\x83\xcf\x32\x85\x59\x19\xa4\xeb\xd8\x68\x71\x77\x56\xaf\xe9\xd4\xbe\xc1\x65\x7d\xdc\x2e\x9b\xbe\xbd\x2e\xc2\x5a\xd5\xde\x17\x85\x53\xec\xef\xa8\x6d\xad\x3a\xc5\x99\xb1\xcd\x65\xc2\xcc\x36\x9b\x5b\xca\x72\x41\x55\xd7\x6d\xeb\xd0\x57\xd9\x71\x6e\x13\x74\x0b\xb9\x9e\xf8\x61\x1a\xfb\xdf\xd7\x5f\x3f\x4b\xe3\xaf\xdd\x4b\x7f\x36\xd6\x70\xb9\xfb\x91\x8a\x79\x34\x9d\x12\x19\x2f\x7e\x6b\xcb\x45\xc8\xe9\xbf\x9f\xd1\xe9\xf4\x9d\xd2\x77\xf4\xdf\xd7\xee\xd5\xff\x73\xfd\xf7\x7b\x28\xf7\x27\xfd\x77\x99\x93\xaf\xca\xdd\x74\xff\xe1\x77\xe6\x42\xf7\x3f\x44\x57\xe3\x1b\xc6\xf4\x1a\xf9\xcf\x77\x17\xaf\x1a\xb0\xba\xe9\xd9\x8b\x1e\x6e\xc8\xa2\xca\x74\x56\x41\x3f\xef\x70\xee\x54\xb7\xb0\xd0\xf2\x41\xbe\x57\x07\xdb\x96\x2d\x1a\xf6\x76\xd7\xdc\x64\xad\x91\x57\xd9\xab\x4d\xcf\x14\x3d\x67\xe5\x0a\x35\xd8\x02\x30\xdf\xa5\xa0\x5f\x2d\x38\x3b\xdd\x1c\xd0\xf9\x68\x36\xb0\x7e\x78\xad\x97\x02\x46\x55\xc4\x95\xe4\x2a\x0e\x59\x1c\xc6\x3c\x0a\x04\x91\x38\xd4\x3a\x22\x5c\x47\x48\x71\x1d\x87\x38\x04\x20\xe4\x3c\x20\x4a\x22\x26\x91\x8e\x88\xe0\x71\x28\x58\x70\x0a\x27\xa2\xf7\xaf\xf5\x7e\x9a\xe3\x85\x4b\xf1\xc1\xa6\xea\x73\xed\xb3\x95\xc0\x88\x64\xf7\xaf\xf5\xbe\x5e\x97\xfc\x4d\x63\xde\xa0\xe1\xde\x5b\xeb\x5d\xf7\x77\x0d\x9c\x37\x7b\x34\xd7\x1d\x15\x6a\xe5\x02\x9e\x67\x33\x41\x5a\xbb\xe2\xb8\x10\x46\x2c\x7b\x4e\xb5\x3d\xf6\xb7\x76\x54\x9b\xb1\xe1\xd1\xa0\x96\x8c\xfd\x8a\xb2\xe6\x05\x0b\x47\xb6\xb1\xa9\x16\xcb\x65\x23\x3b\x94\xeb\x72\xd8\x6d\xe6\x0d\xbc\xdc\xed\xcb\x92\x64\x1e\xb6\xd6\x9b\xf8\xfc\x95\x6b\xad\x9d\x7d\xbd\x3c\xe1\x97\xaf\xbf\xbe\xc3\xea\xa9\x7c\xe2\xa3\x3e\x4e\xfe\x4d\x6b\xcd\x09\x1f\xf5\x8e\xf5\xc5\xd8\xc9\xa1\xf0\xde\xf5\xc5\x3f\xb8\xbe\x69\xbc\x96\xff\x83\xfe\xdc\x9b\x6b\xbd\xad\xdb\xfb\xe2\xd7\x58\x44\x09\x49\xef\x2c\x3e\x7f\xdb\x58\xbc\x9e\x0b\xd7\xc8\x7f\xa2\x4f\xe8\x2b\x5b\x1e\xbc\x59\xa5\xee\x76\xcd\x51\xa3\xbe\x66\xb5\x5d\x7b\x8b\xfb\xdb\x12\xdb\x1a\xd9\xb4\x9f\x69\xc0\x79\xbb\xb8\xcf\x36\x83\xca\x4c\xec\x2a\x5e\xba\x83\xac\xa9\xc1\xea\x3d\x89\x6b\x46\x71\x78\x38\x36\xbc\x0c\x49\x87\x8d\x36\x6a\x99\x5e\x99\x89\x52\x23\xd6\x3f\x7d\x48\x03\x40\x4c\x58\xa4\xa1\x0a\x30\x50\x1a\x60\x48\x64\x24\x63\x4a\x24\xa1\x92\xb2\x00\xa1\x58\xaa\x50\x47\x38\x12\x30\x16\x50\x31\x14\x86\x54\xaa\x58\xa8\x28\x12\xa1\x90\x27\xdf\x92\x3c\xd3\x07\x79\x39\xbf\x81\x72\x46\xd3\x29\xd5\x3a\x85\x62\xbd\x58\xac\xd6\x6c\xd3\x64\x15\xb3\xe2\xe6\x4b\x86\x55\xaf\x36\x6a\x05\xde\x70\xcb\x0d\x54\x77\x6a\xc8\x77\xdb\x96\x51\xb3\xfe\xf3\xdf\xff\x93\x00\x4a\x82\x21\x46\xf0\xd3\x33\x1a\x12\x7e\x40\xa1\xa7\x4a\x08\x30\xe0\x12\x41\x89\xc0\x4b\x68\x4f\xb6\x69\xfb\xd3\xb9\x51\x70\xba\x2e\x1b\x1f\xda\x6b\x51\x37\x1d\xba\x9b\xba\xf5\x9d\x41\xab\x53\xa7\x43\x27\x61\xb5\x39\xd8\xc3\x1e\xec\xbf\xcc\xac\x4c\x22\x91\x58\x62\xa6\x5d\xfe\xf7\x7c\x51\x71\x62\x51\x07\x66\xdc\x3c\xf3\xcc\x7e\xbb\xb6\x99\xab\xf1\x32\xb6\x7b\x7d\xad\xf2\xfb\xd1\xca\xa8\x34\xe8\xbe\x95\xea\x4e\x8e\x30\xb7\x8a\xfc\xb2\x9f\x98\x58\xb6\x76\x87\x89\x49\xfd\xf6\x22\x5e\x98\x6d\x5b\x6d\xfb\x54\x0d\x8a\x29\x26\x2d\xd8\xdf\xcf\x0f\x6b\x63\xd4\x61\x6a\x5b\x1d\x64\x36\x15\x01\x16\x63\x51\xf7\x0a\x5d\x48\xab\x95\xd6\x7e\x2f\x77\xfe\x98\x4d\xba\xcb\x62\x8a\x35\xdb\x6e\x10\xa6\x53\x6c\xda\x43\xa5\x54\x80\xa4\xcd\x2b\xe5\x54\x67\x45\x98\x2f\x4b\xe5\x45\xa3\x2f\xe1\x17\x4f\x24\xfe\x76\x42\xb0\x53\x48\x39\x30\x5f\x59\x09\xe2\x95\xad\xfe\x74\x92\x1b\x0e\x0b\x4d\xcb\x4b\x4d\xec\xed\x46\x77\x77\x56\x31\xbd\x36\x5b\xb5\x8e\x33\x9c\xaa\x37\xdf\x35\x33\xb5\x7d\x32\xe3\x9d\x56\x13\x3c\x09\xba\x72\xac\x0c\x63\xbb\xdc\x25\xc3\x41\xae\xfe\xbe\xf1\xd6\xa2\xfd\x4d\x63\x99\x89\x3b\xfd\x8f\xc6\xf2\x5d\xc0\x27\x3e\x13\x79\xb5\x81\x1e\x19\xb3\xd6\x28\x5c\x74\xf2\x01\xde\xe7\x72\x9d\xa9\xa9\xba\x45\xc3\x1a\xa5\x54\x2b\x9e\x74\x57\xb2\x5e\x7c\x9e\x0f\x67\xb7\x6d\x6a\xbc\xcc\xd7\x77\xca\x27\x80\x7f\x9c\xfc\x9b\x16\xa1\xcd\x8b\x1b\xdb\x39\xfd\xeb\x39\xc7\xa8\x5a\x92\x4e\x73\xc4\x8e\xc7\xbe\x01\x2a\xae\xf6\x07\x95\xd2\xdc\x2b\x5b\xcc\xaf\xa7\x28\x9d\x1a\xa5\x6d\x0a\xe4\x5b\x8e\x6a\x57\xa2\xcb\x9c\x4a\xcc\xd1\x87\xcc\xa9\x0f\x12\x3a\x25\xdc\x50\xe7\xb0\xed\x47\xf5\xc6\xb2\x5a\xb1\x2d\x8f\x74\xe9\x20\x47\x0e\x63\x03\x54\xe7\xfd\x22\x9f\x4e\x94\x71\x48\x73\x6f\xdc\x6c\xed\x7d\x9a\xb8\x88\xf0\xe2\xb6\x3b\x89\x2c\x05\x57\xbe\x53\x77\xcf\xd9\x38\xfd\x5c\xc4\xeb\xe7\x2d\x32\xf1\xee\x29\xa2\xe7\xf6\xfa\x97\xcf\x5f\x3b\x5e\xf7\x8e\x4f\xe6\xa5\xe5\xe9\xd7\x97\x62\x7f\x56\x4e\x89\x80\x13\x3a\xe9\xda\xf1\x1b\x7b\x45\x72\x3c\x4d\x90\xb3\x11\xd4\x33\xde\x3a\x71\x95\x79\xa3\xbf\x92\xe5\xad\xfe\xfd\xed\x7d\xbc\x72\x3e\x98\x75\xd3\xe8\x9f\x97\x71\x4e\xef\xe3\x15\xcb\x38\x5f\x2a\xe7\xf1\x3e\xbf\x9f\xb7\xcc\xb7\xb3\xe0\xc4\x32\xc9\x95\xfa\xe6\xb9\x57\x20\xf1\x2e\xfd\xf5\x76\xfb\x4b\xc6\x3f\xd7\x66\xae\x6d\xef\x65\x89\xc4\xb9\x7d\x53\xeb\x1e\xf9\xb1\x64\xed\xd7\xf2\xbf\xb6\x6c\x78\xe9\x9f\xdf\xca\x27\x86\xfc\x0d\x7d\x74\x16\xe4\xdc\xbe\x8c\xf4\xc0\x31\xba\x46\xfe\x93\x21\xff\x5d\x06\xd5\x4f\x1a\xf2\x91\x08\x11\x05\x02\x22\xcc\x28\x0b\x61\x14\x43\xad\x21\x57\x88\x33\x2e\x90\x0c\x15\x42\x41\x48\xa0\xa4\x32\x88\x10\xd5\x4c\x29\x45\x11\xd0\x82\x48\x0a\x59\x1c\x06\xf0\x97\x21\x8f\x9f\x0d\xf9\x4a\x81\x67\x2a\xcd\x7a\xa5\x5d\xcd\x66\x8c\x72\xc6\x2f\xb1\x52\xae\xe6\x77\xf3\x39\x2b\x57\x6d\xfa\xf9\x6a\x27\xdb\xc8\x1a\x96\xc3\x69\xd3\x6e\xe5\x5a\x7e\x3b\x9b\xad\x94\x3d\xf3\x1f\x86\xfc\x67\x87\xd2\x04\xa4\x54\xbc\xbb\x49\xf4\x52\x2b\x05\x17\x04\x51\x28\xc1\xcb\x99\xb4\x2b\x35\x75\xc2\x92\xff\x60\x93\x28\xb1\x2a\x72\x87\x66\xba\x58\xb3\x1f\x90\xe8\x45\x53\x67\x8c\x46\x8d\x88\xbd\x3f\x28\x84\x1b\x61\x54\x66\x1d\x67\xb7\x55\xdb\x5c\xb1\x0b\xd2\x73\x6f\x14\xbb\x9b\xdd\xce\x98\xe5\xba\x65\x1d\x2f\xf9\x21\xca\xed\xc6\x6a\x53\x24\xa4\x53\x2d\xf1\x79\x3e\xcd\x86\x56\x3d\x5c\x64\x36\x51\xa3\xdc\x8e\x6c\x94\xaf\x0d\x37\x0b\x9e\xcd\xf1\x9c\xf1\xb5\x33\x6a\x6f\x6f\x18\xdd\x6e\xc5\x7c\x7b\xdf\xbd\x67\x39\x3b\x09\x6f\xe2\x5a\x52\x5e\x36\x3c\x12\x96\xeb\x67\xa4\xbc\x94\xcc\x83\xe5\x7f\x8d\xd4\xaf\xe4\x67\x5e\x5b\xce\xe7\xaa\x2b\x2d\xb1\xcb\x62\xbc\xf3\xf5\x0d\xaa\xd7\x6d\x7c\xb4\xfc\xaf\x6d\xf0\x24\xca\x65\x0e\xbd\xee\x29\x65\x3c\xc0\x52\x3f\x97\xef\xd6\x0f\x27\xcb\xd4\xbf\xd4\x5f\xdb\xde\x7b\x2d\xab\xec\xc5\xa8\x7e\xa3\xcf\x9f\xae\x10\x51\x7f\x59\xfb\x5e\xf7\xef\x6f\xe5\xad\xe5\xcb\x76\x72\x82\x5c\x3f\x5f\x7f\xb3\x0c\xff\xe0\xfb\x72\x8d\xfc\x27\xab\xe7\xbb\xe0\xf3\x93\x56\x4f\xa8\x01\xd5\x24\x8c\x24\x63\x11\x15\x4c\x48\x0d\x43\x16\x07\x1a\x40\xac\x69\x10\x70\x1e\x46\x9a\x32\xcd\x02\x15\xa1\x28\x94\xa1\x64\x82\x03\x4d\x35\x27\x2c\x20\x41\x78\x3a\x28\x81\x1e\x68\xf5\x7c\xb6\x7c\x29\x10\xa7\xfc\xdd\x13\x13\x2f\xb5\x92\x10\x21\x91\x20\x0c\x88\xfb\xad\x9e\x0f\xd6\x2f\xcf\x5a\xe6\xa6\xf5\x83\xce\xab\xb7\xf0\x3c\xab\x5f\xe4\x7b\x56\xc9\x6c\xc7\x26\xd0\x6e\x39\xbf\xf1\x73\x1d\xbc\xa2\x46\xb3\x5c\xd4\xcb\xe9\x5c\x65\x1b\x53\x51\x61\x87\xde\x22\x5d\xde\xe1\x3a\xdd\x4e\x0f\xe9\x36\x41\x15\xea\x12\x97\x35\x57\x83\x7e\xab\x09\xf7\x11\x0d\x6b\x64\x30\x41\xa9\xd6\xd1\x1b\x7b\xbe\xd7\xd7\x60\xd8\xdf\x7d\x29\x30\x35\xe9\x3a\xbf\xbb\xa1\xe6\x24\xd6\x0b\x6f\xa1\xf6\xbd\xeb\x6d\x0f\x94\x7f\x6f\xd0\xe7\xa3\xb5\xe0\xef\xe5\x63\x2d\xf8\x07\xb5\xb0\x71\x91\xff\xe3\xeb\x57\x27\x79\x6f\xad\x5f\x3d\x95\x4f\x37\xdc\x6e\xe8\xab\xbb\xfd\xf4\x07\x8e\xd5\x35\xf2\x9f\x88\x55\xda\xe5\xbb\xa2\x58\x23\x3e\x98\xd0\x5e\x3f\xd6\xc7\x51\xc6\x03\x6b\xb6\xd1\xe3\x5d\x54\x89\x77\x7c\x59\x30\x97\x02\x5b\x51\x71\x92\x8a\x8b\x32\x1c\xfa\x7c\x14\xf6\xc2\x79\xfd\x50\x70\x5a\x8d\x8e\x83\xc7\xeb\xec\xa0\x10\x86\xb4\x53\x36\x5b\x99\xbe\xe9\xf0\x7a\x25\xfb\xd3\xc1\x9c\x28\x60\x52\xf0\x80\x49\x0c\x74\x10\x72\x8d\x43\xad\x02\x15\xcb\x90\x33\x1d\xf1\x00\x30\x01\x10\x63\x42\xc1\x18\xea\x10\xc4\x02\xc5\x94\x71\x08\x20\x09\x49\xc8\x30\x3b\x9d\xa6\x87\xf7\x87\x7b\x7c\x76\xa4\x42\x60\x81\xc1\xbb\x39\x63\x5e\x6a\x9f\xc8\xc7\x31\x44\xf7\x47\x7b\x14\x5f\x8d\xfa\x6f\x2f\xf2\x0d\x8a\xf2\x9d\x68\x0f\x2b\x9e\x37\xf5\x2a\x24\x23\x2f\x5d\x8b\x33\x7b\xd8\xdc\x2f\xca\x95\x75\x17\xa5\x48\x8d\xd4\x41\x67\x7f\xec\xf5\xaa\x35\x68\x62\xff\xd0\xef\x1a\xcb\x74\x41\x14\x0e\x5d\xb3\x47\xf4\xd0\x6a\x38\xd3\xfe\x46\x2e\x8c\x3e\x71\x8b\xdd\xe2\x28\xcc\x2c\x03\x77\xaa\x1a\xd2\x52\xbe\xf3\xa8\x68\x0f\xe7\xf6\x68\x0b\x15\x36\x56\xdb\x04\x96\x0a\x6f\x4a\xfe\x0c\x4e\x8f\x93\xff\x7a\x4c\xbf\x24\x3f\x01\xa7\x3b\x22\x0c\xf6\xeb\xca\x41\x26\x9e\xe4\x9d\x1b\x8b\x3e\x56\x78\x77\xc8\x9f\x75\x8b\x60\x7d\x87\x7c\xe3\xb5\xfc\x1f\x54\xf8\x6f\xc2\xc7\xbb\xbd\x2f\xf6\xeb\xca\x31\xb9\xc8\x3b\xbb\xb2\x2f\xee\x1d\x8b\x5f\x73\x21\x05\x6e\x93\xff\x04\x1f\xcc\x5a\xd9\xa5\x9b\xca\xdb\x55\xd0\xd9\xa9\xa8\x55\x0a\x86\x8d\x65\x3b\xda\x6e\x6c\x6d\xaf\x1d\xa1\x48\xce\x02\x91\xb7\x46\xa5\x59\xdb\x2b\xa4\x0f\x5b\x73\x35\xf1\x66\x95\xec\x6c\x07\xf6\x5d\x12\x6e\x83\x5e\x4e\x67\x06\xa8\x4e\xdd\x5d\x80\xfa\x73\x6c\xa7\x3d\xec\xfe\xf4\xcd\x72\x92\x11\x48\x03\x05\x23\x14\x73\xc9\x10\x0c\x11\x0b\x21\x65\x22\x96\x0c\xc7\x91\x88\x22\xa6\x28\x50\x08\x04\x08\x29\x4e\x90\x50\x3a\x0e\x63\x2d\x23\xad\x05\xe3\x54\x88\x27\xf8\xa0\x3b\xe1\xf3\xd9\xf9\x01\x81\x05\x61\xef\xde\x8d\xfb\x52\x7b\x86\x0f\x82\x04\x3c\xe0\x58\xf9\xeb\xb0\xb8\xdf\xe0\x73\xc3\xae\xf8\x7b\xf0\x89\xf2\x6e\xb4\x8d\xba\xa8\x4e\xbc\x59\x27\xaa\xa4\x2a\xd1\x5a\x74\x6b\x91\x6e\x6d\xf8\x24\xb3\x5d\x70\x67\x5d\x95\xb3\xd1\x62\x29\xc5\xdc\xb5\xd2\xc3\xba\xb1\x0c\x46\x63\x6f\x1b\xd4\x26\xe6\xa1\x64\x14\x73\x25\x0b\x8d\x5c\x51\x43\x85\x61\xbf\xb0\x3d\xf0\x59\xae\xc8\x72\x0f\x0b\x35\xbc\x43\xf9\x07\x6e\x5d\x16\xef\x55\xfe\x0f\x94\x7f\x53\xa8\xe3\x63\xe0\xf3\x5a\xf9\xdf\x14\xde\xf6\x07\xc3\xeb\x8c\xd7\xf2\x7f\x70\x57\xf0\xd1\xa1\x86\xf7\x28\x7f\xe3\x41\xf0\x49\x1a\x22\xb7\xc0\xa7\x5e\x9b\x86\xb8\x1d\x8d\x36\x76\xc1\xc1\x8d\xed\x70\x1a\xc6\x6e\xb3\xd3\x19\x87\x1b\xda\x0b\xd9\x66\x1f\x36\xd2\x41\xbe\xb0\x48\xc7\x85\x5a\x2f\x4d\x40\xaf\x80\xe6\xf9\x66\x11\x8d\xba\xbd\xd5\xd0\x30\x0f\x96\x21\xe7\x99\xad\x1d\x0d\x66\xa4\xbe\x14\x1b\x66\x9a\xa9\xc1\x4f\xef\x50\xc6\x40\x44\x0a\xc6\x5a\x41\x0a\x62\xc4\x19\x65\x48\x30\xa6\x34\x89\x29\xe2\x28\x66\x54\xa8\x18\x84\x91\x8c\x23\xa1\x60\x24\xd9\x2f\x08\x41\xc9\x42\x8d\x34\x0c\x11\x3d\x79\x3e\x4f\xd0\x70\xad\x5a\x1b\x73\x5a\x32\xfc\x1a\x61\x15\xcb\x75\x50\xdb\x35\xca\x9e\x89\x6a\xb5\x6e\x91\x57\x10\x61\x96\x9f\xcd\x9a\x6e\xbb\xd1\x42\x35\x9b\xe7\xb2\x36\xf2\x9a\x5e\xd1\xfa\xcf\x7f\xff\x8f\x09\x0e\x25\xe1\x8c\xe3\xcf\xd2\x88\x09\x22\x20\x7e\x7f\xad\xee\xb9\x56\x50\x21\x25\xa6\x00\xc0\x97\x80\xf7\x4a\x79\x9d\x66\x3b\x37\x27\x04\xe9\x0e\xd8\xca\xb7\x7c\x13\xba\x95\x56\x3a\x5a\x4e\xfb\xa4\xa2\x6a\xcb\xc6\x72\x91\xaf\xce\x2a\x8d\xe6\xc9\x3c\x3f\xaf\xd5\x9d\xbe\xf9\xc1\x2d\x3d\x89\x38\x11\x6b\x13\x1c\x7a\xcf\x1f\x18\xce\x32\x25\xbb\x39\xe8\x96\x8b\xcd\xe1\xaa\xdd\x29\xc2\x41\x81\x4a\x4b\x82\xe2\x80\xec\x28\x03\x9c\x85\x22\x5b\xd8\x77\xe3\xf3\x8e\x4e\xad\xd5\xaa\x3f\xfd\xca\x66\xb7\x2d\x1f\xcb\x23\xb9\xde\x85\x9b\x7c\xb6\x99\x59\x4c\x3b\x88\xb9\x7e\x0e\x97\x42\x33\x9a\x7b\x4d\xb9\x26\x53\x66\xb7\x6a\x9d\xd5\x79\x66\xf2\xc9\xea\xb7\x99\x9b\x61\xd6\x08\x9a\xbd\x53\x00\x7d\x8a\x0f\xf7\x7a\x95\x29\x14\x96\x0e\x26\x78\x36\x3d\x1c\xd4\x70\x8e\xd6\x03\xaf\xd8\x1d\xb8\x59\x64\x37\xc6\x29\x19\x6f\x2a\x8b\xd9\x7a\xab\x7d\xb4\xcc\xf5\xb6\x6b\x39\xed\xa5\xbc\x3c\x0a\xac\x2a\x4e\x55\xa7\xd6\xca\xb7\x03\xd9\x6d\x06\x46\xaa\x3b\xd5\x68\x9a\x73\x7b\xf6\x17\xa8\xf6\xdb\x2d\x3c\xc5\x55\xf1\xa8\x8e\xdd\x6a\xa8\x5c\x3e\xa8\x41\x23\x98\x43\xb9\xe9\x4f\xcc\xf2\xd1\xdd\x4d\x83\xa6\x53\x0d\x75\x3e\xd5\x77\x9a\x2d\x9e\x20\xc1\xa9\x3f\x1d\xa7\xd5\x7a\xea\x67\x93\x9b\x02\x97\x50\x03\xe1\xcc\x86\x8c\x22\xcf\x5d\x44\x71\x38\xeb\xf6\x86\x6a\xbf\xca\xa3\x71\xa6\x81\xf0\x20\x9e\xd5\x5a\x8e\xde\xbf\x1e\x93\xbf\x63\x8c\xfe\xdf\xfb\x84\x4f\x34\x93\x20\x9c\x5e\x1a\xfe\xf0\x78\xec\x4f\x8a\x8b\x7d\xaf\xdc\x2b\x36\x7d\xda\x91\x68\xa3\xb3\x3d\xba\x77\xd7\x95\xcd\x6c\x94\xea\xd1\xb2\x77\x3e\x22\xd5\x32\xb6\x03\x78\x99\x99\x37\xed\x58\x3e\x50\xbe\x75\x8b\xfc\x73\xa3\x4f\x54\x69\x24\xbe\x6f\x9b\x95\x9e\xbd\xab\xd5\xf3\x23\xb0\xae\x57\xf6\x5d\xb5\x6d\xe7\x96\x53\x50\xc5\xde\xa6\x38\xb4\xa6\xcb\xc6\x76\xbe\xdd\xa9\xa5\x33\x16\xf7\xce\x95\xd3\x91\xb4\x8f\xd6\xfe\x5e\xfe\x6e\xfe\x91\xf6\x15\x8b\x5e\xe7\xed\xd8\xba\x44\x49\xf4\xdf\x79\x9e\x5f\x3b\x57\x2f\x43\xd1\x6c\xb5\x9a\x4f\xef\xca\x4d\xef\xee\xe5\x5d\xfb\x5a\xac\xe6\xb5\xfd\x71\xf9\xfe\xa3\xdf\x9f\x9b\xe6\xef\x3d\xf2\xdd\xac\xed\xdf\x21\xff\xf4\x79\x3b\x61\x4c\x5e\x39\x5e\x6f\x3f\xff\x6f\xa9\xfc\xde\x8c\x4d\xbc\xe8\xb6\x37\x8f\xc4\x26\xde\x97\x73\xb9\x72\x3e\x16\xaa\xf3\xc5\xb1\x79\x91\x5e\x32\xbe\x1e\x6b\x77\x29\xaf\x8f\x98\xbe\x61\xc9\x36\x12\xdd\x39\x0c\xe3\xd4\x2a\x33\xa8\x56\x2b\xae\xbf\x59\xba\x06\x32\xd6\xb5\xe1\x38\xc6\x01\x25\xda\x9a\xda\x01\x60\x6c\xd0\x78\x61\x6c\x62\xd7\xf7\xdc\xc6\x9b\xa2\x34\x9a\xf7\xc9\x2f\x36\x6f\x93\xff\x64\xc9\xc6\x1b\x22\x3a\x4b\xa3\x3e\x58\xec\xa3\x54\x99\xe5\xc5\x6a\x9a\x63\xd1\xd2\x1f\x99\xc8\xef\xf7\x65\xdf\xa6\xf1\xb6\xc3\x87\x8b\x45\x31\xc4\x93\xf2\xe2\x90\x2b\xf2\xb8\x4b\xaa\x23\x33\x9a\xf4\x8e\x32\x3d\xa4\x3b\xee\x66\xdc\x6d\xbb\xe5\xf6\xaa\x93\x2e\x5e\xcf\x0f\x99\xd9\x4f\x67\xc4\x85\x52\x08\x42\x94\x08\x09\x47\x51\x10\x28\x45\x43\x0e\x39\x93\x34\x20\x2a\x80\x2c\x50\x5c\xca\x00\xe2\x38\x44\x2a\x26\x90\xa2\x08\x4a\x8d\x20\xe4\x81\x86\x8a\xb2\x53\x42\x06\x28\x1f\x68\xc9\x7e\x1a\x6b\xc7\xa8\x64\xfc\x5d\x4b\xf6\xb9\x56\x40\x06\x08\x16\x88\x23\x70\xbf\x25\xfb\x41\xac\xdd\x79\xd6\x5c\x76\x9d\xef\xb1\x72\xbc\x1c\x33\x1a\x19\x27\x37\x69\xd4\x61\x8e\x3b\xe3\x83\xf4\x07\x9b\xd8\x4b\x47\x26\xd9\x94\x2a\x7a\x5d\x49\x4d\xd2\x99\xc3\xaa\xdd\x39\x9c\x3e\x7e\x07\x69\x5e\x1d\xce\x4e\x94\xec\xcb\xf3\x7b\xa5\x95\xdc\x96\xbb\x14\x8a\x99\xdf\x2c\xcd\xb1\x68\x04\xa3\xd9\xb6\x9d\x4e\x5b\x56\x23\x5c\xa5\xe5\xac\x3a\x84\x35\x63\xb0\xa7\xf6\xd8\x4c\x47\xbc\x17\xb6\x83\xa0\x5c\xce\xef\x0b\x5e\x8d\xeb\x52\xb9\xc2\x96\x99\xd4\x74\xed\x2e\xb4\x26\xed\xcd\xb2\x91\xef\x19\x64\x84\x76\xab\xaf\xec\x7a\x9b\xaf\xfa\xf7\x36\x92\x26\x7e\xfa\xf2\xbc\x89\x5d\xce\x3b\xac\xe2\x3f\x62\x95\xbf\x26\x45\xe2\xef\x9f\xb3\xca\x93\xc9\x11\xde\xb7\xca\x93\x54\xbd\xc1\xaa\x78\x8a\x23\x34\x8c\x5b\xe3\x18\x1f\x28\xff\x26\xaf\xc0\xbc\x10\xb2\x96\xf8\xfe\xcf\x59\xbd\xe7\xa6\x7c\xc5\x2a\xff\x8b\xbd\x86\x53\xff\xd5\x2f\xed\xbb\x96\xf0\xf7\xbe\xeb\xd7\xf6\xdf\x0f\xb6\xef\x4b\xe3\x9b\xe8\xbf\x3f\xed\xd5\x9c\xbc\xb0\x73\xa3\x13\xf3\xed\xfd\xfe\xfc\xd3\xed\xfd\x92\x17\x96\xe8\x5f\xe3\x96\xf6\xbe\xb6\x40\x4b\xc6\x97\xe3\x84\x2f\xfd\xf9\xe6\x52\xd6\x39\xae\x35\xb1\x65\x70\xed\xfc\x1a\x7b\x45\x72\x5e\xf2\x3f\x4b\x7f\x7d\x9d\x7d\xb2\x2d\x2f\xe5\xfc\x14\x15\xba\x7c\xda\xa8\x7f\x33\x91\xce\x99\x0f\x89\x13\x66\x77\xb2\xfd\x0e\xdb\x2b\x01\x74\xef\xcd\xe7\x33\xfe\xc9\x93\x3f\xdd\xde\x44\x7f\xbe\xdd\xde\xb7\xf6\x1a\x6a\x89\xae\xbf\xc1\x43\x3a\x47\x39\xd9\x97\xf1\xbd\xd6\x43\x7b\xa0\x87\x78\x43\x5c\xf0\xe1\x88\x04\x9c\x4e\x3b\x87\x7e\xdf\x3b\x4c\xe3\x7d\x79\x51\x1f\xc8\x30\x2d\x4a\xe5\xf2\xe6\x98\x46\xbd\x54\xb5\x65\x9b\xc5\xec\xa8\xde\x2c\x4a\xbc\xc9\xac\xbb\xf3\x19\x00\x53\x7b\x9e\xc9\xae\xc9\x0e\xf0\xc5\x2a\xcb\x34\x08\xe6\x94\xf7\x03\xb6\x2e\x4d\x0c\x6b\xd0\x08\xcd\x1f\x4e\xaa\x23\x01\x0a\x25\x50\x08\x23\x14\x4a\xcd\x42\x8c\xa9\xe6\x94\x60\x2c\x64\xc0\x09\x61\xa1\x60\x1a\x03\x2c\x75\x18\x53\xa9\x15\x63\x51\x1c\x87\x14\xe8\x40\x2b\x10\x29\x71\xba\x1f\x44\x3c\x79\x68\x46\xa7\xe4\x10\xdc\x70\xbb\xd9\x36\xf6\xca\xb8\x66\x57\x9a\x06\x6a\xd2\x6a\x9b\x66\x1a\x46\xad\xe3\xba\x7e\x1e\xe7\x73\x4e\xb6\x8d\xfd\x06\xf3\x6a\x85\x5a\x11\x9b\xd5\x6a\xf3\x1f\x1e\xda\xa7\x71\xc1\x82\x00\xf9\xbe\x87\xf6\x5c\xcb\x4f\x57\x9b\x40\x4a\xd0\xcb\x69\xa8\x2b\xb5\x54\xc2\x43\xfb\xec\x26\xc9\x6b\xad\xc0\x07\x79\x74\x27\xf9\x2f\xed\xf5\x4c\xd9\x41\x39\xdc\x3d\xc2\x3d\x36\xbc\xd2\xa2\x48\x3a\xe6\x51\x57\x1b\xe3\xdd\x74\x36\xda\xa2\x8c\x37\x6d\xbb\x93\x06\x00\x7c\x96\xa5\xb2\x17\x0c\xb0\x2e\x6f\x78\xba\xdd\x9a\x65\xd7\x6d\xd1\x5f\xf5\xb2\xc3\x15\x9c\x74\x0b\x1c\x48\xe7\x78\xac\x39\x48\x85\x16\x5a\x7b\xf6\x57\x3c\xaa\xb7\xaf\x59\x78\x6d\xb5\x27\xd6\xae\xee\x5c\x0b\x7b\xa7\x7c\x62\xb5\x3f\x4e\xfe\x6d\x71\xc4\x6f\x5a\xed\x7f\x9b\x55\x77\xfa\xfb\x2f\xb5\x8a\x3f\x0b\xb5\xba\xc5\x42\xf2\x3e\x1e\xb9\xd7\x12\xde\xeb\xab\x9b\xe5\x27\x09\x78\x8d\xfc\x27\x02\x15\x61\xec\x0f\xa3\x69\xb5\x93\x55\x19\xe3\x30\xdb\xf6\x55\xb1\x4c\x64\xa5\x63\xea\x41\x3d\xed\x3b\x66\xe4\x07\xdd\x6a\xa3\xb1\xe9\xc5\x53\x94\x59\x14\x23\x82\xf8\x56\x76\xdb\x3d\x0d\xc3\x83\x7b\x30\x74\xe5\xd8\xee\x8e\x96\xdb\x06\xe8\x54\xcb\x76\xa7\xbb\x5f\x55\x83\x1f\x3f\x8f\xab\x02\x4e\x59\x04\x29\x94\x4a\x47\x01\x97\xb1\xe0\x08\x01\x82\x42\x88\x94\x0e\x78\x18\x00\x40\x14\x0e\x23\xc9\x60\x10\x85\x0c\x85\x54\xc6\x42\x04\x82\xf1\x58\x30\x1d\xe2\x27\x02\xa1\x47\x11\xe8\xd3\x35\x42\x41\x30\xa7\x1f\x10\x08\x73\x76\x21\x90\xa4\x97\x35\xc2\xdb\x09\x74\xf5\x79\xdc\x6b\xed\xc8\x0b\x56\xec\xb7\xe4\x9d\x4b\xed\xf9\xf3\x19\xa3\xb8\x09\x06\xd4\xdb\x2b\xed\x84\x6b\x63\x60\xd2\xe9\x68\xba\x2e\xb7\xa6\xdb\x7a\x55\xb7\x6b\x29\x33\xe5\xf4\xe6\xe3\xaa\x11\xd5\x7a\xb5\x7a\xaa\x5a\xb5\xeb\xf3\xe6\xa0\x6e\x1e\x36\x83\xdd\xa6\x3f\xd9\x6e\xac\x1d\x1f\xed\xf6\xd3\x94\xc1\x6c\x50\x22\x2a\x80\x2b\xb4\x38\x96\x8c\xde\x1d\xe7\x71\x6f\xd2\x86\xf6\x8f\xf4\xdd\x0f\x10\xf1\x26\x22\x3d\x50\xfe\x3b\x67\x09\xbf\x1c\x3f\xf6\x40\x3f\xf7\x9d\x2c\x2c\xdf\xaa\xc5\xaf\xde\xe9\xf9\xad\xfe\x4d\x3f\xfb\xf4\xc9\x7b\x77\x63\x7f\x78\x8e\x5f\xc8\xfc\x87\xc8\x68\x3c\x68\x4c\x93\xbe\xe1\x35\xf2\x9f\xc9\xfc\x4d\x0a\xf2\x27\xc9\x8c\x79\x18\x72\x19\x33\x49\xa5\x02\x5a\x68\x19\xe2\x08\xc3\x98\x29\x89\x81\x88\x44\x04\x04\x89\xa4\x62\x9c\x20\x15\x07\x94\xa9\x00\x48\xa2\xe2\x80\xe9\x40\x4b\x49\xd0\x33\x99\xf1\xa3\xc8\xfc\x69\x1c\x9a\x20\xfc\x83\x33\xa3\xcf\xb5\x67\x32\x23\xcc\x2e\x71\x68\xb7\x93\xf9\x83\x38\xb4\xf3\xbe\xf8\x1d\x31\x4a\xa7\xb2\x5a\x67\x74\x62\x56\xbf\x93\x29\xe3\x42\xe6\xe5\x71\x2e\x9d\xfd\x7e\x31\x4e\x1d\x66\x87\x55\x6f\x6c\x0d\x3b\x13\x99\x5a\xae\xf2\xba\xdc\x41\xee\xaa\x1e\xf0\x46\xe5\x80\x8d\x63\xb6\xb2\x21\x3e\xed\x8a\x9c\xb9\xa7\xc8\x13\x82\xf6\x3c\xd7\x6b\x97\xd6\x76\x15\xec\xd8\xa1\x2f\x70\xc4\x52\x33\x36\x1a\x9a\xe9\xf6\xe6\xe7\xc9\x7c\x77\x7c\xd7\x97\xfa\xee\x07\xc8\x7c\x5b\x4e\xa9\xcb\x32\xe7\xeb\xef\x3c\x7a\x45\xf8\x31\xa4\xf2\x8c\x7f\xe4\x68\x7b\x60\xff\x7d\x2d\xee\xe6\xcf\xf5\xdf\x63\x56\xd4\x8d\x47\x90\xfe\x87\xdf\x99\x87\x91\xfe\x56\xd2\x1a\xdf\x30\xa6\xd7\xc8\x7f\x22\xfd\x77\x29\xdc\x1f\xf5\xc1\x23\x1d\x13\x1a\xfd\xf2\xb1\x23\x2a\x31\xa7\x98\x42\x1d\xf0\x28\xe2\x3a\x66\x04\x92\x38\x26\x12\x73\x18\x60\x4c\x39\xc2\x5a\x90\x28\x88\x03\xa5\x03\xa8\x21\x66\xec\x14\x71\x0e\xf9\x03\xe3\x74\x3e\x5d\x05\x96\x02\xf0\xf7\x57\x81\x9f\x6b\x39\x06\x90\x10\x22\x20\x12\xf7\xc7\xe9\x5c\x91\x1d\xe2\x8a\x59\xf8\x66\x76\x88\x44\x9c\x4c\x6e\x58\x5c\x28\xbf\x63\x0b\xdb\x58\x65\x99\xb5\x47\xfd\x5d\x75\x38\xb0\xe3\xac\xdb\x25\xc3\x55\xa9\xdc\xed\x2a\x5e\x3d\x4c\xcb\x83\xfc\x40\x8e\x9c\xce\x30\xde\x6e\x8b\xd6\xb8\x3d\x38\xba\xc6\x12\x65\x64\xc9\xb1\x96\xb1\x55\xb3\xb6\xc3\x69\x66\x5f\x28\xf4\xf3\x83\xd8\x56\x5e\xe9\x61\xd9\x21\xec\xc4\x57\x6f\x89\x85\x98\xbe\xd5\xb3\xff\x28\x9f\xf8\xb0\x8f\x93\x7f\x6f\x76\x88\x47\xef\x85\xfd\x5e\x3e\xd6\x82\x7f\x70\x2f\xce\x30\xfe\xde\x55\xed\xcf\x56\x8d\x6f\xe9\xab\xbb\x57\x8d\x1f\x38\x56\xd7\xc8\x7f\x22\xd6\xa0\xb4\x99\xef\xfb\xaa\xb1\xf3\xcc\x5d\x3c\xab\x66\x83\xac\x91\xaa\xe4\x6a\x42\x75\xa7\x83\xca\x6e\x07\xc7\xe3\xe3\x2a\x5d\x50\x28\x37\x29\x22\xaf\xa5\xcb\xa9\x94\x58\x55\x5a\x41\xb1\xe4\x9b\x5b\x3f\x0b\x76\xcd\xca\x5a\x94\xed\x4a\xaa\xa2\xb2\xf6\x6c\x61\x4f\xf2\xa2\xb6\xff\xe9\x8b\x9f\x23\x18\x53\x89\x75\x48\x35\x24\xb1\xe4\x00\xf1\x50\x71\x29\x10\x8c\x03\xc2\x18\x12\x0a\x02\x0e\x30\x89\xc3\x40\x06\x34\x50\x3a\x66\x81\x8c\x02\x2e\x35\xa0\x50\x6b\x8e\x9f\x88\x75\x5e\x35\x36\x8d\x1a\x32\x6c\xdf\x2e\xe4\x1a\x36\x2a\x16\x72\xb4\x56\xea\x38\xb4\x94\x6b\x75\x99\xc7\x3b\xb9\x62\xad\xe2\x5a\x0d\x84\x2a\x3c\xdf\x21\x56\xbd\xed\xd4\xb9\x63\x59\xd5\x6b\x89\x85\x3e\xf0\x4d\x7f\xd5\xe2\x17\x62\x51\x84\x2e\xfb\x96\x57\x46\x6e\x5e\x43\xac\x9b\x6c\xc5\x37\x89\xe5\xbc\xc8\xf7\x72\xbc\x1f\xee\xba\x0a\xa6\x0a\xed\xb8\xaf\x5b\x53\xdf\x58\xd0\x46\xc7\xe9\xc8\x60\xaa\xb2\xf9\x49\x7e\x01\x76\x2d\xa0\x64\xa5\x9c\x8b\x5d\xd6\x14\xeb\x65\x3f\xd7\xd2\xad\xd9\xc0\xb6\x90\x6e\x3a\xce\xa4\xbf\x4f\x85\x99\xb5\x23\x1b\xd5\xfa\x76\x10\x3b\xe9\x49\x6c\x8d\xbd\xd1\xb7\x10\xeb\xca\xc8\xc6\x87\x13\xeb\x4e\xf9\x0f\x24\xd6\xb5\xd1\x79\x8f\x26\xd6\x43\xe4\xdf\x41\xac\xbf\x29\x7a\xf2\xd3\x7d\xce\x1b\xfa\xea\x91\xc4\xba\x77\xac\xae\x91\xff\x44\xac\xe1\xc6\xd9\x66\xc6\xc7\x0e\x99\x77\x53\x0e\x6d\x47\x3d\x73\x39\x2e\xab\x56\x0c\x17\xd1\x4e\x4d\xfc\xc9\xb2\x91\xe9\xd4\x8e\x80\x80\xbe\x08\xe7\x8d\x03\xda\xd8\xfd\x16\x6d\x0f\x72\x5e\xb5\x4b\xbd\x66\x3b\xc8\x66\xe9\xca\x05\x1d\x58\x92\x85\x54\x5e\x74\x52\x5d\x51\x69\x99\x3f\xbc\xcf\x19\xd0\x40\x6a\xac\x02\x86\xb5\x54\x0a\x52\x8a\xa9\x54\x92\x63\xcc\x43\x15\x42\x42\x18\x51\x2a\xa0\x2c\x44\x18\x04\x24\x02\x8a\xc7\x88\x53\x81\x18\x21\x11\x64\x02\x9c\xae\xeb\x60\x77\xe7\x33\xfa\x6c\x77\x53\x42\xc0\x4e\xe9\x2b\x3e\xae\x3d\x83\x4f\x00\x81\x1f\x90\xce\xe8\xf5\x96\xcd\x6f\xef\xf1\x0d\x96\xfd\x7b\x97\x57\xf5\x1d\x2b\x1d\xfa\x41\xa3\xdb\xcd\xe3\x56\x5e\xee\xf3\x8b\xce\xac\x4d\xb5\x2e\x16\x80\xa1\x9d\xc0\x68\x64\xb2\x12\xa9\x5a\xbc\x07\xed\x66\xc3\x59\xcc\xd9\xb2\xb3\x27\x3c\x2e\x65\x9a\xfb\x51\xdb\x5f\x88\xd0\xc8\x96\x62\xdf\xac\xd3\x4e\xa7\x5a\xeb\x09\xb6\x32\xdc\x66\xe1\x51\x19\x25\x92\xef\xc7\x95\x19\x1d\x86\x41\x8b\xab\x04\x00\xb3\x6f\x4a\xfe\x8c\x4d\x8f\x93\xff\xce\x36\xdc\x97\xd9\x94\xa4\xe4\x75\x59\x04\x16\xe5\x79\x67\xbd\x4b\xa4\xd0\xf9\xed\xd0\xdc\xb9\x7c\xac\xef\xee\x90\x6f\xb7\x9a\xdb\xde\x1d\xf2\x5f\xd7\xfe\xa4\x87\xf2\x26\x7b\xca\xb7\xf7\xc5\xaf\xb1\x80\x89\x66\xa8\x2b\xfb\xe2\xde\xb1\xf8\x25\xff\xd8\xbb\x4d\xfe\x13\x7b\xfc\x9a\x97\x46\xc8\x1d\xa1\x76\x3d\x82\xf5\x58\xd5\x83\x31\x73\x36\x9d\xe9\xe0\xb0\x36\xb2\xfd\xf6\x2f\x12\xa6\xa3\xa9\xdd\x11\x91\x33\xb6\xf7\xc1\x42\x2f\xa0\xd0\x15\x7c\x34\x5a\xa5\xae\x33\x29\x6c\xdd\x5d\xe6\x98\x45\xc6\x68\xd3\x82\x47\xe0\x57\x2b\x4b\x23\x33\x36\x7f\x78\x7d\x8f\x05\x80\x32\x28\x64\x48\x28\x67\x40\x31\xc0\x35\xc6\x50\x49\xa0\x68\x20\x42\xa2\x22\x8e\x80\x64\x30\x8a\x45\xa8\x84\xd2\x2a\x8e\x48\x10\x60\x21\x42\xca\x79\xc0\x54\xf8\xc4\x9e\x3b\xd3\x19\x7d\xb6\x7f\x27\x21\x10\xe4\xdd\xc8\x9a\x97\xda\x27\xf6\x10\x89\x1e\x90\xcd\x28\xff\x6a\xd0\x7f\x63\xcf\x0d\x36\xfa\x3b\xec\x31\xf6\x26\x55\x63\xbe\x1e\x0d\xbd\x1c\x50\xb1\xd3\x6d\x0c\x72\x8e\xb5\x99\x81\xfa\xee\xe0\x4f\xcb\x8b\x46\x33\x8b\xfa\x7b\x2b\xb3\x9e\xf0\x7e\x7a\xdb\x1c\x65\x5c\xac\x7a\x3b\xb7\x53\x17\x7c\x3a\x98\xb6\x46\xfd\xc9\x36\xca\xcd\x1b\xed\x58\xe7\xb4\x3b\xd8\xf1\x51\x4f\xc7\x4d\xe3\x2f\x60\x4f\xdf\x69\x15\xc9\xbd\xba\xff\x81\xf2\x5f\x8f\xe9\x97\xe4\x3f\x86\x3d\xaf\x75\xff\xe8\x6d\x89\xdf\xa5\xef\xe6\x3c\x53\xdb\x7b\x77\xc8\xff\xad\xf6\x07\x7d\x8d\x07\xa7\xd2\xbb\x4b\xf7\x1b\x0f\x62\xcf\x5e\xdc\x26\xff\x39\x8f\xab\xb7\xe9\xe4\x35\xef\xe6\x80\x59\xce\x66\xf7\xed\x26\x19\x64\x3c\xbe\x28\xdb\xab\xd2\x24\x7f\x0c\x46\x30\x23\x67\xca\xdb\x85\xdd\x0d\x89\x39\xcc\x1b\xb5\x35\xce\x95\x32\x63\xb0\xad\x50\x32\x87\xdd\x5c\x77\x89\xeb\x85\x26\x9c\xe2\x41\xb6\x3f\x5b\x55\x68\x2e\x3b\x85\x3f\x9d\x79\x1c\x8a\x30\x66\x4a\x69\x04\x54\x1c\x86\x20\x96\x80\x4b\x45\x42\xc1\x05\xe6\x50\x48\x22\x23\x88\xc3\x08\xa2\x08\x72\x1c\x30\x80\x19\x8e\x50\x28\x34\x0e\x00\xd7\xb1\x0e\xa2\x27\xf6\xe0\x3b\x53\xe9\x81\xcf\xe1\x23\xd9\x47\x8e\xcf\xb9\xf6\x09\x3e\x12\x5c\x16\xe8\x6e\x87\xcf\xeb\x3d\xea\xdf\xe0\x73\xc3\xe6\xf9\x3b\xf0\x31\xd3\xb5\xd6\x7a\xc6\x0e\x6b\x63\x91\x9d\x47\xac\xeb\xb4\x87\xbb\x8e\x77\xe8\xcc\xe6\x85\x4a\xed\x28\xbc\xfa\xf6\x08\x22\x51\x9b\x55\x97\x15\x3b\xd3\x2b\xdb\x1b\x63\x28\x52\xa3\xf0\xd0\xaf\x73\x6f\xa0\x2b\x8b\x5d\x38\xc8\x2f\xeb\xc0\x68\x0a\xbf\x1d\x64\x3c\x8f\x1c\x55\x6a\x57\xfc\x0b\xe0\xa3\x77\x4d\xd5\xbc\x57\xf9\x3f\x50\xfe\x4d\x79\x64\x1f\x02\x9f\xdf\x94\xff\x4d\xe9\xdb\xee\x90\x7f\x6f\xee\xd2\xdf\x6a\x7f\x30\xa0\xff\x3b\xe0\x73\xab\xf2\x37\x1e\x04\x9f\xa4\x13\x7c\x03\x7c\xb6\xa0\x15\x06\x95\xd5\xd2\x2b\xf4\x59\x47\x4f\x6a\xad\x99\x70\x40\x69\xcc\x0a\xf5\xe1\x48\xa5\x6d\x7b\x29\x64\x36\xb6\x03\x8b\x1d\xfb\x86\x6f\xd5\x8a\xbd\x5c\xba\x3a\x77\xc5\xac\xb9\x01\xb9\xe9\x70\xb1\x72\xc9\x20\x00\x6b\xc3\xa9\xba\xce\xa4\xd7\xb4\x2b\x25\x5c\x5d\xfd\xf4\xf1\x36\x48\x90\x92\x42\x84\x30\x66\x5c\x0a\x12\x73\x12\x40\x2a\x60\xa4\xa5\x0a\xb4\x8a\x89\x94\x9a\x81\x18\x6a\xa0\x75\x44\x24\x63\x0c\x06\x01\x52\x94\x4a\x84\x05\x67\x44\xfd\x22\xc7\xf3\x9d\xf1\x66\xd6\x24\x16\x32\xeb\x84\x9a\xf9\x5a\xb9\x4c\x3c\x23\xdb\x40\x45\xa7\x6b\xe4\x73\x4d\x5a\x35\x78\x96\xe2\x02\x6e\x55\xaa\xac\x6d\xe7\x59\xa7\x9d\x2d\xd7\xcb\xdd\x82\xe7\xfe\xe7\xbf\xff\x47\xa9\xc0\x84\x72\x22\xe8\xa7\x14\x42\x40\x00\xf2\x2e\x85\x9e\x6b\x19\x21\x88\x50\x88\x29\x7e\x09\x61\xcc\x91\x8d\x05\x0a\x9d\xca\xa0\xe1\x2c\xb5\x67\x68\x3d\x1e\x1f\x32\x85\x42\xa4\x2d\x9a\xe2\xad\xcd\x72\x9a\x5a\xd5\xaa\x4b\x54\x41\x8d\xd3\x54\x38\x53\xe8\x94\xeb\xf1\x83\xc3\x05\xe7\xf7\xc8\xa5\x25\xd9\xae\xa0\x91\xde\x6f\x48\x34\x1e\x36\x22\xe0\xd7\x37\x07\x7b\x3a\xb1\x9a\xab\x7d\x21\x98\x1c\xf3\xed\xc1\x96\x38\xee\x68\x76\x3e\x49\x7a\x09\x84\x30\x2b\xc5\x9e\x34\xc7\xc7\xd9\x68\x1f\xe0\x91\x91\x9d\xce\xbb\xaa\x57\x1f\x4c\x3b\xbd\x54\xbc\x81\xe1\x82\xa6\x97\x76\x83\xc9\xe1\x7a\xf4\x74\x83\x90\x23\x75\xf2\xdd\xcd\xbe\xb4\xd7\xcb\x67\x9a\x7b\xba\x6e\xc7\x43\x63\xd7\xd9\x07\xa1\x6c\xd2\x6c\x65\xd8\xdd\x66\x6a\x5b\xbc\x91\x74\xd8\x09\x0f\xc7\xcd\x42\x77\xd3\xa3\xe1\xea\x50\x5a\x35\xc1\xb0\x92\xee\x01\x5c\x8b\xe1\xb1\xa7\xd5\x1a\xf6\x87\xa4\x6f\xf9\x6e\x59\x4c\xda\x64\x66\xcf\xd6\x60\x55\x6f\x74\x7b\xbb\x87\x1d\x6f\xb3\x12\x49\x21\x86\x03\x52\xf5\xe6\x8a\xe5\x4b\xed\x35\x35\x32\x94\xb5\x3b\x39\x7b\x36\x87\xa4\x3a\xe5\xeb\x36\xdb\xc4\x6c\x6f\xa7\xb6\x3e\xef\x96\x4f\x5f\x32\x1b\x7d\xdf\xac\x5c\xc6\xe3\xa6\x6d\x9d\x07\xca\xbf\x2d\x98\xff\xa2\x35\x2b\x89\xfe\x0b\x47\x47\xe8\xf3\xa0\xc6\x5d\xde\x47\xed\x72\x19\xd7\xfa\x05\x9e\xab\x6b\xbf\x5c\x3f\xda\xf3\x45\x58\x1a\x07\x85\x74\xaf\x19\xd4\xcf\x77\x3d\x24\x02\x01\xae\x9c\xcf\x4f\x4d\xf9\xca\xf1\xb6\xea\x9f\x69\x5f\x07\x12\xef\xea\x6d\x9f\xca\xa5\xfe\xda\x77\x29\x5f\x71\x7a\x85\x93\x6c\xcb\xfb\x60\xfc\x3e\x26\x50\xf5\x3e\xf9\x39\x72\x9b\xfc\x27\x02\x8d\x9c\x46\x76\x02\xbb\xa9\x92\x95\x89\x9d\xf9\x16\x36\x46\x8a\x95\x27\xc2\x71\xd3\x9a\xe3\x49\x39\xda\x16\x2b\x6c\x4e\xa7\xa9\x7a\xe5\x98\x3b\xec\x1b\xf5\x12\x4f\x59\x8d\xc8\x49\x77\x2a\x19\x7a\xc0\x6d\xb7\x3a\xb0\xcb\x3d\x1f\x1f\xba\xe1\xa0\x57\x1f\xe0\xfa\x3e\x5f\x9e\x58\x3f\xec\xfe\x60\x20\x04\x88\x22\x82\x22\xa1\x09\x40\x01\x06\x91\x08\x30\x45\x3c\xa4\x4c\x41\x8d\xb1\x86\x42\x0b\xae\x08\xd3\x10\x63\xa4\x03\xaa\x62\x05\x39\x82\x71\x24\xb8\x8a\x4f\x4b\x6f\xe4\x71\x04\x22\x9f\x2e\xc2\x61\xcc\xd0\xfb\x04\x7a\xae\x65\x00\x22\x49\x09\x43\x04\xdc\x4f\xa0\x4f\x0f\x58\x5f\x49\xa0\xa7\xf2\xea\x62\xd7\xf8\x59\xe3\x65\x8c\x81\xee\xd6\xeb\x9b\x4a\x77\x31\xde\xad\x0f\xc3\xe9\x90\x46\xe9\x3a\x70\x9b\x75\x77\xe0\x6d\x0f\x60\x30\xaf\x16\x0f\xd3\xf9\x98\x34\xb7\x15\xb1\x50\xdc\xb4\x8e\x78\xbb\x2a\xd6\x2a\xe3\x32\xea\x51\xb0\xe8\x0c\x96\x87\xa8\x5e\x89\x82\x19\x65\xfd\x6d\xad\xbf\xb4\xe3\xda\xca\x35\xbf\x76\x9d\xe4\xd7\x68\x92\x58\xb6\xb8\x56\x9b\xbf\x04\x09\x18\xe0\xed\x37\x2e\xd1\xaf\x6f\x94\xcc\x83\xe5\xdf\x44\xb3\xf3\x97\x5e\x6b\xc0\x6b\xb5\xf5\x65\xe3\xd9\xfa\xc8\xe7\xf8\x58\x03\xde\x23\x3f\x30\x54\xfd\x0e\xf9\x77\x13\xe0\xd5\xf3\xdf\x44\x80\x3f\x44\xa0\xcf\x36\xa2\x6e\xe9\x8b\xb3\xa0\xc7\xcc\x85\x7b\xc7\xe2\x1a\xf9\xcf\x61\x7b\xdf\xa4\xb4\x7e\x34\x6c\x2f\x8c\x24\x23\xb1\x8a\xa3\x10\x63\x16\x60\x10\x23\xa8\x10\x01\x71\x1c\x47\x41\xcc\x71\xc4\x15\xa7\x42\x00\x1d\xc1\x50\x4a\xcc\xa9\x62\x28\x16\x44\x63\x4d\x25\xa2\x1c\x3c\xd1\xf0\x1c\xb6\x57\xee\xba\xd5\x82\x4f\xdb\xf5\x6c\xdb\xa5\x7e\xa5\x5b\x2a\xbb\x14\xb9\x66\x81\xd6\xcd\x3c\xf1\xdd\x66\xbb\x94\xcf\xb7\xdc\x6e\xbd\x80\x9c\x2a\xc9\xe4\x50\x3e\x97\x2f\x23\xf3\x4a\x1a\x12\x80\xdf\xbd\xdd\xe9\xa5\xf6\x4c\x43\x0a\xf0\xc5\x1f\xcb\x6c\x1a\xd5\xd6\x70\x3d\xcf\xae\xc2\x4d\xb6\xeb\x03\x1c\xb9\xf6\x72\xd5\xcf\xd3\x1e\x2c\x96\xea\x93\xf9\xea\xd0\x9a\x2d\x53\x99\xda\xbc\x70\x9a\x5a\x5f\xa3\xe1\xeb\x40\xf3\x2b\x66\xe1\xeb\xcb\x40\x4f\xc5\x7d\x91\xef\xb9\x96\xd1\x4a\xd3\xca\x1c\x59\x13\xa7\x59\x15\x24\x9a\x1c\x1a\xd4\x4d\xf7\xf6\x53\xd8\x3e\xf6\xa2\xd2\x72\x54\xaf\x37\xf9\x2e\x9e\x6f\xb0\x3c\xa8\x05\x66\xf5\x5e\xaa\xb7\x42\x87\x79\x6d\xb8\xa3\xfd\xfd\x5e\x97\x9a\xc3\xb4\xdb\xb2\x0b\x83\xb9\xb2\xdc\x69\xa4\x07\x58\x18\x5f\xf2\xaf\xbe\x14\xb6\x97\x24\xd2\x95\xd6\x80\xd9\xee\x65\xed\x47\x12\xf1\x4e\xf9\xf7\x86\xed\x3d\x90\x48\xf7\x12\xe1\x21\xf2\xaf\x0d\xdb\xfb\x4b\xfd\xcb\xcf\x88\x75\x8b\xf5\xf2\x48\x62\xfd\xa4\xf5\xf4\x1c\x3a\x51\xca\x74\xd2\x23\x36\xf5\x2b\x7e\xcb\x4b\x1f\xfb\x28\xcc\x57\x47\x61\xca\x72\xe3\x56\x58\xc9\x80\xc3\xa6\x96\xcf\x37\xb6\x99\xd4\x84\xc7\x38\x7f\x58\xc6\xf3\x82\xc5\xcc\x63\x58\x18\xbb\x55\x6b\x92\xcd\x3a\x64\x5f\xaf\x8a\x6e\xd3\x5b\x14\xc6\xbb\x52\x10\x41\x56\x8c\x77\x3f\xed\xbf\xa9\x48\x04\x42\x4b\x1d\x52\x1c\x47\x88\x89\x08\x22\x49\x34\x42\x42\x4a\xaa\x10\x8f\x09\x42\x91\x04\x5c\x60\x45\x00\x25\x9a\x90\x20\x04\x00\x89\x58\xc1\x28\x40\x10\x9c\x8e\x46\xe1\xbb\xc3\xf6\xd8\x67\x9c\x22\x12\x62\xf6\x2e\xa7\x7e\xd5\xf2\x0b\xf8\x84\x24\x0f\xd8\xbd\x72\x5f\x0d\xfa\x6f\xef\xf1\x0d\x9e\xc3\x7b\xa1\x13\xcd\x75\xe4\xb7\x0f\x4b\x46\x0e\xdb\xf4\xb2\x50\x5d\x82\xf4\xb6\x45\xb6\xfe\x61\x36\x8d\x57\xed\xfd\x7c\x9f\x5d\x0d\xfc\x62\xb6\x90\xc7\xe1\x84\x8d\x52\x87\xf9\xc0\xc8\x1c\x94\x58\x83\x42\x8a\x87\xc7\x7d\xbd\x58\x1d\x4e\x86\x85\x42\x99\x56\x97\x3b\x6e\x44\x7a\x3a\x36\x79\xe9\x61\x17\x41\x25\xdf\x8f\xff\x4f\xdd\x97\x36\x2b\x8a\x2c\x7f\xbf\x9f\x4f\x41\xfc\xdf\x74\x77\xd8\x73\x2d\xb6\x02\x66\xe2\xde\x08\x50\xdc\x77\x70\xc1\xe7\xc5\x09\x96\x42\x51\x04\x04\x5c\xef\x97\x7f\xc2\xe5\x78\x10\x45\x3d\xe8\xe9\x9e\x4b\xc4\xc4\xb4\x87\x22\x33\x2b\xab\x2a\x7f\x95\x59\x59\x55\x9f\x5c\x3d\x72\xc5\x81\x6a\x47\x72\x6b\x0b\x57\x39\xdf\xc3\xa6\xd7\xf1\x8f\xb7\xe9\x43\xfc\x23\xd8\xf4\x44\xaa\xd8\xa8\x63\xcc\x7b\x11\x46\xca\x75\x8e\xb7\xed\xdd\x13\xfc\xfb\x9c\x1a\x14\x9e\xe0\xcf\xf3\xbf\xcf\x43\xb9\x8a\x3d\xb5\xf4\xba\xd8\xb5\x85\x12\x39\x59\x28\xe1\xfa\xe6\x2f\x6b\x8b\x1d\xff\xbe\x9b\x8e\xff\x11\x7b\x0a\xb5\x41\xbf\x10\xcc\x33\x8b\xba\x9f\x85\x9b\x09\xe4\x5a\x0c\x8e\x6a\x44\x7d\x5e\x21\x99\x42\xa0\xea\x1d\xa6\x3c\xcb\xad\x37\x96\x41\xd0\x0b\xaf\x15\xcc\x95\x11\xaf\x3b\xad\x9a\x91\x5b\x2e\x08\x96\xed\x5a\x5b\x8a\x76\x37\xd6\x04\xc9\x90\x6d\xae\x4a\x03\x8f\x6e\x2f\xb6\xbf\xfa\x68\x2c\xcd\xd4\x0c\x1a\x71\x14\xcd\x18\x0c\xce\x68\xba\xc9\x52\x0c\xc1\xe1\x2a\xd4\x09\x4a\x63\x74\x83\x35\x34\xca\x34\x19\x96\x42\xba\x41\xd1\x1c\xa1\x21\x12\x18\x80\xc5\x29\xa8\x03\x9d\x80\xd4\x11\x7b\x9e\x4c\xdb\xbb\xb7\xb5\x89\xa3\x38\x92\x4a\xbc\x84\xf0\xf4\xf6\x80\x3d\x2c\x09\x3e\x22\x86\xe9\xb1\x27\x9e\xde\x7c\x81\x3d\x9f\x9d\xa3\xdf\xb8\x84\x50\xc1\x65\xab\x3e\xc9\xcc\x27\x6c\x66\xab\x68\x44\x4f\x83\x60\x9c\x99\xf7\xd7\xc3\xb0\x60\x4a\xc5\x95\x06\xa6\xcb\x6a\x18\x4a\x05\xbe\xd4\x1e\x17\x9b\x93\xb2\x61\x58\xbd\xb6\xeb\xad\xb9\x5a\xbe\xd3\x84\xdd\x51\x6b\x56\xab\xad\x0b\xcb\xb6\x57\xde\xa2\xa2\xa3\x8e\xc6\xe4\xb2\x9d\xff\x07\x60\x8f\xbd\xec\xfb\xc2\xb3\xb6\xff\x85\xfc\x53\xa5\xac\xbf\x06\x7b\xe2\xb6\x3f\xd5\x6a\xfd\x6f\x4c\x93\xe6\xf9\xdf\xe7\x6b\xbc\x3a\x65\xfc\x19\xdb\xcf\xbf\x08\x7b\xa2\xf3\x90\x14\xd8\x43\x34\xba\xd4\xa4\x9c\x9d\xbb\xd9\x56\x40\x14\x39\xbb\x9f\x09\xcb\xe6\xdc\x0e\xfa\x5a\x67\x00\xc6\x41\x91\xab\xd4\x36\xbe\xd6\x1d\xb7\x05\x50\xee\x4c\xdc\x4d\x69\xa0\xd8\xdd\x6a\x55\x37\xa5\x15\x90\x17\x76\x39\x4f\x5b\x1b\xb6\xa3\x81\xaa\x54\x27\xc7\x1e\xe1\x96\x0d\x06\xfc\xea\x0d\xb6\x00\xe1\x04\x0b\x29\x46\x23\x34\x8e\x64\x58\xa8\x41\x8d\x81\x08\x67\x09\x43\x37\x54\x80\x33\x24\x43\x33\x00\x42\x93\xd5\x55\x13\xd0\x04\x69\xe0\x9a\x4a\x6a\x14\x63\x1a\xd0\x64\x08\x60\xbc\x5f\x5f\xbb\x3f\x12\x22\xd7\x93\x85\xa2\x24\x8a\x5d\xa6\x5a\x1b\x74\xeb\xa5\xba\x34\x10\xf8\xda\xa0\x42\xc8\x54\x99\xa8\x36\x5b\x83\x3e\x21\xd1\x72\xa7\x56\xcd\x77\xca\xfc\x20\x4f\x77\xf3\x25\x5e\x69\x7e\xfb\x89\x51\x0c\x41\x51\x90\x02\x04\x7d\x17\x85\x20\x20\x21\x97\x88\x42\xef\x6f\x69\x9c\x26\x39\x88\xe3\x90\x3a\x25\x8f\xd7\x7b\xc3\x71\xa3\x3c\xae\x9a\xdd\x05\x57\x2c\x0d\xab\x54\xbb\xb6\x70\xba\x99\x32\xf0\xb6\x0c\x81\xd7\x02\xca\xef\x36\xab\xfc\xa0\x44\x8c\xb6\xfc\x09\x85\xf6\x77\x54\xdf\x88\xd4\x1d\x9e\x51\xb6\x9a\x15\x6c\x9f\x2b\x34\xb3\x4e\x4f\x2c\xd6\x8c\x59\x6e\x9b\x1b\xd7\x15\x6f\xa6\xb7\xb7\xeb\xf2\xb8\x30\x83\x0d\x61\xbb\xde\x3a\x83\x43\x64\x2a\x76\x0b\x87\x50\x58\x73\x6e\xfd\xb0\x71\x69\xa5\x70\xa5\x36\xdf\x21\xa4\x7a\x0b\x91\x95\xd6\x72\x26\x08\xa1\x30\x25\x26\xa6\x3b\x02\xc5\x82\x58\x50\xa6\xb5\x46\x61\xdb\x6e\xcc\x97\x8a\xcd\x58\x43\x2b\x9c\x35\xe9\x42\x7b\x36\xad\xda\xcb\x6c\xa3\x49\x0f\x75\xb5\x2f\xcc\x07\x7a\x69\xdc\x6c\x7b\x53\x10\x10\x03\x49\x68\xbf\xec\x1e\xf6\xe8\xc9\x4f\xeb\xde\x4c\x04\x96\xe8\x71\x12\x03\x14\x63\xea\x8f\xf9\x05\x34\x64\x6a\x22\x39\xad\xa5\xd6\x5d\x6c\xad\xb0\x4d\xb9\x82\x6e\xaa\xf9\xc3\x01\x3a\x1f\xeb\x45\x09\xf7\x7e\xef\x9f\x3b\x28\xf4\x3a\xfe\xcf\x46\xe7\x22\xb3\xe6\x7c\xa1\xaf\xc8\x52\x59\x72\xf0\xda\xb2\x33\x26\xa4\x85\x98\x63\x3c\xbc\x65\x35\xaa\x7a\x86\x0b\x25\xa6\x59\xc5\xf3\xd6\xe8\xd4\xc6\x91\x88\x4b\xee\x6a\xf6\xc2\xf1\xb9\x6d\xf9\x9e\xe0\x5f\x26\x5a\x0e\x7c\x82\x3f\x1f\xe3\x9f\xcb\xb3\x3e\x5b\xec\x2f\x41\x97\xc9\x18\xdd\xb6\x12\x12\x4a\xad\x5e\x15\xd7\xd6\x6c\xb8\xce\xb7\x44\x4b\xec\x6b\x2e\x28\xb5\x4a\x4d\xc3\x3c\xd0\x3c\xdd\xa4\x73\xfd\x24\xb1\x5b\xfc\xef\x79\x40\x69\xda\xe2\xc0\x28\x97\x70\x23\xf0\x6d\x5d\x3c\xdb\x16\xf1\xbe\xf0\x79\x5d\xfc\x57\x2f\xb6\x3a\x80\x17\x8d\xe9\x24\x4f\x86\x1b\x99\xa1\x47\x6d\xad\x3d\x6c\xb8\x24\x2c\x37\x84\x71\x47\xe8\x57\x72\xdb\x8e\x0e\xf2\xaa\x4f\x54\x10\x35\x53\xfc\xe1\x64\xd1\xe9\x56\xbc\x9c\xa7\x65\xb7\xf2\xa2\x3f\x28\xda\x23\xd5\x26\x05\x4a\x9e\x56\x87\x8d\x5a\xc3\x06\xa3\xee\xaf\xbe\x87\x1d\x32\x10\xe0\x2a\xa1\xab\x04\x4e\x68\x2c\x05\x38\x42\x65\x0c\x52\xa7\x09\x1c\x67\x08\x0d\x32\x26\xa5\x71\xa4\xc1\x10\x1a\x43\x40\x15\x40\x9d\xa6\x00\x87\x33\x06\xa1\x6a\x2c\xa9\xe3\xea\xce\xef\xc0\xf1\xa7\xa3\x6f\xf4\x3d\xec\x61\xf0\xe4\xd3\x88\xde\x5f\x1e\xa1\x8c\x22\xe9\x17\x6c\x99\x8d\xc7\x89\x2e\xac\x56\x0a\x2b\x98\xb4\x65\xb6\x54\x9b\xba\x30\x2b\x6b\x4b\xb0\xcc\xd2\xb9\x7e\x69\x6a\xad\x07\x8e\xb6\x71\xbb\x70\xde\x86\x1b\xb4\x1a\x16\xe7\xad\x52\x41\xda\x36\xd6\x75\x73\x61\xb0\x10\x29\xc5\x69\x03\x4c\xa8\x59\x50\xcf\x0d\xcc\x1a\xef\x2e\x18\xab\xda\xec\x39\xa0\xde\xdf\x6c\x6d\x6f\xa9\x74\x78\xf0\xb2\xd8\x5b\x74\x74\x7c\xd2\xff\x98\x0f\x95\x6a\x35\x62\x69\x12\xcc\xdd\x6d\xcb\xff\x42\xfe\xa9\x62\x7f\x11\xe4\x79\x22\xde\xe3\xd9\x23\xd7\x7d\x36\xde\xf3\x1b\xe3\x4d\x3c\xff\xfb\xac\xfd\x55\xe4\xa9\xa6\xd7\xc5\xae\x2d\xbc\xd5\xdd\x4a\x7f\x59\x5b\xc4\xfb\xc2\x67\xf8\x1f\x91\xa7\xb3\xa1\xab\xcd\x25\x20\x18\xae\x96\xcd\xb4\xed\x31\x5d\x0e\x7a\x34\xc1\xce\x0b\xcd\xf9\xb4\x19\x38\x41\xb1\x33\x9f\xac\xd7\xdd\x60\xab\xcb\x25\xc6\x31\x9b\xce\x4c\xf0\xf2\x46\x39\x53\xf1\xf3\xbc\x4d\x6e\x56\xd5\xda\x82\xb2\x26\xf6\x90\xcb\x17\x82\x80\x56\x35\x42\x6c\x37\x7e\xf9\x25\xec\x86\x06\x39\xa8\x32\x1c\xa3\x31\x90\xc3\x19\xa8\x6b\x2a\x32\x48\x95\x06\x88\x52\xa1\xca\x42\x06\xc7\x71\x0e\x12\xb8\x09\x69\x95\x34\x39\x9a\x52\x49\x4d\x37\x71\x00\x74\x06\x99\x40\x7f\xdf\x73\xb4\xcf\x54\x28\xd2\x84\xdc\x87\x6d\x5e\x80\x72\xb1\x51\x6f\xca\x35\x92\x50\xa8\x3a\xd9\x6d\xb7\x6b\x8d\x46\xa3\xd4\x12\x4b\x0a\x5f\x56\x3a\x2d\x28\x15\x0a\x70\xc8\xf7\x3a\x05\x7a\xd8\x56\xbe\xfd\xc4\x48\x16\xd2\x14\x03\x68\x08\xe9\x9f\x18\xb1\xc3\x20\x22\x09\x66\x58\xc0\xd2\xc9\xfe\xcf\xfb\x5b\x8a\xe0\x28\x0e\x32\x3b\x92\x27\x0b\x4c\x1a\x72\x08\x79\x3e\x33\x1b\xfa\x25\x79\xb0\xec\x37\xeb\xa4\x24\x16\x42\x15\x30\x9b\xd2\x4a\x28\x96\x97\x5c\xd9\x33\x87\x42\xbf\xb2\x3f\x18\xf2\x70\x3f\xe4\x1e\x2c\xe2\xa8\x73\x71\xc1\xf8\x27\x2c\x62\x84\x4c\x2c\x6f\xaf\xfd\xd9\x5e\x1c\xe9\xfb\xe6\x60\x1c\xa1\x24\x10\xed\x9e\xb5\x3f\x88\x53\xe4\xd7\x1b\x9b\x1e\x2d\x73\xb9\x7c\x8e\xb1\x81\x37\xe7\xb4\xac\x10\x1a\xa4\xde\xec\x76\x75\x85\xeb\x2c\x01\x5f\x5b\xf7\x26\x0b\x9b\x12\x7b\x52\x0d\xef\x6d\x46\x3e\x0e\x98\xe2\x24\xef\xe2\x78\x46\x09\x56\xc6\xcc\xce\x2d\xfa\x26\x53\x2d\x87\x5d\xa0\x8f\x6d\x77\xe4\x39\x01\x75\xbe\x1f\xaa\x1e\x49\x19\xf8\xf8\xe7\x2d\x9f\x31\x19\xe5\x22\xa4\xf2\x06\xde\x24\x5d\x3e\x0f\x87\xb3\xc0\x68\x20\x4e\xa1\xb6\x46\xb9\xdd\xc7\x7d\x79\x59\x36\x79\x51\xb1\xb2\xc0\xb2\xb9\x69\x41\xb1\xf7\xc9\xb7\x1f\x57\x0e\x26\x6d\x06\x8d\xb4\xd7\x95\x47\x78\x31\xff\xcf\xfa\x57\x39\xfe\x3c\x1f\x30\xb2\xbf\xeb\xd3\x96\x6d\x68\x07\xe3\x67\x2d\xeb\x33\x96\xdd\x9c\x54\xed\x27\xf8\xc7\x91\x85\x6f\x90\x5d\x06\x8d\xf8\x96\x37\x53\xd7\x00\x67\xf0\xc9\xa4\x01\xc6\x82\xd6\x0f\x9b\xec\x98\xe5\x3b\x56\x2d\x2b\x55\x07\xa7\x3e\x1f\x39\x6c\x35\x97\x3e\xfb\xe3\x19\xfe\xa7\x8c\xf0\x74\xfc\xf7\x2f\x2e\xc6\xc3\x67\x67\x5d\x03\x6a\xe3\xe9\xb1\x4a\x25\xd4\xf5\xda\x73\x31\x1e\xd2\xcc\xfa\x9e\xe0\xff\xb4\x3d\xf8\xd8\xed\x91\x6a\x3c\x3e\x6d\x0f\xa4\x1c\x3f\x4e\xc9\xff\xda\x4c\x2b\xba\xdf\x33\xc5\x78\x38\xce\xfa\xd2\x67\xd8\xbc\x70\x3c\x7e\x86\xff\xfb\x06\x71\xdd\x43\x4a\x6d\x35\x1a\xad\x16\xb4\x51\x55\x97\xfd\xec\x4a\x1b\x18\x64\xde\x2e\x94\x8a\xad\xae\xc6\xf1\x39\xb6\xa7\x30\x1e\x12\x0a\x5d\x8b\xeb\xe9\x6e\x95\x33\x9a\x6b\x77\x05\x1b\x86\x39\xab\xd5\x4b\x43\xaf\xed\xdb\x4e\x66\x63\xd5\x7a\x8d\x52\x79\xa8\x96\xab\x43\xa6\xf9\xec\x1e\x3d\xe2\xb3\x3e\x3e\xd4\x09\x56\x07\xba\x6e\xd0\x2a\x81\x28\x06\x10\x50\x55\x75\xd5\x54\x09\xa4\xef\x7c\x7d\x80\x9b\x88\x36\x10\x49\x71\xc8\x24\x19\xa8\x03\x93\x55\x4d\x8d\xe5\x48\x9d\xd1\x34\x9a\x36\x8e\x27\x8b\x3c\xe7\xe2\x53\xf7\x5c\x7c\x96\xe3\x92\xef\x9d\x3b\xbd\x3d\xce\xd7\x38\x06\xbe\x60\x91\x33\x3e\x06\x2e\x86\x4a\x0a\x28\x4e\x4a\xb0\xe9\xe4\x61\xbd\xd7\x1f\x89\xbc\xb4\x08\xcc\xb1\x0f\x2b\x46\x81\xab\x92\x1d\x0b\x11\x83\x5c\xa7\x52\xb5\xb3\x0d\xb7\xba\xa9\xe8\xbe\x81\x4f\x8b\x01\xb9\x19\x79\x1e\x4d\xaf\x17\x2c\x50\xec\xc2\x6a\xd4\xe8\x89\xfe\x30\xab\x8b\x7c\x49\x69\xce\x01\xcc\xad\x1a\xa6\x23\x12\x41\xee\x65\x4e\x7e\xfa\x45\xc6\xc0\x57\xab\x41\xc4\xdc\x26\x44\x16\xef\x98\xbb\xd7\xf1\x4f\x05\x37\x11\x27\xff\x89\xe9\xcf\x26\x74\xe7\xeb\x67\xa7\x3f\xbf\x71\xfa\xc5\xf3\xbf\xcf\xdc\x5f\x75\xf2\xcb\xe9\x75\xb1\x6b\x8b\x6d\x24\xca\x51\xff\xa4\x2e\x9e\x6d\x8b\x78\x5f\xf8\x0c\xff\x23\xf4\x88\xed\xcc\xa4\xd0\x73\x05\x5e\xf4\xfd\x12\xa5\x66\xac\x41\xc7\x94\x42\xa0\x38\xa1\xbd\x9a\x4a\x92\x67\x6e\xd5\x5c\x60\x0d\xaa\xa4\x31\x14\xfc\x06\xeb\x56\x55\x84\x74\x6d\xd9\x28\x56\x3a\x7a\x39\xdf\xeb\x54\x09\x93\x14\x78\x81\xc8\xcf\xc3\xe6\x28\xc8\x0f\xe8\x75\xc3\xff\xd5\xe7\xde\x1b\x06\x43\x21\x84\x08\x46\xa5\x39\x96\x22\x35\x82\x55\x01\xad\x1a\x80\x55\x35\x13\xd2\x48\x55\x09\x12\xd7\x18\x03\x69\x88\x32\x00\x4d\xd3\x40\x07\x2a\xa3\x52\xc4\xfe\xa8\x46\x8e\xe0\x8e\x07\x2a\xee\x7d\x7c\x0a\xf6\x3a\x55\x21\x57\x2b\x13\x03\x98\x1f\xd4\x06\x0c\x5f\x16\x7b\x9d\x42\xad\x44\x76\x79\x66\x20\x88\x64\xa3\xd8\x68\xc1\x26\x43\x95\xda\x74\x6d\x50\xaa\x17\xe5\x1e\x51\x11\x76\x98\x01\x00\xa4\x18\x06\x07\x0c\x79\x0f\x84\x38\x8e\xb9\xb1\x37\x6f\xf7\x96\xde\x11\xa4\x48\x9a\x63\x28\x82\x82\xa7\x2c\xcf\xbc\x33\x5f\x77\x45\x09\xa8\x4b\xca\xc0\xc9\x8c\x20\x54\xd7\xd5\x20\x03\xf9\xac\x5e\x69\x84\x75\x3c\xeb\x98\x14\x2a\xf5\xc8\xe6\x0a\x40\xfe\x04\x42\x7b\xb3\x15\x01\x9d\x8f\xfe\x8e\xe2\xeb\x43\x4f\xf8\xe8\x7c\xc5\xea\x47\xa6\x93\x82\xb1\x0d\x1a\xcd\xbd\x8f\x2e\x4c\xa6\xb4\x58\x98\xf7\xd8\xa2\x55\xe3\xd6\x5d\x48\x34\xbb\xb9\x2a\x92\xf4\xc1\xba\x58\x97\xeb\xf3\x8a\x9b\x67\xfc\x8d\x55\x34\xe9\x49\xad\x35\xac\x74\x24\x6f\xac\xf5\x73\xe4\x70\xa3\x97\xc4\x8c\x97\x5f\x2c\xb2\x50\xac\x4a\x73\xbd\xd1\xf5\x2d\x9a\x1f\x6c\xdb\xb3\x7a\xa6\xa8\x3c\x12\x79\x7e\xcc\x27\x8f\x14\x6a\x22\xbf\xd0\xee\xd4\x3a\xf3\xec\x98\x1c\x98\x94\x28\xfa\xe2\x7c\xcb\xb8\x79\x6e\x35\x25\xc0\x76\x90\x31\xb2\x63\xca\x18\xe8\x4c\x5e\x3e\x1d\x50\x69\xe9\x1f\x3a\x4e\x78\xee\x80\xd2\xeb\xf8\x3f\xbb\x47\x2f\x92\xb9\xf3\x69\x43\xe4\xb7\x0b\xb5\x67\x0d\xe1\x33\x86\xd8\x27\x9a\xf6\x13\xfc\xe3\x40\xc0\xd3\x30\xe8\x09\x62\x58\xf4\x33\x25\xc3\xc8\x8e\xda\x52\x20\xf9\xad\xc5\xa8\x45\xe6\x64\x4d\x6e\x98\x34\x99\x29\x8d\xf1\x53\x1f\xdf\x83\x52\x65\x3f\x1a\x84\xf4\x6b\xbe\xcf\xf0\x97\x75\xb0\x4c\xc9\xff\x2a\x28\x96\x9e\xd3\xc5\x81\x91\x90\x7e\xcd\xf5\xc9\xb6\x38\xac\xb9\x7e\x9e\xff\xfb\x8e\x07\xba\xd9\x11\x54\xdb\x14\x5c\x2b\xab\xf7\x9a\xe1\xc4\xe6\x2d\x67\xea\x14\xd8\xce\x44\xdc\x56\x2d\x95\xcf\x40\xd6\x1d\x3b\x19\x65\xb3\x25\xa4\x6e\x77\xae\xf4\xf1\x51\x48\xe8\x8e\xb0\x6e\xcd\xdb\x8c\xbf\xcc\x8c\x73\xd3\xb9\x93\xef\x55\xa9\x45\xbb\xc0\x82\xca\xa4\x35\x9e\x9d\x22\xdf\xd6\xce\xd5\xf9\x86\xef\x2f\x56\xfb\x3a\x4c\x24\x68\x1a\x47\x0c\x54\x49\x1d\x51\x2c\x8b\x6b\x8c\xa6\x33\xa4\x69\x98\x06\xcb\x19\x90\x01\x06\x8d\xef\xaf\x86\xa1\x10\x0d\x71\x1a\x12\x34\xa1\xd1\x38\xc3\x30\x80\x20\x09\x40\x18\x88\x39\x60\x22\xf1\x2a\x4c\xbc\xed\x98\x51\xff\x02\xbb\x27\x61\x87\xde\xf1\x2d\xf5\x81\x89\x90\xfe\x70\xcc\xd2\x63\x62\x3c\xce\x5d\x50\x8b\xbd\x40\x2b\x9e\x8e\xfb\xb9\xd8\xbf\x9e\x2e\x0e\x9e\x53\xec\xe8\x11\x4a\x27\xfb\x2d\xf0\x12\x91\xa9\xab\x2d\x9e\xe1\xf8\x49\x1e\x08\xcc\x7c\x62\x83\xb9\xb8\x05\x0d\x98\x9b\xe6\x67\xae\x44\x4d\x47\xce\x60\x32\x34\xb5\xa5\xa1\x73\xe5\xe9\xbc\x31\x03\x52\x66\x59\x15\x1a\xa3\x1e\x0b\x3c\xc9\xb4\xd6\x0a\x4e\x31\xb5\xcc\x64\x29\x65\x47\xaa\xe3\x2e\xe7\x5a\xcd\xda\x75\xb3\x7f\x02\x36\x76\xc9\x46\x8d\xfd\xd0\x75\xba\xf8\xd4\xeb\xf8\xa7\x3a\x0d\x25\x82\x8d\xbf\x11\x9b\x9e\xc6\xc6\x40\x1f\x64\x7f\x27\x36\xc6\xb0\x29\xd5\xd5\xae\xcf\xf0\x97\x08\xbf\x97\x92\xff\x3d\x87\xf1\x57\x62\xd3\x4b\x74\x71\x8a\x55\xa6\xc6\xc6\xaf\x32\x5a\x7b\x6c\x0c\xd1\x3a\xdc\xfd\x7f\x8c\x6c\xdb\xfd\x52\x7c\x24\x35\x12\x22\xdd\xd4\x74\x9d\x50\x0d\x0d\xe8\xa6\x69\x02\x56\x45\x2c\xc4\x39\xce\x84\x14\xc2\x09\x8e\xa5\x4c\xc0\x52\x9a\x06\x48\x0d\x71\x9a\x46\x50\x1c\xc4\x71\xc3\x64\x09\x92\x20\xb4\x03\x3e\x92\xaf\xc2\xc7\xdb\xb9\x49\x7b\x04\x24\xf0\x84\x9d\x81\x91\xb7\x07\x7c\xa4\x01\xfc\x58\x17\x4e\x8f\x8f\x91\x20\x5b\x5d\xe0\xdb\xe2\x83\xff\xf1\xbf\xc0\xa7\xcc\xe7\xb8\x71\x3d\xac\x2b\x43\x38\xd6\xd6\xb8\xc5\x1b\x03\x67\xd4\xd1\x73\x4a\x7b\x66\xb2\x68\x41\x6d\x75\x81\x93\x6a\x25\x82\xe3\xd8\xb0\xa7\xe8\x2a\x6c\x2b\xd6\x88\xce\x07\xa3\x0d\xe1\xe6\xea\x79\xbc\xc2\x4c\xc7\xe5\x1a\x37\xd9\x66\x7b\xfd\x89\xde\x1a\x2f\xe5\xde\x32\xc7\x3e\x72\x0e\xe6\xd7\xe3\x66\x38\xc7\x23\x3e\x5d\x2a\xdc\x7a\x21\xff\x54\x81\xd6\x17\xe1\xe6\x93\xb8\xf5\x34\x6e\x86\xb9\xf1\xf0\x77\xe2\x66\x0c\xb7\x9e\xad\xff\xe7\xf9\xb7\xc7\x4c\x4a\xfe\x5f\x81\x9b\x69\x71\xeb\x25\xba\x38\x5d\x30\x9a\x1a\x37\x57\x4b\x45\xae\xc9\xc5\x22\x72\xfb\xac\xa1\x8c\x4a\x3d\x9a\x12\x07\xfc\x4c\xac\x38\xd9\x92\xbf\xa8\x93\xbc\xd9\xb5\xd6\xdc\xd2\x34\x6b\xbd\x7e\xa9\xb8\x98\x16\xcb\x6e\xb3\xcd\x94\xeb\xe1\x9c\x9f\xf0\x9c\x84\xe8\xb2\x94\xcb\x2a\x6c\x16\xef\xb9\x64\x9e\xd2\x00\xae\xad\x96\xa7\x35\xbe\xb1\x1a\x8c\xf7\x1a\x7f\xd8\x4a\x8b\xff\xfe\x52\x78\x45\x38\xc5\xb2\xb4\xae\x41\xa8\x9a\xb4\xc9\x98\x34\xe2\x38\x5c\x03\x38\x85\x90\x4e\x31\xb4\x0e\x71\x5d\x67\x49\x9c\xe0\x08\xdd\xa4\x69\x02\xea\x86\x01\x74\x43\xc5\x29\x9a\x04\x80\x25\x8f\xee\x27\xf5\x2a\x78\xbd\xbd\xf1\x7e\x0f\xa0\x14\x9e\xb0\xf9\x31\xf2\xf6\x08\xaf\x14\xf3\x91\xfc\x9b\x1e\x5e\xa3\x18\x99\xe3\x47\xe5\x07\xff\x8b\x7f\xca\x7f\x45\xc8\xb6\x69\xce\xb9\x56\x9b\x15\x8b\xba\x37\xe9\xf4\x45\x75\x5e\x5c\x2f\xc7\xc2\x44\xea\x2d\xa6\xb0\x4a\xf3\x84\x1f\x8e\x6b\x4a\xc9\x99\xf1\x83\x59\x1b\xaf\x4c\x2a\x79\x52\x34\x8c\x89\x25\x4a\xa4\xd6\x1a\x76\x0b\x34\x32\x8b\xed\x65\x67\xe2\x8a\xd5\x91\x25\x10\x46\x97\x34\x89\xd5\x23\xdb\x54\xbe\x1e\x5e\xa7\x65\x14\x71\x0b\xd3\xad\x23\xbe\x8e\x7f\xaa\x75\xc4\x17\xc1\xeb\x93\xf0\xf6\x3c\xbc\x3e\xb7\x76\xf6\x3c\xbc\x9e\xc3\x5b\xaa\x75\xd4\x67\xf8\x77\xe6\xca\x38\x25\xff\xaf\x80\xd7\xb4\xf0\xf6\x12\x5d\xc4\xc2\xe7\x9f\xe1\x7f\x84\x57\xd9\x81\x4b\x19\xb4\x04\xc1\xa9\x2a\xa0\x37\x2e\xce\xc7\x81\x46\xb5\x15\x60\x6b\x5e\xd3\x5a\xb4\x1b\x73\x46\x91\x08\x81\xa6\x47\x05\x7a\xda\x90\x94\x4d\x9b\x5b\x97\x06\x0a\x35\x16\x43\x62\x4b\xf4\x04\x34\x70\xd6\xd3\x1a\x50\xa0\x90\x73\xcb\x23\xc3\xe9\x35\x48\x2e\x38\x6d\x93\xf1\x51\xb8\xf0\x9d\xbd\xce\x1f\xb6\xd3\xe5\xaf\x05\x58\x60\x6a\x9c\x4e\x20\x02\x70\x14\x24\x08\x42\x23\x48\x84\x1b\xb8\x01\x21\x30\x10\x67\x30\x14\xcd\x40\x9d\xc2\x75\xd3\xe0\xb4\x9d\x47\xcb\x19\x34\xa4\x55\x80\x93\x3a\x8e\x4c\x96\xd3\xd5\xe3\x89\x00\xcf\xa5\xdb\xdc\x5e\xe9\xa4\xfe\x05\x70\x1c\xb2\x09\xd7\xa5\x46\xde\x1e\x71\x9a\xc6\xe1\x0b\xae\x02\x8a\x9b\xf4\x8b\xc8\x63\x8a\x55\xb6\xa4\x33\x05\xd8\xb0\x5c\xd8\xb8\x23\xae\x89\x72\x73\x4b\x15\x1a\xe6\xba\x60\xf0\xb6\x83\x1a\x8a\x6c\x4e\xdc\x46\xb7\x5e\xb5\x60\xa1\x92\x53\x68\x61\x8e\x66\x4e\x5e\x58\x17\xdd\x35\x39\xa9\x4a\xd9\xf5\x9a\xda\x7a\x6b\x5e\x76\xc5\x82\x47\x2a\x44\x3d\xd3\xe8\x54\xca\x5d\x6a\x94\x2d\x81\xca\xab\xd2\x6d\x84\xf4\x7b\x5a\x16\x59\xb0\x22\xf0\x8f\xcf\xd3\x45\x4f\x5f\xc7\x3f\x15\x4c\x47\xd2\x6d\x9e\x58\xd9\x64\xb2\x72\x5e\x7b\x16\x26\x7f\xe3\xca\x2a\xcf\xff\xbe\xd5\xbc\xab\x30\x25\xa6\xd7\xc5\xae\x2d\x74\xea\xe3\xfb\x54\x91\xe4\x17\xf6\x85\xcf\x47\x92\xff\x9b\xad\x49\x82\x3e\x2f\xb7\x64\x67\x34\x77\x67\x23\x79\xc0\x76\x06\xed\xca\x90\x9c\xf4\x45\x92\x82\xf9\x5e\x3e\xe7\x2e\xc6\x52\x7b\xd6\x6c\xab\x8e\xe7\xad\x56\x7a\x67\x5e\x37\xa8\xcd\x74\xc9\xea\xa8\x0e\xf5\xb6\x08\x05\x41\x35\x88\xc6\xa4\x35\xe9\x4a\x52\xa1\x59\x6e\xad\xb9\x5f\x7e\x05\x2a\x07\x58\x1a\xe1\xa4\xa9\x21\xce\x64\x29\x04\x18\x44\x12\x40\x05\x06\x45\xd1\x34\x09\x0d\x84\xab\xa6\x4e\xe8\xa6\xc1\xea\x0c\xa2\x70\x16\x42\x96\x61\x01\x83\x0c\x83\xd0\x28\x76\x9f\x60\xf9\x7e\x03\x6a\x7e\x50\xe0\x8b\x95\x9c\x94\x2b\x53\xb9\x2a\xa1\x94\xaa\x50\xe9\xd4\x78\x28\x57\xc5\x41\xa1\x33\x60\x84\x7a\xb1\x57\x6f\x37\x85\x7a\xad\x2c\x76\x2b\x9d\x0a\xad\xb4\x1b\xb5\x7a\x59\xd8\x5f\xfb\x8d\x33\x1c\x0b\x39\x9c\xbd\x7d\x17\x2a\xf5\x2f\x40\xe0\x1c\x4c\x06\xa1\xf7\xb7\x04\xcd\x40\x8e\x05\x0c\xcb\x9c\x7c\xbb\x26\xdd\x2e\x4a\xd5\xf6\x54\x17\xfd\x7e\x7e\xce\x59\xd5\x15\x9a\xb9\xf6\x66\xbd\x64\x6b\xf9\xde\x50\x58\xf5\x6b\x6d\xc9\x52\x3c\xc6\xca\xf7\xf8\x13\x08\x5d\xcd\x89\x8f\x80\x50\xf7\x5a\x47\x89\x2f\x35\x26\x18\xdc\xd8\x63\x39\x8b\x72\xa3\xbb\xff\x9c\x6a\x75\x78\x04\x90\x93\x05\xf4\xb0\x44\xd8\x28\x87\xe4\x66\xb0\xd6\x64\xa0\x77\x17\xe4\x6a\xd4\xb5\xfa\x5d\x7d\x91\x9f\x52\x1b\x95\x2d\x66\x47\x65\x0e\x8c\xed\x1e\xf4\xb6\x4d\x65\xc3\x0b\x70\x18\xd2\x66\x83\xf1\x3a\x7e\xab\x53\xcb\x86\xb2\xed\x4c\x46\x5d\x7e\xa2\x0a\xcb\x55\x63\xdd\xd5\xf7\xf4\x0b\x33\xa3\xd8\x81\x95\xe1\x62\x5a\xad\x74\x73\x64\xcf\x27\x14\xb1\x92\x25\xa8\x22\x19\xa2\x60\x2e\x2f\x29\xbd\x47\x77\x75\xde\xdd\x76\xc6\x12\x91\x59\x81\x96\xd2\xeb\xcd\x11\xd3\x96\x67\xcd\x7a\x43\x2a\x0e\xb2\x39\xb2\xb6\x6e\xe1\xa1\xb4\xf4\x06\x46\x37\xdb\x1c\x2b\x41\x33\xbf\x7a\x68\xa9\x32\xba\xa1\x32\x19\xec\x22\x8e\x2c\x63\xf3\xc3\xb2\x97\xeb\xac\xa4\x50\x69\xfa\x44\xd9\x17\xa0\x6a\x0d\x6a\xc5\xec\x2a\x68\xf4\xa6\x25\x41\x09\x85\x6a\xe5\xa4\xbb\x68\x1a\xcd\xc7\xd6\x84\xcb\x41\x2c\xee\xe6\x74\x1f\x6d\xd5\x1a\xb6\x9c\xee\xa6\x36\xcc\x34\x95\xca\x64\xec\xd0\xa5\xe9\x94\x22\xbb\x8b\x3e\xf4\x9b\x0b\x34\x1b\xb6\x0a\x6d\xdb\x68\x3a\x6c\x5e\xef\x95\xae\xd2\xdb\xff\x8e\x1c\x4e\xf6\xc9\xbe\xc6\xdb\xed\x1a\xe5\x7c\x74\x18\xe1\xe3\x9f\xd1\x47\xd8\xcf\x45\x3f\xaa\x46\xc8\x34\x5e\xb7\x08\x73\x32\xcb\x29\xd4\x30\xd3\xa1\x2b\xcd\x06\x5e\xb3\x17\xf3\xad\xef\x78\x33\x79\xdd\xad\x0c\x64\x2f\xcb\x93\x85\x4e\xf2\xc5\x0b\x07\x7a\xab\xff\x59\xf9\x23\x07\x24\xe5\x17\x5d\x61\x6a\x4d\x2b\x25\xa1\x8a\x8f\xe0\x52\xb1\x82\x92\x37\xaf\xe8\x81\x96\xcd\xad\xf0\x7e\x5b\x2f\x58\x40\x74\x67\x55\x44\x8d\xf0\x3d\xff\x88\x9f\xf2\x21\xd4\xe5\xd2\x76\x2c\x4e\xc3\x4d\x33\x86\x5c\x0e\x1d\x8a\x1e\xcd\x9a\x45\x73\x8a\x24\x79\x62\x48\xb4\x36\x0f\x20\x0d\x87\x53\xb6\x97\xeb\x01\x68\xbe\x8f\xb5\x84\x18\xc8\x07\x80\x16\x9e\x93\xff\xe8\xe7\xf1\x27\x7a\x57\x0e\x6e\x7d\x99\xfc\xa7\xdf\xff\x4b\xe3\x73\x0f\xd4\x5f\x62\x50\x47\xff\xfe\xf7\xcf\xaf\xb2\xa4\xbf\x72\x06\x80\x38\x03\x57\x49\x00\x80\x8a\x54\x12\x32\x14\x89\x53\x84\x49\x20\x03\xe1\x00\x1a\xa4\xae\x91\x8c\x4e\x1a\x0c\x62\x59\x1a\xb0\x88\x34\x09\x5c\xa3\x38\x48\x32\x40\xa3\x59\x48\xb2\x34\x7b\x3c\x8c\xe1\x55\x33\x80\xbb\x8b\xa7\xc9\x77\x61\x7c\xbc\x24\x70\x8a\xa1\x58\x0a\xd0\x0c\x7c\x1e\xff\x6f\x6c\x0f\x7d\x08\xff\x13\xd2\x65\x62\x8f\xf4\x81\xff\xd2\x16\xf0\xe1\x10\x35\xb6\x03\x69\x30\x9d\xb4\xa6\xd5\x8a\xd9\x14\x59\xb5\x2b\xf3\x8b\x56\x07\x7a\xeb\x7a\x5d\x2b\x90\x24\xb3\x5a\x8b\xe4\x6a\xdb\x94\xf3\x6a\x4f\xcf\xb7\x89\x06\xdd\x22\x45\xae\x5e\xd5\x33\xa6\xa6\x15\xc6\x43\xae\x9a\x01\x4c\xa6\x02\x56\xf5\xa2\x1d\x76\x84\xc7\xae\xc2\x78\x0c\x9f\x23\x9f\xa6\x19\xff\x78\x8c\xe9\xe5\x73\xc7\x19\x7d\x1d\xff\x74\x47\x0b\x7d\x89\xfd\x4e\x95\x66\xfa\x9b\xf8\xdf\x73\x06\xd3\xc8\xd2\x8e\x28\x38\xe1\xf9\x52\x5d\x34\x6f\xe5\xb6\xdd\xd5\xc5\x7f\xbf\x6a\xd0\xfe\x4a\x28\xe0\x38\x5a\xe3\x08\xc8\x99\x9c\xc9\xe9\x94\x8e\x23\x55\x47\x0c\x4d\x03\x1c\x67\x59\x06\x42\x03\x22\x56\x45\x14\xd0\x69\x0a\x27\x71\x02\xb0\x38\xae\xd2\x80\x22\x19\xc8\x92\xba\xc6\xec\xaf\xe6\xa3\x8f\x79\xa6\xaf\x80\x82\xbb\x0b\x7d\x24\xa4\xb9\xe4\x3c\xd3\xf7\xb7\x47\x30\xa0\xe0\x2b\x9c\xc1\x1b\x37\xf3\xdd\x03\x83\x7b\x1d\xeb\x89\x09\x71\x04\x3c\xf2\xde\xb4\x5e\xd7\x99\xe9\x74\xaa\x4c\xf2\x6e\x6b\x65\x76\xed\xa6\xc8\x85\x35\x65\xd9\x2f\x95\xb3\xb3\x8c\x20\xa0\xec\x28\x57\x6d\xe0\x7a\x6f\x29\x16\xf0\xae\xd0\x43\xb9\xdc\xa2\x28\xc8\x93\x85\xbf\xa1\xe4\xb9\xbb\xf6\xec\xaa\x4d\x35\x86\xa5\x8a\x24\xd3\xd9\xa6\xef\x53\x83\x07\xef\x51\xfa\xd5\xe0\x91\x6e\x8f\xc4\xeb\xf8\x3f\x7b\x2b\xdf\x0b\x8d\x77\xaa\xe8\xd9\xab\xf9\xdf\xb8\x35\xe2\x9f\xe8\x3c\xa5\x35\xf8\xaf\xd2\xdf\x31\x07\xe6\xd3\xfc\x8f\x80\xf3\x55\x03\xfd\x97\x9e\xe8\xc3\xb0\x86\xae\x72\x04\xa4\x68\x9a\x66\x38\x8d\x52\x29\x12\x00\xce\x34\x11\x49\xab\x80\x20\x38\x15\x1a\x2a\xa5\x21\x83\x24\x0c\x52\xe7\x38\xce\x60\x54\x00\x55\x83\x80\x10\xd0\xea\x7e\x67\x1d\x7d\x4c\xdc\x7c\x05\xe0\xdc\x3e\xd0\x74\x0f\x29\x1c\x4c\x4e\xdc\x7c\x7f\x7b\x04\x1c\x96\xf9\x58\x02\x4b\x0f\x38\x37\x96\xc0\x1e\x02\x9c\x88\xd1\x89\x44\x7c\x3e\x8c\x72\xfc\x11\x4e\x9d\x54\xcc\x8f\xec\x4e\x67\x33\x0b\x6b\x93\x55\xa6\x3c\x9b\x15\x57\xb2\x25\xc8\x55\x91\x19\x30\x19\x22\xb7\x59\xd9\xa5\x15\x3b\x47\x46\x26\xa4\x09\x20\x69\xfc\x68\xa4\xcf\x35\x77\x43\x57\x07\x15\x55\x6c\xd1\x78\x76\xd5\x91\xea\xeb\x70\xd8\x1d\xe5\x9b\x05\x53\xcd\x3b\x5c\xde\x04\x94\xc8\xff\x03\x81\x24\x17\xe3\x7f\x7c\xc4\x73\x1d\xbe\x24\x4a\x18\x69\xb3\x34\x51\xb6\x30\x12\x91\xbe\xbe\x39\x4c\x38\xe7\xf7\xea\x28\xe1\xff\xa4\xfc\xff\x4b\x51\xb6\x2f\x00\xba\xb4\x40\xf3\x15\xfa\xfb\x0c\xff\x23\xd0\x51\x95\x6e\x57\xf7\x7c\x89\x62\x5b\x56\xc5\x1b\x07\x22\x35\xea\x6e\xc6\x4d\x3c\x93\x0d\x47\x41\x50\xe9\xb0\xad\xaa\xe3\x98\x3e\x32\x42\x71\xb6\x2a\x97\x4b\xd5\x19\xac\x2f\x24\x7b\xd3\x1f\xe7\x33\x86\xc9\x8a\xdd\x49\x5d\xeb\xf7\xca\xfc\x76\x3c\x20\x46\x74\xb6\x4d\x72\x4d\x81\xff\xc5\x40\x07\x21\x22\x18\x53\x23\x58\x96\x01\xba\x46\x13\x34\x44\x2a\x47\x30\x90\xd2\x74\x8d\x20\x08\xd5\xd0\x34\x55\xa5\x4d\xa4\x13\x06\xcb\xa9\x90\x50\x39\x55\x65\x75\x4e\x67\x11\x81\x10\x87\xb8\xe3\x71\x28\xcf\x65\x78\x10\xf7\xe0\x8d\x26\xb8\x1b\xfe\xd4\xee\x2d\x75\xc2\x4b\x86\x24\xd8\x17\x1c\xa8\x72\xc3\x9f\x3a\x3c\x29\x4c\x7b\x42\x86\x47\x8e\xef\x7a\xcd\xcc\x78\x6d\x8d\xd4\xac\x32\xea\x04\x3d\xd2\x2f\x78\x42\x65\x63\x8c\x9a\x1b\x07\xc8\xad\xf2\xac\x92\x53\xdb\xb9\xba\x35\x9d\x5a\xc5\x4c\xd0\x18\xf8\x6d\x21\x50\x06\x93\x8a\x6f\x37\xad\xe2\xa4\x18\x74\x49\x7f\x4a\x2d\x96\x45\x9b\xa5\x79\xdf\x52\xf2\x5c\xab\xa1\x94\x5e\x96\xe1\x11\x29\xf4\xc9\x0c\x8b\x75\x17\x1f\x69\xcd\x1b\x3a\x3c\x3c\x8f\x24\x22\xbe\x84\x7f\x3a\xbf\xe8\x23\xc3\x23\x7d\x56\x81\x5f\x90\xfb\x42\xf0\x6c\x56\xc1\x6f\xcc\x6a\xe0\xf9\xdf\x17\x48\xbb\x1a\xd4\xcb\xa7\xd6\xc5\xbe\x2d\x16\xf7\xcf\xd9\xf9\xaa\xb6\xb8\xe8\x0b\x9f\x0f\x70\xfe\x77\x54\xa8\xca\x4b\x57\x57\xdc\xe2\x92\x28\x8b\x5a\xc1\x80\x6b\xb5\x2d\xe9\x8e\x92\x0f\x3c\x4e\xdc\x6e\x2a\x56\x7b\x36\xe5\x27\x65\xaf\x52\x1e\x2f\xfd\x7c\x0f\x02\x5e\x2b\x16\xa8\x8d\x4a\xcb\xee\xd8\x5d\xfb\x85\x06\xa4\x9b\x35\x7f\xed\x99\xcd\x76\x95\x9a\xf1\x59\x79\xdb\x17\x7e\xf1\xfa\x0e\x05\x69\xc6\x64\x54\x8d\x30\x0d\x96\x50\x11\x01\x48\x13\x50\x06\x01\x38\x04\x55\x03\xe9\x00\x41\x4d\xa7\x4c\xc0\xb1\xa4\x46\x99\x3a\x69\xaa\x90\xe1\x58\x02\x20\x83\x62\x10\xc1\x19\xcc\x31\x35\xf0\x39\xe8\xc1\xef\x41\x0f\xa4\x49\x36\x79\x59\xe7\xfd\x2d\x4e\xb0\x2c\xc5\x01\x9a\x63\x5f\x70\x59\x9e\x70\xde\xfc\xc2\x01\x36\x0a\x54\x0d\x2c\x6f\x74\x8f\x1c\x6c\x30\x6e\x45\xaf\x58\xdd\xad\xdc\xef\xe4\x6b\x1c\x2b\x4c\x48\xb3\xe7\x57\xba\x02\xce\xad\x0a\xcb\xdc\x56\x2c\x8d\x59\xc7\xc9\x96\x0f\x16\xd1\x6e\xd7\xe8\xe8\xf7\xbd\xf7\x2d\xe5\x02\xcf\xe6\x36\x93\xad\x38\x18\xf4\xe4\xfa\xca\x19\xca\xbc\x56\x32\x2b\x68\x4e\x94\x72\x85\x2d\xdf\x9f\x76\x39\xd6\x08\x88\xe1\xa0\x30\x9f\x0c\x3a\x94\x68\x35\x80\x92\x97\x78\x2d\xeb\x55\x56\x03\x1d\xc8\x93\xba\x9a\xcd\x4a\xd6\x80\x25\xbb\xcb\x6e\x41\x9a\xd7\x54\x76\xdc\x1c\x94\x73\x8f\x6d\x19\x3f\xeb\xeb\x49\x90\xc4\xa7\x4f\xfa\xdb\x7a\x44\x2b\xeb\x5c\x65\x17\x7d\x1e\x81\x84\x97\xf0\x7f\xf6\x0a\x89\x27\xcc\x60\xd3\x51\xb2\x99\x67\xcd\xe0\x6f\x34\xc3\x7c\x8c\x3f\xbf\x98\x20\x98\x1b\xe4\x14\xbb\x0e\xf0\x69\x7b\x93\x35\x79\x85\x23\x71\x75\xd3\xe3\x0d\x53\x17\xb4\x55\xb0\x16\x28\xb3\x42\x67\x37\xf9\x58\xd2\x21\xff\x9a\xa4\x43\x21\xbd\x2e\x9a\xce\xf0\x66\x35\xef\xe9\xe2\xd9\xb6\x88\xf7\x85\xcf\xeb\xe2\xbf\x5f\x65\x34\x2e\x21\xe9\xdb\xff\xdb\x99\x6c\x9c\x66\x18\x96\x24\x09\x00\x7e\xdc\x05\xab\x28\x40\xfd\xf1\xc7\x9f\x7f\xfe\xf1\xe7\x9f\x58\x43\x9d\xa1\xbf\x30\x35\x08\x50\xf8\x16\x84\x6a\x18\x44\xff\xfd\xe6\x4d\xd1\xe6\x6f\x4c\xde\x78\xe8\x2f\x2c\xd7\x6c\x48\x72\x87\x2f\x37\xe4\xbf\x31\x49\x1f\xa3\x99\xfa\x17\xe6\x2d\x34\xdb\xd2\xff\xc6\x9a\x2b\x07\xf9\x7f\x61\x3b\x8a\x7f\xfc\xc1\xd7\x64\xb1\x83\xc9\xbc\x50\x13\xb1\x66\xa3\xa6\x44\x29\xfe\x81\x61\x18\xc6\xe7\xf3\x11\x6a\x17\x0c\xb1\x56\xa7\x5c\xe7\x3b\x0a\x56\x15\x15\xec\xbb\x65\x5c\x48\x8b\xd6\xde\x5b\x54\xe2\xd8\xef\x17\x49\x1d\xa3\x7a\x4d\xf2\x6b\x8c\xcf\xa5\x3f\xbc\xd5\x5d\x03\xfd\x3c\xd6\xd3\x0a\x82\x05\xf2\xdf\x7f\x85\x1b\x0f\x5d\xd4\x6f\xe4\xfa\xde\xdb\xcc\x1a\xf9\xea\x61\xae\x10\xfb\xfd\xa2\xfa\xc5\xa8\x5e\xab\xdf\x35\xc6\x77\x5b\xe7\x7d\xba\xb3\xaf\x60\x10\xfb\xf9\xf6\xa1\x90\xb7\x0f\x0d\xbc\x45\x55\xf3\xf6\x92\xda\x9d\xb3\xbd\x56\xb9\x54\x82\x61\xdd\x46\xb9\xdd\x15\xaf\x35\xec\xae\xfc\x79\x23\x7f\x52\x35\xaf\x69\xd6\x4f\x57\xfc\x53\x8d\xea\x7a\xe8\xd0\x19\xde\x3c\xd5\x0f\x2d\xdd\xf2\x54\x27\x52\x93\xeb\xaf\x5f\x5c\xb3\xeb\x4c\x6e\xd5\xf4\x86\x58\x0f\xd7\x3c\x32\x7b\xbf\x5e\xf7\xa4\x02\x2f\xae\x7d\x12\x9b\x5b\xf5\xbf\x29\xda\x5d\x0d\x4c\xd1\xe6\x6d\xa9\xda\x0b\xf4\xb6\xa3\x86\xe2\xbf\x5f\x54\xbf\x18\xd5\x6b\xd5\xb9\xc6\xf8\x5c\xfa\x29\xda\x5c\x88\xef\x9a\x26\xf2\x83\xe3\xff\x5e\x24\xec\x81\xd8\x35\x19\x23\x6c\xce\x45\xdb\xbf\x78\xbb\xa2\xde\xd0\x5f\x04\xe1\x9b\x6d\x39\x28\x88\xfe\xfb\x45\x92\x46\x28\x5e\x13\x37\xce\xf0\x5c\x66\x1b\x19\xa3\x83\xdd\xbb\x9c\x31\xe8\xba\xbb\xd8\x75\x21\x43\x0d\xd5\xb7\xe3\xaf\x37\xcb\x78\x73\xd4\x19\x7a\x17\xbb\xdc\xc8\x8b\x83\x3b\x12\xe7\x3a\x22\x2f\x8b\xef\x76\x75\xff\xc5\x6d\xe2\x58\xb3\x71\x5e\x00\xeb\x4a\xe5\x46\x11\xd3\x42\x1f\x21\xec\xfb\x47\xe9\x9f\xd8\xae\x78\xb2\xe4\x63\x77\x86\xde\x0c\x77\xa6\x5a\x4e\x0a\x81\x63\x92\x46\x88\x45\x05\x3c\x97\x2d\x52\x28\x59\x2c\xcb\x31\xed\x83\xb1\x32\x50\x10\x5a\xce\xfe\xdf\xcf\x0b\x78\x95\x6c\xb2\xa8\x57\x8b\x27\xcc\x1b\xb5\xcd\x1e\x08\xd3\xcb\x18\xa5\xb2\x13\x29\x86\x93\xe7\xed\x7b\x02\xde\x64\x69\x0e\xf0\xfb\xbc\x3c\x07\x3a\x8f\x49\x94\x00\xf9\xda\xe6\xbd\xff\xa6\x16\xe7\x83\x44\x54\x92\xb3\x68\xd2\xb5\x11\xf0\xf3\xbd\x65\xdf\x02\x34\x5f\x20\x47\xbf\x54\x98\xb6\x79\x33\x11\xfa\x9c\x80\x9e\x1b\x84\x23\x1f\x05\x57\xe5\x8c\x50\x7b\x4c\xd6\xc8\x07\x3f\xb0\x7e\x49\xec\x88\x58\x94\x46\x59\xc2\x1a\x4d\x79\xef\xbe\xfc\x7d\x21\xfa\x58\x0d\xc6\x2f\x90\x79\x47\x66\x27\xec\xe1\x9b\x7f\xdd\x97\x39\x8a\xa6\xbb\x8f\xaf\xa9\xd5\x72\x1c\xe4\xbf\x4a\xc2\x0f\x62\x8f\x29\xf5\x50\xfe\x42\xcc\xa3\x7e\xaf\xbf\xbd\xad\xea\x03\x10\x3c\xd3\x83\x0f\x14\x1e\x93\xff\x08\x3b\xef\xdd\xf6\x27\xa6\x7a\x9e\x6d\xe9\x07\x73\xe4\xfa\xc6\x95\x61\x16\xf7\xc4\x9e\x35\x49\x09\xf4\x76\xf2\xc7\xbd\xcf\x47\xad\xd3\x15\x92\x4f\xda\xa9\x44\x8a\x0f\x8a\x79\xc3\x4b\x79\x43\x3b\x6a\x7b\x5d\x3f\x0b\xe6\x31\x72\xd1\x2e\x80\x4c\x13\xe9\x17\x20\x79\x31\x69\xdf\x41\xf9\xff\xed\x3f\xfe\xbf\x24\x61\x2d\xe3\x45\x62\x5a\xc6\xc3\x02\x46\x67\x1a\x29\x84\x76\xbd\x37\xef\x55\x72\x1f\x69\x45\x45\x4f\xf0\xd4\x52\xd5\xe4\x7a\x05\xc2\xf5\xeb\x2a\x70\xa4\x95\x60\x1f\x52\x56\x21\x4a\xe1\x5a\x25\x5c\x6f\xd7\x2b\xc7\x6e\xaa\x3a\x1c\x85\xff\xa0\x91\x56\xf9\xb7\x15\x1d\x1c\x2d\xe7\x7e\x70\x3f\xaf\xeb\x73\x72\x51\x91\x0f\x7f\x8f\x23\xc9\x55\x89\xa2\x7a\x7d\x95\x58\x17\x34\x1f\x84\xba\x2b\x02\x86\x87\x26\x09\x9f\x69\xd6\x0f\x1a\xe9\xbb\xe4\xbd\xee\x17\xfa\xc6\x8e\x89\xa6\x06\x9f\x9c\x82\x5d\x15\xf8\x92\x58\x4c\x72\x03\xc5\xe4\x8c\x96\xbd\x2b\xe0\xde\x7d\x7d\x8d\x78\x7b\x52\x0f\x09\x97\xe8\x33\xbf\xd3\xdb\xcb\x8e\xfc\x97\xa9\x2f\x46\xef\x9e\x90\xb1\xe2\x8f\x48\xfa\x1a\x3d\x9e\x51\x7b\x54\xca\xbb\xda\x7c\x8d\x6c\x0f\xc9\x74\x5b\x96\x77\x89\x6d\xd7\x9d\x2e\xbc\xe7\x24\x3a\xa7\xf5\x70\x8b\x1e\x26\x48\x09\xf2\x79\xaa\xe5\xbf\x85\xd6\x0c\xbd\x44\xc2\x38\xb5\xc7\xc6\xed\x51\xc0\x9f\x58\x5c\xe4\x9f\xd8\xd1\xc4\xeb\xb6\x1b\x20\xe3\x4d\x0d\x13\x2a\xf1\x02\xbb\x7d\xa4\x73\x4f\xe2\x4f\xce\x8e\x76\x54\x5f\xa6\xdd\x4f\x28\xf6\xae\xde\x2c\xc7\x40\xeb\xb7\xd8\x94\x23\x78\x73\x9d\x37\xd5\x30\x7c\x14\x04\xcf\x2a\xf4\x2e\x83\xb3\x58\xc4\xd5\xc0\xcd\xb1\xe0\x27\x64\x7f\xbe\x1f\xdc\xa2\x7d\x5f\xe2\x2b\xa3\xec\x9c\xe0\x71\x16\xbe\xa3\x17\x6e\xbc\xf4\x4e\xdd\x4d\xaa\x77\xa7\xfd\x57\x97\xea\xce\x49\x1e\xe7\x50\x3b\x92\xa7\x4e\xf4\x22\x69\xaf\x91\xbe\x3b\x7d\x7b\xb4\x27\x47\x88\xbf\xba\x33\x9c\x91\x4e\x33\xdf\x4c\x26\x37\xf3\x5c\x7f\x67\xf8\x96\xc8\x0f\x9e\x09\x91\x3e\xcc\xe1\xbe\xf8\xb1\x0f\x1e\xaf\xcc\xd1\xf4\x3c\x1e\x30\x4a\xa1\xff\x08\x8f\xbb\x35\x89\x94\x7d\xbc\x12\x9e\x8f\x96\x96\xbb\x08\x7e\x49\x6d\xae\x31\xbb\x5b\xad\x6b\x1f\x3d\x5e\xbf\xf7\x80\xd4\x97\xd5\xe9\x9d\xc1\xdd\x7a\x24\x46\x74\xcf\x49\x9f\xf0\xf6\x4b\x86\x76\x9c\xfa\x55\x07\xf8\xb3\x03\xfc\x9c\xe8\xb9\x0b\xf5\xa2\x11\x7e\x8b\xc5\x23\x75\xb8\xe3\xd7\xdd\x64\xf6\x3a\xf8\xba\x24\xfc\x90\xec\xf7\x41\x2c\xea\x6c\x7f\x45\xb7\xb9\xa4\x9f\xda\xd5\x3f\x2e\xb6\xee\x1c\xcb\xc5\xc6\x72\x46\x87\x39\x70\x6a\x05\x5f\x27\xb7\x93\xee\xb8\x86\x7c\x3e\x0d\x8f\x94\xb9\x21\x99\xad\x06\xe1\xdb\xcc\x35\x2c\xd3\x42\xc6\xb3\x81\xf4\xdb\x64\x93\x24\xbd\x56\xf6\x86\xc4\x01\xb2\xed\x97\xc8\x78\x20\x94\x24\xd5\xe1\xed\xb5\x11\x74\x4e\xe1\x95\xed\x7a\x46\xef\x96\x60\xc9\x2d\x1b\x58\x23\xe7\x48\xed\xd9\xa8\xc3\x25\xa9\xb3\xb5\xed\xe3\xeb\xa4\xe5\xed\x2b\x89\x04\xaa\x81\x4e\xd3\xda\xf7\x78\xfb\x9b\xe6\xba\xd3\xd4\x22\xde\xa0\x79\x77\xc2\xfc\xfd\xbb\x81\x42\xd5\xb2\x03\xec\xcf\xff\xfc\x07\xfb\x16\xb8\xb6\x11\x49\xad\xfa\xf6\xd7\x5f\x21\x5a\x87\x3f\x7e\xfc\xc4\x92\x0b\xea\xae\xf1\x58\xc1\xc3\x52\x46\x72\x51\xcd\x5d\x8c\xc6\xe1\x43\xec\xcf\x8a\xde\x16\xe0\xac\x68\x4c\x84\xf7\xe5\xb6\xbd\xc9\xc5\xfe\x8d\x91\xe4\xad\xcc\x8f\x48\x1f\x78\x06\xe8\x12\x29\xee\x1a\x2b\x9a\x68\xf2\x78\x9f\x3a\x23\xf8\xe4\x82\xd5\x55\x6a\xb7\x45\xbb\xb5\x50\x15\x23\xb7\x4f\xd8\xdb\x27\xf0\xbd\x56\xcc\x38\xdd\x07\x04\x8e\xe6\x02\x5e\x26\x7f\x3e\x9c\x7e\x6b\x19\x6f\x66\x24\x0b\xa8\x50\xfd\x35\x49\xb8\x47\xb6\x58\xa1\xd9\x11\xcb\xc5\xc6\x29\x31\x0c\xeb\x88\x05\xb1\x23\x36\x72\xa2\x14\x4b\x88\xd8\xbf\x6d\x36\xb0\x6e\x2b\xbf\x53\x63\x47\x94\xe4\x4e\x39\x27\xef\xfe\x94\x17\x6b\xa2\x2c\x62\x39\x5e\xca\xf1\x79\xf1\x46\x76\x9d\x81\x82\xd8\xcf\xb7\x58\x84\xfa\x75\xca\x38\xe7\x73\x27\x75\x2e\x49\x92\x73\xfd\xc4\xa3\xe9\x57\x95\x75\x34\xed\x77\xf2\x0c\x13\x35\x71\x8c\xf0\xfd\x76\x3d\x44\xe5\xb8\xa6\x85\xf7\xe0\xe9\xed\x0e\xf3\x39\x0d\x5c\xc6\xda\x7f\xa3\x1a\x12\x84\x39\xd7\xc5\x95\xd5\x81\xd7\x76\x8a\x78\xe4\xf7\x9f\xa0\x90\xe4\xae\x71\x11\x5a\x7f\xa4\x77\x60\x0e\x42\x06\x32\x30\xd3\xf5\xb1\x48\x46\x7c\xe8\x62\x2b\xd7\x9f\x9e\x09\x7e\x0a\x2e\xee\x24\x0d\x3c\xd7\x09\x5c\x1f\x93\xc5\x81\xfc\x77\x42\x46\xdc\x6e\x3e\x78\x2c\x76\x99\x06\x27\xc8\x1d\x51\xfc\x7e\x7c\xbf\x13\xe6\x1a\xab\x43\xfa\xe1\xa3\xfc\xf6\xc9\x8c\xd7\x99\x46\xf3\x18\x6f\x72\x8e\xe2\xce\x1d\xbe\x31\x14\x8b\x70\xbd\x04\xaf\x9b\x3c\x8f\x73\xe4\x3b\xec\x22\x93\xec\x0f\x4e\x67\xd3\xeb\x9b\x4c\x1e\x48\xee\xce\x77\x9a\x2d\x2c\xd7\xac\x75\xeb\x0d\xcc\x32\x12\xbe\xbf\x99\x1e\x7d\x41\x61\xff\x87\x63\x9b\x46\x30\x58\x57\x03\x5d\x35\xd0\x7b\x81\x9b\x29\x41\xe7\x85\xee\xba\xd2\x37\x4a\x9f\x47\x61\xcf\x0a\x9e\xe7\x59\xde\xad\xf9\xa1\xb1\xde\xed\xce\x6c\xb1\x46\x06\xb6\x54\x7d\x7d\xac\xfa\xdf\x21\xf7\xe3\xb8\x1d\x68\x57\x26\x92\x6c\x97\x50\xee\xef\xdb\xcd\x74\xec\x17\xee\xc2\xd7\xd3\x51\x7a\x77\x1d\xf6\x12\x1f\xd6\x2e\x12\xbf\xdf\x5b\x04\x8a\x3b\xef\x78\xe5\xc2\x3e\x71\x4d\x1c\x94\x25\x59\x3a\xac\xf9\xa8\xa3\xd1\x7e\xdd\x27\x08\xd5\x99\xf7\xa6\xf9\x96\x73\xb9\xf4\xf3\x06\x01\x00\xe0\x7d\xf2\xe6\x5b\xce\xf7\xd3\x17\x3f\xf6\x09\x70\x18\x0d\xde\x19\x1d\x24\xb6\xad\xf9\xc2\x32\xac\x70\xf3\xe6\xb9\xae\x1d\x60\xdf\xf7\x7d\xca\x32\xb0\xdd\x84\xff\x94\x3c\xf7\x13\xfb\xf3\x4f\x6c\x8c\xd6\x7f\x22\x67\xd7\x58\x06\xd6\x72\x5d\xbb\x9c\xdf\x97\xdd\xbb\x02\xc1\x4c\xdd\xf9\x97\x91\x2f\xf6\xef\x4c\x84\x30\xcb\x09\xd1\xce\x8f\x3f\x7f\xb3\x1f\xae\xbb\xd1\x7a\xb0\xb2\x98\x66\x8d\xa2\x9f\x63\xb9\x92\x98\xab\x62\xdf\xe3\xc5\xfe\x83\x81\x1f\x07\x02\xc1\x58\xf5\x93\x3e\xce\x8b\x05\xbe\x5b\x93\x31\x70\x20\xf3\x3d\x5a\xf6\x3f\xff\x3e\x91\x38\x74\x40\x1f\x05\xc8\x5f\xa2\x00\x9b\x04\xae\xa3\xc5\xc4\xbc\x1a\x91\xb8\x5e\x23\x03\xd9\x28\x44\x06\xa6\xb9\xae\x8d\x54\xe7\x52\x1a\x53\xb5\x03\x74\x28\x1b\xdf\x9d\xf0\xc7\xae\x75\xce\x3a\x40\xac\x5d\xf6\x8e\xcf\xb9\xb8\xcd\xc6\x45\xe3\x1d\xda\x7d\x64\x39\xdf\xaf\x55\xed\xcd\x53\xc3\xf1\x9b\xeb\x05\x3f\xfe\x8e\xf3\x5a\xa2\xb7\x38\xad\x44\xf2\x7b\x8b\x87\x7d\x3f\x56\xf7\xe7\x55\x15\x45\xaa\x23\x89\xed\xee\x0e\x0e\x3f\x62\xbf\xb1\x9a\x59\xc6\x5b\x80\xe6\x7b\xb5\x48\x32\xdf\x91\xb1\x7e\x59\x2e\x61\xf8\xfe\x0f\xe5\x46\xae\x23\xd6\xc5\x86\x8c\x09\xca\xf1\x4f\x8d\x26\x56\x2f\x37\xf6\x3b\xcd\x4f\xbf\xf9\xc1\xc7\xef\x1c\x9f\x2b\x89\x18\xfe\x21\xc0\xf9\xc8\x4c\xec\xef\x49\x7d\xc8\x41\xeb\x70\xa9\xda\xdf\xbf\xdd\x96\xff\xdb\x5f\x7f\xf9\x68\xa4\xdb\x6a\x10\x1c\x7b\xd7\x79\xb9\xb7\xf8\x90\x8a\x36\xf9\xad\x40\x7a\x8c\xdb\xe5\x92\xd3\xd5\x46\x8a\x86\x17\x53\x31\xb9\x94\xfe\x51\x9e\x17\x5f\xfe\x48\x6a\x8b\x0f\x58\xbc\xde\x2a\xd7\x56\xd8\xe3\xed\xf4\xf3\xac\xe4\xa5\xd4\xb1\xe2\x0f\x6a\x3d\x51\xb2\x83\xfe\x83\xeb\x69\x71\x37\xd5\x72\xb5\x32\x3f\x93\x25\x8f\x0f\xd2\x4f\x08\x78\xc6\xe2\x35\x92\x3e\x21\xcd\x53\x32\x3c\xde\x99\xa2\x73\xa4\xdb\xdd\x29\xb6\x38\xf2\x4b\x3a\xd4\x0d\xe9\xae\x74\xa9\x5b\x75\x79\x20\x2b\x2f\x7d\xb7\xba\x23\x66\xf2\xb2\xd2\x93\x12\x3f\x25\xd5\x93\x92\x5c\xed\x62\xd7\x8e\x3a\x89\x53\x7b\x3f\xed\x04\xff\x89\x7d\x03\x00\x87\xc8\xa0\x4d\x06\x9a\x48\xe3\x4c\x0a\x30\x2a\x09\x19\xa8\x21\x52\xe7\x20\x45\xb1\x3a\x45\x21\x88\x13\x1c\x8b\x58\x44\x6b\x2a\x30\x09\x12\xe0\x38\x49\x03\x02\x27\x4c\x1d\x87\xdf\x7e\xfc\xfd\x87\x24\xd6\xc4\x9c\x8c\x79\xa3\x37\x5d\x0d\x55\xdb\x1d\xfd\x2b\x40\x0f\x41\xcf\xfe\x88\x93\xd0\x5f\xa0\x1f\x7f\xef\xa6\x78\xf2\x18\x61\x1f\x53\xd9\xec\xd9\x14\x5a\xf5\x11\x36\x72\x2d\x67\xb4\xf3\x36\x35\x84\x2d\x1c\x1f\xd9\xea\x6e\xda\x12\xba\x1f\x88\x85\xed\xc9\xff\xc4\xb4\x45\x88\x59\x21\x66\xb8\x28\x70\xbe\x85\xd8\x4c\x0d\x43\xe4\xef\xdd\xd6\x70\xbf\x7f\x6a\x74\x55\x4f\xc9\x43\xfc\xa4\xb1\xd3\x91\x2a\xf4\x4f\x0c\x4f\x38\x59\xe6\x3e\x19\x96\x66\x39\x8e\x64\x21\xcb\x25\x53\xb9\xd5\x1d\x2e\xc5\xa1\x9e\x23\x74\x12\x88\x3d\xd0\xb9\xe9\xe5\x5e\x9f\x1f\xdc\xf6\x77\xaf\xa2\x72\x92\xe7\x7b\xb5\x63\x47\xfc\xaf\xf3\x0c\xc9\x8b\x37\xb1\x7c\xc5\x44\xff\xcc\x40\xc1\xc1\x07\x7d\x4f\x7f\x3c\x58\xd0\x84\xe7\x40\x24\x16\x57\x3c\x7c\x7f\x6e\x81\x6f\x7e\x7f\x19\x85\xfa\x0c\x89\x7c\xfe\x20\x40\x92\x71\xbf\xfb\xf5\x49\x35\x69\x09\xc4\x3e\x3c\xba\x49\x71\x1f\xe0\x2c\xc1\xf8\xe6\x84\xec\x2c\xf1\xef\xd0\xfa\xd7\x3f\x8a\x1b\xda\x78\xee\xed\x67\xb9\x24\x7e\xf7\xee\x6e\xe2\xd1\x7e\x55\x2e\xbc\x7b\xb4\x91\x85\xc6\xc4\x02\xd1\x5d\x7c\xef\x11\xc4\xd6\x61\x4b\x99\xd4\xae\x61\x86\x1a\xaa\xbb\x4a\x62\xc6\x62\xe6\x61\xba\x3b\xf3\x76\x0e\xc9\xae\xdc\xff\x0f\x00\x00\xff\xff\xdc\x9f\xaa\x54\x90\xee\x04\x00") func kahunaHorizonSqlBytes() ([]byte, error) { return bindataRead( @@ -286,7 +286,7 @@ func kahunaHorizonSql() (*asset, error) { } info := bindataFileInfo{name: "kahuna-horizon.sql", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} - a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xc2, 0x8, 0xfd, 0x9e, 0x72, 0xee, 0x37, 0x99, 0x4d, 0x17, 0xd8, 0xe8, 0x4e, 0xf3, 0x22, 0xbe, 0x48, 0x8a, 0xce, 0xdf, 0xfe, 0x80, 0x90, 0xaa, 0x4e, 0x1b, 0x16, 0xdc, 0x94, 0x9, 0x9b, 0x3}} + a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x66, 0x14, 0x83, 0x45, 0x62, 0x5e, 0x28, 0xca, 0xb5, 0xe4, 0xcc, 0x56, 0x58, 0x21, 0x85, 0xc7, 0x5a, 0xa4, 0xb7, 0x51, 0x31, 0x77, 0x19, 0xf2, 0x4f, 0x89, 0xd2, 0x96, 0x8, 0xb, 0x3a, 0x70}} return a, nil } @@ -310,7 +310,7 @@ func offer_idsCoreSql() (*asset, error) { return a, nil } -var _offer_idsHorizonSql = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\x7d\xf7\x8f\xa3\x48\xf6\xf8\xef\xf3\x57\xa0\xd1\x49\xbd\x23\xf7\xac\x29\x32\xb3\xdf\x3d\x09\xdb\x38\x1b\xe7\xd4\xa7\x93\x55\x40\x81\x71\x00\x1b\x70\x3c\x7d\xfe\xf7\xaf\x0c\x0e\x98\x76\xc4\xee\x9e\xd9\xbb\x45\xab\xd9\xb6\x29\x5e\xaa\x97\xea\xd5\x2b\xfc\xfd\xfb\x97\xef\xdf\xb1\x8a\xe5\xb8\xba\x8d\xea\xd5\x22\xa6\x42\x17\xca\xd0\x41\x98\x3a\x1b\x4f\xbe\x7c\xff\xfe\x65\x73\x3f\x35\x1b\x4f\x90\x8a\x69\xb6\x35\x3e\x0c\x98\x23\xdb\x31\x2c\x13\xe3\x7f\x67\x7e\x07\x81\x51\xf2\x0a\x9b\xe8\xbd\xcd\xe3\xa1\x21\x5f\xea\x62\x03\x73\x5c\xe8\xa2\x31\x32\xdd\x9e\x6b\x8c\x91\x35\x73\xb1\x3f\x31\xfc\x0f\xef\xd6\xc8\x52\x86\xef\xbf\x55\x46\xc6\x66\x34\x32\x15\x4b\x35\x4c\x1d\xfb\x13\x7b\x69\x36\xd2\xdc\xcb\x1f\x3b\x70\xa6\x0a\x6d\xb5\xa7\x58\xa6\x66\xd9\x63\xc3\xd4\x7b\x8e\x6b\x1b\xa6\xee\x60\x7f\x62\x96\xb9\x85\xd1\x47\xca\xb0\xa7\xcd\x4c\xc5\x35\x2c\xb3\x27\x5b\xaa\x81\x36\xf7\x35\x38\x72\xd0\x11\x9a\xb1\x61\xf6\xc6\xc8\x71\xa0\xee\x0d\x58\x40\xdb\x34\x4c\xfd\x8f\x2d\xed\x08\xda\x4a\xbf\x37\x81\x6e\x1f\xfb\x13\x9b\xcc\xe4\x91\xa1\xbc\x6e\x98\x55\xa0\x0b\x47\xd6\x66\x98\x50\x6c\x88\x35\xac\x21\x24\x8a\x22\x96\x4b\x63\x62\x27\x57\x6f\xd4\xb1\xb2\x54\xec\x6e\xc7\xff\xde\x37\x1c\xd7\xb2\x57\x3d\xd7\x86\x2a\x72\xb0\x54\xad\x5c\xc1\x92\x65\xa9\xde\xa8\x09\x39\xa9\x11\x78\xe8\x78\x60\x4f\xb1\x66\xa6\x8b\xec\x1e\x74\x1c\xe4\xf6\x0c\xb5\xa7\x0d\xd1\xea\x8f\xcf\x40\xa8\x78\x7f\x7d\x06\xca\x8d\x5e\x7d\x1e\x83\x3e\xb6\xfb\xb9\xf3\x09\xdc\x28\xf2\x25\x64\x81\x51\x07\xe0\xde\xf0\x9c\x94\x12\x3b\x81\x91\x5b\xb0\x1e\x55\x3d\xa4\x69\x48\x71\x9d\x9e\xbc\xea\x59\xb6\x8a\xec\x9e\x6c\x59\xc3\xcb\x0f\x1a\xa6\x8a\x96\xbd\x00\x73\xa6\x03\x3d\x45\x77\x7a\x96\xd9\x33\xd4\x7b\x9e\xb6\x26\xc8\x86\xfb\x67\xdd\xd5\x04\x3d\xf0\xf4\x81\x92\x87\xa8\xb8\xef\xd9\x11\x52\x75\x64\x7b\x0f\x3a\x68\x3a\x43\xa6\x72\x17\x0b\x81\xc7\x27\x36\x9a\x1b\xd6\xcc\xd9\x7e\xd7\xeb\x43\xa7\x1f\x11\xd4\xe3\x10\x8c\xf1\xc4\xb2\x37\xe6\xb8\xf5\xa9\x51\xc1\x44\x95\xa5\x32\xb2\x1c\xa4\xf6\xa0\x7b\xcf\xf3\x3b\x65\x8e\xa0\x4a\x5b\xbb\x8c\x40\x74\xf0\x49\xa8\xaa\x36\x72\x9c\xcb\x8f\xf7\x5d\x5b\xf5\xe2\x4e\x6f\x64\x59\xc3\xd9\xe4\x86\xd1\x93\x6b\x24\xf9\xa3\xa0\x61\xdf\x09\x78\xe7\x74\x6f\x7e\x60\xe3\x27\x34\x0d\xd9\xb7\x0d\xdd\x81\x8f\xf0\xc8\x56\xac\xb7\x3d\xe4\xb9\xd6\x3b\x90\x04\x5d\xf1\xb5\x27\x26\x9b\x07\xfa\xee\xd5\x19\x70\x8e\x1c\x90\xbc\xba\xaa\x46\xfd\xbd\xa5\xdf\x32\xd8\xf2\xe9\xb0\xae\x0e\x34\x1c\xb7\xe7\x2e\x7b\x93\xeb\x20\x37\x23\xad\xc9\xad\x23\xd1\xad\xc3\x76\xa1\xe4\xf2\x60\x79\x67\xee\x57\x87\x5d\xf7\x62\xf2\xea\xb6\xc9\xf4\x63\xe4\x46\xda\x8e\x33\xbb\x86\x79\x3f\x58\xb1\x54\x74\x67\x5e\xb0\x57\x83\x09\xb4\x5d\x43\x31\x26\xd0\xbc\x18\xbc\xaf\x3d\xda\x9b\xdc\x99\x9b\xec\x23\xda\xbd\x14\x9c\x7e\xf0\x6e\xfc\x9e\xf0\x6e\xc1\xe7\x0f\xfc\x70\xf8\xfe\x64\x6e\x66\x72\xfb\xe7\x26\x3e\xec\x52\x3f\x4f\x19\x7a\x37\x52\xa0\x5b\xf6\xa4\x37\x36\xf4\x6d\xc2\x70\x81\x84\xd0\xc8\x9b\x79\xbc\x3f\xdf\xbb\x04\xf9\x56\xe5\xf4\x9f\x4e\x96\x8b\xcd\x92\x84\x19\xaa\x8f\x39\x25\xa6\x85\x66\xb1\x71\x23\xec\x33\x4a\xf7\x04\xc8\xdb\xe9\xbe\x0c\xc9\xfb\x74\x3b\xfb\xbb\x28\x5d\x17\xab\x4d\x51\x4a\x46\x90\xd9\x26\xcf\x76\xd0\xf4\x6e\xcc\x47\x40\x6e\x7e\x5a\x45\x37\x8e\x3d\x64\xb3\x37\x73\x78\xc6\xea\xef\xe1\xef\x34\x88\xdb\x9e\xdd\xe6\x7d\xb7\x0d\xde\x26\x79\x37\xf3\xb6\xf5\x00\xf7\xf0\xe2\x3f\x72\xe3\xd8\x6d\xfa\x77\x3b\x3d\xbb\x7c\xf1\x16\x8a\x42\x3e\xe4\xf2\xe0\x80\x4b\xd8\x0e\x14\x32\x99\x9a\x98\x11\x1a\x27\x06\x8f\x8d\xcd\x8a\xc3\x50\xd0\x6f\xe6\x6c\x8c\x6c\x43\xf9\xd7\xbf\xbf\xdd\xf0\x14\x5c\x46\x78\x6a\x04\x1d\xf7\x37\x68\xae\xd0\xc8\x2b\xc5\xdc\xf0\x84\x66\xd8\x27\x1f\x49\x37\xa5\x64\x23\x57\x96\x2e\xf0\xd3\x83\xba\x7e\xa0\xee\x15\x7b\x47\xe8\x05\x18\x3b\xee\x1e\x80\xb1\xe1\xd5\x7b\xfc\x40\xfc\x2b\x76\x0f\x23\x1e\xeb\x37\x40\x10\x3b\x0d\x51\xaa\x87\x40\x8c\x26\xba\x33\x1d\xed\x74\x31\x99\x15\x4b\xc2\x3b\x0c\x7f\x7c\xf1\xab\x70\x12\x1c\xa3\x1f\xbb\xef\xb0\xc6\x6a\x82\x7e\x6c\x1f\xf9\x03\xab\x2b\x7d\x34\x86\x3f\xb0\xef\x7f\x60\xe5\x85\x89\xec\x1f\xd8\x77\xaf\x38\x97\xac\x89\x9b\xf9\xda\x42\xde\xc1\xfb\x72\x04\xf1\xf8\xe6\x16\x70\xb2\x5c\x2a\x89\x52\xe3\x02\x64\x7f\x00\x56\x96\x8e\x01\x60\xb9\x3a\xf6\xb2\x2b\xbb\xed\xbe\x73\x3c\x20\x2f\x61\xcc\x3b\xf6\xb7\x38\xf7\x12\xba\xca\xcf\x91\x2c\xa5\x72\x23\x24\x4f\xac\x9d\x6b\x64\xf7\x64\x05\xeb\x6f\x47\xe8\x0f\x50\x42\x84\xdc\xc3\xfc\x3b\x20\x9e\x00\x2a\xc5\xf8\x44\xaf\x57\x8b\xd8\xc4\xb6\x14\xa4\xce\x6c\x38\xc2\x46\xd0\xd4\x67\x50\x47\x9e\x18\x6e\xac\x17\x06\xc9\xbd\xae\x68\x5b\xf2\x77\xba\x7a\xa0\x7f\x37\xb7\xa7\x64\xb9\xd7\xec\xab\xf0\xb1\x9a\xd8\x68\xd6\xa4\x7a\xe0\xbb\x2f\x18\x86\x61\x45\x41\xca\x34\x85\x8c\x88\x79\xdc\x97\x4a\x4d\xdf\xdf\xd5\x1b\xb5\x5c\xb2\xe1\x8d\x10\xea\xd8\x3f\x7a\xff\xc0\xea\x62\x51\x4c\x36\xb0\x7f\x80\xcd\xa7\xf0\x6c\x5c\x35\xc4\xc7\xb8\xbb\x06\xfe\x69\xcc\x11\xa7\x98\xbb\xc5\x53\x3d\xc6\xdf\x0d\x18\xf6\x2c\xee\xbf\x8a\xc4\xe1\x6f\x5f\x30\x2c\x29\xd4\x45\xac\x9d\x15\x25\xec\x1f\xe0\x5f\xe0\xdf\xf1\x7f\x80\x7f\x11\xff\xfe\xe7\x3f\x08\xef\x6f\xe2\x5f\xc4\xbf\xb1\x86\x7f\x13\x13\x8b\x75\x71\x23\x14\x51\x4a\x7d\x3b\x29\x99\x1b\xe2\xc0\x83\x92\xb9\x8e\xe1\xa3\x25\xf3\xff\xa2\x48\xe6\x7d\x4c\xdd\xca\x61\x1f\x87\x6f\x13\xc4\x21\x6c\xbf\x83\xe8\x51\x8c\x61\xf5\x8d\xac\xb0\x3f\x0f\x1e\xe0\xd5\xff\xba\xd1\xad\x88\xd8\x9f\x41\x8b\xf8\x76\xca\x6a\x9f\x4a\x63\x18\x60\x88\xc4\x9d\x19\xdf\x4e\xe1\xc9\x14\xe8\x51\x2a\x4f\x01\x0d\x51\x7a\x64\x90\xc7\xe4\x1e\xb4\xec\x3d\xb5\xa7\xd2\xbc\x87\xa9\x3d\x01\x34\x4c\x6d\xd0\x48\x2e\x52\xbb\x89\x5c\x2a\xd2\xe0\x6c\xe4\xf6\x5c\x28\x8f\x90\x33\x81\x0a\xc2\xfe\xc4\x5e\x5e\xfe\x38\xbe\xbb\x30\xdc\x7e\xcf\x32\xd4\xc0\x56\xda\x11\xaf\xc1\xfc\x77\xcb\xa2\x67\x60\xb7\xb1\xe7\xdb\x62\x70\xf1\xed\x73\x64\xa8\x98\x6c\xe8\x86\xe9\x7a\x89\x81\xd4\x2c\x16\x7d\x76\xe0\x78\x93\xc6\x63\x4a\x1f\xda\x50\x71\x91\x8d\xcd\xa1\xbd\x32\x4c\x3d\x34\xcc\x9c\x8d\xf7\x29\x3f\x66\x98\x2e\xd2\x91\x1d\x1a\xa2\x8d\xa0\xee\x60\xce\x18\x8e\x46\xef\xd1\xb8\xd6\x78\xf4\x1e\xc9\x6f\x04\x4d\x7f\xdb\x8f\x7c\x3f\xed\xe1\x75\x43\x54\x71\x84\xab\x1d\x7b\x91\xb8\x68\xf9\x4e\x20\x93\xc9\xc8\xf0\x6a\xf6\x98\x6b\x8c\x91\xe3\xc2\xf1\x04\xdb\xcc\x99\xf7\x11\x5b\x5b\x26\x7a\x4f\xe8\xb9\x55\xd1\x2e\x1f\xdd\x2e\xa7\x6e\xa3\x79\xbf\xf8\x3a\x03\x75\xab\x86\x42\xad\xe1\x67\x74\xc0\xfb\x22\x27\x25\x6b\xa2\x97\x7e\x25\xba\xdb\xaf\xa4\x32\x56\xca\x49\x2d\xa1\xd8\x14\xf7\x9f\x85\xce\xe1\x73\x52\x48\x66\x45\x0c\x5c\x63\x26\xb2\xd8\xc3\x80\xde\xa9\xe2\xb6\xe8\x81\x99\x68\xe9\xce\xe1\xe8\xb7\x97\x33\x1c\xbf\xfc\xf8\x61\x23\x5d\x19\x41\xc7\xf9\x16\x9e\x2e\x7f\xaf\xe2\x84\x6e\x31\xd4\xb7\x0b\x13\xe5\xaf\x8d\x1f\xe6\xcc\xaf\xe8\xec\xf9\x3a\x6d\x19\x87\x5a\xdd\x69\x32\x4f\x0e\x57\x2c\xf5\xd4\x70\x40\x9c\x1e\xee\x97\xff\x4e\x3c\x40\x33\x97\x2c\xec\x74\x79\xe1\x49\x6a\x1b\x84\xf9\x69\x4a\x7b\x89\x11\xac\xdc\x96\xc4\x14\x96\xe8\x5e\xe1\xc8\xaf\xd0\x5d\x66\x68\x0f\x2b\x74\xfb\x77\x43\x3d\x47\xdb\xae\xe6\xf3\xa8\xd6\x6d\xe1\x6c\xd5\x2e\x64\x33\xbd\x73\x9e\xfe\x7d\x89\xeb\xdc\xc8\xaf\xde\xc6\xc7\xd7\x33\xda\xec\xe9\xf1\xe9\x5b\x2a\x72\xa1\x31\x72\xb0\x81\x63\x99\xf2\x79\x65\xdb\x15\xca\x1e\x95\xc3\x16\xce\x56\x0e\xbb\x7d\xeb\x33\xb4\x05\x36\x93\x6f\xb2\xc2\x53\xfb\xd8\xa7\x1f\xdc\x8a\x25\x50\x19\xf5\x26\x62\x4f\xc7\xce\xcb\xe1\x21\x0c\x87\x89\xb8\x6d\xfc\x7e\x33\x39\x14\x98\xac\x99\x7b\x88\x4d\xe1\x67\x6c\x04\xdd\xab\x0f\xf9\x63\x67\x13\xf5\xe6\xb1\x7b\xd5\xd9\x7e\x0c\xed\xb3\xbf\xe3\x05\xbc\xcb\x07\x5c\x38\xea\x29\x96\x61\x3a\xa7\x75\x50\x43\xa8\x37\xb1\xac\xd1\xe9\xbb\xde\xce\xa7\x86\xce\xcd\xb5\x77\xdb\x46\x0e\xb2\xe7\xe7\x86\x6c\xf2\x50\x77\xd9\xf3\xd2\x24\x63\x7d\x6e\xd4\xc4\xb6\x5c\x4b\xb1\x46\x67\xf9\x0a\xcf\xd1\x4e\x59\x10\x54\x91\xed\xa5\x17\xfe\xf7\xce\x4c\x51\x90\xe3\x68\xb3\x51\xef\xac\xa2\x6c\x19\x87\xc6\x08\xa9\xe7\x47\x9d\x37\xab\x33\xb5\xeb\x47\xad\xec\xcc\x7e\xc8\x95\x98\x77\xbb\xb7\xb9\xee\xbf\xee\x65\xf9\xb9\x61\xec\x22\x8e\xcf\x0a\x6b\x77\x31\xfa\x60\x98\xbb\x88\xeb\x7d\xd8\x3b\x3d\xfc\x42\x18\x0c\xec\xec\x3c\x4d\x37\xaf\x2d\x73\x8e\xbb\xaa\xce\x2c\x85\x36\x99\xbf\xe2\xb3\xe2\x45\xc0\x07\x03\xe0\xd6\xf2\xad\x99\xad\xec\xdb\x34\xce\x84\x9e\x9d\x3b\x79\x79\xf9\xf1\xe3\xfc\x52\xec\xbc\x1d\x6c\x37\xd6\x1e\x15\xe7\xb6\x17\xf0\xb7\xa7\xe6\x0b\x5b\x97\x18\x25\x7a\x79\xbd\x30\x67\xd1\x86\x3a\x11\x2f\x0d\xda\x36\x47\x5e\x1a\xe2\xaf\x83\x4f\x0e\x78\xdf\xd3\x79\x65\xdc\x45\x74\xfb\x51\x17\x30\x7a\x24\x19\x4e\xcf\x41\xa3\x11\xb2\x31\xd9\xb2\x46\x08\x9a\xbb\x98\x64\x28\xa8\x67\x1e\xc5\x5f\xff\xbb\xe3\x98\x7c\xe8\x26\xea\x85\xa2\xf5\x51\x3f\x53\xf8\xa6\x6d\xcd\x4c\xd5\x6b\x08\x1e\x19\x93\x09\xd4\xd1\x7b\xa0\x86\xd3\x43\x4b\xa8\xb8\xc7\x74\x05\xf6\xf7\x4f\xb6\x8c\x7a\xec\xf6\xbc\xa6\x62\x2c\x99\x15\x93\x05\xec\xb7\xdf\x82\xa2\xff\x27\x86\x7f\xfb\x76\x0d\xd4\xa9\xc7\x77\xd2\xfe\x7f\xef\x26\xe0\x06\x78\x47\x93\x11\x02\x1f\x9a\x29\x8f\xc0\x8b\x36\x78\x7a\x6b\xfc\x09\x56\x79\xba\xd9\xe1\xc6\x10\x7c\x8b\xef\x7b\x24\x08\x5f\x6b\x2c\x78\x4e\x18\xbe\x82\xe5\xb3\x02\xf1\x9d\xcc\x3e\x18\x8a\xaf\x60\x7b\x1f\x8c\xcf\x3d\x70\x21\x1c\x1f\x35\x93\x3c\x51\x57\x77\xfa\x19\x24\xe9\xe6\xd5\xd7\x36\x68\x5c\x59\xd3\xdd\x1a\xb1\x2f\x07\xdf\x93\x63\x0f\xa8\x4f\xda\xcb\x66\xf9\x70\x7e\xfd\x71\x6e\x65\xf7\x53\xd6\x66\xee\xb2\x87\xcc\x39\x1a\x59\x13\x74\xaa\xde\xe9\x2e\x37\x2b\xa5\xd9\xc8\x3d\x73\x73\x8c\x5c\x78\xe6\xd6\x66\x8d\x76\xee\xb6\x63\xe8\x26\x74\x67\x36\x3a\x55\x9a\xe3\x99\x6f\xff\xfa\xf7\x21\xe9\xf9\xcf\xff\x9d\x4a\x7b\xfe\xf5\xef\xb0\xcc\xd1\xd8\x3a\x53\x45\x3b\xc0\x32\x2d\x13\x5d\x4c\xa2\x0e\xb0\xde\x83\xd9\x72\x66\x8c\x51\x4f\xde\x84\x41\xaf\xd4\xcd\xd9\xd0\xd4\xd1\x91\x5a\x9e\xbe\x39\x36\xcc\xde\x19\xed\x39\x3f\xa0\x17\x8e\xb0\x27\x07\x6d\xf1\xea\x70\x72\x34\x16\x2d\x5d\x1b\xf6\x36\xa2\x46\xb6\xe3\xcd\xc2\xbf\xfe\x1d\x5e\x6f\x1e\x07\xe9\xcd\x94\x6d\xd8\xd6\x91\x7a\x7d\x41\xb9\xad\x6e\x1a\xea\xce\x2d\xec\x9a\xd4\x6e\xf1\x65\xbe\x5f\xf0\x3a\x02\xaf\xf4\xbf\xd5\xc5\xc6\x85\x4a\x70\xb0\xe6\x16\xac\x03\xdf\xb7\x52\x7a\x1e\x13\x37\xb6\x07\x5e\x64\xea\xe2\x0a\xeb\x16\x26\xcf\xa6\x04\x4f\x63\xf3\xe6\x0e\xcb\x8b\x8c\x5e\x89\x5f\xa7\x59\x4d\x41\x17\x62\x9a\x65\x5f\xd9\x0f\xc3\x52\x42\x43\xb8\xc2\x5e\x4e\xaa\x8b\xb5\x06\x96\x93\x1a\xe5\xa3\x3d\x31\x2f\xdc\xd7\xb1\xdf\xc0\x2b\xf6\x42\xe3\xbb\xeb\xe5\x15\x23\x5e\x31\xfc\x15\x7b\x79\xf9\xf6\xc7\xd5\x67\x89\x0b\xcf\x9e\x61\xe5\xd2\x7e\xd6\xbd\xec\x84\xf7\xb4\x76\x64\xbd\x80\x9e\x61\x1a\xae\x01\x47\x3d\xbf\xbf\xe8\x77\x67\x3a\x7a\x79\xc5\x5e\x08\x1c\xf0\xdf\x71\xe6\x3b\x4e\x62\x80\xfb\x41\x70\x3f\x28\xf6\x77\x9c\x24\x28\x9e\x89\xe1\x44\x98\xe1\xb3\xd0\x89\x9e\x7f\x6e\xe4\x68\x36\xe5\x55\xcf\xb5\x0c\xf5\x32\x26\x9e\xa1\xd9\x7b\x30\x91\xbd\x99\x83\x0e\x2e\xd0\x30\xdf\x9d\x55\xb9\x88\x8f\xa2\x70\x8a\xbb\x07\x1f\xd5\x83\xaa\xda\x0b\x57\xfc\x2e\xe2\xa0\x29\x9a\x24\xee\xc1\x41\xf7\xfc\xa0\xbf\x5b\x7e\x78\x3b\xc5\x17\x51\x30\x24\x4e\xdc\xc5\x06\xb3\x43\xb1\xf5\x9c\x37\xa0\xe0\x28\x40\xdf\x83\x82\xed\x8d\x2d\xd5\xd0\x56\xb7\x73\xc1\x01\x86\xb8\x0b\x05\x77\xc4\xc5\xb6\x41\xfc\x06\x3c\x2c\xc5\x90\xf7\xe1\xd9\x4c\x3a\xd4\x75\x1b\xe9\xd0\xb5\xec\xcb\x3a\xc5\xe3\x00\xe7\xef\x01\xcf\x7b\xe0\xfd\x6a\x70\x6f\xa9\xda\x97\xa1\x13\x2c\xb8\x6b\xaa\x01\xee\x81\xdf\xce\x82\x57\x03\xb8\x8c\x80\xe6\xd9\xbb\xa4\x03\x40\x10\xc1\x7e\x6d\xb8\x71\x00\x97\x11\xf1\x0c\x7f\x1f\x27\xc4\xd1\x44\x6f\x57\xe3\xfe\x91\xe4\x4b\x98\x00\xce\xd2\xd4\x5d\x33\x02\x48\x9f\x9d\x7d\xf1\xe3\xe2\x8c\x03\x40\xb0\xcc\x7d\x9c\x50\x3d\xcd\x58\xee\x8e\x67\x58\xe3\x51\x4f\x33\xd0\xe8\xa2\x6b\x04\x80\x06\xe0\x2e\x27\x0c\xe8\x5d\x46\xb8\xdb\x2d\x58\x5e\x61\x83\x61\xef\x73\xf3\x80\xe9\x19\xa6\x8e\x1c\xb7\xf7\x7e\x3f\xe2\x0a\x2a\x96\xe7\xee\x9b\x11\xf6\x28\x4d\xf0\x36\x7e\xe0\xe5\x60\x02\x08\x1c\x27\xa9\xbb\x90\x70\x7b\xf5\xd5\x2c\x7b\x97\x32\x1f\xe1\x00\xf8\x77\x12\x60\x80\xfa\x01\xf8\x1f\x14\xff\x3b\x20\x48\x8e\xa4\x63\x38\xb8\x10\xcf\x2f\x76\x4a\xdc\x1b\xd0\xdf\x75\x4b\x04\x93\x94\x8c\x40\xb7\x13\x95\xae\x40\x77\xa9\xb6\x20\x66\x3b\xed\x1a\xd1\x2c\x94\x89\x66\x99\x4a\x34\x33\xd9\x66\x95\xa5\xc4\x66\xa5\x50\x96\x88\x6a\xb6\x45\xb5\x6b\xd9\x72\xae\x26\x15\x0a\xd9\x77\x02\x3a\x8b\x64\x93\xcd\x64\x92\x9d\x42\x86\xa9\x49\x54\x59\xca\x89\x95\x64\x49\x4a\x27\x58\x92\x10\x28\x92\x79\xa3\x2b\x52\xaa\x5e\x2b\x66\xda\x05\x36\x93\x28\x26\x4b\xd5\x62\x2e\x5d\xa6\xea\xac\xd8\x6d\xb7\x9a\x37\x23\x21\x3d\x24\x04\x59\x4d\x13\xd9\xa6\x48\x13\x42\xa9\xd3\x4c\x37\xb3\xa4\xd0\xcd\x0b\x9d\x4e\xa6\xd3\x69\x11\xad\x6c\xa7\xdb\xad\x31\x62\xb7\x23\x36\x2a\x85\x54\xe7\xad\x2e\xb4\x19\xb6\x53\xa6\x6e\x46\x42\x79\x48\xaa\x95\x6e\x26\x4b\x15\x68\xb6\x93\x48\x89\x52\xa1\xd0\xa1\xe9\x42\xaa\xd1\x2e\x37\x0a\x74\x3b\xd5\xae\x55\xcb\x59\xa2\x98\x15\x53\x1d\x52\x2c\xb4\x72\xd5\x5a\xb1\x24\xd6\x33\x89\xcc\xcd\x48\xe8\x0d\x92\x44\xad\xd2\xcd\xe6\x8a\x44\x32\x47\xa6\xa5\x2a\x95\xe8\x14\xd3\x25\x29\x55\x4c\xe7\x9b\x52\xa5\x49\x64\xbb\xe4\x5b\x29\x5d\xcf\x96\xa5\x66\x52\x2c\x0b\xf5\x36\x5b\x4d\xb2\xe5\x0e\x91\x7d\x89\xda\x3e\xb4\xc9\xb5\xaf\x28\xd4\xb6\xe5\xf2\xd0\x2d\xfd\xbb\x83\x2e\xb7\xd6\xbc\x62\xf4\x2b\xe6\xda\x33\x74\x83\x9a\xbf\x6f\x9a\x89\xac\xe4\xfe\x52\x30\xa8\xe2\x8a\x8d\x54\xc3\xed\xc1\xd1\xa4\x0f\xcd\xd9\x98\xda\x18\x66\xb3\x9e\x7a\xf9\x08\x9d\x39\xc6\x4e\x9c\xc1\x2e\x36\x6b\x2f\x0f\x2a\x53\x94\x26\x95\xa7\xcc\xf2\xd1\xb2\xd9\x5b\x9b\xdc\x36\xc7\xa7\x7a\x54\xa2\x4e\xf2\xae\x4f\x25\x20\x67\x92\x63\x68\x8a\xc5\x79\x96\x01\xaf\x18\x78\xc5\xc8\x8d\x4b\xf8\xcf\x57\x7f\x9f\xe3\xeb\x0f\xec\x6b\x54\x47\xf7\xf5\x15\xfb\xba\x0b\xe9\x5f\x7f\x6c\xf8\xfd\xea\x58\x23\x75\x9b\x4a\x6c\x20\x53\xfc\xef\xbc\x7f\x6d\xc6\xca\xd6\x4c\xef\xbb\xc1\xdb\xf4\xef\xdb\xa5\xdc\xd7\xfd\xb3\xfb\x46\xac\xcd\x80\x66\x3d\x15\xba\xe3\xae\x26\xde\x9d\xb0\xee\x04\xe1\x1f\x81\x10\x9b\xb5\x77\xf7\x2e\x01\x09\xe0\xf2\xfb\xbb\x3c\x09\x45\x34\x86\x77\x98\x83\x20\xa3\x69\xf8\xd7\xff\x3b\x67\x61\xe1\xa9\x07\xa1\xa9\x27\x4e\x4d\x7d\xc4\xf0\x73\xc3\xd4\x1f\xcd\xed\xfb\xa9\x3f\xd2\x8c\x13\x53\xbf\x9d\xb7\x47\xa6\x7e\xab\x3d\x8f\x4e\x7d\xc4\x79\xba\x34\xf5\x11\xb5\xe9\xe6\xa9\x0f\x5b\x3d\xf9\x71\x56\x4f\xbe\x9f\x7a\x80\xe3\x17\xe7\x9e\xc3\xff\x36\xfb\xcf\x33\x7b\xea\xe3\xcc\xfe\xc4\xdc\x73\x97\xa7\x3e\xa4\x1a\x7f\xdb\xfd\xf3\xed\x9e\x22\x69\x9e\xa5\x08\x8a\xa1\x3f\x34\xda\x83\xfb\xed\xfe\xfa\xe4\xff\x6d\xf8\x0f\x1a\x7e\x70\xf2\x3f\x30\xde\x7f\xc8\xe4\xff\x6d\xf9\x4f\xb4\xfc\x0f\x8c\xf8\x27\x92\x3d\xfa\xf2\xdc\xff\x9d\xe7\x7f\xa6\xdd\x7f\x60\xc0\xbf\x3f\xcf\xa7\xff\xb6\xfa\x8f\xb5\x7a\xc0\x02\x96\xe7\x58\x92\xe0\xfc\xd5\x3d\xe1\xcd\x7c\x70\x02\x8e\x66\xe0\xa4\xe4\xae\x8b\xec\xf3\x59\x23\x43\xac\x11\x9e\x4f\xfb\xaf\x60\x0d\xec\x59\x63\x49\x96\xbd\x7f\xd6\xb6\x26\x13\x85\xb5\x8f\xf6\x45\x54\x88\xb5\x7b\x67\xed\x17\x66\x6d\x63\x6b\x04\xc7\x51\x3c\x4e\xf3\x9c\x9f\x5b\x13\xb8\xc7\xdb\xc8\x18\x1b\x1e\x6b\x3c\x41\x90\x24\x4b\xe0\x24\xc3\xd1\xbf\x53\x2c\x4b\x73\x38\xfb\x97\xd3\x4c\x8f\x47\x80\xe3\x3b\x7f\xf2\xdf\xc6\xe3\x7e\x1e\x01\x05\x76\xd6\x17\x89\xc7\x5f\x58\x57\x0f\xf3\xc8\x11\x2c\xf9\xdf\xc9\x23\xf1\x8a\x71\x34\xc7\xf3\x24\xc7\x70\xbc\xc7\xa2\xcf\xa1\xe3\x42\xdb\x35\x4c\xbd\x27\xc3\x11\x34\x15\x14\x5e\x7c\xdc\x8c\x80\x3e\x46\x70\xc2\x95\x81\x53\xae\x6c\x27\x25\x13\xba\xc6\x1c\x45\xe6\x67\x33\x6b\x3e\x43\x0b\x64\xe8\x7d\x77\xbb\xea\xf2\x37\x02\x7a\x43\xb4\x7a\x28\xad\xbb\x47\x93\x3c\xaa\x28\x82\xdd\x3a\xbd\x0f\x92\xf2\x16\xc1\x47\x4b\x39\xc4\xcf\x6d\x52\x8e\xba\x6e\xba\x27\xd9\xf1\xa9\x62\xb8\xad\xdb\xfd\x28\x29\xfb\x08\x3e\x5a\xca\x21\x7e\x6e\xd4\xe5\x8f\xf6\xfc\xd4\x96\x2a\x1a\xe7\xb7\x8e\xff\x83\xa4\xbc\x45\xf0\xd1\x52\x0e\xf1\x73\xa3\x94\x1f\xf1\xcb\x57\x36\x32\x4f\x1d\x32\x8f\xba\x91\xb9\x3b\x68\xbe\x63\x96\x7f\xc5\x5e\x28\x8e\x51\x64\x42\x43\x90\x84\x14\xc3\xf1\x40\x25\x71\x00\x19\x55\x05\x2a\xce\x68\x38\xaf\x92\x8a\x86\x18\x40\x51\xaa\x86\xf3\x34\x07\x38\x8e\x83\xb8\x46\x03\x82\xe7\x91\x02\x29\x85\x7f\x79\xc5\x5e\x64\x04\x11\x64\x48\x82\xc5\x09\x15\xd1\xf8\xe6\x3f\xc0\x11\x9c\xa2\x50\x1a\xa3\x11\x1a\xa4\x01\xcb\xb2\x34\x0e\x69\x42\xd3\x64\x56\xe3\x39\x1c\xe1\x08\xc9\x0a\xcb\x03\xc4\xf0\x2a\x7c\xf1\x14\x07\x84\xba\x64\x98\x1f\x24\xfd\x03\x70\xe1\xe6\x19\xff\x6b\xea\x77\x9a\x01\x24\x47\x5d\xbd\xbb\xad\xdb\xd3\x0c\xb3\xc9\xa3\x99\xcd\x7c\xbe\xbb\x5e\x31\x40\x7b\xff\x6e\xff\xd9\x7f\xbb\xff\x63\x43\x9b\x20\x08\x42\x92\x65\x66\x93\x41\x7e\x51\x44\xcd\x72\xb3\x9c\x49\x0e\x4a\x0d\x82\x9b\x4f\x6a\x2a\xd9\x2c\x34\xe7\x31\x32\xd6\x4d\xe9\xac\xbd\xa4\xb3\x63\x13\x0e\xf9\x75\x92\xcb\x54\xf2\xcc\xdb\x3a\x53\xa1\x63\x95\xa6\x15\xa7\xcd\x2c\x1c\xe5\x57\x95\x54\x01\x2c\xad\x0c\x6b\x4d\x58\x7b\xcd\xa5\x72\xd4\x06\xb4\xd0\xa9\xb4\x4a\x35\x5d\xd8\x5f\xf4\x8c\xcd\x96\x13\x9c\xd2\xc1\xdb\xe6\xd4\x58\x9a\xf3\x75\x79\xd4\x25\x53\x64\x97\xb4\x2a\xb8\xda\x5d\xaf\xdb\xfc\xaa\x6d\xb6\xe4\x31\x0e\x17\xf4\xaa\xd2\x34\xd7\x03\xb4\x58\x51\x31\x9b\x5a\xa0\x39\xdf\x1c\xd6\xd9\x4a\xab\x1a\x17\xa7\x29\x2b\xd7\xd4\xd7\xf1\x04\x22\x5b\xe9\xb1\x07\x7f\x28\x51\x45\xb8\x9e\x10\xd5\x03\x32\xa1\xa3\x08\xc7\x97\xb8\xf9\xe7\x4d\xe8\x00\xaa\x2a\x08\x29\x3c\x2f\xfc\xd5\x2e\x5f\xab\xf0\x33\x86\x1f\xb6\x05\xee\x39\x7a\xfc\x82\xab\xa4\x46\x52\xa4\x4c\x68\xbc\x86\x2b\x10\xc9\x2a\x81\x78\x99\x86\x2a\x4d\x90\xa4\x4a\x72\x94\xaa\x22\x8d\x66\x58\x84\x03\x4d\x55\x54\x0e\xb1\xbc\x4c\x42\x46\xc3\x01\x8e\x00\xa5\xa8\x97\x6c\x81\x3d\xa7\xed\x0c\xce\xe0\x38\x7f\xf5\xae\x5f\xd2\x22\x39\x92\xe1\x2e\xd9\x02\x75\xa3\x2d\x2c\xf0\xb8\x94\x72\xe6\xe6\x62\x35\x9b\xd7\x19\xb9\xed\x36\x07\x95\x46\x5f\x22\xe7\x2d\x93\x4a\xc4\x15\xa2\x8c\xe4\xf2\x98\x4b\xa4\xfa\x0d\x29\x1d\x43\x20\x0e\x0a\xcb\xe6\xba\xcc\x52\x66\x36\x43\x0e\xa7\xc3\xcc\xa4\x3e\x4e\xab\xb0\xff\x96\x37\xfb\x8a\x98\xd4\xa7\x39\xaa\x3d\x1b\x71\xde\xdc\x79\xb6\x10\x54\xcf\x72\x29\xb3\x42\xcb\xf2\x0c\xcd\x87\x54\x35\xd7\x4d\x16\xe2\x88\x68\x14\xab\x1d\xa4\x88\xf1\x46\x62\x36\x03\xea\x3c\x53\x35\x46\x0d\x47\x9a\x17\x80\x2d\xcf\xa9\xac\x38\xa2\xe5\xa4\xc0\x4c\x5a\xf3\x54\x69\x41\x8f\x45\x26\xaf\x68\x4a\xad\x5e\x4a\x0e\x65\x72\x46\x2d\x88\x4e\xc9\x83\xaf\x9f\xb0\x85\x16\x15\x52\xa5\x94\xf0\x3f\x65\x0b\xec\x73\xf4\xf8\x45\x21\x21\xaf\xa8\x24\xc1\x68\x0c\x0e\x79\x8a\x22\x58\x55\x81\x2a\x92\x19\x9e\x57\x49\x8d\x41\x8a\x4a\xf2\x24\x4d\x2a\x0a\x4f\x12\x50\x51\x58\x95\x60\x29\x1a\x10\x2c\x49\x12\x8c\xac\x29\xdc\x25\x5b\x60\xce\x6a\x3b\x41\xb3\xf8\xf5\xbb\x24\x8e\x33\x14\xcb\x02\x9c\x25\x2e\xd9\x02\x79\xa3\x2d\x70\xe5\xc9\xba\x91\x9f\x77\x0b\x23\x31\xcf\xaf\x5c\x86\x18\xab\x15\x82\x95\xca\x8d\x26\xb7\x6a\x14\x9c\x25\x9f\xc7\x9b\x75\x65\x9d\xb7\xe3\xb9\x59\x62\x65\x55\xcb\xd3\x71\x43\x28\x35\x1b\x4b\x46\x5f\xe1\x83\xbe\x95\xc9\x80\xb4\x51\x34\xc9\x59\xae\x9a\x12\x67\x34\xd1\x70\x00\xa9\x05\xe2\x42\x60\x2e\x39\x1c\x80\x1c\xa7\x2c\x90\xd1\x6a\x16\x6b\x43\x56\x8f\xe5\x48\xd4\x2e\xc5\x87\xb1\x66\xcc\x99\x17\x8b\xf3\x7c\x91\xeb\xf0\xa2\x94\x00\x93\x45\x31\x57\xd5\xab\xb9\xb4\xdc\x58\xaf\x13\xe9\xc2\x94\x2d\x8e\x62\x43\xa2\x4d\xcc\xd5\x41\xa6\xea\x54\x17\x68\xa9\xcd\x06\xdd\x56\x12\xc7\x3d\xc8\xca\x09\x5b\x68\x36\x43\xaa\xf4\x3f\x66\x0b\xcc\x73\xf4\xf8\x45\x56\x10\xc4\x69\x16\x01\x45\x25\x00\x50\x09\x45\x93\x59\x44\x6a\x32\xcf\xd3\x9a\x4a\xd1\x8a\xca\x40\x8a\x22\x08\xa0\x91\x1c\x54\x14\x9c\x26\x08\x99\xa2\x65\x4e\xe1\x80\xca\x33\x34\x41\x5d\xb2\x05\xfa\xac\xb6\x93\x1c\x4e\x13\x57\xef\x12\x34\xcb\xf0\x1c\x4e\xb2\x2c\x73\xc9\x16\x88\x5b\x73\xa4\xf5\x34\xd1\xa1\x14\xbc\x9f\xad\xaf\x59\x6d\x10\xa3\x47\x1a\x48\xaf\xdb\x13\x31\xd7\xe7\x28\xbb\x94\xa8\x17\xf0\x36\xb5\x4a\x10\xed\xe6\x70\x30\x2e\x4d\xdd\x18\x21\xce\xe7\x09\xf1\x0d\x16\x33\x8c\x2b\x8f\xdb\xf6\xa8\x0c\x13\x19\x69\x32\xad\xf3\xb5\x98\xd6\x62\x53\x20\x09\x64\x2f\x1d\xf1\x6c\xa1\xba\x38\xcc\xe5\xac\x6a\x57\xaa\x36\x31\x1d\x49\xad\x49\x32\x37\xed\x57\x21\xaa\x96\x9c\x14\x9f\x6f\xb7\x25\xb8\xcc\xd5\xcb\xb9\x45\xc9\x59\xce\x8d\x51\xae\x29\x24\xd5\x58\xbe\xeb\x94\x57\x2d\xb1\x64\xeb\xe2\xbc\x5c\x60\x0c\xa1\xa8\xa4\x51\x5b\x2e\x98\x65\x63\x56\xc9\x2b\xa3\x99\xe8\xb6\x0c\xde\xcb\x91\xba\x27\x6c\xa1\xbe\x08\xa9\x52\x52\xf8\x9f\xb2\x05\xfa\x39\x7a\xfc\xc2\x2a\xb2\x4a\x28\x34\x03\x19\x99\xa4\x48\x0d\xe2\xb8\xc6\xb1\x88\xa0\x08\x86\x52\x11\x4d\x6b\x1a\xce\x22\x92\xd0\x48\x19\x50\x3c\xce\x51\x2a\xcf\x23\x9a\xa1\x91\x86\x2b\x2a\xa5\xe1\xc4\xc5\xf5\xc2\xd9\x15\x01\x43\xb1\x1c\x0f\xae\xde\x25\x00\xc5\x52\x1c\xc9\x50\x1c\x7e\xc9\x16\xc0\x8d\xb6\x40\xae\xf8\x62\x1a\x8e\x1d\xbc\xc2\x08\x95\x7e\x2c\x9f\x7c\x93\xe8\x56\x7c\xa1\x0d\x8a\x6b\xa7\x39\xcc\x35\xde\xcc\xd1\x1b\xe2\x4a\xa0\x22\x4c\x73\xf1\x7c\xda\x5c\x1b\xc3\xea\x62\x24\xb4\x13\xc4\x24\xc9\xf3\x5d\x18\x6f\xc9\x55\x22\x5f\x1f\x75\xec\xc9\x52\xe2\x45\x95\x2f\xc6\xed\x54\xc9\x9b\x3b\xcf\x16\x82\xeb\x05\x37\x0d\x87\x71\xad\xcf\x96\xc4\xb2\xe1\xf6\x07\xa3\x95\x2a\xda\x89\x26\x1e\x2f\xe1\xc6\x08\x22\x6d\x06\x9a\x32\x9e\x5c\x00\x45\xae\xae\xa5\xf8\xb4\xd4\x1f\xe9\xfd\x4e\xde\xe9\x0f\x44\x9d\x9d\x8e\xb9\x16\x2e\x2d\xb3\x89\x01\xf5\x56\x36\x86\xe5\x0e\x5e\x67\xaa\x66\x69\xed\xc7\x9d\xe6\x09\x5b\xa8\x95\x42\xaa\x94\x10\xfe\xa7\x6c\x81\x7a\x8e\x1e\xbf\x40\xc8\x92\xa4\xcc\x20\xc0\xab\xbc\x0a\x54\x0d\xe7\xa0\xcc\x41\x05\xc8\x32\x8b\x2b\x88\xa7\x00\x54\x65\x5e\x21\x01\xcf\x02\x46\x95\x65\xa4\xe2\x32\x47\x42\x4a\xe3\x59\xc0\x42\x8a\x60\xfd\xa6\x68\xe2\xa4\x5a\x93\x67\xb5\x9d\xc1\x71\xf2\xfa\x5d\x7f\xdb\x89\xe1\x01\x77\x71\xed\x8c\xdf\x68\x0b\xcc\x64\x5d\x26\xa8\x37\x42\xcd\x6a\xc9\xc2\xac\xb0\x90\xdd\xc5\x7a\x52\x85\x04\xbd\x58\x8e\x96\xb2\x3c\x77\x93\x54\x79\x18\xeb\xa4\x99\xaa\x39\x18\xf6\x3b\xb3\xc6\x30\xd5\x76\x47\x54\x51\x92\xe3\x5d\xa9\xda\x18\x4c\xf2\x62\x2e\x93\x8a\xf1\x4e\x7f\xe0\xac\xc9\xfc\xda\x99\xce\xa9\x78\xd7\x9b\x3b\xcf\x16\x02\xea\x29\xd1\x09\xba\xcd\x17\x9c\xa5\x55\xee\x94\x27\x8e\x22\x49\x6a\xca\x30\xe1\x4c\x5a\x26\xe3\x95\x05\x31\x1c\xb2\xa9\x54\xd3\xc2\xeb\x9d\x72\xe7\xcd\x74\x53\xc2\xb2\xa1\x75\x4c\x86\x19\xf3\xb9\xbe\x88\x77\xc6\x23\x03\x16\xe6\x43\x94\x9b\x48\x79\x6d\xcd\x17\x2a\xb2\x25\xe4\xde\xca\x9e\xf7\xaf\x9e\xb0\x85\x8a\x75\x4a\x9f\xfe\xe2\xb6\x40\xdc\x6e\x0b\xe4\x73\xf4\xf8\x85\x96\x19\x86\xa4\x14\x85\x47\x3c\xe0\x79\x4d\x25\x35\x59\x86\x1a\xce\xd0\xb4\x42\x53\x0a\xa4\x11\x2b\x73\x80\x50\x69\x86\x40\x0c\x89\x14\x88\x6b\x32\x21\xf3\x90\xe3\x65\xc0\xe1\x0a\xa5\xbd\x78\x8d\x1a\xd4\x49\xb5\x3e\x9f\x05\xb1\x04\x41\x9d\x8f\x0b\xbb\xbb\xdb\x7d\x4a\xc0\x71\x97\xd6\xce\xdc\x8d\xa6\x00\xdc\xb1\x54\x5a\xa1\xe1\x9b\xc9\x57\xd8\xd9\x3c\x31\xea\xa4\x1b\x85\x8e\x39\x4b\x14\x5b\xdd\x59\x37\xb6\xd2\x63\xab\x19\x34\xe4\x8c\xb0\xac\x88\xb4\x50\x76\x63\x04\x49\x36\xb2\x15\xb7\x21\xc9\x4d\x73\x50\x5f\x54\xe6\x63\x8b\xd1\xc9\xf5\x2a\xad\xa4\x2b\x96\xc2\xb5\x8a\x95\x4c\xc6\x9f\x3a\xcf\x14\x02\x53\x59\xef\xaf\xa7\x39\x1e\x16\xbb\x31\xb6\x30\xa1\xdf\x16\x24\xd3\x45\x2c\x4e\x1a\x6f\x4b\x33\x2b\x50\xa9\x05\x18\xd3\x85\x34\x55\xcb\x16\xc6\x65\xa9\x56\x34\x3a\x09\x1a\x66\xb5\x82\x90\x69\xdb\x64\x76\x69\x8d\xaa\xd5\xa5\xbe\x5a\x76\x92\xea\xa0\xb2\x82\xcc\x5b\x6b\x0d\x5b\xf5\x74\xc3\x33\x85\xd2\x09\x53\x28\xe9\xa7\xd4\xe9\x2f\x6e\x0a\xd4\xed\xa6\x40\x3c\x47\x8d\x5f\x18\x52\xe5\x39\x8d\x26\x19\x84\x18\x4e\x05\x32\xc1\xca\xb4\xcc\xf1\x1a\x41\x42\x8d\x26\x01\x90\x59\x9a\xe1\x21\x41\x69\x50\x03\x14\x4e\x42\x15\x97\x69\x42\x66\x48\x52\xc6\x59\x19\xf1\xfc\x25\x53\x38\xaf\xec\x1c\x73\xed\x9e\xbf\x9d\x46\xd1\xfc\xa5\x55\xf3\xad\x05\x24\xa2\xf2\x36\x00\xd2\x8c\xb6\x70\x39\xcf\xb6\x29\x73\x55\x9e\x37\x97\x19\xb2\x35\xb1\x86\xb1\x79\x5a\x28\xbb\x49\x50\x20\x4a\x6c\x82\x65\xde\xfa\x1c\x51\xd5\x9d\x99\x50\x1f\xd7\xf1\xa5\x9e\x9e\x00\x6d\x60\x34\x88\x85\xa4\xcf\x5b\xed\x5a\x72\x54\x6f\xd3\xb3\x52\x85\xa4\xa8\x7a\xc9\xf7\xc5\x1b\x2b\xa8\x78\x5a\x9a\xdb\xff\x23\x78\x8a\xea\x1c\x3e\x2f\x84\x4a\x75\xe8\xcf\x72\x9f\xb5\xb3\x59\x12\xf5\xa7\xf3\xa6\xd3\x16\x2b\x9a\x30\x9a\xb7\x9c\x89\x20\x10\xf1\xb7\x1a\x9e\x1f\x54\x84\x74\x4e\xcd\xca\x55\xc2\xa9\x1b\xb3\xfc\xd2\x6c\xb2\xa3\x55\x6c\x8d\x96\x6f\x33\xa7\xb3\xc4\xa5\x62\x67\x65\x15\xe8\x79\xab\x9a\x9b\xa7\xd6\x29\x33\x96\x1e\x77\xd3\x65\xd4\xf7\x6c\x21\x77\xc2\x4a\x32\xd5\x53\x9a\xf6\xbf\x63\x25\xe0\x39\x1a\xee\xbd\x07\x07\xc3\xfd\x3d\x27\xc0\xb3\xf8\x77\x1c\x7c\xc7\x01\x86\xe3\x3f\xbc\xff\xce\xea\x32\xcf\x31\xe4\xf9\x80\xb0\xbb\x4b\x11\x3c\xc5\x33\x2c\xc1\x5f\x5a\x15\x9f\xd6\x74\x9f\xa4\x9f\x3d\x29\xe7\xaf\x44\xa7\x60\x50\xab\xf8\xaa\x5e\x48\xb0\x29\x33\xc5\x67\x09\x7c\x39\x48\xc4\x1c\x5c\x77\x9d\x45\x6e\xb1\x06\x1d\xb5\xde\xee\xc2\x44\x1e\xa6\x3d\x25\x16\x4f\x28\xf1\xe9\x6b\xa7\xc4\x82\x90\x18\x7e\x02\x23\x4f\xbd\x5e\x7c\x65\xba\xbe\x29\x77\xc3\x2b\x6a\xa3\xee\xd1\x9d\x79\x2f\xcf\xd9\x03\x68\x67\x2c\xee\x0a\x98\x70\x6b\x73\x44\x30\xe4\xbe\x8e\x4a\x03\x86\x7f\xc5\x40\x34\x30\xd4\xbe\x04\xc5\x72\x5e\x6b\x4d\x34\x30\xf4\x6e\xf5\x4e\xe1\xb4\xb7\x19\x1d\x0d\x0c\x13\xea\x92\x24\xa3\x81\x61\xc3\xcd\x96\xd1\xc0\x70\xa1\xee\x3f\x2a\x1a\x18\x3e\xdc\x1f\x19\x0d\x0c\xc0\x43\x1d\x7b\x11\xb9\x02\xef\xba\xe2\x22\xc2\x09\x77\x9e\x45\xa5\x87\x0c\x77\x77\x45\x84\x43\x1d\x77\x1c\xd1\x11\xc1\x84\xfb\xa4\x22\x82\x61\x8e\x3b\x73\xa2\x52\xc3\x86\x1a\x96\x22\x82\xe1\x8e\x3b\x58\xa2\x52\xc3\x87\x1a\x61\x22\x7a\x40\xfc\xb8\xd3\x23\x22\x35\x04\x38\x06\x43\x3d\xe7\x1d\xdf\x4f\x39\x3c\x7f\xf9\xf5\x6c\x1b\x67\x79\xeb\x69\xfa\x33\xaf\xba\x7e\x38\xc6\x05\x22\xc9\xd1\xd1\xda\xfd\x07\xdc\x3f\x6f\xe7\x75\xe0\x78\x2f\x06\xfa\xfa\x03\xfb\x8a\xff\xce\xf9\xa9\x96\xd7\xee\x73\xe8\x03\xa2\x41\xb0\x0f\xc8\x7f\x97\xb0\xfd\xf5\x07\xf6\x9f\xaf\xea\xd7\x1f\x18\xfd\x8a\x7d\x35\xbf\xfe\xc0\xa8\xff\x3b\x3e\x7f\x81\xbf\x62\x5f\xe5\xd9\xca\x30\xf5\x33\xa7\x5f\x82\xf7\x2e\x1e\x81\x40\xa3\xd1\x7b\x28\xbb\x63\x38\x47\x37\x2f\x1e\xc7\x08\xe2\x7b\xce\x59\x8a\x63\xe4\x4f\x69\x0c\xfe\x80\xd7\xac\x9c\xd2\x8a\xa3\xe3\x57\xfb\x0f\xd4\x69\xad\xe0\x4f\x6b\x05\x7e\x49\x2b\x36\x01\xcd\x53\x0b\xfe\x6f\xb5\xf8\xeb\xa8\x45\x30\xe7\x3c\x7c\xe0\x4e\xa9\x05\xf8\x9d\xa0\x4f\xa8\x05\x77\x51\x2b\xa8\xad\x52\xd0\xb7\x2a\xc5\xee\xb8\xd4\x63\x4a\xb1\x3b\xb7\xf5\xb8\x52\x44\x3f\x72\x77\x5e\x29\x22\x37\x39\x7e\xc0\x7b\x9f\x4e\x28\xc5\xd1\x0a\xe2\xf0\x81\x38\xad\x14\xc0\xbf\x8e\x95\x82\xbf\xe2\x2a\x0e\x4b\x7c\x4f\x3b\xc0\xfe\xfa\x5b\x4d\xfe\x3a\x6a\x12\x5c\x21\x1e\x3e\x30\xa7\xd5\x04\x3f\x19\x52\xf0\xcb\x7a\xb2\x53\x8f\xbf\xb5\xe2\x2f\xa3\x15\xc7\x27\x3e\xf7\x1f\xf0\x7d\xa3\xc1\x7f\xbe\xba\xd6\xa3\x87\x7e\x35\xdb\x1a\x3f\x2a\xe1\x5f\xf8\xa4\xe6\x07\xbc\xe0\xec\xfc\x4c\x6d\xab\x18\xfb\x0f\xcc\xfb\x99\x7a\xe0\x64\xfe\x61\xa6\xa2\x67\x57\xbf\xf0\xe9\xcc\x0f\x78\xb3\xe0\xa9\x99\x3a\x3a\xd9\xb9\xff\xe0\x27\xef\xcc\x6d\x27\xe7\x5c\x7b\xe6\xb8\x08\x3d\x6a\x35\x1e\x18\xeb\xe1\x53\xfb\xbf\x88\x8d\x7d\x78\x7e\x7d\x5c\x99\xdb\x7f\xc0\x7f\xf2\xcc\x3d\x60\xd0\xbf\xc6\xcc\x7d\x42\x1c\x3b\x3a\x85\xbb\xff\xc0\x44\x9e\xb9\xe8\xfe\xef\x43\x6c\xee\xa7\x79\xcb\xcf\xb2\xb9\x6d\xf5\x79\xff\x81\xf8\xc9\x33\xf7\x34\x9b\xfb\x59\x33\xf7\xf1\x36\x17\x2c\xd4\xef\xff\xe6\x02\x67\x21\xb5\x99\xa9\x6e\x79\x89\xf8\xaa\x5d\x4f\x2e\xfe\x0b\x6f\x1f\xb5\xa7\xeb\x07\x33\x1f\x7c\x25\xf0\x3d\x52\xdb\x6e\x28\xec\xff\xa6\x3e\x54\x6a\x0f\xe8\xf2\xaf\x25\x35\x7f\xe3\x63\xff\x37\xfe\xb1\xba\xf6\xc0\x72\xf0\x57\x92\xda\x76\x83\x66\xff\x37\xf3\xb1\x52\x7b\xa0\x2c\xfb\xd1\x52\xbb\xb2\xd9\x73\xe2\x47\x38\xa3\x6e\xf4\x6c\x7f\x88\xf3\xe4\x26\x0f\x7e\xf6\xb8\xaf\xdf\xcf\x0c\x5e\x31\x6a\xfb\x3a\x5b\x7e\xf7\x3e\x1f\x8a\xde\x57\xe0\x34\x38\x72\xd0\xeb\x51\x51\xee\x50\x8f\xf3\x9a\x91\xce\x6d\x9a\x5e\x22\xea\xfc\x19\x64\x72\x47\xd4\x11\x46\xef\x4b\x0e\x0f\x53\x45\x79\x6f\x23\xa7\xce\x6f\x4e\x86\x69\x08\xee\x73\x9c\x16\x0c\xfb\xb2\x43\x77\x92\x86\xe0\x37\x3b\xd1\xf8\x32\x64\x00\x60\x38\x06\xa7\x09\x96\x63\x01\x89\x93\x97\xfa\x34\x2e\x91\x75\xfe\x48\xea\x7e\xbe\xe8\x30\x55\x77\xcc\xd7\x29\x32\x89\x9b\x94\xf5\xfa\xaf\x55\x3e\xa0\xbe\xa7\x7f\x3c\xea\x64\x37\x0e\x7e\x51\xe5\x2e\x03\x22\x42\xdb\x5b\x91\x01\x91\xe1\x0d\x91\xa8\x80\xa8\x70\x11\x3d\x2a\x20\x3a\x5c\x66\x8d\x0a\x88\x09\x55\xe6\x2e\xd8\xd6\x65\x40\x6c\x08\x50\x64\x61\x73\xa1\x0a\xd4\xb9\xde\x9c\xab\x80\xf8\x70\x29\x2b\x2a\xa0\xe3\xfe\x9c\x47\x14\x09\xbc\x5b\xfa\x47\x86\x44\x84\x96\xa2\xd1\x69\x7a\xb7\x34\x8a\x0c\x89\x3a\xce\xd5\xcf\x75\x7f\x5c\x07\x44\x1f\x03\x8a\xce\x1b\x73\x9c\x07\x47\xa7\x88\x0d\x25\xd4\x91\x01\x71\xc7\x39\x66\x74\x8a\xf8\x63\x40\x91\x0d\xf7\xa8\x67\x87\x79\x80\xa2\xa3\xae\x1d\xe6\x52\xd7\xce\xbd\xbf\x93\xfb\x8c\xbe\x9d\x6b\xbf\x36\x78\x4f\xe7\xce\xd9\x5f\xc5\x7d\x42\x4c\x0c\xfe\x20\x1c\x85\x08\x16\x91\x2a\xab\x70\x94\xa6\xca\x2c\xaf\x32\x2c\xce\xf3\x04\xa1\xd0\x04\x84\x90\xa5\x09\x4d\xa5\x71\x0e\x57\x15\x95\x22\x49\xa8\xf1\x38\x50\x54\xc0\x72\x0c\x0e\x79\x9a\x95\x89\x97\x57\xcc\x4f\xf2\xa2\x97\x5a\x02\x67\x13\x98\x5d\x4f\xf6\xf9\x97\xc3\xb0\xd4\xa5\x57\xc7\xb0\x14\xfd\x12\x0a\xed\x7e\x33\x77\x81\x19\x20\x83\x1c\x8c\xad\x1c\xd7\xc8\x8c\x52\x71\xa4\x2b\x24\x5b\xe9\xb8\xd9\x42\x61\xdd\x6e\x71\x8b\x96\xf1\x96\x80\xc9\x19\x5d\xa4\xbd\xe3\x91\x6f\xde\x43\xde\x61\x03\x31\xd4\x6b\x9c\x38\xfc\xe9\x0d\x4d\xb4\x5a\xd2\x76\x4c\x12\xcc\x12\x6a\xd6\x6a\xcc\xf4\xd2\xbc\xea\xa6\xd8\x44\x3f\x57\x24\x25\xc4\xab\xad\x8a\x96\xc9\xc5\xf2\x06\x9d\x9f\x37\xcb\xb1\x37\xc1\x65\xbd\x13\x0e\xe9\x74\xab\xe5\x1f\x68\x10\x0a\x29\x2e\x53\x59\x76\x34\x32\x59\x1a\xb4\x0a\x73\x72\xda\x5f\x3b\x0c\x9c\x11\x59\x58\xca\x66\x71\x87\x4e\x90\x44\xad\xd5\xac\x1a\x6e\xdf\x3f\x62\x90\xb6\x84\xa5\x7f\x82\xce\xc3\x9d\x38\xd9\xdf\x9d\xd9\xf3\x53\x95\xe0\xac\x9f\x19\x0f\xf9\x3a\xd9\x65\x87\x0c\xdd\x55\x6b\x05\xa2\x26\x64\x07\xd9\x45\xd7\x70\xe7\x43\x34\x2b\xc5\x48\xb3\x92\xac\x90\xfd\x8c\xde\x1c\xae\xf9\x76\x06\x52\x95\x2e\x47\x25\x51\x49\x1f\x0f\x47\x80\x36\x94\x61\x6c\xd4\x4d\xdb\x1d\x4d\xa6\x8a\x56\x6a\xda\x9f\x35\xaa\xd6\x9f\x2f\xc1\x66\xf9\xe0\xe1\x88\xc3\x9f\xa9\xc3\x97\x3e\xaf\x65\x22\x19\x17\xca\x14\xdd\x4d\xa4\x48\x37\xdb\x4a\x97\x41\x8d\x14\xf0\x12\x1a\x56\xb8\x7c\x8d\x31\x25\x20\xf0\xa8\x6d\xa8\xab\x9c\x1b\x78\x83\x81\xfe\xa0\xbc\x12\x76\x5d\xf5\x1f\x7d\x60\xbe\x04\x75\xdd\x6e\xc4\x7d\xae\x5c\x7d\xbe\x48\xcd\xca\x6d\xa1\xca\xb3\x35\x50\x6b\xb8\x4d\x75\x21\xa5\xb2\x93\x54\x3c\xd9\x44\x93\xb5\x5a\xad\x74\x46\x96\xa9\x18\xc5\x56\x58\x5f\x6a\xad\x56\x7d\x8b\x5f\x8f\x27\x06\x5c\x8b\xe4\x17\x83\x1c\xa8\xdb\x3c\x63\x29\x6c\x79\x6c\xbb\x7d\x62\x90\x58\xf2\xc5\x72\x55\xe5\x87\xad\x96\x98\xb3\xbb\x75\x5f\x9e\x73\x7b\xb1\x3d\xa6\xd5\x6a\x35\x76\xaf\x96\x70\x65\xbd\x53\x63\x44\xd6\x4a\x15\xf1\x62\x35\xb6\xe8\xd6\x93\xfc\xba\x33\xef\xb4\x1a\xe4\xd2\xa8\x18\xdd\x59\x5d\x06\xa9\xf9\xb8\x5a\x44\xfe\x2b\x5a\xca\xb4\x5d\x08\x6a\x89\x3d\x95\x98\x22\x2a\x43\x7d\xb0\x2c\xc1\x66\x85\x67\x12\x6b\xcd\xe1\x11\xae\x58\xb6\xf4\xd6\x59\x27\xda\xf9\x61\xda\x2a\xb0\xc3\xf9\x70\x11\x32\x82\x74\xab\x89\x6f\x27\xba\xd8\xa6\xd2\x38\xea\x97\x19\x61\xc5\x27\xf1\x8a\x93\x11\xf5\xb9\x02\x58\x00\x9a\x3c\xd7\x1d\x50\xe3\xe2\x70\xcc\x57\x59\x7a\x98\x24\xe7\xde\xf8\x66\xab\xd5\xdc\xb2\x62\x55\x16\xdd\x78\x5a\x8d\x2b\xb9\x95\xd4\x9c\xc6\xd1\x34\x5b\x5e\x4f\xa6\x6c\x57\xb5\x16\x8a\x56\x5f\x0f\xb3\xda\x5b\xba\x55\x4b\x16\x08\x71\x7b\x2e\x21\x6f\xb4\xf5\x83\x92\xa5\xc3\x5a\xbf\xd7\xc9\xea\x5e\xe7\x3c\x1d\x4c\x56\xa3\xf3\x5c\xa6\xed\x9c\x22\x1c\xc3\x13\xde\x9d\x98\x0b\xbb\x8a\x63\x71\x3d\x11\xbf\x18\x05\xbf\xe8\xe1\x2f\xed\x81\x6c\x9f\x67\xbb\x45\x4e\x60\x07\x23\x5d\xac\x20\x5c\x6d\x36\xd9\x56\x56\x49\x55\x97\x4c\x35\xbe\x18\x65\xa7\x0a\xd9\x4c\x01\x1a\xe6\xc9\x9c\x01\x0e\xf4\x7b\xaf\x4f\x78\x60\x0e\x1f\xb1\x41\x88\x9b\x75\xa1\x3a\xb0\xc0\x72\x3d\x83\xab\x93\xa7\x16\xb7\xf4\x3d\xca\xdf\x62\x0f\xc4\x57\xf7\x3b\x63\xc8\x23\x3a\xde\x1a\xe3\x31\x3d\x1b\xdf\x5f\xde\x97\x61\x1f\xef\x7d\x1e\xfe\x14\xfa\xac\x32\xc3\x0a\x27\xe9\xdb\x4e\x6b\xd6\xaa\x9f\x53\xc6\xbd\x3d\x0a\x87\xf1\x77\xc6\x84\x07\xf4\x27\xf1\x06\x93\x9c\xa0\xed\x29\xe7\x0e\xf2\xab\xee\xee\xb3\xf1\xf3\xa4\x7b\x68\xf3\x81\xf9\xb8\x53\xbf\x1e\xf0\x99\xc5\x62\xb5\xa3\xf1\x07\xa1\x2f\xf6\xf4\x24\x2e\xc8\xfa\x70\x79\xe3\x95\x83\xe8\x7f\x4a\x0c\x7b\x80\xff\x64\x6c\xee\x13\xee\xfb\xfc\xd3\x4c\xe7\x9e\xc1\xdf\xc3\xfa\x19\x5d\x3e\xa9\xc6\xb8\x58\xbe\xa0\x9f\x41\x55\x9c\x26\xb4\x5c\x98\xff\x87\xf5\x33\x7a\x8e\x95\x1b\x76\xa4\x45\xe2\x41\xfd\x0c\x38\xf4\x7b\xe7\x2f\x35\x83\x2b\x1f\x88\x37\x75\x7e\x4e\xfc\x2e\x31\x3e\x4f\xcb\xc1\x9f\x3e\x11\xff\xbb\x09\x3a\x8f\xff\xd1\x78\xf3\x40\x4e\x88\xe7\xc9\xd4\x69\x7f\x7e\x52\x3e\x9f\x4e\x9f\xba\x6e\x37\x85\xce\x85\x78\x13\xb8\xc6\x79\x18\xfe\xea\xd9\xf9\x5f\xa4\xfc\xeb\xe9\xf8\xc3\x2f\xb5\x3a\x8f\x5f\x38\xe0\xcf\x45\xc2\x2f\xfc\x55\x72\x7e\x6f\x50\x20\xc7\xf5\x39\x9f\x59\xa4\xe5\x52\xf4\x34\x59\x11\x97\x93\x6a\x9c\xb4\xb2\x52\x6c\x0d\xd8\xda\xca\x70\xc0\x48\x2b\xa5\xbb\xe3\x6a\x5b\xb7\x67\xf5\x58\xc3\x7f\x80\x1d\x3b\x83\x66\x08\x5e\xf2\x9d\x40\xcf\x9e\xa9\x0e\xf8\xe0\xc8\xf8\xfb\x8b\x68\xf8\xff\xf4\xd6\xe4\xff\x01\x53\x46\x84\xb0\x01\x8a\xea\x60\xd6\xb0\x47\x7d\x20\xda\x6f\xa2\x80\x4a\x5a\xc2\x28\x10\xb1\x1a\x43\xad\x59\xa4\x70\xb9\x38\x12\x61\xa2\xde\xa8\x80\xee\x9b\xad\xf3\x83\xb5\x9e\xa7\x56\x49\x58\xef\x74\xc6\xf9\x55\x83\x69\xe9\x6d\x57\xe5\xe7\xfa\x4c\x2f\x4f\x33\xb4\x94\xd4\xff\xfc\xd3\xdb\xc3\x34\x2d\x13\xed\x4f\xf1\xdf\xf2\xaf\x6b\xcf\xfc\x2d\xa4\xeb\x75\xbf\xe0\x6f\x66\x6b\x90\x67\xa0\x8c\x90\x8c\x23\x42\x66\x37\x1f\x29\x56\xe5\x34\x16\xc7\x49\x05\xd2\x2a\x89\x78\x9a\x25\x29\x86\x26\x14\x92\x93\x49\x82\x83\x88\x21\x20\xa7\x00\x19\xc8\xa4\xca\x92\x2f\xaf\x18\xf7\xbc\xda\x14\x7d\xa5\x36\xc5\xe0\x0c\x79\xbe\x36\xe5\xdd\xa5\x5f\x42\xbb\x45\x8f\xd6\xa6\x52\xa1\xc9\xff\x45\x6a\x53\x23\xab\xe8\x6b\xaf\xf7\x39\x79\x72\x8d\x16\xa8\x4d\xe5\xa8\x35\x97\x55\x97\xc9\x92\xc2\x77\x07\x6c\xae\xd4\xa5\xc8\x98\x6e\xd6\x8a\xf4\x18\x35\x4b\x8d\x4c\x99\x2e\x49\xd3\xac\x13\x03\x1a\xb4\xda\x49\x33\x19\xc3\x73\x49\xd2\xae\x75\x06\xdd\xb6\x65\xe8\x15\x53\x4c\xa4\xc6\x0d\x69\x59\xed\x6a\x92\xc0\x17\xab\x55\x29\x4b\xb7\xd4\xc5\xe2\xf3\x6a\x53\x8f\xe6\x4d\xa9\xfd\x3a\xf6\x91\x75\x31\x3b\x76\xb6\x6f\xb3\x8a\x94\xf7\x7a\xb4\x3f\x52\x9b\xf2\xd6\xe5\xde\xf5\x40\x9c\xcf\x2a\x60\x14\x9c\x8f\xb3\xb5\x9c\x80\x26\x45\x89\xa5\xe0\x80\x23\x58\x2b\x08\x5c\x57\x62\xf9\xf3\xf0\x47\xaa\x25\xa5\x0e\x71\x21\x7b\x90\xcf\x27\xe6\xfa\x75\x2b\xcd\xe9\xb7\xe5\xfa\x5e\xad\x20\x7c\x55\x85\xe3\x5c\xf7\x5e\x9d\x7d\x20\x97\xc0\x69\x63\x7d\xba\xb6\xf2\xae\xd4\x5f\xd0\x3b\xab\x30\xe5\xde\x7c\x05\x73\xfb\x9f\xe2\x33\x9e\x52\xff\xbd\xb0\x36\xd3\x9f\xc1\xdf\x61\x2d\xed\x7f\xbe\x37\x0f\x7a\x40\x3e\xfe\xfc\x9d\xd2\xcf\xc0\x25\x0a\xc7\x6f\x98\xfa\x44\xfa\xd2\x6f\x6e\xc5\xba\x46\xdf\xc3\xf6\x1d\x3d\x57\x3f\x2f\x3f\x5f\x5f\xbc\x5a\x14\x77\x52\x75\x0e\xf4\x3e\x60\xdf\x0f\xe8\x77\xbb\xad\xcf\x2f\xd5\x26\xdb\x6d\x7d\x16\x7f\xb7\x76\xda\x5f\xbe\x7d\x3f\xaa\xff\x8f\xee\x57\x3d\xc0\xbf\x04\x1b\x13\x41\xcc\x31\x92\xa2\x1c\x72\x82\xf3\xf3\xf3\x40\xad\xec\xd1\x9c\xe1\x01\xfd\xf4\xf6\xf3\x12\xc9\xf2\xa0\x93\x0d\xef\x67\x1d\xae\x80\xfd\xf8\xd7\xbd\x7b\x01\xec\xd8\xd1\x4b\x87\xf9\xf4\xe6\xf7\xdd\xda\xf3\xca\x3a\x30\xf7\x64\xfc\xef\x13\x83\xb3\xf8\x4b\x87\xf1\xd1\xfc\x5b\xf4\xf9\x39\x9f\x1f\x9c\x96\xcf\x67\xd3\x27\x25\xd5\xc5\xe9\x5a\xe5\xf6\xfa\xf3\xcf\x13\x35\x85\xc0\x7a\x21\xca\x9a\x7e\x48\x1d\xe0\x05\x72\xcf\x9b\xe6\x32\xac\x4b\x8f\xd6\x34\xee\xc1\xbf\xad\x29\x0c\x06\x95\x85\x4a\x8a\xb9\xe5\x1a\x18\x15\x47\x5f\x0e\x06\x1a\x93\x54\xc5\xf9\xf8\x8d\xae\x2e\x4b\x5d\x76\xb8\x20\x2c\xb4\x66\x5b\xfc\xb4\xdf\x2d\x28\x45\xb6\xaa\x17\x91\x9b\x46\x52\x1f\x1a\x05\x21\xa6\x54\xc5\xf2\x5b\x89\x4c\x27\xfa\x1c\x9e\xc2\xdd\x84\x80\x6b\xa3\x16\x99\x12\x3e\xb7\xa6\x40\x41\x1c\x2a\x80\x41\x3c\xc5\xb1\x00\x07\x3c\xcf\xd0\xbc\x8c\x23\x0e\x90\x40\x46\x38\xa3\x6a\x34\x4f\x51\x88\x66\x39\x9c\x51\x70\x55\x66\x09\x82\xa3\x79\x44\x21\x0e\x42\x15\x20\x6f\x7d\xcf\x6e\x6b\x0a\x51\x0f\xa8\x04\x6a\x0a\xec\xb5\x9a\x02\x41\xf3\xfc\xf9\x1f\x09\xd8\xdc\x0d\xfc\x24\x86\xdf\x38\xea\xeb\xec\x9d\xfe\x3c\x50\x53\x08\xfb\xb7\x77\x35\x85\x5f\x77\xef\x47\xdc\xf3\x53\xcd\x24\xe7\xc5\x5a\x79\x91\x75\x33\x19\x66\x4c\x54\xf2\x78\x2e\xb7\x26\xd3\xb5\x6c\xa6\xb9\xe4\xdb\x2b\x7d\x2a\x75\xb2\x52\xb5\x22\xe1\xdd\xc9\x30\x6e\x35\xa4\x91\x9b\x17\x66\x15\x93\x26\xd2\x6f\xb1\x32\xab\xe5\xc6\x73\x25\xab\x69\xa5\x62\xab\x94\x4c\xa7\xa4\x54\x43\x4f\x9b\x76\xae\x5a\xba\xb3\xa6\x10\xb8\xfe\xeb\xf6\xda\x02\xfe\x31\xb4\x36\x4f\x04\x72\xab\x7b\x73\xa7\xcd\xda\xd8\x17\xe0\xa1\xce\xfd\x1e\xf7\xe5\xb5\xf1\x13\xf1\x9f\xe1\xfd\x16\xfc\x1f\x92\x7b\xdc\x11\xfb\xc5\x8f\xc0\x7f\x47\xee\x23\x1c\xf0\x47\xef\xc3\xf0\xa7\xe2\xe7\xf4\x99\xec\x7b\xad\xce\xec\x23\x0a\xc7\x6b\x85\xcf\xee\x63\xf0\xaf\x0b\x7d\x0c\xa4\xf4\x56\xb9\xd6\xc7\xf0\xd7\x5c\x5b\x7a\xe3\xbb\xc2\x4f\xa8\x1d\xf9\x05\xa1\xdb\x6a\x47\xcb\x0a\x1b\xfe\xa5\x8d\xa0\x7f\xf8\xec\xbe\x02\xbf\x59\xe0\xa6\xbe\x82\x42\x6a\x36\x3b\x5a\x1f\x9f\xcc\x85\x33\x81\x01\x11\x7c\x4b\x70\x7f\xeb\xcc\x46\xee\xa7\xf9\xb6\x7b\xf0\x6f\x73\xe1\x6e\x81\x73\x45\x56\x40\x78\x57\x9e\xca\x5d\xce\xac\xea\x83\x8a\xd2\x12\x95\xb7\x46\x16\xc8\x85\xa4\x05\x14\x05\x08\x1c\x59\x33\xc6\x8d\x58\xbf\x44\xb4\xf1\x61\x92\x8a\x69\x66\xb7\x65\x52\xac\xcb\x19\x90\x5f\xa8\x3c\xb7\x70\x9b\x8b\x5c\xb3\x84\x4b\x65\xa1\x8d\x9c\xbe\xb0\xf8\xdc\x5c\x98\x50\x71\x95\x60\x28\x95\x47\x04\x22\x49\x86\x52\x08\x5e\x83\x1a\x03\x19\xa4\x70\x80\x86\x1c\xe4\x10\x03\x29\x06\x11\x24\xce\x33\x2a\x04\x14\x00\x1a\xc1\x6f\x3e\xa9\x2c\xc7\x7a\x3f\xcc\xc0\x3c\x2f\x17\xbe\xd6\xfb\xcd\x90\xdc\xf6\xd7\x26\x2e\xde\x3d\x3a\xfb\xf4\x68\x2e\x7c\xb5\xf7\xfb\xa7\xe4\x66\xa9\xf6\x90\xa9\x5e\xab\x7d\x04\x72\xe1\xac\xa5\x21\x52\xd6\xd5\x41\x42\x65\x18\x4a\xb0\xa7\x76\xa1\x38\x20\xe2\x06\xa4\xe4\x22\xa4\xbb\xa3\x4c\xbc\x54\x64\x67\xe9\x56\xad\xd0\x6e\xc8\x13\x7c\x34\x91\x0b\x49\x88\xcb\xe9\x1a\x2d\x88\x66\x32\x9b\x8a\xa7\x57\x79\xbd\xd0\x27\x1b\x86\x54\x9e\x14\xc8\x6c\xba\x36\x6c\x57\xb9\x4f\xce\x85\x7f\x62\xad\xe9\xaa\xbc\x2f\xe4\xc2\x81\x7d\x9d\x28\xb9\xe8\xbb\x9e\xe3\xdb\x7b\x3e\x12\x4f\xc6\x7f\x6f\xcf\x49\x38\x17\x7e\x76\xbc\x78\xaf\x5b\x97\xe3\xc5\x4f\x8c\x57\xc2\x01\xff\x5f\xb3\xe7\x1a\x4c\xca\xc3\x6b\x3d\xd7\x81\x7d\xb1\x5f\x2d\x17\x16\xce\xd7\xc1\x05\xe1\x58\x3f\x7e\xb5\x5c\x38\xab\x80\x61\xfc\x5a\x2e\xdc\x14\x7e\xed\x5c\xf8\xa4\xfc\x03\xfe\xe9\x17\xce\x85\xb3\x62\xdc\xb9\x9e\x0b\x07\xd7\xc5\x11\x7c\xcb\xbb\x5e\xb3\x9f\xe8\xdb\xee\xc1\xbf\xcd\x85\x51\x9f\x67\xd5\x59\x82\x28\xa5\x49\xdb\xd6\x93\xb3\xa9\x63\xcd\x2a\x72\x2c\x6f\xf7\x1d\xd7\x1e\x19\x4d\x99\x5b\xcc\x67\x54\xab\x25\x4e\xde\xa4\x99\x59\x6f\x8f\x1c\x2b\x6f\xd7\x9c\x56\x76\x28\xd4\x95\x9c\x52\xe1\x3a\xb9\xb1\x30\xcd\xaa\xe5\x1c\xce\x0c\x6d\x45\x69\x65\x6a\x6f\xa9\x4f\xce\x85\x15\x16\xca\x24\x47\x91\x1a\x0e\x71\x85\xd2\x10\xcb\xab\x48\x41\xb8\xa6\x01\x99\x23\x79\xa0\xb1\x90\x57\x49\x4a\xa1\x58\x45\x56\x59\x44\xd2\x38\x49\x69\xac\x4c\x70\x1a\x83\xab\x9a\xe2\xfd\x62\x0d\xe9\xbf\x86\xf4\x19\xbd\x66\xd4\xb5\x5c\x98\x25\x38\xfc\xec\x0f\xec\xef\xef\x1e\x1d\xde\x7e\xb4\xd7\x2c\xbc\x57\x10\xc8\x85\xfd\xb5\x78\x24\x7b\x0c\xf7\xf4\x7a\x57\xa0\x37\xac\x1c\x37\xe5\x91\xc5\x15\x84\x61\xbd\xac\x71\x4a\xb5\x5c\x36\x84\x54\x67\xa5\x2f\x63\x39\xfc\x4d\x6d\x5b\x25\xaa\xa5\x53\x62\xa1\x22\x08\xf9\x4e\xda\x74\x15\x77\x90\xcc\xad\xaa\x94\xe2\xb4\x9a\xab\x05\x6c\x93\x44\x3e\x3e\x44\xd5\x76\x57\x5e\xd1\x44\x62\x60\x48\xfd\x46\x9c\xb9\xed\xdc\x62\xd0\xa6\xce\xe6\x77\xc1\x7c\x28\x42\x1f\x50\xbe\x7c\x90\xef\x69\xff\x73\x25\xbf\x7a\x22\xfe\x64\x74\xfc\x1f\xb2\x37\xf6\xbe\xec\x7a\xd9\x07\xfe\xc4\xbd\x39\x41\xf8\x75\xfb\x5c\x3e\x62\x1f\x73\xac\x1c\xe0\x9d\xb9\x3e\x6d\xae\xee\xc1\xbf\x8d\x57\x6c\x4c\x9d\xb5\x07\x0b\x2b\x59\xcb\xd1\xf1\xe5\x52\xa0\x98\x9c\x20\x69\x85\x54\x96\x1a\xd4\x46\x00\xea\xeb\x7e\x3b\xa5\x57\x2d\x4e\x10\x46\x4a\x1b\x81\x15\x51\xca\x0d\xf2\xa9\xfe\x6a\xd9\x6a\x14\x13\x13\x59\xeb\x9a\xb1\x1a\x9d\x78\xeb\xcf\x8b\x66\x37\x53\xce\x11\xe9\x4a\x7c\xf2\xd9\xbd\xd1\x24\xcd\x20\xa4\x00\x0d\xa7\x48\x42\x96\x65\x19\xe2\xbc\xaa\x2a\x0a\xe0\x49\x16\x11\x1c\x41\x93\x90\x52\x15\x0e\xf1\x9c\xa6\xb1\xac\x4a\x23\x5e\x45\x08\x50\xb8\x8c\x68\x9c\x27\x21\xbb\x89\x57\xf4\xf3\x6a\x37\x57\x7b\xa3\x29\x8e\xb8\xf0\xc3\xff\xbb\xbb\x47\xaf\x9b\x79\xb4\x76\x73\xb5\x37\xfa\xe7\xd4\x12\x0e\xbd\xbe\xe7\xf5\x34\x50\xbb\x11\x19\x61\xb8\x4a\xc5\x3a\x64\xc5\x52\x98\xf4\x80\x19\xc1\x51\x77\x3e\xce\x36\x55\x59\x22\xb9\xd9\xcc\x64\x92\x1d\xba\xa4\xc4\x95\xbc\x99\xae\xc2\xa9\xfb\x96\x28\x5b\xc2\x22\x65\xba\x8d\x11\xc8\xac\xe3\x1a\x6b\xa3\xda\xa4\xa3\xe4\xbb\x75\xb5\x1a\x9b\x88\x4a\xd3\x8c\x13\x15\x41\xfc\xe4\xda\x8d\xf8\x0b\xcb\xfb\x42\xed\x26\x30\x36\x4a\xed\xe4\xd1\x1e\xe3\x27\xe2\x8f\xd4\x63\x1c\xa8\xdd\x3c\x7b\x7d\x73\x6f\xdf\xcb\x4f\x5c\x5f\x09\x07\xfc\xd1\x6b\x37\xbe\xee\xfd\x9c\xda\xcd\x61\xed\x7d\xa6\x6c\xb5\xd7\xf7\x83\xbc\x7f\x8d\xb5\xb8\x70\x2c\xbf\x47\x6a\x4b\x9f\x52\x2b\x48\x9d\xaa\x8d\x85\x7b\xa0\x7f\x89\xda\x52\xe0\x0a\xd8\xd7\xaf\x43\x5f\xe2\xbc\x3c\xfd\xeb\x72\x4e\x1b\xc5\x47\x3c\xdc\x9b\xf7\x44\x1f\x15\xa1\x37\xaf\x61\x25\x1b\xb9\x0a\xad\x29\xb1\xfe\xda\x6a\x57\xa6\xad\x69\xcb\x88\x75\xd5\x1a\x70\x48\x6d\xc5\x30\x9a\x95\xd7\x86\xcb\x35\xbf\x18\x2b\xad\xc4\x74\x0a\x86\x22\xa3\xa7\x84\x32\x02\xe5\x4e\x53\xae\xf0\xf1\x99\x4b\x67\x46\xea\x62\xd4\xcf\x83\x14\x33\xac\x2d\xeb\x5a\xbc\xcb\x09\xd5\x4f\xde\x8f\xe4\x48\x16\x02\x99\x54\x91\x46\x28\x84\xaa\x6a\xaa\xa2\x22\x5a\xa6\x28\x59\xc3\x39\x95\x85\x00\x40\x9e\x24\x38\x95\x63\x71\x55\x03\xac\x06\x09\x59\x66\x18\x95\x52\x38\x92\x60\x70\x85\xf5\x7f\xca\x18\x3c\xf2\x73\x16\x81\x9c\x96\xbc\x96\xd3\x32\x38\xe0\xf8\xb3\x39\xed\xee\xee\xd1\x0b\x0b\x7d\x9d\xbd\xd3\x4e\x02\x39\xed\x49\xbf\x18\xd0\xc1\x7b\x6b\x00\x0f\xc4\x95\xf0\xcb\x07\xb2\x7b\x7a\xab\x19\xab\x5a\x31\x52\x78\x56\x4c\x18\x78\x93\x53\xb2\x12\x63\x8e\xde\x48\x6b\x28\x6a\xea\xd8\x65\xc7\xd3\x61\x35\x9b\x73\x09\x77\x56\x2b\xc2\xb7\x37\x60\x94\xaa\x8b\x26\x45\x96\xb8\x79\xcc\x74\xf3\x55\x47\xa0\x14\x02\x25\x3a\x2e\x9f\xe9\x4e\xe2\x04\x9f\x2e\x0e\x4c\x19\x82\xea\x4d\xe7\xf9\x82\xf2\x39\x9f\xd7\x05\x06\x45\x38\x3b\x93\x37\x0f\xf3\x71\xe6\xba\x92\x57\x3d\x0f\xff\x99\x77\x09\x5c\xa9\xd9\x84\x7d\xe6\x67\xf7\x5e\xfb\xa4\xdc\x12\x97\x7e\xd1\xde\xf5\x93\x35\x95\x80\xbf\x7e\x20\x47\x8b\x5e\x53\x11\x1f\xc3\x1f\xb5\xa6\xb3\x8d\x3f\xb0\x2f\xc4\x72\x95\xaa\x52\xcd\x14\x6b\x8d\xe5\x42\x21\xa7\xa8\x65\x22\xa3\x5a\xe3\x09\x48\xce\xe0\xb4\x26\x28\x06\x09\x09\x5a\x74\x27\x23\xb3\x9d\x5b\xa6\x12\x8d\x81\xb2\x5e\xc5\x19\x84\x8f\x92\x8b\x54\x7f\xfd\x46\xa5\x11\x89\xbf\x19\x66\x5c\xc6\x9b\xb3\xb2\xea\xda\xad\xcf\xee\x0d\x47\x94\x86\x64\x99\x81\x50\xa6\x35\x8e\x54\x35\x4a\x01\xbc\x4c\x69\x40\x63\x64\x8e\xe1\x58\x0d\x00\x8e\x63\x00\xc3\x23\x9e\x67\x10\x60\x64\x08\x59\x1a\x42\x85\x50\x39\x88\xf3\x0a\xc3\xf9\xf1\x87\x78\xe4\x47\x7a\xee\x8b\x3f\x24\x73\xfe\xbc\xf9\xe6\x2e\xfd\x12\x7a\x3d\xed\x76\x0f\xe0\xbe\x1a\xe3\x3d\xf1\xe7\xb3\xf3\xf2\x00\xfe\x3d\xbd\x55\x51\xef\xb7\x13\xc5\xd4\x60\x2c\x15\xd7\x4a\x25\xcd\x58\x9c\x3a\x6d\x66\x4b\x4e\x0e\x6f\xf7\x5d\xb7\x2d\xc6\x85\x44\xbd\x00\xb3\x92\x12\xc3\xd3\x53\x27\x1d\x9b\x19\x74\x0c\x0d\x57\x94\x58\x5b\xcd\x78\xbe\x5b\x63\x12\x62\x36\x4d\x49\x23\x7d\x55\x34\xeb\x53\x72\xad\xa4\x6c\xfe\xb6\x3d\x83\xbb\xe3\xcf\xbd\x67\x57\x9f\x1d\x7f\x1e\xc4\xff\xc4\xf8\xf3\x89\x67\x97\x7d\x52\xee\x8c\x3f\xbf\xc4\xd9\xea\xed\x75\x35\xfe\xdc\x7b\x76\xff\xd9\xf1\x27\x02\xfe\x07\xe3\x4f\x3d\x99\xee\x8a\x4e\xb9\xdc\xc5\xe7\xd2\x82\xeb\x4c\x07\x4b\x62\x52\x55\x56\x8b\x41\x0d\x66\x08\xd0\x6d\x70\x42\x3a\x37\xb1\x14\xb0\x66\xab\xed\xe9\xa2\xc3\x30\x45\x93\x66\x1a\x45\xbd\x96\x2d\xb0\x24\xe8\x67\x2d\xb1\xaa\x74\x74\xa2\x9d\xca\xcd\xd4\x82\xad\x49\x8b\xf2\x1c\x7c\x76\x4d\x5f\x56\x29\x8e\x51\x65\x55\xc5\x09\x95\x62\x70\x0e\xb0\x0c\x0b\x14\x0a\xd2\x90\x45\xbc\xca\x20\x8e\xa1\x15\x48\xf0\x8a\x4c\x01\xc4\x10\x2a\x0b\xa1\xc6\xe2\x90\xd0\x10\xa2\x65\x92\x51\x91\xbf\x07\xfd\xac\xf7\x9d\x5c\x8d\x3f\x2c\x41\x91\xe7\xd7\x3f\x2c\xe1\x1d\x96\x3a\x7a\xa7\xf9\xa3\x5b\xd0\x17\xc2\x8f\xbf\x05\x1d\x69\x39\x43\x5e\xd9\x82\x4e\xf0\xc3\x71\xa1\x4d\x4c\xc9\x39\x5b\xd5\x56\x5c\xa5\x84\x86\xa2\x0c\x1a\x8d\x1c\x6d\x2c\xa7\xc3\x1c\x9e\xb0\xf4\x8e\x5d\x76\x59\xbd\x0c\x18\xa2\x2a\x0f\xfb\x84\x5a\x6f\x34\x35\x94\xb2\xe6\x0a\x5e\x11\xa0\xd6\x4f\x75\x96\x6e\xbf\x25\x8c\x9c\xe2\x6c\x30\x4a\x8c\x57\x83\x84\xd0\xfd\x15\xb7\xa0\xcf\x5c\x9f\xb6\x05\x1d\x2d\x9c\x7c\xc8\x16\xf4\x19\x9c\x9f\xb6\xad\x79\xe6\xe4\xd3\xc7\x6d\x41\x7f\xe0\x72\xee\x6a\xb8\x8a\x20\xab\x87\xc3\xd5\x4f\xda\x02\xdf\x86\xab\x2c\x51\xef\x4e\x64\x68\xa3\xb8\x9b\x88\x17\x17\xdc\x92\xa9\xd6\xe6\x2d\xa9\x34\x18\x17\x33\xd3\xea\xa0\x9a\x31\x12\xc8\x61\xc8\x99\xc0\x76\xec\xb7\xc4\xac\x9e\x7d\x03\x79\xa9\xc6\x53\x65\x83\x5f\x57\xb9\xc4\x24\x26\x4a\x5a\x86\x48\x37\x93\xed\xc5\x8c\x29\x37\x33\x72\xa1\x24\x26\x3e\x39\x5c\xe1\x38\x94\x79\x45\x53\x10\x21\x53\x0a\x05\x28\xa0\x72\xb2\xcc\xb0\x0c\xa7\xaa\x38\x4f\xc9\xaa\x2c\x03\x85\xa5\x70\x86\x05\xb8\x2a\xcb\xa4\x0c\x71\xa4\xf1\x1c\xc7\xe2\x1a\x43\x42\xff\x55\x59\xe4\x76\xb9\xf4\x84\x2d\xe8\x1b\xc2\x15\x73\x7e\x07\x7a\x7b\xf3\xe8\x77\x33\x1e\xdd\x80\xfe\xc4\x68\x15\xd8\x30\x2e\xb6\xe4\x5c\x2e\x06\x8a\xc8\x58\x2f\x75\x53\x49\xe5\x28\xa6\x90\x5d\x25\x5c\x9c\x8e\x65\x79\xc2\x04\xb1\x1a\x49\x70\x79\x7e\x2d\x8d\x08\x4d\xcf\xb7\x09\x53\x33\xc9\x74\xce\x2a\xb6\x1c\x62\xda\x02\xb1\x64\x73\x62\x03\x02\x40\x22\xc1\x0a\x25\x26\x5b\xb0\x29\x33\x51\x14\x72\x1f\x12\xad\x22\x6c\x6a\x3e\x35\x5a\x3d\x88\xff\x89\xd1\xea\xd1\x0d\x8b\x47\xa3\xd5\x53\xf0\x3f\x10\xad\x7e\x89\x4d\xa7\xed\x75\x2d\x5a\x45\x91\xd5\x33\xa3\x55\x14\xfc\x0f\x46\x2b\xb7\xe5\xe8\x03\xb6\xe9\x32\xc5\x4a\x26\xa9\x2e\x4a\x83\x81\x65\x69\xb9\x0c\xd9\x30\x29\x8d\x84\x5a\x87\xce\x6a\xf2\xc2\x24\x4b\x44\xe7\x2d\x26\x8c\x64\xa8\xc6\x34\xa5\x69\xe8\x6e\x7b\x0d\x27\x9d\x0e\x95\xaf\x8f\xe7\x1d\xb9\x65\x77\xb3\x8e\xb0\xb6\x94\xe9\xdc\x50\x44\x47\xf8\xe4\x68\x45\x23\x8d\x57\x70\x46\x96\x19\x82\x56\x09\x15\x12\x04\x07\x00\xe0\x64\x55\x03\x94\xca\xe1\x1c\xcb\x70\x24\x4d\x22\x44\x68\x0a\x64\x29\x9a\x55\x38\x44\xe3\x8c\x26\x23\x99\x07\x9a\x42\xd3\x7e\xb4\xa2\x9e\x14\xad\x6e\x68\xf0\xe5\x29\x70\x21\x5c\xf1\x14\xf1\x12\xfa\x4d\xa5\x47\xe3\xd5\x27\x36\xf8\x06\xe2\x55\x39\x43\x64\x0a\x65\xde\x60\x70\xa5\x04\xaa\x05\xa2\x29\x01\xbd\x63\x67\xc5\xee\x00\x65\x8a\xb5\x4e\xba\x41\x3b\x66\x72\x5a\xa6\xd3\x66\x45\x6c\xd0\x4a\xcb\x21\x71\x89\xcd\x35\x2a\x6f\x4c\x36\xcb\x54\x95\x37\x22\xa7\x26\x81\xc2\x30\x8b\xa2\x8e\xa8\xcc\xaa\xc6\xcd\x27\x8b\x05\xfe\x2b\xc6\xab\x87\x1b\x7c\x1f\xc4\xff\xc4\x06\xdf\xa7\x6c\xb0\x3f\xd0\xe0\xfb\xd9\x1b\xfc\x82\xf0\xeb\x16\x2b\xaf\x35\xf8\x7e\x66\xbc\x10\x3e\x60\xae\xee\xc1\xbf\x8d\x57\x94\xdc\xed\x5a\x2c\x51\xb4\x6b\x8b\x75\x4b\xb0\xdf\xaa\x64\x3b\x81\x1c\xa5\x66\x48\x54\xd7\x4d\x2b\xad\xca\x78\xa5\x14\x2c\x76\xd8\x56\xb8\x5a\x65\xb4\x6c\xaf\xb5\x2a\xe9\xf4\x4b\xbc\x69\x29\xda\x24\xb1\x34\xbb\x7d\xbc\xd8\x5a\xdb\xb6\x30\x4b\xb0\xba\x9c\xcf\xae\x62\x66\x2a\xf5\xd9\xcd\x10\x24\x4b\xa1\x4d\xb0\xe0\x65\x1e\x69\xac\x2a\x43\x1e\xd2\xaa\x4c\x92\x24\x2f\xb3\x9c\xa6\x42\x4e\x23\x29\x96\x65\x65\x00\x35\x92\x94\x21\xc5\x70\x50\xa5\x15\x5c\xd5\x78\x8a\x51\x29\xf5\x65\xf7\xdb\x9e\xd1\x7f\x71\x76\xf7\x8b\xa5\x17\xc2\x14\xc7\x10\x04\x71\x36\x4c\x6d\xee\x92\x2f\xc7\xbf\xb3\xe7\x6b\x6a\xa6\xc8\x65\xab\xf3\xea\x50\x2e\x10\x59\x81\x6c\xb7\x06\x35\xbb\x30\x1e\x74\x70\x5c\xcb\x70\x4e\x31\xc7\x8e\x71\xb1\xb6\xc8\xb7\xe3\x42\x87\x14\xf6\x51\xca\xbb\x2e\xac\xaa\xfc\x2b\x42\x0d\x2a\x78\xa4\x37\xd1\x9a\x2f\xd2\xfc\xe6\x96\x98\x4c\xad\xa7\xf3\x61\x35\x51\xb5\x24\x21\x6f\x68\x95\x5a\x27\x65\x15\xfb\x73\x77\xa5\x34\xc8\x51\xba\x92\xac\xd2\x40\x1f\xaa\x4e\x3a\x0b\x13\x52\x7b\x81\xd3\xf5\x78\xab\xdf\xc6\x3b\xfa\xd0\xc6\x93\x89\x8a\x48\x49\x30\xdd\x22\x0a\x63\xc5\x21\xdf\x16\xc5\xb1\x21\x53\x8d\x9a\x5d\x2a\xde\x10\x99\x8e\x54\xfa\x38\x32\x05\x78\x3e\x78\xe6\x80\x27\x4b\x18\xf1\x04\x5e\xc4\xf3\x99\x95\xdb\x5f\x48\x60\xd4\xc5\xe1\x6a\x62\x01\x5e\xca\x2e\xe7\xc5\xe4\xaa\x4c\xbb\x09\x51\x49\xfa\x3c\x92\xba\x6b\x97\xcd\x6e\x9c\x5e\x5c\x23\xe2\x8a\xb5\x3f\x80\x5f\xb2\x57\x8d\xda\x03\xf8\x05\xe1\xe7\xd5\x92\x4e\x7a\xde\x44\x74\x59\x94\xcd\xb7\x8b\x6c\x5e\x93\xc5\xa3\x73\xb1\xd1\x85\x98\x12\x82\x77\x97\x2c\xfe\xa3\x73\x8c\x4d\x8b\x42\xb3\x90\xaa\x26\xbb\xe6\x1a\x6f\x2d\x98\x24\x25\xb3\x8a\x29\xf2\x74\xad\xb1\x18\x96\xd5\x6e\x3e\x2b\x27\x6a\x84\xde\x68\x39\x52\xb9\x39\x07\xdd\x96\x9b\xa6\xf2\x05\x5e\xd0\x1b\xcb\x72\xaa\xdd\x6f\xa9\xc6\xc4\x2c\x4a\x84\x92\xa4\xad\x71\x4c\xc4\xe1\x3a\xf9\xc9\x47\x01\x01\x43\x41\x1a\x67\x28\x24\x43\x86\xd2\x08\x45\x95\xa1\x2a\x73\x34\x23\x6b\x24\x45\x71\x14\x47\x6b\x0a\x43\x30\x04\xc5\x42\x15\x92\x48\x25\x79\x45\x55\x35\x5c\x63\x78\x9c\x00\x24\x29\x33\xfb\x1f\x56\x7e\xc4\xf3\x12\xd7\x3d\xef\xa5\xdd\xff\xdd\xdd\xe0\xef\x89\x3e\xea\x79\x2f\xac\x0f\xfc\x2b\x42\x7e\x7a\xc6\xf3\x0a\x75\xf1\xcd\x78\x93\x51\x7a\x91\x74\xec\x42\xc2\x2c\xe4\x66\x4e\x1c\xa7\x5b\x6e\x3e\x95\xb0\x75\xcb\x99\xf5\x8b\xd5\x78\x93\xe9\x34\x07\x94\xbb\x68\xaf\xfa\x0e\xdb\x74\xeb\x54\xb2\x84\x96\xe5\x12\x93\x9f\x2a\xda\x34\x5f\x00\x78\x7b\x94\x18\x0e\x17\x26\xa5\x73\x95\x9c\x36\xc8\x65\x7e\x2d\xcf\xfb\xa8\xe7\x7b\xd4\xda\x4b\x8b\xe2\x78\xf2\x44\xcf\xfb\x99\x75\x91\x6b\x35\x9a\xcf\xf4\x7c\xc2\x93\x3c\x2f\x47\x1d\x9e\x3f\x53\xdf\xbc\xe4\x79\xc5\x7e\xa6\x3b\x6e\x93\x7d\x45\xb0\x0b\x2b\xfd\x6d\x65\x14\xed\x0a\x5f\x6e\xc9\xf5\xea\x02\x52\x85\x62\xd1\xaa\xe3\x15\x50\x1e\x81\x5c\xac\xa8\xa4\x1d\x4b\x2e\x83\x62\x73\x26\x0c\xb2\x4e\x63\x50\x36\xa0\x99\x65\x8c\xba\xab\xa6\x27\xd5\xb7\x7c\x29\x1f\xcb\x55\x52\xab\x2c\xb5\xfa\xec\x1d\x05\x42\x25\x19\x5a\x21\x15\x8a\xd7\x48\x96\xa1\x59\x5c\xd5\x36\x7e\x57\x81\x0c\x41\xe3\x24\xcf\x30\x1a\x8e\x08\x86\x87\x84\x46\x03\x45\x95\x19\x4e\x41\x04\x42\x80\x87\xac\xc6\x11\x14\x0d\x7d\xbf\x49\x3e\xe6\x79\xaf\x6e\x24\x70\x0c\xc5\x9c\xdf\xf7\xde\xdd\x0d\xfe\x6e\xf2\xa3\x9e\xf7\xc2\x51\x36\xff\x7a\xf0\x27\x40\x03\x9e\x37\x11\xcf\x27\xf4\x79\xae\xc4\x02\xbd\x98\xc8\xf5\xf1\x46\x59\xe2\xe5\xd8\x28\x26\x4c\xde\xd6\x20\x59\x48\x55\x8d\x66\xba\xde\xc2\x1d\xa5\xa6\xcf\x12\x00\x9a\xab\xd2\xa2\x54\x63\x1c\xba\x6e\xc0\xe4\xc2\x4d\x99\x4b\xa7\x62\x42\x40\xd4\xd4\x66\xb5\x30\xca\x12\x10\x95\x84\x15\x97\xfd\xb5\x3c\xef\xa3\x9e\xef\x51\x6b\x2f\xe2\x43\x26\xf1\xcc\x9c\xf7\x13\xdb\x4d\x3f\xc2\xf3\x46\xf5\x7c\xc2\x93\x3c\x2f\x1b\x78\x6f\xfb\xbb\x57\xf6\x5d\x95\xc5\x7f\xb4\x55\xb5\x5b\x5c\xa5\xca\x7c\x37\xb9\xa8\xe7\x54\x71\x3d\xd0\xda\xf1\x89\xa6\x17\xda\x0a\x5f\x35\x74\x3c\x37\x4a\x34\x47\x6a\x31\x2b\x76\x8b\xba\xda\x9e\x70\x83\x52\x4a\x44\x76\xb9\x69\x8d\x75\xa7\x58\xa5\x39\x39\x45\x13\xae\x3a\xec\xb4\xc4\xe4\xa4\xc6\x8f\xcd\x81\x50\x9a\x27\x3e\x39\xe7\xc5\x71\x12\xf1\x00\xe0\x40\x05\x3c\x84\xb2\x4c\x11\x3c\xc5\x03\x9e\x26\x39\x9c\xe1\x38\x46\x65\x59\x56\x21\x18\x9c\x20\x49\x85\xa1\x58\x4e\x03\x0a\x4f\x70\x90\xe5\x91\x42\x21\x82\xa5\x48\xdf\xf3\x52\x8f\x79\xde\xab\x45\x71\x8e\xa1\xd9\x4b\x9e\xd7\xbf\x1b\xfc\x7d\xf8\x47\x3d\xef\x85\x17\xc0\xf9\x57\x84\x06\xca\x33\x9e\x37\x95\x2b\xcf\xd4\xf5\x6c\xa0\x59\x31\xb5\x9e\xcb\x77\x3a\x32\xce\xd4\x07\xc5\x44\xb1\xd8\x71\xd2\x4b\xb3\x65\xd6\x40\x36\x8f\x06\xda\x94\x90\xf4\x74\xd3\x2d\xce\x3a\x44\xc1\x6e\x49\xf5\xb7\x55\x2d\x91\x89\xb5\xe7\x9a\x6a\x75\x16\xc9\x8a\x32\xe1\xe8\x7e\xaa\x26\x27\xc7\x03\xb9\xd2\x2d\xfd\x5a\x9e\xf7\x51\xcf\xf7\xa8\xb5\x17\xa8\x98\xf4\xf6\x4c\xcf\xfb\x89\x8d\x96\x1f\xe1\x79\xa3\x7a\x3e\xe1\x49\x9e\x37\x6a\xe5\x69\xeb\x79\x57\x29\xdb\x54\x58\x8b\x64\x2a\x66\xd3\x48\xb6\x00\xc1\x97\x87\xd6\x6a\x51\x5f\x01\x36\xa1\xbc\x81\x37\x5c\xad\xad\x3a\x16\xc9\xb8\x83\x6e\xa2\x55\xac\xb3\x23\xde\x98\x82\x46\x73\xac\x0c\xab\xb5\xf9\xc8\x26\x49\x98\xe6\x84\x01\x59\xd0\xca\xdd\x2a\xde\x5e\x4c\x2c\x62\x4d\x3c\xe7\xd0\xc1\x97\x2f\xdf\xbf\x7f\xf9\xfe\x1d\x93\xe0\x18\xfd\xc0\xa0\xe3\x20\xb7\xe7\xb8\xd0\x75\x82\x7f\xf7\x26\x43\xb4\xfa\x03\x6b\xac\x26\xe8\x07\x96\x2c\x4b\xf5\x46\x4d\xc8\x49\x8d\x3f\xb0\xba\xd2\x47\x63\xf8\x03\x9b\xcc\xe4\x91\xa1\xfc\x81\x95\x17\x26\xb2\x7f\x60\x1b\x88\x5f\xbe\x08\xc5\x86\x58\xc3\x1a\x42\xa2\x28\x62\x65\xa9\xd8\x0d\x42\xfc\x82\x61\x18\x26\xa4\x52\x01\x68\xef\x10\x62\x95\x5a\xae\x24\xd4\xba\x58\x41\xec\x62\xbf\x19\xea\x3b\x6a\x75\xcb\x9e\xf4\xc6\x86\x6e\x43\x3f\x48\x84\x3e\x3f\x89\xea\x10\xd4\x53\x94\x9f\x42\x7c\x95\xfa\x5d\x9c\xf3\xd8\x76\x42\x1f\xfd\xff\xf5\x14\x4b\x45\xdb\x3f\xdd\xd5\x64\xf7\xa7\xe1\x38\x33\x64\xf7\x9e\xc2\xdd\x31\xda\x53\xcc\x45\x22\x0c\x6b\x4a\xb9\x6a\x53\xc4\x7e\x3b\x0c\x7f\xc5\x0e\xe3\x77\x7f\xfb\x0f\xdc\x29\x9a\xe7\x4c\xeb\xdd\x8c\xdf\x35\xa9\xd6\x04\xf9\xca\xd0\x9b\x40\xdb\x35\x14\x63\x02\xcd\x00\x27\xa7\x6f\x3f\x99\xb3\xd3\x48\x2e\x71\x7a\x81\xac\x9b\x39\x0f\xa4\x6d\xa7\x79\x3f\x37\xe0\xc9\xdc\x9f\x43\x73\x89\xff\x8b\xa4\x5d\x95\x80\xaf\xd2\xf2\xca\xd3\xf6\x1d\x23\x39\x29\x25\x76\xae\xf0\x90\xac\x89\x42\x43\xf4\x87\x1e\x43\xc1\xca\x52\xd8\x18\x9a\xf5\x9c\x94\xc1\x64\xd7\x46\x28\x68\x5d\xe7\xa9\xf1\x6d\xec\x71\x7a\x7c\x38\xb7\x51\x74\xc6\xae\xe5\x55\x0f\x2a\x8a\x35\x33\xdd\xc8\xe4\x1c\x40\x04\x29\x39\x5a\x2b\x1c\xd3\xe3\x0f\x7e\xc5\xb6\x7f\xf4\x1c\x34\x9d\x21\x53\x79\x2f\x30\x79\xd5\xeb\x43\xa7\xff\x08\x65\x9b\xe7\x6f\x23\x2b\xa8\x69\x9b\xa7\x4e\x51\x33\x42\xaa\xfe\xc0\xc4\xed\x21\xdc\x46\x91\x3f\x76\x2f\x9e\x57\x0c\x4e\x26\x23\x43\xf1\xdd\x81\x65\xab\x67\xdc\x74\x0f\x6d\x74\xc3\xbb\x1f\x81\xd2\x6d\x94\xf0\x09\x0e\x81\x0b\x92\x8d\x34\x0d\x29\x61\x55\x7b\xef\xb5\x0c\xf5\x15\xfb\xea\x3d\xfc\xf5\x1c\xb1\x86\xfa\x24\x32\x0d\xf5\x66\x02\x77\xaa\xb7\x21\x2f\x02\xd1\xd6\xa4\x37\x79\x16\xdd\x5b\x58\x41\xd2\xcf\x84\xaa\x48\x9c\x9c\x66\xc0\x5d\x3e\x8f\x81\x2d\xac\x33\x3a\x1d\x91\x85\x20\x84\x53\x4c\x58\x93\x8d\x56\xf6\xad\x48\x3c\x6c\x89\x3f\xc0\x88\x2a\xfc\xcb\x82\x76\xb6\xd6\xee\xb9\xea\xc7\x65\x7d\x0c\x2e\x48\xb2\xff\x7d\x88\xc6\xd3\x14\x05\xe5\xfa\x2c\xb2\xde\xc1\xbc\xcd\xbd\x9d\x22\xd0\xf5\xa7\xc4\x7d\x64\x5a\x0f\x30\xa2\xab\xe4\x35\xf5\x73\x6d\x75\x83\x44\x86\x0e\x7a\x38\x7e\x9e\x02\x16\xa2\x5c\x45\x21\x3a\x83\x63\xaf\x12\x68\x69\xda\x03\x41\xeb\x3d\xa8\x9b\x88\xf3\x46\x5e\x22\xcd\xa3\x1d\xd9\x4f\x13\x5f\x08\xde\x35\x22\x43\xc3\x6f\xa1\xf4\x39\x72\x3c\x82\x76\x2b\x95\x57\xa5\xf9\x1c\xda\x6e\xa2\xe9\x32\x2d\x3b\x8a\x47\x96\x35\x9c\x4d\x1e\xa3\xe8\x18\xd6\xcd\x33\xea\xe7\xbb\x67\xe8\x9b\x40\xc3\xee\xb9\xc6\x18\x3d\x85\xc2\x30\xb4\xdb\xec\x76\x4b\xe0\x2b\x16\x26\xf9\x15\xdb\xba\x78\x65\x64\x39\x48\xed\x41\xf7\x0c\x13\x4f\xf0\xdb\x5b\x38\xd7\x28\xbe\x33\x3b\xda\x40\x7d\x9a\x74\xef\x10\xec\x55\xb9\x19\xa6\x8a\x96\xbd\x50\xca\xe1\xf4\x2c\xb3\x07\x55\xd5\x46\x8e\xf3\xa8\x40\xaf\x22\x38\x5a\xa7\x6d\x6f\x87\x56\x46\xfe\xc0\x3b\x68\x7f\x5c\x0f\x2e\xc1\xbe\x4e\xf1\x09\x2b\x3b\x06\xb8\xcd\xc2\x37\xf0\xdc\xd5\x24\xfa\x1a\xfc\x22\xd4\xab\x69\xff\x66\xd0\x15\x42\xb7\x39\xd4\x06\xe4\x5e\x89\x9e\x44\xed\x29\xd0\x57\xd3\xb7\x5b\x35\x39\x00\xfc\xd9\xca\x70\x04\x3a\x4a\xbe\x79\x1e\xdc\x78\x62\xd9\x1b\xc7\x37\x47\xb6\x63\x58\xe6\xf3\x05\x1d\xc6\x70\x9d\xfc\xd0\x03\xb7\x33\xb3\x75\x3d\x11\x2b\x15\xb7\xc9\x3f\x80\xe3\x2a\x27\x81\xb1\xb7\x33\x31\xb1\xd1\xdc\xb0\x66\xce\xa7\x70\x73\x0a\xd9\x55\xb6\x4e\x3d\x74\x3b\x7f\xbb\x22\xca\x87\xf1\xb4\x43\x70\x95\x8f\xb3\xd5\xae\x63\xd0\xfb\x78\xfb\x21\xa6\x1d\x86\x7e\x72\x01\x7c\xaf\x81\x1f\x03\x3d\x5e\x42\x3d\xc9\xc2\x2f\xa1\xb8\x85\x87\x2b\xeb\xba\x8b\xc8\x9e\x17\xbe\xde\x03\xbe\x89\xf6\xeb\x41\x2c\xb8\xd8\xfe\x08\xb5\x79\x0f\x3f\xf2\x52\xdf\x4b\xe2\xf6\x81\x7c\x57\x61\xec\xc9\x96\x35\x8c\x2c\xe5\x0b\x30\xaf\xa6\x08\xbf\xfd\xa6\x22\x17\x1a\x23\x07\xfb\xfe\xcf\x7f\x62\x2f\x8e\x35\x52\x03\xbb\x69\x2f\x3f\x7e\xb8\x68\xe9\x7e\xfb\xf6\x8a\x9d\x1f\xa8\x58\xea\x6d\x03\xfd\x5a\xfc\xf9\xa1\xb2\x35\xd3\xfb\xee\x4d\xe8\x8f\x86\x5e\x26\xe0\x68\x68\x88\x84\x6f\x58\x3b\x2b\xd6\x44\x5f\xc9\xb0\x3f\x31\x92\xbc\x79\x23\xda\x50\x7b\x5a\x60\x9b\x28\x5d\xf8\x9c\xed\xe8\x2d\x5a\x2c\x5d\xae\x89\xb9\x8c\xb4\xdf\x02\xc2\x6a\x62\x5a\xac\x89\x52\x52\xac\x87\x76\x45\xbc\xbb\x65\x09\x6b\x56\x52\x1b\x95\xa9\x89\xf5\x46\x2d\x97\x6c\x6c\xbe\x4a\x89\x45\xb1\x21\x62\x49\xa1\x9e\x14\x52\xe2\x85\x7d\xb4\xcd\xba\xe3\xf8\x63\x2f\x54\x8a\x79\x9e\x30\x8e\xf1\x5c\xd9\x24\x3b\x47\xc9\xb1\x7c\xc2\x65\xa3\x93\xc2\xda\x26\xfa\x57\x76\x14\xcf\x4a\x62\xbb\x94\xfd\xe9\x72\x08\xd2\x71\x4a\x0a\xbb\x2a\xc1\x65\x85\xb9\x4f\x02\xef\x8b\x4a\x3f\x51\x0c\x67\x88\x39\x96\xc5\x89\x32\xd8\x73\x95\x22\x5c\xe2\xf8\x15\x04\x72\x5e\x35\xde\xd5\x90\xae\x6a\xc7\xf7\xef\x18\x54\x55\xa4\x62\x63\x68\xce\xe0\x68\xb4\x3a\x22\x34\x97\xc6\xc4\x4e\xae\xde\xa8\xfb\x24\xfb\x8c\xfd\x3e\x44\xab\xde\x1c\x8e\x66\xa8\xb7\x01\x88\xb0\x54\xad\x5c\x09\xd2\x7d\x78\x2a\x34\xd2\xdf\x90\xff\xe2\x8d\x0f\x23\x38\x0d\xfb\x8f\x5d\x84\xf4\x87\x87\x31\xff\xe6\x89\xed\xe2\xb5\x91\x91\xd2\x87\x36\x54\x5c\x64\x63\x73\x68\xaf\x0c\x53\xff\x8d\xa0\xe9\x6f\x98\x54\x6e\xf8\xfd\x4b\xd7\xa1\x78\x48\xaf\xc1\xf9\x12\xea\x3b\x0d\x53\x7b\x78\xdb\xea\x72\xd2\x33\x4c\x1d\x39\x6e\x6f\x04\x37\xff\x78\x89\xf6\xcb\x2b\xf6\x82\xbf\x7c\xfb\xe3\xbd\xaa\x84\x00\x9d\xd2\x95\x53\x92\x3e\xee\x2f\x18\xa2\xd5\x66\xc2\x8f\xe4\xb9\xaf\x97\x38\x86\x6e\x6e\x52\xfd\x1b\x04\xba\x7b\xe8\x84\x34\x18\xea\xdb\x0d\xb2\xc4\x7c\x64\xd8\x26\x74\xdf\x32\x7c\x81\x0c\xbd\xef\x62\x86\xe9\x22\x1d\xd9\xa1\x59\xfb\xfe\x1d\x5b\x20\x6c\x61\x8c\x46\xd8\x74\x86\xec\x15\x26\xaf\x76\xf0\x1d\x0b\x73\xfb\xd0\xc5\x0c\x07\x5b\xf4\xf7\xdf\x1a\x0e\xe6\xf6\x11\xa6\x19\xb6\xe3\x62\x86\x8b\xc6\x98\x61\x7a\xdf\x28\xd6\x78\x62\x39\x86\x8b\x36\xb2\xbc\x81\xac\x23\xe1\xfa\xc0\xf7\x3d\x01\xdf\xbe\xf8\xb6\xb5\x31\xaf\x8a\xe5\xb8\xba\x8d\xea\xd5\x22\xa6\x42\x17\x6e\xbc\x37\xa6\xce\xc6\x13\x0f\xe1\x08\xb9\xc8\x73\x0f\xff\x3f\x00\x00\xff\xff\x43\x9b\x57\x9c\xd7\x50\x01\x00") +var _offer_idsHorizonSql = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\x7d\xf7\x8f\xa3\x48\xf6\xf8\xef\xf3\x57\xa0\xd1\x49\xbd\x23\xf7\xac\x29\x32\xb3\xdf\x3d\x09\xdb\x38\x1b\xe7\xd4\xa7\x93\x55\x40\x81\x71\x00\x1b\x70\x3c\x7d\xfe\xf7\xaf\x0c\x0e\x98\x76\xc4\xee\x9e\xd9\xbb\x45\xab\xd9\xb6\x29\x5e\xaa\x97\xea\xd5\x2b\xfc\xfd\xfb\x97\xef\xdf\xb1\x8a\xe5\xb8\xba\x8d\xea\xd5\x22\xa6\x42\x17\xca\xd0\x41\x98\x3a\x1b\x4f\xbe\x7c\xff\xfe\x65\x73\x3f\x35\x1b\x4f\x90\x8a\x69\xb6\x35\x3e\x0c\x98\x23\xdb\x31\x2c\x13\xe3\x7f\x67\x7e\x07\x81\x51\xf2\x0a\x9b\xe8\xbd\xcd\xe3\xa1\x21\x5f\xea\x62\x03\x73\x5c\xe8\xa2\x31\x32\xdd\x9e\x6b\x8c\x91\x35\x73\xb1\x3f\x31\xfc\x0f\xef\xd6\xc8\x52\x86\xef\xbf\x55\x46\xc6\x66\x34\x32\x15\x4b\x35\x4c\x1d\xfb\x13\x7b\x69\x36\xd2\xdc\xcb\x1f\x3b\x70\xa6\x0a\x6d\xb5\xa7\x58\xa6\x66\xd9\x63\xc3\xd4\x7b\x8e\x6b\x1b\xa6\xee\x60\x7f\x62\x96\xb9\x85\xd1\x47\xca\xb0\xa7\xcd\x4c\xc5\x35\x2c\xb3\x27\x5b\xaa\x81\x36\xf7\x35\x38\x72\xd0\x11\x9a\xb1\x61\xf6\xc6\xc8\x71\xa0\xee\x0d\x58\x40\xdb\x34\x4c\xfd\x8f\x2d\xed\x08\xda\x4a\xbf\x37\x81\x6e\x1f\xfb\x13\x9b\xcc\xe4\x91\xa1\xbc\x6e\x98\x55\xa0\x0b\x47\xd6\x66\x98\x50\x6c\x88\x35\xac\x21\x24\x8a\x22\x96\x4b\x63\x62\x27\x57\x6f\xd4\xb1\xb2\x54\xec\x6e\xc7\xff\xde\x37\x1c\xd7\xb2\x57\x3d\xd7\x86\x2a\x72\xb0\x54\xad\x5c\xc1\x92\x65\xa9\xde\xa8\x09\x39\xa9\x11\x78\xe8\x78\x60\x4f\xb1\x66\xa6\x8b\xec\x1e\x74\x1c\xe4\xf6\x0c\xb5\xa7\x0d\xd1\xea\x8f\xcf\x40\xa8\x78\x7f\x7d\x06\xca\x8d\x5e\x7d\x1e\x83\x3e\xb6\xfb\xb9\xf3\x09\xdc\x28\xf2\x25\x64\x81\x51\x07\xe0\xde\xf0\x9c\x94\x12\x3b\x81\x91\x5b\xb0\x1e\x55\x3d\xa4\x69\x48\x71\x9d\x9e\xbc\xea\x59\xb6\x8a\xec\x9e\x6c\x59\xc3\xcb\x0f\x1a\xa6\x8a\x96\xbd\x00\x73\xa6\x03\x3d\x45\x77\x7a\x96\xd9\x33\xd4\x7b\x9e\xb6\x26\xc8\x86\xfb\x67\xdd\xd5\x04\x3d\xf0\xf4\x81\x92\x87\xa8\xb8\xef\xd9\x11\x52\x75\x64\x7b\x0f\x3a\x68\x3a\x43\xa6\x72\x17\x0b\x81\xc7\x27\x36\x9a\x1b\xd6\xcc\xd9\x7e\xd7\xeb\x43\xa7\x1f\x11\xd4\xe3\x10\x8c\xf1\xc4\xb2\x37\xe6\xb8\xf5\xa9\x51\xc1\x44\x95\xa5\x32\xb2\x1c\xa4\xf6\xa0\x7b\xcf\xf3\x3b\x65\x8e\xa0\x4a\x5b\xbb\x8c\x40\x74\xf0\x49\xa8\xaa\x36\x72\x9c\xcb\x8f\xf7\x5d\x5b\xf5\xe2\x4e\x6f\x64\x59\xc3\xd9\xe4\x86\xd1\x93\x6b\x24\xf9\xa3\xa0\x61\xdf\x09\x78\xe7\x74\x6f\x7e\x60\xe3\x27\x34\x0d\xd9\xb7\x0d\xdd\x81\x8f\xf0\xc8\x56\xac\xb7\x3d\xe4\xb9\xd6\x3b\x90\x04\x5d\xf1\xb5\x27\x26\x9b\x07\xfa\xee\xd5\x19\x70\x8e\x1c\x90\xbc\xba\xaa\x46\xfd\xbd\xa5\xdf\x32\xd8\xf2\xe9\xb0\xae\x0e\x34\x1c\xb7\xe7\x2e\x7b\x93\xeb\x20\x37\x23\xad\xc9\xad\x23\xd1\xad\xc3\x76\xa1\xe4\xf2\x60\x79\x67\xee\x57\x87\x5d\xf7\x62\xf2\xea\xb6\xc9\xf4\x63\xe4\x46\xda\x8e\x33\xbb\x86\x79\x3f\x58\xb1\x54\x74\x67\x5e\xb0\x57\x83\x09\xb4\x5d\x43\x31\x26\xd0\xbc\x18\xbc\xaf\x3d\xda\x9b\xdc\x99\x9b\xec\x23\xda\xbd\x14\x9c\x7e\xf0\x6e\xfc\x9e\xf0\x6e\xc1\xe7\x0f\xfc\x70\xf8\xfe\x64\x6e\x66\x72\xfb\xe7\x26\x3e\xec\x52\x3f\x4f\x19\x7a\x37\x52\xa0\x5b\xf6\xa4\x37\x36\xf4\x6d\xc2\x70\x81\x84\xd0\xc8\x9b\x79\xbc\x3f\xdf\xbb\x04\xf9\x56\xe5\xf4\x9f\x4e\x96\x8b\xcd\x92\x84\x19\xaa\x8f\x39\x25\xa6\x85\x66\xb1\x71\x23\xec\x33\x4a\xf7\x04\xc8\xdb\xe9\xbe\x0c\xc9\xfb\x74\x3b\xfb\xbb\x28\x5d\x17\xab\x4d\x51\x4a\x46\x90\xd9\x26\xcf\x76\xd0\xf4\x6e\xcc\x47\x40\x6e\x7e\x5a\x45\x37\x8e\x3d\x64\xb3\x37\x73\x78\xc6\xea\xef\xe1\xef\x34\x88\xdb\x9e\xdd\xe6\x7d\xb7\x0d\xde\x26\x79\x37\xf3\xb6\xf5\x00\xf7\xf0\xe2\x3f\x72\xe3\xd8\x6d\xfa\x77\x3b\x3d\xbb\x7c\xf1\x16\x8a\x42\x3e\xe4\xf2\xe0\x80\x4b\xd8\x0e\x14\x32\x99\x9a\x98\x11\x1a\x27\x06\x8f\x8d\xcd\x8a\xc3\x50\xd0\x6f\xe6\x6c\x8c\x6c\x43\xf9\xd7\xbf\xbf\xdd\xf0\x14\x5c\x46\x78\x6a\x04\x1d\xf7\x37\x68\xae\xd0\xc8\x2b\xc5\xdc\xf0\x84\x66\xd8\x27\x1f\x49\x37\xa5\x64\x23\x57\x96\x2e\xf0\xd3\x83\xba\x7e\xa0\xee\x15\x7b\x47\xe8\x05\x18\x3b\xee\x1e\x80\xb1\xe1\xd5\x7b\xfc\x40\xfc\x2b\x76\x0f\x23\x1e\xeb\x37\x40\x10\x3b\x0d\x51\xaa\x87\x40\x8c\x26\xba\x33\x1d\xed\x74\x31\x99\x15\x4b\xc2\x3b\x0c\x7f\x7c\xf1\xab\x70\x12\x1c\xa3\x1f\xbb\xef\xb0\xc6\x6a\x82\x7e\x6c\x1f\xf9\x03\xab\x2b\x7d\x34\x86\x3f\xb0\xef\x7f\x60\xe5\x85\x89\xec\x1f\xd8\x77\xaf\x38\x97\xac\x89\x9b\xf9\xda\x42\xde\xc1\xfb\x72\x04\xf1\xf8\xe6\x16\x70\xb2\x5c\x2a\x89\x52\xe3\x02\x64\x7f\x00\x56\x96\x8e\x01\x60\xb9\x3a\xf6\xb2\x2b\xbb\xed\xbe\x73\x3c\x20\x2f\x61\xcc\x3b\xf6\xb7\x38\xf7\x12\xba\xca\xcf\x91\x2c\xa5\x72\x23\x24\x4f\xac\x9d\x6b\x64\xf7\x64\x05\xeb\x6f\x47\xe8\x0f\x50\x42\x84\xdc\xc3\xfc\x3b\x20\x9e\x00\x2a\xc5\xf8\x44\xaf\x57\x8b\xd8\xc4\xb6\x14\xa4\xce\x6c\x38\xc2\x46\xd0\xd4\x67\x50\x47\x9e\x18\x6e\xac\x17\x06\xc9\xbd\xae\x68\x5b\xf2\x77\xba\x7a\xa0\x7f\x37\xb7\xa7\x64\xb9\xd7\xec\xab\xf0\xb1\x9a\xd8\x68\xd6\xa4\x7a\xe0\xbb\x2f\x18\x86\x61\x45\x41\xca\x34\x85\x8c\x88\x79\xdc\x97\x4a\x4d\xdf\xdf\xd5\x1b\xb5\x5c\xb2\xe1\x8d\x10\xea\xd8\x3f\x7a\xff\xc0\xea\x62\x51\x4c\x36\xb0\x7f\x80\xcd\xa7\xf0\x6c\x5c\x35\xc4\xc7\xb8\xbb\x06\xfe\x69\xcc\x11\xa7\x98\xbb\xc5\x53\x3d\xc6\xdf\x0d\x18\xf6\x2c\xee\xbf\x8a\xc4\xe1\x6f\x5f\x30\x2c\x29\xd4\x45\xac\x9d\x15\x25\xec\x1f\xe0\x5f\xe0\xdf\xf1\x7f\x80\x7f\x11\xff\xfe\xe7\x3f\x08\xef\x6f\xe2\x5f\xc4\xbf\xb1\x86\x7f\x13\x13\x8b\x75\x71\x23\x14\x51\x4a\x7d\x3b\x29\x99\x1b\xe2\xc0\x83\x92\xb9\x8e\xe1\xa3\x25\xf3\xff\xa2\x48\xe6\x7d\x4c\xdd\xca\x61\x1f\x87\x6f\x13\xc4\x21\x6c\xbf\x83\xe8\x51\x8c\x61\xf5\x8d\xac\xb0\x3f\x0f\x1e\xe0\xd5\xff\xba\xd1\xad\x88\xd8\x9f\x41\x8b\xf8\x76\xca\x6a\x9f\x4a\x63\x18\x60\x88\xc4\x9d\x19\xdf\x4e\xe1\xc9\x14\xe8\x51\x2a\x4f\x01\x0d\x51\x7a\x64\x90\xc7\xe4\x1e\xb4\xec\x3d\xb5\xa7\xd2\xbc\x87\xa9\x3d\x01\x34\x4c\x6d\xd0\x48\x2e\x52\xbb\x89\x5c\x2a\xd2\xe0\x6c\xe4\xf6\x5c\x28\x8f\x90\x33\x81\x0a\xc2\xfe\xc4\x5e\x5e\xfe\x38\xbe\xbb\x30\xdc\x7e\xcf\x32\xd4\xc0\x56\xda\x11\xaf\xc1\xfc\x77\xcb\xa2\x67\x60\xb7\xb1\xe7\xdb\x62\x70\xf1\xed\x73\x64\xa8\x98\x6c\xe8\x86\xe9\x7a\x89\x81\xd4\x2c\x16\x7d\x76\xe0\x78\x93\xc6\x63\x4a\x1f\xda\x50\x71\x91\x8d\xcd\xa1\xbd\x32\x4c\x3d\x34\xcc\x9c\x8d\xf7\x29\x3f\x66\x98\x2e\xd2\x91\x1d\x1a\xa2\x8d\xa0\xee\x60\xce\x18\x8e\x46\xef\xd1\xb8\xd6\x78\xf4\x1e\xc9\x6f\x04\x4d\x7f\xdb\x8f\x7c\x3f\xed\xe1\x75\x43\x54\x71\x84\xab\x1d\x7b\x91\xb8\x68\xf9\x4e\x20\x93\xc9\xc8\xf0\x6a\xf6\x98\x6b\x8c\x91\xe3\xc2\xf1\x04\xdb\xcc\x99\xf7\x11\x5b\x5b\x26\x7a\x4f\xe8\xb9\x55\xd1\x2e\x1f\xdd\x2e\xa7\x6e\xa3\x79\xbf\xf8\x3a\x03\x75\xab\x86\x42\xad\xe1\x67\x74\xc0\xfb\x22\x27\x25\x6b\xa2\x97\x7e\x25\xba\xdb\xaf\xa4\x32\x56\xca\x49\x2d\xa1\xd8\x14\xf7\x9f\x85\xce\xe1\x73\x52\x48\x66\x45\x0c\x5c\x63\x26\xb2\xd8\xc3\x80\xde\xa9\xe2\xb6\xe8\x81\x99\x68\xe9\xce\xe1\xe8\xb7\x97\x33\x1c\xbf\xfc\xf8\x61\x23\x5d\x19\x41\xc7\xf9\x16\x9e\x2e\x7f\xaf\xe2\x84\x6e\x31\xd4\xb7\x0b\x13\xe5\xaf\x8d\x1f\xe6\xcc\xaf\xe8\xec\xf9\x3a\x6d\x19\x87\x5a\xdd\x69\x32\x4f\x0e\x57\x2c\xf5\xd4\x70\x40\x9c\x1e\xee\x97\xff\x4e\x3c\x40\x33\x97\x2c\xec\x74\x79\xe1\x49\x6a\x1b\x84\xf9\x69\x4a\x7b\x89\x11\xac\xdc\x96\xc4\x14\x96\xe8\x5e\xe1\xc8\xaf\xd0\x5d\x66\x68\x0f\x2b\x74\xfb\x77\x43\x3d\x47\xdb\xae\xe6\xf3\xa8\xd6\x6d\xe1\x6c\xd5\x2e\x64\x33\xbd\x73\x9e\xfe\x7d\x89\xeb\xdc\xc8\xaf\xde\xc6\xc7\xd7\x33\xda\xec\xe9\xf1\xe9\x5b\x2a\x72\xa1\x31\x72\xb0\x81\x63\x99\xf2\x79\x65\xdb\x15\xca\x1e\x95\xc3\x16\xce\x56\x0e\xbb\x7d\xeb\x33\xb4\x05\x36\x93\x6f\xb2\xc2\x53\xfb\xd8\xa7\x1f\xdc\x8a\x25\x50\x19\xf5\x26\x62\x4f\xc7\xce\xcb\xe1\x21\x0c\x87\x89\xb8\x6d\xfc\x7e\x33\x39\x14\x98\xac\x99\x7b\x88\x4d\xe1\x67\x6c\x04\xdd\xab\x0f\xf9\x63\x67\x13\xf5\xe6\xb1\x7b\xd5\xd9\x7e\x0c\xed\xb3\xbf\xe3\x05\xbc\xcb\x07\x5c\x38\xea\x29\x96\x61\x3a\xa7\x75\x50\x43\xa8\x37\xb1\xac\xd1\xe9\xbb\xde\xce\xa7\x86\xce\xcd\xb5\x77\xdb\x46\x0e\xb2\xe7\xe7\x86\x6c\xf2\x50\x77\xd9\xf3\xd2\x24\x63\x7d\x6e\xd4\xc4\xb6\x5c\x4b\xb1\x46\x67\xf9\x0a\xcf\xd1\x4e\x59\x10\x54\x91\xed\xa5\x17\xfe\xf7\xce\x4c\x51\x90\xe3\x68\xb3\x51\xef\xac\xa2\x6c\x19\x87\xc6\x08\xa9\xe7\x47\x9d\x37\xab\x33\xb5\xeb\x47\xad\xec\xcc\x7e\xc8\x95\x98\x77\xbb\xb7\xb9\xee\xbf\xee\x65\xf9\xb9\x61\xec\x22\x8e\xcf\x0a\x6b\x77\x31\xfa\x60\x98\xbb\x88\xeb\x7d\xd8\x3b\x3d\xfc\x42\x18\x0c\xec\xec\xdc\xae\x9b\xdf\xbf\x6f\x52\x3d\xa4\x62\x86\xd3\x9b\xc0\xd5\x66\x51\xfb\xa7\xb7\x7a\xda\xad\xab\x30\xd7\xda\x16\x54\x5f\x31\x1b\xba\xfd\x8d\xf9\xf5\xa1\xb9\x71\xd9\xa6\xbe\xb1\x6f\x07\xd9\x2e\x36\x32\x4c\xe4\x5c\x53\xf4\x6b\x6b\xa6\xe3\x16\xad\x33\xeb\xaa\xcd\x32\x42\xf1\xe5\xe2\x85\xd3\x07\xa3\xe9\xd6\x8d\x58\x33\x5b\xd9\xf7\x7c\x9c\x89\x63\x3b\xdf\xf4\xf2\xf2\xe3\xc7\xf9\x75\x9d\xcf\xe1\x5e\x98\x98\x6c\x59\x23\x04\xcd\xbd\x38\x3d\xe1\x9e\xb7\xbc\xed\x56\xde\xa3\xce\x65\xdb\x7d\xf8\xdb\x53\x33\x94\xad\x13\x8e\x12\x2f\xbd\xee\x9b\xb3\x68\x43\xbd\x8f\x97\x06\x6d\xdb\x31\x2f\x0d\xf1\x57\xde\x27\x07\xbc\xef\x22\xbd\x32\xee\x22\xba\xfd\xa8\x0b\x18\x3d\x92\x0c\xa7\xe7\xa0\xd1\x08\xd9\x3b\x6d\xd8\x45\x41\x43\x41\x3d\xf3\x28\xe2\xfb\xdf\x1d\x67\x01\x87\xfe\xa5\x5e\x28\x3f\x38\xea\xa0\x0a\xdf\xb4\xad\x99\xa9\x7a\x2d\xc8\x23\x63\x32\x81\x3a\x7a\x0f\xd4\x70\x7a\x68\x09\x15\xf7\x98\xae\x40\x47\xc1\xc9\x26\x55\x8f\xdd\x9e\xd7\xc6\x8c\x25\xb3\x62\xb2\x80\xfd\xf6\x5b\x50\xf4\xff\xc4\xf0\x6f\xdf\xae\x81\x3a\xf5\xf8\x4e\xda\xff\xef\xdd\x04\xdc\x00\xef\x68\x32\x42\xe0\x43\x33\xe5\x11\x78\xd1\x06\x4f\x6f\xc6\x3f\xc1\x2a\x4f\xb7\x57\xdc\x18\xf4\x6f\x71\x90\x8f\x84\xfd\x6b\xad\x0c\xcf\x09\xfc\x57\xb0\x7c\x56\xe8\xbf\x93\xd9\x07\x83\xff\x15\x6c\xef\xc3\xff\xb9\x07\x2e\x24\x00\x47\xed\x2b\x4f\xd4\xd5\x9d\x7e\x06\x49\xba\x79\xbd\xb7\x0d\x1a\x57\x56\x91\xb7\x86\xf5\xcb\x11\xfa\xe4\xd8\x03\xea\x93\xf6\xb2\x59\xb0\x9c\x5f\xf1\x9c\x5b\x4b\xfe\x94\xd5\xa0\xbb\xec\x21\x73\x8e\x46\xd6\x04\x9d\xaa\xb0\xba\xcb\xcd\xda\xcc\x4b\xd9\x4e\xde\x1c\x23\x17\x9e\xb9\xb5\x59\x15\x9e\xbb\xed\x18\xba\x09\xdd\x99\x8d\x4e\x15\x03\x79\xe6\xdb\xbf\xfe\x7d\xc8\x8c\xfe\xf3\x7f\xa7\x72\xa3\x7f\xfd\x3b\x2c\x73\x34\xb6\xce\xd4\xed\x0e\xb0\x4c\xcb\x44\x17\x33\xad\x03\xac\xf7\x60\xb6\x9c\x19\x63\xd4\x93\x37\x61\xd0\x2b\xae\x73\xf6\x26\x65\x3d\x52\xcb\xd3\x37\xc7\x86\xd9\x3b\xa3\x3d\xe7\x07\xf4\xc2\x11\xf6\xe4\xa0\x2d\x5e\x1d\x4e\x8e\xc6\xa2\xa5\x6b\xc3\xde\x46\xd4\xc8\x76\xbc\x59\xf8\xd7\xbf\xc3\x2b\xdc\xe3\x20\xbd\x99\xb2\x0d\xdb\x3a\x52\xaf\x2f\x61\xb7\xf5\x54\x43\xdd\xb9\x85\x5d\x5b\xdc\x2d\xbe\xcc\xf7\x0b\x5e\x0f\xe2\x95\x8e\xbb\xba\xd8\xb8\x50\x7b\x0e\x56\xf9\x82\x95\xe7\xfb\xd6\x66\xcf\x63\xe2\xc6\x86\xc4\x8b\x4c\x5d\x5c\xd3\xdd\xc2\xe4\xd9\x94\xe0\x69\x6c\xde\xdc\xd3\x79\x91\xd1\x2b\xf1\xeb\x34\xab\x29\xe8\x42\x4c\xb3\xec\x2b\x3b\x70\x58\x4a\x68\x08\x57\xd8\xcb\x49\x75\xb1\xd6\xc0\x72\x52\xa3\x7c\xb4\x0b\xe7\x85\xfb\x3a\xf6\x1b\x78\xc5\x5e\x68\x7c\x77\xbd\xbc\x62\xc4\x2b\x86\xbf\x62\x2f\x2f\xdf\xfe\xb8\xfa\x2c\x71\xe1\xd9\x33\xac\x5c\xda\x41\xbb\x97\x9d\xf0\x2e\xda\x8e\xac\x17\xd0\x33\x4c\xc3\x35\xe0\xa8\xe7\x2f\xc0\x7f\x77\xa6\xa3\x97\x57\xec\x85\xc0\x01\xff\x1d\x67\xbe\xe3\x24\x06\xb8\x1f\x04\xf7\x83\x62\x7f\xc7\x49\x82\xe2\x99\x18\x4e\x84\x19\x3e\x0b\x9d\xe8\xf9\x27\x55\x8e\x66\x53\x5e\xf5\x5c\xcb\x50\x2f\x63\xe2\x19\x9a\xbd\x07\x13\xd9\x9b\x39\xe8\xe0\x02\x0d\xf3\xdd\xe9\x98\x8b\xf8\x28\x0a\xa7\xb8\x7b\xf0\x51\x3d\xa8\xaa\xbd\x70\x8d\xf1\x22\x0e\x9a\xa2\x49\xe2\x1e\x1c\x74\xcf\x0f\xfa\xbb\xe5\x87\xb7\x37\x7d\x11\x05\x43\xe2\xc4\x5d\x6c\x30\x3b\x14\x5b\xcf\x79\x03\x0a\x8e\x02\xf4\x3d\x28\xd8\xde\xd8\x52\x0d\x6d\x75\x3b\x17\x1c\x60\x88\xbb\x50\x70\x47\x5c\x6c\x5b\xd2\x6f\xc0\xc3\x52\x0c\x79\x1f\x9e\xcd\xa4\x43\x5d\xb7\x91\x0e\x5d\xcb\xbe\xac\x53\x3c\x0e\x70\xfe\x1e\xf0\xbc\x07\xde\xaf\x3f\xf7\x96\xaa\x7d\x19\x3a\xc1\x82\xbb\xa6\x1a\xe0\x1e\xf8\xed\x2c\x78\x35\x80\xcb\x08\x68\x9e\xbd\x4b\x3a\x00\x04\x11\xec\xd7\x86\x1b\x07\x70\x19\x11\xcf\xf0\xf7\x71\x42\x1c\x4d\xf4\x76\x35\xee\x1f\x82\xbe\x84\x09\xe0\x2c\x4d\xdd\x35\x23\x80\xf4\xd9\xd9\x17\x3f\x2e\xce\x38\x00\x04\xcb\xdc\xc7\x09\xd5\xd3\x8c\xe5\xee\x40\x88\x35\x1e\xf5\x34\x03\x8d\x2e\xba\x46\x00\x68\x00\xee\x72\xc2\x80\xde\x65\x84\xbb\xfd\x89\xe5\x15\x36\x18\xf6\x3e\x37\x0f\x98\x9e\x61\xea\xc8\x71\x7b\xef\x77\x40\xae\xa0\x62\x79\xee\xbe\x19\x61\x8f\xd2\x04\x6f\xab\x09\x5e\x0e\x26\x80\xc0\x71\x92\xba\x0b\x09\xb7\x57\x5f\xcd\xb2\x77\x29\xf3\x11\x0e\x80\x7f\x27\x01\x06\xa8\x1f\x80\xff\x41\xf1\xbf\x03\x82\xe4\x48\x3a\x86\x83\x0b\xf1\xfc\x62\x6f\xc6\xbd\x01\xfd\x5d\x7f\x46\x30\x49\xc9\x08\x74\x3b\x51\xe9\x0a\x74\x97\x6a\x0b\x62\xb6\xd3\xae\x11\xcd\x42\x99\x68\x96\xa9\x44\x33\x93\x6d\x56\x59\x4a\x6c\x56\x0a\x65\x89\xa8\x66\x5b\x54\xbb\x96\x2d\xe7\x6a\x52\xa1\x90\x7d\x27\xa0\xb3\x48\x36\xd9\x4c\x26\xd9\x29\x64\x98\x9a\x44\x95\xa5\x9c\x58\x49\x96\xa4\x74\x82\x25\x09\x81\x22\x99\x37\xba\x22\xa5\xea\xb5\x62\xa6\x5d\x60\x33\x89\x62\xb2\x54\x2d\xe6\xd2\x65\xaa\xce\x8a\xdd\x76\xab\x79\x33\x12\xd2\x43\x42\x90\xd5\x34\x91\x6d\x8a\x34\x21\x94\x3a\xcd\x74\x33\x4b\x0a\xdd\xbc\xd0\xe9\x64\x3a\x9d\x16\xd1\xca\x76\xba\xdd\x1a\x23\x76\x3b\x62\xa3\x52\x48\x75\xde\xea\x42\x9b\x61\x3b\x65\xea\x66\x24\x94\x87\xa4\x5a\xe9\x66\xb2\x54\x81\x66\x3b\x89\x94\x28\x15\x0a\x1d\x9a\x2e\xa4\x1a\xed\x72\xa3\x40\xb7\x53\xed\x5a\xb5\x9c\x25\x8a\x59\x31\xd5\x21\xc5\x42\x2b\x57\xad\x15\x4b\x62\x3d\x93\xc8\xdc\x8c\x84\xde\x20\x49\xd4\x2a\xdd\x6c\xae\x48\x24\x73\x64\x5a\xaa\x52\x89\x4e\x31\x5d\x92\x52\xc5\x74\xbe\x29\x55\x9a\x44\xb6\x4b\xbe\x95\xd2\xf5\x6c\x59\x6a\x26\xc5\xb2\x50\x6f\xb3\xd5\x24\x5b\xee\x10\xd9\x97\xa8\x0d\x4b\x9b\x5c\xfb\x8a\x42\x6d\x9b\x3c\x0f\xfd\xd9\xbf\x3b\xe8\x72\x33\xcf\x2b\x46\xbf\x62\xae\x3d\x43\x37\xa8\xf9\xfb\x36\x9d\xc8\x4a\xee\x2f\x05\x83\x2a\xae\xd8\x48\x35\xdc\x1e\x1c\x4d\xfa\xd0\x9c\x8d\xa9\x8d\x61\x36\xeb\xa9\x97\x8f\xd0\x99\x63\xec\xc4\x19\xec\x62\xb3\xf6\xf2\xa0\x32\x45\x69\x8b\x79\xca\x2c\x1f\x2d\x9b\xbd\xb5\xc9\x6d\x73\x7c\xaa\x2b\x26\xea\x24\xef\x3a\x63\x02\x72\x26\x39\x86\xa6\x58\x9c\x67\x19\xf0\x8a\x81\x57\x8c\xdc\xb8\x84\xff\x7c\xf5\xf7\x39\xbe\xfe\xc0\xbe\x46\x75\x74\x5f\x5f\xb1\xaf\xbb\x90\xfe\xf5\xc7\x86\xdf\xaf\x8e\x35\x52\xb7\xa9\xc4\x06\x32\xc5\xff\xce\xfb\xd7\x66\xac\x6c\xcd\xf4\xbe\x1b\xbc\x4d\xff\xbe\x5d\xca\x7d\xdd\x3f\xbb\x6f\xfd\xda\x0c\x68\xd6\x53\xa1\x3b\xee\x6a\xe2\xdd\x09\xeb\x4e\x10\xfe\x11\x08\xb1\x59\x7b\x77\xef\x12\x90\x00\x2e\xbf\xa3\xcc\x93\x50\x44\x63\x78\x87\x39\x08\x32\x9a\x86\x7f\xfd\xbf\x73\x16\x16\x9e\x7a\x10\x9a\x7a\xe2\xd4\xd4\x47\x0c\x3f\x37\x4c\xfd\xd1\xdc\xbe\x9f\xfa\x23\xcd\x38\x31\xf5\xdb\x79\x7b\x64\xea\xb7\xda\xf3\xe8\xd4\x47\x9c\xa7\x4b\x53\x1f\x51\x9b\x6e\x9e\xfa\xb0\xd5\x93\x1f\x67\xf5\xe4\xfb\xa9\x07\x38\x7e\x71\xee\x39\xfc\x6f\xb3\xff\x3c\xb3\xa7\x3e\xce\xec\x4f\xcc\x3d\x77\x79\xea\x43\xaa\xf1\xb7\xdd\x3f\xdf\xee\x29\x92\xe6\x59\x8a\xa0\x18\xfa\x43\xa3\x3d\xb8\xdf\xee\xaf\x4f\xfe\xdf\x86\xff\xa0\xe1\x07\x27\xff\x03\xe3\xfd\x87\x4c\xfe\xdf\x96\xff\x44\xcb\xff\xc0\x88\x7f\x22\xd9\xa3\x2f\xcf\xfd\xdf\x79\xfe\x67\xda\xfd\x07\x06\xfc\xfb\xf3\x7c\xfa\x6f\xab\xff\x58\xab\x07\x2c\x60\x79\x8e\x25\x09\xce\x5f\xdd\x13\xde\xcc\x07\x27\xe0\x68\x06\x4e\x4a\xee\xba\xc8\x3e\x9f\x35\x32\xc4\x1a\xe1\xf9\xb4\xff\x0a\xd6\xc0\x9e\x35\x96\x64\xd9\xfb\x67\x6d\x6b\x32\x51\x58\xfb\x68\x5f\x44\x85\x58\xbb\x77\xd6\x7e\x61\xd6\x36\xb6\x46\x70\x1c\xc5\xe3\x34\xcf\xf9\xb9\x35\x81\x7b\xbc\x8d\x8c\xb1\xe1\xb1\xc6\x13\x04\x49\xb2\x04\x4e\x32\x1c\xfd\x3b\xc5\xb2\x34\x87\xb3\x7f\x39\xcd\xf4\x78\x04\x38\xbe\xf3\x27\xff\x6d\x3c\xee\xe7\x11\x50\x60\x67\x7d\x91\x78\xfc\x85\x75\xf5\x30\x8f\x1c\xc1\x92\xff\x9d\x3c\x12\xaf\x18\x47\x73\x3c\x4f\x72\x0c\xc7\x7b\x2c\xfa\x1c\x3a\x2e\xb4\x5d\xc3\xd4\x7b\x32\x1c\x41\x53\x41\xe1\xc5\xc7\xcd\x08\xe8\x63\x04\x27\x5c\x19\x38\xe5\xca\x76\x52\x32\xa1\x6b\xcc\x51\x64\x7e\x36\xb3\xe6\x33\xb4\x40\x86\xde\x77\xb7\xab\x2e\x7f\x23\xa0\x37\x44\xab\x87\xd2\xba\x7b\x34\xc9\xa3\x8a\x22\xd8\xad\xd3\xfb\x20\x29\x6f\x11\x7c\xb4\x94\x43\xfc\xdc\x26\xe5\xa8\xeb\xa6\x7b\x92\x1d\x9f\x2a\x86\xdb\xba\xdd\x8f\x92\xb2\x8f\xe0\xa3\xa5\x1c\xe2\xe7\x46\x5d\xfe\x68\xcf\x4f\x6d\xa9\xa2\x71\x7e\xeb\xf8\x3f\x48\xca\x5b\x04\x1f\x2d\xe5\x10\x3f\x37\x4a\xf9\x11\xbf\x7c\x65\x23\xf3\xd4\xb1\xf6\xa8\x1b\x99\xbb\xa3\xed\x3b\x66\xf9\x57\xec\x85\xe2\x18\x45\x26\x34\x04\x49\x48\x31\x1c\x0f\x54\x12\x07\x90\x51\x55\xa0\xe2\x8c\x86\xf3\x2a\xa9\x68\x88\x01\x14\xa5\x6a\x38\x4f\x73\x80\xe3\x38\x88\x6b\x34\x20\x78\x1e\x29\x90\x52\xf8\x97\x57\xec\x45\x46\x10\x41\x86\x24\x58\x9c\x50\x11\x8d\x6f\xfe\x03\x1c\xc1\x29\x0a\xa5\x31\x1a\xa1\x41\x1a\xb0\x2c\x4b\xe3\x90\x26\x34\x4d\x66\x35\x9e\xc3\x11\x8e\x90\xac\xb0\x3c\x40\x0c\xaf\xc2\x17\x4f\x71\x40\xa8\x4b\x86\xf9\x41\xd2\x3f\x00\x17\x6e\x9e\xf1\xbf\xa6\x7e\xa7\x19\x40\x72\xd4\xd5\xbb\xdb\xba\x3d\xcd\x30\x9b\x3c\x9a\xd9\xcc\xe7\xbb\xeb\x15\x03\xb4\xf7\xef\xf6\x9f\xfd\xb7\xfb\x3f\x36\xb4\x09\x82\x20\x24\x59\x66\x36\x19\xe4\x17\x45\xd4\x2c\x37\xcb\x99\xe4\xa0\xd4\x20\xb8\xf9\xa4\xa6\x92\xcd\x42\x73\x1e\x23\x63\xdd\x94\xce\xda\x4b\x3a\x3b\x36\xe1\x90\x5f\x27\xb9\x4c\x25\xcf\xbc\xad\x33\x15\x3a\x56\x69\x5a\x71\xda\xcc\xc2\x51\x7e\x55\x49\x15\xc0\xd2\xca\xb0\xd6\x84\xb5\xd7\x5c\x2a\x47\x6d\x40\x0b\x9d\x4a\xab\x54\xd3\x85\xfd\x45\xcf\xd8\x6c\x39\xc1\x29\x1d\xbc\x6d\x4e\x8d\xa5\x39\x5f\x97\x47\x5d\x32\x45\x76\x49\xab\x82\xab\xdd\xf5\xba\xcd\xaf\xda\x66\x4b\x1e\xe3\x70\x41\xaf\x2a\x4d\x73\x3d\x40\x8b\x15\x15\xb3\xa9\x05\x9a\xf3\xcd\x61\x9d\xad\xb4\xaa\x71\x71\x9a\xb2\x72\x4d\x7d\x1d\x4f\x20\xb2\x95\x1e\x7b\xf0\x87\x12\x55\x84\xeb\x09\x51\x3d\x20\x13\x3a\x8a\x70\x7c\x89\x9b\x7f\xde\x84\x0e\xa0\xaa\x82\x90\xc2\xf3\xc2\x5f\xed\xf2\xb5\x0a\x3f\x63\xf8\x61\x5b\xe0\x9e\xa3\xc7\x2f\xb8\x4a\x6a\x24\x45\xca\x84\xc6\x6b\xb8\x02\x91\xac\x12\x88\x97\x69\xa8\xd2\x04\x49\xaa\x24\x47\xa9\x2a\xd2\x68\x86\x45\x38\xd0\x54\x45\xe5\x10\xcb\xcb\x24\x64\x34\x1c\xe0\x08\x50\x8a\x7a\xc9\x16\xd8\x73\xda\xce\xe0\x0c\x8e\xf3\x57\xef\xfa\x25\x2d\x92\x23\x19\xee\x92\x2d\x50\x37\xda\xc2\x02\x8f\x4b\x29\x67\x6e\x2e\x56\xb3\x79\x9d\x91\xdb\x6e\x73\x50\x69\xf4\x25\x72\xde\x32\xa9\x44\x5c\x21\xca\x48\x2e\x8f\xb9\x44\xaa\xdf\x90\xd2\x31\x04\xe2\xa0\xb0\x6c\xae\xcb\x2c\x65\x66\x33\xe4\x70\x3a\xcc\x4c\xea\xe3\xb4\x0a\xfb\x6f\x79\xb3\xaf\x88\x49\x7d\x9a\xa3\xda\xb3\x11\xe7\xcd\x9d\x67\x0b\x41\xf5\x2c\x97\x32\x2b\xb4\x2c\xcf\xd0\x7c\x48\x55\x73\xdd\x64\x21\x8e\x88\x46\xb1\xda\x41\x8a\x18\x6f\x24\x66\x33\xa0\xce\x33\x55\x63\xd4\x70\xa4\x79\x01\xd8\xf2\x9c\xca\x8a\x23\x5a\x4e\x0a\xcc\xa4\x35\x4f\x95\x16\xf4\x58\x64\xf2\x8a\xa6\xd4\xea\xa5\xe4\x50\x26\x67\xd4\x82\xe8\x94\x3c\xf8\xfa\x09\x5b\x68\x51\x21\x55\x4a\x09\xff\x53\xb6\xc0\x3e\x47\x8f\x5f\x14\x12\xf2\x8a\x4a\x12\x8c\xc6\xe0\x90\xa7\x28\x82\x55\x15\xa8\x22\x99\xe1\x79\x95\xd4\x18\xa4\xa8\x24\x4f\xd2\xa4\xa2\xf0\x24\x01\x15\x85\x55\x09\x96\xa2\x01\xc1\x92\x24\xc1\xc8\x9a\xc2\x5d\xb2\x05\xe6\xac\xb6\x13\x34\x8b\x5f\xbf\x4b\xe2\x38\x43\xb1\x2c\xc0\x59\xe2\x92\x2d\x90\x37\xda\x02\x57\x9e\xac\x1b\xf9\x79\xb7\x30\x12\xf3\xfc\xca\x65\x88\xb1\x5a\x21\x58\xa9\xdc\x68\x72\xab\x46\xc1\x59\xf2\x79\xbc\x59\x57\xd6\x79\x3b\x9e\x9b\x25\x56\x56\xb5\x3c\x1d\x37\x84\x52\xb3\xb1\x64\xf4\x15\x3e\xe8\x5b\x99\x0c\x48\x1b\x45\x93\x9c\xe5\xaa\x29\x71\x46\x13\x0d\x07\x90\x5a\x20\x2e\x04\xe6\x92\xc3\x01\xc8\x71\xca\x02\x19\xad\x66\xb1\x36\x64\xf5\x58\x8e\x44\xed\x52\x7c\x18\x6b\xc6\x9c\x79\xb1\x38\xcf\x17\xb9\x0e\x2f\x4a\x09\x30\x59\x14\x73\x55\xbd\x9a\x4b\xcb\x8d\xf5\x3a\x91\x2e\x4c\xd9\xe2\x28\x36\x24\xda\xc4\x5c\x1d\x64\xaa\x4e\x75\x81\x96\xda\x6c\xd0\x6d\x25\x71\xdc\x83\xac\x9c\xb0\x85\x66\x33\xa4\x4a\xff\x63\xb6\xc0\x3c\x47\x8f\x5f\x64\x05\x41\x9c\x66\x11\x50\x54\x02\x00\x95\x50\x34\x99\x45\xa4\x26\xf3\x3c\xad\xa9\x14\xad\xa8\x0c\xa4\x28\x82\x00\x1a\xc9\x41\x45\xc1\x69\x82\x90\x29\x5a\xe6\x14\x0e\xa8\x3c\x43\x13\xd4\x25\x5b\xa0\xcf\x6a\x3b\xc9\xe1\x34\x71\xf5\x2e\x41\xb3\x0c\xcf\xe1\x24\xcb\x32\x97\x6c\x81\xb8\x35\x47\x5a\x4f\x13\x1d\x4a\xc1\xfb\xd9\xfa\x9a\xd5\x06\x31\x7a\xa4\x81\xf4\xba\x3d\x11\x73\x7d\x8e\xb2\x4b\x89\x7a\x01\x6f\x53\xab\x04\xd1\x6e\x0e\x07\xe3\xd2\xd4\x8d\x11\xe2\x7c\x9e\x10\xdf\x60\x31\xc3\xb8\xf2\xb8\x6d\x8f\xca\x30\x91\x91\x26\xd3\x3a\x5f\x8b\x69\x2d\x36\x05\x92\x40\xf6\xd2\x11\xcf\x16\xaa\x8b\xc3\x5c\xce\xaa\x76\xa5\x6a\x13\xd3\x91\xd4\x9a\x24\x73\xd3\x7e\x15\xa2\x6a\xc9\x49\xf1\xf9\x76\x5b\x82\xcb\x5c\xbd\x9c\x5b\x94\x9c\xe5\xdc\x18\xe5\x9a\x42\x52\x8d\xe5\xbb\x4e\x79\xd5\x12\x4b\xb6\x2e\xce\xcb\x05\xc6\x10\x8a\x4a\x1a\xb5\xe5\x82\x59\x36\x66\x95\xbc\x32\x9a\x89\x6e\xcb\xe0\xbd\x1c\xa9\x7b\xc2\x16\xea\x8b\x90\x2a\x25\x85\xff\x29\x5b\xa0\x9f\xa3\xc7\x2f\xac\x22\xab\x84\x42\x33\x90\x91\x49\x8a\xd4\x20\x8e\x6b\x1c\x8b\x08\x8a\x60\x28\x15\xd1\xb4\xa6\xe1\x2c\x22\x09\x8d\x94\x01\xc5\xe3\x1c\xa5\xf2\x3c\xa2\x19\x1a\x69\xb8\xa2\x52\x1a\x4e\x5c\x5c\x2f\x9c\x5d\x11\x30\x14\xcb\xf1\xe0\xea\x5d\x02\x50\x2c\xc5\x91\x0c\xc5\xe1\x97\x6c\x01\xdc\x68\x0b\xe4\x8a\x2f\xa6\xe1\xd8\xc1\x2b\x8c\x50\xe9\xc7\xf2\xc9\x37\x89\x6e\xc5\x17\xda\xa0\xb8\x76\x9a\xc3\x5c\xe3\xcd\x1c\xbd\x21\xae\x04\x2a\xc2\x34\x17\xcf\xa7\xcd\xb5\x31\xac\x2e\x46\x42\x3b\x41\x4c\x92\x3c\xdf\x85\xf1\x96\x5c\x25\xf2\xf5\x51\xc7\x9e\x2c\x25\x5e\x54\xf9\x62\xdc\x4e\x95\xbc\xb9\xf3\x6c\x21\xb8\x5e\x70\xd3\x70\x18\xd7\xfa\x6c\x49\x2c\x1b\x6e\x7f\x30\x5a\xa9\xa2\x9d\x68\xe2\xf1\x12\x6e\x8c\x20\xd2\x66\xa0\x29\xe3\xc9\x05\x50\xe4\xea\x5a\x8a\x4f\x4b\xfd\x91\xde\xef\xe4\x9d\xfe\x40\xd4\xd9\xe9\x98\x6b\xe1\xd2\x32\x9b\x18\x50\x6f\x65\x63\x58\xee\xe0\x75\xa6\x6a\x96\xd6\x7e\xdc\x69\x9e\xb0\x85\x5a\x29\xa4\x4a\x09\xe1\x7f\xca\x16\xa8\xe7\xe8\xf1\x0b\x84\x2c\x49\xca\x0c\x02\xbc\xca\xab\x40\xd5\x70\x0e\xca\x1c\x54\x80\x2c\xb3\xb8\x82\x78\x0a\x40\x55\xe6\x15\x12\xf0\x2c\x60\x54\x59\x46\x2a\x2e\x73\x24\xa4\x34\x9e\x05\x2c\xa4\x08\xd6\x6f\x8a\x26\x4e\xaa\x35\x79\x56\xdb\x19\x1c\x27\xaf\xdf\xf5\xb7\x9d\x18\x1e\x70\x17\xd7\xce\xf8\x8d\xb6\xc0\x4c\xd6\x65\x82\x7a\x23\xd4\xac\x96\x2c\xcc\x0a\x0b\xd9\x5d\xac\x27\x55\x48\xd0\x8b\xe5\x68\x29\xcb\x73\x37\x49\x95\x87\xb1\x4e\x9a\xa9\x9a\x83\x61\xbf\x33\x6b\x0c\x53\x6d\x77\x44\x15\x25\x39\xde\x95\xaa\x8d\xc1\x24\x2f\xe6\x32\xa9\x18\xef\xf4\x07\xce\x9a\xcc\xaf\x9d\xe9\x9c\x8a\x77\xbd\xb9\xf3\x6c\x21\xa0\x9e\x12\x9d\xa0\xdb\x7c\xc1\x59\x5a\xe5\x4e\x79\xe2\x28\x92\xa4\xa6\x0c\x13\xce\xa4\x65\x32\x5e\x59\x10\xc3\x21\x9b\x4a\x35\x2d\xbc\xde\x29\x77\xde\x4c\x37\x25\x2c\x1b\x5a\xc7\x64\x98\x31\x9f\xeb\x8b\x78\x67\x3c\x32\x60\x61\x3e\x44\xb9\x89\x94\xd7\xd6\x7c\xa1\x22\x5b\x42\xee\xad\xec\x79\xff\xea\x09\x5b\xa8\x58\xa7\xf4\xe9\x2f\x6e\x0b\xc4\xed\xb6\x40\x3e\x47\x8f\x5f\x68\x99\x61\x48\x4a\x51\x78\xc4\x03\x9e\xd7\x54\x52\x93\x65\xa8\xe1\x0c\x4d\x2b\x34\xa5\x40\x1a\xb1\x32\x07\x08\x95\x66\x08\xc4\x90\x48\x81\xb8\x26\x13\x32\x0f\x39\x5e\x06\x1c\xae\x50\xda\x8b\xd7\xa8\x41\x9d\x54\xeb\xf3\x59\x10\x4b\x10\xd4\xf9\xb8\xb0\xbb\xbb\xdd\xa7\x04\x1c\x77\x69\xed\xcc\xdd\x68\x0a\xc0\x1d\x4b\xa5\x15\x1a\xbe\x99\x7c\x85\x9d\xcd\x13\xa3\x4e\xba\x51\xe8\x98\xb3\x44\xb1\xd5\x9d\x75\x63\x2b\x3d\xb6\x9a\x41\x43\xce\x08\xcb\x8a\x48\x0b\x65\x37\x46\x90\x64\x23\x5b\x71\x1b\x92\xdc\x34\x07\xf5\x45\x65\x3e\xb6\x18\x9d\x5c\xaf\xd2\x4a\xba\x62\x29\x5c\xab\x58\xc9\x64\xfc\xa9\xf3\x4c\x21\x30\x95\xf5\xfe\x7a\x9a\xe3\x61\xb1\x1b\x63\x0b\x13\xfa\x6d\x41\x32\x5d\xc4\xe2\xa4\xf1\xb6\x34\xb3\x02\x95\x5a\x80\x31\x5d\x48\x53\xb5\x6c\x61\x5c\x96\x6a\x45\xa3\x93\xa0\x61\x56\x2b\x08\x99\xb6\x4d\x66\x97\xd6\xa8\x5a\x5d\xea\xab\x65\x27\xa9\x0e\x2a\x2b\xc8\xbc\xb5\xd6\xb0\x55\x4f\x37\x3c\x53\x28\x9d\x30\x85\x92\x7e\x4a\x9d\xfe\xe2\xa6\x40\xdd\x6e\x0a\xc4\x73\xd4\xf8\x85\x21\x55\x9e\xd3\x68\x92\x41\x88\xe1\x54\x20\x13\xac\x4c\xcb\x1c\xaf\x11\x24\xd4\x68\x12\x00\x99\xa5\x19\x1e\x12\x94\x06\x35\x40\xe1\x24\x54\x71\x99\x26\x64\x86\x24\x65\x9c\x95\x11\xcf\x5f\x32\x85\xf3\xca\xce\x31\xd7\xee\xf9\xdb\x69\x14\xcd\x5f\x5a\x35\xdf\x5a\x40\x22\x2a\x6f\x03\x20\xcd\x68\x0b\x97\xf3\x6c\x9b\x32\x57\xe5\x79\x73\x99\x21\x5b\x13\x6b\x18\x9b\xa7\x85\xb2\x9b\x04\x05\xa2\xc4\x26\x58\xe6\xad\xcf\x11\x55\xdd\x99\x09\xf5\x71\x1d\x5f\xea\xe9\x09\xd0\x06\x46\x83\x58\x48\xfa\xbc\xd5\xae\x25\x47\xf5\x36\x3d\x2b\x55\x48\x8a\xaa\x97\x7c\x5f\xbc\xb1\x82\x8a\xa7\xa5\xb9\xfd\x3f\x82\xa7\xa8\xce\xe1\xf3\x42\xa8\x54\x87\xfe\x2c\xf7\x59\x3b\x9b\x25\x51\x7f\x3a\x6f\x3a\x6d\xb1\xa2\x09\xa3\x79\xcb\x99\x08\x02\x11\x7f\xab\xe1\xf9\x41\x45\x48\xe7\xd4\xac\x5c\x25\x9c\xba\x31\xcb\x2f\xcd\x26\x3b\x5a\xc5\xd6\x68\xf9\x36\x73\x3a\x4b\x5c\x2a\x76\x56\x56\x81\x9e\xb7\xaa\xb9\x79\x6a\x9d\x32\x63\xe9\x71\x37\x5d\x46\x7d\xcf\x16\x72\x27\xac\x24\x53\x3d\xa5\x69\xff\x3b\x56\x02\x9e\xa3\xe1\xde\x7b\x70\x30\xdc\xdf\x73\x02\x3c\x8b\x7f\xc7\xc1\x77\x1c\x60\x38\xfe\xc3\xfb\xef\xac\x2e\xf3\x1c\x43\x9e\x0f\x08\xbb\xbb\x14\xc1\x53\x3c\xc3\x12\xfc\xa5\x55\xf1\x69\x4d\xf7\x49\xfa\xd9\x93\x72\xfe\x4a\x74\x0a\x06\xb5\x8a\xaf\xea\x85\x04\x9b\x32\x53\x7c\x96\xc0\x97\x83\x44\xcc\xc1\x75\xd7\x59\xe4\x16\x6b\xd0\x51\xeb\xed\x2e\x4c\xe4\x61\xda\x53\x62\xf1\x84\x12\x9f\xbe\x76\x4a\x2c\x08\x89\xe1\x27\x30\xf2\xd4\xeb\xc5\x57\xa6\xeb\x9b\x72\x37\xbc\x14\x37\xea\x1e\xdd\x99\xf7\xf2\x9c\x3d\x80\x76\xc6\xe2\xae\x80\x09\xb7\x36\x47\x04\x43\xee\xeb\xa8\x34\x60\xf8\x57\x0c\x44\x03\x43\xed\x4b\x50\x2c\xe7\xb5\xd6\x44\x03\x43\xef\x56\xef\x14\x4e\x7b\x9b\xd1\xd1\xc0\x30\xa1\x2e\x49\x32\x1a\x18\x36\xdc\x6c\x19\x0d\x0c\x17\xea\xfe\xa3\xa2\x81\xe1\xc3\xfd\x91\xd1\xc0\x00\x3c\xd4\xb1\x17\x91\x2b\xf0\xae\x2b\x2e\x22\x9c\x70\xe7\x59\x54\x7a\xc8\x70\x77\x57\x44\x38\xd4\x71\xc7\x11\x1d\x11\x4c\xb8\x4f\x2a\x22\x18\xe6\xb8\x33\x27\x2a\x35\x6c\xa8\x61\x29\x22\x18\xee\xb8\x83\x25\x2a\x35\x7c\xa8\x11\x26\xa2\x07\xc4\x8f\x3b\x3d\x22\x52\x43\x80\x63\x30\xd4\x73\xde\x2a\xfe\x94\xc3\xf3\x97\x5f\xcf\xb6\x71\x96\xb7\x9e\xa6\x3f\xf3\x72\xed\x87\x63\x5c\x20\x92\x1c\x1d\xad\xdd\x7f\xc0\xfd\xf3\x76\x5e\x07\x8e\xf7\x62\xa0\xaf\x3f\xb0\xaf\xf8\xef\x9c\x9f\x6a\x79\xed\x3e\x87\x3e\x20\x1a\x04\xfb\x80\xfc\x77\x09\xdb\x5f\x7f\x60\xff\xf9\xaa\x7e\xfd\x81\xd1\xaf\xd8\x57\xf3\xeb\x0f\x8c\xfa\xbf\xe3\xf3\x17\xf8\x2b\xf6\x55\x9e\xad\x0c\x53\x3f\x73\xfa\x25\x78\xef\xe2\x11\x08\x34\x1a\xbd\x87\xb2\x3b\x86\x73\x74\xf3\xe2\x71\x8c\x20\xbe\xe7\x9c\xa5\x38\x46\xfe\x94\xc6\xe0\x0f\x78\xcd\xca\x29\xad\x38\x3a\x7e\xb5\xff\x40\x9d\xd6\x0a\xfe\xb4\x56\xe0\x97\xb4\x62\x13\xd0\x3c\xb5\xe0\xff\x56\x8b\xbf\x8e\x5a\x04\x73\xce\xc3\x07\xee\x94\x5a\x80\xdf\x09\xfa\x84\x5a\x70\x17\xb5\x82\xda\x2a\x05\x7d\xab\x52\xec\x8e\x4b\x3d\xa6\x14\xbb\x73\x5b\x8f\x2b\x45\xf4\x23\x77\xe7\x95\x22\x72\x93\xe3\x07\xbc\xf7\xe9\x84\x52\x1c\xad\x20\x0e\x1f\x88\xd3\x4a\x01\xfc\xeb\x58\x29\xf8\x2b\xae\xe2\xb0\xc4\xf7\xb4\x03\xec\xaf\xbf\xd5\xe4\xaf\xa3\x26\xc1\x15\xe2\xe1\x03\x73\x5a\x4d\xf0\x93\x21\x05\xbf\xac\x27\x3b\xf5\xf8\x5b\x2b\xfe\x32\x5a\x71\x7c\xe2\x73\xff\x01\xdf\x37\x1a\xfc\xe7\xab\x6b\x3d\x7a\xe8\x57\xb3\xad\xf1\xa3\x12\xfe\x85\x4f\x6a\x7e\xc0\x0b\xce\xce\xcf\xd4\xb6\x8a\xb1\xff\xc0\xbc\x9f\xa9\x07\x4e\xe6\x1f\x66\x2a\x7a\x76\xf5\x0b\x9f\xce\xfc\x80\x37\x0b\x9e\x9a\xa9\xa3\x93\x9d\xfb\x0f\x7e\xf2\xce\xdc\x76\x72\xce\xb5\x67\x8e\x8b\xd0\xa3\x56\xe3\x81\xb1\x1e\x3e\xb5\xff\x8b\xd8\xd8\x87\xe7\xd7\xc7\x95\xb9\xfd\x07\xfc\x27\xcf\xdc\x03\x06\xfd\x6b\xcc\xdc\x27\xc4\xb1\xa3\x53\xb8\xfb\x0f\x4c\xe4\x99\x8b\xee\xff\x3e\xc4\xe6\x7e\x9a\xb7\xfc\x2c\x9b\xdb\x56\x9f\xf7\x1f\x88\x9f\x3c\x73\x4f\xb3\xb9\x9f\x35\x73\x1f\x6f\x73\xc1\x42\xfd\xfe\x6f\x2e\x70\x16\x52\x9b\x99\xea\x96\x97\x88\xaf\xda\xf5\xe4\xe2\xbf\xf0\xf6\x51\x7b\xba\x7e\x30\xf3\xc1\x57\x02\xdf\x23\xb5\xed\x86\xc2\xfe\x6f\xea\x43\xa5\xf6\x80\x2e\xff\x5a\x52\xf3\x37\x3e\xf6\x7f\xe3\x1f\xab\x6b\x0f\x2c\x07\x7f\x25\xa9\x6d\x37\x68\xf6\x7f\x33\x1f\x2b\xb5\x07\xca\xb2\x1f\x2d\xb5\x2b\x9b\x3d\x27\x7e\x84\x33\xea\x46\xcf\xf6\x87\x38\x4f\x6e\xf2\xe0\x67\x8f\xfb\xfa\xfd\xcc\xe0\x15\xa3\xb6\xaf\xb3\xe5\x77\xef\xf3\xa1\xe8\x7d\x05\xce\xfb\x25\xd1\xd7\xa3\xa2\xdc\xa1\x1e\xe7\x35\x23\x9d\xdb\x34\xbd\x44\xd4\xf9\x33\xc8\xe4\x8e\xa8\x23\x8c\xde\x97\x1c\x1e\xa6\x8a\xf2\xde\x46\x4e\x9d\xdf\x9c\x0c\xd3\x10\xdc\xe7\x38\x2d\x18\xf6\x65\x87\xee\x24\x0d\xc1\x6f\x76\xa2\xf1\x65\xc8\x00\xc0\x70\x0c\x4e\x13\x2c\xc7\x02\x12\x27\x2f\xf5\x69\x5c\x22\xeb\xfc\x91\xd4\xfd\x7c\xd1\x61\xaa\xee\x98\xaf\x53\x64\x12\x37\x29\xeb\xf5\x5f\xab\x7c\x40\x7d\x4f\xff\x78\xd4\xc9\x6e\x1c\xfc\xa2\xca\x5d\x06\x44\x84\xb6\xb7\x22\x03\x22\xc3\x1b\x22\x51\x01\x51\xe1\x22\x7a\x54\x40\x74\xb8\xcc\x1a\x15\x10\x13\xaa\xcc\x5d\xb0\xad\xcb\x80\xd8\x10\xa0\xc8\xc2\xe6\x42\x15\xa8\x73\xbd\x39\x57\x01\xf1\xe1\x52\x56\x54\x40\xc7\xfd\x39\x8f\x28\x12\x78\xb7\xf4\x8f\x0c\x89\x08\x2d\x45\xa3\xd3\xf4\x6e\x69\x14\x19\x12\x75\x9c\xab\x9f\xeb\xfe\xb8\x0e\x88\x3e\x06\x14\x9d\x37\xe6\x38\x0f\x8e\x4e\x11\x1b\x4a\xa8\x23\x03\xe2\x8e\x73\xcc\xe8\x14\xf1\xc7\x80\x22\x1b\xee\x51\xcf\x0e\xf3\x00\x45\x47\x5d\x3b\xcc\xa5\xae\x9d\x7b\x7f\x27\xf7\x19\x7d\x3b\xd7\x7e\x6d\xf0\x9e\xce\x9d\xb3\xbf\x8a\xfb\x84\x98\x18\xfc\x41\x38\x0a\x11\x2c\x22\x55\x56\xe1\x28\x4d\x95\x59\x5e\x65\x58\x9c\xe7\x09\x42\xa1\x09\x08\x21\x4b\x13\x9a\x4a\xe3\x1c\xae\x2a\x2a\x45\x92\x50\xe3\x71\xa0\xa8\x80\xe5\x18\x1c\xf2\x34\x2b\x13\x2f\xaf\x98\x9f\xe4\x45\x2f\xb5\x04\xce\x26\x30\xbb\x9e\xec\xf3\x2f\x87\x61\xa9\x4b\xaf\x8e\x61\x29\xfa\x25\x14\xda\xfd\x66\xee\x02\x33\x40\x06\x39\x18\x5b\x39\xae\x91\x19\xa5\xe2\x48\x57\x48\xb6\xd2\x71\xb3\x85\xc2\xba\xdd\xe2\x16\x2d\xe3\x2d\x01\x93\x33\xba\x48\x7b\xc7\x23\xdf\xbc\x87\xbc\xc3\x06\x62\xa8\xd7\x38\x71\xf8\xd3\x1b\x9a\x68\xb5\xa4\xed\x98\x24\x98\x25\xd4\xac\xd5\x98\xe9\xa5\x79\xd5\x4d\xb1\x89\x7e\xae\x48\x4a\x88\x57\x5b\x15\x2d\x93\x8b\xe5\x0d\x3a\x3f\x6f\x96\x63\x6f\x82\xcb\x7a\x27\x1c\xd2\xe9\x56\xcb\x3f\xd0\x20\x14\x52\x5c\xa6\xb2\xec\x68\x64\xb2\x34\x68\x15\xe6\xe4\xb4\xbf\x76\x18\x38\x23\xb2\xb0\x94\xcd\xe2\x0e\x9d\x20\x89\x5a\xab\x59\x35\xdc\xbe\x7f\xc4\x20\x6d\x09\x4b\xff\x04\x9d\x87\x3b\x71\xb2\xbf\x3b\xb3\xe7\xa7\x2a\xc1\x59\x3f\x33\x1e\xf2\x75\xb2\xcb\x0e\x19\xba\xab\xd6\x0a\x44\x4d\xc8\x0e\xb2\x8b\xae\xe1\xce\x87\x68\x56\x8a\x91\x66\x25\x59\x21\xfb\x19\xbd\x39\x5c\xf3\xed\x0c\xa4\x2a\x5d\x8e\x4a\xa2\x92\x3e\x1e\x8e\x00\x6d\x28\xc3\xd8\xa8\x9b\xb6\x3b\x9a\x4c\x15\xad\xd4\xb4\x3f\x6b\x54\xad\x3f\x5f\x82\xcd\xf2\xc1\xc3\x11\x87\x3f\x53\x87\x2f\x7d\x5e\xcb\x44\x32\x2e\x94\x29\xba\x9b\x48\x91\x6e\xb6\x95\x2e\x83\x1a\x29\xe0\x25\x34\xac\x70\xf9\x1a\x63\x4a\x40\xe0\x51\xdb\x50\x57\x39\x37\xf0\x06\x03\xfd\x41\x79\x25\xec\xba\xea\x3f\xfa\xc0\x7c\x09\xea\xba\xdd\x88\xfb\x5c\xb9\xfa\x7c\x91\x9a\x95\xdb\x42\x95\x67\x6b\xa0\xd6\x70\x9b\xea\x42\x4a\x65\x27\xa9\x78\xb2\x89\x26\x6b\xb5\x5a\xe9\x8c\x2c\x53\x31\x8a\xad\xb0\xbe\xd4\x5a\xad\xfa\x16\xbf\x1e\x4f\x0c\xb8\x16\xc9\x2f\x06\x39\x50\xb7\x79\xc6\x52\xd8\xf2\xd8\x76\xfb\xc4\x20\xb1\xe4\x8b\xe5\xaa\xca\x0f\x5b\x2d\x31\x67\x77\xeb\xbe\x3c\xe7\xf6\x62\x7b\x4c\xab\xd5\x6a\xec\x5e\x2d\xe1\xca\x7a\xa7\xc6\x88\xac\x95\x2a\xe2\xc5\x6a\x6c\xd1\xad\x27\xf9\x75\x67\xde\x69\x35\xc8\xa5\x51\x31\xba\xb3\xba\x0c\x52\xf3\x71\xb5\x88\xfc\x57\xb4\x94\x69\xbb\x10\xd4\x12\x7b\x2a\x31\x45\x54\x86\xfa\x60\x59\x82\xcd\x0a\xcf\x24\xd6\x9a\xc3\x23\x5c\xb1\x6c\xe9\xad\xb3\x4e\xb4\xf3\xc3\xb4\x55\x60\x87\xf3\xe1\x22\x64\x04\xe9\x56\x13\xdf\x4e\x74\xb1\x4d\xa5\x71\xd4\x2f\x33\xc2\x8a\x4f\xe2\x15\x27\x23\xea\x73\x05\xb0\x00\x34\x79\xae\x3b\xa0\xc6\xc5\xe1\x98\xaf\xb2\xf4\x30\x49\xce\xbd\xf1\xcd\x56\xab\xb9\x65\xc5\xaa\x2c\xba\xf1\xb4\x1a\x57\x72\x2b\xa9\x39\x8d\xa3\x69\xb6\xbc\x9e\x4c\xd9\xae\x6a\x2d\x14\xad\xbe\x1e\x66\xb5\xb7\x74\xab\x96\x2c\x10\xe2\xf6\x5c\x42\xde\x68\xeb\x07\x25\x4b\x87\xb5\x7e\xaf\x93\xd5\xbd\xce\x79\x3a\x98\xac\x46\xe7\xb9\x4c\xdb\x39\x45\x38\x86\x27\xbc\x3b\x31\x17\x76\x15\xc7\xe2\x7a\x22\x7e\x31\x0a\x7e\xd1\xc3\x5f\xda\x03\xd9\x3e\xcf\x76\x8b\x9c\xc0\x0e\x46\xba\x58\x41\xb8\xda\x6c\xb2\xad\xac\x92\xaa\x2e\x99\x6a\x7c\x31\xca\x4e\x15\xb2\x99\x02\x34\xcc\x93\x39\x03\x1c\xe8\xf7\x5e\x9f\xf0\xc0\x1c\x3e\x62\x83\x10\x37\xeb\x42\x75\x60\x81\xe5\x7a\x06\x57\x27\x4f\x2d\x6e\xe9\x7b\x94\xbf\xc5\x1e\x88\xaf\xee\x77\xc6\x90\x47\x74\xbc\x35\xc6\x63\x7a\x36\xbe\xbf\xbc\x2f\xc3\x3e\xde\xfb\x3c\xfc\x29\xf4\x59\x65\x86\x15\x4e\xd2\xb7\x9d\xd6\xac\x55\x3f\xa7\x8c\x7b\x7b\x14\x0e\xe3\xef\x8c\x09\x0f\xe8\x4f\xe2\x0d\x26\x39\x41\xdb\x53\xce\x1d\xe4\x57\xdd\xdd\x67\xe3\xe7\x49\xf7\xd0\xe6\x03\xf3\x71\xa7\x7e\x3d\xe0\x33\x8b\xc5\x6a\x47\xe3\x0f\x42\x5f\xec\xe9\x49\x5c\x90\xf5\xe1\xf2\xc6\x2b\x07\xd1\xff\x94\x18\xf6\x00\xff\xc9\xd8\xdc\x27\xdc\xf7\xf9\xa7\x99\xce\x3d\x83\xbf\x87\xf5\x33\xba\x7c\x52\x8d\x71\xb1\x7c\x41\x3f\x83\xaa\x38\x4d\x68\xb9\x30\xff\x0f\xeb\x67\xf4\x1c\x2b\x37\xec\x48\x8b\xc4\x83\xfa\x19\x70\xe8\xf7\xce\x5f\x6a\x06\x57\x3e\x10\x6f\xea\xfc\x9c\xf8\x5d\x62\x7c\x9e\x96\x83\x3f\x7d\x22\xfe\x77\x13\x74\x1e\xff\xa3\xf1\xe6\x81\x9c\x10\xcf\x93\xa9\xd3\xfe\xfc\xa4\x7c\x3e\x9d\x3e\x75\xdd\x6e\x0a\x9d\x0b\xf1\x26\x70\x8d\xf3\x30\xfc\xd5\xb3\xf3\xbf\x48\xf9\xd7\xd3\xf1\x87\x5f\x6a\x75\x1e\xbf\x70\xc0\x9f\x8b\x84\x5f\xf8\xab\xe4\xfc\xde\xa0\x40\x8e\xeb\x73\x3e\xb3\x48\xcb\xa5\xe8\x69\xb2\x22\x2e\x27\xd5\x38\x69\x65\xa5\xd8\x1a\xb0\xb5\x95\xe1\x80\x91\x56\x4a\x77\xc7\xd5\xb6\x6e\xcf\xea\xb1\x86\xff\x00\x3b\x76\x06\xcd\x10\xbc\xe4\x3b\x81\x9e\x3d\x53\x1d\xf0\xc1\x91\xf1\xf7\x17\xd1\xf0\xff\xe9\xad\xc9\xff\x03\xa6\x8c\x08\x61\x03\x14\xd5\xc1\xac\x61\x8f\xfa\x40\xb4\xdf\x44\x01\x95\xb4\x84\x51\x20\x62\x35\x86\x5a\xb3\x48\xe1\x72\x71\x24\xc2\x44\xbd\x51\x01\xdd\x37\x5b\xe7\x07\x6b\x3d\x4f\xad\x92\xb0\xde\xe9\x8c\xf3\xab\x06\xd3\xd2\xdb\xae\xca\xcf\xf5\x99\x5e\x9e\x66\x68\x29\xa9\xff\xf9\xa7\xb7\x87\x69\x5a\x26\xda\x9f\xe2\xbf\xe5\x5f\xd7\x9e\xf9\x5b\x48\xd7\xeb\x7e\xc1\xdf\xcc\xd6\x20\xcf\x40\x19\x21\x19\x47\x84\xcc\x6e\x3e\x52\xac\xca\x69\x2c\x8e\x93\x0a\xa4\x55\x12\xf1\x34\x4b\x52\x0c\x4d\x28\x24\x27\x93\x04\x07\x11\x43\x40\x4e\x01\x32\x90\x49\x95\x25\x5f\x5e\x31\xee\x79\xb5\x29\xfa\x4a\x6d\x8a\xc1\x19\xf2\x7c\x6d\xca\xbb\x4b\xbf\x84\x76\x8b\x1e\xad\x4d\xa5\x42\x93\xff\x8b\xd4\xa6\x46\x56\xd1\xd7\x5e\xef\x73\xf2\xe4\x1a\x2d\x50\x9b\xca\x51\x6b\x2e\xab\x2e\x93\x25\x85\xef\x0e\xd8\x5c\xa9\x4b\x91\x31\xdd\xac\x15\xe9\x31\x6a\x96\x1a\x99\x32\x5d\x92\xa6\x59\x27\x06\x34\x68\xb5\x93\x66\x32\x86\xe7\x92\xa4\x5d\xeb\x0c\xba\x6d\xcb\xd0\x2b\xa6\x98\x48\x8d\x1b\xd2\xb2\xda\xd5\x24\x81\x2f\x56\xab\x52\x96\x6e\xa9\x8b\xc5\xe7\xd5\xa6\x1e\xcd\x9b\x52\xfb\x75\xec\x23\xeb\x62\x76\xec\x6c\xdf\x66\x15\x29\xef\xf5\x68\x7f\xa4\x36\xe5\xad\xcb\xbd\xeb\x81\x38\x9f\x55\xc0\x28\x38\x1f\x67\x6b\x39\x01\x4d\x8a\x12\x4b\xc1\x01\x47\xb0\x56\x10\xb8\xae\xc4\xf2\xe7\xe1\x8f\x54\x4b\x4a\x1d\xe2\x42\xf6\x20\x9f\x4f\xcc\xf5\xeb\x56\x9a\xd3\x6f\xcb\xf5\xbd\x5a\x41\xf8\xaa\x0a\xc7\xb9\xee\xbd\x3a\xfb\x40\x2e\x81\xd3\xc6\xfa\x74\x6d\xe5\x5d\xa9\xbf\xa0\x77\x56\x61\xca\xbd\xf9\x0a\xe6\xf6\x3f\xc5\x67\x3c\xa5\xfe\x7b\x61\x6d\xa6\x3f\x83\xbf\xc3\x5a\xda\xff\x7c\x6f\x1e\xf4\x80\x7c\xfc\xf9\x3b\xa5\x9f\x81\x4b\x14\x8e\xdf\x30\xf5\x89\xf4\xa5\xdf\xdc\x8a\x75\x8d\xbe\x87\xed\x3b\x7a\xae\x7e\x5e\x7e\xbe\xbe\x78\xb5\x28\xee\xa4\xea\x1c\xe8\x7d\xc0\xbe\x1f\xd0\xef\x76\x5b\x9f\x5f\xaa\x4d\xb6\xdb\xfa\x2c\xfe\x6e\xed\xb4\xbf\x7c\xfb\x7e\x54\xff\x1f\xdd\xaf\x7a\x80\x7f\x09\x36\x26\x82\x98\x63\x24\x45\x39\xe4\x04\xe7\xe7\xe7\x81\x5a\xd9\xa3\x39\xc3\x03\xfa\xe9\xed\xe7\x25\x92\xe5\x41\x27\x1b\xde\xcf\x3a\x5c\x01\xfb\xf1\xaf\x7b\xf7\x02\xd8\xb1\xa3\x97\x0e\xf3\xe9\xcd\xef\xbb\xb5\xe7\x95\x75\x60\xee\xc9\xf8\xdf\x27\x06\x67\xf1\x97\x0e\xe3\xa3\xf9\xb7\xe8\xf3\x73\x3e\x3f\x38\x2d\x9f\xcf\xa6\x4f\x4a\xaa\x8b\xd3\xb5\xca\xed\xf5\xe7\x9f\x27\x6a\x0a\x81\xf5\x42\x94\x35\xfd\x90\x3a\xc0\x0b\xe4\x9e\x37\xcd\x65\x58\x97\x1e\xad\x69\xdc\x83\x7f\x5b\x53\x18\x0c\x2a\x0b\x95\x14\x73\xcb\x35\x30\x2a\x8e\xbe\x1c\x0c\x34\x26\xa9\x8a\xf3\xf1\x1b\x5d\x5d\x96\xba\xec\x70\x41\x58\x68\xcd\xb6\xf8\x69\xbf\x5b\x50\x8a\x6c\x55\x2f\x22\x37\x8d\xa4\x3e\x34\x0a\x42\x4c\xa9\x8a\xe5\xb7\x12\x99\x4e\xf4\x39\x3c\x85\xbb\x09\x01\xd7\x46\x2d\x32\x25\x7c\x6e\x4d\x81\x82\x38\x54\x00\x83\x78\x8a\x63\x01\x0e\x78\x9e\xa1\x79\x19\x47\x1c\x20\x81\x8c\x70\x46\xd5\x68\x9e\xa2\x10\xcd\x72\x38\xa3\xe0\xaa\xcc\x12\x04\x47\xf3\x88\x42\x1c\x84\x2a\x40\xde\xfa\x9e\xdd\xd6\x14\xa2\x1e\x50\x09\xd4\x14\xd8\x6b\x35\x05\x82\xe6\xf9\xf3\x3f\x12\xb0\xb9\x1b\xf8\x49\x0c\xbf\x71\xd4\xd7\xd9\x3b\xfd\x79\xa0\xa6\x10\xf6\x6f\xef\x6a\x0a\xbf\xee\xde\x8f\xb8\xe7\xa7\x9a\x49\xce\x8b\xb5\xf2\x22\xeb\x66\x32\xcc\x98\xa8\xe4\xf1\x5c\x6e\x4d\xa6\x6b\xd9\x4c\x73\xc9\xb7\x57\xfa\x54\xea\x64\xa5\x6a\x45\xc2\xbb\x93\x61\xdc\x6a\x48\x23\x37\x2f\xcc\x2a\x26\x4d\xa4\xdf\x62\x65\x56\xcb\x8d\xe7\x4a\x56\xd3\x4a\xc5\x56\x29\x99\x4e\x49\xa9\x86\x9e\x36\xed\x5c\xb5\x74\x67\x4d\x21\x70\xfd\xd7\xed\xb5\x05\xfc\x63\x68\x6d\x9e\x08\xe4\x56\xf7\xe6\x4e\x9b\xb5\xb1\x2f\xc0\x43\x9d\xfb\x3d\xee\xcb\x6b\xe3\x27\xe2\x3f\xc3\xfb\x2d\xf8\x3f\x24\xf7\xb8\x23\xf6\x8b\x1f\x81\xff\x8e\xdc\x47\x38\xe0\x8f\xde\x87\xe1\x4f\xc5\xcf\xe9\x33\xd9\xf7\x5a\x9d\xd9\x47\x14\x8e\xd7\x0a\x9f\xdd\xc7\xe0\x5f\x17\xfa\x18\x48\xe9\xad\x72\xad\x8f\xe1\xaf\xb9\xb6\xf4\xc6\x77\x85\x9f\x50\x3b\xf2\x0b\x42\xb7\xd5\x8e\x96\x15\x36\xfc\x4b\x1b\x41\xff\xf0\xd9\x7d\x05\x7e\xb3\xc0\x4d\x7d\x05\x85\xd4\x6c\x76\xb4\x3e\x3e\x99\x0b\x67\x02\x03\x22\xf8\x96\xe0\xfe\xd6\x99\x8d\xdc\x4f\xf3\x6d\xf7\xe0\xdf\xe6\xc2\xdd\x02\xe7\x8a\xac\x80\xf0\xae\x3c\x95\xbb\x9c\x59\xd5\x07\x15\xa5\x25\x2a\x6f\x8d\x2c\x90\x0b\x49\x0b\x28\x0a\x10\x38\xb2\x66\x8c\x1b\xb1\x7e\x89\x68\xe3\xc3\x24\x15\xd3\xcc\x6e\xcb\xa4\x58\x97\x33\x20\xbf\x50\x79\x6e\xe1\x36\x17\xb9\x66\x09\x97\xca\x42\x1b\x39\x7d\x61\xf1\xb9\xb9\x30\xa1\xe2\x2a\xc1\x50\x2a\x8f\x08\x44\x92\x0c\xa5\x10\xbc\x06\x35\x06\x32\x48\xe1\x00\x0d\x39\xc8\x21\x06\x52\x0c\x22\x48\x9c\x67\x54\x08\x28\x00\x34\x82\xdf\x7c\x52\x59\x8e\xf5\x7e\x98\x81\x79\x5e\x2e\x7c\xad\xf7\x9b\x21\xb9\xed\xaf\x4d\x5c\xbc\x7b\x74\xf6\xe9\xd1\x5c\xf8\x6a\xef\xf7\x4f\xc9\xcd\x52\xed\x21\x53\xbd\x56\xfb\x08\xe4\xc2\x59\x4b\x43\xa4\xac\xab\x83\x84\xca\x30\x94\x60\x4f\xed\x42\x71\x40\xc4\x0d\x48\xc9\x45\x48\x77\x47\x99\x78\xa9\xc8\xce\xd2\xad\x5a\xa1\xdd\x90\x27\xf8\x68\x22\x17\x92\x10\x97\xd3\x35\x5a\x10\xcd\x64\x36\x15\x4f\xaf\xf2\x7a\xa1\x4f\x36\x0c\xa9\x3c\x29\x90\xd9\x74\x6d\xd8\xae\x72\x9f\x9c\x0b\xff\xc4\x5a\xd3\x55\x79\x5f\xc8\x85\x03\xfb\x3a\x51\x72\xd1\x77\x3d\xc7\xb7\xf7\x7c\x24\x9e\x8c\xff\xde\x9e\x93\x70\x2e\xfc\xec\x78\xf1\x5e\xb7\x2e\xc7\x8b\x9f\x18\xaf\x84\x03\xfe\xbf\x66\xcf\x35\x98\x94\x87\xd7\x7a\xae\x03\xfb\x62\xbf\x5a\x2e\x2c\x9c\xaf\x83\x0b\xc2\xb1\x7e\xfc\x6a\xb9\x70\x56\x01\xc3\xf8\xb5\x5c\xb8\x29\xfc\xda\xb9\xf0\x49\xf9\x07\xfc\xd3\x2f\x9c\x0b\x67\xc5\xb8\x73\x3d\x17\x0e\xae\x8b\x23\xf8\x96\x77\xbd\x66\x3f\xd1\xb7\xdd\x83\x7f\x9b\x0b\xa3\x3e\xcf\xaa\xb3\x04\x51\x4a\x93\xb6\xad\x27\x67\x53\xc7\x9a\x55\xe4\x58\xde\xee\x3b\xae\x3d\x32\x9a\x32\xb7\x98\xcf\xa8\x56\x4b\x9c\xbc\x49\x33\xb3\xde\x1e\x39\x56\xde\xae\x39\xad\xec\x50\xa8\x2b\x39\xa5\xc2\x75\x72\x63\x61\x9a\x55\xcb\x39\x9c\x19\xda\x8a\xd2\xca\xd4\xde\x52\x9f\x9c\x0b\x2b\x2c\x94\x49\x8e\x22\x35\x1c\xe2\x0a\xa5\x21\x96\x57\x91\x82\x70\x4d\x03\x32\x47\xf2\x40\x63\x21\xaf\x92\x94\x42\xb1\x8a\xac\xb2\x88\xa4\x71\x92\xd2\x58\x99\xe0\x34\x06\x57\x35\xc5\xfb\xc5\x1a\xd2\x7f\x0d\xe9\x33\x7a\xcd\xa8\x6b\xb9\x30\x4b\x70\xf8\xd9\x1f\xd8\xdf\xdf\x3d\x3a\xbc\xfd\x68\xaf\x59\x78\xaf\x20\x90\x0b\xfb\x6b\xf1\x48\xf6\x18\xee\xe9\xf5\xae\x40\x6f\x58\x39\x6e\xca\x23\x8b\x2b\x08\xc3\x7a\x59\xe3\x94\x6a\xb9\x6c\x08\xa9\xce\x4a\x5f\xc6\x72\xf8\x9b\xda\xb6\x4a\x54\x4b\xa7\xc4\x42\x45\x10\xf2\x9d\xb4\xe9\x2a\xee\x20\x99\x5b\x55\x29\xc5\x69\x35\x57\x0b\xd8\x26\x89\x7c\x7c\x88\xaa\xed\xae\xbc\xa2\x89\xc4\xc0\x90\xfa\x8d\x38\x73\xdb\xb9\xc5\xa0\x4d\x9d\xcd\xef\x82\xf9\x50\x84\x3e\xa0\x7c\xf9\x20\xdf\xd3\xfe\xe7\x4a\x7e\xf5\x44\xfc\xc9\xe8\xf8\x3f\x64\x6f\xec\x7d\xd9\xf5\xb2\x0f\xfc\x89\x7b\x73\x82\xf0\xeb\xf6\xb9\x7c\xc4\x3e\xe6\x58\x39\xc0\x3b\x73\x7d\xda\x5c\xdd\x83\x7f\x1b\xaf\xd8\x98\x3a\x6b\x0f\x16\x56\xb2\x96\xa3\xe3\xcb\xa5\x40\x31\x39\x41\xd2\x0a\xa9\x2c\x35\xa8\x8d\x00\xd4\xd7\xfd\x76\x4a\xaf\x5a\x9c\x20\x8c\x94\x36\x02\x2b\xa2\x94\x1b\xe4\x53\xfd\xd5\xb2\xd5\x28\x26\x26\xb2\xd6\x35\x63\x35\x3a\xf1\xd6\x9f\x17\xcd\x6e\xa6\x9c\x23\xd2\x95\xf8\xe4\xb3\x7b\xa3\x49\x9a\x41\x48\x01\x1a\x4e\x91\x84\x2c\xcb\x32\xc4\x79\x55\x55\x14\xc0\x93\x2c\x22\x38\x82\x26\x21\xa5\x2a\x1c\xe2\x39\x4d\x63\x59\x95\x46\xbc\x8a\x10\xa0\x70\x19\xd1\x38\x4f\x42\x76\x13\xaf\xe8\xe7\xd5\x6e\xae\xf6\x46\x53\x1c\x71\xe1\x87\xff\x77\x77\x8f\x5e\x37\xf3\x68\xed\xe6\x6a\x6f\xf4\xcf\xa9\x25\x1c\x7a\x7d\xcf\xeb\x69\xa0\x76\x23\x32\xc2\x70\x95\x8a\x75\xc8\x8a\xa5\x30\xe9\x01\x33\x82\xa3\xee\x7c\x9c\x6d\xaa\xb2\x44\x72\xb3\x99\xc9\x24\x3b\x74\x49\x89\x2b\x79\x33\x5d\x85\x53\xf7\x2d\x51\xb6\x84\x45\xca\x74\x1b\x23\x90\x59\xc7\x35\xd6\x46\xb5\x49\x47\xc9\x77\xeb\x6a\x35\x36\x11\x95\xa6\x19\x27\x2a\x82\xf8\xc9\xb5\x1b\xf1\x17\x96\xf7\x85\xda\x4d\x60\x6c\x94\xda\xc9\xa3\x3d\xc6\x4f\xc4\x1f\xa9\xc7\x38\x50\xbb\x79\xf6\xfa\xe6\xde\xbe\x97\x9f\xb8\xbe\x12\x0e\xf8\xa3\xd7\x6e\x7c\xdd\xfb\x39\xb5\x9b\xc3\xda\xfb\x4c\xd9\x6a\xaf\xef\x07\x79\xff\x1a\x6b\x71\xe1\x58\x7e\x8f\xd4\x96\x3e\xa5\x56\x90\x3a\x55\x1b\x0b\xf7\x40\xff\x12\xb5\xa5\xc0\x15\xb0\xaf\x5f\x87\xbe\xc4\x79\x79\xfa\xd7\xe5\x9c\x36\x8a\x8f\x78\xb8\x37\xef\x89\x3e\x2a\x42\x6f\x5e\xc3\x4a\x36\x72\x15\x5a\x53\x62\xfd\xb5\xd5\xae\x4c\x5b\xd3\x96\x11\xeb\xaa\x35\xe0\x90\xda\x8a\x61\x34\x2b\xaf\x0d\x97\x6b\x7e\x31\x56\x5a\x89\xe9\x14\x0c\x45\x46\x4f\x09\x65\x04\xca\x9d\xa6\x5c\xe1\xe3\x33\x97\xce\x8c\xd4\xc5\xa8\x9f\x07\x29\x66\x58\x5b\xd6\xb5\x78\x97\x13\xaa\x9f\xbc\x1f\xc9\x91\x2c\x04\x32\xa9\x22\x8d\x50\x08\x55\xd5\x54\x45\x45\xb4\x4c\x51\xb2\x86\x73\x2a\x0b\x01\x80\x3c\x49\x70\x2a\xc7\xe2\xaa\x06\x58\x0d\x12\xb2\xcc\x30\x2a\xa5\x70\x24\xc1\xe0\x0a\xeb\xff\x94\x31\x78\xe4\xe7\x2c\x02\x39\x2d\x79\x2d\xa7\x65\x70\xc0\xf1\x67\x73\xda\xdd\xdd\xa3\x17\x16\xfa\x3a\x7b\xa7\x9d\x04\x72\xda\x93\x7e\x31\xa0\x83\xf7\xd6\x00\x1e\x88\x2b\xe1\x97\x0f\x64\xf7\xf4\x56\x33\x56\xb5\x62\xa4\xf0\xac\x98\x30\xf0\x26\xa7\x64\x25\xc6\x1c\xbd\x91\xd6\x50\xd4\xd4\xb1\xcb\x8e\xa7\xc3\x6a\x36\xe7\x12\xee\xac\x56\x84\x6f\x6f\xc0\x28\x55\x17\x4d\x8a\x2c\x71\xf3\x98\xe9\xe6\xab\x8e\x40\x29\x04\x4a\x74\x5c\x3e\xd3\x9d\xc4\x09\x3e\x5d\x1c\x98\x32\x04\xd5\x9b\xce\xf3\x05\xe5\x73\x3e\xaf\x0b\x0c\x8a\x70\x76\x26\x6f\x1e\xe6\xe3\xcc\x75\x25\xaf\x7a\x1e\xfe\x33\xef\x12\xb8\x52\xb3\x09\xfb\xcc\xcf\xee\xbd\xf6\x49\xb9\x25\x2e\xfd\xa2\xbd\xeb\x27\x6b\x2a\x01\x7f\xfd\x40\x8e\x16\xbd\xa6\x22\x3e\x86\x3f\x6a\x4d\x67\x1b\x7f\x60\x5f\x88\xe5\x2a\x55\xa5\x9a\x29\xd6\x1a\xcb\x85\x42\x4e\x51\xcb\x44\x46\xb5\xc6\x13\x90\x9c\xc1\x69\x4d\x50\x0c\x12\x12\xb4\xe8\x4e\x46\x66\x3b\xb7\x4c\x25\x1a\x03\x65\xbd\x8a\x33\x08\x1f\x25\x17\xa9\xfe\xfa\x8d\x4a\x23\x12\x7f\x33\xcc\xb8\x8c\x37\x67\x65\xd5\xb5\x5b\x9f\xdd\x1b\x8e\x28\x0d\xc9\x32\x03\xa1\x4c\x6b\x1c\xa9\x6a\x94\x02\x78\x99\xd2\x80\xc6\xc8\x1c\xc3\xb1\x1a\x00\x1c\xc7\x00\x86\x47\x3c\xcf\x20\xc0\xc8\x10\xb2\x34\x84\x0a\xa1\x72\x10\xe7\x15\x86\xf3\xe3\x0f\xf1\xc8\x8f\xf4\xdc\x17\x7f\x48\xe6\xfc\x79\xf3\xcd\x5d\xfa\x25\xf4\x7a\xda\xed\x1e\xc0\x7d\x35\xc6\x7b\xe2\xcf\x67\xe7\xe5\x01\xfc\x7b\x7a\xab\xa2\xde\x6f\x27\x8a\xa9\xc1\x58\x2a\xae\x95\x4a\x9a\xb1\x38\x75\xda\xcc\x96\x9c\x1c\xde\xee\xbb\x6e\x5b\x8c\x0b\x89\x7a\x01\x66\x25\x25\x86\xa7\xa7\x4e\x3a\x36\x33\xe8\x18\x1a\xae\x28\xb1\xb6\x9a\xf1\x7c\xb7\xc6\x24\xc4\x6c\x9a\x92\x46\xfa\xaa\x68\xd6\xa7\xe4\x5a\x49\xd9\xfc\x6d\x7b\x06\x77\xc7\x9f\x7b\xcf\xae\x3e\x3b\xfe\x3c\x88\xff\x89\xf1\xe7\x13\xcf\x2e\xfb\xa4\xdc\x19\x7f\x7e\x89\xb3\xd5\xdb\xeb\x6a\xfc\xb9\xf7\xec\xfe\xb3\xe3\x4f\x04\xfc\x0f\xc6\x9f\x7a\x32\xdd\x15\x9d\x72\xb9\x8b\xcf\xa5\x05\xd7\x99\x0e\x96\xc4\xa4\xaa\xac\x16\x83\x1a\xcc\x10\xa0\xdb\xe0\x84\x74\x6e\x62\x29\x60\xcd\x56\xdb\xd3\x45\x87\x61\x8a\x26\xcd\x34\x8a\x7a\x2d\x5b\x60\x49\xd0\xcf\x5a\x62\x55\xe9\xe8\x44\x3b\x95\x9b\xa9\x05\x5b\x93\x16\xe5\x39\xf8\xec\x9a\xbe\xac\x52\x1c\xa3\xca\xaa\x8a\x13\x2a\xc5\xe0\x1c\x60\x19\x16\x28\x14\xa4\x21\x8b\x78\x95\x41\x1c\x43\x2b\x90\xe0\x15\x99\x02\x88\x21\x54\x16\x42\x8d\xc5\x21\xa1\x21\x44\xcb\x24\xa3\x22\x7f\x0f\xfa\x59\xef\x3b\xb9\x1a\x7f\x58\x82\x22\xcf\xaf\x7f\x58\xc2\x3b\x2c\x75\xf4\x4e\xf3\x47\xb7\xa0\x2f\x84\x1f\x7f\x0b\x3a\xd2\x72\x86\xbc\xb2\x05\x9d\xe0\x87\xe3\x42\x9b\x98\x92\x73\xb6\xaa\xad\xb8\x4a\x09\x0d\x45\x19\x34\x1a\x39\xda\x58\x4e\x87\x39\x3c\x61\xe9\x1d\xbb\xec\xb2\x7a\x19\x30\x44\x55\x1e\xf6\x09\xb5\xde\x68\x6a\x28\x65\xcd\x15\xbc\x22\x40\xad\x9f\xea\x2c\xdd\x7e\x4b\x18\x39\xc5\xd9\x60\x94\x18\xaf\x06\x09\xa1\xfb\x2b\x6e\x41\x9f\xb9\x3e\x6d\x0b\x3a\x5a\x38\xf9\x90\x2d\xe8\x33\x38\x3f\x6d\x5b\xf3\xcc\xc9\xa7\x8f\xdb\x82\xfe\xc0\xe5\xdc\xd5\x70\x15\x41\x56\x0f\x87\xab\x9f\xb4\x05\xbe\x0d\x57\x59\xa2\xde\x9d\xc8\xd0\x46\x71\x37\x11\x2f\x2e\xb8\x25\x53\xad\xcd\x5b\x52\x69\x30\x2e\x66\xa6\xd5\x41\x35\x63\x24\x90\xc3\x90\x33\x81\xed\xd8\x6f\x89\x59\x3d\xfb\x06\xf2\x52\x8d\xa7\xca\x06\xbf\xae\x72\x89\x49\x4c\x94\xb4\x0c\x91\x6e\x26\xdb\x8b\x19\x53\x6e\x66\xe4\x42\x49\x4c\x7c\x72\xb8\xc2\x71\x28\xf3\x8a\xa6\x20\x42\xa6\x14\x0a\x50\x40\xe5\x64\x99\x61\x19\x4e\x55\x71\x9e\x92\x55\x59\x06\x0a\x4b\xe1\x0c\x0b\x70\x55\x96\x49\x19\xe2\x48\xe3\x39\x8e\xc5\x35\x86\x84\xfe\xab\xb2\xc8\xed\x72\xe9\x09\x5b\xd0\x37\x84\x2b\xe6\xfc\x0e\xf4\xf6\xe6\xd1\xef\x66\x3c\xba\x01\xfd\x89\xd1\x2a\xb0\x61\x5c\x6c\xc9\xb9\x5c\x0c\x14\x91\xb1\x5e\xea\xa6\x92\xca\x51\x4c\x21\xbb\x4a\xb8\x38\x1d\xcb\xf2\x84\x09\x62\x35\x92\xe0\xf2\xfc\x5a\x1a\x11\x9a\x9e\x6f\x13\xa6\x66\x92\xe9\x9c\x55\x6c\x39\xc4\xb4\x05\x62\xc9\xe6\xc4\x06\x04\x80\x44\x82\x15\x4a\x4c\xb6\x60\x53\x66\xa2\x28\xe4\x3e\x24\x5a\x45\xd8\xd4\x7c\x6a\xb4\x7a\x10\xff\x13\xa3\xd5\xa3\x1b\x16\x8f\x46\xab\xa7\xe0\x7f\x20\x5a\xfd\x12\x9b\x4e\xdb\xeb\x5a\xb4\x8a\x22\xab\x67\x46\xab\x28\xf8\x1f\x8c\x56\x6e\xcb\xd1\x07\x6c\xd3\x65\x8a\x95\x4c\x52\x5d\x94\x06\x03\xcb\xd2\x72\x19\xb2\x61\x52\x1a\x09\xb5\x0e\x9d\xd5\xe4\x85\x49\x96\x88\xce\x5b\x4c\x18\xc9\x50\x8d\x69\x4a\xd3\xd0\xdd\xf6\x1a\x4e\x3a\x1d\x2a\x5f\x1f\xcf\x3b\x72\xcb\xee\x66\x1d\x61\x6d\x29\xd3\xb9\xa1\x88\x8e\xf0\xc9\xd1\x8a\x46\x1a\xaf\xe0\x8c\x2c\x33\x04\xad\x12\x2a\x24\x08\x0e\x00\xc0\xc9\xaa\x06\x28\x95\xc3\x39\x96\xe1\x48\x9a\x44\x88\xd0\x14\xc8\x52\x34\xab\x70\x88\xc6\x19\x4d\x46\x32\x0f\x34\x85\xa6\xfd\x68\x45\x3d\x29\x5a\xdd\xd0\xe0\xcb\x53\xe0\x42\xb8\xe2\x29\xe2\x25\xf4\x9b\x4a\x8f\xc6\xab\x4f\x6c\xf0\x0d\xc4\xab\x72\x86\xc8\x14\xca\xbc\xc1\xe0\x4a\x09\x54\x0b\x44\x53\x02\x7a\xc7\xce\x8a\xdd\x01\xca\x14\x6b\x9d\x74\x83\x76\xcc\xe4\xb4\x4c\xa7\xcd\x8a\xd8\xa0\x95\x96\x43\xe2\x12\x9b\x6b\x54\xde\x98\x6c\x96\xa9\x2a\x6f\x44\x4e\x4d\x02\x85\x61\x16\x45\x1d\x51\x99\x55\x8d\x9b\x4f\x16\x0b\xfc\x57\x8c\x57\x0f\x37\xf8\x3e\x88\xff\x89\x0d\xbe\x4f\xd9\x60\x7f\xa0\xc1\xf7\xb3\x37\xf8\x05\xe1\xd7\x2d\x56\x5e\x6b\xf0\xfd\xcc\x78\x21\x7c\xc0\x5c\xdd\x83\x7f\x1b\xaf\x28\xb9\xdb\xb5\x58\xa2\x68\xd7\x16\xeb\x96\x60\xbf\x55\xc9\x76\x02\x39\x4a\xcd\x90\xa8\xae\x9b\x56\x5a\x95\xf1\x4a\x29\x58\xec\xb0\xad\x70\xb5\xca\x68\xd9\x5e\x6b\x55\xd2\xe9\x97\x78\xd3\x52\xb4\x49\x62\x69\x76\xfb\x78\xb1\xb5\xb6\x6d\x61\x96\x60\x75\x39\x9f\x5d\xc5\xcc\x54\xea\xb3\x9b\x21\x48\x96\x42\x9b\x60\xc1\xcb\x3c\xd2\x58\x55\x86\x3c\xa4\x55\x99\x24\x49\x5e\x66\x39\x4d\x85\x9c\x46\x52\x2c\xcb\xca\x00\x6a\x24\x29\x43\x8a\xe1\xa0\x4a\x2b\xb8\xaa\xf1\x14\xa3\x52\xea\xcb\xee\xb7\x3d\xa3\xff\xe2\xec\xee\x17\x4b\x2f\x84\x29\x8e\x21\x08\xe2\x6c\x98\xda\xdc\x25\x5f\x8e\x7f\x67\xcf\xd7\xd4\x4c\x91\xcb\x56\xe7\xd5\xa1\x5c\x20\xb2\x02\xd9\x6e\x0d\x6a\x76\x61\x3c\xe8\xe0\xb8\x96\xe1\x9c\x62\x8e\x1d\xe3\x62\x6d\x91\x6f\xc7\x85\x0e\x29\xec\xa3\x94\x77\x5d\x58\x55\xf9\x57\x84\x1a\x54\xf0\x48\x6f\xa2\x35\x5f\xa4\xf9\xcd\x2d\x31\x99\x5a\x4f\xe7\xc3\x6a\xa2\x6a\x49\x42\xde\xd0\x2a\xb5\x4e\xca\x2a\xf6\xe7\xee\x4a\x69\x90\xa3\x74\x25\x59\xa5\x81\x3e\x54\x9d\x74\x16\x26\xa4\xf6\x02\xa7\xeb\xf1\x56\xbf\x8d\x77\xf4\xa1\x8d\x27\x13\x15\x91\x92\x60\xba\x45\x14\xc6\x8a\x43\xbe\x2d\x8a\x63\x43\xa6\x1a\x35\xbb\x54\xbc\x21\x32\x1d\xa9\xf4\x71\x64\x0a\xf0\x7c\xf0\xcc\x01\x4f\x96\x30\xe2\x09\xbc\x88\xe7\x33\x2b\xb7\xbf\x90\xc0\xa8\x8b\xc3\xd5\xc4\x02\xbc\x94\x5d\xce\x8b\xc9\x55\x99\x76\x13\xa2\x92\xf4\x79\x24\x75\xd7\x2e\x9b\xdd\x38\xbd\xb8\x46\xc4\x15\x6b\x7f\x00\xbf\x64\xaf\x1a\xb5\x07\xf0\x0b\xc2\xcf\xab\x25\x9d\xf4\xbc\x89\xe8\xb2\x28\x9b\x6f\x17\xd9\xbc\x26\x8b\x47\xe7\x62\xa3\x0b\x31\x25\x04\xef\x2e\x59\xfc\x47\xe7\x18\x9b\x16\x85\x66\x21\x55\x4d\x76\xcd\x35\xde\x5a\x30\x49\x4a\x66\x15\x53\xe4\xe9\x5a\x63\x31\x2c\xab\xdd\x7c\x56\x4e\xd4\x08\xbd\xd1\x72\xa4\x72\x73\x0e\xba\x2d\x37\x4d\xe5\x0b\xbc\xa0\x37\x96\xe5\x54\xbb\xdf\x52\x8d\x89\x59\x94\x08\x25\x49\x5b\xe3\x98\x88\xc3\x75\xf2\x93\x8f\x02\x02\x86\x82\x34\xce\x50\x48\x86\x0c\xa5\x11\x8a\x2a\x43\x55\xe6\x68\x46\xd6\x48\x8a\xe2\x28\x8e\xd6\x14\x86\x60\x08\x8a\x85\x2a\x24\x91\x4a\xf2\x8a\xaa\x6a\xb8\xc6\xf0\x38\x01\x48\x52\x66\xf6\x3f\xac\xfc\x88\xe7\x25\xae\x7b\xde\x4b\xbb\xff\xbb\xbb\xc1\xdf\x13\x7d\xd4\xf3\x5e\x58\x1f\xf8\x57\x84\xfc\xf4\x8c\xe7\x15\xea\xe2\x9b\xf1\x26\xa3\xf4\x22\xe9\xd8\x85\x84\x59\xc8\xcd\x9c\x38\x4e\xb7\xdc\x7c\x2a\x61\xeb\x96\x33\xeb\x17\xab\xf1\x26\xd3\x69\x0e\x28\x77\xd1\x5e\xf5\x1d\xb6\xe9\xd6\xa9\x64\x09\x2d\xcb\x25\x26\x3f\x55\xb4\x69\xbe\x00\xf0\xf6\x28\x31\x1c\x2e\x4c\x4a\xe7\x2a\x39\x6d\x90\xcb\xfc\x5a\x9e\xf7\x51\xcf\xf7\xa8\xb5\x97\x16\xc5\xf1\xe4\x89\x9e\xf7\x33\xeb\x22\xd7\x6a\x34\x9f\xe9\xf9\x84\x27\x79\x5e\x8e\x3a\x3c\x7f\xa6\xbe\x79\xc9\xf3\x8a\xfd\x4c\x77\xdc\x26\xfb\x8a\x60\x17\x56\xfa\xdb\xca\x28\xda\x15\xbe\xdc\x92\xeb\xd5\x05\xa4\x0a\xc5\xa2\x55\xc7\x2b\xa0\x3c\x02\xb9\x58\x51\x49\x3b\x96\x5c\x06\xc5\xe6\x4c\x18\x64\x9d\xc6\xa0\x6c\x40\x33\xcb\x18\x75\x57\x4d\x4f\xaa\x6f\xf9\x52\x3e\x96\xab\xa4\x56\x59\x6a\xf5\xd9\x3b\x0a\x84\x4a\x32\xb4\x42\x2a\x14\xaf\x91\x2c\x43\xb3\xb8\xaa\x6d\xfc\xae\x02\x19\x82\xc6\x49\x9e\x61\x34\x1c\x11\x0c\x0f\x09\x8d\x06\x8a\x2a\x33\x9c\x82\x08\x84\x00\x0f\x59\x8d\x23\x28\x1a\xfa\x7e\x93\x7c\xcc\xf3\x5e\xdd\x48\xe0\x18\x8a\x39\xbf\xef\xbd\xbb\x1b\xfc\xdd\xe4\x47\x3d\xef\x85\xa3\x6c\xfe\xf5\xe0\x4f\x80\x06\x3c\x6f\x22\x9e\x4f\xe8\xf3\x5c\x89\x05\x7a\x31\x91\xeb\xe3\x8d\xb2\xc4\xcb\xb1\x51\x4c\x98\xbc\xad\x41\xb2\x90\xaa\x1a\xcd\x74\xbd\x85\x3b\x4a\x4d\x9f\x25\x00\x34\x57\xa5\x45\xa9\xc6\x38\x74\xdd\x80\xc9\x85\x9b\x32\x97\x4e\xc5\x84\x80\xa8\xa9\xcd\x6a\x61\x94\x25\x20\x2a\x09\x2b\x2e\xfb\x6b\x79\xde\x47\x3d\xdf\xa3\xd6\x5e\xc4\x87\x4c\xe2\x99\x39\xef\x27\xb6\x9b\x7e\x84\xe7\x8d\xea\xf9\x84\x27\x79\x5e\x36\xf0\xde\xf6\x77\xaf\xec\xbb\x2a\x8b\xff\x68\xab\x6a\xb7\xb8\x4a\x95\xf9\x6e\x72\x51\xcf\xa9\xe2\x7a\xa0\xb5\xe3\x13\x4d\x2f\xb4\x15\xbe\x6a\xe8\x78\x6e\x94\x68\x8e\xd4\x62\x56\xec\x16\x75\xb5\x3d\xe1\x06\xa5\x94\x88\xec\x72\xd3\x1a\xeb\x4e\xb1\x4a\x73\x72\x8a\x26\x5c\x75\xd8\x69\x89\xc9\x49\x8d\x1f\x9b\x03\xa1\x34\x4f\x7c\x72\xce\x8b\xe3\x24\xe2\x01\xc0\x81\x0a\x78\x08\x65\x99\x22\x78\x8a\x07\x3c\x4d\x72\x38\xc3\x71\x8c\xca\xb2\xac\x42\x30\x38\x41\x92\x0a\x43\xb1\x9c\x06\x14\x9e\xe0\x20\xcb\x23\x85\x42\x04\x4b\x91\xbe\xe7\xa5\x1e\xf3\xbc\x57\x8b\xe2\x1c\x43\xb3\x97\x3c\xaf\x7f\x37\xf8\xfb\xf0\x8f\x7a\xde\x0b\x2f\x80\xf3\xaf\x08\x0d\x94\x67\x3c\x6f\x2a\x57\x9e\xa9\xeb\xd9\x40\xb3\x62\x6a\x3d\x97\xef\x74\x64\x9c\xa9\x0f\x8a\x89\x62\xb1\xe3\xa4\x97\x66\xcb\xac\x81\x6c\x1e\x0d\xb4\x29\x21\xe9\xe9\xa6\x5b\x9c\x75\x88\x82\xdd\x92\xea\x6f\xab\x5a\x22\x13\x6b\xcf\x35\xd5\xea\x2c\x92\x15\x65\xc2\xd1\xfd\x54\x4d\x4e\x8e\x07\x72\xa5\x5b\xfa\xb5\x3c\xef\xa3\x9e\xef\x51\x6b\x2f\x50\x31\xe9\xed\x99\x9e\xf7\x13\x1b\x2d\x3f\xc2\xf3\x46\xf5\x7c\xc2\x93\x3c\x6f\xd4\xca\xd3\xd6\xf3\xae\x52\xb6\xa9\xb0\x16\xc9\x54\xcc\xa6\x91\x6c\x01\x82\x2f\x0f\xad\xd5\xa2\xbe\x02\x6c\x42\x79\x03\x6f\xb8\x5a\x5b\x75\x2c\x92\x71\x07\xdd\x44\xab\x58\x67\x47\xbc\x31\x05\x8d\xe6\x58\x19\x56\x6b\xf3\x91\x4d\x92\x30\xcd\x09\x03\xb2\xa0\x95\xbb\x55\xbc\xbd\x98\x58\xc4\x9a\x78\xce\xa1\x83\x2f\x5f\xbe\x7f\xff\xf2\xfd\x3b\x26\xc1\x31\xfa\x81\x41\xc7\x41\x6e\xcf\x71\xa1\xeb\x04\xff\xee\x4d\x86\x68\xf5\x07\xd6\x58\x4d\xd0\x0f\x2c\x59\x96\xea\x8d\x9a\x90\x93\x1a\x7f\x60\x75\xa5\x8f\xc6\xf0\x07\x36\x99\xc9\x23\x43\xf9\x03\x2b\x2f\x4c\x64\xff\xc0\x36\x10\xbf\x7c\x11\x8a\x0d\xb1\x86\x35\x84\x44\x51\xc4\xca\x52\xb1\x1b\x84\xf8\x05\xc3\x30\x4c\x48\xa5\x02\xd0\xde\x21\xc4\x2a\xb5\x5c\x49\xa8\x75\xb1\x82\xd8\xc5\x7e\x33\xd4\x77\xd4\xea\x96\x3d\xe9\x8d\x0d\xdd\x86\x7e\x90\x08\x7d\x7e\x12\xd5\x21\xa8\xa7\x28\x3f\x85\xf8\x2a\xf5\xbb\x38\xe7\xb1\xed\x84\x3e\xfa\xff\xeb\x29\x96\x8a\xb6\x7f\xba\xab\xc9\xee\x4f\xc3\x71\x66\xc8\xee\x3d\x85\xbb\x63\xb4\xa7\x98\x8b\x44\x18\xd6\x94\x72\xd5\xa6\x88\xfd\x76\x18\xfe\x8a\x1d\xc6\xef\xfe\xf6\x1f\xb8\x53\x34\xcf\x99\xd6\xbb\x19\xbf\x6b\x52\xad\x09\xf2\x95\xa1\x37\x81\xb6\x6b\x28\xc6\x04\x9a\x01\x4e\x4e\xdf\x7e\x32\x67\xa7\x91\x5c\xe2\xf4\x02\x59\x37\x73\x1e\x48\xdb\x4e\xf3\x7e\x6e\xc0\x93\xb9\x3f\x87\xe6\x12\xff\x17\x49\xbb\x2a\x01\x5f\xa5\xe5\x95\xa7\xed\x3b\x46\x72\x52\x4a\xec\x5c\xe1\x21\x59\x13\x85\x86\xe8\x0f\x3d\x86\x82\x95\xa5\xb0\x31\x34\xeb\x39\x29\x83\xc9\xae\x8d\x50\xd0\xba\xce\x53\xe3\xdb\xd8\xe3\xf4\xf8\x70\x6e\xa3\xe8\x8c\x5d\xcb\xab\x1e\x54\x14\x6b\x66\xba\x91\xc9\x39\x80\x08\x52\x72\xb4\x56\x38\xa6\xc7\x1f\xfc\x8a\x6d\xff\xe8\x39\x68\x3a\x43\xa6\xf2\x5e\x60\xf2\xaa\xd7\x87\x4e\xff\x11\xca\x36\xcf\xdf\x46\x56\x50\xd3\x36\x4f\x9d\xa2\x66\x84\x54\xfd\x81\x89\xdb\x43\xb8\x8d\x22\x7f\xec\x5e\x3c\xaf\x18\x9c\x4c\x46\x86\xe2\xbb\x03\xcb\x56\xcf\xb8\xe9\x1e\xda\xe8\x86\x77\x3f\x02\xa5\xdb\x28\xe1\x13\x1c\x02\x17\x24\x1b\x69\x1a\x52\xc2\xaa\xf6\xde\x6b\x19\xea\x2b\xf6\xd5\x7b\xf8\xeb\x39\x62\x0d\xf5\x49\x64\x1a\xea\xcd\x04\xee\x54\x6f\x43\x5e\x04\xa2\xad\x49\x6f\xf2\x2c\xba\xb7\xb0\x82\xa4\x9f\x09\x55\x91\x38\x39\xcd\x80\xbb\x7c\x1e\x03\x5b\x58\x67\x74\x3a\x22\x0b\x41\x08\xa7\x98\xb0\x26\x1b\xad\xec\x5b\x91\x78\xd8\x12\x7f\x80\x11\x55\xf8\x97\x05\xed\x6c\xad\xdd\x73\xd5\x8f\xcb\xfa\x18\x5c\x90\x64\xff\xfb\x10\x8d\xa7\x29\x0a\xca\xf5\x59\x64\xbd\x83\x79\x9b\x7b\x3b\x45\xa0\xeb\x4f\x89\xfb\xc8\xb4\x1e\x60\x44\x57\xc9\x6b\xea\xe7\xda\xea\x06\x89\x0c\x1d\xf4\x70\xfc\x3c\x05\x2c\x44\xb9\x8a\x42\x74\x06\xc7\x5e\x25\xd0\xd2\xb4\x07\x82\xd6\x7b\x50\x37\x11\xe7\x8d\xbc\x44\x9a\x47\x3b\xb2\x9f\x26\xbe\x10\xbc\x6b\x44\x86\x86\xdf\x42\xe9\x73\xe4\x78\x04\xed\x56\x2a\xaf\x4a\xf3\x39\xb4\xdd\x44\xd3\x65\x5a\x76\x14\x8f\x2c\x6b\x38\x9b\x3c\x46\xd1\x31\xac\x9b\x67\xd4\xcf\x77\xcf\xd0\x37\x81\x86\xdd\x73\x8d\x31\x7a\x0a\x85\x61\x68\xb7\xd9\xed\x96\xc0\x57\x2c\x4c\xf2\x2b\xb6\x75\xf1\xca\xc8\x72\x90\xda\x83\xee\x19\x26\x9e\xe0\xb7\xb7\x70\xae\x51\x7c\x67\x76\xb4\x81\xfa\x34\xe9\xde\x21\xd8\xab\x72\x33\x4c\x15\x2d\x7b\xa1\x94\xc3\xe9\x59\x66\x0f\xaa\xaa\x8d\x1c\xe7\x51\x81\x5e\x45\x70\xb4\x4e\xdb\xde\x0e\xad\x8c\xfc\x81\x77\xd0\xfe\xb8\x1e\x5c\x82\x7d\x9d\xe2\x13\x56\x76\x0c\x70\x9b\x85\x6f\xe0\xb9\xab\x49\xf4\x35\xf8\x45\xa8\x57\xd3\xfe\xcd\xa0\x2b\x84\x6e\x73\xa8\x0d\xc8\xbd\x12\x3d\x89\xda\x53\xa0\xaf\xa6\x6f\xb7\x6a\x72\x00\xf8\xb3\x95\xe1\x08\x74\x94\x7c\xf3\x3c\xb8\xf1\xc4\xb2\x37\x8e\x6f\x8e\x6c\xc7\xb0\xcc\xe7\x0b\x3a\x8c\xe1\x3a\xf9\xa1\x07\x6e\x67\x66\xeb\x7a\x22\x56\x2a\x6e\x93\x7f\x00\xc7\x55\x4e\x02\x63\x6f\x67\x62\x62\xa3\xb9\x61\xcd\x9c\x4f\xe1\xe6\x14\xb2\xab\x6c\x9d\x7a\xe8\x76\xfe\x76\x45\x94\x0f\xe3\x69\x87\xe0\x2a\x1f\x67\xab\x5d\xc7\xa0\xf7\xf1\xf6\x43\x4c\x3b\x0c\xfd\xe4\x02\xf8\x5e\x03\x3f\x06\x7a\xbc\x84\x7a\x92\x85\x5f\x42\x71\x0b\x0f\x57\xd6\x75\x17\x91\x3d\x2f\x7c\xbd\x07\x7c\x13\xed\xd7\x83\x58\x70\xb1\xfd\x11\x6a\xf3\x1e\x7e\xe4\xa5\xbe\x97\xc4\xed\x03\xf9\xae\xc2\xd8\x93\x2d\x6b\x18\x59\xca\x17\x60\x5e\x4d\x11\x7e\xfb\x4d\x45\x2e\x34\x46\x0e\xf6\xfd\x9f\xff\xc4\x5e\x1c\x6b\xa4\x06\x76\xd3\x5e\x7e\xfc\x70\xd1\xd2\xfd\xf6\xed\x15\x3b\x3f\x50\xb1\xd4\xdb\x06\xfa\xb5\xf8\xf3\x43\x65\x6b\xa6\xf7\xdd\x9b\xd0\x1f\x0d\xbd\x4c\xc0\xd1\xd0\x10\x09\xdf\xb0\x76\x56\xac\x89\xbe\x92\x61\x7f\x62\x24\x79\xf3\x46\xb4\xa1\xf6\xb4\xc0\x36\x51\xba\xf0\x39\xdb\xd1\x5b\xb4\x58\xba\x5c\x13\x73\x19\x69\xbf\x05\x84\xd5\xc4\xb4\x58\x13\xa5\xa4\x58\x0f\xed\x8a\x78\x77\xcb\x12\xd6\xac\xa4\x36\x2a\x53\x13\xeb\x8d\x5a\x2e\xd9\xd8\x7c\x95\x12\x8b\x62\x43\xc4\x92\x42\x3d\x29\xa4\xc4\x0b\xfb\x68\x9b\x75\xc7\xf1\xc7\x5e\xa8\x14\xf3\x3c\x61\x1c\xe3\xb9\xb2\x49\x76\x8e\x92\x63\xf9\x84\xcb\x46\x27\x85\xb5\x4d\xf4\xaf\xec\x28\x9e\x95\xc4\x76\x29\xfb\xd3\xe5\x10\xa4\xe3\x94\x14\x76\x55\x82\xcb\x0a\x73\x9f\x04\xde\x17\x95\x7e\xa2\x18\xce\x10\x73\x2c\x8b\x13\x65\xb0\xe7\x2a\x45\xb8\xc4\xf1\x2b\x08\xe4\xbc\x6a\xbc\xab\x21\x5d\xd5\x8e\xef\xdf\x31\xa8\xaa\x48\xc5\xc6\xd0\x9c\xc1\xd1\x68\x75\x44\x68\x2e\x8d\x89\x9d\x5c\xbd\x51\xf7\x49\xf6\x19\xfb\x7d\x88\x56\xbd\x39\x1c\xcd\x50\x6f\x03\x10\x61\xa9\x5a\xb9\x12\xa4\xfb\xf0\x54\x68\xa4\xbf\x21\xff\xc5\x1b\x1f\x46\x70\x1a\xf6\x1f\xbb\x08\xe9\x0f\x0f\x63\xfe\xcd\x13\xdb\xc5\x6b\x23\x23\xa5\x0f\x6d\xa8\xb8\xc8\xc6\xe6\xd0\x5e\x19\xa6\xfe\x1b\x41\xd3\xdf\x30\xa9\xdc\xf0\xfb\x97\xae\x43\xf1\x90\x5e\x83\xf3\x25\xd4\x77\x1a\xa6\xf6\xf0\xb6\xd5\xe5\xa4\x67\x98\x3a\x72\xdc\xde\x08\x6e\xfe\xf1\x12\xed\x97\x57\xec\x05\x7f\xf9\xf6\xc7\x7b\x55\x09\x01\x3a\xa5\x2b\xa7\x24\x7d\xdc\x5f\x30\x44\xab\xcd\x84\x1f\xc9\x73\x5f\x2f\x71\x0c\xdd\xdc\xa4\xfa\x37\x08\x74\xf7\xd0\x09\x69\x30\xd4\xb7\x1b\x64\x89\xf9\xc8\xb0\x4d\xe8\xbe\x65\xf8\x02\x19\x7a\xdf\xc5\x0c\xd3\x45\x3a\xb2\x43\xb3\xf6\xfd\x3b\xb6\x40\xd8\xc2\x18\x8d\xb0\xe9\x0c\xd9\x2b\x4c\x5e\xed\xe0\x3b\x16\xe6\xf6\xa1\x8b\x19\x0e\xb6\xe8\xef\xbf\x35\x1c\xcc\xed\x23\x4c\x33\x6c\xc7\xc5\x0c\x17\x8d\x31\xc3\xf4\xbe\x51\xac\xf1\xc4\x72\x0c\x17\x6d\x64\x79\x03\x59\x47\xc2\xf5\x81\xef\x7b\x02\xbe\x7d\xf1\x6d\x6b\x63\x5e\x15\xcb\x71\x75\x1b\xd5\xab\x45\x4c\x85\x2e\xdc\x78\x6f\x4c\x9d\x8d\x27\x1e\xc2\x11\x72\x91\xe7\x1e\xfe\x7f\x00\x00\x00\xff\xff\xe2\xe4\x45\xdc\x49\x51\x01\x00") func offer_idsHorizonSqlBytes() ([]byte, error) { return bindataRead( @@ -326,7 +326,7 @@ func offer_idsHorizonSql() (*asset, error) { } info := bindataFileInfo{name: "offer_ids-horizon.sql", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} - a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x9e, 0xd2, 0x15, 0xe6, 0x9b, 0xa7, 0x35, 0x12, 0x96, 0xc8, 0x52, 0xdb, 0xcd, 0x36, 0x7e, 0xb5, 0xd0, 0x60, 0x30, 0x39, 0x7c, 0x50, 0x59, 0x6, 0xe7, 0x8a, 0x46, 0xe, 0xd1, 0x20, 0x2f, 0xe}} + a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xb6, 0xf4, 0xbd, 0x1e, 0x7d, 0xa7, 0xf7, 0xca, 0x39, 0xb0, 0xae, 0x8e, 0x10, 0x7, 0xa6, 0x3b, 0x27, 0xce, 0xee, 0xc6, 0xf1, 0xdd, 0x80, 0xc4, 0xfc, 0xb7, 0xc, 0x8b, 0x31, 0x60, 0xb5, 0x51}} return a, nil } @@ -350,7 +350,7 @@ func operation_fee_stats_1CoreSql() (*asset, error) { return a, nil } -var _operation_fee_stats_1HorizonSql = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\x7d\x79\x8f\xaa\x48\xf7\xff\xff\xf3\x2a\xc8\xcd\x24\x7d\x6f\xba\xef\x34\xfb\x72\xe7\x3b\x4f\x82\x8a\x4b\xab\xb8\xaf\x93\x89\x29\xa0\x50\x5a\x05\x1a\x70\xeb\xc9\xf3\xde\x7f\x11\x70\xa3\x41\x11\xb4\xef\x3c\xf9\x4d\x67\x72\x47\xa4\xea\x6c\x75\xea\x7c\xea\x54\x1d\xf0\xfb\xf7\x5f\xbe\x7f\x47\xea\x86\xed\x8c\x2d\xd8\x6a\x54\x10\x05\x38\x40\x02\x36\x44\x94\xc5\xdc\xfc\xe5\xfb\xf7\x5f\xb6\xf7\x73\x8b\xb9\x09\x15\x44\xb5\x8c\xf9\xa1\xc1\x12\x5a\xb6\x66\xe8\x08\xf7\x1b\xfd\x1b\x76\xd4\x4a\xda\x20\xe6\x78\xb4\xed\x1e\x68\xf2\x4b\x4b\x68\x23\xb6\x03\x1c\x38\x87\xba\x33\x72\xb4\x39\x34\x16\x0e\xf2\x07\x82\xfe\xee\xde\x9a\x19\xf2\xf4\xe3\xb7\xf2\x4c\xdb\xb6\x86\xba\x6c\x28\x9a\x3e\x46\xfe\x40\x1e\x3a\xed\x3c\xfb\xf0\xfb\x8e\x9c\xae\x00\x4b\x19\xc9\x86\xae\x1a\xd6\x5c\xd3\xc7\x23\xdb\xb1\x34\x7d\x6c\x23\x7f\x20\x86\xee\xd3\x98\x40\x79\x3a\x52\x17\xba\xec\x68\x86\x3e\x92\x0c\x45\x83\xdb\xfb\x2a\x98\xd9\xf0\x84\xcd\x5c\xd3\x47\x73\x68\xdb\x60\xec\x36\x58\x01\x4b\xd7\xf4\xf1\xef\xbe\xec\x10\x58\xf2\x64\x64\x02\x67\x82\xfc\x81\x98\x0b\x69\xa6\xc9\x4f\x5b\x65\x65\xe0\x80\x99\xb1\x6d\xc6\x57\xda\x42\x13\x69\xf3\x99\x8a\x80\x94\xf2\x88\xd0\x2f\xb5\xda\x2d\xa4\x26\x56\x06\x7e\xfb\xdf\x26\x9a\xed\x18\xd6\x66\xe4\x58\x40\x81\x36\x92\x6b\xd6\xea\x48\xb6\x26\xb6\xda\x4d\xbe\x24\xb6\x8f\x3a\x9d\x36\x1c\xc9\xc6\x42\x77\xa0\x35\x02\xb6\x0d\x9d\x91\xa6\x8c\xd4\x29\xdc\xfc\xfe\x19\x0c\x65\xf7\xd3\x67\xb0\xdc\xfa\xd5\xe7\x29\xe8\x71\xbb\x5e\x3b\x4f\xc0\xad\x23\x9f\x63\x76\xd4\xea\x40\xdc\x6d\x5e\x12\x73\x42\xff\xa8\xa5\x4f\xd6\x95\x6a\x04\x55\x15\xca\x8e\x3d\x92\x36\x23\xc3\x52\xa0\x35\x92\x0c\x63\x7a\xbe\xa3\xa6\x2b\x70\x3d\x3a\x52\x4e\xb7\x81\xeb\xe8\xf6\xc8\xd0\x47\x9a\x72\x4d\x6f\xc3\x84\x16\xd8\xf7\x75\x36\x26\x4c\xd1\xfb\x20\x49\x2a\x29\xae\xeb\x3b\x83\xca\x18\x5a\x6e\x47\x1b\xbe\x2d\xa0\x2e\x5f\xa5\xc2\x51\x77\xd3\x82\x4b\xcd\x58\xd8\xfe\x77\xa3\x09\xb0\x27\x09\x49\xa5\xa7\xa0\xcd\x4d\xc3\xda\x4e\x47\x3f\xa6\x26\x25\x93\xd4\x96\xf2\xcc\xb0\xa1\x32\x02\xce\x35\xfd\x77\xce\x9c\xc0\x95\xfc\x79\x99\x40\xe8\xe3\x9e\x40\x51\x2c\x68\xdb\xe7\xbb\x4f\x1c\x4b\x71\x71\x67\x34\x33\x8c\xe9\xc2\x8c\xd1\xda\xbc\x24\x92\xd7\x0a\x68\xd6\x95\x84\x77\x41\x37\x76\x87\x6d\x9c\x50\x55\x68\xc5\x6b\xba\x23\x9f\xa0\x8b\x6f\xd6\x78\x9d\xdc\xd0\x7a\x05\x93\xe3\x50\x7c\xa9\x87\xb9\xed\x30\x71\x2e\x8e\x80\x7d\x12\x80\xa4\xcd\x45\x37\x9a\xec\x67\x7a\x9c\xc6\x86\x27\x87\x71\xb1\xa1\x66\x3b\x23\x67\x3d\x32\x2f\x93\xdc\xb6\x34\xcc\xb8\x2d\x61\xdc\x66\x3b\x28\x39\xdf\x58\xda\x4d\xf7\x8b\xcd\x2e\x47\x31\x69\x13\x6f\x30\x3d\x8c\xdc\x5a\xdb\xb6\x17\x97\x38\xef\x1b\xcb\x86\x02\xaf\x5c\x17\xec\xdd\xc0\x04\x96\xa3\xc9\x9a\x09\xf4\xb3\xe0\x7d\xa9\xeb\xc8\xbc\x72\x6d\xb2\x47\xb4\x6b\x25\x08\xef\x78\x35\x7f\xd7\x78\x71\xf8\x79\x0d\xef\x4e\xdf\x1b\xcc\xed\x48\xfa\x1f\xb7\xf8\xb0\x5b\xfa\xb9\xce\x30\x8a\x29\xc1\xd8\xb0\xcc\xd1\x5c\x1b\xfb\x0b\x86\x33\x22\x04\x5a\xc6\xd6\xf1\xfa\xf5\xde\x39\xca\x71\x9d\xd3\xeb\x9d\xad\x55\x3a\x55\x11\xd1\x14\x8f\x73\x4e\xc8\xf3\x9d\x4a\x3b\x26\xed\x08\xa7\xbb\x01\x65\x7f\xb8\xcf\x53\x72\xaf\xe2\xab\xbf\x43\xe9\x96\xd0\xe8\x08\x62\x36\x81\xcd\xb6\xeb\x6c\x1b\xbe\x5d\xcd\xf9\x84\x48\xec\xde\x0a\x8c\xd9\xf6\xb0\x9a\x8d\xad\x61\xc4\xac\xbf\x46\xbf\x70\x12\xf1\xfa\xfa\xeb\xbe\x78\x8d\xfd\x45\x5e\x6c\xdd\xfc\x08\x70\x8d\x2e\x5e\x97\x98\x6d\xfd\xe5\x5f\x7c\x79\x76\xeb\xc5\x38\x12\x05\x62\xc8\xf9\xc6\x47\x21\xc1\x6f\xc8\x17\x0a\x4d\xa1\xc0\xb7\x43\x1a\xcf\xb5\x6d\xc6\xa1\xc9\xf0\xab\xbe\x98\x43\x4b\x93\xff\xfc\xeb\x5b\x8c\x5e\x60\x9d\xa0\xd7\x0c\xd8\xce\x57\xa0\x6f\xe0\xcc\xdd\x8a\x89\xd1\x43\xd5\xac\xd0\x2e\xf9\x8e\x98\x6d\x97\x6a\xe2\x19\x7d\x46\x60\x3c\x3e\x48\xf7\x84\x7c\x10\xf4\x0c\x8d\x9d\x76\x29\x68\x6c\x75\x75\xbb\x1f\x84\x7f\x42\xae\x51\xc4\x55\x3d\x06\x05\xa1\xdf\x16\xc4\x56\x80\xc4\xcc\x1c\xdb\x6f\xb3\x9d\x2f\x66\x8b\x42\x95\xff\xc0\xe1\xf7\x5f\xbc\x5d\x38\x11\xcc\xe1\x8f\xdd\x77\x48\x7b\x63\xc2\x1f\x7e\x97\xdf\x91\x96\x3c\x81\x73\xf0\x03\xf9\xfe\x3b\x52\x5b\xe9\xd0\xfa\x81\x7c\x77\x37\xe7\xb2\x4d\x61\x3b\x5e\x3e\xe5\x1d\xbd\x5f\x4e\x28\x9e\xde\xf4\x09\x67\x6b\xd5\xaa\x20\xb6\xcf\x50\xf6\x1a\x20\x35\xf1\x94\x00\x52\x6a\x21\x0f\xbb\x6d\xb7\xdd\x77\xb6\x4b\xe4\x21\xc8\x79\xa7\xbe\xcf\x73\x6f\xa1\x8b\xfa\x9c\xd8\x52\xac\xb5\x03\xf6\x44\x7a\xa5\x76\x71\x2f\xd6\xf1\xfe\xdb\x09\xfb\x03\x95\x80\x20\xd7\x28\xff\x81\x88\x6b\x80\x7a\xe5\xd9\x1c\xb7\x1a\x15\xc4\xb4\x0c\x19\x2a\x0b\x0b\xcc\x90\x19\xd0\xc7\x0b\x30\x86\xae\x19\x62\xee\x17\x1e\x8b\x7b\xd9\xd1\x7c\xf1\x77\xbe\x7a\x90\x7f\x37\xb6\x61\xb6\xdc\x7b\xf6\x45\xfa\x48\x53\x68\x77\x9a\x62\xeb\xe8\xbb\x5f\x10\x04\x41\x2a\xbc\x58\xe8\xf0\x05\x01\x71\xb5\xaf\x56\x3b\x5e\xbc\x6b\xb5\x9b\xa5\x6c\xdb\x6d\xc1\xb7\x90\x5f\x47\xbf\x22\x2d\xa1\x22\x64\xdb\xc8\xaf\xd8\xf6\x2a\x38\x1a\x17\x27\x62\x3a\xed\x2e\x91\xbf\x99\x72\x78\x98\x72\x71\x22\x55\x3a\xfd\x62\x70\xd8\xab\xb8\xff\x2a\x91\x86\x5f\x7f\x41\x90\x2c\xdf\x12\x90\x5e\x51\x10\x91\x5f\xb1\x3f\xb1\xbf\x9e\x7f\xc5\xfe\xc4\xff\xfa\xcf\xaf\xb8\xfb\x19\xff\x13\xff\x0b\x69\x7b\x37\x11\xa1\xd2\x12\xb6\x46\x11\xc4\xdc\xb7\x50\xcb\xc4\xc0\x81\x94\x96\xb9\xcc\xe1\xde\x96\xf9\xbf\x24\x96\xf9\x88\xa9\xbe\x1d\xf6\x38\x1c\xcf\x10\x07\xd8\xfe\x40\xd1\x95\x18\x41\x5a\x5b\x5b\x21\x7f\x1c\x22\xc0\x93\xf7\x75\x7b\x50\x17\x90\x3f\x8e\x67\xc4\xb7\xb0\x59\x7b\x53\x19\x83\x04\x03\x22\xee\xa6\x71\x7c\x09\x43\x97\x40\x69\xa5\x0c\x23\x1a\x90\xf4\x64\x42\x9e\x8a\x7b\xf0\xb2\x8f\xd2\x86\x2d\xf3\x52\x4b\x1b\x42\x34\x28\xed\xf1\x24\x39\x2b\xed\x16\xb9\x14\xa8\x82\xc5\xcc\x19\x39\x40\x9a\x41\xdb\x04\x32\x44\xfe\x40\x1e\x1e\x7e\x3f\xbd\xbb\xd2\x9c\xc9\xc8\xd0\x94\xa3\xa3\xb4\x13\x5d\x8f\xd7\xbf\xbe\x8a\xee\x04\x8b\xa7\x9e\x37\x17\x8f\x93\x6f\x4f\x23\x4d\x41\x24\x6d\xac\xe9\x8e\xbb\x30\x10\x3b\x95\x8a\xa7\x0e\x98\x6f\x97\xf1\x88\x3c\x01\x16\x90\x1d\x68\x21\x4b\x60\x6d\x34\x7d\x1c\x68\xa6\x2f\xe6\xfb\x25\x3f\xa2\xe9\x0e\x1c\x43\x2b\xd0\x44\x9d\x81\xb1\x8d\xd8\x73\x30\x9b\x7d\x64\xe3\x18\xf3\xd9\x47\x26\x5f\x71\x8a\xfa\xb6\x6f\xf9\x71\xd8\x83\x79\x43\x52\x73\x04\x77\x3b\xf6\x26\x71\xe0\xfa\x83\x41\x4c\x73\xa6\xb9\x7b\xf6\x88\xa3\xcd\xa1\xed\x80\xb9\x89\x6c\xc7\xcc\xbd\x44\xde\x0d\x1d\x7e\x14\x34\x2a\x2b\xda\xad\x47\xfd\x74\x2a\x9e\xcc\xfb\xe4\x2b\x82\xaa\xef\x86\x7c\xb3\xed\xad\xe8\x30\xf7\x8b\x92\x98\x6d\x0a\xee\xf2\x2b\x33\xf0\xbf\x12\x6b\x48\xb5\x24\x76\xf9\x4a\x47\xd8\x5f\xf3\xfd\xc3\x75\x96\xcf\x16\x05\x04\xbb\xa4\x4c\x62\xb3\x07\x09\x7d\x70\x45\x7f\xd3\x03\xd1\xe1\xda\x59\x82\xd9\xd7\x87\x08\x8d\x1f\x7e\xfc\xb0\xe0\x58\x9e\x01\xdb\xfe\x16\x1c\x2e\xef\xac\x22\xc4\xb7\x68\xf2\xdb\x99\x81\xf2\x72\xe3\xd4\x9a\x79\x3b\x3a\x7b\xbd\xc2\x67\xc6\x61\xaf\x2e\x5c\xcc\xd0\xe6\xb2\xa1\x84\x35\xc7\xf0\xf0\xe6\xde\xf6\x5f\x48\x07\x8a\x3e\x37\xc3\xc2\xb7\x17\x6e\xe4\xb6\xc7\x34\x3f\xcd\x69\xcf\x29\x82\xd4\x7a\xa2\x90\x43\x32\x83\x0b\x1a\x79\x3b\x74\xe7\x15\xda\xd3\x0a\xdc\xfe\x4d\x53\xa2\x64\xdb\xed\xf9\xa4\xf5\x3a\x9f\x8e\xef\x76\x81\x39\x33\x8a\x8a\xf4\x1f\xb7\xb8\xa2\x5a\x7e\x71\x0f\x3e\xbe\x44\x78\xb3\xeb\xc7\xe1\xb7\x14\xe8\x00\x6d\x66\x23\xaf\xb6\xa1\x4b\xd1\xce\xb6\xdb\x28\x4b\x6b\x07\x9f\x8e\x6f\x87\xdd\xb9\x75\x84\x6c\x47\x87\xc9\xb1\x66\x61\xd8\x39\x76\x78\x47\xdf\x2c\x47\x3b\xa3\xee\x40\xec\xe5\xd8\x45\x39\x34\xc0\xe1\x30\x10\xf1\xda\xef\x0f\x93\x03\xc0\x64\x2c\x9c\x03\x36\x05\xfb\x58\x10\x38\x17\x3b\x79\x6d\x17\xa6\x12\xbb\xed\xde\x75\xfc\xcb\xc0\x39\xfb\x07\x5d\xb0\x0f\xeb\x01\x07\xcc\x46\xb2\xa1\xe9\x76\xb8\x0f\xaa\x10\x8e\x4c\xc3\x98\x85\xdf\x75\x4f\x3e\x55\x18\x35\xd6\xee\x6d\x0b\xda\xd0\x5a\x46\x35\xd9\xae\x43\x9d\xf5\xc8\x5d\x26\x69\xef\x51\xad\x4c\xcb\x70\x0c\xd9\x98\x45\xea\x15\x1c\xa3\x9d\xb3\x40\xa0\x40\xcb\x5d\x5e\x78\xdf\xdb\x0b\x59\x86\xb6\xad\x2e\x66\xa3\x48\x47\xf1\x15\x07\xda\x0c\x2a\xd1\xad\xa2\xa7\x55\xc4\xde\x75\xda\x59\x16\x71\x1e\x72\x01\xf3\xe2\x47\x9b\xcb\xf1\xeb\x5a\x95\x6f\x0b\x63\x67\x79\x7c\x16\xac\x5d\xa5\x68\x4a\x98\x3b\xcb\xeb\x23\xec\x85\x37\x3f\x03\x83\x47\x27\x3b\x37\xf3\xcd\x4b\x69\xce\x69\x55\x55\x44\x2a\xb4\x5d\xf9\xcb\x9e\x2a\x2e\x02\xa6\x04\x40\x7f\xe6\x1b\x0b\x4b\xde\x97\x69\x44\x40\xcf\x2e\x9c\x3c\x3c\xfc\xf8\x11\x9d\x8a\x45\xcf\x03\xff\x60\x2d\xad\x39\xfd\x5a\xc0\xaf\x37\x5d\x2f\xf8\x21\x31\x09\x7a\xb9\xb5\x30\x91\x6c\x03\x95\x88\xe7\x1a\xf9\xc5\x91\xe7\x9a\x78\x79\x70\x68\x83\x8f\x35\x9d\x17\xda\x9d\x65\xb7\x6f\x75\x86\xa3\x2b\x92\x66\x8f\x6c\x38\x9b\x41\x0b\x91\x0c\x63\x06\x81\xbe\xc3\x24\x4d\x86\x23\xfd\x04\x7f\xbd\xef\x4e\x31\xf9\x50\x4d\x34\x0a\xa0\xf5\x49\x3d\x53\xf0\xa6\x65\x2c\x74\xc5\x2d\x08\x9e\x69\xa6\x09\xc6\xf0\x23\x51\xcd\x1e\xc1\x35\x90\x9d\x53\xb9\x8e\xce\xf7\x43\x4b\x46\x5d\x75\x47\x6e\x51\x31\x92\x2d\x0a\xd9\x32\xf2\xf5\xeb\xb1\xe9\xff\x83\xa0\xdf\xbe\x5d\x22\x15\xd6\x7d\x67\xed\xff\xfb\x30\x00\x31\xe8\x9d\x0c\x46\x80\x7c\x60\xa4\x5c\x01\xcf\xce\xc1\xf0\xa3\xf1\x1b\xcc\xca\xf0\x62\x87\x98\x10\x1c\x27\xf6\xa5\x01\xe1\x4b\x85\x05\xb7\x81\xe1\x0b\x5c\x3e\x0b\x88\xaf\x54\x36\x25\x14\x5f\xe0\xf6\x11\x8c\xa3\x3a\x9c\x81\xe3\x93\x62\x92\x1b\xfa\xea\xce\x3f\x8f\x45\x8a\x9d\x7d\xf9\xa0\x71\x21\xa7\x8b\x8b\xd8\xe7\xc1\x37\xb4\xed\x81\x75\xe8\x7c\xd9\xa6\x0f\xd1\xf9\x47\x54\x66\xf7\x53\x72\x33\x67\x3d\x82\xfa\x12\xce\x0c\x13\x86\xed\x77\x3a\xeb\x6d\xa6\xb4\x98\x39\x11\x37\xe7\xd0\x01\x11\xb7\xb6\x39\x5a\xd4\x6d\x5b\x1b\xeb\xc0\x59\x58\x30\x6c\x6b\x8e\xa3\xbf\xfd\xf9\xd7\x61\xd1\xf3\xf7\x7f\xc3\x96\x3d\x7f\xfe\x15\xb4\x39\x9c\x1b\x11\xbb\x68\x07\x5a\xba\xa1\xc3\xb3\x8b\xa8\x03\xad\x8f\x64\x7c\xcd\xb4\x39\x1c\x49\x5b\x18\x74\xb7\xba\x59\x0b\xe8\x63\x78\xe2\x96\xe1\x37\xe7\x9a\x3e\x8a\xf0\x9e\xe8\x06\xa3\x20\xc2\x86\x36\xf2\xf9\x8e\x81\x79\xd2\x16\xae\x1d\x0b\x8c\xb6\xa6\x86\x96\xed\x8e\xc2\x9f\x7f\x05\xf3\xcd\x53\x90\xde\x0e\xd9\x56\xed\x31\x54\x4e\xd3\x4e\x1d\xae\x46\x01\xa7\xbe\xb4\x5b\x88\x68\xca\x2e\x5e\xec\xaa\xd7\xe2\x04\x39\x2f\x60\xb8\xa5\x82\x17\x0a\xe3\x5a\x42\xfb\xcc\x16\xf1\xf1\x66\xdc\xf1\x06\xf1\x75\x29\xd4\xed\x94\x88\x59\x37\x78\x56\xa9\xb3\xa9\x57\x1c\x25\x23\xd7\x0a\x37\x53\x33\x76\xe9\xe5\x59\x45\x2f\x00\x5b\xb8\xaa\x39\xe0\x00\x44\x35\xac\x0b\x07\x65\x48\x8e\x6f\xf3\x17\xd4\x8b\x20\x79\xee\xc0\x29\x0e\xd9\x92\xd8\x12\x9a\x6d\xa4\x24\xb6\x6b\x1f\x0e\x9d\xdc\x25\x46\x0b\xf9\xfa\x80\x8d\x34\x5d\x73\x34\x30\x1b\x79\x05\x40\xbf\xd9\x6f\xb3\x87\x27\xe4\x01\x47\x31\xee\x3b\x4a\x7f\x47\x09\x04\x63\x7f\xe0\xec\x0f\x92\xf9\x0d\x25\x70\x92\xa3\x1f\x51\xfc\xe1\xdb\xef\xf1\xa8\xe3\x23\xef\xc1\x8e\x13\xab\x4a\x9b\x91\x63\x68\xca\x79\x4e\x1c\x4d\x31\xd7\x70\x22\x46\x0b\x1b\x1e\x62\x94\xa6\x7f\x78\x98\xe4\x2c\x3f\x92\x44\x49\xf6\x1a\x7e\xe4\x08\x28\xca\x28\xb8\x25\x77\x96\x07\x45\x52\x04\x7e\x0d\x0f\x6a\xe4\xa1\xf2\x2e\x3f\x70\x8f\x72\xcf\xb2\xa0\x09\x14\xbf\x4a\x0d\x7a\xc7\xc2\x8f\x60\x31\x58\xb0\x24\x46\x5d\xc3\x82\x19\xcd\x0d\x45\x53\x37\xf1\xb5\x60\x31\x1a\xbf\x8a\x05\x7b\xa2\x85\x5f\xc1\x1d\x83\x0f\x43\xd2\xc4\x75\x7c\xb6\x83\x0e\xc6\x63\x0b\x8e\x81\x63\x58\xe7\x7d\x8a\x43\x31\x94\xbb\x86\x3c\xe7\x92\xf7\xb6\x6b\x47\x6b\xc5\x3a\x4f\x1d\x67\xb0\xab\x86\x1a\x43\x5d\xf2\xfe\x28\xb8\x49\xfa\x79\x06\x14\xc7\x5c\x65\x1d\x0c\x3b\x66\xb0\x4f\xde\xb6\x01\xe0\x3c\x23\x8e\xe6\xae\xd3\x04\x3f\x19\x68\x3f\x5d\xf6\x9e\x19\x3e\xc7\x09\x43\x19\x8a\xbc\x6a\x44\x30\xc2\x53\x67\xbf\x3b\x71\x76\xc4\x31\x0c\x67\xe8\xeb\x34\x21\x47\xaa\xb6\xde\x3d\x3f\x61\xcc\x67\x23\x55\x83\xb3\xb3\xa1\x11\xc3\x28\x0c\xbb\x2a\x08\x63\xd4\x6e\xc9\xb6\xdb\xce\x5f\x5f\x50\x83\x66\xae\x0b\xf3\x18\x3d\xd2\xf4\x31\xb4\x9d\xd1\xc7\x03\x83\x0b\xac\x18\x8e\xbd\x6e\x44\x98\x13\xb8\x76\x4f\x66\xc0\x79\x30\xc1\x70\x14\x25\x48\x9f\x49\x04\xd6\x9e\x2d\x33\xb8\x16\x6c\x3f\x94\x1a\xec\xa4\xc7\x9e\x90\x87\x42\xb6\x5f\x2e\xd0\x4d\x91\xac\x89\x25\xa1\x9e\xad\x8a\xf9\x0c\x43\xe0\x3c\x49\xd0\x43\xaa\x2e\xe6\x5a\xcd\x4a\xa1\x57\x66\x0a\x99\x4a\xb6\xda\xa8\x94\xf2\x35\xb2\xc5\x08\x83\x5e\xb7\x13\xb4\x50\x24\x13\x7c\xcb\x24\xd3\x2f\x34\x5e\x7a\xdd\x4a\xaf\x36\x28\xe6\x2b\xdd\x76\xb9\xd7\xa5\xf2\x85\x22\x4f\x54\xc4\xc1\x00\x7f\x69\x94\xab\x4c\x8d\x7f\xe1\x3b\x42\x23\xdf\xa1\x2b\xf5\x6c\x4b\xc8\x77\xfb\x35\x31\x36\x13\xc2\x65\xd2\xac\x0f\x8a\xa5\x0a\x9e\x2d\x11\x79\xb1\x41\x66\xfa\x95\x7c\x55\xcc\x55\xf2\x2f\x1d\xb1\xde\xc1\x8b\x03\x62\x58\xcd\xb7\x8a\x35\xb1\x93\x15\x6a\x7c\xab\xc7\x34\xb2\x4c\xad\x8f\x17\x1f\x92\x56\xac\x6c\x57\x71\x17\x86\xc1\xaf\xf2\x3b\x14\xe8\xfe\x66\xc3\xf3\xd5\x1c\x4f\x08\xf1\x84\x38\xd6\x02\xc6\x70\x8e\x8f\x75\x1a\xd7\x2c\xef\xae\xa9\x0d\xb8\x89\xa6\x27\x49\xc9\x13\x82\x3d\x79\x25\x5e\x97\x15\x0d\xab\x0d\x48\x3a\x09\x76\xf5\x01\x47\x73\x80\x40\x51\x9a\x64\x18\x0a\xa3\x39\x57\xaa\xad\xc7\xfe\xfd\xc5\x0b\xe3\x5f\x7e\x20\x5f\x30\xf4\x37\xd4\xfb\xfb\xf2\x84\x7c\x39\x14\xac\x6c\xef\xe9\xc0\xd1\x96\xf0\xcb\x7f\xa3\x3c\x35\xc8\x0e\x0f\xb0\xc3\xdd\xf1\xbe\x1b\xbb\x83\x76\x1c\x4e\x53\x9f\xa8\x9d\xc7\xee\xb3\xb4\x63\x09\x82\xc6\x3e\x4f\x3b\x9f\xdd\x9d\xb5\xc3\x9f\x10\x9c\x62\x68\x8e\x45\x19\x96\x21\xee\xae\x1d\x16\x60\x77\xff\xb1\xf3\xd8\x61\x18\xf7\x39\xf3\xee\x84\xdd\x27\x68\x87\x91\x0c\xc9\x92\x28\xc5\x30\x9f\xa2\xdd\x31\xbb\x4f\xd3\x8e\xa4\x3f\xc1\x33\xf1\x00\xbb\x4f\xd3\x8e\x65\x3e\xc9\x33\x8f\xd9\x7d\x96\x76\x14\xce\x7e\x0e\x22\x9c\xb0\xbb\x7f\xcc\xc4\x98\xed\x22\x9e\x21\x70\xf6\xfe\x88\x80\x05\xd8\xdd\x7f\xec\x30\x9c\x65\x49\x0e\xa5\x38\xf6\x53\xc6\xee\x84\xdd\xfd\xb5\x63\x29\x96\xe3\x08\x96\x66\xbd\x69\x87\xba\xdc\x6c\x07\x58\x8e\xa6\x8f\x47\x12\x98\x01\x5d\x86\x1e\xdf\x03\xe3\xd8\x0c\x88\x53\x06\xa1\xea\xdc\x4f\x9f\x6d\x9c\xf4\x14\x5a\x41\x6d\x3c\xd9\xf2\xc3\x9e\x90\x2f\xde\xc2\x75\x34\x85\x9b\x2d\x8f\xa4\xd9\xd8\x55\x83\xea\x4a\x45\xe2\x8c\xef\x42\x77\xb2\xb2\xcf\xe0\xde\x56\x0e\xe8\x13\xcf\xca\x09\xd3\x51\x4f\xaa\x0b\xc9\x4a\x58\x01\x6f\xd2\x64\x65\x57\xc4\xbb\x53\x96\x79\x42\x1e\x30\x5a\xa5\x55\x45\xa2\x64\x1c\x25\x39\x16\x85\x04\x09\x65\x8a\x20\x48\x99\x44\x39\x89\xa4\x70\x89\xe2\x50\x9a\xa2\x50\x85\x86\xb8\x24\x53\x90\xa6\x24\x86\x45\x09\x82\x82\x18\xce\xaa\x38\xf5\xb0\xa5\x81\xab\x18\x2b\x13\xa4\x24\x91\x34\x43\x63\x2c\x50\x19\x05\x47\x39\x82\x56\x20\x2d\x03\x12\x10\x0a\x26\x03\xc0\xb2\x98\x4c\xd0\x40\xe6\x00\x23\xb1\x9c\x0c\x19\x8c\x20\x29\x12\x2a\x24\xee\x65\xa9\x44\x60\x83\x83\xfe\x41\xd0\x3f\x48\x3a\xb8\xef\xe1\x7d\x4d\xfe\x46\x60\x24\xc3\xb2\x67\xef\x72\x0f\xfb\x04\x02\x43\x99\x6d\xfc\xa1\xb7\xe3\xf9\xe1\xef\x09\xc1\x08\xf7\x5f\xff\x9f\xfd\xb7\xfb\x0f\xd8\x13\xf2\xc0\xf3\x3c\x9f\x5d\x57\xd6\xaf\xb9\x16\xd3\xd4\x07\x03\x8b\x40\xc7\x53\x9c\x98\x6f\xa6\x06\x57\x2c\xbf\x95\x8a\x39\x60\xcf\xf5\xc5\xcb\xbb\x2e\xa0\xdd\x1a\x96\x7d\xe1\x05\x60\x72\xef\x22\xb7\x98\x59\xd9\x37\x9b\xd9\xc0\xf2\x5b\x39\x23\x6b\xed\xca\xbc\x58\x13\xe7\x8f\x3c\xdf\x7a\x2b\x4c\x0b\x13\x47\xe8\x6c\x49\xf3\xfd\x7a\xb7\xaa\x8f\xf9\xfd\x5f\x05\xa3\xd0\xe7\x29\xd7\x57\x6d\xb4\xfd\xd2\xc8\xaa\xa5\x05\x97\xcb\xda\x35\x61\xaa\x61\x65\xfd\x71\x52\xc1\x4b\xf9\xcd\xa6\xd2\xad\x2a\xfd\x4a\xeb\xad\x59\x9d\xda\xc3\xf1\x33\x66\x3f\xb7\x45\xbc\xda\x46\xeb\x6d\xbe\xb2\x1c\xae\x20\x3a\xb1\x2a\xcf\xcb\x1a\xf7\xb6\x61\x73\xfd\xd2\x66\xe2\x52\x96\x45\xb2\x02\xde\x4d\xbc\x71\x60\xc6\x77\x3a\x7c\xc8\xdf\x90\xef\x63\x64\x83\xe7\x73\xe8\x4b\xd8\xed\x7f\xf4\x9f\xe7\x55\x68\xc4\xc4\x0f\xce\x05\xfa\x36\x7e\xfc\xc0\xca\x38\x2e\x4b\xac\xcc\xc9\xa8\x44\x30\xb2\xca\xb1\x2a\xa3\x42\x9a\x51\x65\x02\xb0\x34\xca\xd0\x94\x4c\x40\x9a\x95\x65\x14\x12\x32\x60\x08\x12\xe0\x38\x49\x29\x34\x4d\x03\x9c\x54\x80\xfa\xe0\xc6\x38\x3c\xd4\xad\xa9\x48\x6f\x27\x09\x9c\x66\x2e\xde\xf5\x13\x32\x82\x61\xe8\x73\x73\x01\x8d\x39\x17\xc8\x95\xb6\x21\x37\x72\xf6\x5d\xad\xcf\xeb\xea\xe3\xf0\x79\x45\x4f\xc6\xca\x6c\xf5\x08\xaa\xab\x5a\xbd\x2c\xa3\x86\xd6\x54\x86\x73\x63\x8a\x2f\xb5\xb9\xc8\x98\x9b\xb1\xd5\x9c\x11\xdc\xca\x20\xad\x42\x93\x30\x5e\xe1\xfc\x1d\x7b\xe5\x96\x85\xa6\x59\xe8\x8f\x97\xe5\x65\x7e\xd2\x45\xdb\x25\x77\xec\xdc\xb9\x70\xe4\x9e\x8f\x85\xfc\xb0\xf8\xd6\x29\x4d\xf5\x16\x61\x52\xf6\x50\x22\xe5\x77\x99\x2d\xbf\xa2\x40\x2a\xb4\xaa\x5d\x55\x04\x6f\x8f\xdc\xfb\xfb\xcc\xc1\x9b\x2f\x1b\xca\x59\x6d\x0a\x9a\xb8\x79\x7c\xd6\xf9\x35\x66\x31\x79\xe5\x91\x2b\xac\xd6\x98\xda\xab\xb5\xaa\xd3\x82\xda\xdf\xf4\xb2\xce\xba\xf1\xe6\xce\xb5\x41\xc8\x5c\xa8\x1b\x61\xfe\xf4\x3f\x3e\x17\xf0\xf8\x73\x81\xba\x8d\x1f\x3f\x60\x34\x26\x63\x92\x42\x4b\x38\x05\x20\x06\x30\x82\x21\x71\xc0\x32\x32\x2d\x4b\x1c\x2e\xb3\x34\x05\x08\x5a\x26\x58\x56\x95\x58\x56\x56\x18\x8e\x63\x25\x96\xc6\x00\x94\x00\x4d\x73\xb4\xb2\x0d\xdf\xa4\xfb\x5f\x98\x5b\x47\x7a\x3b\xc5\xb0\x58\xf4\x4c\xd9\xdd\xf5\xd2\x08\x82\x26\x59\xf4\xcc\x5c\x60\xe3\xc2\xc2\x40\x2e\x70\x60\xd3\x5b\x14\x26\x22\x5a\x36\xd4\xc2\x86\xaa\x94\x86\x40\xb4\x6b\xa5\x47\xf2\x55\x84\x43\x8d\x1c\x00\x9a\x1e\x9a\xd2\x70\xc9\x6d\xba\x95\x7e\x65\x88\x91\x19\xfe\x55\xea\x37\xcb\xbd\xf2\x5b\xb5\x38\xae\x93\xca\xf3\x46\x6b\x57\x06\x05\xa3\x32\x19\x0e\x4c\xd9\x2e\x78\x2e\xe9\x4e\x85\xa3\xa1\x2c\x33\xc3\x7c\xd1\xec\x2c\xa9\xf5\xb8\x2e\x76\xa9\x7a\x57\x64\x61\x8f\xdb\x6c\xac\x17\x39\xd3\x19\xe6\xca\x78\xb6\x55\x2e\x2a\xcb\xfa\xd8\x19\x53\xd2\x54\xed\xcf\x2b\x39\xde\xe9\x4a\xab\x97\x79\x3f\x07\xcb\x99\x89\xfc\xba\x6c\x64\xbb\xab\x82\x32\x7d\xb3\x4b\x62\x91\xb6\x9a\x0b\xa1\xb0\xda\x52\xee\x84\x4c\x85\xea\x38\xcc\x9d\xfe\xc7\xa7\x02\x19\x7f\x2a\x90\xb7\x71\xe3\x07\x88\x31\x0a\x29\x53\x24\x03\x59\x19\xa7\x14\xc0\x51\x2c\x4b\x70\xdb\xa9\x42\x53\x2a\x50\x48\x9c\xa4\x64\x94\xc6\x24\x8c\x45\x29\x62\x3b\xe5\x08\x8a\x82\x24\x8b\x02\x49\x02\x00\x63\x31\x6f\x83\x1b\x0b\xf5\x6a\x22\xd2\xd9\x19\x96\x66\xa2\x17\x50\xbb\xbb\x5e\xce\x49\x73\x18\x4b\x9e\x99\x0a\x64\xcc\xa9\xf0\x98\xe7\xda\xf9\xe6\xe3\x6b\xb6\x0f\x66\x83\x31\x65\x4c\xb1\xd9\xa3\xd3\x98\xf6\xf9\x81\x54\xe0\x3b\x6c\xf6\x5d\xec\x52\xa5\xac\xb5\x78\x2b\x64\x96\xcc\xb8\xf8\x58\xd5\xac\xbe\x5c\x98\x2d\x55\xab\xb5\xd1\xe9\x57\xbb\x47\x49\xeb\x5a\x9e\x04\x05\xbb\xd2\xef\xf4\x06\xb4\x84\x16\xba\x39\xd9\x1d\xba\xed\x54\x98\xaf\x0e\x43\xc9\x89\x2a\x43\xf1\xea\x7b\xb9\x28\xab\xef\xb8\xae\x12\x2b\x99\xd1\xb0\xaa\x29\xb5\x35\x7b\x38\xb1\x67\x1b\xa6\x2a\xe4\x48\x03\x2b\x12\xba\x3e\x28\xaf\x64\x7b\xed\xcc\x5a\x13\x6d\x65\xbd\xf0\xaf\x1d\xa7\x2b\xa9\xb5\xfa\x80\x23\x29\x32\x8f\x66\x6a\xdd\xc5\x84\x01\x14\x6f\xbd\xba\xde\xdf\x08\x99\x0a\x85\x46\x98\x3b\xfd\x8f\x4f\x05\x2c\xfe\x54\x20\x6e\xe3\xc6\x0f\x12\xce\xd1\xea\x36\xa7\xa0\x64\x8c\x80\x2a\x85\x73\x0a\x20\x39\x1c\x97\x28\x95\x45\x39\x5c\x65\x24\x82\x83\xf2\x36\x34\xcb\x90\x23\x80\xcc\x02\x14\x95\x18\x20\x63\x04\x26\x03\x16\x10\xe7\xa6\x02\x1e\xe9\xec\x1c\x45\xa2\xd1\xd9\xc2\xee\xae\xbf\x41\x81\xb1\x2c\x7b\x66\x2a\xc4\x4d\x16\x98\x72\x8f\x2d\x74\xbb\xab\x36\x83\x95\x15\xf3\xa5\x64\xf5\xc9\x6c\x8b\x63\x6a\x70\x93\x1b\x56\xe9\xb6\x55\x32\x78\x87\x5e\xb5\x8b\x65\xed\x75\xf0\xda\x37\xdb\xef\x03\xbe\x4d\x74\xba\x0a\xf5\xc8\xa2\xf3\x85\xc4\xe4\x36\xaa\x63\x55\x0d\xae\x9e\x2f\x3e\x83\xa1\x28\x36\x27\x68\x6b\x59\x75\x87\xce\x9d\x0a\x47\xb1\xf9\xdd\xec\xad\xd5\x8e\x32\x5d\x99\xa5\xc7\x39\x98\x54\x3b\x85\xee\x0a\x9d\xd4\x71\xb5\xcc\x18\xf9\x62\x81\xd3\x50\xac\xde\x86\xcb\xe5\xbb\xf5\xfc\x32\x29\xcf\x9e\x8b\x4a\xed\xb5\x08\x5a\xe5\xdc\x8c\x60\xd0\x85\xac\xd7\x49\x81\x18\xd7\x4b\x6d\xf2\xed\x7d\xb9\x92\x94\x7a\xa6\xf5\x2a\xbc\xb8\x53\xad\x1a\x32\x15\x04\x3b\xcc\x9d\xfe\xff\x99\x0a\xf8\x6d\xdc\xf8\x81\x26\x14\x8e\x55\x29\x82\x86\x90\x66\x15\x4c\xc2\x19\x89\x92\x58\x4e\xc5\x09\xa0\x52\x04\x86\x49\x0c\x45\x6f\x67\x97\x0a\x54\x8c\x44\x09\xa0\xa0\x12\x85\x4b\x34\x41\x48\x28\x23\x41\x8e\x3b\x97\x2c\x60\x51\xce\x4e\xa2\x14\x4b\x45\xa2\xc2\xfe\xae\xb7\xd9\x44\x52\xdc\xb9\xbc\x19\x8f\x39\x13\xf0\xfa\xf0\x15\x13\x17\x94\x81\x4a\x2f\x4c\x8f\xd4\x37\xb5\x65\x67\x5d\x20\xba\xa6\x31\x7d\x5c\xe6\xf9\x9a\x93\xc5\xca\x78\x95\xc9\x30\xf4\xb0\x39\x6c\x09\xd6\x46\x18\x17\x3a\x1a\xdb\x5c\xe8\x12\x86\x2f\x7a\xac\x52\x9e\x0f\x41\x6f\x8e\x55\x94\x62\x03\x7f\x74\xde\x35\x3d\xef\x00\x6f\xe4\xdc\x99\xe0\x3a\x67\x69\xff\x0f\xef\x5e\xdb\x87\xeb\x15\x5f\x6f\x4c\xbd\xf6\x8f\x5c\xb7\x00\xeb\x85\xac\x26\x1b\xba\x5e\x5e\x15\x7a\x8d\x71\xcb\xca\xd4\xf4\x49\xde\x2e\xbd\xd4\xe6\x83\x97\xda\x33\x5b\x34\x64\xad\x80\xb6\x73\x99\x4e\x91\x9a\xe7\xeb\x85\x22\x41\xa0\xd9\xcd\xb8\x37\x7e\x2d\x71\x6d\xdd\xc6\x4b\x95\xda\x5c\xb4\x1b\x98\xd4\x20\xed\xb7\x77\xc3\x10\xdc\x99\x52\x0a\x99\x29\xb9\x52\x98\xb7\xfd\x8f\xcf\x94\x2b\x52\x09\xec\x36\x5e\xee\x56\x93\x23\xa8\xb7\xbb\x88\x71\x0c\xfa\x1d\xc5\xbe\xa3\x18\x82\xa2\x3f\xdc\xff\x22\xbd\x19\xc7\x69\x26\x7a\x26\x6c\xef\x6e\x21\x83\xc4\x39\x92\xa3\x19\x9c\x3b\x97\x17\x87\x7b\xba\x27\xd2\xcf\x1e\x94\xe8\xbf\x4c\xbf\xac\x91\x9b\xe7\x4d\xab\x9c\x61\x72\x7a\x8e\x2b\xe2\xe8\xfa\x35\xf3\x68\xa3\x63\xc7\x5e\x95\x56\xef\x58\x5f\x69\xf5\x06\x20\xf3\x02\xf2\x2e\x9c\x08\x21\x4e\x1c\xfe\xb7\x73\x62\x9e\xcf\x4c\x3f\x41\x91\x9b\xfe\x3d\x78\xce\x74\x79\xfb\x35\xc6\x83\xde\x49\x77\x63\x23\x8a\xd8\xa3\x2a\x49\xf0\x88\x19\x77\x81\x4c\xb0\x42\x04\x4b\x46\x86\x08\x56\x7e\x24\x23\x43\x06\x2b\x3a\x92\x91\xa1\x82\xa5\x13\xc9\xc8\xd0\xc1\x82\x8f\x64\x64\x98\x60\x65\x45\x32\x32\x6c\xb0\x62\x22\x19\x19\x2e\x58\x9a\x90\x8c\x0c\x86\x06\x2b\x2a\x12\xd2\xf9\x50\xbb\x90\x90\xce\x87\xa2\x84\x84\x74\x88\xe0\xf1\x7f\x42\x3a\x64\xb0\x6a\x21\x21\x1d\x2a\x78\x60\x9f\x90\x0e\x1d\xac\x33\x48\x48\x87\x09\x1e\xb1\x27\xa4\xc3\x06\x2b\x03\x12\xd2\xe1\x82\x67\xf0\x09\xe3\x20\x1a\x3c\x5c\x4f\x48\x27\x78\x6a\x9e\x94\x4e\xf0\x38\x3c\xa9\x5e\x81\x63\x68\x22\x21\x19\x32\x70\x5c\x9e\x90\x0c\x15\x38\x3f\x4d\x48\x86\x0e\x9c\xfa\xde\xe6\xad\x24\x37\xa9\x3b\x3d\xff\xdc\xd8\x13\xb2\x95\x3d\x5e\xc1\x6d\xc4\xcb\x39\x52\xaf\x27\x8e\x50\xfb\x18\xf9\x0f\x17\xec\x7e\x07\xe5\xef\x2f\x8e\x91\xaa\x50\xe0\x09\xf9\xa2\x5a\xc6\x3c\xd5\x31\xf8\x13\x72\x6d\x09\xc8\x1d\x6a\xc0\xa3\xad\xe7\xad\x54\x0e\x17\xe4\xbf\xd6\x8b\x6f\x3d\x7f\x65\x75\xb8\x40\xff\xb5\x5e\x1c\xeb\x9d\xae\x04\xf7\x17\xf8\x47\xeb\xa5\xd0\x7c\x6f\xbd\x14\x23\x90\xc0\x7a\x37\x7e\x44\x24\xd2\x7a\xbb\x05\xf0\xfe\xe2\xdf\xb8\x17\xcf\x7a\x27\xcb\xec\xfd\x05\xfd\xaf\xf5\xae\xb0\x9e\x9f\x5c\xec\x2f\x42\x66\xee\xbf\xd6\x8b\xb4\x9e\x9f\x0a\xed\x2f\xfe\x9d\xb9\x57\x58\x6f\x97\xb8\xed\x2f\xfe\x5d\xb1\xc4\xb2\xde\x69\x9a\xb9\xbf\x08\x59\xb1\xfc\x8b\xb9\x21\xd6\x3b\x49\x66\xf7\x17\xff\xfa\x5e\x2c\xeb\x1d\xe7\xde\xfb\xcf\xec\x51\x41\xb5\xba\xd0\x15\x68\x79\xba\x27\x7b\x30\xd5\xd5\xd1\x7b\x3c\x34\xed\x30\x5c\xae\xee\x4e\xf9\x00\xed\x35\x56\xf3\xf7\x08\xf6\x9f\xc9\xbb\x5a\x2d\x85\xe3\xdd\xdd\x6a\x17\xf6\x1b\x42\xde\x5c\x99\xe2\xfd\x2d\x57\xbd\x8b\x2f\xe9\x9e\x46\xe4\x1b\x70\x42\x4f\x49\xd8\xe8\x7d\xab\x8b\x84\xf0\x00\xa1\xa8\x6d\xbd\x8b\x84\x88\xc0\x5e\x41\x62\x42\x64\x70\xd3\x21\x29\x21\x2a\x90\x7f\x27\x96\x88\x0e\x26\xf2\x49\x09\x31\x81\x9c\x36\xb1\x44\x6c\x30\x39\x4e\x4a\xe8\x43\x9e\x98\x94\xd0\xe9\xb9\x49\x1a\x47\x3a\x3d\x39\xa1\xd3\x50\xc2\x83\x79\x5c\x62\x4a\xc1\x9c\x26\xb9\x4c\x64\x30\x3b\x4a\x4c\x89\x0a\x64\x0a\xc9\x65\xa2\x83\x39\x47\x62\x4a\x4c\x60\xfd\x9d\x5c\x26\x36\xb8\x92\x4f\x4c\x89\x0b\xae\x6a\x13\xc7\x4a\x34\x40\x29\xb1\x76\xa7\xa7\x29\x69\xec\x74\x7a\x9e\x92\xc6\x4e\x27\x27\x2a\x6c\xf4\x19\xc6\x65\x42\x64\x60\x2d\x97\x98\x50\x60\x79\x93\x5c\x22\xfa\x94\x50\xf4\xb9\xca\xb5\xef\x5e\xbd\xc5\xc9\xca\xa5\x17\xd5\x5d\x73\xb6\x12\xf9\xa6\xd5\x1b\xac\x44\x8e\xdf\xfe\x85\xa3\x0c\x45\x12\x04\xa5\xa8\x2c\xc7\x41\x85\xe2\x14\x20\x73\x12\x41\xc9\x2c\x07\x30\x05\xd2\x28\x60\x50\x8a\x94\x51\x94\x56\x24\x92\x95\x21\x86\x2b\x32\x85\xb2\x18\xa0\x25\x49\xa6\xd4\x87\x27\xc4\x7b\x9c\x3f\x79\x8e\x71\x54\xa9\xc7\xed\x2a\x94\xa2\x1f\x8a\xe3\xce\xd4\x83\xef\xee\x9e\xac\x83\xbc\xd2\xa6\x02\x65\xbc\x38\x5d\x45\x1f\xd4\xba\xca\xf0\xcd\xe9\x9b\xed\x62\xc6\x91\xe4\x01\x3a\xcf\xce\x55\x39\x53\x2a\x0b\xe3\x9e\x3e\x5b\xe6\x4b\x13\xb7\x2a\x6f\xe8\x76\x72\x4b\xdf\x8a\x81\xca\x9b\xcc\xe1\xa3\xe0\xfe\x6b\xbd\x89\x74\x05\xd6\xc0\xf8\x75\x5d\x05\x9d\x3a\x47\x67\xde\x55\x9b\x83\xa8\x6c\x58\xe2\xb0\xff\x9e\xe9\xbd\x4c\xf3\x46\x99\x99\x2e\xa7\x47\x95\xdf\xfb\xd2\x23\xff\xaf\xc7\x76\xb4\xbc\xe1\x92\xa7\xba\x8a\xd0\x6f\x4f\x98\x69\x6d\xa6\xcf\xf8\xf9\x70\x33\x95\x48\x1a\x57\xf2\x15\xfa\xb1\xd3\x54\x97\xcc\x54\xc7\x71\xbc\x97\x63\x16\x46\x3f\xe3\x90\xef\x26\xfa\xd2\x6e\xd5\x9d\x0c\x91\x2b\x6c\x26\xaf\x2a\xef\xf4\x71\xca\xca\xbf\xc8\x32\x33\x50\xfa\xe2\x62\xd2\x90\x5a\x62\x8e\x5f\xfd\xf1\xc7\xc3\x71\x99\xd7\x71\x2d\x78\x23\x4c\x37\xfe\xd0\xfe\x50\x9b\x98\x73\x1b\x1d\xa9\x21\xcd\xc7\x73\xac\x8b\x2b\x63\xaa\x8b\xcd\xdf\x30\x38\xab\xca\x05\xcc\x59\xbf\xb6\x06\xe5\x21\xb7\x12\xc6\x46\x2b\x03\xe0\x5e\x37\x9e\x2f\xb1\x62\x56\x3d\xd8\xb6\x10\x5e\xdc\x24\x44\x55\x3d\x65\x6e\xcc\x3f\x38\xb6\xf1\xf8\xbb\x1f\xab\x01\xf9\xb3\x0b\x83\x30\x1c\x92\x7a\xcb\xd6\x85\xb5\xd9\x78\x26\x8c\xa2\xf8\xf8\x8e\x31\xcd\x8d\x66\x63\x33\xb5\x9a\x1f\xcc\x1b\xbd\xb1\xb5\x68\x3d\xb6\x3d\x52\x6d\x79\x8a\x92\xee\xc7\xf1\x5e\x9e\x8f\x7f\x91\x55\x6c\x42\x40\xfe\xab\xf9\x0f\x41\x96\x4c\xc1\xbf\x1a\xe0\x9f\x59\x80\xac\xd4\xed\x0f\xf1\xdc\xac\xdf\x03\x56\x97\xee\xac\x57\x52\x8f\x28\x88\x2f\x63\x53\x27\xf8\x56\x76\x52\xca\x9b\x94\xb4\x6e\x95\x7a\x5e\xd5\xf7\xeb\x0a\x7d\x61\x0f\xfc\xe5\x94\xfa\x5f\xcd\x5f\x79\xef\xe5\x13\xf2\x3f\x9a\x4b\x63\x3e\xc4\x17\x92\xd8\xa2\x66\x1c\xe8\x0d\x3e\xdb\x16\xaf\x2b\x54\x14\x92\xf1\xf7\x6c\xf1\xf7\xbd\x82\x96\xbb\xa5\xe0\xbe\xa7\x79\x57\x43\x1b\xe7\xdf\x2d\xc4\xba\x50\x72\x79\x9d\x71\x84\x85\x8a\x2a\xa1\x04\xc9\xa1\x2a\xa6\x02\x00\x59\x06\xdf\x2e\xc4\x30\x9c\x96\x14\x86\x41\x81\xca\x42\x46\xdd\x02\x9f\xcc\x42\x94\x66\x09\x19\x02\x8a\x02\x2c\x00\x04\x05\x68\x09\xd0\x28\xf0\xb0\x30\xd5\xfb\xdd\xf6\x58\x48\x1f\xea\xd2\x23\xd1\x8e\xc2\xf1\xe8\x47\x66\x77\x77\x4f\x32\xf0\xb4\x58\x18\x0c\x12\x77\xc7\x42\xb1\x5d\x65\x5f\x5a\xfd\xbe\x64\x95\xc9\x4c\x66\xb9\x79\xa6\x37\x6c\x63\xeb\xce\xcc\x82\x2a\xc2\x2e\x39\x54\x5f\x81\xaa\x15\xf5\xbe\x02\x4d\xa5\x5d\xb1\xfb\xd8\xb2\x26\x35\xc6\xc5\x5c\x79\x95\x6f\x35\x30\xa9\xeb\xe4\x6a\xcd\xb7\x9c\x35\x79\xe1\x66\xaf\x4d\x48\x16\xc7\x5a\x33\xd3\xf8\x67\x60\x61\x51\xc6\x26\xa9\xb1\xe8\x76\xfc\x23\x00\x20\x36\x16\xfe\x44\x2c\x4a\x8d\x85\x6a\x7f\xcc\xfe\x4c\x2c\x0c\x60\x51\xe8\x23\xab\xf7\x8c\xff\x7d\x8c\xcc\x24\xe4\x1f\x8a\x85\x3f\x09\x8b\x6e\x62\x8b\xd7\x15\x5a\x19\x27\xe3\xef\x63\xe1\xbd\x82\xd6\x67\x62\xa1\xcc\x51\x0c\xc7\x92\xb4\x42\x60\x34\x05\x59\x95\xc4\x19\x0c\xc7\x71\x19\x00\x52\x86\x18\xaa\x90\x12\xc0\x70\x92\x44\x31\x0c\xb0\x38\x4a\x2a\x32\xcd\x4a\x2c\x86\xaa\x28\x45\xb1\x24\xaa\xfa\x58\x48\xdc\x08\x0b\xb1\xcb\x58\x48\x30\x67\x5e\xa5\xe2\xdf\x3d\xd9\xfb\x4d\x8b\x85\xc1\x07\x9f\xee\x8e\x85\xef\x32\xb1\x7e\x5c\xda\x0e\x56\xd0\x5f\xfa\xcf\x8b\x75\x73\xb0\xea\x3a\x6d\x96\x61\x36\x25\xad\x28\x68\xc3\xc6\x86\x1f\x0f\x0a\x8f\xf5\x47\xd2\xd4\xdf\x84\x2a\x3d\x79\x7e\xe4\x44\x71\x6c\x38\x8b\x56\x3f\xdb\x95\x58\x45\x95\x0a\x40\xcf\xe4\x1a\x5d\xe1\xf9\xcd\x9a\x77\x4a\xfa\x40\xcb\xfc\x43\xf2\xc2\x3c\x07\xf9\xd4\x58\x74\x3b\xfe\x11\x0f\xb5\x7d\x0a\x16\xa6\xc4\xa2\xd4\x58\x38\xeb\x3c\xf3\x3f\x13\x0b\x03\x58\x14\xf1\x64\xd6\xfd\xe2\x7f\x93\x1c\x72\x09\xf9\xdf\x03\x0b\x93\x62\xd1\x4d\x6c\x11\xc8\xd1\x13\x60\xe1\xbd\x82\xd6\x67\x62\xa1\x4a\xa3\x92\xca\x30\x34\xa6\x50\x24\xc5\xa9\x18\xca\x32\x38\x8d\xcb\x80\x64\x48\x96\x96\x39\x14\x63\x51\x56\xc1\x09\x8e\x64\x69\x94\xa3\x65\x0e\xa7\x48\x0c\xaa\x80\x24\x29\x59\x26\x55\xc8\x3d\x3c\x21\xb4\xbf\x47\x9a\xb4\x8a\xe5\x68\x8f\x94\xbc\x84\x85\x24\x41\xb2\xe7\x5e\xa5\x44\xba\x2f\x1d\x3b\x39\x75\xf4\x7c\xb6\x4c\xbf\x42\x8d\x78\x9d\x1b\x25\xb6\x5d\x98\xe5\x9e\xe1\x58\x26\x98\x7a\xdf\x29\x96\xcb\xef\xbd\x2e\xbb\xea\x6a\xc3\x0c\xc8\x2e\xa8\x0a\xe5\x3a\xf6\x11\x16\x66\x03\x83\xff\x01\x0b\xaf\x8d\xc7\xde\x5f\x00\x0b\xc1\x0e\x2b\x33\xfc\xe3\x6c\xc9\x88\x25\x81\xd8\x58\xa5\xfe\xac\x5b\xef\xaf\x75\xcc\x1c\xe4\x09\x76\x5d\xb5\xdf\xa6\x00\x90\xf8\xd4\xb4\x1a\x8d\x15\xdf\x98\xf1\x4a\x81\x2d\x65\x4b\xa4\xf3\x38\xac\xf4\x49\x13\xce\x68\x99\x1f\xe6\x0b\x83\x35\x43\xa8\xc3\x4d\xbf\x9c\x29\x5a\x8b\x2e\xda\x5c\x8a\x85\x2c\x7f\x43\x2c\x3c\x5a\x42\x5f\xbb\x0e\xe8\x10\x2f\x62\xed\x60\xdb\x4c\xf8\xa4\xbb\x80\x45\xb7\xe3\x1f\x1c\xdb\x78\xfc\xdd\x8f\xb7\xde\x17\x0b\x7d\xc3\xdb\xa5\xf8\x97\x86\xbf\xb9\x68\xb5\x52\xf0\xff\x47\xec\x11\xa7\xe1\x2f\xaa\x85\x55\x42\xfe\xa1\x58\x98\x4f\x67\x0b\x5c\x3e\xd0\x8b\xf0\xbf\xfb\xd9\x22\x30\x16\xd7\xf0\xf7\xb1\xf0\x5e\x41\xeb\x33\xb1\x90\x83\x14\x4d\x50\x38\x86\x11\x34\xcd\xa9\x38\x4b\x2b\x24\x47\xa1\x90\xa2\x14\x54\xe1\x18\x94\x56\x15\x12\x03\xa8\x44\x00\x54\x62\x48\x85\x82\x14\x86\xd3\xac\xa4\xa0\x38\xc7\x42\x06\x92\x8c\x87\x85\xb7\xd9\x23\xa5\x38\xf6\x32\x16\x32\x44\xf4\xdb\xa5\x76\x77\x4f\xca\x5d\xd2\xe6\x85\xc1\x33\xad\xbb\xe7\x85\x79\x08\x33\x65\x28\xab\x06\xb5\x44\x69\x4c\xd9\x10\x0d\x55\xca\xb3\xef\xe3\x1a\x3d\x16\x3a\x4d\x56\x9b\x29\xd3\xb2\x36\x26\x71\x11\x1d\xcc\xc8\x21\x49\x30\x65\xf3\x95\xac\xa2\x95\x9e\x9a\xd3\xa4\xc9\xb2\xac\xd0\x8f\x4b\xa3\x5f\xa5\x2c\x21\x5f\xe9\x56\xcd\x41\xde\x7a\xa6\xf8\x3b\x61\xe1\xb5\xeb\x80\xb2\x34\x9d\xbe\x1d\x6c\x9b\x0f\x9f\x74\xf1\xb1\x30\x25\xff\x64\xe7\x95\xee\xc7\xd4\x58\x90\x22\x16\xf3\x77\x88\x7f\x89\xf2\xc2\x1b\x62\x71\xa2\x5c\xe8\x27\x9d\xd1\x5d\xc2\xc2\x24\xb2\x34\xaa\x07\x7a\x9f\xbe\x2e\x4a\xb1\x2e\xf3\xb1\xf0\x5e\x41\xeb\x53\xf3\x42\x94\xa4\x31\x06\xe0\xb4\x4c\xe2\x18\xae\x62\x14\x60\x08\x8a\x61\x55\x8a\x83\x80\xe3\x30\x82\x42\x51\x55\x96\x48\x16\x63\x55\x16\x67\x65\x8c\xc1\x38\x54\xc5\x48\x8a\x04\x28\x89\xb1\xb4\xfc\xf0\x84\x50\xb7\xab\x9d\xb9\x98\x17\x52\x2c\x46\x46\xe7\x85\xbb\xbb\x27\x65\x96\x69\xb1\xf0\x62\x5e\x78\x6b\x2c\x2c\x50\xc5\x6c\xae\x8c\x9b\xea\x33\xc3\xd4\x4d\x55\x1d\x2f\xa9\x09\x98\x31\x0d\x74\xb3\x51\x17\x52\xa7\x52\x11\x39\xfb\x7d\x4e\xe8\x2f\x83\x0a\x37\x68\xd3\xa8\x59\xb1\x17\xa5\x2c\x39\x68\xad\xd6\xfc\xa6\xbb\xb4\x3b\xc5\x4d\x83\xd0\x5e\x48\x56\x68\x3c\x12\xdd\xd6\xf3\xa2\xa4\x69\xfc\xf8\x86\x58\x78\xd4\xf5\x5a\x2c\xaa\x51\x56\x29\x77\xb0\x6d\xb2\xbc\xf0\x76\xfc\xd3\xe6\x85\x47\x0d\xaf\xc5\x22\x9e\x99\xdb\xf3\xb4\xb9\x40\x9a\x5c\x24\x33\x2d\xbf\xa5\xe0\x9f\x3a\xfe\x33\x73\x7b\x7c\x14\xff\x13\xad\x05\xd2\xf0\xc7\xcc\x9a\x9c\x90\x7f\x28\x16\x0a\xe9\x6c\x71\x4b\x5f\x48\xc2\x7f\x9a\x2e\x2f\xbc\x57\xd0\xfa\x4c\x2c\x94\x08\x4c\x91\x21\x89\x73\x14\xa0\xa0\x8a\x42\x56\xc5\x38\x55\x62\x09\x16\xa3\xa1\xc2\xb2\xa8\x42\x31\x04\xa4\x00\xbe\xcd\x1a\x59\x4a\x82\x94\x2c\xd3\x28\x0e\x38\x54\xe5\x70\x0a\x95\x29\x0f\x0b\x6f\x95\x17\x52\x97\xb1\xf0\xcc\x0b\xb6\xd9\xc3\xeb\xb5\xfd\xd2\xfe\xb4\x38\x98\x0b\x0c\xfc\xdd\x71\x70\xfc\xde\xc8\x13\xec\xf4\x7d\x0c\x8b\x65\x95\x1c\x10\xd6\xb0\x3c\xe8\x3b\x0b\xcb\xe8\x10\x3a\x5e\xe9\x6f\x36\x8b\x52\x2b\xaf\x94\xe9\xe7\x1c\x65\xc3\xb6\xf5\x5a\xeb\x17\x3b\x8f\x73\x72\xaa\x95\xba\xb0\xd7\x11\x9d\xe2\x9a\x81\x26\x51\x6d\xe5\xb0\x55\xa9\xbf\x28\xbf\xb6\xd1\x26\xbc\x69\x4e\x98\x02\x87\x44\xd0\xd6\x53\xe3\xd0\xed\xf8\x07\xc7\x36\x1e\x7f\xf7\x63\xea\x3d\xb1\x94\x38\x94\x1a\x07\x8b\x13\x63\xf1\x33\x71\x30\x80\x43\xd5\x94\xfa\x5f\xcd\x7f\x69\xad\x06\x09\xf9\xdf\x3c\x27\x4c\x81\x43\x37\xb1\x05\x33\xb7\x5f\x3b\xc9\xf8\xfb\x38\x78\xaf\xa0\xf5\xa9\x38\x88\x2a\x12\x8a\xab\x24\x4b\xd3\x34\x85\xe2\x2a\x23\x49\x38\xce\xa0\x24\x07\x49\x56\x65\x58\x94\x22\x58\x54\x45\x19\x00\x21\x0d\x19\x94\x94\x68\x80\xe1\x12\x4e\x29\x24\x2b\x33\x12\xc5\x61\x1e\x0e\xde\xa6\x6e\x86\xe2\xe8\x8b\x38\xc8\x61\xf8\x99\x1f\xa2\xf0\xef\x9e\x3c\x52\x96\x16\x0b\x83\x8e\x71\x77\x2c\xcc\xbc\x55\x3b\x44\xef\xa5\x4d\x2f\x2c\x9c\x63\xac\xe5\xeb\x62\x96\x7d\xdb\xcc\xba\x30\x8b\x49\x62\x79\xd3\x90\xb2\xb3\xb7\x0d\x50\x1e\x8d\xc5\xe3\x9a\x5d\x30\x05\x67\x90\x53\x69\xe3\x11\xd4\x9f\xed\x4a\x59\x73\x06\x83\x82\x3e\xcb\x75\x96\x66\x7b\xac\x94\x36\x8b\xea\x5b\x4b\x97\x07\x37\x7d\x9e\x22\x05\x16\x55\x68\xb6\x90\x1a\x8b\x6e\xc7\x3f\x82\xd1\xa7\x60\x61\x4a\x2c\x4a\x8d\x85\xa2\x5a\xd8\xfc\x4c\x2c\x0c\x60\x51\x04\xa3\xfb\xc5\x7f\x73\xd1\xea\x24\xe4\x7f\x0f\x2c\x4c\x8a\x45\x37\xb1\x05\x33\xb7\x27\xab\x64\xfc\x7d\x2c\xbc\x57\xd0\xfa\x4c\x2c\x24\x15\x0c\xb2\x9c\xa4\x70\x2c\x41\xc9\x40\x81\x0a\x86\xa1\x40\x01\x04\x90\x21\x45\x4b\x0a\x06\x38\x8c\x93\x58\x48\x11\x90\x90\x24\x92\x62\x01\x94\x28\x8c\x20\x50\x94\x66\x71\x9a\x93\x69\x0f\x0b\xc9\x1b\x61\x21\x73\x19\x0b\x29\x9c\x3b\x83\x85\x14\xf1\x10\x78\x92\x39\x2d\x14\x06\x8f\xb3\xee\x0e\x85\xe5\x9c\x6e\x1a\x2f\xab\x3e\x59\x65\x20\x85\x67\x14\x67\x08\x94\xd2\x1b\xd6\xca\x32\xca\xcb\x9a\x7f\x7d\xc9\x69\xfd\xf7\x2a\x5f\xa6\x37\x76\x65\x80\x77\xcb\x85\xee\xb2\xdf\xb3\x9f\x9b\xbd\xf9\x70\xa0\xf5\x4b\xd3\x5c\x0d\x15\xb2\x9b\xb2\x5a\x32\x96\x8f\xd8\x86\xb4\x9d\xc6\xc6\x1c\xe6\xfe\x21\x50\x58\x96\xa6\xb3\xd4\x50\x74\x3b\xfe\xc9\x8e\x2a\xdd\x8f\xa9\xa1\x30\x25\x14\xa5\x86\xc2\x94\xa5\x1a\xa9\xc3\x7f\x00\x8a\x12\x1d\x8f\xfd\xa4\xe3\xb9\x7b\x40\x61\x52\x28\xba\x89\x2d\x02\x5b\xd5\x09\xa0\xf0\x5e\x41\xeb\x53\x1f\x2d\xc4\x18\x16\xe2\x34\x2e\xb1\x12\x0e\x80\x4c\xd3\x80\xa1\x54\x9a\x83\x0c\x2a\x43\x42\x96\x18\x55\x51\x51\x0c\xd0\x28\x8d\x92\x04\x41\x13\xb4\xcc\x48\x24\x20\x00\xc6\xb0\x38\x41\x93\xb8\xff\x43\x82\xb7\x2a\x21\x25\x2e\x41\x21\xc3\xb2\x67\x7e\x99\x76\x77\xf7\xe4\x0d\x1a\x69\x4b\x48\x83\xc7\x59\x77\x2f\x21\xe5\xde\x74\xd9\x7a\x24\x20\x28\x82\xc1\x9b\x99\xb3\xcd\xa5\x51\x92\x34\x41\xd4\x07\x84\x03\x39\xe5\xcd\xca\x0e\x9c\x82\xa4\xb5\x31\x22\xdb\x9b\x3c\x4b\x8f\xf2\xfc\x31\xdb\x81\xdc\xf3\xf3\x1a\x15\x73\x6b\xad\xf3\x6c\x3a\x03\xb4\x31\x1b\x3c\xbf\x53\x64\x29\xcf\xbc\xe6\xd1\x22\x93\xbd\xe5\xa3\x85\x47\x8d\xae\x5d\x07\x34\x86\xd9\x37\xfd\x60\xdb\x88\xbf\x38\x58\x74\x13\xfe\xc9\x8e\x2a\xdd\x8f\x55\xfe\x34\xad\x4d\xb2\x45\xa8\xa5\xc5\xc2\x9f\x78\x3c\x95\xf6\xa8\xf4\x26\x5b\xc4\x3f\xe9\xa8\x36\x14\x0b\x73\xe9\x6c\xe1\xff\xee\x5b\xc4\x13\x8e\xf7\xb5\x45\x70\x2c\xae\xe1\xef\x63\xe1\xbd\x82\xd6\x67\x62\x21\x80\x12\x4e\x63\x04\xaa\x60\x0c\x46\xc9\x14\xe4\x24\x54\x66\x29\x05\x92\xb4\x42\x52\x24\x8e\xa2\x32\x94\x71\x9a\xc2\x08\xc8\xca\x10\xa5\x81\x84\x52\x34\xce\xa2\x34\x27\x41\x80\x32\x1c\xe1\xfd\x2c\xf6\xad\xca\x66\x2e\x62\x21\x47\xd1\x67\xca\x66\x76\x77\x4f\xde\xdc\x94\x36\x2f\xbc\x88\x85\xb7\xce\x0b\x5f\x30\xbe\x6d\x18\x84\x22\x14\xb9\x47\xe6\xf9\xb9\xf6\x6a\x96\x8a\x4e\x2f\x9b\xb3\x2b\xcf\x68\xb5\xd3\x98\x49\xaf\x9d\x56\x23\x8b\x3f\x96\x88\x76\x57\x98\x71\xf2\xe4\xcd\x32\xdf\xd6\x54\xa1\x40\x6f\x5e\x45\xb6\x24\xce\x88\xd2\x90\x79\x2e\xb6\x78\x54\x50\x9b\x19\x7c\x3d\xe4\xba\xd5\xec\x0d\xcb\x66\xf8\x14\x8f\xf6\xd5\x28\xeb\x25\x2d\x16\xde\x90\x7f\x5a\x2c\x3c\x3a\xee\x4c\x12\x8b\xfd\xb5\x51\xf2\xf8\xf7\x13\xe3\x6f\xea\xb5\xc0\x2d\x4a\x45\x7e\xd2\x5a\x24\x14\x0b\xb3\xe9\x6c\x71\x4b\x5f\x48\x3b\x16\xd7\xf0\xf7\xb1\xf0\x5e\x41\xeb\x33\xb1\x10\x27\x18\x12\x6e\x81\x88\x93\x38\xa8\x32\x8a\x04\x38\x40\x29\x12\x41\x10\x9c\xc4\xb0\xaa\x02\x58\x95\x20\x19\x86\x91\x30\xa0\x12\x84\x04\x48\x9a\x05\x0a\x25\xa3\x8a\xca\x6d\xe1\x52\xf1\x7e\xcb\x12\x4b\xf3\xda\x5d\xef\xf5\xd6\xe7\x20\x90\x44\x69\x94\x88\xac\x97\x71\xef\x1e\x7e\x6f\xd5\x7b\x53\xa0\x8f\x80\x15\xb6\xd8\x58\x36\xa6\x52\x19\x2f\xf2\x44\xaf\xfb\xda\xb4\xca\xf3\xd7\x3e\x8a\xaa\x05\xd6\xae\x94\x98\x39\x2a\x34\x57\x2f\xbd\x67\xbe\x4f\xf0\x7b\x04\xf4\xdc\x29\x30\xe4\x1f\xa2\xe6\xb5\x08\x58\xa3\xac\xf2\x31\xbd\xee\x72\x95\xe7\xb6\xb7\x84\x6c\xee\xfd\x6d\x39\x6d\x64\x1a\x86\xc8\xbf\x68\x6a\xbd\xd9\xcf\x19\x95\xc9\xd2\xd9\xc8\x6d\x62\x96\xaf\x67\x1b\x14\x36\x9e\x2a\x76\xbe\x08\x32\x62\x6f\x85\x52\xad\xe7\xee\xa4\x87\xf6\xc7\x53\x0b\xcd\x66\xea\x02\x29\x82\x7c\x17\x2f\xcf\x65\x9b\x18\xae\x2a\x73\x4d\x22\xdb\x4d\xab\x5a\x89\x81\x7c\x27\x2e\x7d\x8a\x7c\x47\x3a\x7b\x3f\x61\xcc\x07\x66\xbb\xf6\x9c\x41\x2b\xe8\x4b\x61\xe3\x4c\x56\x22\x36\x1b\xa0\x60\x63\x1a\x18\x27\x16\xd7\xcb\x4a\x76\x53\xa3\x9c\x8c\x20\x67\x3d\x1d\x89\xb1\x63\xd5\xf4\xc1\xb3\xff\x50\xb9\xfb\x97\xa8\x60\x30\x05\x7f\xd1\xda\xb4\x3b\x29\xf8\xf3\xfc\xcf\x43\xbe\xd0\xc8\x9b\x49\x6e\x8b\x9a\x3e\x3c\xab\xe6\x25\x5b\xa4\x1d\x8b\xad\x2f\x3c\xca\x01\x7a\x57\xd9\xe2\xef\x31\x4b\x5b\x94\xc0\x77\xca\xb9\x46\x76\xa0\xbf\xa3\xdd\x15\x9d\x25\x25\x46\xd6\x05\x8e\x6a\xb6\x57\xd3\x9a\x32\x78\x29\x4a\x99\x26\x3e\x6e\x77\x6d\xb1\xd6\x59\x62\x83\xae\x93\x27\x5f\xca\x1c\x3f\x6e\xaf\x6b\xb9\xde\xa4\xab\x68\xa6\x5e\x11\x71\x39\x4b\x19\xf3\x47\x01\x05\xef\xd9\x4f\xde\x91\xc3\xa0\xc2\xe2\x1c\x8d\xa9\x12\x8a\x11\x0a\xc1\xa9\x1c\x0d\x00\x03\x49\x9c\x95\x49\x8c\x21\x65\x00\x48\x40\x01\x92\x50\x24\x99\xa6\x18\x8c\x00\x04\xa3\x90\xb4\xc2\xd1\x10\x52\x32\x81\x91\x87\x5f\xae\x4e\x11\x79\xf1\xcb\x91\x37\xfa\x48\x6a\x77\xf3\xf8\x7d\xa8\x69\xe3\xee\x99\x82\x7d\xef\x2f\xc1\xea\x37\x2a\xee\x2e\x8a\x13\xa2\xc1\x0c\x4d\x69\x31\x5b\x3d\xae\xdf\x4d\x46\x84\xd5\xba\xa2\x0e\x04\x4b\x7c\x7f\xa9\x59\xcb\x86\xc6\x16\x6a\x53\x91\xe9\x8d\xd5\x55\xab\x3e\x7e\x2f\xca\x75\xe1\x59\x78\xb6\xd9\x6c\xe5\x99\x6f\x58\xaf\x19\x67\x85\xd2\x0c\xe8\x0c\xf9\xa5\x01\xba\x2a\x86\x1b\xd9\x46\xe6\x9f\x15\x77\xd3\xc6\xbd\xb4\x73\xbd\xba\xaa\xcc\xed\x1b\xc6\xdd\xcf\x5c\x65\x5e\x5c\xf1\x7e\x62\xdc\xe3\x6f\x14\x77\x93\x62\xb0\x1f\x77\xad\x09\xa9\xa0\x35\x1c\xf4\x18\x53\xae\xdb\x32\x0d\xdf\xfb\xaf\x39\xa2\x8f\x67\xca\xef\xf2\xa6\xfd\xc6\xa0\xa5\x65\xe6\xd5\xcc\x41\xcc\x28\xb2\xc2\x2b\x59\x5d\x13\xb9\x75\x7d\x5d\x67\xea\xbc\xf6\xbc\x12\xca\xe4\x4a\x92\xc5\xda\x02\x9f\x15\x1a\x15\xba\x30\xeb\x73\xca\x1b\x3f\xe5\x6f\xb2\xfb\x73\xfa\x0e\x66\xef\x87\x48\x6c\x07\x38\xf6\xf1\xe7\x91\x39\x85\x9b\xdd\xbb\x8c\xb3\x35\xb1\xd5\x6e\xf2\x25\xf1\xd2\x6b\x97\xf9\x4a\x5b\x68\xfa\xaf\x3e\xae\x89\x95\xc1\x31\xc5\x5f\x10\x04\x41\xf8\x5c\xee\x88\xda\x07\x86\x48\xbd\x59\xaa\xf2\xcd\x01\x52\x16\x06\xc8\x57\x4d\xf9\x20\xed\xd8\xb0\xcc\xd1\x5c\x1b\xef\x7e\x9b\x23\x70\x7d\x23\xa9\x03\x54\xc3\x24\x0f\x63\x7c\x51\xfa\x1d\xca\xb9\x6a\xdb\x81\x4b\xef\x7f\x23\xd9\x50\xe0\xe8\xf0\xeb\x30\xfe\x47\xcd\xb6\x17\xd0\x1a\xdd\x44\xbb\x53\xb6\x61\xca\x25\x12\x0c\xe9\x88\xa5\x46\x47\x40\xbe\x1e\x9a\x3f\x21\x87\xf6\xbb\xcf\x5e\x87\x2b\x4d\x73\x9b\x61\xbd\x5a\xf1\xab\x06\x35\xe2\x57\x66\x2f\xfc\x92\xeb\x6d\x35\x0b\x67\x72\x4e\xd3\x33\x62\xc5\xd6\x3c\xf2\x4d\xf0\x17\xdf\xb5\x7e\x5b\xed\xa3\xd8\x9c\xd3\xff\xac\x68\x17\x2d\xe0\xb9\xb4\xb4\x71\xbd\x7d\xa7\x48\x49\xcc\x09\xfd\x0b\x3a\x64\x9b\x02\xdf\x16\xbc\xa6\xa7\x54\x90\x9a\x18\x9c\x0c\x9d\x56\x49\x2c\x20\x92\x63\x41\x78\x3c\xbb\xa2\xa5\xf1\xe6\x58\x7a\x79\x3c\x3a\xf1\x24\x8a\x98\xd7\xd2\x66\xe4\xff\xa0\x51\x62\x71\x0e\x24\x8e\x25\x39\xc9\x14\x4e\xe5\xf1\x1a\x3f\x21\xfe\x87\x91\x0d\xdf\x16\x50\x97\x3f\x1a\x4c\xda\x8c\x26\xc0\x9e\xa4\x91\x6c\xdb\x3f\x9e\x58\xc7\x9e\xb6\xed\x15\x26\xcd\x0c\x2a\xe3\x14\x03\xb7\xa7\x10\x4f\x22\xaf\xed\xde\x3c\x4f\x08\x30\xcd\x99\x26\x7b\xe1\xc0\xb0\x94\x88\x30\x3d\x82\x5b\xdf\x70\xef\x27\x90\xd4\x47\x09\x4f\xe0\x00\xb9\x63\xb1\xa1\xaa\x42\x39\xe8\x6a\x1f\xa3\x96\xa6\x3c\x21\x5f\xdc\xce\x5f\xa2\x84\xd5\x94\x1b\x89\xa9\x29\xb1\x05\xdc\xb9\xde\x56\xbc\x04\x42\x1b\xe6\xc8\xbc\x95\xdc\x3e\xad\x63\xd1\x23\xa0\x2a\x91\x26\xe1\x0a\x38\xeb\xdb\x29\xe0\xd3\x8a\xf0\xe9\x84\x2a\x1c\x53\x08\x53\xc2\x30\xb7\x5e\x39\x31\x12\xe9\xe0\x0b\x7f\xa0\x91\xd4\xf8\xe7\x0d\x6d\xfb\xb3\xdd\x0d\xd5\xe9\x6d\x7d\x4a\xee\x58\x64\xef\xfb\x80\x8c\xe1\x12\x1d\xdb\xf5\x56\x62\x7d\xa0\x19\x2f\xbc\x85\x09\xe8\x78\x43\xe2\xa4\x19\xd6\x03\x8d\xe4\x2e\x79\xc9\xfd\x1c\x4b\xd9\x32\x91\x80\x0d\x53\xe3\x67\x18\xb1\x80\xe4\x0a\x0c\xc8\x79\xdc\xf6\xa2\x80\x86\xaa\xa6\x00\xad\x8f\xa4\x62\x09\xe7\xb6\x3c\x27\x9a\x2b\x3b\xb4\x6e\x66\xbe\x00\xbd\x4b\x42\x06\x9a\xc7\x91\xf4\x36\x76\x3c\xa1\x16\x57\xca\x8b\xd6\xbc\x8d\x6c\xb1\x64\x3a\x2f\xcb\x4e\xe2\x99\x61\x4c\x17\x66\x3a\x89\x4e\x69\xc5\x1e\x51\x6f\xbd\x1b\x21\x9f\x09\x34\x6b\xe4\x68\x73\x78\x13\x09\x83\xd4\xe2\xcd\x5b\x5f\xc0\x27\x24\x28\xf2\x13\xe2\x87\x78\x79\x66\xd8\x50\x19\x01\x27\x42\x89\x1b\xc4\x6d\x9f\xce\x25\x89\xaf\x5c\x1d\x6d\xa9\xde\xcc\xba\x57\x18\xf6\xa2\xdd\x34\x5d\x81\xeb\x51\x60\xc9\x61\x8f\x0c\x7d\x04\x14\xc5\x82\xb6\x9d\xd6\xa0\x17\x19\x9c\xe4\x69\xfe\xed\x40\x66\xe4\x35\xbc\x42\xf6\xf4\x7e\x70\x8e\xf6\x65\x89\x43\x66\xd9\x29\x41\x7f\x15\xbe\xa5\xe7\x6c\xcc\xe4\x39\xf8\x59\xaa\x17\x97\xfd\xdb\x46\x17\x04\xf5\xd7\x50\x5b\x92\x7b\x27\xba\x91\xb4\x61\xa4\x2f\x2e\xdf\xe2\x7a\xf2\x11\xf1\x5b\x3b\xc3\x09\xe9\x24\xeb\xcd\x68\x72\x73\xd3\xb0\xb6\x81\x6f\x09\x2d\x5b\x33\xf4\xdb\x1b\x3a\xc8\xe1\xb2\xf8\x81\x0e\xf1\x95\xf1\x43\x4f\xc2\x9d\x8a\x78\xf6\x3f\xe2\x71\x51\x93\xa3\xb6\xf1\x95\x30\x2d\xb8\xd4\x8c\x85\xfd\x29\xda\x84\x31\xbb\xa8\x56\x58\xa7\xf8\xfa\xed\x36\x51\xee\xa6\xd3\x8e\xc1\x45\x3d\x22\x77\xbb\x4e\x49\x1f\x7e\xe0\xfc\x1e\x53\x3b\x48\x3d\x34\x01\xbe\x76\x82\x9f\x12\x3d\x4d\xa1\x6e\x34\xc3\xcf\xb1\x88\xa3\xc3\x85\xbc\xee\x2c\xb3\xdb\xc1\xd7\x47\xc2\xb1\x64\xbf\x0c\x62\xc7\xc9\xf6\x3d\xdc\xe6\x23\xfd\xc4\xa9\xbe\xbb\x88\xdb\x03\xf9\x6e\x87\x71\x24\x19\xc6\x34\xb1\x95\xcf\xd0\xbc\xb8\x44\xf8\xfa\x55\x81\x0e\xd0\x66\x36\xf2\xfd\x3f\xff\x41\x1e\x6c\x63\xa6\x1c\x9d\xa6\x3d\xfc\xf8\xe1\xc0\xb5\xf3\xed\xdb\x13\x12\xdd\x50\x36\x94\x78\x0d\xbd\xbd\xf8\xe8\xa6\x92\xb1\x18\x4f\x9c\x58\xec\x4f\x9a\x9e\x17\xe0\xa4\x69\x40\x84\x6f\x48\xaf\x28\x34\x05\xcf\xc9\x90\x3f\x10\x82\x88\x7d\x10\xad\x29\x23\xf5\xe8\x98\x28\x5f\xfe\x9c\xe3\x68\x9f\x2d\x92\xaf\x35\x85\x52\x41\xdc\x1f\x01\x21\x4d\x21\x2f\x34\x05\x31\x2b\xb4\x02\xa7\x22\xee\xdd\x9a\x88\x74\xea\xb9\xad\xcb\x34\x85\x56\xbb\x59\xca\xb6\xb7\x5f\xe5\x84\x8a\xd0\x16\x90\x2c\xdf\xca\xf2\x39\xe1\xcc\x39\xda\x36\xef\x38\xbd\x1c\x05\xb6\x62\x6e\x67\x8c\x53\x3e\x17\x0e\xc9\xa2\x24\x39\xb5\x4f\x70\xdb\x28\xd4\x58\xfe\x42\xff\xc2\x89\x62\xa4\x25\xfc\x54\xf6\xa7\xdb\xe1\x58\x8e\x30\x2b\xec\x76\x09\xce\x3b\xcc\x75\x16\xf8\xb8\xa9\xf4\x13\xcd\x10\x21\xcc\xa9\x2d\x42\xb6\xc1\x6e\xeb\x14\xc1\x2d\x8e\x7f\x82\x41\xa2\x5d\xe3\xc3\x1e\x52\x5c\xef\xa8\x1b\xb6\x33\xb6\x60\xab\x51\x41\x14\xe0\x80\xad\x8b\x21\xca\x62\x6e\x22\xb2\x31\x37\x67\xd0\x81\xae\x0e\xff\x2f\x00\x00\xff\xff\x20\x52\x2f\x76\xc0\x02\x01\x00") +var _operation_fee_stats_1HorizonSql = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\xbd\x79\x6f\xa3\xc8\xf6\x3f\xfc\xff\xbc\x0a\xd4\x1a\x29\xdd\x4a\x7a\xc2\xbe\xf4\xfc\xfa\x4a\xd8\xc6\x4b\x6c\xe3\x7d\x1d\x8d\xac\x02\x0a\x9b\xd8\x06\x02\x78\xcb\xd5\xf7\xbd\x3f\x32\xe0\x8d\x80\x8d\xc1\x4e\xcf\xd5\x33\xd1\xa8\xc7\x98\xaa\xb3\xd5\xa9\xf3\xa9\x53\x75\xc0\xdf\xbf\xff\xf6\xfd\x3b\x52\x37\x6c\x67\x6c\xc1\x56\xa3\x82\x28\xc0\x01\x12\xb0\x21\xa2\x2c\xe6\xe6\x6f\xdf\xbf\xff\xb6\xbd\x9f\x5b\xcc\x4d\xa8\x20\xaa\x65\xcc\x0f\x0d\x96\xd0\xb2\x35\x43\x47\xb8\x3f\xe8\x3f\xb0\xa3\x56\xd2\x06\x31\xc7\xa3\x6d\xf7\x40\x93\xdf\x5a\x42\x1b\xb1\x1d\xe0\xc0\x39\xd4\x9d\x91\xa3\xcd\xa1\xb1\x70\x90\x9f\x08\xfa\xa7\x7b\x6b\x66\xc8\xd3\x8f\xdf\xca\x33\x6d\xdb\x1a\xea\xb2\xa1\x68\xfa\x18\xf9\x89\x3c\x74\xda\x79\xf6\xe1\xcf\x1d\x39\x5d\x01\x96\x32\x92\x0d\x5d\x35\xac\xb9\xa6\x8f\x47\xb6\x63\x69\xfa\xd8\x46\x7e\x22\x86\xee\xd3\x98\x40\x79\x3a\x52\x17\xba\xec\x68\x86\x3e\x92\x0c\x45\x83\xdb\xfb\x2a\x98\xd9\xf0\x84\xcd\x5c\xd3\x47\x73\x68\xdb\x60\xec\x36\x58\x01\x4b\xd7\xf4\xf1\x9f\xbe\xec\x10\x58\xf2\x64\x64\x02\x67\x82\xfc\x44\xcc\x85\x34\xd3\xe4\xa7\xad\xb2\x32\x70\xc0\xcc\xd8\x36\xe3\x2b\x6d\xa1\x89\xb4\xf9\x4c\x45\x40\x4a\x79\x44\xe8\x97\x5a\xed\x16\x52\x13\x2b\x03\xbf\xfd\x1f\x13\xcd\x76\x0c\x6b\x33\x72\x2c\xa0\x40\x1b\xc9\x35\x6b\x75\x24\x5b\x13\x5b\xed\x26\x5f\x12\xdb\x47\x9d\x4e\x1b\x8e\x64\x63\xa1\x3b\xd0\x1a\x01\xdb\x86\xce\x48\x53\x46\xea\x14\x6e\xfe\xfc\x0c\x86\xb2\xfb\xe9\x33\x58\x6e\xfd\xea\xf3\x14\xf4\xb8\x5d\xaf\x9d\x27\xe0\xd6\x91\xcf\x31\x3b\x6a\x75\x20\xee\x36\x2f\x89\x39\xa1\x7f\xd4\xd2\x27\xeb\x4a\x35\x82\xaa\x0a\x65\xc7\x1e\x49\x9b\x91\x61\x29\xd0\x1a\x49\x86\x31\x3d\xdf\x51\xd3\x15\xb8\x1e\x1d\x29\xa7\xdb\xc0\x75\x74\x7b\x64\xe8\x23\x4d\xb9\xa6\xb7\x61\x42\x0b\xec\xfb\x3a\x1b\x13\xa6\xe8\x7d\x90\x24\x95\x14\xd7\xf5\x9d\x41\x65\x0c\x2d\xb7\xa3\x0d\xdf\x16\x50\x97\xaf\x52\xe1\xa8\xbb\x69\xc1\xa5\x66\x2c\x6c\xff\xbb\xd1\x04\xd8\x93\x84\xa4\xd2\x53\xd0\xe6\xa6\x61\x6d\xa7\xa3\x1f\x53\x93\x92\x49\x6a\x4b\x79\x66\xd8\x50\x19\x01\xe7\x9a\xfe\x3b\x67\x4e\xe0\x4a\xfe\xbc\x4c\x20\xf4\x71\x4f\xa0\x28\x16\xb4\xed\xf3\xdd\x27\x8e\xa5\xb8\xb8\x33\x9a\x19\xc6\x74\x61\xc6\x68\x6d\x5e\x12\xc9\x6b\x05\x34\xeb\x4a\xc2\xbb\xa0\x1b\xbb\xc3\x36\x4e\xa8\x2a\xb4\xe2\x35\xdd\x91\x4f\xd0\xc5\x37\x6b\xbc\x4e\x6e\x68\xbd\x82\xc9\x71\x28\xbe\xd4\xc3\xdc\x76\x98\x38\x17\x47\xc0\x3e\x09\x40\xd2\xe6\xa2\x1b\x4d\xf6\x33\x3d\x4e\x63\xc3\x93\xc3\xb8\xd8\x50\xb3\x9d\x91\xb3\x1e\x99\x97\x49\x6e\x5b\x1a\x66\xdc\x96\x30\x6e\xb3\x1d\x94\x9c\x6f\x2c\xed\xa6\xfb\xc5\x66\x97\xa3\x98\xb4\x89\x37\x98\x1e\x46\x6e\xad\x6d\xdb\x8b\x4b\x9c\xf7\x8d\x65\x43\x81\x57\xae\x0b\xf6\x6e\x60\x02\xcb\xd1\x64\xcd\x04\xfa\x59\xf0\xbe\xd4\x75\x64\x5e\xb9\x36\xd9\x23\xda\xb5\x12\x84\x77\xbc\x9a\xbf\x6b\xbc\x38\xfc\xbc\x86\x77\xa7\xef\x0d\xe6\x76\x24\xfd\x8f\x5b\x7c\xd8\x2d\xfd\x5c\x67\x18\xc5\x94\x60\x6c\x58\xe6\x68\xae\x8d\xfd\x05\xc3\x19\x11\x02\x2d\x63\xeb\x78\xfd\x7a\xef\x1c\xe5\xb8\xce\xe9\xf5\xce\xd6\x2a\x9d\xaa\x88\x68\x8a\xc7\x39\x27\xe4\xf9\x4e\xa5\x1d\x93\x76\x84\xd3\xdd\x80\xb2\x3f\xdc\xe7\x29\xb9\x57\xf1\xd5\xdf\xa1\x74\x4b\x68\x74\x04\x31\x9b\xc0\x66\xdb\x75\xb6\x0d\xdf\xae\xe6\x7c\x42\x24\x76\x6f\x05\xc6\x6c\x7b\x58\xcd\xc6\xd6\x30\x62\xd6\x5f\xa3\x5f\x38\x89\x78\x7d\xfd\x75\x5f\xbc\xc6\xfe\x22\x2f\xb6\x6e\x7e\x04\xb8\x46\x17\xaf\x4b\xcc\xb6\xfe\xf2\x2f\xbe\x3c\xbb\xf5\x62\x1c\x89\x02\x31\xe4\x7c\xe3\xa3\x90\xe0\x37\xe4\x0b\x85\xa6\x50\xe0\xdb\x21\x8d\xe7\xda\x36\xe3\xd0\x64\xf8\x55\x5f\xcc\xa1\xa5\xc9\x7f\xfd\xfd\x2d\x46\x2f\xb0\x4e\xd0\x6b\x06\x6c\xe7\x2b\xd0\x37\x70\xe6\x6e\xc5\xc4\xe8\xa1\x6a\x56\x68\x97\x7c\x47\xcc\xb6\x4b\x35\xf1\x8c\x3e\x23\x30\x1e\x1f\xa4\x7b\x42\x3e\x08\x7a\x86\xc6\x4e\xbb\x14\x34\xb6\xba\xba\xdd\x0f\xc2\x3f\x21\xd7\x28\xe2\xaa\x1e\x83\x82\xd0\x6f\x0b\x62\x2b\x40\x62\x66\x8e\xed\xb7\xd9\xce\x17\xb3\x45\xa1\xca\x7f\xe0\xf0\xe7\x6f\xde\x2e\x9c\x08\xe6\xf0\xc7\xee\x3b\xa4\xbd\x31\xe1\x0f\xbf\xcb\x9f\x48\x4b\x9e\xc0\x39\xf8\x81\x7c\xff\x13\xa9\xad\x74\x68\xfd\x40\xbe\xbb\x9b\x73\xd9\xa6\xb0\x1d\x2f\x9f\xf2\x8e\xde\x6f\x27\x14\x4f\x6f\xfa\x84\xb3\xb5\x6a\x55\x10\xdb\x67\x28\x7b\x0d\x90\x9a\x78\x4a\x00\x29\xb5\x90\x87\xdd\xb6\xdb\xee\x3b\xdb\x25\xf2\x10\xe4\xbc\x53\xdf\xe7\xb9\xb7\xd0\x45\x7d\x4e\x6c\x29\xd6\xda\x01\x7b\x22\xbd\x52\xbb\xb8\x17\xeb\x78\xff\xed\x84\xfd\x81\x4a\x40\x90\x6b\x94\xff\x40\xc4\x35\x40\xbd\xf2\x6c\x8e\x5b\x8d\x0a\x62\x5a\x86\x0c\x95\x85\x05\x66\xc8\x0c\xe8\xe3\x05\x18\x43\xd7\x0c\x31\xf7\x0b\x8f\xc5\xbd\xec\x68\xbe\xf8\x3b\x5f\x3d\xc8\xbf\x1b\xdb\x30\x5b\xee\x3d\xfb\x22\x7d\xa4\x29\xb4\x3b\x4d\xb1\x75\xf4\xdd\x6f\x08\x82\x20\x15\x5e\x2c\x74\xf8\x82\x80\xb8\xda\x57\xab\x1d\x2f\xde\xb5\xda\xcd\x52\xb6\xed\xb6\xe0\x5b\xc8\xef\xa3\xdf\x91\x96\x50\x11\xb2\x6d\xe4\x77\x6c\x7b\x15\x1c\x8d\x8b\x13\x31\x9d\x76\x97\xc8\xdf\x4c\x39\x3c\x4c\xb9\x38\x91\x2a\x9d\x7e\x31\x38\xec\x55\xdc\x7f\x95\x48\xc3\xaf\xbf\x21\x48\x96\x6f\x09\x48\xaf\x28\x88\xc8\xef\xd8\x5f\xd8\xdf\xcf\xbf\x63\x7f\xe1\x7f\xff\xe7\x77\xdc\xfd\x8c\xff\x85\xff\x8d\xb4\xbd\x9b\x88\x50\x69\x09\x5b\xa3\x08\x62\xee\x5b\xa8\x65\x62\xe0\x40\x4a\xcb\x5c\xe6\x70\x6f\xcb\xfc\xbf\x24\x96\xf9\x88\xa9\xbe\x1d\xf6\x38\x1c\xcf\x10\x07\xd8\xfe\x40\xd1\x95\x18\x41\x5a\x5b\x5b\x21\x3f\x0f\x11\xe0\xc9\xfb\xba\x3d\xa8\x0b\xc8\xcf\xe3\x19\xf1\x2d\x6c\xd6\xde\x54\xc6\x20\xc1\x80\x88\xbb\x69\x1c\x5f\xc2\xd0\x25\x50\x5a\x29\xc3\x88\x06\x24\x3d\x99\x90\xa7\xe2\x1e\xbc\xec\xa3\xb4\x61\xcb\xbc\xd4\xd2\x86\x10\x0d\x4a\x7b\x3c\x49\xce\x4a\xbb\x45\x2e\x05\xaa\x60\x31\x73\x46\x0e\x90\x66\xd0\x36\x81\x0c\x91\x9f\xc8\xc3\xc3\x9f\xa7\x77\x57\x9a\x33\x19\x19\x9a\x72\x74\x94\x76\xa2\xeb\xf1\xfa\xd7\x57\xd1\x9d\x60\xf1\xd4\xf3\xe6\xe2\x71\xf2\xed\x69\xa4\x29\x88\xa4\x8d\x35\xdd\x71\x17\x06\x62\xa7\x52\xf1\xd4\x01\xf3\xed\x32\x1e\x91\x27\xc0\x02\xb2\x03\x2d\x64\x09\xac\x8d\xa6\x8f\x03\xcd\xf4\xc5\x7c\xbf\xe4\x47\x34\xdd\x81\x63\x68\x05\x9a\xa8\x33\x30\xb6\x11\x7b\x0e\x66\xb3\x8f\x6c\x1c\x63\x3e\xfb\xc8\xe4\x2b\x4e\x51\xdf\xf6\x2d\x3f\x0e\x7b\x30\x6f\x48\x6a\x8e\xe0\x6e\xc7\xde\x24\x0e\x5c\x7f\x30\x88\x69\xce\x34\x77\xcf\x1e\x71\xb4\x39\xb4\x1d\x30\x37\x91\xed\x98\xb9\x97\xc8\xbb\xa1\xc3\x8f\x82\x46\x65\x45\xbb\xf5\xa8\x9f\x4e\xc5\x93\x79\x9f\x7c\x45\x50\xf5\xdd\x90\x6f\xb6\xbd\x15\x1d\xe6\x7e\x51\x12\xb3\x4d\xc1\x5d\x7e\x65\x06\xfe\x57\x62\x0d\xa9\x96\xc4\x2e\x5f\xe9\x08\xfb\x6b\xbe\x7f\xb8\xce\xf2\xd9\xa2\x80\x60\x97\x94\x49\x6c\xf6\x20\xa1\x0f\xae\xe8\x6f\x7a\x20\x3a\x5c\x3b\x4b\x30\xfb\xfa\x10\xa1\xf1\xc3\x8f\x1f\x16\x1c\xcb\x33\x60\xdb\xdf\x82\xc3\xe5\x9d\x55\x84\xf8\x16\x4d\x7e\x3b\x33\x50\x5e\x6e\x9c\x5a\x33\x6f\x47\x67\xaf\x57\xf8\xcc\x38\xec\xd5\x85\x8b\x19\xda\x5c\x36\x94\xb0\xe6\x18\x1e\xde\xdc\xdb\xfe\x0b\xe9\x40\xd1\xe7\x66\x58\xf8\xf6\xc2\x8d\xdc\xf6\x98\xe6\xa7\x39\xed\x39\x45\x90\x5a\x4f\x14\x72\x48\x66\x70\x41\x23\x6f\x87\xee\xbc\x42\x7b\x5a\x81\xdb\x7f\x68\x4a\x94\x6c\xbb\x3d\x9f\xb4\x5e\xe7\xd3\xf1\xdd\x2e\x30\x67\x46\x51\x91\xfe\xe3\x16\x57\x54\xcb\x2f\xee\xc1\xc7\x97\x08\x6f\x76\xfd\x38\xfc\x96\x02\x1d\xa0\xcd\x6c\xe4\xd5\x36\x74\x29\xda\xd9\x76\x1b\x65\x69\xed\xe0\xd3\xf1\xed\xb0\x3b\xb7\x8e\x90\xed\xe8\x30\x39\xd6\x2c\x0c\x3b\xc7\x0e\xef\xe8\x9b\xe5\x68\x67\xd4\x1d\x88\xbd\x1c\xbb\x28\x87\x06\x38\x1c\x06\x22\x5e\xfb\xfd\x61\x72\x00\x98\x8c\x85\x73\xc0\xa6\x60\x1f\x0b\x02\xe7\x62\x27\xaf\xed\xc2\x54\x62\xb7\xdd\xbb\x8e\x7f\x19\x38\x67\xff\xa0\x0b\xf6\x61\x3d\xe0\x80\xd9\x48\x36\x34\xdd\x0e\xf7\x41\x15\xc2\x91\x69\x18\xb3\xf0\xbb\xee\xc9\xa7\x0a\xa3\xc6\xda\xbd\x6d\x41\x1b\x5a\xcb\xa8\x26\xdb\x75\xa8\xb3\x1e\xb9\xcb\x24\xed\x3d\xaa\x95\x69\x19\x8e\x21\x1b\xb3\x48\xbd\x82\x63\xb4\x73\x16\x08\x14\x68\xb9\xcb\x0b\xef\x7b\x7b\x21\xcb\xd0\xb6\xd5\xc5\x6c\x14\xe9\x28\xbe\xe2\x40\x9b\x41\x25\xba\x55\xf4\xb4\x8a\xd8\xbb\x4e\x3b\xcb\x22\xce\x43\x2e\x60\x5e\xfc\x68\x73\x39\x7e\x5d\xab\xf2\x6d\x61\xec\x2c\x8f\xcf\x82\xb5\xab\x14\x4d\x09\x73\x67\x79\x7d\x84\xbd\xf0\xe6\x67\x60\xf0\xe8\x64\x27\xbe\x6f\x7e\xff\xbe\x5d\xea\x41\x05\xd1\xec\x91\x09\x36\xdb\xa4\xf6\xa7\x9b\x3d\xed\xf2\x2a\xc4\x31\xfc\x0d\xd5\x27\xc4\x02\xce\x64\x3b\xfd\x26\x40\xdf\x86\x6c\x7d\xbc\x9d\xdf\x36\xb4\x1c\x64\xa6\xe9\xd0\xbe\xe4\xe8\x97\x72\xa6\xd3\x12\xad\x88\xbc\x6a\x9b\x46\xc8\x9e\x5d\x5c\x38\x4d\x89\xa6\x7e\x18\x31\x16\x96\xbc\xaf\xf9\x88\xc0\xb1\x5d\x6c\x7a\x78\xf8\xf1\xe3\x52\x5e\x77\xb0\x26\x22\x19\xc6\x0c\x02\x7d\x6f\x4f\xd7\xba\xd1\x53\xcf\x3f\xcb\x4b\x1b\x5d\xfc\xf2\xc3\xaf\x37\x5d\xa2\xf8\x51\x38\x09\x60\xba\xe5\x37\x91\x6c\x03\xc5\x8f\xe7\x1a\xf9\xf5\x98\xe7\x9a\x78\xa9\x77\x68\x83\x8f\x65\xa4\x17\xda\x9d\x65\xb7\x6f\x75\x86\xa3\x2b\x92\x66\x8f\x6c\x38\x9b\x41\x6b\xe7\x0d\x3b\x18\xd4\x64\x38\xd2\x4f\x20\xdf\xfb\xee\x74\x19\x70\x28\x60\x1a\x05\x16\x08\x27\x25\x54\xc1\x9b\x96\xb1\xd0\x15\xb7\x06\x79\xa6\x99\x26\x18\xc3\x8f\x44\x35\x7b\x04\xd7\x40\x76\x4e\xe5\x3a\x2a\x29\x08\xad\x52\x75\xd5\x1d\xb9\x75\xcc\x48\xb6\x28\x64\xcb\xc8\xd7\xaf\xc7\xa6\xff\x0f\x82\x7e\xfb\x76\x89\x54\x58\xf7\x9d\xb5\xff\xdf\x87\x01\x88\x41\xef\x64\x30\x02\xe4\x03\x23\xe5\x0a\x78\x76\x0e\x86\x9f\xc6\xdf\x60\x56\x86\xd7\x57\xc4\x44\xfd\x38\x11\x32\x0d\xee\x5f\xaa\x65\xb8\x0d\xf2\x5f\xe0\xf2\x59\xd8\x7f\xa5\xb2\x29\xd1\xff\x02\xb7\x8f\xf8\x1f\xd5\xe1\xcc\x0a\xe0\xa4\x7e\xe5\x86\xbe\xba\xf3\xcf\x63\x91\x62\x27\x7c\x3e\x68\x5c\x48\x23\xe3\xe2\xfa\x79\x88\x0e\x6d\x7b\x60\x1d\x3a\x5f\xb6\x19\x4b\x74\xca\x13\x95\x4c\xfe\x92\x74\xd0\x59\x8f\xa0\xbe\x84\x33\xc3\x84\x61\x5b\xac\xce\x7a\x9b\x9c\xb9\x6b\xb6\xd0\x9b\x73\xe8\x80\x88\x5b\xdb\xb4\x30\xea\xb6\xad\x8d\x75\xe0\x2c\x2c\x18\xb6\x1b\xc8\xd1\xdf\xfe\xfa\xfb\xb0\x34\xfa\xef\xff\x85\x2d\x8e\xfe\xfa\x3b\x68\x73\x38\x37\x22\x36\xee\x0e\xb4\x74\x43\x87\x31\x96\x5a\x5b\x5a\x1f\xc9\xf8\x9a\x69\x73\x38\x92\xb6\x30\xe8\xee\xae\xb3\xd6\x76\xcd\x7a\xe2\x96\xe1\x37\xe7\x9a\x3e\x8a\xf0\x9e\xe8\x06\xa3\x20\xc2\x86\x36\xf2\xf9\x8e\x81\x79\xd2\x16\xae\x1d\x0b\x8c\xb6\xa6\x86\x96\xed\x8e\xc2\x5f\x7f\x07\x53\xdc\x53\x90\xde\x0e\xd9\x56\xed\x31\x54\x4e\x33\x5d\x1d\xae\x46\x01\xa7\xbe\xb4\x41\x89\x68\xca\x2e\x5e\xec\x0a\xe6\xe2\x04\x39\x2f\x60\xb8\xd5\x89\x17\x6a\xf1\x5a\x42\xfb\xcc\xae\xf4\xf1\xfe\xdf\xf1\x9e\xf4\x75\x59\xdb\xed\x94\x88\x59\xaa\x78\x56\xa9\xb3\xd9\x5e\x1c\x25\x23\xd7\x0a\x37\x53\x33\x76\xb5\xe7\x59\x45\x2f\x00\x5b\xb8\xaa\x39\xe0\x00\x44\x35\xac\x0b\x67\x73\x48\x8e\x6f\xf3\x17\xd4\x8b\x20\x79\xee\x8c\x2b\x0e\xd9\x92\xd8\x12\x9a\x6d\xa4\x24\xb6\x6b\x1f\xce\xb9\xdc\x25\x46\x0b\xf9\xfa\x80\x8d\x34\x5d\x73\x34\x30\x1b\x79\x29\xf2\x1f\xf6\xdb\xec\xe1\x09\x79\xc0\x51\x8c\xfb\x8e\xd2\xdf\x51\x02\xc1\xd8\x1f\x38\xfb\x83\x64\xfe\x40\x09\x9c\xe4\xe8\x47\x14\x7f\xf8\xf6\x67\x3c\xea\xf8\xc8\x7b\x96\xe4\xc4\xaa\xd2\x66\xe4\x18\x9a\x72\x9e\x13\x47\x53\xcc\x35\x9c\x88\xd1\xc2\x86\x87\x18\xa5\xe9\x1f\x9e\x5f\x39\xcb\x8f\x24\x51\x92\xbd\x86\x1f\x39\x02\x8a\x32\x0a\xee\x02\x9e\xe5\x41\x91\x14\x81\x5f\xc3\x83\x1a\x79\xa8\xbc\xcb\x0f\xdc\xd3\xe3\xb3\x2c\x68\x02\xc5\xaf\x52\x83\xde\xb1\xf0\x23\x58\x0c\x16\x2c\x89\x51\xd7\xb0\x60\x46\x73\x43\xd1\xd4\x4d\x7c\x2d\x58\x8c\xc6\xaf\x62\xc1\x9e\x68\xe1\x17\x8d\xc7\xe0\xc3\x90\x34\x71\x1d\x9f\xed\xa0\x83\xf1\xd8\x82\x63\xe0\x18\xd6\x79\x9f\xe2\x50\x0c\xe5\xae\x21\xcf\xb9\xe4\xbd\x1d\xe2\xd1\x5a\xb1\xce\x53\xc7\x19\xec\xaa\xa1\xc6\x50\x97\xbc\x3f\x0a\x6e\x92\x7e\x9e\x01\xc5\x31\x57\x59\x07\xc3\x8e\x19\xec\x93\xb7\x6d\x00\x38\xcf\x88\xa3\xb9\xeb\x34\xc1\x4f\x06\xda\x4f\x97\xbd\xc7\x94\xcf\x71\xc2\x50\x86\x22\xaf\x1a\x11\x8c\xf0\xd4\xd9\xef\x4e\x9c\x1d\x71\x0c\xc3\x19\xfa\x3a\x4d\xc8\x91\xaa\xad\x77\x8f\x6c\x18\xf3\xd9\x48\xd5\xe0\xec\x6c\x68\xc4\x30\x0a\xc3\xae\x0a\xc2\x18\xb5\x5b\xb2\xed\x4e\x10\xd6\x17\xd4\xa0\x99\xeb\xc2\x3c\x46\x8f\x34\x7d\x0c\x6d\x67\xf4\xf1\x8c\xe2\x02\x2b\x86\x63\xaf\x1b\x11\xe6\x04\xae\xdd\xc3\x20\x70\x1e\x4c\x30\x1c\x45\x09\xd2\x67\x12\x81\xb5\x67\x2b\x1b\xae\x05\xdb\x0f\xd5\x0d\x3b\xe9\xb1\x27\xe4\xa1\x90\xed\x97\x0b\x74\x53\x24\x6b\x62\x49\xa8\x67\xab\x62\x3e\xc3\x10\x38\x4f\x12\xf4\x90\xaa\x8b\xb9\x56\xb3\x52\xe8\x95\x99\x42\xa6\x92\xad\x36\x2a\xa5\x7c\x8d\x6c\x31\xc2\xa0\xd7\xed\x04\x2d\x14\xc9\x04\xdf\x32\xc9\xf4\x0b\x8d\x97\x5e\xb7\xd2\xab\x0d\x8a\xf9\x4a\xb7\x5d\xee\x75\xa9\x7c\xa1\xc8\x13\x15\x71\x30\xc0\x5f\x1a\xe5\x2a\x53\xe3\x5f\xf8\x8e\xd0\xc8\x77\xe8\x4a\x3d\xdb\x12\xf2\xdd\x7e\x4d\x8c\xcd\x84\x70\x99\x34\xeb\x83\x62\xa9\x82\x67\x4b\x44\x5e\x6c\x90\x99\x7e\x25\x5f\x15\x73\x95\xfc\x4b\x47\xac\x77\xf0\xe2\x80\x18\x56\xf3\xad\x62\x4d\xec\x64\x85\x1a\xdf\xea\x31\x8d\x2c\x53\xeb\xe3\xc5\x87\xa4\x45\x32\xdb\x55\xdc\x85\x61\xf0\x0b\x0b\x0f\x35\xc1\x7f\xd8\xf0\x7c\x01\xc9\x13\x42\x3c\x21\x8e\xb5\x80\x31\x9c\xe3\x63\x69\xc8\x35\xcb\xbb\x6b\xca\x11\x6e\xa2\xe9\x49\x52\xf2\x84\x60\x4f\xde\xce\xfd\x65\x45\xc3\xca\x11\x92\x4e\x82\x5d\x49\xc2\xd1\x1c\x20\x50\x94\x26\x19\x86\xc2\x68\xce\x95\x6a\xeb\xb1\xff\xfd\xe2\x85\xf1\x2f\x3f\x90\x2f\x18\xfa\x07\xea\xfd\x7d\x79\x42\xbe\x1c\x6a\x64\xb6\xf7\x74\xe0\x68\x4b\xf8\xe5\xff\xa2\x3c\x35\xc8\x0e\x0f\xb0\xc3\xdd\xf1\xbe\x1b\xbb\x83\x76\x1c\x4e\x53\x9f\xa8\x9d\xc7\xee\xb3\xb4\x63\x09\x82\xc6\x3e\x4f\x3b\x9f\xdd\x9d\xb5\xc3\x9f\x10\x9c\x62\x68\x8e\x45\x19\x96\x21\xee\xae\x1d\x16\x60\x77\xff\xb1\xf3\xd8\x61\x18\xf7\x39\xf3\xee\x84\xdd\x27\x68\x87\x91\x0c\xc9\x92\x28\xc5\x30\x9f\xa2\xdd\x31\xbb\x4f\xd3\x8e\xa4\x3f\xc1\x33\xf1\x00\xbb\x4f\xd3\x8e\x65\x3e\xc9\x33\x8f\xd9\x7d\x96\x76\x14\xce\x7e\x0e\x22\x9c\xb0\xbb\x7f\xcc\xc4\x98\xed\x22\x9e\x21\x70\xf6\xfe\x88\x80\x05\xd8\xdd\x7f\xec\x30\x9c\x65\x49\x0e\xa5\x38\xf6\x53\xc6\xee\x84\xdd\xfd\xb5\x63\x29\x96\xe3\x08\x96\x66\xbd\x69\x87\xba\xdc\x6c\x07\x58\x8e\xa6\x8f\x47\x12\x98\x01\x5d\x86\x1e\xdf\x03\xe3\xd8\x0c\x88\x53\x06\xa1\xea\xdc\x4f\x9f\x6d\x9c\xf4\x14\x5a\x41\x6d\x3c\xd9\xf2\xc3\x9e\x90\x2f\xde\xc2\x75\x34\x85\x9b\x2d\x8f\xa4\xd9\xd8\x55\x83\xea\x4a\x45\xe2\x8c\xef\x42\x77\xb2\xb2\xcf\xe0\xde\x56\x0e\xe8\x13\xcf\xca\x09\xd3\x51\x4f\xaa\x0b\xc9\x4a\x58\xcd\x70\xd2\x64\x65\x57\x37\xbc\x53\x96\x79\x42\x1e\x30\x5a\xa5\x55\x45\xa2\x64\x1c\x25\x39\x16\x85\x04\x09\x65\x8a\x20\x48\x99\x44\x39\x89\xa4\x70\x89\xe2\x50\x9a\xa2\x50\x85\x86\xb8\x24\x53\x90\xa6\x24\x86\x45\x09\x82\x82\x18\xce\xaa\x38\xf5\xb0\xa5\x81\xab\x18\x2b\x13\xa4\x24\x91\x34\x43\x63\x2c\x50\x19\x05\x47\x39\x82\x56\x20\x2d\x03\x12\x10\x0a\x26\x03\xc0\xb2\x98\x4c\xd0\x40\xe6\x00\x23\xb1\x9c\x0c\x19\x8c\x20\x29\x12\x2a\x24\xee\x65\xa9\x44\x60\x83\x83\xfe\x41\xd0\x3f\x48\x3a\xb8\xef\xe1\x7d\x4d\xfe\x41\x60\x24\xc3\xb2\x67\xef\x72\x0f\xfb\x04\x02\x43\x99\x6d\xfc\xa1\xb7\xe3\xf9\xe1\xef\x09\xc1\x08\xf7\x5f\xff\x9f\xfd\xb7\xfb\x0f\xd8\x13\xf2\xc0\xf3\x3c\x9f\x5d\x57\xd6\xaf\xb9\x16\xd3\xd4\x07\x03\x8b\x40\xc7\x53\x9c\x98\x6f\xa6\x06\x57\x2c\xbf\x95\x8a\x39\x60\xcf\xf5\xc5\xcb\xbb\x2e\xa0\xdd\x1a\x96\x7d\xe1\x05\x60\x72\xef\x22\xb7\x98\x59\xd9\x37\x9b\xd9\xc0\xf2\x5b\x39\x23\x6b\xed\xca\xbc\x58\x13\xe7\x8f\x3c\xdf\x7a\x2b\x4c\x0b\x13\x47\xe8\x6c\x49\xf3\xfd\x7a\xb7\xaa\x8f\xf9\xfd\x5f\x05\xa3\xd0\xe7\x29\xd7\x57\x6d\xb4\xfd\xd2\xc8\xaa\xa5\x05\x97\xcb\xda\x35\x61\xaa\x61\x65\xfd\x71\x52\xc1\x4b\xf9\xcd\xa6\xd2\xad\x2a\xfd\x4a\xeb\xad\x59\x9d\xda\xc3\xf1\x33\x66\x3f\xb7\x45\xbc\xda\x46\xeb\x6d\xbe\xb2\x1c\xae\x20\x3a\xb1\x2a\xcf\xcb\x1a\xf7\xb6\x61\x73\xfd\xd2\x66\xe2\x52\x96\x45\xb2\x02\xde\x4d\xbc\x71\x60\xc6\x77\x3a\x7c\xc8\xdf\x90\xef\x63\x64\x83\xe7\x73\xe8\x4b\xd8\xed\x7f\xf4\x9f\xe7\x55\x68\xc4\xc4\x0f\xce\x05\xfa\x36\x7e\xfc\xc0\xca\x38\x2e\x4b\xac\xcc\xc9\xa8\x44\x30\xb2\xca\xb1\x2a\xa3\x42\x9a\x51\x65\x02\xb0\x34\xca\xd0\x94\x4c\x40\x9a\x95\x65\x14\x12\x32\x60\x08\x12\xe0\x38\x49\x29\x34\x4d\x03\x9c\x54\x80\xfa\xe0\xc6\x38\x3c\xd4\xad\xa9\x48\x6f\x27\x09\x9c\x66\x2e\xde\xf5\x13\x32\x82\x61\xe8\x73\x73\x01\x8d\x39\x17\xc8\x95\xb6\x21\x37\x72\xf6\x5d\xad\xcf\xeb\xea\xe3\xf0\x79\x45\x4f\xc6\xca\x6c\xf5\x08\xaa\xab\x5a\xbd\x2c\xa3\x86\xd6\x54\x86\x73\x63\x8a\x2f\xb5\xb9\xc8\x98\x9b\xb1\xd5\x9c\x11\xdc\xca\x20\xad\x42\x93\x30\x5e\xe1\xfc\x1d\x7b\xe5\x96\x85\xa6\x59\xe8\x8f\x97\xe5\x65\x7e\xd2\x45\xdb\x25\x77\xec\xdc\xb9\x70\xe4\x9e\x8f\x85\xfc\xb0\xf8\xd6\x29\x4d\xf5\x16\x61\x52\xf6\x50\x22\xe5\x77\x99\x2d\xbf\xa2\x40\x2a\xb4\xaa\x5d\x55\x04\x6f\x8f\xdc\xfb\xfb\xcc\xc1\x9b\x2f\x1b\xca\x59\x6d\x0a\x9a\xb8\x79\x7c\xd6\xf9\x35\x66\x31\x79\xe5\x91\x2b\xac\xd6\x98\xda\xab\xb5\xaa\xd3\x82\xda\xdf\xf4\xb2\xce\xba\xf1\xe6\xce\xb5\x41\xc8\x5c\xa8\x1b\x61\xfe\xf4\x3f\x3e\x17\xf0\xf8\x73\x81\xba\x8d\x1f\x3f\x60\x34\x26\x63\x92\x42\x4b\x38\x05\x20\x06\x30\x82\x21\x71\xc0\x32\x32\x2d\x4b\x1c\x2e\xb3\x34\x05\x08\x5a\x26\x58\x56\x95\x58\x56\x56\x18\x8e\x63\x25\x96\xc6\x00\x94\x00\x4d\x73\xb4\xb2\x0d\xdf\xa4\xfb\x5f\x98\x5b\x47\x7a\x3b\xc5\xb0\x58\xf4\x4c\xd9\xdd\xf5\xd2\x08\x82\x26\x59\xf4\xcc\x5c\x60\xe3\xc2\xc2\x40\x2e\x70\x60\xd3\x5b\x14\x26\x22\x5a\x36\xd4\xc2\x86\xaa\x94\x86\x40\xb4\x6b\xa5\x47\xf2\x55\x84\x43\x8d\x1c\x00\x9a\x1e\x9a\xd2\x70\xc9\x6d\xba\x95\x7e\x65\x88\x91\x19\xfe\x55\xea\x37\xcb\xbd\xf2\x5b\xb5\x38\xae\x93\xca\xf3\x46\x6b\x57\x06\x05\xa3\x32\x19\x0e\x4c\xd9\x2e\x78\x2e\xe9\x4e\x85\xa3\xa1\x2c\x33\xc3\x7c\xd1\xec\x2c\xa9\xf5\xb8\x2e\x76\xa9\x7a\x57\x64\x61\x8f\xdb\x6c\xac\x17\x39\xd3\x19\xe6\xca\x78\xb6\x55\x2e\x2a\xcb\xfa\xd8\x19\x53\xd2\x54\xed\xcf\x2b\x39\xde\xe9\x4a\xab\x97\x79\x3f\x07\xcb\x99\x89\xfc\xba\x6c\x64\xbb\xab\x82\x32\x7d\xb3\x4b\x62\x91\xb6\x9a\x0b\xa1\xb0\xda\x52\xee\x84\x4c\x85\xea\x38\xcc\x9d\xfe\xc7\xa7\x02\x19\x7f\x2a\x90\xb7\x71\xe3\x07\x88\x31\x0a\x29\x53\x24\x03\x59\x19\xa7\x14\xc0\x51\x2c\x4b\x70\xdb\xa9\x42\x53\x2a\x50\x48\x9c\xa4\x64\x94\xc6\x24\x8c\x45\x29\x62\x3b\xe5\x08\x8a\x82\x24\x8b\x02\x49\x02\x00\x63\x31\x6f\x83\x1b\x0b\xf5\x6a\x22\xd2\xd9\x19\x96\x66\xa2\x17\x50\xbb\xbb\x5e\xce\x49\x73\x18\x4b\x9e\x99\x0a\x64\xcc\xa9\xf0\x98\xe7\xda\xf9\xe6\xe3\x6b\xb6\x0f\x66\x83\x31\x65\x4c\xb1\xd9\xa3\xd3\x98\xf6\xf9\x81\x54\xe0\x3b\x6c\xf6\x5d\xec\x52\xa5\xac\xb5\x78\x2b\x64\x96\xcc\xb8\xf8\x58\xd5\xac\xbe\x5c\x98\x2d\x55\xab\xb5\xd1\xe9\x57\xbb\x47\x49\xeb\x5a\x9e\x04\x05\xbb\xd2\xef\xf4\x06\xb4\x84\x16\xba\x39\xd9\x1d\xba\xed\x54\x98\xaf\x0e\x43\xc9\x89\x2a\x43\xf1\xea\x7b\xb9\x28\xab\xef\xb8\xae\x12\x2b\x99\xd1\xb0\xaa\x29\xb5\x35\x7b\x38\xb1\x67\x1b\xa6\x2a\xe4\x48\x03\x2b\x12\xba\x3e\x28\xaf\x64\x7b\xed\xcc\x5a\x13\x6d\x65\xbd\xf0\xaf\x1d\xa7\x2b\xa9\xb5\xfa\x80\x23\x29\x32\x8f\x66\x6a\xdd\xc5\x84\x01\x14\x6f\xbd\xba\xde\xdf\x08\x99\x0a\x85\x46\x98\x3b\xfd\x8f\x4f\x05\x2c\xfe\x54\x20\x6e\xe3\xc6\x0f\x12\xce\xd1\xea\x36\xa7\xa0\x64\x8c\x80\x2a\x85\x73\x0a\x20\x39\x1c\x97\x28\x95\x45\x39\x5c\x65\x24\x82\x83\xf2\x36\x34\xcb\x90\x23\x80\xcc\x02\x14\x95\x18\x20\x63\x04\x26\x03\x16\x10\xe7\xa6\x02\x1e\xe9\xec\x1c\x45\xa2\xd1\xd9\xc2\xee\xae\xbf\x41\x81\xb1\x2c\x7b\x66\x2a\xc4\x4d\x16\x98\x72\x8f\x2d\x74\xbb\xab\x36\x83\x95\x15\xf3\xa5\x64\xf5\xc9\x6c\x8b\x63\x6a\x70\x93\x1b\x56\xe9\xb6\x55\x32\x78\x87\x5e\xb5\x8b\x65\xed\x75\xf0\xda\x37\xdb\xef\x03\xbe\x4d\x74\xba\x0a\xf5\xc8\xa2\xf3\x85\xc4\xe4\x36\xaa\x63\x55\x0d\xae\x9e\x2f\x3e\x83\xa1\x28\x36\x27\x68\x6b\x59\x75\x87\xce\x9d\x0a\x47\xb1\xf9\xdd\xec\xad\xd5\x8e\x32\x5d\x99\xa5\xc7\x39\x98\x54\x3b\x85\xee\x0a\x9d\xd4\x71\xb5\xcc\x18\xf9\x62\x81\xd3\x50\xac\xde\x86\xcb\xe5\xbb\xf5\xfc\x32\x29\xcf\x9e\x8b\x4a\xed\xb5\x08\x5a\xe5\xdc\x8c\x60\xd0\x85\xac\xd7\x49\x81\x18\xd7\x4b\x6d\xf2\xed\x7d\xb9\x92\x94\x7a\xa6\xf5\x2a\xbc\xb8\x53\xad\x1a\x32\x15\x04\x3b\xcc\x9d\xfe\xff\x33\x15\xf0\xdb\xb8\xf1\x03\x4d\x28\x1c\xab\x52\x04\x0d\x21\xcd\x2a\x98\x84\x33\x12\x25\xb1\x9c\x8a\x13\x40\xa5\x08\x0c\x93\x18\x8a\xde\xce\x2e\x15\xa8\x18\x89\x12\x40\x41\x25\x0a\x97\x68\x82\x90\x50\x46\x82\x1c\x77\x2e\x59\xc0\xa2\x9c\x9d\x44\x29\x96\x8a\x44\x85\xfd\x5d\x6f\xb3\x89\xa4\xb8\x73\x79\x33\x1e\x73\x26\xe0\xf5\xe1\x2b\x26\x2e\x28\x03\x95\x5e\x98\x1e\xa9\x6f\x6a\xcb\xce\xba\x40\x74\x4d\x63\xfa\xb8\xcc\xf3\x35\x27\x8b\x95\xf1\x2a\x93\x61\xe8\x61\x73\xd8\x12\xac\x8d\x30\x2e\x74\x34\xb6\xb9\xd0\x25\x0c\x5f\xf4\x58\xa5\x3c\x1f\x82\xde\x1c\xab\x28\xc5\x06\xfe\xe8\xbc\x6b\x7a\xde\x01\xde\xc8\xb9\x33\xc1\x75\xce\xd2\xfe\x1f\xde\xbd\xb6\x0f\xd7\x2b\xbe\xde\x98\x7a\xed\x1f\xb9\x6e\x01\xd6\x0b\x59\x4d\x36\x74\xbd\xbc\x2a\xf4\x1a\xe3\x96\x95\xa9\xe9\x93\xbc\x5d\x7a\xa9\xcd\x07\x2f\xb5\x67\xb6\x68\xc8\x5a\x01\x6d\xe7\x32\x9d\x22\x35\xcf\xd7\x0b\x45\x82\x40\xb3\x9b\x71\x6f\xfc\x5a\xe2\xda\xba\x8d\x97\x2a\xb5\xb9\x68\x37\x30\xa9\x41\xda\x6f\xef\x86\x21\xb8\x33\xa5\x14\x32\x53\x72\xa5\x30\x6f\xfb\x1f\x9f\x29\x57\xa4\x12\xd8\x6d\xbc\xdc\xad\x26\x47\x50\x6f\x77\x11\xe3\x18\xf4\x3b\x8a\x7d\x47\x31\x04\x45\x7f\xb8\xff\x45\x7a\x33\x8e\xd3\x4c\xf4\x4c\xd8\xde\xdd\x42\x06\x89\x73\x24\x47\x33\x38\x77\x2e\x2f\x0e\xf7\x74\x4f\xa4\x5f\x3d\x28\xd1\x7f\x99\x7e\x59\x23\x37\xcf\x9b\x56\x39\xc3\xe4\xf4\x1c\x57\xc4\xd1\xf5\x6b\xe6\xd1\x46\xc7\x8e\xbd\x2a\xad\xde\xb1\xbe\xd2\xea\x0d\x40\xe6\x05\xe4\x5d\x38\x11\x42\x9c\x38\xfc\x6f\xe7\xc4\x3c\x9f\x99\x7e\x82\x22\x37\xfd\x7b\xf0\x9c\xe9\xf2\xf6\x6b\x8c\x67\xcb\x93\xee\xc6\x46\x14\xb1\x47\x55\x92\xe0\x11\x33\xee\x02\x99\x60\x85\x08\x96\x8c\x0c\x11\xac\xfc\x48\x46\x86\x0c\x56\x74\x24\x23\x43\x05\x4b\x27\x92\x91\xa1\x83\x05\x1f\xc9\xc8\x30\xc1\xca\x8a\x64\x64\xd8\x60\xc5\x44\x32\x32\x5c\xb0\x34\x21\x19\x19\x0c\x0d\x56\x54\x24\xa4\xf3\xa1\x76\x21\x21\x9d\x0f\x45\x09\x09\xe9\x10\xc1\xe3\xff\x84\x74\xc8\x60\xd5\x42\x42\x3a\x54\xf0\xc0\x3e\x21\x1d\x3a\x58\x67\x90\x90\x0e\x13\x3c\x62\x4f\x48\x87\x0d\x56\x06\x24\xa4\xc3\x05\xcf\xe0\x13\xc6\x41\x34\x78\xb8\x9e\x90\x4e\xf0\xd4\x3c\x29\x9d\xe0\x71\x78\x52\xbd\x02\xc7\xd0\x44\x42\x32\x64\xe0\xb8\x3c\x21\x19\x2a\x70\x7e\x9a\x90\x0c\x1d\x38\xf5\xbd\xcd\x8b\x50\x6e\x52\x77\x7a\xfe\xb9\xb1\x27\x64\x2b\x7b\xbc\x82\xdb\x88\xf7\x81\xa4\x5e\x4f\x1c\xa1\xf6\x31\xf2\x1f\x2e\xd8\xfd\x0e\xca\x7f\xbf\x38\x46\xaa\x42\x81\x27\xe4\x8b\x6a\x19\xf3\x54\xc7\xe0\x4f\xc8\xb5\x25\x20\x77\xa8\x01\x8f\xb6\x9e\xb7\x52\x39\x5c\x90\xff\x5a\x2f\xbe\xf5\xfc\x95\xd5\xe1\x02\xfd\xd7\x7a\x71\xac\x77\xba\x12\xdc\x5f\xe0\x1f\xad\x97\x42\xf3\xbd\xf5\x52\x8c\x40\x02\xeb\xdd\xf8\x11\x91\x48\xeb\xed\x16\xc0\xfb\x8b\x7f\xe3\x5e\x3c\xeb\x9d\x2c\xb3\xf7\x17\xf4\xbf\xd6\xbb\xc2\x7a\x7e\x72\xb1\xbf\x08\x99\xb9\xff\x5a\x2f\xd2\x7a\x7e\x2a\xb4\xbf\xf8\x77\xe6\x5e\x61\xbd\x5d\xe2\xb6\xbf\xf8\x77\xc5\x12\xcb\x7a\xa7\x69\xe6\xfe\x22\x64\xc5\xf2\x2f\xe6\x86\x58\xef\x24\x99\xdd\x5f\xfc\xeb\x7b\xb1\xac\x77\x9c\x7b\xef\x3f\xb3\x47\x05\xd5\xea\x42\x57\xa0\xe5\xe9\x9e\xec\xc1\x54\x57\x47\xef\xf1\xd0\xb4\xc3\x70\xb9\xba\x3b\xe5\x03\xb4\xd7\x58\xcd\xdf\x23\xd8\x7f\x26\xef\x6a\xb5\x14\x8e\x77\x77\xab\x5d\xd8\x6f\x08\x79\x73\x65\x8a\xf7\xb7\x5c\xf5\x2e\xbe\xa4\x7b\x1a\x91\x6f\xc0\x09\x3d\x25\x61\xa3\xf7\xad\x2e\x12\xc2\x03\x84\xa2\xb6\xf5\x2e\x12\x22\x02\x7b\x05\x89\x09\x91\xc1\x4d\x87\xa4\x84\xa8\x40\xfe\x9d\x58\x22\x3a\x98\xc8\x27\x25\xc4\x04\x72\xda\xc4\x12\xb1\xc1\xe4\x38\x29\xa1\x0f\x79\x62\x52\x42\xa7\xe7\x26\x69\x1c\xe9\xf4\xe4\x84\x4e\x43\x09\x0f\xe6\x71\x89\x29\x05\x73\x9a\xe4\x32\x91\xc1\xec\x28\x31\x25\x2a\x90\x29\x24\x97\x89\x0e\xe6\x1c\x89\x29\x31\x81\xf5\x77\x72\x99\xd8\xe0\x4a\x3e\x31\x25\x2e\xb8\xaa\x4d\x1c\x2b\xd1\x00\xa5\xc4\xda\x9d\x9e\xa6\xa4\xb1\xd3\xe9\x79\x4a\x1a\x3b\x9d\x9c\xa8\xb0\xd1\x67\x18\x97\x09\x91\x81\xb5\x5c\x62\x42\x81\xe5\x4d\x72\x89\xe8\x53\x42\xd1\xe7\x2a\xd7\xbe\x7b\xf5\x16\x27\x2b\x97\x5e\x54\x77\xcd\xd9\x4a\xe4\x9b\x56\x6f\xb0\x12\x39\x7e\xfb\x17\x8e\x32\x14\x49\x10\x94\xa2\xb2\x1c\x07\x15\x8a\x53\x80\xcc\x49\x04\x25\xb3\x1c\xc0\x14\x48\xa3\x80\x41\x29\x52\x46\x51\x5a\x91\x48\x56\x86\x18\xae\xc8\x14\xca\x62\x80\x96\x24\x99\x52\x1f\x9e\x10\xef\x71\xfe\xe4\x39\xc6\x51\xa5\x1e\xb7\xab\x50\x8a\x7e\x28\x8e\x3b\x53\x0f\xbe\xbb\x7b\xb2\x0e\xf2\x4a\x9b\x0a\x94\xf1\xe2\x74\x15\x7d\x50\xeb\x2a\xc3\x37\xa7\x6f\xb6\x8b\x19\x47\x92\x07\xe8\x3c\x3b\x57\xe5\x4c\xa9\x2c\x8c\x7b\xfa\x6c\x99\x2f\x4d\xdc\xaa\xbc\xa1\xdb\xc9\x2d\x7d\x2b\x06\x2a\x6f\x32\x87\x8f\x82\xfb\xaf\xf5\x26\xd2\x15\x58\x03\xe3\xd7\x75\x15\x74\xea\x1c\x9d\x79\x57\x6d\x0e\xa2\xb2\x61\x89\xc3\xfe\x7b\xa6\xf7\x32\xcd\x1b\x65\x66\xba\x9c\x1e\x55\x7e\xef\x4b\x8f\xfc\xbf\x1e\xdb\xd1\xf2\x86\x4b\x9e\xea\x2a\x42\xbf\x3d\x61\xa6\xb5\x99\x3e\xe3\xe7\xc3\xcd\x54\x22\x69\x5c\xc9\x57\xe8\xc7\x4e\x53\x5d\x32\x53\x1d\xc7\xf1\x5e\x8e\x59\x18\xfd\x8c\x43\xbe\x9b\xe8\x4b\xbb\x55\x77\x32\x44\xae\xb0\x99\xbc\xaa\xbc\xd3\xc7\x29\x2b\xff\x22\xcb\xcc\x40\xe9\x8b\x8b\x49\x43\x6a\x89\x39\x7e\xf5\xf3\xe7\xc3\x71\x99\xd7\x71\x2d\x78\x23\x4c\x37\xfe\xd0\xfe\x50\x9b\x98\x73\x1b\x1d\xa9\x21\xcd\xc7\x73\xac\x8b\x2b\x63\xaa\x8b\xcd\xdf\x30\x38\xab\xca\x05\xcc\x59\xbf\xb6\x06\xe5\x21\xb7\x12\xc6\x46\x2b\x03\xe0\x5e\x37\x9e\x2f\xb1\x62\x56\x3d\xd8\xb6\x10\x5e\xdc\x24\x44\x55\x3d\x65\x6e\xcc\x3f\x38\xb6\xf1\xf8\xbb\x1f\xab\x01\xf9\xb3\x0b\x83\x30\x1c\x92\x7a\xcb\xd6\x85\xb5\xd9\x78\x26\x8c\xa2\xf8\xf8\x8e\x31\xcd\x8d\x66\x63\x33\xb5\x9a\x1f\xcc\x1b\xbd\xb1\xb5\x68\x3d\xb6\x3d\x52\x6d\x79\x8a\x92\xee\xc7\xf1\x5e\x9e\x8f\x7f\x91\x55\x6c\x42\x40\xfe\xab\xf9\x0f\x41\x96\x4c\xc1\xbf\x1a\xe0\x9f\x59\x80\xac\xd4\xed\x0f\xf1\xdc\xac\xdf\x03\x56\x97\xee\xac\x57\x52\x8f\x28\x88\x2f\x63\x53\x27\xf8\x56\x76\x52\xca\x9b\x94\xb4\x6e\x95\x7a\x5e\xd5\xf7\xeb\x0a\x7d\x61\x0f\xfc\xe5\x94\xfa\x5f\xcd\x5f\x79\xef\xe5\x13\xf2\x3f\x9a\x4b\x63\x3e\xc4\x17\x92\xd8\xa2\x66\x1c\xe8\x0d\x3e\xdb\x16\xaf\x2b\x54\x14\x92\xf1\xf7\x6c\xf1\xdf\x7b\x05\x2d\x77\x4b\xc1\x7d\x4f\xf3\xae\x86\x36\xce\xbf\x5b\x88\x75\xa1\xe4\xf2\x3a\xe3\x08\x0b\x15\x55\x42\x09\x92\x43\x55\x4c\x05\x00\xb2\x0c\xbe\x5d\x88\x61\x38\x2d\x29\x0c\x83\x02\x95\x85\x8c\xba\x05\x3e\x99\x85\x28\xcd\x12\x32\x04\x14\x05\x58\x00\x08\x0a\xd0\x12\xa0\x51\xe0\x61\x61\xaa\xf7\xbb\xed\xb1\x90\x3e\xd4\xa5\x47\xa2\x1d\x85\xe3\xd1\x8f\xcc\xee\xee\x9e\x64\xe0\x69\xb1\x30\x18\x24\xee\x8e\x85\x62\xbb\xca\xbe\xb4\xfa\x7d\xc9\x2a\x93\x99\xcc\x72\xf3\x4c\x6f\xd8\xc6\xd6\x9d\x99\x05\x55\x84\x5d\x72\xa8\xbe\x02\x55\x2b\xea\x7d\x05\x9a\x4a\xbb\x62\xf7\xb1\x65\x4d\x6a\x8c\x8b\xb9\xf2\x2a\xdf\x6a\x60\x52\xd7\xc9\xd5\x9a\x6f\x39\x6b\xf2\xc2\xcd\x5e\x9b\x90\x2c\x8e\xb5\x66\xa6\xf1\xcf\xc0\xc2\xa2\x8c\x4d\x52\x63\xd1\xed\xf8\x47\x00\x40\x6c\x2c\xfc\x85\x58\x94\x1a\x0b\xd5\xfe\x98\xfd\x95\x58\x18\xc0\xa2\xd0\x47\x56\xef\x19\xff\xfb\x18\x99\x49\xc8\x3f\x14\x0b\x7f\x11\x16\xdd\xc4\x16\xaf\x2b\xb4\x32\x4e\xc6\xdf\xc7\xc2\x7b\x05\xad\xcf\xc4\x42\x99\xa3\x18\x8e\x25\x69\x85\xc0\x68\x0a\xb2\x2a\x89\x33\x18\x8e\xe3\x32\x00\xa4\x0c\x31\x54\x21\x25\x80\xe1\x24\x89\x62\x18\x60\x71\x94\x54\x64\x9a\x95\x58\x0c\x55\x51\x8a\x62\x49\x54\xf5\xb1\x90\xb8\x11\x16\x62\x97\xb1\x90\x60\xce\xbc\x4a\xc5\xbf\x7b\xb2\xf7\x9b\x16\x0b\x83\x0f\x3e\xdd\x1d\x0b\xdf\x65\x62\xfd\xb8\xb4\x1d\xac\xa0\xbf\xf4\x9f\x17\xeb\xe6\x60\xd5\x75\xda\x2c\xc3\x6c\x4a\x5a\x51\xd0\x86\x8d\x0d\x3f\x1e\x14\x1e\xeb\x8f\xa4\xa9\xbf\x09\x55\x7a\xf2\xfc\xc8\x89\xe2\xd8\x70\x16\xad\x7e\xb6\x2b\xb1\x8a\x2a\x15\x80\x9e\xc9\x35\xba\xc2\xf3\x9b\x35\xef\x94\xf4\x81\x96\xf9\x87\xe4\x85\x79\x0e\xf2\xa9\xb1\xe8\x76\xfc\x23\x1e\x6a\xfb\x14\x2c\x4c\x89\x45\xa9\xb1\x70\xd6\x79\xe6\x7f\x25\x16\x06\xb0\x28\xe2\xc9\xac\xfb\xc5\xff\x26\x39\xe4\x12\xf2\xbf\x07\x16\x26\xc5\xa2\x9b\xd8\x22\x90\xa3\x27\xc0\xc2\x7b\x05\xad\xcf\xc4\x42\x95\x46\x25\x95\x61\x68\x4c\xa1\x48\x8a\x53\x31\x94\x65\x70\x1a\x97\x01\xc9\x90\x2c\x2d\x73\x28\xc6\xa2\xac\x82\x13\x1c\xc9\xd2\x28\x47\xcb\x1c\x4e\x91\x18\x54\x01\x49\x52\xb2\x4c\xaa\x90\x7b\x78\x42\x68\x7f\x8f\x34\x69\x15\xcb\xd1\x1e\x29\x79\x09\x0b\x49\x82\x64\xcf\xbd\x4a\x89\x74\x5f\x3a\x76\x72\xea\xe8\xf9\x6c\x99\x7e\x85\x1a\xf1\x3a\x37\x4a\x6c\xbb\x30\xcb\x3d\xc3\xb1\x4c\x30\xf5\xbe\x53\x2c\x97\xdf\x7b\x5d\x76\xd5\xd5\x86\x19\x90\x5d\x50\x15\xca\x75\xec\x23\x2c\xcc\x06\x06\xff\x03\x16\x5e\x1b\x8f\xbd\xbf\x00\x16\x82\x1d\x56\x66\xf8\xc7\xd9\x92\x11\x4b\x02\xb1\xb1\x4a\xfd\x59\xb7\xde\x5f\xeb\x98\x39\xc8\x13\xec\xba\x6a\xbf\x4d\x01\x20\xf1\xa9\x69\x35\x1a\x2b\xbe\x31\xe3\x95\x02\x5b\xca\x96\x48\xe7\x71\x58\xe9\x93\x26\x9c\xd1\x32\x3f\xcc\x17\x06\x6b\x86\x50\x87\x9b\x7e\x39\x53\xb4\x16\x5d\xb4\xb9\x14\x0b\x59\xfe\x86\x58\x78\xb4\x84\xbe\x76\x1d\xd0\x21\x5e\xc4\xda\xc1\xb6\x99\xf0\x49\x77\x01\x8b\x6e\xc7\x3f\x38\xb6\xf1\xf8\xbb\x1f\x6f\xbd\x2f\x16\xfa\x86\xb7\x4b\xf1\x2f\x0d\x7f\x73\xd1\x6a\xa5\xe0\xff\x8f\xd8\x23\x4e\xc3\x5f\x54\x0b\xab\x84\xfc\x43\xb1\x30\x9f\xce\x16\xb8\x7c\xa0\x17\xe1\x7f\xf7\xb3\x45\x60\x2c\xae\xe1\xef\x63\xe1\xbd\x82\xd6\x67\x62\x21\x07\x29\x9a\xa0\x70\x0c\x23\x68\x9a\x53\x71\x96\x56\x48\x8e\x42\x21\x45\x29\xa8\xc2\x31\x28\xad\x2a\x24\x06\x50\x89\x00\xa8\xc4\x90\x0a\x05\x29\x0c\xa7\x59\x49\x41\x71\x8e\x85\x0c\x24\x19\x0f\x0b\x6f\xb3\x47\x4a\x71\xec\x65\x2c\x64\x88\xe8\xb7\x4b\xed\xee\x9e\x94\xbb\xa4\xcd\x0b\x83\x67\x5a\x77\xcf\x0b\xf3\x10\x66\xca\x50\x56\x0d\x6a\x89\xd2\x98\xb2\x21\x1a\xaa\x94\x67\xdf\xc7\x35\x7a\x2c\x74\x9a\xac\x36\x53\xa6\x65\x6d\x4c\xe2\x22\x3a\x98\x91\x43\x92\x60\xca\xe6\x2b\x59\x45\x2b\x3d\x35\xa7\x49\x93\x65\x59\xa1\x1f\x97\x46\xbf\x4a\x59\x42\xbe\xd2\xad\x9a\x83\xbc\xf5\x4c\xf1\x77\xc2\xc2\x6b\xd7\x01\x65\x69\x3a\x7d\x3b\xd8\x36\x1f\x3e\xe9\xe2\x63\x61\x4a\xfe\xc9\xce\x2b\xdd\x8f\xa9\xb1\x20\x45\x2c\xe6\xef\x10\xff\x12\xe5\x85\x37\xc4\xe2\x44\xb9\xd0\x2f\x3a\xa3\xbb\x84\x85\x49\x64\x69\x54\x0f\xf4\x3e\x7d\x5d\x94\x62\x5d\xe6\x63\xe1\xbd\x82\xd6\xa7\xe6\x85\x28\x49\x63\x0c\xc0\x69\x99\xc4\x31\x5c\xc5\x28\xc0\x10\x14\xc3\xaa\x14\x07\x01\xc7\x61\x04\x85\xa2\xaa\x2c\x91\x2c\xc6\xaa\x2c\xce\xca\x18\x83\x71\xa8\x8a\x91\x14\x09\x50\x12\x63\x69\xf9\xe1\x09\xa1\x6e\x57\x3b\x73\x31\x2f\xa4\x58\x8c\x8c\xce\x0b\x77\x77\x4f\xca\x2c\xd3\x62\xe1\xc5\xbc\xf0\xd6\x58\x58\xa0\x8a\xd9\x5c\x19\x37\xd5\x67\x86\xa9\x9b\xaa\x3a\x5e\x52\x13\x30\x63\x1a\xe8\x66\xa3\x2e\xa4\x4e\xa5\x22\x72\xf6\xfb\x9c\xd0\x5f\x06\x15\x6e\xd0\xa6\x51\xb3\x62\x2f\x4a\x59\x72\xd0\x5a\xad\xf9\x4d\x77\x69\x77\x8a\x9b\x06\xa1\xbd\x90\xac\xd0\x78\x24\xba\xad\xe7\x45\x49\xd3\xf8\xf1\x0d\xb1\xf0\xa8\xeb\xb5\x58\x54\xa3\xac\x52\xee\x60\xdb\x64\x79\xe1\xed\xf8\xa7\xcd\x0b\x8f\x1a\x5e\x8b\x45\x3c\x33\xb7\xe7\x69\x73\x81\x34\xb9\x48\x66\x5a\x7e\x4b\xc1\x3f\x75\xfc\x67\xe6\xf6\xf8\x28\xfe\x27\x5a\x0b\xa4\xe1\x8f\x99\x35\x39\x21\xff\x50\x2c\x14\xd2\xd9\xe2\x96\xbe\x90\x84\xff\x34\x5d\x5e\x78\xaf\xa0\xf5\x99\x58\x28\x11\x98\x22\x43\x12\xe7\x28\x40\x41\x15\x85\xac\x8a\x71\xaa\xc4\x12\x2c\x46\x43\x85\x65\x51\x85\x62\x08\x48\x01\x7c\x9b\x35\xb2\x94\x04\x29\x59\xa6\x51\x1c\x70\xa8\xca\xe1\x14\x2a\x53\x1e\x16\xde\x2a\x2f\xa4\x2e\x63\xe1\x99\x17\x6c\xb3\x87\xd7\x6b\xfb\xa5\xfd\x69\x71\x30\x17\x18\xf8\xbb\xe3\xe0\xf8\xbd\x91\x27\xd8\xe9\xfb\x18\x16\xcb\x2a\x39\x20\xac\x61\x79\xd0\x77\x16\x96\xd1\x21\x74\xbc\xd2\xdf\x6c\x16\xa5\x56\x5e\x29\xd3\xcf\x39\xca\x86\x6d\xeb\xb5\xd6\x2f\x76\x1e\xe7\xe4\x54\x2b\x75\x61\xaf\x23\x3a\xc5\x35\x03\x4d\xa2\xda\xca\x61\xab\x52\x7f\x51\x7e\x6d\xa3\x4d\x78\xd3\x9c\x30\x05\x0e\x89\xa0\xad\xa7\xc6\xa1\xdb\xf1\x0f\x8e\x6d\x3c\xfe\xee\xc7\xd4\x7b\x62\x29\x71\x28\x35\x0e\x16\x27\xc6\xe2\x57\xe2\x60\x00\x87\xaa\x29\xf5\xbf\x9a\xff\xd2\x5a\x0d\x12\xf2\xbf\x79\x4e\x98\x02\x87\x6e\x62\x0b\x66\x6e\xbf\x76\x92\xf1\xf7\x71\xf0\x5e\x41\xeb\x53\x71\x10\x55\x24\x14\x57\x49\x96\xa6\x69\x0a\xc5\x55\x46\x92\x70\x9c\x41\x49\x0e\x92\xac\xca\xb0\x28\x45\xb0\xa8\x8a\x32\x00\x42\x1a\x32\x28\x29\xd1\x00\xc3\x25\x9c\x52\x48\x56\x66\x24\x8a\xc3\x3c\x1c\xbc\x4d\xdd\x0c\xc5\xd1\x17\x71\x90\xc3\xf0\x33\x3f\x44\xe1\xdf\x3d\x79\xa4\x2c\x2d\x16\x06\x1d\xe3\xee\x58\x98\x79\xab\x76\x88\xde\x4b\x9b\x5e\x58\x38\xc7\x58\xcb\xd7\xc5\x2c\xfb\xb6\x99\x75\x61\x16\x93\xc4\xf2\xa6\x21\x65\x67\x6f\x1b\xa0\x3c\x1a\x8b\xc7\x35\xbb\x60\x0a\xce\x20\xa7\xd2\xc6\x23\xa8\x3f\xdb\x95\xb2\xe6\x0c\x06\x05\x7d\x96\xeb\x2c\xcd\xf6\x58\x29\x6d\x16\xd5\xb7\x96\x2e\x0f\x6e\xfa\x3c\x45\x0a\x2c\xaa\xd0\x6c\x21\x35\x16\xdd\x8e\x7f\x04\xa3\x4f\xc1\xc2\x94\x58\x94\x1a\x0b\x45\xb5\xb0\xf9\x95\x58\x18\xc0\xa2\x08\x46\xf7\x8b\xff\xe6\xa2\xd5\x49\xc8\xff\x1e\x58\x98\x14\x8b\x6e\x62\x0b\x66\x6e\x4f\x56\xc9\xf8\xfb\x58\x78\xaf\xa0\xf5\x99\x58\x48\x2a\x18\x64\x39\x49\xe1\x58\x82\x92\x81\x02\x15\x0c\x43\x81\x02\x08\x20\x43\x8a\x96\x14\x0c\x70\x18\x27\xb1\x90\x22\x20\x21\x49\x24\xc5\x02\x28\x51\x18\x41\xa0\x28\xcd\xe2\x34\x27\xd3\x1e\x16\x92\x37\xc2\x42\xe6\x32\x16\x52\x38\x77\x06\x0b\x29\xe2\x21\xf0\x24\x73\x5a\x28\x0c\x1e\x67\xdd\x1d\x0a\xcb\x39\xdd\x34\x5e\x56\x7d\xb2\xca\x40\x0a\xcf\x28\xce\x10\x28\xa5\x37\xac\x95\x65\x94\x97\x35\xff\xfa\x92\xd3\xfa\xef\x55\xbe\x4c\x6f\xec\xca\x00\xef\x96\x0b\xdd\x65\xbf\x67\x3f\x37\x7b\xf3\xe1\x40\xeb\x97\xa6\xb9\x1a\x2a\x64\x37\x65\xb5\x64\x2c\x1f\xb1\x0d\x69\x3b\x8d\x8d\x39\xcc\xfd\x43\xa0\xb0\x2c\x4d\x67\xa9\xa1\xe8\x76\xfc\x93\x1d\x55\xba\x1f\x53\x43\x61\x4a\x28\x4a\x0d\x85\x29\x4b\x35\x52\x87\xff\x00\x14\x25\x3a\x1e\xfb\x45\xc7\x73\xf7\x80\xc2\xa4\x50\x74\x13\x5b\x04\xb6\xaa\x13\x40\xe1\xbd\x82\xd6\xa7\x3e\x5a\x88\x31\x2c\xc4\x69\x5c\x62\x25\x1c\x00\x99\xa6\x01\x43\xa9\x34\x07\x19\x54\x86\x84\x2c\x31\xaa\xa2\xa2\x18\xa0\x51\x1a\x25\x09\x82\x26\x68\x99\x91\x48\x40\x00\x8c\x61\x71\x82\x26\x71\xff\x87\x04\x6f\x55\x42\x4a\x5c\x82\x42\x86\x65\xcf\xfc\x32\xed\xee\xee\xc9\x1b\x34\xd2\x96\x90\x06\x8f\xb3\xee\x5e\x42\xca\xbd\xe9\xb2\xf5\x48\x40\x50\x04\x83\x37\x33\x67\x9b\x4b\xa3\x24\x69\x82\xa8\x0f\x08\x07\x72\xca\x9b\x95\x1d\x38\x05\x49\x6b\x63\x44\xb6\x37\x79\x96\x1e\xe5\xf9\x63\xb6\x03\xb9\xe7\xe7\x35\x2a\xe6\xd6\x5a\xe7\xd9\x74\x06\x68\x63\x36\x78\x7e\xa7\xc8\x52\x9e\x79\xcd\xa3\x45\x26\x7b\xcb\x47\x0b\x8f\x1a\x5d\xbb\x0e\x68\x0c\xb3\x6f\xfa\xc1\xb6\x11\x7f\x71\xb0\xe8\x26\xfc\x93\x1d\x55\xba\x1f\xab\xfc\x69\x5a\x9b\x64\x8b\x50\x4b\x8b\x85\xbf\xf0\x78\x2a\xed\x51\xe9\x4d\xb6\x88\x7f\xd1\x51\x6d\x28\x16\xe6\xd2\xd9\xc2\xff\xdd\xb7\x88\x27\x1c\xef\x6b\x8b\xe0\x58\x5c\xc3\xdf\xc7\xc2\x7b\x05\xad\xcf\xc4\x42\x00\x25\x9c\xc6\x08\x54\xc1\x18\x8c\x92\x29\xc8\x49\xa8\xcc\x52\x0a\x24\x69\x85\xa4\x48\x1c\x45\x65\x28\xe3\x34\x85\x11\x90\x95\x21\x4a\x03\x09\xa5\x68\x9c\x45\x69\x4e\x82\x00\x65\x38\xc2\xfb\x59\xec\x5b\x95\xcd\x5c\xc4\x42\x8e\xa2\xcf\x94\xcd\xec\xee\x9e\xbc\xb9\x29\x6d\x5e\x78\x11\x0b\x6f\x9d\x17\xbe\x60\x7c\xdb\x30\x08\x45\x28\x72\x8f\xcc\xf3\x73\xed\xd5\x2c\x15\x9d\x5e\x36\x67\x57\x9e\xd1\x6a\xa7\x31\x93\x5e\x3b\xad\x46\x16\x7f\x2c\x11\xed\xae\x30\xe3\xe4\xc9\x9b\x65\xbe\xad\xa9\x42\x81\xde\xbc\x8a\x6c\x49\x9c\x11\xa5\x21\xf3\x5c\x6c\xf1\xa8\xa0\x36\x33\xf8\x7a\xc8\x75\xab\xd9\x1b\x96\xcd\xf0\x29\x1e\xed\xab\x51\xd6\x4b\x5a\x2c\xbc\x21\xff\xb4\x58\x78\x74\xdc\x99\x24\x16\xfb\x6b\xa3\xe4\xf1\xef\x17\xc6\xdf\xd4\x6b\x81\x5b\x94\x8a\xfc\xa2\xb5\x48\x28\x16\x66\xd3\xd9\xe2\x96\xbe\x90\x76\x2c\xae\xe1\xef\x63\xe1\xbd\x82\xd6\x67\x62\x21\x4e\x30\x24\xdc\x02\x11\x27\x71\x50\x65\x14\x09\x70\x80\x52\x24\x82\x20\x38\x89\x61\x55\x05\xb0\x2a\x41\x32\x0c\x23\x61\x40\x25\x08\x09\x90\x34\x0b\x14\x4a\x46\x15\x95\xdb\xc2\xa5\xe2\xfd\x96\x25\x96\xe6\xb5\xbb\xde\xeb\xad\xcf\x41\x20\x89\xd2\x28\x11\x59\x2f\xe3\xde\x3d\xfc\xde\xaa\xf7\xa6\x40\x1f\x01\x2b\x6c\xb1\xb1\x6c\x4c\xa5\x32\x5e\xe4\x89\x5e\xf7\xb5\x69\x95\xe7\xaf\x7d\x14\x55\x0b\xac\x5d\x29\x31\x73\x54\x68\xae\x5e\x7a\xcf\x7c\x9f\xe0\xf7\x08\xe8\xb9\x53\x60\xc8\x3f\x44\xcd\x6b\x11\xb0\x46\x59\xe5\x63\x7a\xdd\xe5\x2a\xcf\x6d\x6f\x09\xd9\xdc\xfb\xdb\x72\xda\xc8\x34\x0c\x91\x7f\xd1\xd4\x7a\xb3\x9f\x33\x2a\x93\xa5\xb3\x91\xdb\xc4\x2c\x5f\xcf\x36\x28\x6c\x3c\x55\xec\x7c\x11\x64\xc4\xde\x0a\xa5\x5a\xcf\xdd\x49\x0f\xed\x8f\xa7\x16\x9a\xcd\xd4\x05\x52\x04\xf9\x2e\x5e\x9e\xcb\x36\x31\x5c\x55\xe6\x9a\x44\xb6\x9b\x56\xb5\x12\x03\xf9\x4e\x5c\xfa\x14\xf9\x8e\x74\xf6\x7e\xc2\x98\x0f\xcc\x76\xed\x39\x83\x56\xd0\x97\xc2\xc6\x99\xac\x44\x6c\x36\x40\xc1\xc6\x34\x30\x4e\x2c\xae\x97\x95\xec\xa6\x46\x39\x19\x41\xce\x7a\x3a\x12\x63\xc7\xaa\xe9\x83\x67\xff\xa1\x72\xf7\x2f\x51\xc1\x60\x0a\xfe\xa2\xb5\x69\x77\x52\xf0\xe7\xf9\x5f\x87\x7c\xa1\x91\x37\x93\xdc\x16\x35\x7d\x78\x56\xcd\x4b\xb6\x48\x3b\x16\x5b\x5f\x78\x94\x03\xf4\xae\xb2\xc5\x7f\xc7\x2c\x6d\x51\x02\xdf\x29\xe7\x1a\xd9\x81\xfe\x8e\x76\x57\x74\x96\x94\x18\x59\x17\x38\xaa\xd9\x5e\x4d\x6b\xca\xe0\xa5\x28\x65\x9a\xf8\xb8\xdd\xb5\xc5\x5a\x67\x89\x0d\xba\x4e\x9e\x7c\x29\x73\xfc\xb8\xbd\xae\xe5\x7a\x93\xae\xa2\x99\x7a\x45\xc4\xe5\x2c\x65\xcc\x1f\x05\x14\xbc\x67\x3f\x79\x47\x0e\x83\x0a\x8b\x73\x34\xa6\x4a\x28\x46\x28\x04\xa7\x72\x34\x00\x0c\x24\x71\x56\x26\x31\x86\x94\x01\x20\x01\x05\x48\x42\x91\x64\x9a\x62\x30\x02\x10\x8c\x42\xd2\x0a\x47\x43\x48\xc9\x04\x46\x1e\x7e\xb9\x3a\x45\xe4\xc5\x2f\x47\xde\xe8\x23\xa9\xdd\xcd\xe3\xf7\xa1\xa6\x8d\xbb\x67\x0a\xf6\xbd\xbf\x04\xab\xdf\xa8\xb8\xbb\x28\x4e\x88\x06\x33\x34\xa5\xc5\x6c\xf5\xb8\x7e\x37\x19\x11\x56\xeb\x8a\x3a\x10\x2c\xf1\xfd\xa5\x66\x2d\x1b\x1a\x5b\xa8\x4d\x45\xa6\x37\x56\x57\xad\xfa\xf8\xbd\x28\xd7\x85\x67\xe1\xd9\x66\xb3\x95\x67\xbe\x61\xbd\x66\x9c\x15\x4a\x33\xa0\x33\xe4\x97\x06\xe8\xaa\x18\x6e\x64\x1b\x99\x7f\x56\xdc\x4d\x1b\xf7\xd2\xce\xf5\xea\xaa\x32\xb7\x6f\x18\x77\x3f\x73\x95\x79\x71\xc5\xfb\x89\x71\x8f\xbf\x51\xdc\x4d\x8a\xc1\x7e\xdc\xb5\x26\xa4\x82\xd6\x70\xd0\x63\x4c\xb9\x6e\xcb\x34\x7c\xef\xbf\xe6\x88\x3e\x9e\x29\xbf\xcb\x9b\xf6\x1b\x83\x96\x96\x99\x57\x33\x07\x31\xa3\xc8\x0a\xaf\x64\x75\x4d\xe4\xd6\xf5\x75\x9d\xa9\xf3\xda\xf3\x4a\x28\x93\x2b\x49\x16\x6b\x0b\x7c\x56\x68\x54\xe8\xc2\xac\xcf\x29\x6f\xfc\x94\xbf\xc9\xee\xcf\xe9\x3b\x98\xbd\x1f\x22\xb1\x1d\xe0\xd8\xc7\x9f\x47\xe6\x14\x6e\x76\xef\x32\xce\xd6\xc4\x56\xbb\xc9\x97\xc4\x4b\xaf\x5d\xe6\x2b\x6d\xa1\xe9\xbf\xfa\xb8\x26\x56\x06\xc7\x14\x7f\x43\x10\x04\xe1\x73\xb9\x23\x6a\x1f\x18\x22\xf5\x66\xa9\xca\x37\x07\x48\x59\x18\x20\x5f\x35\xe5\x83\xb4\x63\xc3\x32\x47\x73\x6d\xbc\xfb\x6d\x8e\xc0\xf5\x8d\xa4\x0e\x50\x0d\x93\x3c\x8c\xf1\x45\xe9\x77\x28\xe7\xaa\x6d\x07\x2e\xbd\xff\x8d\x64\x43\x81\xa3\xc3\xaf\xc3\xf8\x1f\x35\xdb\x5e\x40\x6b\x74\x13\xed\x4e\xd9\x86\x29\x97\x48\x30\xa4\x23\x96\x1a\x1d\x01\xf9\x7a\x68\xfe\x84\x1c\xda\xef\x3e\x7b\x1d\xae\x34\xcd\x6d\x86\xf5\x6a\xc5\xaf\x1a\xd4\x88\x5f\x99\xbd\xf0\x4b\xae\xb7\xd5\x2c\x9c\xc9\x39\x4d\xcf\x88\x15\x5b\xf3\xc8\x37\xc1\x5f\x7c\xd7\xfa\x6d\xb5\x8f\x62\x73\x4e\xff\xb3\xa2\x5d\xb4\x80\xe7\xd2\xd2\xc6\xf5\xf6\x9d\x22\x25\x31\x27\xf4\x2f\xe8\x90\x6d\x0a\x7c\x5b\xf0\x9a\x9e\x52\x41\x6a\x62\x70\x32\x74\x5a\x25\xb1\x80\x48\x8e\x05\xe1\xf1\xec\x8a\x96\xc6\x9b\x63\xe9\xe5\xf1\xe8\xc4\x93\x28\x62\x5e\x4b\x9b\x91\xff\x83\x46\x89\xc5\x39\x90\x38\x96\xe4\x24\x53\x38\x95\xc7\x6b\xfc\x84\xf8\x1f\x46\x36\x7c\x5b\x40\x5d\xfe\x68\x30\x69\x33\x9a\x00\x7b\x92\x46\xb2\x6d\xff\x78\x62\x1d\x7b\xda\xb6\x57\x98\x34\x33\xa8\x8c\x53\x0c\xdc\x9e\x42\x3c\x89\xbc\xb6\x7b\xf3\x3c\x21\xc0\x34\x67\x9a\xec\x85\x03\xc3\x52\x22\xc2\xf4\x08\x6e\x7d\xc3\xbd\x9f\x40\x52\x1f\x25\x3c\x81\x03\xe4\x8e\xc5\x86\xaa\x0a\xe5\xa0\xab\x7d\x8c\x5a\x9a\xf2\x84\x7c\x71\x3b\x7f\x89\x12\x56\x53\x6e\x24\xa6\xa6\xc4\x16\x70\xe7\x7a\x5b\xf1\x12\x08\x6d\x98\x23\xf3\x56\x72\xfb\xb4\x8e\x45\x8f\x80\xaa\x44\x9a\x84\x2b\xe0\xac\x6f\xa7\x80\x4f\x2b\xc2\xa7\x13\xaa\x70\x4c\x21\x4c\x09\xc3\xdc\x7a\xe5\xc4\x48\xa4\x83\x2f\xfc\x81\x46\x52\xe3\x9f\x37\xb4\xed\xcf\x76\x37\x54\xa7\xb7\xf5\x29\xb9\x63\x91\xbd\xef\x03\x32\x86\x4b\x74\x6c\xd7\x5b\x89\xf5\x81\x66\xbc\xf0\x16\x26\xa0\xe3\x0d\x89\x93\x66\x58\x0f\x34\x92\xbb\xe4\x25\xf7\x73\x2c\x65\xcb\x44\x02\x36\x4c\x8d\x9f\x61\xc4\x02\x92\x2b\x30\x20\xe7\x71\xdb\x8b\x02\x1a\xaa\x9a\x02\xb4\x3e\x92\x8a\x25\x9c\xdb\xf2\x9c\x68\xae\xec\xd0\xba\x99\xf9\x02\xf4\x2e\x09\x19\x68\x1e\x47\xd2\xdb\xd8\xf1\x84\x5a\x5c\x29\x2f\x5a\xf3\x36\xb2\xc5\x92\xe9\xbc\x2c\x3b\x89\x67\x86\x31\x5d\x98\xe9\x24\x3a\xa5\x15\x7b\x44\xbd\xf5\x6e\x84\x7c\x26\xd0\xac\x91\xa3\xcd\xe1\x4d\x24\x0c\x52\x8b\x37\x6f\x7d\x01\x9f\x90\xa0\xc8\x4f\x88\x1f\xe2\xe5\x99\x61\x43\x65\x04\x9c\x08\x25\x6e\x10\xb7\x7d\x3a\x97\x24\xbe\x72\x75\xb4\xa5\x7a\x33\xeb\x5e\x61\xd8\x8b\x76\xd3\x74\x05\xae\x47\x81\x25\x87\x3d\x32\xf4\x11\x50\x14\x0b\xda\x76\x5a\x83\x5e\x64\x70\x92\xa7\xf9\xb7\x03\x99\x91\xd7\xf0\x0a\xd9\xd3\xfb\xc1\x39\xda\x97\x25\x0e\x99\x65\xa7\x04\xfd\x55\xf8\x96\x9e\xb3\x31\x93\xe7\xe0\x67\xa9\x5e\x5c\xf6\x6f\x1b\x5d\x10\xd4\x5f\x43\x6d\x49\xee\x9d\xe8\x46\xd2\x86\x91\xbe\xb8\x7c\x8b\xeb\xc9\x47\xc4\x6f\xed\x0c\x27\xa4\x93\xac\x37\xa3\xc9\xcd\x4d\xc3\xda\x06\xbe\x25\xb4\x6c\xcd\xd0\x6f\x6f\xe8\x20\x87\xcb\xe2\x07\x3a\xc4\x57\xc6\x0f\x3d\x09\x77\x2a\xe2\xd9\xff\x88\xc7\x45\x4d\x8e\xda\xc6\x57\xc2\xb4\xe0\x52\x33\x16\xf6\xa7\x68\x13\xc6\xec\xa2\x5a\x61\x9d\xe2\xeb\xb7\xdb\x44\xb9\x9b\x4e\x3b\x06\x17\xf5\x88\xdc\xed\x3a\x25\x7d\xf8\x81\xf3\x7b\x4c\xed\x20\xf5\xd0\x04\xf8\xda\x09\x7e\x4a\xf4\x34\x85\xba\xd1\x0c\x3f\xc7\x22\x8e\x0e\x17\xf2\xba\xb3\xcc\x6e\x07\x5f\x1f\x09\xc7\x92\xfd\x32\x88\x1d\x27\xdb\xf7\x70\x9b\x8f\xf4\x13\xa7\xfa\xee\x22\x6e\x0f\xe4\xbb\x1d\xc6\x91\x64\x18\xd3\xc4\x56\x3e\x43\xf3\xe2\x12\xe1\xeb\x57\x05\x3a\x40\x9b\xd9\xc8\xf7\xff\xfc\x07\x79\xb0\x8d\x99\x72\x74\x9a\xf6\xf0\xe3\x87\x03\xd7\xce\xb7\x6f\x4f\x48\x74\x43\xd9\x50\xe2\x35\xf4\xf6\xe2\xa3\x9b\x4a\xc6\x62\x3c\x71\x62\xb1\x3f\x69\x7a\x5e\x80\x93\xa6\x01\x11\xbe\x21\xbd\xa2\xd0\x14\x3c\x27\x43\x7e\x22\x04\x11\xfb\x20\x5a\x53\x46\xea\xd1\x31\x51\xbe\xfc\x39\xc7\xd1\x3e\x5b\x24\x5f\x6b\x0a\xa5\x82\xb8\x3f\x02\x42\x9a\x42\x5e\x68\x0a\x62\x56\x68\x05\x4e\x45\xdc\xbb\x35\x11\xe9\xd4\x73\x5b\x97\x69\x0a\xad\x76\xb3\x94\x6d\x6f\xbf\xca\x09\x15\xa1\x2d\x20\x59\xbe\x95\xe5\x73\xc2\x99\x73\xb4\x6d\xde\x71\x7a\x39\x0a\x6c\xc5\xdc\xce\x18\xa7\x7c\x2e\x1c\x92\x45\x49\x72\x6a\x9f\xe0\xb6\x51\xa8\xb1\xfc\x85\xfe\x85\x13\xc5\x48\x4b\xf8\xa9\xec\x2f\xb7\xc3\xb1\x1c\x61\x56\xd8\xed\x12\x9c\x77\x98\xeb\x2c\xf0\x71\x53\xe9\x17\x9a\x21\x42\x98\x53\x5b\x84\x6c\x83\xdd\xd6\x29\x82\x5b\x1c\xff\x04\x83\x44\xbb\xc6\x87\x3d\xa4\xb8\xde\x51\x37\x6c\x67\x6c\xc1\x56\xa3\x82\x28\xc0\x01\x5b\x17\x43\x94\xc5\xdc\x44\x64\x63\x6e\xce\xa0\x03\x5d\x1d\xfe\xbf\x00\x00\x00\xff\xff\xb3\x37\x36\x37\x33\x03\x01\x00") func operation_fee_stats_1HorizonSqlBytes() ([]byte, error) { return bindataRead( @@ -366,7 +366,7 @@ func operation_fee_stats_1HorizonSql() (*asset, error) { } info := bindataFileInfo{name: "operation_fee_stats_1-horizon.sql", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} - a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xcd, 0x2, 0x73, 0xc2, 0x43, 0x32, 0x66, 0x55, 0x72, 0x78, 0x5a, 0x12, 0x1, 0x30, 0x8, 0x72, 0x44, 0x96, 0x99, 0xd3, 0xf6, 0x85, 0xc2, 0xb7, 0x46, 0xfb, 0xf8, 0x4c, 0x98, 0xf2, 0x49, 0xa5}} + a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x5b, 0x9d, 0x7d, 0x91, 0xa5, 0x8a, 0xcd, 0x89, 0x34, 0xe4, 0x18, 0xb7, 0xc5, 0x9f, 0x9f, 0x45, 0x26, 0xe3, 0xad, 0xc7, 0x1b, 0xa4, 0x4d, 0xba, 0x12, 0x37, 0x20, 0xeb, 0xf1, 0x34, 0x6e, 0x85}} return a, nil } @@ -390,7 +390,7 @@ func operation_fee_stats_2CoreSql() (*asset, error) { return a, nil } -var _operation_fee_stats_2HorizonSql = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\x5d\xfb\x4f\xdb\xca\xb3\xff\xbd\x7f\xc5\xea\xab\x23\x01\x2a\x14\xaf\xdf\xa6\xdf\x1e\x29\x24\x0e\x04\x42\x02\x49\x68\xa1\x55\x65\xad\xed\x75\x70\x71\xec\x60\x3b\x90\x70\x75\xff\xf7\x2b\xbf\x12\xbf\x1f\x49\xda\x73\x7f\x38\xe8\xe8\xa8\xb1\x67\x67\x3e\x33\x3b\xb3\xb3\x2f\xef\x9e\x9c\x7c\x38\x39\x01\xb7\x96\xe3\x4e\x6d\x3c\xbe\xeb\x03\x15\xb9\x48\x46\x0e\x06\xea\x62\x36\xff\x70\x72\xf2\xc1\x7b\xdf\x59\xcc\xe6\x58\x05\x9a\x6d\xcd\x36\x04\xaf\xd8\x76\x74\xcb\x04\xc2\x27\xf6\x13\x8c\x51\xc9\x2b\x30\x9f\x4a\x5e\xf1\x14\xc9\x87\xb1\x38\x01\x8e\x8b\x5c\x3c\xc3\xa6\x2b\xb9\xfa\x0c\x5b\x0b\x17\x7c\x01\xc4\x67\xff\x95\x61\x29\xcf\xd9\xa7\x8a\xa1\x7b\xd4\xd8\x54\x2c\x55\x37\xa7\xe0\x0b\x38\xb8\x9f\x74\xf9\x83\xcf\x11\x3b\x53\x45\xb6\x2a\x29\x96\xa9\x59\xf6\x4c\x37\xa7\x92\xe3\xda\xba\x39\x75\xc0\x17\x60\x99\x21\x8f\x27\xac\x3c\x4b\xda\xc2\x54\x5c\xdd\x32\x25\xd9\x52\x75\xec\xbd\xd7\x90\xe1\xe0\x84\x98\x99\x6e\x4a\x33\xec\x38\x68\xea\x13\xbc\x21\xdb\xd4\xcd\xe9\xe7\x10\x3b\x46\xb6\xf2\x24\xcd\x91\xfb\x04\xbe\x80\xf9\x42\x36\x74\xe5\xd8\x53\x56\x41\x2e\x32\x2c\x8f\xac\xd5\x9f\x88\x23\x30\x69\x9d\xf7\x45\xd0\xeb\x02\xf1\xa1\x37\x9e\x8c\xc1\x70\xd0\x7f\x0c\xe9\x3f\x3d\xe9\x8e\x6b\xd9\x2b\xc9\xb5\x91\x8a\x1d\xd0\x19\x0d\x6f\x41\x7b\x38\x18\x4f\x46\xad\xde\x60\x12\x2b\x94\x24\x94\x14\x6b\x61\xba\xd8\x96\x90\xe3\x60\x57\xd2\x55\x49\x7b\xc6\xab\xcf\x7f\x42\xa0\xe2\xff\xeb\x4f\x88\xf4\xfc\xea\xcf\x29\x18\x48\x6b\xae\x5d\x00\xd0\x73\xe4\x32\x61\x31\xaa\x0d\x73\x9f\xbc\x37\xe8\x88\x0f\x31\xca\x90\xad\x8f\x4a\xc2\x9a\x86\x15\xd7\x91\xe4\x95\x64\xd9\x2a\xb6\x25\xd9\xb2\x9e\xcb\x0b\xea\xa6\x8a\x97\x52\x4c\x39\xd3\x41\xbe\xa3\x3b\x92\x65\x4a\xba\xda\xa4\xb4\x35\xc7\x36\x5a\x97\x75\x57\x73\xbc\x43\xe9\x0d\x92\x9d\x50\x34\x2b\x6b\x60\x75\x8a\x6d\xbf\xa0\x83\x5f\x16\xd8\x54\x1a\xa9\x10\x2b\x3e\xb7\xf1\xab\x6e\x2d\x9c\xf0\x99\xf4\x84\x9c\xa7\x2d\x59\xed\xce\x41\x9f\xcd\x2d\xdb\x0b\xc7\xb0\x4d\xdd\x96\xcd\xb6\xb6\x54\x0c\xcb\xc1\xaa\x84\xdc\x26\xe5\x23\x67\xde\xc2\x95\xc2\xb8\xdc\x02\x74\xbc\x24\x52\x55\x1b\x3b\x4e\x79\xf1\x27\xd7\x56\xfd\xbc\x23\x19\x96\xf5\xbc\x98\xd7\xa0\x9e\x57\x41\x0a\xa8\x90\x6e\x37\x64\x1c\x35\xba\xb5\x0b\x78\xed\x84\xa6\x61\xbb\x1e\x69\xc4\x7e\x8b\x22\xa1\x59\xeb\x15\xf2\x9b\xd6\x06\x42\xe2\x4d\x71\x55\x89\xb9\x57\xe0\xc9\xad\xac\x01\x27\xd1\x00\xc9\xab\x4a\x37\x7a\x5a\x47\x7a\x1d\x62\x2b\xc0\x61\x55\x12\xea\x8e\x2b\xb9\x4b\x69\x5e\xcd\xd2\xa3\xb4\xe6\x75\x29\x71\x5d\xb2\x28\x95\x94\x13\xcb\x51\xb8\x57\x92\x55\xb7\x62\xf2\xaa\x5e\x65\x06\x39\xd2\xb3\xb6\xe3\x2c\xaa\x24\xaf\x89\x15\x4b\xc5\x0d\xfb\x05\x6b\x37\x98\x23\xdb\xd5\x15\x7d\x8e\xcc\xd2\xe4\x5d\x55\x54\x9a\x37\xec\x9b\xac\x33\x5a\x53\x04\xf9\x05\x1b\xcb\xf7\x8d\x57\x47\x5e\x40\xf8\xdb\xf9\x07\x95\xe9\xd5\x64\xf8\x4f\x2f\x3f\x44\x5d\x3f\xdf\x19\xa4\x9a\x08\xa6\x96\x3d\x97\x66\xfa\x34\xec\x30\x94\x40\x48\x51\xd6\xd6\xb1\x79\x7f\xaf\x8c\x73\x5d\xe7\x0c\x4a\xb7\x87\xfd\xfb\x9b\x01\xd0\xd5\x40\x72\x47\xec\xb6\xee\xfb\x93\x9a\xbc\x0b\x9c\x6e\x0f\x9c\xc3\xea\x2e\xe7\xe4\xff\xaa\xaf\x7e\x94\xa5\xc7\xe2\xdd\xbd\x38\x68\x6f\x61\x33\xaf\x9f\xed\xe0\x97\xc6\x92\x13\x4c\x6a\x97\x56\x71\x4d\xda\x4d\x6f\xb6\xb6\x86\x05\x51\xdf\x44\xbf\x7c\x16\xf5\xca\x86\xfd\xbe\x7a\xc4\x61\x27\xaf\xb6\x6e\x61\x0b\xd0\x44\x97\xa0\x48\x4d\xda\xb0\xfb\x57\x1f\x4f\xd4\x5f\xac\x83\x28\xd5\x86\x94\x13\xc7\x9a\x84\x90\xb0\x75\x71\x31\x12\x2f\x5a\x93\x1c\xe2\x99\xee\x8d\x38\x74\x05\x1f\x9a\x8b\x19\xb6\x75\xe5\xc7\xcf\xa3\x1a\xa5\xd0\x72\x8b\x52\x06\x72\xdc\x43\x64\xae\xb0\xe1\x4f\xc5\xd4\x28\xa1\xe9\x76\x6e\x91\xee\xfd\xa0\x3d\xe9\x0d\x07\x25\xfa\x48\x68\x3a\xdd\xa0\x3b\x06\x19\xa0\x25\x3c\x22\xed\x76\xe0\xe1\xe9\xea\x17\xdf\x80\x3f\x06\x4d\x14\xf1\x55\xaf\xc1\x41\x7c\x98\x88\x83\x71\x8a\x85\x31\x9f\x3a\x2f\x46\xe4\x8b\xed\x4b\xf1\xa6\x95\x91\xf0\xf9\x43\x30\x0b\x37\x40\x33\x7c\x16\x3d\x03\x93\xd5\x1c\x9f\x85\x45\x3e\x83\xb1\xf2\x84\x67\xe8\x0c\x9c\x7c\x06\xc3\x37\x13\xdb\x67\xe0\xc4\x9f\x9c\x6b\x8f\x44\xaf\xbe\x42\xce\x11\xbf\x0f\x09\x8e\xc9\x97\x21\xe3\xf6\xf0\xe6\x46\x1c\x4c\x4a\x38\x07\x04\x60\x38\x48\x32\x00\xbd\x31\x38\x88\xa6\xdd\xa2\x67\x8e\xcf\xe4\x20\x2d\x39\x52\x3f\x94\xb9\xb6\x50\xa5\x3e\x09\x5b\x0e\x86\x93\x94\x3d\xc1\xb7\xde\xe4\x72\x0d\x2b\x3e\xff\x96\x10\xbf\xe1\x92\x02\xd2\x44\xf9\x0c\x13\xdf\x00\xb7\xfd\xd3\xf9\x74\x7c\xd7\x07\x73\xdb\x52\xb0\xba\xb0\x91\x01\x0c\x64\x4e\x17\x68\x8a\x7d\x33\xd4\x9c\x2f\x8c\xc3\xad\x76\xb4\x10\x7e\xe4\xab\x1b\xfc\x51\xdd\xe6\xd9\x72\xed\xd9\x95\xfc\xc1\x48\x9c\xdc\x8f\x06\xe3\xd8\xb3\x0f\x00\x00\xd0\x6f\x0d\x2e\xee\x5b\x17\x22\xf0\xb5\xbf\xb9\xb9\x0f\xda\xbb\xf1\x64\xd4\x6b\x4f\x7c\x8a\xd6\x18\xfc\x25\xfd\x05\xc6\x62\x5f\x6c\x4f\xc0\x5f\xd0\xfb\x95\xae\x8d\xca\x40\xdc\x4d\xbb\x2a\xf6\x7b\x53\x8e\xcc\x53\xae\x4e\x4b\xb5\x9b\x7e\x35\x24\xac\x55\x5c\x3f\xda\x4a\xc3\xc3\x0f\x00\xb4\x5b\x63\x11\x7c\xbb\x14\x07\xe0\x2f\xf8\x03\xfe\x3c\xfd\x0b\xfe\x20\x7f\xfe\xfd\x17\xe9\xff\x9b\xfc\x41\xfe\x04\x93\xe0\x25\x10\xfb\x63\xd1\x33\x8a\x38\xe8\x1c\xe5\x5a\xa6\x46\x1e\xd8\xd1\x32\xd5\x12\x7e\xb7\x65\xfe\xbb\x8d\x65\xb2\x39\x35\xb4\xc3\x3a\x0f\xd7\x33\xc4\x26\x6d\x67\x38\xfa\x88\x01\x18\x7b\xb6\x02\x5f\x36\x2d\xc0\x71\xf0\x78\xf2\x78\x2b\x82\x2f\xf1\x88\x38\xca\x8b\xda\xbd\x62\x4c\x33\x4c\x41\x8c\xc2\xb8\x3e\xc2\xdc\x2e\xd0\xae\x28\xf3\x98\xa6\x90\x26\x02\x32\x09\x77\xe3\x65\x59\xb4\x79\xdd\xbc\x9d\xd1\xe6\x30\x4d\xa3\x8d\x07\x49\x29\x5a\x2f\x73\xa9\x58\x43\x0b\xc3\x95\x5c\x24\x1b\xd8\x99\x23\x05\x83\x2f\xe0\xe0\xe0\x73\xf2\xed\x9b\xee\x3e\x49\x96\xae\xc6\x96\xd2\x12\xba\xc6\xfb\xbf\xa1\x8a\x7e\x80\xd5\x53\x2f\x88\xc5\xf8\xe0\x3b\xd0\x48\x57\x81\xac\x4f\x75\xd3\xf5\x3b\x06\x83\xfb\x7e\x3f\x50\x07\xcd\xbc\x6e\x3c\x50\x9e\x90\x8d\x14\x17\xdb\xe0\x15\xd9\x2b\xdd\x9c\xa6\xc8\xcc\xc5\x6c\xdd\xe5\x07\xba\xe9\xe2\x29\xb6\x53\x24\x9a\x81\xa6\x0e\x70\x66\xc8\x30\xb2\x62\x5c\x6b\x66\x64\x85\x1c\x92\x0c\x73\xb4\xa6\xcc\x56\x7b\x7a\xdc\xb0\xad\x39\xd2\xb3\x1d\x6b\x93\xb8\x78\x99\x31\xc8\x7c\x6e\xe8\xfe\x9c\x3d\x70\xf5\x19\x76\x5c\x34\x9b\x03\xaf\xce\xfc\x9f\xe0\xdd\x32\x71\x16\x68\xd1\xa8\x28\xea\x8f\x86\xc3\xa9\x7a\x98\xd7\x83\xaf\x02\xae\xa1\x1b\xb6\x46\x93\xa0\x47\x07\xfd\x07\xbd\x41\x7b\x24\xfa\xdd\xaf\xf3\xc7\xf0\xd1\x60\x08\x6e\x7a\x83\xaf\xad\xfe\xbd\xb8\xfe\xdd\x7a\xd8\xfc\x6e\xb7\xda\x97\x22\x80\x55\xca\x6c\x6d\xf6\x34\xa3\x8c\x2b\x86\x93\x1e\xc0\xc4\x4b\xf7\x15\x19\x87\x07\x05\x1a\x1f\x9c\x9d\xd9\x78\xaa\x18\xc8\x71\x8e\xd2\xd5\x15\xac\x55\xe4\xf8\x16\x4b\x1f\x95\x54\x54\x30\x36\xde\x59\xb3\x60\x46\x67\xad\x57\x7e\x64\x6c\xe6\xea\xf2\x61\xe6\x92\x2b\x96\x9a\x47\x0e\xc9\x7c\xf2\x60\xfa\x2f\xa7\x00\xc3\x96\x45\x58\xfe\xf4\xc2\x9e\xdc\x36\xce\xf3\x8f\x39\x6d\x99\x22\x60\xf8\x6d\x20\x76\xc0\xf9\x63\x85\x46\xc1\x0c\x5d\xb9\x42\x6b\x5e\xa9\xd7\x9f\x74\xb5\x08\x5b\x34\xe7\xb3\xab\xd7\x85\x7c\x42\xb7\x4b\xc5\x8c\x54\xd4\xd2\x67\xa7\xb8\x8a\x28\xff\xe3\x2f\x7c\xfc\xa7\xc0\x9b\x7d\x3f\xce\x7f\xa5\x62\x17\xe9\x86\x03\x7e\x39\x96\x29\x17\x3b\x5b\x34\x51\xb6\xab\x1d\x42\x3e\xa1\x1d\xa2\x75\xeb\x02\x6c\xb1\xc5\xe4\x5a\x51\x98\xb7\x8e\x9d\x5f\x30\x34\x4b\x6c\x66\xd4\xaf\x88\x35\x8e\xa8\x95\x23\x52\x12\x36\x15\x51\x8f\x7e\xbd\x98\x9c\x4a\x4c\xd6\xc2\xdd\xe4\xa6\x74\x19\x1b\x23\xb7\xb2\x50\x40\xbb\x98\xab\xb5\x69\xd7\xae\x13\xfe\x4c\xad\xb3\x67\x74\x81\x99\xfe\x80\x8b\x0c\x49\xb1\x74\xd3\xc9\xf7\x41\x0d\x63\x69\x6e\x59\x46\xfe\x5b\x7f\xe5\x53\xc3\x45\x75\xed\xbf\xb6\xb1\x83\xed\xd7\x22\x12\xaf\x1f\xea\x2e\x25\xbf\x9b\xa4\xbf\x17\x51\xcd\x6d\xcb\xb5\x14\xcb\x28\xd4\x2b\x5d\x47\x91\xb3\x60\xa4\x62\xdb\xef\x5e\x04\xcf\x9d\x85\xa2\x60\xc7\xd1\x16\x86\x54\xe8\x28\xa1\xe2\x48\x37\xb0\x5a\x4c\x55\x1c\x56\x05\x73\xd7\xbb\x46\x59\xc1\x7a\x48\x45\xce\xab\xdf\xda\x54\xb7\x5f\x4d\x55\xde\x6f\x1a\x2b\x95\xf1\xa7\xd2\x5a\x23\x45\x77\x4c\x73\xa5\xb2\xb2\x69\x2f\x9f\xbc\x24\x0d\xc6\x56\x76\xf6\xe6\x9b\x55\xc3\x9c\xe4\xae\xaa\x82\xa1\x90\xd7\xf3\x57\x02\x55\xfc\x0c\xb8\x63\x02\x0c\x23\xdf\x5a\xd8\xca\x7a\x9b\x46\x41\xea\x89\x9a\x93\x83\x83\xb3\xb3\xe2\xa1\x58\x71\x1c\x84\x0b\x6b\xbb\x9a\x33\xdc\x0b\x78\xb8\xd7\xfe\x42\xd8\x24\x6e\x93\xbd\xfc\xbd\x30\x85\x62\x53\x3b\x11\xcb\x88\xc2\xcd\x91\x65\x24\xc1\x38\x38\x97\x20\xbb\xa7\xb3\x82\xae\x54\xdc\x9a\xaa\x44\xa2\x0f\x49\x77\x24\x07\x1b\x06\xb6\x81\x6c\x59\x06\x46\x66\x94\x93\x74\x05\x4b\x66\x22\xff\x06\xcf\x92\x39\x79\xb3\x9b\x48\x4a\x65\xeb\xc4\x7e\xa6\xf4\x4b\xdb\x5a\x98\xaa\xbf\x21\xd8\xd0\xe7\x73\x34\xc5\x59\xa6\xba\x23\xe1\x25\x52\xdc\x24\xae\xd8\xfa\x7e\xee\x96\x51\x5f\x5d\xc9\xdf\x54\x0c\xda\x97\x62\xfb\x1a\x1c\x1e\xc6\x4d\xff\x37\x20\x8e\x8e\xaa\x58\xe5\x15\x8f\xac\xfd\xdf\x4c\x05\xd4\xe0\x97\xa8\x8c\x14\xfb\x54\x4d\xf9\x00\x4b\x63\x30\x7f\x69\x7c\x0f\x51\x99\xbf\xd9\xa1\x66\x0a\xae\xd3\xf6\xed\x92\x84\xab\x36\x16\xec\x27\x0d\x57\x48\xf9\x53\x89\xb8\xa1\xb2\x3b\xa6\xe2\x0a\x69\xd9\x64\x5c\x54\xa0\x24\x1d\x27\x36\x93\xec\xd1\x57\x23\xff\x8c\x43\xaa\x3d\xfa\x0a\x93\x46\xc5\x98\xae\x6e\xc6\x2e\x4f\xbe\xb9\xb4\x1b\xd1\xb9\xf1\xe2\x0d\x1f\x8a\xc7\x1f\x45\x23\xbb\x7f\x64\x6c\xe6\x2e\x25\x6c\xbe\x62\xc3\x9a\xe3\xbc\xf9\x4e\x77\xe9\x8d\x94\x16\x86\x5b\xf0\x72\x86\x5d\x54\xf0\xca\x1b\xa3\x15\xbd\x76\xf4\xa9\x89\xdc\x85\x8d\xf3\xa6\xe6\x04\xf6\xe8\xc7\xcf\x4d\xa7\xe7\x7f\xfe\x37\xaf\xdb\xf3\xe3\x67\xda\xe6\x78\x66\x15\xcc\xa2\x6d\x78\x99\x96\x89\x4b\x3b\x51\x1b\x5e\x59\x36\xa1\x66\xfa\x0c\x4b\xb2\x97\x06\xfd\xa9\x6e\xde\x46\xe6\x14\x27\xdc\x32\xff\xe5\x4c\x37\xa5\x02\xef\x29\x26\x90\xd2\x19\x36\x97\x28\x94\x3b\x45\xf3\x04\x2d\x5e\xba\x36\x92\x3c\x53\x63\xdb\xf1\x6b\xe1\xc7\xcf\xf4\x78\x33\x99\xa4\xbd\x2a\xf3\xd4\x9e\x62\x35\x39\xec\x34\xf1\x9b\x94\x72\xea\xaa\xd9\x42\xa0\xab\x51\x7b\x11\xed\x5e\xab\xd3\xc8\x05\x0d\x86\xbf\x55\xb0\x62\x63\xdc\x58\x9c\x94\x4c\x11\xc7\x27\xe3\xe2\x13\xc4\xcd\x86\x50\xfb\x53\xa2\xe6\xbe\xc1\x52\xa5\x4a\x87\x5e\x75\x94\x2c\xec\x2b\xec\x4d\xcd\xda\x5b\x2f\x4b\x15\xad\x48\x6c\xf9\xaa\x76\x90\x8b\x80\x66\xd9\x15\x0b\x65\xa0\xd3\x9a\xb4\x2a\xd4\x2b\x60\x59\xb6\xe0\x54\x87\x6d\x6f\x30\x16\x47\x13\xd0\x1b\x4c\x86\x99\x45\x27\xbf\x8b\x31\x06\x87\x07\x50\xd2\x4d\xdd\xd5\x91\x21\x05\x1b\x80\x3e\x39\x2f\xc6\xc1\x31\x38\x20\x09\x28\x9c\x10\xec\x09\x41\x01\xc8\x9f\x91\xfc\x19\xcd\x7d\x22\x28\x92\x16\xd8\x8f\x04\x79\x70\xf4\xb9\x1e\x77\x52\x0a\x3e\xec\x48\x58\x55\x5e\x49\xae\xa5\xab\xe5\x92\x04\x96\xe1\x9a\x48\xa2\xa4\x85\x83\x37\x6d\x94\x6e\x66\x3e\x26\x29\x95\x47\xd3\x04\xcd\x37\x91\x47\x4b\x48\x55\xa5\xf4\x94\x5c\xa9\x0c\x86\x66\x28\xb2\x89\x0c\x46\x0a\xb2\x72\x34\x3e\xf0\x97\x72\x4b\x45\xb0\x14\x41\x36\x52\x83\x8d\x44\x84\x2d\x58\x0d\x11\x3c\x0d\x99\x26\x22\x38\x69\x66\xa9\xba\xb6\xaa\xaf\x05\x0f\x59\xb2\x91\x08\x3e\xa1\x45\xb8\x83\xbb\x86\x1c\x8e\x66\xa9\x66\x72\xbc\x4a\x47\xd3\xa9\x8d\xa7\xc8\xb5\xec\x72\x9f\x12\x08\x48\x08\x4d\xd8\x0b\x3e\xfb\x60\xba\x56\x5a\xaa\x76\x39\x77\x92\x83\x8d\xaa\x1a\x12\x3e\xfb\xb0\x16\xfc\x41\x7a\xb9\x00\x46\xe0\x1a\x59\x07\xc2\xb8\x80\xf5\xe0\xcd\x6b\x00\xca\x05\x09\xac\xd0\x4c\x13\x32\x51\xd1\xe1\x70\x39\xf8\x66\xb8\x4c\x12\x24\x38\x86\x6e\x54\x23\x90\x0a\xd4\x59\xcf\x4e\x94\xd6\x38\x84\x24\xc7\x36\xd3\x84\x96\x34\x7d\x19\x7d\x3f\x61\xcd\x0c\x49\xd3\xb1\x51\xda\x34\x42\xc8\x40\xd8\xa8\x11\x86\x4c\xd4\x65\x8b\xa6\xf3\x97\x15\x6a\xb0\x5c\xb3\x66\x1e\xb2\x92\x6e\x4e\xb1\xe3\x4a\xd9\x05\x83\x0a\x51\x9c\xc0\x37\xab\x11\x2e\x91\xae\xfd\x95\x19\x54\x9e\x4c\x20\x49\x10\x14\x1d\x0a\x29\xc8\xb5\xa5\xdb\x0c\x9a\xe4\xf0\x46\x5b\x30\xbc\x6e\x49\x05\xdf\x70\xdb\xda\x66\xc7\xe9\x27\x07\x97\x6f\x4f\x38\x06\xf0\x38\xd8\xcb\x53\x43\xdd\xec\xce\x83\x1d\x94\x2d\x5d\xed\xde\x8b\xaa\x89\x6e\x76\x13\x45\xf3\x56\xbb\x77\xe8\x9a\x95\x2d\x1e\x37\xed\x9a\xa5\x17\x90\x23\x57\xe7\x8e\xc1\x01\xd4\x58\x42\xe6\x15\x16\x13\xb2\xca\xc9\xb4\xc6\xb1\x32\x43\x10\x58\x25\x68\x95\x50\xb0\x40\x69\xbc\x46\x41\x9e\xa1\x10\xaf\x90\xb2\xaa\xa9\x34\xab\x21\xac\xf0\xb2\x8c\x14\x01\x91\x08\x7a\x21\x81\x08\xa8\xc8\x18\x23\x2c\x43\x5e\x91\xb1\x4a\x60\x2c\x40\x0a\x41\x4a\x46\x1e\x43\x82\x65\x09\x8d\x40\x2c\x43\x43\x19\xf3\x1a\x14\x08\x12\xf2\x90\x65\x09\xa8\x09\x2c\xe2\x54\xfe\xe0\x18\x10\xfe\x7f\x89\xe0\x62\xcf\x28\xee\x0c\x92\xe9\x98\x0b\x1e\x13\x9f\x18\x8e\x86\x0c\x5d\xf9\x96\x22\x08\x96\xe6\x38\x48\x70\xe4\x31\x80\xec\x31\x80\x44\xe6\xcf\x97\x0d\x09\x22\xf6\x72\xfd\xcf\x63\x00\xe1\x31\x38\x68\xb5\x5a\xad\x36\xdb\x52\x5e\x17\xb6\x7d\x71\xf3\xea\x76\x16\xcf\x13\x6b\xb2\x78\x16\xc8\xf3\x59\xe7\x6d\x6e\xdc\xc9\xec\xed\xc5\x5d\xef\xb1\x3b\x6b\x69\xc6\x8b\xf6\x78\x4e\xf4\x86\xba\x69\xfe\x7a\x7b\x16\x0c\x48\xb5\x56\xdf\xda\x5f\x89\xde\x44\xbb\xd0\xaf\xde\xbe\xbe\xce\x2d\xd9\xbc\x5a\x2e\x3b\x04\x9a\xbe\xb1\x96\xc7\xba\xf5\x70\xfb\xf5\x66\xd1\xda\xfc\x51\xef\xc2\xd3\xac\x35\x9e\xf7\x05\xb7\xf5\x75\xf9\xec\x2e\x3b\xd4\xc3\x78\x38\xa7\x74\x77\x39\x7e\x15\x67\x37\x6c\xeb\xfe\xf9\xed\x7c\x4c\x8b\x23\xe3\x45\x1e\xf6\xdf\x2e\x5f\xb4\x2b\x77\xa4\x4d\x4f\x7f\x0d\xf8\x37\x41\x78\xeb\x4f\x3a\xef\xe2\xeb\xf2\x5d\xc7\xef\xb6\xa9\x8c\xd5\x05\x56\xe9\x07\x9f\xb3\x32\xa0\xfb\xe8\x7d\x4e\xde\xb5\xaa\xfe\xbe\xb7\x1e\x20\x7d\xd7\x6a\x75\x88\xab\x4a\xda\xff\x6f\x7f\xa1\x4b\xa5\xda\xfc\xa2\x40\x60\xf7\xe3\xc4\x07\xa4\x46\xc8\x88\xa5\x09\x82\xe1\x09\x82\x47\x90\x51\x79\x4d\x46\x34\x4d\xb1\x1a\xad\x90\xb4\xca\x09\x02\x25\x08\xb4\x26\x68\x1c\x85\x68\x92\x55\x38\x4c\x52\x3c\x27\x28\x88\x82\x48\xa0\xb4\xb2\x40\x80\x85\xae\xce\x93\xb0\xc6\x5b\x92\xe1\x58\x81\x27\x28\x8e\x63\x77\x0e\x84\x15\xdf\x9f\x3f\xb7\xba\xd3\x96\xfe\xf4\xf0\xf8\x91\x1d\x75\x64\xe2\xed\x19\x32\xcf\x8c\x71\x6b\x52\xc3\xe7\x2b\x47\xd3\x87\x97\xe6\xf5\x0d\x7a\x3e\xbd\x1f\xb4\x9e\xec\xf7\x5f\x46\xa7\x83\xe5\xfe\xb5\xdb\x7e\x78\xfc\x8e\x3b\xce\xb5\xd5\xb1\x35\xf3\xdb\xc7\xd6\xec\x97\xa2\x61\x4b\xe8\x3c\xea\xd8\xf1\x2b\xce\x0b\x04\xf7\x6d\x53\x91\xbf\x2f\x10\x1e\xff\x0d\x84\x4c\x20\x30\xfb\x71\xe2\x03\x88\x19\x55\x55\x69\x44\x43\x0a\x69\x24\xcb\x41\x01\xf2\x2a\xcb\x29\xb2\x02\x79\x0e\x41\x45\x55\x58\x82\x12\x10\x41\x11\x1c\x4d\x11\xaa\x00\x19\x05\x71\x34\xc3\x2a\x90\xe5\x05\x12\xd3\x65\x81\x40\x14\xbb\x3a\xc7\x51\x6c\xe5\x5b\x12\xd2\x1c\xcd\x53\x2c\xcd\x13\x3b\x07\xc2\x92\x51\xa9\xfb\xf9\xf9\xf0\xf5\xca\xbc\x18\xfd\xfa\xa6\xf5\xdf\x1e\xf1\xd3\xbb\xf2\xd8\x99\x4d\x6f\x2e\xef\xde\xc8\xd1\xc3\xb5\xda\x95\xcf\xd1\x55\xff\x99\xbd\x13\x86\xc2\x8b\x65\xb2\x0f\xb7\xd6\xa0\xc3\xf6\x2f\xf9\xae\x39\x5e\x0d\x48\x9a\x19\x91\x7d\xe5\x5d\x51\x26\x4b\x91\x77\x69\xfe\x74\x12\x54\x9c\x1f\x08\xd3\x4d\x45\xd6\x0f\x04\x93\x32\xd9\xf6\xe9\xe4\xcd\x38\x9f\xd3\xe4\x64\xf1\x91\x31\xcd\xd5\xb9\xfb\x74\xea\x0c\xac\xa9\xde\xd5\xac\x8f\x8e\x3c\x7c\xbc\x42\xe2\xe8\xa2\xeb\x73\xbe\xff\x37\x10\x32\x81\x40\xef\xc7\x89\x0f\x28\x45\x45\x98\x83\x32\x86\x04\xc7\xf2\x1c\x8d\x15\x06\x51\x02\xc3\x20\x4a\x23\x39\x85\x41\x3c\x43\xd2\x58\x65\x20\x8d\x38\x56\xe1\x58\x8e\xa4\x49\x86\x56\x04\x24\x20\xc8\xaa\x58\x66\x4b\x02\x81\x10\x0a\x5d\x5d\x60\x48\x82\xab\x7c\x0b\x39\x6f\x6c\xc4\x0a\x90\xa7\x77\x0e\x84\xf7\x77\xc4\x2c\x5f\x9f\xce\xc9\x27\x82\xeb\x5a\xcc\x57\x74\xbb\xd2\xba\x2f\xdd\xab\x21\x1c\x8d\x4d\xf9\xf2\xfb\xea\xce\x98\x5c\xbd\xa0\xae\xcb\x92\x8f\x57\xf0\x56\xd3\x9c\x5b\x91\x3e\x9f\xca\xe4\xcd\xc5\x9d\xfb\x95\x36\xe9\x11\x1c\x3d\xa1\x5b\x43\x34\x07\xce\x2b\xe9\x0e\xbb\x2f\x5d\xa7\x13\x78\xbf\x1f\x08\x31\xdf\xfc\x7d\x81\x70\xf7\x6f\x20\x64\x02\x81\xda\x8f\x13\x1f\x68\xaa\xaa\xb2\x2a\xc1\xaa\x1c\x8d\x09\x95\x61\x39\x0e\xcb\x04\x49\xc8\x84\xa6\xf1\x94\x42\x91\x10\x41\x12\x43\xac\xf0\x0a\x4d\x73\x24\xc9\xa8\x8a\x82\xbd\xf8\x92\x39\x8d\x44\x24\x21\x97\x05\x02\x5f\xe4\xea\x2c\x01\x89\xe2\x11\x84\xff\x96\xf2\x02\x81\xe4\x79\x5a\x20\x20\xcf\xf3\x3b\x07\xc2\x29\xa5\xca\x77\xf2\xc3\x64\x0a\xbf\xa9\x1f\x9d\x76\xfb\xed\x94\xbe\xed\xf4\x90\xb8\xb8\x74\x7e\x89\xa3\xd5\x95\xfa\x3e\x5c\x4e\x87\x14\xff\xd2\xeb\x0f\x07\x77\xec\xdb\xa2\xd5\xbe\x64\x97\xda\xd3\xaf\xc5\x83\xf0\x66\xe3\xab\xab\xf1\xea\xc1\x75\xba\x36\x14\xe5\x2e\xb5\x68\x5d\x2d\x3a\xee\xf5\xf7\xa0\xe2\xfc\x40\x88\x55\x64\x83\x40\x78\xfd\xd8\x77\xdd\xd3\x95\xf2\x7e\xba\xe4\x4f\x3f\x1a\xdd\x73\x9e\xb0\xcd\xaf\x4b\xee\x17\x79\x63\xcf\x48\x41\x9c\x2f\x9c\xfb\xd1\xc7\xe9\xab\x10\x88\xba\xf9\x37\x10\x32\x81\x40\xee\xc7\x89\x0f\x58\x4a\x15\x78\x8d\xa1\x58\x8c\x59\x5e\x85\x32\xc9\xc9\x8c\xcc\x0b\x1a\x49\x21\x8d\xa1\x20\x94\x39\x86\x15\x10\x49\x6b\x48\x83\x34\x41\x21\x95\x90\x19\x52\x66\x29\x4a\x26\x38\x19\x0b\x42\x59\x20\x14\xb6\xf9\x2c\x84\x0c\xac\x7e\xcb\x33\xbc\x20\x50\x34\x23\xec\x3e\x56\x26\x6f\xbf\xff\x82\x83\x05\x63\x11\xf2\x15\xf7\x8d\x36\x57\xc3\xd7\xfb\xe5\x05\xf5\x75\x6e\x3d\x7f\x7c\xed\xb6\x86\x6e\x1b\x5e\x93\x37\xdc\x39\xc7\x7e\x5f\x7c\x1f\x5d\xda\xc2\xbd\xfa\x70\x2d\x4f\xae\x75\xc5\xd0\x86\xbf\x56\x1c\xf9\xf8\xbd\x7b\x75\xff\x7c\x75\xfb\x55\xb9\x9e\x30\x4f\xee\xab\x65\xcf\x60\xe0\x8f\x5e\x1c\x38\xfe\x10\xa1\xb7\xfe\x5f\xcb\x7f\xe5\x6c\x7e\xbf\xb5\x6e\xef\x9e\x83\x7a\xfe\x7d\x71\xd2\xfb\x37\x4e\x32\x71\x02\xf7\xe3\xe3\xfe\xde\x85\xc8\xd3\xa1\xc0\x11\x27\x04\x3c\x21\x20\x20\x88\x33\xff\xbf\x62\x5f\x16\x68\x86\xaa\x7c\x4b\x93\x02\x2d\xb0\x1c\x29\x34\x1f\x0c\x07\x90\xfe\xe9\x4a\x29\xfe\x3b\x7f\xb8\xd6\xe9\xd5\xe9\x6a\x7c\x7d\xce\x75\xcc\x8e\x70\x49\x12\xcb\x5f\xe7\x1f\x1d\x62\xea\x3a\x6f\xbd\xb7\x77\xf8\xa0\x8e\xbf\x3d\xa2\xf3\x2b\xd4\xf5\x3b\x58\x62\x63\x27\x6e\xb5\xce\x9f\xff\x80\x22\x7b\xfd\xdb\x38\x71\xc5\x84\x6b\x8d\xcf\x0a\xb6\x9f\xc0\x6e\xb6\xaf\x7d\x1f\x13\xda\xe5\x5b\x2c\x9a\x4c\x70\x17\xec\x63\xdf\xc3\x1c\x77\xce\x76\xee\xfd\x70\xad\xde\xa0\xba\x7d\x55\x36\xdd\x19\xb9\x8f\xca\xac\xda\x46\xd2\xa4\x3a\x0b\xf7\x41\x36\x37\x49\xfc\xf3\xeb\xcc\x09\x67\xeb\xd3\x54\xa2\x3d\xc9\x4d\x77\xe2\xc4\x38\x06\xa7\x2d\x74\x3a\xf1\x1d\xce\x69\x81\xe0\x76\xd4\xbb\x69\x8d\x1e\xc1\xb5\xf8\x08\x0e\x75\xb5\xea\x2b\xeb\xfc\x13\xdf\x76\x46\x9d\xe2\x9a\x87\x3c\x4f\x70\x25\xfa\xd4\x1e\xb2\xed\x4e\xcc\xdb\x59\xbb\xa4\xd8\x3c\xe5\xb6\x02\x06\xee\x07\xbd\xbb\x7b\x11\x1c\x6e\xc8\x8f\x63\x9f\x13\x1f\x27\x3e\xfe\x6d\x68\x9a\xfd\x54\x6b\x63\xc5\x1b\x55\x6a\xc1\x9e\xba\x3a\xc7\x3c\xee\x4d\xb3\x7c\x21\x65\x9a\x96\xc0\xaa\xad\x79\xe1\x36\xbb\x7a\x87\x6c\xee\x4d\xfb\x22\x31\x65\xfa\x97\x42\xab\xb4\x40\xf2\xc4\xd2\x50\x11\xff\x74\xd3\x7a\x1b\xd2\x83\x83\x50\x13\x5c\xc0\x70\x90\x0e\x86\xfb\x71\x6f\x70\x01\x64\xd7\xc6\x38\x1e\x5d\xc5\x68\xc2\xc3\x56\x77\xc6\x13\x7e\xa8\x5f\x0b\x51\x41\x5c\xc7\x0e\x8a\xdd\x16\xce\x86\x45\x1c\x49\x62\xf7\x7e\x12\x4f\x40\x7c\x9c\xd9\x1e\x9f\x07\xce\x3f\xea\x76\x07\x64\xfe\x57\x02\xb5\x60\xa5\xbf\x2d\xc8\x43\x13\x9e\xcf\xbb\x03\x9e\x80\x43\x3d\x44\xa9\x0f\x17\x8e\xb3\xdf\x28\xe4\x86\x7c\xfc\xc0\xe1\xe6\x48\xc3\x2c\x11\x00\x4e\xb1\x8b\xc3\x8e\x0e\x0e\x48\x20\xce\xfb\xce\xef\x38\xfa\xa6\xaf\x08\xec\x66\x3b\xf1\x8e\x30\x75\xb5\x36\xc0\xcd\xb7\x49\xc7\xb9\x1f\x27\x56\x80\x8e\xce\x88\xde\x07\xee\x90\x57\x1c\x7a\x41\xaa\xda\x4a\x93\x7c\x05\xa2\xe3\xb0\xf7\xa1\x40\xc8\xab\xc0\xa7\xb7\x54\x21\xf9\xa1\x59\x56\x89\xd8\xe1\xdf\xdb\x46\x63\x8c\xc7\xb6\xc6\x2f\x37\x74\xea\x34\xf3\x5d\x6d\x9d\x64\x17\x87\x1c\x4d\x13\x25\x30\xe6\x23\xca\x9e\xc8\xbe\x3b\xac\x0c\xcf\x7a\xcd\x5b\x1e\xc0\xd8\xd9\xf2\x5b\x57\xeb\x86\xc7\xf6\x2e\x59\xe5\x7e\x79\xa7\xe6\x6f\x0f\x38\xcb\x2c\x85\x5c\xc5\x29\x9c\xa9\xef\x95\xcb\x01\x06\xd7\x00\xec\x05\x9e\xcf\xaa\x16\xb8\x68\xcb\x6d\x21\xb4\xf4\xb5\x06\xbb\xe2\x4b\xf1\xab\x02\x99\xfd\x10\xbb\x12\xe9\x7e\xec\x98\xe0\x56\x17\x65\xa5\x35\xf7\x83\xad\x16\xa6\x72\x2c\xa9\xfb\x33\x76\x42\x94\xe4\x55\xbb\x46\xa3\x2f\xb6\x73\xf1\x65\xae\x04\xd9\x09\x61\x9a\x5b\xbd\xb8\x0d\x01\x1e\x67\x3e\x32\x3f\xce\x9c\x70\x50\xa0\xc4\x1e\xda\xed\x90\x4f\x15\xe2\x86\xbd\xa3\xf4\x4d\x2e\x3b\x59\xb7\x81\x61\x2b\xed\x56\x7d\x45\xcd\x8e\x06\xad\x14\x90\x18\xa7\x45\xc7\xd8\x25\x47\x46\x01\x61\x03\xec\xbb\xfb\x41\x19\xef\x6a\xc4\x39\x51\x56\x7e\x01\xd1\xb6\xfe\x50\xca\xb5\xb2\xdb\xef\x11\x55\x00\xcd\xbd\x69\x69\x3f\x68\xf3\x58\x57\x76\xdf\xea\x7a\x72\xf2\x6a\xa9\xbd\x3a\x43\x82\xf5\x36\xfd\xcd\xfa\x77\x69\xed\xdd\xd0\x99\x53\xc4\x2a\xe1\xa7\x0a\xd4\x57\x26\x7e\xb5\xd8\xef\xb2\x7f\xfc\xe0\xb8\x2a\x4d\x62\xb4\xf5\x95\xc8\xbd\x6a\xed\x77\x69\x93\x7b\x1e\x5e\x95\x5a\x79\x85\xea\xeb\xb7\xbe\x89\xee\x77\xe9\xb4\xfe\x4a\xbf\x4a\x8f\xc2\xd9\xae\x8a\x1b\xf8\xf6\x0a\x3c\xcd\x3d\x77\x00\xdc\x34\xc0\x4b\x2f\x1f\xdc\x4f\x84\x97\x89\xa8\xa3\x43\xc5\xb8\xae\xf2\x2a\xc6\xdf\xa2\x45\x2a\x83\x15\x62\xaf\x4e\x62\x39\x57\x4f\xee\xd5\x6d\xb2\xfc\xb7\x1e\xea\x97\x5d\xb6\xb9\xad\x95\x4b\x78\x56\x76\x11\x0e\x0f\xa3\x03\xd7\x4e\xfe\xfe\x1b\x1c\x38\x96\xa1\xc6\x56\xd3\x0e\xce\xce\x5c\xbc\x74\x8f\x8e\x8e\x41\x31\xa1\x62\xa9\xf5\x08\x83\xb9\xf8\x62\x52\xd9\x5a\x4c\x9f\xdc\x5a\xe2\x13\xa4\xe5\x00\x12\xa4\x29\x08\x47\xe0\xdb\xa5\x38\x12\x03\x27\x03\x5f\x00\x45\x15\xac\x5e\x64\x17\xa2\xa3\xab\x55\xa3\x2b\x04\xae\xff\xcc\x72\x74\x28\x16\x74\x87\x23\xb1\x77\x31\x58\x2f\x01\x81\x91\xd8\x15\x47\xe2\xa0\x2d\xa6\xaf\x3c\xf3\xdf\x0e\x07\xe0\xfe\xb6\xe3\xb9\xcc\x48\x0c\x6e\x19\xf0\x1e\x75\xc4\xbe\x38\x11\x41\xbb\x35\x6e\xb7\x3a\x62\xf9\xc9\x78\xf9\x27\x92\xa5\x2e\xb1\xdd\x87\x31\x92\x72\x2a\x16\xc9\x8a\x90\x24\xed\x93\x9e\x36\xca\x35\x56\xd8\xd1\xaf\x58\x51\x2c\xb4\x44\xe2\xf2\xe0\x7f\xd0\x0e\x71\x1c\x79\x56\x88\x66\x09\xca\x1d\xa6\x99\x05\x8a\x6e\x6c\xfe\x47\xcc\x50\x00\x26\x69\x8b\x9c\x69\xb0\xfd\x3a\x45\xfe\xad\xd9\xff\xac\x41\x8a\x5d\x23\x33\x87\x54\xd7\x3b\x8a\x2e\x70\x07\x8a\x35\x9b\x1b\xd8\xc5\xbe\x0e\xff\x17\x00\x00\xff\xff\x9a\x31\x24\x7b\xed\x7d\x00\x00") +var _operation_fee_stats_2HorizonSql = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\x5d\xfb\x6f\xda\xca\xb3\xff\xbd\x7f\xc5\xea\xab\x23\x91\xa8\x49\xe3\xf5\xdb\xe9\xb7\x47\x22\x60\x12\x12\x02\x09\x90\x36\x69\x55\x59\x6b\x7b\x0d\x6e\x8c\x4d\x6c\x93\x40\xae\xee\xff\x7e\xe5\x17\xd8\xc6\x4f\xa0\x3d\xf7\x87\x13\x1d\x1d\x15\x7b\x76\xe6\x33\xb3\x33\xfb\x1c\xef\x9e\x9e\x7e\x38\x3d\x05\x77\x96\xe3\x4e\x6c\x3c\xba\xef\x01\x15\xb9\x48\x46\x0e\x06\xea\x62\x36\xff\x70\x7a\xfa\xc1\x7b\xdf\x5e\xcc\xe6\x58\x05\x9a\x6d\xcd\x36\x04\xaf\xd8\x76\x74\xcb\x04\xc2\x27\xf6\x13\x8c\x51\xc9\x2b\x30\x9f\x48\x5e\xf1\x14\xc9\x87\x91\x38\x06\x8e\x8b\x5c\x3c\xc3\xa6\x2b\xb9\xfa\x0c\x5b\x0b\x17\x7c\x01\xc4\x67\xff\x95\x61\x29\xcf\xdb\x4f\x15\x43\xf7\xa8\xb1\xa9\x58\xaa\x6e\x4e\xc0\x17\xd0\x78\x18\x77\xf8\xc6\xe7\x88\x9d\xa9\x22\x5b\x95\x14\xcb\xd4\x2c\x7b\xa6\x9b\x13\xc9\x71\x6d\xdd\x9c\x38\xe0\x0b\xb0\xcc\x90\xc7\x14\x2b\xcf\x92\xb6\x30\x15\x57\xb7\x4c\x49\xb6\x54\x1d\x7b\xef\x35\x64\x38\x38\x21\x66\xa6\x9b\xd2\x0c\x3b\x0e\x9a\xf8\x04\x6f\xc8\x36\x75\x73\xf2\x39\xc4\x8e\x91\xad\x4c\xa5\x39\x72\xa7\xe0\x0b\x98\x2f\x64\x43\x57\x4e\x3c\x65\x15\xe4\x22\xc3\xf2\xc8\x9a\xbd\xb1\x38\x04\xe3\xe6\x45\x4f\x04\xdd\x0e\x10\x1f\xbb\xa3\xf1\x08\x0c\xfa\xbd\xa7\x90\xfe\xd3\x54\x77\x5c\xcb\x5e\x49\xae\x8d\x54\xec\x80\xf6\x70\x70\x07\x5a\x83\xfe\x68\x3c\x6c\x76\xfb\xe3\x58\xa1\x24\xa1\xa4\x58\x0b\xd3\xc5\xb6\x84\x1c\x07\xbb\x92\xae\x4a\xda\x33\x5e\x7d\xfe\x13\x02\x15\xff\x5f\x7f\x42\xa4\xe7\x57\x7f\x4e\xc1\x40\x5a\x7d\xed\x02\x80\x9e\x23\x17\x09\x8b\x51\x6d\x98\xfb\xe4\xdd\x7e\x5b\x7c\x8c\x51\x86\x6c\x7d\x54\x12\xd6\x34\xac\xb8\x8e\x24\xaf\x24\xcb\x56\xb1\x2d\xc9\x96\xf5\x5c\x5c\x50\x37\x55\xbc\x94\x62\xca\x99\x0e\xf2\x1d\xdd\x91\x2c\x53\xd2\xd5\x3a\xa5\xad\x39\xb6\xd1\xba\xac\xbb\x9a\xe3\x3d\x4a\x6f\x90\xec\x85\xa2\x5e\x59\x03\xab\x13\x6c\xfb\x05\x1d\xfc\xb2\xc0\xa6\x52\x4b\x85\x58\xf1\xb9\x8d\x5f\x75\x6b\xe1\x84\xcf\xa4\x29\x72\xa6\x3b\xb2\xda\x9f\x83\x3e\x9b\x5b\xb6\x17\x8e\x61\x9b\xba\x2b\x9b\x5d\x6d\xa9\x18\x96\x83\x55\x09\xb9\x75\xca\x47\xce\xbc\x83\x2b\x85\x71\xb9\x03\xe8\x78\x49\xa4\xaa\x36\x76\x9c\xe2\xe2\x53\xd7\x56\xfd\x7e\x47\x32\x2c\xeb\x79\x31\xaf\x40\x3d\x2f\x83\x14\x50\x21\xdd\xae\xc9\x38\x6a\x74\x2b\x17\xf0\xda\x09\x4d\xc3\x76\x35\xd2\x88\xfd\x0e\x45\x42\xb3\x56\x2b\xe4\x37\xad\x35\x84\xc4\x9b\xe2\xb2\x12\x73\xaf\xc0\xd4\x2d\xad\x01\x27\xd1\x00\xc9\xab\x52\x37\x9a\xae\x23\xbd\x0a\xb1\x15\xe0\xb0\x4a\x09\x75\xc7\x95\xdc\xa5\x34\x2f\x67\xe9\x51\x5a\xf3\xaa\x94\xb8\x2a\x59\xd4\x95\x14\x13\xcb\x51\xb8\x97\x92\x95\xb7\x62\xf2\xaa\x5a\x65\x06\x7d\xa4\x67\x6d\xc7\x59\x94\x49\x5e\x13\x2b\x96\x8a\x6b\x8e\x0b\xd6\x6e\x30\x47\xb6\xab\x2b\xfa\x1c\x99\x85\x9d\x77\x59\x51\x69\x5e\x73\x6c\xb2\xee\xd1\xea\x22\xc8\x2e\x58\x5b\xbe\x6f\xbc\x2a\xf2\x02\xc2\xdf\xce\x3f\xa8\x4c\xaf\x26\xc3\x7f\x7a\xfd\x43\x34\xf4\xf3\x9d\x41\xaa\x88\x60\x62\xd9\x73\x69\xa6\x4f\xc2\x01\x43\x01\x84\x14\x65\x65\x1d\xeb\x8f\xf7\x8a\x38\x57\x75\xce\xa0\x74\x6b\xd0\x7b\xb8\xed\x03\x5d\x0d\x24\xb7\xc5\x4e\xf3\xa1\x37\xae\xc8\x3b\xc7\xe9\x0e\xc0\x39\xac\xee\x62\x4e\xfe\xaf\xea\xea\x47\xbd\xf4\x48\xbc\x7f\x10\xfb\xad\x1d\x6c\xe6\x8d\xb3\x1d\xfc\x52\x5b\x72\x82\x49\xe5\xd2\x2a\xae\x48\xbb\x19\xcd\x56\xd6\x30\x27\xea\xeb\xe8\x97\xcd\xa2\x5a\xd9\x70\xdc\x57\x8d\x38\x1c\xe4\x55\xd6\x2d\x6c\x01\xea\xe8\x12\x14\xa9\x48\x1b\x0e\xff\xaa\xe3\x89\xc6\x8b\x55\x10\xa5\xda\x90\x62\xe2\x58\x93\x10\x12\x36\x2f\x2f\x87\xe2\x65\x73\x9c\x41\x3c\xd3\xbd\x19\x87\xae\xe0\x23\x73\x31\xc3\xb6\xae\xfc\xf8\x79\x5c\xa1\x14\x5a\xee\x50\xca\x40\x8e\x7b\x84\xcc\x15\x36\xfc\xa5\x98\x0a\x25\x34\xdd\xce\x2c\xd2\x79\xe8\xb7\xc6\xdd\x41\xbf\x40\x1f\x09\x4d\x26\x1b\x74\x27\x60\x0b\x68\x01\x8f\x48\xbb\x3d\x78\x78\xba\xfa\xc5\x37\xe0\x4f\x40\x1d\x45\x7c\xd5\x2b\x70\x10\x1f\xc7\x62\x7f\x94\x62\x61\xcc\x27\xce\x8b\x11\xf9\x62\xeb\x4a\xbc\x6d\x6e\x49\xf8\xfc\x21\x58\x85\xeb\xa3\x19\x3e\x8f\x9e\x81\xf1\x6a\x8e\xcf\xc3\x22\x9f\xc1\x48\x99\xe2\x19\x3a\x07\xa7\x9f\xc1\xe0\xcd\xc4\xf6\x39\x38\xf5\x17\xe7\x5a\x43\xd1\xab\xaf\x90\x73\xc4\xef\x43\x82\x63\xf2\x65\xc8\xb8\x35\xb8\xbd\x15\xfb\xe3\x02\xce\x01\x01\x18\xf4\x93\x0c\x40\x77\x04\x1a\xd1\xb2\x5b\xf4\xcc\xf1\x99\x34\xd2\x92\x23\xf5\x43\x99\x6b\x0b\x95\xea\x93\xb0\x65\x7f\x30\x4e\xd9\x13\x7c\xeb\x8e\xaf\xd6\xb0\xe2\xeb\x6f\x09\xf1\x1b\x2e\x29\x20\x75\x94\xdf\x62\xe2\x1b\xe0\xae\x77\x36\x9f\x8c\xee\x7b\x60\x6e\x5b\x0a\x56\x17\x36\x32\x80\x81\xcc\xc9\x02\x4d\xb0\x6f\x86\x8a\xeb\x85\x71\xb8\xe5\x8e\x16\xc2\x8f\x7c\x75\x83\x3f\xaa\xdb\x2c\x5b\xae\x3d\xbb\x94\x3f\x18\x8a\xe3\x87\x61\x7f\x14\x7b\xf6\x01\x00\x00\x7a\xcd\xfe\xe5\x43\xf3\x52\x04\xbe\xf6\xb7\xb7\x0f\x41\x7b\x37\x1a\x0f\xbb\xad\xb1\x4f\xd1\x1c\x81\xbf\xa4\xbf\xc0\x48\xec\x89\xad\x31\xf8\x0b\x7a\xbf\xd2\xb5\x51\x1a\x88\xfb\x69\x57\xc6\xfe\x60\xca\x91\x59\xca\x55\x69\xa9\xf6\xd3\xaf\x82\x84\xb5\x8a\xeb\x47\x3b\x69\x78\xf4\x01\x80\x56\x73\x24\x82\x6f\x57\x62\x1f\xfc\x05\x7f\xc0\x9f\x67\x7f\xc1\x1f\xe4\xcf\xbf\xff\x22\xfd\x7f\x93\x3f\xc8\x9f\x60\x1c\xbc\x04\x62\x6f\x24\x7a\x46\x11\xfb\xed\xe3\x4c\xcb\x54\xe8\x07\xf6\xb4\x4c\xb9\x84\xdf\x6d\x99\xff\xee\x62\x99\xed\x3e\x35\xb4\xc3\xba\x1f\xae\x66\x88\x4d\xb7\xbd\xc5\xd1\x47\x0c\xc0\xc8\xb3\x15\xf8\xb2\x69\x01\x4e\x82\xc7\xe3\xa7\x3b\x11\x7c\x89\x47\xc4\x71\x56\xd4\x1e\x14\x63\x9a\x61\x0a\x62\x14\xc6\xd5\x11\x66\x0e\x81\xf6\x45\x99\xc5\x34\x85\x34\x11\x90\x49\xb8\x1b\x2f\xdb\x46\x9b\x35\xcc\xdb\x1b\x6d\x06\xd3\x34\xda\x78\x90\x14\xa2\xf5\x7a\x2e\x15\x6b\x68\x61\xb8\x92\x8b\x64\x03\x3b\x73\xa4\x60\xf0\x05\x34\x1a\x9f\x93\x6f\xdf\x74\x77\x2a\x59\xba\x1a\xdb\x4a\x4b\xe8\x1a\x1f\xff\x86\x2a\xfa\x01\x56\x4d\xbd\x20\x16\xe3\x93\xef\x40\x23\x5d\x05\xb2\x3e\xd1\x4d\xd7\x1f\x18\xf4\x1f\x7a\xbd\x40\x1d\x34\xf3\x86\xf1\x40\x99\x22\x1b\x29\x2e\xb6\xc1\x2b\xb2\x57\xba\x39\x49\x91\x99\x8b\xd9\x7a\xc8\x0f\x74\xd3\xc5\x13\x6c\xa7\x48\x34\x03\x4d\x1c\xe0\xcc\x90\x61\x6c\x8b\x71\xad\x99\xb1\x2d\xe4\x88\x64\x98\xe3\x35\xe5\x76\xb5\xa7\xe7\x0d\xbb\x9a\x23\xbd\xda\xb1\x36\x89\x8b\x97\x5b\x06\x99\xcf\x0d\xdd\x5f\xb3\x07\xae\x3e\xc3\x8e\x8b\x66\x73\xe0\xd5\x99\xff\x13\xbc\x5b\x26\xde\x06\x9a\x37\x2b\x8a\xc6\xa3\xe1\x74\xaa\x1a\xe6\xf5\xe4\x2b\x87\x6b\xe8\x86\xcd\xe1\x38\x18\xd1\x41\xff\x41\xb7\xdf\x1a\x8a\xfe\xf0\xeb\xe2\x29\x7c\xd4\x1f\x80\xdb\x6e\xff\x6b\xb3\xf7\x20\xae\x7f\x37\x1f\x37\xbf\x5b\xcd\xd6\x95\x08\x60\x99\x32\x3b\x9b\x3d\xcd\x68\xcb\x15\xc3\x45\x0f\x60\xe2\xa5\xfb\x8a\x8c\xa3\x46\x8e\xc6\x8d\xf3\x73\x1b\x4f\x14\x03\x39\xce\x71\xba\xba\x82\xbd\x8a\x0c\xdf\x62\xe9\xe3\x82\x8a\x0a\xe6\xc6\x7b\x6b\x16\xac\xe8\xac\xf5\xca\x8e\x8c\xcd\x5a\x5d\x36\xcc\x4c\x72\xc5\x52\xb3\xc8\x21\x99\x4d\x1e\x2c\xff\x65\x14\x60\xd8\xa2\x08\xcb\x5e\x5e\x38\x90\xdb\xc6\x79\xfe\x31\xa7\x2d\x52\x04\x0c\xbe\xf5\xc5\x36\xb8\x78\x2a\xd1\x28\x58\xa1\x2b\x56\x68\xcd\x2b\xf5\xfa\x93\xae\xe6\x61\x8b\xd6\x7c\xf6\xf5\xba\x90\x4f\xe8\x76\xa9\x98\x91\xf2\x5a\xfa\xed\x25\xae\x3c\xca\xff\xf8\x1b\x1f\xff\xc9\xf1\x66\xdf\x8f\xb3\x5f\xa9\xd8\x45\xba\xe1\x80\x5f\x8e\x65\xca\xf9\xce\x16\x2d\x94\xed\x6b\x87\x90\x4f\x68\x87\x68\xdf\x3a\x07\x5b\x6c\x33\xb9\x52\x14\x66\xed\x63\x67\x17\x0c\xcd\x12\x5b\x19\xf5\x2b\x62\x8d\x23\x6a\xe5\x88\x94\x84\x4d\x45\x54\xa3\x5f\x6f\x26\xa7\x3a\x26\x6b\xe1\x6e\xfa\xa6\x74\x19\x1b\x23\xb7\xb4\x50\x40\xbb\x98\xab\x95\x69\xd7\xae\x13\xfe\x4c\xed\xb3\x6f\xe9\x02\xb7\xc6\x03\x2e\x32\x24\xc5\xd2\x4d\x27\xdb\x07\x35\x8c\xa5\xb9\x65\x19\xd9\x6f\xfd\x9d\x4f\x0d\xe7\xd5\xb5\xff\xda\xc6\x0e\xb6\x5f\xf3\x48\xbc\x71\xa8\xbb\x94\xfc\x61\x92\xfe\x9e\x47\x35\xb7\x2d\xd7\x52\x2c\x23\x57\xaf\x74\x1d\x45\xce\x82\x91\x8a\x6d\x7f\x78\x11\x3c\x77\x16\x8a\x82\x1d\x47\x5b\x18\x52\xae\xa3\x84\x8a\x23\xdd\xc0\x6a\x3e\x55\x7e\x58\xe5\xac\x5d\xef\x1b\x65\x39\xfb\x21\x25\x7d\x5e\xf5\xd6\xa6\xbc\xfd\xaa\xab\xf2\x61\xbb\xb1\x42\x19\x7f\xaa\x5b\xab\xa5\xe8\x9e\xdd\x5c\xa1\xac\xed\x6e\x2f\x9b\xbc\xa0\x1b\x8c\xed\xec\x54\xf7\xcd\xd3\x53\x6f\xa8\x87\x55\xa0\x3b\xd2\x1c\xad\xbc\x49\xed\x17\x7f\xf6\x14\xcd\xab\x80\x6b\x85\x0b\xaa\x27\xc0\x46\xee\xd4\x0b\xbf\x29\x32\xbd\x26\xdb\x9c\x78\xf1\xed\x60\xdb\x05\x86\x6e\x62\xa7\xcc\xd1\xcb\xe6\x4c\xc9\x14\xad\x9c\x79\x95\x37\x8d\x50\x02\xbb\xf8\xdd\xe9\x9e\xbd\x69\xd8\x8c\x58\x0b\x5b\x59\xe7\x7c\xe4\xf4\x63\x51\xdb\xd4\x68\x9c\x9f\x97\xcd\xeb\x36\xd6\x04\xb2\x65\x19\x18\x99\x6b\x7b\xfa\xd6\xcd\x0f\xbd\x70\x2f\x6f\xdf\xd6\x25\x4c\x3f\x3c\x3a\xe8\x10\x25\x6c\x85\x77\xe9\x30\xfd\xf4\x9b\x5c\xb1\xa9\xe4\xc7\x22\xa2\x30\x1f\xb3\x88\x24\x98\x7a\x67\x12\x6c\xa7\x91\x96\xd0\x15\x8a\x5b\x53\x15\x48\xf4\x21\xe9\x8e\xe4\x60\xc3\xc0\x76\xe4\x0d\x51\x37\xa8\x2b\x58\x32\x13\x5d\x7e\xf0\x2c\x39\x0c\xd8\x24\x30\x49\xa9\x01\x42\x22\x85\x2a\xfd\xd2\xb6\x16\xa6\xea\xe7\x20\x1b\xfa\x7c\x8e\x26\x78\x9b\xa9\xee\x48\x78\x89\x14\x37\x89\x2b\x96\x52\x90\x99\xa5\xea\xab\x2b\xf9\x79\xcc\xa0\x75\x25\xb6\x6e\xc0\xd1\x51\xdc\xf4\x7f\x03\xe2\xf8\xb8\x8c\x55\x56\xf1\xc8\xda\xff\xdd\xaa\x80\x0a\xfc\x12\x95\x91\x62\x9f\xaa\x29\x1f\x60\x61\x0c\x66\xef\xc6\x1f\x20\x2a\xb3\xf3\x2b\x2a\xf6\xfa\x55\x5a\xc8\x7d\xfa\xfd\xb2\x5c\x86\xc3\xf4\xfc\x25\x52\xfe\x54\xdf\x5f\x53\xd9\x3d\x7b\xff\x12\x69\xdb\xfd\x7f\x5e\x81\x82\x11\x40\x22\x7f\xe5\x80\xbe\x1a\xf9\x67\x1c\x52\xe5\x09\x5f\xd8\x69\x94\x4c\x23\xab\xf6\xeb\xc5\x5d\x74\x26\xed\x46\x74\x66\xbc\x78\x33\x96\xfc\x29\x4f\xde\x64\xf2\x1f\x99\x0e\xba\x4b\x09\x9b\xaf\xd8\xb0\xe6\x38\x6b\x89\xd5\x5d\x7a\x93\x33\x7f\xcc\x96\xf9\x72\x86\x5d\x94\xf3\xca\x9b\x16\xe6\xbd\x76\xf4\x89\x89\xdc\x85\x8d\xb3\x56\x03\x05\xf6\xf8\xc7\xcf\xcd\xd0\xe8\x7f\xfe\x37\x6b\x70\xf4\xe3\x67\xda\xe6\x78\x66\xe5\x2c\xdc\x6d\x78\x99\x96\x89\x2b\x0c\xb5\x3c\x5e\xdb\x6c\x42\xcd\xf4\x19\x96\x64\xaf\x1b\xf4\x57\xd7\x79\xdb\x1b\xb3\x26\xdc\x32\xfb\xe5\x4c\x37\xa5\x1c\xef\xc9\x27\x90\xd2\x3d\x6c\x26\x51\x28\x77\x82\xe6\x09\x5a\xbc\x74\x6d\x24\x79\xa6\xc6\xb6\xe3\xd7\xc2\x8f\x9f\xe9\x29\x6e\xb2\x93\xf6\xaa\xcc\x53\x7b\x82\xd5\xe4\x4c\xd7\xc4\x6f\x52\xca\xa9\xcb\x16\x28\x81\xae\x46\xed\x45\x94\x30\x57\xa5\x91\x0b\x1a\x0c\x3f\x3b\xb1\x24\x17\x6f\x24\x8e\x0b\x56\xa5\xe3\xeb\x7f\xf1\x35\xe9\x7a\xb3\xb6\xc3\x29\x51\x31\x55\xb1\x50\xa9\xc2\xd9\x5e\x15\x25\x73\xc7\x0a\x07\x53\xb3\x72\xb6\x67\xa1\xa2\x25\x1d\x5b\xb6\xaa\x6d\xe4\x22\xa0\x59\x76\xc9\xde\x1c\x68\x37\xc7\xcd\x12\xf5\x72\x58\x16\xed\x71\x55\x61\xdb\xed\x8f\xc4\xe1\x18\x74\xfb\xe3\xc1\xd6\x3e\x97\x3f\xc4\x18\x81\xa3\x06\x94\x74\x53\x77\x75\x64\x48\xc1\x14\xf9\x93\xf3\x62\x34\x4e\x40\x83\x24\xa0\x70\x4a\xb0\xa7\x04\x05\x20\x7f\x4e\xf2\xe7\x34\xf7\x89\xa0\x48\x5a\x60\x3f\x12\x64\xe3\xf8\x73\x35\xee\xa4\x14\x7c\x4b\x92\xb0\xaa\xbc\x92\x5c\x4b\x57\x8b\x25\x09\x2c\xc3\xd5\x91\x44\x49\x0b\x07\x6f\xda\x28\xdd\xdc\xfa\x7e\xa5\x50\x1e\x4d\x13\x34\x5f\x47\x1e\x2d\x21\x55\x95\xd2\xab\x80\x85\x32\x18\x9a\xa1\xc8\x3a\x32\x18\x29\xe8\x95\xa3\xf9\x81\xbf\x7b\x5c\x28\x82\xa5\x08\xb2\x96\x1a\x6c\x24\x22\x6c\xc1\x2a\x88\xe0\x69\xc8\xd4\x11\xc1\x49\x33\x4b\xd5\xb5\x55\x75\x2d\x78\xc8\x92\xb5\x44\xf0\x09\x2d\xc2\xa4\xf1\x0a\x72\x38\x9a\xa5\xea\xc9\xf1\x2a\x1d\x4d\x26\x36\x9e\x20\xd7\xb2\x8b\x7d\x4a\x20\x20\x21\xd4\x61\x2f\xf8\xec\x83\x15\x62\x69\xa9\xda\xc5\xdc\x49\x0e\xd6\xaa\x6a\x48\xf8\xec\xc3\x5a\xf0\x27\xe9\xc5\x02\x18\x81\xab\x65\x1d\x08\xe3\x02\xd6\x93\x37\xaf\x01\x28\x16\x24\xb0\x42\x3d\x4d\xc8\x44\x45\x87\xd3\xe5\xe0\x33\xe5\x22\x49\x90\xe0\x18\xba\x56\x8d\x40\x2a\x50\x67\xbd\x3a\x51\x58\xe3\x10\x92\x1c\x5b\x4f\x13\x5a\xd2\xf4\x65\xf4\xc9\x86\x35\x33\x24\x4d\xc7\x46\x61\xd3\x08\x21\x03\x61\xad\x46\x18\x32\xd1\x90\x2d\xda\x41\x58\x96\xa8\xc1\x72\xf5\x9a\x79\xc8\x4a\xba\x39\xc1\x8e\x2b\x6d\xef\x51\x94\x88\xe2\x04\xbe\x5e\x8d\x70\x89\xee\xda\xdf\x0c\x42\xc5\x9d\x09\x24\x09\x82\xa2\x43\x21\x39\x7d\x6d\x61\x66\x43\x9d\x3e\xbc\x56\xd6\x87\x37\x2c\x29\xe1\x1b\x66\xca\x6d\x92\x5c\x3f\x39\xb8\x38\x23\xe2\x04\xc0\x93\x60\x89\xb6\x82\xba\xdb\xc9\x0e\x7b\x28\x5b\xb8\xc1\x7e\x10\x55\x13\xc3\xec\x3a\x8a\x66\x6d\xb0\xef\x31\x34\x2b\xda\xaf\xae\x3b\x34\x4b\xef\x59\x47\xae\xce\x9d\x80\x06\xd4\x58\x42\xe6\x15\x16\x13\xb2\xca\xc9\xb4\xc6\xb1\x32\x43\x10\x58\x25\x68\x95\x50\xb0\x40\x69\xbc\x46\x41\x9e\xa1\x10\xaf\x90\xb2\xaa\xa9\x34\xab\x21\xac\xf0\xb2\x8c\x14\x01\x91\x08\x7a\x21\x81\x08\xa8\xc8\x18\x23\x2c\x43\x5e\x91\xb1\x4a\x60\x2c\x40\x0a\x41\x4a\x46\x1e\x43\x82\x65\x09\x8d\x40\x2c\x43\x43\x19\xf3\x1a\x14\x08\x12\xf2\x90\x65\x09\xa8\x09\x2c\xe2\x54\xbe\x71\x02\x08\xff\xbf\x44\x70\xb1\xe7\x14\x77\x0e\xc9\x74\xcc\x05\x8f\x89\x4f\x0c\x47\x43\x86\x2e\x7d\x4b\x11\x04\x4b\x73\x1c\x24\x38\xf2\x04\x40\xf6\x04\x40\x62\xeb\xcf\x97\x0d\x09\x22\xf6\x72\xfd\xcf\x13\x00\xe1\x09\x68\x34\x9b\xcd\x66\x8b\x6d\x2a\xaf\x0b\xdb\xbe\xbc\x7d\x75\xdb\x8b\xe7\xb1\x35\x5e\x3c\x0b\xe4\xc5\xac\xfd\x36\x37\xee\x65\xf6\xee\xf2\xbe\xfb\xd4\x99\x35\x35\xe3\x45\x7b\xba\x20\xba\x03\xdd\x34\x7f\xbd\x3d\x0b\x06\xa4\x9a\xab\x6f\xad\xaf\x44\x77\xac\x5d\xea\xd7\x6f\x5f\x5f\xe7\x96\x6c\x5e\x2f\x97\x6d\x02\x4d\xde\x58\xcb\x63\xdd\x7c\xbc\xfb\x7a\xbb\x68\x6e\xfe\xa8\x77\x61\x3a\x6b\x8e\xe6\x3d\xc1\x6d\x7e\x5d\x3e\xbb\xcb\x36\xf5\x38\x1a\xcc\x29\xdd\x5d\x8e\x5e\xc5\xd9\x2d\xdb\x7c\x78\x7e\xbb\x18\xd1\xe2\xd0\x78\x91\x07\xbd\xb7\xab\x17\xed\xda\x1d\x6a\x93\xb3\x5f\x7d\xfe\x4d\x10\xde\x7a\xe3\xf6\xbb\xf8\xba\x7c\xd7\xf1\xbb\x6d\x2a\x23\x75\x81\x55\xfa\xd1\xe7\xac\xf4\xe9\x1e\x7a\x9f\x93\xf7\xcd\xb2\xbf\xef\xcd\x47\x48\xdf\x37\x9b\x6d\xe2\xba\x94\xf6\xff\xdb\x5f\xe8\x52\xa9\x36\x3f\x2f\x10\xd8\xc3\x38\x71\x83\xd4\x08\x19\xb1\x34\x41\x30\x3c\x41\xf0\x08\x32\x2a\xaf\xc9\x88\xa6\x29\x56\xa3\x15\x92\x56\x39\x41\xa0\x04\x81\xd6\x04\x8d\xa3\x10\x4d\xb2\x0a\x87\x49\x8a\xe7\x04\x05\x51\x10\x09\x94\x56\x14\x08\x30\xd7\xd5\x79\x12\x56\x78\x4b\x32\x1c\x2b\xf0\x04\xc5\x71\xec\xde\x81\xb0\xe2\x7b\xf3\xe7\x66\x67\xd2\xd4\xa7\x8f\x4f\x1f\xd9\x61\x5b\x26\xde\x9e\x21\xf3\xcc\x18\x77\x26\x35\x78\xbe\x76\x34\x7d\x70\x65\xde\xdc\xa2\xe7\xb3\x87\x7e\x73\x6a\xbf\xff\x32\xda\x6d\x2c\xf7\x6e\xdc\xd6\xe3\xd3\x77\xdc\x76\x6e\xac\xb6\xad\x99\xdf\x3e\x36\x67\xbf\x14\x0d\x5b\x42\xfb\x49\xc7\x8e\x5f\x71\x5e\x20\xb8\x6f\x9b\x8a\xfc\x7d\x81\xf0\xf4\x6f\x20\x6c\x05\x02\x73\x18\x27\x6e\x40\xcc\xa8\xaa\x4a\x23\x1a\x52\x48\x23\x59\x0e\x0a\x90\x57\x59\x4e\x91\x15\xc8\x73\x08\x2a\xaa\xc2\x12\x94\x80\x08\x8a\xe0\x68\x8a\x50\x05\xc8\x28\x88\xa3\x19\x56\x81\x2c\x2f\x90\x98\x2e\x0a\x04\x22\xdf\xd5\x39\x8e\x62\x4b\xdf\x92\x90\xe6\x68\x9e\x62\x69\x9e\xd8\x3b\x10\x96\x8c\x4a\x3d\xcc\x2f\x06\xaf\xd7\xe6\xe5\xf0\xd7\x37\xad\xf7\xf6\x84\xa7\xef\xca\x53\x7b\x36\xb9\xbd\xba\x7f\x23\x87\x8f\x37\x6a\x47\xbe\x40\xd7\xbd\x67\xf6\x5e\x18\x08\x2f\x96\xc9\x3e\xde\x59\xfd\x36\xdb\xbb\xe2\x3b\xe6\x68\xd5\x27\x69\x66\x48\xf6\x94\x77\x45\x19\x2f\x45\xde\xa5\xf9\xb3\x71\x50\x71\x7e\x20\x4c\x36\x15\x59\x3d\x10\x4c\xca\x64\x5b\x67\xe3\x37\xe3\x62\x4e\x93\xe3\xc5\x47\xc6\x34\x57\x17\xee\xf4\xcc\xe9\x5b\x13\xbd\xa3\x59\x1f\x1d\x79\xf0\x74\x8d\xc4\xe1\x65\xc7\xe7\xfc\xf0\x6f\x20\x6c\x05\x02\x7d\x18\x27\x6e\x50\x8a\x8a\x30\x07\x65\x0c\x09\x8e\xe5\x39\x1a\x2b\x0c\xa2\x04\x86\x41\x94\x46\x72\x0a\x83\x78\x86\xa4\xb1\xca\x40\x1a\x71\xac\xc2\xb1\x1c\x49\x93\x0c\xad\x08\x48\x40\x90\x55\xb1\xcc\x16\x04\x02\x21\xe4\xba\xba\xc0\x90\x04\x57\xfa\x16\x72\xde\xdc\x88\x15\x20\x4f\xef\x1d\x08\xef\xef\x88\x59\xbe\x4e\x2f\xc8\x29\xc1\x75\x2c\xe6\x2b\xba\x5b\x69\x9d\x97\xce\xf5\x00\x0e\x47\xa6\x7c\xf5\x7d\x75\x6f\x8c\xaf\x5f\x50\xc7\x65\xc9\xa7\x6b\x78\xa7\x69\xce\x9d\x48\x5f\x4c\x64\xf2\xf6\xf2\xde\xfd\x4a\x9b\xf4\x10\x0e\xa7\xe8\xce\x10\xcd\xbe\xf3\x4a\xba\x83\xce\x4b\xc7\x69\x07\xde\xef\x07\x42\xcc\x37\x7f\x5f\x20\xdc\xff\x1b\x08\x5b\x81\x40\x1d\xc6\x89\x1b\x9a\xaa\xaa\xac\x4a\xb0\x2a\x47\x63\x42\x65\x58\x8e\xc3\x32\x41\x12\x32\xa1\x69\x3c\xa5\x50\x24\x44\x90\xc4\x10\x2b\xbc\x42\xd3\x1c\x49\x32\xaa\xa2\x60\x2f\xbe\x64\x4e\x23\x11\x49\xc8\x45\x81\xc0\xe7\xb9\x3a\x4b\x40\x22\x7f\x06\xe1\xbf\xa5\xbc\x40\x20\x79\x9e\x16\x08\xc8\xf3\xfc\xde\x81\x70\x46\xa9\xf2\xbd\xfc\x38\x9e\xc0\x6f\xea\x47\xa7\xd5\x7a\x3b\xa3\xef\xda\x5d\x24\x2e\xae\x9c\x5f\xe2\x70\x75\xad\xbe\x0f\x96\x93\x01\xc5\xbf\x74\x7b\x83\xfe\x3d\xfb\xb6\x68\xb6\xae\xd8\xa5\x36\xfd\xb5\x78\x14\xde\x6c\x7c\x7d\x3d\x5a\x3d\xba\x4e\xc7\x86\xa2\xdc\xa1\x16\xcd\xeb\x45\xdb\xbd\xf9\x1e\x54\x9c\x1f\x08\xb1\x8a\xac\x11\x08\xaf\x1f\x7b\xae\x7b\xb6\x52\xde\xcf\x96\xfc\xd9\x47\xa3\x73\xc1\x13\xb6\xf9\x75\xc9\xfd\x22\x6f\xed\x19\x29\x88\xf3\x85\xf3\x30\xfc\x38\x79\x15\x02\x51\xb7\xff\x06\xc2\x56\x20\x90\x87\x71\xe2\x06\x4b\xa9\x02\xaf\x31\x14\x8b\x31\xcb\xab\x50\x26\x39\x99\x91\x79\x41\x23\x29\xa4\x31\x14\x84\x32\xc7\xb0\x02\x22\x69\x0d\x69\x90\x26\x28\xa4\x12\x32\x43\xca\x2c\x45\xc9\x04\x27\x63\x41\x28\x0a\x84\xdc\x36\x9f\x85\x90\x81\xe5\x6f\x79\x86\x17\x04\x8a\x66\x84\xfd\xe7\xca\xe4\xdd\xf7\x5f\xb0\xbf\x60\x2c\x42\xbe\xe6\xbe\xd1\xe6\x6a\xf0\xfa\xb0\xbc\xa4\xbe\xce\xad\xe7\x8f\xaf\x9d\xe6\xc0\x6d\xc1\x1b\xf2\x96\xbb\xe0\xd8\xef\x8b\xef\xc3\x2b\x5b\x78\x50\x1f\x6f\xe4\xf1\x8d\xae\x18\xda\xe0\xd7\x8a\x23\x9f\xbe\x77\xae\x1f\x9e\xaf\xef\xbe\x2a\x37\x63\x66\xea\xbe\x5a\xf6\x0c\x06\xfe\xe8\xc5\x81\xe3\x4f\x11\xba\xeb\xff\x35\xfd\x57\xce\xe6\xf7\x5b\xf3\xee\xfe\x39\xa8\xe7\xdf\x17\x27\xdd\x7f\xe3\x64\x2b\x4e\xe0\x61\x7c\xdc\xcf\x5d\x88\x3c\x1d\x0a\x1c\x71\x4a\xc0\x53\x02\x02\x82\x38\xf7\xff\xcb\xf7\x65\x81\x66\xa8\xd2\xb7\x34\x29\xd0\x02\xcb\x91\x42\xfd\xc9\x70\x00\xe9\x9f\xae\x94\xfc\xbf\x8b\xc7\x1b\x9d\x5e\x9d\xad\x46\x37\x17\x5c\xdb\x6c\x0b\x57\x24\xb1\xfc\x75\xf1\xd1\x21\x26\xae\xf3\xd6\x7d\x7b\x87\x8f\xea\xe8\xdb\x13\xba\xb8\x46\x1d\x7f\x80\x25\xd6\x76\xe2\x66\xf3\xe2\xf9\x0f\x28\x72\xd0\xbf\x8d\x13\x97\x2c\xb8\x56\xf8\x92\x61\xf7\x05\xec\x7a\xa9\xf4\x87\x58\xd0\x2e\x4e\xb1\xa8\xb3\xc0\x9d\x93\x3a\x7f\x80\x35\xee\x8c\x74\xee\xc3\x70\x2d\x4f\x50\xdd\xbd\x2a\xeb\x66\x46\x1e\xa2\x32\xcb\xd2\x48\xea\x54\x67\x6e\x1e\x64\x7d\x93\xc4\xbf\xf8\xde\x3a\x54\x6d\x7d\x80\x4b\x94\x93\x5c\x37\x13\x27\xc6\x31\x38\xe0\xa1\xdd\x8e\x67\x38\xa7\x05\x82\xbb\x61\xf7\xb6\x39\x7c\x02\x37\xe2\x13\x38\xd2\xd5\xb2\x0f\xbb\xb3\x0f\x99\xdb\x1b\x75\x8a\x6b\x16\xf2\x2c\xc1\xa5\xe8\x53\x39\x64\xbb\x1d\xd2\xb7\xb7\x76\x49\xb1\x59\xca\xed\x04\x0c\x3c\xf4\xbb\xf7\x0f\x22\x38\xda\x90\x9f\xc4\xbe\x60\x3e\x49\x7c\x6f\x5c\xd3\x34\x87\xa9\xd6\xda\x8a\xd7\xaa\xd4\x9c\x9c\xba\x2a\x27\x4b\x1e\x4c\xb3\x6c\x21\x45\x9a\x16\xc0\xaa\xac\x79\x6e\x9a\x5d\xb5\x73\x3d\x0f\xa6\x7d\x9e\x98\x22\xfd\x0b\xa1\x95\x5a\x20\x79\x48\x6a\xa8\x88\x7f\xa0\x6a\xb5\x84\xf4\xe0\xec\xd5\x04\x17\x30\xe8\xa7\x83\xe1\x61\xd4\xed\x5f\x02\xd9\xb5\x31\x8e\x47\x57\x3e\x9a\xf0\x7c\xd7\xbd\xf1\x84\x67\x03\x54\x42\x94\x13\xd7\xb1\xb3\x69\x77\x85\xb3\x61\x11\x47\x92\xc8\xde\x4f\xe2\x09\x88\x4f\xb6\xd2\xe3\xb3\xc0\xf9\xa7\xeb\xee\x81\xcc\xff\x4a\xa0\x12\xac\xf4\xb7\x05\x59\x68\xc2\x23\x81\xf7\xc0\x13\x70\xa8\x86\x28\xf5\xe1\xc2\xc9\xf6\x37\x0a\x99\x21\x1f\x3f\xe3\xb8\x3e\xd2\xb0\x97\x08\x00\xa7\xd8\xc5\x61\x47\x67\x15\x24\x10\x67\x7d\xe7\x77\x12\x7d\xd3\x97\x07\x76\x93\x4e\xbc\x27\x4c\x5d\xad\x0c\x70\xf3\x6d\xd2\x49\xe6\xc7\x89\x25\xa0\xa3\x63\xa9\x0f\x81\x3b\xe4\x15\x87\x9e\xd3\x55\xed\xa4\x49\xb6\x02\xd1\x09\xdc\x87\x50\x20\xe4\x95\xe3\xd3\x3b\xaa\x90\xfc\xd0\x6c\x5b\x89\xd8\x79\xe3\xbb\x46\x63\x8c\xc7\xae\xc6\x2f\x36\x74\xea\x00\xf5\x7d\x6d\x9d\x64\x17\x87\x1c\x2d\x13\x25\x30\x66\x23\xda\x3e\x04\x7e\x7f\x58\x5b\x3c\xab\x35\x6f\x59\x00\x63\xc7\xd9\xef\x5c\xad\x1b\x1e\xbb\xbb\x64\x99\xfb\x65\x1d\xd4\xbf\x3b\xe0\x6d\x66\x29\xe4\x2a\x4e\xe1\x4c\x7d\xaf\x5c\x0c\x30\xb8\x79\xe0\x20\xf0\x7c\x56\x95\xc0\x45\x29\xb7\xb9\xd0\xd2\x37\x29\xec\x8b\x2f\xc5\xaf\x0c\xe4\xf6\x87\xd8\xa5\x48\x0f\x63\xc7\x04\xb7\xaa\x28\x4b\xad\x79\x18\x6c\x95\x30\x15\x63\x49\x5d\xd9\xb1\x17\xa2\x24\xaf\xca\x35\x1a\x7d\xb1\x9d\x89\x6f\xeb\x16\x92\xbd\x10\xa6\xb9\x55\x8b\xdb\x10\xe0\xc9\xd6\x47\xe6\x27\x5b\x27\x1c\xe4\x28\x71\x80\x76\x3b\xe4\x53\x86\xb8\xe6\xe8\x28\x7d\x79\xcc\x5e\xd6\xad\x61\xd8\x52\xbb\x95\xdf\x8a\xb3\xa7\x41\x4b\x05\x24\xe6\x69\xd1\xc9\x79\xc9\x99\x51\x40\x58\x03\xfb\xfe\x7e\x50\xc4\xbb\x1c\x71\x46\x94\x15\xdf\x79\xb4\xab\x3f\x14\x72\x2d\x1d\xf6\x7b\x44\x25\x40\x33\x2f\x77\x3a\x0c\xda\x2c\xd6\xa5\xc3\xb7\xaa\x9e\x9c\xbc\xcd\xea\xa0\xce\x90\x60\xbd\xcb\x78\xb3\xfa\xf5\x5d\x07\x37\xf4\xd6\xc1\x65\xa5\xf0\x53\x05\xaa\x2b\x13\xbf\xcd\xec\x77\xd9\x3f\x7e\x56\x5d\x99\x26\x31\xda\xea\x4a\x64\xde\xee\xf6\xbb\xb4\xc9\x3c\x82\xaf\x4c\xad\xac\x42\xd5\xf5\x5b\x5f\x7e\xf7\xbb\x74\x5a\x7f\xa5\x5f\xa6\x47\xee\x6a\x57\xc9\xa5\x7f\x07\x05\x9e\xe6\x9e\x39\x01\xae\x1b\xe0\x85\xf7\x1d\x1e\x26\xc2\x8b\x44\x54\xd1\xa1\x64\x5e\x57\x7a\xfb\xe3\x6f\xd1\x22\xd5\x83\xe5\x62\x2f\xef\xc4\x32\x6e\xbb\x3c\xa8\xdb\x6c\xf3\xdf\x79\xaa\x5f\x74\xbf\xe7\xae\x56\x2e\xe0\x59\x3a\x44\x38\x3a\x8a\x8e\x65\x3b\xfd\xfb\x6f\xd0\x70\x2c\x43\x8d\xed\xa6\x35\xce\xcf\x5d\xbc\x74\x8f\x8f\x4f\x40\x3e\xa1\x62\xa9\xd5\x08\x83\xb5\xf8\x7c\x52\xd9\x5a\x4c\xa6\x6e\x25\xf1\x09\xd2\x62\x00\x09\xd2\x14\x84\x63\xf0\xed\x4a\x1c\x8a\x81\x93\x81\x2f\x80\xa2\x72\x76\x2f\xb6\x37\xa2\xa3\xdb\x5c\xa3\x5b\x0b\x6e\xfe\xcc\x76\x74\x28\x16\x74\x06\x43\xb1\x7b\xd9\x5f\x6f\x01\x81\xa1\xd8\x11\x87\x62\xbf\x25\xa6\x6f\x59\xf3\xdf\x0e\xfa\xe0\xe1\xae\xed\xb9\xcc\x50\x0c\x2e\x36\xf0\x1e\xb5\xc5\x9e\x38\x16\x41\xab\x39\x6a\x35\xdb\x62\xf1\xc9\x78\xd9\x27\x92\xa5\xee\xcd\x3d\x84\x31\x92\x72\x4a\x36\xc9\xf2\x90\x24\xed\x93\x5e\x36\xca\x34\x56\x38\xd0\x2f\xd9\x51\xcc\xb5\x44\xe2\xbe\xe2\x7f\xd0\x0e\x71\x1c\x59\x56\x88\x56\x09\x8a\x1d\xa6\x9e\x05\xf2\x2e\x89\xfe\x47\xcc\x90\x03\x26\x69\x8b\x8c\x65\xb0\xc3\x3a\x45\xf6\x45\xdd\xff\xac\x41\xf2\x5d\x63\x6b\x0d\xa9\xaa\x77\xe4\xdd\x19\x0f\x14\x6b\x36\x37\xb0\x8b\x7d\x1d\xfe\x2f\x00\x00\xff\xff\x91\xba\x65\xd6\x60\x7e\x00\x00") func operation_fee_stats_2HorizonSqlBytes() ([]byte, error) { return bindataRead( @@ -406,7 +406,7 @@ func operation_fee_stats_2HorizonSql() (*asset, error) { } info := bindataFileInfo{name: "operation_fee_stats_2-horizon.sql", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} - a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x8, 0xd3, 0xca, 0x46, 0x48, 0x2b, 0xeb, 0xa2, 0x94, 0xc0, 0xa1, 0x2a, 0xd, 0x9d, 0x2d, 0x1c, 0xdc, 0x23, 0x22, 0x6, 0x35, 0xbd, 0x69, 0xbc, 0x4f, 0xba, 0x6c, 0x72, 0x69, 0xc1, 0x17, 0x8b}} + a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xd0, 0x5f, 0x60, 0x47, 0xfd, 0xa6, 0xb8, 0x6e, 0xe5, 0x16, 0x66, 0xd5, 0x33, 0x9b, 0xe9, 0x1c, 0xc4, 0xe, 0x1c, 0xee, 0xc5, 0x8e, 0x22, 0xbc, 0x93, 0x88, 0xf6, 0x21, 0xfa, 0x85, 0x58, 0xcb}} return a, nil } @@ -430,7 +430,7 @@ func operation_fee_stats_3CoreSql() (*asset, error) { return a, nil } -var _operation_fee_stats_3HorizonSql = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\x5d\x79\x8f\xe2\xb8\xb6\xff\x7f\x3e\x45\xd4\x1a\xa9\xba\x45\xf5\x90\x7d\xe9\x79\x7d\xa5\x00\x61\xdf\x77\x18\x8d\x90\x93\x38\x90\x22\x5b\x25\x61\xab\xab\xf7\xdd\x9f\x08\x5b\x48\x25\x10\x08\x55\x7d\x9f\xee\xa0\x51\x0d\xc1\xf6\xd9\x7c\x8e\x7f\xf6\xb1\xe3\xfe\xfe\xfd\xb7\xef\xdf\x91\xa6\xe9\xb8\x53\x1b\x76\x5a\x55\x44\x06\x2e\x10\x81\x03\x11\x79\xa1\x5b\xbf\x7d\xff\xfe\xdb\xb6\x3c\xb7\xd0\x2d\x28\x23\x8a\x6d\xea\xa7\x0a\x4b\x68\x3b\xaa\x69\x20\xdc\x1f\xf4\x1f\x98\xaf\x96\xb8\x41\xac\xe9\x64\xdb\x3c\x50\xe5\xb7\x8e\xd0\x45\x1c\x17\xb8\x50\x87\x86\x3b\x71\x55\x1d\x9a\x0b\x17\xf9\x89\xa0\x7f\x7a\x45\x9a\x29\xcd\xdf\xff\x2a\x69\xea\xb6\x36\x34\x24\x53\x56\x8d\x29\xf2\x13\x79\xea\x75\xf3\xec\xd3\x9f\x07\x72\x86\x0c\x6c\x79\x22\x99\x86\x62\xda\xba\x6a\x4c\x27\x8e\x6b\xab\xc6\xd4\x41\x7e\x22\xa6\xb1\xa7\x31\x83\xd2\x7c\xa2\x2c\x0c\xc9\x55\x4d\x63\x22\x9a\xb2\x0a\xb7\xe5\x0a\xd0\x1c\x78\xc6\x46\x57\x8d\x89\x0e\x1d\x07\x4c\xbd\x0a\x2b\x60\x1b\xaa\x31\xfd\x73\x2f\x3b\x04\xb6\x34\x9b\x58\xc0\x9d\x21\x3f\x11\x6b\x21\x6a\xaa\xf4\xbc\x55\x56\x02\x2e\xd0\xcc\x6d\x35\xbe\xda\x15\xda\x48\x97\xcf\x54\x05\xa4\x94\x47\x84\x61\xa9\xd3\xed\x20\x8d\x7a\x75\xb4\xaf\xff\xc7\x4c\x75\x5c\xd3\xde\x4c\x5c\x1b\xc8\xd0\x41\x72\xed\x46\x13\xc9\x36\xea\x9d\x6e\x9b\x2f\xd5\xbb\xbe\x46\xe7\x15\x27\x92\xb9\x30\x5c\x68\x4f\x80\xe3\x40\x77\xa2\xca\x13\x65\x0e\x37\x7f\x7e\x06\x43\xc9\xfb\xf6\x19\x2c\xb7\x7e\xf5\x79\x0a\xee\xb8\xdd\xae\xdd\x4e\xc0\xad\x23\x5f\x62\xe6\xab\x75\x22\xee\x55\x2f\xd5\x73\xc2\xd0\x57\x73\x4f\xd6\x93\x6a\x02\x15\x05\x4a\xae\x33\x11\x37\x13\xd3\x96\xa1\x3d\x11\x4d\x73\x7e\xb9\xa1\x6a\xc8\x70\x3d\xf1\x29\x67\x38\xc0\x73\x74\x67\x62\x1a\x13\x55\xbe\xa5\xb5\x69\x41\x1b\x1c\xdb\xba\x1b\x0b\x26\x68\x7d\x92\x24\x91\x14\xb7\xb5\xd5\xa0\x3c\x85\xb6\xd7\xd0\x81\xaf\x0b\x68\x48\x37\xa9\xe0\x6b\x6e\xd9\x70\xa9\x9a\x0b\x67\xff\xdb\x64\x06\x9c\xd9\x9d\xa4\x92\x53\x50\x75\xcb\xb4\xb7\xe1\xb8\x1f\x53\xef\x25\x73\xaf\x2d\x25\xcd\x74\xa0\x3c\x01\xee\x2d\xed\x0f\xce\x7c\x87\x2b\xed\xe3\xf2\x0e\xa1\xfd\x2d\x81\x2c\xdb\xd0\x71\x2e\x37\x9f\xb9\xb6\xec\xe1\xce\x44\x33\xcd\xf9\xc2\x8a\x51\xdb\xba\x26\xd2\xae\x16\x50\xed\x1b\x09\x1f\x06\xdd\xd8\x0d\xb6\xe3\x84\xa2\x40\x3b\x5e\xd5\x03\xf9\x3b\x9a\xec\xcd\x1a\xaf\x91\x37\xb4\xde\xc0\xc4\x3f\x14\x5f\x6b\x61\x6d\x1b\xcc\xdc\xab\x3d\xe0\x9c\x0d\x40\xe2\xe6\xaa\x1b\xcd\x8e\x91\x1e\xa7\xb2\xb9\x93\xc3\xbc\x5a\x51\x75\xdc\x89\xbb\x9e\x58\xd7\x49\x6e\x6b\x9a\x56\xdc\x9a\x30\x6e\xb5\x03\x94\x5c\xae\x2c\x1e\xc2\xfd\x6a\xb5\xeb\xa3\x98\xb8\x89\xd7\x99\x3b\x8c\xdc\x5a\xdb\x71\x16\xd7\x38\x1f\x2b\x4b\xa6\x0c\x6f\x9c\x17\x1c\xdd\xc0\x02\xb6\xab\x4a\xaa\x05\x8c\x8b\xe0\x7d\xad\xe9\xc4\xba\x71\x6e\x72\x44\xb4\x5b\x25\x08\x6f\x78\x33\x7f\xcf\x78\x71\xf8\xed\x2a\x7e\x38\xfd\x5d\x67\x6e\x7b\x72\xff\x75\x8b\x0f\x87\xa9\x9f\xe7\x0c\x93\x98\x12\x4c\x4d\xdb\x9a\xe8\xea\x74\x3f\x61\xb8\x20\x42\xa0\x66\x6c\x1d\x6f\x9f\xef\x5d\xa2\x1c\xd7\x39\x77\xad\xb3\x8d\x6a\xaf\x56\x47\x54\x79\xc7\x39\x27\xe4\xf9\x5e\xb5\x1b\x93\x76\x84\xd3\x3d\x80\xf2\xbe\xbb\x2f\x53\xf2\x9e\xe2\xab\x7f\x40\xe9\x8e\xd0\xea\x09\xf5\xec\x1d\x36\xdb\xce\xb3\x1d\xf8\x7a\x33\xe7\x33\x22\xb1\x5b\xcb\x30\x66\xdd\xd3\x6c\x36\xb6\x86\x11\x51\x7f\x8b\x7e\xe1\x24\xe2\xb5\xdd\xcf\xfb\xe2\x55\xde\x4f\xf2\x62\xeb\xb6\x1f\x01\x6e\xd1\x65\xd7\x24\x66\xdd\xfd\xf4\x2f\xbe\x3c\x87\xf9\x62\x1c\x89\x02\x63\xc8\xe5\xca\xbe\x21\x61\x5f\x91\x2f\x14\xda\x42\x81\xef\x86\x54\xd6\xd5\xed\x8a\x43\x95\xe0\x57\x63\xa1\x43\x5b\x95\xfe\xfa\xfb\x5b\x8c\x56\x60\x7d\x47\x2b\x0d\x38\xee\x57\x60\x6c\xa0\xe6\xa5\x62\x62\xb4\x50\x54\x3b\xb4\x49\xbe\x57\xcf\x76\x4b\x8d\xfa\x05\x7d\x26\x60\x3a\x3d\x49\xf7\x8c\xbc\x13\xf4\x02\x8d\x83\x76\x09\x68\x6c\x75\xf5\x9a\x9f\x84\x7f\x46\x6e\x51\xc4\x53\x3d\x06\x05\x61\xd8\x15\xea\x9d\x00\x09\xcd\x9a\x3a\xaf\xda\xc1\x17\xb3\x45\xa1\xc6\xbf\xe3\xf0\xe7\x6f\xbb\x2c\x5c\x1d\xe8\xf0\xc7\xe1\x37\xa4\xbb\xb1\xe0\x8f\x7d\x93\x3f\x91\x8e\x34\x83\x3a\xf8\x81\x7c\xff\x13\x69\xac\x0c\x68\xff\x40\xbe\x7b\xc9\xb9\x6c\x5b\xd8\xf6\xd7\x9e\xf2\x81\xde\x6f\x67\x14\xcf\x0b\xf7\x84\xb3\x8d\x5a\x4d\xa8\x77\x2f\x50\xde\x55\x40\x1a\xf5\x73\x02\x48\xa9\x83\x3c\x1d\xd2\x6e\x87\xdf\x1c\x8f\xc8\x53\x90\xf3\x41\xfd\x3d\xcf\xa3\x85\xae\xea\x73\x66\xcb\x7a\xa3\x1b\xb0\x27\x32\x28\x75\x8b\x47\xb1\xfc\xf9\xb7\x33\xf6\x27\x2a\x01\x41\x6e\x51\xfe\x1d\x11\xcf\x00\xcd\x6a\xda\x9a\x76\x5a\x55\xc4\xb2\x4d\x09\xca\x0b\x1b\x68\x88\x06\x8c\xe9\x02\x4c\xa1\x67\x86\x98\xf9\x42\xbf\xb8\xd7\x1d\x6d\x2f\xfe\xc1\x57\x4f\xf2\x1f\xfa\x36\xcc\x96\x47\xcf\xbe\x4a\x1f\x69\x0b\xdd\x5e\xbb\xde\xf1\xfd\xf6\x1b\x82\x20\x48\x95\xaf\x17\x7a\x7c\x41\x40\x3c\xed\x6b\xb5\xde\x6e\xbc\xeb\x74\xdb\xa5\x6c\xd7\xab\xc1\x77\x90\xdf\x27\xbf\x23\x1d\xa1\x2a\x64\xbb\xc8\xef\xd8\xf6\x29\xd8\x1b\x57\x03\x31\x99\x76\xd7\xc8\x3f\x4c\x39\x3c\x4c\xb9\x38\x23\x55\x32\xfd\x62\x70\x38\xaa\x78\xfc\xe9\x2e\x0d\xbf\xfe\x86\x20\x59\xbe\x23\x20\x83\xa2\x50\x47\x7e\xc7\xfe\xc2\xfe\x4e\xff\x8e\xfd\x85\xff\xfd\xaf\xdf\x71\xef\x3b\xfe\x17\xfe\x37\xd2\xdd\x15\x22\x42\xb5\x23\x6c\x8d\x22\xd4\x73\xdf\x42\x2d\x13\x03\x07\x12\x5a\xe6\x3a\x87\x8f\xb6\xcc\xff\xdc\x63\x99\xf7\x98\xba\xb7\xc3\x11\x87\xe3\x19\xe2\x04\xdb\xef\x28\x7a\x12\x23\x48\x67\x6b\x2b\xe4\xe7\x69\x04\x78\xde\xfd\xdc\x1d\x35\x05\xe4\xa7\x3f\x22\xbe\x85\x45\xed\x43\x65\x0c\x12\x0c\x88\x78\x08\xe3\xf8\x12\x86\x4e\x81\x92\x4a\x19\x46\x34\x20\xe9\x59\x40\x9e\x8b\x7b\xf2\xb2\xf7\xd2\x86\x4d\xf3\x12\x4b\x1b\x42\x34\x28\xad\x3f\x48\x2e\x4a\xbb\x45\x2e\x19\x2a\x60\xa1\xb9\x13\x17\x88\x1a\x74\x2c\x20\x41\xe4\x27\xf2\xf4\xf4\xe7\x79\xe9\x4a\x75\x67\x13\x53\x95\x7d\x5b\x69\x67\xba\xfa\xe7\xbf\x7b\x15\xbd\x00\x8b\xa7\xde\x2e\x16\xfd\x8b\xef\x9d\x46\xaa\x8c\x88\xea\x54\x35\x5c\x6f\x62\x50\xef\x55\xab\x3b\x75\x80\xbe\x9d\xc6\x23\xd2\x0c\xd8\x40\x72\xa1\x8d\x2c\x81\xbd\x51\x8d\x69\xa0\x9a\xb1\xd0\x8f\x53\x7e\x44\x35\x5c\x38\x85\x76\xa0\x8a\xa2\x81\xa9\x83\x38\x3a\xd0\xb4\xf7\x6c\x5c\x53\xd7\xde\x33\xf9\x8a\x53\xd4\xb7\x63\xcd\xf7\xdd\x1e\x5c\x37\xdc\x6b\x8e\x60\xb6\xe3\x68\x12\x17\xae\xdf\x19\xc4\xb2\x34\xd5\xcb\xd9\x23\xae\xaa\x43\xc7\x05\xba\x85\x6c\xfb\xcc\x7b\x44\xde\x4c\x03\xbe\x17\x34\x6a\x55\x74\x98\x8f\xee\x97\x53\xf1\x64\x3e\x2e\xbe\x22\xa8\xee\xdd\x90\x6f\x77\x77\x33\x3a\xcc\xfb\xa1\x54\xcf\xb6\x05\x6f\xfa\x95\x19\xed\x7f\xaa\x37\x90\x5a\xa9\xde\xe7\xab\x3d\xe1\xf8\xcc\x0f\x4f\xcf\x59\x3e\x5b\x14\x10\xec\x9a\x32\x77\x9b\x3d\x48\xe8\x9d\x2b\xee\x93\x1e\x88\x01\xd7\xee\x12\x68\x5f\x9f\x22\x34\x7e\xfa\xf1\xc3\x86\x53\x49\x03\x8e\xf3\x2d\xd8\x5d\xbb\xbd\x8a\x10\xdf\xa2\xc9\x6f\x17\x3a\x6a\xb7\x36\x4e\xac\xd9\x2e\xa3\x73\xd4\x2b\x3c\x32\x4e\xb9\xba\x70\x31\x43\xab\x4b\xa6\x1c\x56\x1d\xc3\xc3\xab\xef\xd2\x7f\x21\x0d\x28\xfa\x52\x84\x85\xa7\x17\x1e\xe4\xb6\x7e\x9a\x9f\xe6\xb4\x97\x14\x41\x1a\x83\xba\x90\x43\x32\xa3\x2b\x1a\xed\x32\x74\x97\x15\x3a\xd2\x0a\x14\xff\xa1\xca\x51\xb2\x1d\x72\x3e\x49\xbd\x6e\x4f\x67\xef\x76\x81\x98\x99\x44\x8d\xf4\xef\x53\x5c\x51\x35\xbf\x78\x1b\x1f\x5f\x22\xbc\xd9\xf3\xe3\xf0\x22\x19\xba\x40\xd5\x1c\xe4\xc5\x31\x0d\x31\xda\xd9\x0e\x89\xb2\xa4\x76\xd8\xd3\xd9\xdb\xe1\xb0\x6f\x1d\x21\x9b\x6f\x33\x39\x56\x14\x86\xed\x63\x87\x37\xdc\x9b\xc5\x97\x19\xf5\x3a\xe2\x28\xc7\x61\x94\x43\x03\x1c\x4e\x1d\x11\xaf\xfe\x71\x33\x39\x00\x4c\xe6\xc2\x3d\x61\x53\xb0\x8d\x0d\x81\x7b\xb5\xd1\xae\xee\xc2\x92\x63\xd7\x3d\xba\xce\xfe\x31\xb0\xcf\xfe\x4e\x17\xec\xdd\x7c\xc0\x05\xda\x44\x32\x55\xc3\x09\xf7\x41\x05\xc2\x89\x65\x9a\x5a\x78\xa9\xb7\xf3\xa9\xc0\xa8\xbe\xf6\x8a\x6d\xe8\x40\x7b\x19\x55\x65\x3b\x0f\x75\xd7\x13\x6f\x9a\xa4\xbe\x45\xd5\xb2\x6c\xd3\x35\x25\x53\x8b\xd4\x2b\xd8\x47\x07\x67\x81\x40\x86\xb6\x37\xbd\xd8\xfd\xee\x2c\x24\x09\x3a\x8e\xb2\xd0\x26\x91\x8e\xb2\x57\x1c\xa8\x1a\x94\xa3\x6b\x45\x87\x55\x44\xee\x3a\x69\x94\x45\xec\x87\x5c\xc1\xbc\xf8\xa3\xcd\xf5\xf1\xeb\x56\x95\x1f\x0b\x63\x17\x79\x7c\x16\xac\xdd\xa4\x68\x42\x98\xbb\xc8\xeb\x3d\xec\x85\x57\xbf\x00\x83\xbe\x9d\x9d\x87\xf9\xe6\xb5\x65\xce\xf9\xa9\xaa\x88\xa5\xd0\x76\xe6\x2f\xed\x54\xf1\x10\x30\x21\x00\xee\x23\xdf\x5c\xd8\xd2\xf1\x98\x46\x04\xf4\x1c\x86\x93\xa7\xa7\x1f\x3f\xa2\x97\x62\xd1\x71\xb0\xdf\x58\x4b\x6a\xce\xfd\x59\xc0\xaf\x0f\x9d\x2f\xec\x87\xc4\x7b\xd0\xcb\x3b\x0b\x13\xc9\x36\x70\x12\xf1\x52\xa5\xfd\xe1\xc8\x4b\x55\x76\xeb\xe0\xd0\x0a\xef\xcf\x74\x5e\xa9\x77\x91\xdd\xb1\xd6\x05\x8e\x9e\x48\xaa\x33\x71\xa0\xa6\x41\x1b\x11\x4d\x53\x83\xc0\x38\x60\x92\x2a\xc1\x89\x71\x86\xbf\xbb\xdf\xce\x31\xf9\x74\x9a\x68\x12\x40\xeb\xb3\xf3\x4c\xc1\x42\xdb\x5c\x18\xb2\x77\x20\x58\x53\x2d\x0b\x4c\xe1\x7b\xa2\xaa\x33\x81\x6b\x20\xb9\xe7\x72\xf9\xf6\xf7\x43\x8f\x8c\x7a\xea\x4e\xbc\x43\xc5\x48\xb6\x28\x64\x2b\xc8\xd7\xaf\x7e\xd3\xff\x0b\x41\xbf\x7d\xbb\x46\x2a\xac\xf9\xc1\xda\xff\xf3\xae\x03\x62\xd0\x3b\xeb\x8c\x00\xf9\x40\x4f\x79\x02\x5e\x8c\xc1\xf0\xad\xf1\x07\x44\x65\xf8\x61\x87\x98\x10\x1c\x67\xec\x4b\x02\xc2\xd7\x0e\x16\x3c\x06\x86\xaf\x70\xf9\x2c\x20\xbe\x51\xd9\x84\x50\x7c\x85\xdb\x7b\x30\x8e\x6a\x70\x01\x8e\xcf\x0e\x93\x3c\xd0\x57\x0f\xfe\xe9\x17\x29\xf6\xea\x6b\x0f\x1a\x57\xd6\x74\x71\x11\xfb\x32\xf8\x86\xd6\x3d\xb1\x0e\x8d\x97\xed\xf2\x21\x7a\xfd\x11\xb5\xb2\xfb\x25\x6b\x33\x77\x3d\x81\xc6\x12\x6a\xa6\x05\xc3\xf2\x9d\xee\x7a\xbb\x52\x5a\x68\x6e\x44\xa1\x0e\x5d\x10\x51\xb4\x5d\xa3\x45\x15\x3b\xea\xd4\x00\xee\xc2\x86\x61\xa9\x39\x8e\xfe\xf6\xd7\xdf\xa7\x49\xcf\xbf\xff\x37\x6c\xda\xf3\xd7\xdf\x41\x9b\x43\xdd\x8c\xc8\xa2\x9d\x68\x19\xa6\x01\x2f\x4e\xa2\x4e\xb4\xde\x93\xd9\x6b\xa6\xea\x70\x22\x6e\x61\xd0\x4b\x75\xb3\x36\x30\xa6\xf0\xcc\x2d\xc3\x0b\x75\xd5\x98\x44\x78\x4f\x74\x85\x49\x10\x61\x43\x2b\xed\xf9\x4e\x81\x75\x56\x17\xae\x5d\x1b\x4c\xb6\xa6\x86\xb6\xe3\xf5\xc2\x5f\x7f\x07\xd7\x9b\xe7\x20\xbd\xed\xb2\xad\xda\x53\x28\x9f\x2f\x3b\x0d\xb8\x9a\x04\x9c\xfa\x5a\xb6\x10\x51\xe5\xc3\x78\x71\x38\xbd\x16\x67\x90\xdb\x0d\x18\xde\x51\xc1\x2b\x07\xe3\x3a\x42\xf7\x42\x8a\xd8\x9f\x8c\xf3\x27\x88\x6f\x5b\x42\x3d\x4e\x89\x98\xe7\x06\x2f\x2a\x75\x71\xe9\x15\x47\xc9\xc8\xb9\xc2\xc3\xd4\x8c\x7d\xf4\xf2\xa2\xa2\x57\x80\x2d\x5c\xd5\x1c\x70\x01\xa2\x98\xf6\x95\x8d\x32\x24\xc7\x77\xf9\x2b\xea\x45\x90\xbc\xb4\xe1\x14\x87\x6c\xa9\xde\x11\xda\x5d\xa4\x54\xef\x36\xde\x6d\x3a\x79\x53\x8c\x0e\xf2\xf5\x09\x9b\xa8\x86\xea\xaa\x40\x9b\xec\x0e\x00\xfd\xe1\xbc\x6a\x4f\xcf\xc8\x13\x8e\x62\xdc\x77\x94\xfe\x8e\x12\x08\xc6\xfe\xc0\xd9\x1f\x24\xf3\x07\x4a\xe0\x24\x47\xa7\x50\xfc\xe9\xdb\x9f\xf1\xa8\xe3\x93\xdd\x8b\x1d\x67\x56\x15\x37\x13\xd7\x54\xe5\xcb\x9c\x38\x9a\x62\x6e\xe1\x44\x4c\x16\x0e\x3c\x8d\x51\xaa\xf1\xee\x65\x92\x8b\xfc\x48\x12\x25\xd9\x5b\xf8\x91\x13\x20\xcb\x93\x60\x4a\xee\x22\x0f\x8a\xa4\x08\xfc\x16\x1e\xd4\x64\x87\xca\x87\xf5\x81\xb7\x95\x7b\x91\x05\x4d\xa0\xf8\x4d\x6a\xd0\x07\x16\xfb\x11\x2c\x06\x0b\x96\xc4\xa8\x5b\x58\x30\x13\xdd\x94\x55\x65\x13\x5f\x0b\x16\xa3\xf1\x9b\x58\xb0\x67\x5a\xec\x4f\x70\xc7\xe0\xc3\x90\x34\x71\x1b\x9f\x6d\xa7\x83\xe9\xd4\x86\x53\xe0\x9a\xf6\x65\x9f\xe2\x50\x0c\xe5\x6e\x21\xcf\x79\xe4\x77\xe9\xda\xc9\x5a\xb6\x2f\x53\xc7\x19\xec\xa6\xae\xc6\x50\x8f\xfc\xbe\x17\xbc\x45\xfa\x65\x06\x14\xc7\xdc\x64\x1d\x0c\xf3\x33\x38\x2e\xde\xb6\x03\xc0\x65\x46\x1c\xcd\xdd\xa6\x09\x7e\xd6\xd1\xfb\xe5\xf2\xee\x9d\xe1\x4b\x9c\x30\x94\xa1\xc8\x9b\x7a\x04\x23\x76\xea\x1c\xb3\x13\x17\x7b\x1c\xc3\x70\x86\xbe\x4d\x13\x72\xa2\xa8\xeb\xc3\xfb\x13\xa6\xae\x4d\x14\x15\x6a\x17\x87\x46\x0c\xa3\x30\xec\xa6\x41\x18\xa3\x0e\x53\xb6\x43\x3a\x7f\x7d\x45\x0d\x9a\xb9\x6d\x98\xc7\xe8\x89\x6a\x4c\xa1\xe3\x4e\xde\x6f\x18\x5c\x61\xc5\x70\xec\x6d\x3d\xc2\x9c\xc1\xb5\xb7\x33\x03\x2e\x83\x09\x86\xa3\x28\x41\xee\x99\x44\x60\xed\xc5\x63\x06\xb7\x82\xed\xbb\xa3\x06\x07\xe9\xb1\x67\xe4\xa9\x90\x69\x37\x47\xc5\x52\x15\xcf\x96\x88\x7c\xbd\x45\x66\x86\xd5\x7c\xad\x9e\xab\xe6\xcb\xbd\x7a\xb3\x87\x17\x47\xc4\xb8\x96\xef\x14\x1b\xf5\x5e\x56\x68\xf0\x9d\x01\xd3\xca\x32\x8d\x21\x5e\x0c\x5a\x28\x92\x09\xbe\x65\xc2\x17\x28\xbc\x3b\xa0\x5b\x7c\x86\xee\x16\xea\xb5\x46\xb7\x4a\xe0\x23\xb2\x46\xf4\x5a\xad\x6a\xbd\x5e\x2f\x36\x85\xe2\x88\x2f\x8d\xda\x4d\xba\x93\xcf\xd3\x63\xbe\xdf\xce\x53\xe3\xd6\xe8\xe9\xde\xc3\x24\xdb\x09\xd6\x15\x0b\xed\x0f\xe0\x9d\xce\xce\xfe\xe1\xc0\xcb\x07\x2d\x9e\x11\xfc\x19\x71\xed\x05\x8c\xd1\x6f\xef\x8f\x50\xdc\x32\xf3\xba\x65\xdb\xfe\x21\x9a\x9e\xad\x17\x9e\x11\xec\x79\x77\xfa\xea\xba\xa2\x61\xdb\xf6\xf7\xfa\xe7\x61\xeb\xde\xe7\x9e\x04\x4b\x53\x24\x83\x72\x0c\x8d\x79\x52\x6d\x9d\xe9\xdf\x5f\x76\x23\xec\x97\x1f\xc8\x17\x0c\xfd\x03\xdd\x7d\xbe\x3c\x23\x5f\x4e\x67\x49\xb6\x65\x06\x70\xd5\x25\xfc\xf2\xbf\x51\x9e\x1a\x64\x87\x07\xd8\x6d\x9f\x3f\x90\xdd\x51\x3b\x8c\x60\x29\xe6\xf3\xb4\xdb\xb3\xfb\x34\xed\x18\x8e\x22\x3e\x51\xbb\x1d\xbb\x4f\xd0\x8e\x24\x28\x8e\x21\x71\x92\xa6\x3e\x45\x3b\x3f\xbb\x4f\xd0\x0e\x45\x69\x92\x61\x28\x8c\xe6\x3e\x45\x3b\x3f\xbb\x8f\xd7\x0e\xa7\x18\x9a\x63\x51\x86\x65\x3e\xc5\x33\xcf\xd8\x7d\x82\x76\x18\xc9\x90\x2c\x89\x52\xcc\xa7\x8c\x2a\x67\xec\x3e\x5e\x3b\x6c\x1b\xe2\x2c\x43\xe0\xec\xa7\x20\xc2\x19\xbb\xcf\xd4\x0e\xff\x5c\xed\xf0\x0f\xd7\x6e\xcb\x0e\x67\x59\x92\x43\x29\x8e\xdd\x8d\x99\xa8\xc7\xce\x71\x81\xed\xaa\xc6\x74\x22\x02\x0d\x18\x12\xdc\x31\x46\x4f\xac\x6f\x32\xa0\x9f\x45\xa8\x46\xe8\x07\xea\xb4\x1d\x4e\x76\x4a\xad\xa0\x3a\x9d\x6d\x39\x62\xcf\xc8\x97\xdd\x0c\x68\x32\x87\x9b\x2d\x93\x7b\x27\xc3\x3b\xb1\xae\xcc\xc7\xc2\x8e\x0f\xde\x3b\x1f\x3b\x1c\x21\x3c\x68\xcb\x6d\x17\x34\xa2\x42\x90\x80\x63\x45\x8e\x65\x31\x12\x13\x59\x0a\x13\x25\xa8\xd0\x38\x27\x32\x50\x21\x30\x28\x33\x90\x21\x25\x40\x70\x28\x8a\x4a\xb2\xc2\xe1\x32\x8a\xe2\x80\xc3\x64\x4c\xa2\x39\x82\xda\x2e\x8a\x64\x40\x32\x22\x8d\xe1\xb2\xc4\xca\x94\x88\x2b\x80\x11\x15\x4e\x54\x00\xca\xc9\x22\x86\x29\x84\x2c\x4a\x84\x08\x64\x05\x27\x39\x06\x65\x09\x40\x61\x1c\xc7\xb0\x34\xc7\xb2\x2c\x0a\x18\x56\x79\xf2\x0c\x4d\x04\x96\x57\xf4\x0f\x82\xf9\x41\x60\xc1\x55\x97\xf7\x33\xce\xfc\xc1\x32\x28\xcd\xd1\x57\x4b\xf7\x33\x40\x8a\xa6\xc9\x67\x04\xa3\xb7\xfd\xf9\xee\xb3\xfb\xd1\xfb\xeb\x2b\x3f\x7e\x7d\x46\xb0\xed\xc2\x8a\xe7\x79\x3e\xcb\x59\x45\x77\x56\x95\x5e\xfa\xce\xd2\x62\x52\x62\x6a\x6a\x88\x82\xd2\x14\x57\x8c\xad\x94\xcb\x52\xa9\xa1\x15\xc6\xb0\xa0\x97\xa6\x15\xd8\x9c\x97\xa9\x51\xb1\x9c\x59\x8e\x3b\x0d\x22\x3f\x30\x38\xa5\x4f\xd8\x7c\xa9\x85\x8a\x3a\x37\x75\x8a\x6f\x43\xa5\xc7\xb8\x02\x78\x2b\x4e\xd3\xec\x96\x34\x3f\x6c\xf6\x6b\x9b\x15\x7f\xfc\xc8\x83\xb7\x4e\x71\xa6\x64\xdf\x86\x85\x6a\x69\xde\x68\xbc\x98\x59\x6a\xa4\xb3\x8d\x8c\x65\x5b\x45\x4a\x12\x1a\x95\x5c\x3d\xff\x92\x67\xf4\x22\xa6\x10\x9d\x4d\xbf\x3f\x86\xc5\x11\x85\xda\x1d\x73\x9a\xc1\xbb\x5a\x6d\x5c\x91\xd8\x82\x94\xed\x98\x7a\x7d\x90\x62\x6c\x8b\xa9\xcb\x8e\xe6\xd1\x9f\xd7\xc9\x2a\x78\xb3\xf0\xd6\x89\x19\xdf\x34\xf9\x90\xcf\x98\x1f\x62\x64\x8b\xe7\x73\x68\x39\xac\xf8\x3f\xfa\xb3\xf3\x2a\x34\x22\xf2\x83\xb1\xc0\x3e\xc6\x8f\x9f\x18\x89\x82\x9c\x48\x41\x89\x85\x10\xa3\x20\xa5\x88\x32\x44\x49\x94\x26\x39\x8e\x63\x08\xc0\x52\x00\x95\x39\x54\xc4\x49\x02\xc8\xb2\x04\x51\x09\x53\x14\x8c\x06\x2c\x85\xa1\x1c\x83\x42\x74\xb7\x58\xc3\x42\x63\x01\x8d\xf4\x76\x96\xc3\x08\xfc\x6a\xe9\x6e\xce\x49\xb0\x04\xcd\x5e\x88\x05\x26\x66\x28\x10\x6b\xa8\x63\x4c\x89\x99\x0d\xb5\x14\x47\x0a\x99\xb9\x3e\x96\xe8\x19\xc8\x8d\xb3\x9b\x16\x4d\x48\x64\xad\x98\xce\xbf\xce\xda\xd9\x61\x6e\x5a\xe9\x2c\xdb\x1b\x15\xcf\xce\xd2\x76\x2f\x3b\xcd\x32\xfa\x72\x23\x4c\xe7\x66\xe7\x65\x55\x35\x2d\x5c\x30\x52\x4a\x65\x48\x2e\x18\xa6\xc3\x39\x5e\xd7\x79\xa1\x30\x3d\x75\x25\x36\x18\x6f\xa8\x62\xfd\xad\x55\xa0\x97\x78\x7a\xd3\x52\x64\x33\x8d\xb1\xbd\x26\x5e\x53\x89\x6a\x63\x98\x2a\x3a\xa5\xfc\xea\xc5\x6d\x8e\x08\xf9\xb5\xb9\xe1\x37\x6f\xa8\x58\xcb\x88\x38\xbd\x64\xdb\x5c\x7d\x93\x97\xd9\x4c\xcb\xa6\x4b\x4a\x77\x68\xf5\x14\xf3\x75\xa0\x5a\x6b\x59\xcc\x7a\x94\xa7\x21\xa1\x50\x61\xc3\xdc\xe9\xff\x79\x28\x60\xf1\x43\x81\x79\x8c\x1b\x3f\x29\x94\x4c\x41\x09\xa7\x59\x4e\xc6\x58\x46\x01\x12\x90\x29\x5c\xc2\xa1\xc2\x91\xa8\x82\x8a\x04\x60\x69\x16\xc7\x25\x9c\x84\xac\x22\x03\x08\x24\x85\x56\x18\x02\x63\x64\x82\xc6\x08\x12\xd2\x17\x42\x01\xe7\xa2\x9c\x7d\x0b\x53\x58\x24\x2c\x78\xa5\xcc\xd3\x71\x81\x82\xa1\x0c\x7e\x21\x14\xe8\x98\xa1\x90\x1e\xf6\x99\x2c\x28\xa3\x23\x85\xde\xb8\x3d\xa7\xba\xd4\x78\xb6\xda\x30\x41\xb6\x9a\xed\x9a\x69\x40\x3b\xdc\x52\x5a\x2b\xdd\x51\xb7\xab\xab\x44\x61\xec\x38\xcd\xc5\xdc\xa5\x32\xa4\x35\xe0\x8c\x11\xe4\x55\x4e\x22\x95\x4c\x39\x5d\xc0\x51\x94\xcb\x0f\xbb\x29\x60\x2a\x4d\x03\xf5\xba\xce\x0b\x05\x9f\x77\x36\xa6\x1d\xbd\x94\xd5\x1a\x6b\xae\x3c\xe4\x24\x7c\x9a\x7f\xa1\x75\x91\x1f\x2c\xf0\x0d\xa6\x6b\x0d\x74\x5e\x90\xb5\x15\x35\xcb\x4b\xa3\x37\x6c\x51\x1f\xd8\x73\xbe\x5f\xd6\x18\x56\xef\xda\x26\xb3\x32\xcd\x69\xad\xd8\xd7\x37\xd3\x0c\xa9\x94\xad\xd2\xcb\xa2\x65\xa3\xf3\x62\xdf\xec\x79\x94\xa5\x90\x50\x28\x8f\xc2\xdc\xe9\xbf\x27\x14\xe8\xc7\xb8\xf1\x13\x05\x20\xcb\x52\x28\x03\x15\x49\xa1\x49\x9a\x66\x69\x99\x80\x32\x4a\x10\x38\x86\xe1\x24\x85\x73\x0a\x23\x72\x1c\xce\x8a\x0a\x4a\x11\x98\x22\x43\x02\x03\x80\xa2\x44\x00\x08\x11\x55\xa0\x74\x29\x14\xd8\x48\x67\xc7\x50\x14\xa7\xae\x96\xee\x57\xb3\x04\xc3\xd0\x17\x42\x81\x8a\x19\x0a\x98\x6d\xce\x5a\xca\xf2\x0d\x6f\xeb\x33\xb7\xe9\xf2\x6f\xa5\x76\x39\x5f\x51\x20\x35\x37\x97\xab\xde\x3a\x0d\x6b\xc0\xea\x2f\x5e\x1b\xab\xb4\x63\xa4\x53\x56\x4a\xec\x1a\xcc\xc2\xd4\x36\xa3\xc5\x86\x2a\x57\xf0\x6a\x16\xb3\x87\x45\x6c\x35\xd2\xc4\x29\x26\xd8\xe9\x5c\x07\x37\xb4\x96\x2f\x14\x7c\x5d\xf9\xfa\x3a\xcb\xd4\x67\x9d\x94\x39\x42\xf3\xaf\xe9\x76\xc7\x12\x84\xb9\x99\x9a\x1b\x7d\x9a\xb6\xd0\x91\x96\x4d\xe5\xd4\xbe\x82\x16\x46\x5a\xb6\x30\xe5\x46\x25\x83\x6e\x76\x04\xa5\xda\x77\x8c\x69\xb5\xd0\x6f\x96\xf8\x9a\x98\x19\x75\x3a\x69\x93\x29\x93\x43\x01\xc7\x28\x8e\xaa\xd0\x15\x6f\x82\x34\x0a\x09\x85\x22\x1a\xe6\x4e\xff\x3d\xa1\x40\x3d\xc6\x8d\x9f\x30\x54\xa4\x31\x1a\x63\x49\x02\x8a\x9c\x4c\x53\x38\x44\x39\x82\x64\x69\x05\xb0\x18\x43\x2a\x1c\xa1\x48\x24\x09\x28\x82\x65\x19\x94\xdd\x52\x54\x50\x20\x91\x8c\x0c\x58\x05\x00\x9a\xc2\x2e\x85\x02\x13\xe9\xec\x38\x4a\xd1\xd1\x81\x72\x28\xdd\xa5\x3e\x08\x9a\x64\xd1\x0b\xa1\x40\xc6\x0c\x85\x75\x16\xcf\xcf\x66\x39\x9a\xc2\xb4\xea\x74\x8e\xce\x96\xaf\x19\xb9\x39\x4f\xaf\x05\xab\xab\x16\xb3\x59\x83\x60\x2b\xeb\x22\x6e\xa6\x5e\xc7\xed\x1c\x83\xf2\x6d\x34\x83\x36\xf4\x34\x9e\x2e\xe7\xa6\xae\x89\x8d\x89\xa2\xdc\xa8\x67\xa8\xae\xdc\xe7\x07\x6c\x6a\xd1\x9d\xdb\x14\x20\xa7\xa7\x50\x58\xfb\xd6\x0a\xca\x98\xb2\xd3\x2a\x5f\x92\xd1\xe2\xa8\x99\x2e\xb3\x94\x39\x30\x97\xd6\x60\xb9\xb0\x14\xe2\xad\x2a\x6f\xd0\xd1\x4c\x90\x33\x4d\x63\x80\xd3\x15\x58\xaf\xbf\xcd\xfb\x03\x75\x99\x65\x9d\xba\x49\xc8\xd6\x42\xb4\x86\xaf\xaf\x54\x6a\x44\xda\x6e\xcb\x36\xf2\x86\xc5\x75\x05\x23\x65\x78\x13\xb0\x5e\x48\x28\x14\x5a\x61\xee\xf4\xdf\x13\x0a\xe4\x63\xdc\xf8\x89\x26\x19\x59\x84\x24\xc5\x31\x8c\x08\x19\x5c\x94\x68\x05\x32\x84\x88\x11\x22\x45\x32\x34\xe0\x08\x91\x44\x29\x49\x66\x00\x45\xe3\x40\xc1\x58\x8e\xc6\x59\x89\x91\x44\x99\xc4\xa0\xc4\x72\xfb\x50\xc0\x43\xbd\x3a\x7a\x0a\x44\x60\x14\x1d\x3d\x7d\x3a\x94\xee\x32\x49\x34\x87\xb1\x97\xd6\xcd\x44\xcc\x50\xc0\xdb\xdc\x72\x3e\x18\xc2\x94\x64\xaf\x97\xd4\x9b\xd3\x75\x7b\xf2\xeb\x9c\x69\xe5\xdf\x86\xd6\xa0\xb2\x2c\x94\x47\xe6\x9a\x5d\xf6\x8a\x8e\xda\x56\x9b\xe4\xa0\x00\x28\x01\xa3\x36\x45\xb1\x9c\xce\xbf\x38\x0c\x30\xd4\x9c\xd4\x5c\x16\x97\xad\x65\xbb\xdd\x05\x53\x0b\x2e\x36\x78\x75\x2c\x79\x5d\xe7\x85\x82\x6f\xad\xb0\xec\xa9\xac\x45\x97\x79\x7d\xd8\x06\x16\x55\xa4\x59\xa6\x91\x6a\x0c\x25\xbe\x52\xc7\xd3\xe9\xac\x53\x1d\x8b\x9b\xf5\xa0\xda\xd7\xc6\x22\x37\xee\xd5\x36\xe5\x51\xdf\x1c\xd9\x2f\x25\x4a\x9f\x11\x4a\x1f\xcd\x00\xe2\x75\xdc\x2f\xda\x69\xad\x32\x5d\xa6\xa5\x39\x96\x57\xea\x19\x92\xf2\xe8\xb7\x42\x42\x41\x70\xc2\xdc\xe9\xbf\x27\x14\x88\xc7\xb8\xf1\x13\xcb\xc8\x04\x23\x4b\xa2\x08\x64\x52\x94\xa0\x4c\x03\x49\x01\x14\xcb\x29\x5b\x1f\x94\x21\x60\x09\x8e\xe0\x14\x05\x55\x30\x59\x54\xa0\xc2\x71\x0c\xce\x48\x9c\xc8\x42\x49\x44\x21\xa1\x5c\x44\x85\xe8\x29\x10\x89\xb3\x44\x34\x2a\x6c\x4b\xbd\x50\xd8\x65\x04\x31\x96\xbd\xb4\x6c\xc6\x62\x86\x02\xa9\x74\x15\x69\x41\x63\xd5\x37\x17\x38\x29\x4d\x55\xf4\x82\x01\x5f\x73\x73\x2a\xbd\x62\xe5\x65\x2a\x35\x96\x8c\x8d\xf8\xe2\x38\x8d\xe6\x9a\xb6\x98\x8a\xfe\x66\x56\x5f\xe9\x6e\x51\x5b\xb9\x6f\x72\x7b\xa8\xca\x75\xae\x85\x39\xa9\x92\xd9\x5b\x42\x73\x8d\xaf\x0a\x1d\xbe\x6f\x8c\xe6\x5e\xd7\x79\xa1\xe0\xf3\x4e\x25\x6f\xf4\xc6\xb5\xb5\x25\x81\x76\x7e\x3a\xa0\x59\xb2\x6c\xa8\xbd\x42\x5a\x7e\x1b\x53\x2f\x06\x09\x9b\xb8\x3e\x66\xab\xa5\x82\x69\x74\xec\x52\x4b\xcb\x36\x98\xd1\xb0\x93\x69\x6b\x4e\x39\x8b\x67\xf4\x4e\x39\x4b\xe7\x5f\xf3\xcb\xd9\x5b\x8f\xa6\x97\xc5\xb9\x5a\x97\x9c\xbc\x43\xcf\x3c\xca\xb5\x90\x50\xc8\xcc\xc3\xdc\xe9\xbf\x27\x14\xf0\xc7\xb8\xf1\x13\x4d\xc8\x1c\xab\x50\x04\x0d\x21\xcd\xca\x98\x88\x33\x22\x25\xb2\x9c\x82\x13\x40\xa1\x08\x0c\x13\x19\x8a\xe6\x00\x4e\x2a\x40\xc1\x48\x94\x00\x32\x2a\x52\xb8\x48\x13\x84\x88\x32\x22\xe4\xb6\x1e\x8b\xee\x52\xf1\xef\xbd\x9a\x8c\x74\x76\x0a\x67\xe9\xe8\xe9\xd3\xa1\x94\xa5\x58\x8e\x23\x48\x8a\xbb\xb4\x6a\x8e\x09\x09\xcd\xf1\x0b\x56\x5f\x50\x26\x2a\x96\x99\x01\x69\x6c\x1a\xcb\xde\xba\x40\xf4\x2d\x73\x9e\x5a\xe6\xf9\x86\x9b\xc5\x2a\x78\x8d\xc9\x30\xf4\x78\x31\x6e\x17\x6d\xae\x27\x0f\x2b\x62\xb7\xa2\x4a\x9a\xd2\x78\xd9\x30\xf8\x68\x9c\x2f\xf7\xe6\xe5\x66\x5f\xaa\x74\xa9\x99\xbb\x34\x6d\x1d\xdb\xf9\xa3\x17\x07\xde\xb7\xd2\xf1\x0f\xef\x15\x39\xa7\xe7\x15\xdf\x6c\xed\x3d\x96\x78\xe3\x66\x3a\xdf\xb1\xaa\x9c\xcb\xf7\xd7\x73\x77\x9d\x23\x86\x9d\x86\x45\xa8\xee\xba\xb3\x14\xf4\x1a\xcd\xf7\xe6\xab\x4c\x87\x14\xda\xc6\x32\x55\x75\xdd\xf4\x46\x7a\x4b\xaf\xd9\x74\x4a\xcb\x67\x58\xd4\x36\xfa\x6b\xe6\x05\xaf\xd9\x3a\xce\x09\xd6\xc2\xe9\xb5\x53\xd3\x25\x37\xde\xf1\x0f\x89\x93\xf0\xcf\xff\xf3\x38\x41\xe3\xc7\x09\xf6\x18\x1f\xf7\x5e\x6f\x38\x78\x3a\xc6\x31\xe8\x77\x14\xfb\x8e\x62\x08\x8a\xfe\xf0\xfe\x8b\xf6\x65\x96\xe5\xa2\x07\xfd\x43\x29\x89\x73\x24\x47\x33\x38\x77\x69\x51\x1c\xee\xe9\x3b\x91\x7e\x75\xa7\x44\x7f\x32\xc3\x8a\x4a\x6e\xd2\x9b\x4e\x25\xc3\xe4\x8c\x1c\x57\xc4\xd1\xf5\x4b\x26\xe5\xa0\x53\xd7\x59\x95\x56\x6f\xd8\x50\xee\x0c\x46\x20\x53\x06\x79\x6f\xde\x23\xdc\xec\xc4\x51\x60\xf0\x9f\xfc\x39\x39\xf1\x95\x1d\xb9\x18\x37\x0f\xdc\xbb\x41\x17\xf1\x56\x45\xd4\xf9\x29\x3c\x22\xe2\xae\x90\x09\x9e\x8b\xc2\xee\x23\x43\x04\x0f\x20\xdd\x47\x86\x0c\x1e\x9b\xba\x8f\x0c\x15\x3c\x30\x74\x1f\x19\x3a\x78\xcc\xe9\x3e\x32\x4c\xf0\x80\xcf\x7d\x64\xd8\xe0\xb1\xa4\xfb\xc8\x70\xc1\x03\x39\xf7\x91\xc1\xd0\xe0\x39\xa2\x3b\xe9\x04\x4f\xec\xdc\x2b\x4f\xf0\x28\xce\xbd\xf2\x10\xc1\x43\x2f\x77\xd2\x21\x83\x67\x75\xee\xa4\x43\x05\x8f\xa9\xdc\x49\x87\x0e\x9e\xae\xb9\x93\x0e\x13\x3c\x58\x72\x27\x1d\x36\x78\x1e\xe6\x4e\x3a\x5c\xf0\xe4\xc9\x9d\xe3\x20\x1a\x3c\x5e\xf2\x98\xab\x57\x1e\x72\x82\xf7\xf2\xcb\x71\xcf\xc8\x56\xf8\x78\x47\x97\x23\x6e\x20\x49\x8c\x51\x3e\x24\xf0\xa3\xc9\xe9\x01\x3d\xae\xc9\xff\xfd\xc5\x35\xbd\x93\x32\x77\x9e\x4d\xff\xf2\x8c\x7c\x51\x6c\x53\x4f\x74\xda\xe6\x19\xb9\xf5\x20\x54\xc2\x83\xee\x37\x59\x6f\x8f\x7e\xa7\x07\xfa\x1f\xeb\xdd\x60\xbd\x1d\x5a\x9f\x1e\xf0\x7f\xac\x17\xcb\x7a\xfe\xd9\xc5\xe9\x81\xfc\xc7\x7a\xb1\xac\xe7\x9f\x0c\x9d\x1e\xd8\x7f\xac\x17\xc7\x7a\xe7\x53\xc0\xe3\xc3\x3f\x91\x1b\xcf\x7a\x67\x13\xd6\xe3\xc3\x3f\xa8\x11\xcb\x7a\xe7\xd3\xe2\xe3\xc3\x3f\x33\x96\x1b\xad\x87\x07\xac\x87\xff\x63\xbd\xeb\xd6\x3b\x5b\xba\x1c\x1f\x48\xdf\x09\x7a\x65\x61\xc8\xd0\x4e\x6a\xc1\xfd\xeb\x8e\x49\x8d\x18\xe3\x38\x7f\xc2\xd7\x4e\xaf\x2c\x60\x42\xee\xfb\x4b\x70\xeb\xc5\x4d\x37\x98\xdd\xbb\x48\x8a\xbc\x37\x24\x34\x95\x87\x46\x2f\xa9\xaf\x12\xc2\x83\x2b\xae\x7b\x09\x11\x81\xc5\xc7\xdd\x12\x91\xc1\x55\xcc\xbd\x84\xa8\xc0\x84\xfe\x6e\x89\xe8\xe0\xca\xe0\x5e\x42\x4c\x60\x92\x7c\xb7\x44\x6c\x70\xb6\x7d\x2f\xa1\xe0\xc4\xf3\x6e\x89\xce\x93\x7b\x6c\x02\x91\xce\xd3\x7b\x49\xfa\xed\x3c\xc1\x97\xa4\xe3\xce\x53\x7c\x49\xbc\xfb\x3c\xc9\x97\xc4\xbd\xcf\xd3\x7c\x49\xc6\x80\xf3\x44\x5f\x92\x41\xc0\x4b\xf5\x9d\x41\xd2\xdd\x94\xd8\x00\xa5\xe8\xe4\xda\xad\xb7\x0c\x3e\x22\xbd\x76\xed\x4a\xa6\x67\x64\xab\x40\xbc\x04\x5b\xe4\x9d\x82\x0f\x40\x0f\xff\x55\x3a\x80\x20\x39\xc8\x10\x04\x06\x39\x02\xe0\x14\x46\xd0\x0c\xce\x32\x10\x67\x48\x45\xc4\x68\x8e\x03\x22\x50\x18\x9c\x10\x65\x48\x30\x00\x8a\x90\xa3\x71\x92\x95\x18\x5a\x91\x09\x94\xc1\xc0\xd3\x33\xb2\x7b\xf7\xf7\xfe\x49\x8e\xef\x2c\x0c\x47\x1e\x0e\x42\x46\xbf\x81\xc5\xb2\x91\x47\x6f\x8e\xa5\x67\xe0\xb5\xdf\x34\x25\xe4\xae\x4b\xf3\x7c\x4a\x1f\xdb\xc5\xee\x70\x39\x68\xd4\x88\x8e\x90\x77\x01\xca\x6c\x8a\xab\x4c\xa1\xb4\xe4\x4a\x96\x32\xce\x0c\xca\xf0\xb4\xd3\x58\xdb\xfe\x29\x04\xf6\xf4\x32\xa7\xaf\x82\xf7\x77\xb4\x5c\xc9\x59\x2e\xdb\x76\xec\x91\x94\x93\xc7\x83\x7a\xc1\x79\x05\x75\xa5\xdb\x66\xc5\xcd\xca\x79\x59\x88\xad\x76\x91\xd7\x44\x36\xa3\x48\x3e\x32\x87\x4d\xcd\xfd\x47\x9e\xe7\x47\x1a\xe9\x91\x5f\x16\xf0\x92\x60\xf2\xd3\x52\x6e\xaa\x74\xc6\x59\x34\x47\x66\x35\xbe\xa6\x2d\x7b\xac\x9d\xd5\x0d\xac\xec\x4e\x6d\xdd\xe5\xb9\x62\x67\xd6\x77\x5e\xcd\x5a\x13\x6e\xb2\xac\x2d\x0e\x17\xa9\x9c\xfa\xf6\xca\x90\x1b\xae\xdb\xd1\xb0\x34\xd7\x24\x98\xd1\x88\x9b\x0f\x94\x1e\xca\x99\x99\xd5\xcf\x9f\x4f\xfe\x0d\x64\xff\x71\xcb\x56\x98\x6e\xfc\xa9\xbe\x57\xee\x1d\x70\xc8\x6d\xff\x64\x7d\x4d\x73\x32\xd6\x20\x4c\x3e\x47\x8f\x75\x47\xae\x43\x6e\x44\xbe\xc9\xa5\xd6\x00\xb3\xbb\xcb\x92\xc2\x0b\x23\x35\x8d\xaa\x1a\x77\xd0\x8d\xcf\xd6\x04\x15\x28\x27\xdb\xe6\xc3\xb7\x4d\x85\xa8\xfd\xd4\xcc\x83\xf9\x07\xfb\x36\x16\xff\xcc\xa9\x7d\xc9\x57\xa4\xa6\x33\x68\x15\x2d\x17\x36\xee\x6c\x55\xc7\xb4\x11\x0a\x36\x96\x89\x71\xf5\xe2\x7a\x59\xcd\x6e\x1a\x94\x9b\x11\xa4\x6c\x7f\xb9\xca\x73\x2b\x62\xea\xda\x79\xa2\x80\x17\xa4\xab\x3c\x23\xf7\xc7\xbd\xfa\xe5\x04\xfc\x39\xa1\x57\x49\xc0\xbf\x16\xe0\xcf\xd7\x89\x1e\x03\xa7\x7c\xd3\xd2\xc1\x1a\xc5\x18\xec\xe5\xa5\x8e\xce\x32\xe2\xc0\x6d\xb0\x33\x96\x6f\xab\xd5\x74\xa7\x32\xc4\x5b\x7d\x75\xe8\x1d\x00\x28\xad\x3a\x65\x6b\xf7\x52\xd4\xee\x78\x7c\x42\xfd\x6f\xe6\xff\xda\xb3\xb5\x3b\xf9\xfb\x62\x69\xca\x87\xf8\xc2\x3d\xb6\x58\x98\x27\x59\x7a\x9f\x6d\x8b\x55\xa7\xec\x0a\xf7\xf1\xdf\xd9\xe2\xdf\x1f\x35\x68\x79\xeb\x40\xef\x4a\xd2\xc3\xe9\x9c\x38\x7f\xb7\x18\xeb\x1d\x9b\xb9\x3e\xd3\xf0\x5f\x65\x06\x18\x8c\x83\x00\x15\x25\x5a\x91\x31\x16\x65\x71\x49\x04\x50\x62\x65\x4c\x41\x69\x09\x65\x48\x48\x4b\x34\x00\x0c\x4b\x2a\x80\x83\x90\x53\x50\x11\xc5\x28\x49\x61\x01\xc1\xb1\xa2\x4c\xed\xc0\x30\xd1\x55\x46\x7e\x30\xa4\xae\x82\x21\x16\xfd\x52\x9a\x57\x88\x3d\x05\x96\x4d\x49\xb1\xb0\x18\xe8\xfc\x0f\xc7\xc2\x75\x81\x18\x8b\x59\x52\x7e\xd1\x32\xc3\xd5\xa0\xa5\xca\x5d\x58\x16\xd3\x4c\x0b\x57\x6c\xb4\xd0\xcc\x61\xfa\x3a\x8d\x8b\xf9\x54\xaa\x28\xa4\x60\xa6\x69\x57\x9a\xa8\xa9\x61\xfd\x4e\xbd\xd7\xea\x83\x01\xa3\xd7\x24\x39\xff\xd2\x92\xba\xc5\x8e\x98\x5a\x64\xcc\xd7\xd4\x5c\x26\xe4\xec\xf4\x3f\x03\x0b\x2b\x5a\x85\x4a\x8a\x45\x0f\xe4\x1f\xec\xdb\x58\xfc\x7d\x58\xf8\x0b\xb1\x28\x29\x16\x16\x72\x99\x4d\xe3\x57\x62\x61\x00\x8b\xa4\x84\xfa\xdf\xcc\x7f\x3e\xac\xcf\xee\xe4\x1f\x8a\x85\xbf\x08\x8b\x1e\x62\x8b\x55\xa7\x6c\x4f\xef\xe3\xbf\xc7\xc2\x8f\x1a\xb4\x3e\x13\x0b\x71\x4a\x86\x32\x85\xcb\x1c\x81\x91\x18\x47\x41\x9a\x60\x25\x86\x62\x45\x1a\x42\xa8\x30\x92\x8c\x32\x12\x2a\x29\xa4\xc4\x72\x34\xcd\x31\x0a\x2d\x53\x92\x88\xe3\xac\x44\x92\x32\x90\x64\x99\xdd\x61\x21\xf1\x28\x2c\xa4\xaf\x63\x21\x81\x47\x5f\x56\xb0\x2d\x25\x9e\x02\x19\xbb\xa4\x60\x58\x0a\xf4\xfe\x87\x83\x21\xc0\x5f\xed\x15\x45\x36\x31\x6d\xc9\x95\x0a\xb5\xca\xcb\xb0\xa0\x64\xeb\x9a\x24\x67\xdb\x43\x8d\x20\x96\x14\xd3\x4f\x2d\x78\x7d\x3c\x52\xb0\xde\xb2\x50\x73\xc0\x5c\xae\x8b\xe3\x7c\x51\xa8\x4f\x19\x6a\x29\x1b\xeb\x1a\x09\x8a\x1b\x5e\xb2\xbb\x35\xb3\xd3\x7d\xdd\x2c\x6b\x12\x93\x6d\xfd\x67\x80\x61\x39\xff\x36\x4a\x0a\x46\x0f\xe4\x1f\xec\xdb\x58\xfc\x1f\x03\x86\x49\xc1\x28\x31\x18\x96\xd2\xad\xce\xaf\x04\xc3\x00\x18\x4d\x13\xea\x7f\x33\x7f\x38\x5e\xca\x77\xf2\xff\x08\x30\xbc\x17\x8c\x1e\x62\x8b\xc0\x22\xfd\x0e\x30\xfc\xa8\x41\xeb\x33\xc1\x50\x11\xa1\xc8\x52\xa4\x48\x31\x12\x03\x01\x4b\x11\x28\xce\x2a\x38\x01\x45\xc8\x60\x32\xa4\x31\x09\x83\x92\x28\xb3\x80\x26\x15\x9a\x24\x18\x19\x30\x04\x05\x21\xc1\xb0\x2c\x21\x41\x8a\xda\x82\x21\xfb\xc0\x2c\x29\x71\x78\x47\x36\xfa\x6e\x1e\x02\x8f\xbe\xe3\xea\x50\x7a\xb6\x59\x74\x17\x18\x56\x79\x3e\x2a\x93\xf7\xe1\x60\x68\xf3\x7c\x69\x64\x65\xc8\x42\x63\xd4\x78\x7d\x29\xab\xab\xca\xb2\xed\x8c\x53\x7d\x82\x1f\x0f\x9d\x59\xb7\xda\x12\xa9\x5a\x7b\xd9\x58\x2c\x60\x5a\xeb\x80\x55\x1f\xc3\xd5\x7a\xa7\x2b\x64\x4a\x56\xb3\xf1\x3a\xea\x49\xe8\x4c\xe9\x2f\xe4\x81\xa2\x57\x65\x1c\x0c\xc6\x54\xaf\x25\x73\x67\x01\xcc\x27\x04\x43\x5f\xa5\x5b\xc1\xa8\xfe\x42\xb1\xaf\x27\xdb\x46\x8c\xc0\x57\xc0\xf0\x71\xfc\xef\xca\xd2\xfa\xc0\xd0\x07\xe6\x37\xaf\x0c\xd7\xe5\x51\x36\x29\x18\xfe\xc2\x2c\x6d\xe2\xcc\x20\xde\x34\x36\x49\x33\x83\xbf\x28\x33\x19\x0a\x86\xc5\x64\xb6\x40\x6b\x27\x59\x22\x94\xfe\x38\x5b\x04\xfa\xe2\x16\xfe\x7b\x30\xfc\xa8\x41\xeb\x33\xc1\x50\xc6\x01\x8d\x8b\x0a\x23\x72\x10\xc3\x58\x11\x63\x71\x89\x20\x44\x5c\x91\x39\x42\xc4\x25\x09\x47\x31\x42\x16\x21\x07\x58\x99\x61\x14\x82\x02\x38\xc1\x89\x0c\x2a\xb1\x80\xa6\x19\x48\x41\xea\xe9\x19\x61\x1e\x08\x86\xf8\x95\x95\x21\x87\xa2\x18\x13\xfd\x6a\xe6\xa1\xf4\xec\x98\x42\xd2\x95\x61\x70\x94\xf8\x70\x30\x94\x2a\xc6\xb0\x8a\x49\x36\x03\xba\xf3\x11\x4b\x28\x14\xd5\x98\xa1\xb5\x74\xb3\xfe\xd2\xec\x74\xc1\xd8\x34\x73\x25\x45\x37\xc7\x6f\x18\x9d\x99\xe6\xea\x1c\x39\x7b\xb5\x41\x99\x21\x96\x7a\x5b\x2e\xea\xaf\x6e\x19\x54\x46\xf2\xca\x95\xea\x53\x73\x29\x0b\xcb\xfe\x3a\x3f\x02\xa5\xcc\x03\xd3\xa4\x19\xdf\xb5\x32\xb7\x82\x51\x33\xd7\x86\xb9\x93\x6d\x73\xe1\x51\x77\x05\x8c\x1e\xc7\xff\x2e\x30\xf6\x81\xa1\x2f\xcd\x7b\x33\x18\xd9\x55\x2a\x95\x14\x0c\x7f\x21\x18\x27\x06\x00\xb6\x9e\x27\x93\x02\xc0\x2f\x02\xa0\x50\x30\x2c\x24\xb3\x05\xb5\x3a\xc9\x52\xfb\x6c\x5b\x04\xfa\xe2\x16\xfe\x7b\x30\xfc\xa8\x41\xeb\x33\xc1\x50\x24\x49\x8e\x93\x64\x52\x94\x18\x16\xa7\x71\x42\xe1\x80\xc4\xd1\x14\x89\x92\xa8\x4c\x72\x12\x46\x91\x0a\x10\x69\x20\xb2\x32\x4b\x88\x38\x86\xa1\x28\x8a\x4b\x34\x8e\x02\x0a\x8a\x0c\x89\x32\x4f\xcf\x08\xfd\x40\x30\xc4\xae\x81\x21\x86\xe2\x14\x71\xe1\xf6\x3e\x9c\x22\x9f\x02\xe7\xe3\x92\x82\x61\x70\xc0\xfe\x70\x30\xe4\x33\xca\x1a\x60\xee\xb2\x9a\x9b\x56\x2a\x6d\xc3\xe9\xaf\x74\x8e\x29\xc0\xb1\x5e\x74\x97\x99\x32\x84\x18\xde\x22\xb9\x95\x03\xeb\xcb\x4a\xf1\x65\x25\xa2\x40\x7f\x1d\x16\xca\xfd\x51\xbe\xce\x34\x0b\x45\x6a\x3c\xa6\xe8\x0e\xe4\x0a\xcb\x8d\x5a\xe5\xb8\xb7\x6a\xb5\xfb\x86\x73\xb9\x07\x9e\x9f\xc9\xf8\x32\x4a\xb7\x82\x51\x4b\x35\xd3\xd2\xc9\xb6\xd9\xf0\xa8\xbb\x02\x46\x8f\xe3\x7f\x1f\x18\x9f\xda\xfb\x56\x96\x37\x83\x91\xd6\x10\xe9\xa4\x60\xf8\x0b\xc1\x38\x29\x00\x94\xb3\x95\x17\x2e\x29\x00\xfc\x22\x00\x0a\x05\xc3\x7c\x32\x5b\xa4\x7b\x27\x59\x22\xb2\xf7\x1f\x66\x8b\x60\x5f\xdc\xc2\x7f\x0f\x86\x1f\x35\x68\x7d\x2a\x18\xb2\x8a\x4c\x41\x1a\xca\x84\x8c\xd3\x14\x0b\x00\x4d\xa3\x24\x4a\x60\x1c\x44\x19\x1a\x12\x28\x8a\xd2\x0a\xc3\x51\x28\xc4\x58\xc8\x01\x94\x80\x18\x94\x65\x08\x65\x45\x92\x44\x91\xc4\xb6\xcb\x30\xea\x81\x60\x88\x3e\x23\xf8\x45\x30\xc4\x51\x86\xb9\x74\xbb\xe7\xae\xf4\xec\x60\xf6\x3d\x60\xc8\xef\xee\x97\x0d\x1d\xb0\x3f\x1c\x0c\x47\xec\x5b\x0b\x76\xb5\x39\xfd\xba\xc0\x14\x38\x4b\xe3\x84\xcb\x09\xb5\xb5\x61\x36\x06\x29\x5a\x37\x0b\xfa\xcb\xb0\xb2\xd0\x29\x26\x33\x9f\xb7\x5e\xe9\x37\xb3\x9f\xee\x4b\x6a\x99\x29\xf5\x4b\x96\x9a\x7a\x69\xf6\xc7\x9d\x79\xaa\xd2\xb1\xb3\x2d\x99\xd7\x69\xa1\x4f\xbe\x64\xc4\x65\xe6\x81\x69\xd2\x4c\x82\x3d\xbb\x4e\x96\x9f\x62\x27\xdb\x66\xc2\xa3\xee\x0a\x18\x3d\x8e\xff\x7d\x60\x7c\x6a\xef\xab\x78\x33\x18\x29\x2d\x0e\x4f\x0a\x86\xbf\x10\x8c\x13\x03\x40\xa9\x94\xcd\x25\x05\x80\x5f\x04\x40\xa1\x60\x28\x24\xb3\x85\x40\x9e\x64\x49\xea\x0b\x49\xfb\xe2\x16\xfe\x7b\x30\xfc\xa8\x41\xeb\x53\xc1\x10\x10\x2c\x64\x24\x1c\x25\x45\x42\x61\x81\xc8\x72\x28\x03\x48\x91\xa3\x31\x96\xc4\x18\x96\x22\x45\x49\x12\x29\x12\x30\x0a\x20\x39\x12\x10\xb4\x44\xc8\x18\x4b\x89\x22\x49\xc9\x28\x23\xd3\x4f\xcf\x08\xf9\x38\x30\x64\xb9\x3d\x18\x86\x5f\xec\xeb\xdd\xd1\xcb\x44\xbf\x59\x71\x2c\x3d\x7b\x23\x28\x29\x18\x06\x07\xec\x6c\xc0\x09\x1f\x03\x86\xbb\xab\xe3\x6e\x18\xd0\x4e\x4d\x33\xca\x70\xe6\xa3\x94\x39\x3a\xb9\x90\x79\xeb\x12\x46\x53\x47\xd7\xee\x82\xce\xce\x7b\xd4\x8b\x3a\x5c\x64\xf2\x79\x6d\xcc\x6d\xba\x43\x43\x13\x2a\x1b\xaa\x58\x95\xcc\xbe\xc9\x6d\x74\xd2\x9a\xd5\xd8\x17\x40\xcc\x8d\xb1\x58\x1d\x93\x6f\x65\xb5\x3e\xd7\x9c\xba\xc6\x71\xba\xde\xe9\xcf\xcb\x95\x37\x66\x38\x9c\x36\x86\x42\xf1\x0c\x54\x6b\xbe\x65\xda\xe9\x6b\xd0\x66\xf1\x40\xd6\x57\xe9\x56\x90\xeb\xf3\xcb\x97\xc6\xa9\xcf\x22\x3e\x71\x40\xee\x21\xfc\x6f\x05\xf9\x2c\x7f\x0e\xb2\xbe\x15\xeb\xcd\x20\xd7\x1d\x64\x16\x49\x41\x36\x09\xc8\x8f\xbb\xca\x26\x29\xc8\x26\x01\x96\x5e\x36\x55\x4b\x0a\x2c\x49\xf8\x37\xf2\xd3\x52\x02\xfe\x5e\xc1\xbb\x78\xb8\x61\x8c\xa9\x93\x55\xb0\x1e\xf4\x08\xd6\x38\x35\xbf\x6f\xd2\x99\x80\xff\x10\x6d\xca\x09\xf8\x27\x1e\x0f\xba\xb3\x51\x36\x41\x3c\x26\x1e\x0f\x3a\x59\x7e\x76\x27\xff\xb0\x89\x96\x3f\x83\x75\x47\x3c\xec\x9d\x6d\x15\xa5\xee\x87\xc6\x43\x20\x1e\x6f\xe1\x7f\x48\xc1\xa3\x1c\xf5\x46\xb9\x35\x51\x5c\x4c\xad\x7c\x63\x44\x6a\xcc\xb4\xdd\x1e\x0f\x14\x69\x8e\x51\x54\x3b\xeb\x2c\xda\x1b\xa2\x92\x07\x4d\xc9\x5a\x54\x46\xdd\x66\x09\x77\xa9\x32\x3e\xd8\xe0\xb0\xb6\x19\xbd\x8c\xcb\x62\x6e\xac\x28\x63\x6b\xae\x8d\xb3\x1d\x27\x85\x61\x64\x4e\x5b\x27\x7d\x6b\x07\xbf\xf5\x70\x16\x26\xd3\x84\x84\x8a\x2c\x0b\x30\x20\xd2\x2c\x20\x49\x51\x92\x51\x1c\x32\x12\x27\xcb\x8c\xc4\xc8\x80\xc5\x58\x20\x61\x8a\xc2\x32\x0c\x8d\x43\x0e\xc7\x81\x04\x24\x8e\xa3\x58\x86\xa6\xe1\xee\x9f\x74\x4b\xf4\xaf\x9c\xef\x6e\x78\xb9\x98\x6b\x20\x09\x8c\x8d\xce\x35\x6c\x4b\xd9\xa7\xc0\xcb\xcd\x3b\x57\x2d\x54\xd9\x62\x6b\xd9\x9a\x8b\x15\xbc\xc8\x13\x83\xfe\x4b\xdb\xae\xe8\x2f\x43\x14\x55\x0a\xac\x53\x2d\x31\x3a\x2a\xb4\x57\xe5\x41\x9a\x1f\x12\xbc\x77\x5b\xee\xf1\x73\x69\xaa\xe0\x7d\xee\x80\x62\xff\x0d\xbc\x99\xe3\x74\x49\xc8\xf5\x06\xbc\x61\xd0\x62\x66\xca\xae\xda\xec\x26\x9d\x63\x68\x65\x46\xd7\x52\x79\x5d\x5f\x57\x40\xb6\x55\x25\x08\x61\xd3\x1e\x0c\x46\xf9\xb5\x96\xaf\x93\x2b\xdc\xb6\xc0\x98\x58\x0c\x68\x6e\xda\x9f\x12\xa6\x59\x63\xab\xd9\x79\x3e\xd5\x64\xf9\x01\x58\x4b\x95\x4c\xed\xc5\xce\xd4\xb2\x31\x72\x0c\x67\x3e\x1d\x35\xfd\xf1\x87\xc7\x8d\xc3\xed\x9b\x85\x37\xd3\x46\x74\x70\xed\x3f\x97\x87\xbb\x07\xf2\xbf\x6b\xb8\xf5\x25\x68\x13\x4c\x7f\x1a\xc6\x28\x9d\x78\xf7\xf9\x17\x4e\xbf\x78\xfe\xd7\x0d\xf7\xa1\x6b\xfc\xcc\xfd\xb6\x68\x18\xe3\x8b\x6a\x5e\xb3\x45\xd2\xbe\x08\xfa\xc2\xed\xb6\xf8\x37\x96\x9f\x96\xa9\x94\xbe\x1a\x35\x6b\x82\x52\x5b\xae\x52\x29\x83\x84\x2f\xcd\xd9\xd8\x72\x3a\xfa\x74\x9e\xe5\xb8\x75\x6d\xde\xd7\xf4\x8c\x34\x6e\x77\x61\xad\xfe\x4a\x0f\x74\x99\xd1\x16\xcb\x51\x7e\x54\xa7\x2b\xb9\x66\x76\x65\x65\x94\x97\x34\x9f\xd7\x9d\x61\x76\xda\x2d\xd1\xab\x2e\xff\x90\xdd\xdf\xf3\x0b\x25\x76\xd7\x3a\x39\x2e\x70\x1d\xff\xf7\x89\x35\x87\x9b\xc3\xc5\x0c\xd9\x46\xbd\xd3\x6d\xf3\xa5\xfa\xb5\x3b\x24\xf8\x6a\x57\x68\xef\xef\x71\x68\xd4\xab\x23\x3f\xc5\xdf\x10\x04\x41\xf8\x5c\xce\x47\xed\x1d\x43\xa4\xd9\x2e\xd5\xf8\xf6\x08\xa9\x08\x23\xe4\xab\x2a\xbf\x93\x76\x6a\xda\xd6\x44\x57\xa7\x87\xfb\xa1\x02\xcf\x0f\x92\x3a\x40\x35\x4c\xf2\x30\xc6\x57\xa5\x3f\x00\xbd\xa7\xb6\x13\x78\xdc\xfd\x6f\x22\x99\x32\x9c\x9c\xee\xda\xda\x7f\x55\x1d\x67\x01\xed\xc9\x43\xb4\x3b\x67\x1b\xa6\xdc\x5d\x82\x21\xbd\x7a\xa9\xd5\x13\x90\xaf\xa7\xea\xcf\xc8\xa9\xfe\xe1\xfb\xae\xc1\x8d\xa6\x79\x4c\xb7\xde\xac\xf8\x4d\x9d\x1a\x71\x71\xf2\x95\xbb\x89\x1f\xab\x59\x38\x93\x4b\x9a\x5e\x10\x2b\xb6\xe6\x91\xf7\xda\x5c\xbd\x38\xe6\xb1\xda\x47\xb1\xb9\xa4\xff\x45\xd1\xae\x5a\x60\xe7\xd2\xe2\xc6\xf3\xf6\x83\x22\xa5\x7a\x4e\x18\x5e\xd1\x21\xdb\x16\xf8\xae\xb0\xab\x7a\x4e\x05\x69\xd4\x83\xc1\xd0\xeb\x94\xea\x05\x44\x74\x6d\x08\xfd\xd1\x15\x2d\xcd\x2e\xc6\x92\xcb\xb3\xa3\x13\x4f\xa2\x88\xb8\x16\x37\x93\xfd\x95\x7a\x77\x8b\x73\x22\xe1\x97\xe4\x6c\xb1\x74\x2e\xcf\xae\xf2\x33\xb2\xff\x32\x71\xe0\xeb\x02\x1a\xd2\x7b\x83\x89\x9b\xc9\x0c\x38\xb3\x24\x92\x6d\xdb\xc7\x13\xcb\xef\x69\xdb\x56\x61\xd2\xec\xfe\xd9\x97\x24\xf2\xec\x28\xc4\x93\x68\x57\xf7\x68\x9e\x67\x04\x58\x96\xa6\x4a\xbb\xe1\xc0\xb4\xe5\x88\x61\x7a\x02\xb7\xbe\xe1\x95\xdf\x21\xe9\x1e\x25\x76\x02\x07\xc8\xf9\xc5\x86\x8a\x02\xa5\xa0\xab\xbd\x1f\xb5\x54\xf9\x19\xf9\xe2\x35\xfe\x12\x25\xac\x2a\x3f\x48\x4c\x55\x8e\x2d\xe0\xc1\xf5\xb6\xe2\xdd\x21\xb4\x69\x4d\xac\x47\xc9\xbd\xa7\xe5\x17\x3d\x02\xaa\xee\xd2\x24\x5c\x01\x77\xfd\x38\x05\xf6\xb4\x22\x7c\xfa\x4e\x15\xfc\x14\xc2\x94\x30\xad\xad\x57\xce\xcc\xbb\x74\xd8\x0b\x7f\xa2\x71\xaf\xf1\x2f\x1b\xda\xd9\x47\xbb\x37\x54\x27\xb7\xf5\x39\x39\xbf\xc8\x87\x7f\x8d\xea\x4c\xc6\x70\x89\xfc\x76\x7d\x94\x58\xef\x68\xc6\x1b\xde\xc2\x04\x74\x77\x5d\xe2\x26\xe9\xd6\x13\x8d\xfb\x5d\xf2\x9a\xfb\xb9\xb6\xbc\x65\x22\x02\x07\x26\xc6\xcf\x30\x62\x01\xc9\x65\x18\x90\xd3\x5f\xf7\xaa\x80\xa6\xa2\x24\x00\xad\xf7\xa4\x62\x09\xe7\xd5\xbc\x24\x9a\x27\x3b\xb4\x1f\x66\xbe\x00\xbd\x6b\x42\x06\xaa\xc7\x91\xf4\x31\x76\x3c\xa3\x16\x57\xca\xab\xd6\x7c\x8c\x6c\xb1\x64\xba\x2c\xcb\x41\x62\xcd\x34\xe7\x0b\x2b\x99\x44\xe7\xb4\x62\xf7\xe8\x6e\xbe\x1b\x21\x9f\x05\x54\x7b\xe2\xaa\x3a\x7c\x88\x84\x41\x6a\xf1\xe2\x76\x2f\xe0\x33\x12\x14\xf9\x19\xd9\x0f\xf1\x92\x66\x3a\x50\x9e\x00\x37\x42\x89\x07\x8c\xdb\x7b\x3a\xd7\x24\xbe\x71\x76\xb4\xa5\xfa\x30\xeb\xde\x60\xd8\xab\x76\x53\x0d\x19\xae\x27\x81\x29\x87\x33\x31\x8d\x09\x90\x65\x1b\x3a\x4e\x52\x83\x5e\x65\x70\xb6\x4e\xdb\x17\x07\x56\x46\xbb\x8a\x37\xc8\x9e\xdc\x0f\x2e\xd1\xbe\x2e\x71\x48\x94\x9d\x13\xdc\xcf\xc2\xb7\xf4\xdc\x8d\x75\xff\x1a\xfc\x22\xd5\xab\xd3\xfe\x6d\xa5\x2b\x82\xee\xe7\x50\x5b\x92\x47\x27\x7a\x90\xb4\x61\xa4\xaf\x4e\xdf\xe2\x7a\xb2\x8f\xf8\xa3\x9d\xe1\x8c\xf4\x3d\xf3\xcd\x68\x72\xba\x65\xda\xdb\x81\x6f\x09\x6d\x47\x35\x8d\xc7\x1b\x3a\xc8\xe1\xba\xf8\x81\x06\xf1\x95\xd9\x0f\x3d\x77\x66\x2a\xe2\xd9\xdf\xc7\xe3\xaa\x26\xbe\xba\xf1\x95\xb0\x6c\xb8\x54\xcd\x85\xf3\x29\xda\x84\x31\xbb\xaa\x56\x58\xa3\xf8\xfa\x1d\x92\x28\x1f\xa6\xd3\x81\xc1\x55\x3d\x22\xb3\x5d\xe7\xa4\x4f\xff\xc8\xc6\x47\x84\x76\x90\x7a\xe8\x02\xf8\xd6\x00\x3f\x27\x7a\xbe\x84\x7a\x50\x84\x5f\x62\x11\x47\x87\x2b\xeb\xba\x8b\xcc\x1e\x07\x5f\xef\x09\xc7\x92\xfd\x3a\x88\xf9\x17\xdb\x1f\xe1\x36\xef\xe9\xdf\xbd\xd4\xf7\x26\x71\x47\x20\x3f\x64\x18\x27\xa2\x69\xce\xef\xb6\xf2\x05\x9a\x57\xa7\x08\x5f\xbf\xca\xd0\x05\xaa\xe6\x20\xdf\xff\xf5\x2f\xe4\xc9\x31\x35\xd9\xb7\x9b\xf6\xf4\xe3\x87\x0b\xd7\xee\xb7\x6f\xcf\x48\x74\x45\xc9\x94\xe3\x55\xdc\xe5\xe2\xa3\xab\x8a\xe6\x62\x3a\x73\x63\xb1\x3f\xab\x7a\x59\x80\xb3\xaa\x01\x11\xbe\x21\x83\xa2\xd0\x16\x76\x4e\x86\xfc\x44\x08\x22\xf6\x46\xb4\x2a\x4f\x14\xdf\x36\x51\xbe\xf2\x39\xdb\xd1\x7b\xb6\x48\xbe\xd1\x16\x4a\x85\xfa\x71\x0b\x08\x69\x0b\x79\xa1\x2d\xd4\xb3\x42\x27\xb0\x2b\xe2\x95\x36\xea\x48\xaf\x99\xdb\xba\x4c\x5b\xe8\x74\xdb\xa5\x6c\x77\xfb\x53\x4e\xa8\x0a\x5d\x01\xc9\xf2\x9d\x2c\x9f\x13\x2e\xec\xa3\x6d\xd7\x1d\xe7\x8f\x93\x40\x2a\xe6\x71\xc6\x38\xe7\x73\x65\x93\x2c\x4a\x92\x73\xfb\x04\xd3\x46\xa1\xc6\xda\x4f\xf4\xaf\xec\x28\x46\x5a\x62\xbf\x94\xfd\xe5\x76\xf0\xcb\x11\x66\x85\x43\x96\xe0\xb2\xc3\xdc\x66\x81\xf7\x49\xa5\x5f\x68\x86\x08\x61\xce\x6d\x11\x92\x06\x7b\xac\x53\x04\x53\x1c\xff\x09\x06\x89\x76\x8d\x77\x39\xa4\xb8\xde\xd1\x34\x1d\x77\x6a\xc3\x4e\xab\x8a\xc8\xc0\x05\x5b\x17\x43\xe4\x85\x6e\x21\x92\xa9\x5b\x1a\x74\xa1\xa7\xc3\xff\x05\x00\x00\xff\xff\x66\xc5\x52\x91\x77\xe6\x00\x00") +var _operation_fee_stats_3HorizonSql = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\x5d\x79\x8f\xe2\xb8\xb6\xff\x7f\x3e\x45\xd4\x1a\xa9\xba\x45\xf5\x90\x7d\xe9\x79\x7d\xa5\x00\x61\xdf\x77\x18\x8d\x90\x93\x38\x90\x22\x5b\x25\x61\xab\xab\xf7\xdd\x9f\x08\x5b\x48\x25\x10\x08\x55\x7d\x9f\xee\xa0\x51\x0d\x60\xfb\x6c\x3e\xc7\xbf\xe3\x63\x93\xfe\xfe\xfd\xb7\xef\xdf\x91\xa6\xe9\xb8\x53\x1b\x76\x5a\x55\x44\x06\x2e\x10\x81\x03\x11\x79\xa1\x5b\xbf\x7d\xff\xfe\xdb\xb6\x3d\xb7\xd0\x2d\x28\x23\x8a\x6d\xea\xa7\x0e\x4b\x68\x3b\xaa\x69\x20\xdc\x1f\xf4\x1f\x98\xaf\x97\xb8\x41\xac\xe9\x64\x3b\x3c\xd0\xe5\xb7\x8e\xd0\x45\x1c\x17\xb8\x50\x87\x86\x3b\x71\x55\x1d\x9a\x0b\x17\xf9\x89\xa0\x7f\x7a\x4d\x9a\x29\xcd\xdf\x7f\x2b\x69\xea\xb6\x37\x34\x24\x53\x56\x8d\x29\xf2\x13\x79\xea\x75\xf3\xec\xd3\x9f\x07\x72\x86\x0c\x6c\x79\x22\x99\x86\x62\xda\xba\x6a\x4c\x27\x8e\x6b\xab\xc6\xd4\x41\x7e\x22\xa6\xb1\xa7\x31\x83\xd2\x7c\xa2\x2c\x0c\xc9\x55\x4d\x63\x22\x9a\xb2\x0a\xb7\xed\x0a\xd0\x1c\x78\xc6\x46\x57\x8d\x89\x0e\x1d\x07\x4c\xbd\x0e\x2b\x60\x1b\xaa\x31\xfd\x73\x2f\x3b\x04\xb6\x34\x9b\x58\xc0\x9d\x21\x3f\x11\x6b\x21\x6a\xaa\xf4\xbc\x55\x56\x02\x2e\xd0\xcc\x6d\x37\xbe\xda\x15\xda\x48\x97\xcf\x54\x05\xa4\x94\x47\x84\x61\xa9\xd3\xed\x20\x8d\x7a\x75\xb4\xef\xff\xc7\x4c\x75\x5c\xd3\xde\x4c\x5c\x1b\xc8\xd0\x41\x72\xed\x46\x13\xc9\x36\xea\x9d\x6e\x9b\x2f\xd5\xbb\xbe\x41\xe7\x1d\x27\x92\xb9\x30\x5c\x68\x4f\x80\xe3\x40\x77\xa2\xca\x13\x65\x0e\x37\x7f\x7e\x06\x43\xc9\x7b\xf7\x19\x2c\xb7\x7e\xf5\x79\x0a\xee\xb8\xdd\xae\xdd\x4e\xc0\xad\x23\x5f\x62\xe6\xeb\x75\x22\xee\x75\x2f\xd5\x73\xc2\xd0\xd7\x73\x4f\xd6\x93\x6a\x02\x15\x05\x4a\xae\x33\x11\x37\x13\xd3\x96\xa1\x3d\x11\x4d\x73\x7e\x79\xa0\x6a\xc8\x70\x3d\xf1\x29\x67\x38\xc0\x73\x74\x67\x62\x1a\x13\x55\xbe\x65\xb4\x69\x41\x1b\x1c\xc7\xba\x1b\x0b\x26\x18\x7d\x92\x24\x91\x14\xb7\x8d\xd5\xa0\x3c\x85\xb6\x37\xd0\x81\xaf\x0b\x68\x48\x37\xa9\xe0\x1b\x6e\xd9\x70\xa9\x9a\x0b\x67\xff\xdd\x64\x06\x9c\xd9\x9d\xa4\x92\x53\x50\x75\xcb\xb4\xb7\xe1\xb8\x5f\x53\xef\x25\x73\xaf\x2d\x25\xcd\x74\xa0\x3c\x01\xee\x2d\xe3\x0f\xce\x7c\x87\x2b\xed\xe3\xf2\x0e\xa1\xfd\x23\x81\x2c\xdb\xd0\x71\x2e\x0f\x9f\xb9\xb6\xec\xe1\xce\x44\x33\xcd\xf9\xc2\x8a\xd1\xdb\xba\x26\xd2\xae\x17\x50\xed\x1b\x09\x1f\x16\xdd\xd8\x03\xb6\xeb\x84\xa2\x40\x3b\x5e\xd7\x03\xf9\x3b\x86\xec\xcd\x1a\x6f\x90\xb7\xb4\xde\xc0\xc4\xbf\x14\x5f\x1b\x61\x6d\x07\xcc\xdc\xab\x33\xe0\x9c\x2d\x40\xe2\xe6\xaa\x1b\xcd\x8e\x91\x1e\xa7\xb3\xb9\x93\xc3\xbc\xda\x51\x75\xdc\x89\xbb\x9e\x58\xd7\x49\x6e\x7b\x9a\x56\xdc\x9e\x30\x6e\xb7\x03\x94\x5c\xee\x2c\x1e\xc2\xfd\x6a\xb7\xeb\xab\x98\xb8\x89\x37\x99\x3b\x8c\xdc\x5a\xdb\x71\x16\xd7\x38\x1f\x3b\x4b\xa6\x0c\x6f\xcc\x0b\x8e\x6e\x60\x01\xdb\x55\x25\xd5\x02\xc6\x45\xf0\xbe\x36\x74\x62\xdd\x98\x9b\x1c\x11\xed\x56\x09\xc2\x07\xde\xcc\xdf\x33\x5e\x1c\x7e\xbb\x8e\x1f\x4e\x7f\x37\x99\xdb\x99\xdc\xbf\xdd\xe2\xc3\x21\xf5\xf3\x9c\x61\x12\x53\x82\xa9\x69\x5b\x13\x5d\x9d\xee\x13\x86\x0b\x22\x04\x7a\xc6\xd6\xf1\xf6\x7c\xef\x12\xe5\xb8\xce\xb9\x1b\x9d\x6d\x54\x7b\xb5\x3a\xa2\xca\x3b\xce\x39\x21\xcf\xf7\xaa\xdd\x98\xb4\x23\x9c\xee\x01\x94\xf7\xd3\x7d\x99\x92\xf7\x29\xbe\xfa\x07\x94\xee\x08\xad\x9e\x50\xcf\xde\x61\xb3\x6d\x9e\xed\xc0\xd7\x9b\x39\x9f\x11\x89\x3d\x5a\x86\x31\xfb\x9e\xb2\xd9\xd8\x1a\x46\x44\xfd\x2d\xfa\x85\x93\x88\x37\x76\x9f\xf7\xc5\xeb\xbc\x4f\xf2\x62\xeb\xb6\x5f\x01\x6e\xd1\x65\x37\x24\x66\xdf\x7d\xfa\x17\x5f\x9e\x43\xbe\x18\x47\xa2\xc0\x1a\x72\xb9\xb3\x6f\x49\xd8\x77\xe4\x0b\x85\xb6\x50\xe0\xbb\x21\x9d\x75\x75\xbb\xe3\x50\x25\xf8\xd5\x58\xe8\xd0\x56\xa5\xbf\xfe\xfe\x16\x63\x14\x58\xdf\x31\x4a\x03\x8e\xfb\x15\x18\x1b\xa8\x79\xa5\x98\x18\x23\x14\xd5\x0e\x1d\x92\xef\xd5\xb3\xdd\x52\xa3\x7e\x41\x9f\x09\x98\x4e\x4f\xd2\x3d\x23\xef\x04\xbd\x40\xe3\xa0\x5d\x02\x1a\x5b\x5d\xbd\xe1\x27\xe1\x9f\x91\x5b\x14\xf1\x54\x8f\x41\x41\x18\x76\x85\x7a\x27\x40\x42\xb3\xa6\xce\xab\x76\xf0\xc5\x6c\x51\xa8\xf1\xef\x38\xfc\xf9\xdb\xae\x0a\x57\x07\x3a\xfc\x71\xf8\x0e\xe9\x6e\x2c\xf8\x63\x3f\xe4\x4f\xa4\x23\xcd\xa0\x0e\x7e\x20\xdf\xff\x44\x1a\x2b\x03\xda\x3f\x90\xef\x5e\x71\x2e\xdb\x16\xb6\xf3\xb5\xa7\x7c\xa0\xf7\xdb\x19\xc5\xf3\xc6\x3d\xe1\x6c\xa3\x56\x13\xea\xdd\x0b\x94\x77\x1d\x90\x46\xfd\x9c\x00\x52\xea\x20\x4f\x87\xb2\xdb\xe1\x3b\xc7\x23\xf2\x14\xe4\x7c\x50\x7f\xcf\xf3\x68\xa1\xab\xfa\x9c\xd9\xb2\xde\xe8\x06\xec\x89\x0c\x4a\xdd\xe2\x51\x2c\x7f\xfd\xed\x8c\xfd\x89\x4a\x40\x90\x5b\x94\x7f\x47\xc4\x33\x40\xb3\x9a\xb6\xa6\x9d\x56\x15\xb1\x6c\x53\x82\xf2\xc2\x06\x1a\xa2\x01\x63\xba\x00\x53\xe8\x99\x21\x66\xbd\xd0\x2f\xee\x75\x47\xdb\x8b\x7f\xf0\xd5\x93\xfc\x87\xb9\x0d\xb3\xe5\xd1\xb3\xaf\xd2\x47\xda\x42\xb7\xd7\xae\x77\x7c\xdf\xfd\x86\x20\x08\x52\xe5\xeb\x85\x1e\x5f\x10\x10\x4f\xfb\x5a\xad\xb7\x5b\xef\x3a\xdd\x76\x29\xdb\xf5\x7a\xf0\x1d\xe4\xf7\xc9\xef\x48\x47\xa8\x0a\xd9\x2e\xf2\x3b\xb6\xfd\x14\x9c\x8d\xab\x81\x98\x4c\xbb\x6b\xe4\x1f\xa6\x1c\x1e\xa6\x5c\x9c\x95\x2a\x99\x7e\x31\x38\x1c\x55\x3c\x7e\x75\x97\x86\x5f\x7f\x43\x90\x2c\xdf\x11\x90\x41\x51\xa8\x23\xbf\x63\x7f\x61\x7f\xa7\x7f\xc7\xfe\xc2\xff\xfe\xd7\xef\xb8\xf7\x1e\xff\x0b\xff\x1b\xe9\xee\x1a\x11\xa1\xda\x11\xb6\x46\x11\xea\xb9\x6f\xa1\x96\x89\x81\x03\x09\x2d\x73\x9d\xc3\x47\x5b\xe6\x7f\xee\xb1\xcc\x7b\x4c\xdd\xdb\xe1\x88\xc3\xf1\x0c\x71\x82\xed\x77\x14\x3d\x89\x11\xa4\xb3\xb5\x15\xf2\xf3\xb4\x02\x3c\xef\xbe\xee\x8e\x9a\x02\xf2\xd3\x1f\x11\xdf\xc2\xa2\xf6\xa1\x32\x06\x09\x06\x44\x3c\x84\x71\x7c\x09\x43\x53\xa0\xa4\x52\x86\x11\x0d\x48\x7a\x16\x90\xe7\xe2\x9e\xbc\xec\xbd\xb4\x61\x69\x5e\x62\x69\x43\x88\x06\xa5\xf5\x07\xc9\x45\x69\xb7\xc8\x25\x43\x05\x2c\x34\x77\xe2\x02\x51\x83\x8e\x05\x24\x88\xfc\x44\x9e\x9e\xfe\x3c\x6f\x5d\xa9\xee\x6c\x62\xaa\xb2\xef\x28\xed\x4c\x57\x7f\xfe\xbb\x57\xd1\x0b\xb0\x78\xea\xed\x62\xd1\xbf\xf9\xde\x69\xa4\xca\x88\xa8\x4e\x55\xc3\xf5\x12\x83\x7a\xaf\x5a\xdd\xa9\x03\xf4\x6d\x1a\x8f\x48\x33\x60\x03\xc9\x85\x36\xb2\x04\xf6\x46\x35\xa6\x81\x6e\xc6\x42\x3f\xa6\xfc\x88\x6a\xb8\x70\x0a\xed\x40\x17\x45\x03\x53\x07\x71\x74\xa0\x69\xef\xd9\xb8\xa6\xae\xbd\x67\xf2\x15\xa7\xa8\x6f\xc7\x9e\xef\xa7\x3d\xb8\x6f\xb8\xd7\x1c\xc1\x6a\xc7\xd1\x24\x2e\x5c\xbf\x33\x88\x65\x69\xaa\x57\xb3\x47\x5c\x55\x87\x8e\x0b\x74\x0b\xd9\xce\x99\xf7\x11\x79\x33\x0d\xf8\x5e\xd0\xa8\x5d\xd1\x21\x1f\xdd\x6f\xa7\xe2\xc9\x7c\xdc\x7c\x45\x50\xdd\xbb\x21\xdf\xee\xee\x32\x3a\xcc\xfb\xa2\x54\xcf\xb6\x05\x2f\xfd\xca\x8c\xf6\x5f\xd5\x1b\x48\xad\x54\xef\xf3\xd5\x9e\x70\xfc\xcc\x0f\x4f\x9f\xb3\x7c\xb6\x28\x20\xd8\x35\x65\xee\x36\x7b\x90\xd0\x3b\x57\xdc\x17\x3d\x10\x03\xae\xdd\x25\xd0\xbe\x3e\x45\x68\xfc\xf4\xe3\x87\x0d\xa7\x92\x06\x1c\xe7\x5b\x70\xba\x76\x67\x15\x21\xbe\x45\x93\xdf\x2e\x4c\xd4\x6e\x6f\x9c\x58\xb3\x5d\x45\xe7\xa8\x57\x78\x64\x9c\x6a\x75\xe1\x62\x86\x76\x97\x4c\x39\xac\x3b\x86\x87\x77\xdf\x95\xff\x42\x06\x50\xf4\xa5\x08\x0b\x2f\x2f\x3c\xc8\x6d\xfd\x34\x3f\xcd\x69\x2f\x29\x82\x34\x06\x75\x21\x87\x64\x46\x57\x34\xda\x55\xe8\x2e\x2b\x74\xa4\x15\x68\xfe\x43\x95\xa3\x64\x3b\xd4\x7c\x92\x7a\xdd\x9e\xce\xde\xed\x02\x31\x33\x89\x5a\xe9\xdf\x97\xb8\xa2\x7a\x7e\xf1\x0e\x3e\xbe\x44\x78\xb3\xe7\xc7\xe1\x4d\x32\x74\x81\xaa\x39\xc8\x8b\x63\x1a\x62\xb4\xb3\x1d\x0a\x65\x49\xed\xb0\xa7\xb3\xb7\xc3\xe1\xdc\x3a\x42\x36\xdf\x61\x72\xac\x28\x0c\x3b\xc7\x0e\x1f\xb8\x37\x8b\xaf\x32\xea\x4d\xc4\x51\x8e\xc3\x2a\x87\x06\x38\x9c\x26\x22\x5e\xff\xe3\x61\x72\x00\x98\xcc\x85\x7b\xc2\xa6\xe0\x18\x1b\x02\xf7\xea\xa0\x5d\xdf\x85\x25\xc7\xee\x7b\x74\x9d\xfd\xc7\xc0\x39\xfb\x3b\x5d\xb0\x77\xf9\x80\x0b\xb4\x89\x64\xaa\x86\x13\xee\x83\x0a\x84\x13\xcb\x34\xb5\xf0\x56\xef\xe4\x53\x81\x51\x73\xed\x35\xdb\xd0\x81\xf6\x32\xaa\xcb\x36\x0f\x75\xd7\x13\x2f\x4d\x52\xdf\xa2\x7a\x59\xb6\xe9\x9a\x92\xa9\x45\xea\x15\x9c\xa3\x83\xb3\x40\x20\x43\xdb\x4b\x2f\x76\xdf\x3b\x0b\x49\x82\x8e\xa3\x2c\xb4\x49\xa4\xa3\xec\x15\x07\xaa\x06\xe5\xe8\x5e\xd1\x61\x15\x51\xbb\x4e\x1a\x65\x11\xe7\x21\x57\x30\x2f\xfe\x6a\x73\x7d\xfd\xba\x55\xe5\xc7\xc2\xd8\x45\x1e\x9f\x05\x6b\x37\x29\x9a\x10\xe6\x2e\xf2\x7a\x0f\x7b\xe1\xdd\x2f\xc0\xa0\xef\x64\x27\xbe\x6f\x7e\xff\xbe\x4d\xf5\xa0\x8c\xa8\xce\xc4\x02\x9b\xed\xa6\xf6\xa7\xb7\x7b\x3a\xec\xab\x10\xd7\xdc\x17\x54\x9f\x11\x1b\xb8\xb3\x6d\xf8\xcd\x80\xb1\x5d\xb2\x8d\xe9\x36\xbe\x1d\x68\xbb\x88\xa6\x1a\xd0\xb9\xe6\xe8\xd7\xf6\x4c\xe7\x57\xb4\x22\xf6\x55\xdb\x6d\x84\xb4\xb3\x8b\x07\xa7\x09\xd1\x74\xbf\x8c\x98\x0b\x5b\x3a\xde\xf9\x88\xc0\xb1\xc3\xda\xf4\xf4\xf4\xe3\xc7\xb5\x7d\xdd\xc9\x9a\x88\x68\x9a\x1a\x04\xc6\xd1\x9e\x9e\x75\xa3\x43\x6f\x7f\x96\x97\x74\x75\xd9\x5f\x3f\xfc\xfa\xd0\x14\x65\xbf\x0a\xdf\x03\x98\xde\xf5\x9b\x48\xb6\x81\xcb\x8f\x97\x3a\xed\xef\x63\x5e\xea\xb2\xdb\x7a\x87\x76\x78\x7f\x8d\xf4\x4a\xbf\x8b\xec\x8e\xbd\x2e\x70\xf4\x44\x52\x9d\x89\x03\x35\x0d\xda\x07\x6f\x38\xc0\xa0\x2a\xc1\x89\x71\x06\xf9\xbb\xef\xce\xd3\x80\xd3\x05\xa6\x49\x20\x41\x38\xbb\x42\x15\x6c\xb4\xcd\x85\x21\x7b\x77\x90\x35\xd5\xb2\xc0\x14\xbe\x27\xaa\x3a\x13\xb8\x06\x92\x7b\x2e\x97\xef\x4a\x41\xe8\x2d\x55\x4f\xdd\x89\x77\x8f\x19\xc9\x16\x85\x6c\x05\xf9\xfa\xd5\x6f\xfa\x7f\x21\xe8\xb7\x6f\xd7\x48\x85\x0d\x3f\x58\xfb\x7f\xde\x4d\x40\x0c\x7a\x67\x93\x11\x20\x1f\x98\x29\x4f\xc0\x8b\x31\x18\x7e\x1a\xff\x80\xa8\x0c\xbf\x5f\x11\x13\xf5\xe3\xac\x90\x49\x70\xff\xda\x5d\x86\xc7\x20\xff\x15\x2e\x9f\x85\xfd\x37\x2a\x9b\x10\xfd\xaf\x70\x7b\x8f\xff\x51\x03\x2e\x64\x00\x67\xf7\x57\x1e\xe8\xab\x07\xff\xf4\x8b\x14\x7b\xc3\xb7\x07\x8d\x2b\xdb\xc8\xb8\xb8\x7e\x19\xa2\x43\xfb\x9e\x58\x87\xc6\xcb\x76\xc7\x12\xbd\xe5\x89\xda\x4c\xfe\x92\xed\xa0\xbb\x9e\x40\x63\x09\x35\xd3\x82\x61\x25\x56\x77\xbd\xdd\x9c\x79\x39\x5b\x68\xa3\x0e\x5d\x10\xd1\xb4\xdd\x16\x46\x35\x3b\xea\xd4\x00\xee\xc2\x86\x61\xd5\x40\x8e\xfe\xf6\xd7\xdf\xa7\xd4\xe8\xdf\xff\x1b\x96\x1c\xfd\xf5\x77\xd0\xe6\x50\x37\x23\x0a\x77\x27\x5a\x86\x69\xc0\x18\xa9\xd6\x96\xd6\x7b\x32\x7b\xcd\x54\x1d\x4e\xc4\x2d\x0c\x7a\xd5\x75\xd6\xde\xe6\xac\x67\x6e\x19\xde\xa8\xab\xc6\x24\xc2\x7b\xa2\x3b\x4c\x82\x08\x1b\xda\x69\xcf\x77\x0a\xac\xb3\xbe\x70\xed\xda\x60\xb2\x35\x35\xb4\x1d\x6f\x16\xfe\xfa\x3b\xb8\xc5\x3d\x07\xe9\xed\x94\x6d\xd5\x9e\x42\xf9\x7c\xa7\x6b\xc0\xd5\x24\xe0\xd4\xd7\x0a\x94\x88\x2a\x1f\xd6\x8b\xc3\x85\xb9\x38\x8b\xdc\x6e\xc1\xf0\x6e\x27\x5e\xb9\x8b\xd7\x11\xba\x17\xaa\xd2\xfe\xfa\x9f\xbf\x26\x7d\xdb\xae\xed\x71\x4a\xc4\xbc\xaa\x78\x51\xa9\x8b\xbb\xbd\x38\x4a\x46\xe6\x0a\x0f\x53\x33\xf6\x6d\xcf\x8b\x8a\x5e\x01\xb6\x70\x55\x73\xc0\x05\x88\x62\xda\x57\xce\xe6\x90\x1c\xdf\xe5\xaf\xa8\x17\x41\xf2\xd2\x19\x57\x1c\xb2\xa5\x7a\x47\x68\x77\x91\x52\xbd\xdb\x78\x77\xce\xe5\xa5\x18\x1d\xe4\xeb\x13\x36\x51\x0d\xd5\x55\x81\x36\xd9\x6d\x91\xff\x70\x5e\xb5\xa7\x67\xe4\x09\x47\x31\xee\x3b\x4a\x7f\x47\x09\x04\x63\x7f\xe0\xec\x0f\x92\xf9\x03\x25\x70\x92\xa3\x53\x28\xfe\xf4\xed\xcf\x78\xd4\xf1\xc9\xee\xb7\x24\x67\x56\x15\x37\x13\xd7\x54\xe5\xcb\x9c\x38\x9a\x62\x6e\xe1\x44\x4c\x16\x0e\x3c\xad\x51\xaa\xf1\xee\xf7\x2b\x17\xf9\x91\x24\x4a\xb2\xb7\xf0\x23\x27\x40\x96\x27\xc1\x2a\xe0\x45\x1e\x14\x49\x11\xf8\x2d\x3c\xa8\xc9\x0e\x95\x0f\xfb\x03\xef\xf4\xf8\x22\x0b\x9a\x40\xf1\x9b\xd4\xa0\x0f\x2c\xf6\x2b\x58\x0c\x16\x2c\x89\x51\xb7\xb0\x60\x26\xba\x29\xab\xca\x26\xbe\x16\x2c\x46\xe3\x37\xb1\x60\xcf\xb4\xd8\x5f\x1a\x8f\xc1\x87\x21\x69\xe2\x36\x3e\xdb\x49\x07\xd3\xa9\x0d\xa7\xc0\x35\xed\xcb\x3e\xc5\xa1\x18\xca\xdd\x42\x9e\xf3\xc8\xef\x2a\xc4\x93\xb5\x6c\x5f\xa6\x8e\x33\xd8\x4d\x53\x8d\xa1\x1e\xf9\xfd\x2c\x78\x9b\xf4\xcb\x0c\x28\x8e\xb9\xc9\x3a\x18\xe6\x67\x70\xdc\xbc\x6d\x17\x80\xcb\x8c\x38\x9a\xbb\x4d\x13\xfc\x6c\xa2\xf7\xdb\xe5\xdd\xcf\x94\x2f\x71\xc2\x50\x86\x22\x6f\x9a\x11\x8c\xd8\xa9\x73\xac\x4e\x5c\x9c\x71\x0c\xc3\x19\xfa\x36\x4d\xc8\x89\xa2\xae\x0f\x3f\xd9\x30\x75\x6d\xa2\xa8\x50\xbb\xb8\x34\x62\x18\x85\x61\x37\x2d\xc2\x18\x75\x48\xd9\x0e\x27\x08\xeb\x2b\x6a\xd0\xcc\x6d\xcb\x3c\x46\x4f\x54\x63\x0a\x1d\x77\xf2\xfe\x8c\xe2\x0a\x2b\x86\x63\x6f\x9b\x11\xe6\x0c\xae\xbd\xc3\x20\x70\x19\x4c\x30\x1c\x45\x09\x72\xcf\x24\x02\x6b\x2f\xde\x6c\xb8\x15\x6c\xdf\xdd\x6e\x38\x48\x8f\x3d\x23\x4f\x85\x4c\xbb\x39\x2a\x96\xaa\x78\xb6\x44\xe4\xeb\x2d\x32\x33\xac\xe6\x6b\xf5\x5c\x35\x5f\xee\xd5\x9b\x3d\xbc\x38\x22\xc6\xb5\x7c\xa7\xd8\xa8\xf7\xb2\x42\x83\xef\x0c\x98\x56\x96\x69\x0c\xf1\x62\xd0\x42\x91\x4c\xf0\x2d\x13\xbe\x40\xe1\xdd\x01\xdd\xe2\x33\x74\xb7\x50\xaf\x35\xba\x55\x02\x1f\x91\x35\xa2\xd7\x6a\x55\xeb\xf5\x7a\xb1\x29\x14\x47\x7c\x69\xd4\x6e\xd2\x9d\x7c\x9e\x1e\xf3\xfd\x76\x9e\x1a\xb7\x46\x4f\xf7\xde\x5f\xd9\x26\x58\x57\x2c\xb4\xbf\xf3\x77\xba\xae\xfb\x87\x03\x2f\xdf\xed\x78\x46\xf0\x67\xc4\xb5\x17\x30\xc6\xbc\xbd\xbf\xb5\x71\x4b\xe6\x75\xcb\x4d\x81\x87\x68\x7a\xb6\x5f\x78\x46\xb0\xe7\x5d\x51\xfd\xba\xa2\x61\x37\x05\xee\xf5\xcf\xc3\x6d\x01\x9f\x7b\x12\x2c\x4d\x91\x0c\xca\x31\x34\xe6\x49\xb5\x75\xa6\x7f\x7f\xd9\xad\xb0\x5f\x7e\x20\x5f\x30\xf4\x0f\x74\xf7\xfa\xf2\x8c\x7c\x39\x5d\x5f\xd9\xb6\x19\xc0\x55\x97\xf0\xcb\xff\x46\x79\x6a\x90\x1d\x1e\x60\xb7\xfd\xfc\x81\xec\x8e\xda\x61\x04\x4b\x31\x9f\xa7\xdd\x9e\xdd\xa7\x69\xc7\x70\x14\xf1\x89\xda\xed\xd8\x7d\x82\x76\x24\x41\x71\x0c\x89\x93\x34\xf5\x29\xda\xf9\xd9\x7d\x82\x76\x28\x4a\x93\x0c\x43\x61\x34\xf7\x29\xda\xf9\xd9\x7d\xbc\x76\x38\xc5\xd0\x1c\x8b\x32\x2c\xf3\x29\x9e\x79\xc6\xee\x13\xb4\xc3\x48\x86\x64\x49\x94\x62\x3e\x65\x55\x39\x63\xf7\xf1\xda\x61\xdb\x10\x67\x19\x02\x67\x3f\x05\x11\xce\xd8\x7d\xa6\x76\xf8\xe7\x6a\x87\x7f\xb8\x76\x5b\x76\x38\xcb\x92\x1c\x4a\x71\xec\x6e\xcd\x44\x3d\x76\x8e\x0b\x6c\x57\x35\xa6\x13\x11\x68\xc0\x90\xe0\x8e\x31\x7a\x62\x7d\x93\x01\xfd\x2c\x42\x35\x42\x3f\x50\xa7\xed\x72\xb2\x53\x6a\x05\xd5\xe9\x6c\xcb\x11\x7b\x46\xbe\xec\x32\xa0\xc9\x1c\x6e\xb6\x4c\xee\x4d\x86\x77\x62\x5d\xc9\xc7\xc2\x6e\x2c\xde\x9b\x8f\x1d\x6e\x2d\x1e\xb4\xe5\xb6\x1b\x1a\x51\x21\x48\xc0\xb1\x22\xc7\xb2\x18\x89\x89\x2c\x85\x89\x12\x54\x68\x9c\x13\x19\xa8\x10\x18\x94\x19\xc8\x90\x12\x20\x38\x14\x45\x25\x59\xe1\x70\x19\x45\x71\xc0\x61\x32\x26\xd1\x1c\x41\x6d\x37\x45\x32\x20\x19\x91\xc6\x70\x59\x62\x65\x4a\xc4\x15\xc0\x88\x0a\x27\x2a\x00\xe5\x64\x11\xc3\x14\x42\x16\x25\x42\x04\xb2\x82\x93\x1c\x83\xb2\x04\xa0\x30\x8e\x63\x58\x9a\x63\x59\x16\x05\x0c\xab\x3c\x79\x86\x26\x02\xdb\x2b\xfa\x07\xc1\xfc\x20\xb0\xe0\xae\xcb\xfb\x1a\x67\xfe\x60\x19\x94\xe6\xe8\xab\xad\xfb\x0c\x90\xa2\x69\xf2\x19\xc1\xe8\xed\x7c\xbe\x7b\xed\xbe\xf4\xfe\xfa\xda\x8f\x6f\x9f\x11\x6c\xbb\xb1\xe2\x79\x9e\xcf\x72\x56\xd1\x9d\x55\xa5\x97\xbe\xb3\xb4\x98\x94\x98\x9a\x1a\xa2\xa0\x34\xc5\x15\x63\x2b\xe5\xb2\x54\x6a\x68\x85\x31\x2c\xe8\xa5\x69\x05\x36\xe7\x65\x6a\x54\x2c\x67\x96\xe3\x4e\x83\xc8\x0f\x0c\x4e\xe9\x13\x36\x5f\x6a\xa1\xa2\xce\x4d\x9d\xe2\xdb\x50\xe9\x31\xae\x00\xde\x8a\xd3\x34\xbb\x25\xcd\x0f\x9b\xfd\xda\x66\xc5\x1f\x5f\xf2\xe0\xad\x53\x9c\x29\xd9\xb7\x61\xa1\x5a\x9a\x37\x1a\x2f\x66\x96\x1a\xe9\x6c\x23\x63\xd9\x56\x91\x92\x84\x46\x25\x57\xcf\xbf\xe4\x19\xbd\x88\x29\x44\x67\xd3\xef\x8f\x61\x71\x44\xa1\x76\xc7\x9c\x66\xf0\xae\x56\x1b\x57\x24\xb6\x20\x65\x3b\xa6\x5e\x1f\xa4\x18\xdb\x62\xea\xb2\xa3\x79\xf4\xe7\x75\xb2\x0a\xde\x2c\xbc\x75\x62\xc6\x37\x4d\x3e\xe4\x35\xe6\x87\x18\xd9\xe2\xf9\x1c\x5a\x0e\x6b\xfe\x8f\x7e\xed\xbc\x0a\x8d\x88\xfc\x60\x2c\xb0\x8f\xf1\xe3\x27\x46\xa2\x20\x27\x52\x50\x62\x21\xc4\x28\x48\x29\xa2\x0c\x51\x12\xa5\x49\x8e\xe3\x18\x02\xb0\x14\x40\x65\x0e\x15\x71\x92\x00\xb2\x2c\x41\x54\xc2\x14\x05\xa3\x01\x4b\x61\x28\xc7\xa0\x10\xdd\x6d\xd6\xb0\xd0\x58\x40\x23\xbd\x9d\xe5\x30\x02\xbf\xda\xba\xcb\x39\x09\x96\xa0\xd9\x0b\xb1\xc0\xc4\x0c\x05\x62\x0d\x75\x8c\x29\x31\xb3\xa1\x96\xe2\x48\x21\x33\xd7\xc7\x12\x3d\x03\xb9\x71\x76\xd3\xa2\x09\x89\xac\x15\xd3\xf9\xd7\x59\x3b\x3b\xcc\x4d\x2b\x9d\x65\x7b\xa3\xe2\xd9\x59\xda\xee\x65\xa7\x59\x46\x5f\x6e\x84\xe9\xdc\xec\xbc\xac\xaa\xa6\x85\x0b\x46\x4a\xa9\x0c\xc9\x05\xc3\x74\x38\xc7\x9b\x3a\x2f\x14\xa6\xa7\xa9\xc4\x06\xe3\x0d\x55\xac\xbf\xb5\x0a\xf4\x12\x4f\x6f\x5a\x8a\x6c\xa6\x31\xb6\xd7\xc4\x6b\x2a\x51\x6d\x0c\x53\x45\xa7\x94\x5f\xbd\xb8\xcd\x11\x21\xbf\x36\x37\xfc\xe6\x0d\x15\x6b\x19\x11\xa7\x97\x6c\x9b\xab\x6f\xf2\x32\x9b\x69\xd9\x74\x49\xe9\x0e\xad\x9e\x62\xbe\x0e\x54\x6b\x2d\x8b\x59\x8f\xf2\x34\x24\x14\x2a\x6c\x98\x3b\xfd\x3f\x0f\x05\x2c\x7e\x28\x30\x8f\x71\xe3\x27\x85\x92\x29\x28\xe1\x34\xcb\xc9\x18\xcb\x28\x40\x02\x32\x85\x4b\x38\x54\x38\x12\x55\x50\x91\x00\x2c\xcd\xe2\xb8\x84\x93\x90\x55\x64\x00\x81\xa4\xd0\x0a\x43\x60\x8c\x4c\xd0\x18\x41\x42\xfa\x42\x28\xe0\x5c\x94\xb3\x6f\x61\x0a\x8b\x84\x05\xaf\x95\x79\x3a\x6e\x50\x30\x94\xc1\x2f\x84\x02\x1d\x33\x14\xd2\xc3\x3e\x93\x05\x65\x74\xa4\xd0\x1b\xb7\xe7\x54\x97\x1a\xcf\x56\x1b\x26\xc8\x56\xb3\x5d\x33\x0d\x68\x87\x5b\x4a\x6b\xa5\x3b\xea\x76\x75\x95\x28\x8c\x1d\xa7\xb9\x98\xbb\x54\x86\xb4\x06\x9c\x31\x82\xbc\xca\x49\xa4\x92\x29\xa7\x0b\x38\x8a\x72\xf9\x61\x37\x05\x4c\xa5\x69\xa0\xde\xd4\x79\xa1\xe0\xf3\xce\xc6\xb4\xa3\x97\xb2\x5a\x63\xcd\x95\x87\x9c\x84\x4f\xf3\x2f\xb4\x2e\xf2\x83\x05\xbe\xc1\x74\xad\x81\xce\x0b\xb2\xb6\xa2\x66\x79\x69\xf4\x86\x2d\xea\x03\x7b\xce\xf7\xcb\x1a\xc3\xea\x5d\xdb\x64\x56\xa6\x39\xad\x15\xfb\xfa\x66\x9a\x21\x95\xb2\x55\x7a\x59\xb4\x6c\x74\x5e\xec\x9b\x3d\x8f\xb2\x14\x12\x0a\xe5\x51\x98\x3b\xfd\xf7\x84\x02\xfd\x18\x37\x7e\xa2\x00\x64\x59\x0a\x65\xa0\x22\x29\x34\x49\xd3\x2c\x2d\x13\x50\x46\x09\x02\xc7\x30\x9c\xa4\x70\x4e\x61\x44\x8e\xc3\x59\x51\x41\x29\x02\x53\x64\x48\x60\x00\x50\x94\x08\x00\x21\xa2\x0a\x94\x2e\x85\x02\x1b\xe9\xec\x18\x8a\xe2\xd4\xd5\xd6\xfd\x6e\x96\x60\x18\xfa\x42\x28\x50\x31\x43\x01\xb3\xcd\x59\x4b\x59\xbe\xe1\x6d\x7d\xe6\x36\x5d\xfe\xad\xd4\x2e\xe7\x2b\x0a\xa4\xe6\xe6\x72\xd5\x5b\xa7\x61\x0d\x58\xfd\xc5\x6b\x63\x95\x76\x8c\x74\xca\x4a\x89\x5d\x83\x59\x98\xda\x66\xb4\xd8\x50\xe5\x0a\x5e\xcd\x62\xf6\xb0\x88\xad\x46\x9a\x38\xc5\x04\x3b\x9d\xeb\xe0\x86\xd6\xf2\x85\x82\x6f\x2a\x5f\x5f\x67\x99\xfa\xac\x93\x32\x47\x68\xfe\x35\xdd\xee\x58\x82\x30\x37\x53\x73\xa3\x4f\xd3\x16\x3a\xd2\xb2\xa9\x9c\xda\x57\xd0\xc2\x48\xcb\x16\xa6\xdc\xa8\x64\xd0\xcd\x8e\xa0\x54\xfb\x8e\x31\xad\x16\xfa\xcd\x12\x5f\x13\x33\xa3\x4e\x27\x6d\x32\x65\x72\x28\xe0\x18\xc5\x51\x15\xba\xe2\x25\x48\xa3\x90\x50\x28\xa2\x61\xee\xf4\xdf\x13\x0a\xd4\x63\xdc\xf8\x09\x43\x45\x1a\xa3\x31\x96\x24\xa0\xc8\xc9\x34\x85\x43\x94\x23\x48\x96\x56\x00\x8b\x31\xa4\xc2\x11\x8a\x44\x92\x80\x22\x58\x96\x41\xd9\x2d\x45\x05\x05\x12\xc9\xc8\x80\x55\x00\xa0\x29\xec\x52\x28\x30\x91\xce\x8e\xa3\x14\x1d\x1d\x28\x87\xd6\x5d\xe9\x83\xa0\x49\x16\xbd\x10\x0a\x64\xcc\x50\x58\x67\xf1\xfc\x6c\x96\xa3\x29\x4c\xab\x4e\xe7\xe8\x6c\xf9\x9a\x91\x9b\xf3\xf4\x5a\xb0\xba\x6a\x31\x9b\x35\x08\xb6\xb2\x2e\xe2\x66\xea\x75\xdc\xce\x31\x28\xdf\x46\x33\x68\x43\x4f\xe3\xe9\x72\x6e\xea\x9a\xd8\x98\x28\xca\x8d\x7a\x86\xea\xca\x7d\x7e\xc0\xa6\x16\xdd\xb9\x4d\x01\x72\x7a\x0a\x85\xb5\x6f\xaf\xa0\x8c\x29\x3b\xad\xf2\x25\x19\x2d\x8e\x9a\xe9\x32\x4b\x99\x03\x73\x69\x0d\x96\x0b\x4b\x21\xde\xaa\xf2\x06\x1d\xcd\x04\x39\xd3\x34\x06\x38\x5d\x81\xf5\xfa\xdb\xbc\x3f\x50\x97\x59\xd6\xa9\x9b\x84\x6c\x2d\x44\x6b\xf8\xfa\x4a\xa5\x46\xa4\xed\xb6\x6c\x23\x6f\x58\x5c\x57\x30\x52\x86\x97\x80\xf5\x42\x42\xa1\xd0\x0a\x73\xa7\xff\x9e\x50\x20\x1f\xe3\xc6\x4f\x34\xc9\xc8\x22\x24\x29\x8e\x61\x44\xc8\xe0\xa2\x44\x2b\x90\x21\x44\x8c\x10\x29\x92\xa1\x01\x47\x88\x24\x4a\x49\x32\x03\x28\x1a\x07\x0a\xc6\x72\x34\xce\x4a\x8c\x24\xca\x24\x06\x25\x96\xdb\x87\x02\x1e\xea\xd5\xd1\x29\x10\x81\x51\x74\x74\xfa\x74\x68\xdd\x55\x92\x68\x0e\x63\x2f\xed\x9b\x89\x98\xa1\x80\xb7\xb9\xe5\x7c\x30\x84\x29\xc9\x5e\x2f\xa9\x37\xa7\xeb\xf6\xe4\xd7\x39\xd3\xca\xbf\x0d\xad\x41\x65\x59\x28\x8f\xcc\x35\xbb\xec\x15\x1d\xb5\xad\x36\xc9\x41\x01\x50\x02\x46\x6d\x8a\x62\x39\x9d\x7f\x71\x18\x60\xa8\x39\xa9\xb9\x2c\x2e\x5b\xcb\x76\xbb\x0b\xa6\x16\x5c\x6c\xf0\xea\x58\xf2\xa6\xce\x0b\x05\xdf\x5e\x61\xd9\x53\x59\x8b\x2e\xf3\xfa\xb0\x0d\x2c\xaa\x48\xb3\x4c\x23\xd5\x18\x4a\x7c\xa5\x8e\xa7\xd3\x59\xa7\x3a\x16\x37\xeb\x41\xb5\xaf\x8d\x45\x6e\xdc\xab\x6d\xca\xa3\xbe\x39\xb2\x5f\x4a\x94\x3e\x23\x94\x3e\x9a\x01\xc4\xeb\xb8\x5f\xb4\xd3\x5a\x65\xba\x4c\x4b\x73\x2c\xaf\xd4\x33\x24\xe5\xd1\x6f\x85\x84\x82\xe0\x84\xb9\xd3\x7f\x4f\x28\x10\x8f\x71\xe3\x27\x96\x91\x09\x46\x96\x44\x11\xc8\xa4\x28\x41\x99\x06\x92\x02\x28\x96\x53\xb6\x3e\x28\x43\xc0\x12\x1c\xc1\x29\x0a\xaa\x60\xb2\xa8\x40\x85\xe3\x18\x9c\x91\x38\x91\x85\x92\x88\x42\x42\xb9\x88\x0a\xd1\x29\x10\x89\xb3\x44\x34\x2a\x6c\x5b\xbd\x50\xd8\x55\x04\x31\x96\xbd\xb4\x6d\xc6\x62\x86\x02\xa9\x74\x15\x69\x41\x63\xd5\x37\x17\x38\x29\x4d\x55\xf4\x82\x01\x5f\x73\x73\x2a\xbd\x62\xe5\x65\x2a\x35\x96\x8c\x8d\xf8\xe2\x38\x8d\xe6\x9a\xb6\x98\x8a\xfe\x66\x56\x5f\xe9\x6e\x51\x5b\xb9\x6f\x72\x7b\xa8\xca\x75\xae\x85\x39\xa9\x92\xd9\x5b\x42\x73\x8d\xaf\x0a\x1d\xbe\x6f\x8c\xe6\xde\xd4\x79\xa1\xe0\xf3\x4e\x25\x6f\xf4\xc6\xb5\xb5\x25\x81\x76\x7e\x3a\xa0\x59\xb2\x6c\xa8\xbd\x42\x5a\x7e\x1b\x53\x2f\x06\x09\x9b\xb8\x3e\x66\xab\xa5\x82\x69\x74\xec\x52\x4b\xcb\x36\x98\xd1\xb0\x93\x69\x6b\x4e\x39\x8b\x67\xf4\x4e\x39\x4b\xe7\x5f\xf3\xcb\xd9\x5b\x8f\xa6\x97\xc5\xb9\x5a\x97\x9c\xbc\x43\xcf\x3c\xca\xb5\x90\x50\xc8\xcc\xc3\xdc\xe9\xbf\x27\x14\xf0\xc7\xb8\xf1\x13\x4d\xc8\x1c\xab\x50\x04\x0d\x21\xcd\xca\x98\x88\x33\x22\x25\xb2\x9c\x82\x13\x40\xa1\x08\x0c\x13\x19\x8a\xe6\x00\x4e\x2a\x40\xc1\x48\x94\x00\x32\x2a\x52\xb8\x48\x13\x84\x88\x32\x22\xe4\xb6\x1e\x8b\xee\x4a\xf1\xef\xbd\x9a\x8c\x74\x76\x0a\x67\xe9\xe8\xf4\xe9\xd0\xca\x52\x2c\xc7\x11\x24\xc5\x5d\xda\x35\xc7\x84\x84\xe6\xf8\x05\xab\x2f\x28\x13\x15\xcb\xcc\x80\x34\x36\x8d\x65\x6f\x5d\x20\xfa\x96\x39\x4f\x2d\xf3\x7c\xc3\xcd\x62\x15\xbc\xc6\x64\x18\x7a\xbc\x18\xb7\x8b\x36\xd7\x93\x87\x15\xb1\x5b\x51\x25\x4d\x69\xbc\x6c\x18\x7c\x34\xce\x97\x7b\xf3\x72\xb3\x2f\x55\xba\xd4\xcc\x5d\x9a\xb6\x8e\xed\xfc\xd1\x8b\x03\xef\x5d\xe9\xf8\x87\xf7\x9a\x9c\xd3\xe7\x15\xdf\x6c\xed\x3d\x96\x78\xe3\x66\x3a\xdf\xb1\xaa\x9c\xcb\xf7\xd7\x73\x77\x9d\x23\x86\x9d\x86\x45\xa8\xee\xba\xb3\x14\xf4\x1a\xcd\xf7\xe6\xab\x4c\x87\x14\xda\xc6\x32\x55\x75\xdd\xf4\x46\x7a\x4b\xaf\xd9\x74\x4a\xcb\x67\x58\xd4\x36\xfa\x6b\xe6\x05\xaf\xd9\x3a\xce\x09\xd6\xc2\xe9\xb5\x53\xd3\x25\x37\xde\xf1\x0f\x89\x93\xf0\xd7\xff\xf3\x38\x41\xe3\xc7\x09\xf6\x18\x1f\xf7\x7e\xde\x70\xf0\x74\x8c\x63\xd0\xef\x28\xf6\x1d\xc5\x10\x14\xfd\xe1\xfd\x17\xed\xcb\x2c\xcb\x45\x2f\xfa\x87\x56\x12\xe7\x48\x8e\x66\x70\xee\xd2\xa6\x38\xdc\xd3\x77\x22\xfd\xea\x49\x89\x7e\x65\x86\x15\x95\xdc\xa4\x37\x9d\x4a\x86\xc9\x19\x39\xae\x88\xa3\xeb\x97\x4c\xca\x41\xa7\xae\xb3\x2a\xad\xde\xb0\xa1\xdc\x19\x8c\x40\xa6\x0c\xf2\x5e\xde\x23\xdc\xec\xc4\x51\x60\xf0\x9f\xfc\x3a\x39\xf1\x95\x13\xb9\x18\x0f\x3b\xb8\xf7\x80\x2e\xe2\x57\x15\x51\xf7\xa7\xf0\x88\x88\xbb\x42\x26\x78\x2f\x0a\xbb\x8f\x0c\x11\xbc\x80\x74\x1f\x19\x32\x78\x6d\xea\x3e\x32\x54\xf0\xc2\xd0\x7d\x64\xe8\xe0\x35\xa7\xfb\xc8\x30\xc1\x0b\x3e\xf7\x91\x61\x83\xd7\x92\xee\x23\xc3\x05\x2f\xe4\xdc\x47\x06\x43\x83\xf7\x88\xee\xa4\x13\xbc\xb1\x73\xaf\x3c\xc1\xab\x38\xf7\xca\x43\x04\x2f\xbd\xdc\x49\x87\x0c\xde\xd5\xb9\x93\x0e\x15\xbc\xa6\x72\x27\x1d\x3a\x78\xbb\xe6\x4e\x3a\x4c\xf0\x62\xc9\x9d\x74\xd8\xe0\x7d\x98\x3b\xe9\x70\xc1\x9b\x27\x77\xae\x83\x68\xf0\x7a\xc9\x63\x9e\xf6\xf2\x90\x1b\xbc\x97\x7f\x1c\xf7\x8c\x6c\x85\x8f\x77\x75\x39\xe2\xa1\x27\x89\x31\xca\x87\x04\x7e\x34\x39\x7d\x40\x8f\x7b\xf2\x7f\x7f\x71\x4d\xef\xa6\xcc\x9d\x77\xd3\xbf\x3c\x23\x5f\x14\xdb\xd4\x13\xdd\xb6\x79\x46\x6e\xbd\x08\x95\xf0\xa2\xfb\x4d\xd6\xdb\xa3\xdf\xe9\x03\xfd\x8f\xf5\x6e\xb0\xde\x0e\xad\x4f\x1f\xf0\x7f\xac\x17\xcb\x7a\xfe\xec\xe2\xf4\x81\xfc\xc7\x7a\xb1\xac\xe7\x4f\x86\x4e\x1f\xd8\x7f\xac\x17\xc7\x7a\xe7\x29\xe0\xf1\xc3\x3f\x91\x1b\xcf\x7a\x67\x09\xeb\xf1\xc3\x3f\xa8\x11\xcb\x7a\xe7\x69\xf1\xf1\xc3\x3f\x19\xcb\x8d\xd6\xc3\x03\xd6\xc3\xff\xb1\xde\x75\xeb\x9d\x6d\x5d\x8e\x1f\x48\xdf\x0d\x7a\x65\x61\xc8\xd0\x4e\x6a\xc1\xfd\xcf\x1d\x93\x1a\x31\xc6\x75\xfe\x84\x3f\x3b\xbd\xb2\x81\x09\x79\xde\x5f\x82\xa7\x5e\xdc\xf4\x04\xb3\x7b\x37\x49\x91\xcf\x0d\x09\x2d\xe5\xa1\xd1\x5b\xea\xab\x84\xf0\xe0\x8e\xeb\x5e\x42\x44\x60\xf3\x71\xb7\x44\x64\x70\x17\x73\x2f\x21\x2a\x90\xd0\xdf\x2d\x11\x1d\xdc\x19\xdc\x4b\x88\x09\x24\xc9\x77\x4b\xc4\x06\xb3\xed\x7b\x09\x05\x13\xcf\xbb\x25\x3a\x2f\xee\xb1\x09\x44\x3a\x2f\xef\x25\x99\xb7\xf3\x02\x5f\x92\x89\x3b\x2f\xf1\x25\xf1\xee\xf3\x22\x5f\x12\xf7\x3e\x2f\xf3\x25\x59\x03\xce\x0b\x7d\x49\x16\x01\xaf\xd4\x77\x06\x49\x77\x53\x62\x03\x94\xa2\x8b\x6b\xb7\x3e\x65\xf0\x11\xe5\xb5\x6b\x8f\x64\x7a\x46\xb6\x0a\xc4\x2b\xb0\x45\x3e\x53\xf0\x01\xe8\xe1\x7f\x94\x0e\x20\x48\x0e\x32\x04\x81\x41\x8e\x00\x38\x85\x11\x34\x83\xb3\x0c\xc4\x19\x52\x11\x31\x9a\xe3\x80\x08\x14\x06\x27\x44\x19\x12\x0c\x80\x22\xe4\x68\x9c\x64\x25\x86\x56\x64\x02\x65\x30\xf0\xf4\x8c\xec\x7e\xfb\x7b\x7f\x92\xe3\xbb\x0b\xc3\x91\x87\x8b\x90\xd1\xbf\xc0\x62\xd9\xc8\xab\x37\xc7\xd6\x33\xf0\xda\x1f\x9a\x12\x72\xd7\xa5\x79\x3e\xa5\x8f\xed\x62\x77\xb8\x1c\x34\x6a\x44\x47\xc8\xbb\x00\x65\x36\xc5\x55\xa6\x50\x5a\x72\x25\x4b\x19\x67\x06\x65\x78\x3a\x69\xac\x6d\xff\x14\x02\x67\x7a\x99\xd3\x5b\xc1\xfb\x3b\x5a\xae\xe4\x2c\x97\x6d\x3b\xf6\x48\xca\xc9\xe3\x41\xbd\xe0\xbc\x82\xba\xd2\x6d\xb3\xe2\x66\xe5\xbc\x2c\xc4\x56\xbb\xc8\x6b\x22\x9b\x51\x24\x1f\x99\xc3\xa1\xe6\xfe\x25\xcf\xf3\x23\x8d\xf4\xc8\x2f\x0b\x78\x49\x30\xf9\x69\x29\x37\x55\x3a\xe3\x2c\x9a\x23\xb3\x1a\x5f\xd3\x96\x3d\xd6\xce\xea\x06\x56\x76\xa7\xb6\xee\xf2\x5c\xb1\x33\xeb\x3b\xaf\x66\xad\x09\x37\x59\xd6\x16\x87\x8b\x54\x4e\x7d\x7b\x65\xc8\x0d\xd7\xed\x68\x58\x9a\x6b\x12\xcc\x68\xc4\xcd\x07\x4a\x0f\xe5\xcc\xcc\xea\xe7\xcf\x27\xff\x01\xb2\xff\xba\x65\x2b\x4c\x37\xfe\xd4\xdf\x6b\xf7\x2e\x38\xe4\xb6\x7f\xb2\xbe\xa1\x39\x19\x6b\x10\x26\x9f\xa3\xc7\xba\x23\xd7\x21\x37\x22\xdf\xe4\x52\x6b\x80\xd9\xdd\x65\x49\xe1\x85\x91\x9a\x46\x55\x8d\x3b\xe8\xc6\x67\x6b\x82\x0a\x94\x93\x6d\xf3\xe1\xc7\xa6\x42\xd4\x79\x6a\xe6\xc1\xfc\x83\x73\x1b\x8b\x7f\xe6\x34\xbe\xe4\x6b\x52\xd3\x19\xb4\x8a\x96\x0b\x1b\x77\xb6\xaa\x63\xda\x08\x05\x1b\xcb\xc4\xb8\x7a\x71\xbd\xac\x66\x37\x0d\xca\xcd\x08\x52\xb6\xbf\x5c\xe5\xb9\x15\x31\x75\xed\x3c\x51\xc0\x0b\xd2\x55\x9e\x91\xe7\xe3\x5e\xff\x72\x02\xfe\x9c\xd0\xab\x24\xe0\x5f\x0b\xf0\xe7\xeb\x44\x8f\x81\x53\xbe\x69\xe9\x60\x8d\x62\x0c\xf6\xf2\x52\x47\x67\x19\x71\xe0\x36\xd8\x19\xcb\xb7\xd5\x6a\xba\x53\x19\xe2\xad\xbe\x3a\xf4\x2e\x00\x94\x56\x9d\xb2\xb5\xfb\x51\xd4\xee\x7a\x7c\x42\xfd\x6f\xe6\xff\xda\xb3\xb5\x3b\xf9\xfb\x62\x69\xca\x87\xf8\xc2\x3d\xb6\x58\x98\x27\x59\x7a\x9f\x6d\x8b\x55\xa7\xec\x0a\xf7\xf1\xdf\xd9\xe2\xdf\x1f\xb5\x68\x79\xfb\x40\xef\x91\xa4\x87\xdb\x39\x71\xfe\x6e\x31\xd6\xbb\x36\x73\x3d\xd3\xf0\x3f\xca\x0c\x30\x18\x07\x01\x2a\x4a\xb4\x22\x63\x2c\xca\xe2\x92\x08\xa0\xc4\xca\x98\x82\xd2\x12\xca\x90\x90\x96\x68\x00\x18\x96\x54\x00\x07\x21\xa7\xa0\x22\x8a\x51\x92\xc2\x02\x82\x63\x45\x99\xda\x81\x61\xa2\x47\x19\xf9\xc1\x90\xba\x0a\x86\x58\xf4\x8f\xd2\xbc\x46\xec\x29\xb0\x6d\x4a\x8a\x85\xc5\xc0\xe4\x7f\x38\x16\xae\x0b\xc4\x58\xcc\x92\xf2\x8b\x96\x19\xae\x06\x2d\x55\xee\xc2\xb2\x98\x66\x5a\xb8\x62\xa3\x85\x66\x0e\xd3\xd7\x69\x5c\xcc\xa7\x52\x45\x21\x05\x33\x4d\xbb\xd2\x44\x4d\x0d\xeb\x77\xea\xbd\x56\x1f\x0c\x18\xbd\x26\xc9\xf9\x97\x96\xd4\x2d\x76\xc4\xd4\x22\x63\xbe\xa6\xe6\x32\x21\x67\xa7\xff\x19\x58\x58\xd1\x2a\x54\x52\x2c\x7a\x20\xff\xe0\xdc\xc6\xe2\xef\xc3\xc2\x5f\x88\x45\x49\xb1\xb0\x90\xcb\x6c\x1a\xbf\x12\x0b\x03\x58\x24\x25\xd4\xff\x66\xfe\xf3\x61\x7d\x76\x27\xff\x50\x2c\xfc\x45\x58\xf4\x10\x5b\xac\x3a\x65\x7b\x7a\x1f\xff\x3d\x16\x7e\xd4\xa2\xf5\x99\x58\x88\x53\x32\x94\x29\x5c\xe6\x08\x8c\xc4\x38\x0a\xd2\x04\x2b\x31\x14\x2b\xd2\x10\x42\x85\x91\x64\x94\x91\x50\x49\x21\x25\x96\xa3\x69\x8e\x51\x68\x99\x92\x44\x1c\x67\x25\x92\x94\x81\x24\xcb\xec\x0e\x0b\x89\x47\x61\x21\x7d\x1d\x0b\x09\x3c\xfa\x61\x05\xdb\x56\xe2\x29\x50\xb1\x4b\x0a\x86\xa5\xc0\xec\x7f\x38\x18\x02\xfc\xd5\x5e\x51\x64\x13\xd3\x96\x5c\xa9\x50\xab\xbc\x0c\x0b\x4a\xb6\xae\x49\x72\xb6\x3d\xd4\x08\x62\x49\x31\xfd\xd4\x82\xd7\xc7\x23\x05\xeb\x2d\x0b\x35\x07\xcc\xe5\xba\x38\xce\x17\x85\xfa\x94\xa1\x96\xb2\xb1\xae\x91\xa0\xb8\xe1\x25\xbb\x5b\x33\x3b\xdd\xd7\xcd\xb2\x26\x31\xd9\xd6\x7f\x06\x18\x96\xf3\x6f\xa3\xa4\x60\xf4\x40\xfe\xc1\xb9\x8d\xc5\xff\x31\x60\x98\x14\x8c\x12\x83\x61\x29\xdd\xea\xfc\x4a\x30\x0c\x80\xd1\x34\xa1\xfe\x37\xf3\x87\xe3\xa5\x7c\x27\xff\x8f\x00\xc3\x7b\xc1\xe8\x21\xb6\x08\x6c\xd2\xef\x00\xc3\x8f\x5a\xb4\x3e\x13\x0c\x15\x11\x8a\x2c\x45\x8a\x14\x23\x31\x10\xb0\x14\x81\xe2\xac\x82\x13\x50\x84\x0c\x26\x43\x1a\x93\x30\x28\x89\x32\x0b\x68\x52\xa1\x49\x82\x91\x01\x43\x50\x10\x12\x0c\xcb\x12\x12\xa4\xa8\x2d\x18\xb2\x0f\xac\x92\x12\x87\xdf\xc8\x46\x3f\x9b\x87\xc0\xa3\x9f\x71\x75\x68\x3d\x3b\x2c\xba\x0b\x0c\xab\x3c\x1f\x55\xc9\xfb\x70\x30\xb4\x79\xbe\x34\xb2\x32\x64\xa1\x31\x6a\xbc\xbe\x94\xd5\x55\x65\xd9\x76\xc6\xa9\x3e\xc1\x8f\x87\xce\xac\x5b\x6d\x89\x54\xad\xbd\x6c\x2c\x16\x30\xad\x75\xc0\xaa\x8f\xe1\x6a\xbd\xd3\x15\x32\x25\xab\xd9\x78\x1d\xf5\x24\x74\xa6\xf4\x17\xf2\x40\xd1\xab\x32\x0e\x06\x63\xaa\xd7\x92\xb9\xb3\x00\xe6\x13\x82\xa1\xaf\xd3\xad\x60\x54\x7f\xa1\xd8\xd7\x93\x6d\x23\x56\xe0\x2b\x60\xf8\x38\xfe\x77\x55\x69\x7d\x60\xe8\x03\xf3\x9b\x77\x86\xeb\xf2\x28\x9b\x14\x0c\x7f\x61\x95\x36\x71\x65\x10\x6f\x1a\x9b\xa4\x95\xc1\x5f\x54\x99\x0c\x05\xc3\x62\x32\x5b\xa0\xb5\x93\x2c\x11\x4a\x7f\x9c\x2d\x02\x73\x71\x0b\xff\x3d\x18\x7e\xd4\xa2\xf5\x99\x60\x28\xe3\x80\xc6\x45\x85\x11\x39\x88\x61\xac\x88\xb1\xb8\x44\x10\x22\xae\xc8\x1c\x21\xe2\x92\x84\xa3\x18\x21\x8b\x90\x03\xac\xcc\x30\x0a\x41\x01\x9c\xe0\x44\x06\x95\x58\x40\xd3\x0c\xa4\x20\xf5\xf4\x8c\x30\x0f\x04\x43\xfc\xca\xce\x90\x43\x51\x8c\x89\xfe\x69\xe6\xa1\xf5\xec\x9a\x42\xd2\x9d\x61\x70\x95\xf8\x70\x30\x94\x2a\xc6\xb0\x8a\x49\x36\x03\xba\xf3\x11\x4b\x28\x14\xd5\x98\xa1\xb5\x74\xb3\xfe\xd2\xec\x74\xc1\xd8\x34\x73\x25\x45\x37\xc7\x6f\x18\x9d\x99\xe6\xea\x1c\x39\x7b\xb5\x41\x99\x21\x96\x7a\x5b\x2e\xea\xaf\x6e\x19\x54\x46\xf2\xca\x95\xea\x53\x73\x29\x0b\xcb\xfe\x3a\x3f\x02\xa5\xcc\x03\xcb\xa4\x19\xdf\x63\x65\x6e\x05\xa3\x66\xae\x0d\x73\x27\xdb\xe6\xc2\xa3\xee\x0a\x18\x3d\x8e\xff\x5d\x60\xec\x03\x43\x5f\x99\xf7\x66\x30\xb2\xab\x54\x2a\x29\x18\xfe\x42\x30\x4e\x0c\x00\x6c\x3d\x4f\x26\x05\x80\x5f\x04\x40\xa1\x60\x58\x48\x66\x0b\x6a\x75\x92\xa5\xf6\xd9\xb6\x08\xcc\xc5\x2d\xfc\xf7\x60\xf8\x51\x8b\xd6\x67\x82\xa1\x48\x92\x1c\x27\xc9\xa4\x28\x31\x2c\x4e\xe3\x84\xc2\x01\x89\xa3\x29\x12\x25\x51\x99\xe4\x24\x8c\x22\x15\x20\xd2\x40\x64\x65\x96\x10\x71\x0c\x43\x51\x14\x97\x68\x1c\x05\x14\x14\x19\x12\x65\x9e\x9e\x11\xfa\x81\x60\x88\x5d\x03\x43\x0c\xc5\x29\xe2\xc2\xd3\xfb\x70\x8a\x7c\x0a\xdc\x8f\x4b\x0a\x86\xc1\x05\xfb\xc3\xc1\x90\xcf\x28\x6b\x80\xb9\xcb\x6a\x6e\x5a\xa9\xb4\x0d\xa7\xbf\xd2\x39\xa6\x00\xc7\x7a\xd1\x5d\x66\xca\x10\x62\x78\x8b\xe4\x56\x0e\xac\x2f\x2b\xc5\x97\x95\x88\x02\xfd\x75\x58\x28\xf7\x47\xf9\x3a\xd3\x2c\x14\xa9\xf1\x98\xa2\x3b\x90\x2b\x2c\x37\x6a\x95\xe3\xde\xaa\xd5\xee\x1b\xce\xe5\x1e\x78\x7f\x26\xe3\xab\x28\xdd\x0a\x46\x2d\xd5\x4c\x4b\x27\xdb\x66\xc3\xa3\xee\x0a\x18\x3d\x8e\xff\x7d\x60\x7c\x1a\xef\xdb\x59\xde\x0c\x46\x5a\x43\xa4\x93\x82\xe1\x2f\x04\xe3\xa4\x00\x50\xce\x56\x5e\xb8\xa4\x00\xf0\x8b\x00\x28\x14\x0c\xf3\xc9\x6c\x91\xee\x9d\x64\x89\xa8\xde\x7f\x98\x2d\x82\x73\x71\x0b\xff\x3d\x18\x7e\xd4\xa2\xf5\xa9\x60\xc8\x2a\x32\x05\x69\x28\x13\x32\x4e\x53\x2c\x00\x34\x8d\x92\x28\x81\x71\x10\x65\x68\x48\xa0\x28\x4a\x2b\x0c\x47\xa1\x10\x63\x21\x07\x50\x02\x62\x50\x96\x21\x94\x15\x49\x12\x45\x12\xdb\x6e\xc3\xa8\x07\x82\x21\xfa\x8c\xe0\x17\xc1\x10\x47\x19\xe6\xd2\xd3\x3d\x77\xad\x67\x17\xb3\xef\x01\x43\x7e\xf7\x7c\xd9\xd0\x05\xfb\xc3\xc1\x70\xc4\xbe\xb5\x60\x57\x9b\xd3\xaf\x0b\x4c\x81\xb3\x34\x4e\xb8\x9c\x50\x5b\x1b\x66\x63\x90\xa2\x75\xb3\xa0\xbf\x0c\x2b\x0b\x9d\x62\x32\xf3\x79\xeb\x95\x7e\x33\xfb\xe9\xbe\xa4\x96\x99\x52\xbf\x64\xa9\xa9\x97\x66\x7f\xdc\x99\xa7\x2a\x1d\x3b\xdb\x92\x79\x9d\x16\xfa\xe4\x4b\x46\x5c\x66\x1e\x58\x26\xcd\x24\x38\xb3\xeb\x64\xf9\x29\x76\xb2\x6d\x26\x3c\xea\xae\x80\xd1\xe3\xf8\xdf\x07\xc6\xa7\xf1\xbe\x8e\x37\x83\x91\xd2\xe2\xf0\xa4\x60\xf8\x0b\xc1\x38\x31\x00\x94\x4a\xd9\x5c\x52\x00\xf8\x45\x00\x14\x0a\x86\x42\x32\x5b\x08\xe4\x49\x96\xa4\xbe\x90\x74\x2e\x6e\xe1\xbf\x07\xc3\x8f\x5a\xb4\x3e\x15\x0c\x01\xc1\x42\x46\xc2\x51\x52\x24\x14\x16\x88\x2c\x87\x32\x80\x14\x39\x1a\x63\x49\x8c\x61\x29\x52\x94\x24\x91\x22\x01\xa3\x00\x92\x23\x01\x41\x4b\x84\x8c\xb1\x94\x28\x92\x94\x8c\x32\x32\xfd\xf4\x8c\x90\x8f\x03\x43\x96\xdb\x83\x61\xf8\x83\x7d\xbd\x67\xf4\x32\xd1\xbf\xac\x38\xb6\x9e\xfd\x22\x28\x29\x18\x06\x17\xec\x6c\xc0\x09\x1f\x03\x86\xbb\x47\xc7\xdd\xb0\xa0\x9d\x86\x66\x94\xe1\xcc\x47\x29\x73\x74\x72\x21\xf3\xd6\x25\x8c\xa6\x8e\xae\xdd\x05\x9d\x9d\xf7\xa8\x17\x75\xb8\xc8\xe4\xf3\xda\x98\xdb\x74\x87\x86\x26\x54\x36\x54\xb1\x2a\x99\x7d\x93\xdb\xe8\xa4\x35\xab\xb1\x2f\x80\x98\x1b\x63\xb1\x3a\x26\xdf\xca\x6a\x7d\xae\x39\x75\x8d\xe3\x74\xbd\xd3\x9f\x97\x2b\x6f\xcc\x70\x38\x6d\x0c\x85\xe2\x19\xa8\xd6\x7c\xdb\xb4\xd3\xdb\xa0\xcd\xe2\x81\xac\xaf\xd3\xad\x20\xd7\xe7\x97\x2f\x8d\xd3\x9c\x45\xbc\xe2\x80\xdc\x43\xf8\xdf\x0a\xf2\x59\xfe\x1c\x64\x7d\x3b\xd6\x9b\x41\xae\x3b\xc8\x2c\x92\x82\x6c\x12\x90\x1f\x77\x95\x4d\x52\x90\x4d\x02\x2c\xbd\x6c\xaa\x96\x14\x58\x92\xf0\x6f\xe4\xa7\xa5\x04\xfc\xbd\x86\x77\xf1\x70\xc3\x1a\x53\x27\xab\x60\x3d\xe8\x11\xac\x71\x1a\x7e\x5f\xd2\x99\x80\xff\x10\x6d\xca\x09\xf8\x27\x5e\x0f\xba\xb3\x51\x36\x41\x3c\x26\x5e\x0f\x3a\x59\x7e\x76\x27\xff\xb0\x44\xcb\x5f\xc1\xba\x23\x1e\xf6\xce\xb6\x8a\x52\xf7\x43\xe3\x21\x10\x8f\xb7\xf0\x3f\x94\xe0\x51\x8e\x7a\xa3\xdc\x9a\x28\x2e\xa6\x56\xbe\x31\x22\x35\x66\xda\x6e\x8f\x07\x8a\x34\xc7\x28\xaa\x9d\x75\x16\xed\x0d\x51\xc9\x83\xa6\x64\x2d\x2a\xa3\x6e\xb3\x84\xbb\x54\x19\x1f\x6c\x70\x58\xdb\x8c\x5e\xc6\x65\x31\x37\x56\x94\xb1\x35\xd7\xc6\xd9\x8e\x93\xc2\x30\x32\xa7\xad\x93\xfe\x6a\x07\xbf\xf5\x72\x16\x26\xd3\x84\x84\x8a\x2c\x0b\x30\x20\xd2\x2c\x20\x49\x51\x92\x51\x1c\x32\x12\x27\xcb\x8c\xc4\xc8\x80\xc5\x58\x20\x61\x8a\xc2\x32\x0c\x8d\x43\x0e\xc7\x81\x04\x24\x8e\xa3\x58\x86\xa6\xe1\xee\x9f\x74\x4b\xf4\xaf\x9c\xef\x9e\xf0\x72\xb1\xd6\x40\x12\x18\x1b\x5d\x6b\xd8\xb6\xb2\x4f\x81\x1f\x37\xef\x5c\xb5\x50\x65\x8b\xad\x65\x6b\x2e\x56\xf0\x22\x4f\x0c\xfa\x2f\x6d\xbb\xa2\xbf\x0c\x51\x54\x29\xb0\x4e\xb5\xc4\xe8\xa8\xd0\x5e\x95\x07\x69\x7e\x48\xf0\xde\xd3\x72\x8f\xaf\x4b\xa9\x82\xf7\xba\x03\x8a\xfd\x4f\xe0\xcd\x1c\xd3\x25\x21\xd7\x1b\xf0\x86\x41\x8b\x99\x29\xbb\x6a\xb3\x9b\x74\x8e\xa1\x95\x19\x5d\x4b\xe5\x75\x7d\x5d\x01\xd9\x56\x95\x20\x84\x4d\x7b\x30\x18\xe5\xd7\x5a\xbe\x4e\xae\x70\xdb\x02\x63\x62\x31\xa0\xb9\x69\x7f\x4a\x98\x66\x8d\xad\x66\xe7\xf9\x54\x93\xe5\x07\x60\x2d\x55\x32\xb5\x17\x3b\x53\xcb\xc6\xa8\x31\x9c\xf9\x74\x54\xfa\xe3\x0f\x8f\x1b\x97\xdb\x37\x0b\x6f\xa6\x8d\xe8\xe0\xda\xbf\x2e\x2f\x77\x0f\xe4\x7f\xd7\x72\xeb\x2b\xd0\x26\x48\x7f\x1a\xc6\x28\x9d\xf8\xf4\xf9\x17\xa6\x5f\x3c\xff\xeb\x96\xfb\xd0\x3d\x7e\xe6\x7e\x5b\x34\x8c\xf1\x45\x35\xaf\xd9\x22\xe9\x5c\x04\x7d\xe1\x76\x5b\xfc\x1b\xcb\x4f\xcb\x54\x4a\x5f\x8d\x9a\x35\x41\xa9\x2d\x57\xa9\x94\x41\xc2\x97\xe6\x6c\x6c\x39\x1d\x7d\x3a\xcf\x72\xdc\xba\x36\xef\x6b\x7a\x46\x1a\xb7\xbb\xb0\x56\x7f\xa5\x07\xba\xcc\x68\x8b\xe5\x28\x3f\xaa\xd3\x95\x5c\x33\xbb\xb2\x32\xca\x4b\x9a\xcf\xeb\xce\x30\x3b\xed\x96\xe8\x55\x97\x7f\xc8\xe9\xef\xf9\x03\x25\x76\x8f\x75\x72\x5c\xe0\x3a\xfe\xf7\x13\x6b\x0e\x37\x87\x07\x33\x64\x1b\xf5\x4e\xb7\xcd\x97\xea\xd7\x9e\x21\xc1\x57\xbb\x42\x7b\xff\x1c\x87\x46\xbd\x3a\xf2\x53\xfc\x0d\x41\x10\x84\xcf\xe5\x7c\xd4\xde\x31\x44\x9a\xed\x52\x8d\x6f\x8f\x90\x8a\x30\x42\xbe\xaa\xf2\x3b\x69\xa7\xa6\x6d\x4d\x74\x75\x7a\x78\x3e\x54\xe0\xf3\x83\xa4\x0e\x50\x0d\x93\x3c\x8c\xf1\x55\xe9\x0f\x40\xef\xa9\xed\x04\x3e\xee\xfe\x37\x91\x4c\x19\x4e\x4e\xcf\xda\xda\xbf\x55\x1d\x67\x01\xed\xc9\x43\xb4\x3b\x67\x1b\xa6\xdc\x5d\x82\x21\xbd\x7a\xa9\xd5\x13\x90\xaf\xa7\xee\xcf\xc8\xa9\xff\xe1\xfd\x6e\xc0\x8d\xa6\x79\xcc\xb4\xde\xac\xf8\x4d\x93\x1a\xf1\xe0\xe4\x2b\xcf\x26\x7e\xac\x66\xe1\x4c\x2e\x69\x7a\x41\xac\xd8\x9a\x47\x3e\xd7\xe6\xea\x83\x63\x1e\xab\x7d\x14\x9b\x4b\xfa\x5f\x14\xed\xaa\x05\x76\x2e\x2d\x6e\x3c\x6f\x3f\x28\x52\xaa\xe7\x84\xe1\x15\x1d\xb2\x6d\x81\xef\x0a\xbb\xae\xe7\x54\x90\x46\x3d\x18\x0c\xbd\x4e\xa9\x5e\x40\x44\xd7\x86\xd0\x1f\x5d\xd1\xd2\xec\x62\x2c\xb9\x3c\x3b\x3a\xf1\x24\x8a\x88\x6b\x71\x33\xd9\x3f\x52\xef\x6e\x71\x4e\x24\xfc\x92\x9c\x6d\x96\xce\xe5\xd9\x75\x7e\x46\xf6\x6f\x26\x0e\x7c\x5d\x40\x43\x7a\x6f\x30\x71\x33\x99\x01\x67\x96\x44\xb2\xed\xf8\x78\x62\xf9\x3d\x6d\x3b\x2a\x4c\x9a\xdd\x3f\xfb\x92\x44\x9e\x1d\x85\x78\x12\xed\xfa\x1e\xcd\xf3\x8c\x00\xcb\xd2\x54\x69\xb7\x1c\x98\xb6\x1c\xb1\x4c\x4f\xe0\xd6\x37\xbc\xf6\x3b\x24\xdd\xa3\xc4\x4e\xe0\x00\x39\xbf\xd8\x50\x51\xa0\x14\x74\xb5\xf7\xab\x96\x2a\x3f\x23\x5f\xbc\xc1\x5f\xa2\x84\x55\xe5\x07\x89\xa9\xca\xb1\x05\x3c\xb8\xde\x56\xbc\x3b\x84\x36\xad\x89\xf5\x28\xb9\xf7\xb4\xfc\xa2\x47\x40\xd5\x5d\x9a\x84\x2b\xe0\xae\x1f\xa7\xc0\x9e\x56\x84\x4f\xdf\xa9\x82\x9f\x42\x98\x12\xa6\xb5\xf5\xca\x99\x79\x97\x0e\x7b\xe1\x4f\x34\xee\x35\xfe\x65\x43\x3b\xfb\x68\xf7\x96\xea\xe4\xb6\x3e\x27\xe7\x17\xf9\xf0\xaf\x51\x9d\xc9\x18\x2e\x91\xdf\xae\x8f\x12\xeb\x1d\xcd\x78\xcb\x5b\x98\x80\xee\x6e\x4a\xdc\x24\xd3\x7a\xa2\x71\xbf\x4b\x5e\x73\x3f\xd7\x96\xb7\x4c\x44\xe0\xc0\xc4\xf8\x19\x46\x2c\x20\xb9\x0c\x03\x72\xfa\xfb\x5e\x15\xd0\x54\x94\x04\xa0\xf5\x9e\x54\x2c\xe1\xbc\x9e\x97\x44\xf3\x64\x87\xf6\xc3\xcc\x17\xa0\x77\x4d\xc8\x40\xf7\x38\x92\x3e\xc6\x8e\x67\xd4\xe2\x4a\x79\xd5\x9a\x8f\x91\x2d\x96\x4c\x97\x65\x39\x48\xac\x99\xe6\x7c\x61\x25\x93\xe8\x9c\x56\xec\x19\xdd\xe5\xbb\x11\xf2\x59\x40\xb5\x27\xae\xaa\xc3\x87\x48\x18\xa4\x16\x2f\x6e\xf7\x02\x3e\x23\x41\x91\x9f\x91\xfd\x12\x2f\x69\xa6\x03\xe5\x09\x70\x23\x94\x78\xc0\xba\xbd\xa7\x73\x4d\xe2\x1b\xb3\xa3\x2d\xd5\x87\x59\xf7\x06\xc3\x5e\xb5\x9b\x6a\xc8\x70\x3d\x09\xa4\x1c\xce\xc4\x34\x26\x40\x96\x6d\xe8\x38\x49\x0d\x7a\x95\xc1\xd9\x3e\x6d\xdf\x1c\xd8\x19\xed\x3a\xde\x20\x7b\x72\x3f\xb8\x44\xfb\xba\xc4\x21\x51\x76\x4e\x70\x9f\x85\x6f\xe9\xb9\x1b\xeb\xfe\x3d\xf8\x45\xaa\x57\xd3\xfe\x6d\xa7\x2b\x82\xee\x73\xa8\x2d\xc9\xa3\x13\x3d\x48\xda\x30\xd2\x57\xd3\xb7\xb8\x9e\xec\x23\xfe\x68\x67\x38\x23\x7d\x4f\xbe\x19\x4d\x4e\xb7\x4c\x7b\xbb\xf0\x2d\xa1\xed\xa8\xa6\xf1\x78\x43\x07\x39\x5c\x17\x3f\x30\x20\xbe\x32\xfb\xa5\xe7\xce\x4a\x45\x3c\xfb\xfb\x78\x5c\xd5\xc4\xd7\x37\xbe\x12\x96\x0d\x97\xaa\xb9\x70\x3e\x45\x9b\x30\x66\x57\xd5\x0a\x1b\x14\x5f\xbf\x43\x11\xe5\xc3\x74\x3a\x30\xb8\xaa\x47\x64\xb5\xeb\x9c\xf4\xe9\x1f\xd9\xf8\x88\xd0\x0e\x52\x0f\xdd\x00\xdf\x1a\xe0\xe7\x44\xcf\xb7\x50\x0f\x8a\xf0\x4b\x2c\xe2\xe8\x70\x65\x5f\x77\x91\xd9\xe3\xe0\xeb\x3d\xe1\x58\xb2\x5f\x07\x31\xff\x66\xfb\x23\xdc\xe6\x3d\xfd\xbb\xb7\xfa\x5e\x12\x77\x04\xf2\x43\x85\x71\x22\x9a\xe6\xfc\x6e\x2b\x5f\xa0\x79\x35\x45\xf8\xfa\x55\x86\x2e\x50\x35\x07\xf9\xfe\xaf\x7f\x21\x4f\x8e\xa9\xc9\xbe\xd3\xb4\xa7\x1f\x3f\x5c\xb8\x76\xbf\x7d\x7b\x46\xa2\x3b\x4a\xa6\x1c\xaf\xe3\xae\x16\x1f\xdd\x55\x34\x17\xd3\x99\x1b\x8b\xfd\x59\xd7\xcb\x02\x9c\x75\x0d\x88\xf0\x0d\x19\x14\x85\xb6\xb0\x73\x32\xe4\x27\x42\x10\xb1\x0f\xa2\x55\x79\xa2\xf8\x8e\x89\xf2\x95\xcf\x39\x8e\xde\xb3\x45\xf2\x8d\xb6\x50\x2a\xd4\x8f\x47\x40\x48\x5b\xc8\x0b\x6d\xa1\x9e\x15\x3a\x81\x53\x11\xaf\xb5\x51\x47\x7a\xcd\xdc\xd6\x65\xda\x42\xa7\xdb\x2e\x65\xbb\xdb\xaf\x72\x42\x55\xe8\x0a\x48\x96\xef\x64\xf9\x9c\x70\xe1\x1c\x6d\xbb\xef\x38\xff\x38\x09\x94\x62\x1e\x67\x8c\x73\x3e\x57\x0e\xc9\xa2\x24\x39\xb7\x4f\xb0\x6c\x14\x6a\xac\x7d\xa2\x7f\xe5\x44\x31\xd2\x12\xfb\xad\xec\x2f\xb7\x83\x5f\x8e\x30\x2b\x1c\xaa\x04\x97\x1d\xe6\x36\x0b\xbc\x2f\x2a\xfd\x42\x33\x44\x08\x73\x6e\x8b\x90\x32\xd8\x63\x9d\x22\x58\xe2\xf8\x4f\x30\x48\xb4\x6b\xbc\xab\x21\xc5\xf5\x8e\xa6\xe9\xb8\x53\x1b\x76\x5a\x55\x44\x06\x2e\xd8\xba\x18\x22\x2f\x74\x0b\x91\x4c\xdd\xd2\xa0\x0b\x3d\x1d\xfe\x2f\x00\x00\xff\xff\x40\xe2\xbf\x97\xea\xe6\x00\x00") func operation_fee_stats_3HorizonSqlBytes() ([]byte, error) { return bindataRead( @@ -446,7 +446,7 @@ func operation_fee_stats_3HorizonSql() (*asset, error) { } info := bindataFileInfo{name: "operation_fee_stats_3-horizon.sql", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} - a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x9f, 0x60, 0x30, 0x4, 0xf7, 0xa3, 0xc8, 0xba, 0x95, 0x3c, 0xd1, 0x1, 0x7b, 0x2e, 0x70, 0x13, 0x31, 0xa9, 0x63, 0xb6, 0x92, 0x4d, 0x2e, 0x6b, 0xdf, 0xae, 0x8c, 0x2, 0x2f, 0x50, 0xc0, 0xf8}} + a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xde, 0xde, 0x3, 0x6e, 0x40, 0x63, 0x42, 0xdc, 0x80, 0xe2, 0x43, 0x9a, 0x57, 0x65, 0x9e, 0x4a, 0xa, 0x47, 0x3c, 0x53, 0x2a, 0xe1, 0x24, 0x8a, 0x14, 0x93, 0x3b, 0x23, 0xb4, 0x8f, 0x8a, 0x94}} return a, nil } @@ -470,7 +470,7 @@ func pathed_paymentCoreSql() (*asset, error) { return a, nil } -var _pathed_paymentHorizonSql = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xe4\x7d\x79\x93\xa2\xc8\xf6\xe8\xff\xf3\x29\x88\x8e\x1b\x51\xdd\x61\xf5\x14\xc9\x4e\xcf\x9b\x5f\x04\x2a\xee\xfb\xae\x13\x13\x46\x02\x09\xa2\x28\x0a\xb8\xd5\x8d\xdf\x77\x7f\x21\xb8\x20\x8a\x0b\x5a\x35\x35\xef\x19\x73\xfb\x96\x92\x9c\x2d\xcf\x96\x27\x4f\xc2\xcf\x9f\xbf\xfd\xfc\x89\x55\x4c\xdb\xd1\x2c\x54\xaf\x16\x30\x05\x3a\x50\x82\x36\xc2\x94\xf9\x78\xfa\xdb\xcf\x9f\xbf\x6d\xae\x27\xe7\xe3\x29\x52\x30\xd5\x32\xc7\x87\x01\x0b\x64\xd9\xba\x39\xc1\xf8\xdf\x99\xdf\x81\x6f\x94\xb4\xc6\xa6\x5a\x7f\x73\x7b\x60\xc8\x6f\x75\xb1\x81\xd9\x0e\x74\xd0\x18\x4d\x9c\xbe\xa3\x8f\x91\x39\x77\xb0\x3f\x31\xfc\x0f\xf7\x92\x61\xca\xa3\xd3\x5f\x65\x43\xdf\x8c\x46\x13\xd9\x54\xf4\x89\x86\xfd\x89\xbd\x34\x1b\x29\xee\xe5\x8f\x1d\xb8\x89\x02\x2d\xa5\x2f\x9b\x13\xd5\xb4\xc6\xfa\x44\xeb\xdb\x8e\xa5\x4f\x34\x1b\xfb\x13\x33\x27\x5b\x18\x03\x24\x8f\xfa\xea\x7c\x22\x3b\xba\x39\xe9\x4b\xa6\xa2\xa3\xcd\x75\x15\x1a\x36\x3a\x42\x33\xd6\x27\xfd\x31\xb2\x6d\xa8\xb9\x03\x96\xd0\x9a\xe8\x13\xed\x8f\x2d\xed\x08\x5a\xf2\xa0\x3f\x85\xce\x00\xfb\x13\x9b\xce\x25\x43\x97\x5f\x37\xcc\xca\xd0\x81\x86\xb9\x19\x26\x14\x1a\x62\x0d\x6b\x08\xf1\x82\x88\x65\x53\x98\xd8\xc9\xd6\x1b\x75\xac\x5c\x2a\x74\xb7\xe3\x7f\x1f\xe8\xb6\x63\x5a\xeb\xbe\x63\x41\x05\xd9\x58\xb2\x56\xae\x60\x89\x72\xa9\xde\xa8\x09\xd9\x52\xc3\x77\xd3\xf1\xc0\xbe\x6c\xce\x27\x0e\xb2\xfa\xd0\xb6\x91\xd3\xd7\x95\xbe\x3a\x42\xeb\x3f\x3e\x03\xa1\xec\xfe\xf5\x19\x28\x37\x7a\xf5\x79\x0c\x7a\xd8\xee\xe7\xce\x23\x70\xa3\xc8\x97\x90\xf9\x46\x1d\x80\xbb\xc3\xb3\xa5\xa4\xd8\xf1\x8d\xdc\x82\x75\xa9\xea\x23\x55\x45\xb2\x63\xf7\xa5\x75\xdf\xb4\x14\x64\xf5\x25\xd3\x1c\x5d\xbe\x51\x9f\x28\x68\xd5\xf7\x31\x37\xb1\xa1\xab\xe8\x76\xdf\x9c\xf4\x75\xe5\x9e\xbb\xcd\x29\xb2\xe0\xfe\x5e\x67\x3d\x45\x0f\xdc\x7d\xa0\xe4\x21\x2a\xee\xbb\xd7\x40\x8a\x86\x2c\xf7\x46\x1b\xcd\xe6\x68\x22\xdf\xc5\x82\xef\xf6\xa9\x85\x16\xba\x39\xb7\xb7\xbf\xf5\x07\xd0\x1e\x44\x04\xf5\x38\x04\x7d\x3c\x35\xad\x8d\x39\x6e\x7d\x6a\x54\x30\x51\x65\x29\x1b\xa6\x8d\x94\x3e\x74\xee\xb9\x7f\xa7\xcc\x11\x54\x69\x6b\x97\x11\x88\xf6\xdf\x09\x15\xc5\x42\xb6\x7d\xf9\xf6\x81\x63\x29\x6e\xdc\xe9\x1b\xa6\x39\x9a\x4f\x6f\x18\x3d\xbd\x46\x92\x37\x0a\xea\xd6\x9d\x80\x77\x4e\xf7\xe6\x1b\x36\x7e\x42\x55\x91\x75\xdb\xd0\x1d\xf8\x08\xb7\x6c\xc5\x7a\xdb\x4d\xae\x6b\xbd\x03\x89\xdf\x15\x5f\xbb\x63\xba\xb9\x61\xe0\x5c\x9d\x01\xfb\xc8\x01\x49\xeb\xab\x6a\x34\xd8\x5b\xfa\x2d\x83\x4d\x8f\x0e\xf3\xea\x40\xdd\x76\xfa\xce\xaa\x3f\xbd\x0e\x72\x33\xd2\x9c\xde\x3a\x12\xdd\x3a\x6c\x17\x4a\x2e\x0f\x96\x76\xe6\x7e\x75\xd8\x75\x2f\x26\xad\x6f\x9b\x4c\x2f\x46\x6e\xa4\x6d\xdb\xf3\x6b\x98\xf7\x83\x65\x53\x41\x77\xe6\x05\x7b\x35\x98\x42\xcb\xd1\x65\x7d\x0a\x27\x17\x83\xf7\xb5\x5b\xfb\xd3\x3b\x73\x93\x7d\x44\xbb\x97\x82\xf3\x37\xde\x8d\xdf\x15\xde\x2d\xf8\xbc\x81\x1f\x0e\xdf\x9b\xcc\xcd\x4c\x6e\xff\xdc\xc4\x87\x5d\xea\xe7\x2a\x43\xff\x46\x0a\x34\xd3\x9a\xf6\xc7\xba\xb6\x4d\x18\x2e\x90\x10\x18\x79\x33\x8f\xf7\xe7\x7b\x97\x20\xdf\xaa\x9c\xde\xdd\x89\x72\xa1\x59\x2c\x61\xba\xe2\x61\x4e\x8a\x29\xa1\x59\x68\xdc\x08\x3b\x44\xe9\x9e\x00\x79\x3b\xdd\x97\x21\xb9\xdf\x6e\x67\x7f\x17\xa5\xeb\x62\xb5\x29\x96\x12\x11\x64\xb6\xc9\xb3\x6d\x34\xbb\x1b\xf3\x11\x90\x9b\xef\x56\xd0\x8d\x63\x0f\xd9\xec\xcd\x1c\x86\x58\xfd\x3d\xfc\x9d\x07\x71\xdb\xbd\xdb\xbc\xef\xb6\xc1\xdb\x24\xef\x66\xde\xb6\x1e\xe0\x1e\x5e\xbc\x5b\x6e\x1c\xbb\x4d\xff\x6e\xa7\x67\x97\x2f\xde\x42\x51\xc0\x87\x5c\x1e\xec\x73\x09\xdb\x81\x42\x3a\x5d\x13\xd3\x42\xe3\xcc\xe0\xb1\xbe\x59\x71\xe8\x32\xfa\x3e\x99\x8f\x91\xa5\xcb\x7f\xfd\xfd\xe3\x86\xbb\xe0\x2a\xc2\x5d\x06\xb4\x9d\xef\x70\xb2\x46\x86\x5b\x8a\xb9\xe1\x0e\x55\xb7\xce\xde\x92\x6a\x96\x12\x8d\x6c\xb9\x74\x81\x9f\x3e\xd4\xb4\x03\x75\xaf\xd8\x09\xa1\x17\x60\xec\xb8\x7b\x00\xc6\x86\x57\xf7\xf6\x03\xf1\xaf\xd8\x3d\x8c\xb8\xac\xdf\x00\x41\xec\x34\xc4\x52\x3d\x00\xc2\x98\x6a\xf6\xcc\xd8\xe9\x62\x22\x23\x16\x85\x13\x0c\x7f\xfc\xe6\x55\xe1\x4a\x70\x8c\x7e\xed\x7e\xc3\x1a\xeb\x29\xfa\xb5\xbd\xe5\x0f\xac\x2e\x0f\xd0\x18\xfe\xc2\x7e\xfe\x81\x95\x97\x13\x64\xfd\xc2\x7e\xba\xc5\xb9\x44\x4d\xdc\xcc\xd7\x16\xf2\x0e\xde\x6f\x47\x10\x8f\x2f\x6e\x01\x27\xca\xc5\xa2\x58\x6a\x5c\x80\xec\x0d\xc0\xca\xa5\x63\x00\x58\xb6\x8e\xbd\xec\xca\x6e\xbb\xdf\x6c\x17\xc8\x4b\x10\xf3\x8e\xfd\x2d\xce\xbd\x84\xae\xf2\x73\x24\xcb\x52\xb9\x11\x90\x27\xd6\xce\x36\x32\x7b\xb2\xfc\xf5\xb7\x23\xf4\x07\x28\x01\x42\xee\x61\xfe\x04\x88\x2b\x80\x4a\xe1\x6d\xaa\xd5\xab\x05\x6c\x6a\x99\x32\x52\xe6\x16\x34\x30\x03\x4e\xb4\x39\xd4\x90\x2b\x86\x1b\xeb\x85\x7e\x72\xaf\x2b\xda\x96\xfc\x9d\xae\x1e\xe8\xdf\xcd\xed\x39\x59\xee\x35\xfb\x2a\x7c\xac\x26\x36\x9a\xb5\x52\xdd\xf7\xdb\x6f\x18\x86\x61\x05\xa1\x94\x6e\x0a\x69\x11\x73\xb9\x2f\x16\x9b\x9e\xbf\xab\x37\x6a\xd9\x44\xc3\x1d\x21\xd4\xb1\xff\xf4\xff\x83\xd5\xc5\x82\x98\x68\x60\xff\x01\x9b\x6f\xc1\xd9\xb8\x6a\x88\x8f\x71\x77\x0d\xfc\xd3\x98\x23\xce\x31\x77\x8b\xa7\x7a\x8c\xbf\x1b\x30\xec\x59\xdc\xff\x14\x89\xc3\xef\xbf\x61\x58\x42\xa8\x8b\x58\x3b\x23\x96\xb0\xff\x80\xbf\xc0\xdf\x6f\xff\x01\x7f\x11\x7f\xff\xcf\x7f\x08\xf7\x6f\xe2\x2f\xe2\x6f\xac\xe1\x5d\xc4\xc4\x42\x5d\xdc\x08\x45\x2c\x25\x7f\x9c\x95\xcc\x0d\x71\xe0\x41\xc9\x5c\xc7\xf0\xd1\x92\xf9\x3f\x51\x24\x73\x1a\x53\xb7\x72\xd8\xc7\xe1\xdb\x04\x71\x08\xdb\x27\x10\x5d\x8a\x31\xac\xbe\x91\x15\xf6\xe7\xc1\x03\xbc\x7a\x3f\x37\xba\x15\x11\xfb\xd3\x6f\x11\x3f\xce\x59\xed\x53\x69\x0c\x02\x0c\x90\xb8\x33\xe3\xdb\x29\x3c\x9b\x02\x3d\x4a\xe5\x39\xa0\x01\x4a\x8f\x0c\xf2\x98\xdc\x83\x96\x9d\x52\x7b\x2e\xcd\x7b\x98\xda\x33\x40\x83\xd4\xfa\x8d\xe4\x22\xb5\x9b\xc8\xa5\x20\x15\xce\x0d\xa7\xef\x40\xc9\x40\xf6\x14\xca\x08\xfb\x13\x7b\x79\xf9\xe3\xf8\xea\x52\x77\x06\x7d\x53\x57\x7c\x5b\x69\x47\xbc\xfa\xf3\xdf\x2d\x8b\xae\x81\xdd\xc6\x9e\x67\x8b\xfe\xc5\xb7\xc7\x91\xae\x60\x92\xae\xe9\x13\xc7\x4d\x0c\x4a\xcd\x42\xc1\x63\x07\x8e\x37\x69\x3c\x26\x0f\xa0\x05\x65\x07\x59\xd8\x02\x5a\x6b\x7d\xa2\x05\x86\x4d\xe6\xe3\x7d\xca\x8f\xe9\x13\x07\x69\xc8\x0a\x0c\x51\x0d\xa8\xd9\x98\x3d\x86\x86\x71\x8a\xc6\x31\xc7\xc6\x29\x92\xef\x04\x4d\xff\xd8\x8f\x3c\x9d\xf6\xe0\xba\x21\xaa\x38\x82\xd5\x8e\xbd\x48\x1c\xb4\x3a\x11\xc8\x74\x6a\xe8\x6e\xcd\x1e\x73\xf4\x31\xb2\x1d\x38\x9e\x62\x9b\x39\x73\xbf\x62\xef\xe6\x04\x9d\x12\x1a\xb6\x2a\xda\xe5\xa3\xdb\xe5\xd4\x6d\x34\xef\x17\x5f\x21\x50\xb7\x6a\x28\xd4\x1a\x5e\x46\x07\xdc\x1f\xb2\xa5\x44\x4d\x74\xd3\xaf\x78\x77\xfb\x53\xa9\x8c\x15\xb3\xa5\x96\x50\x68\x8a\xfb\xef\x42\xe7\xf0\x3d\x21\x24\x32\x22\x06\xae\x31\x13\x59\xec\x41\x40\x27\xaa\xb8\x2d\x7a\x60\x13\xb4\x72\x16\xd0\xf8\xfe\x12\xc2\xf1\xcb\xaf\x5f\x16\xd2\x64\x03\xda\xf6\x8f\xe0\x74\x79\x7b\x15\x67\x74\x8b\xa1\x7e\x5c\x98\x28\x6f\x6d\xfc\x30\x67\x5e\x45\x67\xcf\xd7\x79\xcb\x38\xd4\xea\xce\x93\x79\x76\xb8\x6c\x2a\xe7\x86\x03\xe2\xfc\x70\xaf\xfc\x77\xe6\x06\x9a\xb9\x64\x61\xe7\xcb\x0b\x4f\x52\x5b\x3f\xcc\x4f\x53\xda\x4b\x8c\x60\xe5\x76\x49\x4c\x62\xf1\xee\x15\x8e\xbc\x0a\xdd\x65\x86\xf6\xb0\x02\x97\x7f\xd7\x95\x30\xda\x76\x35\x9f\x47\xb5\x6e\x0b\x67\xab\x76\x01\x9b\xe9\x87\x79\xfa\xd3\x12\x57\xd8\xc8\x6f\xee\xc6\xc7\xb7\x10\x6d\x76\xf5\xf8\xfc\x25\x05\x39\x50\x37\x6c\x6c\x68\x9b\x13\x29\x5c\xd9\x76\x85\xb2\x47\xe5\xb0\x85\xb3\x95\xc3\x6e\xdf\x3a\x84\x36\xdf\x66\xf2\x4d\x56\x78\x6e\x1f\xfb\xfc\x8d\x5b\xb1\xf8\x2a\xa3\xee\x44\xec\xe9\xd8\x79\x39\x3c\x80\xe1\x30\x11\xb7\x8d\xdf\x6f\x26\x07\x02\x93\x39\x77\x0e\xb1\x29\x78\x8f\x85\xa0\x73\xf5\x26\x6f\xec\x7c\xaa\xdc\x3c\x76\xaf\x3a\xdb\xaf\x81\x7d\xf6\x13\x5e\xc0\x49\x3e\xe0\x40\xa3\x2f\x9b\xfa\xc4\x3e\xaf\x83\x2a\x42\xfd\xa9\x69\x1a\xe7\xaf\xba\x3b\x9f\x2a\x0a\x9b\x6b\xf7\xb2\x85\x6c\x64\x2d\xc2\x86\x6c\xf2\x50\x67\xd5\x77\xd3\x24\xfd\x3d\x6c\xd4\xd4\x32\x1d\x53\x36\x8d\x50\xbe\x82\x73\xb4\x53\x16\x04\x15\x64\xb9\xe9\x85\xf7\xbb\x3d\x97\x65\x64\xdb\xea\xdc\xe8\x87\x2a\xca\x96\x71\xa8\x1b\x48\xb9\x36\x6a\x4b\x7a\x88\x0a\x85\x9b\x5e\x48\x7d\xfb\x51\x4b\x0c\xd9\x33\xb9\x12\x17\x6f\xf7\x48\xd7\x7d\xdc\xbd\x2c\x3f\x37\xd4\x5d\xc4\xf1\x59\xa1\xef\x2e\x46\x1f\x0c\x85\x17\x71\x9d\x86\xc6\xf3\xc3\x2f\x84\x4a\xdf\xee\xcf\xd3\x74\xf3\xda\x52\xe8\xb8\xf3\x2a\x64\xb9\xb4\x59\x1d\xc8\x1e\x2b\x6e\x94\x7c\x30\x48\x6e\xbd\x83\x39\xb7\xe4\x7d\x2b\x47\x48\x78\xda\xb9\x9c\x97\x97\x5f\xbf\xc2\x97\x6b\xe1\x76\xb0\xdd\x7c\x7b\x54\x9c\xdb\x7e\xc1\xef\x4f\xcd\x29\xb6\x6e\x33\x4a\x84\x73\xfb\x65\x42\xd1\x06\xba\x15\x2f\x0d\xda\x36\x50\x5e\x1a\xe2\xad\x95\xcf\x0e\x38\xed\xfb\xbc\x32\xee\x22\xba\xfd\xa8\x0b\x18\x5d\x92\x74\xbb\x6f\x23\xc3\x40\x16\x26\x99\xa6\x81\xe0\x64\x17\xb7\x74\x19\xf5\x27\x47\x31\xda\xfb\xed\x38\x6e\x1f\x3a\x8e\xfa\x81\x88\x7e\xd4\xf3\x14\xbc\x68\x99\xf3\x89\xe2\x36\x0d\x1b\xfa\x74\x0a\x35\x74\x0a\x54\xb7\xfb\x68\x05\x65\xe7\x98\x2e\x5f\x0f\xc0\xd9\xb6\x52\x97\xdd\xbe\xdb\x78\x8c\x25\x32\x62\x22\x8f\x7d\xff\xee\x17\xfd\xff\x60\xf8\x8f\x1f\xd7\x40\x9d\xbb\x7d\x27\xed\xff\x73\x32\x01\x37\xc0\x3b\x9a\x8c\x00\xf8\xc0\x4c\xb9\x04\x5e\xb4\xc1\xf3\xdb\xe7\x4f\xb0\xca\xf3\x0d\x11\x37\x86\xe0\x5b\x7c\xdf\x23\x41\xf8\x5a\xf3\xc1\x73\xc2\xf0\x15\x2c\x9f\x15\x88\xef\x64\xf6\xc1\x50\x7c\x05\xdb\x69\x30\x0e\xbb\xe1\x42\x38\x3e\x6a\x38\x79\xa2\xae\xee\xf4\xd3\x4f\xd2\xcd\x2b\xb4\x6d\xd0\xb8\xb2\xee\xbb\x35\x62\x5f\x0e\xbe\x67\xc7\x1e\x50\x9f\xb5\x97\xcd\x12\x23\x7c\x8d\x12\xb6\xfa\xfb\x47\xd6\x6f\xce\xaa\x8f\x26\x0b\x64\x98\x53\x74\xae\x26\xea\xac\x36\xab\xa9\xb9\xe1\x84\x5c\x1c\x23\x07\x86\x5c\xda\xac\xe3\xc2\x2e\xdb\xba\x36\x81\xce\xdc\x42\xe7\xca\x77\x3c\xf3\xe3\xaf\xbf\x0f\x49\xcf\x7f\xff\xf7\x5c\xda\xf3\xd7\xdf\x41\x99\xa3\xb1\x19\x52\x69\x3b\xc0\x9a\x98\x13\x74\x31\x89\x3a\xc0\x3a\x05\xb3\xe5\x4c\x1f\xa3\xbe\xb4\x09\x83\x6e\x39\x9c\xb3\xe0\x44\x43\x47\x6a\x79\xfe\xe2\x58\x9f\xf4\x43\xb4\x27\x7c\x40\x3f\x18\x61\xcf\x0e\xda\xe2\xd5\xe0\xf4\x68\x2c\x5a\x39\x16\xec\x6f\x44\x8d\x2c\xdb\x9d\x85\xbf\xfe\x0e\xae\x49\x8f\x83\xf4\x66\xca\x36\x6c\x6b\x28\xb0\xc8\x9f\x4c\x90\xd5\xbf\xcd\x54\x0f\x90\x2e\xda\x95\x1f\xf0\x75\x6d\xd8\x6e\x45\xa0\x65\x7f\x67\x5a\x1e\x79\xd7\xca\x9a\x98\xae\xec\x9c\xd6\xae\xcd\xee\x16\x4f\xeb\x79\x2d\xb7\xa7\xf1\x4a\x07\x5f\x5d\x6c\x5c\xa8\x65\xfb\xab\x86\xfe\x4a\xf6\x7d\xeb\xb8\xe7\x31\x71\x63\x83\xe3\x45\xa6\x2e\xae\xff\x6e\x61\x32\x34\x61\x79\x1a\x9b\x37\xf7\x88\x5e\x64\xf4\x4a\x74\x3d\xcf\x6a\x12\x3a\x10\x53\x4d\xeb\xca\x8e\x1e\x96\x14\x1a\xc2\x15\xf6\xb2\xa5\xba\x58\x6b\x60\xd9\x52\xa3\x7c\xb4\xab\xe7\x26\x23\x75\xec\x3b\x78\xc5\x5e\x00\x81\x6f\x3f\x2f\xaf\x18\xf1\x8a\xe1\xaf\xd8\xcb\xcb\x8f\x3f\xae\xde\x4b\x5c\xb8\x37\x84\x95\x4b\x3b\x72\xf7\xb2\x13\xdc\x95\xdb\x91\xf5\x02\xfa\xfa\x44\x77\x74\x68\xf4\xbd\x0e\xa9\xdf\xed\x99\xf1\xf2\x8a\xbd\x10\x38\xe0\x7f\xe2\xcc\x4f\x9c\xc4\x00\xf7\x8b\xe0\x7e\x51\xec\xef\x38\x49\x50\x3c\x13\xc3\x89\x20\xc3\xa1\xd0\x89\xbe\x77\xf2\xe5\x68\x36\xa5\x75\xdf\x31\x75\xe5\x32\x26\x9e\xa1\xd9\x7b\x30\x91\xfd\xb9\x8d\x0e\x0e\x5a\x9f\x9c\x9c\xb6\xb9\x88\x8f\xa2\x70\x8a\xbb\x07\x1f\xd5\x87\x8a\xd2\x0f\xd6\x2c\x2f\xe2\xa0\x29\x9a\x24\xee\xc1\x41\xf7\xbd\x94\x64\xb7\x38\x72\xf7\xba\x2f\xa2\x60\x48\x9c\xb8\x8b\x0d\x66\x87\x62\xeb\x39\x6f\x40\xc1\x51\x80\xbe\x07\x05\xdb\x1f\x9b\x8a\xae\xae\x6f\xe7\x82\x03\x0c\x71\x17\x0a\xee\x88\x8b\x6d\x8b\xfb\x0d\x78\x58\x8a\x21\xef\xc3\xb3\x99\x74\xa8\x69\x16\xd2\xa0\x63\x5a\x97\x75\x8a\xc7\x01\xce\xdf\x03\x9e\x77\xc1\x7b\xf5\xec\xfe\x4a\xb1\x2e\x43\x27\x58\x70\xd7\x54\x03\xdc\x05\xbf\x9d\x05\xb7\x42\x71\x19\x01\xcd\xb3\x77\x49\x07\x00\x3f\x82\xfd\xca\x75\xe3\x00\x2e\x23\xe2\x19\xfe\x3e\x4e\x88\xa3\x89\xde\xd6\x0a\xbc\x43\xd5\x97\x30\x01\x9c\xa5\xa9\xbb\x66\x04\x90\x1e\x3b\xfb\xd2\xcc\xc5\x19\x07\x80\x60\x99\xfb\x38\xa1\xfa\xaa\xbe\xda\x1d\x30\x31\xc7\x46\x5f\xd5\x91\x71\xd1\x35\x02\x40\x03\x70\x97\x13\x06\xf4\x2e\x5f\xdd\xed\x77\xac\xae\xb0\xc1\xb0\xf7\xb9\x79\xc0\xf4\xf5\x89\x86\x6c\xa7\x7f\xba\xa3\x72\x05\x15\xcb\x73\xf7\xcd\x08\x7b\x94\x26\xb8\x5b\x57\xf0\x72\x30\xd9\x84\x5d\x92\xba\x0b\x09\xb7\x57\x5f\xd5\xb4\x76\x09\xfd\x11\x0e\x80\xff\x24\x01\x06\xa8\x5f\x80\xff\x45\xf1\xbf\x03\x82\xe4\x48\x3a\x86\x83\x0b\xf1\xfc\x62\xaf\xc7\xbd\x01\xfd\xa4\xdf\xc3\x9f\xa4\xa4\xe3\x9d\x74\x35\xd7\x6e\x15\xda\xe5\x6e\x26\x55\x68\x35\xf2\xed\x16\x9d\x4a\x67\x04\xb2\x50\xea\x76\x89\x5c\x35\x5f\x64\xcb\x42\x4e\x68\x8a\xd5\x54\x93\x29\x54\x12\x75\x31\xd5\xea\x94\x4b\x41\x01\x85\x22\xd9\x64\x33\xe9\x44\x27\x9f\x66\x6a\x25\xaa\x5c\xca\x8a\x95\x44\xb1\x94\x8a\xb3\x24\x21\x50\x24\xd3\xa3\x2b\xa5\x64\xbd\x56\x48\xb7\xf3\x6c\x3a\x5e\x48\x14\xab\x85\x6c\xaa\x4c\xd5\x59\xb1\xdb\x6e\x35\x6f\x46\x42\x6e\x90\x08\x74\x3b\x5e\xe9\x0a\x74\x97\x6a\x0b\x62\xa6\xd3\xae\x11\xcd\x7c\x99\x68\x96\xa9\x78\x33\x9d\x69\x56\x59\x4a\x6c\x56\xf2\xe5\x12\x51\xcd\xb4\xa8\x76\x2d\x53\xce\xd6\x4a\xf9\x7c\xe6\x64\xaa\x43\x91\x50\x2e\x27\xd5\x4a\x37\x9d\xa1\xf2\x34\xdb\x89\x27\xc5\x52\x3e\xdf\xa1\xe9\x7c\xb2\xd1\x2e\x37\xf2\x74\x3b\xd9\xae\x55\xcb\x19\xa2\x90\x11\x93\x1d\x52\xcc\xb7\xb2\xd5\x5a\xa1\x28\xd6\xd3\xf1\xf4\xcd\x48\x68\x17\x09\x41\x56\x53\x44\xa6\x29\xd2\x84\x50\xec\x34\x53\xcd\x0c\x29\x74\x73\x42\xa7\x93\xee\x74\x5a\x44\x2b\xd3\xe9\x76\x6b\x8c\xd8\xed\x88\x8d\x4a\x3e\xd9\xe9\xd5\x85\x36\xc3\x76\xca\xd4\xcd\x48\x18\x77\xe2\x6b\x95\x6e\x26\x5b\x20\x12\x59\x32\x55\xaa\x52\xf1\x4e\x21\x55\x2c\x25\x0b\xa9\x5c\xb3\x54\x69\x12\x99\x2e\xd9\x2b\xa6\xea\x99\x72\xa9\x99\x10\xcb\x42\xbd\xcd\x56\x13\x6c\xb9\x43\x64\x5e\xa2\x76\x59\x6d\x12\xfa\x2b\x5a\xbb\xed\x4c\x3d\x34\x95\xff\x6e\xa3\xcb\x1d\x48\xaf\x18\xf3\x8a\x39\xd6\x1c\xdd\x60\x4b\xa7\xbd\x45\x91\x2d\xc9\x5b\x6f\xfa\xed\x48\xb6\x90\xa2\x3b\x7d\x68\x4c\x07\x70\x32\x1f\x53\x1b\xeb\x6f\xd6\x93\x2f\x1f\x31\x9d\xc7\xd8\x89\x10\xec\x62\xb3\xf6\xf2\xa0\xc6\x46\xe9\xe5\x79\xca\x2c\x1f\xad\xcd\xdd\x05\xd0\x6d\x73\x7c\xae\x95\x27\xea\x24\xef\xda\x79\x7c\x3e\x86\xa0\x59\x86\xe7\x70\x96\x63\xc9\x57\x0c\xb8\x74\xbd\xfc\xf7\x9b\x97\x54\x7c\xfb\x85\x7d\x03\xf8\xef\xdb\x55\xdb\xb7\x57\xec\xdb\xa1\x61\x6c\x73\x4d\x6c\xd6\x0e\x3f\x3a\xeb\xa9\xfb\x63\x70\xde\x0e\x23\xbc\xc6\xb1\xcd\x98\xa8\x13\xf8\xed\x7f\xc3\x14\x28\xc8\x19\x11\xe0\x8c\x78\xc5\xc8\x3b\x38\x6b\xd6\x93\x51\x39\x8b\x66\x18\xd1\x39\xdb\xfc\xe7\xb1\xe6\x6d\xcf\xb9\x54\x44\x8c\x80\x1b\x8e\x76\xb9\xde\xb7\x5f\x1b\x75\xf8\x66\x9b\x86\xd2\x0f\x13\x9a\x64\xce\xb5\x81\x13\x7a\xd9\xbb\xf7\x9c\x60\x7d\x57\x2e\x49\x77\x07\xff\x9c\xd6\x1d\x5d\xbb\x04\xc4\x87\xeb\x09\xf3\x14\xc4\xfc\x99\x4a\x0d\x02\x53\x4f\x9d\x9b\xfa\x88\x79\xc9\xc7\x4f\xfd\x76\xde\x1e\x99\xfa\xad\xf6\x3c\x3a\xf5\x11\xe7\xe9\xd2\xd4\x7f\xb4\xd5\x83\x57\x0c\xb0\x9b\xe5\x02\x4b\x12\x1c\x38\xeb\xa9\x89\x7f\xa7\xa7\xa6\x02\x9c\x9d\xf1\xd4\xff\x52\xce\x88\x3d\x67\x2c\xc9\xb2\x21\xd1\xf5\xdf\x19\x84\xe8\x00\x6b\x67\xc3\xeb\xbf\x93\xb5\xbd\xa5\x71\x80\x0a\xc9\x89\x2e\xe9\xe3\x17\xe6\x8c\x0e\x70\x76\xa7\xa5\x7d\x61\xce\xc8\x3d\x67\x34\xcd\xf0\xf7\x5b\xda\x17\x76\x22\x54\x80\xb5\x7b\x2d\xed\x0b\xb3\xb6\x99\x35\x82\xe3\x28\x1e\xa7\x79\x8e\xf6\x66\x0d\x77\x79\x33\xf4\xb1\xee\xb2\xc6\x13\x04\x49\xb2\x04\x4e\x32\x1c\xfd\x3b\xc5\xb2\x34\x87\xb3\xff\x2a\x1e\x89\x1d\x8f\x00\xc7\x77\x71\x3b\x12\x8f\x5f\xd8\xfa\xc0\x9e\x47\x0a\xec\xe2\xdc\xff\xbb\x3c\x72\xc4\x2e\x2a\xfc\xbf\xa6\xab\xf4\x2b\xc6\xd1\x1c\xcf\x93\x1c\xc3\x79\x4e\xd4\xe3\xd0\x76\xa0\xe5\xe8\x13\xad\x2f\x41\x03\x4e\x64\x14\xf4\x39\x37\x23\x60\x8e\x11\xdc\xea\xca\x76\x52\x9a\x40\x47\x5f\xa0\xc8\xfc\x6c\x66\xcd\x63\x68\x89\x74\x6d\xe0\x6c\x57\x39\x5e\xf1\xa4\x3f\x42\xeb\xcf\xd1\x24\x6a\x4b\x15\x45\xb0\x5b\xa7\xf7\x41\x52\xde\x22\xf8\x68\x29\x07\xf8\xb9\x51\xca\x9f\xb0\x54\xf6\xa8\x62\xb8\xad\xdb\xfd\x28\x29\x7b\x08\x3e\x5a\xca\x01\x7e\x6e\x93\x72\xd4\x2a\xd0\x3d\x11\xdc\xa5\x8a\xc6\xf9\xad\xe3\xff\x20\x29\x6f\x11\x7c\xb4\x94\x03\xfc\xdc\x26\xe5\x88\x7b\x34\x77\xe5\x10\x1e\x55\x34\xbe\x0d\x3d\x1f\x25\x65\x0f\xc1\x47\x4b\x39\xc0\xcf\x8d\x1e\x23\x62\x59\xeb\x7f\x6f\xd8\x92\x3c\x77\x4a\x34\x6a\x89\x7d\x77\x52\xd4\xbf\x2f\xc5\x13\x8c\xa2\x12\x80\xa5\x21\xc5\x22\x56\xa5\x64\x1a\x11\x2c\x49\xb2\x3c\x23\x4b\x12\x05\x65\x46\xe2\x24\x1a\xa7\x11\xa5\x40\x8e\x66\x78\x19\x57\x18\x62\x93\x6a\x48\xbc\x02\x58\x40\xab\x2f\xaf\xd8\x0b\xcd\xf0\x2c\x87\x14\x9a\x67\x00\x52\x54\x92\xe3\x08\x20\x4b\x04\xce\x93\x84\xa4\xa8\x04\xab\x22\x1a\x87\x04\xa0\x00\x01\x08\x0a\x27\x14\x5a\x52\x69\x48\xe0\x2c\x64\x09\x85\x96\x79\x86\x7e\x71\x15\x07\x04\x36\x89\x99\x5f\x24\xf3\x0b\xe0\xc1\xbd\x63\xf7\x67\x9c\xff\x9d\x21\x29\x86\xe1\xae\x5e\xdd\x16\x25\x49\x96\x65\x5e\x31\xb0\xf9\x1f\x7e\xf2\x79\xc5\x00\xed\xfe\xbb\xfd\x67\xff\xeb\xfe\x8f\x0d\x6d\x82\x20\x08\x09\x00\x3b\x43\xa7\xdd\xce\x38\x1c\xa5\x0d\xd6\xeb\x44\x23\xcf\x73\x93\x37\x23\xa1\xa7\xe2\xd9\x7a\x35\x01\x24\x1e\x66\x33\xd3\x35\x90\x0d\xc3\xd0\xc7\x60\x46\x54\x01\x29\x0d\x06\x2d\x96\xe8\xe6\x34\x6e\x64\x5b\x55\x76\x50\xe6\x88\xe9\x3a\xd6\x9d\xe9\x46\x32\x2b\x70\xfc\x5a\xd4\x36\xa0\x85\x4e\xa5\x55\x44\xde\x9f\xee\x47\x31\xa7\xe9\x59\xef\x2d\xa5\xbd\x73\x2b\x8d\x07\x6a\x62\xd9\xb0\x17\xab\xec\xd8\xe6\xe7\xa3\x36\x4b\x26\x32\x28\xe1\xc4\xe7\xa5\x71\xa9\x5d\xc8\xb6\xaa\xe3\xb7\xe9\xb2\xbe\x9e\x51\x43\x15\x2d\x26\xc3\x8a\x94\xcd\x10\x59\xb9\x13\x8f\x57\x1a\xb1\xf7\xc6\x4a\x31\xf5\xee\x62\x61\xcc\x54\x17\x7e\xb7\x44\x15\xe0\xfb\x94\xa8\x1e\x90\x09\x1d\x59\x38\xfe\xc4\x37\xff\xf4\x84\x0e\xa0\xaa\x82\x90\xc4\x73\xc2\xbf\xed\xf3\xb2\x73\x47\xa5\x66\xa1\x10\x62\xfe\x41\x8b\xa0\x9f\xa3\xcd\x2f\x14\x89\x24\x88\xab\x04\xe2\x29\x1e\xca\x1c\xaf\xe2\x90\xe0\x55\x12\x4a\x2c\x81\x53\x90\x86\x84\x4a\x90\x0a\xc0\x21\xe4\x21\x8d\x70\xc4\x49\x90\x54\x24\x05\x91\x0c\x64\x38\x9e\xa1\xf8\x0b\x16\x81\xf3\xa1\x3a\xcf\xb0\x0c\x4e\x5e\xbd\x4a\x00\x8a\xa5\x38\x92\xa1\x38\xfc\x92\x45\x50\x37\x5a\x04\x5e\xb1\xcc\x4a\x61\x5a\x87\xeb\x1c\x97\xcf\xab\x65\x4b\xd6\xea\x86\xb9\xc8\xf2\x62\x7e\x06\x3b\x1a\x53\x30\xf9\x05\x2a\xcd\x60\xae\x97\x6b\xd4\x85\x5e\x91\x1e\xe5\x60\x76\x48\xa6\xc6\xb3\x71\x42\x94\xf5\xb6\xd8\xa8\xc5\xaa\x6f\x65\x9b\x67\xd5\x6c\x8b\x12\xca\xb0\x55\xcb\x2d\x44\x77\x06\x5d\x8b\xf0\x29\x69\x51\x9f\xb6\xb4\xa4\x54\x28\xc7\x97\x35\xd3\xc8\xc4\xed\x46\xdd\x1e\xaf\x52\xa5\x77\xd4\xe8\x90\x82\x32\xeb\xd5\x3b\x0e\x59\x48\x17\x53\xe3\x61\x99\xa8\xe8\x13\xd6\x51\xb5\x54\x42\x88\xaf\x2b\xba\xac\x0d\x73\x44\xa9\x5e\x5c\xd5\x14\xa5\xcd\xf0\xc2\xb0\xe0\x2c\x19\x19\xc2\x5a\xcf\xb5\x88\xe6\x19\x8b\x68\x51\x01\x85\xfa\xff\xd2\x22\xa8\xe7\x68\xf3\x0b\xe2\x79\x56\x66\x19\x48\x52\x2c\x2f\x71\xbc\x4c\xa8\x32\xe2\x20\x89\x58\x40\x52\x2a\x49\xaa\x08\xd1\x94\xc2\x2a\x34\x20\x19\x46\x92\x78\x15\xc8\x3c\x49\xc9\x1c\x41\xd2\x40\x91\x08\x1c\xbe\xb8\x5b\x4a\xd4\x59\xe5\x0e\x8f\x02\x1c\x45\xd2\xd4\xc5\xab\x6e\xf0\x71\x8b\x58\x0c\x0f\x38\xea\x92\x45\x90\x37\x5a\x44\x6c\xdc\x59\x11\x26\x8e\x24\x5d\x2e\x70\x4c\xbe\x32\x11\x71\xee\xfd\x6d\xde\x2a\xa9\x2d\x91\x80\xec\x64\xb5\x6e\x34\xb2\x59\x90\x91\xb2\xf9\xda\x4a\x5c\x3b\x7c\x5d\x19\xd1\xcb\xd8\x9a\xaf\xc9\x25\x9b\x4e\xcf\xb3\x2b\x72\x46\xd7\x13\x2d\x42\x2e\x34\xa7\xac\xe9\x34\xf1\x5c\xac\xd1\x75\x67\xd0\xb5\x08\xdf\x8c\xf6\x90\x91\xad\xd4\x49\xbb\x3a\x10\x12\xf3\x7c\x76\x64\x93\x14\x03\x68\xae\x46\xe6\x78\x30\xb2\x66\xb1\x1c\xf7\x86\xc6\xe9\xd1\x6a\x51\xb7\x12\xb5\x4e\xdd\x5c\x52\xac\xf8\x6e\x19\x03\xb2\x6c\xaa\x9d\x65\x3c\x33\x6b\x81\x9e\x55\x98\x9b\xf4\x3c\xdd\x36\xb3\x86\x5a\x50\x0b\x59\xcd\xb5\x88\xea\x19\x8b\x68\x36\xcf\x69\xd5\xbf\xdc\x22\xa8\x7b\x2d\x82\x7c\x8e\x36\xbf\x90\x2a\x4f\xcb\xb2\x2a\x03\x45\xc2\x71\x8e\xe4\x54\x92\xa1\x71\x19\x10\x32\x0b\x64\x9c\x65\x68\x20\xab\x1c\x83\x78\x44\x2a\x12\x29\xd3\x32\xa7\x72\x04\xce\xd1\x1c\x05\x10\x05\x01\x20\x89\x4b\x16\xc1\x86\xea\xfc\x26\xb5\x0d\xb7\x88\xdd\xd5\x6d\xed\x13\x70\x1c\x77\xc1\x22\xf8\x1b\x0d\xe2\x3d\xd6\x7a\xaf\x2c\x15\x5b\xd0\x28\x8e\x68\x16\x45\x5b\x96\xe3\x44\x53\x8e\xa5\x19\x54\x91\x2a\xa9\x75\x45\xd3\x06\xdd\x2a\xaa\x0f\xc4\x75\x8f\x14\x47\x74\x2f\x9b\x07\x6a\x41\xac\x77\xe4\x82\x21\xbe\xe1\xf8\xbb\x60\xe3\x4c\x82\x47\xa3\x29\xc8\x49\x6f\x04\xb2\x4a\x6b\x79\xbe\x74\x27\x70\x63\x10\xca\xf2\x30\xa1\xf5\x71\xbb\xdb\xc5\xc5\xe6\x28\xde\x2e\x52\xda\x5b\x6c\x34\xd1\x9a\xfa\x70\x99\x6d\xb1\x65\x2b\x41\xf7\x46\x6f\xc5\x4c\x37\x9d\x1b\x8a\xa2\x4d\x0a\xf8\x6a\xd8\x9e\xca\x1d\xcb\x68\x27\xda\x52\xa2\xd1\x50\x63\x39\x2b\x9f\xa4\xac\x91\x3e\x9f\x8c\xa4\x64\x99\x58\x65\x74\x4e\x78\xa3\x3d\xc8\xc5\x33\x06\x51\x16\xcf\x29\xd5\xff\x6f\x06\x41\x3c\x47\x99\x5f\x18\x52\xe1\x39\x95\x26\x19\x84\x18\x4e\x01\x12\xc1\x4a\xb4\xc4\xf1\x2a\x41\x42\x95\x26\x01\x90\x58\x9a\xe1\x21\x41\xa9\x50\x05\x14\x4e\x42\x05\x97\x68\x42\x62\x48\x52\xc2\x59\x09\xf1\x9b\x30\x43\xbb\xff\x9d\xd1\x6d\x26\x4c\xe5\x59\xc0\x90\x1e\xfa\xd0\xab\x9b\xa4\xc9\x2b\xd6\x51\x34\x4f\x5c\xb0\x87\x5b\x17\x11\x44\xa5\x37\x04\xa5\x39\x6d\xe2\x52\x8e\x6d\x53\x93\x75\x79\xd1\x5c\xa5\xc9\xd6\xd4\x1c\xc5\x16\x29\xa1\xec\x24\x40\x9e\x28\xb2\x71\x96\xe9\x0d\x26\xaa\x24\x26\xa7\x99\x4a\x57\xa1\xe8\x49\x55\x6e\xb0\x9d\x91\x9a\x2d\x2e\xeb\x1d\x5e\x4b\x25\xf9\x98\xda\x86\x0e\x0b\x98\x6a\xb6\xed\xe5\xef\xae\x3d\xb8\x0e\x3c\xbb\xff\x47\x70\x55\xd6\x3e\x7c\x5f\x0a\x95\xea\xc8\x9b\xef\x2a\x3f\xe6\x0a\xf5\x34\x27\xd1\x6d\x5c\x9a\xaf\x44\x67\x66\x3b\xad\xea\x3b\x9b\x6d\xbd\x65\xac\xe4\x38\x2d\x3a\x8a\x40\x8d\x13\x62\xb2\xb3\xe6\x06\x0d\x87\xe8\x6a\xb5\x49\x23\xdb\xc8\xce\xdf\xa9\x59\xa9\x27\xd2\xb3\x62\xa9\xf1\x8e\x4f\x45\x9c\x02\x2d\xb9\xd9\x4a\x2f\xc7\x6d\xd8\x74\xed\x31\x7b\xc6\x5e\x32\xf8\x39\x9d\xfb\x97\xdb\x0b\x7d\xaf\xbd\x80\xe7\xe8\xba\x7b\x44\x73\x83\x1a\x7f\xc5\x5e\x00\xcf\xe2\x3f\x71\xf0\x13\x07\x18\x8e\xff\x72\xff\x0b\xd5\x69\x92\xf3\xd2\x9e\xcb\x57\x29\x82\xa7\x78\x86\x25\xf8\x4b\xeb\xe6\xf3\xfa\xee\x91\xf4\x4f\x4f\x4d\xf8\x27\xde\xc9\xeb\xd4\xfa\x6d\x5d\xcf\xc7\xd9\xe4\x24\xc9\x67\x08\x7c\x35\x8c\xc7\x6c\x5c\x73\xec\x65\x76\xf9\x0e\x3a\x4a\xbd\xdd\x85\xf1\x1c\x4c\xb9\xa6\x24\x9e\x51\xe5\xf3\x9f\x9d\x2a\x0b\x42\x7c\xf4\x09\x8c\x3c\xf5\xf3\xb2\x53\xa6\xad\x2a\x5f\x29\x4c\xdd\xf0\x0c\xa5\xa8\x75\xaa\x90\xa3\x99\x61\xad\x66\x44\x88\xdd\x5d\x01\x73\xd2\xac\x18\x0d\x0c\xb9\x5b\x51\x53\x38\xed\x16\x9a\xa3\x81\x09\xb6\x1a\x51\xd1\xc0\xd0\xc1\x5e\xac\x68\x60\x98\x40\x0f\x0d\x1d\x0d\x0c\x1b\x6c\xc5\x89\x06\x86\x0b\x34\x87\x44\xa4\x86\x0f\x76\xcf\x44\x03\x03\xf0\x40\xdb\x43\xc4\xa9\x02\x20\x00\x27\xa2\x02\x02\x22\xd0\xab\x10\x15\x0e\x19\xe8\x07\x88\x38\x5b\x80\x0a\xee\xb9\x47\x84\x43\x07\xf7\xb5\x23\xc2\x09\x6c\xed\x32\x11\xc1\xb0\xc7\x60\x22\x2a\x21\xe0\x8e\xf7\x24\xa3\x52\xc3\x1f\x83\x89\xa8\x83\x04\x7e\xbc\x77\x17\x91\x1a\x22\xb8\xa5\x19\x11\x0c\x71\xbc\xc7\x15\x95\x9a\xe0\x56\x59\x44\x30\xd4\xf1\x5e\x50\x54\x6a\xe8\xc0\x0e\xd6\x73\x1e\xd1\xf7\x94\x83\x1f\x97\x9f\x5f\xb0\x89\x8f\xb7\x9e\x04\x09\x79\x52\xdd\xc3\x19\x80\x5f\x8e\xfe\x90\xbf\xff\x42\xf8\x3a\xea\x1c\xf3\xa1\x4d\xcf\x57\xec\x9b\x6a\x99\xe3\x47\x3b\xd5\xa7\xd0\x19\x7c\xfb\x85\xfd\xf5\xf7\x2b\xf6\xec\xb3\x2a\xdb\x27\xe4\x8d\xe1\x2a\x0c\xe4\x73\x5a\xc9\x77\x4f\xe2\x0b\x6d\xa0\xf7\x2e\x9f\x3f\x3d\xe1\xbb\x76\x03\x2f\x4f\x6c\x97\xfa\x80\x93\x8f\xe7\xf4\xd0\x9f\xec\x1d\xbe\x30\xae\x1e\x7a\x7b\xd3\xee\x09\x6e\x57\x6c\x47\x13\x14\xd2\xc9\xea\x3d\x91\x6e\xc3\xfc\x7f\xbf\xed\x8e\x37\x4c\x36\xff\xff\xbf\xc7\xc7\x1e\xf0\x57\xec\x9b\x34\x5f\xeb\x13\x2d\xe4\xe4\x81\xff\xda\x45\xc9\x23\xc3\x38\x85\xb2\x3b\x02\x71\x74\xf1\xe2\x29\x08\x3f\xbe\xe7\x9c\x5e\x39\x46\xfe\x94\xfe\xb2\x0f\x38\x73\x7b\x46\x29\x8e\x73\xee\xfd\x17\x7c\xbf\x8d\xb7\x77\x4e\x0f\x9c\x7e\x3a\x38\xa7\xe8\x96\xfd\x75\x0f\x2e\x7c\xc0\x69\xdf\xf0\x89\xda\x1e\x7a\xd8\x7f\x61\x4e\x27\xea\x81\x08\x70\x98\xa8\xe8\xa6\xf0\x85\x0f\x2b\x7c\xc0\x19\xdb\xd0\x99\xda\x2d\xd5\xf6\x5f\x88\x0f\x32\xa9\x67\xcc\xd4\x57\x3b\xa1\xf0\xa9\x13\xb5\x3d\xdd\xb0\xff\xc2\x9d\x4e\xd4\x53\x12\xb3\x67\xf8\xbe\x2f\x77\x2a\xe1\x93\x9c\xdf\xd1\x89\x86\xfd\x17\xca\x9d\x26\xe6\xb6\x8e\x71\xc7\x9a\xdb\x0e\x42\x8f\xce\x85\x0b\xc6\xb4\x1e\x55\x8b\xaf\x31\x73\x4f\x7e\x12\x46\xe8\xcc\xed\xce\x69\xec\xbf\xe0\x91\x67\x2e\xba\xbb\xf3\xcf\xdc\x03\x31\xf2\x8b\x78\xc7\x0f\x5f\x2e\x1c\x57\xc2\xf6\x5f\x98\x7f\x78\xe6\x1e\x88\x99\x5f\x63\xe6\x3e\x21\xa7\x3f\xaa\x3d\xee\xbf\x10\xff\xb0\xb7\x7c\xda\xcc\xfd\x53\xde\xf2\xe3\x67\xce\x5f\xa6\xdd\xff\xcd\xf9\xba\xd3\xd5\xf9\x44\xd9\x3d\x8d\x22\xda\x63\x79\x5c\xb9\x78\x0f\xc7\x79\x78\xd1\x7b\xb5\x55\xfe\xc1\xc7\x07\xdd\x23\xb5\x6d\x39\x79\xff\x37\xf5\xb1\x52\x7b\xa0\x44\xf5\xa5\xa4\xe6\x95\xbd\xf7\x7f\xe3\x1f\x2a\xb5\x07\x3c\xc0\x97\x92\xda\xb6\x3c\xbf\xff\x9b\xf9\x50\xa9\x3d\x90\x65\x7e\x2d\xa9\x79\xdb\x08\xfb\xbf\x89\x8f\xb5\xd0\xe8\x19\xde\x87\x4b\xed\xca\x96\xc4\x99\x37\xbd\x44\xdd\x8e\xd8\xbe\xed\xe5\xec\x56\x04\x1e\x7a\x6c\xc5\xdb\x97\x00\xc7\xdd\x31\xde\x6f\x87\x1f\xdc\x77\x9f\xee\x96\xca\x14\x03\x00\xc3\x31\x38\x45\x01\x9e\x05\x3c\xcd\xee\xb6\x4f\xaf\xb3\x7a\xfd\x85\x1a\x0f\x30\x7f\xfe\x09\xd2\x67\xfb\x31\x88\xf0\x7d\xe3\xab\x80\x88\x00\xa0\xb0\x8d\xbb\xab\x80\xc8\x60\x65\x3e\x2a\x20\x2a\x50\xcd\x0d\xdb\x66\xbd\x0a\x88\x0e\x96\x85\xa3\x02\x62\x02\x65\xcb\xb0\x6d\xe8\xab\x80\x82\xf5\xcf\xc8\xb3\xc6\x05\xca\x73\x91\x29\xe2\x83\x75\xbe\xa8\x80\x8e\x3b\x34\xb8\x07\xa6\xed\xb8\x47\x83\x7b\x40\x25\x8f\xbb\x34\xa8\x47\x20\x91\x81\x12\x40\xe4\x99\x3b\xee\xd4\x78\xc4\x4e\x8e\x7b\x35\x1e\x9a\x3b\xe6\x38\x67\x0f\xdb\x75\xbf\x0e\x88\x3d\x06\x14\x59\x2d\x8f\x3a\x36\xa8\x47\x28\xe2\x8f\x01\x45\xd6\xca\xa3\xae\x0d\xfc\x01\x8a\x88\x60\xd2\x1a\x19\x10\x71\x9c\xc7\x45\xa7\x88\x3c\x06\x14\xd9\x4a\x8e\xba\x37\x88\x47\x28\xa2\x8f\x01\x85\xf7\x6f\xdc\xfb\xc2\xa3\x67\x74\x70\x5c\x7b\x31\xc3\x3d\x3d\x1c\xa1\xaf\x37\x7a\x42\xe6\xe0\x7f\x84\xb3\x42\x40\x4a\x42\x2c\x41\xb1\x38\x43\x73\x2a\xc3\x29\x12\x8d\x23\xa4\x12\x3c\x82\x38\x54\x49\x95\xe7\x68\x19\x01\x4e\xa2\x65\x02\x70\x2a\x4e\x52\x0c\x50\x28\x5c\xa6\x58\x45\x26\x78\xc2\x7b\x08\x2d\x78\xa4\x7c\xe7\xeb\xe7\xa7\x76\x1d\xcc\xa1\x07\x89\x69\x9c\x0d\xed\x96\xde\x5f\x3d\xca\x5b\xbc\xd6\xe7\x3c\x33\x44\x3a\x39\x1c\x9b\x59\xae\x91\x36\x92\x6f\x48\x93\x49\xb6\xd2\x71\x32\xf9\xfc\x7b\xbb\xc5\x2d\x5b\x7a\x2f\x0e\x13\x73\xba\x40\x17\x05\xb7\x75\x58\xd8\x35\xe8\x27\x02\x9d\xb9\xf1\xc3\x9f\xee\xf5\x78\xab\x55\xda\x9e\x3c\x49\x80\x79\x5c\xc9\x98\x8d\xb9\x56\x5c\x54\x9d\x24\x1b\x1f\x64\x0b\x64\x09\xf1\x4a\xab\xa2\xa6\xb3\xb1\x9c\x4e\xe7\x16\xcd\x72\xac\x27\x38\xac\x77\x4a\x26\xc5\xa3\xed\xad\x49\x47\x5b\x2c\x93\xf3\x72\x5b\xa8\xf2\x6c\x0d\xd4\x1a\x4e\x53\x59\x96\x92\x99\x69\xf2\x2d\xd1\x44\xd3\x77\xa5\x5a\xe9\x18\xe6\x44\xd6\x0b\x2d\x77\x7c\xb3\xd5\x6a\x6e\x8f\x27\x9b\x95\x65\xf7\x2d\xa5\xbc\xc9\xd9\x75\xa9\x39\x7b\x43\xb3\x4c\xf9\x7d\x3a\x63\xbb\x8a\xb9\x94\xd5\xfa\xfb\x28\xa3\xf6\x52\xad\x5a\x22\x4f\x88\x5e\x17\x74\x5c\xed\x0c\x4e\xfa\x8d\x21\x3b\x5a\x8c\x96\x2e\x7b\x49\x8a\x87\xb5\xe6\xfc\xbd\xd3\x41\xa5\xcc\x1c\xa4\xd4\x6c\x37\x2e\x4d\x8d\xb8\x59\x89\x49\x20\x4e\xcd\x8b\x69\x87\x68\xa6\x7b\x0e\x33\xac\xe4\x17\xcb\x56\xb9\x36\x2e\xbe\xab\x9d\x64\x0f\x66\xe2\x8b\xac\x6e\xd9\x59\x0e\x95\xd4\x18\x9f\x02\x62\x16\x4f\x0d\xf8\xe2\x1b\x31\x1c\x27\xb4\x3f\xff\x7c\xf1\xb7\xa1\xa7\x7d\xed\xdb\x87\x3f\x7d\xb2\xf6\xe4\x22\x8d\xb5\x31\x68\x11\x8a\x46\xb7\xc0\x78\x06\x90\x51\x94\xd3\xc0\x59\x0d\xeb\xdd\x7c\x8f\x5f\x8a\x9a\x59\x8f\x43\xd4\xe6\x9a\x7a\xca\x0c\xc0\x4b\xa5\x5a\x2d\xef\x80\x85\x90\x4f\x72\xe9\xca\xaa\xa3\x92\x89\xe2\xb0\x95\x5f\x90\xb3\xc1\xbb\xcd\xc0\x39\x91\x81\xc5\x4c\x06\xb7\xe9\x38\x49\xd4\x5a\xcd\xaa\xee\x0c\xb6\x47\x1e\x76\x6d\xe3\xff\xea\xb9\x3d\xc8\xbb\xba\xd7\xd5\xa4\x3b\xc6\x77\xac\xdd\x9a\x95\x98\x02\x2a\x43\x6d\xb8\x2a\xc2\x66\x85\x67\xe2\xef\xaa\xcd\x23\x5c\x36\xad\x52\xaf\xf3\x1e\x6f\xe7\x46\x29\x33\xbf\xd3\x0d\x41\x28\xd3\x56\xae\xec\xd3\xfd\xc0\xfc\x1d\xcd\xdd\x99\x4f\xfc\xc9\xf8\x13\x51\xf0\x27\x5c\xfc\xc5\xc3\x40\xef\x7e\xb6\x5b\xe0\x04\x76\x68\x68\x62\x05\xe1\x4a\xb3\xc9\xb6\x32\x72\xb2\xba\x62\xaa\x6f\x4b\x23\x33\x93\xc9\x66\x12\xd0\x30\x47\x66\x75\xf0\xa8\x7e\x25\xe7\x70\xad\xc5\xdf\xf6\x9f\xe5\x39\x9a\xdd\xef\xe9\x7f\x84\x3e\x31\x5d\x9d\x2d\xaf\xd1\x17\x94\x5f\x62\x6e\x92\xa6\x43\xd1\xb3\x44\x45\x5c\x4d\xab\x6f\xa4\x99\x29\xc5\xde\x01\x5b\x5b\xeb\x36\x30\xd4\x62\xaa\x3b\xae\xb6\x35\x6b\x5e\x8f\x35\xdc\x9b\x52\xad\x26\xbe\x9d\xb8\x42\x9b\x4a\xe1\x68\x50\x66\x84\x35\x9f\xc0\x2b\x76\x5a\xd4\x16\x32\x60\x01\x68\xf2\x5c\x77\x48\x8d\x0b\xa3\x31\x5f\x65\xe9\x51\x82\x5c\x44\x97\xdf\x67\xd2\xd7\x1e\x31\xd5\x9b\xe4\x97\x72\xff\x74\xf5\x31\x3e\x87\x09\xa9\xd5\xe9\x11\x49\xa3\xd3\x86\x56\x8b\x69\xae\x96\x52\x9b\x4c\x97\x72\xda\x74\x42\x0a\xf5\xc4\x20\x9b\x9a\xd2\xd2\xaa\x9e\x6d\x6b\xc7\xfa\xfc\x80\xbf\x78\xc4\xbf\x15\x18\x6e\xab\x5f\xd5\x73\xfc\x1d\xe8\x8b\x1f\x4e\xc0\xfd\x33\xfe\xbc\xd5\x6a\xd4\xb6\xa0\x1c\x49\xeb\xd4\x18\x91\x35\x93\x05\xbc\x50\x8d\x2d\xbb\xf5\x04\xff\xde\x59\x74\x5a\x0d\x72\xa5\x57\xf4\xee\xbc\x2e\x81\xe4\x62\x5c\x2d\x20\xce\x63\x60\xef\x4f\x45\xe1\x38\xf6\xfb\x3e\xae\x3c\x9a\x87\xeb\x69\xda\xcc\x39\x2d\x65\xd2\x2d\xb7\x94\xde\xcc\xe9\x4c\x1b\x99\xb8\x23\xc9\x5d\x7c\x9c\x18\xab\x72\x3c\x9b\x17\xb5\xf6\xc4\x58\xa4\xb2\x03\xf8\x28\x7d\x89\xd8\x22\x21\x64\x0e\xaa\x16\x9c\x0f\xf7\x7a\xf8\xc7\x37\x3f\x91\xe2\xed\x23\xfa\x53\xa3\x60\x51\x50\xf7\x94\x73\x42\x20\x9e\x1c\xe2\xe7\xd9\x8f\xcf\x7e\xbc\x23\x5e\x77\xda\xcf\x23\xf9\xc1\xc2\x5a\x9e\xf7\x3f\x27\xfa\x71\x56\xfe\x2e\xbd\xdd\xe8\xfa\xf2\x68\x7e\x70\x41\x5f\x7c\x9f\xa0\xfc\x0f\xf9\xc4\x21\x7e\x26\x7d\x9c\xde\xe9\x5f\x05\x76\x6c\x8f\xe5\x03\xbc\x10\xfb\x0a\x3d\xe5\xe7\xf3\xef\x91\xf1\x8f\xa8\x68\xf8\xbd\x5c\xf6\xbf\x1f\x95\x28\xbb\xb5\x78\xf7\x85\xa0\xbb\x73\xa5\xb7\xfc\xbb\x59\x56\xba\xcb\xa7\xeb\x6b\x6b\xdf\xfa\x4f\xa2\x09\x15\x30\xaa\x2a\xf1\x9c\x8c\x53\x2c\x22\x49\x89\x97\x09\x24\x93\x38\xc7\xe1\x24\x89\xcb\x0a\x62\x81\xca\xd1\x12\x49\x51\xa4\x02\x11\x21\xd3\xb2\xc4\x31\x32\xab\x50\x0a\x47\xd1\x84\x77\xe4\xf6\xa1\x97\xe9\xf8\xd6\x7f\xf4\xb5\xf5\x1f\xc3\x01\x26\xfc\x71\x0a\xbb\xab\x47\xe5\x66\x4f\x67\xef\xb4\x31\xdf\xfa\x2f\x19\x98\x7c\x9f\x8e\xb8\x36\x10\xaf\xb5\x5a\xf5\xad\x0e\x6a\x6f\xf1\x21\xd7\x22\xf9\xe5\x30\x0b\xea\x16\xcf\x98\x32\x5b\x1e\x5b\xce\x80\x18\xc6\x57\x7c\xa1\x5c\x55\xf8\x51\xab\x25\x66\xad\x6e\xdd\x8b\x69\xd1\x73\x0c\xd7\x07\xf9\xe8\x39\xab\xa7\xa9\x3d\x3f\xd5\x94\xd1\x59\x42\x73\xcc\xae\x8d\x7a\x43\x59\xc3\x32\x3b\x2b\x15\x59\xaa\x1b\xcb\x35\x47\x02\x61\xe2\x73\x99\x6d\x13\xa9\xf7\xb8\x31\x6a\x21\xc2\x96\xdf\x27\xc5\x22\x8c\xd5\xb8\x41\xab\x21\x19\x65\xda\xa8\x32\xb1\x94\xdc\x28\xd2\xc3\xac\xd5\xae\xce\x56\xb3\x54\xaa\x27\x95\x47\xc2\xf2\x96\x35\x5d\x50\x7e\x42\x94\xf9\xf0\x3e\xe2\x17\x96\xf7\x9f\xe1\xeb\x2d\xdf\xd8\x7b\xf3\x9f\x32\x6d\x65\x81\x20\x1c\xaf\x77\xb4\x20\xee\x2b\xeb\xad\xe7\xe1\x4f\x46\xc2\xef\xc6\x47\x5f\xbc\xf6\x2e\xdd\x9b\xef\xb2\x63\x7b\xd8\x3c\xe0\x2f\x0a\x67\x6a\x33\xd7\xe2\xc5\xb3\xf1\x9f\xea\x76\x28\xfe\xe0\x7a\xe9\x4b\xe4\x2b\xe7\xe5\xf3\x75\xe8\xbb\x2d\x9f\x5a\x1e\x88\x76\xbf\x7f\x89\xfc\x3b\xa8\x13\xff\xca\xf5\x81\xfb\x89\x1f\xfc\xd9\xbf\x6e\xfd\x76\xe0\xef\xbc\x3e\x5d\xce\x69\xa3\xf8\x08\x7f\x4e\x79\xb6\x7e\xfc\x89\x3e\xea\x1e\xfc\xdb\x9c\xb6\xdd\x52\xe3\x33\x5d\x5a\xe4\x5b\xb9\x12\x99\x33\xd9\xb9\x89\xbf\x2f\x06\x43\xca\xa8\x57\x93\x70\x58\xa7\xdf\x1d\xa9\xdb\x29\xa6\xdb\xb5\x16\x0b\x57\xef\x65\x79\xb9\xb2\xe8\xcc\x3a\xd5\x2a\xcd\x9b\xec\xb8\x95\xb4\xa8\xd6\xaa\xf8\x3e\x2e\xea\x4e\x2f\x61\xa5\xcd\x66\xcb\xb0\x99\x6a\x52\xf8\xdc\x9c\x16\xe7\x65\x1c\x50\x2c\x64\x08\x99\x23\x38\x92\x00\x08\x71\x3c\xaf\xe0\xb2\x2c\x2b\x3c\x21\x73\x80\x26\x68\x84\x20\x0b\x08\x1a\x67\x09\x9c\x60\x70\x92\x00\x12\x09\x09\x8a\xe7\x69\xc4\x49\xde\x63\x97\xc0\x23\xc7\x00\x7c\x39\x2d\x79\x2d\xa7\xe5\x28\x06\x84\x3f\x28\x72\x77\xf5\xa8\x61\xe1\x25\x8a\x1d\xf9\x72\xda\xa0\x1d\xc4\x03\x3a\x78\x77\x1d\x20\x7a\x4e\xe6\xab\x23\x79\xf8\xf7\xf4\x56\x13\x30\x33\x98\xea\xad\x12\x2f\x52\x24\x9b\xed\xa4\xe4\xcc\x54\x6d\x59\xe6\x0a\xd4\xcb\x6f\xa5\x9c\x93\x18\xc7\x89\x81\x06\xb5\x62\x35\x93\xac\x25\xd3\xd5\x62\xa6\x44\xce\x86\x75\xb9\x51\x9e\xcd\x90\x68\x97\xc4\xf9\x22\x1f\x9b\xb0\x59\x4a\x8a\xf1\x29\x0b\xaf\x91\xce\x72\x2c\x6b\xf6\x2d\x39\xab\x5f\x3e\xe1\x79\x9d\x6f\xd0\xbd\xeb\xf0\x40\x1d\x3b\xe4\x73\x25\xaf\x7a\x1e\xfe\xf3\x75\xad\x2b\xf8\x4f\x7c\xe6\xa7\xe7\x0d\x2e\xbe\x5b\xf2\x9a\x2f\x9a\x77\xfd\x79\xae\xa6\xe2\xf3\xd7\x77\xdb\x12\x3b\xb6\xb7\x71\xf7\x24\x47\xf7\x7d\x2e\xc7\x1f\xf1\x31\xfc\xfe\x9a\xce\x3d\xf8\xb7\xf1\x27\x67\xa2\xf4\x38\xd7\x24\xf1\xc6\x50\xb5\x07\x72\x6b\x89\x0c\xbe\x3d\x1f\x66\x5a\x59\x96\xc3\xc7\x78\xbe\x9b\x81\xe9\xf8\x4c\x58\x09\x72\x49\x2c\xf6\x84\xa5\x4c\xa2\x59\x29\xb7\x2a\x32\xb3\x29\x55\x5f\xe2\x75\x86\xb3\x18\xd5\x1e\x0e\x16\x2c\xde\x5e\xd4\x32\x88\x4c\xf4\xd6\x89\xe5\xe7\xc6\x1f\x96\x25\x19\x15\x97\x38\x86\x57\x10\xae\xb2\x14\xa4\x91\xc2\xaa\x9c\xc2\xd0\x04\xcf\x53\x3c\x41\x72\x48\xc2\x55\x9c\x22\x80\x4a\xaa\x32\x21\x49\x32\x45\x72\x38\x47\xa9\x04\x90\x39\xdc\x7b\xde\x97\xf7\x14\x85\xc8\x07\x06\xef\x8b\x3f\x1c\x15\x5e\x53\xd9\x5d\x3d\x6a\x4f\xf3\x74\xf6\xce\x35\xf4\x3d\xf1\xe7\xce\x7d\xc1\x47\xea\xd0\x07\x9b\x71\x3f\x99\x3d\xbd\xd5\xe4\x30\x5e\x17\xe6\x46\x5e\xe6\x9d\xda\x2c\xad\xc5\xca\xa3\x96\x94\xaf\xbc\x53\xa6\x51\xab\x76\x9b\x68\xb1\x4e\xa8\x0b\xbc\x20\x18\x33\xa9\x93\x66\xd6\x15\x69\x5a\xc3\xe3\x35\xc6\x64\xc7\x96\x3e\xae\x8d\xb9\x32\xd5\x32\x6b\xf1\x74\x56\x68\x54\xe3\x14\x51\x2a\xb7\xe5\xd4\xbb\x52\xbd\xa9\x66\x72\x77\xfc\xb9\x37\x2f\x7e\x76\xfc\x79\x10\xff\x13\xe3\xcf\x27\xee\xf3\x79\xa4\xdc\x19\x7f\xbe\xd2\x3e\xe9\xd5\xf8\x13\xdd\x96\x9e\x13\x7f\x22\xe0\x7f\x30\xfe\x94\x8b\xa9\x6c\x82\x69\x4e\xdf\x09\x90\x36\x61\x92\x62\x6a\x2d\xdb\x7c\xab\xe8\x7a\x2b\x15\x1f\xd4\x98\xb7\x6c\x2e\xf6\x56\xb5\x13\xed\xa9\x23\x4b\x56\x96\x9f\x1b\x99\x6a\x2a\x33\x1b\xce\xe1\x3c\xdf\x4b\x4b\x4b\x76\xd0\x1e\x88\x62\x57\x8b\x97\x84\xcc\xb0\x8b\xd3\xbd\x65\xa7\x04\x3e\x7b\xfd\xa3\xb2\x94\xac\xd0\x14\x87\xe3\x0a\x4d\xb2\x32\xce\x28\xaa\x4a\xd2\xb2\x4c\xb1\x1c\x29\x21\x8e\x03\x32\xa1\x30\x2c\x2e\x03\x40\x03\x48\x33\x32\x64\x55\x9e\x06\x2c\xcd\x29\x32\x4b\x01\x5a\xf1\xe2\x0f\xf9\xa4\xf8\x73\xb5\xa7\x8b\xa3\x71\xe6\xc2\x63\xc1\x69\x9c\x39\x3c\x16\x7c\xdb\x8c\xfc\x68\xfc\xb9\xd0\xd3\xf5\xe9\xfb\xa0\x81\xf5\x8f\x2f\xfe\x94\xb3\xf9\xba\x91\xac\x8e\xf9\xa6\x35\x23\xe6\xc3\xc9\x62\xd5\x1b\xa6\x67\xcc\x7b\xae\x3a\x91\x2b\x8d\x29\xb7\x30\x28\x3b\x91\xa0\x6a\x90\x2a\x36\x27\x30\xd3\x4d\xc2\x51\xad\xd3\x48\x99\x55\x23\x9b\x12\x2c\xda\xc1\xcd\xdc\x52\x89\xd7\x6d\xa6\x91\xe3\x8a\x74\x0b\xa5\xb5\xb8\x54\xd5\xbe\x62\xfc\x89\xe4\xff\x9f\x88\x3f\xa4\x06\xf6\x29\xeb\x9f\x4f\x8e\x3f\x9f\x49\x5f\xa4\xf5\xcf\x3f\xe4\xff\x85\x27\xc5\x1f\x7f\xfd\xef\x1e\xfc\xdb\xf8\x43\x69\xd3\x7c\xb3\x94\x90\x40\x7d\x6e\x41\xa6\x8c\xde\x52\xe3\x22\xb4\xac\xa2\x91\x50\x96\x7c\x79\xb2\x8e\x75\xf4\x65\xb6\x30\x48\x59\xda\xaa\xae\x98\x8a\x56\x9a\xd5\x52\x4a\xb1\x3d\x48\x34\xb5\x66\x62\x31\x26\xeb\xda\x24\x8e\xa7\xf2\xef\xd3\xe2\x64\xf9\x6e\xb4\x28\x28\xa4\x9c\xc4\x27\xc7\x1f\x99\x27\x55\x0e\x67\x18\x56\x25\x59\x45\x65\x71\x48\xf0\x48\xc6\x15\xc4\x33\xaa\x4a\x92\x1c\x60\x28\x0a\xca\x1c\xc1\x41\x4a\x46\x10\xc8\x12\x23\x23\x09\x48\x32\x92\x19\x55\x55\x71\x9a\x3b\x3c\x4b\xff\x19\xf5\xb7\x1b\xe2\x0f\x71\x61\x4f\x79\x77\xf5\xe8\xe0\xc9\xa3\xf5\xb7\xab\xf1\xa7\x4c\x24\xde\x84\x32\x45\x77\xe3\x49\xd2\xc9\xb4\x52\x65\x50\x23\x05\xbc\x88\x46\x15\x2e\x57\x63\x26\x25\x20\xf0\xa8\xad\x2b\xeb\xac\xe3\xed\x2b\x3c\x50\x7f\x0b\xac\x7f\x7c\xf5\xb7\x34\x65\xb0\xa3\x84\x30\xa3\xe1\x6c\x51\x27\x94\xb7\x4c\xc3\xe9\xca\x6c\x41\x80\xec\xb4\xde\xd4\xf5\x32\x95\x5f\xe7\x73\xd2\x6c\x6c\x27\xb5\x85\x3c\x4a\x27\x08\x45\x1a\xc8\x96\xc9\x3b\xf2\x22\xd1\xcb\xa8\xcb\x59\xa3\x15\xd3\x47\x0b\x2e\x33\xe6\x7a\x2a\x64\xc8\x51\xb7\x32\xaa\x76\xbf\x62\xfd\xed\xe1\xf8\xf3\x20\xfe\x27\xc6\x9f\x4f\xec\x13\xf5\x48\xb9\x33\xfe\x7c\xa5\x3e\xdb\xab\xf1\xe7\x13\xeb\x5f\xc2\x93\xea\x6f\x0f\xc6\x1f\x49\xef\xcc\xab\xd9\x84\x65\xcc\x66\x7c\xa1\x47\x72\x4a\x19\x0c\xde\x6d\x3b\x6e\xcd\x8d\x5c\x3d\x9f\x65\x35\x2b\x6b\x1a\xf3\x19\x5c\x96\x13\xfc\xba\xda\x2d\xf4\xc0\x3c\xb5\x9e\x0f\x09\xb0\xe6\x72\x23\xe5\x2d\x31\x2d\x75\x98\x7c\xfd\x6d\x89\xa4\x95\xc1\x5b\x16\xaa\x69\xb1\x5a\xfc\xd3\x7b\x9a\x64\xa8\xc8\x08\xa7\x55\x19\x87\x0a\xad\x30\x2a\xc2\x71\x5e\xe2\x24\x5c\x41\x92\x8c\x2b\xa4\xa2\x2a\x24\x81\x20\x45\x48\x1c\x92\x20\x89\x78\x04\x19\x4e\x26\x58\x8a\x41\x14\xc0\xd5\x17\xef\x55\x83\x8f\x3c\x4c\xe8\x9e\xfa\x1b\xcf\xb3\x97\xde\x10\xe3\x5e\x3c\x3a\xac\xe8\x69\xec\x9d\xa7\x0a\x6e\xab\xbe\x79\x5d\x89\x91\xa2\x49\x27\xb0\xcb\xec\x69\xf4\x1e\x7f\x55\x28\x55\xeb\xef\x8b\xa9\x18\x4f\x08\x9d\x85\x0d\x2a\xda\x38\xf3\xd6\x4c\x49\xaa\xd0\x75\xc8\xb2\xa0\x69\xdd\x4a\xab\xa1\xe0\xd3\x61\x4b\xce\xc1\x16\x69\x24\xc5\xb7\x61\xb9\x57\x9c\x14\x52\xbd\xe2\x28\x25\x0e\x34\x4a\x31\xe6\xad\xea\x0a\x25\x7b\xc2\xb2\x91\x6f\x56\xe0\x44\xb1\x97\x37\xad\x66\xd2\x7e\x35\x0f\x8b\x26\x82\xef\xbd\x35\x77\x46\x5f\xd7\x9b\x4f\x0e\xf2\x0d\xf9\x5c\xf1\xe6\xcf\xc3\x1f\xad\x9a\x76\xe8\xd2\xf1\x77\xb5\xdc\xe9\xad\xcf\x76\x75\x9e\x7e\x2e\x7b\xc0\x67\xe3\xbf\xa3\xab\x54\x10\xbe\x6e\x34\xbd\x56\xad\x8b\x22\xab\x87\xab\x75\x4f\x9c\xab\x7b\xf0\x6f\xa3\x95\x00\xe2\x85\x72\x6c\x54\x15\xb3\x71\x14\x7b\x6f\xc6\x12\x5d\x95\xaf\xb6\x1c\x2e\xae\x93\x32\x95\x48\xc4\x35\xbe\x55\x22\xeb\xe3\x52\x6b\x69\x4c\x3b\xa8\x59\x6c\xc4\x8a\xf4\x68\x2d\xdb\xad\xd1\xba\xda\xac\xa7\x93\x03\xa2\x4d\xb7\x92\x29\xaa\x34\x4a\xc6\x8b\xd3\x2a\x3f\x53\x88\xf7\xcf\x5e\x2d\x49\x0a\xc5\x31\x8a\xa4\x28\x38\xa1\x50\x0c\xce\x01\x96\x61\x81\x4c\x41\x1a\xb2\x88\x57\x18\xc4\x31\xb4\x0c\x09\x5e\x96\x28\x80\x18\x42\x61\x21\x74\x97\x54\x2a\x42\xb4\x44\x32\x0a\xf2\xa2\x15\xf1\xa4\x13\x98\xd7\xa2\x15\x8b\xe3\x38\x15\xfe\xfe\xa6\xcd\xd5\x43\xbc\xda\x1e\x89\x7f\xf4\x04\xe6\xd5\x78\x15\xa9\xfa\x46\x9e\x8b\x57\xe9\x3d\xfe\x6a\x9c\x1f\x8d\xf3\x6d\x62\x46\x2e\xd8\xaa\xba\xe6\x2a\x45\x34\x12\x25\xd0\x68\x64\x69\x7d\x35\x1b\x65\xf1\xb8\xa9\x75\xac\xb2\xc3\x6a\x65\xc0\x10\x55\x69\x34\x20\x94\x7a\xa3\xa9\xa2\xa4\xb9\x90\xf1\x8a\x00\xd5\x41\xb2\xb3\x72\x06\x2d\xc1\xb0\x0b\xf3\xa1\x11\x1f\xaf\x87\x71\xe1\xa6\xd5\xcf\xdd\xf1\x2a\xca\x29\xba\x67\xc6\xab\x07\xf1\x3f\x31\x5e\x3d\xe5\x14\xc2\xe9\xe7\x66\x1f\xf8\xd9\xa7\x20\x04\xe1\xeb\xee\x7e\x5d\xdd\x5d\x8a\x20\xab\x67\xc6\xab\x47\xe7\xea\x1e\xfc\xdb\x78\x95\x21\xea\xdd\xa9\x04\x2d\xf4\xe6\xc4\xdf\x0a\x4b\x6e\xc5\x54\x6b\x8b\x56\xa9\x38\x1c\x17\xd2\xb3\xea\xb0\x9a\xd6\xe3\xc8\x66\xc8\xb9\xc0\x76\xac\x5e\x7c\x5e\xcf\xf4\x40\xae\x54\xe3\xa9\xb2\xce\xbf\x57\xb9\xf8\x34\x26\x96\xd4\x34\x91\x6a\x26\xda\xcb\x39\x53\x6e\xa6\xa5\x7c\x51\xfc\xec\xd5\x15\x07\x00\xe0\x09\x99\xe4\x18\x8a\x54\x54\x96\x94\x71\x40\x43\x1a\x02\x85\x65\x25\x0e\x27\x14\x55\xc5\x69\x85\x52\x69\x5c\x95\x19\x05\xe0\x1c\x60\x20\x64\x69\x19\x87\x0c\xc0\x79\x95\x87\x5e\xbc\x22\x9f\x74\x62\xe4\x86\x78\x45\x84\xbe\xa3\x79\x77\xf1\xe8\xb1\x2b\x8f\x9e\x17\xf9\xc4\x68\xe5\x3b\xdf\x51\x31\x34\x36\x5d\x18\xe4\x34\x7c\xc5\x0e\xa7\xc2\x12\x88\x4b\x26\x43\x74\x52\xcc\xba\x96\x1d\xab\xb9\xec\x32\xa5\xae\x70\xbe\x34\xd7\x69\xc9\x29\xe7\x84\x14\x5a\xa6\x84\x92\x5a\x86\x42\x9c\x4b\x55\x7b\x06\x3d\x25\x05\x5a\x23\x47\x4c\x32\x93\xd4\x35\xb5\x59\x6a\x26\x01\xa3\xc9\x1f\x12\xad\x22\x9c\x41\x78\xb8\x57\xe1\x89\xf8\x9f\x18\xad\x1e\xed\x2f\x7e\x34\x5a\x3d\x05\xff\x03\xd1\xea\x2b\xed\x95\x5d\x8b\x56\x51\x64\xf5\xcc\x68\x15\x05\xff\x83\xd1\x2a\xd6\x4e\xda\xdd\xb9\x38\x4e\x36\x32\xf3\xf2\x28\x99\x6c\x36\x92\xa6\xda\x93\x3b\x56\x4e\xd4\x7b\xdc\x68\x28\xb4\xde\x32\x0d\x9c\x60\x0a\xc6\x1c\xa7\x46\x42\x8b\x15\x9a\x02\xe0\x68\x53\xc8\x2c\x5b\xf1\x71\x67\x3c\x91\x93\xe3\x24\x6a\x98\x45\xb9\x9c\x8f\xf3\x55\x50\xad\x74\x66\xf1\x4f\xee\xc5\x23\x09\x44\x49\x10\xa8\x04\xe0\x24\x06\x42\x82\x22\x70\x89\xe2\x59\x8a\x66\x20\x90\x70\x1e\xe7\x71\x44\x72\x24\x8b\x18\x46\x22\x29\x9e\xc6\x49\x5c\xa1\x90\xa2\x30\xb8\x82\xab\x38\xcd\xe2\x5e\xb4\xa2\x9e\x14\xad\xae\xed\x45\xb1\x38\x4e\x33\xe1\x6f\x03\xdd\x5d\x3d\x7a\xb8\xd7\xa3\xf1\xea\xc2\x5e\xd4\xb3\xab\x81\xbe\x78\x55\xcc\x8d\x17\x31\x63\x90\xa2\xab\x3d\x43\x53\xb2\xb3\x78\x27\x59\x57\x06\xa2\xa3\x59\xb0\x61\xd5\xea\xcb\x96\x45\x2b\x6f\x71\xab\x94\x20\x38\xa4\x66\x8a\xe6\xaa\x5b\x82\x31\x62\xce\x3b\x75\x51\x59\x35\x63\x83\x74\x87\xc9\xd5\xda\xec\x52\x48\x91\x52\x79\x2a\x70\xd6\x6a\xb5\x12\xc4\xaf\x18\xaf\x22\x3d\x23\xe5\x89\xf8\x23\x3d\x23\xe5\x63\xe2\x55\x48\xfc\xfc\xb4\x78\x75\xef\x79\x1c\x41\xf8\xba\xbd\xed\x67\xe3\xd5\x3f\x14\x2f\x84\x0f\x98\xab\x7b\xf0\x6f\xe3\xd5\x72\x0c\xdf\x98\xb6\xd8\x31\xe2\xe3\x76\x1c\xd7\xcd\x94\x5c\xca\x11\x62\x9d\x48\x38\xd3\xb2\x93\x2a\xc4\xdb\x0b\x83\xe4\xd2\x36\x5e\x90\x56\x34\x27\xaf\x87\x29\x0d\x58\x2c\x64\x09\x90\xad\x91\xa9\x06\x23\xf6\x54\xd3\x48\x49\x0b\x41\xe8\x28\x36\x33\x4a\xae\x17\x99\x8c\x28\x54\x3f\x37\x5e\x31\x0c\xc3\xd0\x0c\x64\x10\x54\x10\x81\x73\x84\x4c\xb3\x1c\x4e\xb3\x80\x60\x58\x85\x47\x14\x45\x93\x08\x21\x9a\xe5\x80\x0c\x79\x48\x73\x10\x92\x80\x47\x12\xae\x22\x8e\xa4\x68\x5a\x55\x5e\x76\x8f\xb9\x8d\xfe\x30\xdf\xdd\x53\x72\x2f\x84\x29\xc0\xd0\x97\xde\xd2\x4e\x1f\x36\xc0\xbc\xc7\x3d\x6e\x63\x54\x81\xcb\x54\x17\xd5\x91\x94\x27\x32\x02\xd9\x6e\x0d\x6b\x56\x7e\x3c\xec\xe0\xb8\x9a\xe6\xec\x42\x96\x1d\xe3\x62\x6d\x99\x6b\xbf\x09\x1d\x52\xd8\xc7\x28\x4f\x99\x02\x13\x7e\xe2\x43\x22\xf4\x7f\xe5\xfd\xf0\x5a\x8b\x65\x8a\xdf\xd8\x98\x18\x57\x92\x1d\x44\x90\x4d\x0a\xf1\x09\xa2\xbe\x9a\xc6\x0b\xbd\xda\x0a\x58\xb9\xf7\x7a\xaa\x90\xc3\x57\xc9\x24\x3e\xcf\xa7\xa7\xe3\x99\xa4\x1a\xc9\x46\xac\xd3\xc9\xce\x98\xa6\x9e\x8c\xbf\x8f\x53\x2b\x27\x96\x2e\xc7\x3a\xb3\x94\x59\xad\x28\x56\xa7\xc1\x4e\x81\x59\xe8\x65\x33\xb3\x46\xb1\x72\x43\x5c\x3a\x52\xe8\xe3\xb8\xe4\xe3\xf9\xe0\x97\xfd\xb9\xa9\xfe\x16\xc7\x0b\x78\x2e\xbd\x76\x06\xcb\x12\x30\xba\x38\x5c\x4f\x4d\xc0\x97\x32\xab\x45\x21\xb1\x2e\xd3\x4e\x5c\x94\x13\x1e\x8f\xa4\xe6\x58\xe5\x49\xf7\x8d\x2a\x1e\xee\x6f\x9e\x25\xe2\x8a\xad\x3f\x80\xbf\x64\xad\x1b\xd5\x07\xf0\x0b\xc2\x3f\xd7\xa7\x7c\xd6\xef\xc6\xa3\xcb\xa2\x3c\xe9\x5d\x64\xf3\x9a\x2c\x1e\x9d\x8b\x8d\x2e\xc4\xe4\x00\xbc\xbb\x64\xf1\xdf\x4e\x15\x90\x8e\x03\xca\x99\x45\xd5\x19\xd9\xb0\x5a\x27\x9a\xb2\x02\xd7\x32\x3e\xa8\xaf\x95\x62\x75\xc9\x17\xf4\xc1\xac\x37\x1b\x93\x74\x15\x7f\x33\xc0\x3a\x3f\x37\xb2\xda\x52\xa6\x07\xb2\xa4\x0e\x86\x0b\x83\x19\x40\x31\x49\x42\x80\xc7\x18\x05\x26\x88\x7a\x9c\x19\xbd\x27\x3f\x79\x9d\x20\x01\x95\x23\x38\x92\xa3\x64\x9a\x41\x94\x84\x13\x94\x4a\x11\x2c\xad\x12\x14\x43\x73\x38\x94\xa0\xa4\xaa\x00\x22\x52\xe2\x25\xc8\x00\x09\x27\x39\x9e\x25\x69\x16\xd1\x2c\x42\x92\x4c\xe0\x9e\xdf\x25\x1e\xf3\xbb\xc4\x75\xbf\xcb\x52\x97\x1c\xaf\x77\xd5\xff\x58\xdb\x47\x3d\xef\x85\xd5\x81\xf7\x89\xd0\xf9\x14\xea\x79\xd5\x49\xaa\xfe\xde\x43\x03\xc0\xbe\x3b\x1c\x61\x16\x95\x19\xa2\x62\x6f\xab\x89\xfd\x36\xca\xc4\x95\x74\x47\xe5\xe3\xd9\x78\xad\xab\xb6\x7a\x64\xb2\xda\x20\xe1\x72\xd9\x9b\xd0\x85\x99\x96\x4d\xf3\xb9\x99\xb1\x28\x8e\x6b\xa0\x91\x87\x2b\xd9\xcc\x55\x93\xf3\x59\x5a\x4e\xd4\xe5\xe2\xd7\xf2\xbc\x8f\x7a\xbe\x47\xad\xbd\xb8\x2c\x8c\xcd\x67\x7a\xde\x4f\x3c\xa1\x78\xb5\x42\xf3\x89\x9e\x4f\x78\x92\xe7\xe5\xa8\xc3\xfd\x21\xd5\xcd\x8b\x9e\xb7\x43\xaf\x9a\x36\xd1\x31\x15\xc4\xb1\x6a\x69\x96\xcc\xc0\xc9\xbc\xb2\xe0\x7a\x6c\x85\x8e\x2f\x3b\x35\x83\x7c\xab\xd6\x85\x66\x3b\x03\xda\xca\x12\x17\x79\xc2\x2e\xa6\x7b\xb1\x3a\x63\x26\xe2\x8b\x3a\x9c\x4a\xef\xb9\x91\xd2\x5c\x8f\xed\x4e\x3e\xd1\x14\xd8\xd9\x60\x22\x8c\x26\x9f\x7d\x5a\x85\x90\x08\xc4\x11\x8a\x04\xa5\x8d\xd7\x95\x08\x16\xe2\x32\x09\x28\x5c\x86\x2c\x50\x38\x28\xf3\x92\xcc\x02\x8e\x04\x2a\xaf\xd2\x90\x94\x14\x86\x47\x32\x24\x15\x8e\x53\x25\x1c\xc9\xb4\xec\xf9\x4d\xf2\x31\xcf\x7b\x75\x1b\x01\x30\x3c\x19\x7a\x48\x7f\x7f\xd5\xff\xf8\xee\x47\x3d\xef\x85\xe7\x4e\x79\x9f\x08\x75\x81\x10\xcf\x9b\xcc\xcd\x0d\xe0\x14\xd2\x85\x14\xd5\x5a\x2d\x1d\x5c\x49\x26\x5a\xa2\xca\x38\x12\x6d\x50\xd2\xba\x68\xa5\xb5\xc4\x34\x66\xb4\x7a\xc5\xf1\x4a\x76\x68\x4a\x2f\xa9\xc4\x78\xe5\x0c\x57\x4c\x51\xa1\x7b\x39\x4a\xa4\x92\x86\x6c\xab\x14\x23\x0a\x83\x78\xba\xde\xac\xd8\x13\x4e\xed\x26\xbf\x96\xe7\x7d\xd4\xf3\x3d\x6a\xed\x05\x7c\xc4\x08\x4f\xf4\xbc\x9f\x59\x8f\xfe\x08\xcf\x1b\xd5\xf3\x09\x4f\xf2\xbc\xac\x6f\x02\x8a\x77\xcb\xe2\xbf\x6b\x69\xaa\x48\xf5\x95\xbe\x42\x29\x59\x2e\x28\x99\xea\xd2\xa8\x65\x62\x56\x3b\xd6\x43\x69\x6e\x98\x5f\x99\xc2\x4c\x9d\xb6\xda\x8d\x9c\xdd\x29\x20\x94\x1d\x76\xf8\xa9\x2d\x75\x39\x34\xcc\xa0\x76\x1d\xc5\xcb\x02\xdd\x29\x64\x62\xe5\x81\x90\xad\xd6\x46\x46\x92\xcd\xbd\x65\x08\xe1\x93\x73\x5e\x04\x58\x09\x22\x9a\x26\x14\x88\x03\x9c\x86\x0a\x49\xa8\xb8\xc4\x43\xa8\xa8\x0a\xae\x32\x04\x89\x54\x92\x45\x12\xc5\x31\x12\xc0\x25\x9c\xa2\x64\xc0\x13\x24\x47\x32\x38\xa2\x68\x5a\x61\x3d\xcf\x4b\x3d\xe6\x79\xaf\x96\xc4\x01\x0b\x40\xb8\xe3\xf5\x2e\xfa\x5f\x52\xf0\xa8\xdf\x0d\xa6\x01\x27\x7e\x37\x42\x77\x66\x98\xdf\xed\x76\xd5\x75\xd9\x1a\x57\x06\xea\x48\x67\x0c\xab\x12\x33\x13\xea\x7c\x92\x1b\xd7\xe6\xc4\x58\x5d\x19\x14\x6e\xd2\xb3\x76\x8d\x5d\x83\xee\xb8\xc2\x4d\xcd\x74\x8c\xe9\xcc\x34\x0a\x0c\xf3\x89\x76\x69\xd9\x32\x2b\x2c\x60\x13\x2d\xb1\x82\x58\x3c\x8b\x3b\xa8\xbd\x68\xa0\xe1\x28\xf7\xb5\xfc\xee\xa3\x7e\xef\x51\x5b\xcf\x53\xb1\x52\xf7\x89\x7e\xf7\x33\xbb\x2c\x3f\xc2\xef\x46\xf5\x7b\xc2\x93\xfc\x2e\xbd\xbc\x8a\xe8\x92\xdf\x25\xd2\x19\x6e\x38\xa3\x87\x54\x87\xce\xce\xa7\xf0\xfd\x6d\x26\x4c\xd8\xe9\xba\x37\x92\x9c\xe9\x84\xeb\xa1\x52\xbe\x0c\x8d\x11\xe2\x9c\x76\x6e\xf8\x96\x87\xf1\xc5\xdc\x60\xcc\x72\xa9\xbb\xd6\x8c\xa1\x9c\x82\xc9\x18\x8f\x96\x46\x2d\x49\xce\xf9\x44\xa9\xd0\x31\x2c\x9c\x34\xe9\xc4\x27\xd7\x78\x65\x55\xe1\x38\xc0\x20\x85\xe6\x58\x99\x46\x0a\xc7\x29\x08\xe2\x48\xc2\x71\x0e\x70\x32\x54\x49\x4e\xc6\x59\x1a\x47\x2c\x4b\xe1\x08\xa7\x15\x44\xca\x04\x0b\x58\x06\xf1\x10\x21\x0e\x21\xcf\xef\xd2\x8f\xf9\xdd\x6b\x8f\x5a\x65\x01\xcb\xb3\xdc\x05\xc7\xcb\xb3\xfc\xcb\xf1\xcb\x58\x1e\xf5\xbc\xa9\xc0\x94\x9f\x78\xde\x08\x7d\x86\x61\x9e\xb7\x34\xae\x0e\x94\x2a\x5a\x17\xe5\x76\xaa\x5d\xe1\x94\x56\x6d\x94\x74\x52\x75\xca\xc9\x64\x13\xeb\xbc\x02\x2b\xa3\x1a\x13\x7b\x2b\xb0\x31\xa7\xf8\x9e\x6f\x9b\xcd\xa1\x94\x14\x3a\xb6\x5c\xeb\x66\x63\x43\x26\xa5\xbc\xb5\x52\x4d\x98\x7c\x57\xba\x76\x3b\x21\xd8\x19\x12\x6f\xcf\x87\xd9\xc2\xd7\xf2\xbc\x8f\x7a\xbe\x47\xad\x3d\xc7\x77\xb4\xe5\x33\x6b\x0d\x9f\xd8\x2f\xf8\x11\x9e\x37\xaa\xe7\x13\x9e\xe4\x79\xa3\x56\xfc\xb7\x9e\xf7\xbd\x37\xca\x76\x9a\x19\x7b\x98\x49\x0d\x5a\xc3\xb7\x4c\xab\xd9\x13\xd8\x5a\x73\x5e\xa8\xad\x05\x5b\x9f\xb4\x87\xb4\x88\x16\x8b\x75\xec\xcd\x6a\x14\xd7\xc6\x2c\x95\x25\x96\xcb\x14\x9b\x11\xdb\x89\x8a\x19\x1b\x74\x54\x50\x6b\xa5\x35\x8e\x6c\x17\x52\x9a\x56\x88\xf3\x7c\xca\x32\x9f\xf4\x64\xa6\xe3\x17\x40\x79\x2f\x48\xb6\x1d\xe8\xd8\xfe\xbf\xfb\xd3\x11\x5a\xef\x5e\xa4\x94\x28\x97\xea\x8d\x9a\x90\x2d\x5d\x7b\xe7\x93\x50\x68\x88\xb5\xed\x7b\x97\xca\xa5\x42\xd7\x0f\xf1\x37\x0c\xc3\x30\x21\x99\xf4\x41\x3b\x41\x88\x55\x6a\xd9\xa2\x50\xeb\x62\x79\xb1\x8b\x7d\xd7\x95\x13\x6a\x35\xd3\x9a\xf6\xc7\xba\xb6\x7b\xbb\x68\xe0\xfb\x93\xa8\x0e\x40\x3d\x47\xf9\x39\xc4\x57\xa9\xdf\xc5\x39\x97\x6d\x3b\xf0\xb5\x7f\x78\xc3\x75\xff\xf0\x5e\xeb\xbe\xff\x05\xd6\xfd\xa7\x70\x77\x8c\xf6\x1c\x73\x91\x08\xc3\x9a\xa5\x6c\xb5\x29\x62\xdf\x0f\xc3\x5f\xb1\xc3\xf8\xdd\xdf\xde\x0d\x77\x8a\xe6\x39\xd3\x7a\x37\xe3\x77\x4d\xea\xfe\x9d\xb7\xc7\xaf\x62\xbb\x7c\xf9\xc9\x9c\x9d\x47\x72\x89\xd3\x0b\x64\xdd\xcc\x79\xe8\x6b\xe8\xae\xbe\xe8\xed\xb9\xdc\x87\xa1\xb9\xc4\xff\x45\xd2\xae\x4a\xc0\x53\x69\x69\xed\x6a\xfb\x8e\x91\x6c\x29\x29\x76\xae\xf0\x90\xa8\x89\x42\x43\xf4\x86\x1e\x43\xc1\xca\xa5\xa0\x31\x34\xeb\xd9\x52\x1a\x93\x1c\x0b\x21\xbf\x75\x85\x53\xe3\xd9\xd8\xe3\xf4\x78\x70\x6e\xa3\x28\xc4\xae\xa5\x75\x7f\xfb\x4a\xe6\xc8\xe4\x1c\x40\xf8\x29\x39\x5a\x2b\x1c\xd3\xe3\x0d\x7e\xc5\xb6\x7f\xf4\x6d\x34\x9b\xa3\x89\x7c\x2a\x30\x69\xdd\x57\x11\xba\x8f\xc0\xa9\x69\x3b\x9a\x85\xec\xb3\x74\xfa\xa0\xdd\x46\xab\xef\x86\x1f\x58\x3b\x23\xd6\x44\xcc\x0f\x23\x5b\xc7\x4a\xe5\x86\x1b\xc3\xff\x38\x21\x7d\x00\xed\xc1\x13\x68\xde\x80\xb9\x8d\x58\xbf\xad\x6c\xee\x3a\x27\x4f\x7d\x32\x41\xd6\xb3\x48\x3b\x00\xbb\x8d\x40\x6f\xfc\x09\x99\x5b\xc1\x9e\xbf\x7a\x59\xc6\x06\x52\xb4\x07\x2c\x69\x0f\xe1\x36\xfa\xbd\xb1\x7b\x7d\x7d\xc5\xe0\x74\x6a\xe8\xb2\xe7\x9f\x4d\x4b\x09\x89\x9b\x7d\xb4\x31\x56\xf7\x7a\x04\x4a\xb7\x61\xdb\x23\x38\x00\xce\x4f\x36\x52\x55\x24\x07\x6d\xff\x34\x8c\xe8\xca\x2b\xf6\xcd\xbd\xf9\x5b\x18\xb1\xba\xf2\x24\x32\x75\xe5\x66\x02\x77\xbe\x60\x43\x5e\x04\xa2\xcd\x69\x7f\xfa\x2c\xba\xb7\xb0\xfc\xa4\x87\xe4\x0e\x91\x38\x39\xcf\x80\xb3\x7a\x1e\x03\x5b\x58\x21\x3a\x1d\x91\x05\x3f\x84\x73\x4c\x98\xd3\x8d\x56\x0e\xcc\x48\x3c\x6c\x89\x3f\xc0\x88\x2a\xfc\xcb\x82\xb6\xb7\xd6\xee\xc6\xce\xc7\x65\x7d\x0c\xce\x4f\xb2\xf7\x7b\xd0\xfb\x9d\xa5\xc8\x2f\xd7\x67\x91\x75\x02\xf3\x46\xf7\x7c\x86\x40\xc7\x9b\x12\xe7\x91\x69\x3d\xc0\x88\xae\x92\xd7\xd4\xcf\xb1\x94\x0d\x12\x09\xda\x77\xe6\x0b\x67\x09\x3e\x05\x16\xa0\x5c\x41\x01\x3a\xfd\x63\xaf\x12\x68\xaa\xea\x03\x41\xeb\x14\xd4\x4d\xc4\xb9\x23\x2f\x91\xe6\xd2\x8e\xac\xa7\x89\x2f\x00\xef\x1a\x91\x81\xe1\xb7\x50\xfa\x1c\x39\x1e\x41\xbb\x95\xca\xab\xd2\x7c\x0e\x6d\x37\xd1\x74\x99\x96\x1d\xc5\x86\x69\x8e\xe6\xd3\xc7\x28\x3a\x86\x75\xf3\x8c\x7a\x0b\x90\x10\xfa\xa6\x50\xb7\xfa\x8e\x3e\x46\x4f\xa1\x30\x08\xed\x36\xbb\xdd\x12\xf8\x8a\x05\x49\x7e\xc5\xb6\x2e\x5e\x36\x4c\x1b\x29\x7d\xe8\x84\x30\xf1\x04\xbf\xbd\x85\x73\x8d\xe2\x3b\xb3\xa3\x0d\xd4\xa7\x49\xf7\x0e\xc1\x5e\x95\x9b\x3e\x51\xd0\xaa\x1f\x48\x39\xec\xbe\x39\xe9\x43\x45\xb1\x90\x6d\x3f\x2a\xd0\xab\x08\x8e\x16\xce\xdb\xcb\x81\xa5\xaa\x37\xf0\x0e\xda\x1f\xd7\x83\x4b\xb0\xaf\x53\x7c\xc6\xca\x8e\x01\x6e\xb3\xf0\x0d\x3c\x67\x3d\x8d\x5e\x14\xb9\x08\xf5\x6a\xda\xbf\x19\x74\x85\xd0\x6d\x0e\xb5\x01\xb9\x57\xa2\x27\x51\x7b\x0e\xf4\xd5\xf4\xed\x56\x4d\xf6\x01\x7f\xb6\x32\x1c\x81\x8e\x92\x6f\x86\x83\x1b\x4f\x4d\x6b\xe3\xf8\x16\xc8\xb2\x75\x73\xf2\x7c\x41\x07\x31\x5c\x27\x3f\x70\xc3\xed\xcc\x6c\x5d\xcf\xed\x45\x8e\x08\xf2\xf7\xe1\xb8\xca\x89\x6f\xec\xed\x4c\x4c\x2d\xb4\xd0\xcd\xb9\xfd\x29\xdc\x9c\x43\x76\x95\xad\x73\x37\xdd\xce\xdf\xae\x88\xf2\x61\x3c\xed\x10\x5c\xe5\x23\xb4\xfc\x78\x0c\x7a\x1f\x6f\x3f\xc4\xb4\x83\xd0\xcf\x2e\x80\xef\x35\xf0\x63\xa0\xc7\x4b\xa8\x27\x59\xf8\x25\x14\xb7\xf0\x70\x65\x5d\x77\x11\xd9\xf3\xc2\xd7\x29\xe0\x9b\x68\xbf\x1e\xc4\xfc\x8b\xed\x8f\x50\x9b\x53\xf8\x91\x97\xfa\x6e\x12\xb7\x0f\xe4\xbb\x0a\x63\x5f\x32\xcd\x51\x64\x29\x5f\x80\x79\x35\x45\xf8\xfe\x5d\x41\x0e\xd4\x0d\x1b\xfb\xf9\x3f\xff\x83\xbd\xd8\xa6\xa1\xf8\xb6\x37\x5f\x7e\xfd\x72\xd0\xca\xf9\xf1\xe3\x15\x0b\x1f\x28\x9b\xca\x6d\x03\xbd\xcd\x91\xf0\xa1\x92\x39\xd7\x06\xce\x4d\xe8\x8f\x86\x5e\x26\xe0\x68\x68\x80\x84\x5d\x51\xdc\x55\x32\xec\x4f\x8c\x24\x6f\xee\x0c\xd0\x95\xbe\xea\xdb\xb7\x4b\xe5\x3f\xa7\x3f\x60\x8b\x16\x4b\x95\x6b\x62\x36\x5d\xda\xef\xc9\x61\x35\x31\x25\xd6\xc4\x52\x42\xac\x07\xb6\xa9\xdc\xab\xe5\x12\xd6\xac\x24\x37\x2a\x53\x13\xeb\x8d\x5a\x36\xd1\xd8\xfc\x94\x14\x0b\x62\x43\xc4\x12\x42\x3d\x21\x24\xc5\x0b\x1b\x9b\x9b\x75\xc7\xf1\xd7\x7e\xa0\x14\xf3\x3c\x61\x1c\xe3\xb9\xb2\x6b\x19\x46\xc9\xb1\x7c\x82\x65\xa3\xb3\xc2\xda\x26\xfa\x57\xb6\x78\x43\x25\xb1\x5d\xca\xfe\xe3\x72\xf0\xd3\x71\x4e\x0a\xbb\x2a\xc1\x65\x85\xb9\x4f\x02\xa7\x45\xa5\x7f\x50\x0c\x21\xc4\x1c\xcb\xe2\x4c\x19\xec\xb9\x4a\x11\x2c\x71\x7c\x05\x81\x84\xab\xc6\x49\x0d\xe9\x16\xed\xc0\xa0\xa2\x20\x05\x1b\xc3\xc9\x1c\x1a\xc6\xfa\x88\xd2\x6c\x0a\x13\x3b\xd9\x7a\xa3\xee\xd1\xec\x71\xf6\xfb\x08\xad\xfb\x0b\x68\xcc\x51\x7f\x03\x11\x61\xc9\x5a\xb9\xe2\x27\xfc\x70\x57\x60\xa4\xd7\x22\xf1\x9b\x3b\x3e\x88\xe0\x3c\xec\x3f\x76\x21\xd2\x1b\x1e\xc4\xfc\xdd\x95\xdb\xc5\xcf\x46\x48\xf2\x00\x5a\x50\x76\x90\x85\x2d\xa0\xb5\xd6\x27\xda\x77\x82\xa6\x7f\xec\x77\x4a\x5f\xaf\x43\x71\x91\x5e\x83\xf3\x5b\xa0\x13\x38\x48\xed\xe1\xf0\xc5\x6a\xda\xd7\x27\x1a\xb2\x9d\xbe\x01\x37\xff\xb8\x99\xf6\xcb\x2b\xf6\x82\xbf\xfc\xf8\xe3\x54\x57\x02\x80\xce\x29\xcb\x39\x49\x1f\x77\x7c\x8c\xd0\x7a\x33\xe3\x47\xf2\xdc\x17\x4c\x6c\x5d\x9b\x6c\x72\xfd\x1b\x04\xba\xbb\xe9\x8c\x34\x18\xea\xc7\x0d\xb2\xc4\x3c\x64\xd8\x26\x76\xdf\x32\x7c\x89\x74\x6d\xe0\x60\xfa\xc4\x41\x1a\xb2\x02\xb3\xf6\xf3\x27\xb6\x44\xd8\x52\x37\x0c\x6c\x36\x47\xd6\x1a\x93\xd6\x3b\xf8\xb6\x89\x39\x03\xe8\x60\xba\x8d\x2d\x07\xfb\x5f\x75\x1b\x73\x06\x08\x53\x75\xcb\x76\x30\xdd\x41\x63\x4c\x9f\xb8\xbf\xc8\xe6\x78\x6a\xda\xba\x83\x36\xb2\xbc\x81\xac\x23\xe1\x7a\xc0\xf7\x5d\x1a\x3f\x7e\x0b\x4c\xe3\xd9\x24\x73\x33\x85\x3b\xcf\x35\x9e\xaf\x90\xb2\x11\xe4\x46\xaa\xdf\x19\xfe\xc7\xb6\xd7\x71\x33\xc6\xd7\x44\x11\x32\xee\x3c\x32\x5f\x2a\xbe\x01\x63\x9b\x73\x4b\x8e\x06\x69\x97\x73\xba\x14\x7b\x65\xbe\xd0\xfb\xb7\xde\xb5\xe2\xf5\x42\xd4\xab\x05\x4c\x81\x0e\xdc\x44\x2d\x4c\x99\x8f\xa7\xae\x9c\x0d\xe4\x20\xd7\x2d\xfe\xdf\x00\x00\x00\xff\xff\x0a\xe9\xcf\xa4\xba\x2c\x01\x00") +var _pathed_paymentHorizonSql = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xe4\x7d\x79\x93\xa2\xc8\xf6\xe8\xff\xf3\x29\x88\x8e\x1b\x51\xdd\x61\xf5\x14\xc9\x4e\xcf\x9b\x5f\x04\x2a\xee\xfb\xae\x13\x13\x46\x02\x09\xa2\x28\x0a\xb8\xd5\x8d\xdf\x77\x7f\x21\xb8\xa2\x28\xa2\x55\x53\xf3\x9e\x31\xb7\x6f\x29\xc9\xd9\xf2\x6c\x79\xf2\x24\xfc\xfc\xf9\xdb\xcf\x9f\x58\xc5\xb4\x1d\xcd\x42\xf5\x6a\x01\x53\xa0\x03\x25\x68\x23\x4c\x99\x8f\xa7\xbf\xfd\xfc\xf9\xdb\xe6\x7a\x72\x3e\x9e\x22\x05\x53\x2d\x73\x7c\x18\xb0\x40\x96\xad\x9b\x13\x8c\xff\x9d\xf9\x1d\x1c\x8d\x92\xd6\xd8\x54\xeb\x6f\x6e\xf7\x0d\xf9\xad\x2e\x36\x30\xdb\x81\x0e\x1a\xa3\x89\xd3\x77\xf4\x31\x32\xe7\x0e\xf6\x27\x86\xff\xe1\x5e\x32\x4c\x79\x74\xfe\xab\x6c\xe8\x9b\xd1\x68\x22\x9b\x8a\x3e\xd1\xb0\x3f\xb1\x97\x66\x23\xc5\xbd\xfc\xb1\x03\x37\x51\xa0\xa5\xf4\x65\x73\xa2\x9a\xd6\x58\x9f\x68\x7d\xdb\xb1\xf4\x89\x66\x63\x7f\x62\xe6\x64\x0b\x63\x80\xe4\x51\x5f\x9d\x4f\x64\x47\x37\x27\x7d\xc9\x54\x74\xb4\xb9\xae\x42\xc3\x46\x27\x68\xc6\xfa\xa4\x3f\x46\xb6\x0d\x35\x77\xc0\x12\x5a\x13\x7d\xa2\xfd\xb1\xa5\x1d\x41\x4b\x1e\xf4\xa7\xd0\x19\x60\x7f\x62\xd3\xb9\x64\xe8\xf2\xeb\x86\x59\x19\x3a\xd0\x30\x37\xc3\x84\x42\x43\xac\x61\x0d\x21\x5e\x10\xb1\x6c\x0a\x13\x3b\xd9\x7a\xa3\x8e\x95\x4b\x85\xee\x76\xfc\xef\x03\xdd\x76\x4c\x6b\xdd\x77\x2c\xa8\x20\x1b\x4b\xd6\xca\x15\x2c\x51\x2e\xd5\x1b\x35\x21\x5b\x6a\x1c\xdd\x74\x3a\xb0\x2f\x9b\xf3\x89\x83\xac\x3e\xb4\x6d\xe4\xf4\x75\xa5\xaf\x8e\xd0\xfa\x8f\xcf\x40\x28\xbb\x7f\x7d\x06\xca\x8d\x5e\x7d\x1e\x83\x1e\xb6\xfb\xb9\xf3\x08\xdc\x28\xf2\x35\x64\x47\xa3\x0e\xc0\xdd\xe1\xd9\x52\x52\xec\x1c\x8d\xdc\x82\x75\xa9\xea\x23\x55\x45\xb2\x63\xf7\xa5\x75\xdf\xb4\x14\x64\xf5\x25\xd3\x1c\x5d\xbf\x51\x9f\x28\x68\xd5\x3f\x62\x6e\x62\x43\x57\xd1\xed\xbe\x39\xe9\xeb\xca\x3d\x77\x9b\x53\x64\xc1\xfd\xbd\xce\x7a\x8a\x1e\xb8\xfb\x40\xc9\x43\x54\xdc\x77\xaf\x81\x14\x0d\x59\xee\x8d\x36\x9a\xcd\xd1\x44\xbe\x8b\x85\xa3\xdb\xa7\x16\x5a\xe8\xe6\xdc\xde\xfe\xd6\x1f\x40\x7b\x10\x11\xd4\xe3\x10\xf4\xf1\xd4\xb4\x36\xe6\xb8\xf5\xa9\x51\xc1\x44\x95\xa5\x6c\x98\x36\x52\xfa\xd0\xb9\xe7\xfe\x9d\x32\x47\x50\xa5\xad\x5d\x46\x20\xfa\xf8\x4e\xa8\x28\x16\xb2\xed\xeb\xb7\x0f\x1c\x4b\x71\xe3\x4e\xdf\x30\xcd\xd1\x7c\x1a\x62\xf4\xf4\x16\x49\xde\x28\xa8\x5b\x77\x02\xde\x39\xdd\xd0\x37\x6c\xfc\x84\xaa\x22\x2b\xdc\xd0\x1d\xf8\x08\xb7\x6c\xc5\x1a\xee\x26\xd7\xb5\xde\x81\xe4\xd8\x15\xdf\xba\x63\xba\xb9\x61\xe0\xdc\x9c\x01\xfb\xc4\x01\x49\xeb\x9b\x6a\x34\xd8\x5b\x7a\x98\xc1\xa6\x47\x87\x79\x73\xa0\x6e\x3b\x7d\x67\xd5\x9f\xde\x06\xb9\x19\x69\x4e\xc3\x8e\x44\x61\x87\xed\x42\xc9\xf5\xc1\xd2\xce\xdc\x6f\x0e\xbb\xed\xc5\xa4\x75\xb8\xc9\xf4\x62\xe4\x46\xda\xb6\x3d\xbf\x85\x79\x3f\x58\x36\x15\x74\x67\x5e\xb0\x57\x83\x29\xb4\x1c\x5d\xd6\xa7\x70\x72\x35\x78\xdf\xba\xb5\x3f\xbd\x33\x37\xd9\x47\xb4\x7b\x29\xb8\x7c\xe3\xdd\xf8\x5d\xe1\x85\xc1\xe7\x0d\xfc\x70\xf8\xde\x64\x6e\x66\x72\xfb\xe7\x26\x3e\xec\x52\x3f\x57\x19\xfa\x21\x29\xd0\x4c\x6b\xda\x1f\xeb\xda\x36\x61\xb8\x42\x82\x6f\x64\x68\x1e\xef\xcf\xf7\xae\x41\x0e\xab\x9c\xde\xdd\x89\x72\xa1\x59\x2c\x61\xba\xe2\x61\x4e\x8a\x29\xa1\x59\x68\x84\x84\x1d\xa0\x74\x4f\x80\xbc\x9d\xee\xeb\x90\xdc\x6f\xe1\xd9\xdf\x45\xe9\xba\x58\x6d\x8a\xa5\x44\x04\x99\x6d\xf2\x6c\x1b\xcd\xee\xc6\x7c\x02\x24\xf4\xdd\x0a\x0a\x39\xf6\x90\xcd\x86\xe6\x30\xc0\xea\xef\xe1\xef\x32\x88\x70\xf7\x6e\xf3\xbe\x70\x83\xb7\x49\x5e\x68\xde\xb6\x1e\xe0\x1e\x5e\xbc\x5b\x42\x8e\xdd\xa6\x7f\xe1\xe9\xd9\xe5\x8b\x61\x28\xf2\xf9\x90\xeb\x83\x8f\x5c\xc2\x76\xa0\x90\x4e\xd7\xc4\xb4\xd0\xb8\x30\x78\xac\x6f\x56\x1c\xba\x8c\xbe\x4f\xe6\x63\x64\xe9\xf2\x5f\x7f\xff\x08\x71\x17\x5c\x45\xb8\xcb\x80\xb6\xf3\x1d\x4e\xd6\xc8\x70\x4b\x31\x21\xee\x50\x75\xeb\xe2\x2d\xa9\x66\x29\xd1\xc8\x96\x4b\x57\xf8\xe9\x43\x4d\x3b\x50\xf7\x8a\x9d\x11\x7a\x05\xc6\x8e\xbb\x07\x60\x6c\x78\x75\x6f\x3f\x10\xff\x8a\xdd\xc3\x88\xcb\x7a\x08\x08\x62\xa7\x21\x96\xea\x3e\x10\xc6\x54\xb3\x67\xc6\x4e\x17\x13\x19\xb1\x28\x9c\x61\xf8\xe3\x37\xaf\x0a\x57\x82\x63\xf4\x6b\xf7\x1b\xd6\x58\x4f\xd1\xaf\xed\x2d\x7f\x60\x75\x79\x80\xc6\xf0\x17\xf6\xf3\x0f\xac\xbc\x9c\x20\xeb\x17\xf6\xd3\x2d\xce\x25\x6a\xe2\x66\xbe\xb6\x90\x77\xf0\x7e\x3b\x81\x78\x7a\x71\x0b\x38\x51\x2e\x16\xc5\x52\xe3\x0a\x64\x6f\x00\x56\x2e\x9d\x02\xc0\xb2\x75\xec\x65\x57\x76\xdb\xfd\x66\xbb\x40\x5e\xfc\x98\x77\xec\x6f\x71\xee\x25\x74\x93\x9f\x13\x59\x96\xca\x0d\x9f\x3c\xb1\x76\xb6\x91\xd9\x93\x75\x5c\x7f\x3b\x41\x7f\x80\xe2\x23\xe4\x1e\xe6\xcf\x80\xb8\x02\xa8\x14\xde\xa6\x5a\xbd\x5a\xc0\xa6\x96\x29\x23\x65\x6e\x41\x03\x33\xe0\x44\x9b\x43\x0d\xb9\x62\x08\x59\x2f\x3c\x26\xf7\xb6\xa2\x6d\xc9\xdf\xe9\xea\x81\xfe\xdd\xdc\x5e\x92\xe5\x5e\xb3\x6f\xc2\xc7\x6a\x62\xa3\x59\x2b\xd5\x8f\x7e\xfb\x0d\xc3\x30\xac\x20\x94\xd2\x4d\x21\x2d\x62\x2e\xf7\xc5\x62\xd3\xf3\x77\xf5\x46\x2d\x9b\x68\xb8\x23\x84\x3a\xf6\x9f\xfe\x7f\xb0\xba\x58\x10\x13\x0d\xec\x3f\x60\xf3\xcd\x3f\x1b\x37\x0d\xf1\x31\xee\x6e\x81\x7f\x1a\x73\xc4\x25\xe6\xc2\x78\xaa\xc7\xf8\x0b\x81\x61\xcf\xe2\xfe\xa7\x48\x1c\x7e\xff\x0d\xc3\x12\x42\x5d\xc4\xda\x19\xb1\x84\xfd\x07\xfc\x05\xfe\x7e\xfb\x0f\xf8\x8b\xf8\xfb\x7f\xfe\x43\xb8\x7f\x13\x7f\x11\x7f\x63\x0d\xef\x22\x26\x16\xea\xe2\x46\x28\x62\x29\xf9\xe3\xa2\x64\x42\xc4\x81\x07\x25\x73\x1b\xc3\x47\x4b\xe6\xff\x44\x91\xcc\x79\x4c\xdd\xca\x61\x1f\x87\xc3\x09\xe2\x10\xb6\xcf\x20\xba\x14\x63\x58\x7d\x23\x2b\xec\xcf\x83\x07\x78\xf5\x7e\x6e\x74\x2b\x22\xf6\xe7\xb1\x45\xfc\xb8\x64\xb5\x4f\xa5\xd1\x0f\xd0\x47\xe2\xce\x8c\xc3\x53\x78\x31\x05\x7a\x94\xca\x4b\x40\x7d\x94\x9e\x18\xe4\x29\xb9\x07\x2d\x3b\xa7\xf6\x52\x9a\xf7\x30\xb5\x17\x80\xfa\xa9\x3d\x36\x92\xab\xd4\x6e\x22\x97\x82\x54\x38\x37\x9c\xbe\x03\x25\x03\xd9\x53\x28\x23\xec\x4f\xec\xe5\xe5\x8f\xd3\xab\x4b\xdd\x19\xf4\x4d\x5d\x39\xda\x4a\x3b\xe1\xf5\x38\xff\xdd\xb2\xe8\x1a\x58\x38\xf6\x3c\x5b\x3c\x5e\x7c\x7b\x1c\xe9\x0a\x26\xe9\x9a\x3e\x71\xdc\xc4\xa0\xd4\x2c\x14\x3c\x76\xe0\x78\x93\xc6\x63\xf2\x00\x5a\x50\x76\x90\x85\x2d\xa0\xb5\xd6\x27\x9a\x6f\xd8\x64\x3e\xde\xa7\xfc\x98\x3e\x71\x90\x86\x2c\xdf\x10\xd5\x80\x9a\x8d\xd9\x63\x68\x18\xe7\x68\x1c\x73\x6c\x9c\x23\xf9\x4e\xd0\xf4\x8f\xfd\xc8\xf3\x69\xf7\xaf\x1b\xa2\x8a\xc3\x5f\xed\xd8\x8b\xc4\x41\xab\x33\x81\x4c\xa7\x86\xee\xd6\xec\x31\x47\x1f\x23\xdb\x81\xe3\x29\xb6\x99\x33\xf7\x2b\xf6\x6e\x4e\xd0\x39\xa1\x41\xab\xa2\x5d\x3e\xba\x5d\x4e\x85\xa3\x79\xbf\xf8\x0a\x80\xba\x55\x43\xa1\xd6\xf0\x32\x3a\xe0\xfe\x90\x2d\x25\x6a\xa2\x9b\x7e\xc5\xbb\xdb\x9f\x4a\x65\xac\x98\x2d\xb5\x84\x42\x53\xdc\x7f\x17\x3a\x87\xef\x09\x21\x91\x11\x31\x70\x8b\x99\xc8\x62\xf7\x03\x3a\x53\xc5\x6d\xd1\x03\x9b\xa0\x95\xb3\x80\xc6\xf7\x97\x00\x8e\x5f\x7e\xfd\xb2\x90\x26\x1b\xd0\xb6\x7f\xf8\xa7\xcb\xdb\xab\xb8\xa0\x5b\x0c\xf5\xe3\xca\x44\x79\x6b\xe3\x87\x39\xf3\x2a\x3a\x7b\xbe\x2e\x5b\xc6\xa1\x56\x77\x99\xcc\x8b\xc3\x65\x53\xb9\x34\x1c\x10\x97\x87\x7b\xe5\xbf\x0b\x37\xd0\xcc\x35\x0b\xbb\x5c\x5e\x78\x92\xda\x1e\xc3\xfc\x34\xa5\xbd\xc6\x08\x56\x6e\x97\xc4\x24\x16\xef\xde\xe0\xc8\xab\xd0\x5d\x67\x68\x0f\xcb\x77\xf9\x77\x5d\x09\xa2\x6d\x57\xf3\x79\x54\xeb\xb6\x70\xb6\x6a\xe7\xb3\x99\x7e\x90\xa7\x3f\x2f\x71\x05\x8d\xfc\xe6\x6e\x7c\x7c\x0b\xd0\x66\x57\x8f\x2f\x5f\x52\x90\x03\x75\xc3\xc6\x86\xb6\x39\x91\x82\x95\x6d\x57\x28\x7b\x54\x0e\x5b\x38\x5b\x39\xec\xf6\xad\x03\x68\x3b\xda\x4c\x0e\x65\x85\x97\xf6\xb1\x2f\xdf\xb8\x15\xcb\x51\x65\xd4\x9d\x88\x3d\x1d\x3b\x2f\x87\xfb\x30\x1c\x26\x22\xdc\xf8\xfd\x66\xb2\x2f\x30\x99\x73\xe7\x10\x9b\xfc\xf7\x58\x08\x3a\x37\x6f\xf2\xc6\xce\xa7\x4a\xe8\xb1\x7b\xd5\xd9\x7e\xf5\xed\xb3\x9f\xf1\x02\xce\xf2\x01\x07\x1a\x7d\xd9\xd4\x27\xf6\x65\x1d\x54\x11\xea\x4f\x4d\xd3\xb8\x7c\xd5\xdd\xf9\x54\x51\xd0\x5c\xbb\x97\x2d\x64\x23\x6b\x11\x34\x64\x93\x87\x3a\xab\xbe\x9b\x26\xe9\xef\x41\xa3\xa6\x96\xe9\x98\xb2\x69\x04\xf2\xe5\x9f\xa3\x9d\xb2\x20\xa8\x20\xcb\x4d\x2f\xbc\xdf\xed\xb9\x2c\x23\xdb\x56\xe7\x46\x3f\x50\x51\xb6\x8c\x43\xdd\x40\xca\xad\x51\x5b\xd2\x03\x54\x28\xd8\xf4\x02\xea\xdb\x8f\x5a\x62\xc0\x9e\xc9\x8d\xb8\x18\xde\x23\xdd\xf6\x71\xf7\xb2\xfc\xdc\x50\x77\x15\xc7\x67\x85\xbe\xbb\x18\x7d\x30\x14\x5e\xc5\x75\x1e\x1a\x2f\x0f\xbf\x12\x2a\x8f\x76\x7f\xc2\xeb\xe6\xcf\x9f\x9b\x74\x10\x29\x98\x6e\xf7\xa7\x70\xbd\x59\xf8\xfe\xe9\xae\xb0\x76\x6b\x2f\xcc\x31\xb7\x45\xd7\x57\xcc\x82\xce\x60\x63\xa2\x03\x38\xd9\xb8\xf5\x89\xb6\xf1\x01\x36\xb2\x1c\xcc\xd0\x27\xc8\xbe\xa5\xe8\xb7\xd6\x55\xa7\x6d\x5c\x01\x6b\xaf\xcd\x52\x43\xf6\xe4\xe2\x86\xdc\x07\x23\xee\xd6\xd5\x98\x73\x4b\xde\xf7\x85\x04\xc4\xba\x9d\xff\x7a\x79\xf9\xf5\xeb\xd6\xda\xef\x20\x4d\x4c\x32\x4d\x03\xc1\xc9\x5e\x9e\xae\x74\x83\x4d\x6f\xbb\xdf\xf7\xa8\x77\xd9\xb6\x28\x7e\x7f\x6a\x1a\xb3\xf5\xd4\x51\x82\xaa\xdb\xa2\x13\x88\xd6\xd7\x20\x79\x6d\xd0\xb6\x67\xf3\xda\x10\x6f\x79\x7e\x71\xc0\x79\xab\xe9\x8d\x71\x57\xd1\xed\x47\x5d\xc1\xe8\x92\xa4\xdb\x7d\x1b\x19\x06\xb2\x76\xda\xb0\x0b\x95\xba\x8c\xfa\x93\x93\xb4\xc0\xfb\xed\x34\x55\x38\x34\x39\xf5\x7d\x49\xc4\x49\x9b\x95\xff\xa2\x65\xce\x27\x8a\xdb\xa7\x6c\xe8\xd3\x29\xd4\xd0\x39\x50\xdd\xee\xa3\x15\x94\x9d\x53\xba\x8e\xda\x0e\x2e\x76\xb2\xba\xec\xf6\xdd\x5e\x67\x2c\x91\x11\x13\x79\xec\xfb\xf7\x63\xd1\xff\x0f\x86\xff\xf8\x71\x0b\xd4\xa5\xdb\x77\xd2\xfe\x3f\x67\x13\x10\x02\xde\xc9\x64\xf8\xc0\xfb\x66\xca\x25\xf0\xaa\x0d\x5e\xde\xb1\x7f\x82\x55\x5e\xee\xc1\x08\x19\xf5\xc3\x78\xc8\x47\xe2\xfe\xad\x7e\x87\xe7\x44\xfe\x1b\x58\x3e\x2b\xf6\xdf\xc9\xec\x83\xd1\xff\x06\xb6\xf3\xf8\x1f\x74\xc3\x95\x0c\xe0\xa4\xc7\xe5\x89\xba\xba\xd3\xcf\x63\x92\x42\x2f\x0a\xb7\x41\xe3\xc6\x52\x33\x6c\x5c\xbf\x1e\xa2\x2f\x8e\x3d\xa0\xbe\x68\x2f\x9b\x55\x4d\xf0\xb2\x28\x68\xc1\xf9\x8f\x2c\x19\x9d\x55\x1f\x4d\x16\xc8\x30\xa7\xe8\x52\x19\xd6\x59\x6d\x16\x70\x6e\xce\x76\xf1\xe2\x18\x39\x30\xe0\xd2\x66\xe9\x18\x74\xd9\xd6\xb5\x09\x74\xe6\x16\xba\x54\x31\xe4\x99\x1f\x7f\xfd\x7d\x48\x8d\xfe\xfb\xbf\x97\x92\xa3\xbf\xfe\xf6\xcb\x1c\x8d\xcd\x80\xe2\xde\x01\xd6\xc4\x9c\xa0\x10\xa9\xd6\x06\xd6\x39\x98\x2d\x67\xfa\x18\xf5\xa5\x4d\x18\x74\x2b\xf0\x9c\xb5\xc9\x59\x4f\xd4\xf2\xf2\xc5\xb1\x3e\xe9\x07\x68\x4f\xf0\x80\xbe\x3f\xc2\x5e\x1c\xb4\xc5\xab\xc1\xe9\xc9\x58\xb4\x72\x2c\xd8\xdf\x88\x1a\x59\xb6\x3b\x0b\x7f\xfd\xed\x5f\x06\x9f\x06\xe9\xcd\x94\x6d\xd8\xd6\x90\xaf\xae\x30\x99\x20\xab\x1f\xce\x54\x0f\x90\xae\xda\xd5\x31\xe0\xdb\xda\xb0\xdd\xfd\x40\xcb\xfe\xce\xb4\x3c\xf2\x6e\x55\x52\x31\x5d\xd9\x39\xad\x5d\x67\x5f\x18\x4f\xeb\x79\x2d\xb7\x8d\xf2\x46\xd3\x60\x5d\x6c\x5c\x29\x9f\x1f\x17\x2a\x8f\x8b\xe7\xf7\x2d\x1d\x9f\xc7\x44\xc8\x9e\xca\xab\x4c\x5d\x5d\x72\x86\x61\x32\x30\x61\x79\x1a\x9b\xa1\xdb\x52\xaf\x32\x7a\x23\xba\x5e\x66\x35\x09\x1d\x88\xa9\xa6\x75\x63\x13\x11\x4b\x0a\x0d\xe1\x06\x7b\xd9\x52\x5d\xac\x35\xb0\x6c\xa9\x51\x3e\xd9\x48\x74\x93\x91\x3a\xf6\x1d\xbc\x62\x2f\x80\xc0\xb7\x9f\x97\x57\x8c\x78\xc5\xf0\x57\xec\xe5\xe5\xc7\x1f\x37\xef\x25\xae\xdc\x1b\xc0\xca\xb5\x4d\xc0\x7b\xd9\xf1\x6f\x04\xee\xc8\x7a\x01\x7d\x7d\xa2\x3b\x3a\x34\xfa\x5e\x7d\xe0\x77\x7b\x66\xbc\xbc\x62\x2f\x04\x0e\xf8\x9f\x38\xf3\x13\x27\x31\xc0\xfd\x22\xb8\x5f\x14\xfb\x3b\x4e\x12\x14\xcf\xc4\x70\xc2\xcf\x70\x20\x74\xa2\xef\x1d\xb6\x39\x99\x4d\x69\xdd\x77\x4c\x5d\xb9\x8e\x89\x67\x68\xf6\x1e\x4c\x64\x7f\x6e\xa3\x83\x83\xd6\x27\x67\x07\x7c\xae\xe2\xa3\x28\x9c\xe2\xee\xc1\x47\xf5\xa1\xa2\xf4\xfd\x65\xd2\xab\x38\x68\x8a\x26\x89\x7b\x70\xd0\x7d\x2f\x25\xd9\x2d\x8e\xdc\xed\xf5\xab\x28\x18\x12\x27\xee\x62\x83\xd9\xa1\xd8\x7a\xce\x10\x28\x38\x0a\xd0\xf7\xa0\x60\xfb\x63\x53\xd1\xd5\x75\x78\x2e\x38\xc0\x10\x77\xa1\xe0\x4e\xb8\xd8\x76\xd5\x87\xc0\xc3\x52\x0c\x79\x1f\x9e\xcd\xa4\x43\x4d\xb3\x90\x06\x1d\xd3\xba\xae\x53\x3c\x0e\x70\xfe\x1e\xf0\xbc\x0b\xde\x2b\xa1\xf7\x57\x8a\x75\x1d\x3a\xc1\x82\xbb\xa6\x1a\xe0\x2e\xf8\xed\x2c\xb8\x15\x8a\xeb\x08\x68\x9e\xbd\x4b\x3a\x00\x1c\x23\xd8\xaf\x5c\x37\x0e\xe0\x3a\x22\x9e\xe1\xef\xe3\x84\x38\x99\xe8\x6d\xad\xc0\x3b\xc7\x7d\x0d\x13\xc0\x59\x9a\xba\x6b\x46\x00\xe9\xb1\xb3\x2f\xcd\x5c\x9d\x71\x00\x08\x96\xb9\x8f\x13\xaa\xaf\xea\xab\xdd\x99\x16\x73\x6c\xf4\x55\x1d\x19\x57\x5d\x23\x00\x34\x00\x77\x39\x61\x40\xef\xf2\xd5\xdd\x16\xcb\xea\x06\x1b\x0c\x7b\x9f\x9b\x07\x4c\x5f\x9f\x68\xc8\x76\xfa\xe7\x9b\x38\x37\x50\xb1\x3c\x77\xdf\x8c\xb0\x27\x69\x82\xbb\x5b\x06\xaf\x07\x93\x4d\xd8\x25\xa9\xbb\x90\x70\x7b\xf5\x55\x4d\x6b\x97\xd0\x9f\xe0\x00\xf8\x4f\x12\x60\x80\xfa\x05\xf8\x5f\x14\xff\x3b\x20\x48\x8e\xa4\x63\x38\xb8\x12\xcf\xaf\xb6\x97\xdc\x1b\xd0\xcf\x5a\x4c\x8e\x93\x94\x74\xbc\x93\xae\xe6\xda\xad\x42\xbb\xdc\xcd\xa4\x0a\xad\x46\xbe\xdd\xa2\x53\xe9\x8c\x40\x16\x4a\xdd\x2e\x91\xab\xe6\x8b\x6c\x59\xc8\x09\x4d\xb1\x9a\x6a\x32\x85\x4a\xa2\x2e\xa6\x5a\x9d\x72\xc9\x2f\xa0\x40\x24\x9b\x6c\x26\x9d\xe8\xe4\xd3\x4c\xad\x44\x95\x4b\x59\xb1\x92\x28\x96\x52\x71\x96\x24\x04\x8a\x64\x7a\x74\xa5\x94\xac\xd7\x0a\xe9\x76\x9e\x4d\xc7\x0b\x89\x62\xb5\x90\x4d\x95\xa9\x3a\x2b\x76\xdb\xad\x66\x68\x24\xe4\x06\x89\x40\xb7\xe3\x95\xae\x40\x77\xa9\xb6\x20\x66\x3a\xed\x1a\xd1\xcc\x97\x89\x66\x99\x8a\x37\xd3\x99\x66\x95\xa5\xc4\x66\x25\x5f\x2e\x11\xd5\x4c\x8b\x6a\xd7\x32\xe5\x6c\xad\x94\xcf\x67\xce\xa6\x3a\x10\x09\xe5\x72\x52\xad\x74\xd3\x19\x2a\x4f\xb3\x9d\x78\x52\x2c\xe5\xf3\x1d\x9a\xce\x27\x1b\xed\x72\x23\x4f\xb7\x93\xed\x5a\xb5\x9c\x21\x0a\x19\x31\xd9\x21\xc5\x7c\x2b\x5b\xad\x15\x8a\x62\x3d\x1d\x4f\x87\x46\x42\xbb\x48\x08\xb2\x9a\x22\x32\x4d\x91\x26\x84\x62\xa7\x99\x6a\x66\x48\xa1\x9b\x13\x3a\x9d\x74\xa7\xd3\x22\x5a\x99\x4e\xb7\x5b\x63\xc4\x6e\x47\x6c\x54\xf2\xc9\x4e\xaf\x2e\xb4\x19\xb6\x53\xa6\x42\x23\x61\xdc\x89\xaf\x55\xba\x99\x6c\x81\x48\x64\xc9\x54\xa9\x4a\xc5\x3b\x85\x54\xb1\x94\x2c\xa4\x72\xcd\x52\xa5\x49\x64\xba\x64\xaf\x98\xaa\x67\xca\xa5\x66\x42\x2c\x0b\xf5\x36\x5b\x4d\xb0\xe5\x0e\x91\x79\x89\xda\xd8\xb5\x49\xe8\x6f\x68\xed\xb6\x19\xf6\xd0\xc7\xfe\xbb\x8d\xae\x37\x3d\xbd\x62\xcc\x2b\xe6\x58\x73\x14\xc2\x96\xce\xdb\x99\x22\x5b\x92\xb7\xde\x3c\xb6\x23\xd9\x42\x8a\xee\xf4\xa1\x31\x1d\xc0\xc9\x7c\x4c\x6d\xac\xbf\x59\x4f\xbe\x7c\xc4\x74\x9e\x62\x27\x02\xb0\x8b\xcd\xda\xcb\x83\x1a\x1b\xa5\x7d\xe8\x29\xb3\x7c\xb2\x36\x77\x17\x40\xe1\xe6\xf8\x52\xf7\x50\xd4\x49\xde\x75\x10\x1d\xf9\x18\x82\x66\x19\x9e\xc3\x59\x8e\x25\x5f\x31\xe0\xd2\xf5\xf2\xdf\x6f\x5e\x52\xf1\xed\x17\xf6\x0d\xe0\xbf\x6f\x57\x6d\xdf\x5e\xb1\x6f\x87\x1e\xb5\xcd\x35\xb1\x59\x3b\xfc\xe8\xac\xa7\xee\x8f\xfe\x79\x3b\x8c\xf0\x7a\xd5\x36\x63\xa2\x4e\xe0\xb7\xff\x0d\x52\x20\x3f\x67\x84\x8f\x33\xe2\x15\x23\xef\xe0\xac\x59\x4f\x46\xe5\x2c\x9a\x61\x44\xe7\x6c\xf3\x9f\xc7\x9a\xb7\x3d\xe7\x52\x11\x31\x02\x6e\x38\xda\xe5\x7a\xdf\x7e\x6d\xd4\xe1\x9b\x6d\x1a\x4a\x3f\x48\x68\x92\x39\xd7\x06\x4e\xe0\x65\xef\xde\x4b\x82\x3d\xba\x72\x4d\xba\x3b\xf8\x97\xb4\xee\xe4\xda\x35\x20\x47\xb8\x9e\x30\x4f\x7e\xcc\x9f\xa9\xd4\xc0\x37\xf5\xd4\xa5\xa9\x8f\x98\x97\x7c\xfc\xd4\x6f\xe7\xed\x91\xa9\xdf\x6a\xcf\xa3\x53\x1f\x71\x9e\xae\x4d\xfd\x47\x5b\x3d\x78\xc5\x00\xbb\x59\x2e\xb0\x24\xc1\x81\x8b\x9e\x9a\xf8\x77\x7a\x6a\xca\xc7\xd9\x05\x4f\xfd\x2f\xe5\x8c\xd8\x73\xc6\x92\x2c\x1b\x10\x5d\xff\x9d\x41\x88\xf6\xb1\x76\x31\xbc\xfe\x3b\x59\xdb\x5b\x1a\x07\xa8\x80\x9c\xe8\x9a\x3e\x7e\x61\xce\x68\x1f\x67\x77\x5a\xda\x17\xe6\x8c\xdc\x73\x46\xd3\x0c\x7f\xbf\xa5\x7d\x61\x27\x42\xf9\x58\xbb\xd7\xd2\xbe\x30\x6b\x9b\x59\x23\x38\x8e\xe2\x71\x9a\xe7\x68\x6f\xd6\x70\x97\x37\x43\x1f\xeb\x2e\x6b\x3c\x41\x90\x24\x4b\xe0\x24\xc3\xd1\xbf\x53\x2c\x4b\x73\x38\xfb\xaf\xe2\x91\xd8\xf1\x08\x70\x7c\x17\xb7\x23\xf1\xf8\x85\xad\x0f\xec\x79\xa4\xc0\x2e\xce\xfd\xbf\xcb\x23\x47\xec\xa2\xc2\xff\x6b\xba\x4a\xbf\x62\x1c\xcd\xf1\x3c\xc9\x31\x9c\xe7\x44\x3d\x0e\x6d\x07\x5a\x8e\x3e\xd1\xfa\x12\x34\xe0\x44\x46\x7e\x9f\x13\x1a\x01\x73\x8a\x20\xac\x2b\xdb\x49\x69\x02\x1d\x7d\x81\x22\xf3\xb3\x99\x35\x8f\xa1\x25\xd2\xb5\x81\xb3\x5d\xe5\x78\xc5\x93\xfe\x08\xad\x3f\x47\x93\xa8\x2d\x55\x14\xc1\x6e\x9d\xde\x07\x49\x79\x8b\xe0\xa3\xa5\xec\xe3\x27\xa4\x94\x3f\x61\xa9\xec\x51\xc5\x70\x5b\xb7\xfb\x51\x52\xf6\x10\x7c\xb4\x94\x7d\xfc\x84\x93\x72\xd4\x2a\xd0\x3d\x11\xdc\xa5\x8a\xc6\xf9\xad\xe3\xff\x20\x29\x6f\x11\x7c\xb4\x94\x7d\xfc\x84\x93\x72\xc4\x3d\x9a\xbb\x72\x08\x8f\x2a\x1a\xdf\x86\x9e\x8f\x92\xb2\x87\xe0\xa3\xa5\xec\xe3\x27\xa4\xc7\x88\x58\xd6\xfa\xdf\x10\x5b\x92\x97\x0e\xa6\x46\x2d\xb1\xef\x0e\xa7\x1e\xef\x4b\xf1\x04\xa3\xa8\x04\x60\x69\x48\xb1\x88\x55\x29\x99\x46\x04\x4b\x92\x2c\xcf\xc8\x92\x44\x41\x99\x91\x38\x89\xc6\x69\x44\x29\x90\xa3\x19\x5e\xc6\x15\x86\xd8\xa4\x1a\x12\xaf\x00\x16\xd0\xea\xcb\x2b\xf6\x42\x33\x3c\xcb\x21\x85\xe6\x19\x80\x14\x95\xe4\x38\x02\xc8\x12\x81\xf3\x24\x21\x29\x2a\xc1\xaa\x88\xc6\x21\x01\x28\x40\x00\x82\xc2\x09\x85\x96\x54\x1a\x12\x38\x0b\x59\x42\xa1\x65\x9e\xa1\x5f\x5c\xc5\x01\xbe\x4d\x62\xe6\x17\xc9\xfc\x02\xb8\x7f\xef\xd8\xfd\x19\xe7\x7f\x67\x48\x8a\x61\xb8\x9b\x57\xb7\x45\x49\x92\x65\x99\x57\x0c\x6c\xfe\x87\x9f\x7d\x5e\x31\x40\xbb\xff\x6e\xff\xd9\xff\xba\xff\x63\x43\x9b\x20\x08\x42\x02\xc0\xce\xd0\x69\xb7\x33\x0e\x47\x69\x83\xf5\x3a\xd1\xc8\xf3\xdc\xe4\xcd\x48\xe8\xa9\x78\xb6\x5e\x4d\x00\x89\x87\xd9\xcc\x74\x0d\x64\xc3\x30\xf4\x31\x98\x11\x55\x40\x4a\x83\x41\x8b\x25\xba\x39\x8d\x1b\xd9\x56\x95\x1d\x94\x39\x62\xba\x8e\x75\x67\xba\x91\xcc\x0a\x1c\xbf\x16\xb5\x0d\x68\xa1\x53\x69\x15\x91\xf7\xa7\xfb\x51\xcc\x69\x7a\xd6\x7b\x4b\x69\xef\xdc\x4a\xe3\x81\x9a\x58\x36\xec\xc5\x2a\x3b\xb6\xf9\xf9\xa8\xcd\x92\x89\x0c\x4a\x38\xf1\x79\x69\x5c\x6a\x17\xb2\xad\xea\xf8\x6d\xba\xac\xaf\x67\xd4\x50\x45\x8b\xc9\xb0\x22\x65\x33\x44\x56\xee\xc4\xe3\x95\x46\xec\xbd\xb1\x52\x4c\xbd\xbb\x58\x18\x33\xd5\x85\xdf\x2d\x51\x05\xf8\x3e\x25\xaa\x07\x64\x42\x47\x16\x4e\x3f\xf1\xcd\x3f\x3d\xa1\x03\xa8\xaa\x20\x24\xf1\x9c\xf0\x6f\xfb\xbc\xec\xdc\x51\xa9\x59\x28\x04\x98\xbf\xdf\x22\xe8\xe7\x68\xf3\x0b\x45\x22\x09\xe2\x2a\x81\x78\x8a\x87\x32\xc7\xab\x38\x24\x78\x95\x84\x12\x4b\xe0\x14\xa4\x21\xa1\x12\xa4\x02\x70\x08\x79\x48\x23\x1c\x71\x12\x24\x15\x49\x41\x24\x03\x19\x8e\x67\x28\xfe\x8a\x45\xe0\x7c\xa0\xce\x33\x2c\x83\x93\x37\xaf\x12\x80\x62\x29\x8e\x64\x28\x0e\xbf\x66\x11\x54\x48\x8b\xc0\x2b\x96\x59\x29\x4c\xeb\x70\x9d\xe3\xf2\x79\xb5\x6c\xc9\x5a\xdd\x30\x17\x59\x5e\xcc\xcf\x60\x47\x63\x0a\x26\xbf\x40\xa5\x19\xcc\xf5\x72\x8d\xba\xd0\x2b\xd2\xa3\x1c\xcc\x0e\xc9\xd4\x78\x36\x4e\x88\xb2\xde\x16\x1b\xb5\x58\xf5\xad\x6c\xf3\xac\x9a\x6d\x51\x42\x19\xb6\x6a\xb9\x85\xe8\xce\xa0\x6b\x11\x47\x4a\x5a\xd4\xa7\x2d\x2d\x29\x15\xca\xf1\x65\xcd\x34\x32\x71\xbb\x51\xb7\xc7\xab\x54\xe9\x1d\x35\x3a\xa4\xa0\xcc\x7a\xf5\x8e\x43\x16\xd2\xc5\xd4\x78\x58\x26\x2a\xfa\x84\x75\x54\x2d\x95\x10\xe2\xeb\x8a\x2e\x6b\xc3\x1c\x51\xaa\x17\x57\x35\x45\x69\x33\xbc\x30\x2c\x38\x4b\x46\x86\xb0\xd6\x73\x2d\xa2\x79\xc1\x22\x5a\x94\x4f\xa1\xfe\xbf\xb4\x08\xea\x39\xda\xfc\x82\x78\x9e\x95\x59\x06\x92\x14\xcb\x4b\x1c\x2f\x13\xaa\x8c\x38\x48\x22\x16\x90\x94\x4a\x92\x2a\x42\x34\xa5\xb0\x0a\x0d\x48\x86\x91\x24\x5e\x05\x32\x4f\x52\x32\x47\x90\x34\x50\x24\x02\x87\x2f\xee\x96\x12\x75\x51\xb9\x83\xa3\x00\x47\x91\x34\x75\xf5\xaa\x1b\x7c\xdc\x22\x16\xc3\x03\x8e\xba\x66\x11\x64\x48\x8b\x88\x8d\x3b\x2b\xc2\xc4\x91\xa4\xcb\x05\x8e\xc9\x57\x26\x22\xce\xbd\xbf\xcd\x5b\x25\xb5\x25\x12\x90\x9d\xac\xd6\x8d\x46\x36\x0b\x32\x52\x36\x5f\x5b\x89\x6b\x87\xaf\x2b\x23\x7a\x19\x5b\xf3\x35\xb9\x64\xd3\xe9\x79\x76\x45\xce\xe8\x7a\xa2\x45\xc8\x85\xe6\x94\x35\x9d\x26\x9e\x8b\x35\xba\xee\x0c\xba\x16\x71\x34\xa3\x3d\x64\x64\x2b\x75\xd2\xae\x0e\x84\xc4\x3c\x9f\x1d\xd9\x24\xc5\x00\x9a\xab\x91\x39\x1e\x8c\xac\x59\x2c\xc7\xbd\xa1\x71\x7a\xb4\x5a\xd4\xad\x44\xad\x53\x37\x97\x14\x2b\xbe\x5b\xc6\x80\x2c\x9b\x6a\x67\x19\xcf\xcc\x5a\xa0\x67\x15\xe6\x26\x3d\x4f\xb7\xcd\xac\xa1\x16\xd4\x42\x56\x73\x2d\xa2\x7a\xc1\x22\x9a\xcd\x4b\x5a\xf5\x2f\xb7\x08\xea\x5e\x8b\x20\x9f\xa3\xcd\x2f\xa4\xca\xd3\xb2\xac\xca\x40\x91\x70\x9c\x23\x39\x95\x64\x68\x5c\x06\x84\xcc\x02\x19\x67\x19\x1a\xc8\x2a\xc7\x20\x1e\x91\x8a\x44\xca\xb4\xcc\xa9\x1c\x81\x73\x34\x47\x01\x44\x41\x00\x48\xe2\x9a\x45\xb0\x81\x3a\xbf\x49\x6d\x83\x2d\x62\x77\x75\x5b\xfb\x04\x1c\xc7\x5d\xb1\x08\x3e\xa4\x41\xbc\xc7\x5a\xef\x95\xa5\x62\x0b\x1a\xc5\x11\xcd\xa2\x68\xcb\x72\x9c\x68\xca\xb1\x34\x83\x2a\x52\x25\xb5\xae\x68\xda\xa0\x5b\x45\xf5\x81\xb8\xee\x91\xe2\x88\xee\x65\xf3\x40\x2d\x88\xf5\x8e\x5c\x30\xc4\x37\x1c\x7f\x17\x6c\x9c\x49\xf0\x68\x34\x05\x39\xe9\x8d\x40\x56\x69\x2d\xcf\x97\xee\x04\x6e\x0c\x42\x59\x1e\x26\xb4\x3e\x6e\x77\xbb\xb8\xd8\x1c\xc5\xdb\x45\x4a\x7b\x8b\x8d\x26\x5a\x53\x1f\x2e\xb3\x2d\xb6\x6c\x25\xe8\xde\xe8\xad\x98\xe9\xa6\x73\x43\x51\xb4\x49\x01\x5f\x0d\xdb\x53\xb9\x63\x19\xed\x44\x5b\x4a\x34\x1a\x6a\x2c\x67\xe5\x93\x94\x35\xd2\xe7\x93\x91\x94\x2c\x13\xab\x8c\xce\x09\x6f\xb4\x07\xb9\x78\xc1\x20\xca\xe2\x25\xa5\xfa\xff\xcd\x20\x88\xe7\x28\xf3\x0b\x43\x2a\x3c\xa7\xd2\x24\x83\x10\xc3\x29\x40\x22\x58\x89\x96\x38\x5e\x25\x48\xa8\xd2\x24\x00\x12\x4b\x33\x3c\x24\x28\x15\xaa\x80\xc2\x49\xa8\xe0\x12\x4d\x48\x0c\x49\x4a\x38\x2b\x21\x7e\x13\x66\x68\xf7\xbf\x0b\xba\xcd\x04\xa9\x3c\x0b\x18\xd2\x43\x1f\x78\x75\x93\x34\x79\xc5\x3a\x8a\xe6\x89\x2b\xf6\x10\x76\x11\x41\x54\x7a\x43\x50\x9a\xd3\x26\x2e\xe5\xd8\x36\x35\x59\x97\x17\xcd\x55\x9a\x6c\x4d\xcd\x51\x6c\x91\x12\xca\x4e\x02\xe4\x89\x22\x1b\x67\x99\xde\x60\xa2\x4a\x62\x72\x9a\xa9\x74\x15\x8a\x9e\x54\xe5\x06\xdb\x19\xa9\xd9\xe2\xb2\xde\xe1\xb5\x54\x92\x8f\xa9\x6d\xe8\xb0\x80\xa9\x66\xdb\x5e\xfe\xee\xda\x83\xeb\xc0\xb3\xfb\x7f\x04\x57\x65\xed\xc3\xf7\xa5\x50\xa9\x8e\xbc\xf9\xae\xf2\x63\xae\x50\x4f\x73\x12\xdd\xc6\xa5\xf9\x4a\x74\x66\xb6\xd3\xaa\xbe\xb3\xd9\xd6\x5b\xc6\x4a\x8e\xd3\xa2\xa3\x08\xd4\x38\x21\x26\x3b\x6b\x6e\xd0\x70\x88\xae\x56\x9b\x34\xb2\x8d\xec\xfc\x9d\x9a\x95\x7a\x22\x3d\x2b\x96\x1a\xef\xf8\x54\xc4\x29\xd0\x92\x9b\xad\xf4\x72\xdc\x86\x4d\xd7\x1e\xb3\x17\xec\x25\x83\x5f\xd2\xb9\x7f\xb9\xbd\xd0\xf7\xda\x0b\x78\x8e\xae\xbb\x47\x34\x37\xa8\xf1\x57\xec\x05\xf0\x2c\xfe\x13\x07\x3f\x71\x80\xe1\xf8\x2f\xf7\xbf\x40\x9d\x26\x39\x2f\xed\xb9\x7e\x95\x22\x78\x8a\x67\x58\x82\xbf\xb6\x6e\xbe\xac\xef\x1e\x49\xff\xf4\xd4\x04\x7f\xe2\x9d\xbc\x4e\xad\xdf\xd6\xf5\x7c\x9c\x4d\x4e\x92\x7c\x86\xc0\x57\xc3\x78\xcc\xc6\x35\xc7\x5e\x66\x97\xef\xa0\xa3\xd4\xdb\x5d\x18\xcf\xc1\x94\x6b\x4a\xe2\x05\x55\xbe\xfc\xd9\xa9\xb2\x20\xc4\x47\x9f\xc0\xc8\x53\x3f\x2f\x3b\x65\xda\xaa\xf2\x8d\xc2\x54\x88\xc7\x36\x45\xad\x53\x05\x1c\xcd\x0c\x6a\x35\x23\x02\xec\xee\x06\x98\xb3\x66\xc5\x68\x60\xc8\xdd\x8a\x9a\xc2\x69\xb7\xd0\x1c\x0d\x8c\xbf\xd5\x88\x8a\x06\x86\xf6\xf7\x62\x45\x03\xc3\xf8\x7a\x68\xe8\x68\x60\x58\x7f\x2b\x4e\x34\x30\x9c\xaf\x39\x24\x22\x35\xbc\xbf\x7b\x26\x1a\x18\x80\xfb\xda\x1e\x22\x4e\x15\x00\x3e\x38\x11\x15\x10\x10\xbe\x5e\x85\xa8\x70\x48\x5f\x3f\x40\xc4\xd9\x02\x94\x7f\xcf\x3d\x22\x1c\xda\xbf\xaf\x1d\x11\x8e\x6f\x6b\x97\x89\x08\x86\x3d\x05\x13\x51\x09\x01\x77\xba\x27\x19\x95\x1a\xfe\x14\x4c\x44\x1d\x24\xf0\xd3\xbd\xbb\x88\xd4\x10\xfe\x2d\xcd\x88\x60\x88\xd3\x3d\xae\xa8\xd4\xf8\xb7\xca\x22\x82\xa1\x4e\xf7\x82\xa2\x52\x43\xfb\x76\xb0\x9e\xf3\x54\xc0\xa7\x1c\xfc\xb8\xfe\xfc\x82\x4d\x7c\x0c\x7b\x12\x24\xe0\xe1\x78\x0f\x67\x00\xc7\x72\x3c\x0e\xf9\xfb\x2f\xc4\x51\x47\x9d\x63\x3e\xb4\xe9\xf9\x8a\x7d\x53\x2d\x73\xfc\x68\xa7\xfa\x14\x3a\x83\x6f\xbf\xb0\xbf\xfe\x7e\xc5\x9e\x7d\x56\x65\xfb\x1c\xbd\x31\x5c\x05\x81\x7c\x4e\x2b\xf9\xee\x79\x7d\x81\x0d\xf4\xde\xe5\xcb\xa7\x27\x8e\xae\x85\xe0\xe5\x89\xed\x52\x1f\x70\xf2\xf1\x92\x1e\x1e\x27\x7b\x87\x2f\x8c\xab\x87\xde\xde\xb4\x7b\x82\xdb\x15\xdb\xc9\x04\x05\x74\xb2\x7a\x4f\xa4\xdb\x30\xff\xdf\x6f\xbb\xe3\x0d\x93\xcd\xff\xff\xef\xe9\xb1\x07\xfc\x15\xfb\x26\xcd\xd7\xfa\x44\x0b\x38\x79\x70\x7c\xed\xaa\xe4\x91\x61\x9c\x43\xd9\x1d\x81\x38\xb9\x78\xf5\x14\xc4\x31\xbe\xe7\x9c\x5e\x39\x45\xfe\x94\xfe\xb2\x0f\x38\x73\x7b\x41\x29\x4e\x73\xee\xfd\x17\x7c\xbf\x8d\xb7\x77\x4e\x0f\x9c\x7e\x3a\x38\xa7\xe8\x96\xfd\x75\x0f\x2e\x7c\xc0\x69\xdf\xe0\x89\xda\x1e\x7a\xd8\x7f\x61\xce\x27\xea\x81\x08\x70\x98\xa8\xe8\xa6\xf0\x85\x0f\x2b\x7c\xc0\x19\xdb\xc0\x99\xda\x2d\xd5\xf6\x5f\x88\x0f\x32\xa9\x67\xcc\xd4\x57\x3b\xa1\xf0\xa9\x13\xb5\x3d\xdd\xb0\xff\xc2\x9d\x4f\xd4\x53\x12\xb3\x67\xf8\xbe\x2f\x77\x2a\xe1\x93\x9c\xdf\xc9\x89\x86\xfd\x17\xca\x9d\x26\x26\x5c\xc7\xb8\x63\xcd\x6d\x07\xa1\x47\xe7\xc2\x05\x63\x5a\x8f\xaa\xc5\xd7\x98\xb9\x27\x3f\x09\x23\x70\xe6\x76\xe7\x34\xf6\x5f\xf0\xc8\x33\x17\xdd\xdd\x1d\xcf\xdc\x03\x31\xf2\x8b\x78\xc7\x0f\x5f\x2e\x9c\x56\xc2\xf6\x5f\x98\x7f\x78\xe6\x1e\x88\x99\x5f\x63\xe6\x3e\x21\xa7\x3f\xa9\x3d\xee\xbf\x10\xff\xb0\xb7\x7c\xda\xcc\xfd\x53\xde\xf2\xe3\x67\xee\xb8\x4c\xbb\xff\x9b\x3b\xea\x4e\x57\xe7\x13\x65\xf7\x34\x8a\x68\x8f\xe5\x71\xe5\xe2\x3d\x1c\xe7\xe1\x45\xef\xcd\x56\xf9\x07\x1f\x1f\x74\x8f\xd4\xb6\xe5\xe4\xfd\xdf\xd4\xc7\x4a\xed\x81\x12\xd5\x97\x92\x9a\x57\xf6\xde\xff\x8d\x7f\xa8\xd4\x1e\xf0\x00\x5f\x4a\x6a\xdb\xf2\xfc\xfe\x6f\xe6\x43\xa5\xf6\x40\x96\xf9\xb5\xa4\xe6\x6d\x23\xec\xff\x26\x3e\xd6\x42\xa3\x67\x78\x1f\x2e\xb5\x1b\x5b\x12\x17\xde\xf4\x12\x75\x3b\x62\xfb\xb6\x97\x8b\x5b\x11\x78\xe0\xb1\x15\x6f\x5f\x02\x9c\x76\xc7\x78\xbf\x1d\x7e\x70\x5f\x57\xb3\x5b\x2a\x53\x0c\x00\x0c\xc7\xe0\x14\x05\x78\x16\xf0\x34\xbb\xdb\x3e\xbd\xcd\xea\xed\x17\x6a\x3c\xc0\xfc\xe5\x27\x48\x5f\xec\xc7\x20\x82\xf7\x8d\x6f\x02\x22\x7c\x80\x82\x36\xee\x6e\x02\x22\xfd\x95\xf9\xa8\x80\x28\x5f\x35\x37\x68\x9b\xf5\x26\x20\xda\x5f\x16\x8e\x0a\x88\xf1\x95\x2d\x83\xb6\xa1\x6f\x02\xf2\xd7\x3f\x23\xcf\x1a\xe7\x2b\xcf\x45\xa6\x88\xf7\xd7\xf9\xa2\x02\x3a\xed\xd0\xe0\x1e\x98\xb6\xd3\x1e\x0d\xee\x01\x95\x3c\xed\xd2\xa0\x1e\x81\x44\xfa\x4a\x00\x91\x67\xee\xb4\x53\xe3\x11\x3b\x39\xed\xd5\x78\x68\xee\x98\xd3\x9c\x3d\x68\xd7\xfd\x36\x20\xf6\x14\x50\x64\xb5\x3c\xe9\xd8\xa0\x1e\xa1\x88\x3f\x05\x14\x59\x2b\x4f\xba\x36\xf0\x07\x28\x22\xfc\x49\x6b\x64\x40\xc4\x69\x1e\x17\x9d\x22\xf2\x14\x50\x64\x2b\x39\xe9\xde\x20\x1e\xa1\x88\x3e\x05\x14\xdc\xbf\x71\xef\x0b\x8f\x9e\xd1\xc1\x71\xeb\xc5\x0c\xf7\xf4\x70\x04\xbe\xde\xe8\x09\x99\xc3\xf1\x23\x9c\x15\x02\x52\x12\x62\x09\x8a\xc5\x19\x9a\x53\x19\x4e\x91\x68\x1c\x21\x95\xe0\x11\xc4\xa1\x4a\xaa\x3c\x47\xcb\x08\x70\x12\x2d\x13\x80\x53\x71\x92\x62\x80\x42\xe1\x32\xc5\x2a\x32\xc1\x13\xde\x43\x68\xc1\x23\xe5\xbb\xa3\x7e\x7e\x6a\xd7\xc1\x1c\x78\x90\x98\xc6\xd9\xc0\x6e\xe9\xfd\xd5\x93\xbc\xc5\x6b\x7d\xce\x33\x43\xa4\x93\xc3\xb1\x99\xe5\x1a\x69\x23\xf9\x86\x34\x99\x64\x2b\x1d\x27\x93\xcf\xbf\xb7\x5b\xdc\xb2\xa5\xf7\xe2\x30\x31\xa7\x0b\x74\x51\x70\x5b\x87\x85\x5d\x83\x7e\xc2\xd7\x99\x1b\x3f\xfc\xe9\x5e\x8f\xb7\x5a\xa5\xed\xc9\x93\x04\x98\xc7\x95\x8c\xd9\x98\x6b\xc5\x45\xd5\x49\xb2\xf1\x41\xb6\x40\x96\x10\xaf\xb4\x2a\x6a\x3a\x1b\xcb\xe9\x74\x6e\xd1\x2c\xc7\x7a\x82\xc3\x7a\xa7\x64\x52\x3c\xda\xde\x9a\x74\xb4\xc5\x32\x39\x2f\xb7\x85\x2a\xcf\xd6\x40\xad\xe1\x34\x95\x65\x29\x99\x99\x26\xdf\x12\x4d\x34\x7d\x57\xaa\x95\x8e\x61\x4e\x64\xbd\xd0\x72\xc7\x37\x5b\xad\xe6\xf6\x78\xb2\x59\x59\x76\xdf\x52\xca\x9b\x9c\x5d\x97\x9a\xb3\x37\x34\xcb\x94\xdf\xa7\x33\xb6\xab\x98\x4b\x59\xad\xbf\x8f\x32\x6a\x2f\xd5\xaa\x25\xf2\x84\xe8\x75\x41\xc7\xd5\xce\xe0\xac\xdf\x18\xb2\xa3\xc5\x68\xe9\xb2\x97\xa4\x78\x58\x6b\xce\xdf\x3b\x1d\x54\xca\xcc\x41\x4a\xcd\x76\xe3\xd2\xd4\x88\x9b\x95\x98\x04\xe2\xd4\xbc\x98\x76\x88\x66\xba\xe7\x30\xc3\x4a\x7e\xb1\x6c\x95\x6b\xe3\xe2\xbb\xda\x49\xf6\x60\x26\xbe\xc8\xea\x96\x9d\xe5\x50\x49\x8d\xf1\x29\x20\x66\xf1\xd4\x80\x2f\xbe\x11\xc3\x71\x42\xfb\xf3\xcf\x97\xe3\x36\xf4\xf4\x51\xfb\xf6\xe1\xcf\x23\x59\x7b\x72\x91\xc6\xda\x18\xb4\x08\x45\xa3\x5b\x60\x3c\x03\xc8\x28\xca\x69\xe0\xac\x86\xf5\x6e\xbe\xc7\x2f\x45\xcd\xac\xc7\x21\x6a\x73\x4d\x3d\x65\xfa\xe0\xa5\x52\xad\x96\x77\xc0\x42\xc8\x27\xb9\x74\x65\xd5\x51\xc9\x44\x71\xd8\xca\x2f\xc8\xd9\xe0\xdd\x66\xe0\x9c\xc8\xc0\x62\x26\x83\xdb\x74\x9c\x24\x6a\xad\x66\x55\x77\x06\xdb\x23\x0f\xbb\xb6\xf1\x7f\xf5\xdc\x1e\xe4\x5d\xdd\xeb\x6a\xd2\x1d\x73\x74\xac\xdd\x9a\x95\x98\x02\x2a\x43\x6d\xb8\x2a\xc2\x66\x85\x67\xe2\xef\xaa\xcd\x23\x5c\x36\xad\x52\xaf\xf3\x1e\x6f\xe7\x46\x29\x33\xbf\xd3\x0d\x41\x28\xd3\x56\xae\x7c\xa4\xfb\xbe\xf9\x3b\x99\xbb\x0b\x9f\xf8\x93\xf1\x27\xa2\xe0\x4f\xb8\xf8\x8b\x87\x81\xde\xfd\x6c\xb7\xc0\x09\xec\xd0\xd0\xc4\x0a\xc2\x95\x66\x93\x6d\x65\xe4\x64\x75\xc5\x54\xdf\x96\x46\x66\x26\x93\xcd\x24\xa0\x61\x8e\xcc\xea\xe0\x51\xfd\x4a\xce\xe1\x5a\x8b\xbf\xed\x3f\xcb\x4b\x34\xbb\xdf\xd3\xff\x08\x7d\x62\xba\x3a\x5b\xde\xa2\xcf\x2f\xbf\xc4\xdc\x24\x4d\x87\xa2\x67\x89\x8a\xb8\x9a\x56\xdf\x48\x33\x53\x8a\xbd\x03\xb6\xb6\xd6\x6d\x60\xa8\xc5\x54\x77\x5c\x6d\x6b\xd6\xbc\x1e\x6b\xb8\x37\xa5\x5a\x4d\x7c\x3b\x71\x85\x36\x95\xc2\xd1\xa0\xcc\x08\x6b\x3e\x81\x57\xec\xb4\xa8\x2d\x64\xc0\x02\xd0\xe4\xb9\xee\x90\x1a\x17\x46\x63\xbe\xca\xd2\xa3\x04\xb9\x88\x2e\xbf\xcf\xa4\xaf\x3d\x62\xaa\xa1\xe4\x97\x72\xff\x74\xf5\x31\x3e\x87\x09\xa9\xd5\xe9\x11\x49\xa3\xd3\x86\x56\x8b\x69\xae\x96\x52\x9b\x4c\x97\x72\xda\x74\x42\x0a\xf5\xc4\x20\x9b\x9a\xd2\xd2\xaa\x9e\x6d\x6b\xa7\xfa\xfc\x80\xbf\x78\xc4\xbf\x15\x18\x6e\xab\x5f\xd5\x4b\xfc\x1d\xe8\x8b\x1f\x4e\xc0\xfd\x33\xfe\xbc\xd5\x6a\xd4\xb6\xa0\x1c\x49\xeb\xd4\x18\x91\x35\x93\x05\xbc\x50\x8d\x2d\xbb\xf5\x04\xff\xde\x59\x74\x5a\x0d\x72\xa5\x57\xf4\xee\xbc\x2e\x81\xe4\x62\x5c\x2d\x20\xce\x63\x60\xef\x4f\x45\xe1\x34\xf6\x1f\x7d\x5c\x79\x34\x0f\xd7\xd3\xb4\x99\x73\x5a\xca\xa4\x5b\x6e\x29\xbd\x99\xd3\x99\x36\x32\x71\x47\x92\xbb\xf8\x38\x31\x56\xe5\x78\x36\x2f\x6a\xed\x89\xb1\x48\x65\x07\xf0\x51\xfa\x12\xb1\x45\x42\xc8\x1c\x54\xcd\x3f\x1f\xee\xf5\xe0\xcf\xd1\xfc\x44\x8a\xb7\x8f\xe8\x4f\x8d\x82\x45\x41\xdd\x53\xce\x09\xbe\x78\x72\x88\x9f\x17\x3f\x47\xf6\xe3\x1d\xf1\xba\xd3\x7e\x1e\xc9\x0f\x16\xd6\xf2\xb2\xff\x39\xd3\x8f\x8b\xf2\x77\xe9\xed\x46\xd7\x97\x47\xf3\x83\x2b\xfa\x72\xf4\xf1\xcb\xff\x90\x4f\x1c\xe2\x67\xf2\x88\xd3\x3b\xfd\xab\xc0\x8e\xed\xb1\x7c\x80\x17\x60\x5f\x81\xa7\xfc\x8e\xfc\x7b\x64\xfc\x23\x2a\x1a\x7e\x2f\x97\xfd\xef\x47\x25\xca\x6e\x2d\xde\x7d\x21\xe8\xee\x5c\x69\x98\x7f\x37\xcb\x4a\x77\xf9\x74\x7b\x6d\x7d\xb4\xfe\x93\x68\x42\x05\x8c\xaa\x4a\x3c\x27\xe3\x14\x8b\x48\x52\xe2\x65\x02\xc9\x24\xce\x71\x38\x49\xe2\xb2\x82\x58\xa0\x72\xb4\x44\x52\x14\xa9\x40\x44\xc8\xb4\x2c\x71\x8c\xcc\x2a\x94\xc2\x51\x34\xe1\x1d\xb9\x7d\xe8\x65\x3a\x47\xeb\x3f\xfa\xd6\xfa\x8f\xe1\x00\x13\xfc\x38\x85\xdd\xd5\x93\x72\xb3\xa7\xb3\x77\xda\xd8\xd1\xfa\x2f\xe9\x9b\xfc\x23\x1d\x71\x6d\x20\x5e\x6b\xb5\xea\x5b\x1d\xd4\xde\xe2\x43\xae\x45\xf2\xcb\x61\x16\xd4\x2d\x9e\x31\x65\xb6\x3c\xb6\x9c\x01\x31\x8c\xaf\xf8\x42\xb9\xaa\xf0\xa3\x56\x4b\xcc\x5a\xdd\xba\x17\xd3\xa2\xe7\x18\xae\x0f\x3a\xa2\xe7\xa2\x9e\xa6\xf6\xfc\x54\x53\x46\x67\x09\xcd\x31\xbb\x36\xea\x0d\x65\x0d\xcb\xec\xac\x54\x64\xa9\x6e\x2c\xd7\x1c\x09\x84\x89\xcf\x65\xb6\x4d\xa4\xde\xe3\xc6\xa8\x85\x08\x5b\x7e\x9f\x14\x8b\x30\x56\xe3\x06\xad\x86\x64\x94\x69\xa3\xca\xc4\x52\x72\xa3\x48\x0f\xb3\x56\xbb\x3a\x5b\xcd\x52\xa9\x9e\x54\x1e\x09\xcb\x30\x6b\x3a\xbf\xfc\x84\x28\xf3\xe1\x7d\xc4\x2f\x2c\xef\x3f\x83\xd7\x5b\x47\x63\xef\xcd\x7f\xca\xb4\x95\x05\x82\x70\xba\xde\xd1\xfc\xb8\x6f\xac\xb7\x9e\x87\x3f\x19\x09\xbf\x1b\x1f\x8f\xe2\xb5\x77\xe9\xde\x7c\x97\x1d\xdb\xc3\xe6\x01\x7f\x51\xb8\x50\x9b\xb9\x15\x2f\x9e\x8d\xff\x5c\xb7\x03\xf1\xfb\xd7\x4b\x5f\x22\x5f\xb9\x2c\x9f\xaf\x43\x5f\xb8\x7c\x6a\x79\x20\xda\xfd\xfe\x25\xf2\x6f\xbf\x4e\xfc\x2b\xd7\x07\xee\x27\x7e\xf0\x67\xff\xba\xf5\xdb\x81\xbf\xcb\xfa\x74\x3d\xa7\x8d\xe2\x23\x8e\x73\xca\x8b\xf5\xe3\x4f\xf4\x51\xf7\xe0\xdf\xe6\xb4\xed\x96\x1a\x9f\xe9\xd2\x22\xdf\xca\x95\xc8\x9c\xc9\xce\x4d\xfc\x7d\x31\x18\x52\x46\xbd\x9a\x84\xc3\x3a\xfd\xee\x48\xdd\x4e\x31\xdd\xae\xb5\x58\xb8\x7a\x2f\xcb\xcb\x95\x45\x67\xd6\xa9\x56\x69\xde\x64\xc7\xad\xa4\x45\xb5\x56\xc5\xf7\x71\x51\x77\x7a\x09\x2b\x6d\x36\x5b\x86\xcd\x54\x93\xc2\xe7\xe6\xb4\x38\x2f\xe3\x80\x62\x21\x43\xc8\x1c\xc1\x91\x04\x40\x88\xe3\x79\x05\x97\x65\x59\xe1\x09\x99\x03\x34\x41\x23\x04\x59\x40\xd0\x38\x4b\xe0\x04\x83\x93\x04\x90\x48\x48\x50\x3c\x4f\x23\x4e\xf2\x1e\xbb\x04\x1e\x39\x06\x70\x94\xd3\x92\xb7\x72\x5a\x8e\x62\x40\xf0\x83\x22\x77\x57\x4f\x1a\x16\x5e\xa2\xd8\xd1\x51\x4e\xeb\xb7\x83\xb8\x4f\x07\xef\xae\x03\x44\xcf\xc9\x8e\xea\x48\x1e\xfe\x3d\xbd\xd5\x04\xcc\x0c\xa6\x7a\xab\xc4\x8b\x14\xc9\x66\x3b\x29\x39\x33\x55\x5b\x96\xb9\x02\xf5\xf2\x5b\x29\xe7\x24\xc6\x71\x62\xa0\x41\xad\x58\xcd\x24\x6b\xc9\x74\xb5\x98\x29\x91\xb3\x61\x5d\x6e\x94\x67\x33\x24\xda\x25\x71\xbe\xc8\xc7\x26\x6c\x96\x92\x62\x7c\xca\xc2\x6b\xa4\xb3\x1c\xcb\x9a\x1d\x26\x67\x3d\x96\x4f\x70\x5e\x77\x34\xe8\xde\x75\xb8\xaf\x8e\x1d\xf0\xb9\x91\x57\x3d\x0f\xff\xe5\xba\xd6\x0d\xfc\x67\x3e\xf3\xd3\xf3\x06\x17\x5f\x98\xbc\xe6\x8b\xe6\x5d\x7f\x5e\xaa\xa9\x1c\xf9\xeb\xbb\x6d\x89\x1d\xdb\xdb\xb8\x7b\x96\xa3\x1f\x7d\xae\xc7\x1f\xf1\x31\xfc\xc7\x35\x9d\x7b\xf0\x6f\xe3\x4f\xce\x44\xe9\x71\xae\x49\xe2\x8d\xa1\x6a\x0f\xe4\xd6\x12\x19\x7c\x7b\x3e\xcc\xb4\xb2\x2c\x87\x8f\xf1\x7c\x37\x03\xd3\xf1\x99\xb0\x12\xe4\x92\x58\xec\x09\x4b\x99\x44\xb3\x52\x6e\x55\x64\x66\x53\xaa\xbe\xc4\xeb\x0c\x67\x31\xaa\x3d\x1c\x2c\x58\xbc\xbd\xa8\x65\x10\x99\xe8\xad\x13\xcb\xcf\x8d\x3f\x2c\x4b\x32\x2a\x2e\x71\x0c\xaf\x20\x5c\x65\x29\x48\x23\x85\x55\x39\x85\xa1\x09\x9e\xa7\x78\x82\xe4\x90\x84\xab\x38\x45\x00\x95\x54\x65\x42\x92\x64\x8a\xe4\x70\x8e\x52\x09\x20\x73\xb8\xf7\xbc\x2f\xef\x29\x0a\x91\x0f\x0c\xde\x17\x7f\x38\x2a\xb8\xa6\xb2\xbb\x7a\xd2\x9e\xe6\xe9\xec\x9d\x6b\xe8\x7b\xe2\xcf\x9d\xfb\x82\x8f\xd4\xa1\x0f\x36\xe3\x7e\x32\x7b\x7a\xab\xc9\x61\xbc\x2e\xcc\x8d\xbc\xcc\x3b\xb5\x59\x5a\x8b\x95\x47\x2d\x29\x5f\x79\xa7\x4c\xa3\x56\xed\x36\xd1\x62\x9d\x50\x17\x78\x41\x30\x66\x52\x27\xcd\xac\x2b\xd2\xb4\x86\xc7\x6b\x8c\xc9\x8e\x2d\x7d\x5c\x1b\x73\x65\xaa\x65\xd6\xe2\xe9\xac\xd0\xa8\xc6\x29\xa2\x54\x6e\xcb\xa9\x77\xa5\x1a\xaa\x66\x72\x77\xfc\xb9\x37\x2f\x7e\x76\xfc\x79\x10\xff\x13\xe3\xcf\x27\xee\xf3\x79\xa4\xdc\x19\x7f\xbe\xd2\x3e\xe9\xcd\xf8\x13\xdd\x96\x9e\x13\x7f\x22\xe0\x7f\x30\xfe\x94\x8b\xa9\x6c\x82\x69\x4e\xdf\x09\x90\x36\x61\x92\x62\x6a\x2d\xdb\x7c\xab\xe8\x7a\x2b\x15\x1f\xd4\x98\xb7\x6c\x2e\xf6\x56\xb5\x13\xed\xa9\x23\x4b\x56\x96\x9f\x1b\x99\x6a\x2a\x33\x1b\xce\xe1\x3c\xdf\x4b\x4b\x4b\x76\xd0\x1e\x88\x62\x57\x8b\x97\x84\xcc\xb0\x8b\xd3\xbd\x65\xa7\x04\x3e\x7b\xfd\xa3\xb2\x94\xac\xd0\x14\x87\xe3\x0a\x4d\xb2\x32\xce\x28\xaa\x4a\xd2\xb2\x4c\xb1\x1c\x29\x21\x8e\x03\x32\xa1\x30\x2c\x2e\x03\x40\x03\x48\x33\x32\x64\x55\x9e\x06\x2c\xcd\x29\x32\x4b\x01\x5a\xf1\xe2\x0f\xf9\xa4\xf8\x73\xb3\xa7\x8b\xa3\x71\xe6\xca\x63\xc1\x69\x9c\x39\x3c\x16\x7c\xdb\x8c\xfc\x68\xfc\xb9\xd2\xd3\xf5\xe9\xfb\xa0\xbe\xf5\xcf\x51\xfc\x29\x67\xf3\x75\x23\x59\x1d\xf3\x4d\x6b\x46\xcc\x87\x93\xc5\xaa\x37\x4c\xcf\x98\xf7\x5c\x75\x22\x57\x1a\x53\x6e\x61\x50\x76\x22\x41\xd5\x20\x55\x6c\x4e\x60\xa6\x9b\x84\xa3\x5a\xa7\x91\x32\xab\x46\x36\x25\x58\xb4\x83\x9b\xb9\xa5\x12\xaf\xdb\x4c\x23\xc7\x15\xe9\x16\x4a\x6b\x71\xa9\xaa\x7d\xc5\xf8\x13\xc9\xff\x3f\x11\x7f\x40\x0d\xec\x53\xd6\x3f\x9f\x1c\x7f\x3e\x93\xbe\x48\xeb\x9f\x7f\xc8\xff\x0b\x4f\x8a\x3f\xc7\xf5\xbf\x7b\xf0\x6f\xe3\x0f\xa5\x4d\xf3\xcd\x52\x42\x02\xf5\xb9\x05\x99\x32\x7a\x4b\x8d\x8b\xd0\xb2\x8a\x46\x42\x59\xf2\xe5\xc9\x3a\xd6\xd1\x97\xd9\xc2\x20\x65\x69\xab\xba\x62\x2a\x5a\x69\x56\x4b\x29\xc5\xf6\x20\xd1\xd4\x9a\x89\xc5\x98\xac\x6b\x93\x38\x9e\xca\xbf\x4f\x8b\x93\xe5\xbb\xd1\xa2\xa0\x90\x72\x12\x9f\x1c\x7f\x64\x9e\x54\x39\x9c\x61\x58\x95\x64\x15\x95\xc5\x21\xc1\x23\x19\x57\x10\xcf\xa8\x2a\x49\x72\x80\xa1\x28\x28\x73\x04\x07\x29\x19\x41\x20\x4b\x8c\x8c\x24\x20\xc9\x48\x66\x54\x55\xc5\x69\xee\xf0\x2c\xfd\x67\xd4\xdf\x42\xc4\x1f\xe2\xca\x9e\xf2\xee\xea\xc9\xc1\x93\x47\xeb\x6f\x37\xe3\x4f\x99\x48\xbc\x09\x65\x8a\xee\xc6\x93\xa4\x93\x69\xa5\xca\xa0\x46\x0a\x78\x11\x8d\x2a\x5c\xae\xc6\x4c\x4a\x40\xe0\x51\x5b\x57\xd6\x59\xc7\xdb\x57\x78\xa0\xfe\xe6\x5b\xff\x1c\xd5\xdf\xd2\x94\xc1\x8e\x12\xc2\x8c\x86\xb3\x45\x9d\x50\xde\x32\x0d\xa7\x2b\xb3\x05\x01\xb2\xd3\x7a\x53\xd7\xcb\x54\x7e\x9d\xcf\x49\xb3\xb1\x9d\xd4\x16\xf2\x28\x9d\x20\x14\x69\x20\x5b\x26\xef\xc8\x8b\x44\x2f\xa3\x2e\x67\x8d\x56\x4c\x1f\x2d\xb8\xcc\x98\xeb\xa9\x90\x21\x47\xdd\xca\xa8\xda\xfd\x8a\xf5\xb7\x87\xe3\xcf\x83\xf8\x9f\x18\x7f\x3e\xb1\x4f\xd4\x23\xe5\xce\xf8\xf3\x95\xfa\x6c\x6f\xc6\x9f\x4f\xac\x7f\x09\x4f\xaa\xbf\x3d\x18\x7f\x24\xbd\x33\xaf\x66\x13\x96\x31\x9b\xf1\x85\x1e\xc9\x29\x65\x30\x78\xb7\xed\xb8\x35\x37\x72\xf5\x7c\x96\xd5\xac\xac\x69\xcc\x67\x70\x59\x4e\xf0\xeb\x6a\xb7\xd0\x03\xf3\xd4\x7a\x3e\x24\xc0\x9a\xcb\x8d\x94\xb7\xc4\xb4\xd4\x61\xf2\xf5\xb7\x25\x92\x56\x06\x6f\x59\xa8\xa6\xc5\x6a\xf1\x4f\xef\x69\x92\xa1\x22\x23\x9c\x56\x65\x1c\x2a\xb4\xc2\xa8\x08\xc7\x79\x89\x93\x70\x05\x49\x32\xae\x90\x8a\xaa\x90\x04\x82\x14\x21\x71\x48\x82\x24\xe2\x11\x64\x38\x99\x60\x29\x06\x51\x00\x57\x5f\xbc\x57\x0d\x3e\xf2\x30\xa1\x7b\xea\x6f\x3c\xcf\x5e\x7b\x43\x8c\x7b\xf1\xe4\xb0\xa2\xa7\xb1\x77\x9e\x2a\x08\x57\x7d\xf3\xba\x12\x23\x45\x93\x8e\x6f\x97\xd9\xd3\xe8\x3d\xfe\xaa\x50\xaa\xd6\xdf\x17\x53\x31\x9e\x10\x3a\x0b\x1b\x54\xb4\x71\xe6\xad\x99\x92\x54\xa1\xeb\x90\x65\x41\xd3\xba\x95\x56\x43\xc1\xa7\xc3\x96\x9c\x83\x2d\xd2\x48\x8a\x6f\xc3\x72\xaf\x38\x29\xa4\x7a\xc5\x51\x4a\x1c\x68\x94\x62\xcc\x5b\xd5\x15\x4a\xf6\x84\x65\x23\xdf\xac\xc0\x89\x62\x2f\x43\xad\x66\xd2\xc7\x6a\x1e\x14\x4d\x84\xa3\xf7\xd6\xdc\x19\x7d\x5d\x6f\x3e\x39\xc8\x37\xe0\x73\xc3\x9b\x3f\x0f\x7f\xb4\x6a\xda\xa1\x4b\xe7\xb8\xab\xe5\x4e\x6f\x7d\xb1\xab\xf3\xfc\x73\xdd\x03\x3e\x1b\xff\x1d\x5d\xa5\x82\xf0\x75\xa3\xe9\xad\x6a\x5d\x14\x59\x3d\x5c\xad\x7b\xe2\x5c\xdd\x83\x7f\x1b\xad\x04\x10\x2f\x94\x63\xa3\xaa\x98\x8d\xa3\xd8\x7b\x33\x96\xe8\xaa\x7c\xb5\xe5\x70\x71\x9d\x94\xa9\x44\x22\xae\xf1\xad\x12\x59\x1f\x97\x5a\x4b\x63\xda\x41\xcd\x62\x23\x56\xa4\x47\x6b\xd9\x6e\x8d\xd6\xd5\x66\x3d\x9d\x1c\x10\x6d\xba\x95\x4c\x51\xa5\x51\x32\x5e\x9c\x56\xf9\x99\x42\xbc\x7f\xf6\x6a\x49\x52\x28\x8e\x51\x24\x45\xc1\x09\x85\x62\x70\x0e\xb0\x0c\x0b\x64\x0a\xd2\x90\x45\xbc\xc2\x20\x8e\xa1\x65\x48\xf0\xb2\x44\x01\xc4\x10\x0a\x0b\xa1\xbb\xa4\x52\x11\xa2\x25\x92\x51\x90\x17\xad\x88\x27\x9d\xc0\xbc\x15\xad\x58\x1c\xc7\xa9\xe0\xf7\x37\x6d\xae\x1e\xe2\xd5\xf6\x48\xfc\xa3\x27\x30\x6f\xc6\xab\x48\xd5\x37\xf2\x52\xbc\x4a\xef\xf1\x57\xe3\xfc\x68\x9c\x6f\x13\x33\x72\xc1\x56\xd5\x35\x57\x29\xa2\x91\x28\x81\x46\x23\x4b\xeb\xab\xd9\x28\x8b\xc7\x4d\xad\x63\x95\x1d\x56\x2b\x03\x86\xa8\x4a\xa3\x01\xa1\xd4\x1b\x4d\x15\x25\xcd\x85\x8c\x57\x04\xa8\x0e\x92\x9d\x95\x33\x68\x09\x86\x5d\x98\x0f\x8d\xf8\x78\x3d\x8c\x0b\xa1\x56\x3f\x77\xc7\xab\x28\xa7\xe8\x9e\x19\xaf\x1e\xc4\xff\xc4\x78\xf5\x94\x53\x08\xe7\x9f\xd0\x3e\xf0\xb3\x4f\x41\x08\xc2\xd7\xdd\xfd\xba\xb9\xbb\x14\x41\x56\xcf\x8c\x57\x8f\xce\xd5\x3d\xf8\xb7\xf1\x2a\x43\xd4\xbb\x53\x09\x5a\xe8\xcd\x89\xbf\x15\x96\xdc\x8a\xa9\xd6\x16\xad\x52\x71\x38\x2e\xa4\x67\xd5\x61\x35\xad\xc7\x91\xcd\x90\x73\x81\xed\x58\xbd\xf8\xbc\x9e\xe9\x81\x5c\xa9\xc6\x53\x65\x9d\x7f\xaf\x72\xf1\x69\x4c\x2c\xa9\x69\x22\xd5\x4c\xb4\x97\x73\xa6\xdc\x4c\x4b\xf9\xa2\xf8\xd9\xab\x2b\x0e\x00\xc0\x13\x32\xc9\x31\x14\xa9\xa8\x2c\x29\xe3\x80\x86\x34\x04\x0a\xcb\x4a\x1c\x4e\x28\xaa\x8a\xd3\x0a\xa5\xd2\xb8\x2a\x33\x0a\xc0\x39\xc0\x40\xc8\xd2\x32\x0e\x19\x80\xf3\x2a\x0f\xbd\x78\x45\x3e\xe9\xc4\x48\x88\x78\x45\x04\xbe\xa3\x79\x77\xf1\xe4\xb1\x2b\x8f\x9e\x17\xf9\xc4\x68\x75\x74\xbe\xa3\x62\x68\x6c\xba\x30\xc8\x69\xf8\x8a\x1d\x4e\x85\x25\x10\x97\x4c\x86\xe8\xa4\x98\x75\x2d\x3b\x56\x73\xd9\x65\x4a\x5d\xe1\x7c\x69\xae\xd3\x92\x53\xce\x09\x29\xb4\x4c\x09\x25\xb5\x0c\x85\x38\x97\xaa\xf6\x0c\x7a\x4a\x0a\xb4\x46\x8e\x98\x64\x26\xa9\x6b\x6a\xb3\xd4\x4c\x02\x46\x93\x3f\x24\x5a\x45\x38\x83\xf0\x70\xaf\xc2\x13\xf1\x3f\x31\x5a\x3d\xda\x5f\xfc\x68\xb4\x7a\x0a\xfe\x07\xa2\xd5\x57\xda\x2b\xbb\x15\xad\xa2\xc8\xea\x99\xd1\x2a\x0a\xfe\x07\xa3\x55\xac\x9d\xb4\xbb\x73\x71\x9c\x6c\x64\xe6\xe5\x51\x32\xd9\x6c\x24\x4d\xb5\x27\x77\xac\x9c\xa8\xf7\xb8\xd1\x50\x68\xbd\x65\x1a\x38\xc1\x14\x8c\x39\x4e\x8d\x84\x16\x2b\x34\x05\xc0\xd1\xa6\x90\x59\xb6\xe2\xe3\xce\x78\x22\x27\xc7\x49\xd4\x30\x8b\x72\x39\x1f\xe7\xab\xa0\x5a\xe9\xcc\xe2\x9f\xdc\x8b\x47\x12\x88\x92\x20\x50\x09\xc0\x49\x0c\x84\x04\x45\xe0\x12\xc5\xb3\x14\xcd\x40\x20\xe1\x3c\xce\xe3\x88\xe4\x48\x16\x31\x8c\x44\x52\x3c\x8d\x93\xb8\x42\x21\x45\x61\x70\x05\x57\x71\x9a\xc5\xbd\x68\x45\x3d\x29\x5a\xdd\xda\x8b\x62\x71\x9c\x66\x82\xdf\x06\xba\xbb\x7a\xf2\x70\xaf\x47\xe3\xd5\x95\xbd\xa8\x67\x57\x03\x8f\xe2\x55\x31\x37\x5e\xc4\x8c\x41\x8a\xae\xf6\x0c\x4d\xc9\xce\xe2\x9d\x64\x5d\x19\x88\x8e\x66\xc1\x86\x55\xab\x2f\x5b\x16\xad\xbc\xc5\xad\x52\x82\xe0\x90\x9a\x29\x9a\xab\x6e\x09\xc6\x88\x39\xef\xd4\x45\x65\xd5\x8c\x0d\xd2\x1d\x26\x57\x6b\xb3\x4b\x21\x45\x4a\xe5\xa9\xc0\x59\xab\xd5\x4a\x10\xbf\x62\xbc\x8a\xf4\x8c\x94\x27\xe2\x8f\xf4\x8c\x94\x8f\x89\x57\x01\xf1\xf3\xd3\xe2\xd5\xbd\xe7\x71\x04\xe1\xeb\xf6\xb6\x5f\x8c\x57\xff\x50\xbc\x10\x3e\x60\xae\xee\xc1\xbf\x8d\x57\xcb\x31\x7c\x63\xda\x62\xc7\x88\x8f\xdb\x71\x5c\x37\x53\x72\x29\x47\x88\x75\x22\xe1\x4c\xcb\x4e\xaa\x10\x6f\x2f\x0c\x92\x4b\xdb\x78\x41\x5a\xd1\x9c\xbc\x1e\xa6\x34\x60\xb1\x90\x25\x40\xb6\x46\xa6\x1a\x8c\xd8\x53\x4d\x23\x25\x2d\x04\xa1\xa3\xd8\xcc\x28\xb9\x5e\x64\x32\xa2\x50\xfd\xdc\x78\xc5\x30\x0c\x43\x33\x90\x41\x50\x41\x04\xce\x11\x32\xcd\x72\x38\xcd\x02\x82\x61\x15\x1e\x51\x14\x4d\x22\x84\x68\x96\x03\x32\xe4\x21\xcd\x41\x48\x02\x1e\x49\xb8\x8a\x38\x92\xa2\x69\x55\x79\xd9\x3d\xe6\x36\xfa\xc3\x7c\x77\x4f\xc9\xbd\x12\xa6\x00\x43\x5f\x7b\x4b\x3b\x7d\xd8\x00\xf3\x1e\xf7\xb8\x8d\x51\x05\x2e\x53\x5d\x54\x47\x52\x9e\xc8\x08\x64\xbb\x35\xac\x59\xf9\xf1\xb0\x83\xe3\x6a\x9a\xb3\x0b\x59\x76\x8c\x8b\xb5\x65\xae\xfd\x26\x74\x48\x61\x1f\xa3\x3c\x65\xf2\x4d\xf8\x99\x0f\x89\xd0\xff\x95\x3f\x86\xd7\x5a\x2c\x53\xfc\xc6\xc6\xc4\xb8\x92\xec\x20\x82\x6c\x52\x88\x4f\x10\xf5\xd5\x34\x5e\xe8\xd5\x56\xc0\xca\xbd\xd7\x53\x85\x1c\xbe\x4a\x26\xf1\x79\x3e\x3d\x1d\xcf\x24\xd5\x48\x36\x62\x9d\x4e\x76\xc6\x34\xf5\x64\xfc\x7d\x9c\x5a\x39\xb1\x74\x39\xd6\x99\xa5\xcc\x6a\x45\xb1\x3a\x0d\x76\x0a\xcc\x42\x2f\x9b\x99\x35\x8a\x95\x10\x71\xe9\x44\xa1\x4f\xe3\xd2\x11\xcf\x07\xbf\x7c\x9c\x9b\xea\x6f\x71\xbc\x80\xe7\xd2\x6b\x67\xb0\x2c\x01\xa3\x8b\xc3\xf5\xd4\x04\x7c\x29\xb3\x5a\x14\x12\xeb\x32\xed\xc4\x45\x39\xe1\xf1\x48\x6a\x8e\x55\x9e\x74\xdf\xa8\xe2\xe1\xfe\xe6\x45\x22\x6e\xd8\xfa\x03\xf8\x4b\xd6\xba\x51\x7d\x00\xbf\x20\xfc\x73\x7d\xca\x17\xfd\x6e\x3c\xba\x2c\xca\x93\xde\x55\x36\x6f\xc9\xe2\xd1\xb9\xd8\xe8\x42\x4c\xf6\xc1\xbb\x4b\x16\xff\xed\x54\x01\xe9\x38\xa0\x9c\x59\x54\x9d\x91\x0d\xab\x75\xa2\x29\x2b\x70\x2d\xe3\x83\xfa\x5a\x29\x56\x97\x7c\x41\x1f\xcc\x7a\xb3\x31\x49\x57\xf1\x37\x03\xac\xf3\x73\x23\xab\x2d\x65\x7a\x20\x4b\xea\x60\xb8\x30\x98\x01\x14\x93\x24\x04\x78\x8c\x51\x60\x82\xa8\xc7\x99\xd1\x7b\xf2\x93\xd7\x09\x12\x50\x39\x82\x23\x39\x4a\xa6\x19\x44\x49\x38\x41\xa9\x14\xc1\xd2\x2a\x41\x31\x34\x87\x43\x09\x4a\xaa\x0a\x20\x22\x25\x5e\x82\x0c\x90\x70\x92\xe3\x59\x92\x66\x11\xcd\x22\x24\xc9\x04\xee\xf9\x5d\xe2\x31\xbf\x4b\xdc\xf6\xbb\x2c\x75\xcd\xf1\x7a\x57\x8f\x1f\x6b\xfb\xa8\xe7\xbd\xb2\x3a\xf0\x3e\x11\x3a\x9f\x02\x3d\xaf\x3a\x49\xd5\xdf\x7b\x68\x00\xd8\x77\x87\x23\xcc\xa2\x32\x43\x54\xec\x6d\x35\xb1\xdf\x46\x99\xb8\x92\xee\xa8\x7c\x3c\x1b\xaf\x75\xd5\x56\x8f\x4c\x56\x1b\x24\x5c\x2e\x7b\x13\xba\x30\xd3\xb2\x69\x3e\x37\x33\x16\xc5\x71\x0d\x34\xf2\x70\x25\x9b\xb9\x6a\x72\x3e\x4b\xcb\x89\xba\x5c\xfc\x5a\x9e\xf7\x51\xcf\xf7\xa8\xb5\x17\x97\x85\xb1\xf9\x4c\xcf\xfb\x89\x27\x14\x6f\x56\x68\x3e\xd1\xf3\x09\x4f\xf2\xbc\x1c\x75\xb8\x3f\xa0\xba\x79\xd5\xf3\x76\xe8\x55\xd3\x26\x3a\xa6\x82\x38\x56\x2d\xcd\x92\x19\x38\x99\x57\x16\x5c\x8f\xad\xd0\xf1\x65\xa7\x66\x90\x6f\xd5\xba\xd0\x6c\x67\x40\x5b\x59\xe2\x22\x4f\xd8\xc5\x74\x2f\x56\x67\xcc\x44\x7c\x51\x87\x53\xe9\x3d\x37\x52\x9a\xeb\xb1\xdd\xc9\x27\x9a\x02\x3b\x1b\x4c\x84\xd1\xe4\xb3\x4f\xab\x10\x12\x81\x38\x42\x91\xa0\xb4\xf1\xba\x12\xc1\x42\x5c\x26\x01\x85\xcb\x90\x05\x0a\x07\x65\x5e\x92\x59\xc0\x91\x40\xe5\x55\x1a\x92\x92\xc2\xf0\x48\x86\xa4\xc2\x71\xaa\x84\x23\x99\x96\x3d\xbf\x49\x3e\xe6\x79\x6f\x6e\x23\x00\x86\x27\x03\x0f\xe9\xef\xaf\x1e\x3f\xbe\xfb\x51\xcf\x7b\xe5\xb9\x53\xde\x27\x42\x5d\x20\xc0\xf3\x26\x73\x73\x03\x38\x85\x74\x21\x45\xb5\x56\x4b\x07\x57\x92\x89\x96\xa8\x32\x8e\x44\x1b\x94\xb4\x2e\x5a\x69\x2d\x31\x8d\x19\xad\x5e\x71\xbc\x92\x1d\x9a\xd2\x4b\x2a\x31\x5e\x39\xc3\x15\x53\x54\xe8\x5e\x8e\x12\xa9\xa4\x21\xdb\x2a\xc5\x88\xc2\x20\x9e\xae\x37\x2b\xf6\x84\x53\xbb\xc9\xaf\xe5\x79\x1f\xf5\x7c\x8f\x5a\x7b\x01\x1f\x31\xc2\x13\x3d\xef\x67\xd6\xa3\x3f\xc2\xf3\x46\xf5\x7c\xc2\x93\x3c\x2f\x7b\x34\x01\xc5\xbb\x65\xf1\xdf\xb5\x34\x55\xa4\xfa\x4a\x5f\xa1\x94\x2c\x17\x94\x4c\x75\x69\xd4\x32\x31\xab\x1d\xeb\xa1\x34\x37\xcc\xaf\x4c\x61\xa6\x4e\x5b\xed\x46\xce\xee\x14\x10\xca\x0e\x3b\xfc\xd4\x96\xba\x1c\x1a\x66\x50\xbb\x8e\xe2\x65\x81\xee\x14\x32\xb1\xf2\x40\xc8\x56\x6b\x23\x23\xc9\xe6\xde\x32\x84\xf0\xc9\x39\x2f\x02\xac\x04\x11\x4d\x13\x0a\xc4\x01\x4e\x43\x85\x24\x54\x5c\xe2\x21\x54\x54\x05\x57\x19\x82\x44\x2a\xc9\x22\x89\xe2\x18\x09\xe0\x12\x4e\x51\x32\xe0\x09\x92\x23\x19\x1c\x51\x34\xad\xb0\x9e\xe7\xa5\x1e\xf3\xbc\x37\x4b\xe2\x80\x05\x20\xd8\xf1\x7a\x17\x8f\x5f\x52\xf0\xa8\xdf\xf5\xa7\x01\x67\x7e\x37\x42\x77\x66\x90\xdf\xed\x76\xd5\x75\xd9\x1a\x57\x06\xea\x48\x67\x0c\xab\x12\x33\x13\xea\x7c\x92\x1b\xd7\xe6\xc4\x58\x5d\x19\x14\x6e\xd2\xb3\x76\x8d\x5d\x83\xee\xb8\xc2\x4d\xcd\x74\x8c\xe9\xcc\x34\x0a\x0c\xf3\x89\x76\x69\xd9\x32\x2b\x2c\x60\x13\x2d\xb1\x82\x58\x3c\x8b\x3b\xa8\xbd\x68\xa0\xe1\x28\xf7\xb5\xfc\xee\xa3\x7e\xef\x51\x5b\xcf\x53\xb1\x52\xf7\x89\x7e\xf7\x33\xbb\x2c\x3f\xc2\xef\x46\xf5\x7b\xc2\x93\xfc\x2e\xbd\xbc\x89\xe8\x9a\xdf\x25\xd2\x19\x6e\x38\xa3\x87\x54\x87\xce\xce\xa7\xf0\xfd\x6d\x26\x4c\xd8\xe9\xba\x37\x92\x9c\xe9\x84\xeb\xa1\x52\xbe\x0c\x8d\x11\xe2\x9c\x76\x6e\xf8\x96\x87\xf1\xc5\xdc\x60\xcc\x72\xa9\xbb\xd6\x8c\xa1\x9c\x82\xc9\x18\x8f\x96\x46\x2d\x49\xce\xf9\x44\xa9\xd0\x31\x2c\x9c\x34\xe9\xc4\x27\xd7\x78\x65\x55\xe1\x38\xc0\x20\x85\xe6\x58\x99\x46\x0a\xc7\x29\x08\xe2\x48\xc2\x71\x0e\x70\x32\x54\x49\x4e\xc6\x59\x1a\x47\x2c\x4b\xe1\x08\xa7\x15\x44\xca\x04\x0b\x58\x06\xf1\x10\x21\x0e\x21\xcf\xef\xd2\x8f\xf9\xdd\x5b\x8f\x5a\x65\x01\xcb\xb3\xdc\x15\xc7\xcb\xb3\xfc\xcb\xe9\xcb\x58\x1e\xf5\xbc\x29\xdf\x94\x9f\x79\xde\x08\x7d\x86\x41\x9e\xb7\x34\xae\x0e\x94\x2a\x5a\x17\xe5\x76\xaa\x5d\xe1\x94\x56\x6d\x94\x74\x52\x75\xca\xc9\x64\x13\xeb\xbc\x02\x2b\xa3\x1a\x13\x7b\x2b\xb0\x31\xa7\xf8\x9e\x6f\x9b\xcd\xa1\x94\x14\x3a\xb6\x5c\xeb\x66\x63\x43\x26\xa5\xbc\xb5\x52\x4d\x98\x7c\x57\xba\x76\x3b\x21\xd8\x19\x12\x6f\xcf\x87\xd9\xc2\xd7\xf2\xbc\x8f\x7a\xbe\x47\xad\x3d\xc7\x77\xb4\xe5\x33\x6b\x0d\x9f\xd8\x2f\xf8\x11\x9e\x37\xaa\xe7\x13\x9e\xe4\x79\xa3\x56\xfc\xb7\x9e\xf7\xbd\x37\xca\x76\x9a\x19\x7b\x98\x49\x0d\x5a\xc3\xb7\x4c\xab\xd9\x13\xd8\x5a\x73\x5e\xa8\xad\x05\x5b\x9f\xb4\x87\xb4\x88\x16\x8b\x75\xec\xcd\x6a\x14\xd7\xc6\x2c\x95\x25\x96\xcb\x14\x9b\x11\xdb\x89\x8a\x19\x1b\x74\x54\x50\x6b\xa5\x35\x8e\x6c\x17\x52\x9a\x56\x88\xf3\x7c\xca\x32\x9f\xf4\x64\xa6\xd3\x17\x40\x79\x2f\x48\xb6\x1d\xe8\xd8\xc7\x7f\xf7\xa7\x23\xb4\xde\xbd\x48\x29\x51\x2e\xd5\x1b\x35\x21\x5b\xba\xf5\xce\x27\xa1\xd0\x10\x6b\xdb\xf7\x2e\x95\x4b\x85\xee\x31\xc4\xdf\x30\x0c\xc3\x84\x64\xf2\x08\xda\x19\x42\xac\x52\xcb\x16\x85\x5a\x17\xcb\x8b\x5d\xec\xbb\xae\x9c\x51\xab\x99\xd6\xb4\x3f\xd6\xb5\xdd\xdb\x45\x7d\xdf\x9f\x44\xb5\x0f\xea\x25\xca\x2f\x21\xbe\x49\xfd\x2e\xce\xb9\x6c\xdb\xbe\xaf\xfd\xc3\x1b\xae\xfb\x87\xf7\x5a\xf7\x8f\x5f\x60\xdd\x7f\x0a\x77\xa7\x68\x2f\x31\x17\x89\x30\xac\x59\xca\x56\x9b\x22\xf6\xfd\x30\xfc\x15\x3b\x8c\xdf\xfd\xed\xdd\x70\xa7\x68\x9e\x33\xad\x77\x33\x7e\xd7\xa4\xee\xdf\x79\x7b\xfa\x2a\xb6\xeb\x97\x9f\xcc\xd9\x65\x24\xd7\x38\xbd\x42\x56\x68\xce\x03\x5f\x43\x77\xf3\x45\x6f\xcf\xe5\x3e\x08\xcd\x35\xfe\xaf\x92\x76\x53\x02\x9e\x4a\x4b\x6b\x57\xdb\x77\x8c\x64\x4b\x49\xb1\x73\x83\x87\x44\x4d\x14\x1a\xa2\x37\xf4\x14\x0a\x56\x2e\xf9\x8d\xa1\x59\xcf\x96\xd2\x98\xe4\x58\x08\x1d\x5b\x57\x30\x35\x9e\x8d\x3d\x4e\x8f\x07\x27\x1c\x45\x01\x76\x2d\xad\xfb\xdb\x57\x32\x47\x26\xe7\x00\xe2\x98\x92\x93\xb5\xc2\x29\x3d\xde\xe0\x57\x6c\xfb\x47\xdf\x46\xb3\x39\x9a\xc8\xe7\x02\x93\xd6\x7d\x15\xa1\xfb\x08\x9c\x9a\xb6\xa3\x59\xc8\xbe\x48\xe7\x11\xb4\x70\xb4\x1e\xdd\xf0\x03\x6b\x67\xc4\x9a\x88\x1d\xc3\xc8\xd6\xb1\x52\xb9\xe1\xc6\xf0\x3f\xce\x48\x1f\x40\x7b\xf0\x04\x9a\x37\x60\xc2\x11\x7b\x6c\x2b\x9b\xbb\x2e\xc9\x53\x9f\x4c\x90\xf5\x2c\xd2\x0e\xc0\xc2\x11\xe8\x8d\x3f\x23\x73\x2b\xd8\xcb\x57\xaf\xcb\xd8\x40\x8a\xf6\x80\x25\xed\x21\x84\xa3\xdf\x1b\xbb\xd7\xd7\x57\x0c\x4e\xa7\x86\x2e\x7b\xfe\xd9\xb4\x94\x80\xb8\xd9\x47\x1b\x63\x75\xaf\x47\xa0\x74\x1b\xb6\x3d\x82\x7d\xe0\x8e\xc9\x46\xaa\x8a\x64\xbf\xed\x9f\x87\x11\x5d\x79\xc5\xbe\xb9\x37\x7f\x0b\x22\x56\x57\x9e\x44\xa6\xae\x84\x26\x70\xe7\x0b\x36\xe4\x45\x20\xda\x9c\xf6\xa7\xcf\xa2\x7b\x0b\xeb\x98\xf4\x80\xdc\x21\x12\x27\x97\x19\x70\x56\xcf\x63\x60\x0b\x2b\x40\xa7\x23\xb2\x70\x0c\xe1\x12\x13\xe6\x74\xa3\x95\x03\x33\x12\x0f\x5b\xe2\x0f\x30\xa2\x0a\xff\xba\xa0\xed\xad\xb5\xbb\xb1\xf3\x71\x59\x9f\x82\x3b\x26\xd9\xfb\xdd\xef\xfd\x2e\x52\x74\x2c\xd7\x67\x91\x75\x06\x33\xa4\x7b\xbe\x40\xa0\xe3\x4d\x89\xf3\xc8\xb4\x1e\x60\x44\x57\xc9\x5b\xea\xe7\x58\xca\x06\x89\x04\xed\x3b\xf3\x85\x8b\x04\x9f\x03\xf3\x51\xae\x20\x1f\x9d\xc7\x63\x6f\x12\x68\xaa\xea\x03\x41\xeb\x1c\x54\x28\xe2\xdc\x91\xd7\x48\x73\x69\x47\xd6\xd3\xc4\xe7\x83\x77\x8b\x48\xdf\xf0\x30\x94\x3e\x47\x8e\x27\xd0\xc2\x52\x79\x53\x9a\xcf\xa1\x2d\x14\x4d\xd7\x69\xd9\x51\x6c\x98\xe6\x68\x3e\x7d\x8c\xa2\x53\x58\xa1\x67\xd4\x5b\x80\x04\xd0\x37\x85\xba\xd5\x77\xf4\x31\x7a\x0a\x85\x7e\x68\xe1\xec\x76\x4b\xe0\x2b\xe6\x27\xf9\x15\xdb\xba\x78\xd9\x30\x6d\xa4\xf4\xa1\x13\xc0\xc4\x13\xfc\xf6\x16\xce\x2d\x8a\xef\xcc\x8e\x36\x50\x9f\x26\xdd\x3b\x04\x7b\x53\x6e\xfa\x44\x41\xab\xbe\x2f\xe5\xb0\xfb\xe6\xa4\x0f\x15\xc5\x42\xb6\xfd\xa8\x40\x6f\x22\x38\x59\x38\x6f\x2f\xfb\x96\xaa\xde\xc0\x3b\x68\x7f\x5c\x0f\xae\xc1\xbe\x4d\xf1\x05\x2b\x3b\x05\xb8\xcd\xc2\x37\xf0\x9c\xf5\x34\x7a\x51\xe4\x2a\xd4\x9b\x69\xff\x66\xd0\x0d\x42\xb7\x39\xd4\x06\xe4\x5e\x89\x9e\x44\xed\x25\xd0\x37\xd3\xb7\xb0\x9a\x7c\x04\xfc\xd9\xca\x70\x02\x3a\x4a\xbe\x19\x0c\x6e\x3c\x35\xad\x8d\xe3\x5b\x20\xcb\xd6\xcd\xc9\xf3\x05\xed\xc7\x70\x9b\x7c\xdf\x0d\xe1\x99\xd9\xba\x9e\xf0\x45\x8e\x08\xf2\x3f\xc2\x71\x93\x93\xa3\xb1\xe1\x99\x98\x5a\x68\xa1\x9b\x73\xfb\x53\xb8\xb9\x84\xec\x26\x5b\x97\x6e\x0a\xcf\xdf\xae\x88\xf2\x61\x3c\xed\x10\xdc\xe4\x23\xb0\xfc\x78\x0a\x7a\x1f\x6f\x3f\xc4\xb4\xfd\xd0\x2f\x2e\x80\xef\x35\xf0\x53\xa0\xa7\x4b\xa8\x27\x59\xf8\x35\x14\x61\x78\xb8\xb1\xae\xbb\x8a\xec\x79\xe1\xeb\x1c\x70\x28\xda\x6f\x07\xb1\xe3\xc5\xf6\x47\xa8\xcd\x39\xfc\xc8\x4b\x7d\x37\x89\xdb\x07\xf2\x5d\x85\xb1\x2f\x99\xe6\x28\xb2\x94\xaf\xc0\xbc\x99\x22\x7c\xff\xae\x20\x07\xea\x86\x8d\xfd\xfc\x9f\xff\xc1\x5e\x6c\xd3\x50\x8e\xb6\x37\x5f\x7e\xfd\x72\xd0\xca\xf9\xf1\xe3\x15\x0b\x1e\x28\x9b\x4a\xb8\x81\xde\xe6\x48\xf0\x50\xc9\x9c\x6b\x03\x27\x14\xfa\x93\xa1\xd7\x09\x38\x19\xea\x23\x61\x57\x14\x77\x95\x0c\xfb\x13\x23\xc9\xd0\x9d\x01\xba\xd2\x57\x8f\xf6\xed\x52\xf9\xcf\xe9\x0f\xd8\xa2\xc5\x52\xe5\x9a\x98\x4d\x97\xf6\x7b\x72\x58\x4d\x4c\x89\x35\xb1\x94\x10\xeb\xbe\x6d\x2a\xf7\x6a\xb9\x84\x35\x2b\xc9\x8d\xca\xd4\xc4\x7a\xa3\x96\x4d\x34\x36\x3f\x25\xc5\x82\xd8\x10\xb1\x84\x50\x4f\x08\x49\xf1\xca\xc6\xe6\x66\xdd\x71\xfa\xb5\xef\x2b\xc5\x3c\x4f\x18\xa7\x78\x6e\xec\x5a\x06\x51\x72\x2a\x1f\x7f\xd9\xe8\xa2\xb0\xb6\x89\xfe\x8d\x2d\xde\x40\x49\x6c\x97\xb2\xff\xb8\x1c\x8e\xe9\xb8\x24\x85\x5d\x95\xe0\xba\xc2\xdc\x27\x81\xf3\xa2\xd2\x3f\x28\x86\x00\x62\x4e\x65\x71\xa1\x0c\xf6\x5c\xa5\xf0\x97\x38\xbe\x82\x40\x82\x55\xe3\xac\x86\x14\x46\x3b\x30\xa8\x28\x48\xc1\xc6\x70\x32\x87\x86\xb1\x3e\xa1\x34\x9b\xc2\xc4\x4e\xb6\xde\xa8\x7b\x34\x7b\x9c\xfd\x3e\x42\xeb\xfe\x02\x1a\x73\xd4\xdf\x40\x44\x58\xb2\x56\xae\x1c\x13\x7e\xb8\xcb\x37\xd2\x6b\x91\xf8\xcd\x1d\xef\x47\x70\x19\xf6\x1f\xbb\x10\xe9\x0d\xf7\x63\xfe\xee\xca\xed\xea\x67\x23\x24\x79\x00\x2d\x28\x3b\xc8\xc2\x16\xd0\x5a\xeb\x13\xed\x3b\x41\xd3\x3f\xf6\x3b\xa5\xaf\xb7\xa1\xb8\x48\x6f\xc1\xf9\xcd\xd7\x09\xec\xa7\xf6\x70\xf8\x62\x35\xed\xeb\x13\x0d\xd9\x4e\xdf\x80\x9b\x7f\xdc\x4c\xfb\xe5\x15\x7b\xc1\x5f\x7e\xfc\x71\xae\x2b\x3e\x40\x97\x94\xe5\x92\xa4\x4f\x3b\x3e\x46\x68\xbd\x99\xf1\x13\x79\xee\x0b\x26\xb6\xae\x4d\x36\xb9\x7e\x08\x81\xee\x6e\xba\x20\x0d\x86\xfa\x11\x42\x96\x98\x87\x0c\xdb\xc4\xee\x30\xc3\x97\x48\xd7\x06\x0e\xa6\x4f\x1c\xa4\x21\xcb\x37\x6b\x3f\x7f\x62\x4b\x84\x2d\x75\xc3\xc0\x66\x73\x64\xad\x31\x69\xbd\x83\x6f\x9b\x98\x33\x80\x0e\xa6\xdb\xd8\x72\xb0\xff\x55\xb7\x31\x67\x80\x30\x55\xb7\x6c\x07\xd3\x1d\x34\xc6\xf4\x89\xfb\x8b\x6c\x8e\xa7\xa6\xad\x3b\x68\x23\xcb\x10\x64\x9d\x08\xd7\x03\xbe\xef\xd2\xf8\xf1\x9b\x6f\x1a\x2f\x26\x99\x9b\x29\xdc\x79\xae\xf1\x7c\x85\x94\x8d\x20\x37\x52\xfd\xce\xf0\x3f\xb6\xbd\x8e\x9b\x31\x47\x4d\x14\x01\xe3\x2e\x23\x3b\x4a\xc5\x37\x60\x6c\x73\x6e\xc9\xd1\x20\xed\x72\x4e\x97\x62\xaf\xcc\x17\x78\xff\xd6\xbb\x56\xbc\x5e\x88\x7a\xb5\x80\x29\xd0\x81\x9b\xa8\x85\x29\xf3\xf1\xd4\x95\xb3\x81\x1c\xe4\xba\xc5\xff\x1b\x00\x00\xff\xff\xbb\x1b\x42\x1b\x2d\x2d\x01\x00") func pathed_paymentHorizonSqlBytes() ([]byte, error) { return bindataRead( @@ -486,7 +486,7 @@ func pathed_paymentHorizonSql() (*asset, error) { } info := bindataFileInfo{name: "pathed_payment-horizon.sql", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} - a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x7d, 0x5e, 0x6d, 0x29, 0xf1, 0x21, 0xc0, 0x53, 0xa0, 0x42, 0x39, 0x22, 0x12, 0x4d, 0x39, 0x20, 0x5, 0x1f, 0x7a, 0xa2, 0xb3, 0x63, 0xc7, 0xe5, 0xdc, 0x14, 0x31, 0x88, 0xd2, 0x52, 0x83, 0x3c}} + a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xe5, 0x86, 0x10, 0x7e, 0x89, 0x23, 0x9, 0x60, 0xa7, 0x40, 0x1d, 0xb9, 0x8a, 0xc, 0xdf, 0x2b, 0xa1, 0x67, 0x1e, 0x67, 0x1f, 0x4c, 0x88, 0x8b, 0x5e, 0x42, 0x72, 0x5b, 0xaa, 0x66, 0xd5, 0x3}} return a, nil } @@ -510,7 +510,7 @@ func paths_strict_sendCoreSql() (*asset, error) { return a, nil } -var _paths_strict_sendHorizonSql = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\xbd\x79\xb3\xa2\xc8\xd2\x38\xfc\xff\x7c\x0a\xa2\xe3\x46\xf4\x4c\xd8\x3d\x42\xb1\xf7\xfc\xe6\x89\x00\xc5\x7d\xdf\xf5\xc6\x84\x51\x40\xa1\x28\x8a\x02\x6e\xe7\xc6\xf3\xdd\xdf\x10\x70\x43\xdc\xd0\x73\xfa\xf4\x7d\x1f\x6e\xdf\x33\x2a\x45\x6e\x95\x99\x95\x95\x95\x55\x7c\xff\xfe\xdb\xf7\xef\x58\xc5\xb4\x9d\x81\x85\xea\xd5\x02\xa6\x42\x07\xca\xd0\x46\x98\xba\x98\xcc\x7e\xfb\xfe\xfd\xb7\xed\xfd\xe4\x62\x32\x43\x2a\xa6\x59\xe6\xe4\xd0\x60\x89\x2c\x5b\x37\xa7\x18\xff\x27\xf3\x27\x71\xd4\x4a\xde\x60\xb3\x41\x7f\xfb\x78\xa0\xc9\x6f\x75\xa9\x81\xd9\x0e\x74\xd0\x04\x4d\x9d\xbe\xa3\x4f\x90\xb9\x70\xb0\xbf\x31\xfc\x2f\xf7\x96\x61\x2a\xe3\xf3\x5f\x15\x43\xdf\xb6\x46\x53\xc5\x54\xf5\xe9\x00\xfb\x1b\xfb\xda\x6c\xa4\xb8\xaf\x7f\xed\xc0\x4d\x55\x68\xa9\x7d\xc5\x9c\x6a\xa6\x35\xd1\xa7\x83\xbe\xed\x58\xfa\x74\x60\x63\x7f\x63\xe6\xd4\x87\x31\x44\xca\xb8\xaf\x2d\xa6\x8a\xa3\x9b\xd3\xbe\x6c\xaa\x3a\xda\xde\xd7\xa0\x61\xa3\x13\x34\x13\x7d\xda\x9f\x20\xdb\x86\x03\xb7\xc1\x0a\x5a\x53\x7d\x3a\xf8\xcb\xa7\x1d\x41\x4b\x19\xf6\x67\xd0\x19\x62\x7f\x63\xb3\x85\x6c\xe8\xca\xb7\x2d\xb3\x0a\x74\xa0\x61\x6e\x9b\x09\x85\x86\x54\xc3\x1a\x82\x58\x90\xb0\x6c\x0a\x93\x3a\xd9\x7a\xa3\x8e\x95\x4b\x85\xae\xdf\xfe\xcf\xa1\x6e\x3b\xa6\xb5\xe9\x3b\x16\x54\x91\x8d\x25\x6b\xe5\x0a\x96\x28\x97\xea\x8d\x9a\x90\x2d\x35\x8e\x1e\x3a\x6d\xd8\x57\xcc\xc5\xd4\x41\x56\x1f\xda\x36\x72\xfa\xba\xda\xd7\xc6\x68\xf3\xd7\x47\x20\x54\xdc\x4f\x1f\x81\x72\xab\x57\x1f\xc7\xa0\x87\xed\x71\xee\x3c\x02\xb7\x8a\x7c\x0d\xd9\x51\xab\x03\x70\xb7\x79\xb6\x94\x94\x3a\x47\x2d\x7d\xb0\x2e\x55\x7d\xa4\x69\x48\x71\xec\xbe\xbc\xe9\x9b\x96\x8a\xac\xbe\x6c\x9a\xe3\xeb\x0f\xda\xfa\x60\x8a\x2c\xf7\x11\x9f\x9b\xeb\xed\x4d\x4d\xf3\x9b\xdb\xc8\x30\xb6\x16\xe3\xd2\xfa\xc8\x43\xc8\xba\xb7\xb5\x01\x6d\xa7\x3f\x31\x55\x5d\xd3\x91\xda\x37\x90\x3a\xb8\xff\x59\x79\xb1\xb9\x93\x3a\x7d\xaa\xa2\x75\xff\xa8\x7f\xa7\x36\x74\x6d\xdd\xee\x9b\xd3\xbe\xae\x3e\xf2\xb4\x39\x43\x16\xdc\x3f\xeb\x6c\x66\xe8\x89\xa7\x0f\x94\x3c\x45\xc5\x63\xcf\x7a\x52\x76\x1f\xb4\xd1\x7c\x81\xa6\xca\x43\x2c\x1c\x3d\x3e\xb3\xd0\x52\x37\x17\xb6\xff\x5b\x7f\x08\xed\x61\x44\x50\xcf\x43\xd0\x27\x33\xd3\xda\x7a\x24\x7f\x58\x89\x0a\x26\xaa\x2c\x15\xc3\xb4\x91\xda\x87\x0f\xe9\xe2\xce\x9e\x23\xa8\x92\x6f\xcc\x11\x88\x3e\x7e\x12\xaa\xaa\x85\x6c\xfb\xfa\xe3\x43\xc7\x52\xdd\xa1\xb7\x6f\x98\xe6\x78\x31\xbb\xa3\xf5\xec\x16\x49\x5e\x2b\xa8\x5b\x0f\x02\xde\x8d\x3b\x77\x3f\xb0\x75\x95\x5b\x9f\x71\x5f\xd3\x1d\xf8\x08\x8f\xdc\xe5\x5d\x77\x0f\xb9\xa3\xcb\x03\x48\x8e\x47\xa3\x5b\x4f\xcc\xb6\x0f\x0c\x9d\x9b\x3d\x60\x9f\x38\x20\x79\x73\x53\x8d\x86\x7b\x4b\xbf\xa7\xb1\xe9\xd1\x61\xde\x6c\xa8\xdb\x4e\xdf\x59\xf7\x67\xb7\x41\x6e\x5b\x9a\xb3\x7b\x5b\xa2\x7b\x9b\xed\x46\xd3\xeb\x8d\xe5\xcd\x5d\x03\xd4\x96\xe7\x9b\x5e\xec\xde\xc1\xd8\x0b\x13\xb6\xd2\xb6\xed\xc5\x2d\xcc\xfb\xc6\x8a\xa9\xa2\x7b\x42\x15\x6f\x2c\xbd\x12\xa5\xf8\x83\xed\xec\xce\xd0\x67\x8c\x36\xfd\x25\x34\x16\xa8\xbf\x75\x34\xe8\x0a\xe0\x40\xcb\xbb\x31\x84\x8c\xe1\xfd\x19\xb4\x1c\x5d\xd1\x67\x70\x7a\x35\xe2\xba\xf5\xe8\xc3\x34\xec\xc7\xe0\x47\x29\x08\x7f\xf0\x61\xfc\x6e\x77\xdf\x83\xcf\x6b\xf8\xee\xf0\x3d\xf5\xdb\xea\x9e\xff\x71\x3b\xa2\xed\xe2\x75\x57\x7d\xfb\x77\x52\x30\x30\xad\x59\x7f\xa2\x0f\xfc\x10\xe7\x0a\x09\x81\x96\x77\xf3\xf8\x78\x90\x7e\x37\xe4\xdd\xe0\xea\xc7\xdd\xd7\xc0\x07\x9a\x5e\xc5\x71\xaf\x01\x78\x4f\x27\xca\x85\x66\xb1\x84\xe9\xaa\x87\x3e\x29\xa5\x84\x66\xa1\x71\x27\xec\x0b\x8a\xfd\x02\xc8\xbe\x4a\x5d\x87\xe4\x7e\xbb\x00\xc8\x73\x48\xd7\xdb\x04\x7c\xcb\xf5\xc6\x61\x93\x02\xff\x89\xba\x54\x6d\x4a\xa5\x44\x84\x4e\xd8\xce\xe8\x6c\x34\x7f\x18\xf3\x09\x90\xbb\x9f\x56\xd1\x9d\x6d\x0f\x93\x86\xbb\x39\xbc\xe0\xaa\x1e\xe1\x2f\x1c\xc4\x7d\xcf\xfa\xe1\xf5\x7d\x8d\xfd\x58\xfa\x6e\xde\x7c\xb7\xf5\x08\x2f\xde\x23\x77\xb6\xf5\xad\xfb\x7e\x7a\x76\xee\xe0\x1e\x8a\x02\x8e\xef\x7a\xe3\x23\x3f\x76\xa3\x61\xc0\x23\xf9\xad\x85\x74\xba\x26\xa5\x85\x46\xc8\x13\x13\x7d\x3b\x0d\xd4\x15\xf4\xfb\x74\x31\x41\x96\xae\xfc\xfb\x9f\x3f\xee\x78\x0a\xae\x23\x3c\x65\x40\xdb\xf9\x1d\x4e\x37\xc8\x70\x53\x84\x77\x3c\xa1\xe9\x56\xe8\x23\xa9\x66\x29\xd1\xc8\x96\x4b\x57\xf8\xe9\xc3\xc1\xe0\x40\xdd\x37\xec\x8c\xd0\x2b\x30\x76\xdc\x3d\x01\xc3\x4d\x8c\x6c\x1f\x3f\x10\xff\x0d\x7b\x84\x11\x97\xf5\x3b\x20\x48\x9d\x86\x54\xaa\x07\x40\x18\xb3\x81\x3d\x37\x76\x9a\x9b\xc8\x48\x45\xe1\x0c\xc3\x5f\xbf\x79\xd9\xe1\x12\x9c\xa0\x1f\xbb\xdf\xb0\xc6\x66\x86\x7e\xf8\x8f\xfc\x85\xd5\x95\x21\x9a\xc0\x1f\xd8\xf7\xbf\xb0\xf2\x6a\x8a\xac\x1f\xd8\x77\x37\x69\x9c\xa8\x49\xdb\xfe\xf2\x21\xef\xe0\xfd\x76\x02\xf1\xf4\xa6\x0f\x38\x51\x2e\x16\xa5\x52\xe3\x0a\x64\xaf\x01\x56\x2e\x9d\x02\xc0\xb2\x75\xec\xeb\x2e\x1d\xbc\xfb\xcd\x76\x81\x7c\x0d\x62\xde\xb1\xef\xe3\xdc\x4b\xe8\x26\x3f\x27\xb2\x2c\x95\x1b\x01\x79\x62\xed\x6c\x23\xb3\x27\xeb\x38\x2f\x7c\x82\xfe\x00\x25\x40\xc8\x23\xcc\x9f\x01\x71\x05\x50\x29\xc4\x67\x83\x7a\xb5\x80\xcd\x2c\x53\x41\xea\xc2\x82\x06\x66\xc0\xe9\x60\x01\x07\xc8\x15\xc3\x9d\x79\xec\x63\x72\x6f\x2b\x9a\x4f\xfe\x4e\x57\x0f\xf4\xef\xfa\x36\x4c\x96\x7b\xcd\xbe\x09\x1f\xab\x49\x8d\x66\xad\x54\x3f\xfa\xed\x37\x0c\xc3\xb0\x82\x50\x4a\x37\x85\xb4\x84\xb9\xdc\x17\x8b\x4d\xcf\xe9\xd5\x1b\xb5\x6c\xa2\xe1\xb6\x10\xea\xd8\xbf\xfa\xff\xc2\xea\x52\x41\x4a\x34\xb0\x7f\x11\xdb\x6f\xc1\xde\xb8\x69\x88\xcf\x71\x77\x0b\xfc\xcb\x98\x03\x61\xcc\xdd\xe3\xa9\x9e\xe3\xef\x0e\x0c\x7b\x16\xf7\x3f\x45\xe2\xf0\xf7\xdf\x30\x2c\x21\xd4\x25\xac\x9d\x91\x4a\xd8\xbf\x88\x7f\x13\xff\xc4\xff\x45\xfc\x1b\xfc\xf3\x3f\xff\x02\xee\x67\xf0\x6f\xf0\x0f\xd6\xf0\x6e\x62\x52\xa1\x2e\x6d\x85\x22\x95\x92\x7f\x84\x4a\xe6\x8e\x71\xe0\x49\xc9\xdc\xc6\xf0\xde\x92\xf9\x7f\x51\x24\x73\x3e\xa6\xfa\x72\xd8\x8f\xc3\xf7\x09\xe2\x30\x6c\x9f\x41\x74\x29\xc6\xb0\xfa\x56\x56\xd8\xdf\x07\x0f\xf0\xcd\xfb\xb9\xd1\xad\x48\xd8\xdf\xc7\x16\xf1\x47\x98\xd5\xbe\x94\xc6\x20\xc0\x00\x89\x3b\x33\xbe\x9f\xc2\xd0\x10\xe8\x59\x2a\xc3\x80\x06\x28\x3d\x31\xc8\x53\x72\x0f\x5a\x76\x4e\x6d\x58\x98\xf7\x34\xb5\x21\x40\x83\xd4\x1e\x1b\xc9\x55\x6a\xb7\x23\x97\x8a\x34\xb8\x30\x9c\xbe\x03\x65\x03\xd9\x33\xa8\x20\xec\x6f\xec\xeb\xd7\xbf\x4e\xef\xae\x74\x67\xd8\x37\x75\xf5\x68\x89\xf7\x84\xd7\xb3\x20\xd8\xe7\xd3\xb5\xb2\xfb\x78\xf4\x0c\xf2\x2c\x15\xe0\xf1\xe6\xff\x8c\x29\x43\x68\x41\xc5\x41\x16\xb6\x84\xd6\x46\x9f\x0e\x7e\x67\xa8\x3f\xdc\xb0\xa1\xd4\x2c\x14\x3c\x66\xbd\x27\x31\x07\xad\x9d\xc0\x9d\x15\xd2\x07\x43\x07\xd3\xa7\x0e\x1a\x20\x6b\x7f\xf3\xbc\xeb\x8e\x83\xff\xc8\x9c\x1c\xa5\x4b\x3c\x26\x74\x15\x93\xf5\x81\x3e\x0d\x92\x05\x27\xe1\xbc\x05\x9a\x4d\x17\x93\xfd\x7c\xe7\x8c\x07\xaf\x89\x66\xc0\x81\x8d\xd9\x13\x68\x18\xe7\x68\x1c\x73\x62\x84\x08\x10\xd0\xf4\x1f\x57\x44\x11\x9c\x34\x45\x15\x47\x30\x3f\xb5\x17\x49\x48\x3f\xc1\xd9\xcc\xd0\xdd\x75\x21\xcc\xd1\x27\xc8\x76\xe0\x64\x86\x6d\x55\xd0\xfd\x8a\xbd\x99\x53\x74\x4e\xe8\xa5\x29\xe1\x2e\xbc\xf6\xe7\x92\xf7\xd1\xbc\x9f\x79\x5e\x80\xea\x5b\x95\x50\x6b\x78\x01\x2a\xe1\xfe\x90\x2d\x25\x6a\x92\x1b\x4d\x8a\x5d\xff\xa7\x52\x19\x2b\x66\x4b\x2d\xa1\xd0\x94\xf6\xdf\x85\xce\xe1\x7b\x42\x48\x64\x24\x8c\xb8\xc5\x4c\x64\xb1\x07\x01\x9d\xa9\xa2\x9f\x42\xc2\xa6\x68\xed\x2c\xa1\xf1\xfb\xd7\x0b\x1c\x7f\xfd\xf1\xc3\x42\x03\xc5\x80\xb6\x1d\x34\x38\x7f\x3d\x2c\xdc\x38\xaf\x74\x94\x97\x18\x78\x9a\x33\x2f\x3f\xb6\xe7\x2b\xdc\x32\x0e\xd9\xd5\xbb\x7c\xc8\x21\x2f\x1b\xd2\x9c\x00\xe1\xcd\xbd\x84\x6d\xc8\x03\x34\x73\xcd\xc2\xc2\x73\x2b\x2f\x52\xdb\x63\x98\x1f\xa6\xb4\xd7\x18\xc1\xca\xed\x92\x94\xc4\xc4\xee\x0d\x8e\xbc\x7c\xe7\x75\x86\xf6\xb0\x02\xb7\xff\xd4\xd5\x4b\xb4\xed\x12\x5e\xcf\x6a\x9d\x0f\xc7\x57\xbb\x80\xcd\xf4\x2f\x79\xfa\xf3\xfc\xde\xa5\x96\x5f\xdc\xc5\xb5\x2f\x17\xb4\xd9\xd5\xe3\xf0\x5b\x2a\x72\xa0\x6e\xd8\xd8\xc8\x36\xa7\xf2\x65\x65\xdb\x65\x09\x9f\x95\x83\x0f\xc7\x97\xc3\xae\x36\xe2\x02\x6d\x47\x05\x0b\x77\x59\x61\x58\xad\x44\xf8\x83\xbe\x58\x8e\xd2\xc2\x5e\xbc\xb0\xa3\x63\xe7\xe5\xf0\x00\x86\x43\x47\xdc\xd7\x7e\x5f\xb0\x10\x18\x98\xcc\x85\x73\x18\x9b\x82\xcf\x58\x08\x3a\x37\x1f\xf2\xda\x2e\x66\xea\xdd\x6d\xf7\xaa\xe3\x7f\x0d\xd4\x72\x9c\xf1\x42\x9c\xc5\x03\x0e\x34\xfa\x8a\xa9\x4f\xed\x70\x1d\xd4\x10\xea\xcf\x4c\xd3\x08\xbf\xeb\xae\xae\x6b\xe8\x52\x5f\xbb\xb7\x2d\x64\x23\x6b\x79\xa9\xc9\x36\xac\x76\xd6\x7d\x37\x4c\xd2\xdf\x2e\xb5\x9a\x59\xa6\x63\x2a\xa6\x71\x91\xaf\x60\x1f\xed\x94\x05\x41\xd5\x0f\x03\xfd\xb8\x70\xa1\x28\xc8\xb6\xb5\x85\xd1\xbf\xa8\x28\x3e\xe3\x50\x37\x90\x7a\xab\x95\x4f\xfa\x05\x15\xba\x6c\x7a\x17\x92\xfb\xcf\x5a\xe2\x85\x15\xa8\x1b\xe3\xe2\xfd\x1e\xe9\xb6\x8f\x7b\x94\xe5\xd7\x0e\x75\x57\x71\x7c\xd4\xd0\xf7\x10\xa3\x4f\x0e\x85\x57\x71\x9d\x0f\x8d\xe1\xcd\xaf\x0c\x95\x47\x4b\x5f\x2f\xd3\xcd\x5b\x53\xa1\xd3\xea\xbe\x0b\xd3\xa5\xed\xec\x40\xf1\x58\x71\x47\xc9\x27\x07\x49\xdf\x3b\x98\x0b\x4b\xd9\x97\x0b\x5d\x18\x9e\x76\x2e\xe7\xeb\xd7\x1f\x3f\x2e\x4f\xd7\x2e\xdb\x81\xbf\xf2\xf8\xac\x38\xfd\xb2\xdc\xdf\x5f\x1a\x53\xf8\x6e\x33\xca\x08\xe7\xae\x30\x5f\x44\x1b\x28\x0a\xbe\xd6\xc8\xaf\x53\xbe\xd6\xc4\x9b\x2b\x87\x36\x38\x2f\xaf\xbe\xd1\xee\x2a\xba\x7d\xab\x2b\x18\x5d\x92\x74\xdb\x2f\xe0\xc5\x64\xd3\x34\x10\x9c\xee\xc6\x2d\x5d\x41\xfd\xe9\xc9\x18\xed\xfd\x76\x3a\x6e\x1f\xaa\xda\xfa\x81\x11\xfd\xa4\xae\x2e\x78\xd3\x32\x17\x53\xd5\xad\xcd\x37\xf4\xd9\x0c\x0e\xd0\x39\x50\xdd\xee\xa3\x35\x54\x9c\x53\xba\x8e\xca\x2a\x42\xab\xb7\x5d\x76\xfb\x6e\x7d\x3f\x96\xc8\x48\x89\x3c\xf6\xfb\xef\xc7\xa2\xff\x9f\xbf\x31\xfc\x8f\x3f\x6e\xc1\x0a\x7b\x7e\x27\xee\xff\x77\xd6\x03\x77\xc0\x3b\xe9\x8d\x00\xf8\x40\x57\x79\x14\x5e\xb5\xc2\xf0\xea\x81\x17\xd8\x65\x78\x81\xc9\x9d\x83\xf0\x3d\xde\xef\x99\x61\xf8\x56\xed\xc5\x6b\x06\xe2\x1b\x58\x3e\x6a\x28\x7e\x90\xd9\x27\x07\xe3\x1b\xd8\xce\x87\xe3\x4b\x0f\x5c\x19\x90\x4f\xea\x6d\x5e\xa8\xab\x3b\xfd\x3c\x26\xe9\xee\x39\x9a\x3f\x6c\xdc\x98\xf9\xdd\x3b\x66\x3f\x92\xe7\xdd\x59\xc0\x1e\x75\xa8\xbd\x6c\x27\x19\x97\x67\x29\x97\xe6\x7f\x3f\x65\x06\xe7\xac\xfb\x68\xba\x44\x86\x39\x43\x61\x59\x51\x67\xbd\x9d\x4f\x2d\x0c\xe7\xc2\xcd\x09\x72\xe0\x85\x5b\xdb\x99\xdc\xa5\xdb\xb6\x3e\x98\x42\x67\x61\xa1\xb0\x04\x1e\xcf\xfc\xf1\xef\x7f\x0e\x61\xcf\x7f\xfe\x37\x2c\xf0\xf9\xf7\x3f\x41\x99\xa3\x89\x79\x21\xd7\x76\x80\x35\x35\xa7\xe8\x6a\x18\x75\x80\x75\x0e\xc6\xe7\x4c\x9f\xa0\xbe\xbc\x1d\x08\xdd\x84\x38\x67\xc1\xe9\x00\x9d\xa8\x65\xf8\xcd\x89\x3e\xed\x5f\xd0\x9e\xcb\x0d\xfa\xc1\x31\x36\xb4\x91\x8f\x77\x00\x67\x27\x6d\xd1\xda\xb1\xe0\x7e\x4d\x63\xdb\x0b\xff\xfe\x27\x38\x2b\x3d\x1d\xa6\xb7\x5d\xb6\x65\x7b\x80\xd4\xcb\x53\xca\x60\xd9\x5e\x54\xa7\x10\x2c\x42\xf6\xfc\xc1\x18\x6d\x6e\xad\x17\x78\xb4\xba\x8f\x3e\xbe\xb4\xe0\x17\x26\x46\x25\xda\xaf\xc4\xde\x65\x9e\xb6\x11\x98\xae\xde\xc8\xbe\x1e\xc5\xab\x97\x06\x58\x7f\x07\x97\x1b\x9a\x84\xd9\x8b\xb7\x85\xea\xe2\xed\x6b\xe1\xa2\x1b\xfe\x4d\x2f\xe6\x39\x74\x05\x5d\x8a\x10\xdc\x9b\x98\x6a\x2e\x64\x03\x61\x33\x0b\x29\xba\x9b\x0a\x09\x5b\xfd\xb9\x10\xdd\x87\x6c\x1a\xbb\x63\x21\x2c\x90\x64\xd7\xd5\x5d\x6f\xed\x2a\x4f\xef\x19\x2c\xbd\xee\x72\x0b\x7e\x6f\x14\xb5\xd6\xa5\xc6\x95\x05\x89\xe3\xd4\xef\xf1\x72\xc4\x63\x93\xf1\xd7\x31\x71\x67\xcd\xef\x55\xa6\xae\x4e\xe2\xef\x61\xf2\x62\xcc\xf9\x32\x36\xef\x2e\x9b\xbe\xca\xe8\x8d\x00\x29\x9c\xd5\x24\x74\x20\xa6\x99\xd6\x3d\xab\xcc\x58\x52\x68\x08\x37\x78\xbc\x04\xf7\xc2\x72\xef\x13\x20\xaf\x2d\x9b\xde\x03\x36\x5b\xaa\x4b\xb5\x06\x96\x2d\x35\xca\x67\x4b\xa7\x6e\x08\x5c\xc7\x7e\xff\x4a\xf4\xf5\xa9\xee\xe8\xd0\xe8\x7b\x55\x79\x7f\xda\x73\xe3\xeb\x37\xec\x2b\xc0\x09\xfe\x3b\x81\x7f\xc7\x59\x8c\xe0\x7f\x50\xe4\x0f\x9c\xfe\x93\x24\x68\x9a\x64\x63\x38\xf8\xfa\xc7\x5f\xf7\x41\x07\x7d\x6f\x0b\xdc\x49\x6f\xc9\x9b\xbe\x63\xea\xea\x55\x4c\x80\xe6\x28\xfe\x11\x4c\x64\x7f\x61\xa3\xc3\x18\xaa\x4f\xcf\xb6\xdd\x5d\xc7\xc7\x73\x0c\xf9\x08\x3e\xaa\x0f\x55\xb5\x1f\x4c\x2c\x5f\xc5\x41\x72\x1c\xfd\x90\xf4\xe8\xbe\x17\x35\xee\x26\xb0\x6e\x7d\xc5\x55\x14\x14\x4b\xf3\x0f\xb1\xc1\xec\x50\xf8\x9e\xf1\x36\x0a\x1a\x70\xd4\x23\x18\x58\x6f\xc8\xd8\xdc\xcf\x04\x43\x93\xcc\x43\x72\xe2\xdc\xbe\x80\x83\x81\x85\x06\xd0\x31\xad\xeb\x5d\xcd\xe2\x14\xfe\x90\x6a\x71\x27\x32\xf2\xf7\xa5\xdc\x66\x83\xa5\x59\xfe\x21\x36\x78\x97\x0d\x6f\xcd\xa1\xbf\x56\xad\xeb\xd0\x39\x9e\x05\x8f\x40\x27\x70\x17\xbc\xdf\x0b\x6e\x30\x70\x15\x01\x47\x70\x0c\xf7\x10\x02\xe2\x18\xc1\x3e\xb7\xb0\xb5\xff\xeb\x88\x68\xe2\xa1\xee\x20\xc0\x49\x47\xf8\xd9\x1c\xef\x78\x89\xab\x88\x78\x82\xa2\x89\x87\x30\x91\x1e\x37\xfb\xec\xd9\x75\xc5\xe2\x59\x9c\x67\x1e\x82\x4f\xf5\x35\x7d\xbd\xdb\xb5\x65\x4e\x8c\xbe\xa6\x23\xe3\xba\x63\xe4\x39\xee\x31\xfb\x23\xe8\xdd\x84\x62\xb7\x24\xb5\xbe\xca\x06\x85\xe3\x2c\xfb\x90\x0f\x21\x98\xbe\x3e\x1d\x20\xdb\xe9\x9f\x2f\x7a\xdd\x40\x05\xc0\x63\xa6\x48\xb0\x27\x41\x80\xbb\xba\x08\xaf\x0f\x25\x14\x4e\xf2\xd4\x63\xfc\x70\x7b\xed\xd5\x4c\x6b\x17\x28\x5c\xc5\x41\xe0\x1c\xf5\x58\xaf\xf0\x9e\x52\x5d\x07\x0b\x00\x05\x1e\xd2\x28\x80\x87\x90\x7e\xdb\x06\x29\x40\xf1\xf8\x63\x88\x88\x9d\xa1\x5b\x68\x62\x2e\x51\xff\x0d\x59\xe6\x3e\xb3\x6a\x4e\x6d\xc7\x82\xfa\x8d\x41\x97\x02\xdc\xc1\x60\x2e\xc4\x40\x57\x8b\x98\x1e\x0d\x82\xce\x0a\x99\x76\xec\x10\xdf\xb0\xaf\x69\xb1\x93\xae\xe6\xda\xad\x42\xbb\xdc\xcd\xa4\x0a\xad\x46\xbe\xdd\xa2\x53\xe9\x8c\x40\x16\x4a\xdd\x2e\xc8\x55\xf3\x45\xb6\x2c\xe4\x84\xa6\x54\x4d\x35\x99\x42\x25\x51\x97\x52\xad\x4e\xb9\x14\x14\xd9\x45\x24\x60\x8b\x24\xd1\xc9\xa7\x99\x5a\x89\x2a\x97\xb2\x52\x25\x51\x2c\xa5\x44\x96\x04\x02\x45\x32\x3d\xba\x52\x4a\xd6\x6b\x85\x74\x3b\xcf\xa6\xc5\x42\xa2\x58\x2d\x64\x53\x65\xaa\xce\x4a\xdd\x76\xab\x79\x37\x12\x72\x8b\x44\xa0\xdb\x62\xa5\x2b\xd0\x5d\xaa\x2d\x48\x99\x4e\xbb\x06\x9a\xf9\x32\x68\x96\x29\xb1\x99\xce\x34\xab\x2c\x25\x35\x2b\xf9\x72\x09\x54\x33\x2d\xaa\x5d\xcb\x94\xb3\xb5\x52\x3e\x9f\x39\xeb\xfc\x8b\x48\x28\x97\x13\x40\x56\x53\x20\xd3\x94\x68\x20\x14\x3b\xcd\x54\x33\x43\x0a\xdd\x9c\xd0\xe9\xa4\x3b\x9d\x16\x68\x65\x3a\xdd\x6e\x8d\x91\xba\x1d\xa9\x51\xc9\x27\x3b\xbd\xba\xd0\x66\xd8\x4e\x99\xba\x1b\x09\xed\x22\xa9\x56\xba\xe9\x0c\x95\xa7\xd9\x8e\x98\x94\x4a\xf9\x7c\x87\xa6\xf3\xc9\x46\xbb\xdc\xc8\xd3\xed\x64\xbb\x56\x2d\x67\x40\x21\x23\x25\x3b\xa4\x94\x6f\x65\xab\xb5\x42\x51\xaa\xa7\xc5\xf4\xdd\x48\x18\xb7\xe3\x6b\x95\x6e\x26\x5b\x00\x89\x2c\x99\x2a\x55\x29\xb1\x53\x48\x15\x4b\xc9\x42\x2a\xd7\x2c\x55\x9a\x20\xd3\x25\x7b\xc5\x54\x3d\x53\x2e\x35\x13\x52\x59\xa8\xb7\xd9\x6a\x82\x2d\x77\x40\xe6\x6b\xd4\xf2\xc1\xed\x24\xe7\x86\xd6\xfa\x15\xe4\x87\xcd\x1f\x7f\xda\xe8\x7a\x69\xdd\x37\x8c\xf9\x86\x39\xd6\x02\xdd\x61\x4b\xe7\x45\x73\x91\x2d\xc9\x9b\x83\x1f\xdb\x91\x62\x21\x55\x77\xfa\xd0\x98\x0d\xe1\x74\x31\xa1\xb6\xd6\x2f\x35\x6b\x5f\xdf\xa3\x3b\x4f\xb1\x83\x0b\xd8\x9b\xf5\xe4\xd7\xf7\xd0\xd8\x53\xec\x5b\xcb\x9b\x42\x47\x5f\xa2\x2d\x32\xf7\xff\xd1\xca\xf4\x5e\xa3\x1e\x27\x89\x8e\x6f\x18\x79\xaf\x72\x84\x15\xb7\x45\xd5\x8e\x5d\x81\xdb\x91\x88\x00\xcd\x32\x3c\x87\xb3\x1c\x4b\x7e\xc3\x88\x6f\xd8\xb6\xcf\xfe\xf3\xc5\x1b\x37\xbe\xfc\xc0\xbe\x10\xe4\x9f\xb8\x77\x7d\xf9\x86\x7d\x39\x94\x50\x6e\xef\x49\xcd\xda\xe1\x47\x67\x33\x73\x7f\x0c\x76\xf8\xa1\x85\x57\x4a\xb9\x6d\x13\x55\xef\xbe\xfc\xef\xa5\xbe\x0f\x72\x06\x02\x9c\x01\x57\xe2\xa7\x9c\xe1\x97\x39\x6b\xd6\x93\x51\x39\x8b\xa6\xd3\xd1\x39\xdb\xfe\xf3\x58\xf3\xd2\xa5\x2e\x15\x11\x87\xce\x2d\x47\xbb\xd0\xfa\xcb\x8f\x2d\xe8\x2f\xb6\x69\xa8\xfd\x4b\x42\x93\xcd\xc5\x60\xe8\xf4\x2f\x69\x8b\xf7\x6c\x98\x60\x8f\xee\x5c\x93\xee\x0e\x7e\x98\xd6\x9d\xdc\xbb\x06\xe4\x08\xd7\x0b\xfa\x29\x88\xf9\x23\x95\x9a\x08\x74\x3d\x15\xd6\xf5\x11\x03\x9a\x3b\xba\x9e\xbc\xde\xf5\xf8\x8d\xae\xf7\xfb\xed\x99\xae\xf7\xb5\xe7\xd9\xae\x8f\xd8\x4f\xd7\xba\xfe\xbd\xad\x7e\xef\xa9\x09\x82\x67\xf8\x70\x4f\x4d\xff\xc9\x51\xbf\xb0\xa7\xf6\x39\x0b\xf3\xd4\xe0\xd7\xf6\xd4\x3e\x67\xef\xe8\xa9\x89\x10\x73\x05\xb7\x3c\x35\x78\x2f\x4f\xbd\x6b\xe8\x45\x5f\xaf\xf7\xc1\x8f\x3b\x4c\xbf\x07\xde\xd1\x61\x86\xf5\xc0\x89\x88\xcf\x7b\x00\x5c\x70\x98\xe7\xe2\x7b\x89\x33\xfc\x69\xbe\x2b\x68\x07\xf4\xfb\xd9\x01\x78\xbc\x17\x4e\xbc\xe6\xe3\xbd\xf0\x68\x34\xf2\xf3\x83\x07\xbf\x17\x98\xf7\xb3\x85\xb0\x5e\x38\x11\xf3\xe3\xde\xe8\x89\xe0\xe1\x6e\x6f\xf4\x01\x3d\x40\xb0\x04\xcb\x73\x2c\x09\x38\x22\x7c\x0c\xc7\x7f\xcd\x49\x09\x15\x60\x2d\x74\xba\xf5\x6b\xb2\x76\xe8\x35\x96\x64\xd9\xc7\x7b\xed\x13\x87\x5e\x74\x80\xb5\x47\x7b\xed\x13\xb3\x06\x76\xac\x71\x04\x75\x29\xb3\xf1\x8b\x2a\x24\x15\x60\xed\xbf\xc8\xd6\xc8\x3d\x6b\x34\x7d\x69\x96\xf3\x8b\x2a\x24\x1d\x60\xed\xbf\xc8\xd6\xb6\x1e\x12\x70\x1c\xc5\xe3\x34\xcf\xd1\x5e\xaf\xe1\x2e\x6f\x86\x3e\xd1\x5d\xd6\x78\x00\x48\x92\x05\x38\xc9\x70\xf4\x9f\x14\xcb\xd2\x1c\xce\xfe\x52\x9a\x09\x76\x3c\x12\x38\xbe\x1b\xbb\xff\xdb\x78\x24\xf7\x3c\x52\xc4\x6e\xa4\x8b\xc4\xe3\xaf\xa0\xab\x04\x07\x76\xe3\xc2\x7f\x1b\x8f\xd4\x37\x8c\xa3\x39\x9e\x27\x39\x86\xf3\x9c\xa8\xc7\xa1\xed\x40\xcb\xd1\xa7\x83\xbe\x0c\x0d\x38\x55\x50\xd0\xe7\xdc\x8d\x80\x39\x45\x70\xaf\x2b\x0b\x04\xe2\x51\xf9\xd9\xf6\x9a\xc7\x90\x77\xf4\x8b\x3f\xf9\xf6\x16\x41\xfa\x63\xb4\xf9\x18\x6b\xa1\x7d\xaa\x28\xc0\xfa\x4e\xef\x9d\xa4\xec\x23\x78\x6f\x29\x07\xf8\xb9\x53\xca\x1f\x60\xaf\x1e\x55\x0c\xe7\xbb\xdd\xf7\x92\xb2\x87\xe0\xbd\xa5\x1c\xe0\xe7\x3e\x29\x47\xcd\x8d\x3c\xe2\xf9\x5d\xaa\x68\x9c\xf7\x1d\xff\x3b\x49\xd9\x47\xf0\xde\x52\x0e\xf0\x73\x9f\x94\x23\x16\x69\x3c\x14\x43\x78\x54\xd1\xb8\x3f\xf4\xbc\x97\x94\x3d\x04\xef\x2d\xe5\x00\x3f\x77\x7a\x8c\x88\x19\xa6\xff\xbd\xa3\x26\x29\xec\xfc\x93\xa8\x4b\xe5\xbb\x33\x50\x8e\x0b\x53\x54\x8e\x62\x48\x92\xd5\x54\x1e\x01\x96\xa1\x48\x9e\xa2\x18\x15\x40\x9a\x02\x9a\xcc\xb3\xb2\xc2\x40\x48\x30\x34\x8e\x23\xa8\xd2\x8a\xca\x20\x9e\x00\x1c\xcb\xb2\x8a\x8a\x54\x44\xe0\xac\xf2\x75\x0b\x03\x21\x9e\x61\x65\x8a\x93\x15\x9c\xd6\x90\xca\x02\x5c\xa5\x80\x8a\xe3\x2c\x41\x72\x2a\xc7\x2b\x2a\x8e\x70\x86\x64\x55\x55\xa3\x28\x1e\x67\x11\xd8\xc6\x63\x24\xa3\xe2\x2a\xab\x30\x1c\xf3\xd5\xed\x57\x10\xa8\xe0\x62\xdd\x0a\x2e\x26\x58\xd8\xc5\xfa\x85\x5d\x0c\xcf\x33\xf4\xed\xbb\xfe\xe2\x22\xc9\xb2\xcc\x37\x8c\xd8\xfe\x1f\x3f\xbb\xbe\x61\x04\xef\xfe\xf5\xff\xec\x7f\xdd\x7f\xd8\xd2\x26\x08\x82\x90\x2c\xb1\xb3\x1e\x5b\x2f\xac\x52\x71\x47\x19\x10\x09\x5c\x50\x1a\xa3\xee\xb4\x94\x1c\x74\x49\x52\xab\xe5\xc4\x58\x2e\x97\x4a\xca\x55\x82\x83\xe9\x24\x9d\x13\x56\x80\x43\xc9\xc4\x24\x09\x88\xc6\x62\x5d\xb1\xa6\x6d\x26\xdd\xe3\xcd\x9a\x5c\x4a\x8f\x2b\xc3\x6c\x5c\x85\x13\x7e\x40\x6c\x8a\x5b\xd0\x42\xa7\xe7\xd0\xf9\x81\xb0\xbf\x90\xd0\x2a\xbc\xad\x97\xab\x37\x61\xbc\x6a\x8a\x24\xb3\xd8\x2c\x3a\x0c\x51\x16\xdf\xd6\xbd\x9c\xad\x57\x8d\x78\xb7\x66\x66\xd2\xac\xd1\xcd\x83\xa1\x25\xaf\xde\x2a\x2c\xcf\x77\x97\x5a\x7e\xa2\xc6\xcb\x13\x82\xd2\x14\xc0\x57\x50\x7e\xda\xec\x0a\x43\xbe\xc0\x37\xc5\x3a\xe5\x64\xf2\xd5\x2d\xe4\x6e\x89\x2a\xc0\xb7\x19\xa8\x1e\x90\x09\xaa\x2d\x9c\x5e\xc9\xed\x9f\x9e\xd0\x21\xa8\xaa\x20\x24\xf1\x9c\xf0\xab\x5d\x9e\x56\x11\xdf\xdc\x1d\x43\x17\xcc\x3f\x68\x11\xf4\x6b\xb4\xf9\xab\x82\x43\x82\x04\x9c\x02\x19\x4d\x95\x65\x8d\x86\x24\x25\xab\x24\x01\x01\xcb\x6a\x34\xcb\xb3\x04\xa5\xc9\x04\xa7\xf2\xb4\x4c\xe2\x14\x82\xb8\xa2\x72\xb2\x2a\xf3\xaa\xc2\x22\x8e\xd3\x54\xca\x2b\xa6\x21\xc3\x95\xfb\x92\xce\xb3\x24\xc7\x12\xb7\x6e\x02\x82\x62\x29\x8e\x64\x28\x0e\xbf\x66\x0f\xcc\x9d\xf6\x50\x4c\x0c\x8b\xe6\x66\x12\x97\x97\x84\x89\x2f\x1b\x69\x5d\x8d\xb7\x68\xa5\x19\x5b\x8f\x7a\xed\x37\xb1\x6c\x16\x41\x01\xd0\x64\x86\xc9\xc6\x9b\x0d\xb9\x36\x8e\xaf\x3b\xe5\x21\xac\x83\x79\x7a\x4d\xb2\xa9\xcc\xb0\xf4\xb6\x9a\xa0\xd1\x52\x9d\xa8\x8b\x95\x59\x57\xa9\x15\xcd\xe9\x02\xcb\xb9\xfd\xe7\xda\xc3\x91\x8a\x1a\x7a\x29\xad\x88\x19\xb1\xc7\xa6\xaa\xc9\x99\x80\x4f\x63\x24\x6b\xac\x55\x55\x63\xb3\x16\x3d\xee\x11\x55\x76\x3e\x55\x6a\xd3\xf5\x5b\x7b\x5c\xc8\xcb\xf9\x46\x52\x01\x50\x5f\xb5\x13\xd3\x41\x42\x10\xcd\x42\x9a\x1d\x28\x53\x9b\x71\x14\xc4\x4a\x9c\x3a\x96\x96\xf2\x9b\x9e\xeb\xb9\x90\x9b\x21\xf6\xd0\x0b\xaa\xd3\x7f\x83\x3d\x90\xee\xf0\xfc\x80\x3d\x50\xaf\xd1\xe5\xaf\x3c\x0b\x68\x59\x51\x55\x59\x53\x11\x80\x80\xe5\x59\x95\xa5\x49\x85\x25\x79\x1a\xa9\x0c\xc7\xe1\x38\xa2\x54\x0d\xb0\x88\x07\xa4\x0c\x79\x0a\xf0\x80\xa6\x19\x12\x91\x2c\x4d\xb0\x90\xdb\x8e\x32\x94\xfb\x2f\x44\xb7\xa9\x8b\x2a\x4f\xe3\x38\x77\xd9\x20\x76\x77\xbd\x14\x16\xc3\x13\x1c\x75\xcd\x22\xc8\x3b\x2d\x22\xa7\x18\xcb\x12\x88\x93\xba\x39\x35\x78\xb5\xb1\x7e\x33\x10\x61\x0e\x04\xba\xc4\x4d\x99\x7a\x99\x31\x12\x63\xa3\x35\xa2\xc8\x66\x67\x5e\x14\xcb\x79\x84\x62\xfc\x78\x90\x1f\xa7\x00\xe8\x8e\x3b\x6c\xad\x9d\x4b\x35\x92\x55\x93\xca\xe0\x82\x45\xf4\x9a\xab\xa1\x2d\xc2\xdc\x40\xf3\x86\x05\xd7\x22\x8e\x7a\xb4\x38\x4a\x97\x9b\x93\xd5\xa0\xcb\xce\x6b\x32\xde\x72\xc8\xe6\xa2\x46\xf7\xe6\x13\x44\x8f\xc1\x7c\x94\xe1\xd8\x79\x66\x28\xd4\xd0\x0a\x9f\xaf\xe0\xc0\xe8\x69\x5d\x67\x92\x9c\x24\x62\x8c\x29\x24\x8d\x0d\x47\x71\x64\x0c\xb4\x26\x8e\x26\x91\x10\xaf\xd7\xf9\x4c\x26\x47\xe9\x7a\xcb\x45\x55\x0d\xb1\x88\x66\x33\x4c\xab\x7e\x71\x8b\xa0\x1e\xb5\x08\xf2\x35\xda\xfc\x15\xa7\x10\x89\x64\x04\x35\x5e\x25\x64\x0e\xe1\x1a\x4d\xd1\x9c\x4a\x93\x38\xc1\xf0\x1a\xc2\x55\x8e\xd7\x08\x59\x53\x55\x56\x56\x29\x55\xe1\x54\x4a\xc6\x69\x8e\x92\x01\xc9\xa8\x04\x8b\x08\xfa\x9a\x45\x90\x17\x75\x9e\xa1\x38\x9e\xbd\x79\xd7\xcf\x7c\x12\x1c\xc7\x5d\xb1\x88\x7b\x43\x26\xa1\x31\x62\x62\x16\x8d\xcb\xa3\x01\xdf\x6c\x97\x9a\xab\xd4\x2c\x3e\x00\x39\x4e\x8e\xab\x88\x6f\x28\xa3\xa6\x9d\x1a\x16\xb2\x00\xef\x50\xad\xd1\xe2\xcd\x28\x18\x42\x45\x8b\x11\xf6\xaa\x09\xb4\x35\x01\x9d\x45\x43\x23\xb4\x4d\x19\xa5\xd6\x49\x7e\xb4\x36\x1b\xce\x30\xd3\x11\x67\xa6\xdb\x81\x5b\x83\xc8\xad\xb6\x9f\xb2\xfb\x3f\x82\xab\xb3\x87\x1f\x85\x95\x50\xa9\x8e\xbd\x0e\xdf\xb0\xd5\x0e\x2a\x8f\xab\xd5\x41\x33\x3d\xc8\x54\xc7\x0a\x8c\xcd\xd5\xd2\x22\x93\xec\x2d\xda\x52\x62\xec\x48\xbd\x6e\x39\x9d\x58\x2d\x52\x7a\x7c\x19\x37\x17\xcb\xbc\xb5\xa4\x38\xbc\xd6\x28\x4c\x8b\xc9\x54\xa6\xd6\x2e\x2e\x56\xb1\x3c\x88\xa7\xf4\x46\x51\x4c\x0e\xde\xa6\xb1\xd6\x28\x13\x73\x0d\xa6\x18\x62\x30\x65\x29\x4c\xe9\xfe\xff\x66\x30\xe0\x35\xca\xfe\x95\x21\x55\x9e\xd3\x68\x92\x41\x88\xe1\x54\x42\x06\xac\x4c\xcb\x1c\xaf\x01\x12\x6a\x34\x49\x10\x32\x4b\x33\x3c\x04\x94\x06\x35\x82\xc2\x49\xa8\xe2\x32\x0d\x64\x86\x24\x65\x9c\x95\x11\xcf\x7f\x75\x8b\x34\xe8\x50\xdd\x07\x17\x4d\x82\x65\x58\xee\xea\xcd\xed\x08\xe2\x65\xf2\x28\x9a\x07\x57\xcc\x85\xbe\x60\x2e\xde\x8c\xd9\x15\x6f\xba\xd2\x1b\x11\xa5\x05\x6d\xe2\x72\x8e\x6d\x53\xd3\x4d\x79\xd9\x5c\xa7\xc9\xd6\xcc\x1c\xc7\x96\x29\xa1\xec\x24\x88\x3c\x28\xb2\x22\xcb\xf4\x86\x53\x4d\x96\x92\xb3\x4c\xa5\xab\x52\xf4\xb4\xaa\x34\xd8\xce\x58\xcb\x16\x57\xf5\x0e\x3f\x48\x25\xf9\x98\xd6\x86\x0e\x4b\x30\xd5\x6c\x5b\x71\x41\xbb\x96\x72\x34\xb9\xa8\xf2\x13\xae\x50\x4f\x73\x32\xdd\xc6\xe5\xc5\x5a\x72\xe6\xb6\xd3\xaa\xbe\xb1\xd9\x56\x3c\x63\x25\x27\x69\xc9\x51\x05\x6a\x92\x90\x92\x9d\xd5\x0c\x0c\xc6\x26\x80\xdd\xf2\x68\x93\xe6\xdb\x25\x83\x49\x08\x19\xb3\x48\x13\xf9\x75\x2e\x95\xe7\x07\xb8\x59\x5e\x14\xc8\xb1\xcd\xe9\x1d\x17\x7e\x36\xc4\x12\x32\x78\x98\x36\xed\x2c\x41\x10\xc4\xf1\xbb\xaa\xed\x3b\x5c\x9e\x36\x3d\x66\x09\xc4\x6b\xb4\xd8\x3d\x2b\x01\xf3\xf5\x86\xe0\x59\xfc\x3b\x4e\x7c\xc7\x09\x0c\xc7\x7f\xb8\xff\x2e\xaa\x2b\x8f\x13\xe4\xe5\x60\x69\x77\x97\x02\x3c\xc5\x33\x2c\xe0\xaf\xcd\x97\x6f\xaa\xf2\xa7\xbc\xc4\x4e\x5e\xa7\x36\xf1\x4d\x3d\x2f\xb2\xc9\x69\x92\xcf\x00\x7c\x3d\x12\x63\x36\x3e\x70\xec\x55\x76\xf5\x46\x74\xd4\x7a\xbb\x0b\xc5\x1c\x4c\xb9\xaa\x2c\x85\xa8\x72\xf8\xf5\x8b\xab\x32\x7e\xac\xca\x37\x12\x52\x77\x9c\x0a\x1a\x35\x3f\x75\xe1\x9c\x8a\x4b\xa5\xe2\xe0\x82\xdd\xdd\x00\x73\xb6\xd9\x20\x1a\x98\x60\xf5\x72\x44\x6a\xa8\x60\x41\x6d\x34\x30\xf4\x1e\x0c\x83\x33\x74\x64\x6a\x98\x00\x98\x88\xd4\xb0\xbb\x3c\x03\x85\xd3\x6e\xf2\x3d\x1a\x18\x6e\x0f\x86\x62\xdc\xec\x72\x34\x30\xfc\x1e\x0c\xc7\xba\x15\x18\xd1\xc0\x10\x78\xa0\x20\x8c\x8a\x08\xe7\xac\x66\x2e\x22\x1c\x10\x28\x75\xa2\x23\xc2\x21\x83\xd5\x60\x11\xe1\x04\x8b\x78\xa2\xca\x87\x0e\x16\x03\x45\x84\xc3\x04\xca\x53\xa2\xca\x87\x0d\xc0\x89\x68\x14\x04\x17\xac\x29\x89\x08\x87\x0f\xd4\x6d\x44\xf5\x83\x78\xa0\x36\x22\x22\x5f\xe0\xac\xfe\x20\x22\x1c\x70\xba\x26\xce\x44\x04\x43\x9e\x82\x89\xa8\x85\x80\x3a\x5d\x3b\x8e\x4a\x4d\x60\x09\x3a\xa2\x0e\x82\xc0\x92\x6e\x54\x6a\xd8\xc0\xd2\x73\x44\x30\x5c\x60\x2d\x32\x22\x18\xfe\x14\x4c\x44\xa6\x48\xfc\x74\xcd\x2e\x2a\x18\x22\xb0\xd2\xf8\x9a\x43\xc2\x5f\xb2\xd1\xf6\xfa\xe1\x5b\xdf\xb0\x2d\xed\xf7\xed\xbc\xbd\x70\x56\xf6\xd3\x11\xdb\xb1\xc6\x1f\x87\x68\xfb\x2f\xde\x52\x0c\xe1\x2d\xde\x3a\xe6\x53\xab\xd3\xdf\xb0\x2f\x9a\x65\x4e\x9e\xad\xee\x9f\x41\x67\xf8\xe5\x07\xf6\xef\x7f\xbe\x61\x9f\x76\x73\xb0\x5b\xd9\xef\x1d\xf8\x7d\x61\x57\xa2\x8a\x6c\x47\x9f\x7a\xda\x31\xd1\xa7\x6e\x83\xd3\x4d\x38\xde\xe3\xe1\x1b\xa1\x8e\xee\x5d\xdf\x74\x78\xd4\xf0\x25\xf5\x7b\xef\x70\x4e\xc5\x45\x65\xdc\x45\xe8\xfb\x2f\xdc\xe7\x55\xc6\xff\x5c\x28\x60\x08\x28\xe9\xa7\xda\x17\x19\xaa\xa4\xe0\x86\x92\x82\xff\x53\xd2\x53\x25\xf5\x27\x6e\xfb\x2f\xd4\xe7\x55\xd2\x53\x65\xfc\x54\x15\xde\xa1\xba\x48\xde\x72\x98\x38\xfe\x7f\xda\xb8\x0f\xe7\x8f\x26\xee\x87\x2f\x8c\xab\x8d\x9e\x32\xba\xe7\xba\x79\x3d\xcf\xe3\xee\xff\xbe\x9c\x28\x04\x38\xb1\x6d\xef\x5d\x02\x5b\xe6\xff\xf3\xc5\xdd\x55\x4a\x7c\xc3\xbe\x6c\xc5\x4e\xe0\xff\x7b\xba\xc7\x0e\xff\x86\x7d\xf1\x4e\xad\xbd\xb0\x2d\xf4\xf8\xde\x55\xd9\x7b\x47\xe3\x5e\xde\xf5\x78\x0c\xe8\x65\x7d\xf3\xe2\xb3\x9d\x2e\xf7\x8d\x97\x0d\x39\x7c\x01\xe1\x7d\xc3\x91\xee\x15\xe8\x1b\xea\x5a\xdf\x30\x7e\xd7\xd0\xb7\x7a\x26\x64\x03\xe2\x89\xcc\x83\x7b\x1c\x43\x3b\xe4\x76\xd7\xbd\xa4\xc4\xfc\x43\xfb\xc6\x4b\x31\x1d\xbe\x70\xe1\x7d\xc3\x32\x3c\x20\x71\x2e\xd0\x37\xcc\x55\xbb\x21\x3f\xd8\x6e\x22\xf7\xe1\xab\xcd\xeb\x57\x56\x8b\xd3\x4c\xdf\xfe\x0b\xee\x0d\xee\xc7\x63\xfb\x13\xbb\xc5\x0f\x63\x7b\x74\x09\x7f\xe2\x9d\x76\xef\x70\xae\xd6\xe5\x9e\xf2\x73\xa0\xfb\x2f\xcc\x3b\xf5\x54\xf4\xf8\xe6\x13\xef\xae\x7b\x87\xf3\xd7\x2e\xf6\xd4\x6e\x17\xec\xfe\x0b\x38\xef\xa9\x27\x62\xdd\xff\xb3\xa9\x97\xd9\xd4\x6e\xe7\xeb\xfe\x0b\x77\xde\x53\x2f\x99\xd9\xfc\x9f\x4d\x45\xb7\xa9\x93\x95\x89\xfd\x17\x6f\x12\xca\xdc\xb7\x9b\xd0\xb1\x16\xb6\x83\xd0\xb3\x56\xe3\x82\x31\x9f\x3e\x42\xe5\x73\xd8\xd8\x07\x44\x18\x27\x7b\x78\xf7\x5f\xf0\x9f\xdc\x73\x4f\xb8\xde\xcf\xd1\x73\xef\x3f\xd5\x3e\xdd\x99\xbc\xff\xc2\x44\xee\xb9\xe8\xfe\xef\xb8\xe7\x9e\x70\xc5\x9f\xc3\x5b\xbe\xf8\x68\xe2\xcb\x3d\xe7\xaf\x77\xee\xbf\x80\x9f\xdc\x73\x2f\xf3\x96\x3f\xab\xe7\xde\xdf\x5b\x1e\x2f\x0d\xef\x3f\x73\x47\x3b\x17\xb5\xc5\x54\xdd\x9d\xdf\x15\xed\xcc\x66\x57\x2e\xde\xc9\xc9\x4f\x4f\x7b\x6f\x6e\xa3\x7c\xf2\x6c\xe9\x47\xa4\xe6\x2f\x61\xef\x3f\x53\xef\x2b\xb5\x27\x12\xc0\x9f\x4a\x6a\xde\x52\xfb\xfe\x33\xfe\xae\x52\x7b\xc2\x03\x7c\x2a\xa9\xf9\x25\x01\xfb\xcf\xcc\xbb\x4a\xed\x89\x11\xef\x73\x49\xcd\x2b\x5d\xd8\x7f\x06\xef\x6b\xa1\xd1\x23\xbc\x77\x97\xda\x8d\x32\x88\x90\xf7\x5b\x47\x2d\x81\xf0\xdf\x71\x1d\x5a\xfe\x80\x5f\xdc\xd2\x4c\xee\x66\xc0\x04\xb9\xaf\xa0\xf6\xf6\x40\x1f\x95\x54\x3b\xd6\x02\x79\x1b\xd0\x09\x6f\x37\x28\xc5\x10\x04\xc3\x31\x38\x45\x11\x3c\x4b\xf0\x34\xcb\xb2\x17\x34\x24\x94\x2a\x7f\x1d\xfc\x32\x55\xc4\x9e\x08\x70\xa8\xeb\xf6\x88\x25\xc1\xee\x07\x0d\x1a\xf6\x96\x2c\xc2\x23\x2d\x40\x13\xcf\x5d\x2b\x01\xbb\x46\x16\x71\x91\xac\x7d\x62\x87\xa0\xfd\x55\xef\xdd\x41\x00\x47\x64\x79\xc2\xa2\xdd\xf0\x0b\x84\x92\x75\x97\x5a\xdc\x7e\xe1\xf2\x13\x8a\x12\xfe\x7a\xba\xd0\xfa\x66\x70\xb9\xae\xef\x26\x20\x10\x00\x74\xa9\x3e\xeb\x26\x20\x32\x50\x34\x11\x19\x10\x15\x00\x14\x99\xb5\xe0\x0a\x79\x64\x40\x4c\x00\x50\x64\xd6\xce\x56\x49\xa3\x02\xe2\x82\x4b\x7a\x51\x01\x9d\xad\x3f\x45\x05\x74\x5a\xf1\x8c\x5f\xae\xa5\xbc\x0d\xe9\x6c\xf1\x23\x32\x24\x10\x48\xce\x5f\xaa\xa8\xbc\x0d\x89\x0c\xa6\xf9\x23\x43\xa2\x02\x69\xe8\xc8\x5a\x79\x5a\xfb\x0c\x9e\x91\x38\x13\x48\xb8\x46\x97\x13\x1b\x80\x14\xd9\x54\x4e\x2b\xa0\xa9\x67\x24\xce\x07\x52\x5d\xd1\x7d\x25\x1e\x48\xbd\x44\xe6\xee\xb4\x0e\xfa\x19\x03\x3e\xa9\x84\xe6\x2e\x57\xb4\xde\x06\x44\x9e\x02\x8a\xac\x4d\x27\xd5\xd0\xd4\x33\x14\x05\x26\x90\x91\xb5\xf2\xa4\x22\x1a\x7f\x86\x22\x36\x30\x39\x8b\x0c\x88\x3b\x9d\xaf\x44\xa7\x88\x3f\x05\x14\x7d\xf8\xc6\x4f\xe7\x02\x91\x8d\xe4\xa4\x36\x1a\x78\xac\x3d\xf6\x96\xdf\xf7\xac\x8e\xbe\xf5\xc6\xde\x47\xea\xa3\x8f\xdf\x2a\xf8\xea\xa8\xef\x20\xcf\xaf\x0c\x85\x20\xa3\x2a\x3c\xce\xe3\x0a\xa7\x12\x00\x00\x82\x55\x28\xa8\xe0\x0a\x09\x79\xc0\x52\x1a\x43\xe3\x14\xa9\xf0\x00\xe2\xaa\xcc\xa8\x88\xa3\x68\x16\x20\x4e\xa5\x78\x45\xc5\x69\xc0\x78\x6f\xe2\x22\x9e\x49\x53\x1f\x6d\x5b\xa6\x76\xbb\x39\x2f\x1f\xa6\xc4\xd3\xfc\x95\xa3\x96\xbc\xbb\x27\x31\xa7\xb7\x0d\x34\xcf\x8c\x90\x4e\x8e\x26\x66\x96\x6b\xa4\x8d\x64\x1c\x0d\x14\x92\xad\x74\x9c\x4c\x3e\xff\xd6\x6e\x71\xab\x96\xde\x13\x61\x62\x41\x17\x68\xf7\x0c\x24\xef\xd0\x15\x77\xdb\x7e\x22\xb0\x4b\x51\x3c\x7c\x74\x37\x13\x8b\xad\x56\xc9\xdf\x5f\x9f\x20\x16\xa2\x9a\x31\x1b\x8b\x41\x71\x59\x75\x92\xac\x38\xcc\x16\xc8\x12\xe2\xd5\x56\x45\x4b\x67\x63\x39\x9d\xce\x2d\x9b\xe5\x58\x4f\x70\x58\xf7\x58\x00\x21\xc5\x23\xff\xd1\xa4\x33\x58\xae\x92\x8b\x72\x5b\xa8\xf2\x6c\x8d\xa8\x35\x9c\xa6\xba\x2a\x25\x33\xb3\x64\x3c\xd1\x44\xb3\x37\xb5\x5a\xe9\x18\xe6\x54\xd1\x0b\x2d\xb7\x7d\xb3\xd5\x6a\xfa\xbb\xa8\xcd\xca\xaa\x1b\x4f\xa9\x71\x25\xbb\x29\x35\xe7\x71\x34\xcf\x94\xdf\x66\x73\xb6\xab\x9a\x2b\x45\xab\xbf\x8d\x33\x5a\x2f\xd5\xaa\x25\xf2\x40\xf2\x77\x84\xe6\xf4\xf6\x20\xb8\xf7\x12\xb2\xe3\xe5\x78\xe5\xb2\xb7\x49\x0c\xde\xa6\x28\xbe\x02\xf9\xf2\x7c\x81\x38\x4d\x41\x66\x6b\xc5\x75\x60\x6a\x23\x35\x37\x02\x51\x55\x06\x93\x42\xac\x2e\x3b\x8d\x1a\xaf\x6f\xba\xf2\x70\x20\x9b\x90\x67\x93\x68\x96\x4a\x72\x6f\x8d\x96\x82\xcf\x9b\x2b\xa8\x5a\x65\x43\x5e\x73\xbc\xda\x98\x64\xb2\xe9\x82\x28\xfc\xfd\xf7\xd7\xe3\x2d\xb9\xe9\xa3\xad\xac\x87\x8f\xa5\xc3\x8f\x9e\x5c\xe4\xc9\x60\x42\xb4\x80\x3a\xa0\x5b\xc4\x64\x4e\x20\xa3\xa8\xa4\x09\x67\x3d\xaa\x77\xf3\x3d\x7e\x25\x0d\xcc\xba\x08\x51\x9b\x6b\xea\x29\xf3\xf0\xa8\x2b\xdb\x54\xaa\xd5\xf2\x8e\x5d\x10\xf2\x49\x2e\x5d\x59\x77\x34\x32\x51\x1c\xb5\xf2\x4b\x72\x3e\x7c\xb3\x19\xb8\x00\x19\x58\xcc\x64\x70\x9b\x16\x49\x50\x6b\x35\xab\xba\x33\xf4\x0f\x42\x40\xf1\x99\xf7\xe8\x2f\xd7\xb7\x22\x1b\x1b\xfb\x8f\x1e\xe4\x5d\xdd\xeb\xb2\x7b\x74\x90\x78\xd4\xf9\xd6\xbc\xc4\x14\x50\x19\x0e\x46\xeb\x22\x6c\x56\x78\x46\x7c\xd3\x6c\x1e\xe1\x8a\x69\x95\x7a\x9d\x37\xb1\x9d\x1b\xa7\xcc\xfc\x4e\x37\x04\xa1\x4c\x5b\x59\xe5\x60\x1b\x62\xa0\xff\x4e\xfa\x2e\xe4\x12\x5f\x8c\x3f\x11\x05\x7f\xc2\x3b\x27\xe3\xd0\xd0\x7d\x3e\xb1\x30\x49\xd3\xa1\xe8\x79\xa2\x22\xad\x67\xd5\x38\x69\x66\x4a\xb1\x37\x82\xad\x6d\x74\x9b\x30\xb4\x62\xaa\x3b\xa9\xb6\x07\xd6\xa2\x1e\x6b\x78\xdd\xdb\x6a\xe2\x3e\xe2\x42\x9b\x4a\xe1\x68\x58\x66\x84\x0d\x9f\xc0\x2b\x76\x5a\x1a\x2c\x15\x82\x25\x88\x26\xcf\x75\x47\xd4\xa4\x30\x9e\xf0\x55\x96\x1e\x27\xc8\xa5\xa7\x0f\x0b\xb8\x19\x88\xf1\xfd\xb5\x0a\xa3\xd9\xfd\x9e\xfe\x39\xf4\xb5\xc7\x4c\xf5\x16\x7d\xae\xfc\x52\xee\x47\x57\x9e\xe2\x02\x26\xe4\x56\xa7\x07\x92\x46\xa7\x0d\xad\x16\xd3\x5c\xaf\xe4\x36\x99\x2e\xe5\x06\xb3\x29\x29\xd4\x13\xc3\x6c\x6a\x46\xcb\xeb\x7a\xf6\xc8\xf9\xb8\xfa\xf8\x84\xbe\x3f\x63\x9f\x15\x0d\xf7\x6c\xc6\xd3\x87\xd0\x83\x21\x8e\xf4\xd5\x73\x08\x3f\xc5\x1f\xb5\x5a\x8d\x9a\x0f\xca\x91\x07\x9d\x1a\x23\xb1\x66\xb2\x80\x17\xaa\xb1\x55\xb7\x9e\xe0\xdf\x3a\xcb\x4e\xab\x41\xae\xf5\x8a\xde\x5d\xd4\x65\x22\xb9\x9c\x54\x0b\xc8\x3b\xba\xec\xe0\x0f\x5c\x7a\x4a\x61\x4c\x7a\xf4\x35\xf7\xfc\x0a\x69\xda\xcc\x39\x2d\x75\xda\x2d\xb7\xd4\xde\xdc\xe9\xcc\x1a\x19\xd1\x91\x95\x2e\x3e\x49\x4c\x34\x45\xcc\xe6\xa5\x41\x7b\x6a\x2c\x53\xd9\x21\x7c\x96\xbe\x32\x6d\xe5\x85\xcc\x41\xd5\x0e\xfa\xee\x75\xeb\xc1\x89\x86\x5e\x47\xfd\x13\x69\xbc\x78\x42\x7f\x44\x71\x9c\xb7\x05\x6d\x4f\x39\x27\x04\xfc\x61\x8d\x82\xc5\x2b\xa4\x1f\xd9\x8f\x77\x5c\xc3\x83\xf6\xf3\x84\x3e\x5d\xf6\x3f\x62\x90\xca\x8c\x42\x18\x67\xa4\x7b\x47\x37\x46\xd7\x97\x27\xc6\xb7\x22\x6f\x1b\x83\x2b\xfa\x72\x74\xb5\x93\x4a\x30\x74\xf3\xc7\x3f\xe1\xd0\xbe\x0c\x12\x71\xa1\x4c\xd1\x5d\x31\x49\x3a\x99\x56\xaa\x4c\xd4\x48\x01\x2f\xa2\x71\x85\xcb\xd5\x98\x69\x89\x10\x78\xd4\xd6\xd5\x4d\xd6\xf1\xec\xa3\xd6\x6a\xd5\x7d\x7d\x19\xc4\xc5\x11\xd7\x22\xf9\xd5\x28\x4b\xd4\x2d\x9e\x31\x15\xb6\x3c\xb1\x9c\x21\x18\x89\x6b\xbe\x50\xae\xaa\xfc\xb8\xd5\x92\xb2\x56\xb7\xee\xe9\x03\x3b\xb1\xcd\x70\x7d\x39\x5c\x67\xfa\xfc\x71\xf4\x89\xc9\xf6\x84\xb9\x46\xdf\x21\x9e\x38\x8c\x9f\xc9\xc3\xed\x47\xc7\xa7\xad\x3c\x26\xca\x01\x5e\xb8\xfe\x9d\x8f\xed\xbb\xeb\x68\x7c\x8c\x8c\x7f\x4c\x45\xc3\xef\xc5\xb2\xff\x79\xaf\x40\xd9\x5d\x73\x9a\x9a\x53\xb4\x3f\x63\xe7\x9e\xbf\xbb\x35\x1a\xfc\xf6\xdc\xfa\x68\xfe\xc7\xb3\x88\x21\x19\x00\x39\x42\x56\x18\x19\x42\x95\x81\x00\x68\x48\x46\x08\x02\x44\x32\x48\x23\x01\xc9\xc9\x0a\xcb\x72\xb4\x4a\x02\x55\x83\x38\x29\x53\x8c\xa2\x72\x0a\x87\x00\x4b\xc9\x5f\x77\xcb\x1c\x2f\x99\xff\xd1\x37\xe6\x7f\x2c\x01\x68\xe6\xf2\x31\x58\xdb\xbb\x87\xf9\x9f\x9f\xe1\x7f\x76\xfe\x97\x0c\x74\xfe\x2b\xe7\x7f\x99\xdc\xca\x53\xc1\x0f\x9d\xff\x35\x24\xe7\xc8\x86\x8e\xae\xf4\x9e\xff\x6a\x86\xa9\xb3\xeb\x78\xb5\x90\x98\x0d\x9c\x38\x18\xf6\x4a\xbd\x61\x47\x9a\xa5\x66\x70\xa3\x34\x99\xf6\x08\xd5\xc9\xb7\x42\x91\x48\x8f\x90\x56\x4a\xb3\xb2\x93\xa4\xe4\x42\x62\xd1\xdd\xb4\x73\xeb\xa5\x22\x97\x34\x96\xe1\x7a\x95\xb7\x5c\xa7\x52\x56\xa5\x06\xdb\x4d\xac\x86\xf4\x4c\x18\x34\x1f\x9c\x03\x3e\x11\x73\x1d\x81\x16\x79\x6a\xe6\x7d\x7a\x22\x26\x16\x94\x69\xd2\x97\x77\x24\x7a\x9e\x1d\xb3\x05\x63\x15\x3f\x99\xb4\x6b\x68\x77\x24\xed\x07\x8e\x61\x39\xa5\xe2\xeb\xeb\xf1\x7c\xfe\xfd\xe6\x97\x91\xe6\x77\x2f\xc4\x9f\x8c\x82\x3f\x79\x18\x1f\x53\x47\xb7\x1e\x9d\x1f\xb1\x13\x7b\xe0\x05\x90\xee\xf7\x66\x00\x9e\x7f\x55\xcf\xf1\x0b\xc2\xd2\x5a\xf9\x32\x48\xd6\xde\x96\xe1\xcf\x74\x0f\xdf\x1f\x8d\xdf\xb6\xf1\xa3\x37\x69\x70\xfb\x47\xac\xee\xe9\x0b\xa1\xe5\x54\x66\xa2\x00\x76\xe7\x19\xa7\x2a\x76\x37\xf8\xcc\x91\xfe\xfc\x6a\xf1\x7c\x70\xbe\xfe\x70\x3c\x1f\xdd\x37\x49\x3a\xb9\x08\x9f\xaf\xfb\x7d\x30\x67\x8c\x6b\x27\xc7\x1d\xe6\x7f\x9e\xbd\x3d\xaa\x0f\x47\xfd\xeb\x5e\x4f\xcc\x07\x0f\xfa\xea\xf6\x67\x21\x94\xde\x83\xfe\xfe\x74\x7a\xc5\x06\x9b\xbe\x49\xef\x4a\x38\x9d\x2f\x3d\x18\x8b\x3c\x43\x5f\x09\x36\x66\xe1\xf3\xeb\x50\x79\x7e\x38\x7d\x85\x29\x29\xdf\xa4\xef\x25\xfa\xe9\xe5\x2b\x9f\x18\xfb\xdc\x2b\x39\xa6\xbc\xe1\xc1\xa3\x27\x1d\xda\xdf\x2f\xd1\xcf\xd7\xd0\x2b\x96\x70\x74\x93\xde\xa0\x7e\xfe\x3a\xf3\xf9\xa7\xf3\x3f\x4f\xc8\x77\x0e\x75\x74\x6d\xbc\x38\xba\x36\xca\xca\x0c\xfe\x56\x14\x4e\xc7\x0b\x81\xed\x16\x38\x81\x1d\x19\x03\xa9\x82\x70\xb5\xd9\x64\x5b\x19\x25\x59\x5d\x33\xd5\xf8\xca\xc8\xcc\x15\xb2\x99\x24\x68\x98\x23\xb3\x3a\xe1\xb6\x7f\x22\x96\x94\x4a\x50\x36\x1f\xcd\x3f\x7f\x24\x7d\x6f\x05\x39\x7b\x8d\xbe\xbf\xc3\x72\x11\x3f\x29\x17\x20\xbc\x28\x17\x31\x6a\x46\xc3\xef\xe7\x22\xb4\x59\x61\x99\xe1\x05\x3b\x3f\x49\x90\x71\x98\x1a\x13\x93\x94\x52\x1f\xb7\x0d\x2b\xb7\x6e\xcc\x60\x89\x2e\x68\x45\xfb\xad\x09\x4b\x34\x87\xcb\xce\x02\xaf\x0c\x6d\x3b\x4f\x8f\x72\xdd\x69\x9a\x5f\xdb\x44\x7c\x69\xad\xc7\xf1\xa2\xa1\x70\x34\x5e\xab\x38\x83\x42\x22\x33\x19\x27\xc4\xea\xc7\xe6\x22\x70\x48\xc8\x32\xa5\x29\x1c\x22\x79\xa8\xf0\x3c\x4b\xe2\x8a\x42\x32\x24\x60\x14\x1c\x70\x3c\x03\x08\x9e\x66\x20\xa3\xf1\x2a\x40\x3c\x40\x88\x07\xac\xca\x32\x00\x32\x2c\xce\x51\xb8\xa2\x78\xb9\x08\xf2\x45\xb9\x08\xe6\x56\x2e\x02\x10\x0c\x79\xf9\xbc\xee\xdd\xdd\x93\xda\xbe\x67\x73\x11\x41\x23\x7d\x69\x2e\x62\xc9\xf8\xae\xf0\x03\x73\x11\x6e\xfe\x3f\x78\x1d\xad\x45\x0b\xd9\xd8\x8c\xd1\x95\x72\xc1\xa8\xf7\x36\xcd\x7a\x33\x27\xc4\x6c\x3c\x39\x2c\xc4\x8a\x8d\x64\x5e\x20\x51\x7b\x89\x68\x3c\x5d\xc9\x68\x2b\x53\x86\x08\x29\x4c\x27\x31\x51\x70\x34\xae\x3b\x38\x31\x5d\xd5\xa9\x52\x61\xa2\x6d\xb4\x46\xba\x37\xe5\xd4\x5a\xad\x97\x18\x54\x9b\xa4\x50\x0d\xae\x45\x37\xc2\x62\x8f\xd2\xf6\x37\xde\xe3\xeb\x23\xe6\xba\x91\xe6\x9a\x2f\xc4\x2f\x3d\x88\x5f\x78\xbd\x0f\x8e\xea\x03\x85\x17\xf9\xe0\xe1\x2a\x1a\x7e\xdf\x07\xbf\x97\xb2\x46\xf3\xc1\xbb\xea\xf8\x07\x9d\x30\x47\x32\x2a\xc5\xa8\x2a\x09\x01\x43\xd1\x34\xae\x00\x59\xa5\x70\x9c\x55\x08\x1c\x87\xb8\xc2\xd3\x32\x4d\x2a\x88\xe5\x18\x06\x67\x11\xa4\x18\x9e\x50\x08\x88\x73\x34\x0d\x34\x0e\x11\x10\x7a\xe7\xd1\x13\xcf\xec\xa1\x7b\x24\x21\x4c\x72\x1c\x77\xf9\x3d\x22\xbb\xbb\x27\x75\xd1\xfe\x2b\x0e\x1e\x0b\x72\xef\x4b\x08\x1f\x25\x08\xde\x7b\x12\xbc\x0f\x62\x45\x61\xb8\xa9\x32\x12\xbe\xe4\xa5\x8a\x50\x52\x06\x95\x2e\x74\x38\x3c\x55\x9e\x1a\x72\xaf\x9e\x68\x65\x26\x8b\x79\xad\x56\x01\x68\x5d\x35\xe2\xf3\x6e\x5d\x98\xa0\x41\x6c\x63\x50\x1a\xce\x8d\x12\xb9\x44\xbe\x4b\xf7\xa8\xb2\x58\x68\xbd\x49\x84\x9d\x8b\x65\xe8\x36\xd9\x26\xdb\x2b\xfd\xdc\x49\x86\x26\x6b\x83\xb2\x10\xa2\xc8\xd6\xbb\x3e\x26\x81\x70\xd1\x91\x1f\xb1\xf7\x68\x82\x77\xeb\x48\x3d\x41\x1c\x25\x2d\xcf\x2a\xac\x6e\x38\xf2\xd7\xe1\x4f\x46\xc7\xff\xea\xa4\x65\x51\x08\x29\xa0\xbb\xe5\xc4\x5f\x8d\xff\x5c\x47\x43\x93\xa6\x87\x2b\x34\x69\xea\x5e\xbf\x50\x92\x6c\xb5\x67\xf4\x13\x15\x75\x04\xfb\xe0\x73\x16\x9d\x24\x62\xcb\x73\x9d\xf5\xae\x1b\x8b\xe0\x51\xf4\xf5\x78\xe2\x19\x5a\x70\xfa\xce\xf6\x72\x1c\x74\x3d\x82\xdf\x0f\x7a\xde\x6b\xf0\xf9\xc8\x89\x27\xc1\x42\x56\xa5\x18\x45\x25\x39\xf7\x30\x3c\x19\x21\x0d\xca\x84\x02\x08\x9a\x05\x04\x50\x64\x0a\xf0\x38\x02\x14\x03\x20\xc9\x50\x9c\x86\xe3\x94\x4c\xf1\x0a\x09\x59\x92\x65\x20\xe3\xc7\x3c\xe0\x45\x31\xcf\xcd\x89\x27\xc9\xe3\xfc\xe5\xd7\xe7\xec\xee\x9e\x6c\xe1\x7a\x36\xe6\xb9\x32\xf1\x74\x6d\xe0\x63\x12\xab\x47\x31\x8f\xde\xc9\xbc\x65\x19\x6b\x44\x82\x78\x4f\x5d\x94\x73\x46\x76\xc8\xc5\xda\xe9\x7a\xa9\x60\xcf\x66\x39\x02\x54\x46\x71\x34\x76\xa6\x00\x6f\x89\x49\x76\x8c\xaf\xdb\x23\x1e\x24\xd0\x9b\x5a\xb7\x06\x02\xcd\x82\x4e\x95\x1c\x36\x3b\xed\x6e\xd3\xac\xb0\x95\xf4\x72\xbc\xe9\x24\xbb\x6f\x89\xd5\x47\xc7\x3c\x1f\x93\x94\xfe\x80\x98\xc7\xfb\xb8\x0a\x62\x0e\xa8\xcd\x99\x1f\xc1\x15\x36\xfc\x99\x17\xc6\x00\x55\xe1\x65\x31\xc0\x61\xcc\x7a\xb5\xfc\x3c\x41\x7d\x5e\xf9\x9d\x07\x8f\x51\x16\x9e\xdd\xeb\x17\x5a\xc8\x79\x36\x86\x7a\x36\x31\xf6\xde\x31\xd4\xbb\xd0\x77\xa6\x2a\xe5\xc6\xf0\x44\x49\xc3\x62\xa8\x9f\x14\xc3\x08\x2f\xb2\x97\xe3\xc4\x51\x84\x18\xea\xbd\x06\xb3\x8f\x8c\xa1\x18\x86\x61\x68\x06\x32\x08\xaa\x08\xe0\x1c\x50\x68\x96\xc3\x69\x96\x00\x0c\xab\xf2\x88\xa2\x68\x12\x21\x44\xb3\x1c\xa1\x40\x1e\xd2\x1c\x84\x24\xc1\x23\x19\xd7\x10\x47\x52\x34\xad\xa9\xfb\xd3\x15\xa2\x9f\xb6\xe1\x9d\xcc\x70\x35\x74\x62\x19\x8e\xbb\xf8\xaa\xfe\xfd\xdd\xe3\x9d\xaa\x7e\xe4\x54\xe0\x32\xd5\x65\x75\x2c\xe7\x41\x46\x20\xdb\xad\x51\xcd\xca\x4f\x46\x1d\x1c\xd7\xd2\x9c\x5d\xc8\xb2\x13\x5c\xaa\xad\x72\xed\xb8\xd0\x21\x85\xd3\x77\x76\x87\x96\xf8\x1e\x5f\x91\x66\x2f\x47\xf0\x5a\xcb\x55\x8a\xdf\xea\x9f\x24\xaa\xc9\x0e\x02\x64\x93\x42\x7c\x02\xd4\xd7\x33\xb1\xd0\xab\xad\x09\x2b\xf7\x56\x4f\x15\x72\xf8\x3a\x99\xc4\x17\xf9\xf4\x6c\x32\x97\x35\x23\xd9\x88\x75\x3a\xd9\x39\xd3\xd4\x93\xe2\xdb\x24\xb5\x76\x62\xe9\x72\xac\x33\x4f\x99\xd5\x8a\x6a\x75\x1a\xec\x8c\x30\x0b\xbd\x6c\x66\xde\x28\x56\xee\x88\x88\x4e\x54\xfa\x34\xda\x38\xe2\xd9\xb5\x91\x60\x46\x40\xd4\xe3\x22\x5e\xc0\x73\xe9\x8d\x33\x5c\x95\x08\xa3\x8b\xc3\xcd\xcc\x24\xf8\x52\x66\xbd\x2c\x24\x36\x65\xda\x11\x25\x25\xe1\xf1\x48\x0e\x1c\xab\x3c\xed\xc6\xa9\xa3\x34\x5b\xe8\xab\xa0\x6f\x59\xfb\x13\xf8\x4b\xd6\xa6\x51\x7d\x02\xbf\x10\xc0\xff\xf0\x32\x8d\x5b\x46\xee\x5e\x67\x19\x9e\x5b\xf8\x43\x97\x4d\xc5\xe8\xb2\x28\x4f\xcf\xde\x4d\xff\x90\x2c\x9e\xed\x8b\xad\x2e\xc4\x94\x00\xbc\x87\x64\xf1\x9f\x4e\x95\x20\x1d\x87\x28\x67\x96\x55\x67\x6c\xc3\x6a\x1d\x34\x15\x15\x6e\x14\x7c\x58\xdf\xa8\xc5\xea\x8a\x2f\xe8\xc3\x79\x6f\x3e\x21\xe9\x2a\x1e\x37\x88\x4d\x7e\x61\x64\x07\x2b\x85\x1e\x2a\xb2\x36\x1c\x2d\x0d\x66\x08\xa5\x24\x09\x09\x3c\xc6\xa8\x30\x01\xea\x22\x33\x7e\x4b\x7e\xb0\xe7\xd5\x64\xc4\xa8\xac\x46\xf1\x0a\x00\x90\xc6\x71\x59\x23\x11\xc0\x71\x96\x60\x29\x5e\x81\x04\x20\x59\x9c\x00\x50\x55\x64\x9a\xd2\x54\x45\xa1\x29\xa4\x40\x55\x63\x71\x45\x83\x1c\xe2\x68\xff\x7d\xc4\xe4\x8b\x66\xaf\xec\xed\xd9\x2b\x60\xaf\xcd\x5e\xbd\xbb\x27\xe7\x86\x3c\x3b\x7b\x0d\x96\x4d\xbe\x70\xf6\xfa\x4c\x49\x31\x1f\xf7\x23\x52\xd7\x9f\x27\x43\xf5\x34\xb5\xe7\xa7\x2a\xd8\x69\x95\x32\x15\x76\xc9\x74\x56\x25\x66\xa0\x29\x5a\xa1\x13\x07\xdd\xec\x6a\x54\x4b\xa6\x50\x45\x28\xbe\x95\x9b\x55\x25\x26\x4e\xb2\x2d\xd4\xaa\xb3\xc4\x6a\x41\x73\x36\x53\x48\xb3\x7a\xb7\xa9\xa5\xab\x82\xce\xbc\x35\xb3\x8c\x69\x49\x13\x05\x08\x99\x91\xb0\x49\xbc\x25\xaa\x77\x95\x64\xbf\x70\xc6\xfb\x99\xe5\x7d\xa5\xa4\xf9\xc5\x33\xbd\xf3\x75\xc5\xd0\x99\x5e\x81\xe1\xfc\x12\x9a\x0f\x99\xe9\x35\x43\x08\x79\xa6\xc4\x58\x79\x0f\xf9\xa5\x3e\xb9\xfc\x5e\x53\xa2\xfd\xec\x96\xcc\x9f\x33\xb3\x13\x4e\x57\x93\x3e\xbc\x24\xef\xf2\x16\xbb\xa0\xad\x8b\x64\xa9\x17\x1e\x97\xfc\xb7\x6f\x69\x4e\x3e\xdb\x3f\x4f\xd0\x77\xab\x7f\x8e\xec\x35\xec\x3a\xb2\xd7\x8f\x2e\xb1\xbf\xb5\x65\x56\xd4\x3a\xc3\x0b\x54\xbf\x3e\xdb\x11\x35\xdb\x20\xbc\x83\xcf\x8b\x90\xed\x48\xac\x7a\xa4\x3e\x7c\x5b\xc4\x67\x9a\x40\xce\x45\x7e\xcd\x39\x5a\xbc\x37\x18\x25\x4a\x52\xb1\x45\x71\xc2\x5b\x91\xae\x89\x6f\x54\xba\x3b\x6c\xd1\xad\xc2\xb2\x93\x60\xa7\x9b\x37\xd3\x96\x17\xb9\x61\x8d\xeb\x09\x89\x82\x55\xaa\x8e\xe6\xba\x5d\xef\xbd\x75\x05\x54\x4c\x66\x0b\xc5\xdc\x47\x97\x2a\xf2\x94\xc6\xf2\x32\x0b\x34\xa8\xaa\x08\x6e\x63\x5f\x1e\xf0\x90\x97\x71\x82\x55\x08\x85\x26\x28\x96\x26\x34\x0d\xe2\x90\x55\x35\x5e\x53\x65\xc8\x2a\x88\x23\x14\x1a\xd7\x58\x1a\x72\x00\xff\xfa\x0d\xa3\x76\xc7\xe6\x44\x7c\xf7\xc5\x51\xcc\x4d\xde\x8a\xb9\x69\x1c\x80\xcb\x69\x8f\xdd\xdd\x93\x73\xf1\xbe\x46\xb1\x93\xa3\x98\xfb\x4a\xde\xe3\xe7\xf8\x9d\xc3\x95\xd9\xd3\x5b\x2d\xce\x81\x34\xcb\xe3\x85\xce\xaa\xa7\xd7\xad\x55\xc7\x9e\x08\x09\x4b\x9c\x0f\x3a\xb5\x78\x6c\x5c\xc9\xce\xd2\x44\xb3\x38\xe8\x55\xa8\x18\x6c\x51\xcb\x06\x53\x96\x56\x4b\x61\x50\x13\xcd\x3c\xac\x55\x46\x39\x95\x2e\x77\xb8\x41\x59\x2c\xe7\x96\x78\x2d\x5f\x41\xd5\xb2\xdc\x9b\x50\xd5\xd5\x3d\x31\x75\xf8\xd6\xea\x60\xdc\x79\xd4\x28\x42\x9e\x28\x57\x3e\xf4\xc7\x85\xeb\x46\x55\xc8\xeb\xf0\x9f\x87\x6c\x77\xe0\x3f\x5b\x65\xff\x68\xbf\xef\x91\x72\x4f\xa9\xbc\xf4\x53\xe8\xbb\x79\x94\x4c\x68\xce\xe7\x27\xe5\x9f\x02\xb2\x8a\x8c\xff\xf8\xd8\x80\x47\xf0\xef\xb6\xed\x5b\xdd\xfa\xd8\xaa\x3a\x9a\x38\xc9\xe5\x97\x22\xda\x74\x85\xbc\x9d\x9e\x8b\x6a\x26\xce\x54\x39\x7d\x2c\xb7\xaa\x1b\x71\x1c\x1f\xd1\xb3\x8e\xce\x57\x4c\xaa\x91\xe0\x12\xa2\x94\x1e\xcc\x66\x52\xac\x68\x90\x63\x5a\xdb\x08\x94\x44\x4d\xe2\x35\xc9\xe4\x69\x81\x76\x26\xf2\x30\xf9\xc1\xdb\xf6\x49\x0d\xe7\x64\x0d\x12\x48\x91\x35\x9e\x94\x09\x44\xf2\x34\xa4\x64\x9e\x80\x80\x03\x88\xa6\x48\x45\x93\x09\x55\x65\x15\x42\xa3\x18\xc4\xf2\x00\xdf\xb6\x03\x24\x87\x38\x40\xf1\xb2\xe2\x8d\x3f\xe0\x99\x37\xfa\x3c\x36\xfe\x90\xec\xb5\xf1\xc7\xbb\x7b\x72\x06\xaa\x5f\x2a\xff\xd8\xd6\x91\xf7\x1c\x7f\x9e\x9d\x97\x1c\xe1\xdf\xd3\x5b\x2d\xb6\xe3\x73\x3d\x56\x4e\x58\x05\x6e\x36\x55\xde\x16\x56\x8e\x11\x47\x8a\x51\x93\x3b\x89\xee\x4a\xc0\xc5\x5c\x09\xae\xf2\x72\x5b\x79\xd3\x84\x55\x6d\x31\x34\x97\x00\x4c\x9a\x32\xa1\x41\x20\xa6\x0b\x86\x9e\xd1\xb8\xda\x9c\xa9\xe9\xf9\x41\xad\x22\x16\x96\x44\xc6\xca\x67\xb2\x2b\xfb\x5d\xc6\x9f\x08\xf3\xc8\x97\x8e\x3f\x4f\xe2\xff\x99\xe3\xcf\x13\xdb\xfe\x85\x8f\x18\x7f\xde\xe3\x28\x21\xff\xba\x39\xfe\x44\xb7\xa5\xd7\x8c\x3f\x11\xf0\x3f\x39\xfe\xac\xe5\xd8\xbc\x40\x51\x79\x7b\xb9\x99\xa8\x6f\x65\xc6\x9e\x9a\xe9\xd2\xa6\x95\x72\x94\xdc\x48\x48\x56\xa5\x31\x61\x09\x33\xa7\xf7\x56\xe2\x92\x62\x9a\x49\xeb\x71\x19\xf6\x6a\xcb\x16\x6f\x75\xa5\xee\xa2\x9d\x55\xe3\xeb\xb4\x35\x4b\x67\xe7\xa2\xc4\x49\x8b\x78\x13\xd9\xa6\x32\xfa\xe8\xd5\x5e\x96\xc7\x81\x8c\x53\xaa\x86\x6b\x32\x49\x6a\x10\xd2\xbc\xcc\x91\x1a\x4f\x70\xb2\x46\x40\x96\x27\x21\xc1\x00\x59\x05\xaa\x42\xaa\x14\x25\xf3\x3c\xc9\x23\x96\x66\x15\x8d\x55\x64\x96\x61\x09\x6f\xfc\x21\x5f\x34\xff\xb9\x75\x6c\x28\x4b\xe3\x14\x77\x79\xcd\x61\x77\xf7\xe4\xbc\xeb\x67\xe7\x3f\x57\x8e\x0d\xf5\xd4\xef\xc1\xed\x3a\xef\x33\xff\x49\x24\xd6\x43\x24\x52\x89\x9e\xd5\xd5\x53\x5a\x51\x68\x33\xca\x78\x14\x1f\x35\x72\x6f\x19\x7d\xc8\x26\x9c\x1a\xd7\x48\xe2\x69\x65\xd9\x92\x99\x38\x23\xb6\x75\xbe\x05\xa6\x62\x75\x99\x74\xe2\x1b\xb2\x34\x15\x9d\x8d\x2d\xa7\xa4\x72\x91\x48\xb7\x18\x66\x9d\x72\x16\x5c\x2b\x95\x16\xaa\x9f\x71\xfe\x13\xc9\xff\xbf\x10\xff\x85\x8a\xe2\x28\xe3\xcf\x07\x1e\x05\xe9\x91\xf2\xe0\xf8\xf3\x99\x8e\xd2\x0c\x1d\x7f\x7e\xd2\xfc\x43\x78\xd1\xfc\xe7\xb8\x62\xfc\x11\xfc\xfe\xf8\x93\x2d\xa4\x53\x54\x66\x90\x9b\x38\x7a\xb6\xc5\xad\x44\x79\xb6\xa9\x57\x62\xa5\xe2\xb4\x88\xf2\x19\x3b\x4f\x64\xd6\xc5\x4a\xb5\xb7\xe1\x5b\x4b\x2b\x6e\xa6\x60\x81\xe8\x40\x25\x95\xe0\xca\x64\xbc\xa0\x00\x25\x4d\xe6\xd7\x76\xb3\x4a\xbd\x35\x7b\x1d\xcb\x92\xda\x80\x5d\x37\x9b\xdd\x8f\x3e\xb6\x4c\x26\x34\x0e\x70\x24\x47\x29\x34\x83\x28\x19\x07\x94\x46\x01\x96\xd6\x00\xc5\xd0\x1c\x0e\x65\x28\x6b\x1a\x01\x11\x29\xf3\x32\x64\x08\x19\x27\x39\x9e\x25\x69\x16\xd1\x2c\x42\xb2\xe2\xe6\xdf\xc0\xae\x62\x3b\x72\xb5\x11\xb8\x59\x6d\xc4\xe2\xd4\x95\x6a\x23\xff\xee\xf1\x29\xf4\xcf\x56\x1b\x5d\x19\x75\xbc\xeb\xc9\x0d\xba\x27\xd5\x46\xda\x34\x55\x7f\xeb\xa1\x21\xc1\xbe\x39\x1c\x30\x8b\xea\x1c\x51\xb1\xf8\x7a\x6a\xc7\xc7\x19\x51\x4d\x77\x34\x5e\xcc\x8a\xb5\xae\xd6\xea\x91\xc9\x6a\x83\x84\xab\x55\x6f\x4a\x17\xe6\x83\x6c\x9a\xcf\xcd\x8d\x65\x71\x52\x23\x1a\x79\xb8\x56\xcc\x5c\x35\xb9\x98\xa7\x95\x44\x5d\x29\x7e\xae\x6a\xa3\x67\xab\x7d\x9e\xad\x70\x29\xae\x0a\x13\xf3\x95\xd5\x46\x1f\x18\x6d\xdf\x8a\xfc\x3f\xb2\xda\x47\x78\x51\xb5\x11\x47\x1d\x9e\xbf\x30\xab\xbd\x5a\x6d\xd4\xa1\xd7\x4d\x1b\x74\x4c\x15\x71\xac\x56\x9a\x27\x33\x70\xba\xa8\x2c\xb9\x1e\x5b\xa1\xc5\x55\xa7\x66\x90\xf1\x6a\x5d\x68\xb6\x33\x44\x5b\x5d\xe1\x12\x0f\xec\x62\xba\x17\xab\x33\x66\x42\x5c\xd6\xe1\x4c\x7e\xcb\x8d\xd5\xe6\x66\x62\x77\xf2\x89\xa6\xc0\xce\x87\x53\x61\x3c\xfd\xe8\xcc\x93\xc2\x93\x1a\x87\x33\x0c\xab\x91\xac\xaa\xb1\x38\x04\x3c\x52\x70\x15\xf1\x8c\xa6\x91\x24\x47\x30\x14\x05\x15\x0e\x70\x90\x52\x10\x24\x14\x99\x51\x90\x4c\xc8\x0a\x52\x18\x4d\xd3\x70\x9a\xf3\x22\x7f\xea\x45\x99\xa7\x3b\x22\x7f\x9a\x27\xae\x44\xfe\xde\xdd\x93\xb7\xca\x3c\x9b\x79\xba\x19\xf9\x7f\xf4\xa1\xb3\x47\xf8\x0f\x99\xa7\x34\x65\xb0\xe3\x84\x30\xa7\xe1\x7c\x59\x07\x6a\x3c\xd3\x70\xba\x0a\x5b\x10\x20\x3b\xab\x37\x75\xbd\x4c\xe5\x37\xf9\x9c\x3c\x9f\xd8\xc9\xc1\x52\x19\xa7\x13\x40\x95\x87\x8a\x65\xf2\x8e\xb2\x4c\xf4\x32\xda\x6a\xde\x68\xc5\xf4\xf1\x92\xcb\x4c\xb8\x9e\x06\x19\x72\xdc\xad\x8c\xab\xdd\xcf\x98\x79\x7a\x3a\xf2\x7f\x12\xff\x0b\x23\xff\x0f\x3c\x84\xc7\x23\xe5\xc1\xc8\xff\x03\xe9\x7b\x3e\xf2\xff\xc0\xcc\x8f\xf0\xa2\xcc\xd3\x93\x91\xbf\xac\x77\x16\xd5\x6c\xc2\x32\xe6\x73\xbe\xd0\x23\x39\xb5\x4c\x0c\xdf\x6c\x5b\xb4\x16\x46\xae\x9e\xcf\xb2\x03\x2b\x6b\x1a\x8b\x39\x5c\x95\x13\xfc\xa6\xda\x2d\xf4\x88\x45\x6a\xb3\x18\x01\x62\xc3\xe5\xc6\x6a\x3c\x31\x2b\x75\x98\x7c\x3d\xbe\x42\xf2\xda\xe0\x2d\x0b\xd5\x06\xb1\x9a\x38\xf8\xd8\xf1\x87\x23\x08\x82\x07\x0a\xc9\x31\x14\xa9\x6a\x2c\xa9\xe0\x04\x0d\x69\x48\xa8\x2c\x2b\x73\x38\x50\xb7\x83\x8c\x4a\x69\x34\xae\x29\x8c\x4a\xe0\x1c\xc1\x40\xc8\xd2\x0a\x0e\x19\x02\xe7\x35\x1e\xee\x5f\x79\xf9\x92\x6a\xd7\x9b\x2b\x1f\x0c\x8d\x13\x97\xc7\x9f\xdd\xdd\x93\x77\x91\x3d\x5b\xed\x7a\x65\xe5\xc3\x3b\xe4\x2d\x52\x26\x89\x0c\x54\x84\xb9\xd7\x51\x75\x6a\xc5\x18\xb0\xe9\xc2\x30\x37\xc0\xd7\xec\x68\x26\xac\x08\x69\xc5\x64\x40\x27\xc5\x6c\x6a\xd9\x89\x96\xcb\xae\x52\xda\x1a\xe7\x4b\x0b\x9d\x96\x9d\x72\x4e\x48\xa1\x55\x4a\x28\x69\x65\x28\x88\x5c\xaa\xda\x33\xe8\x19\x29\xd0\x03\x72\xcc\x24\x33\x49\x7d\xa0\x35\x4b\xcd\x24\xc1\x0c\x94\x7b\xc6\x93\xe3\xbd\x5b\xf7\xcc\x07\x5e\xbd\x5f\xfb\x4e\x1b\x14\x76\xe6\xff\x6a\xfc\x0f\x1c\x92\x23\x08\x9f\x77\x25\xfd\xe6\x7c\x21\x82\xac\x9e\x5e\x29\x78\xb2\xaf\xce\x0e\xb8\xbf\x13\xbf\xef\xaf\x63\xed\xa4\xdd\x5d\x48\x93\x64\x23\xb3\x28\x8f\x93\xc9\x66\x23\x69\x6a\x3d\xa5\x63\xe5\x24\xbd\xc7\x8d\x47\x42\x2b\x9e\x69\xe0\x80\x29\x18\x0b\x9c\x1a\x0b\x2d\x56\x68\x0a\x04\x47\x9b\x42\x66\xd5\x12\x27\x9d\xc9\x54\x49\x4e\x92\xa8\x61\x16\x95\x72\x5e\xe4\xab\x44\xb5\xd2\x99\x8b\x1f\xbc\x52\x20\xab\x14\xc7\xa8\xb2\xaa\xe2\x40\xa5\x18\x9c\x23\x58\x86\x25\x14\x0a\xd2\x90\x45\xbc\xca\x20\x8e\xa1\x15\x08\x78\x45\xa6\x08\xc4\x00\x95\x85\xd0\x9d\x54\x68\x08\xd1\x32\xc9\xa8\xc8\xf3\xd7\xaf\x3a\x60\xfe\x0e\x7f\x4d\x30\xe4\x15\x7f\xed\xdd\x3d\x79\xe3\xe3\xb3\x87\xba\x7d\xa0\xbf\x3e\x3a\xe0\x5d\xe4\xc7\x93\x7c\x1b\xcc\xc9\x25\x5b\xd5\x36\x5c\xa5\x88\xc6\x92\x4c\x34\x1a\x59\x5a\x5f\xcf\xc7\x59\x5c\x34\x07\x1d\xab\xec\xb0\x83\x32\xc1\x80\xaa\x3c\x1e\x02\xb5\xde\x68\x6a\x28\x69\x2e\x15\xbc\x22\x40\x6d\x98\xec\xac\x9d\x61\x4b\x30\xec\xc2\x62\x64\x88\x93\xcd\x48\x14\xee\x8a\xff\x9f\xf0\xd7\x2f\x79\xc9\xc4\x9d\x36\x28\x84\xf8\x80\x8f\x7e\xc9\x85\x20\x7c\xde\xcc\xff\xcd\x95\xdd\x08\xb2\x7a\xa5\xbf\xfe\x48\x5d\xf1\xfd\x75\x06\xd4\xbb\x33\x19\x5a\x28\xee\x88\xf1\xc2\x8a\x5b\x33\xd5\xda\xb2\x55\x2a\x8e\x26\x85\xf4\xbc\x3a\xaa\xa6\x75\x11\xd9\x0c\xb9\x10\xd8\x8e\xd5\x13\x17\xf5\x4c\x8f\xc8\x95\x6a\x3c\x55\xd6\xf9\xb7\x2a\x27\xce\x62\x52\x49\x4b\x83\x54\x33\xd1\x5e\x2d\x98\x72\x33\x2d\xe7\x8b\xd2\x47\xc7\xd7\x32\xad\x40\x55\x41\x38\xad\x29\x38\x54\x69\x95\xd1\x10\x8e\xf3\x32\x27\xe3\x2a\x92\x15\x5c\x25\x55\x4d\x25\x01\x82\x14\x90\x39\x24\x43\x12\xf1\x08\x32\x9c\x02\x58\x8a\x41\x14\x81\x6b\x9e\xbf\x76\x57\x76\x05\xba\x2d\x56\xba\x02\xdd\xa5\xda\x82\x94\xe9\xb4\x6b\xa0\x99\x2f\x83\x66\x99\x12\x9b\xe9\x4c\xb3\xca\x52\x52\xb3\x92\x2f\x97\x40\x35\xd3\xa2\xda\xb5\x4c\x39\x5b\x2b\xe5\xf3\x19\xf0\xa0\xbf\x06\xdc\xe5\x17\x82\xec\xee\x9e\xbc\x57\xd7\xd3\xd9\x07\x0f\xb9\x7c\xc4\x5f\x47\xca\xd7\x74\xc2\xfc\xb5\xb4\xc7\x5f\x15\x4a\xd5\xfa\xdb\x72\x26\x89\x09\xa1\xb3\xb4\x89\xca\x60\x92\x89\x37\x53\xb2\x26\x74\x1d\xb2\x2c\x0c\x06\xdd\x4a\xab\xa1\xe2\xb3\x51\x4b\xc9\xc1\x16\x69\x24\xa5\xf8\xa8\xdc\x2b\x4e\x0b\xa9\x5e\x71\x9c\x92\x86\x03\x4a\x35\x16\xad\xea\x1a\x25\x7b\xc2\xaa\x91\x6f\x56\xe0\x54\xb5\x57\x83\x77\xf6\xd7\x8f\xe6\x03\x5e\xed\xaf\x5f\x82\xff\x09\x7f\xfd\x99\xf2\x35\xb7\xfc\x75\x14\x59\xbd\xd2\x5f\x7f\xa4\xae\xec\x0e\xec\x24\xc4\x42\x39\x36\xae\x4a\x59\x11\xc5\xde\x9a\xb1\x44\x57\xe3\xab\x2d\x87\x13\x75\x52\xa1\x12\x09\x71\xc0\xb7\x4a\x64\x7d\x52\x6a\xad\x8c\x59\x07\x35\x8b\x8d\x58\x91\x1e\x6f\x14\xbb\x35\xde\x54\x9b\xf5\x74\x72\x08\xda\x74\x2b\x99\xa2\x4a\xe3\xa4\x58\x9c\x55\xf9\xb9\x0a\xde\x12\x1f\x5d\x09\x0a\x10\x25\x43\x42\x03\x04\x27\x33\x10\x02\x0a\xe0\x32\xc5\xb3\x14\xcd\x40\x42\xc6\x79\x9c\xc7\x11\xc9\x91\x2c\x62\x18\x99\xa4\x78\x1a\x27\x71\x95\x42\xaa\xca\xe0\x2a\xae\xe1\x34\x8b\x7b\xfe\x9a\x7a\x51\x3e\xe4\x66\x3e\x9e\xa1\x49\xfe\xf2\x79\x9d\xbb\xbb\x27\x6f\x2f\x7f\x36\x1f\x72\x25\x1f\xff\x6a\x7f\x7d\x94\x0f\x29\xe6\x26\xcb\x98\x31\x4c\xd1\xd5\x9e\x31\x50\xb3\x73\xb1\x93\xac\xab\x43\xc9\x19\x58\xb0\x61\xd5\xea\xab\x96\x45\xab\x71\xd1\x2a\x25\x00\x87\xb4\x4c\xd1\x5c\x77\x4b\x30\x06\x16\xbc\x53\x97\xd4\x75\x33\x36\x4c\x77\x98\x5c\xad\xcd\xae\x84\x14\x29\x97\x67\x02\x67\xad\xd7\x6b\x41\xfa\x15\xf2\x21\x8f\x1e\xda\xfb\x13\xcf\xcf\x13\x84\xcf\x5b\xd9\x19\xea\xaf\x7f\x52\x3e\x42\x78\xaf\xbe\xba\x13\xbf\xef\xaf\x57\x13\x18\x67\xda\x52\xc7\x10\x27\x6d\x11\xd7\xcd\x94\x52\xca\x01\xa9\x0e\x12\xce\xac\xec\xa4\x0a\x62\x7b\x69\x90\x5c\xda\xc6\x0b\xf2\x9a\xe6\x94\xcd\x28\x35\x20\x2c\x16\xb2\x80\xc8\xd6\xc8\x54\x83\x91\x7a\x9a\x69\xa4\xe4\xa5\x20\x74\x54\x9b\x19\x27\x37\xcb\x4c\x46\xfa\xe8\xb3\x06\x81\x0c\x10\x07\x54\x19\xca\x32\x0e\x28\x19\xb0\x10\x57\x48\x82\xc2\x15\xc8\x12\x2a\x07\x15\x5e\x56\x58\x82\x23\x09\x8d\xd7\x68\x48\xca\x2a\xc3\x23\x05\x92\x2a\xc7\x69\x32\x8e\x14\x5a\xf1\xea\x4e\xc8\xe7\x2a\x57\x6e\x86\xd5\x2c\x4b\x30\x97\x0b\x26\x77\x77\xbd\xca\x15\x86\x3b\x64\x41\xa2\x57\xae\x5c\x39\x55\xd9\xbb\x22\xec\x1b\xbf\x50\xb9\x92\xcc\x2d\x0c\xc2\x29\xa4\x0b\x29\xaa\xb5\x5e\x39\xb8\x9a\x4c\xb4\x24\x8d\x71\x64\xda\xa0\xe4\x4d\xd1\x4a\x0f\x12\xb3\x98\xd1\xea\x15\x27\x6b\xc5\xa1\x29\xbd\xa4\x81\xc9\xda\x19\xad\x99\xa2\x4a\xf7\x72\x94\x44\x25\x0d\xc5\xd6\x28\x46\x12\x86\x62\xba\xde\xac\xd8\x53\x4e\xeb\x26\x3f\x57\xe5\xca\xb3\x95\x23\xcf\x56\x4b\x14\xf0\x31\x23\xbc\xb0\x72\xe5\x23\xb3\xbf\xef\x51\xb9\x12\xb5\x72\x44\x78\x51\xe5\x0a\x7b\xd4\x01\x17\x5e\x63\x76\x75\xcf\x94\x3c\x53\xe5\xfa\x5a\x5f\xa3\x94\xa2\x14\xd4\x4c\x75\x65\xd4\x32\x31\xab\x1d\xeb\xa1\x34\x37\xca\xaf\x4d\x61\xae\xcd\x5a\xed\x46\xce\xee\x14\x10\xca\x8e\x3a\xfc\xcc\x96\xbb\x1c\x1a\x65\x50\xbb\x8e\xc4\xb2\x40\x77\x0a\x99\x58\x79\x28\x64\xab\xb5\xb1\x91\x64\x73\xf1\x0c\x10\x3e\x38\x13\x8d\x08\x56\x86\x88\xa6\x81\x0a\x71\x02\xa7\xa1\x4a\x02\x0d\x97\x79\x08\x55\x4d\xc5\x35\x06\x90\x48\x23\x59\x24\x53\x1c\x23\x13\xb8\x8c\x53\x94\x42\xf0\x80\xe4\x48\x06\x47\x14\x4d\xab\xac\xe7\x79\xa9\xe7\x3c\xef\xcd\x00\x99\x65\x01\x7b\xf9\xad\x22\xbb\xbb\xae\xe7\xa5\x71\xfe\xe8\x3c\xfb\xc8\x9e\xf7\xca\xd9\xae\xde\xf5\x60\xbd\xca\x35\xcf\xdb\xed\x6a\x9b\xb2\x35\xa9\x0c\xb5\xb1\xce\x18\x56\x25\x66\x26\xb4\xc5\x34\x37\xa9\x2d\xc0\x44\x5b\x1b\x14\x6e\xd2\xf3\x76\x8d\xdd\x10\xdd\x49\x85\x9b\x99\xe9\x18\xd3\x99\x0f\x28\x62\x94\x4f\xb4\x4b\xab\x96\x59\x61\x09\x36\xd1\x92\x2a\x88\xc5\xb3\xb8\x83\xda\xcb\x06\x1a\x8d\x73\x9f\xcb\xf3\x3e\xeb\xf9\x9e\xb5\xf6\x3c\x15\x2b\x75\x5f\xe8\x79\x3f\x32\x2f\xf0\x1e\x9e\x37\xaa\xe7\x13\x5e\xe4\x79\xe9\xd5\x4d\x44\xd7\x3c\x2f\x48\x67\xb8\xd1\x9c\x1e\x51\x1d\x3a\xbb\x98\xc1\xb7\xf8\x5c\x98\xb2\xb3\x4d\x6f\x2c\x3b\xb3\x29\xd7\x43\xa5\x7c\x19\x1a\x63\xc4\x39\xed\xdc\x28\x9e\x87\xe2\x72\x61\x30\x66\xb9\xd4\xdd\x0c\x8c\x91\x92\x82\xc9\x18\x8f\x56\x46\x2d\x49\x2e\xf8\x44\xa9\xd0\x31\x2c\x9c\x34\xe9\xc4\x07\xc7\xbc\x8a\xa6\x72\x1c\xc1\x20\x95\xe6\x58\x85\x46\x2a\xc7\xa9\x08\xe2\x48\xc6\x71\x8e\xe0\x14\xa8\x91\x9c\x82\xb3\x34\x8e\x58\x96\xc2\x11\x4e\xab\x88\x54\x00\x4b\xb0\x0c\xe2\x21\x42\x1c\x42\x9e\xe7\xa5\x9f\xf3\xbc\x37\x5f\x25\xe2\x6e\x3c\xbd\xe2\x79\xbd\xbb\x9e\xe7\xa5\xf1\xa3\xcc\x44\x64\xcf\x7b\xe5\x5c\x32\xef\x8a\xf0\x4a\x9f\x4b\x9e\xb7\x34\xa9\x0e\xd5\x2a\xda\x14\x95\x76\xaa\x5d\xe1\xd4\x56\x6d\x9c\x74\x52\x75\xca\xc9\x64\x13\x9b\xbc\x0a\x2b\xe3\x1a\x13\x8b\x17\xd8\x98\x53\x7c\xcb\xb7\xcd\xe6\x48\x4e\x0a\x1d\x5b\xa9\x75\xb3\xb1\x11\x93\x52\xe3\xad\x54\x13\x26\xdf\xd4\xae\xdd\x4e\x08\x76\x86\xc4\xdb\x8b\x51\xb6\xf0\xb9\x3c\xef\xb3\x9e\xef\x59\x6b\xcf\xf1\x9d\xc1\xea\x95\xd5\xda\x1f\xb8\x82\xf6\x1e\x9e\x37\xaa\xe7\x13\x5e\xe4\x79\xa3\x9e\x13\xea\x7b\xde\xb7\xde\x38\xdb\x69\x66\xec\x51\x26\x35\x6c\x8d\xe2\x99\x56\xb3\x27\xb0\xb5\xe6\xa2\x50\xdb\x08\xb6\x3e\x6d\x8f\x68\x09\x2d\x97\x9b\x58\xdc\x6a\x14\x37\xc6\x3c\x95\x05\xab\x55\x8a\xcd\x48\xed\x44\xc5\x8c\x0d\x3b\x1a\x51\x6b\xa5\x07\x1c\xd9\x2e\xa4\x06\x83\x82\xc8\xf3\x29\xcb\xdc\xbc\x66\x9f\xe6\x6f\xbf\x7d\xff\xfe\xdb\xf7\xef\x58\x12\x3a\x10\xd3\x4c\x0b\x2b\xc1\x09\xfa\x81\x8d\xd1\xa6\xbf\x84\xc6\x02\xf5\xb7\xce\x18\xfd\x85\x35\x36\x33\xf4\x03\x6b\x08\x62\x41\xc2\x92\x42\x43\xf8\x0b\xab\x2b\x43\x34\x81\x3f\xb0\xd9\x42\x36\x74\xe5\x2f\xac\xbc\x9a\x22\xeb\x07\xb6\x85\xf6\xdb\x89\x43\x0f\xc0\x3a\x8a\xa2\xd7\xb3\xbe\x3e\x1d\x20\xdb\xe9\x1b\x70\xfb\x07\xa9\x03\x64\x6d\x59\xc2\xbf\x5e\x26\xcd\xd4\x34\x64\xd9\x0f\x53\xb4\x83\xe6\x01\x81\x8a\x62\x2e\xa6\x8e\xdd\xb7\xf5\xc1\x14\x59\xf6\xd9\x0f\xfd\xd9\x18\x6d\x76\x48\x12\xe5\x52\xbd\x51\x13\xb2\xa5\xc6\x0d\x24\x42\xa1\x21\xd5\x7c\x9a\xca\xa5\x42\xf7\x0c\xec\x6f\x18\x86\x61\x42\x32\x79\x04\x32\x1c\x35\x56\xa9\x65\x8b\x42\xad\x8b\xe5\xa5\x2e\xf6\xbb\x77\xe7\xdb\xae\xe9\x91\x70\x7c\x76\x6c\x1b\x39\x7d\xdb\x81\x8e\x7d\xfc\xf9\x55\x4c\x1c\x20\x86\xd2\x1f\x40\x78\x4a\xba\xae\x9e\x51\x3b\x30\xad\x59\x7f\xa2\x0f\x2c\xe8\x0d\xee\x81\xef\x2f\xa2\x3a\x00\x35\x8c\xf2\x30\xc4\x37\xa9\xdf\xc5\x27\x2e\xdb\x76\xe0\xab\xf7\x9f\xbe\x62\xaa\xc8\xff\xe8\x6c\x66\xbb\x8f\xba\x6d\x2f\x90\xd5\x7f\x09\x77\xa7\x68\xc3\x98\x8b\x44\x18\xd6\x2c\x65\xab\x4d\x09\xfb\xfd\xd0\xfc\x1b\x76\x68\xbf\xfb\xec\x3d\xf0\xa0\x68\x5e\xd3\xad\x0f\x33\xfe\x50\xa7\x9a\x33\xe4\x29\x43\x7f\x06\x2d\x47\x57\xf4\x19\x9c\x1e\x71\x12\x7e\xfb\xc5\x9c\x85\x23\xb9\xc6\xe9\x15\xb2\xee\xe6\xfc\x28\xdc\x0e\xe7\xfd\x52\x83\x17\x73\x7f\x09\xcd\x35\xfe\xaf\x92\x76\x53\x02\xc1\xf1\x29\xf0\xfd\x45\xfc\x05\xa0\x86\xb1\x13\x86\xf8\x94\xfa\x31\xda\x9c\x91\xef\x8d\x87\xfe\x7f\x5e\x44\xac\x07\x2c\x8c\xc6\x23\x34\xa7\xa4\xb9\x37\x42\xa4\xeb\x39\x0c\x79\xe3\xfa\x92\x1d\x65\xd9\x52\x52\xea\xdc\x20\x2a\x51\x93\x84\x86\xe4\x35\x3d\x85\x82\x95\x4b\x41\x57\xd3\xac\x67\x4b\x69\x4c\x76\x2c\x84\x8e\x7d\xd7\x65\x6a\x3c\x0f\xf6\x3c\x3d\x1e\x9c\xfb\x28\xba\xe0\x35\xe5\x4d\xdf\x1f\xd7\x23\x93\x73\x00\x71\x4c\xc9\xc9\x0c\xfa\x94\x1e\xaf\xf1\x3e\xa0\xe8\xdb\x68\xbe\x40\x53\xe5\x5c\x60\xf2\xa6\x3f\x84\xf6\xf0\x19\xca\xb6\xcf\xdf\x47\xd6\xb1\x1d\x6f\x9f\x0a\xa3\xc6\x0b\x12\x9f\xa1\xc7\x83\x70\x1f\x45\x5e\xdb\xbd\x78\xbe\x61\x70\x36\x33\x74\xc5\x73\xb6\xa6\xa5\x5e\x18\x04\xfb\x68\xab\x1b\xee\xfd\x08\x94\xfa\x63\xb0\x47\x70\x00\xdc\x31\xd9\x48\xd3\x90\x12\x54\xb5\xf3\x31\x41\x57\xbf\x61\x5f\xdc\x87\xbf\x5c\x22\x56\x57\x5f\x44\xa6\xae\xde\x4d\xe0\x4e\xf5\xb6\xe4\x45\x20\xda\x9c\xf5\x67\xaf\xa2\xdb\x87\x75\x4c\xfa\x85\x40\x20\x12\x27\xe1\x0c\x38\xeb\xd7\x31\xe0\xc3\xba\xa0\xd3\x11\x59\x38\x86\x10\xc6\x84\x39\xdb\x6a\xe5\xd0\x8c\xc4\x83\x4f\xfc\x01\x46\x54\xe1\x5f\x17\xb4\xed\x5b\xbb\xeb\xaa\x9f\x97\xf5\x29\xb8\x63\x92\xbd\xdf\x03\x34\x86\x53\x74\x2c\xd7\x57\x91\x75\x06\xf3\x3e\xf7\x16\x46\xa0\xe3\x75\x89\xf3\x4c\xb7\x1e\x60\x44\x57\xc9\x5b\xea\xe7\x58\xea\x16\x89\x0c\x6d\xf4\xf4\xf8\x19\x06\x2c\x40\xb9\x8a\x02\x74\x1e\xb7\xbd\x49\xa0\x1b\x1d\xbd\x86\x3c\x17\xd4\x5d\xc4\xb9\x2d\xaf\x91\xe6\xd2\x8e\xac\x97\x89\x2f\x00\xef\x16\x91\x81\xe6\xf7\x50\xfa\x1a\x39\x9e\x40\xbb\x97\xca\x9b\xd2\x7c\x0d\x6d\x77\xd1\x74\x9d\x96\x1d\xc5\x86\x69\x8e\x17\xb3\xe7\x28\x3a\x85\x75\x77\x8f\x7a\xf1\xee\x05\xfa\x66\x50\xb7\xfa\x8e\x3e\x41\x2f\xa1\x30\x08\xed\x3e\xbb\xf5\x09\xfc\x86\x05\x49\xfe\x86\xf9\x2e\x5e\x31\x4c\x1b\xa9\x7d\x78\x9e\x6d\xf3\xd0\xbe\xc0\x6f\xfb\x70\x6e\x51\xfc\x60\x74\xb4\x85\xfa\x32\xe9\x3e\x20\xd8\x9b\x72\xd3\xa7\x2a\x5a\xf7\x03\x21\x87\xdd\x37\xa7\x7d\xa8\xaa\x16\xb2\xed\x67\x05\x7a\x13\xc1\xc9\x3c\xcd\xbf\x1d\x98\x19\x79\x0d\x1f\xa0\xfd\x79\x3d\xb8\x06\xfb\x36\xc5\x21\x56\x76\x0a\xd0\x8f\xc2\xb7\xf0\x9c\xcd\x2c\xfa\x1c\xfc\x2a\xd4\x9b\x61\xff\xb6\xd1\x0d\x42\xfd\x18\x6a\x0b\x72\xaf\x44\x2f\xa2\x36\x0c\xf4\xcd\xf0\xed\x5e\x4d\x3e\x02\xfe\x6a\x65\x38\x01\x1d\x25\xde\xbc\x0c\x6e\x32\x33\xad\xad\xe3\x5b\x22\xcb\xd6\xcd\xe9\xeb\x05\x1d\xc4\x70\x9b\xfc\xc0\x03\xf7\x33\xe3\xbb\x9e\x88\x99\x8a\xfb\xe4\x7f\x84\xe3\x26\x27\x47\x6d\xef\x67\x62\x66\xa1\xa5\x6e\x2e\xec\x0f\xe1\x26\x0c\xd9\x4d\xb6\xc2\x1e\xba\x9f\xbf\x5d\x12\xe5\xdd\x78\xda\x21\xb8\xc9\xc7\xc5\x6c\xd7\x29\xe8\xfd\x78\xfb\x2e\xa6\x1d\x84\x1e\x3a\x01\x7e\xd4\xc0\x4f\x81\x9e\x4e\xa1\x5e\x64\xe1\xd7\x50\xdc\xc3\xc3\x8d\x79\xdd\x55\x64\xaf\x1b\xbe\xce\x01\xdf\x45\xfb\xed\x41\xec\x78\xb2\xfd\x1e\x6a\x73\x0e\x3f\xf2\x54\xdf\xcf\xe5\x6f\x27\x96\x8b\x8d\x3e\x1d\x78\x31\x70\x64\x01\x87\x83\xdb\x52\xe7\x2f\x51\x9c\x86\xe1\x6e\x1b\xb7\xc9\x15\xc2\xdc\xba\x80\x89\xa9\xea\x9a\x8e\xd4\x67\x73\xbf\xd7\xc1\x5e\x22\x34\xac\xed\x15\x8a\x6d\x64\x18\x2f\xa1\xd1\x03\x74\x89\x2a\xef\xee\xd5\x4e\xdd\x36\x79\x65\xaf\x9e\xc0\xbb\x46\xd7\xc5\x7e\xdd\x15\x38\xbc\x60\xc5\xe3\x1c\xd4\x96\xa2\xb3\xb2\x8e\xb0\x55\x8f\x33\xb2\xdc\xc9\xcc\x3e\xa0\xdd\x65\xda\xfb\xb2\x69\x8e\x23\xd3\x77\x05\xe6\xcd\x50\xf9\xf7\xdf\x55\xe4\x40\xdd\xb0\xb1\xef\xff\xf3\x3f\xd8\x57\xdb\x34\xd4\xa3\x35\xfb\xaf\x3f\x7e\x38\x68\xed\xfc\xf1\xc7\x37\xec\x72\x43\xc5\x54\xef\x6b\xe8\xad\x49\x5d\x6e\x2a\x9b\x8b\xc1\xd0\xb9\x0b\xfd\x49\xd3\xeb\x04\x9c\x34\x0d\x90\xf0\x07\xd6\xce\x48\x35\xc9\x73\xb6\xd8\xdf\x18\x49\xde\x5d\xee\xa2\xab\x7d\xed\x68\xfd\x33\x95\xff\x98\xa2\x17\x1f\x2d\x96\x2a\xd7\xa4\x6c\xba\xb4\x5f\x68\xc6\x6a\x52\x4a\xaa\x49\xa5\x84\x54\x0f\xac\x0e\xba\x77\xcb\x25\xac\x59\x49\x6e\x55\xa6\x26\xd5\x1b\xb5\x6c\xa2\xb1\xfd\x29\x29\x15\xa4\x86\x84\x25\x84\x7a\x42\x48\x4a\x57\x56\xeb\xb7\xf3\xef\xd3\xaf\xfd\x40\x4a\xf2\x75\xc2\x38\xc5\x73\x63\x29\xfe\x12\x25\xa7\xf2\x09\xa6\x4f\x43\x85\xe5\x9b\xf3\x8d\xba\x85\x8b\x92\xf0\x53\x3a\x3f\x5d\x0e\xc7\x74\x84\x49\x61\x97\x2d\xbb\xae\x30\x8f\x49\xe0\x3c\xb9\xfa\x13\xc5\x70\x81\x98\x53\x59\x84\xa4\x83\x5f\xab\x14\xc1\x54\xdf\x67\x10\xc8\x65\xd5\x38\xcb\xa5\xde\xd4\x8e\xef\xdf\x31\xa8\xaa\x48\xc5\x26\x70\xba\x80\x86\xb1\x39\x21\x34\x34\x44\xdc\x52\xb9\x93\xf7\x64\xb1\x46\x2a\xb6\x84\x96\x32\x84\xd6\xef\x0c\xff\x87\x5f\x2e\xba\x6d\xa3\xa1\x83\xb1\x86\xb7\xfb\x2b\x14\xd9\x51\x20\xbd\x05\x63\x9b\x0b\x4b\x89\x06\x69\x37\x52\xba\x14\x7b\x49\xba\x8b\xcf\xfb\x3a\x51\x31\x6d\x67\x60\xa1\x7a\xb5\x80\xa9\xd0\x81\x5b\x5b\xc3\xd4\xc5\x64\x86\x29\xe6\x64\x66\x20\x07\xb9\x9d\xf9\xff\x05\x00\x00\xff\xff\xb5\x00\xc3\x66\x33\x6e\x01\x00") +var _paths_strict_sendHorizonSql = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\xbd\x79\xb3\xa2\xc8\xd2\x38\xfc\xff\x7c\x0a\xa2\xe3\x46\xf4\x4c\xd8\x3d\x42\xb1\xf7\xfc\xe6\x89\x00\xc5\x7d\xdf\xf5\xc6\x84\x51\x40\xa1\x28\x8a\x02\x6e\xe7\xc6\xf3\xdd\xdf\x10\x70\x43\xdc\xd0\x73\xfa\xf4\x7d\x1f\x6e\xdf\x33\x2a\x45\x6e\x95\x99\x95\x95\x95\x55\x7c\xff\xfe\xdb\xf7\xef\x58\xc5\xb4\x9d\x81\x85\xea\xd5\x02\xa6\x42\x07\xca\xd0\x46\x98\xba\x98\xcc\x7e\xfb\xfe\xfd\xb7\xed\xfd\xe4\x62\x32\x43\x2a\xa6\x59\xe6\xe4\xd0\x60\x89\x2c\x5b\x37\xa7\x18\xff\x27\xf3\x27\x71\xd4\x4a\xde\x60\xb3\x41\x7f\xfb\x78\xa0\xc9\x6f\x75\xa9\x81\xd9\x0e\x74\xd0\x04\x4d\x9d\xbe\xa3\x4f\x90\xb9\x70\xb0\xbf\x31\xfc\x2f\xf7\x96\x61\x2a\xe3\xf3\x5f\x15\x43\xdf\xb6\x46\x53\xc5\x54\xf5\xe9\x00\xfb\x1b\xfb\xda\x6c\xa4\xb8\xaf\x7f\xed\xc0\x4d\x55\x68\xa9\x7d\xc5\x9c\x6a\xa6\x35\xd1\xa7\x83\xbe\xed\x58\xfa\x74\x60\x63\x7f\x63\xe6\xd4\x87\x31\x44\xca\xb8\xaf\x2d\xa6\x8a\xa3\x9b\xd3\xbe\x6c\xaa\x3a\xda\xde\xd7\xa0\x61\xa3\x13\x34\x13\x7d\xda\x9f\x20\xdb\x86\x03\xb7\xc1\x0a\x5a\x53\x7d\x3a\xf8\xcb\xa7\x1d\x41\x4b\x19\xf6\x67\xd0\x19\x62\x7f\x63\xb3\x85\x6c\xe8\xca\xb7\x2d\xb3\x0a\x74\xa0\x61\x6e\x9b\x09\x85\x86\x54\xc3\x1a\x82\x58\x90\xb0\x6c\x0a\x93\x3a\xd9\x7a\xa3\x8e\x95\x4b\x85\xae\xdf\xfe\xcf\xa1\x6e\x3b\xa6\xb5\xe9\x3b\x16\x54\x91\x8d\x25\x6b\xe5\x0a\x96\x28\x97\xea\x8d\x9a\x90\x2d\x35\x8e\x1e\x3a\x6d\xd8\x57\xcc\xc5\xd4\x41\x56\x1f\xda\x36\x72\xfa\xba\xda\xd7\xc6\x68\xf3\xd7\x47\x20\x54\xdc\x4f\x1f\x81\x72\xab\x57\x1f\xc7\xa0\x87\xed\x71\xee\x3c\x02\xb7\x8a\x7c\x0d\xd9\x51\xab\x03\x70\xb7\x79\xb6\x94\x94\x3a\x47\x2d\x7d\xb0\x2e\x55\x7d\xa4\x69\x48\x71\xec\xbe\xbc\xe9\x9b\x96\x8a\xac\xbe\x6c\x9a\xe3\xeb\x0f\xda\xfa\x60\x8a\x2c\xf7\x11\x9f\x9b\xeb\xed\x4d\x4d\xf3\x9b\xdb\xc8\x30\xb6\x16\xe3\xd2\xfa\xc8\x43\xc8\xba\xb7\xb5\x01\x6d\xa7\x3f\x31\x55\x5d\xd3\x91\xda\x37\x90\x3a\xb8\xff\x59\x79\xb1\xb9\x93\x3a\x7d\xaa\xa2\x75\xff\xa8\x7f\xa7\x36\x74\x6d\xdd\xee\x9b\xd3\xbe\xae\x3e\xf2\xb4\x39\x43\x16\xdc\x3f\xeb\x6c\x66\xe8\x89\xa7\x0f\x94\x3c\x45\xc5\x63\xcf\x7a\x52\x76\x1f\xb4\xd1\x7c\x81\xa6\xca\x43\x2c\x1c\x3d\x3e\xb3\xd0\x52\x37\x17\xb6\xff\x5b\x7f\x08\xed\x61\x44\x50\xcf\x43\xd0\x27\x33\xd3\xda\x7a\x24\x7f\x58\x89\x0a\x26\xaa\x2c\x15\xc3\xb4\x91\xda\x87\x0f\xe9\xe2\xce\x9e\x23\xa8\x92\x6f\xcc\x11\x88\x3e\x7e\x12\xaa\xaa\x85\x6c\xfb\xfa\xe3\x43\xc7\x52\xdd\xa1\xb7\x6f\x98\xe6\x78\x31\xbb\xa3\xf5\xec\x16\x49\x5e\x2b\xa8\x5b\x0f\x02\xde\x8d\x3b\x77\x3f\xb0\x75\x95\x5b\x9f\x71\x5f\xd3\x1d\xf8\x08\x8f\xdc\xe5\x5d\x77\x0f\xb9\xa3\xcb\x03\x48\x8e\x47\xa3\x5b\x4f\xcc\xb6\x0f\x0c\x9d\x9b\x3d\x60\x9f\x38\x20\x79\x73\x53\x8d\x86\x7b\x4b\xbf\xa7\xb1\xe9\xd1\x61\xde\x6c\xa8\xdb\x4e\xdf\x59\xf7\x67\xb7\x41\x6e\x5b\x9a\xb3\x7b\x5b\xa2\x7b\x9b\xed\x46\xd3\xeb\x8d\xe5\xcd\x5d\x03\xd4\x96\xe7\x9b\x5e\xec\xde\xc1\xd8\x0b\x13\xb6\xd2\xb6\xed\xc5\x2d\xcc\xfb\xc6\x8a\xa9\xa2\x7b\x42\x15\x6f\x2c\xbd\x12\xa5\xf8\x83\xed\xec\xce\xd0\x67\x8c\x36\xfd\x25\x34\x16\xa8\xbf\x75\x34\xe8\x0a\xe0\x40\xcb\xbb\x31\x84\x8c\xe1\xfd\x19\xb4\x1c\x5d\xd1\x67\x70\x7a\x35\xe2\xba\xf5\xe8\xc3\x34\xec\xc7\xe0\x47\x29\x08\x7f\xf0\x61\xfc\x6e\x77\xdf\x83\xcf\x6b\xf8\xee\xf0\x3d\xf5\xdb\xea\x9e\xff\x71\x3b\xa2\xed\xe2\x75\x57\x7d\xfb\x77\x52\x30\x30\xad\x59\x7f\xa2\x0f\xfc\x10\xe7\x0a\x09\x81\x96\x77\xf3\xf8\x78\x90\x7e\x37\xe4\xdd\xe0\xea\xc7\xdd\xd7\xc0\x07\x9a\x5e\xc5\x71\xaf\x01\x78\x4f\x27\xca\x85\x66\xb1\x84\xe9\xaa\x87\x3e\x29\xa5\x84\x66\xa1\x71\x27\xec\x0b\x8a\xfd\x02\xc8\xbe\x4a\x5d\x87\xe4\x7e\xbb\x00\xc8\x73\x48\xd7\xdb\x04\x7c\xcb\xf5\xc6\x61\x93\x02\xff\x89\xba\x54\x6d\x4a\xa5\x44\x84\x4e\xd8\xce\xe8\x6c\x34\x7f\x18\xf3\x09\x90\xbb\x9f\x56\xd1\x9d\x6d\x0f\x93\x86\xbb\x39\xbc\xe0\xaa\x1e\xe1\x2f\x1c\xc4\x7d\xcf\xfa\xe1\xf5\x7d\x8d\xfd\x58\xfa\x6e\xde\x7c\xb7\xf5\x08\x2f\xde\x23\x77\xb6\xf5\xad\xfb\x7e\x7a\x76\xee\xe0\x1e\x8a\x02\x8e\xef\x7a\xe3\x23\x3f\x76\xa3\x61\xc0\x23\xf9\xad\x85\x74\xba\x26\xa5\x85\x46\xc8\x13\x13\x7d\x3b\x0d\xd4\x15\xf4\xfb\x74\x31\x41\x96\xae\xfc\xfb\x9f\x3f\xee\x78\x0a\xae\x23\x3c\x65\x40\xdb\xf9\x1d\x4e\x37\xc8\x70\x53\x84\x77\x3c\xa1\xe9\x56\xe8\x23\xa9\x66\x29\xd1\xc8\x96\x4b\x57\xf8\xe9\xc3\xc1\xe0\x40\xdd\x37\xec\x8c\xd0\x2b\x30\x76\xdc\x3d\x01\xc3\x4d\x8c\x6c\x1f\x3f\x10\xff\x0d\x7b\x84\x11\x97\xf5\x3b\x20\x48\x9d\x86\x54\xaa\x07\x40\x18\xb3\x81\x3d\x37\x76\x9a\x9b\xc8\x48\x45\xe1\x0c\xc3\x5f\xbf\x79\xd9\xe1\x12\x9c\xa0\x1f\xbb\xdf\xb0\xc6\x66\x86\x7e\xf8\x8f\xfc\x85\xd5\x95\x21\x9a\xc0\x1f\xd8\xf7\xbf\xb0\xf2\x6a\x8a\xac\x1f\xd8\x77\x37\x69\x9c\xa8\x49\xdb\xfe\xf2\x21\xef\xe0\xfd\x76\x02\xf1\xf4\xa6\x0f\x38\x51\x2e\x16\xa5\x52\xe3\x0a\x64\xaf\x01\x56\x2e\x9d\x02\xc0\xb2\x75\xec\xeb\x2e\x1d\xbc\xfb\xcd\x76\x81\x7c\x0d\x62\xde\xb1\xef\xe3\xdc\x4b\xe8\x26\x3f\x27\xb2\x2c\x95\x1b\x01\x79\x62\xed\x6c\x23\xb3\x27\xeb\x38\x2f\x7c\x82\xfe\x00\x25\x40\xc8\x23\xcc\x9f\x01\x71\x05\x50\x29\xc4\x67\x83\x7a\xb5\x80\xcd\x2c\x53\x41\xea\xc2\x82\x06\x66\xc0\xe9\x60\x01\x07\xc8\x15\xc3\x9d\x79\xec\x63\x72\x6f\x2b\x9a\x4f\xfe\x4e\x57\x0f\xf4\xef\xfa\x36\x4c\x96\x7b\xcd\xbe\x09\x1f\xab\x49\x8d\x66\xad\x54\x3f\xfa\xed\x37\x0c\xc3\xb0\x82\x50\x4a\x37\x85\xb4\x84\xb9\xdc\x17\x8b\x4d\xcf\xe9\xd5\x1b\xb5\x6c\xa2\xe1\xb6\x10\xea\xd8\xbf\xfa\xff\xc2\xea\x52\x41\x4a\x34\xb0\x7f\x11\xdb\x6f\xc1\xde\xb8\x69\x88\xcf\x71\x77\x0b\xfc\xcb\x98\x03\x61\xcc\xdd\xe3\xa9\x9e\xe3\xef\x0e\x0c\x7b\x16\xf7\x3f\x45\xe2\xf0\xf7\xdf\x30\x2c\x21\xd4\x25\xac\x9d\x91\x4a\xd8\xbf\x88\x7f\x13\xff\xc4\xff\x45\xfc\x1b\xfc\xf3\x3f\xff\x02\xee\x67\xf0\x6f\xf0\x0f\xd6\xf0\x6e\x62\x52\xa1\x2e\x6d\x85\x22\x95\x92\x7f\x84\x4a\xe6\x8e\x71\xe0\x49\xc9\xdc\xc6\xf0\xde\x92\xf9\x7f\x51\x24\x73\x3e\xa6\xfa\x72\xd8\x8f\xc3\xf7\x09\xe2\x30\x6c\x9f\x41\x74\x29\xc6\xb0\xfa\x56\x56\xd8\xdf\x07\x0f\xf0\xcd\xfb\xb9\xd1\xad\x48\xd8\xdf\xc7\x16\xf1\x47\x98\xd5\xbe\x94\xc6\x20\xc0\x00\x89\x3b\x33\xbe\x9f\xc2\xd0\x10\xe8\x59\x2a\xc3\x80\x06\x28\x3d\x31\xc8\x53\x72\x0f\x5a\x76\x4e\x6d\x58\x98\xf7\x34\xb5\x21\x40\x83\xd4\x1e\x1b\xc9\x55\x6a\xb7\x23\x97\x8a\x34\xb8\x30\x9c\xbe\x03\x65\x03\xd9\x33\xa8\x20\xec\x6f\xec\xeb\xd7\xbf\x4e\xef\xae\x74\x67\xd8\x37\x75\xf5\x68\x89\xf7\x84\xd7\xb3\x20\xd8\xe7\xd3\xb5\xb2\xfb\x78\xf4\x0c\xf2\x2c\x15\xe0\xf1\xe6\xff\x8c\x29\x43\x68\x41\xc5\x41\x16\xb6\x84\xd6\x46\x9f\x0e\x7e\x67\xa8\x3f\xdc\xb0\xa1\xd4\x2c\x14\x3c\x66\xbd\x27\x31\x07\xad\x9d\xc0\x9d\x15\xd2\x07\x43\x07\xd3\xa7\x0e\x1a\x20\x6b\x7f\xf3\xbc\xeb\x8e\x83\xff\xc8\x9c\x1c\xa5\x4b\x3c\x26\x74\x15\x93\xf5\x81\x3e\x0d\x92\x05\x27\xe1\xbc\x05\x9a\x4d\x17\x93\xfd\x7c\xe7\x8c\x07\xaf\x89\x66\xc0\x81\x8d\xd9\x13\x68\x18\xe7\x68\x1c\x73\x62\x84\x08\x10\xd0\xf4\x1f\x57\x44\x11\x9c\x34\x45\x15\x47\x30\x3f\xb5\x17\x49\x48\x3f\xc1\xd9\xcc\xd0\xdd\x75\x21\xcc\xd1\x27\xc8\x76\xe0\x64\x86\x6d\x55\xd0\xfd\x8a\xbd\x99\x53\x74\x4e\xe8\xa5\x29\xe1\x2e\xbc\xf6\xe7\x92\xf7\xd1\xbc\x9f\x79\x5e\x80\xea\x5b\x95\x50\x6b\x78\x01\x2a\xe1\xfe\x90\x2d\x25\x6a\x92\x1b\x4d\x8a\x5d\xff\xa7\x52\x19\x2b\x66\x4b\x2d\xa1\xd0\x94\xf6\xdf\x85\xce\xe1\x7b\x42\x48\x64\x24\x8c\xb8\xc5\x4c\x64\xb1\x07\x01\x9d\xa9\xa2\x9f\x42\xc2\xa6\x68\xed\x2c\xa1\xf1\xfb\xd7\x0b\x1c\x7f\xfd\xf1\xc3\x42\x03\xc5\x80\xb6\x1d\x34\x38\x7f\x3d\x2c\xdc\x38\xaf\x74\x94\x97\x18\x78\x9a\x33\x2f\x3f\xb6\xe7\x2b\xdc\x32\x0e\xd9\xd5\xbb\x7c\xc8\x21\x2f\x1b\xd2\x9c\x00\xe1\xcd\xbd\x84\x6d\xc8\x03\x34\x73\xcd\xc2\xc2\x73\x2b\x2f\x52\xdb\x63\x98\x1f\xa6\xb4\xd7\x18\xc1\xca\xed\x92\x94\xc4\xc4\xee\x0d\x8e\xbc\x7c\xe7\x75\x86\xf6\xb0\x02\xb7\xff\xd4\xd5\x4b\xb4\xed\x12\x5e\xcf\x6a\x9d\x0f\xc7\x57\xbb\x80\xcd\xf4\x2f\x79\xfa\xf3\xfc\xde\xa5\x96\x5f\xdc\xc5\xb5\x2f\x17\xb4\xd9\xd5\xe3\xf0\x5b\x2a\x72\xa0\x6e\xd8\xd8\xc8\x36\xa7\xf2\x65\x65\xdb\x65\x09\x9f\x95\x83\x0f\xc7\x97\xc3\xae\x36\xe2\x02\x6d\x47\x05\x0b\x77\x59\x61\x58\xad\x44\xf8\x83\xbe\x58\x8e\xd2\xc2\x5e\xbc\xb0\xa3\x63\xe7\xe5\xf0\x00\x86\x43\x47\xdc\xd7\x7e\x5f\xb0\x10\x18\x98\xcc\x85\x73\x18\x9b\x82\xcf\x58\x08\x3a\x37\x1f\xf2\xda\x2e\x66\xea\xdd\x6d\xf7\xaa\xe3\x7f\x0d\xd4\x72\x9c\xf1\x42\x9c\xc5\x03\x0e\x34\xfa\x8a\xa9\x4f\xed\x70\x1d\xd4\x10\xea\xcf\x4c\xd3\x08\xbf\xeb\xae\xae\x6b\xe8\x52\x5f\xbb\xb7\x2d\x64\x23\x6b\x79\xa9\xc9\x36\xac\x76\xd6\x7d\x37\x4c\xd2\xdf\x2e\xb5\x9a\x59\xa6\x63\x2a\xa6\x71\x91\xaf\x60\x1f\xed\x94\x05\x41\xd5\x0f\x03\xfd\xb8\x70\xa1\x28\xc8\xb6\xb5\x85\xd1\xbf\xa8\x28\x3e\xe3\x50\x37\x90\x7a\xab\x95\x4f\xfa\x05\x15\xba\x6c\x7a\x17\x92\xfb\xcf\x5a\xe2\x85\x15\xa8\x1b\xe3\xe2\xfd\x1e\xe9\xb6\x8f\x7b\x94\xe5\xd7\x0e\x75\x57\x71\x7c\xd4\xd0\xf7\x10\xa3\x4f\x0e\x85\x57\x71\x9d\x0f\x8d\xe1\xcd\xaf\x0c\x95\x47\x4b\x5f\xf7\xeb\xe6\xf7\xef\xdb\x70\x10\xa9\x98\x6e\xf7\x67\x70\xb3\x9d\xc7\xff\xed\x4e\x18\x77\x53\x49\xcc\x31\xfd\x1c\xf2\x37\xcc\x82\xce\x70\x6b\xa2\x43\x38\xdd\xba\xf5\xe9\x60\xeb\x03\x6c\x64\x39\x98\xa1\x4f\x91\x7d\x4b\xd1\x6f\xcd\xab\x4e\x4b\x05\x2f\xcc\xbd\xb6\x53\x0d\xc5\x93\x8b\x3b\xe4\x3e\x39\xe2\xfa\xae\xc6\x5c\x58\xca\xbe\xf6\xe8\xc2\x58\xb7\xf3\x5f\x5f\xbf\xfe\xf8\x71\x6b\xee\x77\x90\x26\x26\x9b\xa6\x81\xe0\x74\x2f\x4f\x57\xba\x97\x4d\xcf\x5f\xec\x7c\xd6\xbb\xf8\x95\xc0\xbf\xbf\x34\x8c\xf1\x3d\x75\x94\x41\xd5\x5d\xd4\xbe\x88\x36\x50\x87\x7c\xad\x91\x5f\x1a\x7d\xad\x89\x37\x3d\x0f\x6d\x70\x5e\xd1\x7d\xa3\xdd\x55\x74\xfb\x56\x57\x30\xba\x24\xe9\xb6\x5f\x33\xbc\xd3\x86\xdd\x50\xa9\x2b\xa8\x3f\x3d\x09\x0b\xbc\xdf\x4e\x43\x85\x43\x21\x5d\x3f\x10\x44\x9c\x94\xf2\x05\x6f\x5a\xe6\x62\xaa\xba\xdb\x01\x0c\x7d\x36\x83\x03\x74\x0e\x54\xb7\xfb\x68\x0d\x15\xe7\x94\xae\xa3\x4a\x8e\xd0\x82\x71\x97\xdd\xbe\xbb\xa5\x00\x4b\x64\xa4\x44\x1e\xfb\xfd\xf7\x63\xd1\xff\xcf\xdf\x18\xfe\xc7\x1f\xb7\x60\x85\x3d\xbf\x13\xf7\xff\x3b\xeb\x81\x3b\xe0\x9d\xf4\x46\x00\x7c\xa0\xab\x3c\x0a\xaf\x5a\x61\x78\xc1\xc2\x0b\xec\x32\xbc\xa6\xe5\xce\x71\xff\x1e\x1f\xf9\xcc\xc8\x7f\xab\xdc\xe3\x35\x63\xff\x0d\x2c\x1f\x35\xfa\x3f\xc8\xec\x93\xe3\xff\x0d\x6c\xe7\x11\xc0\xa5\x07\xae\xc4\x00\x27\x25\x3e\x2f\xd4\xd5\x9d\x7e\x1e\x93\x74\xf7\xb4\xd0\x1f\x36\x6e\x4c\x36\xef\x1d\xd9\x1f\x49\x2d\xef\x2c\x60\x8f\x3a\xd4\x5e\xb6\xf3\x9a\xcb\x13\xa3\x4b\x53\xce\x9f\x32\x69\x74\xd6\x7d\x34\x5d\x22\xc3\x9c\xa1\xb0\x44\xac\xb3\xde\x4e\xe1\xdc\xa8\x2d\xf4\xe6\x04\x39\xf0\xc2\xad\xed\xe4\xf1\xd2\x6d\x5b\x1f\x4c\xa1\xb3\xb0\x50\x58\xce\x90\x67\xfe\xf8\xf7\x3f\x87\xe0\xe8\x3f\xff\x1b\x16\x1e\xfd\xfb\x9f\xa0\xcc\xd1\xc4\xbc\x90\xde\x3b\xc0\x9a\x9a\x53\x74\x47\xb0\xb5\x85\x75\x0e\xc6\xe7\x4c\x9f\xa0\xbe\xbc\x1d\x08\xdd\x1c\x3c\x67\x6d\xa3\xd6\x13\xb5\x0c\xbf\x39\xd1\xa7\xfd\x0b\xda\x73\xb9\x41\x3f\x38\xc6\x86\x36\xf2\xf1\x0e\xe0\xec\xa4\x2d\x5a\x3b\x16\xdc\x2f\xa3\x6c\x7b\xe1\xdf\xff\x04\x27\xc2\xa7\xc3\xf4\xb6\xcb\xb6\x6c\x0f\x90\x7a\x79\x16\x1b\xac\x14\x8c\xea\x14\x82\x75\xcf\x9e\x3f\x18\xa3\xcd\xad\x25\x0a\x8f\x56\xf7\xd1\xc7\x57\x33\xfc\x5a\xc8\xa8\x44\xfb\xc5\xdf\xbb\x64\xd7\x36\x02\xd3\xd5\x1b\x09\xdf\xa3\x78\xf5\xd2\x00\xeb\x6f\x1a\x73\x43\x93\x30\x7b\xf1\x76\x6d\x5d\xbc\x7d\x2d\x5c\x74\xc3\xbf\xe9\xc5\xd4\x8a\xae\xa0\x4b\x11\x82\x7b\x13\x53\xcd\x85\x6c\x20\x6c\x66\x21\x45\x77\xb3\x2f\x61\x0b\x4e\x17\xa2\xfb\x90\x7d\x6a\x77\xac\xbd\x05\xf2\xfa\xba\xba\xeb\xad\x5d\xb1\xeb\x3d\x83\xa5\xd7\x5d\x6e\x8d\xf1\x8d\x3a\xda\xba\xd4\xb8\xb2\x06\x72\x9c\x6d\x3e\x5e\x01\x79\x6c\xfe\xff\x3a\x26\xee\x2c\x33\xbe\xca\xd4\xd5\xbc\xc1\x3d\x4c\x5e\x8c\x39\x5f\xc6\xe6\xdd\x95\xda\x57\x19\xbd\x11\x20\x85\xb3\x9a\x84\x0e\xc4\x34\xd3\xba\x67\x61\x1b\x4b\x0a\x0d\xe1\x06\x8f\x97\xe0\x5e\x58\x61\x7e\x02\xe4\xb5\x95\xda\x7b\xc0\x66\x4b\x75\xa9\xd6\xc0\xb2\xa5\x46\xf9\x6c\xb5\xd6\x0d\x81\xeb\xd8\xef\x5f\x89\xbe\x3e\xd5\x1d\x1d\x1a\x7d\x2f\x89\xf3\xa7\x3d\x37\xbe\x7e\xc3\xbe\x02\x9c\xe0\xbf\x13\xf8\x77\x9c\xc5\x08\xfe\x07\x45\xfe\xc0\xe9\x3f\x49\x82\xa6\x49\x36\x86\x83\xaf\x7f\xfc\x75\x1f\x74\xd0\xf7\x76\xdd\x9d\xf4\x96\xbc\xe9\x3b\xa6\xae\x5e\xc5\x04\x68\x8e\xe2\x1f\xc1\x44\xf6\x17\x36\x3a\x8c\xa1\xfa\xf4\x6c\xa7\xdf\x75\x7c\x3c\xc7\x90\x8f\xe0\xa3\xfa\x50\x55\xfb\xc1\x5c\xf6\x55\x1c\x24\xc7\xd1\x0f\x49\x8f\xee\x7b\x51\xe3\x6e\x02\xeb\x96\x74\x5c\x45\x41\xb1\x34\xff\x10\x1b\xcc\x0e\x85\xef\x19\x6f\xa3\xa0\x01\x47\x3d\x82\x81\xf5\x86\x8c\xcd\xfd\x4c\x30\x34\xc9\x3c\x24\x27\xce\xed\x0b\x38\x18\x58\x68\x00\x1d\xd3\xba\xde\xd5\x2c\x4e\xe1\x0f\xa9\x16\x77\x22\x23\x7f\x2b\xcc\x6d\x36\x58\x9a\xe5\x1f\x62\x83\x77\xd9\xf0\x96\x39\xfa\x6b\xd5\xba\x0e\x9d\xe3\x59\xf0\x08\x74\x02\x77\xc1\xfb\xbd\xe0\x06\x03\x57\x11\x70\x04\xc7\x70\x0f\x21\x20\x8e\x11\xec\x73\x0b\x5b\xfb\xbf\x8e\x88\x26\x1e\xea\x0e\x02\x9c\x74\x84\x9f\xcd\xf1\x4e\xb4\xb8\x8a\x88\x27\x28\x9a\x78\x08\x13\xe9\x71\xb3\xcf\x9e\x5d\x57\x2c\x9e\xc5\x79\xe6\x21\xf8\x54\x5f\xd3\xd7\xbb\x8d\x62\xe6\xc4\xe8\x6b\x3a\x32\xae\x3b\x46\x9e\xe3\x1e\xb3\x3f\x82\xde\x4d\x28\x76\xab\x60\xeb\xab\x6c\x50\x38\xce\xb2\x0f\xf9\x10\x82\xe9\xeb\xd3\x01\xb2\x9d\xfe\xf9\x3a\xdb\x0d\x54\x00\x3c\x66\x8a\x04\x7b\x12\x04\xb8\x0b\x9a\xf0\xfa\x50\x42\xe1\x24\x4f\x3d\xc6\x0f\xb7\xd7\x5e\xcd\xb4\x76\x81\xc2\x55\x1c\x04\xce\x51\x8f\xf5\x0a\xef\x29\xd5\x75\xb0\x00\x50\xe0\x21\x8d\x02\x78\x08\xe9\xb7\x6d\x90\x02\x14\x8f\x3f\x86\x88\xd8\x19\xba\x85\x26\xe6\x12\xf5\xdf\x90\x65\xee\x33\xab\xe6\xd4\x76\x2c\xa8\xdf\x18\x74\x29\xc0\x1d\x0c\xe6\x42\x0c\x74\xb5\x6e\xea\xd1\x20\xe8\xac\x76\x6a\xc7\x0e\xf1\x0d\xfb\x9a\x16\x3b\xe9\x6a\xae\xdd\x2a\xb4\xcb\xdd\x4c\xaa\xd0\x6a\xe4\xdb\x2d\x3a\x95\xce\x08\x64\xa1\xd4\xed\x82\x5c\x35\x5f\x64\xcb\x42\x4e\x68\x4a\xd5\x54\x93\x29\x54\x12\x75\x29\xd5\xea\x94\x4b\x41\x91\x5d\x44\x02\xb6\x48\x12\x9d\x7c\x9a\xa9\x95\xa8\x72\x29\x2b\x55\x12\xc5\x52\x4a\x64\x49\x20\x50\x24\xd3\xa3\x2b\xa5\x64\xbd\x56\x48\xb7\xf3\x6c\x5a\x2c\x24\x8a\xd5\x42\x36\x55\xa6\xea\xac\xd4\x6d\xb7\x9a\x77\x23\x21\xb7\x48\x04\xba\x2d\x56\xba\x02\xdd\xa5\xda\x82\x94\xe9\xb4\x6b\xa0\x99\x2f\x83\x66\x99\x12\x9b\xe9\x4c\xb3\xca\x52\x52\xb3\x92\x2f\x97\x40\x35\xd3\xa2\xda\xb5\x4c\x39\x5b\x2b\xe5\xf3\x99\xb3\xce\xbf\x88\x84\x72\x39\x01\x64\x35\x05\x32\x4d\x89\x06\x42\xb1\xd3\x4c\x35\x33\xa4\xd0\xcd\x09\x9d\x4e\xba\xd3\x69\x81\x56\xa6\xd3\xed\xd6\x18\xa9\xdb\x91\x1a\x95\x7c\xb2\xd3\xab\x0b\x6d\x86\xed\x94\xa9\xbb\x91\xd0\x2e\x92\x6a\xa5\x9b\xce\x50\x79\x9a\xed\x88\x49\xa9\x94\xcf\x77\x68\x3a\x9f\x6c\xb4\xcb\x8d\x3c\xdd\x4e\xb6\x6b\xd5\x72\x06\x14\x32\x52\xb2\x43\x4a\xf9\x56\xb6\x5a\x2b\x14\xa5\x7a\x5a\x4c\xdf\x8d\x84\x71\x3b\xbe\x56\xe9\x66\xb2\x05\x90\xc8\x92\xa9\x52\x95\x12\x3b\x85\x54\xb1\x94\x2c\xa4\x72\xcd\x52\xa5\x09\x32\x5d\xb2\x57\x4c\xd5\x33\xe5\x52\x33\x21\x95\x85\x7a\x9b\xad\x26\xd8\x72\x07\x64\xbe\x46\xad\x58\xdc\x4e\x72\x6e\x68\xad\x5f\xb4\x7e\xd8\x6f\xf2\xa7\x8d\xae\x57\xf3\x7d\xc3\x98\x6f\x98\x63\x2d\xd0\x1d\xb6\x74\x5e\xa7\x17\xd9\x92\xbc\x39\xf8\xb1\x1d\x29\x16\x52\x75\xa7\x0f\x8d\xd9\x10\x4e\x17\x13\x6a\x6b\xfd\x52\xb3\xf6\xf5\x3d\xba\xf3\x14\x3b\xb8\x80\xbd\x59\x4f\x7e\x7d\x0f\x8d\x3d\xc5\xbe\xb5\xbc\x29\x74\xf4\x25\xda\x22\x73\xff\x1f\xad\x32\xf0\x35\xea\x71\x92\xe8\xf8\x86\x91\xf7\x2a\x47\x58\x3d\x5d\x54\xed\xd8\xd5\xd4\x1d\x89\x08\xd0\x2c\xc3\x73\x38\xcb\xb1\xe4\x37\x8c\xf8\x86\x6d\xfb\xec\x3f\x5f\xbc\x71\xe3\xcb\x0f\xec\x0b\x41\xfe\x89\x7b\xd7\x97\x6f\xd8\x97\x43\xd5\xe6\xf6\x9e\xd4\xac\x1d\x7e\x74\x36\x33\xf7\xc7\x60\x87\x1f\x5a\x78\xd5\x9b\xdb\x36\x51\xf5\xee\xcb\xff\x5e\xea\xfb\x20\x67\x20\xc0\x19\x70\x25\x7e\xca\x19\x7e\x99\xb3\x66\x3d\x19\x95\xb3\x68\x3a\x1d\x9d\xb3\xed\x3f\x8f\x35\x2f\x5d\xea\x52\x11\x71\xe8\xdc\x72\xb4\x0b\xad\xbf\xfc\xd8\x82\xfe\x62\x9b\x86\xda\xbf\x24\x34\xd9\x5c\x0c\x86\x4e\xff\x92\xb6\x78\xcf\x86\x09\xf6\xe8\xce\x35\xe9\xee\xe0\x87\x69\xdd\xc9\xbd\x6b\x40\x8e\x70\xbd\xa0\x9f\x82\x98\x3f\x52\xa9\x89\x40\xd7\x53\x61\x5d\x1f\x31\xa0\xb9\xa3\xeb\xc9\xeb\x5d\x8f\xdf\xe8\x7a\xbf\xdf\x9e\xe9\x7a\x5f\x7b\x9e\xed\xfa\x88\xfd\x74\xad\xeb\xdf\xdb\xea\xf7\x9e\x9a\x20\x78\x86\x0f\xf7\xd4\xf4\x9f\x1c\xf5\x0b\x7b\x6a\x9f\xb3\x30\x4f\x0d\x7e\x6d\x4f\xed\x73\xf6\x8e\x9e\x9a\x08\x31\x57\x70\xcb\x53\x83\xf7\xf2\xd4\xbb\x86\x5e\xf4\xf5\x7a\x1f\xfc\xb8\xc3\xf4\x7b\xe0\x1d\x1d\x66\x58\x0f\x9c\x88\xf8\xbc\x07\xc0\x05\x87\x79\x2e\xbe\x97\x38\xc3\x9f\xe6\xbb\x82\x76\x40\xbf\x9f\x1d\x80\xc7\x7b\xe1\xc4\x6b\x3e\xde\x0b\x8f\x46\x23\x3f\x3f\x78\xf0\x7b\x81\x79\x3f\x5b\x08\xeb\x85\x13\x31\x3f\xee\x8d\x9e\x08\x1e\xee\xf6\x46\x1f\xd0\x03\x04\x4b\xb0\x3c\xc7\x92\x80\x23\xc2\xc7\x70\xfc\xd7\x9c\x94\x50\x01\xd6\x42\xa7\x5b\xbf\x26\x6b\x87\x5e\x63\x49\x96\x7d\xbc\xd7\x3e\x71\xe8\x45\x07\x58\x7b\xb4\xd7\x3e\x31\x6b\x60\xc7\x1a\x47\x50\x97\x32\x1b\xbf\xa8\x42\x52\x01\xd6\xfe\x8b\x6c\x8d\xdc\xb3\x46\xd3\x97\x66\x39\xbf\xa8\x42\xd2\x01\xd6\xfe\x8b\x6c\x6d\xeb\x21\x01\xc7\x51\x3c\x4e\xf3\x1c\xed\xf5\x1a\xee\xf2\x66\xe8\x13\xdd\x65\x8d\x07\x80\x24\x59\x80\x93\x0c\x47\xff\x49\xb1\x2c\xcd\xe1\xec\x2f\xa5\x99\x60\xc7\x23\x81\xe3\xbb\xb1\xfb\xbf\x8d\x47\x72\xcf\x23\x45\xec\x46\xba\x48\x3c\xfe\x0a\xba\x4a\x70\x60\x37\x2e\xfc\xb7\xf1\x48\x7d\xc3\x38\x9a\xe3\x79\x92\x63\x38\xcf\x89\x7a\x1c\xda\x0e\xb4\x1c\x7d\x3a\xe8\xcb\xd0\x80\x53\x05\x05\x7d\xce\xdd\x08\x98\x53\x04\xf7\xba\xb2\x40\x20\x1e\x95\x9f\x6d\xaf\x79\x0c\x79\xa7\xcd\xf8\x93\x6f\x6f\x11\xa4\x3f\x46\x9b\x8f\xb1\x16\xda\xa7\x8a\x02\xac\xef\xf4\xde\x49\xca\x3e\x82\xf7\x96\x72\x80\x9f\x3b\xa5\xfc\x01\xf6\xea\x51\xc5\x70\xbe\xdb\x7d\x2f\x29\x7b\x08\xde\x5b\xca\x01\x7e\xee\x93\x72\xd4\xdc\xc8\x23\x9e\xdf\xa5\x8a\xc6\x79\xdf\xf1\xbf\x93\x94\x7d\x04\xef\x2d\xe5\x00\x3f\xf7\x49\x39\x62\x91\xc6\x43\x31\x84\x47\x15\x8d\xfb\x43\xcf\x7b\x49\xd9\x43\xf0\xde\x52\x0e\xf0\x73\xa7\xc7\x88\x98\x61\xfa\xdf\x3b\x6a\x92\xc2\x8e\x5c\x89\xba\x54\xbe\x3b\x76\xe5\xb8\x30\x45\xe5\x28\x86\x24\x59\x4d\xe5\x11\x60\x19\x8a\xe4\x29\x8a\x51\x01\xa4\x29\xa0\xc9\x3c\x2b\x2b\x0c\x84\x04\x43\xe3\x38\x82\x2a\xad\xa8\x0c\xe2\x09\xc0\xb1\x2c\xab\xa8\x48\x45\x04\xce\x2a\x5f\xb7\x30\x10\xe2\x19\x56\xa6\x38\x59\xc1\x69\x0d\xa9\x2c\xc0\x55\x0a\xa8\x38\xce\x12\x24\xa7\x72\xbc\xa2\xe2\x08\x67\x48\x56\x55\x35\x8a\xe2\x71\x16\x81\x6d\x3c\x46\x32\x2a\xae\xb2\x0a\xc3\x31\x5f\xdd\x7e\x05\x81\x0a\x2e\xd6\xad\xe0\x62\x82\x85\x5d\xac\x5f\xd8\xc5\xf0\x3c\x43\xdf\xbe\xeb\x2f\x2e\x92\x2c\xcb\x7c\xc3\x88\xed\xff\xf1\xb3\xeb\x1b\x46\xf0\xee\x5f\xff\xcf\xfe\xd7\xfd\x87\x2d\x6d\x82\x20\x08\xc9\x12\x3b\xeb\xb1\xf5\xc2\x2a\x15\x77\x94\x01\x91\xc0\x05\xa5\x31\xea\x4e\x4b\xc9\x41\x97\x24\xb5\x5a\x4e\x8c\xe5\x72\xa9\xa4\x5c\x25\x38\x98\x4e\xd2\x39\x61\x05\x38\x94\x4c\x4c\x92\x80\x68\x2c\xd6\x15\x6b\xda\x66\xd2\x3d\xde\xac\xc9\xa5\xf4\xb8\x32\xcc\xc6\x55\x38\xe1\x07\xc4\xa6\xb8\x05\x2d\x74\x7a\x0e\x9d\x1f\x08\xfb\x0b\x09\xad\xc2\xdb\x7a\xb9\x7a\x13\xc6\xab\xa6\x48\x32\x8b\xcd\xa2\xc3\x10\x65\xf1\x6d\xdd\xcb\xd9\x7a\xd5\x88\x77\x6b\x66\x26\xcd\x1a\xdd\x3c\x18\x5a\xf2\xea\xad\xc2\xf2\x7c\x77\xa9\xe5\x27\x6a\xbc\x3c\x21\x28\x4d\x01\x7c\x05\xe5\xa7\xcd\xae\x30\xe4\x0b\x7c\x53\xac\x53\x4e\x26\x5f\xdd\x42\xee\x96\xa8\x02\x7c\x9b\x81\xea\x01\x99\xa0\xda\xc2\xe9\x95\xdc\xfe\xe9\x09\x1d\x82\xaa\x0a\x42\x12\xcf\x09\xbf\xda\xe5\x69\x15\xf1\xcd\xdd\x31\x74\xc1\xfc\x83\x16\x41\xbf\x46\x9b\xbf\x2a\x38\x24\x48\xc0\x29\x90\xd1\x54\x59\xd6\x68\x48\x52\xb2\x4a\x12\x10\xb0\xac\x46\xb3\x3c\x4b\x50\x9a\x4c\x70\x2a\x4f\xcb\x24\x4e\x21\x88\x2b\x2a\x27\xab\x32\xaf\x2a\x2c\xe2\x38\x4d\xa5\xbc\x62\x1a\x32\x5c\xb9\x2f\xe9\x3c\x4b\x72\x2c\x71\xeb\x26\x20\x28\x96\xe2\x48\x86\xe2\xf0\x6b\xf6\xc0\xdc\x69\x0f\xc5\xc4\xb0\x68\x6e\x26\x71\x79\x49\x98\xf8\xb2\x91\xd6\xd5\x78\x8b\x56\x9a\xb1\xf5\xa8\xd7\x7e\x13\xcb\x66\x11\x14\x00\x4d\x66\x98\x6c\xbc\xd9\x90\x6b\xe3\xf8\xba\x53\x1e\xc2\x3a\x98\xa7\xd7\x24\x9b\xca\x0c\x4b\x6f\xab\x09\x1a\x2d\xd5\x89\xba\x58\x99\x75\x95\x5a\xd1\x9c\x2e\xb0\x9c\xdb\x7f\xae\x3d\x1c\xa9\xa8\xa1\x97\xd2\x8a\x98\x11\x7b\x6c\xaa\x9a\x9c\x09\xf8\x34\x46\xb2\xc6\x5a\x55\x35\x36\x6b\xd1\xe3\x1e\x51\x65\xe7\x53\xa5\x36\x5d\xbf\xb5\xc7\x85\xbc\x9c\x6f\x24\x15\x00\xf5\x55\x3b\x31\x1d\x24\x04\xd1\x2c\xa4\xd9\x81\x32\xb5\x19\x47\x41\xac\xc4\xa9\x63\x69\x29\xbf\xe9\xb9\x9e\x0b\xb9\x19\x62\x0f\xbd\xa0\x3a\xfd\x37\xd8\x03\xe9\x0e\xcf\x0f\xd8\x03\xf5\x1a\x5d\xfe\xca\xb3\x80\x96\x15\x55\x95\x35\x15\x01\x08\x58\x9e\x55\x59\x9a\x54\x58\x92\xa7\x91\xca\x70\x1c\x8e\x23\x4a\xd5\x00\x8b\x78\x40\xca\x90\xa7\x00\x0f\x68\x9a\x21\x11\xc9\xd2\x04\x0b\xb9\xed\x28\x43\xb9\xff\x42\x74\x9b\xba\xa8\xf2\x34\x8e\x73\x97\x0d\x62\x77\xd7\x4b\x61\x31\x3c\xc1\x51\xd7\x2c\x82\xbc\xd3\x22\x72\x8a\xb1\x2c\x81\x38\xa9\x9b\x53\x83\x57\x1b\xeb\x37\x03\x11\xe6\x40\xa0\x4b\xdc\x94\xa9\x97\x19\x23\x31\x36\x5a\x23\x8a\x6c\x76\xe6\x45\xb1\x9c\x47\x28\xc6\x8f\x07\xf9\x71\x0a\x80\xee\xb8\xc3\xd6\xda\xb9\x54\x23\x59\x35\xa9\x0c\x2e\x58\x44\xaf\xb9\x1a\xda\x22\xcc\x0d\x34\x6f\x58\x70\x2d\xe2\xa8\x47\x8b\xa3\x74\xb9\x39\x59\x0d\xba\xec\xbc\x26\xe3\x2d\x87\x6c\x2e\x6a\x74\x6f\x3e\x41\xf4\x18\xcc\x47\x19\x8e\x9d\x67\x86\x42\x0d\xad\xf0\xf9\x0a\x0e\x8c\x9e\xd6\x75\x26\xc9\x49\x22\xc6\x98\x42\xd2\xd8\x70\x14\x47\xc6\x40\x6b\xe2\x68\x12\x09\xf1\x7a\x9d\xcf\x64\x72\x94\xae\xb7\x5c\x54\xd5\x10\x8b\x68\x36\xc3\xb4\xea\x17\xb7\x08\xea\x51\x8b\x20\x5f\xa3\xcd\x5f\x71\x0a\x91\x48\x46\x50\xe3\x55\x42\xe6\x10\xae\xd1\x14\xcd\xa9\x34\x89\x13\x0c\xaf\x21\x5c\xe5\x78\x8d\x90\x35\x55\x65\x65\x95\x52\x15\x4e\xa5\x64\x9c\xe6\x28\x19\x90\x8c\x4a\xb0\x88\xa0\xaf\x59\x04\x79\x51\xe7\x19\x8a\xe3\xd9\x9b\x77\xfd\xcc\x27\xc1\x71\xdc\x15\x8b\xb8\x37\x64\x12\x1a\x23\x26\x66\xd1\xb8\x3c\x1a\xf0\xcd\x76\xa9\xb9\x4a\xcd\xe2\x03\x90\xe3\xe4\xb8\x8a\xf8\x86\x32\x6a\xda\xa9\x61\x21\x0b\xf0\x0e\xd5\x1a\x2d\xde\x8c\x82\x21\x54\xb4\x18\x61\xaf\x9a\x40\x5b\x13\xd0\x59\x34\x34\x42\xdb\x94\x51\x6a\x9d\xe4\x47\x6b\xb3\xe1\x0c\x33\x1d\x71\x66\xba\x1d\xb8\x35\x88\xdc\x6a\xfb\x29\xbb\xff\x23\xb8\x3a\x7b\xf8\x51\x58\x09\x95\xea\xd8\xeb\xf0\x0d\x5b\xed\xa0\xf2\xb8\x5a\x1d\x34\xd3\x83\x4c\x75\xac\xc0\xd8\x5c\x2d\x2d\x32\xc9\xde\xa2\x2d\x25\xc6\x8e\xd4\xeb\x96\xd3\x89\xd5\x22\xa5\xc7\x97\x71\x73\xb1\xcc\x5b\x4b\x8a\xc3\x6b\x8d\xc2\xb4\x98\x4c\x65\x6a\xed\xe2\x62\x15\xcb\x83\x78\x4a\x6f\x14\xc5\xe4\xe0\x6d\x1a\x6b\x8d\x32\x31\xd7\x60\x8a\x21\x06\x53\x96\xc2\x94\xee\xff\x6f\x06\x03\x5e\xa3\xec\x5f\x19\x52\xe5\x39\x8d\x26\x19\x84\x18\x4e\x25\x64\xc0\xca\xb4\xcc\xf1\x1a\x20\xa1\x46\x93\x04\x21\xb3\x34\xc3\x43\x40\x69\x50\x23\x28\x9c\x84\x2a\x2e\xd3\x40\x66\x48\x52\xc6\x59\x19\xf1\xfc\x57\xb7\x48\x83\x0e\xd5\x7d\x70\xd1\x24\x58\x86\xe5\xae\xde\xdc\x8e\x20\x5e\x26\x8f\xa2\x79\x70\xc5\x5c\xe8\x0b\xe6\xe2\xcd\x98\x5d\xf1\xa6\x2b\xbd\x11\x51\x5a\xd0\x26\x2e\xe7\xd8\x36\x35\xdd\x94\x97\xcd\x75\x9a\x6c\xcd\xcc\x71\x6c\x99\x12\xca\x4e\x82\xc8\x83\x22\x2b\xb2\x4c\x6f\x38\xd5\x64\x29\x39\xcb\x54\xba\x2a\x45\x4f\xab\x4a\x83\xed\x8c\xb5\x6c\x71\x55\xef\xf0\x83\x54\x92\x8f\x69\x6d\xe8\xb0\x04\x53\xcd\xb6\x15\x17\xb4\x6b\x29\x47\x93\x8b\x2a\x3f\xe1\x0a\xf5\x34\x27\xd3\x6d\x5c\x5e\xac\x25\x67\x6e\x3b\xad\xea\x1b\x9b\x6d\xc5\x33\x56\x72\x92\x96\x1c\x55\xa0\x26\x09\x29\xd9\x59\xcd\xc0\x60\x6c\x02\xd8\x2d\x8f\x36\x69\xbe\x5d\x32\x98\x84\x90\x31\x8b\x34\x91\x5f\xe7\x52\x79\x7e\x80\x9b\xe5\x45\x81\x1c\xdb\x9c\xde\x71\xe1\x67\x43\x2c\x21\x83\x87\x69\xd3\xce\x12\x04\x41\x1c\xbf\xab\xda\xbe\xc3\xe5\x69\xd3\x63\x96\x40\xbc\x46\x8b\xdd\xb3\x12\x30\x5f\x6f\x08\x9e\xc5\xbf\xe3\xc4\x77\x9c\xc0\x70\xfc\x87\xfb\xef\xa2\xba\xf2\x38\x41\x5e\x0e\x96\x76\x77\x29\xc0\x53\x3c\xc3\x02\xfe\xda\x7c\xf9\xa6\x2a\x7f\xca\x4b\xec\xe4\x75\x6a\x13\xdf\xd4\xf3\x22\x9b\x9c\x26\xf9\x0c\xc0\xd7\x23\x31\x66\xe3\x03\xc7\x5e\x65\x57\x6f\x44\x47\xad\xb7\xbb\x50\xcc\xc1\x94\xab\xca\x52\x88\x2a\x87\x5f\xbf\xb8\x2a\xe3\xc7\xaa\x7c\x23\x21\x75\xc7\x41\xa4\x51\xf3\x53\x17\xce\xa9\xb8\x54\x2a\x0e\x2e\xd8\xdd\x0d\x30\x67\x9b\x0d\xa2\x81\x09\x56\x2f\x47\xa4\x86\x0a\x16\xd4\x46\x03\x43\xef\xc1\x30\x38\x43\x47\xa6\x86\x09\x80\x89\x48\x0d\xbb\xcb\x33\x50\x38\xed\x26\xdf\xa3\x81\xe1\xf6\x60\x28\xc6\xcd\x2e\x47\x03\xc3\xef\xc1\x70\xac\x5b\x81\x11\x0d\x0c\x81\x07\x0a\xc2\xa8\x88\x70\xce\x6a\xe6\x22\xc2\x01\x81\x52\x27\x3a\x22\x1c\x32\x58\x0d\x16\x11\x4e\xb0\x88\x27\xaa\x7c\xe8\x60\x31\x50\x44\x38\x4c\xa0\x3c\x25\xaa\x7c\xd8\x00\x9c\x88\x46\x41\x70\xc1\x9a\x92\x88\x70\xf8\x40\xdd\x46\x54\x3f\x88\x07\x6a\x23\x22\xf2\x05\xce\xea\x0f\x22\xc2\x01\xa7\x6b\xe2\x4c\x44\x30\xe4\x29\x98\x88\x5a\x08\xa8\xd3\xb5\xe3\xa8\xd4\x04\x96\xa0\x23\xea\x20\x08\x2c\xe9\x46\xa5\x86\x0d\x2c\x3d\x47\x04\xc3\x05\xd6\x22\x23\x82\xe1\x4f\xc1\x44\x64\x8a\xc4\x4f\xd7\xec\xa2\x82\x21\x02\x2b\x8d\xaf\x39\x97\xfc\x25\x1b\x6d\xaf\x1f\xbe\xf5\x0d\xdb\xd2\x7e\xdf\xce\xdb\x0b\xc7\x73\x3f\x1d\xb1\x1d\x6b\xfc\x71\x88\xb6\xff\xe2\x2d\xc5\x10\xde\xe2\xad\x63\x3e\xb5\x3a\xfd\x0d\xfb\xa2\x59\xe6\xe4\xd9\xea\xfe\x19\x74\x86\x5f\x7e\x60\xff\xfe\xe7\x1b\xf6\x69\x37\x07\xbb\x95\xfd\xde\xb1\xe0\x17\x76\x25\xaa\xc8\x76\xf4\xa9\xa7\x1d\x13\x7d\xea\x36\x38\xdd\x84\xe3\x3d\x1e\xbe\x11\xea\xe8\xde\xf5\x4d\x87\x47\x0d\x5f\x52\xbf\xf7\x0e\xe7\x54\x5c\x54\xc6\x5d\x84\xbe\xff\xc2\x7d\x5e\x65\xfc\xcf\x85\x02\x86\x80\x92\x7e\xaa\x7d\x91\xa1\x4a\x0a\x6e\x28\x29\xf8\x3f\x25\x3d\x55\x52\x7f\xe2\xb6\xff\x42\x7d\x5e\x25\x3d\x55\xc6\x4f\x55\xe1\x1d\xaa\x8b\xe4\x2d\x87\x89\xe3\xff\xa7\x8d\xfb\x70\xfe\x68\xe2\x7e\xf8\xc2\xb8\xda\xe8\x29\xa3\x7b\xae\x9b\xd7\xf3\x3c\xee\xfe\xef\xcb\x89\x42\x80\x13\xdb\xf6\xde\x25\xb0\x65\xfe\x3f\x5f\xdc\x5d\xa5\xc4\x37\xec\xcb\x56\xec\x04\xfe\xbf\xa7\x7b\xec\xf0\x6f\xd8\x17\xef\xd4\xda\x0b\xdb\x42\x8f\xef\x5d\x95\xbd\x77\x34\xee\xe5\x5d\x8f\xc7\x80\x5e\xd6\x37\x2f\x3e\xdb\xe9\x72\xdf\x78\xd9\x90\xc3\x17\x10\xde\x37\x1c\xe9\x5e\x81\xbe\xa1\xae\xf5\x0d\xe3\x77\x0d\x7d\xab\x67\x42\x36\x20\x9e\xc8\x3c\xb8\xc7\x31\xb4\x43\x6e\x77\xdd\x4b\x4a\xcc\x3f\xb4\x6f\xbc\x14\xd3\xe1\x0b\x17\xde\x37\x2c\xc3\x03\x12\xe7\x02\x7d\xc3\x5c\xb5\x1b\xf2\x83\xed\x26\x72\x1f\xbe\xda\xbc\x7e\x65\xb5\x38\xcd\xf4\xed\xbf\xe0\xde\xe0\x7e\x3c\xb6\x3f\xb1\x5b\xfc\x30\xb6\x47\x97\xf0\x27\xde\x69\xf7\x0e\xe7\x6a\x5d\xee\x29\x3f\x07\xba\xff\xc2\xbc\x53\x4f\x45\x8f\x6f\x3e\xf1\xee\xba\x77\x38\x7f\xed\x62\x4f\xed\x76\xc1\xee\xbf\x80\xf3\x9e\x7a\x22\xd6\xfd\x3f\x9b\x7a\x99\x4d\xed\x76\xbe\xee\xbf\x70\xe7\x3d\xf5\x92\x99\xcd\xff\xd9\x54\x74\x9b\x3a\x59\x99\xd8\x7f\xf1\x26\xa1\xcc\x7d\xbb\x09\x1d\x6b\x61\x3b\x08\x3d\x6b\x35\x2e\x18\xf3\xe9\x23\x54\x3e\x87\x8d\x7d\x40\x84\x71\xb2\x87\x77\xff\x05\xff\xc9\x3d\xf7\x84\xeb\xfd\x1c\x3d\xf7\xfe\x53\xed\xd3\x9d\xc9\xfb\x2f\x4c\xe4\x9e\x8b\xee\xff\x8e\x7b\xee\x09\x57\xfc\x39\xbc\xe5\x8b\x8f\x26\xbe\xdc\x73\xfe\x7a\xe7\xfe\x0b\xf8\xc9\x3d\xf7\x32\x6f\xf9\xb3\x7a\xee\xfd\xbd\xe5\xf1\xd2\xf0\xfe\x33\x77\xb4\x73\x51\x5b\x4c\xd5\xdd\xf9\x5d\xd1\xce\x6c\x76\xe5\xe2\x9d\x9c\xfc\xf4\xb4\xf7\xe6\x36\xca\x27\xcf\x96\x7e\x44\x6a\xfe\x12\xf6\xfe\x33\xf5\xbe\x52\x7b\x22\x01\xfc\xa9\xa4\xe6\x2d\xb5\xef\x3f\xe3\xef\x2a\xb5\x27\x3c\xc0\xa7\x92\x9a\x5f\x12\xb0\xff\xcc\xbc\xab\xd4\x9e\x18\xf1\x3e\x97\xd4\xbc\xd2\x85\xfd\x67\xf0\xbe\x16\x1a\x3d\xc2\x7b\x77\xa9\xdd\x28\x83\x08\x79\xbf\x75\xd4\x12\x08\xff\x1d\xd7\xa1\xe5\x0f\xf8\xc5\x2d\xcd\xe4\x6e\x06\x4c\x90\xfb\x0a\x6a\x6f\x0f\xf4\x51\x49\xb5\x63\x2d\x90\xb7\x01\x9d\xf0\x76\x83\x52\x0c\x41\x30\x1c\x83\x53\x14\xc1\xb3\x04\x4f\xb3\x2c\x7b\x41\x43\x42\xa9\xf2\xd7\xc1\x2f\x53\x45\xec\x89\x00\x87\xba\x6e\x8f\x58\x12\xec\x7e\x70\x5f\x1d\xfe\xcd\x5d\xc6\xd9\x92\x16\xa0\x89\xe7\xae\x95\x80\x5d\x23\x8b\xb8\x48\xd6\x3e\xb1\x43\xd0\xfe\xaa\xf7\xee\x20\x80\x23\xb2\x3c\x61\xd1\x6e\xf8\x05\x42\xc9\xba\x4b\x2d\x6e\xbf\x70\xf9\x09\x45\x09\x7f\x3d\x5d\x68\x7d\x33\xb8\x5c\xd7\x77\x13\x10\x08\x00\xba\x54\x9f\x75\x13\x10\x19\x28\x9a\x88\x0c\x88\x0a\x00\x8a\xcc\x5a\x70\x85\x3c\x32\x20\x26\x00\x28\x32\x6b\x67\xab\xa4\x51\x01\x71\xc1\x25\xbd\xa8\x80\xce\xd6\x9f\xa2\x02\x3a\xad\x78\xc6\x2f\xd7\x52\xde\x86\x74\xb6\xf8\x11\x19\x12\x08\x24\xe7\x2f\x55\x54\xde\x86\x44\x06\xd3\xfc\x91\x21\x51\x81\x34\x74\x64\xad\x3c\xad\x7d\x06\xcf\x48\x9c\x09\x24\x5c\xa3\xcb\x89\x0d\x40\x8a\x6c\x2a\xa7\x15\xd0\xd4\x33\x12\xe7\x03\xa9\xae\xe8\xbe\x12\x0f\xa4\x5e\x22\x73\x77\x5a\x07\xfd\x8c\x01\x9f\x54\x42\x73\x97\x2b\x5a\x6f\x03\x22\x4f\x01\x45\xd6\xa6\x93\x6a\x68\xea\x19\x8a\x02\x13\xc8\xc8\x5a\x79\x52\x11\x8d\x3f\x43\x11\x1b\x98\x9c\x45\x06\xc4\x9d\xce\x57\xa2\x53\xc4\x9f\x02\x8a\x3e\x7c\xe3\xa7\x73\x81\xc8\x46\x72\x52\x1b\x0d\x3c\xd6\x1e\x7b\xcb\xef\x7b\x56\x47\xdf\x7a\x63\xef\x23\xf5\xd1\xc7\x6f\x15\x7c\x75\xd4\x77\x90\xe7\x57\x86\x42\x90\x51\x15\x1e\xe7\x71\x85\x53\x09\x00\x00\xc1\x2a\x14\x54\x70\x85\x84\x3c\x60\x29\x8d\xa1\x71\x8a\x54\x78\x00\x71\x55\x66\x54\xc4\x51\x34\x0b\x10\xa7\x52\xbc\xa2\xe2\x34\x60\xbc\x37\x71\x11\xcf\xa4\xa9\x8f\xb6\x2d\x53\xbb\xdd\x9c\x97\x0f\x53\xe2\x69\xfe\xca\x51\x4b\xde\xdd\x93\x98\xd3\xdb\x06\x9a\x67\x46\x48\x27\x47\x13\x33\xcb\x35\xd2\x46\x32\x8e\x06\x0a\xc9\x56\x3a\x4e\x26\x9f\x7f\x6b\xb7\xb8\x55\x4b\xef\x89\x30\xb1\xa0\x0b\xb4\x7b\x06\x92\x77\xe8\x8a\xbb\x6d\x3f\x11\xd8\xa5\x28\x1e\x3e\xba\x9b\x89\xc5\x56\xab\xe4\xef\xaf\x4f\x10\x0b\x51\xcd\x98\x8d\xc5\xa0\xb8\xac\x3a\x49\x56\x1c\x66\x0b\x64\x09\xf1\x6a\xab\xa2\xa5\xb3\xb1\x9c\x4e\xe7\x96\xcd\x72\xac\x27\x38\xac\x7b\x2c\x80\x90\xe2\x91\xff\x68\xd2\x19\x2c\x57\xc9\x45\xb9\x2d\x54\x79\xb6\x46\xd4\x1a\x4e\x53\x5d\x95\x92\x99\x59\x32\x9e\x68\xa2\xd9\x9b\x5a\xad\x74\x0c\x73\xaa\xe8\x85\x96\xdb\xbe\xd9\x6a\x35\xfd\x5d\xd4\x66\x65\xd5\x8d\xa7\xd4\xb8\x92\xdd\x94\x9a\xf3\x38\x9a\x67\xca\x6f\xb3\x39\xdb\x55\xcd\x95\xa2\xd5\xdf\xc6\x19\xad\x97\x6a\xd5\x12\x79\x20\xf9\x3b\x42\x73\x7a\x7b\x10\xdc\x7b\x09\xd9\xf1\x72\xbc\x72\xd9\xdb\x24\x06\x6f\x53\x14\x5f\x81\x7c\x79\xbe\x40\x9c\xa6\x20\xb3\xb5\xe2\x3a\x30\xb5\x91\x9a\x1b\x81\xa8\x2a\x83\x49\x21\x56\x97\x9d\x46\x8d\xd7\x37\x5d\x79\x38\x90\x4d\xc8\xb3\x49\x34\x4b\x25\xb9\xb7\x46\x4b\xc1\xe7\xcd\x15\x54\xad\xb2\x21\xaf\x39\x5e\x6d\x4c\x32\xd9\x74\x41\x14\xfe\xfe\xfb\xeb\xf1\x96\xdc\xf4\xd1\x56\xd6\xc3\xc7\xd2\xe1\x47\x4f\x2e\xf2\x64\x30\x21\x5a\x40\x1d\xd0\x2d\x62\x32\x27\x90\x51\x54\xd2\x84\xb3\x1e\xd5\xbb\xf9\x1e\xbf\x92\x06\x66\x5d\x84\xa8\xcd\x35\xf5\x94\x79\x78\xd4\x95\x6d\x2a\xd5\x6a\x79\xc7\x2e\x08\xf9\x24\x97\xae\xac\x3b\x1a\x99\x28\x8e\x5a\xf9\x25\x39\x1f\xbe\xd9\x0c\x5c\x80\x0c\x2c\x66\x32\xb8\x4d\x8b\x24\xa8\xb5\x9a\x55\xdd\x19\xfa\x07\x21\xa0\xf8\xcc\x7b\xf4\x97\xeb\x5b\x91\x8d\x8d\xfd\x47\x0f\xf2\xae\xee\x75\xd9\x3d\x3a\x48\x3c\xea\x7c\x6b\x5e\x62\x0a\xa8\x0c\x07\xa3\x75\x11\x36\x2b\x3c\x23\xbe\x69\x36\x8f\x70\xc5\xb4\x4a\xbd\xce\x9b\xd8\xce\x8d\x53\x66\x7e\xa7\x1b\x82\x50\xa6\xad\xac\x72\xb0\x0d\x31\xd0\x7f\x27\x7d\x17\x72\x89\x2f\xc6\x9f\x88\x82\x3f\xe1\x9d\x93\x71\x68\xe8\x3e\x9f\x58\x98\xa4\xe9\x50\xf4\x3c\x51\x91\xd6\xb3\x6a\x9c\x34\x33\xa5\xd8\x1b\xc1\xd6\x36\xba\x4d\x18\x5a\x31\xd5\x9d\x54\xdb\x03\x6b\x51\x8f\x35\xbc\xee\x6d\x35\x71\x1f\x71\xa1\x4d\xa5\x70\x34\x2c\x33\xc2\x86\x4f\xe0\x15\x3b\x2d\x0d\x96\x0a\xc1\x12\x44\x93\xe7\xba\x23\x6a\x52\x18\x4f\xf8\x2a\x4b\x8f\x13\xe4\xd2\xd3\x87\x05\xdc\x0c\xc4\xf8\xfe\x5a\x85\xd1\xec\x7e\x4f\xff\x1c\xfa\xda\x63\xa6\x7a\x8b\x3e\x57\x7e\x29\xf7\xa3\x2b\x4f\x71\x01\x13\x72\xab\xd3\x03\x49\xa3\xd3\x86\x56\x8b\x69\xae\x57\x72\x9b\x4c\x97\x72\x83\xd9\x94\x14\xea\x89\x61\x36\x35\xa3\xe5\x75\x3d\x7b\xe4\x7c\x5c\x7d\x7c\x42\xdf\x9f\xb1\xcf\x8a\x86\x7b\x36\xe3\xe9\x43\xe8\xc1\x10\x47\xfa\xea\x39\x84\x9f\xe2\x8f\x5a\xad\x46\xcd\x07\xe5\xc8\x83\x4e\x8d\x91\x58\x33\x59\xc0\x0b\xd5\xd8\xaa\x5b\x4f\xf0\x6f\x9d\x65\xa7\xd5\x20\xd7\x7a\x45\xef\x2e\xea\x32\x91\x5c\x4e\xaa\x05\xe4\x1d\x5d\x76\xf0\x07\x2e\x3d\xa5\x30\x26\x3d\xfa\x9a\x7b\x7e\x85\x34\x6d\xe6\x9c\x96\x3a\xed\x96\x5b\x6a\x6f\xee\x74\x66\x8d\x8c\xe8\xc8\x4a\x17\x9f\x24\x26\x9a\x22\x66\xf3\xd2\xa0\x3d\x35\x96\xa9\xec\x10\x3e\x4b\x5f\x99\xb6\xf2\x42\xe6\xa0\x6a\x07\x7d\xf7\xba\xf5\xe0\x44\x43\xaf\xa3\xfe\x89\x34\x5e\x3c\xa1\x3f\xa2\x38\xce\xdb\x82\xb6\xa7\x9c\x13\x02\xfe\xb0\x46\xc1\xe2\x15\xd2\x8f\xec\xc7\x3b\xae\xe1\x41\xfb\x79\x42\x9f\x2e\xfb\x1f\x31\x48\x65\x46\x21\x8c\x33\xd2\xbd\xa3\x1b\xa3\xeb\xcb\x13\xe3\x5b\x91\xb7\x8d\xc1\x15\x7d\x39\xba\xda\x49\x25\x18\xba\xf9\xe3\x9f\x70\x68\x5f\x06\x89\xb8\x50\xa6\xe8\xae\x98\x24\x9d\x4c\x2b\x55\x26\x6a\xa4\x80\x17\xd1\xb8\xc2\xe5\x6a\xcc\xb4\x44\x08\x3c\x6a\xeb\xea\x26\xeb\x78\xf6\x51\x6b\xb5\xea\xbe\xbe\x0c\xe2\xe2\x88\x6b\x91\xfc\x6a\x94\x25\xea\x16\xcf\x98\x0a\x5b\x9e\x58\xce\x10\x8c\xc4\x35\x5f\x28\x57\x55\x7e\xdc\x6a\x49\x59\xab\x5b\xf7\xf4\x81\x9d\xd8\x66\xb8\xbe\x1c\xae\x33\x7d\xfe\x38\xfa\xc4\x64\x7b\xc2\x5c\xa3\xef\x10\x4f\x1c\xc6\xcf\xe4\xe1\xf6\xa3\xe3\xd3\x56\x1e\x13\xe5\x00\x2f\x5c\xff\xce\xc7\xf6\xdd\x75\x34\x3e\x46\xc6\x3f\xa6\xa2\xe1\xf7\x62\xd9\xff\xbc\x57\xa0\xec\xae\x39\x4d\xcd\x29\xda\x9f\xb1\x73\xcf\xdf\xdd\x1a\x0d\x7e\x7b\x6e\x7d\x34\xff\xe3\x59\xc4\x90\x0c\x80\x1c\x21\x2b\x8c\x0c\xa1\xca\x40\x00\x34\x24\x23\x04\x01\x22\x19\xa4\x91\x80\xe4\x64\x85\x65\x39\x5a\x25\x81\xaa\x41\x9c\x94\x29\x46\x51\x39\x85\x43\x80\xa5\xe4\xaf\xbb\x65\x8e\x97\xcc\xff\xe8\x1b\xf3\x3f\x96\x00\x34\x73\xf9\x18\xac\xed\xdd\xc3\xfc\xcf\xcf\xf0\x3f\x3b\xff\x4b\x06\x3a\xff\x95\xf3\xbf\x4c\x6e\xe5\xa9\xe0\x87\xce\xff\x1a\x92\x73\x64\x43\x47\x57\x7a\xcf\x7f\x35\xc3\xd4\xd9\x75\xbc\x5a\x48\xcc\x06\x4e\x1c\x0c\x7b\xa5\xde\xb0\x23\xcd\x52\x33\xb8\x51\x9a\x4c\x7b\x84\xea\xe4\x5b\xa1\x48\xa4\x47\x48\x2b\xa5\x59\xd9\x49\x52\x72\x21\xb1\xe8\x6e\xda\xb9\xf5\x52\x91\x4b\x1a\xcb\x70\xbd\xca\x5b\xae\x53\x29\xab\x52\x83\xed\x26\x56\x43\x7a\x26\x0c\x9a\x0f\xce\x01\x9f\x88\xb9\x8e\x40\x8b\x3c\x35\xf3\x3e\x3d\x11\x13\x0b\xca\x34\xe9\xcb\x3b\x12\x3d\xcf\x8e\xd9\x82\xb1\x8a\x9f\x4c\xda\x35\xb4\x3b\x92\xf6\x03\xc7\xb0\x9c\x52\xf1\xf5\xf5\x78\x3e\xff\x7e\xf3\xcb\x48\xf3\xbb\x17\xe2\x4f\x46\xc1\x9f\x3c\x8c\x8f\xa9\xa3\x5b\x8f\xce\x8f\xd8\x89\x3d\xf0\x02\x48\xf7\x7b\x33\x00\xcf\xbf\xaa\xe7\xf8\x05\x61\x69\xad\x7c\x19\x24\x6b\x6f\xcb\xf0\x67\xba\x87\xef\x8f\xc6\x6f\xdb\xf8\xd1\x9b\x34\xb8\xfd\x23\x56\xf7\xf4\x85\xd0\x72\x2a\x33\x51\x00\xbb\xf3\x8c\x53\x15\xbb\x1b\x7c\xe6\x48\x7f\x7e\xb5\x78\x3e\x38\x5f\x7f\x38\x9e\x8f\xee\x9b\x24\x9d\x5c\x84\xcf\xd7\xfd\x3e\x98\x33\xc6\xb5\x93\xe3\x0e\xf3\x3f\xcf\xde\x1e\xd5\x87\xa3\xfe\x75\xaf\x27\xe6\x83\x07\x7d\x75\xfb\xb3\x10\x4a\xef\x41\x7f\x7f\x3a\xbd\x62\x83\x4d\xdf\xa4\x77\x25\x9c\xce\x97\x1e\x8c\x45\x9e\xa1\xaf\x04\x1b\xb3\xf0\xf9\x75\xa8\x3c\x3f\x9c\xbe\xc2\x94\x94\x6f\xd2\xf7\x12\xfd\xf4\xf2\x95\x4f\x8c\x7d\xee\x95\x1c\x53\xde\xf0\xe0\xd1\x93\x0e\xed\xef\x97\xe8\xe7\x6b\xe8\x15\x4b\x38\xba\x49\x6f\x50\x3f\x7f\x9d\xf9\xfc\xd3\xf9\x9f\x27\xe4\x3b\x87\x3a\xba\x36\x5e\x1c\x5d\x1b\x65\x65\x06\x7f\x2b\x0a\xa7\xe3\x85\xc0\x76\x0b\x9c\xc0\x8e\x8c\x81\x54\x41\xb8\xda\x6c\xb2\xad\x8c\x92\xac\xae\x99\x6a\x7c\x65\x64\xe6\x0a\xd9\x4c\x12\x34\xcc\x91\x59\x9d\x70\xdb\x3f\x11\x4b\x4a\x25\x28\x9b\x8f\xe6\x9f\x3f\x92\xbe\xb7\x82\x9c\xbd\x46\xdf\xdf\x61\xb9\x88\x9f\x94\x0b\x10\x5e\x94\x8b\x18\x35\xa3\xe1\xf7\x73\x11\xda\xac\xb0\xcc\xf0\x82\x9d\x9f\x24\xc8\x38\x4c\x8d\x89\x49\x4a\xa9\x8f\xdb\x86\x95\x5b\x37\x66\xb0\x44\x17\xb4\xa2\xfd\xd6\x84\x25\x9a\xc3\x65\x67\x81\x57\x86\xb6\x9d\xa7\x47\xb9\xee\x34\xcd\xaf\x6d\x22\xbe\xb4\xd6\xe3\x78\xd1\x50\x38\x1a\xaf\x55\x9c\x41\x21\x91\x99\x8c\x13\x62\xf5\x63\x73\x11\x38\x24\x64\x99\xd2\x14\x0e\x91\x3c\x54\x78\x9e\x25\x71\x45\x21\x19\x12\x30\x0a\x0e\x38\x9e\x01\x04\x4f\x33\x90\xd1\x78\x15\x20\x1e\x20\xc4\x03\x56\x65\x19\x00\x19\x16\xe7\x28\x5c\x51\xbc\x5c\x04\xf9\xa2\x5c\x04\x73\x2b\x17\x01\x08\x86\xbc\x7c\x5e\xf7\xee\xee\x49\x6d\xdf\xb3\xb9\x88\xa0\x91\xbe\x34\x17\xb1\x64\x7c\x57\xf8\x81\xb9\x08\x37\xff\x1f\xbc\x8e\xd6\xa2\x85\x6c\x6c\xc6\xe8\x4a\xb9\x60\xd4\x7b\x9b\x66\xbd\x99\x13\x62\x36\x9e\x1c\x16\x62\xc5\x46\x32\x2f\x90\xa8\xbd\x44\x34\x9e\xae\x64\xb4\x95\x29\x43\x84\x14\xa6\x93\x98\x28\x38\x1a\xd7\x1d\x9c\x98\xae\xea\x54\xa9\x30\xd1\x36\x5a\x23\xdd\x9b\x72\x6a\xad\xd6\x4b\x0c\xaa\x4d\x52\xa8\x06\xd7\xa2\x1b\x61\xb1\x47\x69\xfb\x1b\xef\xf1\xf5\x11\x73\xdd\x48\x73\xcd\x17\xe2\x97\x1e\xc4\x2f\xbc\xde\x07\x47\xf5\x81\xc2\x8b\x7c\xf0\x70\x15\x0d\xbf\xef\x83\xdf\x4b\x59\xa3\xf9\xe0\x5d\x75\xfc\x83\x4e\x98\x23\x19\x95\x62\x54\x95\x84\x80\xa1\x68\x1a\x57\x80\xac\x52\x38\xce\x2a\x04\x8e\x43\x5c\xe1\x69\x99\x26\x15\xc4\x72\x0c\x83\xb3\x08\x52\x0c\x4f\x28\x04\xc4\x39\x9a\x06\x1a\x87\x08\x08\xbd\xf3\xe8\x89\x67\xf6\xd0\x3d\x92\x10\x26\x39\x8e\xbb\xfc\x1e\x91\xdd\xdd\x93\xba\x68\xff\x15\x07\x8f\x05\xb9\xf7\x25\x84\x8f\x12\x04\xef\x3d\x09\xde\x07\xb1\xa2\x30\xdc\x54\x19\x09\x5f\xf2\x52\x45\x28\x29\x83\x4a\x17\x3a\x1c\x9e\x2a\x4f\x0d\xb9\x57\x4f\xb4\x32\x93\xc5\xbc\x56\xab\x00\xb4\xae\x1a\xf1\x79\xb7\x2e\x4c\xd0\x20\xb6\x31\x28\x0d\xe7\x46\x89\x5c\x22\xdf\xa5\x7b\x54\x59\x2c\xb4\xde\x24\xc2\xce\xc5\x32\x74\x9b\x6c\x93\xed\x95\x7e\xee\x24\x43\x93\xb5\x41\x59\x08\x51\x64\xeb\x5d\x1f\x93\x40\xb8\xe8\xc8\x8f\xd8\x7b\x34\xc1\xbb\x75\xa4\x9e\x20\x8e\x92\x96\x67\x15\x56\x37\x1c\xf9\xeb\xf0\x27\xa3\xe3\x7f\x75\xd2\xb2\x28\x84\x14\xd0\xdd\x72\xe2\xaf\xc6\x7f\xae\xa3\xa1\x49\xd3\xc3\x15\x9a\x34\x75\xaf\x5f\x28\x49\xb6\xda\x33\xfa\x89\x8a\x3a\x82\x7d\xf0\x39\x8b\x4e\x12\xb1\xe5\xb9\xce\x7a\xd7\x8d\x45\xf0\x28\xfa\x7a\x3c\xf1\x0c\x2d\x38\x7d\x67\x7b\x39\x0e\xba\x1e\xc1\xef\x07\x3d\xef\x35\xf8\x7c\xe4\xc4\x93\x60\x21\xab\x52\x8c\xa2\x92\x9c\x7b\x18\x9e\x8c\x90\x06\x65\x42\x01\x04\xcd\x02\x02\x28\x32\x05\x78\x1c\x01\x8a\x01\x90\x64\x28\x4e\xc3\x71\x4a\xa6\x78\x85\x84\x2c\xc9\x32\x90\xf1\x63\x1e\xf0\xa2\x98\xe7\xe6\xc4\x93\xe4\x71\xfe\xf2\xeb\x73\x76\x77\x4f\xb6\x70\x3d\x1b\xf3\x5c\x99\x78\xba\x36\xf0\x31\x89\xd5\xa3\x98\x47\xef\x64\xde\xb2\x8c\x35\x22\x41\xbc\xa7\x2e\xca\x39\x23\x3b\xe4\x62\xed\x74\xbd\x54\xb0\x67\xb3\x1c\x01\x2a\xa3\x38\x1a\x3b\x53\x80\xb7\xc4\x24\x3b\xc6\xd7\xed\x11\x0f\x12\xe8\x4d\xad\x5b\x03\x81\x66\x41\xa7\x4a\x0e\x9b\x9d\x76\xb7\x69\x56\xd8\x4a\x7a\x39\xde\x74\x92\xdd\xb7\xc4\xea\xa3\x63\x9e\x8f\x49\x4a\x7f\x40\xcc\xe3\x7d\x5c\x05\x31\x07\xd4\xe6\xcc\x8f\xe0\x0a\x1b\xfe\xcc\x0b\x63\x80\xaa\xf0\xb2\x18\xe0\x30\x66\xbd\x5a\x7e\x9e\xa0\x3e\xaf\xfc\xce\x83\xc7\x28\x0b\xcf\xee\xf5\x0b\x2d\xe4\x3c\x1b\x43\x3d\x9b\x18\x7b\xef\x18\xea\x5d\xe8\x3b\x53\x95\x72\x63\x78\xa2\xa4\x61\x31\xd4\x4f\x8a\x61\x84\x17\xd9\xcb\x71\xe2\x28\x42\x0c\xf5\x5e\x83\xd9\x47\xc6\x50\x0c\xc3\x30\x34\x03\x19\x04\x55\x04\x70\x0e\x28\x34\xcb\xe1\x34\x4b\x00\x86\x55\x79\x44\x51\x34\x89\x10\xa2\x59\x8e\x50\x20\x0f\x69\x0e\x42\x92\xe0\x91\x8c\x6b\x88\x23\x29\x9a\xd6\xd4\xfd\xe9\x0a\xd1\x4f\xdb\xf0\x4e\x66\xb8\x1a\x3a\xb1\x0c\xc7\x5d\x7c\x55\xff\xfe\xee\xf1\x4e\x55\x3f\x72\x2a\x70\x99\xea\xb2\x3a\x96\xf3\x20\x23\x90\xed\xd6\xa8\x66\xe5\x27\xa3\x0e\x8e\x6b\x69\xce\x2e\x64\xd9\x09\x2e\xd5\x56\xb9\x76\x5c\xe8\x90\xc2\xe9\x3b\xbb\x43\x4b\x7c\x8f\xaf\x48\xb3\x97\x23\x78\xad\xe5\x2a\xc5\x6f\xf5\x4f\x12\xd5\x64\x07\x01\xb2\x49\x21\x3e\x01\xea\xeb\x99\x58\xe8\xd5\xd6\x84\x95\x7b\xab\xa7\x0a\x39\x7c\x9d\x4c\xe2\x8b\x7c\x7a\x36\x99\xcb\x9a\x91\x6c\xc4\x3a\x9d\xec\x9c\x69\xea\x49\xf1\x6d\x92\x5a\x3b\xb1\x74\x39\xd6\x99\xa7\xcc\x6a\x45\xb5\x3a\x0d\x76\x46\x98\x85\x5e\x36\x33\x6f\x14\x2b\x77\x44\x44\x27\x2a\x7d\x1a\x6d\x1c\xf1\xec\xda\x48\x30\x23\x20\xea\x71\x11\x2f\xe0\xb9\xf4\xc6\x19\xae\x4a\x84\xd1\xc5\xe1\x66\x66\x12\x7c\x29\xb3\x5e\x16\x12\x9b\x32\xed\x88\x92\x92\xf0\x78\x24\x07\x8e\x55\x9e\x76\xe3\xd4\x51\x9a\x2d\xf4\x55\xd0\xb7\xac\xfd\x09\xfc\x25\x6b\xd3\xa8\x3e\x81\x5f\x08\xe0\x7f\x78\x99\xc6\x2d\x23\x77\xaf\xb3\x0c\xcf\x2d\xfc\xa1\xcb\xa6\x62\x74\x59\x94\xa7\x67\xef\xa6\x7f\x48\x16\xcf\xf6\xc5\x56\x17\x62\x4a\x00\xde\x43\xb2\xf8\x4f\xa7\x4a\x90\x8e\x43\x94\x33\xcb\xaa\x33\xb6\x61\xb5\x0e\x9a\x8a\x0a\x37\x0a\x3e\xac\x6f\xd4\x62\x75\xc5\x17\xf4\xe1\xbc\x37\x9f\x90\x74\x15\x8f\x1b\xc4\x26\xbf\x30\xb2\x83\x95\x42\x0f\x15\x59\x1b\x8e\x96\x06\x33\x84\x52\x92\x84\x04\x1e\x63\x54\x98\x00\x75\x91\x19\xbf\x25\x3f\xd8\xf3\x6a\x32\x62\x54\x56\xa3\x78\x05\x00\x48\xe3\xb8\xac\x91\x08\xe0\x38\x4b\xb0\x14\xaf\x40\x02\x90\x2c\x4e\x00\xa8\x2a\x32\x4d\x69\xaa\xa2\xd0\x14\x52\xa0\xaa\xb1\xb8\xa2\x41\x0e\x71\xb4\xff\x3e\x62\xf2\x45\xb3\x57\xf6\xf6\xec\x15\xb0\xd7\x66\xaf\xde\xdd\x93\x73\x43\x9e\x9d\xbd\x06\xcb\x26\x5f\x38\x7b\x7d\xa6\xa4\x98\x8f\xfb\x11\xa9\xeb\xcf\x93\xa1\x7a\x9a\xda\xf3\x53\x15\xec\xb4\x4a\x99\x0a\xbb\x64\x3a\xab\x12\x33\xd0\x14\xad\xd0\x89\x83\x6e\x76\x35\xaa\x25\x53\xa8\x22\x14\xdf\xca\xcd\xaa\x12\x13\x27\xd9\x16\x6a\xd5\x59\x62\xb5\xa0\x39\x9b\x29\xa4\x59\xbd\xdb\xd4\xd2\x55\x41\x67\xde\x9a\x59\xc6\xb4\xa4\x89\x02\x84\xcc\x48\xd8\x24\xde\x12\xd5\xbb\x4a\xb2\x5f\x38\xe3\xfd\xcc\xf2\xbe\x52\xd2\xfc\xe2\x99\xde\xf9\xba\x62\xe8\x4c\xaf\xc0\x70\x7e\x09\xcd\x87\xcc\xf4\x9a\x21\x84\x3c\x53\x62\xac\xbc\x87\xfc\x52\x9f\x5c\x7e\xaf\x29\xd1\x7e\x76\x4b\xe6\xcf\x99\xd9\x09\xa7\xab\x49\x1f\x5e\x92\x77\x79\x8b\x5d\xd0\xd6\x45\xb2\xd4\x0b\x8f\x4b\xfe\xdb\xb7\x34\x27\x9f\xed\x9f\x27\xe8\xbb\xd5\x3f\x47\xf6\x1a\x76\x1d\xd9\xeb\x47\x97\xd8\xdf\xda\x32\x2b\x6a\x9d\xe1\x05\xaa\x5f\x9f\xed\x88\x9a\x6d\x10\xde\xc1\xe7\x45\xc8\x76\x24\x56\x3d\x52\x1f\xbe\x2d\xe2\x33\x4d\x20\xe7\x22\xbf\xe6\x1c\x2d\xde\x1b\x8c\x12\x25\xa9\xd8\xa2\x38\xe1\xad\x48\xd7\xc4\x37\x2a\xdd\x1d\xb6\xe8\x56\x61\xd9\x49\xb0\xd3\xcd\x9b\x69\xcb\x8b\xdc\xb0\xc6\xf5\x84\x44\xc1\x2a\x55\x47\x73\xdd\xae\xf7\xde\xba\x02\x2a\x26\xb3\x85\x62\xee\xa3\x4b\x15\x79\x4a\x63\x79\x99\x05\x1a\x54\x55\x04\xb7\xb1\x2f\x0f\x78\xc8\xcb\x38\xc1\x2a\x84\x42\x13\x14\x4b\x13\x9a\x06\x71\xc8\xaa\x1a\xaf\xa9\x32\x64\x15\xc4\x11\x0a\x8d\x6b\x2c\x0d\x39\x80\x7f\xfd\x86\x51\xbb\x63\x73\x22\xbe\xfb\xe2\x28\xe6\x26\x6f\xc5\xdc\x34\x0e\xc0\xe5\xb4\xc7\xee\xee\xc9\xb9\x78\x5f\xa3\xd8\xc9\x51\xcc\x7d\x25\xef\xf1\x73\xfc\xce\xe1\xca\xec\xe9\xad\x16\xe7\x40\x9a\xe5\xf1\x42\x67\xd5\xd3\xeb\xd6\xaa\x63\x4f\x84\x84\x25\xce\x07\x9d\x5a\x3c\x36\xae\x64\x67\x69\xa2\x59\x1c\xf4\x2a\x54\x0c\xb6\xa8\x65\x83\x29\x4b\xab\xa5\x30\xa8\x89\x66\x1e\xd6\x2a\xa3\x9c\x4a\x97\x3b\xdc\xa0\x2c\x96\x73\x4b\xbc\x96\xaf\xa0\x6a\x59\xee\x4d\xa8\xea\xea\x9e\x98\x3a\x7c\x6b\x75\x30\xee\x3c\x6a\x14\x21\x4f\x94\x2b\x1f\xfa\xe3\xc2\x75\xa3\x2a\xe4\x75\xf8\xcf\x43\xb6\x3b\xf0\x9f\xad\xb2\x7f\xb4\xdf\xf7\x48\xb9\xa7\x54\x5e\xfa\x29\xf4\xdd\x3c\x4a\x26\x34\xe7\xf3\x93\xf2\x4f\x01\x59\x45\xc6\x7f\x7c\x6c\xc0\x23\xf8\x77\xdb\xf6\xad\x6e\x7d\x6c\x55\x1d\x4d\x9c\xe4\xf2\x4b\x11\x6d\xba\x42\xde\x4e\xcf\x45\x35\x13\x67\xaa\x9c\x3e\x96\x5b\xd5\x8d\x38\x8e\x8f\xe8\x59\x47\xe7\x2b\x26\xd5\x48\x70\x09\x51\x4a\x0f\x66\x33\x29\x56\x34\xc8\x31\xad\x6d\x04\x4a\xa2\x26\xf1\x9a\x64\xf2\xb4\x40\x3b\x13\x79\x98\xfc\xe0\x6d\xfb\xa4\x86\x73\xb2\x06\x09\xa4\xc8\x1a\x4f\xca\x04\x22\x79\x1a\x52\x32\x4f\x40\xc0\x01\x44\x53\xa4\xa2\xc9\x84\xaa\xb2\x0a\xa1\x51\x0c\x62\x79\x80\x6f\xdb\x01\x92\x43\x1c\xa0\x78\x59\xf1\xc6\x1f\xf0\xcc\x1b\x7d\x1e\x1b\x7f\x48\xf6\xda\xf8\xe3\xdd\x3d\x39\x03\xd5\x2f\x95\x7f\x6c\xeb\xc8\x7b\x8e\x3f\xcf\xce\x4b\x8e\xf0\xef\xe9\xad\x16\xdb\xf1\xb9\x1e\x2b\x27\xac\x02\x37\x9b\x2a\x6f\x0b\x2b\xc7\x88\x23\xc5\xa8\xc9\x9d\x44\x77\x25\xe0\x62\xae\x04\x57\x79\xb9\xad\xbc\x69\xc2\xaa\xb6\x18\x9a\x4b\x00\x26\x4d\x99\xd0\x20\x10\xd3\x05\x43\xcf\x68\x5c\x6d\xce\xd4\xf4\xfc\xa0\x56\x11\x0b\x4b\x22\x63\xe5\x33\xd9\x95\xfd\x2e\xe3\x4f\x84\x79\xe4\x4b\xc7\x9f\x27\xf1\xff\xcc\xf1\xe7\x89\x6d\xff\xc2\x47\x8c\x3f\xef\x71\x94\x90\x7f\xdd\x1c\x7f\xa2\xdb\xd2\x6b\xc6\x9f\x08\xf8\x9f\x1c\x7f\xd6\x72\x6c\x5e\xa0\xa8\xbc\xbd\xdc\x4c\xd4\xb7\x32\x63\x4f\xcd\x74\x69\xd3\x4a\x39\x4a\x6e\x24\x24\xab\xd2\x98\xb0\x84\x99\xd3\x7b\x2b\x71\x49\x31\xcd\xa4\xf5\xb8\x0c\x7b\xb5\x65\x8b\xb7\xba\x52\x77\xd1\xce\xaa\xf1\x75\xda\x9a\xa5\xb3\x73\x51\xe2\xa4\x45\xbc\x89\x6c\x53\x19\x7d\xf4\x6a\x2f\xcb\xe3\x40\xc6\x29\x55\xc3\x35\x99\x24\x35\x08\x69\x5e\xe6\x48\x8d\x27\x38\x59\x23\x20\xcb\x93\x90\x60\x80\xac\x02\x55\x21\x55\x8a\x92\x79\x9e\xe4\x11\x4b\xb3\x8a\xc6\x2a\x32\xcb\xb0\x84\x37\xfe\x90\x2f\x9a\xff\xdc\x3a\x36\x94\xa5\x71\x8a\xbb\xbc\xe6\xb0\xbb\x7b\x72\xde\xf5\xb3\xf3\x9f\x2b\xc7\x86\x7a\xea\xf7\xe0\x76\x9d\xf7\x99\xff\x24\x12\xeb\x21\x12\xa9\x44\xcf\xea\xea\x29\xad\x28\xb4\x19\x65\x3c\x8a\x8f\x1a\xb9\xb7\x8c\x3e\x64\x13\x4e\x8d\x6b\x24\xf1\xb4\xb2\x6c\xc9\x4c\x9c\x11\xdb\x3a\xdf\x02\x53\xb1\xba\x4c\x3a\xf1\x0d\x59\x9a\x8a\xce\xc6\x96\x53\x52\xb9\x48\xa4\x5b\x0c\xb3\x4e\x39\x0b\xae\x95\x4a\x0b\xd5\xcf\x38\xff\x89\xe4\xff\x5f\x88\xff\x42\x45\x71\x94\xf1\xe7\x03\x8f\x82\xf4\x48\x79\x70\xfc\xf9\x4c\x47\x69\x86\x8e\x3f\x3f\x69\xfe\x21\xbc\x68\xfe\x73\x5c\x31\xfe\x08\x7e\x7f\xfc\xc9\x16\xd2\x29\x2a\x33\xc8\x4d\x1c\x3d\xdb\xe2\x56\xa2\x3c\xdb\xd4\x2b\xb1\x52\x71\x5a\x44\xf9\x8c\x9d\x27\x32\xeb\x62\xa5\xda\xdb\xf0\xad\xa5\x15\x37\x53\xb0\x40\x74\xa0\x92\x4a\x70\x65\x32\x5e\x50\x80\x92\x26\xf3\x6b\xbb\x59\xa5\xde\x9a\xbd\x8e\x65\x49\x6d\xc0\xae\x9b\xcd\xee\x47\x1f\x5b\x26\x13\x1a\x07\x38\x92\xa3\x14\x9a\x41\x94\x8c\x03\x4a\xa3\x00\x4b\x6b\x80\x62\x68\x0e\x87\x32\x94\x35\x8d\x80\x88\x94\x79\x19\x32\x84\x8c\x93\x1c\xcf\x92\x34\x8b\x68\x16\x21\x59\x71\xf3\x6f\x60\x57\xb1\x1d\xb9\xda\x08\xdc\xac\x36\x62\x71\xea\x4a\xb5\x91\x7f\xf7\xf8\x14\xfa\x67\xab\x8d\xae\x8c\x3a\xde\xf5\xe4\x06\xdd\x93\x6a\x23\x6d\x9a\xaa\xbf\xf5\xd0\x90\x60\xdf\x1c\x0e\x98\x45\x75\x8e\xa8\x58\x7c\x3d\xb5\xe3\xe3\x8c\xa8\xa6\x3b\x1a\x2f\x66\xc5\x5a\x57\x6b\xf5\xc8\x64\xb5\x41\xc2\xd5\xaa\x37\xa5\x0b\xf3\x41\x36\xcd\xe7\xe6\xc6\xb2\x38\xa9\x11\x8d\x3c\x5c\x2b\x66\xae\x9a\x5c\xcc\xd3\x4a\xa2\xae\x14\x3f\x57\xb5\xd1\xb3\xd5\x3e\xcf\x56\xb8\x14\x57\x85\x89\xf9\xca\x6a\xa3\x0f\x8c\xb6\x6f\x45\xfe\x1f\x59\xed\x23\xbc\xa8\xda\x88\xa3\x0e\xcf\x5f\x98\xd5\x5e\xad\x36\xea\xd0\xeb\xa6\x0d\x3a\xa6\x8a\x38\x56\x2b\xcd\x93\x19\x38\x5d\x54\x96\x5c\x8f\xad\xd0\xe2\xaa\x53\x33\xc8\x78\xb5\x2e\x34\xdb\x19\xa2\xad\xae\x70\x89\x07\x76\x31\xdd\x8b\xd5\x19\x33\x21\x2e\xeb\x70\x26\xbf\xe5\xc6\x6a\x73\x33\xb1\x3b\xf9\x44\x53\x60\xe7\xc3\xa9\x30\x9e\x7e\x74\xe6\x49\xe1\x49\x8d\xc3\x19\x86\xd5\x48\x56\xd5\x58\x1c\x02\x1e\x29\xb8\x8a\x78\x46\xd3\x48\x92\x23\x18\x8a\x82\x0a\x07\x38\x48\x29\x08\x12\x8a\xcc\x28\x48\x26\x64\x05\x29\x8c\xa6\x69\x38\xcd\x79\x91\x3f\xf5\xa2\xcc\xd3\x1d\x91\x3f\xcd\x13\x57\x22\x7f\xef\xee\xc9\x5b\x65\x9e\xcd\x3c\xdd\x8c\xfc\x3f\xfa\xd0\xd9\x23\xfc\x87\xcc\x53\x9a\x32\xd8\x71\x42\x98\xd3\x70\xbe\xac\x03\x35\x9e\x69\x38\x5d\x85\x2d\x08\x90\x9d\xd5\x9b\xba\x5e\xa6\xf2\x9b\x7c\x4e\x9e\x4f\xec\xe4\x60\xa9\x8c\xd3\x09\xa0\xca\x43\xc5\x32\x79\x47\x59\x26\x7a\x19\x6d\x35\x6f\xb4\x62\xfa\x78\xc9\x65\x26\x5c\x4f\x83\x0c\x39\xee\x56\xc6\xd5\xee\x67\xcc\x3c\x3d\x1d\xf9\x3f\x89\xff\x85\x91\xff\x07\x1e\xc2\xe3\x91\xf2\x60\xe4\xff\x81\xf4\x3d\x1f\xf9\x7f\x60\xe6\x47\x78\x51\xe6\xe9\xc9\xc8\x5f\xd6\x3b\x8b\x6a\x36\x61\x19\xf3\x39\x5f\xe8\x91\x9c\x5a\x26\x86\x6f\xb6\x2d\x5a\x0b\x23\x57\xcf\x67\xd9\x81\x95\x35\x8d\xc5\x1c\xae\xca\x09\x7e\x53\xed\x16\x7a\xc4\x22\xb5\x59\x8c\x00\xb1\xe1\x72\x63\x35\x9e\x98\x95\x3a\x4c\xbe\x1e\x5f\x21\x79\x6d\xf0\x96\x85\x6a\x83\x58\x4d\x1c\x7c\xec\xf8\xc3\x11\x04\xc1\x03\x85\xe4\x18\x8a\x54\x35\x96\x54\x70\x82\x86\x34\x24\x54\x96\x95\x39\x1c\xa8\xdb\x41\x46\xa5\x34\x1a\xd7\x14\x46\x25\x70\x8e\x60\x20\x64\x69\x05\x87\x0c\x81\xf3\x1a\x0f\xf7\xaf\xbc\x7c\x49\xb5\xeb\xcd\x95\x0f\x86\xc6\x89\xcb\xe3\xcf\xee\xee\xc9\xbb\xc8\x9e\xad\x76\xbd\xb2\xf2\xe1\x1d\xf2\x16\x29\x93\x44\x06\x2a\xc2\xdc\xeb\xa8\x3a\xb5\x62\x0c\xd8\x74\x61\x98\x1b\xe0\x6b\x76\x34\x13\x56\x84\xb4\x62\x32\xa0\x93\x62\x36\xb5\xec\x44\xcb\x65\x57\x29\x6d\x8d\xf3\xa5\x85\x4e\xcb\x4e\x39\x27\xa4\xd0\x2a\x25\x94\xb4\x32\x14\x44\x2e\x55\xed\x19\xf4\x8c\x14\xe8\x01\x39\x66\x92\x99\xa4\x3e\xd0\x9a\xa5\x66\x92\x60\x06\xca\x3d\xe3\xc9\xf1\xde\xad\x7b\xe6\x03\xaf\xde\xaf\x7d\xa7\x0d\x0a\x3b\xf3\x7f\x35\xfe\x07\x0e\xc9\x11\x84\xcf\xbb\x92\x7e\x73\xbe\x10\x41\x56\x4f\xaf\x14\x3c\xd9\x57\x67\x07\xdc\xdf\x89\xdf\xf7\xd7\xb1\x76\xd2\xee\x2e\xa4\x49\xb2\x91\x59\x94\xc7\xc9\x64\xb3\x91\x34\xb5\x9e\xd2\xb1\x72\x92\xde\xe3\xc6\x23\xa1\x15\xcf\x34\x70\xc0\x14\x8c\x05\x4e\x8d\x85\x16\x2b\x34\x05\x82\xa3\x4d\x21\xb3\x6a\x89\x93\xce\x64\xaa\x24\x27\x49\xd4\x30\x8b\x4a\x39\x2f\xf2\x55\xa2\x5a\xe9\xcc\xc5\x0f\x5e\x29\x90\x55\x8a\x63\x54\x59\x55\x71\xa0\x52\x0c\xce\x11\x2c\xc3\x12\x0a\x05\x69\xc8\x22\x5e\x65\x10\xc7\xd0\x0a\x04\xbc\x22\x53\x04\x62\x80\xca\x42\xe8\x4e\x2a\x34\x84\x68\x99\x64\x54\xe4\xf9\xeb\x57\x1d\x30\x7f\x87\xbf\x26\x18\xf2\x8a\xbf\xf6\xee\x9e\xbc\xf1\xf1\xd9\x43\xdd\x3e\xd0\x5f\x1f\x1d\xf0\x2e\xf2\xe3\x49\xbe\x0d\xe6\xe4\x92\xad\x6a\x1b\xae\x52\x44\x63\x49\x26\x1a\x8d\x2c\xad\xaf\xe7\xe3\x2c\x2e\x9a\x83\x8e\x55\x76\xd8\x41\x99\x60\x40\x55\x1e\x0f\x81\x5a\x6f\x34\x35\x94\x34\x97\x0a\x5e\x11\xa0\x36\x4c\x76\xd6\xce\xb0\x25\x18\x76\x61\x31\x32\xc4\xc9\x66\x24\x0a\x77\xc5\xff\x4f\xf8\xeb\x97\xbc\x64\xe2\x4e\x1b\x14\x42\x7c\xc0\x47\xbf\xe4\x42\x10\x3e\x6f\xe6\xff\xe6\xca\x6e\x04\x59\xbd\xd2\x5f\x7f\xa4\xae\xf8\xfe\x3a\x03\xea\xdd\x99\x0c\x2d\x14\x77\xc4\x78\x61\xc5\xad\x99\x6a\x6d\xd9\x2a\x15\x47\x93\x42\x7a\x5e\x1d\x55\xd3\xba\x88\x6c\x86\x5c\x08\x6c\xc7\xea\x89\x8b\x7a\xa6\x47\xe4\x4a\x35\x9e\x2a\xeb\xfc\x5b\x95\x13\x67\x31\xa9\xa4\xa5\x41\xaa\x99\x68\xaf\x16\x4c\xb9\x99\x96\xf3\x45\xe9\xa3\xe3\x6b\x99\x56\xa0\xaa\x20\x9c\xd6\x14\x1c\xaa\xb4\xca\x68\x08\xc7\x79\x99\x93\x71\x15\xc9\x0a\xae\x92\xaa\xa6\x92\x00\x41\x0a\xc8\x1c\x92\x21\x89\x78\x04\x19\x4e\x01\x2c\xc5\x20\x8a\xc0\x35\xcf\x5f\xbb\x2b\xbb\x02\xdd\x16\x2b\x5d\x81\xee\x52\x6d\x41\xca\x74\xda\x35\xd0\xcc\x97\x41\xb3\x4c\x89\xcd\x74\xa6\x59\x65\x29\xa9\x59\xc9\x97\x4b\xa0\x9a\x69\x51\xed\x5a\xa6\x9c\xad\x95\xf2\xf9\x0c\x78\xd0\x5f\x03\xee\xf2\x0b\x41\x76\x77\x4f\xde\xab\xeb\xe9\xec\x83\x87\x5c\x3e\xe2\xaf\x23\xe5\x6b\x3a\x61\xfe\x5a\xda\xe3\xaf\x0a\xa5\x6a\xfd\x6d\x39\x93\xc4\x84\xd0\x59\xda\x44\x65\x30\xc9\xc4\x9b\x29\x59\x13\xba\x0e\x59\x16\x06\x83\x6e\xa5\xd5\x50\xf1\xd9\xa8\xa5\xe4\x60\x8b\x34\x92\x52\x7c\x54\xee\x15\xa7\x85\x54\xaf\x38\x4e\x49\xc3\x01\xa5\x1a\x8b\x56\x75\x8d\x92\x3d\x61\xd5\xc8\x37\x2b\x70\xaa\xda\xab\xc1\x3b\xfb\xeb\x47\xf3\x01\xaf\xf6\xd7\x2f\xc1\xff\x84\xbf\xfe\x4c\xf9\x9a\x5b\xfe\x3a\x8a\xac\x5e\xe9\xaf\x3f\x52\x57\x76\x07\x76\x12\x62\xa1\x1c\x1b\x57\xa5\xac\x88\x62\x6f\xcd\x58\xa2\xab\xf1\xd5\x96\xc3\x89\x3a\xa9\x50\x89\x84\x38\xe0\x5b\x25\xb2\x3e\x29\xb5\x56\xc6\xac\x83\x9a\xc5\x46\xac\x48\x8f\x37\x8a\xdd\x1a\x6f\xaa\xcd\x7a\x3a\x39\x04\x6d\xba\x95\x4c\x51\xa5\x71\x52\x2c\xce\xaa\xfc\x5c\x05\x6f\x89\x8f\xae\x04\x05\x88\x92\x21\xa1\x01\x82\x93\x19\x08\x01\x05\x70\x99\xe2\x59\x8a\x66\x20\x21\xe3\x3c\xce\xe3\x88\xe4\x48\x16\x31\x8c\x4c\x52\x3c\x8d\x93\xb8\x4a\x21\x55\x65\x70\x15\xd7\x70\x9a\xc5\x3d\x7f\x4d\xbd\x28\x1f\x72\x33\x1f\xcf\xd0\x24\x7f\xf9\xbc\xce\xdd\xdd\x93\xb7\x97\x3f\x9b\x0f\xb9\x92\x8f\x7f\xb5\xbf\x3e\xca\x87\x14\x73\x93\x65\xcc\x18\xa6\xe8\x6a\xcf\x18\xa8\xd9\xb9\xd8\x49\xd6\xd5\xa1\xe4\x0c\x2c\xd8\xb0\x6a\xf5\x55\xcb\xa2\xd5\xb8\x68\x95\x12\x80\x43\x5a\xa6\x68\xae\xbb\x25\x18\x03\x0b\xde\xa9\x4b\xea\xba\x19\x1b\xa6\x3b\x4c\xae\xd6\x66\x57\x42\x8a\x94\xcb\x33\x81\xb3\xd6\xeb\xb5\x20\xfd\x0a\xf9\x90\x47\x0f\xed\xfd\x89\xe7\xe7\x09\xc2\xe7\xad\xec\x0c\xf5\xd7\x3f\x29\x1f\x21\xbc\x57\x5f\xdd\x89\xdf\xf7\xd7\xab\x09\x8c\x33\x6d\xa9\x63\x88\x93\xb6\x88\xeb\x66\x4a\x29\xe5\x80\x54\x07\x09\x67\x56\x76\x52\x05\xb1\xbd\x34\x48\x2e\x6d\xe3\x05\x79\x4d\x73\xca\x66\x94\x1a\x10\x16\x0b\x59\x40\x64\x6b\x64\xaa\xc1\x48\x3d\xcd\x34\x52\xf2\x52\x10\x3a\xaa\xcd\x8c\x93\x9b\x65\x26\x23\x7d\xf4\x59\x83\x40\x06\x88\x03\xaa\x0c\x65\x19\x07\x94\x0c\x58\x88\x2b\x24\x41\xe1\x0a\x64\x09\x95\x83\x0a\x2f\x2b\x2c\xc1\x91\x84\xc6\x6b\x34\x24\x65\x95\xe1\x91\x02\x49\x95\xe3\x34\x19\x47\x0a\xad\x78\x75\x27\xe4\x73\x95\x2b\x37\xc3\x6a\x96\x25\x98\xcb\x05\x93\xbb\xbb\x5e\xe5\x0a\xc3\x1d\xb2\x20\xd1\x2b\x57\xae\x9c\xaa\xec\x5d\x11\xf6\x8d\x5f\xa8\x5c\x49\xe6\x16\x06\xe1\x14\xd2\x85\x14\xd5\x5a\xaf\x1c\x5c\x4d\x26\x5a\x92\xc6\x38\x32\x6d\x50\xf2\xa6\x68\xa5\x07\x89\x59\xcc\x68\xf5\x8a\x93\xb5\xe2\xd0\x94\x5e\xd2\xc0\x64\xed\x8c\xd6\x4c\x51\xa5\x7b\x39\x4a\xa2\x92\x86\x62\x6b\x14\x23\x09\x43\x31\x5d\x6f\x56\xec\x29\xa7\x75\x93\x9f\xab\x72\xe5\xd9\xca\x91\x67\xab\x25\x0a\xf8\x98\x11\x5e\x58\xb9\xf2\x91\xd9\xdf\xf7\xa8\x5c\x89\x5a\x39\x22\xbc\xa8\x72\x85\x3d\xea\x80\x0b\xaf\x31\xbb\xba\x67\x4a\x9e\xa9\x72\x7d\xad\xaf\x51\x4a\x51\x0a\x6a\xa6\xba\x32\x6a\x99\x98\xd5\x8e\xf5\x50\x9a\x1b\xe5\xd7\xa6\x30\xd7\x66\xad\x76\x23\x67\x77\x0a\x08\x65\x47\x1d\x7e\x66\xcb\x5d\x0e\x8d\x32\xa8\x5d\x47\x62\x59\xa0\x3b\x85\x4c\xac\x3c\x14\xb2\xd5\xda\xd8\x48\xb2\xb9\x78\x06\x08\x1f\x9c\x89\x46\x04\x2b\x43\x44\xd3\x40\x85\x38\x81\xd3\x50\x25\x81\x86\xcb\x3c\x84\xaa\xa6\xe2\x1a\x03\x48\xa4\x91\x2c\x92\x29\x8e\x91\x09\x5c\xc6\x29\x4a\x21\x78\x40\x72\x24\x83\x23\x8a\xa6\x55\xd6\xf3\xbc\xd4\x73\x9e\xf7\x66\x80\xcc\xb2\x80\xbd\xfc\x56\x91\xdd\x5d\xd7\xf3\xd2\x38\x7f\x74\x9e\x7d\x64\xcf\x7b\xe5\x6c\x57\xef\x7a\xb0\x5e\xe5\x9a\xe7\xed\x76\xb5\x4d\xd9\x9a\x54\x86\xda\x58\x67\x0c\xab\x12\x33\x13\xda\x62\x9a\x9b\xd4\x16\x60\xa2\xad\x0d\x0a\x37\xe9\x79\xbb\xc6\x6e\x88\xee\xa4\xc2\xcd\xcc\x74\x8c\xe9\xcc\x07\x14\x31\xca\x27\xda\xa5\x55\xcb\xac\xb0\x04\x9b\x68\x49\x15\xc4\xe2\x59\xdc\x41\xed\x65\x03\x8d\xc6\xb9\xcf\xe5\x79\x9f\xf5\x7c\xcf\x5a\x7b\x9e\x8a\x95\xba\x2f\xf4\xbc\x1f\x99\x17\x78\x0f\xcf\x1b\xd5\xf3\x09\x2f\xf2\xbc\xf4\xea\x26\xa2\x6b\x9e\x17\xa4\x33\xdc\x68\x4e\x8f\xa8\x0e\x9d\x5d\xcc\xe0\x5b\x7c\x2e\x4c\xd9\xd9\xa6\x37\x96\x9d\xd9\x94\xeb\xa1\x52\xbe\x0c\x8d\x31\xe2\x9c\x76\x6e\x14\xcf\x43\x71\xb9\x30\x18\xb3\x5c\xea\x6e\x06\xc6\x48\x49\xc1\x64\x8c\x47\x2b\xa3\x96\x24\x17\x7c\xa2\x54\xe8\x18\x16\x4e\x9a\x74\xe2\x83\x63\x5e\x45\x53\x39\x8e\x60\x90\x4a\x73\xac\x42\x23\x95\xe3\x54\x04\x71\x24\xe3\x38\x47\x70\x0a\xd4\x48\x4e\xc1\x59\x1a\x47\x2c\x4b\xe1\x08\xa7\x55\x44\x2a\x80\x25\x58\x06\xf1\x10\x21\x0e\x21\xcf\xf3\xd2\xcf\x79\xde\x9b\xaf\x12\x71\x37\x9e\x5e\xf1\xbc\xde\x5d\xcf\xf3\xd2\xf8\x51\x66\x22\xb2\xe7\xbd\x72\x2e\x99\x77\x45\x78\xa5\xcf\x25\xcf\x5b\x9a\x54\x87\x6a\x15\x6d\x8a\x4a\x3b\xd5\xae\x70\x6a\xab\x36\x4e\x3a\xa9\x3a\xe5\x64\xb2\x89\x4d\x5e\x85\x95\x71\x8d\x89\xc5\x0b\x6c\xcc\x29\xbe\xe5\xdb\x66\x73\x24\x27\x85\x8e\xad\xd4\xba\xd9\xd8\x88\x49\xa9\xf1\x56\xaa\x09\x93\x6f\x6a\xd7\x6e\x27\x04\x3b\x43\xe2\xed\xc5\x28\x5b\xf8\x5c\x9e\xf7\x59\xcf\xf7\xac\xb5\xe7\xf8\xce\x60\xf5\xca\x6a\xed\x0f\x5c\x41\x7b\x0f\xcf\x1b\xd5\xf3\x09\x2f\xf2\xbc\x51\xcf\x09\xf5\x3d\xef\x5b\x6f\x9c\xed\x34\x33\xf6\x28\x93\x1a\xb6\x46\xf1\x4c\xab\xd9\x13\xd8\x5a\x73\x51\xa8\x6d\x04\x5b\x9f\xb6\x47\xb4\x84\x96\xcb\x4d\x2c\x6e\x35\x8a\x1b\x63\x9e\xca\x82\xd5\x2a\xc5\x66\xa4\x76\xa2\x62\xc6\x86\x1d\x8d\xa8\xb5\xd2\x03\x8e\x6c\x17\x52\x83\x41\x41\xe4\xf9\x94\x65\x6e\x5e\xb3\x4f\xf3\xb7\xdf\xbe\x7f\xff\xed\xfb\x77\x2c\x09\x1d\x88\x69\xa6\x85\x95\xe0\x04\xfd\xc0\xc6\x68\xd3\x5f\x42\x63\x81\xfa\x5b\x67\x8c\xfe\xc2\x1a\x9b\x19\xfa\x81\x35\x04\xb1\x20\x61\x49\xa1\x21\xfc\x85\xd5\x95\x21\x9a\xc0\x1f\xd8\x6c\x21\x1b\xba\xf2\x17\x56\x5e\x4d\x91\xf5\x03\xdb\x42\xfb\xed\xc4\xa1\x07\x60\x1d\x45\xd1\xeb\x59\x5f\x9f\x0e\x90\xed\xf4\x0d\xb8\xfd\x83\xd4\x01\xb2\xb6\x2c\xe1\x5f\x2f\x93\x66\x6a\x1a\xb2\xec\x87\x29\xda\x41\xf3\x80\x40\x45\x31\x17\x53\xc7\xee\xdb\xfa\x60\x8a\x2c\xfb\xec\x87\xfe\x6c\x8c\x36\x3b\x24\x89\x72\xa9\xde\xa8\x09\xd9\x52\xe3\x06\x12\xa1\xd0\x90\x6a\x3e\x4d\xe5\x52\xa1\x7b\x06\xf6\x37\x0c\xc3\x30\x21\x99\x3c\x02\x19\x8e\x1a\xab\xd4\xb2\x45\xa1\xd6\xc5\xf2\x52\x17\xfb\xdd\xbb\xf3\x6d\xd7\xf4\x48\x38\x3e\x3b\xb6\x8d\x9c\xbe\xed\x40\xc7\x3e\xfe\xfc\x2a\x26\x0e\x10\x43\xe9\x0f\x20\x3c\x25\x5d\x57\xcf\xa8\x1d\x98\xd6\xac\x3f\xd1\x07\x16\xf4\x06\xf7\xc0\xf7\x17\x51\x1d\x80\x1a\x46\x79\x18\xe2\x9b\xd4\xef\xe2\x13\x97\x6d\x3b\xf0\xd5\xfb\x4f\x5f\x31\x55\xe4\x7f\x74\x36\xb3\xdd\x47\xdd\xb6\x17\xc8\xea\xbf\x84\xbb\x53\xb4\x61\xcc\x45\x22\x0c\x6b\x96\xb2\xd5\xa6\x84\xfd\x7e\x68\xfe\x0d\x3b\xb4\xdf\x7d\xf6\x1e\x78\x50\x34\xaf\xe9\xd6\x87\x19\x7f\xa8\x53\xcd\x19\xf2\x94\xa1\x3f\x83\x96\xa3\x2b\xfa\x0c\x4e\x8f\x38\x09\xbf\xfd\x62\xce\xc2\x91\x5c\xe3\xf4\x0a\x59\x77\x73\x7e\x14\x6e\x87\xf3\x7e\xa9\xc1\x8b\xb9\xbf\x84\xe6\x1a\xff\x57\x49\xbb\x29\x81\xe0\xf8\x14\xf8\xfe\x22\xfe\x02\x50\xc3\xd8\x09\x43\x7c\x4a\xfd\x18\x6d\xce\xc8\xf7\xc6\x43\xff\x3f\x2f\x22\xd6\x03\x16\x46\xe3\x11\x9a\x53\xd2\xdc\x1b\x21\xd2\xf5\x1c\x86\xbc\x71\x7d\xc9\x8e\xb2\x6c\x29\x29\x75\x6e\x10\x95\xa8\x49\x42\x43\xf2\x9a\x9e\x42\xc1\xca\xa5\xa0\xab\x69\xd6\xb3\xa5\x34\x26\x3b\x16\x42\xc7\xbe\xeb\x32\x35\x9e\x07\x7b\x9e\x1e\x0f\xce\x7d\x14\x5d\xf0\x9a\xf2\xa6\xef\x8f\xeb\x91\xc9\x39\x80\x38\xa6\xe4\x64\x06\x7d\x4a\x8f\xd7\x78\x1f\x50\xf4\x6d\x34\x5f\xa0\xa9\x72\x2e\x30\x79\xd3\x1f\x42\x7b\xf8\x0c\x65\xdb\xe7\xef\x23\xeb\xd8\x8e\xb7\x4f\x85\x51\xe3\x05\x89\xcf\xd0\xe3\x41\xb8\x8f\x22\xaf\xed\x5e\x3c\xdf\x30\x38\x9b\x19\xba\xe2\x39\x5b\xd3\x52\x2f\x0c\x82\x7d\xb4\xd5\x0d\xf7\x7e\x04\x4a\xfd\x31\xd8\x23\x38\x00\xee\x98\x6c\xa4\x69\x48\x09\xaa\xda\xf9\x98\xa0\xab\xdf\xb0\x2f\xee\xc3\x5f\x2e\x11\xab\xab\x2f\x22\x53\x57\xef\x26\x70\xa7\x7a\x5b\xf2\x22\x10\x6d\xce\xfa\xb3\x57\xd1\xed\xc3\x3a\x26\xfd\x42\x20\x10\x89\x93\x70\x06\x9c\xf5\xeb\x18\xf0\x61\x5d\xd0\xe9\x88\x2c\x1c\x43\x08\x63\xc2\x9c\x6d\xb5\x72\x68\x46\xe2\xc1\x27\xfe\x00\x23\xaa\xf0\xaf\x0b\xda\xf6\xad\xdd\x75\xd5\xcf\xcb\xfa\x14\xdc\x31\xc9\xde\xef\x01\x1a\xc3\x29\x3a\x96\xeb\xab\xc8\x3a\x83\x79\x9f\x7b\x0b\x23\xd0\xf1\xba\xc4\x79\xa6\x5b\x0f\x30\xa2\xab\xe4\x2d\xf5\x73\x2c\x75\x8b\x44\x86\x36\x7a\x7a\xfc\x0c\x03\x16\xa0\x5c\x45\x01\x3a\x8f\xdb\xde\x24\xd0\x8d\x8e\x5e\x43\x9e\x0b\xea\x2e\xe2\xdc\x96\xd7\x48\x73\x69\x47\xd6\xcb\xc4\x17\x80\x77\x8b\xc8\x40\xf3\x7b\x28\x7d\x8d\x1c\x4f\xa0\xdd\x4b\xe5\x4d\x69\xbe\x86\xb6\xbb\x68\xba\x4e\xcb\x8e\x62\xc3\x34\xc7\x8b\xd9\x73\x14\x9d\xc2\xba\xbb\x47\xbd\x78\xf7\x02\x7d\x33\xa8\x5b\x7d\x47\x9f\xa0\x97\x50\x18\x84\x76\x9f\xdd\xfa\x04\x7e\xc3\x82\x24\x7f\xc3\x7c\x17\xaf\x18\xa6\x8d\xd4\x3e\x3c\xcf\xb6\x79\x68\x5f\xe0\xb7\x7d\x38\xb7\x28\x7e\x30\x3a\xda\x42\x7d\x99\x74\x1f\x10\xec\x4d\xb9\xe9\x53\x15\xad\xfb\x81\x90\xc3\xee\x9b\xd3\x3e\x54\x55\x0b\xd9\xf6\xb3\x02\xbd\x89\xe0\x64\x9e\xe6\xdf\x0e\xcc\x8c\xbc\x86\x0f\xd0\xfe\xbc\x1e\x5c\x83\x7d\x9b\xe2\x10\x2b\x3b\x05\xe8\x47\xe1\x5b\x78\xce\x66\x16\x7d\x0e\x7e\x15\xea\xcd\xb0\x7f\xdb\xe8\x06\xa1\x7e\x0c\xb5\x05\xb9\x57\xa2\x17\x51\x1b\x06\xfa\x66\xf8\x76\xaf\x26\x1f\x01\x7f\xb5\x32\x9c\x80\x8e\x12\x6f\x5e\x06\x37\x99\x99\xd6\xd6\xf1\x2d\x91\x65\xeb\xe6\xf4\xf5\x82\x0e\x62\xb8\x4d\x7e\xe0\x81\xfb\x99\xf1\x5d\x4f\xc4\x4c\xc5\x7d\xf2\x3f\xc2\x71\x93\x93\xa3\xb6\xf7\x33\x31\xb3\xd0\x52\x37\x17\xf6\x87\x70\x13\x86\xec\x26\x5b\x61\x0f\xdd\xcf\xdf\x2e\x89\xf2\x6e\x3c\xed\x10\xdc\xe4\xe3\x62\xb6\xeb\x14\xf4\x7e\xbc\x7d\x17\xd3\x0e\x42\x0f\x9d\x00\x3f\x6a\xe0\xa7\x40\x4f\xa7\x50\x2f\xb2\xf0\x6b\x28\xee\xe1\xe1\xc6\xbc\xee\x2a\xb2\xd7\x0d\x5f\xe7\x80\xef\xa2\xfd\xf6\x20\x76\x3c\xd9\x7e\x0f\xb5\x39\x87\x1f\x79\xaa\xef\xe7\xf2\xb7\x13\xcb\xc5\x46\x9f\x0e\xbc\x18\x38\xb2\x80\xc3\xc1\x6d\xa9\xf3\x97\x28\x4e\xc3\x70\xb7\x8d\xdb\xe4\x0a\x61\x6e\x5d\xc0\xc4\x54\x75\x4d\x47\xea\xb3\xb9\xdf\xeb\x60\x2f\x11\x1a\xd6\xf6\x0a\xc5\x36\x32\x8c\x97\xd0\xe8\x01\xba\x44\x95\x77\xf7\x6a\xa7\x6e\x9b\xbc\xb2\x57\x4f\xe0\x5d\xa3\xeb\x62\xbf\xee\x0a\x1c\x5e\xb0\xe2\x71\x0e\x6a\x4b\xd1\x59\x59\x47\xd8\xaa\xc7\x19\x59\xee\x64\x66\x1f\xd0\xee\x32\xed\x7d\xd9\x34\xc7\x91\xe9\xbb\x02\xf3\x66\xa8\xfc\xfb\xef\x2a\x72\xa0\x6e\xd8\xd8\xf7\xff\xf9\x1f\xec\xab\x6d\x1a\xea\xd1\x9a\xfd\xd7\x1f\x3f\x1c\xb4\x76\xfe\xf8\xe3\x1b\x76\xb9\xa1\x62\xaa\xf7\x35\xf4\xd6\xa4\x2e\x37\x95\xcd\xc5\x60\xe8\xdc\x85\xfe\xa4\xe9\x75\x02\x4e\x9a\x06\x48\xf8\x03\x6b\x67\xa4\x9a\xe4\x39\x5b\xec\x6f\x8c\x24\xef\x2e\x77\xd1\xd5\xbe\x76\xb4\xfe\x99\xca\x7f\x4c\xd1\x8b\x8f\x16\x4b\x95\x6b\x52\x36\x5d\xda\x2f\x34\x63\x35\x29\x25\xd5\xa4\x52\x42\xaa\x07\x56\x07\xdd\xbb\xe5\x12\xd6\xac\x24\xb7\x2a\x53\x93\xea\x8d\x5a\x36\xd1\xd8\xfe\x94\x94\x0a\x52\x43\xc2\x12\x42\x3d\x21\x24\xa5\x2b\xab\xf5\xdb\xf9\xf7\xe9\xd7\x7e\x20\x25\xf9\x3a\x61\x9c\xe2\xb9\xb1\x14\x7f\x89\x92\x53\xf9\x04\xd3\xa7\xa1\xc2\xf2\xcd\xf9\x46\xdd\xc2\x45\x49\xf8\x29\x9d\x9f\x2e\x87\x63\x3a\xc2\xa4\xb0\xcb\x96\x5d\x57\x98\xc7\x24\x70\x9e\x5c\xfd\x89\x62\xb8\x40\xcc\xa9\x2c\x42\xd2\xc1\xaf\x55\x8a\x60\xaa\xef\x33\x08\xe4\xb2\x6a\x9c\xe5\x52\x6f\x6a\xc7\xf7\xef\x18\x54\x55\xa4\x62\x13\x38\x5d\x40\xc3\xd8\x9c\x10\x1a\x1a\x22\x6e\xa9\xdc\xc9\x7b\xb2\x58\x23\x15\x5b\x42\x4b\x19\x42\xeb\x77\x86\xff\xc3\x2f\x17\xdd\xb6\xd1\xd0\xc1\x58\xc3\xdb\xfd\x15\x8a\xec\x28\x90\xde\x82\xb1\xcd\x85\xa5\x44\x83\xb4\x1b\x29\x5d\x8a\xbd\x24\xdd\xc5\xe7\x7d\x9d\xa8\x98\xb6\x33\xb0\x50\xbd\x5a\xc0\x54\xe8\xc0\xad\xad\x61\xea\x62\x32\xc3\x14\x73\x32\x33\x90\x83\xdc\xce\xfc\xff\x02\x00\x00\xff\xff\xa2\x47\xaf\x32\xa6\x6e\x01\x00") func paths_strict_sendHorizonSqlBytes() ([]byte, error) { return bindataRead( @@ -526,7 +526,7 @@ func paths_strict_sendHorizonSql() (*asset, error) { } info := bindataFileInfo{name: "paths_strict_send-horizon.sql", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} - a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x9e, 0x74, 0x9c, 0x8e, 0x42, 0x41, 0x63, 0xf5, 0x2c, 0x29, 0x9f, 0xc, 0x88, 0x53, 0x6c, 0x7e, 0x3, 0x8, 0x88, 0xaa, 0xa1, 0x8e, 0x9, 0x79, 0xfd, 0xa7, 0x98, 0x43, 0xc2, 0xe9, 0x39, 0xf3}} + a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xcb, 0x25, 0xf, 0x98, 0xa9, 0xd, 0x4e, 0x7a, 0x28, 0x91, 0xb5, 0x90, 0x6d, 0x5f, 0x44, 0x45, 0x2, 0x39, 0x35, 0x37, 0x84, 0x1f, 0x66, 0xfa, 0xc9, 0xc6, 0x96, 0x3b, 0xc4, 0xb4, 0x3b, 0xac}} return a, nil } @@ -649,13 +649,11 @@ var _bindata = map[string]func() (*asset, error){ // directory embedded in the file by go-bindata. // For example if you run go-bindata on data/... and data contains the // following hierarchy: -// -// data/ -// foo.txt -// img/ -// a.png -// b.png -// +// data/ +// foo.txt +// img/ +// a.png +// b.png // then AssetDir("data") would return []string{"foo.txt", "img"}, // AssetDir("data/img") would return []string{"a.png", "b.png"}, // AssetDir("foo.txt") and AssetDir("notexist") would return an error, and diff --git a/services/horizon/internal/test/scenarios/failed_transactions-horizon.sql b/services/horizon/internal/test/scenarios/failed_transactions-horizon.sql index 3b3c3a1ea4..3dac331789 100644 --- a/services/horizon/internal/test/scenarios/failed_transactions-horizon.sql +++ b/services/horizon/internal/test/scenarios/failed_transactions-horizon.sql @@ -351,6 +351,7 @@ ALTER SEQUENCE history_operation_participants_id_seq OWNED BY history_operation_ -- -- Name: history_operations; Type: TABLE; Schema: public; Owner: - -- +-- added is_payment=false default to schema, rather than change insert lines CREATE TABLE history_operations ( id bigint NOT NULL, @@ -358,7 +359,8 @@ CREATE TABLE history_operations ( application_order integer NOT NULL, type integer NOT NULL, details jsonb, - source_account character varying(64) DEFAULT ''::character varying NOT NULL + source_account character varying(64) DEFAULT ''::character varying NOT NULL, + is_payment boolean default false ); diff --git a/services/horizon/internal/test/scenarios/ingest_asset_stats-horizon.sql b/services/horizon/internal/test/scenarios/ingest_asset_stats-horizon.sql index d93b7b4632..55e146180e 100644 --- a/services/horizon/internal/test/scenarios/ingest_asset_stats-horizon.sql +++ b/services/horizon/internal/test/scenarios/ingest_asset_stats-horizon.sql @@ -350,6 +350,7 @@ ALTER SEQUENCE history_operation_participants_id_seq OWNED BY history_operation_ -- -- Name: history_operations; Type: TABLE; Schema: public; Owner: - -- +-- added is_payment=false default to schema, rather than change insert lines CREATE TABLE history_operations ( id bigint NOT NULL, @@ -357,10 +358,10 @@ CREATE TABLE history_operations ( application_order integer NOT NULL, type integer NOT NULL, details jsonb, - source_account character varying(64) DEFAULT ''::character varying NOT NULL + source_account character varying(64) DEFAULT ''::character varying NOT NULL, + is_payment boolean default false ); - -- -- Name: history_trades; Type: TABLE; Schema: public; Owner: - -- diff --git a/services/horizon/internal/test/scenarios/kahuna-horizon.sql b/services/horizon/internal/test/scenarios/kahuna-horizon.sql index c32bb7f6c8..7a8d51858f 100644 --- a/services/horizon/internal/test/scenarios/kahuna-horizon.sql +++ b/services/horizon/internal/test/scenarios/kahuna-horizon.sql @@ -489,6 +489,7 @@ ALTER SEQUENCE history_operation_participants_id_seq OWNED BY history_operation_ -- -- Name: history_operations; Type: TABLE; Schema: public; Owner: - -- +-- added is_payment=false default to schema, rather than change insert lines CREATE TABLE history_operations ( id bigint NOT NULL, @@ -496,7 +497,8 @@ CREATE TABLE history_operations ( application_order integer NOT NULL, type integer NOT NULL, details jsonb, - source_account character varying(64) DEFAULT ''::character varying NOT NULL + source_account character varying(64) DEFAULT ''::character varying NOT NULL, + is_payment boolean default false ); diff --git a/services/horizon/internal/test/scenarios/offer_ids-horizon.sql b/services/horizon/internal/test/scenarios/offer_ids-horizon.sql index 48db72508a..81864ba4ba 100644 --- a/services/horizon/internal/test/scenarios/offer_ids-horizon.sql +++ b/services/horizon/internal/test/scenarios/offer_ids-horizon.sql @@ -350,6 +350,7 @@ ALTER SEQUENCE history_operation_participants_id_seq OWNED BY history_operation_ -- -- Name: history_operations; Type: TABLE; Schema: public; Owner: - -- +-- added is_payment=false default to schema, rather than change insert lines CREATE TABLE history_operations ( id bigint NOT NULL, @@ -358,6 +359,7 @@ CREATE TABLE history_operations ( type integer NOT NULL, details jsonb, source_account character varying(64) DEFAULT ''::character varying NOT NULL + is_payment boolean default false ); diff --git a/services/horizon/internal/test/scenarios/operation_fee_stats_1-horizon.sql b/services/horizon/internal/test/scenarios/operation_fee_stats_1-horizon.sql index dd4af318c2..076603efd1 100644 --- a/services/horizon/internal/test/scenarios/operation_fee_stats_1-horizon.sql +++ b/services/horizon/internal/test/scenarios/operation_fee_stats_1-horizon.sql @@ -350,6 +350,7 @@ ALTER SEQUENCE history_operation_participants_id_seq OWNED BY history_operation_ -- -- Name: history_operations; Type: TABLE; Schema: public; Owner: - -- +-- added is_payment=false default to schema, rather than change insert lines CREATE TABLE history_operations ( id bigint NOT NULL, @@ -357,7 +358,8 @@ CREATE TABLE history_operations ( application_order integer NOT NULL, type integer NOT NULL, details jsonb, - source_account character varying(64) DEFAULT ''::character varying NOT NULL + source_account character varying(64) DEFAULT ''::character varying NOT NULL, + is_payment boolean default false ); diff --git a/services/horizon/internal/test/scenarios/operation_fee_stats_2-horizon.sql b/services/horizon/internal/test/scenarios/operation_fee_stats_2-horizon.sql index b29163aefd..987dfaa18f 100644 --- a/services/horizon/internal/test/scenarios/operation_fee_stats_2-horizon.sql +++ b/services/horizon/internal/test/scenarios/operation_fee_stats_2-horizon.sql @@ -350,6 +350,7 @@ ALTER SEQUENCE history_operation_participants_id_seq OWNED BY history_operation_ -- -- Name: history_operations; Type: TABLE; Schema: public; Owner: - -- +-- added is_payment=false default to schema, rather than change insert lines CREATE TABLE history_operations ( id bigint NOT NULL, @@ -357,7 +358,8 @@ CREATE TABLE history_operations ( application_order integer NOT NULL, type integer NOT NULL, details jsonb, - source_account character varying(64) DEFAULT ''::character varying NOT NULL + source_account character varying(64) DEFAULT ''::character varying NOT NULL, + is_payment boolean default false ); diff --git a/services/horizon/internal/test/scenarios/operation_fee_stats_3-horizon.sql b/services/horizon/internal/test/scenarios/operation_fee_stats_3-horizon.sql index 739ecaa543..9546734c1c 100644 --- a/services/horizon/internal/test/scenarios/operation_fee_stats_3-horizon.sql +++ b/services/horizon/internal/test/scenarios/operation_fee_stats_3-horizon.sql @@ -350,6 +350,7 @@ ALTER SEQUENCE history_operation_participants_id_seq OWNED BY history_operation_ -- -- Name: history_operations; Type: TABLE; Schema: public; Owner: - -- +-- added is_payment=false default to schema, rather than change insert lines CREATE TABLE history_operations ( id bigint NOT NULL, @@ -357,7 +358,8 @@ CREATE TABLE history_operations ( application_order integer NOT NULL, type integer NOT NULL, details jsonb, - source_account character varying(64) DEFAULT ''::character varying NOT NULL + source_account character varying(64) DEFAULT ''::character varying NOT NULL, + is_payment boolean default false ); diff --git a/services/horizon/internal/test/scenarios/pathed_payment-horizon.sql b/services/horizon/internal/test/scenarios/pathed_payment-horizon.sql index 1621ca105a..1d0f26ab98 100644 --- a/services/horizon/internal/test/scenarios/pathed_payment-horizon.sql +++ b/services/horizon/internal/test/scenarios/pathed_payment-horizon.sql @@ -351,6 +351,7 @@ ALTER SEQUENCE history_operation_participants_id_seq OWNED BY history_operation_ -- -- Name: history_operations; Type: TABLE; Schema: public; Owner: - -- +-- added is_payment=false default to schema, rather than change insert lines CREATE TABLE history_operations ( id bigint NOT NULL, @@ -358,7 +359,8 @@ CREATE TABLE history_operations ( application_order integer NOT NULL, type integer NOT NULL, details jsonb, - source_account character varying(64) DEFAULT ''::character varying NOT NULL + source_account character varying(64) DEFAULT ''::character varying NOT NULL, + is_payment boolean default false ); diff --git a/services/horizon/internal/test/scenarios/paths_strict_send-horizon.sql b/services/horizon/internal/test/scenarios/paths_strict_send-horizon.sql index 0fc86136d5..313eacfb3d 100644 --- a/services/horizon/internal/test/scenarios/paths_strict_send-horizon.sql +++ b/services/horizon/internal/test/scenarios/paths_strict_send-horizon.sql @@ -373,6 +373,7 @@ ALTER SEQUENCE history_operation_participants_id_seq OWNED BY history_operation_ -- -- Name: history_operations; Type: TABLE; Schema: public; Owner: - -- +-- added is_payment=false default to schema, rather than change insert lines CREATE TABLE history_operations ( id bigint NOT NULL, @@ -380,7 +381,8 @@ CREATE TABLE history_operations ( application_order integer NOT NULL, type integer NOT NULL, details jsonb, - source_account character varying(64) DEFAULT ''::character varying NOT NULL + source_account character varying(64) DEFAULT ''::character varying NOT NULL, + is_payment boolean default false ); diff --git a/services/horizon/internal/txsub/errors.go b/services/horizon/internal/txsub/errors.go index 7821537d7f..160ea7a4a4 100644 --- a/services/horizon/internal/txsub/errors.go +++ b/services/horizon/internal/txsub/errors.go @@ -16,10 +16,7 @@ var ( // ErrBadSequence is a canned error response for transactions whose sequence // number is wrong. - ErrBadSequence = &FailedTransactionError{"AAAAAAAAAAD////7AAAAAA=="} - // ErrNoAccount is returned when the source account for the transaction - // cannot be found in the database - ErrNoAccount = &FailedTransactionError{"AAAAAAAAAAD////4AAAAAA=="} + ErrBadSequence = &FailedTransactionError{"AAAAAAAAAAD////7AAAAAA==", ""} ) // FailedTransactionError represent an error that occurred because @@ -27,6 +24,8 @@ var ( // encoded TransactionResult struct type FailedTransactionError struct { ResultXDR string + // DiagnosticEventsXDR is a base64-encoded []xdr.DiagnosticEvent + DiagnosticEventsXDR string } func (err *FailedTransactionError) Error() string { diff --git a/services/horizon/internal/txsub/helpers_test.go b/services/horizon/internal/txsub/helpers_test.go index 67ecd372c8..0e5a63bca7 100644 --- a/services/horizon/internal/txsub/helpers_test.go +++ b/services/horizon/internal/txsub/helpers_test.go @@ -30,8 +30,8 @@ type mockDBQ struct { mock.Mock } -func (m *mockDBQ) BeginTx(txOpts *sql.TxOptions) error { - args := m.Called(txOpts) +func (m *mockDBQ) BeginTx(ctx context.Context, txOpts *sql.TxOptions) error { + args := m.Called(ctx, txOpts) return args.Error(0) } diff --git a/services/horizon/internal/txsub/main.go b/services/horizon/internal/txsub/main.go index ede2df8dd8..b466fc0055 100644 --- a/services/horizon/internal/txsub/main.go +++ b/services/horizon/internal/txsub/main.go @@ -24,18 +24,18 @@ type Listener chan<- Result type OpenSubmissionList interface { // Add registers the provided listener as interested in being notified when a // result is available for the provided transaction hash. - Add(context.Context, string, Listener) error + Add(string, Listener) // Finish forwards the provided result on to any listeners and cleans up any // resources associated with the transaction that this result is for - Finish(context.Context, string, Result) error + Finish(string, Result) // Clean removes any open submissions over the provided age. - Clean(context.Context, time.Duration) (int, error) + Clean(time.Duration) int // Pending return a list of transaction hashes that have at least one // listener registered to them in this list. - Pending(context.Context) []string + Pending() []string } // Submitter represents the low-level "submit a transaction to stellar-core" diff --git a/services/horizon/internal/txsub/open_submission_list.go b/services/horizon/internal/txsub/open_submission_list.go index 9b64915732..8d781b7bb7 100644 --- a/services/horizon/internal/txsub/open_submission_list.go +++ b/services/horizon/internal/txsub/open_submission_list.go @@ -1,12 +1,10 @@ package txsub import ( - "context" "fmt" "sync" "time" - "github.com/go-errors/errors" "github.com/stellar/go/support/log" ) @@ -33,7 +31,7 @@ type submissionList struct { log *log.Entry } -func (s *submissionList) Add(ctx context.Context, hash string, l Listener) error { +func (s *submissionList) Add(hash string, l Listener) { s.Lock() defer s.Unlock() @@ -41,10 +39,6 @@ func (s *submissionList) Add(ctx context.Context, hash string, l Listener) error panic("Unbuffered listener cannot be added to OpenSubmissionList") } - if len(hash) != 64 { - return errors.New("Unexpected transaction hash length: must be 64 hex characters") - } - os, ok := s.submissions[hash] if !ok { @@ -60,17 +54,15 @@ func (s *submissionList) Add(ctx context.Context, hash string, l Listener) error } os.Listeners = append(os.Listeners, l) - - return nil } -func (s *submissionList) Finish(ctx context.Context, hash string, r Result) error { +func (s *submissionList) Finish(hash string, r Result) { s.Lock() defer s.Unlock() os, ok := s.submissions[hash] if !ok { - return nil + return } s.log.WithFields(log.F{ @@ -85,10 +77,9 @@ func (s *submissionList) Finish(ctx context.Context, hash string, r Result) erro } delete(s.submissions, hash) - return nil } -func (s *submissionList) Clean(ctx context.Context, maxAge time.Duration) (int, error) { +func (s *submissionList) Clean(maxAge time.Duration) int { s.Lock() defer s.Unlock() @@ -107,10 +98,10 @@ func (s *submissionList) Clean(ctx context.Context, maxAge time.Duration) (int, } } - return len(s.submissions), nil + return len(s.submissions) } -func (s *submissionList) Pending(ctx context.Context) []string { +func (s *submissionList) Pending() []string { s.Lock() defer s.Unlock() results := make([]string, 0, len(s.submissions)) diff --git a/services/horizon/internal/txsub/open_submission_list_test.go b/services/horizon/internal/txsub/open_submission_list_test.go index 772aca96fe..d34033a0ac 100644 --- a/services/horizon/internal/txsub/open_submission_list_test.go +++ b/services/horizon/internal/txsub/open_submission_list_test.go @@ -38,7 +38,7 @@ func (suite *SubmissionListTestSuite) SetupTest() { func (suite *SubmissionListTestSuite) TestSubmissionList_Add() { // adds an entry to the submission list when a new hash is used - suite.list.Add(suite.ctx, suite.hashes[0], suite.listeners[0]) + suite.list.Add(suite.hashes[0], suite.listeners[0]) sub := suite.realList.submissions[suite.hashes[0]] assert.Equal(suite.T(), suite.hashes[0], sub.Hash) assert.WithinDuration(suite.T(), sub.SubmittedAt, time.Now(), 1*time.Second) @@ -50,12 +50,12 @@ func (suite *SubmissionListTestSuite) TestSubmissionList_Add() { } func (suite *SubmissionListTestSuite) TestSubmissionList_AddListener() { - // adds an listener to an existing entry when a hash is used with a new listener - suite.list.Add(suite.ctx, suite.hashes[0], suite.listeners[0]) + // adds a listener to an existing entry when a hash is used with a new listener + suite.list.Add(suite.hashes[0], suite.listeners[0]) sub := suite.realList.submissions[suite.hashes[0]] st := sub.SubmittedAt <-time.After(20 * time.Millisecond) - suite.list.Add(suite.ctx, suite.hashes[0], suite.listeners[1]) + suite.list.Add(suite.hashes[0], suite.listeners[1]) // increases the size of the listener assert.Equal(suite.T(), 2, len(sub.Listeners)) @@ -65,20 +65,16 @@ func (suite *SubmissionListTestSuite) TestSubmissionList_AddListener() { // Panics when the listener is not buffered // panics when the listener is not buffered assert.Panics(suite.T(), func() { - suite.list.Add(suite.ctx, suite.hashes[0], make(Listener)) + suite.list.Add(suite.hashes[0], make(Listener)) }) - - // errors when the provided hash is not 64-bytes - err := suite.list.Add(suite.ctx, "123", suite.listeners[0]) - assert.NotNil(suite.T(), err) } func (suite *SubmissionListTestSuite) TestSubmissionList_Finish() { - suite.list.Add(suite.ctx, suite.hashes[0], suite.listeners[0]) - suite.list.Add(suite.ctx, suite.hashes[0], suite.listeners[1]) + suite.list.Add(suite.hashes[0], suite.listeners[0]) + suite.list.Add(suite.hashes[0], suite.listeners[1]) r := Result{Err: errors.New("test error")} - suite.list.Finish(suite.ctx, suite.hashes[0], r) + suite.list.Finish(suite.hashes[0], r) // Wries to every listener r1, ok1 := <-suite.listeners[0] @@ -102,20 +98,15 @@ func (suite *SubmissionListTestSuite) TestSubmissionList_Finish() { _, _ = <-suite.listeners[1] _, more = <-suite.listeners[1] assert.False(suite.T(), more) - - // works when no one is waiting for the result - err := suite.list.Finish(suite.ctx, suite.hashes[0], r) - assert.Nil(suite.T(), err) } func (suite *SubmissionListTestSuite) TestSubmissionList_Clean() { - suite.list.Add(suite.ctx, suite.hashes[0], suite.listeners[0]) + suite.list.Add(suite.hashes[0], suite.listeners[0]) <-time.After(200 * time.Millisecond) - suite.list.Add(suite.ctx, suite.hashes[1], suite.listeners[1]) - left, err := suite.list.Clean(suite.ctx, 200*time.Millisecond) + suite.list.Add(suite.hashes[1], suite.listeners[1]) + left := suite.list.Clean(200 * time.Millisecond) - assert.Nil(suite.T(), err) assert.Equal(suite.T(), 1, left) // removes submissions older than the maxAge provided @@ -139,11 +130,11 @@ func (suite *SubmissionListTestSuite) TestSubmissionList_Clean() { // Tests that Pending works as expected func (suite *SubmissionListTestSuite) TestSubmissionList_Pending() { - assert.Equal(suite.T(), 0, len(suite.list.Pending(suite.ctx))) - suite.list.Add(suite.ctx, suite.hashes[0], suite.listeners[0]) - assert.Equal(suite.T(), 1, len(suite.list.Pending(suite.ctx))) - suite.list.Add(suite.ctx, suite.hashes[1], suite.listeners[1]) - assert.Equal(suite.T(), 2, len(suite.list.Pending(suite.ctx))) + assert.Equal(suite.T(), 0, len(suite.list.Pending())) + suite.list.Add(suite.hashes[0], suite.listeners[0]) + assert.Equal(suite.T(), 1, len(suite.list.Pending())) + suite.list.Add(suite.hashes[1], suite.listeners[1]) + assert.Equal(suite.T(), 2, len(suite.list.Pending())) } func TestSubmissionListTestSuite(t *testing.T) { diff --git a/services/horizon/internal/txsub/results.go b/services/horizon/internal/txsub/results.go index 34dc52a1c8..4adba767bd 100644 --- a/services/horizon/internal/txsub/results.go +++ b/services/horizon/internal/txsub/results.go @@ -2,8 +2,6 @@ package txsub import ( "context" - "database/sql" - "github.com/stellar/go/services/horizon/internal/db2/history" "github.com/stellar/go/support/errors" "github.com/stellar/go/xdr" @@ -49,35 +47,3 @@ func txResultFromHistory(tx history.Transaction) (history.Transaction, error) { return tx, err } - -// checkTxAlreadyExists uses a repeatable read transaction to look up both transaction results -// and sequence numbers. Without the repeatable read transaction it is possible that the two database -// queries execute on different ledgers. In this case, txsub can mistakenly respond with a bad_seq error -// because the first query occurs when the tx is not yet ingested and the second query occurs when the tx -// is ingested. -func checkTxAlreadyExists(ctx context.Context, db HorizonDB, hash, sourceAddress string) (history.Transaction, uint64, error) { - err := db.BeginTx(&sql.TxOptions{ - Isolation: sql.LevelRepeatableRead, - ReadOnly: true, - }) - if err != nil { - return history.Transaction{}, 0, errors.Wrap(err, "cannot start repeatable read tx") - } - defer db.Rollback() - - tx, err := txResultByHash(ctx, db, hash) - if err == ErrNoResults { - var sequenceNumbers map[string]uint64 - sequenceNumbers, err = db.GetSequenceNumbers(ctx, []string{sourceAddress}) - if err != nil { - return tx, 0, errors.Wrapf(err, "cannot fetch sequence number for %v", sourceAddress) - } - - num, ok := sequenceNumbers[sourceAddress] - if !ok { - return tx, 0, ErrNoAccount - } - return tx, num, ErrNoResults - } - return tx, 0, err -} diff --git a/services/horizon/internal/txsub/sequence/account_tx_submission_queue.go b/services/horizon/internal/txsub/sequence/account_tx_submission_queue.go deleted file mode 100644 index 9d92595bac..0000000000 --- a/services/horizon/internal/txsub/sequence/account_tx_submission_queue.go +++ /dev/null @@ -1,132 +0,0 @@ -package sequence - -import ( - "sort" - "time" -) - -// AccountTxSubmissionQueue manages the submission queue for a single source account. The -// transaction system uses Push to enqueue submissions for given sequence -// numbers. -// -// AccountTxSubmissionQueue maintains a priority queue of pending submissions, and when updated -// (via the NotifyLastAccountSequence() method) with the current sequence number of the account -// being managed, queued submissions that can be acted upon will be unblocked. -type AccountTxSubmissionQueue struct { - lastActiveAt time.Time - timeout time.Duration - lastSeenAccountSequence uint64 - transactions []txToSubmit -} - -// txToSubmit represents a transaction being tracked by the queue -type txToSubmit struct { - minAccSeqNum uint64 // minimum account sequence required to send the transaction - maxAccSeqNum uint64 // maximum account sequence required to send the transaction - notifyBackChan chan error // submission notification channel -} - -// NewAccountTxSubmissionQueue creates a new *AccountTxSubmissionQueue -func NewAccountTxSubmissionQueue() *AccountTxSubmissionQueue { - result := &AccountTxSubmissionQueue{ - lastActiveAt: time.Now(), - timeout: 10 * time.Second, - } - return result -} - -// Size returns the count of currently buffered submissions in the queue. -func (q *AccountTxSubmissionQueue) Size() int { - return len(q.transactions) -} - -// Push enqueues the intent to submit a transaction at the provided sequence -// number and returns a channel that will emit when it is safe for the client -// to do so. -// -// Push does not perform any triggering (which -// occurs in NotifyLastAccountSequence(), even if the current sequence number for this queue is -// the same as the provided sequence, to keep internal complexity much lower. -// Given that, the recommended usage pattern is: -// -// 1. Push the submission onto the queue -// 2. Load the current sequence number for the source account from the DB -// 3. Call NotifyLastAccountSequence() with the result from step 2 to trigger the submission if -// possible -func (q *AccountTxSubmissionQueue) Push(sequence uint64, minSeqNum *uint64) <-chan error { - // From CAP 21: If minSeqNum is nil, the txToSubmit is only valid when sourceAccount's sequence number is seqNum - 1. - // Otherwise, valid when sourceAccount's sequence number n satisfies minSeqNum <= n < txToSubmit.seqNum. - effectiveMinSeqNum := sequence - 1 - if minSeqNum != nil { - effectiveMinSeqNum = *minSeqNum - } - ch := make(chan error, 1) - q.transactions = append(q.transactions, txToSubmit{ - minAccSeqNum: effectiveMinSeqNum, - maxAccSeqNum: sequence - 1, - notifyBackChan: ch, - }) - return ch -} - -// NotifyLastAccountSequence notifies the queue that the provided sequence number is the latest -// seen value for the account that this queue manages submissions for. -// -// This function is monotonic... calling it with a sequence number lower than -// the latest seen sequence number is a noop. -func (q *AccountTxSubmissionQueue) NotifyLastAccountSequence(sequence uint64) { - if q.lastSeenAccountSequence < sequence { - q.lastSeenAccountSequence = sequence - } - - queueWasChanged := false - - txsToSubmit := make([]txToSubmit, 0, len(q.transactions)) - // Extract transactions ready to submit and notify those which are un-submittable. - for i := 0; i < len(q.transactions); { - candidate := q.transactions[i] - removeCandidateFromQueue := false - if q.lastSeenAccountSequence > candidate.maxAccSeqNum { - // this transaction can never be submitted because account sequence numbers only grow - candidate.notifyBackChan <- ErrBadSequence - close(candidate.notifyBackChan) - removeCandidateFromQueue = true - } else if q.lastSeenAccountSequence >= candidate.minAccSeqNum { - txsToSubmit = append(txsToSubmit, candidate) - removeCandidateFromQueue = true - } - if removeCandidateFromQueue { - q.transactions = append(q.transactions[:i], q.transactions[i+1:]...) - queueWasChanged = true - } else { - // only increment the index if there was no removal - i++ - } - } - - // To maximize successful submission opportunity, submit transactions by the account sequence - // which would result from a successful submission (i.e. maxAccSeqNum+1) - sort.Slice(txsToSubmit, func(i, j int) bool { - return txsToSubmit[i].maxAccSeqNum < txsToSubmit[j].maxAccSeqNum - }) - for _, tx := range txsToSubmit { - tx.notifyBackChan <- nil - close(tx.notifyBackChan) - } - - // if we modified the queue, bump the timeout for this queue - if queueWasChanged { - q.lastActiveAt = time.Now() - return - } - - // if the queue wasn't changed, see if it is too old, clear - // it and make room for other submissions - if time.Since(q.lastActiveAt) > q.timeout { - for _, tx := range q.transactions { - tx.notifyBackChan <- ErrBadSequence - close(tx.notifyBackChan) - } - q.transactions = nil - } -} diff --git a/services/horizon/internal/txsub/sequence/account_tx_submission_queue_test.go b/services/horizon/internal/txsub/sequence/account_tx_submission_queue_test.go deleted file mode 100644 index 0b4497f2fd..0000000000 --- a/services/horizon/internal/txsub/sequence/account_tx_submission_queue_test.go +++ /dev/null @@ -1,68 +0,0 @@ -//lint:file-ignore U1001 Ignore all unused code, staticcheck doesn't understand testify/suite - -package sequence - -import ( - "context" - "testing" - "time" - - "github.com/stellar/go/services/horizon/internal/test" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/suite" -) - -type QueueTestSuite struct { - suite.Suite - ctx context.Context - queue *AccountTxSubmissionQueue -} - -func (suite *QueueTestSuite) SetupTest() { - suite.ctx = test.Context() - suite.queue = NewAccountTxSubmissionQueue() -} - -// Tests the NotifyLastAccountSequence method -func (suite *QueueTestSuite) TestQueue_NotifyLastAccountSequence() { - // NotifyLastAccountSequence removes sequences that are submittable or in the past - lowMin := uint64(1) - results := []<-chan error{ - suite.queue.Push(1, nil), - suite.queue.Push(2, nil), - suite.queue.Push(3, nil), - suite.queue.Push(4, nil), - suite.queue.Push(4, &lowMin), - } - - suite.queue.NotifyLastAccountSequence(2) - - // the update above signifies that 2 is the accounts current sequence, - // meaning that 3 is submittable, and so only 4 (Min/maxAccSeqNum=3) should remain - assert.Equal(suite.T(), 1, suite.queue.Size()) - entry := suite.queue.transactions[0] - assert.Equal(suite.T(), uint64(3), entry.minAccSeqNum) - assert.Equal(suite.T(), uint64(3), entry.maxAccSeqNum) - - suite.queue.NotifyLastAccountSequence(4) - assert.Equal(suite.T(), 0, suite.queue.Size()) - - assert.Equal(suite.T(), ErrBadSequence, <-results[0]) - assert.Equal(suite.T(), ErrBadSequence, <-results[1]) - assert.Equal(suite.T(), nil, <-results[2]) - assert.Equal(suite.T(), ErrBadSequence, <-results[3]) - assert.Equal(suite.T(), nil, <-results[4]) - - // NotifyLastAccountSequence clears the queue if the head has not been released within the time limit - suite.queue.timeout = 1 * time.Millisecond - result := suite.queue.Push(2, nil) - <-time.After(10 * time.Millisecond) - suite.queue.NotifyLastAccountSequence(0) - - assert.Equal(suite.T(), 0, suite.queue.Size()) - assert.Equal(suite.T(), ErrBadSequence, <-result) -} - -func TestQueueTestSuite(t *testing.T) { - suite.Run(t, new(QueueTestSuite)) -} diff --git a/services/horizon/internal/txsub/sequence/doc.go b/services/horizon/internal/txsub/sequence/doc.go deleted file mode 100644 index 805e571090..0000000000 --- a/services/horizon/internal/txsub/sequence/doc.go +++ /dev/null @@ -1,3 +0,0 @@ -// Package sequence providers helpers to manage sequence numbers on behalf of horizon clients. -// See Manager for more details on the api. -package sequence diff --git a/services/horizon/internal/txsub/sequence/errors.go b/services/horizon/internal/txsub/sequence/errors.go deleted file mode 100644 index 2a7e1258e5..0000000000 --- a/services/horizon/internal/txsub/sequence/errors.go +++ /dev/null @@ -1,10 +0,0 @@ -package sequence - -import ( - "errors" -) - -var ( - ErrNoMoreRoom = errors.New("queue full") - ErrBadSequence = errors.New("bad sequence") -) diff --git a/services/horizon/internal/txsub/sequence/manager.go b/services/horizon/internal/txsub/sequence/manager.go deleted file mode 100644 index 1a776f44d8..0000000000 --- a/services/horizon/internal/txsub/sequence/manager.go +++ /dev/null @@ -1,115 +0,0 @@ -package sequence - -import ( - "fmt" - "strings" - "sync" -) - -// Manager provides a system for tracking the transaction submission queue for -// a set of addresses. Requests to submit at a certain sequence number are -// registered using the Push() method, and as the system is updated with -// account sequence information (through the Update() method) requests are -// notified that they can safely submit to stellar-core. -type Manager struct { - mutex sync.Mutex - MaxSize int - queues map[string]*AccountTxSubmissionQueue -} - -// NewManager returns a new manager -func NewManager() *Manager { - return &Manager{ - MaxSize: 1024, //TODO: make MaxSize configurable - queues: map[string]*AccountTxSubmissionQueue{}, - } -} - -func (m *Manager) String() string { - m.mutex.Lock() - defer m.mutex.Unlock() - var addys []string - - for addy, q := range m.queues { - addys = append(addys, fmt.Sprintf("%5s:%d", addy, q.lastSeenAccountSequence)) - } - - return "[ " + strings.Join(addys, ",") + " ]" -} - -// Size returns the count of submissions buffered within -// this manager. -func (m *Manager) Size() int { - m.mutex.Lock() - defer m.mutex.Unlock() - return m.size() -} - -func (m *Manager) Addresses() []string { - m.mutex.Lock() - defer m.mutex.Unlock() - addys := make([]string, 0, len(m.queues)) - - for addy := range m.queues { - addys = append(addys, addy) - } - - return addys -} - -// Push registers an intent to submit a transaction for the provided address at -// the provided sequence. A channel is returned that will be written to when -// the requester should attempt the submission. -func (m *Manager) Push(address string, sequence uint64, minSeqNum *uint64) <-chan error { - m.mutex.Lock() - defer m.mutex.Unlock() - - if m.size() >= m.MaxSize { - return m.getError(ErrNoMoreRoom) - } - - aq, ok := m.queues[address] - if !ok { - aq = NewAccountTxSubmissionQueue() - m.queues[address] = aq - } - - return aq.Push(sequence, minSeqNum) -} - -// NotifyLastAccountSequences notifies the manager of newly loaded account sequence information. The manager uses this information -// to notify requests to submit that they should proceed. See AccountTxSubmissionQueue#NotifyLastAccountSequence for the actual meat of the logic. -func (m *Manager) NotifyLastAccountSequences(updates map[string]uint64) { - m.mutex.Lock() - defer m.mutex.Unlock() - - for address, seq := range updates { - queue, ok := m.queues[address] - if !ok { - continue - } - - queue.NotifyLastAccountSequence(seq) - if queue.Size() == 0 { - delete(m.queues, address) - } - } -} - -// size returns the count of submissions buffered within this manager. This -// internal version assumes you have locked the manager previously. -func (m *Manager) size() int { - var result int - for _, q := range m.queues { - result += q.Size() - } - - return result -} - -func (m *Manager) getError(err error) <-chan error { - ch := make(chan error, 1) - ch <- err - close(ch) - return ch -} diff --git a/services/horizon/internal/txsub/sequence/manager_test.go b/services/horizon/internal/txsub/sequence/manager_test.go deleted file mode 100644 index e69b8be6fc..0000000000 --- a/services/horizon/internal/txsub/sequence/manager_test.go +++ /dev/null @@ -1,57 +0,0 @@ -package sequence - -import ( - "testing" - - "github.com/stretchr/testify/assert" -) - -// Test the Push method -func TestManager_Push(t *testing.T) { - mgr := NewManager() - - minSeq := uint64(1) - mgr.Push("1", 2, nil) - mgr.Push("1", 2, nil) - mgr.Push("1", 3, &minSeq) - mgr.Push("2", 2, nil) - - assert.Equal(t, 4, mgr.Size()) - assert.Equal(t, 3, mgr.queues["1"].Size()) - assert.Equal(t, 1, mgr.queues["2"].Size()) -} - -// Test the NotifyLastAccountSequences method -func TestManager_NotifyLastAccountSequences(t *testing.T) { - mgr := NewManager() - minSeq := uint64(1) - results := []<-chan error{ - mgr.Push("1", 4, &minSeq), - mgr.Push("1", 3, nil), - mgr.Push("2", 2, nil), - } - - mgr.NotifyLastAccountSequences(map[string]uint64{ - "1": 1, - "2": 1, - }) - - assert.Equal(t, 1, mgr.Size()) - _, ok := mgr.queues["2"] - assert.False(t, ok) - - assert.Equal(t, nil, <-results[0]) - assert.Equal(t, nil, <-results[2]) - assert.Equal(t, 0, len(results[1])) -} - -// Push until maximum queue size is reached and check that another push results in ErrNoMoreRoom -func TestManager_PushNoMoreRoom(t *testing.T) { - mgr := NewManager() - for i := 0; i < mgr.MaxSize; i++ { - mgr.Push("1", 2, nil) - } - - assert.Equal(t, 1024, mgr.Size()) - assert.Equal(t, ErrNoMoreRoom, <-mgr.Push("1", 2, nil)) -} diff --git a/services/horizon/internal/txsub/submitter.go b/services/horizon/internal/txsub/submitter.go index 85fd858233..27ce85c87a 100644 --- a/services/horizon/internal/txsub/submitter.go +++ b/services/horizon/internal/txsub/submitter.go @@ -58,7 +58,7 @@ func (sub *submitter) Submit(ctx context.Context, env string) (result Submission switch cresp.Status { case proto.TXStatusError: - result.Err = &FailedTransactionError{cresp.Error} + result.Err = &FailedTransactionError{cresp.Error, cresp.DiagnosticEvents} case proto.TXStatusPending, proto.TXStatusDuplicate, proto.TXStatusTryAgainLater: //noop. A nil Err indicates success default: diff --git a/services/horizon/internal/txsub/system.go b/services/horizon/internal/txsub/system.go index f9a8553c83..189f1619ff 100644 --- a/services/horizon/internal/txsub/system.go +++ b/services/horizon/internal/txsub/system.go @@ -9,7 +9,6 @@ import ( "github.com/prometheus/client_golang/prometheus" "github.com/stellar/go/services/horizon/internal/db2/history" - "github.com/stellar/go/services/horizon/internal/txsub/sequence" "github.com/stellar/go/support/log" "github.com/stellar/go/xdr" ) @@ -20,7 +19,7 @@ type HorizonDB interface { TransactionByHash(ctx context.Context, dest interface{}, hash string) error AllTransactionsByHashesSinceLedger(ctx context.Context, hashes []string, sinceLedgerSeq uint32) ([]history.Transaction, error) GetSequenceNumbers(ctx context.Context, addresses []string) (map[string]uint64, error) - BeginTx(*sql.TxOptions) error + BeginTx(context.Context, *sql.TxOptions) error Rollback() error NoRows(error) bool } @@ -39,7 +38,6 @@ type System struct { DB func(context.Context) HorizonDB Pending OpenSubmissionList Submitter Submitter - SubmissionQueue *sequence.Manager SubmissionTimeout time.Duration Log *log.Entry @@ -48,10 +46,6 @@ type System struct { // submissions to stellar-core SubmissionDuration prometheus.Summary - // BufferedSubmissionGauge tracks the count of submissions buffered - // behind this system's SubmissionQueue - BufferedSubmissionsGauge prometheus.Gauge - // OpenSubmissionsGauge tracks the count of "open" submissions (i.e. // submissions whose transactions haven't been confirmed successful or failed OpenSubmissionsGauge prometheus.Gauge @@ -81,7 +75,6 @@ type System struct { // RegisterMetrics registers the prometheus metrics func (sys *System) RegisterMetrics(registry *prometheus.Registry) { registry.MustRegister(sys.Metrics.SubmissionDuration) - registry.MustRegister(sys.Metrics.BufferedSubmissionsGauge) registry.MustRegister(sys.Metrics.OpenSubmissionsGauge) registry.MustRegister(sys.Metrics.FailedSubmissionsCounter) registry.MustRegister(sys.Metrics.SuccessfulSubmissionsCounter) @@ -122,7 +115,7 @@ func (sys *System) Submit( return } - tx, sequenceNumber, err := checkTxAlreadyExists(ctx, db, hash, sourceAddress) + tx, err := txResultByHash(ctx, db, hash) if err == nil { sys.Log.Ctx(ctx).WithField("hash", hash).Info("Found submission result in a DB") sys.finish(ctx, hash, resultCh, Result{Transaction: tx}) @@ -134,75 +127,45 @@ func (sys *System) Submit( return } - // queue the submission and get the channel that will emit when - // submission is valid - var pMinSeqNum *uint64 - if minSeqNum != nil { - uMinSeqNum := uint64(*minSeqNum) - pMinSeqNum = &uMinSeqNum - } - submissionWait := sys.SubmissionQueue.Push(sourceAddress, uint64(seqNum), pMinSeqNum) - - // update the submission queue with the source accounts current sequence value - // which will cause the channel returned by Push() to emit if possible. - sys.SubmissionQueue.NotifyLastAccountSequences(map[string]uint64{ - sourceAddress: sequenceNumber, - }) - - select { - case err := <-submissionWait: - if err == sequence.ErrBadSequence { - // convert the internal only ErrBadSequence into the FailedTransactionError - err = ErrBadSequence - } + sr := sys.submitOnce(ctx, rawTx) + sys.updateTransactionTypeMetrics(envelope) + if sr.Err != nil { + // any error other than "txBAD_SEQ" is a failure + isBad, err := sr.IsBadSeq() if err != nil { sys.finish(ctx, hash, resultCh, Result{Err: err}) return } + if !isBad { + sys.finish(ctx, hash, resultCh, Result{Err: sr.Err}) + return + } - sr := sys.submitOnce(ctx, rawTx) - sys.updateTransactionTypeMetrics(envelope) - - if sr.Err != nil { - // any error other than "txBAD_SEQ" is a failure - isBad, err := sr.IsBadSeq() - if err != nil { - sys.finish(ctx, hash, resultCh, Result{Err: err}) - return - } - if !isBad { - sys.finish(ctx, hash, resultCh, Result{Err: sr.Err}) - return - } - - if err = sys.waitUntilAccountSequence(ctx, db, sourceAddress, uint64(envelope.SeqNum())); err != nil { - sys.finish(ctx, hash, resultCh, Result{Err: err}) - return - } - - // If error is txBAD_SEQ, check for the result again - tx, err = txResultByHash(ctx, db, hash) - if err != nil { - // finally, return the bad_seq error if no result was found on 2nd attempt - sys.finish(ctx, hash, resultCh, Result{Err: sr.Err}) - return - } - // If we found the result, use it as the result - sys.finish(ctx, hash, resultCh, Result{Transaction: tx}) + // Even if a transaction is successfully submitted to core, Horizon ingestion might + // be lagging behind leading to txBAD_SEQ. This function will block a txsub request + // until the request times out or account sequence is bumped to txn sequence. + if err = sys.waitUntilAccountSequence(ctx, db, sourceAddress, uint64(envelope.SeqNum())); err != nil { + sys.finish(ctx, hash, resultCh, Result{Err: err}) return } - // add transactions to open list - sys.Pending.Add(ctx, hash, resultCh) - // update the submission queue, allowing the next submission to proceed - sys.SubmissionQueue.NotifyLastAccountSequences(map[string]uint64{ - sourceAddress: uint64(envelope.SeqNum()), - }) - case <-ctx.Done(): - sys.finish(ctx, hash, resultCh, Result{Err: sys.deriveTxSubError(ctx)}) + // If error is txBAD_SEQ, check for the result again + tx, err = txResultByHash(ctx, db, hash) + if err != nil { + // finally, return the bad_seq error if no result was found on 2nd attempt + sys.finish(ctx, hash, resultCh, Result{Err: sr.Err}) + return + } + // If we found the result, use it as the result + sys.finish(ctx, hash, resultCh, Result{Transaction: tx}) + return } + // Add transaction to open list of pending txns: the transaction has been successfully submitted to core + // but that does not mean it is included in the ledger. The txn status remains pending + // until we see an ingestion in the db. + sys.Pending.Add(hash, resultCh) return } @@ -311,33 +274,20 @@ func (sys *System) Tick(ctx context.Context) { defer sys.unsetTickInProgress() - logger. - WithField("queued", sys.SubmissionQueue.String()). - Debug("ticking txsub system") + logger.Debug("ticking txsub system") db := sys.DB(ctx) options := &sql.TxOptions{ Isolation: sql.LevelRepeatableRead, ReadOnly: true, } - if err := db.BeginTx(options); err != nil { + if err := db.BeginTx(ctx, options); err != nil { logger.WithError(err).Error("could not start repeatable read transaction for txsub tick") return } defer db.Rollback() - addys := sys.SubmissionQueue.Addresses() - if len(addys) > 0 { - curSeq, err := db.GetSequenceNumbers(ctx, addys) - if err != nil { - logger.WithStack(err).Error(err) - return - } else { - sys.SubmissionQueue.NotifyLastAccountSequences(curSeq) - } - } - - pending := sys.Pending.Pending(ctx) + pending := sys.Pending.Pending() if len(pending) > 0 { latestLedger, err := db.GetLatestHistoryLedger(ctx) @@ -376,13 +326,13 @@ func (sys *System) Tick(ctx context.Context) { if err == nil { logger.WithField("hash", hash).Debug("finishing open submission") - sys.Pending.Finish(ctx, hash, Result{Transaction: tx}) + sys.Pending.Finish(hash, Result{Transaction: tx}) continue } if _, ok := err.(*FailedTransactionError); ok { logger.WithField("hash", hash).Debug("finishing open submission") - sys.Pending.Finish(ctx, hash, Result{Transaction: tx, Err: err}) + sys.Pending.Finish(hash, Result{Transaction: tx, Err: err}) continue } @@ -392,14 +342,8 @@ func (sys *System) Tick(ctx context.Context) { } } - stillOpen, err := sys.Pending.Clean(ctx, sys.SubmissionTimeout) - if err != nil { - logger.WithStack(err).Error(err) - return - } - + stillOpen := sys.Pending.Clean(sys.SubmissionTimeout) sys.Metrics.OpenSubmissionsGauge.Set(float64(stillOpen)) - sys.Metrics.BufferedSubmissionsGauge.Set(float64(sys.SubmissionQueue.Size())) } // Init initializes `sys` @@ -409,7 +353,8 @@ func (sys *System) Init() { sys.Metrics.SubmissionDuration = prometheus.NewSummary(prometheus.SummaryOpts{ Namespace: "horizon", Subsystem: "txsub", Name: "submission_duration_seconds", - Help: "submission durations to Stellar-Core, sliding window = 10m", + Help: "submission durations to Stellar-Core, sliding window = 10m", + Objectives: map[float64]float64{0.5: 0.05, 0.9: 0.01, 0.99: 0.001}, }) sys.Metrics.FailedSubmissionsCounter = prometheus.NewCounter(prometheus.CounterOpts{ Namespace: "horizon", Subsystem: "txsub", Name: "failed", @@ -420,9 +365,6 @@ func (sys *System) Init() { sys.Metrics.OpenSubmissionsGauge = prometheus.NewGauge(prometheus.GaugeOpts{ Namespace: "horizon", Subsystem: "txsub", Name: "open", }) - sys.Metrics.BufferedSubmissionsGauge = prometheus.NewGauge(prometheus.GaugeOpts{ - Namespace: "horizon", Subsystem: "txsub", Name: "buffered", - }) sys.Metrics.V0TransactionsCounter = prometheus.NewCounter(prometheus.CounterOpts{ Namespace: "horizon", Subsystem: "txsub", Name: "v0", }) diff --git a/services/horizon/internal/txsub/system_test.go b/services/horizon/internal/txsub/system_test.go index 439c90d858..816cc28e66 100644 --- a/services/horizon/internal/txsub/system_test.go +++ b/services/horizon/internal/txsub/system_test.go @@ -19,7 +19,6 @@ import ( "github.com/stellar/go/services/horizon/internal/db2/history" "github.com/stellar/go/services/horizon/internal/test" - "github.com/stellar/go/services/horizon/internal/txsub/sequence" "github.com/stellar/go/xdr" ) @@ -42,9 +41,8 @@ func (suite *SystemTestSuite) SetupTest() { suite.db = &mockDBQ{} suite.system = &System{ - Pending: NewDefaultSubmissionList(), - Submitter: suite.submitter, - SubmissionQueue: sequence.NewManager(), + Pending: NewDefaultSubmissionList(), + Submitter: suite.submitter, DB: func(ctx context.Context) HorizonDB { return suite.db }, @@ -124,11 +122,6 @@ func (suite *SystemTestSuite) TearDownTest() { // Returns the result provided by the ResultProvider. func (suite *SystemTestSuite) TestSubmit_Basic() { - suite.db.On("BeginTx", &sql.TxOptions{ - Isolation: sql.LevelRepeatableRead, - ReadOnly: true, - }).Return(nil).Once() - suite.db.On("Rollback").Return(nil).Once() suite.db.On("PreFilteredTransactionByHash", suite.ctx, mock.Anything, suite.successTx.Transaction.TransactionHash). Run(func(args mock.Arguments) { ptr := args.Get(1).(*history.Transaction) @@ -148,17 +141,12 @@ func (suite *SystemTestSuite) TestSubmit_Basic() { assert.False(suite.T(), suite.submitter.WasSubmittedTo) } -func (suite *SystemTestSuite) TestTimeoutDuringSequnceLoop() { +func (suite *SystemTestSuite) TestTimeoutDuringSequenceLoop() { var cancel context.CancelFunc suite.ctx, cancel = context.WithTimeout(suite.ctx, time.Duration(0)) defer cancel() suite.submitter.R = suite.badSeq - suite.db.On("BeginTx", &sql.TxOptions{ - Isolation: sql.LevelRepeatableRead, - ReadOnly: true, - }).Return(nil).Once() - suite.db.On("Rollback").Return(nil).Once() suite.db.On("PreFilteredTransactionByHash", suite.ctx, mock.Anything, suite.successTx.Transaction.TransactionHash). Return(sql.ErrNoRows).Once() suite.db.On("TransactionByHash", suite.ctx, mock.Anything, suite.successTx.Transaction.TransactionHash). @@ -178,16 +166,11 @@ func (suite *SystemTestSuite) TestTimeoutDuringSequnceLoop() { assert.Equal(suite.T(), ErrTimeout, r.Err) } -func (suite *SystemTestSuite) TestClientDisconnectedDuringSequnceLoop() { +func (suite *SystemTestSuite) TestClientDisconnectedDuringSequenceLoop() { var cancel context.CancelFunc suite.ctx, cancel = context.WithCancel(suite.ctx) suite.submitter.R = suite.badSeq - suite.db.On("BeginTx", &sql.TxOptions{ - Isolation: sql.LevelRepeatableRead, - ReadOnly: true, - }).Return(nil).Once() - suite.db.On("Rollback").Return(nil).Once() suite.db.On("PreFilteredTransactionByHash", suite.ctx, mock.Anything, suite.successTx.Transaction.TransactionHash). Return(sql.ErrNoRows).Once() suite.db.On("TransactionByHash", suite.ctx, mock.Anything, suite.successTx.Transaction.TransactionHash). @@ -196,7 +179,7 @@ func (suite *SystemTestSuite) TestClientDisconnectedDuringSequnceLoop() { suite.db.On("GetSequenceNumbers", suite.ctx, []string{suite.unmuxedSource.Address()}). Return(map[string]uint64{suite.unmuxedSource.Address(): 0}, nil). Run(func(args mock.Arguments) { - // simulate client disconnecting while looping on sequnce number check + // simulate client disconnecting while looping on sequence number check cancel() suite.ctx.Deadline() }). @@ -226,19 +209,11 @@ func getMetricValue(metric prometheus.Metric) *dto.Metric { // Returns the error from submission if no result is found by hash and the suite.submitter returns an error. func (suite *SystemTestSuite) TestSubmit_NotFoundError() { - suite.db.On("BeginTx", &sql.TxOptions{ - Isolation: sql.LevelRepeatableRead, - ReadOnly: true, - }).Return(nil).Once() - suite.db.On("Rollback").Return(nil).Once() suite.db.On("PreFilteredTransactionByHash", suite.ctx, mock.Anything, suite.successTx.Transaction.TransactionHash). Return(sql.ErrNoRows).Once() suite.db.On("TransactionByHash", suite.ctx, mock.Anything, suite.successTx.Transaction.TransactionHash). Return(sql.ErrNoRows).Once() suite.db.On("NoRows", sql.ErrNoRows).Return(true).Twice() - suite.db.On("GetSequenceNumbers", suite.ctx, []string{suite.unmuxedSource.Address()}). - Return(map[string]uint64{suite.unmuxedSource.Address(): 0}, nil). - Once() suite.submitter.R.Err = errors.New("busted for some reason") r := <-suite.system.Submit( @@ -258,11 +233,6 @@ func (suite *SystemTestSuite) TestSubmit_NotFoundError() { // If the error is bad_seq and the result at the transaction's sequence number is for the same hash, return result. func (suite *SystemTestSuite) TestSubmit_BadSeq() { suite.submitter.R = suite.badSeq - suite.db.On("BeginTx", &sql.TxOptions{ - Isolation: sql.LevelRepeatableRead, - ReadOnly: true, - }).Return(nil).Once() - suite.db.On("Rollback").Return(nil).Once() suite.db.On("NoRows", sql.ErrNoRows).Return(true).Once() suite.db.On("GetSequenceNumbers", suite.ctx, []string{suite.unmuxedSource.Address()}). Return(map[string]uint64{suite.unmuxedSource.Address(): 0}, nil). @@ -298,11 +268,6 @@ func (suite *SystemTestSuite) TestSubmit_BadSeq() { // If error is bad_seq and no result is found, return error. func (suite *SystemTestSuite) TestSubmit_BadSeqNotFound() { suite.submitter.R = suite.badSeq - suite.db.On("BeginTx", &sql.TxOptions{ - Isolation: sql.LevelRepeatableRead, - ReadOnly: true, - }).Return(nil).Once() - suite.db.On("Rollback").Return(nil).Once() suite.db.On("PreFilteredTransactionByHash", suite.ctx, mock.Anything, suite.successTx.Transaction.TransactionHash). Return(sql.ErrNoRows).Twice() suite.db.On("NoRows", sql.ErrNoRows).Return(true).Twice() @@ -333,19 +298,11 @@ func (suite *SystemTestSuite) TestSubmit_BadSeqNotFound() { // If no result found and no error submitting, add to open transaction list. func (suite *SystemTestSuite) TestSubmit_OpenTransactionList() { - suite.db.On("BeginTx", &sql.TxOptions{ - Isolation: sql.LevelRepeatableRead, - ReadOnly: true, - }).Return(nil).Once() - suite.db.On("Rollback").Return(nil).Once() suite.db.On("PreFilteredTransactionByHash", suite.ctx, mock.Anything, suite.successTx.Transaction.TransactionHash). Return(sql.ErrNoRows).Once() suite.db.On("TransactionByHash", suite.ctx, mock.Anything, suite.successTx.Transaction.TransactionHash). Return(sql.ErrNoRows).Once() suite.db.On("NoRows", sql.ErrNoRows).Return(true).Twice() - suite.db.On("GetSequenceNumbers", suite.ctx, []string{suite.unmuxedSource.Address()}). - Return(map[string]uint64{suite.unmuxedSource.Address(): 0}, nil). - Once() suite.system.Submit( suite.ctx, @@ -353,7 +310,7 @@ func (suite *SystemTestSuite) TestSubmit_OpenTransactionList() { suite.successXDR, suite.successTx.Transaction.TransactionHash, ) - pending := suite.system.Pending.Pending(suite.ctx) + pending := suite.system.Pending.Pending() assert.Equal(suite.T(), 1, len(pending)) assert.Equal(suite.T(), suite.successTx.Transaction.TransactionHash, pending[0]) assert.Equal(suite.T(), float64(1), getMetricValue(suite.system.Metrics.SuccessfulSubmissionsCounter).GetCounter().GetValue()) @@ -363,7 +320,7 @@ func (suite *SystemTestSuite) TestSubmit_OpenTransactionList() { // Tick should be a no-op if there are no open submissions. func (suite *SystemTestSuite) TestTick_Noop() { - suite.db.On("BeginTx", &sql.TxOptions{ + suite.db.On("BeginTx", mock.AnythingOfType("*context.valueCtx"), &sql.TxOptions{ Isolation: sql.LevelRepeatableRead, ReadOnly: true, }).Return(nil).Once() @@ -372,37 +329,12 @@ func (suite *SystemTestSuite) TestTick_Noop() { suite.system.Tick(suite.ctx) } -// TestTick_Deadlock is a regression test for Tick() deadlock: if for any reason -// call to Tick() takes more time and another Tick() is called. -// This test starts two go routines: both calling Tick() but the call to -// `sys.Sequences.Get(addys)` is delayed by 1 second. It allows to simulate two -// calls to `Tick()` executed at the same time. -func (suite *SystemTestSuite) TestTick_Deadlock() { - suite.db.On("BeginTx", &sql.TxOptions{ - Isolation: sql.LevelRepeatableRead, - ReadOnly: true, - }).Return(nil).Once() - suite.db.On("Rollback").Return(nil).Once() - - // Start first Tick - suite.system.SubmissionQueue.Push("address", 0, nil) - suite.db.On("GetSequenceNumbers", suite.ctx, []string{"address"}). - Return(map[string]uint64{}, nil). - Run(func(args mock.Arguments) { - // Start second tick - suite.system.Tick(suite.ctx) - }). - Once() - - suite.system.Tick(suite.ctx) -} - // Test that Tick finishes any available transactions, func (suite *SystemTestSuite) TestTick_FinishesTransactions() { l := make(chan Result, 1) - suite.system.Pending.Add(suite.ctx, suite.successTx.Transaction.TransactionHash, l) + suite.system.Pending.Add(suite.successTx.Transaction.TransactionHash, l) - suite.db.On("BeginTx", &sql.TxOptions{ + suite.db.On("BeginTx", mock.AnythingOfType("*context.valueCtx"), &sql.TxOptions{ Isolation: sql.LevelRepeatableRead, ReadOnly: true, }).Return(nil).Once() @@ -414,9 +346,9 @@ func (suite *SystemTestSuite) TestTick_FinishesTransactions() { suite.system.Tick(suite.ctx) assert.Equal(suite.T(), 0, len(l)) - assert.Equal(suite.T(), 1, len(suite.system.Pending.Pending(suite.ctx))) + assert.Equal(suite.T(), 1, len(suite.system.Pending.Pending())) - suite.db.On("BeginTx", &sql.TxOptions{ + suite.db.On("BeginTx", mock.AnythingOfType("*context.valueCtx"), &sql.TxOptions{ Isolation: sql.LevelRepeatableRead, ReadOnly: true, }).Return(nil).Once() @@ -427,7 +359,7 @@ func (suite *SystemTestSuite) TestTick_FinishesTransactions() { suite.system.Tick(suite.ctx) assert.Equal(suite.T(), 1, len(l)) - assert.Equal(suite.T(), 0, len(suite.system.Pending.Pending(suite.ctx))) + assert.Equal(suite.T(), 0, len(suite.system.Pending.Pending())) } func (suite *SystemTestSuite) TestTickFinishFeeBumpTransaction() { @@ -450,25 +382,17 @@ func (suite *SystemTestSuite) TestTickFinishFeeBumpTransaction() { }, } - suite.db.On("BeginTx", &sql.TxOptions{ - Isolation: sql.LevelRepeatableRead, - ReadOnly: true, - }).Return(nil).Once() - suite.db.On("Rollback").Return(nil).Once() suite.db.On("PreFilteredTransactionByHash", suite.ctx, mock.Anything, innerHash). Return(sql.ErrNoRows).Once() suite.db.On("TransactionByHash", suite.ctx, mock.Anything, innerHash). Return(sql.ErrNoRows).Once() suite.db.On("NoRows", sql.ErrNoRows).Return(true).Twice() - suite.db.On("GetSequenceNumbers", suite.ctx, []string{"GABQGAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB2MX"}). - Return(map[string]uint64{"GABQGAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB2MX": 96}, nil). - Once() l := suite.system.Submit(suite.ctx, innerTxEnvelope, parsedInnerTx, innerHash) assert.Equal(suite.T(), 0, len(l)) - assert.Equal(suite.T(), 1, len(suite.system.Pending.Pending(suite.ctx))) + assert.Equal(suite.T(), 1, len(suite.system.Pending.Pending())) - suite.db.On("BeginTx", &sql.TxOptions{ + suite.db.On("BeginTx", mock.AnythingOfType("*context.valueCtx"), &sql.TxOptions{ Isolation: sql.LevelRepeatableRead, ReadOnly: true, }).Return(nil).Once() @@ -479,7 +403,7 @@ func (suite *SystemTestSuite) TestTickFinishFeeBumpTransaction() { suite.system.Tick(suite.ctx) assert.Equal(suite.T(), 1, len(l)) - assert.Equal(suite.T(), 0, len(suite.system.Pending.Pending(suite.ctx))) + assert.Equal(suite.T(), 0, len(suite.system.Pending.Pending())) r := <-l assert.NoError(suite.T(), r.Err) assert.Equal(suite.T(), feeBumpTx, r) @@ -489,10 +413,10 @@ func (suite *SystemTestSuite) TestTickFinishFeeBumpTransaction() { func (suite *SystemTestSuite) TestTick_RemovesStaleSubmissions() { l := make(chan Result, 1) suite.system.SubmissionTimeout = 100 * time.Millisecond - suite.system.Pending.Add(suite.ctx, suite.successTx.Transaction.TransactionHash, l) + suite.system.Pending.Add(suite.successTx.Transaction.TransactionHash, l) <-time.After(101 * time.Millisecond) - suite.db.On("BeginTx", &sql.TxOptions{ + suite.db.On("BeginTx", mock.AnythingOfType("*context.valueCtx"), &sql.TxOptions{ Isolation: sql.LevelRepeatableRead, ReadOnly: true, }).Return(nil).Once() @@ -503,7 +427,7 @@ func (suite *SystemTestSuite) TestTick_RemovesStaleSubmissions() { suite.system.Tick(suite.ctx) - assert.Equal(suite.T(), 0, len(suite.system.Pending.Pending(suite.ctx))) + assert.Equal(suite.T(), 0, len(suite.system.Pending.Pending())) assert.Equal(suite.T(), 1, len(l)) <-l select { diff --git a/services/keystore/api.go b/services/keystore/api.go index f4915f6334..bdce9513cc 100644 --- a/services/keystore/api.go +++ b/services/keystore/api.go @@ -65,8 +65,8 @@ type authResponse struct { } var forwardHeaders = map[string]struct{}{ - "authorization": struct{}{}, - "cookie": struct{}{}, + "authorization": {}, + "cookie": {}, } func authHandler(next http.Handler, authenticator *Authenticator) http.Handler { diff --git a/services/keystore/docker/Dockerfile b/services/keystore/docker/Dockerfile index f348d3afdd..d44d714972 100644 --- a/services/keystore/docker/Dockerfile +++ b/services/keystore/docker/Dockerfile @@ -1,4 +1,4 @@ -FROM golang:1.18 as build +FROM golang:1.19.1 as build ADD . /src/keystore WORKDIR /src/keystore diff --git a/services/keystore/keys.go b/services/keystore/keys.go index 9da6606659..7f134b5024 100644 --- a/services/keystore/keys.go +++ b/services/keystore/keys.go @@ -42,7 +42,7 @@ func (s *Service) putKeys(ctx context.Context, in putKeysRequest) (*encryptedKey if err != nil { // TODO: we need to implement a helper function in the // support/error package for keeping the stack trace from err - // and substitude the root error for the one we want for better + // and substitute the root error for the one we want for better // debugging experience. // Thowing away the original err makes it harder for debugging. return nil, probInvalidKeysBlob diff --git a/services/regulated-assets-approval-server/docker/Dockerfile b/services/regulated-assets-approval-server/docker/Dockerfile index 849ebff828..c029189e50 100644 --- a/services/regulated-assets-approval-server/docker/Dockerfile +++ b/services/regulated-assets-approval-server/docker/Dockerfile @@ -1,11 +1,11 @@ -FROM golang:1.18 as build +FROM golang:1.19.1 as build ADD . /src/regulated-assets-approval-server WORKDIR /src/regulated-assets-approval-server RUN go build -o /bin/regulated-assets-approval-server ./services/regulated-assets-approval-server -FROM ubuntu:20.04 +FROM ubuntu:22.04 RUN apt-get update && apt-get install -y --no-install-recommends ca-certificates COPY --from=build /bin/regulated-assets-approval-server /app/ diff --git a/services/regulated-assets-approval-server/internal/configureissuer/configureissuer_test.go b/services/regulated-assets-approval-server/internal/configureissuer/configureissuer_test.go index 4d91467b3f..f26afdae11 100644 --- a/services/regulated-assets-approval-server/internal/configureissuer/configureissuer_test.go +++ b/services/regulated-assets-approval-server/internal/configureissuer/configureissuer_test.go @@ -75,7 +75,7 @@ func TestGetOrFundIssuerAccount_failsIfNotDefaultTesntet(t *testing.T) { _, err := getOrFundIssuerAccount(issuerKP.Address(), &horizonMock) wantErrMsg := fmt.Sprintf("getting detail for account %s: problem: not_found", issuerKP.Address()) - require.EqualError(t, err, wantErrMsg) + require.True(t, strings.Contains(err.Error(), wantErrMsg)) } func TestSetup(t *testing.T) { diff --git a/services/regulated-assets-approval-server/internal/db/dbmigrate/dbmigrate_generated.go b/services/regulated-assets-approval-server/internal/db/dbmigrate/dbmigrate_generated.go index 39efd3c0a8..4b52521be3 100644 --- a/services/regulated-assets-approval-server/internal/db/dbmigrate/dbmigrate_generated.go +++ b/services/regulated-assets-approval-server/internal/db/dbmigrate/dbmigrate_generated.go @@ -231,13 +231,11 @@ var _bindata = map[string]func() (*asset, error){ // directory embedded in the file by go-bindata. // For example if you run go-bindata on data/... and data contains the // following hierarchy: -// -// data/ -// foo.txt -// img/ -// a.png -// b.png -// +// data/ +// foo.txt +// img/ +// a.png +// b.png // then AssetDir("data") would return []string{"foo.txt", "img"}, // AssetDir("data/img") would return []string{"a.png", "b.png"}, // AssetDir("foo.txt") and AssetDir("notexist") would return an error, and diff --git a/services/regulated-assets-approval-server/internal/serve/httperror/http_error_test.go b/services/regulated-assets-approval-server/internal/serve/httperror/http_error_test.go index 695ada7c78..3434a24c78 100644 --- a/services/regulated-assets-approval-server/internal/serve/httperror/http_error_test.go +++ b/services/regulated-assets-approval-server/internal/serve/httperror/http_error_test.go @@ -36,5 +36,5 @@ func TestParseHorizonError(t *testing.T) { }, } err = ParseHorizonError(horizonError) - require.EqualError(t, err, "error submitting transaction: problem: bad_request, &{TransactionCode:tx_code_here InnerTransactionCode: OperationCodes:[op_success op_bad_auth]}\n: horizon error: \"Bad Request\" (tx_code_here, op_success, op_bad_auth) - check horizon.Error.Problem for more information") + require.EqualError(t, err, "error submitting transaction: problem: bad_request. full details: , &{TransactionCode:tx_code_here InnerTransactionCode: OperationCodes:[op_success op_bad_auth]}\n: horizon error: \"Bad Request\" (tx_code_here, op_success, op_bad_auth) - check horizon.Error.Problem for more information") } diff --git a/services/regulated-assets-approval-server/internal/serve/kycstatus/post_handler.go b/services/regulated-assets-approval-server/internal/serve/kycstatus/post_handler.go index 6695f886df..2ac37317e2 100644 --- a/services/regulated-assets-approval-server/internal/serve/kycstatus/post_handler.go +++ b/services/regulated-assets-approval-server/internal/serve/kycstatus/post_handler.go @@ -154,5 +154,5 @@ func (in kycPostRequest) buildUpdateKYCQuery() (string, []interface{}) { } // RxEmail is a regex used to validate e-mail addresses, according with the reference https://www.alexedwards.net/blog/validation-snippets-for-go#email-validation. -// It's free to use under the [MIT Licence](https://opensource.org/licenses/MIT) +// It's free to use under the [MIT License](https://opensource.org/licenses/MIT) var RxEmail = regexp.MustCompile("^[a-zA-Z0-9.!#$%&'*+\\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$") diff --git a/services/ticker/docker/Dockerfile b/services/ticker/docker/Dockerfile index c93ee784c1..ac72c1ad3e 100644 --- a/services/ticker/docker/Dockerfile +++ b/services/ticker/docker/Dockerfile @@ -1,11 +1,11 @@ -FROM golang:1.18 as build +FROM golang:1.19.1 as build ADD . /src/ticker WORKDIR /src/ticker RUN go build -o /bin/ticker ./services/ticker -FROM ubuntu:20.04 +FROM ubuntu:22.04 RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends ca-certificates COPY --from=build /bin/ticker /app/ diff --git a/services/ticker/docker/Dockerfile-dev b/services/ticker/docker/Dockerfile-dev index 7eb5963f44..3a60c44716 100644 --- a/services/ticker/docker/Dockerfile-dev +++ b/services/ticker/docker/Dockerfile-dev @@ -1,4 +1,4 @@ -FROM golang:1.18 as build +FROM golang:1.19.1 as build LABEL maintainer="Alex Cordeiro " diff --git a/services/ticker/internal/gql/static/bindata.go b/services/ticker/internal/gql/static/bindata.go index 298e85a5d3..3295ebab36 100644 --- a/services/ticker/internal/gql/static/bindata.go +++ b/services/ticker/internal/gql/static/bindata.go @@ -209,13 +209,11 @@ var _bindata = map[string]func() (*asset, error){ // directory embedded in the file by go-bindata. // For example if you run go-bindata on data/... and data contains the // following hierarchy: -// -// data/ -// foo.txt -// img/ -// a.png -// b.png -// +// data/ +// foo.txt +// img/ +// a.png +// b.png // then AssetDir("data") would return []string{"foo.txt", "img"}, // AssetDir("data/img") would return []string{"a.png", "b.png"}, // AssetDir("foo.txt") and AssetDir("notexist") would return an error, and diff --git a/services/ticker/internal/main.go b/services/ticker/internal/main.go index bc2cfc96d2..6a2b67b6d7 100644 --- a/services/ticker/internal/main.go +++ b/services/ticker/internal/main.go @@ -43,7 +43,7 @@ type MarketStats struct { SpreadMidPoint float64 `json:"spread_mid_point"` } -// Asset Sumary represents the collection of valid assets. +// Asset Summary represents the collection of valid assets. type AssetSummary struct { GeneratedAt int64 `json:"generated_at"` GeneratedAtRFC3339 string `json:"generated_at_rfc3339"` diff --git a/services/ticker/internal/tickerdb/helpers.go b/services/ticker/internal/tickerdb/helpers.go index 4958d61535..d15799824a 100644 --- a/services/ticker/internal/tickerdb/helpers.go +++ b/services/ticker/internal/tickerdb/helpers.go @@ -6,8 +6,10 @@ import ( "fmt" "reflect" "strings" + "testing" "github.com/stellar/go/services/ticker/internal/utils" + "github.com/stellar/go/support/db/dbtest" ) // getDBFieldTags returns all "db" tags for a given struct, optionally excluding the "id". @@ -136,3 +138,15 @@ func (s *TickerSession) performUpsertQuery(ctx context.Context, dbStruct interfa _, err := s.ExecRaw(ctx, qs, dbValues...) return err } + +func OpenTestDBConnection(t *testing.T) *dbtest.DB { + db := dbtest.Postgres(t) + dbVersion := db.Version() + + // Ticker requires Postgres >= v10 + if dbVersion < 10 { + t.Skipf("Skipping test because Postgres v%d found, and Postgres v10+ required for this test.", dbVersion) + } + + return db +} diff --git a/services/ticker/internal/tickerdb/helpers_test.go b/services/ticker/internal/tickerdb/helpers_test.go index 6c09306636..71f025aa20 100644 --- a/services/ticker/internal/tickerdb/helpers_test.go +++ b/services/ticker/internal/tickerdb/helpers_test.go @@ -70,20 +70,20 @@ func TestGenerateWhereClause(t *testing.T) { *baseAssetIssuer = "baseAssetIssuer" where1, args1 := generateWhereClause([]optionalVar{ - optionalVar{"t1.base_asset_code", nil}, - optionalVar{"t1.base_asset_issuer", nil}, - optionalVar{"t1.counter_asset_code", nil}, - optionalVar{"t1.counter_asset_issuer", nil}, + {"t1.base_asset_code", nil}, + {"t1.base_asset_issuer", nil}, + {"t1.counter_asset_code", nil}, + {"t1.counter_asset_issuer", nil}, }) assert.Equal(t, "", where1) assert.Equal(t, 0, len(args1)) where2, args2 := generateWhereClause([]optionalVar{ - optionalVar{"t1.base_asset_code", baseAssetCode}, - optionalVar{"t1.base_asset_issuer", nil}, - optionalVar{"t1.counter_asset_code", nil}, - optionalVar{"t1.counter_asset_issuer", nil}, + {"t1.base_asset_code", baseAssetCode}, + {"t1.base_asset_issuer", nil}, + {"t1.counter_asset_code", nil}, + {"t1.counter_asset_issuer", nil}, }) assert.Equal(t, "WHERE t1.base_asset_code = ?", where2) @@ -91,10 +91,10 @@ func TestGenerateWhereClause(t *testing.T) { assert.Equal(t, *baseAssetCode, args2[0]) where3, args3 := generateWhereClause([]optionalVar{ - optionalVar{"t1.base_asset_code", baseAssetCode}, - optionalVar{"t1.base_asset_issuer", baseAssetIssuer}, - optionalVar{"t1.counter_asset_code", nil}, - optionalVar{"t1.counter_asset_issuer", nil}, + {"t1.base_asset_code", baseAssetCode}, + {"t1.base_asset_issuer", baseAssetIssuer}, + {"t1.counter_asset_code", nil}, + {"t1.counter_asset_issuer", nil}, }) assert.Equal(t, "WHERE t1.base_asset_code = ? AND t1.base_asset_issuer = ?", where3) diff --git a/services/ticker/internal/tickerdb/main.go b/services/ticker/internal/tickerdb/main.go index 3553273fc3..943ca046b5 100644 --- a/services/ticker/internal/tickerdb/main.go +++ b/services/ticker/internal/tickerdb/main.go @@ -67,7 +67,7 @@ type Issuer struct { // Trade represents an entry on the trades table type Trade struct { - ID int32 `db:"id"` + ID int64 `db:"id"` HorizonID string `db:"horizon_id"` LedgerCloseTime time.Time `db:"ledger_close_time"` OfferID string `db:"offer_id"` diff --git a/services/ticker/internal/tickerdb/migrations/20220909100700-trades_pk_to_bigint.sql b/services/ticker/internal/tickerdb/migrations/20220909100700-trades_pk_to_bigint.sql new file mode 100644 index 0000000000..919f22ced5 --- /dev/null +++ b/services/ticker/internal/tickerdb/migrations/20220909100700-trades_pk_to_bigint.sql @@ -0,0 +1,9 @@ + +-- +migrate Up +ALTER TABLE trades ALTER COLUMN id TYPE BIGINT; +ALTER SEQUENCE trades_id_seq AS BIGINT CYCLE; + + +-- +migrate Down +ALTER TABLE trades ALTER COLUMN id TYPE INT; +ALTER SEQUENCE trades_id_seq AS INT NO CYCLE; diff --git a/services/ticker/internal/tickerdb/migrations/bindata.go b/services/ticker/internal/tickerdb/migrations/bindata.go index 8762c4b1ae..772b9a366d 100644 --- a/services/ticker/internal/tickerdb/migrations/bindata.go +++ b/services/ticker/internal/tickerdb/migrations/bindata.go @@ -10,6 +10,7 @@ // migrations/20190411165735-data_seed_and_indices.sql (1.522kB) // migrations/20190425110313-add_orderbook_stats.sql (749B) // migrations/20190426092321-add_aggregated_orderbook_view.sql (831B) +// migrations/20220909100700-trades_pk_to_bigint.sql (220B) package bdata @@ -278,6 +279,26 @@ func migrations20190426092321Add_aggregated_orderbook_viewSql() (*asset, error) return a, nil } +var _migrations20220909100700Trades_pk_to_bigintSql = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xe2\xd2\xd5\x55\xd0\xce\xcd\x4c\x2f\x4a\x2c\x49\x55\x08\x2d\xe0\x72\xf4\x09\x71\x0d\x52\x08\x71\x74\xf2\x71\x55\x28\x29\x4a\x4c\x49\x2d\x56\x80\x08\x39\xfb\xfb\x84\xfa\xfa\x29\x64\xa6\x28\x84\x44\x06\xb8\x2a\x38\x79\xba\x7b\xfa\x85\x58\x43\xd5\x07\xbb\x06\x86\xba\xfa\x39\xc3\xb4\xc4\x67\xa6\xc4\x17\xa7\x16\x2a\x38\x06\x43\xd5\x29\x38\x47\x3a\xfb\xb8\x5a\x73\x71\xa1\x58\xe7\x92\x5f\x9e\x47\xb4\x85\x44\xd9\x06\xb2\xca\xcf\x1f\x66\x1b\x20\x00\x00\xff\xff\xed\x82\xee\x3c\xdc\x00\x00\x00") + +func migrations20220909100700Trades_pk_to_bigintSqlBytes() ([]byte, error) { + return bindataRead( + _migrations20220909100700Trades_pk_to_bigintSql, + "migrations/20220909100700-trades_pk_to_bigint.sql", + ) +} + +func migrations20220909100700Trades_pk_to_bigintSql() (*asset, error) { + bytes, err := migrations20220909100700Trades_pk_to_bigintSqlBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "migrations/20220909100700-trades_pk_to_bigint.sql", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} + a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xef, 0x7e, 0x21, 0xaf, 0xf, 0xb, 0x48, 0x35, 0x40, 0x5d, 0xbb, 0xb7, 0xa7, 0x64, 0x32, 0x67, 0xba, 0xfa, 0xea, 0xcb, 0x51, 0x28, 0x33, 0x99, 0x8c, 0xbc, 0x77, 0xd3, 0xd3, 0xf6, 0x3d, 0xc6}} + return a, nil +} + // Asset loads and returns the asset for the given name. // It returns an error if the asset could not be found or // could not be loaded. @@ -379,19 +400,18 @@ var _bindata = map[string]func() (*asset, error){ "migrations/20190411165735-data_seed_and_indices.sql": migrations20190411165735Data_seed_and_indicesSql, "migrations/20190425110313-add_orderbook_stats.sql": migrations20190425110313Add_orderbook_statsSql, "migrations/20190426092321-add_aggregated_orderbook_view.sql": migrations20190426092321Add_aggregated_orderbook_viewSql, + "migrations/20220909100700-trades_pk_to_bigint.sql": migrations20220909100700Trades_pk_to_bigintSql, } // AssetDir returns the file names below a certain // directory embedded in the file by go-bindata. // For example if you run go-bindata on data/... and data contains the // following hierarchy: -// -// data/ -// foo.txt -// img/ -// a.png -// b.png -// +// data/ +// foo.txt +// img/ +// a.png +// b.png // then AssetDir("data") would return []string{"foo.txt", "img"}, // AssetDir("data/img") would return []string{"a.png", "b.png"}, // AssetDir("foo.txt") and AssetDir("notexist") would return an error, and @@ -435,6 +455,7 @@ var _bintree = &bintree{nil, map[string]*bintree{ "20190411165735-data_seed_and_indices.sql": &bintree{migrations20190411165735Data_seed_and_indicesSql, map[string]*bintree{}}, "20190425110313-add_orderbook_stats.sql": &bintree{migrations20190425110313Add_orderbook_statsSql, map[string]*bintree{}}, "20190426092321-add_aggregated_orderbook_view.sql": &bintree{migrations20190426092321Add_aggregated_orderbook_viewSql, map[string]*bintree{}}, + "20220909100700-trades_pk_to_bigint.sql": &bintree{migrations20220909100700Trades_pk_to_bigintSql, map[string]*bintree{}}, }}, }} diff --git a/services/ticker/internal/tickerdb/queries_asset_test.go b/services/ticker/internal/tickerdb/queries_asset_test.go index c6d53a2249..3bff69caa5 100644 --- a/services/ticker/internal/tickerdb/queries_asset_test.go +++ b/services/ticker/internal/tickerdb/queries_asset_test.go @@ -7,13 +7,12 @@ import ( _ "github.com/lib/pq" migrate "github.com/rubenv/sql-migrate" - "github.com/stellar/go/support/db/dbtest" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) func TestInsertOrUpdateAsset(t *testing.T) { - db := dbtest.Postgres(t) + db := OpenTestDBConnection(t) defer db.Close() var session TickerSession @@ -157,7 +156,7 @@ func TestInsertOrUpdateAsset(t *testing.T) { } func TestGetAssetByCodeAndIssuerAccount(t *testing.T) { - db := dbtest.Postgres(t) + db := OpenTestDBConnection(t) defer db.Close() var session TickerSession diff --git a/services/ticker/internal/tickerdb/queries_issuer_test.go b/services/ticker/internal/tickerdb/queries_issuer_test.go index f4400e497b..eaf236dfba 100644 --- a/services/ticker/internal/tickerdb/queries_issuer_test.go +++ b/services/ticker/internal/tickerdb/queries_issuer_test.go @@ -6,13 +6,12 @@ import ( _ "github.com/lib/pq" migrate "github.com/rubenv/sql-migrate" - "github.com/stellar/go/support/db/dbtest" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) func TestInsertOrUpdateIssuer(t *testing.T) { - db := dbtest.Postgres(t) + db := OpenTestDBConnection(t) defer db.Close() var session TickerSession diff --git a/services/ticker/internal/tickerdb/queries_market.go b/services/ticker/internal/tickerdb/queries_market.go index 8984fcb3eb..d0121cdeac 100644 --- a/services/ticker/internal/tickerdb/queries_market.go +++ b/services/ticker/internal/tickerdb/queries_market.go @@ -23,8 +23,8 @@ func (s *TickerSession) RetrievePartialAggMarkets(ctx context.Context, sqlTrue := new(string) *sqlTrue = "TRUE" optVars := []optionalVar{ - optionalVar{"bAsset.is_valid", sqlTrue}, - optionalVar{"cAsset.is_valid", sqlTrue}, + {"bAsset.is_valid", sqlTrue}, + {"cAsset.is_valid", sqlTrue}, } // parse base and asset codes and add them as SQL parameters @@ -34,8 +34,8 @@ func (s *TickerSession) RetrievePartialAggMarkets(ctx context.Context, return } optVars = append(optVars, []optionalVar{ - optionalVar{"bAsset.code", &bCode}, - optionalVar{"cAsset.code", &cCode}, + {"bAsset.code", &bCode}, + {"cAsset.code", &cCode}, }...) } @@ -70,12 +70,12 @@ func (s *TickerSession) RetrievePartialMarkets(ctx context.Context, *sqlTrue = "TRUE" where, args := generateWhereClause([]optionalVar{ - optionalVar{"bAsset.is_valid", sqlTrue}, - optionalVar{"cAsset.is_valid", sqlTrue}, - optionalVar{"bAsset.code", baseAssetCode}, - optionalVar{"bAsset.issuer_account", baseAssetIssuer}, - optionalVar{"cAsset.code", counterAssetCode}, - optionalVar{"cAsset.issuer_account", counterAssetIssuer}, + {"bAsset.is_valid", sqlTrue}, + {"cAsset.is_valid", sqlTrue}, + {"bAsset.code", baseAssetCode}, + {"bAsset.issuer_account", baseAssetIssuer}, + {"cAsset.code", counterAssetCode}, + {"cAsset.issuer_account", counterAssetIssuer}, }) where += fmt.Sprintf( " AND t.ledger_close_time > now() - interval '%d hours'", diff --git a/services/ticker/internal/tickerdb/queries_market_test.go b/services/ticker/internal/tickerdb/queries_market_test.go index 65a9df2e47..727a659dd7 100644 --- a/services/ticker/internal/tickerdb/queries_market_test.go +++ b/services/ticker/internal/tickerdb/queries_market_test.go @@ -8,13 +8,12 @@ import ( "time" migrate "github.com/rubenv/sql-migrate" - "github.com/stellar/go/support/db/dbtest" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) func TestRetrieveMarketData(t *testing.T) { - db := dbtest.Postgres(t) + db := OpenTestDBConnection(t) defer db.Close() var session TickerSession @@ -107,7 +106,7 @@ func TestRetrieveMarketData(t *testing.T) { // Now let's create the trades: trades := []Trade{ - Trade{ // XLM_BTC trade + { // XLM_BTC trade HorizonID: "hrzid1", BaseAssetID: xlmAsset.ID, BaseAmount: 100.0, @@ -116,7 +115,7 @@ func TestRetrieveMarketData(t *testing.T) { Price: 0.1, LedgerCloseTime: now, }, - Trade{ // XLM_ETH trade + { // XLM_ETH trade HorizonID: "hrzid3", BaseAssetID: xlmAsset.ID, BaseAmount: 24.0, @@ -125,7 +124,7 @@ func TestRetrieveMarketData(t *testing.T) { Price: 0.92, LedgerCloseTime: oneHourAgo, }, - Trade{ // XLM_ETH trade + { // XLM_ETH trade HorizonID: "hrzid2", BaseAssetID: xlmAsset.ID, BaseAmount: 50.0, @@ -134,7 +133,7 @@ func TestRetrieveMarketData(t *testing.T) { Price: 1.0, LedgerCloseTime: now, }, - Trade{ // XLM_BTC trade + { // XLM_BTC trade HorizonID: "hrzid4", BaseAssetID: xlmAsset.ID, BaseAmount: 50.0, @@ -143,7 +142,7 @@ func TestRetrieveMarketData(t *testing.T) { Price: 0.12, LedgerCloseTime: threeDaysAgo, }, - Trade{ // XLM_ETH trade + { // XLM_ETH trade HorizonID: "hrzid5", BaseAssetID: xlmAsset.ID, BaseAmount: 24.0, @@ -286,7 +285,7 @@ func TestRetrieveMarketData(t *testing.T) { assert.Equal(t, priceChange24hDiff, priceChange7dDiff) - // Analysing aggregated orderbook data: + // Analyzing aggregated orderbook data: assert.Equal(t, 15, xlmethMkt.NumBids) assert.Equal(t, 0.15, xlmethMkt.BidVolume) assert.Equal(t, 200.0, xlmethMkt.HighestBid) @@ -303,7 +302,7 @@ func TestRetrieveMarketData(t *testing.T) { } func TestRetrievePartialMarkets(t *testing.T) { - db := dbtest.Postgres(t) + db := OpenTestDBConnection(t) defer db.Close() var session TickerSession @@ -417,7 +416,7 @@ func TestRetrievePartialMarkets(t *testing.T) { // Now let's create the trades: trades := []Trade{ - Trade{ // BTC_ETH trade (ETH is from issuer 1) + { // BTC_ETH trade (ETH is from issuer 1) HorizonID: "hrzid1", BaseAssetID: btcAsset.ID, BaseAmount: 100.0, @@ -426,7 +425,7 @@ func TestRetrievePartialMarkets(t *testing.T) { Price: 0.1, LedgerCloseTime: tenMinutesAgo, }, - Trade{ // BTC_ETH trade (ETH is from issuer 2) + { // BTC_ETH trade (ETH is from issuer 2) HorizonID: "hrzid3", BaseAssetID: btcAsset.ID, BaseAmount: 24.0, @@ -435,7 +434,7 @@ func TestRetrievePartialMarkets(t *testing.T) { Price: 0.92, LedgerCloseTime: now, }, - Trade{ // BTC_ETH trade (ETH is from issuer 1) + { // BTC_ETH trade (ETH is from issuer 1) HorizonID: "hrzid2", BaseAssetID: btcAsset.ID, BaseAmount: 50.0, @@ -444,7 +443,7 @@ func TestRetrievePartialMarkets(t *testing.T) { Price: 1.0, LedgerCloseTime: oneHourAgo, }, - Trade{ // BTC_ETH trade (ETH is from issuer 1) + { // BTC_ETH trade (ETH is from issuer 1) HorizonID: "hrzid4", BaseAssetID: btcAsset.ID, BaseAmount: 50.0, @@ -618,7 +617,7 @@ func TestRetrievePartialMarkets(t *testing.T) { } func Test24hStatsFallback(t *testing.T) { - db := dbtest.Postgres(t) + db := OpenTestDBConnection(t) defer db.Close() var session TickerSession @@ -689,7 +688,7 @@ func Test24hStatsFallback(t *testing.T) { // Now let's create the trades: trades := []Trade{ - Trade{ + { HorizonID: "hrzid1", BaseAssetID: xlmAsset.ID, BaseAmount: 1.0, @@ -698,7 +697,7 @@ func Test24hStatsFallback(t *testing.T) { Price: 0.5, // close price & lowest price LedgerCloseTime: twoDaysAgo, }, - Trade{ // BTC_ETH trade (ETH is from issuer 2) + { // BTC_ETH trade (ETH is from issuer 2) HorizonID: "hrzid2", BaseAssetID: xlmAsset.ID, BaseAmount: 1.0, @@ -724,7 +723,7 @@ func Test24hStatsFallback(t *testing.T) { } func TestPreferAnchorAssetCode(t *testing.T) { - db := dbtest.Postgres(t) + db := OpenTestDBConnection(t) defer db.Close() var session TickerSession @@ -796,7 +795,7 @@ func TestPreferAnchorAssetCode(t *testing.T) { // Now let's create the trades: trades := []Trade{ - Trade{ + { HorizonID: "hrzid1", BaseAssetID: xlmAsset.ID, BaseAmount: 1.0, @@ -805,7 +804,7 @@ func TestPreferAnchorAssetCode(t *testing.T) { Price: 0.5, // close price & lowest price LedgerCloseTime: twoDaysAgo, }, - Trade{ // BTC_ETH trade (ETH is from issuer 2) + { // BTC_ETH trade (ETH is from issuer 2) HorizonID: "hrzid2", BaseAssetID: xlmAsset.ID, BaseAmount: 1.0, diff --git a/services/ticker/internal/tickerdb/queries_orderbook_test.go b/services/ticker/internal/tickerdb/queries_orderbook_test.go index b3c9344f0b..855d9511aa 100644 --- a/services/ticker/internal/tickerdb/queries_orderbook_test.go +++ b/services/ticker/internal/tickerdb/queries_orderbook_test.go @@ -6,13 +6,12 @@ import ( "time" migrate "github.com/rubenv/sql-migrate" - "github.com/stellar/go/support/db/dbtest" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) func TestInsertOrUpdateOrderbokStats(t *testing.T) { - db := dbtest.Postgres(t) + db := OpenTestDBConnection(t) defer db.Close() var session TickerSession diff --git a/services/ticker/internal/tickerdb/queries_trade_test.go b/services/ticker/internal/tickerdb/queries_trade_test.go index 51b67dff8c..c24717261b 100644 --- a/services/ticker/internal/tickerdb/queries_trade_test.go +++ b/services/ticker/internal/tickerdb/queries_trade_test.go @@ -9,12 +9,11 @@ import ( _ "github.com/lib/pq" migrate "github.com/rubenv/sql-migrate" - "github.com/stellar/go/support/db/dbtest" "github.com/stretchr/testify/require" ) func TestBulkInsertTrades(t *testing.T) { - db := dbtest.Postgres(t) + db := OpenTestDBConnection(t) defer db.Close() var session TickerSession @@ -81,13 +80,13 @@ func TestBulkInsertTrades(t *testing.T) { // Now let's create the trades: trades := []Trade{ - Trade{ + { HorizonID: "hrzid1", BaseAssetID: asset1.ID, CounterAssetID: asset2.ID, LedgerCloseTime: time.Now(), }, - Trade{ + { HorizonID: "hrzid2", BaseAssetID: asset2.ID, CounterAssetID: asset1.ID, @@ -120,7 +119,7 @@ func TestBulkInsertTrades(t *testing.T) { } func TestGetLastTrade(t *testing.T) { - db := dbtest.Postgres(t) + db := OpenTestDBConnection(t) defer db.Close() var session TickerSession @@ -194,19 +193,19 @@ func TestGetLastTrade(t *testing.T) { // Now let's create the trades: trades := []Trade{ - Trade{ + { HorizonID: "hrzid2", BaseAssetID: asset2.ID, CounterAssetID: asset1.ID, LedgerCloseTime: oneYearBefore, }, - Trade{ + { HorizonID: "hrzid1", BaseAssetID: asset1.ID, CounterAssetID: asset2.ID, LedgerCloseTime: now, }, - Trade{ + { HorizonID: "hrzid2", BaseAssetID: asset2.ID, CounterAssetID: asset1.ID, @@ -224,7 +223,7 @@ func TestGetLastTrade(t *testing.T) { } func TestDeleteOldTrades(t *testing.T) { - db := dbtest.Postgres(t) + db := OpenTestDBConnection(t) defer db.Close() var session TickerSession @@ -297,25 +296,25 @@ func TestDeleteOldTrades(t *testing.T) { // Now let's create the trades: trades := []Trade{ - Trade{ + { HorizonID: "hrzid1", BaseAssetID: asset1.ID, CounterAssetID: asset2.ID, LedgerCloseTime: now, }, - Trade{ + { HorizonID: "hrzid2", BaseAssetID: asset2.ID, CounterAssetID: asset1.ID, LedgerCloseTime: oneDayAgo, }, - Trade{ + { HorizonID: "hrzid3", BaseAssetID: asset2.ID, CounterAssetID: asset1.ID, LedgerCloseTime: oneMonthAgo, }, - Trade{ + { HorizonID: "hrzid4", BaseAssetID: asset2.ID, CounterAssetID: asset1.ID, diff --git a/services/ticker/internal/tickerdb/tickerdbtest/tickerdbtest.go b/services/ticker/internal/tickerdb/tickerdbtest/tickerdbtest.go index 34bebb6602..0160b409f8 100644 --- a/services/ticker/internal/tickerdb/tickerdbtest/tickerdbtest.go +++ b/services/ticker/internal/tickerdb/tickerdbtest/tickerdbtest.go @@ -7,7 +7,6 @@ import ( migrate "github.com/rubenv/sql-migrate" "github.com/stellar/go/services/ticker/internal/tickerdb" - "github.com/stellar/go/support/db/dbtest" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -15,7 +14,7 @@ import ( // SetupTickerTestSession sets up the database for testing the GraphQL endpoints // and associated query logic. func SetupTickerTestSession(t *testing.T, migrationsDir string) (session tickerdb.TickerSession) { - db := dbtest.Postgres(t) + db := tickerdb.OpenTestDBConnection(t) session.DB = db.Open() ctx := context.Background() @@ -129,7 +128,7 @@ func SetupTickerTestSession(t *testing.T, migrationsDir string) (session tickerd // Now let's create the trades: trades := []tickerdb.Trade{ - tickerdb.Trade{ // BTC_ETH trade (ETH is from issuer 1) + { // BTC_ETH trade (ETH is from issuer 1) HorizonID: "hrzid1", BaseAssetID: btcAsset.ID, BaseAmount: 100.0, @@ -138,7 +137,7 @@ func SetupTickerTestSession(t *testing.T, migrationsDir string) (session tickerd Price: 0.1, LedgerCloseTime: tenMinutesAgo, }, - tickerdb.Trade{ // BTC_ETH trade (ETH is from issuer 2) + { // BTC_ETH trade (ETH is from issuer 2) HorizonID: "hrzid3", BaseAssetID: btcAsset.ID, BaseAmount: 24.0, @@ -147,7 +146,7 @@ func SetupTickerTestSession(t *testing.T, migrationsDir string) (session tickerd Price: 0.92, LedgerCloseTime: now, }, - tickerdb.Trade{ // BTC_ETH trade (ETH is from issuer 1) + { // BTC_ETH trade (ETH is from issuer 1) HorizonID: "hrzid2", BaseAssetID: btcAsset.ID, BaseAmount: 50.0, @@ -156,7 +155,7 @@ func SetupTickerTestSession(t *testing.T, migrationsDir string) (session tickerd Price: 1.0, LedgerCloseTime: oneHourAgo, }, - tickerdb.Trade{ // BTC_ETH trade (ETH is from issuer 1) + { // BTC_ETH trade (ETH is from issuer 1) HorizonID: "hrzid4", BaseAssetID: btcAsset.ID, BaseAmount: 50.0, @@ -304,7 +303,7 @@ func SetupTickerTestSession(t *testing.T, migrationsDir string) (session tickerd // Add XLM/BTC trades. trades = []tickerdb.Trade{ - tickerdb.Trade{ + { HorizonID: "hrzid5", BaseAssetID: xlmAsset.ID, BaseAmount: 10.0, @@ -313,7 +312,7 @@ func SetupTickerTestSession(t *testing.T, migrationsDir string) (session tickerd Price: 0.5, // close price & lowest price LedgerCloseTime: tenMinutesAgo, }, - tickerdb.Trade{ + { HorizonID: "hrzid6", BaseAssetID: xlmAsset.ID, BaseAmount: 10.0, diff --git a/staticcheck.sh b/staticcheck.sh index 139ccb6e45..539641a4b3 100755 --- a/staticcheck.sh +++ b/staticcheck.sh @@ -1,7 +1,7 @@ #! /bin/bash set -e -version='2022.1' +version='2023.1.1' staticcheck='go run honnef.co/go/tools/cmd/staticcheck@'"$version" diff --git a/strkey/decode_test.go b/strkey/decode_test.go index 2637bcbe1c..ba17bef045 100644 --- a/strkey/decode_test.go +++ b/strkey/decode_test.go @@ -88,11 +88,22 @@ func TestDecode(t *testing.T) { 0x00, 0x00, 0x00, }, }, + { + Name: "Contract", + ExpectedVersionByte: VersionByteContract, + ExpectedPayload: []byte{ + 0x3f, 0x0c, 0x34, 0xbf, 0x93, 0xad, 0x0d, 0x99, + 0x71, 0xd0, 0x4c, 0xcc, 0x90, 0xf7, 0x05, 0x51, + 0x1c, 0x83, 0x8a, 0xad, 0x97, 0x34, 0xa4, 0xa2, + 0xfb, 0x0d, 0x7a, 0x03, 0xfc, 0x7f, 0xe8, 0x9a, + }, + Address: "CA7QYNF7SOWQ3GLR2BGMZEHXAVIRZA4KVWLTJJFC7MGXUA74P7UJUWDA", + }, } for _, kase := range cases { payload, err := Decode(kase.ExpectedVersionByte, kase.Address) - if assert.NoError(t, err, "An error occured decoding case %s", kase.Name) { + if assert.NoError(t, err, "An error occurred decoding case %s", kase.Name) { assert.Equal(t, kase.ExpectedPayload, payload, "Output mismatch in case %s", kase.Name) } } diff --git a/strkey/encode_test.go b/strkey/encode_test.go index 2326f54279..1a60e47be8 100644 --- a/strkey/encode_test.go +++ b/strkey/encode_test.go @@ -89,11 +89,22 @@ func TestEncode(t *testing.T) { }, Expected: "PA3D5KRYM6CB7OWQ6TWYRR3Z4T7GNZLKERYNZGGA5SOAOPIFY6YQGAAAAAEQAAAAAAAAAAAAAAAAAABBXA", }, + { + Name: "Contract", + VersionByte: VersionByteContract, + Payload: []byte{ + 0x3f, 0x0c, 0x34, 0xbf, 0x93, 0xad, 0x0d, 0x99, + 0x71, 0xd0, 0x4c, 0xcc, 0x90, 0xf7, 0x05, 0x51, + 0x1c, 0x83, 0x8a, 0xad, 0x97, 0x34, 0xa4, 0xa2, + 0xfb, 0x0d, 0x7a, 0x03, 0xfc, 0x7f, 0xe8, 0x9a, + }, + Expected: "CA7QYNF7SOWQ3GLR2BGMZEHXAVIRZA4KVWLTJJFC7MGXUA74P7UJUWDA", + }, } for _, kase := range cases { actual, err := Encode(kase.VersionByte, kase.Payload) - if assert.NoError(t, err, "An error occured in case %s", kase.Name) { + if assert.NoError(t, err, "An error occurred in case %s", kase.Name) { assert.Equal(t, kase.Expected, actual, "Output mismatch in case %s", kase.Name) } } diff --git a/strkey/main.go b/strkey/main.go index 63a596b4fc..591f7bf7af 100644 --- a/strkey/main.go +++ b/strkey/main.go @@ -24,7 +24,7 @@ const ( //VersionByteSeed is the version byte used for encoded stellar seed VersionByteSeed = 18 << 3 // Base32-encodes to 'S...' - //VersionByteMuxedAccounts is the version byte used for encoded stellar multiplexed addresses + //VersionByteMuxedAccount is the version byte used for encoded stellar multiplexed addresses VersionByteMuxedAccount = 12 << 3 // Base32-encodes to 'M...' //VersionByteHashTx is the version byte used for encoded stellar hashTx @@ -38,6 +38,9 @@ const ( //VersionByteSignedPayload is the version byte used for encoding "signed //payload" (CAP-40) signer keys. VersionByteSignedPayload = 15 << 3 // Base-32 encodes to 'P' + + //VersionByteContract is the version byte used for encoded stellar contracts + VersionByteContract = 2 << 3 // Base-32 encodes to 'C' ) // maxPayloadSize is the maximum length of the payload for all versions. The @@ -188,7 +191,7 @@ func Version(src string) (VersionByte, error) { // is not one of the defined valid version byte constants. func checkValidVersionByte(version VersionByte) error { switch version { - case VersionByteAccountID, VersionByteMuxedAccount, VersionByteSeed, VersionByteHashTx, VersionByteHashX, VersionByteSignedPayload: + case VersionByteAccountID, VersionByteMuxedAccount, VersionByteSeed, VersionByteHashTx, VersionByteHashX, VersionByteSignedPayload, VersionByteContract: return nil default: return ErrInvalidVersionByte diff --git a/strkey/main_test.go b/strkey/main_test.go index 0f4d14c5e5..ae4ea70477 100644 --- a/strkey/main_test.go +++ b/strkey/main_test.go @@ -46,11 +46,16 @@ func TestVersion(t *testing.T) { Address: "PDPYP7E6NEYZSVOTV6M23OFM2XRIMPDUJABHGHHH2Y67X7JL25GW6AAAAAAAAAAAAAAJEVA", ExpectedVersionByte: VersionByteSignedPayload, }, + { + Name: "Contract", + Address: "CA7QYNF7SOWQ3GLR2BGMZEHXAVIRZA4KVWLTJJFC7MGXUA74P7UJUWDA", + ExpectedVersionByte: VersionByteContract, + }, } for _, kase := range cases { actual, err := Version(kase.Address) - if assert.NoError(t, err, "An error occured decoding case %s", kase.Name) { + if assert.NoError(t, err, "An error occurred decoding case %s", kase.Name) { assert.Equal(t, kase.ExpectedVersionByte, actual, "Output mismatch in case %s", kase.Name) } } diff --git a/support/config/config_option.go b/support/config/config_option.go index 6c6ab72d8f..97df9ef956 100644 --- a/support/config/config_option.go +++ b/support/config/config_option.go @@ -23,10 +23,10 @@ type ConfigOptions []*ConfigOption // Init calls Init on each ConfigOption passing on the cobra.Command. func (cos ConfigOptions) Init(cmd *cobra.Command) error { for _, co := range cos { - err := co.Init(cmd) - if err != nil { + if err := co.Init(cmd); err != nil { return err } + co.SetDeprecated(cmd) } return nil } @@ -58,6 +58,17 @@ func (cos ConfigOptions) SetValues() error { return nil } +// GetCommandLineFlagsPassedByUser returns a list of command-line flags that were passed by the user when running Horizon. +func (cos ConfigOptions) GetCommandLineFlagsPassedByUser() []string { + var flagsPassedByUser []string + for _, co := range cos { + if co.flag.Changed { + flagsPassedByUser = append(flagsPassedByUser, co.flag.Name) + } + } + return flagsPassedByUser +} + // ConfigOption is a complete description of the configuration of a command line option type ConfigOption struct { Name string // e.g. "db-url" @@ -69,6 +80,8 @@ type ConfigOption struct { CustomSetValue func(*ConfigOption) error // Optional function for custom validation/transformation ConfigKey interface{} // Pointer to the final key in the linked Config struct flag *pflag.Flag // The persistent flag that the config option is attached to + Hidden bool // Indicates whether to hide the flag from --help output + UsedInCommands []string // the list of sub-comands this flag is relevant in } // Init handles initialisation steps, including configuring and binding the env variable name. @@ -82,6 +95,19 @@ func (co *ConfigOption) Init(cmd *cobra.Command) error { return co.setFlag(cmd) } +// SetDeprecated Hides the deprecated flag from --help output +func (co *ConfigOption) SetDeprecated(cmd *cobra.Command) { + if co.Hidden { + co.ToggleHidden(true) + } +} + +// ToggleHidden sets the hidden attibute on the persistent flag associated to +// this config option +func (co *ConfigOption) ToggleHidden(hidden bool) { + co.flag.Hidden = hidden +} + // Bind binds the config option to viper. func (co *ConfigOption) Bind() { viper.BindPFlag(co.Name, co.flag) @@ -181,6 +207,12 @@ func SetDuration(co *ConfigOption) error { return nil } +// SetDurationMinutes converts a command line minutes value to a duration, and stores it in the final config. +func SetDurationMinutes(co *ConfigOption) error { + *(co.ConfigKey.(*time.Duration)) = time.Duration(viper.GetInt(co.Name)) * time.Minute + return nil +} + // SetURL converts a command line string to a URL, and stores it in the final config. func SetURL(co *ConfigOption) error { urlString := viper.GetString(co.Name) diff --git a/support/contractevents/burn.go b/support/contractevents/burn.go new file mode 100644 index 0000000000..33022fb7dc --- /dev/null +++ b/support/contractevents/burn.go @@ -0,0 +1,57 @@ +package contractevents + +import ( + "github.com/stellar/go/support/errors" + "github.com/stellar/go/xdr" +) + +var ErrNotBurnEvent = errors.New("event is not a valid 'burn' event") + +type BurnEvent struct { + sacEvent + + From string + Amount xdr.Int128Parts +} + +// parseBurnEvent tries to parse the given topics and value as a SAC "burn" +// event. +// +// Internally, it assumes that the `topics` array has already validated both the +// function name AND the asset <--> contract ID relationship. It will return a +// best-effort parsing even in error cases. +func (event *BurnEvent) parse(topics xdr.ScVec, value xdr.ScVal) error { + // + // The burn event format is: + // + // "burn" Symbol + // Address + // Bytes + // + // i128 + // + // Reference: https://github.com/stellar/rs-soroban-env/blob/main/soroban-env-host/src/native_contract/token/event.rs#L102-L109 + // + if len(topics) != 3 { + return ErrNotBurnEvent + } + + from, ok := topics[1].GetAddress() + if !ok { + return ErrNotBurnEvent + } + + var err error + event.From, err = from.String() + if err != nil { + return errors.Wrap(err, ErrNotBurnEvent.Error()) + } + + amount, ok := value.GetI128() + if !ok { + return ErrNotBurnEvent + } + event.Amount = amount + + return nil +} diff --git a/support/contractevents/clawback.go b/support/contractevents/clawback.go new file mode 100644 index 0000000000..847c619d88 --- /dev/null +++ b/support/contractevents/clawback.go @@ -0,0 +1,41 @@ +package contractevents + +import ( + "github.com/stellar/go/support/errors" + "github.com/stellar/go/xdr" +) + +var ErrNotClawbackEvent = errors.New("event is not a valid 'clawback' event") + +type ClawbackEvent struct { + sacEvent + + Admin string + From string + Amount xdr.Int128Parts +} + +// parseClawbackEvent tries to parse the given topics and value as a SAC +// "clawback" event. +// +// Internally, it assumes that the `topics` array has already validated both the +// function name AND the asset <--> contract ID relationship. It will return a +// best-effort parsing even in error cases. +func (event *ClawbackEvent) parse(topics xdr.ScVec, value xdr.ScVal) error { + // + // The clawback event format is: + // + // "clawback" Symbol + // Address + // Address + // Bytes + // + // i128 + // + var err error + event.Admin, event.From, event.Amount, err = parseBalanceChangeEvent(topics, value) + if err != nil { + return ErrNotClawbackEvent + } + return nil +} diff --git a/support/contractevents/event.go b/support/contractevents/event.go new file mode 100644 index 0000000000..fbdc595dcc --- /dev/null +++ b/support/contractevents/event.go @@ -0,0 +1,201 @@ +package contractevents + +import ( + "fmt" + "strings" + + "github.com/stellar/go/support/errors" + "github.com/stellar/go/xdr" +) + +type Event = xdr.ContractEvent +type EventType int + +// Note that there is no distinction between transfer() and transfer_from() in events, +// nor the other *_from variants. This is intentional from the host environment. + +const ( + // Implemented + EventTypeTransfer EventType = iota + EventTypeMint + EventTypeClawback + EventTypeBurn + // TODO: Not implemented + EventTypeIncrAllow + EventTypeDecrAllow + EventTypeSetAuthorized + EventTypeSetAdmin +) + +var ( + STELLAR_ASSET_CONTRACT_TOPICS = map[xdr.ScSymbol]EventType{ + xdr.ScSymbol("transfer"): EventTypeTransfer, + xdr.ScSymbol("mint"): EventTypeMint, + xdr.ScSymbol("clawback"): EventTypeClawback, + xdr.ScSymbol("burn"): EventTypeBurn, + } + + ErrNotStellarAssetContract = errors.New("event was not from a Stellar Asset Contract") + ErrEventUnsupported = errors.New("this type of Stellar Asset Contract event is unsupported") + ErrEventIntegrity = errors.New("contract ID doesn't match asset + passphrase") +) + +type StellarAssetContractEvent interface { + GetType() EventType + GetAsset() xdr.Asset +} + +type sacEvent struct { + Type EventType + Asset xdr.Asset +} + +func (e sacEvent) GetAsset() xdr.Asset { + return e.Asset +} + +func (e sacEvent) GetType() EventType { + return e.Type +} + +func NewStellarAssetContractEvent(event *Event, networkPassphrase string) (StellarAssetContractEvent, error) { + evt := &sacEvent{} + + if event.Type != xdr.ContractEventTypeContract || event.ContractId == nil || event.Body.V != 0 { + return evt, ErrNotStellarAssetContract + } + + // SAC event topics take the form //. + // + // For specific event forms, see here: + // https://github.com/stellar/rs-soroban-env/blob/main/soroban-env-host/src/native_contract/token/event.rs#L44-L49 + topics := event.Body.V0.Topics + value := event.Body.V0.Data + + // No relevant SAC events have <= 2 topics + if len(topics) <= 2 { + return evt, ErrNotStellarAssetContract + } + + // Filter out events for function calls we don't care about + fn, ok := topics[0].GetSym() + if !ok { + return evt, ErrNotStellarAssetContract + } + + if eventType, found := STELLAR_ASSET_CONTRACT_TOPICS[fn]; !found { + return evt, ErrNotStellarAssetContract + } else { + evt.Type = eventType + } + + // This looks like a SAC event, but does it act like a SAC event? + // + // To check that, ensure that the contract ID of the event matches the + // contract ID that *would* represent the asset the event is claiming to + // be as included as the last topic in canonical asset encoding. + // + // For all parsing errors, we just continue, since it's not a real error, + // just an event non-complaint with SAC events. + rawAsset := topics[len(topics)-1] + assetSc, ok := rawAsset.GetStr() + if !ok || assetSc == "" { + return evt, ErrNotStellarAssetContract + } + + asset, err := parseCanonicalAsset(string(assetSc)) + if err != nil { + return evt, errors.Wrap(ErrNotStellarAssetContract, err.Error()) + } + + evt.Asset = *asset + expectedId, err := evt.Asset.ContractID(networkPassphrase) + if err != nil { + return evt, errors.Wrap(ErrNotStellarAssetContract, err.Error()) + } + + // This is the DEFINITIVE integrity check for whether or not this is a + // SAC event. At this point, we can parse the event and treat it as + // truth, mapping it to effects where appropriate. + if expectedId != *event.ContractId { // nil check was earlier + return evt, ErrEventIntegrity + } + + switch evt.GetType() { + case EventTypeTransfer: + transferEvent := TransferEvent{sacEvent: *evt} + return &transferEvent, transferEvent.parse(topics, value) + + case EventTypeMint: + mintEvent := MintEvent{sacEvent: *evt} + return &mintEvent, mintEvent.parse(topics, value) + + case EventTypeClawback: + cbEvent := ClawbackEvent{sacEvent: *evt} + return &cbEvent, cbEvent.parse(topics, value) + + case EventTypeBurn: + burnEvent := BurnEvent{sacEvent: *evt} + return &burnEvent, burnEvent.parse(topics, value) + + default: + return evt, errors.Wrapf(ErrEventUnsupported, + "event type %d ('%s') unsupported", evt.Type, fn) + } +} + +func parseCanonicalAsset(assetStr string) (*xdr.Asset, error) { + // The asset is in canonical SEP-11 form: + // https://stellar.org/protocol/sep-11#alphanum4-alphanum12 + // namely, its split by colon, first part is asset code padded to + // exactly 4 or 12 bytes. and second part is issuer encoded + // as strkey + asset := xdr.Asset{ + Type: xdr.AssetTypeAssetTypeNative, + } + + if assetStr == "native" { + return &asset, nil + } + + parts := strings.Split(assetStr, ":") + if len(parts) != 2 { + return nil, errors.New("invalid asset byte format (expected canonical :)") + } + rawCode, rawIssuerKey := parts[0], parts[1] + + issuerKey, err := xdr.AddressToAccountId(rawIssuerKey) + if err != nil { + return nil, errors.New("invalid asset byte format (expected canonical :)") + } + accountId := xdr.AccountId(xdr.PublicKey{ + Type: xdr.PublicKeyTypePublicKeyTypeEd25519, + Ed25519: issuerKey.Ed25519, + }) + + if len(rawCode) <= 4 { + code := [4]byte{} + copy(code[:], rawCode[:]) + + asset.Type = xdr.AssetTypeAssetTypeCreditAlphanum4 + asset.AlphaNum4 = &xdr.AlphaNum4{ + AssetCode: xdr.AssetCode4(code), + Issuer: accountId, + } + } else if len(rawCode) <= 12 { + code := [12]byte{} + copy(code[:], rawCode[:]) + + asset.Type = xdr.AssetTypeAssetTypeCreditAlphanum12 + asset.AlphaNum12 = &xdr.AlphaNum12{ + AssetCode: xdr.AssetCode12(code), + Issuer: accountId, + } + } else { + return nil, fmt.Errorf( + "asset code invalid (expected 4 or 12 bytes, got %d: '%v' or '%s')", + len(rawCode), rawCode, string(rawCode)) + } + + return &asset, nil +} diff --git a/support/contractevents/event_test.go b/support/contractevents/event_test.go new file mode 100644 index 0000000000..c815d1142b --- /dev/null +++ b/support/contractevents/event_test.go @@ -0,0 +1,279 @@ +package contractevents + +import ( + _ "embed" + "math" + "math/big" + "testing" + + "github.com/stellar/go/gxdr" + "github.com/stellar/go/keypair" + "github.com/stellar/go/randxdr" + "github.com/stellar/go/strkey" + "github.com/stellar/go/xdr" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +const passphrase = "passphrase" + +var ( + randomIssuer = keypair.MustRandom() + randomAsset = xdr.MustNewCreditAsset("TESTING", randomIssuer.Address()) + randomAccount = keypair.MustRandom().Address() + zeroContractHash = xdr.Hash([32]byte{}) + zeroContract = strkey.MustEncode(strkey.VersionByteContract, zeroContractHash[:]) +) + +func TestScValCreators(t *testing.T) { + val := makeSymbol("hello") + assert.Equal(t, val.Type, xdr.ScValTypeScvSymbol) + assert.NotNil(t, val.Sym) + assert.EqualValues(t, *val.Sym, "hello") + + val = makeAmount(1234) + amt, ok := val.GetI128() + assert.True(t, ok) + assert.EqualValues(t, 0, amt.Hi) + assert.EqualValues(t, 1234, amt.Lo) + + // make an amount which is 2^65 + 1234 to check both hi and lo parts + amount := big.NewInt(math.MaxInt64) + amount. // this is 2^63-1 + Add(amount, big.NewInt(1)). // 2^63 + Or(amount, big.NewInt(math.MaxInt64)). // 2^64-1 (max uint64) + Lsh(amount, 2). // now it's (2^64 - 1) * 4 = 2^66 - 4 + Add(amount, big.NewInt(1234+4)) // now it's 2^66 + 1234 + + val = makeBigAmount(amount) + amt, ok = val.GetI128() + assert.True(t, ok) + assert.EqualValues(t, 4, amt.Hi) + assert.EqualValues(t, 1234, amt.Lo) +} + +func TestEventGenerator(t *testing.T) { + passphrase := "This is a passphrase." + issuer := keypair.MustRandom().Address() + from, to, admin := issuer, issuer, issuer + + for _, type_ := range []EventType{ + EventTypeTransfer, + EventTypeMint, + EventTypeClawback, + EventTypeBurn, + } { + event := GenerateEvent(type_, from, to, admin, xdr.MustNewNativeAsset(), big.NewInt(12345), passphrase) + parsedEvent, err := NewStellarAssetContractEvent(&event, passphrase) + require.NoErrorf(t, err, "generating an event of type %v failed", type_) + require.Equal(t, type_, parsedEvent.GetType()) + require.Equal(t, xdr.AssetTypeAssetTypeNative, parsedEvent.GetAsset().Type) + + event = GenerateEvent(type_, from, to, admin, + xdr.MustNewCreditAsset("TESTER", issuer), + big.NewInt(12345), passphrase) + parsedEvent, err = NewStellarAssetContractEvent(&event, passphrase) + require.NoErrorf(t, err, "generating an event of type %v failed", type_) + require.Equal(t, type_, parsedEvent.GetType()) + require.Equal(t, xdr.AssetTypeAssetTypeCreditAlphanum12, parsedEvent.GetAsset().Type) + } +} + +func TestSACTransferEvent(t *testing.T) { + xdrEvent := GenerateEvent(EventTypeTransfer, randomAccount, zeroContract, "", randomAsset, big.NewInt(10000), passphrase) + + // Ensure the happy path for transfer events works + sacEvent, err := NewStellarAssetContractEvent(&xdrEvent, passphrase) + require.NoError(t, err) + require.NotNil(t, sacEvent) + require.Equal(t, EventTypeTransfer, sacEvent.GetType()) + + transferEvent := sacEvent.(*TransferEvent) + require.Equal(t, randomAccount, transferEvent.From) + require.Equal(t, zeroContract, transferEvent.To) + require.EqualValues(t, 10000, transferEvent.Amount.Lo) + require.EqualValues(t, 0, transferEvent.Amount.Hi) +} + +func TestSACEventCreation(t *testing.T) { + var xdrEvent xdr.ContractEvent + resetEvent := func(from string, to string, asset xdr.Asset) { + xdrEvent = GenerateEvent(EventTypeTransfer, from, to, "", asset, big.NewInt(10000), passphrase) + } + + // Ensure that changing the passphrase invalidates the event + t.Run("wrong passphrase", func(t *testing.T) { + resetEvent(randomAccount, zeroContract, randomAsset) + _, err := NewStellarAssetContractEvent(&xdrEvent, "different") + require.Error(t, err) + }) + + // Ensure that the native asset still works + t.Run("native transfer", func(t *testing.T) { + resetEvent(randomAccount, zeroContract, xdr.MustNewNativeAsset()) + sacEvent, err := NewStellarAssetContractEvent(&xdrEvent, passphrase) + require.NoError(t, err) + require.Equal(t, xdr.AssetTypeAssetTypeNative, sacEvent.GetAsset().Type) + }) + + // Ensure that invalid asset binaries are rejected + t.Run("bad asset binary", func(t *testing.T) { + resetEvent(randomAccount, zeroContract, randomAsset) + rawBsAsset := xdr.ScString("no bueno") + xdrEvent.Body.V0.Topics[3].Str = &rawBsAsset + _, err := NewStellarAssetContractEvent(&xdrEvent, passphrase) + require.Error(t, err) + }) + + // Ensure that valid asset binaries that mismatch the contract are rejected + t.Run("mismatching ID", func(t *testing.T) { + resetEvent(randomAccount, zeroContract, randomAsset) + // change the ID but keep the asset + rawNativeContractId, err := xdr.MustNewNativeAsset().ContractID(passphrase) + require.NoError(t, err) + nativeContractId := xdr.Hash(rawNativeContractId) + xdrEvent.ContractId = &nativeContractId + _, err = NewStellarAssetContractEvent(&xdrEvent, passphrase) + require.Error(t, err) + + // now change the asset but keep the ID + resetEvent(randomAccount, zeroContract, randomAsset) + diffRandomAsset := xdr.MustNewCreditAsset("TESTING", keypair.MustRandom().Address()) + xdrEvent.Body.V0.Topics = makeTransferTopic(diffRandomAsset) + _, err = NewStellarAssetContractEvent(&xdrEvent, passphrase) + require.Error(t, err) + }) + + // Ensure that system events are rejected + t.Run("system events", func(t *testing.T) { + resetEvent(randomAccount, zeroContract, randomAsset) + xdrEvent.Type = xdr.ContractEventTypeSystem + _, err := NewStellarAssetContractEvent(&xdrEvent, passphrase) + require.Error(t, err) + }) +} + +func TestSACMintEvent(t *testing.T) { + xdrEvent := GenerateEvent(EventTypeMint, "", zeroContract, randomAccount, randomAsset, big.NewInt(10000), passphrase) + + // Ensure the happy path for mint events works + sacEvent, err := NewStellarAssetContractEvent(&xdrEvent, passphrase) + require.NoError(t, err) + require.NotNil(t, sacEvent) + require.Equal(t, EventTypeMint, sacEvent.GetType()) + + mintEvent := sacEvent.(*MintEvent) + require.Equal(t, randomAccount, mintEvent.Admin) + require.Equal(t, zeroContract, mintEvent.To) + require.EqualValues(t, 10000, mintEvent.Amount.Lo) + require.EqualValues(t, 0, mintEvent.Amount.Hi) +} + +func TestSACClawbackEvent(t *testing.T) { + xdrEvent := GenerateEvent(EventTypeClawback, zeroContract, "", randomAccount, randomAsset, big.NewInt(10000), passphrase) + + // Ensure the happy path for clawback events works + sacEvent, err := NewStellarAssetContractEvent(&xdrEvent, passphrase) + require.NoError(t, err) + require.NotNil(t, sacEvent) + require.Equal(t, EventTypeClawback, sacEvent.GetType()) + + clawEvent := sacEvent.(*ClawbackEvent) + require.Equal(t, randomAccount, clawEvent.Admin) + require.Equal(t, zeroContract, clawEvent.From) + require.EqualValues(t, 10000, clawEvent.Amount.Lo) + require.EqualValues(t, 0, clawEvent.Amount.Hi) +} + +func TestSACBurnEvent(t *testing.T) { + xdrEvent := GenerateEvent(EventTypeBurn, randomAccount, "", "", randomAsset, big.NewInt(10000), passphrase) + + // Ensure the happy path for burn events works + sacEvent, err := NewStellarAssetContractEvent(&xdrEvent, passphrase) + require.NoError(t, err) + require.NotNil(t, sacEvent) + require.Equal(t, EventTypeBurn, sacEvent.GetType()) + + burnEvent := sacEvent.(*BurnEvent) + require.Equal(t, randomAccount, burnEvent.From) + require.EqualValues(t, 10000, burnEvent.Amount.Lo) + require.EqualValues(t, 0, burnEvent.Amount.Hi) +} + +func TestFuzzingSACEventParser(t *testing.T) { + gen := randxdr.NewGenerator() + for i := 0; i < 100_000; i++ { + event, shape := xdr.ContractEvent{}, &gxdr.ContractEvent{} + + gen.Next( + shape, + []randxdr.Preset{}, + ) + assert.NoError(t, gxdr.Convert(shape, &event)) + + // return values are ignored, but this should never panic + NewStellarAssetContractEvent(&event, "passphrase") + } +} + +// +// Test suite helpers below +// + +func makeEvent() xdr.ContractEvent { + rawContractId, err := randomAsset.ContractID(passphrase) + if err != nil { + panic(err) + } + contractId := xdr.Hash(rawContractId) + + baseXdrEvent := xdr.ContractEvent{ + Ext: xdr.ExtensionPoint{V: 0}, + ContractId: &contractId, + Type: xdr.ContractEventTypeContract, + Body: xdr.ContractEventBody{ + V: 0, + V0: &xdr.ContractEventV0{}, + }, + } + + return baseXdrEvent +} + +func makeTransferTopic(asset xdr.Asset) xdr.ScVec { + contractStr := strkey.MustEncode(strkey.VersionByteContract, zeroContractHash[:]) + + return xdr.ScVec([]xdr.ScVal{ + makeSymbol("transfer"), // event name + makeAddress(randomAccount), // from + makeAddress(contractStr), // to + makeAsset(asset), // asset details + }) +} + +func makeMintTopic(asset xdr.Asset) xdr.ScVec { + // mint is just transfer but with an admin instead of a from... nice + topics := makeTransferTopic(asset) + topics[0] = makeSymbol("mint") + return topics +} + +func makeClawbackTopic(asset xdr.Asset) xdr.ScVec { + // clawback is just mint but with a from instead of a to + topics := makeTransferTopic(asset) + topics[0] = makeSymbol("clawback") + return topics +} + +func makeBurnTopic(asset xdr.Asset) xdr.ScVec { + // burn is like clawback but without a "to", so we drop that topic + topics := makeTransferTopic(asset) + topics[0] = makeSymbol("burn") + topics = append(topics[:2], topics[3:]...) + return topics +} + +func makeAmount(amount int64) xdr.ScVal { + return makeBigAmount(big.NewInt(amount)) +} diff --git a/support/contractevents/fixtures/transfer_event_xdr.bin b/support/contractevents/fixtures/transfer_event_xdr.bin new file mode 100755 index 0000000000..d5a201b6a5 Binary files /dev/null and b/support/contractevents/fixtures/transfer_event_xdr.bin differ diff --git a/support/contractevents/generate.go b/support/contractevents/generate.go new file mode 100644 index 0000000000..ed4e7da264 --- /dev/null +++ b/support/contractevents/generate.go @@ -0,0 +1,183 @@ +package contractevents + +import ( + "bytes" + "encoding/hex" + "fmt" + "math" + "math/big" + + "github.com/stellar/go/strkey" + "github.com/stellar/go/xdr" +) + +// GenerateEvent is a utility function to be used by testing frameworks in order +// to generate Stellar Asset Contract events. +// +// To provide a generic interface, there are more arguments than apply to the +// type, but you should only expect the relevant ones to be set (for example, +// transfer events have no admin, so it will be ignored). This means you can +// always pass your set of testing parameters, modify the type, and get the +// event filled out with the details you expect. +func GenerateEvent( + type_ EventType, + from, to, admin string, + asset xdr.Asset, + amount *big.Int, + passphrase string, +) xdr.ContractEvent { + var topics []xdr.ScVal + data := makeBigAmount(amount) + + switch type_ { + case EventTypeTransfer: + topics = []xdr.ScVal{ + makeSymbol("transfer"), + makeAddress(from), + makeAddress(to), + makeAsset(asset), + } + + case EventTypeMint: + topics = []xdr.ScVal{ + makeSymbol("mint"), + makeAddress(admin), + makeAddress(to), + makeAsset(asset), + } + + case EventTypeClawback: + topics = []xdr.ScVal{ + makeSymbol("clawback"), + makeAddress(admin), + makeAddress(from), + makeAsset(asset), + } + + case EventTypeBurn: + topics = []xdr.ScVal{ + makeSymbol("burn"), + makeAddress(from), + makeAsset(asset), + } + + default: + panic(fmt.Errorf("event type %v unsupported", type_)) + } + + rawContractId, err := asset.ContractID(passphrase) + if err != nil { + panic(err) + } + contractId := xdr.Hash(rawContractId) + + event := xdr.ContractEvent{ + Type: xdr.ContractEventTypeContract, + ContractId: &contractId, + Body: xdr.ContractEventBody{ + V: 0, + V0: &xdr.ContractEventV0{ + Topics: xdr.ScVec(topics), + Data: data, + }, + }, + } + + return event +} + +func contractIdToHash(contractId string) *xdr.Hash { + idBytes := [32]byte{} + rawBytes, err := hex.DecodeString(contractId) + if err != nil { + panic(fmt.Errorf("invalid contract id (%s): %v", contractId, err)) + } + if copy(idBytes[:], rawBytes[:]) != 32 { + panic("couldn't copy 32 bytes to contract hash") + } + + hash := xdr.Hash(idBytes) + return &hash +} + +func makeSymbol(sym string) xdr.ScVal { + symbol := xdr.ScSymbol(sym) + return xdr.ScVal{ + Type: xdr.ScValTypeScvSymbol, + Sym: &symbol, + } +} + +func makeBigAmount(amount *big.Int) xdr.ScVal { + // TODO: Better check, as MaxUint128 shouldn't be allowed + if amount.BitLen() > 128 { + panic(fmt.Errorf( + "amount is too large: %d bits (max 128)", + amount.BitLen())) + } + + // + // We create the two Uint64 parts as follows: + // + // - take the upper 64 by shifting 64 right + // - take the lower 64 by zeroing the top 64 + // + keepLower := big.NewInt(0).SetUint64(math.MaxUint64) + + hi := new(big.Int).Rsh(amount, 64) + lo := amount.And(amount, keepLower) + + return xdr.ScVal{ + Type: xdr.ScValTypeScvI128, + I128: &xdr.Int128Parts{ + Lo: xdr.Uint64(lo.Uint64()), + Hi: xdr.Int64(hi.Int64()), + }, + } +} + +func makeAddress(address string) xdr.ScVal { + scAddress := xdr.ScAddress{} + + switch address[0] { + case 'C': + scAddress.Type = xdr.ScAddressTypeScAddressTypeContract + contractHash := strkey.MustDecode(strkey.VersionByteContract, address) + scAddress.ContractId = contractIdToHash(hex.EncodeToString(contractHash)) + + case 'G': + scAddress.Type = xdr.ScAddressTypeScAddressTypeAccount + scAddress.AccountId = xdr.MustAddressPtr(address) + + default: + panic(fmt.Errorf("unsupported address: %s", address)) + } + + return xdr.ScVal{ + Type: xdr.ScValTypeScvAddress, + Address: &scAddress, + } +} + +func makeAsset(asset xdr.Asset) xdr.ScVal { + buffer := new(bytes.Buffer) + + switch asset.Type { + case xdr.AssetTypeAssetTypeNative: + _, err := buffer.WriteString("native") + if err != nil { + panic(err) + } + + case xdr.AssetTypeAssetTypeCreditAlphanum4, xdr.AssetTypeAssetTypeCreditAlphanum12: + buffer.WriteString(asset.GetCode() + ":" + asset.GetIssuer()) + default: + panic("unexpected asset type") + } + + assetScStr := xdr.ScString(buffer.String()) + return xdr.ScVal{ + Type: xdr.ScValTypeScvString, + Str: &assetScStr, + } +} diff --git a/support/contractevents/mint.go b/support/contractevents/mint.go new file mode 100644 index 0000000000..a2c72be2fc --- /dev/null +++ b/support/contractevents/mint.go @@ -0,0 +1,41 @@ +package contractevents + +import ( + "github.com/stellar/go/support/errors" + "github.com/stellar/go/xdr" +) + +var ErrNotMintEvent = errors.New("event is not a valid 'mint' event") + +type MintEvent struct { + sacEvent + + Admin string + To string + Amount xdr.Int128Parts +} + +// parseMintEvent tries to parse the given topics and value as a SAC "mint" +// event. +// +// Internally, it assumes that the `topics` array has already validated both the +// function name AND the asset <--> contract ID relationship. It will return a +// best-effort parsing even in error cases. +func (event *MintEvent) parse(topics xdr.ScVec, value xdr.ScVal) error { + // + // The mint event format is: + // + // "mint" Symbol + // Address + // Address + // Bytes + // + // i128 + // + var err error + event.Admin, event.To, event.Amount, err = parseBalanceChangeEvent(topics, value) + if err != nil { + return ErrNotMintEvent + } + return nil +} diff --git a/support/contractevents/transfer.go b/support/contractevents/transfer.go new file mode 100644 index 0000000000..23c8896cc3 --- /dev/null +++ b/support/contractevents/transfer.go @@ -0,0 +1,41 @@ +package contractevents + +import ( + "github.com/stellar/go/support/errors" + "github.com/stellar/go/xdr" +) + +var ErrNotTransferEvent = errors.New("event is not a valid 'transfer' event") + +type TransferEvent struct { + sacEvent + + From string + To string + Amount xdr.Int128Parts +} + +// parseTransferEvent tries to parse the given topics and value as a SAC +// "transfer" event. +// +// Internally, it assumes that the `topics` array has already validated both the +// function name AND the asset <--> contract ID relationship. It will return a +// best-effort parsing even in error cases. +func (event *TransferEvent) parse(topics xdr.ScVec, value xdr.ScVal) error { + // + // The transfer event format is: + // + // "transfer" Symbol + // Address + // Address + // Bytes + // + // i128 + // + var err error + event.From, event.To, event.Amount, err = parseBalanceChangeEvent(topics, value) + if err != nil { + return ErrNotTransferEvent + } + return nil +} diff --git a/support/contractevents/utils.go b/support/contractevents/utils.go new file mode 100644 index 0000000000..afd0da86f7 --- /dev/null +++ b/support/contractevents/utils.go @@ -0,0 +1,52 @@ +package contractevents + +import ( + "github.com/stellar/go/support/errors" + "github.com/stellar/go/xdr" +) + +var ErrNotBalanceChangeEvent = errors.New("event doesn't represent a balance change") + +// parseBalanceChangeEvent is a generalization of a subset of the Stellar Asset +// Contract events. Transfer, mint, clawback, and burn events all have two +// addresses and an amount involved. The addresses represent different things in +// different event types (e.g. "from" or "admin"), but the parsing is identical. +// This helper extracts all three parts or returns a generic error if it can't. +func parseBalanceChangeEvent(topics xdr.ScVec, value xdr.ScVal) ( + first string, + second string, + amount xdr.Int128Parts, + err error, +) { + err = ErrNotBalanceChangeEvent + if len(topics) != 4 { + return + } + + firstSc, ok := topics[1].GetAddress() + if !ok { + return + } + first, err = firstSc.String() + if err != nil { + err = errors.Wrap(err, ErrNotBalanceChangeEvent.Error()) + return + } + + secondSc, ok := topics[2].GetAddress() + if !ok { + return + } + second, err = secondSc.String() + if err != nil { + err = errors.Wrap(err, ErrNotBalanceChangeEvent.Error()) + return + } + + amount, ok = value.GetI128() + if !ok { + return + } + + return first, second, amount, nil +} diff --git a/support/db/batch_insert_builder_test.go b/support/db/batch_insert_builder_test.go index e283e8bf57..a7a772757f 100644 --- a/support/db/batch_insert_builder_test.go +++ b/support/db/batch_insert_builder_test.go @@ -13,6 +13,7 @@ import ( type hungerRow struct { Name string `db:"name"` HungerLevel string `db:"hunger_level"` + JsonValue string `db:"json_value"` } type invalidHungerRow struct { diff --git a/support/db/dbtest/db.go b/support/db/dbtest/db.go index 2791257022..2caf1fee6a 100644 --- a/support/db/dbtest/db.go +++ b/support/db/dbtest/db.go @@ -150,9 +150,13 @@ func Postgres(t testing.TB) *DB { if len(pgUser) == 0 { pgUser = "postgres" } + pgPwd := os.Getenv("PGPASSWORD") + if len(pgPwd) == 0 { + pgPwd = "postgres" + } - postgresDSN := fmt.Sprintf("postgres://%s@localhost/?sslmode=disable", pgUser) - result.DSN = fmt.Sprintf("postgres://%s@localhost/%s?sslmode=disable&timezone=UTC", pgUser, result.dbName) + postgresDSN := fmt.Sprintf("postgres://%s:%s@localhost/?sslmode=disable", pgUser, pgPwd) + result.DSN = fmt.Sprintf("postgres://%s:%s@localhost/%s?sslmode=disable&timezone=UTC", pgUser, pgPwd, result.dbName) result.RO_DSN = fmt.Sprintf("postgres://%s:%s@localhost/%s?sslmode=disable&timezone=UTC", "user_ro", "user_ro", result.dbName) execStatement(t, fmt.Sprintf("CREATE DATABASE %s;", result.dbName), postgresDSN) diff --git a/support/db/fast_batch_insert_builder.go b/support/db/fast_batch_insert_builder.go new file mode 100644 index 0000000000..ec235ee31d --- /dev/null +++ b/support/db/fast_batch_insert_builder.go @@ -0,0 +1,150 @@ +package db + +import ( + "context" + "reflect" + "sort" + + "github.com/lib/pq" + + "github.com/stellar/go/support/errors" +) + +// ErrSealed is returned when trying to add rows to the FastBatchInsertBuilder after Exec() is called. +// Once Exec() is called no more rows can be added to the FastBatchInsertBuilder unless you call Reset() +// which clears out the old rows from the FastBatchInsertBuilder. +var ErrSealed = errors.New("cannot add more rows after Exec() without calling Reset() first") + +// ErrNoTx is returned when Exec() is called outside of a transaction. +var ErrNoTx = errors.New("cannot call Exec() outside of a transaction") + +// FastBatchInsertBuilder works like sq.InsertBuilder but has a better support for batching +// large number of rows. +// It is NOT safe for concurrent use. +// It does NOT support updating existing rows. +type FastBatchInsertBuilder struct { + columns []string + rows [][]interface{} + rowStructType reflect.Type + sealed bool +} + +// Row adds a new row to the batch. All rows must have exactly the same columns +// (map keys). Otherwise, error will be returned. Please note that rows are not +// added one by one but in batches when `Exec` is called. +func (b *FastBatchInsertBuilder) Row(row map[string]interface{}) error { + if b.sealed { + return ErrSealed + } + + if b.columns == nil { + b.columns = make([]string, 0, len(row)) + b.rows = make([][]interface{}, 0) + + for column := range row { + b.columns = append(b.columns, column) + } + + sort.Strings(b.columns) + } + + if len(b.columns) != len(row) { + return errors.Errorf("invalid number of columns (expected=%d, actual=%d)", len(b.columns), len(row)) + } + + rowSlice := make([]interface{}, 0, len(b.columns)) + for _, column := range b.columns { + val, ok := row[column] + if !ok { + return errors.Errorf(`column "%s" does not exist`, column) + } + rowSlice = append(rowSlice, val) + } + b.rows = append(b.rows, rowSlice) + + return nil +} + +// RowStruct adds a new row to the batch. All rows must have exactly the same columns +// (map keys). Otherwise, error will be returned. Please note that rows are not +// added one by one but in batches when `Exec` is called. +func (b *FastBatchInsertBuilder) RowStruct(row interface{}) error { + if b.sealed { + return ErrSealed + } + + if b.columns == nil { + b.columns = ColumnsForStruct(row) + b.rows = make([][]interface{}, 0) + } + + rowType := reflect.TypeOf(row) + if b.rowStructType == nil { + b.rowStructType = rowType + } else if b.rowStructType != rowType { + return errors.Errorf(`expected value of type "%s" but got "%s" value`, b.rowStructType.String(), rowType.String()) + } + + rrow := reflect.ValueOf(row) + rvals := mapper.FieldsByName(rrow, b.columns) + + // convert fields values to interface{} + columnValues := make([]interface{}, len(b.columns)) + for i, rval := range rvals { + columnValues[i] = rval.Interface() + } + + b.rows = append(b.rows, columnValues) + + return nil +} + +// Len returns the number of rows held in memory by the FastBatchInsertBuilder. +func (b *FastBatchInsertBuilder) Len() int { + return len(b.rows) +} + +// Exec inserts rows in a single COPY statement. Once Exec is called no more rows +// can be added to the FastBatchInsertBuilder unless Reset is called. +// Exec must be called within a transaction. +func (b *FastBatchInsertBuilder) Exec(ctx context.Context, session SessionInterface, tableName string) error { + b.sealed = true + if session.GetTx() == nil { + return ErrNoTx + } + + if len(b.rows) == 0 { + return nil + } + + tx := session.GetTx() + stmt, err := tx.PrepareContext(ctx, pq.CopyIn(tableName, b.columns...)) + if err != nil { + return err + } + + for _, row := range b.rows { + if _, err = stmt.ExecContext(ctx, row...); err != nil { + // we need to close the statement otherwise the session + // will always return bad connection errors when executing + // any other sql statements, + // see https://github.com/stellar/go/pull/316#issuecomment-368990324 + stmt.Close() + return err + } + } + + if err = stmt.Close(); err != nil { + return err + } + return nil +} + +// Reset clears out all the rows contained in the FastBatchInsertBuilder. +// After Reset is called new rows can be added to the FastBatchInsertBuilder. +func (b *FastBatchInsertBuilder) Reset() { + b.sealed = false + b.columns = nil + b.rows = nil + b.rowStructType = nil +} diff --git a/support/db/fast_batch_insert_builder_test.go b/support/db/fast_batch_insert_builder_test.go new file mode 100644 index 0000000000..4acc09369c --- /dev/null +++ b/support/db/fast_batch_insert_builder_test.go @@ -0,0 +1,132 @@ +package db + +import ( + "context" + "testing" + + "github.com/guregu/null" + "github.com/stretchr/testify/assert" + + "github.com/stellar/go/support/db/dbtest" +) + +func TestFastBatchInsertBuilder(t *testing.T) { + db := dbtest.Postgres(t).Load(testSchema) + defer db.Close() + sess := &Session{DB: db.Open()} + defer sess.DB.Close() + + insertBuilder := &FastBatchInsertBuilder{} + + assert.NoError(t, + insertBuilder.Row(map[string]interface{}{ + "name": "bubba", + "hunger_level": "1", + "json_value": `{"bump_to": "97"}`, + }), + ) + + assert.EqualError(t, + insertBuilder.Row(map[string]interface{}{ + "name": "bubba", + }), + "invalid number of columns (expected=3, actual=1)", + ) + + assert.EqualError(t, + insertBuilder.Row(map[string]interface{}{ + "name": "bubba", + "city": "London", + "json_value": `{"bump_to": "98"}`, + }), + "column \"hunger_level\" does not exist", + ) + + assert.NoError(t, + insertBuilder.RowStruct(hungerRow{ + Name: "bubba2", + HungerLevel: "9", + JsonValue: `{"bump_to": "98"}`, + }), + ) + + assert.EqualError(t, + insertBuilder.RowStruct(invalidHungerRow{ + Name: "bubba", + HungerLevel: "2", + LastName: "b", + }), + "expected value of type \"db.hungerRow\" but got \"db.invalidHungerRow\" value", + ) + assert.Equal(t, 2, insertBuilder.Len()) + assert.Equal(t, false, insertBuilder.sealed) + + ctx := context.Background() + assert.EqualError(t, + insertBuilder.Exec(ctx, sess, "people"), + "cannot call Exec() outside of a transaction", + ) + assert.Equal(t, true, insertBuilder.sealed) + + assert.NoError(t, sess.Begin(ctx)) + assert.NoError(t, insertBuilder.Exec(ctx, sess, "people")) + assert.Equal(t, 2, insertBuilder.Len()) + assert.Equal(t, true, insertBuilder.sealed) + + var found []person + assert.NoError(t, sess.SelectRaw(context.Background(), &found, `SELECT * FROM people WHERE name like 'bubba%'`)) + assert.Equal( + t, + found, + []person{ + {Name: "bubba", HungerLevel: "1", JsonValue: null.NewString(`{"bump_to": "97"}`, true)}, + {Name: "bubba2", HungerLevel: "9", JsonValue: null.NewString(`{"bump_to": "98"}`, true)}, + }, + ) + + assert.EqualError(t, + insertBuilder.Row(map[string]interface{}{ + "name": "bubba3", + "hunger_level": "100", + }), + "cannot add more rows after Exec() without calling Reset() first", + ) + assert.Equal(t, 2, insertBuilder.Len()) + assert.Equal(t, true, insertBuilder.sealed) + + insertBuilder.Reset() + assert.Equal(t, 0, insertBuilder.Len()) + assert.Equal(t, false, insertBuilder.sealed) + + assert.NoError(t, + insertBuilder.Row(map[string]interface{}{ + "name": "bubba3", + "hunger_level": "3", + }), + ) + assert.Equal(t, 1, insertBuilder.Len()) + assert.Equal(t, false, insertBuilder.sealed) + + ctx, cancel := context.WithCancel(context.Background()) + cancel() + assert.EqualError(t, + insertBuilder.Exec(ctx, sess, "people"), + "context canceled", + ) + assert.Equal(t, 1, insertBuilder.Len()) + assert.Equal(t, true, insertBuilder.sealed) + + assert.NoError(t, sess.SelectRaw(context.Background(), &found, `SELECT * FROM people WHERE name like 'bubba%'`)) + assert.Equal( + t, + found, + []person{ + {Name: "bubba", HungerLevel: "1", JsonValue: null.NewString(`{"bump_to": "97"}`, true)}, + {Name: "bubba2", HungerLevel: "9", JsonValue: null.NewString(`{"bump_to": "98"}`, true)}, + }, + ) + assert.NoError(t, sess.Rollback()) + + assert.NoError(t, sess.SelectRaw(context.Background(), &found, `SELECT * FROM people WHERE name like 'bubba%'`)) + assert.Empty(t, found) +} diff --git a/support/db/internal_test.go b/support/db/internal_test.go index 8ce0370a92..3e1a06dabc 100644 --- a/support/db/internal_test.go +++ b/support/db/internal_test.go @@ -7,6 +7,7 @@ const testSchema = ` CREATE TABLE IF NOT EXISTS people ( name character varying NOT NULL, hunger_level integer NOT NULL, + json_value jsonb, PRIMARY KEY (name) ); DELETE FROM people; diff --git a/support/db/main.go b/support/db/main.go index c8cc9f62aa..2fb1f18a10 100644 --- a/support/db/main.go +++ b/support/db/main.go @@ -38,8 +38,11 @@ var ( // taken longer than context's deadline max duration ErrTimeout = errors.New("canceling statement due to lack of response within timeout period") // ErrCancelled is an error returned by Session methods when request has - // been cancelled (ex. context cancelled). + // been canceled (ex. context canceled). ErrCancelled = errors.New("canceling statement due to user request") + // ErrAlreadyRolledback is an error returned by Session methods when the transaction + // containing the request has already been rolled back. + ErrAlreadyRolledback = errors.New("transaction has already been committed or rolled back") // ErrConflictWithRecovery is an error returned by Session methods when // read replica cancels the query due to conflict with about-to-be-applied // WAL entries (https://www.postgresql.org/docs/current/hot-standby.html). @@ -48,7 +51,7 @@ var ( // error. ErrBadConnection = errors.New("bad connection") // ErrStatementTimeout is an error returned by Session methods when request has - // been cancelled due to a statement timeout. + // been canceled due to a statement timeout. ErrStatementTimeout = errors.New("canceling statement due to statement timeout") ) @@ -120,8 +123,8 @@ type Session struct { } type SessionInterface interface { - BeginTx(opts *sql.TxOptions) error - Begin() error + BeginTx(ctx context.Context, opts *sql.TxOptions) error + Begin(ctx context.Context) error Rollback() error Commit() error GetTx() *sqlx.Tx diff --git a/support/db/main_test.go b/support/db/main_test.go index 68724d197d..301b533aa4 100644 --- a/support/db/main_test.go +++ b/support/db/main_test.go @@ -4,15 +4,16 @@ import ( "testing" "time" + "github.com/guregu/null" "github.com/stellar/go/support/db/dbtest" "github.com/stretchr/testify/assert" ) type person struct { - Name string `db:"name"` - HungerLevel string `db:"hunger_level"` - - SomethingIgnored int `db:"-"` + Name string `db:"name"` + HungerLevel string `db:"hunger_level"` + JsonValue null.String `db:"json_value"` + SomethingIgnored int `db:"-"` } func TestGetTable(t *testing.T) { diff --git a/support/db/metrics.go b/support/db/metrics.go index 5e893f026e..0726a85f91 100644 --- a/support/db/metrics.go +++ b/support/db/metrics.go @@ -25,6 +25,7 @@ var IngestSubservice = Subservice("ingest") type QueryType string +var AdvisoryLockQueryType = QueryType("advisory_lock") var DeleteQueryType = QueryType("delete") var InsertQueryType = QueryType("insert") var SelectQueryType = QueryType("select") @@ -81,6 +82,7 @@ func RegisterMetrics(base *Session, namespace string, sub Subservice, registry * Namespace: namespace, Subsystem: "db", Name: "query_duration_seconds", ConstLabels: prometheus.Labels{"subservice": string(sub)}, + Objectives: map[float64]float64{0.5: 0.05, 0.9: 0.01, 0.99: 0.001}, }, []string{"query_type", "error", "route"}, ) @@ -231,6 +233,7 @@ func RegisterMetrics(base *Session, namespace string, sub Subservice, registry * Name: "round_trip_time_seconds", Help: "time required to run `select 1` query in a DB - effectively measures round trip time, if time exceeds 1s it will be recorded as 1", ConstLabels: prometheus.Labels{"subservice": string(sub)}, + Objectives: map[float64]float64{0.5: 0.05, 0.9: 0.01, 0.99: 0.001}, }, ) registry.MustRegister(s.roundTripTimeSummary) diff --git a/support/db/mock_session.go b/support/db/mock_session.go index 9c3c4e7861..ce932cdbb3 100644 --- a/support/db/mock_session.go +++ b/support/db/mock_session.go @@ -17,13 +17,13 @@ type MockSession struct { mock.Mock } -func (m *MockSession) Begin() error { - args := m.Called() +func (m *MockSession) Begin(ctx context.Context) error { + args := m.Called(ctx) return args.Error(0) } -func (m *MockSession) BeginTx(opts *sql.TxOptions) error { - args := m.Called(opts) +func (m *MockSession) BeginTx(ctx context.Context, opts *sql.TxOptions) error { + args := m.Called(ctx, opts) return args.Error(0) } diff --git a/support/db/session.go b/support/db/session.go index 33514e2a09..4ad0bc86b5 100644 --- a/support/db/session.go +++ b/support/db/session.go @@ -16,14 +16,14 @@ import ( ) // Begin binds this session to a new transaction. -func (s *Session) Begin() error { +func (s *Session) Begin(ctx context.Context) error { if s.tx != nil { return errors.New("already in transaction") } - tx, err := s.DB.BeginTxx(context.Background(), nil) + tx, err := s.DB.BeginTxx(ctx, nil) if err != nil { - if knownErr := s.replaceWithKnownError(err, context.Background()); knownErr != nil { + if knownErr := s.replaceWithKnownError(err, ctx); knownErr != nil { return knownErr } @@ -37,14 +37,14 @@ func (s *Session) Begin() error { // BeginTx binds this session to a new transaction which is configured with the // given transaction options -func (s *Session) BeginTx(opts *sql.TxOptions) error { +func (s *Session) BeginTx(ctx context.Context, opts *sql.TxOptions) error { if s.tx != nil { return errors.New("already in transaction") } - tx, err := s.DB.BeginTxx(context.Background(), opts) + tx, err := s.DB.BeginTxx(ctx, opts) if err != nil { - if knownErr := s.replaceWithKnownError(err, context.Background()); knownErr != nil { + if knownErr := s.replaceWithKnownError(err, ctx); knownErr != nil { return knownErr } @@ -183,7 +183,7 @@ func (s *Session) Exec(ctx context.Context, query sq.Sqlizer) (sql.Result, error // ExecAll runs all sql commands in `script` against `r` within a single // transaction. func (s *Session) ExecAll(ctx context.Context, script string) error { - err := s.Begin() + err := s.Begin(ctx) if err != nil { return err } @@ -253,6 +253,8 @@ func (s *Session) replaceWithKnownError(err error, ctx context.Context) error { return ErrBadConnection case strings.Contains(err.Error(), "pq: canceling statement due to statement timeout"): return ErrStatementTimeout + case strings.Contains(err.Error(), "transaction has already been committed or rolled back"): + return ErrAlreadyRolledback default: return nil } diff --git a/support/db/session_test.go b/support/db/session_test.go index 8b13ba2736..8629b2ca7e 100644 --- a/support/db/session_test.go +++ b/support/db/session_test.go @@ -97,7 +97,7 @@ func TestSession(t *testing.T) { // Test transactions db.Load(testSchema) - require.NoError(sess.Begin(), "begin failed") + require.NoError(sess.Begin(ctx), "begin failed") err = sess.GetRaw(ctx, &count, "SELECT COUNT(*) FROM people") assert.NoError(err) assert.Equal(3, count) @@ -109,7 +109,7 @@ func TestSession(t *testing.T) { assert.NoError(sess.Rollback(), "rollback failed") // Ensure commit works - require.NoError(sess.Begin(), "begin failed") + require.NoError(sess.Begin(ctx), "begin failed") sess.ExecRaw(ctx, "DELETE FROM people") assert.NoError(sess.Commit(), "commit failed") err = sess.GetRaw(ctx, &count, "SELECT COUNT(*) FROM people") @@ -153,10 +153,48 @@ func TestIdleTransactionTimeout(t *testing.T) { assert.NoError(err) defer sess.Close() - assert.NoError(sess.Begin()) - <-time.After(100 * time.Millisecond) + assert.NoError(sess.Begin(context.Background())) + <-time.After(150 * time.Millisecond) var count int err = sess.GetRaw(context.Background(), &count, "SELECT COUNT(*) FROM people") assert.ErrorIs(err, ErrBadConnection) } + +func TestSessionRollbackAfterContextCanceled(t *testing.T) { + db := dbtest.Postgres(t).Load(testSchema) + defer db.Close() + + sess := setupRolledbackTx(t, db) + defer sess.DB.Close() + + assert.ErrorIs(t, sess.Rollback(), ErrAlreadyRolledback) +} + +func TestSessionCommitAfterContextCanceled(t *testing.T) { + db := dbtest.Postgres(t).Load(testSchema) + defer db.Close() + + sess := setupRolledbackTx(t, db) + defer sess.DB.Close() + + assert.ErrorIs(t, sess.Commit(), ErrAlreadyRolledback) +} + +func setupRolledbackTx(t *testing.T, db *dbtest.DB) *Session { + var cancel context.CancelFunc + ctx := context.Background() + ctx, cancel = context.WithCancel(ctx) + + sess := &Session{DB: db.Open()} + + assert.NoError(t, sess.Begin(ctx)) + + var count int + assert.NoError(t, sess.GetRaw(ctx, &count, "SELECT COUNT(*) FROM people")) + assert.Equal(t, 3, count) + + cancel() + time.Sleep(500 * time.Millisecond) + return sess +} diff --git a/support/http/httpdecode/httpdecode_test.go b/support/http/httpdecode/httpdecode_test.go index 5989b27f73..9fb80f3d62 100644 --- a/support/http/httpdecode/httpdecode_test.go +++ b/support/http/httpdecode/httpdecode_test.go @@ -161,7 +161,7 @@ func TestDecodeForm_validTags(t *testing.T) { assert.Equal(t, "bar", bodyDecoded.FooName) } -func TestDecodeForm_validIgnoresUnkownKeys(t *testing.T) { +func TestDecodeForm_validIgnoresUnknownKeys(t *testing.T) { body := `foo=bar&foz=baz` r, _ := http.NewRequest("POST", "/", strings.NewReader(body)) r.Header.Set("Content-Type", "application/x-www-form-urlencoded; charset=utf-8") diff --git a/support/log/entry.go b/support/log/entry.go index 5cd8b7718d..a4661cb8c0 100644 --- a/support/log/entry.go +++ b/support/log/entry.go @@ -9,9 +9,12 @@ import ( gerr "github.com/go-errors/errors" "github.com/sirupsen/logrus" "github.com/sirupsen/logrus/hooks/test" + "github.com/stellar/go/support/errors" ) +const timeStampFormat = "2006-01-02T15:04:05.000Z07:00" + // Ctx appends all fields from `e` to the new logger created from `ctx` // logger and returns it. func (e *Entry) Ctx(ctx context.Context) *Entry { @@ -38,12 +41,24 @@ func (e *Entry) SetLevel(level logrus.Level) { e.entry.Logger.SetLevel(level) } +func (e *Entry) UseJSONFormatter() { + formatter := new(logrus.JSONFormatter) + formatter.TimestampFormat = timeStampFormat + e.entry.Logger.Formatter = formatter +} + func (e *Entry) DisableColors() { - e.entry.Logger.Formatter.(*logrus.TextFormatter).DisableColors = true + if f, ok := e.entry.Logger.Formatter.(*logrus.TextFormatter); ok { + f.DisableColors = true + } } func (e *Entry) DisableTimestamp() { - e.entry.Logger.Formatter.(*logrus.TextFormatter).DisableTimestamp = true + if f, ok := e.entry.Logger.Formatter.(*logrus.TextFormatter); ok { + f.DisableTimestamp = true + } else if f, ok := e.entry.Logger.Formatter.(*logrus.JSONFormatter); ok { + f.DisableTimestamp = true + } } // WithField creates a child logger annotated with the provided key value pair. diff --git a/support/log/main.go b/support/log/main.go index 1e9893c34a..ce5f80cc04 100644 --- a/support/log/main.go +++ b/support/log/main.go @@ -2,9 +2,10 @@ package log import ( "context" + "io" "os" - loggly "github.com/segmentio/go-loggly" + "github.com/segmentio/go-loggly" "github.com/sirupsen/logrus" ) @@ -43,7 +44,7 @@ func New() *Entry { l := logrus.New() l.Level = logrus.WarnLevel l.Formatter.(*logrus.TextFormatter).FullTimestamp = true - l.Formatter.(*logrus.TextFormatter).TimestampFormat = "2006-01-02T15:04:05.000Z07:00" + l.Formatter.(*logrus.TextFormatter).TimestampFormat = timeStampFormat return &Entry{entry: *logrus.NewEntry(l).WithField("pid", os.Getpid())} } @@ -80,6 +81,10 @@ func SetLevel(level logrus.Level) { DefaultLogger.SetLevel(level) } +func SetOut(out io.Writer) { + DefaultLogger.entry.Logger.Out = out +} + func WithField(key string, value interface{}) *Entry { result := DefaultLogger.WithField(key, value) return result diff --git a/services/horizon/internal/logmetrics/main.go b/support/logmetrics/main.go similarity index 52% rename from services/horizon/internal/logmetrics/main.go rename to support/logmetrics/main.go index baace30e97..06df3fccba 100644 --- a/services/horizon/internal/logmetrics/main.go +++ b/support/logmetrics/main.go @@ -1,60 +1,51 @@ package logmetrics import ( + "fmt" "github.com/prometheus/client_golang/prometheus" "github.com/sirupsen/logrus" - "github.com/stellar/go/support/log" ) // Metrics is a logrus hook-compliant struct that records metrics about logging // when added to a logrus.Logger type Metrics map[logrus.Level]prometheus.Counter -var DefaultMetrics = NewMetrics() - -func init() { - _, DefaultMetrics = New() -} - -// New creates a new logger according to horizon specifications. -func New() (l *log.Entry, m *Metrics) { - m = NewMetrics() - l = log.New() - l.SetLevel(logrus.WarnLevel) - l.AddHook(m) - return -} - -// NewMetrics creates a new hook for recording metrics. -func NewMetrics() *Metrics { - return &Metrics{ +// New creates a new hook for recording metrics. +// New takes a namespace parameter which defines the namespace +// for the prometheus metrics. +func New(namespace string) Metrics { + return Metrics{ logrus.DebugLevel: prometheus.NewCounter(prometheus.CounterOpts{ - Namespace: "horizon", Subsystem: "log", Name: "debug_total", + Namespace: namespace, Subsystem: "log", Name: "debug_total", }), logrus.InfoLevel: prometheus.NewCounter(prometheus.CounterOpts{ - Namespace: "horizon", Subsystem: "log", Name: "info_total", + Namespace: namespace, Subsystem: "log", Name: "info_total", }), logrus.WarnLevel: prometheus.NewCounter(prometheus.CounterOpts{ - Namespace: "horizon", Subsystem: "log", Name: "warn_total", + Namespace: namespace, Subsystem: "log", Name: "warn_total", }), logrus.ErrorLevel: prometheus.NewCounter(prometheus.CounterOpts{ - Namespace: "horizon", Subsystem: "log", Name: "error_total", + Namespace: namespace, Subsystem: "log", Name: "error_total", }), logrus.PanicLevel: prometheus.NewCounter(prometheus.CounterOpts{ - Namespace: "horizon", Subsystem: "log", Name: "panic_total", + Namespace: namespace, Subsystem: "log", Name: "panic_total", }), } } // Fire is triggered by logrus, in response to a logging event -func (m *Metrics) Fire(e *logrus.Entry) error { - (*m)[e.Level].Inc() - return nil +func (m Metrics) Fire(e *logrus.Entry) error { + counter, ok := m[e.Level] + if ok { + counter.Inc() + return nil + } + return fmt.Errorf("level %v not supported", e.Level) } // Levels returns the logging levels that will trigger this hook to run. In // this case, all of them. -func (m *Metrics) Levels() []logrus.Level { +func (m Metrics) Levels() []logrus.Level { return []logrus.Level{ logrus.DebugLevel, logrus.InfoLevel, diff --git a/services/horizon/internal/logmetrics/main_test.go b/support/logmetrics/main_test.go similarity index 64% rename from services/horizon/internal/logmetrics/main_test.go rename to support/logmetrics/main_test.go index 9f80bfc359..bdcbfaf37a 100644 --- a/services/horizon/internal/logmetrics/main_test.go +++ b/support/logmetrics/main_test.go @@ -2,22 +2,28 @@ package logmetrics import ( "bytes" + "fmt" "testing" "github.com/prometheus/client_golang/prometheus" dto "github.com/prometheus/client_model/go" "github.com/sirupsen/logrus" "github.com/stretchr/testify/assert" + + "github.com/stellar/go/support/log" ) func TestLogPackageMetrics(t *testing.T) { output := new(bytes.Buffer) - l, m := New() + l := log.New() + m := New("horizon") + l.DisableColors() l.SetLevel(logrus.DebugLevel) l.SetOutput(output) + l.AddHook(m) - for _, meter := range *m { + for _, meter := range m { assert.Equal(t, float64(0), getMetricValue(meter).GetCounter().GetValue()) } @@ -29,7 +35,16 @@ func TestLogPackageMetrics(t *testing.T) { l.Panic("foo") }) - for _, meter := range *m { + for level, meter := range m { + levelString := level.String() + if levelString == "warning" { + levelString = "warn" + } + expectedDesc := fmt.Sprintf( + "Desc{fqName: \"horizon_log_%s_total\", help: \"\", constLabels: {}, variableLabels: {}}", + levelString, + ) + assert.Equal(t, expectedDesc, meter.Desc().String()) assert.Equal(t, float64(1), getMetricValue(meter).GetCounter().GetValue()) } } diff --git a/support/render/hal/io.go b/support/render/hal/io.go index b5164b4419..2b1bbc71b7 100644 --- a/support/render/hal/io.go +++ b/support/render/hal/io.go @@ -6,7 +6,7 @@ import ( "github.com/stellar/go/support/render/httpjson" ) -// Render write data to w, after marshalling to json +// Render write data to w, after marshaling to json func Render(w http.ResponseWriter, data interface{}) { httpjson.Render(w, data, httpjson.HALJSON) } diff --git a/support/render/httpjson/io.go b/support/render/httpjson/io.go index 79ad907ead..2071629462 100644 --- a/support/render/httpjson/io.go +++ b/support/render/httpjson/io.go @@ -24,13 +24,13 @@ func renderToString(data interface{}, pretty bool) ([]byte, error) { return json.Marshal(data) } -// Render write data to w, after marshalling to json. The response header is +// Render write data to w, after marshaling to json. The response header is // set based on cType. func Render(w http.ResponseWriter, data interface{}, cType contentType) { RenderStatus(w, http.StatusOK, data, cType) } -// RenderStatus write data to w, after marshalling to json. +// RenderStatus write data to w, after marshaling to json. // The response header is set based on cType. // The response status code is set to the statusCode. func RenderStatus(w http.ResponseWriter, statusCode int, data interface{}, cType contentType) { diff --git a/support/render/problem/problem.go b/support/render/problem/problem.go index 23d61d8d6c..566dbd4426 100644 --- a/support/render/problem/problem.go +++ b/support/render/problem/problem.go @@ -61,7 +61,7 @@ type P struct { } func (p P) Error() string { - return fmt.Sprintf("problem: %s", p.Type) + return fmt.Sprintf("problem: %s. full details: %s", p.Type, p.Detail) } // LogFilter describes which errors should be logged when terminating requests in diff --git a/support/render/problem/problem_test.go b/support/render/problem/problem_test.go index 2b142b3deb..77a45798b2 100644 --- a/support/render/problem/problem_test.go +++ b/support/render/problem/problem_test.go @@ -184,3 +184,9 @@ func TestProblemIsKnownError(t *testing.T) { err = problem.IsKnownError(errors.New("foo")) assert.NoError(t, err) } + +func TestErrorIncludesPInformation(t *testing.T) { + err_str := ServerError.Error() + assert.True(t, strings.Contains(err_str, ServerError.Detail)) + assert.True(t, strings.Contains(err_str, ServerError.Type)) +} diff --git a/support/scripts/build_release_artifacts/main.go b/support/scripts/build_release_artifacts/main.go index 4acbba1b2c..0a96d627fa 100644 --- a/support/scripts/build_release_artifacts/main.go +++ b/support/scripts/build_release_artifacts/main.go @@ -321,11 +321,6 @@ func prepareDest(pkg, bin, version, os, arch string) string { run("cp", "COPYING", dest) run("cp", filepath.Join(pkg, "README.md"), dest) run("cp", filepath.Join(pkg, "CHANGELOG.md"), dest) - if bin == "horizon" { - // Add default config files for Captive-Core - run("cp", filepath.Join(pkg, "configs/captive-core-pubnet.cfg"), dest) - run("cp", filepath.Join(pkg, "configs/captive-core-testnet.cfg"), dest) - } return dest } diff --git a/support/storage/http.go b/support/storage/http.go index 87e9221e6c..0aba319c40 100644 --- a/support/storage/http.go +++ b/support/storage/http.go @@ -26,15 +26,6 @@ func NewHttpStorage(ctx context.Context, base *url.URL, userAgent string) Storag } } -func checkResp(r *http.Response) error { - if r.StatusCode >= 200 && r.StatusCode < 400 { - return nil - } else { - return fmt.Errorf("bad HTTP response '%s' for %s '%s'", - r.Status, r.Request.Method, r.Request.URL.String()) - } -} - func (b *HttpStorage) GetFile(pth string) (io.ReadCloser, error) { derived := b.base derived.Path = path.Join(derived.Path, pth) @@ -70,7 +61,7 @@ func (b *HttpStorage) Head(pth string) (*http.Response, error) { return resp, nil } -func (b *HttpStorage) Exists(pth string) (bool, error) { +func (b *HttpArchiveBackend) Exists(pth string) (bool, error) { resp, err := b.Head(pth) if err != nil { return false, err @@ -80,11 +71,11 @@ func (b *HttpStorage) Exists(pth string) (bool, error) { } else if resp.StatusCode == http.StatusNotFound { return false, nil } else { - return false, errors.Errorf("Unkown status code=%d", resp.StatusCode) + return false, errors.Errorf("Unknown status code=%d", resp.StatusCode) } } -func (b *HttpStorage) Size(pth string) (int64, error) { +func (b *HttpArchiveBackend) Size(pth string) (int64, error) { resp, err := b.Head(pth) if err != nil { return 0, err @@ -94,16 +85,16 @@ func (b *HttpStorage) Size(pth string) (int64, error) { } else if resp.StatusCode == http.StatusNotFound { return 0, nil } else { - return 0, errors.Errorf("Unkown status code=%d", resp.StatusCode) + return 0, errors.Errorf("Unknown status code=%d", resp.StatusCode) } } -func (b *HttpStorage) PutFile(pth string, in io.ReadCloser) error { +func (b *HttpArchiveBackend) PutFile(pth string, in io.ReadCloser) error { in.Close() return errors.New("PutFile not available over HTTP") } -func (b *HttpStorage) ListFiles(pth string) (chan string, chan error) { +func (b *HttpArchiveBackend) ListFiles(pth string) (chan string, chan error) { ch := make(chan string) er := make(chan error) close(ch) @@ -112,10 +103,14 @@ func (b *HttpStorage) ListFiles(pth string) (chan string, chan error) { return ch, er } -func (b *HttpStorage) CanListFiles() bool { +func (b *HttpArchiveBackend) CanListFiles() bool { return false } +func (b *HttpStorage) Close() error { + return nil +} + func (b *HttpStorage) makeSendRequest(method, url string) (*http.Response, error) { req, err := http.NewRequest(method, url, nil) if err != nil { @@ -131,6 +126,19 @@ func (b *HttpStorage) makeSendRequest(method, url string) (*http.Response, error return resp, err } -func (b *HttpStorage) Close() error { - return nil +func makeHttpBackend(base *url.URL, opts ConnectOptions) ArchiveBackend { + return &HttpArchiveBackend{ + ctx: opts.Context, + userAgent: opts.UserAgent, + base: *base, + } +} + +func checkResp(r *http.Response) error { + if r.StatusCode >= 200 && r.StatusCode < 400 { + return nil + } else { + return fmt.Errorf("bad HTTP response '%s' for %s '%s'", + r.Status, r.Request.Method, r.Request.URL.String()) + } } diff --git a/support/storage/s3.go b/support/storage/s3.go index 87790e7426..eae46b1d7b 100644 --- a/support/storage/s3.go +++ b/support/storage/s3.go @@ -146,7 +146,7 @@ func (b *S3Storage) Exists(pth string) (bool, error) { } else if resp.StatusCode == http.StatusNotFound { return false, nil } else { - return false, errors.Errorf("Unkown status code=%d", resp.StatusCode) + return false, errors.Errorf("Unknown status code=%d", resp.StatusCode) } } @@ -160,7 +160,7 @@ func (b *S3Storage) Size(pth string) (int64, error) { } else if resp.StatusCode == http.StatusNotFound { return 0, nil } else { - return 0, errors.Errorf("Unkown status code=%d", resp.StatusCode) + return 0, errors.Errorf("Unknown status code=%d", resp.StatusCode) } } diff --git a/toid/main_test.go b/toid/main_test.go index 70433b1ac9..cac6305b69 100644 --- a/toid/main_test.go +++ b/toid/main_test.go @@ -18,7 +18,7 @@ func TestID_ToInt64(t *testing.T) { expected int64 shouldPanic bool }{ - // accomodates 12-bits of precision for the operation field + // accommodates 12-bits of precision for the operation field { id: &ID{0, 0, 1}, expected: 1, @@ -31,7 +31,7 @@ func TestID_ToInt64(t *testing.T) { id: &ID{0, 0, 4096}, shouldPanic: true, }, - // accomodates 20-bits of precision for the transaction field + // accommodates 20-bits of precision for the transaction field { id: &ID{0, 1, 0}, expected: 4096, @@ -44,7 +44,7 @@ func TestID_ToInt64(t *testing.T) { id: &ID{0, 1048576, 0}, shouldPanic: true, }, - // accomodates 32-bits of precision for the ledger field + // accommodates 32-bits of precision for the ledger field { id: &ID{1, 0, 0}, expected: 4294967296, diff --git a/tools/goreplay-middleware/CHANGELOG.md b/tools/goreplay-middleware/CHANGELOG.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tools/goreplay-middleware/README.md b/tools/goreplay-middleware/README.md new file mode 100644 index 0000000000..87ebde01f4 --- /dev/null +++ b/tools/goreplay-middleware/README.md @@ -0,0 +1 @@ +# goreplay-middleware \ No newline at end of file diff --git a/tools/goreplay-middleware/main.go b/tools/goreplay-middleware/main.go new file mode 100644 index 0000000000..89e1e23a73 --- /dev/null +++ b/tools/goreplay-middleware/main.go @@ -0,0 +1,157 @@ +// The code below is a goreplay middleware used for regression testing current +// vs next Horizon version. The middleware system of goreplay is rather simple: +// it streams one of 3 message types to stdin: request (HTTP headers), +// original response and replayed response. On request we can modify the request +// and send it to stdout but we don't use this feature here: we send request +// to mirroring target as is. Finally, everything printed to stderr is the +// middleware log, this is where we put the information about the request if the +// diff is found. +// +// More information and diagrams about the middlewares can be found here: +// https://github.com/buger/goreplay/wiki/Middleware +package main + +import ( + "bufio" + "bytes" + "encoding/hex" + "fmt" + "io" + "os" + "time" + + "github.com/buger/goreplay/proto" + "github.com/stellar/go/support/log" +) + +// maxPerSecond defines how many requests should be checked at max per second +const maxPerSecond = 100 + +const ( + requestType byte = '1' + originalResponseType byte = '2' + replayedResponseType byte = '3' +) + +var lastCheck = time.Now() +var reqsCheckedPerSeq = 0 +var pendingRequestsAdded, ignoredCount, diffsCount, okCount int64 +var pendingRequests = make(map[string]*Request) + +func main() { + processAll(os.Stdin, os.Stderr, os.Stdout) +} + +func processAll(stdin io.Reader, stderr, stdout io.Writer) { + log.SetOut(stderr) + log.SetLevel(log.InfoLevel) + + bufSize := 20 * 1024 * 1024 // 20MB + scanner := bufio.NewScanner(stdin) + buf := make([]byte, bufSize) + scanner.Buffer(buf, bufSize) + var maxPendingRequests = 2000 + + for scanner.Scan() { + encoded := scanner.Bytes() + buf := make([]byte, len(encoded)/2) + _, err := hex.Decode(buf, encoded) + if err != nil { + os.Stderr.WriteString(fmt.Sprintf("hex.Decode error: %v", err)) + continue + } + + if err := scanner.Err(); err != nil { + os.Stderr.WriteString(fmt.Sprintf("scanner.Err(): %v\n", err)) + } + + process(stderr, stdout, buf) + + if len(pendingRequests) > maxPendingRequests { + // Around 3-4% of responses is lost (not sure why) so pendingRequests can grow + // indefinitely. Let's just truncate it when it becomes too big. + // There is one gotcha here. Goreplay will still send requests + // (`1` type payloads) even if traffic is rate limited. So if rate + // limit is applied even more requests can be lost. So we should + // use rate limiting implemented here when using middleware rather than + // Goreplay's rate limit. + pendingRequests = make(map[string]*Request) + } + } +} + +func process(stderr, stdout io.Writer, buf []byte) { + // First byte indicate payload type: + payloadType := buf[0] + headerSize := bytes.IndexByte(buf, '\n') + 1 + header := buf[:headerSize-1] + + // Header contains space separated values of: request type, request id, and request start time (or round-trip time for responses) + meta := bytes.Split(header, []byte(" ")) + // For each request you should receive 3 payloads (request, response, replayed response) with same request id + reqID := string(meta[1]) + payload := buf[headerSize:] + + switch payloadType { + case requestType: + if time.Since(lastCheck) > time.Second { + reqsCheckedPerSeq = 0 + lastCheck = time.Now() + + // Print stats every second + _, _ = os.Stderr.WriteString(fmt.Sprintf( + "middleware stats: pendingRequests=%d requestsAdded=%d ok=%d diffs=%d ignored=%d\n", + len(pendingRequests), + pendingRequestsAdded, + okCount, + diffsCount, + ignoredCount, + )) + } + + if reqsCheckedPerSeq < maxPerSecond { + pendingRequests[reqID] = &Request{ + Headers: payload, + } + pendingRequestsAdded++ + reqsCheckedPerSeq++ + } + + // Emitting data back, without modification + _, err := io.WriteString(stdout, hex.EncodeToString(buf)+"\n") + if err != nil { + _, _ = io.WriteString(stderr, fmt.Sprintf("stdout.WriteString error: %v", err)) + } + case originalResponseType: + if req, ok := pendingRequests[reqID]; ok { + // Original response can arrive after mirrored so this should be improved + // instead of ignoring this case. + req.OriginalResponse = payload + } + case replayedResponseType: + if req, ok := pendingRequests[reqID]; ok { + req.MirroredResponse = payload + + if req.IsIgnored() { + ignoredCount++ + } else { + if !req.ResponseEquals() { + // TODO in the future publish the results to S3 for easier processing + log.WithFields(log.F{ + "expected": req.OriginalBody(), + "actual": req.MirroredBody(), + "headers": string(req.Headers), + "path": string(proto.Path(req.Headers)), + }).Info("Mismatch found") + diffsCount++ + } else { + okCount++ + } + } + + delete(pendingRequests, reqID) + } + default: + _, _ = io.WriteString(stderr, "Unknown message type\n") + } +} diff --git a/tools/goreplay-middleware/main_test.go b/tools/goreplay-middleware/main_test.go new file mode 100644 index 0000000000..42cbcafd13 --- /dev/null +++ b/tools/goreplay-middleware/main_test.go @@ -0,0 +1,49 @@ +package main + +import ( + "bytes" + "encoding/hex" + "strings" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestProcess(t *testing.T) { + // For 1 type, it returns the same msg to stdout + payload := "1 ID\nGET /ledgers HTTP/1.1\r\nHost: horizon.stellar.org\r\n\r\n" + stdin := strings.NewReader(hex.EncodeToString([]byte(payload))) + + stdout := bytes.Buffer{} + stderr := bytes.Buffer{} + processAll(stdin, &stderr, &stdout) + + decodedOut, err := hex.DecodeString(strings.TrimRight(stdout.String(), "\n")) + assert.NoError(t, err) + assert.Equal(t, payload, string(decodedOut)) + assert.Equal(t, "", stderr.String()) + + // For 2 type, save the original response + payload = "2 ID\nHeader: true\r\n\r\nBody" + stdin = strings.NewReader(hex.EncodeToString([]byte(payload))) + + stdout = bytes.Buffer{} + stderr = bytes.Buffer{} + processAll(stdin, &stderr, &stdout) + + assert.Len(t, pendingRequests, 1) + assert.Equal(t, "", stdout.String()) + assert.Equal(t, "", stderr.String()) + + // For 2 type, save the original response + payload = "3 ID\nHeader: true\r\n\r\nBody" + stdin = strings.NewReader(hex.EncodeToString([]byte(payload))) + + stdout = bytes.Buffer{} + stderr = bytes.Buffer{} + processAll(stdin, &stderr, &stdout) + + assert.Len(t, pendingRequests, 0) + assert.Equal(t, "", stdout.String()) + assert.Equal(t, "", stderr.String()) +} diff --git a/tools/goreplay-middleware/request.go b/tools/goreplay-middleware/request.go new file mode 100644 index 0000000000..165971f725 --- /dev/null +++ b/tools/goreplay-middleware/request.go @@ -0,0 +1,99 @@ +package main + +import ( + "bytes" + "regexp" + "strings" + + "github.com/buger/goreplay/proto" +) + +var horizonURLs = regexp.MustCompile(`https:\/\/.*?(stellar\.org|127.0.0.1:8000)`) +var findResultMetaXDR = regexp.MustCompile(`"result_meta_xdr":[ ]?"([^"]*)",`) + +// removeRegexps contains a list of regular expressions that, when matched, +// will be changed to an empty string. This is done to exclude known +// differences in responses between two Horizon version. +// +// Let's say that next Horizon version adds a new bool field: +// `is_authorized` on account balances list. You want to remove this +// field so it's not reported for each `/accounts/{id}` response. +var removeRegexps = []*regexp.Regexp{} + +type replace struct { + regexp *regexp.Regexp + repl string +} + +// replaceRegexps works like removeRegexps but replaces data +var replaceRegexps = []replace{} + +type Request struct { + Headers []byte + OriginalResponse []byte + MirroredResponse []byte +} + +func (r *Request) OriginalBody() string { + return string(proto.Body(r.OriginalResponse)) +} + +func (r *Request) MirroredBody() string { + return string(proto.Body(r.MirroredResponse)) +} + +func (r *Request) IsIgnored() bool { + if len(r.OriginalResponse) == 0 { + return true + } + + originalLatestLedgerHeader := proto.Header(r.OriginalResponse, []byte("Latest-Ledger")) + mirroredLatestLedgerHeader := proto.Header(r.MirroredResponse, []byte("Latest-Ledger")) + + if !bytes.Equal(originalLatestLedgerHeader, mirroredLatestLedgerHeader) { + return true + } + + // Responses below are not supported but support can be added with some effort + originalTransferEncodingHeader := proto.Header(r.OriginalResponse, []byte("Transfer-Encoding")) + mirroredTransferEncodingHeader := proto.Header(r.MirroredResponse, []byte("Transfer-Encoding")) + if len(originalTransferEncodingHeader) > 0 || + len(mirroredTransferEncodingHeader) > 0 { + return true + } + + acceptEncodingHeader := proto.Header(r.Headers, []byte("Accept-Encoding")) + if strings.Contains(string(acceptEncodingHeader), "gzip") { + return true + } + + acceptHeader := proto.Header(r.Headers, []byte("Accept")) + return strings.Contains(string(acceptHeader), "event-stream") +} + +func (r *Request) ResponseEquals() bool { + originalBody := proto.Body(r.OriginalResponse) + mirroredBody := proto.Body(r.MirroredResponse) + + return normalizeResponseBody(originalBody) == normalizeResponseBody(mirroredBody) +} + +// normalizeResponseBody normalizes body to allow byte-byte comparison like removing +// URLs from _links or tx meta. May require updating on new releases. +func normalizeResponseBody(body []byte) string { + normalizedBody := string(body) + // `result_meta_xdr` can differ between core instances (confirmed this with core team) + normalizedBody = findResultMetaXDR.ReplaceAllString(normalizedBody, "") + // Remove Horizon URL from the _links + normalizedBody = horizonURLs.ReplaceAllString(normalizedBody, "") + + for _, reg := range removeRegexps { + normalizedBody = reg.ReplaceAllString(normalizedBody, "") + } + + for _, reg := range replaceRegexps { + normalizedBody = reg.regexp.ReplaceAllString(normalizedBody, reg.repl) + } + + return normalizedBody +} diff --git a/tools/goreplay-middleware/request_test.go b/tools/goreplay-middleware/request_test.go new file mode 100644 index 0000000000..3ba2072096 --- /dev/null +++ b/tools/goreplay-middleware/request_test.go @@ -0,0 +1,86 @@ +package main + +import ( + "testing" +) + +func TestNormalizeResponseBody(t *testing.T) { + //nolint:all + resp := `{ + "_links": { + "self": { + "href": "https://horizon-testnet.stellar.org/transactions?cursor=\u0026limit=1\u0026order=desc" + }, + "next": { + "href": "https://horizon-testnet.stellar.org/transactions?cursor=2892102128111616\u0026limit=1\u0026order=desc" + }, + "prev": { + "href": "https://horizon-testnet.stellar.org/transactions?cursor=2892102128111616\u0026limit=1\u0026order=asc" + } + }, + "_embedded": { + "records": [ + { + "_links": { + "self": { + "href": "https://horizon-testnet.stellar.org/transactions/cfc6395b98ed0c5ad63bd808e6b5ec994c3ccc67814945d3c652659b5077da18" + }, + "account": { + "href": "https://horizon-testnet.stellar.org/accounts/GBW7BTQDKVMB62NXB3Z55NZCENRBD4O4OE7YBKBOG4K4DM4QK76L2DJD" + }, + "ledger": { + "href": "https://horizon-testnet.stellar.org/ledgers/673370" + }, + "operations": { + "href": "https://horizon-testnet.stellar.org/transactions/cfc6395b98ed0c5ad63bd808e6b5ec994c3ccc67814945d3c652659b5077da18/operations{?cursor,limit,order}", + "templated": true + }, + "effects": { + "href": "https://horizon-testnet.stellar.org/transactions/cfc6395b98ed0c5ad63bd808e6b5ec994c3ccc67814945d3c652659b5077da18/effects{?cursor,limit,order}", + "templated": true + }, + "precedes": { + "href": "https://horizon-testnet.stellar.org/transactions?order=asc\u0026cursor=2892102128111616" + }, + "succeeds": { + "href": "https://horizon-testnet.stellar.org/transactions?order=desc\u0026cursor=2892102128111616" + }, + "transaction": { + "href": "https://horizon-testnet.stellar.org/transactions/cfc6395b98ed0c5ad63bd808e6b5ec994c3ccc67814945d3c652659b5077da18" + } + }, + "id": "cfc6395b98ed0c5ad63bd808e6b5ec994c3ccc67814945d3c652659b5077da18", + "paging_token": "2892102128111616", + "successful": true, + "hash": "cfc6395b98ed0c5ad63bd808e6b5ec994c3ccc67814945d3c652659b5077da18", + "ledger": 673370, + "created_at": "2022-08-02T12:34:28Z", + "source_account": "GBW7BTQDKVMB62NXB3Z55NZCENRBD4O4OE7YBKBOG4K4DM4QK76L2DJD", + "source_account_sequence": "2892097833140225", + "fee_account": "GBW7BTQDKVMB62NXB3Z55NZCENRBD4O4OE7YBKBOG4K4DM4QK76L2DJD", + "fee_charged": "10000000", + "max_fee": "10000000", + "operation_count": 1, + "envelope_xdr": "AAAAAgAAAABt8M4DVVgfabcO8963IiNiEfHccT+AqC43FcGzkFf8vQCYloAACkZZAAAAAQAAAAEAAAAAAAAAAAAAAABi6RnwAAAAAAAAAAEAAAAAAAAACAAAAABKBB+2UBMP/abwcm/M1TXO+/JQWhPwkalgqizKmXyRIQAAAAAAAAABkFf8vQAAAEDmHHsYzqrzruPqKTFS0mcBPkpVkiF4ykNCJdAf/meM9NDYk+Eg/LD2B2epHdQZDC8TvecyiMQACjrb+Bdb+2YD", + "result_xdr": "AAAAAACYloAAAAAAAAAAAQAAAAAAAAAIAAAAAAAAABdH3lGAAAAAAA==", + "result_meta_xdr": "AAAAAgAAAAIAAAADAApGWgAAAAAAAAAAbfDOA1VYH2m3DvPetyIjYhHx3HE/gKguNxXBs5BX/L0AAAAXR95RgAAKRlkAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAABAApGWgAAAAAAAAAAbfDOA1VYH2m3DvPetyIjYhHx3HE/gKguNxXBs5BX/L0AAAAXR95RgAAKRlkAAAABAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAwAAAAAACkZaAAAAAGLpGdQAAAAAAAAAAQAAAAQAAAADAApGWgAAAAAAAAAAbfDOA1VYH2m3DvPetyIjYhHx3HE/gKguNxXBs5BX/L0AAAAXR95RgAAKRlkAAAABAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAwAAAAAACkZaAAAAAGLpGdQAAAAAAAAAAgAAAAAAAAAAbfDOA1VYH2m3DvPetyIjYhHx3HE/gKguNxXBs5BX/L0AAAADAApGTwAAAAAAAAAASgQftlATD/2m8HJvzNU1zvvyUFoT8JGpYKosypl8kSEMj1jFrrjxTQAAAM4AAAABAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAwAAAAAAAAhlAAAAAGKzGdkAAAAAAAAAAQAKRloAAAAAAAAAAEoEH7ZQEw/9pvByb8zVNc778lBaE/CRqWCqLMqZfJEhDI9Y3PaXQs0AAADOAAAAAQAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAMAAAAAAAAIZQAAAABisxnZAAAAAAAAAAA=", + "fee_meta_xdr": "AAAAAgAAAAMACkZZAAAAAAAAAABt8M4DVVgfabcO8963IiNiEfHccT+AqC43FcGzkFf8vQAAABdIdugAAApGWQAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAEACkZaAAAAAAAAAABt8M4DVVgfabcO8963IiNiEfHccT+AqC43FcGzkFf8vQAAABdH3lGAAApGWQAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAA==", + "memo_type": "none", + "signatures": [ + "5hx7GM6q867j6ikxUtJnAT5KVZIheMpDQiXQH/5njPTQ2JPhIPyw9gdnqR3UGQwvE73nMojEAAo62/gXW/tmAw==" + ], + "valid_after": "1970-01-01T00:00:00Z", + "valid_before": "2022-08-02T12:34:56Z", + "preconditions": { + "timebounds": { + "min_time": "0", + "max_time": "1659443696" + } + } + } + ] + } + }` + normalizedResp := normalizeResponseBody([]byte(resp)) + t.Log(normalizedResp) +} diff --git a/tools/stellar-sign/README.md b/tools/stellar-sign/README.md index 4a2d09fb0e..81e40fde30 100644 --- a/tools/stellar-sign/README.md +++ b/tools/stellar-sign/README.md @@ -1,10 +1,16 @@ # Stellar Sign -This folder contains `stellar-sign` a simple utility to make it easy to add your signature to a transaction envelope. When run on the terminal it: +This folder contains `stellar-sign` a simple utility to make it easy to add your signature to a transaction envelope or to verify a transaction signature with a public key. +When run on the terminal it: -1. Prompts your for a base64-encoded envelope: -2. Asks for your private seed. -3. Outputs a new envelope with your signature added. +1. Prompts your for a base64-encoded envelope +2. + - If `-verify` is used + - Asks for your public key + - Outputs if the transaction has a valid signature or not + - If in signature mode (default) + - Asks for your private seed + - Outputs a new envelope with your signature added ## Installing @@ -14,6 +20,17 @@ $ go get -u github.com/stellar/go/tools/stellar-sign ## Running +```bash +$ stellar-sign --help +Usage of ./stellar-sign: + -infile string + transaction envelope + -testnet + Sign or verify the transaction using Testnet passphrase instead of Public + -verify + Verify the transaction instead of signing +``` + ```bash $ stellar-sign ``` diff --git a/tools/stellar-sign/main.go b/tools/stellar-sign/main.go index 5a02ead8ab..47c143d46d 100644 --- a/tools/stellar-sign/main.go +++ b/tools/stellar-sign/main.go @@ -1,28 +1,123 @@ // stellar-sign is a small interactive utility to help you contribute a -// signature to a transaction envelope. +// signature to a transaction envelope or verify a transaction. // -// It prompts you for a key +// It prompts you for a key, public (verify) or private (sign) package main import ( "bufio" + b64 "encoding/base64" "flag" "fmt" - "github.com/stellar/go/keypair" - "github.com/stellar/go/network" "io/ioutil" "log" "os" "strings" + "github.com/stellar/go/keypair" + "github.com/stellar/go/network" + "github.com/howeyc/gopass" "github.com/stellar/go/txnbuild" "github.com/stellar/go/xdr" ) +type SignOrVerify struct { + verify bool + networkPassphrase string + privKey *keypair.Full + pubKey *keypair.FromAddress +} + +func (router *SignOrVerify) setKey(input string) { + var err error + if router.verify { + var inputPubKey keypair.KP + inputPubKey, err = keypair.Parse(input) + if err != nil { + log.Fatal(err) + } + router.pubKey = inputPubKey.FromAddress() + } else { + router.privKey, err = keypair.ParseFull(input) + if err != nil { + log.Fatal(err) + } + } +} + +func (router *SignOrVerify) doVerify(gentx *txnbuild.GenericTransaction) error { + var err error + var gentxHash [32]byte + var gentxEnv xdr.TransactionEnvelope + gentxEnv, err = gentx.ToXDR() + if err != nil { + log.Fatal(err) + } + signatures := gentxEnv.Signatures() + gentxHash, err = gentx.Hash(router.networkPassphrase) + if err != nil { + log.Fatal(err) + } + if gentxEnv.IsFeeBump() { + signatures = gentxEnv.FeeBumpSignatures() + gentxFeeBump, ok := gentx.FeeBump() + if !ok { + log.Fatal("Cannot find the correct transaction type") + } + gentxHash, err = gentxFeeBump.Hash(router.networkPassphrase) + if err != nil { + log.Fatal(err) + } + } + if len(signatures) == 0 { + log.Fatal("The transaction does not contain any signature") + } + // We try all signature and stop if we find a correct one + for _, signature := range signatures { + err = router.pubKey.Verify(gentxHash[:], signature.Signature) + if err == nil { + break + } + } + return err +} + +func (router *SignOrVerify) doSign(gentx *txnbuild.GenericTransaction) string { + var newEnv string + var err error + if tx, ok := gentx.Transaction(); ok { + tx, err = tx.Sign(router.networkPassphrase, router.privKey) + if err != nil { + log.Fatal(err) + } + newEnv, err = tx.Base64() + if err != nil { + log.Fatal(err) + } + } else { + var txFeeBump *txnbuild.FeeBumpTransaction + txFeeBump, ok = gentx.FeeBump() + if !ok { + log.Fatal("Cannot find the correct transaction type") + } + txFeeBump, err = txFeeBump.Sign(router.networkPassphrase, router.privKey) + if err != nil { + log.Fatal(err) + } + newEnv, err = txFeeBump.Base64() + if err != nil { + log.Fatal(err) + } + } + return newEnv +} + var in *bufio.Reader var infile = flag.String("infile", "", "transaction envelope") +var verify = flag.Bool("verify", false, "Verify the transaction instead of signing") +var testnet = flag.Bool("testnet", false, "Sign or verify the transaction using Testnet passphrase instead of Public") func main() { flag.Parse() @@ -63,64 +158,65 @@ func main() { log.Fatal(err) } + isFeeBump := txe.IsFeeBump() + fmt.Println("") fmt.Println("Transaction Summary:") sourceAccount := txe.SourceAccount().ToAccountId() fmt.Printf(" type: %s\n", txe.Type.String()) + if isFeeBump { + fmt.Printf(" fee bump source: %s\n", txe.FeeBumpAccount().ToAccountId().Address()) + } fmt.Printf(" source: %s\n", sourceAccount.Address()) fmt.Printf(" ops: %d\n", len(txe.Operations())) fmt.Printf(" sigs: %d\n", len(txe.Signatures())) - if txe.IsFeeBump() { + for _, signature := range txe.Signatures() { + fmt.Printf(" %s\n", b64.StdEncoding.EncodeToString(signature.Signature)) + } + if isFeeBump { fmt.Printf(" fee bump sigs: %d\n", len(txe.FeeBumpSignatures())) + for _, feeBumpSignature := range txe.FeeBumpSignatures() { + fmt.Printf(" %s\n", b64.StdEncoding.EncodeToString(feeBumpSignature.Signature)) + } } fmt.Println("") // TODO: add operation details - // read seed - seed, err := readLine("Enter seed: ", true) - if err != nil { - log.Fatal(err) + passPhrase := network.PublicNetworkPassphrase + if *testnet { + passPhrase = network.TestNetworkPassphrase } - // sign the transaction - kp, err := keypair.ParseFull(seed) + // read seed/public key + key, err := readLine("Enter key", true) if err != nil { log.Fatal(err) } + flowRouter := &SignOrVerify{verify: *verify, networkPassphrase: passPhrase} + flowRouter.setKey(key) + parsed, err := txnbuild.TransactionFromXDR(env) if err != nil { log.Fatal(err) } - var newEnv string - if tx, ok := parsed.Transaction(); ok { - tx, err = tx.Sign(network.PublicNetworkPassphrase, kp) + if *verify { + err := flowRouter.doVerify(parsed) if err != nil { - log.Fatal(err) - } - newEnv, err = tx.Base64() - if err != nil { - log.Fatal(err) + fmt.Print("\nSignature is INVALID\n") + } else { + fmt.Print("\nSignature is VALID\n") } } else { - tx, _ := parsed.FeeBump() - tx, err = tx.Sign(network.PublicNetworkPassphrase, kp) - if err != nil { - log.Fatal(err) - } - newEnv, err = tx.Base64() - if err != nil { - log.Fatal(err) - } + newEnv := flowRouter.doSign(parsed) + fmt.Print("\n==== Result ====\n\n") + fmt.Print("```\n") + fmt.Println(newEnv) + fmt.Print("```\n") } - fmt.Print("\n==== Result ====\n\n") - fmt.Print("```\n") - fmt.Println(newEnv) - fmt.Print("```\n") - } func readLine(prompt string, private bool) (string, error) { diff --git a/tools/xdr2go/main.go b/tools/xdr2go/main.go index 797db57207..9e262bd967 100644 --- a/tools/xdr2go/main.go +++ b/tools/xdr2go/main.go @@ -37,7 +37,7 @@ func run(cmd *cobra.Command, args []string) error { } err := xdr.SafeUnmarshalBase64(args[0], object) if err != nil { - return errors.Wrap(err, "Error unmarshalling XDR stucture.") + return errors.Wrap(err, "Error unmarshaling XDR stucture.") } source := fmt.Sprintf("%#v\n", object) diff --git a/txnbuild/CHANGELOG.md b/txnbuild/CHANGELOG.md index d7ed9c8cd1..ef1e53239f 100644 --- a/txnbuild/CHANGELOG.md +++ b/txnbuild/CHANGELOG.md @@ -3,11 +3,22 @@ All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). - ## Unreleased +## [11.0.0](https://github.com/stellar/go/releases/tag/horizonclient-v11.0.0) - 2023-03-29 + +### Breaking changes + +* Muxed accounts and ID memos can be used in the `BuildChallengeTx()` and `ReadChallengeTx()` SEP-10 utilitiy functions to identify users of shared Stellar accounts. ([#4746](https://github.com/stellar/go/pull/4746)) + * `BuildChallengeTx()`: + * Muxed account addresses can be passed as the `clientAccountID`. + * Adds an additional parameter of type `*txnbuild.MemoID`. Memos cannot be specified if the `clientAccoutID` id a muxed account address. + * `ReadChallengeTx()`: + * Muxed account addresses may be returned as the `clientAccountID`. + * Adds an additional return value of type `*txnbuild.MemoID`. + -## [10.0.0](https://github.com/stellar/go/releases/tag/horizonclient-v9.0.0) - 2022-04-18 +## [10.0.0](https://github.com/stellar/go/releases/tag/horizonclient-v10.0.0) - 2022-04-18 * Adds support for Protocol 19 transaction preconditions ([CAP-21](https://stellar.org/protocol/cap-21)). diff --git a/txnbuild/account_merge_test.go b/txnbuild/account_merge_test.go index 9e5f70315a..8cbe0a5866 100644 --- a/txnbuild/account_merge_test.go +++ b/txnbuild/account_merge_test.go @@ -33,11 +33,11 @@ func TestAccountMergeRoundtrip(t *testing.T) { SourceAccount: "GB7BDSZU2Y27LYNLALKKALB52WS2IZWYBDGY6EQBLEED3TJOCVMZRH7H", Destination: "GB7BDSZU2Y27LYNLALKKALB52WS2IZWYBDGY6EQBLEED3TJOCVMZRH7H", } - testOperationsMarshallingRoundtrip(t, []Operation{&accountMerge}, false) + testOperationsMarshalingRoundtrip(t, []Operation{&accountMerge}, false) accountMerge = AccountMerge{ SourceAccount: "MA7QYNF7SOWQ3GLR2BGMZEHXAVIRZA4KVWLTJJFC7MGXUA74P7UJVAAAAAAAAAAAAAJLK", Destination: "GB7BDSZU2Y27LYNLALKKALB52WS2IZWYBDGY6EQBLEED3TJOCVMZRH7H", } - testOperationsMarshallingRoundtrip(t, []Operation{&accountMerge}, true) + testOperationsMarshalingRoundtrip(t, []Operation{&accountMerge}, true) } diff --git a/txnbuild/allow_trust_test.go b/txnbuild/allow_trust_test.go index 60f811128a..9d614a5758 100644 --- a/txnbuild/allow_trust_test.go +++ b/txnbuild/allow_trust_test.go @@ -65,7 +65,7 @@ func TestAllowTrustRoundtrip(t *testing.T) { Type: CreditAsset{"USD", ""}, Authorize: true, } - testOperationsMarshallingRoundtrip(t, []Operation{&allowTrust}, false) + testOperationsMarshalingRoundtrip(t, []Operation{&allowTrust}, false) // with muxed accounts allowTrust = AllowTrust{ @@ -74,5 +74,5 @@ func TestAllowTrustRoundtrip(t *testing.T) { Type: CreditAsset{"USD", ""}, Authorize: true, } - testOperationsMarshallingRoundtrip(t, []Operation{&allowTrust}, true) + testOperationsMarshalingRoundtrip(t, []Operation{&allowTrust}, true) } diff --git a/txnbuild/asset.go b/txnbuild/asset.go index a0683da5cf..121a2d18b6 100644 --- a/txnbuild/asset.go +++ b/txnbuild/asset.go @@ -213,3 +213,13 @@ func assetFromXDR(xAsset xdr.Asset) (Asset, error) { return nil, errors.New("invalid asset") } + +// MustAssetFromXDR constructs an Asset from its xdr representation. +// If the given asset xdr is invalid, MustAssetFromXDR will panic. +func MustAssetFromXDR(xAsset xdr.Asset) Asset { + asset, err := assetFromXDR(xAsset) + if err != nil { + panic(err) + } + return asset +} diff --git a/txnbuild/begin_sponsoring_future_reserves_test.go b/txnbuild/begin_sponsoring_future_reserves_test.go index bcacb96c1d..4e2b64267c 100644 --- a/txnbuild/begin_sponsoring_future_reserves_test.go +++ b/txnbuild/begin_sponsoring_future_reserves_test.go @@ -9,5 +9,5 @@ func TestBeginSponsoringFutureReservesRoundTrip(t *testing.T) { SponsoredID: newKeypair1().Address(), } - testOperationsMarshallingRoundtrip(t, []Operation{beginSponsoring}, false) + testOperationsMarshalingRoundtrip(t, []Operation{beginSponsoring}, false) } diff --git a/txnbuild/bump_sequence_test.go b/txnbuild/bump_sequence_test.go index f29250f976..7ac10715f9 100644 --- a/txnbuild/bump_sequence_test.go +++ b/txnbuild/bump_sequence_test.go @@ -33,11 +33,11 @@ func TestBumpSequenceRountrip(t *testing.T) { SourceAccount: "GB7BDSZU2Y27LYNLALKKALB52WS2IZWYBDGY6EQBLEED3TJOCVMZRH7H", BumpTo: 10, } - testOperationsMarshallingRoundtrip(t, []Operation{&bumpSequence}, false) + testOperationsMarshalingRoundtrip(t, []Operation{&bumpSequence}, false) bumpSequence = BumpSequence{ SourceAccount: "MA7QYNF7SOWQ3GLR2BGMZEHXAVIRZA4KVWLTJJFC7MGXUA74P7UJVAAAAAAAAAAAAAJLK", BumpTo: 10, } - testOperationsMarshallingRoundtrip(t, []Operation{&bumpSequence}, true) + testOperationsMarshalingRoundtrip(t, []Operation{&bumpSequence}, true) } diff --git a/txnbuild/change_trust_test.go b/txnbuild/change_trust_test.go index 88484ed3a1..3282c65fac 100644 --- a/txnbuild/change_trust_test.go +++ b/txnbuild/change_trust_test.go @@ -85,7 +85,7 @@ func TestChangeTrustRoundtrip(t *testing.T) { Line: CreditAsset{"ABCD", "GB7BDSZU2Y27LYNLALKKALB52WS2IZWYBDGY6EQBLEED3TJOCVMZRH7H"}.MustToChangeTrustAsset(), Limit: "1.0000000", } - testOperationsMarshallingRoundtrip(t, []Operation{&changeTrust}, false) + testOperationsMarshalingRoundtrip(t, []Operation{&changeTrust}, false) // with muxed accounts changeTrust = ChangeTrust{ @@ -93,5 +93,5 @@ func TestChangeTrustRoundtrip(t *testing.T) { Line: CreditAsset{"ABCD", "GB7BDSZU2Y27LYNLALKKALB52WS2IZWYBDGY6EQBLEED3TJOCVMZRH7H"}.MustToChangeTrustAsset(), Limit: "1.0000000", } - testOperationsMarshallingRoundtrip(t, []Operation{&changeTrust}, true) + testOperationsMarshalingRoundtrip(t, []Operation{&changeTrust}, true) } diff --git a/txnbuild/claim_claimable_balance_test.go b/txnbuild/claim_claimable_balance_test.go index 1a1e285292..e37275b586 100644 --- a/txnbuild/claim_claimable_balance_test.go +++ b/txnbuild/claim_claimable_balance_test.go @@ -10,7 +10,7 @@ func TestClaimClaimableBalanceRoundTrip(t *testing.T) { BalanceID: "00000000929b20b72e5890ab51c24f1cc46fa01c4f318d8d33367d24dd614cfdf5491072", } - testOperationsMarshallingRoundtrip(t, []Operation{claimClaimableBalance}, false) + testOperationsMarshalingRoundtrip(t, []Operation{claimClaimableBalance}, false) // with muxed accounts claimClaimableBalance = &ClaimClaimableBalance{ @@ -18,5 +18,5 @@ func TestClaimClaimableBalanceRoundTrip(t *testing.T) { BalanceID: "00000000929b20b72e5890ab51c24f1cc46fa01c4f318d8d33367d24dd614cfdf5491072", } - testOperationsMarshallingRoundtrip(t, []Operation{claimClaimableBalance}, true) + testOperationsMarshalingRoundtrip(t, []Operation{claimClaimableBalance}, true) } diff --git a/txnbuild/clawback_claimable_balance_test.go b/txnbuild/clawback_claimable_balance_test.go index 9ff2914a0e..ba43c1fed1 100644 --- a/txnbuild/clawback_claimable_balance_test.go +++ b/txnbuild/clawback_claimable_balance_test.go @@ -10,7 +10,7 @@ func TestClawbackClaimableBalanceRoundTrip(t *testing.T) { BalanceID: "00000000929b20b72e5890ab51c24f1cc46fa01c4f318d8d33367d24dd614cfdf5491072", } - testOperationsMarshallingRoundtrip(t, []Operation{claimClaimableBalance}, false) + testOperationsMarshalingRoundtrip(t, []Operation{claimClaimableBalance}, false) // with muxed accounts claimClaimableBalance = &ClawbackClaimableBalance{ @@ -18,5 +18,5 @@ func TestClawbackClaimableBalanceRoundTrip(t *testing.T) { BalanceID: "00000000929b20b72e5890ab51c24f1cc46fa01c4f318d8d33367d24dd614cfdf5491072", } - testOperationsMarshallingRoundtrip(t, []Operation{claimClaimableBalance}, false) + testOperationsMarshalingRoundtrip(t, []Operation{claimClaimableBalance}, false) } diff --git a/txnbuild/clawback_test.go b/txnbuild/clawback_test.go index 62b9bac12f..1311d1bce4 100644 --- a/txnbuild/clawback_test.go +++ b/txnbuild/clawback_test.go @@ -88,7 +88,7 @@ func TestClawbackRoundTrip(t *testing.T) { Amount: "10.0000000", Asset: CreditAsset{"USD", "GCXKG6RN4ONIEPCMNFB732A436Z5PNDSRLGWK7GBLCMQLIFO4S7EYWVU"}, } - testOperationsMarshallingRoundtrip(t, []Operation{&clawback}, false) + testOperationsMarshalingRoundtrip(t, []Operation{&clawback}, false) // with muxed accounts clawback = Clawback{ @@ -97,5 +97,5 @@ func TestClawbackRoundTrip(t *testing.T) { Amount: "10.0000000", Asset: CreditAsset{"USD", "GCXKG6RN4ONIEPCMNFB732A436Z5PNDSRLGWK7GBLCMQLIFO4S7EYWVU"}, } - testOperationsMarshallingRoundtrip(t, []Operation{&clawback}, true) + testOperationsMarshalingRoundtrip(t, []Operation{&clawback}, true) } diff --git a/txnbuild/cmd/demo/operations/demo.go b/txnbuild/cmd/demo/operations/demo.go index d7a74ef3b3..f4730a4e06 100644 --- a/txnbuild/cmd/demo/operations/demo.go +++ b/txnbuild/cmd/demo/operations/demo.go @@ -50,7 +50,7 @@ func InitKeys(n int) []Account { } jsonAccounts, err2 := json.MarshalIndent(accounts, "", " ") - dieIfError("problem marshalling json accounts", err2) + dieIfError("problem marshaling json accounts", err2) err = ioutil.WriteFile(accountsFile, jsonAccounts, 0644) dieIfError("problem writing json accounts file", err) log.Info("Wrote keypairs to local file ", accountsFile) diff --git a/txnbuild/create_account_test.go b/txnbuild/create_account_test.go index a5b3b62628..da502dbc6d 100644 --- a/txnbuild/create_account_test.go +++ b/txnbuild/create_account_test.go @@ -61,7 +61,7 @@ func TestCreateAccountRoundtrip(t *testing.T) { Destination: "GDYNXQFHU6W5RBW2CCCDDAAU3TMTSU2RMGIBM6HGHAR4NJJKY3IJETHT", Amount: "1.0000000", } - testOperationsMarshallingRoundtrip(t, []Operation{&createAccount}, false) + testOperationsMarshalingRoundtrip(t, []Operation{&createAccount}, false) // with muxed accounts createAccount = CreateAccount{ @@ -69,6 +69,6 @@ func TestCreateAccountRoundtrip(t *testing.T) { Destination: "GDYNXQFHU6W5RBW2CCCDDAAU3TMTSU2RMGIBM6HGHAR4NJJKY3IJETHT", Amount: "1.0000000", } - testOperationsMarshallingRoundtrip(t, []Operation{&createAccount}, true) + testOperationsMarshalingRoundtrip(t, []Operation{&createAccount}, true) } diff --git a/txnbuild/create_claimable_balance_test.go b/txnbuild/create_claimable_balance_test.go index 7fe949be02..e5f9c2eac4 100644 --- a/txnbuild/create_claimable_balance_test.go +++ b/txnbuild/create_claimable_balance_test.go @@ -34,7 +34,7 @@ func TestCreateClaimableBalanceRoundTrip(t *testing.T) { }, } - testOperationsMarshallingRoundtrip(t, []Operation{createNativeBalance, createAssetBalance}, false) + testOperationsMarshalingRoundtrip(t, []Operation{createNativeBalance, createAssetBalance}, false) createNativeBalanceWithMuxedAcounts := &CreateClaimableBalance{ SourceAccount: "MA7QYNF7SOWQ3GLR2BGMZEHXAVIRZA4KVWLTJJFC7MGXUA74P7UJVAAAAAAAAAAAAAJLK", @@ -46,7 +46,7 @@ func TestCreateClaimableBalanceRoundTrip(t *testing.T) { }, } - testOperationsMarshallingRoundtrip(t, []Operation{createNativeBalanceWithMuxedAcounts}, true) + testOperationsMarshalingRoundtrip(t, []Operation{createNativeBalanceWithMuxedAcounts}, true) } func TestClaimableBalanceID(t *testing.T) { diff --git a/txnbuild/end_sponsoring_future_reserves_test.go b/txnbuild/end_sponsoring_future_reserves_test.go index 8b5ab5cdde..393a24caef 100644 --- a/txnbuild/end_sponsoring_future_reserves_test.go +++ b/txnbuild/end_sponsoring_future_reserves_test.go @@ -4,7 +4,7 @@ import "testing" func TestEndSponsoringFutureReservesRoundTrip(t *testing.T) { withoutMuxedAccounts := &EndSponsoringFutureReserves{SourceAccount: "GB7BDSZU2Y27LYNLALKKALB52WS2IZWYBDGY6EQBLEED3TJOCVMZRH7H"} - testOperationsMarshallingRoundtrip(t, []Operation{withoutMuxedAccounts}, false) + testOperationsMarshalingRoundtrip(t, []Operation{withoutMuxedAccounts}, false) withMuxedAccounts := &EndSponsoringFutureReserves{SourceAccount: "MA7QYNF7SOWQ3GLR2BGMZEHXAVIRZA4KVWLTJJFC7MGXUA74P7UJVAAAAAAAAAAAAAJLK"} - testOperationsMarshallingRoundtrip(t, []Operation{withMuxedAccounts}, true) + testOperationsMarshalingRoundtrip(t, []Operation{withMuxedAccounts}, true) } diff --git a/txnbuild/example_test.go b/txnbuild/example_test.go index 3aab258ab9..26b5d95187 100644 --- a/txnbuild/example_test.go +++ b/txnbuild/example_test.go @@ -760,7 +760,7 @@ func ExampleBuildChallengeTx() { webAuthDomain := "webauthdomain.example.org" timebound := time.Duration(5 * time.Minute) - tx, err := BuildChallengeTx(serverSignerSeed, clientAccountID, webAuthDomain, anchorName, network.TestNetworkPassphrase, timebound) + tx, err := BuildChallengeTx(serverSignerSeed, clientAccountID, webAuthDomain, anchorName, network.TestNetworkPassphrase, timebound, nil) check(err) txeBase64, err := tx.Base64() diff --git a/txnbuild/extend_footprint_ttl.go b/txnbuild/extend_footprint_ttl.go new file mode 100644 index 0000000000..f28dee6e15 --- /dev/null +++ b/txnbuild/extend_footprint_ttl.go @@ -0,0 +1,59 @@ +package txnbuild + +import ( + "github.com/stellar/go/support/errors" + "github.com/stellar/go/xdr" +) + +type ExtendFootprintTtl struct { + ExtendTo uint32 + SourceAccount string + Ext xdr.TransactionExt +} + +func (f *ExtendFootprintTtl) BuildXDR() (xdr.Operation, error) { + xdrOp := xdr.ExtendFootprintTtlOp{ + Ext: xdr.ExtensionPoint{ + V: 0, + }, + ExtendTo: xdr.Uint32(f.ExtendTo), + } + + body, err := xdr.NewOperationBody(xdr.OperationTypeExtendFootprintTtl, xdrOp) + if err != nil { + return xdr.Operation{}, errors.Wrap(err, "failed to build XDR Operation") + } + + op := xdr.Operation{Body: body} + + SetOpSourceAccount(&op, f.SourceAccount) + return op, nil +} + +func (f *ExtendFootprintTtl) FromXDR(xdrOp xdr.Operation) error { + result, ok := xdrOp.Body.GetExtendFootprintTtlOp() + if !ok { + return errors.New("error parsing invoke host function operation from xdr") + } + f.SourceAccount = accountFromXDR(xdrOp.SourceAccount) + f.ExtendTo = uint32(result.ExtendTo) + return nil +} + +func (f *ExtendFootprintTtl) Validate() error { + if f.SourceAccount != "" { + _, err := xdr.AddressToMuxedAccount(f.SourceAccount) + if err != nil { + return NewValidationError("SourceAccount", err.Error()) + } + } + return nil +} + +func (f *ExtendFootprintTtl) GetSourceAccount() string { + return f.SourceAccount +} + +func (f *ExtendFootprintTtl) BuildTransactionExt() (xdr.TransactionExt, error) { + return f.Ext, nil +} diff --git a/txnbuild/helpers.go b/txnbuild/helpers.go index 87f548c58d..866fd95c94 100644 --- a/txnbuild/helpers.go +++ b/txnbuild/helpers.go @@ -198,7 +198,7 @@ func validateOffer(buying, selling Asset, offerAmount string, price xdr.Price, o // ValidationError is a custom error struct that holds validation errors of txnbuild's operation structs. type ValidationError struct { - Field string // Field is the struct field on which the validation error occured. + Field string // Field is the struct field on which the validation error occurred. Message string // Message is the validation error message. } diff --git a/txnbuild/inflation_test.go b/txnbuild/inflation_test.go index 038dc10d08..1ca84188f5 100644 --- a/txnbuild/inflation_test.go +++ b/txnbuild/inflation_test.go @@ -6,11 +6,11 @@ func TestInflationRoundtrip(t *testing.T) { inflation := Inflation{ SourceAccount: "GB7BDSZU2Y27LYNLALKKALB52WS2IZWYBDGY6EQBLEED3TJOCVMZRH7H", } - testOperationsMarshallingRoundtrip(t, []Operation{&inflation}, false) + testOperationsMarshalingRoundtrip(t, []Operation{&inflation}, false) // with muxed accounts inflation = Inflation{ SourceAccount: "MA7QYNF7SOWQ3GLR2BGMZEHXAVIRZA4KVWLTJJFC7MGXUA74P7UJVAAAAAAAAAAAAAJLK", } - testOperationsMarshallingRoundtrip(t, []Operation{&inflation}, true) + testOperationsMarshalingRoundtrip(t, []Operation{&inflation}, true) } diff --git a/txnbuild/invoke_host_function.go b/txnbuild/invoke_host_function.go new file mode 100644 index 0000000000..c278b5f81c --- /dev/null +++ b/txnbuild/invoke_host_function.go @@ -0,0 +1,63 @@ +package txnbuild + +import ( + "github.com/stellar/go/support/errors" + "github.com/stellar/go/xdr" +) + +type InvokeHostFunction struct { + HostFunction xdr.HostFunction + Auth []xdr.SorobanAuthorizationEntry + SourceAccount string + Ext xdr.TransactionExt +} + +func (f *InvokeHostFunction) BuildXDR() (xdr.Operation, error) { + + opType := xdr.OperationTypeInvokeHostFunction + xdrOp := xdr.InvokeHostFunctionOp{ + HostFunction: f.HostFunction, + Auth: f.Auth, + } + + body, err := xdr.NewOperationBody(opType, xdrOp) + if err != nil { + return xdr.Operation{}, errors.Wrap(err, "failed to build XDR Operation") + } + + op := xdr.Operation{Body: body} + + SetOpSourceAccount(&op, f.SourceAccount) + return op, nil +} + +func (f *InvokeHostFunction) FromXDR(xdrOp xdr.Operation) error { + result, ok := xdrOp.Body.GetInvokeHostFunctionOp() + if !ok { + return errors.New("error parsing invoke host function operation from xdr") + } + + f.SourceAccount = accountFromXDR(xdrOp.SourceAccount) + f.HostFunction = result.HostFunction + f.Auth = result.Auth + + return nil +} + +func (f *InvokeHostFunction) Validate() error { + if f.SourceAccount != "" { + _, err := xdr.AddressToMuxedAccount(f.SourceAccount) + if err != nil { + return NewValidationError("SourceAccount", err.Error()) + } + } + return nil +} + +func (f *InvokeHostFunction) GetSourceAccount() string { + return f.SourceAccount +} + +func (f *InvokeHostFunction) BuildTransactionExt() (xdr.TransactionExt, error) { + return f.Ext, nil +} diff --git a/txnbuild/invoke_host_function_test.go b/txnbuild/invoke_host_function_test.go new file mode 100644 index 0000000000..8fd5e6e48e --- /dev/null +++ b/txnbuild/invoke_host_function_test.go @@ -0,0 +1,158 @@ +package txnbuild + +import ( + "testing" + + "github.com/stellar/go/xdr" + + "github.com/stretchr/testify/assert" +) + +func TestCreateInvokeHostFunctionValid(t *testing.T) { + kp1 := newKeypair1() + sourceAccount := NewSimpleAccount(kp1.Address(), int64(41137196761100)) + + invokeHostFunctionOp := InvokeHostFunction{ + HostFunction: xdr.HostFunction{ + Type: xdr.HostFunctionTypeHostFunctionTypeInvokeContract, + InvokeContract: &xdr.InvokeContractArgs{}, + }, + Auth: []xdr.SorobanAuthorizationEntry{}, + SourceAccount: sourceAccount.AccountID, + } + + assert.NoError(t, invokeHostFunctionOp.Validate()) +} + +func TestCreateInvokeHostFunctionInvalid(t *testing.T) { + invokeHostFunctionOp := InvokeHostFunction{ + HostFunction: xdr.HostFunction{ + Type: xdr.HostFunctionTypeHostFunctionTypeInvokeContract, + InvokeContract: &xdr.InvokeContractArgs{}, + }, + Auth: []xdr.SorobanAuthorizationEntry{}, + SourceAccount: "invalid account value", + } + + assert.Error(t, invokeHostFunctionOp.Validate()) +} + +func TestInvokeHostFunctionRoundTrip(t *testing.T) { + val := xdr.Int32(4) + wasmId := xdr.Hash{1, 2, 3, 4} + i64 := xdr.Int64(45) + accountId := xdr.MustAddress("GB7BDSZU2Y27LYNLALKKALB52WS2IZWYBDGY6EQBLEED3TJOCVMZRH7H") + var invokeHostFunctionOp = &InvokeHostFunction{ + HostFunction: xdr.HostFunction{ + Type: xdr.HostFunctionTypeHostFunctionTypeInvokeContract, + InvokeContract: &xdr.InvokeContractArgs{ + ContractAddress: xdr.ScAddress{ + Type: xdr.ScAddressTypeScAddressTypeContract, + ContractId: &xdr.Hash{0x1, 0x2}, + }, + FunctionName: "foo", + Args: xdr.ScVec{ + xdr.ScVal{ + Type: xdr.ScValTypeScvI32, + I32: &val, + }, + }, + }, + }, + Auth: []xdr.SorobanAuthorizationEntry{ + { + Credentials: xdr.SorobanCredentials{ + Type: xdr.SorobanCredentialsTypeSorobanCredentialsAddress, + Address: &xdr.SorobanAddressCredentials{ + Address: xdr.ScAddress{ + Type: xdr.ScAddressTypeScAddressTypeAccount, + AccountId: &accountId, + }, + Nonce: 0, + SignatureExpirationLedger: 0, + Signature: xdr.ScVal{ + Type: xdr.ScValTypeScvI64, + I64: &i64, + }, + }, + }, + RootInvocation: xdr.SorobanAuthorizedInvocation{ + Function: xdr.SorobanAuthorizedFunction{ + Type: xdr.SorobanAuthorizedFunctionTypeSorobanAuthorizedFunctionTypeContractFn, + ContractFn: &xdr.InvokeContractArgs{ + ContractAddress: xdr.ScAddress{ + Type: xdr.ScAddressTypeScAddressTypeContract, + ContractId: &xdr.Hash{0x1, 0x2}, + }, + FunctionName: "foo", + Args: xdr.ScVec{ + xdr.ScVal{ + Type: xdr.ScValTypeScvI32, + I32: &val, + }, + }, + }, + }, + SubInvocations: nil, + }, + }, + }, + SourceAccount: "GB7BDSZU2Y27LYNLALKKALB52WS2IZWYBDGY6EQBLEED3TJOCVMZRH7H", + Ext: xdr.TransactionExt{ + V: 1, + SorobanData: &xdr.SorobanTransactionData{ + Resources: xdr.SorobanResources{ + Footprint: xdr.LedgerFootprint{ + ReadOnly: []xdr.LedgerKey{ + { + Type: xdr.LedgerEntryTypeContractData, + ContractData: &xdr.LedgerKeyContractData{ + Contract: xdr.ScAddress{ + Type: xdr.ScAddressTypeScAddressTypeContract, + ContractId: &xdr.Hash{1, 2, 3}, + }, + Key: xdr.ScVal{ + Type: xdr.ScValTypeScvContractInstance, + Instance: &xdr.ScContractInstance{ + Executable: xdr.ContractExecutable{ + Type: xdr.ContractExecutableTypeContractExecutableWasm, + WasmHash: &wasmId, + }, + }, + }, + }, + }, + }, + ReadWrite: []xdr.LedgerKey{ + { + Type: xdr.LedgerEntryTypeContractData, + ContractData: &xdr.LedgerKeyContractData{ + Contract: xdr.ScAddress{ + Type: xdr.ScAddressTypeScAddressTypeContract, + ContractId: &xdr.Hash{1, 2, 3}, + }, + Key: xdr.ScVal{ + Type: xdr.ScValTypeScvI64, + I64: &i64, + }, + }, + }, + }, + }, + Instructions: 0, + ReadBytes: 0, + WriteBytes: 0, + }, + ResourceFee: 1, + Ext: xdr.ExtensionPoint{ + V: 0, + }, + }, + }, + } + testOperationsMarshalingRoundtrip(t, []Operation{invokeHostFunctionOp}, false) + + // with muxed accounts + invokeHostFunctionOp.SourceAccount = "MA7QYNF7SOWQ3GLR2BGMZEHXAVIRZA4KVWLTJJFC7MGXUA74P7UJVAAAAAAAAAAAAAJLK" + testOperationsMarshalingRoundtrip(t, []Operation{invokeHostFunctionOp}, true) +} diff --git a/txnbuild/liquidity_pool_deposit_test.go b/txnbuild/liquidity_pool_deposit_test.go index 15f53ad67a..cf488f85c6 100644 --- a/txnbuild/liquidity_pool_deposit_test.go +++ b/txnbuild/liquidity_pool_deposit_test.go @@ -1,9 +1,10 @@ package txnbuild import ( - "github.com/stellar/go/price" "testing" + "github.com/stellar/go/price" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -67,7 +68,7 @@ func TestLiquidityPoolDepositRoundTrip(t *testing.T) { MaxPrice: price.MustParse("0.4"), } - testOperationsMarshallingRoundtrip(t, []Operation{lpd}, false) + testOperationsMarshalingRoundtrip(t, []Operation{lpd}, false) // with muxed accounts lpd = &LiquidityPoolDeposit{ @@ -79,5 +80,5 @@ func TestLiquidityPoolDepositRoundTrip(t *testing.T) { MaxPrice: price.MustParse("0.4"), } - testOperationsMarshallingRoundtrip(t, []Operation{lpd}, true) + testOperationsMarshalingRoundtrip(t, []Operation{lpd}, true) } diff --git a/txnbuild/liquidity_pool_withdraw_test.go b/txnbuild/liquidity_pool_withdraw_test.go index e503f36853..d2b172392e 100644 --- a/txnbuild/liquidity_pool_withdraw_test.go +++ b/txnbuild/liquidity_pool_withdraw_test.go @@ -62,7 +62,7 @@ func TestLiquidityPoolWithdrawRoundTrip(t *testing.T) { MinAmountB: "0.2000000", } - testOperationsMarshallingRoundtrip(t, []Operation{lpd}, false) + testOperationsMarshalingRoundtrip(t, []Operation{lpd}, false) // with muxed accounts lpd = &LiquidityPoolWithdraw{ @@ -73,5 +73,5 @@ func TestLiquidityPoolWithdrawRoundTrip(t *testing.T) { MinAmountB: "0.2000000", } - testOperationsMarshallingRoundtrip(t, []Operation{lpd}, true) + testOperationsMarshalingRoundtrip(t, []Operation{lpd}, true) } diff --git a/txnbuild/manage_buy_offer_test.go b/txnbuild/manage_buy_offer_test.go index 86422436e2..24a46656df 100644 --- a/txnbuild/manage_buy_offer_test.go +++ b/txnbuild/manage_buy_offer_test.go @@ -179,7 +179,7 @@ func TestManageBuyOfferRoundtrip(t *testing.T) { Price: price.MustParse("0.01"), OfferID: 0, } - testOperationsMarshallingRoundtrip(t, []Operation{&manageBuyOffer}, false) + testOperationsMarshalingRoundtrip(t, []Operation{&manageBuyOffer}, false) // with muxed accounts manageBuyOffer = ManageBuyOffer{ @@ -190,5 +190,5 @@ func TestManageBuyOfferRoundtrip(t *testing.T) { Price: price.MustParse("0.01"), OfferID: 0, } - testOperationsMarshallingRoundtrip(t, []Operation{&manageBuyOffer}, true) + testOperationsMarshalingRoundtrip(t, []Operation{&manageBuyOffer}, true) } diff --git a/txnbuild/manage_data_test.go b/txnbuild/manage_data_test.go index 19ac76f390..d7a768dc33 100644 --- a/txnbuild/manage_data_test.go +++ b/txnbuild/manage_data_test.go @@ -133,7 +133,7 @@ func TestManageDataRoundtrip(t *testing.T) { Name: "foo", Value: []byte("bar"), } - testOperationsMarshallingRoundtrip(t, []Operation{&manageData}, false) + testOperationsMarshalingRoundtrip(t, []Operation{&manageData}, false) // with muxed accounts manageData = ManageData{ @@ -141,5 +141,5 @@ func TestManageDataRoundtrip(t *testing.T) { Name: "foo", Value: []byte("bar"), } - testOperationsMarshallingRoundtrip(t, []Operation{&manageData}, true) + testOperationsMarshalingRoundtrip(t, []Operation{&manageData}, true) } diff --git a/txnbuild/manage_offer_test.go b/txnbuild/manage_offer_test.go index d2447b0d99..27c19dc408 100644 --- a/txnbuild/manage_offer_test.go +++ b/txnbuild/manage_offer_test.go @@ -171,7 +171,7 @@ func TestManageSellOfferRoundtrip(t *testing.T) { Price: price.MustParse("0.01"), OfferID: 0, } - testOperationsMarshallingRoundtrip(t, []Operation{&manageSellOffer}, false) + testOperationsMarshalingRoundtrip(t, []Operation{&manageSellOffer}, false) // with muxed accounts manageSellOffer = ManageSellOffer{ @@ -182,5 +182,5 @@ func TestManageSellOfferRoundtrip(t *testing.T) { Price: price.MustParse("0.01"), OfferID: 0, } - testOperationsMarshallingRoundtrip(t, []Operation{&manageSellOffer}, true) + testOperationsMarshalingRoundtrip(t, []Operation{&manageSellOffer}, true) } diff --git a/txnbuild/operation.go b/txnbuild/operation.go index d0e8ce1b70..a436271592 100644 --- a/txnbuild/operation.go +++ b/txnbuild/operation.go @@ -76,6 +76,12 @@ func operationFromXDR(xdrOp xdr.Operation) (Operation, error) { newOp = &LiquidityPoolDeposit{} case xdr.OperationTypeLiquidityPoolWithdraw: newOp = &LiquidityPoolWithdraw{} + case xdr.OperationTypeInvokeHostFunction: + newOp = &InvokeHostFunction{} + case xdr.OperationTypeExtendFootprintTtl: + newOp = &ExtendFootprintTtl{} + case xdr.OperationTypeRestoreFootprint: + newOp = &RestoreFootprint{} default: return nil, fmt.Errorf("unknown operation type: %d", xdrOp.Body.Type) } @@ -90,3 +96,8 @@ func accountFromXDR(account *xdr.MuxedAccount) string { } return "" } + +// SorobanOperation represents a smart contract operation on the Stellar network. +type SorobanOperation interface { + BuildTransactionExt() (xdr.TransactionExt, error) +} diff --git a/txnbuild/operation_test.go b/txnbuild/operation_test.go index 1fe40dea4c..75b340d3d4 100644 --- a/txnbuild/operation_test.go +++ b/txnbuild/operation_test.go @@ -4,7 +4,10 @@ import ( "testing" "github.com/stellar/go/amount" + "github.com/stellar/go/gxdr" + "github.com/stellar/go/randxdr" "github.com/stellar/go/xdr" + goxdr "github.com/xdrpp/goxdr/xdr" "github.com/stretchr/testify/assert" ) @@ -445,7 +448,7 @@ func TestBumpSequenceFromXDR(t *testing.T) { } } -func testOperationsMarshallingRoundtrip(t *testing.T, operations []Operation, withMuxedAccounts bool) { +func testOperationsMarshalingRoundtrip(t *testing.T, operations []Operation, withMuxedAccounts bool) { kp1 := newKeypair1() accountID := xdr.MustAddress(kp1.Address()) mx := xdr.MuxedAccount{ @@ -491,3 +494,33 @@ func testOperationsMarshallingRoundtrip(t *testing.T, operations []Operation, wi assert.Equal(t, operations[i], tx.Operations()[i]) } } + +func TestOperationCoverage(t *testing.T) { + gen := randxdr.NewGenerator() + for i := 0; i < 10000; i++ { + op := xdr.Operation{} + shape := &gxdr.Operation{} + gen.Next( + shape, + []randxdr.Preset{ + {randxdr.IsDeepAuthorizedInvocationTree, randxdr.SetVecLen(0)}, + { + randxdr.FieldEquals("body.revokeSponsorshipOp.ledgerKey.type"), + randxdr.SetU32( + gxdr.ACCOUNT.GetU32(), + gxdr.TRUSTLINE.GetU32(), + gxdr.OFFER.GetU32(), + gxdr.DATA.GetU32(), + gxdr.CLAIMABLE_BALANCE.GetU32(), + ), + }, + }, + ) + assert.NoError(t, gxdr.Convert(shape, &op)) + + _, err := operationFromXDR(op) + if !assert.NoError(t, err) { + t.Log(goxdr.XdrToString(shape)) + } + } +} diff --git a/txnbuild/path_payment_strict_send_test.go b/txnbuild/path_payment_strict_send_test.go index 7e0a97da77..3cc09a98f7 100644 --- a/txnbuild/path_payment_strict_send_test.go +++ b/txnbuild/path_payment_strict_send_test.go @@ -167,7 +167,7 @@ func TestPathPaymentStrictSendRoundtrip(t *testing.T) { DestMin: "1.0000000", Path: []Asset{CreditAsset{"ABCD", "GB7BDSZU2Y27LYNLALKKALB52WS2IZWYBDGY6EQBLEED3TJOCVMZRH7H"}}, } - testOperationsMarshallingRoundtrip(t, []Operation{&pathPaymentStrictSend}, false) + testOperationsMarshalingRoundtrip(t, []Operation{&pathPaymentStrictSend}, false) // with muxed accounts pathPaymentStrictSend = PathPaymentStrictSend{ @@ -179,5 +179,5 @@ func TestPathPaymentStrictSendRoundtrip(t *testing.T) { DestMin: "1.0000000", Path: []Asset{CreditAsset{"ABCD", "GB7BDSZU2Y27LYNLALKKALB52WS2IZWYBDGY6EQBLEED3TJOCVMZRH7H"}}, } - testOperationsMarshallingRoundtrip(t, []Operation{&pathPaymentStrictSend}, true) + testOperationsMarshalingRoundtrip(t, []Operation{&pathPaymentStrictSend}, true) } diff --git a/txnbuild/path_payment_test.go b/txnbuild/path_payment_test.go index 5e3ae7b980..665aa9f4c9 100644 --- a/txnbuild/path_payment_test.go +++ b/txnbuild/path_payment_test.go @@ -167,7 +167,7 @@ func TestPathPaymentRoundtrip(t *testing.T) { DestAmount: "1.0000000", Path: []Asset{CreditAsset{"ABCD", "GB7BDSZU2Y27LYNLALKKALB52WS2IZWYBDGY6EQBLEED3TJOCVMZRH7H"}}, } - testOperationsMarshallingRoundtrip(t, []Operation{&pathPayment}, false) + testOperationsMarshalingRoundtrip(t, []Operation{&pathPayment}, false) // with muxed accounts pathPayment = PathPayment{ @@ -179,5 +179,5 @@ func TestPathPaymentRoundtrip(t *testing.T) { DestAmount: "1.0000000", Path: []Asset{CreditAsset{"ABCD", "GB7BDSZU2Y27LYNLALKKALB52WS2IZWYBDGY6EQBLEED3TJOCVMZRH7H"}}, } - testOperationsMarshallingRoundtrip(t, []Operation{&pathPayment}, true) + testOperationsMarshalingRoundtrip(t, []Operation{&pathPayment}, true) } diff --git a/txnbuild/payment_test.go b/txnbuild/payment_test.go index 4ee33e8871..19407300b8 100644 --- a/txnbuild/payment_test.go +++ b/txnbuild/payment_test.go @@ -88,7 +88,7 @@ func TestPaymentRoundtrip(t *testing.T) { Amount: "10.0000000", Asset: NativeAsset{}, } - testOperationsMarshallingRoundtrip(t, []Operation{&payment}, false) + testOperationsMarshalingRoundtrip(t, []Operation{&payment}, false) // with muxed accounts payment = Payment{ @@ -97,5 +97,5 @@ func TestPaymentRoundtrip(t *testing.T) { Amount: "10.0000000", Asset: NativeAsset{}, } - testOperationsMarshallingRoundtrip(t, []Operation{&payment}, true) + testOperationsMarshalingRoundtrip(t, []Operation{&payment}, true) } diff --git a/txnbuild/restore_footprint.go b/txnbuild/restore_footprint.go new file mode 100644 index 0000000000..d71a94fb4b --- /dev/null +++ b/txnbuild/restore_footprint.go @@ -0,0 +1,56 @@ +package txnbuild + +import ( + "github.com/stellar/go/support/errors" + "github.com/stellar/go/xdr" +) + +type RestoreFootprint struct { + SourceAccount string + Ext xdr.TransactionExt +} + +func (f *RestoreFootprint) BuildXDR() (xdr.Operation, error) { + xdrOp := xdr.RestoreFootprintOp{ + Ext: xdr.ExtensionPoint{ + V: 0, + }, + } + + body, err := xdr.NewOperationBody(xdr.OperationTypeRestoreFootprint, xdrOp) + if err != nil { + return xdr.Operation{}, errors.Wrap(err, "failed to build XDR Operation") + } + + op := xdr.Operation{Body: body} + + SetOpSourceAccount(&op, f.SourceAccount) + return op, nil +} + +func (f *RestoreFootprint) FromXDR(xdrOp xdr.Operation) error { + _, ok := xdrOp.Body.GetRestoreFootprintOp() + if !ok { + return errors.New("error parsing invoke host function operation from xdr") + } + f.SourceAccount = accountFromXDR(xdrOp.SourceAccount) + return nil +} + +func (f *RestoreFootprint) Validate() error { + if f.SourceAccount != "" { + _, err := xdr.AddressToMuxedAccount(f.SourceAccount) + if err != nil { + return NewValidationError("SourceAccount", err.Error()) + } + } + return nil +} + +func (f *RestoreFootprint) GetSourceAccount() string { + return f.SourceAccount +} + +func (f *RestoreFootprint) BuildTransactionExt() (xdr.TransactionExt, error) { + return f.Ext, nil +} diff --git a/txnbuild/revoke_sponsorship.go b/txnbuild/revoke_sponsorship.go index cee5139efe..ff229c296a 100644 --- a/txnbuild/revoke_sponsorship.go +++ b/txnbuild/revoke_sponsorship.go @@ -162,7 +162,7 @@ func (r *RevokeSponsorship) FromXDR(xdrOp xdr.Operation) error { r.SourceAccount = accountFromXDR(xdrOp.SourceAccount) op, ok := xdrOp.Body.GetRevokeSponsorshipOp() if !ok { - return errors.New("error parsing revoke_sponsorhip operation from xdr") + return errors.New("error parsing revoke_sponsorship operation from xdr") } switch op.Type { case xdr.RevokeSponsorshipTypeRevokeSponsorshipLedgerEntry: diff --git a/txnbuild/revoke_sponsorship_test.go b/txnbuild/revoke_sponsorship_test.go index 83632e8682..c886ef9fcf 100644 --- a/txnbuild/revoke_sponsorship_test.go +++ b/txnbuild/revoke_sponsorship_test.go @@ -98,7 +98,7 @@ func TestRevokeSponsorship(t *testing.T) { var op2 RevokeSponsorship assert.NoError(t, op2.FromXDR(xdrOp2)) assert.Equal(t, op, op2) - testOperationsMarshallingRoundtrip(t, []Operation{&testcase.op}, false) + testOperationsMarshalingRoundtrip(t, []Operation{&testcase.op}, false) }) } @@ -108,7 +108,7 @@ func TestRevokeSponsorship(t *testing.T) { SponsorshipType: RevokeSponsorshipTypeAccount, Account: &accountAddress, } - testOperationsMarshallingRoundtrip(t, []Operation{&revokeOp}, false) + testOperationsMarshalingRoundtrip(t, []Operation{&revokeOp}, false) // with muxed accounts revokeOp = RevokeSponsorship{ @@ -116,5 +116,5 @@ func TestRevokeSponsorship(t *testing.T) { SponsorshipType: RevokeSponsorshipTypeAccount, Account: &accountAddress, } - testOperationsMarshallingRoundtrip(t, []Operation{&revokeOp}, true) + testOperationsMarshalingRoundtrip(t, []Operation{&revokeOp}, true) } diff --git a/txnbuild/set_trustline_flags_test.go b/txnbuild/set_trustline_flags_test.go index ee56c618b0..36c93a82cc 100644 --- a/txnbuild/set_trustline_flags_test.go +++ b/txnbuild/set_trustline_flags_test.go @@ -88,7 +88,7 @@ func TestSetTrustLineFlags(t *testing.T) { var op2 SetTrustLineFlags assert.NoError(t, op2.FromXDR(xdrOp2)) assert.Equal(t, op, op2) - testOperationsMarshallingRoundtrip(t, []Operation{&testcase.op}, false) + testOperationsMarshalingRoundtrip(t, []Operation{&testcase.op}, false) }) } @@ -100,5 +100,5 @@ func TestSetTrustLineFlags(t *testing.T) { ClearFlags: []TrustLineFlag{TrustLineAuthorized, TrustLineAuthorizedToMaintainLiabilities}, SourceAccount: "MA7QYNF7SOWQ3GLR2BGMZEHXAVIRZA4KVWLTJJFC7MGXUA74P7UJVAAAAAAAAAAAAAJLK", } - testOperationsMarshallingRoundtrip(t, []Operation{&setTrustLineFlags}, true) + testOperationsMarshalingRoundtrip(t, []Operation{&setTrustLineFlags}, true) } diff --git a/txnbuild/timebounds.go b/txnbuild/timebounds.go index 1019497c2e..2be8cb1c5c 100644 --- a/txnbuild/timebounds.go +++ b/txnbuild/timebounds.go @@ -28,7 +28,7 @@ type Timebounds = TimeBounds // Validate for TimeBounds sanity-checks the configured Timebound limits, and confirms the object was built // using a factory method. This is done to ensure that default Timebound structs (which have no limits) are not -// valid - you must explicitly specifiy the Timebound you require. +// valid - you must explicitly specify the Timebound you require. func (tb *TimeBounds) Validate() error { if tb == nil || !tb.wasBuilt { return errors.New("timebounds must be constructed using NewTimebounds(), NewTimeout(), or NewInfiniteTimeout()") diff --git a/txnbuild/transaction.go b/txnbuild/transaction.go index ce95bba2ff..0cf284fe02 100644 --- a/txnbuild/transaction.go +++ b/txnbuild/transaction.go @@ -139,7 +139,7 @@ func stringsToKP(keys ...string) ([]*keypair.Full, error) { func concatHashX(signatures []xdr.DecoratedSignature, preimage []byte) ([]xdr.DecoratedSignature, error) { if maxSize := xdr.Signature(preimage).XDRMaxSize(); len(preimage) > maxSize { return nil, errors.Errorf( - "preimage cannnot be more than %d bytes", maxSize, + "preimage cannot be more than %d bytes", maxSize, ) } extended := make( @@ -785,6 +785,12 @@ func transactionFromParsedXDR(xdrEnv xdr.TransactionEnvelope) (*GenericTransacti if err != nil { return nil, err } + // if it's a soroban transaction, and we found a InvokeHostFunction operation. + if xdrEnv.V1 != nil && xdrEnv.V1.Tx.Ext.V != 0 { + if invoke, ok := newOp.(*InvokeHostFunction); ok { + invoke.Ext = xdrEnv.V1.Tx.Ext + } + } newTx.simple.operations = append(newTx.simple.operations, newOp) } @@ -876,13 +882,16 @@ func NewTransaction(params TransactionParams) (*Transaction, error) { // Handle the memo, if one is present if tx.memo != nil { - xdrMemo, err := tx.memo.ToXDR() + var xdrMemo xdr.Memo + xdrMemo, err = tx.memo.ToXDR() if err != nil { return nil, errors.Wrap(err, "couldn't build memo XDR") } envelope.V1.Tx.Memo = xdrMemo } + var sorobanOp SorobanOperation + for _, op := range tx.operations { if verr := op.Validate(); verr != nil { return nil, errors.Wrap(verr, fmt.Sprintf("validation failed for %T operation", op)) @@ -892,6 +901,20 @@ func NewTransaction(params TransactionParams) (*Transaction, error) { return nil, errors.Wrap(err2, fmt.Sprintf("failed to build operation %T", op)) } envelope.V1.Tx.Operations = append(envelope.V1.Tx.Operations, xdrOperation) + + if scOp, ok := op.(SorobanOperation); ok { + // this is a smart contract operation. + // smart contract operations are limited to 1 operation / transaction. + sorobanOp = scOp + } + } + + // In case it's a smart contract transaction, we need to include the Ext field within the envelope. + if sorobanOp != nil { + envelope.V1.Tx.Ext, err = sorobanOp.BuildTransactionExt() + if err != nil { + return nil, errors.Wrap(err, fmt.Sprintf("failed to build operation %T", sorobanOp)) + } } tx.envelope = envelope @@ -998,8 +1021,9 @@ func NewFeeBumpTransaction(params FeeBumpTransactionParams) (*FeeBumpTransaction // BuildChallengeTx is a factory method that creates a valid SEP 10 challenge, for use in web authentication. // "timebound" is the time duration the transaction should be valid for, and must be greater than 1s (300s is recommended). +// Muxed accounts or ID memos can be provided to identity a user of a shared Stellar account. // More details on SEP 10: https://github.com/stellar/stellar-protocol/blob/master/ecosystem/sep-0010.md -func BuildChallengeTx(serverSignerSecret, clientAccountID, webAuthDomain, homeDomain, network string, timebound time.Duration) (*Transaction, error) { +func BuildChallengeTx(serverSignerSecret, clientAccountID, webAuthDomain, homeDomain, network string, timebound time.Duration, memo *MemoID) (*Transaction, error) { if timebound < time.Second { return nil, errors.New("provided timebound must be at least 1s (300s is recommended)") } @@ -1021,7 +1045,11 @@ func BuildChallengeTx(serverSignerSecret, clientAccountID, webAuthDomain, homeDo } if _, err = xdr.AddressToAccountId(clientAccountID); err != nil { - return nil, errors.Wrapf(err, "%s is not a valid account id", clientAccountID) + if _, err = xdr.AddressToMuxedAccount(clientAccountID); err != nil { + return nil, errors.Wrapf(err, "%s is not a valid account id or muxed account", clientAccountID) + } else if memo != nil { + return nil, errors.New("memos are not valid for challenge transactions with a muxed client account") + } } // represent server signing account as SimpleAccount @@ -1035,29 +1063,32 @@ func BuildChallengeTx(serverSignerSecret, clientAccountID, webAuthDomain, homeDo // Create a SEP 10 compatible response. See // https://github.com/stellar/stellar-protocol/blob/master/ecosystem/sep-0010.md#response - tx, err := NewTransaction( - TransactionParams{ - SourceAccount: &sa, - IncrementSequenceNum: false, - Operations: []Operation{ - &ManageData{ - SourceAccount: clientAccountID, - Name: homeDomain + " auth", - Value: []byte(randomNonceToString), - }, - &ManageData{ - SourceAccount: serverKP.Address(), - Name: "web_auth_domain", - Value: []byte(webAuthDomain), - }, + txParams := TransactionParams{ + SourceAccount: &sa, + IncrementSequenceNum: false, + Operations: []Operation{ + &ManageData{ + SourceAccount: clientAccountID, + Name: homeDomain + " auth", + Value: []byte(randomNonceToString), }, - BaseFee: MinBaseFee, - Memo: nil, - Preconditions: Preconditions{ - TimeBounds: NewTimebounds(currentTime.Unix(), maxTime.Unix()), + &ManageData{ + SourceAccount: serverKP.Address(), + Name: "web_auth_domain", + Value: []byte(webAuthDomain), }, }, - ) + BaseFee: MinBaseFee, + Preconditions: Preconditions{ + TimeBounds: NewTimebounds(currentTime.Unix(), maxTime.Unix()), + }, + } + // Do not replace this if-then-assign block by assigning `memo` within the `TransactionParams` + // struct above. Doing so will cause errors as described here: https://go.dev/doc/faq#nil_error + if memo != nil { + txParams.Memo = memo + } + tx, err := NewTransaction(txParams) if err != nil { return nil, err } @@ -1105,57 +1136,61 @@ func generateRandomNonce(n int) ([]byte, error) { // one of the following functions to completely verify the transaction: // - VerifyChallengeTxThreshold // - VerifyChallengeTxSigners -func ReadChallengeTx(challengeTx, serverAccountID, network, webAuthDomain string, homeDomains []string) (tx *Transaction, clientAccountID string, matchedHomeDomain string, err error) { +// +// The returned clientAccountID may be a Stellar account (G...) or Muxed account (M...) address. If +// the address is muxed, or if the memo returned is non-nil, the challenge transaction +// is being used to authenticate a user of a shared Stellar account. +func ReadChallengeTx(challengeTx, serverAccountID, network, webAuthDomain string, homeDomains []string) (tx *Transaction, clientAccountID string, matchedHomeDomain string, memo *MemoID, err error) { parsed, err := TransactionFromXDR(challengeTx) if err != nil { - return tx, clientAccountID, matchedHomeDomain, errors.Wrap(err, "could not parse challenge") + return tx, clientAccountID, matchedHomeDomain, memo, errors.Wrap(err, "could not parse challenge") } var isSimple bool tx, isSimple = parsed.Transaction() if !isSimple { - return tx, clientAccountID, matchedHomeDomain, errors.New("challenge cannot be a fee bump transaction") + return tx, clientAccountID, matchedHomeDomain, memo, errors.New("challenge cannot be a fee bump transaction") } // Enforce no muxed accounts (at least until we understand their impact) if tx.envelope.SourceAccount().Type == xdr.CryptoKeyTypeKeyTypeMuxedEd25519 { err = errors.New("invalid source account: only valid Ed25519 accounts are allowed in challenge transactions") - return tx, clientAccountID, matchedHomeDomain, err + return tx, clientAccountID, matchedHomeDomain, memo, err } // verify transaction source if tx.SourceAccount().AccountID != serverAccountID { - return tx, clientAccountID, matchedHomeDomain, errors.New("transaction source account is not equal to server's account") + return tx, clientAccountID, matchedHomeDomain, memo, errors.New("transaction source account is not equal to server's account") } // verify sequence number if tx.SourceAccount().Sequence != 0 { - return tx, clientAccountID, matchedHomeDomain, errors.New("transaction sequence number must be 0") + return tx, clientAccountID, matchedHomeDomain, memo, errors.New("transaction sequence number must be 0") } // verify timebounds if tx.Timebounds().MaxTime == TimeoutInfinite { - return tx, clientAccountID, matchedHomeDomain, errors.New("transaction requires non-infinite timebounds") + return tx, clientAccountID, matchedHomeDomain, memo, errors.New("transaction requires non-infinite timebounds") } // Apply a grace period to the challenge MinTime to account for clock drift between the server and client var gracePeriod int64 = 5 * 60 // seconds currentTime := time.Now().UTC().Unix() if currentTime+gracePeriod < tx.Timebounds().MinTime || currentTime > tx.Timebounds().MaxTime { - return tx, clientAccountID, matchedHomeDomain, errors.Errorf("transaction is not within range of the specified timebounds (currentTime=%d, MinTime=%d, MaxTime=%d)", + return tx, clientAccountID, matchedHomeDomain, memo, errors.Errorf("transaction is not within range of the specified timebounds (currentTime=%d, MinTime=%d, MaxTime=%d)", currentTime, tx.Timebounds().MinTime, tx.Timebounds().MaxTime) } // verify operation operations := tx.Operations() if len(operations) < 1 { - return tx, clientAccountID, matchedHomeDomain, errors.New("transaction requires at least one manage_data operation") + return tx, clientAccountID, matchedHomeDomain, memo, errors.New("transaction requires at least one manage_data operation") } op, ok := operations[0].(*ManageData) if !ok { - return tx, clientAccountID, matchedHomeDomain, errors.New("operation type should be manage_data") + return tx, clientAccountID, matchedHomeDomain, memo, errors.New("operation type should be manage_data") } if op.SourceAccount == "" { - return tx, clientAccountID, matchedHomeDomain, errors.New("operation should have a source account") + return tx, clientAccountID, matchedHomeDomain, memo, errors.New("operation should have a source account") } for _, homeDomain := range homeDomains { if op.Name == homeDomain+" auth" { @@ -1164,60 +1199,72 @@ func ReadChallengeTx(challengeTx, serverAccountID, network, webAuthDomain string } } if matchedHomeDomain == "" { - return tx, clientAccountID, matchedHomeDomain, errors.Errorf("operation key does not match any homeDomains passed (key=%q, homeDomains=%v)", op.Name, homeDomains) + return tx, clientAccountID, matchedHomeDomain, memo, errors.Errorf("operation key does not match any homeDomains passed (key=%q, homeDomains=%v)", op.Name, homeDomains) } clientAccountID = op.SourceAccount - rawOperations := tx.envelope.Operations() - if len(rawOperations) > 0 && rawOperations[0].SourceAccount.Type == xdr.CryptoKeyTypeKeyTypeMuxedEd25519 { - err = errors.New("invalid operation source account: only valid Ed25519 accounts are allowed in challenge transactions") - return tx, clientAccountID, matchedHomeDomain, err + firstOpSourceAccountType := tx.envelope.Operations()[0].SourceAccount.Type + if firstOpSourceAccountType != xdr.CryptoKeyTypeKeyTypeMuxedEd25519 && firstOpSourceAccountType != xdr.CryptoKeyTypeKeyTypeEd25519 { + err = errors.New("invalid source account for first operation: only valid Ed25519 or muxed accounts are valid") + return tx, clientAccountID, matchedHomeDomain, memo, err + } + if tx.Memo() != nil { + if firstOpSourceAccountType == xdr.CryptoKeyTypeKeyTypeMuxedEd25519 { + err = errors.New("memos are not valid for challenge transactions with a muxed client account") + return tx, clientAccountID, matchedHomeDomain, memo, err + } + var txMemo MemoID + if txMemo, ok = (tx.Memo()).(MemoID); !ok { + err = errors.New("invalid memo, only ID memos are permitted") + return tx, clientAccountID, matchedHomeDomain, memo, err + } + memo = &txMemo } // verify manage data value nonceB64 := string(op.Value) if len(nonceB64) != 64 { - return tx, clientAccountID, matchedHomeDomain, errors.New("random nonce encoded as base64 should be 64 bytes long") + return tx, clientAccountID, matchedHomeDomain, memo, errors.New("random nonce encoded as base64 should be 64 bytes long") } nonceBytes, err := base64.StdEncoding.DecodeString(nonceB64) if err != nil { - return tx, clientAccountID, matchedHomeDomain, errors.Wrap(err, "failed to decode random nonce provided in manage_data operation") + return tx, clientAccountID, matchedHomeDomain, memo, errors.Wrap(err, "failed to decode random nonce provided in manage_data operation") } if len(nonceBytes) != 48 { - return tx, clientAccountID, matchedHomeDomain, errors.New("random nonce before encoding as base64 should be 48 bytes long") + return tx, clientAccountID, matchedHomeDomain, memo, errors.New("random nonce before encoding as base64 should be 48 bytes long") } // verify subsequent operations are manage data ops and known, or unknown with source account set to server account for _, op := range operations[1:] { op, ok := op.(*ManageData) if !ok { - return tx, clientAccountID, matchedHomeDomain, errors.New("operation type should be manage_data") + return tx, clientAccountID, matchedHomeDomain, memo, errors.New("operation type should be manage_data") } if op.SourceAccount == "" { - return tx, clientAccountID, matchedHomeDomain, errors.New("operation should have a source account") + return tx, clientAccountID, matchedHomeDomain, memo, errors.New("operation should have a source account") } switch op.Name { case "web_auth_domain": if op.SourceAccount != serverAccountID { - return tx, clientAccountID, matchedHomeDomain, errors.New("web auth domain operation must have server source account") + return tx, clientAccountID, matchedHomeDomain, memo, errors.New("web auth domain operation must have server source account") } if !bytes.Equal(op.Value, []byte(webAuthDomain)) { - return tx, clientAccountID, matchedHomeDomain, errors.Errorf("web auth domain operation value is %q but expect %q", string(op.Value), webAuthDomain) + return tx, clientAccountID, matchedHomeDomain, memo, errors.Errorf("web auth domain operation value is %q but expect %q", string(op.Value), webAuthDomain) } default: // verify unknown subsequent operations are manage data ops with source account set to server account if op.SourceAccount != serverAccountID { - return tx, clientAccountID, matchedHomeDomain, errors.New("subsequent operations are unrecognized") + return tx, clientAccountID, matchedHomeDomain, memo, errors.New("subsequent operations are unrecognized") } } } err = verifyTxSignature(tx, network, serverAccountID) if err != nil { - return tx, clientAccountID, matchedHomeDomain, err + return tx, clientAccountID, matchedHomeDomain, memo, err } - return tx, clientAccountID, matchedHomeDomain, nil + return tx, clientAccountID, matchedHomeDomain, memo, nil } // VerifyChallengeTxThreshold verifies that for a SEP 10 challenge transaction @@ -1289,7 +1336,7 @@ func VerifyChallengeTxThreshold(challengeTx, serverAccountID, network, webAuthDo // server account or one of the signers provided in the arguments. func VerifyChallengeTxSigners(challengeTx, serverAccountID, network, webAuthDomain string, homeDomains []string, signers ...string) ([]string, error) { // Read the transaction which validates its structure. - tx, _, _, err := ReadChallengeTx(challengeTx, serverAccountID, network, webAuthDomain, homeDomains) + tx, _, _, _, err := ReadChallengeTx(challengeTx, serverAccountID, network, webAuthDomain, homeDomains) if err != nil { return nil, err } diff --git a/txnbuild/transaction_challenge_example_test.go b/txnbuild/transaction_challenge_example_test.go index a183aa44f4..a0db63064a 100644 --- a/txnbuild/transaction_challenge_example_test.go +++ b/txnbuild/transaction_challenge_example_test.go @@ -37,7 +37,7 @@ func ExampleVerifyChallengeTxThreshold() { // Server builds challenge transaction var challengeTx string { - tx, err := txnbuild.BuildChallengeTx(serverAccount.Seed(), clientAccount.Address(), "webauthdomain.stellar.org", "test", network.TestNetworkPassphrase, time.Minute) + tx, err := txnbuild.BuildChallengeTx(serverAccount.Seed(), clientAccount.Address(), "webauthdomain.stellar.org", "test", network.TestNetworkPassphrase, time.Minute, nil) if err != nil { fmt.Println("Error:", err) return @@ -52,7 +52,7 @@ func ExampleVerifyChallengeTxThreshold() { // Client reads and signs challenge transaction var signedChallengeTx string { - tx, txClientAccountID, _, err := txnbuild.ReadChallengeTx(challengeTx, serverAccount.Address(), network.TestNetworkPassphrase, "webauthdomain.stellar.org", []string{"test"}) + tx, txClientAccountID, _, _, err := txnbuild.ReadChallengeTx(challengeTx, serverAccount.Address(), network.TestNetworkPassphrase, "webauthdomain.stellar.org", []string{"test"}) if err != nil { fmt.Println("Error:", err) return @@ -75,10 +75,13 @@ func ExampleVerifyChallengeTxThreshold() { // Server verifies signed challenge transaction { - _, txClientAccountID, _, err := txnbuild.ReadChallengeTx(challengeTx, serverAccount.Address(), network.TestNetworkPassphrase, "webauthdomain.stellar.org", []string{"test"}) + _, txClientAccountID, _, memo, err := txnbuild.ReadChallengeTx(challengeTx, serverAccount.Address(), network.TestNetworkPassphrase, "webauthdomain.stellar.org", []string{"test"}) if err != nil { fmt.Println("Error:", err) return + } else if memo != nil { + fmt.Println("Expected memo to be nil, got: ", memo) + return } // Server gets account diff --git a/txnbuild/transaction_test.go b/txnbuild/transaction_test.go index b813dd8b95..f8fce12e9c 100644 --- a/txnbuild/transaction_test.go +++ b/txnbuild/transaction_test.go @@ -1073,7 +1073,7 @@ func TestBuildChallengeTx(t *testing.T) { { // 1 minute timebound - tx, err := BuildChallengeTx(kp0.Seed(), kp0.Address(), "testwebauth.stellar.org", "testanchor.stellar.org", network.TestNetworkPassphrase, time.Minute) + tx, err := BuildChallengeTx(kp0.Seed(), kp0.Address(), "testwebauth.stellar.org", "testanchor.stellar.org", network.TestNetworkPassphrase, time.Minute, nil) assert.NoError(t, err) txeBase64, err := tx.Base64() assert.NoError(t, err) @@ -1097,7 +1097,7 @@ func TestBuildChallengeTx(t *testing.T) { { // 5 minutes timebound - tx, err := BuildChallengeTx(kp0.Seed(), kp0.Address(), "testwebauth.stellar.org", "testanchor.stellar.org", network.TestNetworkPassphrase, time.Duration(5*time.Minute)) + tx, err := BuildChallengeTx(kp0.Seed(), kp0.Address(), "testwebauth.stellar.org", "testanchor.stellar.org", network.TestNetworkPassphrase, time.Duration(5*time.Minute), nil) assert.NoError(t, err) txeBase64, err := tx.Base64() assert.NoError(t, err) @@ -1120,8 +1120,37 @@ func TestBuildChallengeTx(t *testing.T) { assert.Equal(t, "testwebauth.stellar.org", string(*webAuthOp.Body.ManageDataOp.DataValue), "DataValue should be 'testwebauth.stellar.org'") } + // transaction with invalid clientAccountID + { + _, err := BuildChallengeTx(kp0.Seed(), "test", "testwebauth.stellar.org", "testanchor.stellar.org", network.TestNetworkPassphrase, time.Minute, nil) + require.EqualError(t, err, "test is not a valid account id or muxed account: invalid address length") + } + + // transaction with memo + { + var memo MemoID = MemoID(1) + tx, err := BuildChallengeTx(kp0.Seed(), kp0.Address(), "testwebauth.stellar.org", "testanchor.stellar.org", network.TestNetworkPassphrase, time.Minute, &memo) + assert.NoError(t, err) + assert.Equal(t, tx.Memo(), &memo) + } + + // transaction with muxed account + { + muxedAccount := "MA7QYNF7SOWQ3GLR2BGMZEHXAVIRZA4KVWLTJJFC7MGXUA74P7UJVAAAAAAAAAAAAAJLK" + tx, err := BuildChallengeTx(kp0.Seed(), muxedAccount, "testwebauth.stellar.org", "testanchor.stellar.org", network.TestNetworkPassphrase, time.Minute, nil) + assert.NoError(t, err) + assert.Equal(t, tx.operations[0].GetSourceAccount(), muxedAccount) + } + + // transaction with memo and muxed account + { + var memo MemoID = MemoID(1) + _, err := BuildChallengeTx(kp0.Seed(), "MA7QYNF7SOWQ3GLR2BGMZEHXAVIRZA4KVWLTJJFC7MGXUA74P7UJVAAAAAAAAAAAAAJLK", "testwebauth.stellar.org", "testanchor.stellar.org", network.TestNetworkPassphrase, time.Minute, &memo) + assert.EqualError(t, err, "memos are not valid for challenge transactions with a muxed client account") + } + //transaction with infinite timebound - _, err := BuildChallengeTx(kp0.Seed(), kp0.Address(), "webauthdomain", "sdf", network.TestNetworkPassphrase, 0) + _, err := BuildChallengeTx(kp0.Seed(), kp0.Address(), "webauthdomain", "sdf", network.TestNetworkPassphrase, 0, nil) if assert.Error(t, err) { assert.Contains(t, err.Error(), "provided timebound must be at least 1s (300s is recommended)") } @@ -1878,7 +1907,7 @@ func TestReadChallengeTx_validSignedByServerAndClient(t *testing.T) { assert.NoError(t, err) tx64, err := tx.Base64() require.NoError(t, err) - readTx, readClientAccountID, _, err := ReadChallengeTx(tx64, serverKP.Address(), network.TestNetworkPassphrase, "testwebauth.stellar.org", []string{"testanchor.stellar.org"}) + readTx, readClientAccountID, _, _, err := ReadChallengeTx(tx64, serverKP.Address(), network.TestNetworkPassphrase, "testwebauth.stellar.org", []string{"testanchor.stellar.org"}) assert.Equal(t, tx, readTx) assert.Equal(t, clientKP.Address(), readClientAccountID) assert.NoError(t, err) @@ -1913,7 +1942,7 @@ func TestReadChallengeTx_validSignedByServer(t *testing.T) { assert.NoError(t, err) tx64, err := tx.Base64() require.NoError(t, err) - readTx, readClientAccountID, _, err := ReadChallengeTx(tx64, serverKP.Address(), network.TestNetworkPassphrase, "testwebauth.stellar.org", []string{"testanchor.stellar.org"}) + readTx, readClientAccountID, _, _, err := ReadChallengeTx(tx64, serverKP.Address(), network.TestNetworkPassphrase, "testwebauth.stellar.org", []string{"testanchor.stellar.org"}) assert.Equal(t, tx, readTx) assert.Equal(t, clientKP.Address(), readClientAccountID) assert.NoError(t, err) @@ -1946,7 +1975,7 @@ func TestReadChallengeTx_invalidNotSignedByServer(t *testing.T) { tx64, err := tx.Base64() require.NoError(t, err) - readTx, readClientAccountID, _, err := ReadChallengeTx(tx64, serverKP.Address(), network.TestNetworkPassphrase, "testwebauth.stellar.org", []string{"testanchor.stellar.org"}) + readTx, readClientAccountID, _, _, err := ReadChallengeTx(tx64, serverKP.Address(), network.TestNetworkPassphrase, "testwebauth.stellar.org", []string{"testanchor.stellar.org"}) assert.Equal(t, tx, readTx) assert.Equal(t, clientKP.Address(), readClientAccountID) assert.EqualError(t, err, "transaction not signed by "+serverKP.Address()) @@ -1982,7 +2011,7 @@ func TestReadChallengeTx_invalidCorrupted(t *testing.T) { tx64, err := tx.Base64() require.NoError(t, err) tx64 = strings.ReplaceAll(tx64, "A", "B") - readTx, readClientAccountID, _, err := ReadChallengeTx(tx64, serverKP.Address(), network.TestNetworkPassphrase, "testwebauth.stellar.org", []string{"testanchor.stellar.org"}) + readTx, readClientAccountID, _, _, err := ReadChallengeTx(tx64, serverKP.Address(), network.TestNetworkPassphrase, "testwebauth.stellar.org", []string{"testanchor.stellar.org"}) assert.Nil(t, readTx) assert.Equal(t, "", readClientAccountID) assert.EqualError( @@ -2022,7 +2051,7 @@ func TestReadChallengeTx_invalidServerAccountIDMismatch(t *testing.T) { assert.NoError(t, err) tx64, err := tx.Base64() require.NoError(t, err) - readTx, readClientAccountID, _, err := ReadChallengeTx(tx64, serverKP.Address(), network.TestNetworkPassphrase, "testwebauth.stellar.org", []string{"testanchor.stellar.org"}) + readTx, readClientAccountID, _, _, err := ReadChallengeTx(tx64, serverKP.Address(), network.TestNetworkPassphrase, "testwebauth.stellar.org", []string{"testanchor.stellar.org"}) assert.Equal(t, tx, readTx) assert.Equal(t, "", readClientAccountID) assert.EqualError(t, err, "transaction source account is not equal to server's account") @@ -2057,7 +2086,7 @@ func TestReadChallengeTx_invalidSeqNoNotZero(t *testing.T) { assert.NoError(t, err) tx64, err := tx.Base64() require.NoError(t, err) - readTx, readClientAccountID, _, err := ReadChallengeTx(tx64, serverKP.Address(), network.TestNetworkPassphrase, "testwebauth.stellar.org", []string{"testanchor.stellar.org"}) + readTx, readClientAccountID, _, _, err := ReadChallengeTx(tx64, serverKP.Address(), network.TestNetworkPassphrase, "testwebauth.stellar.org", []string{"testanchor.stellar.org"}) assert.Equal(t, tx, readTx) assert.Equal(t, "", readClientAccountID) assert.EqualError(t, err, "transaction sequence number must be 0") @@ -2092,7 +2121,7 @@ func TestReadChallengeTx_invalidTimeboundsInfinite(t *testing.T) { assert.NoError(t, err) tx64, err := tx.Base64() require.NoError(t, err) - readTx, readClientAccountID, _, err := ReadChallengeTx(tx64, serverKP.Address(), network.TestNetworkPassphrase, "testwebauth.stellar.org", []string{"testanchor.stellar.org"}) + readTx, readClientAccountID, _, _, err := ReadChallengeTx(tx64, serverKP.Address(), network.TestNetworkPassphrase, "testwebauth.stellar.org", []string{"testanchor.stellar.org"}) assert.Equal(t, tx, readTx) assert.Equal(t, "", readClientAccountID) assert.EqualError(t, err, "transaction requires non-infinite timebounds") @@ -2127,7 +2156,7 @@ func TestReadChallengeTx_invalidTimeboundsOutsideRange(t *testing.T) { assert.NoError(t, err) tx64, err := tx.Base64() require.NoError(t, err) - readTx, readClientAccountID, _, err := ReadChallengeTx(tx64, serverKP.Address(), network.TestNetworkPassphrase, "testwebauth.stellar.org", []string{"testanchor.stellar.org"}) + readTx, readClientAccountID, _, _, err := ReadChallengeTx(tx64, serverKP.Address(), network.TestNetworkPassphrase, "testwebauth.stellar.org", []string{"testanchor.stellar.org"}) assert.Equal(t, tx, readTx) assert.Equal(t, "", readClientAccountID) assert.Error(t, err) @@ -2164,7 +2193,7 @@ func TestReadChallengeTx_validTimeboundsWithGracePeriod(t *testing.T) { assert.NoError(t, err) tx64, err := tx.Base64() require.NoError(t, err) - readTx, readClientAccountID, _, err := ReadChallengeTx(tx64, serverKP.Address(), network.TestNetworkPassphrase, "testwebauth.stellar.org", []string{"testanchor.stellar.org"}) + readTx, readClientAccountID, _, _, err := ReadChallengeTx(tx64, serverKP.Address(), network.TestNetworkPassphrase, "testwebauth.stellar.org", []string{"testanchor.stellar.org"}) assert.Equal(t, tx, readTx) assert.Equal(t, clientKP.Address(), readClientAccountID) assert.NoError(t, err) @@ -2200,7 +2229,7 @@ func TestReadChallengeTx_invalidTimeboundsWithGracePeriod(t *testing.T) { assert.NoError(t, err) tx64, err := tx.Base64() require.NoError(t, err) - readTx, readClientAccountID, _, err := ReadChallengeTx(tx64, serverKP.Address(), network.TestNetworkPassphrase, "testwebauth.stellar.org", []string{"testanchor.stellar.org"}) + readTx, readClientAccountID, _, _, err := ReadChallengeTx(tx64, serverKP.Address(), network.TestNetworkPassphrase, "testwebauth.stellar.org", []string{"testanchor.stellar.org"}) assert.Equal(t, tx, readTx) assert.Equal(t, "", readClientAccountID) assert.Error(t, err) @@ -2230,7 +2259,7 @@ func TestReadChallengeTx_invalidOperationWrongType(t *testing.T) { assert.NoError(t, err) tx64, err := tx.Base64() require.NoError(t, err) - readTx, readClientAccountID, _, err := ReadChallengeTx(tx64, serverKP.Address(), network.TestNetworkPassphrase, "testwebauth.stellar.org", []string{"testanchor.stellar.org"}) + readTx, readClientAccountID, _, _, err := ReadChallengeTx(tx64, serverKP.Address(), network.TestNetworkPassphrase, "testwebauth.stellar.org", []string{"testanchor.stellar.org"}) assert.Equal(t, tx, readTx) assert.Equal(t, "", readClientAccountID) assert.EqualError(t, err, "operation type should be manage_data") @@ -2258,7 +2287,7 @@ func TestReadChallengeTx_invalidOperationNoSourceAccount(t *testing.T) { assert.NoError(t, err) tx64, err := tx.Base64() require.NoError(t, err) - _, _, _, err = ReadChallengeTx(tx64, serverKP.Address(), network.TestNetworkPassphrase, "testwebauth.stellar.org", []string{"testanchor.stellar.org"}) + _, _, _, _, err = ReadChallengeTx(tx64, serverKP.Address(), network.TestNetworkPassphrase, "testwebauth.stellar.org", []string{"testanchor.stellar.org"}) assert.EqualError(t, err, "operation should have a source account") } @@ -2291,7 +2320,7 @@ func TestReadChallengeTx_invalidDataValueWrongEncodedLength(t *testing.T) { assert.NoError(t, err) tx64, err := tx.Base64() require.NoError(t, err) - readTx, readClientAccountID, _, err := ReadChallengeTx(tx64, serverKP.Address(), network.TestNetworkPassphrase, "testwebauth.stellar.org", []string{"testanchor.stellar.org"}) + readTx, readClientAccountID, _, _, err := ReadChallengeTx(tx64, serverKP.Address(), network.TestNetworkPassphrase, "testwebauth.stellar.org", []string{"testanchor.stellar.org"}) assert.Equal(t, tx, readTx) assert.Equal(t, clientKP.Address(), readClientAccountID) assert.EqualError(t, err, "random nonce encoded as base64 should be 64 bytes long") @@ -2326,7 +2355,7 @@ func TestReadChallengeTx_invalidDataValueCorruptBase64(t *testing.T) { assert.NoError(t, err) tx64, err := tx.Base64() require.NoError(t, err) - readTx, readClientAccountID, _, err := ReadChallengeTx(tx64, serverKP.Address(), network.TestNetworkPassphrase, "testwebauth.stellar.org", []string{"testanchor.stellar.org"}) + readTx, readClientAccountID, _, _, err := ReadChallengeTx(tx64, serverKP.Address(), network.TestNetworkPassphrase, "testwebauth.stellar.org", []string{"testanchor.stellar.org"}) assert.Equal(t, tx, readTx) assert.Equal(t, clientKP.Address(), readClientAccountID) assert.EqualError(t, err, "failed to decode random nonce provided in manage_data operation: illegal base64 data at input byte 37") @@ -2362,7 +2391,7 @@ func TestReadChallengeTx_invalidDataValueWrongByteLength(t *testing.T) { tx64, err := tx.Base64() assert.NoError(t, err) - readTx, readClientAccountID, _, err := ReadChallengeTx(tx64, serverKP.Address(), network.TestNetworkPassphrase, "testwebauth.stellar.org", []string{"testanchor.stellar.org"}) + readTx, readClientAccountID, _, _, err := ReadChallengeTx(tx64, serverKP.Address(), network.TestNetworkPassphrase, "testwebauth.stellar.org", []string{"testanchor.stellar.org"}) assert.Equal(t, tx, readTx) assert.Equal(t, clientKP.Address(), readClientAccountID) assert.EqualError(t, err, "random nonce before encoding as base64 should be 48 bytes long") @@ -2377,6 +2406,7 @@ func TestReadChallengeTx_acceptsV0AndV1Transactions(t *testing.T) { "testanchor.stellar.org", network.TestNetworkPassphrase, time.Hour, + nil, ) assert.NoError(t, err) @@ -2391,7 +2421,7 @@ func TestReadChallengeTx_acceptsV0AndV1Transactions(t *testing.T) { assert.NoError(t, err) for _, challenge := range []string{v1Challenge, v0Challenge} { - parsedTx, clientAccountID, _, err := ReadChallengeTx( + parsedTx, clientAccountID, _, _, err := ReadChallengeTx( challenge, kp0.Address(), network.TestNetworkPassphrase, @@ -2417,6 +2447,7 @@ func TestReadChallengeTx_forbidsFeeBumpTransactions(t *testing.T) { "testanchor.stellar.org", network.TestNetworkPassphrase, time.Hour, + nil, ) assert.NoError(t, err) @@ -2435,7 +2466,7 @@ func TestReadChallengeTx_forbidsFeeBumpTransactions(t *testing.T) { challenge, err := feeBumpTx.Base64() assert.NoError(t, err) - _, _, _, err = ReadChallengeTx( + _, _, _, _, err = ReadChallengeTx( challenge, kp0.Address(), network.TestNetworkPassphrase, @@ -2445,19 +2476,48 @@ func TestReadChallengeTx_forbidsFeeBumpTransactions(t *testing.T) { assert.EqualError(t, err, "challenge cannot be a fee bump transaction") } -func TestReadChallengeTx_forbidsMuxedAccounts(t *testing.T) { +func TestReadChallengeTx_allowsMuxedAccountsForClientAccountId(t *testing.T) { kp0 := newKeypair0() + kp1 := newKeypair1() + aid := xdr.MustAddress(kp1.Address()) + muxedAccount := xdr.MuxedAccount{ + Type: xdr.CryptoKeyTypeKeyTypeMuxedEd25519, + Med25519: &xdr.MuxedAccountMed25519{ + Id: 0xcafebabe, + Ed25519: *aid.Ed25519, + }, + } tx, err := BuildChallengeTx( kp0.Seed(), - kp0.Address(), + muxedAccount.Address(), "testwebauth.stellar.org", "testanchor.stellar.org", network.TestNetworkPassphrase, time.Hour, + nil, ) + assert.NoError(t, err) - env := tx.ToXDR() + challenge, err := marshallBase64(tx.ToXDR(), tx.Signatures()) assert.NoError(t, err) + + tx, _, _, _, err = ReadChallengeTx( + challenge, + kp0.Address(), + network.TestNetworkPassphrase, + "testwebauth.stellar.org", + []string{"testanchor.stellar.org"}, + ) + assert.NoError(t, err) + assert.Equal(t, tx.envelope.Operations()[0].SourceAccount, &muxedAccount) +} + +func TestReadChallengeTransaction_forbidsMuxedTxSourceAccount(t *testing.T) { + kp0 := newKeypair0() + kp1 := newKeypair1() + homeDomain := "testanchor.stellar.org" + webAuthDomain := "testwebauth.stellar.org" + aid := xdr.MustAddress(kp0.Address()) muxedAccount := xdr.MuxedAccount{ Type: xdr.CryptoKeyTypeKeyTypeMuxedEd25519, @@ -2466,20 +2526,174 @@ func TestReadChallengeTx_forbidsMuxedAccounts(t *testing.T) { Ed25519: *aid.Ed25519, }, } - *env.V1.Tx.Operations[0].SourceAccount = muxedAccount + serverAccount := SimpleAccount{ + AccountID: muxedAccount.Address(), + Sequence: 0, + } + randomNonce, _ := generateRandomNonce(48) + randomNonceToString := base64.StdEncoding.EncodeToString(randomNonce) + currentTime := time.Now().UTC() + maxTime := currentTime.Add(300) - challenge, err := marshallBase64(env, env.Signatures()) + tx, err := NewTransaction( + TransactionParams{ + SourceAccount: &serverAccount, + IncrementSequenceNum: false, + Operations: []Operation{ + &ManageData{ + SourceAccount: kp1.Address(), + Name: homeDomain + " auth", + Value: []byte(randomNonceToString), + }, + &ManageData{ + SourceAccount: serverAccount.GetAccountID(), + Name: "web_auth_domain", + Value: []byte(webAuthDomain), + }, + }, + BaseFee: MinBaseFee, + Memo: MemoID(1), + Preconditions: Preconditions{ + TimeBounds: NewTimebounds(currentTime.Unix(), maxTime.Unix()), + }, + }, + ) assert.NoError(t, err) - _, _, _, err = ReadChallengeTx( + tx, err = tx.Sign(network.TestNetworkPassphrase, kp0) + assert.NoError(t, err) + + challenge, err := marshallBase64(tx.ToXDR(), tx.Signatures()) + assert.NoError(t, err) + + _, _, _, _, err = ReadChallengeTx( challenge, kp0.Address(), network.TestNetworkPassphrase, - "testwebauth.stellar.org", - []string{"testanchor.stellar.org"}, + webAuthDomain, + []string{homeDomain}, + ) + assert.EqualError(t, err, "invalid source account: only valid Ed25519 accounts are allowed in challenge transactions") +} + +func TestReadChallengeTransaction_forbidsMemoWithMuxedClientAccount(t *testing.T) { + kp0 := newKeypair0() + kp1 := newKeypair1() + homeDomain := "testanchor.stellar.org" + webAuthDomain := "testwebauth.stellar.org" + + serverAccount := SimpleAccount{ + AccountID: kp0.Address(), + Sequence: 0, + } + aid := xdr.MustAddress(kp1.Address()) + muxedAccount := xdr.MuxedAccount{ + Type: xdr.CryptoKeyTypeKeyTypeMuxedEd25519, + Med25519: &xdr.MuxedAccountMed25519{ + Id: 0xcafebabe, + Ed25519: *aid.Ed25519, + }, + } + randomNonce, _ := generateRandomNonce(48) + randomNonceToString := base64.StdEncoding.EncodeToString(randomNonce) + currentTime := time.Now().UTC() + maxTime := currentTime.Add(300) + + tx, err := NewTransaction( + TransactionParams{ + SourceAccount: &serverAccount, + IncrementSequenceNum: false, + Operations: []Operation{ + &ManageData{ + SourceAccount: muxedAccount.Address(), + Name: homeDomain + " auth", + Value: []byte(randomNonceToString), + }, + &ManageData{ + SourceAccount: serverAccount.GetAccountID(), + Name: "web_auth_domain", + Value: []byte(webAuthDomain), + }, + }, + BaseFee: MinBaseFee, + Memo: MemoID(1), + Preconditions: Preconditions{ + TimeBounds: NewTimebounds(currentTime.Unix(), maxTime.Unix()), + }, + }, + ) + assert.NoError(t, err) + + tx, err = tx.Sign(network.TestNetworkPassphrase, kp0) + assert.NoError(t, err) + + challenge, err := marshallBase64(tx.ToXDR(), tx.Signatures()) + assert.NoError(t, err) + + _, _, _, _, err = ReadChallengeTx( + challenge, + kp0.Address(), + network.TestNetworkPassphrase, + webAuthDomain, + []string{homeDomain}, + ) + assert.EqualError(t, err, "memos are not valid for challenge transactions with a muxed client account") +} + +func TestReadChallengeTransaction_forbidsNonIdMemo(t *testing.T) { + kp0 := newKeypair0() + kp1 := newKeypair1() + homeDomain := "testanchor.stellar.org" + webAuthDomain := "testwebauth.stellar.org" + + serverAccount := SimpleAccount{ + AccountID: kp0.Address(), + Sequence: 0, + } + randomNonce, _ := generateRandomNonce(48) + randomNonceToString := base64.StdEncoding.EncodeToString(randomNonce) + currentTime := time.Now().UTC() + maxTime := currentTime.Add(300) + + tx, err := NewTransaction( + TransactionParams{ + SourceAccount: &serverAccount, + IncrementSequenceNum: false, + Operations: []Operation{ + &ManageData{ + SourceAccount: kp1.Address(), + Name: homeDomain + " auth", + Value: []byte(randomNonceToString), + }, + &ManageData{ + SourceAccount: serverAccount.GetAccountID(), + Name: "web_auth_domain", + Value: []byte(webAuthDomain), + }, + }, + BaseFee: MinBaseFee, + Memo: MemoText("test"), + Preconditions: Preconditions{ + TimeBounds: NewTimebounds(currentTime.Unix(), maxTime.Unix()), + }, + }, + ) + assert.NoError(t, err) + + tx, err = tx.Sign(network.TestNetworkPassphrase, kp0) + assert.NoError(t, err) + + challenge, err := marshallBase64(tx.ToXDR(), tx.Signatures()) + assert.NoError(t, err) + + _, _, _, _, err = ReadChallengeTx( + challenge, + kp0.Address(), + network.TestNetworkPassphrase, + webAuthDomain, + []string{homeDomain}, ) - errorMessage := "only valid Ed25519 accounts are allowed in challenge transactions" - assert.Contains(t, err.Error(), errorMessage) + assert.EqualError(t, err, "invalid memo, only ID memos are permitted") } func TestReadChallengeTx_doesVerifyHomeDomainFailure(t *testing.T) { @@ -2511,7 +2725,7 @@ func TestReadChallengeTx_doesVerifyHomeDomainFailure(t *testing.T) { assert.NoError(t, err) tx64, err := tx.Base64() require.NoError(t, err) - _, _, _, err = ReadChallengeTx(tx64, serverKP.Address(), network.TestNetworkPassphrase, "testwebauth.stellar.org", []string{"willfail"}) + _, _, _, _, err = ReadChallengeTx(tx64, serverKP.Address(), network.TestNetworkPassphrase, "testwebauth.stellar.org", []string{"willfail"}) assert.EqualError(t, err, "operation key does not match any homeDomains passed (key=\"testanchor.stellar.org auth\", homeDomains=[willfail])") } @@ -2544,7 +2758,7 @@ func TestReadChallengeTx_doesVerifyHomeDomainSuccess(t *testing.T) { assert.NoError(t, err) tx64, err := tx.Base64() require.NoError(t, err) - _, _, _, err = ReadChallengeTx(tx64, serverKP.Address(), network.TestNetworkPassphrase, "testwebauth.stellar.org", []string{"testanchor.stellar.org"}) + _, _, _, _, err = ReadChallengeTx(tx64, serverKP.Address(), network.TestNetworkPassphrase, "testwebauth.stellar.org", []string{"testanchor.stellar.org"}) assert.Equal(t, nil, err) } @@ -2582,7 +2796,7 @@ func TestReadChallengeTx_allowsAdditionalManageDataOpsWithSourceAccountSetToServ assert.NoError(t, err) tx64, err := tx.Base64() require.NoError(t, err) - readTx, readClientAccountID, _, err := ReadChallengeTx(tx64, serverKP.Address(), network.TestNetworkPassphrase, "testwebauth.stellar.org", []string{"testanchor.stellar.org"}) + readTx, readClientAccountID, _, _, err := ReadChallengeTx(tx64, serverKP.Address(), network.TestNetworkPassphrase, "testwebauth.stellar.org", []string{"testanchor.stellar.org"}) assert.Equal(t, tx, readTx) assert.Equal(t, clientKP.Address(), readClientAccountID) assert.NoError(t, err) @@ -2622,7 +2836,7 @@ func TestReadChallengeTx_disallowsAdditionalManageDataOpsWithoutSourceAccountSet assert.NoError(t, err) tx64, err := tx.Base64() require.NoError(t, err) - _, _, _, err = ReadChallengeTx(tx64, serverKP.Address(), network.TestNetworkPassphrase, "testwebauth.stellar.org", []string{"testanchor.stellar.org"}) + _, _, _, _, err = ReadChallengeTx(tx64, serverKP.Address(), network.TestNetworkPassphrase, "testwebauth.stellar.org", []string{"testanchor.stellar.org"}) assert.EqualError(t, err, "subsequent operations are unrecognized") } @@ -2659,7 +2873,7 @@ func TestReadChallengeTx_disallowsAdditionalOpsOfOtherTypes(t *testing.T) { assert.NoError(t, err) tx64, err := tx.Base64() require.NoError(t, err) - readTx, readClientAccountID, _, err := ReadChallengeTx(tx64, serverKP.Address(), network.TestNetworkPassphrase, "testwebauth.stellar.org", []string{"testanchor.stellar.org"}) + readTx, readClientAccountID, _, _, err := ReadChallengeTx(tx64, serverKP.Address(), network.TestNetworkPassphrase, "testwebauth.stellar.org", []string{"testanchor.stellar.org"}) assert.Equal(t, tx, readTx) assert.Equal(t, clientKP.Address(), readClientAccountID) assert.EqualError(t, err, "operation type should be manage_data") @@ -2693,7 +2907,7 @@ func TestReadChallengeTx_matchesHomeDomain(t *testing.T) { assert.NoError(t, err) tx64, err := tx.Base64() require.NoError(t, err) - _, _, matchedHomeDomain, err := ReadChallengeTx(tx64, serverKP.Address(), network.TestNetworkPassphrase, "testwebauth.stellar.org", []string{"testanchor.stellar.org"}) + _, _, matchedHomeDomain, _, err := ReadChallengeTx(tx64, serverKP.Address(), network.TestNetworkPassphrase, "testwebauth.stellar.org", []string{"testanchor.stellar.org"}) require.NoError(t, err) assert.Equal(t, matchedHomeDomain, "testanchor.stellar.org") } @@ -2726,7 +2940,7 @@ func TestReadChallengeTx_doesNotMatchHomeDomain(t *testing.T) { assert.NoError(t, err) tx64, err := tx.Base64() require.NoError(t, err) - _, _, matchedHomeDomain, err := ReadChallengeTx(tx64, serverKP.Address(), network.TestNetworkPassphrase, "testwebauth.stellar.org", []string{"not", "going", "to", "match"}) + _, _, matchedHomeDomain, _, err := ReadChallengeTx(tx64, serverKP.Address(), network.TestNetworkPassphrase, "testwebauth.stellar.org", []string{"not", "going", "to", "match"}) assert.Equal(t, matchedHomeDomain, "") assert.EqualError(t, err, "operation key does not match any homeDomains passed (key=\"testanchor.stellar.org auth\", homeDomains=[not going to match])") } @@ -2754,7 +2968,7 @@ func TestReadChallengeTx_validWhenWebAuthDomainMissing(t *testing.T) { assert.NoError(t, err) tx64, err := tx.Base64() require.NoError(t, err) - _, _, _, err = ReadChallengeTx(tx64, serverKP.Address(), network.TestNetworkPassphrase, "testwebauth.stellar.org", []string{"testanchor.stellar.org"}) + _, _, _, _, err = ReadChallengeTx(tx64, serverKP.Address(), network.TestNetworkPassphrase, "testwebauth.stellar.org", []string{"testanchor.stellar.org"}) assert.NoError(t, err) } @@ -2786,7 +3000,7 @@ func TestReadChallengeTx_invalidWebAuthDomainSourceAccount(t *testing.T) { assert.NoError(t, err) tx64, err := tx.Base64() require.NoError(t, err) - _, _, _, err = ReadChallengeTx(tx64, serverKP.Address(), network.TestNetworkPassphrase, "testwebauth.stellar.org", []string{"testanchor.stellar.org"}) + _, _, _, _, err = ReadChallengeTx(tx64, serverKP.Address(), network.TestNetworkPassphrase, "testwebauth.stellar.org", []string{"testanchor.stellar.org"}) assert.EqualError(t, err, `web auth domain operation must have server source account`) } @@ -2818,7 +3032,7 @@ func TestReadChallengeTx_invalidWebAuthDomain(t *testing.T) { assert.NoError(t, err) tx64, err := tx.Base64() require.NoError(t, err) - _, _, _, err = ReadChallengeTx(tx64, serverKP.Address(), network.TestNetworkPassphrase, "testwebauth.stellar.org", []string{"testanchor.stellar.org"}) + _, _, _, _, err = ReadChallengeTx(tx64, serverKP.Address(), network.TestNetworkPassphrase, "testwebauth.stellar.org", []string{"testanchor.stellar.org"}) assert.EqualError(t, err, `web auth domain operation value is "testwebauth.example.org" but expect "testwebauth.stellar.org"`) } diff --git a/xdr/Stellar-contract-config-setting.x b/xdr/Stellar-contract-config-setting.x new file mode 100644 index 0000000000..b187a18c5a --- /dev/null +++ b/xdr/Stellar-contract-config-setting.x @@ -0,0 +1,236 @@ +%#include "xdr/Stellar-types.h" + +namespace stellar { +// General “Soroban execution lane” settings +struct ConfigSettingContractExecutionLanesV0 +{ + // maximum number of Soroban transactions per ledger + uint32 ledgerMaxTxCount; +}; + +// "Compute" settings for contracts (instructions and memory). +struct ConfigSettingContractComputeV0 +{ + // Maximum instructions per ledger + int64 ledgerMaxInstructions; + // Maximum instructions per transaction + int64 txMaxInstructions; + // Cost of 10000 instructions + int64 feeRatePerInstructionsIncrement; + + // Memory limit per transaction. Unlike instructions, there is no fee + // for memory, just the limit. + uint32 txMemoryLimit; +}; + +// Ledger access settings for contracts. +struct ConfigSettingContractLedgerCostV0 +{ + // Maximum number of ledger entry read operations per ledger + uint32 ledgerMaxReadLedgerEntries; + // Maximum number of bytes that can be read per ledger + uint32 ledgerMaxReadBytes; + // Maximum number of ledger entry write operations per ledger + uint32 ledgerMaxWriteLedgerEntries; + // Maximum number of bytes that can be written per ledger + uint32 ledgerMaxWriteBytes; + + // Maximum number of ledger entry read operations per transaction + uint32 txMaxReadLedgerEntries; + // Maximum number of bytes that can be read per transaction + uint32 txMaxReadBytes; + // Maximum number of ledger entry write operations per transaction + uint32 txMaxWriteLedgerEntries; + // Maximum number of bytes that can be written per transaction + uint32 txMaxWriteBytes; + + int64 feeReadLedgerEntry; // Fee per ledger entry read + int64 feeWriteLedgerEntry; // Fee per ledger entry write + + int64 feeRead1KB; // Fee for reading 1KB + + // The following parameters determine the write fee per 1KB. + // Write fee grows linearly until bucket list reaches this size + int64 bucketListTargetSizeBytes; + // Fee per 1KB write when the bucket list is empty + int64 writeFee1KBBucketListLow; + // Fee per 1KB write when the bucket list has reached `bucketListTargetSizeBytes` + int64 writeFee1KBBucketListHigh; + // Write fee multiplier for any additional data past the first `bucketListTargetSizeBytes` + uint32 bucketListWriteFeeGrowthFactor; +}; + +// Historical data (pushed to core archives) settings for contracts. +struct ConfigSettingContractHistoricalDataV0 +{ + int64 feeHistorical1KB; // Fee for storing 1KB in archives +}; + +// Contract event-related settings. +struct ConfigSettingContractEventsV0 +{ + // Maximum size of events that a contract call can emit. + uint32 txMaxContractEventsSizeBytes; + // Fee for generating 1KB of contract events. + int64 feeContractEvents1KB; +}; + +// Bandwidth related data settings for contracts. +// We consider bandwidth to only be consumed by the transaction envelopes, hence +// this concerns only transaction sizes. +struct ConfigSettingContractBandwidthV0 +{ + // Maximum sum of all transaction sizes in the ledger in bytes + uint32 ledgerMaxTxsSizeBytes; + // Maximum size in bytes for a transaction + uint32 txMaxSizeBytes; + + // Fee for 1 KB of transaction size + int64 feeTxSize1KB; +}; + +enum ContractCostType { + // Cost of running 1 wasm instruction + WasmInsnExec = 0, + // Cost of allocating a slice of memory (in bytes) + MemAlloc = 1, + // Cost of copying a slice of bytes into a pre-allocated memory + MemCpy = 2, + // Cost of comparing two slices of memory + MemCmp = 3, + // Cost of a host function dispatch, not including the actual work done by + // the function nor the cost of VM invocation machinary + DispatchHostFunction = 4, + // Cost of visiting a host object from the host object storage. Exists to + // make sure some baseline cost coverage, i.e. repeatly visiting objects + // by the guest will always incur some charges. + VisitObject = 5, + // Cost of serializing an xdr object to bytes + ValSer = 6, + // Cost of deserializing an xdr object from bytes + ValDeser = 7, + // Cost of computing the sha256 hash from bytes + ComputeSha256Hash = 8, + // Cost of computing the ed25519 pubkey from bytes + ComputeEd25519PubKey = 9, + // Cost of verifying ed25519 signature of a payload. + VerifyEd25519Sig = 10, + // Cost of instantiation a VM from wasm bytes code. + VmInstantiation = 11, + // Cost of instantiation a VM from a cached state. + VmCachedInstantiation = 12, + // Cost of invoking a function on the VM. If the function is a host function, + // additional cost will be covered by `DispatchHostFunction`. + InvokeVmFunction = 13, + // Cost of computing a keccak256 hash from bytes. + ComputeKeccak256Hash = 14, + // Cost of computing an ECDSA secp256k1 signature from bytes. + ComputeEcdsaSecp256k1Sig = 15, + // Cost of recovering an ECDSA secp256k1 key from a signature. + RecoverEcdsaSecp256k1Key = 16, + // Cost of int256 addition (`+`) and subtraction (`-`) operations + Int256AddSub = 17, + // Cost of int256 multiplication (`*`) operation + Int256Mul = 18, + // Cost of int256 division (`/`) operation + Int256Div = 19, + // Cost of int256 power (`exp`) operation + Int256Pow = 20, + // Cost of int256 shift (`shl`, `shr`) operation + Int256Shift = 21, + // Cost of drawing random bytes using a ChaCha20 PRNG + ChaCha20DrawBytes = 22 +}; + +struct ContractCostParamEntry { + // use `ext` to add more terms (e.g. higher order polynomials) in the future + ExtensionPoint ext; + + int64 constTerm; + int64 linearTerm; +}; + +struct StateArchivalSettings { + uint32 maxEntryTTL; + uint32 minTemporaryTTL; + uint32 minPersistentTTL; + + // rent_fee = wfee_rate_average / rent_rate_denominator_for_type + int64 persistentRentRateDenominator; + int64 tempRentRateDenominator; + + // max number of entries that emit archival meta in a single ledger + uint32 maxEntriesToArchive; + + // Number of snapshots to use when calculating average BucketList size + uint32 bucketListSizeWindowSampleSize; + + // Maximum number of bytes that we scan for eviction per ledger + uint64 evictionScanSize; + + // Lowest BucketList level to be scanned to evict entries + uint32 startingEvictionScanLevel; +}; + +struct EvictionIterator { + uint32 bucketListLevel; + bool isCurrBucket; + uint64 bucketFileOffset; +}; + +// limits the ContractCostParams size to 20kB +const CONTRACT_COST_COUNT_LIMIT = 1024; + +typedef ContractCostParamEntry ContractCostParams; + +// Identifiers of all the network settings. +enum ConfigSettingID +{ + CONFIG_SETTING_CONTRACT_MAX_SIZE_BYTES = 0, + CONFIG_SETTING_CONTRACT_COMPUTE_V0 = 1, + CONFIG_SETTING_CONTRACT_LEDGER_COST_V0 = 2, + CONFIG_SETTING_CONTRACT_HISTORICAL_DATA_V0 = 3, + CONFIG_SETTING_CONTRACT_EVENTS_V0 = 4, + CONFIG_SETTING_CONTRACT_BANDWIDTH_V0 = 5, + CONFIG_SETTING_CONTRACT_COST_PARAMS_CPU_INSTRUCTIONS = 6, + CONFIG_SETTING_CONTRACT_COST_PARAMS_MEMORY_BYTES = 7, + CONFIG_SETTING_CONTRACT_DATA_KEY_SIZE_BYTES = 8, + CONFIG_SETTING_CONTRACT_DATA_ENTRY_SIZE_BYTES = 9, + CONFIG_SETTING_STATE_ARCHIVAL = 10, + CONFIG_SETTING_CONTRACT_EXECUTION_LANES = 11, + CONFIG_SETTING_BUCKETLIST_SIZE_WINDOW = 12, + CONFIG_SETTING_EVICTION_ITERATOR = 13 +}; + +union ConfigSettingEntry switch (ConfigSettingID configSettingID) +{ +case CONFIG_SETTING_CONTRACT_MAX_SIZE_BYTES: + uint32 contractMaxSizeBytes; +case CONFIG_SETTING_CONTRACT_COMPUTE_V0: + ConfigSettingContractComputeV0 contractCompute; +case CONFIG_SETTING_CONTRACT_LEDGER_COST_V0: + ConfigSettingContractLedgerCostV0 contractLedgerCost; +case CONFIG_SETTING_CONTRACT_HISTORICAL_DATA_V0: + ConfigSettingContractHistoricalDataV0 contractHistoricalData; +case CONFIG_SETTING_CONTRACT_EVENTS_V0: + ConfigSettingContractEventsV0 contractEvents; +case CONFIG_SETTING_CONTRACT_BANDWIDTH_V0: + ConfigSettingContractBandwidthV0 contractBandwidth; +case CONFIG_SETTING_CONTRACT_COST_PARAMS_CPU_INSTRUCTIONS: + ContractCostParams contractCostParamsCpuInsns; +case CONFIG_SETTING_CONTRACT_COST_PARAMS_MEMORY_BYTES: + ContractCostParams contractCostParamsMemBytes; +case CONFIG_SETTING_CONTRACT_DATA_KEY_SIZE_BYTES: + uint32 contractDataKeySizeBytes; +case CONFIG_SETTING_CONTRACT_DATA_ENTRY_SIZE_BYTES: + uint32 contractDataEntrySizeBytes; +case CONFIG_SETTING_STATE_ARCHIVAL: + StateArchivalSettings stateArchivalSettings; +case CONFIG_SETTING_CONTRACT_EXECUTION_LANES: + ConfigSettingContractExecutionLanesV0 contractExecutionLanes; +case CONFIG_SETTING_BUCKETLIST_SIZE_WINDOW: + uint64 bucketListSizeWindow<>; +case CONFIG_SETTING_EVICTION_ITERATOR: + EvictionIterator evictionIterator; +}; +} diff --git a/xdr/Stellar-contract-env-meta.x b/xdr/Stellar-contract-env-meta.x new file mode 100644 index 0000000000..330726de41 --- /dev/null +++ b/xdr/Stellar-contract-env-meta.x @@ -0,0 +1,23 @@ +// Copyright 2022 Stellar Development Foundation and contributors. Licensed +// under the Apache License, Version 2.0. See the COPYING file at the root +// of this distribution or at http://www.apache.org/licenses/LICENSE-2.0 + +// The contract spec XDR is highly experimental, incomplete, and still being +// iterated on. Breaking changes expected. + +% #include "xdr/Stellar-types.h" +namespace stellar +{ + +enum SCEnvMetaKind +{ + SC_ENV_META_KIND_INTERFACE_VERSION = 0 +}; + +union SCEnvMetaEntry switch (SCEnvMetaKind kind) +{ +case SC_ENV_META_KIND_INTERFACE_VERSION: + uint64 interfaceVersion; +}; + +} diff --git a/xdr/Stellar-contract-meta.x b/xdr/Stellar-contract-meta.x new file mode 100644 index 0000000000..16eb5f9e20 --- /dev/null +++ b/xdr/Stellar-contract-meta.x @@ -0,0 +1,29 @@ +// Copyright 2022 Stellar Development Foundation and contributors. Licensed +// under the Apache License, Version 2.0. See the COPYING file at the root +// of this distribution or at http://www.apache.org/licenses/LICENSE-2.0 + +// The contract meta XDR is highly experimental, incomplete, and still being +// iterated on. Breaking changes expected. + +% #include "xdr/Stellar-types.h" +namespace stellar +{ + +struct SCMetaV0 +{ + string key<>; + string val<>; +}; + +enum SCMetaKind +{ + SC_META_V0 = 0 +}; + +union SCMetaEntry switch (SCMetaKind kind) +{ +case SC_META_V0: + SCMetaV0 v0; +}; + +} diff --git a/xdr/Stellar-contract-spec.x b/xdr/Stellar-contract-spec.x new file mode 100644 index 0000000000..6988a63385 --- /dev/null +++ b/xdr/Stellar-contract-spec.x @@ -0,0 +1,242 @@ +// Copyright 2022 Stellar Development Foundation and contributors. Licensed +// under the Apache License, Version 2.0. See the COPYING file at the root +// of this distribution or at http://www.apache.org/licenses/LICENSE-2.0 + +// The contract Contractspec XDR is highly experimental, incomplete, and still being +// iterated on. Breaking changes expected. + +% #include "xdr/Stellar-types.h" +% #include "xdr/Stellar-contract.h" +namespace stellar +{ + +const SC_SPEC_DOC_LIMIT = 1024; + +enum SCSpecType +{ + SC_SPEC_TYPE_VAL = 0, + + // Types with no parameters. + SC_SPEC_TYPE_BOOL = 1, + SC_SPEC_TYPE_VOID = 2, + SC_SPEC_TYPE_ERROR = 3, + SC_SPEC_TYPE_U32 = 4, + SC_SPEC_TYPE_I32 = 5, + SC_SPEC_TYPE_U64 = 6, + SC_SPEC_TYPE_I64 = 7, + SC_SPEC_TYPE_TIMEPOINT = 8, + SC_SPEC_TYPE_DURATION = 9, + SC_SPEC_TYPE_U128 = 10, + SC_SPEC_TYPE_I128 = 11, + SC_SPEC_TYPE_U256 = 12, + SC_SPEC_TYPE_I256 = 13, + SC_SPEC_TYPE_BYTES = 14, + SC_SPEC_TYPE_STRING = 16, + SC_SPEC_TYPE_SYMBOL = 17, + SC_SPEC_TYPE_ADDRESS = 19, + + // Types with parameters. + SC_SPEC_TYPE_OPTION = 1000, + SC_SPEC_TYPE_RESULT = 1001, + SC_SPEC_TYPE_VEC = 1002, + SC_SPEC_TYPE_MAP = 1004, + SC_SPEC_TYPE_TUPLE = 1005, + SC_SPEC_TYPE_BYTES_N = 1006, + + // User defined types. + SC_SPEC_TYPE_UDT = 2000 +}; + +struct SCSpecTypeOption +{ + SCSpecTypeDef valueType; +}; + +struct SCSpecTypeResult +{ + SCSpecTypeDef okType; + SCSpecTypeDef errorType; +}; + +struct SCSpecTypeVec +{ + SCSpecTypeDef elementType; +}; + +struct SCSpecTypeMap +{ + SCSpecTypeDef keyType; + SCSpecTypeDef valueType; +}; + +struct SCSpecTypeTuple +{ + SCSpecTypeDef valueTypes<12>; +}; + +struct SCSpecTypeBytesN +{ + uint32 n; +}; + +struct SCSpecTypeUDT +{ + string name<60>; +}; + +union SCSpecTypeDef switch (SCSpecType type) +{ +case SC_SPEC_TYPE_VAL: +case SC_SPEC_TYPE_BOOL: +case SC_SPEC_TYPE_VOID: +case SC_SPEC_TYPE_ERROR: +case SC_SPEC_TYPE_U32: +case SC_SPEC_TYPE_I32: +case SC_SPEC_TYPE_U64: +case SC_SPEC_TYPE_I64: +case SC_SPEC_TYPE_TIMEPOINT: +case SC_SPEC_TYPE_DURATION: +case SC_SPEC_TYPE_U128: +case SC_SPEC_TYPE_I128: +case SC_SPEC_TYPE_U256: +case SC_SPEC_TYPE_I256: +case SC_SPEC_TYPE_BYTES: +case SC_SPEC_TYPE_STRING: +case SC_SPEC_TYPE_SYMBOL: +case SC_SPEC_TYPE_ADDRESS: + void; +case SC_SPEC_TYPE_OPTION: + SCSpecTypeOption option; +case SC_SPEC_TYPE_RESULT: + SCSpecTypeResult result; +case SC_SPEC_TYPE_VEC: + SCSpecTypeVec vec; +case SC_SPEC_TYPE_MAP: + SCSpecTypeMap map; +case SC_SPEC_TYPE_TUPLE: + SCSpecTypeTuple tuple; +case SC_SPEC_TYPE_BYTES_N: + SCSpecTypeBytesN bytesN; +case SC_SPEC_TYPE_UDT: + SCSpecTypeUDT udt; +}; + +struct SCSpecUDTStructFieldV0 +{ + string doc; + string name<30>; + SCSpecTypeDef type; +}; + +struct SCSpecUDTStructV0 +{ + string doc; + string lib<80>; + string name<60>; + SCSpecUDTStructFieldV0 fields<40>; +}; + +struct SCSpecUDTUnionCaseVoidV0 +{ + string doc; + string name<60>; +}; + +struct SCSpecUDTUnionCaseTupleV0 +{ + string doc; + string name<60>; + SCSpecTypeDef type<12>; +}; + +enum SCSpecUDTUnionCaseV0Kind +{ + SC_SPEC_UDT_UNION_CASE_VOID_V0 = 0, + SC_SPEC_UDT_UNION_CASE_TUPLE_V0 = 1 +}; + +union SCSpecUDTUnionCaseV0 switch (SCSpecUDTUnionCaseV0Kind kind) +{ +case SC_SPEC_UDT_UNION_CASE_VOID_V0: + SCSpecUDTUnionCaseVoidV0 voidCase; +case SC_SPEC_UDT_UNION_CASE_TUPLE_V0: + SCSpecUDTUnionCaseTupleV0 tupleCase; +}; + +struct SCSpecUDTUnionV0 +{ + string doc; + string lib<80>; + string name<60>; + SCSpecUDTUnionCaseV0 cases<50>; +}; + +struct SCSpecUDTEnumCaseV0 +{ + string doc; + string name<60>; + uint32 value; +}; + +struct SCSpecUDTEnumV0 +{ + string doc; + string lib<80>; + string name<60>; + SCSpecUDTEnumCaseV0 cases<50>; +}; + +struct SCSpecUDTErrorEnumCaseV0 +{ + string doc; + string name<60>; + uint32 value; +}; + +struct SCSpecUDTErrorEnumV0 +{ + string doc; + string lib<80>; + string name<60>; + SCSpecUDTErrorEnumCaseV0 cases<50>; +}; + +struct SCSpecFunctionInputV0 +{ + string doc; + string name<30>; + SCSpecTypeDef type; +}; + +struct SCSpecFunctionV0 +{ + string doc; + SCSymbol name; + SCSpecFunctionInputV0 inputs<10>; + SCSpecTypeDef outputs<1>; +}; + +enum SCSpecEntryKind +{ + SC_SPEC_ENTRY_FUNCTION_V0 = 0, + SC_SPEC_ENTRY_UDT_STRUCT_V0 = 1, + SC_SPEC_ENTRY_UDT_UNION_V0 = 2, + SC_SPEC_ENTRY_UDT_ENUM_V0 = 3, + SC_SPEC_ENTRY_UDT_ERROR_ENUM_V0 = 4 +}; + +union SCSpecEntry switch (SCSpecEntryKind kind) +{ +case SC_SPEC_ENTRY_FUNCTION_V0: + SCSpecFunctionV0 functionV0; +case SC_SPEC_ENTRY_UDT_STRUCT_V0: + SCSpecUDTStructV0 udtStructV0; +case SC_SPEC_ENTRY_UDT_UNION_V0: + SCSpecUDTUnionV0 udtUnionV0; +case SC_SPEC_ENTRY_UDT_ENUM_V0: + SCSpecUDTEnumV0 udtEnumV0; +case SC_SPEC_ENTRY_UDT_ERROR_ENUM_V0: + SCSpecUDTErrorEnumV0 udtErrorEnumV0; +}; + +} diff --git a/xdr/Stellar-contract.x b/xdr/Stellar-contract.x new file mode 100644 index 0000000000..511300562e --- /dev/null +++ b/xdr/Stellar-contract.x @@ -0,0 +1,282 @@ +// Copyright 2022 Stellar Development Foundation and contributors. Licensed +// under the Apache License, Version 2.0. See the COPYING file at the root +// of this distribution or at http://www.apache.org/licenses/LICENSE-2.0 + +% #include "xdr/Stellar-types.h" +namespace stellar +{ + +// We fix a maximum of 128 value types in the system for two reasons: we want to +// keep the codes relatively small (<= 8 bits) when bit-packing values into a +// u64 at the environment interface level, so that we keep many bits for +// payloads (small strings, small numeric values, object handles); and then we +// actually want to go one step further and ensure (for code-size) that our +// codes fit in a single ULEB128-code byte, which means we can only use 7 bits. +// +// We also reserve several type codes from this space because we want to _reuse_ +// the SCValType codes at the environment interface level (or at least not +// exceed its number-space) but there are more types at that level, assigned to +// optimizations/special case representations of values abstract at this level. + +enum SCValType +{ + SCV_BOOL = 0, + SCV_VOID = 1, + SCV_ERROR = 2, + + // 32 bits is the smallest type in WASM or XDR; no need for u8/u16. + SCV_U32 = 3, + SCV_I32 = 4, + + // 64 bits is naturally supported by both WASM and XDR also. + SCV_U64 = 5, + SCV_I64 = 6, + + // Time-related u64 subtypes with their own functions and formatting. + SCV_TIMEPOINT = 7, + SCV_DURATION = 8, + + // 128 bits is naturally supported by Rust and we use it for Soroban + // fixed-point arithmetic prices / balances / similar "quantities". These + // are represented in XDR as a pair of 2 u64s. + SCV_U128 = 9, + SCV_I128 = 10, + + // 256 bits is the size of sha256 output, ed25519 keys, and the EVM machine + // word, so for interop use we include this even though it requires a small + // amount of Rust guest and/or host library code. + SCV_U256 = 11, + SCV_I256 = 12, + + // Bytes come in 3 flavors, 2 of which have meaningfully different + // formatting and validity-checking / domain-restriction. + SCV_BYTES = 13, + SCV_STRING = 14, + SCV_SYMBOL = 15, + + // Vecs and maps are just polymorphic containers of other ScVals. + SCV_VEC = 16, + SCV_MAP = 17, + + // Address is the universal identifier for contracts and classic + // accounts. + SCV_ADDRESS = 18, + + // The following are the internal SCVal variants that are not + // exposed to the contracts. + SCV_CONTRACT_INSTANCE = 19, + + // SCV_LEDGER_KEY_CONTRACT_INSTANCE and SCV_LEDGER_KEY_NONCE are unique + // symbolic SCVals used as the key for ledger entries for a contract's + // instance and an address' nonce, respectively. + SCV_LEDGER_KEY_CONTRACT_INSTANCE = 20, + SCV_LEDGER_KEY_NONCE = 21 +}; + +enum SCErrorType +{ + SCE_CONTRACT = 0, // Contract-specific, user-defined codes. + SCE_WASM_VM = 1, // Errors while interpreting WASM bytecode. + SCE_CONTEXT = 2, // Errors in the contract's host context. + SCE_STORAGE = 3, // Errors accessing host storage. + SCE_OBJECT = 4, // Errors working with host objects. + SCE_CRYPTO = 5, // Errors in cryptographic operations. + SCE_EVENTS = 6, // Errors while emitting events. + SCE_BUDGET = 7, // Errors relating to budget limits. + SCE_VALUE = 8, // Errors working with host values or SCVals. + SCE_AUTH = 9 // Errors from the authentication subsystem. +}; + +enum SCErrorCode +{ + SCEC_ARITH_DOMAIN = 0, // Some arithmetic was undefined (overflow, divide-by-zero). + SCEC_INDEX_BOUNDS = 1, // Something was indexed beyond its bounds. + SCEC_INVALID_INPUT = 2, // User provided some otherwise-bad data. + SCEC_MISSING_VALUE = 3, // Some value was required but not provided. + SCEC_EXISTING_VALUE = 4, // Some value was provided where not allowed. + SCEC_EXCEEDED_LIMIT = 5, // Some arbitrary limit -- gas or otherwise -- was hit. + SCEC_INVALID_ACTION = 6, // Data was valid but action requested was not. + SCEC_INTERNAL_ERROR = 7, // The host detected an error in its own logic. + SCEC_UNEXPECTED_TYPE = 8, // Some type wasn't as expected. + SCEC_UNEXPECTED_SIZE = 9 // Something's size wasn't as expected. +}; + +// Smart contract errors are split into a type (SCErrorType) and a code. When an +// error is of type SCE_CONTRACT it carries a user-defined uint32 code that +// Soroban assigns no specific meaning to. In all other cases, the type +// specifies a subsystem of the Soroban host where the error originated, and the +// accompanying code is an SCErrorCode, each of which specifies a slightly more +// precise class of errors within that subsystem. +// +// Error types and codes are not maximally precise; there is a tradeoff between +// precision and flexibility in the implementation, and the granularity here is +// chosen to be adequate for most purposes while not placing a burden on future +// system evolution and maintenance. When additional precision is needed for +// debugging, Soroban can be run with diagnostic events enabled. + +union SCError switch (SCErrorType type) +{ +case SCE_CONTRACT: + uint32 contractCode; +case SCE_WASM_VM: +case SCE_CONTEXT: +case SCE_STORAGE: +case SCE_OBJECT: +case SCE_CRYPTO: +case SCE_EVENTS: +case SCE_BUDGET: +case SCE_VALUE: +case SCE_AUTH: + SCErrorCode code; +}; + +struct UInt128Parts { + uint64 hi; + uint64 lo; +}; + +// A signed int128 has a high sign bit and 127 value bits. We break it into a +// signed high int64 (that carries the sign bit and the high 63 value bits) and +// a low unsigned uint64 that carries the low 64 bits. This will sort in +// generated code in the same order the underlying int128 sorts. +struct Int128Parts { + int64 hi; + uint64 lo; +}; + +struct UInt256Parts { + uint64 hi_hi; + uint64 hi_lo; + uint64 lo_hi; + uint64 lo_lo; +}; + +// A signed int256 has a high sign bit and 255 value bits. We break it into a +// signed high int64 (that carries the sign bit and the high 63 value bits) and +// three low unsigned `uint64`s that carry the lower bits. This will sort in +// generated code in the same order the underlying int256 sorts. +struct Int256Parts { + int64 hi_hi; + uint64 hi_lo; + uint64 lo_hi; + uint64 lo_lo; +}; + +enum ContractExecutableType +{ + CONTRACT_EXECUTABLE_WASM = 0, + CONTRACT_EXECUTABLE_STELLAR_ASSET = 1 +}; + +union ContractExecutable switch (ContractExecutableType type) +{ +case CONTRACT_EXECUTABLE_WASM: + Hash wasm_hash; +case CONTRACT_EXECUTABLE_STELLAR_ASSET: + void; +}; + +enum SCAddressType +{ + SC_ADDRESS_TYPE_ACCOUNT = 0, + SC_ADDRESS_TYPE_CONTRACT = 1 +}; + +union SCAddress switch (SCAddressType type) +{ +case SC_ADDRESS_TYPE_ACCOUNT: + AccountID accountId; +case SC_ADDRESS_TYPE_CONTRACT: + Hash contractId; +}; + +%struct SCVal; +%struct SCMapEntry; + +const SCSYMBOL_LIMIT = 32; + +typedef SCVal SCVec<>; +typedef SCMapEntry SCMap<>; + +typedef opaque SCBytes<>; +typedef string SCString<>; +typedef string SCSymbol; + +struct SCNonceKey { + int64 nonce; +}; + +struct SCContractInstance { + ContractExecutable executable; + SCMap* storage; +}; + +union SCVal switch (SCValType type) +{ + +case SCV_BOOL: + bool b; +case SCV_VOID: + void; +case SCV_ERROR: + SCError error; + +case SCV_U32: + uint32 u32; +case SCV_I32: + int32 i32; + +case SCV_U64: + uint64 u64; +case SCV_I64: + int64 i64; +case SCV_TIMEPOINT: + TimePoint timepoint; +case SCV_DURATION: + Duration duration; + +case SCV_U128: + UInt128Parts u128; +case SCV_I128: + Int128Parts i128; + +case SCV_U256: + UInt256Parts u256; +case SCV_I256: + Int256Parts i256; + +case SCV_BYTES: + SCBytes bytes; +case SCV_STRING: + SCString str; +case SCV_SYMBOL: + SCSymbol sym; + +// Vec and Map are recursive so need to live +// behind an option, due to xdrpp limitations. +case SCV_VEC: + SCVec *vec; +case SCV_MAP: + SCMap *map; + +case SCV_ADDRESS: + SCAddress address; + +// Special SCVals reserved for system-constructed contract-data +// ledger keys, not generally usable elsewhere. +case SCV_LEDGER_KEY_CONTRACT_INSTANCE: + void; +case SCV_LEDGER_KEY_NONCE: + SCNonceKey nonce_key; + +case SCV_CONTRACT_INSTANCE: + SCContractInstance instance; +}; + +struct SCMapEntry +{ + SCVal key; + SCVal val; +}; + +} diff --git a/xdr/Stellar-internal.x b/xdr/Stellar-internal.x new file mode 100644 index 0000000000..02f1b81e8e --- /dev/null +++ b/xdr/Stellar-internal.x @@ -0,0 +1,48 @@ +// Copyright 2022 Stellar Development Foundation and contributors. Licensed +// under the Apache License, Version 2.0. See the COPYING file at the root +// of this distribution or at http://www.apache.org/licenses/LICENSE-2.0 + +// This is for 'internal'-only messages that are not meant to be read/written +// by any other binaries besides a single Core instance. +%#include "xdr/Stellar-ledger.h" +%#include "xdr/Stellar-SCP.h" + +namespace stellar +{ +union StoredTransactionSet switch (int v) +{ +case 0: + TransactionSet txSet; +case 1: + GeneralizedTransactionSet generalizedTxSet; +}; + +struct StoredDebugTransactionSet +{ + StoredTransactionSet txSet; + uint32 ledgerSeq; + StellarValue scpValue; +}; + +struct PersistedSCPStateV0 +{ + SCPEnvelope scpEnvelopes<>; + SCPQuorumSet quorumSets<>; + StoredTransactionSet txSets<>; +}; + +struct PersistedSCPStateV1 +{ + // Tx sets are saved separately + SCPEnvelope scpEnvelopes<>; + SCPQuorumSet quorumSets<>; +}; + +union PersistedSCPState switch (int v) +{ +case 0: + PersistedSCPStateV0 v0; +case 1: + PersistedSCPStateV1 v1; +}; +} \ No newline at end of file diff --git a/xdr/Stellar-ledger-entries.x b/xdr/Stellar-ledger-entries.x index 3eb578f16b..8a8784e2bb 100644 --- a/xdr/Stellar-ledger-entries.x +++ b/xdr/Stellar-ledger-entries.x @@ -3,17 +3,16 @@ // of this distribution or at http://www.apache.org/licenses/LICENSE-2.0 %#include "xdr/Stellar-types.h" +%#include "xdr/Stellar-contract.h" +%#include "xdr/Stellar-contract-config-setting.h" namespace stellar { -typedef PublicKey AccountID; typedef opaque Thresholds[4]; typedef string string32<32>; typedef string string64<64>; typedef int64 SequenceNumber; -typedef uint64 TimePoint; -typedef uint64 Duration; typedef opaque DataValue<64>; typedef Hash PoolID; // SHA256(LiquidityPoolParameters) @@ -98,7 +97,11 @@ enum LedgerEntryType OFFER = 2, DATA = 3, CLAIMABLE_BALANCE = 4, - LIQUIDITY_POOL = 5 + LIQUIDITY_POOL = 5, + CONTRACT_DATA = 6, + CONTRACT_CODE = 7, + CONFIG_SETTING = 8, + TTL = 9 }; struct Signer @@ -491,6 +494,33 @@ struct LiquidityPoolEntry body; }; +enum ContractDataDurability { + TEMPORARY = 0, + PERSISTENT = 1 +}; + +struct ContractDataEntry { + ExtensionPoint ext; + + SCAddress contract; + SCVal key; + ContractDataDurability durability; + SCVal val; +}; + +struct ContractCodeEntry { + ExtensionPoint ext; + + Hash hash; + opaque code<>; +}; + +struct TTLEntry { + // Hash of the LedgerKey that is associated with this TTLEntry + Hash keyHash; + uint32 liveUntilLedgerSeq; +}; + struct LedgerEntryExtensionV1 { SponsorshipDescriptor sponsoringID; @@ -521,6 +551,14 @@ struct LedgerEntry ClaimableBalanceEntry claimableBalance; case LIQUIDITY_POOL: LiquidityPoolEntry liquidityPool; + case CONTRACT_DATA: + ContractDataEntry contractData; + case CONTRACT_CODE: + ContractCodeEntry contractCode; + case CONFIG_SETTING: + ConfigSettingEntry configSetting; + case TTL: + TTLEntry ttl; } data; @@ -575,6 +613,29 @@ case LIQUIDITY_POOL: { PoolID liquidityPoolID; } liquidityPool; +case CONTRACT_DATA: + struct + { + SCAddress contract; + SCVal key; + ContractDataDurability durability; + } contractData; +case CONTRACT_CODE: + struct + { + Hash hash; + } contractCode; +case CONFIG_SETTING: + struct + { + ConfigSettingID configSettingID; + } configSetting; +case TTL: + struct + { + // Hash of the LedgerKey that is associated with this TTLEntry + Hash keyHash; + } ttl; }; // list of all envelope types used in the application @@ -589,6 +650,8 @@ enum EnvelopeType ENVELOPE_TYPE_SCPVALUE = 4, ENVELOPE_TYPE_TX_FEE_BUMP = 5, ENVELOPE_TYPE_OP_ID = 6, - ENVELOPE_TYPE_POOL_REVOKE_OP_ID = 7 + ENVELOPE_TYPE_POOL_REVOKE_OP_ID = 7, + ENVELOPE_TYPE_CONTRACT_ID = 8, + ENVELOPE_TYPE_SOROBAN_AUTHORIZATION = 9 }; } diff --git a/xdr/Stellar-ledger.x b/xdr/Stellar-ledger.x index 9c2cbcee56..b18a3a0d57 100644 --- a/xdr/Stellar-ledger.x +++ b/xdr/Stellar-ledger.x @@ -122,7 +122,14 @@ enum LedgerUpgradeType LEDGER_UPGRADE_BASE_FEE = 2, LEDGER_UPGRADE_MAX_TX_SET_SIZE = 3, LEDGER_UPGRADE_BASE_RESERVE = 4, - LEDGER_UPGRADE_FLAGS = 5 + LEDGER_UPGRADE_FLAGS = 5, + LEDGER_UPGRADE_CONFIG = 6, + LEDGER_UPGRADE_MAX_SOROBAN_TX_SET_SIZE = 7 +}; + +struct ConfigUpgradeSetKey { + Hash contractID; + Hash contentHash; }; union LedgerUpgrade switch (LedgerUpgradeType type) @@ -137,6 +144,17 @@ case LEDGER_UPGRADE_BASE_RESERVE: uint32 newBaseReserve; // update baseReserve case LEDGER_UPGRADE_FLAGS: uint32 newFlags; // update flags +case LEDGER_UPGRADE_CONFIG: + // Update arbitrary `ConfigSetting` entries identified by the key. + ConfigUpgradeSetKey newConfig; +case LEDGER_UPGRADE_MAX_SOROBAN_TX_SET_SIZE: + // Update ConfigSettingContractExecutionLanesV0.ledgerMaxTxCount without + // using `LEDGER_UPGRADE_CONFIG`. + uint32 newMaxSorobanTxSetSize; +}; + +struct ConfigUpgradeSet { + ConfigSettingEntry updatedEntry<>; }; /* Entries used to define the bucket list */ @@ -348,6 +366,74 @@ struct TransactionMetaV2 // applied if any }; +enum ContractEventType +{ + SYSTEM = 0, + CONTRACT = 1, + DIAGNOSTIC = 2 +}; + +struct ContractEvent +{ + // We can use this to add more fields, or because it + // is first, to change ContractEvent into a union. + ExtensionPoint ext; + + Hash* contractID; + ContractEventType type; + + union switch (int v) + { + case 0: + struct + { + SCVal topics<>; + SCVal data; + } v0; + } + body; +}; + +struct DiagnosticEvent +{ + bool inSuccessfulContractCall; + ContractEvent event; +}; + +struct SorobanTransactionMeta +{ + ExtensionPoint ext; + + ContractEvent events<>; // custom events populated by the + // contracts themselves. + SCVal returnValue; // return value of the host fn invocation + + // Diagnostics events that are not hashed. + // This will contain all contract and diagnostic events. Even ones + // that were emitted in a failed contract call. + DiagnosticEvent diagnosticEvents<>; +}; + +struct TransactionMetaV3 +{ + ExtensionPoint ext; + + LedgerEntryChanges txChangesBefore; // tx level changes before operations + // are applied if any + OperationMeta operations<>; // meta for each operation + LedgerEntryChanges txChangesAfter; // tx level changes after operations are + // applied if any + SorobanTransactionMeta* sorobanMeta; // Soroban-specific meta (only for + // Soroban transactions). +}; + +// This is in Stellar-ledger.x to due to a circular dependency +struct InvokeHostFunctionSuccessPreImage +{ + SCVal returnValue; + ContractEvent events<>; +}; + // this is the meta produced when applying transactions // it does not include pre-apply updates such as fees union TransactionMeta switch (int v) @@ -358,6 +444,8 @@ case 1: TransactionMetaV1 v1; case 2: TransactionMetaV2 v2; +case 3: + TransactionMetaV3 v3; }; // This struct groups together changes on a per transaction basis @@ -398,6 +486,10 @@ struct LedgerCloseMetaV0 struct LedgerCloseMetaV1 { + // We forgot to add an ExtensionPoint in v0 but at least + // we can add one now in v1. + ExtensionPoint ext; + LedgerHeaderHistoryEntry ledgerHeader; GeneralizedTransactionSet txSet; @@ -412,6 +504,17 @@ struct LedgerCloseMetaV1 // other misc information attached to the ledger close SCPHistoryEntry scpInfo<>; + + // Size in bytes of BucketList, to support downstream + // systems calculating storage fees correctly. + uint64 totalByteSizeOfBucketList; + + // Temp keys that are being evicted at this ledger. + LedgerKey evictedTemporaryLedgerKeys<>; + + // Archived restorable ledger entries that are being + // evicted at this ledger. + LedgerEntry evictedPersistentLedgerEntries<>; }; union LedgerCloseMeta switch (int v) diff --git a/xdr/Stellar-overlay.x b/xdr/Stellar-overlay.x index 0601a3a4e4..4c964736dc 100644 --- a/xdr/Stellar-overlay.x +++ b/xdr/Stellar-overlay.x @@ -27,6 +27,12 @@ struct SendMore uint32 numMessages; }; +struct SendMoreExtended +{ + uint32 numMessages; + uint32 numBytes; +}; + struct AuthCert { Curve25519Public pubkey; @@ -47,11 +53,18 @@ struct Hello uint256 nonce; }; +// During the roll-out phrase, nodes can disable flow control in bytes. +// Therefore, we need a way to communicate with other nodes +// that we want/don't want flow control in bytes. +// We use the `flags` field in the Auth message with a special value +// set to communicate this. Note that AUTH_MSG_FLAG_FLOW_CONTROL_BYTES_REQUESTED != 0 +// AND AUTH_MSG_FLAG_FLOW_CONTROL_BYTES_REQUESTED != 100 (as previously +// that value was used for other purposes). +const AUTH_MSG_FLAG_FLOW_CONTROL_BYTES_REQUESTED = 200; + struct Auth { - // Empty message, just to confirm - // establishment of MAC keys. - int unused; + int flags; }; enum IPAddrType @@ -74,7 +87,7 @@ struct PeerAddress uint32 numFailures; }; -// Next ID: 18 +// Next ID: 21 enum MessageType { ERROR_MSG = 0, @@ -102,7 +115,11 @@ enum MessageType SURVEY_REQUEST = 14, SURVEY_RESPONSE = 15, - SEND_MORE = 16 + SEND_MORE = 16, + SEND_MORE_EXTENDED = 20, + + FLOOD_ADVERT = 18, + FLOOD_DEMAND = 19 }; struct DontHave @@ -116,6 +133,12 @@ enum SurveyMessageCommandType SURVEY_TOPOLOGY = 0 }; +enum SurveyMessageResponseType +{ + SURVEY_TOPOLOGY_RESPONSE_V0 = 0, + SURVEY_TOPOLOGY_RESPONSE_V1 = 1 +}; + struct SurveyRequestMessage { NodeID surveyorPeerID; @@ -170,19 +193,49 @@ struct PeerStats typedef PeerStats PeerStatList<25>; -struct TopologyResponseBody +struct TopologyResponseBodyV0 +{ + PeerStatList inboundPeers; + PeerStatList outboundPeers; + + uint32 totalInboundPeerCount; + uint32 totalOutboundPeerCount; +}; + +struct TopologyResponseBodyV1 { PeerStatList inboundPeers; PeerStatList outboundPeers; uint32 totalInboundPeerCount; uint32 totalOutboundPeerCount; + + uint32 maxInboundPeerCount; + uint32 maxOutboundPeerCount; }; -union SurveyResponseBody switch (SurveyMessageCommandType type) +union SurveyResponseBody switch (SurveyMessageResponseType type) +{ +case SURVEY_TOPOLOGY_RESPONSE_V0: + TopologyResponseBodyV0 topologyResponseBodyV0; +case SURVEY_TOPOLOGY_RESPONSE_V1: + TopologyResponseBodyV1 topologyResponseBodyV1; +}; + +const TX_ADVERT_VECTOR_MAX_SIZE = 1000; +typedef Hash TxAdvertVector; + +struct FloodAdvert +{ + TxAdvertVector txHashes; +}; + +const TX_DEMAND_VECTOR_MAX_SIZE = 1000; +typedef Hash TxDemandVector; + +struct FloodDemand { -case SURVEY_TOPOLOGY: - TopologyResponseBody topologyResponseBody; + TxDemandVector txHashes; }; union StellarMessage switch (MessageType type) @@ -227,6 +280,13 @@ case GET_SCP_STATE: uint32 getSCPLedgerSeq; // ledger seq requested ; if 0, requests the latest case SEND_MORE: SendMore sendMoreMessage; +case SEND_MORE_EXTENDED: + SendMoreExtended sendMoreExtendedMessage; +// Pull mode +case FLOOD_ADVERT: + FloodAdvert floodAdvert; +case FLOOD_DEMAND: + FloodDemand floodDemand; }; union AuthenticatedMessage switch (uint32 v) diff --git a/xdr/Stellar-transaction.x b/xdr/Stellar-transaction.x index 23918226df..87dd32d385 100644 --- a/xdr/Stellar-transaction.x +++ b/xdr/Stellar-transaction.x @@ -2,11 +2,15 @@ // under the Apache License, Version 2.0. See the COPYING file at the root // of this distribution or at http://www.apache.org/licenses/LICENSE-2.0 +%#include "xdr/Stellar-contract.h" %#include "xdr/Stellar-ledger-entries.h" namespace stellar { +// maximum number of operations per transaction +const MAX_OPS_PER_TX = 100; + union LiquidityPoolParameters switch (LiquidityPoolType type) { case LIQUIDITY_POOL_CONSTANT_PRODUCT: @@ -57,7 +61,10 @@ enum OperationType CLAWBACK_CLAIMABLE_BALANCE = 20, SET_TRUST_LINE_FLAGS = 21, LIQUIDITY_POOL_DEPOSIT = 22, - LIQUIDITY_POOL_WITHDRAW = 23 + LIQUIDITY_POOL_WITHDRAW = 23, + INVOKE_HOST_FUNCTION = 24, + EXTEND_FOOTPRINT_TTL = 25, + RESTORE_FOOTPRINT = 26 }; /* CreateAccount @@ -465,6 +472,141 @@ struct LiquidityPoolWithdrawOp int64 minAmountB; // minimum amount of second asset to withdraw }; +enum HostFunctionType +{ + HOST_FUNCTION_TYPE_INVOKE_CONTRACT = 0, + HOST_FUNCTION_TYPE_CREATE_CONTRACT = 1, + HOST_FUNCTION_TYPE_UPLOAD_CONTRACT_WASM = 2 +}; + +enum ContractIDPreimageType +{ + CONTRACT_ID_PREIMAGE_FROM_ADDRESS = 0, + CONTRACT_ID_PREIMAGE_FROM_ASSET = 1 +}; + +union ContractIDPreimage switch (ContractIDPreimageType type) +{ +case CONTRACT_ID_PREIMAGE_FROM_ADDRESS: + struct + { + SCAddress address; + uint256 salt; + } fromAddress; +case CONTRACT_ID_PREIMAGE_FROM_ASSET: + Asset fromAsset; +}; + +struct CreateContractArgs +{ + ContractIDPreimage contractIDPreimage; + ContractExecutable executable; +}; + +struct InvokeContractArgs { + SCAddress contractAddress; + SCSymbol functionName; + SCVal args<>; +}; + +union HostFunction switch (HostFunctionType type) +{ +case HOST_FUNCTION_TYPE_INVOKE_CONTRACT: + InvokeContractArgs invokeContract; +case HOST_FUNCTION_TYPE_CREATE_CONTRACT: + CreateContractArgs createContract; +case HOST_FUNCTION_TYPE_UPLOAD_CONTRACT_WASM: + opaque wasm<>; +}; + +enum SorobanAuthorizedFunctionType +{ + SOROBAN_AUTHORIZED_FUNCTION_TYPE_CONTRACT_FN = 0, + SOROBAN_AUTHORIZED_FUNCTION_TYPE_CREATE_CONTRACT_HOST_FN = 1 +}; + +union SorobanAuthorizedFunction switch (SorobanAuthorizedFunctionType type) +{ +case SOROBAN_AUTHORIZED_FUNCTION_TYPE_CONTRACT_FN: + InvokeContractArgs contractFn; +case SOROBAN_AUTHORIZED_FUNCTION_TYPE_CREATE_CONTRACT_HOST_FN: + CreateContractArgs createContractHostFn; +}; + +struct SorobanAuthorizedInvocation +{ + SorobanAuthorizedFunction function; + SorobanAuthorizedInvocation subInvocations<>; +}; + +struct SorobanAddressCredentials +{ + SCAddress address; + int64 nonce; + uint32 signatureExpirationLedger; + SCVal signature; +}; + +enum SorobanCredentialsType +{ + SOROBAN_CREDENTIALS_SOURCE_ACCOUNT = 0, + SOROBAN_CREDENTIALS_ADDRESS = 1 +}; + +union SorobanCredentials switch (SorobanCredentialsType type) +{ +case SOROBAN_CREDENTIALS_SOURCE_ACCOUNT: + void; +case SOROBAN_CREDENTIALS_ADDRESS: + SorobanAddressCredentials address; +}; + +/* Unit of authorization data for Soroban. + + Represents an authorization for executing the tree of authorized contract + and/or host function calls by the user defined by `credentials`. +*/ +struct SorobanAuthorizationEntry +{ + SorobanCredentials credentials; + SorobanAuthorizedInvocation rootInvocation; +}; + +/* Upload Wasm, create, and invoke contracts in Soroban. + + Threshold: med + Result: InvokeHostFunctionResult +*/ +struct InvokeHostFunctionOp +{ + // Host function to invoke. + HostFunction hostFunction; + // Per-address authorizations for this host function. + SorobanAuthorizationEntry auth<>; +}; + +/* Extend the TTL of the entries specified in the readOnly footprint + so they will live at least extendTo ledgers from lcl. + + Threshold: low + Result: ExtendFootprintTTLResult +*/ +struct ExtendFootprintTTLOp +{ + ExtensionPoint ext; + uint32 extendTo; +}; + +/* Restore the archived entries specified in the readWrite footprint. + + Threshold: low + Result: RestoreFootprintOp +*/ +struct RestoreFootprintOp +{ + ExtensionPoint ext; +}; + /* An operation is the lowest unit of work that a transaction does */ struct Operation { @@ -523,6 +665,12 @@ struct Operation LiquidityPoolDepositOp liquidityPoolDepositOp; case LIQUIDITY_POOL_WITHDRAW: LiquidityPoolWithdrawOp liquidityPoolWithdrawOp; + case INVOKE_HOST_FUNCTION: + InvokeHostFunctionOp invokeHostFunctionOp; + case EXTEND_FOOTPRINT_TTL: + ExtendFootprintTTLOp extendFootprintTTLOp; + case RESTORE_FOOTPRINT: + RestoreFootprintOp restoreFootprintOp; } body; }; @@ -540,11 +688,25 @@ case ENVELOPE_TYPE_POOL_REVOKE_OP_ID: struct { AccountID sourceAccount; - SequenceNumber seqNum; + SequenceNumber seqNum; uint32 opNum; PoolID liquidityPoolID; Asset asset; } revokeID; +case ENVELOPE_TYPE_CONTRACT_ID: + struct + { + Hash networkID; + ContractIDPreimage contractIDPreimage; + } contractID; +case ENVELOPE_TYPE_SOROBAN_AUTHORIZATION: + struct + { + Hash networkID; + int64 nonce; + uint32 signatureExpirationLedger; + SorobanAuthorizedInvocation invocation; + } sorobanAuthorization; }; enum MemoType @@ -632,8 +794,44 @@ case PRECOND_V2: PreconditionsV2 v2; }; -// maximum number of operations per transaction -const MAX_OPS_PER_TX = 100; +// Ledger key sets touched by a smart contract transaction. +struct LedgerFootprint +{ + LedgerKey readOnly<>; + LedgerKey readWrite<>; +}; + +// Resource limits for a Soroban transaction. +// The transaction will fail if it exceeds any of these limits. +struct SorobanResources +{ + // The ledger footprint of the transaction. + LedgerFootprint footprint; + // The maximum number of instructions this transaction can use + uint32 instructions; + + // The maximum number of bytes this transaction can read from ledger + uint32 readBytes; + // The maximum number of bytes this transaction can write to ledger + uint32 writeBytes; +}; + +// The transaction extension for Soroban. +struct SorobanTransactionData +{ + ExtensionPoint ext; + SorobanResources resources; + // Amount of the transaction `fee` allocated to the Soroban resource fees. + // The fraction of `resourceFee` corresponding to `resources` specified + // above is *not* refundable (i.e. fees for instructions, ledger I/O), as + // well as fees for the transaction size. + // The remaining part of the fee is refundable and the charged value is + // based on the actual consumption of refundable resources (events, ledger + // rent bumps). + // The `inclusionFee` used for prioritization of the transaction is defined + // as `tx.fee - resourceFee`. + int64 resourceFee; +}; // TransactionV0 is a transaction with the AccountID discriminant stripped off, // leaving a raw ed25519 public key to identify the source account. This is used @@ -695,6 +893,8 @@ struct Transaction { case 0: void; + case 1: + SorobanTransactionData sorobanData; } ext; }; @@ -1588,6 +1788,73 @@ case LIQUIDITY_POOL_WITHDRAW_UNDER_MINIMUM: void; }; +enum InvokeHostFunctionResultCode +{ + // codes considered as "success" for the operation + INVOKE_HOST_FUNCTION_SUCCESS = 0, + + // codes considered as "failure" for the operation + INVOKE_HOST_FUNCTION_MALFORMED = -1, + INVOKE_HOST_FUNCTION_TRAPPED = -2, + INVOKE_HOST_FUNCTION_RESOURCE_LIMIT_EXCEEDED = -3, + INVOKE_HOST_FUNCTION_ENTRY_ARCHIVED = -4, + INVOKE_HOST_FUNCTION_INSUFFICIENT_REFUNDABLE_FEE = -5 +}; + +union InvokeHostFunctionResult switch (InvokeHostFunctionResultCode code) +{ +case INVOKE_HOST_FUNCTION_SUCCESS: + Hash success; // sha256(InvokeHostFunctionSuccessPreImage) +case INVOKE_HOST_FUNCTION_MALFORMED: +case INVOKE_HOST_FUNCTION_TRAPPED: +case INVOKE_HOST_FUNCTION_RESOURCE_LIMIT_EXCEEDED: +case INVOKE_HOST_FUNCTION_ENTRY_ARCHIVED: +case INVOKE_HOST_FUNCTION_INSUFFICIENT_REFUNDABLE_FEE: + void; +}; + +enum ExtendFootprintTTLResultCode +{ + // codes considered as "success" for the operation + EXTEND_FOOTPRINT_TTL_SUCCESS = 0, + + // codes considered as "failure" for the operation + EXTEND_FOOTPRINT_TTL_MALFORMED = -1, + EXTEND_FOOTPRINT_TTL_RESOURCE_LIMIT_EXCEEDED = -2, + EXTEND_FOOTPRINT_TTL_INSUFFICIENT_REFUNDABLE_FEE = -3 +}; + +union ExtendFootprintTTLResult switch (ExtendFootprintTTLResultCode code) +{ +case EXTEND_FOOTPRINT_TTL_SUCCESS: + void; +case EXTEND_FOOTPRINT_TTL_MALFORMED: +case EXTEND_FOOTPRINT_TTL_RESOURCE_LIMIT_EXCEEDED: +case EXTEND_FOOTPRINT_TTL_INSUFFICIENT_REFUNDABLE_FEE: + void; +}; + +enum RestoreFootprintResultCode +{ + // codes considered as "success" for the operation + RESTORE_FOOTPRINT_SUCCESS = 0, + + // codes considered as "failure" for the operation + RESTORE_FOOTPRINT_MALFORMED = -1, + RESTORE_FOOTPRINT_RESOURCE_LIMIT_EXCEEDED = -2, + RESTORE_FOOTPRINT_INSUFFICIENT_REFUNDABLE_FEE = -3 +}; + +union RestoreFootprintResult switch (RestoreFootprintResultCode code) +{ +case RESTORE_FOOTPRINT_SUCCESS: + void; +case RESTORE_FOOTPRINT_MALFORMED: +case RESTORE_FOOTPRINT_RESOURCE_LIMIT_EXCEEDED: +case RESTORE_FOOTPRINT_INSUFFICIENT_REFUNDABLE_FEE: + void; +}; + /* High level Operation Result */ enum OperationResultCode { @@ -1654,6 +1921,12 @@ case opINNER: LiquidityPoolDepositResult liquidityPoolDepositResult; case LIQUIDITY_POOL_WITHDRAW: LiquidityPoolWithdrawResult liquidityPoolWithdrawResult; + case INVOKE_HOST_FUNCTION: + InvokeHostFunctionResult invokeHostFunctionResult; + case EXTEND_FOOTPRINT_TTL: + ExtendFootprintTTLResult extendFootprintTTLResult; + case RESTORE_FOOTPRINT: + RestoreFootprintResult restoreFootprintResult; } tr; case opBAD_AUTH: @@ -1684,12 +1957,12 @@ enum TransactionResultCode txBAD_AUTH_EXTRA = -10, // unused signatures attached to transaction txINTERNAL_ERROR = -11, // an unknown error occurred - txNOT_SUPPORTED = -12, // transaction type not supported - txFEE_BUMP_INNER_FAILED = -13, // fee bump inner transaction failed - txBAD_SPONSORSHIP = -14, // sponsorship not confirmed - txBAD_MIN_SEQ_AGE_OR_GAP = - -15, // minSeqAge or minSeqLedgerGap conditions not met - txMALFORMED = -16 // precondition is invalid + txNOT_SUPPORTED = -12, // transaction type not supported + txFEE_BUMP_INNER_FAILED = -13, // fee bump inner transaction failed + txBAD_SPONSORSHIP = -14, // sponsorship not confirmed + txBAD_MIN_SEQ_AGE_OR_GAP = -15, // minSeqAge or minSeqLedgerGap conditions not met + txMALFORMED = -16, // precondition is invalid + txSOROBAN_INVALID = -17 // soroban-specific preconditions were not met }; // InnerTransactionResult must be binary compatible with TransactionResult @@ -1720,6 +1993,7 @@ struct InnerTransactionResult case txBAD_SPONSORSHIP: case txBAD_MIN_SEQ_AGE_OR_GAP: case txMALFORMED: + case txSOROBAN_INVALID: void; } result; @@ -1766,6 +2040,7 @@ struct TransactionResult case txBAD_SPONSORSHIP: case txBAD_MIN_SEQ_AGE_OR_GAP: case txMALFORMED: + case txSOROBAN_INVALID: void; } result; diff --git a/xdr/Stellar-types.x b/xdr/Stellar-types.x index c3a1ebe2c8..d71bf0d49d 100644 --- a/xdr/Stellar-types.x +++ b/xdr/Stellar-types.x @@ -14,6 +14,9 @@ typedef int int32; typedef unsigned hyper uint64; typedef hyper int64; +typedef uint64 TimePoint; +typedef uint64 Duration; + // An ExtensionPoint is always marshaled as a 32-bit 0 value. At a // later point, it can be replaced by a different union so as to // extend a structure. @@ -79,6 +82,7 @@ typedef opaque Signature<64>; typedef opaque SignatureHint[4]; typedef PublicKey NodeID; +typedef PublicKey AccountID; struct Curve25519Secret { diff --git a/xdr/account_id.go b/xdr/account_id.go index 9b9e231a8c..da36310e79 100644 --- a/xdr/account_id.go +++ b/xdr/account_id.go @@ -55,13 +55,8 @@ func (aid *AccountId) Equals(other AccountId) bool { } // LedgerKey implements the `Keyer` interface -func (aid *AccountId) LedgerKey() (ret LedgerKey) { - err := ret.SetAccount(*aid) - if err != nil { - panic(err) - } - - return +func (aid *AccountId) LedgerKey() (key LedgerKey, err error) { + return key, key.SetAccount(*aid) } func (e *EncodingBuffer) accountIdCompressEncodeTo(aid AccountId) error { diff --git a/xdr/account_id_test.go b/xdr/account_id_test.go index 5211b45873..d4119aaae5 100644 --- a/xdr/account_id_test.go +++ b/xdr/account_id_test.go @@ -43,7 +43,8 @@ var _ = Describe("xdr.AccountId#LedgerKey()", func() { err := aid.SetAddress("GCR22L3WS7TP72S4Z27YTO6JIQYDJK2KLS2TQNHK6Y7XYPA3AGT3X4FH") Expect(err).ShouldNot(HaveOccurred()) - key := aid.LedgerKey() + key, err := aid.LedgerKey() + Expect(err).ShouldNot(HaveOccurred()) packed := key.MustAccount().AccountId Expect(packed.Equals(aid)).To(BeTrue()) }) diff --git a/xdr/asset.go b/xdr/asset.go index 4f30bb69fe..eaf2b4f754 100644 --- a/xdr/asset.go +++ b/xdr/asset.go @@ -1,6 +1,7 @@ package xdr import ( + "crypto/sha256" "errors" "fmt" "regexp" @@ -44,7 +45,7 @@ func MustNewCreditAsset(code string, issuer string) Asset { return a } -// NewAssetCodeFromString returns a new allow trust asset, panicking if it can't. +// NewAssetCodeFromString returns a new credit asset, erroring if it can't. func NewAssetCodeFromString(code string) (AssetCode, error) { a := AssetCode{} length := len(code) @@ -433,3 +434,24 @@ func (a *Asset) LessThan(b Asset) bool { return a.GetIssuer() < b.GetIssuer() } + +// ContractID returns the expected Stellar Asset Contract id for the given +// asset and network. +func (a Asset) ContractID(passphrase string) ([32]byte, error) { + networkId := Hash(sha256.Sum256([]byte(passphrase))) + preImage := HashIdPreimage{ + Type: EnvelopeTypeEnvelopeTypeContractId, + ContractId: &HashIdPreimageContractId{ + NetworkId: networkId, + ContractIdPreimage: ContractIdPreimage{ + Type: ContractIdPreimageTypeContractIdPreimageFromAsset, + FromAsset: &a, + }, + }, + } + xdrPreImageBytes, err := preImage.MarshalBinary() + if err != nil { + return [32]byte{}, err + } + return sha256.Sum256(xdrPreImageBytes), nil +} diff --git a/xdr/asset_test.go b/xdr/asset_test.go index e1d99d9454..12ecee0875 100644 --- a/xdr/asset_test.go +++ b/xdr/asset_test.go @@ -473,6 +473,16 @@ func TestAssetLessThan(t *testing.T) { assert.False(t, assetIssuerB.LessThan(assetIssuerA)) assert.False(t, assetIssuerB.LessThan(assetIssuerB)) }) + + t.Run("test if codes with upper-case letters are sorted before lower-case letters", func(t *testing.T) { + // All upper-case letters should come before any lower-case ones + assetA, err := NewCreditAsset("B", "GA7NLOF4EHWMJF6DBXXV2H6AYI7IHYWNFZR6R52BYBLY7TE5Q74AIDRA") + require.NoError(t, err) + assetB, err := NewCreditAsset("a", "GA7NLOF4EHWMJF6DBXXV2H6AYI7IHYWNFZR6R52BYBLY7TE5Q74AIDRA") + require.NoError(t, err) + + assert.True(t, assetA.LessThan(assetB)) + }) } func BenchmarkAssetString(b *testing.B) { diff --git a/xdr/db.go b/xdr/db.go index 04fae28752..5884b07419 100644 --- a/xdr/db.go +++ b/xdr/db.go @@ -9,8 +9,18 @@ import ( // This file contains implementations of the sql.Scanner interface for stellar xdr types +// Scan reads from src into a ledgerCloseMeta struct +func (l *LedgerCloseMeta) Scan(src any) error { + return l.UnmarshalBinary(src.([]byte)) +} + +// Value implements the database/sql/driver Valuer interface. +func (l LedgerCloseMeta) Value() (driver.Value, error) { + return l.MarshalBinary() +} + // Scan reads from src into an AccountFlags -func (t *AccountFlags) Scan(src interface{}) error { +func (t *AccountFlags) Scan(src any) error { val, ok := src.(int64) if !ok { return errors.New("Invalid value for xdr.AccountFlags") @@ -21,7 +31,7 @@ func (t *AccountFlags) Scan(src interface{}) error { } // Scan reads from src into an AssetType -func (t *AssetType) Scan(src interface{}) error { +func (t *AssetType) Scan(src any) error { val, ok := src.(int64) if !ok { return errors.New("Invalid value for xdr.AssetType") @@ -32,7 +42,7 @@ func (t *AssetType) Scan(src interface{}) error { } // Scan reads from src into an Asset -func (t *Asset) Scan(src interface{}) error { +func (t *Asset) Scan(src any) error { return safeBase64Scan(src, t) } @@ -42,7 +52,7 @@ func (t Asset) Value() (driver.Value, error) { } // Scan reads from src into a ClaimPredicate -func (c *ClaimPredicate) Scan(src interface{}) error { +func (c *ClaimPredicate) Scan(src any) error { return safeBase64Scan(src, c) } @@ -52,7 +62,7 @@ func (c ClaimPredicate) Value() (driver.Value, error) { } // Scan reads from src into an Int64 -func (t *Int64) Scan(src interface{}) error { +func (t *Int64) Scan(src any) error { val, ok := src.(int64) if !ok { return errors.New("Invalid value for xdr.Int64") @@ -63,7 +73,7 @@ func (t *Int64) Scan(src interface{}) error { } // Scan reads from a src into an xdr.Hash -func (t *Hash) Scan(src interface{}) error { +func (t *Hash) Scan(src any) error { decodedBytes, err := hex.DecodeString(string(src.([]uint8))) if err != nil { return err @@ -78,58 +88,58 @@ func (t *Hash) Scan(src interface{}) error { } // Scan reads from src into an LedgerUpgrade struct -func (t *LedgerUpgrade) Scan(src interface{}) error { +func (t *LedgerUpgrade) Scan(src any) error { return safeBase64Scan(src, t) } // Scan reads from src into an LedgerEntryChanges struct -func (t *LedgerEntryChanges) Scan(src interface{}) error { +func (t *LedgerEntryChanges) Scan(src any) error { return safeBase64Scan(src, t) } // Scan reads from src into an LedgerHeader struct -func (t *LedgerHeader) Scan(src interface{}) error { +func (t *LedgerHeader) Scan(src any) error { return safeBase64Scan(src, t) } // Scan reads from src into an ScpEnvelope struct -func (t *ScpEnvelope) Scan(src interface{}) error { +func (t *ScpEnvelope) Scan(src any) error { return safeBase64Scan(src, t) } // Scan reads from src into an ScpEnvelope struct -func (t *ScpQuorumSet) Scan(src interface{}) error { +func (t *ScpQuorumSet) Scan(src any) error { return safeBase64Scan(src, t) } // Scan reads from src into an Thresholds struct -func (t *Thresholds) Scan(src interface{}) error { +func (t *Thresholds) Scan(src any) error { return safeBase64Scan(src, t) } // Scan reads from src into an TransactionEnvelope struct -func (t *TransactionEnvelope) Scan(src interface{}) error { +func (t *TransactionEnvelope) Scan(src any) error { return safeBase64Scan(src, t) } // Scan reads from src into an TransactionMeta struct -func (t *TransactionMeta) Scan(src interface{}) error { +func (t *TransactionMeta) Scan(src any) error { return safeBase64Scan(src, t) } // Scan reads from src into an TransactionResult struct -func (t *TransactionResult) Scan(src interface{}) error { +func (t *TransactionResult) Scan(src any) error { return safeBase64Scan(src, t) } // Scan reads from src into an TransactionResultPair struct -func (t *TransactionResultPair) Scan(src interface{}) error { +func (t *TransactionResultPair) Scan(src any) error { return safeBase64Scan(src, t) } // safeBase64Scan scans from src (which should be either a []byte or string) // into dest by using `SafeUnmarshalBase64`. -func safeBase64Scan(src, dest interface{}) error { +func safeBase64Scan(src, dest any) error { var val string switch src := src.(type) { case []byte: diff --git a/xdr/event.go b/xdr/event.go new file mode 100644 index 0000000000..2ae97a0d2c --- /dev/null +++ b/xdr/event.go @@ -0,0 +1,23 @@ +package xdr + +import ( + "encoding/hex" + "fmt" +) + +func (ce ContractEvent) String() string { + result := ce.Type.String() + "(" + if ce.ContractId != nil { + result += hex.EncodeToString(ce.ContractId[:]) + "," + } + result += ce.Body.String() + ")" + return result +} + +func (eb ContractEventBody) String() string { + return fmt.Sprintf("%+v", *eb.V0) +} + +func (de DiagnosticEvent) String() string { + return fmt.Sprintf("%s, successful call: %t", de.Event, de.InSuccessfulContractCall) +} diff --git a/xdr/go_string_test.go b/xdr/go_string_test.go index c3d87b6d3f..30d3c40080 100644 --- a/xdr/go_string_test.go +++ b/xdr/go_string_test.go @@ -221,7 +221,7 @@ func TestTransactionEnvelopeGoStringerV1(t *testing.T) { assert.Equal( t, - `xdr.TransactionEnvelope{Type: xdr.EnvelopeTypeEnvelopeTypeTx,V1: &xdr.TransactionV1Envelope{Tx:xdr.Transaction{SourceAccount:xdr.MustMuxedAddress("GC7ERFCD7QLDFRSEPLYB3GYSWX6GYMCHLDL45N4S5Q2N5EJDOMOJ63V4"), Fee:100, SeqNum:99284448289310326, Cond:xdr.Preconditions{Type: xdr.PreconditionTypePrecondTime, TimeBounds: &xdr.TimeBounds{MinTime: xdr.TimePoint(0), MaxTime: xdr.TimePoint(0)}}, Memo:xdr.Memo{Type: xdr.MemoTypeMemoNone}, Operations:[]xdr.Operation{xdr.Operation{Body: xdr.OperationBody{Type: xdr.OperationTypeManageSellOffer,ManageSellOfferOp: &xdr.ManageSellOfferOp{Selling:xdr.MustNewNativeAsset(), Buying:xdr.MustNewCreditAsset("USD", "GB2O5PBQJDAFCNM2U2DIMVAEI7ISOYL4UJDTLN42JYYXAENKBWY6OBKZ"), Amount:19995825, Price:xdr.Price{N:524087, D:5000000}, OfferId:258020376}}}}, Ext:xdr.TransactionExt{V:0}}, Signatures:[]xdr.DecoratedSignature{xdr.DecoratedSignature{Hint:xdr.SignatureHint{0x23, 0x73, 0x1c, 0x9f}, Signature:xdr.Signature{0x71, 0xd3, 0xfa, 0x9, 0xd9, 0x12, 0xd3, 0xcf, 0x2c, 0x6f, 0xd9, 0x29, 0x9a, 0xdd, 0xfd, 0x77, 0x84, 0xe1, 0x6, 0x4f, 0xe, 0xed, 0x9, 0x77, 0xe, 0x46, 0x9a, 0xa3, 0x59, 0xf3, 0x7, 0x16, 0xb3, 0x28, 0x4a, 0x40, 0x40, 0x98, 0x1e, 0xe1, 0xea, 0xc6, 0xa4, 0xc, 0x6e, 0x96, 0xc3, 0x1e, 0x46, 0x71, 0x4f, 0x54, 0x32, 0xc5, 0x93, 0x81, 0x7d, 0xb1, 0xa4, 0xf9, 0xa5, 0x3e, 0x33, 0x4}}}}}`, + `xdr.TransactionEnvelope{Type: xdr.EnvelopeTypeEnvelopeTypeTx,V1: &xdr.TransactionV1Envelope{Tx:xdr.Transaction{SourceAccount:xdr.MustMuxedAddress("GC7ERFCD7QLDFRSEPLYB3GYSWX6GYMCHLDL45N4S5Q2N5EJDOMOJ63V4"), Fee:100, SeqNum:99284448289310326, Cond:xdr.Preconditions{Type: xdr.PreconditionTypePrecondTime, TimeBounds: &xdr.TimeBounds{MinTime: xdr.TimePoint(0), MaxTime: xdr.TimePoint(0)}}, Memo:xdr.Memo{Type: xdr.MemoTypeMemoNone}, Operations:[]xdr.Operation{xdr.Operation{Body: xdr.OperationBody{Type: xdr.OperationTypeManageSellOffer,ManageSellOfferOp: &xdr.ManageSellOfferOp{Selling:xdr.MustNewNativeAsset(), Buying:xdr.MustNewCreditAsset("USD", "GB2O5PBQJDAFCNM2U2DIMVAEI7ISOYL4UJDTLN42JYYXAENKBWY6OBKZ"), Amount:19995825, Price:xdr.Price{N:524087, D:5000000}, OfferId:258020376}}}}, Ext:xdr.TransactionExt{V:0, SorobanData:(*xdr.SorobanTransactionData)(nil)}}, Signatures:[]xdr.DecoratedSignature{xdr.DecoratedSignature{Hint:xdr.SignatureHint{0x23, 0x73, 0x1c, 0x9f}, Signature:xdr.Signature{0x71, 0xd3, 0xfa, 0x9, 0xd9, 0x12, 0xd3, 0xcf, 0x2c, 0x6f, 0xd9, 0x29, 0x9a, 0xdd, 0xfd, 0x77, 0x84, 0xe1, 0x6, 0x4f, 0xe, 0xed, 0x9, 0x77, 0xe, 0x46, 0x9a, 0xa3, 0x59, 0xf3, 0x7, 0x16, 0xb3, 0x28, 0x4a, 0x40, 0x40, 0x98, 0x1e, 0xe1, 0xea, 0xc6, 0xa4, 0xc, 0x6e, 0x96, 0xc3, 0x1e, 0x46, 0x71, 0x4f, 0x54, 0x32, 0xc5, 0x93, 0x81, 0x7d, 0xb1, 0xa4, 0xf9, 0xa5, 0x3e, 0x33, 0x4}}}}}`, fmt.Sprintf("%#v", envelope), ) } @@ -282,7 +282,7 @@ func TestTransactionEnvelopeGoStringerFeeBump(t *testing.T) { assert.Equal( t, - `xdr.TransactionEnvelope{Type: xdr.EnvelopeTypeEnvelopeTypeTxFeeBump,FeeBump: &xdr.FeeBumpTransactionEnvelope{Tx:xdr.FeeBumpTransaction{FeeSource:xdr.MustMuxedAddress("GD6WNNTW664WH7FXC5RUMUTF7P5QSURC2IT36VOQEEGFZ4UWUEQGECAL"), Fee:4000, InnerTx:xdr.FeeBumpTransactionInnerTx{Type: xdr.EnvelopeTypeEnvelopeTypeTx,V1: &xdr.TransactionV1Envelope{Tx:xdr.Transaction{SourceAccount:xdr.MustMuxedAddress("GD6WNNTW664WH7FXC5RUMUTF7P5QSURC2IT36VOQEEGFZ4UWUEQGECAL"), Fee:0, SeqNum:566862668627969, Cond:xdr.Preconditions{Type: xdr.PreconditionTypePrecondTime, TimeBounds: &xdr.TimeBounds{MinTime: xdr.TimePoint(0), MaxTime: xdr.TimePoint(0)}}, Memo:xdr.MemoText("My 1st fee bump! Woohoo!"), Operations:[]xdr.Operation{xdr.Operation{Body: xdr.OperationBody{Type: xdr.OperationTypePayment,PaymentOp: &xdr.PaymentOp{Destination:xdr.MustMuxedAddress("GD6WNNTW664WH7FXC5RUMUTF7P5QSURC2IT36VOQEEGFZ4UWUEQGECAL"), Asset:xdr.MustNewNativeAsset(), Amount:1000000000}}}}, Ext:xdr.TransactionExt{V:0}}, Signatures:[]xdr.DecoratedSignature{xdr.DecoratedSignature{Hint:xdr.SignatureHint{0x96, 0xa1, 0x20, 0x62}, Signature:xdr.Signature{0x5e, 0x36, 0x9, 0x6c, 0x7a, 0xa4, 0x73, 0xde, 0x20, 0xf9, 0x4f, 0x2, 0xf4, 0x9c, 0x66, 0x10, 0x42, 0x1f, 0xa1, 0x34, 0x68, 0x6b, 0xe4, 0xbf, 0xce, 0x67, 0x71, 0x3b, 0x61, 0x2c, 0x78, 0xae, 0x25, 0x66, 0xe, 0x28, 0xad, 0xe9, 0xe7, 0xb8, 0x8c, 0xf8, 0x46, 0xba, 0x98, 0x43, 0xde, 0x40, 0x27, 0xb8, 0xb4, 0x52, 0xf3, 0x70, 0xab, 0x80, 0x8b, 0xac, 0x45, 0xb, 0x1, 0xee, 0xbe, 0x6}}}}}, Ext:xdr.FeeBumpTransactionExt{V:0}}, Signatures:[]xdr.DecoratedSignature{xdr.DecoratedSignature{Hint:xdr.SignatureHint{0x96, 0xa1, 0x20, 0x62}, Signature:xdr.Signature{0xb2, 0xcc, 0x82, 0x6e, 0x9c, 0xa4, 0x3a, 0x11, 0x75, 0x33, 0xd1, 0xfd, 0xa2, 0x49, 0xc0, 0x50, 0xf1, 0xd8, 0x62, 0x7, 0xf6, 0xdf, 0x2, 0x9a, 0x46, 0xa5, 0xe8, 0x3a, 0xb7, 0xbf, 0x4b, 0xc7, 0xcb, 0xd4, 0x4f, 0xe0, 0xe5, 0x25, 0xb8, 0xe, 0xbe, 0xdc, 0x53, 0x68, 0x69, 0x19, 0xdc, 0x57, 0xf3, 0x39, 0x77, 0x71, 0xca, 0x73, 0x89, 0xa4, 0xdc, 0x2c, 0xca, 0xd4, 0x1d, 0x5f, 0x9d, 0x4}}}}}`, + `xdr.TransactionEnvelope{Type: xdr.EnvelopeTypeEnvelopeTypeTxFeeBump,FeeBump: &xdr.FeeBumpTransactionEnvelope{Tx:xdr.FeeBumpTransaction{FeeSource:xdr.MustMuxedAddress("GD6WNNTW664WH7FXC5RUMUTF7P5QSURC2IT36VOQEEGFZ4UWUEQGECAL"), Fee:4000, InnerTx:xdr.FeeBumpTransactionInnerTx{Type: xdr.EnvelopeTypeEnvelopeTypeTx,V1: &xdr.TransactionV1Envelope{Tx:xdr.Transaction{SourceAccount:xdr.MustMuxedAddress("GD6WNNTW664WH7FXC5RUMUTF7P5QSURC2IT36VOQEEGFZ4UWUEQGECAL"), Fee:0, SeqNum:566862668627969, Cond:xdr.Preconditions{Type: xdr.PreconditionTypePrecondTime, TimeBounds: &xdr.TimeBounds{MinTime: xdr.TimePoint(0), MaxTime: xdr.TimePoint(0)}}, Memo:xdr.MemoText("My 1st fee bump! Woohoo!"), Operations:[]xdr.Operation{xdr.Operation{Body: xdr.OperationBody{Type: xdr.OperationTypePayment,PaymentOp: &xdr.PaymentOp{Destination:xdr.MustMuxedAddress("GD6WNNTW664WH7FXC5RUMUTF7P5QSURC2IT36VOQEEGFZ4UWUEQGECAL"), Asset:xdr.MustNewNativeAsset(), Amount:1000000000}}}}, Ext:xdr.TransactionExt{V:0, SorobanData:(*xdr.SorobanTransactionData)(nil)}}, Signatures:[]xdr.DecoratedSignature{xdr.DecoratedSignature{Hint:xdr.SignatureHint{0x96, 0xa1, 0x20, 0x62}, Signature:xdr.Signature{0x5e, 0x36, 0x9, 0x6c, 0x7a, 0xa4, 0x73, 0xde, 0x20, 0xf9, 0x4f, 0x2, 0xf4, 0x9c, 0x66, 0x10, 0x42, 0x1f, 0xa1, 0x34, 0x68, 0x6b, 0xe4, 0xbf, 0xce, 0x67, 0x71, 0x3b, 0x61, 0x2c, 0x78, 0xae, 0x25, 0x66, 0xe, 0x28, 0xad, 0xe9, 0xe7, 0xb8, 0x8c, 0xf8, 0x46, 0xba, 0x98, 0x43, 0xde, 0x40, 0x27, 0xb8, 0xb4, 0x52, 0xf3, 0x70, 0xab, 0x80, 0x8b, 0xac, 0x45, 0xb, 0x1, 0xee, 0xbe, 0x6}}}}}, Ext:xdr.FeeBumpTransactionExt{V:0}}, Signatures:[]xdr.DecoratedSignature{xdr.DecoratedSignature{Hint:xdr.SignatureHint{0x96, 0xa1, 0x20, 0x62}, Signature:xdr.Signature{0xb2, 0xcc, 0x82, 0x6e, 0x9c, 0xa4, 0x3a, 0x11, 0x75, 0x33, 0xd1, 0xfd, 0xa2, 0x49, 0xc0, 0x50, 0xf1, 0xd8, 0x62, 0x7, 0xf6, 0xdf, 0x2, 0x9a, 0x46, 0xa5, 0xe8, 0x3a, 0xb7, 0xbf, 0x4b, 0xc7, 0xcb, 0xd4, 0x4f, 0xe0, 0xe5, 0x25, 0xb8, 0xe, 0xbe, 0xdc, 0x53, 0x68, 0x69, 0x19, 0xdc, 0x57, 0xf3, 0x39, 0x77, 0x71, 0xca, 0x73, 0x89, 0xa4, 0xdc, 0x2c, 0xca, 0xd4, 0x1d, 0x5f, 0x9d, 0x4}}}}}`, fmt.Sprintf("%#v", envelope), ) } diff --git a/xdr/hash.go b/xdr/hash.go index 80a1800464..2a15c18c9c 100644 --- a/xdr/hash.go +++ b/xdr/hash.go @@ -5,3 +5,15 @@ import "encoding/hex" func (h Hash) HexString() string { return hex.EncodeToString(h[:]) } + +func (s Hash) Equals(o Hash) bool { + if len(s) != len(o) { + return false + } + for i := 0; i < len(s); i++ { + if s[i] != o[i] { + return false + } + } + return true +} diff --git a/xdr/json_test.go b/xdr/json_test.go index 1e72912ee7..077c2f1777 100644 --- a/xdr/json_test.go +++ b/xdr/json_test.go @@ -71,7 +71,7 @@ func TestRandClaimPredicateJSON(t *testing.T) { gen.Next( shape, []randxdr.Preset{ - {randxdr.IsPtr, randxdr.SetPtr(true)}, + {Selector: randxdr.IsPtr, Setter: randxdr.SetPtr(true)}, }, ) assert.NoError(t, gxdr.Convert(shape, cp)) diff --git a/xdr/ledger_close_meta.go b/xdr/ledger_close_meta.go index 4d3248f394..2290f3bee1 100644 --- a/xdr/ledger_close_meta.go +++ b/xdr/ledger_close_meta.go @@ -1,21 +1,154 @@ package xdr +import ( + "fmt" +) + +func (l LedgerCloseMeta) LedgerHeaderHistoryEntry() LedgerHeaderHistoryEntry { + switch l.V { + case 0: + return l.MustV0().LedgerHeader + case 1: + return l.MustV1().LedgerHeader + default: + panic(fmt.Sprintf("Unsupported LedgerCloseMeta.V: %d", l.V)) + } +} + func (l LedgerCloseMeta) LedgerSequence() uint32 { - return uint32(l.MustV0().LedgerHeader.Header.LedgerSeq) + return uint32(l.LedgerHeaderHistoryEntry().Header.LedgerSeq) } func (l LedgerCloseMeta) LedgerHash() Hash { - return l.MustV0().LedgerHeader.Hash + return l.LedgerHeaderHistoryEntry().Hash } func (l LedgerCloseMeta) PreviousLedgerHash() Hash { - return l.MustV0().LedgerHeader.Header.PreviousLedgerHash + return l.LedgerHeaderHistoryEntry().Header.PreviousLedgerHash } func (l LedgerCloseMeta) ProtocolVersion() uint32 { - return uint32(l.MustV0().LedgerHeader.Header.LedgerVersion) + return uint32(l.LedgerHeaderHistoryEntry().Header.LedgerVersion) } func (l LedgerCloseMeta) BucketListHash() Hash { - return l.MustV0().LedgerHeader.Header.BucketListHash + return l.LedgerHeaderHistoryEntry().Header.BucketListHash +} + +func (l LedgerCloseMeta) CountTransactions() int { + switch l.V { + case 0: + return len(l.MustV0().TxProcessing) + case 1: + return len(l.MustV1().TxProcessing) + + default: + panic(fmt.Sprintf("Unsupported LedgerCloseMeta.V: %d", l.V)) + } +} + +func (l LedgerCloseMeta) TransactionEnvelopes() []TransactionEnvelope { + switch l.V { + case 0: + return l.MustV0().TxSet.Txs + case 1: + var envelopes = make([]TransactionEnvelope, 0, l.CountTransactions()) + for _, phase := range l.MustV1().TxSet.V1TxSet.Phases { + for _, component := range *phase.V0Components { + envelopes = append(envelopes, component.TxsMaybeDiscountedFee.Txs...) + } + } + return envelopes + default: + panic(fmt.Sprintf("Unsupported LedgerCloseMeta.V: %d", l.V)) + } +} + +// TransactionHash returns Hash for tx at index i in processing order.. +func (l LedgerCloseMeta) TransactionHash(i int) Hash { + switch l.V { + case 0: + return l.MustV0().TxProcessing[i].Result.TransactionHash + case 1: + return l.MustV1().TxProcessing[i].Result.TransactionHash + default: + panic(fmt.Sprintf("Unsupported LedgerCloseMeta.V: %d", l.V)) + } +} + +// TransactionResultPair returns TransactionResultPair for tx at index i in processing order. +func (l LedgerCloseMeta) TransactionResultPair(i int) TransactionResultPair { + switch l.V { + case 0: + return l.MustV0().TxProcessing[i].Result + case 1: + return l.MustV1().TxProcessing[i].Result + default: + panic(fmt.Sprintf("Unsupported LedgerCloseMeta.V: %d", l.V)) + } +} + +// FeeProcessing returns FeeProcessing for tx at index i in processing order. +func (l LedgerCloseMeta) FeeProcessing(i int) LedgerEntryChanges { + switch l.V { + case 0: + return l.MustV0().TxProcessing[i].FeeProcessing + case 1: + return l.MustV1().TxProcessing[i].FeeProcessing + default: + panic(fmt.Sprintf("Unsupported LedgerCloseMeta.V: %d", l.V)) + } +} + +// TxApplyProcessing returns TxApplyProcessing for tx at index i in processing order. +func (l LedgerCloseMeta) TxApplyProcessing(i int) TransactionMeta { + switch l.V { + case 0: + return l.MustV0().TxProcessing[i].TxApplyProcessing + case 1: + if l.MustV1().TxProcessing[i].TxApplyProcessing.V != 3 { + panic("TransactionResult unavailable because LedgerCloseMeta.V = 1 and TransactionMeta.V != 3") + } + return l.MustV1().TxProcessing[i].TxApplyProcessing + default: + panic(fmt.Sprintf("Unsupported LedgerCloseMeta.V: %d", l.V)) + } +} + +// UpgradesProcessing returns UpgradesProcessing for ledger. +func (l LedgerCloseMeta) UpgradesProcessing() []UpgradeEntryMeta { + switch l.V { + case 0: + return l.MustV0().UpgradesProcessing + case 1: + return l.MustV1().UpgradesProcessing + default: + panic(fmt.Sprintf("Unsupported LedgerCloseMeta.V: %d", l.V)) + } +} + +// EvictedTemporaryLedgerKeys returns a slice of ledger keys for +// temporary ledger entries that have been evicted in this ledger. +func (l LedgerCloseMeta) EvictedTemporaryLedgerKeys() ([]LedgerKey, error) { + switch l.V { + case 0: + return nil, nil + case 1: + return l.MustV1().EvictedTemporaryLedgerKeys, nil + default: + panic(fmt.Sprintf("Unsupported LedgerCloseMeta.V: %d", l.V)) + } +} + +// EvictedPersistentLedgerEntries returns the persistent ledger entries +// which have been evicted in this ledger. +func (l LedgerCloseMeta) EvictedPersistentLedgerEntries() ([]LedgerEntry, error) { + switch l.V { + case 0: + return nil, nil + case 1: + return l.MustV1().EvictedPersistentLedgerEntries, nil + default: + panic(fmt.Sprintf("Unsupported LedgerCloseMeta.V: %d", l.V)) + } } diff --git a/xdr/ledger_close_meta_test.go b/xdr/ledger_close_meta_test.go index ac978bfae8..7ed1cd3128 100644 --- a/xdr/ledger_close_meta_test.go +++ b/xdr/ledger_close_meta_test.go @@ -1,8 +1,9 @@ package xdr import ( - "github.com/stretchr/testify/assert" "testing" + + "github.com/stretchr/testify/assert" ) func TestLedgerSequence(t *testing.T) { diff --git a/xdr/ledger_entry.go b/xdr/ledger_entry.go index 3085836ed4..c04defb693 100644 --- a/xdr/ledger_entry.go +++ b/xdr/ledger_entry.go @@ -3,53 +3,8 @@ package xdr import "fmt" // LedgerKey implements the `Keyer` interface -func (entry *LedgerEntry) LedgerKey() LedgerKey { - var body interface{} - - switch entry.Data.Type { - case LedgerEntryTypeAccount: - account := entry.Data.MustAccount() - body = LedgerKeyAccount{ - AccountId: account.AccountId, - } - case LedgerEntryTypeData: - data := entry.Data.MustData() - body = LedgerKeyData{ - AccountId: data.AccountId, - DataName: data.DataName, - } - case LedgerEntryTypeOffer: - offer := entry.Data.MustOffer() - body = LedgerKeyOffer{ - SellerId: offer.SellerId, - OfferId: offer.OfferId, - } - case LedgerEntryTypeTrustline: - tline := entry.Data.MustTrustLine() - body = LedgerKeyTrustLine{ - AccountId: tline.AccountId, - Asset: tline.Asset, - } - case LedgerEntryTypeClaimableBalance: - cBalance := entry.Data.MustClaimableBalance() - body = LedgerKeyClaimableBalance{ - BalanceId: cBalance.BalanceId, - } - case LedgerEntryTypeLiquidityPool: - lPool := entry.Data.MustLiquidityPool() - body = LedgerKeyLiquidityPool{ - LiquidityPoolId: lPool.LiquidityPoolId, - } - default: - panic(fmt.Errorf("Unknown entry type: %v", entry.Data.Type)) - } - - ret, err := NewLedgerKey(entry.Data.Type, body) - if err != nil { - panic(err) - } - - return ret +func (entry *LedgerEntry) LedgerKey() (LedgerKey, error) { + return entry.Data.LedgerKey() } // SponsoringID return SponsorshipDescriptor for a given ledger entry @@ -158,3 +113,73 @@ func (entry *LedgerEntry) Normalize() *LedgerEntry { return entry } + +func (data *LedgerEntryData) SetContractData(entry *ContractDataEntry) error { + *data = LedgerEntryData{ + Type: LedgerEntryTypeContractData, + ContractData: entry, + } + return nil +} + +func (data *LedgerEntryData) SetContractCode(entry *ContractCodeEntry) error { + *data = LedgerEntryData{ + Type: LedgerEntryTypeContractCode, + ContractCode: entry, + } + return nil +} + +// LedgerKey implements the `Keyer` interface +func (data *LedgerEntryData) LedgerKey() (LedgerKey, error) { + var key LedgerKey + switch data.Type { + case LedgerEntryTypeAccount: + if err := key.SetAccount(data.Account.AccountId); err != nil { + return key, err + } + case LedgerEntryTypeTrustline: + if err := key.SetTrustline(data.TrustLine.AccountId, data.TrustLine.Asset); err != nil { + return key, err + } + case LedgerEntryTypeContractData: + if err := key.SetContractData( + data.ContractData.Contract, + data.ContractData.Key, + data.ContractData.Durability); err != nil { + return key, err + } + case LedgerEntryTypeContractCode: + if err := key.SetContractCode(data.ContractCode.Hash); err != nil { + return key, err + } + case LedgerEntryTypeData: + if err := key.SetData(data.Data.AccountId, string(data.Data.DataName)); err != nil { + return key, err + } + case LedgerEntryTypeOffer: + if err := key.SetOffer(data.Offer.SellerId, uint64(data.Offer.OfferId)); err != nil { + return key, err + } + case LedgerEntryTypeLiquidityPool: + if err := key.SetLiquidityPool(data.LiquidityPool.LiquidityPoolId); err != nil { + return key, err + } + case LedgerEntryTypeClaimableBalance: + if err := key.SetClaimableBalance(data.ClaimableBalance.BalanceId); err != nil { + return key, err + } + case LedgerEntryTypeConfigSetting: + if err := key.SetConfigSetting(data.ConfigSetting.ConfigSettingId); err != nil { + return key, err + } + case LedgerEntryTypeTtl: + if err := key.SetTtl(data.Ttl.KeyHash); err != nil { + return key, err + } + default: + return key, fmt.Errorf("unknown ledger entry type %d", data.Type) + } + + return key, nil +} diff --git a/xdr/ledger_entry_change.go b/xdr/ledger_entry_change.go index 6330385871..fe371c84a2 100644 --- a/xdr/ledger_entry_change.go +++ b/xdr/ledger_entry_change.go @@ -6,19 +6,20 @@ import ( ) // EntryType is a helper to get at the entry type for a change. -func (change *LedgerEntryChange) EntryType() LedgerEntryType { - return change.LedgerKey().Type +func (change *LedgerEntryChange) EntryType() (LedgerEntryType, error) { + key, err := change.LedgerKey() + return key.Type, err } // LedgerKey returns the key for the ledger entry that was changed -// in `change`. -func (change *LedgerEntryChange) LedgerKey() LedgerKey { +// in `change`. LedgerKey implements `Keyer` +func (change *LedgerEntryChange) LedgerKey() (LedgerKey, error) { switch change.Type { case LedgerEntryChangeTypeLedgerEntryCreated: change := change.MustCreated() return change.LedgerKey() case LedgerEntryChangeTypeLedgerEntryRemoved: - return change.MustRemoved() + return change.MustRemoved(), nil case LedgerEntryChangeTypeLedgerEntryUpdated: change := change.MustUpdated() return change.LedgerKey() @@ -26,7 +27,7 @@ func (change *LedgerEntryChange) LedgerKey() LedgerKey { change := change.MustState() return change.LedgerKey() default: - panic(fmt.Errorf("Unknown change type: %v", change.Type)) + return LedgerKey{}, fmt.Errorf("unknown change type: %v", change.Type) } } diff --git a/xdr/ledger_entry_test.go b/xdr/ledger_entry_test.go index 765fedef0f..6ee1974cad 100644 --- a/xdr/ledger_entry_test.go +++ b/xdr/ledger_entry_test.go @@ -3,6 +3,9 @@ package xdr import ( "testing" + "github.com/stellar/go/gxdr" + "github.com/stellar/go/randxdr" + "github.com/stretchr/testify/assert" ) @@ -89,3 +92,34 @@ func TestNormalizedClaimableBalance(t *testing.T) { input.Normalize() assert.Equal(t, expectedOutput, input) } + +func TestLedgerKeyCoverage(t *testing.T) { + gen := randxdr.NewGenerator() + for i := 0; i < 10000; i++ { + ledgerEntry := LedgerEntry{} + shape := &gxdr.LedgerEntry{} + gen.Next( + shape, + []randxdr.Preset{}, + ) + assert.NoError(t, gxdr.Convert(shape, &ledgerEntry)) + _, err := ledgerEntry.LedgerKey() + assert.NoError(t, err) + } +} + +func TestLedgerEntryDataLedgerKeyCoverage(t *testing.T) { + gen := randxdr.NewGenerator() + for i := 0; i < 10000; i++ { + ledgerEntryData := LedgerEntryData{} + + shape := &gxdr.XdrAnon_LedgerEntry_Data{} + gen.Next( + shape, + []randxdr.Preset{}, + ) + assert.NoError(t, gxdr.Convert(shape, &ledgerEntryData)) + _, err := ledgerEntryData.LedgerKey() + assert.NoError(t, err) + } +} diff --git a/xdr/ledger_key.go b/xdr/ledger_key.go index 125c4c20b9..88ba800cf2 100644 --- a/xdr/ledger_key.go +++ b/xdr/ledger_key.go @@ -37,8 +37,28 @@ func (key *LedgerKey) Equals(other LedgerKey) bool { l := key.MustLiquidityPool() r := other.MustLiquidityPool() return l.LiquidityPoolId == r.LiquidityPoolId + case LedgerEntryTypeConfigSetting: + l := key.MustConfigSetting() + r := other.MustConfigSetting() + return l.ConfigSettingId == r.ConfigSettingId + case LedgerEntryTypeContractData: + l := key.MustContractData() + r := other.MustContractData() + return l.Contract.Equals(r.Contract) && l.Key.Equals(r.Key) && l.Durability == r.Durability + case LedgerEntryTypeContractCode: + l := key.MustContractCode() + r := other.MustContractCode() + return l.Hash == r.Hash + case LedgerEntryTypeClaimableBalance: + l := key.MustClaimableBalance() + r := other.MustClaimableBalance() + return l.BalanceId.MustV0() == r.BalanceId.MustV0() + case LedgerEntryTypeTtl: + l := key.MustTtl() + r := other.MustTtl() + return l.KeyHash == r.KeyHash default: - panic(fmt.Errorf("Unknown ledger key type: %v", key.Type)) + panic(fmt.Errorf("unknown ledger key type: %v", key.Type)) } } @@ -119,6 +139,77 @@ func (key *LedgerKey) SetLiquidityPool(poolID PoolId) error { return nil } +// SetContractData mutates `key` such that it represents the identity of a +// contract data entry. +func (key *LedgerKey) SetContractData(contract ScAddress, + keyVal ScVal, + keyDurability ContractDataDurability) error { + data := LedgerKeyContractData{ + Contract: contract, + Key: keyVal, + Durability: keyDurability, + } + nkey, err := NewLedgerKey(LedgerEntryTypeContractData, data) + if err != nil { + return err + } + + *key = nkey + return nil +} + +// SetContractCode mutates `key` such that it represents the identity of a +// contract code entry. +func (key *LedgerKey) SetContractCode(contractID Hash) error { + data := LedgerKeyContractCode{ + Hash: contractID, + } + nkey, err := NewLedgerKey(LedgerEntryTypeContractCode, data) + if err != nil { + return err + } + + *key = nkey + return nil +} + +// SetConfigSetting mutates `key` such that it represents the identity of a +// config setting entry. +func (key *LedgerKey) SetConfigSetting(configSettingID ConfigSettingId) error { + data := LedgerKeyConfigSetting{ + ConfigSettingId: configSettingID, + } + nkey, err := NewLedgerKey(LedgerEntryTypeConfigSetting, data) + if err != nil { + return err + } + + *key = nkey + return nil +} + +// SetTtl mutates `key` such that it represents the identity of an +// expiration entry. +func (key *LedgerKey) SetTtl(keyHash Hash) error { + data := LedgerKeyTtl{ + KeyHash: keyHash, + } + nkey, err := NewLedgerKey(LedgerEntryTypeTtl, data) + if err != nil { + return err + } + + *key = nkey + return nil +} + +// GetLedgerKeyFromData obtains a ledger key from LedgerEntryData +// +// deprecated: Use `LedgerEntryData.LedgerKey()` +func GetLedgerKeyFromData(data LedgerEntryData) (LedgerKey, error) { + return data.LedgerKey() +} + func (e *EncodingBuffer) ledgerKeyCompressEncodeTo(key LedgerKey) error { if err := e.xdrEncoderBuf.WriteByte(byte(key.Type)); err != nil { return err @@ -148,6 +239,28 @@ func (e *EncodingBuffer) ledgerKeyCompressEncodeTo(key LedgerKey) error { case LedgerEntryTypeLiquidityPool: _, err := e.xdrEncoderBuf.Write(key.LiquidityPool.LiquidityPoolId[:]) return err + case LedgerEntryTypeContractData: + // contract + if contractBytes, err := key.ContractData.Contract.MarshalBinary(); err != nil { + return err + } else { + if _, err := e.xdrEncoderBuf.Write(contractBytes[:]); err != nil { + return err + } + } + // key + if err := key.ContractData.Key.EncodeTo(e.encoder); err != nil { + return err + } + // durability + return e.xdrEncoderBuf.WriteByte(byte(key.ContractData.Durability)) + case LedgerEntryTypeContractCode: + _, err := e.xdrEncoderBuf.Write(key.ContractCode.Hash[:]) + return err + case LedgerEntryTypeConfigSetting: + return key.ConfigSetting.ConfigSettingId.EncodeTo(e.encoder) + case LedgerEntryTypeTtl: + return key.Ttl.KeyHash.EncodeTo(e.encoder) default: panic("Unknown type") } diff --git a/xdr/ledger_key_test.go b/xdr/ledger_key_test.go index 33f52f90b4..7762e40528 100644 --- a/xdr/ledger_key_test.go +++ b/xdr/ledger_key_test.go @@ -4,6 +4,9 @@ import ( "encoding/base64" "testing" + "github.com/stellar/go/gxdr" + "github.com/stellar/go/randxdr" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -38,3 +41,21 @@ func TestTrimRightZeros(t *testing.T) { require.Equal(t, []byte{0x0, 0x2}, trimRightZeros([]byte{0x0, 0x2, 0x0, 0x0})) require.Equal(t, []byte{0x0, 0x2, 0x0, 0x1}, trimRightZeros([]byte{0x0, 0x2, 0x0, 0x1, 0x0})) } + +func TestLedgerKeyEqualsCoverage(t *testing.T) { + gen := randxdr.NewGenerator() + for i := 0; i < 10000; i++ { + ledgerKey := LedgerKey{} + + shape := &gxdr.LedgerKey{} + gen.Next( + shape, + []randxdr.Preset{}, + ) + assert.NoError(t, gxdr.Convert(shape, &ledgerKey)) + + clonedLedgerKey := LedgerKey{} + assert.NoError(t, gxdr.Convert(shape, &clonedLedgerKey)) + assert.True(t, ledgerKey.Equals(clonedLedgerKey)) + } +} diff --git a/xdr/main.go b/xdr/main.go index 77618af842..44e8ced3ea 100644 --- a/xdr/main.go +++ b/xdr/main.go @@ -4,6 +4,7 @@ package xdr import ( "bytes" + _ "embed" "encoding/base64" "encoding/binary" "encoding/hex" @@ -12,12 +13,20 @@ import ( "strings" xdr "github.com/stellar/go-xdr/xdr3" + "github.com/stellar/go/support/errors" ) +// CommitHash is the commit hash that was used to generate the xdr in this folder. +// During the process of updating the XDR, the text file below is being updated. +// Then, during compile time, the file content are being embedded into the given string. +// +//go:embed xdr_commit_generated.txt +var CommitHash string + // Keyer represents a type that can be converted into a LedgerKey type Keyer interface { - LedgerKey() LedgerKey + LedgerKey() (LedgerKey, error) } var _ = LedgerEntry{} @@ -25,11 +34,13 @@ var _ = LedgerKey{} var OperationTypeToStringMap = operationTypeMap -func safeUnmarshalString(decoder func(reader io.Reader) io.Reader, data string, dest interface{}) error { +var LedgerEntryTypeMap = ledgerEntryTypeMap + +func safeUnmarshalString(decoder func(reader io.Reader) io.Reader, options xdr.DecodeOptions, data string, dest interface{}) error { count := &countWriter{} l := len(data) - _, err := Unmarshal(decoder(io.TeeReader(strings.NewReader(data), count)), dest) + _, err := UnmarshalWithOptions(decoder(io.TeeReader(strings.NewReader(data), count)), dest, options) if err != nil { return err } @@ -41,14 +52,23 @@ func safeUnmarshalString(decoder func(reader io.Reader) io.Reader, data string, return nil } +func decodeOptionsWithMaxInputLen(maxInputLen int) xdr.DecodeOptions { + options := xdr.DefaultDecodeOptions + options.MaxInputLen = maxInputLen + return options +} + // SafeUnmarshalBase64 first decodes the provided reader from base64 before // decoding the xdr into the provided destination. Also ensures that the reader // is fully consumed. func SafeUnmarshalBase64(data string, dest interface{}) error { + decodedLen := base64.StdEncoding.DecodedLen(len(data)) + options := decodeOptionsWithMaxInputLen(decodedLen) return safeUnmarshalString( func(r io.Reader) io.Reader { return base64.NewDecoder(base64.StdEncoding, r) }, + options, data, dest, ) @@ -58,11 +78,13 @@ func SafeUnmarshalBase64(data string, dest interface{}) error { // decoding the xdr into the provided destination. Also ensures that the reader // is fully consumed. func SafeUnmarshalHex(data string, dest interface{}) error { - return safeUnmarshalString(hex.NewDecoder, data, dest) + decodedLen := hex.DecodedLen(len(data)) + options := decodeOptionsWithMaxInputLen(decodedLen) + return safeUnmarshalString(hex.NewDecoder, options, data, dest) } // SafeUnmarshal decodes the provided reader into the destination and verifies -// that provided bytes are all consumed by the unmarshalling process. +// that provided bytes are all consumed by the unmarshaling process. func SafeUnmarshal(data []byte, dest interface{}) error { r := bytes.NewReader(data) n, err := Unmarshal(r, dest) @@ -101,7 +123,7 @@ func NewBytesDecoder() *BytesDecoder { func (d *BytesDecoder) DecodeBytes(v DecoderFrom, b []byte) (int, error) { d.reader.Reset(b) - return v.DecodeFrom(d.decoder) + return v.DecodeFrom(d.decoder, xdr.DecodeDefaultMaxDepth) } func marshalString(encoder func([]byte) string, v interface{}) (string, error) { @@ -156,7 +178,7 @@ func NewEncodingBuffer() *EncodingBuffer { // UnsafeMarshalBinary marshals the input XDR binary, returning // a slice pointing to the internal buffer. Handled with care this improveds // performance since copying is not required. -// Subsequent calls to marshalling methods will overwrite the returned buffer. +// Subsequent calls to marshaling methods will overwrite the returned buffer. func (e *EncodingBuffer) UnsafeMarshalBinary(encodable EncoderTo) ([]byte, error) { e.xdrEncoderBuf.Reset() if err := encodable.EncodeTo(e.encoder); err != nil { @@ -220,6 +242,18 @@ func (e *EncodingBuffer) LedgerKeyUnsafeMarshalBinaryCompress(key LedgerKey) ([] return e.xdrEncoderBuf.Bytes(), nil } +// GetBinaryCompressedLedgerKeyType gets the key type from the result of LedgerKeyUnsafeMarshalBinaryCompress +func GetBinaryCompressedLedgerKeyType(compressedKey []byte) (LedgerEntryType, error) { + if len(compressedKey) < 1 { + return 0, errors.New("empty compressed ledger key") + } + result := LedgerEntryType(compressedKey[0]) + if int(result) > len(ledgerEntryTypeMap)-1 { + return 0, fmt.Errorf("incorrect key type %d", result) + } + return result, nil +} + func (e *EncodingBuffer) MarshalBase64(encodable EncoderTo) (string, error) { b, err := e.UnsafeMarshalBase64(encodable) if err != nil { @@ -263,7 +297,7 @@ func MarshalFramed(w io.Writer, v interface{}) error { func ReadFrameLength(d *xdr.Decoder) (uint32, error) { frameLen, n, e := d.DecodeUint() if e != nil { - return 0, errors.Wrap(e, "unmarshalling XDR frame header") + return 0, errors.Wrap(e, "unmarshaling XDR frame header") } if n != 4 { return 0, errors.New("bad length of XDR frame header") diff --git a/xdr/main_test.go b/xdr/main_test.go index ab7c21195e..42d280f4b1 100644 --- a/xdr/main_test.go +++ b/xdr/main_test.go @@ -7,9 +7,13 @@ import ( "strings" "testing" + "github.com/stellar/go/gxdr" + "github.com/stellar/go/randxdr" + . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) // ExampleUnmarshal shows the lowest-level process to decode a base64 @@ -184,10 +188,43 @@ func TestLedgerKeyBinaryCompress(t *testing.T) { }, expectedOut: []byte{0x5, 0xca, 0xfe, 0xba, 0xbe, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, }, + { + key: LedgerKey{ + Type: LedgerEntryTypeConfigSetting, + ConfigSetting: &LedgerKeyConfigSetting{ + ConfigSettingId: ConfigSettingIdConfigSettingContractMaxSizeBytes, + }, + }, + expectedOut: []byte{0x8, 0x0, 0x0, 0x0, 0x0}, + }, } { b, err := e.LedgerKeyUnsafeMarshalBinaryCompress(tc.key) assert.NoError(t, err) assert.Equal(t, tc.expectedOut, b) } +} + +func TestLedgerKeyBinaryCompressCoverage(t *testing.T) { + e := NewEncodingBuffer() + gen := randxdr.NewGenerator() + for i := 0; i < 10000; i++ { + ledgerKey := LedgerKey{} + + shape := &gxdr.LedgerKey{} + gen.Next( + shape, + []randxdr.Preset{}, + ) + assert.NoError(t, gxdr.Convert(shape, &ledgerKey)) + + compressed, err := e.LedgerKeyUnsafeMarshalBinaryCompress(ledgerKey) + assert.NoError(t, err) + keyType, err := GetBinaryCompressedLedgerKeyType(compressed) + assert.NoError(t, err) + assert.Equal(t, ledgerKey.Type, keyType) + } +} +func TestCommitHashLength(t *testing.T) { + require.Equal(t, 40, len(CommitHash)) } diff --git a/xdr/price.go b/xdr/price.go index bfafb8bfc0..eed12c7339 100644 --- a/xdr/price.go +++ b/xdr/price.go @@ -4,7 +4,7 @@ import ( "math/big" ) -// String returns a string represenation of `p` +// String returns a string representation of `p` func (p Price) String() string { return big.NewRat(int64(p.N), int64(p.D)).FloatString(7) } diff --git a/xdr/scval.go b/xdr/scval.go new file mode 100644 index 0000000000..003efe885f --- /dev/null +++ b/xdr/scval.go @@ -0,0 +1,284 @@ +package xdr + +import ( + "bytes" + "encoding/hex" + "fmt" + "math/big" + "time" + + "github.com/stellar/go/strkey" +) + +func (address ScAddress) String() (string, error) { + var result string + var err error + + switch address.Type { + case ScAddressTypeScAddressTypeAccount: + pubkey := address.MustAccountId().Ed25519 + result, err = strkey.Encode(strkey.VersionByteAccountID, pubkey[:]) + case ScAddressTypeScAddressTypeContract: + contractID := *address.ContractId + result, err = strkey.Encode(strkey.VersionByteContract, contractID[:]) + default: + return "", fmt.Errorf("unfamiliar address type: %v", address.Type) + } + + if err != nil { + return "", err + } + + return result, nil +} + +func (s ContractExecutable) Equals(o ContractExecutable) bool { + if s.Type != o.Type { + return false + } + switch s.Type { + case ContractExecutableTypeContractExecutableStellarAsset: + return true + case ContractExecutableTypeContractExecutableWasm: + return s.MustWasmHash().Equals(o.MustWasmHash()) + default: + panic("unknown ScContractExecutable type: " + s.Type.String()) + } +} + +func (s ScError) Equals(o ScError) bool { + if s.Type != o.Type { + return false + } + switch s.Type { + case ScErrorTypeSceContract: + return *s.ContractCode == *o.ContractCode + case ScErrorTypeSceWasmVm, ScErrorTypeSceContext, ScErrorTypeSceStorage, ScErrorTypeSceObject, + ScErrorTypeSceCrypto, ScErrorTypeSceEvents, ScErrorTypeSceBudget, ScErrorTypeSceValue, ScErrorTypeSceAuth: + return *s.Code == *o.Code + default: + panic("unknown ScError type: " + s.Type.String()) + } +} + +func (s ScVal) Equals(o ScVal) bool { + if s.Type != o.Type { + return false + } + + switch s.Type { + case ScValTypeScvBool: + return s.MustB() == o.MustB() + case ScValTypeScvVoid: + return true + case ScValTypeScvError: + return s.MustError().Equals(o.MustError()) + case ScValTypeScvU32: + return s.MustU32() == o.MustU32() + case ScValTypeScvI32: + return s.MustI32() == o.MustI32() + case ScValTypeScvU64: + return s.MustU64() == o.MustU64() + case ScValTypeScvI64: + return s.MustI64() == o.MustI64() + case ScValTypeScvTimepoint: + return s.MustTimepoint() == o.MustTimepoint() + case ScValTypeScvDuration: + return s.MustDuration() == o.MustDuration() + case ScValTypeScvU128: + return s.MustU128() == o.MustU128() + case ScValTypeScvI128: + return s.MustI128() == o.MustI128() + case ScValTypeScvU256: + return s.MustU256() == o.MustU256() + case ScValTypeScvI256: + return s.MustI256() == o.MustI256() + case ScValTypeScvBytes: + return s.MustBytes().Equals(o.MustBytes()) + case ScValTypeScvString: + return s.MustStr() == o.MustStr() + case ScValTypeScvSymbol: + return s.MustSym() == o.MustSym() + case ScValTypeScvVec: + return s.MustVec().Equals(o.MustVec()) + case ScValTypeScvMap: + return s.MustMap().Equals(o.MustMap()) + case ScValTypeScvAddress: + return s.MustAddress().Equals(o.MustAddress()) + case ScValTypeScvContractInstance: + return s.MustInstance().Executable.Equals(o.MustInstance().Executable) && s.MustInstance().Storage.Equals(o.MustInstance().Storage) + case ScValTypeScvLedgerKeyContractInstance: + return true + case ScValTypeScvLedgerKeyNonce: + return s.MustNonceKey().Equals(o.MustNonceKey()) + + default: + panic("unknown ScVal type: " + s.Type.String()) + } +} + +func (s ScBytes) Equals(o ScBytes) bool { + return bytes.Equal([]byte(s), []byte(o)) +} + +func (s ScAddress) Equals(o ScAddress) bool { + if s.Type != o.Type { + return false + } + + switch s.Type { + case ScAddressTypeScAddressTypeAccount: + sAccountID := s.MustAccountId() + return sAccountID.Equals(o.MustAccountId()) + case ScAddressTypeScAddressTypeContract: + return s.MustContractId() == o.MustContractId() + default: + panic("unknown ScAddress type: " + s.Type.String()) + } +} + +// IsBool returns true if the given ScVal is a boolean +func (s ScVal) IsBool() bool { + return s.Type == ScValTypeScvBool +} + +func (s *ScVec) Equals(o *ScVec) bool { + if s == nil && o == nil { + return true + } + if s == nil || o == nil { + return false + } + if len(*s) != len(*o) { + return false + } + for i := range *s { + if !(*s)[i].Equals((*o)[i]) { + return false + } + } + return true +} + +func (s *ScMap) Equals(o *ScMap) bool { + if s == nil && o == nil { + return true + } + if s == nil || o == nil { + return false + } + if len(*s) != len(*o) { + return false + } + for i, entry := range *s { + if !entry.Equals((*o)[i]) { + return false + } + } + return true +} + +func (s ScMapEntry) Equals(o ScMapEntry) bool { + return s.Key.Equals(o.Key) && s.Val.Equals(o.Val) +} + +func (s ScNonceKey) Equals(o ScNonceKey) bool { + return s.Nonce == o.Nonce +} + +func bigIntFromParts(hi Int64, lowerParts ...Uint64) *big.Int { + result := new(big.Int).SetInt64(int64(hi)) + secondary := new(big.Int) + for _, part := range lowerParts { + result.Lsh(result, 64) + result.Or(result, secondary.SetUint64(uint64(part))) + } + return result +} + +func bigUIntFromParts(hi Uint64, lowerParts ...Uint64) *big.Int { + result := new(big.Int).SetUint64(uint64(hi)) + secondary := new(big.Int) + for _, part := range lowerParts { + result.Lsh(result, 64) + result.Or(result, secondary.SetUint64(uint64(part))) + } + return result +} + +func (s ScVal) String() string { + switch s.Type { + case ScValTypeScvBool: + return fmt.Sprintf("%t", *s.B) + case ScValTypeScvVoid: + return "(void)" + case ScValTypeScvError: + switch s.Error.Type { + case ScErrorTypeSceContract: + return fmt.Sprintf("%s(%d)", s.Error.Type, *s.Error.ContractCode) + case ScErrorTypeSceWasmVm, ScErrorTypeSceContext, ScErrorTypeSceStorage, ScErrorTypeSceObject, + ScErrorTypeSceCrypto, ScErrorTypeSceEvents, ScErrorTypeSceBudget, ScErrorTypeSceValue, ScErrorTypeSceAuth: + return fmt.Sprintf("%s(%s)", s.Error.Type, *s.Error.Code) + } + case ScValTypeScvU32: + return fmt.Sprintf("%d", *s.U32) + case ScValTypeScvI32: + return fmt.Sprintf("%d", *s.I32) + case ScValTypeScvU64: + return fmt.Sprintf("%d", *s.U64) + case ScValTypeScvI64: + return fmt.Sprintf("%d", *s.I64) + case ScValTypeScvTimepoint: + return time.Unix(int64(*s.Timepoint), 0).String() + case ScValTypeScvDuration: + return fmt.Sprintf("%d", *s.Duration) + case ScValTypeScvU128: + return bigUIntFromParts(s.U128.Hi, s.U128.Lo).String() + case ScValTypeScvI128: + return bigIntFromParts(s.I128.Hi, s.I128.Lo).String() + case ScValTypeScvU256: + return bigUIntFromParts(s.U256.HiHi, s.U256.HiLo, s.U256.LoHi, s.U256.LoLo).String() + case ScValTypeScvI256: + return bigIntFromParts(s.I256.HiHi, s.I256.HiLo, s.I256.LoHi, s.I256.LoLo).String() + case ScValTypeScvBytes: + return hex.EncodeToString(*s.Bytes) + case ScValTypeScvString: + return string(*s.Str) + case ScValTypeScvSymbol: + return string(*s.Sym) + case ScValTypeScvVec: + if *s.Vec == nil { + return "nil" + } + return fmt.Sprintf("%s", **s.Vec) + case ScValTypeScvMap: + if *s.Map == nil { + return "nil" + } + return fmt.Sprintf("%v", **s.Map) + case ScValTypeScvAddress: + str, err := s.Address.String() + if err != nil { + return err.Error() + } + return str + case ScValTypeScvContractInstance: + result := "" + switch s.Instance.Executable.Type { + case ContractExecutableTypeContractExecutableStellarAsset: + result = "(StellarAssetContract)" + case ContractExecutableTypeContractExecutableWasm: + result = hex.EncodeToString(s.Instance.Executable.WasmHash[:]) + } + if s.Instance.Storage != nil && len(*s.Instance.Storage) > 0 { + result += fmt.Sprintf(": %v", *s.Instance.Storage) + } + return result + case ScValTypeScvLedgerKeyContractInstance: + return "(LedgerKeyContractInstance)" + case ScValTypeScvLedgerKeyNonce: + return fmt.Sprintf("%X", *s.NonceKey) + } + + return "unknown" +} diff --git a/xdr/scval_test.go b/xdr/scval_test.go new file mode 100644 index 0000000000..8bfa97deb3 --- /dev/null +++ b/xdr/scval_test.go @@ -0,0 +1,48 @@ +package xdr + +import ( + "testing" + + "github.com/stretchr/testify/require" + + "github.com/stellar/go/gxdr" + "github.com/stellar/go/randxdr" +) + +func TestScValEqualsCoverage(t *testing.T) { + gen := randxdr.NewGenerator() + for i := 0; i < 30000; i++ { + scVal := ScVal{} + + shape := &gxdr.SCVal{} + gen.Next( + shape, + []randxdr.Preset{}, + ) + require.NoError(t, gxdr.Convert(shape, &scVal)) + + clonedScVal := ScVal{} + require.NoError(t, gxdr.Convert(shape, &clonedScVal)) + require.True(t, scVal.Equals(clonedScVal), "scVal: %#v, clonedScVal: %#v", scVal, clonedScVal) + } +} + +func TestScValStringCoverage(t *testing.T) { + gen := randxdr.NewGenerator() + for i := 0; i < 30000; i++ { + scVal := ScVal{} + + shape := &gxdr.SCVal{} + gen.Next( + shape, + []randxdr.Preset{}, + ) + require.NoError(t, gxdr.Convert(shape, &scVal)) + + var str string + require.NotPanics(t, func() { + str = scVal.String() + }) + require.NotEqual(t, str, "unknown") + } +} diff --git a/xdr/transaction_meta.go b/xdr/transaction_meta.go index 0f0c130c63..3fee38ae93 100644 --- a/xdr/transaction_meta.go +++ b/xdr/transaction_meta.go @@ -10,6 +10,8 @@ func (transactionMeta *TransactionMeta) OperationsMeta() []OperationMeta { return transactionMeta.MustV1().Operations case 2: return transactionMeta.MustV2().Operations + case 3: + return transactionMeta.MustV3().Operations default: panic("Unsupported TransactionMeta version") } diff --git a/xdr/transaction_result.go b/xdr/transaction_result.go index 77abed4ddf..fd548b414e 100644 --- a/xdr/transaction_result.go +++ b/xdr/transaction_result.go @@ -30,7 +30,13 @@ func (r TransactionResultPair) OperationResults() ([]OperationResult, bool) { // InnerHash returns the hash of the inner transaction. // This function can only be called on fee bump transactions. func (r TransactionResultPair) InnerHash() Hash { - return r.Result.Result.MustInnerResultPair().TransactionHash + return r.Result.InnerHash() +} + +// InnerHash returns the hash of the inner transaction. +// This function can only be called on fee bump transactions. +func (r TransactionResult) InnerHash() Hash { + return r.Result.MustInnerResultPair().TransactionHash } // ExtractBalanceID will parse the operation result at `opIndex` within the diff --git a/xdr/uint256.go b/xdr/uint256.go new file mode 100644 index 0000000000..6543a49e7d --- /dev/null +++ b/xdr/uint256.go @@ -0,0 +1,22 @@ +package xdr + +import ( + "math/big" +) + +// String returns a display friendly form of the uint256 +func (u Uint256) String() string { + return new(big.Int).SetBytes(u[:]).String() +} + +func (s Uint256) Equals(o Uint256) bool { + if len(s) != len(o) { + return false + } + for i := 0; i < len(s); i++ { + if s[i] != o[i] { + return false + } + } + return true +} diff --git a/xdr/uint256_test.go b/xdr/uint256_test.go new file mode 100644 index 0000000000..4e8d8ab115 --- /dev/null +++ b/xdr/uint256_test.go @@ -0,0 +1,24 @@ +package xdr_test + +import ( + "testing" + + "github.com/stellar/go/xdr" + "github.com/stretchr/testify/assert" +) + +func TestUint256String(t *testing.T) { + assert.Equal(t, "0", xdr.Uint256{}.String()) + assert.Equal(t, "1", xdr.Uint256{ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1, + }.String()) + assert.Equal(t, "16909060", xdr.Uint256{ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 2, 3, 4, + }.String()) +} diff --git a/xdr/xdr_commit_generated.txt b/xdr/xdr_commit_generated.txt new file mode 100644 index 0000000000..9746cc5569 --- /dev/null +++ b/xdr/xdr_commit_generated.txt @@ -0,0 +1 @@ +bb54e505f814386a3f45172e0b7e95b7badbe969 \ No newline at end of file diff --git a/xdr/xdr_generated.go b/xdr/xdr_generated.go index d39ffd82aa..e8f49981ff 100644 --- a/xdr/xdr_generated.go +++ b/xdr/xdr_generated.go @@ -4,12 +4,17 @@ // Package xdr is generated from: // // xdr/Stellar-SCP.x +// xdr/Stellar-contract-config-setting.x +// xdr/Stellar-contract-env-meta.x +// xdr/Stellar-contract-meta.x +// xdr/Stellar-contract-spec.x +// xdr/Stellar-contract.x +// xdr/Stellar-internal.x // xdr/Stellar-ledger-entries.x // xdr/Stellar-ledger.x // xdr/Stellar-overlay.x // xdr/Stellar-transaction.x // xdr/Stellar-types.x -// xdr/Stellar-lighthorizon.x // // DO NOT EDIT or your changes may be overwritten package xdr @@ -17,28 +22,52 @@ package xdr import ( "bytes" "encoding" + "errors" "fmt" "io" "github.com/stellar/go-xdr/xdr3" ) +// XdrFilesSHA256 is the SHA256 hashes of source files. +var XdrFilesSHA256 = map[string]string{ + "xdr/Stellar-SCP.x": "8f32b04d008f8bc33b8843d075e69837231a673691ee41d8b821ca229a6e802a", + "xdr/Stellar-contract-config-setting.x": "e466c4dfae1d5d181afbd990b91f26c5d8ed84a7fa987875f8d643cf97e34a77", + "xdr/Stellar-contract-env-meta.x": "928a30de814ee589bc1d2aadd8dd81c39f71b7e6f430f56974505ccb1f49654b", + "xdr/Stellar-contract-meta.x": "f01532c11ca044e19d9f9f16fe373e9af64835da473be556b9a807ee3319ae0d", + "xdr/Stellar-contract-spec.x": "c7ffa21d2e91afb8e666b33524d307955426ff553a486d670c29217ed9888d49", + "xdr/Stellar-contract.x": "7f665e4103e146a88fcdabce879aaaacd3bf9283feb194cc47ff986264c1e315", + "xdr/Stellar-internal.x": "227835866c1b2122d1eaf28839ba85ea7289d1cb681dda4ca619c2da3d71fe00", + "xdr/Stellar-ledger-entries.x": "4f8f2324f567a40065f54f696ea1428740f043ea4154f5986d9f499ad00ac333", + "xdr/Stellar-ledger.x": "2c842f3fe6e269498af5467f849cf6818554e90babc845f34c87cda471298d0f", + "xdr/Stellar-overlay.x": "de3957c58b96ae07968b3d3aebea84f83603e95322d1fa336360e13e3aba737a", + "xdr/Stellar-transaction.x": "0d2b35a331a540b48643925d0869857236eb2487c02d340ea32e365e784ea2b8", + "xdr/Stellar-types.x": "6e3b13f0d3e360b09fa5e2b0e55d43f4d974a769df66afb34e8aecbb329d3f15", +} + +var ErrMaxDecodingDepthReached = errors.New("maximum decoding depth reached") + type xdrType interface { xdrType() } type decoderFrom interface { - DecodeFrom(d *xdr.Decoder) (int, error) + DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) } // Unmarshal reads an xdr element from `r` into `v`. func Unmarshal(r io.Reader, v interface{}) (int, error) { + return UnmarshalWithOptions(r, v, xdr.DefaultDecodeOptions) +} + +// UnmarshalWithOptions works like Unmarshal but uses decoding options. +func UnmarshalWithOptions(r io.Reader, v interface{}, options xdr.DecodeOptions) (int, error) { if decodable, ok := v.(decoderFrom); ok { - d := xdr.NewDecoder(r) - return decodable.DecodeFrom(d) + d := xdr.NewDecoderWithOptions(r, options) + return decodable.DecodeFrom(d, options.MaxDepth) } // delegate to xdr package's Unmarshal - return xdr.Unmarshal(r, v) + return xdr.UnmarshalWithOptions(r, v, options) } // Marshal writes an xdr element `v` into `w`. @@ -73,13 +102,17 @@ func (s Value) EncodeTo(e *xdr.Encoder) error { var _ decoderFrom = (*Value)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *Value) DecodeFrom(d *xdr.Decoder) (int, error) { +func (s *Value) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding Value: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int (*s), nTmp, err = d.DecodeOpaque(0) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Value: %s", err) + return n, fmt.Errorf("decoding Value: %w", err) } return n, nil } @@ -95,8 +128,10 @@ func (s Value) MarshalBinary() ([]byte, error) { // UnmarshalBinary implements encoding.BinaryUnmarshaler. func (s *Value) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } @@ -105,8 +140,7 @@ var ( _ encoding.BinaryUnmarshaler = (*Value)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. +// xdrType signals that this type represents XDR values defined by this package. func (s Value) xdrType() {} var _ xdrType = (*Value)(nil) @@ -138,18 +172,22 @@ func (s *ScpBallot) EncodeTo(e *xdr.Encoder) error { var _ decoderFrom = (*ScpBallot)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *ScpBallot) DecodeFrom(d *xdr.Decoder) (int, error) { +func (s *ScpBallot) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding ScpBallot: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = s.Counter.DecodeFrom(d) + nTmp, err = s.Counter.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Uint32: %s", err) + return n, fmt.Errorf("decoding Uint32: %w", err) } - nTmp, err = s.Value.DecodeFrom(d) + nTmp, err = s.Value.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Value: %s", err) + return n, fmt.Errorf("decoding Value: %w", err) } return n, nil } @@ -165,8 +203,10 @@ func (s ScpBallot) MarshalBinary() ([]byte, error) { // UnmarshalBinary implements encoding.BinaryUnmarshaler. func (s *ScpBallot) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } @@ -175,8 +215,7 @@ var ( _ encoding.BinaryUnmarshaler = (*ScpBallot)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. +// xdrType signals that this type represents XDR values defined by this package. func (s ScpBallot) xdrType() {} var _ xdrType = (*ScpBallot)(nil) @@ -231,10 +270,14 @@ func (e ScpStatementType) EncodeTo(enc *xdr.Encoder) error { var _ decoderFrom = (*ScpStatementType)(nil) // DecodeFrom decodes this value using the Decoder. -func (e *ScpStatementType) DecodeFrom(d *xdr.Decoder) (int, error) { +func (e *ScpStatementType) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding ScpStatementType: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 v, n, err := d.DecodeInt() if err != nil { - return n, fmt.Errorf("decoding ScpStatementType: %s", err) + return n, fmt.Errorf("decoding ScpStatementType: %w", err) } if _, ok := scpStatementTypeMap[v]; !ok { return n, fmt.Errorf("'%d' is not a valid ScpStatementType enum value", v) @@ -254,8 +297,10 @@ func (s ScpStatementType) MarshalBinary() ([]byte, error) { // UnmarshalBinary implements encoding.BinaryUnmarshaler. func (s *ScpStatementType) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } @@ -264,8 +309,7 @@ var ( _ encoding.BinaryUnmarshaler = (*ScpStatementType)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. +// xdrType signals that this type represents XDR values defined by this package. func (s ScpStatementType) xdrType() {} var _ xdrType = (*ScpStatementType)(nil) @@ -312,44 +356,54 @@ func (s *ScpNomination) EncodeTo(e *xdr.Encoder) error { var _ decoderFrom = (*ScpNomination)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *ScpNomination) DecodeFrom(d *xdr.Decoder) (int, error) { +func (s *ScpNomination) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding ScpNomination: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = s.QuorumSetHash.DecodeFrom(d) + nTmp, err = s.QuorumSetHash.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Hash: %s", err) + return n, fmt.Errorf("decoding Hash: %w", err) } var l uint32 l, nTmp, err = d.DecodeUint() n += nTmp if err != nil { - return n, fmt.Errorf("decoding Value: %s", err) + return n, fmt.Errorf("decoding Value: %w", err) } s.Votes = nil if l > 0 { + if il, ok := d.InputLen(); ok && uint(il) < uint(l) { + return n, fmt.Errorf("decoding Value: length (%d) exceeds remaining input length (%d)", l, il) + } s.Votes = make([]Value, l) for i := uint32(0); i < l; i++ { - nTmp, err = s.Votes[i].DecodeFrom(d) + nTmp, err = s.Votes[i].DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Value: %s", err) + return n, fmt.Errorf("decoding Value: %w", err) } } } l, nTmp, err = d.DecodeUint() n += nTmp if err != nil { - return n, fmt.Errorf("decoding Value: %s", err) + return n, fmt.Errorf("decoding Value: %w", err) } s.Accepted = nil if l > 0 { + if il, ok := d.InputLen(); ok && uint(il) < uint(l) { + return n, fmt.Errorf("decoding Value: length (%d) exceeds remaining input length (%d)", l, il) + } s.Accepted = make([]Value, l) for i := uint32(0); i < l; i++ { - nTmp, err = s.Accepted[i].DecodeFrom(d) + nTmp, err = s.Accepted[i].DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Value: %s", err) + return n, fmt.Errorf("decoding Value: %w", err) } } } @@ -367,8 +421,10 @@ func (s ScpNomination) MarshalBinary() ([]byte, error) { // UnmarshalBinary implements encoding.BinaryUnmarshaler. func (s *ScpNomination) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } @@ -377,8 +433,7 @@ var ( _ encoding.BinaryUnmarshaler = (*ScpNomination)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. +// xdrType signals that this type represents XDR values defined by this package. func (s ScpNomination) xdrType() {} var _ xdrType = (*ScpNomination)(nil) @@ -440,57 +495,61 @@ func (s *ScpStatementPrepare) EncodeTo(e *xdr.Encoder) error { var _ decoderFrom = (*ScpStatementPrepare)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *ScpStatementPrepare) DecodeFrom(d *xdr.Decoder) (int, error) { +func (s *ScpStatementPrepare) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding ScpStatementPrepare: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = s.QuorumSetHash.DecodeFrom(d) + nTmp, err = s.QuorumSetHash.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Hash: %s", err) + return n, fmt.Errorf("decoding Hash: %w", err) } - nTmp, err = s.Ballot.DecodeFrom(d) + nTmp, err = s.Ballot.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding ScpBallot: %s", err) + return n, fmt.Errorf("decoding ScpBallot: %w", err) } var b bool b, nTmp, err = d.DecodeBool() n += nTmp if err != nil { - return n, fmt.Errorf("decoding ScpBallot: %s", err) + return n, fmt.Errorf("decoding ScpBallot: %w", err) } s.Prepared = nil if b { s.Prepared = new(ScpBallot) - nTmp, err = s.Prepared.DecodeFrom(d) + nTmp, err = s.Prepared.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding ScpBallot: %s", err) + return n, fmt.Errorf("decoding ScpBallot: %w", err) } } b, nTmp, err = d.DecodeBool() n += nTmp if err != nil { - return n, fmt.Errorf("decoding ScpBallot: %s", err) + return n, fmt.Errorf("decoding ScpBallot: %w", err) } s.PreparedPrime = nil if b { s.PreparedPrime = new(ScpBallot) - nTmp, err = s.PreparedPrime.DecodeFrom(d) + nTmp, err = s.PreparedPrime.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding ScpBallot: %s", err) + return n, fmt.Errorf("decoding ScpBallot: %w", err) } } - nTmp, err = s.NC.DecodeFrom(d) + nTmp, err = s.NC.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Uint32: %s", err) + return n, fmt.Errorf("decoding Uint32: %w", err) } - nTmp, err = s.NH.DecodeFrom(d) + nTmp, err = s.NH.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Uint32: %s", err) + return n, fmt.Errorf("decoding Uint32: %w", err) } return n, nil } @@ -506,8 +565,10 @@ func (s ScpStatementPrepare) MarshalBinary() ([]byte, error) { // UnmarshalBinary implements encoding.BinaryUnmarshaler. func (s *ScpStatementPrepare) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } @@ -516,8 +577,7 @@ var ( _ encoding.BinaryUnmarshaler = (*ScpStatementPrepare)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. +// xdrType signals that this type represents XDR values defined by this package. func (s ScpStatementPrepare) xdrType() {} var _ xdrType = (*ScpStatementPrepare)(nil) @@ -564,33 +624,37 @@ func (s *ScpStatementConfirm) EncodeTo(e *xdr.Encoder) error { var _ decoderFrom = (*ScpStatementConfirm)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *ScpStatementConfirm) DecodeFrom(d *xdr.Decoder) (int, error) { +func (s *ScpStatementConfirm) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding ScpStatementConfirm: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = s.Ballot.DecodeFrom(d) + nTmp, err = s.Ballot.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding ScpBallot: %s", err) + return n, fmt.Errorf("decoding ScpBallot: %w", err) } - nTmp, err = s.NPrepared.DecodeFrom(d) + nTmp, err = s.NPrepared.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Uint32: %s", err) + return n, fmt.Errorf("decoding Uint32: %w", err) } - nTmp, err = s.NCommit.DecodeFrom(d) + nTmp, err = s.NCommit.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Uint32: %s", err) + return n, fmt.Errorf("decoding Uint32: %w", err) } - nTmp, err = s.NH.DecodeFrom(d) + nTmp, err = s.NH.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Uint32: %s", err) + return n, fmt.Errorf("decoding Uint32: %w", err) } - nTmp, err = s.QuorumSetHash.DecodeFrom(d) + nTmp, err = s.QuorumSetHash.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Hash: %s", err) + return n, fmt.Errorf("decoding Hash: %w", err) } return n, nil } @@ -606,8 +670,10 @@ func (s ScpStatementConfirm) MarshalBinary() ([]byte, error) { // UnmarshalBinary implements encoding.BinaryUnmarshaler. func (s *ScpStatementConfirm) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } @@ -616,8 +682,7 @@ var ( _ encoding.BinaryUnmarshaler = (*ScpStatementConfirm)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. +// xdrType signals that this type represents XDR values defined by this package. func (s ScpStatementConfirm) xdrType() {} var _ xdrType = (*ScpStatementConfirm)(nil) @@ -654,23 +719,27 @@ func (s *ScpStatementExternalize) EncodeTo(e *xdr.Encoder) error { var _ decoderFrom = (*ScpStatementExternalize)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *ScpStatementExternalize) DecodeFrom(d *xdr.Decoder) (int, error) { +func (s *ScpStatementExternalize) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding ScpStatementExternalize: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = s.Commit.DecodeFrom(d) + nTmp, err = s.Commit.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding ScpBallot: %s", err) + return n, fmt.Errorf("decoding ScpBallot: %w", err) } - nTmp, err = s.NH.DecodeFrom(d) + nTmp, err = s.NH.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Uint32: %s", err) + return n, fmt.Errorf("decoding Uint32: %w", err) } - nTmp, err = s.CommitQuorumSetHash.DecodeFrom(d) + nTmp, err = s.CommitQuorumSetHash.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Hash: %s", err) + return n, fmt.Errorf("decoding Hash: %w", err) } return n, nil } @@ -686,8 +755,10 @@ func (s ScpStatementExternalize) MarshalBinary() ([]byte, error) { // UnmarshalBinary implements encoding.BinaryUnmarshaler. func (s *ScpStatementExternalize) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } @@ -696,8 +767,7 @@ var ( _ encoding.BinaryUnmarshaler = (*ScpStatementExternalize)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. +// xdrType signals that this type represents XDR values defined by this package. func (s ScpStatementExternalize) xdrType() {} var _ xdrType = (*ScpStatementExternalize)(nil) @@ -772,28 +842,28 @@ func NewScpStatementPledges(aType ScpStatementType, value interface{}) (result S case ScpStatementTypeScpStPrepare: tv, ok := value.(ScpStatementPrepare) if !ok { - err = fmt.Errorf("invalid value, must be ScpStatementPrepare") + err = errors.New("invalid value, must be ScpStatementPrepare") return } result.Prepare = &tv case ScpStatementTypeScpStConfirm: tv, ok := value.(ScpStatementConfirm) if !ok { - err = fmt.Errorf("invalid value, must be ScpStatementConfirm") + err = errors.New("invalid value, must be ScpStatementConfirm") return } result.Confirm = &tv case ScpStatementTypeScpStExternalize: tv, ok := value.(ScpStatementExternalize) if !ok { - err = fmt.Errorf("invalid value, must be ScpStatementExternalize") + err = errors.New("invalid value, must be ScpStatementExternalize") return } result.Externalize = &tv case ScpStatementTypeScpStNominate: tv, ok := value.(ScpNomination) if !ok { - err = fmt.Errorf("invalid value, must be ScpNomination") + err = errors.New("invalid value, must be ScpNomination") return } result.Nominate = &tv @@ -935,45 +1005,49 @@ func (u ScpStatementPledges) EncodeTo(e *xdr.Encoder) error { var _ decoderFrom = (*ScpStatementPledges)(nil) // DecodeFrom decodes this value using the Decoder. -func (u *ScpStatementPledges) DecodeFrom(d *xdr.Decoder) (int, error) { +func (u *ScpStatementPledges) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding ScpStatementPledges: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = u.Type.DecodeFrom(d) + nTmp, err = u.Type.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding ScpStatementType: %s", err) + return n, fmt.Errorf("decoding ScpStatementType: %w", err) } switch ScpStatementType(u.Type) { case ScpStatementTypeScpStPrepare: u.Prepare = new(ScpStatementPrepare) - nTmp, err = (*u.Prepare).DecodeFrom(d) + nTmp, err = (*u.Prepare).DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding ScpStatementPrepare: %s", err) + return n, fmt.Errorf("decoding ScpStatementPrepare: %w", err) } return n, nil case ScpStatementTypeScpStConfirm: u.Confirm = new(ScpStatementConfirm) - nTmp, err = (*u.Confirm).DecodeFrom(d) + nTmp, err = (*u.Confirm).DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding ScpStatementConfirm: %s", err) + return n, fmt.Errorf("decoding ScpStatementConfirm: %w", err) } return n, nil case ScpStatementTypeScpStExternalize: u.Externalize = new(ScpStatementExternalize) - nTmp, err = (*u.Externalize).DecodeFrom(d) + nTmp, err = (*u.Externalize).DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding ScpStatementExternalize: %s", err) + return n, fmt.Errorf("decoding ScpStatementExternalize: %w", err) } return n, nil case ScpStatementTypeScpStNominate: u.Nominate = new(ScpNomination) - nTmp, err = (*u.Nominate).DecodeFrom(d) + nTmp, err = (*u.Nominate).DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding ScpNomination: %s", err) + return n, fmt.Errorf("decoding ScpNomination: %w", err) } return n, nil } @@ -991,8 +1065,10 @@ func (s ScpStatementPledges) MarshalBinary() ([]byte, error) { // UnmarshalBinary implements encoding.BinaryUnmarshaler. func (s *ScpStatementPledges) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } @@ -1001,8 +1077,7 @@ var ( _ encoding.BinaryUnmarshaler = (*ScpStatementPledges)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. +// xdrType signals that this type represents XDR values defined by this package. func (s ScpStatementPledges) xdrType() {} var _ xdrType = (*ScpStatementPledges)(nil) @@ -1071,23 +1146,27 @@ func (s *ScpStatement) EncodeTo(e *xdr.Encoder) error { var _ decoderFrom = (*ScpStatement)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *ScpStatement) DecodeFrom(d *xdr.Decoder) (int, error) { +func (s *ScpStatement) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding ScpStatement: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = s.NodeId.DecodeFrom(d) + nTmp, err = s.NodeId.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding NodeId: %s", err) + return n, fmt.Errorf("decoding NodeId: %w", err) } - nTmp, err = s.SlotIndex.DecodeFrom(d) + nTmp, err = s.SlotIndex.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Uint64: %s", err) + return n, fmt.Errorf("decoding Uint64: %w", err) } - nTmp, err = s.Pledges.DecodeFrom(d) + nTmp, err = s.Pledges.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding ScpStatementPledges: %s", err) + return n, fmt.Errorf("decoding ScpStatementPledges: %w", err) } return n, nil } @@ -1103,8 +1182,10 @@ func (s ScpStatement) MarshalBinary() ([]byte, error) { // UnmarshalBinary implements encoding.BinaryUnmarshaler. func (s *ScpStatement) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } @@ -1113,8 +1194,7 @@ var ( _ encoding.BinaryUnmarshaler = (*ScpStatement)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. +// xdrType signals that this type represents XDR values defined by this package. func (s ScpStatement) xdrType() {} var _ xdrType = (*ScpStatement)(nil) @@ -1146,18 +1226,22 @@ func (s *ScpEnvelope) EncodeTo(e *xdr.Encoder) error { var _ decoderFrom = (*ScpEnvelope)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *ScpEnvelope) DecodeFrom(d *xdr.Decoder) (int, error) { +func (s *ScpEnvelope) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding ScpEnvelope: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = s.Statement.DecodeFrom(d) + nTmp, err = s.Statement.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding ScpStatement: %s", err) + return n, fmt.Errorf("decoding ScpStatement: %w", err) } - nTmp, err = s.Signature.DecodeFrom(d) + nTmp, err = s.Signature.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Signature: %s", err) + return n, fmt.Errorf("decoding Signature: %w", err) } return n, nil } @@ -1173,8 +1257,10 @@ func (s ScpEnvelope) MarshalBinary() ([]byte, error) { // UnmarshalBinary implements encoding.BinaryUnmarshaler. func (s *ScpEnvelope) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } @@ -1183,8 +1269,7 @@ var ( _ encoding.BinaryUnmarshaler = (*ScpEnvelope)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. +// xdrType signals that this type represents XDR values defined by this package. func (s ScpEnvelope) xdrType() {} var _ xdrType = (*ScpEnvelope)(nil) @@ -1231,44 +1316,54 @@ func (s *ScpQuorumSet) EncodeTo(e *xdr.Encoder) error { var _ decoderFrom = (*ScpQuorumSet)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *ScpQuorumSet) DecodeFrom(d *xdr.Decoder) (int, error) { +func (s *ScpQuorumSet) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding ScpQuorumSet: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = s.Threshold.DecodeFrom(d) + nTmp, err = s.Threshold.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Uint32: %s", err) + return n, fmt.Errorf("decoding Uint32: %w", err) } var l uint32 l, nTmp, err = d.DecodeUint() n += nTmp if err != nil { - return n, fmt.Errorf("decoding NodeId: %s", err) + return n, fmt.Errorf("decoding NodeId: %w", err) } s.Validators = nil if l > 0 { + if il, ok := d.InputLen(); ok && uint(il) < uint(l) { + return n, fmt.Errorf("decoding NodeId: length (%d) exceeds remaining input length (%d)", l, il) + } s.Validators = make([]NodeId, l) for i := uint32(0); i < l; i++ { - nTmp, err = s.Validators[i].DecodeFrom(d) + nTmp, err = s.Validators[i].DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding NodeId: %s", err) + return n, fmt.Errorf("decoding NodeId: %w", err) } } } l, nTmp, err = d.DecodeUint() n += nTmp if err != nil { - return n, fmt.Errorf("decoding ScpQuorumSet: %s", err) + return n, fmt.Errorf("decoding ScpQuorumSet: %w", err) } s.InnerSets = nil if l > 0 { + if il, ok := d.InputLen(); ok && uint(il) < uint(l) { + return n, fmt.Errorf("decoding ScpQuorumSet: length (%d) exceeds remaining input length (%d)", l, il) + } s.InnerSets = make([]ScpQuorumSet, l) for i := uint32(0); i < l; i++ { - nTmp, err = s.InnerSets[i].DecodeFrom(d) + nTmp, err = s.InnerSets[i].DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding ScpQuorumSet: %s", err) + return n, fmt.Errorf("decoding ScpQuorumSet: %w", err) } } } @@ -1286,8 +1381,10 @@ func (s ScpQuorumSet) MarshalBinary() ([]byte, error) { // UnmarshalBinary implements encoding.BinaryUnmarshaler. func (s *ScpQuorumSet) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } @@ -1296,98 +1393,11 @@ var ( _ encoding.BinaryUnmarshaler = (*ScpQuorumSet)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. +// xdrType signals that this type represents XDR values defined by this package. func (s ScpQuorumSet) xdrType() {} var _ xdrType = (*ScpQuorumSet)(nil) -// AccountId is an XDR Typedef defines as: -// -// typedef PublicKey AccountID; -type AccountId PublicKey - -// SwitchFieldName returns the field name in which this union's -// discriminant is stored -func (u AccountId) SwitchFieldName() string { - return PublicKey(u).SwitchFieldName() -} - -// ArmForSwitch returns which field name should be used for storing -// the value for an instance of PublicKey -func (u AccountId) ArmForSwitch(sw int32) (string, bool) { - return PublicKey(u).ArmForSwitch(sw) -} - -// NewAccountId creates a new AccountId. -func NewAccountId(aType PublicKeyType, value interface{}) (result AccountId, err error) { - u, err := NewPublicKey(aType, value) - result = AccountId(u) - return -} - -// MustEd25519 retrieves the Ed25519 value from the union, -// panicing if the value is not set. -func (u AccountId) MustEd25519() Uint256 { - return PublicKey(u).MustEd25519() -} - -// GetEd25519 retrieves the Ed25519 value from the union, -// returning ok if the union's switch indicated the value is valid. -func (u AccountId) GetEd25519() (result Uint256, ok bool) { - return PublicKey(u).GetEd25519() -} - -// EncodeTo encodes this value using the Encoder. -func (s AccountId) EncodeTo(e *xdr.Encoder) error { - var err error - if err = PublicKey(s).EncodeTo(e); err != nil { - return err - } - return nil -} - -var _ decoderFrom = (*AccountId)(nil) - -// DecodeFrom decodes this value using the Decoder. -func (s *AccountId) DecodeFrom(d *xdr.Decoder) (int, error) { - var err error - var n, nTmp int - nTmp, err = (*PublicKey)(s).DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding PublicKey: %s", err) - } - return n, nil -} - -// MarshalBinary implements encoding.BinaryMarshaler. -func (s AccountId) MarshalBinary() ([]byte, error) { - b := bytes.Buffer{} - e := xdr.NewEncoder(&b) - err := s.EncodeTo(e) - return b.Bytes(), err -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *AccountId) UnmarshalBinary(inp []byte) error { - r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) - return err -} - -var ( - _ encoding.BinaryMarshaler = (*AccountId)(nil) - _ encoding.BinaryUnmarshaler = (*AccountId)(nil) -) - -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s AccountId) xdrType() {} - -var _ xdrType = (*AccountId)(nil) - // Thresholds is an XDR Typedef defines as: // // typedef opaque Thresholds[4]; @@ -1410,13 +1420,17 @@ func (s *Thresholds) EncodeTo(e *xdr.Encoder) error { var _ decoderFrom = (*Thresholds)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *Thresholds) DecodeFrom(d *xdr.Decoder) (int, error) { +func (s *Thresholds) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding Thresholds: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int nTmp, err = d.DecodeFixedOpaqueInplace(s[:]) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Thresholds: %s", err) + return n, fmt.Errorf("decoding Thresholds: %w", err) } return n, nil } @@ -1432,8 +1446,10 @@ func (s Thresholds) MarshalBinary() ([]byte, error) { // UnmarshalBinary implements encoding.BinaryUnmarshaler. func (s *Thresholds) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } @@ -1442,8 +1458,7 @@ var ( _ encoding.BinaryUnmarshaler = (*Thresholds)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. +// xdrType signals that this type represents XDR values defined by this package. func (s Thresholds) xdrType() {} var _ xdrType = (*Thresholds)(nil) @@ -1470,14 +1485,18 @@ func (s String32) EncodeTo(e *xdr.Encoder) error { var _ decoderFrom = (*String32)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *String32) DecodeFrom(d *xdr.Decoder) (int, error) { +func (s *String32) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding String32: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int var v string v, nTmp, err = d.DecodeString(32) n += nTmp if err != nil { - return n, fmt.Errorf("decoding String32: %s", err) + return n, fmt.Errorf("decoding String32: %w", err) } *s = String32(v) return n, nil @@ -1494,8 +1513,10 @@ func (s String32) MarshalBinary() ([]byte, error) { // UnmarshalBinary implements encoding.BinaryUnmarshaler. func (s *String32) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } @@ -1504,8 +1525,7 @@ var ( _ encoding.BinaryUnmarshaler = (*String32)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. +// xdrType signals that this type represents XDR values defined by this package. func (s String32) xdrType() {} var _ xdrType = (*String32)(nil) @@ -1532,14 +1552,18 @@ func (s String64) EncodeTo(e *xdr.Encoder) error { var _ decoderFrom = (*String64)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *String64) DecodeFrom(d *xdr.Decoder) (int, error) { +func (s *String64) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding String64: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int var v string v, nTmp, err = d.DecodeString(64) n += nTmp if err != nil { - return n, fmt.Errorf("decoding String64: %s", err) + return n, fmt.Errorf("decoding String64: %w", err) } *s = String64(v) return n, nil @@ -1556,8 +1580,10 @@ func (s String64) MarshalBinary() ([]byte, error) { // UnmarshalBinary implements encoding.BinaryUnmarshaler. func (s *String64) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } @@ -1566,8 +1592,7 @@ var ( _ encoding.BinaryUnmarshaler = (*String64)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. +// xdrType signals that this type represents XDR values defined by this package. func (s String64) xdrType() {} var _ xdrType = (*String64)(nil) @@ -1589,13 +1614,17 @@ func (s SequenceNumber) EncodeTo(e *xdr.Encoder) error { var _ decoderFrom = (*SequenceNumber)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *SequenceNumber) DecodeFrom(d *xdr.Decoder) (int, error) { +func (s *SequenceNumber) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding SequenceNumber: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = (*Int64)(s).DecodeFrom(d) + nTmp, err = (*Int64)(s).DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Int64: %s", err) + return n, fmt.Errorf("decoding Int64: %w", err) } return n, nil } @@ -1611,8 +1640,10 @@ func (s SequenceNumber) MarshalBinary() ([]byte, error) { // UnmarshalBinary implements encoding.BinaryUnmarshaler. func (s *SequenceNumber) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } @@ -1621,122 +1652,11 @@ var ( _ encoding.BinaryUnmarshaler = (*SequenceNumber)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. +// xdrType signals that this type represents XDR values defined by this package. func (s SequenceNumber) xdrType() {} var _ xdrType = (*SequenceNumber)(nil) -// TimePoint is an XDR Typedef defines as: -// -// typedef uint64 TimePoint; -type TimePoint Uint64 - -// EncodeTo encodes this value using the Encoder. -func (s TimePoint) EncodeTo(e *xdr.Encoder) error { - var err error - if err = Uint64(s).EncodeTo(e); err != nil { - return err - } - return nil -} - -var _ decoderFrom = (*TimePoint)(nil) - -// DecodeFrom decodes this value using the Decoder. -func (s *TimePoint) DecodeFrom(d *xdr.Decoder) (int, error) { - var err error - var n, nTmp int - nTmp, err = (*Uint64)(s).DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Uint64: %s", err) - } - return n, nil -} - -// MarshalBinary implements encoding.BinaryMarshaler. -func (s TimePoint) MarshalBinary() ([]byte, error) { - b := bytes.Buffer{} - e := xdr.NewEncoder(&b) - err := s.EncodeTo(e) - return b.Bytes(), err -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *TimePoint) UnmarshalBinary(inp []byte) error { - r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) - return err -} - -var ( - _ encoding.BinaryMarshaler = (*TimePoint)(nil) - _ encoding.BinaryUnmarshaler = (*TimePoint)(nil) -) - -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s TimePoint) xdrType() {} - -var _ xdrType = (*TimePoint)(nil) - -// Duration is an XDR Typedef defines as: -// -// typedef uint64 Duration; -type Duration Uint64 - -// EncodeTo encodes this value using the Encoder. -func (s Duration) EncodeTo(e *xdr.Encoder) error { - var err error - if err = Uint64(s).EncodeTo(e); err != nil { - return err - } - return nil -} - -var _ decoderFrom = (*Duration)(nil) - -// DecodeFrom decodes this value using the Decoder. -func (s *Duration) DecodeFrom(d *xdr.Decoder) (int, error) { - var err error - var n, nTmp int - nTmp, err = (*Uint64)(s).DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Uint64: %s", err) - } - return n, nil -} - -// MarshalBinary implements encoding.BinaryMarshaler. -func (s Duration) MarshalBinary() ([]byte, error) { - b := bytes.Buffer{} - e := xdr.NewEncoder(&b) - err := s.EncodeTo(e) - return b.Bytes(), err -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *Duration) UnmarshalBinary(inp []byte) error { - r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) - return err -} - -var ( - _ encoding.BinaryMarshaler = (*Duration)(nil) - _ encoding.BinaryUnmarshaler = (*Duration)(nil) -) - -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s Duration) xdrType() {} - -var _ xdrType = (*Duration)(nil) - // DataValue is an XDR Typedef defines as: // // typedef opaque DataValue<64>; @@ -1759,13 +1679,17 @@ func (s DataValue) EncodeTo(e *xdr.Encoder) error { var _ decoderFrom = (*DataValue)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *DataValue) DecodeFrom(d *xdr.Decoder) (int, error) { +func (s *DataValue) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding DataValue: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int (*s), nTmp, err = d.DecodeOpaque(64) n += nTmp if err != nil { - return n, fmt.Errorf("decoding DataValue: %s", err) + return n, fmt.Errorf("decoding DataValue: %w", err) } return n, nil } @@ -1781,8 +1705,10 @@ func (s DataValue) MarshalBinary() ([]byte, error) { // UnmarshalBinary implements encoding.BinaryUnmarshaler. func (s *DataValue) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } @@ -1791,8 +1717,7 @@ var ( _ encoding.BinaryUnmarshaler = (*DataValue)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. +// xdrType signals that this type represents XDR values defined by this package. func (s DataValue) xdrType() {} var _ xdrType = (*DataValue)(nil) @@ -1814,13 +1739,17 @@ func (s *PoolId) EncodeTo(e *xdr.Encoder) error { var _ decoderFrom = (*PoolId)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *PoolId) DecodeFrom(d *xdr.Decoder) (int, error) { +func (s *PoolId) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding PoolId: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = (*Hash)(s).DecodeFrom(d) + nTmp, err = (*Hash)(s).DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Hash: %s", err) + return n, fmt.Errorf("decoding Hash: %w", err) } return n, nil } @@ -1836,8 +1765,10 @@ func (s PoolId) MarshalBinary() ([]byte, error) { // UnmarshalBinary implements encoding.BinaryUnmarshaler. func (s *PoolId) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } @@ -1846,8 +1777,7 @@ var ( _ encoding.BinaryUnmarshaler = (*PoolId)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. +// xdrType signals that this type represents XDR values defined by this package. func (s PoolId) xdrType() {} var _ xdrType = (*PoolId)(nil) @@ -1874,13 +1804,17 @@ func (s *AssetCode4) EncodeTo(e *xdr.Encoder) error { var _ decoderFrom = (*AssetCode4)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *AssetCode4) DecodeFrom(d *xdr.Decoder) (int, error) { +func (s *AssetCode4) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding AssetCode4: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int nTmp, err = d.DecodeFixedOpaqueInplace(s[:]) n += nTmp if err != nil { - return n, fmt.Errorf("decoding AssetCode4: %s", err) + return n, fmt.Errorf("decoding AssetCode4: %w", err) } return n, nil } @@ -1896,8 +1830,10 @@ func (s AssetCode4) MarshalBinary() ([]byte, error) { // UnmarshalBinary implements encoding.BinaryUnmarshaler. func (s *AssetCode4) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } @@ -1906,8 +1842,7 @@ var ( _ encoding.BinaryUnmarshaler = (*AssetCode4)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. +// xdrType signals that this type represents XDR values defined by this package. func (s AssetCode4) xdrType() {} var _ xdrType = (*AssetCode4)(nil) @@ -1934,13 +1869,17 @@ func (s *AssetCode12) EncodeTo(e *xdr.Encoder) error { var _ decoderFrom = (*AssetCode12)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *AssetCode12) DecodeFrom(d *xdr.Decoder) (int, error) { +func (s *AssetCode12) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding AssetCode12: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int nTmp, err = d.DecodeFixedOpaqueInplace(s[:]) n += nTmp if err != nil { - return n, fmt.Errorf("decoding AssetCode12: %s", err) + return n, fmt.Errorf("decoding AssetCode12: %w", err) } return n, nil } @@ -1956,8 +1895,10 @@ func (s AssetCode12) MarshalBinary() ([]byte, error) { // UnmarshalBinary implements encoding.BinaryUnmarshaler. func (s *AssetCode12) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } @@ -1966,8 +1907,7 @@ var ( _ encoding.BinaryUnmarshaler = (*AssetCode12)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. +// xdrType signals that this type represents XDR values defined by this package. func (s AssetCode12) xdrType() {} var _ xdrType = (*AssetCode12)(nil) @@ -2022,10 +1962,14 @@ func (e AssetType) EncodeTo(enc *xdr.Encoder) error { var _ decoderFrom = (*AssetType)(nil) // DecodeFrom decodes this value using the Decoder. -func (e *AssetType) DecodeFrom(d *xdr.Decoder) (int, error) { +func (e *AssetType) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding AssetType: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 v, n, err := d.DecodeInt() if err != nil { - return n, fmt.Errorf("decoding AssetType: %s", err) + return n, fmt.Errorf("decoding AssetType: %w", err) } if _, ok := assetTypeMap[v]; !ok { return n, fmt.Errorf("'%d' is not a valid AssetType enum value", v) @@ -2045,8 +1989,10 @@ func (s AssetType) MarshalBinary() ([]byte, error) { // UnmarshalBinary implements encoding.BinaryUnmarshaler. func (s *AssetType) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } @@ -2055,8 +2001,7 @@ var ( _ encoding.BinaryUnmarshaler = (*AssetType)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. +// xdrType signals that this type represents XDR values defined by this package. func (s AssetType) xdrType() {} var _ xdrType = (*AssetType)(nil) @@ -2104,14 +2049,14 @@ func NewAssetCode(aType AssetType, value interface{}) (result AssetCode, err err case AssetTypeAssetTypeCreditAlphanum4: tv, ok := value.(AssetCode4) if !ok { - err = fmt.Errorf("invalid value, must be AssetCode4") + err = errors.New("invalid value, must be AssetCode4") return } result.AssetCode4 = &tv case AssetTypeAssetTypeCreditAlphanum12: tv, ok := value.(AssetCode12) if !ok { - err = fmt.Errorf("invalid value, must be AssetCode12") + err = errors.New("invalid value, must be AssetCode12") return } result.AssetCode12 = &tv @@ -2193,29 +2138,33 @@ func (u AssetCode) EncodeTo(e *xdr.Encoder) error { var _ decoderFrom = (*AssetCode)(nil) // DecodeFrom decodes this value using the Decoder. -func (u *AssetCode) DecodeFrom(d *xdr.Decoder) (int, error) { +func (u *AssetCode) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding AssetCode: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = u.Type.DecodeFrom(d) + nTmp, err = u.Type.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding AssetType: %s", err) + return n, fmt.Errorf("decoding AssetType: %w", err) } switch AssetType(u.Type) { case AssetTypeAssetTypeCreditAlphanum4: u.AssetCode4 = new(AssetCode4) - nTmp, err = (*u.AssetCode4).DecodeFrom(d) + nTmp, err = (*u.AssetCode4).DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding AssetCode4: %s", err) + return n, fmt.Errorf("decoding AssetCode4: %w", err) } return n, nil case AssetTypeAssetTypeCreditAlphanum12: u.AssetCode12 = new(AssetCode12) - nTmp, err = (*u.AssetCode12).DecodeFrom(d) + nTmp, err = (*u.AssetCode12).DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding AssetCode12: %s", err) + return n, fmt.Errorf("decoding AssetCode12: %w", err) } return n, nil } @@ -2233,8 +2182,10 @@ func (s AssetCode) MarshalBinary() ([]byte, error) { // UnmarshalBinary implements encoding.BinaryUnmarshaler. func (s *AssetCode) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } @@ -2243,8 +2194,7 @@ var ( _ encoding.BinaryUnmarshaler = (*AssetCode)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. +// xdrType signals that this type represents XDR values defined by this package. func (s AssetCode) xdrType() {} var _ xdrType = (*AssetCode)(nil) @@ -2276,18 +2226,22 @@ func (s *AlphaNum4) EncodeTo(e *xdr.Encoder) error { var _ decoderFrom = (*AlphaNum4)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *AlphaNum4) DecodeFrom(d *xdr.Decoder) (int, error) { +func (s *AlphaNum4) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding AlphaNum4: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = s.AssetCode.DecodeFrom(d) + nTmp, err = s.AssetCode.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding AssetCode4: %s", err) + return n, fmt.Errorf("decoding AssetCode4: %w", err) } - nTmp, err = s.Issuer.DecodeFrom(d) + nTmp, err = s.Issuer.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding AccountId: %s", err) + return n, fmt.Errorf("decoding AccountId: %w", err) } return n, nil } @@ -2303,8 +2257,10 @@ func (s AlphaNum4) MarshalBinary() ([]byte, error) { // UnmarshalBinary implements encoding.BinaryUnmarshaler. func (s *AlphaNum4) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } @@ -2313,8 +2269,7 @@ var ( _ encoding.BinaryUnmarshaler = (*AlphaNum4)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. +// xdrType signals that this type represents XDR values defined by this package. func (s AlphaNum4) xdrType() {} var _ xdrType = (*AlphaNum4)(nil) @@ -2346,18 +2301,22 @@ func (s *AlphaNum12) EncodeTo(e *xdr.Encoder) error { var _ decoderFrom = (*AlphaNum12)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *AlphaNum12) DecodeFrom(d *xdr.Decoder) (int, error) { +func (s *AlphaNum12) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding AlphaNum12: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = s.AssetCode.DecodeFrom(d) + nTmp, err = s.AssetCode.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding AssetCode12: %s", err) + return n, fmt.Errorf("decoding AssetCode12: %w", err) } - nTmp, err = s.Issuer.DecodeFrom(d) + nTmp, err = s.Issuer.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding AccountId: %s", err) + return n, fmt.Errorf("decoding AccountId: %w", err) } return n, nil } @@ -2373,8 +2332,10 @@ func (s AlphaNum12) MarshalBinary() ([]byte, error) { // UnmarshalBinary implements encoding.BinaryUnmarshaler. func (s *AlphaNum12) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } @@ -2383,8 +2344,7 @@ var ( _ encoding.BinaryUnmarshaler = (*AlphaNum12)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. +// xdrType signals that this type represents XDR values defined by this package. func (s AlphaNum12) xdrType() {} var _ xdrType = (*AlphaNum12)(nil) @@ -2439,14 +2399,14 @@ func NewAsset(aType AssetType, value interface{}) (result Asset, err error) { case AssetTypeAssetTypeCreditAlphanum4: tv, ok := value.(AlphaNum4) if !ok { - err = fmt.Errorf("invalid value, must be AlphaNum4") + err = errors.New("invalid value, must be AlphaNum4") return } result.AlphaNum4 = &tv case AssetTypeAssetTypeCreditAlphanum12: tv, ok := value.(AlphaNum12) if !ok { - err = fmt.Errorf("invalid value, must be AlphaNum12") + err = errors.New("invalid value, must be AlphaNum12") return } result.AlphaNum12 = &tv @@ -2531,13 +2491,17 @@ func (u Asset) EncodeTo(e *xdr.Encoder) error { var _ decoderFrom = (*Asset)(nil) // DecodeFrom decodes this value using the Decoder. -func (u *Asset) DecodeFrom(d *xdr.Decoder) (int, error) { +func (u *Asset) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding Asset: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = u.Type.DecodeFrom(d) + nTmp, err = u.Type.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding AssetType: %s", err) + return n, fmt.Errorf("decoding AssetType: %w", err) } switch AssetType(u.Type) { case AssetTypeAssetTypeNative: @@ -2545,18 +2509,18 @@ func (u *Asset) DecodeFrom(d *xdr.Decoder) (int, error) { return n, nil case AssetTypeAssetTypeCreditAlphanum4: u.AlphaNum4 = new(AlphaNum4) - nTmp, err = (*u.AlphaNum4).DecodeFrom(d) + nTmp, err = (*u.AlphaNum4).DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding AlphaNum4: %s", err) + return n, fmt.Errorf("decoding AlphaNum4: %w", err) } return n, nil case AssetTypeAssetTypeCreditAlphanum12: u.AlphaNum12 = new(AlphaNum12) - nTmp, err = (*u.AlphaNum12).DecodeFrom(d) + nTmp, err = (*u.AlphaNum12).DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding AlphaNum12: %s", err) + return n, fmt.Errorf("decoding AlphaNum12: %w", err) } return n, nil } @@ -2574,8 +2538,10 @@ func (s Asset) MarshalBinary() ([]byte, error) { // UnmarshalBinary implements encoding.BinaryUnmarshaler. func (s *Asset) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } @@ -2584,8 +2550,7 @@ var ( _ encoding.BinaryUnmarshaler = (*Asset)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. +// xdrType signals that this type represents XDR values defined by this package. func (s Asset) xdrType() {} var _ xdrType = (*Asset)(nil) @@ -2617,18 +2582,22 @@ func (s *Price) EncodeTo(e *xdr.Encoder) error { var _ decoderFrom = (*Price)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *Price) DecodeFrom(d *xdr.Decoder) (int, error) { +func (s *Price) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding Price: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = s.N.DecodeFrom(d) + nTmp, err = s.N.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Int32: %s", err) + return n, fmt.Errorf("decoding Int32: %w", err) } - nTmp, err = s.D.DecodeFrom(d) + nTmp, err = s.D.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Int32: %s", err) + return n, fmt.Errorf("decoding Int32: %w", err) } return n, nil } @@ -2644,8 +2613,10 @@ func (s Price) MarshalBinary() ([]byte, error) { // UnmarshalBinary implements encoding.BinaryUnmarshaler. func (s *Price) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } @@ -2654,8 +2625,7 @@ var ( _ encoding.BinaryUnmarshaler = (*Price)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. +// xdrType signals that this type represents XDR values defined by this package. func (s Price) xdrType() {} var _ xdrType = (*Price)(nil) @@ -2687,18 +2657,22 @@ func (s *Liabilities) EncodeTo(e *xdr.Encoder) error { var _ decoderFrom = (*Liabilities)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *Liabilities) DecodeFrom(d *xdr.Decoder) (int, error) { +func (s *Liabilities) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding Liabilities: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = s.Buying.DecodeFrom(d) + nTmp, err = s.Buying.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Int64: %s", err) + return n, fmt.Errorf("decoding Int64: %w", err) } - nTmp, err = s.Selling.DecodeFrom(d) + nTmp, err = s.Selling.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Int64: %s", err) + return n, fmt.Errorf("decoding Int64: %w", err) } return n, nil } @@ -2714,8 +2688,10 @@ func (s Liabilities) MarshalBinary() ([]byte, error) { // UnmarshalBinary implements encoding.BinaryUnmarshaler. func (s *Liabilities) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } @@ -2724,8 +2700,7 @@ var ( _ encoding.BinaryUnmarshaler = (*Liabilities)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. +// xdrType signals that this type represents XDR values defined by this package. func (s Liabilities) xdrType() {} var _ xdrType = (*Liabilities)(nil) @@ -2780,10 +2755,14 @@ func (e ThresholdIndexes) EncodeTo(enc *xdr.Encoder) error { var _ decoderFrom = (*ThresholdIndexes)(nil) // DecodeFrom decodes this value using the Decoder. -func (e *ThresholdIndexes) DecodeFrom(d *xdr.Decoder) (int, error) { +func (e *ThresholdIndexes) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding ThresholdIndexes: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 v, n, err := d.DecodeInt() if err != nil { - return n, fmt.Errorf("decoding ThresholdIndexes: %s", err) + return n, fmt.Errorf("decoding ThresholdIndexes: %w", err) } if _, ok := thresholdIndexesMap[v]; !ok { return n, fmt.Errorf("'%d' is not a valid ThresholdIndexes enum value", v) @@ -2803,8 +2782,10 @@ func (s ThresholdIndexes) MarshalBinary() ([]byte, error) { // UnmarshalBinary implements encoding.BinaryUnmarshaler. func (s *ThresholdIndexes) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } @@ -2813,8 +2794,7 @@ var ( _ encoding.BinaryUnmarshaler = (*ThresholdIndexes)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. +// xdrType signals that this type represents XDR values defined by this package. func (s ThresholdIndexes) xdrType() {} var _ xdrType = (*ThresholdIndexes)(nil) @@ -2828,7 +2808,11 @@ var _ xdrType = (*ThresholdIndexes)(nil) // OFFER = 2, // DATA = 3, // CLAIMABLE_BALANCE = 4, -// LIQUIDITY_POOL = 5 +// LIQUIDITY_POOL = 5, +// CONTRACT_DATA = 6, +// CONTRACT_CODE = 7, +// CONFIG_SETTING = 8, +// TTL = 9 // }; type LedgerEntryType int32 @@ -2839,6 +2823,10 @@ const ( LedgerEntryTypeData LedgerEntryType = 3 LedgerEntryTypeClaimableBalance LedgerEntryType = 4 LedgerEntryTypeLiquidityPool LedgerEntryType = 5 + LedgerEntryTypeContractData LedgerEntryType = 6 + LedgerEntryTypeContractCode LedgerEntryType = 7 + LedgerEntryTypeConfigSetting LedgerEntryType = 8 + LedgerEntryTypeTtl LedgerEntryType = 9 ) var ledgerEntryTypeMap = map[int32]string{ @@ -2848,6 +2836,10 @@ var ledgerEntryTypeMap = map[int32]string{ 3: "LedgerEntryTypeData", 4: "LedgerEntryTypeClaimableBalance", 5: "LedgerEntryTypeLiquidityPool", + 6: "LedgerEntryTypeContractData", + 7: "LedgerEntryTypeContractCode", + 8: "LedgerEntryTypeConfigSetting", + 9: "LedgerEntryTypeTtl", } // ValidEnum validates a proposed value for this enum. Implements @@ -2875,10 +2867,14 @@ func (e LedgerEntryType) EncodeTo(enc *xdr.Encoder) error { var _ decoderFrom = (*LedgerEntryType)(nil) // DecodeFrom decodes this value using the Decoder. -func (e *LedgerEntryType) DecodeFrom(d *xdr.Decoder) (int, error) { +func (e *LedgerEntryType) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding LedgerEntryType: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 v, n, err := d.DecodeInt() if err != nil { - return n, fmt.Errorf("decoding LedgerEntryType: %s", err) + return n, fmt.Errorf("decoding LedgerEntryType: %w", err) } if _, ok := ledgerEntryTypeMap[v]; !ok { return n, fmt.Errorf("'%d' is not a valid LedgerEntryType enum value", v) @@ -2898,8 +2894,10 @@ func (s LedgerEntryType) MarshalBinary() ([]byte, error) { // UnmarshalBinary implements encoding.BinaryUnmarshaler. func (s *LedgerEntryType) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } @@ -2908,8 +2906,7 @@ var ( _ encoding.BinaryUnmarshaler = (*LedgerEntryType)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. +// xdrType signals that this type represents XDR values defined by this package. func (s LedgerEntryType) xdrType() {} var _ xdrType = (*LedgerEntryType)(nil) @@ -2941,18 +2938,22 @@ func (s *Signer) EncodeTo(e *xdr.Encoder) error { var _ decoderFrom = (*Signer)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *Signer) DecodeFrom(d *xdr.Decoder) (int, error) { +func (s *Signer) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding Signer: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = s.Key.DecodeFrom(d) + nTmp, err = s.Key.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding SignerKey: %s", err) + return n, fmt.Errorf("decoding SignerKey: %w", err) } - nTmp, err = s.Weight.DecodeFrom(d) + nTmp, err = s.Weight.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Uint32: %s", err) + return n, fmt.Errorf("decoding Uint32: %w", err) } return n, nil } @@ -2968,8 +2969,10 @@ func (s Signer) MarshalBinary() ([]byte, error) { // UnmarshalBinary implements encoding.BinaryUnmarshaler. func (s *Signer) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } @@ -2978,8 +2981,7 @@ var ( _ encoding.BinaryUnmarshaler = (*Signer)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. +// xdrType signals that this type represents XDR values defined by this package. func (s Signer) xdrType() {} var _ xdrType = (*Signer)(nil) @@ -3044,10 +3046,14 @@ func (e AccountFlags) EncodeTo(enc *xdr.Encoder) error { var _ decoderFrom = (*AccountFlags)(nil) // DecodeFrom decodes this value using the Decoder. -func (e *AccountFlags) DecodeFrom(d *xdr.Decoder) (int, error) { +func (e *AccountFlags) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding AccountFlags: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 v, n, err := d.DecodeInt() if err != nil { - return n, fmt.Errorf("decoding AccountFlags: %s", err) + return n, fmt.Errorf("decoding AccountFlags: %w", err) } if _, ok := accountFlagsMap[v]; !ok { return n, fmt.Errorf("'%d' is not a valid AccountFlags enum value", v) @@ -3067,8 +3073,10 @@ func (s AccountFlags) MarshalBinary() ([]byte, error) { // UnmarshalBinary implements encoding.BinaryUnmarshaler. func (s *AccountFlags) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } @@ -3077,8 +3085,7 @@ var ( _ encoding.BinaryUnmarshaler = (*AccountFlags)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. +// xdrType signals that this type represents XDR values defined by this package. func (s AccountFlags) xdrType() {} var _ xdrType = (*AccountFlags)(nil) @@ -3141,23 +3148,27 @@ func (s *AccountEntryExtensionV3) EncodeTo(e *xdr.Encoder) error { var _ decoderFrom = (*AccountEntryExtensionV3)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *AccountEntryExtensionV3) DecodeFrom(d *xdr.Decoder) (int, error) { +func (s *AccountEntryExtensionV3) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding AccountEntryExtensionV3: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = s.Ext.DecodeFrom(d) + nTmp, err = s.Ext.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding ExtensionPoint: %s", err) + return n, fmt.Errorf("decoding ExtensionPoint: %w", err) } - nTmp, err = s.SeqLedger.DecodeFrom(d) + nTmp, err = s.SeqLedger.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Uint32: %s", err) + return n, fmt.Errorf("decoding Uint32: %w", err) } - nTmp, err = s.SeqTime.DecodeFrom(d) + nTmp, err = s.SeqTime.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding TimePoint: %s", err) + return n, fmt.Errorf("decoding TimePoint: %w", err) } return n, nil } @@ -3173,8 +3184,10 @@ func (s AccountEntryExtensionV3) MarshalBinary() ([]byte, error) { // UnmarshalBinary implements encoding.BinaryUnmarshaler. func (s *AccountEntryExtensionV3) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } @@ -3183,8 +3196,7 @@ var ( _ encoding.BinaryUnmarshaler = (*AccountEntryExtensionV3)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. +// xdrType signals that this type represents XDR values defined by this package. func (s AccountEntryExtensionV3) xdrType() {} var _ xdrType = (*AccountEntryExtensionV3)(nil) @@ -3230,7 +3242,7 @@ func NewAccountEntryExtensionV2Ext(v int32, value interface{}) (result AccountEn case 3: tv, ok := value.(AccountEntryExtensionV3) if !ok { - err = fmt.Errorf("invalid value, must be AccountEntryExtensionV3") + err = errors.New("invalid value, must be AccountEntryExtensionV3") return } result.V3 = &tv @@ -3285,13 +3297,17 @@ func (u AccountEntryExtensionV2Ext) EncodeTo(e *xdr.Encoder) error { var _ decoderFrom = (*AccountEntryExtensionV2Ext)(nil) // DecodeFrom decodes this value using the Decoder. -func (u *AccountEntryExtensionV2Ext) DecodeFrom(d *xdr.Decoder) (int, error) { +func (u *AccountEntryExtensionV2Ext) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding AccountEntryExtensionV2Ext: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int u.V, nTmp, err = d.DecodeInt() n += nTmp if err != nil { - return n, fmt.Errorf("decoding Int: %s", err) + return n, fmt.Errorf("decoding Int: %w", err) } switch int32(u.V) { case 0: @@ -3299,10 +3315,10 @@ func (u *AccountEntryExtensionV2Ext) DecodeFrom(d *xdr.Decoder) (int, error) { return n, nil case 3: u.V3 = new(AccountEntryExtensionV3) - nTmp, err = (*u.V3).DecodeFrom(d) + nTmp, err = (*u.V3).DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding AccountEntryExtensionV3: %s", err) + return n, fmt.Errorf("decoding AccountEntryExtensionV3: %w", err) } return n, nil } @@ -3320,8 +3336,10 @@ func (s AccountEntryExtensionV2Ext) MarshalBinary() ([]byte, error) { // UnmarshalBinary implements encoding.BinaryUnmarshaler. func (s *AccountEntryExtensionV2Ext) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } @@ -3330,8 +3348,7 @@ var ( _ encoding.BinaryUnmarshaler = (*AccountEntryExtensionV2Ext)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. +// xdrType signals that this type represents XDR values defined by this package. func (s AccountEntryExtensionV2Ext) xdrType() {} var _ xdrType = (*AccountEntryExtensionV2Ext)(nil) @@ -3391,53 +3408,60 @@ func (s *AccountEntryExtensionV2) EncodeTo(e *xdr.Encoder) error { var _ decoderFrom = (*AccountEntryExtensionV2)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *AccountEntryExtensionV2) DecodeFrom(d *xdr.Decoder) (int, error) { +func (s *AccountEntryExtensionV2) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding AccountEntryExtensionV2: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = s.NumSponsored.DecodeFrom(d) + nTmp, err = s.NumSponsored.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Uint32: %s", err) + return n, fmt.Errorf("decoding Uint32: %w", err) } - nTmp, err = s.NumSponsoring.DecodeFrom(d) + nTmp, err = s.NumSponsoring.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Uint32: %s", err) + return n, fmt.Errorf("decoding Uint32: %w", err) } var l uint32 l, nTmp, err = d.DecodeUint() n += nTmp if err != nil { - return n, fmt.Errorf("decoding SponsorshipDescriptor: %s", err) + return n, fmt.Errorf("decoding SponsorshipDescriptor: %w", err) } if l > 20 { return n, fmt.Errorf("decoding SponsorshipDescriptor: data size (%d) exceeds size limit (20)", l) } s.SignerSponsoringIDs = nil if l > 0 { + if il, ok := d.InputLen(); ok && uint(il) < uint(l) { + return n, fmt.Errorf("decoding SponsorshipDescriptor: length (%d) exceeds remaining input length (%d)", l, il) + } s.SignerSponsoringIDs = make([]SponsorshipDescriptor, l) for i := uint32(0); i < l; i++ { var eb bool eb, nTmp, err = d.DecodeBool() n += nTmp if err != nil { - return n, fmt.Errorf("decoding SponsorshipDescriptor: %s", err) + return n, fmt.Errorf("decoding SponsorshipDescriptor: %w", err) } s.SignerSponsoringIDs[i] = nil if eb { s.SignerSponsoringIDs[i] = new(AccountId) - nTmp, err = s.SignerSponsoringIDs[i].DecodeFrom(d) + nTmp, err = s.SignerSponsoringIDs[i].DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding SponsorshipDescriptor: %s", err) + return n, fmt.Errorf("decoding SponsorshipDescriptor: %w", err) } } } } - nTmp, err = s.Ext.DecodeFrom(d) + nTmp, err = s.Ext.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding AccountEntryExtensionV2Ext: %s", err) + return n, fmt.Errorf("decoding AccountEntryExtensionV2Ext: %w", err) } return n, nil } @@ -3453,8 +3477,10 @@ func (s AccountEntryExtensionV2) MarshalBinary() ([]byte, error) { // UnmarshalBinary implements encoding.BinaryUnmarshaler. func (s *AccountEntryExtensionV2) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } @@ -3463,8 +3489,7 @@ var ( _ encoding.BinaryUnmarshaler = (*AccountEntryExtensionV2)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. +// xdrType signals that this type represents XDR values defined by this package. func (s AccountEntryExtensionV2) xdrType() {} var _ xdrType = (*AccountEntryExtensionV2)(nil) @@ -3510,7 +3535,7 @@ func NewAccountEntryExtensionV1Ext(v int32, value interface{}) (result AccountEn case 2: tv, ok := value.(AccountEntryExtensionV2) if !ok { - err = fmt.Errorf("invalid value, must be AccountEntryExtensionV2") + err = errors.New("invalid value, must be AccountEntryExtensionV2") return } result.V2 = &tv @@ -3565,13 +3590,17 @@ func (u AccountEntryExtensionV1Ext) EncodeTo(e *xdr.Encoder) error { var _ decoderFrom = (*AccountEntryExtensionV1Ext)(nil) // DecodeFrom decodes this value using the Decoder. -func (u *AccountEntryExtensionV1Ext) DecodeFrom(d *xdr.Decoder) (int, error) { +func (u *AccountEntryExtensionV1Ext) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding AccountEntryExtensionV1Ext: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int u.V, nTmp, err = d.DecodeInt() n += nTmp if err != nil { - return n, fmt.Errorf("decoding Int: %s", err) + return n, fmt.Errorf("decoding Int: %w", err) } switch int32(u.V) { case 0: @@ -3579,10 +3608,10 @@ func (u *AccountEntryExtensionV1Ext) DecodeFrom(d *xdr.Decoder) (int, error) { return n, nil case 2: u.V2 = new(AccountEntryExtensionV2) - nTmp, err = (*u.V2).DecodeFrom(d) + nTmp, err = (*u.V2).DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding AccountEntryExtensionV2: %s", err) + return n, fmt.Errorf("decoding AccountEntryExtensionV2: %w", err) } return n, nil } @@ -3600,8 +3629,10 @@ func (s AccountEntryExtensionV1Ext) MarshalBinary() ([]byte, error) { // UnmarshalBinary implements encoding.BinaryUnmarshaler. func (s *AccountEntryExtensionV1Ext) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } @@ -3610,8 +3641,7 @@ var ( _ encoding.BinaryUnmarshaler = (*AccountEntryExtensionV1Ext)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. +// xdrType signals that this type represents XDR values defined by this package. func (s AccountEntryExtensionV1Ext) xdrType() {} var _ xdrType = (*AccountEntryExtensionV1Ext)(nil) @@ -3651,18 +3681,22 @@ func (s *AccountEntryExtensionV1) EncodeTo(e *xdr.Encoder) error { var _ decoderFrom = (*AccountEntryExtensionV1)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *AccountEntryExtensionV1) DecodeFrom(d *xdr.Decoder) (int, error) { +func (s *AccountEntryExtensionV1) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding AccountEntryExtensionV1: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = s.Liabilities.DecodeFrom(d) + nTmp, err = s.Liabilities.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Liabilities: %s", err) + return n, fmt.Errorf("decoding Liabilities: %w", err) } - nTmp, err = s.Ext.DecodeFrom(d) + nTmp, err = s.Ext.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding AccountEntryExtensionV1Ext: %s", err) + return n, fmt.Errorf("decoding AccountEntryExtensionV1Ext: %w", err) } return n, nil } @@ -3678,8 +3712,10 @@ func (s AccountEntryExtensionV1) MarshalBinary() ([]byte, error) { // UnmarshalBinary implements encoding.BinaryUnmarshaler. func (s *AccountEntryExtensionV1) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } @@ -3688,8 +3724,7 @@ var ( _ encoding.BinaryUnmarshaler = (*AccountEntryExtensionV1)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. +// xdrType signals that this type represents XDR values defined by this package. func (s AccountEntryExtensionV1) xdrType() {} var _ xdrType = (*AccountEntryExtensionV1)(nil) @@ -3735,7 +3770,7 @@ func NewAccountEntryExt(v int32, value interface{}) (result AccountEntryExt, err case 1: tv, ok := value.(AccountEntryExtensionV1) if !ok { - err = fmt.Errorf("invalid value, must be AccountEntryExtensionV1") + err = errors.New("invalid value, must be AccountEntryExtensionV1") return } result.V1 = &tv @@ -3790,13 +3825,17 @@ func (u AccountEntryExt) EncodeTo(e *xdr.Encoder) error { var _ decoderFrom = (*AccountEntryExt)(nil) // DecodeFrom decodes this value using the Decoder. -func (u *AccountEntryExt) DecodeFrom(d *xdr.Decoder) (int, error) { +func (u *AccountEntryExt) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding AccountEntryExt: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int u.V, nTmp, err = d.DecodeInt() n += nTmp if err != nil { - return n, fmt.Errorf("decoding Int: %s", err) + return n, fmt.Errorf("decoding Int: %w", err) } switch int32(u.V) { case 0: @@ -3804,10 +3843,10 @@ func (u *AccountEntryExt) DecodeFrom(d *xdr.Decoder) (int, error) { return n, nil case 1: u.V1 = new(AccountEntryExtensionV1) - nTmp, err = (*u.V1).DecodeFrom(d) + nTmp, err = (*u.V1).DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding AccountEntryExtensionV1: %s", err) + return n, fmt.Errorf("decoding AccountEntryExtensionV1: %w", err) } return n, nil } @@ -3825,8 +3864,10 @@ func (s AccountEntryExt) MarshalBinary() ([]byte, error) { // UnmarshalBinary implements encoding.BinaryUnmarshaler. func (s *AccountEntryExt) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } @@ -3835,8 +3876,7 @@ var ( _ encoding.BinaryUnmarshaler = (*AccountEntryExt)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. +// xdrType signals that this type represents XDR values defined by this package. func (s AccountEntryExt) xdrType() {} var _ xdrType = (*AccountEntryExt)(nil) @@ -3933,83 +3973,90 @@ func (s *AccountEntry) EncodeTo(e *xdr.Encoder) error { var _ decoderFrom = (*AccountEntry)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *AccountEntry) DecodeFrom(d *xdr.Decoder) (int, error) { +func (s *AccountEntry) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding AccountEntry: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = s.AccountId.DecodeFrom(d) + nTmp, err = s.AccountId.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding AccountId: %s", err) + return n, fmt.Errorf("decoding AccountId: %w", err) } - nTmp, err = s.Balance.DecodeFrom(d) + nTmp, err = s.Balance.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Int64: %s", err) + return n, fmt.Errorf("decoding Int64: %w", err) } - nTmp, err = s.SeqNum.DecodeFrom(d) + nTmp, err = s.SeqNum.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding SequenceNumber: %s", err) + return n, fmt.Errorf("decoding SequenceNumber: %w", err) } - nTmp, err = s.NumSubEntries.DecodeFrom(d) + nTmp, err = s.NumSubEntries.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Uint32: %s", err) + return n, fmt.Errorf("decoding Uint32: %w", err) } var b bool b, nTmp, err = d.DecodeBool() n += nTmp if err != nil { - return n, fmt.Errorf("decoding AccountId: %s", err) + return n, fmt.Errorf("decoding AccountId: %w", err) } s.InflationDest = nil if b { s.InflationDest = new(AccountId) - nTmp, err = s.InflationDest.DecodeFrom(d) + nTmp, err = s.InflationDest.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding AccountId: %s", err) + return n, fmt.Errorf("decoding AccountId: %w", err) } } - nTmp, err = s.Flags.DecodeFrom(d) + nTmp, err = s.Flags.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Uint32: %s", err) + return n, fmt.Errorf("decoding Uint32: %w", err) } - nTmp, err = s.HomeDomain.DecodeFrom(d) + nTmp, err = s.HomeDomain.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding String32: %s", err) + return n, fmt.Errorf("decoding String32: %w", err) } - nTmp, err = s.Thresholds.DecodeFrom(d) + nTmp, err = s.Thresholds.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Thresholds: %s", err) + return n, fmt.Errorf("decoding Thresholds: %w", err) } var l uint32 l, nTmp, err = d.DecodeUint() n += nTmp if err != nil { - return n, fmt.Errorf("decoding Signer: %s", err) + return n, fmt.Errorf("decoding Signer: %w", err) } if l > 20 { return n, fmt.Errorf("decoding Signer: data size (%d) exceeds size limit (20)", l) } s.Signers = nil if l > 0 { + if il, ok := d.InputLen(); ok && uint(il) < uint(l) { + return n, fmt.Errorf("decoding Signer: length (%d) exceeds remaining input length (%d)", l, il) + } s.Signers = make([]Signer, l) for i := uint32(0); i < l; i++ { - nTmp, err = s.Signers[i].DecodeFrom(d) + nTmp, err = s.Signers[i].DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Signer: %s", err) + return n, fmt.Errorf("decoding Signer: %w", err) } } } - nTmp, err = s.Ext.DecodeFrom(d) + nTmp, err = s.Ext.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding AccountEntryExt: %s", err) + return n, fmt.Errorf("decoding AccountEntryExt: %w", err) } return n, nil } @@ -4025,8 +4072,10 @@ func (s AccountEntry) MarshalBinary() ([]byte, error) { // UnmarshalBinary implements encoding.BinaryUnmarshaler. func (s *AccountEntry) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } @@ -4035,8 +4084,7 @@ var ( _ encoding.BinaryUnmarshaler = (*AccountEntry)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. +// xdrType signals that this type represents XDR values defined by this package. func (s AccountEntry) xdrType() {} var _ xdrType = (*AccountEntry)(nil) @@ -4093,10 +4141,14 @@ func (e TrustLineFlags) EncodeTo(enc *xdr.Encoder) error { var _ decoderFrom = (*TrustLineFlags)(nil) // DecodeFrom decodes this value using the Decoder. -func (e *TrustLineFlags) DecodeFrom(d *xdr.Decoder) (int, error) { +func (e *TrustLineFlags) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding TrustLineFlags: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 v, n, err := d.DecodeInt() if err != nil { - return n, fmt.Errorf("decoding TrustLineFlags: %s", err) + return n, fmt.Errorf("decoding TrustLineFlags: %w", err) } if _, ok := trustLineFlagsMap[v]; !ok { return n, fmt.Errorf("'%d' is not a valid TrustLineFlags enum value", v) @@ -4116,8 +4168,10 @@ func (s TrustLineFlags) MarshalBinary() ([]byte, error) { // UnmarshalBinary implements encoding.BinaryUnmarshaler. func (s *TrustLineFlags) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } @@ -4126,8 +4180,7 @@ var ( _ encoding.BinaryUnmarshaler = (*TrustLineFlags)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. +// xdrType signals that this type represents XDR values defined by this package. func (s TrustLineFlags) xdrType() {} var _ xdrType = (*TrustLineFlags)(nil) @@ -4188,10 +4241,14 @@ func (e LiquidityPoolType) EncodeTo(enc *xdr.Encoder) error { var _ decoderFrom = (*LiquidityPoolType)(nil) // DecodeFrom decodes this value using the Decoder. -func (e *LiquidityPoolType) DecodeFrom(d *xdr.Decoder) (int, error) { +func (e *LiquidityPoolType) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding LiquidityPoolType: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 v, n, err := d.DecodeInt() if err != nil { - return n, fmt.Errorf("decoding LiquidityPoolType: %s", err) + return n, fmt.Errorf("decoding LiquidityPoolType: %w", err) } if _, ok := liquidityPoolTypeMap[v]; !ok { return n, fmt.Errorf("'%d' is not a valid LiquidityPoolType enum value", v) @@ -4211,8 +4268,10 @@ func (s LiquidityPoolType) MarshalBinary() ([]byte, error) { // UnmarshalBinary implements encoding.BinaryUnmarshaler. func (s *LiquidityPoolType) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } @@ -4221,8 +4280,7 @@ var ( _ encoding.BinaryUnmarshaler = (*LiquidityPoolType)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. +// xdrType signals that this type represents XDR values defined by this package. func (s LiquidityPoolType) xdrType() {} var _ xdrType = (*LiquidityPoolType)(nil) @@ -4283,21 +4341,21 @@ func NewTrustLineAsset(aType AssetType, value interface{}) (result TrustLineAsse case AssetTypeAssetTypeCreditAlphanum4: tv, ok := value.(AlphaNum4) if !ok { - err = fmt.Errorf("invalid value, must be AlphaNum4") + err = errors.New("invalid value, must be AlphaNum4") return } result.AlphaNum4 = &tv case AssetTypeAssetTypeCreditAlphanum12: tv, ok := value.(AlphaNum12) if !ok { - err = fmt.Errorf("invalid value, must be AlphaNum12") + err = errors.New("invalid value, must be AlphaNum12") return } result.AlphaNum12 = &tv case AssetTypeAssetTypePoolShare: tv, ok := value.(PoolId) if !ok { - err = fmt.Errorf("invalid value, must be PoolId") + err = errors.New("invalid value, must be PoolId") return } result.LiquidityPoolId = &tv @@ -4412,13 +4470,17 @@ func (u TrustLineAsset) EncodeTo(e *xdr.Encoder) error { var _ decoderFrom = (*TrustLineAsset)(nil) // DecodeFrom decodes this value using the Decoder. -func (u *TrustLineAsset) DecodeFrom(d *xdr.Decoder) (int, error) { +func (u *TrustLineAsset) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding TrustLineAsset: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = u.Type.DecodeFrom(d) + nTmp, err = u.Type.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding AssetType: %s", err) + return n, fmt.Errorf("decoding AssetType: %w", err) } switch AssetType(u.Type) { case AssetTypeAssetTypeNative: @@ -4426,26 +4488,26 @@ func (u *TrustLineAsset) DecodeFrom(d *xdr.Decoder) (int, error) { return n, nil case AssetTypeAssetTypeCreditAlphanum4: u.AlphaNum4 = new(AlphaNum4) - nTmp, err = (*u.AlphaNum4).DecodeFrom(d) + nTmp, err = (*u.AlphaNum4).DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding AlphaNum4: %s", err) + return n, fmt.Errorf("decoding AlphaNum4: %w", err) } return n, nil case AssetTypeAssetTypeCreditAlphanum12: u.AlphaNum12 = new(AlphaNum12) - nTmp, err = (*u.AlphaNum12).DecodeFrom(d) + nTmp, err = (*u.AlphaNum12).DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding AlphaNum12: %s", err) + return n, fmt.Errorf("decoding AlphaNum12: %w", err) } return n, nil case AssetTypeAssetTypePoolShare: u.LiquidityPoolId = new(PoolId) - nTmp, err = (*u.LiquidityPoolId).DecodeFrom(d) + nTmp, err = (*u.LiquidityPoolId).DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding PoolId: %s", err) + return n, fmt.Errorf("decoding PoolId: %w", err) } return n, nil } @@ -4463,8 +4525,10 @@ func (s TrustLineAsset) MarshalBinary() ([]byte, error) { // UnmarshalBinary implements encoding.BinaryUnmarshaler. func (s *TrustLineAsset) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } @@ -4473,8 +4537,7 @@ var ( _ encoding.BinaryUnmarshaler = (*TrustLineAsset)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. +// xdrType signals that this type represents XDR values defined by this package. func (s TrustLineAsset) xdrType() {} var _ xdrType = (*TrustLineAsset)(nil) @@ -4533,13 +4596,17 @@ func (u TrustLineEntryExtensionV2Ext) EncodeTo(e *xdr.Encoder) error { var _ decoderFrom = (*TrustLineEntryExtensionV2Ext)(nil) // DecodeFrom decodes this value using the Decoder. -func (u *TrustLineEntryExtensionV2Ext) DecodeFrom(d *xdr.Decoder) (int, error) { +func (u *TrustLineEntryExtensionV2Ext) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding TrustLineEntryExtensionV2Ext: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int u.V, nTmp, err = d.DecodeInt() n += nTmp if err != nil { - return n, fmt.Errorf("decoding Int: %s", err) + return n, fmt.Errorf("decoding Int: %w", err) } switch int32(u.V) { case 0: @@ -4560,8 +4627,10 @@ func (s TrustLineEntryExtensionV2Ext) MarshalBinary() ([]byte, error) { // UnmarshalBinary implements encoding.BinaryUnmarshaler. func (s *TrustLineEntryExtensionV2Ext) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } @@ -4570,8 +4639,7 @@ var ( _ encoding.BinaryUnmarshaler = (*TrustLineEntryExtensionV2Ext)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. +// xdrType signals that this type represents XDR values defined by this package. func (s TrustLineEntryExtensionV2Ext) xdrType() {} var _ xdrType = (*TrustLineEntryExtensionV2Ext)(nil) @@ -4609,18 +4677,22 @@ func (s *TrustLineEntryExtensionV2) EncodeTo(e *xdr.Encoder) error { var _ decoderFrom = (*TrustLineEntryExtensionV2)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *TrustLineEntryExtensionV2) DecodeFrom(d *xdr.Decoder) (int, error) { +func (s *TrustLineEntryExtensionV2) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding TrustLineEntryExtensionV2: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = s.LiquidityPoolUseCount.DecodeFrom(d) + nTmp, err = s.LiquidityPoolUseCount.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Int32: %s", err) + return n, fmt.Errorf("decoding Int32: %w", err) } - nTmp, err = s.Ext.DecodeFrom(d) + nTmp, err = s.Ext.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding TrustLineEntryExtensionV2Ext: %s", err) + return n, fmt.Errorf("decoding TrustLineEntryExtensionV2Ext: %w", err) } return n, nil } @@ -4636,8 +4708,10 @@ func (s TrustLineEntryExtensionV2) MarshalBinary() ([]byte, error) { // UnmarshalBinary implements encoding.BinaryUnmarshaler. func (s *TrustLineEntryExtensionV2) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } @@ -4646,8 +4720,7 @@ var ( _ encoding.BinaryUnmarshaler = (*TrustLineEntryExtensionV2)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. +// xdrType signals that this type represents XDR values defined by this package. func (s TrustLineEntryExtensionV2) xdrType() {} var _ xdrType = (*TrustLineEntryExtensionV2)(nil) @@ -4693,7 +4766,7 @@ func NewTrustLineEntryV1Ext(v int32, value interface{}) (result TrustLineEntryV1 case 2: tv, ok := value.(TrustLineEntryExtensionV2) if !ok { - err = fmt.Errorf("invalid value, must be TrustLineEntryExtensionV2") + err = errors.New("invalid value, must be TrustLineEntryExtensionV2") return } result.V2 = &tv @@ -4748,13 +4821,17 @@ func (u TrustLineEntryV1Ext) EncodeTo(e *xdr.Encoder) error { var _ decoderFrom = (*TrustLineEntryV1Ext)(nil) // DecodeFrom decodes this value using the Decoder. -func (u *TrustLineEntryV1Ext) DecodeFrom(d *xdr.Decoder) (int, error) { +func (u *TrustLineEntryV1Ext) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding TrustLineEntryV1Ext: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int u.V, nTmp, err = d.DecodeInt() n += nTmp if err != nil { - return n, fmt.Errorf("decoding Int: %s", err) + return n, fmt.Errorf("decoding Int: %w", err) } switch int32(u.V) { case 0: @@ -4762,10 +4839,10 @@ func (u *TrustLineEntryV1Ext) DecodeFrom(d *xdr.Decoder) (int, error) { return n, nil case 2: u.V2 = new(TrustLineEntryExtensionV2) - nTmp, err = (*u.V2).DecodeFrom(d) + nTmp, err = (*u.V2).DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding TrustLineEntryExtensionV2: %s", err) + return n, fmt.Errorf("decoding TrustLineEntryExtensionV2: %w", err) } return n, nil } @@ -4783,8 +4860,10 @@ func (s TrustLineEntryV1Ext) MarshalBinary() ([]byte, error) { // UnmarshalBinary implements encoding.BinaryUnmarshaler. func (s *TrustLineEntryV1Ext) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } @@ -4793,8 +4872,7 @@ var ( _ encoding.BinaryUnmarshaler = (*TrustLineEntryV1Ext)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. +// xdrType signals that this type represents XDR values defined by this package. func (s TrustLineEntryV1Ext) xdrType() {} var _ xdrType = (*TrustLineEntryV1Ext)(nil) @@ -4834,18 +4912,22 @@ func (s *TrustLineEntryV1) EncodeTo(e *xdr.Encoder) error { var _ decoderFrom = (*TrustLineEntryV1)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *TrustLineEntryV1) DecodeFrom(d *xdr.Decoder) (int, error) { +func (s *TrustLineEntryV1) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding TrustLineEntryV1: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = s.Liabilities.DecodeFrom(d) + nTmp, err = s.Liabilities.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Liabilities: %s", err) + return n, fmt.Errorf("decoding Liabilities: %w", err) } - nTmp, err = s.Ext.DecodeFrom(d) + nTmp, err = s.Ext.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding TrustLineEntryV1Ext: %s", err) + return n, fmt.Errorf("decoding TrustLineEntryV1Ext: %w", err) } return n, nil } @@ -4861,8 +4943,10 @@ func (s TrustLineEntryV1) MarshalBinary() ([]byte, error) { // UnmarshalBinary implements encoding.BinaryUnmarshaler. func (s *TrustLineEntryV1) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } @@ -4871,8 +4955,7 @@ var ( _ encoding.BinaryUnmarshaler = (*TrustLineEntryV1)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. +// xdrType signals that this type represents XDR values defined by this package. func (s TrustLineEntryV1) xdrType() {} var _ xdrType = (*TrustLineEntryV1)(nil) @@ -4930,7 +5013,7 @@ func NewTrustLineEntryExt(v int32, value interface{}) (result TrustLineEntryExt, case 1: tv, ok := value.(TrustLineEntryV1) if !ok { - err = fmt.Errorf("invalid value, must be TrustLineEntryV1") + err = errors.New("invalid value, must be TrustLineEntryV1") return } result.V1 = &tv @@ -4985,13 +5068,17 @@ func (u TrustLineEntryExt) EncodeTo(e *xdr.Encoder) error { var _ decoderFrom = (*TrustLineEntryExt)(nil) // DecodeFrom decodes this value using the Decoder. -func (u *TrustLineEntryExt) DecodeFrom(d *xdr.Decoder) (int, error) { +func (u *TrustLineEntryExt) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding TrustLineEntryExt: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int u.V, nTmp, err = d.DecodeInt() n += nTmp if err != nil { - return n, fmt.Errorf("decoding Int: %s", err) + return n, fmt.Errorf("decoding Int: %w", err) } switch int32(u.V) { case 0: @@ -4999,10 +5086,10 @@ func (u *TrustLineEntryExt) DecodeFrom(d *xdr.Decoder) (int, error) { return n, nil case 1: u.V1 = new(TrustLineEntryV1) - nTmp, err = (*u.V1).DecodeFrom(d) + nTmp, err = (*u.V1).DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding TrustLineEntryV1: %s", err) + return n, fmt.Errorf("decoding TrustLineEntryV1: %w", err) } return n, nil } @@ -5020,8 +5107,10 @@ func (s TrustLineEntryExt) MarshalBinary() ([]byte, error) { // UnmarshalBinary implements encoding.BinaryUnmarshaler. func (s *TrustLineEntryExt) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } @@ -5030,8 +5119,7 @@ var ( _ encoding.BinaryUnmarshaler = (*TrustLineEntryExt)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. +// xdrType signals that this type represents XDR values defined by this package. func (s TrustLineEntryExt) xdrType() {} var _ xdrType = (*TrustLineEntryExt)(nil) @@ -5106,38 +5194,42 @@ func (s *TrustLineEntry) EncodeTo(e *xdr.Encoder) error { var _ decoderFrom = (*TrustLineEntry)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *TrustLineEntry) DecodeFrom(d *xdr.Decoder) (int, error) { +func (s *TrustLineEntry) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding TrustLineEntry: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = s.AccountId.DecodeFrom(d) + nTmp, err = s.AccountId.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding AccountId: %s", err) + return n, fmt.Errorf("decoding AccountId: %w", err) } - nTmp, err = s.Asset.DecodeFrom(d) + nTmp, err = s.Asset.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding TrustLineAsset: %s", err) + return n, fmt.Errorf("decoding TrustLineAsset: %w", err) } - nTmp, err = s.Balance.DecodeFrom(d) + nTmp, err = s.Balance.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Int64: %s", err) + return n, fmt.Errorf("decoding Int64: %w", err) } - nTmp, err = s.Limit.DecodeFrom(d) + nTmp, err = s.Limit.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Int64: %s", err) + return n, fmt.Errorf("decoding Int64: %w", err) } - nTmp, err = s.Flags.DecodeFrom(d) + nTmp, err = s.Flags.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Uint32: %s", err) + return n, fmt.Errorf("decoding Uint32: %w", err) } - nTmp, err = s.Ext.DecodeFrom(d) + nTmp, err = s.Ext.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding TrustLineEntryExt: %s", err) + return n, fmt.Errorf("decoding TrustLineEntryExt: %w", err) } return n, nil } @@ -5153,8 +5245,10 @@ func (s TrustLineEntry) MarshalBinary() ([]byte, error) { // UnmarshalBinary implements encoding.BinaryUnmarshaler. func (s *TrustLineEntry) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } @@ -5163,8 +5257,7 @@ var ( _ encoding.BinaryUnmarshaler = (*TrustLineEntry)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. +// xdrType signals that this type represents XDR values defined by this package. func (s TrustLineEntry) xdrType() {} var _ xdrType = (*TrustLineEntry)(nil) @@ -5212,10 +5305,14 @@ func (e OfferEntryFlags) EncodeTo(enc *xdr.Encoder) error { var _ decoderFrom = (*OfferEntryFlags)(nil) // DecodeFrom decodes this value using the Decoder. -func (e *OfferEntryFlags) DecodeFrom(d *xdr.Decoder) (int, error) { +func (e *OfferEntryFlags) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding OfferEntryFlags: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 v, n, err := d.DecodeInt() if err != nil { - return n, fmt.Errorf("decoding OfferEntryFlags: %s", err) + return n, fmt.Errorf("decoding OfferEntryFlags: %w", err) } if _, ok := offerEntryFlagsMap[v]; !ok { return n, fmt.Errorf("'%d' is not a valid OfferEntryFlags enum value", v) @@ -5235,8 +5332,10 @@ func (s OfferEntryFlags) MarshalBinary() ([]byte, error) { // UnmarshalBinary implements encoding.BinaryUnmarshaler. func (s *OfferEntryFlags) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } @@ -5245,8 +5344,7 @@ var ( _ encoding.BinaryUnmarshaler = (*OfferEntryFlags)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. +// xdrType signals that this type represents XDR values defined by this package. func (s OfferEntryFlags) xdrType() {} var _ xdrType = (*OfferEntryFlags)(nil) @@ -5310,13 +5408,17 @@ func (u OfferEntryExt) EncodeTo(e *xdr.Encoder) error { var _ decoderFrom = (*OfferEntryExt)(nil) // DecodeFrom decodes this value using the Decoder. -func (u *OfferEntryExt) DecodeFrom(d *xdr.Decoder) (int, error) { +func (u *OfferEntryExt) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding OfferEntryExt: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int u.V, nTmp, err = d.DecodeInt() n += nTmp if err != nil { - return n, fmt.Errorf("decoding Int: %s", err) + return n, fmt.Errorf("decoding Int: %w", err) } switch int32(u.V) { case 0: @@ -5337,8 +5439,10 @@ func (s OfferEntryExt) MarshalBinary() ([]byte, error) { // UnmarshalBinary implements encoding.BinaryUnmarshaler. func (s *OfferEntryExt) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } @@ -5347,8 +5451,7 @@ var ( _ encoding.BinaryUnmarshaler = (*OfferEntryExt)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. +// xdrType signals that this type represents XDR values defined by this package. func (s OfferEntryExt) xdrType() {} var _ xdrType = (*OfferEntryExt)(nil) @@ -5423,48 +5526,52 @@ func (s *OfferEntry) EncodeTo(e *xdr.Encoder) error { var _ decoderFrom = (*OfferEntry)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *OfferEntry) DecodeFrom(d *xdr.Decoder) (int, error) { +func (s *OfferEntry) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding OfferEntry: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = s.SellerId.DecodeFrom(d) + nTmp, err = s.SellerId.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding AccountId: %s", err) + return n, fmt.Errorf("decoding AccountId: %w", err) } - nTmp, err = s.OfferId.DecodeFrom(d) + nTmp, err = s.OfferId.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Int64: %s", err) + return n, fmt.Errorf("decoding Int64: %w", err) } - nTmp, err = s.Selling.DecodeFrom(d) + nTmp, err = s.Selling.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Asset: %s", err) + return n, fmt.Errorf("decoding Asset: %w", err) } - nTmp, err = s.Buying.DecodeFrom(d) + nTmp, err = s.Buying.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Asset: %s", err) + return n, fmt.Errorf("decoding Asset: %w", err) } - nTmp, err = s.Amount.DecodeFrom(d) + nTmp, err = s.Amount.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Int64: %s", err) + return n, fmt.Errorf("decoding Int64: %w", err) } - nTmp, err = s.Price.DecodeFrom(d) + nTmp, err = s.Price.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Price: %s", err) + return n, fmt.Errorf("decoding Price: %w", err) } - nTmp, err = s.Flags.DecodeFrom(d) + nTmp, err = s.Flags.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Uint32: %s", err) + return n, fmt.Errorf("decoding Uint32: %w", err) } - nTmp, err = s.Ext.DecodeFrom(d) + nTmp, err = s.Ext.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding OfferEntryExt: %s", err) + return n, fmt.Errorf("decoding OfferEntryExt: %w", err) } return n, nil } @@ -5480,8 +5587,10 @@ func (s OfferEntry) MarshalBinary() ([]byte, error) { // UnmarshalBinary implements encoding.BinaryUnmarshaler. func (s *OfferEntry) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } @@ -5490,8 +5599,7 @@ var ( _ encoding.BinaryUnmarshaler = (*OfferEntry)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. +// xdrType signals that this type represents XDR values defined by this package. func (s OfferEntry) xdrType() {} var _ xdrType = (*OfferEntry)(nil) @@ -5550,13 +5658,17 @@ func (u DataEntryExt) EncodeTo(e *xdr.Encoder) error { var _ decoderFrom = (*DataEntryExt)(nil) // DecodeFrom decodes this value using the Decoder. -func (u *DataEntryExt) DecodeFrom(d *xdr.Decoder) (int, error) { +func (u *DataEntryExt) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding DataEntryExt: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int u.V, nTmp, err = d.DecodeInt() n += nTmp if err != nil { - return n, fmt.Errorf("decoding Int: %s", err) + return n, fmt.Errorf("decoding Int: %w", err) } switch int32(u.V) { case 0: @@ -5577,8 +5689,10 @@ func (s DataEntryExt) MarshalBinary() ([]byte, error) { // UnmarshalBinary implements encoding.BinaryUnmarshaler. func (s *DataEntryExt) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } @@ -5587,8 +5701,7 @@ var ( _ encoding.BinaryUnmarshaler = (*DataEntryExt)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. +// xdrType signals that this type represents XDR values defined by this package. func (s DataEntryExt) xdrType() {} var _ xdrType = (*DataEntryExt)(nil) @@ -5637,28 +5750,32 @@ func (s *DataEntry) EncodeTo(e *xdr.Encoder) error { var _ decoderFrom = (*DataEntry)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *DataEntry) DecodeFrom(d *xdr.Decoder) (int, error) { +func (s *DataEntry) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding DataEntry: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = s.AccountId.DecodeFrom(d) + nTmp, err = s.AccountId.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding AccountId: %s", err) + return n, fmt.Errorf("decoding AccountId: %w", err) } - nTmp, err = s.DataName.DecodeFrom(d) + nTmp, err = s.DataName.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding String64: %s", err) + return n, fmt.Errorf("decoding String64: %w", err) } - nTmp, err = s.DataValue.DecodeFrom(d) + nTmp, err = s.DataValue.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding DataValue: %s", err) + return n, fmt.Errorf("decoding DataValue: %w", err) } - nTmp, err = s.Ext.DecodeFrom(d) + nTmp, err = s.Ext.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding DataEntryExt: %s", err) + return n, fmt.Errorf("decoding DataEntryExt: %w", err) } return n, nil } @@ -5674,8 +5791,10 @@ func (s DataEntry) MarshalBinary() ([]byte, error) { // UnmarshalBinary implements encoding.BinaryUnmarshaler. func (s *DataEntry) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } @@ -5684,8 +5803,7 @@ var ( _ encoding.BinaryUnmarshaler = (*DataEntry)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. +// xdrType signals that this type represents XDR values defined by this package. func (s DataEntry) xdrType() {} var _ xdrType = (*DataEntry)(nil) @@ -5746,10 +5864,14 @@ func (e ClaimPredicateType) EncodeTo(enc *xdr.Encoder) error { var _ decoderFrom = (*ClaimPredicateType)(nil) // DecodeFrom decodes this value using the Decoder. -func (e *ClaimPredicateType) DecodeFrom(d *xdr.Decoder) (int, error) { +func (e *ClaimPredicateType) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding ClaimPredicateType: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 v, n, err := d.DecodeInt() if err != nil { - return n, fmt.Errorf("decoding ClaimPredicateType: %s", err) + return n, fmt.Errorf("decoding ClaimPredicateType: %w", err) } if _, ok := claimPredicateTypeMap[v]; !ok { return n, fmt.Errorf("'%d' is not a valid ClaimPredicateType enum value", v) @@ -5769,8 +5891,10 @@ func (s ClaimPredicateType) MarshalBinary() ([]byte, error) { // UnmarshalBinary implements encoding.BinaryUnmarshaler. func (s *ClaimPredicateType) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } @@ -5779,8 +5903,7 @@ var ( _ encoding.BinaryUnmarshaler = (*ClaimPredicateType)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. +// xdrType signals that this type represents XDR values defined by this package. func (s ClaimPredicateType) xdrType() {} var _ xdrType = (*ClaimPredicateType)(nil) @@ -5847,35 +5970,35 @@ func NewClaimPredicate(aType ClaimPredicateType, value interface{}) (result Clai case ClaimPredicateTypeClaimPredicateAnd: tv, ok := value.([]ClaimPredicate) if !ok { - err = fmt.Errorf("invalid value, must be []ClaimPredicate") + err = errors.New("invalid value, must be []ClaimPredicate") return } result.AndPredicates = &tv case ClaimPredicateTypeClaimPredicateOr: tv, ok := value.([]ClaimPredicate) if !ok { - err = fmt.Errorf("invalid value, must be []ClaimPredicate") + err = errors.New("invalid value, must be []ClaimPredicate") return } result.OrPredicates = &tv case ClaimPredicateTypeClaimPredicateNot: tv, ok := value.(*ClaimPredicate) if !ok { - err = fmt.Errorf("invalid value, must be *ClaimPredicate") + err = errors.New("invalid value, must be *ClaimPredicate") return } result.NotPredicate = &tv case ClaimPredicateTypeClaimPredicateBeforeAbsoluteTime: tv, ok := value.(Int64) if !ok { - err = fmt.Errorf("invalid value, must be Int64") + err = errors.New("invalid value, must be Int64") return } result.AbsBefore = &tv case ClaimPredicateTypeClaimPredicateBeforeRelativeTime: tv, ok := value.(Int64) if !ok { - err = fmt.Errorf("invalid value, must be Int64") + err = errors.New("invalid value, must be Int64") return } result.RelBefore = &tv @@ -6065,13 +6188,17 @@ func (u ClaimPredicate) EncodeTo(e *xdr.Encoder) error { var _ decoderFrom = (*ClaimPredicate)(nil) // DecodeFrom decodes this value using the Decoder. -func (u *ClaimPredicate) DecodeFrom(d *xdr.Decoder) (int, error) { +func (u *ClaimPredicate) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding ClaimPredicate: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = u.Type.DecodeFrom(d) + nTmp, err = u.Type.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding ClaimPredicateType: %s", err) + return n, fmt.Errorf("decoding ClaimPredicateType: %w", err) } switch ClaimPredicateType(u.Type) { case ClaimPredicateTypeClaimPredicateUnconditional: @@ -6083,19 +6210,22 @@ func (u *ClaimPredicate) DecodeFrom(d *xdr.Decoder) (int, error) { l, nTmp, err = d.DecodeUint() n += nTmp if err != nil { - return n, fmt.Errorf("decoding ClaimPredicate: %s", err) + return n, fmt.Errorf("decoding ClaimPredicate: %w", err) } if l > 2 { return n, fmt.Errorf("decoding ClaimPredicate: data size (%d) exceeds size limit (2)", l) } (*u.AndPredicates) = nil if l > 0 { + if il, ok := d.InputLen(); ok && uint(il) < uint(l) { + return n, fmt.Errorf("decoding ClaimPredicate: length (%d) exceeds remaining input length (%d)", l, il) + } (*u.AndPredicates) = make([]ClaimPredicate, l) for i := uint32(0); i < l; i++ { - nTmp, err = (*u.AndPredicates)[i].DecodeFrom(d) + nTmp, err = (*u.AndPredicates)[i].DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding ClaimPredicate: %s", err) + return n, fmt.Errorf("decoding ClaimPredicate: %w", err) } } } @@ -6106,19 +6236,22 @@ func (u *ClaimPredicate) DecodeFrom(d *xdr.Decoder) (int, error) { l, nTmp, err = d.DecodeUint() n += nTmp if err != nil { - return n, fmt.Errorf("decoding ClaimPredicate: %s", err) + return n, fmt.Errorf("decoding ClaimPredicate: %w", err) } if l > 2 { return n, fmt.Errorf("decoding ClaimPredicate: data size (%d) exceeds size limit (2)", l) } (*u.OrPredicates) = nil if l > 0 { + if il, ok := d.InputLen(); ok && uint(il) < uint(l) { + return n, fmt.Errorf("decoding ClaimPredicate: length (%d) exceeds remaining input length (%d)", l, il) + } (*u.OrPredicates) = make([]ClaimPredicate, l) for i := uint32(0); i < l; i++ { - nTmp, err = (*u.OrPredicates)[i].DecodeFrom(d) + nTmp, err = (*u.OrPredicates)[i].DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding ClaimPredicate: %s", err) + return n, fmt.Errorf("decoding ClaimPredicate: %w", err) } } } @@ -6129,32 +6262,32 @@ func (u *ClaimPredicate) DecodeFrom(d *xdr.Decoder) (int, error) { b, nTmp, err = d.DecodeBool() n += nTmp if err != nil { - return n, fmt.Errorf("decoding ClaimPredicate: %s", err) + return n, fmt.Errorf("decoding ClaimPredicate: %w", err) } (*u.NotPredicate) = nil if b { (*u.NotPredicate) = new(ClaimPredicate) - nTmp, err = (*u.NotPredicate).DecodeFrom(d) + nTmp, err = (*u.NotPredicate).DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding ClaimPredicate: %s", err) + return n, fmt.Errorf("decoding ClaimPredicate: %w", err) } } return n, nil case ClaimPredicateTypeClaimPredicateBeforeAbsoluteTime: u.AbsBefore = new(Int64) - nTmp, err = (*u.AbsBefore).DecodeFrom(d) + nTmp, err = (*u.AbsBefore).DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Int64: %s", err) + return n, fmt.Errorf("decoding Int64: %w", err) } return n, nil case ClaimPredicateTypeClaimPredicateBeforeRelativeTime: u.RelBefore = new(Int64) - nTmp, err = (*u.RelBefore).DecodeFrom(d) + nTmp, err = (*u.RelBefore).DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Int64: %s", err) + return n, fmt.Errorf("decoding Int64: %w", err) } return n, nil } @@ -6172,8 +6305,10 @@ func (s ClaimPredicate) MarshalBinary() ([]byte, error) { // UnmarshalBinary implements encoding.BinaryUnmarshaler. func (s *ClaimPredicate) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } @@ -6182,8 +6317,7 @@ var ( _ encoding.BinaryUnmarshaler = (*ClaimPredicate)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. +// xdrType signals that this type represents XDR values defined by this package. func (s ClaimPredicate) xdrType() {} var _ xdrType = (*ClaimPredicate)(nil) @@ -6229,10 +6363,14 @@ func (e ClaimantType) EncodeTo(enc *xdr.Encoder) error { var _ decoderFrom = (*ClaimantType)(nil) // DecodeFrom decodes this value using the Decoder. -func (e *ClaimantType) DecodeFrom(d *xdr.Decoder) (int, error) { +func (e *ClaimantType) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding ClaimantType: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 v, n, err := d.DecodeInt() if err != nil { - return n, fmt.Errorf("decoding ClaimantType: %s", err) + return n, fmt.Errorf("decoding ClaimantType: %w", err) } if _, ok := claimantTypeMap[v]; !ok { return n, fmt.Errorf("'%d' is not a valid ClaimantType enum value", v) @@ -6252,8 +6390,10 @@ func (s ClaimantType) MarshalBinary() ([]byte, error) { // UnmarshalBinary implements encoding.BinaryUnmarshaler. func (s *ClaimantType) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } @@ -6262,8 +6402,7 @@ var ( _ encoding.BinaryUnmarshaler = (*ClaimantType)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. +// xdrType signals that this type represents XDR values defined by this package. func (s ClaimantType) xdrType() {} var _ xdrType = (*ClaimantType)(nil) @@ -6295,18 +6434,22 @@ func (s *ClaimantV0) EncodeTo(e *xdr.Encoder) error { var _ decoderFrom = (*ClaimantV0)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *ClaimantV0) DecodeFrom(d *xdr.Decoder) (int, error) { +func (s *ClaimantV0) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding ClaimantV0: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = s.Destination.DecodeFrom(d) + nTmp, err = s.Destination.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding AccountId: %s", err) + return n, fmt.Errorf("decoding AccountId: %w", err) } - nTmp, err = s.Predicate.DecodeFrom(d) + nTmp, err = s.Predicate.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding ClaimPredicate: %s", err) + return n, fmt.Errorf("decoding ClaimPredicate: %w", err) } return n, nil } @@ -6322,8 +6465,10 @@ func (s ClaimantV0) MarshalBinary() ([]byte, error) { // UnmarshalBinary implements encoding.BinaryUnmarshaler. func (s *ClaimantV0) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } @@ -6332,8 +6477,7 @@ var ( _ encoding.BinaryUnmarshaler = (*ClaimantV0)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. +// xdrType signals that this type represents XDR values defined by this package. func (s ClaimantV0) xdrType() {} var _ xdrType = (*ClaimantV0)(nil) @@ -6377,7 +6521,7 @@ func NewClaimant(aType ClaimantType, value interface{}) (result Claimant, err er case ClaimantTypeClaimantTypeV0: tv, ok := value.(ClaimantV0) if !ok { - err = fmt.Errorf("invalid value, must be ClaimantV0") + err = errors.New("invalid value, must be ClaimantV0") return } result.V0 = &tv @@ -6429,21 +6573,25 @@ func (u Claimant) EncodeTo(e *xdr.Encoder) error { var _ decoderFrom = (*Claimant)(nil) // DecodeFrom decodes this value using the Decoder. -func (u *Claimant) DecodeFrom(d *xdr.Decoder) (int, error) { +func (u *Claimant) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding Claimant: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = u.Type.DecodeFrom(d) + nTmp, err = u.Type.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding ClaimantType: %s", err) + return n, fmt.Errorf("decoding ClaimantType: %w", err) } switch ClaimantType(u.Type) { case ClaimantTypeClaimantTypeV0: u.V0 = new(ClaimantV0) - nTmp, err = (*u.V0).DecodeFrom(d) + nTmp, err = (*u.V0).DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding ClaimantV0: %s", err) + return n, fmt.Errorf("decoding ClaimantV0: %w", err) } return n, nil } @@ -6461,8 +6609,10 @@ func (s Claimant) MarshalBinary() ([]byte, error) { // UnmarshalBinary implements encoding.BinaryUnmarshaler. func (s *Claimant) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } @@ -6471,8 +6621,7 @@ var ( _ encoding.BinaryUnmarshaler = (*Claimant)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. +// xdrType signals that this type represents XDR values defined by this package. func (s Claimant) xdrType() {} var _ xdrType = (*Claimant)(nil) @@ -6518,10 +6667,14 @@ func (e ClaimableBalanceIdType) EncodeTo(enc *xdr.Encoder) error { var _ decoderFrom = (*ClaimableBalanceIdType)(nil) // DecodeFrom decodes this value using the Decoder. -func (e *ClaimableBalanceIdType) DecodeFrom(d *xdr.Decoder) (int, error) { +func (e *ClaimableBalanceIdType) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding ClaimableBalanceIdType: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 v, n, err := d.DecodeInt() if err != nil { - return n, fmt.Errorf("decoding ClaimableBalanceIdType: %s", err) + return n, fmt.Errorf("decoding ClaimableBalanceIdType: %w", err) } if _, ok := claimableBalanceIdTypeMap[v]; !ok { return n, fmt.Errorf("'%d' is not a valid ClaimableBalanceIdType enum value", v) @@ -6541,8 +6694,10 @@ func (s ClaimableBalanceIdType) MarshalBinary() ([]byte, error) { // UnmarshalBinary implements encoding.BinaryUnmarshaler. func (s *ClaimableBalanceIdType) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } @@ -6551,8 +6706,7 @@ var ( _ encoding.BinaryUnmarshaler = (*ClaimableBalanceIdType)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. +// xdrType signals that this type represents XDR values defined by this package. func (s ClaimableBalanceIdType) xdrType() {} var _ xdrType = (*ClaimableBalanceIdType)(nil) @@ -6592,7 +6746,7 @@ func NewClaimableBalanceId(aType ClaimableBalanceIdType, value interface{}) (res case ClaimableBalanceIdTypeClaimableBalanceIdTypeV0: tv, ok := value.(Hash) if !ok { - err = fmt.Errorf("invalid value, must be Hash") + err = errors.New("invalid value, must be Hash") return } result.V0 = &tv @@ -6644,21 +6798,25 @@ func (u ClaimableBalanceId) EncodeTo(e *xdr.Encoder) error { var _ decoderFrom = (*ClaimableBalanceId)(nil) // DecodeFrom decodes this value using the Decoder. -func (u *ClaimableBalanceId) DecodeFrom(d *xdr.Decoder) (int, error) { +func (u *ClaimableBalanceId) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding ClaimableBalanceId: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = u.Type.DecodeFrom(d) + nTmp, err = u.Type.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding ClaimableBalanceIdType: %s", err) + return n, fmt.Errorf("decoding ClaimableBalanceIdType: %w", err) } switch ClaimableBalanceIdType(u.Type) { case ClaimableBalanceIdTypeClaimableBalanceIdTypeV0: u.V0 = new(Hash) - nTmp, err = (*u.V0).DecodeFrom(d) + nTmp, err = (*u.V0).DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Hash: %s", err) + return n, fmt.Errorf("decoding Hash: %w", err) } return n, nil } @@ -6676,8 +6834,10 @@ func (s ClaimableBalanceId) MarshalBinary() ([]byte, error) { // UnmarshalBinary implements encoding.BinaryUnmarshaler. func (s *ClaimableBalanceId) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } @@ -6686,8 +6846,7 @@ var ( _ encoding.BinaryUnmarshaler = (*ClaimableBalanceId)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. +// xdrType signals that this type represents XDR values defined by this package. func (s ClaimableBalanceId) xdrType() {} var _ xdrType = (*ClaimableBalanceId)(nil) @@ -6735,10 +6894,14 @@ func (e ClaimableBalanceFlags) EncodeTo(enc *xdr.Encoder) error { var _ decoderFrom = (*ClaimableBalanceFlags)(nil) // DecodeFrom decodes this value using the Decoder. -func (e *ClaimableBalanceFlags) DecodeFrom(d *xdr.Decoder) (int, error) { +func (e *ClaimableBalanceFlags) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding ClaimableBalanceFlags: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 v, n, err := d.DecodeInt() if err != nil { - return n, fmt.Errorf("decoding ClaimableBalanceFlags: %s", err) + return n, fmt.Errorf("decoding ClaimableBalanceFlags: %w", err) } if _, ok := claimableBalanceFlagsMap[v]; !ok { return n, fmt.Errorf("'%d' is not a valid ClaimableBalanceFlags enum value", v) @@ -6758,8 +6921,10 @@ func (s ClaimableBalanceFlags) MarshalBinary() ([]byte, error) { // UnmarshalBinary implements encoding.BinaryUnmarshaler. func (s *ClaimableBalanceFlags) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } @@ -6768,8 +6933,7 @@ var ( _ encoding.BinaryUnmarshaler = (*ClaimableBalanceFlags)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. +// xdrType signals that this type represents XDR values defined by this package. func (s ClaimableBalanceFlags) xdrType() {} var _ xdrType = (*ClaimableBalanceFlags)(nil) @@ -6833,13 +6997,17 @@ func (u ClaimableBalanceEntryExtensionV1Ext) EncodeTo(e *xdr.Encoder) error { var _ decoderFrom = (*ClaimableBalanceEntryExtensionV1Ext)(nil) // DecodeFrom decodes this value using the Decoder. -func (u *ClaimableBalanceEntryExtensionV1Ext) DecodeFrom(d *xdr.Decoder) (int, error) { +func (u *ClaimableBalanceEntryExtensionV1Ext) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding ClaimableBalanceEntryExtensionV1Ext: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int u.V, nTmp, err = d.DecodeInt() n += nTmp if err != nil { - return n, fmt.Errorf("decoding Int: %s", err) + return n, fmt.Errorf("decoding Int: %w", err) } switch int32(u.V) { case 0: @@ -6860,8 +7028,10 @@ func (s ClaimableBalanceEntryExtensionV1Ext) MarshalBinary() ([]byte, error) { // UnmarshalBinary implements encoding.BinaryUnmarshaler. func (s *ClaimableBalanceEntryExtensionV1Ext) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } @@ -6870,8 +7040,7 @@ var ( _ encoding.BinaryUnmarshaler = (*ClaimableBalanceEntryExtensionV1Ext)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. +// xdrType signals that this type represents XDR values defined by this package. func (s ClaimableBalanceEntryExtensionV1Ext) xdrType() {} var _ xdrType = (*ClaimableBalanceEntryExtensionV1Ext)(nil) @@ -6909,18 +7078,22 @@ func (s *ClaimableBalanceEntryExtensionV1) EncodeTo(e *xdr.Encoder) error { var _ decoderFrom = (*ClaimableBalanceEntryExtensionV1)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *ClaimableBalanceEntryExtensionV1) DecodeFrom(d *xdr.Decoder) (int, error) { +func (s *ClaimableBalanceEntryExtensionV1) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding ClaimableBalanceEntryExtensionV1: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = s.Ext.DecodeFrom(d) + nTmp, err = s.Ext.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding ClaimableBalanceEntryExtensionV1Ext: %s", err) + return n, fmt.Errorf("decoding ClaimableBalanceEntryExtensionV1Ext: %w", err) } - nTmp, err = s.Flags.DecodeFrom(d) + nTmp, err = s.Flags.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Uint32: %s", err) + return n, fmt.Errorf("decoding Uint32: %w", err) } return n, nil } @@ -6936,8 +7109,10 @@ func (s ClaimableBalanceEntryExtensionV1) MarshalBinary() ([]byte, error) { // UnmarshalBinary implements encoding.BinaryUnmarshaler. func (s *ClaimableBalanceEntryExtensionV1) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } @@ -6946,8 +7121,7 @@ var ( _ encoding.BinaryUnmarshaler = (*ClaimableBalanceEntryExtensionV1)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. +// xdrType signals that this type represents XDR values defined by this package. func (s ClaimableBalanceEntryExtensionV1) xdrType() {} var _ xdrType = (*ClaimableBalanceEntryExtensionV1)(nil) @@ -6993,7 +7167,7 @@ func NewClaimableBalanceEntryExt(v int32, value interface{}) (result ClaimableBa case 1: tv, ok := value.(ClaimableBalanceEntryExtensionV1) if !ok { - err = fmt.Errorf("invalid value, must be ClaimableBalanceEntryExtensionV1") + err = errors.New("invalid value, must be ClaimableBalanceEntryExtensionV1") return } result.V1 = &tv @@ -7048,13 +7222,17 @@ func (u ClaimableBalanceEntryExt) EncodeTo(e *xdr.Encoder) error { var _ decoderFrom = (*ClaimableBalanceEntryExt)(nil) // DecodeFrom decodes this value using the Decoder. -func (u *ClaimableBalanceEntryExt) DecodeFrom(d *xdr.Decoder) (int, error) { +func (u *ClaimableBalanceEntryExt) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding ClaimableBalanceEntryExt: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int u.V, nTmp, err = d.DecodeInt() n += nTmp if err != nil { - return n, fmt.Errorf("decoding Int: %s", err) + return n, fmt.Errorf("decoding Int: %w", err) } switch int32(u.V) { case 0: @@ -7062,10 +7240,10 @@ func (u *ClaimableBalanceEntryExt) DecodeFrom(d *xdr.Decoder) (int, error) { return n, nil case 1: u.V1 = new(ClaimableBalanceEntryExtensionV1) - nTmp, err = (*u.V1).DecodeFrom(d) + nTmp, err = (*u.V1).DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding ClaimableBalanceEntryExtensionV1: %s", err) + return n, fmt.Errorf("decoding ClaimableBalanceEntryExtensionV1: %w", err) } return n, nil } @@ -7083,8 +7261,10 @@ func (s ClaimableBalanceEntryExt) MarshalBinary() ([]byte, error) { // UnmarshalBinary implements encoding.BinaryUnmarshaler. func (s *ClaimableBalanceEntryExt) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } @@ -7093,8 +7273,7 @@ var ( _ encoding.BinaryUnmarshaler = (*ClaimableBalanceEntryExt)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. +// xdrType signals that this type represents XDR values defined by this package. func (s ClaimableBalanceEntryExt) xdrType() {} var _ xdrType = (*ClaimableBalanceEntryExt)(nil) @@ -7162,48 +7341,55 @@ func (s *ClaimableBalanceEntry) EncodeTo(e *xdr.Encoder) error { var _ decoderFrom = (*ClaimableBalanceEntry)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *ClaimableBalanceEntry) DecodeFrom(d *xdr.Decoder) (int, error) { +func (s *ClaimableBalanceEntry) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding ClaimableBalanceEntry: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = s.BalanceId.DecodeFrom(d) + nTmp, err = s.BalanceId.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding ClaimableBalanceId: %s", err) + return n, fmt.Errorf("decoding ClaimableBalanceId: %w", err) } var l uint32 l, nTmp, err = d.DecodeUint() n += nTmp if err != nil { - return n, fmt.Errorf("decoding Claimant: %s", err) + return n, fmt.Errorf("decoding Claimant: %w", err) } if l > 10 { return n, fmt.Errorf("decoding Claimant: data size (%d) exceeds size limit (10)", l) } s.Claimants = nil if l > 0 { + if il, ok := d.InputLen(); ok && uint(il) < uint(l) { + return n, fmt.Errorf("decoding Claimant: length (%d) exceeds remaining input length (%d)", l, il) + } s.Claimants = make([]Claimant, l) for i := uint32(0); i < l; i++ { - nTmp, err = s.Claimants[i].DecodeFrom(d) + nTmp, err = s.Claimants[i].DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Claimant: %s", err) + return n, fmt.Errorf("decoding Claimant: %w", err) } } } - nTmp, err = s.Asset.DecodeFrom(d) + nTmp, err = s.Asset.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Asset: %s", err) + return n, fmt.Errorf("decoding Asset: %w", err) } - nTmp, err = s.Amount.DecodeFrom(d) + nTmp, err = s.Amount.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Int64: %s", err) + return n, fmt.Errorf("decoding Int64: %w", err) } - nTmp, err = s.Ext.DecodeFrom(d) + nTmp, err = s.Ext.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding ClaimableBalanceEntryExt: %s", err) + return n, fmt.Errorf("decoding ClaimableBalanceEntryExt: %w", err) } return n, nil } @@ -7219,8 +7405,10 @@ func (s ClaimableBalanceEntry) MarshalBinary() ([]byte, error) { // UnmarshalBinary implements encoding.BinaryUnmarshaler. func (s *ClaimableBalanceEntry) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } @@ -7229,8 +7417,7 @@ var ( _ encoding.BinaryUnmarshaler = (*ClaimableBalanceEntry)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. +// xdrType signals that this type represents XDR values defined by this package. func (s ClaimableBalanceEntry) xdrType() {} var _ xdrType = (*ClaimableBalanceEntry)(nil) @@ -7267,23 +7454,27 @@ func (s *LiquidityPoolConstantProductParameters) EncodeTo(e *xdr.Encoder) error var _ decoderFrom = (*LiquidityPoolConstantProductParameters)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *LiquidityPoolConstantProductParameters) DecodeFrom(d *xdr.Decoder) (int, error) { +func (s *LiquidityPoolConstantProductParameters) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding LiquidityPoolConstantProductParameters: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = s.AssetA.DecodeFrom(d) + nTmp, err = s.AssetA.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Asset: %s", err) + return n, fmt.Errorf("decoding Asset: %w", err) } - nTmp, err = s.AssetB.DecodeFrom(d) + nTmp, err = s.AssetB.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Asset: %s", err) + return n, fmt.Errorf("decoding Asset: %w", err) } - nTmp, err = s.Fee.DecodeFrom(d) + nTmp, err = s.Fee.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Int32: %s", err) + return n, fmt.Errorf("decoding Int32: %w", err) } return n, nil } @@ -7299,8 +7490,10 @@ func (s LiquidityPoolConstantProductParameters) MarshalBinary() ([]byte, error) // UnmarshalBinary implements encoding.BinaryUnmarshaler. func (s *LiquidityPoolConstantProductParameters) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } @@ -7309,8 +7502,7 @@ var ( _ encoding.BinaryUnmarshaler = (*LiquidityPoolConstantProductParameters)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. +// xdrType signals that this type represents XDR values defined by this package. func (s LiquidityPoolConstantProductParameters) xdrType() {} var _ xdrType = (*LiquidityPoolConstantProductParameters)(nil) @@ -7359,33 +7551,37 @@ func (s *LiquidityPoolEntryConstantProduct) EncodeTo(e *xdr.Encoder) error { var _ decoderFrom = (*LiquidityPoolEntryConstantProduct)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *LiquidityPoolEntryConstantProduct) DecodeFrom(d *xdr.Decoder) (int, error) { +func (s *LiquidityPoolEntryConstantProduct) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding LiquidityPoolEntryConstantProduct: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = s.Params.DecodeFrom(d) + nTmp, err = s.Params.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding LiquidityPoolConstantProductParameters: %s", err) + return n, fmt.Errorf("decoding LiquidityPoolConstantProductParameters: %w", err) } - nTmp, err = s.ReserveA.DecodeFrom(d) + nTmp, err = s.ReserveA.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Int64: %s", err) + return n, fmt.Errorf("decoding Int64: %w", err) } - nTmp, err = s.ReserveB.DecodeFrom(d) + nTmp, err = s.ReserveB.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Int64: %s", err) + return n, fmt.Errorf("decoding Int64: %w", err) } - nTmp, err = s.TotalPoolShares.DecodeFrom(d) + nTmp, err = s.TotalPoolShares.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Int64: %s", err) + return n, fmt.Errorf("decoding Int64: %w", err) } - nTmp, err = s.PoolSharesTrustLineCount.DecodeFrom(d) + nTmp, err = s.PoolSharesTrustLineCount.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Int64: %s", err) + return n, fmt.Errorf("decoding Int64: %w", err) } return n, nil } @@ -7401,8 +7597,10 @@ func (s LiquidityPoolEntryConstantProduct) MarshalBinary() ([]byte, error) { // UnmarshalBinary implements encoding.BinaryUnmarshaler. func (s *LiquidityPoolEntryConstantProduct) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } @@ -7411,8 +7609,7 @@ var ( _ encoding.BinaryUnmarshaler = (*LiquidityPoolEntryConstantProduct)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. +// xdrType signals that this type represents XDR values defined by this package. func (s LiquidityPoolEntryConstantProduct) xdrType() {} var _ xdrType = (*LiquidityPoolEntryConstantProduct)(nil) @@ -7461,7 +7658,7 @@ func NewLiquidityPoolEntryBody(aType LiquidityPoolType, value interface{}) (resu case LiquidityPoolTypeLiquidityPoolConstantProduct: tv, ok := value.(LiquidityPoolEntryConstantProduct) if !ok { - err = fmt.Errorf("invalid value, must be LiquidityPoolEntryConstantProduct") + err = errors.New("invalid value, must be LiquidityPoolEntryConstantProduct") return } result.ConstantProduct = &tv @@ -7513,21 +7710,25 @@ func (u LiquidityPoolEntryBody) EncodeTo(e *xdr.Encoder) error { var _ decoderFrom = (*LiquidityPoolEntryBody)(nil) // DecodeFrom decodes this value using the Decoder. -func (u *LiquidityPoolEntryBody) DecodeFrom(d *xdr.Decoder) (int, error) { +func (u *LiquidityPoolEntryBody) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding LiquidityPoolEntryBody: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = u.Type.DecodeFrom(d) + nTmp, err = u.Type.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding LiquidityPoolType: %s", err) + return n, fmt.Errorf("decoding LiquidityPoolType: %w", err) } switch LiquidityPoolType(u.Type) { case LiquidityPoolTypeLiquidityPoolConstantProduct: u.ConstantProduct = new(LiquidityPoolEntryConstantProduct) - nTmp, err = (*u.ConstantProduct).DecodeFrom(d) + nTmp, err = (*u.ConstantProduct).DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding LiquidityPoolEntryConstantProduct: %s", err) + return n, fmt.Errorf("decoding LiquidityPoolEntryConstantProduct: %w", err) } return n, nil } @@ -7545,8 +7746,10 @@ func (s LiquidityPoolEntryBody) MarshalBinary() ([]byte, error) { // UnmarshalBinary implements encoding.BinaryUnmarshaler. func (s *LiquidityPoolEntryBody) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } @@ -7555,8 +7758,7 @@ var ( _ encoding.BinaryUnmarshaler = (*LiquidityPoolEntryBody)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. +// xdrType signals that this type represents XDR values defined by this package. func (s LiquidityPoolEntryBody) xdrType() {} var _ xdrType = (*LiquidityPoolEntryBody)(nil) @@ -7603,18 +7805,22 @@ func (s *LiquidityPoolEntry) EncodeTo(e *xdr.Encoder) error { var _ decoderFrom = (*LiquidityPoolEntry)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *LiquidityPoolEntry) DecodeFrom(d *xdr.Decoder) (int, error) { +func (s *LiquidityPoolEntry) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding LiquidityPoolEntry: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = s.LiquidityPoolId.DecodeFrom(d) + nTmp, err = s.LiquidityPoolId.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding PoolId: %s", err) + return n, fmt.Errorf("decoding PoolId: %w", err) } - nTmp, err = s.Body.DecodeFrom(d) + nTmp, err = s.Body.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding LiquidityPoolEntryBody: %s", err) + return n, fmt.Errorf("decoding LiquidityPoolEntryBody: %w", err) } return n, nil } @@ -7630,8 +7836,10 @@ func (s LiquidityPoolEntry) MarshalBinary() ([]byte, error) { // UnmarshalBinary implements encoding.BinaryUnmarshaler. func (s *LiquidityPoolEntry) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } @@ -7640,12 +7848,363 @@ var ( _ encoding.BinaryUnmarshaler = (*LiquidityPoolEntry)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. +// xdrType signals that this type represents XDR values defined by this package. func (s LiquidityPoolEntry) xdrType() {} var _ xdrType = (*LiquidityPoolEntry)(nil) +// ContractDataDurability is an XDR Enum defines as: +// +// enum ContractDataDurability { +// TEMPORARY = 0, +// PERSISTENT = 1 +// }; +type ContractDataDurability int32 + +const ( + ContractDataDurabilityTemporary ContractDataDurability = 0 + ContractDataDurabilityPersistent ContractDataDurability = 1 +) + +var contractDataDurabilityMap = map[int32]string{ + 0: "ContractDataDurabilityTemporary", + 1: "ContractDataDurabilityPersistent", +} + +// ValidEnum validates a proposed value for this enum. Implements +// the Enum interface for ContractDataDurability +func (e ContractDataDurability) ValidEnum(v int32) bool { + _, ok := contractDataDurabilityMap[v] + return ok +} + +// String returns the name of `e` +func (e ContractDataDurability) String() string { + name, _ := contractDataDurabilityMap[int32(e)] + return name +} + +// EncodeTo encodes this value using the Encoder. +func (e ContractDataDurability) EncodeTo(enc *xdr.Encoder) error { + if _, ok := contractDataDurabilityMap[int32(e)]; !ok { + return fmt.Errorf("'%d' is not a valid ContractDataDurability enum value", e) + } + _, err := enc.EncodeInt(int32(e)) + return err +} + +var _ decoderFrom = (*ContractDataDurability)(nil) + +// DecodeFrom decodes this value using the Decoder. +func (e *ContractDataDurability) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding ContractDataDurability: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + v, n, err := d.DecodeInt() + if err != nil { + return n, fmt.Errorf("decoding ContractDataDurability: %w", err) + } + if _, ok := contractDataDurabilityMap[v]; !ok { + return n, fmt.Errorf("'%d' is not a valid ContractDataDurability enum value", v) + } + *e = ContractDataDurability(v) + return n, nil +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (s ContractDataDurability) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *ContractDataDurability) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} + +var ( + _ encoding.BinaryMarshaler = (*ContractDataDurability)(nil) + _ encoding.BinaryUnmarshaler = (*ContractDataDurability)(nil) +) + +// xdrType signals that this type represents XDR values defined by this package. +func (s ContractDataDurability) xdrType() {} + +var _ xdrType = (*ContractDataDurability)(nil) + +// ContractDataEntry is an XDR Struct defines as: +// +// struct ContractDataEntry { +// ExtensionPoint ext; +// +// SCAddress contract; +// SCVal key; +// ContractDataDurability durability; +// SCVal val; +// }; +type ContractDataEntry struct { + Ext ExtensionPoint + Contract ScAddress + Key ScVal + Durability ContractDataDurability + Val ScVal +} + +// EncodeTo encodes this value using the Encoder. +func (s *ContractDataEntry) EncodeTo(e *xdr.Encoder) error { + var err error + if err = s.Ext.EncodeTo(e); err != nil { + return err + } + if err = s.Contract.EncodeTo(e); err != nil { + return err + } + if err = s.Key.EncodeTo(e); err != nil { + return err + } + if err = s.Durability.EncodeTo(e); err != nil { + return err + } + if err = s.Val.EncodeTo(e); err != nil { + return err + } + return nil +} + +var _ decoderFrom = (*ContractDataEntry)(nil) + +// DecodeFrom decodes this value using the Decoder. +func (s *ContractDataEntry) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding ContractDataEntry: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + var err error + var n, nTmp int + nTmp, err = s.Ext.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ExtensionPoint: %w", err) + } + nTmp, err = s.Contract.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ScAddress: %w", err) + } + nTmp, err = s.Key.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ScVal: %w", err) + } + nTmp, err = s.Durability.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ContractDataDurability: %w", err) + } + nTmp, err = s.Val.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ScVal: %w", err) + } + return n, nil +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (s ContractDataEntry) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *ContractDataEntry) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} + +var ( + _ encoding.BinaryMarshaler = (*ContractDataEntry)(nil) + _ encoding.BinaryUnmarshaler = (*ContractDataEntry)(nil) +) + +// xdrType signals that this type represents XDR values defined by this package. +func (s ContractDataEntry) xdrType() {} + +var _ xdrType = (*ContractDataEntry)(nil) + +// ContractCodeEntry is an XDR Struct defines as: +// +// struct ContractCodeEntry { +// ExtensionPoint ext; +// +// Hash hash; +// opaque code<>; +// }; +type ContractCodeEntry struct { + Ext ExtensionPoint + Hash Hash + Code []byte +} + +// EncodeTo encodes this value using the Encoder. +func (s *ContractCodeEntry) EncodeTo(e *xdr.Encoder) error { + var err error + if err = s.Ext.EncodeTo(e); err != nil { + return err + } + if err = s.Hash.EncodeTo(e); err != nil { + return err + } + if _, err = e.EncodeOpaque(s.Code[:]); err != nil { + return err + } + return nil +} + +var _ decoderFrom = (*ContractCodeEntry)(nil) + +// DecodeFrom decodes this value using the Decoder. +func (s *ContractCodeEntry) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding ContractCodeEntry: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + var err error + var n, nTmp int + nTmp, err = s.Ext.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ExtensionPoint: %w", err) + } + nTmp, err = s.Hash.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Hash: %w", err) + } + s.Code, nTmp, err = d.DecodeOpaque(0) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Code: %w", err) + } + return n, nil +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (s ContractCodeEntry) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *ContractCodeEntry) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} + +var ( + _ encoding.BinaryMarshaler = (*ContractCodeEntry)(nil) + _ encoding.BinaryUnmarshaler = (*ContractCodeEntry)(nil) +) + +// xdrType signals that this type represents XDR values defined by this package. +func (s ContractCodeEntry) xdrType() {} + +var _ xdrType = (*ContractCodeEntry)(nil) + +// TtlEntry is an XDR Struct defines as: +// +// struct TTLEntry { +// // Hash of the LedgerKey that is associated with this TTLEntry +// Hash keyHash; +// uint32 liveUntilLedgerSeq; +// }; +type TtlEntry struct { + KeyHash Hash + LiveUntilLedgerSeq Uint32 +} + +// EncodeTo encodes this value using the Encoder. +func (s *TtlEntry) EncodeTo(e *xdr.Encoder) error { + var err error + if err = s.KeyHash.EncodeTo(e); err != nil { + return err + } + if err = s.LiveUntilLedgerSeq.EncodeTo(e); err != nil { + return err + } + return nil +} + +var _ decoderFrom = (*TtlEntry)(nil) + +// DecodeFrom decodes this value using the Decoder. +func (s *TtlEntry) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding TtlEntry: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + var err error + var n, nTmp int + nTmp, err = s.KeyHash.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Hash: %w", err) + } + nTmp, err = s.LiveUntilLedgerSeq.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Uint32: %w", err) + } + return n, nil +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (s TtlEntry) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *TtlEntry) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} + +var ( + _ encoding.BinaryMarshaler = (*TtlEntry)(nil) + _ encoding.BinaryUnmarshaler = (*TtlEntry)(nil) +) + +// xdrType signals that this type represents XDR values defined by this package. +func (s TtlEntry) xdrType() {} + +var _ xdrType = (*TtlEntry)(nil) + // LedgerEntryExtensionV1Ext is an XDR NestedUnion defines as: // // union switch (int v) @@ -7700,13 +8259,17 @@ func (u LedgerEntryExtensionV1Ext) EncodeTo(e *xdr.Encoder) error { var _ decoderFrom = (*LedgerEntryExtensionV1Ext)(nil) // DecodeFrom decodes this value using the Decoder. -func (u *LedgerEntryExtensionV1Ext) DecodeFrom(d *xdr.Decoder) (int, error) { +func (u *LedgerEntryExtensionV1Ext) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding LedgerEntryExtensionV1Ext: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int u.V, nTmp, err = d.DecodeInt() n += nTmp if err != nil { - return n, fmt.Errorf("decoding Int: %s", err) + return n, fmt.Errorf("decoding Int: %w", err) } switch int32(u.V) { case 0: @@ -7727,8 +8290,10 @@ func (s LedgerEntryExtensionV1Ext) MarshalBinary() ([]byte, error) { // UnmarshalBinary implements encoding.BinaryUnmarshaler. func (s *LedgerEntryExtensionV1Ext) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } @@ -7737,8 +8302,7 @@ var ( _ encoding.BinaryUnmarshaler = (*LedgerEntryExtensionV1Ext)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. +// xdrType signals that this type represents XDR values defined by this package. func (s LedgerEntryExtensionV1Ext) xdrType() {} var _ xdrType = (*LedgerEntryExtensionV1Ext)(nil) @@ -7781,28 +8345,32 @@ func (s *LedgerEntryExtensionV1) EncodeTo(e *xdr.Encoder) error { var _ decoderFrom = (*LedgerEntryExtensionV1)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *LedgerEntryExtensionV1) DecodeFrom(d *xdr.Decoder) (int, error) { +func (s *LedgerEntryExtensionV1) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding LedgerEntryExtensionV1: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int var b bool b, nTmp, err = d.DecodeBool() n += nTmp if err != nil { - return n, fmt.Errorf("decoding SponsorshipDescriptor: %s", err) + return n, fmt.Errorf("decoding SponsorshipDescriptor: %w", err) } s.SponsoringId = nil if b { s.SponsoringId = new(AccountId) - nTmp, err = s.SponsoringId.DecodeFrom(d) + nTmp, err = s.SponsoringId.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding SponsorshipDescriptor: %s", err) + return n, fmt.Errorf("decoding SponsorshipDescriptor: %w", err) } } - nTmp, err = s.Ext.DecodeFrom(d) + nTmp, err = s.Ext.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding LedgerEntryExtensionV1Ext: %s", err) + return n, fmt.Errorf("decoding LedgerEntryExtensionV1Ext: %w", err) } return n, nil } @@ -7818,8 +8386,10 @@ func (s LedgerEntryExtensionV1) MarshalBinary() ([]byte, error) { // UnmarshalBinary implements encoding.BinaryUnmarshaler. func (s *LedgerEntryExtensionV1) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } @@ -7828,8 +8398,7 @@ var ( _ encoding.BinaryUnmarshaler = (*LedgerEntryExtensionV1)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. +// xdrType signals that this type represents XDR values defined by this package. func (s LedgerEntryExtensionV1) xdrType() {} var _ xdrType = (*LedgerEntryExtensionV1)(nil) @@ -7850,6 +8419,14 @@ var _ xdrType = (*LedgerEntryExtensionV1)(nil) // ClaimableBalanceEntry claimableBalance; // case LIQUIDITY_POOL: // LiquidityPoolEntry liquidityPool; +// case CONTRACT_DATA: +// ContractDataEntry contractData; +// case CONTRACT_CODE: +// ContractCodeEntry contractCode; +// case CONFIG_SETTING: +// ConfigSettingEntry configSetting; +// case TTL: +// TTLEntry ttl; // } type LedgerEntryData struct { Type LedgerEntryType @@ -7859,6 +8436,10 @@ type LedgerEntryData struct { Data *DataEntry ClaimableBalance *ClaimableBalanceEntry LiquidityPool *LiquidityPoolEntry + ContractData *ContractDataEntry + ContractCode *ContractCodeEntry + ConfigSetting *ConfigSettingEntry + Ttl *TtlEntry } // SwitchFieldName returns the field name in which this union's @@ -7883,6 +8464,14 @@ func (u LedgerEntryData) ArmForSwitch(sw int32) (string, bool) { return "ClaimableBalance", true case LedgerEntryTypeLiquidityPool: return "LiquidityPool", true + case LedgerEntryTypeContractData: + return "ContractData", true + case LedgerEntryTypeContractCode: + return "ContractCode", true + case LedgerEntryTypeConfigSetting: + return "ConfigSetting", true + case LedgerEntryTypeTtl: + return "Ttl", true } return "-", false } @@ -7894,45 +8483,73 @@ func NewLedgerEntryData(aType LedgerEntryType, value interface{}) (result Ledger case LedgerEntryTypeAccount: tv, ok := value.(AccountEntry) if !ok { - err = fmt.Errorf("invalid value, must be AccountEntry") + err = errors.New("invalid value, must be AccountEntry") return } result.Account = &tv case LedgerEntryTypeTrustline: tv, ok := value.(TrustLineEntry) if !ok { - err = fmt.Errorf("invalid value, must be TrustLineEntry") + err = errors.New("invalid value, must be TrustLineEntry") return } result.TrustLine = &tv case LedgerEntryTypeOffer: tv, ok := value.(OfferEntry) if !ok { - err = fmt.Errorf("invalid value, must be OfferEntry") + err = errors.New("invalid value, must be OfferEntry") return } result.Offer = &tv case LedgerEntryTypeData: tv, ok := value.(DataEntry) if !ok { - err = fmt.Errorf("invalid value, must be DataEntry") + err = errors.New("invalid value, must be DataEntry") return } result.Data = &tv case LedgerEntryTypeClaimableBalance: tv, ok := value.(ClaimableBalanceEntry) if !ok { - err = fmt.Errorf("invalid value, must be ClaimableBalanceEntry") + err = errors.New("invalid value, must be ClaimableBalanceEntry") return } result.ClaimableBalance = &tv case LedgerEntryTypeLiquidityPool: tv, ok := value.(LiquidityPoolEntry) if !ok { - err = fmt.Errorf("invalid value, must be LiquidityPoolEntry") + err = errors.New("invalid value, must be LiquidityPoolEntry") return } result.LiquidityPool = &tv + case LedgerEntryTypeContractData: + tv, ok := value.(ContractDataEntry) + if !ok { + err = errors.New("invalid value, must be ContractDataEntry") + return + } + result.ContractData = &tv + case LedgerEntryTypeContractCode: + tv, ok := value.(ContractCodeEntry) + if !ok { + err = errors.New("invalid value, must be ContractCodeEntry") + return + } + result.ContractCode = &tv + case LedgerEntryTypeConfigSetting: + tv, ok := value.(ConfigSettingEntry) + if !ok { + err = errors.New("invalid value, must be ConfigSettingEntry") + return + } + result.ConfigSetting = &tv + case LedgerEntryTypeTtl: + tv, ok := value.(TtlEntry) + if !ok { + err = errors.New("invalid value, must be TtlEntry") + return + } + result.Ttl = &tv } return } @@ -8087,6 +8704,106 @@ func (u LedgerEntryData) GetLiquidityPool() (result LiquidityPoolEntry, ok bool) return } +// MustContractData retrieves the ContractData value from the union, +// panicing if the value is not set. +func (u LedgerEntryData) MustContractData() ContractDataEntry { + val, ok := u.GetContractData() + + if !ok { + panic("arm ContractData is not set") + } + + return val +} + +// GetContractData retrieves the ContractData value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u LedgerEntryData) GetContractData() (result ContractDataEntry, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) + + if armName == "ContractData" { + result = *u.ContractData + ok = true + } + + return +} + +// MustContractCode retrieves the ContractCode value from the union, +// panicing if the value is not set. +func (u LedgerEntryData) MustContractCode() ContractCodeEntry { + val, ok := u.GetContractCode() + + if !ok { + panic("arm ContractCode is not set") + } + + return val +} + +// GetContractCode retrieves the ContractCode value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u LedgerEntryData) GetContractCode() (result ContractCodeEntry, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) + + if armName == "ContractCode" { + result = *u.ContractCode + ok = true + } + + return +} + +// MustConfigSetting retrieves the ConfigSetting value from the union, +// panicing if the value is not set. +func (u LedgerEntryData) MustConfigSetting() ConfigSettingEntry { + val, ok := u.GetConfigSetting() + + if !ok { + panic("arm ConfigSetting is not set") + } + + return val +} + +// GetConfigSetting retrieves the ConfigSetting value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u LedgerEntryData) GetConfigSetting() (result ConfigSettingEntry, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) + + if armName == "ConfigSetting" { + result = *u.ConfigSetting + ok = true + } + + return +} + +// MustTtl retrieves the Ttl value from the union, +// panicing if the value is not set. +func (u LedgerEntryData) MustTtl() TtlEntry { + val, ok := u.GetTtl() + + if !ok { + panic("arm Ttl is not set") + } + + return val +} + +// GetTtl retrieves the Ttl value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u LedgerEntryData) GetTtl() (result TtlEntry, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) + + if armName == "Ttl" { + result = *u.Ttl + ok = true + } + + return +} + // EncodeTo encodes this value using the Encoder. func (u LedgerEntryData) EncodeTo(e *xdr.Encoder) error { var err error @@ -8124,6 +8841,26 @@ func (u LedgerEntryData) EncodeTo(e *xdr.Encoder) error { return err } return nil + case LedgerEntryTypeContractData: + if err = (*u.ContractData).EncodeTo(e); err != nil { + return err + } + return nil + case LedgerEntryTypeContractCode: + if err = (*u.ContractCode).EncodeTo(e); err != nil { + return err + } + return nil + case LedgerEntryTypeConfigSetting: + if err = (*u.ConfigSetting).EncodeTo(e); err != nil { + return err + } + return nil + case LedgerEntryTypeTtl: + if err = (*u.Ttl).EncodeTo(e); err != nil { + return err + } + return nil } return fmt.Errorf("Type (LedgerEntryType) switch value '%d' is not valid for union LedgerEntryData", u.Type) } @@ -8131,61 +8868,97 @@ func (u LedgerEntryData) EncodeTo(e *xdr.Encoder) error { var _ decoderFrom = (*LedgerEntryData)(nil) // DecodeFrom decodes this value using the Decoder. -func (u *LedgerEntryData) DecodeFrom(d *xdr.Decoder) (int, error) { +func (u *LedgerEntryData) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding LedgerEntryData: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = u.Type.DecodeFrom(d) + nTmp, err = u.Type.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding LedgerEntryType: %s", err) + return n, fmt.Errorf("decoding LedgerEntryType: %w", err) } switch LedgerEntryType(u.Type) { case LedgerEntryTypeAccount: u.Account = new(AccountEntry) - nTmp, err = (*u.Account).DecodeFrom(d) + nTmp, err = (*u.Account).DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding AccountEntry: %s", err) + return n, fmt.Errorf("decoding AccountEntry: %w", err) } return n, nil case LedgerEntryTypeTrustline: u.TrustLine = new(TrustLineEntry) - nTmp, err = (*u.TrustLine).DecodeFrom(d) + nTmp, err = (*u.TrustLine).DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding TrustLineEntry: %s", err) + return n, fmt.Errorf("decoding TrustLineEntry: %w", err) } return n, nil case LedgerEntryTypeOffer: u.Offer = new(OfferEntry) - nTmp, err = (*u.Offer).DecodeFrom(d) + nTmp, err = (*u.Offer).DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding OfferEntry: %s", err) + return n, fmt.Errorf("decoding OfferEntry: %w", err) } return n, nil case LedgerEntryTypeData: u.Data = new(DataEntry) - nTmp, err = (*u.Data).DecodeFrom(d) + nTmp, err = (*u.Data).DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding DataEntry: %s", err) + return n, fmt.Errorf("decoding DataEntry: %w", err) } return n, nil case LedgerEntryTypeClaimableBalance: u.ClaimableBalance = new(ClaimableBalanceEntry) - nTmp, err = (*u.ClaimableBalance).DecodeFrom(d) + nTmp, err = (*u.ClaimableBalance).DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding ClaimableBalanceEntry: %s", err) + return n, fmt.Errorf("decoding ClaimableBalanceEntry: %w", err) } return n, nil case LedgerEntryTypeLiquidityPool: u.LiquidityPool = new(LiquidityPoolEntry) - nTmp, err = (*u.LiquidityPool).DecodeFrom(d) + nTmp, err = (*u.LiquidityPool).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding LiquidityPoolEntry: %w", err) + } + return n, nil + case LedgerEntryTypeContractData: + u.ContractData = new(ContractDataEntry) + nTmp, err = (*u.ContractData).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ContractDataEntry: %w", err) + } + return n, nil + case LedgerEntryTypeContractCode: + u.ContractCode = new(ContractCodeEntry) + nTmp, err = (*u.ContractCode).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ContractCodeEntry: %w", err) + } + return n, nil + case LedgerEntryTypeConfigSetting: + u.ConfigSetting = new(ConfigSettingEntry) + nTmp, err = (*u.ConfigSetting).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ConfigSettingEntry: %w", err) + } + return n, nil + case LedgerEntryTypeTtl: + u.Ttl = new(TtlEntry) + nTmp, err = (*u.Ttl).DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding LiquidityPoolEntry: %s", err) + return n, fmt.Errorf("decoding TtlEntry: %w", err) } return n, nil } @@ -8203,8 +8976,10 @@ func (s LedgerEntryData) MarshalBinary() ([]byte, error) { // UnmarshalBinary implements encoding.BinaryUnmarshaler. func (s *LedgerEntryData) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } @@ -8213,8 +8988,7 @@ var ( _ encoding.BinaryUnmarshaler = (*LedgerEntryData)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. +// xdrType signals that this type represents XDR values defined by this package. func (s LedgerEntryData) xdrType() {} var _ xdrType = (*LedgerEntryData)(nil) @@ -8260,7 +9034,7 @@ func NewLedgerEntryExt(v int32, value interface{}) (result LedgerEntryExt, err e case 1: tv, ok := value.(LedgerEntryExtensionV1) if !ok { - err = fmt.Errorf("invalid value, must be LedgerEntryExtensionV1") + err = errors.New("invalid value, must be LedgerEntryExtensionV1") return } result.V1 = &tv @@ -8315,13 +9089,17 @@ func (u LedgerEntryExt) EncodeTo(e *xdr.Encoder) error { var _ decoderFrom = (*LedgerEntryExt)(nil) // DecodeFrom decodes this value using the Decoder. -func (u *LedgerEntryExt) DecodeFrom(d *xdr.Decoder) (int, error) { +func (u *LedgerEntryExt) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding LedgerEntryExt: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int u.V, nTmp, err = d.DecodeInt() n += nTmp if err != nil { - return n, fmt.Errorf("decoding Int: %s", err) + return n, fmt.Errorf("decoding Int: %w", err) } switch int32(u.V) { case 0: @@ -8329,10 +9107,10 @@ func (u *LedgerEntryExt) DecodeFrom(d *xdr.Decoder) (int, error) { return n, nil case 1: u.V1 = new(LedgerEntryExtensionV1) - nTmp, err = (*u.V1).DecodeFrom(d) + nTmp, err = (*u.V1).DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding LedgerEntryExtensionV1: %s", err) + return n, fmt.Errorf("decoding LedgerEntryExtensionV1: %w", err) } return n, nil } @@ -8350,8 +9128,10 @@ func (s LedgerEntryExt) MarshalBinary() ([]byte, error) { // UnmarshalBinary implements encoding.BinaryUnmarshaler. func (s *LedgerEntryExt) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } @@ -8360,8 +9140,7 @@ var ( _ encoding.BinaryUnmarshaler = (*LedgerEntryExt)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. +// xdrType signals that this type represents XDR values defined by this package. func (s LedgerEntryExt) xdrType() {} var _ xdrType = (*LedgerEntryExt)(nil) @@ -8386,6 +9165,14 @@ var _ xdrType = (*LedgerEntryExt)(nil) // ClaimableBalanceEntry claimableBalance; // case LIQUIDITY_POOL: // LiquidityPoolEntry liquidityPool; +// case CONTRACT_DATA: +// ContractDataEntry contractData; +// case CONTRACT_CODE: +// ContractCodeEntry contractCode; +// case CONFIG_SETTING: +// ConfigSettingEntry configSetting; +// case TTL: +// TTLEntry ttl; // } // data; // @@ -8423,23 +9210,27 @@ func (s *LedgerEntry) EncodeTo(e *xdr.Encoder) error { var _ decoderFrom = (*LedgerEntry)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *LedgerEntry) DecodeFrom(d *xdr.Decoder) (int, error) { +func (s *LedgerEntry) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding LedgerEntry: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = s.LastModifiedLedgerSeq.DecodeFrom(d) + nTmp, err = s.LastModifiedLedgerSeq.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Uint32: %s", err) + return n, fmt.Errorf("decoding Uint32: %w", err) } - nTmp, err = s.Data.DecodeFrom(d) + nTmp, err = s.Data.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding LedgerEntryData: %s", err) + return n, fmt.Errorf("decoding LedgerEntryData: %w", err) } - nTmp, err = s.Ext.DecodeFrom(d) + nTmp, err = s.Ext.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding LedgerEntryExt: %s", err) + return n, fmt.Errorf("decoding LedgerEntryExt: %w", err) } return n, nil } @@ -8455,8 +9246,10 @@ func (s LedgerEntry) MarshalBinary() ([]byte, error) { // UnmarshalBinary implements encoding.BinaryUnmarshaler. func (s *LedgerEntry) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } @@ -8465,8 +9258,7 @@ var ( _ encoding.BinaryUnmarshaler = (*LedgerEntry)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. +// xdrType signals that this type represents XDR values defined by this package. func (s LedgerEntry) xdrType() {} var _ xdrType = (*LedgerEntry)(nil) @@ -8493,13 +9285,17 @@ func (s *LedgerKeyAccount) EncodeTo(e *xdr.Encoder) error { var _ decoderFrom = (*LedgerKeyAccount)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *LedgerKeyAccount) DecodeFrom(d *xdr.Decoder) (int, error) { +func (s *LedgerKeyAccount) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding LedgerKeyAccount: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = s.AccountId.DecodeFrom(d) + nTmp, err = s.AccountId.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding AccountId: %s", err) + return n, fmt.Errorf("decoding AccountId: %w", err) } return n, nil } @@ -8515,8 +9311,10 @@ func (s LedgerKeyAccount) MarshalBinary() ([]byte, error) { // UnmarshalBinary implements encoding.BinaryUnmarshaler. func (s *LedgerKeyAccount) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } @@ -8525,8 +9323,7 @@ var ( _ encoding.BinaryUnmarshaler = (*LedgerKeyAccount)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. +// xdrType signals that this type represents XDR values defined by this package. func (s LedgerKeyAccount) xdrType() {} var _ xdrType = (*LedgerKeyAccount)(nil) @@ -8558,18 +9355,22 @@ func (s *LedgerKeyTrustLine) EncodeTo(e *xdr.Encoder) error { var _ decoderFrom = (*LedgerKeyTrustLine)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *LedgerKeyTrustLine) DecodeFrom(d *xdr.Decoder) (int, error) { +func (s *LedgerKeyTrustLine) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding LedgerKeyTrustLine: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = s.AccountId.DecodeFrom(d) + nTmp, err = s.AccountId.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding AccountId: %s", err) + return n, fmt.Errorf("decoding AccountId: %w", err) } - nTmp, err = s.Asset.DecodeFrom(d) + nTmp, err = s.Asset.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding TrustLineAsset: %s", err) + return n, fmt.Errorf("decoding TrustLineAsset: %w", err) } return n, nil } @@ -8585,8 +9386,10 @@ func (s LedgerKeyTrustLine) MarshalBinary() ([]byte, error) { // UnmarshalBinary implements encoding.BinaryUnmarshaler. func (s *LedgerKeyTrustLine) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } @@ -8595,8 +9398,7 @@ var ( _ encoding.BinaryUnmarshaler = (*LedgerKeyTrustLine)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. +// xdrType signals that this type represents XDR values defined by this package. func (s LedgerKeyTrustLine) xdrType() {} var _ xdrType = (*LedgerKeyTrustLine)(nil) @@ -8628,18 +9430,22 @@ func (s *LedgerKeyOffer) EncodeTo(e *xdr.Encoder) error { var _ decoderFrom = (*LedgerKeyOffer)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *LedgerKeyOffer) DecodeFrom(d *xdr.Decoder) (int, error) { +func (s *LedgerKeyOffer) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding LedgerKeyOffer: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = s.SellerId.DecodeFrom(d) + nTmp, err = s.SellerId.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding AccountId: %s", err) + return n, fmt.Errorf("decoding AccountId: %w", err) } - nTmp, err = s.OfferId.DecodeFrom(d) + nTmp, err = s.OfferId.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Int64: %s", err) + return n, fmt.Errorf("decoding Int64: %w", err) } return n, nil } @@ -8655,8 +9461,10 @@ func (s LedgerKeyOffer) MarshalBinary() ([]byte, error) { // UnmarshalBinary implements encoding.BinaryUnmarshaler. func (s *LedgerKeyOffer) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } @@ -8665,8 +9473,7 @@ var ( _ encoding.BinaryUnmarshaler = (*LedgerKeyOffer)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. +// xdrType signals that this type represents XDR values defined by this package. func (s LedgerKeyOffer) xdrType() {} var _ xdrType = (*LedgerKeyOffer)(nil) @@ -8698,18 +9505,22 @@ func (s *LedgerKeyData) EncodeTo(e *xdr.Encoder) error { var _ decoderFrom = (*LedgerKeyData)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *LedgerKeyData) DecodeFrom(d *xdr.Decoder) (int, error) { +func (s *LedgerKeyData) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding LedgerKeyData: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = s.AccountId.DecodeFrom(d) + nTmp, err = s.AccountId.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding AccountId: %s", err) + return n, fmt.Errorf("decoding AccountId: %w", err) } - nTmp, err = s.DataName.DecodeFrom(d) + nTmp, err = s.DataName.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding String64: %s", err) + return n, fmt.Errorf("decoding String64: %w", err) } return n, nil } @@ -8725,8 +9536,10 @@ func (s LedgerKeyData) MarshalBinary() ([]byte, error) { // UnmarshalBinary implements encoding.BinaryUnmarshaler. func (s *LedgerKeyData) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } @@ -8735,8 +9548,7 @@ var ( _ encoding.BinaryUnmarshaler = (*LedgerKeyData)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. +// xdrType signals that this type represents XDR values defined by this package. func (s LedgerKeyData) xdrType() {} var _ xdrType = (*LedgerKeyData)(nil) @@ -8763,13 +9575,17 @@ func (s *LedgerKeyClaimableBalance) EncodeTo(e *xdr.Encoder) error { var _ decoderFrom = (*LedgerKeyClaimableBalance)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *LedgerKeyClaimableBalance) DecodeFrom(d *xdr.Decoder) (int, error) { +func (s *LedgerKeyClaimableBalance) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding LedgerKeyClaimableBalance: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = s.BalanceId.DecodeFrom(d) + nTmp, err = s.BalanceId.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding ClaimableBalanceId: %s", err) + return n, fmt.Errorf("decoding ClaimableBalanceId: %w", err) } return n, nil } @@ -8785,8 +9601,10 @@ func (s LedgerKeyClaimableBalance) MarshalBinary() ([]byte, error) { // UnmarshalBinary implements encoding.BinaryUnmarshaler. func (s *LedgerKeyClaimableBalance) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } @@ -8795,8 +9613,7 @@ var ( _ encoding.BinaryUnmarshaler = (*LedgerKeyClaimableBalance)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. +// xdrType signals that this type represents XDR values defined by this package. func (s LedgerKeyClaimableBalance) xdrType() {} var _ xdrType = (*LedgerKeyClaimableBalance)(nil) @@ -8823,13 +9640,17 @@ func (s *LedgerKeyLiquidityPool) EncodeTo(e *xdr.Encoder) error { var _ decoderFrom = (*LedgerKeyLiquidityPool)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *LedgerKeyLiquidityPool) DecodeFrom(d *xdr.Decoder) (int, error) { +func (s *LedgerKeyLiquidityPool) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding LedgerKeyLiquidityPool: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = s.LiquidityPoolId.DecodeFrom(d) + nTmp, err = s.LiquidityPoolId.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding PoolId: %s", err) + return n, fmt.Errorf("decoding PoolId: %w", err) } return n, nil } @@ -8845,8 +9666,10 @@ func (s LedgerKeyLiquidityPool) MarshalBinary() ([]byte, error) { // UnmarshalBinary implements encoding.BinaryUnmarshaler. func (s *LedgerKeyLiquidityPool) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } @@ -8855,12 +9678,292 @@ var ( _ encoding.BinaryUnmarshaler = (*LedgerKeyLiquidityPool)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. +// xdrType signals that this type represents XDR values defined by this package. func (s LedgerKeyLiquidityPool) xdrType() {} var _ xdrType = (*LedgerKeyLiquidityPool)(nil) +// LedgerKeyContractData is an XDR NestedStruct defines as: +// +// struct +// { +// SCAddress contract; +// SCVal key; +// ContractDataDurability durability; +// } +type LedgerKeyContractData struct { + Contract ScAddress + Key ScVal + Durability ContractDataDurability +} + +// EncodeTo encodes this value using the Encoder. +func (s *LedgerKeyContractData) EncodeTo(e *xdr.Encoder) error { + var err error + if err = s.Contract.EncodeTo(e); err != nil { + return err + } + if err = s.Key.EncodeTo(e); err != nil { + return err + } + if err = s.Durability.EncodeTo(e); err != nil { + return err + } + return nil +} + +var _ decoderFrom = (*LedgerKeyContractData)(nil) + +// DecodeFrom decodes this value using the Decoder. +func (s *LedgerKeyContractData) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding LedgerKeyContractData: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + var err error + var n, nTmp int + nTmp, err = s.Contract.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ScAddress: %w", err) + } + nTmp, err = s.Key.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ScVal: %w", err) + } + nTmp, err = s.Durability.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ContractDataDurability: %w", err) + } + return n, nil +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (s LedgerKeyContractData) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *LedgerKeyContractData) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} + +var ( + _ encoding.BinaryMarshaler = (*LedgerKeyContractData)(nil) + _ encoding.BinaryUnmarshaler = (*LedgerKeyContractData)(nil) +) + +// xdrType signals that this type represents XDR values defined by this package. +func (s LedgerKeyContractData) xdrType() {} + +var _ xdrType = (*LedgerKeyContractData)(nil) + +// LedgerKeyContractCode is an XDR NestedStruct defines as: +// +// struct +// { +// Hash hash; +// } +type LedgerKeyContractCode struct { + Hash Hash +} + +// EncodeTo encodes this value using the Encoder. +func (s *LedgerKeyContractCode) EncodeTo(e *xdr.Encoder) error { + var err error + if err = s.Hash.EncodeTo(e); err != nil { + return err + } + return nil +} + +var _ decoderFrom = (*LedgerKeyContractCode)(nil) + +// DecodeFrom decodes this value using the Decoder. +func (s *LedgerKeyContractCode) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding LedgerKeyContractCode: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + var err error + var n, nTmp int + nTmp, err = s.Hash.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Hash: %w", err) + } + return n, nil +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (s LedgerKeyContractCode) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *LedgerKeyContractCode) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} + +var ( + _ encoding.BinaryMarshaler = (*LedgerKeyContractCode)(nil) + _ encoding.BinaryUnmarshaler = (*LedgerKeyContractCode)(nil) +) + +// xdrType signals that this type represents XDR values defined by this package. +func (s LedgerKeyContractCode) xdrType() {} + +var _ xdrType = (*LedgerKeyContractCode)(nil) + +// LedgerKeyConfigSetting is an XDR NestedStruct defines as: +// +// struct +// { +// ConfigSettingID configSettingID; +// } +type LedgerKeyConfigSetting struct { + ConfigSettingId ConfigSettingId +} + +// EncodeTo encodes this value using the Encoder. +func (s *LedgerKeyConfigSetting) EncodeTo(e *xdr.Encoder) error { + var err error + if err = s.ConfigSettingId.EncodeTo(e); err != nil { + return err + } + return nil +} + +var _ decoderFrom = (*LedgerKeyConfigSetting)(nil) + +// DecodeFrom decodes this value using the Decoder. +func (s *LedgerKeyConfigSetting) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding LedgerKeyConfigSetting: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + var err error + var n, nTmp int + nTmp, err = s.ConfigSettingId.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ConfigSettingId: %w", err) + } + return n, nil +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (s LedgerKeyConfigSetting) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *LedgerKeyConfigSetting) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} + +var ( + _ encoding.BinaryMarshaler = (*LedgerKeyConfigSetting)(nil) + _ encoding.BinaryUnmarshaler = (*LedgerKeyConfigSetting)(nil) +) + +// xdrType signals that this type represents XDR values defined by this package. +func (s LedgerKeyConfigSetting) xdrType() {} + +var _ xdrType = (*LedgerKeyConfigSetting)(nil) + +// LedgerKeyTtl is an XDR NestedStruct defines as: +// +// struct +// { +// // Hash of the LedgerKey that is associated with this TTLEntry +// Hash keyHash; +// } +type LedgerKeyTtl struct { + KeyHash Hash +} + +// EncodeTo encodes this value using the Encoder. +func (s *LedgerKeyTtl) EncodeTo(e *xdr.Encoder) error { + var err error + if err = s.KeyHash.EncodeTo(e); err != nil { + return err + } + return nil +} + +var _ decoderFrom = (*LedgerKeyTtl)(nil) + +// DecodeFrom decodes this value using the Decoder. +func (s *LedgerKeyTtl) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding LedgerKeyTtl: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + var err error + var n, nTmp int + nTmp, err = s.KeyHash.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Hash: %w", err) + } + return n, nil +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (s LedgerKeyTtl) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *LedgerKeyTtl) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} + +var ( + _ encoding.BinaryMarshaler = (*LedgerKeyTtl)(nil) + _ encoding.BinaryUnmarshaler = (*LedgerKeyTtl)(nil) +) + +// xdrType signals that this type represents XDR values defined by this package. +func (s LedgerKeyTtl) xdrType() {} + +var _ xdrType = (*LedgerKeyTtl)(nil) + // LedgerKey is an XDR Union defines as: // // union LedgerKey switch (LedgerEntryType type) @@ -8903,6 +10006,29 @@ var _ xdrType = (*LedgerKeyLiquidityPool)(nil) // { // PoolID liquidityPoolID; // } liquidityPool; +// case CONTRACT_DATA: +// struct +// { +// SCAddress contract; +// SCVal key; +// ContractDataDurability durability; +// } contractData; +// case CONTRACT_CODE: +// struct +// { +// Hash hash; +// } contractCode; +// case CONFIG_SETTING: +// struct +// { +// ConfigSettingID configSettingID; +// } configSetting; +// case TTL: +// struct +// { +// // Hash of the LedgerKey that is associated with this TTLEntry +// Hash keyHash; +// } ttl; // }; type LedgerKey struct { Type LedgerEntryType @@ -8912,6 +10038,10 @@ type LedgerKey struct { Data *LedgerKeyData ClaimableBalance *LedgerKeyClaimableBalance LiquidityPool *LedgerKeyLiquidityPool + ContractData *LedgerKeyContractData + ContractCode *LedgerKeyContractCode + ConfigSetting *LedgerKeyConfigSetting + Ttl *LedgerKeyTtl } // SwitchFieldName returns the field name in which this union's @@ -8936,6 +10066,14 @@ func (u LedgerKey) ArmForSwitch(sw int32) (string, bool) { return "ClaimableBalance", true case LedgerEntryTypeLiquidityPool: return "LiquidityPool", true + case LedgerEntryTypeContractData: + return "ContractData", true + case LedgerEntryTypeContractCode: + return "ContractCode", true + case LedgerEntryTypeConfigSetting: + return "ConfigSetting", true + case LedgerEntryTypeTtl: + return "Ttl", true } return "-", false } @@ -8947,45 +10085,73 @@ func NewLedgerKey(aType LedgerEntryType, value interface{}) (result LedgerKey, e case LedgerEntryTypeAccount: tv, ok := value.(LedgerKeyAccount) if !ok { - err = fmt.Errorf("invalid value, must be LedgerKeyAccount") + err = errors.New("invalid value, must be LedgerKeyAccount") return } result.Account = &tv case LedgerEntryTypeTrustline: tv, ok := value.(LedgerKeyTrustLine) if !ok { - err = fmt.Errorf("invalid value, must be LedgerKeyTrustLine") + err = errors.New("invalid value, must be LedgerKeyTrustLine") return } result.TrustLine = &tv case LedgerEntryTypeOffer: tv, ok := value.(LedgerKeyOffer) if !ok { - err = fmt.Errorf("invalid value, must be LedgerKeyOffer") + err = errors.New("invalid value, must be LedgerKeyOffer") return } result.Offer = &tv case LedgerEntryTypeData: tv, ok := value.(LedgerKeyData) if !ok { - err = fmt.Errorf("invalid value, must be LedgerKeyData") + err = errors.New("invalid value, must be LedgerKeyData") return } result.Data = &tv case LedgerEntryTypeClaimableBalance: tv, ok := value.(LedgerKeyClaimableBalance) if !ok { - err = fmt.Errorf("invalid value, must be LedgerKeyClaimableBalance") + err = errors.New("invalid value, must be LedgerKeyClaimableBalance") return } result.ClaimableBalance = &tv case LedgerEntryTypeLiquidityPool: tv, ok := value.(LedgerKeyLiquidityPool) if !ok { - err = fmt.Errorf("invalid value, must be LedgerKeyLiquidityPool") + err = errors.New("invalid value, must be LedgerKeyLiquidityPool") return } result.LiquidityPool = &tv + case LedgerEntryTypeContractData: + tv, ok := value.(LedgerKeyContractData) + if !ok { + err = errors.New("invalid value, must be LedgerKeyContractData") + return + } + result.ContractData = &tv + case LedgerEntryTypeContractCode: + tv, ok := value.(LedgerKeyContractCode) + if !ok { + err = errors.New("invalid value, must be LedgerKeyContractCode") + return + } + result.ContractCode = &tv + case LedgerEntryTypeConfigSetting: + tv, ok := value.(LedgerKeyConfigSetting) + if !ok { + err = errors.New("invalid value, must be LedgerKeyConfigSetting") + return + } + result.ConfigSetting = &tv + case LedgerEntryTypeTtl: + tv, ok := value.(LedgerKeyTtl) + if !ok { + err = errors.New("invalid value, must be LedgerKeyTtl") + return + } + result.Ttl = &tv } return } @@ -9140,6 +10306,106 @@ func (u LedgerKey) GetLiquidityPool() (result LedgerKeyLiquidityPool, ok bool) { return } +// MustContractData retrieves the ContractData value from the union, +// panicing if the value is not set. +func (u LedgerKey) MustContractData() LedgerKeyContractData { + val, ok := u.GetContractData() + + if !ok { + panic("arm ContractData is not set") + } + + return val +} + +// GetContractData retrieves the ContractData value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u LedgerKey) GetContractData() (result LedgerKeyContractData, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) + + if armName == "ContractData" { + result = *u.ContractData + ok = true + } + + return +} + +// MustContractCode retrieves the ContractCode value from the union, +// panicing if the value is not set. +func (u LedgerKey) MustContractCode() LedgerKeyContractCode { + val, ok := u.GetContractCode() + + if !ok { + panic("arm ContractCode is not set") + } + + return val +} + +// GetContractCode retrieves the ContractCode value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u LedgerKey) GetContractCode() (result LedgerKeyContractCode, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) + + if armName == "ContractCode" { + result = *u.ContractCode + ok = true + } + + return +} + +// MustConfigSetting retrieves the ConfigSetting value from the union, +// panicing if the value is not set. +func (u LedgerKey) MustConfigSetting() LedgerKeyConfigSetting { + val, ok := u.GetConfigSetting() + + if !ok { + panic("arm ConfigSetting is not set") + } + + return val +} + +// GetConfigSetting retrieves the ConfigSetting value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u LedgerKey) GetConfigSetting() (result LedgerKeyConfigSetting, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) + + if armName == "ConfigSetting" { + result = *u.ConfigSetting + ok = true + } + + return +} + +// MustTtl retrieves the Ttl value from the union, +// panicing if the value is not set. +func (u LedgerKey) MustTtl() LedgerKeyTtl { + val, ok := u.GetTtl() + + if !ok { + panic("arm Ttl is not set") + } + + return val +} + +// GetTtl retrieves the Ttl value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u LedgerKey) GetTtl() (result LedgerKeyTtl, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) + + if armName == "Ttl" { + result = *u.Ttl + ok = true + } + + return +} + // EncodeTo encodes this value using the Encoder. func (u LedgerKey) EncodeTo(e *xdr.Encoder) error { var err error @@ -9177,6 +10443,26 @@ func (u LedgerKey) EncodeTo(e *xdr.Encoder) error { return err } return nil + case LedgerEntryTypeContractData: + if err = (*u.ContractData).EncodeTo(e); err != nil { + return err + } + return nil + case LedgerEntryTypeContractCode: + if err = (*u.ContractCode).EncodeTo(e); err != nil { + return err + } + return nil + case LedgerEntryTypeConfigSetting: + if err = (*u.ConfigSetting).EncodeTo(e); err != nil { + return err + } + return nil + case LedgerEntryTypeTtl: + if err = (*u.Ttl).EncodeTo(e); err != nil { + return err + } + return nil } return fmt.Errorf("Type (LedgerEntryType) switch value '%d' is not valid for union LedgerKey", u.Type) } @@ -9184,61 +10470,97 @@ func (u LedgerKey) EncodeTo(e *xdr.Encoder) error { var _ decoderFrom = (*LedgerKey)(nil) // DecodeFrom decodes this value using the Decoder. -func (u *LedgerKey) DecodeFrom(d *xdr.Decoder) (int, error) { +func (u *LedgerKey) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding LedgerKey: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = u.Type.DecodeFrom(d) + nTmp, err = u.Type.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding LedgerEntryType: %s", err) + return n, fmt.Errorf("decoding LedgerEntryType: %w", err) } switch LedgerEntryType(u.Type) { case LedgerEntryTypeAccount: u.Account = new(LedgerKeyAccount) - nTmp, err = (*u.Account).DecodeFrom(d) + nTmp, err = (*u.Account).DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding LedgerKeyAccount: %s", err) + return n, fmt.Errorf("decoding LedgerKeyAccount: %w", err) } return n, nil case LedgerEntryTypeTrustline: u.TrustLine = new(LedgerKeyTrustLine) - nTmp, err = (*u.TrustLine).DecodeFrom(d) + nTmp, err = (*u.TrustLine).DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding LedgerKeyTrustLine: %s", err) + return n, fmt.Errorf("decoding LedgerKeyTrustLine: %w", err) } return n, nil case LedgerEntryTypeOffer: u.Offer = new(LedgerKeyOffer) - nTmp, err = (*u.Offer).DecodeFrom(d) + nTmp, err = (*u.Offer).DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding LedgerKeyOffer: %s", err) + return n, fmt.Errorf("decoding LedgerKeyOffer: %w", err) } return n, nil case LedgerEntryTypeData: u.Data = new(LedgerKeyData) - nTmp, err = (*u.Data).DecodeFrom(d) + nTmp, err = (*u.Data).DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding LedgerKeyData: %s", err) + return n, fmt.Errorf("decoding LedgerKeyData: %w", err) } return n, nil case LedgerEntryTypeClaimableBalance: u.ClaimableBalance = new(LedgerKeyClaimableBalance) - nTmp, err = (*u.ClaimableBalance).DecodeFrom(d) + nTmp, err = (*u.ClaimableBalance).DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding LedgerKeyClaimableBalance: %s", err) + return n, fmt.Errorf("decoding LedgerKeyClaimableBalance: %w", err) } return n, nil case LedgerEntryTypeLiquidityPool: u.LiquidityPool = new(LedgerKeyLiquidityPool) - nTmp, err = (*u.LiquidityPool).DecodeFrom(d) + nTmp, err = (*u.LiquidityPool).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding LedgerKeyLiquidityPool: %w", err) + } + return n, nil + case LedgerEntryTypeContractData: + u.ContractData = new(LedgerKeyContractData) + nTmp, err = (*u.ContractData).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding LedgerKeyContractData: %w", err) + } + return n, nil + case LedgerEntryTypeContractCode: + u.ContractCode = new(LedgerKeyContractCode) + nTmp, err = (*u.ContractCode).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding LedgerKeyContractCode: %w", err) + } + return n, nil + case LedgerEntryTypeConfigSetting: + u.ConfigSetting = new(LedgerKeyConfigSetting) + nTmp, err = (*u.ConfigSetting).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding LedgerKeyConfigSetting: %w", err) + } + return n, nil + case LedgerEntryTypeTtl: + u.Ttl = new(LedgerKeyTtl) + nTmp, err = (*u.Ttl).DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding LedgerKeyLiquidityPool: %s", err) + return n, fmt.Errorf("decoding LedgerKeyTtl: %w", err) } return n, nil } @@ -9256,8 +10578,10 @@ func (s LedgerKey) MarshalBinary() ([]byte, error) { // UnmarshalBinary implements encoding.BinaryUnmarshaler. func (s *LedgerKey) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } @@ -9266,8 +10590,7 @@ var ( _ encoding.BinaryUnmarshaler = (*LedgerKey)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. +// xdrType signals that this type represents XDR values defined by this package. func (s LedgerKey) xdrType() {} var _ xdrType = (*LedgerKey)(nil) @@ -9283,19 +10606,23 @@ var _ xdrType = (*LedgerKey)(nil) // ENVELOPE_TYPE_SCPVALUE = 4, // ENVELOPE_TYPE_TX_FEE_BUMP = 5, // ENVELOPE_TYPE_OP_ID = 6, -// ENVELOPE_TYPE_POOL_REVOKE_OP_ID = 7 +// ENVELOPE_TYPE_POOL_REVOKE_OP_ID = 7, +// ENVELOPE_TYPE_CONTRACT_ID = 8, +// ENVELOPE_TYPE_SOROBAN_AUTHORIZATION = 9 // }; type EnvelopeType int32 const ( - EnvelopeTypeEnvelopeTypeTxV0 EnvelopeType = 0 - EnvelopeTypeEnvelopeTypeScp EnvelopeType = 1 - EnvelopeTypeEnvelopeTypeTx EnvelopeType = 2 - EnvelopeTypeEnvelopeTypeAuth EnvelopeType = 3 - EnvelopeTypeEnvelopeTypeScpvalue EnvelopeType = 4 - EnvelopeTypeEnvelopeTypeTxFeeBump EnvelopeType = 5 - EnvelopeTypeEnvelopeTypeOpId EnvelopeType = 6 - EnvelopeTypeEnvelopeTypePoolRevokeOpId EnvelopeType = 7 + EnvelopeTypeEnvelopeTypeTxV0 EnvelopeType = 0 + EnvelopeTypeEnvelopeTypeScp EnvelopeType = 1 + EnvelopeTypeEnvelopeTypeTx EnvelopeType = 2 + EnvelopeTypeEnvelopeTypeAuth EnvelopeType = 3 + EnvelopeTypeEnvelopeTypeScpvalue EnvelopeType = 4 + EnvelopeTypeEnvelopeTypeTxFeeBump EnvelopeType = 5 + EnvelopeTypeEnvelopeTypeOpId EnvelopeType = 6 + EnvelopeTypeEnvelopeTypePoolRevokeOpId EnvelopeType = 7 + EnvelopeTypeEnvelopeTypeContractId EnvelopeType = 8 + EnvelopeTypeEnvelopeTypeSorobanAuthorization EnvelopeType = 9 ) var envelopeTypeMap = map[int32]string{ @@ -9307,6 +10634,8 @@ var envelopeTypeMap = map[int32]string{ 5: "EnvelopeTypeEnvelopeTypeTxFeeBump", 6: "EnvelopeTypeEnvelopeTypeOpId", 7: "EnvelopeTypeEnvelopeTypePoolRevokeOpId", + 8: "EnvelopeTypeEnvelopeTypeContractId", + 9: "EnvelopeTypeEnvelopeTypeSorobanAuthorization", } // ValidEnum validates a proposed value for this enum. Implements @@ -9334,10 +10663,14 @@ func (e EnvelopeType) EncodeTo(enc *xdr.Encoder) error { var _ decoderFrom = (*EnvelopeType)(nil) // DecodeFrom decodes this value using the Decoder. -func (e *EnvelopeType) DecodeFrom(d *xdr.Decoder) (int, error) { +func (e *EnvelopeType) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding EnvelopeType: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 v, n, err := d.DecodeInt() if err != nil { - return n, fmt.Errorf("decoding EnvelopeType: %s", err) + return n, fmt.Errorf("decoding EnvelopeType: %w", err) } if _, ok := envelopeTypeMap[v]; !ok { return n, fmt.Errorf("'%d' is not a valid EnvelopeType enum value", v) @@ -9357,8 +10690,10 @@ func (s EnvelopeType) MarshalBinary() ([]byte, error) { // UnmarshalBinary implements encoding.BinaryUnmarshaler. func (s *EnvelopeType) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } @@ -9367,8 +10702,7 @@ var ( _ encoding.BinaryUnmarshaler = (*EnvelopeType)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. +// xdrType signals that this type represents XDR values defined by this package. func (s EnvelopeType) xdrType() {} var _ xdrType = (*EnvelopeType)(nil) @@ -9395,13 +10729,17 @@ func (s UpgradeType) EncodeTo(e *xdr.Encoder) error { var _ decoderFrom = (*UpgradeType)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *UpgradeType) DecodeFrom(d *xdr.Decoder) (int, error) { +func (s *UpgradeType) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding UpgradeType: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int (*s), nTmp, err = d.DecodeOpaque(128) n += nTmp if err != nil { - return n, fmt.Errorf("decoding UpgradeType: %s", err) + return n, fmt.Errorf("decoding UpgradeType: %w", err) } return n, nil } @@ -9417,8 +10755,10 @@ func (s UpgradeType) MarshalBinary() ([]byte, error) { // UnmarshalBinary implements encoding.BinaryUnmarshaler. func (s *UpgradeType) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } @@ -9427,8 +10767,7 @@ var ( _ encoding.BinaryUnmarshaler = (*UpgradeType)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. +// xdrType signals that this type represents XDR values defined by this package. func (s UpgradeType) xdrType() {} var _ xdrType = (*UpgradeType)(nil) @@ -9477,10 +10816,14 @@ func (e StellarValueType) EncodeTo(enc *xdr.Encoder) error { var _ decoderFrom = (*StellarValueType)(nil) // DecodeFrom decodes this value using the Decoder. -func (e *StellarValueType) DecodeFrom(d *xdr.Decoder) (int, error) { +func (e *StellarValueType) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding StellarValueType: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 v, n, err := d.DecodeInt() if err != nil { - return n, fmt.Errorf("decoding StellarValueType: %s", err) + return n, fmt.Errorf("decoding StellarValueType: %w", err) } if _, ok := stellarValueTypeMap[v]; !ok { return n, fmt.Errorf("'%d' is not a valid StellarValueType enum value", v) @@ -9500,8 +10843,10 @@ func (s StellarValueType) MarshalBinary() ([]byte, error) { // UnmarshalBinary implements encoding.BinaryUnmarshaler. func (s *StellarValueType) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } @@ -9510,8 +10855,7 @@ var ( _ encoding.BinaryUnmarshaler = (*StellarValueType)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. +// xdrType signals that this type represents XDR values defined by this package. func (s StellarValueType) xdrType() {} var _ xdrType = (*StellarValueType)(nil) @@ -9543,18 +10887,22 @@ func (s *LedgerCloseValueSignature) EncodeTo(e *xdr.Encoder) error { var _ decoderFrom = (*LedgerCloseValueSignature)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *LedgerCloseValueSignature) DecodeFrom(d *xdr.Decoder) (int, error) { +func (s *LedgerCloseValueSignature) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding LedgerCloseValueSignature: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = s.NodeId.DecodeFrom(d) + nTmp, err = s.NodeId.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding NodeId: %s", err) + return n, fmt.Errorf("decoding NodeId: %w", err) } - nTmp, err = s.Signature.DecodeFrom(d) + nTmp, err = s.Signature.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Signature: %s", err) + return n, fmt.Errorf("decoding Signature: %w", err) } return n, nil } @@ -9570,8 +10918,10 @@ func (s LedgerCloseValueSignature) MarshalBinary() ([]byte, error) { // UnmarshalBinary implements encoding.BinaryUnmarshaler. func (s *LedgerCloseValueSignature) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } @@ -9580,8 +10930,7 @@ var ( _ encoding.BinaryUnmarshaler = (*LedgerCloseValueSignature)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. +// xdrType signals that this type represents XDR values defined by this package. func (s LedgerCloseValueSignature) xdrType() {} var _ xdrType = (*LedgerCloseValueSignature)(nil) @@ -9627,7 +10976,7 @@ func NewStellarValueExt(v StellarValueType, value interface{}) (result StellarVa case StellarValueTypeStellarValueSigned: tv, ok := value.(LedgerCloseValueSignature) if !ok { - err = fmt.Errorf("invalid value, must be LedgerCloseValueSignature") + err = errors.New("invalid value, must be LedgerCloseValueSignature") return } result.LcValueSignature = &tv @@ -9682,13 +11031,17 @@ func (u StellarValueExt) EncodeTo(e *xdr.Encoder) error { var _ decoderFrom = (*StellarValueExt)(nil) // DecodeFrom decodes this value using the Decoder. -func (u *StellarValueExt) DecodeFrom(d *xdr.Decoder) (int, error) { +func (u *StellarValueExt) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding StellarValueExt: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = u.V.DecodeFrom(d) + nTmp, err = u.V.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding StellarValueType: %s", err) + return n, fmt.Errorf("decoding StellarValueType: %w", err) } switch StellarValueType(u.V) { case StellarValueTypeStellarValueBasic: @@ -9696,10 +11049,10 @@ func (u *StellarValueExt) DecodeFrom(d *xdr.Decoder) (int, error) { return n, nil case StellarValueTypeStellarValueSigned: u.LcValueSignature = new(LedgerCloseValueSignature) - nTmp, err = (*u.LcValueSignature).DecodeFrom(d) + nTmp, err = (*u.LcValueSignature).DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding LedgerCloseValueSignature: %s", err) + return n, fmt.Errorf("decoding LedgerCloseValueSignature: %w", err) } return n, nil } @@ -9717,8 +11070,10 @@ func (s StellarValueExt) MarshalBinary() ([]byte, error) { // UnmarshalBinary implements encoding.BinaryUnmarshaler. func (s *StellarValueExt) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } @@ -9727,8 +11082,7 @@ var ( _ encoding.BinaryUnmarshaler = (*StellarValueExt)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. +// xdrType signals that this type represents XDR values defined by this package. func (s StellarValueExt) xdrType() {} var _ xdrType = (*StellarValueExt)(nil) @@ -9790,43 +11144,50 @@ func (s *StellarValue) EncodeTo(e *xdr.Encoder) error { var _ decoderFrom = (*StellarValue)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *StellarValue) DecodeFrom(d *xdr.Decoder) (int, error) { +func (s *StellarValue) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding StellarValue: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = s.TxSetHash.DecodeFrom(d) + nTmp, err = s.TxSetHash.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Hash: %s", err) + return n, fmt.Errorf("decoding Hash: %w", err) } - nTmp, err = s.CloseTime.DecodeFrom(d) + nTmp, err = s.CloseTime.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding TimePoint: %s", err) + return n, fmt.Errorf("decoding TimePoint: %w", err) } var l uint32 l, nTmp, err = d.DecodeUint() n += nTmp if err != nil { - return n, fmt.Errorf("decoding UpgradeType: %s", err) + return n, fmt.Errorf("decoding UpgradeType: %w", err) } if l > 6 { return n, fmt.Errorf("decoding UpgradeType: data size (%d) exceeds size limit (6)", l) } s.Upgrades = nil if l > 0 { + if il, ok := d.InputLen(); ok && uint(il) < uint(l) { + return n, fmt.Errorf("decoding UpgradeType: length (%d) exceeds remaining input length (%d)", l, il) + } s.Upgrades = make([]UpgradeType, l) for i := uint32(0); i < l; i++ { - nTmp, err = s.Upgrades[i].DecodeFrom(d) + nTmp, err = s.Upgrades[i].DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding UpgradeType: %s", err) + return n, fmt.Errorf("decoding UpgradeType: %w", err) } } } - nTmp, err = s.Ext.DecodeFrom(d) + nTmp, err = s.Ext.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding StellarValueExt: %s", err) + return n, fmt.Errorf("decoding StellarValueExt: %w", err) } return n, nil } @@ -9842,8 +11203,10 @@ func (s StellarValue) MarshalBinary() ([]byte, error) { // UnmarshalBinary implements encoding.BinaryUnmarshaler. func (s *StellarValue) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } @@ -9852,8 +11215,7 @@ var ( _ encoding.BinaryUnmarshaler = (*StellarValue)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. +// xdrType signals that this type represents XDR values defined by this package. func (s StellarValue) xdrType() {} var _ xdrType = (*StellarValue)(nil) @@ -9910,10 +11272,14 @@ func (e LedgerHeaderFlags) EncodeTo(enc *xdr.Encoder) error { var _ decoderFrom = (*LedgerHeaderFlags)(nil) // DecodeFrom decodes this value using the Decoder. -func (e *LedgerHeaderFlags) DecodeFrom(d *xdr.Decoder) (int, error) { +func (e *LedgerHeaderFlags) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding LedgerHeaderFlags: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 v, n, err := d.DecodeInt() if err != nil { - return n, fmt.Errorf("decoding LedgerHeaderFlags: %s", err) + return n, fmt.Errorf("decoding LedgerHeaderFlags: %w", err) } if _, ok := ledgerHeaderFlagsMap[v]; !ok { return n, fmt.Errorf("'%d' is not a valid LedgerHeaderFlags enum value", v) @@ -9933,8 +11299,10 @@ func (s LedgerHeaderFlags) MarshalBinary() ([]byte, error) { // UnmarshalBinary implements encoding.BinaryUnmarshaler. func (s *LedgerHeaderFlags) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } @@ -9943,8 +11311,7 @@ var ( _ encoding.BinaryUnmarshaler = (*LedgerHeaderFlags)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. +// xdrType signals that this type represents XDR values defined by this package. func (s LedgerHeaderFlags) xdrType() {} var _ xdrType = (*LedgerHeaderFlags)(nil) @@ -10003,13 +11370,17 @@ func (u LedgerHeaderExtensionV1Ext) EncodeTo(e *xdr.Encoder) error { var _ decoderFrom = (*LedgerHeaderExtensionV1Ext)(nil) // DecodeFrom decodes this value using the Decoder. -func (u *LedgerHeaderExtensionV1Ext) DecodeFrom(d *xdr.Decoder) (int, error) { +func (u *LedgerHeaderExtensionV1Ext) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding LedgerHeaderExtensionV1Ext: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int u.V, nTmp, err = d.DecodeInt() n += nTmp if err != nil { - return n, fmt.Errorf("decoding Int: %s", err) + return n, fmt.Errorf("decoding Int: %w", err) } switch int32(u.V) { case 0: @@ -10030,8 +11401,10 @@ func (s LedgerHeaderExtensionV1Ext) MarshalBinary() ([]byte, error) { // UnmarshalBinary implements encoding.BinaryUnmarshaler. func (s *LedgerHeaderExtensionV1Ext) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } @@ -10040,8 +11413,7 @@ var ( _ encoding.BinaryUnmarshaler = (*LedgerHeaderExtensionV1Ext)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. +// xdrType signals that this type represents XDR values defined by this package. func (s LedgerHeaderExtensionV1Ext) xdrType() {} var _ xdrType = (*LedgerHeaderExtensionV1Ext)(nil) @@ -10079,18 +11451,22 @@ func (s *LedgerHeaderExtensionV1) EncodeTo(e *xdr.Encoder) error { var _ decoderFrom = (*LedgerHeaderExtensionV1)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *LedgerHeaderExtensionV1) DecodeFrom(d *xdr.Decoder) (int, error) { +func (s *LedgerHeaderExtensionV1) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding LedgerHeaderExtensionV1: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = s.Flags.DecodeFrom(d) + nTmp, err = s.Flags.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Uint32: %s", err) + return n, fmt.Errorf("decoding Uint32: %w", err) } - nTmp, err = s.Ext.DecodeFrom(d) + nTmp, err = s.Ext.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding LedgerHeaderExtensionV1Ext: %s", err) + return n, fmt.Errorf("decoding LedgerHeaderExtensionV1Ext: %w", err) } return n, nil } @@ -10106,8 +11482,10 @@ func (s LedgerHeaderExtensionV1) MarshalBinary() ([]byte, error) { // UnmarshalBinary implements encoding.BinaryUnmarshaler. func (s *LedgerHeaderExtensionV1) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } @@ -10116,8 +11494,7 @@ var ( _ encoding.BinaryUnmarshaler = (*LedgerHeaderExtensionV1)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. +// xdrType signals that this type represents XDR values defined by this package. func (s LedgerHeaderExtensionV1) xdrType() {} var _ xdrType = (*LedgerHeaderExtensionV1)(nil) @@ -10163,7 +11540,7 @@ func NewLedgerHeaderExt(v int32, value interface{}) (result LedgerHeaderExt, err case 1: tv, ok := value.(LedgerHeaderExtensionV1) if !ok { - err = fmt.Errorf("invalid value, must be LedgerHeaderExtensionV1") + err = errors.New("invalid value, must be LedgerHeaderExtensionV1") return } result.V1 = &tv @@ -10218,13 +11595,17 @@ func (u LedgerHeaderExt) EncodeTo(e *xdr.Encoder) error { var _ decoderFrom = (*LedgerHeaderExt)(nil) // DecodeFrom decodes this value using the Decoder. -func (u *LedgerHeaderExt) DecodeFrom(d *xdr.Decoder) (int, error) { +func (u *LedgerHeaderExt) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding LedgerHeaderExt: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int u.V, nTmp, err = d.DecodeInt() n += nTmp if err != nil { - return n, fmt.Errorf("decoding Int: %s", err) + return n, fmt.Errorf("decoding Int: %w", err) } switch int32(u.V) { case 0: @@ -10232,10 +11613,10 @@ func (u *LedgerHeaderExt) DecodeFrom(d *xdr.Decoder) (int, error) { return n, nil case 1: u.V1 = new(LedgerHeaderExtensionV1) - nTmp, err = (*u.V1).DecodeFrom(d) + nTmp, err = (*u.V1).DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding LedgerHeaderExtensionV1: %s", err) + return n, fmt.Errorf("decoding LedgerHeaderExtensionV1: %w", err) } return n, nil } @@ -10253,8 +11634,10 @@ func (s LedgerHeaderExt) MarshalBinary() ([]byte, error) { // UnmarshalBinary implements encoding.BinaryUnmarshaler. func (s *LedgerHeaderExt) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } @@ -10263,8 +11646,7 @@ var ( _ encoding.BinaryUnmarshaler = (*LedgerHeaderExt)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. +// xdrType signals that this type represents XDR values defined by this package. func (s LedgerHeaderExt) xdrType() {} var _ xdrType = (*LedgerHeaderExt)(nil) @@ -10384,85 +11766,89 @@ func (s *LedgerHeader) EncodeTo(e *xdr.Encoder) error { var _ decoderFrom = (*LedgerHeader)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *LedgerHeader) DecodeFrom(d *xdr.Decoder) (int, error) { +func (s *LedgerHeader) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding LedgerHeader: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = s.LedgerVersion.DecodeFrom(d) + nTmp, err = s.LedgerVersion.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Uint32: %s", err) + return n, fmt.Errorf("decoding Uint32: %w", err) } - nTmp, err = s.PreviousLedgerHash.DecodeFrom(d) + nTmp, err = s.PreviousLedgerHash.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Hash: %s", err) + return n, fmt.Errorf("decoding Hash: %w", err) } - nTmp, err = s.ScpValue.DecodeFrom(d) + nTmp, err = s.ScpValue.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding StellarValue: %s", err) + return n, fmt.Errorf("decoding StellarValue: %w", err) } - nTmp, err = s.TxSetResultHash.DecodeFrom(d) + nTmp, err = s.TxSetResultHash.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Hash: %s", err) + return n, fmt.Errorf("decoding Hash: %w", err) } - nTmp, err = s.BucketListHash.DecodeFrom(d) + nTmp, err = s.BucketListHash.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Hash: %s", err) + return n, fmt.Errorf("decoding Hash: %w", err) } - nTmp, err = s.LedgerSeq.DecodeFrom(d) + nTmp, err = s.LedgerSeq.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Uint32: %s", err) + return n, fmt.Errorf("decoding Uint32: %w", err) } - nTmp, err = s.TotalCoins.DecodeFrom(d) + nTmp, err = s.TotalCoins.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Int64: %s", err) + return n, fmt.Errorf("decoding Int64: %w", err) } - nTmp, err = s.FeePool.DecodeFrom(d) + nTmp, err = s.FeePool.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Int64: %s", err) + return n, fmt.Errorf("decoding Int64: %w", err) } - nTmp, err = s.InflationSeq.DecodeFrom(d) + nTmp, err = s.InflationSeq.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Uint32: %s", err) + return n, fmt.Errorf("decoding Uint32: %w", err) } - nTmp, err = s.IdPool.DecodeFrom(d) + nTmp, err = s.IdPool.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Uint64: %s", err) + return n, fmt.Errorf("decoding Uint64: %w", err) } - nTmp, err = s.BaseFee.DecodeFrom(d) + nTmp, err = s.BaseFee.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Uint32: %s", err) + return n, fmt.Errorf("decoding Uint32: %w", err) } - nTmp, err = s.BaseReserve.DecodeFrom(d) + nTmp, err = s.BaseReserve.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Uint32: %s", err) + return n, fmt.Errorf("decoding Uint32: %w", err) } - nTmp, err = s.MaxTxSetSize.DecodeFrom(d) + nTmp, err = s.MaxTxSetSize.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Uint32: %s", err) + return n, fmt.Errorf("decoding Uint32: %w", err) } for i := 0; i < len(s.SkipList); i++ { - nTmp, err = s.SkipList[i].DecodeFrom(d) + nTmp, err = s.SkipList[i].DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Hash: %s", err) + return n, fmt.Errorf("decoding Hash: %w", err) } } - nTmp, err = s.Ext.DecodeFrom(d) + nTmp, err = s.Ext.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding LedgerHeaderExt: %s", err) + return n, fmt.Errorf("decoding LedgerHeaderExt: %w", err) } return n, nil } @@ -10478,8 +11864,10 @@ func (s LedgerHeader) MarshalBinary() ([]byte, error) { // UnmarshalBinary implements encoding.BinaryUnmarshaler. func (s *LedgerHeader) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } @@ -10488,8 +11876,7 @@ var ( _ encoding.BinaryUnmarshaler = (*LedgerHeader)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. +// xdrType signals that this type represents XDR values defined by this package. func (s LedgerHeader) xdrType() {} var _ xdrType = (*LedgerHeader)(nil) @@ -10502,16 +11889,20 @@ var _ xdrType = (*LedgerHeader)(nil) // LEDGER_UPGRADE_BASE_FEE = 2, // LEDGER_UPGRADE_MAX_TX_SET_SIZE = 3, // LEDGER_UPGRADE_BASE_RESERVE = 4, -// LEDGER_UPGRADE_FLAGS = 5 +// LEDGER_UPGRADE_FLAGS = 5, +// LEDGER_UPGRADE_CONFIG = 6, +// LEDGER_UPGRADE_MAX_SOROBAN_TX_SET_SIZE = 7 // }; type LedgerUpgradeType int32 const ( - LedgerUpgradeTypeLedgerUpgradeVersion LedgerUpgradeType = 1 - LedgerUpgradeTypeLedgerUpgradeBaseFee LedgerUpgradeType = 2 - LedgerUpgradeTypeLedgerUpgradeMaxTxSetSize LedgerUpgradeType = 3 - LedgerUpgradeTypeLedgerUpgradeBaseReserve LedgerUpgradeType = 4 - LedgerUpgradeTypeLedgerUpgradeFlags LedgerUpgradeType = 5 + LedgerUpgradeTypeLedgerUpgradeVersion LedgerUpgradeType = 1 + LedgerUpgradeTypeLedgerUpgradeBaseFee LedgerUpgradeType = 2 + LedgerUpgradeTypeLedgerUpgradeMaxTxSetSize LedgerUpgradeType = 3 + LedgerUpgradeTypeLedgerUpgradeBaseReserve LedgerUpgradeType = 4 + LedgerUpgradeTypeLedgerUpgradeFlags LedgerUpgradeType = 5 + LedgerUpgradeTypeLedgerUpgradeConfig LedgerUpgradeType = 6 + LedgerUpgradeTypeLedgerUpgradeMaxSorobanTxSetSize LedgerUpgradeType = 7 ) var ledgerUpgradeTypeMap = map[int32]string{ @@ -10520,6 +11911,8 @@ var ledgerUpgradeTypeMap = map[int32]string{ 3: "LedgerUpgradeTypeLedgerUpgradeMaxTxSetSize", 4: "LedgerUpgradeTypeLedgerUpgradeBaseReserve", 5: "LedgerUpgradeTypeLedgerUpgradeFlags", + 6: "LedgerUpgradeTypeLedgerUpgradeConfig", + 7: "LedgerUpgradeTypeLedgerUpgradeMaxSorobanTxSetSize", } // ValidEnum validates a proposed value for this enum. Implements @@ -10547,10 +11940,14 @@ func (e LedgerUpgradeType) EncodeTo(enc *xdr.Encoder) error { var _ decoderFrom = (*LedgerUpgradeType)(nil) // DecodeFrom decodes this value using the Decoder. -func (e *LedgerUpgradeType) DecodeFrom(d *xdr.Decoder) (int, error) { +func (e *LedgerUpgradeType) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding LedgerUpgradeType: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 v, n, err := d.DecodeInt() if err != nil { - return n, fmt.Errorf("decoding LedgerUpgradeType: %s", err) + return n, fmt.Errorf("decoding LedgerUpgradeType: %w", err) } if _, ok := ledgerUpgradeTypeMap[v]; !ok { return n, fmt.Errorf("'%d' is not a valid LedgerUpgradeType enum value", v) @@ -10570,8 +11967,10 @@ func (s LedgerUpgradeType) MarshalBinary() ([]byte, error) { // UnmarshalBinary implements encoding.BinaryUnmarshaler. func (s *LedgerUpgradeType) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } @@ -10580,12 +11979,85 @@ var ( _ encoding.BinaryUnmarshaler = (*LedgerUpgradeType)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. +// xdrType signals that this type represents XDR values defined by this package. func (s LedgerUpgradeType) xdrType() {} var _ xdrType = (*LedgerUpgradeType)(nil) +// ConfigUpgradeSetKey is an XDR Struct defines as: +// +// struct ConfigUpgradeSetKey { +// Hash contractID; +// Hash contentHash; +// }; +type ConfigUpgradeSetKey struct { + ContractId Hash + ContentHash Hash +} + +// EncodeTo encodes this value using the Encoder. +func (s *ConfigUpgradeSetKey) EncodeTo(e *xdr.Encoder) error { + var err error + if err = s.ContractId.EncodeTo(e); err != nil { + return err + } + if err = s.ContentHash.EncodeTo(e); err != nil { + return err + } + return nil +} + +var _ decoderFrom = (*ConfigUpgradeSetKey)(nil) + +// DecodeFrom decodes this value using the Decoder. +func (s *ConfigUpgradeSetKey) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding ConfigUpgradeSetKey: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + var err error + var n, nTmp int + nTmp, err = s.ContractId.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Hash: %w", err) + } + nTmp, err = s.ContentHash.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Hash: %w", err) + } + return n, nil +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (s ConfigUpgradeSetKey) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *ConfigUpgradeSetKey) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} + +var ( + _ encoding.BinaryMarshaler = (*ConfigUpgradeSetKey)(nil) + _ encoding.BinaryUnmarshaler = (*ConfigUpgradeSetKey)(nil) +) + +// xdrType signals that this type represents XDR values defined by this package. +func (s ConfigUpgradeSetKey) xdrType() {} + +var _ xdrType = (*ConfigUpgradeSetKey)(nil) + // LedgerUpgrade is an XDR Union defines as: // // union LedgerUpgrade switch (LedgerUpgradeType type) @@ -10600,14 +12072,23 @@ var _ xdrType = (*LedgerUpgradeType)(nil) // uint32 newBaseReserve; // update baseReserve // case LEDGER_UPGRADE_FLAGS: // uint32 newFlags; // update flags +// case LEDGER_UPGRADE_CONFIG: +// // Update arbitrary `ConfigSetting` entries identified by the key. +// ConfigUpgradeSetKey newConfig; +// case LEDGER_UPGRADE_MAX_SOROBAN_TX_SET_SIZE: +// // Update ConfigSettingContractExecutionLanesV0.ledgerMaxTxCount without +// // using `LEDGER_UPGRADE_CONFIG`. +// uint32 newMaxSorobanTxSetSize; // }; type LedgerUpgrade struct { - Type LedgerUpgradeType - NewLedgerVersion *Uint32 - NewBaseFee *Uint32 - NewMaxTxSetSize *Uint32 - NewBaseReserve *Uint32 - NewFlags *Uint32 + Type LedgerUpgradeType + NewLedgerVersion *Uint32 + NewBaseFee *Uint32 + NewMaxTxSetSize *Uint32 + NewBaseReserve *Uint32 + NewFlags *Uint32 + NewConfig *ConfigUpgradeSetKey + NewMaxSorobanTxSetSize *Uint32 } // SwitchFieldName returns the field name in which this union's @@ -10630,6 +12111,10 @@ func (u LedgerUpgrade) ArmForSwitch(sw int32) (string, bool) { return "NewBaseReserve", true case LedgerUpgradeTypeLedgerUpgradeFlags: return "NewFlags", true + case LedgerUpgradeTypeLedgerUpgradeConfig: + return "NewConfig", true + case LedgerUpgradeTypeLedgerUpgradeMaxSorobanTxSetSize: + return "NewMaxSorobanTxSetSize", true } return "-", false } @@ -10641,38 +12126,52 @@ func NewLedgerUpgrade(aType LedgerUpgradeType, value interface{}) (result Ledger case LedgerUpgradeTypeLedgerUpgradeVersion: tv, ok := value.(Uint32) if !ok { - err = fmt.Errorf("invalid value, must be Uint32") + err = errors.New("invalid value, must be Uint32") return } result.NewLedgerVersion = &tv case LedgerUpgradeTypeLedgerUpgradeBaseFee: tv, ok := value.(Uint32) if !ok { - err = fmt.Errorf("invalid value, must be Uint32") + err = errors.New("invalid value, must be Uint32") return } result.NewBaseFee = &tv case LedgerUpgradeTypeLedgerUpgradeMaxTxSetSize: tv, ok := value.(Uint32) if !ok { - err = fmt.Errorf("invalid value, must be Uint32") + err = errors.New("invalid value, must be Uint32") return } result.NewMaxTxSetSize = &tv case LedgerUpgradeTypeLedgerUpgradeBaseReserve: tv, ok := value.(Uint32) if !ok { - err = fmt.Errorf("invalid value, must be Uint32") + err = errors.New("invalid value, must be Uint32") return } result.NewBaseReserve = &tv case LedgerUpgradeTypeLedgerUpgradeFlags: tv, ok := value.(Uint32) if !ok { - err = fmt.Errorf("invalid value, must be Uint32") + err = errors.New("invalid value, must be Uint32") return } result.NewFlags = &tv + case LedgerUpgradeTypeLedgerUpgradeConfig: + tv, ok := value.(ConfigUpgradeSetKey) + if !ok { + err = errors.New("invalid value, must be ConfigUpgradeSetKey") + return + } + result.NewConfig = &tv + case LedgerUpgradeTypeLedgerUpgradeMaxSorobanTxSetSize: + tv, ok := value.(Uint32) + if !ok { + err = errors.New("invalid value, must be Uint32") + return + } + result.NewMaxSorobanTxSetSize = &tv } return } @@ -10802,6 +12301,56 @@ func (u LedgerUpgrade) GetNewFlags() (result Uint32, ok bool) { return } +// MustNewConfig retrieves the NewConfig value from the union, +// panicing if the value is not set. +func (u LedgerUpgrade) MustNewConfig() ConfigUpgradeSetKey { + val, ok := u.GetNewConfig() + + if !ok { + panic("arm NewConfig is not set") + } + + return val +} + +// GetNewConfig retrieves the NewConfig value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u LedgerUpgrade) GetNewConfig() (result ConfigUpgradeSetKey, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) + + if armName == "NewConfig" { + result = *u.NewConfig + ok = true + } + + return +} + +// MustNewMaxSorobanTxSetSize retrieves the NewMaxSorobanTxSetSize value from the union, +// panicing if the value is not set. +func (u LedgerUpgrade) MustNewMaxSorobanTxSetSize() Uint32 { + val, ok := u.GetNewMaxSorobanTxSetSize() + + if !ok { + panic("arm NewMaxSorobanTxSetSize is not set") + } + + return val +} + +// GetNewMaxSorobanTxSetSize retrieves the NewMaxSorobanTxSetSize value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u LedgerUpgrade) GetNewMaxSorobanTxSetSize() (result Uint32, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) + + if armName == "NewMaxSorobanTxSetSize" { + result = *u.NewMaxSorobanTxSetSize + ok = true + } + + return +} + // EncodeTo encodes this value using the Encoder. func (u LedgerUpgrade) EncodeTo(e *xdr.Encoder) error { var err error @@ -10834,6 +12383,16 @@ func (u LedgerUpgrade) EncodeTo(e *xdr.Encoder) error { return err } return nil + case LedgerUpgradeTypeLedgerUpgradeConfig: + if err = (*u.NewConfig).EncodeTo(e); err != nil { + return err + } + return nil + case LedgerUpgradeTypeLedgerUpgradeMaxSorobanTxSetSize: + if err = (*u.NewMaxSorobanTxSetSize).EncodeTo(e); err != nil { + return err + } + return nil } return fmt.Errorf("Type (LedgerUpgradeType) switch value '%d' is not valid for union LedgerUpgrade", u.Type) } @@ -10841,53 +12400,73 @@ func (u LedgerUpgrade) EncodeTo(e *xdr.Encoder) error { var _ decoderFrom = (*LedgerUpgrade)(nil) // DecodeFrom decodes this value using the Decoder. -func (u *LedgerUpgrade) DecodeFrom(d *xdr.Decoder) (int, error) { +func (u *LedgerUpgrade) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding LedgerUpgrade: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = u.Type.DecodeFrom(d) + nTmp, err = u.Type.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding LedgerUpgradeType: %s", err) + return n, fmt.Errorf("decoding LedgerUpgradeType: %w", err) } switch LedgerUpgradeType(u.Type) { case LedgerUpgradeTypeLedgerUpgradeVersion: u.NewLedgerVersion = new(Uint32) - nTmp, err = (*u.NewLedgerVersion).DecodeFrom(d) + nTmp, err = (*u.NewLedgerVersion).DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Uint32: %s", err) + return n, fmt.Errorf("decoding Uint32: %w", err) } return n, nil case LedgerUpgradeTypeLedgerUpgradeBaseFee: u.NewBaseFee = new(Uint32) - nTmp, err = (*u.NewBaseFee).DecodeFrom(d) + nTmp, err = (*u.NewBaseFee).DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Uint32: %s", err) + return n, fmt.Errorf("decoding Uint32: %w", err) } return n, nil case LedgerUpgradeTypeLedgerUpgradeMaxTxSetSize: u.NewMaxTxSetSize = new(Uint32) - nTmp, err = (*u.NewMaxTxSetSize).DecodeFrom(d) + nTmp, err = (*u.NewMaxTxSetSize).DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Uint32: %s", err) + return n, fmt.Errorf("decoding Uint32: %w", err) } return n, nil case LedgerUpgradeTypeLedgerUpgradeBaseReserve: u.NewBaseReserve = new(Uint32) - nTmp, err = (*u.NewBaseReserve).DecodeFrom(d) + nTmp, err = (*u.NewBaseReserve).DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Uint32: %s", err) + return n, fmt.Errorf("decoding Uint32: %w", err) } return n, nil case LedgerUpgradeTypeLedgerUpgradeFlags: u.NewFlags = new(Uint32) - nTmp, err = (*u.NewFlags).DecodeFrom(d) + nTmp, err = (*u.NewFlags).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Uint32: %w", err) + } + return n, nil + case LedgerUpgradeTypeLedgerUpgradeConfig: + u.NewConfig = new(ConfigUpgradeSetKey) + nTmp, err = (*u.NewConfig).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ConfigUpgradeSetKey: %w", err) + } + return n, nil + case LedgerUpgradeTypeLedgerUpgradeMaxSorobanTxSetSize: + u.NewMaxSorobanTxSetSize = new(Uint32) + nTmp, err = (*u.NewMaxSorobanTxSetSize).DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Uint32: %s", err) + return n, fmt.Errorf("decoding Uint32: %w", err) } return n, nil } @@ -10905,8 +12484,10 @@ func (s LedgerUpgrade) MarshalBinary() ([]byte, error) { // UnmarshalBinary implements encoding.BinaryUnmarshaler. func (s *LedgerUpgrade) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } @@ -10915,12 +12496,95 @@ var ( _ encoding.BinaryUnmarshaler = (*LedgerUpgrade)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. +// xdrType signals that this type represents XDR values defined by this package. func (s LedgerUpgrade) xdrType() {} var _ xdrType = (*LedgerUpgrade)(nil) +// ConfigUpgradeSet is an XDR Struct defines as: +// +// struct ConfigUpgradeSet { +// ConfigSettingEntry updatedEntry<>; +// }; +type ConfigUpgradeSet struct { + UpdatedEntry []ConfigSettingEntry +} + +// EncodeTo encodes this value using the Encoder. +func (s *ConfigUpgradeSet) EncodeTo(e *xdr.Encoder) error { + var err error + if _, err = e.EncodeUint(uint32(len(s.UpdatedEntry))); err != nil { + return err + } + for i := 0; i < len(s.UpdatedEntry); i++ { + if err = s.UpdatedEntry[i].EncodeTo(e); err != nil { + return err + } + } + return nil +} + +var _ decoderFrom = (*ConfigUpgradeSet)(nil) + +// DecodeFrom decodes this value using the Decoder. +func (s *ConfigUpgradeSet) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding ConfigUpgradeSet: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + var err error + var n, nTmp int + var l uint32 + l, nTmp, err = d.DecodeUint() + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ConfigSettingEntry: %w", err) + } + s.UpdatedEntry = nil + if l > 0 { + if il, ok := d.InputLen(); ok && uint(il) < uint(l) { + return n, fmt.Errorf("decoding ConfigSettingEntry: length (%d) exceeds remaining input length (%d)", l, il) + } + s.UpdatedEntry = make([]ConfigSettingEntry, l) + for i := uint32(0); i < l; i++ { + nTmp, err = s.UpdatedEntry[i].DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ConfigSettingEntry: %w", err) + } + } + } + return n, nil +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (s ConfigUpgradeSet) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *ConfigUpgradeSet) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} + +var ( + _ encoding.BinaryMarshaler = (*ConfigUpgradeSet)(nil) + _ encoding.BinaryUnmarshaler = (*ConfigUpgradeSet)(nil) +) + +// xdrType signals that this type represents XDR values defined by this package. +func (s ConfigUpgradeSet) xdrType() {} + +var _ xdrType = (*ConfigUpgradeSet)(nil) + // BucketEntryType is an XDR Enum defines as: // // enum BucketEntryType @@ -10973,10 +12637,14 @@ func (e BucketEntryType) EncodeTo(enc *xdr.Encoder) error { var _ decoderFrom = (*BucketEntryType)(nil) // DecodeFrom decodes this value using the Decoder. -func (e *BucketEntryType) DecodeFrom(d *xdr.Decoder) (int, error) { +func (e *BucketEntryType) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding BucketEntryType: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 v, n, err := d.DecodeInt() if err != nil { - return n, fmt.Errorf("decoding BucketEntryType: %s", err) + return n, fmt.Errorf("decoding BucketEntryType: %w", err) } if _, ok := bucketEntryTypeMap[v]; !ok { return n, fmt.Errorf("'%d' is not a valid BucketEntryType enum value", v) @@ -10996,8 +12664,10 @@ func (s BucketEntryType) MarshalBinary() ([]byte, error) { // UnmarshalBinary implements encoding.BinaryUnmarshaler. func (s *BucketEntryType) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } @@ -11006,8 +12676,7 @@ var ( _ encoding.BinaryUnmarshaler = (*BucketEntryType)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. +// xdrType signals that this type represents XDR values defined by this package. func (s BucketEntryType) xdrType() {} var _ xdrType = (*BucketEntryType)(nil) @@ -11066,13 +12735,17 @@ func (u BucketMetadataExt) EncodeTo(e *xdr.Encoder) error { var _ decoderFrom = (*BucketMetadataExt)(nil) // DecodeFrom decodes this value using the Decoder. -func (u *BucketMetadataExt) DecodeFrom(d *xdr.Decoder) (int, error) { +func (u *BucketMetadataExt) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding BucketMetadataExt: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int u.V, nTmp, err = d.DecodeInt() n += nTmp if err != nil { - return n, fmt.Errorf("decoding Int: %s", err) + return n, fmt.Errorf("decoding Int: %w", err) } switch int32(u.V) { case 0: @@ -11093,8 +12766,10 @@ func (s BucketMetadataExt) MarshalBinary() ([]byte, error) { // UnmarshalBinary implements encoding.BinaryUnmarshaler. func (s *BucketMetadataExt) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } @@ -11103,8 +12778,7 @@ var ( _ encoding.BinaryUnmarshaler = (*BucketMetadataExt)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. +// xdrType signals that this type represents XDR values defined by this package. func (s BucketMetadataExt) xdrType() {} var _ xdrType = (*BucketMetadataExt)(nil) @@ -11144,18 +12818,22 @@ func (s *BucketMetadata) EncodeTo(e *xdr.Encoder) error { var _ decoderFrom = (*BucketMetadata)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *BucketMetadata) DecodeFrom(d *xdr.Decoder) (int, error) { +func (s *BucketMetadata) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding BucketMetadata: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = s.LedgerVersion.DecodeFrom(d) + nTmp, err = s.LedgerVersion.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Uint32: %s", err) + return n, fmt.Errorf("decoding Uint32: %w", err) } - nTmp, err = s.Ext.DecodeFrom(d) + nTmp, err = s.Ext.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding BucketMetadataExt: %s", err) + return n, fmt.Errorf("decoding BucketMetadataExt: %w", err) } return n, nil } @@ -11171,8 +12849,10 @@ func (s BucketMetadata) MarshalBinary() ([]byte, error) { // UnmarshalBinary implements encoding.BinaryUnmarshaler. func (s *BucketMetadata) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } @@ -11181,8 +12861,7 @@ var ( _ encoding.BinaryUnmarshaler = (*BucketMetadata)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. +// xdrType signals that this type represents XDR values defined by this package. func (s BucketMetadata) xdrType() {} var _ xdrType = (*BucketMetadata)(nil) @@ -11236,28 +12915,28 @@ func NewBucketEntry(aType BucketEntryType, value interface{}) (result BucketEntr case BucketEntryTypeLiveentry: tv, ok := value.(LedgerEntry) if !ok { - err = fmt.Errorf("invalid value, must be LedgerEntry") + err = errors.New("invalid value, must be LedgerEntry") return } result.LiveEntry = &tv case BucketEntryTypeInitentry: tv, ok := value.(LedgerEntry) if !ok { - err = fmt.Errorf("invalid value, must be LedgerEntry") + err = errors.New("invalid value, must be LedgerEntry") return } result.LiveEntry = &tv case BucketEntryTypeDeadentry: tv, ok := value.(LedgerKey) if !ok { - err = fmt.Errorf("invalid value, must be LedgerKey") + err = errors.New("invalid value, must be LedgerKey") return } result.DeadEntry = &tv case BucketEntryTypeMetaentry: tv, ok := value.(BucketMetadata) if !ok { - err = fmt.Errorf("invalid value, must be BucketMetadata") + err = errors.New("invalid value, must be BucketMetadata") return } result.MetaEntry = &tv @@ -11374,45 +13053,49 @@ func (u BucketEntry) EncodeTo(e *xdr.Encoder) error { var _ decoderFrom = (*BucketEntry)(nil) // DecodeFrom decodes this value using the Decoder. -func (u *BucketEntry) DecodeFrom(d *xdr.Decoder) (int, error) { +func (u *BucketEntry) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding BucketEntry: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = u.Type.DecodeFrom(d) + nTmp, err = u.Type.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding BucketEntryType: %s", err) + return n, fmt.Errorf("decoding BucketEntryType: %w", err) } switch BucketEntryType(u.Type) { case BucketEntryTypeLiveentry: u.LiveEntry = new(LedgerEntry) - nTmp, err = (*u.LiveEntry).DecodeFrom(d) + nTmp, err = (*u.LiveEntry).DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding LedgerEntry: %s", err) + return n, fmt.Errorf("decoding LedgerEntry: %w", err) } return n, nil case BucketEntryTypeInitentry: u.LiveEntry = new(LedgerEntry) - nTmp, err = (*u.LiveEntry).DecodeFrom(d) + nTmp, err = (*u.LiveEntry).DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding LedgerEntry: %s", err) + return n, fmt.Errorf("decoding LedgerEntry: %w", err) } return n, nil case BucketEntryTypeDeadentry: u.DeadEntry = new(LedgerKey) - nTmp, err = (*u.DeadEntry).DecodeFrom(d) + nTmp, err = (*u.DeadEntry).DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding LedgerKey: %s", err) + return n, fmt.Errorf("decoding LedgerKey: %w", err) } return n, nil case BucketEntryTypeMetaentry: u.MetaEntry = new(BucketMetadata) - nTmp, err = (*u.MetaEntry).DecodeFrom(d) + nTmp, err = (*u.MetaEntry).DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding BucketMetadata: %s", err) + return n, fmt.Errorf("decoding BucketMetadata: %w", err) } return n, nil } @@ -11430,8 +13113,10 @@ func (s BucketEntry) MarshalBinary() ([]byte, error) { // UnmarshalBinary implements encoding.BinaryUnmarshaler. func (s *BucketEntry) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } @@ -11440,8 +13125,7 @@ var ( _ encoding.BinaryUnmarshaler = (*BucketEntry)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. +// xdrType signals that this type represents XDR values defined by this package. func (s BucketEntry) xdrType() {} var _ xdrType = (*BucketEntry)(nil) @@ -11489,10 +13173,14 @@ func (e TxSetComponentType) EncodeTo(enc *xdr.Encoder) error { var _ decoderFrom = (*TxSetComponentType)(nil) // DecodeFrom decodes this value using the Decoder. -func (e *TxSetComponentType) DecodeFrom(d *xdr.Decoder) (int, error) { +func (e *TxSetComponentType) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding TxSetComponentType: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 v, n, err := d.DecodeInt() if err != nil { - return n, fmt.Errorf("decoding TxSetComponentType: %s", err) + return n, fmt.Errorf("decoding TxSetComponentType: %w", err) } if _, ok := txSetComponentTypeMap[v]; !ok { return n, fmt.Errorf("'%d' is not a valid TxSetComponentType enum value", v) @@ -11512,8 +13200,10 @@ func (s TxSetComponentType) MarshalBinary() ([]byte, error) { // UnmarshalBinary implements encoding.BinaryUnmarshaler. func (s *TxSetComponentType) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } @@ -11522,8 +13212,7 @@ var ( _ encoding.BinaryUnmarshaler = (*TxSetComponentType)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. +// xdrType signals that this type represents XDR values defined by this package. func (s TxSetComponentType) xdrType() {} var _ xdrType = (*TxSetComponentType)(nil) @@ -11565,38 +13254,45 @@ func (s *TxSetComponentTxsMaybeDiscountedFee) EncodeTo(e *xdr.Encoder) error { var _ decoderFrom = (*TxSetComponentTxsMaybeDiscountedFee)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *TxSetComponentTxsMaybeDiscountedFee) DecodeFrom(d *xdr.Decoder) (int, error) { +func (s *TxSetComponentTxsMaybeDiscountedFee) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding TxSetComponentTxsMaybeDiscountedFee: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int var b bool b, nTmp, err = d.DecodeBool() n += nTmp if err != nil { - return n, fmt.Errorf("decoding Int64: %s", err) + return n, fmt.Errorf("decoding Int64: %w", err) } s.BaseFee = nil if b { s.BaseFee = new(Int64) - nTmp, err = s.BaseFee.DecodeFrom(d) + nTmp, err = s.BaseFee.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Int64: %s", err) + return n, fmt.Errorf("decoding Int64: %w", err) } } var l uint32 l, nTmp, err = d.DecodeUint() n += nTmp if err != nil { - return n, fmt.Errorf("decoding TransactionEnvelope: %s", err) + return n, fmt.Errorf("decoding TransactionEnvelope: %w", err) } s.Txs = nil if l > 0 { + if il, ok := d.InputLen(); ok && uint(il) < uint(l) { + return n, fmt.Errorf("decoding TransactionEnvelope: length (%d) exceeds remaining input length (%d)", l, il) + } s.Txs = make([]TransactionEnvelope, l) for i := uint32(0); i < l; i++ { - nTmp, err = s.Txs[i].DecodeFrom(d) + nTmp, err = s.Txs[i].DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding TransactionEnvelope: %s", err) + return n, fmt.Errorf("decoding TransactionEnvelope: %w", err) } } } @@ -11614,8 +13310,10 @@ func (s TxSetComponentTxsMaybeDiscountedFee) MarshalBinary() ([]byte, error) { // UnmarshalBinary implements encoding.BinaryUnmarshaler. func (s *TxSetComponentTxsMaybeDiscountedFee) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } @@ -11624,8 +13322,7 @@ var ( _ encoding.BinaryUnmarshaler = (*TxSetComponentTxsMaybeDiscountedFee)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. +// xdrType signals that this type represents XDR values defined by this package. func (s TxSetComponentTxsMaybeDiscountedFee) xdrType() {} var _ xdrType = (*TxSetComponentTxsMaybeDiscountedFee)(nil) @@ -11669,7 +13366,7 @@ func NewTxSetComponent(aType TxSetComponentType, value interface{}) (result TxSe case TxSetComponentTypeTxsetCompTxsMaybeDiscountedFee: tv, ok := value.(TxSetComponentTxsMaybeDiscountedFee) if !ok { - err = fmt.Errorf("invalid value, must be TxSetComponentTxsMaybeDiscountedFee") + err = errors.New("invalid value, must be TxSetComponentTxsMaybeDiscountedFee") return } result.TxsMaybeDiscountedFee = &tv @@ -11721,21 +13418,25 @@ func (u TxSetComponent) EncodeTo(e *xdr.Encoder) error { var _ decoderFrom = (*TxSetComponent)(nil) // DecodeFrom decodes this value using the Decoder. -func (u *TxSetComponent) DecodeFrom(d *xdr.Decoder) (int, error) { +func (u *TxSetComponent) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding TxSetComponent: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = u.Type.DecodeFrom(d) + nTmp, err = u.Type.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding TxSetComponentType: %s", err) + return n, fmt.Errorf("decoding TxSetComponentType: %w", err) } switch TxSetComponentType(u.Type) { case TxSetComponentTypeTxsetCompTxsMaybeDiscountedFee: u.TxsMaybeDiscountedFee = new(TxSetComponentTxsMaybeDiscountedFee) - nTmp, err = (*u.TxsMaybeDiscountedFee).DecodeFrom(d) + nTmp, err = (*u.TxsMaybeDiscountedFee).DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding TxSetComponentTxsMaybeDiscountedFee: %s", err) + return n, fmt.Errorf("decoding TxSetComponentTxsMaybeDiscountedFee: %w", err) } return n, nil } @@ -11753,8 +13454,10 @@ func (s TxSetComponent) MarshalBinary() ([]byte, error) { // UnmarshalBinary implements encoding.BinaryUnmarshaler. func (s *TxSetComponent) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } @@ -11763,8 +13466,7 @@ var ( _ encoding.BinaryUnmarshaler = (*TxSetComponent)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. +// xdrType signals that this type represents XDR values defined by this package. func (s TxSetComponent) xdrType() {} var _ xdrType = (*TxSetComponent)(nil) @@ -11804,7 +13506,7 @@ func NewTransactionPhase(v int32, value interface{}) (result TransactionPhase, e case 0: tv, ok := value.([]TxSetComponent) if !ok { - err = fmt.Errorf("invalid value, must be []TxSetComponent") + err = errors.New("invalid value, must be []TxSetComponent") return } result.V0Components = &tv @@ -11861,13 +13563,17 @@ func (u TransactionPhase) EncodeTo(e *xdr.Encoder) error { var _ decoderFrom = (*TransactionPhase)(nil) // DecodeFrom decodes this value using the Decoder. -func (u *TransactionPhase) DecodeFrom(d *xdr.Decoder) (int, error) { +func (u *TransactionPhase) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding TransactionPhase: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int u.V, nTmp, err = d.DecodeInt() n += nTmp if err != nil { - return n, fmt.Errorf("decoding Int: %s", err) + return n, fmt.Errorf("decoding Int: %w", err) } switch int32(u.V) { case 0: @@ -11876,16 +13582,19 @@ func (u *TransactionPhase) DecodeFrom(d *xdr.Decoder) (int, error) { l, nTmp, err = d.DecodeUint() n += nTmp if err != nil { - return n, fmt.Errorf("decoding TxSetComponent: %s", err) + return n, fmt.Errorf("decoding TxSetComponent: %w", err) } (*u.V0Components) = nil if l > 0 { + if il, ok := d.InputLen(); ok && uint(il) < uint(l) { + return n, fmt.Errorf("decoding TxSetComponent: length (%d) exceeds remaining input length (%d)", l, il) + } (*u.V0Components) = make([]TxSetComponent, l) for i := uint32(0); i < l; i++ { - nTmp, err = (*u.V0Components)[i].DecodeFrom(d) + nTmp, err = (*u.V0Components)[i].DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding TxSetComponent: %s", err) + return n, fmt.Errorf("decoding TxSetComponent: %w", err) } } } @@ -11905,8 +13614,10 @@ func (s TransactionPhase) MarshalBinary() ([]byte, error) { // UnmarshalBinary implements encoding.BinaryUnmarshaler. func (s *TransactionPhase) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } @@ -11915,8 +13626,7 @@ var ( _ encoding.BinaryUnmarshaler = (*TransactionPhase)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. +// xdrType signals that this type represents XDR values defined by this package. func (s TransactionPhase) xdrType() {} var _ xdrType = (*TransactionPhase)(nil) @@ -11953,28 +13663,35 @@ func (s *TransactionSet) EncodeTo(e *xdr.Encoder) error { var _ decoderFrom = (*TransactionSet)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *TransactionSet) DecodeFrom(d *xdr.Decoder) (int, error) { +func (s *TransactionSet) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding TransactionSet: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = s.PreviousLedgerHash.DecodeFrom(d) + nTmp, err = s.PreviousLedgerHash.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Hash: %s", err) + return n, fmt.Errorf("decoding Hash: %w", err) } var l uint32 l, nTmp, err = d.DecodeUint() n += nTmp if err != nil { - return n, fmt.Errorf("decoding TransactionEnvelope: %s", err) + return n, fmt.Errorf("decoding TransactionEnvelope: %w", err) } s.Txs = nil if l > 0 { + if il, ok := d.InputLen(); ok && uint(il) < uint(l) { + return n, fmt.Errorf("decoding TransactionEnvelope: length (%d) exceeds remaining input length (%d)", l, il) + } s.Txs = make([]TransactionEnvelope, l) for i := uint32(0); i < l; i++ { - nTmp, err = s.Txs[i].DecodeFrom(d) + nTmp, err = s.Txs[i].DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding TransactionEnvelope: %s", err) + return n, fmt.Errorf("decoding TransactionEnvelope: %w", err) } } } @@ -11992,8 +13709,10 @@ func (s TransactionSet) MarshalBinary() ([]byte, error) { // UnmarshalBinary implements encoding.BinaryUnmarshaler. func (s *TransactionSet) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } @@ -12002,8 +13721,7 @@ var ( _ encoding.BinaryUnmarshaler = (*TransactionSet)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. +// xdrType signals that this type represents XDR values defined by this package. func (s TransactionSet) xdrType() {} var _ xdrType = (*TransactionSet)(nil) @@ -12040,28 +13758,35 @@ func (s *TransactionSetV1) EncodeTo(e *xdr.Encoder) error { var _ decoderFrom = (*TransactionSetV1)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *TransactionSetV1) DecodeFrom(d *xdr.Decoder) (int, error) { +func (s *TransactionSetV1) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding TransactionSetV1: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = s.PreviousLedgerHash.DecodeFrom(d) + nTmp, err = s.PreviousLedgerHash.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Hash: %s", err) + return n, fmt.Errorf("decoding Hash: %w", err) } var l uint32 l, nTmp, err = d.DecodeUint() n += nTmp if err != nil { - return n, fmt.Errorf("decoding TransactionPhase: %s", err) + return n, fmt.Errorf("decoding TransactionPhase: %w", err) } s.Phases = nil if l > 0 { + if il, ok := d.InputLen(); ok && uint(il) < uint(l) { + return n, fmt.Errorf("decoding TransactionPhase: length (%d) exceeds remaining input length (%d)", l, il) + } s.Phases = make([]TransactionPhase, l) for i := uint32(0); i < l; i++ { - nTmp, err = s.Phases[i].DecodeFrom(d) + nTmp, err = s.Phases[i].DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding TransactionPhase: %s", err) + return n, fmt.Errorf("decoding TransactionPhase: %w", err) } } } @@ -12079,8 +13804,10 @@ func (s TransactionSetV1) MarshalBinary() ([]byte, error) { // UnmarshalBinary implements encoding.BinaryUnmarshaler. func (s *TransactionSetV1) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } @@ -12089,8 +13816,7 @@ var ( _ encoding.BinaryUnmarshaler = (*TransactionSetV1)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. +// xdrType signals that this type represents XDR values defined by this package. func (s TransactionSetV1) xdrType() {} var _ xdrType = (*TransactionSetV1)(nil) @@ -12131,7 +13857,7 @@ func NewGeneralizedTransactionSet(v int32, value interface{}) (result Generalize case 1: tv, ok := value.(TransactionSetV1) if !ok { - err = fmt.Errorf("invalid value, must be TransactionSetV1") + err = errors.New("invalid value, must be TransactionSetV1") return } result.V1TxSet = &tv @@ -12183,21 +13909,25 @@ func (u GeneralizedTransactionSet) EncodeTo(e *xdr.Encoder) error { var _ decoderFrom = (*GeneralizedTransactionSet)(nil) // DecodeFrom decodes this value using the Decoder. -func (u *GeneralizedTransactionSet) DecodeFrom(d *xdr.Decoder) (int, error) { +func (u *GeneralizedTransactionSet) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding GeneralizedTransactionSet: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int u.V, nTmp, err = d.DecodeInt() n += nTmp if err != nil { - return n, fmt.Errorf("decoding Int: %s", err) + return n, fmt.Errorf("decoding Int: %w", err) } switch int32(u.V) { case 1: u.V1TxSet = new(TransactionSetV1) - nTmp, err = (*u.V1TxSet).DecodeFrom(d) + nTmp, err = (*u.V1TxSet).DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding TransactionSetV1: %s", err) + return n, fmt.Errorf("decoding TransactionSetV1: %w", err) } return n, nil } @@ -12215,8 +13945,10 @@ func (s GeneralizedTransactionSet) MarshalBinary() ([]byte, error) { // UnmarshalBinary implements encoding.BinaryUnmarshaler. func (s *GeneralizedTransactionSet) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } @@ -12225,8 +13957,7 @@ var ( _ encoding.BinaryUnmarshaler = (*GeneralizedTransactionSet)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. +// xdrType signals that this type represents XDR values defined by this package. func (s GeneralizedTransactionSet) xdrType() {} var _ xdrType = (*GeneralizedTransactionSet)(nil) @@ -12258,18 +13989,22 @@ func (s *TransactionResultPair) EncodeTo(e *xdr.Encoder) error { var _ decoderFrom = (*TransactionResultPair)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *TransactionResultPair) DecodeFrom(d *xdr.Decoder) (int, error) { +func (s *TransactionResultPair) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding TransactionResultPair: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = s.TransactionHash.DecodeFrom(d) + nTmp, err = s.TransactionHash.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Hash: %s", err) + return n, fmt.Errorf("decoding Hash: %w", err) } - nTmp, err = s.Result.DecodeFrom(d) + nTmp, err = s.Result.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding TransactionResult: %s", err) + return n, fmt.Errorf("decoding TransactionResult: %w", err) } return n, nil } @@ -12285,8 +14020,10 @@ func (s TransactionResultPair) MarshalBinary() ([]byte, error) { // UnmarshalBinary implements encoding.BinaryUnmarshaler. func (s *TransactionResultPair) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } @@ -12295,8 +14032,7 @@ var ( _ encoding.BinaryUnmarshaler = (*TransactionResultPair)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. +// xdrType signals that this type represents XDR values defined by this package. func (s TransactionResultPair) xdrType() {} var _ xdrType = (*TransactionResultPair)(nil) @@ -12328,23 +14064,30 @@ func (s *TransactionResultSet) EncodeTo(e *xdr.Encoder) error { var _ decoderFrom = (*TransactionResultSet)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *TransactionResultSet) DecodeFrom(d *xdr.Decoder) (int, error) { +func (s *TransactionResultSet) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding TransactionResultSet: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int var l uint32 l, nTmp, err = d.DecodeUint() n += nTmp if err != nil { - return n, fmt.Errorf("decoding TransactionResultPair: %s", err) + return n, fmt.Errorf("decoding TransactionResultPair: %w", err) } s.Results = nil if l > 0 { + if il, ok := d.InputLen(); ok && uint(il) < uint(l) { + return n, fmt.Errorf("decoding TransactionResultPair: length (%d) exceeds remaining input length (%d)", l, il) + } s.Results = make([]TransactionResultPair, l) for i := uint32(0); i < l; i++ { - nTmp, err = s.Results[i].DecodeFrom(d) + nTmp, err = s.Results[i].DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding TransactionResultPair: %s", err) + return n, fmt.Errorf("decoding TransactionResultPair: %w", err) } } } @@ -12362,8 +14105,10 @@ func (s TransactionResultSet) MarshalBinary() ([]byte, error) { // UnmarshalBinary implements encoding.BinaryUnmarshaler. func (s *TransactionResultSet) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } @@ -12372,8 +14117,7 @@ var ( _ encoding.BinaryUnmarshaler = (*TransactionResultSet)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. +// xdrType signals that this type represents XDR values defined by this package. func (s TransactionResultSet) xdrType() {} var _ xdrType = (*TransactionResultSet)(nil) @@ -12419,7 +14163,7 @@ func NewTransactionHistoryEntryExt(v int32, value interface{}) (result Transacti case 1: tv, ok := value.(GeneralizedTransactionSet) if !ok { - err = fmt.Errorf("invalid value, must be GeneralizedTransactionSet") + err = errors.New("invalid value, must be GeneralizedTransactionSet") return } result.GeneralizedTxSet = &tv @@ -12474,13 +14218,17 @@ func (u TransactionHistoryEntryExt) EncodeTo(e *xdr.Encoder) error { var _ decoderFrom = (*TransactionHistoryEntryExt)(nil) // DecodeFrom decodes this value using the Decoder. -func (u *TransactionHistoryEntryExt) DecodeFrom(d *xdr.Decoder) (int, error) { +func (u *TransactionHistoryEntryExt) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding TransactionHistoryEntryExt: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int u.V, nTmp, err = d.DecodeInt() n += nTmp if err != nil { - return n, fmt.Errorf("decoding Int: %s", err) + return n, fmt.Errorf("decoding Int: %w", err) } switch int32(u.V) { case 0: @@ -12488,10 +14236,10 @@ func (u *TransactionHistoryEntryExt) DecodeFrom(d *xdr.Decoder) (int, error) { return n, nil case 1: u.GeneralizedTxSet = new(GeneralizedTransactionSet) - nTmp, err = (*u.GeneralizedTxSet).DecodeFrom(d) + nTmp, err = (*u.GeneralizedTxSet).DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding GeneralizedTransactionSet: %s", err) + return n, fmt.Errorf("decoding GeneralizedTransactionSet: %w", err) } return n, nil } @@ -12509,8 +14257,10 @@ func (s TransactionHistoryEntryExt) MarshalBinary() ([]byte, error) { // UnmarshalBinary implements encoding.BinaryUnmarshaler. func (s *TransactionHistoryEntryExt) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } @@ -12519,8 +14269,7 @@ var ( _ encoding.BinaryUnmarshaler = (*TransactionHistoryEntryExt)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. +// xdrType signals that this type represents XDR values defined by this package. func (s TransactionHistoryEntryExt) xdrType() {} var _ xdrType = (*TransactionHistoryEntryExt)(nil) @@ -12566,23 +14315,27 @@ func (s *TransactionHistoryEntry) EncodeTo(e *xdr.Encoder) error { var _ decoderFrom = (*TransactionHistoryEntry)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *TransactionHistoryEntry) DecodeFrom(d *xdr.Decoder) (int, error) { +func (s *TransactionHistoryEntry) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding TransactionHistoryEntry: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = s.LedgerSeq.DecodeFrom(d) + nTmp, err = s.LedgerSeq.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Uint32: %s", err) + return n, fmt.Errorf("decoding Uint32: %w", err) } - nTmp, err = s.TxSet.DecodeFrom(d) + nTmp, err = s.TxSet.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding TransactionSet: %s", err) + return n, fmt.Errorf("decoding TransactionSet: %w", err) } - nTmp, err = s.Ext.DecodeFrom(d) + nTmp, err = s.Ext.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding TransactionHistoryEntryExt: %s", err) + return n, fmt.Errorf("decoding TransactionHistoryEntryExt: %w", err) } return n, nil } @@ -12598,8 +14351,10 @@ func (s TransactionHistoryEntry) MarshalBinary() ([]byte, error) { // UnmarshalBinary implements encoding.BinaryUnmarshaler. func (s *TransactionHistoryEntry) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } @@ -12608,8 +14363,7 @@ var ( _ encoding.BinaryUnmarshaler = (*TransactionHistoryEntry)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. +// xdrType signals that this type represents XDR values defined by this package. func (s TransactionHistoryEntry) xdrType() {} var _ xdrType = (*TransactionHistoryEntry)(nil) @@ -12668,13 +14422,17 @@ func (u TransactionHistoryResultEntryExt) EncodeTo(e *xdr.Encoder) error { var _ decoderFrom = (*TransactionHistoryResultEntryExt)(nil) // DecodeFrom decodes this value using the Decoder. -func (u *TransactionHistoryResultEntryExt) DecodeFrom(d *xdr.Decoder) (int, error) { +func (u *TransactionHistoryResultEntryExt) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding TransactionHistoryResultEntryExt: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int u.V, nTmp, err = d.DecodeInt() n += nTmp if err != nil { - return n, fmt.Errorf("decoding Int: %s", err) + return n, fmt.Errorf("decoding Int: %w", err) } switch int32(u.V) { case 0: @@ -12695,8 +14453,10 @@ func (s TransactionHistoryResultEntryExt) MarshalBinary() ([]byte, error) { // UnmarshalBinary implements encoding.BinaryUnmarshaler. func (s *TransactionHistoryResultEntryExt) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } @@ -12705,8 +14465,7 @@ var ( _ encoding.BinaryUnmarshaler = (*TransactionHistoryResultEntryExt)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. +// xdrType signals that this type represents XDR values defined by this package. func (s TransactionHistoryResultEntryExt) xdrType() {} var _ xdrType = (*TransactionHistoryResultEntryExt)(nil) @@ -12750,23 +14509,27 @@ func (s *TransactionHistoryResultEntry) EncodeTo(e *xdr.Encoder) error { var _ decoderFrom = (*TransactionHistoryResultEntry)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *TransactionHistoryResultEntry) DecodeFrom(d *xdr.Decoder) (int, error) { +func (s *TransactionHistoryResultEntry) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding TransactionHistoryResultEntry: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = s.LedgerSeq.DecodeFrom(d) + nTmp, err = s.LedgerSeq.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Uint32: %s", err) + return n, fmt.Errorf("decoding Uint32: %w", err) } - nTmp, err = s.TxResultSet.DecodeFrom(d) + nTmp, err = s.TxResultSet.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding TransactionResultSet: %s", err) + return n, fmt.Errorf("decoding TransactionResultSet: %w", err) } - nTmp, err = s.Ext.DecodeFrom(d) + nTmp, err = s.Ext.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding TransactionHistoryResultEntryExt: %s", err) + return n, fmt.Errorf("decoding TransactionHistoryResultEntryExt: %w", err) } return n, nil } @@ -12782,8 +14545,10 @@ func (s TransactionHistoryResultEntry) MarshalBinary() ([]byte, error) { // UnmarshalBinary implements encoding.BinaryUnmarshaler. func (s *TransactionHistoryResultEntry) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } @@ -12792,8 +14557,7 @@ var ( _ encoding.BinaryUnmarshaler = (*TransactionHistoryResultEntry)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. +// xdrType signals that this type represents XDR values defined by this package. func (s TransactionHistoryResultEntry) xdrType() {} var _ xdrType = (*TransactionHistoryResultEntry)(nil) @@ -12852,13 +14616,17 @@ func (u LedgerHeaderHistoryEntryExt) EncodeTo(e *xdr.Encoder) error { var _ decoderFrom = (*LedgerHeaderHistoryEntryExt)(nil) // DecodeFrom decodes this value using the Decoder. -func (u *LedgerHeaderHistoryEntryExt) DecodeFrom(d *xdr.Decoder) (int, error) { +func (u *LedgerHeaderHistoryEntryExt) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding LedgerHeaderHistoryEntryExt: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int u.V, nTmp, err = d.DecodeInt() n += nTmp if err != nil { - return n, fmt.Errorf("decoding Int: %s", err) + return n, fmt.Errorf("decoding Int: %w", err) } switch int32(u.V) { case 0: @@ -12879,8 +14647,10 @@ func (s LedgerHeaderHistoryEntryExt) MarshalBinary() ([]byte, error) { // UnmarshalBinary implements encoding.BinaryUnmarshaler. func (s *LedgerHeaderHistoryEntryExt) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } @@ -12889,8 +14659,7 @@ var ( _ encoding.BinaryUnmarshaler = (*LedgerHeaderHistoryEntryExt)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. +// xdrType signals that this type represents XDR values defined by this package. func (s LedgerHeaderHistoryEntryExt) xdrType() {} var _ xdrType = (*LedgerHeaderHistoryEntryExt)(nil) @@ -12934,23 +14703,27 @@ func (s *LedgerHeaderHistoryEntry) EncodeTo(e *xdr.Encoder) error { var _ decoderFrom = (*LedgerHeaderHistoryEntry)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *LedgerHeaderHistoryEntry) DecodeFrom(d *xdr.Decoder) (int, error) { +func (s *LedgerHeaderHistoryEntry) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding LedgerHeaderHistoryEntry: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = s.Hash.DecodeFrom(d) + nTmp, err = s.Hash.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Hash: %s", err) + return n, fmt.Errorf("decoding Hash: %w", err) } - nTmp, err = s.Header.DecodeFrom(d) + nTmp, err = s.Header.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding LedgerHeader: %s", err) + return n, fmt.Errorf("decoding LedgerHeader: %w", err) } - nTmp, err = s.Ext.DecodeFrom(d) + nTmp, err = s.Ext.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding LedgerHeaderHistoryEntryExt: %s", err) + return n, fmt.Errorf("decoding LedgerHeaderHistoryEntryExt: %w", err) } return n, nil } @@ -12966,8 +14739,10 @@ func (s LedgerHeaderHistoryEntry) MarshalBinary() ([]byte, error) { // UnmarshalBinary implements encoding.BinaryUnmarshaler. func (s *LedgerHeaderHistoryEntry) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } @@ -12976,8 +14751,7 @@ var ( _ encoding.BinaryUnmarshaler = (*LedgerHeaderHistoryEntry)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. +// xdrType signals that this type represents XDR values defined by this package. func (s LedgerHeaderHistoryEntry) xdrType() {} var _ xdrType = (*LedgerHeaderHistoryEntry)(nil) @@ -13014,28 +14788,35 @@ func (s *LedgerScpMessages) EncodeTo(e *xdr.Encoder) error { var _ decoderFrom = (*LedgerScpMessages)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *LedgerScpMessages) DecodeFrom(d *xdr.Decoder) (int, error) { +func (s *LedgerScpMessages) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding LedgerScpMessages: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = s.LedgerSeq.DecodeFrom(d) + nTmp, err = s.LedgerSeq.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Uint32: %s", err) + return n, fmt.Errorf("decoding Uint32: %w", err) } var l uint32 l, nTmp, err = d.DecodeUint() n += nTmp if err != nil { - return n, fmt.Errorf("decoding ScpEnvelope: %s", err) + return n, fmt.Errorf("decoding ScpEnvelope: %w", err) } s.Messages = nil if l > 0 { + if il, ok := d.InputLen(); ok && uint(il) < uint(l) { + return n, fmt.Errorf("decoding ScpEnvelope: length (%d) exceeds remaining input length (%d)", l, il) + } s.Messages = make([]ScpEnvelope, l) for i := uint32(0); i < l; i++ { - nTmp, err = s.Messages[i].DecodeFrom(d) + nTmp, err = s.Messages[i].DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding ScpEnvelope: %s", err) + return n, fmt.Errorf("decoding ScpEnvelope: %w", err) } } } @@ -13053,8 +14834,10 @@ func (s LedgerScpMessages) MarshalBinary() ([]byte, error) { // UnmarshalBinary implements encoding.BinaryUnmarshaler. func (s *LedgerScpMessages) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } @@ -13063,8 +14846,7 @@ var ( _ encoding.BinaryUnmarshaler = (*LedgerScpMessages)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. +// xdrType signals that this type represents XDR values defined by this package. func (s LedgerScpMessages) xdrType() {} var _ xdrType = (*LedgerScpMessages)(nil) @@ -13101,30 +14883,37 @@ func (s *ScpHistoryEntryV0) EncodeTo(e *xdr.Encoder) error { var _ decoderFrom = (*ScpHistoryEntryV0)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *ScpHistoryEntryV0) DecodeFrom(d *xdr.Decoder) (int, error) { +func (s *ScpHistoryEntryV0) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding ScpHistoryEntryV0: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int var l uint32 l, nTmp, err = d.DecodeUint() n += nTmp if err != nil { - return n, fmt.Errorf("decoding ScpQuorumSet: %s", err) + return n, fmt.Errorf("decoding ScpQuorumSet: %w", err) } s.QuorumSets = nil if l > 0 { + if il, ok := d.InputLen(); ok && uint(il) < uint(l) { + return n, fmt.Errorf("decoding ScpQuorumSet: length (%d) exceeds remaining input length (%d)", l, il) + } s.QuorumSets = make([]ScpQuorumSet, l) for i := uint32(0); i < l; i++ { - nTmp, err = s.QuorumSets[i].DecodeFrom(d) + nTmp, err = s.QuorumSets[i].DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding ScpQuorumSet: %s", err) + return n, fmt.Errorf("decoding ScpQuorumSet: %w", err) } } } - nTmp, err = s.LedgerMessages.DecodeFrom(d) + nTmp, err = s.LedgerMessages.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding LedgerScpMessages: %s", err) + return n, fmt.Errorf("decoding LedgerScpMessages: %w", err) } return n, nil } @@ -13140,8 +14929,10 @@ func (s ScpHistoryEntryV0) MarshalBinary() ([]byte, error) { // UnmarshalBinary implements encoding.BinaryUnmarshaler. func (s *ScpHistoryEntryV0) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } @@ -13150,8 +14941,7 @@ var ( _ encoding.BinaryUnmarshaler = (*ScpHistoryEntryV0)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. +// xdrType signals that this type represents XDR values defined by this package. func (s ScpHistoryEntryV0) xdrType() {} var _ xdrType = (*ScpHistoryEntryV0)(nil) @@ -13191,7 +14981,7 @@ func NewScpHistoryEntry(v int32, value interface{}) (result ScpHistoryEntry, err case 0: tv, ok := value.(ScpHistoryEntryV0) if !ok { - err = fmt.Errorf("invalid value, must be ScpHistoryEntryV0") + err = errors.New("invalid value, must be ScpHistoryEntryV0") return } result.V0 = &tv @@ -13243,21 +15033,25 @@ func (u ScpHistoryEntry) EncodeTo(e *xdr.Encoder) error { var _ decoderFrom = (*ScpHistoryEntry)(nil) // DecodeFrom decodes this value using the Decoder. -func (u *ScpHistoryEntry) DecodeFrom(d *xdr.Decoder) (int, error) { +func (u *ScpHistoryEntry) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding ScpHistoryEntry: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int u.V, nTmp, err = d.DecodeInt() n += nTmp if err != nil { - return n, fmt.Errorf("decoding Int: %s", err) + return n, fmt.Errorf("decoding Int: %w", err) } switch int32(u.V) { case 0: u.V0 = new(ScpHistoryEntryV0) - nTmp, err = (*u.V0).DecodeFrom(d) + nTmp, err = (*u.V0).DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding ScpHistoryEntryV0: %s", err) + return n, fmt.Errorf("decoding ScpHistoryEntryV0: %w", err) } return n, nil } @@ -13275,8 +15069,10 @@ func (s ScpHistoryEntry) MarshalBinary() ([]byte, error) { // UnmarshalBinary implements encoding.BinaryUnmarshaler. func (s *ScpHistoryEntry) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } @@ -13285,8 +15081,7 @@ var ( _ encoding.BinaryUnmarshaler = (*ScpHistoryEntry)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. +// xdrType signals that this type represents XDR values defined by this package. func (s ScpHistoryEntry) xdrType() {} var _ xdrType = (*ScpHistoryEntry)(nil) @@ -13341,10 +15136,14 @@ func (e LedgerEntryChangeType) EncodeTo(enc *xdr.Encoder) error { var _ decoderFrom = (*LedgerEntryChangeType)(nil) // DecodeFrom decodes this value using the Decoder. -func (e *LedgerEntryChangeType) DecodeFrom(d *xdr.Decoder) (int, error) { +func (e *LedgerEntryChangeType) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding LedgerEntryChangeType: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 v, n, err := d.DecodeInt() if err != nil { - return n, fmt.Errorf("decoding LedgerEntryChangeType: %s", err) + return n, fmt.Errorf("decoding LedgerEntryChangeType: %w", err) } if _, ok := ledgerEntryChangeTypeMap[v]; !ok { return n, fmt.Errorf("'%d' is not a valid LedgerEntryChangeType enum value", v) @@ -13364,8 +15163,10 @@ func (s LedgerEntryChangeType) MarshalBinary() ([]byte, error) { // UnmarshalBinary implements encoding.BinaryUnmarshaler. func (s *LedgerEntryChangeType) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } @@ -13374,8 +15175,7 @@ var ( _ encoding.BinaryUnmarshaler = (*LedgerEntryChangeType)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. +// xdrType signals that this type represents XDR values defined by this package. func (s LedgerEntryChangeType) xdrType() {} var _ xdrType = (*LedgerEntryChangeType)(nil) @@ -13430,28 +15230,28 @@ func NewLedgerEntryChange(aType LedgerEntryChangeType, value interface{}) (resul case LedgerEntryChangeTypeLedgerEntryCreated: tv, ok := value.(LedgerEntry) if !ok { - err = fmt.Errorf("invalid value, must be LedgerEntry") + err = errors.New("invalid value, must be LedgerEntry") return } result.Created = &tv case LedgerEntryChangeTypeLedgerEntryUpdated: tv, ok := value.(LedgerEntry) if !ok { - err = fmt.Errorf("invalid value, must be LedgerEntry") + err = errors.New("invalid value, must be LedgerEntry") return } result.Updated = &tv case LedgerEntryChangeTypeLedgerEntryRemoved: tv, ok := value.(LedgerKey) if !ok { - err = fmt.Errorf("invalid value, must be LedgerKey") + err = errors.New("invalid value, must be LedgerKey") return } result.Removed = &tv case LedgerEntryChangeTypeLedgerEntryState: tv, ok := value.(LedgerEntry) if !ok { - err = fmt.Errorf("invalid value, must be LedgerEntry") + err = errors.New("invalid value, must be LedgerEntry") return } result.State = &tv @@ -13593,45 +15393,49 @@ func (u LedgerEntryChange) EncodeTo(e *xdr.Encoder) error { var _ decoderFrom = (*LedgerEntryChange)(nil) // DecodeFrom decodes this value using the Decoder. -func (u *LedgerEntryChange) DecodeFrom(d *xdr.Decoder) (int, error) { +func (u *LedgerEntryChange) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding LedgerEntryChange: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = u.Type.DecodeFrom(d) + nTmp, err = u.Type.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding LedgerEntryChangeType: %s", err) + return n, fmt.Errorf("decoding LedgerEntryChangeType: %w", err) } switch LedgerEntryChangeType(u.Type) { case LedgerEntryChangeTypeLedgerEntryCreated: u.Created = new(LedgerEntry) - nTmp, err = (*u.Created).DecodeFrom(d) + nTmp, err = (*u.Created).DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding LedgerEntry: %s", err) + return n, fmt.Errorf("decoding LedgerEntry: %w", err) } return n, nil case LedgerEntryChangeTypeLedgerEntryUpdated: u.Updated = new(LedgerEntry) - nTmp, err = (*u.Updated).DecodeFrom(d) + nTmp, err = (*u.Updated).DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding LedgerEntry: %s", err) + return n, fmt.Errorf("decoding LedgerEntry: %w", err) } return n, nil case LedgerEntryChangeTypeLedgerEntryRemoved: u.Removed = new(LedgerKey) - nTmp, err = (*u.Removed).DecodeFrom(d) + nTmp, err = (*u.Removed).DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding LedgerKey: %s", err) + return n, fmt.Errorf("decoding LedgerKey: %w", err) } return n, nil case LedgerEntryChangeTypeLedgerEntryState: u.State = new(LedgerEntry) - nTmp, err = (*u.State).DecodeFrom(d) + nTmp, err = (*u.State).DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding LedgerEntry: %s", err) + return n, fmt.Errorf("decoding LedgerEntry: %w", err) } return n, nil } @@ -13649,8 +15453,10 @@ func (s LedgerEntryChange) MarshalBinary() ([]byte, error) { // UnmarshalBinary implements encoding.BinaryUnmarshaler. func (s *LedgerEntryChange) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } @@ -13659,8 +15465,7 @@ var ( _ encoding.BinaryUnmarshaler = (*LedgerEntryChange)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. +// xdrType signals that this type represents XDR values defined by this package. func (s LedgerEntryChange) xdrType() {} var _ xdrType = (*LedgerEntryChange)(nil) @@ -13687,23 +15492,30 @@ func (s LedgerEntryChanges) EncodeTo(e *xdr.Encoder) error { var _ decoderFrom = (*LedgerEntryChanges)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *LedgerEntryChanges) DecodeFrom(d *xdr.Decoder) (int, error) { +func (s *LedgerEntryChanges) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding LedgerEntryChanges: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int var l uint32 l, nTmp, err = d.DecodeUint() n += nTmp if err != nil { - return n, fmt.Errorf("decoding LedgerEntryChange: %s", err) + return n, fmt.Errorf("decoding LedgerEntryChange: %w", err) } (*s) = nil if l > 0 { + if il, ok := d.InputLen(); ok && uint(il) < uint(l) { + return n, fmt.Errorf("decoding LedgerEntryChange: length (%d) exceeds remaining input length (%d)", l, il) + } (*s) = make([]LedgerEntryChange, l) for i := uint32(0); i < l; i++ { - nTmp, err = (*s)[i].DecodeFrom(d) + nTmp, err = (*s)[i].DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding LedgerEntryChange: %s", err) + return n, fmt.Errorf("decoding LedgerEntryChange: %w", err) } } } @@ -13721,8 +15533,10 @@ func (s LedgerEntryChanges) MarshalBinary() ([]byte, error) { // UnmarshalBinary implements encoding.BinaryUnmarshaler. func (s *LedgerEntryChanges) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } @@ -13731,8 +15545,7 @@ var ( _ encoding.BinaryUnmarshaler = (*LedgerEntryChanges)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. +// xdrType signals that this type represents XDR values defined by this package. func (s LedgerEntryChanges) xdrType() {} var _ xdrType = (*LedgerEntryChanges)(nil) @@ -13759,13 +15572,17 @@ func (s *OperationMeta) EncodeTo(e *xdr.Encoder) error { var _ decoderFrom = (*OperationMeta)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *OperationMeta) DecodeFrom(d *xdr.Decoder) (int, error) { +func (s *OperationMeta) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding OperationMeta: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = s.Changes.DecodeFrom(d) + nTmp, err = s.Changes.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding LedgerEntryChanges: %s", err) + return n, fmt.Errorf("decoding LedgerEntryChanges: %w", err) } return n, nil } @@ -13781,8 +15598,10 @@ func (s OperationMeta) MarshalBinary() ([]byte, error) { // UnmarshalBinary implements encoding.BinaryUnmarshaler. func (s *OperationMeta) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } @@ -13791,8 +15610,7 @@ var ( _ encoding.BinaryUnmarshaler = (*OperationMeta)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. +// xdrType signals that this type represents XDR values defined by this package. func (s OperationMeta) xdrType() {} var _ xdrType = (*OperationMeta)(nil) @@ -13829,28 +15647,35 @@ func (s *TransactionMetaV1) EncodeTo(e *xdr.Encoder) error { var _ decoderFrom = (*TransactionMetaV1)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *TransactionMetaV1) DecodeFrom(d *xdr.Decoder) (int, error) { +func (s *TransactionMetaV1) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding TransactionMetaV1: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = s.TxChanges.DecodeFrom(d) + nTmp, err = s.TxChanges.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding LedgerEntryChanges: %s", err) + return n, fmt.Errorf("decoding LedgerEntryChanges: %w", err) } var l uint32 l, nTmp, err = d.DecodeUint() n += nTmp if err != nil { - return n, fmt.Errorf("decoding OperationMeta: %s", err) + return n, fmt.Errorf("decoding OperationMeta: %w", err) } s.Operations = nil if l > 0 { + if il, ok := d.InputLen(); ok && uint(il) < uint(l) { + return n, fmt.Errorf("decoding OperationMeta: length (%d) exceeds remaining input length (%d)", l, il) + } s.Operations = make([]OperationMeta, l) for i := uint32(0); i < l; i++ { - nTmp, err = s.Operations[i].DecodeFrom(d) + nTmp, err = s.Operations[i].DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding OperationMeta: %s", err) + return n, fmt.Errorf("decoding OperationMeta: %w", err) } } } @@ -13868,8 +15693,10 @@ func (s TransactionMetaV1) MarshalBinary() ([]byte, error) { // UnmarshalBinary implements encoding.BinaryUnmarshaler. func (s *TransactionMetaV1) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } @@ -13878,8 +15705,7 @@ var ( _ encoding.BinaryUnmarshaler = (*TransactionMetaV1)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. +// xdrType signals that this type represents XDR values defined by this package. func (s TransactionMetaV1) xdrType() {} var _ xdrType = (*TransactionMetaV1)(nil) @@ -13923,35 +15749,42 @@ func (s *TransactionMetaV2) EncodeTo(e *xdr.Encoder) error { var _ decoderFrom = (*TransactionMetaV2)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *TransactionMetaV2) DecodeFrom(d *xdr.Decoder) (int, error) { +func (s *TransactionMetaV2) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding TransactionMetaV2: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = s.TxChangesBefore.DecodeFrom(d) + nTmp, err = s.TxChangesBefore.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding LedgerEntryChanges: %s", err) + return n, fmt.Errorf("decoding LedgerEntryChanges: %w", err) } var l uint32 l, nTmp, err = d.DecodeUint() n += nTmp if err != nil { - return n, fmt.Errorf("decoding OperationMeta: %s", err) + return n, fmt.Errorf("decoding OperationMeta: %w", err) } s.Operations = nil if l > 0 { + if il, ok := d.InputLen(); ok && uint(il) < uint(l) { + return n, fmt.Errorf("decoding OperationMeta: length (%d) exceeds remaining input length (%d)", l, il) + } s.Operations = make([]OperationMeta, l) for i := uint32(0); i < l; i++ { - nTmp, err = s.Operations[i].DecodeFrom(d) + nTmp, err = s.Operations[i].DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding OperationMeta: %s", err) + return n, fmt.Errorf("decoding OperationMeta: %w", err) } } } - nTmp, err = s.TxChangesAfter.DecodeFrom(d) + nTmp, err = s.TxChangesAfter.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding LedgerEntryChanges: %s", err) + return n, fmt.Errorf("decoding LedgerEntryChanges: %w", err) } return n, nil } @@ -13967,8 +15800,10 @@ func (s TransactionMetaV2) MarshalBinary() ([]byte, error) { // UnmarshalBinary implements encoding.BinaryUnmarshaler. func (s *TransactionMetaV2) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } @@ -13977,148 +15812,263 @@ var ( _ encoding.BinaryUnmarshaler = (*TransactionMetaV2)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. +// xdrType signals that this type represents XDR values defined by this package. func (s TransactionMetaV2) xdrType() {} var _ xdrType = (*TransactionMetaV2)(nil) -// TransactionMeta is an XDR Union defines as: +// ContractEventType is an XDR Enum defines as: // -// union TransactionMeta switch (int v) +// enum ContractEventType // { -// case 0: -// OperationMeta operations<>; -// case 1: -// TransactionMetaV1 v1; -// case 2: -// TransactionMetaV2 v2; +// SYSTEM = 0, +// CONTRACT = 1, +// DIAGNOSTIC = 2 // }; -type TransactionMeta struct { - V int32 - Operations *[]OperationMeta - V1 *TransactionMetaV1 - V2 *TransactionMetaV2 +type ContractEventType int32 + +const ( + ContractEventTypeSystem ContractEventType = 0 + ContractEventTypeContract ContractEventType = 1 + ContractEventTypeDiagnostic ContractEventType = 2 +) + +var contractEventTypeMap = map[int32]string{ + 0: "ContractEventTypeSystem", + 1: "ContractEventTypeContract", + 2: "ContractEventTypeDiagnostic", } -// SwitchFieldName returns the field name in which this union's -// discriminant is stored -func (u TransactionMeta) SwitchFieldName() string { - return "V" +// ValidEnum validates a proposed value for this enum. Implements +// the Enum interface for ContractEventType +func (e ContractEventType) ValidEnum(v int32) bool { + _, ok := contractEventTypeMap[v] + return ok } -// ArmForSwitch returns which field name should be used for storing -// the value for an instance of TransactionMeta -func (u TransactionMeta) ArmForSwitch(sw int32) (string, bool) { - switch int32(sw) { - case 0: - return "Operations", true - case 1: - return "V1", true - case 2: - return "V2", true - } - return "-", false +// String returns the name of `e` +func (e ContractEventType) String() string { + name, _ := contractEventTypeMap[int32(e)] + return name } -// NewTransactionMeta creates a new TransactionMeta. -func NewTransactionMeta(v int32, value interface{}) (result TransactionMeta, err error) { - result.V = v - switch int32(v) { - case 0: - tv, ok := value.([]OperationMeta) - if !ok { - err = fmt.Errorf("invalid value, must be []OperationMeta") - return - } - result.Operations = &tv - case 1: - tv, ok := value.(TransactionMetaV1) - if !ok { - err = fmt.Errorf("invalid value, must be TransactionMetaV1") - return - } - result.V1 = &tv - case 2: - tv, ok := value.(TransactionMetaV2) - if !ok { - err = fmt.Errorf("invalid value, must be TransactionMetaV2") - return - } - result.V2 = &tv +// EncodeTo encodes this value using the Encoder. +func (e ContractEventType) EncodeTo(enc *xdr.Encoder) error { + if _, ok := contractEventTypeMap[int32(e)]; !ok { + return fmt.Errorf("'%d' is not a valid ContractEventType enum value", e) } - return + _, err := enc.EncodeInt(int32(e)) + return err } -// MustOperations retrieves the Operations value from the union, -// panicing if the value is not set. -func (u TransactionMeta) MustOperations() []OperationMeta { - val, ok := u.GetOperations() +var _ decoderFrom = (*ContractEventType)(nil) - if !ok { - panic("arm Operations is not set") +// DecodeFrom decodes this value using the Decoder. +func (e *ContractEventType) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding ContractEventType: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + v, n, err := d.DecodeInt() + if err != nil { + return n, fmt.Errorf("decoding ContractEventType: %w", err) + } + if _, ok := contractEventTypeMap[v]; !ok { + return n, fmt.Errorf("'%d' is not a valid ContractEventType enum value", v) } + *e = ContractEventType(v) + return n, nil +} - return val +// MarshalBinary implements encoding.BinaryMarshaler. +func (s ContractEventType) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err } -// GetOperations retrieves the Operations value from the union, -// returning ok if the union's switch indicated the value is valid. -func (u TransactionMeta) GetOperations() (result []OperationMeta, ok bool) { - armName, _ := u.ArmForSwitch(int32(u.V)) +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *ContractEventType) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} - if armName == "Operations" { - result = *u.Operations - ok = true - } +var ( + _ encoding.BinaryMarshaler = (*ContractEventType)(nil) + _ encoding.BinaryUnmarshaler = (*ContractEventType)(nil) +) - return +// xdrType signals that this type represents XDR values defined by this package. +func (s ContractEventType) xdrType() {} + +var _ xdrType = (*ContractEventType)(nil) + +// ContractEventV0 is an XDR NestedStruct defines as: +// +// struct +// { +// SCVal topics<>; +// SCVal data; +// } +type ContractEventV0 struct { + Topics []ScVal + Data ScVal } -// MustV1 retrieves the V1 value from the union, -// panicing if the value is not set. -func (u TransactionMeta) MustV1() TransactionMetaV1 { - val, ok := u.GetV1() +// EncodeTo encodes this value using the Encoder. +func (s *ContractEventV0) EncodeTo(e *xdr.Encoder) error { + var err error + if _, err = e.EncodeUint(uint32(len(s.Topics))); err != nil { + return err + } + for i := 0; i < len(s.Topics); i++ { + if err = s.Topics[i].EncodeTo(e); err != nil { + return err + } + } + if err = s.Data.EncodeTo(e); err != nil { + return err + } + return nil +} - if !ok { - panic("arm V1 is not set") +var _ decoderFrom = (*ContractEventV0)(nil) + +// DecodeFrom decodes this value using the Decoder. +func (s *ContractEventV0) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding ContractEventV0: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + var err error + var n, nTmp int + var l uint32 + l, nTmp, err = d.DecodeUint() + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ScVal: %w", err) + } + s.Topics = nil + if l > 0 { + if il, ok := d.InputLen(); ok && uint(il) < uint(l) { + return n, fmt.Errorf("decoding ScVal: length (%d) exceeds remaining input length (%d)", l, il) + } + s.Topics = make([]ScVal, l) + for i := uint32(0); i < l; i++ { + nTmp, err = s.Topics[i].DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ScVal: %w", err) + } + } } + nTmp, err = s.Data.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ScVal: %w", err) + } + return n, nil +} - return val +// MarshalBinary implements encoding.BinaryMarshaler. +func (s ContractEventV0) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err } -// GetV1 retrieves the V1 value from the union, -// returning ok if the union's switch indicated the value is valid. -func (u TransactionMeta) GetV1() (result TransactionMetaV1, ok bool) { - armName, _ := u.ArmForSwitch(int32(u.V)) +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *ContractEventV0) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} - if armName == "V1" { - result = *u.V1 - ok = true +var ( + _ encoding.BinaryMarshaler = (*ContractEventV0)(nil) + _ encoding.BinaryUnmarshaler = (*ContractEventV0)(nil) +) + +// xdrType signals that this type represents XDR values defined by this package. +func (s ContractEventV0) xdrType() {} + +var _ xdrType = (*ContractEventV0)(nil) + +// ContractEventBody is an XDR NestedUnion defines as: +// +// union switch (int v) +// { +// case 0: +// struct +// { +// SCVal topics<>; +// SCVal data; +// } v0; +// } +type ContractEventBody struct { + V int32 + V0 *ContractEventV0 +} + +// SwitchFieldName returns the field name in which this union's +// discriminant is stored +func (u ContractEventBody) SwitchFieldName() string { + return "V" +} + +// ArmForSwitch returns which field name should be used for storing +// the value for an instance of ContractEventBody +func (u ContractEventBody) ArmForSwitch(sw int32) (string, bool) { + switch int32(sw) { + case 0: + return "V0", true } + return "-", false +} +// NewContractEventBody creates a new ContractEventBody. +func NewContractEventBody(v int32, value interface{}) (result ContractEventBody, err error) { + result.V = v + switch int32(v) { + case 0: + tv, ok := value.(ContractEventV0) + if !ok { + err = errors.New("invalid value, must be ContractEventV0") + return + } + result.V0 = &tv + } return } -// MustV2 retrieves the V2 value from the union, +// MustV0 retrieves the V0 value from the union, // panicing if the value is not set. -func (u TransactionMeta) MustV2() TransactionMetaV2 { - val, ok := u.GetV2() +func (u ContractEventBody) MustV0() ContractEventV0 { + val, ok := u.GetV0() if !ok { - panic("arm V2 is not set") + panic("arm V0 is not set") } return val } -// GetV2 retrieves the V2 value from the union, +// GetV0 retrieves the V0 value from the union, // returning ok if the union's switch indicated the value is valid. -func (u TransactionMeta) GetV2() (result TransactionMetaV2, ok bool) { +func (u ContractEventBody) GetV0() (result ContractEventV0, ok bool) { armName, _ := u.ArmForSwitch(int32(u.V)) - if armName == "V2" { - result = *u.V2 + if armName == "V0" { + result = *u.V0 ok = true } @@ -14126,90 +16076,51 @@ func (u TransactionMeta) GetV2() (result TransactionMetaV2, ok bool) { } // EncodeTo encodes this value using the Encoder. -func (u TransactionMeta) EncodeTo(e *xdr.Encoder) error { +func (u ContractEventBody) EncodeTo(e *xdr.Encoder) error { var err error if _, err = e.EncodeInt(int32(u.V)); err != nil { return err } switch int32(u.V) { case 0: - if _, err = e.EncodeUint(uint32(len((*u.Operations)))); err != nil { - return err - } - for i := 0; i < len((*u.Operations)); i++ { - if err = (*u.Operations)[i].EncodeTo(e); err != nil { - return err - } - } - return nil - case 1: - if err = (*u.V1).EncodeTo(e); err != nil { - return err - } - return nil - case 2: - if err = (*u.V2).EncodeTo(e); err != nil { + if err = (*u.V0).EncodeTo(e); err != nil { return err } return nil } - return fmt.Errorf("V (int32) switch value '%d' is not valid for union TransactionMeta", u.V) + return fmt.Errorf("V (int32) switch value '%d' is not valid for union ContractEventBody", u.V) } -var _ decoderFrom = (*TransactionMeta)(nil) +var _ decoderFrom = (*ContractEventBody)(nil) // DecodeFrom decodes this value using the Decoder. -func (u *TransactionMeta) DecodeFrom(d *xdr.Decoder) (int, error) { +func (u *ContractEventBody) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding ContractEventBody: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int u.V, nTmp, err = d.DecodeInt() n += nTmp if err != nil { - return n, fmt.Errorf("decoding Int: %s", err) + return n, fmt.Errorf("decoding Int: %w", err) } switch int32(u.V) { case 0: - u.Operations = new([]OperationMeta) - var l uint32 - l, nTmp, err = d.DecodeUint() - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding OperationMeta: %s", err) - } - (*u.Operations) = nil - if l > 0 { - (*u.Operations) = make([]OperationMeta, l) - for i := uint32(0); i < l; i++ { - nTmp, err = (*u.Operations)[i].DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding OperationMeta: %s", err) - } - } - } - return n, nil - case 1: - u.V1 = new(TransactionMetaV1) - nTmp, err = (*u.V1).DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding TransactionMetaV1: %s", err) - } - return n, nil - case 2: - u.V2 = new(TransactionMetaV2) - nTmp, err = (*u.V2).DecodeFrom(d) + u.V0 = new(ContractEventV0) + nTmp, err = (*u.V0).DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding TransactionMetaV2: %s", err) + return n, fmt.Errorf("decoding ContractEventV0: %w", err) } return n, nil } - return n, fmt.Errorf("union TransactionMeta has invalid V (int32) switch value '%d'", u.V) + return n, fmt.Errorf("union ContractEventBody has invalid V (int32) switch value '%d'", u.V) } // MarshalBinary implements encoding.BinaryMarshaler. -func (s TransactionMeta) MarshalBinary() ([]byte, error) { +func (s ContractEventBody) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -14217,79 +16128,122 @@ func (s TransactionMeta) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *TransactionMeta) UnmarshalBinary(inp []byte) error { +func (s *ContractEventBody) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*TransactionMeta)(nil) - _ encoding.BinaryUnmarshaler = (*TransactionMeta)(nil) + _ encoding.BinaryMarshaler = (*ContractEventBody)(nil) + _ encoding.BinaryUnmarshaler = (*ContractEventBody)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s TransactionMeta) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s ContractEventBody) xdrType() {} -var _ xdrType = (*TransactionMeta)(nil) +var _ xdrType = (*ContractEventBody)(nil) -// TransactionResultMeta is an XDR Struct defines as: +// ContractEvent is an XDR Struct defines as: // -// struct TransactionResultMeta +// struct ContractEvent // { -// TransactionResultPair result; -// LedgerEntryChanges feeProcessing; -// TransactionMeta txApplyProcessing; +// // We can use this to add more fields, or because it +// // is first, to change ContractEvent into a union. +// ExtensionPoint ext; +// +// Hash* contractID; +// ContractEventType type; +// +// union switch (int v) +// { +// case 0: +// struct +// { +// SCVal topics<>; +// SCVal data; +// } v0; +// } +// body; // }; -type TransactionResultMeta struct { - Result TransactionResultPair - FeeProcessing LedgerEntryChanges - TxApplyProcessing TransactionMeta +type ContractEvent struct { + Ext ExtensionPoint + ContractId *Hash + Type ContractEventType + Body ContractEventBody } // EncodeTo encodes this value using the Encoder. -func (s *TransactionResultMeta) EncodeTo(e *xdr.Encoder) error { +func (s *ContractEvent) EncodeTo(e *xdr.Encoder) error { var err error - if err = s.Result.EncodeTo(e); err != nil { + if err = s.Ext.EncodeTo(e); err != nil { return err } - if err = s.FeeProcessing.EncodeTo(e); err != nil { + if _, err = e.EncodeBool(s.ContractId != nil); err != nil { return err } - if err = s.TxApplyProcessing.EncodeTo(e); err != nil { + if s.ContractId != nil { + if err = (*s.ContractId).EncodeTo(e); err != nil { + return err + } + } + if err = s.Type.EncodeTo(e); err != nil { + return err + } + if err = s.Body.EncodeTo(e); err != nil { return err } return nil } -var _ decoderFrom = (*TransactionResultMeta)(nil) +var _ decoderFrom = (*ContractEvent)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *TransactionResultMeta) DecodeFrom(d *xdr.Decoder) (int, error) { +func (s *ContractEvent) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding ContractEvent: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = s.Result.DecodeFrom(d) + nTmp, err = s.Ext.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ExtensionPoint: %w", err) + } + var b bool + b, nTmp, err = d.DecodeBool() n += nTmp if err != nil { - return n, fmt.Errorf("decoding TransactionResultPair: %s", err) + return n, fmt.Errorf("decoding Hash: %w", err) } - nTmp, err = s.FeeProcessing.DecodeFrom(d) + s.ContractId = nil + if b { + s.ContractId = new(Hash) + nTmp, err = s.ContractId.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Hash: %w", err) + } + } + nTmp, err = s.Type.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding LedgerEntryChanges: %s", err) + return n, fmt.Errorf("decoding ContractEventType: %w", err) } - nTmp, err = s.TxApplyProcessing.DecodeFrom(d) + nTmp, err = s.Body.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding TransactionMeta: %s", err) + return n, fmt.Errorf("decoding ContractEventBody: %w", err) } return n, nil } // MarshalBinary implements encoding.BinaryMarshaler. -func (s TransactionResultMeta) MarshalBinary() ([]byte, error) { +func (s ContractEvent) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -14297,69 +16251,74 @@ func (s TransactionResultMeta) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *TransactionResultMeta) UnmarshalBinary(inp []byte) error { +func (s *ContractEvent) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*TransactionResultMeta)(nil) - _ encoding.BinaryUnmarshaler = (*TransactionResultMeta)(nil) + _ encoding.BinaryMarshaler = (*ContractEvent)(nil) + _ encoding.BinaryUnmarshaler = (*ContractEvent)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s TransactionResultMeta) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s ContractEvent) xdrType() {} -var _ xdrType = (*TransactionResultMeta)(nil) +var _ xdrType = (*ContractEvent)(nil) -// UpgradeEntryMeta is an XDR Struct defines as: +// DiagnosticEvent is an XDR Struct defines as: // -// struct UpgradeEntryMeta +// struct DiagnosticEvent // { -// LedgerUpgrade upgrade; -// LedgerEntryChanges changes; +// bool inSuccessfulContractCall; +// ContractEvent event; // }; -type UpgradeEntryMeta struct { - Upgrade LedgerUpgrade - Changes LedgerEntryChanges +type DiagnosticEvent struct { + InSuccessfulContractCall bool + Event ContractEvent } // EncodeTo encodes this value using the Encoder. -func (s *UpgradeEntryMeta) EncodeTo(e *xdr.Encoder) error { +func (s *DiagnosticEvent) EncodeTo(e *xdr.Encoder) error { var err error - if err = s.Upgrade.EncodeTo(e); err != nil { + if _, err = e.EncodeBool(bool(s.InSuccessfulContractCall)); err != nil { return err } - if err = s.Changes.EncodeTo(e); err != nil { + if err = s.Event.EncodeTo(e); err != nil { return err } return nil } -var _ decoderFrom = (*UpgradeEntryMeta)(nil) +var _ decoderFrom = (*DiagnosticEvent)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *UpgradeEntryMeta) DecodeFrom(d *xdr.Decoder) (int, error) { +func (s *DiagnosticEvent) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding DiagnosticEvent: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = s.Upgrade.DecodeFrom(d) + s.InSuccessfulContractCall, nTmp, err = d.DecodeBool() n += nTmp if err != nil { - return n, fmt.Errorf("decoding LedgerUpgrade: %s", err) + return n, fmt.Errorf("decoding Bool: %w", err) } - nTmp, err = s.Changes.DecodeFrom(d) + nTmp, err = s.Event.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding LedgerEntryChanges: %s", err) + return n, fmt.Errorf("decoding ContractEvent: %w", err) } return n, nil } // MarshalBinary implements encoding.BinaryMarshaler. -func (s UpgradeEntryMeta) MarshalBinary() ([]byte, error) { +func (s DiagnosticEvent) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -14367,149 +16326,131 @@ func (s UpgradeEntryMeta) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *UpgradeEntryMeta) UnmarshalBinary(inp []byte) error { +func (s *DiagnosticEvent) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*UpgradeEntryMeta)(nil) - _ encoding.BinaryUnmarshaler = (*UpgradeEntryMeta)(nil) + _ encoding.BinaryMarshaler = (*DiagnosticEvent)(nil) + _ encoding.BinaryUnmarshaler = (*DiagnosticEvent)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s UpgradeEntryMeta) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s DiagnosticEvent) xdrType() {} -var _ xdrType = (*UpgradeEntryMeta)(nil) +var _ xdrType = (*DiagnosticEvent)(nil) -// LedgerCloseMetaV0 is an XDR Struct defines as: +// SorobanTransactionMeta is an XDR Struct defines as: // -// struct LedgerCloseMetaV0 +// struct SorobanTransactionMeta // { -// LedgerHeaderHistoryEntry ledgerHeader; -// // NB: txSet is sorted in "Hash order" -// TransactionSet txSet; -// -// // NB: transactions are sorted in apply order here -// // fees for all transactions are processed first -// // followed by applying transactions -// TransactionResultMeta txProcessing<>; +// ExtensionPoint ext; // -// // upgrades are applied last -// UpgradeEntryMeta upgradesProcessing<>; +// ContractEvent events<>; // custom events populated by the +// // contracts themselves. +// SCVal returnValue; // return value of the host fn invocation // -// // other misc information attached to the ledger close -// SCPHistoryEntry scpInfo<>; +// // Diagnostics events that are not hashed. +// // This will contain all contract and diagnostic events. Even ones +// // that were emitted in a failed contract call. +// DiagnosticEvent diagnosticEvents<>; // }; -type LedgerCloseMetaV0 struct { - LedgerHeader LedgerHeaderHistoryEntry - TxSet TransactionSet - TxProcessing []TransactionResultMeta - UpgradesProcessing []UpgradeEntryMeta - ScpInfo []ScpHistoryEntry +type SorobanTransactionMeta struct { + Ext ExtensionPoint + Events []ContractEvent + ReturnValue ScVal + DiagnosticEvents []DiagnosticEvent } // EncodeTo encodes this value using the Encoder. -func (s *LedgerCloseMetaV0) EncodeTo(e *xdr.Encoder) error { +func (s *SorobanTransactionMeta) EncodeTo(e *xdr.Encoder) error { var err error - if err = s.LedgerHeader.EncodeTo(e); err != nil { - return err - } - if err = s.TxSet.EncodeTo(e); err != nil { + if err = s.Ext.EncodeTo(e); err != nil { return err } - if _, err = e.EncodeUint(uint32(len(s.TxProcessing))); err != nil { + if _, err = e.EncodeUint(uint32(len(s.Events))); err != nil { return err } - for i := 0; i < len(s.TxProcessing); i++ { - if err = s.TxProcessing[i].EncodeTo(e); err != nil { + for i := 0; i < len(s.Events); i++ { + if err = s.Events[i].EncodeTo(e); err != nil { return err } } - if _, err = e.EncodeUint(uint32(len(s.UpgradesProcessing))); err != nil { + if err = s.ReturnValue.EncodeTo(e); err != nil { return err } - for i := 0; i < len(s.UpgradesProcessing); i++ { - if err = s.UpgradesProcessing[i].EncodeTo(e); err != nil { - return err - } - } - if _, err = e.EncodeUint(uint32(len(s.ScpInfo))); err != nil { + if _, err = e.EncodeUint(uint32(len(s.DiagnosticEvents))); err != nil { return err } - for i := 0; i < len(s.ScpInfo); i++ { - if err = s.ScpInfo[i].EncodeTo(e); err != nil { + for i := 0; i < len(s.DiagnosticEvents); i++ { + if err = s.DiagnosticEvents[i].EncodeTo(e); err != nil { return err } } return nil } -var _ decoderFrom = (*LedgerCloseMetaV0)(nil) +var _ decoderFrom = (*SorobanTransactionMeta)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *LedgerCloseMetaV0) DecodeFrom(d *xdr.Decoder) (int, error) { +func (s *SorobanTransactionMeta) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding SorobanTransactionMeta: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = s.LedgerHeader.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding LedgerHeaderHistoryEntry: %s", err) - } - nTmp, err = s.TxSet.DecodeFrom(d) + nTmp, err = s.Ext.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding TransactionSet: %s", err) + return n, fmt.Errorf("decoding ExtensionPoint: %w", err) } var l uint32 l, nTmp, err = d.DecodeUint() n += nTmp if err != nil { - return n, fmt.Errorf("decoding TransactionResultMeta: %s", err) + return n, fmt.Errorf("decoding ContractEvent: %w", err) } - s.TxProcessing = nil + s.Events = nil if l > 0 { - s.TxProcessing = make([]TransactionResultMeta, l) + if il, ok := d.InputLen(); ok && uint(il) < uint(l) { + return n, fmt.Errorf("decoding ContractEvent: length (%d) exceeds remaining input length (%d)", l, il) + } + s.Events = make([]ContractEvent, l) for i := uint32(0); i < l; i++ { - nTmp, err = s.TxProcessing[i].DecodeFrom(d) + nTmp, err = s.Events[i].DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding TransactionResultMeta: %s", err) + return n, fmt.Errorf("decoding ContractEvent: %w", err) } } } - l, nTmp, err = d.DecodeUint() + nTmp, err = s.ReturnValue.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding UpgradeEntryMeta: %s", err) - } - s.UpgradesProcessing = nil - if l > 0 { - s.UpgradesProcessing = make([]UpgradeEntryMeta, l) - for i := uint32(0); i < l; i++ { - nTmp, err = s.UpgradesProcessing[i].DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding UpgradeEntryMeta: %s", err) - } - } + return n, fmt.Errorf("decoding ScVal: %w", err) } l, nTmp, err = d.DecodeUint() n += nTmp if err != nil { - return n, fmt.Errorf("decoding ScpHistoryEntry: %s", err) + return n, fmt.Errorf("decoding DiagnosticEvent: %w", err) } - s.ScpInfo = nil + s.DiagnosticEvents = nil if l > 0 { - s.ScpInfo = make([]ScpHistoryEntry, l) + if il, ok := d.InputLen(); ok && uint(il) < uint(l) { + return n, fmt.Errorf("decoding DiagnosticEvent: length (%d) exceeds remaining input length (%d)", l, il) + } + s.DiagnosticEvents = make([]DiagnosticEvent, l) for i := uint32(0); i < l; i++ { - nTmp, err = s.ScpInfo[i].DecodeFrom(d) + nTmp, err = s.DiagnosticEvents[i].DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding ScpHistoryEntry: %s", err) + return n, fmt.Errorf("decoding DiagnosticEvent: %w", err) } } } @@ -14517,7 +16458,7 @@ func (s *LedgerCloseMetaV0) DecodeFrom(d *xdr.Decoder) (int, error) { } // MarshalBinary implements encoding.BinaryMarshaler. -func (s LedgerCloseMetaV0) MarshalBinary() ([]byte, error) { +func (s SorobanTransactionMeta) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -14525,157 +16466,143 @@ func (s LedgerCloseMetaV0) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *LedgerCloseMetaV0) UnmarshalBinary(inp []byte) error { +func (s *SorobanTransactionMeta) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*LedgerCloseMetaV0)(nil) - _ encoding.BinaryUnmarshaler = (*LedgerCloseMetaV0)(nil) + _ encoding.BinaryMarshaler = (*SorobanTransactionMeta)(nil) + _ encoding.BinaryUnmarshaler = (*SorobanTransactionMeta)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s LedgerCloseMetaV0) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s SorobanTransactionMeta) xdrType() {} -var _ xdrType = (*LedgerCloseMetaV0)(nil) +var _ xdrType = (*SorobanTransactionMeta)(nil) -// LedgerCloseMetaV1 is an XDR Struct defines as: +// TransactionMetaV3 is an XDR Struct defines as: // -// struct LedgerCloseMetaV1 +// struct TransactionMetaV3 // { -// LedgerHeaderHistoryEntry ledgerHeader; -// -// GeneralizedTransactionSet txSet; -// -// // NB: transactions are sorted in apply order here -// // fees for all transactions are processed first -// // followed by applying transactions -// TransactionResultMeta txProcessing<>; -// -// // upgrades are applied last -// UpgradeEntryMeta upgradesProcessing<>; +// ExtensionPoint ext; // -// // other misc information attached to the ledger close -// SCPHistoryEntry scpInfo<>; +// LedgerEntryChanges txChangesBefore; // tx level changes before operations +// // are applied if any +// OperationMeta operations<>; // meta for each operation +// LedgerEntryChanges txChangesAfter; // tx level changes after operations are +// // applied if any +// SorobanTransactionMeta* sorobanMeta; // Soroban-specific meta (only for +// // Soroban transactions). // }; -type LedgerCloseMetaV1 struct { - LedgerHeader LedgerHeaderHistoryEntry - TxSet GeneralizedTransactionSet - TxProcessing []TransactionResultMeta - UpgradesProcessing []UpgradeEntryMeta - ScpInfo []ScpHistoryEntry +type TransactionMetaV3 struct { + Ext ExtensionPoint + TxChangesBefore LedgerEntryChanges + Operations []OperationMeta + TxChangesAfter LedgerEntryChanges + SorobanMeta *SorobanTransactionMeta } // EncodeTo encodes this value using the Encoder. -func (s *LedgerCloseMetaV1) EncodeTo(e *xdr.Encoder) error { +func (s *TransactionMetaV3) EncodeTo(e *xdr.Encoder) error { var err error - if err = s.LedgerHeader.EncodeTo(e); err != nil { + if err = s.Ext.EncodeTo(e); err != nil { return err } - if err = s.TxSet.EncodeTo(e); err != nil { + if err = s.TxChangesBefore.EncodeTo(e); err != nil { return err } - if _, err = e.EncodeUint(uint32(len(s.TxProcessing))); err != nil { + if _, err = e.EncodeUint(uint32(len(s.Operations))); err != nil { return err } - for i := 0; i < len(s.TxProcessing); i++ { - if err = s.TxProcessing[i].EncodeTo(e); err != nil { + for i := 0; i < len(s.Operations); i++ { + if err = s.Operations[i].EncodeTo(e); err != nil { return err } } - if _, err = e.EncodeUint(uint32(len(s.UpgradesProcessing))); err != nil { + if err = s.TxChangesAfter.EncodeTo(e); err != nil { return err } - for i := 0; i < len(s.UpgradesProcessing); i++ { - if err = s.UpgradesProcessing[i].EncodeTo(e); err != nil { - return err - } - } - if _, err = e.EncodeUint(uint32(len(s.ScpInfo))); err != nil { + if _, err = e.EncodeBool(s.SorobanMeta != nil); err != nil { return err } - for i := 0; i < len(s.ScpInfo); i++ { - if err = s.ScpInfo[i].EncodeTo(e); err != nil { + if s.SorobanMeta != nil { + if err = (*s.SorobanMeta).EncodeTo(e); err != nil { return err } } return nil } -var _ decoderFrom = (*LedgerCloseMetaV1)(nil) +var _ decoderFrom = (*TransactionMetaV3)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *LedgerCloseMetaV1) DecodeFrom(d *xdr.Decoder) (int, error) { +func (s *TransactionMetaV3) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding TransactionMetaV3: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = s.LedgerHeader.DecodeFrom(d) + nTmp, err = s.Ext.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding LedgerHeaderHistoryEntry: %s", err) + return n, fmt.Errorf("decoding ExtensionPoint: %w", err) } - nTmp, err = s.TxSet.DecodeFrom(d) + nTmp, err = s.TxChangesBefore.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding GeneralizedTransactionSet: %s", err) + return n, fmt.Errorf("decoding LedgerEntryChanges: %w", err) } var l uint32 l, nTmp, err = d.DecodeUint() n += nTmp if err != nil { - return n, fmt.Errorf("decoding TransactionResultMeta: %s", err) + return n, fmt.Errorf("decoding OperationMeta: %w", err) } - s.TxProcessing = nil + s.Operations = nil if l > 0 { - s.TxProcessing = make([]TransactionResultMeta, l) + if il, ok := d.InputLen(); ok && uint(il) < uint(l) { + return n, fmt.Errorf("decoding OperationMeta: length (%d) exceeds remaining input length (%d)", l, il) + } + s.Operations = make([]OperationMeta, l) for i := uint32(0); i < l; i++ { - nTmp, err = s.TxProcessing[i].DecodeFrom(d) + nTmp, err = s.Operations[i].DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding TransactionResultMeta: %s", err) + return n, fmt.Errorf("decoding OperationMeta: %w", err) } } } - l, nTmp, err = d.DecodeUint() + nTmp, err = s.TxChangesAfter.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding UpgradeEntryMeta: %s", err) - } - s.UpgradesProcessing = nil - if l > 0 { - s.UpgradesProcessing = make([]UpgradeEntryMeta, l) - for i := uint32(0); i < l; i++ { - nTmp, err = s.UpgradesProcessing[i].DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding UpgradeEntryMeta: %s", err) - } - } + return n, fmt.Errorf("decoding LedgerEntryChanges: %w", err) } - l, nTmp, err = d.DecodeUint() + var b bool + b, nTmp, err = d.DecodeBool() n += nTmp if err != nil { - return n, fmt.Errorf("decoding ScpHistoryEntry: %s", err) + return n, fmt.Errorf("decoding SorobanTransactionMeta: %w", err) } - s.ScpInfo = nil - if l > 0 { - s.ScpInfo = make([]ScpHistoryEntry, l) - for i := uint32(0); i < l; i++ { - nTmp, err = s.ScpInfo[i].DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding ScpHistoryEntry: %s", err) - } + s.SorobanMeta = nil + if b { + s.SorobanMeta = new(SorobanTransactionMeta) + nTmp, err = s.SorobanMeta.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding SorobanTransactionMeta: %w", err) } } return n, nil } // MarshalBinary implements encoding.BinaryMarshaler. -func (s LedgerCloseMetaV1) MarshalBinary() ([]byte, error) { +func (s TransactionMetaV3) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -14683,98 +16610,218 @@ func (s LedgerCloseMetaV1) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *LedgerCloseMetaV1) UnmarshalBinary(inp []byte) error { +func (s *TransactionMetaV3) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*LedgerCloseMetaV1)(nil) - _ encoding.BinaryUnmarshaler = (*LedgerCloseMetaV1)(nil) + _ encoding.BinaryMarshaler = (*TransactionMetaV3)(nil) + _ encoding.BinaryUnmarshaler = (*TransactionMetaV3)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s LedgerCloseMetaV1) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s TransactionMetaV3) xdrType() {} -var _ xdrType = (*LedgerCloseMetaV1)(nil) +var _ xdrType = (*TransactionMetaV3)(nil) -// LedgerCloseMeta is an XDR Union defines as: +// InvokeHostFunctionSuccessPreImage is an XDR Struct defines as: // -// union LedgerCloseMeta switch (int v) +// struct InvokeHostFunctionSuccessPreImage +// { +// SCVal returnValue; +// ContractEvent events<>; +// }; +type InvokeHostFunctionSuccessPreImage struct { + ReturnValue ScVal + Events []ContractEvent +} + +// EncodeTo encodes this value using the Encoder. +func (s *InvokeHostFunctionSuccessPreImage) EncodeTo(e *xdr.Encoder) error { + var err error + if err = s.ReturnValue.EncodeTo(e); err != nil { + return err + } + if _, err = e.EncodeUint(uint32(len(s.Events))); err != nil { + return err + } + for i := 0; i < len(s.Events); i++ { + if err = s.Events[i].EncodeTo(e); err != nil { + return err + } + } + return nil +} + +var _ decoderFrom = (*InvokeHostFunctionSuccessPreImage)(nil) + +// DecodeFrom decodes this value using the Decoder. +func (s *InvokeHostFunctionSuccessPreImage) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding InvokeHostFunctionSuccessPreImage: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + var err error + var n, nTmp int + nTmp, err = s.ReturnValue.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ScVal: %w", err) + } + var l uint32 + l, nTmp, err = d.DecodeUint() + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ContractEvent: %w", err) + } + s.Events = nil + if l > 0 { + if il, ok := d.InputLen(); ok && uint(il) < uint(l) { + return n, fmt.Errorf("decoding ContractEvent: length (%d) exceeds remaining input length (%d)", l, il) + } + s.Events = make([]ContractEvent, l) + for i := uint32(0); i < l; i++ { + nTmp, err = s.Events[i].DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ContractEvent: %w", err) + } + } + } + return n, nil +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (s InvokeHostFunctionSuccessPreImage) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *InvokeHostFunctionSuccessPreImage) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} + +var ( + _ encoding.BinaryMarshaler = (*InvokeHostFunctionSuccessPreImage)(nil) + _ encoding.BinaryUnmarshaler = (*InvokeHostFunctionSuccessPreImage)(nil) +) + +// xdrType signals that this type represents XDR values defined by this package. +func (s InvokeHostFunctionSuccessPreImage) xdrType() {} + +var _ xdrType = (*InvokeHostFunctionSuccessPreImage)(nil) + +// TransactionMeta is an XDR Union defines as: +// +// union TransactionMeta switch (int v) // { // case 0: -// LedgerCloseMetaV0 v0; +// OperationMeta operations<>; // case 1: -// LedgerCloseMetaV1 v1; +// TransactionMetaV1 v1; +// case 2: +// TransactionMetaV2 v2; +// case 3: +// TransactionMetaV3 v3; // }; -type LedgerCloseMeta struct { - V int32 - V0 *LedgerCloseMetaV0 - V1 *LedgerCloseMetaV1 +type TransactionMeta struct { + V int32 + Operations *[]OperationMeta + V1 *TransactionMetaV1 + V2 *TransactionMetaV2 + V3 *TransactionMetaV3 } // SwitchFieldName returns the field name in which this union's // discriminant is stored -func (u LedgerCloseMeta) SwitchFieldName() string { +func (u TransactionMeta) SwitchFieldName() string { return "V" } // ArmForSwitch returns which field name should be used for storing -// the value for an instance of LedgerCloseMeta -func (u LedgerCloseMeta) ArmForSwitch(sw int32) (string, bool) { +// the value for an instance of TransactionMeta +func (u TransactionMeta) ArmForSwitch(sw int32) (string, bool) { switch int32(sw) { case 0: - return "V0", true + return "Operations", true case 1: return "V1", true + case 2: + return "V2", true + case 3: + return "V3", true } return "-", false } -// NewLedgerCloseMeta creates a new LedgerCloseMeta. -func NewLedgerCloseMeta(v int32, value interface{}) (result LedgerCloseMeta, err error) { +// NewTransactionMeta creates a new TransactionMeta. +func NewTransactionMeta(v int32, value interface{}) (result TransactionMeta, err error) { result.V = v switch int32(v) { case 0: - tv, ok := value.(LedgerCloseMetaV0) + tv, ok := value.([]OperationMeta) if !ok { - err = fmt.Errorf("invalid value, must be LedgerCloseMetaV0") + err = errors.New("invalid value, must be []OperationMeta") return } - result.V0 = &tv + result.Operations = &tv case 1: - tv, ok := value.(LedgerCloseMetaV1) + tv, ok := value.(TransactionMetaV1) if !ok { - err = fmt.Errorf("invalid value, must be LedgerCloseMetaV1") + err = errors.New("invalid value, must be TransactionMetaV1") return } result.V1 = &tv + case 2: + tv, ok := value.(TransactionMetaV2) + if !ok { + err = errors.New("invalid value, must be TransactionMetaV2") + return + } + result.V2 = &tv + case 3: + tv, ok := value.(TransactionMetaV3) + if !ok { + err = errors.New("invalid value, must be TransactionMetaV3") + return + } + result.V3 = &tv } return } -// MustV0 retrieves the V0 value from the union, +// MustOperations retrieves the Operations value from the union, // panicing if the value is not set. -func (u LedgerCloseMeta) MustV0() LedgerCloseMetaV0 { - val, ok := u.GetV0() +func (u TransactionMeta) MustOperations() []OperationMeta { + val, ok := u.GetOperations() if !ok { - panic("arm V0 is not set") + panic("arm Operations is not set") } return val } -// GetV0 retrieves the V0 value from the union, +// GetOperations retrieves the Operations value from the union, // returning ok if the union's switch indicated the value is valid. -func (u LedgerCloseMeta) GetV0() (result LedgerCloseMetaV0, ok bool) { +func (u TransactionMeta) GetOperations() (result []OperationMeta, ok bool) { armName, _ := u.ArmForSwitch(int32(u.V)) - if armName == "V0" { - result = *u.V0 + if armName == "Operations" { + result = *u.Operations ok = true } @@ -14783,7 +16830,7 @@ func (u LedgerCloseMeta) GetV0() (result LedgerCloseMetaV0, ok bool) { // MustV1 retrieves the V1 value from the union, // panicing if the value is not set. -func (u LedgerCloseMeta) MustV1() LedgerCloseMetaV1 { +func (u TransactionMeta) MustV1() TransactionMetaV1 { val, ok := u.GetV1() if !ok { @@ -14795,7 +16842,7 @@ func (u LedgerCloseMeta) MustV1() LedgerCloseMetaV1 { // GetV1 retrieves the V1 value from the union, // returning ok if the union's switch indicated the value is valid. -func (u LedgerCloseMeta) GetV1() (result LedgerCloseMetaV1, ok bool) { +func (u TransactionMeta) GetV1() (result TransactionMetaV1, ok bool) { armName, _ := u.ArmForSwitch(int32(u.V)) if armName == "V1" { @@ -14806,61 +16853,161 @@ func (u LedgerCloseMeta) GetV1() (result LedgerCloseMetaV1, ok bool) { return } +// MustV2 retrieves the V2 value from the union, +// panicing if the value is not set. +func (u TransactionMeta) MustV2() TransactionMetaV2 { + val, ok := u.GetV2() + + if !ok { + panic("arm V2 is not set") + } + + return val +} + +// GetV2 retrieves the V2 value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u TransactionMeta) GetV2() (result TransactionMetaV2, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.V)) + + if armName == "V2" { + result = *u.V2 + ok = true + } + + return +} + +// MustV3 retrieves the V3 value from the union, +// panicing if the value is not set. +func (u TransactionMeta) MustV3() TransactionMetaV3 { + val, ok := u.GetV3() + + if !ok { + panic("arm V3 is not set") + } + + return val +} + +// GetV3 retrieves the V3 value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u TransactionMeta) GetV3() (result TransactionMetaV3, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.V)) + + if armName == "V3" { + result = *u.V3 + ok = true + } + + return +} + // EncodeTo encodes this value using the Encoder. -func (u LedgerCloseMeta) EncodeTo(e *xdr.Encoder) error { +func (u TransactionMeta) EncodeTo(e *xdr.Encoder) error { var err error if _, err = e.EncodeInt(int32(u.V)); err != nil { return err } switch int32(u.V) { case 0: - if err = (*u.V0).EncodeTo(e); err != nil { + if _, err = e.EncodeUint(uint32(len((*u.Operations)))); err != nil { return err } + for i := 0; i < len((*u.Operations)); i++ { + if err = (*u.Operations)[i].EncodeTo(e); err != nil { + return err + } + } return nil case 1: if err = (*u.V1).EncodeTo(e); err != nil { return err } return nil + case 2: + if err = (*u.V2).EncodeTo(e); err != nil { + return err + } + return nil + case 3: + if err = (*u.V3).EncodeTo(e); err != nil { + return err + } + return nil } - return fmt.Errorf("V (int32) switch value '%d' is not valid for union LedgerCloseMeta", u.V) + return fmt.Errorf("V (int32) switch value '%d' is not valid for union TransactionMeta", u.V) } -var _ decoderFrom = (*LedgerCloseMeta)(nil) +var _ decoderFrom = (*TransactionMeta)(nil) // DecodeFrom decodes this value using the Decoder. -func (u *LedgerCloseMeta) DecodeFrom(d *xdr.Decoder) (int, error) { +func (u *TransactionMeta) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding TransactionMeta: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int u.V, nTmp, err = d.DecodeInt() n += nTmp if err != nil { - return n, fmt.Errorf("decoding Int: %s", err) + return n, fmt.Errorf("decoding Int: %w", err) } switch int32(u.V) { case 0: - u.V0 = new(LedgerCloseMetaV0) - nTmp, err = (*u.V0).DecodeFrom(d) + u.Operations = new([]OperationMeta) + var l uint32 + l, nTmp, err = d.DecodeUint() n += nTmp if err != nil { - return n, fmt.Errorf("decoding LedgerCloseMetaV0: %s", err) + return n, fmt.Errorf("decoding OperationMeta: %w", err) + } + (*u.Operations) = nil + if l > 0 { + if il, ok := d.InputLen(); ok && uint(il) < uint(l) { + return n, fmt.Errorf("decoding OperationMeta: length (%d) exceeds remaining input length (%d)", l, il) + } + (*u.Operations) = make([]OperationMeta, l) + for i := uint32(0); i < l; i++ { + nTmp, err = (*u.Operations)[i].DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding OperationMeta: %w", err) + } + } } return n, nil case 1: - u.V1 = new(LedgerCloseMetaV1) - nTmp, err = (*u.V1).DecodeFrom(d) + u.V1 = new(TransactionMetaV1) + nTmp, err = (*u.V1).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding TransactionMetaV1: %w", err) + } + return n, nil + case 2: + u.V2 = new(TransactionMetaV2) + nTmp, err = (*u.V2).DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding LedgerCloseMetaV1: %s", err) + return n, fmt.Errorf("decoding TransactionMetaV2: %w", err) + } + return n, nil + case 3: + u.V3 = new(TransactionMetaV3) + nTmp, err = (*u.V3).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding TransactionMetaV3: %w", err) } return n, nil } - return n, fmt.Errorf("union LedgerCloseMeta has invalid V (int32) switch value '%d'", u.V) + return n, fmt.Errorf("union TransactionMeta has invalid V (int32) switch value '%d'", u.V) } // MarshalBinary implements encoding.BinaryMarshaler. -func (s LedgerCloseMeta) MarshalBinary() ([]byte, error) { +func (s TransactionMeta) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -14868,91 +17015,84 @@ func (s LedgerCloseMeta) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *LedgerCloseMeta) UnmarshalBinary(inp []byte) error { +func (s *TransactionMeta) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*LedgerCloseMeta)(nil) - _ encoding.BinaryUnmarshaler = (*LedgerCloseMeta)(nil) + _ encoding.BinaryMarshaler = (*TransactionMeta)(nil) + _ encoding.BinaryUnmarshaler = (*TransactionMeta)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s LedgerCloseMeta) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s TransactionMeta) xdrType() {} -var _ xdrType = (*LedgerCloseMeta)(nil) +var _ xdrType = (*TransactionMeta)(nil) -// ErrorCode is an XDR Enum defines as: +// TransactionResultMeta is an XDR Struct defines as: // -// enum ErrorCode +// struct TransactionResultMeta // { -// ERR_MISC = 0, // Unspecific error -// ERR_DATA = 1, // Malformed data -// ERR_CONF = 2, // Misconfiguration error -// ERR_AUTH = 3, // Authentication failure -// ERR_LOAD = 4 // System overloaded +// TransactionResultPair result; +// LedgerEntryChanges feeProcessing; +// TransactionMeta txApplyProcessing; // }; -type ErrorCode int32 - -const ( - ErrorCodeErrMisc ErrorCode = 0 - ErrorCodeErrData ErrorCode = 1 - ErrorCodeErrConf ErrorCode = 2 - ErrorCodeErrAuth ErrorCode = 3 - ErrorCodeErrLoad ErrorCode = 4 -) - -var errorCodeMap = map[int32]string{ - 0: "ErrorCodeErrMisc", - 1: "ErrorCodeErrData", - 2: "ErrorCodeErrConf", - 3: "ErrorCodeErrAuth", - 4: "ErrorCodeErrLoad", -} - -// ValidEnum validates a proposed value for this enum. Implements -// the Enum interface for ErrorCode -func (e ErrorCode) ValidEnum(v int32) bool { - _, ok := errorCodeMap[v] - return ok -} - -// String returns the name of `e` -func (e ErrorCode) String() string { - name, _ := errorCodeMap[int32(e)] - return name +type TransactionResultMeta struct { + Result TransactionResultPair + FeeProcessing LedgerEntryChanges + TxApplyProcessing TransactionMeta } // EncodeTo encodes this value using the Encoder. -func (e ErrorCode) EncodeTo(enc *xdr.Encoder) error { - if _, ok := errorCodeMap[int32(e)]; !ok { - return fmt.Errorf("'%d' is not a valid ErrorCode enum value", e) +func (s *TransactionResultMeta) EncodeTo(e *xdr.Encoder) error { + var err error + if err = s.Result.EncodeTo(e); err != nil { + return err } - _, err := enc.EncodeInt(int32(e)) - return err + if err = s.FeeProcessing.EncodeTo(e); err != nil { + return err + } + if err = s.TxApplyProcessing.EncodeTo(e); err != nil { + return err + } + return nil } -var _ decoderFrom = (*ErrorCode)(nil) +var _ decoderFrom = (*TransactionResultMeta)(nil) // DecodeFrom decodes this value using the Decoder. -func (e *ErrorCode) DecodeFrom(d *xdr.Decoder) (int, error) { - v, n, err := d.DecodeInt() +func (s *TransactionResultMeta) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding TransactionResultMeta: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + var err error + var n, nTmp int + nTmp, err = s.Result.DecodeFrom(d, maxDepth) + n += nTmp if err != nil { - return n, fmt.Errorf("decoding ErrorCode: %s", err) + return n, fmt.Errorf("decoding TransactionResultPair: %w", err) } - if _, ok := errorCodeMap[v]; !ok { - return n, fmt.Errorf("'%d' is not a valid ErrorCode enum value", v) + nTmp, err = s.FeeProcessing.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding LedgerEntryChanges: %w", err) + } + nTmp, err = s.TxApplyProcessing.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding TransactionMeta: %w", err) } - *e = ErrorCode(v) return n, nil } // MarshalBinary implements encoding.BinaryMarshaler. -func (s ErrorCode) MarshalBinary() ([]byte, error) { +func (s TransactionResultMeta) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -14960,69 +17100,74 @@ func (s ErrorCode) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *ErrorCode) UnmarshalBinary(inp []byte) error { +func (s *TransactionResultMeta) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*ErrorCode)(nil) - _ encoding.BinaryUnmarshaler = (*ErrorCode)(nil) + _ encoding.BinaryMarshaler = (*TransactionResultMeta)(nil) + _ encoding.BinaryUnmarshaler = (*TransactionResultMeta)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s ErrorCode) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s TransactionResultMeta) xdrType() {} -var _ xdrType = (*ErrorCode)(nil) +var _ xdrType = (*TransactionResultMeta)(nil) -// Error is an XDR Struct defines as: +// UpgradeEntryMeta is an XDR Struct defines as: // -// struct Error +// struct UpgradeEntryMeta // { -// ErrorCode code; -// string msg<100>; +// LedgerUpgrade upgrade; +// LedgerEntryChanges changes; // }; -type Error struct { - Code ErrorCode - Msg string `xdrmaxsize:"100"` +type UpgradeEntryMeta struct { + Upgrade LedgerUpgrade + Changes LedgerEntryChanges } // EncodeTo encodes this value using the Encoder. -func (s *Error) EncodeTo(e *xdr.Encoder) error { +func (s *UpgradeEntryMeta) EncodeTo(e *xdr.Encoder) error { var err error - if err = s.Code.EncodeTo(e); err != nil { + if err = s.Upgrade.EncodeTo(e); err != nil { return err } - if _, err = e.EncodeString(string(s.Msg)); err != nil { + if err = s.Changes.EncodeTo(e); err != nil { return err } return nil } -var _ decoderFrom = (*Error)(nil) +var _ decoderFrom = (*UpgradeEntryMeta)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *Error) DecodeFrom(d *xdr.Decoder) (int, error) { +func (s *UpgradeEntryMeta) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding UpgradeEntryMeta: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = s.Code.DecodeFrom(d) + nTmp, err = s.Upgrade.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding ErrorCode: %s", err) + return n, fmt.Errorf("decoding LedgerUpgrade: %w", err) } - s.Msg, nTmp, err = d.DecodeString(100) + nTmp, err = s.Changes.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Msg: %s", err) + return n, fmt.Errorf("decoding LedgerEntryChanges: %w", err) } return n, nil } // MarshalBinary implements encoding.BinaryMarshaler. -func (s Error) MarshalBinary() ([]byte, error) { +func (s UpgradeEntryMeta) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -15030,59 +17175,171 @@ func (s Error) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *Error) UnmarshalBinary(inp []byte) error { +func (s *UpgradeEntryMeta) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*Error)(nil) - _ encoding.BinaryUnmarshaler = (*Error)(nil) + _ encoding.BinaryMarshaler = (*UpgradeEntryMeta)(nil) + _ encoding.BinaryUnmarshaler = (*UpgradeEntryMeta)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s Error) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s UpgradeEntryMeta) xdrType() {} -var _ xdrType = (*Error)(nil) +var _ xdrType = (*UpgradeEntryMeta)(nil) -// SendMore is an XDR Struct defines as: +// LedgerCloseMetaV0 is an XDR Struct defines as: // -// struct SendMore +// struct LedgerCloseMetaV0 // { -// uint32 numMessages; +// LedgerHeaderHistoryEntry ledgerHeader; +// // NB: txSet is sorted in "Hash order" +// TransactionSet txSet; +// +// // NB: transactions are sorted in apply order here +// // fees for all transactions are processed first +// // followed by applying transactions +// TransactionResultMeta txProcessing<>; +// +// // upgrades are applied last +// UpgradeEntryMeta upgradesProcessing<>; +// +// // other misc information attached to the ledger close +// SCPHistoryEntry scpInfo<>; // }; -type SendMore struct { - NumMessages Uint32 +type LedgerCloseMetaV0 struct { + LedgerHeader LedgerHeaderHistoryEntry + TxSet TransactionSet + TxProcessing []TransactionResultMeta + UpgradesProcessing []UpgradeEntryMeta + ScpInfo []ScpHistoryEntry } // EncodeTo encodes this value using the Encoder. -func (s *SendMore) EncodeTo(e *xdr.Encoder) error { +func (s *LedgerCloseMetaV0) EncodeTo(e *xdr.Encoder) error { var err error - if err = s.NumMessages.EncodeTo(e); err != nil { + if err = s.LedgerHeader.EncodeTo(e); err != nil { + return err + } + if err = s.TxSet.EncodeTo(e); err != nil { + return err + } + if _, err = e.EncodeUint(uint32(len(s.TxProcessing))); err != nil { + return err + } + for i := 0; i < len(s.TxProcessing); i++ { + if err = s.TxProcessing[i].EncodeTo(e); err != nil { + return err + } + } + if _, err = e.EncodeUint(uint32(len(s.UpgradesProcessing))); err != nil { + return err + } + for i := 0; i < len(s.UpgradesProcessing); i++ { + if err = s.UpgradesProcessing[i].EncodeTo(e); err != nil { + return err + } + } + if _, err = e.EncodeUint(uint32(len(s.ScpInfo))); err != nil { return err } + for i := 0; i < len(s.ScpInfo); i++ { + if err = s.ScpInfo[i].EncodeTo(e); err != nil { + return err + } + } return nil } -var _ decoderFrom = (*SendMore)(nil) +var _ decoderFrom = (*LedgerCloseMetaV0)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *SendMore) DecodeFrom(d *xdr.Decoder) (int, error) { +func (s *LedgerCloseMetaV0) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding LedgerCloseMetaV0: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = s.NumMessages.DecodeFrom(d) + nTmp, err = s.LedgerHeader.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding LedgerHeaderHistoryEntry: %w", err) + } + nTmp, err = s.TxSet.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding TransactionSet: %w", err) + } + var l uint32 + l, nTmp, err = d.DecodeUint() + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding TransactionResultMeta: %w", err) + } + s.TxProcessing = nil + if l > 0 { + if il, ok := d.InputLen(); ok && uint(il) < uint(l) { + return n, fmt.Errorf("decoding TransactionResultMeta: length (%d) exceeds remaining input length (%d)", l, il) + } + s.TxProcessing = make([]TransactionResultMeta, l) + for i := uint32(0); i < l; i++ { + nTmp, err = s.TxProcessing[i].DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding TransactionResultMeta: %w", err) + } + } + } + l, nTmp, err = d.DecodeUint() + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding UpgradeEntryMeta: %w", err) + } + s.UpgradesProcessing = nil + if l > 0 { + if il, ok := d.InputLen(); ok && uint(il) < uint(l) { + return n, fmt.Errorf("decoding UpgradeEntryMeta: length (%d) exceeds remaining input length (%d)", l, il) + } + s.UpgradesProcessing = make([]UpgradeEntryMeta, l) + for i := uint32(0); i < l; i++ { + nTmp, err = s.UpgradesProcessing[i].DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding UpgradeEntryMeta: %w", err) + } + } + } + l, nTmp, err = d.DecodeUint() n += nTmp if err != nil { - return n, fmt.Errorf("decoding Uint32: %s", err) + return n, fmt.Errorf("decoding ScpHistoryEntry: %w", err) + } + s.ScpInfo = nil + if l > 0 { + if il, ok := d.InputLen(); ok && uint(il) < uint(l) { + return n, fmt.Errorf("decoding ScpHistoryEntry: length (%d) exceeds remaining input length (%d)", l, il) + } + s.ScpInfo = make([]ScpHistoryEntry, l) + for i := uint32(0); i < l; i++ { + nTmp, err = s.ScpInfo[i].DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ScpHistoryEntry: %w", err) + } + } } return n, nil } // MarshalBinary implements encoding.BinaryMarshaler. -func (s SendMore) MarshalBinary() ([]byte, error) { +func (s LedgerCloseMetaV0) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -15090,281 +17347,260 @@ func (s SendMore) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *SendMore) UnmarshalBinary(inp []byte) error { +func (s *LedgerCloseMetaV0) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*SendMore)(nil) - _ encoding.BinaryUnmarshaler = (*SendMore)(nil) + _ encoding.BinaryMarshaler = (*LedgerCloseMetaV0)(nil) + _ encoding.BinaryUnmarshaler = (*LedgerCloseMetaV0)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s SendMore) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s LedgerCloseMetaV0) xdrType() {} -var _ xdrType = (*SendMore)(nil) +var _ xdrType = (*LedgerCloseMetaV0)(nil) -// AuthCert is an XDR Struct defines as: +// LedgerCloseMetaV1 is an XDR Struct defines as: // -// struct AuthCert +// struct LedgerCloseMetaV1 // { -// Curve25519Public pubkey; -// uint64 expiration; -// Signature sig; +// // We forgot to add an ExtensionPoint in v0 but at least +// // we can add one now in v1. +// ExtensionPoint ext; +// +// LedgerHeaderHistoryEntry ledgerHeader; +// +// GeneralizedTransactionSet txSet; +// +// // NB: transactions are sorted in apply order here +// // fees for all transactions are processed first +// // followed by applying transactions +// TransactionResultMeta txProcessing<>; +// +// // upgrades are applied last +// UpgradeEntryMeta upgradesProcessing<>; +// +// // other misc information attached to the ledger close +// SCPHistoryEntry scpInfo<>; +// +// // Size in bytes of BucketList, to support downstream +// // systems calculating storage fees correctly. +// uint64 totalByteSizeOfBucketList; +// +// // Temp keys that are being evicted at this ledger. +// LedgerKey evictedTemporaryLedgerKeys<>; +// +// // Archived restorable ledger entries that are being +// // evicted at this ledger. +// LedgerEntry evictedPersistentLedgerEntries<>; // }; -type AuthCert struct { - Pubkey Curve25519Public - Expiration Uint64 - Sig Signature +type LedgerCloseMetaV1 struct { + Ext ExtensionPoint + LedgerHeader LedgerHeaderHistoryEntry + TxSet GeneralizedTransactionSet + TxProcessing []TransactionResultMeta + UpgradesProcessing []UpgradeEntryMeta + ScpInfo []ScpHistoryEntry + TotalByteSizeOfBucketList Uint64 + EvictedTemporaryLedgerKeys []LedgerKey + EvictedPersistentLedgerEntries []LedgerEntry } // EncodeTo encodes this value using the Encoder. -func (s *AuthCert) EncodeTo(e *xdr.Encoder) error { +func (s *LedgerCloseMetaV1) EncodeTo(e *xdr.Encoder) error { var err error - if err = s.Pubkey.EncodeTo(e); err != nil { + if err = s.Ext.EncodeTo(e); err != nil { return err } - if err = s.Expiration.EncodeTo(e); err != nil { + if err = s.LedgerHeader.EncodeTo(e); err != nil { return err } - if err = s.Sig.EncodeTo(e); err != nil { + if err = s.TxSet.EncodeTo(e); err != nil { return err } - return nil -} - -var _ decoderFrom = (*AuthCert)(nil) - -// DecodeFrom decodes this value using the Decoder. -func (s *AuthCert) DecodeFrom(d *xdr.Decoder) (int, error) { - var err error - var n, nTmp int - nTmp, err = s.Pubkey.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Curve25519Public: %s", err) - } - nTmp, err = s.Expiration.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Uint64: %s", err) + if _, err = e.EncodeUint(uint32(len(s.TxProcessing))); err != nil { + return err } - nTmp, err = s.Sig.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Signature: %s", err) + for i := 0; i < len(s.TxProcessing); i++ { + if err = s.TxProcessing[i].EncodeTo(e); err != nil { + return err + } } - return n, nil -} - -// MarshalBinary implements encoding.BinaryMarshaler. -func (s AuthCert) MarshalBinary() ([]byte, error) { - b := bytes.Buffer{} - e := xdr.NewEncoder(&b) - err := s.EncodeTo(e) - return b.Bytes(), err -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *AuthCert) UnmarshalBinary(inp []byte) error { - r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) - return err -} - -var ( - _ encoding.BinaryMarshaler = (*AuthCert)(nil) - _ encoding.BinaryUnmarshaler = (*AuthCert)(nil) -) - -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s AuthCert) xdrType() {} - -var _ xdrType = (*AuthCert)(nil) - -// Hello is an XDR Struct defines as: -// -// struct Hello -// { -// uint32 ledgerVersion; -// uint32 overlayVersion; -// uint32 overlayMinVersion; -// Hash networkID; -// string versionStr<100>; -// int listeningPort; -// NodeID peerID; -// AuthCert cert; -// uint256 nonce; -// }; -type Hello struct { - LedgerVersion Uint32 - OverlayVersion Uint32 - OverlayMinVersion Uint32 - NetworkId Hash - VersionStr string `xdrmaxsize:"100"` - ListeningPort int32 - PeerId NodeId - Cert AuthCert - Nonce Uint256 -} - -// EncodeTo encodes this value using the Encoder. -func (s *Hello) EncodeTo(e *xdr.Encoder) error { - var err error - if err = s.LedgerVersion.EncodeTo(e); err != nil { + if _, err = e.EncodeUint(uint32(len(s.UpgradesProcessing))); err != nil { return err } - if err = s.OverlayVersion.EncodeTo(e); err != nil { - return err + for i := 0; i < len(s.UpgradesProcessing); i++ { + if err = s.UpgradesProcessing[i].EncodeTo(e); err != nil { + return err + } } - if err = s.OverlayMinVersion.EncodeTo(e); err != nil { + if _, err = e.EncodeUint(uint32(len(s.ScpInfo))); err != nil { return err } - if err = s.NetworkId.EncodeTo(e); err != nil { - return err + for i := 0; i < len(s.ScpInfo); i++ { + if err = s.ScpInfo[i].EncodeTo(e); err != nil { + return err + } } - if _, err = e.EncodeString(string(s.VersionStr)); err != nil { + if err = s.TotalByteSizeOfBucketList.EncodeTo(e); err != nil { return err } - if _, err = e.EncodeInt(int32(s.ListeningPort)); err != nil { + if _, err = e.EncodeUint(uint32(len(s.EvictedTemporaryLedgerKeys))); err != nil { return err } - if err = s.PeerId.EncodeTo(e); err != nil { - return err + for i := 0; i < len(s.EvictedTemporaryLedgerKeys); i++ { + if err = s.EvictedTemporaryLedgerKeys[i].EncodeTo(e); err != nil { + return err + } } - if err = s.Cert.EncodeTo(e); err != nil { + if _, err = e.EncodeUint(uint32(len(s.EvictedPersistentLedgerEntries))); err != nil { return err } - if err = s.Nonce.EncodeTo(e); err != nil { - return err + for i := 0; i < len(s.EvictedPersistentLedgerEntries); i++ { + if err = s.EvictedPersistentLedgerEntries[i].EncodeTo(e); err != nil { + return err + } } return nil } -var _ decoderFrom = (*Hello)(nil) +var _ decoderFrom = (*LedgerCloseMetaV1)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *Hello) DecodeFrom(d *xdr.Decoder) (int, error) { +func (s *LedgerCloseMetaV1) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding LedgerCloseMetaV1: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = s.LedgerVersion.DecodeFrom(d) + nTmp, err = s.Ext.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Uint32: %s", err) + return n, fmt.Errorf("decoding ExtensionPoint: %w", err) } - nTmp, err = s.OverlayVersion.DecodeFrom(d) + nTmp, err = s.LedgerHeader.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Uint32: %s", err) + return n, fmt.Errorf("decoding LedgerHeaderHistoryEntry: %w", err) } - nTmp, err = s.OverlayMinVersion.DecodeFrom(d) + nTmp, err = s.TxSet.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Uint32: %s", err) + return n, fmt.Errorf("decoding GeneralizedTransactionSet: %w", err) } - nTmp, err = s.NetworkId.DecodeFrom(d) + var l uint32 + l, nTmp, err = d.DecodeUint() n += nTmp if err != nil { - return n, fmt.Errorf("decoding Hash: %s", err) + return n, fmt.Errorf("decoding TransactionResultMeta: %w", err) } - s.VersionStr, nTmp, err = d.DecodeString(100) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding VersionStr: %s", err) + s.TxProcessing = nil + if l > 0 { + if il, ok := d.InputLen(); ok && uint(il) < uint(l) { + return n, fmt.Errorf("decoding TransactionResultMeta: length (%d) exceeds remaining input length (%d)", l, il) + } + s.TxProcessing = make([]TransactionResultMeta, l) + for i := uint32(0); i < l; i++ { + nTmp, err = s.TxProcessing[i].DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding TransactionResultMeta: %w", err) + } + } } - s.ListeningPort, nTmp, err = d.DecodeInt() + l, nTmp, err = d.DecodeUint() n += nTmp if err != nil { - return n, fmt.Errorf("decoding Int: %s", err) + return n, fmt.Errorf("decoding UpgradeEntryMeta: %w", err) + } + s.UpgradesProcessing = nil + if l > 0 { + if il, ok := d.InputLen(); ok && uint(il) < uint(l) { + return n, fmt.Errorf("decoding UpgradeEntryMeta: length (%d) exceeds remaining input length (%d)", l, il) + } + s.UpgradesProcessing = make([]UpgradeEntryMeta, l) + for i := uint32(0); i < l; i++ { + nTmp, err = s.UpgradesProcessing[i].DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding UpgradeEntryMeta: %w", err) + } + } } - nTmp, err = s.PeerId.DecodeFrom(d) + l, nTmp, err = d.DecodeUint() n += nTmp if err != nil { - return n, fmt.Errorf("decoding NodeId: %s", err) + return n, fmt.Errorf("decoding ScpHistoryEntry: %w", err) + } + s.ScpInfo = nil + if l > 0 { + if il, ok := d.InputLen(); ok && uint(il) < uint(l) { + return n, fmt.Errorf("decoding ScpHistoryEntry: length (%d) exceeds remaining input length (%d)", l, il) + } + s.ScpInfo = make([]ScpHistoryEntry, l) + for i := uint32(0); i < l; i++ { + nTmp, err = s.ScpInfo[i].DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ScpHistoryEntry: %w", err) + } + } } - nTmp, err = s.Cert.DecodeFrom(d) + nTmp, err = s.TotalByteSizeOfBucketList.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding AuthCert: %s", err) + return n, fmt.Errorf("decoding Uint64: %w", err) } - nTmp, err = s.Nonce.DecodeFrom(d) + l, nTmp, err = d.DecodeUint() n += nTmp if err != nil { - return n, fmt.Errorf("decoding Uint256: %s", err) + return n, fmt.Errorf("decoding LedgerKey: %w", err) } - return n, nil -} - -// MarshalBinary implements encoding.BinaryMarshaler. -func (s Hello) MarshalBinary() ([]byte, error) { - b := bytes.Buffer{} - e := xdr.NewEncoder(&b) - err := s.EncodeTo(e) - return b.Bytes(), err -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *Hello) UnmarshalBinary(inp []byte) error { - r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) - return err -} - -var ( - _ encoding.BinaryMarshaler = (*Hello)(nil) - _ encoding.BinaryUnmarshaler = (*Hello)(nil) -) - -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s Hello) xdrType() {} - -var _ xdrType = (*Hello)(nil) - -// Auth is an XDR Struct defines as: -// -// struct Auth -// { -// // Empty message, just to confirm -// // establishment of MAC keys. -// int unused; -// }; -type Auth struct { - Unused int32 -} - -// EncodeTo encodes this value using the Encoder. -func (s *Auth) EncodeTo(e *xdr.Encoder) error { - var err error - if _, err = e.EncodeInt(int32(s.Unused)); err != nil { - return err + s.EvictedTemporaryLedgerKeys = nil + if l > 0 { + if il, ok := d.InputLen(); ok && uint(il) < uint(l) { + return n, fmt.Errorf("decoding LedgerKey: length (%d) exceeds remaining input length (%d)", l, il) + } + s.EvictedTemporaryLedgerKeys = make([]LedgerKey, l) + for i := uint32(0); i < l; i++ { + nTmp, err = s.EvictedTemporaryLedgerKeys[i].DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding LedgerKey: %w", err) + } + } } - return nil -} - -var _ decoderFrom = (*Auth)(nil) - -// DecodeFrom decodes this value using the Decoder. -func (s *Auth) DecodeFrom(d *xdr.Decoder) (int, error) { - var err error - var n, nTmp int - s.Unused, nTmp, err = d.DecodeInt() + l, nTmp, err = d.DecodeUint() n += nTmp if err != nil { - return n, fmt.Errorf("decoding Int: %s", err) + return n, fmt.Errorf("decoding LedgerEntry: %w", err) + } + s.EvictedPersistentLedgerEntries = nil + if l > 0 { + if il, ok := d.InputLen(); ok && uint(il) < uint(l) { + return n, fmt.Errorf("decoding LedgerEntry: length (%d) exceeds remaining input length (%d)", l, il) + } + s.EvictedPersistentLedgerEntries = make([]LedgerEntry, l) + for i := uint32(0); i < l; i++ { + nTmp, err = s.EvictedPersistentLedgerEntries[i].DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding LedgerEntry: %w", err) + } + } } return n, nil } // MarshalBinary implements encoding.BinaryMarshaler. -func (s Auth) MarshalBinary() ([]byte, error) { +func (s LedgerCloseMetaV1) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -15372,206 +17608,124 @@ func (s Auth) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *Auth) UnmarshalBinary(inp []byte) error { +func (s *LedgerCloseMetaV1) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*Auth)(nil) - _ encoding.BinaryUnmarshaler = (*Auth)(nil) + _ encoding.BinaryMarshaler = (*LedgerCloseMetaV1)(nil) + _ encoding.BinaryUnmarshaler = (*LedgerCloseMetaV1)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s Auth) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s LedgerCloseMetaV1) xdrType() {} -var _ xdrType = (*Auth)(nil) +var _ xdrType = (*LedgerCloseMetaV1)(nil) -// IpAddrType is an XDR Enum defines as: +// LedgerCloseMeta is an XDR Union defines as: // -// enum IPAddrType +// union LedgerCloseMeta switch (int v) // { -// IPv4 = 0, -// IPv6 = 1 +// case 0: +// LedgerCloseMetaV0 v0; +// case 1: +// LedgerCloseMetaV1 v1; // }; -type IpAddrType int32 - -const ( - IpAddrTypeIPv4 IpAddrType = 0 - IpAddrTypeIPv6 IpAddrType = 1 -) - -var ipAddrTypeMap = map[int32]string{ - 0: "IpAddrTypeIPv4", - 1: "IpAddrTypeIPv6", -} - -// ValidEnum validates a proposed value for this enum. Implements -// the Enum interface for IpAddrType -func (e IpAddrType) ValidEnum(v int32) bool { - _, ok := ipAddrTypeMap[v] - return ok -} - -// String returns the name of `e` -func (e IpAddrType) String() string { - name, _ := ipAddrTypeMap[int32(e)] - return name -} - -// EncodeTo encodes this value using the Encoder. -func (e IpAddrType) EncodeTo(enc *xdr.Encoder) error { - if _, ok := ipAddrTypeMap[int32(e)]; !ok { - return fmt.Errorf("'%d' is not a valid IpAddrType enum value", e) - } - _, err := enc.EncodeInt(int32(e)) - return err -} - -var _ decoderFrom = (*IpAddrType)(nil) - -// DecodeFrom decodes this value using the Decoder. -func (e *IpAddrType) DecodeFrom(d *xdr.Decoder) (int, error) { - v, n, err := d.DecodeInt() - if err != nil { - return n, fmt.Errorf("decoding IpAddrType: %s", err) - } - if _, ok := ipAddrTypeMap[v]; !ok { - return n, fmt.Errorf("'%d' is not a valid IpAddrType enum value", v) - } - *e = IpAddrType(v) - return n, nil -} - -// MarshalBinary implements encoding.BinaryMarshaler. -func (s IpAddrType) MarshalBinary() ([]byte, error) { - b := bytes.Buffer{} - e := xdr.NewEncoder(&b) - err := s.EncodeTo(e) - return b.Bytes(), err -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *IpAddrType) UnmarshalBinary(inp []byte) error { - r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) - return err -} - -var ( - _ encoding.BinaryMarshaler = (*IpAddrType)(nil) - _ encoding.BinaryUnmarshaler = (*IpAddrType)(nil) -) - -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s IpAddrType) xdrType() {} - -var _ xdrType = (*IpAddrType)(nil) - -// PeerAddressIp is an XDR NestedUnion defines as: -// -// union switch (IPAddrType type) -// { -// case IPv4: -// opaque ipv4[4]; -// case IPv6: -// opaque ipv6[16]; -// } -type PeerAddressIp struct { - Type IpAddrType - Ipv4 *[4]byte `xdrmaxsize:"4"` - Ipv6 *[16]byte `xdrmaxsize:"16"` +type LedgerCloseMeta struct { + V int32 + V0 *LedgerCloseMetaV0 + V1 *LedgerCloseMetaV1 } // SwitchFieldName returns the field name in which this union's // discriminant is stored -func (u PeerAddressIp) SwitchFieldName() string { - return "Type" +func (u LedgerCloseMeta) SwitchFieldName() string { + return "V" } // ArmForSwitch returns which field name should be used for storing -// the value for an instance of PeerAddressIp -func (u PeerAddressIp) ArmForSwitch(sw int32) (string, bool) { - switch IpAddrType(sw) { - case IpAddrTypeIPv4: - return "Ipv4", true - case IpAddrTypeIPv6: - return "Ipv6", true +// the value for an instance of LedgerCloseMeta +func (u LedgerCloseMeta) ArmForSwitch(sw int32) (string, bool) { + switch int32(sw) { + case 0: + return "V0", true + case 1: + return "V1", true } return "-", false } -// NewPeerAddressIp creates a new PeerAddressIp. -func NewPeerAddressIp(aType IpAddrType, value interface{}) (result PeerAddressIp, err error) { - result.Type = aType - switch IpAddrType(aType) { - case IpAddrTypeIPv4: - tv, ok := value.([4]byte) +// NewLedgerCloseMeta creates a new LedgerCloseMeta. +func NewLedgerCloseMeta(v int32, value interface{}) (result LedgerCloseMeta, err error) { + result.V = v + switch int32(v) { + case 0: + tv, ok := value.(LedgerCloseMetaV0) if !ok { - err = fmt.Errorf("invalid value, must be [4]byte") + err = errors.New("invalid value, must be LedgerCloseMetaV0") return } - result.Ipv4 = &tv - case IpAddrTypeIPv6: - tv, ok := value.([16]byte) + result.V0 = &tv + case 1: + tv, ok := value.(LedgerCloseMetaV1) if !ok { - err = fmt.Errorf("invalid value, must be [16]byte") + err = errors.New("invalid value, must be LedgerCloseMetaV1") return } - result.Ipv6 = &tv + result.V1 = &tv } return } -// MustIpv4 retrieves the Ipv4 value from the union, +// MustV0 retrieves the V0 value from the union, // panicing if the value is not set. -func (u PeerAddressIp) MustIpv4() [4]byte { - val, ok := u.GetIpv4() +func (u LedgerCloseMeta) MustV0() LedgerCloseMetaV0 { + val, ok := u.GetV0() if !ok { - panic("arm Ipv4 is not set") + panic("arm V0 is not set") } return val } -// GetIpv4 retrieves the Ipv4 value from the union, +// GetV0 retrieves the V0 value from the union, // returning ok if the union's switch indicated the value is valid. -func (u PeerAddressIp) GetIpv4() (result [4]byte, ok bool) { - armName, _ := u.ArmForSwitch(int32(u.Type)) +func (u LedgerCloseMeta) GetV0() (result LedgerCloseMetaV0, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.V)) - if armName == "Ipv4" { - result = *u.Ipv4 + if armName == "V0" { + result = *u.V0 ok = true } return } -// MustIpv6 retrieves the Ipv6 value from the union, +// MustV1 retrieves the V1 value from the union, // panicing if the value is not set. -func (u PeerAddressIp) MustIpv6() [16]byte { - val, ok := u.GetIpv6() +func (u LedgerCloseMeta) MustV1() LedgerCloseMetaV1 { + val, ok := u.GetV1() if !ok { - panic("arm Ipv6 is not set") + panic("arm V1 is not set") } return val } -// GetIpv6 retrieves the Ipv6 value from the union, +// GetV1 retrieves the V1 value from the union, // returning ok if the union's switch indicated the value is valid. -func (u PeerAddressIp) GetIpv6() (result [16]byte, ok bool) { - armName, _ := u.ArmForSwitch(int32(u.Type)) +func (u LedgerCloseMeta) GetV1() (result LedgerCloseMetaV1, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.V)) - if armName == "Ipv6" { - result = *u.Ipv6 + if armName == "V1" { + result = *u.V1 ok = true } @@ -15579,60 +17733,64 @@ func (u PeerAddressIp) GetIpv6() (result [16]byte, ok bool) { } // EncodeTo encodes this value using the Encoder. -func (u PeerAddressIp) EncodeTo(e *xdr.Encoder) error { +func (u LedgerCloseMeta) EncodeTo(e *xdr.Encoder) error { var err error - if err = u.Type.EncodeTo(e); err != nil { + if _, err = e.EncodeInt(int32(u.V)); err != nil { return err } - switch IpAddrType(u.Type) { - case IpAddrTypeIPv4: - if _, err = e.EncodeFixedOpaque((*u.Ipv4)[:]); err != nil { + switch int32(u.V) { + case 0: + if err = (*u.V0).EncodeTo(e); err != nil { return err } return nil - case IpAddrTypeIPv6: - if _, err = e.EncodeFixedOpaque((*u.Ipv6)[:]); err != nil { + case 1: + if err = (*u.V1).EncodeTo(e); err != nil { return err } return nil } - return fmt.Errorf("Type (IpAddrType) switch value '%d' is not valid for union PeerAddressIp", u.Type) + return fmt.Errorf("V (int32) switch value '%d' is not valid for union LedgerCloseMeta", u.V) } -var _ decoderFrom = (*PeerAddressIp)(nil) +var _ decoderFrom = (*LedgerCloseMeta)(nil) // DecodeFrom decodes this value using the Decoder. -func (u *PeerAddressIp) DecodeFrom(d *xdr.Decoder) (int, error) { +func (u *LedgerCloseMeta) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding LedgerCloseMeta: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = u.Type.DecodeFrom(d) + u.V, nTmp, err = d.DecodeInt() n += nTmp if err != nil { - return n, fmt.Errorf("decoding IpAddrType: %s", err) + return n, fmt.Errorf("decoding Int: %w", err) } - switch IpAddrType(u.Type) { - case IpAddrTypeIPv4: - u.Ipv4 = new([4]byte) - nTmp, err = d.DecodeFixedOpaqueInplace((*u.Ipv4)[:]) + switch int32(u.V) { + case 0: + u.V0 = new(LedgerCloseMetaV0) + nTmp, err = (*u.V0).DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Ipv4: %s", err) + return n, fmt.Errorf("decoding LedgerCloseMetaV0: %w", err) } return n, nil - case IpAddrTypeIPv6: - u.Ipv6 = new([16]byte) - nTmp, err = d.DecodeFixedOpaqueInplace((*u.Ipv6)[:]) + case 1: + u.V1 = new(LedgerCloseMetaV1) + nTmp, err = (*u.V1).DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Ipv6: %s", err) + return n, fmt.Errorf("decoding LedgerCloseMetaV1: %w", err) } return n, nil } - return n, fmt.Errorf("union PeerAddressIp has invalid Type (IpAddrType) switch value '%d'", u.Type) + return n, fmt.Errorf("union LedgerCloseMeta has invalid V (int32) switch value '%d'", u.V) } // MarshalBinary implements encoding.BinaryMarshaler. -func (s PeerAddressIp) MarshalBinary() ([]byte, error) { +func (s LedgerCloseMeta) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -15640,223 +17798,96 @@ func (s PeerAddressIp) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *PeerAddressIp) UnmarshalBinary(inp []byte) error { +func (s *LedgerCloseMeta) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*PeerAddressIp)(nil) - _ encoding.BinaryUnmarshaler = (*PeerAddressIp)(nil) + _ encoding.BinaryMarshaler = (*LedgerCloseMeta)(nil) + _ encoding.BinaryUnmarshaler = (*LedgerCloseMeta)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s PeerAddressIp) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s LedgerCloseMeta) xdrType() {} -var _ xdrType = (*PeerAddressIp)(nil) +var _ xdrType = (*LedgerCloseMeta)(nil) -// PeerAddress is an XDR Struct defines as: +// ErrorCode is an XDR Enum defines as: // -// struct PeerAddress +// enum ErrorCode // { -// union switch (IPAddrType type) -// { -// case IPv4: -// opaque ipv4[4]; -// case IPv6: -// opaque ipv6[16]; -// } -// ip; -// uint32 port; -// uint32 numFailures; +// ERR_MISC = 0, // Unspecific error +// ERR_DATA = 1, // Malformed data +// ERR_CONF = 2, // Misconfiguration error +// ERR_AUTH = 3, // Authentication failure +// ERR_LOAD = 4 // System overloaded // }; -type PeerAddress struct { - Ip PeerAddressIp - Port Uint32 - NumFailures Uint32 +type ErrorCode int32 + +const ( + ErrorCodeErrMisc ErrorCode = 0 + ErrorCodeErrData ErrorCode = 1 + ErrorCodeErrConf ErrorCode = 2 + ErrorCodeErrAuth ErrorCode = 3 + ErrorCodeErrLoad ErrorCode = 4 +) + +var errorCodeMap = map[int32]string{ + 0: "ErrorCodeErrMisc", + 1: "ErrorCodeErrData", + 2: "ErrorCodeErrConf", + 3: "ErrorCodeErrAuth", + 4: "ErrorCodeErrLoad", } -// EncodeTo encodes this value using the Encoder. -func (s *PeerAddress) EncodeTo(e *xdr.Encoder) error { - var err error - if err = s.Ip.EncodeTo(e); err != nil { - return err - } - if err = s.Port.EncodeTo(e); err != nil { - return err - } - if err = s.NumFailures.EncodeTo(e); err != nil { - return err - } - return nil +// ValidEnum validates a proposed value for this enum. Implements +// the Enum interface for ErrorCode +func (e ErrorCode) ValidEnum(v int32) bool { + _, ok := errorCodeMap[v] + return ok } -var _ decoderFrom = (*PeerAddress)(nil) - -// DecodeFrom decodes this value using the Decoder. -func (s *PeerAddress) DecodeFrom(d *xdr.Decoder) (int, error) { - var err error - var n, nTmp int - nTmp, err = s.Ip.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding PeerAddressIp: %s", err) - } - nTmp, err = s.Port.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Uint32: %s", err) - } - nTmp, err = s.NumFailures.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Uint32: %s", err) - } - return n, nil -} - -// MarshalBinary implements encoding.BinaryMarshaler. -func (s PeerAddress) MarshalBinary() ([]byte, error) { - b := bytes.Buffer{} - e := xdr.NewEncoder(&b) - err := s.EncodeTo(e) - return b.Bytes(), err -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *PeerAddress) UnmarshalBinary(inp []byte) error { - r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) - return err -} - -var ( - _ encoding.BinaryMarshaler = (*PeerAddress)(nil) - _ encoding.BinaryUnmarshaler = (*PeerAddress)(nil) -) - -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s PeerAddress) xdrType() {} - -var _ xdrType = (*PeerAddress)(nil) - -// MessageType is an XDR Enum defines as: -// -// enum MessageType -// { -// ERROR_MSG = 0, -// AUTH = 2, -// DONT_HAVE = 3, -// -// GET_PEERS = 4, // gets a list of peers this guy knows about -// PEERS = 5, -// -// GET_TX_SET = 6, // gets a particular txset by hash -// TX_SET = 7, -// GENERALIZED_TX_SET = 17, -// -// TRANSACTION = 8, // pass on a tx you have heard about -// -// // SCP -// GET_SCP_QUORUMSET = 9, -// SCP_QUORUMSET = 10, -// SCP_MESSAGE = 11, -// GET_SCP_STATE = 12, -// -// // new messages -// HELLO = 13, -// -// SURVEY_REQUEST = 14, -// SURVEY_RESPONSE = 15, -// -// SEND_MORE = 16 -// }; -type MessageType int32 - -const ( - MessageTypeErrorMsg MessageType = 0 - MessageTypeAuth MessageType = 2 - MessageTypeDontHave MessageType = 3 - MessageTypeGetPeers MessageType = 4 - MessageTypePeers MessageType = 5 - MessageTypeGetTxSet MessageType = 6 - MessageTypeTxSet MessageType = 7 - MessageTypeGeneralizedTxSet MessageType = 17 - MessageTypeTransaction MessageType = 8 - MessageTypeGetScpQuorumset MessageType = 9 - MessageTypeScpQuorumset MessageType = 10 - MessageTypeScpMessage MessageType = 11 - MessageTypeGetScpState MessageType = 12 - MessageTypeHello MessageType = 13 - MessageTypeSurveyRequest MessageType = 14 - MessageTypeSurveyResponse MessageType = 15 - MessageTypeSendMore MessageType = 16 -) - -var messageTypeMap = map[int32]string{ - 0: "MessageTypeErrorMsg", - 2: "MessageTypeAuth", - 3: "MessageTypeDontHave", - 4: "MessageTypeGetPeers", - 5: "MessageTypePeers", - 6: "MessageTypeGetTxSet", - 7: "MessageTypeTxSet", - 17: "MessageTypeGeneralizedTxSet", - 8: "MessageTypeTransaction", - 9: "MessageTypeGetScpQuorumset", - 10: "MessageTypeScpQuorumset", - 11: "MessageTypeScpMessage", - 12: "MessageTypeGetScpState", - 13: "MessageTypeHello", - 14: "MessageTypeSurveyRequest", - 15: "MessageTypeSurveyResponse", - 16: "MessageTypeSendMore", -} - -// ValidEnum validates a proposed value for this enum. Implements -// the Enum interface for MessageType -func (e MessageType) ValidEnum(v int32) bool { - _, ok := messageTypeMap[v] - return ok -} - -// String returns the name of `e` -func (e MessageType) String() string { - name, _ := messageTypeMap[int32(e)] - return name -} +// String returns the name of `e` +func (e ErrorCode) String() string { + name, _ := errorCodeMap[int32(e)] + return name +} // EncodeTo encodes this value using the Encoder. -func (e MessageType) EncodeTo(enc *xdr.Encoder) error { - if _, ok := messageTypeMap[int32(e)]; !ok { - return fmt.Errorf("'%d' is not a valid MessageType enum value", e) +func (e ErrorCode) EncodeTo(enc *xdr.Encoder) error { + if _, ok := errorCodeMap[int32(e)]; !ok { + return fmt.Errorf("'%d' is not a valid ErrorCode enum value", e) } _, err := enc.EncodeInt(int32(e)) return err } -var _ decoderFrom = (*MessageType)(nil) +var _ decoderFrom = (*ErrorCode)(nil) // DecodeFrom decodes this value using the Decoder. -func (e *MessageType) DecodeFrom(d *xdr.Decoder) (int, error) { +func (e *ErrorCode) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding ErrorCode: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 v, n, err := d.DecodeInt() if err != nil { - return n, fmt.Errorf("decoding MessageType: %s", err) + return n, fmt.Errorf("decoding ErrorCode: %w", err) } - if _, ok := messageTypeMap[v]; !ok { - return n, fmt.Errorf("'%d' is not a valid MessageType enum value", v) + if _, ok := errorCodeMap[v]; !ok { + return n, fmt.Errorf("'%d' is not a valid ErrorCode enum value", v) } - *e = MessageType(v) + *e = ErrorCode(v) return n, nil } // MarshalBinary implements encoding.BinaryMarshaler. -func (s MessageType) MarshalBinary() ([]byte, error) { +func (s ErrorCode) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -15864,69 +17895,74 @@ func (s MessageType) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *MessageType) UnmarshalBinary(inp []byte) error { +func (s *ErrorCode) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*MessageType)(nil) - _ encoding.BinaryUnmarshaler = (*MessageType)(nil) + _ encoding.BinaryMarshaler = (*ErrorCode)(nil) + _ encoding.BinaryUnmarshaler = (*ErrorCode)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s MessageType) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s ErrorCode) xdrType() {} -var _ xdrType = (*MessageType)(nil) +var _ xdrType = (*ErrorCode)(nil) -// DontHave is an XDR Struct defines as: +// Error is an XDR Struct defines as: // -// struct DontHave +// struct Error // { -// MessageType type; -// uint256 reqHash; +// ErrorCode code; +// string msg<100>; // }; -type DontHave struct { - Type MessageType - ReqHash Uint256 +type Error struct { + Code ErrorCode + Msg string `xdrmaxsize:"100"` } // EncodeTo encodes this value using the Encoder. -func (s *DontHave) EncodeTo(e *xdr.Encoder) error { +func (s *Error) EncodeTo(e *xdr.Encoder) error { var err error - if err = s.Type.EncodeTo(e); err != nil { + if err = s.Code.EncodeTo(e); err != nil { return err } - if err = s.ReqHash.EncodeTo(e); err != nil { + if _, err = e.EncodeString(string(s.Msg)); err != nil { return err } return nil } -var _ decoderFrom = (*DontHave)(nil) +var _ decoderFrom = (*Error)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *DontHave) DecodeFrom(d *xdr.Decoder) (int, error) { +func (s *Error) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding Error: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = s.Type.DecodeFrom(d) + nTmp, err = s.Code.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding MessageType: %s", err) + return n, fmt.Errorf("decoding ErrorCode: %w", err) } - nTmp, err = s.ReqHash.DecodeFrom(d) + s.Msg, nTmp, err = d.DecodeString(100) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Uint256: %s", err) + return n, fmt.Errorf("decoding Msg: %w", err) } return n, nil } // MarshalBinary implements encoding.BinaryMarshaler. -func (s DontHave) MarshalBinary() ([]byte, error) { +func (s Error) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -15934,79 +17970,64 @@ func (s DontHave) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *DontHave) UnmarshalBinary(inp []byte) error { +func (s *Error) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*DontHave)(nil) - _ encoding.BinaryUnmarshaler = (*DontHave)(nil) + _ encoding.BinaryMarshaler = (*Error)(nil) + _ encoding.BinaryUnmarshaler = (*Error)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s DontHave) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s Error) xdrType() {} -var _ xdrType = (*DontHave)(nil) +var _ xdrType = (*Error)(nil) -// SurveyMessageCommandType is an XDR Enum defines as: +// SendMore is an XDR Struct defines as: // -// enum SurveyMessageCommandType +// struct SendMore // { -// SURVEY_TOPOLOGY = 0 +// uint32 numMessages; // }; -type SurveyMessageCommandType int32 - -const ( - SurveyMessageCommandTypeSurveyTopology SurveyMessageCommandType = 0 -) - -var surveyMessageCommandTypeMap = map[int32]string{ - 0: "SurveyMessageCommandTypeSurveyTopology", -} - -// ValidEnum validates a proposed value for this enum. Implements -// the Enum interface for SurveyMessageCommandType -func (e SurveyMessageCommandType) ValidEnum(v int32) bool { - _, ok := surveyMessageCommandTypeMap[v] - return ok -} - -// String returns the name of `e` -func (e SurveyMessageCommandType) String() string { - name, _ := surveyMessageCommandTypeMap[int32(e)] - return name +type SendMore struct { + NumMessages Uint32 } // EncodeTo encodes this value using the Encoder. -func (e SurveyMessageCommandType) EncodeTo(enc *xdr.Encoder) error { - if _, ok := surveyMessageCommandTypeMap[int32(e)]; !ok { - return fmt.Errorf("'%d' is not a valid SurveyMessageCommandType enum value", e) +func (s *SendMore) EncodeTo(e *xdr.Encoder) error { + var err error + if err = s.NumMessages.EncodeTo(e); err != nil { + return err } - _, err := enc.EncodeInt(int32(e)) - return err + return nil } -var _ decoderFrom = (*SurveyMessageCommandType)(nil) +var _ decoderFrom = (*SendMore)(nil) // DecodeFrom decodes this value using the Decoder. -func (e *SurveyMessageCommandType) DecodeFrom(d *xdr.Decoder) (int, error) { - v, n, err := d.DecodeInt() - if err != nil { - return n, fmt.Errorf("decoding SurveyMessageCommandType: %s", err) +func (s *SendMore) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding SendMore: %w", ErrMaxDecodingDepthReached) } - if _, ok := surveyMessageCommandTypeMap[v]; !ok { - return n, fmt.Errorf("'%d' is not a valid SurveyMessageCommandType enum value", v) + maxDepth -= 1 + var err error + var n, nTmp int + nTmp, err = s.NumMessages.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Uint32: %w", err) } - *e = SurveyMessageCommandType(v) return n, nil } // MarshalBinary implements encoding.BinaryMarshaler. -func (s SurveyMessageCommandType) MarshalBinary() ([]byte, error) { +func (s SendMore) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -16014,99 +18035,74 @@ func (s SurveyMessageCommandType) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *SurveyMessageCommandType) UnmarshalBinary(inp []byte) error { +func (s *SendMore) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*SurveyMessageCommandType)(nil) - _ encoding.BinaryUnmarshaler = (*SurveyMessageCommandType)(nil) + _ encoding.BinaryMarshaler = (*SendMore)(nil) + _ encoding.BinaryUnmarshaler = (*SendMore)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s SurveyMessageCommandType) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s SendMore) xdrType() {} -var _ xdrType = (*SurveyMessageCommandType)(nil) +var _ xdrType = (*SendMore)(nil) -// SurveyRequestMessage is an XDR Struct defines as: +// SendMoreExtended is an XDR Struct defines as: // -// struct SurveyRequestMessage +// struct SendMoreExtended // { -// NodeID surveyorPeerID; -// NodeID surveyedPeerID; -// uint32 ledgerNum; -// Curve25519Public encryptionKey; -// SurveyMessageCommandType commandType; +// uint32 numMessages; +// uint32 numBytes; // }; -type SurveyRequestMessage struct { - SurveyorPeerId NodeId - SurveyedPeerId NodeId - LedgerNum Uint32 - EncryptionKey Curve25519Public - CommandType SurveyMessageCommandType +type SendMoreExtended struct { + NumMessages Uint32 + NumBytes Uint32 } // EncodeTo encodes this value using the Encoder. -func (s *SurveyRequestMessage) EncodeTo(e *xdr.Encoder) error { +func (s *SendMoreExtended) EncodeTo(e *xdr.Encoder) error { var err error - if err = s.SurveyorPeerId.EncodeTo(e); err != nil { - return err - } - if err = s.SurveyedPeerId.EncodeTo(e); err != nil { - return err - } - if err = s.LedgerNum.EncodeTo(e); err != nil { - return err - } - if err = s.EncryptionKey.EncodeTo(e); err != nil { + if err = s.NumMessages.EncodeTo(e); err != nil { return err } - if err = s.CommandType.EncodeTo(e); err != nil { + if err = s.NumBytes.EncodeTo(e); err != nil { return err } return nil } -var _ decoderFrom = (*SurveyRequestMessage)(nil) +var _ decoderFrom = (*SendMoreExtended)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *SurveyRequestMessage) DecodeFrom(d *xdr.Decoder) (int, error) { +func (s *SendMoreExtended) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding SendMoreExtended: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = s.SurveyorPeerId.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding NodeId: %s", err) - } - nTmp, err = s.SurveyedPeerId.DecodeFrom(d) + nTmp, err = s.NumMessages.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding NodeId: %s", err) + return n, fmt.Errorf("decoding Uint32: %w", err) } - nTmp, err = s.LedgerNum.DecodeFrom(d) + nTmp, err = s.NumBytes.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Uint32: %s", err) - } - nTmp, err = s.EncryptionKey.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Curve25519Public: %s", err) - } - nTmp, err = s.CommandType.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding SurveyMessageCommandType: %s", err) + return n, fmt.Errorf("decoding Uint32: %w", err) } return n, nil } // MarshalBinary implements encoding.BinaryMarshaler. -func (s SurveyRequestMessage) MarshalBinary() ([]byte, error) { +func (s SendMoreExtended) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -16114,129 +18110,84 @@ func (s SurveyRequestMessage) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *SurveyRequestMessage) UnmarshalBinary(inp []byte) error { +func (s *SendMoreExtended) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*SurveyRequestMessage)(nil) - _ encoding.BinaryUnmarshaler = (*SurveyRequestMessage)(nil) + _ encoding.BinaryMarshaler = (*SendMoreExtended)(nil) + _ encoding.BinaryUnmarshaler = (*SendMoreExtended)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s SurveyRequestMessage) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s SendMoreExtended) xdrType() {} -var _ xdrType = (*SurveyRequestMessage)(nil) +var _ xdrType = (*SendMoreExtended)(nil) -// SignedSurveyRequestMessage is an XDR Struct defines as: +// AuthCert is an XDR Struct defines as: // -// struct SignedSurveyRequestMessage +// struct AuthCert // { -// Signature requestSignature; -// SurveyRequestMessage request; +// Curve25519Public pubkey; +// uint64 expiration; +// Signature sig; // }; -type SignedSurveyRequestMessage struct { - RequestSignature Signature - Request SurveyRequestMessage +type AuthCert struct { + Pubkey Curve25519Public + Expiration Uint64 + Sig Signature } // EncodeTo encodes this value using the Encoder. -func (s *SignedSurveyRequestMessage) EncodeTo(e *xdr.Encoder) error { +func (s *AuthCert) EncodeTo(e *xdr.Encoder) error { var err error - if err = s.RequestSignature.EncodeTo(e); err != nil { + if err = s.Pubkey.EncodeTo(e); err != nil { return err } - if err = s.Request.EncodeTo(e); err != nil { + if err = s.Expiration.EncodeTo(e); err != nil { + return err + } + if err = s.Sig.EncodeTo(e); err != nil { return err } return nil } -var _ decoderFrom = (*SignedSurveyRequestMessage)(nil) +var _ decoderFrom = (*AuthCert)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *SignedSurveyRequestMessage) DecodeFrom(d *xdr.Decoder) (int, error) { +func (s *AuthCert) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding AuthCert: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = s.RequestSignature.DecodeFrom(d) + nTmp, err = s.Pubkey.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Signature: %s", err) + return n, fmt.Errorf("decoding Curve25519Public: %w", err) } - nTmp, err = s.Request.DecodeFrom(d) + nTmp, err = s.Expiration.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding SurveyRequestMessage: %s", err) + return n, fmt.Errorf("decoding Uint64: %w", err) } - return n, nil -} - -// MarshalBinary implements encoding.BinaryMarshaler. -func (s SignedSurveyRequestMessage) MarshalBinary() ([]byte, error) { - b := bytes.Buffer{} - e := xdr.NewEncoder(&b) - err := s.EncodeTo(e) - return b.Bytes(), err -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *SignedSurveyRequestMessage) UnmarshalBinary(inp []byte) error { - r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) - return err -} - -var ( - _ encoding.BinaryMarshaler = (*SignedSurveyRequestMessage)(nil) - _ encoding.BinaryUnmarshaler = (*SignedSurveyRequestMessage)(nil) -) - -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s SignedSurveyRequestMessage) xdrType() {} - -var _ xdrType = (*SignedSurveyRequestMessage)(nil) - -// EncryptedBody is an XDR Typedef defines as: -// -// typedef opaque EncryptedBody<64000>; -type EncryptedBody []byte - -// XDRMaxSize implements the Sized interface for EncryptedBody -func (e EncryptedBody) XDRMaxSize() int { - return 64000 -} - -// EncodeTo encodes this value using the Encoder. -func (s EncryptedBody) EncodeTo(e *xdr.Encoder) error { - var err error - if _, err = e.EncodeOpaque(s[:]); err != nil { - return err - } - return nil -} - -var _ decoderFrom = (*EncryptedBody)(nil) - -// DecodeFrom decodes this value using the Decoder. -func (s *EncryptedBody) DecodeFrom(d *xdr.Decoder) (int, error) { - var err error - var n, nTmp int - (*s), nTmp, err = d.DecodeOpaque(64000) + nTmp, err = s.Sig.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding EncryptedBody: %s", err) + return n, fmt.Errorf("decoding Signature: %w", err) } return n, nil } // MarshalBinary implements encoding.BinaryMarshaler. -func (s EncryptedBody) MarshalBinary() ([]byte, error) { +func (s AuthCert) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -16244,99 +18195,144 @@ func (s EncryptedBody) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *EncryptedBody) UnmarshalBinary(inp []byte) error { +func (s *AuthCert) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*EncryptedBody)(nil) - _ encoding.BinaryUnmarshaler = (*EncryptedBody)(nil) + _ encoding.BinaryMarshaler = (*AuthCert)(nil) + _ encoding.BinaryUnmarshaler = (*AuthCert)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s EncryptedBody) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s AuthCert) xdrType() {} -var _ xdrType = (*EncryptedBody)(nil) +var _ xdrType = (*AuthCert)(nil) -// SurveyResponseMessage is an XDR Struct defines as: +// Hello is an XDR Struct defines as: // -// struct SurveyResponseMessage +// struct Hello // { -// NodeID surveyorPeerID; -// NodeID surveyedPeerID; -// uint32 ledgerNum; -// SurveyMessageCommandType commandType; -// EncryptedBody encryptedBody; +// uint32 ledgerVersion; +// uint32 overlayVersion; +// uint32 overlayMinVersion; +// Hash networkID; +// string versionStr<100>; +// int listeningPort; +// NodeID peerID; +// AuthCert cert; +// uint256 nonce; // }; -type SurveyResponseMessage struct { - SurveyorPeerId NodeId - SurveyedPeerId NodeId - LedgerNum Uint32 - CommandType SurveyMessageCommandType - EncryptedBody EncryptedBody +type Hello struct { + LedgerVersion Uint32 + OverlayVersion Uint32 + OverlayMinVersion Uint32 + NetworkId Hash + VersionStr string `xdrmaxsize:"100"` + ListeningPort int32 + PeerId NodeId + Cert AuthCert + Nonce Uint256 } // EncodeTo encodes this value using the Encoder. -func (s *SurveyResponseMessage) EncodeTo(e *xdr.Encoder) error { +func (s *Hello) EncodeTo(e *xdr.Encoder) error { var err error - if err = s.SurveyorPeerId.EncodeTo(e); err != nil { + if err = s.LedgerVersion.EncodeTo(e); err != nil { return err } - if err = s.SurveyedPeerId.EncodeTo(e); err != nil { + if err = s.OverlayVersion.EncodeTo(e); err != nil { return err } - if err = s.LedgerNum.EncodeTo(e); err != nil { + if err = s.OverlayMinVersion.EncodeTo(e); err != nil { return err } - if err = s.CommandType.EncodeTo(e); err != nil { + if err = s.NetworkId.EncodeTo(e); err != nil { return err } - if err = s.EncryptedBody.EncodeTo(e); err != nil { + if _, err = e.EncodeString(string(s.VersionStr)); err != nil { + return err + } + if _, err = e.EncodeInt(int32(s.ListeningPort)); err != nil { + return err + } + if err = s.PeerId.EncodeTo(e); err != nil { + return err + } + if err = s.Cert.EncodeTo(e); err != nil { + return err + } + if err = s.Nonce.EncodeTo(e); err != nil { return err } return nil } -var _ decoderFrom = (*SurveyResponseMessage)(nil) +var _ decoderFrom = (*Hello)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *SurveyResponseMessage) DecodeFrom(d *xdr.Decoder) (int, error) { +func (s *Hello) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding Hello: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = s.SurveyorPeerId.DecodeFrom(d) + nTmp, err = s.LedgerVersion.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Uint32: %w", err) + } + nTmp, err = s.OverlayVersion.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Uint32: %w", err) + } + nTmp, err = s.OverlayMinVersion.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Uint32: %w", err) + } + nTmp, err = s.NetworkId.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Hash: %w", err) + } + s.VersionStr, nTmp, err = d.DecodeString(100) n += nTmp if err != nil { - return n, fmt.Errorf("decoding NodeId: %s", err) + return n, fmt.Errorf("decoding VersionStr: %w", err) } - nTmp, err = s.SurveyedPeerId.DecodeFrom(d) + s.ListeningPort, nTmp, err = d.DecodeInt() n += nTmp if err != nil { - return n, fmt.Errorf("decoding NodeId: %s", err) + return n, fmt.Errorf("decoding Int: %w", err) } - nTmp, err = s.LedgerNum.DecodeFrom(d) + nTmp, err = s.PeerId.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Uint32: %s", err) + return n, fmt.Errorf("decoding NodeId: %w", err) } - nTmp, err = s.CommandType.DecodeFrom(d) + nTmp, err = s.Cert.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding SurveyMessageCommandType: %s", err) + return n, fmt.Errorf("decoding AuthCert: %w", err) } - nTmp, err = s.EncryptedBody.DecodeFrom(d) + nTmp, err = s.Nonce.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding EncryptedBody: %s", err) + return n, fmt.Errorf("decoding Uint256: %w", err) } return n, nil } // MarshalBinary implements encoding.BinaryMarshaler. -func (s SurveyResponseMessage) MarshalBinary() ([]byte, error) { +func (s Hello) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -16344,69 +18340,69 @@ func (s SurveyResponseMessage) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *SurveyResponseMessage) UnmarshalBinary(inp []byte) error { +func (s *Hello) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*SurveyResponseMessage)(nil) - _ encoding.BinaryUnmarshaler = (*SurveyResponseMessage)(nil) + _ encoding.BinaryMarshaler = (*Hello)(nil) + _ encoding.BinaryUnmarshaler = (*Hello)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s SurveyResponseMessage) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s Hello) xdrType() {} -var _ xdrType = (*SurveyResponseMessage)(nil) +var _ xdrType = (*Hello)(nil) -// SignedSurveyResponseMessage is an XDR Struct defines as: +// AuthMsgFlagFlowControlBytesRequested is an XDR Const defines as: // -// struct SignedSurveyResponseMessage +// const AUTH_MSG_FLAG_FLOW_CONTROL_BYTES_REQUESTED = 200; +const AuthMsgFlagFlowControlBytesRequested = 200 + +// Auth is an XDR Struct defines as: +// +// struct Auth // { -// Signature responseSignature; -// SurveyResponseMessage response; +// int flags; // }; -type SignedSurveyResponseMessage struct { - ResponseSignature Signature - Response SurveyResponseMessage +type Auth struct { + Flags int32 } // EncodeTo encodes this value using the Encoder. -func (s *SignedSurveyResponseMessage) EncodeTo(e *xdr.Encoder) error { +func (s *Auth) EncodeTo(e *xdr.Encoder) error { var err error - if err = s.ResponseSignature.EncodeTo(e); err != nil { - return err - } - if err = s.Response.EncodeTo(e); err != nil { + if _, err = e.EncodeInt(int32(s.Flags)); err != nil { return err } return nil } -var _ decoderFrom = (*SignedSurveyResponseMessage)(nil) +var _ decoderFrom = (*Auth)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *SignedSurveyResponseMessage) DecodeFrom(d *xdr.Decoder) (int, error) { +func (s *Auth) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding Auth: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = s.ResponseSignature.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Signature: %s", err) - } - nTmp, err = s.Response.DecodeFrom(d) + s.Flags, nTmp, err = d.DecodeInt() n += nTmp if err != nil { - return n, fmt.Errorf("decoding SurveyResponseMessage: %s", err) + return n, fmt.Errorf("decoding Int: %w", err) } return n, nil } // MarshalBinary implements encoding.BinaryMarshaler. -func (s SignedSurveyResponseMessage) MarshalBinary() ([]byte, error) { +func (s Auth) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -16414,201 +18410,87 @@ func (s SignedSurveyResponseMessage) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *SignedSurveyResponseMessage) UnmarshalBinary(inp []byte) error { +func (s *Auth) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*SignedSurveyResponseMessage)(nil) - _ encoding.BinaryUnmarshaler = (*SignedSurveyResponseMessage)(nil) + _ encoding.BinaryMarshaler = (*Auth)(nil) + _ encoding.BinaryUnmarshaler = (*Auth)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s SignedSurveyResponseMessage) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s Auth) xdrType() {} -var _ xdrType = (*SignedSurveyResponseMessage)(nil) +var _ xdrType = (*Auth)(nil) -// PeerStats is an XDR Struct defines as: +// IpAddrType is an XDR Enum defines as: // -// struct PeerStats +// enum IPAddrType // { -// NodeID id; -// string versionStr<100>; -// uint64 messagesRead; -// uint64 messagesWritten; -// uint64 bytesRead; -// uint64 bytesWritten; -// uint64 secondsConnected; -// -// uint64 uniqueFloodBytesRecv; -// uint64 duplicateFloodBytesRecv; -// uint64 uniqueFetchBytesRecv; -// uint64 duplicateFetchBytesRecv; -// -// uint64 uniqueFloodMessageRecv; -// uint64 duplicateFloodMessageRecv; -// uint64 uniqueFetchMessageRecv; -// uint64 duplicateFetchMessageRecv; +// IPv4 = 0, +// IPv6 = 1 // }; -type PeerStats struct { - Id NodeId - VersionStr string `xdrmaxsize:"100"` - MessagesRead Uint64 - MessagesWritten Uint64 - BytesRead Uint64 - BytesWritten Uint64 - SecondsConnected Uint64 - UniqueFloodBytesRecv Uint64 - DuplicateFloodBytesRecv Uint64 - UniqueFetchBytesRecv Uint64 - DuplicateFetchBytesRecv Uint64 - UniqueFloodMessageRecv Uint64 - DuplicateFloodMessageRecv Uint64 - UniqueFetchMessageRecv Uint64 - DuplicateFetchMessageRecv Uint64 +type IpAddrType int32 + +const ( + IpAddrTypeIPv4 IpAddrType = 0 + IpAddrTypeIPv6 IpAddrType = 1 +) + +var ipAddrTypeMap = map[int32]string{ + 0: "IpAddrTypeIPv4", + 1: "IpAddrTypeIPv6", +} + +// ValidEnum validates a proposed value for this enum. Implements +// the Enum interface for IpAddrType +func (e IpAddrType) ValidEnum(v int32) bool { + _, ok := ipAddrTypeMap[v] + return ok +} + +// String returns the name of `e` +func (e IpAddrType) String() string { + name, _ := ipAddrTypeMap[int32(e)] + return name } // EncodeTo encodes this value using the Encoder. -func (s *PeerStats) EncodeTo(e *xdr.Encoder) error { - var err error - if err = s.Id.EncodeTo(e); err != nil { - return err - } - if _, err = e.EncodeString(string(s.VersionStr)); err != nil { - return err - } - if err = s.MessagesRead.EncodeTo(e); err != nil { - return err - } - if err = s.MessagesWritten.EncodeTo(e); err != nil { - return err - } - if err = s.BytesRead.EncodeTo(e); err != nil { - return err - } - if err = s.BytesWritten.EncodeTo(e); err != nil { - return err - } - if err = s.SecondsConnected.EncodeTo(e); err != nil { - return err - } - if err = s.UniqueFloodBytesRecv.EncodeTo(e); err != nil { - return err - } - if err = s.DuplicateFloodBytesRecv.EncodeTo(e); err != nil { - return err - } - if err = s.UniqueFetchBytesRecv.EncodeTo(e); err != nil { - return err - } - if err = s.DuplicateFetchBytesRecv.EncodeTo(e); err != nil { - return err - } - if err = s.UniqueFloodMessageRecv.EncodeTo(e); err != nil { - return err - } - if err = s.DuplicateFloodMessageRecv.EncodeTo(e); err != nil { - return err - } - if err = s.UniqueFetchMessageRecv.EncodeTo(e); err != nil { - return err - } - if err = s.DuplicateFetchMessageRecv.EncodeTo(e); err != nil { - return err +func (e IpAddrType) EncodeTo(enc *xdr.Encoder) error { + if _, ok := ipAddrTypeMap[int32(e)]; !ok { + return fmt.Errorf("'%d' is not a valid IpAddrType enum value", e) } - return nil + _, err := enc.EncodeInt(int32(e)) + return err } -var _ decoderFrom = (*PeerStats)(nil) +var _ decoderFrom = (*IpAddrType)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *PeerStats) DecodeFrom(d *xdr.Decoder) (int, error) { - var err error - var n, nTmp int - nTmp, err = s.Id.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding NodeId: %s", err) - } - s.VersionStr, nTmp, err = d.DecodeString(100) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding VersionStr: %s", err) - } - nTmp, err = s.MessagesRead.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Uint64: %s", err) - } - nTmp, err = s.MessagesWritten.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Uint64: %s", err) - } - nTmp, err = s.BytesRead.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Uint64: %s", err) - } - nTmp, err = s.BytesWritten.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Uint64: %s", err) - } - nTmp, err = s.SecondsConnected.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Uint64: %s", err) - } - nTmp, err = s.UniqueFloodBytesRecv.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Uint64: %s", err) - } - nTmp, err = s.DuplicateFloodBytesRecv.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Uint64: %s", err) - } - nTmp, err = s.UniqueFetchBytesRecv.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Uint64: %s", err) - } - nTmp, err = s.DuplicateFetchBytesRecv.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Uint64: %s", err) - } - nTmp, err = s.UniqueFloodMessageRecv.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Uint64: %s", err) +func (e *IpAddrType) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding IpAddrType: %w", ErrMaxDecodingDepthReached) } - nTmp, err = s.DuplicateFloodMessageRecv.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Uint64: %s", err) - } - nTmp, err = s.UniqueFetchMessageRecv.DecodeFrom(d) - n += nTmp + maxDepth -= 1 + v, n, err := d.DecodeInt() if err != nil { - return n, fmt.Errorf("decoding Uint64: %s", err) + return n, fmt.Errorf("decoding IpAddrType: %w", err) } - nTmp, err = s.DuplicateFetchMessageRecv.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Uint64: %s", err) + if _, ok := ipAddrTypeMap[v]; !ok { + return n, fmt.Errorf("'%d' is not a valid IpAddrType enum value", v) } + *e = IpAddrType(v) return n, nil } // MarshalBinary implements encoding.BinaryMarshaler. -func (s PeerStats) MarshalBinary() ([]byte, error) { +func (s IpAddrType) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -16616,79 +18498,189 @@ func (s PeerStats) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *PeerStats) UnmarshalBinary(inp []byte) error { +func (s *IpAddrType) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*PeerStats)(nil) - _ encoding.BinaryUnmarshaler = (*PeerStats)(nil) + _ encoding.BinaryMarshaler = (*IpAddrType)(nil) + _ encoding.BinaryUnmarshaler = (*IpAddrType)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s PeerStats) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s IpAddrType) xdrType() {} -var _ xdrType = (*PeerStats)(nil) +var _ xdrType = (*IpAddrType)(nil) -// PeerStatList is an XDR Typedef defines as: +// PeerAddressIp is an XDR NestedUnion defines as: // -// typedef PeerStats PeerStatList<25>; -type PeerStatList []PeerStats +// union switch (IPAddrType type) +// { +// case IPv4: +// opaque ipv4[4]; +// case IPv6: +// opaque ipv6[16]; +// } +type PeerAddressIp struct { + Type IpAddrType + Ipv4 *[4]byte `xdrmaxsize:"4"` + Ipv6 *[16]byte `xdrmaxsize:"16"` +} -// XDRMaxSize implements the Sized interface for PeerStatList -func (e PeerStatList) XDRMaxSize() int { - return 25 +// SwitchFieldName returns the field name in which this union's +// discriminant is stored +func (u PeerAddressIp) SwitchFieldName() string { + return "Type" +} + +// ArmForSwitch returns which field name should be used for storing +// the value for an instance of PeerAddressIp +func (u PeerAddressIp) ArmForSwitch(sw int32) (string, bool) { + switch IpAddrType(sw) { + case IpAddrTypeIPv4: + return "Ipv4", true + case IpAddrTypeIPv6: + return "Ipv6", true + } + return "-", false +} + +// NewPeerAddressIp creates a new PeerAddressIp. +func NewPeerAddressIp(aType IpAddrType, value interface{}) (result PeerAddressIp, err error) { + result.Type = aType + switch IpAddrType(aType) { + case IpAddrTypeIPv4: + tv, ok := value.([4]byte) + if !ok { + err = errors.New("invalid value, must be [4]byte") + return + } + result.Ipv4 = &tv + case IpAddrTypeIPv6: + tv, ok := value.([16]byte) + if !ok { + err = errors.New("invalid value, must be [16]byte") + return + } + result.Ipv6 = &tv + } + return +} + +// MustIpv4 retrieves the Ipv4 value from the union, +// panicing if the value is not set. +func (u PeerAddressIp) MustIpv4() [4]byte { + val, ok := u.GetIpv4() + + if !ok { + panic("arm Ipv4 is not set") + } + + return val +} + +// GetIpv4 retrieves the Ipv4 value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u PeerAddressIp) GetIpv4() (result [4]byte, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) + + if armName == "Ipv4" { + result = *u.Ipv4 + ok = true + } + + return +} + +// MustIpv6 retrieves the Ipv6 value from the union, +// panicing if the value is not set. +func (u PeerAddressIp) MustIpv6() [16]byte { + val, ok := u.GetIpv6() + + if !ok { + panic("arm Ipv6 is not set") + } + + return val +} + +// GetIpv6 retrieves the Ipv6 value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u PeerAddressIp) GetIpv6() (result [16]byte, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) + + if armName == "Ipv6" { + result = *u.Ipv6 + ok = true + } + + return } // EncodeTo encodes this value using the Encoder. -func (s PeerStatList) EncodeTo(e *xdr.Encoder) error { +func (u PeerAddressIp) EncodeTo(e *xdr.Encoder) error { var err error - if _, err = e.EncodeUint(uint32(len(s))); err != nil { + if err = u.Type.EncodeTo(e); err != nil { return err } - for i := 0; i < len(s); i++ { - if err = s[i].EncodeTo(e); err != nil { + switch IpAddrType(u.Type) { + case IpAddrTypeIPv4: + if _, err = e.EncodeFixedOpaque((*u.Ipv4)[:]); err != nil { + return err + } + return nil + case IpAddrTypeIPv6: + if _, err = e.EncodeFixedOpaque((*u.Ipv6)[:]); err != nil { return err } + return nil } - return nil + return fmt.Errorf("Type (IpAddrType) switch value '%d' is not valid for union PeerAddressIp", u.Type) } -var _ decoderFrom = (*PeerStatList)(nil) +var _ decoderFrom = (*PeerAddressIp)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *PeerStatList) DecodeFrom(d *xdr.Decoder) (int, error) { +func (u *PeerAddressIp) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding PeerAddressIp: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - var l uint32 - l, nTmp, err = d.DecodeUint() + nTmp, err = u.Type.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding PeerStats: %s", err) - } - if l > 25 { - return n, fmt.Errorf("decoding PeerStats: data size (%d) exceeds size limit (25)", l) + return n, fmt.Errorf("decoding IpAddrType: %w", err) } - (*s) = nil - if l > 0 { - (*s) = make([]PeerStats, l) - for i := uint32(0); i < l; i++ { - nTmp, err = (*s)[i].DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding PeerStats: %s", err) - } + switch IpAddrType(u.Type) { + case IpAddrTypeIPv4: + u.Ipv4 = new([4]byte) + nTmp, err = d.DecodeFixedOpaqueInplace((*u.Ipv4)[:]) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Ipv4: %w", err) + } + return n, nil + case IpAddrTypeIPv6: + u.Ipv6 = new([16]byte) + nTmp, err = d.DecodeFixedOpaqueInplace((*u.Ipv6)[:]) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Ipv6: %w", err) } + return n, nil } - return n, nil + return n, fmt.Errorf("union PeerAddressIp has invalid Type (IpAddrType) switch value '%d'", u.Type) } // MarshalBinary implements encoding.BinaryMarshaler. -func (s PeerStatList) MarshalBinary() ([]byte, error) { +func (s PeerAddressIp) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -16696,90 +18688,91 @@ func (s PeerStatList) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *PeerStatList) UnmarshalBinary(inp []byte) error { +func (s *PeerAddressIp) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*PeerStatList)(nil) - _ encoding.BinaryUnmarshaler = (*PeerStatList)(nil) + _ encoding.BinaryMarshaler = (*PeerAddressIp)(nil) + _ encoding.BinaryUnmarshaler = (*PeerAddressIp)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s PeerStatList) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s PeerAddressIp) xdrType() {} -var _ xdrType = (*PeerStatList)(nil) +var _ xdrType = (*PeerAddressIp)(nil) -// TopologyResponseBody is an XDR Struct defines as: +// PeerAddress is an XDR Struct defines as: // -// struct TopologyResponseBody +// struct PeerAddress // { -// PeerStatList inboundPeers; -// PeerStatList outboundPeers; -// -// uint32 totalInboundPeerCount; -// uint32 totalOutboundPeerCount; +// union switch (IPAddrType type) +// { +// case IPv4: +// opaque ipv4[4]; +// case IPv6: +// opaque ipv6[16]; +// } +// ip; +// uint32 port; +// uint32 numFailures; // }; -type TopologyResponseBody struct { - InboundPeers PeerStatList - OutboundPeers PeerStatList - TotalInboundPeerCount Uint32 - TotalOutboundPeerCount Uint32 +type PeerAddress struct { + Ip PeerAddressIp + Port Uint32 + NumFailures Uint32 } // EncodeTo encodes this value using the Encoder. -func (s *TopologyResponseBody) EncodeTo(e *xdr.Encoder) error { +func (s *PeerAddress) EncodeTo(e *xdr.Encoder) error { var err error - if err = s.InboundPeers.EncodeTo(e); err != nil { - return err - } - if err = s.OutboundPeers.EncodeTo(e); err != nil { + if err = s.Ip.EncodeTo(e); err != nil { return err } - if err = s.TotalInboundPeerCount.EncodeTo(e); err != nil { + if err = s.Port.EncodeTo(e); err != nil { return err } - if err = s.TotalOutboundPeerCount.EncodeTo(e); err != nil { + if err = s.NumFailures.EncodeTo(e); err != nil { return err } return nil } -var _ decoderFrom = (*TopologyResponseBody)(nil) +var _ decoderFrom = (*PeerAddress)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *TopologyResponseBody) DecodeFrom(d *xdr.Decoder) (int, error) { +func (s *PeerAddress) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding PeerAddress: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = s.InboundPeers.DecodeFrom(d) + nTmp, err = s.Ip.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding PeerStatList: %s", err) + return n, fmt.Errorf("decoding PeerAddressIp: %w", err) } - nTmp, err = s.OutboundPeers.DecodeFrom(d) + nTmp, err = s.Port.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding PeerStatList: %s", err) + return n, fmt.Errorf("decoding Uint32: %w", err) } - nTmp, err = s.TotalInboundPeerCount.DecodeFrom(d) + nTmp, err = s.NumFailures.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Uint32: %s", err) - } - nTmp, err = s.TotalOutboundPeerCount.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Uint32: %s", err) + return n, fmt.Errorf("decoding Uint32: %w", err) } return n, nil } // MarshalBinary implements encoding.BinaryMarshaler. -func (s TopologyResponseBody) MarshalBinary() ([]byte, error) { +func (s PeerAddress) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -16787,134 +18780,151 @@ func (s TopologyResponseBody) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *TopologyResponseBody) UnmarshalBinary(inp []byte) error { +func (s *PeerAddress) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*TopologyResponseBody)(nil) - _ encoding.BinaryUnmarshaler = (*TopologyResponseBody)(nil) + _ encoding.BinaryMarshaler = (*PeerAddress)(nil) + _ encoding.BinaryUnmarshaler = (*PeerAddress)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s TopologyResponseBody) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s PeerAddress) xdrType() {} -var _ xdrType = (*TopologyResponseBody)(nil) +var _ xdrType = (*PeerAddress)(nil) -// SurveyResponseBody is an XDR Union defines as: +// MessageType is an XDR Enum defines as: // -// union SurveyResponseBody switch (SurveyMessageCommandType type) +// enum MessageType // { -// case SURVEY_TOPOLOGY: -// TopologyResponseBody topologyResponseBody; +// ERROR_MSG = 0, +// AUTH = 2, +// DONT_HAVE = 3, +// +// GET_PEERS = 4, // gets a list of peers this guy knows about +// PEERS = 5, +// +// GET_TX_SET = 6, // gets a particular txset by hash +// TX_SET = 7, +// GENERALIZED_TX_SET = 17, +// +// TRANSACTION = 8, // pass on a tx you have heard about +// +// // SCP +// GET_SCP_QUORUMSET = 9, +// SCP_QUORUMSET = 10, +// SCP_MESSAGE = 11, +// GET_SCP_STATE = 12, +// +// // new messages +// HELLO = 13, +// +// SURVEY_REQUEST = 14, +// SURVEY_RESPONSE = 15, +// +// SEND_MORE = 16, +// SEND_MORE_EXTENDED = 20, +// +// FLOOD_ADVERT = 18, +// FLOOD_DEMAND = 19 // }; -type SurveyResponseBody struct { - Type SurveyMessageCommandType - TopologyResponseBody *TopologyResponseBody -} - -// SwitchFieldName returns the field name in which this union's -// discriminant is stored -func (u SurveyResponseBody) SwitchFieldName() string { - return "Type" -} +type MessageType int32 -// ArmForSwitch returns which field name should be used for storing -// the value for an instance of SurveyResponseBody -func (u SurveyResponseBody) ArmForSwitch(sw int32) (string, bool) { - switch SurveyMessageCommandType(sw) { - case SurveyMessageCommandTypeSurveyTopology: - return "TopologyResponseBody", true - } - return "-", false -} +const ( + MessageTypeErrorMsg MessageType = 0 + MessageTypeAuth MessageType = 2 + MessageTypeDontHave MessageType = 3 + MessageTypeGetPeers MessageType = 4 + MessageTypePeers MessageType = 5 + MessageTypeGetTxSet MessageType = 6 + MessageTypeTxSet MessageType = 7 + MessageTypeGeneralizedTxSet MessageType = 17 + MessageTypeTransaction MessageType = 8 + MessageTypeGetScpQuorumset MessageType = 9 + MessageTypeScpQuorumset MessageType = 10 + MessageTypeScpMessage MessageType = 11 + MessageTypeGetScpState MessageType = 12 + MessageTypeHello MessageType = 13 + MessageTypeSurveyRequest MessageType = 14 + MessageTypeSurveyResponse MessageType = 15 + MessageTypeSendMore MessageType = 16 + MessageTypeSendMoreExtended MessageType = 20 + MessageTypeFloodAdvert MessageType = 18 + MessageTypeFloodDemand MessageType = 19 +) -// NewSurveyResponseBody creates a new SurveyResponseBody. -func NewSurveyResponseBody(aType SurveyMessageCommandType, value interface{}) (result SurveyResponseBody, err error) { - result.Type = aType - switch SurveyMessageCommandType(aType) { - case SurveyMessageCommandTypeSurveyTopology: - tv, ok := value.(TopologyResponseBody) - if !ok { - err = fmt.Errorf("invalid value, must be TopologyResponseBody") - return - } - result.TopologyResponseBody = &tv - } - return +var messageTypeMap = map[int32]string{ + 0: "MessageTypeErrorMsg", + 2: "MessageTypeAuth", + 3: "MessageTypeDontHave", + 4: "MessageTypeGetPeers", + 5: "MessageTypePeers", + 6: "MessageTypeGetTxSet", + 7: "MessageTypeTxSet", + 17: "MessageTypeGeneralizedTxSet", + 8: "MessageTypeTransaction", + 9: "MessageTypeGetScpQuorumset", + 10: "MessageTypeScpQuorumset", + 11: "MessageTypeScpMessage", + 12: "MessageTypeGetScpState", + 13: "MessageTypeHello", + 14: "MessageTypeSurveyRequest", + 15: "MessageTypeSurveyResponse", + 16: "MessageTypeSendMore", + 20: "MessageTypeSendMoreExtended", + 18: "MessageTypeFloodAdvert", + 19: "MessageTypeFloodDemand", } -// MustTopologyResponseBody retrieves the TopologyResponseBody value from the union, -// panicing if the value is not set. -func (u SurveyResponseBody) MustTopologyResponseBody() TopologyResponseBody { - val, ok := u.GetTopologyResponseBody() - - if !ok { - panic("arm TopologyResponseBody is not set") - } - - return val +// ValidEnum validates a proposed value for this enum. Implements +// the Enum interface for MessageType +func (e MessageType) ValidEnum(v int32) bool { + _, ok := messageTypeMap[v] + return ok } -// GetTopologyResponseBody retrieves the TopologyResponseBody value from the union, -// returning ok if the union's switch indicated the value is valid. -func (u SurveyResponseBody) GetTopologyResponseBody() (result TopologyResponseBody, ok bool) { - armName, _ := u.ArmForSwitch(int32(u.Type)) - - if armName == "TopologyResponseBody" { - result = *u.TopologyResponseBody - ok = true - } - - return +// String returns the name of `e` +func (e MessageType) String() string { + name, _ := messageTypeMap[int32(e)] + return name } // EncodeTo encodes this value using the Encoder. -func (u SurveyResponseBody) EncodeTo(e *xdr.Encoder) error { - var err error - if err = u.Type.EncodeTo(e); err != nil { - return err - } - switch SurveyMessageCommandType(u.Type) { - case SurveyMessageCommandTypeSurveyTopology: - if err = (*u.TopologyResponseBody).EncodeTo(e); err != nil { - return err - } - return nil +func (e MessageType) EncodeTo(enc *xdr.Encoder) error { + if _, ok := messageTypeMap[int32(e)]; !ok { + return fmt.Errorf("'%d' is not a valid MessageType enum value", e) } - return fmt.Errorf("Type (SurveyMessageCommandType) switch value '%d' is not valid for union SurveyResponseBody", u.Type) + _, err := enc.EncodeInt(int32(e)) + return err } -var _ decoderFrom = (*SurveyResponseBody)(nil) +var _ decoderFrom = (*MessageType)(nil) // DecodeFrom decodes this value using the Decoder. -func (u *SurveyResponseBody) DecodeFrom(d *xdr.Decoder) (int, error) { - var err error - var n, nTmp int - nTmp, err = u.Type.DecodeFrom(d) - n += nTmp +func (e *MessageType) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding MessageType: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + v, n, err := d.DecodeInt() if err != nil { - return n, fmt.Errorf("decoding SurveyMessageCommandType: %s", err) + return n, fmt.Errorf("decoding MessageType: %w", err) } - switch SurveyMessageCommandType(u.Type) { - case SurveyMessageCommandTypeSurveyTopology: - u.TopologyResponseBody = new(TopologyResponseBody) - nTmp, err = (*u.TopologyResponseBody).DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding TopologyResponseBody: %s", err) - } - return n, nil + if _, ok := messageTypeMap[v]; !ok { + return n, fmt.Errorf("'%d' is not a valid MessageType enum value", v) } - return n, fmt.Errorf("union SurveyResponseBody has invalid Type (SurveyMessageCommandType) switch value '%d'", u.Type) + *e = MessageType(v) + return n, nil } // MarshalBinary implements encoding.BinaryMarshaler. -func (s SurveyResponseBody) MarshalBinary() ([]byte, error) { +func (s MessageType) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -16922,922 +18932,427 @@ func (s SurveyResponseBody) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *SurveyResponseBody) UnmarshalBinary(inp []byte) error { +func (s *MessageType) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*SurveyResponseBody)(nil) - _ encoding.BinaryUnmarshaler = (*SurveyResponseBody)(nil) + _ encoding.BinaryMarshaler = (*MessageType)(nil) + _ encoding.BinaryUnmarshaler = (*MessageType)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s SurveyResponseBody) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s MessageType) xdrType() {} -var _ xdrType = (*SurveyResponseBody)(nil) +var _ xdrType = (*MessageType)(nil) -// StellarMessage is an XDR Union defines as: +// DontHave is an XDR Struct defines as: // -// union StellarMessage switch (MessageType type) +// struct DontHave // { -// case ERROR_MSG: -// Error error; -// case HELLO: -// Hello hello; -// case AUTH: -// Auth auth; -// case DONT_HAVE: -// DontHave dontHave; -// case GET_PEERS: -// void; -// case PEERS: -// PeerAddress peers<100>; -// -// case GET_TX_SET: -// uint256 txSetHash; -// case TX_SET: -// TransactionSet txSet; -// case GENERALIZED_TX_SET: -// GeneralizedTransactionSet generalizedTxSet; -// -// case TRANSACTION: -// TransactionEnvelope transaction; -// -// case SURVEY_REQUEST: -// SignedSurveyRequestMessage signedSurveyRequestMessage; -// -// case SURVEY_RESPONSE: -// SignedSurveyResponseMessage signedSurveyResponseMessage; -// -// // SCP -// case GET_SCP_QUORUMSET: -// uint256 qSetHash; -// case SCP_QUORUMSET: -// SCPQuorumSet qSet; -// case SCP_MESSAGE: -// SCPEnvelope envelope; -// case GET_SCP_STATE: -// uint32 getSCPLedgerSeq; // ledger seq requested ; if 0, requests the latest -// case SEND_MORE: -// SendMore sendMoreMessage; +// MessageType type; +// uint256 reqHash; // }; -type StellarMessage struct { - Type MessageType - Error *Error - Hello *Hello - Auth *Auth - DontHave *DontHave - Peers *[]PeerAddress `xdrmaxsize:"100"` - TxSetHash *Uint256 - TxSet *TransactionSet - GeneralizedTxSet *GeneralizedTransactionSet - Transaction *TransactionEnvelope - SignedSurveyRequestMessage *SignedSurveyRequestMessage - SignedSurveyResponseMessage *SignedSurveyResponseMessage - QSetHash *Uint256 - QSet *ScpQuorumSet - Envelope *ScpEnvelope - GetScpLedgerSeq *Uint32 - SendMoreMessage *SendMore -} - -// SwitchFieldName returns the field name in which this union's -// discriminant is stored -func (u StellarMessage) SwitchFieldName() string { - return "Type" +type DontHave struct { + Type MessageType + ReqHash Uint256 } -// ArmForSwitch returns which field name should be used for storing -// the value for an instance of StellarMessage -func (u StellarMessage) ArmForSwitch(sw int32) (string, bool) { - switch MessageType(sw) { - case MessageTypeErrorMsg: - return "Error", true - case MessageTypeHello: - return "Hello", true - case MessageTypeAuth: - return "Auth", true - case MessageTypeDontHave: - return "DontHave", true - case MessageTypeGetPeers: - return "", true - case MessageTypePeers: - return "Peers", true - case MessageTypeGetTxSet: - return "TxSetHash", true - case MessageTypeTxSet: - return "TxSet", true - case MessageTypeGeneralizedTxSet: - return "GeneralizedTxSet", true - case MessageTypeTransaction: - return "Transaction", true - case MessageTypeSurveyRequest: - return "SignedSurveyRequestMessage", true - case MessageTypeSurveyResponse: - return "SignedSurveyResponseMessage", true - case MessageTypeGetScpQuorumset: - return "QSetHash", true - case MessageTypeScpQuorumset: - return "QSet", true - case MessageTypeScpMessage: - return "Envelope", true - case MessageTypeGetScpState: - return "GetScpLedgerSeq", true - case MessageTypeSendMore: - return "SendMoreMessage", true +// EncodeTo encodes this value using the Encoder. +func (s *DontHave) EncodeTo(e *xdr.Encoder) error { + var err error + if err = s.Type.EncodeTo(e); err != nil { + return err } - return "-", false -} - -// NewStellarMessage creates a new StellarMessage. -func NewStellarMessage(aType MessageType, value interface{}) (result StellarMessage, err error) { - result.Type = aType - switch MessageType(aType) { - case MessageTypeErrorMsg: - tv, ok := value.(Error) - if !ok { - err = fmt.Errorf("invalid value, must be Error") - return - } - result.Error = &tv - case MessageTypeHello: - tv, ok := value.(Hello) - if !ok { - err = fmt.Errorf("invalid value, must be Hello") - return - } - result.Hello = &tv - case MessageTypeAuth: - tv, ok := value.(Auth) - if !ok { - err = fmt.Errorf("invalid value, must be Auth") - return - } - result.Auth = &tv - case MessageTypeDontHave: - tv, ok := value.(DontHave) - if !ok { - err = fmt.Errorf("invalid value, must be DontHave") - return - } - result.DontHave = &tv - case MessageTypeGetPeers: - // void - case MessageTypePeers: - tv, ok := value.([]PeerAddress) - if !ok { - err = fmt.Errorf("invalid value, must be []PeerAddress") - return - } - result.Peers = &tv - case MessageTypeGetTxSet: - tv, ok := value.(Uint256) - if !ok { - err = fmt.Errorf("invalid value, must be Uint256") - return - } - result.TxSetHash = &tv - case MessageTypeTxSet: - tv, ok := value.(TransactionSet) - if !ok { - err = fmt.Errorf("invalid value, must be TransactionSet") - return - } - result.TxSet = &tv - case MessageTypeGeneralizedTxSet: - tv, ok := value.(GeneralizedTransactionSet) - if !ok { - err = fmt.Errorf("invalid value, must be GeneralizedTransactionSet") - return - } - result.GeneralizedTxSet = &tv - case MessageTypeTransaction: - tv, ok := value.(TransactionEnvelope) - if !ok { - err = fmt.Errorf("invalid value, must be TransactionEnvelope") - return - } - result.Transaction = &tv - case MessageTypeSurveyRequest: - tv, ok := value.(SignedSurveyRequestMessage) - if !ok { - err = fmt.Errorf("invalid value, must be SignedSurveyRequestMessage") - return - } - result.SignedSurveyRequestMessage = &tv - case MessageTypeSurveyResponse: - tv, ok := value.(SignedSurveyResponseMessage) - if !ok { - err = fmt.Errorf("invalid value, must be SignedSurveyResponseMessage") - return - } - result.SignedSurveyResponseMessage = &tv - case MessageTypeGetScpQuorumset: - tv, ok := value.(Uint256) - if !ok { - err = fmt.Errorf("invalid value, must be Uint256") - return - } - result.QSetHash = &tv - case MessageTypeScpQuorumset: - tv, ok := value.(ScpQuorumSet) - if !ok { - err = fmt.Errorf("invalid value, must be ScpQuorumSet") - return - } - result.QSet = &tv - case MessageTypeScpMessage: - tv, ok := value.(ScpEnvelope) - if !ok { - err = fmt.Errorf("invalid value, must be ScpEnvelope") - return - } - result.Envelope = &tv - case MessageTypeGetScpState: - tv, ok := value.(Uint32) - if !ok { - err = fmt.Errorf("invalid value, must be Uint32") - return - } - result.GetScpLedgerSeq = &tv - case MessageTypeSendMore: - tv, ok := value.(SendMore) - if !ok { - err = fmt.Errorf("invalid value, must be SendMore") - return - } - result.SendMoreMessage = &tv + if err = s.ReqHash.EncodeTo(e); err != nil { + return err } - return + return nil } -// MustError retrieves the Error value from the union, -// panicing if the value is not set. -func (u StellarMessage) MustError() Error { - val, ok := u.GetError() +var _ decoderFrom = (*DontHave)(nil) - if !ok { - panic("arm Error is not set") +// DecodeFrom decodes this value using the Decoder. +func (s *DontHave) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding DontHave: %w", ErrMaxDecodingDepthReached) } - - return val -} - -// GetError retrieves the Error value from the union, -// returning ok if the union's switch indicated the value is valid. -func (u StellarMessage) GetError() (result Error, ok bool) { - armName, _ := u.ArmForSwitch(int32(u.Type)) - - if armName == "Error" { - result = *u.Error - ok = true + maxDepth -= 1 + var err error + var n, nTmp int + nTmp, err = s.Type.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding MessageType: %w", err) } - - return -} - -// MustHello retrieves the Hello value from the union, -// panicing if the value is not set. -func (u StellarMessage) MustHello() Hello { - val, ok := u.GetHello() - - if !ok { - panic("arm Hello is not set") + nTmp, err = s.ReqHash.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Uint256: %w", err) } - - return val + return n, nil } -// GetHello retrieves the Hello value from the union, -// returning ok if the union's switch indicated the value is valid. -func (u StellarMessage) GetHello() (result Hello, ok bool) { - armName, _ := u.ArmForSwitch(int32(u.Type)) - - if armName == "Hello" { - result = *u.Hello - ok = true - } +// MarshalBinary implements encoding.BinaryMarshaler. +func (s DontHave) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} - return +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *DontHave) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err } -// MustAuth retrieves the Auth value from the union, -// panicing if the value is not set. -func (u StellarMessage) MustAuth() Auth { - val, ok := u.GetAuth() +var ( + _ encoding.BinaryMarshaler = (*DontHave)(nil) + _ encoding.BinaryUnmarshaler = (*DontHave)(nil) +) - if !ok { - panic("arm Auth is not set") - } +// xdrType signals that this type represents XDR values defined by this package. +func (s DontHave) xdrType() {} - return val -} +var _ xdrType = (*DontHave)(nil) -// GetAuth retrieves the Auth value from the union, -// returning ok if the union's switch indicated the value is valid. -func (u StellarMessage) GetAuth() (result Auth, ok bool) { - armName, _ := u.ArmForSwitch(int32(u.Type)) +// SurveyMessageCommandType is an XDR Enum defines as: +// +// enum SurveyMessageCommandType +// { +// SURVEY_TOPOLOGY = 0 +// }; +type SurveyMessageCommandType int32 - if armName == "Auth" { - result = *u.Auth - ok = true - } +const ( + SurveyMessageCommandTypeSurveyTopology SurveyMessageCommandType = 0 +) - return +var surveyMessageCommandTypeMap = map[int32]string{ + 0: "SurveyMessageCommandTypeSurveyTopology", } -// MustDontHave retrieves the DontHave value from the union, -// panicing if the value is not set. -func (u StellarMessage) MustDontHave() DontHave { - val, ok := u.GetDontHave() - - if !ok { - panic("arm DontHave is not set") - } - - return val +// ValidEnum validates a proposed value for this enum. Implements +// the Enum interface for SurveyMessageCommandType +func (e SurveyMessageCommandType) ValidEnum(v int32) bool { + _, ok := surveyMessageCommandTypeMap[v] + return ok } -// GetDontHave retrieves the DontHave value from the union, -// returning ok if the union's switch indicated the value is valid. -func (u StellarMessage) GetDontHave() (result DontHave, ok bool) { - armName, _ := u.ArmForSwitch(int32(u.Type)) +// String returns the name of `e` +func (e SurveyMessageCommandType) String() string { + name, _ := surveyMessageCommandTypeMap[int32(e)] + return name +} - if armName == "DontHave" { - result = *u.DontHave - ok = true +// EncodeTo encodes this value using the Encoder. +func (e SurveyMessageCommandType) EncodeTo(enc *xdr.Encoder) error { + if _, ok := surveyMessageCommandTypeMap[int32(e)]; !ok { + return fmt.Errorf("'%d' is not a valid SurveyMessageCommandType enum value", e) } - - return + _, err := enc.EncodeInt(int32(e)) + return err } -// MustPeers retrieves the Peers value from the union, -// panicing if the value is not set. -func (u StellarMessage) MustPeers() []PeerAddress { - val, ok := u.GetPeers() +var _ decoderFrom = (*SurveyMessageCommandType)(nil) - if !ok { - panic("arm Peers is not set") +// DecodeFrom decodes this value using the Decoder. +func (e *SurveyMessageCommandType) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding SurveyMessageCommandType: %w", ErrMaxDecodingDepthReached) } - - return val + maxDepth -= 1 + v, n, err := d.DecodeInt() + if err != nil { + return n, fmt.Errorf("decoding SurveyMessageCommandType: %w", err) + } + if _, ok := surveyMessageCommandTypeMap[v]; !ok { + return n, fmt.Errorf("'%d' is not a valid SurveyMessageCommandType enum value", v) + } + *e = SurveyMessageCommandType(v) + return n, nil } -// GetPeers retrieves the Peers value from the union, -// returning ok if the union's switch indicated the value is valid. -func (u StellarMessage) GetPeers() (result []PeerAddress, ok bool) { - armName, _ := u.ArmForSwitch(int32(u.Type)) - - if armName == "Peers" { - result = *u.Peers - ok = true - } +// MarshalBinary implements encoding.BinaryMarshaler. +func (s SurveyMessageCommandType) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} - return +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *SurveyMessageCommandType) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err } -// MustTxSetHash retrieves the TxSetHash value from the union, -// panicing if the value is not set. -func (u StellarMessage) MustTxSetHash() Uint256 { - val, ok := u.GetTxSetHash() +var ( + _ encoding.BinaryMarshaler = (*SurveyMessageCommandType)(nil) + _ encoding.BinaryUnmarshaler = (*SurveyMessageCommandType)(nil) +) - if !ok { - panic("arm TxSetHash is not set") - } +// xdrType signals that this type represents XDR values defined by this package. +func (s SurveyMessageCommandType) xdrType() {} - return val -} +var _ xdrType = (*SurveyMessageCommandType)(nil) -// GetTxSetHash retrieves the TxSetHash value from the union, -// returning ok if the union's switch indicated the value is valid. -func (u StellarMessage) GetTxSetHash() (result Uint256, ok bool) { - armName, _ := u.ArmForSwitch(int32(u.Type)) +// SurveyMessageResponseType is an XDR Enum defines as: +// +// enum SurveyMessageResponseType +// { +// SURVEY_TOPOLOGY_RESPONSE_V0 = 0, +// SURVEY_TOPOLOGY_RESPONSE_V1 = 1 +// }; +type SurveyMessageResponseType int32 - if armName == "TxSetHash" { - result = *u.TxSetHash - ok = true - } +const ( + SurveyMessageResponseTypeSurveyTopologyResponseV0 SurveyMessageResponseType = 0 + SurveyMessageResponseTypeSurveyTopologyResponseV1 SurveyMessageResponseType = 1 +) - return +var surveyMessageResponseTypeMap = map[int32]string{ + 0: "SurveyMessageResponseTypeSurveyTopologyResponseV0", + 1: "SurveyMessageResponseTypeSurveyTopologyResponseV1", } -// MustTxSet retrieves the TxSet value from the union, -// panicing if the value is not set. -func (u StellarMessage) MustTxSet() TransactionSet { - val, ok := u.GetTxSet() - - if !ok { - panic("arm TxSet is not set") - } - - return val +// ValidEnum validates a proposed value for this enum. Implements +// the Enum interface for SurveyMessageResponseType +func (e SurveyMessageResponseType) ValidEnum(v int32) bool { + _, ok := surveyMessageResponseTypeMap[v] + return ok } -// GetTxSet retrieves the TxSet value from the union, -// returning ok if the union's switch indicated the value is valid. -func (u StellarMessage) GetTxSet() (result TransactionSet, ok bool) { - armName, _ := u.ArmForSwitch(int32(u.Type)) +// String returns the name of `e` +func (e SurveyMessageResponseType) String() string { + name, _ := surveyMessageResponseTypeMap[int32(e)] + return name +} - if armName == "TxSet" { - result = *u.TxSet - ok = true +// EncodeTo encodes this value using the Encoder. +func (e SurveyMessageResponseType) EncodeTo(enc *xdr.Encoder) error { + if _, ok := surveyMessageResponseTypeMap[int32(e)]; !ok { + return fmt.Errorf("'%d' is not a valid SurveyMessageResponseType enum value", e) } - - return + _, err := enc.EncodeInt(int32(e)) + return err } -// MustGeneralizedTxSet retrieves the GeneralizedTxSet value from the union, -// panicing if the value is not set. -func (u StellarMessage) MustGeneralizedTxSet() GeneralizedTransactionSet { - val, ok := u.GetGeneralizedTxSet() +var _ decoderFrom = (*SurveyMessageResponseType)(nil) - if !ok { - panic("arm GeneralizedTxSet is not set") +// DecodeFrom decodes this value using the Decoder. +func (e *SurveyMessageResponseType) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding SurveyMessageResponseType: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + v, n, err := d.DecodeInt() + if err != nil { + return n, fmt.Errorf("decoding SurveyMessageResponseType: %w", err) + } + if _, ok := surveyMessageResponseTypeMap[v]; !ok { + return n, fmt.Errorf("'%d' is not a valid SurveyMessageResponseType enum value", v) } + *e = SurveyMessageResponseType(v) + return n, nil +} - return val +// MarshalBinary implements encoding.BinaryMarshaler. +func (s SurveyMessageResponseType) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err } -// GetGeneralizedTxSet retrieves the GeneralizedTxSet value from the union, -// returning ok if the union's switch indicated the value is valid. -func (u StellarMessage) GetGeneralizedTxSet() (result GeneralizedTransactionSet, ok bool) { - armName, _ := u.ArmForSwitch(int32(u.Type)) +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *SurveyMessageResponseType) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} - if armName == "GeneralizedTxSet" { - result = *u.GeneralizedTxSet - ok = true - } +var ( + _ encoding.BinaryMarshaler = (*SurveyMessageResponseType)(nil) + _ encoding.BinaryUnmarshaler = (*SurveyMessageResponseType)(nil) +) - return -} +// xdrType signals that this type represents XDR values defined by this package. +func (s SurveyMessageResponseType) xdrType() {} -// MustTransaction retrieves the Transaction value from the union, -// panicing if the value is not set. -func (u StellarMessage) MustTransaction() TransactionEnvelope { - val, ok := u.GetTransaction() +var _ xdrType = (*SurveyMessageResponseType)(nil) - if !ok { - panic("arm Transaction is not set") - } - - return val +// SurveyRequestMessage is an XDR Struct defines as: +// +// struct SurveyRequestMessage +// { +// NodeID surveyorPeerID; +// NodeID surveyedPeerID; +// uint32 ledgerNum; +// Curve25519Public encryptionKey; +// SurveyMessageCommandType commandType; +// }; +type SurveyRequestMessage struct { + SurveyorPeerId NodeId + SurveyedPeerId NodeId + LedgerNum Uint32 + EncryptionKey Curve25519Public + CommandType SurveyMessageCommandType } -// GetTransaction retrieves the Transaction value from the union, -// returning ok if the union's switch indicated the value is valid. -func (u StellarMessage) GetTransaction() (result TransactionEnvelope, ok bool) { - armName, _ := u.ArmForSwitch(int32(u.Type)) - - if armName == "Transaction" { - result = *u.Transaction - ok = true +// EncodeTo encodes this value using the Encoder. +func (s *SurveyRequestMessage) EncodeTo(e *xdr.Encoder) error { + var err error + if err = s.SurveyorPeerId.EncodeTo(e); err != nil { + return err } - - return -} - -// MustSignedSurveyRequestMessage retrieves the SignedSurveyRequestMessage value from the union, -// panicing if the value is not set. -func (u StellarMessage) MustSignedSurveyRequestMessage() SignedSurveyRequestMessage { - val, ok := u.GetSignedSurveyRequestMessage() - - if !ok { - panic("arm SignedSurveyRequestMessage is not set") + if err = s.SurveyedPeerId.EncodeTo(e); err != nil { + return err } - - return val -} - -// GetSignedSurveyRequestMessage retrieves the SignedSurveyRequestMessage value from the union, -// returning ok if the union's switch indicated the value is valid. -func (u StellarMessage) GetSignedSurveyRequestMessage() (result SignedSurveyRequestMessage, ok bool) { - armName, _ := u.ArmForSwitch(int32(u.Type)) - - if armName == "SignedSurveyRequestMessage" { - result = *u.SignedSurveyRequestMessage - ok = true + if err = s.LedgerNum.EncodeTo(e); err != nil { + return err } - - return -} - -// MustSignedSurveyResponseMessage retrieves the SignedSurveyResponseMessage value from the union, -// panicing if the value is not set. -func (u StellarMessage) MustSignedSurveyResponseMessage() SignedSurveyResponseMessage { - val, ok := u.GetSignedSurveyResponseMessage() - - if !ok { - panic("arm SignedSurveyResponseMessage is not set") + if err = s.EncryptionKey.EncodeTo(e); err != nil { + return err } - - return val -} - -// GetSignedSurveyResponseMessage retrieves the SignedSurveyResponseMessage value from the union, -// returning ok if the union's switch indicated the value is valid. -func (u StellarMessage) GetSignedSurveyResponseMessage() (result SignedSurveyResponseMessage, ok bool) { - armName, _ := u.ArmForSwitch(int32(u.Type)) - - if armName == "SignedSurveyResponseMessage" { - result = *u.SignedSurveyResponseMessage - ok = true + if err = s.CommandType.EncodeTo(e); err != nil { + return err } - - return + return nil } -// MustQSetHash retrieves the QSetHash value from the union, -// panicing if the value is not set. -func (u StellarMessage) MustQSetHash() Uint256 { - val, ok := u.GetQSetHash() +var _ decoderFrom = (*SurveyRequestMessage)(nil) - if !ok { - panic("arm QSetHash is not set") +// DecodeFrom decodes this value using the Decoder. +func (s *SurveyRequestMessage) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding SurveyRequestMessage: %w", ErrMaxDecodingDepthReached) } - - return val -} - -// GetQSetHash retrieves the QSetHash value from the union, -// returning ok if the union's switch indicated the value is valid. -func (u StellarMessage) GetQSetHash() (result Uint256, ok bool) { - armName, _ := u.ArmForSwitch(int32(u.Type)) - - if armName == "QSetHash" { - result = *u.QSetHash - ok = true + maxDepth -= 1 + var err error + var n, nTmp int + nTmp, err = s.SurveyorPeerId.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding NodeId: %w", err) } - - return -} - -// MustQSet retrieves the QSet value from the union, -// panicing if the value is not set. -func (u StellarMessage) MustQSet() ScpQuorumSet { - val, ok := u.GetQSet() - - if !ok { - panic("arm QSet is not set") + nTmp, err = s.SurveyedPeerId.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding NodeId: %w", err) } - - return val -} - -// GetQSet retrieves the QSet value from the union, -// returning ok if the union's switch indicated the value is valid. -func (u StellarMessage) GetQSet() (result ScpQuorumSet, ok bool) { - armName, _ := u.ArmForSwitch(int32(u.Type)) - - if armName == "QSet" { - result = *u.QSet - ok = true + nTmp, err = s.LedgerNum.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Uint32: %w", err) } - - return -} - -// MustEnvelope retrieves the Envelope value from the union, -// panicing if the value is not set. -func (u StellarMessage) MustEnvelope() ScpEnvelope { - val, ok := u.GetEnvelope() - - if !ok { - panic("arm Envelope is not set") + nTmp, err = s.EncryptionKey.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Curve25519Public: %w", err) } - - return val -} - -// GetEnvelope retrieves the Envelope value from the union, -// returning ok if the union's switch indicated the value is valid. -func (u StellarMessage) GetEnvelope() (result ScpEnvelope, ok bool) { - armName, _ := u.ArmForSwitch(int32(u.Type)) - - if armName == "Envelope" { - result = *u.Envelope - ok = true + nTmp, err = s.CommandType.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding SurveyMessageCommandType: %w", err) } - - return + return n, nil } -// MustGetScpLedgerSeq retrieves the GetScpLedgerSeq value from the union, -// panicing if the value is not set. -func (u StellarMessage) MustGetScpLedgerSeq() Uint32 { - val, ok := u.GetGetScpLedgerSeq() - - if !ok { - panic("arm GetScpLedgerSeq is not set") - } - - return val +// MarshalBinary implements encoding.BinaryMarshaler. +func (s SurveyRequestMessage) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err } -// GetGetScpLedgerSeq retrieves the GetScpLedgerSeq value from the union, -// returning ok if the union's switch indicated the value is valid. -func (u StellarMessage) GetGetScpLedgerSeq() (result Uint32, ok bool) { - armName, _ := u.ArmForSwitch(int32(u.Type)) - - if armName == "GetScpLedgerSeq" { - result = *u.GetScpLedgerSeq - ok = true - } - - return +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *SurveyRequestMessage) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err } -// MustSendMoreMessage retrieves the SendMoreMessage value from the union, -// panicing if the value is not set. -func (u StellarMessage) MustSendMoreMessage() SendMore { - val, ok := u.GetSendMoreMessage() - - if !ok { - panic("arm SendMoreMessage is not set") - } - - return val -} +var ( + _ encoding.BinaryMarshaler = (*SurveyRequestMessage)(nil) + _ encoding.BinaryUnmarshaler = (*SurveyRequestMessage)(nil) +) -// GetSendMoreMessage retrieves the SendMoreMessage value from the union, -// returning ok if the union's switch indicated the value is valid. -func (u StellarMessage) GetSendMoreMessage() (result SendMore, ok bool) { - armName, _ := u.ArmForSwitch(int32(u.Type)) +// xdrType signals that this type represents XDR values defined by this package. +func (s SurveyRequestMessage) xdrType() {} - if armName == "SendMoreMessage" { - result = *u.SendMoreMessage - ok = true - } +var _ xdrType = (*SurveyRequestMessage)(nil) - return +// SignedSurveyRequestMessage is an XDR Struct defines as: +// +// struct SignedSurveyRequestMessage +// { +// Signature requestSignature; +// SurveyRequestMessage request; +// }; +type SignedSurveyRequestMessage struct { + RequestSignature Signature + Request SurveyRequestMessage } // EncodeTo encodes this value using the Encoder. -func (u StellarMessage) EncodeTo(e *xdr.Encoder) error { +func (s *SignedSurveyRequestMessage) EncodeTo(e *xdr.Encoder) error { var err error - if err = u.Type.EncodeTo(e); err != nil { + if err = s.RequestSignature.EncodeTo(e); err != nil { return err } - switch MessageType(u.Type) { - case MessageTypeErrorMsg: - if err = (*u.Error).EncodeTo(e); err != nil { - return err - } - return nil - case MessageTypeHello: - if err = (*u.Hello).EncodeTo(e); err != nil { - return err - } - return nil - case MessageTypeAuth: - if err = (*u.Auth).EncodeTo(e); err != nil { - return err - } - return nil - case MessageTypeDontHave: - if err = (*u.DontHave).EncodeTo(e); err != nil { - return err - } - return nil - case MessageTypeGetPeers: - // Void - return nil - case MessageTypePeers: - if _, err = e.EncodeUint(uint32(len((*u.Peers)))); err != nil { - return err - } - for i := 0; i < len((*u.Peers)); i++ { - if err = (*u.Peers)[i].EncodeTo(e); err != nil { - return err - } - } - return nil - case MessageTypeGetTxSet: - if err = (*u.TxSetHash).EncodeTo(e); err != nil { - return err - } - return nil - case MessageTypeTxSet: - if err = (*u.TxSet).EncodeTo(e); err != nil { - return err - } - return nil - case MessageTypeGeneralizedTxSet: - if err = (*u.GeneralizedTxSet).EncodeTo(e); err != nil { - return err - } - return nil - case MessageTypeTransaction: - if err = (*u.Transaction).EncodeTo(e); err != nil { - return err - } - return nil - case MessageTypeSurveyRequest: - if err = (*u.SignedSurveyRequestMessage).EncodeTo(e); err != nil { - return err - } - return nil - case MessageTypeSurveyResponse: - if err = (*u.SignedSurveyResponseMessage).EncodeTo(e); err != nil { - return err - } - return nil - case MessageTypeGetScpQuorumset: - if err = (*u.QSetHash).EncodeTo(e); err != nil { - return err - } - return nil - case MessageTypeScpQuorumset: - if err = (*u.QSet).EncodeTo(e); err != nil { - return err - } - return nil - case MessageTypeScpMessage: - if err = (*u.Envelope).EncodeTo(e); err != nil { - return err - } - return nil - case MessageTypeGetScpState: - if err = (*u.GetScpLedgerSeq).EncodeTo(e); err != nil { - return err - } - return nil - case MessageTypeSendMore: - if err = (*u.SendMoreMessage).EncodeTo(e); err != nil { - return err - } - return nil + if err = s.Request.EncodeTo(e); err != nil { + return err } - return fmt.Errorf("Type (MessageType) switch value '%d' is not valid for union StellarMessage", u.Type) + return nil } -var _ decoderFrom = (*StellarMessage)(nil) +var _ decoderFrom = (*SignedSurveyRequestMessage)(nil) // DecodeFrom decodes this value using the Decoder. -func (u *StellarMessage) DecodeFrom(d *xdr.Decoder) (int, error) { +func (s *SignedSurveyRequestMessage) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding SignedSurveyRequestMessage: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = u.Type.DecodeFrom(d) + nTmp, err = s.RequestSignature.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding MessageType: %s", err) + return n, fmt.Errorf("decoding Signature: %w", err) } - switch MessageType(u.Type) { - case MessageTypeErrorMsg: - u.Error = new(Error) - nTmp, err = (*u.Error).DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Error: %s", err) - } - return n, nil - case MessageTypeHello: - u.Hello = new(Hello) - nTmp, err = (*u.Hello).DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Hello: %s", err) - } - return n, nil - case MessageTypeAuth: - u.Auth = new(Auth) - nTmp, err = (*u.Auth).DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Auth: %s", err) - } - return n, nil - case MessageTypeDontHave: - u.DontHave = new(DontHave) - nTmp, err = (*u.DontHave).DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding DontHave: %s", err) - } - return n, nil - case MessageTypeGetPeers: - // Void - return n, nil - case MessageTypePeers: - u.Peers = new([]PeerAddress) - var l uint32 - l, nTmp, err = d.DecodeUint() - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding PeerAddress: %s", err) - } - if l > 100 { - return n, fmt.Errorf("decoding PeerAddress: data size (%d) exceeds size limit (100)", l) - } - (*u.Peers) = nil - if l > 0 { - (*u.Peers) = make([]PeerAddress, l) - for i := uint32(0); i < l; i++ { - nTmp, err = (*u.Peers)[i].DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding PeerAddress: %s", err) - } - } - } - return n, nil - case MessageTypeGetTxSet: - u.TxSetHash = new(Uint256) - nTmp, err = (*u.TxSetHash).DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Uint256: %s", err) - } - return n, nil - case MessageTypeTxSet: - u.TxSet = new(TransactionSet) - nTmp, err = (*u.TxSet).DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding TransactionSet: %s", err) - } - return n, nil - case MessageTypeGeneralizedTxSet: - u.GeneralizedTxSet = new(GeneralizedTransactionSet) - nTmp, err = (*u.GeneralizedTxSet).DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding GeneralizedTransactionSet: %s", err) - } - return n, nil - case MessageTypeTransaction: - u.Transaction = new(TransactionEnvelope) - nTmp, err = (*u.Transaction).DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding TransactionEnvelope: %s", err) - } - return n, nil - case MessageTypeSurveyRequest: - u.SignedSurveyRequestMessage = new(SignedSurveyRequestMessage) - nTmp, err = (*u.SignedSurveyRequestMessage).DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding SignedSurveyRequestMessage: %s", err) - } - return n, nil - case MessageTypeSurveyResponse: - u.SignedSurveyResponseMessage = new(SignedSurveyResponseMessage) - nTmp, err = (*u.SignedSurveyResponseMessage).DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding SignedSurveyResponseMessage: %s", err) - } - return n, nil - case MessageTypeGetScpQuorumset: - u.QSetHash = new(Uint256) - nTmp, err = (*u.QSetHash).DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Uint256: %s", err) - } - return n, nil - case MessageTypeScpQuorumset: - u.QSet = new(ScpQuorumSet) - nTmp, err = (*u.QSet).DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding ScpQuorumSet: %s", err) - } - return n, nil - case MessageTypeScpMessage: - u.Envelope = new(ScpEnvelope) - nTmp, err = (*u.Envelope).DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding ScpEnvelope: %s", err) - } - return n, nil - case MessageTypeGetScpState: - u.GetScpLedgerSeq = new(Uint32) - nTmp, err = (*u.GetScpLedgerSeq).DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Uint32: %s", err) - } - return n, nil - case MessageTypeSendMore: - u.SendMoreMessage = new(SendMore) - nTmp, err = (*u.SendMoreMessage).DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding SendMore: %s", err) - } - return n, nil + nTmp, err = s.Request.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding SurveyRequestMessage: %w", err) } - return n, fmt.Errorf("union StellarMessage has invalid Type (MessageType) switch value '%d'", u.Type) + return n, nil } // MarshalBinary implements encoding.BinaryMarshaler. -func (s StellarMessage) MarshalBinary() ([]byte, error) { +func (s SignedSurveyRequestMessage) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -17845,79 +19360,64 @@ func (s StellarMessage) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *StellarMessage) UnmarshalBinary(inp []byte) error { +func (s *SignedSurveyRequestMessage) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*StellarMessage)(nil) - _ encoding.BinaryUnmarshaler = (*StellarMessage)(nil) + _ encoding.BinaryMarshaler = (*SignedSurveyRequestMessage)(nil) + _ encoding.BinaryUnmarshaler = (*SignedSurveyRequestMessage)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s StellarMessage) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s SignedSurveyRequestMessage) xdrType() {} -var _ xdrType = (*StellarMessage)(nil) +var _ xdrType = (*SignedSurveyRequestMessage)(nil) -// AuthenticatedMessageV0 is an XDR NestedStruct defines as: +// EncryptedBody is an XDR Typedef defines as: // -// struct -// { -// uint64 sequence; -// StellarMessage message; -// HmacSha256Mac mac; -// } -type AuthenticatedMessageV0 struct { - Sequence Uint64 - Message StellarMessage - Mac HmacSha256Mac +// typedef opaque EncryptedBody<64000>; +type EncryptedBody []byte + +// XDRMaxSize implements the Sized interface for EncryptedBody +func (e EncryptedBody) XDRMaxSize() int { + return 64000 } // EncodeTo encodes this value using the Encoder. -func (s *AuthenticatedMessageV0) EncodeTo(e *xdr.Encoder) error { +func (s EncryptedBody) EncodeTo(e *xdr.Encoder) error { var err error - if err = s.Sequence.EncodeTo(e); err != nil { - return err - } - if err = s.Message.EncodeTo(e); err != nil { - return err - } - if err = s.Mac.EncodeTo(e); err != nil { + if _, err = e.EncodeOpaque(s[:]); err != nil { return err } return nil } -var _ decoderFrom = (*AuthenticatedMessageV0)(nil) +var _ decoderFrom = (*EncryptedBody)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *AuthenticatedMessageV0) DecodeFrom(d *xdr.Decoder) (int, error) { +func (s *EncryptedBody) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding EncryptedBody: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = s.Sequence.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Uint64: %s", err) - } - nTmp, err = s.Message.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding StellarMessage: %s", err) - } - nTmp, err = s.Mac.DecodeFrom(d) + (*s), nTmp, err = d.DecodeOpaque(64000) n += nTmp if err != nil { - return n, fmt.Errorf("decoding HmacSha256Mac: %s", err) + return n, fmt.Errorf("decoding EncryptedBody: %w", err) } return n, nil } // MarshalBinary implements encoding.BinaryMarshaler. -func (s AuthenticatedMessageV0) MarshalBinary() ([]byte, error) { +func (s EncryptedBody) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -17925,139 +19425,179 @@ func (s AuthenticatedMessageV0) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *AuthenticatedMessageV0) UnmarshalBinary(inp []byte) error { +func (s *EncryptedBody) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*AuthenticatedMessageV0)(nil) - _ encoding.BinaryUnmarshaler = (*AuthenticatedMessageV0)(nil) -) + _ encoding.BinaryMarshaler = (*EncryptedBody)(nil) + _ encoding.BinaryUnmarshaler = (*EncryptedBody)(nil) +) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s AuthenticatedMessageV0) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s EncryptedBody) xdrType() {} -var _ xdrType = (*AuthenticatedMessageV0)(nil) +var _ xdrType = (*EncryptedBody)(nil) -// AuthenticatedMessage is an XDR Union defines as: +// SurveyResponseMessage is an XDR Struct defines as: // -// union AuthenticatedMessage switch (uint32 v) +// struct SurveyResponseMessage // { -// case 0: -// struct -// { -// uint64 sequence; -// StellarMessage message; -// HmacSha256Mac mac; -// } v0; +// NodeID surveyorPeerID; +// NodeID surveyedPeerID; +// uint32 ledgerNum; +// SurveyMessageCommandType commandType; +// EncryptedBody encryptedBody; // }; -type AuthenticatedMessage struct { - V Uint32 - V0 *AuthenticatedMessageV0 -} - -// SwitchFieldName returns the field name in which this union's -// discriminant is stored -func (u AuthenticatedMessage) SwitchFieldName() string { - return "V" +type SurveyResponseMessage struct { + SurveyorPeerId NodeId + SurveyedPeerId NodeId + LedgerNum Uint32 + CommandType SurveyMessageCommandType + EncryptedBody EncryptedBody } -// ArmForSwitch returns which field name should be used for storing -// the value for an instance of AuthenticatedMessage -func (u AuthenticatedMessage) ArmForSwitch(sw int32) (string, bool) { - switch Uint32(sw) { - case 0: - return "V0", true +// EncodeTo encodes this value using the Encoder. +func (s *SurveyResponseMessage) EncodeTo(e *xdr.Encoder) error { + var err error + if err = s.SurveyorPeerId.EncodeTo(e); err != nil { + return err } - return "-", false -} - -// NewAuthenticatedMessage creates a new AuthenticatedMessage. -func NewAuthenticatedMessage(v Uint32, value interface{}) (result AuthenticatedMessage, err error) { - result.V = v - switch Uint32(v) { - case 0: - tv, ok := value.(AuthenticatedMessageV0) - if !ok { - err = fmt.Errorf("invalid value, must be AuthenticatedMessageV0") - return - } - result.V0 = &tv + if err = s.SurveyedPeerId.EncodeTo(e); err != nil { + return err } - return + if err = s.LedgerNum.EncodeTo(e); err != nil { + return err + } + if err = s.CommandType.EncodeTo(e); err != nil { + return err + } + if err = s.EncryptedBody.EncodeTo(e); err != nil { + return err + } + return nil } -// MustV0 retrieves the V0 value from the union, -// panicing if the value is not set. -func (u AuthenticatedMessage) MustV0() AuthenticatedMessageV0 { - val, ok := u.GetV0() +var _ decoderFrom = (*SurveyResponseMessage)(nil) - if !ok { - panic("arm V0 is not set") +// DecodeFrom decodes this value using the Decoder. +func (s *SurveyResponseMessage) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding SurveyResponseMessage: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + var err error + var n, nTmp int + nTmp, err = s.SurveyorPeerId.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding NodeId: %w", err) + } + nTmp, err = s.SurveyedPeerId.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding NodeId: %w", err) + } + nTmp, err = s.LedgerNum.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Uint32: %w", err) + } + nTmp, err = s.CommandType.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding SurveyMessageCommandType: %w", err) + } + nTmp, err = s.EncryptedBody.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding EncryptedBody: %w", err) } + return n, nil +} - return val +// MarshalBinary implements encoding.BinaryMarshaler. +func (s SurveyResponseMessage) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err } -// GetV0 retrieves the V0 value from the union, -// returning ok if the union's switch indicated the value is valid. -func (u AuthenticatedMessage) GetV0() (result AuthenticatedMessageV0, ok bool) { - armName, _ := u.ArmForSwitch(int32(u.V)) +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *SurveyResponseMessage) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} - if armName == "V0" { - result = *u.V0 - ok = true - } +var ( + _ encoding.BinaryMarshaler = (*SurveyResponseMessage)(nil) + _ encoding.BinaryUnmarshaler = (*SurveyResponseMessage)(nil) +) - return +// xdrType signals that this type represents XDR values defined by this package. +func (s SurveyResponseMessage) xdrType() {} + +var _ xdrType = (*SurveyResponseMessage)(nil) + +// SignedSurveyResponseMessage is an XDR Struct defines as: +// +// struct SignedSurveyResponseMessage +// { +// Signature responseSignature; +// SurveyResponseMessage response; +// }; +type SignedSurveyResponseMessage struct { + ResponseSignature Signature + Response SurveyResponseMessage } // EncodeTo encodes this value using the Encoder. -func (u AuthenticatedMessage) EncodeTo(e *xdr.Encoder) error { +func (s *SignedSurveyResponseMessage) EncodeTo(e *xdr.Encoder) error { var err error - if err = u.V.EncodeTo(e); err != nil { + if err = s.ResponseSignature.EncodeTo(e); err != nil { return err } - switch Uint32(u.V) { - case 0: - if err = (*u.V0).EncodeTo(e); err != nil { - return err - } - return nil + if err = s.Response.EncodeTo(e); err != nil { + return err } - return fmt.Errorf("V (Uint32) switch value '%d' is not valid for union AuthenticatedMessage", u.V) + return nil } -var _ decoderFrom = (*AuthenticatedMessage)(nil) +var _ decoderFrom = (*SignedSurveyResponseMessage)(nil) // DecodeFrom decodes this value using the Decoder. -func (u *AuthenticatedMessage) DecodeFrom(d *xdr.Decoder) (int, error) { +func (s *SignedSurveyResponseMessage) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding SignedSurveyResponseMessage: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = u.V.DecodeFrom(d) + nTmp, err = s.ResponseSignature.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Uint32: %s", err) + return n, fmt.Errorf("decoding Signature: %w", err) } - switch Uint32(u.V) { - case 0: - u.V0 = new(AuthenticatedMessageV0) - nTmp, err = (*u.V0).DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding AuthenticatedMessageV0: %s", err) - } - return n, nil + nTmp, err = s.Response.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding SurveyResponseMessage: %w", err) } - return n, fmt.Errorf("union AuthenticatedMessage has invalid V (Uint32) switch value '%d'", u.V) + return n, nil } // MarshalBinary implements encoding.BinaryMarshaler. -func (s AuthenticatedMessage) MarshalBinary() ([]byte, error) { +func (s SignedSurveyResponseMessage) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -18065,134 +19605,294 @@ func (s AuthenticatedMessage) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *AuthenticatedMessage) UnmarshalBinary(inp []byte) error { +func (s *SignedSurveyResponseMessage) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*AuthenticatedMessage)(nil) - _ encoding.BinaryUnmarshaler = (*AuthenticatedMessage)(nil) + _ encoding.BinaryMarshaler = (*SignedSurveyResponseMessage)(nil) + _ encoding.BinaryUnmarshaler = (*SignedSurveyResponseMessage)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s AuthenticatedMessage) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s SignedSurveyResponseMessage) xdrType() {} -var _ xdrType = (*AuthenticatedMessage)(nil) +var _ xdrType = (*SignedSurveyResponseMessage)(nil) -// LiquidityPoolParameters is an XDR Union defines as: +// PeerStats is an XDR Struct defines as: // -// union LiquidityPoolParameters switch (LiquidityPoolType type) +// struct PeerStats // { -// case LIQUIDITY_POOL_CONSTANT_PRODUCT: -// LiquidityPoolConstantProductParameters constantProduct; +// NodeID id; +// string versionStr<100>; +// uint64 messagesRead; +// uint64 messagesWritten; +// uint64 bytesRead; +// uint64 bytesWritten; +// uint64 secondsConnected; +// +// uint64 uniqueFloodBytesRecv; +// uint64 duplicateFloodBytesRecv; +// uint64 uniqueFetchBytesRecv; +// uint64 duplicateFetchBytesRecv; +// +// uint64 uniqueFloodMessageRecv; +// uint64 duplicateFloodMessageRecv; +// uint64 uniqueFetchMessageRecv; +// uint64 duplicateFetchMessageRecv; // }; -type LiquidityPoolParameters struct { - Type LiquidityPoolType - ConstantProduct *LiquidityPoolConstantProductParameters +type PeerStats struct { + Id NodeId + VersionStr string `xdrmaxsize:"100"` + MessagesRead Uint64 + MessagesWritten Uint64 + BytesRead Uint64 + BytesWritten Uint64 + SecondsConnected Uint64 + UniqueFloodBytesRecv Uint64 + DuplicateFloodBytesRecv Uint64 + UniqueFetchBytesRecv Uint64 + DuplicateFetchBytesRecv Uint64 + UniqueFloodMessageRecv Uint64 + DuplicateFloodMessageRecv Uint64 + UniqueFetchMessageRecv Uint64 + DuplicateFetchMessageRecv Uint64 } -// SwitchFieldName returns the field name in which this union's -// discriminant is stored -func (u LiquidityPoolParameters) SwitchFieldName() string { - return "Type" +// EncodeTo encodes this value using the Encoder. +func (s *PeerStats) EncodeTo(e *xdr.Encoder) error { + var err error + if err = s.Id.EncodeTo(e); err != nil { + return err + } + if _, err = e.EncodeString(string(s.VersionStr)); err != nil { + return err + } + if err = s.MessagesRead.EncodeTo(e); err != nil { + return err + } + if err = s.MessagesWritten.EncodeTo(e); err != nil { + return err + } + if err = s.BytesRead.EncodeTo(e); err != nil { + return err + } + if err = s.BytesWritten.EncodeTo(e); err != nil { + return err + } + if err = s.SecondsConnected.EncodeTo(e); err != nil { + return err + } + if err = s.UniqueFloodBytesRecv.EncodeTo(e); err != nil { + return err + } + if err = s.DuplicateFloodBytesRecv.EncodeTo(e); err != nil { + return err + } + if err = s.UniqueFetchBytesRecv.EncodeTo(e); err != nil { + return err + } + if err = s.DuplicateFetchBytesRecv.EncodeTo(e); err != nil { + return err + } + if err = s.UniqueFloodMessageRecv.EncodeTo(e); err != nil { + return err + } + if err = s.DuplicateFloodMessageRecv.EncodeTo(e); err != nil { + return err + } + if err = s.UniqueFetchMessageRecv.EncodeTo(e); err != nil { + return err + } + if err = s.DuplicateFetchMessageRecv.EncodeTo(e); err != nil { + return err + } + return nil } -// ArmForSwitch returns which field name should be used for storing -// the value for an instance of LiquidityPoolParameters -func (u LiquidityPoolParameters) ArmForSwitch(sw int32) (string, bool) { - switch LiquidityPoolType(sw) { - case LiquidityPoolTypeLiquidityPoolConstantProduct: - return "ConstantProduct", true +var _ decoderFrom = (*PeerStats)(nil) + +// DecodeFrom decodes this value using the Decoder. +func (s *PeerStats) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding PeerStats: %w", ErrMaxDecodingDepthReached) } - return "-", false + maxDepth -= 1 + var err error + var n, nTmp int + nTmp, err = s.Id.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding NodeId: %w", err) + } + s.VersionStr, nTmp, err = d.DecodeString(100) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding VersionStr: %w", err) + } + nTmp, err = s.MessagesRead.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Uint64: %w", err) + } + nTmp, err = s.MessagesWritten.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Uint64: %w", err) + } + nTmp, err = s.BytesRead.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Uint64: %w", err) + } + nTmp, err = s.BytesWritten.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Uint64: %w", err) + } + nTmp, err = s.SecondsConnected.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Uint64: %w", err) + } + nTmp, err = s.UniqueFloodBytesRecv.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Uint64: %w", err) + } + nTmp, err = s.DuplicateFloodBytesRecv.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Uint64: %w", err) + } + nTmp, err = s.UniqueFetchBytesRecv.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Uint64: %w", err) + } + nTmp, err = s.DuplicateFetchBytesRecv.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Uint64: %w", err) + } + nTmp, err = s.UniqueFloodMessageRecv.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Uint64: %w", err) + } + nTmp, err = s.DuplicateFloodMessageRecv.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Uint64: %w", err) + } + nTmp, err = s.UniqueFetchMessageRecv.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Uint64: %w", err) + } + nTmp, err = s.DuplicateFetchMessageRecv.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Uint64: %w", err) + } + return n, nil } -// NewLiquidityPoolParameters creates a new LiquidityPoolParameters. -func NewLiquidityPoolParameters(aType LiquidityPoolType, value interface{}) (result LiquidityPoolParameters, err error) { - result.Type = aType - switch LiquidityPoolType(aType) { - case LiquidityPoolTypeLiquidityPoolConstantProduct: - tv, ok := value.(LiquidityPoolConstantProductParameters) - if !ok { - err = fmt.Errorf("invalid value, must be LiquidityPoolConstantProductParameters") - return - } - result.ConstantProduct = &tv - } - return +// MarshalBinary implements encoding.BinaryMarshaler. +func (s PeerStats) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err } -// MustConstantProduct retrieves the ConstantProduct value from the union, -// panicing if the value is not set. -func (u LiquidityPoolParameters) MustConstantProduct() LiquidityPoolConstantProductParameters { - val, ok := u.GetConstantProduct() +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *PeerStats) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} - if !ok { - panic("arm ConstantProduct is not set") - } +var ( + _ encoding.BinaryMarshaler = (*PeerStats)(nil) + _ encoding.BinaryUnmarshaler = (*PeerStats)(nil) +) - return val -} +// xdrType signals that this type represents XDR values defined by this package. +func (s PeerStats) xdrType() {} -// GetConstantProduct retrieves the ConstantProduct value from the union, -// returning ok if the union's switch indicated the value is valid. -func (u LiquidityPoolParameters) GetConstantProduct() (result LiquidityPoolConstantProductParameters, ok bool) { - armName, _ := u.ArmForSwitch(int32(u.Type)) +var _ xdrType = (*PeerStats)(nil) - if armName == "ConstantProduct" { - result = *u.ConstantProduct - ok = true - } +// PeerStatList is an XDR Typedef defines as: +// +// typedef PeerStats PeerStatList<25>; +type PeerStatList []PeerStats - return +// XDRMaxSize implements the Sized interface for PeerStatList +func (e PeerStatList) XDRMaxSize() int { + return 25 } // EncodeTo encodes this value using the Encoder. -func (u LiquidityPoolParameters) EncodeTo(e *xdr.Encoder) error { +func (s PeerStatList) EncodeTo(e *xdr.Encoder) error { var err error - if err = u.Type.EncodeTo(e); err != nil { + if _, err = e.EncodeUint(uint32(len(s))); err != nil { return err } - switch LiquidityPoolType(u.Type) { - case LiquidityPoolTypeLiquidityPoolConstantProduct: - if err = (*u.ConstantProduct).EncodeTo(e); err != nil { + for i := 0; i < len(s); i++ { + if err = s[i].EncodeTo(e); err != nil { return err } - return nil } - return fmt.Errorf("Type (LiquidityPoolType) switch value '%d' is not valid for union LiquidityPoolParameters", u.Type) + return nil } -var _ decoderFrom = (*LiquidityPoolParameters)(nil) +var _ decoderFrom = (*PeerStatList)(nil) // DecodeFrom decodes this value using the Decoder. -func (u *LiquidityPoolParameters) DecodeFrom(d *xdr.Decoder) (int, error) { +func (s *PeerStatList) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding PeerStatList: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = u.Type.DecodeFrom(d) + var l uint32 + l, nTmp, err = d.DecodeUint() n += nTmp if err != nil { - return n, fmt.Errorf("decoding LiquidityPoolType: %s", err) + return n, fmt.Errorf("decoding PeerStats: %w", err) } - switch LiquidityPoolType(u.Type) { - case LiquidityPoolTypeLiquidityPoolConstantProduct: - u.ConstantProduct = new(LiquidityPoolConstantProductParameters) - nTmp, err = (*u.ConstantProduct).DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding LiquidityPoolConstantProductParameters: %s", err) + if l > 25 { + return n, fmt.Errorf("decoding PeerStats: data size (%d) exceeds size limit (25)", l) + } + (*s) = nil + if l > 0 { + if il, ok := d.InputLen(); ok && uint(il) < uint(l) { + return n, fmt.Errorf("decoding PeerStats: length (%d) exceeds remaining input length (%d)", l, il) + } + (*s) = make([]PeerStats, l) + for i := uint32(0); i < l; i++ { + nTmp, err = (*s)[i].DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding PeerStats: %w", err) + } } - return n, nil } - return n, fmt.Errorf("union LiquidityPoolParameters has invalid Type (LiquidityPoolType) switch value '%d'", u.Type) + return n, nil } // MarshalBinary implements encoding.BinaryMarshaler. -func (s LiquidityPoolParameters) MarshalBinary() ([]byte, error) { +func (s PeerStatList) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -18200,69 +19900,95 @@ func (s LiquidityPoolParameters) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *LiquidityPoolParameters) UnmarshalBinary(inp []byte) error { +func (s *PeerStatList) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*LiquidityPoolParameters)(nil) - _ encoding.BinaryUnmarshaler = (*LiquidityPoolParameters)(nil) + _ encoding.BinaryMarshaler = (*PeerStatList)(nil) + _ encoding.BinaryUnmarshaler = (*PeerStatList)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s LiquidityPoolParameters) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s PeerStatList) xdrType() {} -var _ xdrType = (*LiquidityPoolParameters)(nil) +var _ xdrType = (*PeerStatList)(nil) -// MuxedAccountMed25519 is an XDR NestedStruct defines as: +// TopologyResponseBodyV0 is an XDR Struct defines as: // -// struct -// { -// uint64 id; -// uint256 ed25519; -// } -type MuxedAccountMed25519 struct { - Id Uint64 - Ed25519 Uint256 +// struct TopologyResponseBodyV0 +// { +// PeerStatList inboundPeers; +// PeerStatList outboundPeers; +// +// uint32 totalInboundPeerCount; +// uint32 totalOutboundPeerCount; +// }; +type TopologyResponseBodyV0 struct { + InboundPeers PeerStatList + OutboundPeers PeerStatList + TotalInboundPeerCount Uint32 + TotalOutboundPeerCount Uint32 } // EncodeTo encodes this value using the Encoder. -func (s *MuxedAccountMed25519) EncodeTo(e *xdr.Encoder) error { +func (s *TopologyResponseBodyV0) EncodeTo(e *xdr.Encoder) error { var err error - if err = s.Id.EncodeTo(e); err != nil { + if err = s.InboundPeers.EncodeTo(e); err != nil { return err } - if err = s.Ed25519.EncodeTo(e); err != nil { + if err = s.OutboundPeers.EncodeTo(e); err != nil { + return err + } + if err = s.TotalInboundPeerCount.EncodeTo(e); err != nil { + return err + } + if err = s.TotalOutboundPeerCount.EncodeTo(e); err != nil { return err } return nil } -var _ decoderFrom = (*MuxedAccountMed25519)(nil) +var _ decoderFrom = (*TopologyResponseBodyV0)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *MuxedAccountMed25519) DecodeFrom(d *xdr.Decoder) (int, error) { +func (s *TopologyResponseBodyV0) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding TopologyResponseBodyV0: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = s.Id.DecodeFrom(d) + nTmp, err = s.InboundPeers.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding PeerStatList: %w", err) + } + nTmp, err = s.OutboundPeers.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding PeerStatList: %w", err) + } + nTmp, err = s.TotalInboundPeerCount.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Uint64: %s", err) + return n, fmt.Errorf("decoding Uint32: %w", err) } - nTmp, err = s.Ed25519.DecodeFrom(d) + nTmp, err = s.TotalOutboundPeerCount.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Uint256: %s", err) + return n, fmt.Errorf("decoding Uint32: %w", err) } return n, nil } // MarshalBinary implements encoding.BinaryMarshaler. -func (s MuxedAccountMed25519) MarshalBinary() ([]byte, error) { +func (s TopologyResponseBodyV0) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -18270,127 +19996,241 @@ func (s MuxedAccountMed25519) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *MuxedAccountMed25519) UnmarshalBinary(inp []byte) error { +func (s *TopologyResponseBodyV0) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*MuxedAccountMed25519)(nil) - _ encoding.BinaryUnmarshaler = (*MuxedAccountMed25519)(nil) + _ encoding.BinaryMarshaler = (*TopologyResponseBodyV0)(nil) + _ encoding.BinaryUnmarshaler = (*TopologyResponseBodyV0)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s MuxedAccountMed25519) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s TopologyResponseBodyV0) xdrType() {} -var _ xdrType = (*MuxedAccountMed25519)(nil) +var _ xdrType = (*TopologyResponseBodyV0)(nil) -// MuxedAccount is an XDR Union defines as: +// TopologyResponseBodyV1 is an XDR Struct defines as: // -// union MuxedAccount switch (CryptoKeyType type) +// struct TopologyResponseBodyV1 // { -// case KEY_TYPE_ED25519: -// uint256 ed25519; -// case KEY_TYPE_MUXED_ED25519: -// struct -// { -// uint64 id; -// uint256 ed25519; -// } med25519; +// PeerStatList inboundPeers; +// PeerStatList outboundPeers; +// +// uint32 totalInboundPeerCount; +// uint32 totalOutboundPeerCount; +// +// uint32 maxInboundPeerCount; +// uint32 maxOutboundPeerCount; // }; -type MuxedAccount struct { - Type CryptoKeyType - Ed25519 *Uint256 - Med25519 *MuxedAccountMed25519 -} - -// SwitchFieldName returns the field name in which this union's -// discriminant is stored -func (u MuxedAccount) SwitchFieldName() string { - return "Type" +type TopologyResponseBodyV1 struct { + InboundPeers PeerStatList + OutboundPeers PeerStatList + TotalInboundPeerCount Uint32 + TotalOutboundPeerCount Uint32 + MaxInboundPeerCount Uint32 + MaxOutboundPeerCount Uint32 +} + +// EncodeTo encodes this value using the Encoder. +func (s *TopologyResponseBodyV1) EncodeTo(e *xdr.Encoder) error { + var err error + if err = s.InboundPeers.EncodeTo(e); err != nil { + return err + } + if err = s.OutboundPeers.EncodeTo(e); err != nil { + return err + } + if err = s.TotalInboundPeerCount.EncodeTo(e); err != nil { + return err + } + if err = s.TotalOutboundPeerCount.EncodeTo(e); err != nil { + return err + } + if err = s.MaxInboundPeerCount.EncodeTo(e); err != nil { + return err + } + if err = s.MaxOutboundPeerCount.EncodeTo(e); err != nil { + return err + } + return nil +} + +var _ decoderFrom = (*TopologyResponseBodyV1)(nil) + +// DecodeFrom decodes this value using the Decoder. +func (s *TopologyResponseBodyV1) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding TopologyResponseBodyV1: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + var err error + var n, nTmp int + nTmp, err = s.InboundPeers.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding PeerStatList: %w", err) + } + nTmp, err = s.OutboundPeers.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding PeerStatList: %w", err) + } + nTmp, err = s.TotalInboundPeerCount.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Uint32: %w", err) + } + nTmp, err = s.TotalOutboundPeerCount.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Uint32: %w", err) + } + nTmp, err = s.MaxInboundPeerCount.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Uint32: %w", err) + } + nTmp, err = s.MaxOutboundPeerCount.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Uint32: %w", err) + } + return n, nil +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (s TopologyResponseBodyV1) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *TopologyResponseBodyV1) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} + +var ( + _ encoding.BinaryMarshaler = (*TopologyResponseBodyV1)(nil) + _ encoding.BinaryUnmarshaler = (*TopologyResponseBodyV1)(nil) +) + +// xdrType signals that this type represents XDR values defined by this package. +func (s TopologyResponseBodyV1) xdrType() {} + +var _ xdrType = (*TopologyResponseBodyV1)(nil) + +// SurveyResponseBody is an XDR Union defines as: +// +// union SurveyResponseBody switch (SurveyMessageResponseType type) +// { +// case SURVEY_TOPOLOGY_RESPONSE_V0: +// TopologyResponseBodyV0 topologyResponseBodyV0; +// case SURVEY_TOPOLOGY_RESPONSE_V1: +// TopologyResponseBodyV1 topologyResponseBodyV1; +// }; +type SurveyResponseBody struct { + Type SurveyMessageResponseType + TopologyResponseBodyV0 *TopologyResponseBodyV0 + TopologyResponseBodyV1 *TopologyResponseBodyV1 +} + +// SwitchFieldName returns the field name in which this union's +// discriminant is stored +func (u SurveyResponseBody) SwitchFieldName() string { + return "Type" } // ArmForSwitch returns which field name should be used for storing -// the value for an instance of MuxedAccount -func (u MuxedAccount) ArmForSwitch(sw int32) (string, bool) { - switch CryptoKeyType(sw) { - case CryptoKeyTypeKeyTypeEd25519: - return "Ed25519", true - case CryptoKeyTypeKeyTypeMuxedEd25519: - return "Med25519", true +// the value for an instance of SurveyResponseBody +func (u SurveyResponseBody) ArmForSwitch(sw int32) (string, bool) { + switch SurveyMessageResponseType(sw) { + case SurveyMessageResponseTypeSurveyTopologyResponseV0: + return "TopologyResponseBodyV0", true + case SurveyMessageResponseTypeSurveyTopologyResponseV1: + return "TopologyResponseBodyV1", true } return "-", false } -// NewMuxedAccount creates a new MuxedAccount. -func NewMuxedAccount(aType CryptoKeyType, value interface{}) (result MuxedAccount, err error) { +// NewSurveyResponseBody creates a new SurveyResponseBody. +func NewSurveyResponseBody(aType SurveyMessageResponseType, value interface{}) (result SurveyResponseBody, err error) { result.Type = aType - switch CryptoKeyType(aType) { - case CryptoKeyTypeKeyTypeEd25519: - tv, ok := value.(Uint256) + switch SurveyMessageResponseType(aType) { + case SurveyMessageResponseTypeSurveyTopologyResponseV0: + tv, ok := value.(TopologyResponseBodyV0) if !ok { - err = fmt.Errorf("invalid value, must be Uint256") + err = errors.New("invalid value, must be TopologyResponseBodyV0") return } - result.Ed25519 = &tv - case CryptoKeyTypeKeyTypeMuxedEd25519: - tv, ok := value.(MuxedAccountMed25519) + result.TopologyResponseBodyV0 = &tv + case SurveyMessageResponseTypeSurveyTopologyResponseV1: + tv, ok := value.(TopologyResponseBodyV1) if !ok { - err = fmt.Errorf("invalid value, must be MuxedAccountMed25519") + err = errors.New("invalid value, must be TopologyResponseBodyV1") return } - result.Med25519 = &tv + result.TopologyResponseBodyV1 = &tv } return } -// MustEd25519 retrieves the Ed25519 value from the union, +// MustTopologyResponseBodyV0 retrieves the TopologyResponseBodyV0 value from the union, // panicing if the value is not set. -func (u MuxedAccount) MustEd25519() Uint256 { - val, ok := u.GetEd25519() +func (u SurveyResponseBody) MustTopologyResponseBodyV0() TopologyResponseBodyV0 { + val, ok := u.GetTopologyResponseBodyV0() if !ok { - panic("arm Ed25519 is not set") + panic("arm TopologyResponseBodyV0 is not set") } return val } -// GetEd25519 retrieves the Ed25519 value from the union, +// GetTopologyResponseBodyV0 retrieves the TopologyResponseBodyV0 value from the union, // returning ok if the union's switch indicated the value is valid. -func (u MuxedAccount) GetEd25519() (result Uint256, ok bool) { +func (u SurveyResponseBody) GetTopologyResponseBodyV0() (result TopologyResponseBodyV0, ok bool) { armName, _ := u.ArmForSwitch(int32(u.Type)) - if armName == "Ed25519" { - result = *u.Ed25519 + if armName == "TopologyResponseBodyV0" { + result = *u.TopologyResponseBodyV0 ok = true } return } -// MustMed25519 retrieves the Med25519 value from the union, +// MustTopologyResponseBodyV1 retrieves the TopologyResponseBodyV1 value from the union, // panicing if the value is not set. -func (u MuxedAccount) MustMed25519() MuxedAccountMed25519 { - val, ok := u.GetMed25519() +func (u SurveyResponseBody) MustTopologyResponseBodyV1() TopologyResponseBodyV1 { + val, ok := u.GetTopologyResponseBodyV1() if !ok { - panic("arm Med25519 is not set") + panic("arm TopologyResponseBodyV1 is not set") } return val } -// GetMed25519 retrieves the Med25519 value from the union, +// GetTopologyResponseBodyV1 retrieves the TopologyResponseBodyV1 value from the union, // returning ok if the union's switch indicated the value is valid. -func (u MuxedAccount) GetMed25519() (result MuxedAccountMed25519, ok bool) { +func (u SurveyResponseBody) GetTopologyResponseBodyV1() (result TopologyResponseBodyV1, ok bool) { armName, _ := u.ArmForSwitch(int32(u.Type)) - if armName == "Med25519" { - result = *u.Med25519 + if armName == "TopologyResponseBodyV1" { + result = *u.TopologyResponseBodyV1 ok = true } @@ -18398,60 +20238,64 @@ func (u MuxedAccount) GetMed25519() (result MuxedAccountMed25519, ok bool) { } // EncodeTo encodes this value using the Encoder. -func (u MuxedAccount) EncodeTo(e *xdr.Encoder) error { +func (u SurveyResponseBody) EncodeTo(e *xdr.Encoder) error { var err error if err = u.Type.EncodeTo(e); err != nil { return err } - switch CryptoKeyType(u.Type) { - case CryptoKeyTypeKeyTypeEd25519: - if err = (*u.Ed25519).EncodeTo(e); err != nil { + switch SurveyMessageResponseType(u.Type) { + case SurveyMessageResponseTypeSurveyTopologyResponseV0: + if err = (*u.TopologyResponseBodyV0).EncodeTo(e); err != nil { return err } return nil - case CryptoKeyTypeKeyTypeMuxedEd25519: - if err = (*u.Med25519).EncodeTo(e); err != nil { + case SurveyMessageResponseTypeSurveyTopologyResponseV1: + if err = (*u.TopologyResponseBodyV1).EncodeTo(e); err != nil { return err } return nil } - return fmt.Errorf("Type (CryptoKeyType) switch value '%d' is not valid for union MuxedAccount", u.Type) + return fmt.Errorf("Type (SurveyMessageResponseType) switch value '%d' is not valid for union SurveyResponseBody", u.Type) } -var _ decoderFrom = (*MuxedAccount)(nil) +var _ decoderFrom = (*SurveyResponseBody)(nil) // DecodeFrom decodes this value using the Decoder. -func (u *MuxedAccount) DecodeFrom(d *xdr.Decoder) (int, error) { +func (u *SurveyResponseBody) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding SurveyResponseBody: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = u.Type.DecodeFrom(d) + nTmp, err = u.Type.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding CryptoKeyType: %s", err) + return n, fmt.Errorf("decoding SurveyMessageResponseType: %w", err) } - switch CryptoKeyType(u.Type) { - case CryptoKeyTypeKeyTypeEd25519: - u.Ed25519 = new(Uint256) - nTmp, err = (*u.Ed25519).DecodeFrom(d) + switch SurveyMessageResponseType(u.Type) { + case SurveyMessageResponseTypeSurveyTopologyResponseV0: + u.TopologyResponseBodyV0 = new(TopologyResponseBodyV0) + nTmp, err = (*u.TopologyResponseBodyV0).DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Uint256: %s", err) + return n, fmt.Errorf("decoding TopologyResponseBodyV0: %w", err) } return n, nil - case CryptoKeyTypeKeyTypeMuxedEd25519: - u.Med25519 = new(MuxedAccountMed25519) - nTmp, err = (*u.Med25519).DecodeFrom(d) + case SurveyMessageResponseTypeSurveyTopologyResponseV1: + u.TopologyResponseBodyV1 = new(TopologyResponseBodyV1) + nTmp, err = (*u.TopologyResponseBodyV1).DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding MuxedAccountMed25519: %s", err) + return n, fmt.Errorf("decoding TopologyResponseBodyV1: %w", err) } return n, nil } - return n, fmt.Errorf("union MuxedAccount has invalid Type (CryptoKeyType) switch value '%d'", u.Type) + return n, fmt.Errorf("union SurveyResponseBody has invalid Type (SurveyMessageResponseType) switch value '%d'", u.Type) } // MarshalBinary implements encoding.BinaryMarshaler. -func (s MuxedAccount) MarshalBinary() ([]byte, error) { +func (s SurveyResponseBody) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -18459,218 +20303,92 @@ func (s MuxedAccount) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *MuxedAccount) UnmarshalBinary(inp []byte) error { +func (s *SurveyResponseBody) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*MuxedAccount)(nil) - _ encoding.BinaryUnmarshaler = (*MuxedAccount)(nil) + _ encoding.BinaryMarshaler = (*SurveyResponseBody)(nil) + _ encoding.BinaryUnmarshaler = (*SurveyResponseBody)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s MuxedAccount) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s SurveyResponseBody) xdrType() {} -var _ xdrType = (*MuxedAccount)(nil) +var _ xdrType = (*SurveyResponseBody)(nil) -// DecoratedSignature is an XDR Struct defines as: +// TxAdvertVectorMaxSize is an XDR Const defines as: // -// struct DecoratedSignature -// { -// SignatureHint hint; // last 4 bytes of the public key, used as a hint -// Signature signature; // actual signature -// }; -type DecoratedSignature struct { - Hint SignatureHint - Signature Signature +// const TX_ADVERT_VECTOR_MAX_SIZE = 1000; +const TxAdvertVectorMaxSize = 1000 + +// TxAdvertVector is an XDR Typedef defines as: +// +// typedef Hash TxAdvertVector; +type TxAdvertVector []Hash + +// XDRMaxSize implements the Sized interface for TxAdvertVector +func (e TxAdvertVector) XDRMaxSize() int { + return 1000 } // EncodeTo encodes this value using the Encoder. -func (s *DecoratedSignature) EncodeTo(e *xdr.Encoder) error { +func (s TxAdvertVector) EncodeTo(e *xdr.Encoder) error { var err error - if err = s.Hint.EncodeTo(e); err != nil { + if _, err = e.EncodeUint(uint32(len(s))); err != nil { return err } - if err = s.Signature.EncodeTo(e); err != nil { - return err + for i := 0; i < len(s); i++ { + if err = s[i].EncodeTo(e); err != nil { + return err + } } return nil } -var _ decoderFrom = (*DecoratedSignature)(nil) +var _ decoderFrom = (*TxAdvertVector)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *DecoratedSignature) DecodeFrom(d *xdr.Decoder) (int, error) { +func (s *TxAdvertVector) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding TxAdvertVector: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = s.Hint.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding SignatureHint: %s", err) - } - nTmp, err = s.Signature.DecodeFrom(d) + var l uint32 + l, nTmp, err = d.DecodeUint() n += nTmp if err != nil { - return n, fmt.Errorf("decoding Signature: %s", err) - } - return n, nil -} - -// MarshalBinary implements encoding.BinaryMarshaler. -func (s DecoratedSignature) MarshalBinary() ([]byte, error) { - b := bytes.Buffer{} - e := xdr.NewEncoder(&b) - err := s.EncodeTo(e) - return b.Bytes(), err -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *DecoratedSignature) UnmarshalBinary(inp []byte) error { - r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) - return err -} - -var ( - _ encoding.BinaryMarshaler = (*DecoratedSignature)(nil) - _ encoding.BinaryUnmarshaler = (*DecoratedSignature)(nil) -) - -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s DecoratedSignature) xdrType() {} - -var _ xdrType = (*DecoratedSignature)(nil) - -// OperationType is an XDR Enum defines as: -// -// enum OperationType -// { -// CREATE_ACCOUNT = 0, -// PAYMENT = 1, -// PATH_PAYMENT_STRICT_RECEIVE = 2, -// MANAGE_SELL_OFFER = 3, -// CREATE_PASSIVE_SELL_OFFER = 4, -// SET_OPTIONS = 5, -// CHANGE_TRUST = 6, -// ALLOW_TRUST = 7, -// ACCOUNT_MERGE = 8, -// INFLATION = 9, -// MANAGE_DATA = 10, -// BUMP_SEQUENCE = 11, -// MANAGE_BUY_OFFER = 12, -// PATH_PAYMENT_STRICT_SEND = 13, -// CREATE_CLAIMABLE_BALANCE = 14, -// CLAIM_CLAIMABLE_BALANCE = 15, -// BEGIN_SPONSORING_FUTURE_RESERVES = 16, -// END_SPONSORING_FUTURE_RESERVES = 17, -// REVOKE_SPONSORSHIP = 18, -// CLAWBACK = 19, -// CLAWBACK_CLAIMABLE_BALANCE = 20, -// SET_TRUST_LINE_FLAGS = 21, -// LIQUIDITY_POOL_DEPOSIT = 22, -// LIQUIDITY_POOL_WITHDRAW = 23 -// }; -type OperationType int32 - -const ( - OperationTypeCreateAccount OperationType = 0 - OperationTypePayment OperationType = 1 - OperationTypePathPaymentStrictReceive OperationType = 2 - OperationTypeManageSellOffer OperationType = 3 - OperationTypeCreatePassiveSellOffer OperationType = 4 - OperationTypeSetOptions OperationType = 5 - OperationTypeChangeTrust OperationType = 6 - OperationTypeAllowTrust OperationType = 7 - OperationTypeAccountMerge OperationType = 8 - OperationTypeInflation OperationType = 9 - OperationTypeManageData OperationType = 10 - OperationTypeBumpSequence OperationType = 11 - OperationTypeManageBuyOffer OperationType = 12 - OperationTypePathPaymentStrictSend OperationType = 13 - OperationTypeCreateClaimableBalance OperationType = 14 - OperationTypeClaimClaimableBalance OperationType = 15 - OperationTypeBeginSponsoringFutureReserves OperationType = 16 - OperationTypeEndSponsoringFutureReserves OperationType = 17 - OperationTypeRevokeSponsorship OperationType = 18 - OperationTypeClawback OperationType = 19 - OperationTypeClawbackClaimableBalance OperationType = 20 - OperationTypeSetTrustLineFlags OperationType = 21 - OperationTypeLiquidityPoolDeposit OperationType = 22 - OperationTypeLiquidityPoolWithdraw OperationType = 23 -) - -var operationTypeMap = map[int32]string{ - 0: "OperationTypeCreateAccount", - 1: "OperationTypePayment", - 2: "OperationTypePathPaymentStrictReceive", - 3: "OperationTypeManageSellOffer", - 4: "OperationTypeCreatePassiveSellOffer", - 5: "OperationTypeSetOptions", - 6: "OperationTypeChangeTrust", - 7: "OperationTypeAllowTrust", - 8: "OperationTypeAccountMerge", - 9: "OperationTypeInflation", - 10: "OperationTypeManageData", - 11: "OperationTypeBumpSequence", - 12: "OperationTypeManageBuyOffer", - 13: "OperationTypePathPaymentStrictSend", - 14: "OperationTypeCreateClaimableBalance", - 15: "OperationTypeClaimClaimableBalance", - 16: "OperationTypeBeginSponsoringFutureReserves", - 17: "OperationTypeEndSponsoringFutureReserves", - 18: "OperationTypeRevokeSponsorship", - 19: "OperationTypeClawback", - 20: "OperationTypeClawbackClaimableBalance", - 21: "OperationTypeSetTrustLineFlags", - 22: "OperationTypeLiquidityPoolDeposit", - 23: "OperationTypeLiquidityPoolWithdraw", -} - -// ValidEnum validates a proposed value for this enum. Implements -// the Enum interface for OperationType -func (e OperationType) ValidEnum(v int32) bool { - _, ok := operationTypeMap[v] - return ok -} - -// String returns the name of `e` -func (e OperationType) String() string { - name, _ := operationTypeMap[int32(e)] - return name -} - -// EncodeTo encodes this value using the Encoder. -func (e OperationType) EncodeTo(enc *xdr.Encoder) error { - if _, ok := operationTypeMap[int32(e)]; !ok { - return fmt.Errorf("'%d' is not a valid OperationType enum value", e) + return n, fmt.Errorf("decoding Hash: %w", err) } - _, err := enc.EncodeInt(int32(e)) - return err -} - -var _ decoderFrom = (*OperationType)(nil) - -// DecodeFrom decodes this value using the Decoder. -func (e *OperationType) DecodeFrom(d *xdr.Decoder) (int, error) { - v, n, err := d.DecodeInt() - if err != nil { - return n, fmt.Errorf("decoding OperationType: %s", err) + if l > 1000 { + return n, fmt.Errorf("decoding Hash: data size (%d) exceeds size limit (1000)", l) } - if _, ok := operationTypeMap[v]; !ok { - return n, fmt.Errorf("'%d' is not a valid OperationType enum value", v) + (*s) = nil + if l > 0 { + if il, ok := d.InputLen(); ok && uint(il) < uint(l) { + return n, fmt.Errorf("decoding Hash: length (%d) exceeds remaining input length (%d)", l, il) + } + (*s) = make([]Hash, l) + for i := uint32(0); i < l; i++ { + nTmp, err = (*s)[i].DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Hash: %w", err) + } + } } - *e = OperationType(v) return n, nil } // MarshalBinary implements encoding.BinaryMarshaler. -func (s OperationType) MarshalBinary() ([]byte, error) { +func (s TxAdvertVector) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -18678,69 +20396,64 @@ func (s OperationType) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *OperationType) UnmarshalBinary(inp []byte) error { +func (s *TxAdvertVector) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*OperationType)(nil) - _ encoding.BinaryUnmarshaler = (*OperationType)(nil) + _ encoding.BinaryMarshaler = (*TxAdvertVector)(nil) + _ encoding.BinaryUnmarshaler = (*TxAdvertVector)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s OperationType) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s TxAdvertVector) xdrType() {} -var _ xdrType = (*OperationType)(nil) +var _ xdrType = (*TxAdvertVector)(nil) -// CreateAccountOp is an XDR Struct defines as: +// FloodAdvert is an XDR Struct defines as: // -// struct CreateAccountOp +// struct FloodAdvert // { -// AccountID destination; // account to create -// int64 startingBalance; // amount they end up with +// TxAdvertVector txHashes; // }; -type CreateAccountOp struct { - Destination AccountId - StartingBalance Int64 +type FloodAdvert struct { + TxHashes TxAdvertVector } // EncodeTo encodes this value using the Encoder. -func (s *CreateAccountOp) EncodeTo(e *xdr.Encoder) error { +func (s *FloodAdvert) EncodeTo(e *xdr.Encoder) error { var err error - if err = s.Destination.EncodeTo(e); err != nil { - return err - } - if err = s.StartingBalance.EncodeTo(e); err != nil { + if err = s.TxHashes.EncodeTo(e); err != nil { return err } return nil } -var _ decoderFrom = (*CreateAccountOp)(nil) +var _ decoderFrom = (*FloodAdvert)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *CreateAccountOp) DecodeFrom(d *xdr.Decoder) (int, error) { +func (s *FloodAdvert) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding FloodAdvert: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = s.Destination.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding AccountId: %s", err) - } - nTmp, err = s.StartingBalance.DecodeFrom(d) + nTmp, err = s.TxHashes.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Int64: %s", err) + return n, fmt.Errorf("decoding TxAdvertVector: %w", err) } return n, nil } // MarshalBinary implements encoding.BinaryMarshaler. -func (s CreateAccountOp) MarshalBinary() ([]byte, error) { +func (s FloodAdvert) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -18748,79 +20461,92 @@ func (s CreateAccountOp) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *CreateAccountOp) UnmarshalBinary(inp []byte) error { +func (s *FloodAdvert) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*CreateAccountOp)(nil) - _ encoding.BinaryUnmarshaler = (*CreateAccountOp)(nil) + _ encoding.BinaryMarshaler = (*FloodAdvert)(nil) + _ encoding.BinaryUnmarshaler = (*FloodAdvert)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s CreateAccountOp) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s FloodAdvert) xdrType() {} -var _ xdrType = (*CreateAccountOp)(nil) +var _ xdrType = (*FloodAdvert)(nil) -// PaymentOp is an XDR Struct defines as: +// TxDemandVectorMaxSize is an XDR Const defines as: // -// struct PaymentOp -// { -// MuxedAccount destination; // recipient of the payment -// Asset asset; // what they end up with -// int64 amount; // amount they end up with -// }; -type PaymentOp struct { - Destination MuxedAccount - Asset Asset - Amount Int64 +// const TX_DEMAND_VECTOR_MAX_SIZE = 1000; +const TxDemandVectorMaxSize = 1000 + +// TxDemandVector is an XDR Typedef defines as: +// +// typedef Hash TxDemandVector; +type TxDemandVector []Hash + +// XDRMaxSize implements the Sized interface for TxDemandVector +func (e TxDemandVector) XDRMaxSize() int { + return 1000 } // EncodeTo encodes this value using the Encoder. -func (s *PaymentOp) EncodeTo(e *xdr.Encoder) error { +func (s TxDemandVector) EncodeTo(e *xdr.Encoder) error { var err error - if err = s.Destination.EncodeTo(e); err != nil { - return err - } - if err = s.Asset.EncodeTo(e); err != nil { + if _, err = e.EncodeUint(uint32(len(s))); err != nil { return err } - if err = s.Amount.EncodeTo(e); err != nil { - return err + for i := 0; i < len(s); i++ { + if err = s[i].EncodeTo(e); err != nil { + return err + } } return nil } -var _ decoderFrom = (*PaymentOp)(nil) +var _ decoderFrom = (*TxDemandVector)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *PaymentOp) DecodeFrom(d *xdr.Decoder) (int, error) { +func (s *TxDemandVector) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding TxDemandVector: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = s.Destination.DecodeFrom(d) + var l uint32 + l, nTmp, err = d.DecodeUint() n += nTmp if err != nil { - return n, fmt.Errorf("decoding MuxedAccount: %s", err) + return n, fmt.Errorf("decoding Hash: %w", err) } - nTmp, err = s.Asset.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Asset: %s", err) + if l > 1000 { + return n, fmt.Errorf("decoding Hash: data size (%d) exceeds size limit (1000)", l) } - nTmp, err = s.Amount.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Int64: %s", err) + (*s) = nil + if l > 0 { + if il, ok := d.InputLen(); ok && uint(il) < uint(l) { + return n, fmt.Errorf("decoding Hash: length (%d) exceeds remaining input length (%d)", l, il) + } + (*s) = make([]Hash, l) + for i := uint32(0); i < l; i++ { + nTmp, err = (*s)[i].DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Hash: %w", err) + } + } } return n, nil } // MarshalBinary implements encoding.BinaryMarshaler. -func (s PaymentOp) MarshalBinary() ([]byte, error) { +func (s TxDemandVector) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -18828,133 +20554,64 @@ func (s PaymentOp) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *PaymentOp) UnmarshalBinary(inp []byte) error { +func (s *TxDemandVector) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*PaymentOp)(nil) - _ encoding.BinaryUnmarshaler = (*PaymentOp)(nil) + _ encoding.BinaryMarshaler = (*TxDemandVector)(nil) + _ encoding.BinaryUnmarshaler = (*TxDemandVector)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s PaymentOp) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s TxDemandVector) xdrType() {} -var _ xdrType = (*PaymentOp)(nil) +var _ xdrType = (*TxDemandVector)(nil) -// PathPaymentStrictReceiveOp is an XDR Struct defines as: +// FloodDemand is an XDR Struct defines as: // -// struct PathPaymentStrictReceiveOp +// struct FloodDemand // { -// Asset sendAsset; // asset we pay with -// int64 sendMax; // the maximum amount of sendAsset to -// // send (excluding fees). -// // The operation will fail if can't be met -// -// MuxedAccount destination; // recipient of the payment -// Asset destAsset; // what they end up with -// int64 destAmount; // amount they end up with -// -// Asset path<5>; // additional hops it must go through to get there +// TxDemandVector txHashes; // }; -type PathPaymentStrictReceiveOp struct { - SendAsset Asset - SendMax Int64 - Destination MuxedAccount - DestAsset Asset - DestAmount Int64 - Path []Asset `xdrmaxsize:"5"` +type FloodDemand struct { + TxHashes TxDemandVector } // EncodeTo encodes this value using the Encoder. -func (s *PathPaymentStrictReceiveOp) EncodeTo(e *xdr.Encoder) error { +func (s *FloodDemand) EncodeTo(e *xdr.Encoder) error { var err error - if err = s.SendAsset.EncodeTo(e); err != nil { - return err - } - if err = s.SendMax.EncodeTo(e); err != nil { - return err - } - if err = s.Destination.EncodeTo(e); err != nil { - return err - } - if err = s.DestAsset.EncodeTo(e); err != nil { + if err = s.TxHashes.EncodeTo(e); err != nil { return err } - if err = s.DestAmount.EncodeTo(e); err != nil { - return err - } - if _, err = e.EncodeUint(uint32(len(s.Path))); err != nil { - return err - } - for i := 0; i < len(s.Path); i++ { - if err = s.Path[i].EncodeTo(e); err != nil { - return err - } - } return nil } -var _ decoderFrom = (*PathPaymentStrictReceiveOp)(nil) +var _ decoderFrom = (*FloodDemand)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *PathPaymentStrictReceiveOp) DecodeFrom(d *xdr.Decoder) (int, error) { +func (s *FloodDemand) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding FloodDemand: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = s.SendAsset.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Asset: %s", err) - } - nTmp, err = s.SendMax.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Int64: %s", err) - } - nTmp, err = s.Destination.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding MuxedAccount: %s", err) - } - nTmp, err = s.DestAsset.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Asset: %s", err) - } - nTmp, err = s.DestAmount.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Int64: %s", err) - } - var l uint32 - l, nTmp, err = d.DecodeUint() + nTmp, err = s.TxHashes.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Asset: %s", err) - } - if l > 5 { - return n, fmt.Errorf("decoding Asset: data size (%d) exceeds size limit (5)", l) - } - s.Path = nil - if l > 0 { - s.Path = make([]Asset, l) - for i := uint32(0); i < l; i++ { - nTmp, err = s.Path[i].DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Asset: %s", err) - } - } + return n, fmt.Errorf("decoding TxDemandVector: %w", err) } return n, nil } // MarshalBinary implements encoding.BinaryMarshaler. -func (s PathPaymentStrictReceiveOp) MarshalBinary() ([]byte, error) { +func (s FloodDemand) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -18962,133 +20619,14215 @@ func (s PathPaymentStrictReceiveOp) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *PathPaymentStrictReceiveOp) UnmarshalBinary(inp []byte) error { +func (s *FloodDemand) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*PathPaymentStrictReceiveOp)(nil) - _ encoding.BinaryUnmarshaler = (*PathPaymentStrictReceiveOp)(nil) + _ encoding.BinaryMarshaler = (*FloodDemand)(nil) + _ encoding.BinaryUnmarshaler = (*FloodDemand)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s PathPaymentStrictReceiveOp) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s FloodDemand) xdrType() {} -var _ xdrType = (*PathPaymentStrictReceiveOp)(nil) +var _ xdrType = (*FloodDemand)(nil) -// PathPaymentStrictSendOp is an XDR Struct defines as: +// StellarMessage is an XDR Union defines as: // -// struct PathPaymentStrictSendOp +// union StellarMessage switch (MessageType type) // { -// Asset sendAsset; // asset we pay with -// int64 sendAmount; // amount of sendAsset to send (excluding fees) +// case ERROR_MSG: +// Error error; +// case HELLO: +// Hello hello; +// case AUTH: +// Auth auth; +// case DONT_HAVE: +// DontHave dontHave; +// case GET_PEERS: +// void; +// case PEERS: +// PeerAddress peers<100>; // -// MuxedAccount destination; // recipient of the payment -// Asset destAsset; // what they end up with -// int64 destMin; // the minimum amount of dest asset to -// // be received -// // The operation will fail if it can't be met +// case GET_TX_SET: +// uint256 txSetHash; +// case TX_SET: +// TransactionSet txSet; +// case GENERALIZED_TX_SET: +// GeneralizedTransactionSet generalizedTxSet; // -// Asset path<5>; // additional hops it must go through to get there -// }; -type PathPaymentStrictSendOp struct { - SendAsset Asset - SendAmount Int64 - Destination MuxedAccount - DestAsset Asset - DestMin Int64 - Path []Asset `xdrmaxsize:"5"` -} - +// case TRANSACTION: +// TransactionEnvelope transaction; +// +// case SURVEY_REQUEST: +// SignedSurveyRequestMessage signedSurveyRequestMessage; +// +// case SURVEY_RESPONSE: +// SignedSurveyResponseMessage signedSurveyResponseMessage; +// +// // SCP +// case GET_SCP_QUORUMSET: +// uint256 qSetHash; +// case SCP_QUORUMSET: +// SCPQuorumSet qSet; +// case SCP_MESSAGE: +// SCPEnvelope envelope; +// case GET_SCP_STATE: +// uint32 getSCPLedgerSeq; // ledger seq requested ; if 0, requests the latest +// case SEND_MORE: +// SendMore sendMoreMessage; +// case SEND_MORE_EXTENDED: +// SendMoreExtended sendMoreExtendedMessage; +// // Pull mode +// case FLOOD_ADVERT: +// FloodAdvert floodAdvert; +// case FLOOD_DEMAND: +// FloodDemand floodDemand; +// }; +type StellarMessage struct { + Type MessageType + Error *Error + Hello *Hello + Auth *Auth + DontHave *DontHave + Peers *[]PeerAddress `xdrmaxsize:"100"` + TxSetHash *Uint256 + TxSet *TransactionSet + GeneralizedTxSet *GeneralizedTransactionSet + Transaction *TransactionEnvelope + SignedSurveyRequestMessage *SignedSurveyRequestMessage + SignedSurveyResponseMessage *SignedSurveyResponseMessage + QSetHash *Uint256 + QSet *ScpQuorumSet + Envelope *ScpEnvelope + GetScpLedgerSeq *Uint32 + SendMoreMessage *SendMore + SendMoreExtendedMessage *SendMoreExtended + FloodAdvert *FloodAdvert + FloodDemand *FloodDemand +} + +// SwitchFieldName returns the field name in which this union's +// discriminant is stored +func (u StellarMessage) SwitchFieldName() string { + return "Type" +} + +// ArmForSwitch returns which field name should be used for storing +// the value for an instance of StellarMessage +func (u StellarMessage) ArmForSwitch(sw int32) (string, bool) { + switch MessageType(sw) { + case MessageTypeErrorMsg: + return "Error", true + case MessageTypeHello: + return "Hello", true + case MessageTypeAuth: + return "Auth", true + case MessageTypeDontHave: + return "DontHave", true + case MessageTypeGetPeers: + return "", true + case MessageTypePeers: + return "Peers", true + case MessageTypeGetTxSet: + return "TxSetHash", true + case MessageTypeTxSet: + return "TxSet", true + case MessageTypeGeneralizedTxSet: + return "GeneralizedTxSet", true + case MessageTypeTransaction: + return "Transaction", true + case MessageTypeSurveyRequest: + return "SignedSurveyRequestMessage", true + case MessageTypeSurveyResponse: + return "SignedSurveyResponseMessage", true + case MessageTypeGetScpQuorumset: + return "QSetHash", true + case MessageTypeScpQuorumset: + return "QSet", true + case MessageTypeScpMessage: + return "Envelope", true + case MessageTypeGetScpState: + return "GetScpLedgerSeq", true + case MessageTypeSendMore: + return "SendMoreMessage", true + case MessageTypeSendMoreExtended: + return "SendMoreExtendedMessage", true + case MessageTypeFloodAdvert: + return "FloodAdvert", true + case MessageTypeFloodDemand: + return "FloodDemand", true + } + return "-", false +} + +// NewStellarMessage creates a new StellarMessage. +func NewStellarMessage(aType MessageType, value interface{}) (result StellarMessage, err error) { + result.Type = aType + switch MessageType(aType) { + case MessageTypeErrorMsg: + tv, ok := value.(Error) + if !ok { + err = errors.New("invalid value, must be Error") + return + } + result.Error = &tv + case MessageTypeHello: + tv, ok := value.(Hello) + if !ok { + err = errors.New("invalid value, must be Hello") + return + } + result.Hello = &tv + case MessageTypeAuth: + tv, ok := value.(Auth) + if !ok { + err = errors.New("invalid value, must be Auth") + return + } + result.Auth = &tv + case MessageTypeDontHave: + tv, ok := value.(DontHave) + if !ok { + err = errors.New("invalid value, must be DontHave") + return + } + result.DontHave = &tv + case MessageTypeGetPeers: + // void + case MessageTypePeers: + tv, ok := value.([]PeerAddress) + if !ok { + err = errors.New("invalid value, must be []PeerAddress") + return + } + result.Peers = &tv + case MessageTypeGetTxSet: + tv, ok := value.(Uint256) + if !ok { + err = errors.New("invalid value, must be Uint256") + return + } + result.TxSetHash = &tv + case MessageTypeTxSet: + tv, ok := value.(TransactionSet) + if !ok { + err = errors.New("invalid value, must be TransactionSet") + return + } + result.TxSet = &tv + case MessageTypeGeneralizedTxSet: + tv, ok := value.(GeneralizedTransactionSet) + if !ok { + err = errors.New("invalid value, must be GeneralizedTransactionSet") + return + } + result.GeneralizedTxSet = &tv + case MessageTypeTransaction: + tv, ok := value.(TransactionEnvelope) + if !ok { + err = errors.New("invalid value, must be TransactionEnvelope") + return + } + result.Transaction = &tv + case MessageTypeSurveyRequest: + tv, ok := value.(SignedSurveyRequestMessage) + if !ok { + err = errors.New("invalid value, must be SignedSurveyRequestMessage") + return + } + result.SignedSurveyRequestMessage = &tv + case MessageTypeSurveyResponse: + tv, ok := value.(SignedSurveyResponseMessage) + if !ok { + err = errors.New("invalid value, must be SignedSurveyResponseMessage") + return + } + result.SignedSurveyResponseMessage = &tv + case MessageTypeGetScpQuorumset: + tv, ok := value.(Uint256) + if !ok { + err = errors.New("invalid value, must be Uint256") + return + } + result.QSetHash = &tv + case MessageTypeScpQuorumset: + tv, ok := value.(ScpQuorumSet) + if !ok { + err = errors.New("invalid value, must be ScpQuorumSet") + return + } + result.QSet = &tv + case MessageTypeScpMessage: + tv, ok := value.(ScpEnvelope) + if !ok { + err = errors.New("invalid value, must be ScpEnvelope") + return + } + result.Envelope = &tv + case MessageTypeGetScpState: + tv, ok := value.(Uint32) + if !ok { + err = errors.New("invalid value, must be Uint32") + return + } + result.GetScpLedgerSeq = &tv + case MessageTypeSendMore: + tv, ok := value.(SendMore) + if !ok { + err = errors.New("invalid value, must be SendMore") + return + } + result.SendMoreMessage = &tv + case MessageTypeSendMoreExtended: + tv, ok := value.(SendMoreExtended) + if !ok { + err = errors.New("invalid value, must be SendMoreExtended") + return + } + result.SendMoreExtendedMessage = &tv + case MessageTypeFloodAdvert: + tv, ok := value.(FloodAdvert) + if !ok { + err = errors.New("invalid value, must be FloodAdvert") + return + } + result.FloodAdvert = &tv + case MessageTypeFloodDemand: + tv, ok := value.(FloodDemand) + if !ok { + err = errors.New("invalid value, must be FloodDemand") + return + } + result.FloodDemand = &tv + } + return +} + +// MustError retrieves the Error value from the union, +// panicing if the value is not set. +func (u StellarMessage) MustError() Error { + val, ok := u.GetError() + + if !ok { + panic("arm Error is not set") + } + + return val +} + +// GetError retrieves the Error value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u StellarMessage) GetError() (result Error, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) + + if armName == "Error" { + result = *u.Error + ok = true + } + + return +} + +// MustHello retrieves the Hello value from the union, +// panicing if the value is not set. +func (u StellarMessage) MustHello() Hello { + val, ok := u.GetHello() + + if !ok { + panic("arm Hello is not set") + } + + return val +} + +// GetHello retrieves the Hello value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u StellarMessage) GetHello() (result Hello, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) + + if armName == "Hello" { + result = *u.Hello + ok = true + } + + return +} + +// MustAuth retrieves the Auth value from the union, +// panicing if the value is not set. +func (u StellarMessage) MustAuth() Auth { + val, ok := u.GetAuth() + + if !ok { + panic("arm Auth is not set") + } + + return val +} + +// GetAuth retrieves the Auth value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u StellarMessage) GetAuth() (result Auth, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) + + if armName == "Auth" { + result = *u.Auth + ok = true + } + + return +} + +// MustDontHave retrieves the DontHave value from the union, +// panicing if the value is not set. +func (u StellarMessage) MustDontHave() DontHave { + val, ok := u.GetDontHave() + + if !ok { + panic("arm DontHave is not set") + } + + return val +} + +// GetDontHave retrieves the DontHave value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u StellarMessage) GetDontHave() (result DontHave, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) + + if armName == "DontHave" { + result = *u.DontHave + ok = true + } + + return +} + +// MustPeers retrieves the Peers value from the union, +// panicing if the value is not set. +func (u StellarMessage) MustPeers() []PeerAddress { + val, ok := u.GetPeers() + + if !ok { + panic("arm Peers is not set") + } + + return val +} + +// GetPeers retrieves the Peers value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u StellarMessage) GetPeers() (result []PeerAddress, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) + + if armName == "Peers" { + result = *u.Peers + ok = true + } + + return +} + +// MustTxSetHash retrieves the TxSetHash value from the union, +// panicing if the value is not set. +func (u StellarMessage) MustTxSetHash() Uint256 { + val, ok := u.GetTxSetHash() + + if !ok { + panic("arm TxSetHash is not set") + } + + return val +} + +// GetTxSetHash retrieves the TxSetHash value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u StellarMessage) GetTxSetHash() (result Uint256, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) + + if armName == "TxSetHash" { + result = *u.TxSetHash + ok = true + } + + return +} + +// MustTxSet retrieves the TxSet value from the union, +// panicing if the value is not set. +func (u StellarMessage) MustTxSet() TransactionSet { + val, ok := u.GetTxSet() + + if !ok { + panic("arm TxSet is not set") + } + + return val +} + +// GetTxSet retrieves the TxSet value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u StellarMessage) GetTxSet() (result TransactionSet, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) + + if armName == "TxSet" { + result = *u.TxSet + ok = true + } + + return +} + +// MustGeneralizedTxSet retrieves the GeneralizedTxSet value from the union, +// panicing if the value is not set. +func (u StellarMessage) MustGeneralizedTxSet() GeneralizedTransactionSet { + val, ok := u.GetGeneralizedTxSet() + + if !ok { + panic("arm GeneralizedTxSet is not set") + } + + return val +} + +// GetGeneralizedTxSet retrieves the GeneralizedTxSet value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u StellarMessage) GetGeneralizedTxSet() (result GeneralizedTransactionSet, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) + + if armName == "GeneralizedTxSet" { + result = *u.GeneralizedTxSet + ok = true + } + + return +} + +// MustTransaction retrieves the Transaction value from the union, +// panicing if the value is not set. +func (u StellarMessage) MustTransaction() TransactionEnvelope { + val, ok := u.GetTransaction() + + if !ok { + panic("arm Transaction is not set") + } + + return val +} + +// GetTransaction retrieves the Transaction value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u StellarMessage) GetTransaction() (result TransactionEnvelope, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) + + if armName == "Transaction" { + result = *u.Transaction + ok = true + } + + return +} + +// MustSignedSurveyRequestMessage retrieves the SignedSurveyRequestMessage value from the union, +// panicing if the value is not set. +func (u StellarMessage) MustSignedSurveyRequestMessage() SignedSurveyRequestMessage { + val, ok := u.GetSignedSurveyRequestMessage() + + if !ok { + panic("arm SignedSurveyRequestMessage is not set") + } + + return val +} + +// GetSignedSurveyRequestMessage retrieves the SignedSurveyRequestMessage value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u StellarMessage) GetSignedSurveyRequestMessage() (result SignedSurveyRequestMessage, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) + + if armName == "SignedSurveyRequestMessage" { + result = *u.SignedSurveyRequestMessage + ok = true + } + + return +} + +// MustSignedSurveyResponseMessage retrieves the SignedSurveyResponseMessage value from the union, +// panicing if the value is not set. +func (u StellarMessage) MustSignedSurveyResponseMessage() SignedSurveyResponseMessage { + val, ok := u.GetSignedSurveyResponseMessage() + + if !ok { + panic("arm SignedSurveyResponseMessage is not set") + } + + return val +} + +// GetSignedSurveyResponseMessage retrieves the SignedSurveyResponseMessage value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u StellarMessage) GetSignedSurveyResponseMessage() (result SignedSurveyResponseMessage, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) + + if armName == "SignedSurveyResponseMessage" { + result = *u.SignedSurveyResponseMessage + ok = true + } + + return +} + +// MustQSetHash retrieves the QSetHash value from the union, +// panicing if the value is not set. +func (u StellarMessage) MustQSetHash() Uint256 { + val, ok := u.GetQSetHash() + + if !ok { + panic("arm QSetHash is not set") + } + + return val +} + +// GetQSetHash retrieves the QSetHash value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u StellarMessage) GetQSetHash() (result Uint256, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) + + if armName == "QSetHash" { + result = *u.QSetHash + ok = true + } + + return +} + +// MustQSet retrieves the QSet value from the union, +// panicing if the value is not set. +func (u StellarMessage) MustQSet() ScpQuorumSet { + val, ok := u.GetQSet() + + if !ok { + panic("arm QSet is not set") + } + + return val +} + +// GetQSet retrieves the QSet value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u StellarMessage) GetQSet() (result ScpQuorumSet, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) + + if armName == "QSet" { + result = *u.QSet + ok = true + } + + return +} + +// MustEnvelope retrieves the Envelope value from the union, +// panicing if the value is not set. +func (u StellarMessage) MustEnvelope() ScpEnvelope { + val, ok := u.GetEnvelope() + + if !ok { + panic("arm Envelope is not set") + } + + return val +} + +// GetEnvelope retrieves the Envelope value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u StellarMessage) GetEnvelope() (result ScpEnvelope, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) + + if armName == "Envelope" { + result = *u.Envelope + ok = true + } + + return +} + +// MustGetScpLedgerSeq retrieves the GetScpLedgerSeq value from the union, +// panicing if the value is not set. +func (u StellarMessage) MustGetScpLedgerSeq() Uint32 { + val, ok := u.GetGetScpLedgerSeq() + + if !ok { + panic("arm GetScpLedgerSeq is not set") + } + + return val +} + +// GetGetScpLedgerSeq retrieves the GetScpLedgerSeq value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u StellarMessage) GetGetScpLedgerSeq() (result Uint32, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) + + if armName == "GetScpLedgerSeq" { + result = *u.GetScpLedgerSeq + ok = true + } + + return +} + +// MustSendMoreMessage retrieves the SendMoreMessage value from the union, +// panicing if the value is not set. +func (u StellarMessage) MustSendMoreMessage() SendMore { + val, ok := u.GetSendMoreMessage() + + if !ok { + panic("arm SendMoreMessage is not set") + } + + return val +} + +// GetSendMoreMessage retrieves the SendMoreMessage value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u StellarMessage) GetSendMoreMessage() (result SendMore, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) + + if armName == "SendMoreMessage" { + result = *u.SendMoreMessage + ok = true + } + + return +} + +// MustSendMoreExtendedMessage retrieves the SendMoreExtendedMessage value from the union, +// panicing if the value is not set. +func (u StellarMessage) MustSendMoreExtendedMessage() SendMoreExtended { + val, ok := u.GetSendMoreExtendedMessage() + + if !ok { + panic("arm SendMoreExtendedMessage is not set") + } + + return val +} + +// GetSendMoreExtendedMessage retrieves the SendMoreExtendedMessage value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u StellarMessage) GetSendMoreExtendedMessage() (result SendMoreExtended, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) + + if armName == "SendMoreExtendedMessage" { + result = *u.SendMoreExtendedMessage + ok = true + } + + return +} + +// MustFloodAdvert retrieves the FloodAdvert value from the union, +// panicing if the value is not set. +func (u StellarMessage) MustFloodAdvert() FloodAdvert { + val, ok := u.GetFloodAdvert() + + if !ok { + panic("arm FloodAdvert is not set") + } + + return val +} + +// GetFloodAdvert retrieves the FloodAdvert value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u StellarMessage) GetFloodAdvert() (result FloodAdvert, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) + + if armName == "FloodAdvert" { + result = *u.FloodAdvert + ok = true + } + + return +} + +// MustFloodDemand retrieves the FloodDemand value from the union, +// panicing if the value is not set. +func (u StellarMessage) MustFloodDemand() FloodDemand { + val, ok := u.GetFloodDemand() + + if !ok { + panic("arm FloodDemand is not set") + } + + return val +} + +// GetFloodDemand retrieves the FloodDemand value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u StellarMessage) GetFloodDemand() (result FloodDemand, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) + + if armName == "FloodDemand" { + result = *u.FloodDemand + ok = true + } + + return +} + +// EncodeTo encodes this value using the Encoder. +func (u StellarMessage) EncodeTo(e *xdr.Encoder) error { + var err error + if err = u.Type.EncodeTo(e); err != nil { + return err + } + switch MessageType(u.Type) { + case MessageTypeErrorMsg: + if err = (*u.Error).EncodeTo(e); err != nil { + return err + } + return nil + case MessageTypeHello: + if err = (*u.Hello).EncodeTo(e); err != nil { + return err + } + return nil + case MessageTypeAuth: + if err = (*u.Auth).EncodeTo(e); err != nil { + return err + } + return nil + case MessageTypeDontHave: + if err = (*u.DontHave).EncodeTo(e); err != nil { + return err + } + return nil + case MessageTypeGetPeers: + // Void + return nil + case MessageTypePeers: + if _, err = e.EncodeUint(uint32(len((*u.Peers)))); err != nil { + return err + } + for i := 0; i < len((*u.Peers)); i++ { + if err = (*u.Peers)[i].EncodeTo(e); err != nil { + return err + } + } + return nil + case MessageTypeGetTxSet: + if err = (*u.TxSetHash).EncodeTo(e); err != nil { + return err + } + return nil + case MessageTypeTxSet: + if err = (*u.TxSet).EncodeTo(e); err != nil { + return err + } + return nil + case MessageTypeGeneralizedTxSet: + if err = (*u.GeneralizedTxSet).EncodeTo(e); err != nil { + return err + } + return nil + case MessageTypeTransaction: + if err = (*u.Transaction).EncodeTo(e); err != nil { + return err + } + return nil + case MessageTypeSurveyRequest: + if err = (*u.SignedSurveyRequestMessage).EncodeTo(e); err != nil { + return err + } + return nil + case MessageTypeSurveyResponse: + if err = (*u.SignedSurveyResponseMessage).EncodeTo(e); err != nil { + return err + } + return nil + case MessageTypeGetScpQuorumset: + if err = (*u.QSetHash).EncodeTo(e); err != nil { + return err + } + return nil + case MessageTypeScpQuorumset: + if err = (*u.QSet).EncodeTo(e); err != nil { + return err + } + return nil + case MessageTypeScpMessage: + if err = (*u.Envelope).EncodeTo(e); err != nil { + return err + } + return nil + case MessageTypeGetScpState: + if err = (*u.GetScpLedgerSeq).EncodeTo(e); err != nil { + return err + } + return nil + case MessageTypeSendMore: + if err = (*u.SendMoreMessage).EncodeTo(e); err != nil { + return err + } + return nil + case MessageTypeSendMoreExtended: + if err = (*u.SendMoreExtendedMessage).EncodeTo(e); err != nil { + return err + } + return nil + case MessageTypeFloodAdvert: + if err = (*u.FloodAdvert).EncodeTo(e); err != nil { + return err + } + return nil + case MessageTypeFloodDemand: + if err = (*u.FloodDemand).EncodeTo(e); err != nil { + return err + } + return nil + } + return fmt.Errorf("Type (MessageType) switch value '%d' is not valid for union StellarMessage", u.Type) +} + +var _ decoderFrom = (*StellarMessage)(nil) + +// DecodeFrom decodes this value using the Decoder. +func (u *StellarMessage) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding StellarMessage: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + var err error + var n, nTmp int + nTmp, err = u.Type.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding MessageType: %w", err) + } + switch MessageType(u.Type) { + case MessageTypeErrorMsg: + u.Error = new(Error) + nTmp, err = (*u.Error).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Error: %w", err) + } + return n, nil + case MessageTypeHello: + u.Hello = new(Hello) + nTmp, err = (*u.Hello).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Hello: %w", err) + } + return n, nil + case MessageTypeAuth: + u.Auth = new(Auth) + nTmp, err = (*u.Auth).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Auth: %w", err) + } + return n, nil + case MessageTypeDontHave: + u.DontHave = new(DontHave) + nTmp, err = (*u.DontHave).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding DontHave: %w", err) + } + return n, nil + case MessageTypeGetPeers: + // Void + return n, nil + case MessageTypePeers: + u.Peers = new([]PeerAddress) + var l uint32 + l, nTmp, err = d.DecodeUint() + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding PeerAddress: %w", err) + } + if l > 100 { + return n, fmt.Errorf("decoding PeerAddress: data size (%d) exceeds size limit (100)", l) + } + (*u.Peers) = nil + if l > 0 { + if il, ok := d.InputLen(); ok && uint(il) < uint(l) { + return n, fmt.Errorf("decoding PeerAddress: length (%d) exceeds remaining input length (%d)", l, il) + } + (*u.Peers) = make([]PeerAddress, l) + for i := uint32(0); i < l; i++ { + nTmp, err = (*u.Peers)[i].DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding PeerAddress: %w", err) + } + } + } + return n, nil + case MessageTypeGetTxSet: + u.TxSetHash = new(Uint256) + nTmp, err = (*u.TxSetHash).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Uint256: %w", err) + } + return n, nil + case MessageTypeTxSet: + u.TxSet = new(TransactionSet) + nTmp, err = (*u.TxSet).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding TransactionSet: %w", err) + } + return n, nil + case MessageTypeGeneralizedTxSet: + u.GeneralizedTxSet = new(GeneralizedTransactionSet) + nTmp, err = (*u.GeneralizedTxSet).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding GeneralizedTransactionSet: %w", err) + } + return n, nil + case MessageTypeTransaction: + u.Transaction = new(TransactionEnvelope) + nTmp, err = (*u.Transaction).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding TransactionEnvelope: %w", err) + } + return n, nil + case MessageTypeSurveyRequest: + u.SignedSurveyRequestMessage = new(SignedSurveyRequestMessage) + nTmp, err = (*u.SignedSurveyRequestMessage).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding SignedSurveyRequestMessage: %w", err) + } + return n, nil + case MessageTypeSurveyResponse: + u.SignedSurveyResponseMessage = new(SignedSurveyResponseMessage) + nTmp, err = (*u.SignedSurveyResponseMessage).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding SignedSurveyResponseMessage: %w", err) + } + return n, nil + case MessageTypeGetScpQuorumset: + u.QSetHash = new(Uint256) + nTmp, err = (*u.QSetHash).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Uint256: %w", err) + } + return n, nil + case MessageTypeScpQuorumset: + u.QSet = new(ScpQuorumSet) + nTmp, err = (*u.QSet).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ScpQuorumSet: %w", err) + } + return n, nil + case MessageTypeScpMessage: + u.Envelope = new(ScpEnvelope) + nTmp, err = (*u.Envelope).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ScpEnvelope: %w", err) + } + return n, nil + case MessageTypeGetScpState: + u.GetScpLedgerSeq = new(Uint32) + nTmp, err = (*u.GetScpLedgerSeq).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Uint32: %w", err) + } + return n, nil + case MessageTypeSendMore: + u.SendMoreMessage = new(SendMore) + nTmp, err = (*u.SendMoreMessage).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding SendMore: %w", err) + } + return n, nil + case MessageTypeSendMoreExtended: + u.SendMoreExtendedMessage = new(SendMoreExtended) + nTmp, err = (*u.SendMoreExtendedMessage).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding SendMoreExtended: %w", err) + } + return n, nil + case MessageTypeFloodAdvert: + u.FloodAdvert = new(FloodAdvert) + nTmp, err = (*u.FloodAdvert).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding FloodAdvert: %w", err) + } + return n, nil + case MessageTypeFloodDemand: + u.FloodDemand = new(FloodDemand) + nTmp, err = (*u.FloodDemand).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding FloodDemand: %w", err) + } + return n, nil + } + return n, fmt.Errorf("union StellarMessage has invalid Type (MessageType) switch value '%d'", u.Type) +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (s StellarMessage) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *StellarMessage) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} + +var ( + _ encoding.BinaryMarshaler = (*StellarMessage)(nil) + _ encoding.BinaryUnmarshaler = (*StellarMessage)(nil) +) + +// xdrType signals that this type represents XDR values defined by this package. +func (s StellarMessage) xdrType() {} + +var _ xdrType = (*StellarMessage)(nil) + +// AuthenticatedMessageV0 is an XDR NestedStruct defines as: +// +// struct +// { +// uint64 sequence; +// StellarMessage message; +// HmacSha256Mac mac; +// } +type AuthenticatedMessageV0 struct { + Sequence Uint64 + Message StellarMessage + Mac HmacSha256Mac +} + +// EncodeTo encodes this value using the Encoder. +func (s *AuthenticatedMessageV0) EncodeTo(e *xdr.Encoder) error { + var err error + if err = s.Sequence.EncodeTo(e); err != nil { + return err + } + if err = s.Message.EncodeTo(e); err != nil { + return err + } + if err = s.Mac.EncodeTo(e); err != nil { + return err + } + return nil +} + +var _ decoderFrom = (*AuthenticatedMessageV0)(nil) + +// DecodeFrom decodes this value using the Decoder. +func (s *AuthenticatedMessageV0) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding AuthenticatedMessageV0: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + var err error + var n, nTmp int + nTmp, err = s.Sequence.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Uint64: %w", err) + } + nTmp, err = s.Message.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding StellarMessage: %w", err) + } + nTmp, err = s.Mac.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding HmacSha256Mac: %w", err) + } + return n, nil +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (s AuthenticatedMessageV0) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *AuthenticatedMessageV0) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} + +var ( + _ encoding.BinaryMarshaler = (*AuthenticatedMessageV0)(nil) + _ encoding.BinaryUnmarshaler = (*AuthenticatedMessageV0)(nil) +) + +// xdrType signals that this type represents XDR values defined by this package. +func (s AuthenticatedMessageV0) xdrType() {} + +var _ xdrType = (*AuthenticatedMessageV0)(nil) + +// AuthenticatedMessage is an XDR Union defines as: +// +// union AuthenticatedMessage switch (uint32 v) +// { +// case 0: +// struct +// { +// uint64 sequence; +// StellarMessage message; +// HmacSha256Mac mac; +// } v0; +// }; +type AuthenticatedMessage struct { + V Uint32 + V0 *AuthenticatedMessageV0 +} + +// SwitchFieldName returns the field name in which this union's +// discriminant is stored +func (u AuthenticatedMessage) SwitchFieldName() string { + return "V" +} + +// ArmForSwitch returns which field name should be used for storing +// the value for an instance of AuthenticatedMessage +func (u AuthenticatedMessage) ArmForSwitch(sw int32) (string, bool) { + switch Uint32(sw) { + case 0: + return "V0", true + } + return "-", false +} + +// NewAuthenticatedMessage creates a new AuthenticatedMessage. +func NewAuthenticatedMessage(v Uint32, value interface{}) (result AuthenticatedMessage, err error) { + result.V = v + switch Uint32(v) { + case 0: + tv, ok := value.(AuthenticatedMessageV0) + if !ok { + err = errors.New("invalid value, must be AuthenticatedMessageV0") + return + } + result.V0 = &tv + } + return +} + +// MustV0 retrieves the V0 value from the union, +// panicing if the value is not set. +func (u AuthenticatedMessage) MustV0() AuthenticatedMessageV0 { + val, ok := u.GetV0() + + if !ok { + panic("arm V0 is not set") + } + + return val +} + +// GetV0 retrieves the V0 value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u AuthenticatedMessage) GetV0() (result AuthenticatedMessageV0, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.V)) + + if armName == "V0" { + result = *u.V0 + ok = true + } + + return +} + +// EncodeTo encodes this value using the Encoder. +func (u AuthenticatedMessage) EncodeTo(e *xdr.Encoder) error { + var err error + if err = u.V.EncodeTo(e); err != nil { + return err + } + switch Uint32(u.V) { + case 0: + if err = (*u.V0).EncodeTo(e); err != nil { + return err + } + return nil + } + return fmt.Errorf("V (Uint32) switch value '%d' is not valid for union AuthenticatedMessage", u.V) +} + +var _ decoderFrom = (*AuthenticatedMessage)(nil) + +// DecodeFrom decodes this value using the Decoder. +func (u *AuthenticatedMessage) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding AuthenticatedMessage: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + var err error + var n, nTmp int + nTmp, err = u.V.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Uint32: %w", err) + } + switch Uint32(u.V) { + case 0: + u.V0 = new(AuthenticatedMessageV0) + nTmp, err = (*u.V0).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding AuthenticatedMessageV0: %w", err) + } + return n, nil + } + return n, fmt.Errorf("union AuthenticatedMessage has invalid V (Uint32) switch value '%d'", u.V) +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (s AuthenticatedMessage) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *AuthenticatedMessage) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} + +var ( + _ encoding.BinaryMarshaler = (*AuthenticatedMessage)(nil) + _ encoding.BinaryUnmarshaler = (*AuthenticatedMessage)(nil) +) + +// xdrType signals that this type represents XDR values defined by this package. +func (s AuthenticatedMessage) xdrType() {} + +var _ xdrType = (*AuthenticatedMessage)(nil) + +// MaxOpsPerTx is an XDR Const defines as: +// +// const MAX_OPS_PER_TX = 100; +const MaxOpsPerTx = 100 + +// LiquidityPoolParameters is an XDR Union defines as: +// +// union LiquidityPoolParameters switch (LiquidityPoolType type) +// { +// case LIQUIDITY_POOL_CONSTANT_PRODUCT: +// LiquidityPoolConstantProductParameters constantProduct; +// }; +type LiquidityPoolParameters struct { + Type LiquidityPoolType + ConstantProduct *LiquidityPoolConstantProductParameters +} + +// SwitchFieldName returns the field name in which this union's +// discriminant is stored +func (u LiquidityPoolParameters) SwitchFieldName() string { + return "Type" +} + +// ArmForSwitch returns which field name should be used for storing +// the value for an instance of LiquidityPoolParameters +func (u LiquidityPoolParameters) ArmForSwitch(sw int32) (string, bool) { + switch LiquidityPoolType(sw) { + case LiquidityPoolTypeLiquidityPoolConstantProduct: + return "ConstantProduct", true + } + return "-", false +} + +// NewLiquidityPoolParameters creates a new LiquidityPoolParameters. +func NewLiquidityPoolParameters(aType LiquidityPoolType, value interface{}) (result LiquidityPoolParameters, err error) { + result.Type = aType + switch LiquidityPoolType(aType) { + case LiquidityPoolTypeLiquidityPoolConstantProduct: + tv, ok := value.(LiquidityPoolConstantProductParameters) + if !ok { + err = errors.New("invalid value, must be LiquidityPoolConstantProductParameters") + return + } + result.ConstantProduct = &tv + } + return +} + +// MustConstantProduct retrieves the ConstantProduct value from the union, +// panicing if the value is not set. +func (u LiquidityPoolParameters) MustConstantProduct() LiquidityPoolConstantProductParameters { + val, ok := u.GetConstantProduct() + + if !ok { + panic("arm ConstantProduct is not set") + } + + return val +} + +// GetConstantProduct retrieves the ConstantProduct value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u LiquidityPoolParameters) GetConstantProduct() (result LiquidityPoolConstantProductParameters, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) + + if armName == "ConstantProduct" { + result = *u.ConstantProduct + ok = true + } + + return +} + +// EncodeTo encodes this value using the Encoder. +func (u LiquidityPoolParameters) EncodeTo(e *xdr.Encoder) error { + var err error + if err = u.Type.EncodeTo(e); err != nil { + return err + } + switch LiquidityPoolType(u.Type) { + case LiquidityPoolTypeLiquidityPoolConstantProduct: + if err = (*u.ConstantProduct).EncodeTo(e); err != nil { + return err + } + return nil + } + return fmt.Errorf("Type (LiquidityPoolType) switch value '%d' is not valid for union LiquidityPoolParameters", u.Type) +} + +var _ decoderFrom = (*LiquidityPoolParameters)(nil) + +// DecodeFrom decodes this value using the Decoder. +func (u *LiquidityPoolParameters) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding LiquidityPoolParameters: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + var err error + var n, nTmp int + nTmp, err = u.Type.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding LiquidityPoolType: %w", err) + } + switch LiquidityPoolType(u.Type) { + case LiquidityPoolTypeLiquidityPoolConstantProduct: + u.ConstantProduct = new(LiquidityPoolConstantProductParameters) + nTmp, err = (*u.ConstantProduct).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding LiquidityPoolConstantProductParameters: %w", err) + } + return n, nil + } + return n, fmt.Errorf("union LiquidityPoolParameters has invalid Type (LiquidityPoolType) switch value '%d'", u.Type) +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (s LiquidityPoolParameters) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *LiquidityPoolParameters) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} + +var ( + _ encoding.BinaryMarshaler = (*LiquidityPoolParameters)(nil) + _ encoding.BinaryUnmarshaler = (*LiquidityPoolParameters)(nil) +) + +// xdrType signals that this type represents XDR values defined by this package. +func (s LiquidityPoolParameters) xdrType() {} + +var _ xdrType = (*LiquidityPoolParameters)(nil) + +// MuxedAccountMed25519 is an XDR NestedStruct defines as: +// +// struct +// { +// uint64 id; +// uint256 ed25519; +// } +type MuxedAccountMed25519 struct { + Id Uint64 + Ed25519 Uint256 +} + +// EncodeTo encodes this value using the Encoder. +func (s *MuxedAccountMed25519) EncodeTo(e *xdr.Encoder) error { + var err error + if err = s.Id.EncodeTo(e); err != nil { + return err + } + if err = s.Ed25519.EncodeTo(e); err != nil { + return err + } + return nil +} + +var _ decoderFrom = (*MuxedAccountMed25519)(nil) + +// DecodeFrom decodes this value using the Decoder. +func (s *MuxedAccountMed25519) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding MuxedAccountMed25519: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + var err error + var n, nTmp int + nTmp, err = s.Id.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Uint64: %w", err) + } + nTmp, err = s.Ed25519.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Uint256: %w", err) + } + return n, nil +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (s MuxedAccountMed25519) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *MuxedAccountMed25519) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} + +var ( + _ encoding.BinaryMarshaler = (*MuxedAccountMed25519)(nil) + _ encoding.BinaryUnmarshaler = (*MuxedAccountMed25519)(nil) +) + +// xdrType signals that this type represents XDR values defined by this package. +func (s MuxedAccountMed25519) xdrType() {} + +var _ xdrType = (*MuxedAccountMed25519)(nil) + +// MuxedAccount is an XDR Union defines as: +// +// union MuxedAccount switch (CryptoKeyType type) +// { +// case KEY_TYPE_ED25519: +// uint256 ed25519; +// case KEY_TYPE_MUXED_ED25519: +// struct +// { +// uint64 id; +// uint256 ed25519; +// } med25519; +// }; +type MuxedAccount struct { + Type CryptoKeyType + Ed25519 *Uint256 + Med25519 *MuxedAccountMed25519 +} + +// SwitchFieldName returns the field name in which this union's +// discriminant is stored +func (u MuxedAccount) SwitchFieldName() string { + return "Type" +} + +// ArmForSwitch returns which field name should be used for storing +// the value for an instance of MuxedAccount +func (u MuxedAccount) ArmForSwitch(sw int32) (string, bool) { + switch CryptoKeyType(sw) { + case CryptoKeyTypeKeyTypeEd25519: + return "Ed25519", true + case CryptoKeyTypeKeyTypeMuxedEd25519: + return "Med25519", true + } + return "-", false +} + +// NewMuxedAccount creates a new MuxedAccount. +func NewMuxedAccount(aType CryptoKeyType, value interface{}) (result MuxedAccount, err error) { + result.Type = aType + switch CryptoKeyType(aType) { + case CryptoKeyTypeKeyTypeEd25519: + tv, ok := value.(Uint256) + if !ok { + err = errors.New("invalid value, must be Uint256") + return + } + result.Ed25519 = &tv + case CryptoKeyTypeKeyTypeMuxedEd25519: + tv, ok := value.(MuxedAccountMed25519) + if !ok { + err = errors.New("invalid value, must be MuxedAccountMed25519") + return + } + result.Med25519 = &tv + } + return +} + +// MustEd25519 retrieves the Ed25519 value from the union, +// panicing if the value is not set. +func (u MuxedAccount) MustEd25519() Uint256 { + val, ok := u.GetEd25519() + + if !ok { + panic("arm Ed25519 is not set") + } + + return val +} + +// GetEd25519 retrieves the Ed25519 value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u MuxedAccount) GetEd25519() (result Uint256, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) + + if armName == "Ed25519" { + result = *u.Ed25519 + ok = true + } + + return +} + +// MustMed25519 retrieves the Med25519 value from the union, +// panicing if the value is not set. +func (u MuxedAccount) MustMed25519() MuxedAccountMed25519 { + val, ok := u.GetMed25519() + + if !ok { + panic("arm Med25519 is not set") + } + + return val +} + +// GetMed25519 retrieves the Med25519 value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u MuxedAccount) GetMed25519() (result MuxedAccountMed25519, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) + + if armName == "Med25519" { + result = *u.Med25519 + ok = true + } + + return +} + +// EncodeTo encodes this value using the Encoder. +func (u MuxedAccount) EncodeTo(e *xdr.Encoder) error { + var err error + if err = u.Type.EncodeTo(e); err != nil { + return err + } + switch CryptoKeyType(u.Type) { + case CryptoKeyTypeKeyTypeEd25519: + if err = (*u.Ed25519).EncodeTo(e); err != nil { + return err + } + return nil + case CryptoKeyTypeKeyTypeMuxedEd25519: + if err = (*u.Med25519).EncodeTo(e); err != nil { + return err + } + return nil + } + return fmt.Errorf("Type (CryptoKeyType) switch value '%d' is not valid for union MuxedAccount", u.Type) +} + +var _ decoderFrom = (*MuxedAccount)(nil) + +// DecodeFrom decodes this value using the Decoder. +func (u *MuxedAccount) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding MuxedAccount: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + var err error + var n, nTmp int + nTmp, err = u.Type.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding CryptoKeyType: %w", err) + } + switch CryptoKeyType(u.Type) { + case CryptoKeyTypeKeyTypeEd25519: + u.Ed25519 = new(Uint256) + nTmp, err = (*u.Ed25519).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Uint256: %w", err) + } + return n, nil + case CryptoKeyTypeKeyTypeMuxedEd25519: + u.Med25519 = new(MuxedAccountMed25519) + nTmp, err = (*u.Med25519).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding MuxedAccountMed25519: %w", err) + } + return n, nil + } + return n, fmt.Errorf("union MuxedAccount has invalid Type (CryptoKeyType) switch value '%d'", u.Type) +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (s MuxedAccount) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *MuxedAccount) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} + +var ( + _ encoding.BinaryMarshaler = (*MuxedAccount)(nil) + _ encoding.BinaryUnmarshaler = (*MuxedAccount)(nil) +) + +// xdrType signals that this type represents XDR values defined by this package. +func (s MuxedAccount) xdrType() {} + +var _ xdrType = (*MuxedAccount)(nil) + +// DecoratedSignature is an XDR Struct defines as: +// +// struct DecoratedSignature +// { +// SignatureHint hint; // last 4 bytes of the public key, used as a hint +// Signature signature; // actual signature +// }; +type DecoratedSignature struct { + Hint SignatureHint + Signature Signature +} + +// EncodeTo encodes this value using the Encoder. +func (s *DecoratedSignature) EncodeTo(e *xdr.Encoder) error { + var err error + if err = s.Hint.EncodeTo(e); err != nil { + return err + } + if err = s.Signature.EncodeTo(e); err != nil { + return err + } + return nil +} + +var _ decoderFrom = (*DecoratedSignature)(nil) + +// DecodeFrom decodes this value using the Decoder. +func (s *DecoratedSignature) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding DecoratedSignature: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + var err error + var n, nTmp int + nTmp, err = s.Hint.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding SignatureHint: %w", err) + } + nTmp, err = s.Signature.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Signature: %w", err) + } + return n, nil +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (s DecoratedSignature) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *DecoratedSignature) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} + +var ( + _ encoding.BinaryMarshaler = (*DecoratedSignature)(nil) + _ encoding.BinaryUnmarshaler = (*DecoratedSignature)(nil) +) + +// xdrType signals that this type represents XDR values defined by this package. +func (s DecoratedSignature) xdrType() {} + +var _ xdrType = (*DecoratedSignature)(nil) + +// OperationType is an XDR Enum defines as: +// +// enum OperationType +// { +// CREATE_ACCOUNT = 0, +// PAYMENT = 1, +// PATH_PAYMENT_STRICT_RECEIVE = 2, +// MANAGE_SELL_OFFER = 3, +// CREATE_PASSIVE_SELL_OFFER = 4, +// SET_OPTIONS = 5, +// CHANGE_TRUST = 6, +// ALLOW_TRUST = 7, +// ACCOUNT_MERGE = 8, +// INFLATION = 9, +// MANAGE_DATA = 10, +// BUMP_SEQUENCE = 11, +// MANAGE_BUY_OFFER = 12, +// PATH_PAYMENT_STRICT_SEND = 13, +// CREATE_CLAIMABLE_BALANCE = 14, +// CLAIM_CLAIMABLE_BALANCE = 15, +// BEGIN_SPONSORING_FUTURE_RESERVES = 16, +// END_SPONSORING_FUTURE_RESERVES = 17, +// REVOKE_SPONSORSHIP = 18, +// CLAWBACK = 19, +// CLAWBACK_CLAIMABLE_BALANCE = 20, +// SET_TRUST_LINE_FLAGS = 21, +// LIQUIDITY_POOL_DEPOSIT = 22, +// LIQUIDITY_POOL_WITHDRAW = 23, +// INVOKE_HOST_FUNCTION = 24, +// EXTEND_FOOTPRINT_TTL = 25, +// RESTORE_FOOTPRINT = 26 +// }; +type OperationType int32 + +const ( + OperationTypeCreateAccount OperationType = 0 + OperationTypePayment OperationType = 1 + OperationTypePathPaymentStrictReceive OperationType = 2 + OperationTypeManageSellOffer OperationType = 3 + OperationTypeCreatePassiveSellOffer OperationType = 4 + OperationTypeSetOptions OperationType = 5 + OperationTypeChangeTrust OperationType = 6 + OperationTypeAllowTrust OperationType = 7 + OperationTypeAccountMerge OperationType = 8 + OperationTypeInflation OperationType = 9 + OperationTypeManageData OperationType = 10 + OperationTypeBumpSequence OperationType = 11 + OperationTypeManageBuyOffer OperationType = 12 + OperationTypePathPaymentStrictSend OperationType = 13 + OperationTypeCreateClaimableBalance OperationType = 14 + OperationTypeClaimClaimableBalance OperationType = 15 + OperationTypeBeginSponsoringFutureReserves OperationType = 16 + OperationTypeEndSponsoringFutureReserves OperationType = 17 + OperationTypeRevokeSponsorship OperationType = 18 + OperationTypeClawback OperationType = 19 + OperationTypeClawbackClaimableBalance OperationType = 20 + OperationTypeSetTrustLineFlags OperationType = 21 + OperationTypeLiquidityPoolDeposit OperationType = 22 + OperationTypeLiquidityPoolWithdraw OperationType = 23 + OperationTypeInvokeHostFunction OperationType = 24 + OperationTypeExtendFootprintTtl OperationType = 25 + OperationTypeRestoreFootprint OperationType = 26 +) + +var operationTypeMap = map[int32]string{ + 0: "OperationTypeCreateAccount", + 1: "OperationTypePayment", + 2: "OperationTypePathPaymentStrictReceive", + 3: "OperationTypeManageSellOffer", + 4: "OperationTypeCreatePassiveSellOffer", + 5: "OperationTypeSetOptions", + 6: "OperationTypeChangeTrust", + 7: "OperationTypeAllowTrust", + 8: "OperationTypeAccountMerge", + 9: "OperationTypeInflation", + 10: "OperationTypeManageData", + 11: "OperationTypeBumpSequence", + 12: "OperationTypeManageBuyOffer", + 13: "OperationTypePathPaymentStrictSend", + 14: "OperationTypeCreateClaimableBalance", + 15: "OperationTypeClaimClaimableBalance", + 16: "OperationTypeBeginSponsoringFutureReserves", + 17: "OperationTypeEndSponsoringFutureReserves", + 18: "OperationTypeRevokeSponsorship", + 19: "OperationTypeClawback", + 20: "OperationTypeClawbackClaimableBalance", + 21: "OperationTypeSetTrustLineFlags", + 22: "OperationTypeLiquidityPoolDeposit", + 23: "OperationTypeLiquidityPoolWithdraw", + 24: "OperationTypeInvokeHostFunction", + 25: "OperationTypeExtendFootprintTtl", + 26: "OperationTypeRestoreFootprint", +} + +// ValidEnum validates a proposed value for this enum. Implements +// the Enum interface for OperationType +func (e OperationType) ValidEnum(v int32) bool { + _, ok := operationTypeMap[v] + return ok +} + +// String returns the name of `e` +func (e OperationType) String() string { + name, _ := operationTypeMap[int32(e)] + return name +} + +// EncodeTo encodes this value using the Encoder. +func (e OperationType) EncodeTo(enc *xdr.Encoder) error { + if _, ok := operationTypeMap[int32(e)]; !ok { + return fmt.Errorf("'%d' is not a valid OperationType enum value", e) + } + _, err := enc.EncodeInt(int32(e)) + return err +} + +var _ decoderFrom = (*OperationType)(nil) + +// DecodeFrom decodes this value using the Decoder. +func (e *OperationType) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding OperationType: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + v, n, err := d.DecodeInt() + if err != nil { + return n, fmt.Errorf("decoding OperationType: %w", err) + } + if _, ok := operationTypeMap[v]; !ok { + return n, fmt.Errorf("'%d' is not a valid OperationType enum value", v) + } + *e = OperationType(v) + return n, nil +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (s OperationType) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *OperationType) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} + +var ( + _ encoding.BinaryMarshaler = (*OperationType)(nil) + _ encoding.BinaryUnmarshaler = (*OperationType)(nil) +) + +// xdrType signals that this type represents XDR values defined by this package. +func (s OperationType) xdrType() {} + +var _ xdrType = (*OperationType)(nil) + +// CreateAccountOp is an XDR Struct defines as: +// +// struct CreateAccountOp +// { +// AccountID destination; // account to create +// int64 startingBalance; // amount they end up with +// }; +type CreateAccountOp struct { + Destination AccountId + StartingBalance Int64 +} + +// EncodeTo encodes this value using the Encoder. +func (s *CreateAccountOp) EncodeTo(e *xdr.Encoder) error { + var err error + if err = s.Destination.EncodeTo(e); err != nil { + return err + } + if err = s.StartingBalance.EncodeTo(e); err != nil { + return err + } + return nil +} + +var _ decoderFrom = (*CreateAccountOp)(nil) + +// DecodeFrom decodes this value using the Decoder. +func (s *CreateAccountOp) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding CreateAccountOp: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + var err error + var n, nTmp int + nTmp, err = s.Destination.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding AccountId: %w", err) + } + nTmp, err = s.StartingBalance.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Int64: %w", err) + } + return n, nil +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (s CreateAccountOp) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *CreateAccountOp) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} + +var ( + _ encoding.BinaryMarshaler = (*CreateAccountOp)(nil) + _ encoding.BinaryUnmarshaler = (*CreateAccountOp)(nil) +) + +// xdrType signals that this type represents XDR values defined by this package. +func (s CreateAccountOp) xdrType() {} + +var _ xdrType = (*CreateAccountOp)(nil) + +// PaymentOp is an XDR Struct defines as: +// +// struct PaymentOp +// { +// MuxedAccount destination; // recipient of the payment +// Asset asset; // what they end up with +// int64 amount; // amount they end up with +// }; +type PaymentOp struct { + Destination MuxedAccount + Asset Asset + Amount Int64 +} + +// EncodeTo encodes this value using the Encoder. +func (s *PaymentOp) EncodeTo(e *xdr.Encoder) error { + var err error + if err = s.Destination.EncodeTo(e); err != nil { + return err + } + if err = s.Asset.EncodeTo(e); err != nil { + return err + } + if err = s.Amount.EncodeTo(e); err != nil { + return err + } + return nil +} + +var _ decoderFrom = (*PaymentOp)(nil) + +// DecodeFrom decodes this value using the Decoder. +func (s *PaymentOp) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding PaymentOp: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + var err error + var n, nTmp int + nTmp, err = s.Destination.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding MuxedAccount: %w", err) + } + nTmp, err = s.Asset.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Asset: %w", err) + } + nTmp, err = s.Amount.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Int64: %w", err) + } + return n, nil +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (s PaymentOp) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *PaymentOp) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} + +var ( + _ encoding.BinaryMarshaler = (*PaymentOp)(nil) + _ encoding.BinaryUnmarshaler = (*PaymentOp)(nil) +) + +// xdrType signals that this type represents XDR values defined by this package. +func (s PaymentOp) xdrType() {} + +var _ xdrType = (*PaymentOp)(nil) + +// PathPaymentStrictReceiveOp is an XDR Struct defines as: +// +// struct PathPaymentStrictReceiveOp +// { +// Asset sendAsset; // asset we pay with +// int64 sendMax; // the maximum amount of sendAsset to +// // send (excluding fees). +// // The operation will fail if can't be met +// +// MuxedAccount destination; // recipient of the payment +// Asset destAsset; // what they end up with +// int64 destAmount; // amount they end up with +// +// Asset path<5>; // additional hops it must go through to get there +// }; +type PathPaymentStrictReceiveOp struct { + SendAsset Asset + SendMax Int64 + Destination MuxedAccount + DestAsset Asset + DestAmount Int64 + Path []Asset `xdrmaxsize:"5"` +} + +// EncodeTo encodes this value using the Encoder. +func (s *PathPaymentStrictReceiveOp) EncodeTo(e *xdr.Encoder) error { + var err error + if err = s.SendAsset.EncodeTo(e); err != nil { + return err + } + if err = s.SendMax.EncodeTo(e); err != nil { + return err + } + if err = s.Destination.EncodeTo(e); err != nil { + return err + } + if err = s.DestAsset.EncodeTo(e); err != nil { + return err + } + if err = s.DestAmount.EncodeTo(e); err != nil { + return err + } + if _, err = e.EncodeUint(uint32(len(s.Path))); err != nil { + return err + } + for i := 0; i < len(s.Path); i++ { + if err = s.Path[i].EncodeTo(e); err != nil { + return err + } + } + return nil +} + +var _ decoderFrom = (*PathPaymentStrictReceiveOp)(nil) + +// DecodeFrom decodes this value using the Decoder. +func (s *PathPaymentStrictReceiveOp) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding PathPaymentStrictReceiveOp: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + var err error + var n, nTmp int + nTmp, err = s.SendAsset.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Asset: %w", err) + } + nTmp, err = s.SendMax.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Int64: %w", err) + } + nTmp, err = s.Destination.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding MuxedAccount: %w", err) + } + nTmp, err = s.DestAsset.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Asset: %w", err) + } + nTmp, err = s.DestAmount.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Int64: %w", err) + } + var l uint32 + l, nTmp, err = d.DecodeUint() + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Asset: %w", err) + } + if l > 5 { + return n, fmt.Errorf("decoding Asset: data size (%d) exceeds size limit (5)", l) + } + s.Path = nil + if l > 0 { + if il, ok := d.InputLen(); ok && uint(il) < uint(l) { + return n, fmt.Errorf("decoding Asset: length (%d) exceeds remaining input length (%d)", l, il) + } + s.Path = make([]Asset, l) + for i := uint32(0); i < l; i++ { + nTmp, err = s.Path[i].DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Asset: %w", err) + } + } + } + return n, nil +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (s PathPaymentStrictReceiveOp) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *PathPaymentStrictReceiveOp) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} + +var ( + _ encoding.BinaryMarshaler = (*PathPaymentStrictReceiveOp)(nil) + _ encoding.BinaryUnmarshaler = (*PathPaymentStrictReceiveOp)(nil) +) + +// xdrType signals that this type represents XDR values defined by this package. +func (s PathPaymentStrictReceiveOp) xdrType() {} + +var _ xdrType = (*PathPaymentStrictReceiveOp)(nil) + +// PathPaymentStrictSendOp is an XDR Struct defines as: +// +// struct PathPaymentStrictSendOp +// { +// Asset sendAsset; // asset we pay with +// int64 sendAmount; // amount of sendAsset to send (excluding fees) +// +// MuxedAccount destination; // recipient of the payment +// Asset destAsset; // what they end up with +// int64 destMin; // the minimum amount of dest asset to +// // be received +// // The operation will fail if it can't be met +// +// Asset path<5>; // additional hops it must go through to get there +// }; +type PathPaymentStrictSendOp struct { + SendAsset Asset + SendAmount Int64 + Destination MuxedAccount + DestAsset Asset + DestMin Int64 + Path []Asset `xdrmaxsize:"5"` +} + +// EncodeTo encodes this value using the Encoder. +func (s *PathPaymentStrictSendOp) EncodeTo(e *xdr.Encoder) error { + var err error + if err = s.SendAsset.EncodeTo(e); err != nil { + return err + } + if err = s.SendAmount.EncodeTo(e); err != nil { + return err + } + if err = s.Destination.EncodeTo(e); err != nil { + return err + } + if err = s.DestAsset.EncodeTo(e); err != nil { + return err + } + if err = s.DestMin.EncodeTo(e); err != nil { + return err + } + if _, err = e.EncodeUint(uint32(len(s.Path))); err != nil { + return err + } + for i := 0; i < len(s.Path); i++ { + if err = s.Path[i].EncodeTo(e); err != nil { + return err + } + } + return nil +} + +var _ decoderFrom = (*PathPaymentStrictSendOp)(nil) + +// DecodeFrom decodes this value using the Decoder. +func (s *PathPaymentStrictSendOp) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding PathPaymentStrictSendOp: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + var err error + var n, nTmp int + nTmp, err = s.SendAsset.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Asset: %w", err) + } + nTmp, err = s.SendAmount.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Int64: %w", err) + } + nTmp, err = s.Destination.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding MuxedAccount: %w", err) + } + nTmp, err = s.DestAsset.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Asset: %w", err) + } + nTmp, err = s.DestMin.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Int64: %w", err) + } + var l uint32 + l, nTmp, err = d.DecodeUint() + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Asset: %w", err) + } + if l > 5 { + return n, fmt.Errorf("decoding Asset: data size (%d) exceeds size limit (5)", l) + } + s.Path = nil + if l > 0 { + if il, ok := d.InputLen(); ok && uint(il) < uint(l) { + return n, fmt.Errorf("decoding Asset: length (%d) exceeds remaining input length (%d)", l, il) + } + s.Path = make([]Asset, l) + for i := uint32(0); i < l; i++ { + nTmp, err = s.Path[i].DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Asset: %w", err) + } + } + } + return n, nil +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (s PathPaymentStrictSendOp) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *PathPaymentStrictSendOp) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} + +var ( + _ encoding.BinaryMarshaler = (*PathPaymentStrictSendOp)(nil) + _ encoding.BinaryUnmarshaler = (*PathPaymentStrictSendOp)(nil) +) + +// xdrType signals that this type represents XDR values defined by this package. +func (s PathPaymentStrictSendOp) xdrType() {} + +var _ xdrType = (*PathPaymentStrictSendOp)(nil) + +// ManageSellOfferOp is an XDR Struct defines as: +// +// struct ManageSellOfferOp +// { +// Asset selling; +// Asset buying; +// int64 amount; // amount being sold. if set to 0, delete the offer +// Price price; // price of thing being sold in terms of what you are buying +// +// // 0=create a new offer, otherwise edit an existing offer +// int64 offerID; +// }; +type ManageSellOfferOp struct { + Selling Asset + Buying Asset + Amount Int64 + Price Price + OfferId Int64 +} + +// EncodeTo encodes this value using the Encoder. +func (s *ManageSellOfferOp) EncodeTo(e *xdr.Encoder) error { + var err error + if err = s.Selling.EncodeTo(e); err != nil { + return err + } + if err = s.Buying.EncodeTo(e); err != nil { + return err + } + if err = s.Amount.EncodeTo(e); err != nil { + return err + } + if err = s.Price.EncodeTo(e); err != nil { + return err + } + if err = s.OfferId.EncodeTo(e); err != nil { + return err + } + return nil +} + +var _ decoderFrom = (*ManageSellOfferOp)(nil) + +// DecodeFrom decodes this value using the Decoder. +func (s *ManageSellOfferOp) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding ManageSellOfferOp: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + var err error + var n, nTmp int + nTmp, err = s.Selling.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Asset: %w", err) + } + nTmp, err = s.Buying.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Asset: %w", err) + } + nTmp, err = s.Amount.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Int64: %w", err) + } + nTmp, err = s.Price.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Price: %w", err) + } + nTmp, err = s.OfferId.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Int64: %w", err) + } + return n, nil +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (s ManageSellOfferOp) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *ManageSellOfferOp) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} + +var ( + _ encoding.BinaryMarshaler = (*ManageSellOfferOp)(nil) + _ encoding.BinaryUnmarshaler = (*ManageSellOfferOp)(nil) +) + +// xdrType signals that this type represents XDR values defined by this package. +func (s ManageSellOfferOp) xdrType() {} + +var _ xdrType = (*ManageSellOfferOp)(nil) + +// ManageBuyOfferOp is an XDR Struct defines as: +// +// struct ManageBuyOfferOp +// { +// Asset selling; +// Asset buying; +// int64 buyAmount; // amount being bought. if set to 0, delete the offer +// Price price; // price of thing being bought in terms of what you are +// // selling +// +// // 0=create a new offer, otherwise edit an existing offer +// int64 offerID; +// }; +type ManageBuyOfferOp struct { + Selling Asset + Buying Asset + BuyAmount Int64 + Price Price + OfferId Int64 +} + +// EncodeTo encodes this value using the Encoder. +func (s *ManageBuyOfferOp) EncodeTo(e *xdr.Encoder) error { + var err error + if err = s.Selling.EncodeTo(e); err != nil { + return err + } + if err = s.Buying.EncodeTo(e); err != nil { + return err + } + if err = s.BuyAmount.EncodeTo(e); err != nil { + return err + } + if err = s.Price.EncodeTo(e); err != nil { + return err + } + if err = s.OfferId.EncodeTo(e); err != nil { + return err + } + return nil +} + +var _ decoderFrom = (*ManageBuyOfferOp)(nil) + +// DecodeFrom decodes this value using the Decoder. +func (s *ManageBuyOfferOp) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding ManageBuyOfferOp: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + var err error + var n, nTmp int + nTmp, err = s.Selling.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Asset: %w", err) + } + nTmp, err = s.Buying.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Asset: %w", err) + } + nTmp, err = s.BuyAmount.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Int64: %w", err) + } + nTmp, err = s.Price.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Price: %w", err) + } + nTmp, err = s.OfferId.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Int64: %w", err) + } + return n, nil +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (s ManageBuyOfferOp) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *ManageBuyOfferOp) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} + +var ( + _ encoding.BinaryMarshaler = (*ManageBuyOfferOp)(nil) + _ encoding.BinaryUnmarshaler = (*ManageBuyOfferOp)(nil) +) + +// xdrType signals that this type represents XDR values defined by this package. +func (s ManageBuyOfferOp) xdrType() {} + +var _ xdrType = (*ManageBuyOfferOp)(nil) + +// CreatePassiveSellOfferOp is an XDR Struct defines as: +// +// struct CreatePassiveSellOfferOp +// { +// Asset selling; // A +// Asset buying; // B +// int64 amount; // amount taker gets +// Price price; // cost of A in terms of B +// }; +type CreatePassiveSellOfferOp struct { + Selling Asset + Buying Asset + Amount Int64 + Price Price +} + +// EncodeTo encodes this value using the Encoder. +func (s *CreatePassiveSellOfferOp) EncodeTo(e *xdr.Encoder) error { + var err error + if err = s.Selling.EncodeTo(e); err != nil { + return err + } + if err = s.Buying.EncodeTo(e); err != nil { + return err + } + if err = s.Amount.EncodeTo(e); err != nil { + return err + } + if err = s.Price.EncodeTo(e); err != nil { + return err + } + return nil +} + +var _ decoderFrom = (*CreatePassiveSellOfferOp)(nil) + +// DecodeFrom decodes this value using the Decoder. +func (s *CreatePassiveSellOfferOp) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding CreatePassiveSellOfferOp: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + var err error + var n, nTmp int + nTmp, err = s.Selling.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Asset: %w", err) + } + nTmp, err = s.Buying.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Asset: %w", err) + } + nTmp, err = s.Amount.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Int64: %w", err) + } + nTmp, err = s.Price.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Price: %w", err) + } + return n, nil +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (s CreatePassiveSellOfferOp) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *CreatePassiveSellOfferOp) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} + +var ( + _ encoding.BinaryMarshaler = (*CreatePassiveSellOfferOp)(nil) + _ encoding.BinaryUnmarshaler = (*CreatePassiveSellOfferOp)(nil) +) + +// xdrType signals that this type represents XDR values defined by this package. +func (s CreatePassiveSellOfferOp) xdrType() {} + +var _ xdrType = (*CreatePassiveSellOfferOp)(nil) + +// SetOptionsOp is an XDR Struct defines as: +// +// struct SetOptionsOp +// { +// AccountID* inflationDest; // sets the inflation destination +// +// uint32* clearFlags; // which flags to clear +// uint32* setFlags; // which flags to set +// +// // account threshold manipulation +// uint32* masterWeight; // weight of the master account +// uint32* lowThreshold; +// uint32* medThreshold; +// uint32* highThreshold; +// +// string32* homeDomain; // sets the home domain +// +// // Add, update or remove a signer for the account +// // signer is deleted if the weight is 0 +// Signer* signer; +// }; +type SetOptionsOp struct { + InflationDest *AccountId + ClearFlags *Uint32 + SetFlags *Uint32 + MasterWeight *Uint32 + LowThreshold *Uint32 + MedThreshold *Uint32 + HighThreshold *Uint32 + HomeDomain *String32 + Signer *Signer +} + +// EncodeTo encodes this value using the Encoder. +func (s *SetOptionsOp) EncodeTo(e *xdr.Encoder) error { + var err error + if _, err = e.EncodeBool(s.InflationDest != nil); err != nil { + return err + } + if s.InflationDest != nil { + if err = (*s.InflationDest).EncodeTo(e); err != nil { + return err + } + } + if _, err = e.EncodeBool(s.ClearFlags != nil); err != nil { + return err + } + if s.ClearFlags != nil { + if err = (*s.ClearFlags).EncodeTo(e); err != nil { + return err + } + } + if _, err = e.EncodeBool(s.SetFlags != nil); err != nil { + return err + } + if s.SetFlags != nil { + if err = (*s.SetFlags).EncodeTo(e); err != nil { + return err + } + } + if _, err = e.EncodeBool(s.MasterWeight != nil); err != nil { + return err + } + if s.MasterWeight != nil { + if err = (*s.MasterWeight).EncodeTo(e); err != nil { + return err + } + } + if _, err = e.EncodeBool(s.LowThreshold != nil); err != nil { + return err + } + if s.LowThreshold != nil { + if err = (*s.LowThreshold).EncodeTo(e); err != nil { + return err + } + } + if _, err = e.EncodeBool(s.MedThreshold != nil); err != nil { + return err + } + if s.MedThreshold != nil { + if err = (*s.MedThreshold).EncodeTo(e); err != nil { + return err + } + } + if _, err = e.EncodeBool(s.HighThreshold != nil); err != nil { + return err + } + if s.HighThreshold != nil { + if err = (*s.HighThreshold).EncodeTo(e); err != nil { + return err + } + } + if _, err = e.EncodeBool(s.HomeDomain != nil); err != nil { + return err + } + if s.HomeDomain != nil { + if err = (*s.HomeDomain).EncodeTo(e); err != nil { + return err + } + } + if _, err = e.EncodeBool(s.Signer != nil); err != nil { + return err + } + if s.Signer != nil { + if err = (*s.Signer).EncodeTo(e); err != nil { + return err + } + } + return nil +} + +var _ decoderFrom = (*SetOptionsOp)(nil) + +// DecodeFrom decodes this value using the Decoder. +func (s *SetOptionsOp) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding SetOptionsOp: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + var err error + var n, nTmp int + var b bool + b, nTmp, err = d.DecodeBool() + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding AccountId: %w", err) + } + s.InflationDest = nil + if b { + s.InflationDest = new(AccountId) + nTmp, err = s.InflationDest.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding AccountId: %w", err) + } + } + b, nTmp, err = d.DecodeBool() + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Uint32: %w", err) + } + s.ClearFlags = nil + if b { + s.ClearFlags = new(Uint32) + nTmp, err = s.ClearFlags.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Uint32: %w", err) + } + } + b, nTmp, err = d.DecodeBool() + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Uint32: %w", err) + } + s.SetFlags = nil + if b { + s.SetFlags = new(Uint32) + nTmp, err = s.SetFlags.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Uint32: %w", err) + } + } + b, nTmp, err = d.DecodeBool() + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Uint32: %w", err) + } + s.MasterWeight = nil + if b { + s.MasterWeight = new(Uint32) + nTmp, err = s.MasterWeight.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Uint32: %w", err) + } + } + b, nTmp, err = d.DecodeBool() + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Uint32: %w", err) + } + s.LowThreshold = nil + if b { + s.LowThreshold = new(Uint32) + nTmp, err = s.LowThreshold.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Uint32: %w", err) + } + } + b, nTmp, err = d.DecodeBool() + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Uint32: %w", err) + } + s.MedThreshold = nil + if b { + s.MedThreshold = new(Uint32) + nTmp, err = s.MedThreshold.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Uint32: %w", err) + } + } + b, nTmp, err = d.DecodeBool() + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Uint32: %w", err) + } + s.HighThreshold = nil + if b { + s.HighThreshold = new(Uint32) + nTmp, err = s.HighThreshold.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Uint32: %w", err) + } + } + b, nTmp, err = d.DecodeBool() + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding String32: %w", err) + } + s.HomeDomain = nil + if b { + s.HomeDomain = new(String32) + nTmp, err = s.HomeDomain.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding String32: %w", err) + } + } + b, nTmp, err = d.DecodeBool() + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Signer: %w", err) + } + s.Signer = nil + if b { + s.Signer = new(Signer) + nTmp, err = s.Signer.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Signer: %w", err) + } + } + return n, nil +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (s SetOptionsOp) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *SetOptionsOp) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} + +var ( + _ encoding.BinaryMarshaler = (*SetOptionsOp)(nil) + _ encoding.BinaryUnmarshaler = (*SetOptionsOp)(nil) +) + +// xdrType signals that this type represents XDR values defined by this package. +func (s SetOptionsOp) xdrType() {} + +var _ xdrType = (*SetOptionsOp)(nil) + +// ChangeTrustAsset is an XDR Union defines as: +// +// union ChangeTrustAsset switch (AssetType type) +// { +// case ASSET_TYPE_NATIVE: // Not credit +// void; +// +// case ASSET_TYPE_CREDIT_ALPHANUM4: +// AlphaNum4 alphaNum4; +// +// case ASSET_TYPE_CREDIT_ALPHANUM12: +// AlphaNum12 alphaNum12; +// +// case ASSET_TYPE_POOL_SHARE: +// LiquidityPoolParameters liquidityPool; +// +// // add other asset types here in the future +// }; +type ChangeTrustAsset struct { + Type AssetType + AlphaNum4 *AlphaNum4 + AlphaNum12 *AlphaNum12 + LiquidityPool *LiquidityPoolParameters +} + +// SwitchFieldName returns the field name in which this union's +// discriminant is stored +func (u ChangeTrustAsset) SwitchFieldName() string { + return "Type" +} + +// ArmForSwitch returns which field name should be used for storing +// the value for an instance of ChangeTrustAsset +func (u ChangeTrustAsset) ArmForSwitch(sw int32) (string, bool) { + switch AssetType(sw) { + case AssetTypeAssetTypeNative: + return "", true + case AssetTypeAssetTypeCreditAlphanum4: + return "AlphaNum4", true + case AssetTypeAssetTypeCreditAlphanum12: + return "AlphaNum12", true + case AssetTypeAssetTypePoolShare: + return "LiquidityPool", true + } + return "-", false +} + +// NewChangeTrustAsset creates a new ChangeTrustAsset. +func NewChangeTrustAsset(aType AssetType, value interface{}) (result ChangeTrustAsset, err error) { + result.Type = aType + switch AssetType(aType) { + case AssetTypeAssetTypeNative: + // void + case AssetTypeAssetTypeCreditAlphanum4: + tv, ok := value.(AlphaNum4) + if !ok { + err = errors.New("invalid value, must be AlphaNum4") + return + } + result.AlphaNum4 = &tv + case AssetTypeAssetTypeCreditAlphanum12: + tv, ok := value.(AlphaNum12) + if !ok { + err = errors.New("invalid value, must be AlphaNum12") + return + } + result.AlphaNum12 = &tv + case AssetTypeAssetTypePoolShare: + tv, ok := value.(LiquidityPoolParameters) + if !ok { + err = errors.New("invalid value, must be LiquidityPoolParameters") + return + } + result.LiquidityPool = &tv + } + return +} + +// MustAlphaNum4 retrieves the AlphaNum4 value from the union, +// panicing if the value is not set. +func (u ChangeTrustAsset) MustAlphaNum4() AlphaNum4 { + val, ok := u.GetAlphaNum4() + + if !ok { + panic("arm AlphaNum4 is not set") + } + + return val +} + +// GetAlphaNum4 retrieves the AlphaNum4 value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u ChangeTrustAsset) GetAlphaNum4() (result AlphaNum4, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) + + if armName == "AlphaNum4" { + result = *u.AlphaNum4 + ok = true + } + + return +} + +// MustAlphaNum12 retrieves the AlphaNum12 value from the union, +// panicing if the value is not set. +func (u ChangeTrustAsset) MustAlphaNum12() AlphaNum12 { + val, ok := u.GetAlphaNum12() + + if !ok { + panic("arm AlphaNum12 is not set") + } + + return val +} + +// GetAlphaNum12 retrieves the AlphaNum12 value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u ChangeTrustAsset) GetAlphaNum12() (result AlphaNum12, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) + + if armName == "AlphaNum12" { + result = *u.AlphaNum12 + ok = true + } + + return +} + +// MustLiquidityPool retrieves the LiquidityPool value from the union, +// panicing if the value is not set. +func (u ChangeTrustAsset) MustLiquidityPool() LiquidityPoolParameters { + val, ok := u.GetLiquidityPool() + + if !ok { + panic("arm LiquidityPool is not set") + } + + return val +} + +// GetLiquidityPool retrieves the LiquidityPool value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u ChangeTrustAsset) GetLiquidityPool() (result LiquidityPoolParameters, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) + + if armName == "LiquidityPool" { + result = *u.LiquidityPool + ok = true + } + + return +} + +// EncodeTo encodes this value using the Encoder. +func (u ChangeTrustAsset) EncodeTo(e *xdr.Encoder) error { + var err error + if err = u.Type.EncodeTo(e); err != nil { + return err + } + switch AssetType(u.Type) { + case AssetTypeAssetTypeNative: + // Void + return nil + case AssetTypeAssetTypeCreditAlphanum4: + if err = (*u.AlphaNum4).EncodeTo(e); err != nil { + return err + } + return nil + case AssetTypeAssetTypeCreditAlphanum12: + if err = (*u.AlphaNum12).EncodeTo(e); err != nil { + return err + } + return nil + case AssetTypeAssetTypePoolShare: + if err = (*u.LiquidityPool).EncodeTo(e); err != nil { + return err + } + return nil + } + return fmt.Errorf("Type (AssetType) switch value '%d' is not valid for union ChangeTrustAsset", u.Type) +} + +var _ decoderFrom = (*ChangeTrustAsset)(nil) + +// DecodeFrom decodes this value using the Decoder. +func (u *ChangeTrustAsset) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding ChangeTrustAsset: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + var err error + var n, nTmp int + nTmp, err = u.Type.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding AssetType: %w", err) + } + switch AssetType(u.Type) { + case AssetTypeAssetTypeNative: + // Void + return n, nil + case AssetTypeAssetTypeCreditAlphanum4: + u.AlphaNum4 = new(AlphaNum4) + nTmp, err = (*u.AlphaNum4).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding AlphaNum4: %w", err) + } + return n, nil + case AssetTypeAssetTypeCreditAlphanum12: + u.AlphaNum12 = new(AlphaNum12) + nTmp, err = (*u.AlphaNum12).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding AlphaNum12: %w", err) + } + return n, nil + case AssetTypeAssetTypePoolShare: + u.LiquidityPool = new(LiquidityPoolParameters) + nTmp, err = (*u.LiquidityPool).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding LiquidityPoolParameters: %w", err) + } + return n, nil + } + return n, fmt.Errorf("union ChangeTrustAsset has invalid Type (AssetType) switch value '%d'", u.Type) +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (s ChangeTrustAsset) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *ChangeTrustAsset) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} + +var ( + _ encoding.BinaryMarshaler = (*ChangeTrustAsset)(nil) + _ encoding.BinaryUnmarshaler = (*ChangeTrustAsset)(nil) +) + +// xdrType signals that this type represents XDR values defined by this package. +func (s ChangeTrustAsset) xdrType() {} + +var _ xdrType = (*ChangeTrustAsset)(nil) + +// ChangeTrustOp is an XDR Struct defines as: +// +// struct ChangeTrustOp +// { +// ChangeTrustAsset line; +// +// // if limit is set to 0, deletes the trust line +// int64 limit; +// }; +type ChangeTrustOp struct { + Line ChangeTrustAsset + Limit Int64 +} + +// EncodeTo encodes this value using the Encoder. +func (s *ChangeTrustOp) EncodeTo(e *xdr.Encoder) error { + var err error + if err = s.Line.EncodeTo(e); err != nil { + return err + } + if err = s.Limit.EncodeTo(e); err != nil { + return err + } + return nil +} + +var _ decoderFrom = (*ChangeTrustOp)(nil) + +// DecodeFrom decodes this value using the Decoder. +func (s *ChangeTrustOp) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding ChangeTrustOp: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + var err error + var n, nTmp int + nTmp, err = s.Line.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ChangeTrustAsset: %w", err) + } + nTmp, err = s.Limit.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Int64: %w", err) + } + return n, nil +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (s ChangeTrustOp) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *ChangeTrustOp) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} + +var ( + _ encoding.BinaryMarshaler = (*ChangeTrustOp)(nil) + _ encoding.BinaryUnmarshaler = (*ChangeTrustOp)(nil) +) + +// xdrType signals that this type represents XDR values defined by this package. +func (s ChangeTrustOp) xdrType() {} + +var _ xdrType = (*ChangeTrustOp)(nil) + +// AllowTrustOp is an XDR Struct defines as: +// +// struct AllowTrustOp +// { +// AccountID trustor; +// AssetCode asset; +// +// // One of 0, AUTHORIZED_FLAG, or AUTHORIZED_TO_MAINTAIN_LIABILITIES_FLAG +// uint32 authorize; +// }; +type AllowTrustOp struct { + Trustor AccountId + Asset AssetCode + Authorize Uint32 +} + +// EncodeTo encodes this value using the Encoder. +func (s *AllowTrustOp) EncodeTo(e *xdr.Encoder) error { + var err error + if err = s.Trustor.EncodeTo(e); err != nil { + return err + } + if err = s.Asset.EncodeTo(e); err != nil { + return err + } + if err = s.Authorize.EncodeTo(e); err != nil { + return err + } + return nil +} + +var _ decoderFrom = (*AllowTrustOp)(nil) + +// DecodeFrom decodes this value using the Decoder. +func (s *AllowTrustOp) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding AllowTrustOp: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + var err error + var n, nTmp int + nTmp, err = s.Trustor.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding AccountId: %w", err) + } + nTmp, err = s.Asset.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding AssetCode: %w", err) + } + nTmp, err = s.Authorize.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Uint32: %w", err) + } + return n, nil +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (s AllowTrustOp) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *AllowTrustOp) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} + +var ( + _ encoding.BinaryMarshaler = (*AllowTrustOp)(nil) + _ encoding.BinaryUnmarshaler = (*AllowTrustOp)(nil) +) + +// xdrType signals that this type represents XDR values defined by this package. +func (s AllowTrustOp) xdrType() {} + +var _ xdrType = (*AllowTrustOp)(nil) + +// ManageDataOp is an XDR Struct defines as: +// +// struct ManageDataOp +// { +// string64 dataName; +// DataValue* dataValue; // set to null to clear +// }; +type ManageDataOp struct { + DataName String64 + DataValue *DataValue +} + +// EncodeTo encodes this value using the Encoder. +func (s *ManageDataOp) EncodeTo(e *xdr.Encoder) error { + var err error + if err = s.DataName.EncodeTo(e); err != nil { + return err + } + if _, err = e.EncodeBool(s.DataValue != nil); err != nil { + return err + } + if s.DataValue != nil { + if err = (*s.DataValue).EncodeTo(e); err != nil { + return err + } + } + return nil +} + +var _ decoderFrom = (*ManageDataOp)(nil) + +// DecodeFrom decodes this value using the Decoder. +func (s *ManageDataOp) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding ManageDataOp: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + var err error + var n, nTmp int + nTmp, err = s.DataName.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding String64: %w", err) + } + var b bool + b, nTmp, err = d.DecodeBool() + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding DataValue: %w", err) + } + s.DataValue = nil + if b { + s.DataValue = new(DataValue) + nTmp, err = s.DataValue.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding DataValue: %w", err) + } + } + return n, nil +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (s ManageDataOp) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *ManageDataOp) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} + +var ( + _ encoding.BinaryMarshaler = (*ManageDataOp)(nil) + _ encoding.BinaryUnmarshaler = (*ManageDataOp)(nil) +) + +// xdrType signals that this type represents XDR values defined by this package. +func (s ManageDataOp) xdrType() {} + +var _ xdrType = (*ManageDataOp)(nil) + +// BumpSequenceOp is an XDR Struct defines as: +// +// struct BumpSequenceOp +// { +// SequenceNumber bumpTo; +// }; +type BumpSequenceOp struct { + BumpTo SequenceNumber +} + +// EncodeTo encodes this value using the Encoder. +func (s *BumpSequenceOp) EncodeTo(e *xdr.Encoder) error { + var err error + if err = s.BumpTo.EncodeTo(e); err != nil { + return err + } + return nil +} + +var _ decoderFrom = (*BumpSequenceOp)(nil) + +// DecodeFrom decodes this value using the Decoder. +func (s *BumpSequenceOp) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding BumpSequenceOp: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + var err error + var n, nTmp int + nTmp, err = s.BumpTo.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding SequenceNumber: %w", err) + } + return n, nil +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (s BumpSequenceOp) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *BumpSequenceOp) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} + +var ( + _ encoding.BinaryMarshaler = (*BumpSequenceOp)(nil) + _ encoding.BinaryUnmarshaler = (*BumpSequenceOp)(nil) +) + +// xdrType signals that this type represents XDR values defined by this package. +func (s BumpSequenceOp) xdrType() {} + +var _ xdrType = (*BumpSequenceOp)(nil) + +// CreateClaimableBalanceOp is an XDR Struct defines as: +// +// struct CreateClaimableBalanceOp +// { +// Asset asset; +// int64 amount; +// Claimant claimants<10>; +// }; +type CreateClaimableBalanceOp struct { + Asset Asset + Amount Int64 + Claimants []Claimant `xdrmaxsize:"10"` +} + +// EncodeTo encodes this value using the Encoder. +func (s *CreateClaimableBalanceOp) EncodeTo(e *xdr.Encoder) error { + var err error + if err = s.Asset.EncodeTo(e); err != nil { + return err + } + if err = s.Amount.EncodeTo(e); err != nil { + return err + } + if _, err = e.EncodeUint(uint32(len(s.Claimants))); err != nil { + return err + } + for i := 0; i < len(s.Claimants); i++ { + if err = s.Claimants[i].EncodeTo(e); err != nil { + return err + } + } + return nil +} + +var _ decoderFrom = (*CreateClaimableBalanceOp)(nil) + +// DecodeFrom decodes this value using the Decoder. +func (s *CreateClaimableBalanceOp) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding CreateClaimableBalanceOp: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + var err error + var n, nTmp int + nTmp, err = s.Asset.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Asset: %w", err) + } + nTmp, err = s.Amount.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Int64: %w", err) + } + var l uint32 + l, nTmp, err = d.DecodeUint() + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Claimant: %w", err) + } + if l > 10 { + return n, fmt.Errorf("decoding Claimant: data size (%d) exceeds size limit (10)", l) + } + s.Claimants = nil + if l > 0 { + if il, ok := d.InputLen(); ok && uint(il) < uint(l) { + return n, fmt.Errorf("decoding Claimant: length (%d) exceeds remaining input length (%d)", l, il) + } + s.Claimants = make([]Claimant, l) + for i := uint32(0); i < l; i++ { + nTmp, err = s.Claimants[i].DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Claimant: %w", err) + } + } + } + return n, nil +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (s CreateClaimableBalanceOp) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *CreateClaimableBalanceOp) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} + +var ( + _ encoding.BinaryMarshaler = (*CreateClaimableBalanceOp)(nil) + _ encoding.BinaryUnmarshaler = (*CreateClaimableBalanceOp)(nil) +) + +// xdrType signals that this type represents XDR values defined by this package. +func (s CreateClaimableBalanceOp) xdrType() {} + +var _ xdrType = (*CreateClaimableBalanceOp)(nil) + +// ClaimClaimableBalanceOp is an XDR Struct defines as: +// +// struct ClaimClaimableBalanceOp +// { +// ClaimableBalanceID balanceID; +// }; +type ClaimClaimableBalanceOp struct { + BalanceId ClaimableBalanceId +} + +// EncodeTo encodes this value using the Encoder. +func (s *ClaimClaimableBalanceOp) EncodeTo(e *xdr.Encoder) error { + var err error + if err = s.BalanceId.EncodeTo(e); err != nil { + return err + } + return nil +} + +var _ decoderFrom = (*ClaimClaimableBalanceOp)(nil) + +// DecodeFrom decodes this value using the Decoder. +func (s *ClaimClaimableBalanceOp) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding ClaimClaimableBalanceOp: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + var err error + var n, nTmp int + nTmp, err = s.BalanceId.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ClaimableBalanceId: %w", err) + } + return n, nil +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (s ClaimClaimableBalanceOp) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *ClaimClaimableBalanceOp) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} + +var ( + _ encoding.BinaryMarshaler = (*ClaimClaimableBalanceOp)(nil) + _ encoding.BinaryUnmarshaler = (*ClaimClaimableBalanceOp)(nil) +) + +// xdrType signals that this type represents XDR values defined by this package. +func (s ClaimClaimableBalanceOp) xdrType() {} + +var _ xdrType = (*ClaimClaimableBalanceOp)(nil) + +// BeginSponsoringFutureReservesOp is an XDR Struct defines as: +// +// struct BeginSponsoringFutureReservesOp +// { +// AccountID sponsoredID; +// }; +type BeginSponsoringFutureReservesOp struct { + SponsoredId AccountId +} + +// EncodeTo encodes this value using the Encoder. +func (s *BeginSponsoringFutureReservesOp) EncodeTo(e *xdr.Encoder) error { + var err error + if err = s.SponsoredId.EncodeTo(e); err != nil { + return err + } + return nil +} + +var _ decoderFrom = (*BeginSponsoringFutureReservesOp)(nil) + +// DecodeFrom decodes this value using the Decoder. +func (s *BeginSponsoringFutureReservesOp) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding BeginSponsoringFutureReservesOp: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + var err error + var n, nTmp int + nTmp, err = s.SponsoredId.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding AccountId: %w", err) + } + return n, nil +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (s BeginSponsoringFutureReservesOp) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *BeginSponsoringFutureReservesOp) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} + +var ( + _ encoding.BinaryMarshaler = (*BeginSponsoringFutureReservesOp)(nil) + _ encoding.BinaryUnmarshaler = (*BeginSponsoringFutureReservesOp)(nil) +) + +// xdrType signals that this type represents XDR values defined by this package. +func (s BeginSponsoringFutureReservesOp) xdrType() {} + +var _ xdrType = (*BeginSponsoringFutureReservesOp)(nil) + +// RevokeSponsorshipType is an XDR Enum defines as: +// +// enum RevokeSponsorshipType +// { +// REVOKE_SPONSORSHIP_LEDGER_ENTRY = 0, +// REVOKE_SPONSORSHIP_SIGNER = 1 +// }; +type RevokeSponsorshipType int32 + +const ( + RevokeSponsorshipTypeRevokeSponsorshipLedgerEntry RevokeSponsorshipType = 0 + RevokeSponsorshipTypeRevokeSponsorshipSigner RevokeSponsorshipType = 1 +) + +var revokeSponsorshipTypeMap = map[int32]string{ + 0: "RevokeSponsorshipTypeRevokeSponsorshipLedgerEntry", + 1: "RevokeSponsorshipTypeRevokeSponsorshipSigner", +} + +// ValidEnum validates a proposed value for this enum. Implements +// the Enum interface for RevokeSponsorshipType +func (e RevokeSponsorshipType) ValidEnum(v int32) bool { + _, ok := revokeSponsorshipTypeMap[v] + return ok +} + +// String returns the name of `e` +func (e RevokeSponsorshipType) String() string { + name, _ := revokeSponsorshipTypeMap[int32(e)] + return name +} + +// EncodeTo encodes this value using the Encoder. +func (e RevokeSponsorshipType) EncodeTo(enc *xdr.Encoder) error { + if _, ok := revokeSponsorshipTypeMap[int32(e)]; !ok { + return fmt.Errorf("'%d' is not a valid RevokeSponsorshipType enum value", e) + } + _, err := enc.EncodeInt(int32(e)) + return err +} + +var _ decoderFrom = (*RevokeSponsorshipType)(nil) + +// DecodeFrom decodes this value using the Decoder. +func (e *RevokeSponsorshipType) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding RevokeSponsorshipType: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + v, n, err := d.DecodeInt() + if err != nil { + return n, fmt.Errorf("decoding RevokeSponsorshipType: %w", err) + } + if _, ok := revokeSponsorshipTypeMap[v]; !ok { + return n, fmt.Errorf("'%d' is not a valid RevokeSponsorshipType enum value", v) + } + *e = RevokeSponsorshipType(v) + return n, nil +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (s RevokeSponsorshipType) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *RevokeSponsorshipType) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} + +var ( + _ encoding.BinaryMarshaler = (*RevokeSponsorshipType)(nil) + _ encoding.BinaryUnmarshaler = (*RevokeSponsorshipType)(nil) +) + +// xdrType signals that this type represents XDR values defined by this package. +func (s RevokeSponsorshipType) xdrType() {} + +var _ xdrType = (*RevokeSponsorshipType)(nil) + +// RevokeSponsorshipOpSigner is an XDR NestedStruct defines as: +// +// struct +// { +// AccountID accountID; +// SignerKey signerKey; +// } +type RevokeSponsorshipOpSigner struct { + AccountId AccountId + SignerKey SignerKey +} + +// EncodeTo encodes this value using the Encoder. +func (s *RevokeSponsorshipOpSigner) EncodeTo(e *xdr.Encoder) error { + var err error + if err = s.AccountId.EncodeTo(e); err != nil { + return err + } + if err = s.SignerKey.EncodeTo(e); err != nil { + return err + } + return nil +} + +var _ decoderFrom = (*RevokeSponsorshipOpSigner)(nil) + +// DecodeFrom decodes this value using the Decoder. +func (s *RevokeSponsorshipOpSigner) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding RevokeSponsorshipOpSigner: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + var err error + var n, nTmp int + nTmp, err = s.AccountId.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding AccountId: %w", err) + } + nTmp, err = s.SignerKey.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding SignerKey: %w", err) + } + return n, nil +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (s RevokeSponsorshipOpSigner) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *RevokeSponsorshipOpSigner) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} + +var ( + _ encoding.BinaryMarshaler = (*RevokeSponsorshipOpSigner)(nil) + _ encoding.BinaryUnmarshaler = (*RevokeSponsorshipOpSigner)(nil) +) + +// xdrType signals that this type represents XDR values defined by this package. +func (s RevokeSponsorshipOpSigner) xdrType() {} + +var _ xdrType = (*RevokeSponsorshipOpSigner)(nil) + +// RevokeSponsorshipOp is an XDR Union defines as: +// +// union RevokeSponsorshipOp switch (RevokeSponsorshipType type) +// { +// case REVOKE_SPONSORSHIP_LEDGER_ENTRY: +// LedgerKey ledgerKey; +// case REVOKE_SPONSORSHIP_SIGNER: +// struct +// { +// AccountID accountID; +// SignerKey signerKey; +// } signer; +// }; +type RevokeSponsorshipOp struct { + Type RevokeSponsorshipType + LedgerKey *LedgerKey + Signer *RevokeSponsorshipOpSigner +} + +// SwitchFieldName returns the field name in which this union's +// discriminant is stored +func (u RevokeSponsorshipOp) SwitchFieldName() string { + return "Type" +} + +// ArmForSwitch returns which field name should be used for storing +// the value for an instance of RevokeSponsorshipOp +func (u RevokeSponsorshipOp) ArmForSwitch(sw int32) (string, bool) { + switch RevokeSponsorshipType(sw) { + case RevokeSponsorshipTypeRevokeSponsorshipLedgerEntry: + return "LedgerKey", true + case RevokeSponsorshipTypeRevokeSponsorshipSigner: + return "Signer", true + } + return "-", false +} + +// NewRevokeSponsorshipOp creates a new RevokeSponsorshipOp. +func NewRevokeSponsorshipOp(aType RevokeSponsorshipType, value interface{}) (result RevokeSponsorshipOp, err error) { + result.Type = aType + switch RevokeSponsorshipType(aType) { + case RevokeSponsorshipTypeRevokeSponsorshipLedgerEntry: + tv, ok := value.(LedgerKey) + if !ok { + err = errors.New("invalid value, must be LedgerKey") + return + } + result.LedgerKey = &tv + case RevokeSponsorshipTypeRevokeSponsorshipSigner: + tv, ok := value.(RevokeSponsorshipOpSigner) + if !ok { + err = errors.New("invalid value, must be RevokeSponsorshipOpSigner") + return + } + result.Signer = &tv + } + return +} + +// MustLedgerKey retrieves the LedgerKey value from the union, +// panicing if the value is not set. +func (u RevokeSponsorshipOp) MustLedgerKey() LedgerKey { + val, ok := u.GetLedgerKey() + + if !ok { + panic("arm LedgerKey is not set") + } + + return val +} + +// GetLedgerKey retrieves the LedgerKey value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u RevokeSponsorshipOp) GetLedgerKey() (result LedgerKey, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) + + if armName == "LedgerKey" { + result = *u.LedgerKey + ok = true + } + + return +} + +// MustSigner retrieves the Signer value from the union, +// panicing if the value is not set. +func (u RevokeSponsorshipOp) MustSigner() RevokeSponsorshipOpSigner { + val, ok := u.GetSigner() + + if !ok { + panic("arm Signer is not set") + } + + return val +} + +// GetSigner retrieves the Signer value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u RevokeSponsorshipOp) GetSigner() (result RevokeSponsorshipOpSigner, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) + + if armName == "Signer" { + result = *u.Signer + ok = true + } + + return +} + +// EncodeTo encodes this value using the Encoder. +func (u RevokeSponsorshipOp) EncodeTo(e *xdr.Encoder) error { + var err error + if err = u.Type.EncodeTo(e); err != nil { + return err + } + switch RevokeSponsorshipType(u.Type) { + case RevokeSponsorshipTypeRevokeSponsorshipLedgerEntry: + if err = (*u.LedgerKey).EncodeTo(e); err != nil { + return err + } + return nil + case RevokeSponsorshipTypeRevokeSponsorshipSigner: + if err = (*u.Signer).EncodeTo(e); err != nil { + return err + } + return nil + } + return fmt.Errorf("Type (RevokeSponsorshipType) switch value '%d' is not valid for union RevokeSponsorshipOp", u.Type) +} + +var _ decoderFrom = (*RevokeSponsorshipOp)(nil) + +// DecodeFrom decodes this value using the Decoder. +func (u *RevokeSponsorshipOp) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding RevokeSponsorshipOp: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + var err error + var n, nTmp int + nTmp, err = u.Type.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding RevokeSponsorshipType: %w", err) + } + switch RevokeSponsorshipType(u.Type) { + case RevokeSponsorshipTypeRevokeSponsorshipLedgerEntry: + u.LedgerKey = new(LedgerKey) + nTmp, err = (*u.LedgerKey).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding LedgerKey: %w", err) + } + return n, nil + case RevokeSponsorshipTypeRevokeSponsorshipSigner: + u.Signer = new(RevokeSponsorshipOpSigner) + nTmp, err = (*u.Signer).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding RevokeSponsorshipOpSigner: %w", err) + } + return n, nil + } + return n, fmt.Errorf("union RevokeSponsorshipOp has invalid Type (RevokeSponsorshipType) switch value '%d'", u.Type) +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (s RevokeSponsorshipOp) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *RevokeSponsorshipOp) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} + +var ( + _ encoding.BinaryMarshaler = (*RevokeSponsorshipOp)(nil) + _ encoding.BinaryUnmarshaler = (*RevokeSponsorshipOp)(nil) +) + +// xdrType signals that this type represents XDR values defined by this package. +func (s RevokeSponsorshipOp) xdrType() {} + +var _ xdrType = (*RevokeSponsorshipOp)(nil) + +// ClawbackOp is an XDR Struct defines as: +// +// struct ClawbackOp +// { +// Asset asset; +// MuxedAccount from; +// int64 amount; +// }; +type ClawbackOp struct { + Asset Asset + From MuxedAccount + Amount Int64 +} + +// EncodeTo encodes this value using the Encoder. +func (s *ClawbackOp) EncodeTo(e *xdr.Encoder) error { + var err error + if err = s.Asset.EncodeTo(e); err != nil { + return err + } + if err = s.From.EncodeTo(e); err != nil { + return err + } + if err = s.Amount.EncodeTo(e); err != nil { + return err + } + return nil +} + +var _ decoderFrom = (*ClawbackOp)(nil) + +// DecodeFrom decodes this value using the Decoder. +func (s *ClawbackOp) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding ClawbackOp: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + var err error + var n, nTmp int + nTmp, err = s.Asset.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Asset: %w", err) + } + nTmp, err = s.From.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding MuxedAccount: %w", err) + } + nTmp, err = s.Amount.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Int64: %w", err) + } + return n, nil +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (s ClawbackOp) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *ClawbackOp) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} + +var ( + _ encoding.BinaryMarshaler = (*ClawbackOp)(nil) + _ encoding.BinaryUnmarshaler = (*ClawbackOp)(nil) +) + +// xdrType signals that this type represents XDR values defined by this package. +func (s ClawbackOp) xdrType() {} + +var _ xdrType = (*ClawbackOp)(nil) + +// ClawbackClaimableBalanceOp is an XDR Struct defines as: +// +// struct ClawbackClaimableBalanceOp +// { +// ClaimableBalanceID balanceID; +// }; +type ClawbackClaimableBalanceOp struct { + BalanceId ClaimableBalanceId +} + +// EncodeTo encodes this value using the Encoder. +func (s *ClawbackClaimableBalanceOp) EncodeTo(e *xdr.Encoder) error { + var err error + if err = s.BalanceId.EncodeTo(e); err != nil { + return err + } + return nil +} + +var _ decoderFrom = (*ClawbackClaimableBalanceOp)(nil) + +// DecodeFrom decodes this value using the Decoder. +func (s *ClawbackClaimableBalanceOp) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding ClawbackClaimableBalanceOp: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + var err error + var n, nTmp int + nTmp, err = s.BalanceId.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ClaimableBalanceId: %w", err) + } + return n, nil +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (s ClawbackClaimableBalanceOp) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *ClawbackClaimableBalanceOp) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} + +var ( + _ encoding.BinaryMarshaler = (*ClawbackClaimableBalanceOp)(nil) + _ encoding.BinaryUnmarshaler = (*ClawbackClaimableBalanceOp)(nil) +) + +// xdrType signals that this type represents XDR values defined by this package. +func (s ClawbackClaimableBalanceOp) xdrType() {} + +var _ xdrType = (*ClawbackClaimableBalanceOp)(nil) + +// SetTrustLineFlagsOp is an XDR Struct defines as: +// +// struct SetTrustLineFlagsOp +// { +// AccountID trustor; +// Asset asset; +// +// uint32 clearFlags; // which flags to clear +// uint32 setFlags; // which flags to set +// }; +type SetTrustLineFlagsOp struct { + Trustor AccountId + Asset Asset + ClearFlags Uint32 + SetFlags Uint32 +} + +// EncodeTo encodes this value using the Encoder. +func (s *SetTrustLineFlagsOp) EncodeTo(e *xdr.Encoder) error { + var err error + if err = s.Trustor.EncodeTo(e); err != nil { + return err + } + if err = s.Asset.EncodeTo(e); err != nil { + return err + } + if err = s.ClearFlags.EncodeTo(e); err != nil { + return err + } + if err = s.SetFlags.EncodeTo(e); err != nil { + return err + } + return nil +} + +var _ decoderFrom = (*SetTrustLineFlagsOp)(nil) + +// DecodeFrom decodes this value using the Decoder. +func (s *SetTrustLineFlagsOp) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding SetTrustLineFlagsOp: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + var err error + var n, nTmp int + nTmp, err = s.Trustor.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding AccountId: %w", err) + } + nTmp, err = s.Asset.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Asset: %w", err) + } + nTmp, err = s.ClearFlags.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Uint32: %w", err) + } + nTmp, err = s.SetFlags.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Uint32: %w", err) + } + return n, nil +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (s SetTrustLineFlagsOp) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *SetTrustLineFlagsOp) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} + +var ( + _ encoding.BinaryMarshaler = (*SetTrustLineFlagsOp)(nil) + _ encoding.BinaryUnmarshaler = (*SetTrustLineFlagsOp)(nil) +) + +// xdrType signals that this type represents XDR values defined by this package. +func (s SetTrustLineFlagsOp) xdrType() {} + +var _ xdrType = (*SetTrustLineFlagsOp)(nil) + +// LiquidityPoolFeeV18 is an XDR Const defines as: +// +// const LIQUIDITY_POOL_FEE_V18 = 30; +const LiquidityPoolFeeV18 = 30 + +// LiquidityPoolDepositOp is an XDR Struct defines as: +// +// struct LiquidityPoolDepositOp +// { +// PoolID liquidityPoolID; +// int64 maxAmountA; // maximum amount of first asset to deposit +// int64 maxAmountB; // maximum amount of second asset to deposit +// Price minPrice; // minimum depositA/depositB +// Price maxPrice; // maximum depositA/depositB +// }; +type LiquidityPoolDepositOp struct { + LiquidityPoolId PoolId + MaxAmountA Int64 + MaxAmountB Int64 + MinPrice Price + MaxPrice Price +} + +// EncodeTo encodes this value using the Encoder. +func (s *LiquidityPoolDepositOp) EncodeTo(e *xdr.Encoder) error { + var err error + if err = s.LiquidityPoolId.EncodeTo(e); err != nil { + return err + } + if err = s.MaxAmountA.EncodeTo(e); err != nil { + return err + } + if err = s.MaxAmountB.EncodeTo(e); err != nil { + return err + } + if err = s.MinPrice.EncodeTo(e); err != nil { + return err + } + if err = s.MaxPrice.EncodeTo(e); err != nil { + return err + } + return nil +} + +var _ decoderFrom = (*LiquidityPoolDepositOp)(nil) + +// DecodeFrom decodes this value using the Decoder. +func (s *LiquidityPoolDepositOp) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding LiquidityPoolDepositOp: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + var err error + var n, nTmp int + nTmp, err = s.LiquidityPoolId.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding PoolId: %w", err) + } + nTmp, err = s.MaxAmountA.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Int64: %w", err) + } + nTmp, err = s.MaxAmountB.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Int64: %w", err) + } + nTmp, err = s.MinPrice.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Price: %w", err) + } + nTmp, err = s.MaxPrice.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Price: %w", err) + } + return n, nil +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (s LiquidityPoolDepositOp) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *LiquidityPoolDepositOp) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} + +var ( + _ encoding.BinaryMarshaler = (*LiquidityPoolDepositOp)(nil) + _ encoding.BinaryUnmarshaler = (*LiquidityPoolDepositOp)(nil) +) + +// xdrType signals that this type represents XDR values defined by this package. +func (s LiquidityPoolDepositOp) xdrType() {} + +var _ xdrType = (*LiquidityPoolDepositOp)(nil) + +// LiquidityPoolWithdrawOp is an XDR Struct defines as: +// +// struct LiquidityPoolWithdrawOp +// { +// PoolID liquidityPoolID; +// int64 amount; // amount of pool shares to withdraw +// int64 minAmountA; // minimum amount of first asset to withdraw +// int64 minAmountB; // minimum amount of second asset to withdraw +// }; +type LiquidityPoolWithdrawOp struct { + LiquidityPoolId PoolId + Amount Int64 + MinAmountA Int64 + MinAmountB Int64 +} + +// EncodeTo encodes this value using the Encoder. +func (s *LiquidityPoolWithdrawOp) EncodeTo(e *xdr.Encoder) error { + var err error + if err = s.LiquidityPoolId.EncodeTo(e); err != nil { + return err + } + if err = s.Amount.EncodeTo(e); err != nil { + return err + } + if err = s.MinAmountA.EncodeTo(e); err != nil { + return err + } + if err = s.MinAmountB.EncodeTo(e); err != nil { + return err + } + return nil +} + +var _ decoderFrom = (*LiquidityPoolWithdrawOp)(nil) + +// DecodeFrom decodes this value using the Decoder. +func (s *LiquidityPoolWithdrawOp) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding LiquidityPoolWithdrawOp: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + var err error + var n, nTmp int + nTmp, err = s.LiquidityPoolId.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding PoolId: %w", err) + } + nTmp, err = s.Amount.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Int64: %w", err) + } + nTmp, err = s.MinAmountA.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Int64: %w", err) + } + nTmp, err = s.MinAmountB.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Int64: %w", err) + } + return n, nil +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (s LiquidityPoolWithdrawOp) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *LiquidityPoolWithdrawOp) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} + +var ( + _ encoding.BinaryMarshaler = (*LiquidityPoolWithdrawOp)(nil) + _ encoding.BinaryUnmarshaler = (*LiquidityPoolWithdrawOp)(nil) +) + +// xdrType signals that this type represents XDR values defined by this package. +func (s LiquidityPoolWithdrawOp) xdrType() {} + +var _ xdrType = (*LiquidityPoolWithdrawOp)(nil) + +// HostFunctionType is an XDR Enum defines as: +// +// enum HostFunctionType +// { +// HOST_FUNCTION_TYPE_INVOKE_CONTRACT = 0, +// HOST_FUNCTION_TYPE_CREATE_CONTRACT = 1, +// HOST_FUNCTION_TYPE_UPLOAD_CONTRACT_WASM = 2 +// }; +type HostFunctionType int32 + +const ( + HostFunctionTypeHostFunctionTypeInvokeContract HostFunctionType = 0 + HostFunctionTypeHostFunctionTypeCreateContract HostFunctionType = 1 + HostFunctionTypeHostFunctionTypeUploadContractWasm HostFunctionType = 2 +) + +var hostFunctionTypeMap = map[int32]string{ + 0: "HostFunctionTypeHostFunctionTypeInvokeContract", + 1: "HostFunctionTypeHostFunctionTypeCreateContract", + 2: "HostFunctionTypeHostFunctionTypeUploadContractWasm", +} + +// ValidEnum validates a proposed value for this enum. Implements +// the Enum interface for HostFunctionType +func (e HostFunctionType) ValidEnum(v int32) bool { + _, ok := hostFunctionTypeMap[v] + return ok +} + +// String returns the name of `e` +func (e HostFunctionType) String() string { + name, _ := hostFunctionTypeMap[int32(e)] + return name +} + +// EncodeTo encodes this value using the Encoder. +func (e HostFunctionType) EncodeTo(enc *xdr.Encoder) error { + if _, ok := hostFunctionTypeMap[int32(e)]; !ok { + return fmt.Errorf("'%d' is not a valid HostFunctionType enum value", e) + } + _, err := enc.EncodeInt(int32(e)) + return err +} + +var _ decoderFrom = (*HostFunctionType)(nil) + +// DecodeFrom decodes this value using the Decoder. +func (e *HostFunctionType) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding HostFunctionType: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + v, n, err := d.DecodeInt() + if err != nil { + return n, fmt.Errorf("decoding HostFunctionType: %w", err) + } + if _, ok := hostFunctionTypeMap[v]; !ok { + return n, fmt.Errorf("'%d' is not a valid HostFunctionType enum value", v) + } + *e = HostFunctionType(v) + return n, nil +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (s HostFunctionType) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *HostFunctionType) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} + +var ( + _ encoding.BinaryMarshaler = (*HostFunctionType)(nil) + _ encoding.BinaryUnmarshaler = (*HostFunctionType)(nil) +) + +// xdrType signals that this type represents XDR values defined by this package. +func (s HostFunctionType) xdrType() {} + +var _ xdrType = (*HostFunctionType)(nil) + +// ContractIdPreimageType is an XDR Enum defines as: +// +// enum ContractIDPreimageType +// { +// CONTRACT_ID_PREIMAGE_FROM_ADDRESS = 0, +// CONTRACT_ID_PREIMAGE_FROM_ASSET = 1 +// }; +type ContractIdPreimageType int32 + +const ( + ContractIdPreimageTypeContractIdPreimageFromAddress ContractIdPreimageType = 0 + ContractIdPreimageTypeContractIdPreimageFromAsset ContractIdPreimageType = 1 +) + +var contractIdPreimageTypeMap = map[int32]string{ + 0: "ContractIdPreimageTypeContractIdPreimageFromAddress", + 1: "ContractIdPreimageTypeContractIdPreimageFromAsset", +} + +// ValidEnum validates a proposed value for this enum. Implements +// the Enum interface for ContractIdPreimageType +func (e ContractIdPreimageType) ValidEnum(v int32) bool { + _, ok := contractIdPreimageTypeMap[v] + return ok +} + +// String returns the name of `e` +func (e ContractIdPreimageType) String() string { + name, _ := contractIdPreimageTypeMap[int32(e)] + return name +} + +// EncodeTo encodes this value using the Encoder. +func (e ContractIdPreimageType) EncodeTo(enc *xdr.Encoder) error { + if _, ok := contractIdPreimageTypeMap[int32(e)]; !ok { + return fmt.Errorf("'%d' is not a valid ContractIdPreimageType enum value", e) + } + _, err := enc.EncodeInt(int32(e)) + return err +} + +var _ decoderFrom = (*ContractIdPreimageType)(nil) + +// DecodeFrom decodes this value using the Decoder. +func (e *ContractIdPreimageType) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding ContractIdPreimageType: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + v, n, err := d.DecodeInt() + if err != nil { + return n, fmt.Errorf("decoding ContractIdPreimageType: %w", err) + } + if _, ok := contractIdPreimageTypeMap[v]; !ok { + return n, fmt.Errorf("'%d' is not a valid ContractIdPreimageType enum value", v) + } + *e = ContractIdPreimageType(v) + return n, nil +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (s ContractIdPreimageType) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *ContractIdPreimageType) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} + +var ( + _ encoding.BinaryMarshaler = (*ContractIdPreimageType)(nil) + _ encoding.BinaryUnmarshaler = (*ContractIdPreimageType)(nil) +) + +// xdrType signals that this type represents XDR values defined by this package. +func (s ContractIdPreimageType) xdrType() {} + +var _ xdrType = (*ContractIdPreimageType)(nil) + +// ContractIdPreimageFromAddress is an XDR NestedStruct defines as: +// +// struct +// { +// SCAddress address; +// uint256 salt; +// } +type ContractIdPreimageFromAddress struct { + Address ScAddress + Salt Uint256 +} + +// EncodeTo encodes this value using the Encoder. +func (s *ContractIdPreimageFromAddress) EncodeTo(e *xdr.Encoder) error { + var err error + if err = s.Address.EncodeTo(e); err != nil { + return err + } + if err = s.Salt.EncodeTo(e); err != nil { + return err + } + return nil +} + +var _ decoderFrom = (*ContractIdPreimageFromAddress)(nil) + +// DecodeFrom decodes this value using the Decoder. +func (s *ContractIdPreimageFromAddress) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding ContractIdPreimageFromAddress: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + var err error + var n, nTmp int + nTmp, err = s.Address.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ScAddress: %w", err) + } + nTmp, err = s.Salt.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Uint256: %w", err) + } + return n, nil +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (s ContractIdPreimageFromAddress) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *ContractIdPreimageFromAddress) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} + +var ( + _ encoding.BinaryMarshaler = (*ContractIdPreimageFromAddress)(nil) + _ encoding.BinaryUnmarshaler = (*ContractIdPreimageFromAddress)(nil) +) + +// xdrType signals that this type represents XDR values defined by this package. +func (s ContractIdPreimageFromAddress) xdrType() {} + +var _ xdrType = (*ContractIdPreimageFromAddress)(nil) + +// ContractIdPreimage is an XDR Union defines as: +// +// union ContractIDPreimage switch (ContractIDPreimageType type) +// { +// case CONTRACT_ID_PREIMAGE_FROM_ADDRESS: +// struct +// { +// SCAddress address; +// uint256 salt; +// } fromAddress; +// case CONTRACT_ID_PREIMAGE_FROM_ASSET: +// Asset fromAsset; +// }; +type ContractIdPreimage struct { + Type ContractIdPreimageType + FromAddress *ContractIdPreimageFromAddress + FromAsset *Asset +} + +// SwitchFieldName returns the field name in which this union's +// discriminant is stored +func (u ContractIdPreimage) SwitchFieldName() string { + return "Type" +} + +// ArmForSwitch returns which field name should be used for storing +// the value for an instance of ContractIdPreimage +func (u ContractIdPreimage) ArmForSwitch(sw int32) (string, bool) { + switch ContractIdPreimageType(sw) { + case ContractIdPreimageTypeContractIdPreimageFromAddress: + return "FromAddress", true + case ContractIdPreimageTypeContractIdPreimageFromAsset: + return "FromAsset", true + } + return "-", false +} + +// NewContractIdPreimage creates a new ContractIdPreimage. +func NewContractIdPreimage(aType ContractIdPreimageType, value interface{}) (result ContractIdPreimage, err error) { + result.Type = aType + switch ContractIdPreimageType(aType) { + case ContractIdPreimageTypeContractIdPreimageFromAddress: + tv, ok := value.(ContractIdPreimageFromAddress) + if !ok { + err = errors.New("invalid value, must be ContractIdPreimageFromAddress") + return + } + result.FromAddress = &tv + case ContractIdPreimageTypeContractIdPreimageFromAsset: + tv, ok := value.(Asset) + if !ok { + err = errors.New("invalid value, must be Asset") + return + } + result.FromAsset = &tv + } + return +} + +// MustFromAddress retrieves the FromAddress value from the union, +// panicing if the value is not set. +func (u ContractIdPreimage) MustFromAddress() ContractIdPreimageFromAddress { + val, ok := u.GetFromAddress() + + if !ok { + panic("arm FromAddress is not set") + } + + return val +} + +// GetFromAddress retrieves the FromAddress value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u ContractIdPreimage) GetFromAddress() (result ContractIdPreimageFromAddress, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) + + if armName == "FromAddress" { + result = *u.FromAddress + ok = true + } + + return +} + +// MustFromAsset retrieves the FromAsset value from the union, +// panicing if the value is not set. +func (u ContractIdPreimage) MustFromAsset() Asset { + val, ok := u.GetFromAsset() + + if !ok { + panic("arm FromAsset is not set") + } + + return val +} + +// GetFromAsset retrieves the FromAsset value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u ContractIdPreimage) GetFromAsset() (result Asset, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) + + if armName == "FromAsset" { + result = *u.FromAsset + ok = true + } + + return +} + +// EncodeTo encodes this value using the Encoder. +func (u ContractIdPreimage) EncodeTo(e *xdr.Encoder) error { + var err error + if err = u.Type.EncodeTo(e); err != nil { + return err + } + switch ContractIdPreimageType(u.Type) { + case ContractIdPreimageTypeContractIdPreimageFromAddress: + if err = (*u.FromAddress).EncodeTo(e); err != nil { + return err + } + return nil + case ContractIdPreimageTypeContractIdPreimageFromAsset: + if err = (*u.FromAsset).EncodeTo(e); err != nil { + return err + } + return nil + } + return fmt.Errorf("Type (ContractIdPreimageType) switch value '%d' is not valid for union ContractIdPreimage", u.Type) +} + +var _ decoderFrom = (*ContractIdPreimage)(nil) + +// DecodeFrom decodes this value using the Decoder. +func (u *ContractIdPreimage) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding ContractIdPreimage: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + var err error + var n, nTmp int + nTmp, err = u.Type.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ContractIdPreimageType: %w", err) + } + switch ContractIdPreimageType(u.Type) { + case ContractIdPreimageTypeContractIdPreimageFromAddress: + u.FromAddress = new(ContractIdPreimageFromAddress) + nTmp, err = (*u.FromAddress).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ContractIdPreimageFromAddress: %w", err) + } + return n, nil + case ContractIdPreimageTypeContractIdPreimageFromAsset: + u.FromAsset = new(Asset) + nTmp, err = (*u.FromAsset).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Asset: %w", err) + } + return n, nil + } + return n, fmt.Errorf("union ContractIdPreimage has invalid Type (ContractIdPreimageType) switch value '%d'", u.Type) +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (s ContractIdPreimage) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *ContractIdPreimage) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} + +var ( + _ encoding.BinaryMarshaler = (*ContractIdPreimage)(nil) + _ encoding.BinaryUnmarshaler = (*ContractIdPreimage)(nil) +) + +// xdrType signals that this type represents XDR values defined by this package. +func (s ContractIdPreimage) xdrType() {} + +var _ xdrType = (*ContractIdPreimage)(nil) + +// CreateContractArgs is an XDR Struct defines as: +// +// struct CreateContractArgs +// { +// ContractIDPreimage contractIDPreimage; +// ContractExecutable executable; +// }; +type CreateContractArgs struct { + ContractIdPreimage ContractIdPreimage + Executable ContractExecutable +} + +// EncodeTo encodes this value using the Encoder. +func (s *CreateContractArgs) EncodeTo(e *xdr.Encoder) error { + var err error + if err = s.ContractIdPreimage.EncodeTo(e); err != nil { + return err + } + if err = s.Executable.EncodeTo(e); err != nil { + return err + } + return nil +} + +var _ decoderFrom = (*CreateContractArgs)(nil) + +// DecodeFrom decodes this value using the Decoder. +func (s *CreateContractArgs) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding CreateContractArgs: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + var err error + var n, nTmp int + nTmp, err = s.ContractIdPreimage.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ContractIdPreimage: %w", err) + } + nTmp, err = s.Executable.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ContractExecutable: %w", err) + } + return n, nil +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (s CreateContractArgs) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *CreateContractArgs) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} + +var ( + _ encoding.BinaryMarshaler = (*CreateContractArgs)(nil) + _ encoding.BinaryUnmarshaler = (*CreateContractArgs)(nil) +) + +// xdrType signals that this type represents XDR values defined by this package. +func (s CreateContractArgs) xdrType() {} + +var _ xdrType = (*CreateContractArgs)(nil) + +// InvokeContractArgs is an XDR Struct defines as: +// +// struct InvokeContractArgs { +// SCAddress contractAddress; +// SCSymbol functionName; +// SCVal args<>; +// }; +type InvokeContractArgs struct { + ContractAddress ScAddress + FunctionName ScSymbol + Args []ScVal +} + +// EncodeTo encodes this value using the Encoder. +func (s *InvokeContractArgs) EncodeTo(e *xdr.Encoder) error { + var err error + if err = s.ContractAddress.EncodeTo(e); err != nil { + return err + } + if err = s.FunctionName.EncodeTo(e); err != nil { + return err + } + if _, err = e.EncodeUint(uint32(len(s.Args))); err != nil { + return err + } + for i := 0; i < len(s.Args); i++ { + if err = s.Args[i].EncodeTo(e); err != nil { + return err + } + } + return nil +} + +var _ decoderFrom = (*InvokeContractArgs)(nil) + +// DecodeFrom decodes this value using the Decoder. +func (s *InvokeContractArgs) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding InvokeContractArgs: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + var err error + var n, nTmp int + nTmp, err = s.ContractAddress.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ScAddress: %w", err) + } + nTmp, err = s.FunctionName.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ScSymbol: %w", err) + } + var l uint32 + l, nTmp, err = d.DecodeUint() + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ScVal: %w", err) + } + s.Args = nil + if l > 0 { + if il, ok := d.InputLen(); ok && uint(il) < uint(l) { + return n, fmt.Errorf("decoding ScVal: length (%d) exceeds remaining input length (%d)", l, il) + } + s.Args = make([]ScVal, l) + for i := uint32(0); i < l; i++ { + nTmp, err = s.Args[i].DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ScVal: %w", err) + } + } + } + return n, nil +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (s InvokeContractArgs) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *InvokeContractArgs) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} + +var ( + _ encoding.BinaryMarshaler = (*InvokeContractArgs)(nil) + _ encoding.BinaryUnmarshaler = (*InvokeContractArgs)(nil) +) + +// xdrType signals that this type represents XDR values defined by this package. +func (s InvokeContractArgs) xdrType() {} + +var _ xdrType = (*InvokeContractArgs)(nil) + +// HostFunction is an XDR Union defines as: +// +// union HostFunction switch (HostFunctionType type) +// { +// case HOST_FUNCTION_TYPE_INVOKE_CONTRACT: +// InvokeContractArgs invokeContract; +// case HOST_FUNCTION_TYPE_CREATE_CONTRACT: +// CreateContractArgs createContract; +// case HOST_FUNCTION_TYPE_UPLOAD_CONTRACT_WASM: +// opaque wasm<>; +// }; +type HostFunction struct { + Type HostFunctionType + InvokeContract *InvokeContractArgs + CreateContract *CreateContractArgs + Wasm *[]byte +} + +// SwitchFieldName returns the field name in which this union's +// discriminant is stored +func (u HostFunction) SwitchFieldName() string { + return "Type" +} + +// ArmForSwitch returns which field name should be used for storing +// the value for an instance of HostFunction +func (u HostFunction) ArmForSwitch(sw int32) (string, bool) { + switch HostFunctionType(sw) { + case HostFunctionTypeHostFunctionTypeInvokeContract: + return "InvokeContract", true + case HostFunctionTypeHostFunctionTypeCreateContract: + return "CreateContract", true + case HostFunctionTypeHostFunctionTypeUploadContractWasm: + return "Wasm", true + } + return "-", false +} + +// NewHostFunction creates a new HostFunction. +func NewHostFunction(aType HostFunctionType, value interface{}) (result HostFunction, err error) { + result.Type = aType + switch HostFunctionType(aType) { + case HostFunctionTypeHostFunctionTypeInvokeContract: + tv, ok := value.(InvokeContractArgs) + if !ok { + err = errors.New("invalid value, must be InvokeContractArgs") + return + } + result.InvokeContract = &tv + case HostFunctionTypeHostFunctionTypeCreateContract: + tv, ok := value.(CreateContractArgs) + if !ok { + err = errors.New("invalid value, must be CreateContractArgs") + return + } + result.CreateContract = &tv + case HostFunctionTypeHostFunctionTypeUploadContractWasm: + tv, ok := value.([]byte) + if !ok { + err = errors.New("invalid value, must be []byte") + return + } + result.Wasm = &tv + } + return +} + +// MustInvokeContract retrieves the InvokeContract value from the union, +// panicing if the value is not set. +func (u HostFunction) MustInvokeContract() InvokeContractArgs { + val, ok := u.GetInvokeContract() + + if !ok { + panic("arm InvokeContract is not set") + } + + return val +} + +// GetInvokeContract retrieves the InvokeContract value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u HostFunction) GetInvokeContract() (result InvokeContractArgs, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) + + if armName == "InvokeContract" { + result = *u.InvokeContract + ok = true + } + + return +} + +// MustCreateContract retrieves the CreateContract value from the union, +// panicing if the value is not set. +func (u HostFunction) MustCreateContract() CreateContractArgs { + val, ok := u.GetCreateContract() + + if !ok { + panic("arm CreateContract is not set") + } + + return val +} + +// GetCreateContract retrieves the CreateContract value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u HostFunction) GetCreateContract() (result CreateContractArgs, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) + + if armName == "CreateContract" { + result = *u.CreateContract + ok = true + } + + return +} + +// MustWasm retrieves the Wasm value from the union, +// panicing if the value is not set. +func (u HostFunction) MustWasm() []byte { + val, ok := u.GetWasm() + + if !ok { + panic("arm Wasm is not set") + } + + return val +} + +// GetWasm retrieves the Wasm value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u HostFunction) GetWasm() (result []byte, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) + + if armName == "Wasm" { + result = *u.Wasm + ok = true + } + + return +} + +// EncodeTo encodes this value using the Encoder. +func (u HostFunction) EncodeTo(e *xdr.Encoder) error { + var err error + if err = u.Type.EncodeTo(e); err != nil { + return err + } + switch HostFunctionType(u.Type) { + case HostFunctionTypeHostFunctionTypeInvokeContract: + if err = (*u.InvokeContract).EncodeTo(e); err != nil { + return err + } + return nil + case HostFunctionTypeHostFunctionTypeCreateContract: + if err = (*u.CreateContract).EncodeTo(e); err != nil { + return err + } + return nil + case HostFunctionTypeHostFunctionTypeUploadContractWasm: + if _, err = e.EncodeOpaque((*u.Wasm)[:]); err != nil { + return err + } + return nil + } + return fmt.Errorf("Type (HostFunctionType) switch value '%d' is not valid for union HostFunction", u.Type) +} + +var _ decoderFrom = (*HostFunction)(nil) + +// DecodeFrom decodes this value using the Decoder. +func (u *HostFunction) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding HostFunction: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + var err error + var n, nTmp int + nTmp, err = u.Type.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding HostFunctionType: %w", err) + } + switch HostFunctionType(u.Type) { + case HostFunctionTypeHostFunctionTypeInvokeContract: + u.InvokeContract = new(InvokeContractArgs) + nTmp, err = (*u.InvokeContract).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding InvokeContractArgs: %w", err) + } + return n, nil + case HostFunctionTypeHostFunctionTypeCreateContract: + u.CreateContract = new(CreateContractArgs) + nTmp, err = (*u.CreateContract).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding CreateContractArgs: %w", err) + } + return n, nil + case HostFunctionTypeHostFunctionTypeUploadContractWasm: + u.Wasm = new([]byte) + (*u.Wasm), nTmp, err = d.DecodeOpaque(0) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Wasm: %w", err) + } + return n, nil + } + return n, fmt.Errorf("union HostFunction has invalid Type (HostFunctionType) switch value '%d'", u.Type) +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (s HostFunction) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *HostFunction) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} + +var ( + _ encoding.BinaryMarshaler = (*HostFunction)(nil) + _ encoding.BinaryUnmarshaler = (*HostFunction)(nil) +) + +// xdrType signals that this type represents XDR values defined by this package. +func (s HostFunction) xdrType() {} + +var _ xdrType = (*HostFunction)(nil) + +// SorobanAuthorizedFunctionType is an XDR Enum defines as: +// +// enum SorobanAuthorizedFunctionType +// { +// SOROBAN_AUTHORIZED_FUNCTION_TYPE_CONTRACT_FN = 0, +// SOROBAN_AUTHORIZED_FUNCTION_TYPE_CREATE_CONTRACT_HOST_FN = 1 +// }; +type SorobanAuthorizedFunctionType int32 + +const ( + SorobanAuthorizedFunctionTypeSorobanAuthorizedFunctionTypeContractFn SorobanAuthorizedFunctionType = 0 + SorobanAuthorizedFunctionTypeSorobanAuthorizedFunctionTypeCreateContractHostFn SorobanAuthorizedFunctionType = 1 +) + +var sorobanAuthorizedFunctionTypeMap = map[int32]string{ + 0: "SorobanAuthorizedFunctionTypeSorobanAuthorizedFunctionTypeContractFn", + 1: "SorobanAuthorizedFunctionTypeSorobanAuthorizedFunctionTypeCreateContractHostFn", +} + +// ValidEnum validates a proposed value for this enum. Implements +// the Enum interface for SorobanAuthorizedFunctionType +func (e SorobanAuthorizedFunctionType) ValidEnum(v int32) bool { + _, ok := sorobanAuthorizedFunctionTypeMap[v] + return ok +} + +// String returns the name of `e` +func (e SorobanAuthorizedFunctionType) String() string { + name, _ := sorobanAuthorizedFunctionTypeMap[int32(e)] + return name +} + +// EncodeTo encodes this value using the Encoder. +func (e SorobanAuthorizedFunctionType) EncodeTo(enc *xdr.Encoder) error { + if _, ok := sorobanAuthorizedFunctionTypeMap[int32(e)]; !ok { + return fmt.Errorf("'%d' is not a valid SorobanAuthorizedFunctionType enum value", e) + } + _, err := enc.EncodeInt(int32(e)) + return err +} + +var _ decoderFrom = (*SorobanAuthorizedFunctionType)(nil) + +// DecodeFrom decodes this value using the Decoder. +func (e *SorobanAuthorizedFunctionType) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding SorobanAuthorizedFunctionType: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + v, n, err := d.DecodeInt() + if err != nil { + return n, fmt.Errorf("decoding SorobanAuthorizedFunctionType: %w", err) + } + if _, ok := sorobanAuthorizedFunctionTypeMap[v]; !ok { + return n, fmt.Errorf("'%d' is not a valid SorobanAuthorizedFunctionType enum value", v) + } + *e = SorobanAuthorizedFunctionType(v) + return n, nil +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (s SorobanAuthorizedFunctionType) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *SorobanAuthorizedFunctionType) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} + +var ( + _ encoding.BinaryMarshaler = (*SorobanAuthorizedFunctionType)(nil) + _ encoding.BinaryUnmarshaler = (*SorobanAuthorizedFunctionType)(nil) +) + +// xdrType signals that this type represents XDR values defined by this package. +func (s SorobanAuthorizedFunctionType) xdrType() {} + +var _ xdrType = (*SorobanAuthorizedFunctionType)(nil) + +// SorobanAuthorizedFunction is an XDR Union defines as: +// +// union SorobanAuthorizedFunction switch (SorobanAuthorizedFunctionType type) +// { +// case SOROBAN_AUTHORIZED_FUNCTION_TYPE_CONTRACT_FN: +// InvokeContractArgs contractFn; +// case SOROBAN_AUTHORIZED_FUNCTION_TYPE_CREATE_CONTRACT_HOST_FN: +// CreateContractArgs createContractHostFn; +// }; +type SorobanAuthorizedFunction struct { + Type SorobanAuthorizedFunctionType + ContractFn *InvokeContractArgs + CreateContractHostFn *CreateContractArgs +} + +// SwitchFieldName returns the field name in which this union's +// discriminant is stored +func (u SorobanAuthorizedFunction) SwitchFieldName() string { + return "Type" +} + +// ArmForSwitch returns which field name should be used for storing +// the value for an instance of SorobanAuthorizedFunction +func (u SorobanAuthorizedFunction) ArmForSwitch(sw int32) (string, bool) { + switch SorobanAuthorizedFunctionType(sw) { + case SorobanAuthorizedFunctionTypeSorobanAuthorizedFunctionTypeContractFn: + return "ContractFn", true + case SorobanAuthorizedFunctionTypeSorobanAuthorizedFunctionTypeCreateContractHostFn: + return "CreateContractHostFn", true + } + return "-", false +} + +// NewSorobanAuthorizedFunction creates a new SorobanAuthorizedFunction. +func NewSorobanAuthorizedFunction(aType SorobanAuthorizedFunctionType, value interface{}) (result SorobanAuthorizedFunction, err error) { + result.Type = aType + switch SorobanAuthorizedFunctionType(aType) { + case SorobanAuthorizedFunctionTypeSorobanAuthorizedFunctionTypeContractFn: + tv, ok := value.(InvokeContractArgs) + if !ok { + err = errors.New("invalid value, must be InvokeContractArgs") + return + } + result.ContractFn = &tv + case SorobanAuthorizedFunctionTypeSorobanAuthorizedFunctionTypeCreateContractHostFn: + tv, ok := value.(CreateContractArgs) + if !ok { + err = errors.New("invalid value, must be CreateContractArgs") + return + } + result.CreateContractHostFn = &tv + } + return +} + +// MustContractFn retrieves the ContractFn value from the union, +// panicing if the value is not set. +func (u SorobanAuthorizedFunction) MustContractFn() InvokeContractArgs { + val, ok := u.GetContractFn() + + if !ok { + panic("arm ContractFn is not set") + } + + return val +} + +// GetContractFn retrieves the ContractFn value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u SorobanAuthorizedFunction) GetContractFn() (result InvokeContractArgs, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) + + if armName == "ContractFn" { + result = *u.ContractFn + ok = true + } + + return +} + +// MustCreateContractHostFn retrieves the CreateContractHostFn value from the union, +// panicing if the value is not set. +func (u SorobanAuthorizedFunction) MustCreateContractHostFn() CreateContractArgs { + val, ok := u.GetCreateContractHostFn() + + if !ok { + panic("arm CreateContractHostFn is not set") + } + + return val +} + +// GetCreateContractHostFn retrieves the CreateContractHostFn value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u SorobanAuthorizedFunction) GetCreateContractHostFn() (result CreateContractArgs, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) + + if armName == "CreateContractHostFn" { + result = *u.CreateContractHostFn + ok = true + } + + return +} + +// EncodeTo encodes this value using the Encoder. +func (u SorobanAuthorizedFunction) EncodeTo(e *xdr.Encoder) error { + var err error + if err = u.Type.EncodeTo(e); err != nil { + return err + } + switch SorobanAuthorizedFunctionType(u.Type) { + case SorobanAuthorizedFunctionTypeSorobanAuthorizedFunctionTypeContractFn: + if err = (*u.ContractFn).EncodeTo(e); err != nil { + return err + } + return nil + case SorobanAuthorizedFunctionTypeSorobanAuthorizedFunctionTypeCreateContractHostFn: + if err = (*u.CreateContractHostFn).EncodeTo(e); err != nil { + return err + } + return nil + } + return fmt.Errorf("Type (SorobanAuthorizedFunctionType) switch value '%d' is not valid for union SorobanAuthorizedFunction", u.Type) +} + +var _ decoderFrom = (*SorobanAuthorizedFunction)(nil) + +// DecodeFrom decodes this value using the Decoder. +func (u *SorobanAuthorizedFunction) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding SorobanAuthorizedFunction: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + var err error + var n, nTmp int + nTmp, err = u.Type.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding SorobanAuthorizedFunctionType: %w", err) + } + switch SorobanAuthorizedFunctionType(u.Type) { + case SorobanAuthorizedFunctionTypeSorobanAuthorizedFunctionTypeContractFn: + u.ContractFn = new(InvokeContractArgs) + nTmp, err = (*u.ContractFn).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding InvokeContractArgs: %w", err) + } + return n, nil + case SorobanAuthorizedFunctionTypeSorobanAuthorizedFunctionTypeCreateContractHostFn: + u.CreateContractHostFn = new(CreateContractArgs) + nTmp, err = (*u.CreateContractHostFn).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding CreateContractArgs: %w", err) + } + return n, nil + } + return n, fmt.Errorf("union SorobanAuthorizedFunction has invalid Type (SorobanAuthorizedFunctionType) switch value '%d'", u.Type) +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (s SorobanAuthorizedFunction) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *SorobanAuthorizedFunction) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} + +var ( + _ encoding.BinaryMarshaler = (*SorobanAuthorizedFunction)(nil) + _ encoding.BinaryUnmarshaler = (*SorobanAuthorizedFunction)(nil) +) + +// xdrType signals that this type represents XDR values defined by this package. +func (s SorobanAuthorizedFunction) xdrType() {} + +var _ xdrType = (*SorobanAuthorizedFunction)(nil) + +// SorobanAuthorizedInvocation is an XDR Struct defines as: +// +// struct SorobanAuthorizedInvocation +// { +// SorobanAuthorizedFunction function; +// SorobanAuthorizedInvocation subInvocations<>; +// }; +type SorobanAuthorizedInvocation struct { + Function SorobanAuthorizedFunction + SubInvocations []SorobanAuthorizedInvocation +} + +// EncodeTo encodes this value using the Encoder. +func (s *SorobanAuthorizedInvocation) EncodeTo(e *xdr.Encoder) error { + var err error + if err = s.Function.EncodeTo(e); err != nil { + return err + } + if _, err = e.EncodeUint(uint32(len(s.SubInvocations))); err != nil { + return err + } + for i := 0; i < len(s.SubInvocations); i++ { + if err = s.SubInvocations[i].EncodeTo(e); err != nil { + return err + } + } + return nil +} + +var _ decoderFrom = (*SorobanAuthorizedInvocation)(nil) + +// DecodeFrom decodes this value using the Decoder. +func (s *SorobanAuthorizedInvocation) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding SorobanAuthorizedInvocation: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + var err error + var n, nTmp int + nTmp, err = s.Function.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding SorobanAuthorizedFunction: %w", err) + } + var l uint32 + l, nTmp, err = d.DecodeUint() + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding SorobanAuthorizedInvocation: %w", err) + } + s.SubInvocations = nil + if l > 0 { + if il, ok := d.InputLen(); ok && uint(il) < uint(l) { + return n, fmt.Errorf("decoding SorobanAuthorizedInvocation: length (%d) exceeds remaining input length (%d)", l, il) + } + s.SubInvocations = make([]SorobanAuthorizedInvocation, l) + for i := uint32(0); i < l; i++ { + nTmp, err = s.SubInvocations[i].DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding SorobanAuthorizedInvocation: %w", err) + } + } + } + return n, nil +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (s SorobanAuthorizedInvocation) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *SorobanAuthorizedInvocation) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} + +var ( + _ encoding.BinaryMarshaler = (*SorobanAuthorizedInvocation)(nil) + _ encoding.BinaryUnmarshaler = (*SorobanAuthorizedInvocation)(nil) +) + +// xdrType signals that this type represents XDR values defined by this package. +func (s SorobanAuthorizedInvocation) xdrType() {} + +var _ xdrType = (*SorobanAuthorizedInvocation)(nil) + +// SorobanAddressCredentials is an XDR Struct defines as: +// +// struct SorobanAddressCredentials +// { +// SCAddress address; +// int64 nonce; +// uint32 signatureExpirationLedger; +// SCVal signature; +// }; +type SorobanAddressCredentials struct { + Address ScAddress + Nonce Int64 + SignatureExpirationLedger Uint32 + Signature ScVal +} + +// EncodeTo encodes this value using the Encoder. +func (s *SorobanAddressCredentials) EncodeTo(e *xdr.Encoder) error { + var err error + if err = s.Address.EncodeTo(e); err != nil { + return err + } + if err = s.Nonce.EncodeTo(e); err != nil { + return err + } + if err = s.SignatureExpirationLedger.EncodeTo(e); err != nil { + return err + } + if err = s.Signature.EncodeTo(e); err != nil { + return err + } + return nil +} + +var _ decoderFrom = (*SorobanAddressCredentials)(nil) + +// DecodeFrom decodes this value using the Decoder. +func (s *SorobanAddressCredentials) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding SorobanAddressCredentials: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + var err error + var n, nTmp int + nTmp, err = s.Address.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ScAddress: %w", err) + } + nTmp, err = s.Nonce.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Int64: %w", err) + } + nTmp, err = s.SignatureExpirationLedger.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Uint32: %w", err) + } + nTmp, err = s.Signature.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ScVal: %w", err) + } + return n, nil +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (s SorobanAddressCredentials) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *SorobanAddressCredentials) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} + +var ( + _ encoding.BinaryMarshaler = (*SorobanAddressCredentials)(nil) + _ encoding.BinaryUnmarshaler = (*SorobanAddressCredentials)(nil) +) + +// xdrType signals that this type represents XDR values defined by this package. +func (s SorobanAddressCredentials) xdrType() {} + +var _ xdrType = (*SorobanAddressCredentials)(nil) + +// SorobanCredentialsType is an XDR Enum defines as: +// +// enum SorobanCredentialsType +// { +// SOROBAN_CREDENTIALS_SOURCE_ACCOUNT = 0, +// SOROBAN_CREDENTIALS_ADDRESS = 1 +// }; +type SorobanCredentialsType int32 + +const ( + SorobanCredentialsTypeSorobanCredentialsSourceAccount SorobanCredentialsType = 0 + SorobanCredentialsTypeSorobanCredentialsAddress SorobanCredentialsType = 1 +) + +var sorobanCredentialsTypeMap = map[int32]string{ + 0: "SorobanCredentialsTypeSorobanCredentialsSourceAccount", + 1: "SorobanCredentialsTypeSorobanCredentialsAddress", +} + +// ValidEnum validates a proposed value for this enum. Implements +// the Enum interface for SorobanCredentialsType +func (e SorobanCredentialsType) ValidEnum(v int32) bool { + _, ok := sorobanCredentialsTypeMap[v] + return ok +} + +// String returns the name of `e` +func (e SorobanCredentialsType) String() string { + name, _ := sorobanCredentialsTypeMap[int32(e)] + return name +} + +// EncodeTo encodes this value using the Encoder. +func (e SorobanCredentialsType) EncodeTo(enc *xdr.Encoder) error { + if _, ok := sorobanCredentialsTypeMap[int32(e)]; !ok { + return fmt.Errorf("'%d' is not a valid SorobanCredentialsType enum value", e) + } + _, err := enc.EncodeInt(int32(e)) + return err +} + +var _ decoderFrom = (*SorobanCredentialsType)(nil) + +// DecodeFrom decodes this value using the Decoder. +func (e *SorobanCredentialsType) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding SorobanCredentialsType: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + v, n, err := d.DecodeInt() + if err != nil { + return n, fmt.Errorf("decoding SorobanCredentialsType: %w", err) + } + if _, ok := sorobanCredentialsTypeMap[v]; !ok { + return n, fmt.Errorf("'%d' is not a valid SorobanCredentialsType enum value", v) + } + *e = SorobanCredentialsType(v) + return n, nil +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (s SorobanCredentialsType) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *SorobanCredentialsType) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} + +var ( + _ encoding.BinaryMarshaler = (*SorobanCredentialsType)(nil) + _ encoding.BinaryUnmarshaler = (*SorobanCredentialsType)(nil) +) + +// xdrType signals that this type represents XDR values defined by this package. +func (s SorobanCredentialsType) xdrType() {} + +var _ xdrType = (*SorobanCredentialsType)(nil) + +// SorobanCredentials is an XDR Union defines as: +// +// union SorobanCredentials switch (SorobanCredentialsType type) +// { +// case SOROBAN_CREDENTIALS_SOURCE_ACCOUNT: +// void; +// case SOROBAN_CREDENTIALS_ADDRESS: +// SorobanAddressCredentials address; +// }; +type SorobanCredentials struct { + Type SorobanCredentialsType + Address *SorobanAddressCredentials +} + +// SwitchFieldName returns the field name in which this union's +// discriminant is stored +func (u SorobanCredentials) SwitchFieldName() string { + return "Type" +} + +// ArmForSwitch returns which field name should be used for storing +// the value for an instance of SorobanCredentials +func (u SorobanCredentials) ArmForSwitch(sw int32) (string, bool) { + switch SorobanCredentialsType(sw) { + case SorobanCredentialsTypeSorobanCredentialsSourceAccount: + return "", true + case SorobanCredentialsTypeSorobanCredentialsAddress: + return "Address", true + } + return "-", false +} + +// NewSorobanCredentials creates a new SorobanCredentials. +func NewSorobanCredentials(aType SorobanCredentialsType, value interface{}) (result SorobanCredentials, err error) { + result.Type = aType + switch SorobanCredentialsType(aType) { + case SorobanCredentialsTypeSorobanCredentialsSourceAccount: + // void + case SorobanCredentialsTypeSorobanCredentialsAddress: + tv, ok := value.(SorobanAddressCredentials) + if !ok { + err = errors.New("invalid value, must be SorobanAddressCredentials") + return + } + result.Address = &tv + } + return +} + +// MustAddress retrieves the Address value from the union, +// panicing if the value is not set. +func (u SorobanCredentials) MustAddress() SorobanAddressCredentials { + val, ok := u.GetAddress() + + if !ok { + panic("arm Address is not set") + } + + return val +} + +// GetAddress retrieves the Address value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u SorobanCredentials) GetAddress() (result SorobanAddressCredentials, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) + + if armName == "Address" { + result = *u.Address + ok = true + } + + return +} + +// EncodeTo encodes this value using the Encoder. +func (u SorobanCredentials) EncodeTo(e *xdr.Encoder) error { + var err error + if err = u.Type.EncodeTo(e); err != nil { + return err + } + switch SorobanCredentialsType(u.Type) { + case SorobanCredentialsTypeSorobanCredentialsSourceAccount: + // Void + return nil + case SorobanCredentialsTypeSorobanCredentialsAddress: + if err = (*u.Address).EncodeTo(e); err != nil { + return err + } + return nil + } + return fmt.Errorf("Type (SorobanCredentialsType) switch value '%d' is not valid for union SorobanCredentials", u.Type) +} + +var _ decoderFrom = (*SorobanCredentials)(nil) + +// DecodeFrom decodes this value using the Decoder. +func (u *SorobanCredentials) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding SorobanCredentials: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + var err error + var n, nTmp int + nTmp, err = u.Type.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding SorobanCredentialsType: %w", err) + } + switch SorobanCredentialsType(u.Type) { + case SorobanCredentialsTypeSorobanCredentialsSourceAccount: + // Void + return n, nil + case SorobanCredentialsTypeSorobanCredentialsAddress: + u.Address = new(SorobanAddressCredentials) + nTmp, err = (*u.Address).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding SorobanAddressCredentials: %w", err) + } + return n, nil + } + return n, fmt.Errorf("union SorobanCredentials has invalid Type (SorobanCredentialsType) switch value '%d'", u.Type) +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (s SorobanCredentials) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *SorobanCredentials) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} + +var ( + _ encoding.BinaryMarshaler = (*SorobanCredentials)(nil) + _ encoding.BinaryUnmarshaler = (*SorobanCredentials)(nil) +) + +// xdrType signals that this type represents XDR values defined by this package. +func (s SorobanCredentials) xdrType() {} + +var _ xdrType = (*SorobanCredentials)(nil) + +// SorobanAuthorizationEntry is an XDR Struct defines as: +// +// struct SorobanAuthorizationEntry +// { +// SorobanCredentials credentials; +// SorobanAuthorizedInvocation rootInvocation; +// }; +type SorobanAuthorizationEntry struct { + Credentials SorobanCredentials + RootInvocation SorobanAuthorizedInvocation +} + +// EncodeTo encodes this value using the Encoder. +func (s *SorobanAuthorizationEntry) EncodeTo(e *xdr.Encoder) error { + var err error + if err = s.Credentials.EncodeTo(e); err != nil { + return err + } + if err = s.RootInvocation.EncodeTo(e); err != nil { + return err + } + return nil +} + +var _ decoderFrom = (*SorobanAuthorizationEntry)(nil) + +// DecodeFrom decodes this value using the Decoder. +func (s *SorobanAuthorizationEntry) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding SorobanAuthorizationEntry: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + var err error + var n, nTmp int + nTmp, err = s.Credentials.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding SorobanCredentials: %w", err) + } + nTmp, err = s.RootInvocation.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding SorobanAuthorizedInvocation: %w", err) + } + return n, nil +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (s SorobanAuthorizationEntry) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *SorobanAuthorizationEntry) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} + +var ( + _ encoding.BinaryMarshaler = (*SorobanAuthorizationEntry)(nil) + _ encoding.BinaryUnmarshaler = (*SorobanAuthorizationEntry)(nil) +) + +// xdrType signals that this type represents XDR values defined by this package. +func (s SorobanAuthorizationEntry) xdrType() {} + +var _ xdrType = (*SorobanAuthorizationEntry)(nil) + +// InvokeHostFunctionOp is an XDR Struct defines as: +// +// struct InvokeHostFunctionOp +// { +// // Host function to invoke. +// HostFunction hostFunction; +// // Per-address authorizations for this host function. +// SorobanAuthorizationEntry auth<>; +// }; +type InvokeHostFunctionOp struct { + HostFunction HostFunction + Auth []SorobanAuthorizationEntry +} + +// EncodeTo encodes this value using the Encoder. +func (s *InvokeHostFunctionOp) EncodeTo(e *xdr.Encoder) error { + var err error + if err = s.HostFunction.EncodeTo(e); err != nil { + return err + } + if _, err = e.EncodeUint(uint32(len(s.Auth))); err != nil { + return err + } + for i := 0; i < len(s.Auth); i++ { + if err = s.Auth[i].EncodeTo(e); err != nil { + return err + } + } + return nil +} + +var _ decoderFrom = (*InvokeHostFunctionOp)(nil) + +// DecodeFrom decodes this value using the Decoder. +func (s *InvokeHostFunctionOp) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding InvokeHostFunctionOp: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + var err error + var n, nTmp int + nTmp, err = s.HostFunction.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding HostFunction: %w", err) + } + var l uint32 + l, nTmp, err = d.DecodeUint() + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding SorobanAuthorizationEntry: %w", err) + } + s.Auth = nil + if l > 0 { + if il, ok := d.InputLen(); ok && uint(il) < uint(l) { + return n, fmt.Errorf("decoding SorobanAuthorizationEntry: length (%d) exceeds remaining input length (%d)", l, il) + } + s.Auth = make([]SorobanAuthorizationEntry, l) + for i := uint32(0); i < l; i++ { + nTmp, err = s.Auth[i].DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding SorobanAuthorizationEntry: %w", err) + } + } + } + return n, nil +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (s InvokeHostFunctionOp) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *InvokeHostFunctionOp) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} + +var ( + _ encoding.BinaryMarshaler = (*InvokeHostFunctionOp)(nil) + _ encoding.BinaryUnmarshaler = (*InvokeHostFunctionOp)(nil) +) + +// xdrType signals that this type represents XDR values defined by this package. +func (s InvokeHostFunctionOp) xdrType() {} + +var _ xdrType = (*InvokeHostFunctionOp)(nil) + +// ExtendFootprintTtlOp is an XDR Struct defines as: +// +// struct ExtendFootprintTTLOp +// { +// ExtensionPoint ext; +// uint32 extendTo; +// }; +type ExtendFootprintTtlOp struct { + Ext ExtensionPoint + ExtendTo Uint32 +} + +// EncodeTo encodes this value using the Encoder. +func (s *ExtendFootprintTtlOp) EncodeTo(e *xdr.Encoder) error { + var err error + if err = s.Ext.EncodeTo(e); err != nil { + return err + } + if err = s.ExtendTo.EncodeTo(e); err != nil { + return err + } + return nil +} + +var _ decoderFrom = (*ExtendFootprintTtlOp)(nil) + +// DecodeFrom decodes this value using the Decoder. +func (s *ExtendFootprintTtlOp) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding ExtendFootprintTtlOp: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + var err error + var n, nTmp int + nTmp, err = s.Ext.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ExtensionPoint: %w", err) + } + nTmp, err = s.ExtendTo.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Uint32: %w", err) + } + return n, nil +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (s ExtendFootprintTtlOp) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *ExtendFootprintTtlOp) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} + +var ( + _ encoding.BinaryMarshaler = (*ExtendFootprintTtlOp)(nil) + _ encoding.BinaryUnmarshaler = (*ExtendFootprintTtlOp)(nil) +) + +// xdrType signals that this type represents XDR values defined by this package. +func (s ExtendFootprintTtlOp) xdrType() {} + +var _ xdrType = (*ExtendFootprintTtlOp)(nil) + +// RestoreFootprintOp is an XDR Struct defines as: +// +// struct RestoreFootprintOp +// { +// ExtensionPoint ext; +// }; +type RestoreFootprintOp struct { + Ext ExtensionPoint +} + +// EncodeTo encodes this value using the Encoder. +func (s *RestoreFootprintOp) EncodeTo(e *xdr.Encoder) error { + var err error + if err = s.Ext.EncodeTo(e); err != nil { + return err + } + return nil +} + +var _ decoderFrom = (*RestoreFootprintOp)(nil) + +// DecodeFrom decodes this value using the Decoder. +func (s *RestoreFootprintOp) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding RestoreFootprintOp: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + var err error + var n, nTmp int + nTmp, err = s.Ext.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ExtensionPoint: %w", err) + } + return n, nil +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (s RestoreFootprintOp) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *RestoreFootprintOp) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} + +var ( + _ encoding.BinaryMarshaler = (*RestoreFootprintOp)(nil) + _ encoding.BinaryUnmarshaler = (*RestoreFootprintOp)(nil) +) + +// xdrType signals that this type represents XDR values defined by this package. +func (s RestoreFootprintOp) xdrType() {} + +var _ xdrType = (*RestoreFootprintOp)(nil) + +// OperationBody is an XDR NestedUnion defines as: +// +// union switch (OperationType type) +// { +// case CREATE_ACCOUNT: +// CreateAccountOp createAccountOp; +// case PAYMENT: +// PaymentOp paymentOp; +// case PATH_PAYMENT_STRICT_RECEIVE: +// PathPaymentStrictReceiveOp pathPaymentStrictReceiveOp; +// case MANAGE_SELL_OFFER: +// ManageSellOfferOp manageSellOfferOp; +// case CREATE_PASSIVE_SELL_OFFER: +// CreatePassiveSellOfferOp createPassiveSellOfferOp; +// case SET_OPTIONS: +// SetOptionsOp setOptionsOp; +// case CHANGE_TRUST: +// ChangeTrustOp changeTrustOp; +// case ALLOW_TRUST: +// AllowTrustOp allowTrustOp; +// case ACCOUNT_MERGE: +// MuxedAccount destination; +// case INFLATION: +// void; +// case MANAGE_DATA: +// ManageDataOp manageDataOp; +// case BUMP_SEQUENCE: +// BumpSequenceOp bumpSequenceOp; +// case MANAGE_BUY_OFFER: +// ManageBuyOfferOp manageBuyOfferOp; +// case PATH_PAYMENT_STRICT_SEND: +// PathPaymentStrictSendOp pathPaymentStrictSendOp; +// case CREATE_CLAIMABLE_BALANCE: +// CreateClaimableBalanceOp createClaimableBalanceOp; +// case CLAIM_CLAIMABLE_BALANCE: +// ClaimClaimableBalanceOp claimClaimableBalanceOp; +// case BEGIN_SPONSORING_FUTURE_RESERVES: +// BeginSponsoringFutureReservesOp beginSponsoringFutureReservesOp; +// case END_SPONSORING_FUTURE_RESERVES: +// void; +// case REVOKE_SPONSORSHIP: +// RevokeSponsorshipOp revokeSponsorshipOp; +// case CLAWBACK: +// ClawbackOp clawbackOp; +// case CLAWBACK_CLAIMABLE_BALANCE: +// ClawbackClaimableBalanceOp clawbackClaimableBalanceOp; +// case SET_TRUST_LINE_FLAGS: +// SetTrustLineFlagsOp setTrustLineFlagsOp; +// case LIQUIDITY_POOL_DEPOSIT: +// LiquidityPoolDepositOp liquidityPoolDepositOp; +// case LIQUIDITY_POOL_WITHDRAW: +// LiquidityPoolWithdrawOp liquidityPoolWithdrawOp; +// case INVOKE_HOST_FUNCTION: +// InvokeHostFunctionOp invokeHostFunctionOp; +// case EXTEND_FOOTPRINT_TTL: +// ExtendFootprintTTLOp extendFootprintTTLOp; +// case RESTORE_FOOTPRINT: +// RestoreFootprintOp restoreFootprintOp; +// } +type OperationBody struct { + Type OperationType + CreateAccountOp *CreateAccountOp + PaymentOp *PaymentOp + PathPaymentStrictReceiveOp *PathPaymentStrictReceiveOp + ManageSellOfferOp *ManageSellOfferOp + CreatePassiveSellOfferOp *CreatePassiveSellOfferOp + SetOptionsOp *SetOptionsOp + ChangeTrustOp *ChangeTrustOp + AllowTrustOp *AllowTrustOp + Destination *MuxedAccount + ManageDataOp *ManageDataOp + BumpSequenceOp *BumpSequenceOp + ManageBuyOfferOp *ManageBuyOfferOp + PathPaymentStrictSendOp *PathPaymentStrictSendOp + CreateClaimableBalanceOp *CreateClaimableBalanceOp + ClaimClaimableBalanceOp *ClaimClaimableBalanceOp + BeginSponsoringFutureReservesOp *BeginSponsoringFutureReservesOp + RevokeSponsorshipOp *RevokeSponsorshipOp + ClawbackOp *ClawbackOp + ClawbackClaimableBalanceOp *ClawbackClaimableBalanceOp + SetTrustLineFlagsOp *SetTrustLineFlagsOp + LiquidityPoolDepositOp *LiquidityPoolDepositOp + LiquidityPoolWithdrawOp *LiquidityPoolWithdrawOp + InvokeHostFunctionOp *InvokeHostFunctionOp + ExtendFootprintTtlOp *ExtendFootprintTtlOp + RestoreFootprintOp *RestoreFootprintOp +} + +// SwitchFieldName returns the field name in which this union's +// discriminant is stored +func (u OperationBody) SwitchFieldName() string { + return "Type" +} + +// ArmForSwitch returns which field name should be used for storing +// the value for an instance of OperationBody +func (u OperationBody) ArmForSwitch(sw int32) (string, bool) { + switch OperationType(sw) { + case OperationTypeCreateAccount: + return "CreateAccountOp", true + case OperationTypePayment: + return "PaymentOp", true + case OperationTypePathPaymentStrictReceive: + return "PathPaymentStrictReceiveOp", true + case OperationTypeManageSellOffer: + return "ManageSellOfferOp", true + case OperationTypeCreatePassiveSellOffer: + return "CreatePassiveSellOfferOp", true + case OperationTypeSetOptions: + return "SetOptionsOp", true + case OperationTypeChangeTrust: + return "ChangeTrustOp", true + case OperationTypeAllowTrust: + return "AllowTrustOp", true + case OperationTypeAccountMerge: + return "Destination", true + case OperationTypeInflation: + return "", true + case OperationTypeManageData: + return "ManageDataOp", true + case OperationTypeBumpSequence: + return "BumpSequenceOp", true + case OperationTypeManageBuyOffer: + return "ManageBuyOfferOp", true + case OperationTypePathPaymentStrictSend: + return "PathPaymentStrictSendOp", true + case OperationTypeCreateClaimableBalance: + return "CreateClaimableBalanceOp", true + case OperationTypeClaimClaimableBalance: + return "ClaimClaimableBalanceOp", true + case OperationTypeBeginSponsoringFutureReserves: + return "BeginSponsoringFutureReservesOp", true + case OperationTypeEndSponsoringFutureReserves: + return "", true + case OperationTypeRevokeSponsorship: + return "RevokeSponsorshipOp", true + case OperationTypeClawback: + return "ClawbackOp", true + case OperationTypeClawbackClaimableBalance: + return "ClawbackClaimableBalanceOp", true + case OperationTypeSetTrustLineFlags: + return "SetTrustLineFlagsOp", true + case OperationTypeLiquidityPoolDeposit: + return "LiquidityPoolDepositOp", true + case OperationTypeLiquidityPoolWithdraw: + return "LiquidityPoolWithdrawOp", true + case OperationTypeInvokeHostFunction: + return "InvokeHostFunctionOp", true + case OperationTypeExtendFootprintTtl: + return "ExtendFootprintTtlOp", true + case OperationTypeRestoreFootprint: + return "RestoreFootprintOp", true + } + return "-", false +} + +// NewOperationBody creates a new OperationBody. +func NewOperationBody(aType OperationType, value interface{}) (result OperationBody, err error) { + result.Type = aType + switch OperationType(aType) { + case OperationTypeCreateAccount: + tv, ok := value.(CreateAccountOp) + if !ok { + err = errors.New("invalid value, must be CreateAccountOp") + return + } + result.CreateAccountOp = &tv + case OperationTypePayment: + tv, ok := value.(PaymentOp) + if !ok { + err = errors.New("invalid value, must be PaymentOp") + return + } + result.PaymentOp = &tv + case OperationTypePathPaymentStrictReceive: + tv, ok := value.(PathPaymentStrictReceiveOp) + if !ok { + err = errors.New("invalid value, must be PathPaymentStrictReceiveOp") + return + } + result.PathPaymentStrictReceiveOp = &tv + case OperationTypeManageSellOffer: + tv, ok := value.(ManageSellOfferOp) + if !ok { + err = errors.New("invalid value, must be ManageSellOfferOp") + return + } + result.ManageSellOfferOp = &tv + case OperationTypeCreatePassiveSellOffer: + tv, ok := value.(CreatePassiveSellOfferOp) + if !ok { + err = errors.New("invalid value, must be CreatePassiveSellOfferOp") + return + } + result.CreatePassiveSellOfferOp = &tv + case OperationTypeSetOptions: + tv, ok := value.(SetOptionsOp) + if !ok { + err = errors.New("invalid value, must be SetOptionsOp") + return + } + result.SetOptionsOp = &tv + case OperationTypeChangeTrust: + tv, ok := value.(ChangeTrustOp) + if !ok { + err = errors.New("invalid value, must be ChangeTrustOp") + return + } + result.ChangeTrustOp = &tv + case OperationTypeAllowTrust: + tv, ok := value.(AllowTrustOp) + if !ok { + err = errors.New("invalid value, must be AllowTrustOp") + return + } + result.AllowTrustOp = &tv + case OperationTypeAccountMerge: + tv, ok := value.(MuxedAccount) + if !ok { + err = errors.New("invalid value, must be MuxedAccount") + return + } + result.Destination = &tv + case OperationTypeInflation: + // void + case OperationTypeManageData: + tv, ok := value.(ManageDataOp) + if !ok { + err = errors.New("invalid value, must be ManageDataOp") + return + } + result.ManageDataOp = &tv + case OperationTypeBumpSequence: + tv, ok := value.(BumpSequenceOp) + if !ok { + err = errors.New("invalid value, must be BumpSequenceOp") + return + } + result.BumpSequenceOp = &tv + case OperationTypeManageBuyOffer: + tv, ok := value.(ManageBuyOfferOp) + if !ok { + err = errors.New("invalid value, must be ManageBuyOfferOp") + return + } + result.ManageBuyOfferOp = &tv + case OperationTypePathPaymentStrictSend: + tv, ok := value.(PathPaymentStrictSendOp) + if !ok { + err = errors.New("invalid value, must be PathPaymentStrictSendOp") + return + } + result.PathPaymentStrictSendOp = &tv + case OperationTypeCreateClaimableBalance: + tv, ok := value.(CreateClaimableBalanceOp) + if !ok { + err = errors.New("invalid value, must be CreateClaimableBalanceOp") + return + } + result.CreateClaimableBalanceOp = &tv + case OperationTypeClaimClaimableBalance: + tv, ok := value.(ClaimClaimableBalanceOp) + if !ok { + err = errors.New("invalid value, must be ClaimClaimableBalanceOp") + return + } + result.ClaimClaimableBalanceOp = &tv + case OperationTypeBeginSponsoringFutureReserves: + tv, ok := value.(BeginSponsoringFutureReservesOp) + if !ok { + err = errors.New("invalid value, must be BeginSponsoringFutureReservesOp") + return + } + result.BeginSponsoringFutureReservesOp = &tv + case OperationTypeEndSponsoringFutureReserves: + // void + case OperationTypeRevokeSponsorship: + tv, ok := value.(RevokeSponsorshipOp) + if !ok { + err = errors.New("invalid value, must be RevokeSponsorshipOp") + return + } + result.RevokeSponsorshipOp = &tv + case OperationTypeClawback: + tv, ok := value.(ClawbackOp) + if !ok { + err = errors.New("invalid value, must be ClawbackOp") + return + } + result.ClawbackOp = &tv + case OperationTypeClawbackClaimableBalance: + tv, ok := value.(ClawbackClaimableBalanceOp) + if !ok { + err = errors.New("invalid value, must be ClawbackClaimableBalanceOp") + return + } + result.ClawbackClaimableBalanceOp = &tv + case OperationTypeSetTrustLineFlags: + tv, ok := value.(SetTrustLineFlagsOp) + if !ok { + err = errors.New("invalid value, must be SetTrustLineFlagsOp") + return + } + result.SetTrustLineFlagsOp = &tv + case OperationTypeLiquidityPoolDeposit: + tv, ok := value.(LiquidityPoolDepositOp) + if !ok { + err = errors.New("invalid value, must be LiquidityPoolDepositOp") + return + } + result.LiquidityPoolDepositOp = &tv + case OperationTypeLiquidityPoolWithdraw: + tv, ok := value.(LiquidityPoolWithdrawOp) + if !ok { + err = errors.New("invalid value, must be LiquidityPoolWithdrawOp") + return + } + result.LiquidityPoolWithdrawOp = &tv + case OperationTypeInvokeHostFunction: + tv, ok := value.(InvokeHostFunctionOp) + if !ok { + err = errors.New("invalid value, must be InvokeHostFunctionOp") + return + } + result.InvokeHostFunctionOp = &tv + case OperationTypeExtendFootprintTtl: + tv, ok := value.(ExtendFootprintTtlOp) + if !ok { + err = errors.New("invalid value, must be ExtendFootprintTtlOp") + return + } + result.ExtendFootprintTtlOp = &tv + case OperationTypeRestoreFootprint: + tv, ok := value.(RestoreFootprintOp) + if !ok { + err = errors.New("invalid value, must be RestoreFootprintOp") + return + } + result.RestoreFootprintOp = &tv + } + return +} + +// MustCreateAccountOp retrieves the CreateAccountOp value from the union, +// panicing if the value is not set. +func (u OperationBody) MustCreateAccountOp() CreateAccountOp { + val, ok := u.GetCreateAccountOp() + + if !ok { + panic("arm CreateAccountOp is not set") + } + + return val +} + +// GetCreateAccountOp retrieves the CreateAccountOp value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u OperationBody) GetCreateAccountOp() (result CreateAccountOp, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) + + if armName == "CreateAccountOp" { + result = *u.CreateAccountOp + ok = true + } + + return +} + +// MustPaymentOp retrieves the PaymentOp value from the union, +// panicing if the value is not set. +func (u OperationBody) MustPaymentOp() PaymentOp { + val, ok := u.GetPaymentOp() + + if !ok { + panic("arm PaymentOp is not set") + } + + return val +} + +// GetPaymentOp retrieves the PaymentOp value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u OperationBody) GetPaymentOp() (result PaymentOp, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) + + if armName == "PaymentOp" { + result = *u.PaymentOp + ok = true + } + + return +} + +// MustPathPaymentStrictReceiveOp retrieves the PathPaymentStrictReceiveOp value from the union, +// panicing if the value is not set. +func (u OperationBody) MustPathPaymentStrictReceiveOp() PathPaymentStrictReceiveOp { + val, ok := u.GetPathPaymentStrictReceiveOp() + + if !ok { + panic("arm PathPaymentStrictReceiveOp is not set") + } + + return val +} + +// GetPathPaymentStrictReceiveOp retrieves the PathPaymentStrictReceiveOp value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u OperationBody) GetPathPaymentStrictReceiveOp() (result PathPaymentStrictReceiveOp, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) + + if armName == "PathPaymentStrictReceiveOp" { + result = *u.PathPaymentStrictReceiveOp + ok = true + } + + return +} + +// MustManageSellOfferOp retrieves the ManageSellOfferOp value from the union, +// panicing if the value is not set. +func (u OperationBody) MustManageSellOfferOp() ManageSellOfferOp { + val, ok := u.GetManageSellOfferOp() + + if !ok { + panic("arm ManageSellOfferOp is not set") + } + + return val +} + +// GetManageSellOfferOp retrieves the ManageSellOfferOp value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u OperationBody) GetManageSellOfferOp() (result ManageSellOfferOp, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) + + if armName == "ManageSellOfferOp" { + result = *u.ManageSellOfferOp + ok = true + } + + return +} + +// MustCreatePassiveSellOfferOp retrieves the CreatePassiveSellOfferOp value from the union, +// panicing if the value is not set. +func (u OperationBody) MustCreatePassiveSellOfferOp() CreatePassiveSellOfferOp { + val, ok := u.GetCreatePassiveSellOfferOp() + + if !ok { + panic("arm CreatePassiveSellOfferOp is not set") + } + + return val +} + +// GetCreatePassiveSellOfferOp retrieves the CreatePassiveSellOfferOp value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u OperationBody) GetCreatePassiveSellOfferOp() (result CreatePassiveSellOfferOp, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) + + if armName == "CreatePassiveSellOfferOp" { + result = *u.CreatePassiveSellOfferOp + ok = true + } + + return +} + +// MustSetOptionsOp retrieves the SetOptionsOp value from the union, +// panicing if the value is not set. +func (u OperationBody) MustSetOptionsOp() SetOptionsOp { + val, ok := u.GetSetOptionsOp() + + if !ok { + panic("arm SetOptionsOp is not set") + } + + return val +} + +// GetSetOptionsOp retrieves the SetOptionsOp value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u OperationBody) GetSetOptionsOp() (result SetOptionsOp, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) + + if armName == "SetOptionsOp" { + result = *u.SetOptionsOp + ok = true + } + + return +} + +// MustChangeTrustOp retrieves the ChangeTrustOp value from the union, +// panicing if the value is not set. +func (u OperationBody) MustChangeTrustOp() ChangeTrustOp { + val, ok := u.GetChangeTrustOp() + + if !ok { + panic("arm ChangeTrustOp is not set") + } + + return val +} + +// GetChangeTrustOp retrieves the ChangeTrustOp value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u OperationBody) GetChangeTrustOp() (result ChangeTrustOp, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) + + if armName == "ChangeTrustOp" { + result = *u.ChangeTrustOp + ok = true + } + + return +} + +// MustAllowTrustOp retrieves the AllowTrustOp value from the union, +// panicing if the value is not set. +func (u OperationBody) MustAllowTrustOp() AllowTrustOp { + val, ok := u.GetAllowTrustOp() + + if !ok { + panic("arm AllowTrustOp is not set") + } + + return val +} + +// GetAllowTrustOp retrieves the AllowTrustOp value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u OperationBody) GetAllowTrustOp() (result AllowTrustOp, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) + + if armName == "AllowTrustOp" { + result = *u.AllowTrustOp + ok = true + } + + return +} + +// MustDestination retrieves the Destination value from the union, +// panicing if the value is not set. +func (u OperationBody) MustDestination() MuxedAccount { + val, ok := u.GetDestination() + + if !ok { + panic("arm Destination is not set") + } + + return val +} + +// GetDestination retrieves the Destination value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u OperationBody) GetDestination() (result MuxedAccount, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) + + if armName == "Destination" { + result = *u.Destination + ok = true + } + + return +} + +// MustManageDataOp retrieves the ManageDataOp value from the union, +// panicing if the value is not set. +func (u OperationBody) MustManageDataOp() ManageDataOp { + val, ok := u.GetManageDataOp() + + if !ok { + panic("arm ManageDataOp is not set") + } + + return val +} + +// GetManageDataOp retrieves the ManageDataOp value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u OperationBody) GetManageDataOp() (result ManageDataOp, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) + + if armName == "ManageDataOp" { + result = *u.ManageDataOp + ok = true + } + + return +} + +// MustBumpSequenceOp retrieves the BumpSequenceOp value from the union, +// panicing if the value is not set. +func (u OperationBody) MustBumpSequenceOp() BumpSequenceOp { + val, ok := u.GetBumpSequenceOp() + + if !ok { + panic("arm BumpSequenceOp is not set") + } + + return val +} + +// GetBumpSequenceOp retrieves the BumpSequenceOp value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u OperationBody) GetBumpSequenceOp() (result BumpSequenceOp, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) + + if armName == "BumpSequenceOp" { + result = *u.BumpSequenceOp + ok = true + } + + return +} + +// MustManageBuyOfferOp retrieves the ManageBuyOfferOp value from the union, +// panicing if the value is not set. +func (u OperationBody) MustManageBuyOfferOp() ManageBuyOfferOp { + val, ok := u.GetManageBuyOfferOp() + + if !ok { + panic("arm ManageBuyOfferOp is not set") + } + + return val +} + +// GetManageBuyOfferOp retrieves the ManageBuyOfferOp value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u OperationBody) GetManageBuyOfferOp() (result ManageBuyOfferOp, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) + + if armName == "ManageBuyOfferOp" { + result = *u.ManageBuyOfferOp + ok = true + } + + return +} + +// MustPathPaymentStrictSendOp retrieves the PathPaymentStrictSendOp value from the union, +// panicing if the value is not set. +func (u OperationBody) MustPathPaymentStrictSendOp() PathPaymentStrictSendOp { + val, ok := u.GetPathPaymentStrictSendOp() + + if !ok { + panic("arm PathPaymentStrictSendOp is not set") + } + + return val +} + +// GetPathPaymentStrictSendOp retrieves the PathPaymentStrictSendOp value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u OperationBody) GetPathPaymentStrictSendOp() (result PathPaymentStrictSendOp, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) + + if armName == "PathPaymentStrictSendOp" { + result = *u.PathPaymentStrictSendOp + ok = true + } + + return +} + +// MustCreateClaimableBalanceOp retrieves the CreateClaimableBalanceOp value from the union, +// panicing if the value is not set. +func (u OperationBody) MustCreateClaimableBalanceOp() CreateClaimableBalanceOp { + val, ok := u.GetCreateClaimableBalanceOp() + + if !ok { + panic("arm CreateClaimableBalanceOp is not set") + } + + return val +} + +// GetCreateClaimableBalanceOp retrieves the CreateClaimableBalanceOp value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u OperationBody) GetCreateClaimableBalanceOp() (result CreateClaimableBalanceOp, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) + + if armName == "CreateClaimableBalanceOp" { + result = *u.CreateClaimableBalanceOp + ok = true + } + + return +} + +// MustClaimClaimableBalanceOp retrieves the ClaimClaimableBalanceOp value from the union, +// panicing if the value is not set. +func (u OperationBody) MustClaimClaimableBalanceOp() ClaimClaimableBalanceOp { + val, ok := u.GetClaimClaimableBalanceOp() + + if !ok { + panic("arm ClaimClaimableBalanceOp is not set") + } + + return val +} + +// GetClaimClaimableBalanceOp retrieves the ClaimClaimableBalanceOp value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u OperationBody) GetClaimClaimableBalanceOp() (result ClaimClaimableBalanceOp, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) + + if armName == "ClaimClaimableBalanceOp" { + result = *u.ClaimClaimableBalanceOp + ok = true + } + + return +} + +// MustBeginSponsoringFutureReservesOp retrieves the BeginSponsoringFutureReservesOp value from the union, +// panicing if the value is not set. +func (u OperationBody) MustBeginSponsoringFutureReservesOp() BeginSponsoringFutureReservesOp { + val, ok := u.GetBeginSponsoringFutureReservesOp() + + if !ok { + panic("arm BeginSponsoringFutureReservesOp is not set") + } + + return val +} + +// GetBeginSponsoringFutureReservesOp retrieves the BeginSponsoringFutureReservesOp value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u OperationBody) GetBeginSponsoringFutureReservesOp() (result BeginSponsoringFutureReservesOp, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) + + if armName == "BeginSponsoringFutureReservesOp" { + result = *u.BeginSponsoringFutureReservesOp + ok = true + } + + return +} + +// MustRevokeSponsorshipOp retrieves the RevokeSponsorshipOp value from the union, +// panicing if the value is not set. +func (u OperationBody) MustRevokeSponsorshipOp() RevokeSponsorshipOp { + val, ok := u.GetRevokeSponsorshipOp() + + if !ok { + panic("arm RevokeSponsorshipOp is not set") + } + + return val +} + +// GetRevokeSponsorshipOp retrieves the RevokeSponsorshipOp value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u OperationBody) GetRevokeSponsorshipOp() (result RevokeSponsorshipOp, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) + + if armName == "RevokeSponsorshipOp" { + result = *u.RevokeSponsorshipOp + ok = true + } + + return +} + +// MustClawbackOp retrieves the ClawbackOp value from the union, +// panicing if the value is not set. +func (u OperationBody) MustClawbackOp() ClawbackOp { + val, ok := u.GetClawbackOp() + + if !ok { + panic("arm ClawbackOp is not set") + } + + return val +} + +// GetClawbackOp retrieves the ClawbackOp value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u OperationBody) GetClawbackOp() (result ClawbackOp, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) + + if armName == "ClawbackOp" { + result = *u.ClawbackOp + ok = true + } + + return +} + +// MustClawbackClaimableBalanceOp retrieves the ClawbackClaimableBalanceOp value from the union, +// panicing if the value is not set. +func (u OperationBody) MustClawbackClaimableBalanceOp() ClawbackClaimableBalanceOp { + val, ok := u.GetClawbackClaimableBalanceOp() + + if !ok { + panic("arm ClawbackClaimableBalanceOp is not set") + } + + return val +} + +// GetClawbackClaimableBalanceOp retrieves the ClawbackClaimableBalanceOp value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u OperationBody) GetClawbackClaimableBalanceOp() (result ClawbackClaimableBalanceOp, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) + + if armName == "ClawbackClaimableBalanceOp" { + result = *u.ClawbackClaimableBalanceOp + ok = true + } + + return +} + +// MustSetTrustLineFlagsOp retrieves the SetTrustLineFlagsOp value from the union, +// panicing if the value is not set. +func (u OperationBody) MustSetTrustLineFlagsOp() SetTrustLineFlagsOp { + val, ok := u.GetSetTrustLineFlagsOp() + + if !ok { + panic("arm SetTrustLineFlagsOp is not set") + } + + return val +} + +// GetSetTrustLineFlagsOp retrieves the SetTrustLineFlagsOp value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u OperationBody) GetSetTrustLineFlagsOp() (result SetTrustLineFlagsOp, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) + + if armName == "SetTrustLineFlagsOp" { + result = *u.SetTrustLineFlagsOp + ok = true + } + + return +} + +// MustLiquidityPoolDepositOp retrieves the LiquidityPoolDepositOp value from the union, +// panicing if the value is not set. +func (u OperationBody) MustLiquidityPoolDepositOp() LiquidityPoolDepositOp { + val, ok := u.GetLiquidityPoolDepositOp() + + if !ok { + panic("arm LiquidityPoolDepositOp is not set") + } + + return val +} + +// GetLiquidityPoolDepositOp retrieves the LiquidityPoolDepositOp value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u OperationBody) GetLiquidityPoolDepositOp() (result LiquidityPoolDepositOp, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) + + if armName == "LiquidityPoolDepositOp" { + result = *u.LiquidityPoolDepositOp + ok = true + } + + return +} + +// MustLiquidityPoolWithdrawOp retrieves the LiquidityPoolWithdrawOp value from the union, +// panicing if the value is not set. +func (u OperationBody) MustLiquidityPoolWithdrawOp() LiquidityPoolWithdrawOp { + val, ok := u.GetLiquidityPoolWithdrawOp() + + if !ok { + panic("arm LiquidityPoolWithdrawOp is not set") + } + + return val +} + +// GetLiquidityPoolWithdrawOp retrieves the LiquidityPoolWithdrawOp value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u OperationBody) GetLiquidityPoolWithdrawOp() (result LiquidityPoolWithdrawOp, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) + + if armName == "LiquidityPoolWithdrawOp" { + result = *u.LiquidityPoolWithdrawOp + ok = true + } + + return +} + +// MustInvokeHostFunctionOp retrieves the InvokeHostFunctionOp value from the union, +// panicing if the value is not set. +func (u OperationBody) MustInvokeHostFunctionOp() InvokeHostFunctionOp { + val, ok := u.GetInvokeHostFunctionOp() + + if !ok { + panic("arm InvokeHostFunctionOp is not set") + } + + return val +} + +// GetInvokeHostFunctionOp retrieves the InvokeHostFunctionOp value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u OperationBody) GetInvokeHostFunctionOp() (result InvokeHostFunctionOp, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) + + if armName == "InvokeHostFunctionOp" { + result = *u.InvokeHostFunctionOp + ok = true + } + + return +} + +// MustExtendFootprintTtlOp retrieves the ExtendFootprintTtlOp value from the union, +// panicing if the value is not set. +func (u OperationBody) MustExtendFootprintTtlOp() ExtendFootprintTtlOp { + val, ok := u.GetExtendFootprintTtlOp() + + if !ok { + panic("arm ExtendFootprintTtlOp is not set") + } + + return val +} + +// GetExtendFootprintTtlOp retrieves the ExtendFootprintTtlOp value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u OperationBody) GetExtendFootprintTtlOp() (result ExtendFootprintTtlOp, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) + + if armName == "ExtendFootprintTtlOp" { + result = *u.ExtendFootprintTtlOp + ok = true + } + + return +} + +// MustRestoreFootprintOp retrieves the RestoreFootprintOp value from the union, +// panicing if the value is not set. +func (u OperationBody) MustRestoreFootprintOp() RestoreFootprintOp { + val, ok := u.GetRestoreFootprintOp() + + if !ok { + panic("arm RestoreFootprintOp is not set") + } + + return val +} + +// GetRestoreFootprintOp retrieves the RestoreFootprintOp value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u OperationBody) GetRestoreFootprintOp() (result RestoreFootprintOp, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) + + if armName == "RestoreFootprintOp" { + result = *u.RestoreFootprintOp + ok = true + } + + return +} + +// EncodeTo encodes this value using the Encoder. +func (u OperationBody) EncodeTo(e *xdr.Encoder) error { + var err error + if err = u.Type.EncodeTo(e); err != nil { + return err + } + switch OperationType(u.Type) { + case OperationTypeCreateAccount: + if err = (*u.CreateAccountOp).EncodeTo(e); err != nil { + return err + } + return nil + case OperationTypePayment: + if err = (*u.PaymentOp).EncodeTo(e); err != nil { + return err + } + return nil + case OperationTypePathPaymentStrictReceive: + if err = (*u.PathPaymentStrictReceiveOp).EncodeTo(e); err != nil { + return err + } + return nil + case OperationTypeManageSellOffer: + if err = (*u.ManageSellOfferOp).EncodeTo(e); err != nil { + return err + } + return nil + case OperationTypeCreatePassiveSellOffer: + if err = (*u.CreatePassiveSellOfferOp).EncodeTo(e); err != nil { + return err + } + return nil + case OperationTypeSetOptions: + if err = (*u.SetOptionsOp).EncodeTo(e); err != nil { + return err + } + return nil + case OperationTypeChangeTrust: + if err = (*u.ChangeTrustOp).EncodeTo(e); err != nil { + return err + } + return nil + case OperationTypeAllowTrust: + if err = (*u.AllowTrustOp).EncodeTo(e); err != nil { + return err + } + return nil + case OperationTypeAccountMerge: + if err = (*u.Destination).EncodeTo(e); err != nil { + return err + } + return nil + case OperationTypeInflation: + // Void + return nil + case OperationTypeManageData: + if err = (*u.ManageDataOp).EncodeTo(e); err != nil { + return err + } + return nil + case OperationTypeBumpSequence: + if err = (*u.BumpSequenceOp).EncodeTo(e); err != nil { + return err + } + return nil + case OperationTypeManageBuyOffer: + if err = (*u.ManageBuyOfferOp).EncodeTo(e); err != nil { + return err + } + return nil + case OperationTypePathPaymentStrictSend: + if err = (*u.PathPaymentStrictSendOp).EncodeTo(e); err != nil { + return err + } + return nil + case OperationTypeCreateClaimableBalance: + if err = (*u.CreateClaimableBalanceOp).EncodeTo(e); err != nil { + return err + } + return nil + case OperationTypeClaimClaimableBalance: + if err = (*u.ClaimClaimableBalanceOp).EncodeTo(e); err != nil { + return err + } + return nil + case OperationTypeBeginSponsoringFutureReserves: + if err = (*u.BeginSponsoringFutureReservesOp).EncodeTo(e); err != nil { + return err + } + return nil + case OperationTypeEndSponsoringFutureReserves: + // Void + return nil + case OperationTypeRevokeSponsorship: + if err = (*u.RevokeSponsorshipOp).EncodeTo(e); err != nil { + return err + } + return nil + case OperationTypeClawback: + if err = (*u.ClawbackOp).EncodeTo(e); err != nil { + return err + } + return nil + case OperationTypeClawbackClaimableBalance: + if err = (*u.ClawbackClaimableBalanceOp).EncodeTo(e); err != nil { + return err + } + return nil + case OperationTypeSetTrustLineFlags: + if err = (*u.SetTrustLineFlagsOp).EncodeTo(e); err != nil { + return err + } + return nil + case OperationTypeLiquidityPoolDeposit: + if err = (*u.LiquidityPoolDepositOp).EncodeTo(e); err != nil { + return err + } + return nil + case OperationTypeLiquidityPoolWithdraw: + if err = (*u.LiquidityPoolWithdrawOp).EncodeTo(e); err != nil { + return err + } + return nil + case OperationTypeInvokeHostFunction: + if err = (*u.InvokeHostFunctionOp).EncodeTo(e); err != nil { + return err + } + return nil + case OperationTypeExtendFootprintTtl: + if err = (*u.ExtendFootprintTtlOp).EncodeTo(e); err != nil { + return err + } + return nil + case OperationTypeRestoreFootprint: + if err = (*u.RestoreFootprintOp).EncodeTo(e); err != nil { + return err + } + return nil + } + return fmt.Errorf("Type (OperationType) switch value '%d' is not valid for union OperationBody", u.Type) +} + +var _ decoderFrom = (*OperationBody)(nil) + +// DecodeFrom decodes this value using the Decoder. +func (u *OperationBody) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding OperationBody: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + var err error + var n, nTmp int + nTmp, err = u.Type.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding OperationType: %w", err) + } + switch OperationType(u.Type) { + case OperationTypeCreateAccount: + u.CreateAccountOp = new(CreateAccountOp) + nTmp, err = (*u.CreateAccountOp).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding CreateAccountOp: %w", err) + } + return n, nil + case OperationTypePayment: + u.PaymentOp = new(PaymentOp) + nTmp, err = (*u.PaymentOp).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding PaymentOp: %w", err) + } + return n, nil + case OperationTypePathPaymentStrictReceive: + u.PathPaymentStrictReceiveOp = new(PathPaymentStrictReceiveOp) + nTmp, err = (*u.PathPaymentStrictReceiveOp).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding PathPaymentStrictReceiveOp: %w", err) + } + return n, nil + case OperationTypeManageSellOffer: + u.ManageSellOfferOp = new(ManageSellOfferOp) + nTmp, err = (*u.ManageSellOfferOp).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ManageSellOfferOp: %w", err) + } + return n, nil + case OperationTypeCreatePassiveSellOffer: + u.CreatePassiveSellOfferOp = new(CreatePassiveSellOfferOp) + nTmp, err = (*u.CreatePassiveSellOfferOp).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding CreatePassiveSellOfferOp: %w", err) + } + return n, nil + case OperationTypeSetOptions: + u.SetOptionsOp = new(SetOptionsOp) + nTmp, err = (*u.SetOptionsOp).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding SetOptionsOp: %w", err) + } + return n, nil + case OperationTypeChangeTrust: + u.ChangeTrustOp = new(ChangeTrustOp) + nTmp, err = (*u.ChangeTrustOp).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ChangeTrustOp: %w", err) + } + return n, nil + case OperationTypeAllowTrust: + u.AllowTrustOp = new(AllowTrustOp) + nTmp, err = (*u.AllowTrustOp).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding AllowTrustOp: %w", err) + } + return n, nil + case OperationTypeAccountMerge: + u.Destination = new(MuxedAccount) + nTmp, err = (*u.Destination).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding MuxedAccount: %w", err) + } + return n, nil + case OperationTypeInflation: + // Void + return n, nil + case OperationTypeManageData: + u.ManageDataOp = new(ManageDataOp) + nTmp, err = (*u.ManageDataOp).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ManageDataOp: %w", err) + } + return n, nil + case OperationTypeBumpSequence: + u.BumpSequenceOp = new(BumpSequenceOp) + nTmp, err = (*u.BumpSequenceOp).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding BumpSequenceOp: %w", err) + } + return n, nil + case OperationTypeManageBuyOffer: + u.ManageBuyOfferOp = new(ManageBuyOfferOp) + nTmp, err = (*u.ManageBuyOfferOp).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ManageBuyOfferOp: %w", err) + } + return n, nil + case OperationTypePathPaymentStrictSend: + u.PathPaymentStrictSendOp = new(PathPaymentStrictSendOp) + nTmp, err = (*u.PathPaymentStrictSendOp).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding PathPaymentStrictSendOp: %w", err) + } + return n, nil + case OperationTypeCreateClaimableBalance: + u.CreateClaimableBalanceOp = new(CreateClaimableBalanceOp) + nTmp, err = (*u.CreateClaimableBalanceOp).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding CreateClaimableBalanceOp: %w", err) + } + return n, nil + case OperationTypeClaimClaimableBalance: + u.ClaimClaimableBalanceOp = new(ClaimClaimableBalanceOp) + nTmp, err = (*u.ClaimClaimableBalanceOp).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ClaimClaimableBalanceOp: %w", err) + } + return n, nil + case OperationTypeBeginSponsoringFutureReserves: + u.BeginSponsoringFutureReservesOp = new(BeginSponsoringFutureReservesOp) + nTmp, err = (*u.BeginSponsoringFutureReservesOp).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding BeginSponsoringFutureReservesOp: %w", err) + } + return n, nil + case OperationTypeEndSponsoringFutureReserves: + // Void + return n, nil + case OperationTypeRevokeSponsorship: + u.RevokeSponsorshipOp = new(RevokeSponsorshipOp) + nTmp, err = (*u.RevokeSponsorshipOp).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding RevokeSponsorshipOp: %w", err) + } + return n, nil + case OperationTypeClawback: + u.ClawbackOp = new(ClawbackOp) + nTmp, err = (*u.ClawbackOp).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ClawbackOp: %w", err) + } + return n, nil + case OperationTypeClawbackClaimableBalance: + u.ClawbackClaimableBalanceOp = new(ClawbackClaimableBalanceOp) + nTmp, err = (*u.ClawbackClaimableBalanceOp).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ClawbackClaimableBalanceOp: %w", err) + } + return n, nil + case OperationTypeSetTrustLineFlags: + u.SetTrustLineFlagsOp = new(SetTrustLineFlagsOp) + nTmp, err = (*u.SetTrustLineFlagsOp).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding SetTrustLineFlagsOp: %w", err) + } + return n, nil + case OperationTypeLiquidityPoolDeposit: + u.LiquidityPoolDepositOp = new(LiquidityPoolDepositOp) + nTmp, err = (*u.LiquidityPoolDepositOp).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding LiquidityPoolDepositOp: %w", err) + } + return n, nil + case OperationTypeLiquidityPoolWithdraw: + u.LiquidityPoolWithdrawOp = new(LiquidityPoolWithdrawOp) + nTmp, err = (*u.LiquidityPoolWithdrawOp).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding LiquidityPoolWithdrawOp: %w", err) + } + return n, nil + case OperationTypeInvokeHostFunction: + u.InvokeHostFunctionOp = new(InvokeHostFunctionOp) + nTmp, err = (*u.InvokeHostFunctionOp).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding InvokeHostFunctionOp: %w", err) + } + return n, nil + case OperationTypeExtendFootprintTtl: + u.ExtendFootprintTtlOp = new(ExtendFootprintTtlOp) + nTmp, err = (*u.ExtendFootprintTtlOp).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ExtendFootprintTtlOp: %w", err) + } + return n, nil + case OperationTypeRestoreFootprint: + u.RestoreFootprintOp = new(RestoreFootprintOp) + nTmp, err = (*u.RestoreFootprintOp).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding RestoreFootprintOp: %w", err) + } + return n, nil + } + return n, fmt.Errorf("union OperationBody has invalid Type (OperationType) switch value '%d'", u.Type) +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (s OperationBody) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *OperationBody) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} + +var ( + _ encoding.BinaryMarshaler = (*OperationBody)(nil) + _ encoding.BinaryUnmarshaler = (*OperationBody)(nil) +) + +// xdrType signals that this type represents XDR values defined by this package. +func (s OperationBody) xdrType() {} + +var _ xdrType = (*OperationBody)(nil) + +// Operation is an XDR Struct defines as: +// +// struct Operation +// { +// // sourceAccount is the account used to run the operation +// // if not set, the runtime defaults to "sourceAccount" specified at +// // the transaction level +// MuxedAccount* sourceAccount; +// +// union switch (OperationType type) +// { +// case CREATE_ACCOUNT: +// CreateAccountOp createAccountOp; +// case PAYMENT: +// PaymentOp paymentOp; +// case PATH_PAYMENT_STRICT_RECEIVE: +// PathPaymentStrictReceiveOp pathPaymentStrictReceiveOp; +// case MANAGE_SELL_OFFER: +// ManageSellOfferOp manageSellOfferOp; +// case CREATE_PASSIVE_SELL_OFFER: +// CreatePassiveSellOfferOp createPassiveSellOfferOp; +// case SET_OPTIONS: +// SetOptionsOp setOptionsOp; +// case CHANGE_TRUST: +// ChangeTrustOp changeTrustOp; +// case ALLOW_TRUST: +// AllowTrustOp allowTrustOp; +// case ACCOUNT_MERGE: +// MuxedAccount destination; +// case INFLATION: +// void; +// case MANAGE_DATA: +// ManageDataOp manageDataOp; +// case BUMP_SEQUENCE: +// BumpSequenceOp bumpSequenceOp; +// case MANAGE_BUY_OFFER: +// ManageBuyOfferOp manageBuyOfferOp; +// case PATH_PAYMENT_STRICT_SEND: +// PathPaymentStrictSendOp pathPaymentStrictSendOp; +// case CREATE_CLAIMABLE_BALANCE: +// CreateClaimableBalanceOp createClaimableBalanceOp; +// case CLAIM_CLAIMABLE_BALANCE: +// ClaimClaimableBalanceOp claimClaimableBalanceOp; +// case BEGIN_SPONSORING_FUTURE_RESERVES: +// BeginSponsoringFutureReservesOp beginSponsoringFutureReservesOp; +// case END_SPONSORING_FUTURE_RESERVES: +// void; +// case REVOKE_SPONSORSHIP: +// RevokeSponsorshipOp revokeSponsorshipOp; +// case CLAWBACK: +// ClawbackOp clawbackOp; +// case CLAWBACK_CLAIMABLE_BALANCE: +// ClawbackClaimableBalanceOp clawbackClaimableBalanceOp; +// case SET_TRUST_LINE_FLAGS: +// SetTrustLineFlagsOp setTrustLineFlagsOp; +// case LIQUIDITY_POOL_DEPOSIT: +// LiquidityPoolDepositOp liquidityPoolDepositOp; +// case LIQUIDITY_POOL_WITHDRAW: +// LiquidityPoolWithdrawOp liquidityPoolWithdrawOp; +// case INVOKE_HOST_FUNCTION: +// InvokeHostFunctionOp invokeHostFunctionOp; +// case EXTEND_FOOTPRINT_TTL: +// ExtendFootprintTTLOp extendFootprintTTLOp; +// case RESTORE_FOOTPRINT: +// RestoreFootprintOp restoreFootprintOp; +// } +// body; +// }; +type Operation struct { + SourceAccount *MuxedAccount + Body OperationBody +} + +// EncodeTo encodes this value using the Encoder. +func (s *Operation) EncodeTo(e *xdr.Encoder) error { + var err error + if _, err = e.EncodeBool(s.SourceAccount != nil); err != nil { + return err + } + if s.SourceAccount != nil { + if err = (*s.SourceAccount).EncodeTo(e); err != nil { + return err + } + } + if err = s.Body.EncodeTo(e); err != nil { + return err + } + return nil +} + +var _ decoderFrom = (*Operation)(nil) + +// DecodeFrom decodes this value using the Decoder. +func (s *Operation) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding Operation: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + var err error + var n, nTmp int + var b bool + b, nTmp, err = d.DecodeBool() + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding MuxedAccount: %w", err) + } + s.SourceAccount = nil + if b { + s.SourceAccount = new(MuxedAccount) + nTmp, err = s.SourceAccount.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding MuxedAccount: %w", err) + } + } + nTmp, err = s.Body.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding OperationBody: %w", err) + } + return n, nil +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (s Operation) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *Operation) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} + +var ( + _ encoding.BinaryMarshaler = (*Operation)(nil) + _ encoding.BinaryUnmarshaler = (*Operation)(nil) +) + +// xdrType signals that this type represents XDR values defined by this package. +func (s Operation) xdrType() {} + +var _ xdrType = (*Operation)(nil) + +// HashIdPreimageOperationId is an XDR NestedStruct defines as: +// +// struct +// { +// AccountID sourceAccount; +// SequenceNumber seqNum; +// uint32 opNum; +// } +type HashIdPreimageOperationId struct { + SourceAccount AccountId + SeqNum SequenceNumber + OpNum Uint32 +} + +// EncodeTo encodes this value using the Encoder. +func (s *HashIdPreimageOperationId) EncodeTo(e *xdr.Encoder) error { + var err error + if err = s.SourceAccount.EncodeTo(e); err != nil { + return err + } + if err = s.SeqNum.EncodeTo(e); err != nil { + return err + } + if err = s.OpNum.EncodeTo(e); err != nil { + return err + } + return nil +} + +var _ decoderFrom = (*HashIdPreimageOperationId)(nil) + +// DecodeFrom decodes this value using the Decoder. +func (s *HashIdPreimageOperationId) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding HashIdPreimageOperationId: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + var err error + var n, nTmp int + nTmp, err = s.SourceAccount.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding AccountId: %w", err) + } + nTmp, err = s.SeqNum.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding SequenceNumber: %w", err) + } + nTmp, err = s.OpNum.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Uint32: %w", err) + } + return n, nil +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (s HashIdPreimageOperationId) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *HashIdPreimageOperationId) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} + +var ( + _ encoding.BinaryMarshaler = (*HashIdPreimageOperationId)(nil) + _ encoding.BinaryUnmarshaler = (*HashIdPreimageOperationId)(nil) +) + +// xdrType signals that this type represents XDR values defined by this package. +func (s HashIdPreimageOperationId) xdrType() {} + +var _ xdrType = (*HashIdPreimageOperationId)(nil) + +// HashIdPreimageRevokeId is an XDR NestedStruct defines as: +// +// struct +// { +// AccountID sourceAccount; +// SequenceNumber seqNum; +// uint32 opNum; +// PoolID liquidityPoolID; +// Asset asset; +// } +type HashIdPreimageRevokeId struct { + SourceAccount AccountId + SeqNum SequenceNumber + OpNum Uint32 + LiquidityPoolId PoolId + Asset Asset +} + +// EncodeTo encodes this value using the Encoder. +func (s *HashIdPreimageRevokeId) EncodeTo(e *xdr.Encoder) error { + var err error + if err = s.SourceAccount.EncodeTo(e); err != nil { + return err + } + if err = s.SeqNum.EncodeTo(e); err != nil { + return err + } + if err = s.OpNum.EncodeTo(e); err != nil { + return err + } + if err = s.LiquidityPoolId.EncodeTo(e); err != nil { + return err + } + if err = s.Asset.EncodeTo(e); err != nil { + return err + } + return nil +} + +var _ decoderFrom = (*HashIdPreimageRevokeId)(nil) + +// DecodeFrom decodes this value using the Decoder. +func (s *HashIdPreimageRevokeId) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding HashIdPreimageRevokeId: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + var err error + var n, nTmp int + nTmp, err = s.SourceAccount.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding AccountId: %w", err) + } + nTmp, err = s.SeqNum.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding SequenceNumber: %w", err) + } + nTmp, err = s.OpNum.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Uint32: %w", err) + } + nTmp, err = s.LiquidityPoolId.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding PoolId: %w", err) + } + nTmp, err = s.Asset.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Asset: %w", err) + } + return n, nil +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (s HashIdPreimageRevokeId) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *HashIdPreimageRevokeId) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} + +var ( + _ encoding.BinaryMarshaler = (*HashIdPreimageRevokeId)(nil) + _ encoding.BinaryUnmarshaler = (*HashIdPreimageRevokeId)(nil) +) + +// xdrType signals that this type represents XDR values defined by this package. +func (s HashIdPreimageRevokeId) xdrType() {} + +var _ xdrType = (*HashIdPreimageRevokeId)(nil) + +// HashIdPreimageContractId is an XDR NestedStruct defines as: +// +// struct +// { +// Hash networkID; +// ContractIDPreimage contractIDPreimage; +// } +type HashIdPreimageContractId struct { + NetworkId Hash + ContractIdPreimage ContractIdPreimage +} + +// EncodeTo encodes this value using the Encoder. +func (s *HashIdPreimageContractId) EncodeTo(e *xdr.Encoder) error { + var err error + if err = s.NetworkId.EncodeTo(e); err != nil { + return err + } + if err = s.ContractIdPreimage.EncodeTo(e); err != nil { + return err + } + return nil +} + +var _ decoderFrom = (*HashIdPreimageContractId)(nil) + +// DecodeFrom decodes this value using the Decoder. +func (s *HashIdPreimageContractId) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding HashIdPreimageContractId: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + var err error + var n, nTmp int + nTmp, err = s.NetworkId.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Hash: %w", err) + } + nTmp, err = s.ContractIdPreimage.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ContractIdPreimage: %w", err) + } + return n, nil +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (s HashIdPreimageContractId) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *HashIdPreimageContractId) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} + +var ( + _ encoding.BinaryMarshaler = (*HashIdPreimageContractId)(nil) + _ encoding.BinaryUnmarshaler = (*HashIdPreimageContractId)(nil) +) + +// xdrType signals that this type represents XDR values defined by this package. +func (s HashIdPreimageContractId) xdrType() {} + +var _ xdrType = (*HashIdPreimageContractId)(nil) + +// HashIdPreimageSorobanAuthorization is an XDR NestedStruct defines as: +// +// struct +// { +// Hash networkID; +// int64 nonce; +// uint32 signatureExpirationLedger; +// SorobanAuthorizedInvocation invocation; +// } +type HashIdPreimageSorobanAuthorization struct { + NetworkId Hash + Nonce Int64 + SignatureExpirationLedger Uint32 + Invocation SorobanAuthorizedInvocation +} + +// EncodeTo encodes this value using the Encoder. +func (s *HashIdPreimageSorobanAuthorization) EncodeTo(e *xdr.Encoder) error { + var err error + if err = s.NetworkId.EncodeTo(e); err != nil { + return err + } + if err = s.Nonce.EncodeTo(e); err != nil { + return err + } + if err = s.SignatureExpirationLedger.EncodeTo(e); err != nil { + return err + } + if err = s.Invocation.EncodeTo(e); err != nil { + return err + } + return nil +} + +var _ decoderFrom = (*HashIdPreimageSorobanAuthorization)(nil) + +// DecodeFrom decodes this value using the Decoder. +func (s *HashIdPreimageSorobanAuthorization) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding HashIdPreimageSorobanAuthorization: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + var err error + var n, nTmp int + nTmp, err = s.NetworkId.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Hash: %w", err) + } + nTmp, err = s.Nonce.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Int64: %w", err) + } + nTmp, err = s.SignatureExpirationLedger.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Uint32: %w", err) + } + nTmp, err = s.Invocation.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding SorobanAuthorizedInvocation: %w", err) + } + return n, nil +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (s HashIdPreimageSorobanAuthorization) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *HashIdPreimageSorobanAuthorization) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} + +var ( + _ encoding.BinaryMarshaler = (*HashIdPreimageSorobanAuthorization)(nil) + _ encoding.BinaryUnmarshaler = (*HashIdPreimageSorobanAuthorization)(nil) +) + +// xdrType signals that this type represents XDR values defined by this package. +func (s HashIdPreimageSorobanAuthorization) xdrType() {} + +var _ xdrType = (*HashIdPreimageSorobanAuthorization)(nil) + +// HashIdPreimage is an XDR Union defines as: +// +// union HashIDPreimage switch (EnvelopeType type) +// { +// case ENVELOPE_TYPE_OP_ID: +// struct +// { +// AccountID sourceAccount; +// SequenceNumber seqNum; +// uint32 opNum; +// } operationID; +// case ENVELOPE_TYPE_POOL_REVOKE_OP_ID: +// struct +// { +// AccountID sourceAccount; +// SequenceNumber seqNum; +// uint32 opNum; +// PoolID liquidityPoolID; +// Asset asset; +// } revokeID; +// case ENVELOPE_TYPE_CONTRACT_ID: +// struct +// { +// Hash networkID; +// ContractIDPreimage contractIDPreimage; +// } contractID; +// case ENVELOPE_TYPE_SOROBAN_AUTHORIZATION: +// struct +// { +// Hash networkID; +// int64 nonce; +// uint32 signatureExpirationLedger; +// SorobanAuthorizedInvocation invocation; +// } sorobanAuthorization; +// }; +type HashIdPreimage struct { + Type EnvelopeType + OperationId *HashIdPreimageOperationId + RevokeId *HashIdPreimageRevokeId + ContractId *HashIdPreimageContractId + SorobanAuthorization *HashIdPreimageSorobanAuthorization +} + +// SwitchFieldName returns the field name in which this union's +// discriminant is stored +func (u HashIdPreimage) SwitchFieldName() string { + return "Type" +} + +// ArmForSwitch returns which field name should be used for storing +// the value for an instance of HashIdPreimage +func (u HashIdPreimage) ArmForSwitch(sw int32) (string, bool) { + switch EnvelopeType(sw) { + case EnvelopeTypeEnvelopeTypeOpId: + return "OperationId", true + case EnvelopeTypeEnvelopeTypePoolRevokeOpId: + return "RevokeId", true + case EnvelopeTypeEnvelopeTypeContractId: + return "ContractId", true + case EnvelopeTypeEnvelopeTypeSorobanAuthorization: + return "SorobanAuthorization", true + } + return "-", false +} + +// NewHashIdPreimage creates a new HashIdPreimage. +func NewHashIdPreimage(aType EnvelopeType, value interface{}) (result HashIdPreimage, err error) { + result.Type = aType + switch EnvelopeType(aType) { + case EnvelopeTypeEnvelopeTypeOpId: + tv, ok := value.(HashIdPreimageOperationId) + if !ok { + err = errors.New("invalid value, must be HashIdPreimageOperationId") + return + } + result.OperationId = &tv + case EnvelopeTypeEnvelopeTypePoolRevokeOpId: + tv, ok := value.(HashIdPreimageRevokeId) + if !ok { + err = errors.New("invalid value, must be HashIdPreimageRevokeId") + return + } + result.RevokeId = &tv + case EnvelopeTypeEnvelopeTypeContractId: + tv, ok := value.(HashIdPreimageContractId) + if !ok { + err = errors.New("invalid value, must be HashIdPreimageContractId") + return + } + result.ContractId = &tv + case EnvelopeTypeEnvelopeTypeSorobanAuthorization: + tv, ok := value.(HashIdPreimageSorobanAuthorization) + if !ok { + err = errors.New("invalid value, must be HashIdPreimageSorobanAuthorization") + return + } + result.SorobanAuthorization = &tv + } + return +} + +// MustOperationId retrieves the OperationId value from the union, +// panicing if the value is not set. +func (u HashIdPreimage) MustOperationId() HashIdPreimageOperationId { + val, ok := u.GetOperationId() + + if !ok { + panic("arm OperationId is not set") + } + + return val +} + +// GetOperationId retrieves the OperationId value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u HashIdPreimage) GetOperationId() (result HashIdPreimageOperationId, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) + + if armName == "OperationId" { + result = *u.OperationId + ok = true + } + + return +} + +// MustRevokeId retrieves the RevokeId value from the union, +// panicing if the value is not set. +func (u HashIdPreimage) MustRevokeId() HashIdPreimageRevokeId { + val, ok := u.GetRevokeId() + + if !ok { + panic("arm RevokeId is not set") + } + + return val +} + +// GetRevokeId retrieves the RevokeId value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u HashIdPreimage) GetRevokeId() (result HashIdPreimageRevokeId, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) + + if armName == "RevokeId" { + result = *u.RevokeId + ok = true + } + + return +} + +// MustContractId retrieves the ContractId value from the union, +// panicing if the value is not set. +func (u HashIdPreimage) MustContractId() HashIdPreimageContractId { + val, ok := u.GetContractId() + + if !ok { + panic("arm ContractId is not set") + } + + return val +} + +// GetContractId retrieves the ContractId value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u HashIdPreimage) GetContractId() (result HashIdPreimageContractId, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) + + if armName == "ContractId" { + result = *u.ContractId + ok = true + } + + return +} + +// MustSorobanAuthorization retrieves the SorobanAuthorization value from the union, +// panicing if the value is not set. +func (u HashIdPreimage) MustSorobanAuthorization() HashIdPreimageSorobanAuthorization { + val, ok := u.GetSorobanAuthorization() + + if !ok { + panic("arm SorobanAuthorization is not set") + } + + return val +} + +// GetSorobanAuthorization retrieves the SorobanAuthorization value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u HashIdPreimage) GetSorobanAuthorization() (result HashIdPreimageSorobanAuthorization, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) + + if armName == "SorobanAuthorization" { + result = *u.SorobanAuthorization + ok = true + } + + return +} + +// EncodeTo encodes this value using the Encoder. +func (u HashIdPreimage) EncodeTo(e *xdr.Encoder) error { + var err error + if err = u.Type.EncodeTo(e); err != nil { + return err + } + switch EnvelopeType(u.Type) { + case EnvelopeTypeEnvelopeTypeOpId: + if err = (*u.OperationId).EncodeTo(e); err != nil { + return err + } + return nil + case EnvelopeTypeEnvelopeTypePoolRevokeOpId: + if err = (*u.RevokeId).EncodeTo(e); err != nil { + return err + } + return nil + case EnvelopeTypeEnvelopeTypeContractId: + if err = (*u.ContractId).EncodeTo(e); err != nil { + return err + } + return nil + case EnvelopeTypeEnvelopeTypeSorobanAuthorization: + if err = (*u.SorobanAuthorization).EncodeTo(e); err != nil { + return err + } + return nil + } + return fmt.Errorf("Type (EnvelopeType) switch value '%d' is not valid for union HashIdPreimage", u.Type) +} + +var _ decoderFrom = (*HashIdPreimage)(nil) + +// DecodeFrom decodes this value using the Decoder. +func (u *HashIdPreimage) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding HashIdPreimage: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + var err error + var n, nTmp int + nTmp, err = u.Type.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding EnvelopeType: %w", err) + } + switch EnvelopeType(u.Type) { + case EnvelopeTypeEnvelopeTypeOpId: + u.OperationId = new(HashIdPreimageOperationId) + nTmp, err = (*u.OperationId).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding HashIdPreimageOperationId: %w", err) + } + return n, nil + case EnvelopeTypeEnvelopeTypePoolRevokeOpId: + u.RevokeId = new(HashIdPreimageRevokeId) + nTmp, err = (*u.RevokeId).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding HashIdPreimageRevokeId: %w", err) + } + return n, nil + case EnvelopeTypeEnvelopeTypeContractId: + u.ContractId = new(HashIdPreimageContractId) + nTmp, err = (*u.ContractId).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding HashIdPreimageContractId: %w", err) + } + return n, nil + case EnvelopeTypeEnvelopeTypeSorobanAuthorization: + u.SorobanAuthorization = new(HashIdPreimageSorobanAuthorization) + nTmp, err = (*u.SorobanAuthorization).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding HashIdPreimageSorobanAuthorization: %w", err) + } + return n, nil + } + return n, fmt.Errorf("union HashIdPreimage has invalid Type (EnvelopeType) switch value '%d'", u.Type) +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (s HashIdPreimage) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *HashIdPreimage) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} + +var ( + _ encoding.BinaryMarshaler = (*HashIdPreimage)(nil) + _ encoding.BinaryUnmarshaler = (*HashIdPreimage)(nil) +) + +// xdrType signals that this type represents XDR values defined by this package. +func (s HashIdPreimage) xdrType() {} + +var _ xdrType = (*HashIdPreimage)(nil) + +// MemoType is an XDR Enum defines as: +// +// enum MemoType +// { +// MEMO_NONE = 0, +// MEMO_TEXT = 1, +// MEMO_ID = 2, +// MEMO_HASH = 3, +// MEMO_RETURN = 4 +// }; +type MemoType int32 + +const ( + MemoTypeMemoNone MemoType = 0 + MemoTypeMemoText MemoType = 1 + MemoTypeMemoId MemoType = 2 + MemoTypeMemoHash MemoType = 3 + MemoTypeMemoReturn MemoType = 4 +) + +var memoTypeMap = map[int32]string{ + 0: "MemoTypeMemoNone", + 1: "MemoTypeMemoText", + 2: "MemoTypeMemoId", + 3: "MemoTypeMemoHash", + 4: "MemoTypeMemoReturn", +} + +// ValidEnum validates a proposed value for this enum. Implements +// the Enum interface for MemoType +func (e MemoType) ValidEnum(v int32) bool { + _, ok := memoTypeMap[v] + return ok +} + +// String returns the name of `e` +func (e MemoType) String() string { + name, _ := memoTypeMap[int32(e)] + return name +} + +// EncodeTo encodes this value using the Encoder. +func (e MemoType) EncodeTo(enc *xdr.Encoder) error { + if _, ok := memoTypeMap[int32(e)]; !ok { + return fmt.Errorf("'%d' is not a valid MemoType enum value", e) + } + _, err := enc.EncodeInt(int32(e)) + return err +} + +var _ decoderFrom = (*MemoType)(nil) + +// DecodeFrom decodes this value using the Decoder. +func (e *MemoType) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding MemoType: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + v, n, err := d.DecodeInt() + if err != nil { + return n, fmt.Errorf("decoding MemoType: %w", err) + } + if _, ok := memoTypeMap[v]; !ok { + return n, fmt.Errorf("'%d' is not a valid MemoType enum value", v) + } + *e = MemoType(v) + return n, nil +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (s MemoType) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *MemoType) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} + +var ( + _ encoding.BinaryMarshaler = (*MemoType)(nil) + _ encoding.BinaryUnmarshaler = (*MemoType)(nil) +) + +// xdrType signals that this type represents XDR values defined by this package. +func (s MemoType) xdrType() {} + +var _ xdrType = (*MemoType)(nil) + +// Memo is an XDR Union defines as: +// +// union Memo switch (MemoType type) +// { +// case MEMO_NONE: +// void; +// case MEMO_TEXT: +// string text<28>; +// case MEMO_ID: +// uint64 id; +// case MEMO_HASH: +// Hash hash; // the hash of what to pull from the content server +// case MEMO_RETURN: +// Hash retHash; // the hash of the tx you are rejecting +// }; +type Memo struct { + Type MemoType + Text *string `xdrmaxsize:"28"` + Id *Uint64 + Hash *Hash + RetHash *Hash +} + +// SwitchFieldName returns the field name in which this union's +// discriminant is stored +func (u Memo) SwitchFieldName() string { + return "Type" +} + +// ArmForSwitch returns which field name should be used for storing +// the value for an instance of Memo +func (u Memo) ArmForSwitch(sw int32) (string, bool) { + switch MemoType(sw) { + case MemoTypeMemoNone: + return "", true + case MemoTypeMemoText: + return "Text", true + case MemoTypeMemoId: + return "Id", true + case MemoTypeMemoHash: + return "Hash", true + case MemoTypeMemoReturn: + return "RetHash", true + } + return "-", false +} + +// NewMemo creates a new Memo. +func NewMemo(aType MemoType, value interface{}) (result Memo, err error) { + result.Type = aType + switch MemoType(aType) { + case MemoTypeMemoNone: + // void + case MemoTypeMemoText: + tv, ok := value.(string) + if !ok { + err = errors.New("invalid value, must be string") + return + } + result.Text = &tv + case MemoTypeMemoId: + tv, ok := value.(Uint64) + if !ok { + err = errors.New("invalid value, must be Uint64") + return + } + result.Id = &tv + case MemoTypeMemoHash: + tv, ok := value.(Hash) + if !ok { + err = errors.New("invalid value, must be Hash") + return + } + result.Hash = &tv + case MemoTypeMemoReturn: + tv, ok := value.(Hash) + if !ok { + err = errors.New("invalid value, must be Hash") + return + } + result.RetHash = &tv + } + return +} + +// MustText retrieves the Text value from the union, +// panicing if the value is not set. +func (u Memo) MustText() string { + val, ok := u.GetText() + + if !ok { + panic("arm Text is not set") + } + + return val +} + +// GetText retrieves the Text value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u Memo) GetText() (result string, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) + + if armName == "Text" { + result = *u.Text + ok = true + } + + return +} + +// MustId retrieves the Id value from the union, +// panicing if the value is not set. +func (u Memo) MustId() Uint64 { + val, ok := u.GetId() + + if !ok { + panic("arm Id is not set") + } + + return val +} + +// GetId retrieves the Id value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u Memo) GetId() (result Uint64, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) + + if armName == "Id" { + result = *u.Id + ok = true + } + + return +} + +// MustHash retrieves the Hash value from the union, +// panicing if the value is not set. +func (u Memo) MustHash() Hash { + val, ok := u.GetHash() + + if !ok { + panic("arm Hash is not set") + } + + return val +} + +// GetHash retrieves the Hash value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u Memo) GetHash() (result Hash, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) + + if armName == "Hash" { + result = *u.Hash + ok = true + } + + return +} + +// MustRetHash retrieves the RetHash value from the union, +// panicing if the value is not set. +func (u Memo) MustRetHash() Hash { + val, ok := u.GetRetHash() + + if !ok { + panic("arm RetHash is not set") + } + + return val +} + +// GetRetHash retrieves the RetHash value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u Memo) GetRetHash() (result Hash, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) + + if armName == "RetHash" { + result = *u.RetHash + ok = true + } + + return +} + +// EncodeTo encodes this value using the Encoder. +func (u Memo) EncodeTo(e *xdr.Encoder) error { + var err error + if err = u.Type.EncodeTo(e); err != nil { + return err + } + switch MemoType(u.Type) { + case MemoTypeMemoNone: + // Void + return nil + case MemoTypeMemoText: + if _, err = e.EncodeString(string((*u.Text))); err != nil { + return err + } + return nil + case MemoTypeMemoId: + if err = (*u.Id).EncodeTo(e); err != nil { + return err + } + return nil + case MemoTypeMemoHash: + if err = (*u.Hash).EncodeTo(e); err != nil { + return err + } + return nil + case MemoTypeMemoReturn: + if err = (*u.RetHash).EncodeTo(e); err != nil { + return err + } + return nil + } + return fmt.Errorf("Type (MemoType) switch value '%d' is not valid for union Memo", u.Type) +} + +var _ decoderFrom = (*Memo)(nil) + +// DecodeFrom decodes this value using the Decoder. +func (u *Memo) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding Memo: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + var err error + var n, nTmp int + nTmp, err = u.Type.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding MemoType: %w", err) + } + switch MemoType(u.Type) { + case MemoTypeMemoNone: + // Void + return n, nil + case MemoTypeMemoText: + u.Text = new(string) + (*u.Text), nTmp, err = d.DecodeString(28) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Text: %w", err) + } + return n, nil + case MemoTypeMemoId: + u.Id = new(Uint64) + nTmp, err = (*u.Id).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Uint64: %w", err) + } + return n, nil + case MemoTypeMemoHash: + u.Hash = new(Hash) + nTmp, err = (*u.Hash).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Hash: %w", err) + } + return n, nil + case MemoTypeMemoReturn: + u.RetHash = new(Hash) + nTmp, err = (*u.RetHash).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Hash: %w", err) + } + return n, nil + } + return n, fmt.Errorf("union Memo has invalid Type (MemoType) switch value '%d'", u.Type) +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (s Memo) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *Memo) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} + +var ( + _ encoding.BinaryMarshaler = (*Memo)(nil) + _ encoding.BinaryUnmarshaler = (*Memo)(nil) +) + +// xdrType signals that this type represents XDR values defined by this package. +func (s Memo) xdrType() {} + +var _ xdrType = (*Memo)(nil) + +// TimeBounds is an XDR Struct defines as: +// +// struct TimeBounds +// { +// TimePoint minTime; +// TimePoint maxTime; // 0 here means no maxTime +// }; +type TimeBounds struct { + MinTime TimePoint + MaxTime TimePoint +} + +// EncodeTo encodes this value using the Encoder. +func (s *TimeBounds) EncodeTo(e *xdr.Encoder) error { + var err error + if err = s.MinTime.EncodeTo(e); err != nil { + return err + } + if err = s.MaxTime.EncodeTo(e); err != nil { + return err + } + return nil +} + +var _ decoderFrom = (*TimeBounds)(nil) + +// DecodeFrom decodes this value using the Decoder. +func (s *TimeBounds) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding TimeBounds: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + var err error + var n, nTmp int + nTmp, err = s.MinTime.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding TimePoint: %w", err) + } + nTmp, err = s.MaxTime.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding TimePoint: %w", err) + } + return n, nil +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (s TimeBounds) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *TimeBounds) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} + +var ( + _ encoding.BinaryMarshaler = (*TimeBounds)(nil) + _ encoding.BinaryUnmarshaler = (*TimeBounds)(nil) +) + +// xdrType signals that this type represents XDR values defined by this package. +func (s TimeBounds) xdrType() {} + +var _ xdrType = (*TimeBounds)(nil) + +// LedgerBounds is an XDR Struct defines as: +// +// struct LedgerBounds +// { +// uint32 minLedger; +// uint32 maxLedger; // 0 here means no maxLedger +// }; +type LedgerBounds struct { + MinLedger Uint32 + MaxLedger Uint32 +} + +// EncodeTo encodes this value using the Encoder. +func (s *LedgerBounds) EncodeTo(e *xdr.Encoder) error { + var err error + if err = s.MinLedger.EncodeTo(e); err != nil { + return err + } + if err = s.MaxLedger.EncodeTo(e); err != nil { + return err + } + return nil +} + +var _ decoderFrom = (*LedgerBounds)(nil) + +// DecodeFrom decodes this value using the Decoder. +func (s *LedgerBounds) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding LedgerBounds: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + var err error + var n, nTmp int + nTmp, err = s.MinLedger.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Uint32: %w", err) + } + nTmp, err = s.MaxLedger.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Uint32: %w", err) + } + return n, nil +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (s LedgerBounds) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *LedgerBounds) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} + +var ( + _ encoding.BinaryMarshaler = (*LedgerBounds)(nil) + _ encoding.BinaryUnmarshaler = (*LedgerBounds)(nil) +) + +// xdrType signals that this type represents XDR values defined by this package. +func (s LedgerBounds) xdrType() {} + +var _ xdrType = (*LedgerBounds)(nil) + +// PreconditionsV2 is an XDR Struct defines as: +// +// struct PreconditionsV2 +// { +// TimeBounds* timeBounds; +// +// // Transaction only valid for ledger numbers n such that +// // minLedger <= n < maxLedger (if maxLedger == 0, then +// // only minLedger is checked) +// LedgerBounds* ledgerBounds; +// +// // If NULL, only valid when sourceAccount's sequence number +// // is seqNum - 1. Otherwise, valid when sourceAccount's +// // sequence number n satisfies minSeqNum <= n < tx.seqNum. +// // Note that after execution the account's sequence number +// // is always raised to tx.seqNum, and a transaction is not +// // valid if tx.seqNum is too high to ensure replay protection. +// SequenceNumber* minSeqNum; +// +// // For the transaction to be valid, the current ledger time must +// // be at least minSeqAge greater than sourceAccount's seqTime. +// Duration minSeqAge; +// +// // For the transaction to be valid, the current ledger number +// // must be at least minSeqLedgerGap greater than sourceAccount's +// // seqLedger. +// uint32 minSeqLedgerGap; +// +// // For the transaction to be valid, there must be a signature +// // corresponding to every Signer in this array, even if the +// // signature is not otherwise required by the sourceAccount or +// // operations. +// SignerKey extraSigners<2>; +// }; +type PreconditionsV2 struct { + TimeBounds *TimeBounds + LedgerBounds *LedgerBounds + MinSeqNum *SequenceNumber + MinSeqAge Duration + MinSeqLedgerGap Uint32 + ExtraSigners []SignerKey `xdrmaxsize:"2"` +} + +// EncodeTo encodes this value using the Encoder. +func (s *PreconditionsV2) EncodeTo(e *xdr.Encoder) error { + var err error + if _, err = e.EncodeBool(s.TimeBounds != nil); err != nil { + return err + } + if s.TimeBounds != nil { + if err = (*s.TimeBounds).EncodeTo(e); err != nil { + return err + } + } + if _, err = e.EncodeBool(s.LedgerBounds != nil); err != nil { + return err + } + if s.LedgerBounds != nil { + if err = (*s.LedgerBounds).EncodeTo(e); err != nil { + return err + } + } + if _, err = e.EncodeBool(s.MinSeqNum != nil); err != nil { + return err + } + if s.MinSeqNum != nil { + if err = (*s.MinSeqNum).EncodeTo(e); err != nil { + return err + } + } + if err = s.MinSeqAge.EncodeTo(e); err != nil { + return err + } + if err = s.MinSeqLedgerGap.EncodeTo(e); err != nil { + return err + } + if _, err = e.EncodeUint(uint32(len(s.ExtraSigners))); err != nil { + return err + } + for i := 0; i < len(s.ExtraSigners); i++ { + if err = s.ExtraSigners[i].EncodeTo(e); err != nil { + return err + } + } + return nil +} + +var _ decoderFrom = (*PreconditionsV2)(nil) + +// DecodeFrom decodes this value using the Decoder. +func (s *PreconditionsV2) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding PreconditionsV2: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + var err error + var n, nTmp int + var b bool + b, nTmp, err = d.DecodeBool() + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding TimeBounds: %w", err) + } + s.TimeBounds = nil + if b { + s.TimeBounds = new(TimeBounds) + nTmp, err = s.TimeBounds.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding TimeBounds: %w", err) + } + } + b, nTmp, err = d.DecodeBool() + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding LedgerBounds: %w", err) + } + s.LedgerBounds = nil + if b { + s.LedgerBounds = new(LedgerBounds) + nTmp, err = s.LedgerBounds.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding LedgerBounds: %w", err) + } + } + b, nTmp, err = d.DecodeBool() + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding SequenceNumber: %w", err) + } + s.MinSeqNum = nil + if b { + s.MinSeqNum = new(SequenceNumber) + nTmp, err = s.MinSeqNum.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding SequenceNumber: %w", err) + } + } + nTmp, err = s.MinSeqAge.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Duration: %w", err) + } + nTmp, err = s.MinSeqLedgerGap.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Uint32: %w", err) + } + var l uint32 + l, nTmp, err = d.DecodeUint() + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding SignerKey: %w", err) + } + if l > 2 { + return n, fmt.Errorf("decoding SignerKey: data size (%d) exceeds size limit (2)", l) + } + s.ExtraSigners = nil + if l > 0 { + if il, ok := d.InputLen(); ok && uint(il) < uint(l) { + return n, fmt.Errorf("decoding SignerKey: length (%d) exceeds remaining input length (%d)", l, il) + } + s.ExtraSigners = make([]SignerKey, l) + for i := uint32(0); i < l; i++ { + nTmp, err = s.ExtraSigners[i].DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding SignerKey: %w", err) + } + } + } + return n, nil +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (s PreconditionsV2) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *PreconditionsV2) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} + +var ( + _ encoding.BinaryMarshaler = (*PreconditionsV2)(nil) + _ encoding.BinaryUnmarshaler = (*PreconditionsV2)(nil) +) + +// xdrType signals that this type represents XDR values defined by this package. +func (s PreconditionsV2) xdrType() {} + +var _ xdrType = (*PreconditionsV2)(nil) + +// PreconditionType is an XDR Enum defines as: +// +// enum PreconditionType +// { +// PRECOND_NONE = 0, +// PRECOND_TIME = 1, +// PRECOND_V2 = 2 +// }; +type PreconditionType int32 + +const ( + PreconditionTypePrecondNone PreconditionType = 0 + PreconditionTypePrecondTime PreconditionType = 1 + PreconditionTypePrecondV2 PreconditionType = 2 +) + +var preconditionTypeMap = map[int32]string{ + 0: "PreconditionTypePrecondNone", + 1: "PreconditionTypePrecondTime", + 2: "PreconditionTypePrecondV2", +} + +// ValidEnum validates a proposed value for this enum. Implements +// the Enum interface for PreconditionType +func (e PreconditionType) ValidEnum(v int32) bool { + _, ok := preconditionTypeMap[v] + return ok +} + +// String returns the name of `e` +func (e PreconditionType) String() string { + name, _ := preconditionTypeMap[int32(e)] + return name +} + +// EncodeTo encodes this value using the Encoder. +func (e PreconditionType) EncodeTo(enc *xdr.Encoder) error { + if _, ok := preconditionTypeMap[int32(e)]; !ok { + return fmt.Errorf("'%d' is not a valid PreconditionType enum value", e) + } + _, err := enc.EncodeInt(int32(e)) + return err +} + +var _ decoderFrom = (*PreconditionType)(nil) + +// DecodeFrom decodes this value using the Decoder. +func (e *PreconditionType) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding PreconditionType: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + v, n, err := d.DecodeInt() + if err != nil { + return n, fmt.Errorf("decoding PreconditionType: %w", err) + } + if _, ok := preconditionTypeMap[v]; !ok { + return n, fmt.Errorf("'%d' is not a valid PreconditionType enum value", v) + } + *e = PreconditionType(v) + return n, nil +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (s PreconditionType) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *PreconditionType) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} + +var ( + _ encoding.BinaryMarshaler = (*PreconditionType)(nil) + _ encoding.BinaryUnmarshaler = (*PreconditionType)(nil) +) + +// xdrType signals that this type represents XDR values defined by this package. +func (s PreconditionType) xdrType() {} + +var _ xdrType = (*PreconditionType)(nil) + +// Preconditions is an XDR Union defines as: +// +// union Preconditions switch (PreconditionType type) +// { +// case PRECOND_NONE: +// void; +// case PRECOND_TIME: +// TimeBounds timeBounds; +// case PRECOND_V2: +// PreconditionsV2 v2; +// }; +type Preconditions struct { + Type PreconditionType + TimeBounds *TimeBounds + V2 *PreconditionsV2 +} + +// SwitchFieldName returns the field name in which this union's +// discriminant is stored +func (u Preconditions) SwitchFieldName() string { + return "Type" +} + +// ArmForSwitch returns which field name should be used for storing +// the value for an instance of Preconditions +func (u Preconditions) ArmForSwitch(sw int32) (string, bool) { + switch PreconditionType(sw) { + case PreconditionTypePrecondNone: + return "", true + case PreconditionTypePrecondTime: + return "TimeBounds", true + case PreconditionTypePrecondV2: + return "V2", true + } + return "-", false +} + +// NewPreconditions creates a new Preconditions. +func NewPreconditions(aType PreconditionType, value interface{}) (result Preconditions, err error) { + result.Type = aType + switch PreconditionType(aType) { + case PreconditionTypePrecondNone: + // void + case PreconditionTypePrecondTime: + tv, ok := value.(TimeBounds) + if !ok { + err = errors.New("invalid value, must be TimeBounds") + return + } + result.TimeBounds = &tv + case PreconditionTypePrecondV2: + tv, ok := value.(PreconditionsV2) + if !ok { + err = errors.New("invalid value, must be PreconditionsV2") + return + } + result.V2 = &tv + } + return +} + +// MustTimeBounds retrieves the TimeBounds value from the union, +// panicing if the value is not set. +func (u Preconditions) MustTimeBounds() TimeBounds { + val, ok := u.GetTimeBounds() + + if !ok { + panic("arm TimeBounds is not set") + } + + return val +} + +// GetTimeBounds retrieves the TimeBounds value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u Preconditions) GetTimeBounds() (result TimeBounds, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) + + if armName == "TimeBounds" { + result = *u.TimeBounds + ok = true + } + + return +} + +// MustV2 retrieves the V2 value from the union, +// panicing if the value is not set. +func (u Preconditions) MustV2() PreconditionsV2 { + val, ok := u.GetV2() + + if !ok { + panic("arm V2 is not set") + } + + return val +} + +// GetV2 retrieves the V2 value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u Preconditions) GetV2() (result PreconditionsV2, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) + + if armName == "V2" { + result = *u.V2 + ok = true + } + + return +} + +// EncodeTo encodes this value using the Encoder. +func (u Preconditions) EncodeTo(e *xdr.Encoder) error { + var err error + if err = u.Type.EncodeTo(e); err != nil { + return err + } + switch PreconditionType(u.Type) { + case PreconditionTypePrecondNone: + // Void + return nil + case PreconditionTypePrecondTime: + if err = (*u.TimeBounds).EncodeTo(e); err != nil { + return err + } + return nil + case PreconditionTypePrecondV2: + if err = (*u.V2).EncodeTo(e); err != nil { + return err + } + return nil + } + return fmt.Errorf("Type (PreconditionType) switch value '%d' is not valid for union Preconditions", u.Type) +} + +var _ decoderFrom = (*Preconditions)(nil) + +// DecodeFrom decodes this value using the Decoder. +func (u *Preconditions) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding Preconditions: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + var err error + var n, nTmp int + nTmp, err = u.Type.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding PreconditionType: %w", err) + } + switch PreconditionType(u.Type) { + case PreconditionTypePrecondNone: + // Void + return n, nil + case PreconditionTypePrecondTime: + u.TimeBounds = new(TimeBounds) + nTmp, err = (*u.TimeBounds).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding TimeBounds: %w", err) + } + return n, nil + case PreconditionTypePrecondV2: + u.V2 = new(PreconditionsV2) + nTmp, err = (*u.V2).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding PreconditionsV2: %w", err) + } + return n, nil + } + return n, fmt.Errorf("union Preconditions has invalid Type (PreconditionType) switch value '%d'", u.Type) +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (s Preconditions) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *Preconditions) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} + +var ( + _ encoding.BinaryMarshaler = (*Preconditions)(nil) + _ encoding.BinaryUnmarshaler = (*Preconditions)(nil) +) + +// xdrType signals that this type represents XDR values defined by this package. +func (s Preconditions) xdrType() {} + +var _ xdrType = (*Preconditions)(nil) + +// LedgerFootprint is an XDR Struct defines as: +// +// struct LedgerFootprint +// { +// LedgerKey readOnly<>; +// LedgerKey readWrite<>; +// }; +type LedgerFootprint struct { + ReadOnly []LedgerKey + ReadWrite []LedgerKey +} + +// EncodeTo encodes this value using the Encoder. +func (s *LedgerFootprint) EncodeTo(e *xdr.Encoder) error { + var err error + if _, err = e.EncodeUint(uint32(len(s.ReadOnly))); err != nil { + return err + } + for i := 0; i < len(s.ReadOnly); i++ { + if err = s.ReadOnly[i].EncodeTo(e); err != nil { + return err + } + } + if _, err = e.EncodeUint(uint32(len(s.ReadWrite))); err != nil { + return err + } + for i := 0; i < len(s.ReadWrite); i++ { + if err = s.ReadWrite[i].EncodeTo(e); err != nil { + return err + } + } + return nil +} + +var _ decoderFrom = (*LedgerFootprint)(nil) + +// DecodeFrom decodes this value using the Decoder. +func (s *LedgerFootprint) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding LedgerFootprint: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + var err error + var n, nTmp int + var l uint32 + l, nTmp, err = d.DecodeUint() + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding LedgerKey: %w", err) + } + s.ReadOnly = nil + if l > 0 { + if il, ok := d.InputLen(); ok && uint(il) < uint(l) { + return n, fmt.Errorf("decoding LedgerKey: length (%d) exceeds remaining input length (%d)", l, il) + } + s.ReadOnly = make([]LedgerKey, l) + for i := uint32(0); i < l; i++ { + nTmp, err = s.ReadOnly[i].DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding LedgerKey: %w", err) + } + } + } + l, nTmp, err = d.DecodeUint() + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding LedgerKey: %w", err) + } + s.ReadWrite = nil + if l > 0 { + if il, ok := d.InputLen(); ok && uint(il) < uint(l) { + return n, fmt.Errorf("decoding LedgerKey: length (%d) exceeds remaining input length (%d)", l, il) + } + s.ReadWrite = make([]LedgerKey, l) + for i := uint32(0); i < l; i++ { + nTmp, err = s.ReadWrite[i].DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding LedgerKey: %w", err) + } + } + } + return n, nil +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (s LedgerFootprint) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *LedgerFootprint) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} + +var ( + _ encoding.BinaryMarshaler = (*LedgerFootprint)(nil) + _ encoding.BinaryUnmarshaler = (*LedgerFootprint)(nil) +) + +// xdrType signals that this type represents XDR values defined by this package. +func (s LedgerFootprint) xdrType() {} + +var _ xdrType = (*LedgerFootprint)(nil) + +// SorobanResources is an XDR Struct defines as: +// +// struct SorobanResources +// { +// // The ledger footprint of the transaction. +// LedgerFootprint footprint; +// // The maximum number of instructions this transaction can use +// uint32 instructions; +// +// // The maximum number of bytes this transaction can read from ledger +// uint32 readBytes; +// // The maximum number of bytes this transaction can write to ledger +// uint32 writeBytes; +// }; +type SorobanResources struct { + Footprint LedgerFootprint + Instructions Uint32 + ReadBytes Uint32 + WriteBytes Uint32 +} + +// EncodeTo encodes this value using the Encoder. +func (s *SorobanResources) EncodeTo(e *xdr.Encoder) error { + var err error + if err = s.Footprint.EncodeTo(e); err != nil { + return err + } + if err = s.Instructions.EncodeTo(e); err != nil { + return err + } + if err = s.ReadBytes.EncodeTo(e); err != nil { + return err + } + if err = s.WriteBytes.EncodeTo(e); err != nil { + return err + } + return nil +} + +var _ decoderFrom = (*SorobanResources)(nil) + +// DecodeFrom decodes this value using the Decoder. +func (s *SorobanResources) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding SorobanResources: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + var err error + var n, nTmp int + nTmp, err = s.Footprint.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding LedgerFootprint: %w", err) + } + nTmp, err = s.Instructions.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Uint32: %w", err) + } + nTmp, err = s.ReadBytes.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Uint32: %w", err) + } + nTmp, err = s.WriteBytes.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Uint32: %w", err) + } + return n, nil +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (s SorobanResources) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *SorobanResources) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} + +var ( + _ encoding.BinaryMarshaler = (*SorobanResources)(nil) + _ encoding.BinaryUnmarshaler = (*SorobanResources)(nil) +) + +// xdrType signals that this type represents XDR values defined by this package. +func (s SorobanResources) xdrType() {} + +var _ xdrType = (*SorobanResources)(nil) + +// SorobanTransactionData is an XDR Struct defines as: +// +// struct SorobanTransactionData +// { +// ExtensionPoint ext; +// SorobanResources resources; +// // Amount of the transaction `fee` allocated to the Soroban resource fees. +// // The fraction of `resourceFee` corresponding to `resources` specified +// // above is *not* refundable (i.e. fees for instructions, ledger I/O), as +// // well as fees for the transaction size. +// // The remaining part of the fee is refundable and the charged value is +// // based on the actual consumption of refundable resources (events, ledger +// // rent bumps). +// // The `inclusionFee` used for prioritization of the transaction is defined +// // as `tx.fee - resourceFee`. +// int64 resourceFee; +// }; +type SorobanTransactionData struct { + Ext ExtensionPoint + Resources SorobanResources + ResourceFee Int64 +} + +// EncodeTo encodes this value using the Encoder. +func (s *SorobanTransactionData) EncodeTo(e *xdr.Encoder) error { + var err error + if err = s.Ext.EncodeTo(e); err != nil { + return err + } + if err = s.Resources.EncodeTo(e); err != nil { + return err + } + if err = s.ResourceFee.EncodeTo(e); err != nil { + return err + } + return nil +} + +var _ decoderFrom = (*SorobanTransactionData)(nil) + +// DecodeFrom decodes this value using the Decoder. +func (s *SorobanTransactionData) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding SorobanTransactionData: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + var err error + var n, nTmp int + nTmp, err = s.Ext.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ExtensionPoint: %w", err) + } + nTmp, err = s.Resources.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding SorobanResources: %w", err) + } + nTmp, err = s.ResourceFee.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Int64: %w", err) + } + return n, nil +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (s SorobanTransactionData) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *SorobanTransactionData) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} + +var ( + _ encoding.BinaryMarshaler = (*SorobanTransactionData)(nil) + _ encoding.BinaryUnmarshaler = (*SorobanTransactionData)(nil) +) + +// xdrType signals that this type represents XDR values defined by this package. +func (s SorobanTransactionData) xdrType() {} + +var _ xdrType = (*SorobanTransactionData)(nil) + +// TransactionV0Ext is an XDR NestedUnion defines as: +// +// union switch (int v) +// { +// case 0: +// void; +// } +type TransactionV0Ext struct { + V int32 +} + +// SwitchFieldName returns the field name in which this union's +// discriminant is stored +func (u TransactionV0Ext) SwitchFieldName() string { + return "V" +} + +// ArmForSwitch returns which field name should be used for storing +// the value for an instance of TransactionV0Ext +func (u TransactionV0Ext) ArmForSwitch(sw int32) (string, bool) { + switch int32(sw) { + case 0: + return "", true + } + return "-", false +} + +// NewTransactionV0Ext creates a new TransactionV0Ext. +func NewTransactionV0Ext(v int32, value interface{}) (result TransactionV0Ext, err error) { + result.V = v + switch int32(v) { + case 0: + // void + } + return +} + +// EncodeTo encodes this value using the Encoder. +func (u TransactionV0Ext) EncodeTo(e *xdr.Encoder) error { + var err error + if _, err = e.EncodeInt(int32(u.V)); err != nil { + return err + } + switch int32(u.V) { + case 0: + // Void + return nil + } + return fmt.Errorf("V (int32) switch value '%d' is not valid for union TransactionV0Ext", u.V) +} + +var _ decoderFrom = (*TransactionV0Ext)(nil) + +// DecodeFrom decodes this value using the Decoder. +func (u *TransactionV0Ext) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding TransactionV0Ext: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + var err error + var n, nTmp int + u.V, nTmp, err = d.DecodeInt() + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Int: %w", err) + } + switch int32(u.V) { + case 0: + // Void + return n, nil + } + return n, fmt.Errorf("union TransactionV0Ext has invalid V (int32) switch value '%d'", u.V) +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (s TransactionV0Ext) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *TransactionV0Ext) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} + +var ( + _ encoding.BinaryMarshaler = (*TransactionV0Ext)(nil) + _ encoding.BinaryUnmarshaler = (*TransactionV0Ext)(nil) +) + +// xdrType signals that this type represents XDR values defined by this package. +func (s TransactionV0Ext) xdrType() {} + +var _ xdrType = (*TransactionV0Ext)(nil) + +// TransactionV0 is an XDR Struct defines as: +// +// struct TransactionV0 +// { +// uint256 sourceAccountEd25519; +// uint32 fee; +// SequenceNumber seqNum; +// TimeBounds* timeBounds; +// Memo memo; +// Operation operations; +// union switch (int v) +// { +// case 0: +// void; +// } +// ext; +// }; +type TransactionV0 struct { + SourceAccountEd25519 Uint256 + Fee Uint32 + SeqNum SequenceNumber + TimeBounds *TimeBounds + Memo Memo + Operations []Operation `xdrmaxsize:"100"` + Ext TransactionV0Ext +} + +// EncodeTo encodes this value using the Encoder. +func (s *TransactionV0) EncodeTo(e *xdr.Encoder) error { + var err error + if err = s.SourceAccountEd25519.EncodeTo(e); err != nil { + return err + } + if err = s.Fee.EncodeTo(e); err != nil { + return err + } + if err = s.SeqNum.EncodeTo(e); err != nil { + return err + } + if _, err = e.EncodeBool(s.TimeBounds != nil); err != nil { + return err + } + if s.TimeBounds != nil { + if err = (*s.TimeBounds).EncodeTo(e); err != nil { + return err + } + } + if err = s.Memo.EncodeTo(e); err != nil { + return err + } + if _, err = e.EncodeUint(uint32(len(s.Operations))); err != nil { + return err + } + for i := 0; i < len(s.Operations); i++ { + if err = s.Operations[i].EncodeTo(e); err != nil { + return err + } + } + if err = s.Ext.EncodeTo(e); err != nil { + return err + } + return nil +} + +var _ decoderFrom = (*TransactionV0)(nil) + +// DecodeFrom decodes this value using the Decoder. +func (s *TransactionV0) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding TransactionV0: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + var err error + var n, nTmp int + nTmp, err = s.SourceAccountEd25519.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Uint256: %w", err) + } + nTmp, err = s.Fee.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Uint32: %w", err) + } + nTmp, err = s.SeqNum.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding SequenceNumber: %w", err) + } + var b bool + b, nTmp, err = d.DecodeBool() + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding TimeBounds: %w", err) + } + s.TimeBounds = nil + if b { + s.TimeBounds = new(TimeBounds) + nTmp, err = s.TimeBounds.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding TimeBounds: %w", err) + } + } + nTmp, err = s.Memo.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Memo: %w", err) + } + var l uint32 + l, nTmp, err = d.DecodeUint() + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Operation: %w", err) + } + if l > 100 { + return n, fmt.Errorf("decoding Operation: data size (%d) exceeds size limit (100)", l) + } + s.Operations = nil + if l > 0 { + if il, ok := d.InputLen(); ok && uint(il) < uint(l) { + return n, fmt.Errorf("decoding Operation: length (%d) exceeds remaining input length (%d)", l, il) + } + s.Operations = make([]Operation, l) + for i := uint32(0); i < l; i++ { + nTmp, err = s.Operations[i].DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Operation: %w", err) + } + } + } + nTmp, err = s.Ext.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding TransactionV0Ext: %w", err) + } + return n, nil +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (s TransactionV0) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *TransactionV0) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} + +var ( + _ encoding.BinaryMarshaler = (*TransactionV0)(nil) + _ encoding.BinaryUnmarshaler = (*TransactionV0)(nil) +) + +// xdrType signals that this type represents XDR values defined by this package. +func (s TransactionV0) xdrType() {} + +var _ xdrType = (*TransactionV0)(nil) + +// TransactionV0Envelope is an XDR Struct defines as: +// +// struct TransactionV0Envelope +// { +// TransactionV0 tx; +// /* Each decorated signature is a signature over the SHA256 hash of +// * a TransactionSignaturePayload */ +// DecoratedSignature signatures<20>; +// }; +type TransactionV0Envelope struct { + Tx TransactionV0 + Signatures []DecoratedSignature `xdrmaxsize:"20"` +} + +// EncodeTo encodes this value using the Encoder. +func (s *TransactionV0Envelope) EncodeTo(e *xdr.Encoder) error { + var err error + if err = s.Tx.EncodeTo(e); err != nil { + return err + } + if _, err = e.EncodeUint(uint32(len(s.Signatures))); err != nil { + return err + } + for i := 0; i < len(s.Signatures); i++ { + if err = s.Signatures[i].EncodeTo(e); err != nil { + return err + } + } + return nil +} + +var _ decoderFrom = (*TransactionV0Envelope)(nil) + +// DecodeFrom decodes this value using the Decoder. +func (s *TransactionV0Envelope) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding TransactionV0Envelope: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + var err error + var n, nTmp int + nTmp, err = s.Tx.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding TransactionV0: %w", err) + } + var l uint32 + l, nTmp, err = d.DecodeUint() + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding DecoratedSignature: %w", err) + } + if l > 20 { + return n, fmt.Errorf("decoding DecoratedSignature: data size (%d) exceeds size limit (20)", l) + } + s.Signatures = nil + if l > 0 { + if il, ok := d.InputLen(); ok && uint(il) < uint(l) { + return n, fmt.Errorf("decoding DecoratedSignature: length (%d) exceeds remaining input length (%d)", l, il) + } + s.Signatures = make([]DecoratedSignature, l) + for i := uint32(0); i < l; i++ { + nTmp, err = s.Signatures[i].DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding DecoratedSignature: %w", err) + } + } + } + return n, nil +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (s TransactionV0Envelope) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *TransactionV0Envelope) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} + +var ( + _ encoding.BinaryMarshaler = (*TransactionV0Envelope)(nil) + _ encoding.BinaryUnmarshaler = (*TransactionV0Envelope)(nil) +) + +// xdrType signals that this type represents XDR values defined by this package. +func (s TransactionV0Envelope) xdrType() {} + +var _ xdrType = (*TransactionV0Envelope)(nil) + +// TransactionExt is an XDR NestedUnion defines as: +// +// union switch (int v) +// { +// case 0: +// void; +// case 1: +// SorobanTransactionData sorobanData; +// } +type TransactionExt struct { + V int32 + SorobanData *SorobanTransactionData +} + +// SwitchFieldName returns the field name in which this union's +// discriminant is stored +func (u TransactionExt) SwitchFieldName() string { + return "V" +} + +// ArmForSwitch returns which field name should be used for storing +// the value for an instance of TransactionExt +func (u TransactionExt) ArmForSwitch(sw int32) (string, bool) { + switch int32(sw) { + case 0: + return "", true + case 1: + return "SorobanData", true + } + return "-", false +} + +// NewTransactionExt creates a new TransactionExt. +func NewTransactionExt(v int32, value interface{}) (result TransactionExt, err error) { + result.V = v + switch int32(v) { + case 0: + // void + case 1: + tv, ok := value.(SorobanTransactionData) + if !ok { + err = errors.New("invalid value, must be SorobanTransactionData") + return + } + result.SorobanData = &tv + } + return +} + +// MustSorobanData retrieves the SorobanData value from the union, +// panicing if the value is not set. +func (u TransactionExt) MustSorobanData() SorobanTransactionData { + val, ok := u.GetSorobanData() + + if !ok { + panic("arm SorobanData is not set") + } + + return val +} + +// GetSorobanData retrieves the SorobanData value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u TransactionExt) GetSorobanData() (result SorobanTransactionData, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.V)) + + if armName == "SorobanData" { + result = *u.SorobanData + ok = true + } + + return +} + +// EncodeTo encodes this value using the Encoder. +func (u TransactionExt) EncodeTo(e *xdr.Encoder) error { + var err error + if _, err = e.EncodeInt(int32(u.V)); err != nil { + return err + } + switch int32(u.V) { + case 0: + // Void + return nil + case 1: + if err = (*u.SorobanData).EncodeTo(e); err != nil { + return err + } + return nil + } + return fmt.Errorf("V (int32) switch value '%d' is not valid for union TransactionExt", u.V) +} + +var _ decoderFrom = (*TransactionExt)(nil) + +// DecodeFrom decodes this value using the Decoder. +func (u *TransactionExt) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding TransactionExt: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + var err error + var n, nTmp int + u.V, nTmp, err = d.DecodeInt() + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Int: %w", err) + } + switch int32(u.V) { + case 0: + // Void + return n, nil + case 1: + u.SorobanData = new(SorobanTransactionData) + nTmp, err = (*u.SorobanData).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding SorobanTransactionData: %w", err) + } + return n, nil + } + return n, fmt.Errorf("union TransactionExt has invalid V (int32) switch value '%d'", u.V) +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (s TransactionExt) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *TransactionExt) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} + +var ( + _ encoding.BinaryMarshaler = (*TransactionExt)(nil) + _ encoding.BinaryUnmarshaler = (*TransactionExt)(nil) +) + +// xdrType signals that this type represents XDR values defined by this package. +func (s TransactionExt) xdrType() {} + +var _ xdrType = (*TransactionExt)(nil) + +// Transaction is an XDR Struct defines as: +// +// struct Transaction +// { +// // account used to run the transaction +// MuxedAccount sourceAccount; +// +// // the fee the sourceAccount will pay +// uint32 fee; +// +// // sequence number to consume in the account +// SequenceNumber seqNum; +// +// // validity conditions +// Preconditions cond; +// +// Memo memo; +// +// Operation operations; +// +// // reserved for future use +// union switch (int v) +// { +// case 0: +// void; +// case 1: +// SorobanTransactionData sorobanData; +// } +// ext; +// }; +type Transaction struct { + SourceAccount MuxedAccount + Fee Uint32 + SeqNum SequenceNumber + Cond Preconditions + Memo Memo + Operations []Operation `xdrmaxsize:"100"` + Ext TransactionExt +} + +// EncodeTo encodes this value using the Encoder. +func (s *Transaction) EncodeTo(e *xdr.Encoder) error { + var err error + if err = s.SourceAccount.EncodeTo(e); err != nil { + return err + } + if err = s.Fee.EncodeTo(e); err != nil { + return err + } + if err = s.SeqNum.EncodeTo(e); err != nil { + return err + } + if err = s.Cond.EncodeTo(e); err != nil { + return err + } + if err = s.Memo.EncodeTo(e); err != nil { + return err + } + if _, err = e.EncodeUint(uint32(len(s.Operations))); err != nil { + return err + } + for i := 0; i < len(s.Operations); i++ { + if err = s.Operations[i].EncodeTo(e); err != nil { + return err + } + } + if err = s.Ext.EncodeTo(e); err != nil { + return err + } + return nil +} + +var _ decoderFrom = (*Transaction)(nil) + +// DecodeFrom decodes this value using the Decoder. +func (s *Transaction) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding Transaction: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + var err error + var n, nTmp int + nTmp, err = s.SourceAccount.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding MuxedAccount: %w", err) + } + nTmp, err = s.Fee.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Uint32: %w", err) + } + nTmp, err = s.SeqNum.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding SequenceNumber: %w", err) + } + nTmp, err = s.Cond.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Preconditions: %w", err) + } + nTmp, err = s.Memo.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Memo: %w", err) + } + var l uint32 + l, nTmp, err = d.DecodeUint() + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Operation: %w", err) + } + if l > 100 { + return n, fmt.Errorf("decoding Operation: data size (%d) exceeds size limit (100)", l) + } + s.Operations = nil + if l > 0 { + if il, ok := d.InputLen(); ok && uint(il) < uint(l) { + return n, fmt.Errorf("decoding Operation: length (%d) exceeds remaining input length (%d)", l, il) + } + s.Operations = make([]Operation, l) + for i := uint32(0); i < l; i++ { + nTmp, err = s.Operations[i].DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Operation: %w", err) + } + } + } + nTmp, err = s.Ext.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding TransactionExt: %w", err) + } + return n, nil +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (s Transaction) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *Transaction) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} + +var ( + _ encoding.BinaryMarshaler = (*Transaction)(nil) + _ encoding.BinaryUnmarshaler = (*Transaction)(nil) +) + +// xdrType signals that this type represents XDR values defined by this package. +func (s Transaction) xdrType() {} + +var _ xdrType = (*Transaction)(nil) + +// TransactionV1Envelope is an XDR Struct defines as: +// +// struct TransactionV1Envelope +// { +// Transaction tx; +// /* Each decorated signature is a signature over the SHA256 hash of +// * a TransactionSignaturePayload */ +// DecoratedSignature signatures<20>; +// }; +type TransactionV1Envelope struct { + Tx Transaction + Signatures []DecoratedSignature `xdrmaxsize:"20"` +} + +// EncodeTo encodes this value using the Encoder. +func (s *TransactionV1Envelope) EncodeTo(e *xdr.Encoder) error { + var err error + if err = s.Tx.EncodeTo(e); err != nil { + return err + } + if _, err = e.EncodeUint(uint32(len(s.Signatures))); err != nil { + return err + } + for i := 0; i < len(s.Signatures); i++ { + if err = s.Signatures[i].EncodeTo(e); err != nil { + return err + } + } + return nil +} + +var _ decoderFrom = (*TransactionV1Envelope)(nil) + +// DecodeFrom decodes this value using the Decoder. +func (s *TransactionV1Envelope) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding TransactionV1Envelope: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + var err error + var n, nTmp int + nTmp, err = s.Tx.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Transaction: %w", err) + } + var l uint32 + l, nTmp, err = d.DecodeUint() + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding DecoratedSignature: %w", err) + } + if l > 20 { + return n, fmt.Errorf("decoding DecoratedSignature: data size (%d) exceeds size limit (20)", l) + } + s.Signatures = nil + if l > 0 { + if il, ok := d.InputLen(); ok && uint(il) < uint(l) { + return n, fmt.Errorf("decoding DecoratedSignature: length (%d) exceeds remaining input length (%d)", l, il) + } + s.Signatures = make([]DecoratedSignature, l) + for i := uint32(0); i < l; i++ { + nTmp, err = s.Signatures[i].DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding DecoratedSignature: %w", err) + } + } + } + return n, nil +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (s TransactionV1Envelope) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *TransactionV1Envelope) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} + +var ( + _ encoding.BinaryMarshaler = (*TransactionV1Envelope)(nil) + _ encoding.BinaryUnmarshaler = (*TransactionV1Envelope)(nil) +) + +// xdrType signals that this type represents XDR values defined by this package. +func (s TransactionV1Envelope) xdrType() {} + +var _ xdrType = (*TransactionV1Envelope)(nil) + +// FeeBumpTransactionInnerTx is an XDR NestedUnion defines as: +// +// union switch (EnvelopeType type) +// { +// case ENVELOPE_TYPE_TX: +// TransactionV1Envelope v1; +// } +type FeeBumpTransactionInnerTx struct { + Type EnvelopeType + V1 *TransactionV1Envelope +} + +// SwitchFieldName returns the field name in which this union's +// discriminant is stored +func (u FeeBumpTransactionInnerTx) SwitchFieldName() string { + return "Type" +} + +// ArmForSwitch returns which field name should be used for storing +// the value for an instance of FeeBumpTransactionInnerTx +func (u FeeBumpTransactionInnerTx) ArmForSwitch(sw int32) (string, bool) { + switch EnvelopeType(sw) { + case EnvelopeTypeEnvelopeTypeTx: + return "V1", true + } + return "-", false +} + +// NewFeeBumpTransactionInnerTx creates a new FeeBumpTransactionInnerTx. +func NewFeeBumpTransactionInnerTx(aType EnvelopeType, value interface{}) (result FeeBumpTransactionInnerTx, err error) { + result.Type = aType + switch EnvelopeType(aType) { + case EnvelopeTypeEnvelopeTypeTx: + tv, ok := value.(TransactionV1Envelope) + if !ok { + err = errors.New("invalid value, must be TransactionV1Envelope") + return + } + result.V1 = &tv + } + return +} + +// MustV1 retrieves the V1 value from the union, +// panicing if the value is not set. +func (u FeeBumpTransactionInnerTx) MustV1() TransactionV1Envelope { + val, ok := u.GetV1() + + if !ok { + panic("arm V1 is not set") + } + + return val +} + +// GetV1 retrieves the V1 value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u FeeBumpTransactionInnerTx) GetV1() (result TransactionV1Envelope, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) + + if armName == "V1" { + result = *u.V1 + ok = true + } + + return +} + +// EncodeTo encodes this value using the Encoder. +func (u FeeBumpTransactionInnerTx) EncodeTo(e *xdr.Encoder) error { + var err error + if err = u.Type.EncodeTo(e); err != nil { + return err + } + switch EnvelopeType(u.Type) { + case EnvelopeTypeEnvelopeTypeTx: + if err = (*u.V1).EncodeTo(e); err != nil { + return err + } + return nil + } + return fmt.Errorf("Type (EnvelopeType) switch value '%d' is not valid for union FeeBumpTransactionInnerTx", u.Type) +} + +var _ decoderFrom = (*FeeBumpTransactionInnerTx)(nil) + +// DecodeFrom decodes this value using the Decoder. +func (u *FeeBumpTransactionInnerTx) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding FeeBumpTransactionInnerTx: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + var err error + var n, nTmp int + nTmp, err = u.Type.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding EnvelopeType: %w", err) + } + switch EnvelopeType(u.Type) { + case EnvelopeTypeEnvelopeTypeTx: + u.V1 = new(TransactionV1Envelope) + nTmp, err = (*u.V1).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding TransactionV1Envelope: %w", err) + } + return n, nil + } + return n, fmt.Errorf("union FeeBumpTransactionInnerTx has invalid Type (EnvelopeType) switch value '%d'", u.Type) +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (s FeeBumpTransactionInnerTx) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *FeeBumpTransactionInnerTx) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} + +var ( + _ encoding.BinaryMarshaler = (*FeeBumpTransactionInnerTx)(nil) + _ encoding.BinaryUnmarshaler = (*FeeBumpTransactionInnerTx)(nil) +) + +// xdrType signals that this type represents XDR values defined by this package. +func (s FeeBumpTransactionInnerTx) xdrType() {} + +var _ xdrType = (*FeeBumpTransactionInnerTx)(nil) + +// FeeBumpTransactionExt is an XDR NestedUnion defines as: +// +// union switch (int v) +// { +// case 0: +// void; +// } +type FeeBumpTransactionExt struct { + V int32 +} + +// SwitchFieldName returns the field name in which this union's +// discriminant is stored +func (u FeeBumpTransactionExt) SwitchFieldName() string { + return "V" +} + +// ArmForSwitch returns which field name should be used for storing +// the value for an instance of FeeBumpTransactionExt +func (u FeeBumpTransactionExt) ArmForSwitch(sw int32) (string, bool) { + switch int32(sw) { + case 0: + return "", true + } + return "-", false +} + +// NewFeeBumpTransactionExt creates a new FeeBumpTransactionExt. +func NewFeeBumpTransactionExt(v int32, value interface{}) (result FeeBumpTransactionExt, err error) { + result.V = v + switch int32(v) { + case 0: + // void + } + return +} + +// EncodeTo encodes this value using the Encoder. +func (u FeeBumpTransactionExt) EncodeTo(e *xdr.Encoder) error { + var err error + if _, err = e.EncodeInt(int32(u.V)); err != nil { + return err + } + switch int32(u.V) { + case 0: + // Void + return nil + } + return fmt.Errorf("V (int32) switch value '%d' is not valid for union FeeBumpTransactionExt", u.V) +} + +var _ decoderFrom = (*FeeBumpTransactionExt)(nil) + +// DecodeFrom decodes this value using the Decoder. +func (u *FeeBumpTransactionExt) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding FeeBumpTransactionExt: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + var err error + var n, nTmp int + u.V, nTmp, err = d.DecodeInt() + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Int: %w", err) + } + switch int32(u.V) { + case 0: + // Void + return n, nil + } + return n, fmt.Errorf("union FeeBumpTransactionExt has invalid V (int32) switch value '%d'", u.V) +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (s FeeBumpTransactionExt) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *FeeBumpTransactionExt) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} + +var ( + _ encoding.BinaryMarshaler = (*FeeBumpTransactionExt)(nil) + _ encoding.BinaryUnmarshaler = (*FeeBumpTransactionExt)(nil) +) + +// xdrType signals that this type represents XDR values defined by this package. +func (s FeeBumpTransactionExt) xdrType() {} + +var _ xdrType = (*FeeBumpTransactionExt)(nil) + +// FeeBumpTransaction is an XDR Struct defines as: +// +// struct FeeBumpTransaction +// { +// MuxedAccount feeSource; +// int64 fee; +// union switch (EnvelopeType type) +// { +// case ENVELOPE_TYPE_TX: +// TransactionV1Envelope v1; +// } +// innerTx; +// union switch (int v) +// { +// case 0: +// void; +// } +// ext; +// }; +type FeeBumpTransaction struct { + FeeSource MuxedAccount + Fee Int64 + InnerTx FeeBumpTransactionInnerTx + Ext FeeBumpTransactionExt +} + +// EncodeTo encodes this value using the Encoder. +func (s *FeeBumpTransaction) EncodeTo(e *xdr.Encoder) error { + var err error + if err = s.FeeSource.EncodeTo(e); err != nil { + return err + } + if err = s.Fee.EncodeTo(e); err != nil { + return err + } + if err = s.InnerTx.EncodeTo(e); err != nil { + return err + } + if err = s.Ext.EncodeTo(e); err != nil { + return err + } + return nil +} + +var _ decoderFrom = (*FeeBumpTransaction)(nil) + +// DecodeFrom decodes this value using the Decoder. +func (s *FeeBumpTransaction) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding FeeBumpTransaction: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + var err error + var n, nTmp int + nTmp, err = s.FeeSource.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding MuxedAccount: %w", err) + } + nTmp, err = s.Fee.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Int64: %w", err) + } + nTmp, err = s.InnerTx.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding FeeBumpTransactionInnerTx: %w", err) + } + nTmp, err = s.Ext.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding FeeBumpTransactionExt: %w", err) + } + return n, nil +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (s FeeBumpTransaction) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *FeeBumpTransaction) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} + +var ( + _ encoding.BinaryMarshaler = (*FeeBumpTransaction)(nil) + _ encoding.BinaryUnmarshaler = (*FeeBumpTransaction)(nil) +) + +// xdrType signals that this type represents XDR values defined by this package. +func (s FeeBumpTransaction) xdrType() {} + +var _ xdrType = (*FeeBumpTransaction)(nil) + +// FeeBumpTransactionEnvelope is an XDR Struct defines as: +// +// struct FeeBumpTransactionEnvelope +// { +// FeeBumpTransaction tx; +// /* Each decorated signature is a signature over the SHA256 hash of +// * a TransactionSignaturePayload */ +// DecoratedSignature signatures<20>; +// }; +type FeeBumpTransactionEnvelope struct { + Tx FeeBumpTransaction + Signatures []DecoratedSignature `xdrmaxsize:"20"` +} + +// EncodeTo encodes this value using the Encoder. +func (s *FeeBumpTransactionEnvelope) EncodeTo(e *xdr.Encoder) error { + var err error + if err = s.Tx.EncodeTo(e); err != nil { + return err + } + if _, err = e.EncodeUint(uint32(len(s.Signatures))); err != nil { + return err + } + for i := 0; i < len(s.Signatures); i++ { + if err = s.Signatures[i].EncodeTo(e); err != nil { + return err + } + } + return nil +} + +var _ decoderFrom = (*FeeBumpTransactionEnvelope)(nil) + +// DecodeFrom decodes this value using the Decoder. +func (s *FeeBumpTransactionEnvelope) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding FeeBumpTransactionEnvelope: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + var err error + var n, nTmp int + nTmp, err = s.Tx.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding FeeBumpTransaction: %w", err) + } + var l uint32 + l, nTmp, err = d.DecodeUint() + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding DecoratedSignature: %w", err) + } + if l > 20 { + return n, fmt.Errorf("decoding DecoratedSignature: data size (%d) exceeds size limit (20)", l) + } + s.Signatures = nil + if l > 0 { + if il, ok := d.InputLen(); ok && uint(il) < uint(l) { + return n, fmt.Errorf("decoding DecoratedSignature: length (%d) exceeds remaining input length (%d)", l, il) + } + s.Signatures = make([]DecoratedSignature, l) + for i := uint32(0); i < l; i++ { + nTmp, err = s.Signatures[i].DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding DecoratedSignature: %w", err) + } + } + } + return n, nil +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (s FeeBumpTransactionEnvelope) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *FeeBumpTransactionEnvelope) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} + +var ( + _ encoding.BinaryMarshaler = (*FeeBumpTransactionEnvelope)(nil) + _ encoding.BinaryUnmarshaler = (*FeeBumpTransactionEnvelope)(nil) +) + +// xdrType signals that this type represents XDR values defined by this package. +func (s FeeBumpTransactionEnvelope) xdrType() {} + +var _ xdrType = (*FeeBumpTransactionEnvelope)(nil) + +// TransactionEnvelope is an XDR Union defines as: +// +// union TransactionEnvelope switch (EnvelopeType type) +// { +// case ENVELOPE_TYPE_TX_V0: +// TransactionV0Envelope v0; +// case ENVELOPE_TYPE_TX: +// TransactionV1Envelope v1; +// case ENVELOPE_TYPE_TX_FEE_BUMP: +// FeeBumpTransactionEnvelope feeBump; +// }; +type TransactionEnvelope struct { + Type EnvelopeType + V0 *TransactionV0Envelope + V1 *TransactionV1Envelope + FeeBump *FeeBumpTransactionEnvelope +} + +// SwitchFieldName returns the field name in which this union's +// discriminant is stored +func (u TransactionEnvelope) SwitchFieldName() string { + return "Type" +} + +// ArmForSwitch returns which field name should be used for storing +// the value for an instance of TransactionEnvelope +func (u TransactionEnvelope) ArmForSwitch(sw int32) (string, bool) { + switch EnvelopeType(sw) { + case EnvelopeTypeEnvelopeTypeTxV0: + return "V0", true + case EnvelopeTypeEnvelopeTypeTx: + return "V1", true + case EnvelopeTypeEnvelopeTypeTxFeeBump: + return "FeeBump", true + } + return "-", false +} + +// NewTransactionEnvelope creates a new TransactionEnvelope. +func NewTransactionEnvelope(aType EnvelopeType, value interface{}) (result TransactionEnvelope, err error) { + result.Type = aType + switch EnvelopeType(aType) { + case EnvelopeTypeEnvelopeTypeTxV0: + tv, ok := value.(TransactionV0Envelope) + if !ok { + err = errors.New("invalid value, must be TransactionV0Envelope") + return + } + result.V0 = &tv + case EnvelopeTypeEnvelopeTypeTx: + tv, ok := value.(TransactionV1Envelope) + if !ok { + err = errors.New("invalid value, must be TransactionV1Envelope") + return + } + result.V1 = &tv + case EnvelopeTypeEnvelopeTypeTxFeeBump: + tv, ok := value.(FeeBumpTransactionEnvelope) + if !ok { + err = errors.New("invalid value, must be FeeBumpTransactionEnvelope") + return + } + result.FeeBump = &tv + } + return +} + +// MustV0 retrieves the V0 value from the union, +// panicing if the value is not set. +func (u TransactionEnvelope) MustV0() TransactionV0Envelope { + val, ok := u.GetV0() + + if !ok { + panic("arm V0 is not set") + } + + return val +} + +// GetV0 retrieves the V0 value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u TransactionEnvelope) GetV0() (result TransactionV0Envelope, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) + + if armName == "V0" { + result = *u.V0 + ok = true + } + + return +} + +// MustV1 retrieves the V1 value from the union, +// panicing if the value is not set. +func (u TransactionEnvelope) MustV1() TransactionV1Envelope { + val, ok := u.GetV1() + + if !ok { + panic("arm V1 is not set") + } + + return val +} + +// GetV1 retrieves the V1 value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u TransactionEnvelope) GetV1() (result TransactionV1Envelope, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) + + if armName == "V1" { + result = *u.V1 + ok = true + } + + return +} + +// MustFeeBump retrieves the FeeBump value from the union, +// panicing if the value is not set. +func (u TransactionEnvelope) MustFeeBump() FeeBumpTransactionEnvelope { + val, ok := u.GetFeeBump() + + if !ok { + panic("arm FeeBump is not set") + } + + return val +} + +// GetFeeBump retrieves the FeeBump value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u TransactionEnvelope) GetFeeBump() (result FeeBumpTransactionEnvelope, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) + + if armName == "FeeBump" { + result = *u.FeeBump + ok = true + } + + return +} + +// EncodeTo encodes this value using the Encoder. +func (u TransactionEnvelope) EncodeTo(e *xdr.Encoder) error { + var err error + if err = u.Type.EncodeTo(e); err != nil { + return err + } + switch EnvelopeType(u.Type) { + case EnvelopeTypeEnvelopeTypeTxV0: + if err = (*u.V0).EncodeTo(e); err != nil { + return err + } + return nil + case EnvelopeTypeEnvelopeTypeTx: + if err = (*u.V1).EncodeTo(e); err != nil { + return err + } + return nil + case EnvelopeTypeEnvelopeTypeTxFeeBump: + if err = (*u.FeeBump).EncodeTo(e); err != nil { + return err + } + return nil + } + return fmt.Errorf("Type (EnvelopeType) switch value '%d' is not valid for union TransactionEnvelope", u.Type) +} + +var _ decoderFrom = (*TransactionEnvelope)(nil) + +// DecodeFrom decodes this value using the Decoder. +func (u *TransactionEnvelope) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding TransactionEnvelope: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + var err error + var n, nTmp int + nTmp, err = u.Type.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding EnvelopeType: %w", err) + } + switch EnvelopeType(u.Type) { + case EnvelopeTypeEnvelopeTypeTxV0: + u.V0 = new(TransactionV0Envelope) + nTmp, err = (*u.V0).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding TransactionV0Envelope: %w", err) + } + return n, nil + case EnvelopeTypeEnvelopeTypeTx: + u.V1 = new(TransactionV1Envelope) + nTmp, err = (*u.V1).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding TransactionV1Envelope: %w", err) + } + return n, nil + case EnvelopeTypeEnvelopeTypeTxFeeBump: + u.FeeBump = new(FeeBumpTransactionEnvelope) + nTmp, err = (*u.FeeBump).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding FeeBumpTransactionEnvelope: %w", err) + } + return n, nil + } + return n, fmt.Errorf("union TransactionEnvelope has invalid Type (EnvelopeType) switch value '%d'", u.Type) +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (s TransactionEnvelope) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *TransactionEnvelope) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} + +var ( + _ encoding.BinaryMarshaler = (*TransactionEnvelope)(nil) + _ encoding.BinaryUnmarshaler = (*TransactionEnvelope)(nil) +) + +// xdrType signals that this type represents XDR values defined by this package. +func (s TransactionEnvelope) xdrType() {} + +var _ xdrType = (*TransactionEnvelope)(nil) + +// TransactionSignaturePayloadTaggedTransaction is an XDR NestedUnion defines as: +// +// union switch (EnvelopeType type) +// { +// // Backwards Compatibility: Use ENVELOPE_TYPE_TX to sign ENVELOPE_TYPE_TX_V0 +// case ENVELOPE_TYPE_TX: +// Transaction tx; +// case ENVELOPE_TYPE_TX_FEE_BUMP: +// FeeBumpTransaction feeBump; +// } +type TransactionSignaturePayloadTaggedTransaction struct { + Type EnvelopeType + Tx *Transaction + FeeBump *FeeBumpTransaction +} + +// SwitchFieldName returns the field name in which this union's +// discriminant is stored +func (u TransactionSignaturePayloadTaggedTransaction) SwitchFieldName() string { + return "Type" +} + +// ArmForSwitch returns which field name should be used for storing +// the value for an instance of TransactionSignaturePayloadTaggedTransaction +func (u TransactionSignaturePayloadTaggedTransaction) ArmForSwitch(sw int32) (string, bool) { + switch EnvelopeType(sw) { + case EnvelopeTypeEnvelopeTypeTx: + return "Tx", true + case EnvelopeTypeEnvelopeTypeTxFeeBump: + return "FeeBump", true + } + return "-", false +} + +// NewTransactionSignaturePayloadTaggedTransaction creates a new TransactionSignaturePayloadTaggedTransaction. +func NewTransactionSignaturePayloadTaggedTransaction(aType EnvelopeType, value interface{}) (result TransactionSignaturePayloadTaggedTransaction, err error) { + result.Type = aType + switch EnvelopeType(aType) { + case EnvelopeTypeEnvelopeTypeTx: + tv, ok := value.(Transaction) + if !ok { + err = errors.New("invalid value, must be Transaction") + return + } + result.Tx = &tv + case EnvelopeTypeEnvelopeTypeTxFeeBump: + tv, ok := value.(FeeBumpTransaction) + if !ok { + err = errors.New("invalid value, must be FeeBumpTransaction") + return + } + result.FeeBump = &tv + } + return +} + +// MustTx retrieves the Tx value from the union, +// panicing if the value is not set. +func (u TransactionSignaturePayloadTaggedTransaction) MustTx() Transaction { + val, ok := u.GetTx() + + if !ok { + panic("arm Tx is not set") + } + + return val +} + +// GetTx retrieves the Tx value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u TransactionSignaturePayloadTaggedTransaction) GetTx() (result Transaction, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) + + if armName == "Tx" { + result = *u.Tx + ok = true + } + + return +} + +// MustFeeBump retrieves the FeeBump value from the union, +// panicing if the value is not set. +func (u TransactionSignaturePayloadTaggedTransaction) MustFeeBump() FeeBumpTransaction { + val, ok := u.GetFeeBump() + + if !ok { + panic("arm FeeBump is not set") + } + + return val +} + +// GetFeeBump retrieves the FeeBump value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u TransactionSignaturePayloadTaggedTransaction) GetFeeBump() (result FeeBumpTransaction, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) + + if armName == "FeeBump" { + result = *u.FeeBump + ok = true + } + + return +} + +// EncodeTo encodes this value using the Encoder. +func (u TransactionSignaturePayloadTaggedTransaction) EncodeTo(e *xdr.Encoder) error { + var err error + if err = u.Type.EncodeTo(e); err != nil { + return err + } + switch EnvelopeType(u.Type) { + case EnvelopeTypeEnvelopeTypeTx: + if err = (*u.Tx).EncodeTo(e); err != nil { + return err + } + return nil + case EnvelopeTypeEnvelopeTypeTxFeeBump: + if err = (*u.FeeBump).EncodeTo(e); err != nil { + return err + } + return nil + } + return fmt.Errorf("Type (EnvelopeType) switch value '%d' is not valid for union TransactionSignaturePayloadTaggedTransaction", u.Type) +} + +var _ decoderFrom = (*TransactionSignaturePayloadTaggedTransaction)(nil) + +// DecodeFrom decodes this value using the Decoder. +func (u *TransactionSignaturePayloadTaggedTransaction) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding TransactionSignaturePayloadTaggedTransaction: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + var err error + var n, nTmp int + nTmp, err = u.Type.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding EnvelopeType: %w", err) + } + switch EnvelopeType(u.Type) { + case EnvelopeTypeEnvelopeTypeTx: + u.Tx = new(Transaction) + nTmp, err = (*u.Tx).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Transaction: %w", err) + } + return n, nil + case EnvelopeTypeEnvelopeTypeTxFeeBump: + u.FeeBump = new(FeeBumpTransaction) + nTmp, err = (*u.FeeBump).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding FeeBumpTransaction: %w", err) + } + return n, nil + } + return n, fmt.Errorf("union TransactionSignaturePayloadTaggedTransaction has invalid Type (EnvelopeType) switch value '%d'", u.Type) +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (s TransactionSignaturePayloadTaggedTransaction) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *TransactionSignaturePayloadTaggedTransaction) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} + +var ( + _ encoding.BinaryMarshaler = (*TransactionSignaturePayloadTaggedTransaction)(nil) + _ encoding.BinaryUnmarshaler = (*TransactionSignaturePayloadTaggedTransaction)(nil) +) + +// xdrType signals that this type represents XDR values defined by this package. +func (s TransactionSignaturePayloadTaggedTransaction) xdrType() {} + +var _ xdrType = (*TransactionSignaturePayloadTaggedTransaction)(nil) + +// TransactionSignaturePayload is an XDR Struct defines as: +// +// struct TransactionSignaturePayload +// { +// Hash networkId; +// union switch (EnvelopeType type) +// { +// // Backwards Compatibility: Use ENVELOPE_TYPE_TX to sign ENVELOPE_TYPE_TX_V0 +// case ENVELOPE_TYPE_TX: +// Transaction tx; +// case ENVELOPE_TYPE_TX_FEE_BUMP: +// FeeBumpTransaction feeBump; +// } +// taggedTransaction; +// }; +type TransactionSignaturePayload struct { + NetworkId Hash + TaggedTransaction TransactionSignaturePayloadTaggedTransaction +} + +// EncodeTo encodes this value using the Encoder. +func (s *TransactionSignaturePayload) EncodeTo(e *xdr.Encoder) error { + var err error + if err = s.NetworkId.EncodeTo(e); err != nil { + return err + } + if err = s.TaggedTransaction.EncodeTo(e); err != nil { + return err + } + return nil +} + +var _ decoderFrom = (*TransactionSignaturePayload)(nil) + +// DecodeFrom decodes this value using the Decoder. +func (s *TransactionSignaturePayload) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding TransactionSignaturePayload: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + var err error + var n, nTmp int + nTmp, err = s.NetworkId.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Hash: %w", err) + } + nTmp, err = s.TaggedTransaction.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding TransactionSignaturePayloadTaggedTransaction: %w", err) + } + return n, nil +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (s TransactionSignaturePayload) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *TransactionSignaturePayload) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} + +var ( + _ encoding.BinaryMarshaler = (*TransactionSignaturePayload)(nil) + _ encoding.BinaryUnmarshaler = (*TransactionSignaturePayload)(nil) +) + +// xdrType signals that this type represents XDR values defined by this package. +func (s TransactionSignaturePayload) xdrType() {} + +var _ xdrType = (*TransactionSignaturePayload)(nil) + +// ClaimAtomType is an XDR Enum defines as: +// +// enum ClaimAtomType +// { +// CLAIM_ATOM_TYPE_V0 = 0, +// CLAIM_ATOM_TYPE_ORDER_BOOK = 1, +// CLAIM_ATOM_TYPE_LIQUIDITY_POOL = 2 +// }; +type ClaimAtomType int32 + +const ( + ClaimAtomTypeClaimAtomTypeV0 ClaimAtomType = 0 + ClaimAtomTypeClaimAtomTypeOrderBook ClaimAtomType = 1 + ClaimAtomTypeClaimAtomTypeLiquidityPool ClaimAtomType = 2 +) + +var claimAtomTypeMap = map[int32]string{ + 0: "ClaimAtomTypeClaimAtomTypeV0", + 1: "ClaimAtomTypeClaimAtomTypeOrderBook", + 2: "ClaimAtomTypeClaimAtomTypeLiquidityPool", +} + +// ValidEnum validates a proposed value for this enum. Implements +// the Enum interface for ClaimAtomType +func (e ClaimAtomType) ValidEnum(v int32) bool { + _, ok := claimAtomTypeMap[v] + return ok +} + +// String returns the name of `e` +func (e ClaimAtomType) String() string { + name, _ := claimAtomTypeMap[int32(e)] + return name +} + +// EncodeTo encodes this value using the Encoder. +func (e ClaimAtomType) EncodeTo(enc *xdr.Encoder) error { + if _, ok := claimAtomTypeMap[int32(e)]; !ok { + return fmt.Errorf("'%d' is not a valid ClaimAtomType enum value", e) + } + _, err := enc.EncodeInt(int32(e)) + return err +} + +var _ decoderFrom = (*ClaimAtomType)(nil) + +// DecodeFrom decodes this value using the Decoder. +func (e *ClaimAtomType) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding ClaimAtomType: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + v, n, err := d.DecodeInt() + if err != nil { + return n, fmt.Errorf("decoding ClaimAtomType: %w", err) + } + if _, ok := claimAtomTypeMap[v]; !ok { + return n, fmt.Errorf("'%d' is not a valid ClaimAtomType enum value", v) + } + *e = ClaimAtomType(v) + return n, nil +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (s ClaimAtomType) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *ClaimAtomType) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} + +var ( + _ encoding.BinaryMarshaler = (*ClaimAtomType)(nil) + _ encoding.BinaryUnmarshaler = (*ClaimAtomType)(nil) +) + +// xdrType signals that this type represents XDR values defined by this package. +func (s ClaimAtomType) xdrType() {} + +var _ xdrType = (*ClaimAtomType)(nil) + +// ClaimOfferAtomV0 is an XDR Struct defines as: +// +// struct ClaimOfferAtomV0 +// { +// // emitted to identify the offer +// uint256 sellerEd25519; // Account that owns the offer +// int64 offerID; +// +// // amount and asset taken from the owner +// Asset assetSold; +// int64 amountSold; +// +// // amount and asset sent to the owner +// Asset assetBought; +// int64 amountBought; +// }; +type ClaimOfferAtomV0 struct { + SellerEd25519 Uint256 + OfferId Int64 + AssetSold Asset + AmountSold Int64 + AssetBought Asset + AmountBought Int64 +} + +// EncodeTo encodes this value using the Encoder. +func (s *ClaimOfferAtomV0) EncodeTo(e *xdr.Encoder) error { + var err error + if err = s.SellerEd25519.EncodeTo(e); err != nil { + return err + } + if err = s.OfferId.EncodeTo(e); err != nil { + return err + } + if err = s.AssetSold.EncodeTo(e); err != nil { + return err + } + if err = s.AmountSold.EncodeTo(e); err != nil { + return err + } + if err = s.AssetBought.EncodeTo(e); err != nil { + return err + } + if err = s.AmountBought.EncodeTo(e); err != nil { + return err + } + return nil +} + +var _ decoderFrom = (*ClaimOfferAtomV0)(nil) + +// DecodeFrom decodes this value using the Decoder. +func (s *ClaimOfferAtomV0) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding ClaimOfferAtomV0: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + var err error + var n, nTmp int + nTmp, err = s.SellerEd25519.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Uint256: %w", err) + } + nTmp, err = s.OfferId.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Int64: %w", err) + } + nTmp, err = s.AssetSold.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Asset: %w", err) + } + nTmp, err = s.AmountSold.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Int64: %w", err) + } + nTmp, err = s.AssetBought.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Asset: %w", err) + } + nTmp, err = s.AmountBought.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Int64: %w", err) + } + return n, nil +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (s ClaimOfferAtomV0) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *ClaimOfferAtomV0) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} + +var ( + _ encoding.BinaryMarshaler = (*ClaimOfferAtomV0)(nil) + _ encoding.BinaryUnmarshaler = (*ClaimOfferAtomV0)(nil) +) + +// xdrType signals that this type represents XDR values defined by this package. +func (s ClaimOfferAtomV0) xdrType() {} + +var _ xdrType = (*ClaimOfferAtomV0)(nil) + +// ClaimOfferAtom is an XDR Struct defines as: +// +// struct ClaimOfferAtom +// { +// // emitted to identify the offer +// AccountID sellerID; // Account that owns the offer +// int64 offerID; +// +// // amount and asset taken from the owner +// Asset assetSold; +// int64 amountSold; +// +// // amount and asset sent to the owner +// Asset assetBought; +// int64 amountBought; +// }; +type ClaimOfferAtom struct { + SellerId AccountId + OfferId Int64 + AssetSold Asset + AmountSold Int64 + AssetBought Asset + AmountBought Int64 +} + +// EncodeTo encodes this value using the Encoder. +func (s *ClaimOfferAtom) EncodeTo(e *xdr.Encoder) error { + var err error + if err = s.SellerId.EncodeTo(e); err != nil { + return err + } + if err = s.OfferId.EncodeTo(e); err != nil { + return err + } + if err = s.AssetSold.EncodeTo(e); err != nil { + return err + } + if err = s.AmountSold.EncodeTo(e); err != nil { + return err + } + if err = s.AssetBought.EncodeTo(e); err != nil { + return err + } + if err = s.AmountBought.EncodeTo(e); err != nil { + return err + } + return nil +} + +var _ decoderFrom = (*ClaimOfferAtom)(nil) + +// DecodeFrom decodes this value using the Decoder. +func (s *ClaimOfferAtom) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding ClaimOfferAtom: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + var err error + var n, nTmp int + nTmp, err = s.SellerId.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding AccountId: %w", err) + } + nTmp, err = s.OfferId.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Int64: %w", err) + } + nTmp, err = s.AssetSold.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Asset: %w", err) + } + nTmp, err = s.AmountSold.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Int64: %w", err) + } + nTmp, err = s.AssetBought.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Asset: %w", err) + } + nTmp, err = s.AmountBought.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Int64: %w", err) + } + return n, nil +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (s ClaimOfferAtom) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *ClaimOfferAtom) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} + +var ( + _ encoding.BinaryMarshaler = (*ClaimOfferAtom)(nil) + _ encoding.BinaryUnmarshaler = (*ClaimOfferAtom)(nil) +) + +// xdrType signals that this type represents XDR values defined by this package. +func (s ClaimOfferAtom) xdrType() {} + +var _ xdrType = (*ClaimOfferAtom)(nil) + +// ClaimLiquidityAtom is an XDR Struct defines as: +// +// struct ClaimLiquidityAtom +// { +// PoolID liquidityPoolID; +// +// // amount and asset taken from the pool +// Asset assetSold; +// int64 amountSold; +// +// // amount and asset sent to the pool +// Asset assetBought; +// int64 amountBought; +// }; +type ClaimLiquidityAtom struct { + LiquidityPoolId PoolId + AssetSold Asset + AmountSold Int64 + AssetBought Asset + AmountBought Int64 +} + +// EncodeTo encodes this value using the Encoder. +func (s *ClaimLiquidityAtom) EncodeTo(e *xdr.Encoder) error { + var err error + if err = s.LiquidityPoolId.EncodeTo(e); err != nil { + return err + } + if err = s.AssetSold.EncodeTo(e); err != nil { + return err + } + if err = s.AmountSold.EncodeTo(e); err != nil { + return err + } + if err = s.AssetBought.EncodeTo(e); err != nil { + return err + } + if err = s.AmountBought.EncodeTo(e); err != nil { + return err + } + return nil +} + +var _ decoderFrom = (*ClaimLiquidityAtom)(nil) + +// DecodeFrom decodes this value using the Decoder. +func (s *ClaimLiquidityAtom) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding ClaimLiquidityAtom: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + var err error + var n, nTmp int + nTmp, err = s.LiquidityPoolId.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding PoolId: %w", err) + } + nTmp, err = s.AssetSold.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Asset: %w", err) + } + nTmp, err = s.AmountSold.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Int64: %w", err) + } + nTmp, err = s.AssetBought.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Asset: %w", err) + } + nTmp, err = s.AmountBought.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Int64: %w", err) + } + return n, nil +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (s ClaimLiquidityAtom) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *ClaimLiquidityAtom) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} + +var ( + _ encoding.BinaryMarshaler = (*ClaimLiquidityAtom)(nil) + _ encoding.BinaryUnmarshaler = (*ClaimLiquidityAtom)(nil) +) + +// xdrType signals that this type represents XDR values defined by this package. +func (s ClaimLiquidityAtom) xdrType() {} + +var _ xdrType = (*ClaimLiquidityAtom)(nil) + +// ClaimAtom is an XDR Union defines as: +// +// union ClaimAtom switch (ClaimAtomType type) +// { +// case CLAIM_ATOM_TYPE_V0: +// ClaimOfferAtomV0 v0; +// case CLAIM_ATOM_TYPE_ORDER_BOOK: +// ClaimOfferAtom orderBook; +// case CLAIM_ATOM_TYPE_LIQUIDITY_POOL: +// ClaimLiquidityAtom liquidityPool; +// }; +type ClaimAtom struct { + Type ClaimAtomType + V0 *ClaimOfferAtomV0 + OrderBook *ClaimOfferAtom + LiquidityPool *ClaimLiquidityAtom +} + +// SwitchFieldName returns the field name in which this union's +// discriminant is stored +func (u ClaimAtom) SwitchFieldName() string { + return "Type" +} + +// ArmForSwitch returns which field name should be used for storing +// the value for an instance of ClaimAtom +func (u ClaimAtom) ArmForSwitch(sw int32) (string, bool) { + switch ClaimAtomType(sw) { + case ClaimAtomTypeClaimAtomTypeV0: + return "V0", true + case ClaimAtomTypeClaimAtomTypeOrderBook: + return "OrderBook", true + case ClaimAtomTypeClaimAtomTypeLiquidityPool: + return "LiquidityPool", true + } + return "-", false +} + +// NewClaimAtom creates a new ClaimAtom. +func NewClaimAtom(aType ClaimAtomType, value interface{}) (result ClaimAtom, err error) { + result.Type = aType + switch ClaimAtomType(aType) { + case ClaimAtomTypeClaimAtomTypeV0: + tv, ok := value.(ClaimOfferAtomV0) + if !ok { + err = errors.New("invalid value, must be ClaimOfferAtomV0") + return + } + result.V0 = &tv + case ClaimAtomTypeClaimAtomTypeOrderBook: + tv, ok := value.(ClaimOfferAtom) + if !ok { + err = errors.New("invalid value, must be ClaimOfferAtom") + return + } + result.OrderBook = &tv + case ClaimAtomTypeClaimAtomTypeLiquidityPool: + tv, ok := value.(ClaimLiquidityAtom) + if !ok { + err = errors.New("invalid value, must be ClaimLiquidityAtom") + return + } + result.LiquidityPool = &tv + } + return +} + +// MustV0 retrieves the V0 value from the union, +// panicing if the value is not set. +func (u ClaimAtom) MustV0() ClaimOfferAtomV0 { + val, ok := u.GetV0() + + if !ok { + panic("arm V0 is not set") + } + + return val +} + +// GetV0 retrieves the V0 value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u ClaimAtom) GetV0() (result ClaimOfferAtomV0, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) + + if armName == "V0" { + result = *u.V0 + ok = true + } + + return +} + +// MustOrderBook retrieves the OrderBook value from the union, +// panicing if the value is not set. +func (u ClaimAtom) MustOrderBook() ClaimOfferAtom { + val, ok := u.GetOrderBook() + + if !ok { + panic("arm OrderBook is not set") + } + + return val +} + +// GetOrderBook retrieves the OrderBook value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u ClaimAtom) GetOrderBook() (result ClaimOfferAtom, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) + + if armName == "OrderBook" { + result = *u.OrderBook + ok = true + } + + return +} + +// MustLiquidityPool retrieves the LiquidityPool value from the union, +// panicing if the value is not set. +func (u ClaimAtom) MustLiquidityPool() ClaimLiquidityAtom { + val, ok := u.GetLiquidityPool() + + if !ok { + panic("arm LiquidityPool is not set") + } + + return val +} + +// GetLiquidityPool retrieves the LiquidityPool value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u ClaimAtom) GetLiquidityPool() (result ClaimLiquidityAtom, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) + + if armName == "LiquidityPool" { + result = *u.LiquidityPool + ok = true + } + + return +} + +// EncodeTo encodes this value using the Encoder. +func (u ClaimAtom) EncodeTo(e *xdr.Encoder) error { + var err error + if err = u.Type.EncodeTo(e); err != nil { + return err + } + switch ClaimAtomType(u.Type) { + case ClaimAtomTypeClaimAtomTypeV0: + if err = (*u.V0).EncodeTo(e); err != nil { + return err + } + return nil + case ClaimAtomTypeClaimAtomTypeOrderBook: + if err = (*u.OrderBook).EncodeTo(e); err != nil { + return err + } + return nil + case ClaimAtomTypeClaimAtomTypeLiquidityPool: + if err = (*u.LiquidityPool).EncodeTo(e); err != nil { + return err + } + return nil + } + return fmt.Errorf("Type (ClaimAtomType) switch value '%d' is not valid for union ClaimAtom", u.Type) +} + +var _ decoderFrom = (*ClaimAtom)(nil) + +// DecodeFrom decodes this value using the Decoder. +func (u *ClaimAtom) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding ClaimAtom: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + var err error + var n, nTmp int + nTmp, err = u.Type.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ClaimAtomType: %w", err) + } + switch ClaimAtomType(u.Type) { + case ClaimAtomTypeClaimAtomTypeV0: + u.V0 = new(ClaimOfferAtomV0) + nTmp, err = (*u.V0).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ClaimOfferAtomV0: %w", err) + } + return n, nil + case ClaimAtomTypeClaimAtomTypeOrderBook: + u.OrderBook = new(ClaimOfferAtom) + nTmp, err = (*u.OrderBook).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ClaimOfferAtom: %w", err) + } + return n, nil + case ClaimAtomTypeClaimAtomTypeLiquidityPool: + u.LiquidityPool = new(ClaimLiquidityAtom) + nTmp, err = (*u.LiquidityPool).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ClaimLiquidityAtom: %w", err) + } + return n, nil + } + return n, fmt.Errorf("union ClaimAtom has invalid Type (ClaimAtomType) switch value '%d'", u.Type) +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (s ClaimAtom) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *ClaimAtom) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} + +var ( + _ encoding.BinaryMarshaler = (*ClaimAtom)(nil) + _ encoding.BinaryUnmarshaler = (*ClaimAtom)(nil) +) + +// xdrType signals that this type represents XDR values defined by this package. +func (s ClaimAtom) xdrType() {} + +var _ xdrType = (*ClaimAtom)(nil) + +// CreateAccountResultCode is an XDR Enum defines as: +// +// enum CreateAccountResultCode +// { +// // codes considered as "success" for the operation +// CREATE_ACCOUNT_SUCCESS = 0, // account was created +// +// // codes considered as "failure" for the operation +// CREATE_ACCOUNT_MALFORMED = -1, // invalid destination +// CREATE_ACCOUNT_UNDERFUNDED = -2, // not enough funds in source account +// CREATE_ACCOUNT_LOW_RESERVE = +// -3, // would create an account below the min reserve +// CREATE_ACCOUNT_ALREADY_EXIST = -4 // account already exists +// }; +type CreateAccountResultCode int32 + +const ( + CreateAccountResultCodeCreateAccountSuccess CreateAccountResultCode = 0 + CreateAccountResultCodeCreateAccountMalformed CreateAccountResultCode = -1 + CreateAccountResultCodeCreateAccountUnderfunded CreateAccountResultCode = -2 + CreateAccountResultCodeCreateAccountLowReserve CreateAccountResultCode = -3 + CreateAccountResultCodeCreateAccountAlreadyExist CreateAccountResultCode = -4 +) + +var createAccountResultCodeMap = map[int32]string{ + 0: "CreateAccountResultCodeCreateAccountSuccess", + -1: "CreateAccountResultCodeCreateAccountMalformed", + -2: "CreateAccountResultCodeCreateAccountUnderfunded", + -3: "CreateAccountResultCodeCreateAccountLowReserve", + -4: "CreateAccountResultCodeCreateAccountAlreadyExist", +} + +// ValidEnum validates a proposed value for this enum. Implements +// the Enum interface for CreateAccountResultCode +func (e CreateAccountResultCode) ValidEnum(v int32) bool { + _, ok := createAccountResultCodeMap[v] + return ok +} + +// String returns the name of `e` +func (e CreateAccountResultCode) String() string { + name, _ := createAccountResultCodeMap[int32(e)] + return name +} + +// EncodeTo encodes this value using the Encoder. +func (e CreateAccountResultCode) EncodeTo(enc *xdr.Encoder) error { + if _, ok := createAccountResultCodeMap[int32(e)]; !ok { + return fmt.Errorf("'%d' is not a valid CreateAccountResultCode enum value", e) + } + _, err := enc.EncodeInt(int32(e)) + return err +} + +var _ decoderFrom = (*CreateAccountResultCode)(nil) + +// DecodeFrom decodes this value using the Decoder. +func (e *CreateAccountResultCode) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding CreateAccountResultCode: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + v, n, err := d.DecodeInt() + if err != nil { + return n, fmt.Errorf("decoding CreateAccountResultCode: %w", err) + } + if _, ok := createAccountResultCodeMap[v]; !ok { + return n, fmt.Errorf("'%d' is not a valid CreateAccountResultCode enum value", v) + } + *e = CreateAccountResultCode(v) + return n, nil +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (s CreateAccountResultCode) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *CreateAccountResultCode) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} + +var ( + _ encoding.BinaryMarshaler = (*CreateAccountResultCode)(nil) + _ encoding.BinaryUnmarshaler = (*CreateAccountResultCode)(nil) +) + +// xdrType signals that this type represents XDR values defined by this package. +func (s CreateAccountResultCode) xdrType() {} + +var _ xdrType = (*CreateAccountResultCode)(nil) + +// CreateAccountResult is an XDR Union defines as: +// +// union CreateAccountResult switch (CreateAccountResultCode code) +// { +// case CREATE_ACCOUNT_SUCCESS: +// void; +// case CREATE_ACCOUNT_MALFORMED: +// case CREATE_ACCOUNT_UNDERFUNDED: +// case CREATE_ACCOUNT_LOW_RESERVE: +// case CREATE_ACCOUNT_ALREADY_EXIST: +// void; +// }; +type CreateAccountResult struct { + Code CreateAccountResultCode +} + +// SwitchFieldName returns the field name in which this union's +// discriminant is stored +func (u CreateAccountResult) SwitchFieldName() string { + return "Code" +} + +// ArmForSwitch returns which field name should be used for storing +// the value for an instance of CreateAccountResult +func (u CreateAccountResult) ArmForSwitch(sw int32) (string, bool) { + switch CreateAccountResultCode(sw) { + case CreateAccountResultCodeCreateAccountSuccess: + return "", true + case CreateAccountResultCodeCreateAccountMalformed: + return "", true + case CreateAccountResultCodeCreateAccountUnderfunded: + return "", true + case CreateAccountResultCodeCreateAccountLowReserve: + return "", true + case CreateAccountResultCodeCreateAccountAlreadyExist: + return "", true + } + return "-", false +} + +// NewCreateAccountResult creates a new CreateAccountResult. +func NewCreateAccountResult(code CreateAccountResultCode, value interface{}) (result CreateAccountResult, err error) { + result.Code = code + switch CreateAccountResultCode(code) { + case CreateAccountResultCodeCreateAccountSuccess: + // void + case CreateAccountResultCodeCreateAccountMalformed: + // void + case CreateAccountResultCodeCreateAccountUnderfunded: + // void + case CreateAccountResultCodeCreateAccountLowReserve: + // void + case CreateAccountResultCodeCreateAccountAlreadyExist: + // void + } + return +} + +// EncodeTo encodes this value using the Encoder. +func (u CreateAccountResult) EncodeTo(e *xdr.Encoder) error { + var err error + if err = u.Code.EncodeTo(e); err != nil { + return err + } + switch CreateAccountResultCode(u.Code) { + case CreateAccountResultCodeCreateAccountSuccess: + // Void + return nil + case CreateAccountResultCodeCreateAccountMalformed: + // Void + return nil + case CreateAccountResultCodeCreateAccountUnderfunded: + // Void + return nil + case CreateAccountResultCodeCreateAccountLowReserve: + // Void + return nil + case CreateAccountResultCodeCreateAccountAlreadyExist: + // Void + return nil + } + return fmt.Errorf("Code (CreateAccountResultCode) switch value '%d' is not valid for union CreateAccountResult", u.Code) +} + +var _ decoderFrom = (*CreateAccountResult)(nil) + +// DecodeFrom decodes this value using the Decoder. +func (u *CreateAccountResult) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding CreateAccountResult: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + var err error + var n, nTmp int + nTmp, err = u.Code.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding CreateAccountResultCode: %w", err) + } + switch CreateAccountResultCode(u.Code) { + case CreateAccountResultCodeCreateAccountSuccess: + // Void + return n, nil + case CreateAccountResultCodeCreateAccountMalformed: + // Void + return n, nil + case CreateAccountResultCodeCreateAccountUnderfunded: + // Void + return n, nil + case CreateAccountResultCodeCreateAccountLowReserve: + // Void + return n, nil + case CreateAccountResultCodeCreateAccountAlreadyExist: + // Void + return n, nil + } + return n, fmt.Errorf("union CreateAccountResult has invalid Code (CreateAccountResultCode) switch value '%d'", u.Code) +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (s CreateAccountResult) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *CreateAccountResult) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} + +var ( + _ encoding.BinaryMarshaler = (*CreateAccountResult)(nil) + _ encoding.BinaryUnmarshaler = (*CreateAccountResult)(nil) +) + +// xdrType signals that this type represents XDR values defined by this package. +func (s CreateAccountResult) xdrType() {} + +var _ xdrType = (*CreateAccountResult)(nil) + +// PaymentResultCode is an XDR Enum defines as: +// +// enum PaymentResultCode +// { +// // codes considered as "success" for the operation +// PAYMENT_SUCCESS = 0, // payment successfully completed +// +// // codes considered as "failure" for the operation +// PAYMENT_MALFORMED = -1, // bad input +// PAYMENT_UNDERFUNDED = -2, // not enough funds in source account +// PAYMENT_SRC_NO_TRUST = -3, // no trust line on source account +// PAYMENT_SRC_NOT_AUTHORIZED = -4, // source not authorized to transfer +// PAYMENT_NO_DESTINATION = -5, // destination account does not exist +// PAYMENT_NO_TRUST = -6, // destination missing a trust line for asset +// PAYMENT_NOT_AUTHORIZED = -7, // destination not authorized to hold asset +// PAYMENT_LINE_FULL = -8, // destination would go above their limit +// PAYMENT_NO_ISSUER = -9 // missing issuer on asset +// }; +type PaymentResultCode int32 + +const ( + PaymentResultCodePaymentSuccess PaymentResultCode = 0 + PaymentResultCodePaymentMalformed PaymentResultCode = -1 + PaymentResultCodePaymentUnderfunded PaymentResultCode = -2 + PaymentResultCodePaymentSrcNoTrust PaymentResultCode = -3 + PaymentResultCodePaymentSrcNotAuthorized PaymentResultCode = -4 + PaymentResultCodePaymentNoDestination PaymentResultCode = -5 + PaymentResultCodePaymentNoTrust PaymentResultCode = -6 + PaymentResultCodePaymentNotAuthorized PaymentResultCode = -7 + PaymentResultCodePaymentLineFull PaymentResultCode = -8 + PaymentResultCodePaymentNoIssuer PaymentResultCode = -9 +) + +var paymentResultCodeMap = map[int32]string{ + 0: "PaymentResultCodePaymentSuccess", + -1: "PaymentResultCodePaymentMalformed", + -2: "PaymentResultCodePaymentUnderfunded", + -3: "PaymentResultCodePaymentSrcNoTrust", + -4: "PaymentResultCodePaymentSrcNotAuthorized", + -5: "PaymentResultCodePaymentNoDestination", + -6: "PaymentResultCodePaymentNoTrust", + -7: "PaymentResultCodePaymentNotAuthorized", + -8: "PaymentResultCodePaymentLineFull", + -9: "PaymentResultCodePaymentNoIssuer", +} + +// ValidEnum validates a proposed value for this enum. Implements +// the Enum interface for PaymentResultCode +func (e PaymentResultCode) ValidEnum(v int32) bool { + _, ok := paymentResultCodeMap[v] + return ok +} + +// String returns the name of `e` +func (e PaymentResultCode) String() string { + name, _ := paymentResultCodeMap[int32(e)] + return name +} + +// EncodeTo encodes this value using the Encoder. +func (e PaymentResultCode) EncodeTo(enc *xdr.Encoder) error { + if _, ok := paymentResultCodeMap[int32(e)]; !ok { + return fmt.Errorf("'%d' is not a valid PaymentResultCode enum value", e) + } + _, err := enc.EncodeInt(int32(e)) + return err +} + +var _ decoderFrom = (*PaymentResultCode)(nil) + +// DecodeFrom decodes this value using the Decoder. +func (e *PaymentResultCode) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding PaymentResultCode: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + v, n, err := d.DecodeInt() + if err != nil { + return n, fmt.Errorf("decoding PaymentResultCode: %w", err) + } + if _, ok := paymentResultCodeMap[v]; !ok { + return n, fmt.Errorf("'%d' is not a valid PaymentResultCode enum value", v) + } + *e = PaymentResultCode(v) + return n, nil +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (s PaymentResultCode) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *PaymentResultCode) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} + +var ( + _ encoding.BinaryMarshaler = (*PaymentResultCode)(nil) + _ encoding.BinaryUnmarshaler = (*PaymentResultCode)(nil) +) + +// xdrType signals that this type represents XDR values defined by this package. +func (s PaymentResultCode) xdrType() {} + +var _ xdrType = (*PaymentResultCode)(nil) + +// PaymentResult is an XDR Union defines as: +// +// union PaymentResult switch (PaymentResultCode code) +// { +// case PAYMENT_SUCCESS: +// void; +// case PAYMENT_MALFORMED: +// case PAYMENT_UNDERFUNDED: +// case PAYMENT_SRC_NO_TRUST: +// case PAYMENT_SRC_NOT_AUTHORIZED: +// case PAYMENT_NO_DESTINATION: +// case PAYMENT_NO_TRUST: +// case PAYMENT_NOT_AUTHORIZED: +// case PAYMENT_LINE_FULL: +// case PAYMENT_NO_ISSUER: +// void; +// }; +type PaymentResult struct { + Code PaymentResultCode +} + +// SwitchFieldName returns the field name in which this union's +// discriminant is stored +func (u PaymentResult) SwitchFieldName() string { + return "Code" +} + +// ArmForSwitch returns which field name should be used for storing +// the value for an instance of PaymentResult +func (u PaymentResult) ArmForSwitch(sw int32) (string, bool) { + switch PaymentResultCode(sw) { + case PaymentResultCodePaymentSuccess: + return "", true + case PaymentResultCodePaymentMalformed: + return "", true + case PaymentResultCodePaymentUnderfunded: + return "", true + case PaymentResultCodePaymentSrcNoTrust: + return "", true + case PaymentResultCodePaymentSrcNotAuthorized: + return "", true + case PaymentResultCodePaymentNoDestination: + return "", true + case PaymentResultCodePaymentNoTrust: + return "", true + case PaymentResultCodePaymentNotAuthorized: + return "", true + case PaymentResultCodePaymentLineFull: + return "", true + case PaymentResultCodePaymentNoIssuer: + return "", true + } + return "-", false +} + +// NewPaymentResult creates a new PaymentResult. +func NewPaymentResult(code PaymentResultCode, value interface{}) (result PaymentResult, err error) { + result.Code = code + switch PaymentResultCode(code) { + case PaymentResultCodePaymentSuccess: + // void + case PaymentResultCodePaymentMalformed: + // void + case PaymentResultCodePaymentUnderfunded: + // void + case PaymentResultCodePaymentSrcNoTrust: + // void + case PaymentResultCodePaymentSrcNotAuthorized: + // void + case PaymentResultCodePaymentNoDestination: + // void + case PaymentResultCodePaymentNoTrust: + // void + case PaymentResultCodePaymentNotAuthorized: + // void + case PaymentResultCodePaymentLineFull: + // void + case PaymentResultCodePaymentNoIssuer: + // void + } + return +} + +// EncodeTo encodes this value using the Encoder. +func (u PaymentResult) EncodeTo(e *xdr.Encoder) error { + var err error + if err = u.Code.EncodeTo(e); err != nil { + return err + } + switch PaymentResultCode(u.Code) { + case PaymentResultCodePaymentSuccess: + // Void + return nil + case PaymentResultCodePaymentMalformed: + // Void + return nil + case PaymentResultCodePaymentUnderfunded: + // Void + return nil + case PaymentResultCodePaymentSrcNoTrust: + // Void + return nil + case PaymentResultCodePaymentSrcNotAuthorized: + // Void + return nil + case PaymentResultCodePaymentNoDestination: + // Void + return nil + case PaymentResultCodePaymentNoTrust: + // Void + return nil + case PaymentResultCodePaymentNotAuthorized: + // Void + return nil + case PaymentResultCodePaymentLineFull: + // Void + return nil + case PaymentResultCodePaymentNoIssuer: + // Void + return nil + } + return fmt.Errorf("Code (PaymentResultCode) switch value '%d' is not valid for union PaymentResult", u.Code) +} + +var _ decoderFrom = (*PaymentResult)(nil) + +// DecodeFrom decodes this value using the Decoder. +func (u *PaymentResult) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding PaymentResult: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + var err error + var n, nTmp int + nTmp, err = u.Code.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding PaymentResultCode: %w", err) + } + switch PaymentResultCode(u.Code) { + case PaymentResultCodePaymentSuccess: + // Void + return n, nil + case PaymentResultCodePaymentMalformed: + // Void + return n, nil + case PaymentResultCodePaymentUnderfunded: + // Void + return n, nil + case PaymentResultCodePaymentSrcNoTrust: + // Void + return n, nil + case PaymentResultCodePaymentSrcNotAuthorized: + // Void + return n, nil + case PaymentResultCodePaymentNoDestination: + // Void + return n, nil + case PaymentResultCodePaymentNoTrust: + // Void + return n, nil + case PaymentResultCodePaymentNotAuthorized: + // Void + return n, nil + case PaymentResultCodePaymentLineFull: + // Void + return n, nil + case PaymentResultCodePaymentNoIssuer: + // Void + return n, nil + } + return n, fmt.Errorf("union PaymentResult has invalid Code (PaymentResultCode) switch value '%d'", u.Code) +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (s PaymentResult) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *PaymentResult) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} + +var ( + _ encoding.BinaryMarshaler = (*PaymentResult)(nil) + _ encoding.BinaryUnmarshaler = (*PaymentResult)(nil) +) + +// xdrType signals that this type represents XDR values defined by this package. +func (s PaymentResult) xdrType() {} + +var _ xdrType = (*PaymentResult)(nil) + +// PathPaymentStrictReceiveResultCode is an XDR Enum defines as: +// +// enum PathPaymentStrictReceiveResultCode +// { +// // codes considered as "success" for the operation +// PATH_PAYMENT_STRICT_RECEIVE_SUCCESS = 0, // success +// +// // codes considered as "failure" for the operation +// PATH_PAYMENT_STRICT_RECEIVE_MALFORMED = -1, // bad input +// PATH_PAYMENT_STRICT_RECEIVE_UNDERFUNDED = +// -2, // not enough funds in source account +// PATH_PAYMENT_STRICT_RECEIVE_SRC_NO_TRUST = +// -3, // no trust line on source account +// PATH_PAYMENT_STRICT_RECEIVE_SRC_NOT_AUTHORIZED = +// -4, // source not authorized to transfer +// PATH_PAYMENT_STRICT_RECEIVE_NO_DESTINATION = +// -5, // destination account does not exist +// PATH_PAYMENT_STRICT_RECEIVE_NO_TRUST = +// -6, // dest missing a trust line for asset +// PATH_PAYMENT_STRICT_RECEIVE_NOT_AUTHORIZED = +// -7, // dest not authorized to hold asset +// PATH_PAYMENT_STRICT_RECEIVE_LINE_FULL = +// -8, // dest would go above their limit +// PATH_PAYMENT_STRICT_RECEIVE_NO_ISSUER = -9, // missing issuer on one asset +// PATH_PAYMENT_STRICT_RECEIVE_TOO_FEW_OFFERS = +// -10, // not enough offers to satisfy path +// PATH_PAYMENT_STRICT_RECEIVE_OFFER_CROSS_SELF = +// -11, // would cross one of its own offers +// PATH_PAYMENT_STRICT_RECEIVE_OVER_SENDMAX = -12 // could not satisfy sendmax +// }; +type PathPaymentStrictReceiveResultCode int32 + +const ( + PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveSuccess PathPaymentStrictReceiveResultCode = 0 + PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveMalformed PathPaymentStrictReceiveResultCode = -1 + PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveUnderfunded PathPaymentStrictReceiveResultCode = -2 + PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveSrcNoTrust PathPaymentStrictReceiveResultCode = -3 + PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveSrcNotAuthorized PathPaymentStrictReceiveResultCode = -4 + PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveNoDestination PathPaymentStrictReceiveResultCode = -5 + PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveNoTrust PathPaymentStrictReceiveResultCode = -6 + PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveNotAuthorized PathPaymentStrictReceiveResultCode = -7 + PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveLineFull PathPaymentStrictReceiveResultCode = -8 + PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveNoIssuer PathPaymentStrictReceiveResultCode = -9 + PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveTooFewOffers PathPaymentStrictReceiveResultCode = -10 + PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveOfferCrossSelf PathPaymentStrictReceiveResultCode = -11 + PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveOverSendmax PathPaymentStrictReceiveResultCode = -12 +) + +var pathPaymentStrictReceiveResultCodeMap = map[int32]string{ + 0: "PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveSuccess", + -1: "PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveMalformed", + -2: "PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveUnderfunded", + -3: "PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveSrcNoTrust", + -4: "PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveSrcNotAuthorized", + -5: "PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveNoDestination", + -6: "PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveNoTrust", + -7: "PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveNotAuthorized", + -8: "PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveLineFull", + -9: "PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveNoIssuer", + -10: "PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveTooFewOffers", + -11: "PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveOfferCrossSelf", + -12: "PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveOverSendmax", +} + +// ValidEnum validates a proposed value for this enum. Implements +// the Enum interface for PathPaymentStrictReceiveResultCode +func (e PathPaymentStrictReceiveResultCode) ValidEnum(v int32) bool { + _, ok := pathPaymentStrictReceiveResultCodeMap[v] + return ok +} + +// String returns the name of `e` +func (e PathPaymentStrictReceiveResultCode) String() string { + name, _ := pathPaymentStrictReceiveResultCodeMap[int32(e)] + return name +} + +// EncodeTo encodes this value using the Encoder. +func (e PathPaymentStrictReceiveResultCode) EncodeTo(enc *xdr.Encoder) error { + if _, ok := pathPaymentStrictReceiveResultCodeMap[int32(e)]; !ok { + return fmt.Errorf("'%d' is not a valid PathPaymentStrictReceiveResultCode enum value", e) + } + _, err := enc.EncodeInt(int32(e)) + return err +} + +var _ decoderFrom = (*PathPaymentStrictReceiveResultCode)(nil) + +// DecodeFrom decodes this value using the Decoder. +func (e *PathPaymentStrictReceiveResultCode) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding PathPaymentStrictReceiveResultCode: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + v, n, err := d.DecodeInt() + if err != nil { + return n, fmt.Errorf("decoding PathPaymentStrictReceiveResultCode: %w", err) + } + if _, ok := pathPaymentStrictReceiveResultCodeMap[v]; !ok { + return n, fmt.Errorf("'%d' is not a valid PathPaymentStrictReceiveResultCode enum value", v) + } + *e = PathPaymentStrictReceiveResultCode(v) + return n, nil +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (s PathPaymentStrictReceiveResultCode) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *PathPaymentStrictReceiveResultCode) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} + +var ( + _ encoding.BinaryMarshaler = (*PathPaymentStrictReceiveResultCode)(nil) + _ encoding.BinaryUnmarshaler = (*PathPaymentStrictReceiveResultCode)(nil) +) + +// xdrType signals that this type represents XDR values defined by this package. +func (s PathPaymentStrictReceiveResultCode) xdrType() {} + +var _ xdrType = (*PathPaymentStrictReceiveResultCode)(nil) + +// SimplePaymentResult is an XDR Struct defines as: +// +// struct SimplePaymentResult +// { +// AccountID destination; +// Asset asset; +// int64 amount; +// }; +type SimplePaymentResult struct { + Destination AccountId + Asset Asset + Amount Int64 +} + +// EncodeTo encodes this value using the Encoder. +func (s *SimplePaymentResult) EncodeTo(e *xdr.Encoder) error { + var err error + if err = s.Destination.EncodeTo(e); err != nil { + return err + } + if err = s.Asset.EncodeTo(e); err != nil { + return err + } + if err = s.Amount.EncodeTo(e); err != nil { + return err + } + return nil +} + +var _ decoderFrom = (*SimplePaymentResult)(nil) + +// DecodeFrom decodes this value using the Decoder. +func (s *SimplePaymentResult) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding SimplePaymentResult: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + var err error + var n, nTmp int + nTmp, err = s.Destination.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding AccountId: %w", err) + } + nTmp, err = s.Asset.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Asset: %w", err) + } + nTmp, err = s.Amount.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Int64: %w", err) + } + return n, nil +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (s SimplePaymentResult) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *SimplePaymentResult) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} + +var ( + _ encoding.BinaryMarshaler = (*SimplePaymentResult)(nil) + _ encoding.BinaryUnmarshaler = (*SimplePaymentResult)(nil) +) + +// xdrType signals that this type represents XDR values defined by this package. +func (s SimplePaymentResult) xdrType() {} + +var _ xdrType = (*SimplePaymentResult)(nil) + +// PathPaymentStrictReceiveResultSuccess is an XDR NestedStruct defines as: +// +// struct +// { +// ClaimAtom offers<>; +// SimplePaymentResult last; +// } +type PathPaymentStrictReceiveResultSuccess struct { + Offers []ClaimAtom + Last SimplePaymentResult +} + +// EncodeTo encodes this value using the Encoder. +func (s *PathPaymentStrictReceiveResultSuccess) EncodeTo(e *xdr.Encoder) error { + var err error + if _, err = e.EncodeUint(uint32(len(s.Offers))); err != nil { + return err + } + for i := 0; i < len(s.Offers); i++ { + if err = s.Offers[i].EncodeTo(e); err != nil { + return err + } + } + if err = s.Last.EncodeTo(e); err != nil { + return err + } + return nil +} + +var _ decoderFrom = (*PathPaymentStrictReceiveResultSuccess)(nil) + +// DecodeFrom decodes this value using the Decoder. +func (s *PathPaymentStrictReceiveResultSuccess) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding PathPaymentStrictReceiveResultSuccess: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + var err error + var n, nTmp int + var l uint32 + l, nTmp, err = d.DecodeUint() + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ClaimAtom: %w", err) + } + s.Offers = nil + if l > 0 { + if il, ok := d.InputLen(); ok && uint(il) < uint(l) { + return n, fmt.Errorf("decoding ClaimAtom: length (%d) exceeds remaining input length (%d)", l, il) + } + s.Offers = make([]ClaimAtom, l) + for i := uint32(0); i < l; i++ { + nTmp, err = s.Offers[i].DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ClaimAtom: %w", err) + } + } + } + nTmp, err = s.Last.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding SimplePaymentResult: %w", err) + } + return n, nil +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (s PathPaymentStrictReceiveResultSuccess) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *PathPaymentStrictReceiveResultSuccess) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} + +var ( + _ encoding.BinaryMarshaler = (*PathPaymentStrictReceiveResultSuccess)(nil) + _ encoding.BinaryUnmarshaler = (*PathPaymentStrictReceiveResultSuccess)(nil) +) + +// xdrType signals that this type represents XDR values defined by this package. +func (s PathPaymentStrictReceiveResultSuccess) xdrType() {} + +var _ xdrType = (*PathPaymentStrictReceiveResultSuccess)(nil) + +// PathPaymentStrictReceiveResult is an XDR Union defines as: +// +// union PathPaymentStrictReceiveResult switch ( +// PathPaymentStrictReceiveResultCode code) +// { +// case PATH_PAYMENT_STRICT_RECEIVE_SUCCESS: +// struct +// { +// ClaimAtom offers<>; +// SimplePaymentResult last; +// } success; +// case PATH_PAYMENT_STRICT_RECEIVE_MALFORMED: +// case PATH_PAYMENT_STRICT_RECEIVE_UNDERFUNDED: +// case PATH_PAYMENT_STRICT_RECEIVE_SRC_NO_TRUST: +// case PATH_PAYMENT_STRICT_RECEIVE_SRC_NOT_AUTHORIZED: +// case PATH_PAYMENT_STRICT_RECEIVE_NO_DESTINATION: +// case PATH_PAYMENT_STRICT_RECEIVE_NO_TRUST: +// case PATH_PAYMENT_STRICT_RECEIVE_NOT_AUTHORIZED: +// case PATH_PAYMENT_STRICT_RECEIVE_LINE_FULL: +// void; +// case PATH_PAYMENT_STRICT_RECEIVE_NO_ISSUER: +// Asset noIssuer; // the asset that caused the error +// case PATH_PAYMENT_STRICT_RECEIVE_TOO_FEW_OFFERS: +// case PATH_PAYMENT_STRICT_RECEIVE_OFFER_CROSS_SELF: +// case PATH_PAYMENT_STRICT_RECEIVE_OVER_SENDMAX: +// void; +// }; +type PathPaymentStrictReceiveResult struct { + Code PathPaymentStrictReceiveResultCode + Success *PathPaymentStrictReceiveResultSuccess + NoIssuer *Asset +} + +// SwitchFieldName returns the field name in which this union's +// discriminant is stored +func (u PathPaymentStrictReceiveResult) SwitchFieldName() string { + return "Code" +} + +// ArmForSwitch returns which field name should be used for storing +// the value for an instance of PathPaymentStrictReceiveResult +func (u PathPaymentStrictReceiveResult) ArmForSwitch(sw int32) (string, bool) { + switch PathPaymentStrictReceiveResultCode(sw) { + case PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveSuccess: + return "Success", true + case PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveMalformed: + return "", true + case PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveUnderfunded: + return "", true + case PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveSrcNoTrust: + return "", true + case PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveSrcNotAuthorized: + return "", true + case PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveNoDestination: + return "", true + case PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveNoTrust: + return "", true + case PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveNotAuthorized: + return "", true + case PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveLineFull: + return "", true + case PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveNoIssuer: + return "NoIssuer", true + case PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveTooFewOffers: + return "", true + case PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveOfferCrossSelf: + return "", true + case PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveOverSendmax: + return "", true + } + return "-", false +} + +// NewPathPaymentStrictReceiveResult creates a new PathPaymentStrictReceiveResult. +func NewPathPaymentStrictReceiveResult(code PathPaymentStrictReceiveResultCode, value interface{}) (result PathPaymentStrictReceiveResult, err error) { + result.Code = code + switch PathPaymentStrictReceiveResultCode(code) { + case PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveSuccess: + tv, ok := value.(PathPaymentStrictReceiveResultSuccess) + if !ok { + err = errors.New("invalid value, must be PathPaymentStrictReceiveResultSuccess") + return + } + result.Success = &tv + case PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveMalformed: + // void + case PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveUnderfunded: + // void + case PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveSrcNoTrust: + // void + case PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveSrcNotAuthorized: + // void + case PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveNoDestination: + // void + case PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveNoTrust: + // void + case PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveNotAuthorized: + // void + case PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveLineFull: + // void + case PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveNoIssuer: + tv, ok := value.(Asset) + if !ok { + err = errors.New("invalid value, must be Asset") + return + } + result.NoIssuer = &tv + case PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveTooFewOffers: + // void + case PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveOfferCrossSelf: + // void + case PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveOverSendmax: + // void + } + return +} + +// MustSuccess retrieves the Success value from the union, +// panicing if the value is not set. +func (u PathPaymentStrictReceiveResult) MustSuccess() PathPaymentStrictReceiveResultSuccess { + val, ok := u.GetSuccess() + + if !ok { + panic("arm Success is not set") + } + + return val +} + +// GetSuccess retrieves the Success value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u PathPaymentStrictReceiveResult) GetSuccess() (result PathPaymentStrictReceiveResultSuccess, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Code)) + + if armName == "Success" { + result = *u.Success + ok = true + } + + return +} + +// MustNoIssuer retrieves the NoIssuer value from the union, +// panicing if the value is not set. +func (u PathPaymentStrictReceiveResult) MustNoIssuer() Asset { + val, ok := u.GetNoIssuer() + + if !ok { + panic("arm NoIssuer is not set") + } + + return val +} + +// GetNoIssuer retrieves the NoIssuer value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u PathPaymentStrictReceiveResult) GetNoIssuer() (result Asset, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Code)) + + if armName == "NoIssuer" { + result = *u.NoIssuer + ok = true + } + + return +} + // EncodeTo encodes this value using the Encoder. -func (s *PathPaymentStrictSendOp) EncodeTo(e *xdr.Encoder) error { +func (u PathPaymentStrictReceiveResult) EncodeTo(e *xdr.Encoder) error { var err error - if err = s.SendAsset.EncodeTo(e); err != nil { + if err = u.Code.EncodeTo(e); err != nil { + return err + } + switch PathPaymentStrictReceiveResultCode(u.Code) { + case PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveSuccess: + if err = (*u.Success).EncodeTo(e); err != nil { + return err + } + return nil + case PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveMalformed: + // Void + return nil + case PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveUnderfunded: + // Void + return nil + case PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveSrcNoTrust: + // Void + return nil + case PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveSrcNotAuthorized: + // Void + return nil + case PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveNoDestination: + // Void + return nil + case PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveNoTrust: + // Void + return nil + case PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveNotAuthorized: + // Void + return nil + case PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveLineFull: + // Void + return nil + case PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveNoIssuer: + if err = (*u.NoIssuer).EncodeTo(e); err != nil { + return err + } + return nil + case PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveTooFewOffers: + // Void + return nil + case PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveOfferCrossSelf: + // Void + return nil + case PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveOverSendmax: + // Void + return nil + } + return fmt.Errorf("Code (PathPaymentStrictReceiveResultCode) switch value '%d' is not valid for union PathPaymentStrictReceiveResult", u.Code) +} + +var _ decoderFrom = (*PathPaymentStrictReceiveResult)(nil) + +// DecodeFrom decodes this value using the Decoder. +func (u *PathPaymentStrictReceiveResult) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding PathPaymentStrictReceiveResult: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + var err error + var n, nTmp int + nTmp, err = u.Code.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding PathPaymentStrictReceiveResultCode: %w", err) + } + switch PathPaymentStrictReceiveResultCode(u.Code) { + case PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveSuccess: + u.Success = new(PathPaymentStrictReceiveResultSuccess) + nTmp, err = (*u.Success).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding PathPaymentStrictReceiveResultSuccess: %w", err) + } + return n, nil + case PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveMalformed: + // Void + return n, nil + case PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveUnderfunded: + // Void + return n, nil + case PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveSrcNoTrust: + // Void + return n, nil + case PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveSrcNotAuthorized: + // Void + return n, nil + case PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveNoDestination: + // Void + return n, nil + case PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveNoTrust: + // Void + return n, nil + case PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveNotAuthorized: + // Void + return n, nil + case PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveLineFull: + // Void + return n, nil + case PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveNoIssuer: + u.NoIssuer = new(Asset) + nTmp, err = (*u.NoIssuer).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Asset: %w", err) + } + return n, nil + case PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveTooFewOffers: + // Void + return n, nil + case PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveOfferCrossSelf: + // Void + return n, nil + case PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveOverSendmax: + // Void + return n, nil + } + return n, fmt.Errorf("union PathPaymentStrictReceiveResult has invalid Code (PathPaymentStrictReceiveResultCode) switch value '%d'", u.Code) +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (s PathPaymentStrictReceiveResult) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *PathPaymentStrictReceiveResult) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} + +var ( + _ encoding.BinaryMarshaler = (*PathPaymentStrictReceiveResult)(nil) + _ encoding.BinaryUnmarshaler = (*PathPaymentStrictReceiveResult)(nil) +) + +// xdrType signals that this type represents XDR values defined by this package. +func (s PathPaymentStrictReceiveResult) xdrType() {} + +var _ xdrType = (*PathPaymentStrictReceiveResult)(nil) + +// PathPaymentStrictSendResultCode is an XDR Enum defines as: +// +// enum PathPaymentStrictSendResultCode +// { +// // codes considered as "success" for the operation +// PATH_PAYMENT_STRICT_SEND_SUCCESS = 0, // success +// +// // codes considered as "failure" for the operation +// PATH_PAYMENT_STRICT_SEND_MALFORMED = -1, // bad input +// PATH_PAYMENT_STRICT_SEND_UNDERFUNDED = +// -2, // not enough funds in source account +// PATH_PAYMENT_STRICT_SEND_SRC_NO_TRUST = +// -3, // no trust line on source account +// PATH_PAYMENT_STRICT_SEND_SRC_NOT_AUTHORIZED = +// -4, // source not authorized to transfer +// PATH_PAYMENT_STRICT_SEND_NO_DESTINATION = +// -5, // destination account does not exist +// PATH_PAYMENT_STRICT_SEND_NO_TRUST = +// -6, // dest missing a trust line for asset +// PATH_PAYMENT_STRICT_SEND_NOT_AUTHORIZED = +// -7, // dest not authorized to hold asset +// PATH_PAYMENT_STRICT_SEND_LINE_FULL = -8, // dest would go above their limit +// PATH_PAYMENT_STRICT_SEND_NO_ISSUER = -9, // missing issuer on one asset +// PATH_PAYMENT_STRICT_SEND_TOO_FEW_OFFERS = +// -10, // not enough offers to satisfy path +// PATH_PAYMENT_STRICT_SEND_OFFER_CROSS_SELF = +// -11, // would cross one of its own offers +// PATH_PAYMENT_STRICT_SEND_UNDER_DESTMIN = -12 // could not satisfy destMin +// }; +type PathPaymentStrictSendResultCode int32 + +const ( + PathPaymentStrictSendResultCodePathPaymentStrictSendSuccess PathPaymentStrictSendResultCode = 0 + PathPaymentStrictSendResultCodePathPaymentStrictSendMalformed PathPaymentStrictSendResultCode = -1 + PathPaymentStrictSendResultCodePathPaymentStrictSendUnderfunded PathPaymentStrictSendResultCode = -2 + PathPaymentStrictSendResultCodePathPaymentStrictSendSrcNoTrust PathPaymentStrictSendResultCode = -3 + PathPaymentStrictSendResultCodePathPaymentStrictSendSrcNotAuthorized PathPaymentStrictSendResultCode = -4 + PathPaymentStrictSendResultCodePathPaymentStrictSendNoDestination PathPaymentStrictSendResultCode = -5 + PathPaymentStrictSendResultCodePathPaymentStrictSendNoTrust PathPaymentStrictSendResultCode = -6 + PathPaymentStrictSendResultCodePathPaymentStrictSendNotAuthorized PathPaymentStrictSendResultCode = -7 + PathPaymentStrictSendResultCodePathPaymentStrictSendLineFull PathPaymentStrictSendResultCode = -8 + PathPaymentStrictSendResultCodePathPaymentStrictSendNoIssuer PathPaymentStrictSendResultCode = -9 + PathPaymentStrictSendResultCodePathPaymentStrictSendTooFewOffers PathPaymentStrictSendResultCode = -10 + PathPaymentStrictSendResultCodePathPaymentStrictSendOfferCrossSelf PathPaymentStrictSendResultCode = -11 + PathPaymentStrictSendResultCodePathPaymentStrictSendUnderDestmin PathPaymentStrictSendResultCode = -12 +) + +var pathPaymentStrictSendResultCodeMap = map[int32]string{ + 0: "PathPaymentStrictSendResultCodePathPaymentStrictSendSuccess", + -1: "PathPaymentStrictSendResultCodePathPaymentStrictSendMalformed", + -2: "PathPaymentStrictSendResultCodePathPaymentStrictSendUnderfunded", + -3: "PathPaymentStrictSendResultCodePathPaymentStrictSendSrcNoTrust", + -4: "PathPaymentStrictSendResultCodePathPaymentStrictSendSrcNotAuthorized", + -5: "PathPaymentStrictSendResultCodePathPaymentStrictSendNoDestination", + -6: "PathPaymentStrictSendResultCodePathPaymentStrictSendNoTrust", + -7: "PathPaymentStrictSendResultCodePathPaymentStrictSendNotAuthorized", + -8: "PathPaymentStrictSendResultCodePathPaymentStrictSendLineFull", + -9: "PathPaymentStrictSendResultCodePathPaymentStrictSendNoIssuer", + -10: "PathPaymentStrictSendResultCodePathPaymentStrictSendTooFewOffers", + -11: "PathPaymentStrictSendResultCodePathPaymentStrictSendOfferCrossSelf", + -12: "PathPaymentStrictSendResultCodePathPaymentStrictSendUnderDestmin", +} + +// ValidEnum validates a proposed value for this enum. Implements +// the Enum interface for PathPaymentStrictSendResultCode +func (e PathPaymentStrictSendResultCode) ValidEnum(v int32) bool { + _, ok := pathPaymentStrictSendResultCodeMap[v] + return ok +} + +// String returns the name of `e` +func (e PathPaymentStrictSendResultCode) String() string { + name, _ := pathPaymentStrictSendResultCodeMap[int32(e)] + return name +} + +// EncodeTo encodes this value using the Encoder. +func (e PathPaymentStrictSendResultCode) EncodeTo(enc *xdr.Encoder) error { + if _, ok := pathPaymentStrictSendResultCodeMap[int32(e)]; !ok { + return fmt.Errorf("'%d' is not a valid PathPaymentStrictSendResultCode enum value", e) + } + _, err := enc.EncodeInt(int32(e)) + return err +} + +var _ decoderFrom = (*PathPaymentStrictSendResultCode)(nil) + +// DecodeFrom decodes this value using the Decoder. +func (e *PathPaymentStrictSendResultCode) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding PathPaymentStrictSendResultCode: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + v, n, err := d.DecodeInt() + if err != nil { + return n, fmt.Errorf("decoding PathPaymentStrictSendResultCode: %w", err) + } + if _, ok := pathPaymentStrictSendResultCodeMap[v]; !ok { + return n, fmt.Errorf("'%d' is not a valid PathPaymentStrictSendResultCode enum value", v) + } + *e = PathPaymentStrictSendResultCode(v) + return n, nil +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (s PathPaymentStrictSendResultCode) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *PathPaymentStrictSendResultCode) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} + +var ( + _ encoding.BinaryMarshaler = (*PathPaymentStrictSendResultCode)(nil) + _ encoding.BinaryUnmarshaler = (*PathPaymentStrictSendResultCode)(nil) +) + +// xdrType signals that this type represents XDR values defined by this package. +func (s PathPaymentStrictSendResultCode) xdrType() {} + +var _ xdrType = (*PathPaymentStrictSendResultCode)(nil) + +// PathPaymentStrictSendResultSuccess is an XDR NestedStruct defines as: +// +// struct +// { +// ClaimAtom offers<>; +// SimplePaymentResult last; +// } +type PathPaymentStrictSendResultSuccess struct { + Offers []ClaimAtom + Last SimplePaymentResult +} + +// EncodeTo encodes this value using the Encoder. +func (s *PathPaymentStrictSendResultSuccess) EncodeTo(e *xdr.Encoder) error { + var err error + if _, err = e.EncodeUint(uint32(len(s.Offers))); err != nil { + return err + } + for i := 0; i < len(s.Offers); i++ { + if err = s.Offers[i].EncodeTo(e); err != nil { + return err + } + } + if err = s.Last.EncodeTo(e); err != nil { return err } - if err = s.SendAmount.EncodeTo(e); err != nil { - return err + return nil +} + +var _ decoderFrom = (*PathPaymentStrictSendResultSuccess)(nil) + +// DecodeFrom decodes this value using the Decoder. +func (s *PathPaymentStrictSendResultSuccess) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding PathPaymentStrictSendResultSuccess: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + var err error + var n, nTmp int + var l uint32 + l, nTmp, err = d.DecodeUint() + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ClaimAtom: %w", err) + } + s.Offers = nil + if l > 0 { + if il, ok := d.InputLen(); ok && uint(il) < uint(l) { + return n, fmt.Errorf("decoding ClaimAtom: length (%d) exceeds remaining input length (%d)", l, il) + } + s.Offers = make([]ClaimAtom, l) + for i := uint32(0); i < l; i++ { + nTmp, err = s.Offers[i].DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ClaimAtom: %w", err) + } + } + } + nTmp, err = s.Last.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding SimplePaymentResult: %w", err) + } + return n, nil +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (s PathPaymentStrictSendResultSuccess) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *PathPaymentStrictSendResultSuccess) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} + +var ( + _ encoding.BinaryMarshaler = (*PathPaymentStrictSendResultSuccess)(nil) + _ encoding.BinaryUnmarshaler = (*PathPaymentStrictSendResultSuccess)(nil) +) + +// xdrType signals that this type represents XDR values defined by this package. +func (s PathPaymentStrictSendResultSuccess) xdrType() {} + +var _ xdrType = (*PathPaymentStrictSendResultSuccess)(nil) + +// PathPaymentStrictSendResult is an XDR Union defines as: +// +// union PathPaymentStrictSendResult switch (PathPaymentStrictSendResultCode code) +// { +// case PATH_PAYMENT_STRICT_SEND_SUCCESS: +// struct +// { +// ClaimAtom offers<>; +// SimplePaymentResult last; +// } success; +// case PATH_PAYMENT_STRICT_SEND_MALFORMED: +// case PATH_PAYMENT_STRICT_SEND_UNDERFUNDED: +// case PATH_PAYMENT_STRICT_SEND_SRC_NO_TRUST: +// case PATH_PAYMENT_STRICT_SEND_SRC_NOT_AUTHORIZED: +// case PATH_PAYMENT_STRICT_SEND_NO_DESTINATION: +// case PATH_PAYMENT_STRICT_SEND_NO_TRUST: +// case PATH_PAYMENT_STRICT_SEND_NOT_AUTHORIZED: +// case PATH_PAYMENT_STRICT_SEND_LINE_FULL: +// void; +// case PATH_PAYMENT_STRICT_SEND_NO_ISSUER: +// Asset noIssuer; // the asset that caused the error +// case PATH_PAYMENT_STRICT_SEND_TOO_FEW_OFFERS: +// case PATH_PAYMENT_STRICT_SEND_OFFER_CROSS_SELF: +// case PATH_PAYMENT_STRICT_SEND_UNDER_DESTMIN: +// void; +// }; +type PathPaymentStrictSendResult struct { + Code PathPaymentStrictSendResultCode + Success *PathPaymentStrictSendResultSuccess + NoIssuer *Asset +} + +// SwitchFieldName returns the field name in which this union's +// discriminant is stored +func (u PathPaymentStrictSendResult) SwitchFieldName() string { + return "Code" +} + +// ArmForSwitch returns which field name should be used for storing +// the value for an instance of PathPaymentStrictSendResult +func (u PathPaymentStrictSendResult) ArmForSwitch(sw int32) (string, bool) { + switch PathPaymentStrictSendResultCode(sw) { + case PathPaymentStrictSendResultCodePathPaymentStrictSendSuccess: + return "Success", true + case PathPaymentStrictSendResultCodePathPaymentStrictSendMalformed: + return "", true + case PathPaymentStrictSendResultCodePathPaymentStrictSendUnderfunded: + return "", true + case PathPaymentStrictSendResultCodePathPaymentStrictSendSrcNoTrust: + return "", true + case PathPaymentStrictSendResultCodePathPaymentStrictSendSrcNotAuthorized: + return "", true + case PathPaymentStrictSendResultCodePathPaymentStrictSendNoDestination: + return "", true + case PathPaymentStrictSendResultCodePathPaymentStrictSendNoTrust: + return "", true + case PathPaymentStrictSendResultCodePathPaymentStrictSendNotAuthorized: + return "", true + case PathPaymentStrictSendResultCodePathPaymentStrictSendLineFull: + return "", true + case PathPaymentStrictSendResultCodePathPaymentStrictSendNoIssuer: + return "NoIssuer", true + case PathPaymentStrictSendResultCodePathPaymentStrictSendTooFewOffers: + return "", true + case PathPaymentStrictSendResultCodePathPaymentStrictSendOfferCrossSelf: + return "", true + case PathPaymentStrictSendResultCodePathPaymentStrictSendUnderDestmin: + return "", true + } + return "-", false +} + +// NewPathPaymentStrictSendResult creates a new PathPaymentStrictSendResult. +func NewPathPaymentStrictSendResult(code PathPaymentStrictSendResultCode, value interface{}) (result PathPaymentStrictSendResult, err error) { + result.Code = code + switch PathPaymentStrictSendResultCode(code) { + case PathPaymentStrictSendResultCodePathPaymentStrictSendSuccess: + tv, ok := value.(PathPaymentStrictSendResultSuccess) + if !ok { + err = errors.New("invalid value, must be PathPaymentStrictSendResultSuccess") + return + } + result.Success = &tv + case PathPaymentStrictSendResultCodePathPaymentStrictSendMalformed: + // void + case PathPaymentStrictSendResultCodePathPaymentStrictSendUnderfunded: + // void + case PathPaymentStrictSendResultCodePathPaymentStrictSendSrcNoTrust: + // void + case PathPaymentStrictSendResultCodePathPaymentStrictSendSrcNotAuthorized: + // void + case PathPaymentStrictSendResultCodePathPaymentStrictSendNoDestination: + // void + case PathPaymentStrictSendResultCodePathPaymentStrictSendNoTrust: + // void + case PathPaymentStrictSendResultCodePathPaymentStrictSendNotAuthorized: + // void + case PathPaymentStrictSendResultCodePathPaymentStrictSendLineFull: + // void + case PathPaymentStrictSendResultCodePathPaymentStrictSendNoIssuer: + tv, ok := value.(Asset) + if !ok { + err = errors.New("invalid value, must be Asset") + return + } + result.NoIssuer = &tv + case PathPaymentStrictSendResultCodePathPaymentStrictSendTooFewOffers: + // void + case PathPaymentStrictSendResultCodePathPaymentStrictSendOfferCrossSelf: + // void + case PathPaymentStrictSendResultCodePathPaymentStrictSendUnderDestmin: + // void + } + return +} + +// MustSuccess retrieves the Success value from the union, +// panicing if the value is not set. +func (u PathPaymentStrictSendResult) MustSuccess() PathPaymentStrictSendResultSuccess { + val, ok := u.GetSuccess() + + if !ok { + panic("arm Success is not set") } - if err = s.Destination.EncodeTo(e); err != nil { - return err + + return val +} + +// GetSuccess retrieves the Success value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u PathPaymentStrictSendResult) GetSuccess() (result PathPaymentStrictSendResultSuccess, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Code)) + + if armName == "Success" { + result = *u.Success + ok = true } - if err = s.DestAsset.EncodeTo(e); err != nil { - return err + + return +} + +// MustNoIssuer retrieves the NoIssuer value from the union, +// panicing if the value is not set. +func (u PathPaymentStrictSendResult) MustNoIssuer() Asset { + val, ok := u.GetNoIssuer() + + if !ok { + panic("arm NoIssuer is not set") } - if err = s.DestMin.EncodeTo(e); err != nil { - return err + + return val +} + +// GetNoIssuer retrieves the NoIssuer value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u PathPaymentStrictSendResult) GetNoIssuer() (result Asset, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Code)) + + if armName == "NoIssuer" { + result = *u.NoIssuer + ok = true } - if _, err = e.EncodeUint(uint32(len(s.Path))); err != nil { + + return +} + +// EncodeTo encodes this value using the Encoder. +func (u PathPaymentStrictSendResult) EncodeTo(e *xdr.Encoder) error { + var err error + if err = u.Code.EncodeTo(e); err != nil { return err } - for i := 0; i < len(s.Path); i++ { - if err = s.Path[i].EncodeTo(e); err != nil { + switch PathPaymentStrictSendResultCode(u.Code) { + case PathPaymentStrictSendResultCodePathPaymentStrictSendSuccess: + if err = (*u.Success).EncodeTo(e); err != nil { + return err + } + return nil + case PathPaymentStrictSendResultCodePathPaymentStrictSendMalformed: + // Void + return nil + case PathPaymentStrictSendResultCodePathPaymentStrictSendUnderfunded: + // Void + return nil + case PathPaymentStrictSendResultCodePathPaymentStrictSendSrcNoTrust: + // Void + return nil + case PathPaymentStrictSendResultCodePathPaymentStrictSendSrcNotAuthorized: + // Void + return nil + case PathPaymentStrictSendResultCodePathPaymentStrictSendNoDestination: + // Void + return nil + case PathPaymentStrictSendResultCodePathPaymentStrictSendNoTrust: + // Void + return nil + case PathPaymentStrictSendResultCodePathPaymentStrictSendNotAuthorized: + // Void + return nil + case PathPaymentStrictSendResultCodePathPaymentStrictSendLineFull: + // Void + return nil + case PathPaymentStrictSendResultCodePathPaymentStrictSendNoIssuer: + if err = (*u.NoIssuer).EncodeTo(e); err != nil { return err } + return nil + case PathPaymentStrictSendResultCodePathPaymentStrictSendTooFewOffers: + // Void + return nil + case PathPaymentStrictSendResultCodePathPaymentStrictSendOfferCrossSelf: + // Void + return nil + case PathPaymentStrictSendResultCodePathPaymentStrictSendUnderDestmin: + // Void + return nil } - return nil + return fmt.Errorf("Code (PathPaymentStrictSendResultCode) switch value '%d' is not valid for union PathPaymentStrictSendResult", u.Code) } -var _ decoderFrom = (*PathPaymentStrictSendOp)(nil) +var _ decoderFrom = (*PathPaymentStrictSendResult)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *PathPaymentStrictSendOp) DecodeFrom(d *xdr.Decoder) (int, error) { +func (u *PathPaymentStrictSendResult) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding PathPaymentStrictSendResult: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = s.SendAsset.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Asset: %s", err) - } - nTmp, err = s.SendAmount.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Int64: %s", err) - } - nTmp, err = s.Destination.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding MuxedAccount: %s", err) - } - nTmp, err = s.DestAsset.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Asset: %s", err) - } - nTmp, err = s.DestMin.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Int64: %s", err) - } - var l uint32 - l, nTmp, err = d.DecodeUint() + nTmp, err = u.Code.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Asset: %s", err) - } - if l > 5 { - return n, fmt.Errorf("decoding Asset: data size (%d) exceeds size limit (5)", l) + return n, fmt.Errorf("decoding PathPaymentStrictSendResultCode: %w", err) } - s.Path = nil - if l > 0 { - s.Path = make([]Asset, l) - for i := uint32(0); i < l; i++ { - nTmp, err = s.Path[i].DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Asset: %s", err) - } + switch PathPaymentStrictSendResultCode(u.Code) { + case PathPaymentStrictSendResultCodePathPaymentStrictSendSuccess: + u.Success = new(PathPaymentStrictSendResultSuccess) + nTmp, err = (*u.Success).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding PathPaymentStrictSendResultSuccess: %w", err) + } + return n, nil + case PathPaymentStrictSendResultCodePathPaymentStrictSendMalformed: + // Void + return n, nil + case PathPaymentStrictSendResultCodePathPaymentStrictSendUnderfunded: + // Void + return n, nil + case PathPaymentStrictSendResultCodePathPaymentStrictSendSrcNoTrust: + // Void + return n, nil + case PathPaymentStrictSendResultCodePathPaymentStrictSendSrcNotAuthorized: + // Void + return n, nil + case PathPaymentStrictSendResultCodePathPaymentStrictSendNoDestination: + // Void + return n, nil + case PathPaymentStrictSendResultCodePathPaymentStrictSendNoTrust: + // Void + return n, nil + case PathPaymentStrictSendResultCodePathPaymentStrictSendNotAuthorized: + // Void + return n, nil + case PathPaymentStrictSendResultCodePathPaymentStrictSendLineFull: + // Void + return n, nil + case PathPaymentStrictSendResultCodePathPaymentStrictSendNoIssuer: + u.NoIssuer = new(Asset) + nTmp, err = (*u.NoIssuer).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Asset: %w", err) } + return n, nil + case PathPaymentStrictSendResultCodePathPaymentStrictSendTooFewOffers: + // Void + return n, nil + case PathPaymentStrictSendResultCodePathPaymentStrictSendOfferCrossSelf: + // Void + return n, nil + case PathPaymentStrictSendResultCodePathPaymentStrictSendUnderDestmin: + // Void + return n, nil } - return n, nil + return n, fmt.Errorf("union PathPaymentStrictSendResult has invalid Code (PathPaymentStrictSendResultCode) switch value '%d'", u.Code) } // MarshalBinary implements encoding.BinaryMarshaler. -func (s PathPaymentStrictSendOp) MarshalBinary() ([]byte, error) { +func (s PathPaymentStrictSendResult) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -19096,101 +34835,221 @@ func (s PathPaymentStrictSendOp) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *PathPaymentStrictSendOp) UnmarshalBinary(inp []byte) error { +func (s *PathPaymentStrictSendResult) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*PathPaymentStrictSendOp)(nil) - _ encoding.BinaryUnmarshaler = (*PathPaymentStrictSendOp)(nil) + _ encoding.BinaryMarshaler = (*PathPaymentStrictSendResult)(nil) + _ encoding.BinaryUnmarshaler = (*PathPaymentStrictSendResult)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s PathPaymentStrictSendOp) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s PathPaymentStrictSendResult) xdrType() {} -var _ xdrType = (*PathPaymentStrictSendOp)(nil) +var _ xdrType = (*PathPaymentStrictSendResult)(nil) -// ManageSellOfferOp is an XDR Struct defines as: +// ManageSellOfferResultCode is an XDR Enum defines as: // -// struct ManageSellOfferOp +// enum ManageSellOfferResultCode // { -// Asset selling; -// Asset buying; -// int64 amount; // amount being sold. if set to 0, delete the offer -// Price price; // price of thing being sold in terms of what you are buying +// // codes considered as "success" for the operation +// MANAGE_SELL_OFFER_SUCCESS = 0, // -// // 0=create a new offer, otherwise edit an existing offer -// int64 offerID; +// // codes considered as "failure" for the operation +// MANAGE_SELL_OFFER_MALFORMED = -1, // generated offer would be invalid +// MANAGE_SELL_OFFER_SELL_NO_TRUST = +// -2, // no trust line for what we're selling +// MANAGE_SELL_OFFER_BUY_NO_TRUST = -3, // no trust line for what we're buying +// MANAGE_SELL_OFFER_SELL_NOT_AUTHORIZED = -4, // not authorized to sell +// MANAGE_SELL_OFFER_BUY_NOT_AUTHORIZED = -5, // not authorized to buy +// MANAGE_SELL_OFFER_LINE_FULL = -6, // can't receive more of what it's buying +// MANAGE_SELL_OFFER_UNDERFUNDED = -7, // doesn't hold what it's trying to sell +// MANAGE_SELL_OFFER_CROSS_SELF = +// -8, // would cross an offer from the same user +// MANAGE_SELL_OFFER_SELL_NO_ISSUER = -9, // no issuer for what we're selling +// MANAGE_SELL_OFFER_BUY_NO_ISSUER = -10, // no issuer for what we're buying +// +// // update errors +// MANAGE_SELL_OFFER_NOT_FOUND = +// -11, // offerID does not match an existing offer +// +// MANAGE_SELL_OFFER_LOW_RESERVE = +// -12 // not enough funds to create a new Offer // }; -type ManageSellOfferOp struct { - Selling Asset - Buying Asset - Amount Int64 - Price Price - OfferId Int64 +type ManageSellOfferResultCode int32 + +const ( + ManageSellOfferResultCodeManageSellOfferSuccess ManageSellOfferResultCode = 0 + ManageSellOfferResultCodeManageSellOfferMalformed ManageSellOfferResultCode = -1 + ManageSellOfferResultCodeManageSellOfferSellNoTrust ManageSellOfferResultCode = -2 + ManageSellOfferResultCodeManageSellOfferBuyNoTrust ManageSellOfferResultCode = -3 + ManageSellOfferResultCodeManageSellOfferSellNotAuthorized ManageSellOfferResultCode = -4 + ManageSellOfferResultCodeManageSellOfferBuyNotAuthorized ManageSellOfferResultCode = -5 + ManageSellOfferResultCodeManageSellOfferLineFull ManageSellOfferResultCode = -6 + ManageSellOfferResultCodeManageSellOfferUnderfunded ManageSellOfferResultCode = -7 + ManageSellOfferResultCodeManageSellOfferCrossSelf ManageSellOfferResultCode = -8 + ManageSellOfferResultCodeManageSellOfferSellNoIssuer ManageSellOfferResultCode = -9 + ManageSellOfferResultCodeManageSellOfferBuyNoIssuer ManageSellOfferResultCode = -10 + ManageSellOfferResultCodeManageSellOfferNotFound ManageSellOfferResultCode = -11 + ManageSellOfferResultCodeManageSellOfferLowReserve ManageSellOfferResultCode = -12 +) + +var manageSellOfferResultCodeMap = map[int32]string{ + 0: "ManageSellOfferResultCodeManageSellOfferSuccess", + -1: "ManageSellOfferResultCodeManageSellOfferMalformed", + -2: "ManageSellOfferResultCodeManageSellOfferSellNoTrust", + -3: "ManageSellOfferResultCodeManageSellOfferBuyNoTrust", + -4: "ManageSellOfferResultCodeManageSellOfferSellNotAuthorized", + -5: "ManageSellOfferResultCodeManageSellOfferBuyNotAuthorized", + -6: "ManageSellOfferResultCodeManageSellOfferLineFull", + -7: "ManageSellOfferResultCodeManageSellOfferUnderfunded", + -8: "ManageSellOfferResultCodeManageSellOfferCrossSelf", + -9: "ManageSellOfferResultCodeManageSellOfferSellNoIssuer", + -10: "ManageSellOfferResultCodeManageSellOfferBuyNoIssuer", + -11: "ManageSellOfferResultCodeManageSellOfferNotFound", + -12: "ManageSellOfferResultCodeManageSellOfferLowReserve", +} + +// ValidEnum validates a proposed value for this enum. Implements +// the Enum interface for ManageSellOfferResultCode +func (e ManageSellOfferResultCode) ValidEnum(v int32) bool { + _, ok := manageSellOfferResultCodeMap[v] + return ok +} + +// String returns the name of `e` +func (e ManageSellOfferResultCode) String() string { + name, _ := manageSellOfferResultCodeMap[int32(e)] + return name } // EncodeTo encodes this value using the Encoder. -func (s *ManageSellOfferOp) EncodeTo(e *xdr.Encoder) error { - var err error - if err = s.Selling.EncodeTo(e); err != nil { - return err +func (e ManageSellOfferResultCode) EncodeTo(enc *xdr.Encoder) error { + if _, ok := manageSellOfferResultCodeMap[int32(e)]; !ok { + return fmt.Errorf("'%d' is not a valid ManageSellOfferResultCode enum value", e) } - if err = s.Buying.EncodeTo(e); err != nil { - return err + _, err := enc.EncodeInt(int32(e)) + return err +} + +var _ decoderFrom = (*ManageSellOfferResultCode)(nil) + +// DecodeFrom decodes this value using the Decoder. +func (e *ManageSellOfferResultCode) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding ManageSellOfferResultCode: %w", ErrMaxDecodingDepthReached) } - if err = s.Amount.EncodeTo(e); err != nil { - return err + maxDepth -= 1 + v, n, err := d.DecodeInt() + if err != nil { + return n, fmt.Errorf("decoding ManageSellOfferResultCode: %w", err) } - if err = s.Price.EncodeTo(e); err != nil { - return err + if _, ok := manageSellOfferResultCodeMap[v]; !ok { + return n, fmt.Errorf("'%d' is not a valid ManageSellOfferResultCode enum value", v) } - if err = s.OfferId.EncodeTo(e); err != nil { - return err + *e = ManageSellOfferResultCode(v) + return n, nil +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (s ManageSellOfferResultCode) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *ManageSellOfferResultCode) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} + +var ( + _ encoding.BinaryMarshaler = (*ManageSellOfferResultCode)(nil) + _ encoding.BinaryUnmarshaler = (*ManageSellOfferResultCode)(nil) +) + +// xdrType signals that this type represents XDR values defined by this package. +func (s ManageSellOfferResultCode) xdrType() {} + +var _ xdrType = (*ManageSellOfferResultCode)(nil) + +// ManageOfferEffect is an XDR Enum defines as: +// +// enum ManageOfferEffect +// { +// MANAGE_OFFER_CREATED = 0, +// MANAGE_OFFER_UPDATED = 1, +// MANAGE_OFFER_DELETED = 2 +// }; +type ManageOfferEffect int32 + +const ( + ManageOfferEffectManageOfferCreated ManageOfferEffect = 0 + ManageOfferEffectManageOfferUpdated ManageOfferEffect = 1 + ManageOfferEffectManageOfferDeleted ManageOfferEffect = 2 +) + +var manageOfferEffectMap = map[int32]string{ + 0: "ManageOfferEffectManageOfferCreated", + 1: "ManageOfferEffectManageOfferUpdated", + 2: "ManageOfferEffectManageOfferDeleted", +} + +// ValidEnum validates a proposed value for this enum. Implements +// the Enum interface for ManageOfferEffect +func (e ManageOfferEffect) ValidEnum(v int32) bool { + _, ok := manageOfferEffectMap[v] + return ok +} + +// String returns the name of `e` +func (e ManageOfferEffect) String() string { + name, _ := manageOfferEffectMap[int32(e)] + return name +} + +// EncodeTo encodes this value using the Encoder. +func (e ManageOfferEffect) EncodeTo(enc *xdr.Encoder) error { + if _, ok := manageOfferEffectMap[int32(e)]; !ok { + return fmt.Errorf("'%d' is not a valid ManageOfferEffect enum value", e) } - return nil + _, err := enc.EncodeInt(int32(e)) + return err } -var _ decoderFrom = (*ManageSellOfferOp)(nil) +var _ decoderFrom = (*ManageOfferEffect)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *ManageSellOfferOp) DecodeFrom(d *xdr.Decoder) (int, error) { - var err error - var n, nTmp int - nTmp, err = s.Selling.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Asset: %s", err) - } - nTmp, err = s.Buying.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Asset: %s", err) - } - nTmp, err = s.Amount.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Int64: %s", err) +func (e *ManageOfferEffect) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding ManageOfferEffect: %w", ErrMaxDecodingDepthReached) } - nTmp, err = s.Price.DecodeFrom(d) - n += nTmp + maxDepth -= 1 + v, n, err := d.DecodeInt() if err != nil { - return n, fmt.Errorf("decoding Price: %s", err) + return n, fmt.Errorf("decoding ManageOfferEffect: %w", err) } - nTmp, err = s.OfferId.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Int64: %s", err) + if _, ok := manageOfferEffectMap[v]; !ok { + return n, fmt.Errorf("'%d' is not a valid ManageOfferEffect enum value", v) } + *e = ManageOfferEffect(v) return n, nil } // MarshalBinary implements encoding.BinaryMarshaler. -func (s ManageSellOfferOp) MarshalBinary() ([]byte, error) { +func (s ManageOfferEffect) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -19198,102 +35057,174 @@ func (s ManageSellOfferOp) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *ManageSellOfferOp) UnmarshalBinary(inp []byte) error { +func (s *ManageOfferEffect) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*ManageSellOfferOp)(nil) - _ encoding.BinaryUnmarshaler = (*ManageSellOfferOp)(nil) + _ encoding.BinaryMarshaler = (*ManageOfferEffect)(nil) + _ encoding.BinaryUnmarshaler = (*ManageOfferEffect)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s ManageSellOfferOp) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s ManageOfferEffect) xdrType() {} -var _ xdrType = (*ManageSellOfferOp)(nil) +var _ xdrType = (*ManageOfferEffect)(nil) -// ManageBuyOfferOp is an XDR Struct defines as: -// -// struct ManageBuyOfferOp -// { -// Asset selling; -// Asset buying; -// int64 buyAmount; // amount being bought. if set to 0, delete the offer -// Price price; // price of thing being bought in terms of what you are -// // selling +// ManageOfferSuccessResultOffer is an XDR NestedUnion defines as: // -// // 0=create a new offer, otherwise edit an existing offer -// int64 offerID; -// }; -type ManageBuyOfferOp struct { - Selling Asset - Buying Asset - BuyAmount Int64 - Price Price - OfferId Int64 +// union switch (ManageOfferEffect effect) +// { +// case MANAGE_OFFER_CREATED: +// case MANAGE_OFFER_UPDATED: +// OfferEntry offer; +// case MANAGE_OFFER_DELETED: +// void; +// } +type ManageOfferSuccessResultOffer struct { + Effect ManageOfferEffect + Offer *OfferEntry +} + +// SwitchFieldName returns the field name in which this union's +// discriminant is stored +func (u ManageOfferSuccessResultOffer) SwitchFieldName() string { + return "Effect" +} + +// ArmForSwitch returns which field name should be used for storing +// the value for an instance of ManageOfferSuccessResultOffer +func (u ManageOfferSuccessResultOffer) ArmForSwitch(sw int32) (string, bool) { + switch ManageOfferEffect(sw) { + case ManageOfferEffectManageOfferCreated: + return "Offer", true + case ManageOfferEffectManageOfferUpdated: + return "Offer", true + case ManageOfferEffectManageOfferDeleted: + return "", true + } + return "-", false +} + +// NewManageOfferSuccessResultOffer creates a new ManageOfferSuccessResultOffer. +func NewManageOfferSuccessResultOffer(effect ManageOfferEffect, value interface{}) (result ManageOfferSuccessResultOffer, err error) { + result.Effect = effect + switch ManageOfferEffect(effect) { + case ManageOfferEffectManageOfferCreated: + tv, ok := value.(OfferEntry) + if !ok { + err = errors.New("invalid value, must be OfferEntry") + return + } + result.Offer = &tv + case ManageOfferEffectManageOfferUpdated: + tv, ok := value.(OfferEntry) + if !ok { + err = errors.New("invalid value, must be OfferEntry") + return + } + result.Offer = &tv + case ManageOfferEffectManageOfferDeleted: + // void + } + return +} + +// MustOffer retrieves the Offer value from the union, +// panicing if the value is not set. +func (u ManageOfferSuccessResultOffer) MustOffer() OfferEntry { + val, ok := u.GetOffer() + + if !ok { + panic("arm Offer is not set") + } + + return val +} + +// GetOffer retrieves the Offer value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u ManageOfferSuccessResultOffer) GetOffer() (result OfferEntry, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Effect)) + + if armName == "Offer" { + result = *u.Offer + ok = true + } + + return } // EncodeTo encodes this value using the Encoder. -func (s *ManageBuyOfferOp) EncodeTo(e *xdr.Encoder) error { +func (u ManageOfferSuccessResultOffer) EncodeTo(e *xdr.Encoder) error { var err error - if err = s.Selling.EncodeTo(e); err != nil { - return err - } - if err = s.Buying.EncodeTo(e); err != nil { - return err - } - if err = s.BuyAmount.EncodeTo(e); err != nil { - return err - } - if err = s.Price.EncodeTo(e); err != nil { + if err = u.Effect.EncodeTo(e); err != nil { return err } - if err = s.OfferId.EncodeTo(e); err != nil { - return err + switch ManageOfferEffect(u.Effect) { + case ManageOfferEffectManageOfferCreated: + if err = (*u.Offer).EncodeTo(e); err != nil { + return err + } + return nil + case ManageOfferEffectManageOfferUpdated: + if err = (*u.Offer).EncodeTo(e); err != nil { + return err + } + return nil + case ManageOfferEffectManageOfferDeleted: + // Void + return nil } - return nil + return fmt.Errorf("Effect (ManageOfferEffect) switch value '%d' is not valid for union ManageOfferSuccessResultOffer", u.Effect) } -var _ decoderFrom = (*ManageBuyOfferOp)(nil) +var _ decoderFrom = (*ManageOfferSuccessResultOffer)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *ManageBuyOfferOp) DecodeFrom(d *xdr.Decoder) (int, error) { +func (u *ManageOfferSuccessResultOffer) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding ManageOfferSuccessResultOffer: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = s.Selling.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Asset: %s", err) - } - nTmp, err = s.Buying.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Asset: %s", err) - } - nTmp, err = s.BuyAmount.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Int64: %s", err) - } - nTmp, err = s.Price.DecodeFrom(d) + nTmp, err = u.Effect.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Price: %s", err) + return n, fmt.Errorf("decoding ManageOfferEffect: %w", err) } - nTmp, err = s.OfferId.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Int64: %s", err) + switch ManageOfferEffect(u.Effect) { + case ManageOfferEffectManageOfferCreated: + u.Offer = new(OfferEntry) + nTmp, err = (*u.Offer).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding OfferEntry: %w", err) + } + return n, nil + case ManageOfferEffectManageOfferUpdated: + u.Offer = new(OfferEntry) + nTmp, err = (*u.Offer).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding OfferEntry: %w", err) + } + return n, nil + case ManageOfferEffectManageOfferDeleted: + // Void + return n, nil } - return n, nil + return n, fmt.Errorf("union ManageOfferSuccessResultOffer has invalid Effect (ManageOfferEffect) switch value '%d'", u.Effect) } // MarshalBinary implements encoding.BinaryMarshaler. -func (s ManageBuyOfferOp) MarshalBinary() ([]byte, error) { +func (s ManageOfferSuccessResultOffer) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -19301,89 +35232,104 @@ func (s ManageBuyOfferOp) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *ManageBuyOfferOp) UnmarshalBinary(inp []byte) error { +func (s *ManageOfferSuccessResultOffer) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*ManageBuyOfferOp)(nil) - _ encoding.BinaryUnmarshaler = (*ManageBuyOfferOp)(nil) + _ encoding.BinaryMarshaler = (*ManageOfferSuccessResultOffer)(nil) + _ encoding.BinaryUnmarshaler = (*ManageOfferSuccessResultOffer)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s ManageBuyOfferOp) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s ManageOfferSuccessResultOffer) xdrType() {} -var _ xdrType = (*ManageBuyOfferOp)(nil) +var _ xdrType = (*ManageOfferSuccessResultOffer)(nil) -// CreatePassiveSellOfferOp is an XDR Struct defines as: +// ManageOfferSuccessResult is an XDR Struct defines as: // -// struct CreatePassiveSellOfferOp +// struct ManageOfferSuccessResult // { -// Asset selling; // A -// Asset buying; // B -// int64 amount; // amount taker gets -// Price price; // cost of A in terms of B +// // offers that got claimed while creating this offer +// ClaimAtom offersClaimed<>; +// +// union switch (ManageOfferEffect effect) +// { +// case MANAGE_OFFER_CREATED: +// case MANAGE_OFFER_UPDATED: +// OfferEntry offer; +// case MANAGE_OFFER_DELETED: +// void; +// } +// offer; // }; -type CreatePassiveSellOfferOp struct { - Selling Asset - Buying Asset - Amount Int64 - Price Price +type ManageOfferSuccessResult struct { + OffersClaimed []ClaimAtom + Offer ManageOfferSuccessResultOffer } // EncodeTo encodes this value using the Encoder. -func (s *CreatePassiveSellOfferOp) EncodeTo(e *xdr.Encoder) error { +func (s *ManageOfferSuccessResult) EncodeTo(e *xdr.Encoder) error { var err error - if err = s.Selling.EncodeTo(e); err != nil { - return err - } - if err = s.Buying.EncodeTo(e); err != nil { + if _, err = e.EncodeUint(uint32(len(s.OffersClaimed))); err != nil { return err } - if err = s.Amount.EncodeTo(e); err != nil { - return err + for i := 0; i < len(s.OffersClaimed); i++ { + if err = s.OffersClaimed[i].EncodeTo(e); err != nil { + return err + } } - if err = s.Price.EncodeTo(e); err != nil { + if err = s.Offer.EncodeTo(e); err != nil { return err } return nil } -var _ decoderFrom = (*CreatePassiveSellOfferOp)(nil) +var _ decoderFrom = (*ManageOfferSuccessResult)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *CreatePassiveSellOfferOp) DecodeFrom(d *xdr.Decoder) (int, error) { +func (s *ManageOfferSuccessResult) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding ManageOfferSuccessResult: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = s.Selling.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Asset: %s", err) - } - nTmp, err = s.Buying.DecodeFrom(d) + var l uint32 + l, nTmp, err = d.DecodeUint() n += nTmp if err != nil { - return n, fmt.Errorf("decoding Asset: %s", err) + return n, fmt.Errorf("decoding ClaimAtom: %w", err) } - nTmp, err = s.Amount.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Int64: %s", err) + s.OffersClaimed = nil + if l > 0 { + if il, ok := d.InputLen(); ok && uint(il) < uint(l) { + return n, fmt.Errorf("decoding ClaimAtom: length (%d) exceeds remaining input length (%d)", l, il) + } + s.OffersClaimed = make([]ClaimAtom, l) + for i := uint32(0); i < l; i++ { + nTmp, err = s.OffersClaimed[i].DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ClaimAtom: %w", err) + } + } } - nTmp, err = s.Price.DecodeFrom(d) + nTmp, err = s.Offer.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Price: %s", err) + return n, fmt.Errorf("decoding ManageOfferSuccessResultOffer: %w", err) } return n, nil } // MarshalBinary implements encoding.BinaryMarshaler. -func (s CreatePassiveSellOfferOp) MarshalBinary() ([]byte, error) { +func (s ManageOfferSuccessResult) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -19391,273 +35337,272 @@ func (s CreatePassiveSellOfferOp) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *CreatePassiveSellOfferOp) UnmarshalBinary(inp []byte) error { +func (s *ManageOfferSuccessResult) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*CreatePassiveSellOfferOp)(nil) - _ encoding.BinaryUnmarshaler = (*CreatePassiveSellOfferOp)(nil) + _ encoding.BinaryMarshaler = (*ManageOfferSuccessResult)(nil) + _ encoding.BinaryUnmarshaler = (*ManageOfferSuccessResult)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s CreatePassiveSellOfferOp) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s ManageOfferSuccessResult) xdrType() {} -var _ xdrType = (*CreatePassiveSellOfferOp)(nil) +var _ xdrType = (*ManageOfferSuccessResult)(nil) -// SetOptionsOp is an XDR Struct defines as: +// ManageSellOfferResult is an XDR Union defines as: // -// struct SetOptionsOp +// union ManageSellOfferResult switch (ManageSellOfferResultCode code) // { -// AccountID* inflationDest; // sets the inflation destination -// -// uint32* clearFlags; // which flags to clear -// uint32* setFlags; // which flags to set -// -// // account threshold manipulation -// uint32* masterWeight; // weight of the master account -// uint32* lowThreshold; -// uint32* medThreshold; -// uint32* highThreshold; -// -// string32* homeDomain; // sets the home domain -// -// // Add, update or remove a signer for the account -// // signer is deleted if the weight is 0 -// Signer* signer; +// case MANAGE_SELL_OFFER_SUCCESS: +// ManageOfferSuccessResult success; +// case MANAGE_SELL_OFFER_MALFORMED: +// case MANAGE_SELL_OFFER_SELL_NO_TRUST: +// case MANAGE_SELL_OFFER_BUY_NO_TRUST: +// case MANAGE_SELL_OFFER_SELL_NOT_AUTHORIZED: +// case MANAGE_SELL_OFFER_BUY_NOT_AUTHORIZED: +// case MANAGE_SELL_OFFER_LINE_FULL: +// case MANAGE_SELL_OFFER_UNDERFUNDED: +// case MANAGE_SELL_OFFER_CROSS_SELF: +// case MANAGE_SELL_OFFER_SELL_NO_ISSUER: +// case MANAGE_SELL_OFFER_BUY_NO_ISSUER: +// case MANAGE_SELL_OFFER_NOT_FOUND: +// case MANAGE_SELL_OFFER_LOW_RESERVE: +// void; // }; -type SetOptionsOp struct { - InflationDest *AccountId - ClearFlags *Uint32 - SetFlags *Uint32 - MasterWeight *Uint32 - LowThreshold *Uint32 - MedThreshold *Uint32 - HighThreshold *Uint32 - HomeDomain *String32 - Signer *Signer +type ManageSellOfferResult struct { + Code ManageSellOfferResultCode + Success *ManageOfferSuccessResult } -// EncodeTo encodes this value using the Encoder. -func (s *SetOptionsOp) EncodeTo(e *xdr.Encoder) error { - var err error - if _, err = e.EncodeBool(s.InflationDest != nil); err != nil { - return err - } - if s.InflationDest != nil { - if err = (*s.InflationDest).EncodeTo(e); err != nil { - return err - } - } - if _, err = e.EncodeBool(s.ClearFlags != nil); err != nil { - return err - } - if s.ClearFlags != nil { - if err = (*s.ClearFlags).EncodeTo(e); err != nil { - return err - } - } - if _, err = e.EncodeBool(s.SetFlags != nil); err != nil { - return err - } - if s.SetFlags != nil { - if err = (*s.SetFlags).EncodeTo(e); err != nil { - return err - } - } - if _, err = e.EncodeBool(s.MasterWeight != nil); err != nil { - return err - } - if s.MasterWeight != nil { - if err = (*s.MasterWeight).EncodeTo(e); err != nil { - return err - } - } - if _, err = e.EncodeBool(s.LowThreshold != nil); err != nil { - return err - } - if s.LowThreshold != nil { - if err = (*s.LowThreshold).EncodeTo(e); err != nil { - return err - } - } - if _, err = e.EncodeBool(s.MedThreshold != nil); err != nil { - return err - } - if s.MedThreshold != nil { - if err = (*s.MedThreshold).EncodeTo(e); err != nil { - return err - } - } - if _, err = e.EncodeBool(s.HighThreshold != nil); err != nil { - return err - } - if s.HighThreshold != nil { - if err = (*s.HighThreshold).EncodeTo(e); err != nil { - return err - } - } - if _, err = e.EncodeBool(s.HomeDomain != nil); err != nil { - return err - } - if s.HomeDomain != nil { - if err = (*s.HomeDomain).EncodeTo(e); err != nil { - return err - } - } - if _, err = e.EncodeBool(s.Signer != nil); err != nil { - return err +// SwitchFieldName returns the field name in which this union's +// discriminant is stored +func (u ManageSellOfferResult) SwitchFieldName() string { + return "Code" +} + +// ArmForSwitch returns which field name should be used for storing +// the value for an instance of ManageSellOfferResult +func (u ManageSellOfferResult) ArmForSwitch(sw int32) (string, bool) { + switch ManageSellOfferResultCode(sw) { + case ManageSellOfferResultCodeManageSellOfferSuccess: + return "Success", true + case ManageSellOfferResultCodeManageSellOfferMalformed: + return "", true + case ManageSellOfferResultCodeManageSellOfferSellNoTrust: + return "", true + case ManageSellOfferResultCodeManageSellOfferBuyNoTrust: + return "", true + case ManageSellOfferResultCodeManageSellOfferSellNotAuthorized: + return "", true + case ManageSellOfferResultCodeManageSellOfferBuyNotAuthorized: + return "", true + case ManageSellOfferResultCodeManageSellOfferLineFull: + return "", true + case ManageSellOfferResultCodeManageSellOfferUnderfunded: + return "", true + case ManageSellOfferResultCodeManageSellOfferCrossSelf: + return "", true + case ManageSellOfferResultCodeManageSellOfferSellNoIssuer: + return "", true + case ManageSellOfferResultCodeManageSellOfferBuyNoIssuer: + return "", true + case ManageSellOfferResultCodeManageSellOfferNotFound: + return "", true + case ManageSellOfferResultCodeManageSellOfferLowReserve: + return "", true } - if s.Signer != nil { - if err = (*s.Signer).EncodeTo(e); err != nil { - return err + return "-", false +} + +// NewManageSellOfferResult creates a new ManageSellOfferResult. +func NewManageSellOfferResult(code ManageSellOfferResultCode, value interface{}) (result ManageSellOfferResult, err error) { + result.Code = code + switch ManageSellOfferResultCode(code) { + case ManageSellOfferResultCodeManageSellOfferSuccess: + tv, ok := value.(ManageOfferSuccessResult) + if !ok { + err = errors.New("invalid value, must be ManageOfferSuccessResult") + return } + result.Success = &tv + case ManageSellOfferResultCodeManageSellOfferMalformed: + // void + case ManageSellOfferResultCodeManageSellOfferSellNoTrust: + // void + case ManageSellOfferResultCodeManageSellOfferBuyNoTrust: + // void + case ManageSellOfferResultCodeManageSellOfferSellNotAuthorized: + // void + case ManageSellOfferResultCodeManageSellOfferBuyNotAuthorized: + // void + case ManageSellOfferResultCodeManageSellOfferLineFull: + // void + case ManageSellOfferResultCodeManageSellOfferUnderfunded: + // void + case ManageSellOfferResultCodeManageSellOfferCrossSelf: + // void + case ManageSellOfferResultCodeManageSellOfferSellNoIssuer: + // void + case ManageSellOfferResultCodeManageSellOfferBuyNoIssuer: + // void + case ManageSellOfferResultCodeManageSellOfferNotFound: + // void + case ManageSellOfferResultCodeManageSellOfferLowReserve: + // void } - return nil + return } -var _ decoderFrom = (*SetOptionsOp)(nil) +// MustSuccess retrieves the Success value from the union, +// panicing if the value is not set. +func (u ManageSellOfferResult) MustSuccess() ManageOfferSuccessResult { + val, ok := u.GetSuccess() -// DecodeFrom decodes this value using the Decoder. -func (s *SetOptionsOp) DecodeFrom(d *xdr.Decoder) (int, error) { - var err error - var n, nTmp int - var b bool - b, nTmp, err = d.DecodeBool() - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding AccountId: %s", err) - } - s.InflationDest = nil - if b { - s.InflationDest = new(AccountId) - nTmp, err = s.InflationDest.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding AccountId: %s", err) - } - } - b, nTmp, err = d.DecodeBool() - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Uint32: %s", err) - } - s.ClearFlags = nil - if b { - s.ClearFlags = new(Uint32) - nTmp, err = s.ClearFlags.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Uint32: %s", err) - } - } - b, nTmp, err = d.DecodeBool() - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Uint32: %s", err) - } - s.SetFlags = nil - if b { - s.SetFlags = new(Uint32) - nTmp, err = s.SetFlags.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Uint32: %s", err) - } - } - b, nTmp, err = d.DecodeBool() - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Uint32: %s", err) - } - s.MasterWeight = nil - if b { - s.MasterWeight = new(Uint32) - nTmp, err = s.MasterWeight.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Uint32: %s", err) - } - } - b, nTmp, err = d.DecodeBool() - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Uint32: %s", err) - } - s.LowThreshold = nil - if b { - s.LowThreshold = new(Uint32) - nTmp, err = s.LowThreshold.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Uint32: %s", err) - } - } - b, nTmp, err = d.DecodeBool() - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Uint32: %s", err) + if !ok { + panic("arm Success is not set") } - s.MedThreshold = nil - if b { - s.MedThreshold = new(Uint32) - nTmp, err = s.MedThreshold.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Uint32: %s", err) - } + + return val +} + +// GetSuccess retrieves the Success value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u ManageSellOfferResult) GetSuccess() (result ManageOfferSuccessResult, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Code)) + + if armName == "Success" { + result = *u.Success + ok = true } - b, nTmp, err = d.DecodeBool() - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Uint32: %s", err) + + return +} + +// EncodeTo encodes this value using the Encoder. +func (u ManageSellOfferResult) EncodeTo(e *xdr.Encoder) error { + var err error + if err = u.Code.EncodeTo(e); err != nil { + return err } - s.HighThreshold = nil - if b { - s.HighThreshold = new(Uint32) - nTmp, err = s.HighThreshold.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Uint32: %s", err) + switch ManageSellOfferResultCode(u.Code) { + case ManageSellOfferResultCodeManageSellOfferSuccess: + if err = (*u.Success).EncodeTo(e); err != nil { + return err } + return nil + case ManageSellOfferResultCodeManageSellOfferMalformed: + // Void + return nil + case ManageSellOfferResultCodeManageSellOfferSellNoTrust: + // Void + return nil + case ManageSellOfferResultCodeManageSellOfferBuyNoTrust: + // Void + return nil + case ManageSellOfferResultCodeManageSellOfferSellNotAuthorized: + // Void + return nil + case ManageSellOfferResultCodeManageSellOfferBuyNotAuthorized: + // Void + return nil + case ManageSellOfferResultCodeManageSellOfferLineFull: + // Void + return nil + case ManageSellOfferResultCodeManageSellOfferUnderfunded: + // Void + return nil + case ManageSellOfferResultCodeManageSellOfferCrossSelf: + // Void + return nil + case ManageSellOfferResultCodeManageSellOfferSellNoIssuer: + // Void + return nil + case ManageSellOfferResultCodeManageSellOfferBuyNoIssuer: + // Void + return nil + case ManageSellOfferResultCodeManageSellOfferNotFound: + // Void + return nil + case ManageSellOfferResultCodeManageSellOfferLowReserve: + // Void + return nil } - b, nTmp, err = d.DecodeBool() - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding String32: %s", err) - } - s.HomeDomain = nil - if b { - s.HomeDomain = new(String32) - nTmp, err = s.HomeDomain.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding String32: %s", err) - } + return fmt.Errorf("Code (ManageSellOfferResultCode) switch value '%d' is not valid for union ManageSellOfferResult", u.Code) +} + +var _ decoderFrom = (*ManageSellOfferResult)(nil) + +// DecodeFrom decodes this value using the Decoder. +func (u *ManageSellOfferResult) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding ManageSellOfferResult: %w", ErrMaxDecodingDepthReached) } - b, nTmp, err = d.DecodeBool() + maxDepth -= 1 + var err error + var n, nTmp int + nTmp, err = u.Code.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Signer: %s", err) + return n, fmt.Errorf("decoding ManageSellOfferResultCode: %w", err) } - s.Signer = nil - if b { - s.Signer = new(Signer) - nTmp, err = s.Signer.DecodeFrom(d) + switch ManageSellOfferResultCode(u.Code) { + case ManageSellOfferResultCodeManageSellOfferSuccess: + u.Success = new(ManageOfferSuccessResult) + nTmp, err = (*u.Success).DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Signer: %s", err) + return n, fmt.Errorf("decoding ManageOfferSuccessResult: %w", err) } + return n, nil + case ManageSellOfferResultCodeManageSellOfferMalformed: + // Void + return n, nil + case ManageSellOfferResultCodeManageSellOfferSellNoTrust: + // Void + return n, nil + case ManageSellOfferResultCodeManageSellOfferBuyNoTrust: + // Void + return n, nil + case ManageSellOfferResultCodeManageSellOfferSellNotAuthorized: + // Void + return n, nil + case ManageSellOfferResultCodeManageSellOfferBuyNotAuthorized: + // Void + return n, nil + case ManageSellOfferResultCodeManageSellOfferLineFull: + // Void + return n, nil + case ManageSellOfferResultCodeManageSellOfferUnderfunded: + // Void + return n, nil + case ManageSellOfferResultCodeManageSellOfferCrossSelf: + // Void + return n, nil + case ManageSellOfferResultCodeManageSellOfferSellNoIssuer: + // Void + return n, nil + case ManageSellOfferResultCodeManageSellOfferBuyNoIssuer: + // Void + return n, nil + case ManageSellOfferResultCodeManageSellOfferNotFound: + // Void + return n, nil + case ManageSellOfferResultCodeManageSellOfferLowReserve: + // Void + return n, nil } - return n, nil + return n, fmt.Errorf("union ManageSellOfferResult has invalid Code (ManageSellOfferResultCode) switch value '%d'", u.Code) } // MarshalBinary implements encoding.BinaryMarshaler. -func (s SetOptionsOp) MarshalBinary() ([]byte, error) { +func (s ManageSellOfferResult) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -19665,251 +35610,731 @@ func (s SetOptionsOp) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *SetOptionsOp) UnmarshalBinary(inp []byte) error { +func (s *ManageSellOfferResult) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*SetOptionsOp)(nil) - _ encoding.BinaryUnmarshaler = (*SetOptionsOp)(nil) + _ encoding.BinaryMarshaler = (*ManageSellOfferResult)(nil) + _ encoding.BinaryUnmarshaler = (*ManageSellOfferResult)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s SetOptionsOp) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s ManageSellOfferResult) xdrType() {} -var _ xdrType = (*SetOptionsOp)(nil) +var _ xdrType = (*ManageSellOfferResult)(nil) -// ChangeTrustAsset is an XDR Union defines as: +// ManageBuyOfferResultCode is an XDR Enum defines as: // -// union ChangeTrustAsset switch (AssetType type) +// enum ManageBuyOfferResultCode // { -// case ASSET_TYPE_NATIVE: // Not credit -// void; +// // codes considered as "success" for the operation +// MANAGE_BUY_OFFER_SUCCESS = 0, // -// case ASSET_TYPE_CREDIT_ALPHANUM4: -// AlphaNum4 alphaNum4; +// // codes considered as "failure" for the operation +// MANAGE_BUY_OFFER_MALFORMED = -1, // generated offer would be invalid +// MANAGE_BUY_OFFER_SELL_NO_TRUST = -2, // no trust line for what we're selling +// MANAGE_BUY_OFFER_BUY_NO_TRUST = -3, // no trust line for what we're buying +// MANAGE_BUY_OFFER_SELL_NOT_AUTHORIZED = -4, // not authorized to sell +// MANAGE_BUY_OFFER_BUY_NOT_AUTHORIZED = -5, // not authorized to buy +// MANAGE_BUY_OFFER_LINE_FULL = -6, // can't receive more of what it's buying +// MANAGE_BUY_OFFER_UNDERFUNDED = -7, // doesn't hold what it's trying to sell +// MANAGE_BUY_OFFER_CROSS_SELF = -8, // would cross an offer from the same user +// MANAGE_BUY_OFFER_SELL_NO_ISSUER = -9, // no issuer for what we're selling +// MANAGE_BUY_OFFER_BUY_NO_ISSUER = -10, // no issuer for what we're buying // -// case ASSET_TYPE_CREDIT_ALPHANUM12: -// AlphaNum12 alphaNum12; +// // update errors +// MANAGE_BUY_OFFER_NOT_FOUND = +// -11, // offerID does not match an existing offer // -// case ASSET_TYPE_POOL_SHARE: -// LiquidityPoolParameters liquidityPool; +// MANAGE_BUY_OFFER_LOW_RESERVE = -12 // not enough funds to create a new Offer +// }; +type ManageBuyOfferResultCode int32 + +const ( + ManageBuyOfferResultCodeManageBuyOfferSuccess ManageBuyOfferResultCode = 0 + ManageBuyOfferResultCodeManageBuyOfferMalformed ManageBuyOfferResultCode = -1 + ManageBuyOfferResultCodeManageBuyOfferSellNoTrust ManageBuyOfferResultCode = -2 + ManageBuyOfferResultCodeManageBuyOfferBuyNoTrust ManageBuyOfferResultCode = -3 + ManageBuyOfferResultCodeManageBuyOfferSellNotAuthorized ManageBuyOfferResultCode = -4 + ManageBuyOfferResultCodeManageBuyOfferBuyNotAuthorized ManageBuyOfferResultCode = -5 + ManageBuyOfferResultCodeManageBuyOfferLineFull ManageBuyOfferResultCode = -6 + ManageBuyOfferResultCodeManageBuyOfferUnderfunded ManageBuyOfferResultCode = -7 + ManageBuyOfferResultCodeManageBuyOfferCrossSelf ManageBuyOfferResultCode = -8 + ManageBuyOfferResultCodeManageBuyOfferSellNoIssuer ManageBuyOfferResultCode = -9 + ManageBuyOfferResultCodeManageBuyOfferBuyNoIssuer ManageBuyOfferResultCode = -10 + ManageBuyOfferResultCodeManageBuyOfferNotFound ManageBuyOfferResultCode = -11 + ManageBuyOfferResultCodeManageBuyOfferLowReserve ManageBuyOfferResultCode = -12 +) + +var manageBuyOfferResultCodeMap = map[int32]string{ + 0: "ManageBuyOfferResultCodeManageBuyOfferSuccess", + -1: "ManageBuyOfferResultCodeManageBuyOfferMalformed", + -2: "ManageBuyOfferResultCodeManageBuyOfferSellNoTrust", + -3: "ManageBuyOfferResultCodeManageBuyOfferBuyNoTrust", + -4: "ManageBuyOfferResultCodeManageBuyOfferSellNotAuthorized", + -5: "ManageBuyOfferResultCodeManageBuyOfferBuyNotAuthorized", + -6: "ManageBuyOfferResultCodeManageBuyOfferLineFull", + -7: "ManageBuyOfferResultCodeManageBuyOfferUnderfunded", + -8: "ManageBuyOfferResultCodeManageBuyOfferCrossSelf", + -9: "ManageBuyOfferResultCodeManageBuyOfferSellNoIssuer", + -10: "ManageBuyOfferResultCodeManageBuyOfferBuyNoIssuer", + -11: "ManageBuyOfferResultCodeManageBuyOfferNotFound", + -12: "ManageBuyOfferResultCodeManageBuyOfferLowReserve", +} + +// ValidEnum validates a proposed value for this enum. Implements +// the Enum interface for ManageBuyOfferResultCode +func (e ManageBuyOfferResultCode) ValidEnum(v int32) bool { + _, ok := manageBuyOfferResultCodeMap[v] + return ok +} + +// String returns the name of `e` +func (e ManageBuyOfferResultCode) String() string { + name, _ := manageBuyOfferResultCodeMap[int32(e)] + return name +} + +// EncodeTo encodes this value using the Encoder. +func (e ManageBuyOfferResultCode) EncodeTo(enc *xdr.Encoder) error { + if _, ok := manageBuyOfferResultCodeMap[int32(e)]; !ok { + return fmt.Errorf("'%d' is not a valid ManageBuyOfferResultCode enum value", e) + } + _, err := enc.EncodeInt(int32(e)) + return err +} + +var _ decoderFrom = (*ManageBuyOfferResultCode)(nil) + +// DecodeFrom decodes this value using the Decoder. +func (e *ManageBuyOfferResultCode) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding ManageBuyOfferResultCode: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + v, n, err := d.DecodeInt() + if err != nil { + return n, fmt.Errorf("decoding ManageBuyOfferResultCode: %w", err) + } + if _, ok := manageBuyOfferResultCodeMap[v]; !ok { + return n, fmt.Errorf("'%d' is not a valid ManageBuyOfferResultCode enum value", v) + } + *e = ManageBuyOfferResultCode(v) + return n, nil +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (s ManageBuyOfferResultCode) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *ManageBuyOfferResultCode) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} + +var ( + _ encoding.BinaryMarshaler = (*ManageBuyOfferResultCode)(nil) + _ encoding.BinaryUnmarshaler = (*ManageBuyOfferResultCode)(nil) +) + +// xdrType signals that this type represents XDR values defined by this package. +func (s ManageBuyOfferResultCode) xdrType() {} + +var _ xdrType = (*ManageBuyOfferResultCode)(nil) + +// ManageBuyOfferResult is an XDR Union defines as: // -// // add other asset types here in the future +// union ManageBuyOfferResult switch (ManageBuyOfferResultCode code) +// { +// case MANAGE_BUY_OFFER_SUCCESS: +// ManageOfferSuccessResult success; +// case MANAGE_BUY_OFFER_MALFORMED: +// case MANAGE_BUY_OFFER_SELL_NO_TRUST: +// case MANAGE_BUY_OFFER_BUY_NO_TRUST: +// case MANAGE_BUY_OFFER_SELL_NOT_AUTHORIZED: +// case MANAGE_BUY_OFFER_BUY_NOT_AUTHORIZED: +// case MANAGE_BUY_OFFER_LINE_FULL: +// case MANAGE_BUY_OFFER_UNDERFUNDED: +// case MANAGE_BUY_OFFER_CROSS_SELF: +// case MANAGE_BUY_OFFER_SELL_NO_ISSUER: +// case MANAGE_BUY_OFFER_BUY_NO_ISSUER: +// case MANAGE_BUY_OFFER_NOT_FOUND: +// case MANAGE_BUY_OFFER_LOW_RESERVE: +// void; // }; -type ChangeTrustAsset struct { - Type AssetType - AlphaNum4 *AlphaNum4 - AlphaNum12 *AlphaNum12 - LiquidityPool *LiquidityPoolParameters +type ManageBuyOfferResult struct { + Code ManageBuyOfferResultCode + Success *ManageOfferSuccessResult } // SwitchFieldName returns the field name in which this union's // discriminant is stored -func (u ChangeTrustAsset) SwitchFieldName() string { - return "Type" +func (u ManageBuyOfferResult) SwitchFieldName() string { + return "Code" } // ArmForSwitch returns which field name should be used for storing -// the value for an instance of ChangeTrustAsset -func (u ChangeTrustAsset) ArmForSwitch(sw int32) (string, bool) { - switch AssetType(sw) { - case AssetTypeAssetTypeNative: +// the value for an instance of ManageBuyOfferResult +func (u ManageBuyOfferResult) ArmForSwitch(sw int32) (string, bool) { + switch ManageBuyOfferResultCode(sw) { + case ManageBuyOfferResultCodeManageBuyOfferSuccess: + return "Success", true + case ManageBuyOfferResultCodeManageBuyOfferMalformed: + return "", true + case ManageBuyOfferResultCodeManageBuyOfferSellNoTrust: + return "", true + case ManageBuyOfferResultCodeManageBuyOfferBuyNoTrust: + return "", true + case ManageBuyOfferResultCodeManageBuyOfferSellNotAuthorized: + return "", true + case ManageBuyOfferResultCodeManageBuyOfferBuyNotAuthorized: + return "", true + case ManageBuyOfferResultCodeManageBuyOfferLineFull: + return "", true + case ManageBuyOfferResultCodeManageBuyOfferUnderfunded: + return "", true + case ManageBuyOfferResultCodeManageBuyOfferCrossSelf: + return "", true + case ManageBuyOfferResultCodeManageBuyOfferSellNoIssuer: + return "", true + case ManageBuyOfferResultCodeManageBuyOfferBuyNoIssuer: + return "", true + case ManageBuyOfferResultCodeManageBuyOfferNotFound: + return "", true + case ManageBuyOfferResultCodeManageBuyOfferLowReserve: return "", true - case AssetTypeAssetTypeCreditAlphanum4: - return "AlphaNum4", true - case AssetTypeAssetTypeCreditAlphanum12: - return "AlphaNum12", true - case AssetTypeAssetTypePoolShare: - return "LiquidityPool", true } return "-", false } -// NewChangeTrustAsset creates a new ChangeTrustAsset. -func NewChangeTrustAsset(aType AssetType, value interface{}) (result ChangeTrustAsset, err error) { - result.Type = aType - switch AssetType(aType) { - case AssetTypeAssetTypeNative: - // void - case AssetTypeAssetTypeCreditAlphanum4: - tv, ok := value.(AlphaNum4) - if !ok { - err = fmt.Errorf("invalid value, must be AlphaNum4") - return - } - result.AlphaNum4 = &tv - case AssetTypeAssetTypeCreditAlphanum12: - tv, ok := value.(AlphaNum12) - if !ok { - err = fmt.Errorf("invalid value, must be AlphaNum12") - return - } - result.AlphaNum12 = &tv - case AssetTypeAssetTypePoolShare: - tv, ok := value.(LiquidityPoolParameters) +// NewManageBuyOfferResult creates a new ManageBuyOfferResult. +func NewManageBuyOfferResult(code ManageBuyOfferResultCode, value interface{}) (result ManageBuyOfferResult, err error) { + result.Code = code + switch ManageBuyOfferResultCode(code) { + case ManageBuyOfferResultCodeManageBuyOfferSuccess: + tv, ok := value.(ManageOfferSuccessResult) if !ok { - err = fmt.Errorf("invalid value, must be LiquidityPoolParameters") + err = errors.New("invalid value, must be ManageOfferSuccessResult") return } - result.LiquidityPool = &tv + result.Success = &tv + case ManageBuyOfferResultCodeManageBuyOfferMalformed: + // void + case ManageBuyOfferResultCodeManageBuyOfferSellNoTrust: + // void + case ManageBuyOfferResultCodeManageBuyOfferBuyNoTrust: + // void + case ManageBuyOfferResultCodeManageBuyOfferSellNotAuthorized: + // void + case ManageBuyOfferResultCodeManageBuyOfferBuyNotAuthorized: + // void + case ManageBuyOfferResultCodeManageBuyOfferLineFull: + // void + case ManageBuyOfferResultCodeManageBuyOfferUnderfunded: + // void + case ManageBuyOfferResultCodeManageBuyOfferCrossSelf: + // void + case ManageBuyOfferResultCodeManageBuyOfferSellNoIssuer: + // void + case ManageBuyOfferResultCodeManageBuyOfferBuyNoIssuer: + // void + case ManageBuyOfferResultCodeManageBuyOfferNotFound: + // void + case ManageBuyOfferResultCodeManageBuyOfferLowReserve: + // void } return } -// MustAlphaNum4 retrieves the AlphaNum4 value from the union, +// MustSuccess retrieves the Success value from the union, // panicing if the value is not set. -func (u ChangeTrustAsset) MustAlphaNum4() AlphaNum4 { - val, ok := u.GetAlphaNum4() +func (u ManageBuyOfferResult) MustSuccess() ManageOfferSuccessResult { + val, ok := u.GetSuccess() if !ok { - panic("arm AlphaNum4 is not set") + panic("arm Success is not set") + } + + return val +} + +// GetSuccess retrieves the Success value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u ManageBuyOfferResult) GetSuccess() (result ManageOfferSuccessResult, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Code)) + + if armName == "Success" { + result = *u.Success + ok = true + } + + return +} + +// EncodeTo encodes this value using the Encoder. +func (u ManageBuyOfferResult) EncodeTo(e *xdr.Encoder) error { + var err error + if err = u.Code.EncodeTo(e); err != nil { + return err + } + switch ManageBuyOfferResultCode(u.Code) { + case ManageBuyOfferResultCodeManageBuyOfferSuccess: + if err = (*u.Success).EncodeTo(e); err != nil { + return err + } + return nil + case ManageBuyOfferResultCodeManageBuyOfferMalformed: + // Void + return nil + case ManageBuyOfferResultCodeManageBuyOfferSellNoTrust: + // Void + return nil + case ManageBuyOfferResultCodeManageBuyOfferBuyNoTrust: + // Void + return nil + case ManageBuyOfferResultCodeManageBuyOfferSellNotAuthorized: + // Void + return nil + case ManageBuyOfferResultCodeManageBuyOfferBuyNotAuthorized: + // Void + return nil + case ManageBuyOfferResultCodeManageBuyOfferLineFull: + // Void + return nil + case ManageBuyOfferResultCodeManageBuyOfferUnderfunded: + // Void + return nil + case ManageBuyOfferResultCodeManageBuyOfferCrossSelf: + // Void + return nil + case ManageBuyOfferResultCodeManageBuyOfferSellNoIssuer: + // Void + return nil + case ManageBuyOfferResultCodeManageBuyOfferBuyNoIssuer: + // Void + return nil + case ManageBuyOfferResultCodeManageBuyOfferNotFound: + // Void + return nil + case ManageBuyOfferResultCodeManageBuyOfferLowReserve: + // Void + return nil + } + return fmt.Errorf("Code (ManageBuyOfferResultCode) switch value '%d' is not valid for union ManageBuyOfferResult", u.Code) +} + +var _ decoderFrom = (*ManageBuyOfferResult)(nil) + +// DecodeFrom decodes this value using the Decoder. +func (u *ManageBuyOfferResult) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding ManageBuyOfferResult: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + var err error + var n, nTmp int + nTmp, err = u.Code.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ManageBuyOfferResultCode: %w", err) + } + switch ManageBuyOfferResultCode(u.Code) { + case ManageBuyOfferResultCodeManageBuyOfferSuccess: + u.Success = new(ManageOfferSuccessResult) + nTmp, err = (*u.Success).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ManageOfferSuccessResult: %w", err) + } + return n, nil + case ManageBuyOfferResultCodeManageBuyOfferMalformed: + // Void + return n, nil + case ManageBuyOfferResultCodeManageBuyOfferSellNoTrust: + // Void + return n, nil + case ManageBuyOfferResultCodeManageBuyOfferBuyNoTrust: + // Void + return n, nil + case ManageBuyOfferResultCodeManageBuyOfferSellNotAuthorized: + // Void + return n, nil + case ManageBuyOfferResultCodeManageBuyOfferBuyNotAuthorized: + // Void + return n, nil + case ManageBuyOfferResultCodeManageBuyOfferLineFull: + // Void + return n, nil + case ManageBuyOfferResultCodeManageBuyOfferUnderfunded: + // Void + return n, nil + case ManageBuyOfferResultCodeManageBuyOfferCrossSelf: + // Void + return n, nil + case ManageBuyOfferResultCodeManageBuyOfferSellNoIssuer: + // Void + return n, nil + case ManageBuyOfferResultCodeManageBuyOfferBuyNoIssuer: + // Void + return n, nil + case ManageBuyOfferResultCodeManageBuyOfferNotFound: + // Void + return n, nil + case ManageBuyOfferResultCodeManageBuyOfferLowReserve: + // Void + return n, nil } + return n, fmt.Errorf("union ManageBuyOfferResult has invalid Code (ManageBuyOfferResultCode) switch value '%d'", u.Code) +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (s ManageBuyOfferResult) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *ManageBuyOfferResult) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} + +var ( + _ encoding.BinaryMarshaler = (*ManageBuyOfferResult)(nil) + _ encoding.BinaryUnmarshaler = (*ManageBuyOfferResult)(nil) +) + +// xdrType signals that this type represents XDR values defined by this package. +func (s ManageBuyOfferResult) xdrType() {} + +var _ xdrType = (*ManageBuyOfferResult)(nil) + +// SetOptionsResultCode is an XDR Enum defines as: +// +// enum SetOptionsResultCode +// { +// // codes considered as "success" for the operation +// SET_OPTIONS_SUCCESS = 0, +// // codes considered as "failure" for the operation +// SET_OPTIONS_LOW_RESERVE = -1, // not enough funds to add a signer +// SET_OPTIONS_TOO_MANY_SIGNERS = -2, // max number of signers already reached +// SET_OPTIONS_BAD_FLAGS = -3, // invalid combination of clear/set flags +// SET_OPTIONS_INVALID_INFLATION = -4, // inflation account does not exist +// SET_OPTIONS_CANT_CHANGE = -5, // can no longer change this option +// SET_OPTIONS_UNKNOWN_FLAG = -6, // can't set an unknown flag +// SET_OPTIONS_THRESHOLD_OUT_OF_RANGE = -7, // bad value for weight/threshold +// SET_OPTIONS_BAD_SIGNER = -8, // signer cannot be masterkey +// SET_OPTIONS_INVALID_HOME_DOMAIN = -9, // malformed home domain +// SET_OPTIONS_AUTH_REVOCABLE_REQUIRED = +// -10 // auth revocable is required for clawback +// }; +type SetOptionsResultCode int32 + +const ( + SetOptionsResultCodeSetOptionsSuccess SetOptionsResultCode = 0 + SetOptionsResultCodeSetOptionsLowReserve SetOptionsResultCode = -1 + SetOptionsResultCodeSetOptionsTooManySigners SetOptionsResultCode = -2 + SetOptionsResultCodeSetOptionsBadFlags SetOptionsResultCode = -3 + SetOptionsResultCodeSetOptionsInvalidInflation SetOptionsResultCode = -4 + SetOptionsResultCodeSetOptionsCantChange SetOptionsResultCode = -5 + SetOptionsResultCodeSetOptionsUnknownFlag SetOptionsResultCode = -6 + SetOptionsResultCodeSetOptionsThresholdOutOfRange SetOptionsResultCode = -7 + SetOptionsResultCodeSetOptionsBadSigner SetOptionsResultCode = -8 + SetOptionsResultCodeSetOptionsInvalidHomeDomain SetOptionsResultCode = -9 + SetOptionsResultCodeSetOptionsAuthRevocableRequired SetOptionsResultCode = -10 +) + +var setOptionsResultCodeMap = map[int32]string{ + 0: "SetOptionsResultCodeSetOptionsSuccess", + -1: "SetOptionsResultCodeSetOptionsLowReserve", + -2: "SetOptionsResultCodeSetOptionsTooManySigners", + -3: "SetOptionsResultCodeSetOptionsBadFlags", + -4: "SetOptionsResultCodeSetOptionsInvalidInflation", + -5: "SetOptionsResultCodeSetOptionsCantChange", + -6: "SetOptionsResultCodeSetOptionsUnknownFlag", + -7: "SetOptionsResultCodeSetOptionsThresholdOutOfRange", + -8: "SetOptionsResultCodeSetOptionsBadSigner", + -9: "SetOptionsResultCodeSetOptionsInvalidHomeDomain", + -10: "SetOptionsResultCodeSetOptionsAuthRevocableRequired", +} - return val +// ValidEnum validates a proposed value for this enum. Implements +// the Enum interface for SetOptionsResultCode +func (e SetOptionsResultCode) ValidEnum(v int32) bool { + _, ok := setOptionsResultCodeMap[v] + return ok } -// GetAlphaNum4 retrieves the AlphaNum4 value from the union, -// returning ok if the union's switch indicated the value is valid. -func (u ChangeTrustAsset) GetAlphaNum4() (result AlphaNum4, ok bool) { - armName, _ := u.ArmForSwitch(int32(u.Type)) +// String returns the name of `e` +func (e SetOptionsResultCode) String() string { + name, _ := setOptionsResultCodeMap[int32(e)] + return name +} - if armName == "AlphaNum4" { - result = *u.AlphaNum4 - ok = true +// EncodeTo encodes this value using the Encoder. +func (e SetOptionsResultCode) EncodeTo(enc *xdr.Encoder) error { + if _, ok := setOptionsResultCodeMap[int32(e)]; !ok { + return fmt.Errorf("'%d' is not a valid SetOptionsResultCode enum value", e) } - - return + _, err := enc.EncodeInt(int32(e)) + return err } -// MustAlphaNum12 retrieves the AlphaNum12 value from the union, -// panicing if the value is not set. -func (u ChangeTrustAsset) MustAlphaNum12() AlphaNum12 { - val, ok := u.GetAlphaNum12() +var _ decoderFrom = (*SetOptionsResultCode)(nil) - if !ok { - panic("arm AlphaNum12 is not set") +// DecodeFrom decodes this value using the Decoder. +func (e *SetOptionsResultCode) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding SetOptionsResultCode: %w", ErrMaxDecodingDepthReached) } - - return val + maxDepth -= 1 + v, n, err := d.DecodeInt() + if err != nil { + return n, fmt.Errorf("decoding SetOptionsResultCode: %w", err) + } + if _, ok := setOptionsResultCodeMap[v]; !ok { + return n, fmt.Errorf("'%d' is not a valid SetOptionsResultCode enum value", v) + } + *e = SetOptionsResultCode(v) + return n, nil } -// GetAlphaNum12 retrieves the AlphaNum12 value from the union, -// returning ok if the union's switch indicated the value is valid. -func (u ChangeTrustAsset) GetAlphaNum12() (result AlphaNum12, ok bool) { - armName, _ := u.ArmForSwitch(int32(u.Type)) - - if armName == "AlphaNum12" { - result = *u.AlphaNum12 - ok = true - } +// MarshalBinary implements encoding.BinaryMarshaler. +func (s SetOptionsResultCode) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} - return +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *SetOptionsResultCode) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err } -// MustLiquidityPool retrieves the LiquidityPool value from the union, -// panicing if the value is not set. -func (u ChangeTrustAsset) MustLiquidityPool() LiquidityPoolParameters { - val, ok := u.GetLiquidityPool() +var ( + _ encoding.BinaryMarshaler = (*SetOptionsResultCode)(nil) + _ encoding.BinaryUnmarshaler = (*SetOptionsResultCode)(nil) +) - if !ok { - panic("arm LiquidityPool is not set") - } +// xdrType signals that this type represents XDR values defined by this package. +func (s SetOptionsResultCode) xdrType() {} - return val +var _ xdrType = (*SetOptionsResultCode)(nil) + +// SetOptionsResult is an XDR Union defines as: +// +// union SetOptionsResult switch (SetOptionsResultCode code) +// { +// case SET_OPTIONS_SUCCESS: +// void; +// case SET_OPTIONS_LOW_RESERVE: +// case SET_OPTIONS_TOO_MANY_SIGNERS: +// case SET_OPTIONS_BAD_FLAGS: +// case SET_OPTIONS_INVALID_INFLATION: +// case SET_OPTIONS_CANT_CHANGE: +// case SET_OPTIONS_UNKNOWN_FLAG: +// case SET_OPTIONS_THRESHOLD_OUT_OF_RANGE: +// case SET_OPTIONS_BAD_SIGNER: +// case SET_OPTIONS_INVALID_HOME_DOMAIN: +// case SET_OPTIONS_AUTH_REVOCABLE_REQUIRED: +// void; +// }; +type SetOptionsResult struct { + Code SetOptionsResultCode } -// GetLiquidityPool retrieves the LiquidityPool value from the union, -// returning ok if the union's switch indicated the value is valid. -func (u ChangeTrustAsset) GetLiquidityPool() (result LiquidityPoolParameters, ok bool) { - armName, _ := u.ArmForSwitch(int32(u.Type)) +// SwitchFieldName returns the field name in which this union's +// discriminant is stored +func (u SetOptionsResult) SwitchFieldName() string { + return "Code" +} - if armName == "LiquidityPool" { - result = *u.LiquidityPool - ok = true +// ArmForSwitch returns which field name should be used for storing +// the value for an instance of SetOptionsResult +func (u SetOptionsResult) ArmForSwitch(sw int32) (string, bool) { + switch SetOptionsResultCode(sw) { + case SetOptionsResultCodeSetOptionsSuccess: + return "", true + case SetOptionsResultCodeSetOptionsLowReserve: + return "", true + case SetOptionsResultCodeSetOptionsTooManySigners: + return "", true + case SetOptionsResultCodeSetOptionsBadFlags: + return "", true + case SetOptionsResultCodeSetOptionsInvalidInflation: + return "", true + case SetOptionsResultCodeSetOptionsCantChange: + return "", true + case SetOptionsResultCodeSetOptionsUnknownFlag: + return "", true + case SetOptionsResultCodeSetOptionsThresholdOutOfRange: + return "", true + case SetOptionsResultCodeSetOptionsBadSigner: + return "", true + case SetOptionsResultCodeSetOptionsInvalidHomeDomain: + return "", true + case SetOptionsResultCodeSetOptionsAuthRevocableRequired: + return "", true } + return "-", false +} +// NewSetOptionsResult creates a new SetOptionsResult. +func NewSetOptionsResult(code SetOptionsResultCode, value interface{}) (result SetOptionsResult, err error) { + result.Code = code + switch SetOptionsResultCode(code) { + case SetOptionsResultCodeSetOptionsSuccess: + // void + case SetOptionsResultCodeSetOptionsLowReserve: + // void + case SetOptionsResultCodeSetOptionsTooManySigners: + // void + case SetOptionsResultCodeSetOptionsBadFlags: + // void + case SetOptionsResultCodeSetOptionsInvalidInflation: + // void + case SetOptionsResultCodeSetOptionsCantChange: + // void + case SetOptionsResultCodeSetOptionsUnknownFlag: + // void + case SetOptionsResultCodeSetOptionsThresholdOutOfRange: + // void + case SetOptionsResultCodeSetOptionsBadSigner: + // void + case SetOptionsResultCodeSetOptionsInvalidHomeDomain: + // void + case SetOptionsResultCodeSetOptionsAuthRevocableRequired: + // void + } return } // EncodeTo encodes this value using the Encoder. -func (u ChangeTrustAsset) EncodeTo(e *xdr.Encoder) error { +func (u SetOptionsResult) EncodeTo(e *xdr.Encoder) error { var err error - if err = u.Type.EncodeTo(e); err != nil { + if err = u.Code.EncodeTo(e); err != nil { return err } - switch AssetType(u.Type) { - case AssetTypeAssetTypeNative: + switch SetOptionsResultCode(u.Code) { + case SetOptionsResultCodeSetOptionsSuccess: // Void return nil - case AssetTypeAssetTypeCreditAlphanum4: - if err = (*u.AlphaNum4).EncodeTo(e); err != nil { - return err - } + case SetOptionsResultCodeSetOptionsLowReserve: + // Void return nil - case AssetTypeAssetTypeCreditAlphanum12: - if err = (*u.AlphaNum12).EncodeTo(e); err != nil { - return err - } + case SetOptionsResultCodeSetOptionsTooManySigners: + // Void return nil - case AssetTypeAssetTypePoolShare: - if err = (*u.LiquidityPool).EncodeTo(e); err != nil { - return err - } + case SetOptionsResultCodeSetOptionsBadFlags: + // Void + return nil + case SetOptionsResultCodeSetOptionsInvalidInflation: + // Void + return nil + case SetOptionsResultCodeSetOptionsCantChange: + // Void + return nil + case SetOptionsResultCodeSetOptionsUnknownFlag: + // Void + return nil + case SetOptionsResultCodeSetOptionsThresholdOutOfRange: + // Void + return nil + case SetOptionsResultCodeSetOptionsBadSigner: + // Void + return nil + case SetOptionsResultCodeSetOptionsInvalidHomeDomain: + // Void + return nil + case SetOptionsResultCodeSetOptionsAuthRevocableRequired: + // Void return nil } - return fmt.Errorf("Type (AssetType) switch value '%d' is not valid for union ChangeTrustAsset", u.Type) + return fmt.Errorf("Code (SetOptionsResultCode) switch value '%d' is not valid for union SetOptionsResult", u.Code) } -var _ decoderFrom = (*ChangeTrustAsset)(nil) +var _ decoderFrom = (*SetOptionsResult)(nil) // DecodeFrom decodes this value using the Decoder. -func (u *ChangeTrustAsset) DecodeFrom(d *xdr.Decoder) (int, error) { +func (u *SetOptionsResult) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding SetOptionsResult: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = u.Type.DecodeFrom(d) + nTmp, err = u.Code.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding AssetType: %s", err) + return n, fmt.Errorf("decoding SetOptionsResultCode: %w", err) } - switch AssetType(u.Type) { - case AssetTypeAssetTypeNative: + switch SetOptionsResultCode(u.Code) { + case SetOptionsResultCodeSetOptionsSuccess: // Void return n, nil - case AssetTypeAssetTypeCreditAlphanum4: - u.AlphaNum4 = new(AlphaNum4) - nTmp, err = (*u.AlphaNum4).DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding AlphaNum4: %s", err) - } + case SetOptionsResultCodeSetOptionsLowReserve: + // Void return n, nil - case AssetTypeAssetTypeCreditAlphanum12: - u.AlphaNum12 = new(AlphaNum12) - nTmp, err = (*u.AlphaNum12).DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding AlphaNum12: %s", err) - } + case SetOptionsResultCodeSetOptionsTooManySigners: + // Void return n, nil - case AssetTypeAssetTypePoolShare: - u.LiquidityPool = new(LiquidityPoolParameters) - nTmp, err = (*u.LiquidityPool).DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding LiquidityPoolParameters: %s", err) - } + case SetOptionsResultCodeSetOptionsBadFlags: + // Void + return n, nil + case SetOptionsResultCodeSetOptionsInvalidInflation: + // Void + return n, nil + case SetOptionsResultCodeSetOptionsCantChange: + // Void + return n, nil + case SetOptionsResultCodeSetOptionsUnknownFlag: + // Void + return n, nil + case SetOptionsResultCodeSetOptionsThresholdOutOfRange: + // Void + return n, nil + case SetOptionsResultCodeSetOptionsBadSigner: + // Void + return n, nil + case SetOptionsResultCodeSetOptionsInvalidHomeDomain: + // Void + return n, nil + case SetOptionsResultCodeSetOptionsAuthRevocableRequired: + // Void return n, nil } - return n, fmt.Errorf("union ChangeTrustAsset has invalid Type (AssetType) switch value '%d'", u.Type) + return n, fmt.Errorf("union SetOptionsResult has invalid Code (SetOptionsResultCode) switch value '%d'", u.Code) } // MarshalBinary implements encoding.BinaryMarshaler. -func (s ChangeTrustAsset) MarshalBinary() ([]byte, error) { +func (s SetOptionsResult) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -19917,71 +36342,114 @@ func (s ChangeTrustAsset) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *ChangeTrustAsset) UnmarshalBinary(inp []byte) error { +func (s *SetOptionsResult) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*ChangeTrustAsset)(nil) - _ encoding.BinaryUnmarshaler = (*ChangeTrustAsset)(nil) + _ encoding.BinaryMarshaler = (*SetOptionsResult)(nil) + _ encoding.BinaryUnmarshaler = (*SetOptionsResult)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s ChangeTrustAsset) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s SetOptionsResult) xdrType() {} -var _ xdrType = (*ChangeTrustAsset)(nil) +var _ xdrType = (*SetOptionsResult)(nil) -// ChangeTrustOp is an XDR Struct defines as: +// ChangeTrustResultCode is an XDR Enum defines as: // -// struct ChangeTrustOp +// enum ChangeTrustResultCode // { -// ChangeTrustAsset line; -// -// // if limit is set to 0, deletes the trust line -// int64 limit; +// // codes considered as "success" for the operation +// CHANGE_TRUST_SUCCESS = 0, +// // codes considered as "failure" for the operation +// CHANGE_TRUST_MALFORMED = -1, // bad input +// CHANGE_TRUST_NO_ISSUER = -2, // could not find issuer +// CHANGE_TRUST_INVALID_LIMIT = -3, // cannot drop limit below balance +// // cannot create with a limit of 0 +// CHANGE_TRUST_LOW_RESERVE = +// -4, // not enough funds to create a new trust line, +// CHANGE_TRUST_SELF_NOT_ALLOWED = -5, // trusting self is not allowed +// CHANGE_TRUST_TRUST_LINE_MISSING = -6, // Asset trustline is missing for pool +// CHANGE_TRUST_CANNOT_DELETE = +// -7, // Asset trustline is still referenced in a pool +// CHANGE_TRUST_NOT_AUTH_MAINTAIN_LIABILITIES = +// -8 // Asset trustline is deauthorized // }; -type ChangeTrustOp struct { - Line ChangeTrustAsset - Limit Int64 +type ChangeTrustResultCode int32 + +const ( + ChangeTrustResultCodeChangeTrustSuccess ChangeTrustResultCode = 0 + ChangeTrustResultCodeChangeTrustMalformed ChangeTrustResultCode = -1 + ChangeTrustResultCodeChangeTrustNoIssuer ChangeTrustResultCode = -2 + ChangeTrustResultCodeChangeTrustInvalidLimit ChangeTrustResultCode = -3 + ChangeTrustResultCodeChangeTrustLowReserve ChangeTrustResultCode = -4 + ChangeTrustResultCodeChangeTrustSelfNotAllowed ChangeTrustResultCode = -5 + ChangeTrustResultCodeChangeTrustTrustLineMissing ChangeTrustResultCode = -6 + ChangeTrustResultCodeChangeTrustCannotDelete ChangeTrustResultCode = -7 + ChangeTrustResultCodeChangeTrustNotAuthMaintainLiabilities ChangeTrustResultCode = -8 +) + +var changeTrustResultCodeMap = map[int32]string{ + 0: "ChangeTrustResultCodeChangeTrustSuccess", + -1: "ChangeTrustResultCodeChangeTrustMalformed", + -2: "ChangeTrustResultCodeChangeTrustNoIssuer", + -3: "ChangeTrustResultCodeChangeTrustInvalidLimit", + -4: "ChangeTrustResultCodeChangeTrustLowReserve", + -5: "ChangeTrustResultCodeChangeTrustSelfNotAllowed", + -6: "ChangeTrustResultCodeChangeTrustTrustLineMissing", + -7: "ChangeTrustResultCodeChangeTrustCannotDelete", + -8: "ChangeTrustResultCodeChangeTrustNotAuthMaintainLiabilities", +} + +// ValidEnum validates a proposed value for this enum. Implements +// the Enum interface for ChangeTrustResultCode +func (e ChangeTrustResultCode) ValidEnum(v int32) bool { + _, ok := changeTrustResultCodeMap[v] + return ok +} + +// String returns the name of `e` +func (e ChangeTrustResultCode) String() string { + name, _ := changeTrustResultCodeMap[int32(e)] + return name } // EncodeTo encodes this value using the Encoder. -func (s *ChangeTrustOp) EncodeTo(e *xdr.Encoder) error { - var err error - if err = s.Line.EncodeTo(e); err != nil { - return err - } - if err = s.Limit.EncodeTo(e); err != nil { - return err +func (e ChangeTrustResultCode) EncodeTo(enc *xdr.Encoder) error { + if _, ok := changeTrustResultCodeMap[int32(e)]; !ok { + return fmt.Errorf("'%d' is not a valid ChangeTrustResultCode enum value", e) } - return nil + _, err := enc.EncodeInt(int32(e)) + return err } -var _ decoderFrom = (*ChangeTrustOp)(nil) +var _ decoderFrom = (*ChangeTrustResultCode)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *ChangeTrustOp) DecodeFrom(d *xdr.Decoder) (int, error) { - var err error - var n, nTmp int - nTmp, err = s.Line.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding ChangeTrustAsset: %s", err) +func (e *ChangeTrustResultCode) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding ChangeTrustResultCode: %w", ErrMaxDecodingDepthReached) } - nTmp, err = s.Limit.DecodeFrom(d) - n += nTmp + maxDepth -= 1 + v, n, err := d.DecodeInt() if err != nil { - return n, fmt.Errorf("decoding Int64: %s", err) + return n, fmt.Errorf("decoding ChangeTrustResultCode: %w", err) } + if _, ok := changeTrustResultCodeMap[v]; !ok { + return n, fmt.Errorf("'%d' is not a valid ChangeTrustResultCode enum value", v) + } + *e = ChangeTrustResultCode(v) return n, nil } // MarshalBinary implements encoding.BinaryMarshaler. -func (s ChangeTrustOp) MarshalBinary() ([]byte, error) { +func (s ChangeTrustResultCode) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -19989,81 +36457,190 @@ func (s ChangeTrustOp) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *ChangeTrustOp) UnmarshalBinary(inp []byte) error { +func (s *ChangeTrustResultCode) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*ChangeTrustOp)(nil) - _ encoding.BinaryUnmarshaler = (*ChangeTrustOp)(nil) + _ encoding.BinaryMarshaler = (*ChangeTrustResultCode)(nil) + _ encoding.BinaryUnmarshaler = (*ChangeTrustResultCode)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s ChangeTrustOp) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s ChangeTrustResultCode) xdrType() {} -var _ xdrType = (*ChangeTrustOp)(nil) +var _ xdrType = (*ChangeTrustResultCode)(nil) -// AllowTrustOp is an XDR Struct defines as: +// ChangeTrustResult is an XDR Union defines as: // -// struct AllowTrustOp +// union ChangeTrustResult switch (ChangeTrustResultCode code) // { -// AccountID trustor; -// AssetCode asset; -// -// // One of 0, AUTHORIZED_FLAG, or AUTHORIZED_TO_MAINTAIN_LIABILITIES_FLAG -// uint32 authorize; +// case CHANGE_TRUST_SUCCESS: +// void; +// case CHANGE_TRUST_MALFORMED: +// case CHANGE_TRUST_NO_ISSUER: +// case CHANGE_TRUST_INVALID_LIMIT: +// case CHANGE_TRUST_LOW_RESERVE: +// case CHANGE_TRUST_SELF_NOT_ALLOWED: +// case CHANGE_TRUST_TRUST_LINE_MISSING: +// case CHANGE_TRUST_CANNOT_DELETE: +// case CHANGE_TRUST_NOT_AUTH_MAINTAIN_LIABILITIES: +// void; // }; -type AllowTrustOp struct { - Trustor AccountId - Asset AssetCode - Authorize Uint32 +type ChangeTrustResult struct { + Code ChangeTrustResultCode +} + +// SwitchFieldName returns the field name in which this union's +// discriminant is stored +func (u ChangeTrustResult) SwitchFieldName() string { + return "Code" +} + +// ArmForSwitch returns which field name should be used for storing +// the value for an instance of ChangeTrustResult +func (u ChangeTrustResult) ArmForSwitch(sw int32) (string, bool) { + switch ChangeTrustResultCode(sw) { + case ChangeTrustResultCodeChangeTrustSuccess: + return "", true + case ChangeTrustResultCodeChangeTrustMalformed: + return "", true + case ChangeTrustResultCodeChangeTrustNoIssuer: + return "", true + case ChangeTrustResultCodeChangeTrustInvalidLimit: + return "", true + case ChangeTrustResultCodeChangeTrustLowReserve: + return "", true + case ChangeTrustResultCodeChangeTrustSelfNotAllowed: + return "", true + case ChangeTrustResultCodeChangeTrustTrustLineMissing: + return "", true + case ChangeTrustResultCodeChangeTrustCannotDelete: + return "", true + case ChangeTrustResultCodeChangeTrustNotAuthMaintainLiabilities: + return "", true + } + return "-", false +} + +// NewChangeTrustResult creates a new ChangeTrustResult. +func NewChangeTrustResult(code ChangeTrustResultCode, value interface{}) (result ChangeTrustResult, err error) { + result.Code = code + switch ChangeTrustResultCode(code) { + case ChangeTrustResultCodeChangeTrustSuccess: + // void + case ChangeTrustResultCodeChangeTrustMalformed: + // void + case ChangeTrustResultCodeChangeTrustNoIssuer: + // void + case ChangeTrustResultCodeChangeTrustInvalidLimit: + // void + case ChangeTrustResultCodeChangeTrustLowReserve: + // void + case ChangeTrustResultCodeChangeTrustSelfNotAllowed: + // void + case ChangeTrustResultCodeChangeTrustTrustLineMissing: + // void + case ChangeTrustResultCodeChangeTrustCannotDelete: + // void + case ChangeTrustResultCodeChangeTrustNotAuthMaintainLiabilities: + // void + } + return } // EncodeTo encodes this value using the Encoder. -func (s *AllowTrustOp) EncodeTo(e *xdr.Encoder) error { +func (u ChangeTrustResult) EncodeTo(e *xdr.Encoder) error { var err error - if err = s.Trustor.EncodeTo(e); err != nil { - return err - } - if err = s.Asset.EncodeTo(e); err != nil { + if err = u.Code.EncodeTo(e); err != nil { return err } - if err = s.Authorize.EncodeTo(e); err != nil { - return err + switch ChangeTrustResultCode(u.Code) { + case ChangeTrustResultCodeChangeTrustSuccess: + // Void + return nil + case ChangeTrustResultCodeChangeTrustMalformed: + // Void + return nil + case ChangeTrustResultCodeChangeTrustNoIssuer: + // Void + return nil + case ChangeTrustResultCodeChangeTrustInvalidLimit: + // Void + return nil + case ChangeTrustResultCodeChangeTrustLowReserve: + // Void + return nil + case ChangeTrustResultCodeChangeTrustSelfNotAllowed: + // Void + return nil + case ChangeTrustResultCodeChangeTrustTrustLineMissing: + // Void + return nil + case ChangeTrustResultCodeChangeTrustCannotDelete: + // Void + return nil + case ChangeTrustResultCodeChangeTrustNotAuthMaintainLiabilities: + // Void + return nil } - return nil + return fmt.Errorf("Code (ChangeTrustResultCode) switch value '%d' is not valid for union ChangeTrustResult", u.Code) } -var _ decoderFrom = (*AllowTrustOp)(nil) +var _ decoderFrom = (*ChangeTrustResult)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *AllowTrustOp) DecodeFrom(d *xdr.Decoder) (int, error) { +func (u *ChangeTrustResult) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding ChangeTrustResult: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = s.Trustor.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding AccountId: %s", err) - } - nTmp, err = s.Asset.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding AssetCode: %s", err) - } - nTmp, err = s.Authorize.DecodeFrom(d) + nTmp, err = u.Code.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Uint32: %s", err) + return n, fmt.Errorf("decoding ChangeTrustResultCode: %w", err) } - return n, nil + switch ChangeTrustResultCode(u.Code) { + case ChangeTrustResultCodeChangeTrustSuccess: + // Void + return n, nil + case ChangeTrustResultCodeChangeTrustMalformed: + // Void + return n, nil + case ChangeTrustResultCodeChangeTrustNoIssuer: + // Void + return n, nil + case ChangeTrustResultCodeChangeTrustInvalidLimit: + // Void + return n, nil + case ChangeTrustResultCodeChangeTrustLowReserve: + // Void + return n, nil + case ChangeTrustResultCodeChangeTrustSelfNotAllowed: + // Void + return n, nil + case ChangeTrustResultCodeChangeTrustTrustLineMissing: + // Void + return n, nil + case ChangeTrustResultCodeChangeTrustCannotDelete: + // Void + return n, nil + case ChangeTrustResultCodeChangeTrustNotAuthMaintainLiabilities: + // Void + return n, nil + } + return n, fmt.Errorf("union ChangeTrustResult has invalid Code (ChangeTrustResultCode) switch value '%d'", u.Code) } // MarshalBinary implements encoding.BinaryMarshaler. -func (s AllowTrustOp) MarshalBinary() ([]byte, error) { +func (s ChangeTrustResult) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -20071,84 +36648,106 @@ func (s AllowTrustOp) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *AllowTrustOp) UnmarshalBinary(inp []byte) error { +func (s *ChangeTrustResult) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*AllowTrustOp)(nil) - _ encoding.BinaryUnmarshaler = (*AllowTrustOp)(nil) + _ encoding.BinaryMarshaler = (*ChangeTrustResult)(nil) + _ encoding.BinaryUnmarshaler = (*ChangeTrustResult)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s AllowTrustOp) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s ChangeTrustResult) xdrType() {} -var _ xdrType = (*AllowTrustOp)(nil) +var _ xdrType = (*ChangeTrustResult)(nil) -// ManageDataOp is an XDR Struct defines as: +// AllowTrustResultCode is an XDR Enum defines as: // -// struct ManageDataOp +// enum AllowTrustResultCode // { -// string64 dataName; -// DataValue* dataValue; // set to null to clear +// // codes considered as "success" for the operation +// ALLOW_TRUST_SUCCESS = 0, +// // codes considered as "failure" for the operation +// ALLOW_TRUST_MALFORMED = -1, // asset is not ASSET_TYPE_ALPHANUM +// ALLOW_TRUST_NO_TRUST_LINE = -2, // trustor does not have a trustline +// // source account does not require trust +// ALLOW_TRUST_TRUST_NOT_REQUIRED = -3, +// ALLOW_TRUST_CANT_REVOKE = -4, // source account can't revoke trust, +// ALLOW_TRUST_SELF_NOT_ALLOWED = -5, // trusting self is not allowed +// ALLOW_TRUST_LOW_RESERVE = -6 // claimable balances can't be created +// // on revoke due to low reserves // }; -type ManageDataOp struct { - DataName String64 - DataValue *DataValue +type AllowTrustResultCode int32 + +const ( + AllowTrustResultCodeAllowTrustSuccess AllowTrustResultCode = 0 + AllowTrustResultCodeAllowTrustMalformed AllowTrustResultCode = -1 + AllowTrustResultCodeAllowTrustNoTrustLine AllowTrustResultCode = -2 + AllowTrustResultCodeAllowTrustTrustNotRequired AllowTrustResultCode = -3 + AllowTrustResultCodeAllowTrustCantRevoke AllowTrustResultCode = -4 + AllowTrustResultCodeAllowTrustSelfNotAllowed AllowTrustResultCode = -5 + AllowTrustResultCodeAllowTrustLowReserve AllowTrustResultCode = -6 +) + +var allowTrustResultCodeMap = map[int32]string{ + 0: "AllowTrustResultCodeAllowTrustSuccess", + -1: "AllowTrustResultCodeAllowTrustMalformed", + -2: "AllowTrustResultCodeAllowTrustNoTrustLine", + -3: "AllowTrustResultCodeAllowTrustTrustNotRequired", + -4: "AllowTrustResultCodeAllowTrustCantRevoke", + -5: "AllowTrustResultCodeAllowTrustSelfNotAllowed", + -6: "AllowTrustResultCodeAllowTrustLowReserve", +} + +// ValidEnum validates a proposed value for this enum. Implements +// the Enum interface for AllowTrustResultCode +func (e AllowTrustResultCode) ValidEnum(v int32) bool { + _, ok := allowTrustResultCodeMap[v] + return ok +} + +// String returns the name of `e` +func (e AllowTrustResultCode) String() string { + name, _ := allowTrustResultCodeMap[int32(e)] + return name } // EncodeTo encodes this value using the Encoder. -func (s *ManageDataOp) EncodeTo(e *xdr.Encoder) error { - var err error - if err = s.DataName.EncodeTo(e); err != nil { - return err - } - if _, err = e.EncodeBool(s.DataValue != nil); err != nil { - return err - } - if s.DataValue != nil { - if err = (*s.DataValue).EncodeTo(e); err != nil { - return err - } +func (e AllowTrustResultCode) EncodeTo(enc *xdr.Encoder) error { + if _, ok := allowTrustResultCodeMap[int32(e)]; !ok { + return fmt.Errorf("'%d' is not a valid AllowTrustResultCode enum value", e) } - return nil + _, err := enc.EncodeInt(int32(e)) + return err } -var _ decoderFrom = (*ManageDataOp)(nil) +var _ decoderFrom = (*AllowTrustResultCode)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *ManageDataOp) DecodeFrom(d *xdr.Decoder) (int, error) { - var err error - var n, nTmp int - nTmp, err = s.DataName.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding String64: %s", err) +func (e *AllowTrustResultCode) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding AllowTrustResultCode: %w", ErrMaxDecodingDepthReached) } - var b bool - b, nTmp, err = d.DecodeBool() - n += nTmp + maxDepth -= 1 + v, n, err := d.DecodeInt() if err != nil { - return n, fmt.Errorf("decoding DataValue: %s", err) + return n, fmt.Errorf("decoding AllowTrustResultCode: %w", err) } - s.DataValue = nil - if b { - s.DataValue = new(DataValue) - nTmp, err = s.DataValue.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding DataValue: %s", err) - } + if _, ok := allowTrustResultCodeMap[v]; !ok { + return n, fmt.Errorf("'%d' is not a valid AllowTrustResultCode enum value", v) } + *e = AllowTrustResultCode(v) return n, nil } // MarshalBinary implements encoding.BinaryMarshaler. -func (s ManageDataOp) MarshalBinary() ([]byte, error) { +func (s AllowTrustResultCode) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -20156,59 +36755,168 @@ func (s ManageDataOp) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *ManageDataOp) UnmarshalBinary(inp []byte) error { +func (s *AllowTrustResultCode) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*ManageDataOp)(nil) - _ encoding.BinaryUnmarshaler = (*ManageDataOp)(nil) + _ encoding.BinaryMarshaler = (*AllowTrustResultCode)(nil) + _ encoding.BinaryUnmarshaler = (*AllowTrustResultCode)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s ManageDataOp) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s AllowTrustResultCode) xdrType() {} -var _ xdrType = (*ManageDataOp)(nil) +var _ xdrType = (*AllowTrustResultCode)(nil) -// BumpSequenceOp is an XDR Struct defines as: +// AllowTrustResult is an XDR Union defines as: // -// struct BumpSequenceOp +// union AllowTrustResult switch (AllowTrustResultCode code) // { -// SequenceNumber bumpTo; +// case ALLOW_TRUST_SUCCESS: +// void; +// case ALLOW_TRUST_MALFORMED: +// case ALLOW_TRUST_NO_TRUST_LINE: +// case ALLOW_TRUST_TRUST_NOT_REQUIRED: +// case ALLOW_TRUST_CANT_REVOKE: +// case ALLOW_TRUST_SELF_NOT_ALLOWED: +// case ALLOW_TRUST_LOW_RESERVE: +// void; // }; -type BumpSequenceOp struct { - BumpTo SequenceNumber +type AllowTrustResult struct { + Code AllowTrustResultCode +} + +// SwitchFieldName returns the field name in which this union's +// discriminant is stored +func (u AllowTrustResult) SwitchFieldName() string { + return "Code" +} + +// ArmForSwitch returns which field name should be used for storing +// the value for an instance of AllowTrustResult +func (u AllowTrustResult) ArmForSwitch(sw int32) (string, bool) { + switch AllowTrustResultCode(sw) { + case AllowTrustResultCodeAllowTrustSuccess: + return "", true + case AllowTrustResultCodeAllowTrustMalformed: + return "", true + case AllowTrustResultCodeAllowTrustNoTrustLine: + return "", true + case AllowTrustResultCodeAllowTrustTrustNotRequired: + return "", true + case AllowTrustResultCodeAllowTrustCantRevoke: + return "", true + case AllowTrustResultCodeAllowTrustSelfNotAllowed: + return "", true + case AllowTrustResultCodeAllowTrustLowReserve: + return "", true + } + return "-", false +} + +// NewAllowTrustResult creates a new AllowTrustResult. +func NewAllowTrustResult(code AllowTrustResultCode, value interface{}) (result AllowTrustResult, err error) { + result.Code = code + switch AllowTrustResultCode(code) { + case AllowTrustResultCodeAllowTrustSuccess: + // void + case AllowTrustResultCodeAllowTrustMalformed: + // void + case AllowTrustResultCodeAllowTrustNoTrustLine: + // void + case AllowTrustResultCodeAllowTrustTrustNotRequired: + // void + case AllowTrustResultCodeAllowTrustCantRevoke: + // void + case AllowTrustResultCodeAllowTrustSelfNotAllowed: + // void + case AllowTrustResultCodeAllowTrustLowReserve: + // void + } + return } // EncodeTo encodes this value using the Encoder. -func (s *BumpSequenceOp) EncodeTo(e *xdr.Encoder) error { +func (u AllowTrustResult) EncodeTo(e *xdr.Encoder) error { var err error - if err = s.BumpTo.EncodeTo(e); err != nil { + if err = u.Code.EncodeTo(e); err != nil { return err } - return nil + switch AllowTrustResultCode(u.Code) { + case AllowTrustResultCodeAllowTrustSuccess: + // Void + return nil + case AllowTrustResultCodeAllowTrustMalformed: + // Void + return nil + case AllowTrustResultCodeAllowTrustNoTrustLine: + // Void + return nil + case AllowTrustResultCodeAllowTrustTrustNotRequired: + // Void + return nil + case AllowTrustResultCodeAllowTrustCantRevoke: + // Void + return nil + case AllowTrustResultCodeAllowTrustSelfNotAllowed: + // Void + return nil + case AllowTrustResultCodeAllowTrustLowReserve: + // Void + return nil + } + return fmt.Errorf("Code (AllowTrustResultCode) switch value '%d' is not valid for union AllowTrustResult", u.Code) } -var _ decoderFrom = (*BumpSequenceOp)(nil) +var _ decoderFrom = (*AllowTrustResult)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *BumpSequenceOp) DecodeFrom(d *xdr.Decoder) (int, error) { +func (u *AllowTrustResult) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding AllowTrustResult: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = s.BumpTo.DecodeFrom(d) + nTmp, err = u.Code.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding SequenceNumber: %s", err) + return n, fmt.Errorf("decoding AllowTrustResultCode: %w", err) } - return n, nil + switch AllowTrustResultCode(u.Code) { + case AllowTrustResultCodeAllowTrustSuccess: + // Void + return n, nil + case AllowTrustResultCodeAllowTrustMalformed: + // Void + return n, nil + case AllowTrustResultCodeAllowTrustNoTrustLine: + // Void + return n, nil + case AllowTrustResultCodeAllowTrustTrustNotRequired: + // Void + return n, nil + case AllowTrustResultCodeAllowTrustCantRevoke: + // Void + return n, nil + case AllowTrustResultCodeAllowTrustSelfNotAllowed: + // Void + return n, nil + case AllowTrustResultCodeAllowTrustLowReserve: + // Void + return n, nil + } + return n, fmt.Errorf("union AllowTrustResult has invalid Code (AllowTrustResultCode) switch value '%d'", u.Code) } // MarshalBinary implements encoding.BinaryMarshaler. -func (s BumpSequenceOp) MarshalBinary() ([]byte, error) { +func (s AllowTrustResult) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -20216,99 +36924,108 @@ func (s BumpSequenceOp) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *BumpSequenceOp) UnmarshalBinary(inp []byte) error { +func (s *AllowTrustResult) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*BumpSequenceOp)(nil) - _ encoding.BinaryUnmarshaler = (*BumpSequenceOp)(nil) + _ encoding.BinaryMarshaler = (*AllowTrustResult)(nil) + _ encoding.BinaryUnmarshaler = (*AllowTrustResult)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s BumpSequenceOp) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s AllowTrustResult) xdrType() {} -var _ xdrType = (*BumpSequenceOp)(nil) +var _ xdrType = (*AllowTrustResult)(nil) -// CreateClaimableBalanceOp is an XDR Struct defines as: +// AccountMergeResultCode is an XDR Enum defines as: // -// struct CreateClaimableBalanceOp +// enum AccountMergeResultCode // { -// Asset asset; -// int64 amount; -// Claimant claimants<10>; +// // codes considered as "success" for the operation +// ACCOUNT_MERGE_SUCCESS = 0, +// // codes considered as "failure" for the operation +// ACCOUNT_MERGE_MALFORMED = -1, // can't merge onto itself +// ACCOUNT_MERGE_NO_ACCOUNT = -2, // destination does not exist +// ACCOUNT_MERGE_IMMUTABLE_SET = -3, // source account has AUTH_IMMUTABLE set +// ACCOUNT_MERGE_HAS_SUB_ENTRIES = -4, // account has trust lines/offers +// ACCOUNT_MERGE_SEQNUM_TOO_FAR = -5, // sequence number is over max allowed +// ACCOUNT_MERGE_DEST_FULL = -6, // can't add source balance to +// // destination balance +// ACCOUNT_MERGE_IS_SPONSOR = -7 // can't merge account that is a sponsor // }; -type CreateClaimableBalanceOp struct { - Asset Asset - Amount Int64 - Claimants []Claimant `xdrmaxsize:"10"` +type AccountMergeResultCode int32 + +const ( + AccountMergeResultCodeAccountMergeSuccess AccountMergeResultCode = 0 + AccountMergeResultCodeAccountMergeMalformed AccountMergeResultCode = -1 + AccountMergeResultCodeAccountMergeNoAccount AccountMergeResultCode = -2 + AccountMergeResultCodeAccountMergeImmutableSet AccountMergeResultCode = -3 + AccountMergeResultCodeAccountMergeHasSubEntries AccountMergeResultCode = -4 + AccountMergeResultCodeAccountMergeSeqnumTooFar AccountMergeResultCode = -5 + AccountMergeResultCodeAccountMergeDestFull AccountMergeResultCode = -6 + AccountMergeResultCodeAccountMergeIsSponsor AccountMergeResultCode = -7 +) + +var accountMergeResultCodeMap = map[int32]string{ + 0: "AccountMergeResultCodeAccountMergeSuccess", + -1: "AccountMergeResultCodeAccountMergeMalformed", + -2: "AccountMergeResultCodeAccountMergeNoAccount", + -3: "AccountMergeResultCodeAccountMergeImmutableSet", + -4: "AccountMergeResultCodeAccountMergeHasSubEntries", + -5: "AccountMergeResultCodeAccountMergeSeqnumTooFar", + -6: "AccountMergeResultCodeAccountMergeDestFull", + -7: "AccountMergeResultCodeAccountMergeIsSponsor", +} + +// ValidEnum validates a proposed value for this enum. Implements +// the Enum interface for AccountMergeResultCode +func (e AccountMergeResultCode) ValidEnum(v int32) bool { + _, ok := accountMergeResultCodeMap[v] + return ok +} + +// String returns the name of `e` +func (e AccountMergeResultCode) String() string { + name, _ := accountMergeResultCodeMap[int32(e)] + return name } // EncodeTo encodes this value using the Encoder. -func (s *CreateClaimableBalanceOp) EncodeTo(e *xdr.Encoder) error { - var err error - if err = s.Asset.EncodeTo(e); err != nil { - return err - } - if err = s.Amount.EncodeTo(e); err != nil { - return err - } - if _, err = e.EncodeUint(uint32(len(s.Claimants))); err != nil { - return err - } - for i := 0; i < len(s.Claimants); i++ { - if err = s.Claimants[i].EncodeTo(e); err != nil { - return err - } +func (e AccountMergeResultCode) EncodeTo(enc *xdr.Encoder) error { + if _, ok := accountMergeResultCodeMap[int32(e)]; !ok { + return fmt.Errorf("'%d' is not a valid AccountMergeResultCode enum value", e) } - return nil + _, err := enc.EncodeInt(int32(e)) + return err } -var _ decoderFrom = (*CreateClaimableBalanceOp)(nil) +var _ decoderFrom = (*AccountMergeResultCode)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *CreateClaimableBalanceOp) DecodeFrom(d *xdr.Decoder) (int, error) { - var err error - var n, nTmp int - nTmp, err = s.Asset.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Asset: %s", err) - } - nTmp, err = s.Amount.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Int64: %s", err) +func (e *AccountMergeResultCode) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding AccountMergeResultCode: %w", ErrMaxDecodingDepthReached) } - var l uint32 - l, nTmp, err = d.DecodeUint() - n += nTmp + maxDepth -= 1 + v, n, err := d.DecodeInt() if err != nil { - return n, fmt.Errorf("decoding Claimant: %s", err) - } - if l > 10 { - return n, fmt.Errorf("decoding Claimant: data size (%d) exceeds size limit (10)", l) + return n, fmt.Errorf("decoding AccountMergeResultCode: %w", err) } - s.Claimants = nil - if l > 0 { - s.Claimants = make([]Claimant, l) - for i := uint32(0); i < l; i++ { - nTmp, err = s.Claimants[i].DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Claimant: %s", err) - } - } + if _, ok := accountMergeResultCodeMap[v]; !ok { + return n, fmt.Errorf("'%d' is not a valid AccountMergeResultCode enum value", v) } + *e = AccountMergeResultCode(v) return n, nil } // MarshalBinary implements encoding.BinaryMarshaler. -func (s CreateClaimableBalanceOp) MarshalBinary() ([]byte, error) { +func (s AccountMergeResultCode) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -20316,119 +37033,217 @@ func (s CreateClaimableBalanceOp) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *CreateClaimableBalanceOp) UnmarshalBinary(inp []byte) error { +func (s *AccountMergeResultCode) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*CreateClaimableBalanceOp)(nil) - _ encoding.BinaryUnmarshaler = (*CreateClaimableBalanceOp)(nil) + _ encoding.BinaryMarshaler = (*AccountMergeResultCode)(nil) + _ encoding.BinaryUnmarshaler = (*AccountMergeResultCode)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s CreateClaimableBalanceOp) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s AccountMergeResultCode) xdrType() {} -var _ xdrType = (*CreateClaimableBalanceOp)(nil) +var _ xdrType = (*AccountMergeResultCode)(nil) -// ClaimClaimableBalanceOp is an XDR Struct defines as: +// AccountMergeResult is an XDR Union defines as: // -// struct ClaimClaimableBalanceOp +// union AccountMergeResult switch (AccountMergeResultCode code) // { -// ClaimableBalanceID balanceID; +// case ACCOUNT_MERGE_SUCCESS: +// int64 sourceAccountBalance; // how much got transferred from source account +// case ACCOUNT_MERGE_MALFORMED: +// case ACCOUNT_MERGE_NO_ACCOUNT: +// case ACCOUNT_MERGE_IMMUTABLE_SET: +// case ACCOUNT_MERGE_HAS_SUB_ENTRIES: +// case ACCOUNT_MERGE_SEQNUM_TOO_FAR: +// case ACCOUNT_MERGE_DEST_FULL: +// case ACCOUNT_MERGE_IS_SPONSOR: +// void; // }; -type ClaimClaimableBalanceOp struct { - BalanceId ClaimableBalanceId +type AccountMergeResult struct { + Code AccountMergeResultCode + SourceAccountBalance *Int64 } -// EncodeTo encodes this value using the Encoder. -func (s *ClaimClaimableBalanceOp) EncodeTo(e *xdr.Encoder) error { - var err error - if err = s.BalanceId.EncodeTo(e); err != nil { - return err - } - return nil +// SwitchFieldName returns the field name in which this union's +// discriminant is stored +func (u AccountMergeResult) SwitchFieldName() string { + return "Code" } -var _ decoderFrom = (*ClaimClaimableBalanceOp)(nil) - -// DecodeFrom decodes this value using the Decoder. -func (s *ClaimClaimableBalanceOp) DecodeFrom(d *xdr.Decoder) (int, error) { - var err error - var n, nTmp int - nTmp, err = s.BalanceId.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding ClaimableBalanceId: %s", err) +// ArmForSwitch returns which field name should be used for storing +// the value for an instance of AccountMergeResult +func (u AccountMergeResult) ArmForSwitch(sw int32) (string, bool) { + switch AccountMergeResultCode(sw) { + case AccountMergeResultCodeAccountMergeSuccess: + return "SourceAccountBalance", true + case AccountMergeResultCodeAccountMergeMalformed: + return "", true + case AccountMergeResultCodeAccountMergeNoAccount: + return "", true + case AccountMergeResultCodeAccountMergeImmutableSet: + return "", true + case AccountMergeResultCodeAccountMergeHasSubEntries: + return "", true + case AccountMergeResultCodeAccountMergeSeqnumTooFar: + return "", true + case AccountMergeResultCodeAccountMergeDestFull: + return "", true + case AccountMergeResultCodeAccountMergeIsSponsor: + return "", true } - return n, nil + return "-", false } -// MarshalBinary implements encoding.BinaryMarshaler. -func (s ClaimClaimableBalanceOp) MarshalBinary() ([]byte, error) { - b := bytes.Buffer{} - e := xdr.NewEncoder(&b) - err := s.EncodeTo(e) - return b.Bytes(), err +// NewAccountMergeResult creates a new AccountMergeResult. +func NewAccountMergeResult(code AccountMergeResultCode, value interface{}) (result AccountMergeResult, err error) { + result.Code = code + switch AccountMergeResultCode(code) { + case AccountMergeResultCodeAccountMergeSuccess: + tv, ok := value.(Int64) + if !ok { + err = errors.New("invalid value, must be Int64") + return + } + result.SourceAccountBalance = &tv + case AccountMergeResultCodeAccountMergeMalformed: + // void + case AccountMergeResultCodeAccountMergeNoAccount: + // void + case AccountMergeResultCodeAccountMergeImmutableSet: + // void + case AccountMergeResultCodeAccountMergeHasSubEntries: + // void + case AccountMergeResultCodeAccountMergeSeqnumTooFar: + // void + case AccountMergeResultCodeAccountMergeDestFull: + // void + case AccountMergeResultCodeAccountMergeIsSponsor: + // void + } + return } -// UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *ClaimClaimableBalanceOp) UnmarshalBinary(inp []byte) error { - r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) - return err -} +// MustSourceAccountBalance retrieves the SourceAccountBalance value from the union, +// panicing if the value is not set. +func (u AccountMergeResult) MustSourceAccountBalance() Int64 { + val, ok := u.GetSourceAccountBalance() -var ( - _ encoding.BinaryMarshaler = (*ClaimClaimableBalanceOp)(nil) - _ encoding.BinaryUnmarshaler = (*ClaimClaimableBalanceOp)(nil) -) + if !ok { + panic("arm SourceAccountBalance is not set") + } -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s ClaimClaimableBalanceOp) xdrType() {} + return val +} + +// GetSourceAccountBalance retrieves the SourceAccountBalance value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u AccountMergeResult) GetSourceAccountBalance() (result Int64, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Code)) -var _ xdrType = (*ClaimClaimableBalanceOp)(nil) + if armName == "SourceAccountBalance" { + result = *u.SourceAccountBalance + ok = true + } -// BeginSponsoringFutureReservesOp is an XDR Struct defines as: -// -// struct BeginSponsoringFutureReservesOp -// { -// AccountID sponsoredID; -// }; -type BeginSponsoringFutureReservesOp struct { - SponsoredId AccountId + return } // EncodeTo encodes this value using the Encoder. -func (s *BeginSponsoringFutureReservesOp) EncodeTo(e *xdr.Encoder) error { +func (u AccountMergeResult) EncodeTo(e *xdr.Encoder) error { var err error - if err = s.SponsoredId.EncodeTo(e); err != nil { + if err = u.Code.EncodeTo(e); err != nil { return err } - return nil + switch AccountMergeResultCode(u.Code) { + case AccountMergeResultCodeAccountMergeSuccess: + if err = (*u.SourceAccountBalance).EncodeTo(e); err != nil { + return err + } + return nil + case AccountMergeResultCodeAccountMergeMalformed: + // Void + return nil + case AccountMergeResultCodeAccountMergeNoAccount: + // Void + return nil + case AccountMergeResultCodeAccountMergeImmutableSet: + // Void + return nil + case AccountMergeResultCodeAccountMergeHasSubEntries: + // Void + return nil + case AccountMergeResultCodeAccountMergeSeqnumTooFar: + // Void + return nil + case AccountMergeResultCodeAccountMergeDestFull: + // Void + return nil + case AccountMergeResultCodeAccountMergeIsSponsor: + // Void + return nil + } + return fmt.Errorf("Code (AccountMergeResultCode) switch value '%d' is not valid for union AccountMergeResult", u.Code) } -var _ decoderFrom = (*BeginSponsoringFutureReservesOp)(nil) +var _ decoderFrom = (*AccountMergeResult)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *BeginSponsoringFutureReservesOp) DecodeFrom(d *xdr.Decoder) (int, error) { +func (u *AccountMergeResult) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding AccountMergeResult: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = s.SponsoredId.DecodeFrom(d) + nTmp, err = u.Code.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding AccountId: %s", err) + return n, fmt.Errorf("decoding AccountMergeResultCode: %w", err) } - return n, nil + switch AccountMergeResultCode(u.Code) { + case AccountMergeResultCodeAccountMergeSuccess: + u.SourceAccountBalance = new(Int64) + nTmp, err = (*u.SourceAccountBalance).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Int64: %w", err) + } + return n, nil + case AccountMergeResultCodeAccountMergeMalformed: + // Void + return n, nil + case AccountMergeResultCodeAccountMergeNoAccount: + // Void + return n, nil + case AccountMergeResultCodeAccountMergeImmutableSet: + // Void + return n, nil + case AccountMergeResultCodeAccountMergeHasSubEntries: + // Void + return n, nil + case AccountMergeResultCodeAccountMergeSeqnumTooFar: + // Void + return n, nil + case AccountMergeResultCodeAccountMergeDestFull: + // Void + return n, nil + case AccountMergeResultCodeAccountMergeIsSponsor: + // Void + return n, nil + } + return n, fmt.Errorf("union AccountMergeResult has invalid Code (AccountMergeResultCode) switch value '%d'", u.Code) } // MarshalBinary implements encoding.BinaryMarshaler. -func (s BeginSponsoringFutureReservesOp) MarshalBinary() ([]byte, error) { +func (s AccountMergeResult) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -20436,82 +37251,89 @@ func (s BeginSponsoringFutureReservesOp) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *BeginSponsoringFutureReservesOp) UnmarshalBinary(inp []byte) error { +func (s *AccountMergeResult) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*BeginSponsoringFutureReservesOp)(nil) - _ encoding.BinaryUnmarshaler = (*BeginSponsoringFutureReservesOp)(nil) + _ encoding.BinaryMarshaler = (*AccountMergeResult)(nil) + _ encoding.BinaryUnmarshaler = (*AccountMergeResult)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s BeginSponsoringFutureReservesOp) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s AccountMergeResult) xdrType() {} -var _ xdrType = (*BeginSponsoringFutureReservesOp)(nil) +var _ xdrType = (*AccountMergeResult)(nil) -// RevokeSponsorshipType is an XDR Enum defines as: +// InflationResultCode is an XDR Enum defines as: // -// enum RevokeSponsorshipType +// enum InflationResultCode // { -// REVOKE_SPONSORSHIP_LEDGER_ENTRY = 0, -// REVOKE_SPONSORSHIP_SIGNER = 1 +// // codes considered as "success" for the operation +// INFLATION_SUCCESS = 0, +// // codes considered as "failure" for the operation +// INFLATION_NOT_TIME = -1 // }; -type RevokeSponsorshipType int32 +type InflationResultCode int32 const ( - RevokeSponsorshipTypeRevokeSponsorshipLedgerEntry RevokeSponsorshipType = 0 - RevokeSponsorshipTypeRevokeSponsorshipSigner RevokeSponsorshipType = 1 + InflationResultCodeInflationSuccess InflationResultCode = 0 + InflationResultCodeInflationNotTime InflationResultCode = -1 ) -var revokeSponsorshipTypeMap = map[int32]string{ - 0: "RevokeSponsorshipTypeRevokeSponsorshipLedgerEntry", - 1: "RevokeSponsorshipTypeRevokeSponsorshipSigner", +var inflationResultCodeMap = map[int32]string{ + 0: "InflationResultCodeInflationSuccess", + -1: "InflationResultCodeInflationNotTime", } // ValidEnum validates a proposed value for this enum. Implements -// the Enum interface for RevokeSponsorshipType -func (e RevokeSponsorshipType) ValidEnum(v int32) bool { - _, ok := revokeSponsorshipTypeMap[v] +// the Enum interface for InflationResultCode +func (e InflationResultCode) ValidEnum(v int32) bool { + _, ok := inflationResultCodeMap[v] return ok } // String returns the name of `e` -func (e RevokeSponsorshipType) String() string { - name, _ := revokeSponsorshipTypeMap[int32(e)] +func (e InflationResultCode) String() string { + name, _ := inflationResultCodeMap[int32(e)] return name } // EncodeTo encodes this value using the Encoder. -func (e RevokeSponsorshipType) EncodeTo(enc *xdr.Encoder) error { - if _, ok := revokeSponsorshipTypeMap[int32(e)]; !ok { - return fmt.Errorf("'%d' is not a valid RevokeSponsorshipType enum value", e) +func (e InflationResultCode) EncodeTo(enc *xdr.Encoder) error { + if _, ok := inflationResultCodeMap[int32(e)]; !ok { + return fmt.Errorf("'%d' is not a valid InflationResultCode enum value", e) } _, err := enc.EncodeInt(int32(e)) return err } -var _ decoderFrom = (*RevokeSponsorshipType)(nil) +var _ decoderFrom = (*InflationResultCode)(nil) // DecodeFrom decodes this value using the Decoder. -func (e *RevokeSponsorshipType) DecodeFrom(d *xdr.Decoder) (int, error) { +func (e *InflationResultCode) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding InflationResultCode: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 v, n, err := d.DecodeInt() if err != nil { - return n, fmt.Errorf("decoding RevokeSponsorshipType: %s", err) + return n, fmt.Errorf("decoding InflationResultCode: %w", err) } - if _, ok := revokeSponsorshipTypeMap[v]; !ok { - return n, fmt.Errorf("'%d' is not a valid RevokeSponsorshipType enum value", v) + if _, ok := inflationResultCodeMap[v]; !ok { + return n, fmt.Errorf("'%d' is not a valid InflationResultCode enum value", v) } - *e = RevokeSponsorshipType(v) + *e = InflationResultCode(v) return n, nil } // MarshalBinary implements encoding.BinaryMarshaler. -func (s RevokeSponsorshipType) MarshalBinary() ([]byte, error) { +func (s InflationResultCode) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -20519,69 +37341,74 @@ func (s RevokeSponsorshipType) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *RevokeSponsorshipType) UnmarshalBinary(inp []byte) error { +func (s *InflationResultCode) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*RevokeSponsorshipType)(nil) - _ encoding.BinaryUnmarshaler = (*RevokeSponsorshipType)(nil) + _ encoding.BinaryMarshaler = (*InflationResultCode)(nil) + _ encoding.BinaryUnmarshaler = (*InflationResultCode)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s RevokeSponsorshipType) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s InflationResultCode) xdrType() {} -var _ xdrType = (*RevokeSponsorshipType)(nil) +var _ xdrType = (*InflationResultCode)(nil) -// RevokeSponsorshipOpSigner is an XDR NestedStruct defines as: +// InflationPayout is an XDR Struct defines as: // -// struct -// { -// AccountID accountID; -// SignerKey signerKey; -// } -type RevokeSponsorshipOpSigner struct { - AccountId AccountId - SignerKey SignerKey +// struct InflationPayout // or use PaymentResultAtom to limit types? +// { +// AccountID destination; +// int64 amount; +// }; +type InflationPayout struct { + Destination AccountId + Amount Int64 } // EncodeTo encodes this value using the Encoder. -func (s *RevokeSponsorshipOpSigner) EncodeTo(e *xdr.Encoder) error { +func (s *InflationPayout) EncodeTo(e *xdr.Encoder) error { var err error - if err = s.AccountId.EncodeTo(e); err != nil { + if err = s.Destination.EncodeTo(e); err != nil { return err } - if err = s.SignerKey.EncodeTo(e); err != nil { + if err = s.Amount.EncodeTo(e); err != nil { return err } return nil } -var _ decoderFrom = (*RevokeSponsorshipOpSigner)(nil) +var _ decoderFrom = (*InflationPayout)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *RevokeSponsorshipOpSigner) DecodeFrom(d *xdr.Decoder) (int, error) { +func (s *InflationPayout) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding InflationPayout: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = s.AccountId.DecodeFrom(d) + nTmp, err = s.Destination.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding AccountId: %s", err) + return n, fmt.Errorf("decoding AccountId: %w", err) } - nTmp, err = s.SignerKey.DecodeFrom(d) + nTmp, err = s.Amount.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding SignerKey: %s", err) + return n, fmt.Errorf("decoding Int64: %w", err) } return n, nil } // MarshalBinary implements encoding.BinaryMarshaler. -func (s RevokeSponsorshipOpSigner) MarshalBinary() ([]byte, error) { +func (s InflationPayout) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -20589,127 +37416,93 @@ func (s RevokeSponsorshipOpSigner) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *RevokeSponsorshipOpSigner) UnmarshalBinary(inp []byte) error { +func (s *InflationPayout) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*RevokeSponsorshipOpSigner)(nil) - _ encoding.BinaryUnmarshaler = (*RevokeSponsorshipOpSigner)(nil) + _ encoding.BinaryMarshaler = (*InflationPayout)(nil) + _ encoding.BinaryUnmarshaler = (*InflationPayout)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s RevokeSponsorshipOpSigner) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s InflationPayout) xdrType() {} -var _ xdrType = (*RevokeSponsorshipOpSigner)(nil) +var _ xdrType = (*InflationPayout)(nil) -// RevokeSponsorshipOp is an XDR Union defines as: +// InflationResult is an XDR Union defines as: // -// union RevokeSponsorshipOp switch (RevokeSponsorshipType type) +// union InflationResult switch (InflationResultCode code) // { -// case REVOKE_SPONSORSHIP_LEDGER_ENTRY: -// LedgerKey ledgerKey; -// case REVOKE_SPONSORSHIP_SIGNER: -// struct -// { -// AccountID accountID; -// SignerKey signerKey; -// } signer; +// case INFLATION_SUCCESS: +// InflationPayout payouts<>; +// case INFLATION_NOT_TIME: +// void; // }; -type RevokeSponsorshipOp struct { - Type RevokeSponsorshipType - LedgerKey *LedgerKey - Signer *RevokeSponsorshipOpSigner +type InflationResult struct { + Code InflationResultCode + Payouts *[]InflationPayout } // SwitchFieldName returns the field name in which this union's // discriminant is stored -func (u RevokeSponsorshipOp) SwitchFieldName() string { - return "Type" +func (u InflationResult) SwitchFieldName() string { + return "Code" } // ArmForSwitch returns which field name should be used for storing -// the value for an instance of RevokeSponsorshipOp -func (u RevokeSponsorshipOp) ArmForSwitch(sw int32) (string, bool) { - switch RevokeSponsorshipType(sw) { - case RevokeSponsorshipTypeRevokeSponsorshipLedgerEntry: - return "LedgerKey", true - case RevokeSponsorshipTypeRevokeSponsorshipSigner: - return "Signer", true +// the value for an instance of InflationResult +func (u InflationResult) ArmForSwitch(sw int32) (string, bool) { + switch InflationResultCode(sw) { + case InflationResultCodeInflationSuccess: + return "Payouts", true + case InflationResultCodeInflationNotTime: + return "", true } return "-", false } -// NewRevokeSponsorshipOp creates a new RevokeSponsorshipOp. -func NewRevokeSponsorshipOp(aType RevokeSponsorshipType, value interface{}) (result RevokeSponsorshipOp, err error) { - result.Type = aType - switch RevokeSponsorshipType(aType) { - case RevokeSponsorshipTypeRevokeSponsorshipLedgerEntry: - tv, ok := value.(LedgerKey) - if !ok { - err = fmt.Errorf("invalid value, must be LedgerKey") - return - } - result.LedgerKey = &tv - case RevokeSponsorshipTypeRevokeSponsorshipSigner: - tv, ok := value.(RevokeSponsorshipOpSigner) +// NewInflationResult creates a new InflationResult. +func NewInflationResult(code InflationResultCode, value interface{}) (result InflationResult, err error) { + result.Code = code + switch InflationResultCode(code) { + case InflationResultCodeInflationSuccess: + tv, ok := value.([]InflationPayout) if !ok { - err = fmt.Errorf("invalid value, must be RevokeSponsorshipOpSigner") + err = errors.New("invalid value, must be []InflationPayout") return } - result.Signer = &tv - } - return -} - -// MustLedgerKey retrieves the LedgerKey value from the union, -// panicing if the value is not set. -func (u RevokeSponsorshipOp) MustLedgerKey() LedgerKey { - val, ok := u.GetLedgerKey() - - if !ok { - panic("arm LedgerKey is not set") - } - - return val -} - -// GetLedgerKey retrieves the LedgerKey value from the union, -// returning ok if the union's switch indicated the value is valid. -func (u RevokeSponsorshipOp) GetLedgerKey() (result LedgerKey, ok bool) { - armName, _ := u.ArmForSwitch(int32(u.Type)) - - if armName == "LedgerKey" { - result = *u.LedgerKey - ok = true + result.Payouts = &tv + case InflationResultCodeInflationNotTime: + // void } - return } -// MustSigner retrieves the Signer value from the union, +// MustPayouts retrieves the Payouts value from the union, // panicing if the value is not set. -func (u RevokeSponsorshipOp) MustSigner() RevokeSponsorshipOpSigner { - val, ok := u.GetSigner() +func (u InflationResult) MustPayouts() []InflationPayout { + val, ok := u.GetPayouts() if !ok { - panic("arm Signer is not set") + panic("arm Payouts is not set") } return val } -// GetSigner retrieves the Signer value from the union, +// GetPayouts retrieves the Payouts value from the union, // returning ok if the union's switch indicated the value is valid. -func (u RevokeSponsorshipOp) GetSigner() (result RevokeSponsorshipOpSigner, ok bool) { - armName, _ := u.ArmForSwitch(int32(u.Type)) +func (u InflationResult) GetPayouts() (result []InflationPayout, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Code)) - if armName == "Signer" { - result = *u.Signer + if armName == "Payouts" { + result = *u.Payouts ok = true } @@ -20717,60 +37510,77 @@ func (u RevokeSponsorshipOp) GetSigner() (result RevokeSponsorshipOpSigner, ok b } // EncodeTo encodes this value using the Encoder. -func (u RevokeSponsorshipOp) EncodeTo(e *xdr.Encoder) error { +func (u InflationResult) EncodeTo(e *xdr.Encoder) error { var err error - if err = u.Type.EncodeTo(e); err != nil { + if err = u.Code.EncodeTo(e); err != nil { return err } - switch RevokeSponsorshipType(u.Type) { - case RevokeSponsorshipTypeRevokeSponsorshipLedgerEntry: - if err = (*u.LedgerKey).EncodeTo(e); err != nil { + switch InflationResultCode(u.Code) { + case InflationResultCodeInflationSuccess: + if _, err = e.EncodeUint(uint32(len((*u.Payouts)))); err != nil { return err } - return nil - case RevokeSponsorshipTypeRevokeSponsorshipSigner: - if err = (*u.Signer).EncodeTo(e); err != nil { - return err + for i := 0; i < len((*u.Payouts)); i++ { + if err = (*u.Payouts)[i].EncodeTo(e); err != nil { + return err + } } return nil + case InflationResultCodeInflationNotTime: + // Void + return nil } - return fmt.Errorf("Type (RevokeSponsorshipType) switch value '%d' is not valid for union RevokeSponsorshipOp", u.Type) + return fmt.Errorf("Code (InflationResultCode) switch value '%d' is not valid for union InflationResult", u.Code) } -var _ decoderFrom = (*RevokeSponsorshipOp)(nil) +var _ decoderFrom = (*InflationResult)(nil) // DecodeFrom decodes this value using the Decoder. -func (u *RevokeSponsorshipOp) DecodeFrom(d *xdr.Decoder) (int, error) { +func (u *InflationResult) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding InflationResult: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = u.Type.DecodeFrom(d) + nTmp, err = u.Code.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding RevokeSponsorshipType: %s", err) + return n, fmt.Errorf("decoding InflationResultCode: %w", err) } - switch RevokeSponsorshipType(u.Type) { - case RevokeSponsorshipTypeRevokeSponsorshipLedgerEntry: - u.LedgerKey = new(LedgerKey) - nTmp, err = (*u.LedgerKey).DecodeFrom(d) + switch InflationResultCode(u.Code) { + case InflationResultCodeInflationSuccess: + u.Payouts = new([]InflationPayout) + var l uint32 + l, nTmp, err = d.DecodeUint() n += nTmp if err != nil { - return n, fmt.Errorf("decoding LedgerKey: %s", err) + return n, fmt.Errorf("decoding InflationPayout: %w", err) } - return n, nil - case RevokeSponsorshipTypeRevokeSponsorshipSigner: - u.Signer = new(RevokeSponsorshipOpSigner) - nTmp, err = (*u.Signer).DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding RevokeSponsorshipOpSigner: %s", err) + (*u.Payouts) = nil + if l > 0 { + if il, ok := d.InputLen(); ok && uint(il) < uint(l) { + return n, fmt.Errorf("decoding InflationPayout: length (%d) exceeds remaining input length (%d)", l, il) + } + (*u.Payouts) = make([]InflationPayout, l) + for i := uint32(0); i < l; i++ { + nTmp, err = (*u.Payouts)[i].DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding InflationPayout: %w", err) + } + } } return n, nil + case InflationResultCodeInflationNotTime: + // Void + return n, nil } - return n, fmt.Errorf("union RevokeSponsorshipOp has invalid Type (RevokeSponsorshipType) switch value '%d'", u.Type) + return n, fmt.Errorf("union InflationResult has invalid Code (InflationResultCode) switch value '%d'", u.Code) } // MarshalBinary implements encoding.BinaryMarshaler. -func (s RevokeSponsorshipOp) MarshalBinary() ([]byte, error) { +func (s InflationResult) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -20778,79 +37588,100 @@ func (s RevokeSponsorshipOp) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *RevokeSponsorshipOp) UnmarshalBinary(inp []byte) error { +func (s *InflationResult) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*RevokeSponsorshipOp)(nil) - _ encoding.BinaryUnmarshaler = (*RevokeSponsorshipOp)(nil) + _ encoding.BinaryMarshaler = (*InflationResult)(nil) + _ encoding.BinaryUnmarshaler = (*InflationResult)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s RevokeSponsorshipOp) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s InflationResult) xdrType() {} -var _ xdrType = (*RevokeSponsorshipOp)(nil) +var _ xdrType = (*InflationResult)(nil) -// ClawbackOp is an XDR Struct defines as: +// ManageDataResultCode is an XDR Enum defines as: // -// struct ClawbackOp +// enum ManageDataResultCode // { -// Asset asset; -// MuxedAccount from; -// int64 amount; +// // codes considered as "success" for the operation +// MANAGE_DATA_SUCCESS = 0, +// // codes considered as "failure" for the operation +// MANAGE_DATA_NOT_SUPPORTED_YET = +// -1, // The network hasn't moved to this protocol change yet +// MANAGE_DATA_NAME_NOT_FOUND = +// -2, // Trying to remove a Data Entry that isn't there +// MANAGE_DATA_LOW_RESERVE = -3, // not enough funds to create a new Data Entry +// MANAGE_DATA_INVALID_NAME = -4 // Name not a valid string // }; -type ClawbackOp struct { - Asset Asset - From MuxedAccount - Amount Int64 +type ManageDataResultCode int32 + +const ( + ManageDataResultCodeManageDataSuccess ManageDataResultCode = 0 + ManageDataResultCodeManageDataNotSupportedYet ManageDataResultCode = -1 + ManageDataResultCodeManageDataNameNotFound ManageDataResultCode = -2 + ManageDataResultCodeManageDataLowReserve ManageDataResultCode = -3 + ManageDataResultCodeManageDataInvalidName ManageDataResultCode = -4 +) + +var manageDataResultCodeMap = map[int32]string{ + 0: "ManageDataResultCodeManageDataSuccess", + -1: "ManageDataResultCodeManageDataNotSupportedYet", + -2: "ManageDataResultCodeManageDataNameNotFound", + -3: "ManageDataResultCodeManageDataLowReserve", + -4: "ManageDataResultCodeManageDataInvalidName", +} + +// ValidEnum validates a proposed value for this enum. Implements +// the Enum interface for ManageDataResultCode +func (e ManageDataResultCode) ValidEnum(v int32) bool { + _, ok := manageDataResultCodeMap[v] + return ok +} + +// String returns the name of `e` +func (e ManageDataResultCode) String() string { + name, _ := manageDataResultCodeMap[int32(e)] + return name } // EncodeTo encodes this value using the Encoder. -func (s *ClawbackOp) EncodeTo(e *xdr.Encoder) error { - var err error - if err = s.Asset.EncodeTo(e); err != nil { - return err - } - if err = s.From.EncodeTo(e); err != nil { - return err - } - if err = s.Amount.EncodeTo(e); err != nil { - return err +func (e ManageDataResultCode) EncodeTo(enc *xdr.Encoder) error { + if _, ok := manageDataResultCodeMap[int32(e)]; !ok { + return fmt.Errorf("'%d' is not a valid ManageDataResultCode enum value", e) } - return nil + _, err := enc.EncodeInt(int32(e)) + return err } -var _ decoderFrom = (*ClawbackOp)(nil) +var _ decoderFrom = (*ManageDataResultCode)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *ClawbackOp) DecodeFrom(d *xdr.Decoder) (int, error) { - var err error - var n, nTmp int - nTmp, err = s.Asset.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Asset: %s", err) +func (e *ManageDataResultCode) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding ManageDataResultCode: %w", ErrMaxDecodingDepthReached) } - nTmp, err = s.From.DecodeFrom(d) - n += nTmp + maxDepth -= 1 + v, n, err := d.DecodeInt() if err != nil { - return n, fmt.Errorf("decoding MuxedAccount: %s", err) + return n, fmt.Errorf("decoding ManageDataResultCode: %w", err) } - nTmp, err = s.Amount.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Int64: %s", err) + if _, ok := manageDataResultCodeMap[v]; !ok { + return n, fmt.Errorf("'%d' is not a valid ManageDataResultCode enum value", v) } + *e = ManageDataResultCode(v) return n, nil } // MarshalBinary implements encoding.BinaryMarshaler. -func (s ClawbackOp) MarshalBinary() ([]byte, error) { +func (s ManageDataResultCode) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -20858,59 +37689,146 @@ func (s ClawbackOp) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *ClawbackOp) UnmarshalBinary(inp []byte) error { +func (s *ManageDataResultCode) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*ClawbackOp)(nil) - _ encoding.BinaryUnmarshaler = (*ClawbackOp)(nil) + _ encoding.BinaryMarshaler = (*ManageDataResultCode)(nil) + _ encoding.BinaryUnmarshaler = (*ManageDataResultCode)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s ClawbackOp) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s ManageDataResultCode) xdrType() {} -var _ xdrType = (*ClawbackOp)(nil) +var _ xdrType = (*ManageDataResultCode)(nil) -// ClawbackClaimableBalanceOp is an XDR Struct defines as: +// ManageDataResult is an XDR Union defines as: // -// struct ClawbackClaimableBalanceOp +// union ManageDataResult switch (ManageDataResultCode code) // { -// ClaimableBalanceID balanceID; +// case MANAGE_DATA_SUCCESS: +// void; +// case MANAGE_DATA_NOT_SUPPORTED_YET: +// case MANAGE_DATA_NAME_NOT_FOUND: +// case MANAGE_DATA_LOW_RESERVE: +// case MANAGE_DATA_INVALID_NAME: +// void; // }; -type ClawbackClaimableBalanceOp struct { - BalanceId ClaimableBalanceId +type ManageDataResult struct { + Code ManageDataResultCode +} + +// SwitchFieldName returns the field name in which this union's +// discriminant is stored +func (u ManageDataResult) SwitchFieldName() string { + return "Code" +} + +// ArmForSwitch returns which field name should be used for storing +// the value for an instance of ManageDataResult +func (u ManageDataResult) ArmForSwitch(sw int32) (string, bool) { + switch ManageDataResultCode(sw) { + case ManageDataResultCodeManageDataSuccess: + return "", true + case ManageDataResultCodeManageDataNotSupportedYet: + return "", true + case ManageDataResultCodeManageDataNameNotFound: + return "", true + case ManageDataResultCodeManageDataLowReserve: + return "", true + case ManageDataResultCodeManageDataInvalidName: + return "", true + } + return "-", false +} + +// NewManageDataResult creates a new ManageDataResult. +func NewManageDataResult(code ManageDataResultCode, value interface{}) (result ManageDataResult, err error) { + result.Code = code + switch ManageDataResultCode(code) { + case ManageDataResultCodeManageDataSuccess: + // void + case ManageDataResultCodeManageDataNotSupportedYet: + // void + case ManageDataResultCodeManageDataNameNotFound: + // void + case ManageDataResultCodeManageDataLowReserve: + // void + case ManageDataResultCodeManageDataInvalidName: + // void + } + return } // EncodeTo encodes this value using the Encoder. -func (s *ClawbackClaimableBalanceOp) EncodeTo(e *xdr.Encoder) error { +func (u ManageDataResult) EncodeTo(e *xdr.Encoder) error { var err error - if err = s.BalanceId.EncodeTo(e); err != nil { + if err = u.Code.EncodeTo(e); err != nil { return err } - return nil + switch ManageDataResultCode(u.Code) { + case ManageDataResultCodeManageDataSuccess: + // Void + return nil + case ManageDataResultCodeManageDataNotSupportedYet: + // Void + return nil + case ManageDataResultCodeManageDataNameNotFound: + // Void + return nil + case ManageDataResultCodeManageDataLowReserve: + // Void + return nil + case ManageDataResultCodeManageDataInvalidName: + // Void + return nil + } + return fmt.Errorf("Code (ManageDataResultCode) switch value '%d' is not valid for union ManageDataResult", u.Code) } -var _ decoderFrom = (*ClawbackClaimableBalanceOp)(nil) +var _ decoderFrom = (*ManageDataResult)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *ClawbackClaimableBalanceOp) DecodeFrom(d *xdr.Decoder) (int, error) { +func (u *ManageDataResult) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding ManageDataResult: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = s.BalanceId.DecodeFrom(d) + nTmp, err = u.Code.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding ClaimableBalanceId: %s", err) + return n, fmt.Errorf("decoding ManageDataResultCode: %w", err) } - return n, nil + switch ManageDataResultCode(u.Code) { + case ManageDataResultCodeManageDataSuccess: + // Void + return n, nil + case ManageDataResultCodeManageDataNotSupportedYet: + // Void + return n, nil + case ManageDataResultCodeManageDataNameNotFound: + // Void + return n, nil + case ManageDataResultCodeManageDataLowReserve: + // Void + return n, nil + case ManageDataResultCodeManageDataInvalidName: + // Void + return n, nil + } + return n, fmt.Errorf("union ManageDataResult has invalid Code (ManageDataResultCode) switch value '%d'", u.Code) } // MarshalBinary implements encoding.BinaryMarshaler. -func (s ClawbackClaimableBalanceOp) MarshalBinary() ([]byte, error) { +func (s ManageDataResult) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -20918,90 +37836,89 @@ func (s ClawbackClaimableBalanceOp) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *ClawbackClaimableBalanceOp) UnmarshalBinary(inp []byte) error { +func (s *ManageDataResult) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*ClawbackClaimableBalanceOp)(nil) - _ encoding.BinaryUnmarshaler = (*ClawbackClaimableBalanceOp)(nil) + _ encoding.BinaryMarshaler = (*ManageDataResult)(nil) + _ encoding.BinaryUnmarshaler = (*ManageDataResult)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s ClawbackClaimableBalanceOp) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s ManageDataResult) xdrType() {} -var _ xdrType = (*ClawbackClaimableBalanceOp)(nil) +var _ xdrType = (*ManageDataResult)(nil) -// SetTrustLineFlagsOp is an XDR Struct defines as: +// BumpSequenceResultCode is an XDR Enum defines as: // -// struct SetTrustLineFlagsOp +// enum BumpSequenceResultCode // { -// AccountID trustor; -// Asset asset; -// -// uint32 clearFlags; // which flags to clear -// uint32 setFlags; // which flags to set +// // codes considered as "success" for the operation +// BUMP_SEQUENCE_SUCCESS = 0, +// // codes considered as "failure" for the operation +// BUMP_SEQUENCE_BAD_SEQ = -1 // `bumpTo` is not within bounds // }; -type SetTrustLineFlagsOp struct { - Trustor AccountId - Asset Asset - ClearFlags Uint32 - SetFlags Uint32 +type BumpSequenceResultCode int32 + +const ( + BumpSequenceResultCodeBumpSequenceSuccess BumpSequenceResultCode = 0 + BumpSequenceResultCodeBumpSequenceBadSeq BumpSequenceResultCode = -1 +) + +var bumpSequenceResultCodeMap = map[int32]string{ + 0: "BumpSequenceResultCodeBumpSequenceSuccess", + -1: "BumpSequenceResultCodeBumpSequenceBadSeq", +} + +// ValidEnum validates a proposed value for this enum. Implements +// the Enum interface for BumpSequenceResultCode +func (e BumpSequenceResultCode) ValidEnum(v int32) bool { + _, ok := bumpSequenceResultCodeMap[v] + return ok +} + +// String returns the name of `e` +func (e BumpSequenceResultCode) String() string { + name, _ := bumpSequenceResultCodeMap[int32(e)] + return name } // EncodeTo encodes this value using the Encoder. -func (s *SetTrustLineFlagsOp) EncodeTo(e *xdr.Encoder) error { - var err error - if err = s.Trustor.EncodeTo(e); err != nil { - return err - } - if err = s.Asset.EncodeTo(e); err != nil { - return err - } - if err = s.ClearFlags.EncodeTo(e); err != nil { - return err - } - if err = s.SetFlags.EncodeTo(e); err != nil { - return err +func (e BumpSequenceResultCode) EncodeTo(enc *xdr.Encoder) error { + if _, ok := bumpSequenceResultCodeMap[int32(e)]; !ok { + return fmt.Errorf("'%d' is not a valid BumpSequenceResultCode enum value", e) } - return nil + _, err := enc.EncodeInt(int32(e)) + return err } -var _ decoderFrom = (*SetTrustLineFlagsOp)(nil) +var _ decoderFrom = (*BumpSequenceResultCode)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *SetTrustLineFlagsOp) DecodeFrom(d *xdr.Decoder) (int, error) { - var err error - var n, nTmp int - nTmp, err = s.Trustor.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding AccountId: %s", err) - } - nTmp, err = s.Asset.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Asset: %s", err) +func (e *BumpSequenceResultCode) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding BumpSequenceResultCode: %w", ErrMaxDecodingDepthReached) } - nTmp, err = s.ClearFlags.DecodeFrom(d) - n += nTmp + maxDepth -= 1 + v, n, err := d.DecodeInt() if err != nil { - return n, fmt.Errorf("decoding Uint32: %s", err) + return n, fmt.Errorf("decoding BumpSequenceResultCode: %w", err) } - nTmp, err = s.SetFlags.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Uint32: %s", err) + if _, ok := bumpSequenceResultCodeMap[v]; !ok { + return n, fmt.Errorf("'%d' is not a valid BumpSequenceResultCode enum value", v) } + *e = BumpSequenceResultCode(v) return n, nil } // MarshalBinary implements encoding.BinaryMarshaler. -func (s SetTrustLineFlagsOp) MarshalBinary() ([]byte, error) { +func (s BumpSequenceResultCode) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -21009,104 +37926,113 @@ func (s SetTrustLineFlagsOp) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *SetTrustLineFlagsOp) UnmarshalBinary(inp []byte) error { +func (s *BumpSequenceResultCode) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*SetTrustLineFlagsOp)(nil) - _ encoding.BinaryUnmarshaler = (*SetTrustLineFlagsOp)(nil) + _ encoding.BinaryMarshaler = (*BumpSequenceResultCode)(nil) + _ encoding.BinaryUnmarshaler = (*BumpSequenceResultCode)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s SetTrustLineFlagsOp) xdrType() {} - -var _ xdrType = (*SetTrustLineFlagsOp)(nil) +// xdrType signals that this type represents XDR values defined by this package. +func (s BumpSequenceResultCode) xdrType() {} -// LiquidityPoolFeeV18 is an XDR Const defines as: -// -// const LIQUIDITY_POOL_FEE_V18 = 30; -const LiquidityPoolFeeV18 = 30 +var _ xdrType = (*BumpSequenceResultCode)(nil) -// LiquidityPoolDepositOp is an XDR Struct defines as: +// BumpSequenceResult is an XDR Union defines as: // -// struct LiquidityPoolDepositOp +// union BumpSequenceResult switch (BumpSequenceResultCode code) // { -// PoolID liquidityPoolID; -// int64 maxAmountA; // maximum amount of first asset to deposit -// int64 maxAmountB; // maximum amount of second asset to deposit -// Price minPrice; // minimum depositA/depositB -// Price maxPrice; // maximum depositA/depositB +// case BUMP_SEQUENCE_SUCCESS: +// void; +// case BUMP_SEQUENCE_BAD_SEQ: +// void; // }; -type LiquidityPoolDepositOp struct { - LiquidityPoolId PoolId - MaxAmountA Int64 - MaxAmountB Int64 - MinPrice Price - MaxPrice Price +type BumpSequenceResult struct { + Code BumpSequenceResultCode } -// EncodeTo encodes this value using the Encoder. -func (s *LiquidityPoolDepositOp) EncodeTo(e *xdr.Encoder) error { - var err error - if err = s.LiquidityPoolId.EncodeTo(e); err != nil { - return err - } - if err = s.MaxAmountA.EncodeTo(e); err != nil { - return err +// SwitchFieldName returns the field name in which this union's +// discriminant is stored +func (u BumpSequenceResult) SwitchFieldName() string { + return "Code" +} + +// ArmForSwitch returns which field name should be used for storing +// the value for an instance of BumpSequenceResult +func (u BumpSequenceResult) ArmForSwitch(sw int32) (string, bool) { + switch BumpSequenceResultCode(sw) { + case BumpSequenceResultCodeBumpSequenceSuccess: + return "", true + case BumpSequenceResultCodeBumpSequenceBadSeq: + return "", true } - if err = s.MaxAmountB.EncodeTo(e); err != nil { - return err + return "-", false +} + +// NewBumpSequenceResult creates a new BumpSequenceResult. +func NewBumpSequenceResult(code BumpSequenceResultCode, value interface{}) (result BumpSequenceResult, err error) { + result.Code = code + switch BumpSequenceResultCode(code) { + case BumpSequenceResultCodeBumpSequenceSuccess: + // void + case BumpSequenceResultCodeBumpSequenceBadSeq: + // void } - if err = s.MinPrice.EncodeTo(e); err != nil { + return +} + +// EncodeTo encodes this value using the Encoder. +func (u BumpSequenceResult) EncodeTo(e *xdr.Encoder) error { + var err error + if err = u.Code.EncodeTo(e); err != nil { return err } - if err = s.MaxPrice.EncodeTo(e); err != nil { - return err + switch BumpSequenceResultCode(u.Code) { + case BumpSequenceResultCodeBumpSequenceSuccess: + // Void + return nil + case BumpSequenceResultCodeBumpSequenceBadSeq: + // Void + return nil } - return nil + return fmt.Errorf("Code (BumpSequenceResultCode) switch value '%d' is not valid for union BumpSequenceResult", u.Code) } -var _ decoderFrom = (*LiquidityPoolDepositOp)(nil) +var _ decoderFrom = (*BumpSequenceResult)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *LiquidityPoolDepositOp) DecodeFrom(d *xdr.Decoder) (int, error) { +func (u *BumpSequenceResult) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding BumpSequenceResult: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = s.LiquidityPoolId.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding PoolId: %s", err) - } - nTmp, err = s.MaxAmountA.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Int64: %s", err) - } - nTmp, err = s.MaxAmountB.DecodeFrom(d) + nTmp, err = u.Code.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Int64: %s", err) + return n, fmt.Errorf("decoding BumpSequenceResultCode: %w", err) } - nTmp, err = s.MinPrice.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Price: %s", err) - } - nTmp, err = s.MaxPrice.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Price: %s", err) + switch BumpSequenceResultCode(u.Code) { + case BumpSequenceResultCodeBumpSequenceSuccess: + // Void + return n, nil + case BumpSequenceResultCodeBumpSequenceBadSeq: + // Void + return n, nil } - return n, nil + return n, fmt.Errorf("union BumpSequenceResult has invalid Code (BumpSequenceResultCode) switch value '%d'", u.Code) } // MarshalBinary implements encoding.BinaryMarshaler. -func (s LiquidityPoolDepositOp) MarshalBinary() ([]byte, error) { +func (s BumpSequenceResult) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -21114,89 +38040,99 @@ func (s LiquidityPoolDepositOp) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *LiquidityPoolDepositOp) UnmarshalBinary(inp []byte) error { +func (s *BumpSequenceResult) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*LiquidityPoolDepositOp)(nil) - _ encoding.BinaryUnmarshaler = (*LiquidityPoolDepositOp)(nil) + _ encoding.BinaryMarshaler = (*BumpSequenceResult)(nil) + _ encoding.BinaryUnmarshaler = (*BumpSequenceResult)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s LiquidityPoolDepositOp) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s BumpSequenceResult) xdrType() {} -var _ xdrType = (*LiquidityPoolDepositOp)(nil) +var _ xdrType = (*BumpSequenceResult)(nil) -// LiquidityPoolWithdrawOp is an XDR Struct defines as: +// CreateClaimableBalanceResultCode is an XDR Enum defines as: // -// struct LiquidityPoolWithdrawOp +// enum CreateClaimableBalanceResultCode // { -// PoolID liquidityPoolID; -// int64 amount; // amount of pool shares to withdraw -// int64 minAmountA; // minimum amount of first asset to withdraw -// int64 minAmountB; // minimum amount of second asset to withdraw +// CREATE_CLAIMABLE_BALANCE_SUCCESS = 0, +// CREATE_CLAIMABLE_BALANCE_MALFORMED = -1, +// CREATE_CLAIMABLE_BALANCE_LOW_RESERVE = -2, +// CREATE_CLAIMABLE_BALANCE_NO_TRUST = -3, +// CREATE_CLAIMABLE_BALANCE_NOT_AUTHORIZED = -4, +// CREATE_CLAIMABLE_BALANCE_UNDERFUNDED = -5 // }; -type LiquidityPoolWithdrawOp struct { - LiquidityPoolId PoolId - Amount Int64 - MinAmountA Int64 - MinAmountB Int64 +type CreateClaimableBalanceResultCode int32 + +const ( + CreateClaimableBalanceResultCodeCreateClaimableBalanceSuccess CreateClaimableBalanceResultCode = 0 + CreateClaimableBalanceResultCodeCreateClaimableBalanceMalformed CreateClaimableBalanceResultCode = -1 + CreateClaimableBalanceResultCodeCreateClaimableBalanceLowReserve CreateClaimableBalanceResultCode = -2 + CreateClaimableBalanceResultCodeCreateClaimableBalanceNoTrust CreateClaimableBalanceResultCode = -3 + CreateClaimableBalanceResultCodeCreateClaimableBalanceNotAuthorized CreateClaimableBalanceResultCode = -4 + CreateClaimableBalanceResultCodeCreateClaimableBalanceUnderfunded CreateClaimableBalanceResultCode = -5 +) + +var createClaimableBalanceResultCodeMap = map[int32]string{ + 0: "CreateClaimableBalanceResultCodeCreateClaimableBalanceSuccess", + -1: "CreateClaimableBalanceResultCodeCreateClaimableBalanceMalformed", + -2: "CreateClaimableBalanceResultCodeCreateClaimableBalanceLowReserve", + -3: "CreateClaimableBalanceResultCodeCreateClaimableBalanceNoTrust", + -4: "CreateClaimableBalanceResultCodeCreateClaimableBalanceNotAuthorized", + -5: "CreateClaimableBalanceResultCodeCreateClaimableBalanceUnderfunded", +} + +// ValidEnum validates a proposed value for this enum. Implements +// the Enum interface for CreateClaimableBalanceResultCode +func (e CreateClaimableBalanceResultCode) ValidEnum(v int32) bool { + _, ok := createClaimableBalanceResultCodeMap[v] + return ok +} + +// String returns the name of `e` +func (e CreateClaimableBalanceResultCode) String() string { + name, _ := createClaimableBalanceResultCodeMap[int32(e)] + return name } // EncodeTo encodes this value using the Encoder. -func (s *LiquidityPoolWithdrawOp) EncodeTo(e *xdr.Encoder) error { - var err error - if err = s.LiquidityPoolId.EncodeTo(e); err != nil { - return err - } - if err = s.Amount.EncodeTo(e); err != nil { - return err - } - if err = s.MinAmountA.EncodeTo(e); err != nil { - return err - } - if err = s.MinAmountB.EncodeTo(e); err != nil { - return err +func (e CreateClaimableBalanceResultCode) EncodeTo(enc *xdr.Encoder) error { + if _, ok := createClaimableBalanceResultCodeMap[int32(e)]; !ok { + return fmt.Errorf("'%d' is not a valid CreateClaimableBalanceResultCode enum value", e) } - return nil + _, err := enc.EncodeInt(int32(e)) + return err } -var _ decoderFrom = (*LiquidityPoolWithdrawOp)(nil) +var _ decoderFrom = (*CreateClaimableBalanceResultCode)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *LiquidityPoolWithdrawOp) DecodeFrom(d *xdr.Decoder) (int, error) { - var err error - var n, nTmp int - nTmp, err = s.LiquidityPoolId.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding PoolId: %s", err) - } - nTmp, err = s.Amount.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Int64: %s", err) +func (e *CreateClaimableBalanceResultCode) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding CreateClaimableBalanceResultCode: %w", ErrMaxDecodingDepthReached) } - nTmp, err = s.MinAmountA.DecodeFrom(d) - n += nTmp + maxDepth -= 1 + v, n, err := d.DecodeInt() if err != nil { - return n, fmt.Errorf("decoding Int64: %s", err) + return n, fmt.Errorf("decoding CreateClaimableBalanceResultCode: %w", err) } - nTmp, err = s.MinAmountB.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Int64: %s", err) + if _, ok := createClaimableBalanceResultCodeMap[v]; !ok { + return n, fmt.Errorf("'%d' is not a valid CreateClaimableBalanceResultCode enum value", v) } + *e = CreateClaimableBalanceResultCode(v) return n, nil } // MarshalBinary implements encoding.BinaryMarshaler. -func (s LiquidityPoolWithdrawOp) MarshalBinary() ([]byte, error) { +func (s CreateClaimableBalanceResultCode) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -21204,1208 +38140,1155 @@ func (s LiquidityPoolWithdrawOp) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *LiquidityPoolWithdrawOp) UnmarshalBinary(inp []byte) error { +func (s *CreateClaimableBalanceResultCode) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*LiquidityPoolWithdrawOp)(nil) - _ encoding.BinaryUnmarshaler = (*LiquidityPoolWithdrawOp)(nil) + _ encoding.BinaryMarshaler = (*CreateClaimableBalanceResultCode)(nil) + _ encoding.BinaryUnmarshaler = (*CreateClaimableBalanceResultCode)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s LiquidityPoolWithdrawOp) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s CreateClaimableBalanceResultCode) xdrType() {} -var _ xdrType = (*LiquidityPoolWithdrawOp)(nil) +var _ xdrType = (*CreateClaimableBalanceResultCode)(nil) -// OperationBody is an XDR NestedUnion defines as: +// CreateClaimableBalanceResult is an XDR Union defines as: // -// union switch (OperationType type) -// { -// case CREATE_ACCOUNT: -// CreateAccountOp createAccountOp; -// case PAYMENT: -// PaymentOp paymentOp; -// case PATH_PAYMENT_STRICT_RECEIVE: -// PathPaymentStrictReceiveOp pathPaymentStrictReceiveOp; -// case MANAGE_SELL_OFFER: -// ManageSellOfferOp manageSellOfferOp; -// case CREATE_PASSIVE_SELL_OFFER: -// CreatePassiveSellOfferOp createPassiveSellOfferOp; -// case SET_OPTIONS: -// SetOptionsOp setOptionsOp; -// case CHANGE_TRUST: -// ChangeTrustOp changeTrustOp; -// case ALLOW_TRUST: -// AllowTrustOp allowTrustOp; -// case ACCOUNT_MERGE: -// MuxedAccount destination; -// case INFLATION: -// void; -// case MANAGE_DATA: -// ManageDataOp manageDataOp; -// case BUMP_SEQUENCE: -// BumpSequenceOp bumpSequenceOp; -// case MANAGE_BUY_OFFER: -// ManageBuyOfferOp manageBuyOfferOp; -// case PATH_PAYMENT_STRICT_SEND: -// PathPaymentStrictSendOp pathPaymentStrictSendOp; -// case CREATE_CLAIMABLE_BALANCE: -// CreateClaimableBalanceOp createClaimableBalanceOp; -// case CLAIM_CLAIMABLE_BALANCE: -// ClaimClaimableBalanceOp claimClaimableBalanceOp; -// case BEGIN_SPONSORING_FUTURE_RESERVES: -// BeginSponsoringFutureReservesOp beginSponsoringFutureReservesOp; -// case END_SPONSORING_FUTURE_RESERVES: -// void; -// case REVOKE_SPONSORSHIP: -// RevokeSponsorshipOp revokeSponsorshipOp; -// case CLAWBACK: -// ClawbackOp clawbackOp; -// case CLAWBACK_CLAIMABLE_BALANCE: -// ClawbackClaimableBalanceOp clawbackClaimableBalanceOp; -// case SET_TRUST_LINE_FLAGS: -// SetTrustLineFlagsOp setTrustLineFlagsOp; -// case LIQUIDITY_POOL_DEPOSIT: -// LiquidityPoolDepositOp liquidityPoolDepositOp; -// case LIQUIDITY_POOL_WITHDRAW: -// LiquidityPoolWithdrawOp liquidityPoolWithdrawOp; -// } -type OperationBody struct { - Type OperationType - CreateAccountOp *CreateAccountOp - PaymentOp *PaymentOp - PathPaymentStrictReceiveOp *PathPaymentStrictReceiveOp - ManageSellOfferOp *ManageSellOfferOp - CreatePassiveSellOfferOp *CreatePassiveSellOfferOp - SetOptionsOp *SetOptionsOp - ChangeTrustOp *ChangeTrustOp - AllowTrustOp *AllowTrustOp - Destination *MuxedAccount - ManageDataOp *ManageDataOp - BumpSequenceOp *BumpSequenceOp - ManageBuyOfferOp *ManageBuyOfferOp - PathPaymentStrictSendOp *PathPaymentStrictSendOp - CreateClaimableBalanceOp *CreateClaimableBalanceOp - ClaimClaimableBalanceOp *ClaimClaimableBalanceOp - BeginSponsoringFutureReservesOp *BeginSponsoringFutureReservesOp - RevokeSponsorshipOp *RevokeSponsorshipOp - ClawbackOp *ClawbackOp - ClawbackClaimableBalanceOp *ClawbackClaimableBalanceOp - SetTrustLineFlagsOp *SetTrustLineFlagsOp - LiquidityPoolDepositOp *LiquidityPoolDepositOp - LiquidityPoolWithdrawOp *LiquidityPoolWithdrawOp +// union CreateClaimableBalanceResult switch ( +// CreateClaimableBalanceResultCode code) +// { +// case CREATE_CLAIMABLE_BALANCE_SUCCESS: +// ClaimableBalanceID balanceID; +// case CREATE_CLAIMABLE_BALANCE_MALFORMED: +// case CREATE_CLAIMABLE_BALANCE_LOW_RESERVE: +// case CREATE_CLAIMABLE_BALANCE_NO_TRUST: +// case CREATE_CLAIMABLE_BALANCE_NOT_AUTHORIZED: +// case CREATE_CLAIMABLE_BALANCE_UNDERFUNDED: +// void; +// }; +type CreateClaimableBalanceResult struct { + Code CreateClaimableBalanceResultCode + BalanceId *ClaimableBalanceId } // SwitchFieldName returns the field name in which this union's // discriminant is stored -func (u OperationBody) SwitchFieldName() string { - return "Type" +func (u CreateClaimableBalanceResult) SwitchFieldName() string { + return "Code" } // ArmForSwitch returns which field name should be used for storing -// the value for an instance of OperationBody -func (u OperationBody) ArmForSwitch(sw int32) (string, bool) { - switch OperationType(sw) { - case OperationTypeCreateAccount: - return "CreateAccountOp", true - case OperationTypePayment: - return "PaymentOp", true - case OperationTypePathPaymentStrictReceive: - return "PathPaymentStrictReceiveOp", true - case OperationTypeManageSellOffer: - return "ManageSellOfferOp", true - case OperationTypeCreatePassiveSellOffer: - return "CreatePassiveSellOfferOp", true - case OperationTypeSetOptions: - return "SetOptionsOp", true - case OperationTypeChangeTrust: - return "ChangeTrustOp", true - case OperationTypeAllowTrust: - return "AllowTrustOp", true - case OperationTypeAccountMerge: - return "Destination", true - case OperationTypeInflation: +// the value for an instance of CreateClaimableBalanceResult +func (u CreateClaimableBalanceResult) ArmForSwitch(sw int32) (string, bool) { + switch CreateClaimableBalanceResultCode(sw) { + case CreateClaimableBalanceResultCodeCreateClaimableBalanceSuccess: + return "BalanceId", true + case CreateClaimableBalanceResultCodeCreateClaimableBalanceMalformed: return "", true - case OperationTypeManageData: - return "ManageDataOp", true - case OperationTypeBumpSequence: - return "BumpSequenceOp", true - case OperationTypeManageBuyOffer: - return "ManageBuyOfferOp", true - case OperationTypePathPaymentStrictSend: - return "PathPaymentStrictSendOp", true - case OperationTypeCreateClaimableBalance: - return "CreateClaimableBalanceOp", true - case OperationTypeClaimClaimableBalance: - return "ClaimClaimableBalanceOp", true - case OperationTypeBeginSponsoringFutureReserves: - return "BeginSponsoringFutureReservesOp", true - case OperationTypeEndSponsoringFutureReserves: + case CreateClaimableBalanceResultCodeCreateClaimableBalanceLowReserve: + return "", true + case CreateClaimableBalanceResultCodeCreateClaimableBalanceNoTrust: + return "", true + case CreateClaimableBalanceResultCodeCreateClaimableBalanceNotAuthorized: + return "", true + case CreateClaimableBalanceResultCodeCreateClaimableBalanceUnderfunded: return "", true - case OperationTypeRevokeSponsorship: - return "RevokeSponsorshipOp", true - case OperationTypeClawback: - return "ClawbackOp", true - case OperationTypeClawbackClaimableBalance: - return "ClawbackClaimableBalanceOp", true - case OperationTypeSetTrustLineFlags: - return "SetTrustLineFlagsOp", true - case OperationTypeLiquidityPoolDeposit: - return "LiquidityPoolDepositOp", true - case OperationTypeLiquidityPoolWithdraw: - return "LiquidityPoolWithdrawOp", true } return "-", false } -// NewOperationBody creates a new OperationBody. -func NewOperationBody(aType OperationType, value interface{}) (result OperationBody, err error) { - result.Type = aType - switch OperationType(aType) { - case OperationTypeCreateAccount: - tv, ok := value.(CreateAccountOp) - if !ok { - err = fmt.Errorf("invalid value, must be CreateAccountOp") - return - } - result.CreateAccountOp = &tv - case OperationTypePayment: - tv, ok := value.(PaymentOp) - if !ok { - err = fmt.Errorf("invalid value, must be PaymentOp") - return - } - result.PaymentOp = &tv - case OperationTypePathPaymentStrictReceive: - tv, ok := value.(PathPaymentStrictReceiveOp) - if !ok { - err = fmt.Errorf("invalid value, must be PathPaymentStrictReceiveOp") - return - } - result.PathPaymentStrictReceiveOp = &tv - case OperationTypeManageSellOffer: - tv, ok := value.(ManageSellOfferOp) - if !ok { - err = fmt.Errorf("invalid value, must be ManageSellOfferOp") - return - } - result.ManageSellOfferOp = &tv - case OperationTypeCreatePassiveSellOffer: - tv, ok := value.(CreatePassiveSellOfferOp) - if !ok { - err = fmt.Errorf("invalid value, must be CreatePassiveSellOfferOp") - return - } - result.CreatePassiveSellOfferOp = &tv - case OperationTypeSetOptions: - tv, ok := value.(SetOptionsOp) - if !ok { - err = fmt.Errorf("invalid value, must be SetOptionsOp") - return - } - result.SetOptionsOp = &tv - case OperationTypeChangeTrust: - tv, ok := value.(ChangeTrustOp) - if !ok { - err = fmt.Errorf("invalid value, must be ChangeTrustOp") - return - } - result.ChangeTrustOp = &tv - case OperationTypeAllowTrust: - tv, ok := value.(AllowTrustOp) - if !ok { - err = fmt.Errorf("invalid value, must be AllowTrustOp") - return - } - result.AllowTrustOp = &tv - case OperationTypeAccountMerge: - tv, ok := value.(MuxedAccount) +// NewCreateClaimableBalanceResult creates a new CreateClaimableBalanceResult. +func NewCreateClaimableBalanceResult(code CreateClaimableBalanceResultCode, value interface{}) (result CreateClaimableBalanceResult, err error) { + result.Code = code + switch CreateClaimableBalanceResultCode(code) { + case CreateClaimableBalanceResultCodeCreateClaimableBalanceSuccess: + tv, ok := value.(ClaimableBalanceId) if !ok { - err = fmt.Errorf("invalid value, must be MuxedAccount") + err = errors.New("invalid value, must be ClaimableBalanceId") return } - result.Destination = &tv - case OperationTypeInflation: + result.BalanceId = &tv + case CreateClaimableBalanceResultCodeCreateClaimableBalanceMalformed: // void - case OperationTypeManageData: - tv, ok := value.(ManageDataOp) - if !ok { - err = fmt.Errorf("invalid value, must be ManageDataOp") - return - } - result.ManageDataOp = &tv - case OperationTypeBumpSequence: - tv, ok := value.(BumpSequenceOp) - if !ok { - err = fmt.Errorf("invalid value, must be BumpSequenceOp") - return - } - result.BumpSequenceOp = &tv - case OperationTypeManageBuyOffer: - tv, ok := value.(ManageBuyOfferOp) - if !ok { - err = fmt.Errorf("invalid value, must be ManageBuyOfferOp") - return - } - result.ManageBuyOfferOp = &tv - case OperationTypePathPaymentStrictSend: - tv, ok := value.(PathPaymentStrictSendOp) - if !ok { - err = fmt.Errorf("invalid value, must be PathPaymentStrictSendOp") - return - } - result.PathPaymentStrictSendOp = &tv - case OperationTypeCreateClaimableBalance: - tv, ok := value.(CreateClaimableBalanceOp) - if !ok { - err = fmt.Errorf("invalid value, must be CreateClaimableBalanceOp") - return - } - result.CreateClaimableBalanceOp = &tv - case OperationTypeClaimClaimableBalance: - tv, ok := value.(ClaimClaimableBalanceOp) - if !ok { - err = fmt.Errorf("invalid value, must be ClaimClaimableBalanceOp") - return - } - result.ClaimClaimableBalanceOp = &tv - case OperationTypeBeginSponsoringFutureReserves: - tv, ok := value.(BeginSponsoringFutureReservesOp) - if !ok { - err = fmt.Errorf("invalid value, must be BeginSponsoringFutureReservesOp") - return - } - result.BeginSponsoringFutureReservesOp = &tv - case OperationTypeEndSponsoringFutureReserves: + case CreateClaimableBalanceResultCodeCreateClaimableBalanceLowReserve: + // void + case CreateClaimableBalanceResultCodeCreateClaimableBalanceNoTrust: + // void + case CreateClaimableBalanceResultCodeCreateClaimableBalanceNotAuthorized: + // void + case CreateClaimableBalanceResultCodeCreateClaimableBalanceUnderfunded: // void - case OperationTypeRevokeSponsorship: - tv, ok := value.(RevokeSponsorshipOp) - if !ok { - err = fmt.Errorf("invalid value, must be RevokeSponsorshipOp") - return - } - result.RevokeSponsorshipOp = &tv - case OperationTypeClawback: - tv, ok := value.(ClawbackOp) - if !ok { - err = fmt.Errorf("invalid value, must be ClawbackOp") - return - } - result.ClawbackOp = &tv - case OperationTypeClawbackClaimableBalance: - tv, ok := value.(ClawbackClaimableBalanceOp) - if !ok { - err = fmt.Errorf("invalid value, must be ClawbackClaimableBalanceOp") - return - } - result.ClawbackClaimableBalanceOp = &tv - case OperationTypeSetTrustLineFlags: - tv, ok := value.(SetTrustLineFlagsOp) - if !ok { - err = fmt.Errorf("invalid value, must be SetTrustLineFlagsOp") - return - } - result.SetTrustLineFlagsOp = &tv - case OperationTypeLiquidityPoolDeposit: - tv, ok := value.(LiquidityPoolDepositOp) - if !ok { - err = fmt.Errorf("invalid value, must be LiquidityPoolDepositOp") - return - } - result.LiquidityPoolDepositOp = &tv - case OperationTypeLiquidityPoolWithdraw: - tv, ok := value.(LiquidityPoolWithdrawOp) - if !ok { - err = fmt.Errorf("invalid value, must be LiquidityPoolWithdrawOp") - return - } - result.LiquidityPoolWithdrawOp = &tv } return } -// MustCreateAccountOp retrieves the CreateAccountOp value from the union, +// MustBalanceId retrieves the BalanceId value from the union, // panicing if the value is not set. -func (u OperationBody) MustCreateAccountOp() CreateAccountOp { - val, ok := u.GetCreateAccountOp() +func (u CreateClaimableBalanceResult) MustBalanceId() ClaimableBalanceId { + val, ok := u.GetBalanceId() if !ok { - panic("arm CreateAccountOp is not set") + panic("arm BalanceId is not set") } return val } -// GetCreateAccountOp retrieves the CreateAccountOp value from the union, +// GetBalanceId retrieves the BalanceId value from the union, // returning ok if the union's switch indicated the value is valid. -func (u OperationBody) GetCreateAccountOp() (result CreateAccountOp, ok bool) { - armName, _ := u.ArmForSwitch(int32(u.Type)) +func (u CreateClaimableBalanceResult) GetBalanceId() (result ClaimableBalanceId, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Code)) - if armName == "CreateAccountOp" { - result = *u.CreateAccountOp + if armName == "BalanceId" { + result = *u.BalanceId ok = true } return } -// MustPaymentOp retrieves the PaymentOp value from the union, -// panicing if the value is not set. -func (u OperationBody) MustPaymentOp() PaymentOp { - val, ok := u.GetPaymentOp() - - if !ok { - panic("arm PaymentOp is not set") +// EncodeTo encodes this value using the Encoder. +func (u CreateClaimableBalanceResult) EncodeTo(e *xdr.Encoder) error { + var err error + if err = u.Code.EncodeTo(e); err != nil { + return err } - - return val + switch CreateClaimableBalanceResultCode(u.Code) { + case CreateClaimableBalanceResultCodeCreateClaimableBalanceSuccess: + if err = (*u.BalanceId).EncodeTo(e); err != nil { + return err + } + return nil + case CreateClaimableBalanceResultCodeCreateClaimableBalanceMalformed: + // Void + return nil + case CreateClaimableBalanceResultCodeCreateClaimableBalanceLowReserve: + // Void + return nil + case CreateClaimableBalanceResultCodeCreateClaimableBalanceNoTrust: + // Void + return nil + case CreateClaimableBalanceResultCodeCreateClaimableBalanceNotAuthorized: + // Void + return nil + case CreateClaimableBalanceResultCodeCreateClaimableBalanceUnderfunded: + // Void + return nil + } + return fmt.Errorf("Code (CreateClaimableBalanceResultCode) switch value '%d' is not valid for union CreateClaimableBalanceResult", u.Code) } -// GetPaymentOp retrieves the PaymentOp value from the union, -// returning ok if the union's switch indicated the value is valid. -func (u OperationBody) GetPaymentOp() (result PaymentOp, ok bool) { - armName, _ := u.ArmForSwitch(int32(u.Type)) +var _ decoderFrom = (*CreateClaimableBalanceResult)(nil) - if armName == "PaymentOp" { - result = *u.PaymentOp - ok = true +// DecodeFrom decodes this value using the Decoder. +func (u *CreateClaimableBalanceResult) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding CreateClaimableBalanceResult: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + var err error + var n, nTmp int + nTmp, err = u.Code.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding CreateClaimableBalanceResultCode: %w", err) } + switch CreateClaimableBalanceResultCode(u.Code) { + case CreateClaimableBalanceResultCodeCreateClaimableBalanceSuccess: + u.BalanceId = new(ClaimableBalanceId) + nTmp, err = (*u.BalanceId).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ClaimableBalanceId: %w", err) + } + return n, nil + case CreateClaimableBalanceResultCodeCreateClaimableBalanceMalformed: + // Void + return n, nil + case CreateClaimableBalanceResultCodeCreateClaimableBalanceLowReserve: + // Void + return n, nil + case CreateClaimableBalanceResultCodeCreateClaimableBalanceNoTrust: + // Void + return n, nil + case CreateClaimableBalanceResultCodeCreateClaimableBalanceNotAuthorized: + // Void + return n, nil + case CreateClaimableBalanceResultCodeCreateClaimableBalanceUnderfunded: + // Void + return n, nil + } + return n, fmt.Errorf("union CreateClaimableBalanceResult has invalid Code (CreateClaimableBalanceResultCode) switch value '%d'", u.Code) +} - return +// MarshalBinary implements encoding.BinaryMarshaler. +func (s CreateClaimableBalanceResult) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err } -// MustPathPaymentStrictReceiveOp retrieves the PathPaymentStrictReceiveOp value from the union, -// panicing if the value is not set. -func (u OperationBody) MustPathPaymentStrictReceiveOp() PathPaymentStrictReceiveOp { - val, ok := u.GetPathPaymentStrictReceiveOp() +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *CreateClaimableBalanceResult) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} - if !ok { - panic("arm PathPaymentStrictReceiveOp is not set") - } +var ( + _ encoding.BinaryMarshaler = (*CreateClaimableBalanceResult)(nil) + _ encoding.BinaryUnmarshaler = (*CreateClaimableBalanceResult)(nil) +) - return val -} +// xdrType signals that this type represents XDR values defined by this package. +func (s CreateClaimableBalanceResult) xdrType() {} -// GetPathPaymentStrictReceiveOp retrieves the PathPaymentStrictReceiveOp value from the union, -// returning ok if the union's switch indicated the value is valid. -func (u OperationBody) GetPathPaymentStrictReceiveOp() (result PathPaymentStrictReceiveOp, ok bool) { - armName, _ := u.ArmForSwitch(int32(u.Type)) +var _ xdrType = (*CreateClaimableBalanceResult)(nil) - if armName == "PathPaymentStrictReceiveOp" { - result = *u.PathPaymentStrictReceiveOp - ok = true - } +// ClaimClaimableBalanceResultCode is an XDR Enum defines as: +// +// enum ClaimClaimableBalanceResultCode +// { +// CLAIM_CLAIMABLE_BALANCE_SUCCESS = 0, +// CLAIM_CLAIMABLE_BALANCE_DOES_NOT_EXIST = -1, +// CLAIM_CLAIMABLE_BALANCE_CANNOT_CLAIM = -2, +// CLAIM_CLAIMABLE_BALANCE_LINE_FULL = -3, +// CLAIM_CLAIMABLE_BALANCE_NO_TRUST = -4, +// CLAIM_CLAIMABLE_BALANCE_NOT_AUTHORIZED = -5 +// }; +type ClaimClaimableBalanceResultCode int32 - return +const ( + ClaimClaimableBalanceResultCodeClaimClaimableBalanceSuccess ClaimClaimableBalanceResultCode = 0 + ClaimClaimableBalanceResultCodeClaimClaimableBalanceDoesNotExist ClaimClaimableBalanceResultCode = -1 + ClaimClaimableBalanceResultCodeClaimClaimableBalanceCannotClaim ClaimClaimableBalanceResultCode = -2 + ClaimClaimableBalanceResultCodeClaimClaimableBalanceLineFull ClaimClaimableBalanceResultCode = -3 + ClaimClaimableBalanceResultCodeClaimClaimableBalanceNoTrust ClaimClaimableBalanceResultCode = -4 + ClaimClaimableBalanceResultCodeClaimClaimableBalanceNotAuthorized ClaimClaimableBalanceResultCode = -5 +) + +var claimClaimableBalanceResultCodeMap = map[int32]string{ + 0: "ClaimClaimableBalanceResultCodeClaimClaimableBalanceSuccess", + -1: "ClaimClaimableBalanceResultCodeClaimClaimableBalanceDoesNotExist", + -2: "ClaimClaimableBalanceResultCodeClaimClaimableBalanceCannotClaim", + -3: "ClaimClaimableBalanceResultCodeClaimClaimableBalanceLineFull", + -4: "ClaimClaimableBalanceResultCodeClaimClaimableBalanceNoTrust", + -5: "ClaimClaimableBalanceResultCodeClaimClaimableBalanceNotAuthorized", } -// MustManageSellOfferOp retrieves the ManageSellOfferOp value from the union, -// panicing if the value is not set. -func (u OperationBody) MustManageSellOfferOp() ManageSellOfferOp { - val, ok := u.GetManageSellOfferOp() +// ValidEnum validates a proposed value for this enum. Implements +// the Enum interface for ClaimClaimableBalanceResultCode +func (e ClaimClaimableBalanceResultCode) ValidEnum(v int32) bool { + _, ok := claimClaimableBalanceResultCodeMap[v] + return ok +} - if !ok { - panic("arm ManageSellOfferOp is not set") - } +// String returns the name of `e` +func (e ClaimClaimableBalanceResultCode) String() string { + name, _ := claimClaimableBalanceResultCodeMap[int32(e)] + return name +} - return val +// EncodeTo encodes this value using the Encoder. +func (e ClaimClaimableBalanceResultCode) EncodeTo(enc *xdr.Encoder) error { + if _, ok := claimClaimableBalanceResultCodeMap[int32(e)]; !ok { + return fmt.Errorf("'%d' is not a valid ClaimClaimableBalanceResultCode enum value", e) + } + _, err := enc.EncodeInt(int32(e)) + return err } -// GetManageSellOfferOp retrieves the ManageSellOfferOp value from the union, -// returning ok if the union's switch indicated the value is valid. -func (u OperationBody) GetManageSellOfferOp() (result ManageSellOfferOp, ok bool) { - armName, _ := u.ArmForSwitch(int32(u.Type)) +var _ decoderFrom = (*ClaimClaimableBalanceResultCode)(nil) - if armName == "ManageSellOfferOp" { - result = *u.ManageSellOfferOp - ok = true +// DecodeFrom decodes this value using the Decoder. +func (e *ClaimClaimableBalanceResultCode) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding ClaimClaimableBalanceResultCode: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + v, n, err := d.DecodeInt() + if err != nil { + return n, fmt.Errorf("decoding ClaimClaimableBalanceResultCode: %w", err) + } + if _, ok := claimClaimableBalanceResultCodeMap[v]; !ok { + return n, fmt.Errorf("'%d' is not a valid ClaimClaimableBalanceResultCode enum value", v) } + *e = ClaimClaimableBalanceResultCode(v) + return n, nil +} - return +// MarshalBinary implements encoding.BinaryMarshaler. +func (s ClaimClaimableBalanceResultCode) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err } -// MustCreatePassiveSellOfferOp retrieves the CreatePassiveSellOfferOp value from the union, -// panicing if the value is not set. -func (u OperationBody) MustCreatePassiveSellOfferOp() CreatePassiveSellOfferOp { - val, ok := u.GetCreatePassiveSellOfferOp() +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *ClaimClaimableBalanceResultCode) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} - if !ok { - panic("arm CreatePassiveSellOfferOp is not set") - } +var ( + _ encoding.BinaryMarshaler = (*ClaimClaimableBalanceResultCode)(nil) + _ encoding.BinaryUnmarshaler = (*ClaimClaimableBalanceResultCode)(nil) +) - return val +// xdrType signals that this type represents XDR values defined by this package. +func (s ClaimClaimableBalanceResultCode) xdrType() {} + +var _ xdrType = (*ClaimClaimableBalanceResultCode)(nil) + +// ClaimClaimableBalanceResult is an XDR Union defines as: +// +// union ClaimClaimableBalanceResult switch (ClaimClaimableBalanceResultCode code) +// { +// case CLAIM_CLAIMABLE_BALANCE_SUCCESS: +// void; +// case CLAIM_CLAIMABLE_BALANCE_DOES_NOT_EXIST: +// case CLAIM_CLAIMABLE_BALANCE_CANNOT_CLAIM: +// case CLAIM_CLAIMABLE_BALANCE_LINE_FULL: +// case CLAIM_CLAIMABLE_BALANCE_NO_TRUST: +// case CLAIM_CLAIMABLE_BALANCE_NOT_AUTHORIZED: +// void; +// }; +type ClaimClaimableBalanceResult struct { + Code ClaimClaimableBalanceResultCode } -// GetCreatePassiveSellOfferOp retrieves the CreatePassiveSellOfferOp value from the union, -// returning ok if the union's switch indicated the value is valid. -func (u OperationBody) GetCreatePassiveSellOfferOp() (result CreatePassiveSellOfferOp, ok bool) { - armName, _ := u.ArmForSwitch(int32(u.Type)) +// SwitchFieldName returns the field name in which this union's +// discriminant is stored +func (u ClaimClaimableBalanceResult) SwitchFieldName() string { + return "Code" +} - if armName == "CreatePassiveSellOfferOp" { - result = *u.CreatePassiveSellOfferOp - ok = true +// ArmForSwitch returns which field name should be used for storing +// the value for an instance of ClaimClaimableBalanceResult +func (u ClaimClaimableBalanceResult) ArmForSwitch(sw int32) (string, bool) { + switch ClaimClaimableBalanceResultCode(sw) { + case ClaimClaimableBalanceResultCodeClaimClaimableBalanceSuccess: + return "", true + case ClaimClaimableBalanceResultCodeClaimClaimableBalanceDoesNotExist: + return "", true + case ClaimClaimableBalanceResultCodeClaimClaimableBalanceCannotClaim: + return "", true + case ClaimClaimableBalanceResultCodeClaimClaimableBalanceLineFull: + return "", true + case ClaimClaimableBalanceResultCodeClaimClaimableBalanceNoTrust: + return "", true + case ClaimClaimableBalanceResultCodeClaimClaimableBalanceNotAuthorized: + return "", true } + return "-", false +} +// NewClaimClaimableBalanceResult creates a new ClaimClaimableBalanceResult. +func NewClaimClaimableBalanceResult(code ClaimClaimableBalanceResultCode, value interface{}) (result ClaimClaimableBalanceResult, err error) { + result.Code = code + switch ClaimClaimableBalanceResultCode(code) { + case ClaimClaimableBalanceResultCodeClaimClaimableBalanceSuccess: + // void + case ClaimClaimableBalanceResultCodeClaimClaimableBalanceDoesNotExist: + // void + case ClaimClaimableBalanceResultCodeClaimClaimableBalanceCannotClaim: + // void + case ClaimClaimableBalanceResultCodeClaimClaimableBalanceLineFull: + // void + case ClaimClaimableBalanceResultCodeClaimClaimableBalanceNoTrust: + // void + case ClaimClaimableBalanceResultCodeClaimClaimableBalanceNotAuthorized: + // void + } return } -// MustSetOptionsOp retrieves the SetOptionsOp value from the union, -// panicing if the value is not set. -func (u OperationBody) MustSetOptionsOp() SetOptionsOp { - val, ok := u.GetSetOptionsOp() - - if !ok { - panic("arm SetOptionsOp is not set") +// EncodeTo encodes this value using the Encoder. +func (u ClaimClaimableBalanceResult) EncodeTo(e *xdr.Encoder) error { + var err error + if err = u.Code.EncodeTo(e); err != nil { + return err + } + switch ClaimClaimableBalanceResultCode(u.Code) { + case ClaimClaimableBalanceResultCodeClaimClaimableBalanceSuccess: + // Void + return nil + case ClaimClaimableBalanceResultCodeClaimClaimableBalanceDoesNotExist: + // Void + return nil + case ClaimClaimableBalanceResultCodeClaimClaimableBalanceCannotClaim: + // Void + return nil + case ClaimClaimableBalanceResultCodeClaimClaimableBalanceLineFull: + // Void + return nil + case ClaimClaimableBalanceResultCodeClaimClaimableBalanceNoTrust: + // Void + return nil + case ClaimClaimableBalanceResultCodeClaimClaimableBalanceNotAuthorized: + // Void + return nil } + return fmt.Errorf("Code (ClaimClaimableBalanceResultCode) switch value '%d' is not valid for union ClaimClaimableBalanceResult", u.Code) +} - return val +var _ decoderFrom = (*ClaimClaimableBalanceResult)(nil) + +// DecodeFrom decodes this value using the Decoder. +func (u *ClaimClaimableBalanceResult) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding ClaimClaimableBalanceResult: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + var err error + var n, nTmp int + nTmp, err = u.Code.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ClaimClaimableBalanceResultCode: %w", err) + } + switch ClaimClaimableBalanceResultCode(u.Code) { + case ClaimClaimableBalanceResultCodeClaimClaimableBalanceSuccess: + // Void + return n, nil + case ClaimClaimableBalanceResultCodeClaimClaimableBalanceDoesNotExist: + // Void + return n, nil + case ClaimClaimableBalanceResultCodeClaimClaimableBalanceCannotClaim: + // Void + return n, nil + case ClaimClaimableBalanceResultCodeClaimClaimableBalanceLineFull: + // Void + return n, nil + case ClaimClaimableBalanceResultCodeClaimClaimableBalanceNoTrust: + // Void + return n, nil + case ClaimClaimableBalanceResultCodeClaimClaimableBalanceNotAuthorized: + // Void + return n, nil + } + return n, fmt.Errorf("union ClaimClaimableBalanceResult has invalid Code (ClaimClaimableBalanceResultCode) switch value '%d'", u.Code) } -// GetSetOptionsOp retrieves the SetOptionsOp value from the union, -// returning ok if the union's switch indicated the value is valid. -func (u OperationBody) GetSetOptionsOp() (result SetOptionsOp, ok bool) { - armName, _ := u.ArmForSwitch(int32(u.Type)) - - if armName == "SetOptionsOp" { - result = *u.SetOptionsOp - ok = true - } +// MarshalBinary implements encoding.BinaryMarshaler. +func (s ClaimClaimableBalanceResult) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} - return +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *ClaimClaimableBalanceResult) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err } -// MustChangeTrustOp retrieves the ChangeTrustOp value from the union, -// panicing if the value is not set. -func (u OperationBody) MustChangeTrustOp() ChangeTrustOp { - val, ok := u.GetChangeTrustOp() +var ( + _ encoding.BinaryMarshaler = (*ClaimClaimableBalanceResult)(nil) + _ encoding.BinaryUnmarshaler = (*ClaimClaimableBalanceResult)(nil) +) - if !ok { - panic("arm ChangeTrustOp is not set") - } +// xdrType signals that this type represents XDR values defined by this package. +func (s ClaimClaimableBalanceResult) xdrType() {} - return val -} +var _ xdrType = (*ClaimClaimableBalanceResult)(nil) -// GetChangeTrustOp retrieves the ChangeTrustOp value from the union, -// returning ok if the union's switch indicated the value is valid. -func (u OperationBody) GetChangeTrustOp() (result ChangeTrustOp, ok bool) { - armName, _ := u.ArmForSwitch(int32(u.Type)) +// BeginSponsoringFutureReservesResultCode is an XDR Enum defines as: +// +// enum BeginSponsoringFutureReservesResultCode +// { +// // codes considered as "success" for the operation +// BEGIN_SPONSORING_FUTURE_RESERVES_SUCCESS = 0, +// +// // codes considered as "failure" for the operation +// BEGIN_SPONSORING_FUTURE_RESERVES_MALFORMED = -1, +// BEGIN_SPONSORING_FUTURE_RESERVES_ALREADY_SPONSORED = -2, +// BEGIN_SPONSORING_FUTURE_RESERVES_RECURSIVE = -3 +// }; +type BeginSponsoringFutureReservesResultCode int32 - if armName == "ChangeTrustOp" { - result = *u.ChangeTrustOp - ok = true - } +const ( + BeginSponsoringFutureReservesResultCodeBeginSponsoringFutureReservesSuccess BeginSponsoringFutureReservesResultCode = 0 + BeginSponsoringFutureReservesResultCodeBeginSponsoringFutureReservesMalformed BeginSponsoringFutureReservesResultCode = -1 + BeginSponsoringFutureReservesResultCodeBeginSponsoringFutureReservesAlreadySponsored BeginSponsoringFutureReservesResultCode = -2 + BeginSponsoringFutureReservesResultCodeBeginSponsoringFutureReservesRecursive BeginSponsoringFutureReservesResultCode = -3 +) - return +var beginSponsoringFutureReservesResultCodeMap = map[int32]string{ + 0: "BeginSponsoringFutureReservesResultCodeBeginSponsoringFutureReservesSuccess", + -1: "BeginSponsoringFutureReservesResultCodeBeginSponsoringFutureReservesMalformed", + -2: "BeginSponsoringFutureReservesResultCodeBeginSponsoringFutureReservesAlreadySponsored", + -3: "BeginSponsoringFutureReservesResultCodeBeginSponsoringFutureReservesRecursive", } -// MustAllowTrustOp retrieves the AllowTrustOp value from the union, -// panicing if the value is not set. -func (u OperationBody) MustAllowTrustOp() AllowTrustOp { - val, ok := u.GetAllowTrustOp() - - if !ok { - panic("arm AllowTrustOp is not set") - } - - return val +// ValidEnum validates a proposed value for this enum. Implements +// the Enum interface for BeginSponsoringFutureReservesResultCode +func (e BeginSponsoringFutureReservesResultCode) ValidEnum(v int32) bool { + _, ok := beginSponsoringFutureReservesResultCodeMap[v] + return ok } -// GetAllowTrustOp retrieves the AllowTrustOp value from the union, -// returning ok if the union's switch indicated the value is valid. -func (u OperationBody) GetAllowTrustOp() (result AllowTrustOp, ok bool) { - armName, _ := u.ArmForSwitch(int32(u.Type)) +// String returns the name of `e` +func (e BeginSponsoringFutureReservesResultCode) String() string { + name, _ := beginSponsoringFutureReservesResultCodeMap[int32(e)] + return name +} - if armName == "AllowTrustOp" { - result = *u.AllowTrustOp - ok = true +// EncodeTo encodes this value using the Encoder. +func (e BeginSponsoringFutureReservesResultCode) EncodeTo(enc *xdr.Encoder) error { + if _, ok := beginSponsoringFutureReservesResultCodeMap[int32(e)]; !ok { + return fmt.Errorf("'%d' is not a valid BeginSponsoringFutureReservesResultCode enum value", e) } - - return + _, err := enc.EncodeInt(int32(e)) + return err } -// MustDestination retrieves the Destination value from the union, -// panicing if the value is not set. -func (u OperationBody) MustDestination() MuxedAccount { - val, ok := u.GetDestination() +var _ decoderFrom = (*BeginSponsoringFutureReservesResultCode)(nil) - if !ok { - panic("arm Destination is not set") +// DecodeFrom decodes this value using the Decoder. +func (e *BeginSponsoringFutureReservesResultCode) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding BeginSponsoringFutureReservesResultCode: %w", ErrMaxDecodingDepthReached) } - - return val + maxDepth -= 1 + v, n, err := d.DecodeInt() + if err != nil { + return n, fmt.Errorf("decoding BeginSponsoringFutureReservesResultCode: %w", err) + } + if _, ok := beginSponsoringFutureReservesResultCodeMap[v]; !ok { + return n, fmt.Errorf("'%d' is not a valid BeginSponsoringFutureReservesResultCode enum value", v) + } + *e = BeginSponsoringFutureReservesResultCode(v) + return n, nil } -// GetDestination retrieves the Destination value from the union, -// returning ok if the union's switch indicated the value is valid. -func (u OperationBody) GetDestination() (result MuxedAccount, ok bool) { - armName, _ := u.ArmForSwitch(int32(u.Type)) - - if armName == "Destination" { - result = *u.Destination - ok = true - } +// MarshalBinary implements encoding.BinaryMarshaler. +func (s BeginSponsoringFutureReservesResultCode) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} - return +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *BeginSponsoringFutureReservesResultCode) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err } -// MustManageDataOp retrieves the ManageDataOp value from the union, -// panicing if the value is not set. -func (u OperationBody) MustManageDataOp() ManageDataOp { - val, ok := u.GetManageDataOp() +var ( + _ encoding.BinaryMarshaler = (*BeginSponsoringFutureReservesResultCode)(nil) + _ encoding.BinaryUnmarshaler = (*BeginSponsoringFutureReservesResultCode)(nil) +) - if !ok { - panic("arm ManageDataOp is not set") - } +// xdrType signals that this type represents XDR values defined by this package. +func (s BeginSponsoringFutureReservesResultCode) xdrType() {} - return val +var _ xdrType = (*BeginSponsoringFutureReservesResultCode)(nil) + +// BeginSponsoringFutureReservesResult is an XDR Union defines as: +// +// union BeginSponsoringFutureReservesResult switch ( +// BeginSponsoringFutureReservesResultCode code) +// { +// case BEGIN_SPONSORING_FUTURE_RESERVES_SUCCESS: +// void; +// case BEGIN_SPONSORING_FUTURE_RESERVES_MALFORMED: +// case BEGIN_SPONSORING_FUTURE_RESERVES_ALREADY_SPONSORED: +// case BEGIN_SPONSORING_FUTURE_RESERVES_RECURSIVE: +// void; +// }; +type BeginSponsoringFutureReservesResult struct { + Code BeginSponsoringFutureReservesResultCode } -// GetManageDataOp retrieves the ManageDataOp value from the union, -// returning ok if the union's switch indicated the value is valid. -func (u OperationBody) GetManageDataOp() (result ManageDataOp, ok bool) { - armName, _ := u.ArmForSwitch(int32(u.Type)) +// SwitchFieldName returns the field name in which this union's +// discriminant is stored +func (u BeginSponsoringFutureReservesResult) SwitchFieldName() string { + return "Code" +} - if armName == "ManageDataOp" { - result = *u.ManageDataOp - ok = true +// ArmForSwitch returns which field name should be used for storing +// the value for an instance of BeginSponsoringFutureReservesResult +func (u BeginSponsoringFutureReservesResult) ArmForSwitch(sw int32) (string, bool) { + switch BeginSponsoringFutureReservesResultCode(sw) { + case BeginSponsoringFutureReservesResultCodeBeginSponsoringFutureReservesSuccess: + return "", true + case BeginSponsoringFutureReservesResultCodeBeginSponsoringFutureReservesMalformed: + return "", true + case BeginSponsoringFutureReservesResultCodeBeginSponsoringFutureReservesAlreadySponsored: + return "", true + case BeginSponsoringFutureReservesResultCodeBeginSponsoringFutureReservesRecursive: + return "", true } + return "-", false +} +// NewBeginSponsoringFutureReservesResult creates a new BeginSponsoringFutureReservesResult. +func NewBeginSponsoringFutureReservesResult(code BeginSponsoringFutureReservesResultCode, value interface{}) (result BeginSponsoringFutureReservesResult, err error) { + result.Code = code + switch BeginSponsoringFutureReservesResultCode(code) { + case BeginSponsoringFutureReservesResultCodeBeginSponsoringFutureReservesSuccess: + // void + case BeginSponsoringFutureReservesResultCodeBeginSponsoringFutureReservesMalformed: + // void + case BeginSponsoringFutureReservesResultCodeBeginSponsoringFutureReservesAlreadySponsored: + // void + case BeginSponsoringFutureReservesResultCodeBeginSponsoringFutureReservesRecursive: + // void + } return } -// MustBumpSequenceOp retrieves the BumpSequenceOp value from the union, -// panicing if the value is not set. -func (u OperationBody) MustBumpSequenceOp() BumpSequenceOp { - val, ok := u.GetBumpSequenceOp() - - if !ok { - panic("arm BumpSequenceOp is not set") +// EncodeTo encodes this value using the Encoder. +func (u BeginSponsoringFutureReservesResult) EncodeTo(e *xdr.Encoder) error { + var err error + if err = u.Code.EncodeTo(e); err != nil { + return err } - - return val + switch BeginSponsoringFutureReservesResultCode(u.Code) { + case BeginSponsoringFutureReservesResultCodeBeginSponsoringFutureReservesSuccess: + // Void + return nil + case BeginSponsoringFutureReservesResultCodeBeginSponsoringFutureReservesMalformed: + // Void + return nil + case BeginSponsoringFutureReservesResultCodeBeginSponsoringFutureReservesAlreadySponsored: + // Void + return nil + case BeginSponsoringFutureReservesResultCodeBeginSponsoringFutureReservesRecursive: + // Void + return nil + } + return fmt.Errorf("Code (BeginSponsoringFutureReservesResultCode) switch value '%d' is not valid for union BeginSponsoringFutureReservesResult", u.Code) } -// GetBumpSequenceOp retrieves the BumpSequenceOp value from the union, -// returning ok if the union's switch indicated the value is valid. -func (u OperationBody) GetBumpSequenceOp() (result BumpSequenceOp, ok bool) { - armName, _ := u.ArmForSwitch(int32(u.Type)) +var _ decoderFrom = (*BeginSponsoringFutureReservesResult)(nil) - if armName == "BumpSequenceOp" { - result = *u.BumpSequenceOp - ok = true +// DecodeFrom decodes this value using the Decoder. +func (u *BeginSponsoringFutureReservesResult) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding BeginSponsoringFutureReservesResult: %w", ErrMaxDecodingDepthReached) } - - return + maxDepth -= 1 + var err error + var n, nTmp int + nTmp, err = u.Code.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding BeginSponsoringFutureReservesResultCode: %w", err) + } + switch BeginSponsoringFutureReservesResultCode(u.Code) { + case BeginSponsoringFutureReservesResultCodeBeginSponsoringFutureReservesSuccess: + // Void + return n, nil + case BeginSponsoringFutureReservesResultCodeBeginSponsoringFutureReservesMalformed: + // Void + return n, nil + case BeginSponsoringFutureReservesResultCodeBeginSponsoringFutureReservesAlreadySponsored: + // Void + return n, nil + case BeginSponsoringFutureReservesResultCodeBeginSponsoringFutureReservesRecursive: + // Void + return n, nil + } + return n, fmt.Errorf("union BeginSponsoringFutureReservesResult has invalid Code (BeginSponsoringFutureReservesResultCode) switch value '%d'", u.Code) } -// MustManageBuyOfferOp retrieves the ManageBuyOfferOp value from the union, -// panicing if the value is not set. -func (u OperationBody) MustManageBuyOfferOp() ManageBuyOfferOp { - val, ok := u.GetManageBuyOfferOp() - - if !ok { - panic("arm ManageBuyOfferOp is not set") - } +// MarshalBinary implements encoding.BinaryMarshaler. +func (s BeginSponsoringFutureReservesResult) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} - return val +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *BeginSponsoringFutureReservesResult) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err } -// GetManageBuyOfferOp retrieves the ManageBuyOfferOp value from the union, -// returning ok if the union's switch indicated the value is valid. -func (u OperationBody) GetManageBuyOfferOp() (result ManageBuyOfferOp, ok bool) { - armName, _ := u.ArmForSwitch(int32(u.Type)) +var ( + _ encoding.BinaryMarshaler = (*BeginSponsoringFutureReservesResult)(nil) + _ encoding.BinaryUnmarshaler = (*BeginSponsoringFutureReservesResult)(nil) +) - if armName == "ManageBuyOfferOp" { - result = *u.ManageBuyOfferOp - ok = true - } +// xdrType signals that this type represents XDR values defined by this package. +func (s BeginSponsoringFutureReservesResult) xdrType() {} - return -} +var _ xdrType = (*BeginSponsoringFutureReservesResult)(nil) -// MustPathPaymentStrictSendOp retrieves the PathPaymentStrictSendOp value from the union, -// panicing if the value is not set. -func (u OperationBody) MustPathPaymentStrictSendOp() PathPaymentStrictSendOp { - val, ok := u.GetPathPaymentStrictSendOp() +// EndSponsoringFutureReservesResultCode is an XDR Enum defines as: +// +// enum EndSponsoringFutureReservesResultCode +// { +// // codes considered as "success" for the operation +// END_SPONSORING_FUTURE_RESERVES_SUCCESS = 0, +// +// // codes considered as "failure" for the operation +// END_SPONSORING_FUTURE_RESERVES_NOT_SPONSORED = -1 +// }; +type EndSponsoringFutureReservesResultCode int32 - if !ok { - panic("arm PathPaymentStrictSendOp is not set") - } +const ( + EndSponsoringFutureReservesResultCodeEndSponsoringFutureReservesSuccess EndSponsoringFutureReservesResultCode = 0 + EndSponsoringFutureReservesResultCodeEndSponsoringFutureReservesNotSponsored EndSponsoringFutureReservesResultCode = -1 +) - return val +var endSponsoringFutureReservesResultCodeMap = map[int32]string{ + 0: "EndSponsoringFutureReservesResultCodeEndSponsoringFutureReservesSuccess", + -1: "EndSponsoringFutureReservesResultCodeEndSponsoringFutureReservesNotSponsored", } -// GetPathPaymentStrictSendOp retrieves the PathPaymentStrictSendOp value from the union, -// returning ok if the union's switch indicated the value is valid. -func (u OperationBody) GetPathPaymentStrictSendOp() (result PathPaymentStrictSendOp, ok bool) { - armName, _ := u.ArmForSwitch(int32(u.Type)) - - if armName == "PathPaymentStrictSendOp" { - result = *u.PathPaymentStrictSendOp - ok = true - } - - return +// ValidEnum validates a proposed value for this enum. Implements +// the Enum interface for EndSponsoringFutureReservesResultCode +func (e EndSponsoringFutureReservesResultCode) ValidEnum(v int32) bool { + _, ok := endSponsoringFutureReservesResultCodeMap[v] + return ok } -// MustCreateClaimableBalanceOp retrieves the CreateClaimableBalanceOp value from the union, -// panicing if the value is not set. -func (u OperationBody) MustCreateClaimableBalanceOp() CreateClaimableBalanceOp { - val, ok := u.GetCreateClaimableBalanceOp() +// String returns the name of `e` +func (e EndSponsoringFutureReservesResultCode) String() string { + name, _ := endSponsoringFutureReservesResultCodeMap[int32(e)] + return name +} - if !ok { - panic("arm CreateClaimableBalanceOp is not set") +// EncodeTo encodes this value using the Encoder. +func (e EndSponsoringFutureReservesResultCode) EncodeTo(enc *xdr.Encoder) error { + if _, ok := endSponsoringFutureReservesResultCodeMap[int32(e)]; !ok { + return fmt.Errorf("'%d' is not a valid EndSponsoringFutureReservesResultCode enum value", e) } - - return val + _, err := enc.EncodeInt(int32(e)) + return err } -// GetCreateClaimableBalanceOp retrieves the CreateClaimableBalanceOp value from the union, -// returning ok if the union's switch indicated the value is valid. -func (u OperationBody) GetCreateClaimableBalanceOp() (result CreateClaimableBalanceOp, ok bool) { - armName, _ := u.ArmForSwitch(int32(u.Type)) +var _ decoderFrom = (*EndSponsoringFutureReservesResultCode)(nil) - if armName == "CreateClaimableBalanceOp" { - result = *u.CreateClaimableBalanceOp - ok = true +// DecodeFrom decodes this value using the Decoder. +func (e *EndSponsoringFutureReservesResultCode) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding EndSponsoringFutureReservesResultCode: %w", ErrMaxDecodingDepthReached) } - - return + maxDepth -= 1 + v, n, err := d.DecodeInt() + if err != nil { + return n, fmt.Errorf("decoding EndSponsoringFutureReservesResultCode: %w", err) + } + if _, ok := endSponsoringFutureReservesResultCodeMap[v]; !ok { + return n, fmt.Errorf("'%d' is not a valid EndSponsoringFutureReservesResultCode enum value", v) + } + *e = EndSponsoringFutureReservesResultCode(v) + return n, nil } -// MustClaimClaimableBalanceOp retrieves the ClaimClaimableBalanceOp value from the union, -// panicing if the value is not set. -func (u OperationBody) MustClaimClaimableBalanceOp() ClaimClaimableBalanceOp { - val, ok := u.GetClaimClaimableBalanceOp() - - if !ok { - panic("arm ClaimClaimableBalanceOp is not set") - } +// MarshalBinary implements encoding.BinaryMarshaler. +func (s EndSponsoringFutureReservesResultCode) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} - return val +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *EndSponsoringFutureReservesResultCode) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err } -// GetClaimClaimableBalanceOp retrieves the ClaimClaimableBalanceOp value from the union, -// returning ok if the union's switch indicated the value is valid. -func (u OperationBody) GetClaimClaimableBalanceOp() (result ClaimClaimableBalanceOp, ok bool) { - armName, _ := u.ArmForSwitch(int32(u.Type)) +var ( + _ encoding.BinaryMarshaler = (*EndSponsoringFutureReservesResultCode)(nil) + _ encoding.BinaryUnmarshaler = (*EndSponsoringFutureReservesResultCode)(nil) +) - if armName == "ClaimClaimableBalanceOp" { - result = *u.ClaimClaimableBalanceOp - ok = true - } +// xdrType signals that this type represents XDR values defined by this package. +func (s EndSponsoringFutureReservesResultCode) xdrType() {} - return +var _ xdrType = (*EndSponsoringFutureReservesResultCode)(nil) + +// EndSponsoringFutureReservesResult is an XDR Union defines as: +// +// union EndSponsoringFutureReservesResult switch ( +// EndSponsoringFutureReservesResultCode code) +// { +// case END_SPONSORING_FUTURE_RESERVES_SUCCESS: +// void; +// case END_SPONSORING_FUTURE_RESERVES_NOT_SPONSORED: +// void; +// }; +type EndSponsoringFutureReservesResult struct { + Code EndSponsoringFutureReservesResultCode } -// MustBeginSponsoringFutureReservesOp retrieves the BeginSponsoringFutureReservesOp value from the union, -// panicing if the value is not set. -func (u OperationBody) MustBeginSponsoringFutureReservesOp() BeginSponsoringFutureReservesOp { - val, ok := u.GetBeginSponsoringFutureReservesOp() +// SwitchFieldName returns the field name in which this union's +// discriminant is stored +func (u EndSponsoringFutureReservesResult) SwitchFieldName() string { + return "Code" +} - if !ok { - panic("arm BeginSponsoringFutureReservesOp is not set") +// ArmForSwitch returns which field name should be used for storing +// the value for an instance of EndSponsoringFutureReservesResult +func (u EndSponsoringFutureReservesResult) ArmForSwitch(sw int32) (string, bool) { + switch EndSponsoringFutureReservesResultCode(sw) { + case EndSponsoringFutureReservesResultCodeEndSponsoringFutureReservesSuccess: + return "", true + case EndSponsoringFutureReservesResultCodeEndSponsoringFutureReservesNotSponsored: + return "", true } - - return val + return "-", false } -// GetBeginSponsoringFutureReservesOp retrieves the BeginSponsoringFutureReservesOp value from the union, -// returning ok if the union's switch indicated the value is valid. -func (u OperationBody) GetBeginSponsoringFutureReservesOp() (result BeginSponsoringFutureReservesOp, ok bool) { - armName, _ := u.ArmForSwitch(int32(u.Type)) - - if armName == "BeginSponsoringFutureReservesOp" { - result = *u.BeginSponsoringFutureReservesOp - ok = true +// NewEndSponsoringFutureReservesResult creates a new EndSponsoringFutureReservesResult. +func NewEndSponsoringFutureReservesResult(code EndSponsoringFutureReservesResultCode, value interface{}) (result EndSponsoringFutureReservesResult, err error) { + result.Code = code + switch EndSponsoringFutureReservesResultCode(code) { + case EndSponsoringFutureReservesResultCodeEndSponsoringFutureReservesSuccess: + // void + case EndSponsoringFutureReservesResultCodeEndSponsoringFutureReservesNotSponsored: + // void } - return } -// MustRevokeSponsorshipOp retrieves the RevokeSponsorshipOp value from the union, -// panicing if the value is not set. -func (u OperationBody) MustRevokeSponsorshipOp() RevokeSponsorshipOp { - val, ok := u.GetRevokeSponsorshipOp() - - if !ok { - panic("arm RevokeSponsorshipOp is not set") +// EncodeTo encodes this value using the Encoder. +func (u EndSponsoringFutureReservesResult) EncodeTo(e *xdr.Encoder) error { + var err error + if err = u.Code.EncodeTo(e); err != nil { + return err } - - return val + switch EndSponsoringFutureReservesResultCode(u.Code) { + case EndSponsoringFutureReservesResultCodeEndSponsoringFutureReservesSuccess: + // Void + return nil + case EndSponsoringFutureReservesResultCodeEndSponsoringFutureReservesNotSponsored: + // Void + return nil + } + return fmt.Errorf("Code (EndSponsoringFutureReservesResultCode) switch value '%d' is not valid for union EndSponsoringFutureReservesResult", u.Code) } -// GetRevokeSponsorshipOp retrieves the RevokeSponsorshipOp value from the union, -// returning ok if the union's switch indicated the value is valid. -func (u OperationBody) GetRevokeSponsorshipOp() (result RevokeSponsorshipOp, ok bool) { - armName, _ := u.ArmForSwitch(int32(u.Type)) +var _ decoderFrom = (*EndSponsoringFutureReservesResult)(nil) - if armName == "RevokeSponsorshipOp" { - result = *u.RevokeSponsorshipOp - ok = true +// DecodeFrom decodes this value using the Decoder. +func (u *EndSponsoringFutureReservesResult) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding EndSponsoringFutureReservesResult: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + var err error + var n, nTmp int + nTmp, err = u.Code.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding EndSponsoringFutureReservesResultCode: %w", err) + } + switch EndSponsoringFutureReservesResultCode(u.Code) { + case EndSponsoringFutureReservesResultCodeEndSponsoringFutureReservesSuccess: + // Void + return n, nil + case EndSponsoringFutureReservesResultCodeEndSponsoringFutureReservesNotSponsored: + // Void + return n, nil } - - return + return n, fmt.Errorf("union EndSponsoringFutureReservesResult has invalid Code (EndSponsoringFutureReservesResultCode) switch value '%d'", u.Code) } -// MustClawbackOp retrieves the ClawbackOp value from the union, -// panicing if the value is not set. -func (u OperationBody) MustClawbackOp() ClawbackOp { - val, ok := u.GetClawbackOp() - - if !ok { - panic("arm ClawbackOp is not set") - } +// MarshalBinary implements encoding.BinaryMarshaler. +func (s EndSponsoringFutureReservesResult) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} - return val +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *EndSponsoringFutureReservesResult) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err } -// GetClawbackOp retrieves the ClawbackOp value from the union, -// returning ok if the union's switch indicated the value is valid. -func (u OperationBody) GetClawbackOp() (result ClawbackOp, ok bool) { - armName, _ := u.ArmForSwitch(int32(u.Type)) +var ( + _ encoding.BinaryMarshaler = (*EndSponsoringFutureReservesResult)(nil) + _ encoding.BinaryUnmarshaler = (*EndSponsoringFutureReservesResult)(nil) +) - if armName == "ClawbackOp" { - result = *u.ClawbackOp - ok = true - } +// xdrType signals that this type represents XDR values defined by this package. +func (s EndSponsoringFutureReservesResult) xdrType() {} - return -} +var _ xdrType = (*EndSponsoringFutureReservesResult)(nil) -// MustClawbackClaimableBalanceOp retrieves the ClawbackClaimableBalanceOp value from the union, -// panicing if the value is not set. -func (u OperationBody) MustClawbackClaimableBalanceOp() ClawbackClaimableBalanceOp { - val, ok := u.GetClawbackClaimableBalanceOp() +// RevokeSponsorshipResultCode is an XDR Enum defines as: +// +// enum RevokeSponsorshipResultCode +// { +// // codes considered as "success" for the operation +// REVOKE_SPONSORSHIP_SUCCESS = 0, +// +// // codes considered as "failure" for the operation +// REVOKE_SPONSORSHIP_DOES_NOT_EXIST = -1, +// REVOKE_SPONSORSHIP_NOT_SPONSOR = -2, +// REVOKE_SPONSORSHIP_LOW_RESERVE = -3, +// REVOKE_SPONSORSHIP_ONLY_TRANSFERABLE = -4, +// REVOKE_SPONSORSHIP_MALFORMED = -5 +// }; +type RevokeSponsorshipResultCode int32 - if !ok { - panic("arm ClawbackClaimableBalanceOp is not set") - } +const ( + RevokeSponsorshipResultCodeRevokeSponsorshipSuccess RevokeSponsorshipResultCode = 0 + RevokeSponsorshipResultCodeRevokeSponsorshipDoesNotExist RevokeSponsorshipResultCode = -1 + RevokeSponsorshipResultCodeRevokeSponsorshipNotSponsor RevokeSponsorshipResultCode = -2 + RevokeSponsorshipResultCodeRevokeSponsorshipLowReserve RevokeSponsorshipResultCode = -3 + RevokeSponsorshipResultCodeRevokeSponsorshipOnlyTransferable RevokeSponsorshipResultCode = -4 + RevokeSponsorshipResultCodeRevokeSponsorshipMalformed RevokeSponsorshipResultCode = -5 +) - return val +var revokeSponsorshipResultCodeMap = map[int32]string{ + 0: "RevokeSponsorshipResultCodeRevokeSponsorshipSuccess", + -1: "RevokeSponsorshipResultCodeRevokeSponsorshipDoesNotExist", + -2: "RevokeSponsorshipResultCodeRevokeSponsorshipNotSponsor", + -3: "RevokeSponsorshipResultCodeRevokeSponsorshipLowReserve", + -4: "RevokeSponsorshipResultCodeRevokeSponsorshipOnlyTransferable", + -5: "RevokeSponsorshipResultCodeRevokeSponsorshipMalformed", } -// GetClawbackClaimableBalanceOp retrieves the ClawbackClaimableBalanceOp value from the union, -// returning ok if the union's switch indicated the value is valid. -func (u OperationBody) GetClawbackClaimableBalanceOp() (result ClawbackClaimableBalanceOp, ok bool) { - armName, _ := u.ArmForSwitch(int32(u.Type)) - - if armName == "ClawbackClaimableBalanceOp" { - result = *u.ClawbackClaimableBalanceOp - ok = true - } - - return +// ValidEnum validates a proposed value for this enum. Implements +// the Enum interface for RevokeSponsorshipResultCode +func (e RevokeSponsorshipResultCode) ValidEnum(v int32) bool { + _, ok := revokeSponsorshipResultCodeMap[v] + return ok } -// MustSetTrustLineFlagsOp retrieves the SetTrustLineFlagsOp value from the union, -// panicing if the value is not set. -func (u OperationBody) MustSetTrustLineFlagsOp() SetTrustLineFlagsOp { - val, ok := u.GetSetTrustLineFlagsOp() +// String returns the name of `e` +func (e RevokeSponsorshipResultCode) String() string { + name, _ := revokeSponsorshipResultCodeMap[int32(e)] + return name +} - if !ok { - panic("arm SetTrustLineFlagsOp is not set") +// EncodeTo encodes this value using the Encoder. +func (e RevokeSponsorshipResultCode) EncodeTo(enc *xdr.Encoder) error { + if _, ok := revokeSponsorshipResultCodeMap[int32(e)]; !ok { + return fmt.Errorf("'%d' is not a valid RevokeSponsorshipResultCode enum value", e) } - - return val + _, err := enc.EncodeInt(int32(e)) + return err } -// GetSetTrustLineFlagsOp retrieves the SetTrustLineFlagsOp value from the union, -// returning ok if the union's switch indicated the value is valid. -func (u OperationBody) GetSetTrustLineFlagsOp() (result SetTrustLineFlagsOp, ok bool) { - armName, _ := u.ArmForSwitch(int32(u.Type)) +var _ decoderFrom = (*RevokeSponsorshipResultCode)(nil) - if armName == "SetTrustLineFlagsOp" { - result = *u.SetTrustLineFlagsOp - ok = true +// DecodeFrom decodes this value using the Decoder. +func (e *RevokeSponsorshipResultCode) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding RevokeSponsorshipResultCode: %w", ErrMaxDecodingDepthReached) } - - return + maxDepth -= 1 + v, n, err := d.DecodeInt() + if err != nil { + return n, fmt.Errorf("decoding RevokeSponsorshipResultCode: %w", err) + } + if _, ok := revokeSponsorshipResultCodeMap[v]; !ok { + return n, fmt.Errorf("'%d' is not a valid RevokeSponsorshipResultCode enum value", v) + } + *e = RevokeSponsorshipResultCode(v) + return n, nil } -// MustLiquidityPoolDepositOp retrieves the LiquidityPoolDepositOp value from the union, -// panicing if the value is not set. -func (u OperationBody) MustLiquidityPoolDepositOp() LiquidityPoolDepositOp { - val, ok := u.GetLiquidityPoolDepositOp() - - if !ok { - panic("arm LiquidityPoolDepositOp is not set") - } +// MarshalBinary implements encoding.BinaryMarshaler. +func (s RevokeSponsorshipResultCode) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} - return val +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *RevokeSponsorshipResultCode) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err } -// GetLiquidityPoolDepositOp retrieves the LiquidityPoolDepositOp value from the union, -// returning ok if the union's switch indicated the value is valid. -func (u OperationBody) GetLiquidityPoolDepositOp() (result LiquidityPoolDepositOp, ok bool) { - armName, _ := u.ArmForSwitch(int32(u.Type)) +var ( + _ encoding.BinaryMarshaler = (*RevokeSponsorshipResultCode)(nil) + _ encoding.BinaryUnmarshaler = (*RevokeSponsorshipResultCode)(nil) +) - if armName == "LiquidityPoolDepositOp" { - result = *u.LiquidityPoolDepositOp - ok = true - } +// xdrType signals that this type represents XDR values defined by this package. +func (s RevokeSponsorshipResultCode) xdrType() {} - return +var _ xdrType = (*RevokeSponsorshipResultCode)(nil) + +// RevokeSponsorshipResult is an XDR Union defines as: +// +// union RevokeSponsorshipResult switch (RevokeSponsorshipResultCode code) +// { +// case REVOKE_SPONSORSHIP_SUCCESS: +// void; +// case REVOKE_SPONSORSHIP_DOES_NOT_EXIST: +// case REVOKE_SPONSORSHIP_NOT_SPONSOR: +// case REVOKE_SPONSORSHIP_LOW_RESERVE: +// case REVOKE_SPONSORSHIP_ONLY_TRANSFERABLE: +// case REVOKE_SPONSORSHIP_MALFORMED: +// void; +// }; +type RevokeSponsorshipResult struct { + Code RevokeSponsorshipResultCode } -// MustLiquidityPoolWithdrawOp retrieves the LiquidityPoolWithdrawOp value from the union, -// panicing if the value is not set. -func (u OperationBody) MustLiquidityPoolWithdrawOp() LiquidityPoolWithdrawOp { - val, ok := u.GetLiquidityPoolWithdrawOp() +// SwitchFieldName returns the field name in which this union's +// discriminant is stored +func (u RevokeSponsorshipResult) SwitchFieldName() string { + return "Code" +} - if !ok { - panic("arm LiquidityPoolWithdrawOp is not set") +// ArmForSwitch returns which field name should be used for storing +// the value for an instance of RevokeSponsorshipResult +func (u RevokeSponsorshipResult) ArmForSwitch(sw int32) (string, bool) { + switch RevokeSponsorshipResultCode(sw) { + case RevokeSponsorshipResultCodeRevokeSponsorshipSuccess: + return "", true + case RevokeSponsorshipResultCodeRevokeSponsorshipDoesNotExist: + return "", true + case RevokeSponsorshipResultCodeRevokeSponsorshipNotSponsor: + return "", true + case RevokeSponsorshipResultCodeRevokeSponsorshipLowReserve: + return "", true + case RevokeSponsorshipResultCodeRevokeSponsorshipOnlyTransferable: + return "", true + case RevokeSponsorshipResultCodeRevokeSponsorshipMalformed: + return "", true } - - return val + return "-", false } -// GetLiquidityPoolWithdrawOp retrieves the LiquidityPoolWithdrawOp value from the union, -// returning ok if the union's switch indicated the value is valid. -func (u OperationBody) GetLiquidityPoolWithdrawOp() (result LiquidityPoolWithdrawOp, ok bool) { - armName, _ := u.ArmForSwitch(int32(u.Type)) - - if armName == "LiquidityPoolWithdrawOp" { - result = *u.LiquidityPoolWithdrawOp - ok = true +// NewRevokeSponsorshipResult creates a new RevokeSponsorshipResult. +func NewRevokeSponsorshipResult(code RevokeSponsorshipResultCode, value interface{}) (result RevokeSponsorshipResult, err error) { + result.Code = code + switch RevokeSponsorshipResultCode(code) { + case RevokeSponsorshipResultCodeRevokeSponsorshipSuccess: + // void + case RevokeSponsorshipResultCodeRevokeSponsorshipDoesNotExist: + // void + case RevokeSponsorshipResultCodeRevokeSponsorshipNotSponsor: + // void + case RevokeSponsorshipResultCodeRevokeSponsorshipLowReserve: + // void + case RevokeSponsorshipResultCodeRevokeSponsorshipOnlyTransferable: + // void + case RevokeSponsorshipResultCodeRevokeSponsorshipMalformed: + // void } - return } // EncodeTo encodes this value using the Encoder. -func (u OperationBody) EncodeTo(e *xdr.Encoder) error { +func (u RevokeSponsorshipResult) EncodeTo(e *xdr.Encoder) error { var err error - if err = u.Type.EncodeTo(e); err != nil { + if err = u.Code.EncodeTo(e); err != nil { return err } - switch OperationType(u.Type) { - case OperationTypeCreateAccount: - if err = (*u.CreateAccountOp).EncodeTo(e); err != nil { - return err - } - return nil - case OperationTypePayment: - if err = (*u.PaymentOp).EncodeTo(e); err != nil { - return err - } - return nil - case OperationTypePathPaymentStrictReceive: - if err = (*u.PathPaymentStrictReceiveOp).EncodeTo(e); err != nil { - return err - } - return nil - case OperationTypeManageSellOffer: - if err = (*u.ManageSellOfferOp).EncodeTo(e); err != nil { - return err - } - return nil - case OperationTypeCreatePassiveSellOffer: - if err = (*u.CreatePassiveSellOfferOp).EncodeTo(e); err != nil { - return err - } - return nil - case OperationTypeSetOptions: - if err = (*u.SetOptionsOp).EncodeTo(e); err != nil { - return err - } - return nil - case OperationTypeChangeTrust: - if err = (*u.ChangeTrustOp).EncodeTo(e); err != nil { - return err - } - return nil - case OperationTypeAllowTrust: - if err = (*u.AllowTrustOp).EncodeTo(e); err != nil { - return err - } - return nil - case OperationTypeAccountMerge: - if err = (*u.Destination).EncodeTo(e); err != nil { - return err - } - return nil - case OperationTypeInflation: + switch RevokeSponsorshipResultCode(u.Code) { + case RevokeSponsorshipResultCodeRevokeSponsorshipSuccess: // Void return nil - case OperationTypeManageData: - if err = (*u.ManageDataOp).EncodeTo(e); err != nil { - return err - } - return nil - case OperationTypeBumpSequence: - if err = (*u.BumpSequenceOp).EncodeTo(e); err != nil { - return err - } - return nil - case OperationTypeManageBuyOffer: - if err = (*u.ManageBuyOfferOp).EncodeTo(e); err != nil { - return err - } - return nil - case OperationTypePathPaymentStrictSend: - if err = (*u.PathPaymentStrictSendOp).EncodeTo(e); err != nil { - return err - } - return nil - case OperationTypeCreateClaimableBalance: - if err = (*u.CreateClaimableBalanceOp).EncodeTo(e); err != nil { - return err - } - return nil - case OperationTypeClaimClaimableBalance: - if err = (*u.ClaimClaimableBalanceOp).EncodeTo(e); err != nil { - return err - } - return nil - case OperationTypeBeginSponsoringFutureReserves: - if err = (*u.BeginSponsoringFutureReservesOp).EncodeTo(e); err != nil { - return err - } - return nil - case OperationTypeEndSponsoringFutureReserves: + case RevokeSponsorshipResultCodeRevokeSponsorshipDoesNotExist: // Void return nil - case OperationTypeRevokeSponsorship: - if err = (*u.RevokeSponsorshipOp).EncodeTo(e); err != nil { - return err - } - return nil - case OperationTypeClawback: - if err = (*u.ClawbackOp).EncodeTo(e); err != nil { - return err - } - return nil - case OperationTypeClawbackClaimableBalance: - if err = (*u.ClawbackClaimableBalanceOp).EncodeTo(e); err != nil { - return err - } + case RevokeSponsorshipResultCodeRevokeSponsorshipNotSponsor: + // Void return nil - case OperationTypeSetTrustLineFlags: - if err = (*u.SetTrustLineFlagsOp).EncodeTo(e); err != nil { - return err - } + case RevokeSponsorshipResultCodeRevokeSponsorshipLowReserve: + // Void return nil - case OperationTypeLiquidityPoolDeposit: - if err = (*u.LiquidityPoolDepositOp).EncodeTo(e); err != nil { - return err - } + case RevokeSponsorshipResultCodeRevokeSponsorshipOnlyTransferable: + // Void return nil - case OperationTypeLiquidityPoolWithdraw: - if err = (*u.LiquidityPoolWithdrawOp).EncodeTo(e); err != nil { - return err - } + case RevokeSponsorshipResultCodeRevokeSponsorshipMalformed: + // Void return nil } - return fmt.Errorf("Type (OperationType) switch value '%d' is not valid for union OperationBody", u.Type) + return fmt.Errorf("Code (RevokeSponsorshipResultCode) switch value '%d' is not valid for union RevokeSponsorshipResult", u.Code) } -var _ decoderFrom = (*OperationBody)(nil) +var _ decoderFrom = (*RevokeSponsorshipResult)(nil) // DecodeFrom decodes this value using the Decoder. -func (u *OperationBody) DecodeFrom(d *xdr.Decoder) (int, error) { +func (u *RevokeSponsorshipResult) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding RevokeSponsorshipResult: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = u.Type.DecodeFrom(d) + nTmp, err = u.Code.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding OperationType: %s", err) + return n, fmt.Errorf("decoding RevokeSponsorshipResultCode: %w", err) } - switch OperationType(u.Type) { - case OperationTypeCreateAccount: - u.CreateAccountOp = new(CreateAccountOp) - nTmp, err = (*u.CreateAccountOp).DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding CreateAccountOp: %s", err) - } - return n, nil - case OperationTypePayment: - u.PaymentOp = new(PaymentOp) - nTmp, err = (*u.PaymentOp).DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding PaymentOp: %s", err) - } - return n, nil - case OperationTypePathPaymentStrictReceive: - u.PathPaymentStrictReceiveOp = new(PathPaymentStrictReceiveOp) - nTmp, err = (*u.PathPaymentStrictReceiveOp).DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding PathPaymentStrictReceiveOp: %s", err) - } - return n, nil - case OperationTypeManageSellOffer: - u.ManageSellOfferOp = new(ManageSellOfferOp) - nTmp, err = (*u.ManageSellOfferOp).DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding ManageSellOfferOp: %s", err) - } - return n, nil - case OperationTypeCreatePassiveSellOffer: - u.CreatePassiveSellOfferOp = new(CreatePassiveSellOfferOp) - nTmp, err = (*u.CreatePassiveSellOfferOp).DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding CreatePassiveSellOfferOp: %s", err) - } - return n, nil - case OperationTypeSetOptions: - u.SetOptionsOp = new(SetOptionsOp) - nTmp, err = (*u.SetOptionsOp).DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding SetOptionsOp: %s", err) - } - return n, nil - case OperationTypeChangeTrust: - u.ChangeTrustOp = new(ChangeTrustOp) - nTmp, err = (*u.ChangeTrustOp).DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding ChangeTrustOp: %s", err) - } - return n, nil - case OperationTypeAllowTrust: - u.AllowTrustOp = new(AllowTrustOp) - nTmp, err = (*u.AllowTrustOp).DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding AllowTrustOp: %s", err) - } - return n, nil - case OperationTypeAccountMerge: - u.Destination = new(MuxedAccount) - nTmp, err = (*u.Destination).DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding MuxedAccount: %s", err) - } - return n, nil - case OperationTypeInflation: + switch RevokeSponsorshipResultCode(u.Code) { + case RevokeSponsorshipResultCodeRevokeSponsorshipSuccess: // Void return n, nil - case OperationTypeManageData: - u.ManageDataOp = new(ManageDataOp) - nTmp, err = (*u.ManageDataOp).DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding ManageDataOp: %s", err) - } - return n, nil - case OperationTypeBumpSequence: - u.BumpSequenceOp = new(BumpSequenceOp) - nTmp, err = (*u.BumpSequenceOp).DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding BumpSequenceOp: %s", err) - } - return n, nil - case OperationTypeManageBuyOffer: - u.ManageBuyOfferOp = new(ManageBuyOfferOp) - nTmp, err = (*u.ManageBuyOfferOp).DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding ManageBuyOfferOp: %s", err) - } - return n, nil - case OperationTypePathPaymentStrictSend: - u.PathPaymentStrictSendOp = new(PathPaymentStrictSendOp) - nTmp, err = (*u.PathPaymentStrictSendOp).DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding PathPaymentStrictSendOp: %s", err) - } - return n, nil - case OperationTypeCreateClaimableBalance: - u.CreateClaimableBalanceOp = new(CreateClaimableBalanceOp) - nTmp, err = (*u.CreateClaimableBalanceOp).DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding CreateClaimableBalanceOp: %s", err) - } - return n, nil - case OperationTypeClaimClaimableBalance: - u.ClaimClaimableBalanceOp = new(ClaimClaimableBalanceOp) - nTmp, err = (*u.ClaimClaimableBalanceOp).DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding ClaimClaimableBalanceOp: %s", err) - } - return n, nil - case OperationTypeBeginSponsoringFutureReserves: - u.BeginSponsoringFutureReservesOp = new(BeginSponsoringFutureReservesOp) - nTmp, err = (*u.BeginSponsoringFutureReservesOp).DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding BeginSponsoringFutureReservesOp: %s", err) - } - return n, nil - case OperationTypeEndSponsoringFutureReserves: + case RevokeSponsorshipResultCodeRevokeSponsorshipDoesNotExist: // Void return n, nil - case OperationTypeRevokeSponsorship: - u.RevokeSponsorshipOp = new(RevokeSponsorshipOp) - nTmp, err = (*u.RevokeSponsorshipOp).DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding RevokeSponsorshipOp: %s", err) - } - return n, nil - case OperationTypeClawback: - u.ClawbackOp = new(ClawbackOp) - nTmp, err = (*u.ClawbackOp).DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding ClawbackOp: %s", err) - } - return n, nil - case OperationTypeClawbackClaimableBalance: - u.ClawbackClaimableBalanceOp = new(ClawbackClaimableBalanceOp) - nTmp, err = (*u.ClawbackClaimableBalanceOp).DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding ClawbackClaimableBalanceOp: %s", err) - } - return n, nil - case OperationTypeSetTrustLineFlags: - u.SetTrustLineFlagsOp = new(SetTrustLineFlagsOp) - nTmp, err = (*u.SetTrustLineFlagsOp).DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding SetTrustLineFlagsOp: %s", err) - } + case RevokeSponsorshipResultCodeRevokeSponsorshipNotSponsor: + // Void return n, nil - case OperationTypeLiquidityPoolDeposit: - u.LiquidityPoolDepositOp = new(LiquidityPoolDepositOp) - nTmp, err = (*u.LiquidityPoolDepositOp).DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding LiquidityPoolDepositOp: %s", err) - } + case RevokeSponsorshipResultCodeRevokeSponsorshipLowReserve: + // Void return n, nil - case OperationTypeLiquidityPoolWithdraw: - u.LiquidityPoolWithdrawOp = new(LiquidityPoolWithdrawOp) - nTmp, err = (*u.LiquidityPoolWithdrawOp).DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding LiquidityPoolWithdrawOp: %s", err) - } + case RevokeSponsorshipResultCodeRevokeSponsorshipOnlyTransferable: + // Void + return n, nil + case RevokeSponsorshipResultCodeRevokeSponsorshipMalformed: + // Void return n, nil } - return n, fmt.Errorf("union OperationBody has invalid Type (OperationType) switch value '%d'", u.Type) + return n, fmt.Errorf("union RevokeSponsorshipResult has invalid Code (RevokeSponsorshipResultCode) switch value '%d'", u.Code) } // MarshalBinary implements encoding.BinaryMarshaler. -func (s OperationBody) MarshalBinary() ([]byte, error) { +func (s RevokeSponsorshipResult) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -22413,139 +39296,99 @@ func (s OperationBody) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *OperationBody) UnmarshalBinary(inp []byte) error { +func (s *RevokeSponsorshipResult) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*OperationBody)(nil) - _ encoding.BinaryUnmarshaler = (*OperationBody)(nil) + _ encoding.BinaryMarshaler = (*RevokeSponsorshipResult)(nil) + _ encoding.BinaryUnmarshaler = (*RevokeSponsorshipResult)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s OperationBody) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s RevokeSponsorshipResult) xdrType() {} -var _ xdrType = (*OperationBody)(nil) +var _ xdrType = (*RevokeSponsorshipResult)(nil) -// Operation is an XDR Struct defines as: +// ClawbackResultCode is an XDR Enum defines as: // -// struct Operation +// enum ClawbackResultCode // { -// // sourceAccount is the account used to run the operation -// // if not set, the runtime defaults to "sourceAccount" specified at -// // the transaction level -// MuxedAccount* sourceAccount; +// // codes considered as "success" for the operation +// CLAWBACK_SUCCESS = 0, // -// union switch (OperationType type) -// { -// case CREATE_ACCOUNT: -// CreateAccountOp createAccountOp; -// case PAYMENT: -// PaymentOp paymentOp; -// case PATH_PAYMENT_STRICT_RECEIVE: -// PathPaymentStrictReceiveOp pathPaymentStrictReceiveOp; -// case MANAGE_SELL_OFFER: -// ManageSellOfferOp manageSellOfferOp; -// case CREATE_PASSIVE_SELL_OFFER: -// CreatePassiveSellOfferOp createPassiveSellOfferOp; -// case SET_OPTIONS: -// SetOptionsOp setOptionsOp; -// case CHANGE_TRUST: -// ChangeTrustOp changeTrustOp; -// case ALLOW_TRUST: -// AllowTrustOp allowTrustOp; -// case ACCOUNT_MERGE: -// MuxedAccount destination; -// case INFLATION: -// void; -// case MANAGE_DATA: -// ManageDataOp manageDataOp; -// case BUMP_SEQUENCE: -// BumpSequenceOp bumpSequenceOp; -// case MANAGE_BUY_OFFER: -// ManageBuyOfferOp manageBuyOfferOp; -// case PATH_PAYMENT_STRICT_SEND: -// PathPaymentStrictSendOp pathPaymentStrictSendOp; -// case CREATE_CLAIMABLE_BALANCE: -// CreateClaimableBalanceOp createClaimableBalanceOp; -// case CLAIM_CLAIMABLE_BALANCE: -// ClaimClaimableBalanceOp claimClaimableBalanceOp; -// case BEGIN_SPONSORING_FUTURE_RESERVES: -// BeginSponsoringFutureReservesOp beginSponsoringFutureReservesOp; -// case END_SPONSORING_FUTURE_RESERVES: -// void; -// case REVOKE_SPONSORSHIP: -// RevokeSponsorshipOp revokeSponsorshipOp; -// case CLAWBACK: -// ClawbackOp clawbackOp; -// case CLAWBACK_CLAIMABLE_BALANCE: -// ClawbackClaimableBalanceOp clawbackClaimableBalanceOp; -// case SET_TRUST_LINE_FLAGS: -// SetTrustLineFlagsOp setTrustLineFlagsOp; -// case LIQUIDITY_POOL_DEPOSIT: -// LiquidityPoolDepositOp liquidityPoolDepositOp; -// case LIQUIDITY_POOL_WITHDRAW: -// LiquidityPoolWithdrawOp liquidityPoolWithdrawOp; -// } -// body; +// // codes considered as "failure" for the operation +// CLAWBACK_MALFORMED = -1, +// CLAWBACK_NOT_CLAWBACK_ENABLED = -2, +// CLAWBACK_NO_TRUST = -3, +// CLAWBACK_UNDERFUNDED = -4 // }; -type Operation struct { - SourceAccount *MuxedAccount - Body OperationBody +type ClawbackResultCode int32 + +const ( + ClawbackResultCodeClawbackSuccess ClawbackResultCode = 0 + ClawbackResultCodeClawbackMalformed ClawbackResultCode = -1 + ClawbackResultCodeClawbackNotClawbackEnabled ClawbackResultCode = -2 + ClawbackResultCodeClawbackNoTrust ClawbackResultCode = -3 + ClawbackResultCodeClawbackUnderfunded ClawbackResultCode = -4 +) + +var clawbackResultCodeMap = map[int32]string{ + 0: "ClawbackResultCodeClawbackSuccess", + -1: "ClawbackResultCodeClawbackMalformed", + -2: "ClawbackResultCodeClawbackNotClawbackEnabled", + -3: "ClawbackResultCodeClawbackNoTrust", + -4: "ClawbackResultCodeClawbackUnderfunded", +} + +// ValidEnum validates a proposed value for this enum. Implements +// the Enum interface for ClawbackResultCode +func (e ClawbackResultCode) ValidEnum(v int32) bool { + _, ok := clawbackResultCodeMap[v] + return ok +} + +// String returns the name of `e` +func (e ClawbackResultCode) String() string { + name, _ := clawbackResultCodeMap[int32(e)] + return name } // EncodeTo encodes this value using the Encoder. -func (s *Operation) EncodeTo(e *xdr.Encoder) error { - var err error - if _, err = e.EncodeBool(s.SourceAccount != nil); err != nil { - return err - } - if s.SourceAccount != nil { - if err = (*s.SourceAccount).EncodeTo(e); err != nil { - return err - } - } - if err = s.Body.EncodeTo(e); err != nil { - return err +func (e ClawbackResultCode) EncodeTo(enc *xdr.Encoder) error { + if _, ok := clawbackResultCodeMap[int32(e)]; !ok { + return fmt.Errorf("'%d' is not a valid ClawbackResultCode enum value", e) } - return nil + _, err := enc.EncodeInt(int32(e)) + return err } -var _ decoderFrom = (*Operation)(nil) +var _ decoderFrom = (*ClawbackResultCode)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *Operation) DecodeFrom(d *xdr.Decoder) (int, error) { - var err error - var n, nTmp int - var b bool - b, nTmp, err = d.DecodeBool() - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding MuxedAccount: %s", err) +func (e *ClawbackResultCode) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding ClawbackResultCode: %w", ErrMaxDecodingDepthReached) } - s.SourceAccount = nil - if b { - s.SourceAccount = new(MuxedAccount) - nTmp, err = s.SourceAccount.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding MuxedAccount: %s", err) - } - } - nTmp, err = s.Body.DecodeFrom(d) - n += nTmp + maxDepth -= 1 + v, n, err := d.DecodeInt() if err != nil { - return n, fmt.Errorf("decoding OperationBody: %s", err) + return n, fmt.Errorf("decoding ClawbackResultCode: %w", err) + } + if _, ok := clawbackResultCodeMap[v]; !ok { + return n, fmt.Errorf("'%d' is not a valid ClawbackResultCode enum value", v) } + *e = ClawbackResultCode(v) return n, nil } // MarshalBinary implements encoding.BinaryMarshaler. -func (s Operation) MarshalBinary() ([]byte, error) { +func (s ClawbackResultCode) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -22553,79 +39396,146 @@ func (s Operation) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *Operation) UnmarshalBinary(inp []byte) error { +func (s *ClawbackResultCode) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*Operation)(nil) - _ encoding.BinaryUnmarshaler = (*Operation)(nil) + _ encoding.BinaryMarshaler = (*ClawbackResultCode)(nil) + _ encoding.BinaryUnmarshaler = (*ClawbackResultCode)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s Operation) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s ClawbackResultCode) xdrType() {} -var _ xdrType = (*Operation)(nil) +var _ xdrType = (*ClawbackResultCode)(nil) -// HashIdPreimageOperationId is an XDR NestedStruct defines as: +// ClawbackResult is an XDR Union defines as: // -// struct -// { -// AccountID sourceAccount; -// SequenceNumber seqNum; -// uint32 opNum; -// } -type HashIdPreimageOperationId struct { - SourceAccount AccountId - SeqNum SequenceNumber - OpNum Uint32 +// union ClawbackResult switch (ClawbackResultCode code) +// { +// case CLAWBACK_SUCCESS: +// void; +// case CLAWBACK_MALFORMED: +// case CLAWBACK_NOT_CLAWBACK_ENABLED: +// case CLAWBACK_NO_TRUST: +// case CLAWBACK_UNDERFUNDED: +// void; +// }; +type ClawbackResult struct { + Code ClawbackResultCode +} + +// SwitchFieldName returns the field name in which this union's +// discriminant is stored +func (u ClawbackResult) SwitchFieldName() string { + return "Code" +} + +// ArmForSwitch returns which field name should be used for storing +// the value for an instance of ClawbackResult +func (u ClawbackResult) ArmForSwitch(sw int32) (string, bool) { + switch ClawbackResultCode(sw) { + case ClawbackResultCodeClawbackSuccess: + return "", true + case ClawbackResultCodeClawbackMalformed: + return "", true + case ClawbackResultCodeClawbackNotClawbackEnabled: + return "", true + case ClawbackResultCodeClawbackNoTrust: + return "", true + case ClawbackResultCodeClawbackUnderfunded: + return "", true + } + return "-", false +} + +// NewClawbackResult creates a new ClawbackResult. +func NewClawbackResult(code ClawbackResultCode, value interface{}) (result ClawbackResult, err error) { + result.Code = code + switch ClawbackResultCode(code) { + case ClawbackResultCodeClawbackSuccess: + // void + case ClawbackResultCodeClawbackMalformed: + // void + case ClawbackResultCodeClawbackNotClawbackEnabled: + // void + case ClawbackResultCodeClawbackNoTrust: + // void + case ClawbackResultCodeClawbackUnderfunded: + // void + } + return } // EncodeTo encodes this value using the Encoder. -func (s *HashIdPreimageOperationId) EncodeTo(e *xdr.Encoder) error { +func (u ClawbackResult) EncodeTo(e *xdr.Encoder) error { var err error - if err = s.SourceAccount.EncodeTo(e); err != nil { - return err - } - if err = s.SeqNum.EncodeTo(e); err != nil { + if err = u.Code.EncodeTo(e); err != nil { return err } - if err = s.OpNum.EncodeTo(e); err != nil { - return err + switch ClawbackResultCode(u.Code) { + case ClawbackResultCodeClawbackSuccess: + // Void + return nil + case ClawbackResultCodeClawbackMalformed: + // Void + return nil + case ClawbackResultCodeClawbackNotClawbackEnabled: + // Void + return nil + case ClawbackResultCodeClawbackNoTrust: + // Void + return nil + case ClawbackResultCodeClawbackUnderfunded: + // Void + return nil } - return nil + return fmt.Errorf("Code (ClawbackResultCode) switch value '%d' is not valid for union ClawbackResult", u.Code) } -var _ decoderFrom = (*HashIdPreimageOperationId)(nil) +var _ decoderFrom = (*ClawbackResult)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *HashIdPreimageOperationId) DecodeFrom(d *xdr.Decoder) (int, error) { +func (u *ClawbackResult) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding ClawbackResult: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = s.SourceAccount.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding AccountId: %s", err) - } - nTmp, err = s.SeqNum.DecodeFrom(d) + nTmp, err = u.Code.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding SequenceNumber: %s", err) + return n, fmt.Errorf("decoding ClawbackResultCode: %w", err) } - nTmp, err = s.OpNum.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Uint32: %s", err) + switch ClawbackResultCode(u.Code) { + case ClawbackResultCodeClawbackSuccess: + // Void + return n, nil + case ClawbackResultCodeClawbackMalformed: + // Void + return n, nil + case ClawbackResultCodeClawbackNotClawbackEnabled: + // Void + return n, nil + case ClawbackResultCodeClawbackNoTrust: + // Void + return n, nil + case ClawbackResultCodeClawbackUnderfunded: + // Void + return n, nil } - return n, nil + return n, fmt.Errorf("union ClawbackResult has invalid Code (ClawbackResultCode) switch value '%d'", u.Code) } // MarshalBinary implements encoding.BinaryMarshaler. -func (s HashIdPreimageOperationId) MarshalBinary() ([]byte, error) { +func (s ClawbackResult) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -22633,99 +39543,96 @@ func (s HashIdPreimageOperationId) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *HashIdPreimageOperationId) UnmarshalBinary(inp []byte) error { +func (s *ClawbackResult) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*HashIdPreimageOperationId)(nil) - _ encoding.BinaryUnmarshaler = (*HashIdPreimageOperationId)(nil) + _ encoding.BinaryMarshaler = (*ClawbackResult)(nil) + _ encoding.BinaryUnmarshaler = (*ClawbackResult)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s HashIdPreimageOperationId) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s ClawbackResult) xdrType() {} -var _ xdrType = (*HashIdPreimageOperationId)(nil) +var _ xdrType = (*ClawbackResult)(nil) -// HashIdPreimageRevokeId is an XDR NestedStruct defines as: +// ClawbackClaimableBalanceResultCode is an XDR Enum defines as: // -// struct -// { -// AccountID sourceAccount; -// SequenceNumber seqNum; -// uint32 opNum; -// PoolID liquidityPoolID; -// Asset asset; -// } -type HashIdPreimageRevokeId struct { - SourceAccount AccountId - SeqNum SequenceNumber - OpNum Uint32 - LiquidityPoolId PoolId - Asset Asset +// enum ClawbackClaimableBalanceResultCode +// { +// // codes considered as "success" for the operation +// CLAWBACK_CLAIMABLE_BALANCE_SUCCESS = 0, +// +// // codes considered as "failure" for the operation +// CLAWBACK_CLAIMABLE_BALANCE_DOES_NOT_EXIST = -1, +// CLAWBACK_CLAIMABLE_BALANCE_NOT_ISSUER = -2, +// CLAWBACK_CLAIMABLE_BALANCE_NOT_CLAWBACK_ENABLED = -3 +// }; +type ClawbackClaimableBalanceResultCode int32 + +const ( + ClawbackClaimableBalanceResultCodeClawbackClaimableBalanceSuccess ClawbackClaimableBalanceResultCode = 0 + ClawbackClaimableBalanceResultCodeClawbackClaimableBalanceDoesNotExist ClawbackClaimableBalanceResultCode = -1 + ClawbackClaimableBalanceResultCodeClawbackClaimableBalanceNotIssuer ClawbackClaimableBalanceResultCode = -2 + ClawbackClaimableBalanceResultCodeClawbackClaimableBalanceNotClawbackEnabled ClawbackClaimableBalanceResultCode = -3 +) + +var clawbackClaimableBalanceResultCodeMap = map[int32]string{ + 0: "ClawbackClaimableBalanceResultCodeClawbackClaimableBalanceSuccess", + -1: "ClawbackClaimableBalanceResultCodeClawbackClaimableBalanceDoesNotExist", + -2: "ClawbackClaimableBalanceResultCodeClawbackClaimableBalanceNotIssuer", + -3: "ClawbackClaimableBalanceResultCodeClawbackClaimableBalanceNotClawbackEnabled", +} + +// ValidEnum validates a proposed value for this enum. Implements +// the Enum interface for ClawbackClaimableBalanceResultCode +func (e ClawbackClaimableBalanceResultCode) ValidEnum(v int32) bool { + _, ok := clawbackClaimableBalanceResultCodeMap[v] + return ok +} + +// String returns the name of `e` +func (e ClawbackClaimableBalanceResultCode) String() string { + name, _ := clawbackClaimableBalanceResultCodeMap[int32(e)] + return name } // EncodeTo encodes this value using the Encoder. -func (s *HashIdPreimageRevokeId) EncodeTo(e *xdr.Encoder) error { - var err error - if err = s.SourceAccount.EncodeTo(e); err != nil { - return err - } - if err = s.SeqNum.EncodeTo(e); err != nil { - return err - } - if err = s.OpNum.EncodeTo(e); err != nil { - return err - } - if err = s.LiquidityPoolId.EncodeTo(e); err != nil { - return err - } - if err = s.Asset.EncodeTo(e); err != nil { - return err +func (e ClawbackClaimableBalanceResultCode) EncodeTo(enc *xdr.Encoder) error { + if _, ok := clawbackClaimableBalanceResultCodeMap[int32(e)]; !ok { + return fmt.Errorf("'%d' is not a valid ClawbackClaimableBalanceResultCode enum value", e) } - return nil + _, err := enc.EncodeInt(int32(e)) + return err } -var _ decoderFrom = (*HashIdPreimageRevokeId)(nil) +var _ decoderFrom = (*ClawbackClaimableBalanceResultCode)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *HashIdPreimageRevokeId) DecodeFrom(d *xdr.Decoder) (int, error) { - var err error - var n, nTmp int - nTmp, err = s.SourceAccount.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding AccountId: %s", err) - } - nTmp, err = s.SeqNum.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding SequenceNumber: %s", err) +func (e *ClawbackClaimableBalanceResultCode) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding ClawbackClaimableBalanceResultCode: %w", ErrMaxDecodingDepthReached) } - nTmp, err = s.OpNum.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Uint32: %s", err) - } - nTmp, err = s.LiquidityPoolId.DecodeFrom(d) - n += nTmp + maxDepth -= 1 + v, n, err := d.DecodeInt() if err != nil { - return n, fmt.Errorf("decoding PoolId: %s", err) + return n, fmt.Errorf("decoding ClawbackClaimableBalanceResultCode: %w", err) } - nTmp, err = s.Asset.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Asset: %s", err) + if _, ok := clawbackClaimableBalanceResultCodeMap[v]; !ok { + return n, fmt.Errorf("'%d' is not a valid ClawbackClaimableBalanceResultCode enum value", v) } + *e = ClawbackClaimableBalanceResultCode(v) return n, nil } // MarshalBinary implements encoding.BinaryMarshaler. -func (s HashIdPreimageRevokeId) MarshalBinary() ([]byte, error) { +func (s ClawbackClaimableBalanceResultCode) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -22733,196 +39640,136 @@ func (s HashIdPreimageRevokeId) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *HashIdPreimageRevokeId) UnmarshalBinary(inp []byte) error { +func (s *ClawbackClaimableBalanceResultCode) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*HashIdPreimageRevokeId)(nil) - _ encoding.BinaryUnmarshaler = (*HashIdPreimageRevokeId)(nil) + _ encoding.BinaryMarshaler = (*ClawbackClaimableBalanceResultCode)(nil) + _ encoding.BinaryUnmarshaler = (*ClawbackClaimableBalanceResultCode)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s HashIdPreimageRevokeId) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s ClawbackClaimableBalanceResultCode) xdrType() {} -var _ xdrType = (*HashIdPreimageRevokeId)(nil) +var _ xdrType = (*ClawbackClaimableBalanceResultCode)(nil) -// HashIdPreimage is an XDR Union defines as: +// ClawbackClaimableBalanceResult is an XDR Union defines as: // -// union HashIDPreimage switch (EnvelopeType type) +// union ClawbackClaimableBalanceResult switch ( +// ClawbackClaimableBalanceResultCode code) // { -// case ENVELOPE_TYPE_OP_ID: -// struct -// { -// AccountID sourceAccount; -// SequenceNumber seqNum; -// uint32 opNum; -// } operationID; -// case ENVELOPE_TYPE_POOL_REVOKE_OP_ID: -// struct -// { -// AccountID sourceAccount; -// SequenceNumber seqNum; -// uint32 opNum; -// PoolID liquidityPoolID; -// Asset asset; -// } revokeID; +// case CLAWBACK_CLAIMABLE_BALANCE_SUCCESS: +// void; +// case CLAWBACK_CLAIMABLE_BALANCE_DOES_NOT_EXIST: +// case CLAWBACK_CLAIMABLE_BALANCE_NOT_ISSUER: +// case CLAWBACK_CLAIMABLE_BALANCE_NOT_CLAWBACK_ENABLED: +// void; // }; -type HashIdPreimage struct { - Type EnvelopeType - OperationId *HashIdPreimageOperationId - RevokeId *HashIdPreimageRevokeId +type ClawbackClaimableBalanceResult struct { + Code ClawbackClaimableBalanceResultCode } // SwitchFieldName returns the field name in which this union's // discriminant is stored -func (u HashIdPreimage) SwitchFieldName() string { - return "Type" +func (u ClawbackClaimableBalanceResult) SwitchFieldName() string { + return "Code" } // ArmForSwitch returns which field name should be used for storing -// the value for an instance of HashIdPreimage -func (u HashIdPreimage) ArmForSwitch(sw int32) (string, bool) { - switch EnvelopeType(sw) { - case EnvelopeTypeEnvelopeTypeOpId: - return "OperationId", true - case EnvelopeTypeEnvelopeTypePoolRevokeOpId: - return "RevokeId", true - } - return "-", false -} - -// NewHashIdPreimage creates a new HashIdPreimage. -func NewHashIdPreimage(aType EnvelopeType, value interface{}) (result HashIdPreimage, err error) { - result.Type = aType - switch EnvelopeType(aType) { - case EnvelopeTypeEnvelopeTypeOpId: - tv, ok := value.(HashIdPreimageOperationId) - if !ok { - err = fmt.Errorf("invalid value, must be HashIdPreimageOperationId") - return - } - result.OperationId = &tv - case EnvelopeTypeEnvelopeTypePoolRevokeOpId: - tv, ok := value.(HashIdPreimageRevokeId) - if !ok { - err = fmt.Errorf("invalid value, must be HashIdPreimageRevokeId") - return - } - result.RevokeId = &tv - } - return -} - -// MustOperationId retrieves the OperationId value from the union, -// panicing if the value is not set. -func (u HashIdPreimage) MustOperationId() HashIdPreimageOperationId { - val, ok := u.GetOperationId() - - if !ok { - panic("arm OperationId is not set") - } - - return val -} - -// GetOperationId retrieves the OperationId value from the union, -// returning ok if the union's switch indicated the value is valid. -func (u HashIdPreimage) GetOperationId() (result HashIdPreimageOperationId, ok bool) { - armName, _ := u.ArmForSwitch(int32(u.Type)) - - if armName == "OperationId" { - result = *u.OperationId - ok = true - } - - return -} - -// MustRevokeId retrieves the RevokeId value from the union, -// panicing if the value is not set. -func (u HashIdPreimage) MustRevokeId() HashIdPreimageRevokeId { - val, ok := u.GetRevokeId() - - if !ok { - panic("arm RevokeId is not set") +// the value for an instance of ClawbackClaimableBalanceResult +func (u ClawbackClaimableBalanceResult) ArmForSwitch(sw int32) (string, bool) { + switch ClawbackClaimableBalanceResultCode(sw) { + case ClawbackClaimableBalanceResultCodeClawbackClaimableBalanceSuccess: + return "", true + case ClawbackClaimableBalanceResultCodeClawbackClaimableBalanceDoesNotExist: + return "", true + case ClawbackClaimableBalanceResultCodeClawbackClaimableBalanceNotIssuer: + return "", true + case ClawbackClaimableBalanceResultCodeClawbackClaimableBalanceNotClawbackEnabled: + return "", true } - - return val + return "-", false } -// GetRevokeId retrieves the RevokeId value from the union, -// returning ok if the union's switch indicated the value is valid. -func (u HashIdPreimage) GetRevokeId() (result HashIdPreimageRevokeId, ok bool) { - armName, _ := u.ArmForSwitch(int32(u.Type)) - - if armName == "RevokeId" { - result = *u.RevokeId - ok = true +// NewClawbackClaimableBalanceResult creates a new ClawbackClaimableBalanceResult. +func NewClawbackClaimableBalanceResult(code ClawbackClaimableBalanceResultCode, value interface{}) (result ClawbackClaimableBalanceResult, err error) { + result.Code = code + switch ClawbackClaimableBalanceResultCode(code) { + case ClawbackClaimableBalanceResultCodeClawbackClaimableBalanceSuccess: + // void + case ClawbackClaimableBalanceResultCodeClawbackClaimableBalanceDoesNotExist: + // void + case ClawbackClaimableBalanceResultCodeClawbackClaimableBalanceNotIssuer: + // void + case ClawbackClaimableBalanceResultCodeClawbackClaimableBalanceNotClawbackEnabled: + // void } - return } // EncodeTo encodes this value using the Encoder. -func (u HashIdPreimage) EncodeTo(e *xdr.Encoder) error { +func (u ClawbackClaimableBalanceResult) EncodeTo(e *xdr.Encoder) error { var err error - if err = u.Type.EncodeTo(e); err != nil { + if err = u.Code.EncodeTo(e); err != nil { return err } - switch EnvelopeType(u.Type) { - case EnvelopeTypeEnvelopeTypeOpId: - if err = (*u.OperationId).EncodeTo(e); err != nil { - return err - } + switch ClawbackClaimableBalanceResultCode(u.Code) { + case ClawbackClaimableBalanceResultCodeClawbackClaimableBalanceSuccess: + // Void return nil - case EnvelopeTypeEnvelopeTypePoolRevokeOpId: - if err = (*u.RevokeId).EncodeTo(e); err != nil { - return err - } + case ClawbackClaimableBalanceResultCodeClawbackClaimableBalanceDoesNotExist: + // Void + return nil + case ClawbackClaimableBalanceResultCodeClawbackClaimableBalanceNotIssuer: + // Void + return nil + case ClawbackClaimableBalanceResultCodeClawbackClaimableBalanceNotClawbackEnabled: + // Void return nil } - return fmt.Errorf("Type (EnvelopeType) switch value '%d' is not valid for union HashIdPreimage", u.Type) + return fmt.Errorf("Code (ClawbackClaimableBalanceResultCode) switch value '%d' is not valid for union ClawbackClaimableBalanceResult", u.Code) } -var _ decoderFrom = (*HashIdPreimage)(nil) +var _ decoderFrom = (*ClawbackClaimableBalanceResult)(nil) // DecodeFrom decodes this value using the Decoder. -func (u *HashIdPreimage) DecodeFrom(d *xdr.Decoder) (int, error) { +func (u *ClawbackClaimableBalanceResult) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding ClawbackClaimableBalanceResult: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = u.Type.DecodeFrom(d) + nTmp, err = u.Code.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding EnvelopeType: %s", err) + return n, fmt.Errorf("decoding ClawbackClaimableBalanceResultCode: %w", err) } - switch EnvelopeType(u.Type) { - case EnvelopeTypeEnvelopeTypeOpId: - u.OperationId = new(HashIdPreimageOperationId) - nTmp, err = (*u.OperationId).DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding HashIdPreimageOperationId: %s", err) - } + switch ClawbackClaimableBalanceResultCode(u.Code) { + case ClawbackClaimableBalanceResultCodeClawbackClaimableBalanceSuccess: + // Void return n, nil - case EnvelopeTypeEnvelopeTypePoolRevokeOpId: - u.RevokeId = new(HashIdPreimageRevokeId) - nTmp, err = (*u.RevokeId).DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding HashIdPreimageRevokeId: %s", err) - } + case ClawbackClaimableBalanceResultCodeClawbackClaimableBalanceDoesNotExist: + // Void + return n, nil + case ClawbackClaimableBalanceResultCodeClawbackClaimableBalanceNotIssuer: + // Void + return n, nil + case ClawbackClaimableBalanceResultCodeClawbackClaimableBalanceNotClawbackEnabled: + // Void return n, nil } - return n, fmt.Errorf("union HashIdPreimage has invalid Type (EnvelopeType) switch value '%d'", u.Type) + return n, fmt.Errorf("union ClawbackClaimableBalanceResult has invalid Code (ClawbackClaimableBalanceResultCode) switch value '%d'", u.Code) } // MarshalBinary implements encoding.BinaryMarshaler. -func (s HashIdPreimage) MarshalBinary() ([]byte, error) { +func (s ClawbackClaimableBalanceResult) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -22930,91 +39777,103 @@ func (s HashIdPreimage) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *HashIdPreimage) UnmarshalBinary(inp []byte) error { +func (s *ClawbackClaimableBalanceResult) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*HashIdPreimage)(nil) - _ encoding.BinaryUnmarshaler = (*HashIdPreimage)(nil) + _ encoding.BinaryMarshaler = (*ClawbackClaimableBalanceResult)(nil) + _ encoding.BinaryUnmarshaler = (*ClawbackClaimableBalanceResult)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s HashIdPreimage) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s ClawbackClaimableBalanceResult) xdrType() {} -var _ xdrType = (*HashIdPreimage)(nil) +var _ xdrType = (*ClawbackClaimableBalanceResult)(nil) -// MemoType is an XDR Enum defines as: +// SetTrustLineFlagsResultCode is an XDR Enum defines as: // -// enum MemoType +// enum SetTrustLineFlagsResultCode // { -// MEMO_NONE = 0, -// MEMO_TEXT = 1, -// MEMO_ID = 2, -// MEMO_HASH = 3, -// MEMO_RETURN = 4 +// // codes considered as "success" for the operation +// SET_TRUST_LINE_FLAGS_SUCCESS = 0, +// +// // codes considered as "failure" for the operation +// SET_TRUST_LINE_FLAGS_MALFORMED = -1, +// SET_TRUST_LINE_FLAGS_NO_TRUST_LINE = -2, +// SET_TRUST_LINE_FLAGS_CANT_REVOKE = -3, +// SET_TRUST_LINE_FLAGS_INVALID_STATE = -4, +// SET_TRUST_LINE_FLAGS_LOW_RESERVE = -5 // claimable balances can't be created +// // on revoke due to low reserves // }; -type MemoType int32 +type SetTrustLineFlagsResultCode int32 const ( - MemoTypeMemoNone MemoType = 0 - MemoTypeMemoText MemoType = 1 - MemoTypeMemoId MemoType = 2 - MemoTypeMemoHash MemoType = 3 - MemoTypeMemoReturn MemoType = 4 + SetTrustLineFlagsResultCodeSetTrustLineFlagsSuccess SetTrustLineFlagsResultCode = 0 + SetTrustLineFlagsResultCodeSetTrustLineFlagsMalformed SetTrustLineFlagsResultCode = -1 + SetTrustLineFlagsResultCodeSetTrustLineFlagsNoTrustLine SetTrustLineFlagsResultCode = -2 + SetTrustLineFlagsResultCodeSetTrustLineFlagsCantRevoke SetTrustLineFlagsResultCode = -3 + SetTrustLineFlagsResultCodeSetTrustLineFlagsInvalidState SetTrustLineFlagsResultCode = -4 + SetTrustLineFlagsResultCodeSetTrustLineFlagsLowReserve SetTrustLineFlagsResultCode = -5 ) -var memoTypeMap = map[int32]string{ - 0: "MemoTypeMemoNone", - 1: "MemoTypeMemoText", - 2: "MemoTypeMemoId", - 3: "MemoTypeMemoHash", - 4: "MemoTypeMemoReturn", +var setTrustLineFlagsResultCodeMap = map[int32]string{ + 0: "SetTrustLineFlagsResultCodeSetTrustLineFlagsSuccess", + -1: "SetTrustLineFlagsResultCodeSetTrustLineFlagsMalformed", + -2: "SetTrustLineFlagsResultCodeSetTrustLineFlagsNoTrustLine", + -3: "SetTrustLineFlagsResultCodeSetTrustLineFlagsCantRevoke", + -4: "SetTrustLineFlagsResultCodeSetTrustLineFlagsInvalidState", + -5: "SetTrustLineFlagsResultCodeSetTrustLineFlagsLowReserve", } // ValidEnum validates a proposed value for this enum. Implements -// the Enum interface for MemoType -func (e MemoType) ValidEnum(v int32) bool { - _, ok := memoTypeMap[v] +// the Enum interface for SetTrustLineFlagsResultCode +func (e SetTrustLineFlagsResultCode) ValidEnum(v int32) bool { + _, ok := setTrustLineFlagsResultCodeMap[v] return ok } // String returns the name of `e` -func (e MemoType) String() string { - name, _ := memoTypeMap[int32(e)] +func (e SetTrustLineFlagsResultCode) String() string { + name, _ := setTrustLineFlagsResultCodeMap[int32(e)] return name } // EncodeTo encodes this value using the Encoder. -func (e MemoType) EncodeTo(enc *xdr.Encoder) error { - if _, ok := memoTypeMap[int32(e)]; !ok { - return fmt.Errorf("'%d' is not a valid MemoType enum value", e) +func (e SetTrustLineFlagsResultCode) EncodeTo(enc *xdr.Encoder) error { + if _, ok := setTrustLineFlagsResultCodeMap[int32(e)]; !ok { + return fmt.Errorf("'%d' is not a valid SetTrustLineFlagsResultCode enum value", e) } _, err := enc.EncodeInt(int32(e)) return err } -var _ decoderFrom = (*MemoType)(nil) +var _ decoderFrom = (*SetTrustLineFlagsResultCode)(nil) // DecodeFrom decodes this value using the Decoder. -func (e *MemoType) DecodeFrom(d *xdr.Decoder) (int, error) { +func (e *SetTrustLineFlagsResultCode) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding SetTrustLineFlagsResultCode: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 v, n, err := d.DecodeInt() if err != nil { - return n, fmt.Errorf("decoding MemoType: %s", err) + return n, fmt.Errorf("decoding SetTrustLineFlagsResultCode: %w", err) } - if _, ok := memoTypeMap[v]; !ok { - return n, fmt.Errorf("'%d' is not a valid MemoType enum value", v) + if _, ok := setTrustLineFlagsResultCodeMap[v]; !ok { + return n, fmt.Errorf("'%d' is not a valid SetTrustLineFlagsResultCode enum value", v) } - *e = MemoType(v) + *e = SetTrustLineFlagsResultCode(v) return n, nil } // MarshalBinary implements encoding.BinaryMarshaler. -func (s MemoType) MarshalBinary() ([]byte, error) { +func (s SetTrustLineFlagsResultCode) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -23022,296 +39881,270 @@ func (s MemoType) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *MemoType) UnmarshalBinary(inp []byte) error { +func (s *SetTrustLineFlagsResultCode) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*MemoType)(nil) - _ encoding.BinaryUnmarshaler = (*MemoType)(nil) + _ encoding.BinaryMarshaler = (*SetTrustLineFlagsResultCode)(nil) + _ encoding.BinaryUnmarshaler = (*SetTrustLineFlagsResultCode)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s MemoType) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s SetTrustLineFlagsResultCode) xdrType() {} -var _ xdrType = (*MemoType)(nil) +var _ xdrType = (*SetTrustLineFlagsResultCode)(nil) -// Memo is an XDR Union defines as: +// SetTrustLineFlagsResult is an XDR Union defines as: // -// union Memo switch (MemoType type) +// union SetTrustLineFlagsResult switch (SetTrustLineFlagsResultCode code) // { -// case MEMO_NONE: +// case SET_TRUST_LINE_FLAGS_SUCCESS: +// void; +// case SET_TRUST_LINE_FLAGS_MALFORMED: +// case SET_TRUST_LINE_FLAGS_NO_TRUST_LINE: +// case SET_TRUST_LINE_FLAGS_CANT_REVOKE: +// case SET_TRUST_LINE_FLAGS_INVALID_STATE: +// case SET_TRUST_LINE_FLAGS_LOW_RESERVE: // void; -// case MEMO_TEXT: -// string text<28>; -// case MEMO_ID: -// uint64 id; -// case MEMO_HASH: -// Hash hash; // the hash of what to pull from the content server -// case MEMO_RETURN: -// Hash retHash; // the hash of the tx you are rejecting // }; -type Memo struct { - Type MemoType - Text *string `xdrmaxsize:"28"` - Id *Uint64 - Hash *Hash - RetHash *Hash +type SetTrustLineFlagsResult struct { + Code SetTrustLineFlagsResultCode } // SwitchFieldName returns the field name in which this union's // discriminant is stored -func (u Memo) SwitchFieldName() string { - return "Type" +func (u SetTrustLineFlagsResult) SwitchFieldName() string { + return "Code" } // ArmForSwitch returns which field name should be used for storing -// the value for an instance of Memo -func (u Memo) ArmForSwitch(sw int32) (string, bool) { - switch MemoType(sw) { - case MemoTypeMemoNone: +// the value for an instance of SetTrustLineFlagsResult +func (u SetTrustLineFlagsResult) ArmForSwitch(sw int32) (string, bool) { + switch SetTrustLineFlagsResultCode(sw) { + case SetTrustLineFlagsResultCodeSetTrustLineFlagsSuccess: + return "", true + case SetTrustLineFlagsResultCodeSetTrustLineFlagsMalformed: + return "", true + case SetTrustLineFlagsResultCodeSetTrustLineFlagsNoTrustLine: + return "", true + case SetTrustLineFlagsResultCodeSetTrustLineFlagsCantRevoke: + return "", true + case SetTrustLineFlagsResultCodeSetTrustLineFlagsInvalidState: + return "", true + case SetTrustLineFlagsResultCodeSetTrustLineFlagsLowReserve: return "", true - case MemoTypeMemoText: - return "Text", true - case MemoTypeMemoId: - return "Id", true - case MemoTypeMemoHash: - return "Hash", true - case MemoTypeMemoReturn: - return "RetHash", true } return "-", false } -// NewMemo creates a new Memo. -func NewMemo(aType MemoType, value interface{}) (result Memo, err error) { - result.Type = aType - switch MemoType(aType) { - case MemoTypeMemoNone: +// NewSetTrustLineFlagsResult creates a new SetTrustLineFlagsResult. +func NewSetTrustLineFlagsResult(code SetTrustLineFlagsResultCode, value interface{}) (result SetTrustLineFlagsResult, err error) { + result.Code = code + switch SetTrustLineFlagsResultCode(code) { + case SetTrustLineFlagsResultCodeSetTrustLineFlagsSuccess: + // void + case SetTrustLineFlagsResultCodeSetTrustLineFlagsMalformed: + // void + case SetTrustLineFlagsResultCodeSetTrustLineFlagsNoTrustLine: + // void + case SetTrustLineFlagsResultCodeSetTrustLineFlagsCantRevoke: + // void + case SetTrustLineFlagsResultCodeSetTrustLineFlagsInvalidState: + // void + case SetTrustLineFlagsResultCodeSetTrustLineFlagsLowReserve: // void - case MemoTypeMemoText: - tv, ok := value.(string) - if !ok { - err = fmt.Errorf("invalid value, must be string") - return - } - result.Text = &tv - case MemoTypeMemoId: - tv, ok := value.(Uint64) - if !ok { - err = fmt.Errorf("invalid value, must be Uint64") - return - } - result.Id = &tv - case MemoTypeMemoHash: - tv, ok := value.(Hash) - if !ok { - err = fmt.Errorf("invalid value, must be Hash") - return - } - result.Hash = &tv - case MemoTypeMemoReturn: - tv, ok := value.(Hash) - if !ok { - err = fmt.Errorf("invalid value, must be Hash") - return - } - result.RetHash = &tv } return } -// MustText retrieves the Text value from the union, -// panicing if the value is not set. -func (u Memo) MustText() string { - val, ok := u.GetText() - - if !ok { - panic("arm Text is not set") +// EncodeTo encodes this value using the Encoder. +func (u SetTrustLineFlagsResult) EncodeTo(e *xdr.Encoder) error { + var err error + if err = u.Code.EncodeTo(e); err != nil { + return err } - - return val -} - -// GetText retrieves the Text value from the union, -// returning ok if the union's switch indicated the value is valid. -func (u Memo) GetText() (result string, ok bool) { - armName, _ := u.ArmForSwitch(int32(u.Type)) - - if armName == "Text" { - result = *u.Text - ok = true + switch SetTrustLineFlagsResultCode(u.Code) { + case SetTrustLineFlagsResultCodeSetTrustLineFlagsSuccess: + // Void + return nil + case SetTrustLineFlagsResultCodeSetTrustLineFlagsMalformed: + // Void + return nil + case SetTrustLineFlagsResultCodeSetTrustLineFlagsNoTrustLine: + // Void + return nil + case SetTrustLineFlagsResultCodeSetTrustLineFlagsCantRevoke: + // Void + return nil + case SetTrustLineFlagsResultCodeSetTrustLineFlagsInvalidState: + // Void + return nil + case SetTrustLineFlagsResultCodeSetTrustLineFlagsLowReserve: + // Void + return nil } - - return + return fmt.Errorf("Code (SetTrustLineFlagsResultCode) switch value '%d' is not valid for union SetTrustLineFlagsResult", u.Code) } -// MustId retrieves the Id value from the union, -// panicing if the value is not set. -func (u Memo) MustId() Uint64 { - val, ok := u.GetId() +var _ decoderFrom = (*SetTrustLineFlagsResult)(nil) - if !ok { - panic("arm Id is not set") +// DecodeFrom decodes this value using the Decoder. +func (u *SetTrustLineFlagsResult) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding SetTrustLineFlagsResult: %w", ErrMaxDecodingDepthReached) } - - return val -} - -// GetId retrieves the Id value from the union, -// returning ok if the union's switch indicated the value is valid. -func (u Memo) GetId() (result Uint64, ok bool) { - armName, _ := u.ArmForSwitch(int32(u.Type)) - - if armName == "Id" { - result = *u.Id - ok = true + maxDepth -= 1 + var err error + var n, nTmp int + nTmp, err = u.Code.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding SetTrustLineFlagsResultCode: %w", err) } - - return + switch SetTrustLineFlagsResultCode(u.Code) { + case SetTrustLineFlagsResultCodeSetTrustLineFlagsSuccess: + // Void + return n, nil + case SetTrustLineFlagsResultCodeSetTrustLineFlagsMalformed: + // Void + return n, nil + case SetTrustLineFlagsResultCodeSetTrustLineFlagsNoTrustLine: + // Void + return n, nil + case SetTrustLineFlagsResultCodeSetTrustLineFlagsCantRevoke: + // Void + return n, nil + case SetTrustLineFlagsResultCodeSetTrustLineFlagsInvalidState: + // Void + return n, nil + case SetTrustLineFlagsResultCodeSetTrustLineFlagsLowReserve: + // Void + return n, nil + } + return n, fmt.Errorf("union SetTrustLineFlagsResult has invalid Code (SetTrustLineFlagsResultCode) switch value '%d'", u.Code) } -// MustHash retrieves the Hash value from the union, -// panicing if the value is not set. -func (u Memo) MustHash() Hash { - val, ok := u.GetHash() - - if !ok { - panic("arm Hash is not set") - } +// MarshalBinary implements encoding.BinaryMarshaler. +func (s SetTrustLineFlagsResult) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} - return val +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *SetTrustLineFlagsResult) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err } -// GetHash retrieves the Hash value from the union, -// returning ok if the union's switch indicated the value is valid. -func (u Memo) GetHash() (result Hash, ok bool) { - armName, _ := u.ArmForSwitch(int32(u.Type)) +var ( + _ encoding.BinaryMarshaler = (*SetTrustLineFlagsResult)(nil) + _ encoding.BinaryUnmarshaler = (*SetTrustLineFlagsResult)(nil) +) - if armName == "Hash" { - result = *u.Hash - ok = true - } +// xdrType signals that this type represents XDR values defined by this package. +func (s SetTrustLineFlagsResult) xdrType() {} - return -} +var _ xdrType = (*SetTrustLineFlagsResult)(nil) -// MustRetHash retrieves the RetHash value from the union, -// panicing if the value is not set. -func (u Memo) MustRetHash() Hash { - val, ok := u.GetRetHash() +// LiquidityPoolDepositResultCode is an XDR Enum defines as: +// +// enum LiquidityPoolDepositResultCode +// { +// // codes considered as "success" for the operation +// LIQUIDITY_POOL_DEPOSIT_SUCCESS = 0, +// +// // codes considered as "failure" for the operation +// LIQUIDITY_POOL_DEPOSIT_MALFORMED = -1, // bad input +// LIQUIDITY_POOL_DEPOSIT_NO_TRUST = -2, // no trust line for one of the +// // assets +// LIQUIDITY_POOL_DEPOSIT_NOT_AUTHORIZED = -3, // not authorized for one of the +// // assets +// LIQUIDITY_POOL_DEPOSIT_UNDERFUNDED = -4, // not enough balance for one of +// // the assets +// LIQUIDITY_POOL_DEPOSIT_LINE_FULL = -5, // pool share trust line doesn't +// // have sufficient limit +// LIQUIDITY_POOL_DEPOSIT_BAD_PRICE = -6, // deposit price outside bounds +// LIQUIDITY_POOL_DEPOSIT_POOL_FULL = -7 // pool reserves are full +// }; +type LiquidityPoolDepositResultCode int32 - if !ok { - panic("arm RetHash is not set") - } +const ( + LiquidityPoolDepositResultCodeLiquidityPoolDepositSuccess LiquidityPoolDepositResultCode = 0 + LiquidityPoolDepositResultCodeLiquidityPoolDepositMalformed LiquidityPoolDepositResultCode = -1 + LiquidityPoolDepositResultCodeLiquidityPoolDepositNoTrust LiquidityPoolDepositResultCode = -2 + LiquidityPoolDepositResultCodeLiquidityPoolDepositNotAuthorized LiquidityPoolDepositResultCode = -3 + LiquidityPoolDepositResultCodeLiquidityPoolDepositUnderfunded LiquidityPoolDepositResultCode = -4 + LiquidityPoolDepositResultCodeLiquidityPoolDepositLineFull LiquidityPoolDepositResultCode = -5 + LiquidityPoolDepositResultCodeLiquidityPoolDepositBadPrice LiquidityPoolDepositResultCode = -6 + LiquidityPoolDepositResultCodeLiquidityPoolDepositPoolFull LiquidityPoolDepositResultCode = -7 +) - return val +var liquidityPoolDepositResultCodeMap = map[int32]string{ + 0: "LiquidityPoolDepositResultCodeLiquidityPoolDepositSuccess", + -1: "LiquidityPoolDepositResultCodeLiquidityPoolDepositMalformed", + -2: "LiquidityPoolDepositResultCodeLiquidityPoolDepositNoTrust", + -3: "LiquidityPoolDepositResultCodeLiquidityPoolDepositNotAuthorized", + -4: "LiquidityPoolDepositResultCodeLiquidityPoolDepositUnderfunded", + -5: "LiquidityPoolDepositResultCodeLiquidityPoolDepositLineFull", + -6: "LiquidityPoolDepositResultCodeLiquidityPoolDepositBadPrice", + -7: "LiquidityPoolDepositResultCodeLiquidityPoolDepositPoolFull", } -// GetRetHash retrieves the RetHash value from the union, -// returning ok if the union's switch indicated the value is valid. -func (u Memo) GetRetHash() (result Hash, ok bool) { - armName, _ := u.ArmForSwitch(int32(u.Type)) - - if armName == "RetHash" { - result = *u.RetHash - ok = true - } +// ValidEnum validates a proposed value for this enum. Implements +// the Enum interface for LiquidityPoolDepositResultCode +func (e LiquidityPoolDepositResultCode) ValidEnum(v int32) bool { + _, ok := liquidityPoolDepositResultCodeMap[v] + return ok +} - return +// String returns the name of `e` +func (e LiquidityPoolDepositResultCode) String() string { + name, _ := liquidityPoolDepositResultCodeMap[int32(e)] + return name } // EncodeTo encodes this value using the Encoder. -func (u Memo) EncodeTo(e *xdr.Encoder) error { - var err error - if err = u.Type.EncodeTo(e); err != nil { - return err - } - switch MemoType(u.Type) { - case MemoTypeMemoNone: - // Void - return nil - case MemoTypeMemoText: - if _, err = e.EncodeString(string((*u.Text))); err != nil { - return err - } - return nil - case MemoTypeMemoId: - if err = (*u.Id).EncodeTo(e); err != nil { - return err - } - return nil - case MemoTypeMemoHash: - if err = (*u.Hash).EncodeTo(e); err != nil { - return err - } - return nil - case MemoTypeMemoReturn: - if err = (*u.RetHash).EncodeTo(e); err != nil { - return err - } - return nil +func (e LiquidityPoolDepositResultCode) EncodeTo(enc *xdr.Encoder) error { + if _, ok := liquidityPoolDepositResultCodeMap[int32(e)]; !ok { + return fmt.Errorf("'%d' is not a valid LiquidityPoolDepositResultCode enum value", e) } - return fmt.Errorf("Type (MemoType) switch value '%d' is not valid for union Memo", u.Type) + _, err := enc.EncodeInt(int32(e)) + return err } -var _ decoderFrom = (*Memo)(nil) +var _ decoderFrom = (*LiquidityPoolDepositResultCode)(nil) // DecodeFrom decodes this value using the Decoder. -func (u *Memo) DecodeFrom(d *xdr.Decoder) (int, error) { - var err error - var n, nTmp int - nTmp, err = u.Type.DecodeFrom(d) - n += nTmp +func (e *LiquidityPoolDepositResultCode) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding LiquidityPoolDepositResultCode: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + v, n, err := d.DecodeInt() if err != nil { - return n, fmt.Errorf("decoding MemoType: %s", err) + return n, fmt.Errorf("decoding LiquidityPoolDepositResultCode: %w", err) } - switch MemoType(u.Type) { - case MemoTypeMemoNone: - // Void - return n, nil - case MemoTypeMemoText: - u.Text = new(string) - (*u.Text), nTmp, err = d.DecodeString(28) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Text: %s", err) - } - return n, nil - case MemoTypeMemoId: - u.Id = new(Uint64) - nTmp, err = (*u.Id).DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Uint64: %s", err) - } - return n, nil - case MemoTypeMemoHash: - u.Hash = new(Hash) - nTmp, err = (*u.Hash).DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Hash: %s", err) - } - return n, nil - case MemoTypeMemoReturn: - u.RetHash = new(Hash) - nTmp, err = (*u.RetHash).DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Hash: %s", err) - } - return n, nil + if _, ok := liquidityPoolDepositResultCodeMap[v]; !ok { + return n, fmt.Errorf("'%d' is not a valid LiquidityPoolDepositResultCode enum value", v) } - return n, fmt.Errorf("union Memo has invalid Type (MemoType) switch value '%d'", u.Type) + *e = LiquidityPoolDepositResultCode(v) + return n, nil } // MarshalBinary implements encoding.BinaryMarshaler. -func (s Memo) MarshalBinary() ([]byte, error) { +func (s LiquidityPoolDepositResultCode) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -23319,69 +40152,179 @@ func (s Memo) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *Memo) UnmarshalBinary(inp []byte) error { +func (s *LiquidityPoolDepositResultCode) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*Memo)(nil) - _ encoding.BinaryUnmarshaler = (*Memo)(nil) + _ encoding.BinaryMarshaler = (*LiquidityPoolDepositResultCode)(nil) + _ encoding.BinaryUnmarshaler = (*LiquidityPoolDepositResultCode)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s Memo) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s LiquidityPoolDepositResultCode) xdrType() {} -var _ xdrType = (*Memo)(nil) +var _ xdrType = (*LiquidityPoolDepositResultCode)(nil) -// TimeBounds is an XDR Struct defines as: +// LiquidityPoolDepositResult is an XDR Union defines as: // -// struct TimeBounds +// union LiquidityPoolDepositResult switch (LiquidityPoolDepositResultCode code) // { -// TimePoint minTime; -// TimePoint maxTime; // 0 here means no maxTime +// case LIQUIDITY_POOL_DEPOSIT_SUCCESS: +// void; +// case LIQUIDITY_POOL_DEPOSIT_MALFORMED: +// case LIQUIDITY_POOL_DEPOSIT_NO_TRUST: +// case LIQUIDITY_POOL_DEPOSIT_NOT_AUTHORIZED: +// case LIQUIDITY_POOL_DEPOSIT_UNDERFUNDED: +// case LIQUIDITY_POOL_DEPOSIT_LINE_FULL: +// case LIQUIDITY_POOL_DEPOSIT_BAD_PRICE: +// case LIQUIDITY_POOL_DEPOSIT_POOL_FULL: +// void; // }; -type TimeBounds struct { - MinTime TimePoint - MaxTime TimePoint +type LiquidityPoolDepositResult struct { + Code LiquidityPoolDepositResultCode +} + +// SwitchFieldName returns the field name in which this union's +// discriminant is stored +func (u LiquidityPoolDepositResult) SwitchFieldName() string { + return "Code" +} + +// ArmForSwitch returns which field name should be used for storing +// the value for an instance of LiquidityPoolDepositResult +func (u LiquidityPoolDepositResult) ArmForSwitch(sw int32) (string, bool) { + switch LiquidityPoolDepositResultCode(sw) { + case LiquidityPoolDepositResultCodeLiquidityPoolDepositSuccess: + return "", true + case LiquidityPoolDepositResultCodeLiquidityPoolDepositMalformed: + return "", true + case LiquidityPoolDepositResultCodeLiquidityPoolDepositNoTrust: + return "", true + case LiquidityPoolDepositResultCodeLiquidityPoolDepositNotAuthorized: + return "", true + case LiquidityPoolDepositResultCodeLiquidityPoolDepositUnderfunded: + return "", true + case LiquidityPoolDepositResultCodeLiquidityPoolDepositLineFull: + return "", true + case LiquidityPoolDepositResultCodeLiquidityPoolDepositBadPrice: + return "", true + case LiquidityPoolDepositResultCodeLiquidityPoolDepositPoolFull: + return "", true + } + return "-", false +} + +// NewLiquidityPoolDepositResult creates a new LiquidityPoolDepositResult. +func NewLiquidityPoolDepositResult(code LiquidityPoolDepositResultCode, value interface{}) (result LiquidityPoolDepositResult, err error) { + result.Code = code + switch LiquidityPoolDepositResultCode(code) { + case LiquidityPoolDepositResultCodeLiquidityPoolDepositSuccess: + // void + case LiquidityPoolDepositResultCodeLiquidityPoolDepositMalformed: + // void + case LiquidityPoolDepositResultCodeLiquidityPoolDepositNoTrust: + // void + case LiquidityPoolDepositResultCodeLiquidityPoolDepositNotAuthorized: + // void + case LiquidityPoolDepositResultCodeLiquidityPoolDepositUnderfunded: + // void + case LiquidityPoolDepositResultCodeLiquidityPoolDepositLineFull: + // void + case LiquidityPoolDepositResultCodeLiquidityPoolDepositBadPrice: + // void + case LiquidityPoolDepositResultCodeLiquidityPoolDepositPoolFull: + // void + } + return } // EncodeTo encodes this value using the Encoder. -func (s *TimeBounds) EncodeTo(e *xdr.Encoder) error { +func (u LiquidityPoolDepositResult) EncodeTo(e *xdr.Encoder) error { var err error - if err = s.MinTime.EncodeTo(e); err != nil { + if err = u.Code.EncodeTo(e); err != nil { return err } - if err = s.MaxTime.EncodeTo(e); err != nil { - return err + switch LiquidityPoolDepositResultCode(u.Code) { + case LiquidityPoolDepositResultCodeLiquidityPoolDepositSuccess: + // Void + return nil + case LiquidityPoolDepositResultCodeLiquidityPoolDepositMalformed: + // Void + return nil + case LiquidityPoolDepositResultCodeLiquidityPoolDepositNoTrust: + // Void + return nil + case LiquidityPoolDepositResultCodeLiquidityPoolDepositNotAuthorized: + // Void + return nil + case LiquidityPoolDepositResultCodeLiquidityPoolDepositUnderfunded: + // Void + return nil + case LiquidityPoolDepositResultCodeLiquidityPoolDepositLineFull: + // Void + return nil + case LiquidityPoolDepositResultCodeLiquidityPoolDepositBadPrice: + // Void + return nil + case LiquidityPoolDepositResultCodeLiquidityPoolDepositPoolFull: + // Void + return nil } - return nil + return fmt.Errorf("Code (LiquidityPoolDepositResultCode) switch value '%d' is not valid for union LiquidityPoolDepositResult", u.Code) } -var _ decoderFrom = (*TimeBounds)(nil) +var _ decoderFrom = (*LiquidityPoolDepositResult)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *TimeBounds) DecodeFrom(d *xdr.Decoder) (int, error) { +func (u *LiquidityPoolDepositResult) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding LiquidityPoolDepositResult: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = s.MinTime.DecodeFrom(d) + nTmp, err = u.Code.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding TimePoint: %s", err) + return n, fmt.Errorf("decoding LiquidityPoolDepositResultCode: %w", err) } - nTmp, err = s.MaxTime.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding TimePoint: %s", err) + switch LiquidityPoolDepositResultCode(u.Code) { + case LiquidityPoolDepositResultCodeLiquidityPoolDepositSuccess: + // Void + return n, nil + case LiquidityPoolDepositResultCodeLiquidityPoolDepositMalformed: + // Void + return n, nil + case LiquidityPoolDepositResultCodeLiquidityPoolDepositNoTrust: + // Void + return n, nil + case LiquidityPoolDepositResultCodeLiquidityPoolDepositNotAuthorized: + // Void + return n, nil + case LiquidityPoolDepositResultCodeLiquidityPoolDepositUnderfunded: + // Void + return n, nil + case LiquidityPoolDepositResultCodeLiquidityPoolDepositLineFull: + // Void + return n, nil + case LiquidityPoolDepositResultCodeLiquidityPoolDepositBadPrice: + // Void + return n, nil + case LiquidityPoolDepositResultCodeLiquidityPoolDepositPoolFull: + // Void + return n, nil } - return n, nil + return n, fmt.Errorf("union LiquidityPoolDepositResult has invalid Code (LiquidityPoolDepositResultCode) switch value '%d'", u.Code) } // MarshalBinary implements encoding.BinaryMarshaler. -func (s TimeBounds) MarshalBinary() ([]byte, error) { +func (s LiquidityPoolDepositResult) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -23389,69 +40332,105 @@ func (s TimeBounds) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *TimeBounds) UnmarshalBinary(inp []byte) error { +func (s *LiquidityPoolDepositResult) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*TimeBounds)(nil) - _ encoding.BinaryUnmarshaler = (*TimeBounds)(nil) + _ encoding.BinaryMarshaler = (*LiquidityPoolDepositResult)(nil) + _ encoding.BinaryUnmarshaler = (*LiquidityPoolDepositResult)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s TimeBounds) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s LiquidityPoolDepositResult) xdrType() {} -var _ xdrType = (*TimeBounds)(nil) +var _ xdrType = (*LiquidityPoolDepositResult)(nil) -// LedgerBounds is an XDR Struct defines as: +// LiquidityPoolWithdrawResultCode is an XDR Enum defines as: // -// struct LedgerBounds +// enum LiquidityPoolWithdrawResultCode // { -// uint32 minLedger; -// uint32 maxLedger; // 0 here means no maxLedger +// // codes considered as "success" for the operation +// LIQUIDITY_POOL_WITHDRAW_SUCCESS = 0, +// +// // codes considered as "failure" for the operation +// LIQUIDITY_POOL_WITHDRAW_MALFORMED = -1, // bad input +// LIQUIDITY_POOL_WITHDRAW_NO_TRUST = -2, // no trust line for one of the +// // assets +// LIQUIDITY_POOL_WITHDRAW_UNDERFUNDED = -3, // not enough balance of the +// // pool share +// LIQUIDITY_POOL_WITHDRAW_LINE_FULL = -4, // would go above limit for one +// // of the assets +// LIQUIDITY_POOL_WITHDRAW_UNDER_MINIMUM = -5 // didn't withdraw enough // }; -type LedgerBounds struct { - MinLedger Uint32 - MaxLedger Uint32 +type LiquidityPoolWithdrawResultCode int32 + +const ( + LiquidityPoolWithdrawResultCodeLiquidityPoolWithdrawSuccess LiquidityPoolWithdrawResultCode = 0 + LiquidityPoolWithdrawResultCodeLiquidityPoolWithdrawMalformed LiquidityPoolWithdrawResultCode = -1 + LiquidityPoolWithdrawResultCodeLiquidityPoolWithdrawNoTrust LiquidityPoolWithdrawResultCode = -2 + LiquidityPoolWithdrawResultCodeLiquidityPoolWithdrawUnderfunded LiquidityPoolWithdrawResultCode = -3 + LiquidityPoolWithdrawResultCodeLiquidityPoolWithdrawLineFull LiquidityPoolWithdrawResultCode = -4 + LiquidityPoolWithdrawResultCodeLiquidityPoolWithdrawUnderMinimum LiquidityPoolWithdrawResultCode = -5 +) + +var liquidityPoolWithdrawResultCodeMap = map[int32]string{ + 0: "LiquidityPoolWithdrawResultCodeLiquidityPoolWithdrawSuccess", + -1: "LiquidityPoolWithdrawResultCodeLiquidityPoolWithdrawMalformed", + -2: "LiquidityPoolWithdrawResultCodeLiquidityPoolWithdrawNoTrust", + -3: "LiquidityPoolWithdrawResultCodeLiquidityPoolWithdrawUnderfunded", + -4: "LiquidityPoolWithdrawResultCodeLiquidityPoolWithdrawLineFull", + -5: "LiquidityPoolWithdrawResultCodeLiquidityPoolWithdrawUnderMinimum", +} + +// ValidEnum validates a proposed value for this enum. Implements +// the Enum interface for LiquidityPoolWithdrawResultCode +func (e LiquidityPoolWithdrawResultCode) ValidEnum(v int32) bool { + _, ok := liquidityPoolWithdrawResultCodeMap[v] + return ok +} + +// String returns the name of `e` +func (e LiquidityPoolWithdrawResultCode) String() string { + name, _ := liquidityPoolWithdrawResultCodeMap[int32(e)] + return name } // EncodeTo encodes this value using the Encoder. -func (s *LedgerBounds) EncodeTo(e *xdr.Encoder) error { - var err error - if err = s.MinLedger.EncodeTo(e); err != nil { - return err - } - if err = s.MaxLedger.EncodeTo(e); err != nil { - return err +func (e LiquidityPoolWithdrawResultCode) EncodeTo(enc *xdr.Encoder) error { + if _, ok := liquidityPoolWithdrawResultCodeMap[int32(e)]; !ok { + return fmt.Errorf("'%d' is not a valid LiquidityPoolWithdrawResultCode enum value", e) } - return nil + _, err := enc.EncodeInt(int32(e)) + return err } -var _ decoderFrom = (*LedgerBounds)(nil) +var _ decoderFrom = (*LiquidityPoolWithdrawResultCode)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *LedgerBounds) DecodeFrom(d *xdr.Decoder) (int, error) { - var err error - var n, nTmp int - nTmp, err = s.MinLedger.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Uint32: %s", err) +func (e *LiquidityPoolWithdrawResultCode) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding LiquidityPoolWithdrawResultCode: %w", ErrMaxDecodingDepthReached) } - nTmp, err = s.MaxLedger.DecodeFrom(d) - n += nTmp + maxDepth -= 1 + v, n, err := d.DecodeInt() if err != nil { - return n, fmt.Errorf("decoding Uint32: %s", err) + return n, fmt.Errorf("decoding LiquidityPoolWithdrawResultCode: %w", err) + } + if _, ok := liquidityPoolWithdrawResultCodeMap[v]; !ok { + return n, fmt.Errorf("'%d' is not a valid LiquidityPoolWithdrawResultCode enum value", v) } + *e = LiquidityPoolWithdrawResultCode(v) return n, nil } // MarshalBinary implements encoding.BinaryMarshaler. -func (s LedgerBounds) MarshalBinary() ([]byte, error) { +func (s LiquidityPoolWithdrawResultCode) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -23459,195 +40438,157 @@ func (s LedgerBounds) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *LedgerBounds) UnmarshalBinary(inp []byte) error { +func (s *LiquidityPoolWithdrawResultCode) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*LedgerBounds)(nil) - _ encoding.BinaryUnmarshaler = (*LedgerBounds)(nil) + _ encoding.BinaryMarshaler = (*LiquidityPoolWithdrawResultCode)(nil) + _ encoding.BinaryUnmarshaler = (*LiquidityPoolWithdrawResultCode)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s LedgerBounds) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s LiquidityPoolWithdrawResultCode) xdrType() {} -var _ xdrType = (*LedgerBounds)(nil) +var _ xdrType = (*LiquidityPoolWithdrawResultCode)(nil) -// PreconditionsV2 is an XDR Struct defines as: +// LiquidityPoolWithdrawResult is an XDR Union defines as: // -// struct PreconditionsV2 +// union LiquidityPoolWithdrawResult switch (LiquidityPoolWithdrawResultCode code) // { -// TimeBounds* timeBounds; -// -// // Transaction only valid for ledger numbers n such that -// // minLedger <= n < maxLedger (if maxLedger == 0, then -// // only minLedger is checked) -// LedgerBounds* ledgerBounds; -// -// // If NULL, only valid when sourceAccount's sequence number -// // is seqNum - 1. Otherwise, valid when sourceAccount's -// // sequence number n satisfies minSeqNum <= n < tx.seqNum. -// // Note that after execution the account's sequence number -// // is always raised to tx.seqNum, and a transaction is not -// // valid if tx.seqNum is too high to ensure replay protection. -// SequenceNumber* minSeqNum; -// -// // For the transaction to be valid, the current ledger time must -// // be at least minSeqAge greater than sourceAccount's seqTime. -// Duration minSeqAge; -// -// // For the transaction to be valid, the current ledger number -// // must be at least minSeqLedgerGap greater than sourceAccount's -// // seqLedger. -// uint32 minSeqLedgerGap; -// -// // For the transaction to be valid, there must be a signature -// // corresponding to every Signer in this array, even if the -// // signature is not otherwise required by the sourceAccount or -// // operations. -// SignerKey extraSigners<2>; +// case LIQUIDITY_POOL_WITHDRAW_SUCCESS: +// void; +// case LIQUIDITY_POOL_WITHDRAW_MALFORMED: +// case LIQUIDITY_POOL_WITHDRAW_NO_TRUST: +// case LIQUIDITY_POOL_WITHDRAW_UNDERFUNDED: +// case LIQUIDITY_POOL_WITHDRAW_LINE_FULL: +// case LIQUIDITY_POOL_WITHDRAW_UNDER_MINIMUM: +// void; // }; -type PreconditionsV2 struct { - TimeBounds *TimeBounds - LedgerBounds *LedgerBounds - MinSeqNum *SequenceNumber - MinSeqAge Duration - MinSeqLedgerGap Uint32 - ExtraSigners []SignerKey `xdrmaxsize:"2"` +type LiquidityPoolWithdrawResult struct { + Code LiquidityPoolWithdrawResultCode } -// EncodeTo encodes this value using the Encoder. -func (s *PreconditionsV2) EncodeTo(e *xdr.Encoder) error { - var err error - if _, err = e.EncodeBool(s.TimeBounds != nil); err != nil { - return err - } - if s.TimeBounds != nil { - if err = (*s.TimeBounds).EncodeTo(e); err != nil { - return err - } - } - if _, err = e.EncodeBool(s.LedgerBounds != nil); err != nil { - return err - } - if s.LedgerBounds != nil { - if err = (*s.LedgerBounds).EncodeTo(e); err != nil { - return err - } - } - if _, err = e.EncodeBool(s.MinSeqNum != nil); err != nil { - return err - } - if s.MinSeqNum != nil { - if err = (*s.MinSeqNum).EncodeTo(e); err != nil { - return err - } - } - if err = s.MinSeqAge.EncodeTo(e); err != nil { - return err +// SwitchFieldName returns the field name in which this union's +// discriminant is stored +func (u LiquidityPoolWithdrawResult) SwitchFieldName() string { + return "Code" +} + +// ArmForSwitch returns which field name should be used for storing +// the value for an instance of LiquidityPoolWithdrawResult +func (u LiquidityPoolWithdrawResult) ArmForSwitch(sw int32) (string, bool) { + switch LiquidityPoolWithdrawResultCode(sw) { + case LiquidityPoolWithdrawResultCodeLiquidityPoolWithdrawSuccess: + return "", true + case LiquidityPoolWithdrawResultCodeLiquidityPoolWithdrawMalformed: + return "", true + case LiquidityPoolWithdrawResultCodeLiquidityPoolWithdrawNoTrust: + return "", true + case LiquidityPoolWithdrawResultCodeLiquidityPoolWithdrawUnderfunded: + return "", true + case LiquidityPoolWithdrawResultCodeLiquidityPoolWithdrawLineFull: + return "", true + case LiquidityPoolWithdrawResultCodeLiquidityPoolWithdrawUnderMinimum: + return "", true } - if err = s.MinSeqLedgerGap.EncodeTo(e); err != nil { - return err + return "-", false +} + +// NewLiquidityPoolWithdrawResult creates a new LiquidityPoolWithdrawResult. +func NewLiquidityPoolWithdrawResult(code LiquidityPoolWithdrawResultCode, value interface{}) (result LiquidityPoolWithdrawResult, err error) { + result.Code = code + switch LiquidityPoolWithdrawResultCode(code) { + case LiquidityPoolWithdrawResultCodeLiquidityPoolWithdrawSuccess: + // void + case LiquidityPoolWithdrawResultCodeLiquidityPoolWithdrawMalformed: + // void + case LiquidityPoolWithdrawResultCodeLiquidityPoolWithdrawNoTrust: + // void + case LiquidityPoolWithdrawResultCodeLiquidityPoolWithdrawUnderfunded: + // void + case LiquidityPoolWithdrawResultCodeLiquidityPoolWithdrawLineFull: + // void + case LiquidityPoolWithdrawResultCodeLiquidityPoolWithdrawUnderMinimum: + // void } - if _, err = e.EncodeUint(uint32(len(s.ExtraSigners))); err != nil { + return +} + +// EncodeTo encodes this value using the Encoder. +func (u LiquidityPoolWithdrawResult) EncodeTo(e *xdr.Encoder) error { + var err error + if err = u.Code.EncodeTo(e); err != nil { return err } - for i := 0; i < len(s.ExtraSigners); i++ { - if err = s.ExtraSigners[i].EncodeTo(e); err != nil { - return err - } + switch LiquidityPoolWithdrawResultCode(u.Code) { + case LiquidityPoolWithdrawResultCodeLiquidityPoolWithdrawSuccess: + // Void + return nil + case LiquidityPoolWithdrawResultCodeLiquidityPoolWithdrawMalformed: + // Void + return nil + case LiquidityPoolWithdrawResultCodeLiquidityPoolWithdrawNoTrust: + // Void + return nil + case LiquidityPoolWithdrawResultCodeLiquidityPoolWithdrawUnderfunded: + // Void + return nil + case LiquidityPoolWithdrawResultCodeLiquidityPoolWithdrawLineFull: + // Void + return nil + case LiquidityPoolWithdrawResultCodeLiquidityPoolWithdrawUnderMinimum: + // Void + return nil } - return nil + return fmt.Errorf("Code (LiquidityPoolWithdrawResultCode) switch value '%d' is not valid for union LiquidityPoolWithdrawResult", u.Code) } -var _ decoderFrom = (*PreconditionsV2)(nil) +var _ decoderFrom = (*LiquidityPoolWithdrawResult)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *PreconditionsV2) DecodeFrom(d *xdr.Decoder) (int, error) { +func (u *LiquidityPoolWithdrawResult) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding LiquidityPoolWithdrawResult: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - var b bool - b, nTmp, err = d.DecodeBool() - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding TimeBounds: %s", err) - } - s.TimeBounds = nil - if b { - s.TimeBounds = new(TimeBounds) - nTmp, err = s.TimeBounds.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding TimeBounds: %s", err) - } - } - b, nTmp, err = d.DecodeBool() - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding LedgerBounds: %s", err) - } - s.LedgerBounds = nil - if b { - s.LedgerBounds = new(LedgerBounds) - nTmp, err = s.LedgerBounds.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding LedgerBounds: %s", err) - } - } - b, nTmp, err = d.DecodeBool() - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding SequenceNumber: %s", err) - } - s.MinSeqNum = nil - if b { - s.MinSeqNum = new(SequenceNumber) - nTmp, err = s.MinSeqNum.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding SequenceNumber: %s", err) - } - } - nTmp, err = s.MinSeqAge.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Duration: %s", err) - } - nTmp, err = s.MinSeqLedgerGap.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Uint32: %s", err) - } - var l uint32 - l, nTmp, err = d.DecodeUint() + nTmp, err = u.Code.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding SignerKey: %s", err) - } - if l > 2 { - return n, fmt.Errorf("decoding SignerKey: data size (%d) exceeds size limit (2)", l) + return n, fmt.Errorf("decoding LiquidityPoolWithdrawResultCode: %w", err) } - s.ExtraSigners = nil - if l > 0 { - s.ExtraSigners = make([]SignerKey, l) - for i := uint32(0); i < l; i++ { - nTmp, err = s.ExtraSigners[i].DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding SignerKey: %s", err) - } - } + switch LiquidityPoolWithdrawResultCode(u.Code) { + case LiquidityPoolWithdrawResultCodeLiquidityPoolWithdrawSuccess: + // Void + return n, nil + case LiquidityPoolWithdrawResultCodeLiquidityPoolWithdrawMalformed: + // Void + return n, nil + case LiquidityPoolWithdrawResultCodeLiquidityPoolWithdrawNoTrust: + // Void + return n, nil + case LiquidityPoolWithdrawResultCodeLiquidityPoolWithdrawUnderfunded: + // Void + return n, nil + case LiquidityPoolWithdrawResultCodeLiquidityPoolWithdrawLineFull: + // Void + return n, nil + case LiquidityPoolWithdrawResultCodeLiquidityPoolWithdrawUnderMinimum: + // Void + return n, nil } - return n, nil + return n, fmt.Errorf("union LiquidityPoolWithdrawResult has invalid Code (LiquidityPoolWithdrawResultCode) switch value '%d'", u.Code) } // MarshalBinary implements encoding.BinaryMarshaler. -func (s PreconditionsV2) MarshalBinary() ([]byte, error) { +func (s LiquidityPoolWithdrawResult) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -23655,85 +40596,102 @@ func (s PreconditionsV2) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *PreconditionsV2) UnmarshalBinary(inp []byte) error { +func (s *LiquidityPoolWithdrawResult) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*PreconditionsV2)(nil) - _ encoding.BinaryUnmarshaler = (*PreconditionsV2)(nil) + _ encoding.BinaryMarshaler = (*LiquidityPoolWithdrawResult)(nil) + _ encoding.BinaryUnmarshaler = (*LiquidityPoolWithdrawResult)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s PreconditionsV2) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s LiquidityPoolWithdrawResult) xdrType() {} -var _ xdrType = (*PreconditionsV2)(nil) +var _ xdrType = (*LiquidityPoolWithdrawResult)(nil) -// PreconditionType is an XDR Enum defines as: +// InvokeHostFunctionResultCode is an XDR Enum defines as: // -// enum PreconditionType +// enum InvokeHostFunctionResultCode // { -// PRECOND_NONE = 0, -// PRECOND_TIME = 1, -// PRECOND_V2 = 2 +// // codes considered as "success" for the operation +// INVOKE_HOST_FUNCTION_SUCCESS = 0, +// +// // codes considered as "failure" for the operation +// INVOKE_HOST_FUNCTION_MALFORMED = -1, +// INVOKE_HOST_FUNCTION_TRAPPED = -2, +// INVOKE_HOST_FUNCTION_RESOURCE_LIMIT_EXCEEDED = -3, +// INVOKE_HOST_FUNCTION_ENTRY_ARCHIVED = -4, +// INVOKE_HOST_FUNCTION_INSUFFICIENT_REFUNDABLE_FEE = -5 // }; -type PreconditionType int32 +type InvokeHostFunctionResultCode int32 const ( - PreconditionTypePrecondNone PreconditionType = 0 - PreconditionTypePrecondTime PreconditionType = 1 - PreconditionTypePrecondV2 PreconditionType = 2 + InvokeHostFunctionResultCodeInvokeHostFunctionSuccess InvokeHostFunctionResultCode = 0 + InvokeHostFunctionResultCodeInvokeHostFunctionMalformed InvokeHostFunctionResultCode = -1 + InvokeHostFunctionResultCodeInvokeHostFunctionTrapped InvokeHostFunctionResultCode = -2 + InvokeHostFunctionResultCodeInvokeHostFunctionResourceLimitExceeded InvokeHostFunctionResultCode = -3 + InvokeHostFunctionResultCodeInvokeHostFunctionEntryArchived InvokeHostFunctionResultCode = -4 + InvokeHostFunctionResultCodeInvokeHostFunctionInsufficientRefundableFee InvokeHostFunctionResultCode = -5 ) -var preconditionTypeMap = map[int32]string{ - 0: "PreconditionTypePrecondNone", - 1: "PreconditionTypePrecondTime", - 2: "PreconditionTypePrecondV2", +var invokeHostFunctionResultCodeMap = map[int32]string{ + 0: "InvokeHostFunctionResultCodeInvokeHostFunctionSuccess", + -1: "InvokeHostFunctionResultCodeInvokeHostFunctionMalformed", + -2: "InvokeHostFunctionResultCodeInvokeHostFunctionTrapped", + -3: "InvokeHostFunctionResultCodeInvokeHostFunctionResourceLimitExceeded", + -4: "InvokeHostFunctionResultCodeInvokeHostFunctionEntryArchived", + -5: "InvokeHostFunctionResultCodeInvokeHostFunctionInsufficientRefundableFee", } // ValidEnum validates a proposed value for this enum. Implements -// the Enum interface for PreconditionType -func (e PreconditionType) ValidEnum(v int32) bool { - _, ok := preconditionTypeMap[v] +// the Enum interface for InvokeHostFunctionResultCode +func (e InvokeHostFunctionResultCode) ValidEnum(v int32) bool { + _, ok := invokeHostFunctionResultCodeMap[v] return ok } // String returns the name of `e` -func (e PreconditionType) String() string { - name, _ := preconditionTypeMap[int32(e)] +func (e InvokeHostFunctionResultCode) String() string { + name, _ := invokeHostFunctionResultCodeMap[int32(e)] return name } // EncodeTo encodes this value using the Encoder. -func (e PreconditionType) EncodeTo(enc *xdr.Encoder) error { - if _, ok := preconditionTypeMap[int32(e)]; !ok { - return fmt.Errorf("'%d' is not a valid PreconditionType enum value", e) +func (e InvokeHostFunctionResultCode) EncodeTo(enc *xdr.Encoder) error { + if _, ok := invokeHostFunctionResultCodeMap[int32(e)]; !ok { + return fmt.Errorf("'%d' is not a valid InvokeHostFunctionResultCode enum value", e) } _, err := enc.EncodeInt(int32(e)) return err } -var _ decoderFrom = (*PreconditionType)(nil) +var _ decoderFrom = (*InvokeHostFunctionResultCode)(nil) // DecodeFrom decodes this value using the Decoder. -func (e *PreconditionType) DecodeFrom(d *xdr.Decoder) (int, error) { +func (e *InvokeHostFunctionResultCode) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding InvokeHostFunctionResultCode: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 v, n, err := d.DecodeInt() if err != nil { - return n, fmt.Errorf("decoding PreconditionType: %s", err) + return n, fmt.Errorf("decoding InvokeHostFunctionResultCode: %w", err) } - if _, ok := preconditionTypeMap[v]; !ok { - return n, fmt.Errorf("'%d' is not a valid PreconditionType enum value", v) + if _, ok := invokeHostFunctionResultCodeMap[v]; !ok { + return n, fmt.Errorf("'%d' is not a valid InvokeHostFunctionResultCode enum value", v) } - *e = PreconditionType(v) + *e = InvokeHostFunctionResultCode(v) return n, nil } // MarshalBinary implements encoding.BinaryMarshaler. -func (s PreconditionType) MarshalBinary() ([]byte, error) { +func (s InvokeHostFunctionResultCode) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -23741,129 +40699,113 @@ func (s PreconditionType) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *PreconditionType) UnmarshalBinary(inp []byte) error { +func (s *InvokeHostFunctionResultCode) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*PreconditionType)(nil) - _ encoding.BinaryUnmarshaler = (*PreconditionType)(nil) + _ encoding.BinaryMarshaler = (*InvokeHostFunctionResultCode)(nil) + _ encoding.BinaryUnmarshaler = (*InvokeHostFunctionResultCode)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s PreconditionType) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s InvokeHostFunctionResultCode) xdrType() {} -var _ xdrType = (*PreconditionType)(nil) +var _ xdrType = (*InvokeHostFunctionResultCode)(nil) -// Preconditions is an XDR Union defines as: +// InvokeHostFunctionResult is an XDR Union defines as: // -// union Preconditions switch (PreconditionType type) +// union InvokeHostFunctionResult switch (InvokeHostFunctionResultCode code) // { -// case PRECOND_NONE: +// case INVOKE_HOST_FUNCTION_SUCCESS: +// Hash success; // sha256(InvokeHostFunctionSuccessPreImage) +// case INVOKE_HOST_FUNCTION_MALFORMED: +// case INVOKE_HOST_FUNCTION_TRAPPED: +// case INVOKE_HOST_FUNCTION_RESOURCE_LIMIT_EXCEEDED: +// case INVOKE_HOST_FUNCTION_ENTRY_ARCHIVED: +// case INVOKE_HOST_FUNCTION_INSUFFICIENT_REFUNDABLE_FEE: // void; -// case PRECOND_TIME: -// TimeBounds timeBounds; -// case PRECOND_V2: -// PreconditionsV2 v2; // }; -type Preconditions struct { - Type PreconditionType - TimeBounds *TimeBounds - V2 *PreconditionsV2 +type InvokeHostFunctionResult struct { + Code InvokeHostFunctionResultCode + Success *Hash } // SwitchFieldName returns the field name in which this union's // discriminant is stored -func (u Preconditions) SwitchFieldName() string { - return "Type" +func (u InvokeHostFunctionResult) SwitchFieldName() string { + return "Code" } // ArmForSwitch returns which field name should be used for storing -// the value for an instance of Preconditions -func (u Preconditions) ArmForSwitch(sw int32) (string, bool) { - switch PreconditionType(sw) { - case PreconditionTypePrecondNone: +// the value for an instance of InvokeHostFunctionResult +func (u InvokeHostFunctionResult) ArmForSwitch(sw int32) (string, bool) { + switch InvokeHostFunctionResultCode(sw) { + case InvokeHostFunctionResultCodeInvokeHostFunctionSuccess: + return "Success", true + case InvokeHostFunctionResultCodeInvokeHostFunctionMalformed: + return "", true + case InvokeHostFunctionResultCodeInvokeHostFunctionTrapped: + return "", true + case InvokeHostFunctionResultCodeInvokeHostFunctionResourceLimitExceeded: + return "", true + case InvokeHostFunctionResultCodeInvokeHostFunctionEntryArchived: + return "", true + case InvokeHostFunctionResultCodeInvokeHostFunctionInsufficientRefundableFee: return "", true - case PreconditionTypePrecondTime: - return "TimeBounds", true - case PreconditionTypePrecondV2: - return "V2", true } return "-", false } -// NewPreconditions creates a new Preconditions. -func NewPreconditions(aType PreconditionType, value interface{}) (result Preconditions, err error) { - result.Type = aType - switch PreconditionType(aType) { - case PreconditionTypePrecondNone: - // void - case PreconditionTypePrecondTime: - tv, ok := value.(TimeBounds) - if !ok { - err = fmt.Errorf("invalid value, must be TimeBounds") - return - } - result.TimeBounds = &tv - case PreconditionTypePrecondV2: - tv, ok := value.(PreconditionsV2) +// NewInvokeHostFunctionResult creates a new InvokeHostFunctionResult. +func NewInvokeHostFunctionResult(code InvokeHostFunctionResultCode, value interface{}) (result InvokeHostFunctionResult, err error) { + result.Code = code + switch InvokeHostFunctionResultCode(code) { + case InvokeHostFunctionResultCodeInvokeHostFunctionSuccess: + tv, ok := value.(Hash) if !ok { - err = fmt.Errorf("invalid value, must be PreconditionsV2") + err = errors.New("invalid value, must be Hash") return } - result.V2 = &tv - } - return -} - -// MustTimeBounds retrieves the TimeBounds value from the union, -// panicing if the value is not set. -func (u Preconditions) MustTimeBounds() TimeBounds { - val, ok := u.GetTimeBounds() - - if !ok { - panic("arm TimeBounds is not set") - } - - return val -} - -// GetTimeBounds retrieves the TimeBounds value from the union, -// returning ok if the union's switch indicated the value is valid. -func (u Preconditions) GetTimeBounds() (result TimeBounds, ok bool) { - armName, _ := u.ArmForSwitch(int32(u.Type)) - - if armName == "TimeBounds" { - result = *u.TimeBounds - ok = true + result.Success = &tv + case InvokeHostFunctionResultCodeInvokeHostFunctionMalformed: + // void + case InvokeHostFunctionResultCodeInvokeHostFunctionTrapped: + // void + case InvokeHostFunctionResultCodeInvokeHostFunctionResourceLimitExceeded: + // void + case InvokeHostFunctionResultCodeInvokeHostFunctionEntryArchived: + // void + case InvokeHostFunctionResultCodeInvokeHostFunctionInsufficientRefundableFee: + // void } - return } -// MustV2 retrieves the V2 value from the union, +// MustSuccess retrieves the Success value from the union, // panicing if the value is not set. -func (u Preconditions) MustV2() PreconditionsV2 { - val, ok := u.GetV2() +func (u InvokeHostFunctionResult) MustSuccess() Hash { + val, ok := u.GetSuccess() if !ok { - panic("arm V2 is not set") + panic("arm Success is not set") } return val } -// GetV2 retrieves the V2 value from the union, +// GetSuccess retrieves the Success value from the union, // returning ok if the union's switch indicated the value is valid. -func (u Preconditions) GetV2() (result PreconditionsV2, ok bool) { - armName, _ := u.ArmForSwitch(int32(u.Type)) +func (u InvokeHostFunctionResult) GetSuccess() (result Hash, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Code)) - if armName == "V2" { - result = *u.V2 + if armName == "Success" { + result = *u.Success ok = true } @@ -23871,66 +40813,81 @@ func (u Preconditions) GetV2() (result PreconditionsV2, ok bool) { } // EncodeTo encodes this value using the Encoder. -func (u Preconditions) EncodeTo(e *xdr.Encoder) error { +func (u InvokeHostFunctionResult) EncodeTo(e *xdr.Encoder) error { var err error - if err = u.Type.EncodeTo(e); err != nil { + if err = u.Code.EncodeTo(e); err != nil { return err } - switch PreconditionType(u.Type) { - case PreconditionTypePrecondNone: - // Void - return nil - case PreconditionTypePrecondTime: - if err = (*u.TimeBounds).EncodeTo(e); err != nil { + switch InvokeHostFunctionResultCode(u.Code) { + case InvokeHostFunctionResultCodeInvokeHostFunctionSuccess: + if err = (*u.Success).EncodeTo(e); err != nil { return err } return nil - case PreconditionTypePrecondV2: - if err = (*u.V2).EncodeTo(e); err != nil { - return err - } + case InvokeHostFunctionResultCodeInvokeHostFunctionMalformed: + // Void + return nil + case InvokeHostFunctionResultCodeInvokeHostFunctionTrapped: + // Void + return nil + case InvokeHostFunctionResultCodeInvokeHostFunctionResourceLimitExceeded: + // Void + return nil + case InvokeHostFunctionResultCodeInvokeHostFunctionEntryArchived: + // Void + return nil + case InvokeHostFunctionResultCodeInvokeHostFunctionInsufficientRefundableFee: + // Void return nil } - return fmt.Errorf("Type (PreconditionType) switch value '%d' is not valid for union Preconditions", u.Type) + return fmt.Errorf("Code (InvokeHostFunctionResultCode) switch value '%d' is not valid for union InvokeHostFunctionResult", u.Code) } -var _ decoderFrom = (*Preconditions)(nil) +var _ decoderFrom = (*InvokeHostFunctionResult)(nil) // DecodeFrom decodes this value using the Decoder. -func (u *Preconditions) DecodeFrom(d *xdr.Decoder) (int, error) { +func (u *InvokeHostFunctionResult) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding InvokeHostFunctionResult: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = u.Type.DecodeFrom(d) + nTmp, err = u.Code.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding PreconditionType: %s", err) + return n, fmt.Errorf("decoding InvokeHostFunctionResultCode: %w", err) } - switch PreconditionType(u.Type) { - case PreconditionTypePrecondNone: - // Void - return n, nil - case PreconditionTypePrecondTime: - u.TimeBounds = new(TimeBounds) - nTmp, err = (*u.TimeBounds).DecodeFrom(d) + switch InvokeHostFunctionResultCode(u.Code) { + case InvokeHostFunctionResultCodeInvokeHostFunctionSuccess: + u.Success = new(Hash) + nTmp, err = (*u.Success).DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding TimeBounds: %s", err) + return n, fmt.Errorf("decoding Hash: %w", err) } return n, nil - case PreconditionTypePrecondV2: - u.V2 = new(PreconditionsV2) - nTmp, err = (*u.V2).DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding PreconditionsV2: %s", err) - } + case InvokeHostFunctionResultCodeInvokeHostFunctionMalformed: + // Void + return n, nil + case InvokeHostFunctionResultCodeInvokeHostFunctionTrapped: + // Void + return n, nil + case InvokeHostFunctionResultCodeInvokeHostFunctionResourceLimitExceeded: + // Void + return n, nil + case InvokeHostFunctionResultCodeInvokeHostFunctionEntryArchived: + // Void + return n, nil + case InvokeHostFunctionResultCodeInvokeHostFunctionInsufficientRefundableFee: + // Void return n, nil } - return n, fmt.Errorf("union Preconditions has invalid Type (PreconditionType) switch value '%d'", u.Type) + return n, fmt.Errorf("union InvokeHostFunctionResult has invalid Code (InvokeHostFunctionResultCode) switch value '%d'", u.Code) } // MarshalBinary implements encoding.BinaryMarshaler. -func (s Preconditions) MarshalBinary() ([]byte, error) { +func (s InvokeHostFunctionResult) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -23938,101 +40895,96 @@ func (s Preconditions) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *Preconditions) UnmarshalBinary(inp []byte) error { +func (s *InvokeHostFunctionResult) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*Preconditions)(nil) - _ encoding.BinaryUnmarshaler = (*Preconditions)(nil) + _ encoding.BinaryMarshaler = (*InvokeHostFunctionResult)(nil) + _ encoding.BinaryUnmarshaler = (*InvokeHostFunctionResult)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s Preconditions) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s InvokeHostFunctionResult) xdrType() {} -var _ xdrType = (*Preconditions)(nil) +var _ xdrType = (*InvokeHostFunctionResult)(nil) -// MaxOpsPerTx is an XDR Const defines as: +// ExtendFootprintTtlResultCode is an XDR Enum defines as: // -// const MAX_OPS_PER_TX = 100; -const MaxOpsPerTx = 100 - -// TransactionV0Ext is an XDR NestedUnion defines as: +// enum ExtendFootprintTTLResultCode +// { +// // codes considered as "success" for the operation +// EXTEND_FOOTPRINT_TTL_SUCCESS = 0, // -// union switch (int v) -// { -// case 0: -// void; -// } -type TransactionV0Ext struct { - V int32 -} +// // codes considered as "failure" for the operation +// EXTEND_FOOTPRINT_TTL_MALFORMED = -1, +// EXTEND_FOOTPRINT_TTL_RESOURCE_LIMIT_EXCEEDED = -2, +// EXTEND_FOOTPRINT_TTL_INSUFFICIENT_REFUNDABLE_FEE = -3 +// }; +type ExtendFootprintTtlResultCode int32 -// SwitchFieldName returns the field name in which this union's -// discriminant is stored -func (u TransactionV0Ext) SwitchFieldName() string { - return "V" +const ( + ExtendFootprintTtlResultCodeExtendFootprintTtlSuccess ExtendFootprintTtlResultCode = 0 + ExtendFootprintTtlResultCodeExtendFootprintTtlMalformed ExtendFootprintTtlResultCode = -1 + ExtendFootprintTtlResultCodeExtendFootprintTtlResourceLimitExceeded ExtendFootprintTtlResultCode = -2 + ExtendFootprintTtlResultCodeExtendFootprintTtlInsufficientRefundableFee ExtendFootprintTtlResultCode = -3 +) + +var extendFootprintTtlResultCodeMap = map[int32]string{ + 0: "ExtendFootprintTtlResultCodeExtendFootprintTtlSuccess", + -1: "ExtendFootprintTtlResultCodeExtendFootprintTtlMalformed", + -2: "ExtendFootprintTtlResultCodeExtendFootprintTtlResourceLimitExceeded", + -3: "ExtendFootprintTtlResultCodeExtendFootprintTtlInsufficientRefundableFee", } -// ArmForSwitch returns which field name should be used for storing -// the value for an instance of TransactionV0Ext -func (u TransactionV0Ext) ArmForSwitch(sw int32) (string, bool) { - switch int32(sw) { - case 0: - return "", true - } - return "-", false +// ValidEnum validates a proposed value for this enum. Implements +// the Enum interface for ExtendFootprintTtlResultCode +func (e ExtendFootprintTtlResultCode) ValidEnum(v int32) bool { + _, ok := extendFootprintTtlResultCodeMap[v] + return ok } -// NewTransactionV0Ext creates a new TransactionV0Ext. -func NewTransactionV0Ext(v int32, value interface{}) (result TransactionV0Ext, err error) { - result.V = v - switch int32(v) { - case 0: - // void - } - return +// String returns the name of `e` +func (e ExtendFootprintTtlResultCode) String() string { + name, _ := extendFootprintTtlResultCodeMap[int32(e)] + return name } // EncodeTo encodes this value using the Encoder. -func (u TransactionV0Ext) EncodeTo(e *xdr.Encoder) error { - var err error - if _, err = e.EncodeInt(int32(u.V)); err != nil { - return err +func (e ExtendFootprintTtlResultCode) EncodeTo(enc *xdr.Encoder) error { + if _, ok := extendFootprintTtlResultCodeMap[int32(e)]; !ok { + return fmt.Errorf("'%d' is not a valid ExtendFootprintTtlResultCode enum value", e) } - switch int32(u.V) { - case 0: - // Void - return nil - } - return fmt.Errorf("V (int32) switch value '%d' is not valid for union TransactionV0Ext", u.V) + _, err := enc.EncodeInt(int32(e)) + return err } -var _ decoderFrom = (*TransactionV0Ext)(nil) +var _ decoderFrom = (*ExtendFootprintTtlResultCode)(nil) // DecodeFrom decodes this value using the Decoder. -func (u *TransactionV0Ext) DecodeFrom(d *xdr.Decoder) (int, error) { - var err error - var n, nTmp int - u.V, nTmp, err = d.DecodeInt() - n += nTmp +func (e *ExtendFootprintTtlResultCode) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding ExtendFootprintTtlResultCode: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + v, n, err := d.DecodeInt() if err != nil { - return n, fmt.Errorf("decoding Int: %s", err) + return n, fmt.Errorf("decoding ExtendFootprintTtlResultCode: %w", err) } - switch int32(u.V) { - case 0: - // Void - return n, nil + if _, ok := extendFootprintTtlResultCodeMap[v]; !ok { + return n, fmt.Errorf("'%d' is not a valid ExtendFootprintTtlResultCode enum value", v) } - return n, fmt.Errorf("union TransactionV0Ext has invalid V (int32) switch value '%d'", u.V) + *e = ExtendFootprintTtlResultCode(v) + return n, nil } // MarshalBinary implements encoding.BinaryMarshaler. -func (s TransactionV0Ext) MarshalBinary() ([]byte, error) { +func (s ExtendFootprintTtlResultCode) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -24040,159 +40992,135 @@ func (s TransactionV0Ext) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *TransactionV0Ext) UnmarshalBinary(inp []byte) error { +func (s *ExtendFootprintTtlResultCode) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*TransactionV0Ext)(nil) - _ encoding.BinaryUnmarshaler = (*TransactionV0Ext)(nil) + _ encoding.BinaryMarshaler = (*ExtendFootprintTtlResultCode)(nil) + _ encoding.BinaryUnmarshaler = (*ExtendFootprintTtlResultCode)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s TransactionV0Ext) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s ExtendFootprintTtlResultCode) xdrType() {} -var _ xdrType = (*TransactionV0Ext)(nil) +var _ xdrType = (*ExtendFootprintTtlResultCode)(nil) -// TransactionV0 is an XDR Struct defines as: +// ExtendFootprintTtlResult is an XDR Union defines as: // -// struct TransactionV0 +// union ExtendFootprintTTLResult switch (ExtendFootprintTTLResultCode code) // { -// uint256 sourceAccountEd25519; -// uint32 fee; -// SequenceNumber seqNum; -// TimeBounds* timeBounds; -// Memo memo; -// Operation operations; -// union switch (int v) -// { -// case 0: -// void; -// } -// ext; +// case EXTEND_FOOTPRINT_TTL_SUCCESS: +// void; +// case EXTEND_FOOTPRINT_TTL_MALFORMED: +// case EXTEND_FOOTPRINT_TTL_RESOURCE_LIMIT_EXCEEDED: +// case EXTEND_FOOTPRINT_TTL_INSUFFICIENT_REFUNDABLE_FEE: +// void; // }; -type TransactionV0 struct { - SourceAccountEd25519 Uint256 - Fee Uint32 - SeqNum SequenceNumber - TimeBounds *TimeBounds - Memo Memo - Operations []Operation `xdrmaxsize:"100"` - Ext TransactionV0Ext +type ExtendFootprintTtlResult struct { + Code ExtendFootprintTtlResultCode } -// EncodeTo encodes this value using the Encoder. -func (s *TransactionV0) EncodeTo(e *xdr.Encoder) error { - var err error - if err = s.SourceAccountEd25519.EncodeTo(e); err != nil { - return err - } - if err = s.Fee.EncodeTo(e); err != nil { - return err - } - if err = s.SeqNum.EncodeTo(e); err != nil { - return err - } - if _, err = e.EncodeBool(s.TimeBounds != nil); err != nil { - return err - } - if s.TimeBounds != nil { - if err = (*s.TimeBounds).EncodeTo(e); err != nil { - return err - } +// SwitchFieldName returns the field name in which this union's +// discriminant is stored +func (u ExtendFootprintTtlResult) SwitchFieldName() string { + return "Code" +} + +// ArmForSwitch returns which field name should be used for storing +// the value for an instance of ExtendFootprintTtlResult +func (u ExtendFootprintTtlResult) ArmForSwitch(sw int32) (string, bool) { + switch ExtendFootprintTtlResultCode(sw) { + case ExtendFootprintTtlResultCodeExtendFootprintTtlSuccess: + return "", true + case ExtendFootprintTtlResultCodeExtendFootprintTtlMalformed: + return "", true + case ExtendFootprintTtlResultCodeExtendFootprintTtlResourceLimitExceeded: + return "", true + case ExtendFootprintTtlResultCodeExtendFootprintTtlInsufficientRefundableFee: + return "", true } - if err = s.Memo.EncodeTo(e); err != nil { - return err + return "-", false +} + +// NewExtendFootprintTtlResult creates a new ExtendFootprintTtlResult. +func NewExtendFootprintTtlResult(code ExtendFootprintTtlResultCode, value interface{}) (result ExtendFootprintTtlResult, err error) { + result.Code = code + switch ExtendFootprintTtlResultCode(code) { + case ExtendFootprintTtlResultCodeExtendFootprintTtlSuccess: + // void + case ExtendFootprintTtlResultCodeExtendFootprintTtlMalformed: + // void + case ExtendFootprintTtlResultCodeExtendFootprintTtlResourceLimitExceeded: + // void + case ExtendFootprintTtlResultCodeExtendFootprintTtlInsufficientRefundableFee: + // void } - if _, err = e.EncodeUint(uint32(len(s.Operations))); err != nil { + return +} + +// EncodeTo encodes this value using the Encoder. +func (u ExtendFootprintTtlResult) EncodeTo(e *xdr.Encoder) error { + var err error + if err = u.Code.EncodeTo(e); err != nil { return err } - for i := 0; i < len(s.Operations); i++ { - if err = s.Operations[i].EncodeTo(e); err != nil { - return err - } - } - if err = s.Ext.EncodeTo(e); err != nil { - return err + switch ExtendFootprintTtlResultCode(u.Code) { + case ExtendFootprintTtlResultCodeExtendFootprintTtlSuccess: + // Void + return nil + case ExtendFootprintTtlResultCodeExtendFootprintTtlMalformed: + // Void + return nil + case ExtendFootprintTtlResultCodeExtendFootprintTtlResourceLimitExceeded: + // Void + return nil + case ExtendFootprintTtlResultCodeExtendFootprintTtlInsufficientRefundableFee: + // Void + return nil } - return nil + return fmt.Errorf("Code (ExtendFootprintTtlResultCode) switch value '%d' is not valid for union ExtendFootprintTtlResult", u.Code) } -var _ decoderFrom = (*TransactionV0)(nil) +var _ decoderFrom = (*ExtendFootprintTtlResult)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *TransactionV0) DecodeFrom(d *xdr.Decoder) (int, error) { +func (u *ExtendFootprintTtlResult) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding ExtendFootprintTtlResult: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = s.SourceAccountEd25519.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Uint256: %s", err) - } - nTmp, err = s.Fee.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Uint32: %s", err) - } - nTmp, err = s.SeqNum.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding SequenceNumber: %s", err) - } - var b bool - b, nTmp, err = d.DecodeBool() - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding TimeBounds: %s", err) - } - s.TimeBounds = nil - if b { - s.TimeBounds = new(TimeBounds) - nTmp, err = s.TimeBounds.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding TimeBounds: %s", err) - } - } - nTmp, err = s.Memo.DecodeFrom(d) + nTmp, err = u.Code.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Memo: %s", err) + return n, fmt.Errorf("decoding ExtendFootprintTtlResultCode: %w", err) } - var l uint32 - l, nTmp, err = d.DecodeUint() - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Operation: %s", err) - } - if l > 100 { - return n, fmt.Errorf("decoding Operation: data size (%d) exceeds size limit (100)", l) - } - s.Operations = nil - if l > 0 { - s.Operations = make([]Operation, l) - for i := uint32(0); i < l; i++ { - nTmp, err = s.Operations[i].DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Operation: %s", err) - } - } - } - nTmp, err = s.Ext.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding TransactionV0Ext: %s", err) + switch ExtendFootprintTtlResultCode(u.Code) { + case ExtendFootprintTtlResultCodeExtendFootprintTtlSuccess: + // Void + return n, nil + case ExtendFootprintTtlResultCodeExtendFootprintTtlMalformed: + // Void + return n, nil + case ExtendFootprintTtlResultCodeExtendFootprintTtlResourceLimitExceeded: + // Void + return n, nil + case ExtendFootprintTtlResultCodeExtendFootprintTtlInsufficientRefundableFee: + // Void + return n, nil } - return n, nil + return n, fmt.Errorf("union ExtendFootprintTtlResult has invalid Code (ExtendFootprintTtlResultCode) switch value '%d'", u.Code) } // MarshalBinary implements encoding.BinaryMarshaler. -func (s TransactionV0) MarshalBinary() ([]byte, error) { +func (s ExtendFootprintTtlResult) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -24200,91 +41128,96 @@ func (s TransactionV0) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *TransactionV0) UnmarshalBinary(inp []byte) error { +func (s *ExtendFootprintTtlResult) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*TransactionV0)(nil) - _ encoding.BinaryUnmarshaler = (*TransactionV0)(nil) + _ encoding.BinaryMarshaler = (*ExtendFootprintTtlResult)(nil) + _ encoding.BinaryUnmarshaler = (*ExtendFootprintTtlResult)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s TransactionV0) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s ExtendFootprintTtlResult) xdrType() {} -var _ xdrType = (*TransactionV0)(nil) +var _ xdrType = (*ExtendFootprintTtlResult)(nil) -// TransactionV0Envelope is an XDR Struct defines as: +// RestoreFootprintResultCode is an XDR Enum defines as: // -// struct TransactionV0Envelope +// enum RestoreFootprintResultCode // { -// TransactionV0 tx; -// /* Each decorated signature is a signature over the SHA256 hash of -// * a TransactionSignaturePayload */ -// DecoratedSignature signatures<20>; +// // codes considered as "success" for the operation +// RESTORE_FOOTPRINT_SUCCESS = 0, +// +// // codes considered as "failure" for the operation +// RESTORE_FOOTPRINT_MALFORMED = -1, +// RESTORE_FOOTPRINT_RESOURCE_LIMIT_EXCEEDED = -2, +// RESTORE_FOOTPRINT_INSUFFICIENT_REFUNDABLE_FEE = -3 // }; -type TransactionV0Envelope struct { - Tx TransactionV0 - Signatures []DecoratedSignature `xdrmaxsize:"20"` +type RestoreFootprintResultCode int32 + +const ( + RestoreFootprintResultCodeRestoreFootprintSuccess RestoreFootprintResultCode = 0 + RestoreFootprintResultCodeRestoreFootprintMalformed RestoreFootprintResultCode = -1 + RestoreFootprintResultCodeRestoreFootprintResourceLimitExceeded RestoreFootprintResultCode = -2 + RestoreFootprintResultCodeRestoreFootprintInsufficientRefundableFee RestoreFootprintResultCode = -3 +) + +var restoreFootprintResultCodeMap = map[int32]string{ + 0: "RestoreFootprintResultCodeRestoreFootprintSuccess", + -1: "RestoreFootprintResultCodeRestoreFootprintMalformed", + -2: "RestoreFootprintResultCodeRestoreFootprintResourceLimitExceeded", + -3: "RestoreFootprintResultCodeRestoreFootprintInsufficientRefundableFee", +} + +// ValidEnum validates a proposed value for this enum. Implements +// the Enum interface for RestoreFootprintResultCode +func (e RestoreFootprintResultCode) ValidEnum(v int32) bool { + _, ok := restoreFootprintResultCodeMap[v] + return ok +} + +// String returns the name of `e` +func (e RestoreFootprintResultCode) String() string { + name, _ := restoreFootprintResultCodeMap[int32(e)] + return name } // EncodeTo encodes this value using the Encoder. -func (s *TransactionV0Envelope) EncodeTo(e *xdr.Encoder) error { - var err error - if err = s.Tx.EncodeTo(e); err != nil { - return err - } - if _, err = e.EncodeUint(uint32(len(s.Signatures))); err != nil { - return err - } - for i := 0; i < len(s.Signatures); i++ { - if err = s.Signatures[i].EncodeTo(e); err != nil { - return err - } +func (e RestoreFootprintResultCode) EncodeTo(enc *xdr.Encoder) error { + if _, ok := restoreFootprintResultCodeMap[int32(e)]; !ok { + return fmt.Errorf("'%d' is not a valid RestoreFootprintResultCode enum value", e) } - return nil + _, err := enc.EncodeInt(int32(e)) + return err } -var _ decoderFrom = (*TransactionV0Envelope)(nil) +var _ decoderFrom = (*RestoreFootprintResultCode)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *TransactionV0Envelope) DecodeFrom(d *xdr.Decoder) (int, error) { - var err error - var n, nTmp int - nTmp, err = s.Tx.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding TransactionV0: %s", err) +func (e *RestoreFootprintResultCode) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding RestoreFootprintResultCode: %w", ErrMaxDecodingDepthReached) } - var l uint32 - l, nTmp, err = d.DecodeUint() - n += nTmp + maxDepth -= 1 + v, n, err := d.DecodeInt() if err != nil { - return n, fmt.Errorf("decoding DecoratedSignature: %s", err) - } - if l > 20 { - return n, fmt.Errorf("decoding DecoratedSignature: data size (%d) exceeds size limit (20)", l) + return n, fmt.Errorf("decoding RestoreFootprintResultCode: %w", err) } - s.Signatures = nil - if l > 0 { - s.Signatures = make([]DecoratedSignature, l) - for i := uint32(0); i < l; i++ { - nTmp, err = s.Signatures[i].DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding DecoratedSignature: %s", err) - } - } + if _, ok := restoreFootprintResultCodeMap[v]; !ok { + return n, fmt.Errorf("'%d' is not a valid RestoreFootprintResultCode enum value", v) } + *e = RestoreFootprintResultCode(v) return n, nil } // MarshalBinary implements encoding.BinaryMarshaler. -func (s TransactionV0Envelope) MarshalBinary() ([]byte, error) { +func (s RestoreFootprintResultCode) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -24292,96 +41225,135 @@ func (s TransactionV0Envelope) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *TransactionV0Envelope) UnmarshalBinary(inp []byte) error { +func (s *RestoreFootprintResultCode) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*TransactionV0Envelope)(nil) - _ encoding.BinaryUnmarshaler = (*TransactionV0Envelope)(nil) + _ encoding.BinaryMarshaler = (*RestoreFootprintResultCode)(nil) + _ encoding.BinaryUnmarshaler = (*RestoreFootprintResultCode)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s TransactionV0Envelope) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s RestoreFootprintResultCode) xdrType() {} -var _ xdrType = (*TransactionV0Envelope)(nil) +var _ xdrType = (*RestoreFootprintResultCode)(nil) -// TransactionExt is an XDR NestedUnion defines as: +// RestoreFootprintResult is an XDR Union defines as: // -// union switch (int v) -// { -// case 0: -// void; -// } -type TransactionExt struct { - V int32 +// union RestoreFootprintResult switch (RestoreFootprintResultCode code) +// { +// case RESTORE_FOOTPRINT_SUCCESS: +// void; +// case RESTORE_FOOTPRINT_MALFORMED: +// case RESTORE_FOOTPRINT_RESOURCE_LIMIT_EXCEEDED: +// case RESTORE_FOOTPRINT_INSUFFICIENT_REFUNDABLE_FEE: +// void; +// }; +type RestoreFootprintResult struct { + Code RestoreFootprintResultCode } // SwitchFieldName returns the field name in which this union's // discriminant is stored -func (u TransactionExt) SwitchFieldName() string { - return "V" +func (u RestoreFootprintResult) SwitchFieldName() string { + return "Code" } // ArmForSwitch returns which field name should be used for storing -// the value for an instance of TransactionExt -func (u TransactionExt) ArmForSwitch(sw int32) (string, bool) { - switch int32(sw) { - case 0: +// the value for an instance of RestoreFootprintResult +func (u RestoreFootprintResult) ArmForSwitch(sw int32) (string, bool) { + switch RestoreFootprintResultCode(sw) { + case RestoreFootprintResultCodeRestoreFootprintSuccess: + return "", true + case RestoreFootprintResultCodeRestoreFootprintMalformed: + return "", true + case RestoreFootprintResultCodeRestoreFootprintResourceLimitExceeded: + return "", true + case RestoreFootprintResultCodeRestoreFootprintInsufficientRefundableFee: return "", true } return "-", false -} - -// NewTransactionExt creates a new TransactionExt. -func NewTransactionExt(v int32, value interface{}) (result TransactionExt, err error) { - result.V = v - switch int32(v) { - case 0: +} + +// NewRestoreFootprintResult creates a new RestoreFootprintResult. +func NewRestoreFootprintResult(code RestoreFootprintResultCode, value interface{}) (result RestoreFootprintResult, err error) { + result.Code = code + switch RestoreFootprintResultCode(code) { + case RestoreFootprintResultCodeRestoreFootprintSuccess: + // void + case RestoreFootprintResultCodeRestoreFootprintMalformed: + // void + case RestoreFootprintResultCodeRestoreFootprintResourceLimitExceeded: + // void + case RestoreFootprintResultCodeRestoreFootprintInsufficientRefundableFee: // void } return } // EncodeTo encodes this value using the Encoder. -func (u TransactionExt) EncodeTo(e *xdr.Encoder) error { +func (u RestoreFootprintResult) EncodeTo(e *xdr.Encoder) error { var err error - if _, err = e.EncodeInt(int32(u.V)); err != nil { + if err = u.Code.EncodeTo(e); err != nil { return err } - switch int32(u.V) { - case 0: + switch RestoreFootprintResultCode(u.Code) { + case RestoreFootprintResultCodeRestoreFootprintSuccess: + // Void + return nil + case RestoreFootprintResultCodeRestoreFootprintMalformed: + // Void + return nil + case RestoreFootprintResultCodeRestoreFootprintResourceLimitExceeded: + // Void + return nil + case RestoreFootprintResultCodeRestoreFootprintInsufficientRefundableFee: // Void return nil } - return fmt.Errorf("V (int32) switch value '%d' is not valid for union TransactionExt", u.V) + return fmt.Errorf("Code (RestoreFootprintResultCode) switch value '%d' is not valid for union RestoreFootprintResult", u.Code) } -var _ decoderFrom = (*TransactionExt)(nil) +var _ decoderFrom = (*RestoreFootprintResult)(nil) // DecodeFrom decodes this value using the Decoder. -func (u *TransactionExt) DecodeFrom(d *xdr.Decoder) (int, error) { +func (u *RestoreFootprintResult) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding RestoreFootprintResult: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - u.V, nTmp, err = d.DecodeInt() + nTmp, err = u.Code.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Int: %s", err) + return n, fmt.Errorf("decoding RestoreFootprintResultCode: %w", err) } - switch int32(u.V) { - case 0: + switch RestoreFootprintResultCode(u.Code) { + case RestoreFootprintResultCodeRestoreFootprintSuccess: + // Void + return n, nil + case RestoreFootprintResultCodeRestoreFootprintMalformed: + // Void + return n, nil + case RestoreFootprintResultCodeRestoreFootprintResourceLimitExceeded: + // Void + return n, nil + case RestoreFootprintResultCodeRestoreFootprintInsufficientRefundableFee: // Void return n, nil } - return n, fmt.Errorf("union TransactionExt has invalid V (int32) switch value '%d'", u.V) + return n, fmt.Errorf("union RestoreFootprintResult has invalid Code (RestoreFootprintResultCode) switch value '%d'", u.Code) } // MarshalBinary implements encoding.BinaryMarshaler. -func (s TransactionExt) MarshalBinary() ([]byte, error) { +func (s RestoreFootprintResult) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -24389,155 +41361,103 @@ func (s TransactionExt) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *TransactionExt) UnmarshalBinary(inp []byte) error { +func (s *RestoreFootprintResult) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*TransactionExt)(nil) - _ encoding.BinaryUnmarshaler = (*TransactionExt)(nil) + _ encoding.BinaryMarshaler = (*RestoreFootprintResult)(nil) + _ encoding.BinaryUnmarshaler = (*RestoreFootprintResult)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s TransactionExt) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s RestoreFootprintResult) xdrType() {} -var _ xdrType = (*TransactionExt)(nil) +var _ xdrType = (*RestoreFootprintResult)(nil) -// Transaction is an XDR Struct defines as: +// OperationResultCode is an XDR Enum defines as: // -// struct Transaction +// enum OperationResultCode // { -// // account used to run the transaction -// MuxedAccount sourceAccount; -// -// // the fee the sourceAccount will pay -// uint32 fee; -// -// // sequence number to consume in the account -// SequenceNumber seqNum; -// -// // validity conditions -// Preconditions cond; -// -// Memo memo; -// -// Operation operations; +// opINNER = 0, // inner object result is valid // -// // reserved for future use -// union switch (int v) -// { -// case 0: -// void; -// } -// ext; +// opBAD_AUTH = -1, // too few valid signatures / wrong network +// opNO_ACCOUNT = -2, // source account was not found +// opNOT_SUPPORTED = -3, // operation not supported at this time +// opTOO_MANY_SUBENTRIES = -4, // max number of subentries already reached +// opEXCEEDED_WORK_LIMIT = -5, // operation did too much work +// opTOO_MANY_SPONSORING = -6 // account is sponsoring too many entries // }; -type Transaction struct { - SourceAccount MuxedAccount - Fee Uint32 - SeqNum SequenceNumber - Cond Preconditions - Memo Memo - Operations []Operation `xdrmaxsize:"100"` - Ext TransactionExt +type OperationResultCode int32 + +const ( + OperationResultCodeOpInner OperationResultCode = 0 + OperationResultCodeOpBadAuth OperationResultCode = -1 + OperationResultCodeOpNoAccount OperationResultCode = -2 + OperationResultCodeOpNotSupported OperationResultCode = -3 + OperationResultCodeOpTooManySubentries OperationResultCode = -4 + OperationResultCodeOpExceededWorkLimit OperationResultCode = -5 + OperationResultCodeOpTooManySponsoring OperationResultCode = -6 +) + +var operationResultCodeMap = map[int32]string{ + 0: "OperationResultCodeOpInner", + -1: "OperationResultCodeOpBadAuth", + -2: "OperationResultCodeOpNoAccount", + -3: "OperationResultCodeOpNotSupported", + -4: "OperationResultCodeOpTooManySubentries", + -5: "OperationResultCodeOpExceededWorkLimit", + -6: "OperationResultCodeOpTooManySponsoring", +} + +// ValidEnum validates a proposed value for this enum. Implements +// the Enum interface for OperationResultCode +func (e OperationResultCode) ValidEnum(v int32) bool { + _, ok := operationResultCodeMap[v] + return ok +} + +// String returns the name of `e` +func (e OperationResultCode) String() string { + name, _ := operationResultCodeMap[int32(e)] + return name } // EncodeTo encodes this value using the Encoder. -func (s *Transaction) EncodeTo(e *xdr.Encoder) error { - var err error - if err = s.SourceAccount.EncodeTo(e); err != nil { - return err - } - if err = s.Fee.EncodeTo(e); err != nil { - return err - } - if err = s.SeqNum.EncodeTo(e); err != nil { - return err - } - if err = s.Cond.EncodeTo(e); err != nil { - return err - } - if err = s.Memo.EncodeTo(e); err != nil { - return err - } - if _, err = e.EncodeUint(uint32(len(s.Operations))); err != nil { - return err - } - for i := 0; i < len(s.Operations); i++ { - if err = s.Operations[i].EncodeTo(e); err != nil { - return err - } - } - if err = s.Ext.EncodeTo(e); err != nil { - return err +func (e OperationResultCode) EncodeTo(enc *xdr.Encoder) error { + if _, ok := operationResultCodeMap[int32(e)]; !ok { + return fmt.Errorf("'%d' is not a valid OperationResultCode enum value", e) } - return nil + _, err := enc.EncodeInt(int32(e)) + return err } -var _ decoderFrom = (*Transaction)(nil) +var _ decoderFrom = (*OperationResultCode)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *Transaction) DecodeFrom(d *xdr.Decoder) (int, error) { - var err error - var n, nTmp int - nTmp, err = s.SourceAccount.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding MuxedAccount: %s", err) - } - nTmp, err = s.Fee.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Uint32: %s", err) - } - nTmp, err = s.SeqNum.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding SequenceNumber: %s", err) - } - nTmp, err = s.Cond.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Preconditions: %s", err) - } - nTmp, err = s.Memo.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Memo: %s", err) +func (e *OperationResultCode) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding OperationResultCode: %w", ErrMaxDecodingDepthReached) } - var l uint32 - l, nTmp, err = d.DecodeUint() - n += nTmp + maxDepth -= 1 + v, n, err := d.DecodeInt() if err != nil { - return n, fmt.Errorf("decoding Operation: %s", err) - } - if l > 100 { - return n, fmt.Errorf("decoding Operation: data size (%d) exceeds size limit (100)", l) - } - s.Operations = nil - if l > 0 { - s.Operations = make([]Operation, l) - for i := uint32(0); i < l; i++ { - nTmp, err = s.Operations[i].DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Operation: %s", err) - } - } + return n, fmt.Errorf("decoding OperationResultCode: %w", err) } - nTmp, err = s.Ext.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding TransactionExt: %s", err) + if _, ok := operationResultCodeMap[v]; !ok { + return n, fmt.Errorf("'%d' is not a valid OperationResultCode enum value", v) } + *e = OperationResultCode(v) return n, nil } // MarshalBinary implements encoding.BinaryMarshaler. -func (s Transaction) MarshalBinary() ([]byte, error) { +func (s OperationResultCode) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -24545,1595 +41465,1049 @@ func (s Transaction) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *Transaction) UnmarshalBinary(inp []byte) error { +func (s *OperationResultCode) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*Transaction)(nil) - _ encoding.BinaryUnmarshaler = (*Transaction)(nil) + _ encoding.BinaryMarshaler = (*OperationResultCode)(nil) + _ encoding.BinaryUnmarshaler = (*OperationResultCode)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s Transaction) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s OperationResultCode) xdrType() {} -var _ xdrType = (*Transaction)(nil) +var _ xdrType = (*OperationResultCode)(nil) -// TransactionV1Envelope is an XDR Struct defines as: +// OperationResultTr is an XDR NestedUnion defines as: // -// struct TransactionV1Envelope -// { -// Transaction tx; -// /* Each decorated signature is a signature over the SHA256 hash of -// * a TransactionSignaturePayload */ -// DecoratedSignature signatures<20>; -// }; -type TransactionV1Envelope struct { - Tx Transaction - Signatures []DecoratedSignature `xdrmaxsize:"20"` +// union switch (OperationType type) +// { +// case CREATE_ACCOUNT: +// CreateAccountResult createAccountResult; +// case PAYMENT: +// PaymentResult paymentResult; +// case PATH_PAYMENT_STRICT_RECEIVE: +// PathPaymentStrictReceiveResult pathPaymentStrictReceiveResult; +// case MANAGE_SELL_OFFER: +// ManageSellOfferResult manageSellOfferResult; +// case CREATE_PASSIVE_SELL_OFFER: +// ManageSellOfferResult createPassiveSellOfferResult; +// case SET_OPTIONS: +// SetOptionsResult setOptionsResult; +// case CHANGE_TRUST: +// ChangeTrustResult changeTrustResult; +// case ALLOW_TRUST: +// AllowTrustResult allowTrustResult; +// case ACCOUNT_MERGE: +// AccountMergeResult accountMergeResult; +// case INFLATION: +// InflationResult inflationResult; +// case MANAGE_DATA: +// ManageDataResult manageDataResult; +// case BUMP_SEQUENCE: +// BumpSequenceResult bumpSeqResult; +// case MANAGE_BUY_OFFER: +// ManageBuyOfferResult manageBuyOfferResult; +// case PATH_PAYMENT_STRICT_SEND: +// PathPaymentStrictSendResult pathPaymentStrictSendResult; +// case CREATE_CLAIMABLE_BALANCE: +// CreateClaimableBalanceResult createClaimableBalanceResult; +// case CLAIM_CLAIMABLE_BALANCE: +// ClaimClaimableBalanceResult claimClaimableBalanceResult; +// case BEGIN_SPONSORING_FUTURE_RESERVES: +// BeginSponsoringFutureReservesResult beginSponsoringFutureReservesResult; +// case END_SPONSORING_FUTURE_RESERVES: +// EndSponsoringFutureReservesResult endSponsoringFutureReservesResult; +// case REVOKE_SPONSORSHIP: +// RevokeSponsorshipResult revokeSponsorshipResult; +// case CLAWBACK: +// ClawbackResult clawbackResult; +// case CLAWBACK_CLAIMABLE_BALANCE: +// ClawbackClaimableBalanceResult clawbackClaimableBalanceResult; +// case SET_TRUST_LINE_FLAGS: +// SetTrustLineFlagsResult setTrustLineFlagsResult; +// case LIQUIDITY_POOL_DEPOSIT: +// LiquidityPoolDepositResult liquidityPoolDepositResult; +// case LIQUIDITY_POOL_WITHDRAW: +// LiquidityPoolWithdrawResult liquidityPoolWithdrawResult; +// case INVOKE_HOST_FUNCTION: +// InvokeHostFunctionResult invokeHostFunctionResult; +// case EXTEND_FOOTPRINT_TTL: +// ExtendFootprintTTLResult extendFootprintTTLResult; +// case RESTORE_FOOTPRINT: +// RestoreFootprintResult restoreFootprintResult; +// } +type OperationResultTr struct { + Type OperationType + CreateAccountResult *CreateAccountResult + PaymentResult *PaymentResult + PathPaymentStrictReceiveResult *PathPaymentStrictReceiveResult + ManageSellOfferResult *ManageSellOfferResult + CreatePassiveSellOfferResult *ManageSellOfferResult + SetOptionsResult *SetOptionsResult + ChangeTrustResult *ChangeTrustResult + AllowTrustResult *AllowTrustResult + AccountMergeResult *AccountMergeResult + InflationResult *InflationResult + ManageDataResult *ManageDataResult + BumpSeqResult *BumpSequenceResult + ManageBuyOfferResult *ManageBuyOfferResult + PathPaymentStrictSendResult *PathPaymentStrictSendResult + CreateClaimableBalanceResult *CreateClaimableBalanceResult + ClaimClaimableBalanceResult *ClaimClaimableBalanceResult + BeginSponsoringFutureReservesResult *BeginSponsoringFutureReservesResult + EndSponsoringFutureReservesResult *EndSponsoringFutureReservesResult + RevokeSponsorshipResult *RevokeSponsorshipResult + ClawbackResult *ClawbackResult + ClawbackClaimableBalanceResult *ClawbackClaimableBalanceResult + SetTrustLineFlagsResult *SetTrustLineFlagsResult + LiquidityPoolDepositResult *LiquidityPoolDepositResult + LiquidityPoolWithdrawResult *LiquidityPoolWithdrawResult + InvokeHostFunctionResult *InvokeHostFunctionResult + ExtendFootprintTtlResult *ExtendFootprintTtlResult + RestoreFootprintResult *RestoreFootprintResult } -// EncodeTo encodes this value using the Encoder. -func (s *TransactionV1Envelope) EncodeTo(e *xdr.Encoder) error { - var err error - if err = s.Tx.EncodeTo(e); err != nil { - return err - } - if _, err = e.EncodeUint(uint32(len(s.Signatures))); err != nil { - return err - } - for i := 0; i < len(s.Signatures); i++ { - if err = s.Signatures[i].EncodeTo(e); err != nil { - return err - } - } - return nil +// SwitchFieldName returns the field name in which this union's +// discriminant is stored +func (u OperationResultTr) SwitchFieldName() string { + return "Type" } -var _ decoderFrom = (*TransactionV1Envelope)(nil) - -// DecodeFrom decodes this value using the Decoder. -func (s *TransactionV1Envelope) DecodeFrom(d *xdr.Decoder) (int, error) { - var err error - var n, nTmp int - nTmp, err = s.Tx.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Transaction: %s", err) - } - var l uint32 - l, nTmp, err = d.DecodeUint() - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding DecoratedSignature: %s", err) - } - if l > 20 { - return n, fmt.Errorf("decoding DecoratedSignature: data size (%d) exceeds size limit (20)", l) +// ArmForSwitch returns which field name should be used for storing +// the value for an instance of OperationResultTr +func (u OperationResultTr) ArmForSwitch(sw int32) (string, bool) { + switch OperationType(sw) { + case OperationTypeCreateAccount: + return "CreateAccountResult", true + case OperationTypePayment: + return "PaymentResult", true + case OperationTypePathPaymentStrictReceive: + return "PathPaymentStrictReceiveResult", true + case OperationTypeManageSellOffer: + return "ManageSellOfferResult", true + case OperationTypeCreatePassiveSellOffer: + return "CreatePassiveSellOfferResult", true + case OperationTypeSetOptions: + return "SetOptionsResult", true + case OperationTypeChangeTrust: + return "ChangeTrustResult", true + case OperationTypeAllowTrust: + return "AllowTrustResult", true + case OperationTypeAccountMerge: + return "AccountMergeResult", true + case OperationTypeInflation: + return "InflationResult", true + case OperationTypeManageData: + return "ManageDataResult", true + case OperationTypeBumpSequence: + return "BumpSeqResult", true + case OperationTypeManageBuyOffer: + return "ManageBuyOfferResult", true + case OperationTypePathPaymentStrictSend: + return "PathPaymentStrictSendResult", true + case OperationTypeCreateClaimableBalance: + return "CreateClaimableBalanceResult", true + case OperationTypeClaimClaimableBalance: + return "ClaimClaimableBalanceResult", true + case OperationTypeBeginSponsoringFutureReserves: + return "BeginSponsoringFutureReservesResult", true + case OperationTypeEndSponsoringFutureReserves: + return "EndSponsoringFutureReservesResult", true + case OperationTypeRevokeSponsorship: + return "RevokeSponsorshipResult", true + case OperationTypeClawback: + return "ClawbackResult", true + case OperationTypeClawbackClaimableBalance: + return "ClawbackClaimableBalanceResult", true + case OperationTypeSetTrustLineFlags: + return "SetTrustLineFlagsResult", true + case OperationTypeLiquidityPoolDeposit: + return "LiquidityPoolDepositResult", true + case OperationTypeLiquidityPoolWithdraw: + return "LiquidityPoolWithdrawResult", true + case OperationTypeInvokeHostFunction: + return "InvokeHostFunctionResult", true + case OperationTypeExtendFootprintTtl: + return "ExtendFootprintTtlResult", true + case OperationTypeRestoreFootprint: + return "RestoreFootprintResult", true } - s.Signatures = nil - if l > 0 { - s.Signatures = make([]DecoratedSignature, l) - for i := uint32(0); i < l; i++ { - nTmp, err = s.Signatures[i].DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding DecoratedSignature: %s", err) - } + return "-", false +} + +// NewOperationResultTr creates a new OperationResultTr. +func NewOperationResultTr(aType OperationType, value interface{}) (result OperationResultTr, err error) { + result.Type = aType + switch OperationType(aType) { + case OperationTypeCreateAccount: + tv, ok := value.(CreateAccountResult) + if !ok { + err = errors.New("invalid value, must be CreateAccountResult") + return + } + result.CreateAccountResult = &tv + case OperationTypePayment: + tv, ok := value.(PaymentResult) + if !ok { + err = errors.New("invalid value, must be PaymentResult") + return + } + result.PaymentResult = &tv + case OperationTypePathPaymentStrictReceive: + tv, ok := value.(PathPaymentStrictReceiveResult) + if !ok { + err = errors.New("invalid value, must be PathPaymentStrictReceiveResult") + return + } + result.PathPaymentStrictReceiveResult = &tv + case OperationTypeManageSellOffer: + tv, ok := value.(ManageSellOfferResult) + if !ok { + err = errors.New("invalid value, must be ManageSellOfferResult") + return + } + result.ManageSellOfferResult = &tv + case OperationTypeCreatePassiveSellOffer: + tv, ok := value.(ManageSellOfferResult) + if !ok { + err = errors.New("invalid value, must be ManageSellOfferResult") + return + } + result.CreatePassiveSellOfferResult = &tv + case OperationTypeSetOptions: + tv, ok := value.(SetOptionsResult) + if !ok { + err = errors.New("invalid value, must be SetOptionsResult") + return + } + result.SetOptionsResult = &tv + case OperationTypeChangeTrust: + tv, ok := value.(ChangeTrustResult) + if !ok { + err = errors.New("invalid value, must be ChangeTrustResult") + return + } + result.ChangeTrustResult = &tv + case OperationTypeAllowTrust: + tv, ok := value.(AllowTrustResult) + if !ok { + err = errors.New("invalid value, must be AllowTrustResult") + return + } + result.AllowTrustResult = &tv + case OperationTypeAccountMerge: + tv, ok := value.(AccountMergeResult) + if !ok { + err = errors.New("invalid value, must be AccountMergeResult") + return + } + result.AccountMergeResult = &tv + case OperationTypeInflation: + tv, ok := value.(InflationResult) + if !ok { + err = errors.New("invalid value, must be InflationResult") + return + } + result.InflationResult = &tv + case OperationTypeManageData: + tv, ok := value.(ManageDataResult) + if !ok { + err = errors.New("invalid value, must be ManageDataResult") + return + } + result.ManageDataResult = &tv + case OperationTypeBumpSequence: + tv, ok := value.(BumpSequenceResult) + if !ok { + err = errors.New("invalid value, must be BumpSequenceResult") + return + } + result.BumpSeqResult = &tv + case OperationTypeManageBuyOffer: + tv, ok := value.(ManageBuyOfferResult) + if !ok { + err = errors.New("invalid value, must be ManageBuyOfferResult") + return + } + result.ManageBuyOfferResult = &tv + case OperationTypePathPaymentStrictSend: + tv, ok := value.(PathPaymentStrictSendResult) + if !ok { + err = errors.New("invalid value, must be PathPaymentStrictSendResult") + return + } + result.PathPaymentStrictSendResult = &tv + case OperationTypeCreateClaimableBalance: + tv, ok := value.(CreateClaimableBalanceResult) + if !ok { + err = errors.New("invalid value, must be CreateClaimableBalanceResult") + return + } + result.CreateClaimableBalanceResult = &tv + case OperationTypeClaimClaimableBalance: + tv, ok := value.(ClaimClaimableBalanceResult) + if !ok { + err = errors.New("invalid value, must be ClaimClaimableBalanceResult") + return + } + result.ClaimClaimableBalanceResult = &tv + case OperationTypeBeginSponsoringFutureReserves: + tv, ok := value.(BeginSponsoringFutureReservesResult) + if !ok { + err = errors.New("invalid value, must be BeginSponsoringFutureReservesResult") + return + } + result.BeginSponsoringFutureReservesResult = &tv + case OperationTypeEndSponsoringFutureReserves: + tv, ok := value.(EndSponsoringFutureReservesResult) + if !ok { + err = errors.New("invalid value, must be EndSponsoringFutureReservesResult") + return + } + result.EndSponsoringFutureReservesResult = &tv + case OperationTypeRevokeSponsorship: + tv, ok := value.(RevokeSponsorshipResult) + if !ok { + err = errors.New("invalid value, must be RevokeSponsorshipResult") + return + } + result.RevokeSponsorshipResult = &tv + case OperationTypeClawback: + tv, ok := value.(ClawbackResult) + if !ok { + err = errors.New("invalid value, must be ClawbackResult") + return + } + result.ClawbackResult = &tv + case OperationTypeClawbackClaimableBalance: + tv, ok := value.(ClawbackClaimableBalanceResult) + if !ok { + err = errors.New("invalid value, must be ClawbackClaimableBalanceResult") + return + } + result.ClawbackClaimableBalanceResult = &tv + case OperationTypeSetTrustLineFlags: + tv, ok := value.(SetTrustLineFlagsResult) + if !ok { + err = errors.New("invalid value, must be SetTrustLineFlagsResult") + return } - } - return n, nil -} - -// MarshalBinary implements encoding.BinaryMarshaler. -func (s TransactionV1Envelope) MarshalBinary() ([]byte, error) { - b := bytes.Buffer{} - e := xdr.NewEncoder(&b) - err := s.EncodeTo(e) - return b.Bytes(), err -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *TransactionV1Envelope) UnmarshalBinary(inp []byte) error { - r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) - return err -} - -var ( - _ encoding.BinaryMarshaler = (*TransactionV1Envelope)(nil) - _ encoding.BinaryUnmarshaler = (*TransactionV1Envelope)(nil) -) - -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s TransactionV1Envelope) xdrType() {} - -var _ xdrType = (*TransactionV1Envelope)(nil) - -// FeeBumpTransactionInnerTx is an XDR NestedUnion defines as: -// -// union switch (EnvelopeType type) -// { -// case ENVELOPE_TYPE_TX: -// TransactionV1Envelope v1; -// } -type FeeBumpTransactionInnerTx struct { - Type EnvelopeType - V1 *TransactionV1Envelope -} - -// SwitchFieldName returns the field name in which this union's -// discriminant is stored -func (u FeeBumpTransactionInnerTx) SwitchFieldName() string { - return "Type" -} - -// ArmForSwitch returns which field name should be used for storing -// the value for an instance of FeeBumpTransactionInnerTx -func (u FeeBumpTransactionInnerTx) ArmForSwitch(sw int32) (string, bool) { - switch EnvelopeType(sw) { - case EnvelopeTypeEnvelopeTypeTx: - return "V1", true - } - return "-", false -} - -// NewFeeBumpTransactionInnerTx creates a new FeeBumpTransactionInnerTx. -func NewFeeBumpTransactionInnerTx(aType EnvelopeType, value interface{}) (result FeeBumpTransactionInnerTx, err error) { - result.Type = aType - switch EnvelopeType(aType) { - case EnvelopeTypeEnvelopeTypeTx: - tv, ok := value.(TransactionV1Envelope) + result.SetTrustLineFlagsResult = &tv + case OperationTypeLiquidityPoolDeposit: + tv, ok := value.(LiquidityPoolDepositResult) if !ok { - err = fmt.Errorf("invalid value, must be TransactionV1Envelope") + err = errors.New("invalid value, must be LiquidityPoolDepositResult") return } - result.V1 = &tv + result.LiquidityPoolDepositResult = &tv + case OperationTypeLiquidityPoolWithdraw: + tv, ok := value.(LiquidityPoolWithdrawResult) + if !ok { + err = errors.New("invalid value, must be LiquidityPoolWithdrawResult") + return + } + result.LiquidityPoolWithdrawResult = &tv + case OperationTypeInvokeHostFunction: + tv, ok := value.(InvokeHostFunctionResult) + if !ok { + err = errors.New("invalid value, must be InvokeHostFunctionResult") + return + } + result.InvokeHostFunctionResult = &tv + case OperationTypeExtendFootprintTtl: + tv, ok := value.(ExtendFootprintTtlResult) + if !ok { + err = errors.New("invalid value, must be ExtendFootprintTtlResult") + return + } + result.ExtendFootprintTtlResult = &tv + case OperationTypeRestoreFootprint: + tv, ok := value.(RestoreFootprintResult) + if !ok { + err = errors.New("invalid value, must be RestoreFootprintResult") + return + } + result.RestoreFootprintResult = &tv } return } -// MustV1 retrieves the V1 value from the union, +// MustCreateAccountResult retrieves the CreateAccountResult value from the union, // panicing if the value is not set. -func (u FeeBumpTransactionInnerTx) MustV1() TransactionV1Envelope { - val, ok := u.GetV1() +func (u OperationResultTr) MustCreateAccountResult() CreateAccountResult { + val, ok := u.GetCreateAccountResult() if !ok { - panic("arm V1 is not set") + panic("arm CreateAccountResult is not set") } return val } -// GetV1 retrieves the V1 value from the union, +// GetCreateAccountResult retrieves the CreateAccountResult value from the union, // returning ok if the union's switch indicated the value is valid. -func (u FeeBumpTransactionInnerTx) GetV1() (result TransactionV1Envelope, ok bool) { +func (u OperationResultTr) GetCreateAccountResult() (result CreateAccountResult, ok bool) { armName, _ := u.ArmForSwitch(int32(u.Type)) - if armName == "V1" { - result = *u.V1 + if armName == "CreateAccountResult" { + result = *u.CreateAccountResult ok = true } return } -// EncodeTo encodes this value using the Encoder. -func (u FeeBumpTransactionInnerTx) EncodeTo(e *xdr.Encoder) error { - var err error - if err = u.Type.EncodeTo(e); err != nil { - return err - } - switch EnvelopeType(u.Type) { - case EnvelopeTypeEnvelopeTypeTx: - if err = (*u.V1).EncodeTo(e); err != nil { - return err - } - return nil - } - return fmt.Errorf("Type (EnvelopeType) switch value '%d' is not valid for union FeeBumpTransactionInnerTx", u.Type) -} - -var _ decoderFrom = (*FeeBumpTransactionInnerTx)(nil) +// MustPaymentResult retrieves the PaymentResult value from the union, +// panicing if the value is not set. +func (u OperationResultTr) MustPaymentResult() PaymentResult { + val, ok := u.GetPaymentResult() -// DecodeFrom decodes this value using the Decoder. -func (u *FeeBumpTransactionInnerTx) DecodeFrom(d *xdr.Decoder) (int, error) { - var err error - var n, nTmp int - nTmp, err = u.Type.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding EnvelopeType: %s", err) - } - switch EnvelopeType(u.Type) { - case EnvelopeTypeEnvelopeTypeTx: - u.V1 = new(TransactionV1Envelope) - nTmp, err = (*u.V1).DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding TransactionV1Envelope: %s", err) - } - return n, nil + if !ok { + panic("arm PaymentResult is not set") } - return n, fmt.Errorf("union FeeBumpTransactionInnerTx has invalid Type (EnvelopeType) switch value '%d'", u.Type) -} - -// MarshalBinary implements encoding.BinaryMarshaler. -func (s FeeBumpTransactionInnerTx) MarshalBinary() ([]byte, error) { - b := bytes.Buffer{} - e := xdr.NewEncoder(&b) - err := s.EncodeTo(e) - return b.Bytes(), err -} -// UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *FeeBumpTransactionInnerTx) UnmarshalBinary(inp []byte) error { - r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) - return err -} - -var ( - _ encoding.BinaryMarshaler = (*FeeBumpTransactionInnerTx)(nil) - _ encoding.BinaryUnmarshaler = (*FeeBumpTransactionInnerTx)(nil) -) - -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s FeeBumpTransactionInnerTx) xdrType() {} - -var _ xdrType = (*FeeBumpTransactionInnerTx)(nil) - -// FeeBumpTransactionExt is an XDR NestedUnion defines as: -// -// union switch (int v) -// { -// case 0: -// void; -// } -type FeeBumpTransactionExt struct { - V int32 + return val } -// SwitchFieldName returns the field name in which this union's -// discriminant is stored -func (u FeeBumpTransactionExt) SwitchFieldName() string { - return "V" -} +// GetPaymentResult retrieves the PaymentResult value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u OperationResultTr) GetPaymentResult() (result PaymentResult, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) -// ArmForSwitch returns which field name should be used for storing -// the value for an instance of FeeBumpTransactionExt -func (u FeeBumpTransactionExt) ArmForSwitch(sw int32) (string, bool) { - switch int32(sw) { - case 0: - return "", true + if armName == "PaymentResult" { + result = *u.PaymentResult + ok = true } - return "-", false -} -// NewFeeBumpTransactionExt creates a new FeeBumpTransactionExt. -func NewFeeBumpTransactionExt(v int32, value interface{}) (result FeeBumpTransactionExt, err error) { - result.V = v - switch int32(v) { - case 0: - // void - } return } -// EncodeTo encodes this value using the Encoder. -func (u FeeBumpTransactionExt) EncodeTo(e *xdr.Encoder) error { - var err error - if _, err = e.EncodeInt(int32(u.V)); err != nil { - return err - } - switch int32(u.V) { - case 0: - // Void - return nil - } - return fmt.Errorf("V (int32) switch value '%d' is not valid for union FeeBumpTransactionExt", u.V) -} - -var _ decoderFrom = (*FeeBumpTransactionExt)(nil) +// MustPathPaymentStrictReceiveResult retrieves the PathPaymentStrictReceiveResult value from the union, +// panicing if the value is not set. +func (u OperationResultTr) MustPathPaymentStrictReceiveResult() PathPaymentStrictReceiveResult { + val, ok := u.GetPathPaymentStrictReceiveResult() -// DecodeFrom decodes this value using the Decoder. -func (u *FeeBumpTransactionExt) DecodeFrom(d *xdr.Decoder) (int, error) { - var err error - var n, nTmp int - u.V, nTmp, err = d.DecodeInt() - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Int: %s", err) - } - switch int32(u.V) { - case 0: - // Void - return n, nil + if !ok { + panic("arm PathPaymentStrictReceiveResult is not set") } - return n, fmt.Errorf("union FeeBumpTransactionExt has invalid V (int32) switch value '%d'", u.V) -} - -// MarshalBinary implements encoding.BinaryMarshaler. -func (s FeeBumpTransactionExt) MarshalBinary() ([]byte, error) { - b := bytes.Buffer{} - e := xdr.NewEncoder(&b) - err := s.EncodeTo(e) - return b.Bytes(), err -} -// UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *FeeBumpTransactionExt) UnmarshalBinary(inp []byte) error { - r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) - return err + return val } -var ( - _ encoding.BinaryMarshaler = (*FeeBumpTransactionExt)(nil) - _ encoding.BinaryUnmarshaler = (*FeeBumpTransactionExt)(nil) -) - -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s FeeBumpTransactionExt) xdrType() {} - -var _ xdrType = (*FeeBumpTransactionExt)(nil) - -// FeeBumpTransaction is an XDR Struct defines as: -// -// struct FeeBumpTransaction -// { -// MuxedAccount feeSource; -// int64 fee; -// union switch (EnvelopeType type) -// { -// case ENVELOPE_TYPE_TX: -// TransactionV1Envelope v1; -// } -// innerTx; -// union switch (int v) -// { -// case 0: -// void; -// } -// ext; -// }; -type FeeBumpTransaction struct { - FeeSource MuxedAccount - Fee Int64 - InnerTx FeeBumpTransactionInnerTx - Ext FeeBumpTransactionExt -} +// GetPathPaymentStrictReceiveResult retrieves the PathPaymentStrictReceiveResult value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u OperationResultTr) GetPathPaymentStrictReceiveResult() (result PathPaymentStrictReceiveResult, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) -// EncodeTo encodes this value using the Encoder. -func (s *FeeBumpTransaction) EncodeTo(e *xdr.Encoder) error { - var err error - if err = s.FeeSource.EncodeTo(e); err != nil { - return err - } - if err = s.Fee.EncodeTo(e); err != nil { - return err - } - if err = s.InnerTx.EncodeTo(e); err != nil { - return err - } - if err = s.Ext.EncodeTo(e); err != nil { - return err + if armName == "PathPaymentStrictReceiveResult" { + result = *u.PathPaymentStrictReceiveResult + ok = true } - return nil + + return } -var _ decoderFrom = (*FeeBumpTransaction)(nil) +// MustManageSellOfferResult retrieves the ManageSellOfferResult value from the union, +// panicing if the value is not set. +func (u OperationResultTr) MustManageSellOfferResult() ManageSellOfferResult { + val, ok := u.GetManageSellOfferResult() -// DecodeFrom decodes this value using the Decoder. -func (s *FeeBumpTransaction) DecodeFrom(d *xdr.Decoder) (int, error) { - var err error - var n, nTmp int - nTmp, err = s.FeeSource.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding MuxedAccount: %s", err) - } - nTmp, err = s.Fee.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Int64: %s", err) - } - nTmp, err = s.InnerTx.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding FeeBumpTransactionInnerTx: %s", err) - } - nTmp, err = s.Ext.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding FeeBumpTransactionExt: %s", err) + if !ok { + panic("arm ManageSellOfferResult is not set") } - return n, nil -} - -// MarshalBinary implements encoding.BinaryMarshaler. -func (s FeeBumpTransaction) MarshalBinary() ([]byte, error) { - b := bytes.Buffer{} - e := xdr.NewEncoder(&b) - err := s.EncodeTo(e) - return b.Bytes(), err -} -// UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *FeeBumpTransaction) UnmarshalBinary(inp []byte) error { - r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) - return err + return val } -var ( - _ encoding.BinaryMarshaler = (*FeeBumpTransaction)(nil) - _ encoding.BinaryUnmarshaler = (*FeeBumpTransaction)(nil) -) - -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s FeeBumpTransaction) xdrType() {} +// GetManageSellOfferResult retrieves the ManageSellOfferResult value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u OperationResultTr) GetManageSellOfferResult() (result ManageSellOfferResult, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) -var _ xdrType = (*FeeBumpTransaction)(nil) + if armName == "ManageSellOfferResult" { + result = *u.ManageSellOfferResult + ok = true + } -// FeeBumpTransactionEnvelope is an XDR Struct defines as: -// -// struct FeeBumpTransactionEnvelope -// { -// FeeBumpTransaction tx; -// /* Each decorated signature is a signature over the SHA256 hash of -// * a TransactionSignaturePayload */ -// DecoratedSignature signatures<20>; -// }; -type FeeBumpTransactionEnvelope struct { - Tx FeeBumpTransaction - Signatures []DecoratedSignature `xdrmaxsize:"20"` + return } -// EncodeTo encodes this value using the Encoder. -func (s *FeeBumpTransactionEnvelope) EncodeTo(e *xdr.Encoder) error { - var err error - if err = s.Tx.EncodeTo(e); err != nil { - return err - } - if _, err = e.EncodeUint(uint32(len(s.Signatures))); err != nil { - return err - } - for i := 0; i < len(s.Signatures); i++ { - if err = s.Signatures[i].EncodeTo(e); err != nil { - return err - } +// MustCreatePassiveSellOfferResult retrieves the CreatePassiveSellOfferResult value from the union, +// panicing if the value is not set. +func (u OperationResultTr) MustCreatePassiveSellOfferResult() ManageSellOfferResult { + val, ok := u.GetCreatePassiveSellOfferResult() + + if !ok { + panic("arm CreatePassiveSellOfferResult is not set") } - return nil + + return val } -var _ decoderFrom = (*FeeBumpTransactionEnvelope)(nil) +// GetCreatePassiveSellOfferResult retrieves the CreatePassiveSellOfferResult value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u OperationResultTr) GetCreatePassiveSellOfferResult() (result ManageSellOfferResult, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) -// DecodeFrom decodes this value using the Decoder. -func (s *FeeBumpTransactionEnvelope) DecodeFrom(d *xdr.Decoder) (int, error) { - var err error - var n, nTmp int - nTmp, err = s.Tx.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding FeeBumpTransaction: %s", err) - } - var l uint32 - l, nTmp, err = d.DecodeUint() - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding DecoratedSignature: %s", err) - } - if l > 20 { - return n, fmt.Errorf("decoding DecoratedSignature: data size (%d) exceeds size limit (20)", l) - } - s.Signatures = nil - if l > 0 { - s.Signatures = make([]DecoratedSignature, l) - for i := uint32(0); i < l; i++ { - nTmp, err = s.Signatures[i].DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding DecoratedSignature: %s", err) - } - } + if armName == "CreatePassiveSellOfferResult" { + result = *u.CreatePassiveSellOfferResult + ok = true } - return n, nil -} - -// MarshalBinary implements encoding.BinaryMarshaler. -func (s FeeBumpTransactionEnvelope) MarshalBinary() ([]byte, error) { - b := bytes.Buffer{} - e := xdr.NewEncoder(&b) - err := s.EncodeTo(e) - return b.Bytes(), err -} -// UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *FeeBumpTransactionEnvelope) UnmarshalBinary(inp []byte) error { - r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) - return err + return } -var ( - _ encoding.BinaryMarshaler = (*FeeBumpTransactionEnvelope)(nil) - _ encoding.BinaryUnmarshaler = (*FeeBumpTransactionEnvelope)(nil) -) - -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s FeeBumpTransactionEnvelope) xdrType() {} +// MustSetOptionsResult retrieves the SetOptionsResult value from the union, +// panicing if the value is not set. +func (u OperationResultTr) MustSetOptionsResult() SetOptionsResult { + val, ok := u.GetSetOptionsResult() -var _ xdrType = (*FeeBumpTransactionEnvelope)(nil) + if !ok { + panic("arm SetOptionsResult is not set") + } -// TransactionEnvelope is an XDR Union defines as: -// -// union TransactionEnvelope switch (EnvelopeType type) -// { -// case ENVELOPE_TYPE_TX_V0: -// TransactionV0Envelope v0; -// case ENVELOPE_TYPE_TX: -// TransactionV1Envelope v1; -// case ENVELOPE_TYPE_TX_FEE_BUMP: -// FeeBumpTransactionEnvelope feeBump; -// }; -type TransactionEnvelope struct { - Type EnvelopeType - V0 *TransactionV0Envelope - V1 *TransactionV1Envelope - FeeBump *FeeBumpTransactionEnvelope + return val } -// SwitchFieldName returns the field name in which this union's -// discriminant is stored -func (u TransactionEnvelope) SwitchFieldName() string { - return "Type" -} +// GetSetOptionsResult retrieves the SetOptionsResult value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u OperationResultTr) GetSetOptionsResult() (result SetOptionsResult, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) -// ArmForSwitch returns which field name should be used for storing -// the value for an instance of TransactionEnvelope -func (u TransactionEnvelope) ArmForSwitch(sw int32) (string, bool) { - switch EnvelopeType(sw) { - case EnvelopeTypeEnvelopeTypeTxV0: - return "V0", true - case EnvelopeTypeEnvelopeTypeTx: - return "V1", true - case EnvelopeTypeEnvelopeTypeTxFeeBump: - return "FeeBump", true + if armName == "SetOptionsResult" { + result = *u.SetOptionsResult + ok = true } - return "-", false -} -// NewTransactionEnvelope creates a new TransactionEnvelope. -func NewTransactionEnvelope(aType EnvelopeType, value interface{}) (result TransactionEnvelope, err error) { - result.Type = aType - switch EnvelopeType(aType) { - case EnvelopeTypeEnvelopeTypeTxV0: - tv, ok := value.(TransactionV0Envelope) - if !ok { - err = fmt.Errorf("invalid value, must be TransactionV0Envelope") - return - } - result.V0 = &tv - case EnvelopeTypeEnvelopeTypeTx: - tv, ok := value.(TransactionV1Envelope) - if !ok { - err = fmt.Errorf("invalid value, must be TransactionV1Envelope") - return - } - result.V1 = &tv - case EnvelopeTypeEnvelopeTypeTxFeeBump: - tv, ok := value.(FeeBumpTransactionEnvelope) - if !ok { - err = fmt.Errorf("invalid value, must be FeeBumpTransactionEnvelope") - return - } - result.FeeBump = &tv - } return } -// MustV0 retrieves the V0 value from the union, +// MustChangeTrustResult retrieves the ChangeTrustResult value from the union, // panicing if the value is not set. -func (u TransactionEnvelope) MustV0() TransactionV0Envelope { - val, ok := u.GetV0() +func (u OperationResultTr) MustChangeTrustResult() ChangeTrustResult { + val, ok := u.GetChangeTrustResult() if !ok { - panic("arm V0 is not set") + panic("arm ChangeTrustResult is not set") } return val } -// GetV0 retrieves the V0 value from the union, +// GetChangeTrustResult retrieves the ChangeTrustResult value from the union, // returning ok if the union's switch indicated the value is valid. -func (u TransactionEnvelope) GetV0() (result TransactionV0Envelope, ok bool) { +func (u OperationResultTr) GetChangeTrustResult() (result ChangeTrustResult, ok bool) { armName, _ := u.ArmForSwitch(int32(u.Type)) - if armName == "V0" { - result = *u.V0 + if armName == "ChangeTrustResult" { + result = *u.ChangeTrustResult ok = true } return } -// MustV1 retrieves the V1 value from the union, +// MustAllowTrustResult retrieves the AllowTrustResult value from the union, // panicing if the value is not set. -func (u TransactionEnvelope) MustV1() TransactionV1Envelope { - val, ok := u.GetV1() +func (u OperationResultTr) MustAllowTrustResult() AllowTrustResult { + val, ok := u.GetAllowTrustResult() if !ok { - panic("arm V1 is not set") + panic("arm AllowTrustResult is not set") } return val } -// GetV1 retrieves the V1 value from the union, +// GetAllowTrustResult retrieves the AllowTrustResult value from the union, // returning ok if the union's switch indicated the value is valid. -func (u TransactionEnvelope) GetV1() (result TransactionV1Envelope, ok bool) { +func (u OperationResultTr) GetAllowTrustResult() (result AllowTrustResult, ok bool) { armName, _ := u.ArmForSwitch(int32(u.Type)) - if armName == "V1" { - result = *u.V1 + if armName == "AllowTrustResult" { + result = *u.AllowTrustResult ok = true } return } -// MustFeeBump retrieves the FeeBump value from the union, +// MustAccountMergeResult retrieves the AccountMergeResult value from the union, // panicing if the value is not set. -func (u TransactionEnvelope) MustFeeBump() FeeBumpTransactionEnvelope { - val, ok := u.GetFeeBump() +func (u OperationResultTr) MustAccountMergeResult() AccountMergeResult { + val, ok := u.GetAccountMergeResult() if !ok { - panic("arm FeeBump is not set") + panic("arm AccountMergeResult is not set") } return val } -// GetFeeBump retrieves the FeeBump value from the union, +// GetAccountMergeResult retrieves the AccountMergeResult value from the union, // returning ok if the union's switch indicated the value is valid. -func (u TransactionEnvelope) GetFeeBump() (result FeeBumpTransactionEnvelope, ok bool) { +func (u OperationResultTr) GetAccountMergeResult() (result AccountMergeResult, ok bool) { armName, _ := u.ArmForSwitch(int32(u.Type)) - if armName == "FeeBump" { - result = *u.FeeBump + if armName == "AccountMergeResult" { + result = *u.AccountMergeResult ok = true } return } -// EncodeTo encodes this value using the Encoder. -func (u TransactionEnvelope) EncodeTo(e *xdr.Encoder) error { - var err error - if err = u.Type.EncodeTo(e); err != nil { - return err - } - switch EnvelopeType(u.Type) { - case EnvelopeTypeEnvelopeTypeTxV0: - if err = (*u.V0).EncodeTo(e); err != nil { - return err - } - return nil - case EnvelopeTypeEnvelopeTypeTx: - if err = (*u.V1).EncodeTo(e); err != nil { - return err - } - return nil - case EnvelopeTypeEnvelopeTypeTxFeeBump: - if err = (*u.FeeBump).EncodeTo(e); err != nil { - return err - } - return nil - } - return fmt.Errorf("Type (EnvelopeType) switch value '%d' is not valid for union TransactionEnvelope", u.Type) -} - -var _ decoderFrom = (*TransactionEnvelope)(nil) +// MustInflationResult retrieves the InflationResult value from the union, +// panicing if the value is not set. +func (u OperationResultTr) MustInflationResult() InflationResult { + val, ok := u.GetInflationResult() -// DecodeFrom decodes this value using the Decoder. -func (u *TransactionEnvelope) DecodeFrom(d *xdr.Decoder) (int, error) { - var err error - var n, nTmp int - nTmp, err = u.Type.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding EnvelopeType: %s", err) - } - switch EnvelopeType(u.Type) { - case EnvelopeTypeEnvelopeTypeTxV0: - u.V0 = new(TransactionV0Envelope) - nTmp, err = (*u.V0).DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding TransactionV0Envelope: %s", err) - } - return n, nil - case EnvelopeTypeEnvelopeTypeTx: - u.V1 = new(TransactionV1Envelope) - nTmp, err = (*u.V1).DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding TransactionV1Envelope: %s", err) - } - return n, nil - case EnvelopeTypeEnvelopeTypeTxFeeBump: - u.FeeBump = new(FeeBumpTransactionEnvelope) - nTmp, err = (*u.FeeBump).DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding FeeBumpTransactionEnvelope: %s", err) - } - return n, nil + if !ok { + panic("arm InflationResult is not set") } - return n, fmt.Errorf("union TransactionEnvelope has invalid Type (EnvelopeType) switch value '%d'", u.Type) -} - -// MarshalBinary implements encoding.BinaryMarshaler. -func (s TransactionEnvelope) MarshalBinary() ([]byte, error) { - b := bytes.Buffer{} - e := xdr.NewEncoder(&b) - err := s.EncodeTo(e) - return b.Bytes(), err -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *TransactionEnvelope) UnmarshalBinary(inp []byte) error { - r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) - return err -} - -var ( - _ encoding.BinaryMarshaler = (*TransactionEnvelope)(nil) - _ encoding.BinaryUnmarshaler = (*TransactionEnvelope)(nil) -) - -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s TransactionEnvelope) xdrType() {} -var _ xdrType = (*TransactionEnvelope)(nil) - -// TransactionSignaturePayloadTaggedTransaction is an XDR NestedUnion defines as: -// -// union switch (EnvelopeType type) -// { -// // Backwards Compatibility: Use ENVELOPE_TYPE_TX to sign ENVELOPE_TYPE_TX_V0 -// case ENVELOPE_TYPE_TX: -// Transaction tx; -// case ENVELOPE_TYPE_TX_FEE_BUMP: -// FeeBumpTransaction feeBump; -// } -type TransactionSignaturePayloadTaggedTransaction struct { - Type EnvelopeType - Tx *Transaction - FeeBump *FeeBumpTransaction + return val } -// SwitchFieldName returns the field name in which this union's -// discriminant is stored -func (u TransactionSignaturePayloadTaggedTransaction) SwitchFieldName() string { - return "Type" -} +// GetInflationResult retrieves the InflationResult value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u OperationResultTr) GetInflationResult() (result InflationResult, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) -// ArmForSwitch returns which field name should be used for storing -// the value for an instance of TransactionSignaturePayloadTaggedTransaction -func (u TransactionSignaturePayloadTaggedTransaction) ArmForSwitch(sw int32) (string, bool) { - switch EnvelopeType(sw) { - case EnvelopeTypeEnvelopeTypeTx: - return "Tx", true - case EnvelopeTypeEnvelopeTypeTxFeeBump: - return "FeeBump", true + if armName == "InflationResult" { + result = *u.InflationResult + ok = true } - return "-", false -} -// NewTransactionSignaturePayloadTaggedTransaction creates a new TransactionSignaturePayloadTaggedTransaction. -func NewTransactionSignaturePayloadTaggedTransaction(aType EnvelopeType, value interface{}) (result TransactionSignaturePayloadTaggedTransaction, err error) { - result.Type = aType - switch EnvelopeType(aType) { - case EnvelopeTypeEnvelopeTypeTx: - tv, ok := value.(Transaction) - if !ok { - err = fmt.Errorf("invalid value, must be Transaction") - return - } - result.Tx = &tv - case EnvelopeTypeEnvelopeTypeTxFeeBump: - tv, ok := value.(FeeBumpTransaction) - if !ok { - err = fmt.Errorf("invalid value, must be FeeBumpTransaction") - return - } - result.FeeBump = &tv - } return } -// MustTx retrieves the Tx value from the union, +// MustManageDataResult retrieves the ManageDataResult value from the union, // panicing if the value is not set. -func (u TransactionSignaturePayloadTaggedTransaction) MustTx() Transaction { - val, ok := u.GetTx() +func (u OperationResultTr) MustManageDataResult() ManageDataResult { + val, ok := u.GetManageDataResult() if !ok { - panic("arm Tx is not set") + panic("arm ManageDataResult is not set") } return val } -// GetTx retrieves the Tx value from the union, +// GetManageDataResult retrieves the ManageDataResult value from the union, // returning ok if the union's switch indicated the value is valid. -func (u TransactionSignaturePayloadTaggedTransaction) GetTx() (result Transaction, ok bool) { +func (u OperationResultTr) GetManageDataResult() (result ManageDataResult, ok bool) { armName, _ := u.ArmForSwitch(int32(u.Type)) - if armName == "Tx" { - result = *u.Tx + if armName == "ManageDataResult" { + result = *u.ManageDataResult ok = true } return } -// MustFeeBump retrieves the FeeBump value from the union, +// MustBumpSeqResult retrieves the BumpSeqResult value from the union, // panicing if the value is not set. -func (u TransactionSignaturePayloadTaggedTransaction) MustFeeBump() FeeBumpTransaction { - val, ok := u.GetFeeBump() +func (u OperationResultTr) MustBumpSeqResult() BumpSequenceResult { + val, ok := u.GetBumpSeqResult() if !ok { - panic("arm FeeBump is not set") + panic("arm BumpSeqResult is not set") } return val } -// GetFeeBump retrieves the FeeBump value from the union, +// GetBumpSeqResult retrieves the BumpSeqResult value from the union, // returning ok if the union's switch indicated the value is valid. -func (u TransactionSignaturePayloadTaggedTransaction) GetFeeBump() (result FeeBumpTransaction, ok bool) { +func (u OperationResultTr) GetBumpSeqResult() (result BumpSequenceResult, ok bool) { armName, _ := u.ArmForSwitch(int32(u.Type)) - if armName == "FeeBump" { - result = *u.FeeBump + if armName == "BumpSeqResult" { + result = *u.BumpSeqResult ok = true } return } -// EncodeTo encodes this value using the Encoder. -func (u TransactionSignaturePayloadTaggedTransaction) EncodeTo(e *xdr.Encoder) error { - var err error - if err = u.Type.EncodeTo(e); err != nil { - return err - } - switch EnvelopeType(u.Type) { - case EnvelopeTypeEnvelopeTypeTx: - if err = (*u.Tx).EncodeTo(e); err != nil { - return err - } - return nil - case EnvelopeTypeEnvelopeTypeTxFeeBump: - if err = (*u.FeeBump).EncodeTo(e); err != nil { - return err - } - return nil - } - return fmt.Errorf("Type (EnvelopeType) switch value '%d' is not valid for union TransactionSignaturePayloadTaggedTransaction", u.Type) -} - -var _ decoderFrom = (*TransactionSignaturePayloadTaggedTransaction)(nil) +// MustManageBuyOfferResult retrieves the ManageBuyOfferResult value from the union, +// panicing if the value is not set. +func (u OperationResultTr) MustManageBuyOfferResult() ManageBuyOfferResult { + val, ok := u.GetManageBuyOfferResult() -// DecodeFrom decodes this value using the Decoder. -func (u *TransactionSignaturePayloadTaggedTransaction) DecodeFrom(d *xdr.Decoder) (int, error) { - var err error - var n, nTmp int - nTmp, err = u.Type.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding EnvelopeType: %s", err) - } - switch EnvelopeType(u.Type) { - case EnvelopeTypeEnvelopeTypeTx: - u.Tx = new(Transaction) - nTmp, err = (*u.Tx).DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Transaction: %s", err) - } - return n, nil - case EnvelopeTypeEnvelopeTypeTxFeeBump: - u.FeeBump = new(FeeBumpTransaction) - nTmp, err = (*u.FeeBump).DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding FeeBumpTransaction: %s", err) - } - return n, nil + if !ok { + panic("arm ManageBuyOfferResult is not set") } - return n, fmt.Errorf("union TransactionSignaturePayloadTaggedTransaction has invalid Type (EnvelopeType) switch value '%d'", u.Type) -} - -// MarshalBinary implements encoding.BinaryMarshaler. -func (s TransactionSignaturePayloadTaggedTransaction) MarshalBinary() ([]byte, error) { - b := bytes.Buffer{} - e := xdr.NewEncoder(&b) - err := s.EncodeTo(e) - return b.Bytes(), err -} -// UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *TransactionSignaturePayloadTaggedTransaction) UnmarshalBinary(inp []byte) error { - r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) - return err + return val } -var ( - _ encoding.BinaryMarshaler = (*TransactionSignaturePayloadTaggedTransaction)(nil) - _ encoding.BinaryUnmarshaler = (*TransactionSignaturePayloadTaggedTransaction)(nil) -) - -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s TransactionSignaturePayloadTaggedTransaction) xdrType() {} - -var _ xdrType = (*TransactionSignaturePayloadTaggedTransaction)(nil) - -// TransactionSignaturePayload is an XDR Struct defines as: -// -// struct TransactionSignaturePayload -// { -// Hash networkId; -// union switch (EnvelopeType type) -// { -// // Backwards Compatibility: Use ENVELOPE_TYPE_TX to sign ENVELOPE_TYPE_TX_V0 -// case ENVELOPE_TYPE_TX: -// Transaction tx; -// case ENVELOPE_TYPE_TX_FEE_BUMP: -// FeeBumpTransaction feeBump; -// } -// taggedTransaction; -// }; -type TransactionSignaturePayload struct { - NetworkId Hash - TaggedTransaction TransactionSignaturePayloadTaggedTransaction -} +// GetManageBuyOfferResult retrieves the ManageBuyOfferResult value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u OperationResultTr) GetManageBuyOfferResult() (result ManageBuyOfferResult, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) -// EncodeTo encodes this value using the Encoder. -func (s *TransactionSignaturePayload) EncodeTo(e *xdr.Encoder) error { - var err error - if err = s.NetworkId.EncodeTo(e); err != nil { - return err - } - if err = s.TaggedTransaction.EncodeTo(e); err != nil { - return err + if armName == "ManageBuyOfferResult" { + result = *u.ManageBuyOfferResult + ok = true } - return nil + + return } -var _ decoderFrom = (*TransactionSignaturePayload)(nil) +// MustPathPaymentStrictSendResult retrieves the PathPaymentStrictSendResult value from the union, +// panicing if the value is not set. +func (u OperationResultTr) MustPathPaymentStrictSendResult() PathPaymentStrictSendResult { + val, ok := u.GetPathPaymentStrictSendResult() -// DecodeFrom decodes this value using the Decoder. -func (s *TransactionSignaturePayload) DecodeFrom(d *xdr.Decoder) (int, error) { - var err error - var n, nTmp int - nTmp, err = s.NetworkId.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Hash: %s", err) - } - nTmp, err = s.TaggedTransaction.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding TransactionSignaturePayloadTaggedTransaction: %s", err) + if !ok { + panic("arm PathPaymentStrictSendResult is not set") } - return n, nil -} - -// MarshalBinary implements encoding.BinaryMarshaler. -func (s TransactionSignaturePayload) MarshalBinary() ([]byte, error) { - b := bytes.Buffer{} - e := xdr.NewEncoder(&b) - err := s.EncodeTo(e) - return b.Bytes(), err -} -// UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *TransactionSignaturePayload) UnmarshalBinary(inp []byte) error { - r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) - return err + return val } -var ( - _ encoding.BinaryMarshaler = (*TransactionSignaturePayload)(nil) - _ encoding.BinaryUnmarshaler = (*TransactionSignaturePayload)(nil) -) - -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s TransactionSignaturePayload) xdrType() {} +// GetPathPaymentStrictSendResult retrieves the PathPaymentStrictSendResult value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u OperationResultTr) GetPathPaymentStrictSendResult() (result PathPaymentStrictSendResult, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) -var _ xdrType = (*TransactionSignaturePayload)(nil) + if armName == "PathPaymentStrictSendResult" { + result = *u.PathPaymentStrictSendResult + ok = true + } -// ClaimAtomType is an XDR Enum defines as: -// -// enum ClaimAtomType -// { -// CLAIM_ATOM_TYPE_V0 = 0, -// CLAIM_ATOM_TYPE_ORDER_BOOK = 1, -// CLAIM_ATOM_TYPE_LIQUIDITY_POOL = 2 -// }; -type ClaimAtomType int32 + return +} -const ( - ClaimAtomTypeClaimAtomTypeV0 ClaimAtomType = 0 - ClaimAtomTypeClaimAtomTypeOrderBook ClaimAtomType = 1 - ClaimAtomTypeClaimAtomTypeLiquidityPool ClaimAtomType = 2 -) +// MustCreateClaimableBalanceResult retrieves the CreateClaimableBalanceResult value from the union, +// panicing if the value is not set. +func (u OperationResultTr) MustCreateClaimableBalanceResult() CreateClaimableBalanceResult { + val, ok := u.GetCreateClaimableBalanceResult() -var claimAtomTypeMap = map[int32]string{ - 0: "ClaimAtomTypeClaimAtomTypeV0", - 1: "ClaimAtomTypeClaimAtomTypeOrderBook", - 2: "ClaimAtomTypeClaimAtomTypeLiquidityPool", -} + if !ok { + panic("arm CreateClaimableBalanceResult is not set") + } -// ValidEnum validates a proposed value for this enum. Implements -// the Enum interface for ClaimAtomType -func (e ClaimAtomType) ValidEnum(v int32) bool { - _, ok := claimAtomTypeMap[v] - return ok + return val } -// String returns the name of `e` -func (e ClaimAtomType) String() string { - name, _ := claimAtomTypeMap[int32(e)] - return name -} +// GetCreateClaimableBalanceResult retrieves the CreateClaimableBalanceResult value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u OperationResultTr) GetCreateClaimableBalanceResult() (result CreateClaimableBalanceResult, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) -// EncodeTo encodes this value using the Encoder. -func (e ClaimAtomType) EncodeTo(enc *xdr.Encoder) error { - if _, ok := claimAtomTypeMap[int32(e)]; !ok { - return fmt.Errorf("'%d' is not a valid ClaimAtomType enum value", e) + if armName == "CreateClaimableBalanceResult" { + result = *u.CreateClaimableBalanceResult + ok = true } - _, err := enc.EncodeInt(int32(e)) - return err + + return } -var _ decoderFrom = (*ClaimAtomType)(nil) +// MustClaimClaimableBalanceResult retrieves the ClaimClaimableBalanceResult value from the union, +// panicing if the value is not set. +func (u OperationResultTr) MustClaimClaimableBalanceResult() ClaimClaimableBalanceResult { + val, ok := u.GetClaimClaimableBalanceResult() -// DecodeFrom decodes this value using the Decoder. -func (e *ClaimAtomType) DecodeFrom(d *xdr.Decoder) (int, error) { - v, n, err := d.DecodeInt() - if err != nil { - return n, fmt.Errorf("decoding ClaimAtomType: %s", err) - } - if _, ok := claimAtomTypeMap[v]; !ok { - return n, fmt.Errorf("'%d' is not a valid ClaimAtomType enum value", v) + if !ok { + panic("arm ClaimClaimableBalanceResult is not set") } - *e = ClaimAtomType(v) - return n, nil -} - -// MarshalBinary implements encoding.BinaryMarshaler. -func (s ClaimAtomType) MarshalBinary() ([]byte, error) { - b := bytes.Buffer{} - e := xdr.NewEncoder(&b) - err := s.EncodeTo(e) - return b.Bytes(), err -} -// UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *ClaimAtomType) UnmarshalBinary(inp []byte) error { - r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) - return err + return val } -var ( - _ encoding.BinaryMarshaler = (*ClaimAtomType)(nil) - _ encoding.BinaryUnmarshaler = (*ClaimAtomType)(nil) -) - -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s ClaimAtomType) xdrType() {} +// GetClaimClaimableBalanceResult retrieves the ClaimClaimableBalanceResult value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u OperationResultTr) GetClaimClaimableBalanceResult() (result ClaimClaimableBalanceResult, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) -var _ xdrType = (*ClaimAtomType)(nil) + if armName == "ClaimClaimableBalanceResult" { + result = *u.ClaimClaimableBalanceResult + ok = true + } -// ClaimOfferAtomV0 is an XDR Struct defines as: -// -// struct ClaimOfferAtomV0 -// { -// // emitted to identify the offer -// uint256 sellerEd25519; // Account that owns the offer -// int64 offerID; -// -// // amount and asset taken from the owner -// Asset assetSold; -// int64 amountSold; -// -// // amount and asset sent to the owner -// Asset assetBought; -// int64 amountBought; -// }; -type ClaimOfferAtomV0 struct { - SellerEd25519 Uint256 - OfferId Int64 - AssetSold Asset - AmountSold Int64 - AssetBought Asset - AmountBought Int64 + return } -// EncodeTo encodes this value using the Encoder. -func (s *ClaimOfferAtomV0) EncodeTo(e *xdr.Encoder) error { - var err error - if err = s.SellerEd25519.EncodeTo(e); err != nil { - return err - } - if err = s.OfferId.EncodeTo(e); err != nil { - return err - } - if err = s.AssetSold.EncodeTo(e); err != nil { - return err - } - if err = s.AmountSold.EncodeTo(e); err != nil { - return err - } - if err = s.AssetBought.EncodeTo(e); err != nil { - return err - } - if err = s.AmountBought.EncodeTo(e); err != nil { - return err +// MustBeginSponsoringFutureReservesResult retrieves the BeginSponsoringFutureReservesResult value from the union, +// panicing if the value is not set. +func (u OperationResultTr) MustBeginSponsoringFutureReservesResult() BeginSponsoringFutureReservesResult { + val, ok := u.GetBeginSponsoringFutureReservesResult() + + if !ok { + panic("arm BeginSponsoringFutureReservesResult is not set") } - return nil + + return val } -var _ decoderFrom = (*ClaimOfferAtomV0)(nil) +// GetBeginSponsoringFutureReservesResult retrieves the BeginSponsoringFutureReservesResult value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u OperationResultTr) GetBeginSponsoringFutureReservesResult() (result BeginSponsoringFutureReservesResult, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) -// DecodeFrom decodes this value using the Decoder. -func (s *ClaimOfferAtomV0) DecodeFrom(d *xdr.Decoder) (int, error) { - var err error - var n, nTmp int - nTmp, err = s.SellerEd25519.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Uint256: %s", err) - } - nTmp, err = s.OfferId.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Int64: %s", err) - } - nTmp, err = s.AssetSold.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Asset: %s", err) - } - nTmp, err = s.AmountSold.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Int64: %s", err) - } - nTmp, err = s.AssetBought.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Asset: %s", err) - } - nTmp, err = s.AmountBought.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Int64: %s", err) + if armName == "BeginSponsoringFutureReservesResult" { + result = *u.BeginSponsoringFutureReservesResult + ok = true } - return n, nil -} -// MarshalBinary implements encoding.BinaryMarshaler. -func (s ClaimOfferAtomV0) MarshalBinary() ([]byte, error) { - b := bytes.Buffer{} - e := xdr.NewEncoder(&b) - err := s.EncodeTo(e) - return b.Bytes(), err + return } -// UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *ClaimOfferAtomV0) UnmarshalBinary(inp []byte) error { - r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) - return err -} +// MustEndSponsoringFutureReservesResult retrieves the EndSponsoringFutureReservesResult value from the union, +// panicing if the value is not set. +func (u OperationResultTr) MustEndSponsoringFutureReservesResult() EndSponsoringFutureReservesResult { + val, ok := u.GetEndSponsoringFutureReservesResult() -var ( - _ encoding.BinaryMarshaler = (*ClaimOfferAtomV0)(nil) - _ encoding.BinaryUnmarshaler = (*ClaimOfferAtomV0)(nil) -) + if !ok { + panic("arm EndSponsoringFutureReservesResult is not set") + } -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s ClaimOfferAtomV0) xdrType() {} + return val +} -var _ xdrType = (*ClaimOfferAtomV0)(nil) +// GetEndSponsoringFutureReservesResult retrieves the EndSponsoringFutureReservesResult value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u OperationResultTr) GetEndSponsoringFutureReservesResult() (result EndSponsoringFutureReservesResult, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) -// ClaimOfferAtom is an XDR Struct defines as: -// -// struct ClaimOfferAtom -// { -// // emitted to identify the offer -// AccountID sellerID; // Account that owns the offer -// int64 offerID; -// -// // amount and asset taken from the owner -// Asset assetSold; -// int64 amountSold; -// -// // amount and asset sent to the owner -// Asset assetBought; -// int64 amountBought; -// }; -type ClaimOfferAtom struct { - SellerId AccountId - OfferId Int64 - AssetSold Asset - AmountSold Int64 - AssetBought Asset - AmountBought Int64 + if armName == "EndSponsoringFutureReservesResult" { + result = *u.EndSponsoringFutureReservesResult + ok = true + } + + return } -// EncodeTo encodes this value using the Encoder. -func (s *ClaimOfferAtom) EncodeTo(e *xdr.Encoder) error { - var err error - if err = s.SellerId.EncodeTo(e); err != nil { - return err - } - if err = s.OfferId.EncodeTo(e); err != nil { - return err - } - if err = s.AssetSold.EncodeTo(e); err != nil { - return err - } - if err = s.AmountSold.EncodeTo(e); err != nil { - return err - } - if err = s.AssetBought.EncodeTo(e); err != nil { - return err - } - if err = s.AmountBought.EncodeTo(e); err != nil { - return err +// MustRevokeSponsorshipResult retrieves the RevokeSponsorshipResult value from the union, +// panicing if the value is not set. +func (u OperationResultTr) MustRevokeSponsorshipResult() RevokeSponsorshipResult { + val, ok := u.GetRevokeSponsorshipResult() + + if !ok { + panic("arm RevokeSponsorshipResult is not set") } - return nil + + return val } -var _ decoderFrom = (*ClaimOfferAtom)(nil) +// GetRevokeSponsorshipResult retrieves the RevokeSponsorshipResult value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u OperationResultTr) GetRevokeSponsorshipResult() (result RevokeSponsorshipResult, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) -// DecodeFrom decodes this value using the Decoder. -func (s *ClaimOfferAtom) DecodeFrom(d *xdr.Decoder) (int, error) { - var err error - var n, nTmp int - nTmp, err = s.SellerId.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding AccountId: %s", err) - } - nTmp, err = s.OfferId.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Int64: %s", err) - } - nTmp, err = s.AssetSold.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Asset: %s", err) - } - nTmp, err = s.AmountSold.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Int64: %s", err) - } - nTmp, err = s.AssetBought.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Asset: %s", err) - } - nTmp, err = s.AmountBought.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Int64: %s", err) + if armName == "RevokeSponsorshipResult" { + result = *u.RevokeSponsorshipResult + ok = true } - return n, nil -} -// MarshalBinary implements encoding.BinaryMarshaler. -func (s ClaimOfferAtom) MarshalBinary() ([]byte, error) { - b := bytes.Buffer{} - e := xdr.NewEncoder(&b) - err := s.EncodeTo(e) - return b.Bytes(), err + return } -// UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *ClaimOfferAtom) UnmarshalBinary(inp []byte) error { - r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) - return err -} +// MustClawbackResult retrieves the ClawbackResult value from the union, +// panicing if the value is not set. +func (u OperationResultTr) MustClawbackResult() ClawbackResult { + val, ok := u.GetClawbackResult() -var ( - _ encoding.BinaryMarshaler = (*ClaimOfferAtom)(nil) - _ encoding.BinaryUnmarshaler = (*ClaimOfferAtom)(nil) -) + if !ok { + panic("arm ClawbackResult is not set") + } -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s ClaimOfferAtom) xdrType() {} + return val +} -var _ xdrType = (*ClaimOfferAtom)(nil) +// GetClawbackResult retrieves the ClawbackResult value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u OperationResultTr) GetClawbackResult() (result ClawbackResult, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) -// ClaimLiquidityAtom is an XDR Struct defines as: -// -// struct ClaimLiquidityAtom -// { -// PoolID liquidityPoolID; -// -// // amount and asset taken from the pool -// Asset assetSold; -// int64 amountSold; -// -// // amount and asset sent to the pool -// Asset assetBought; -// int64 amountBought; -// }; -type ClaimLiquidityAtom struct { - LiquidityPoolId PoolId - AssetSold Asset - AmountSold Int64 - AssetBought Asset - AmountBought Int64 + if armName == "ClawbackResult" { + result = *u.ClawbackResult + ok = true + } + + return } -// EncodeTo encodes this value using the Encoder. -func (s *ClaimLiquidityAtom) EncodeTo(e *xdr.Encoder) error { - var err error - if err = s.LiquidityPoolId.EncodeTo(e); err != nil { - return err - } - if err = s.AssetSold.EncodeTo(e); err != nil { - return err - } - if err = s.AmountSold.EncodeTo(e); err != nil { - return err - } - if err = s.AssetBought.EncodeTo(e); err != nil { - return err - } - if err = s.AmountBought.EncodeTo(e); err != nil { - return err +// MustClawbackClaimableBalanceResult retrieves the ClawbackClaimableBalanceResult value from the union, +// panicing if the value is not set. +func (u OperationResultTr) MustClawbackClaimableBalanceResult() ClawbackClaimableBalanceResult { + val, ok := u.GetClawbackClaimableBalanceResult() + + if !ok { + panic("arm ClawbackClaimableBalanceResult is not set") } - return nil + + return val } -var _ decoderFrom = (*ClaimLiquidityAtom)(nil) +// GetClawbackClaimableBalanceResult retrieves the ClawbackClaimableBalanceResult value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u OperationResultTr) GetClawbackClaimableBalanceResult() (result ClawbackClaimableBalanceResult, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) -// DecodeFrom decodes this value using the Decoder. -func (s *ClaimLiquidityAtom) DecodeFrom(d *xdr.Decoder) (int, error) { - var err error - var n, nTmp int - nTmp, err = s.LiquidityPoolId.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding PoolId: %s", err) - } - nTmp, err = s.AssetSold.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Asset: %s", err) - } - nTmp, err = s.AmountSold.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Int64: %s", err) - } - nTmp, err = s.AssetBought.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Asset: %s", err) - } - nTmp, err = s.AmountBought.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Int64: %s", err) + if armName == "ClawbackClaimableBalanceResult" { + result = *u.ClawbackClaimableBalanceResult + ok = true } - return n, nil -} -// MarshalBinary implements encoding.BinaryMarshaler. -func (s ClaimLiquidityAtom) MarshalBinary() ([]byte, error) { - b := bytes.Buffer{} - e := xdr.NewEncoder(&b) - err := s.EncodeTo(e) - return b.Bytes(), err + return } -// UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *ClaimLiquidityAtom) UnmarshalBinary(inp []byte) error { - r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) - return err +// MustSetTrustLineFlagsResult retrieves the SetTrustLineFlagsResult value from the union, +// panicing if the value is not set. +func (u OperationResultTr) MustSetTrustLineFlagsResult() SetTrustLineFlagsResult { + val, ok := u.GetSetTrustLineFlagsResult() + + if !ok { + panic("arm SetTrustLineFlagsResult is not set") + } + + return val } -var ( - _ encoding.BinaryMarshaler = (*ClaimLiquidityAtom)(nil) - _ encoding.BinaryUnmarshaler = (*ClaimLiquidityAtom)(nil) -) +// GetSetTrustLineFlagsResult retrieves the SetTrustLineFlagsResult value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u OperationResultTr) GetSetTrustLineFlagsResult() (result SetTrustLineFlagsResult, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s ClaimLiquidityAtom) xdrType() {} + if armName == "SetTrustLineFlagsResult" { + result = *u.SetTrustLineFlagsResult + ok = true + } -var _ xdrType = (*ClaimLiquidityAtom)(nil) + return +} -// ClaimAtom is an XDR Union defines as: -// -// union ClaimAtom switch (ClaimAtomType type) -// { -// case CLAIM_ATOM_TYPE_V0: -// ClaimOfferAtomV0 v0; -// case CLAIM_ATOM_TYPE_ORDER_BOOK: -// ClaimOfferAtom orderBook; -// case CLAIM_ATOM_TYPE_LIQUIDITY_POOL: -// ClaimLiquidityAtom liquidityPool; -// }; -type ClaimAtom struct { - Type ClaimAtomType - V0 *ClaimOfferAtomV0 - OrderBook *ClaimOfferAtom - LiquidityPool *ClaimLiquidityAtom +// MustLiquidityPoolDepositResult retrieves the LiquidityPoolDepositResult value from the union, +// panicing if the value is not set. +func (u OperationResultTr) MustLiquidityPoolDepositResult() LiquidityPoolDepositResult { + val, ok := u.GetLiquidityPoolDepositResult() + + if !ok { + panic("arm LiquidityPoolDepositResult is not set") + } + + return val } -// SwitchFieldName returns the field name in which this union's -// discriminant is stored -func (u ClaimAtom) SwitchFieldName() string { - return "Type" +// GetLiquidityPoolDepositResult retrieves the LiquidityPoolDepositResult value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u OperationResultTr) GetLiquidityPoolDepositResult() (result LiquidityPoolDepositResult, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) + + if armName == "LiquidityPoolDepositResult" { + result = *u.LiquidityPoolDepositResult + ok = true + } + + return } -// ArmForSwitch returns which field name should be used for storing -// the value for an instance of ClaimAtom -func (u ClaimAtom) ArmForSwitch(sw int32) (string, bool) { - switch ClaimAtomType(sw) { - case ClaimAtomTypeClaimAtomTypeV0: - return "V0", true - case ClaimAtomTypeClaimAtomTypeOrderBook: - return "OrderBook", true - case ClaimAtomTypeClaimAtomTypeLiquidityPool: - return "LiquidityPool", true +// MustLiquidityPoolWithdrawResult retrieves the LiquidityPoolWithdrawResult value from the union, +// panicing if the value is not set. +func (u OperationResultTr) MustLiquidityPoolWithdrawResult() LiquidityPoolWithdrawResult { + val, ok := u.GetLiquidityPoolWithdrawResult() + + if !ok { + panic("arm LiquidityPoolWithdrawResult is not set") } - return "-", false + + return val } -// NewClaimAtom creates a new ClaimAtom. -func NewClaimAtom(aType ClaimAtomType, value interface{}) (result ClaimAtom, err error) { - result.Type = aType - switch ClaimAtomType(aType) { - case ClaimAtomTypeClaimAtomTypeV0: - tv, ok := value.(ClaimOfferAtomV0) - if !ok { - err = fmt.Errorf("invalid value, must be ClaimOfferAtomV0") - return - } - result.V0 = &tv - case ClaimAtomTypeClaimAtomTypeOrderBook: - tv, ok := value.(ClaimOfferAtom) - if !ok { - err = fmt.Errorf("invalid value, must be ClaimOfferAtom") - return - } - result.OrderBook = &tv - case ClaimAtomTypeClaimAtomTypeLiquidityPool: - tv, ok := value.(ClaimLiquidityAtom) - if !ok { - err = fmt.Errorf("invalid value, must be ClaimLiquidityAtom") - return - } - result.LiquidityPool = &tv +// GetLiquidityPoolWithdrawResult retrieves the LiquidityPoolWithdrawResult value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u OperationResultTr) GetLiquidityPoolWithdrawResult() (result LiquidityPoolWithdrawResult, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) + + if armName == "LiquidityPoolWithdrawResult" { + result = *u.LiquidityPoolWithdrawResult + ok = true } + return } -// MustV0 retrieves the V0 value from the union, +// MustInvokeHostFunctionResult retrieves the InvokeHostFunctionResult value from the union, // panicing if the value is not set. -func (u ClaimAtom) MustV0() ClaimOfferAtomV0 { - val, ok := u.GetV0() +func (u OperationResultTr) MustInvokeHostFunctionResult() InvokeHostFunctionResult { + val, ok := u.GetInvokeHostFunctionResult() if !ok { - panic("arm V0 is not set") + panic("arm InvokeHostFunctionResult is not set") } return val } -// GetV0 retrieves the V0 value from the union, +// GetInvokeHostFunctionResult retrieves the InvokeHostFunctionResult value from the union, // returning ok if the union's switch indicated the value is valid. -func (u ClaimAtom) GetV0() (result ClaimOfferAtomV0, ok bool) { +func (u OperationResultTr) GetInvokeHostFunctionResult() (result InvokeHostFunctionResult, ok bool) { armName, _ := u.ArmForSwitch(int32(u.Type)) - if armName == "V0" { - result = *u.V0 + if armName == "InvokeHostFunctionResult" { + result = *u.InvokeHostFunctionResult ok = true } return } -// MustOrderBook retrieves the OrderBook value from the union, +// MustExtendFootprintTtlResult retrieves the ExtendFootprintTtlResult value from the union, // panicing if the value is not set. -func (u ClaimAtom) MustOrderBook() ClaimOfferAtom { - val, ok := u.GetOrderBook() +func (u OperationResultTr) MustExtendFootprintTtlResult() ExtendFootprintTtlResult { + val, ok := u.GetExtendFootprintTtlResult() if !ok { - panic("arm OrderBook is not set") + panic("arm ExtendFootprintTtlResult is not set") } return val } -// GetOrderBook retrieves the OrderBook value from the union, +// GetExtendFootprintTtlResult retrieves the ExtendFootprintTtlResult value from the union, // returning ok if the union's switch indicated the value is valid. -func (u ClaimAtom) GetOrderBook() (result ClaimOfferAtom, ok bool) { +func (u OperationResultTr) GetExtendFootprintTtlResult() (result ExtendFootprintTtlResult, ok bool) { armName, _ := u.ArmForSwitch(int32(u.Type)) - if armName == "OrderBook" { - result = *u.OrderBook + if armName == "ExtendFootprintTtlResult" { + result = *u.ExtendFootprintTtlResult ok = true } return } -// MustLiquidityPool retrieves the LiquidityPool value from the union, +// MustRestoreFootprintResult retrieves the RestoreFootprintResult value from the union, // panicing if the value is not set. -func (u ClaimAtom) MustLiquidityPool() ClaimLiquidityAtom { - val, ok := u.GetLiquidityPool() +func (u OperationResultTr) MustRestoreFootprintResult() RestoreFootprintResult { + val, ok := u.GetRestoreFootprintResult() if !ok { - panic("arm LiquidityPool is not set") + panic("arm RestoreFootprintResult is not set") } return val } -// GetLiquidityPool retrieves the LiquidityPool value from the union, +// GetRestoreFootprintResult retrieves the RestoreFootprintResult value from the union, // returning ok if the union's switch indicated the value is valid. -func (u ClaimAtom) GetLiquidityPool() (result ClaimLiquidityAtom, ok bool) { +func (u OperationResultTr) GetRestoreFootprintResult() (result RestoreFootprintResult, ok bool) { armName, _ := u.ArmForSwitch(int32(u.Type)) - if armName == "LiquidityPool" { - result = *u.LiquidityPool + if armName == "RestoreFootprintResult" { + result = *u.RestoreFootprintResult ok = true } @@ -26141,169 +42515,389 @@ func (u ClaimAtom) GetLiquidityPool() (result ClaimLiquidityAtom, ok bool) { } // EncodeTo encodes this value using the Encoder. -func (u ClaimAtom) EncodeTo(e *xdr.Encoder) error { +func (u OperationResultTr) EncodeTo(e *xdr.Encoder) error { var err error if err = u.Type.EncodeTo(e); err != nil { return err } - switch ClaimAtomType(u.Type) { - case ClaimAtomTypeClaimAtomTypeV0: - if err = (*u.V0).EncodeTo(e); err != nil { + switch OperationType(u.Type) { + case OperationTypeCreateAccount: + if err = (*u.CreateAccountResult).EncodeTo(e); err != nil { + return err + } + return nil + case OperationTypePayment: + if err = (*u.PaymentResult).EncodeTo(e); err != nil { + return err + } + return nil + case OperationTypePathPaymentStrictReceive: + if err = (*u.PathPaymentStrictReceiveResult).EncodeTo(e); err != nil { + return err + } + return nil + case OperationTypeManageSellOffer: + if err = (*u.ManageSellOfferResult).EncodeTo(e); err != nil { + return err + } + return nil + case OperationTypeCreatePassiveSellOffer: + if err = (*u.CreatePassiveSellOfferResult).EncodeTo(e); err != nil { + return err + } + return nil + case OperationTypeSetOptions: + if err = (*u.SetOptionsResult).EncodeTo(e); err != nil { + return err + } + return nil + case OperationTypeChangeTrust: + if err = (*u.ChangeTrustResult).EncodeTo(e); err != nil { + return err + } + return nil + case OperationTypeAllowTrust: + if err = (*u.AllowTrustResult).EncodeTo(e); err != nil { + return err + } + return nil + case OperationTypeAccountMerge: + if err = (*u.AccountMergeResult).EncodeTo(e); err != nil { + return err + } + return nil + case OperationTypeInflation: + if err = (*u.InflationResult).EncodeTo(e); err != nil { + return err + } + return nil + case OperationTypeManageData: + if err = (*u.ManageDataResult).EncodeTo(e); err != nil { + return err + } + return nil + case OperationTypeBumpSequence: + if err = (*u.BumpSeqResult).EncodeTo(e); err != nil { + return err + } + return nil + case OperationTypeManageBuyOffer: + if err = (*u.ManageBuyOfferResult).EncodeTo(e); err != nil { + return err + } + return nil + case OperationTypePathPaymentStrictSend: + if err = (*u.PathPaymentStrictSendResult).EncodeTo(e); err != nil { + return err + } + return nil + case OperationTypeCreateClaimableBalance: + if err = (*u.CreateClaimableBalanceResult).EncodeTo(e); err != nil { + return err + } + return nil + case OperationTypeClaimClaimableBalance: + if err = (*u.ClaimClaimableBalanceResult).EncodeTo(e); err != nil { + return err + } + return nil + case OperationTypeBeginSponsoringFutureReserves: + if err = (*u.BeginSponsoringFutureReservesResult).EncodeTo(e); err != nil { + return err + } + return nil + case OperationTypeEndSponsoringFutureReserves: + if err = (*u.EndSponsoringFutureReservesResult).EncodeTo(e); err != nil { return err } return nil - case ClaimAtomTypeClaimAtomTypeOrderBook: - if err = (*u.OrderBook).EncodeTo(e); err != nil { + case OperationTypeRevokeSponsorship: + if err = (*u.RevokeSponsorshipResult).EncodeTo(e); err != nil { return err } return nil - case ClaimAtomTypeClaimAtomTypeLiquidityPool: - if err = (*u.LiquidityPool).EncodeTo(e); err != nil { + case OperationTypeClawback: + if err = (*u.ClawbackResult).EncodeTo(e); err != nil { + return err + } + return nil + case OperationTypeClawbackClaimableBalance: + if err = (*u.ClawbackClaimableBalanceResult).EncodeTo(e); err != nil { + return err + } + return nil + case OperationTypeSetTrustLineFlags: + if err = (*u.SetTrustLineFlagsResult).EncodeTo(e); err != nil { + return err + } + return nil + case OperationTypeLiquidityPoolDeposit: + if err = (*u.LiquidityPoolDepositResult).EncodeTo(e); err != nil { + return err + } + return nil + case OperationTypeLiquidityPoolWithdraw: + if err = (*u.LiquidityPoolWithdrawResult).EncodeTo(e); err != nil { + return err + } + return nil + case OperationTypeInvokeHostFunction: + if err = (*u.InvokeHostFunctionResult).EncodeTo(e); err != nil { + return err + } + return nil + case OperationTypeExtendFootprintTtl: + if err = (*u.ExtendFootprintTtlResult).EncodeTo(e); err != nil { + return err + } + return nil + case OperationTypeRestoreFootprint: + if err = (*u.RestoreFootprintResult).EncodeTo(e); err != nil { return err } return nil } - return fmt.Errorf("Type (ClaimAtomType) switch value '%d' is not valid for union ClaimAtom", u.Type) + return fmt.Errorf("Type (OperationType) switch value '%d' is not valid for union OperationResultTr", u.Type) } -var _ decoderFrom = (*ClaimAtom)(nil) +var _ decoderFrom = (*OperationResultTr)(nil) // DecodeFrom decodes this value using the Decoder. -func (u *ClaimAtom) DecodeFrom(d *xdr.Decoder) (int, error) { +func (u *OperationResultTr) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding OperationResultTr: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = u.Type.DecodeFrom(d) + nTmp, err = u.Type.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding ClaimAtomType: %s", err) + return n, fmt.Errorf("decoding OperationType: %w", err) } - switch ClaimAtomType(u.Type) { - case ClaimAtomTypeClaimAtomTypeV0: - u.V0 = new(ClaimOfferAtomV0) - nTmp, err = (*u.V0).DecodeFrom(d) + switch OperationType(u.Type) { + case OperationTypeCreateAccount: + u.CreateAccountResult = new(CreateAccountResult) + nTmp, err = (*u.CreateAccountResult).DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding ClaimOfferAtomV0: %s", err) + return n, fmt.Errorf("decoding CreateAccountResult: %w", err) } return n, nil - case ClaimAtomTypeClaimAtomTypeOrderBook: - u.OrderBook = new(ClaimOfferAtom) - nTmp, err = (*u.OrderBook).DecodeFrom(d) + case OperationTypePayment: + u.PaymentResult = new(PaymentResult) + nTmp, err = (*u.PaymentResult).DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding ClaimOfferAtom: %s", err) + return n, fmt.Errorf("decoding PaymentResult: %w", err) } return n, nil - case ClaimAtomTypeClaimAtomTypeLiquidityPool: - u.LiquidityPool = new(ClaimLiquidityAtom) - nTmp, err = (*u.LiquidityPool).DecodeFrom(d) + case OperationTypePathPaymentStrictReceive: + u.PathPaymentStrictReceiveResult = new(PathPaymentStrictReceiveResult) + nTmp, err = (*u.PathPaymentStrictReceiveResult).DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding ClaimLiquidityAtom: %s", err) + return n, fmt.Errorf("decoding PathPaymentStrictReceiveResult: %w", err) + } + return n, nil + case OperationTypeManageSellOffer: + u.ManageSellOfferResult = new(ManageSellOfferResult) + nTmp, err = (*u.ManageSellOfferResult).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ManageSellOfferResult: %w", err) + } + return n, nil + case OperationTypeCreatePassiveSellOffer: + u.CreatePassiveSellOfferResult = new(ManageSellOfferResult) + nTmp, err = (*u.CreatePassiveSellOfferResult).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ManageSellOfferResult: %w", err) + } + return n, nil + case OperationTypeSetOptions: + u.SetOptionsResult = new(SetOptionsResult) + nTmp, err = (*u.SetOptionsResult).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding SetOptionsResult: %w", err) + } + return n, nil + case OperationTypeChangeTrust: + u.ChangeTrustResult = new(ChangeTrustResult) + nTmp, err = (*u.ChangeTrustResult).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ChangeTrustResult: %w", err) + } + return n, nil + case OperationTypeAllowTrust: + u.AllowTrustResult = new(AllowTrustResult) + nTmp, err = (*u.AllowTrustResult).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding AllowTrustResult: %w", err) + } + return n, nil + case OperationTypeAccountMerge: + u.AccountMergeResult = new(AccountMergeResult) + nTmp, err = (*u.AccountMergeResult).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding AccountMergeResult: %w", err) + } + return n, nil + case OperationTypeInflation: + u.InflationResult = new(InflationResult) + nTmp, err = (*u.InflationResult).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding InflationResult: %w", err) + } + return n, nil + case OperationTypeManageData: + u.ManageDataResult = new(ManageDataResult) + nTmp, err = (*u.ManageDataResult).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ManageDataResult: %w", err) + } + return n, nil + case OperationTypeBumpSequence: + u.BumpSeqResult = new(BumpSequenceResult) + nTmp, err = (*u.BumpSeqResult).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding BumpSequenceResult: %w", err) + } + return n, nil + case OperationTypeManageBuyOffer: + u.ManageBuyOfferResult = new(ManageBuyOfferResult) + nTmp, err = (*u.ManageBuyOfferResult).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ManageBuyOfferResult: %w", err) + } + return n, nil + case OperationTypePathPaymentStrictSend: + u.PathPaymentStrictSendResult = new(PathPaymentStrictSendResult) + nTmp, err = (*u.PathPaymentStrictSendResult).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding PathPaymentStrictSendResult: %w", err) + } + return n, nil + case OperationTypeCreateClaimableBalance: + u.CreateClaimableBalanceResult = new(CreateClaimableBalanceResult) + nTmp, err = (*u.CreateClaimableBalanceResult).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding CreateClaimableBalanceResult: %w", err) + } + return n, nil + case OperationTypeClaimClaimableBalance: + u.ClaimClaimableBalanceResult = new(ClaimClaimableBalanceResult) + nTmp, err = (*u.ClaimClaimableBalanceResult).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ClaimClaimableBalanceResult: %w", err) + } + return n, nil + case OperationTypeBeginSponsoringFutureReserves: + u.BeginSponsoringFutureReservesResult = new(BeginSponsoringFutureReservesResult) + nTmp, err = (*u.BeginSponsoringFutureReservesResult).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding BeginSponsoringFutureReservesResult: %w", err) + } + return n, nil + case OperationTypeEndSponsoringFutureReserves: + u.EndSponsoringFutureReservesResult = new(EndSponsoringFutureReservesResult) + nTmp, err = (*u.EndSponsoringFutureReservesResult).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding EndSponsoringFutureReservesResult: %w", err) + } + return n, nil + case OperationTypeRevokeSponsorship: + u.RevokeSponsorshipResult = new(RevokeSponsorshipResult) + nTmp, err = (*u.RevokeSponsorshipResult).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding RevokeSponsorshipResult: %w", err) + } + return n, nil + case OperationTypeClawback: + u.ClawbackResult = new(ClawbackResult) + nTmp, err = (*u.ClawbackResult).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ClawbackResult: %w", err) + } + return n, nil + case OperationTypeClawbackClaimableBalance: + u.ClawbackClaimableBalanceResult = new(ClawbackClaimableBalanceResult) + nTmp, err = (*u.ClawbackClaimableBalanceResult).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ClawbackClaimableBalanceResult: %w", err) + } + return n, nil + case OperationTypeSetTrustLineFlags: + u.SetTrustLineFlagsResult = new(SetTrustLineFlagsResult) + nTmp, err = (*u.SetTrustLineFlagsResult).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding SetTrustLineFlagsResult: %w", err) + } + return n, nil + case OperationTypeLiquidityPoolDeposit: + u.LiquidityPoolDepositResult = new(LiquidityPoolDepositResult) + nTmp, err = (*u.LiquidityPoolDepositResult).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding LiquidityPoolDepositResult: %w", err) + } + return n, nil + case OperationTypeLiquidityPoolWithdraw: + u.LiquidityPoolWithdrawResult = new(LiquidityPoolWithdrawResult) + nTmp, err = (*u.LiquidityPoolWithdrawResult).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding LiquidityPoolWithdrawResult: %w", err) + } + return n, nil + case OperationTypeInvokeHostFunction: + u.InvokeHostFunctionResult = new(InvokeHostFunctionResult) + nTmp, err = (*u.InvokeHostFunctionResult).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding InvokeHostFunctionResult: %w", err) + } + return n, nil + case OperationTypeExtendFootprintTtl: + u.ExtendFootprintTtlResult = new(ExtendFootprintTtlResult) + nTmp, err = (*u.ExtendFootprintTtlResult).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ExtendFootprintTtlResult: %w", err) + } + return n, nil + case OperationTypeRestoreFootprint: + u.RestoreFootprintResult = new(RestoreFootprintResult) + nTmp, err = (*u.RestoreFootprintResult).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding RestoreFootprintResult: %w", err) } return n, nil } - return n, fmt.Errorf("union ClaimAtom has invalid Type (ClaimAtomType) switch value '%d'", u.Type) -} - -// MarshalBinary implements encoding.BinaryMarshaler. -func (s ClaimAtom) MarshalBinary() ([]byte, error) { - b := bytes.Buffer{} - e := xdr.NewEncoder(&b) - err := s.EncodeTo(e) - return b.Bytes(), err -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *ClaimAtom) UnmarshalBinary(inp []byte) error { - r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) - return err -} - -var ( - _ encoding.BinaryMarshaler = (*ClaimAtom)(nil) - _ encoding.BinaryUnmarshaler = (*ClaimAtom)(nil) -) - -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s ClaimAtom) xdrType() {} - -var _ xdrType = (*ClaimAtom)(nil) - -// CreateAccountResultCode is an XDR Enum defines as: -// -// enum CreateAccountResultCode -// { -// // codes considered as "success" for the operation -// CREATE_ACCOUNT_SUCCESS = 0, // account was created -// -// // codes considered as "failure" for the operation -// CREATE_ACCOUNT_MALFORMED = -1, // invalid destination -// CREATE_ACCOUNT_UNDERFUNDED = -2, // not enough funds in source account -// CREATE_ACCOUNT_LOW_RESERVE = -// -3, // would create an account below the min reserve -// CREATE_ACCOUNT_ALREADY_EXIST = -4 // account already exists -// }; -type CreateAccountResultCode int32 - -const ( - CreateAccountResultCodeCreateAccountSuccess CreateAccountResultCode = 0 - CreateAccountResultCodeCreateAccountMalformed CreateAccountResultCode = -1 - CreateAccountResultCodeCreateAccountUnderfunded CreateAccountResultCode = -2 - CreateAccountResultCodeCreateAccountLowReserve CreateAccountResultCode = -3 - CreateAccountResultCodeCreateAccountAlreadyExist CreateAccountResultCode = -4 -) - -var createAccountResultCodeMap = map[int32]string{ - 0: "CreateAccountResultCodeCreateAccountSuccess", - -1: "CreateAccountResultCodeCreateAccountMalformed", - -2: "CreateAccountResultCodeCreateAccountUnderfunded", - -3: "CreateAccountResultCodeCreateAccountLowReserve", - -4: "CreateAccountResultCodeCreateAccountAlreadyExist", -} - -// ValidEnum validates a proposed value for this enum. Implements -// the Enum interface for CreateAccountResultCode -func (e CreateAccountResultCode) ValidEnum(v int32) bool { - _, ok := createAccountResultCodeMap[v] - return ok -} - -// String returns the name of `e` -func (e CreateAccountResultCode) String() string { - name, _ := createAccountResultCodeMap[int32(e)] - return name -} - -// EncodeTo encodes this value using the Encoder. -func (e CreateAccountResultCode) EncodeTo(enc *xdr.Encoder) error { - if _, ok := createAccountResultCodeMap[int32(e)]; !ok { - return fmt.Errorf("'%d' is not a valid CreateAccountResultCode enum value", e) - } - _, err := enc.EncodeInt(int32(e)) - return err -} - -var _ decoderFrom = (*CreateAccountResultCode)(nil) - -// DecodeFrom decodes this value using the Decoder. -func (e *CreateAccountResultCode) DecodeFrom(d *xdr.Decoder) (int, error) { - v, n, err := d.DecodeInt() - if err != nil { - return n, fmt.Errorf("decoding CreateAccountResultCode: %s", err) - } - if _, ok := createAccountResultCodeMap[v]; !ok { - return n, fmt.Errorf("'%d' is not a valid CreateAccountResultCode enum value", v) - } - *e = CreateAccountResultCode(v) - return n, nil + return n, fmt.Errorf("union OperationResultTr has invalid Type (OperationType) switch value '%d'", u.Type) } // MarshalBinary implements encoding.BinaryMarshaler. -func (s CreateAccountResultCode) MarshalBinary() ([]byte, error) { +func (s OperationResultTr) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -26311,141 +42905,263 @@ func (s CreateAccountResultCode) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *CreateAccountResultCode) UnmarshalBinary(inp []byte) error { +func (s *OperationResultTr) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*CreateAccountResultCode)(nil) - _ encoding.BinaryUnmarshaler = (*CreateAccountResultCode)(nil) + _ encoding.BinaryMarshaler = (*OperationResultTr)(nil) + _ encoding.BinaryUnmarshaler = (*OperationResultTr)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s CreateAccountResultCode) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s OperationResultTr) xdrType() {} -var _ xdrType = (*CreateAccountResultCode)(nil) +var _ xdrType = (*OperationResultTr)(nil) -// CreateAccountResult is an XDR Union defines as: +// OperationResult is an XDR Union defines as: // -// union CreateAccountResult switch (CreateAccountResultCode code) +// union OperationResult switch (OperationResultCode code) // { -// case CREATE_ACCOUNT_SUCCESS: -// void; -// case CREATE_ACCOUNT_MALFORMED: -// case CREATE_ACCOUNT_UNDERFUNDED: -// case CREATE_ACCOUNT_LOW_RESERVE: -// case CREATE_ACCOUNT_ALREADY_EXIST: +// case opINNER: +// union switch (OperationType type) +// { +// case CREATE_ACCOUNT: +// CreateAccountResult createAccountResult; +// case PAYMENT: +// PaymentResult paymentResult; +// case PATH_PAYMENT_STRICT_RECEIVE: +// PathPaymentStrictReceiveResult pathPaymentStrictReceiveResult; +// case MANAGE_SELL_OFFER: +// ManageSellOfferResult manageSellOfferResult; +// case CREATE_PASSIVE_SELL_OFFER: +// ManageSellOfferResult createPassiveSellOfferResult; +// case SET_OPTIONS: +// SetOptionsResult setOptionsResult; +// case CHANGE_TRUST: +// ChangeTrustResult changeTrustResult; +// case ALLOW_TRUST: +// AllowTrustResult allowTrustResult; +// case ACCOUNT_MERGE: +// AccountMergeResult accountMergeResult; +// case INFLATION: +// InflationResult inflationResult; +// case MANAGE_DATA: +// ManageDataResult manageDataResult; +// case BUMP_SEQUENCE: +// BumpSequenceResult bumpSeqResult; +// case MANAGE_BUY_OFFER: +// ManageBuyOfferResult manageBuyOfferResult; +// case PATH_PAYMENT_STRICT_SEND: +// PathPaymentStrictSendResult pathPaymentStrictSendResult; +// case CREATE_CLAIMABLE_BALANCE: +// CreateClaimableBalanceResult createClaimableBalanceResult; +// case CLAIM_CLAIMABLE_BALANCE: +// ClaimClaimableBalanceResult claimClaimableBalanceResult; +// case BEGIN_SPONSORING_FUTURE_RESERVES: +// BeginSponsoringFutureReservesResult beginSponsoringFutureReservesResult; +// case END_SPONSORING_FUTURE_RESERVES: +// EndSponsoringFutureReservesResult endSponsoringFutureReservesResult; +// case REVOKE_SPONSORSHIP: +// RevokeSponsorshipResult revokeSponsorshipResult; +// case CLAWBACK: +// ClawbackResult clawbackResult; +// case CLAWBACK_CLAIMABLE_BALANCE: +// ClawbackClaimableBalanceResult clawbackClaimableBalanceResult; +// case SET_TRUST_LINE_FLAGS: +// SetTrustLineFlagsResult setTrustLineFlagsResult; +// case LIQUIDITY_POOL_DEPOSIT: +// LiquidityPoolDepositResult liquidityPoolDepositResult; +// case LIQUIDITY_POOL_WITHDRAW: +// LiquidityPoolWithdrawResult liquidityPoolWithdrawResult; +// case INVOKE_HOST_FUNCTION: +// InvokeHostFunctionResult invokeHostFunctionResult; +// case EXTEND_FOOTPRINT_TTL: +// ExtendFootprintTTLResult extendFootprintTTLResult; +// case RESTORE_FOOTPRINT: +// RestoreFootprintResult restoreFootprintResult; +// } +// tr; +// case opBAD_AUTH: +// case opNO_ACCOUNT: +// case opNOT_SUPPORTED: +// case opTOO_MANY_SUBENTRIES: +// case opEXCEEDED_WORK_LIMIT: +// case opTOO_MANY_SPONSORING: // void; // }; -type CreateAccountResult struct { - Code CreateAccountResultCode +type OperationResult struct { + Code OperationResultCode + Tr *OperationResultTr } // SwitchFieldName returns the field name in which this union's // discriminant is stored -func (u CreateAccountResult) SwitchFieldName() string { +func (u OperationResult) SwitchFieldName() string { return "Code" } // ArmForSwitch returns which field name should be used for storing -// the value for an instance of CreateAccountResult -func (u CreateAccountResult) ArmForSwitch(sw int32) (string, bool) { - switch CreateAccountResultCode(sw) { - case CreateAccountResultCodeCreateAccountSuccess: +// the value for an instance of OperationResult +func (u OperationResult) ArmForSwitch(sw int32) (string, bool) { + switch OperationResultCode(sw) { + case OperationResultCodeOpInner: + return "Tr", true + case OperationResultCodeOpBadAuth: return "", true - case CreateAccountResultCodeCreateAccountMalformed: + case OperationResultCodeOpNoAccount: return "", true - case CreateAccountResultCodeCreateAccountUnderfunded: + case OperationResultCodeOpNotSupported: return "", true - case CreateAccountResultCodeCreateAccountLowReserve: + case OperationResultCodeOpTooManySubentries: return "", true - case CreateAccountResultCodeCreateAccountAlreadyExist: + case OperationResultCodeOpExceededWorkLimit: + return "", true + case OperationResultCodeOpTooManySponsoring: return "", true } return "-", false } -// NewCreateAccountResult creates a new CreateAccountResult. -func NewCreateAccountResult(code CreateAccountResultCode, value interface{}) (result CreateAccountResult, err error) { +// NewOperationResult creates a new OperationResult. +func NewOperationResult(code OperationResultCode, value interface{}) (result OperationResult, err error) { result.Code = code - switch CreateAccountResultCode(code) { - case CreateAccountResultCodeCreateAccountSuccess: + switch OperationResultCode(code) { + case OperationResultCodeOpInner: + tv, ok := value.(OperationResultTr) + if !ok { + err = errors.New("invalid value, must be OperationResultTr") + return + } + result.Tr = &tv + case OperationResultCodeOpBadAuth: // void - case CreateAccountResultCodeCreateAccountMalformed: + case OperationResultCodeOpNoAccount: // void - case CreateAccountResultCodeCreateAccountUnderfunded: + case OperationResultCodeOpNotSupported: // void - case CreateAccountResultCodeCreateAccountLowReserve: + case OperationResultCodeOpTooManySubentries: // void - case CreateAccountResultCodeCreateAccountAlreadyExist: + case OperationResultCodeOpExceededWorkLimit: // void + case OperationResultCodeOpTooManySponsoring: + // void + } + return +} + +// MustTr retrieves the Tr value from the union, +// panicing if the value is not set. +func (u OperationResult) MustTr() OperationResultTr { + val, ok := u.GetTr() + + if !ok { + panic("arm Tr is not set") + } + + return val +} + +// GetTr retrieves the Tr value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u OperationResult) GetTr() (result OperationResultTr, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Code)) + + if armName == "Tr" { + result = *u.Tr + ok = true } + return } // EncodeTo encodes this value using the Encoder. -func (u CreateAccountResult) EncodeTo(e *xdr.Encoder) error { +func (u OperationResult) EncodeTo(e *xdr.Encoder) error { var err error if err = u.Code.EncodeTo(e); err != nil { return err } - switch CreateAccountResultCode(u.Code) { - case CreateAccountResultCodeCreateAccountSuccess: + switch OperationResultCode(u.Code) { + case OperationResultCodeOpInner: + if err = (*u.Tr).EncodeTo(e); err != nil { + return err + } + return nil + case OperationResultCodeOpBadAuth: // Void return nil - case CreateAccountResultCodeCreateAccountMalformed: + case OperationResultCodeOpNoAccount: // Void return nil - case CreateAccountResultCodeCreateAccountUnderfunded: + case OperationResultCodeOpNotSupported: // Void return nil - case CreateAccountResultCodeCreateAccountLowReserve: + case OperationResultCodeOpTooManySubentries: // Void return nil - case CreateAccountResultCodeCreateAccountAlreadyExist: + case OperationResultCodeOpExceededWorkLimit: + // Void + return nil + case OperationResultCodeOpTooManySponsoring: // Void return nil } - return fmt.Errorf("Code (CreateAccountResultCode) switch value '%d' is not valid for union CreateAccountResult", u.Code) + return fmt.Errorf("Code (OperationResultCode) switch value '%d' is not valid for union OperationResult", u.Code) } -var _ decoderFrom = (*CreateAccountResult)(nil) +var _ decoderFrom = (*OperationResult)(nil) // DecodeFrom decodes this value using the Decoder. -func (u *CreateAccountResult) DecodeFrom(d *xdr.Decoder) (int, error) { +func (u *OperationResult) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding OperationResult: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = u.Code.DecodeFrom(d) + nTmp, err = u.Code.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding CreateAccountResultCode: %s", err) + return n, fmt.Errorf("decoding OperationResultCode: %w", err) } - switch CreateAccountResultCode(u.Code) { - case CreateAccountResultCodeCreateAccountSuccess: + switch OperationResultCode(u.Code) { + case OperationResultCodeOpInner: + u.Tr = new(OperationResultTr) + nTmp, err = (*u.Tr).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding OperationResultTr: %w", err) + } + return n, nil + case OperationResultCodeOpBadAuth: // Void return n, nil - case CreateAccountResultCodeCreateAccountMalformed: + case OperationResultCodeOpNoAccount: // Void return n, nil - case CreateAccountResultCodeCreateAccountUnderfunded: + case OperationResultCodeOpNotSupported: // Void return n, nil - case CreateAccountResultCodeCreateAccountLowReserve: + case OperationResultCodeOpTooManySubentries: // Void return n, nil - case CreateAccountResultCodeCreateAccountAlreadyExist: + case OperationResultCodeOpExceededWorkLimit: + // Void + return n, nil + case OperationResultCodeOpTooManySponsoring: // Void return n, nil } - return n, fmt.Errorf("union CreateAccountResult has invalid Code (CreateAccountResultCode) switch value '%d'", u.Code) + return n, fmt.Errorf("union OperationResult has invalid Code (OperationResultCode) switch value '%d'", u.Code) } // MarshalBinary implements encoding.BinaryMarshaler. -func (s CreateAccountResult) MarshalBinary() ([]byte, error) { +func (s OperationResult) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -26453,109 +43169,142 @@ func (s CreateAccountResult) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *CreateAccountResult) UnmarshalBinary(inp []byte) error { +func (s *OperationResult) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*CreateAccountResult)(nil) - _ encoding.BinaryUnmarshaler = (*CreateAccountResult)(nil) + _ encoding.BinaryMarshaler = (*OperationResult)(nil) + _ encoding.BinaryUnmarshaler = (*OperationResult)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s CreateAccountResult) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s OperationResult) xdrType() {} -var _ xdrType = (*CreateAccountResult)(nil) +var _ xdrType = (*OperationResult)(nil) -// PaymentResultCode is an XDR Enum defines as: +// TransactionResultCode is an XDR Enum defines as: // -// enum PaymentResultCode +// enum TransactionResultCode // { -// // codes considered as "success" for the operation -// PAYMENT_SUCCESS = 0, // payment successfully completed +// txFEE_BUMP_INNER_SUCCESS = 1, // fee bump inner transaction succeeded +// txSUCCESS = 0, // all operations succeeded // -// // codes considered as "failure" for the operation -// PAYMENT_MALFORMED = -1, // bad input -// PAYMENT_UNDERFUNDED = -2, // not enough funds in source account -// PAYMENT_SRC_NO_TRUST = -3, // no trust line on source account -// PAYMENT_SRC_NOT_AUTHORIZED = -4, // source not authorized to transfer -// PAYMENT_NO_DESTINATION = -5, // destination account does not exist -// PAYMENT_NO_TRUST = -6, // destination missing a trust line for asset -// PAYMENT_NOT_AUTHORIZED = -7, // destination not authorized to hold asset -// PAYMENT_LINE_FULL = -8, // destination would go above their limit -// PAYMENT_NO_ISSUER = -9 // missing issuer on asset +// txFAILED = -1, // one of the operations failed (none were applied) +// +// txTOO_EARLY = -2, // ledger closeTime before minTime +// txTOO_LATE = -3, // ledger closeTime after maxTime +// txMISSING_OPERATION = -4, // no operation was specified +// txBAD_SEQ = -5, // sequence number does not match source account +// +// txBAD_AUTH = -6, // too few valid signatures / wrong network +// txINSUFFICIENT_BALANCE = -7, // fee would bring account below reserve +// txNO_ACCOUNT = -8, // source account not found +// txINSUFFICIENT_FEE = -9, // fee is too small +// txBAD_AUTH_EXTRA = -10, // unused signatures attached to transaction +// txINTERNAL_ERROR = -11, // an unknown error occurred +// +// txNOT_SUPPORTED = -12, // transaction type not supported +// txFEE_BUMP_INNER_FAILED = -13, // fee bump inner transaction failed +// txBAD_SPONSORSHIP = -14, // sponsorship not confirmed +// txBAD_MIN_SEQ_AGE_OR_GAP = -15, // minSeqAge or minSeqLedgerGap conditions not met +// txMALFORMED = -16, // precondition is invalid +// txSOROBAN_INVALID = -17 // soroban-specific preconditions were not met // }; -type PaymentResultCode int32 +type TransactionResultCode int32 const ( - PaymentResultCodePaymentSuccess PaymentResultCode = 0 - PaymentResultCodePaymentMalformed PaymentResultCode = -1 - PaymentResultCodePaymentUnderfunded PaymentResultCode = -2 - PaymentResultCodePaymentSrcNoTrust PaymentResultCode = -3 - PaymentResultCodePaymentSrcNotAuthorized PaymentResultCode = -4 - PaymentResultCodePaymentNoDestination PaymentResultCode = -5 - PaymentResultCodePaymentNoTrust PaymentResultCode = -6 - PaymentResultCodePaymentNotAuthorized PaymentResultCode = -7 - PaymentResultCodePaymentLineFull PaymentResultCode = -8 - PaymentResultCodePaymentNoIssuer PaymentResultCode = -9 + TransactionResultCodeTxFeeBumpInnerSuccess TransactionResultCode = 1 + TransactionResultCodeTxSuccess TransactionResultCode = 0 + TransactionResultCodeTxFailed TransactionResultCode = -1 + TransactionResultCodeTxTooEarly TransactionResultCode = -2 + TransactionResultCodeTxTooLate TransactionResultCode = -3 + TransactionResultCodeTxMissingOperation TransactionResultCode = -4 + TransactionResultCodeTxBadSeq TransactionResultCode = -5 + TransactionResultCodeTxBadAuth TransactionResultCode = -6 + TransactionResultCodeTxInsufficientBalance TransactionResultCode = -7 + TransactionResultCodeTxNoAccount TransactionResultCode = -8 + TransactionResultCodeTxInsufficientFee TransactionResultCode = -9 + TransactionResultCodeTxBadAuthExtra TransactionResultCode = -10 + TransactionResultCodeTxInternalError TransactionResultCode = -11 + TransactionResultCodeTxNotSupported TransactionResultCode = -12 + TransactionResultCodeTxFeeBumpInnerFailed TransactionResultCode = -13 + TransactionResultCodeTxBadSponsorship TransactionResultCode = -14 + TransactionResultCodeTxBadMinSeqAgeOrGap TransactionResultCode = -15 + TransactionResultCodeTxMalformed TransactionResultCode = -16 + TransactionResultCodeTxSorobanInvalid TransactionResultCode = -17 ) -var paymentResultCodeMap = map[int32]string{ - 0: "PaymentResultCodePaymentSuccess", - -1: "PaymentResultCodePaymentMalformed", - -2: "PaymentResultCodePaymentUnderfunded", - -3: "PaymentResultCodePaymentSrcNoTrust", - -4: "PaymentResultCodePaymentSrcNotAuthorized", - -5: "PaymentResultCodePaymentNoDestination", - -6: "PaymentResultCodePaymentNoTrust", - -7: "PaymentResultCodePaymentNotAuthorized", - -8: "PaymentResultCodePaymentLineFull", - -9: "PaymentResultCodePaymentNoIssuer", +var transactionResultCodeMap = map[int32]string{ + 1: "TransactionResultCodeTxFeeBumpInnerSuccess", + 0: "TransactionResultCodeTxSuccess", + -1: "TransactionResultCodeTxFailed", + -2: "TransactionResultCodeTxTooEarly", + -3: "TransactionResultCodeTxTooLate", + -4: "TransactionResultCodeTxMissingOperation", + -5: "TransactionResultCodeTxBadSeq", + -6: "TransactionResultCodeTxBadAuth", + -7: "TransactionResultCodeTxInsufficientBalance", + -8: "TransactionResultCodeTxNoAccount", + -9: "TransactionResultCodeTxInsufficientFee", + -10: "TransactionResultCodeTxBadAuthExtra", + -11: "TransactionResultCodeTxInternalError", + -12: "TransactionResultCodeTxNotSupported", + -13: "TransactionResultCodeTxFeeBumpInnerFailed", + -14: "TransactionResultCodeTxBadSponsorship", + -15: "TransactionResultCodeTxBadMinSeqAgeOrGap", + -16: "TransactionResultCodeTxMalformed", + -17: "TransactionResultCodeTxSorobanInvalid", } // ValidEnum validates a proposed value for this enum. Implements -// the Enum interface for PaymentResultCode -func (e PaymentResultCode) ValidEnum(v int32) bool { - _, ok := paymentResultCodeMap[v] +// the Enum interface for TransactionResultCode +func (e TransactionResultCode) ValidEnum(v int32) bool { + _, ok := transactionResultCodeMap[v] return ok } // String returns the name of `e` -func (e PaymentResultCode) String() string { - name, _ := paymentResultCodeMap[int32(e)] +func (e TransactionResultCode) String() string { + name, _ := transactionResultCodeMap[int32(e)] return name } // EncodeTo encodes this value using the Encoder. -func (e PaymentResultCode) EncodeTo(enc *xdr.Encoder) error { - if _, ok := paymentResultCodeMap[int32(e)]; !ok { - return fmt.Errorf("'%d' is not a valid PaymentResultCode enum value", e) +func (e TransactionResultCode) EncodeTo(enc *xdr.Encoder) error { + if _, ok := transactionResultCodeMap[int32(e)]; !ok { + return fmt.Errorf("'%d' is not a valid TransactionResultCode enum value", e) } _, err := enc.EncodeInt(int32(e)) return err } -var _ decoderFrom = (*PaymentResultCode)(nil) +var _ decoderFrom = (*TransactionResultCode)(nil) // DecodeFrom decodes this value using the Decoder. -func (e *PaymentResultCode) DecodeFrom(d *xdr.Decoder) (int, error) { +func (e *TransactionResultCode) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding TransactionResultCode: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 v, n, err := d.DecodeInt() if err != nil { - return n, fmt.Errorf("decoding PaymentResultCode: %s", err) + return n, fmt.Errorf("decoding TransactionResultCode: %w", err) } - if _, ok := paymentResultCodeMap[v]; !ok { - return n, fmt.Errorf("'%d' is not a valid PaymentResultCode enum value", v) + if _, ok := transactionResultCodeMap[v]; !ok { + return n, fmt.Errorf("'%d' is not a valid TransactionResultCode enum value", v) } - *e = PaymentResultCode(v) + *e = TransactionResultCode(v) return n, nil } // MarshalBinary implements encoding.BinaryMarshaler. -func (s PaymentResultCode) MarshalBinary() ([]byte, error) { +func (s TransactionResultCode) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -26563,196 +43312,370 @@ func (s PaymentResultCode) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *PaymentResultCode) UnmarshalBinary(inp []byte) error { +func (s *TransactionResultCode) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*PaymentResultCode)(nil) - _ encoding.BinaryUnmarshaler = (*PaymentResultCode)(nil) + _ encoding.BinaryMarshaler = (*TransactionResultCode)(nil) + _ encoding.BinaryUnmarshaler = (*TransactionResultCode)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s PaymentResultCode) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s TransactionResultCode) xdrType() {} -var _ xdrType = (*PaymentResultCode)(nil) +var _ xdrType = (*TransactionResultCode)(nil) -// PaymentResult is an XDR Union defines as: +// InnerTransactionResultResult is an XDR NestedUnion defines as: // -// union PaymentResult switch (PaymentResultCode code) -// { -// case PAYMENT_SUCCESS: -// void; -// case PAYMENT_MALFORMED: -// case PAYMENT_UNDERFUNDED: -// case PAYMENT_SRC_NO_TRUST: -// case PAYMENT_SRC_NOT_AUTHORIZED: -// case PAYMENT_NO_DESTINATION: -// case PAYMENT_NO_TRUST: -// case PAYMENT_NOT_AUTHORIZED: -// case PAYMENT_LINE_FULL: -// case PAYMENT_NO_ISSUER: -// void; -// }; -type PaymentResult struct { - Code PaymentResultCode +// union switch (TransactionResultCode code) +// { +// // txFEE_BUMP_INNER_SUCCESS is not included +// case txSUCCESS: +// case txFAILED: +// OperationResult results<>; +// case txTOO_EARLY: +// case txTOO_LATE: +// case txMISSING_OPERATION: +// case txBAD_SEQ: +// case txBAD_AUTH: +// case txINSUFFICIENT_BALANCE: +// case txNO_ACCOUNT: +// case txINSUFFICIENT_FEE: +// case txBAD_AUTH_EXTRA: +// case txINTERNAL_ERROR: +// case txNOT_SUPPORTED: +// // txFEE_BUMP_INNER_FAILED is not included +// case txBAD_SPONSORSHIP: +// case txBAD_MIN_SEQ_AGE_OR_GAP: +// case txMALFORMED: +// case txSOROBAN_INVALID: +// void; +// } +type InnerTransactionResultResult struct { + Code TransactionResultCode + Results *[]OperationResult } // SwitchFieldName returns the field name in which this union's // discriminant is stored -func (u PaymentResult) SwitchFieldName() string { +func (u InnerTransactionResultResult) SwitchFieldName() string { return "Code" } // ArmForSwitch returns which field name should be used for storing -// the value for an instance of PaymentResult -func (u PaymentResult) ArmForSwitch(sw int32) (string, bool) { - switch PaymentResultCode(sw) { - case PaymentResultCodePaymentSuccess: +// the value for an instance of InnerTransactionResultResult +func (u InnerTransactionResultResult) ArmForSwitch(sw int32) (string, bool) { + switch TransactionResultCode(sw) { + case TransactionResultCodeTxSuccess: + return "Results", true + case TransactionResultCodeTxFailed: + return "Results", true + case TransactionResultCodeTxTooEarly: return "", true - case PaymentResultCodePaymentMalformed: + case TransactionResultCodeTxTooLate: return "", true - case PaymentResultCodePaymentUnderfunded: + case TransactionResultCodeTxMissingOperation: return "", true - case PaymentResultCodePaymentSrcNoTrust: + case TransactionResultCodeTxBadSeq: return "", true - case PaymentResultCodePaymentSrcNotAuthorized: + case TransactionResultCodeTxBadAuth: return "", true - case PaymentResultCodePaymentNoDestination: + case TransactionResultCodeTxInsufficientBalance: return "", true - case PaymentResultCodePaymentNoTrust: + case TransactionResultCodeTxNoAccount: return "", true - case PaymentResultCodePaymentNotAuthorized: + case TransactionResultCodeTxInsufficientFee: return "", true - case PaymentResultCodePaymentLineFull: + case TransactionResultCodeTxBadAuthExtra: return "", true - case PaymentResultCodePaymentNoIssuer: + case TransactionResultCodeTxInternalError: + return "", true + case TransactionResultCodeTxNotSupported: + return "", true + case TransactionResultCodeTxBadSponsorship: + return "", true + case TransactionResultCodeTxBadMinSeqAgeOrGap: + return "", true + case TransactionResultCodeTxMalformed: + return "", true + case TransactionResultCodeTxSorobanInvalid: return "", true } return "-", false } -// NewPaymentResult creates a new PaymentResult. -func NewPaymentResult(code PaymentResultCode, value interface{}) (result PaymentResult, err error) { +// NewInnerTransactionResultResult creates a new InnerTransactionResultResult. +func NewInnerTransactionResultResult(code TransactionResultCode, value interface{}) (result InnerTransactionResultResult, err error) { result.Code = code - switch PaymentResultCode(code) { - case PaymentResultCodePaymentSuccess: + switch TransactionResultCode(code) { + case TransactionResultCodeTxSuccess: + tv, ok := value.([]OperationResult) + if !ok { + err = errors.New("invalid value, must be []OperationResult") + return + } + result.Results = &tv + case TransactionResultCodeTxFailed: + tv, ok := value.([]OperationResult) + if !ok { + err = errors.New("invalid value, must be []OperationResult") + return + } + result.Results = &tv + case TransactionResultCodeTxTooEarly: // void - case PaymentResultCodePaymentMalformed: + case TransactionResultCodeTxTooLate: // void - case PaymentResultCodePaymentUnderfunded: + case TransactionResultCodeTxMissingOperation: // void - case PaymentResultCodePaymentSrcNoTrust: + case TransactionResultCodeTxBadSeq: // void - case PaymentResultCodePaymentSrcNotAuthorized: + case TransactionResultCodeTxBadAuth: // void - case PaymentResultCodePaymentNoDestination: + case TransactionResultCodeTxInsufficientBalance: // void - case PaymentResultCodePaymentNoTrust: + case TransactionResultCodeTxNoAccount: // void - case PaymentResultCodePaymentNotAuthorized: + case TransactionResultCodeTxInsufficientFee: // void - case PaymentResultCodePaymentLineFull: + case TransactionResultCodeTxBadAuthExtra: // void - case PaymentResultCodePaymentNoIssuer: + case TransactionResultCodeTxInternalError: + // void + case TransactionResultCodeTxNotSupported: + // void + case TransactionResultCodeTxBadSponsorship: + // void + case TransactionResultCodeTxBadMinSeqAgeOrGap: // void + case TransactionResultCodeTxMalformed: + // void + case TransactionResultCodeTxSorobanInvalid: + // void + } + return +} + +// MustResults retrieves the Results value from the union, +// panicing if the value is not set. +func (u InnerTransactionResultResult) MustResults() []OperationResult { + val, ok := u.GetResults() + + if !ok { + panic("arm Results is not set") + } + + return val +} + +// GetResults retrieves the Results value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u InnerTransactionResultResult) GetResults() (result []OperationResult, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Code)) + + if armName == "Results" { + result = *u.Results + ok = true } + return } // EncodeTo encodes this value using the Encoder. -func (u PaymentResult) EncodeTo(e *xdr.Encoder) error { +func (u InnerTransactionResultResult) EncodeTo(e *xdr.Encoder) error { var err error if err = u.Code.EncodeTo(e); err != nil { return err } - switch PaymentResultCode(u.Code) { - case PaymentResultCodePaymentSuccess: + switch TransactionResultCode(u.Code) { + case TransactionResultCodeTxSuccess: + if _, err = e.EncodeUint(uint32(len((*u.Results)))); err != nil { + return err + } + for i := 0; i < len((*u.Results)); i++ { + if err = (*u.Results)[i].EncodeTo(e); err != nil { + return err + } + } + return nil + case TransactionResultCodeTxFailed: + if _, err = e.EncodeUint(uint32(len((*u.Results)))); err != nil { + return err + } + for i := 0; i < len((*u.Results)); i++ { + if err = (*u.Results)[i].EncodeTo(e); err != nil { + return err + } + } + return nil + case TransactionResultCodeTxTooEarly: // Void return nil - case PaymentResultCodePaymentMalformed: + case TransactionResultCodeTxTooLate: // Void return nil - case PaymentResultCodePaymentUnderfunded: + case TransactionResultCodeTxMissingOperation: // Void return nil - case PaymentResultCodePaymentSrcNoTrust: + case TransactionResultCodeTxBadSeq: // Void return nil - case PaymentResultCodePaymentSrcNotAuthorized: + case TransactionResultCodeTxBadAuth: // Void return nil - case PaymentResultCodePaymentNoDestination: + case TransactionResultCodeTxInsufficientBalance: // Void return nil - case PaymentResultCodePaymentNoTrust: + case TransactionResultCodeTxNoAccount: // Void return nil - case PaymentResultCodePaymentNotAuthorized: + case TransactionResultCodeTxInsufficientFee: // Void return nil - case PaymentResultCodePaymentLineFull: + case TransactionResultCodeTxBadAuthExtra: // Void return nil - case PaymentResultCodePaymentNoIssuer: + case TransactionResultCodeTxInternalError: + // Void + return nil + case TransactionResultCodeTxNotSupported: + // Void + return nil + case TransactionResultCodeTxBadSponsorship: + // Void + return nil + case TransactionResultCodeTxBadMinSeqAgeOrGap: + // Void + return nil + case TransactionResultCodeTxMalformed: + // Void + return nil + case TransactionResultCodeTxSorobanInvalid: // Void return nil } - return fmt.Errorf("Code (PaymentResultCode) switch value '%d' is not valid for union PaymentResult", u.Code) + return fmt.Errorf("Code (TransactionResultCode) switch value '%d' is not valid for union InnerTransactionResultResult", u.Code) } -var _ decoderFrom = (*PaymentResult)(nil) +var _ decoderFrom = (*InnerTransactionResultResult)(nil) // DecodeFrom decodes this value using the Decoder. -func (u *PaymentResult) DecodeFrom(d *xdr.Decoder) (int, error) { +func (u *InnerTransactionResultResult) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding InnerTransactionResultResult: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = u.Code.DecodeFrom(d) + nTmp, err = u.Code.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding PaymentResultCode: %s", err) + return n, fmt.Errorf("decoding TransactionResultCode: %w", err) } - switch PaymentResultCode(u.Code) { - case PaymentResultCodePaymentSuccess: + switch TransactionResultCode(u.Code) { + case TransactionResultCodeTxSuccess: + u.Results = new([]OperationResult) + var l uint32 + l, nTmp, err = d.DecodeUint() + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding OperationResult: %w", err) + } + (*u.Results) = nil + if l > 0 { + if il, ok := d.InputLen(); ok && uint(il) < uint(l) { + return n, fmt.Errorf("decoding OperationResult: length (%d) exceeds remaining input length (%d)", l, il) + } + (*u.Results) = make([]OperationResult, l) + for i := uint32(0); i < l; i++ { + nTmp, err = (*u.Results)[i].DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding OperationResult: %w", err) + } + } + } + return n, nil + case TransactionResultCodeTxFailed: + u.Results = new([]OperationResult) + var l uint32 + l, nTmp, err = d.DecodeUint() + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding OperationResult: %w", err) + } + (*u.Results) = nil + if l > 0 { + if il, ok := d.InputLen(); ok && uint(il) < uint(l) { + return n, fmt.Errorf("decoding OperationResult: length (%d) exceeds remaining input length (%d)", l, il) + } + (*u.Results) = make([]OperationResult, l) + for i := uint32(0); i < l; i++ { + nTmp, err = (*u.Results)[i].DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding OperationResult: %w", err) + } + } + } + return n, nil + case TransactionResultCodeTxTooEarly: // Void return n, nil - case PaymentResultCodePaymentMalformed: + case TransactionResultCodeTxTooLate: // Void return n, nil - case PaymentResultCodePaymentUnderfunded: + case TransactionResultCodeTxMissingOperation: // Void return n, nil - case PaymentResultCodePaymentSrcNoTrust: + case TransactionResultCodeTxBadSeq: // Void return n, nil - case PaymentResultCodePaymentSrcNotAuthorized: + case TransactionResultCodeTxBadAuth: // Void return n, nil - case PaymentResultCodePaymentNoDestination: + case TransactionResultCodeTxInsufficientBalance: // Void return n, nil - case PaymentResultCodePaymentNoTrust: + case TransactionResultCodeTxNoAccount: // Void return n, nil - case PaymentResultCodePaymentNotAuthorized: + case TransactionResultCodeTxInsufficientFee: // Void return n, nil - case PaymentResultCodePaymentLineFull: + case TransactionResultCodeTxBadAuthExtra: // Void return n, nil - case PaymentResultCodePaymentNoIssuer: + case TransactionResultCodeTxInternalError: + // Void + return n, nil + case TransactionResultCodeTxNotSupported: + // Void + return n, nil + case TransactionResultCodeTxBadSponsorship: + // Void + return n, nil + case TransactionResultCodeTxBadMinSeqAgeOrGap: + // Void + return n, nil + case TransactionResultCodeTxMalformed: + // Void + return n, nil + case TransactionResultCodeTxSorobanInvalid: // Void return n, nil } - return n, fmt.Errorf("union PaymentResult has invalid Code (PaymentResultCode) switch value '%d'", u.Code) + return n, fmt.Errorf("union InnerTransactionResultResult has invalid Code (TransactionResultCode) switch value '%d'", u.Code) } // MarshalBinary implements encoding.BinaryMarshaler. -func (s PaymentResult) MarshalBinary() ([]byte, error) { +func (s InnerTransactionResultResult) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -26760,127 +43683,101 @@ func (s PaymentResult) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *PaymentResult) UnmarshalBinary(inp []byte) error { +func (s *InnerTransactionResultResult) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*PaymentResult)(nil) - _ encoding.BinaryUnmarshaler = (*PaymentResult)(nil) + _ encoding.BinaryMarshaler = (*InnerTransactionResultResult)(nil) + _ encoding.BinaryUnmarshaler = (*InnerTransactionResultResult)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s PaymentResult) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s InnerTransactionResultResult) xdrType() {} -var _ xdrType = (*PaymentResult)(nil) +var _ xdrType = (*InnerTransactionResultResult)(nil) -// PathPaymentStrictReceiveResultCode is an XDR Enum defines as: -// -// enum PathPaymentStrictReceiveResultCode -// { -// // codes considered as "success" for the operation -// PATH_PAYMENT_STRICT_RECEIVE_SUCCESS = 0, // success +// InnerTransactionResultExt is an XDR NestedUnion defines as: // -// // codes considered as "failure" for the operation -// PATH_PAYMENT_STRICT_RECEIVE_MALFORMED = -1, // bad input -// PATH_PAYMENT_STRICT_RECEIVE_UNDERFUNDED = -// -2, // not enough funds in source account -// PATH_PAYMENT_STRICT_RECEIVE_SRC_NO_TRUST = -// -3, // no trust line on source account -// PATH_PAYMENT_STRICT_RECEIVE_SRC_NOT_AUTHORIZED = -// -4, // source not authorized to transfer -// PATH_PAYMENT_STRICT_RECEIVE_NO_DESTINATION = -// -5, // destination account does not exist -// PATH_PAYMENT_STRICT_RECEIVE_NO_TRUST = -// -6, // dest missing a trust line for asset -// PATH_PAYMENT_STRICT_RECEIVE_NOT_AUTHORIZED = -// -7, // dest not authorized to hold asset -// PATH_PAYMENT_STRICT_RECEIVE_LINE_FULL = -// -8, // dest would go above their limit -// PATH_PAYMENT_STRICT_RECEIVE_NO_ISSUER = -9, // missing issuer on one asset -// PATH_PAYMENT_STRICT_RECEIVE_TOO_FEW_OFFERS = -// -10, // not enough offers to satisfy path -// PATH_PAYMENT_STRICT_RECEIVE_OFFER_CROSS_SELF = -// -11, // would cross one of its own offers -// PATH_PAYMENT_STRICT_RECEIVE_OVER_SENDMAX = -12 // could not satisfy sendmax -// }; -type PathPaymentStrictReceiveResultCode int32 - -const ( - PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveSuccess PathPaymentStrictReceiveResultCode = 0 - PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveMalformed PathPaymentStrictReceiveResultCode = -1 - PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveUnderfunded PathPaymentStrictReceiveResultCode = -2 - PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveSrcNoTrust PathPaymentStrictReceiveResultCode = -3 - PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveSrcNotAuthorized PathPaymentStrictReceiveResultCode = -4 - PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveNoDestination PathPaymentStrictReceiveResultCode = -5 - PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveNoTrust PathPaymentStrictReceiveResultCode = -6 - PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveNotAuthorized PathPaymentStrictReceiveResultCode = -7 - PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveLineFull PathPaymentStrictReceiveResultCode = -8 - PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveNoIssuer PathPaymentStrictReceiveResultCode = -9 - PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveTooFewOffers PathPaymentStrictReceiveResultCode = -10 - PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveOfferCrossSelf PathPaymentStrictReceiveResultCode = -11 - PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveOverSendmax PathPaymentStrictReceiveResultCode = -12 -) - -var pathPaymentStrictReceiveResultCodeMap = map[int32]string{ - 0: "PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveSuccess", - -1: "PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveMalformed", - -2: "PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveUnderfunded", - -3: "PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveSrcNoTrust", - -4: "PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveSrcNotAuthorized", - -5: "PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveNoDestination", - -6: "PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveNoTrust", - -7: "PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveNotAuthorized", - -8: "PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveLineFull", - -9: "PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveNoIssuer", - -10: "PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveTooFewOffers", - -11: "PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveOfferCrossSelf", - -12: "PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveOverSendmax", +// union switch (int v) +// { +// case 0: +// void; +// } +type InnerTransactionResultExt struct { + V int32 } -// ValidEnum validates a proposed value for this enum. Implements -// the Enum interface for PathPaymentStrictReceiveResultCode -func (e PathPaymentStrictReceiveResultCode) ValidEnum(v int32) bool { - _, ok := pathPaymentStrictReceiveResultCodeMap[v] - return ok +// SwitchFieldName returns the field name in which this union's +// discriminant is stored +func (u InnerTransactionResultExt) SwitchFieldName() string { + return "V" +} + +// ArmForSwitch returns which field name should be used for storing +// the value for an instance of InnerTransactionResultExt +func (u InnerTransactionResultExt) ArmForSwitch(sw int32) (string, bool) { + switch int32(sw) { + case 0: + return "", true + } + return "-", false } -// String returns the name of `e` -func (e PathPaymentStrictReceiveResultCode) String() string { - name, _ := pathPaymentStrictReceiveResultCodeMap[int32(e)] - return name +// NewInnerTransactionResultExt creates a new InnerTransactionResultExt. +func NewInnerTransactionResultExt(v int32, value interface{}) (result InnerTransactionResultExt, err error) { + result.V = v + switch int32(v) { + case 0: + // void + } + return } // EncodeTo encodes this value using the Encoder. -func (e PathPaymentStrictReceiveResultCode) EncodeTo(enc *xdr.Encoder) error { - if _, ok := pathPaymentStrictReceiveResultCodeMap[int32(e)]; !ok { - return fmt.Errorf("'%d' is not a valid PathPaymentStrictReceiveResultCode enum value", e) +func (u InnerTransactionResultExt) EncodeTo(e *xdr.Encoder) error { + var err error + if _, err = e.EncodeInt(int32(u.V)); err != nil { + return err } - _, err := enc.EncodeInt(int32(e)) - return err + switch int32(u.V) { + case 0: + // Void + return nil + } + return fmt.Errorf("V (int32) switch value '%d' is not valid for union InnerTransactionResultExt", u.V) } -var _ decoderFrom = (*PathPaymentStrictReceiveResultCode)(nil) +var _ decoderFrom = (*InnerTransactionResultExt)(nil) // DecodeFrom decodes this value using the Decoder. -func (e *PathPaymentStrictReceiveResultCode) DecodeFrom(d *xdr.Decoder) (int, error) { - v, n, err := d.DecodeInt() +func (u *InnerTransactionResultExt) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding InnerTransactionResultExt: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + var err error + var n, nTmp int + u.V, nTmp, err = d.DecodeInt() + n += nTmp if err != nil { - return n, fmt.Errorf("decoding PathPaymentStrictReceiveResultCode: %s", err) + return n, fmt.Errorf("decoding Int: %w", err) } - if _, ok := pathPaymentStrictReceiveResultCodeMap[v]; !ok { - return n, fmt.Errorf("'%d' is not a valid PathPaymentStrictReceiveResultCode enum value", v) + switch int32(u.V) { + case 0: + // Void + return n, nil } - *e = PathPaymentStrictReceiveResultCode(v) - return n, nil + return n, fmt.Errorf("union InnerTransactionResultExt has invalid V (int32) switch value '%d'", u.V) } // MarshalBinary implements encoding.BinaryMarshaler. -func (s PathPaymentStrictReceiveResultCode) MarshalBinary() ([]byte, error) { +func (s InnerTransactionResultExt) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -26888,79 +43785,117 @@ func (s PathPaymentStrictReceiveResultCode) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *PathPaymentStrictReceiveResultCode) UnmarshalBinary(inp []byte) error { +func (s *InnerTransactionResultExt) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*PathPaymentStrictReceiveResultCode)(nil) - _ encoding.BinaryUnmarshaler = (*PathPaymentStrictReceiveResultCode)(nil) + _ encoding.BinaryMarshaler = (*InnerTransactionResultExt)(nil) + _ encoding.BinaryUnmarshaler = (*InnerTransactionResultExt)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s PathPaymentStrictReceiveResultCode) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s InnerTransactionResultExt) xdrType() {} -var _ xdrType = (*PathPaymentStrictReceiveResultCode)(nil) +var _ xdrType = (*InnerTransactionResultExt)(nil) -// SimplePaymentResult is an XDR Struct defines as: +// InnerTransactionResult is an XDR Struct defines as: // -// struct SimplePaymentResult +// struct InnerTransactionResult // { -// AccountID destination; -// Asset asset; -// int64 amount; +// // Always 0. Here for binary compatibility. +// int64 feeCharged; +// +// union switch (TransactionResultCode code) +// { +// // txFEE_BUMP_INNER_SUCCESS is not included +// case txSUCCESS: +// case txFAILED: +// OperationResult results<>; +// case txTOO_EARLY: +// case txTOO_LATE: +// case txMISSING_OPERATION: +// case txBAD_SEQ: +// case txBAD_AUTH: +// case txINSUFFICIENT_BALANCE: +// case txNO_ACCOUNT: +// case txINSUFFICIENT_FEE: +// case txBAD_AUTH_EXTRA: +// case txINTERNAL_ERROR: +// case txNOT_SUPPORTED: +// // txFEE_BUMP_INNER_FAILED is not included +// case txBAD_SPONSORSHIP: +// case txBAD_MIN_SEQ_AGE_OR_GAP: +// case txMALFORMED: +// case txSOROBAN_INVALID: +// void; +// } +// result; +// +// // reserved for future use +// union switch (int v) +// { +// case 0: +// void; +// } +// ext; // }; -type SimplePaymentResult struct { - Destination AccountId - Asset Asset - Amount Int64 +type InnerTransactionResult struct { + FeeCharged Int64 + Result InnerTransactionResultResult + Ext InnerTransactionResultExt } // EncodeTo encodes this value using the Encoder. -func (s *SimplePaymentResult) EncodeTo(e *xdr.Encoder) error { +func (s *InnerTransactionResult) EncodeTo(e *xdr.Encoder) error { var err error - if err = s.Destination.EncodeTo(e); err != nil { + if err = s.FeeCharged.EncodeTo(e); err != nil { return err } - if err = s.Asset.EncodeTo(e); err != nil { + if err = s.Result.EncodeTo(e); err != nil { return err } - if err = s.Amount.EncodeTo(e); err != nil { + if err = s.Ext.EncodeTo(e); err != nil { return err } return nil } -var _ decoderFrom = (*SimplePaymentResult)(nil) +var _ decoderFrom = (*InnerTransactionResult)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *SimplePaymentResult) DecodeFrom(d *xdr.Decoder) (int, error) { +func (s *InnerTransactionResult) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding InnerTransactionResult: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = s.Destination.DecodeFrom(d) + nTmp, err = s.FeeCharged.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding AccountId: %s", err) + return n, fmt.Errorf("decoding Int64: %w", err) } - nTmp, err = s.Asset.DecodeFrom(d) + nTmp, err = s.Result.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Asset: %s", err) + return n, fmt.Errorf("decoding InnerTransactionResultResult: %w", err) } - nTmp, err = s.Amount.DecodeFrom(d) + nTmp, err = s.Ext.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Int64: %s", err) + return n, fmt.Errorf("decoding InnerTransactionResultExt: %w", err) } return n, nil } // MarshalBinary implements encoding.BinaryMarshaler. -func (s SimplePaymentResult) MarshalBinary() ([]byte, error) { +func (s InnerTransactionResult) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -26968,86 +43903,74 @@ func (s SimplePaymentResult) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *SimplePaymentResult) UnmarshalBinary(inp []byte) error { +func (s *InnerTransactionResult) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*SimplePaymentResult)(nil) - _ encoding.BinaryUnmarshaler = (*SimplePaymentResult)(nil) + _ encoding.BinaryMarshaler = (*InnerTransactionResult)(nil) + _ encoding.BinaryUnmarshaler = (*InnerTransactionResult)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s SimplePaymentResult) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s InnerTransactionResult) xdrType() {} -var _ xdrType = (*SimplePaymentResult)(nil) +var _ xdrType = (*InnerTransactionResult)(nil) -// PathPaymentStrictReceiveResultSuccess is an XDR NestedStruct defines as: +// InnerTransactionResultPair is an XDR Struct defines as: // -// struct -// { -// ClaimAtom offers<>; -// SimplePaymentResult last; -// } -type PathPaymentStrictReceiveResultSuccess struct { - Offers []ClaimAtom - Last SimplePaymentResult +// struct InnerTransactionResultPair +// { +// Hash transactionHash; // hash of the inner transaction +// InnerTransactionResult result; // result for the inner transaction +// }; +type InnerTransactionResultPair struct { + TransactionHash Hash + Result InnerTransactionResult } // EncodeTo encodes this value using the Encoder. -func (s *PathPaymentStrictReceiveResultSuccess) EncodeTo(e *xdr.Encoder) error { +func (s *InnerTransactionResultPair) EncodeTo(e *xdr.Encoder) error { var err error - if _, err = e.EncodeUint(uint32(len(s.Offers))); err != nil { + if err = s.TransactionHash.EncodeTo(e); err != nil { return err } - for i := 0; i < len(s.Offers); i++ { - if err = s.Offers[i].EncodeTo(e); err != nil { - return err - } - } - if err = s.Last.EncodeTo(e); err != nil { + if err = s.Result.EncodeTo(e); err != nil { return err } return nil } -var _ decoderFrom = (*PathPaymentStrictReceiveResultSuccess)(nil) +var _ decoderFrom = (*InnerTransactionResultPair)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *PathPaymentStrictReceiveResultSuccess) DecodeFrom(d *xdr.Decoder) (int, error) { +func (s *InnerTransactionResultPair) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding InnerTransactionResultPair: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - var l uint32 - l, nTmp, err = d.DecodeUint() + nTmp, err = s.TransactionHash.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding ClaimAtom: %s", err) - } - s.Offers = nil - if l > 0 { - s.Offers = make([]ClaimAtom, l) - for i := uint32(0); i < l; i++ { - nTmp, err = s.Offers[i].DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding ClaimAtom: %s", err) - } - } + return n, fmt.Errorf("decoding Hash: %w", err) } - nTmp, err = s.Last.DecodeFrom(d) + nTmp, err = s.Result.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding SimplePaymentResult: %s", err) + return n, fmt.Errorf("decoding InnerTransactionResult: %w", err) } return n, nil } // MarshalBinary implements encoding.BinaryMarshaler. -func (s PathPaymentStrictReceiveResultSuccess) MarshalBinary() ([]byte, error) { +func (s InnerTransactionResultPair) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -27055,185 +43978,221 @@ func (s PathPaymentStrictReceiveResultSuccess) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *PathPaymentStrictReceiveResultSuccess) UnmarshalBinary(inp []byte) error { +func (s *InnerTransactionResultPair) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*PathPaymentStrictReceiveResultSuccess)(nil) - _ encoding.BinaryUnmarshaler = (*PathPaymentStrictReceiveResultSuccess)(nil) + _ encoding.BinaryMarshaler = (*InnerTransactionResultPair)(nil) + _ encoding.BinaryUnmarshaler = (*InnerTransactionResultPair)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s PathPaymentStrictReceiveResultSuccess) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s InnerTransactionResultPair) xdrType() {} -var _ xdrType = (*PathPaymentStrictReceiveResultSuccess)(nil) +var _ xdrType = (*InnerTransactionResultPair)(nil) -// PathPaymentStrictReceiveResult is an XDR Union defines as: +// TransactionResultResult is an XDR NestedUnion defines as: // -// union PathPaymentStrictReceiveResult switch ( -// PathPaymentStrictReceiveResultCode code) -// { -// case PATH_PAYMENT_STRICT_RECEIVE_SUCCESS: -// struct +// union switch (TransactionResultCode code) // { -// ClaimAtom offers<>; -// SimplePaymentResult last; -// } success; -// case PATH_PAYMENT_STRICT_RECEIVE_MALFORMED: -// case PATH_PAYMENT_STRICT_RECEIVE_UNDERFUNDED: -// case PATH_PAYMENT_STRICT_RECEIVE_SRC_NO_TRUST: -// case PATH_PAYMENT_STRICT_RECEIVE_SRC_NOT_AUTHORIZED: -// case PATH_PAYMENT_STRICT_RECEIVE_NO_DESTINATION: -// case PATH_PAYMENT_STRICT_RECEIVE_NO_TRUST: -// case PATH_PAYMENT_STRICT_RECEIVE_NOT_AUTHORIZED: -// case PATH_PAYMENT_STRICT_RECEIVE_LINE_FULL: -// void; -// case PATH_PAYMENT_STRICT_RECEIVE_NO_ISSUER: -// Asset noIssuer; // the asset that caused the error -// case PATH_PAYMENT_STRICT_RECEIVE_TOO_FEW_OFFERS: -// case PATH_PAYMENT_STRICT_RECEIVE_OFFER_CROSS_SELF: -// case PATH_PAYMENT_STRICT_RECEIVE_OVER_SENDMAX: -// void; -// }; -type PathPaymentStrictReceiveResult struct { - Code PathPaymentStrictReceiveResultCode - Success *PathPaymentStrictReceiveResultSuccess - NoIssuer *Asset +// case txFEE_BUMP_INNER_SUCCESS: +// case txFEE_BUMP_INNER_FAILED: +// InnerTransactionResultPair innerResultPair; +// case txSUCCESS: +// case txFAILED: +// OperationResult results<>; +// case txTOO_EARLY: +// case txTOO_LATE: +// case txMISSING_OPERATION: +// case txBAD_SEQ: +// case txBAD_AUTH: +// case txINSUFFICIENT_BALANCE: +// case txNO_ACCOUNT: +// case txINSUFFICIENT_FEE: +// case txBAD_AUTH_EXTRA: +// case txINTERNAL_ERROR: +// case txNOT_SUPPORTED: +// // case txFEE_BUMP_INNER_FAILED: handled above +// case txBAD_SPONSORSHIP: +// case txBAD_MIN_SEQ_AGE_OR_GAP: +// case txMALFORMED: +// case txSOROBAN_INVALID: +// void; +// } +type TransactionResultResult struct { + Code TransactionResultCode + InnerResultPair *InnerTransactionResultPair + Results *[]OperationResult } // SwitchFieldName returns the field name in which this union's // discriminant is stored -func (u PathPaymentStrictReceiveResult) SwitchFieldName() string { +func (u TransactionResultResult) SwitchFieldName() string { return "Code" } // ArmForSwitch returns which field name should be used for storing -// the value for an instance of PathPaymentStrictReceiveResult -func (u PathPaymentStrictReceiveResult) ArmForSwitch(sw int32) (string, bool) { - switch PathPaymentStrictReceiveResultCode(sw) { - case PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveSuccess: - return "Success", true - case PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveMalformed: +// the value for an instance of TransactionResultResult +func (u TransactionResultResult) ArmForSwitch(sw int32) (string, bool) { + switch TransactionResultCode(sw) { + case TransactionResultCodeTxFeeBumpInnerSuccess: + return "InnerResultPair", true + case TransactionResultCodeTxFeeBumpInnerFailed: + return "InnerResultPair", true + case TransactionResultCodeTxSuccess: + return "Results", true + case TransactionResultCodeTxFailed: + return "Results", true + case TransactionResultCodeTxTooEarly: return "", true - case PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveUnderfunded: + case TransactionResultCodeTxTooLate: return "", true - case PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveSrcNoTrust: + case TransactionResultCodeTxMissingOperation: return "", true - case PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveSrcNotAuthorized: + case TransactionResultCodeTxBadSeq: return "", true - case PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveNoDestination: + case TransactionResultCodeTxBadAuth: return "", true - case PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveNoTrust: + case TransactionResultCodeTxInsufficientBalance: return "", true - case PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveNotAuthorized: + case TransactionResultCodeTxNoAccount: return "", true - case PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveLineFull: + case TransactionResultCodeTxInsufficientFee: return "", true - case PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveNoIssuer: - return "NoIssuer", true - case PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveTooFewOffers: + case TransactionResultCodeTxBadAuthExtra: return "", true - case PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveOfferCrossSelf: + case TransactionResultCodeTxInternalError: return "", true - case PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveOverSendmax: + case TransactionResultCodeTxNotSupported: + return "", true + case TransactionResultCodeTxBadSponsorship: + return "", true + case TransactionResultCodeTxBadMinSeqAgeOrGap: + return "", true + case TransactionResultCodeTxMalformed: + return "", true + case TransactionResultCodeTxSorobanInvalid: return "", true } return "-", false } -// NewPathPaymentStrictReceiveResult creates a new PathPaymentStrictReceiveResult. -func NewPathPaymentStrictReceiveResult(code PathPaymentStrictReceiveResultCode, value interface{}) (result PathPaymentStrictReceiveResult, err error) { +// NewTransactionResultResult creates a new TransactionResultResult. +func NewTransactionResultResult(code TransactionResultCode, value interface{}) (result TransactionResultResult, err error) { result.Code = code - switch PathPaymentStrictReceiveResultCode(code) { - case PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveSuccess: - tv, ok := value.(PathPaymentStrictReceiveResultSuccess) + switch TransactionResultCode(code) { + case TransactionResultCodeTxFeeBumpInnerSuccess: + tv, ok := value.(InnerTransactionResultPair) if !ok { - err = fmt.Errorf("invalid value, must be PathPaymentStrictReceiveResultSuccess") + err = errors.New("invalid value, must be InnerTransactionResultPair") return } - result.Success = &tv - case PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveMalformed: + result.InnerResultPair = &tv + case TransactionResultCodeTxFeeBumpInnerFailed: + tv, ok := value.(InnerTransactionResultPair) + if !ok { + err = errors.New("invalid value, must be InnerTransactionResultPair") + return + } + result.InnerResultPair = &tv + case TransactionResultCodeTxSuccess: + tv, ok := value.([]OperationResult) + if !ok { + err = errors.New("invalid value, must be []OperationResult") + return + } + result.Results = &tv + case TransactionResultCodeTxFailed: + tv, ok := value.([]OperationResult) + if !ok { + err = errors.New("invalid value, must be []OperationResult") + return + } + result.Results = &tv + case TransactionResultCodeTxTooEarly: // void - case PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveUnderfunded: + case TransactionResultCodeTxTooLate: // void - case PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveSrcNoTrust: + case TransactionResultCodeTxMissingOperation: // void - case PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveSrcNotAuthorized: + case TransactionResultCodeTxBadSeq: // void - case PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveNoDestination: + case TransactionResultCodeTxBadAuth: // void - case PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveNoTrust: + case TransactionResultCodeTxInsufficientBalance: // void - case PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveNotAuthorized: + case TransactionResultCodeTxNoAccount: // void - case PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveLineFull: + case TransactionResultCodeTxInsufficientFee: // void - case PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveNoIssuer: - tv, ok := value.(Asset) - if !ok { - err = fmt.Errorf("invalid value, must be Asset") - return - } - result.NoIssuer = &tv - case PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveTooFewOffers: + case TransactionResultCodeTxBadAuthExtra: // void - case PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveOfferCrossSelf: + case TransactionResultCodeTxInternalError: // void - case PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveOverSendmax: + case TransactionResultCodeTxNotSupported: + // void + case TransactionResultCodeTxBadSponsorship: + // void + case TransactionResultCodeTxBadMinSeqAgeOrGap: + // void + case TransactionResultCodeTxMalformed: + // void + case TransactionResultCodeTxSorobanInvalid: // void } return } -// MustSuccess retrieves the Success value from the union, +// MustInnerResultPair retrieves the InnerResultPair value from the union, // panicing if the value is not set. -func (u PathPaymentStrictReceiveResult) MustSuccess() PathPaymentStrictReceiveResultSuccess { - val, ok := u.GetSuccess() +func (u TransactionResultResult) MustInnerResultPair() InnerTransactionResultPair { + val, ok := u.GetInnerResultPair() if !ok { - panic("arm Success is not set") + panic("arm InnerResultPair is not set") } return val } -// GetSuccess retrieves the Success value from the union, +// GetInnerResultPair retrieves the InnerResultPair value from the union, // returning ok if the union's switch indicated the value is valid. -func (u PathPaymentStrictReceiveResult) GetSuccess() (result PathPaymentStrictReceiveResultSuccess, ok bool) { +func (u TransactionResultResult) GetInnerResultPair() (result InnerTransactionResultPair, ok bool) { armName, _ := u.ArmForSwitch(int32(u.Code)) - if armName == "Success" { - result = *u.Success + if armName == "InnerResultPair" { + result = *u.InnerResultPair ok = true } return } -// MustNoIssuer retrieves the NoIssuer value from the union, +// MustResults retrieves the Results value from the union, // panicing if the value is not set. -func (u PathPaymentStrictReceiveResult) MustNoIssuer() Asset { - val, ok := u.GetNoIssuer() +func (u TransactionResultResult) MustResults() []OperationResult { + val, ok := u.GetResults() if !ok { - panic("arm NoIssuer is not set") + panic("arm Results is not set") } return val } -// GetNoIssuer retrieves the NoIssuer value from the union, +// GetResults retrieves the Results value from the union, // returning ok if the union's switch indicated the value is valid. -func (u PathPaymentStrictReceiveResult) GetNoIssuer() (result Asset, ok bool) { +func (u TransactionResultResult) GetResults() (result []OperationResult, ok bool) { armName, _ := u.ArmForSwitch(int32(u.Code)) - if armName == "NoIssuer" { - result = *u.NoIssuer + if armName == "Results" { + result = *u.Results ok = true } @@ -27241,126 +44200,220 @@ func (u PathPaymentStrictReceiveResult) GetNoIssuer() (result Asset, ok bool) { } // EncodeTo encodes this value using the Encoder. -func (u PathPaymentStrictReceiveResult) EncodeTo(e *xdr.Encoder) error { +func (u TransactionResultResult) EncodeTo(e *xdr.Encoder) error { var err error if err = u.Code.EncodeTo(e); err != nil { return err } - switch PathPaymentStrictReceiveResultCode(u.Code) { - case PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveSuccess: - if err = (*u.Success).EncodeTo(e); err != nil { + switch TransactionResultCode(u.Code) { + case TransactionResultCodeTxFeeBumpInnerSuccess: + if err = (*u.InnerResultPair).EncodeTo(e); err != nil { return err } return nil - case PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveMalformed: + case TransactionResultCodeTxFeeBumpInnerFailed: + if err = (*u.InnerResultPair).EncodeTo(e); err != nil { + return err + } + return nil + case TransactionResultCodeTxSuccess: + if _, err = e.EncodeUint(uint32(len((*u.Results)))); err != nil { + return err + } + for i := 0; i < len((*u.Results)); i++ { + if err = (*u.Results)[i].EncodeTo(e); err != nil { + return err + } + } + return nil + case TransactionResultCodeTxFailed: + if _, err = e.EncodeUint(uint32(len((*u.Results)))); err != nil { + return err + } + for i := 0; i < len((*u.Results)); i++ { + if err = (*u.Results)[i].EncodeTo(e); err != nil { + return err + } + } + return nil + case TransactionResultCodeTxTooEarly: // Void return nil - case PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveUnderfunded: + case TransactionResultCodeTxTooLate: // Void return nil - case PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveSrcNoTrust: + case TransactionResultCodeTxMissingOperation: // Void return nil - case PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveSrcNotAuthorized: + case TransactionResultCodeTxBadSeq: // Void return nil - case PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveNoDestination: + case TransactionResultCodeTxBadAuth: // Void return nil - case PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveNoTrust: + case TransactionResultCodeTxInsufficientBalance: // Void return nil - case PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveNotAuthorized: + case TransactionResultCodeTxNoAccount: // Void return nil - case PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveLineFull: + case TransactionResultCodeTxInsufficientFee: // Void return nil - case PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveNoIssuer: - if err = (*u.NoIssuer).EncodeTo(e); err != nil { - return err - } + case TransactionResultCodeTxBadAuthExtra: + // Void return nil - case PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveTooFewOffers: + case TransactionResultCodeTxInternalError: // Void return nil - case PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveOfferCrossSelf: + case TransactionResultCodeTxNotSupported: // Void return nil - case PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveOverSendmax: + case TransactionResultCodeTxBadSponsorship: + // Void + return nil + case TransactionResultCodeTxBadMinSeqAgeOrGap: + // Void + return nil + case TransactionResultCodeTxMalformed: + // Void + return nil + case TransactionResultCodeTxSorobanInvalid: // Void return nil } - return fmt.Errorf("Code (PathPaymentStrictReceiveResultCode) switch value '%d' is not valid for union PathPaymentStrictReceiveResult", u.Code) + return fmt.Errorf("Code (TransactionResultCode) switch value '%d' is not valid for union TransactionResultResult", u.Code) } -var _ decoderFrom = (*PathPaymentStrictReceiveResult)(nil) +var _ decoderFrom = (*TransactionResultResult)(nil) // DecodeFrom decodes this value using the Decoder. -func (u *PathPaymentStrictReceiveResult) DecodeFrom(d *xdr.Decoder) (int, error) { +func (u *TransactionResultResult) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding TransactionResultResult: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = u.Code.DecodeFrom(d) + nTmp, err = u.Code.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding PathPaymentStrictReceiveResultCode: %s", err) + return n, fmt.Errorf("decoding TransactionResultCode: %w", err) } - switch PathPaymentStrictReceiveResultCode(u.Code) { - case PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveSuccess: - u.Success = new(PathPaymentStrictReceiveResultSuccess) - nTmp, err = (*u.Success).DecodeFrom(d) + switch TransactionResultCode(u.Code) { + case TransactionResultCodeTxFeeBumpInnerSuccess: + u.InnerResultPair = new(InnerTransactionResultPair) + nTmp, err = (*u.InnerResultPair).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding InnerTransactionResultPair: %w", err) + } + return n, nil + case TransactionResultCodeTxFeeBumpInnerFailed: + u.InnerResultPair = new(InnerTransactionResultPair) + nTmp, err = (*u.InnerResultPair).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding InnerTransactionResultPair: %w", err) + } + return n, nil + case TransactionResultCodeTxSuccess: + u.Results = new([]OperationResult) + var l uint32 + l, nTmp, err = d.DecodeUint() + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding OperationResult: %w", err) + } + (*u.Results) = nil + if l > 0 { + if il, ok := d.InputLen(); ok && uint(il) < uint(l) { + return n, fmt.Errorf("decoding OperationResult: length (%d) exceeds remaining input length (%d)", l, il) + } + (*u.Results) = make([]OperationResult, l) + for i := uint32(0); i < l; i++ { + nTmp, err = (*u.Results)[i].DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding OperationResult: %w", err) + } + } + } + return n, nil + case TransactionResultCodeTxFailed: + u.Results = new([]OperationResult) + var l uint32 + l, nTmp, err = d.DecodeUint() n += nTmp if err != nil { - return n, fmt.Errorf("decoding PathPaymentStrictReceiveResultSuccess: %s", err) + return n, fmt.Errorf("decoding OperationResult: %w", err) + } + (*u.Results) = nil + if l > 0 { + if il, ok := d.InputLen(); ok && uint(il) < uint(l) { + return n, fmt.Errorf("decoding OperationResult: length (%d) exceeds remaining input length (%d)", l, il) + } + (*u.Results) = make([]OperationResult, l) + for i := uint32(0); i < l; i++ { + nTmp, err = (*u.Results)[i].DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding OperationResult: %w", err) + } + } } return n, nil - case PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveMalformed: + case TransactionResultCodeTxTooEarly: // Void return n, nil - case PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveUnderfunded: + case TransactionResultCodeTxTooLate: // Void return n, nil - case PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveSrcNoTrust: + case TransactionResultCodeTxMissingOperation: // Void return n, nil - case PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveSrcNotAuthorized: + case TransactionResultCodeTxBadSeq: // Void return n, nil - case PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveNoDestination: + case TransactionResultCodeTxBadAuth: // Void return n, nil - case PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveNoTrust: + case TransactionResultCodeTxInsufficientBalance: // Void return n, nil - case PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveNotAuthorized: + case TransactionResultCodeTxNoAccount: // Void return n, nil - case PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveLineFull: + case TransactionResultCodeTxInsufficientFee: // Void return n, nil - case PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveNoIssuer: - u.NoIssuer = new(Asset) - nTmp, err = (*u.NoIssuer).DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Asset: %s", err) - } + case TransactionResultCodeTxBadAuthExtra: + // Void return n, nil - case PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveTooFewOffers: + case TransactionResultCodeTxInternalError: // Void return n, nil - case PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveOfferCrossSelf: + case TransactionResultCodeTxNotSupported: // Void return n, nil - case PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveOverSendmax: + case TransactionResultCodeTxBadSponsorship: + // Void + return n, nil + case TransactionResultCodeTxBadMinSeqAgeOrGap: + // Void + return n, nil + case TransactionResultCodeTxMalformed: + // Void + return n, nil + case TransactionResultCodeTxSorobanInvalid: // Void return n, nil } - return n, fmt.Errorf("union PathPaymentStrictReceiveResult has invalid Code (PathPaymentStrictReceiveResultCode) switch value '%d'", u.Code) + return n, fmt.Errorf("union TransactionResultResult has invalid Code (TransactionResultCode) switch value '%d'", u.Code) } // MarshalBinary implements encoding.BinaryMarshaler. -func (s PathPaymentStrictReceiveResult) MarshalBinary() ([]byte, error) { +func (s TransactionResultResult) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -27368,126 +44421,101 @@ func (s PathPaymentStrictReceiveResult) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *PathPaymentStrictReceiveResult) UnmarshalBinary(inp []byte) error { +func (s *TransactionResultResult) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*PathPaymentStrictReceiveResult)(nil) - _ encoding.BinaryUnmarshaler = (*PathPaymentStrictReceiveResult)(nil) + _ encoding.BinaryMarshaler = (*TransactionResultResult)(nil) + _ encoding.BinaryUnmarshaler = (*TransactionResultResult)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s PathPaymentStrictReceiveResult) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s TransactionResultResult) xdrType() {} -var _ xdrType = (*PathPaymentStrictReceiveResult)(nil) +var _ xdrType = (*TransactionResultResult)(nil) -// PathPaymentStrictSendResultCode is an XDR Enum defines as: -// -// enum PathPaymentStrictSendResultCode -// { -// // codes considered as "success" for the operation -// PATH_PAYMENT_STRICT_SEND_SUCCESS = 0, // success +// TransactionResultExt is an XDR NestedUnion defines as: // -// // codes considered as "failure" for the operation -// PATH_PAYMENT_STRICT_SEND_MALFORMED = -1, // bad input -// PATH_PAYMENT_STRICT_SEND_UNDERFUNDED = -// -2, // not enough funds in source account -// PATH_PAYMENT_STRICT_SEND_SRC_NO_TRUST = -// -3, // no trust line on source account -// PATH_PAYMENT_STRICT_SEND_SRC_NOT_AUTHORIZED = -// -4, // source not authorized to transfer -// PATH_PAYMENT_STRICT_SEND_NO_DESTINATION = -// -5, // destination account does not exist -// PATH_PAYMENT_STRICT_SEND_NO_TRUST = -// -6, // dest missing a trust line for asset -// PATH_PAYMENT_STRICT_SEND_NOT_AUTHORIZED = -// -7, // dest not authorized to hold asset -// PATH_PAYMENT_STRICT_SEND_LINE_FULL = -8, // dest would go above their limit -// PATH_PAYMENT_STRICT_SEND_NO_ISSUER = -9, // missing issuer on one asset -// PATH_PAYMENT_STRICT_SEND_TOO_FEW_OFFERS = -// -10, // not enough offers to satisfy path -// PATH_PAYMENT_STRICT_SEND_OFFER_CROSS_SELF = -// -11, // would cross one of its own offers -// PATH_PAYMENT_STRICT_SEND_UNDER_DESTMIN = -12 // could not satisfy destMin -// }; -type PathPaymentStrictSendResultCode int32 - -const ( - PathPaymentStrictSendResultCodePathPaymentStrictSendSuccess PathPaymentStrictSendResultCode = 0 - PathPaymentStrictSendResultCodePathPaymentStrictSendMalformed PathPaymentStrictSendResultCode = -1 - PathPaymentStrictSendResultCodePathPaymentStrictSendUnderfunded PathPaymentStrictSendResultCode = -2 - PathPaymentStrictSendResultCodePathPaymentStrictSendSrcNoTrust PathPaymentStrictSendResultCode = -3 - PathPaymentStrictSendResultCodePathPaymentStrictSendSrcNotAuthorized PathPaymentStrictSendResultCode = -4 - PathPaymentStrictSendResultCodePathPaymentStrictSendNoDestination PathPaymentStrictSendResultCode = -5 - PathPaymentStrictSendResultCodePathPaymentStrictSendNoTrust PathPaymentStrictSendResultCode = -6 - PathPaymentStrictSendResultCodePathPaymentStrictSendNotAuthorized PathPaymentStrictSendResultCode = -7 - PathPaymentStrictSendResultCodePathPaymentStrictSendLineFull PathPaymentStrictSendResultCode = -8 - PathPaymentStrictSendResultCodePathPaymentStrictSendNoIssuer PathPaymentStrictSendResultCode = -9 - PathPaymentStrictSendResultCodePathPaymentStrictSendTooFewOffers PathPaymentStrictSendResultCode = -10 - PathPaymentStrictSendResultCodePathPaymentStrictSendOfferCrossSelf PathPaymentStrictSendResultCode = -11 - PathPaymentStrictSendResultCodePathPaymentStrictSendUnderDestmin PathPaymentStrictSendResultCode = -12 -) +// union switch (int v) +// { +// case 0: +// void; +// } +type TransactionResultExt struct { + V int32 +} -var pathPaymentStrictSendResultCodeMap = map[int32]string{ - 0: "PathPaymentStrictSendResultCodePathPaymentStrictSendSuccess", - -1: "PathPaymentStrictSendResultCodePathPaymentStrictSendMalformed", - -2: "PathPaymentStrictSendResultCodePathPaymentStrictSendUnderfunded", - -3: "PathPaymentStrictSendResultCodePathPaymentStrictSendSrcNoTrust", - -4: "PathPaymentStrictSendResultCodePathPaymentStrictSendSrcNotAuthorized", - -5: "PathPaymentStrictSendResultCodePathPaymentStrictSendNoDestination", - -6: "PathPaymentStrictSendResultCodePathPaymentStrictSendNoTrust", - -7: "PathPaymentStrictSendResultCodePathPaymentStrictSendNotAuthorized", - -8: "PathPaymentStrictSendResultCodePathPaymentStrictSendLineFull", - -9: "PathPaymentStrictSendResultCodePathPaymentStrictSendNoIssuer", - -10: "PathPaymentStrictSendResultCodePathPaymentStrictSendTooFewOffers", - -11: "PathPaymentStrictSendResultCodePathPaymentStrictSendOfferCrossSelf", - -12: "PathPaymentStrictSendResultCodePathPaymentStrictSendUnderDestmin", +// SwitchFieldName returns the field name in which this union's +// discriminant is stored +func (u TransactionResultExt) SwitchFieldName() string { + return "V" } -// ValidEnum validates a proposed value for this enum. Implements -// the Enum interface for PathPaymentStrictSendResultCode -func (e PathPaymentStrictSendResultCode) ValidEnum(v int32) bool { - _, ok := pathPaymentStrictSendResultCodeMap[v] - return ok +// ArmForSwitch returns which field name should be used for storing +// the value for an instance of TransactionResultExt +func (u TransactionResultExt) ArmForSwitch(sw int32) (string, bool) { + switch int32(sw) { + case 0: + return "", true + } + return "-", false } -// String returns the name of `e` -func (e PathPaymentStrictSendResultCode) String() string { - name, _ := pathPaymentStrictSendResultCodeMap[int32(e)] - return name +// NewTransactionResultExt creates a new TransactionResultExt. +func NewTransactionResultExt(v int32, value interface{}) (result TransactionResultExt, err error) { + result.V = v + switch int32(v) { + case 0: + // void + } + return } // EncodeTo encodes this value using the Encoder. -func (e PathPaymentStrictSendResultCode) EncodeTo(enc *xdr.Encoder) error { - if _, ok := pathPaymentStrictSendResultCodeMap[int32(e)]; !ok { - return fmt.Errorf("'%d' is not a valid PathPaymentStrictSendResultCode enum value", e) +func (u TransactionResultExt) EncodeTo(e *xdr.Encoder) error { + var err error + if _, err = e.EncodeInt(int32(u.V)); err != nil { + return err } - _, err := enc.EncodeInt(int32(e)) - return err + switch int32(u.V) { + case 0: + // Void + return nil + } + return fmt.Errorf("V (int32) switch value '%d' is not valid for union TransactionResultExt", u.V) } -var _ decoderFrom = (*PathPaymentStrictSendResultCode)(nil) +var _ decoderFrom = (*TransactionResultExt)(nil) // DecodeFrom decodes this value using the Decoder. -func (e *PathPaymentStrictSendResultCode) DecodeFrom(d *xdr.Decoder) (int, error) { - v, n, err := d.DecodeInt() +func (u *TransactionResultExt) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding TransactionResultExt: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + var err error + var n, nTmp int + u.V, nTmp, err = d.DecodeInt() + n += nTmp if err != nil { - return n, fmt.Errorf("decoding PathPaymentStrictSendResultCode: %s", err) + return n, fmt.Errorf("decoding Int: %w", err) } - if _, ok := pathPaymentStrictSendResultCodeMap[v]; !ok { - return n, fmt.Errorf("'%d' is not a valid PathPaymentStrictSendResultCode enum value", v) + switch int32(u.V) { + case 0: + // Void + return n, nil } - *e = PathPaymentStrictSendResultCode(v) - return n, nil + return n, fmt.Errorf("union TransactionResultExt has invalid V (int32) switch value '%d'", u.V) } // MarshalBinary implements encoding.BinaryMarshaler. -func (s PathPaymentStrictSendResultCode) MarshalBinary() ([]byte, error) { +func (s TransactionResultExt) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -27495,398 +44523,183 @@ func (s PathPaymentStrictSendResultCode) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *PathPaymentStrictSendResultCode) UnmarshalBinary(inp []byte) error { +func (s *TransactionResultExt) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*PathPaymentStrictSendResultCode)(nil) - _ encoding.BinaryUnmarshaler = (*PathPaymentStrictSendResultCode)(nil) + _ encoding.BinaryMarshaler = (*TransactionResultExt)(nil) + _ encoding.BinaryUnmarshaler = (*TransactionResultExt)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s PathPaymentStrictSendResultCode) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s TransactionResultExt) xdrType() {} -var _ xdrType = (*PathPaymentStrictSendResultCode)(nil) +var _ xdrType = (*TransactionResultExt)(nil) -// PathPaymentStrictSendResultSuccess is an XDR NestedStruct defines as: +// TransactionResult is an XDR Struct defines as: // -// struct +// struct TransactionResult +// { +// int64 feeCharged; // actual fee charged for the transaction +// +// union switch (TransactionResultCode code) // { -// ClaimAtom offers<>; -// SimplePaymentResult last; +// case txFEE_BUMP_INNER_SUCCESS: +// case txFEE_BUMP_INNER_FAILED: +// InnerTransactionResultPair innerResultPair; +// case txSUCCESS: +// case txFAILED: +// OperationResult results<>; +// case txTOO_EARLY: +// case txTOO_LATE: +// case txMISSING_OPERATION: +// case txBAD_SEQ: +// case txBAD_AUTH: +// case txINSUFFICIENT_BALANCE: +// case txNO_ACCOUNT: +// case txINSUFFICIENT_FEE: +// case txBAD_AUTH_EXTRA: +// case txINTERNAL_ERROR: +// case txNOT_SUPPORTED: +// // case txFEE_BUMP_INNER_FAILED: handled above +// case txBAD_SPONSORSHIP: +// case txBAD_MIN_SEQ_AGE_OR_GAP: +// case txMALFORMED: +// case txSOROBAN_INVALID: +// void; // } -type PathPaymentStrictSendResultSuccess struct { - Offers []ClaimAtom - Last SimplePaymentResult +// result; +// +// // reserved for future use +// union switch (int v) +// { +// case 0: +// void; +// } +// ext; +// }; +type TransactionResult struct { + FeeCharged Int64 + Result TransactionResultResult + Ext TransactionResultExt } // EncodeTo encodes this value using the Encoder. -func (s *PathPaymentStrictSendResultSuccess) EncodeTo(e *xdr.Encoder) error { +func (s *TransactionResult) EncodeTo(e *xdr.Encoder) error { var err error - if _, err = e.EncodeUint(uint32(len(s.Offers))); err != nil { + if err = s.FeeCharged.EncodeTo(e); err != nil { return err } - for i := 0; i < len(s.Offers); i++ { - if err = s.Offers[i].EncodeTo(e); err != nil { - return err - } + if err = s.Result.EncodeTo(e); err != nil { + return err } - if err = s.Last.EncodeTo(e); err != nil { + if err = s.Ext.EncodeTo(e); err != nil { return err } return nil } -var _ decoderFrom = (*PathPaymentStrictSendResultSuccess)(nil) +var _ decoderFrom = (*TransactionResult)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *PathPaymentStrictSendResultSuccess) DecodeFrom(d *xdr.Decoder) (int, error) { +func (s *TransactionResult) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding TransactionResult: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - var l uint32 - l, nTmp, err = d.DecodeUint() + nTmp, err = s.FeeCharged.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding ClaimAtom: %s", err) + return n, fmt.Errorf("decoding Int64: %w", err) } - s.Offers = nil - if l > 0 { - s.Offers = make([]ClaimAtom, l) - for i := uint32(0); i < l; i++ { - nTmp, err = s.Offers[i].DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding ClaimAtom: %s", err) - } - } + nTmp, err = s.Result.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding TransactionResultResult: %w", err) } - nTmp, err = s.Last.DecodeFrom(d) + nTmp, err = s.Ext.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding SimplePaymentResult: %s", err) + return n, fmt.Errorf("decoding TransactionResultExt: %w", err) } return n, nil } // MarshalBinary implements encoding.BinaryMarshaler. -func (s PathPaymentStrictSendResultSuccess) MarshalBinary() ([]byte, error) { - b := bytes.Buffer{} - e := xdr.NewEncoder(&b) - err := s.EncodeTo(e) - return b.Bytes(), err -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *PathPaymentStrictSendResultSuccess) UnmarshalBinary(inp []byte) error { - r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) - return err -} - -var ( - _ encoding.BinaryMarshaler = (*PathPaymentStrictSendResultSuccess)(nil) - _ encoding.BinaryUnmarshaler = (*PathPaymentStrictSendResultSuccess)(nil) -) - -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s PathPaymentStrictSendResultSuccess) xdrType() {} - -var _ xdrType = (*PathPaymentStrictSendResultSuccess)(nil) - -// PathPaymentStrictSendResult is an XDR Union defines as: -// -// union PathPaymentStrictSendResult switch (PathPaymentStrictSendResultCode code) -// { -// case PATH_PAYMENT_STRICT_SEND_SUCCESS: -// struct -// { -// ClaimAtom offers<>; -// SimplePaymentResult last; -// } success; -// case PATH_PAYMENT_STRICT_SEND_MALFORMED: -// case PATH_PAYMENT_STRICT_SEND_UNDERFUNDED: -// case PATH_PAYMENT_STRICT_SEND_SRC_NO_TRUST: -// case PATH_PAYMENT_STRICT_SEND_SRC_NOT_AUTHORIZED: -// case PATH_PAYMENT_STRICT_SEND_NO_DESTINATION: -// case PATH_PAYMENT_STRICT_SEND_NO_TRUST: -// case PATH_PAYMENT_STRICT_SEND_NOT_AUTHORIZED: -// case PATH_PAYMENT_STRICT_SEND_LINE_FULL: -// void; -// case PATH_PAYMENT_STRICT_SEND_NO_ISSUER: -// Asset noIssuer; // the asset that caused the error -// case PATH_PAYMENT_STRICT_SEND_TOO_FEW_OFFERS: -// case PATH_PAYMENT_STRICT_SEND_OFFER_CROSS_SELF: -// case PATH_PAYMENT_STRICT_SEND_UNDER_DESTMIN: -// void; -// }; -type PathPaymentStrictSendResult struct { - Code PathPaymentStrictSendResultCode - Success *PathPaymentStrictSendResultSuccess - NoIssuer *Asset -} - -// SwitchFieldName returns the field name in which this union's -// discriminant is stored -func (u PathPaymentStrictSendResult) SwitchFieldName() string { - return "Code" -} - -// ArmForSwitch returns which field name should be used for storing -// the value for an instance of PathPaymentStrictSendResult -func (u PathPaymentStrictSendResult) ArmForSwitch(sw int32) (string, bool) { - switch PathPaymentStrictSendResultCode(sw) { - case PathPaymentStrictSendResultCodePathPaymentStrictSendSuccess: - return "Success", true - case PathPaymentStrictSendResultCodePathPaymentStrictSendMalformed: - return "", true - case PathPaymentStrictSendResultCodePathPaymentStrictSendUnderfunded: - return "", true - case PathPaymentStrictSendResultCodePathPaymentStrictSendSrcNoTrust: - return "", true - case PathPaymentStrictSendResultCodePathPaymentStrictSendSrcNotAuthorized: - return "", true - case PathPaymentStrictSendResultCodePathPaymentStrictSendNoDestination: - return "", true - case PathPaymentStrictSendResultCodePathPaymentStrictSendNoTrust: - return "", true - case PathPaymentStrictSendResultCodePathPaymentStrictSendNotAuthorized: - return "", true - case PathPaymentStrictSendResultCodePathPaymentStrictSendLineFull: - return "", true - case PathPaymentStrictSendResultCodePathPaymentStrictSendNoIssuer: - return "NoIssuer", true - case PathPaymentStrictSendResultCodePathPaymentStrictSendTooFewOffers: - return "", true - case PathPaymentStrictSendResultCodePathPaymentStrictSendOfferCrossSelf: - return "", true - case PathPaymentStrictSendResultCodePathPaymentStrictSendUnderDestmin: - return "", true - } - return "-", false -} - -// NewPathPaymentStrictSendResult creates a new PathPaymentStrictSendResult. -func NewPathPaymentStrictSendResult(code PathPaymentStrictSendResultCode, value interface{}) (result PathPaymentStrictSendResult, err error) { - result.Code = code - switch PathPaymentStrictSendResultCode(code) { - case PathPaymentStrictSendResultCodePathPaymentStrictSendSuccess: - tv, ok := value.(PathPaymentStrictSendResultSuccess) - if !ok { - err = fmt.Errorf("invalid value, must be PathPaymentStrictSendResultSuccess") - return - } - result.Success = &tv - case PathPaymentStrictSendResultCodePathPaymentStrictSendMalformed: - // void - case PathPaymentStrictSendResultCodePathPaymentStrictSendUnderfunded: - // void - case PathPaymentStrictSendResultCodePathPaymentStrictSendSrcNoTrust: - // void - case PathPaymentStrictSendResultCodePathPaymentStrictSendSrcNotAuthorized: - // void - case PathPaymentStrictSendResultCodePathPaymentStrictSendNoDestination: - // void - case PathPaymentStrictSendResultCodePathPaymentStrictSendNoTrust: - // void - case PathPaymentStrictSendResultCodePathPaymentStrictSendNotAuthorized: - // void - case PathPaymentStrictSendResultCodePathPaymentStrictSendLineFull: - // void - case PathPaymentStrictSendResultCodePathPaymentStrictSendNoIssuer: - tv, ok := value.(Asset) - if !ok { - err = fmt.Errorf("invalid value, must be Asset") - return - } - result.NoIssuer = &tv - case PathPaymentStrictSendResultCodePathPaymentStrictSendTooFewOffers: - // void - case PathPaymentStrictSendResultCodePathPaymentStrictSendOfferCrossSelf: - // void - case PathPaymentStrictSendResultCodePathPaymentStrictSendUnderDestmin: - // void - } - return -} - -// MustSuccess retrieves the Success value from the union, -// panicing if the value is not set. -func (u PathPaymentStrictSendResult) MustSuccess() PathPaymentStrictSendResultSuccess { - val, ok := u.GetSuccess() - - if !ok { - panic("arm Success is not set") - } - - return val -} - -// GetSuccess retrieves the Success value from the union, -// returning ok if the union's switch indicated the value is valid. -func (u PathPaymentStrictSendResult) GetSuccess() (result PathPaymentStrictSendResultSuccess, ok bool) { - armName, _ := u.ArmForSwitch(int32(u.Code)) - - if armName == "Success" { - result = *u.Success - ok = true - } - - return -} - -// MustNoIssuer retrieves the NoIssuer value from the union, -// panicing if the value is not set. -func (u PathPaymentStrictSendResult) MustNoIssuer() Asset { - val, ok := u.GetNoIssuer() - - if !ok { - panic("arm NoIssuer is not set") - } - - return val -} - -// GetNoIssuer retrieves the NoIssuer value from the union, -// returning ok if the union's switch indicated the value is valid. -func (u PathPaymentStrictSendResult) GetNoIssuer() (result Asset, ok bool) { - armName, _ := u.ArmForSwitch(int32(u.Code)) - - if armName == "NoIssuer" { - result = *u.NoIssuer - ok = true - } - - return -} - -// EncodeTo encodes this value using the Encoder. -func (u PathPaymentStrictSendResult) EncodeTo(e *xdr.Encoder) error { - var err error - if err = u.Code.EncodeTo(e); err != nil { - return err - } - switch PathPaymentStrictSendResultCode(u.Code) { - case PathPaymentStrictSendResultCodePathPaymentStrictSendSuccess: - if err = (*u.Success).EncodeTo(e); err != nil { - return err - } - return nil - case PathPaymentStrictSendResultCodePathPaymentStrictSendMalformed: - // Void - return nil - case PathPaymentStrictSendResultCodePathPaymentStrictSendUnderfunded: - // Void - return nil - case PathPaymentStrictSendResultCodePathPaymentStrictSendSrcNoTrust: - // Void - return nil - case PathPaymentStrictSendResultCodePathPaymentStrictSendSrcNotAuthorized: - // Void - return nil - case PathPaymentStrictSendResultCodePathPaymentStrictSendNoDestination: - // Void - return nil - case PathPaymentStrictSendResultCodePathPaymentStrictSendNoTrust: - // Void - return nil - case PathPaymentStrictSendResultCodePathPaymentStrictSendNotAuthorized: - // Void - return nil - case PathPaymentStrictSendResultCodePathPaymentStrictSendLineFull: - // Void - return nil - case PathPaymentStrictSendResultCodePathPaymentStrictSendNoIssuer: - if err = (*u.NoIssuer).EncodeTo(e); err != nil { - return err - } - return nil - case PathPaymentStrictSendResultCodePathPaymentStrictSendTooFewOffers: - // Void - return nil - case PathPaymentStrictSendResultCodePathPaymentStrictSendOfferCrossSelf: - // Void - return nil - case PathPaymentStrictSendResultCodePathPaymentStrictSendUnderDestmin: - // Void - return nil +func (s TransactionResult) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *TransactionResult) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} + +var ( + _ encoding.BinaryMarshaler = (*TransactionResult)(nil) + _ encoding.BinaryUnmarshaler = (*TransactionResult)(nil) +) + +// xdrType signals that this type represents XDR values defined by this package. +func (s TransactionResult) xdrType() {} + +var _ xdrType = (*TransactionResult)(nil) + +// Hash is an XDR Typedef defines as: +// +// typedef opaque Hash[32]; +type Hash [32]byte + +// XDRMaxSize implements the Sized interface for Hash +func (e Hash) XDRMaxSize() int { + return 32 +} + +// EncodeTo encodes this value using the Encoder. +func (s *Hash) EncodeTo(e *xdr.Encoder) error { + var err error + if _, err = e.EncodeFixedOpaque(s[:]); err != nil { + return err } - return fmt.Errorf("Code (PathPaymentStrictSendResultCode) switch value '%d' is not valid for union PathPaymentStrictSendResult", u.Code) + return nil } -var _ decoderFrom = (*PathPaymentStrictSendResult)(nil) +var _ decoderFrom = (*Hash)(nil) // DecodeFrom decodes this value using the Decoder. -func (u *PathPaymentStrictSendResult) DecodeFrom(d *xdr.Decoder) (int, error) { +func (s *Hash) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding Hash: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = u.Code.DecodeFrom(d) + nTmp, err = d.DecodeFixedOpaqueInplace(s[:]) n += nTmp if err != nil { - return n, fmt.Errorf("decoding PathPaymentStrictSendResultCode: %s", err) - } - switch PathPaymentStrictSendResultCode(u.Code) { - case PathPaymentStrictSendResultCodePathPaymentStrictSendSuccess: - u.Success = new(PathPaymentStrictSendResultSuccess) - nTmp, err = (*u.Success).DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding PathPaymentStrictSendResultSuccess: %s", err) - } - return n, nil - case PathPaymentStrictSendResultCodePathPaymentStrictSendMalformed: - // Void - return n, nil - case PathPaymentStrictSendResultCodePathPaymentStrictSendUnderfunded: - // Void - return n, nil - case PathPaymentStrictSendResultCodePathPaymentStrictSendSrcNoTrust: - // Void - return n, nil - case PathPaymentStrictSendResultCodePathPaymentStrictSendSrcNotAuthorized: - // Void - return n, nil - case PathPaymentStrictSendResultCodePathPaymentStrictSendNoDestination: - // Void - return n, nil - case PathPaymentStrictSendResultCodePathPaymentStrictSendNoTrust: - // Void - return n, nil - case PathPaymentStrictSendResultCodePathPaymentStrictSendNotAuthorized: - // Void - return n, nil - case PathPaymentStrictSendResultCodePathPaymentStrictSendLineFull: - // Void - return n, nil - case PathPaymentStrictSendResultCodePathPaymentStrictSendNoIssuer: - u.NoIssuer = new(Asset) - nTmp, err = (*u.NoIssuer).DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Asset: %s", err) - } - return n, nil - case PathPaymentStrictSendResultCodePathPaymentStrictSendTooFewOffers: - // Void - return n, nil - case PathPaymentStrictSendResultCodePathPaymentStrictSendOfferCrossSelf: - // Void - return n, nil - case PathPaymentStrictSendResultCodePathPaymentStrictSendUnderDestmin: - // Void - return n, nil + return n, fmt.Errorf("decoding Hash: %w", err) } - return n, fmt.Errorf("union PathPaymentStrictSendResult has invalid Code (PathPaymentStrictSendResultCode) switch value '%d'", u.Code) + return n, nil } // MarshalBinary implements encoding.BinaryMarshaler. -func (s PathPaymentStrictSendResult) MarshalBinary() ([]byte, error) { +func (s Hash) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -27894,125 +44707,64 @@ func (s PathPaymentStrictSendResult) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *PathPaymentStrictSendResult) UnmarshalBinary(inp []byte) error { +func (s *Hash) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*PathPaymentStrictSendResult)(nil) - _ encoding.BinaryUnmarshaler = (*PathPaymentStrictSendResult)(nil) + _ encoding.BinaryMarshaler = (*Hash)(nil) + _ encoding.BinaryUnmarshaler = (*Hash)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s PathPaymentStrictSendResult) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s Hash) xdrType() {} -var _ xdrType = (*PathPaymentStrictSendResult)(nil) +var _ xdrType = (*Hash)(nil) -// ManageSellOfferResultCode is an XDR Enum defines as: -// -// enum ManageSellOfferResultCode -// { -// // codes considered as "success" for the operation -// MANAGE_SELL_OFFER_SUCCESS = 0, -// -// // codes considered as "failure" for the operation -// MANAGE_SELL_OFFER_MALFORMED = -1, // generated offer would be invalid -// MANAGE_SELL_OFFER_SELL_NO_TRUST = -// -2, // no trust line for what we're selling -// MANAGE_SELL_OFFER_BUY_NO_TRUST = -3, // no trust line for what we're buying -// MANAGE_SELL_OFFER_SELL_NOT_AUTHORIZED = -4, // not authorized to sell -// MANAGE_SELL_OFFER_BUY_NOT_AUTHORIZED = -5, // not authorized to buy -// MANAGE_SELL_OFFER_LINE_FULL = -6, // can't receive more of what it's buying -// MANAGE_SELL_OFFER_UNDERFUNDED = -7, // doesn't hold what it's trying to sell -// MANAGE_SELL_OFFER_CROSS_SELF = -// -8, // would cross an offer from the same user -// MANAGE_SELL_OFFER_SELL_NO_ISSUER = -9, // no issuer for what we're selling -// MANAGE_SELL_OFFER_BUY_NO_ISSUER = -10, // no issuer for what we're buying -// -// // update errors -// MANAGE_SELL_OFFER_NOT_FOUND = -// -11, // offerID does not match an existing offer +// Uint256 is an XDR Typedef defines as: // -// MANAGE_SELL_OFFER_LOW_RESERVE = -// -12 // not enough funds to create a new Offer -// }; -type ManageSellOfferResultCode int32 - -const ( - ManageSellOfferResultCodeManageSellOfferSuccess ManageSellOfferResultCode = 0 - ManageSellOfferResultCodeManageSellOfferMalformed ManageSellOfferResultCode = -1 - ManageSellOfferResultCodeManageSellOfferSellNoTrust ManageSellOfferResultCode = -2 - ManageSellOfferResultCodeManageSellOfferBuyNoTrust ManageSellOfferResultCode = -3 - ManageSellOfferResultCodeManageSellOfferSellNotAuthorized ManageSellOfferResultCode = -4 - ManageSellOfferResultCodeManageSellOfferBuyNotAuthorized ManageSellOfferResultCode = -5 - ManageSellOfferResultCodeManageSellOfferLineFull ManageSellOfferResultCode = -6 - ManageSellOfferResultCodeManageSellOfferUnderfunded ManageSellOfferResultCode = -7 - ManageSellOfferResultCodeManageSellOfferCrossSelf ManageSellOfferResultCode = -8 - ManageSellOfferResultCodeManageSellOfferSellNoIssuer ManageSellOfferResultCode = -9 - ManageSellOfferResultCodeManageSellOfferBuyNoIssuer ManageSellOfferResultCode = -10 - ManageSellOfferResultCodeManageSellOfferNotFound ManageSellOfferResultCode = -11 - ManageSellOfferResultCodeManageSellOfferLowReserve ManageSellOfferResultCode = -12 -) - -var manageSellOfferResultCodeMap = map[int32]string{ - 0: "ManageSellOfferResultCodeManageSellOfferSuccess", - -1: "ManageSellOfferResultCodeManageSellOfferMalformed", - -2: "ManageSellOfferResultCodeManageSellOfferSellNoTrust", - -3: "ManageSellOfferResultCodeManageSellOfferBuyNoTrust", - -4: "ManageSellOfferResultCodeManageSellOfferSellNotAuthorized", - -5: "ManageSellOfferResultCodeManageSellOfferBuyNotAuthorized", - -6: "ManageSellOfferResultCodeManageSellOfferLineFull", - -7: "ManageSellOfferResultCodeManageSellOfferUnderfunded", - -8: "ManageSellOfferResultCodeManageSellOfferCrossSelf", - -9: "ManageSellOfferResultCodeManageSellOfferSellNoIssuer", - -10: "ManageSellOfferResultCodeManageSellOfferBuyNoIssuer", - -11: "ManageSellOfferResultCodeManageSellOfferNotFound", - -12: "ManageSellOfferResultCodeManageSellOfferLowReserve", -} - -// ValidEnum validates a proposed value for this enum. Implements -// the Enum interface for ManageSellOfferResultCode -func (e ManageSellOfferResultCode) ValidEnum(v int32) bool { - _, ok := manageSellOfferResultCodeMap[v] - return ok -} +// typedef opaque uint256[32]; +type Uint256 [32]byte -// String returns the name of `e` -func (e ManageSellOfferResultCode) String() string { - name, _ := manageSellOfferResultCodeMap[int32(e)] - return name +// XDRMaxSize implements the Sized interface for Uint256 +func (e Uint256) XDRMaxSize() int { + return 32 } // EncodeTo encodes this value using the Encoder. -func (e ManageSellOfferResultCode) EncodeTo(enc *xdr.Encoder) error { - if _, ok := manageSellOfferResultCodeMap[int32(e)]; !ok { - return fmt.Errorf("'%d' is not a valid ManageSellOfferResultCode enum value", e) +func (s *Uint256) EncodeTo(e *xdr.Encoder) error { + var err error + if _, err = e.EncodeFixedOpaque(s[:]); err != nil { + return err } - _, err := enc.EncodeInt(int32(e)) - return err + return nil } -var _ decoderFrom = (*ManageSellOfferResultCode)(nil) +var _ decoderFrom = (*Uint256)(nil) // DecodeFrom decodes this value using the Decoder. -func (e *ManageSellOfferResultCode) DecodeFrom(d *xdr.Decoder) (int, error) { - v, n, err := d.DecodeInt() - if err != nil { - return n, fmt.Errorf("decoding ManageSellOfferResultCode: %s", err) +func (s *Uint256) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding Uint256: %w", ErrMaxDecodingDepthReached) } - if _, ok := manageSellOfferResultCodeMap[v]; !ok { - return n, fmt.Errorf("'%d' is not a valid ManageSellOfferResultCode enum value", v) + maxDepth -= 1 + var err error + var n, nTmp int + nTmp, err = d.DecodeFixedOpaqueInplace(s[:]) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Uint256: %w", err) } - *e = ManageSellOfferResultCode(v) return n, nil } // MarshalBinary implements encoding.BinaryMarshaler. -func (s ManageSellOfferResultCode) MarshalBinary() ([]byte, error) { +func (s Uint256) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -28020,85 +44772,123 @@ func (s ManageSellOfferResultCode) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *ManageSellOfferResultCode) UnmarshalBinary(inp []byte) error { +func (s *Uint256) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*ManageSellOfferResultCode)(nil) - _ encoding.BinaryUnmarshaler = (*ManageSellOfferResultCode)(nil) + _ encoding.BinaryMarshaler = (*Uint256)(nil) + _ encoding.BinaryUnmarshaler = (*Uint256)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s ManageSellOfferResultCode) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s Uint256) xdrType() {} -var _ xdrType = (*ManageSellOfferResultCode)(nil) +var _ xdrType = (*Uint256)(nil) -// ManageOfferEffect is an XDR Enum defines as: +// Uint32 is an XDR Typedef defines as: // -// enum ManageOfferEffect -// { -// MANAGE_OFFER_CREATED = 0, -// MANAGE_OFFER_UPDATED = 1, -// MANAGE_OFFER_DELETED = 2 -// }; -type ManageOfferEffect int32 +// typedef unsigned int uint32; +type Uint32 uint32 -const ( - ManageOfferEffectManageOfferCreated ManageOfferEffect = 0 - ManageOfferEffectManageOfferUpdated ManageOfferEffect = 1 - ManageOfferEffectManageOfferDeleted ManageOfferEffect = 2 -) +// EncodeTo encodes this value using the Encoder. +func (s Uint32) EncodeTo(e *xdr.Encoder) error { + var err error + if _, err = e.EncodeUint(uint32(s)); err != nil { + return err + } + return nil +} -var manageOfferEffectMap = map[int32]string{ - 0: "ManageOfferEffectManageOfferCreated", - 1: "ManageOfferEffectManageOfferUpdated", - 2: "ManageOfferEffectManageOfferDeleted", +var _ decoderFrom = (*Uint32)(nil) + +// DecodeFrom decodes this value using the Decoder. +func (s *Uint32) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding Uint32: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + var err error + var n, nTmp int + var v uint32 + v, nTmp, err = d.DecodeUint() + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Unsigned int: %w", err) + } + *s = Uint32(v) + return n, nil } -// ValidEnum validates a proposed value for this enum. Implements -// the Enum interface for ManageOfferEffect -func (e ManageOfferEffect) ValidEnum(v int32) bool { - _, ok := manageOfferEffectMap[v] - return ok +// MarshalBinary implements encoding.BinaryMarshaler. +func (s Uint32) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err } -// String returns the name of `e` -func (e ManageOfferEffect) String() string { - name, _ := manageOfferEffectMap[int32(e)] - return name +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *Uint32) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err } +var ( + _ encoding.BinaryMarshaler = (*Uint32)(nil) + _ encoding.BinaryUnmarshaler = (*Uint32)(nil) +) + +// xdrType signals that this type represents XDR values defined by this package. +func (s Uint32) xdrType() {} + +var _ xdrType = (*Uint32)(nil) + +// Int32 is an XDR Typedef defines as: +// +// typedef int int32; +type Int32 int32 + // EncodeTo encodes this value using the Encoder. -func (e ManageOfferEffect) EncodeTo(enc *xdr.Encoder) error { - if _, ok := manageOfferEffectMap[int32(e)]; !ok { - return fmt.Errorf("'%d' is not a valid ManageOfferEffect enum value", e) +func (s Int32) EncodeTo(e *xdr.Encoder) error { + var err error + if _, err = e.EncodeInt(int32(s)); err != nil { + return err } - _, err := enc.EncodeInt(int32(e)) - return err + return nil } -var _ decoderFrom = (*ManageOfferEffect)(nil) +var _ decoderFrom = (*Int32)(nil) // DecodeFrom decodes this value using the Decoder. -func (e *ManageOfferEffect) DecodeFrom(d *xdr.Decoder) (int, error) { - v, n, err := d.DecodeInt() - if err != nil { - return n, fmt.Errorf("decoding ManageOfferEffect: %s", err) +func (s *Int32) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding Int32: %w", ErrMaxDecodingDepthReached) } - if _, ok := manageOfferEffectMap[v]; !ok { - return n, fmt.Errorf("'%d' is not a valid ManageOfferEffect enum value", v) + maxDepth -= 1 + var err error + var n, nTmp int + var v int32 + v, nTmp, err = d.DecodeInt() + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Int: %w", err) } - *e = ManageOfferEffect(v) + *s = Int32(v) return n, nil } // MarshalBinary implements encoding.BinaryMarshaler. -func (s ManageOfferEffect) MarshalBinary() ([]byte, error) { +func (s Int32) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -28106,169 +44896,183 @@ func (s ManageOfferEffect) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *ManageOfferEffect) UnmarshalBinary(inp []byte) error { +func (s *Int32) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*ManageOfferEffect)(nil) - _ encoding.BinaryUnmarshaler = (*ManageOfferEffect)(nil) + _ encoding.BinaryMarshaler = (*Int32)(nil) + _ encoding.BinaryUnmarshaler = (*Int32)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s ManageOfferEffect) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s Int32) xdrType() {} -var _ xdrType = (*ManageOfferEffect)(nil) +var _ xdrType = (*Int32)(nil) -// ManageOfferSuccessResultOffer is an XDR NestedUnion defines as: +// Uint64 is an XDR Typedef defines as: // -// union switch (ManageOfferEffect effect) -// { -// case MANAGE_OFFER_CREATED: -// case MANAGE_OFFER_UPDATED: -// OfferEntry offer; -// case MANAGE_OFFER_DELETED: -// void; -// } -type ManageOfferSuccessResultOffer struct { - Effect ManageOfferEffect - Offer *OfferEntry -} - -// SwitchFieldName returns the field name in which this union's -// discriminant is stored -func (u ManageOfferSuccessResultOffer) SwitchFieldName() string { - return "Effect" -} +// typedef unsigned hyper uint64; +type Uint64 uint64 -// ArmForSwitch returns which field name should be used for storing -// the value for an instance of ManageOfferSuccessResultOffer -func (u ManageOfferSuccessResultOffer) ArmForSwitch(sw int32) (string, bool) { - switch ManageOfferEffect(sw) { - case ManageOfferEffectManageOfferCreated: - return "Offer", true - case ManageOfferEffectManageOfferUpdated: - return "Offer", true - case ManageOfferEffectManageOfferDeleted: - return "", true +// EncodeTo encodes this value using the Encoder. +func (s Uint64) EncodeTo(e *xdr.Encoder) error { + var err error + if _, err = e.EncodeUhyper(uint64(s)); err != nil { + return err } - return "-", false + return nil } -// NewManageOfferSuccessResultOffer creates a new ManageOfferSuccessResultOffer. -func NewManageOfferSuccessResultOffer(effect ManageOfferEffect, value interface{}) (result ManageOfferSuccessResultOffer, err error) { - result.Effect = effect - switch ManageOfferEffect(effect) { - case ManageOfferEffectManageOfferCreated: - tv, ok := value.(OfferEntry) - if !ok { - err = fmt.Errorf("invalid value, must be OfferEntry") - return - } - result.Offer = &tv - case ManageOfferEffectManageOfferUpdated: - tv, ok := value.(OfferEntry) - if !ok { - err = fmt.Errorf("invalid value, must be OfferEntry") - return - } - result.Offer = &tv - case ManageOfferEffectManageOfferDeleted: - // void +var _ decoderFrom = (*Uint64)(nil) + +// DecodeFrom decodes this value using the Decoder. +func (s *Uint64) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding Uint64: %w", ErrMaxDecodingDepthReached) } - return + maxDepth -= 1 + var err error + var n, nTmp int + var v uint64 + v, nTmp, err = d.DecodeUhyper() + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Unsigned hyper: %w", err) + } + *s = Uint64(v) + return n, nil } -// MustOffer retrieves the Offer value from the union, -// panicing if the value is not set. -func (u ManageOfferSuccessResultOffer) MustOffer() OfferEntry { - val, ok := u.GetOffer() - - if !ok { - panic("arm Offer is not set") - } +// MarshalBinary implements encoding.BinaryMarshaler. +func (s Uint64) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} - return val +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *Uint64) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err } -// GetOffer retrieves the Offer value from the union, -// returning ok if the union's switch indicated the value is valid. -func (u ManageOfferSuccessResultOffer) GetOffer() (result OfferEntry, ok bool) { - armName, _ := u.ArmForSwitch(int32(u.Effect)) +var ( + _ encoding.BinaryMarshaler = (*Uint64)(nil) + _ encoding.BinaryUnmarshaler = (*Uint64)(nil) +) - if armName == "Offer" { - result = *u.Offer - ok = true - } +// xdrType signals that this type represents XDR values defined by this package. +func (s Uint64) xdrType() {} - return -} +var _ xdrType = (*Uint64)(nil) + +// Int64 is an XDR Typedef defines as: +// +// typedef hyper int64; +type Int64 int64 // EncodeTo encodes this value using the Encoder. -func (u ManageOfferSuccessResultOffer) EncodeTo(e *xdr.Encoder) error { +func (s Int64) EncodeTo(e *xdr.Encoder) error { var err error - if err = u.Effect.EncodeTo(e); err != nil { + if _, err = e.EncodeHyper(int64(s)); err != nil { return err } - switch ManageOfferEffect(u.Effect) { - case ManageOfferEffectManageOfferCreated: - if err = (*u.Offer).EncodeTo(e); err != nil { - return err - } - return nil - case ManageOfferEffectManageOfferUpdated: - if err = (*u.Offer).EncodeTo(e); err != nil { - return err - } - return nil - case ManageOfferEffectManageOfferDeleted: - // Void - return nil - } - return fmt.Errorf("Effect (ManageOfferEffect) switch value '%d' is not valid for union ManageOfferSuccessResultOffer", u.Effect) + return nil } -var _ decoderFrom = (*ManageOfferSuccessResultOffer)(nil) +var _ decoderFrom = (*Int64)(nil) // DecodeFrom decodes this value using the Decoder. -func (u *ManageOfferSuccessResultOffer) DecodeFrom(d *xdr.Decoder) (int, error) { +func (s *Int64) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding Int64: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = u.Effect.DecodeFrom(d) + var v int64 + v, nTmp, err = d.DecodeHyper() n += nTmp if err != nil { - return n, fmt.Errorf("decoding ManageOfferEffect: %s", err) + return n, fmt.Errorf("decoding Hyper: %w", err) } - switch ManageOfferEffect(u.Effect) { - case ManageOfferEffectManageOfferCreated: - u.Offer = new(OfferEntry) - nTmp, err = (*u.Offer).DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding OfferEntry: %s", err) - } - return n, nil - case ManageOfferEffectManageOfferUpdated: - u.Offer = new(OfferEntry) - nTmp, err = (*u.Offer).DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding OfferEntry: %s", err) - } - return n, nil - case ManageOfferEffectManageOfferDeleted: - // Void - return n, nil + *s = Int64(v) + return n, nil +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (s Int64) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *Int64) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} + +var ( + _ encoding.BinaryMarshaler = (*Int64)(nil) + _ encoding.BinaryUnmarshaler = (*Int64)(nil) +) + +// xdrType signals that this type represents XDR values defined by this package. +func (s Int64) xdrType() {} + +var _ xdrType = (*Int64)(nil) + +// TimePoint is an XDR Typedef defines as: +// +// typedef uint64 TimePoint; +type TimePoint Uint64 + +// EncodeTo encodes this value using the Encoder. +func (s TimePoint) EncodeTo(e *xdr.Encoder) error { + var err error + if err = Uint64(s).EncodeTo(e); err != nil { + return err } - return n, fmt.Errorf("union ManageOfferSuccessResultOffer has invalid Effect (ManageOfferEffect) switch value '%d'", u.Effect) + return nil +} + +var _ decoderFrom = (*TimePoint)(nil) + +// DecodeFrom decodes this value using the Decoder. +func (s *TimePoint) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding TimePoint: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + var err error + var n, nTmp int + nTmp, err = (*Uint64)(s).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Uint64: %w", err) + } + return n, nil } // MarshalBinary implements encoding.BinaryMarshaler. -func (s ManageOfferSuccessResultOffer) MarshalBinary() ([]byte, error) { +func (s TimePoint) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -28276,96 +45080,59 @@ func (s ManageOfferSuccessResultOffer) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *ManageOfferSuccessResultOffer) UnmarshalBinary(inp []byte) error { +func (s *TimePoint) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*ManageOfferSuccessResultOffer)(nil) - _ encoding.BinaryUnmarshaler = (*ManageOfferSuccessResultOffer)(nil) + _ encoding.BinaryMarshaler = (*TimePoint)(nil) + _ encoding.BinaryUnmarshaler = (*TimePoint)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s ManageOfferSuccessResultOffer) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s TimePoint) xdrType() {} -var _ xdrType = (*ManageOfferSuccessResultOffer)(nil) +var _ xdrType = (*TimePoint)(nil) -// ManageOfferSuccessResult is an XDR Struct defines as: -// -// struct ManageOfferSuccessResult -// { -// // offers that got claimed while creating this offer -// ClaimAtom offersClaimed<>; +// Duration is an XDR Typedef defines as: // -// union switch (ManageOfferEffect effect) -// { -// case MANAGE_OFFER_CREATED: -// case MANAGE_OFFER_UPDATED: -// OfferEntry offer; -// case MANAGE_OFFER_DELETED: -// void; -// } -// offer; -// }; -type ManageOfferSuccessResult struct { - OffersClaimed []ClaimAtom - Offer ManageOfferSuccessResultOffer -} +// typedef uint64 Duration; +type Duration Uint64 // EncodeTo encodes this value using the Encoder. -func (s *ManageOfferSuccessResult) EncodeTo(e *xdr.Encoder) error { +func (s Duration) EncodeTo(e *xdr.Encoder) error { var err error - if _, err = e.EncodeUint(uint32(len(s.OffersClaimed))); err != nil { - return err - } - for i := 0; i < len(s.OffersClaimed); i++ { - if err = s.OffersClaimed[i].EncodeTo(e); err != nil { - return err - } - } - if err = s.Offer.EncodeTo(e); err != nil { + if err = Uint64(s).EncodeTo(e); err != nil { return err } return nil } -var _ decoderFrom = (*ManageOfferSuccessResult)(nil) +var _ decoderFrom = (*Duration)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *ManageOfferSuccessResult) DecodeFrom(d *xdr.Decoder) (int, error) { +func (s *Duration) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding Duration: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - var l uint32 - l, nTmp, err = d.DecodeUint() - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding ClaimAtom: %s", err) - } - s.OffersClaimed = nil - if l > 0 { - s.OffersClaimed = make([]ClaimAtom, l) - for i := uint32(0); i < l; i++ { - nTmp, err = s.OffersClaimed[i].DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding ClaimAtom: %s", err) - } - } - } - nTmp, err = s.Offer.DecodeFrom(d) + nTmp, err = (*Uint64)(s).DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding ManageOfferSuccessResultOffer: %s", err) + return n, fmt.Errorf("decoding Uint64: %w", err) } return n, nil } // MarshalBinary implements encoding.BinaryMarshaler. -func (s ManageOfferSuccessResult) MarshalBinary() ([]byte, error) { +func (s Duration) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -28373,267 +45140,101 @@ func (s ManageOfferSuccessResult) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *ManageOfferSuccessResult) UnmarshalBinary(inp []byte) error { +func (s *Duration) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*ManageOfferSuccessResult)(nil) - _ encoding.BinaryUnmarshaler = (*ManageOfferSuccessResult)(nil) + _ encoding.BinaryMarshaler = (*Duration)(nil) + _ encoding.BinaryUnmarshaler = (*Duration)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s ManageOfferSuccessResult) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s Duration) xdrType() {} -var _ xdrType = (*ManageOfferSuccessResult)(nil) +var _ xdrType = (*Duration)(nil) -// ManageSellOfferResult is an XDR Union defines as: +// ExtensionPoint is an XDR Union defines as: // -// union ManageSellOfferResult switch (ManageSellOfferResultCode code) +// union ExtensionPoint switch (int v) // { -// case MANAGE_SELL_OFFER_SUCCESS: -// ManageOfferSuccessResult success; -// case MANAGE_SELL_OFFER_MALFORMED: -// case MANAGE_SELL_OFFER_SELL_NO_TRUST: -// case MANAGE_SELL_OFFER_BUY_NO_TRUST: -// case MANAGE_SELL_OFFER_SELL_NOT_AUTHORIZED: -// case MANAGE_SELL_OFFER_BUY_NOT_AUTHORIZED: -// case MANAGE_SELL_OFFER_LINE_FULL: -// case MANAGE_SELL_OFFER_UNDERFUNDED: -// case MANAGE_SELL_OFFER_CROSS_SELF: -// case MANAGE_SELL_OFFER_SELL_NO_ISSUER: -// case MANAGE_SELL_OFFER_BUY_NO_ISSUER: -// case MANAGE_SELL_OFFER_NOT_FOUND: -// case MANAGE_SELL_OFFER_LOW_RESERVE: +// case 0: // void; // }; -type ManageSellOfferResult struct { - Code ManageSellOfferResultCode - Success *ManageOfferSuccessResult +type ExtensionPoint struct { + V int32 } // SwitchFieldName returns the field name in which this union's // discriminant is stored -func (u ManageSellOfferResult) SwitchFieldName() string { - return "Code" +func (u ExtensionPoint) SwitchFieldName() string { + return "V" } // ArmForSwitch returns which field name should be used for storing -// the value for an instance of ManageSellOfferResult -func (u ManageSellOfferResult) ArmForSwitch(sw int32) (string, bool) { - switch ManageSellOfferResultCode(sw) { - case ManageSellOfferResultCodeManageSellOfferSuccess: - return "Success", true - case ManageSellOfferResultCodeManageSellOfferMalformed: - return "", true - case ManageSellOfferResultCodeManageSellOfferSellNoTrust: - return "", true - case ManageSellOfferResultCodeManageSellOfferBuyNoTrust: - return "", true - case ManageSellOfferResultCodeManageSellOfferSellNotAuthorized: - return "", true - case ManageSellOfferResultCodeManageSellOfferBuyNotAuthorized: - return "", true - case ManageSellOfferResultCodeManageSellOfferLineFull: - return "", true - case ManageSellOfferResultCodeManageSellOfferUnderfunded: - return "", true - case ManageSellOfferResultCodeManageSellOfferCrossSelf: - return "", true - case ManageSellOfferResultCodeManageSellOfferSellNoIssuer: - return "", true - case ManageSellOfferResultCodeManageSellOfferBuyNoIssuer: - return "", true - case ManageSellOfferResultCodeManageSellOfferNotFound: - return "", true - case ManageSellOfferResultCodeManageSellOfferLowReserve: +// the value for an instance of ExtensionPoint +func (u ExtensionPoint) ArmForSwitch(sw int32) (string, bool) { + switch int32(sw) { + case 0: return "", true } return "-", false } -// NewManageSellOfferResult creates a new ManageSellOfferResult. -func NewManageSellOfferResult(code ManageSellOfferResultCode, value interface{}) (result ManageSellOfferResult, err error) { - result.Code = code - switch ManageSellOfferResultCode(code) { - case ManageSellOfferResultCodeManageSellOfferSuccess: - tv, ok := value.(ManageOfferSuccessResult) - if !ok { - err = fmt.Errorf("invalid value, must be ManageOfferSuccessResult") - return - } - result.Success = &tv - case ManageSellOfferResultCodeManageSellOfferMalformed: - // void - case ManageSellOfferResultCodeManageSellOfferSellNoTrust: - // void - case ManageSellOfferResultCodeManageSellOfferBuyNoTrust: - // void - case ManageSellOfferResultCodeManageSellOfferSellNotAuthorized: - // void - case ManageSellOfferResultCodeManageSellOfferBuyNotAuthorized: - // void - case ManageSellOfferResultCodeManageSellOfferLineFull: - // void - case ManageSellOfferResultCodeManageSellOfferUnderfunded: - // void - case ManageSellOfferResultCodeManageSellOfferCrossSelf: - // void - case ManageSellOfferResultCodeManageSellOfferSellNoIssuer: - // void - case ManageSellOfferResultCodeManageSellOfferBuyNoIssuer: - // void - case ManageSellOfferResultCodeManageSellOfferNotFound: - // void - case ManageSellOfferResultCodeManageSellOfferLowReserve: +// NewExtensionPoint creates a new ExtensionPoint. +func NewExtensionPoint(v int32, value interface{}) (result ExtensionPoint, err error) { + result.V = v + switch int32(v) { + case 0: // void } return } -// MustSuccess retrieves the Success value from the union, -// panicing if the value is not set. -func (u ManageSellOfferResult) MustSuccess() ManageOfferSuccessResult { - val, ok := u.GetSuccess() - - if !ok { - panic("arm Success is not set") - } - - return val -} - -// GetSuccess retrieves the Success value from the union, -// returning ok if the union's switch indicated the value is valid. -func (u ManageSellOfferResult) GetSuccess() (result ManageOfferSuccessResult, ok bool) { - armName, _ := u.ArmForSwitch(int32(u.Code)) - - if armName == "Success" { - result = *u.Success - ok = true - } - - return -} - // EncodeTo encodes this value using the Encoder. -func (u ManageSellOfferResult) EncodeTo(e *xdr.Encoder) error { +func (u ExtensionPoint) EncodeTo(e *xdr.Encoder) error { var err error - if err = u.Code.EncodeTo(e); err != nil { + if _, err = e.EncodeInt(int32(u.V)); err != nil { return err } - switch ManageSellOfferResultCode(u.Code) { - case ManageSellOfferResultCodeManageSellOfferSuccess: - if err = (*u.Success).EncodeTo(e); err != nil { - return err - } - return nil - case ManageSellOfferResultCodeManageSellOfferMalformed: - // Void - return nil - case ManageSellOfferResultCodeManageSellOfferSellNoTrust: - // Void - return nil - case ManageSellOfferResultCodeManageSellOfferBuyNoTrust: - // Void - return nil - case ManageSellOfferResultCodeManageSellOfferSellNotAuthorized: - // Void - return nil - case ManageSellOfferResultCodeManageSellOfferBuyNotAuthorized: - // Void - return nil - case ManageSellOfferResultCodeManageSellOfferLineFull: - // Void - return nil - case ManageSellOfferResultCodeManageSellOfferUnderfunded: - // Void - return nil - case ManageSellOfferResultCodeManageSellOfferCrossSelf: - // Void - return nil - case ManageSellOfferResultCodeManageSellOfferSellNoIssuer: - // Void - return nil - case ManageSellOfferResultCodeManageSellOfferBuyNoIssuer: - // Void - return nil - case ManageSellOfferResultCodeManageSellOfferNotFound: - // Void - return nil - case ManageSellOfferResultCodeManageSellOfferLowReserve: + switch int32(u.V) { + case 0: // Void return nil } - return fmt.Errorf("Code (ManageSellOfferResultCode) switch value '%d' is not valid for union ManageSellOfferResult", u.Code) + return fmt.Errorf("V (int32) switch value '%d' is not valid for union ExtensionPoint", u.V) } -var _ decoderFrom = (*ManageSellOfferResult)(nil) +var _ decoderFrom = (*ExtensionPoint)(nil) // DecodeFrom decodes this value using the Decoder. -func (u *ManageSellOfferResult) DecodeFrom(d *xdr.Decoder) (int, error) { +func (u *ExtensionPoint) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding ExtensionPoint: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = u.Code.DecodeFrom(d) + u.V, nTmp, err = d.DecodeInt() n += nTmp if err != nil { - return n, fmt.Errorf("decoding ManageSellOfferResultCode: %s", err) + return n, fmt.Errorf("decoding Int: %w", err) } - switch ManageSellOfferResultCode(u.Code) { - case ManageSellOfferResultCodeManageSellOfferSuccess: - u.Success = new(ManageOfferSuccessResult) - nTmp, err = (*u.Success).DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding ManageOfferSuccessResult: %s", err) - } - return n, nil - case ManageSellOfferResultCodeManageSellOfferMalformed: - // Void - return n, nil - case ManageSellOfferResultCodeManageSellOfferSellNoTrust: - // Void - return n, nil - case ManageSellOfferResultCodeManageSellOfferBuyNoTrust: - // Void - return n, nil - case ManageSellOfferResultCodeManageSellOfferSellNotAuthorized: - // Void - return n, nil - case ManageSellOfferResultCodeManageSellOfferBuyNotAuthorized: - // Void - return n, nil - case ManageSellOfferResultCodeManageSellOfferLineFull: - // Void - return n, nil - case ManageSellOfferResultCodeManageSellOfferUnderfunded: - // Void - return n, nil - case ManageSellOfferResultCodeManageSellOfferCrossSelf: - // Void - return n, nil - case ManageSellOfferResultCodeManageSellOfferSellNoIssuer: - // Void - return n, nil - case ManageSellOfferResultCodeManageSellOfferBuyNoIssuer: - // Void - return n, nil - case ManageSellOfferResultCodeManageSellOfferNotFound: - // Void - return n, nil - case ManageSellOfferResultCodeManageSellOfferLowReserve: + switch int32(u.V) { + case 0: // Void return n, nil } - return n, fmt.Errorf("union ManageSellOfferResult has invalid Code (ManageSellOfferResultCode) switch value '%d'", u.Code) + return n, fmt.Errorf("union ExtensionPoint has invalid V (int32) switch value '%d'", u.V) } // MarshalBinary implements encoding.BinaryMarshaler. -func (s ManageSellOfferResult) MarshalBinary() ([]byte, error) { +func (s ExtensionPoint) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -28641,390 +45242,183 @@ func (s ManageSellOfferResult) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *ManageSellOfferResult) UnmarshalBinary(inp []byte) error { +func (s *ExtensionPoint) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*ManageSellOfferResult)(nil) - _ encoding.BinaryUnmarshaler = (*ManageSellOfferResult)(nil) + _ encoding.BinaryMarshaler = (*ExtensionPoint)(nil) + _ encoding.BinaryUnmarshaler = (*ExtensionPoint)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s ManageSellOfferResult) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s ExtensionPoint) xdrType() {} -var _ xdrType = (*ManageSellOfferResult)(nil) +var _ xdrType = (*ExtensionPoint)(nil) -// ManageBuyOfferResultCode is an XDR Enum defines as: +// CryptoKeyType is an XDR Enum defines as: // -// enum ManageBuyOfferResultCode +// enum CryptoKeyType // { -// // codes considered as "success" for the operation -// MANAGE_BUY_OFFER_SUCCESS = 0, -// -// // codes considered as "failure" for the operation -// MANAGE_BUY_OFFER_MALFORMED = -1, // generated offer would be invalid -// MANAGE_BUY_OFFER_SELL_NO_TRUST = -2, // no trust line for what we're selling -// MANAGE_BUY_OFFER_BUY_NO_TRUST = -3, // no trust line for what we're buying -// MANAGE_BUY_OFFER_SELL_NOT_AUTHORIZED = -4, // not authorized to sell -// MANAGE_BUY_OFFER_BUY_NOT_AUTHORIZED = -5, // not authorized to buy -// MANAGE_BUY_OFFER_LINE_FULL = -6, // can't receive more of what it's buying -// MANAGE_BUY_OFFER_UNDERFUNDED = -7, // doesn't hold what it's trying to sell -// MANAGE_BUY_OFFER_CROSS_SELF = -8, // would cross an offer from the same user -// MANAGE_BUY_OFFER_SELL_NO_ISSUER = -9, // no issuer for what we're selling -// MANAGE_BUY_OFFER_BUY_NO_ISSUER = -10, // no issuer for what we're buying -// -// // update errors -// MANAGE_BUY_OFFER_NOT_FOUND = -// -11, // offerID does not match an existing offer -// -// MANAGE_BUY_OFFER_LOW_RESERVE = -12 // not enough funds to create a new Offer +// KEY_TYPE_ED25519 = 0, +// KEY_TYPE_PRE_AUTH_TX = 1, +// KEY_TYPE_HASH_X = 2, +// KEY_TYPE_ED25519_SIGNED_PAYLOAD = 3, +// // MUXED enum values for supported type are derived from the enum values +// // above by ORing them with 0x100 +// KEY_TYPE_MUXED_ED25519 = 0x100 // }; -type ManageBuyOfferResultCode int32 +type CryptoKeyType int32 const ( - ManageBuyOfferResultCodeManageBuyOfferSuccess ManageBuyOfferResultCode = 0 - ManageBuyOfferResultCodeManageBuyOfferMalformed ManageBuyOfferResultCode = -1 - ManageBuyOfferResultCodeManageBuyOfferSellNoTrust ManageBuyOfferResultCode = -2 - ManageBuyOfferResultCodeManageBuyOfferBuyNoTrust ManageBuyOfferResultCode = -3 - ManageBuyOfferResultCodeManageBuyOfferSellNotAuthorized ManageBuyOfferResultCode = -4 - ManageBuyOfferResultCodeManageBuyOfferBuyNotAuthorized ManageBuyOfferResultCode = -5 - ManageBuyOfferResultCodeManageBuyOfferLineFull ManageBuyOfferResultCode = -6 - ManageBuyOfferResultCodeManageBuyOfferUnderfunded ManageBuyOfferResultCode = -7 - ManageBuyOfferResultCodeManageBuyOfferCrossSelf ManageBuyOfferResultCode = -8 - ManageBuyOfferResultCodeManageBuyOfferSellNoIssuer ManageBuyOfferResultCode = -9 - ManageBuyOfferResultCodeManageBuyOfferBuyNoIssuer ManageBuyOfferResultCode = -10 - ManageBuyOfferResultCodeManageBuyOfferNotFound ManageBuyOfferResultCode = -11 - ManageBuyOfferResultCodeManageBuyOfferLowReserve ManageBuyOfferResultCode = -12 -) - -var manageBuyOfferResultCodeMap = map[int32]string{ - 0: "ManageBuyOfferResultCodeManageBuyOfferSuccess", - -1: "ManageBuyOfferResultCodeManageBuyOfferMalformed", - -2: "ManageBuyOfferResultCodeManageBuyOfferSellNoTrust", - -3: "ManageBuyOfferResultCodeManageBuyOfferBuyNoTrust", - -4: "ManageBuyOfferResultCodeManageBuyOfferSellNotAuthorized", - -5: "ManageBuyOfferResultCodeManageBuyOfferBuyNotAuthorized", - -6: "ManageBuyOfferResultCodeManageBuyOfferLineFull", - -7: "ManageBuyOfferResultCodeManageBuyOfferUnderfunded", - -8: "ManageBuyOfferResultCodeManageBuyOfferCrossSelf", - -9: "ManageBuyOfferResultCodeManageBuyOfferSellNoIssuer", - -10: "ManageBuyOfferResultCodeManageBuyOfferBuyNoIssuer", - -11: "ManageBuyOfferResultCodeManageBuyOfferNotFound", - -12: "ManageBuyOfferResultCodeManageBuyOfferLowReserve", -} - -// ValidEnum validates a proposed value for this enum. Implements -// the Enum interface for ManageBuyOfferResultCode -func (e ManageBuyOfferResultCode) ValidEnum(v int32) bool { - _, ok := manageBuyOfferResultCodeMap[v] - return ok -} - -// String returns the name of `e` -func (e ManageBuyOfferResultCode) String() string { - name, _ := manageBuyOfferResultCodeMap[int32(e)] - return name -} - -// EncodeTo encodes this value using the Encoder. -func (e ManageBuyOfferResultCode) EncodeTo(enc *xdr.Encoder) error { - if _, ok := manageBuyOfferResultCodeMap[int32(e)]; !ok { - return fmt.Errorf("'%d' is not a valid ManageBuyOfferResultCode enum value", e) - } - _, err := enc.EncodeInt(int32(e)) - return err -} - -var _ decoderFrom = (*ManageBuyOfferResultCode)(nil) - -// DecodeFrom decodes this value using the Decoder. -func (e *ManageBuyOfferResultCode) DecodeFrom(d *xdr.Decoder) (int, error) { - v, n, err := d.DecodeInt() - if err != nil { - return n, fmt.Errorf("decoding ManageBuyOfferResultCode: %s", err) - } - if _, ok := manageBuyOfferResultCodeMap[v]; !ok { - return n, fmt.Errorf("'%d' is not a valid ManageBuyOfferResultCode enum value", v) - } - *e = ManageBuyOfferResultCode(v) - return n, nil -} - -// MarshalBinary implements encoding.BinaryMarshaler. -func (s ManageBuyOfferResultCode) MarshalBinary() ([]byte, error) { - b := bytes.Buffer{} - e := xdr.NewEncoder(&b) - err := s.EncodeTo(e) - return b.Bytes(), err -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *ManageBuyOfferResultCode) UnmarshalBinary(inp []byte) error { - r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) - return err -} - -var ( - _ encoding.BinaryMarshaler = (*ManageBuyOfferResultCode)(nil) - _ encoding.BinaryUnmarshaler = (*ManageBuyOfferResultCode)(nil) + CryptoKeyTypeKeyTypeEd25519 CryptoKeyType = 0 + CryptoKeyTypeKeyTypePreAuthTx CryptoKeyType = 1 + CryptoKeyTypeKeyTypeHashX CryptoKeyType = 2 + CryptoKeyTypeKeyTypeEd25519SignedPayload CryptoKeyType = 3 + CryptoKeyTypeKeyTypeMuxedEd25519 CryptoKeyType = 256 ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s ManageBuyOfferResultCode) xdrType() {} - -var _ xdrType = (*ManageBuyOfferResultCode)(nil) - -// ManageBuyOfferResult is an XDR Union defines as: -// -// union ManageBuyOfferResult switch (ManageBuyOfferResultCode code) -// { -// case MANAGE_BUY_OFFER_SUCCESS: -// ManageOfferSuccessResult success; -// case MANAGE_BUY_OFFER_MALFORMED: -// case MANAGE_BUY_OFFER_SELL_NO_TRUST: -// case MANAGE_BUY_OFFER_BUY_NO_TRUST: -// case MANAGE_BUY_OFFER_SELL_NOT_AUTHORIZED: -// case MANAGE_BUY_OFFER_BUY_NOT_AUTHORIZED: -// case MANAGE_BUY_OFFER_LINE_FULL: -// case MANAGE_BUY_OFFER_UNDERFUNDED: -// case MANAGE_BUY_OFFER_CROSS_SELF: -// case MANAGE_BUY_OFFER_SELL_NO_ISSUER: -// case MANAGE_BUY_OFFER_BUY_NO_ISSUER: -// case MANAGE_BUY_OFFER_NOT_FOUND: -// case MANAGE_BUY_OFFER_LOW_RESERVE: -// void; -// }; -type ManageBuyOfferResult struct { - Code ManageBuyOfferResultCode - Success *ManageOfferSuccessResult -} - -// SwitchFieldName returns the field name in which this union's -// discriminant is stored -func (u ManageBuyOfferResult) SwitchFieldName() string { - return "Code" -} - -// ArmForSwitch returns which field name should be used for storing -// the value for an instance of ManageBuyOfferResult -func (u ManageBuyOfferResult) ArmForSwitch(sw int32) (string, bool) { - switch ManageBuyOfferResultCode(sw) { - case ManageBuyOfferResultCodeManageBuyOfferSuccess: - return "Success", true - case ManageBuyOfferResultCodeManageBuyOfferMalformed: - return "", true - case ManageBuyOfferResultCodeManageBuyOfferSellNoTrust: - return "", true - case ManageBuyOfferResultCodeManageBuyOfferBuyNoTrust: - return "", true - case ManageBuyOfferResultCodeManageBuyOfferSellNotAuthorized: - return "", true - case ManageBuyOfferResultCodeManageBuyOfferBuyNotAuthorized: - return "", true - case ManageBuyOfferResultCodeManageBuyOfferLineFull: - return "", true - case ManageBuyOfferResultCodeManageBuyOfferUnderfunded: - return "", true - case ManageBuyOfferResultCodeManageBuyOfferCrossSelf: - return "", true - case ManageBuyOfferResultCodeManageBuyOfferSellNoIssuer: - return "", true - case ManageBuyOfferResultCodeManageBuyOfferBuyNoIssuer: - return "", true - case ManageBuyOfferResultCodeManageBuyOfferNotFound: - return "", true - case ManageBuyOfferResultCodeManageBuyOfferLowReserve: - return "", true - } - return "-", false +var cryptoKeyTypeMap = map[int32]string{ + 0: "CryptoKeyTypeKeyTypeEd25519", + 1: "CryptoKeyTypeKeyTypePreAuthTx", + 2: "CryptoKeyTypeKeyTypeHashX", + 3: "CryptoKeyTypeKeyTypeEd25519SignedPayload", + 256: "CryptoKeyTypeKeyTypeMuxedEd25519", } -// NewManageBuyOfferResult creates a new ManageBuyOfferResult. -func NewManageBuyOfferResult(code ManageBuyOfferResultCode, value interface{}) (result ManageBuyOfferResult, err error) { - result.Code = code - switch ManageBuyOfferResultCode(code) { - case ManageBuyOfferResultCodeManageBuyOfferSuccess: - tv, ok := value.(ManageOfferSuccessResult) - if !ok { - err = fmt.Errorf("invalid value, must be ManageOfferSuccessResult") - return - } - result.Success = &tv - case ManageBuyOfferResultCodeManageBuyOfferMalformed: - // void - case ManageBuyOfferResultCodeManageBuyOfferSellNoTrust: - // void - case ManageBuyOfferResultCodeManageBuyOfferBuyNoTrust: - // void - case ManageBuyOfferResultCodeManageBuyOfferSellNotAuthorized: - // void - case ManageBuyOfferResultCodeManageBuyOfferBuyNotAuthorized: - // void - case ManageBuyOfferResultCodeManageBuyOfferLineFull: - // void - case ManageBuyOfferResultCodeManageBuyOfferUnderfunded: - // void - case ManageBuyOfferResultCodeManageBuyOfferCrossSelf: - // void - case ManageBuyOfferResultCodeManageBuyOfferSellNoIssuer: - // void - case ManageBuyOfferResultCodeManageBuyOfferBuyNoIssuer: - // void - case ManageBuyOfferResultCodeManageBuyOfferNotFound: - // void - case ManageBuyOfferResultCodeManageBuyOfferLowReserve: - // void +// ValidEnum validates a proposed value for this enum. Implements +// the Enum interface for CryptoKeyType +func (e CryptoKeyType) ValidEnum(v int32) bool { + _, ok := cryptoKeyTypeMap[v] + return ok +} + +// String returns the name of `e` +func (e CryptoKeyType) String() string { + name, _ := cryptoKeyTypeMap[int32(e)] + return name +} + +// EncodeTo encodes this value using the Encoder. +func (e CryptoKeyType) EncodeTo(enc *xdr.Encoder) error { + if _, ok := cryptoKeyTypeMap[int32(e)]; !ok { + return fmt.Errorf("'%d' is not a valid CryptoKeyType enum value", e) } - return + _, err := enc.EncodeInt(int32(e)) + return err } -// MustSuccess retrieves the Success value from the union, -// panicing if the value is not set. -func (u ManageBuyOfferResult) MustSuccess() ManageOfferSuccessResult { - val, ok := u.GetSuccess() +var _ decoderFrom = (*CryptoKeyType)(nil) - if !ok { - panic("arm Success is not set") +// DecodeFrom decodes this value using the Decoder. +func (e *CryptoKeyType) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding CryptoKeyType: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + v, n, err := d.DecodeInt() + if err != nil { + return n, fmt.Errorf("decoding CryptoKeyType: %w", err) + } + if _, ok := cryptoKeyTypeMap[v]; !ok { + return n, fmt.Errorf("'%d' is not a valid CryptoKeyType enum value", v) } + *e = CryptoKeyType(v) + return n, nil +} - return val +// MarshalBinary implements encoding.BinaryMarshaler. +func (s CryptoKeyType) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err } -// GetSuccess retrieves the Success value from the union, -// returning ok if the union's switch indicated the value is valid. -func (u ManageBuyOfferResult) GetSuccess() (result ManageOfferSuccessResult, ok bool) { - armName, _ := u.ArmForSwitch(int32(u.Code)) +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *CryptoKeyType) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} - if armName == "Success" { - result = *u.Success - ok = true - } +var ( + _ encoding.BinaryMarshaler = (*CryptoKeyType)(nil) + _ encoding.BinaryUnmarshaler = (*CryptoKeyType)(nil) +) - return +// xdrType signals that this type represents XDR values defined by this package. +func (s CryptoKeyType) xdrType() {} + +var _ xdrType = (*CryptoKeyType)(nil) + +// PublicKeyType is an XDR Enum defines as: +// +// enum PublicKeyType +// { +// PUBLIC_KEY_TYPE_ED25519 = KEY_TYPE_ED25519 +// }; +type PublicKeyType int32 + +const ( + PublicKeyTypePublicKeyTypeEd25519 PublicKeyType = 0 +) + +var publicKeyTypeMap = map[int32]string{ + 0: "PublicKeyTypePublicKeyTypeEd25519", +} + +// ValidEnum validates a proposed value for this enum. Implements +// the Enum interface for PublicKeyType +func (e PublicKeyType) ValidEnum(v int32) bool { + _, ok := publicKeyTypeMap[v] + return ok +} + +// String returns the name of `e` +func (e PublicKeyType) String() string { + name, _ := publicKeyTypeMap[int32(e)] + return name } // EncodeTo encodes this value using the Encoder. -func (u ManageBuyOfferResult) EncodeTo(e *xdr.Encoder) error { - var err error - if err = u.Code.EncodeTo(e); err != nil { - return err - } - switch ManageBuyOfferResultCode(u.Code) { - case ManageBuyOfferResultCodeManageBuyOfferSuccess: - if err = (*u.Success).EncodeTo(e); err != nil { - return err - } - return nil - case ManageBuyOfferResultCodeManageBuyOfferMalformed: - // Void - return nil - case ManageBuyOfferResultCodeManageBuyOfferSellNoTrust: - // Void - return nil - case ManageBuyOfferResultCodeManageBuyOfferBuyNoTrust: - // Void - return nil - case ManageBuyOfferResultCodeManageBuyOfferSellNotAuthorized: - // Void - return nil - case ManageBuyOfferResultCodeManageBuyOfferBuyNotAuthorized: - // Void - return nil - case ManageBuyOfferResultCodeManageBuyOfferLineFull: - // Void - return nil - case ManageBuyOfferResultCodeManageBuyOfferUnderfunded: - // Void - return nil - case ManageBuyOfferResultCodeManageBuyOfferCrossSelf: - // Void - return nil - case ManageBuyOfferResultCodeManageBuyOfferSellNoIssuer: - // Void - return nil - case ManageBuyOfferResultCodeManageBuyOfferBuyNoIssuer: - // Void - return nil - case ManageBuyOfferResultCodeManageBuyOfferNotFound: - // Void - return nil - case ManageBuyOfferResultCodeManageBuyOfferLowReserve: - // Void - return nil +func (e PublicKeyType) EncodeTo(enc *xdr.Encoder) error { + if _, ok := publicKeyTypeMap[int32(e)]; !ok { + return fmt.Errorf("'%d' is not a valid PublicKeyType enum value", e) } - return fmt.Errorf("Code (ManageBuyOfferResultCode) switch value '%d' is not valid for union ManageBuyOfferResult", u.Code) + _, err := enc.EncodeInt(int32(e)) + return err } -var _ decoderFrom = (*ManageBuyOfferResult)(nil) +var _ decoderFrom = (*PublicKeyType)(nil) // DecodeFrom decodes this value using the Decoder. -func (u *ManageBuyOfferResult) DecodeFrom(d *xdr.Decoder) (int, error) { - var err error - var n, nTmp int - nTmp, err = u.Code.DecodeFrom(d) - n += nTmp +func (e *PublicKeyType) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding PublicKeyType: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + v, n, err := d.DecodeInt() if err != nil { - return n, fmt.Errorf("decoding ManageBuyOfferResultCode: %s", err) + return n, fmt.Errorf("decoding PublicKeyType: %w", err) } - switch ManageBuyOfferResultCode(u.Code) { - case ManageBuyOfferResultCodeManageBuyOfferSuccess: - u.Success = new(ManageOfferSuccessResult) - nTmp, err = (*u.Success).DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding ManageOfferSuccessResult: %s", err) - } - return n, nil - case ManageBuyOfferResultCodeManageBuyOfferMalformed: - // Void - return n, nil - case ManageBuyOfferResultCodeManageBuyOfferSellNoTrust: - // Void - return n, nil - case ManageBuyOfferResultCodeManageBuyOfferBuyNoTrust: - // Void - return n, nil - case ManageBuyOfferResultCodeManageBuyOfferSellNotAuthorized: - // Void - return n, nil - case ManageBuyOfferResultCodeManageBuyOfferBuyNotAuthorized: - // Void - return n, nil - case ManageBuyOfferResultCodeManageBuyOfferLineFull: - // Void - return n, nil - case ManageBuyOfferResultCodeManageBuyOfferUnderfunded: - // Void - return n, nil - case ManageBuyOfferResultCodeManageBuyOfferCrossSelf: - // Void - return n, nil - case ManageBuyOfferResultCodeManageBuyOfferSellNoIssuer: - // Void - return n, nil - case ManageBuyOfferResultCodeManageBuyOfferBuyNoIssuer: - // Void - return n, nil - case ManageBuyOfferResultCodeManageBuyOfferNotFound: - // Void - return n, nil - case ManageBuyOfferResultCodeManageBuyOfferLowReserve: - // Void - return n, nil + if _, ok := publicKeyTypeMap[v]; !ok { + return n, fmt.Errorf("'%d' is not a valid PublicKeyType enum value", v) } - return n, fmt.Errorf("union ManageBuyOfferResult has invalid Code (ManageBuyOfferResultCode) switch value '%d'", u.Code) + *e = PublicKeyType(v) + return n, nil } // MarshalBinary implements encoding.BinaryMarshaler. -func (s ManageBuyOfferResult) MarshalBinary() ([]byte, error) { +func (s PublicKeyType) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -29032,112 +45426,93 @@ func (s ManageBuyOfferResult) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *ManageBuyOfferResult) UnmarshalBinary(inp []byte) error { +func (s *PublicKeyType) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*ManageBuyOfferResult)(nil) - _ encoding.BinaryUnmarshaler = (*ManageBuyOfferResult)(nil) + _ encoding.BinaryMarshaler = (*PublicKeyType)(nil) + _ encoding.BinaryUnmarshaler = (*PublicKeyType)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s ManageBuyOfferResult) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s PublicKeyType) xdrType() {} -var _ xdrType = (*ManageBuyOfferResult)(nil) +var _ xdrType = (*PublicKeyType)(nil) -// SetOptionsResultCode is an XDR Enum defines as: +// SignerKeyType is an XDR Enum defines as: // -// enum SetOptionsResultCode +// enum SignerKeyType // { -// // codes considered as "success" for the operation -// SET_OPTIONS_SUCCESS = 0, -// // codes considered as "failure" for the operation -// SET_OPTIONS_LOW_RESERVE = -1, // not enough funds to add a signer -// SET_OPTIONS_TOO_MANY_SIGNERS = -2, // max number of signers already reached -// SET_OPTIONS_BAD_FLAGS = -3, // invalid combination of clear/set flags -// SET_OPTIONS_INVALID_INFLATION = -4, // inflation account does not exist -// SET_OPTIONS_CANT_CHANGE = -5, // can no longer change this option -// SET_OPTIONS_UNKNOWN_FLAG = -6, // can't set an unknown flag -// SET_OPTIONS_THRESHOLD_OUT_OF_RANGE = -7, // bad value for weight/threshold -// SET_OPTIONS_BAD_SIGNER = -8, // signer cannot be masterkey -// SET_OPTIONS_INVALID_HOME_DOMAIN = -9, // malformed home domain -// SET_OPTIONS_AUTH_REVOCABLE_REQUIRED = -// -10 // auth revocable is required for clawback +// SIGNER_KEY_TYPE_ED25519 = KEY_TYPE_ED25519, +// SIGNER_KEY_TYPE_PRE_AUTH_TX = KEY_TYPE_PRE_AUTH_TX, +// SIGNER_KEY_TYPE_HASH_X = KEY_TYPE_HASH_X, +// SIGNER_KEY_TYPE_ED25519_SIGNED_PAYLOAD = KEY_TYPE_ED25519_SIGNED_PAYLOAD // }; -type SetOptionsResultCode int32 +type SignerKeyType int32 const ( - SetOptionsResultCodeSetOptionsSuccess SetOptionsResultCode = 0 - SetOptionsResultCodeSetOptionsLowReserve SetOptionsResultCode = -1 - SetOptionsResultCodeSetOptionsTooManySigners SetOptionsResultCode = -2 - SetOptionsResultCodeSetOptionsBadFlags SetOptionsResultCode = -3 - SetOptionsResultCodeSetOptionsInvalidInflation SetOptionsResultCode = -4 - SetOptionsResultCodeSetOptionsCantChange SetOptionsResultCode = -5 - SetOptionsResultCodeSetOptionsUnknownFlag SetOptionsResultCode = -6 - SetOptionsResultCodeSetOptionsThresholdOutOfRange SetOptionsResultCode = -7 - SetOptionsResultCodeSetOptionsBadSigner SetOptionsResultCode = -8 - SetOptionsResultCodeSetOptionsInvalidHomeDomain SetOptionsResultCode = -9 - SetOptionsResultCodeSetOptionsAuthRevocableRequired SetOptionsResultCode = -10 + SignerKeyTypeSignerKeyTypeEd25519 SignerKeyType = 0 + SignerKeyTypeSignerKeyTypePreAuthTx SignerKeyType = 1 + SignerKeyTypeSignerKeyTypeHashX SignerKeyType = 2 + SignerKeyTypeSignerKeyTypeEd25519SignedPayload SignerKeyType = 3 ) -var setOptionsResultCodeMap = map[int32]string{ - 0: "SetOptionsResultCodeSetOptionsSuccess", - -1: "SetOptionsResultCodeSetOptionsLowReserve", - -2: "SetOptionsResultCodeSetOptionsTooManySigners", - -3: "SetOptionsResultCodeSetOptionsBadFlags", - -4: "SetOptionsResultCodeSetOptionsInvalidInflation", - -5: "SetOptionsResultCodeSetOptionsCantChange", - -6: "SetOptionsResultCodeSetOptionsUnknownFlag", - -7: "SetOptionsResultCodeSetOptionsThresholdOutOfRange", - -8: "SetOptionsResultCodeSetOptionsBadSigner", - -9: "SetOptionsResultCodeSetOptionsInvalidHomeDomain", - -10: "SetOptionsResultCodeSetOptionsAuthRevocableRequired", +var signerKeyTypeMap = map[int32]string{ + 0: "SignerKeyTypeSignerKeyTypeEd25519", + 1: "SignerKeyTypeSignerKeyTypePreAuthTx", + 2: "SignerKeyTypeSignerKeyTypeHashX", + 3: "SignerKeyTypeSignerKeyTypeEd25519SignedPayload", } // ValidEnum validates a proposed value for this enum. Implements -// the Enum interface for SetOptionsResultCode -func (e SetOptionsResultCode) ValidEnum(v int32) bool { - _, ok := setOptionsResultCodeMap[v] +// the Enum interface for SignerKeyType +func (e SignerKeyType) ValidEnum(v int32) bool { + _, ok := signerKeyTypeMap[v] return ok } // String returns the name of `e` -func (e SetOptionsResultCode) String() string { - name, _ := setOptionsResultCodeMap[int32(e)] +func (e SignerKeyType) String() string { + name, _ := signerKeyTypeMap[int32(e)] return name } // EncodeTo encodes this value using the Encoder. -func (e SetOptionsResultCode) EncodeTo(enc *xdr.Encoder) error { - if _, ok := setOptionsResultCodeMap[int32(e)]; !ok { - return fmt.Errorf("'%d' is not a valid SetOptionsResultCode enum value", e) +func (e SignerKeyType) EncodeTo(enc *xdr.Encoder) error { + if _, ok := signerKeyTypeMap[int32(e)]; !ok { + return fmt.Errorf("'%d' is not a valid SignerKeyType enum value", e) } _, err := enc.EncodeInt(int32(e)) return err } -var _ decoderFrom = (*SetOptionsResultCode)(nil) +var _ decoderFrom = (*SignerKeyType)(nil) // DecodeFrom decodes this value using the Decoder. -func (e *SetOptionsResultCode) DecodeFrom(d *xdr.Decoder) (int, error) { +func (e *SignerKeyType) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding SignerKeyType: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 v, n, err := d.DecodeInt() if err != nil { - return n, fmt.Errorf("decoding SetOptionsResultCode: %s", err) + return n, fmt.Errorf("decoding SignerKeyType: %w", err) } - if _, ok := setOptionsResultCodeMap[v]; !ok { - return n, fmt.Errorf("'%d' is not a valid SetOptionsResultCode enum value", v) + if _, ok := signerKeyTypeMap[v]; !ok { + return n, fmt.Errorf("'%d' is not a valid SignerKeyType enum value", v) } - *e = SetOptionsResultCode(v) + *e = SignerKeyType(v) return n, nil } // MarshalBinary implements encoding.BinaryMarshaler. -func (s SetOptionsResultCode) MarshalBinary() ([]byte, error) { +func (s SignerKeyType) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -29145,207 +45520,139 @@ func (s SetOptionsResultCode) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *SetOptionsResultCode) UnmarshalBinary(inp []byte) error { +func (s *SignerKeyType) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*SetOptionsResultCode)(nil) - _ encoding.BinaryUnmarshaler = (*SetOptionsResultCode)(nil) + _ encoding.BinaryMarshaler = (*SignerKeyType)(nil) + _ encoding.BinaryUnmarshaler = (*SignerKeyType)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s SetOptionsResultCode) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s SignerKeyType) xdrType() {} -var _ xdrType = (*SetOptionsResultCode)(nil) +var _ xdrType = (*SignerKeyType)(nil) -// SetOptionsResult is an XDR Union defines as: +// PublicKey is an XDR Union defines as: // -// union SetOptionsResult switch (SetOptionsResultCode code) +// union PublicKey switch (PublicKeyType type) // { -// case SET_OPTIONS_SUCCESS: -// void; -// case SET_OPTIONS_LOW_RESERVE: -// case SET_OPTIONS_TOO_MANY_SIGNERS: -// case SET_OPTIONS_BAD_FLAGS: -// case SET_OPTIONS_INVALID_INFLATION: -// case SET_OPTIONS_CANT_CHANGE: -// case SET_OPTIONS_UNKNOWN_FLAG: -// case SET_OPTIONS_THRESHOLD_OUT_OF_RANGE: -// case SET_OPTIONS_BAD_SIGNER: -// case SET_OPTIONS_INVALID_HOME_DOMAIN: -// case SET_OPTIONS_AUTH_REVOCABLE_REQUIRED: -// void; +// case PUBLIC_KEY_TYPE_ED25519: +// uint256 ed25519; // }; -type SetOptionsResult struct { - Code SetOptionsResultCode +type PublicKey struct { + Type PublicKeyType + Ed25519 *Uint256 } // SwitchFieldName returns the field name in which this union's // discriminant is stored -func (u SetOptionsResult) SwitchFieldName() string { - return "Code" +func (u PublicKey) SwitchFieldName() string { + return "Type" } // ArmForSwitch returns which field name should be used for storing -// the value for an instance of SetOptionsResult -func (u SetOptionsResult) ArmForSwitch(sw int32) (string, bool) { - switch SetOptionsResultCode(sw) { - case SetOptionsResultCodeSetOptionsSuccess: - return "", true - case SetOptionsResultCodeSetOptionsLowReserve: - return "", true - case SetOptionsResultCodeSetOptionsTooManySigners: - return "", true - case SetOptionsResultCodeSetOptionsBadFlags: - return "", true - case SetOptionsResultCodeSetOptionsInvalidInflation: - return "", true - case SetOptionsResultCodeSetOptionsCantChange: - return "", true - case SetOptionsResultCodeSetOptionsUnknownFlag: - return "", true - case SetOptionsResultCodeSetOptionsThresholdOutOfRange: - return "", true - case SetOptionsResultCodeSetOptionsBadSigner: - return "", true - case SetOptionsResultCodeSetOptionsInvalidHomeDomain: - return "", true - case SetOptionsResultCodeSetOptionsAuthRevocableRequired: - return "", true +// the value for an instance of PublicKey +func (u PublicKey) ArmForSwitch(sw int32) (string, bool) { + switch PublicKeyType(sw) { + case PublicKeyTypePublicKeyTypeEd25519: + return "Ed25519", true } return "-", false } -// NewSetOptionsResult creates a new SetOptionsResult. -func NewSetOptionsResult(code SetOptionsResultCode, value interface{}) (result SetOptionsResult, err error) { - result.Code = code - switch SetOptionsResultCode(code) { - case SetOptionsResultCodeSetOptionsSuccess: - // void - case SetOptionsResultCodeSetOptionsLowReserve: - // void - case SetOptionsResultCodeSetOptionsTooManySigners: - // void - case SetOptionsResultCodeSetOptionsBadFlags: - // void - case SetOptionsResultCodeSetOptionsInvalidInflation: - // void - case SetOptionsResultCodeSetOptionsCantChange: - // void - case SetOptionsResultCodeSetOptionsUnknownFlag: - // void - case SetOptionsResultCodeSetOptionsThresholdOutOfRange: - // void - case SetOptionsResultCodeSetOptionsBadSigner: - // void - case SetOptionsResultCodeSetOptionsInvalidHomeDomain: - // void - case SetOptionsResultCodeSetOptionsAuthRevocableRequired: - // void +// NewPublicKey creates a new PublicKey. +func NewPublicKey(aType PublicKeyType, value interface{}) (result PublicKey, err error) { + result.Type = aType + switch PublicKeyType(aType) { + case PublicKeyTypePublicKeyTypeEd25519: + tv, ok := value.(Uint256) + if !ok { + err = errors.New("invalid value, must be Uint256") + return + } + result.Ed25519 = &tv + } + return +} + +// MustEd25519 retrieves the Ed25519 value from the union, +// panicing if the value is not set. +func (u PublicKey) MustEd25519() Uint256 { + val, ok := u.GetEd25519() + + if !ok { + panic("arm Ed25519 is not set") + } + + return val +} + +// GetEd25519 retrieves the Ed25519 value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u PublicKey) GetEd25519() (result Uint256, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) + + if armName == "Ed25519" { + result = *u.Ed25519 + ok = true } + return } // EncodeTo encodes this value using the Encoder. -func (u SetOptionsResult) EncodeTo(e *xdr.Encoder) error { +func (u PublicKey) EncodeTo(e *xdr.Encoder) error { var err error - if err = u.Code.EncodeTo(e); err != nil { + if err = u.Type.EncodeTo(e); err != nil { return err } - switch SetOptionsResultCode(u.Code) { - case SetOptionsResultCodeSetOptionsSuccess: - // Void - return nil - case SetOptionsResultCodeSetOptionsLowReserve: - // Void - return nil - case SetOptionsResultCodeSetOptionsTooManySigners: - // Void - return nil - case SetOptionsResultCodeSetOptionsBadFlags: - // Void - return nil - case SetOptionsResultCodeSetOptionsInvalidInflation: - // Void - return nil - case SetOptionsResultCodeSetOptionsCantChange: - // Void - return nil - case SetOptionsResultCodeSetOptionsUnknownFlag: - // Void - return nil - case SetOptionsResultCodeSetOptionsThresholdOutOfRange: - // Void - return nil - case SetOptionsResultCodeSetOptionsBadSigner: - // Void - return nil - case SetOptionsResultCodeSetOptionsInvalidHomeDomain: - // Void - return nil - case SetOptionsResultCodeSetOptionsAuthRevocableRequired: - // Void + switch PublicKeyType(u.Type) { + case PublicKeyTypePublicKeyTypeEd25519: + if err = (*u.Ed25519).EncodeTo(e); err != nil { + return err + } return nil } - return fmt.Errorf("Code (SetOptionsResultCode) switch value '%d' is not valid for union SetOptionsResult", u.Code) + return fmt.Errorf("Type (PublicKeyType) switch value '%d' is not valid for union PublicKey", u.Type) } -var _ decoderFrom = (*SetOptionsResult)(nil) +var _ decoderFrom = (*PublicKey)(nil) // DecodeFrom decodes this value using the Decoder. -func (u *SetOptionsResult) DecodeFrom(d *xdr.Decoder) (int, error) { +func (u *PublicKey) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding PublicKey: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = u.Code.DecodeFrom(d) + nTmp, err = u.Type.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding SetOptionsResultCode: %s", err) + return n, fmt.Errorf("decoding PublicKeyType: %w", err) } - switch SetOptionsResultCode(u.Code) { - case SetOptionsResultCodeSetOptionsSuccess: - // Void - return n, nil - case SetOptionsResultCodeSetOptionsLowReserve: - // Void - return n, nil - case SetOptionsResultCodeSetOptionsTooManySigners: - // Void - return n, nil - case SetOptionsResultCodeSetOptionsBadFlags: - // Void - return n, nil - case SetOptionsResultCodeSetOptionsInvalidInflation: - // Void - return n, nil - case SetOptionsResultCodeSetOptionsCantChange: - // Void - return n, nil - case SetOptionsResultCodeSetOptionsUnknownFlag: - // Void - return n, nil - case SetOptionsResultCodeSetOptionsThresholdOutOfRange: - // Void - return n, nil - case SetOptionsResultCodeSetOptionsBadSigner: - // Void - return n, nil - case SetOptionsResultCodeSetOptionsInvalidHomeDomain: - // Void - return n, nil - case SetOptionsResultCodeSetOptionsAuthRevocableRequired: - // Void + switch PublicKeyType(u.Type) { + case PublicKeyTypePublicKeyTypeEd25519: + u.Ed25519 = new(Uint256) + nTmp, err = (*u.Ed25519).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Uint256: %w", err) + } return n, nil } - return n, fmt.Errorf("union SetOptionsResult has invalid Code (SetOptionsResultCode) switch value '%d'", u.Code) + return n, fmt.Errorf("union PublicKey has invalid Type (PublicKeyType) switch value '%d'", u.Type) } // MarshalBinary implements encoding.BinaryMarshaler. -func (s SetOptionsResult) MarshalBinary() ([]byte, error) { +func (s PublicKey) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -29353,109 +45660,76 @@ func (s SetOptionsResult) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *SetOptionsResult) UnmarshalBinary(inp []byte) error { +func (s *PublicKey) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*SetOptionsResult)(nil) - _ encoding.BinaryUnmarshaler = (*SetOptionsResult)(nil) + _ encoding.BinaryMarshaler = (*PublicKey)(nil) + _ encoding.BinaryUnmarshaler = (*PublicKey)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s SetOptionsResult) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s PublicKey) xdrType() {} -var _ xdrType = (*SetOptionsResult)(nil) +var _ xdrType = (*PublicKey)(nil) -// ChangeTrustResultCode is an XDR Enum defines as: +// SignerKeyEd25519SignedPayload is an XDR NestedStruct defines as: // -// enum ChangeTrustResultCode -// { -// // codes considered as "success" for the operation -// CHANGE_TRUST_SUCCESS = 0, -// // codes considered as "failure" for the operation -// CHANGE_TRUST_MALFORMED = -1, // bad input -// CHANGE_TRUST_NO_ISSUER = -2, // could not find issuer -// CHANGE_TRUST_INVALID_LIMIT = -3, // cannot drop limit below balance -// // cannot create with a limit of 0 -// CHANGE_TRUST_LOW_RESERVE = -// -4, // not enough funds to create a new trust line, -// CHANGE_TRUST_SELF_NOT_ALLOWED = -5, // trusting self is not allowed -// CHANGE_TRUST_TRUST_LINE_MISSING = -6, // Asset trustline is missing for pool -// CHANGE_TRUST_CANNOT_DELETE = -// -7, // Asset trustline is still referenced in a pool -// CHANGE_TRUST_NOT_AUTH_MAINTAIN_LIABILITIES = -// -8 // Asset trustline is deauthorized -// }; -type ChangeTrustResultCode int32 - -const ( - ChangeTrustResultCodeChangeTrustSuccess ChangeTrustResultCode = 0 - ChangeTrustResultCodeChangeTrustMalformed ChangeTrustResultCode = -1 - ChangeTrustResultCodeChangeTrustNoIssuer ChangeTrustResultCode = -2 - ChangeTrustResultCodeChangeTrustInvalidLimit ChangeTrustResultCode = -3 - ChangeTrustResultCodeChangeTrustLowReserve ChangeTrustResultCode = -4 - ChangeTrustResultCodeChangeTrustSelfNotAllowed ChangeTrustResultCode = -5 - ChangeTrustResultCodeChangeTrustTrustLineMissing ChangeTrustResultCode = -6 - ChangeTrustResultCodeChangeTrustCannotDelete ChangeTrustResultCode = -7 - ChangeTrustResultCodeChangeTrustNotAuthMaintainLiabilities ChangeTrustResultCode = -8 -) - -var changeTrustResultCodeMap = map[int32]string{ - 0: "ChangeTrustResultCodeChangeTrustSuccess", - -1: "ChangeTrustResultCodeChangeTrustMalformed", - -2: "ChangeTrustResultCodeChangeTrustNoIssuer", - -3: "ChangeTrustResultCodeChangeTrustInvalidLimit", - -4: "ChangeTrustResultCodeChangeTrustLowReserve", - -5: "ChangeTrustResultCodeChangeTrustSelfNotAllowed", - -6: "ChangeTrustResultCodeChangeTrustTrustLineMissing", - -7: "ChangeTrustResultCodeChangeTrustCannotDelete", - -8: "ChangeTrustResultCodeChangeTrustNotAuthMaintainLiabilities", -} - -// ValidEnum validates a proposed value for this enum. Implements -// the Enum interface for ChangeTrustResultCode -func (e ChangeTrustResultCode) ValidEnum(v int32) bool { - _, ok := changeTrustResultCodeMap[v] - return ok -} - -// String returns the name of `e` -func (e ChangeTrustResultCode) String() string { - name, _ := changeTrustResultCodeMap[int32(e)] - return name +// struct +// { +// /* Public key that must sign the payload. */ +// uint256 ed25519; +// /* Payload to be raw signed by ed25519. */ +// opaque payload<64>; +// } +type SignerKeyEd25519SignedPayload struct { + Ed25519 Uint256 + Payload []byte `xdrmaxsize:"64"` } // EncodeTo encodes this value using the Encoder. -func (e ChangeTrustResultCode) EncodeTo(enc *xdr.Encoder) error { - if _, ok := changeTrustResultCodeMap[int32(e)]; !ok { - return fmt.Errorf("'%d' is not a valid ChangeTrustResultCode enum value", e) +func (s *SignerKeyEd25519SignedPayload) EncodeTo(e *xdr.Encoder) error { + var err error + if err = s.Ed25519.EncodeTo(e); err != nil { + return err } - _, err := enc.EncodeInt(int32(e)) - return err + if _, err = e.EncodeOpaque(s.Payload[:]); err != nil { + return err + } + return nil } -var _ decoderFrom = (*ChangeTrustResultCode)(nil) +var _ decoderFrom = (*SignerKeyEd25519SignedPayload)(nil) // DecodeFrom decodes this value using the Decoder. -func (e *ChangeTrustResultCode) DecodeFrom(d *xdr.Decoder) (int, error) { - v, n, err := d.DecodeInt() +func (s *SignerKeyEd25519SignedPayload) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding SignerKeyEd25519SignedPayload: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + var err error + var n, nTmp int + nTmp, err = s.Ed25519.DecodeFrom(d, maxDepth) + n += nTmp if err != nil { - return n, fmt.Errorf("decoding ChangeTrustResultCode: %s", err) + return n, fmt.Errorf("decoding Uint256: %w", err) } - if _, ok := changeTrustResultCodeMap[v]; !ok { - return n, fmt.Errorf("'%d' is not a valid ChangeTrustResultCode enum value", v) + s.Payload, nTmp, err = d.DecodeOpaque(64) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Payload: %w", err) } - *e = ChangeTrustResultCode(v) return n, nil } // MarshalBinary implements encoding.BinaryMarshaler. -func (s ChangeTrustResultCode) MarshalBinary() ([]byte, error) { +func (s SignerKeyEd25519SignedPayload) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -29463,287 +45737,297 @@ func (s ChangeTrustResultCode) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *ChangeTrustResultCode) UnmarshalBinary(inp []byte) error { +func (s *SignerKeyEd25519SignedPayload) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*ChangeTrustResultCode)(nil) - _ encoding.BinaryUnmarshaler = (*ChangeTrustResultCode)(nil) + _ encoding.BinaryMarshaler = (*SignerKeyEd25519SignedPayload)(nil) + _ encoding.BinaryUnmarshaler = (*SignerKeyEd25519SignedPayload)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s ChangeTrustResultCode) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s SignerKeyEd25519SignedPayload) xdrType() {} -var _ xdrType = (*ChangeTrustResultCode)(nil) +var _ xdrType = (*SignerKeyEd25519SignedPayload)(nil) -// ChangeTrustResult is an XDR Union defines as: +// SignerKey is an XDR Union defines as: // -// union ChangeTrustResult switch (ChangeTrustResultCode code) +// union SignerKey switch (SignerKeyType type) // { -// case CHANGE_TRUST_SUCCESS: -// void; -// case CHANGE_TRUST_MALFORMED: -// case CHANGE_TRUST_NO_ISSUER: -// case CHANGE_TRUST_INVALID_LIMIT: -// case CHANGE_TRUST_LOW_RESERVE: -// case CHANGE_TRUST_SELF_NOT_ALLOWED: -// case CHANGE_TRUST_TRUST_LINE_MISSING: -// case CHANGE_TRUST_CANNOT_DELETE: -// case CHANGE_TRUST_NOT_AUTH_MAINTAIN_LIABILITIES: -// void; +// case SIGNER_KEY_TYPE_ED25519: +// uint256 ed25519; +// case SIGNER_KEY_TYPE_PRE_AUTH_TX: +// /* SHA-256 Hash of TransactionSignaturePayload structure */ +// uint256 preAuthTx; +// case SIGNER_KEY_TYPE_HASH_X: +// /* Hash of random 256 bit preimage X */ +// uint256 hashX; +// case SIGNER_KEY_TYPE_ED25519_SIGNED_PAYLOAD: +// struct +// { +// /* Public key that must sign the payload. */ +// uint256 ed25519; +// /* Payload to be raw signed by ed25519. */ +// opaque payload<64>; +// } ed25519SignedPayload; // }; -type ChangeTrustResult struct { - Code ChangeTrustResultCode +type SignerKey struct { + Type SignerKeyType + Ed25519 *Uint256 + PreAuthTx *Uint256 + HashX *Uint256 + Ed25519SignedPayload *SignerKeyEd25519SignedPayload } // SwitchFieldName returns the field name in which this union's // discriminant is stored -func (u ChangeTrustResult) SwitchFieldName() string { - return "Code" +func (u SignerKey) SwitchFieldName() string { + return "Type" } // ArmForSwitch returns which field name should be used for storing -// the value for an instance of ChangeTrustResult -func (u ChangeTrustResult) ArmForSwitch(sw int32) (string, bool) { - switch ChangeTrustResultCode(sw) { - case ChangeTrustResultCodeChangeTrustSuccess: - return "", true - case ChangeTrustResultCodeChangeTrustMalformed: - return "", true - case ChangeTrustResultCodeChangeTrustNoIssuer: - return "", true - case ChangeTrustResultCodeChangeTrustInvalidLimit: - return "", true - case ChangeTrustResultCodeChangeTrustLowReserve: - return "", true - case ChangeTrustResultCodeChangeTrustSelfNotAllowed: - return "", true - case ChangeTrustResultCodeChangeTrustTrustLineMissing: - return "", true - case ChangeTrustResultCodeChangeTrustCannotDelete: - return "", true - case ChangeTrustResultCodeChangeTrustNotAuthMaintainLiabilities: - return "", true +// the value for an instance of SignerKey +func (u SignerKey) ArmForSwitch(sw int32) (string, bool) { + switch SignerKeyType(sw) { + case SignerKeyTypeSignerKeyTypeEd25519: + return "Ed25519", true + case SignerKeyTypeSignerKeyTypePreAuthTx: + return "PreAuthTx", true + case SignerKeyTypeSignerKeyTypeHashX: + return "HashX", true + case SignerKeyTypeSignerKeyTypeEd25519SignedPayload: + return "Ed25519SignedPayload", true } return "-", false } -// NewChangeTrustResult creates a new ChangeTrustResult. -func NewChangeTrustResult(code ChangeTrustResultCode, value interface{}) (result ChangeTrustResult, err error) { - result.Code = code - switch ChangeTrustResultCode(code) { - case ChangeTrustResultCodeChangeTrustSuccess: - // void - case ChangeTrustResultCodeChangeTrustMalformed: - // void - case ChangeTrustResultCodeChangeTrustNoIssuer: - // void - case ChangeTrustResultCodeChangeTrustInvalidLimit: - // void - case ChangeTrustResultCodeChangeTrustLowReserve: - // void - case ChangeTrustResultCodeChangeTrustSelfNotAllowed: - // void - case ChangeTrustResultCodeChangeTrustTrustLineMissing: - // void - case ChangeTrustResultCodeChangeTrustCannotDelete: - // void - case ChangeTrustResultCodeChangeTrustNotAuthMaintainLiabilities: - // void +// NewSignerKey creates a new SignerKey. +func NewSignerKey(aType SignerKeyType, value interface{}) (result SignerKey, err error) { + result.Type = aType + switch SignerKeyType(aType) { + case SignerKeyTypeSignerKeyTypeEd25519: + tv, ok := value.(Uint256) + if !ok { + err = errors.New("invalid value, must be Uint256") + return + } + result.Ed25519 = &tv + case SignerKeyTypeSignerKeyTypePreAuthTx: + tv, ok := value.(Uint256) + if !ok { + err = errors.New("invalid value, must be Uint256") + return + } + result.PreAuthTx = &tv + case SignerKeyTypeSignerKeyTypeHashX: + tv, ok := value.(Uint256) + if !ok { + err = errors.New("invalid value, must be Uint256") + return + } + result.HashX = &tv + case SignerKeyTypeSignerKeyTypeEd25519SignedPayload: + tv, ok := value.(SignerKeyEd25519SignedPayload) + if !ok { + err = errors.New("invalid value, must be SignerKeyEd25519SignedPayload") + return + } + result.Ed25519SignedPayload = &tv } return } -// EncodeTo encodes this value using the Encoder. -func (u ChangeTrustResult) EncodeTo(e *xdr.Encoder) error { - var err error - if err = u.Code.EncodeTo(e); err != nil { - return err - } - switch ChangeTrustResultCode(u.Code) { - case ChangeTrustResultCodeChangeTrustSuccess: - // Void - return nil - case ChangeTrustResultCodeChangeTrustMalformed: - // Void - return nil - case ChangeTrustResultCodeChangeTrustNoIssuer: - // Void - return nil - case ChangeTrustResultCodeChangeTrustInvalidLimit: - // Void - return nil - case ChangeTrustResultCodeChangeTrustLowReserve: - // Void - return nil - case ChangeTrustResultCodeChangeTrustSelfNotAllowed: - // Void - return nil - case ChangeTrustResultCodeChangeTrustTrustLineMissing: - // Void - return nil - case ChangeTrustResultCodeChangeTrustCannotDelete: - // Void - return nil - case ChangeTrustResultCodeChangeTrustNotAuthMaintainLiabilities: - // Void - return nil +// MustEd25519 retrieves the Ed25519 value from the union, +// panicing if the value is not set. +func (u SignerKey) MustEd25519() Uint256 { + val, ok := u.GetEd25519() + + if !ok { + panic("arm Ed25519 is not set") } - return fmt.Errorf("Code (ChangeTrustResultCode) switch value '%d' is not valid for union ChangeTrustResult", u.Code) + + return val } -var _ decoderFrom = (*ChangeTrustResult)(nil) +// GetEd25519 retrieves the Ed25519 value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u SignerKey) GetEd25519() (result Uint256, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) -// DecodeFrom decodes this value using the Decoder. -func (u *ChangeTrustResult) DecodeFrom(d *xdr.Decoder) (int, error) { - var err error - var n, nTmp int - nTmp, err = u.Code.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding ChangeTrustResultCode: %s", err) - } - switch ChangeTrustResultCode(u.Code) { - case ChangeTrustResultCodeChangeTrustSuccess: - // Void - return n, nil - case ChangeTrustResultCodeChangeTrustMalformed: - // Void - return n, nil - case ChangeTrustResultCodeChangeTrustNoIssuer: - // Void - return n, nil - case ChangeTrustResultCodeChangeTrustInvalidLimit: - // Void - return n, nil - case ChangeTrustResultCodeChangeTrustLowReserve: - // Void - return n, nil - case ChangeTrustResultCodeChangeTrustSelfNotAllowed: - // Void - return n, nil - case ChangeTrustResultCodeChangeTrustTrustLineMissing: - // Void - return n, nil - case ChangeTrustResultCodeChangeTrustCannotDelete: - // Void - return n, nil - case ChangeTrustResultCodeChangeTrustNotAuthMaintainLiabilities: - // Void - return n, nil + if armName == "Ed25519" { + result = *u.Ed25519 + ok = true } - return n, fmt.Errorf("union ChangeTrustResult has invalid Code (ChangeTrustResultCode) switch value '%d'", u.Code) + + return } -// MarshalBinary implements encoding.BinaryMarshaler. -func (s ChangeTrustResult) MarshalBinary() ([]byte, error) { - b := bytes.Buffer{} - e := xdr.NewEncoder(&b) - err := s.EncodeTo(e) - return b.Bytes(), err +// MustPreAuthTx retrieves the PreAuthTx value from the union, +// panicing if the value is not set. +func (u SignerKey) MustPreAuthTx() Uint256 { + val, ok := u.GetPreAuthTx() + + if !ok { + panic("arm PreAuthTx is not set") + } + + return val } -// UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *ChangeTrustResult) UnmarshalBinary(inp []byte) error { - r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) - return err +// GetPreAuthTx retrieves the PreAuthTx value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u SignerKey) GetPreAuthTx() (result Uint256, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) + + if armName == "PreAuthTx" { + result = *u.PreAuthTx + ok = true + } + + return } -var ( - _ encoding.BinaryMarshaler = (*ChangeTrustResult)(nil) - _ encoding.BinaryUnmarshaler = (*ChangeTrustResult)(nil) -) +// MustHashX retrieves the HashX value from the union, +// panicing if the value is not set. +func (u SignerKey) MustHashX() Uint256 { + val, ok := u.GetHashX() -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s ChangeTrustResult) xdrType() {} + if !ok { + panic("arm HashX is not set") + } -var _ xdrType = (*ChangeTrustResult)(nil) + return val +} -// AllowTrustResultCode is an XDR Enum defines as: -// -// enum AllowTrustResultCode -// { -// // codes considered as "success" for the operation -// ALLOW_TRUST_SUCCESS = 0, -// // codes considered as "failure" for the operation -// ALLOW_TRUST_MALFORMED = -1, // asset is not ASSET_TYPE_ALPHANUM -// ALLOW_TRUST_NO_TRUST_LINE = -2, // trustor does not have a trustline -// // source account does not require trust -// ALLOW_TRUST_TRUST_NOT_REQUIRED = -3, -// ALLOW_TRUST_CANT_REVOKE = -4, // source account can't revoke trust, -// ALLOW_TRUST_SELF_NOT_ALLOWED = -5, // trusting self is not allowed -// ALLOW_TRUST_LOW_RESERVE = -6 // claimable balances can't be created -// // on revoke due to low reserves -// }; -type AllowTrustResultCode int32 +// GetHashX retrieves the HashX value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u SignerKey) GetHashX() (result Uint256, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) -const ( - AllowTrustResultCodeAllowTrustSuccess AllowTrustResultCode = 0 - AllowTrustResultCodeAllowTrustMalformed AllowTrustResultCode = -1 - AllowTrustResultCodeAllowTrustNoTrustLine AllowTrustResultCode = -2 - AllowTrustResultCodeAllowTrustTrustNotRequired AllowTrustResultCode = -3 - AllowTrustResultCodeAllowTrustCantRevoke AllowTrustResultCode = -4 - AllowTrustResultCodeAllowTrustSelfNotAllowed AllowTrustResultCode = -5 - AllowTrustResultCodeAllowTrustLowReserve AllowTrustResultCode = -6 -) + if armName == "HashX" { + result = *u.HashX + ok = true + } -var allowTrustResultCodeMap = map[int32]string{ - 0: "AllowTrustResultCodeAllowTrustSuccess", - -1: "AllowTrustResultCodeAllowTrustMalformed", - -2: "AllowTrustResultCodeAllowTrustNoTrustLine", - -3: "AllowTrustResultCodeAllowTrustTrustNotRequired", - -4: "AllowTrustResultCodeAllowTrustCantRevoke", - -5: "AllowTrustResultCodeAllowTrustSelfNotAllowed", - -6: "AllowTrustResultCodeAllowTrustLowReserve", + return } -// ValidEnum validates a proposed value for this enum. Implements -// the Enum interface for AllowTrustResultCode -func (e AllowTrustResultCode) ValidEnum(v int32) bool { - _, ok := allowTrustResultCodeMap[v] - return ok +// MustEd25519SignedPayload retrieves the Ed25519SignedPayload value from the union, +// panicing if the value is not set. +func (u SignerKey) MustEd25519SignedPayload() SignerKeyEd25519SignedPayload { + val, ok := u.GetEd25519SignedPayload() + + if !ok { + panic("arm Ed25519SignedPayload is not set") + } + + return val } -// String returns the name of `e` -func (e AllowTrustResultCode) String() string { - name, _ := allowTrustResultCodeMap[int32(e)] - return name +// GetEd25519SignedPayload retrieves the Ed25519SignedPayload value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u SignerKey) GetEd25519SignedPayload() (result SignerKeyEd25519SignedPayload, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) + + if armName == "Ed25519SignedPayload" { + result = *u.Ed25519SignedPayload + ok = true + } + + return } // EncodeTo encodes this value using the Encoder. -func (e AllowTrustResultCode) EncodeTo(enc *xdr.Encoder) error { - if _, ok := allowTrustResultCodeMap[int32(e)]; !ok { - return fmt.Errorf("'%d' is not a valid AllowTrustResultCode enum value", e) +func (u SignerKey) EncodeTo(e *xdr.Encoder) error { + var err error + if err = u.Type.EncodeTo(e); err != nil { + return err + } + switch SignerKeyType(u.Type) { + case SignerKeyTypeSignerKeyTypeEd25519: + if err = (*u.Ed25519).EncodeTo(e); err != nil { + return err + } + return nil + case SignerKeyTypeSignerKeyTypePreAuthTx: + if err = (*u.PreAuthTx).EncodeTo(e); err != nil { + return err + } + return nil + case SignerKeyTypeSignerKeyTypeHashX: + if err = (*u.HashX).EncodeTo(e); err != nil { + return err + } + return nil + case SignerKeyTypeSignerKeyTypeEd25519SignedPayload: + if err = (*u.Ed25519SignedPayload).EncodeTo(e); err != nil { + return err + } + return nil } - _, err := enc.EncodeInt(int32(e)) - return err + return fmt.Errorf("Type (SignerKeyType) switch value '%d' is not valid for union SignerKey", u.Type) } -var _ decoderFrom = (*AllowTrustResultCode)(nil) +var _ decoderFrom = (*SignerKey)(nil) // DecodeFrom decodes this value using the Decoder. -func (e *AllowTrustResultCode) DecodeFrom(d *xdr.Decoder) (int, error) { - v, n, err := d.DecodeInt() +func (u *SignerKey) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding SignerKey: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + var err error + var n, nTmp int + nTmp, err = u.Type.DecodeFrom(d, maxDepth) + n += nTmp if err != nil { - return n, fmt.Errorf("decoding AllowTrustResultCode: %s", err) + return n, fmt.Errorf("decoding SignerKeyType: %w", err) } - if _, ok := allowTrustResultCodeMap[v]; !ok { - return n, fmt.Errorf("'%d' is not a valid AllowTrustResultCode enum value", v) + switch SignerKeyType(u.Type) { + case SignerKeyTypeSignerKeyTypeEd25519: + u.Ed25519 = new(Uint256) + nTmp, err = (*u.Ed25519).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Uint256: %w", err) + } + return n, nil + case SignerKeyTypeSignerKeyTypePreAuthTx: + u.PreAuthTx = new(Uint256) + nTmp, err = (*u.PreAuthTx).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Uint256: %w", err) + } + return n, nil + case SignerKeyTypeSignerKeyTypeHashX: + u.HashX = new(Uint256) + nTmp, err = (*u.HashX).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Uint256: %w", err) + } + return n, nil + case SignerKeyTypeSignerKeyTypeEd25519SignedPayload: + u.Ed25519SignedPayload = new(SignerKeyEd25519SignedPayload) + nTmp, err = (*u.Ed25519SignedPayload).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding SignerKeyEd25519SignedPayload: %w", err) + } + return n, nil } - *e = AllowTrustResultCode(v) - return n, nil + return n, fmt.Errorf("union SignerKey has invalid Type (SignerKeyType) switch value '%d'", u.Type) } // MarshalBinary implements encoding.BinaryMarshaler. -func (s AllowTrustResultCode) MarshalBinary() ([]byte, error) { +func (s SignerKey) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -29751,163 +46035,64 @@ func (s AllowTrustResultCode) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *AllowTrustResultCode) UnmarshalBinary(inp []byte) error { +func (s *SignerKey) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*AllowTrustResultCode)(nil) - _ encoding.BinaryUnmarshaler = (*AllowTrustResultCode)(nil) + _ encoding.BinaryMarshaler = (*SignerKey)(nil) + _ encoding.BinaryUnmarshaler = (*SignerKey)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s AllowTrustResultCode) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s SignerKey) xdrType() {} -var _ xdrType = (*AllowTrustResultCode)(nil) +var _ xdrType = (*SignerKey)(nil) -// AllowTrustResult is an XDR Union defines as: +// Signature is an XDR Typedef defines as: // -// union AllowTrustResult switch (AllowTrustResultCode code) -// { -// case ALLOW_TRUST_SUCCESS: -// void; -// case ALLOW_TRUST_MALFORMED: -// case ALLOW_TRUST_NO_TRUST_LINE: -// case ALLOW_TRUST_TRUST_NOT_REQUIRED: -// case ALLOW_TRUST_CANT_REVOKE: -// case ALLOW_TRUST_SELF_NOT_ALLOWED: -// case ALLOW_TRUST_LOW_RESERVE: -// void; -// }; -type AllowTrustResult struct { - Code AllowTrustResultCode -} - -// SwitchFieldName returns the field name in which this union's -// discriminant is stored -func (u AllowTrustResult) SwitchFieldName() string { - return "Code" -} - -// ArmForSwitch returns which field name should be used for storing -// the value for an instance of AllowTrustResult -func (u AllowTrustResult) ArmForSwitch(sw int32) (string, bool) { - switch AllowTrustResultCode(sw) { - case AllowTrustResultCodeAllowTrustSuccess: - return "", true - case AllowTrustResultCodeAllowTrustMalformed: - return "", true - case AllowTrustResultCodeAllowTrustNoTrustLine: - return "", true - case AllowTrustResultCodeAllowTrustTrustNotRequired: - return "", true - case AllowTrustResultCodeAllowTrustCantRevoke: - return "", true - case AllowTrustResultCodeAllowTrustSelfNotAllowed: - return "", true - case AllowTrustResultCodeAllowTrustLowReserve: - return "", true - } - return "-", false -} +// typedef opaque Signature<64>; +type Signature []byte -// NewAllowTrustResult creates a new AllowTrustResult. -func NewAllowTrustResult(code AllowTrustResultCode, value interface{}) (result AllowTrustResult, err error) { - result.Code = code - switch AllowTrustResultCode(code) { - case AllowTrustResultCodeAllowTrustSuccess: - // void - case AllowTrustResultCodeAllowTrustMalformed: - // void - case AllowTrustResultCodeAllowTrustNoTrustLine: - // void - case AllowTrustResultCodeAllowTrustTrustNotRequired: - // void - case AllowTrustResultCodeAllowTrustCantRevoke: - // void - case AllowTrustResultCodeAllowTrustSelfNotAllowed: - // void - case AllowTrustResultCodeAllowTrustLowReserve: - // void - } - return +// XDRMaxSize implements the Sized interface for Signature +func (e Signature) XDRMaxSize() int { + return 64 } // EncodeTo encodes this value using the Encoder. -func (u AllowTrustResult) EncodeTo(e *xdr.Encoder) error { +func (s Signature) EncodeTo(e *xdr.Encoder) error { var err error - if err = u.Code.EncodeTo(e); err != nil { + if _, err = e.EncodeOpaque(s[:]); err != nil { return err } - switch AllowTrustResultCode(u.Code) { - case AllowTrustResultCodeAllowTrustSuccess: - // Void - return nil - case AllowTrustResultCodeAllowTrustMalformed: - // Void - return nil - case AllowTrustResultCodeAllowTrustNoTrustLine: - // Void - return nil - case AllowTrustResultCodeAllowTrustTrustNotRequired: - // Void - return nil - case AllowTrustResultCodeAllowTrustCantRevoke: - // Void - return nil - case AllowTrustResultCodeAllowTrustSelfNotAllowed: - // Void - return nil - case AllowTrustResultCodeAllowTrustLowReserve: - // Void - return nil - } - return fmt.Errorf("Code (AllowTrustResultCode) switch value '%d' is not valid for union AllowTrustResult", u.Code) + return nil } -var _ decoderFrom = (*AllowTrustResult)(nil) +var _ decoderFrom = (*Signature)(nil) // DecodeFrom decodes this value using the Decoder. -func (u *AllowTrustResult) DecodeFrom(d *xdr.Decoder) (int, error) { +func (s *Signature) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding Signature: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = u.Code.DecodeFrom(d) + (*s), nTmp, err = d.DecodeOpaque(64) n += nTmp if err != nil { - return n, fmt.Errorf("decoding AllowTrustResultCode: %s", err) - } - switch AllowTrustResultCode(u.Code) { - case AllowTrustResultCodeAllowTrustSuccess: - // Void - return n, nil - case AllowTrustResultCodeAllowTrustMalformed: - // Void - return n, nil - case AllowTrustResultCodeAllowTrustNoTrustLine: - // Void - return n, nil - case AllowTrustResultCodeAllowTrustTrustNotRequired: - // Void - return n, nil - case AllowTrustResultCodeAllowTrustCantRevoke: - // Void - return n, nil - case AllowTrustResultCodeAllowTrustSelfNotAllowed: - // Void - return n, nil - case AllowTrustResultCodeAllowTrustLowReserve: - // Void - return n, nil + return n, fmt.Errorf("decoding Signature: %w", err) } - return n, fmt.Errorf("union AllowTrustResult has invalid Code (AllowTrustResultCode) switch value '%d'", u.Code) + return n, nil } // MarshalBinary implements encoding.BinaryMarshaler. -func (s AllowTrustResult) MarshalBinary() ([]byte, error) { +func (s Signature) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -29915,103 +46100,64 @@ func (s AllowTrustResult) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *AllowTrustResult) UnmarshalBinary(inp []byte) error { +func (s *Signature) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*AllowTrustResult)(nil) - _ encoding.BinaryUnmarshaler = (*AllowTrustResult)(nil) + _ encoding.BinaryMarshaler = (*Signature)(nil) + _ encoding.BinaryUnmarshaler = (*Signature)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s AllowTrustResult) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s Signature) xdrType() {} -var _ xdrType = (*AllowTrustResult)(nil) +var _ xdrType = (*Signature)(nil) -// AccountMergeResultCode is an XDR Enum defines as: +// SignatureHint is an XDR Typedef defines as: // -// enum AccountMergeResultCode -// { -// // codes considered as "success" for the operation -// ACCOUNT_MERGE_SUCCESS = 0, -// // codes considered as "failure" for the operation -// ACCOUNT_MERGE_MALFORMED = -1, // can't merge onto itself -// ACCOUNT_MERGE_NO_ACCOUNT = -2, // destination does not exist -// ACCOUNT_MERGE_IMMUTABLE_SET = -3, // source account has AUTH_IMMUTABLE set -// ACCOUNT_MERGE_HAS_SUB_ENTRIES = -4, // account has trust lines/offers -// ACCOUNT_MERGE_SEQNUM_TOO_FAR = -5, // sequence number is over max allowed -// ACCOUNT_MERGE_DEST_FULL = -6, // can't add source balance to -// // destination balance -// ACCOUNT_MERGE_IS_SPONSOR = -7 // can't merge account that is a sponsor -// }; -type AccountMergeResultCode int32 - -const ( - AccountMergeResultCodeAccountMergeSuccess AccountMergeResultCode = 0 - AccountMergeResultCodeAccountMergeMalformed AccountMergeResultCode = -1 - AccountMergeResultCodeAccountMergeNoAccount AccountMergeResultCode = -2 - AccountMergeResultCodeAccountMergeImmutableSet AccountMergeResultCode = -3 - AccountMergeResultCodeAccountMergeHasSubEntries AccountMergeResultCode = -4 - AccountMergeResultCodeAccountMergeSeqnumTooFar AccountMergeResultCode = -5 - AccountMergeResultCodeAccountMergeDestFull AccountMergeResultCode = -6 - AccountMergeResultCodeAccountMergeIsSponsor AccountMergeResultCode = -7 -) - -var accountMergeResultCodeMap = map[int32]string{ - 0: "AccountMergeResultCodeAccountMergeSuccess", - -1: "AccountMergeResultCodeAccountMergeMalformed", - -2: "AccountMergeResultCodeAccountMergeNoAccount", - -3: "AccountMergeResultCodeAccountMergeImmutableSet", - -4: "AccountMergeResultCodeAccountMergeHasSubEntries", - -5: "AccountMergeResultCodeAccountMergeSeqnumTooFar", - -6: "AccountMergeResultCodeAccountMergeDestFull", - -7: "AccountMergeResultCodeAccountMergeIsSponsor", -} - -// ValidEnum validates a proposed value for this enum. Implements -// the Enum interface for AccountMergeResultCode -func (e AccountMergeResultCode) ValidEnum(v int32) bool { - _, ok := accountMergeResultCodeMap[v] - return ok -} +// typedef opaque SignatureHint[4]; +type SignatureHint [4]byte -// String returns the name of `e` -func (e AccountMergeResultCode) String() string { - name, _ := accountMergeResultCodeMap[int32(e)] - return name +// XDRMaxSize implements the Sized interface for SignatureHint +func (e SignatureHint) XDRMaxSize() int { + return 4 } // EncodeTo encodes this value using the Encoder. -func (e AccountMergeResultCode) EncodeTo(enc *xdr.Encoder) error { - if _, ok := accountMergeResultCodeMap[int32(e)]; !ok { - return fmt.Errorf("'%d' is not a valid AccountMergeResultCode enum value", e) +func (s *SignatureHint) EncodeTo(e *xdr.Encoder) error { + var err error + if _, err = e.EncodeFixedOpaque(s[:]); err != nil { + return err } - _, err := enc.EncodeInt(int32(e)) - return err + return nil } -var _ decoderFrom = (*AccountMergeResultCode)(nil) +var _ decoderFrom = (*SignatureHint)(nil) // DecodeFrom decodes this value using the Decoder. -func (e *AccountMergeResultCode) DecodeFrom(d *xdr.Decoder) (int, error) { - v, n, err := d.DecodeInt() - if err != nil { - return n, fmt.Errorf("decoding AccountMergeResultCode: %s", err) +func (s *SignatureHint) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding SignatureHint: %w", ErrMaxDecodingDepthReached) } - if _, ok := accountMergeResultCodeMap[v]; !ok { - return n, fmt.Errorf("'%d' is not a valid AccountMergeResultCode enum value", v) + maxDepth -= 1 + var err error + var n, nTmp int + nTmp, err = d.DecodeFixedOpaqueInplace(s[:]) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding SignatureHint: %w", err) } - *e = AccountMergeResultCode(v) return n, nil } // MarshalBinary implements encoding.BinaryMarshaler. -func (s AccountMergeResultCode) MarshalBinary() ([]byte, error) { +func (s SignatureHint) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -30019,212 +46165,90 @@ func (s AccountMergeResultCode) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *AccountMergeResultCode) UnmarshalBinary(inp []byte) error { +func (s *SignatureHint) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*AccountMergeResultCode)(nil) - _ encoding.BinaryUnmarshaler = (*AccountMergeResultCode)(nil) + _ encoding.BinaryMarshaler = (*SignatureHint)(nil) + _ encoding.BinaryUnmarshaler = (*SignatureHint)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s AccountMergeResultCode) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s SignatureHint) xdrType() {} -var _ xdrType = (*AccountMergeResultCode)(nil) +var _ xdrType = (*SignatureHint)(nil) -// AccountMergeResult is an XDR Union defines as: +// NodeId is an XDR Typedef defines as: // -// union AccountMergeResult switch (AccountMergeResultCode code) -// { -// case ACCOUNT_MERGE_SUCCESS: -// int64 sourceAccountBalance; // how much got transferred from source account -// case ACCOUNT_MERGE_MALFORMED: -// case ACCOUNT_MERGE_NO_ACCOUNT: -// case ACCOUNT_MERGE_IMMUTABLE_SET: -// case ACCOUNT_MERGE_HAS_SUB_ENTRIES: -// case ACCOUNT_MERGE_SEQNUM_TOO_FAR: -// case ACCOUNT_MERGE_DEST_FULL: -// case ACCOUNT_MERGE_IS_SPONSOR: -// void; -// }; -type AccountMergeResult struct { - Code AccountMergeResultCode - SourceAccountBalance *Int64 -} +// typedef PublicKey NodeID; +type NodeId PublicKey // SwitchFieldName returns the field name in which this union's // discriminant is stored -func (u AccountMergeResult) SwitchFieldName() string { - return "Code" +func (u NodeId) SwitchFieldName() string { + return PublicKey(u).SwitchFieldName() } // ArmForSwitch returns which field name should be used for storing -// the value for an instance of AccountMergeResult -func (u AccountMergeResult) ArmForSwitch(sw int32) (string, bool) { - switch AccountMergeResultCode(sw) { - case AccountMergeResultCodeAccountMergeSuccess: - return "SourceAccountBalance", true - case AccountMergeResultCodeAccountMergeMalformed: - return "", true - case AccountMergeResultCodeAccountMergeNoAccount: - return "", true - case AccountMergeResultCodeAccountMergeImmutableSet: - return "", true - case AccountMergeResultCodeAccountMergeHasSubEntries: - return "", true - case AccountMergeResultCodeAccountMergeSeqnumTooFar: - return "", true - case AccountMergeResultCodeAccountMergeDestFull: - return "", true - case AccountMergeResultCodeAccountMergeIsSponsor: - return "", true - } - return "-", false +// the value for an instance of PublicKey +func (u NodeId) ArmForSwitch(sw int32) (string, bool) { + return PublicKey(u).ArmForSwitch(sw) } -// NewAccountMergeResult creates a new AccountMergeResult. -func NewAccountMergeResult(code AccountMergeResultCode, value interface{}) (result AccountMergeResult, err error) { - result.Code = code - switch AccountMergeResultCode(code) { - case AccountMergeResultCodeAccountMergeSuccess: - tv, ok := value.(Int64) - if !ok { - err = fmt.Errorf("invalid value, must be Int64") - return - } - result.SourceAccountBalance = &tv - case AccountMergeResultCodeAccountMergeMalformed: - // void - case AccountMergeResultCodeAccountMergeNoAccount: - // void - case AccountMergeResultCodeAccountMergeImmutableSet: - // void - case AccountMergeResultCodeAccountMergeHasSubEntries: - // void - case AccountMergeResultCodeAccountMergeSeqnumTooFar: - // void - case AccountMergeResultCodeAccountMergeDestFull: - // void - case AccountMergeResultCodeAccountMergeIsSponsor: - // void - } +// NewNodeId creates a new NodeId. +func NewNodeId(aType PublicKeyType, value interface{}) (result NodeId, err error) { + u, err := NewPublicKey(aType, value) + result = NodeId(u) return } -// MustSourceAccountBalance retrieves the SourceAccountBalance value from the union, +// MustEd25519 retrieves the Ed25519 value from the union, // panicing if the value is not set. -func (u AccountMergeResult) MustSourceAccountBalance() Int64 { - val, ok := u.GetSourceAccountBalance() - - if !ok { - panic("arm SourceAccountBalance is not set") - } - - return val +func (u NodeId) MustEd25519() Uint256 { + return PublicKey(u).MustEd25519() } -// GetSourceAccountBalance retrieves the SourceAccountBalance value from the union, +// GetEd25519 retrieves the Ed25519 value from the union, // returning ok if the union's switch indicated the value is valid. -func (u AccountMergeResult) GetSourceAccountBalance() (result Int64, ok bool) { - armName, _ := u.ArmForSwitch(int32(u.Code)) - - if armName == "SourceAccountBalance" { - result = *u.SourceAccountBalance - ok = true - } - - return +func (u NodeId) GetEd25519() (result Uint256, ok bool) { + return PublicKey(u).GetEd25519() } // EncodeTo encodes this value using the Encoder. -func (u AccountMergeResult) EncodeTo(e *xdr.Encoder) error { +func (s NodeId) EncodeTo(e *xdr.Encoder) error { var err error - if err = u.Code.EncodeTo(e); err != nil { + if err = PublicKey(s).EncodeTo(e); err != nil { return err } - switch AccountMergeResultCode(u.Code) { - case AccountMergeResultCodeAccountMergeSuccess: - if err = (*u.SourceAccountBalance).EncodeTo(e); err != nil { - return err - } - return nil - case AccountMergeResultCodeAccountMergeMalformed: - // Void - return nil - case AccountMergeResultCodeAccountMergeNoAccount: - // Void - return nil - case AccountMergeResultCodeAccountMergeImmutableSet: - // Void - return nil - case AccountMergeResultCodeAccountMergeHasSubEntries: - // Void - return nil - case AccountMergeResultCodeAccountMergeSeqnumTooFar: - // Void - return nil - case AccountMergeResultCodeAccountMergeDestFull: - // Void - return nil - case AccountMergeResultCodeAccountMergeIsSponsor: - // Void - return nil - } - return fmt.Errorf("Code (AccountMergeResultCode) switch value '%d' is not valid for union AccountMergeResult", u.Code) + return nil } -var _ decoderFrom = (*AccountMergeResult)(nil) +var _ decoderFrom = (*NodeId)(nil) // DecodeFrom decodes this value using the Decoder. -func (u *AccountMergeResult) DecodeFrom(d *xdr.Decoder) (int, error) { +func (s *NodeId) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding NodeId: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = u.Code.DecodeFrom(d) + nTmp, err = (*PublicKey)(s).DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding AccountMergeResultCode: %s", err) - } - switch AccountMergeResultCode(u.Code) { - case AccountMergeResultCodeAccountMergeSuccess: - u.SourceAccountBalance = new(Int64) - nTmp, err = (*u.SourceAccountBalance).DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Int64: %s", err) - } - return n, nil - case AccountMergeResultCodeAccountMergeMalformed: - // Void - return n, nil - case AccountMergeResultCodeAccountMergeNoAccount: - // Void - return n, nil - case AccountMergeResultCodeAccountMergeImmutableSet: - // Void - return n, nil - case AccountMergeResultCodeAccountMergeHasSubEntries: - // Void - return n, nil - case AccountMergeResultCodeAccountMergeSeqnumTooFar: - // Void - return n, nil - case AccountMergeResultCodeAccountMergeDestFull: - // Void - return n, nil - case AccountMergeResultCodeAccountMergeIsSponsor: - // Void - return n, nil + return n, fmt.Errorf("decoding PublicKey: %w", err) } - return n, fmt.Errorf("union AccountMergeResult has invalid Code (AccountMergeResultCode) switch value '%d'", u.Code) + return n, nil } // MarshalBinary implements encoding.BinaryMarshaler. -func (s AccountMergeResult) MarshalBinary() ([]byte, error) { +func (s NodeId) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -30232,84 +46256,90 @@ func (s AccountMergeResult) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *AccountMergeResult) UnmarshalBinary(inp []byte) error { +func (s *NodeId) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*AccountMergeResult)(nil) - _ encoding.BinaryUnmarshaler = (*AccountMergeResult)(nil) + _ encoding.BinaryMarshaler = (*NodeId)(nil) + _ encoding.BinaryUnmarshaler = (*NodeId)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s AccountMergeResult) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s NodeId) xdrType() {} -var _ xdrType = (*AccountMergeResult)(nil) +var _ xdrType = (*NodeId)(nil) -// InflationResultCode is an XDR Enum defines as: +// AccountId is an XDR Typedef defines as: // -// enum InflationResultCode -// { -// // codes considered as "success" for the operation -// INFLATION_SUCCESS = 0, -// // codes considered as "failure" for the operation -// INFLATION_NOT_TIME = -1 -// }; -type InflationResultCode int32 +// typedef PublicKey AccountID; +type AccountId PublicKey -const ( - InflationResultCodeInflationSuccess InflationResultCode = 0 - InflationResultCodeInflationNotTime InflationResultCode = -1 -) +// SwitchFieldName returns the field name in which this union's +// discriminant is stored +func (u AccountId) SwitchFieldName() string { + return PublicKey(u).SwitchFieldName() +} -var inflationResultCodeMap = map[int32]string{ - 0: "InflationResultCodeInflationSuccess", - -1: "InflationResultCodeInflationNotTime", +// ArmForSwitch returns which field name should be used for storing +// the value for an instance of PublicKey +func (u AccountId) ArmForSwitch(sw int32) (string, bool) { + return PublicKey(u).ArmForSwitch(sw) } -// ValidEnum validates a proposed value for this enum. Implements -// the Enum interface for InflationResultCode -func (e InflationResultCode) ValidEnum(v int32) bool { - _, ok := inflationResultCodeMap[v] - return ok +// NewAccountId creates a new AccountId. +func NewAccountId(aType PublicKeyType, value interface{}) (result AccountId, err error) { + u, err := NewPublicKey(aType, value) + result = AccountId(u) + return +} + +// MustEd25519 retrieves the Ed25519 value from the union, +// panicing if the value is not set. +func (u AccountId) MustEd25519() Uint256 { + return PublicKey(u).MustEd25519() } -// String returns the name of `e` -func (e InflationResultCode) String() string { - name, _ := inflationResultCodeMap[int32(e)] - return name +// GetEd25519 retrieves the Ed25519 value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u AccountId) GetEd25519() (result Uint256, ok bool) { + return PublicKey(u).GetEd25519() } // EncodeTo encodes this value using the Encoder. -func (e InflationResultCode) EncodeTo(enc *xdr.Encoder) error { - if _, ok := inflationResultCodeMap[int32(e)]; !ok { - return fmt.Errorf("'%d' is not a valid InflationResultCode enum value", e) +func (s AccountId) EncodeTo(e *xdr.Encoder) error { + var err error + if err = PublicKey(s).EncodeTo(e); err != nil { + return err } - _, err := enc.EncodeInt(int32(e)) - return err + return nil } -var _ decoderFrom = (*InflationResultCode)(nil) +var _ decoderFrom = (*AccountId)(nil) // DecodeFrom decodes this value using the Decoder. -func (e *InflationResultCode) DecodeFrom(d *xdr.Decoder) (int, error) { - v, n, err := d.DecodeInt() - if err != nil { - return n, fmt.Errorf("decoding InflationResultCode: %s", err) +func (s *AccountId) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding AccountId: %w", ErrMaxDecodingDepthReached) } - if _, ok := inflationResultCodeMap[v]; !ok { - return n, fmt.Errorf("'%d' is not a valid InflationResultCode enum value", v) + maxDepth -= 1 + var err error + var n, nTmp int + nTmp, err = (*PublicKey)(s).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding PublicKey: %w", err) } - *e = InflationResultCode(v) return n, nil } // MarshalBinary implements encoding.BinaryMarshaler. -func (s InflationResultCode) MarshalBinary() ([]byte, error) { +func (s AccountId) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -30317,69 +46347,64 @@ func (s InflationResultCode) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *InflationResultCode) UnmarshalBinary(inp []byte) error { +func (s *AccountId) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*InflationResultCode)(nil) - _ encoding.BinaryUnmarshaler = (*InflationResultCode)(nil) + _ encoding.BinaryMarshaler = (*AccountId)(nil) + _ encoding.BinaryUnmarshaler = (*AccountId)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s InflationResultCode) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s AccountId) xdrType() {} -var _ xdrType = (*InflationResultCode)(nil) +var _ xdrType = (*AccountId)(nil) -// InflationPayout is an XDR Struct defines as: +// Curve25519Secret is an XDR Struct defines as: // -// struct InflationPayout // or use PaymentResultAtom to limit types? +// struct Curve25519Secret // { -// AccountID destination; -// int64 amount; +// opaque key[32]; // }; -type InflationPayout struct { - Destination AccountId - Amount Int64 +type Curve25519Secret struct { + Key [32]byte `xdrmaxsize:"32"` } // EncodeTo encodes this value using the Encoder. -func (s *InflationPayout) EncodeTo(e *xdr.Encoder) error { +func (s *Curve25519Secret) EncodeTo(e *xdr.Encoder) error { var err error - if err = s.Destination.EncodeTo(e); err != nil { - return err - } - if err = s.Amount.EncodeTo(e); err != nil { + if _, err = e.EncodeFixedOpaque(s.Key[:]); err != nil { return err } return nil } -var _ decoderFrom = (*InflationPayout)(nil) +var _ decoderFrom = (*Curve25519Secret)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *InflationPayout) DecodeFrom(d *xdr.Decoder) (int, error) { +func (s *Curve25519Secret) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding Curve25519Secret: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = s.Destination.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding AccountId: %s", err) - } - nTmp, err = s.Amount.DecodeFrom(d) + nTmp, err = d.DecodeFixedOpaqueInplace(s.Key[:]) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Int64: %s", err) + return n, fmt.Errorf("decoding Key: %w", err) } return n, nil } // MarshalBinary implements encoding.BinaryMarshaler. -func (s InflationPayout) MarshalBinary() ([]byte, error) { +func (s Curve25519Secret) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -30387,163 +46412,64 @@ func (s InflationPayout) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *InflationPayout) UnmarshalBinary(inp []byte) error { +func (s *Curve25519Secret) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*InflationPayout)(nil) - _ encoding.BinaryUnmarshaler = (*InflationPayout)(nil) + _ encoding.BinaryMarshaler = (*Curve25519Secret)(nil) + _ encoding.BinaryUnmarshaler = (*Curve25519Secret)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s InflationPayout) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s Curve25519Secret) xdrType() {} -var _ xdrType = (*InflationPayout)(nil) +var _ xdrType = (*Curve25519Secret)(nil) -// InflationResult is an XDR Union defines as: +// Curve25519Public is an XDR Struct defines as: // -// union InflationResult switch (InflationResultCode code) +// struct Curve25519Public // { -// case INFLATION_SUCCESS: -// InflationPayout payouts<>; -// case INFLATION_NOT_TIME: -// void; +// opaque key[32]; // }; -type InflationResult struct { - Code InflationResultCode - Payouts *[]InflationPayout -} - -// SwitchFieldName returns the field name in which this union's -// discriminant is stored -func (u InflationResult) SwitchFieldName() string { - return "Code" -} - -// ArmForSwitch returns which field name should be used for storing -// the value for an instance of InflationResult -func (u InflationResult) ArmForSwitch(sw int32) (string, bool) { - switch InflationResultCode(sw) { - case InflationResultCodeInflationSuccess: - return "Payouts", true - case InflationResultCodeInflationNotTime: - return "", true - } - return "-", false -} - -// NewInflationResult creates a new InflationResult. -func NewInflationResult(code InflationResultCode, value interface{}) (result InflationResult, err error) { - result.Code = code - switch InflationResultCode(code) { - case InflationResultCodeInflationSuccess: - tv, ok := value.([]InflationPayout) - if !ok { - err = fmt.Errorf("invalid value, must be []InflationPayout") - return - } - result.Payouts = &tv - case InflationResultCodeInflationNotTime: - // void - } - return -} - -// MustPayouts retrieves the Payouts value from the union, -// panicing if the value is not set. -func (u InflationResult) MustPayouts() []InflationPayout { - val, ok := u.GetPayouts() - - if !ok { - panic("arm Payouts is not set") - } - - return val -} - -// GetPayouts retrieves the Payouts value from the union, -// returning ok if the union's switch indicated the value is valid. -func (u InflationResult) GetPayouts() (result []InflationPayout, ok bool) { - armName, _ := u.ArmForSwitch(int32(u.Code)) - - if armName == "Payouts" { - result = *u.Payouts - ok = true - } - - return +type Curve25519Public struct { + Key [32]byte `xdrmaxsize:"32"` } // EncodeTo encodes this value using the Encoder. -func (u InflationResult) EncodeTo(e *xdr.Encoder) error { +func (s *Curve25519Public) EncodeTo(e *xdr.Encoder) error { var err error - if err = u.Code.EncodeTo(e); err != nil { + if _, err = e.EncodeFixedOpaque(s.Key[:]); err != nil { return err } - switch InflationResultCode(u.Code) { - case InflationResultCodeInflationSuccess: - if _, err = e.EncodeUint(uint32(len((*u.Payouts)))); err != nil { - return err - } - for i := 0; i < len((*u.Payouts)); i++ { - if err = (*u.Payouts)[i].EncodeTo(e); err != nil { - return err - } - } - return nil - case InflationResultCodeInflationNotTime: - // Void - return nil - } - return fmt.Errorf("Code (InflationResultCode) switch value '%d' is not valid for union InflationResult", u.Code) + return nil } -var _ decoderFrom = (*InflationResult)(nil) +var _ decoderFrom = (*Curve25519Public)(nil) // DecodeFrom decodes this value using the Decoder. -func (u *InflationResult) DecodeFrom(d *xdr.Decoder) (int, error) { +func (s *Curve25519Public) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding Curve25519Public: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = u.Code.DecodeFrom(d) + nTmp, err = d.DecodeFixedOpaqueInplace(s.Key[:]) n += nTmp if err != nil { - return n, fmt.Errorf("decoding InflationResultCode: %s", err) - } - switch InflationResultCode(u.Code) { - case InflationResultCodeInflationSuccess: - u.Payouts = new([]InflationPayout) - var l uint32 - l, nTmp, err = d.DecodeUint() - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding InflationPayout: %s", err) - } - (*u.Payouts) = nil - if l > 0 { - (*u.Payouts) = make([]InflationPayout, l) - for i := uint32(0); i < l; i++ { - nTmp, err = (*u.Payouts)[i].DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding InflationPayout: %s", err) - } - } - } - return n, nil - case InflationResultCodeInflationNotTime: - // Void - return n, nil + return n, fmt.Errorf("decoding Key: %w", err) } - return n, fmt.Errorf("union InflationResult has invalid Code (InflationResultCode) switch value '%d'", u.Code) + return n, nil } // MarshalBinary implements encoding.BinaryMarshaler. -func (s InflationResult) MarshalBinary() ([]byte, error) { +func (s Curve25519Public) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -30551,95 +46477,64 @@ func (s InflationResult) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *InflationResult) UnmarshalBinary(inp []byte) error { +func (s *Curve25519Public) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*InflationResult)(nil) - _ encoding.BinaryUnmarshaler = (*InflationResult)(nil) + _ encoding.BinaryMarshaler = (*Curve25519Public)(nil) + _ encoding.BinaryUnmarshaler = (*Curve25519Public)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s InflationResult) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s Curve25519Public) xdrType() {} -var _ xdrType = (*InflationResult)(nil) +var _ xdrType = (*Curve25519Public)(nil) -// ManageDataResultCode is an XDR Enum defines as: +// HmacSha256Key is an XDR Struct defines as: // -// enum ManageDataResultCode +// struct HmacSha256Key // { -// // codes considered as "success" for the operation -// MANAGE_DATA_SUCCESS = 0, -// // codes considered as "failure" for the operation -// MANAGE_DATA_NOT_SUPPORTED_YET = -// -1, // The network hasn't moved to this protocol change yet -// MANAGE_DATA_NAME_NOT_FOUND = -// -2, // Trying to remove a Data Entry that isn't there -// MANAGE_DATA_LOW_RESERVE = -3, // not enough funds to create a new Data Entry -// MANAGE_DATA_INVALID_NAME = -4 // Name not a valid string +// opaque key[32]; // }; -type ManageDataResultCode int32 - -const ( - ManageDataResultCodeManageDataSuccess ManageDataResultCode = 0 - ManageDataResultCodeManageDataNotSupportedYet ManageDataResultCode = -1 - ManageDataResultCodeManageDataNameNotFound ManageDataResultCode = -2 - ManageDataResultCodeManageDataLowReserve ManageDataResultCode = -3 - ManageDataResultCodeManageDataInvalidName ManageDataResultCode = -4 -) - -var manageDataResultCodeMap = map[int32]string{ - 0: "ManageDataResultCodeManageDataSuccess", - -1: "ManageDataResultCodeManageDataNotSupportedYet", - -2: "ManageDataResultCodeManageDataNameNotFound", - -3: "ManageDataResultCodeManageDataLowReserve", - -4: "ManageDataResultCodeManageDataInvalidName", -} - -// ValidEnum validates a proposed value for this enum. Implements -// the Enum interface for ManageDataResultCode -func (e ManageDataResultCode) ValidEnum(v int32) bool { - _, ok := manageDataResultCodeMap[v] - return ok -} - -// String returns the name of `e` -func (e ManageDataResultCode) String() string { - name, _ := manageDataResultCodeMap[int32(e)] - return name +type HmacSha256Key struct { + Key [32]byte `xdrmaxsize:"32"` } // EncodeTo encodes this value using the Encoder. -func (e ManageDataResultCode) EncodeTo(enc *xdr.Encoder) error { - if _, ok := manageDataResultCodeMap[int32(e)]; !ok { - return fmt.Errorf("'%d' is not a valid ManageDataResultCode enum value", e) +func (s *HmacSha256Key) EncodeTo(e *xdr.Encoder) error { + var err error + if _, err = e.EncodeFixedOpaque(s.Key[:]); err != nil { + return err } - _, err := enc.EncodeInt(int32(e)) - return err + return nil } -var _ decoderFrom = (*ManageDataResultCode)(nil) +var _ decoderFrom = (*HmacSha256Key)(nil) // DecodeFrom decodes this value using the Decoder. -func (e *ManageDataResultCode) DecodeFrom(d *xdr.Decoder) (int, error) { - v, n, err := d.DecodeInt() - if err != nil { - return n, fmt.Errorf("decoding ManageDataResultCode: %s", err) +func (s *HmacSha256Key) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding HmacSha256Key: %w", ErrMaxDecodingDepthReached) } - if _, ok := manageDataResultCodeMap[v]; !ok { - return n, fmt.Errorf("'%d' is not a valid ManageDataResultCode enum value", v) + maxDepth -= 1 + var err error + var n, nTmp int + nTmp, err = d.DecodeFixedOpaqueInplace(s.Key[:]) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Key: %w", err) } - *e = ManageDataResultCode(v) return n, nil } // MarshalBinary implements encoding.BinaryMarshaler. -func (s ManageDataResultCode) MarshalBinary() ([]byte, error) { +func (s HmacSha256Key) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -30647,141 +46542,64 @@ func (s ManageDataResultCode) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *ManageDataResultCode) UnmarshalBinary(inp []byte) error { +func (s *HmacSha256Key) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*ManageDataResultCode)(nil) - _ encoding.BinaryUnmarshaler = (*ManageDataResultCode)(nil) + _ encoding.BinaryMarshaler = (*HmacSha256Key)(nil) + _ encoding.BinaryUnmarshaler = (*HmacSha256Key)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s ManageDataResultCode) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s HmacSha256Key) xdrType() {} -var _ xdrType = (*ManageDataResultCode)(nil) +var _ xdrType = (*HmacSha256Key)(nil) -// ManageDataResult is an XDR Union defines as: +// HmacSha256Mac is an XDR Struct defines as: // -// union ManageDataResult switch (ManageDataResultCode code) +// struct HmacSha256Mac // { -// case MANAGE_DATA_SUCCESS: -// void; -// case MANAGE_DATA_NOT_SUPPORTED_YET: -// case MANAGE_DATA_NAME_NOT_FOUND: -// case MANAGE_DATA_LOW_RESERVE: -// case MANAGE_DATA_INVALID_NAME: -// void; +// opaque mac[32]; // }; -type ManageDataResult struct { - Code ManageDataResultCode -} - -// SwitchFieldName returns the field name in which this union's -// discriminant is stored -func (u ManageDataResult) SwitchFieldName() string { - return "Code" -} - -// ArmForSwitch returns which field name should be used for storing -// the value for an instance of ManageDataResult -func (u ManageDataResult) ArmForSwitch(sw int32) (string, bool) { - switch ManageDataResultCode(sw) { - case ManageDataResultCodeManageDataSuccess: - return "", true - case ManageDataResultCodeManageDataNotSupportedYet: - return "", true - case ManageDataResultCodeManageDataNameNotFound: - return "", true - case ManageDataResultCodeManageDataLowReserve: - return "", true - case ManageDataResultCodeManageDataInvalidName: - return "", true - } - return "-", false -} - -// NewManageDataResult creates a new ManageDataResult. -func NewManageDataResult(code ManageDataResultCode, value interface{}) (result ManageDataResult, err error) { - result.Code = code - switch ManageDataResultCode(code) { - case ManageDataResultCodeManageDataSuccess: - // void - case ManageDataResultCodeManageDataNotSupportedYet: - // void - case ManageDataResultCodeManageDataNameNotFound: - // void - case ManageDataResultCodeManageDataLowReserve: - // void - case ManageDataResultCodeManageDataInvalidName: - // void - } - return +type HmacSha256Mac struct { + Mac [32]byte `xdrmaxsize:"32"` } // EncodeTo encodes this value using the Encoder. -func (u ManageDataResult) EncodeTo(e *xdr.Encoder) error { +func (s *HmacSha256Mac) EncodeTo(e *xdr.Encoder) error { var err error - if err = u.Code.EncodeTo(e); err != nil { + if _, err = e.EncodeFixedOpaque(s.Mac[:]); err != nil { return err } - switch ManageDataResultCode(u.Code) { - case ManageDataResultCodeManageDataSuccess: - // Void - return nil - case ManageDataResultCodeManageDataNotSupportedYet: - // Void - return nil - case ManageDataResultCodeManageDataNameNotFound: - // Void - return nil - case ManageDataResultCodeManageDataLowReserve: - // Void - return nil - case ManageDataResultCodeManageDataInvalidName: - // Void - return nil - } - return fmt.Errorf("Code (ManageDataResultCode) switch value '%d' is not valid for union ManageDataResult", u.Code) + return nil } -var _ decoderFrom = (*ManageDataResult)(nil) +var _ decoderFrom = (*HmacSha256Mac)(nil) // DecodeFrom decodes this value using the Decoder. -func (u *ManageDataResult) DecodeFrom(d *xdr.Decoder) (int, error) { +func (s *HmacSha256Mac) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding HmacSha256Mac: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = u.Code.DecodeFrom(d) + nTmp, err = d.DecodeFixedOpaqueInplace(s.Mac[:]) n += nTmp if err != nil { - return n, fmt.Errorf("decoding ManageDataResultCode: %s", err) - } - switch ManageDataResultCode(u.Code) { - case ManageDataResultCodeManageDataSuccess: - // Void - return n, nil - case ManageDataResultCodeManageDataNotSupportedYet: - // Void - return n, nil - case ManageDataResultCodeManageDataNameNotFound: - // Void - return n, nil - case ManageDataResultCodeManageDataLowReserve: - // Void - return n, nil - case ManageDataResultCodeManageDataInvalidName: - // Void - return n, nil + return n, fmt.Errorf("decoding Mac: %w", err) } - return n, fmt.Errorf("union ManageDataResult has invalid Code (ManageDataResultCode) switch value '%d'", u.Code) + return n, nil } // MarshalBinary implements encoding.BinaryMarshaler. -func (s ManageDataResult) MarshalBinary() ([]byte, error) { +func (s HmacSha256Mac) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -30789,84 +46607,84 @@ func (s ManageDataResult) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *ManageDataResult) UnmarshalBinary(inp []byte) error { +func (s *HmacSha256Mac) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*ManageDataResult)(nil) - _ encoding.BinaryUnmarshaler = (*ManageDataResult)(nil) + _ encoding.BinaryMarshaler = (*HmacSha256Mac)(nil) + _ encoding.BinaryUnmarshaler = (*HmacSha256Mac)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s ManageDataResult) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s HmacSha256Mac) xdrType() {} -var _ xdrType = (*ManageDataResult)(nil) +var _ xdrType = (*HmacSha256Mac)(nil) -// BumpSequenceResultCode is an XDR Enum defines as: +// ScEnvMetaKind is an XDR Enum defines as: // -// enum BumpSequenceResultCode +// enum SCEnvMetaKind // { -// // codes considered as "success" for the operation -// BUMP_SEQUENCE_SUCCESS = 0, -// // codes considered as "failure" for the operation -// BUMP_SEQUENCE_BAD_SEQ = -1 // `bumpTo` is not within bounds +// SC_ENV_META_KIND_INTERFACE_VERSION = 0 // }; -type BumpSequenceResultCode int32 +type ScEnvMetaKind int32 const ( - BumpSequenceResultCodeBumpSequenceSuccess BumpSequenceResultCode = 0 - BumpSequenceResultCodeBumpSequenceBadSeq BumpSequenceResultCode = -1 + ScEnvMetaKindScEnvMetaKindInterfaceVersion ScEnvMetaKind = 0 ) -var bumpSequenceResultCodeMap = map[int32]string{ - 0: "BumpSequenceResultCodeBumpSequenceSuccess", - -1: "BumpSequenceResultCodeBumpSequenceBadSeq", +var scEnvMetaKindMap = map[int32]string{ + 0: "ScEnvMetaKindScEnvMetaKindInterfaceVersion", } // ValidEnum validates a proposed value for this enum. Implements -// the Enum interface for BumpSequenceResultCode -func (e BumpSequenceResultCode) ValidEnum(v int32) bool { - _, ok := bumpSequenceResultCodeMap[v] +// the Enum interface for ScEnvMetaKind +func (e ScEnvMetaKind) ValidEnum(v int32) bool { + _, ok := scEnvMetaKindMap[v] return ok } // String returns the name of `e` -func (e BumpSequenceResultCode) String() string { - name, _ := bumpSequenceResultCodeMap[int32(e)] +func (e ScEnvMetaKind) String() string { + name, _ := scEnvMetaKindMap[int32(e)] return name } // EncodeTo encodes this value using the Encoder. -func (e BumpSequenceResultCode) EncodeTo(enc *xdr.Encoder) error { - if _, ok := bumpSequenceResultCodeMap[int32(e)]; !ok { - return fmt.Errorf("'%d' is not a valid BumpSequenceResultCode enum value", e) +func (e ScEnvMetaKind) EncodeTo(enc *xdr.Encoder) error { + if _, ok := scEnvMetaKindMap[int32(e)]; !ok { + return fmt.Errorf("'%d' is not a valid ScEnvMetaKind enum value", e) } _, err := enc.EncodeInt(int32(e)) return err } -var _ decoderFrom = (*BumpSequenceResultCode)(nil) +var _ decoderFrom = (*ScEnvMetaKind)(nil) // DecodeFrom decodes this value using the Decoder. -func (e *BumpSequenceResultCode) DecodeFrom(d *xdr.Decoder) (int, error) { +func (e *ScEnvMetaKind) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding ScEnvMetaKind: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 v, n, err := d.DecodeInt() if err != nil { - return n, fmt.Errorf("decoding BumpSequenceResultCode: %s", err) + return n, fmt.Errorf("decoding ScEnvMetaKind: %w", err) } - if _, ok := bumpSequenceResultCodeMap[v]; !ok { - return n, fmt.Errorf("'%d' is not a valid BumpSequenceResultCode enum value", v) + if _, ok := scEnvMetaKindMap[v]; !ok { + return n, fmt.Errorf("'%d' is not a valid ScEnvMetaKind enum value", v) } - *e = BumpSequenceResultCode(v) + *e = ScEnvMetaKind(v) return n, nil } // MarshalBinary implements encoding.BinaryMarshaler. -func (s BumpSequenceResultCode) MarshalBinary() ([]byte, error) { +func (s ScEnvMetaKind) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -30874,108 +46692,214 @@ func (s BumpSequenceResultCode) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *BumpSequenceResultCode) UnmarshalBinary(inp []byte) error { +func (s *ScEnvMetaKind) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*BumpSequenceResultCode)(nil) - _ encoding.BinaryUnmarshaler = (*BumpSequenceResultCode)(nil) + _ encoding.BinaryMarshaler = (*ScEnvMetaKind)(nil) + _ encoding.BinaryUnmarshaler = (*ScEnvMetaKind)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s BumpSequenceResultCode) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s ScEnvMetaKind) xdrType() {} -var _ xdrType = (*BumpSequenceResultCode)(nil) +var _ xdrType = (*ScEnvMetaKind)(nil) -// BumpSequenceResult is an XDR Union defines as: +// ScEnvMetaEntry is an XDR Union defines as: // -// union BumpSequenceResult switch (BumpSequenceResultCode code) +// union SCEnvMetaEntry switch (SCEnvMetaKind kind) // { -// case BUMP_SEQUENCE_SUCCESS: -// void; -// case BUMP_SEQUENCE_BAD_SEQ: -// void; +// case SC_ENV_META_KIND_INTERFACE_VERSION: +// uint64 interfaceVersion; // }; -type BumpSequenceResult struct { - Code BumpSequenceResultCode +type ScEnvMetaEntry struct { + Kind ScEnvMetaKind + InterfaceVersion *Uint64 } // SwitchFieldName returns the field name in which this union's // discriminant is stored -func (u BumpSequenceResult) SwitchFieldName() string { - return "Code" +func (u ScEnvMetaEntry) SwitchFieldName() string { + return "Kind" +} + +// ArmForSwitch returns which field name should be used for storing +// the value for an instance of ScEnvMetaEntry +func (u ScEnvMetaEntry) ArmForSwitch(sw int32) (string, bool) { + switch ScEnvMetaKind(sw) { + case ScEnvMetaKindScEnvMetaKindInterfaceVersion: + return "InterfaceVersion", true + } + return "-", false +} + +// NewScEnvMetaEntry creates a new ScEnvMetaEntry. +func NewScEnvMetaEntry(kind ScEnvMetaKind, value interface{}) (result ScEnvMetaEntry, err error) { + result.Kind = kind + switch ScEnvMetaKind(kind) { + case ScEnvMetaKindScEnvMetaKindInterfaceVersion: + tv, ok := value.(Uint64) + if !ok { + err = errors.New("invalid value, must be Uint64") + return + } + result.InterfaceVersion = &tv + } + return +} + +// MustInterfaceVersion retrieves the InterfaceVersion value from the union, +// panicing if the value is not set. +func (u ScEnvMetaEntry) MustInterfaceVersion() Uint64 { + val, ok := u.GetInterfaceVersion() + + if !ok { + panic("arm InterfaceVersion is not set") + } + + return val +} + +// GetInterfaceVersion retrieves the InterfaceVersion value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u ScEnvMetaEntry) GetInterfaceVersion() (result Uint64, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Kind)) + + if armName == "InterfaceVersion" { + result = *u.InterfaceVersion + ok = true + } + + return +} + +// EncodeTo encodes this value using the Encoder. +func (u ScEnvMetaEntry) EncodeTo(e *xdr.Encoder) error { + var err error + if err = u.Kind.EncodeTo(e); err != nil { + return err + } + switch ScEnvMetaKind(u.Kind) { + case ScEnvMetaKindScEnvMetaKindInterfaceVersion: + if err = (*u.InterfaceVersion).EncodeTo(e); err != nil { + return err + } + return nil + } + return fmt.Errorf("Kind (ScEnvMetaKind) switch value '%d' is not valid for union ScEnvMetaEntry", u.Kind) +} + +var _ decoderFrom = (*ScEnvMetaEntry)(nil) + +// DecodeFrom decodes this value using the Decoder. +func (u *ScEnvMetaEntry) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding ScEnvMetaEntry: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + var err error + var n, nTmp int + nTmp, err = u.Kind.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ScEnvMetaKind: %w", err) + } + switch ScEnvMetaKind(u.Kind) { + case ScEnvMetaKindScEnvMetaKindInterfaceVersion: + u.InterfaceVersion = new(Uint64) + nTmp, err = (*u.InterfaceVersion).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Uint64: %w", err) + } + return n, nil + } + return n, fmt.Errorf("union ScEnvMetaEntry has invalid Kind (ScEnvMetaKind) switch value '%d'", u.Kind) +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (s ScEnvMetaEntry) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err } -// ArmForSwitch returns which field name should be used for storing -// the value for an instance of BumpSequenceResult -func (u BumpSequenceResult) ArmForSwitch(sw int32) (string, bool) { - switch BumpSequenceResultCode(sw) { - case BumpSequenceResultCodeBumpSequenceSuccess: - return "", true - case BumpSequenceResultCodeBumpSequenceBadSeq: - return "", true - } - return "-", false +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *ScEnvMetaEntry) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err } -// NewBumpSequenceResult creates a new BumpSequenceResult. -func NewBumpSequenceResult(code BumpSequenceResultCode, value interface{}) (result BumpSequenceResult, err error) { - result.Code = code - switch BumpSequenceResultCode(code) { - case BumpSequenceResultCodeBumpSequenceSuccess: - // void - case BumpSequenceResultCodeBumpSequenceBadSeq: - // void - } - return +var ( + _ encoding.BinaryMarshaler = (*ScEnvMetaEntry)(nil) + _ encoding.BinaryUnmarshaler = (*ScEnvMetaEntry)(nil) +) + +// xdrType signals that this type represents XDR values defined by this package. +func (s ScEnvMetaEntry) xdrType() {} + +var _ xdrType = (*ScEnvMetaEntry)(nil) + +// ScMetaV0 is an XDR Struct defines as: +// +// struct SCMetaV0 +// { +// string key<>; +// string val<>; +// }; +type ScMetaV0 struct { + Key string + Val string } // EncodeTo encodes this value using the Encoder. -func (u BumpSequenceResult) EncodeTo(e *xdr.Encoder) error { +func (s *ScMetaV0) EncodeTo(e *xdr.Encoder) error { var err error - if err = u.Code.EncodeTo(e); err != nil { + if _, err = e.EncodeString(string(s.Key)); err != nil { return err } - switch BumpSequenceResultCode(u.Code) { - case BumpSequenceResultCodeBumpSequenceSuccess: - // Void - return nil - case BumpSequenceResultCodeBumpSequenceBadSeq: - // Void - return nil + if _, err = e.EncodeString(string(s.Val)); err != nil { + return err } - return fmt.Errorf("Code (BumpSequenceResultCode) switch value '%d' is not valid for union BumpSequenceResult", u.Code) + return nil } -var _ decoderFrom = (*BumpSequenceResult)(nil) +var _ decoderFrom = (*ScMetaV0)(nil) // DecodeFrom decodes this value using the Decoder. -func (u *BumpSequenceResult) DecodeFrom(d *xdr.Decoder) (int, error) { +func (s *ScMetaV0) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding ScMetaV0: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = u.Code.DecodeFrom(d) + s.Key, nTmp, err = d.DecodeString(0) n += nTmp if err != nil { - return n, fmt.Errorf("decoding BumpSequenceResultCode: %s", err) + return n, fmt.Errorf("decoding Key: %w", err) } - switch BumpSequenceResultCode(u.Code) { - case BumpSequenceResultCodeBumpSequenceSuccess: - // Void - return n, nil - case BumpSequenceResultCodeBumpSequenceBadSeq: - // Void - return n, nil + s.Val, nTmp, err = d.DecodeString(0) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Val: %w", err) } - return n, fmt.Errorf("union BumpSequenceResult has invalid Code (BumpSequenceResultCode) switch value '%d'", u.Code) + return n, nil } // MarshalBinary implements encoding.BinaryMarshaler. -func (s BumpSequenceResult) MarshalBinary() ([]byte, error) { +func (s ScMetaV0) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -30983,94 +46907,84 @@ func (s BumpSequenceResult) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *BumpSequenceResult) UnmarshalBinary(inp []byte) error { +func (s *ScMetaV0) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*BumpSequenceResult)(nil) - _ encoding.BinaryUnmarshaler = (*BumpSequenceResult)(nil) + _ encoding.BinaryMarshaler = (*ScMetaV0)(nil) + _ encoding.BinaryUnmarshaler = (*ScMetaV0)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s BumpSequenceResult) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s ScMetaV0) xdrType() {} -var _ xdrType = (*BumpSequenceResult)(nil) +var _ xdrType = (*ScMetaV0)(nil) -// CreateClaimableBalanceResultCode is an XDR Enum defines as: +// ScMetaKind is an XDR Enum defines as: // -// enum CreateClaimableBalanceResultCode +// enum SCMetaKind // { -// CREATE_CLAIMABLE_BALANCE_SUCCESS = 0, -// CREATE_CLAIMABLE_BALANCE_MALFORMED = -1, -// CREATE_CLAIMABLE_BALANCE_LOW_RESERVE = -2, -// CREATE_CLAIMABLE_BALANCE_NO_TRUST = -3, -// CREATE_CLAIMABLE_BALANCE_NOT_AUTHORIZED = -4, -// CREATE_CLAIMABLE_BALANCE_UNDERFUNDED = -5 +// SC_META_V0 = 0 // }; -type CreateClaimableBalanceResultCode int32 +type ScMetaKind int32 const ( - CreateClaimableBalanceResultCodeCreateClaimableBalanceSuccess CreateClaimableBalanceResultCode = 0 - CreateClaimableBalanceResultCodeCreateClaimableBalanceMalformed CreateClaimableBalanceResultCode = -1 - CreateClaimableBalanceResultCodeCreateClaimableBalanceLowReserve CreateClaimableBalanceResultCode = -2 - CreateClaimableBalanceResultCodeCreateClaimableBalanceNoTrust CreateClaimableBalanceResultCode = -3 - CreateClaimableBalanceResultCodeCreateClaimableBalanceNotAuthorized CreateClaimableBalanceResultCode = -4 - CreateClaimableBalanceResultCodeCreateClaimableBalanceUnderfunded CreateClaimableBalanceResultCode = -5 + ScMetaKindScMetaV0 ScMetaKind = 0 ) -var createClaimableBalanceResultCodeMap = map[int32]string{ - 0: "CreateClaimableBalanceResultCodeCreateClaimableBalanceSuccess", - -1: "CreateClaimableBalanceResultCodeCreateClaimableBalanceMalformed", - -2: "CreateClaimableBalanceResultCodeCreateClaimableBalanceLowReserve", - -3: "CreateClaimableBalanceResultCodeCreateClaimableBalanceNoTrust", - -4: "CreateClaimableBalanceResultCodeCreateClaimableBalanceNotAuthorized", - -5: "CreateClaimableBalanceResultCodeCreateClaimableBalanceUnderfunded", +var scMetaKindMap = map[int32]string{ + 0: "ScMetaKindScMetaV0", } // ValidEnum validates a proposed value for this enum. Implements -// the Enum interface for CreateClaimableBalanceResultCode -func (e CreateClaimableBalanceResultCode) ValidEnum(v int32) bool { - _, ok := createClaimableBalanceResultCodeMap[v] +// the Enum interface for ScMetaKind +func (e ScMetaKind) ValidEnum(v int32) bool { + _, ok := scMetaKindMap[v] return ok } // String returns the name of `e` -func (e CreateClaimableBalanceResultCode) String() string { - name, _ := createClaimableBalanceResultCodeMap[int32(e)] +func (e ScMetaKind) String() string { + name, _ := scMetaKindMap[int32(e)] return name } // EncodeTo encodes this value using the Encoder. -func (e CreateClaimableBalanceResultCode) EncodeTo(enc *xdr.Encoder) error { - if _, ok := createClaimableBalanceResultCodeMap[int32(e)]; !ok { - return fmt.Errorf("'%d' is not a valid CreateClaimableBalanceResultCode enum value", e) +func (e ScMetaKind) EncodeTo(enc *xdr.Encoder) error { + if _, ok := scMetaKindMap[int32(e)]; !ok { + return fmt.Errorf("'%d' is not a valid ScMetaKind enum value", e) } _, err := enc.EncodeInt(int32(e)) return err } -var _ decoderFrom = (*CreateClaimableBalanceResultCode)(nil) +var _ decoderFrom = (*ScMetaKind)(nil) // DecodeFrom decodes this value using the Decoder. -func (e *CreateClaimableBalanceResultCode) DecodeFrom(d *xdr.Decoder) (int, error) { +func (e *ScMetaKind) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding ScMetaKind: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 v, n, err := d.DecodeInt() if err != nil { - return n, fmt.Errorf("decoding CreateClaimableBalanceResultCode: %s", err) + return n, fmt.Errorf("decoding ScMetaKind: %w", err) } - if _, ok := createClaimableBalanceResultCodeMap[v]; !ok { - return n, fmt.Errorf("'%d' is not a valid CreateClaimableBalanceResultCode enum value", v) + if _, ok := scMetaKindMap[v]; !ok { + return n, fmt.Errorf("'%d' is not a valid ScMetaKind enum value", v) } - *e = CreateClaimableBalanceResultCode(v) + *e = ScMetaKind(v) return n, nil } // MarshalBinary implements encoding.BinaryMarshaler. -func (s CreateClaimableBalanceResultCode) MarshalBinary() ([]byte, error) { +func (s ScMetaKind) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -31078,113 +46992,87 @@ func (s CreateClaimableBalanceResultCode) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *CreateClaimableBalanceResultCode) UnmarshalBinary(inp []byte) error { +func (s *ScMetaKind) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*CreateClaimableBalanceResultCode)(nil) - _ encoding.BinaryUnmarshaler = (*CreateClaimableBalanceResultCode)(nil) + _ encoding.BinaryMarshaler = (*ScMetaKind)(nil) + _ encoding.BinaryUnmarshaler = (*ScMetaKind)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s CreateClaimableBalanceResultCode) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s ScMetaKind) xdrType() {} -var _ xdrType = (*CreateClaimableBalanceResultCode)(nil) +var _ xdrType = (*ScMetaKind)(nil) -// CreateClaimableBalanceResult is an XDR Union defines as: +// ScMetaEntry is an XDR Union defines as: // -// union CreateClaimableBalanceResult switch ( -// CreateClaimableBalanceResultCode code) +// union SCMetaEntry switch (SCMetaKind kind) // { -// case CREATE_CLAIMABLE_BALANCE_SUCCESS: -// ClaimableBalanceID balanceID; -// case CREATE_CLAIMABLE_BALANCE_MALFORMED: -// case CREATE_CLAIMABLE_BALANCE_LOW_RESERVE: -// case CREATE_CLAIMABLE_BALANCE_NO_TRUST: -// case CREATE_CLAIMABLE_BALANCE_NOT_AUTHORIZED: -// case CREATE_CLAIMABLE_BALANCE_UNDERFUNDED: -// void; +// case SC_META_V0: +// SCMetaV0 v0; // }; -type CreateClaimableBalanceResult struct { - Code CreateClaimableBalanceResultCode - BalanceId *ClaimableBalanceId +type ScMetaEntry struct { + Kind ScMetaKind + V0 *ScMetaV0 } // SwitchFieldName returns the field name in which this union's // discriminant is stored -func (u CreateClaimableBalanceResult) SwitchFieldName() string { - return "Code" +func (u ScMetaEntry) SwitchFieldName() string { + return "Kind" } // ArmForSwitch returns which field name should be used for storing -// the value for an instance of CreateClaimableBalanceResult -func (u CreateClaimableBalanceResult) ArmForSwitch(sw int32) (string, bool) { - switch CreateClaimableBalanceResultCode(sw) { - case CreateClaimableBalanceResultCodeCreateClaimableBalanceSuccess: - return "BalanceId", true - case CreateClaimableBalanceResultCodeCreateClaimableBalanceMalformed: - return "", true - case CreateClaimableBalanceResultCodeCreateClaimableBalanceLowReserve: - return "", true - case CreateClaimableBalanceResultCodeCreateClaimableBalanceNoTrust: - return "", true - case CreateClaimableBalanceResultCodeCreateClaimableBalanceNotAuthorized: - return "", true - case CreateClaimableBalanceResultCodeCreateClaimableBalanceUnderfunded: - return "", true +// the value for an instance of ScMetaEntry +func (u ScMetaEntry) ArmForSwitch(sw int32) (string, bool) { + switch ScMetaKind(sw) { + case ScMetaKindScMetaV0: + return "V0", true } return "-", false } -// NewCreateClaimableBalanceResult creates a new CreateClaimableBalanceResult. -func NewCreateClaimableBalanceResult(code CreateClaimableBalanceResultCode, value interface{}) (result CreateClaimableBalanceResult, err error) { - result.Code = code - switch CreateClaimableBalanceResultCode(code) { - case CreateClaimableBalanceResultCodeCreateClaimableBalanceSuccess: - tv, ok := value.(ClaimableBalanceId) +// NewScMetaEntry creates a new ScMetaEntry. +func NewScMetaEntry(kind ScMetaKind, value interface{}) (result ScMetaEntry, err error) { + result.Kind = kind + switch ScMetaKind(kind) { + case ScMetaKindScMetaV0: + tv, ok := value.(ScMetaV0) if !ok { - err = fmt.Errorf("invalid value, must be ClaimableBalanceId") + err = errors.New("invalid value, must be ScMetaV0") return } - result.BalanceId = &tv - case CreateClaimableBalanceResultCodeCreateClaimableBalanceMalformed: - // void - case CreateClaimableBalanceResultCodeCreateClaimableBalanceLowReserve: - // void - case CreateClaimableBalanceResultCodeCreateClaimableBalanceNoTrust: - // void - case CreateClaimableBalanceResultCodeCreateClaimableBalanceNotAuthorized: - // void - case CreateClaimableBalanceResultCodeCreateClaimableBalanceUnderfunded: - // void + result.V0 = &tv } return } -// MustBalanceId retrieves the BalanceId value from the union, +// MustV0 retrieves the V0 value from the union, // panicing if the value is not set. -func (u CreateClaimableBalanceResult) MustBalanceId() ClaimableBalanceId { - val, ok := u.GetBalanceId() +func (u ScMetaEntry) MustV0() ScMetaV0 { + val, ok := u.GetV0() if !ok { - panic("arm BalanceId is not set") + panic("arm V0 is not set") } return val } -// GetBalanceId retrieves the BalanceId value from the union, +// GetV0 retrieves the V0 value from the union, // returning ok if the union's switch indicated the value is valid. -func (u CreateClaimableBalanceResult) GetBalanceId() (result ClaimableBalanceId, ok bool) { - armName, _ := u.ArmForSwitch(int32(u.Code)) +func (u ScMetaEntry) GetV0() (result ScMetaV0, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Kind)) - if armName == "BalanceId" { - result = *u.BalanceId + if armName == "V0" { + result = *u.V0 ok = true } @@ -31192,77 +47080,51 @@ func (u CreateClaimableBalanceResult) GetBalanceId() (result ClaimableBalanceId, } // EncodeTo encodes this value using the Encoder. -func (u CreateClaimableBalanceResult) EncodeTo(e *xdr.Encoder) error { +func (u ScMetaEntry) EncodeTo(e *xdr.Encoder) error { var err error - if err = u.Code.EncodeTo(e); err != nil { + if err = u.Kind.EncodeTo(e); err != nil { return err } - switch CreateClaimableBalanceResultCode(u.Code) { - case CreateClaimableBalanceResultCodeCreateClaimableBalanceSuccess: - if err = (*u.BalanceId).EncodeTo(e); err != nil { + switch ScMetaKind(u.Kind) { + case ScMetaKindScMetaV0: + if err = (*u.V0).EncodeTo(e); err != nil { return err } return nil - case CreateClaimableBalanceResultCodeCreateClaimableBalanceMalformed: - // Void - return nil - case CreateClaimableBalanceResultCodeCreateClaimableBalanceLowReserve: - // Void - return nil - case CreateClaimableBalanceResultCodeCreateClaimableBalanceNoTrust: - // Void - return nil - case CreateClaimableBalanceResultCodeCreateClaimableBalanceNotAuthorized: - // Void - return nil - case CreateClaimableBalanceResultCodeCreateClaimableBalanceUnderfunded: - // Void - return nil } - return fmt.Errorf("Code (CreateClaimableBalanceResultCode) switch value '%d' is not valid for union CreateClaimableBalanceResult", u.Code) + return fmt.Errorf("Kind (ScMetaKind) switch value '%d' is not valid for union ScMetaEntry", u.Kind) } -var _ decoderFrom = (*CreateClaimableBalanceResult)(nil) +var _ decoderFrom = (*ScMetaEntry)(nil) // DecodeFrom decodes this value using the Decoder. -func (u *CreateClaimableBalanceResult) DecodeFrom(d *xdr.Decoder) (int, error) { +func (u *ScMetaEntry) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding ScMetaEntry: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = u.Code.DecodeFrom(d) + nTmp, err = u.Kind.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding CreateClaimableBalanceResultCode: %s", err) + return n, fmt.Errorf("decoding ScMetaKind: %w", err) } - switch CreateClaimableBalanceResultCode(u.Code) { - case CreateClaimableBalanceResultCodeCreateClaimableBalanceSuccess: - u.BalanceId = new(ClaimableBalanceId) - nTmp, err = (*u.BalanceId).DecodeFrom(d) + switch ScMetaKind(u.Kind) { + case ScMetaKindScMetaV0: + u.V0 = new(ScMetaV0) + nTmp, err = (*u.V0).DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding ClaimableBalanceId: %s", err) + return n, fmt.Errorf("decoding ScMetaV0: %w", err) } return n, nil - case CreateClaimableBalanceResultCodeCreateClaimableBalanceMalformed: - // Void - return n, nil - case CreateClaimableBalanceResultCodeCreateClaimableBalanceLowReserve: - // Void - return n, nil - case CreateClaimableBalanceResultCodeCreateClaimableBalanceNoTrust: - // Void - return n, nil - case CreateClaimableBalanceResultCodeCreateClaimableBalanceNotAuthorized: - // Void - return n, nil - case CreateClaimableBalanceResultCodeCreateClaimableBalanceUnderfunded: - // Void - return n, nil } - return n, fmt.Errorf("union CreateClaimableBalanceResult has invalid Code (CreateClaimableBalanceResultCode) switch value '%d'", u.Code) + return n, fmt.Errorf("union ScMetaEntry has invalid Kind (ScMetaKind) switch value '%d'", u.Kind) } // MarshalBinary implements encoding.BinaryMarshaler. -func (s CreateClaimableBalanceResult) MarshalBinary() ([]byte, error) { +func (s ScMetaEntry) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -31270,94 +47132,167 @@ func (s CreateClaimableBalanceResult) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *CreateClaimableBalanceResult) UnmarshalBinary(inp []byte) error { +func (s *ScMetaEntry) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*CreateClaimableBalanceResult)(nil) - _ encoding.BinaryUnmarshaler = (*CreateClaimableBalanceResult)(nil) + _ encoding.BinaryMarshaler = (*ScMetaEntry)(nil) + _ encoding.BinaryUnmarshaler = (*ScMetaEntry)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s CreateClaimableBalanceResult) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s ScMetaEntry) xdrType() {} -var _ xdrType = (*CreateClaimableBalanceResult)(nil) +var _ xdrType = (*ScMetaEntry)(nil) -// ClaimClaimableBalanceResultCode is an XDR Enum defines as: +// ScSpecDocLimit is an XDR Const defines as: // -// enum ClaimClaimableBalanceResultCode +// const SC_SPEC_DOC_LIMIT = 1024; +const ScSpecDocLimit = 1024 + +// ScSpecType is an XDR Enum defines as: +// +// enum SCSpecType // { -// CLAIM_CLAIMABLE_BALANCE_SUCCESS = 0, -// CLAIM_CLAIMABLE_BALANCE_DOES_NOT_EXIST = -1, -// CLAIM_CLAIMABLE_BALANCE_CANNOT_CLAIM = -2, -// CLAIM_CLAIMABLE_BALANCE_LINE_FULL = -3, -// CLAIM_CLAIMABLE_BALANCE_NO_TRUST = -4, -// CLAIM_CLAIMABLE_BALANCE_NOT_AUTHORIZED = -5 +// SC_SPEC_TYPE_VAL = 0, +// +// // Types with no parameters. +// SC_SPEC_TYPE_BOOL = 1, +// SC_SPEC_TYPE_VOID = 2, +// SC_SPEC_TYPE_ERROR = 3, +// SC_SPEC_TYPE_U32 = 4, +// SC_SPEC_TYPE_I32 = 5, +// SC_SPEC_TYPE_U64 = 6, +// SC_SPEC_TYPE_I64 = 7, +// SC_SPEC_TYPE_TIMEPOINT = 8, +// SC_SPEC_TYPE_DURATION = 9, +// SC_SPEC_TYPE_U128 = 10, +// SC_SPEC_TYPE_I128 = 11, +// SC_SPEC_TYPE_U256 = 12, +// SC_SPEC_TYPE_I256 = 13, +// SC_SPEC_TYPE_BYTES = 14, +// SC_SPEC_TYPE_STRING = 16, +// SC_SPEC_TYPE_SYMBOL = 17, +// SC_SPEC_TYPE_ADDRESS = 19, +// +// // Types with parameters. +// SC_SPEC_TYPE_OPTION = 1000, +// SC_SPEC_TYPE_RESULT = 1001, +// SC_SPEC_TYPE_VEC = 1002, +// SC_SPEC_TYPE_MAP = 1004, +// SC_SPEC_TYPE_TUPLE = 1005, +// SC_SPEC_TYPE_BYTES_N = 1006, +// +// // User defined types. +// SC_SPEC_TYPE_UDT = 2000 // }; -type ClaimClaimableBalanceResultCode int32 +type ScSpecType int32 const ( - ClaimClaimableBalanceResultCodeClaimClaimableBalanceSuccess ClaimClaimableBalanceResultCode = 0 - ClaimClaimableBalanceResultCodeClaimClaimableBalanceDoesNotExist ClaimClaimableBalanceResultCode = -1 - ClaimClaimableBalanceResultCodeClaimClaimableBalanceCannotClaim ClaimClaimableBalanceResultCode = -2 - ClaimClaimableBalanceResultCodeClaimClaimableBalanceLineFull ClaimClaimableBalanceResultCode = -3 - ClaimClaimableBalanceResultCodeClaimClaimableBalanceNoTrust ClaimClaimableBalanceResultCode = -4 - ClaimClaimableBalanceResultCodeClaimClaimableBalanceNotAuthorized ClaimClaimableBalanceResultCode = -5 -) - -var claimClaimableBalanceResultCodeMap = map[int32]string{ - 0: "ClaimClaimableBalanceResultCodeClaimClaimableBalanceSuccess", - -1: "ClaimClaimableBalanceResultCodeClaimClaimableBalanceDoesNotExist", - -2: "ClaimClaimableBalanceResultCodeClaimClaimableBalanceCannotClaim", - -3: "ClaimClaimableBalanceResultCodeClaimClaimableBalanceLineFull", - -4: "ClaimClaimableBalanceResultCodeClaimClaimableBalanceNoTrust", - -5: "ClaimClaimableBalanceResultCodeClaimClaimableBalanceNotAuthorized", + ScSpecTypeScSpecTypeVal ScSpecType = 0 + ScSpecTypeScSpecTypeBool ScSpecType = 1 + ScSpecTypeScSpecTypeVoid ScSpecType = 2 + ScSpecTypeScSpecTypeError ScSpecType = 3 + ScSpecTypeScSpecTypeU32 ScSpecType = 4 + ScSpecTypeScSpecTypeI32 ScSpecType = 5 + ScSpecTypeScSpecTypeU64 ScSpecType = 6 + ScSpecTypeScSpecTypeI64 ScSpecType = 7 + ScSpecTypeScSpecTypeTimepoint ScSpecType = 8 + ScSpecTypeScSpecTypeDuration ScSpecType = 9 + ScSpecTypeScSpecTypeU128 ScSpecType = 10 + ScSpecTypeScSpecTypeI128 ScSpecType = 11 + ScSpecTypeScSpecTypeU256 ScSpecType = 12 + ScSpecTypeScSpecTypeI256 ScSpecType = 13 + ScSpecTypeScSpecTypeBytes ScSpecType = 14 + ScSpecTypeScSpecTypeString ScSpecType = 16 + ScSpecTypeScSpecTypeSymbol ScSpecType = 17 + ScSpecTypeScSpecTypeAddress ScSpecType = 19 + ScSpecTypeScSpecTypeOption ScSpecType = 1000 + ScSpecTypeScSpecTypeResult ScSpecType = 1001 + ScSpecTypeScSpecTypeVec ScSpecType = 1002 + ScSpecTypeScSpecTypeMap ScSpecType = 1004 + ScSpecTypeScSpecTypeTuple ScSpecType = 1005 + ScSpecTypeScSpecTypeBytesN ScSpecType = 1006 + ScSpecTypeScSpecTypeUdt ScSpecType = 2000 +) + +var scSpecTypeMap = map[int32]string{ + 0: "ScSpecTypeScSpecTypeVal", + 1: "ScSpecTypeScSpecTypeBool", + 2: "ScSpecTypeScSpecTypeVoid", + 3: "ScSpecTypeScSpecTypeError", + 4: "ScSpecTypeScSpecTypeU32", + 5: "ScSpecTypeScSpecTypeI32", + 6: "ScSpecTypeScSpecTypeU64", + 7: "ScSpecTypeScSpecTypeI64", + 8: "ScSpecTypeScSpecTypeTimepoint", + 9: "ScSpecTypeScSpecTypeDuration", + 10: "ScSpecTypeScSpecTypeU128", + 11: "ScSpecTypeScSpecTypeI128", + 12: "ScSpecTypeScSpecTypeU256", + 13: "ScSpecTypeScSpecTypeI256", + 14: "ScSpecTypeScSpecTypeBytes", + 16: "ScSpecTypeScSpecTypeString", + 17: "ScSpecTypeScSpecTypeSymbol", + 19: "ScSpecTypeScSpecTypeAddress", + 1000: "ScSpecTypeScSpecTypeOption", + 1001: "ScSpecTypeScSpecTypeResult", + 1002: "ScSpecTypeScSpecTypeVec", + 1004: "ScSpecTypeScSpecTypeMap", + 1005: "ScSpecTypeScSpecTypeTuple", + 1006: "ScSpecTypeScSpecTypeBytesN", + 2000: "ScSpecTypeScSpecTypeUdt", } // ValidEnum validates a proposed value for this enum. Implements -// the Enum interface for ClaimClaimableBalanceResultCode -func (e ClaimClaimableBalanceResultCode) ValidEnum(v int32) bool { - _, ok := claimClaimableBalanceResultCodeMap[v] +// the Enum interface for ScSpecType +func (e ScSpecType) ValidEnum(v int32) bool { + _, ok := scSpecTypeMap[v] return ok } // String returns the name of `e` -func (e ClaimClaimableBalanceResultCode) String() string { - name, _ := claimClaimableBalanceResultCodeMap[int32(e)] +func (e ScSpecType) String() string { + name, _ := scSpecTypeMap[int32(e)] return name } // EncodeTo encodes this value using the Encoder. -func (e ClaimClaimableBalanceResultCode) EncodeTo(enc *xdr.Encoder) error { - if _, ok := claimClaimableBalanceResultCodeMap[int32(e)]; !ok { - return fmt.Errorf("'%d' is not a valid ClaimClaimableBalanceResultCode enum value", e) +func (e ScSpecType) EncodeTo(enc *xdr.Encoder) error { + if _, ok := scSpecTypeMap[int32(e)]; !ok { + return fmt.Errorf("'%d' is not a valid ScSpecType enum value", e) } _, err := enc.EncodeInt(int32(e)) return err } -var _ decoderFrom = (*ClaimClaimableBalanceResultCode)(nil) +var _ decoderFrom = (*ScSpecType)(nil) // DecodeFrom decodes this value using the Decoder. -func (e *ClaimClaimableBalanceResultCode) DecodeFrom(d *xdr.Decoder) (int, error) { +func (e *ScSpecType) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding ScSpecType: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 v, n, err := d.DecodeInt() if err != nil { - return n, fmt.Errorf("decoding ClaimClaimableBalanceResultCode: %s", err) + return n, fmt.Errorf("decoding ScSpecType: %w", err) } - if _, ok := claimClaimableBalanceResultCodeMap[v]; !ok { - return n, fmt.Errorf("'%d' is not a valid ClaimClaimableBalanceResultCode enum value", v) + if _, ok := scSpecTypeMap[v]; !ok { + return n, fmt.Errorf("'%d' is not a valid ScSpecType enum value", v) } - *e = ClaimClaimableBalanceResultCode(v) + *e = ScSpecType(v) return n, nil } // MarshalBinary implements encoding.BinaryMarshaler. -func (s ClaimClaimableBalanceResultCode) MarshalBinary() ([]byte, error) { +func (s ScSpecType) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -31365,152 +47300,139 @@ func (s ClaimClaimableBalanceResultCode) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *ClaimClaimableBalanceResultCode) UnmarshalBinary(inp []byte) error { +func (s *ScSpecType) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*ClaimClaimableBalanceResultCode)(nil) - _ encoding.BinaryUnmarshaler = (*ClaimClaimableBalanceResultCode)(nil) + _ encoding.BinaryMarshaler = (*ScSpecType)(nil) + _ encoding.BinaryUnmarshaler = (*ScSpecType)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s ClaimClaimableBalanceResultCode) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s ScSpecType) xdrType() {} -var _ xdrType = (*ClaimClaimableBalanceResultCode)(nil) +var _ xdrType = (*ScSpecType)(nil) -// ClaimClaimableBalanceResult is an XDR Union defines as: +// ScSpecTypeOption is an XDR Struct defines as: // -// union ClaimClaimableBalanceResult switch (ClaimClaimableBalanceResultCode code) +// struct SCSpecTypeOption // { -// case CLAIM_CLAIMABLE_BALANCE_SUCCESS: -// void; -// case CLAIM_CLAIMABLE_BALANCE_DOES_NOT_EXIST: -// case CLAIM_CLAIMABLE_BALANCE_CANNOT_CLAIM: -// case CLAIM_CLAIMABLE_BALANCE_LINE_FULL: -// case CLAIM_CLAIMABLE_BALANCE_NO_TRUST: -// case CLAIM_CLAIMABLE_BALANCE_NOT_AUTHORIZED: -// void; +// SCSpecTypeDef valueType; // }; -type ClaimClaimableBalanceResult struct { - Code ClaimClaimableBalanceResultCode +type ScSpecTypeOption struct { + ValueType ScSpecTypeDef } -// SwitchFieldName returns the field name in which this union's -// discriminant is stored -func (u ClaimClaimableBalanceResult) SwitchFieldName() string { - return "Code" +// EncodeTo encodes this value using the Encoder. +func (s *ScSpecTypeOption) EncodeTo(e *xdr.Encoder) error { + var err error + if err = s.ValueType.EncodeTo(e); err != nil { + return err + } + return nil } -// ArmForSwitch returns which field name should be used for storing -// the value for an instance of ClaimClaimableBalanceResult -func (u ClaimClaimableBalanceResult) ArmForSwitch(sw int32) (string, bool) { - switch ClaimClaimableBalanceResultCode(sw) { - case ClaimClaimableBalanceResultCodeClaimClaimableBalanceSuccess: - return "", true - case ClaimClaimableBalanceResultCodeClaimClaimableBalanceDoesNotExist: - return "", true - case ClaimClaimableBalanceResultCodeClaimClaimableBalanceCannotClaim: - return "", true - case ClaimClaimableBalanceResultCodeClaimClaimableBalanceLineFull: - return "", true - case ClaimClaimableBalanceResultCodeClaimClaimableBalanceNoTrust: - return "", true - case ClaimClaimableBalanceResultCodeClaimClaimableBalanceNotAuthorized: - return "", true +var _ decoderFrom = (*ScSpecTypeOption)(nil) + +// DecodeFrom decodes this value using the Decoder. +func (s *ScSpecTypeOption) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding ScSpecTypeOption: %w", ErrMaxDecodingDepthReached) } - return "-", false + maxDepth -= 1 + var err error + var n, nTmp int + nTmp, err = s.ValueType.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ScSpecTypeDef: %w", err) + } + return n, nil } -// NewClaimClaimableBalanceResult creates a new ClaimClaimableBalanceResult. -func NewClaimClaimableBalanceResult(code ClaimClaimableBalanceResultCode, value interface{}) (result ClaimClaimableBalanceResult, err error) { - result.Code = code - switch ClaimClaimableBalanceResultCode(code) { - case ClaimClaimableBalanceResultCodeClaimClaimableBalanceSuccess: - // void - case ClaimClaimableBalanceResultCodeClaimClaimableBalanceDoesNotExist: - // void - case ClaimClaimableBalanceResultCodeClaimClaimableBalanceCannotClaim: - // void - case ClaimClaimableBalanceResultCodeClaimClaimableBalanceLineFull: - // void - case ClaimClaimableBalanceResultCodeClaimClaimableBalanceNoTrust: - // void - case ClaimClaimableBalanceResultCodeClaimClaimableBalanceNotAuthorized: - // void - } - return +// MarshalBinary implements encoding.BinaryMarshaler. +func (s ScSpecTypeOption) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *ScSpecTypeOption) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} + +var ( + _ encoding.BinaryMarshaler = (*ScSpecTypeOption)(nil) + _ encoding.BinaryUnmarshaler = (*ScSpecTypeOption)(nil) +) + +// xdrType signals that this type represents XDR values defined by this package. +func (s ScSpecTypeOption) xdrType() {} + +var _ xdrType = (*ScSpecTypeOption)(nil) + +// ScSpecTypeResult is an XDR Struct defines as: +// +// struct SCSpecTypeResult +// { +// SCSpecTypeDef okType; +// SCSpecTypeDef errorType; +// }; +type ScSpecTypeResult struct { + OkType ScSpecTypeDef + ErrorType ScSpecTypeDef } // EncodeTo encodes this value using the Encoder. -func (u ClaimClaimableBalanceResult) EncodeTo(e *xdr.Encoder) error { +func (s *ScSpecTypeResult) EncodeTo(e *xdr.Encoder) error { var err error - if err = u.Code.EncodeTo(e); err != nil { + if err = s.OkType.EncodeTo(e); err != nil { return err } - switch ClaimClaimableBalanceResultCode(u.Code) { - case ClaimClaimableBalanceResultCodeClaimClaimableBalanceSuccess: - // Void - return nil - case ClaimClaimableBalanceResultCodeClaimClaimableBalanceDoesNotExist: - // Void - return nil - case ClaimClaimableBalanceResultCodeClaimClaimableBalanceCannotClaim: - // Void - return nil - case ClaimClaimableBalanceResultCodeClaimClaimableBalanceLineFull: - // Void - return nil - case ClaimClaimableBalanceResultCodeClaimClaimableBalanceNoTrust: - // Void - return nil - case ClaimClaimableBalanceResultCodeClaimClaimableBalanceNotAuthorized: - // Void - return nil + if err = s.ErrorType.EncodeTo(e); err != nil { + return err } - return fmt.Errorf("Code (ClaimClaimableBalanceResultCode) switch value '%d' is not valid for union ClaimClaimableBalanceResult", u.Code) + return nil } -var _ decoderFrom = (*ClaimClaimableBalanceResult)(nil) +var _ decoderFrom = (*ScSpecTypeResult)(nil) // DecodeFrom decodes this value using the Decoder. -func (u *ClaimClaimableBalanceResult) DecodeFrom(d *xdr.Decoder) (int, error) { +func (s *ScSpecTypeResult) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding ScSpecTypeResult: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = u.Code.DecodeFrom(d) + nTmp, err = s.OkType.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding ClaimClaimableBalanceResultCode: %s", err) + return n, fmt.Errorf("decoding ScSpecTypeDef: %w", err) } - switch ClaimClaimableBalanceResultCode(u.Code) { - case ClaimClaimableBalanceResultCodeClaimClaimableBalanceSuccess: - // Void - return n, nil - case ClaimClaimableBalanceResultCodeClaimClaimableBalanceDoesNotExist: - // Void - return n, nil - case ClaimClaimableBalanceResultCodeClaimClaimableBalanceCannotClaim: - // Void - return n, nil - case ClaimClaimableBalanceResultCodeClaimClaimableBalanceLineFull: - // Void - return n, nil - case ClaimClaimableBalanceResultCodeClaimClaimableBalanceNoTrust: - // Void - return n, nil - case ClaimClaimableBalanceResultCodeClaimClaimableBalanceNotAuthorized: - // Void - return n, nil + nTmp, err = s.ErrorType.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ScSpecTypeDef: %w", err) } - return n, fmt.Errorf("union ClaimClaimableBalanceResult has invalid Code (ClaimClaimableBalanceResultCode) switch value '%d'", u.Code) + return n, nil } // MarshalBinary implements encoding.BinaryMarshaler. -func (s ClaimClaimableBalanceResult) MarshalBinary() ([]byte, error) { +func (s ScSpecTypeResult) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -31518,91 +47440,64 @@ func (s ClaimClaimableBalanceResult) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *ClaimClaimableBalanceResult) UnmarshalBinary(inp []byte) error { +func (s *ScSpecTypeResult) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*ClaimClaimableBalanceResult)(nil) - _ encoding.BinaryUnmarshaler = (*ClaimClaimableBalanceResult)(nil) + _ encoding.BinaryMarshaler = (*ScSpecTypeResult)(nil) + _ encoding.BinaryUnmarshaler = (*ScSpecTypeResult)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s ClaimClaimableBalanceResult) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s ScSpecTypeResult) xdrType() {} -var _ xdrType = (*ClaimClaimableBalanceResult)(nil) +var _ xdrType = (*ScSpecTypeResult)(nil) -// BeginSponsoringFutureReservesResultCode is an XDR Enum defines as: +// ScSpecTypeVec is an XDR Struct defines as: // -// enum BeginSponsoringFutureReservesResultCode +// struct SCSpecTypeVec // { -// // codes considered as "success" for the operation -// BEGIN_SPONSORING_FUTURE_RESERVES_SUCCESS = 0, -// -// // codes considered as "failure" for the operation -// BEGIN_SPONSORING_FUTURE_RESERVES_MALFORMED = -1, -// BEGIN_SPONSORING_FUTURE_RESERVES_ALREADY_SPONSORED = -2, -// BEGIN_SPONSORING_FUTURE_RESERVES_RECURSIVE = -3 +// SCSpecTypeDef elementType; // }; -type BeginSponsoringFutureReservesResultCode int32 - -const ( - BeginSponsoringFutureReservesResultCodeBeginSponsoringFutureReservesSuccess BeginSponsoringFutureReservesResultCode = 0 - BeginSponsoringFutureReservesResultCodeBeginSponsoringFutureReservesMalformed BeginSponsoringFutureReservesResultCode = -1 - BeginSponsoringFutureReservesResultCodeBeginSponsoringFutureReservesAlreadySponsored BeginSponsoringFutureReservesResultCode = -2 - BeginSponsoringFutureReservesResultCodeBeginSponsoringFutureReservesRecursive BeginSponsoringFutureReservesResultCode = -3 -) - -var beginSponsoringFutureReservesResultCodeMap = map[int32]string{ - 0: "BeginSponsoringFutureReservesResultCodeBeginSponsoringFutureReservesSuccess", - -1: "BeginSponsoringFutureReservesResultCodeBeginSponsoringFutureReservesMalformed", - -2: "BeginSponsoringFutureReservesResultCodeBeginSponsoringFutureReservesAlreadySponsored", - -3: "BeginSponsoringFutureReservesResultCodeBeginSponsoringFutureReservesRecursive", -} - -// ValidEnum validates a proposed value for this enum. Implements -// the Enum interface for BeginSponsoringFutureReservesResultCode -func (e BeginSponsoringFutureReservesResultCode) ValidEnum(v int32) bool { - _, ok := beginSponsoringFutureReservesResultCodeMap[v] - return ok -} - -// String returns the name of `e` -func (e BeginSponsoringFutureReservesResultCode) String() string { - name, _ := beginSponsoringFutureReservesResultCodeMap[int32(e)] - return name +type ScSpecTypeVec struct { + ElementType ScSpecTypeDef } // EncodeTo encodes this value using the Encoder. -func (e BeginSponsoringFutureReservesResultCode) EncodeTo(enc *xdr.Encoder) error { - if _, ok := beginSponsoringFutureReservesResultCodeMap[int32(e)]; !ok { - return fmt.Errorf("'%d' is not a valid BeginSponsoringFutureReservesResultCode enum value", e) +func (s *ScSpecTypeVec) EncodeTo(e *xdr.Encoder) error { + var err error + if err = s.ElementType.EncodeTo(e); err != nil { + return err } - _, err := enc.EncodeInt(int32(e)) - return err + return nil } -var _ decoderFrom = (*BeginSponsoringFutureReservesResultCode)(nil) +var _ decoderFrom = (*ScSpecTypeVec)(nil) // DecodeFrom decodes this value using the Decoder. -func (e *BeginSponsoringFutureReservesResultCode) DecodeFrom(d *xdr.Decoder) (int, error) { - v, n, err := d.DecodeInt() - if err != nil { - return n, fmt.Errorf("decoding BeginSponsoringFutureReservesResultCode: %s", err) +func (s *ScSpecTypeVec) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding ScSpecTypeVec: %w", ErrMaxDecodingDepthReached) } - if _, ok := beginSponsoringFutureReservesResultCodeMap[v]; !ok { - return n, fmt.Errorf("'%d' is not a valid BeginSponsoringFutureReservesResultCode enum value", v) + maxDepth -= 1 + var err error + var n, nTmp int + nTmp, err = s.ElementType.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ScSpecTypeDef: %w", err) } - *e = BeginSponsoringFutureReservesResultCode(v) return n, nil } // MarshalBinary implements encoding.BinaryMarshaler. -func (s BeginSponsoringFutureReservesResultCode) MarshalBinary() ([]byte, error) { +func (s ScSpecTypeVec) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -31610,131 +47505,74 @@ func (s BeginSponsoringFutureReservesResultCode) MarshalBinary() ([]byte, error) } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *BeginSponsoringFutureReservesResultCode) UnmarshalBinary(inp []byte) error { +func (s *ScSpecTypeVec) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*BeginSponsoringFutureReservesResultCode)(nil) - _ encoding.BinaryUnmarshaler = (*BeginSponsoringFutureReservesResultCode)(nil) + _ encoding.BinaryMarshaler = (*ScSpecTypeVec)(nil) + _ encoding.BinaryUnmarshaler = (*ScSpecTypeVec)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s BeginSponsoringFutureReservesResultCode) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s ScSpecTypeVec) xdrType() {} -var _ xdrType = (*BeginSponsoringFutureReservesResultCode)(nil) +var _ xdrType = (*ScSpecTypeVec)(nil) -// BeginSponsoringFutureReservesResult is an XDR Union defines as: +// ScSpecTypeMap is an XDR Struct defines as: // -// union BeginSponsoringFutureReservesResult switch ( -// BeginSponsoringFutureReservesResultCode code) +// struct SCSpecTypeMap // { -// case BEGIN_SPONSORING_FUTURE_RESERVES_SUCCESS: -// void; -// case BEGIN_SPONSORING_FUTURE_RESERVES_MALFORMED: -// case BEGIN_SPONSORING_FUTURE_RESERVES_ALREADY_SPONSORED: -// case BEGIN_SPONSORING_FUTURE_RESERVES_RECURSIVE: -// void; +// SCSpecTypeDef keyType; +// SCSpecTypeDef valueType; // }; -type BeginSponsoringFutureReservesResult struct { - Code BeginSponsoringFutureReservesResultCode -} - -// SwitchFieldName returns the field name in which this union's -// discriminant is stored -func (u BeginSponsoringFutureReservesResult) SwitchFieldName() string { - return "Code" -} - -// ArmForSwitch returns which field name should be used for storing -// the value for an instance of BeginSponsoringFutureReservesResult -func (u BeginSponsoringFutureReservesResult) ArmForSwitch(sw int32) (string, bool) { - switch BeginSponsoringFutureReservesResultCode(sw) { - case BeginSponsoringFutureReservesResultCodeBeginSponsoringFutureReservesSuccess: - return "", true - case BeginSponsoringFutureReservesResultCodeBeginSponsoringFutureReservesMalformed: - return "", true - case BeginSponsoringFutureReservesResultCodeBeginSponsoringFutureReservesAlreadySponsored: - return "", true - case BeginSponsoringFutureReservesResultCodeBeginSponsoringFutureReservesRecursive: - return "", true - } - return "-", false -} - -// NewBeginSponsoringFutureReservesResult creates a new BeginSponsoringFutureReservesResult. -func NewBeginSponsoringFutureReservesResult(code BeginSponsoringFutureReservesResultCode, value interface{}) (result BeginSponsoringFutureReservesResult, err error) { - result.Code = code - switch BeginSponsoringFutureReservesResultCode(code) { - case BeginSponsoringFutureReservesResultCodeBeginSponsoringFutureReservesSuccess: - // void - case BeginSponsoringFutureReservesResultCodeBeginSponsoringFutureReservesMalformed: - // void - case BeginSponsoringFutureReservesResultCodeBeginSponsoringFutureReservesAlreadySponsored: - // void - case BeginSponsoringFutureReservesResultCodeBeginSponsoringFutureReservesRecursive: - // void - } - return +type ScSpecTypeMap struct { + KeyType ScSpecTypeDef + ValueType ScSpecTypeDef } // EncodeTo encodes this value using the Encoder. -func (u BeginSponsoringFutureReservesResult) EncodeTo(e *xdr.Encoder) error { +func (s *ScSpecTypeMap) EncodeTo(e *xdr.Encoder) error { var err error - if err = u.Code.EncodeTo(e); err != nil { + if err = s.KeyType.EncodeTo(e); err != nil { return err } - switch BeginSponsoringFutureReservesResultCode(u.Code) { - case BeginSponsoringFutureReservesResultCodeBeginSponsoringFutureReservesSuccess: - // Void - return nil - case BeginSponsoringFutureReservesResultCodeBeginSponsoringFutureReservesMalformed: - // Void - return nil - case BeginSponsoringFutureReservesResultCodeBeginSponsoringFutureReservesAlreadySponsored: - // Void - return nil - case BeginSponsoringFutureReservesResultCodeBeginSponsoringFutureReservesRecursive: - // Void - return nil + if err = s.ValueType.EncodeTo(e); err != nil { + return err } - return fmt.Errorf("Code (BeginSponsoringFutureReservesResultCode) switch value '%d' is not valid for union BeginSponsoringFutureReservesResult", u.Code) + return nil } -var _ decoderFrom = (*BeginSponsoringFutureReservesResult)(nil) +var _ decoderFrom = (*ScSpecTypeMap)(nil) // DecodeFrom decodes this value using the Decoder. -func (u *BeginSponsoringFutureReservesResult) DecodeFrom(d *xdr.Decoder) (int, error) { +func (s *ScSpecTypeMap) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding ScSpecTypeMap: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = u.Code.DecodeFrom(d) + nTmp, err = s.KeyType.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding BeginSponsoringFutureReservesResultCode: %s", err) + return n, fmt.Errorf("decoding ScSpecTypeDef: %w", err) } - switch BeginSponsoringFutureReservesResultCode(u.Code) { - case BeginSponsoringFutureReservesResultCodeBeginSponsoringFutureReservesSuccess: - // Void - return n, nil - case BeginSponsoringFutureReservesResultCodeBeginSponsoringFutureReservesMalformed: - // Void - return n, nil - case BeginSponsoringFutureReservesResultCodeBeginSponsoringFutureReservesAlreadySponsored: - // Void - return n, nil - case BeginSponsoringFutureReservesResultCodeBeginSponsoringFutureReservesRecursive: - // Void - return n, nil + nTmp, err = s.ValueType.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ScSpecTypeDef: %w", err) } - return n, fmt.Errorf("union BeginSponsoringFutureReservesResult has invalid Code (BeginSponsoringFutureReservesResultCode) switch value '%d'", u.Code) + return n, nil } // MarshalBinary implements encoding.BinaryMarshaler. -func (s BeginSponsoringFutureReservesResult) MarshalBinary() ([]byte, error) { +func (s ScSpecTypeMap) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -31742,85 +47580,87 @@ func (s BeginSponsoringFutureReservesResult) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *BeginSponsoringFutureReservesResult) UnmarshalBinary(inp []byte) error { +func (s *ScSpecTypeMap) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*BeginSponsoringFutureReservesResult)(nil) - _ encoding.BinaryUnmarshaler = (*BeginSponsoringFutureReservesResult)(nil) + _ encoding.BinaryMarshaler = (*ScSpecTypeMap)(nil) + _ encoding.BinaryUnmarshaler = (*ScSpecTypeMap)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s BeginSponsoringFutureReservesResult) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s ScSpecTypeMap) xdrType() {} -var _ xdrType = (*BeginSponsoringFutureReservesResult)(nil) +var _ xdrType = (*ScSpecTypeMap)(nil) -// EndSponsoringFutureReservesResultCode is an XDR Enum defines as: +// ScSpecTypeTuple is an XDR Struct defines as: // -// enum EndSponsoringFutureReservesResultCode +// struct SCSpecTypeTuple // { -// // codes considered as "success" for the operation -// END_SPONSORING_FUTURE_RESERVES_SUCCESS = 0, -// -// // codes considered as "failure" for the operation -// END_SPONSORING_FUTURE_RESERVES_NOT_SPONSORED = -1 +// SCSpecTypeDef valueTypes<12>; // }; -type EndSponsoringFutureReservesResultCode int32 - -const ( - EndSponsoringFutureReservesResultCodeEndSponsoringFutureReservesSuccess EndSponsoringFutureReservesResultCode = 0 - EndSponsoringFutureReservesResultCodeEndSponsoringFutureReservesNotSponsored EndSponsoringFutureReservesResultCode = -1 -) - -var endSponsoringFutureReservesResultCodeMap = map[int32]string{ - 0: "EndSponsoringFutureReservesResultCodeEndSponsoringFutureReservesSuccess", - -1: "EndSponsoringFutureReservesResultCodeEndSponsoringFutureReservesNotSponsored", -} - -// ValidEnum validates a proposed value for this enum. Implements -// the Enum interface for EndSponsoringFutureReservesResultCode -func (e EndSponsoringFutureReservesResultCode) ValidEnum(v int32) bool { - _, ok := endSponsoringFutureReservesResultCodeMap[v] - return ok -} - -// String returns the name of `e` -func (e EndSponsoringFutureReservesResultCode) String() string { - name, _ := endSponsoringFutureReservesResultCodeMap[int32(e)] - return name +type ScSpecTypeTuple struct { + ValueTypes []ScSpecTypeDef `xdrmaxsize:"12"` } // EncodeTo encodes this value using the Encoder. -func (e EndSponsoringFutureReservesResultCode) EncodeTo(enc *xdr.Encoder) error { - if _, ok := endSponsoringFutureReservesResultCodeMap[int32(e)]; !ok { - return fmt.Errorf("'%d' is not a valid EndSponsoringFutureReservesResultCode enum value", e) +func (s *ScSpecTypeTuple) EncodeTo(e *xdr.Encoder) error { + var err error + if _, err = e.EncodeUint(uint32(len(s.ValueTypes))); err != nil { + return err } - _, err := enc.EncodeInt(int32(e)) - return err + for i := 0; i < len(s.ValueTypes); i++ { + if err = s.ValueTypes[i].EncodeTo(e); err != nil { + return err + } + } + return nil } -var _ decoderFrom = (*EndSponsoringFutureReservesResultCode)(nil) +var _ decoderFrom = (*ScSpecTypeTuple)(nil) // DecodeFrom decodes this value using the Decoder. -func (e *EndSponsoringFutureReservesResultCode) DecodeFrom(d *xdr.Decoder) (int, error) { - v, n, err := d.DecodeInt() +func (s *ScSpecTypeTuple) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding ScSpecTypeTuple: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + var err error + var n, nTmp int + var l uint32 + l, nTmp, err = d.DecodeUint() + n += nTmp if err != nil { - return n, fmt.Errorf("decoding EndSponsoringFutureReservesResultCode: %s", err) + return n, fmt.Errorf("decoding ScSpecTypeDef: %w", err) } - if _, ok := endSponsoringFutureReservesResultCodeMap[v]; !ok { - return n, fmt.Errorf("'%d' is not a valid EndSponsoringFutureReservesResultCode enum value", v) + if l > 12 { + return n, fmt.Errorf("decoding ScSpecTypeDef: data size (%d) exceeds size limit (12)", l) + } + s.ValueTypes = nil + if l > 0 { + if il, ok := d.InputLen(); ok && uint(il) < uint(l) { + return n, fmt.Errorf("decoding ScSpecTypeDef: length (%d) exceeds remaining input length (%d)", l, il) + } + s.ValueTypes = make([]ScSpecTypeDef, l) + for i := uint32(0); i < l; i++ { + nTmp, err = s.ValueTypes[i].DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ScSpecTypeDef: %w", err) + } + } } - *e = EndSponsoringFutureReservesResultCode(v) return n, nil } // MarshalBinary implements encoding.BinaryMarshaler. -func (s EndSponsoringFutureReservesResultCode) MarshalBinary() ([]byte, error) { +func (s ScSpecTypeTuple) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -31828,109 +47668,64 @@ func (s EndSponsoringFutureReservesResultCode) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *EndSponsoringFutureReservesResultCode) UnmarshalBinary(inp []byte) error { +func (s *ScSpecTypeTuple) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*EndSponsoringFutureReservesResultCode)(nil) - _ encoding.BinaryUnmarshaler = (*EndSponsoringFutureReservesResultCode)(nil) + _ encoding.BinaryMarshaler = (*ScSpecTypeTuple)(nil) + _ encoding.BinaryUnmarshaler = (*ScSpecTypeTuple)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s EndSponsoringFutureReservesResultCode) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s ScSpecTypeTuple) xdrType() {} -var _ xdrType = (*EndSponsoringFutureReservesResultCode)(nil) +var _ xdrType = (*ScSpecTypeTuple)(nil) -// EndSponsoringFutureReservesResult is an XDR Union defines as: +// ScSpecTypeBytesN is an XDR Struct defines as: // -// union EndSponsoringFutureReservesResult switch ( -// EndSponsoringFutureReservesResultCode code) +// struct SCSpecTypeBytesN // { -// case END_SPONSORING_FUTURE_RESERVES_SUCCESS: -// void; -// case END_SPONSORING_FUTURE_RESERVES_NOT_SPONSORED: -// void; +// uint32 n; // }; -type EndSponsoringFutureReservesResult struct { - Code EndSponsoringFutureReservesResultCode -} - -// SwitchFieldName returns the field name in which this union's -// discriminant is stored -func (u EndSponsoringFutureReservesResult) SwitchFieldName() string { - return "Code" -} - -// ArmForSwitch returns which field name should be used for storing -// the value for an instance of EndSponsoringFutureReservesResult -func (u EndSponsoringFutureReservesResult) ArmForSwitch(sw int32) (string, bool) { - switch EndSponsoringFutureReservesResultCode(sw) { - case EndSponsoringFutureReservesResultCodeEndSponsoringFutureReservesSuccess: - return "", true - case EndSponsoringFutureReservesResultCodeEndSponsoringFutureReservesNotSponsored: - return "", true - } - return "-", false -} - -// NewEndSponsoringFutureReservesResult creates a new EndSponsoringFutureReservesResult. -func NewEndSponsoringFutureReservesResult(code EndSponsoringFutureReservesResultCode, value interface{}) (result EndSponsoringFutureReservesResult, err error) { - result.Code = code - switch EndSponsoringFutureReservesResultCode(code) { - case EndSponsoringFutureReservesResultCodeEndSponsoringFutureReservesSuccess: - // void - case EndSponsoringFutureReservesResultCodeEndSponsoringFutureReservesNotSponsored: - // void - } - return +type ScSpecTypeBytesN struct { + N Uint32 } // EncodeTo encodes this value using the Encoder. -func (u EndSponsoringFutureReservesResult) EncodeTo(e *xdr.Encoder) error { +func (s *ScSpecTypeBytesN) EncodeTo(e *xdr.Encoder) error { var err error - if err = u.Code.EncodeTo(e); err != nil { + if err = s.N.EncodeTo(e); err != nil { return err } - switch EndSponsoringFutureReservesResultCode(u.Code) { - case EndSponsoringFutureReservesResultCodeEndSponsoringFutureReservesSuccess: - // Void - return nil - case EndSponsoringFutureReservesResultCodeEndSponsoringFutureReservesNotSponsored: - // Void - return nil - } - return fmt.Errorf("Code (EndSponsoringFutureReservesResultCode) switch value '%d' is not valid for union EndSponsoringFutureReservesResult", u.Code) + return nil } -var _ decoderFrom = (*EndSponsoringFutureReservesResult)(nil) +var _ decoderFrom = (*ScSpecTypeBytesN)(nil) // DecodeFrom decodes this value using the Decoder. -func (u *EndSponsoringFutureReservesResult) DecodeFrom(d *xdr.Decoder) (int, error) { +func (s *ScSpecTypeBytesN) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding ScSpecTypeBytesN: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = u.Code.DecodeFrom(d) + nTmp, err = s.N.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding EndSponsoringFutureReservesResultCode: %s", err) - } - switch EndSponsoringFutureReservesResultCode(u.Code) { - case EndSponsoringFutureReservesResultCodeEndSponsoringFutureReservesSuccess: - // Void - return n, nil - case EndSponsoringFutureReservesResultCodeEndSponsoringFutureReservesNotSponsored: - // Void - return n, nil + return n, fmt.Errorf("decoding Uint32: %w", err) } - return n, fmt.Errorf("union EndSponsoringFutureReservesResult has invalid Code (EndSponsoringFutureReservesResultCode) switch value '%d'", u.Code) + return n, nil } // MarshalBinary implements encoding.BinaryMarshaler. -func (s EndSponsoringFutureReservesResult) MarshalBinary() ([]byte, error) { +func (s ScSpecTypeBytesN) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -31938,97 +47733,64 @@ func (s EndSponsoringFutureReservesResult) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *EndSponsoringFutureReservesResult) UnmarshalBinary(inp []byte) error { +func (s *ScSpecTypeBytesN) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*EndSponsoringFutureReservesResult)(nil) - _ encoding.BinaryUnmarshaler = (*EndSponsoringFutureReservesResult)(nil) + _ encoding.BinaryMarshaler = (*ScSpecTypeBytesN)(nil) + _ encoding.BinaryUnmarshaler = (*ScSpecTypeBytesN)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s EndSponsoringFutureReservesResult) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s ScSpecTypeBytesN) xdrType() {} -var _ xdrType = (*EndSponsoringFutureReservesResult)(nil) +var _ xdrType = (*ScSpecTypeBytesN)(nil) -// RevokeSponsorshipResultCode is an XDR Enum defines as: +// ScSpecTypeUdt is an XDR Struct defines as: // -// enum RevokeSponsorshipResultCode +// struct SCSpecTypeUDT // { -// // codes considered as "success" for the operation -// REVOKE_SPONSORSHIP_SUCCESS = 0, -// -// // codes considered as "failure" for the operation -// REVOKE_SPONSORSHIP_DOES_NOT_EXIST = -1, -// REVOKE_SPONSORSHIP_NOT_SPONSOR = -2, -// REVOKE_SPONSORSHIP_LOW_RESERVE = -3, -// REVOKE_SPONSORSHIP_ONLY_TRANSFERABLE = -4, -// REVOKE_SPONSORSHIP_MALFORMED = -5 +// string name<60>; // }; -type RevokeSponsorshipResultCode int32 - -const ( - RevokeSponsorshipResultCodeRevokeSponsorshipSuccess RevokeSponsorshipResultCode = 0 - RevokeSponsorshipResultCodeRevokeSponsorshipDoesNotExist RevokeSponsorshipResultCode = -1 - RevokeSponsorshipResultCodeRevokeSponsorshipNotSponsor RevokeSponsorshipResultCode = -2 - RevokeSponsorshipResultCodeRevokeSponsorshipLowReserve RevokeSponsorshipResultCode = -3 - RevokeSponsorshipResultCodeRevokeSponsorshipOnlyTransferable RevokeSponsorshipResultCode = -4 - RevokeSponsorshipResultCodeRevokeSponsorshipMalformed RevokeSponsorshipResultCode = -5 -) - -var revokeSponsorshipResultCodeMap = map[int32]string{ - 0: "RevokeSponsorshipResultCodeRevokeSponsorshipSuccess", - -1: "RevokeSponsorshipResultCodeRevokeSponsorshipDoesNotExist", - -2: "RevokeSponsorshipResultCodeRevokeSponsorshipNotSponsor", - -3: "RevokeSponsorshipResultCodeRevokeSponsorshipLowReserve", - -4: "RevokeSponsorshipResultCodeRevokeSponsorshipOnlyTransferable", - -5: "RevokeSponsorshipResultCodeRevokeSponsorshipMalformed", -} - -// ValidEnum validates a proposed value for this enum. Implements -// the Enum interface for RevokeSponsorshipResultCode -func (e RevokeSponsorshipResultCode) ValidEnum(v int32) bool { - _, ok := revokeSponsorshipResultCodeMap[v] - return ok -} - -// String returns the name of `e` -func (e RevokeSponsorshipResultCode) String() string { - name, _ := revokeSponsorshipResultCodeMap[int32(e)] - return name +type ScSpecTypeUdt struct { + Name string `xdrmaxsize:"60"` } // EncodeTo encodes this value using the Encoder. -func (e RevokeSponsorshipResultCode) EncodeTo(enc *xdr.Encoder) error { - if _, ok := revokeSponsorshipResultCodeMap[int32(e)]; !ok { - return fmt.Errorf("'%d' is not a valid RevokeSponsorshipResultCode enum value", e) +func (s *ScSpecTypeUdt) EncodeTo(e *xdr.Encoder) error { + var err error + if _, err = e.EncodeString(string(s.Name)); err != nil { + return err } - _, err := enc.EncodeInt(int32(e)) - return err + return nil } -var _ decoderFrom = (*RevokeSponsorshipResultCode)(nil) +var _ decoderFrom = (*ScSpecTypeUdt)(nil) // DecodeFrom decodes this value using the Decoder. -func (e *RevokeSponsorshipResultCode) DecodeFrom(d *xdr.Decoder) (int, error) { - v, n, err := d.DecodeInt() - if err != nil { - return n, fmt.Errorf("decoding RevokeSponsorshipResultCode: %s", err) +func (s *ScSpecTypeUdt) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding ScSpecTypeUdt: %w", ErrMaxDecodingDepthReached) } - if _, ok := revokeSponsorshipResultCodeMap[v]; !ok { - return n, fmt.Errorf("'%d' is not a valid RevokeSponsorshipResultCode enum value", v) + maxDepth -= 1 + var err error + var n, nTmp int + s.Name, nTmp, err = d.DecodeString(60) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Name: %w", err) } - *e = RevokeSponsorshipResultCode(v) return n, nil } // MarshalBinary implements encoding.BinaryMarshaler. -func (s RevokeSponsorshipResultCode) MarshalBinary() ([]byte, error) { +func (s ScSpecTypeUdt) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -32036,389 +47798,638 @@ func (s RevokeSponsorshipResultCode) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *RevokeSponsorshipResultCode) UnmarshalBinary(inp []byte) error { +func (s *ScSpecTypeUdt) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*RevokeSponsorshipResultCode)(nil) - _ encoding.BinaryUnmarshaler = (*RevokeSponsorshipResultCode)(nil) + _ encoding.BinaryMarshaler = (*ScSpecTypeUdt)(nil) + _ encoding.BinaryUnmarshaler = (*ScSpecTypeUdt)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s RevokeSponsorshipResultCode) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s ScSpecTypeUdt) xdrType() {} -var _ xdrType = (*RevokeSponsorshipResultCode)(nil) +var _ xdrType = (*ScSpecTypeUdt)(nil) -// RevokeSponsorshipResult is an XDR Union defines as: +// ScSpecTypeDef is an XDR Union defines as: // -// union RevokeSponsorshipResult switch (RevokeSponsorshipResultCode code) +// union SCSpecTypeDef switch (SCSpecType type) // { -// case REVOKE_SPONSORSHIP_SUCCESS: -// void; -// case REVOKE_SPONSORSHIP_DOES_NOT_EXIST: -// case REVOKE_SPONSORSHIP_NOT_SPONSOR: -// case REVOKE_SPONSORSHIP_LOW_RESERVE: -// case REVOKE_SPONSORSHIP_ONLY_TRANSFERABLE: -// case REVOKE_SPONSORSHIP_MALFORMED: +// case SC_SPEC_TYPE_VAL: +// case SC_SPEC_TYPE_BOOL: +// case SC_SPEC_TYPE_VOID: +// case SC_SPEC_TYPE_ERROR: +// case SC_SPEC_TYPE_U32: +// case SC_SPEC_TYPE_I32: +// case SC_SPEC_TYPE_U64: +// case SC_SPEC_TYPE_I64: +// case SC_SPEC_TYPE_TIMEPOINT: +// case SC_SPEC_TYPE_DURATION: +// case SC_SPEC_TYPE_U128: +// case SC_SPEC_TYPE_I128: +// case SC_SPEC_TYPE_U256: +// case SC_SPEC_TYPE_I256: +// case SC_SPEC_TYPE_BYTES: +// case SC_SPEC_TYPE_STRING: +// case SC_SPEC_TYPE_SYMBOL: +// case SC_SPEC_TYPE_ADDRESS: // void; +// case SC_SPEC_TYPE_OPTION: +// SCSpecTypeOption option; +// case SC_SPEC_TYPE_RESULT: +// SCSpecTypeResult result; +// case SC_SPEC_TYPE_VEC: +// SCSpecTypeVec vec; +// case SC_SPEC_TYPE_MAP: +// SCSpecTypeMap map; +// case SC_SPEC_TYPE_TUPLE: +// SCSpecTypeTuple tuple; +// case SC_SPEC_TYPE_BYTES_N: +// SCSpecTypeBytesN bytesN; +// case SC_SPEC_TYPE_UDT: +// SCSpecTypeUDT udt; // }; -type RevokeSponsorshipResult struct { - Code RevokeSponsorshipResultCode +type ScSpecTypeDef struct { + Type ScSpecType + Option *ScSpecTypeOption + Result *ScSpecTypeResult + Vec *ScSpecTypeVec + Map *ScSpecTypeMap + Tuple *ScSpecTypeTuple + BytesN *ScSpecTypeBytesN + Udt *ScSpecTypeUdt } // SwitchFieldName returns the field name in which this union's // discriminant is stored -func (u RevokeSponsorshipResult) SwitchFieldName() string { - return "Code" +func (u ScSpecTypeDef) SwitchFieldName() string { + return "Type" } // ArmForSwitch returns which field name should be used for storing -// the value for an instance of RevokeSponsorshipResult -func (u RevokeSponsorshipResult) ArmForSwitch(sw int32) (string, bool) { - switch RevokeSponsorshipResultCode(sw) { - case RevokeSponsorshipResultCodeRevokeSponsorshipSuccess: +// the value for an instance of ScSpecTypeDef +func (u ScSpecTypeDef) ArmForSwitch(sw int32) (string, bool) { + switch ScSpecType(sw) { + case ScSpecTypeScSpecTypeVal: return "", true - case RevokeSponsorshipResultCodeRevokeSponsorshipDoesNotExist: + case ScSpecTypeScSpecTypeBool: return "", true - case RevokeSponsorshipResultCodeRevokeSponsorshipNotSponsor: + case ScSpecTypeScSpecTypeVoid: return "", true - case RevokeSponsorshipResultCodeRevokeSponsorshipLowReserve: + case ScSpecTypeScSpecTypeError: return "", true - case RevokeSponsorshipResultCodeRevokeSponsorshipOnlyTransferable: + case ScSpecTypeScSpecTypeU32: return "", true - case RevokeSponsorshipResultCodeRevokeSponsorshipMalformed: + case ScSpecTypeScSpecTypeI32: + return "", true + case ScSpecTypeScSpecTypeU64: + return "", true + case ScSpecTypeScSpecTypeI64: + return "", true + case ScSpecTypeScSpecTypeTimepoint: + return "", true + case ScSpecTypeScSpecTypeDuration: return "", true + case ScSpecTypeScSpecTypeU128: + return "", true + case ScSpecTypeScSpecTypeI128: + return "", true + case ScSpecTypeScSpecTypeU256: + return "", true + case ScSpecTypeScSpecTypeI256: + return "", true + case ScSpecTypeScSpecTypeBytes: + return "", true + case ScSpecTypeScSpecTypeString: + return "", true + case ScSpecTypeScSpecTypeSymbol: + return "", true + case ScSpecTypeScSpecTypeAddress: + return "", true + case ScSpecTypeScSpecTypeOption: + return "Option", true + case ScSpecTypeScSpecTypeResult: + return "Result", true + case ScSpecTypeScSpecTypeVec: + return "Vec", true + case ScSpecTypeScSpecTypeMap: + return "Map", true + case ScSpecTypeScSpecTypeTuple: + return "Tuple", true + case ScSpecTypeScSpecTypeBytesN: + return "BytesN", true + case ScSpecTypeScSpecTypeUdt: + return "Udt", true } return "-", false } -// NewRevokeSponsorshipResult creates a new RevokeSponsorshipResult. -func NewRevokeSponsorshipResult(code RevokeSponsorshipResultCode, value interface{}) (result RevokeSponsorshipResult, err error) { - result.Code = code - switch RevokeSponsorshipResultCode(code) { - case RevokeSponsorshipResultCodeRevokeSponsorshipSuccess: +// NewScSpecTypeDef creates a new ScSpecTypeDef. +func NewScSpecTypeDef(aType ScSpecType, value interface{}) (result ScSpecTypeDef, err error) { + result.Type = aType + switch ScSpecType(aType) { + case ScSpecTypeScSpecTypeVal: // void - case RevokeSponsorshipResultCodeRevokeSponsorshipDoesNotExist: + case ScSpecTypeScSpecTypeBool: // void - case RevokeSponsorshipResultCodeRevokeSponsorshipNotSponsor: + case ScSpecTypeScSpecTypeVoid: // void - case RevokeSponsorshipResultCodeRevokeSponsorshipLowReserve: + case ScSpecTypeScSpecTypeError: // void - case RevokeSponsorshipResultCodeRevokeSponsorshipOnlyTransferable: + case ScSpecTypeScSpecTypeU32: // void - case RevokeSponsorshipResultCodeRevokeSponsorshipMalformed: + case ScSpecTypeScSpecTypeI32: + // void + case ScSpecTypeScSpecTypeU64: + // void + case ScSpecTypeScSpecTypeI64: + // void + case ScSpecTypeScSpecTypeTimepoint: + // void + case ScSpecTypeScSpecTypeDuration: + // void + case ScSpecTypeScSpecTypeU128: // void + case ScSpecTypeScSpecTypeI128: + // void + case ScSpecTypeScSpecTypeU256: + // void + case ScSpecTypeScSpecTypeI256: + // void + case ScSpecTypeScSpecTypeBytes: + // void + case ScSpecTypeScSpecTypeString: + // void + case ScSpecTypeScSpecTypeSymbol: + // void + case ScSpecTypeScSpecTypeAddress: + // void + case ScSpecTypeScSpecTypeOption: + tv, ok := value.(ScSpecTypeOption) + if !ok { + err = errors.New("invalid value, must be ScSpecTypeOption") + return + } + result.Option = &tv + case ScSpecTypeScSpecTypeResult: + tv, ok := value.(ScSpecTypeResult) + if !ok { + err = errors.New("invalid value, must be ScSpecTypeResult") + return + } + result.Result = &tv + case ScSpecTypeScSpecTypeVec: + tv, ok := value.(ScSpecTypeVec) + if !ok { + err = errors.New("invalid value, must be ScSpecTypeVec") + return + } + result.Vec = &tv + case ScSpecTypeScSpecTypeMap: + tv, ok := value.(ScSpecTypeMap) + if !ok { + err = errors.New("invalid value, must be ScSpecTypeMap") + return + } + result.Map = &tv + case ScSpecTypeScSpecTypeTuple: + tv, ok := value.(ScSpecTypeTuple) + if !ok { + err = errors.New("invalid value, must be ScSpecTypeTuple") + return + } + result.Tuple = &tv + case ScSpecTypeScSpecTypeBytesN: + tv, ok := value.(ScSpecTypeBytesN) + if !ok { + err = errors.New("invalid value, must be ScSpecTypeBytesN") + return + } + result.BytesN = &tv + case ScSpecTypeScSpecTypeUdt: + tv, ok := value.(ScSpecTypeUdt) + if !ok { + err = errors.New("invalid value, must be ScSpecTypeUdt") + return + } + result.Udt = &tv } return } -// EncodeTo encodes this value using the Encoder. -func (u RevokeSponsorshipResult) EncodeTo(e *xdr.Encoder) error { - var err error - if err = u.Code.EncodeTo(e); err != nil { - return err - } - switch RevokeSponsorshipResultCode(u.Code) { - case RevokeSponsorshipResultCodeRevokeSponsorshipSuccess: - // Void - return nil - case RevokeSponsorshipResultCodeRevokeSponsorshipDoesNotExist: - // Void - return nil - case RevokeSponsorshipResultCodeRevokeSponsorshipNotSponsor: - // Void - return nil - case RevokeSponsorshipResultCodeRevokeSponsorshipLowReserve: - // Void - return nil - case RevokeSponsorshipResultCodeRevokeSponsorshipOnlyTransferable: - // Void - return nil - case RevokeSponsorshipResultCodeRevokeSponsorshipMalformed: - // Void - return nil +// MustOption retrieves the Option value from the union, +// panicing if the value is not set. +func (u ScSpecTypeDef) MustOption() ScSpecTypeOption { + val, ok := u.GetOption() + + if !ok { + panic("arm Option is not set") } - return fmt.Errorf("Code (RevokeSponsorshipResultCode) switch value '%d' is not valid for union RevokeSponsorshipResult", u.Code) + + return val } -var _ decoderFrom = (*RevokeSponsorshipResult)(nil) +// GetOption retrieves the Option value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u ScSpecTypeDef) GetOption() (result ScSpecTypeOption, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) -// DecodeFrom decodes this value using the Decoder. -func (u *RevokeSponsorshipResult) DecodeFrom(d *xdr.Decoder) (int, error) { - var err error - var n, nTmp int - nTmp, err = u.Code.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding RevokeSponsorshipResultCode: %s", err) - } - switch RevokeSponsorshipResultCode(u.Code) { - case RevokeSponsorshipResultCodeRevokeSponsorshipSuccess: - // Void - return n, nil - case RevokeSponsorshipResultCodeRevokeSponsorshipDoesNotExist: - // Void - return n, nil - case RevokeSponsorshipResultCodeRevokeSponsorshipNotSponsor: - // Void - return n, nil - case RevokeSponsorshipResultCodeRevokeSponsorshipLowReserve: - // Void - return n, nil - case RevokeSponsorshipResultCodeRevokeSponsorshipOnlyTransferable: - // Void - return n, nil - case RevokeSponsorshipResultCodeRevokeSponsorshipMalformed: - // Void - return n, nil + if armName == "Option" { + result = *u.Option + ok = true } - return n, fmt.Errorf("union RevokeSponsorshipResult has invalid Code (RevokeSponsorshipResultCode) switch value '%d'", u.Code) -} -// MarshalBinary implements encoding.BinaryMarshaler. -func (s RevokeSponsorshipResult) MarshalBinary() ([]byte, error) { - b := bytes.Buffer{} - e := xdr.NewEncoder(&b) - err := s.EncodeTo(e) - return b.Bytes(), err + return } -// UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *RevokeSponsorshipResult) UnmarshalBinary(inp []byte) error { - r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) - return err +// MustResult retrieves the Result value from the union, +// panicing if the value is not set. +func (u ScSpecTypeDef) MustResult() ScSpecTypeResult { + val, ok := u.GetResult() + + if !ok { + panic("arm Result is not set") + } + + return val } -var ( - _ encoding.BinaryMarshaler = (*RevokeSponsorshipResult)(nil) - _ encoding.BinaryUnmarshaler = (*RevokeSponsorshipResult)(nil) -) +// GetResult retrieves the Result value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u ScSpecTypeDef) GetResult() (result ScSpecTypeResult, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s RevokeSponsorshipResult) xdrType() {} + if armName == "Result" { + result = *u.Result + ok = true + } -var _ xdrType = (*RevokeSponsorshipResult)(nil) + return +} -// ClawbackResultCode is an XDR Enum defines as: -// -// enum ClawbackResultCode -// { -// // codes considered as "success" for the operation -// CLAWBACK_SUCCESS = 0, -// -// // codes considered as "failure" for the operation -// CLAWBACK_MALFORMED = -1, -// CLAWBACK_NOT_CLAWBACK_ENABLED = -2, -// CLAWBACK_NO_TRUST = -3, -// CLAWBACK_UNDERFUNDED = -4 -// }; -type ClawbackResultCode int32 +// MustVec retrieves the Vec value from the union, +// panicing if the value is not set. +func (u ScSpecTypeDef) MustVec() ScSpecTypeVec { + val, ok := u.GetVec() -const ( - ClawbackResultCodeClawbackSuccess ClawbackResultCode = 0 - ClawbackResultCodeClawbackMalformed ClawbackResultCode = -1 - ClawbackResultCodeClawbackNotClawbackEnabled ClawbackResultCode = -2 - ClawbackResultCodeClawbackNoTrust ClawbackResultCode = -3 - ClawbackResultCodeClawbackUnderfunded ClawbackResultCode = -4 -) + if !ok { + panic("arm Vec is not set") + } -var clawbackResultCodeMap = map[int32]string{ - 0: "ClawbackResultCodeClawbackSuccess", - -1: "ClawbackResultCodeClawbackMalformed", - -2: "ClawbackResultCodeClawbackNotClawbackEnabled", - -3: "ClawbackResultCodeClawbackNoTrust", - -4: "ClawbackResultCodeClawbackUnderfunded", + return val } -// ValidEnum validates a proposed value for this enum. Implements -// the Enum interface for ClawbackResultCode -func (e ClawbackResultCode) ValidEnum(v int32) bool { - _, ok := clawbackResultCodeMap[v] - return ok -} +// GetVec retrieves the Vec value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u ScSpecTypeDef) GetVec() (result ScSpecTypeVec, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) -// String returns the name of `e` -func (e ClawbackResultCode) String() string { - name, _ := clawbackResultCodeMap[int32(e)] - return name + if armName == "Vec" { + result = *u.Vec + ok = true + } + + return } -// EncodeTo encodes this value using the Encoder. -func (e ClawbackResultCode) EncodeTo(enc *xdr.Encoder) error { - if _, ok := clawbackResultCodeMap[int32(e)]; !ok { - return fmt.Errorf("'%d' is not a valid ClawbackResultCode enum value", e) +// MustMap retrieves the Map value from the union, +// panicing if the value is not set. +func (u ScSpecTypeDef) MustMap() ScSpecTypeMap { + val, ok := u.GetMap() + + if !ok { + panic("arm Map is not set") } - _, err := enc.EncodeInt(int32(e)) - return err + + return val } -var _ decoderFrom = (*ClawbackResultCode)(nil) +// GetMap retrieves the Map value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u ScSpecTypeDef) GetMap() (result ScSpecTypeMap, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) -// DecodeFrom decodes this value using the Decoder. -func (e *ClawbackResultCode) DecodeFrom(d *xdr.Decoder) (int, error) { - v, n, err := d.DecodeInt() - if err != nil { - return n, fmt.Errorf("decoding ClawbackResultCode: %s", err) - } - if _, ok := clawbackResultCodeMap[v]; !ok { - return n, fmt.Errorf("'%d' is not a valid ClawbackResultCode enum value", v) + if armName == "Map" { + result = *u.Map + ok = true } - *e = ClawbackResultCode(v) - return n, nil -} -// MarshalBinary implements encoding.BinaryMarshaler. -func (s ClawbackResultCode) MarshalBinary() ([]byte, error) { - b := bytes.Buffer{} - e := xdr.NewEncoder(&b) - err := s.EncodeTo(e) - return b.Bytes(), err + return } -// UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *ClawbackResultCode) UnmarshalBinary(inp []byte) error { - r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) - return err +// MustTuple retrieves the Tuple value from the union, +// panicing if the value is not set. +func (u ScSpecTypeDef) MustTuple() ScSpecTypeTuple { + val, ok := u.GetTuple() + + if !ok { + panic("arm Tuple is not set") + } + + return val } -var ( - _ encoding.BinaryMarshaler = (*ClawbackResultCode)(nil) - _ encoding.BinaryUnmarshaler = (*ClawbackResultCode)(nil) -) +// GetTuple retrieves the Tuple value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u ScSpecTypeDef) GetTuple() (result ScSpecTypeTuple, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) + + if armName == "Tuple" { + result = *u.Tuple + ok = true + } -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s ClawbackResultCode) xdrType() {} + return +} -var _ xdrType = (*ClawbackResultCode)(nil) +// MustBytesN retrieves the BytesN value from the union, +// panicing if the value is not set. +func (u ScSpecTypeDef) MustBytesN() ScSpecTypeBytesN { + val, ok := u.GetBytesN() -// ClawbackResult is an XDR Union defines as: -// -// union ClawbackResult switch (ClawbackResultCode code) -// { -// case CLAWBACK_SUCCESS: -// void; -// case CLAWBACK_MALFORMED: -// case CLAWBACK_NOT_CLAWBACK_ENABLED: -// case CLAWBACK_NO_TRUST: -// case CLAWBACK_UNDERFUNDED: -// void; -// }; -type ClawbackResult struct { - Code ClawbackResultCode + if !ok { + panic("arm BytesN is not set") + } + + return val } -// SwitchFieldName returns the field name in which this union's -// discriminant is stored -func (u ClawbackResult) SwitchFieldName() string { - return "Code" +// GetBytesN retrieves the BytesN value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u ScSpecTypeDef) GetBytesN() (result ScSpecTypeBytesN, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) + + if armName == "BytesN" { + result = *u.BytesN + ok = true + } + + return } -// ArmForSwitch returns which field name should be used for storing -// the value for an instance of ClawbackResult -func (u ClawbackResult) ArmForSwitch(sw int32) (string, bool) { - switch ClawbackResultCode(sw) { - case ClawbackResultCodeClawbackSuccess: - return "", true - case ClawbackResultCodeClawbackMalformed: - return "", true - case ClawbackResultCodeClawbackNotClawbackEnabled: - return "", true - case ClawbackResultCodeClawbackNoTrust: - return "", true - case ClawbackResultCodeClawbackUnderfunded: - return "", true +// MustUdt retrieves the Udt value from the union, +// panicing if the value is not set. +func (u ScSpecTypeDef) MustUdt() ScSpecTypeUdt { + val, ok := u.GetUdt() + + if !ok { + panic("arm Udt is not set") } - return "-", false + + return val } -// NewClawbackResult creates a new ClawbackResult. -func NewClawbackResult(code ClawbackResultCode, value interface{}) (result ClawbackResult, err error) { - result.Code = code - switch ClawbackResultCode(code) { - case ClawbackResultCodeClawbackSuccess: - // void - case ClawbackResultCodeClawbackMalformed: - // void - case ClawbackResultCodeClawbackNotClawbackEnabled: - // void - case ClawbackResultCodeClawbackNoTrust: - // void - case ClawbackResultCodeClawbackUnderfunded: - // void +// GetUdt retrieves the Udt value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u ScSpecTypeDef) GetUdt() (result ScSpecTypeUdt, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) + + if armName == "Udt" { + result = *u.Udt + ok = true } + return } // EncodeTo encodes this value using the Encoder. -func (u ClawbackResult) EncodeTo(e *xdr.Encoder) error { +func (u ScSpecTypeDef) EncodeTo(e *xdr.Encoder) error { var err error - if err = u.Code.EncodeTo(e); err != nil { + if err = u.Type.EncodeTo(e); err != nil { return err } - switch ClawbackResultCode(u.Code) { - case ClawbackResultCodeClawbackSuccess: + switch ScSpecType(u.Type) { + case ScSpecTypeScSpecTypeVal: // Void return nil - case ClawbackResultCodeClawbackMalformed: + case ScSpecTypeScSpecTypeBool: // Void return nil - case ClawbackResultCodeClawbackNotClawbackEnabled: + case ScSpecTypeScSpecTypeVoid: // Void return nil - case ClawbackResultCodeClawbackNoTrust: + case ScSpecTypeScSpecTypeError: // Void return nil - case ClawbackResultCodeClawbackUnderfunded: + case ScSpecTypeScSpecTypeU32: + // Void + return nil + case ScSpecTypeScSpecTypeI32: + // Void + return nil + case ScSpecTypeScSpecTypeU64: + // Void + return nil + case ScSpecTypeScSpecTypeI64: + // Void + return nil + case ScSpecTypeScSpecTypeTimepoint: + // Void + return nil + case ScSpecTypeScSpecTypeDuration: + // Void + return nil + case ScSpecTypeScSpecTypeU128: + // Void + return nil + case ScSpecTypeScSpecTypeI128: // Void return nil + case ScSpecTypeScSpecTypeU256: + // Void + return nil + case ScSpecTypeScSpecTypeI256: + // Void + return nil + case ScSpecTypeScSpecTypeBytes: + // Void + return nil + case ScSpecTypeScSpecTypeString: + // Void + return nil + case ScSpecTypeScSpecTypeSymbol: + // Void + return nil + case ScSpecTypeScSpecTypeAddress: + // Void + return nil + case ScSpecTypeScSpecTypeOption: + if err = (*u.Option).EncodeTo(e); err != nil { + return err + } + return nil + case ScSpecTypeScSpecTypeResult: + if err = (*u.Result).EncodeTo(e); err != nil { + return err + } + return nil + case ScSpecTypeScSpecTypeVec: + if err = (*u.Vec).EncodeTo(e); err != nil { + return err + } + return nil + case ScSpecTypeScSpecTypeMap: + if err = (*u.Map).EncodeTo(e); err != nil { + return err + } + return nil + case ScSpecTypeScSpecTypeTuple: + if err = (*u.Tuple).EncodeTo(e); err != nil { + return err + } + return nil + case ScSpecTypeScSpecTypeBytesN: + if err = (*u.BytesN).EncodeTo(e); err != nil { + return err + } + return nil + case ScSpecTypeScSpecTypeUdt: + if err = (*u.Udt).EncodeTo(e); err != nil { + return err + } + return nil } - return fmt.Errorf("Code (ClawbackResultCode) switch value '%d' is not valid for union ClawbackResult", u.Code) + return fmt.Errorf("Type (ScSpecType) switch value '%d' is not valid for union ScSpecTypeDef", u.Type) } -var _ decoderFrom = (*ClawbackResult)(nil) +var _ decoderFrom = (*ScSpecTypeDef)(nil) // DecodeFrom decodes this value using the Decoder. -func (u *ClawbackResult) DecodeFrom(d *xdr.Decoder) (int, error) { +func (u *ScSpecTypeDef) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding ScSpecTypeDef: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = u.Code.DecodeFrom(d) + nTmp, err = u.Type.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding ClawbackResultCode: %s", err) + return n, fmt.Errorf("decoding ScSpecType: %w", err) } - switch ClawbackResultCode(u.Code) { - case ClawbackResultCodeClawbackSuccess: + switch ScSpecType(u.Type) { + case ScSpecTypeScSpecTypeVal: // Void return n, nil - case ClawbackResultCodeClawbackMalformed: + case ScSpecTypeScSpecTypeBool: // Void return n, nil - case ClawbackResultCodeClawbackNotClawbackEnabled: + case ScSpecTypeScSpecTypeVoid: // Void return n, nil - case ClawbackResultCodeClawbackNoTrust: + case ScSpecTypeScSpecTypeError: // Void return n, nil - case ClawbackResultCodeClawbackUnderfunded: + case ScSpecTypeScSpecTypeU32: + // Void + return n, nil + case ScSpecTypeScSpecTypeI32: + // Void + return n, nil + case ScSpecTypeScSpecTypeU64: + // Void + return n, nil + case ScSpecTypeScSpecTypeI64: + // Void + return n, nil + case ScSpecTypeScSpecTypeTimepoint: + // Void + return n, nil + case ScSpecTypeScSpecTypeDuration: + // Void + return n, nil + case ScSpecTypeScSpecTypeU128: + // Void + return n, nil + case ScSpecTypeScSpecTypeI128: + // Void + return n, nil + case ScSpecTypeScSpecTypeU256: + // Void + return n, nil + case ScSpecTypeScSpecTypeI256: + // Void + return n, nil + case ScSpecTypeScSpecTypeBytes: + // Void + return n, nil + case ScSpecTypeScSpecTypeString: // Void return n, nil + case ScSpecTypeScSpecTypeSymbol: + // Void + return n, nil + case ScSpecTypeScSpecTypeAddress: + // Void + return n, nil + case ScSpecTypeScSpecTypeOption: + u.Option = new(ScSpecTypeOption) + nTmp, err = (*u.Option).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ScSpecTypeOption: %w", err) + } + return n, nil + case ScSpecTypeScSpecTypeResult: + u.Result = new(ScSpecTypeResult) + nTmp, err = (*u.Result).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ScSpecTypeResult: %w", err) + } + return n, nil + case ScSpecTypeScSpecTypeVec: + u.Vec = new(ScSpecTypeVec) + nTmp, err = (*u.Vec).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ScSpecTypeVec: %w", err) + } + return n, nil + case ScSpecTypeScSpecTypeMap: + u.Map = new(ScSpecTypeMap) + nTmp, err = (*u.Map).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ScSpecTypeMap: %w", err) + } + return n, nil + case ScSpecTypeScSpecTypeTuple: + u.Tuple = new(ScSpecTypeTuple) + nTmp, err = (*u.Tuple).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ScSpecTypeTuple: %w", err) + } + return n, nil + case ScSpecTypeScSpecTypeBytesN: + u.BytesN = new(ScSpecTypeBytesN) + nTmp, err = (*u.BytesN).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ScSpecTypeBytesN: %w", err) + } + return n, nil + case ScSpecTypeScSpecTypeUdt: + u.Udt = new(ScSpecTypeUdt) + nTmp, err = (*u.Udt).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ScSpecTypeUdt: %w", err) + } + return n, nil } - return n, fmt.Errorf("union ClawbackResult has invalid Code (ClawbackResultCode) switch value '%d'", u.Code) + return n, fmt.Errorf("union ScSpecTypeDef has invalid Type (ScSpecType) switch value '%d'", u.Type) } // MarshalBinary implements encoding.BinaryMarshaler. -func (s ClawbackResult) MarshalBinary() ([]byte, error) { +func (s ScSpecTypeDef) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -32426,91 +48437,84 @@ func (s ClawbackResult) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *ClawbackResult) UnmarshalBinary(inp []byte) error { +func (s *ScSpecTypeDef) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*ClawbackResult)(nil) - _ encoding.BinaryUnmarshaler = (*ClawbackResult)(nil) + _ encoding.BinaryMarshaler = (*ScSpecTypeDef)(nil) + _ encoding.BinaryUnmarshaler = (*ScSpecTypeDef)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s ClawbackResult) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s ScSpecTypeDef) xdrType() {} -var _ xdrType = (*ClawbackResult)(nil) +var _ xdrType = (*ScSpecTypeDef)(nil) -// ClawbackClaimableBalanceResultCode is an XDR Enum defines as: +// ScSpecUdtStructFieldV0 is an XDR Struct defines as: // -// enum ClawbackClaimableBalanceResultCode +// struct SCSpecUDTStructFieldV0 // { -// // codes considered as "success" for the operation -// CLAWBACK_CLAIMABLE_BALANCE_SUCCESS = 0, -// -// // codes considered as "failure" for the operation -// CLAWBACK_CLAIMABLE_BALANCE_DOES_NOT_EXIST = -1, -// CLAWBACK_CLAIMABLE_BALANCE_NOT_ISSUER = -2, -// CLAWBACK_CLAIMABLE_BALANCE_NOT_CLAWBACK_ENABLED = -3 +// string doc; +// string name<30>; +// SCSpecTypeDef type; // }; -type ClawbackClaimableBalanceResultCode int32 - -const ( - ClawbackClaimableBalanceResultCodeClawbackClaimableBalanceSuccess ClawbackClaimableBalanceResultCode = 0 - ClawbackClaimableBalanceResultCodeClawbackClaimableBalanceDoesNotExist ClawbackClaimableBalanceResultCode = -1 - ClawbackClaimableBalanceResultCodeClawbackClaimableBalanceNotIssuer ClawbackClaimableBalanceResultCode = -2 - ClawbackClaimableBalanceResultCodeClawbackClaimableBalanceNotClawbackEnabled ClawbackClaimableBalanceResultCode = -3 -) - -var clawbackClaimableBalanceResultCodeMap = map[int32]string{ - 0: "ClawbackClaimableBalanceResultCodeClawbackClaimableBalanceSuccess", - -1: "ClawbackClaimableBalanceResultCodeClawbackClaimableBalanceDoesNotExist", - -2: "ClawbackClaimableBalanceResultCodeClawbackClaimableBalanceNotIssuer", - -3: "ClawbackClaimableBalanceResultCodeClawbackClaimableBalanceNotClawbackEnabled", -} - -// ValidEnum validates a proposed value for this enum. Implements -// the Enum interface for ClawbackClaimableBalanceResultCode -func (e ClawbackClaimableBalanceResultCode) ValidEnum(v int32) bool { - _, ok := clawbackClaimableBalanceResultCodeMap[v] - return ok -} - -// String returns the name of `e` -func (e ClawbackClaimableBalanceResultCode) String() string { - name, _ := clawbackClaimableBalanceResultCodeMap[int32(e)] - return name +type ScSpecUdtStructFieldV0 struct { + Doc string `xdrmaxsize:"1024"` + Name string `xdrmaxsize:"30"` + Type ScSpecTypeDef } // EncodeTo encodes this value using the Encoder. -func (e ClawbackClaimableBalanceResultCode) EncodeTo(enc *xdr.Encoder) error { - if _, ok := clawbackClaimableBalanceResultCodeMap[int32(e)]; !ok { - return fmt.Errorf("'%d' is not a valid ClawbackClaimableBalanceResultCode enum value", e) +func (s *ScSpecUdtStructFieldV0) EncodeTo(e *xdr.Encoder) error { + var err error + if _, err = e.EncodeString(string(s.Doc)); err != nil { + return err } - _, err := enc.EncodeInt(int32(e)) - return err + if _, err = e.EncodeString(string(s.Name)); err != nil { + return err + } + if err = s.Type.EncodeTo(e); err != nil { + return err + } + return nil } -var _ decoderFrom = (*ClawbackClaimableBalanceResultCode)(nil) +var _ decoderFrom = (*ScSpecUdtStructFieldV0)(nil) // DecodeFrom decodes this value using the Decoder. -func (e *ClawbackClaimableBalanceResultCode) DecodeFrom(d *xdr.Decoder) (int, error) { - v, n, err := d.DecodeInt() +func (s *ScSpecUdtStructFieldV0) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding ScSpecUdtStructFieldV0: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + var err error + var n, nTmp int + s.Doc, nTmp, err = d.DecodeString(1024) + n += nTmp if err != nil { - return n, fmt.Errorf("decoding ClawbackClaimableBalanceResultCode: %s", err) + return n, fmt.Errorf("decoding Doc: %w", err) } - if _, ok := clawbackClaimableBalanceResultCodeMap[v]; !ok { - return n, fmt.Errorf("'%d' is not a valid ClawbackClaimableBalanceResultCode enum value", v) + s.Name, nTmp, err = d.DecodeString(30) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Name: %w", err) + } + nTmp, err = s.Type.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ScSpecTypeDef: %w", err) } - *e = ClawbackClaimableBalanceResultCode(v) return n, nil } // MarshalBinary implements encoding.BinaryMarshaler. -func (s ClawbackClaimableBalanceResultCode) MarshalBinary() ([]byte, error) { +func (s ScSpecUdtStructFieldV0) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -32518,131 +48522,117 @@ func (s ClawbackClaimableBalanceResultCode) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *ClawbackClaimableBalanceResultCode) UnmarshalBinary(inp []byte) error { +func (s *ScSpecUdtStructFieldV0) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*ClawbackClaimableBalanceResultCode)(nil) - _ encoding.BinaryUnmarshaler = (*ClawbackClaimableBalanceResultCode)(nil) + _ encoding.BinaryMarshaler = (*ScSpecUdtStructFieldV0)(nil) + _ encoding.BinaryUnmarshaler = (*ScSpecUdtStructFieldV0)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s ClawbackClaimableBalanceResultCode) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s ScSpecUdtStructFieldV0) xdrType() {} -var _ xdrType = (*ClawbackClaimableBalanceResultCode)(nil) +var _ xdrType = (*ScSpecUdtStructFieldV0)(nil) -// ClawbackClaimableBalanceResult is an XDR Union defines as: +// ScSpecUdtStructV0 is an XDR Struct defines as: // -// union ClawbackClaimableBalanceResult switch ( -// ClawbackClaimableBalanceResultCode code) +// struct SCSpecUDTStructV0 // { -// case CLAWBACK_CLAIMABLE_BALANCE_SUCCESS: -// void; -// case CLAWBACK_CLAIMABLE_BALANCE_DOES_NOT_EXIST: -// case CLAWBACK_CLAIMABLE_BALANCE_NOT_ISSUER: -// case CLAWBACK_CLAIMABLE_BALANCE_NOT_CLAWBACK_ENABLED: -// void; +// string doc; +// string lib<80>; +// string name<60>; +// SCSpecUDTStructFieldV0 fields<40>; // }; -type ClawbackClaimableBalanceResult struct { - Code ClawbackClaimableBalanceResultCode -} - -// SwitchFieldName returns the field name in which this union's -// discriminant is stored -func (u ClawbackClaimableBalanceResult) SwitchFieldName() string { - return "Code" -} - -// ArmForSwitch returns which field name should be used for storing -// the value for an instance of ClawbackClaimableBalanceResult -func (u ClawbackClaimableBalanceResult) ArmForSwitch(sw int32) (string, bool) { - switch ClawbackClaimableBalanceResultCode(sw) { - case ClawbackClaimableBalanceResultCodeClawbackClaimableBalanceSuccess: - return "", true - case ClawbackClaimableBalanceResultCodeClawbackClaimableBalanceDoesNotExist: - return "", true - case ClawbackClaimableBalanceResultCodeClawbackClaimableBalanceNotIssuer: - return "", true - case ClawbackClaimableBalanceResultCodeClawbackClaimableBalanceNotClawbackEnabled: - return "", true - } - return "-", false -} - -// NewClawbackClaimableBalanceResult creates a new ClawbackClaimableBalanceResult. -func NewClawbackClaimableBalanceResult(code ClawbackClaimableBalanceResultCode, value interface{}) (result ClawbackClaimableBalanceResult, err error) { - result.Code = code - switch ClawbackClaimableBalanceResultCode(code) { - case ClawbackClaimableBalanceResultCodeClawbackClaimableBalanceSuccess: - // void - case ClawbackClaimableBalanceResultCodeClawbackClaimableBalanceDoesNotExist: - // void - case ClawbackClaimableBalanceResultCodeClawbackClaimableBalanceNotIssuer: - // void - case ClawbackClaimableBalanceResultCodeClawbackClaimableBalanceNotClawbackEnabled: - // void - } - return +type ScSpecUdtStructV0 struct { + Doc string `xdrmaxsize:"1024"` + Lib string `xdrmaxsize:"80"` + Name string `xdrmaxsize:"60"` + Fields []ScSpecUdtStructFieldV0 `xdrmaxsize:"40"` } // EncodeTo encodes this value using the Encoder. -func (u ClawbackClaimableBalanceResult) EncodeTo(e *xdr.Encoder) error { +func (s *ScSpecUdtStructV0) EncodeTo(e *xdr.Encoder) error { var err error - if err = u.Code.EncodeTo(e); err != nil { + if _, err = e.EncodeString(string(s.Doc)); err != nil { return err } - switch ClawbackClaimableBalanceResultCode(u.Code) { - case ClawbackClaimableBalanceResultCodeClawbackClaimableBalanceSuccess: - // Void - return nil - case ClawbackClaimableBalanceResultCodeClawbackClaimableBalanceDoesNotExist: - // Void - return nil - case ClawbackClaimableBalanceResultCodeClawbackClaimableBalanceNotIssuer: - // Void - return nil - case ClawbackClaimableBalanceResultCodeClawbackClaimableBalanceNotClawbackEnabled: - // Void - return nil + if _, err = e.EncodeString(string(s.Lib)); err != nil { + return err } - return fmt.Errorf("Code (ClawbackClaimableBalanceResultCode) switch value '%d' is not valid for union ClawbackClaimableBalanceResult", u.Code) + if _, err = e.EncodeString(string(s.Name)); err != nil { + return err + } + if _, err = e.EncodeUint(uint32(len(s.Fields))); err != nil { + return err + } + for i := 0; i < len(s.Fields); i++ { + if err = s.Fields[i].EncodeTo(e); err != nil { + return err + } + } + return nil } -var _ decoderFrom = (*ClawbackClaimableBalanceResult)(nil) +var _ decoderFrom = (*ScSpecUdtStructV0)(nil) // DecodeFrom decodes this value using the Decoder. -func (u *ClawbackClaimableBalanceResult) DecodeFrom(d *xdr.Decoder) (int, error) { +func (s *ScSpecUdtStructV0) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding ScSpecUdtStructV0: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = u.Code.DecodeFrom(d) + s.Doc, nTmp, err = d.DecodeString(1024) n += nTmp if err != nil { - return n, fmt.Errorf("decoding ClawbackClaimableBalanceResultCode: %s", err) + return n, fmt.Errorf("decoding Doc: %w", err) } - switch ClawbackClaimableBalanceResultCode(u.Code) { - case ClawbackClaimableBalanceResultCodeClawbackClaimableBalanceSuccess: - // Void - return n, nil - case ClawbackClaimableBalanceResultCodeClawbackClaimableBalanceDoesNotExist: - // Void - return n, nil - case ClawbackClaimableBalanceResultCodeClawbackClaimableBalanceNotIssuer: - // Void - return n, nil - case ClawbackClaimableBalanceResultCodeClawbackClaimableBalanceNotClawbackEnabled: - // Void - return n, nil + s.Lib, nTmp, err = d.DecodeString(80) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Lib: %w", err) } - return n, fmt.Errorf("union ClawbackClaimableBalanceResult has invalid Code (ClawbackClaimableBalanceResultCode) switch value '%d'", u.Code) + s.Name, nTmp, err = d.DecodeString(60) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Name: %w", err) + } + var l uint32 + l, nTmp, err = d.DecodeUint() + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ScSpecUdtStructFieldV0: %w", err) + } + if l > 40 { + return n, fmt.Errorf("decoding ScSpecUdtStructFieldV0: data size (%d) exceeds size limit (40)", l) + } + s.Fields = nil + if l > 0 { + if il, ok := d.InputLen(); ok && uint(il) < uint(l) { + return n, fmt.Errorf("decoding ScSpecUdtStructFieldV0: length (%d) exceeds remaining input length (%d)", l, il) + } + s.Fields = make([]ScSpecUdtStructFieldV0, l) + for i := uint32(0); i < l; i++ { + nTmp, err = s.Fields[i].DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ScSpecUdtStructFieldV0: %w", err) + } + } + } + return n, nil } // MarshalBinary implements encoding.BinaryMarshaler. -func (s ClawbackClaimableBalanceResult) MarshalBinary() ([]byte, error) { +func (s ScSpecUdtStructV0) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -32650,251 +48640,182 @@ func (s ClawbackClaimableBalanceResult) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *ClawbackClaimableBalanceResult) UnmarshalBinary(inp []byte) error { +func (s *ScSpecUdtStructV0) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*ClawbackClaimableBalanceResult)(nil) - _ encoding.BinaryUnmarshaler = (*ClawbackClaimableBalanceResult)(nil) + _ encoding.BinaryMarshaler = (*ScSpecUdtStructV0)(nil) + _ encoding.BinaryUnmarshaler = (*ScSpecUdtStructV0)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s ClawbackClaimableBalanceResult) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s ScSpecUdtStructV0) xdrType() {} -var _ xdrType = (*ClawbackClaimableBalanceResult)(nil) +var _ xdrType = (*ScSpecUdtStructV0)(nil) -// SetTrustLineFlagsResultCode is an XDR Enum defines as: +// ScSpecUdtUnionCaseVoidV0 is an XDR Struct defines as: // -// enum SetTrustLineFlagsResultCode +// struct SCSpecUDTUnionCaseVoidV0 // { -// // codes considered as "success" for the operation -// SET_TRUST_LINE_FLAGS_SUCCESS = 0, -// -// // codes considered as "failure" for the operation -// SET_TRUST_LINE_FLAGS_MALFORMED = -1, -// SET_TRUST_LINE_FLAGS_NO_TRUST_LINE = -2, -// SET_TRUST_LINE_FLAGS_CANT_REVOKE = -3, -// SET_TRUST_LINE_FLAGS_INVALID_STATE = -4, -// SET_TRUST_LINE_FLAGS_LOW_RESERVE = -5 // claimable balances can't be created -// // on revoke due to low reserves +// string doc; +// string name<60>; // }; -type SetTrustLineFlagsResultCode int32 - -const ( - SetTrustLineFlagsResultCodeSetTrustLineFlagsSuccess SetTrustLineFlagsResultCode = 0 - SetTrustLineFlagsResultCodeSetTrustLineFlagsMalformed SetTrustLineFlagsResultCode = -1 - SetTrustLineFlagsResultCodeSetTrustLineFlagsNoTrustLine SetTrustLineFlagsResultCode = -2 - SetTrustLineFlagsResultCodeSetTrustLineFlagsCantRevoke SetTrustLineFlagsResultCode = -3 - SetTrustLineFlagsResultCodeSetTrustLineFlagsInvalidState SetTrustLineFlagsResultCode = -4 - SetTrustLineFlagsResultCodeSetTrustLineFlagsLowReserve SetTrustLineFlagsResultCode = -5 -) - -var setTrustLineFlagsResultCodeMap = map[int32]string{ - 0: "SetTrustLineFlagsResultCodeSetTrustLineFlagsSuccess", - -1: "SetTrustLineFlagsResultCodeSetTrustLineFlagsMalformed", - -2: "SetTrustLineFlagsResultCodeSetTrustLineFlagsNoTrustLine", - -3: "SetTrustLineFlagsResultCodeSetTrustLineFlagsCantRevoke", - -4: "SetTrustLineFlagsResultCodeSetTrustLineFlagsInvalidState", - -5: "SetTrustLineFlagsResultCodeSetTrustLineFlagsLowReserve", -} - -// ValidEnum validates a proposed value for this enum. Implements -// the Enum interface for SetTrustLineFlagsResultCode -func (e SetTrustLineFlagsResultCode) ValidEnum(v int32) bool { - _, ok := setTrustLineFlagsResultCodeMap[v] - return ok -} - -// String returns the name of `e` -func (e SetTrustLineFlagsResultCode) String() string { - name, _ := setTrustLineFlagsResultCodeMap[int32(e)] - return name +type ScSpecUdtUnionCaseVoidV0 struct { + Doc string `xdrmaxsize:"1024"` + Name string `xdrmaxsize:"60"` } // EncodeTo encodes this value using the Encoder. -func (e SetTrustLineFlagsResultCode) EncodeTo(enc *xdr.Encoder) error { - if _, ok := setTrustLineFlagsResultCodeMap[int32(e)]; !ok { - return fmt.Errorf("'%d' is not a valid SetTrustLineFlagsResultCode enum value", e) +func (s *ScSpecUdtUnionCaseVoidV0) EncodeTo(e *xdr.Encoder) error { + var err error + if _, err = e.EncodeString(string(s.Doc)); err != nil { + return err } - _, err := enc.EncodeInt(int32(e)) - return err + if _, err = e.EncodeString(string(s.Name)); err != nil { + return err + } + return nil } -var _ decoderFrom = (*SetTrustLineFlagsResultCode)(nil) +var _ decoderFrom = (*ScSpecUdtUnionCaseVoidV0)(nil) // DecodeFrom decodes this value using the Decoder. -func (e *SetTrustLineFlagsResultCode) DecodeFrom(d *xdr.Decoder) (int, error) { - v, n, err := d.DecodeInt() +func (s *ScSpecUdtUnionCaseVoidV0) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding ScSpecUdtUnionCaseVoidV0: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + var err error + var n, nTmp int + s.Doc, nTmp, err = d.DecodeString(1024) + n += nTmp if err != nil { - return n, fmt.Errorf("decoding SetTrustLineFlagsResultCode: %s", err) + return n, fmt.Errorf("decoding Doc: %w", err) } - if _, ok := setTrustLineFlagsResultCodeMap[v]; !ok { - return n, fmt.Errorf("'%d' is not a valid SetTrustLineFlagsResultCode enum value", v) + s.Name, nTmp, err = d.DecodeString(60) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Name: %w", err) } - *e = SetTrustLineFlagsResultCode(v) return n, nil } -// MarshalBinary implements encoding.BinaryMarshaler. -func (s SetTrustLineFlagsResultCode) MarshalBinary() ([]byte, error) { - b := bytes.Buffer{} - e := xdr.NewEncoder(&b) - err := s.EncodeTo(e) - return b.Bytes(), err -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *SetTrustLineFlagsResultCode) UnmarshalBinary(inp []byte) error { - r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) - return err -} - -var ( - _ encoding.BinaryMarshaler = (*SetTrustLineFlagsResultCode)(nil) - _ encoding.BinaryUnmarshaler = (*SetTrustLineFlagsResultCode)(nil) -) - -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s SetTrustLineFlagsResultCode) xdrType() {} - -var _ xdrType = (*SetTrustLineFlagsResultCode)(nil) - -// SetTrustLineFlagsResult is an XDR Union defines as: -// -// union SetTrustLineFlagsResult switch (SetTrustLineFlagsResultCode code) -// { -// case SET_TRUST_LINE_FLAGS_SUCCESS: -// void; -// case SET_TRUST_LINE_FLAGS_MALFORMED: -// case SET_TRUST_LINE_FLAGS_NO_TRUST_LINE: -// case SET_TRUST_LINE_FLAGS_CANT_REVOKE: -// case SET_TRUST_LINE_FLAGS_INVALID_STATE: -// case SET_TRUST_LINE_FLAGS_LOW_RESERVE: -// void; -// }; -type SetTrustLineFlagsResult struct { - Code SetTrustLineFlagsResultCode -} - -// SwitchFieldName returns the field name in which this union's -// discriminant is stored -func (u SetTrustLineFlagsResult) SwitchFieldName() string { - return "Code" -} - -// ArmForSwitch returns which field name should be used for storing -// the value for an instance of SetTrustLineFlagsResult -func (u SetTrustLineFlagsResult) ArmForSwitch(sw int32) (string, bool) { - switch SetTrustLineFlagsResultCode(sw) { - case SetTrustLineFlagsResultCodeSetTrustLineFlagsSuccess: - return "", true - case SetTrustLineFlagsResultCodeSetTrustLineFlagsMalformed: - return "", true - case SetTrustLineFlagsResultCodeSetTrustLineFlagsNoTrustLine: - return "", true - case SetTrustLineFlagsResultCodeSetTrustLineFlagsCantRevoke: - return "", true - case SetTrustLineFlagsResultCodeSetTrustLineFlagsInvalidState: - return "", true - case SetTrustLineFlagsResultCodeSetTrustLineFlagsLowReserve: - return "", true - } - return "-", false +// MarshalBinary implements encoding.BinaryMarshaler. +func (s ScSpecUdtUnionCaseVoidV0) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err } -// NewSetTrustLineFlagsResult creates a new SetTrustLineFlagsResult. -func NewSetTrustLineFlagsResult(code SetTrustLineFlagsResultCode, value interface{}) (result SetTrustLineFlagsResult, err error) { - result.Code = code - switch SetTrustLineFlagsResultCode(code) { - case SetTrustLineFlagsResultCodeSetTrustLineFlagsSuccess: - // void - case SetTrustLineFlagsResultCodeSetTrustLineFlagsMalformed: - // void - case SetTrustLineFlagsResultCodeSetTrustLineFlagsNoTrustLine: - // void - case SetTrustLineFlagsResultCodeSetTrustLineFlagsCantRevoke: - // void - case SetTrustLineFlagsResultCodeSetTrustLineFlagsInvalidState: - // void - case SetTrustLineFlagsResultCodeSetTrustLineFlagsLowReserve: - // void - } - return +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *ScSpecUdtUnionCaseVoidV0) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} + +var ( + _ encoding.BinaryMarshaler = (*ScSpecUdtUnionCaseVoidV0)(nil) + _ encoding.BinaryUnmarshaler = (*ScSpecUdtUnionCaseVoidV0)(nil) +) + +// xdrType signals that this type represents XDR values defined by this package. +func (s ScSpecUdtUnionCaseVoidV0) xdrType() {} + +var _ xdrType = (*ScSpecUdtUnionCaseVoidV0)(nil) + +// ScSpecUdtUnionCaseTupleV0 is an XDR Struct defines as: +// +// struct SCSpecUDTUnionCaseTupleV0 +// { +// string doc; +// string name<60>; +// SCSpecTypeDef type<12>; +// }; +type ScSpecUdtUnionCaseTupleV0 struct { + Doc string `xdrmaxsize:"1024"` + Name string `xdrmaxsize:"60"` + Type []ScSpecTypeDef `xdrmaxsize:"12"` } // EncodeTo encodes this value using the Encoder. -func (u SetTrustLineFlagsResult) EncodeTo(e *xdr.Encoder) error { +func (s *ScSpecUdtUnionCaseTupleV0) EncodeTo(e *xdr.Encoder) error { var err error - if err = u.Code.EncodeTo(e); err != nil { + if _, err = e.EncodeString(string(s.Doc)); err != nil { return err } - switch SetTrustLineFlagsResultCode(u.Code) { - case SetTrustLineFlagsResultCodeSetTrustLineFlagsSuccess: - // Void - return nil - case SetTrustLineFlagsResultCodeSetTrustLineFlagsMalformed: - // Void - return nil - case SetTrustLineFlagsResultCodeSetTrustLineFlagsNoTrustLine: - // Void - return nil - case SetTrustLineFlagsResultCodeSetTrustLineFlagsCantRevoke: - // Void - return nil - case SetTrustLineFlagsResultCodeSetTrustLineFlagsInvalidState: - // Void - return nil - case SetTrustLineFlagsResultCodeSetTrustLineFlagsLowReserve: - // Void - return nil + if _, err = e.EncodeString(string(s.Name)); err != nil { + return err } - return fmt.Errorf("Code (SetTrustLineFlagsResultCode) switch value '%d' is not valid for union SetTrustLineFlagsResult", u.Code) + if _, err = e.EncodeUint(uint32(len(s.Type))); err != nil { + return err + } + for i := 0; i < len(s.Type); i++ { + if err = s.Type[i].EncodeTo(e); err != nil { + return err + } + } + return nil } -var _ decoderFrom = (*SetTrustLineFlagsResult)(nil) +var _ decoderFrom = (*ScSpecUdtUnionCaseTupleV0)(nil) // DecodeFrom decodes this value using the Decoder. -func (u *SetTrustLineFlagsResult) DecodeFrom(d *xdr.Decoder) (int, error) { +func (s *ScSpecUdtUnionCaseTupleV0) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding ScSpecUdtUnionCaseTupleV0: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = u.Code.DecodeFrom(d) + s.Doc, nTmp, err = d.DecodeString(1024) n += nTmp if err != nil { - return n, fmt.Errorf("decoding SetTrustLineFlagsResultCode: %s", err) + return n, fmt.Errorf("decoding Doc: %w", err) } - switch SetTrustLineFlagsResultCode(u.Code) { - case SetTrustLineFlagsResultCodeSetTrustLineFlagsSuccess: - // Void - return n, nil - case SetTrustLineFlagsResultCodeSetTrustLineFlagsMalformed: - // Void - return n, nil - case SetTrustLineFlagsResultCodeSetTrustLineFlagsNoTrustLine: - // Void - return n, nil - case SetTrustLineFlagsResultCodeSetTrustLineFlagsCantRevoke: - // Void - return n, nil - case SetTrustLineFlagsResultCodeSetTrustLineFlagsInvalidState: - // Void - return n, nil - case SetTrustLineFlagsResultCodeSetTrustLineFlagsLowReserve: - // Void - return n, nil + s.Name, nTmp, err = d.DecodeString(60) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Name: %w", err) } - return n, fmt.Errorf("union SetTrustLineFlagsResult has invalid Code (SetTrustLineFlagsResultCode) switch value '%d'", u.Code) + var l uint32 + l, nTmp, err = d.DecodeUint() + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ScSpecTypeDef: %w", err) + } + if l > 12 { + return n, fmt.Errorf("decoding ScSpecTypeDef: data size (%d) exceeds size limit (12)", l) + } + s.Type = nil + if l > 0 { + if il, ok := d.InputLen(); ok && uint(il) < uint(l) { + return n, fmt.Errorf("decoding ScSpecTypeDef: length (%d) exceeds remaining input length (%d)", l, il) + } + s.Type = make([]ScSpecTypeDef, l) + for i := uint32(0); i < l; i++ { + nTmp, err = s.Type[i].DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ScSpecTypeDef: %w", err) + } + } + } + return n, nil } // MarshalBinary implements encoding.BinaryMarshaler. -func (s SetTrustLineFlagsResult) MarshalBinary() ([]byte, error) { +func (s ScSpecUdtUnionCaseTupleV0) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -32902,107 +48823,87 @@ func (s SetTrustLineFlagsResult) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *SetTrustLineFlagsResult) UnmarshalBinary(inp []byte) error { +func (s *ScSpecUdtUnionCaseTupleV0) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*SetTrustLineFlagsResult)(nil) - _ encoding.BinaryUnmarshaler = (*SetTrustLineFlagsResult)(nil) + _ encoding.BinaryMarshaler = (*ScSpecUdtUnionCaseTupleV0)(nil) + _ encoding.BinaryUnmarshaler = (*ScSpecUdtUnionCaseTupleV0)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s SetTrustLineFlagsResult) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s ScSpecUdtUnionCaseTupleV0) xdrType() {} -var _ xdrType = (*SetTrustLineFlagsResult)(nil) +var _ xdrType = (*ScSpecUdtUnionCaseTupleV0)(nil) -// LiquidityPoolDepositResultCode is an XDR Enum defines as: +// ScSpecUdtUnionCaseV0Kind is an XDR Enum defines as: // -// enum LiquidityPoolDepositResultCode +// enum SCSpecUDTUnionCaseV0Kind // { -// // codes considered as "success" for the operation -// LIQUIDITY_POOL_DEPOSIT_SUCCESS = 0, -// -// // codes considered as "failure" for the operation -// LIQUIDITY_POOL_DEPOSIT_MALFORMED = -1, // bad input -// LIQUIDITY_POOL_DEPOSIT_NO_TRUST = -2, // no trust line for one of the -// // assets -// LIQUIDITY_POOL_DEPOSIT_NOT_AUTHORIZED = -3, // not authorized for one of the -// // assets -// LIQUIDITY_POOL_DEPOSIT_UNDERFUNDED = -4, // not enough balance for one of -// // the assets -// LIQUIDITY_POOL_DEPOSIT_LINE_FULL = -5, // pool share trust line doesn't -// // have sufficient limit -// LIQUIDITY_POOL_DEPOSIT_BAD_PRICE = -6, // deposit price outside bounds -// LIQUIDITY_POOL_DEPOSIT_POOL_FULL = -7 // pool reserves are full +// SC_SPEC_UDT_UNION_CASE_VOID_V0 = 0, +// SC_SPEC_UDT_UNION_CASE_TUPLE_V0 = 1 // }; -type LiquidityPoolDepositResultCode int32 +type ScSpecUdtUnionCaseV0Kind int32 const ( - LiquidityPoolDepositResultCodeLiquidityPoolDepositSuccess LiquidityPoolDepositResultCode = 0 - LiquidityPoolDepositResultCodeLiquidityPoolDepositMalformed LiquidityPoolDepositResultCode = -1 - LiquidityPoolDepositResultCodeLiquidityPoolDepositNoTrust LiquidityPoolDepositResultCode = -2 - LiquidityPoolDepositResultCodeLiquidityPoolDepositNotAuthorized LiquidityPoolDepositResultCode = -3 - LiquidityPoolDepositResultCodeLiquidityPoolDepositUnderfunded LiquidityPoolDepositResultCode = -4 - LiquidityPoolDepositResultCodeLiquidityPoolDepositLineFull LiquidityPoolDepositResultCode = -5 - LiquidityPoolDepositResultCodeLiquidityPoolDepositBadPrice LiquidityPoolDepositResultCode = -6 - LiquidityPoolDepositResultCodeLiquidityPoolDepositPoolFull LiquidityPoolDepositResultCode = -7 + ScSpecUdtUnionCaseV0KindScSpecUdtUnionCaseVoidV0 ScSpecUdtUnionCaseV0Kind = 0 + ScSpecUdtUnionCaseV0KindScSpecUdtUnionCaseTupleV0 ScSpecUdtUnionCaseV0Kind = 1 ) -var liquidityPoolDepositResultCodeMap = map[int32]string{ - 0: "LiquidityPoolDepositResultCodeLiquidityPoolDepositSuccess", - -1: "LiquidityPoolDepositResultCodeLiquidityPoolDepositMalformed", - -2: "LiquidityPoolDepositResultCodeLiquidityPoolDepositNoTrust", - -3: "LiquidityPoolDepositResultCodeLiquidityPoolDepositNotAuthorized", - -4: "LiquidityPoolDepositResultCodeLiquidityPoolDepositUnderfunded", - -5: "LiquidityPoolDepositResultCodeLiquidityPoolDepositLineFull", - -6: "LiquidityPoolDepositResultCodeLiquidityPoolDepositBadPrice", - -7: "LiquidityPoolDepositResultCodeLiquidityPoolDepositPoolFull", +var scSpecUdtUnionCaseV0KindMap = map[int32]string{ + 0: "ScSpecUdtUnionCaseV0KindScSpecUdtUnionCaseVoidV0", + 1: "ScSpecUdtUnionCaseV0KindScSpecUdtUnionCaseTupleV0", } // ValidEnum validates a proposed value for this enum. Implements -// the Enum interface for LiquidityPoolDepositResultCode -func (e LiquidityPoolDepositResultCode) ValidEnum(v int32) bool { - _, ok := liquidityPoolDepositResultCodeMap[v] +// the Enum interface for ScSpecUdtUnionCaseV0Kind +func (e ScSpecUdtUnionCaseV0Kind) ValidEnum(v int32) bool { + _, ok := scSpecUdtUnionCaseV0KindMap[v] return ok } // String returns the name of `e` -func (e LiquidityPoolDepositResultCode) String() string { - name, _ := liquidityPoolDepositResultCodeMap[int32(e)] +func (e ScSpecUdtUnionCaseV0Kind) String() string { + name, _ := scSpecUdtUnionCaseV0KindMap[int32(e)] return name } // EncodeTo encodes this value using the Encoder. -func (e LiquidityPoolDepositResultCode) EncodeTo(enc *xdr.Encoder) error { - if _, ok := liquidityPoolDepositResultCodeMap[int32(e)]; !ok { - return fmt.Errorf("'%d' is not a valid LiquidityPoolDepositResultCode enum value", e) +func (e ScSpecUdtUnionCaseV0Kind) EncodeTo(enc *xdr.Encoder) error { + if _, ok := scSpecUdtUnionCaseV0KindMap[int32(e)]; !ok { + return fmt.Errorf("'%d' is not a valid ScSpecUdtUnionCaseV0Kind enum value", e) } _, err := enc.EncodeInt(int32(e)) return err } -var _ decoderFrom = (*LiquidityPoolDepositResultCode)(nil) +var _ decoderFrom = (*ScSpecUdtUnionCaseV0Kind)(nil) // DecodeFrom decodes this value using the Decoder. -func (e *LiquidityPoolDepositResultCode) DecodeFrom(d *xdr.Decoder) (int, error) { +func (e *ScSpecUdtUnionCaseV0Kind) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding ScSpecUdtUnionCaseV0Kind: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 v, n, err := d.DecodeInt() if err != nil { - return n, fmt.Errorf("decoding LiquidityPoolDepositResultCode: %s", err) + return n, fmt.Errorf("decoding ScSpecUdtUnionCaseV0Kind: %w", err) } - if _, ok := liquidityPoolDepositResultCodeMap[v]; !ok { - return n, fmt.Errorf("'%d' is not a valid LiquidityPoolDepositResultCode enum value", v) + if _, ok := scSpecUdtUnionCaseV0KindMap[v]; !ok { + return n, fmt.Errorf("'%d' is not a valid ScSpecUdtUnionCaseV0Kind enum value", v) } - *e = LiquidityPoolDepositResultCode(v) + *e = ScSpecUdtUnionCaseV0Kind(v) return n, nil } // MarshalBinary implements encoding.BinaryMarshaler. -func (s LiquidityPoolDepositResultCode) MarshalBinary() ([]byte, error) { +func (s ScSpecUdtUnionCaseV0Kind) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -33010,174 +48911,189 @@ func (s LiquidityPoolDepositResultCode) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *LiquidityPoolDepositResultCode) UnmarshalBinary(inp []byte) error { +func (s *ScSpecUdtUnionCaseV0Kind) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*LiquidityPoolDepositResultCode)(nil) - _ encoding.BinaryUnmarshaler = (*LiquidityPoolDepositResultCode)(nil) + _ encoding.BinaryMarshaler = (*ScSpecUdtUnionCaseV0Kind)(nil) + _ encoding.BinaryUnmarshaler = (*ScSpecUdtUnionCaseV0Kind)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s LiquidityPoolDepositResultCode) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s ScSpecUdtUnionCaseV0Kind) xdrType() {} -var _ xdrType = (*LiquidityPoolDepositResultCode)(nil) +var _ xdrType = (*ScSpecUdtUnionCaseV0Kind)(nil) -// LiquidityPoolDepositResult is an XDR Union defines as: +// ScSpecUdtUnionCaseV0 is an XDR Union defines as: // -// union LiquidityPoolDepositResult switch (LiquidityPoolDepositResultCode code) +// union SCSpecUDTUnionCaseV0 switch (SCSpecUDTUnionCaseV0Kind kind) // { -// case LIQUIDITY_POOL_DEPOSIT_SUCCESS: -// void; -// case LIQUIDITY_POOL_DEPOSIT_MALFORMED: -// case LIQUIDITY_POOL_DEPOSIT_NO_TRUST: -// case LIQUIDITY_POOL_DEPOSIT_NOT_AUTHORIZED: -// case LIQUIDITY_POOL_DEPOSIT_UNDERFUNDED: -// case LIQUIDITY_POOL_DEPOSIT_LINE_FULL: -// case LIQUIDITY_POOL_DEPOSIT_BAD_PRICE: -// case LIQUIDITY_POOL_DEPOSIT_POOL_FULL: -// void; +// case SC_SPEC_UDT_UNION_CASE_VOID_V0: +// SCSpecUDTUnionCaseVoidV0 voidCase; +// case SC_SPEC_UDT_UNION_CASE_TUPLE_V0: +// SCSpecUDTUnionCaseTupleV0 tupleCase; // }; -type LiquidityPoolDepositResult struct { - Code LiquidityPoolDepositResultCode +type ScSpecUdtUnionCaseV0 struct { + Kind ScSpecUdtUnionCaseV0Kind + VoidCase *ScSpecUdtUnionCaseVoidV0 + TupleCase *ScSpecUdtUnionCaseTupleV0 } // SwitchFieldName returns the field name in which this union's // discriminant is stored -func (u LiquidityPoolDepositResult) SwitchFieldName() string { - return "Code" +func (u ScSpecUdtUnionCaseV0) SwitchFieldName() string { + return "Kind" } // ArmForSwitch returns which field name should be used for storing -// the value for an instance of LiquidityPoolDepositResult -func (u LiquidityPoolDepositResult) ArmForSwitch(sw int32) (string, bool) { - switch LiquidityPoolDepositResultCode(sw) { - case LiquidityPoolDepositResultCodeLiquidityPoolDepositSuccess: - return "", true - case LiquidityPoolDepositResultCodeLiquidityPoolDepositMalformed: - return "", true - case LiquidityPoolDepositResultCodeLiquidityPoolDepositNoTrust: - return "", true - case LiquidityPoolDepositResultCodeLiquidityPoolDepositNotAuthorized: - return "", true - case LiquidityPoolDepositResultCodeLiquidityPoolDepositUnderfunded: - return "", true - case LiquidityPoolDepositResultCodeLiquidityPoolDepositLineFull: - return "", true - case LiquidityPoolDepositResultCodeLiquidityPoolDepositBadPrice: - return "", true - case LiquidityPoolDepositResultCodeLiquidityPoolDepositPoolFull: - return "", true +// the value for an instance of ScSpecUdtUnionCaseV0 +func (u ScSpecUdtUnionCaseV0) ArmForSwitch(sw int32) (string, bool) { + switch ScSpecUdtUnionCaseV0Kind(sw) { + case ScSpecUdtUnionCaseV0KindScSpecUdtUnionCaseVoidV0: + return "VoidCase", true + case ScSpecUdtUnionCaseV0KindScSpecUdtUnionCaseTupleV0: + return "TupleCase", true } return "-", false } -// NewLiquidityPoolDepositResult creates a new LiquidityPoolDepositResult. -func NewLiquidityPoolDepositResult(code LiquidityPoolDepositResultCode, value interface{}) (result LiquidityPoolDepositResult, err error) { - result.Code = code - switch LiquidityPoolDepositResultCode(code) { - case LiquidityPoolDepositResultCodeLiquidityPoolDepositSuccess: - // void - case LiquidityPoolDepositResultCodeLiquidityPoolDepositMalformed: - // void - case LiquidityPoolDepositResultCodeLiquidityPoolDepositNoTrust: - // void - case LiquidityPoolDepositResultCodeLiquidityPoolDepositNotAuthorized: - // void - case LiquidityPoolDepositResultCodeLiquidityPoolDepositUnderfunded: - // void - case LiquidityPoolDepositResultCodeLiquidityPoolDepositLineFull: - // void - case LiquidityPoolDepositResultCodeLiquidityPoolDepositBadPrice: - // void - case LiquidityPoolDepositResultCodeLiquidityPoolDepositPoolFull: - // void +// NewScSpecUdtUnionCaseV0 creates a new ScSpecUdtUnionCaseV0. +func NewScSpecUdtUnionCaseV0(kind ScSpecUdtUnionCaseV0Kind, value interface{}) (result ScSpecUdtUnionCaseV0, err error) { + result.Kind = kind + switch ScSpecUdtUnionCaseV0Kind(kind) { + case ScSpecUdtUnionCaseV0KindScSpecUdtUnionCaseVoidV0: + tv, ok := value.(ScSpecUdtUnionCaseVoidV0) + if !ok { + err = errors.New("invalid value, must be ScSpecUdtUnionCaseVoidV0") + return + } + result.VoidCase = &tv + case ScSpecUdtUnionCaseV0KindScSpecUdtUnionCaseTupleV0: + tv, ok := value.(ScSpecUdtUnionCaseTupleV0) + if !ok { + err = errors.New("invalid value, must be ScSpecUdtUnionCaseTupleV0") + return + } + result.TupleCase = &tv + } + return +} + +// MustVoidCase retrieves the VoidCase value from the union, +// panicing if the value is not set. +func (u ScSpecUdtUnionCaseV0) MustVoidCase() ScSpecUdtUnionCaseVoidV0 { + val, ok := u.GetVoidCase() + + if !ok { + panic("arm VoidCase is not set") + } + + return val +} + +// GetVoidCase retrieves the VoidCase value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u ScSpecUdtUnionCaseV0) GetVoidCase() (result ScSpecUdtUnionCaseVoidV0, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Kind)) + + if armName == "VoidCase" { + result = *u.VoidCase + ok = true + } + + return +} + +// MustTupleCase retrieves the TupleCase value from the union, +// panicing if the value is not set. +func (u ScSpecUdtUnionCaseV0) MustTupleCase() ScSpecUdtUnionCaseTupleV0 { + val, ok := u.GetTupleCase() + + if !ok { + panic("arm TupleCase is not set") + } + + return val +} + +// GetTupleCase retrieves the TupleCase value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u ScSpecUdtUnionCaseV0) GetTupleCase() (result ScSpecUdtUnionCaseTupleV0, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Kind)) + + if armName == "TupleCase" { + result = *u.TupleCase + ok = true } + return } // EncodeTo encodes this value using the Encoder. -func (u LiquidityPoolDepositResult) EncodeTo(e *xdr.Encoder) error { +func (u ScSpecUdtUnionCaseV0) EncodeTo(e *xdr.Encoder) error { var err error - if err = u.Code.EncodeTo(e); err != nil { + if err = u.Kind.EncodeTo(e); err != nil { return err } - switch LiquidityPoolDepositResultCode(u.Code) { - case LiquidityPoolDepositResultCodeLiquidityPoolDepositSuccess: - // Void - return nil - case LiquidityPoolDepositResultCodeLiquidityPoolDepositMalformed: - // Void - return nil - case LiquidityPoolDepositResultCodeLiquidityPoolDepositNoTrust: - // Void - return nil - case LiquidityPoolDepositResultCodeLiquidityPoolDepositNotAuthorized: - // Void - return nil - case LiquidityPoolDepositResultCodeLiquidityPoolDepositUnderfunded: - // Void - return nil - case LiquidityPoolDepositResultCodeLiquidityPoolDepositLineFull: - // Void - return nil - case LiquidityPoolDepositResultCodeLiquidityPoolDepositBadPrice: - // Void + switch ScSpecUdtUnionCaseV0Kind(u.Kind) { + case ScSpecUdtUnionCaseV0KindScSpecUdtUnionCaseVoidV0: + if err = (*u.VoidCase).EncodeTo(e); err != nil { + return err + } return nil - case LiquidityPoolDepositResultCodeLiquidityPoolDepositPoolFull: - // Void + case ScSpecUdtUnionCaseV0KindScSpecUdtUnionCaseTupleV0: + if err = (*u.TupleCase).EncodeTo(e); err != nil { + return err + } return nil } - return fmt.Errorf("Code (LiquidityPoolDepositResultCode) switch value '%d' is not valid for union LiquidityPoolDepositResult", u.Code) + return fmt.Errorf("Kind (ScSpecUdtUnionCaseV0Kind) switch value '%d' is not valid for union ScSpecUdtUnionCaseV0", u.Kind) } -var _ decoderFrom = (*LiquidityPoolDepositResult)(nil) +var _ decoderFrom = (*ScSpecUdtUnionCaseV0)(nil) // DecodeFrom decodes this value using the Decoder. -func (u *LiquidityPoolDepositResult) DecodeFrom(d *xdr.Decoder) (int, error) { +func (u *ScSpecUdtUnionCaseV0) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding ScSpecUdtUnionCaseV0: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = u.Code.DecodeFrom(d) + nTmp, err = u.Kind.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding LiquidityPoolDepositResultCode: %s", err) + return n, fmt.Errorf("decoding ScSpecUdtUnionCaseV0Kind: %w", err) } - switch LiquidityPoolDepositResultCode(u.Code) { - case LiquidityPoolDepositResultCodeLiquidityPoolDepositSuccess: - // Void - return n, nil - case LiquidityPoolDepositResultCodeLiquidityPoolDepositMalformed: - // Void - return n, nil - case LiquidityPoolDepositResultCodeLiquidityPoolDepositNoTrust: - // Void - return n, nil - case LiquidityPoolDepositResultCodeLiquidityPoolDepositNotAuthorized: - // Void - return n, nil - case LiquidityPoolDepositResultCodeLiquidityPoolDepositUnderfunded: - // Void - return n, nil - case LiquidityPoolDepositResultCodeLiquidityPoolDepositLineFull: - // Void - return n, nil - case LiquidityPoolDepositResultCodeLiquidityPoolDepositBadPrice: - // Void + switch ScSpecUdtUnionCaseV0Kind(u.Kind) { + case ScSpecUdtUnionCaseV0KindScSpecUdtUnionCaseVoidV0: + u.VoidCase = new(ScSpecUdtUnionCaseVoidV0) + nTmp, err = (*u.VoidCase).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ScSpecUdtUnionCaseVoidV0: %w", err) + } return n, nil - case LiquidityPoolDepositResultCodeLiquidityPoolDepositPoolFull: - // Void + case ScSpecUdtUnionCaseV0KindScSpecUdtUnionCaseTupleV0: + u.TupleCase = new(ScSpecUdtUnionCaseTupleV0) + nTmp, err = (*u.TupleCase).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ScSpecUdtUnionCaseTupleV0: %w", err) + } return n, nil } - return n, fmt.Errorf("union LiquidityPoolDepositResult has invalid Code (LiquidityPoolDepositResultCode) switch value '%d'", u.Code) + return n, fmt.Errorf("union ScSpecUdtUnionCaseV0 has invalid Kind (ScSpecUdtUnionCaseV0Kind) switch value '%d'", u.Kind) } // MarshalBinary implements encoding.BinaryMarshaler. -func (s LiquidityPoolDepositResult) MarshalBinary() ([]byte, error) { +func (s ScSpecUdtUnionCaseV0) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -33185,100 +49101,117 @@ func (s LiquidityPoolDepositResult) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *LiquidityPoolDepositResult) UnmarshalBinary(inp []byte) error { +func (s *ScSpecUdtUnionCaseV0) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*LiquidityPoolDepositResult)(nil) - _ encoding.BinaryUnmarshaler = (*LiquidityPoolDepositResult)(nil) + _ encoding.BinaryMarshaler = (*ScSpecUdtUnionCaseV0)(nil) + _ encoding.BinaryUnmarshaler = (*ScSpecUdtUnionCaseV0)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s LiquidityPoolDepositResult) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s ScSpecUdtUnionCaseV0) xdrType() {} -var _ xdrType = (*LiquidityPoolDepositResult)(nil) +var _ xdrType = (*ScSpecUdtUnionCaseV0)(nil) -// LiquidityPoolWithdrawResultCode is an XDR Enum defines as: +// ScSpecUdtUnionV0 is an XDR Struct defines as: // -// enum LiquidityPoolWithdrawResultCode +// struct SCSpecUDTUnionV0 // { -// // codes considered as "success" for the operation -// LIQUIDITY_POOL_WITHDRAW_SUCCESS = 0, -// -// // codes considered as "failure" for the operation -// LIQUIDITY_POOL_WITHDRAW_MALFORMED = -1, // bad input -// LIQUIDITY_POOL_WITHDRAW_NO_TRUST = -2, // no trust line for one of the -// // assets -// LIQUIDITY_POOL_WITHDRAW_UNDERFUNDED = -3, // not enough balance of the -// // pool share -// LIQUIDITY_POOL_WITHDRAW_LINE_FULL = -4, // would go above limit for one -// // of the assets -// LIQUIDITY_POOL_WITHDRAW_UNDER_MINIMUM = -5 // didn't withdraw enough +// string doc; +// string lib<80>; +// string name<60>; +// SCSpecUDTUnionCaseV0 cases<50>; // }; -type LiquidityPoolWithdrawResultCode int32 - -const ( - LiquidityPoolWithdrawResultCodeLiquidityPoolWithdrawSuccess LiquidityPoolWithdrawResultCode = 0 - LiquidityPoolWithdrawResultCodeLiquidityPoolWithdrawMalformed LiquidityPoolWithdrawResultCode = -1 - LiquidityPoolWithdrawResultCodeLiquidityPoolWithdrawNoTrust LiquidityPoolWithdrawResultCode = -2 - LiquidityPoolWithdrawResultCodeLiquidityPoolWithdrawUnderfunded LiquidityPoolWithdrawResultCode = -3 - LiquidityPoolWithdrawResultCodeLiquidityPoolWithdrawLineFull LiquidityPoolWithdrawResultCode = -4 - LiquidityPoolWithdrawResultCodeLiquidityPoolWithdrawUnderMinimum LiquidityPoolWithdrawResultCode = -5 -) - -var liquidityPoolWithdrawResultCodeMap = map[int32]string{ - 0: "LiquidityPoolWithdrawResultCodeLiquidityPoolWithdrawSuccess", - -1: "LiquidityPoolWithdrawResultCodeLiquidityPoolWithdrawMalformed", - -2: "LiquidityPoolWithdrawResultCodeLiquidityPoolWithdrawNoTrust", - -3: "LiquidityPoolWithdrawResultCodeLiquidityPoolWithdrawUnderfunded", - -4: "LiquidityPoolWithdrawResultCodeLiquidityPoolWithdrawLineFull", - -5: "LiquidityPoolWithdrawResultCodeLiquidityPoolWithdrawUnderMinimum", -} - -// ValidEnum validates a proposed value for this enum. Implements -// the Enum interface for LiquidityPoolWithdrawResultCode -func (e LiquidityPoolWithdrawResultCode) ValidEnum(v int32) bool { - _, ok := liquidityPoolWithdrawResultCodeMap[v] - return ok -} - -// String returns the name of `e` -func (e LiquidityPoolWithdrawResultCode) String() string { - name, _ := liquidityPoolWithdrawResultCodeMap[int32(e)] - return name +type ScSpecUdtUnionV0 struct { + Doc string `xdrmaxsize:"1024"` + Lib string `xdrmaxsize:"80"` + Name string `xdrmaxsize:"60"` + Cases []ScSpecUdtUnionCaseV0 `xdrmaxsize:"50"` } // EncodeTo encodes this value using the Encoder. -func (e LiquidityPoolWithdrawResultCode) EncodeTo(enc *xdr.Encoder) error { - if _, ok := liquidityPoolWithdrawResultCodeMap[int32(e)]; !ok { - return fmt.Errorf("'%d' is not a valid LiquidityPoolWithdrawResultCode enum value", e) +func (s *ScSpecUdtUnionV0) EncodeTo(e *xdr.Encoder) error { + var err error + if _, err = e.EncodeString(string(s.Doc)); err != nil { + return err } - _, err := enc.EncodeInt(int32(e)) - return err + if _, err = e.EncodeString(string(s.Lib)); err != nil { + return err + } + if _, err = e.EncodeString(string(s.Name)); err != nil { + return err + } + if _, err = e.EncodeUint(uint32(len(s.Cases))); err != nil { + return err + } + for i := 0; i < len(s.Cases); i++ { + if err = s.Cases[i].EncodeTo(e); err != nil { + return err + } + } + return nil } -var _ decoderFrom = (*LiquidityPoolWithdrawResultCode)(nil) +var _ decoderFrom = (*ScSpecUdtUnionV0)(nil) // DecodeFrom decodes this value using the Decoder. -func (e *LiquidityPoolWithdrawResultCode) DecodeFrom(d *xdr.Decoder) (int, error) { - v, n, err := d.DecodeInt() +func (s *ScSpecUdtUnionV0) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding ScSpecUdtUnionV0: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + var err error + var n, nTmp int + s.Doc, nTmp, err = d.DecodeString(1024) + n += nTmp if err != nil { - return n, fmt.Errorf("decoding LiquidityPoolWithdrawResultCode: %s", err) + return n, fmt.Errorf("decoding Doc: %w", err) } - if _, ok := liquidityPoolWithdrawResultCodeMap[v]; !ok { - return n, fmt.Errorf("'%d' is not a valid LiquidityPoolWithdrawResultCode enum value", v) + s.Lib, nTmp, err = d.DecodeString(80) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Lib: %w", err) + } + s.Name, nTmp, err = d.DecodeString(60) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Name: %w", err) + } + var l uint32 + l, nTmp, err = d.DecodeUint() + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ScSpecUdtUnionCaseV0: %w", err) + } + if l > 50 { + return n, fmt.Errorf("decoding ScSpecUdtUnionCaseV0: data size (%d) exceeds size limit (50)", l) + } + s.Cases = nil + if l > 0 { + if il, ok := d.InputLen(); ok && uint(il) < uint(l) { + return n, fmt.Errorf("decoding ScSpecUdtUnionCaseV0: length (%d) exceeds remaining input length (%d)", l, il) + } + s.Cases = make([]ScSpecUdtUnionCaseV0, l) + for i := uint32(0); i < l; i++ { + nTmp, err = s.Cases[i].DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ScSpecUdtUnionCaseV0: %w", err) + } + } } - *e = LiquidityPoolWithdrawResultCode(v) return n, nil } // MarshalBinary implements encoding.BinaryMarshaler. -func (s LiquidityPoolWithdrawResultCode) MarshalBinary() ([]byte, error) { +func (s ScSpecUdtUnionV0) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -33286,152 +49219,202 @@ func (s LiquidityPoolWithdrawResultCode) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *LiquidityPoolWithdrawResultCode) UnmarshalBinary(inp []byte) error { +func (s *ScSpecUdtUnionV0) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*LiquidityPoolWithdrawResultCode)(nil) - _ encoding.BinaryUnmarshaler = (*LiquidityPoolWithdrawResultCode)(nil) + _ encoding.BinaryMarshaler = (*ScSpecUdtUnionV0)(nil) + _ encoding.BinaryUnmarshaler = (*ScSpecUdtUnionV0)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s LiquidityPoolWithdrawResultCode) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s ScSpecUdtUnionV0) xdrType() {} -var _ xdrType = (*LiquidityPoolWithdrawResultCode)(nil) +var _ xdrType = (*ScSpecUdtUnionV0)(nil) -// LiquidityPoolWithdrawResult is an XDR Union defines as: +// ScSpecUdtEnumCaseV0 is an XDR Struct defines as: // -// union LiquidityPoolWithdrawResult switch (LiquidityPoolWithdrawResultCode code) +// struct SCSpecUDTEnumCaseV0 // { -// case LIQUIDITY_POOL_WITHDRAW_SUCCESS: -// void; -// case LIQUIDITY_POOL_WITHDRAW_MALFORMED: -// case LIQUIDITY_POOL_WITHDRAW_NO_TRUST: -// case LIQUIDITY_POOL_WITHDRAW_UNDERFUNDED: -// case LIQUIDITY_POOL_WITHDRAW_LINE_FULL: -// case LIQUIDITY_POOL_WITHDRAW_UNDER_MINIMUM: -// void; +// string doc; +// string name<60>; +// uint32 value; // }; -type LiquidityPoolWithdrawResult struct { - Code LiquidityPoolWithdrawResultCode +type ScSpecUdtEnumCaseV0 struct { + Doc string `xdrmaxsize:"1024"` + Name string `xdrmaxsize:"60"` + Value Uint32 } -// SwitchFieldName returns the field name in which this union's -// discriminant is stored -func (u LiquidityPoolWithdrawResult) SwitchFieldName() string { - return "Code" +// EncodeTo encodes this value using the Encoder. +func (s *ScSpecUdtEnumCaseV0) EncodeTo(e *xdr.Encoder) error { + var err error + if _, err = e.EncodeString(string(s.Doc)); err != nil { + return err + } + if _, err = e.EncodeString(string(s.Name)); err != nil { + return err + } + if err = s.Value.EncodeTo(e); err != nil { + return err + } + return nil } -// ArmForSwitch returns which field name should be used for storing -// the value for an instance of LiquidityPoolWithdrawResult -func (u LiquidityPoolWithdrawResult) ArmForSwitch(sw int32) (string, bool) { - switch LiquidityPoolWithdrawResultCode(sw) { - case LiquidityPoolWithdrawResultCodeLiquidityPoolWithdrawSuccess: - return "", true - case LiquidityPoolWithdrawResultCodeLiquidityPoolWithdrawMalformed: - return "", true - case LiquidityPoolWithdrawResultCodeLiquidityPoolWithdrawNoTrust: - return "", true - case LiquidityPoolWithdrawResultCodeLiquidityPoolWithdrawUnderfunded: - return "", true - case LiquidityPoolWithdrawResultCodeLiquidityPoolWithdrawLineFull: - return "", true - case LiquidityPoolWithdrawResultCodeLiquidityPoolWithdrawUnderMinimum: - return "", true +var _ decoderFrom = (*ScSpecUdtEnumCaseV0)(nil) + +// DecodeFrom decodes this value using the Decoder. +func (s *ScSpecUdtEnumCaseV0) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding ScSpecUdtEnumCaseV0: %w", ErrMaxDecodingDepthReached) } - return "-", false + maxDepth -= 1 + var err error + var n, nTmp int + s.Doc, nTmp, err = d.DecodeString(1024) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Doc: %w", err) + } + s.Name, nTmp, err = d.DecodeString(60) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Name: %w", err) + } + nTmp, err = s.Value.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Uint32: %w", err) + } + return n, nil } -// NewLiquidityPoolWithdrawResult creates a new LiquidityPoolWithdrawResult. -func NewLiquidityPoolWithdrawResult(code LiquidityPoolWithdrawResultCode, value interface{}) (result LiquidityPoolWithdrawResult, err error) { - result.Code = code - switch LiquidityPoolWithdrawResultCode(code) { - case LiquidityPoolWithdrawResultCodeLiquidityPoolWithdrawSuccess: - // void - case LiquidityPoolWithdrawResultCodeLiquidityPoolWithdrawMalformed: - // void - case LiquidityPoolWithdrawResultCodeLiquidityPoolWithdrawNoTrust: - // void - case LiquidityPoolWithdrawResultCodeLiquidityPoolWithdrawUnderfunded: - // void - case LiquidityPoolWithdrawResultCodeLiquidityPoolWithdrawLineFull: - // void - case LiquidityPoolWithdrawResultCodeLiquidityPoolWithdrawUnderMinimum: - // void - } - return +// MarshalBinary implements encoding.BinaryMarshaler. +func (s ScSpecUdtEnumCaseV0) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *ScSpecUdtEnumCaseV0) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} + +var ( + _ encoding.BinaryMarshaler = (*ScSpecUdtEnumCaseV0)(nil) + _ encoding.BinaryUnmarshaler = (*ScSpecUdtEnumCaseV0)(nil) +) + +// xdrType signals that this type represents XDR values defined by this package. +func (s ScSpecUdtEnumCaseV0) xdrType() {} + +var _ xdrType = (*ScSpecUdtEnumCaseV0)(nil) + +// ScSpecUdtEnumV0 is an XDR Struct defines as: +// +// struct SCSpecUDTEnumV0 +// { +// string doc; +// string lib<80>; +// string name<60>; +// SCSpecUDTEnumCaseV0 cases<50>; +// }; +type ScSpecUdtEnumV0 struct { + Doc string `xdrmaxsize:"1024"` + Lib string `xdrmaxsize:"80"` + Name string `xdrmaxsize:"60"` + Cases []ScSpecUdtEnumCaseV0 `xdrmaxsize:"50"` } // EncodeTo encodes this value using the Encoder. -func (u LiquidityPoolWithdrawResult) EncodeTo(e *xdr.Encoder) error { +func (s *ScSpecUdtEnumV0) EncodeTo(e *xdr.Encoder) error { var err error - if err = u.Code.EncodeTo(e); err != nil { + if _, err = e.EncodeString(string(s.Doc)); err != nil { return err } - switch LiquidityPoolWithdrawResultCode(u.Code) { - case LiquidityPoolWithdrawResultCodeLiquidityPoolWithdrawSuccess: - // Void - return nil - case LiquidityPoolWithdrawResultCodeLiquidityPoolWithdrawMalformed: - // Void - return nil - case LiquidityPoolWithdrawResultCodeLiquidityPoolWithdrawNoTrust: - // Void - return nil - case LiquidityPoolWithdrawResultCodeLiquidityPoolWithdrawUnderfunded: - // Void - return nil - case LiquidityPoolWithdrawResultCodeLiquidityPoolWithdrawLineFull: - // Void - return nil - case LiquidityPoolWithdrawResultCodeLiquidityPoolWithdrawUnderMinimum: - // Void - return nil + if _, err = e.EncodeString(string(s.Lib)); err != nil { + return err } - return fmt.Errorf("Code (LiquidityPoolWithdrawResultCode) switch value '%d' is not valid for union LiquidityPoolWithdrawResult", u.Code) + if _, err = e.EncodeString(string(s.Name)); err != nil { + return err + } + if _, err = e.EncodeUint(uint32(len(s.Cases))); err != nil { + return err + } + for i := 0; i < len(s.Cases); i++ { + if err = s.Cases[i].EncodeTo(e); err != nil { + return err + } + } + return nil } -var _ decoderFrom = (*LiquidityPoolWithdrawResult)(nil) +var _ decoderFrom = (*ScSpecUdtEnumV0)(nil) // DecodeFrom decodes this value using the Decoder. -func (u *LiquidityPoolWithdrawResult) DecodeFrom(d *xdr.Decoder) (int, error) { +func (s *ScSpecUdtEnumV0) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding ScSpecUdtEnumV0: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = u.Code.DecodeFrom(d) + s.Doc, nTmp, err = d.DecodeString(1024) n += nTmp if err != nil { - return n, fmt.Errorf("decoding LiquidityPoolWithdrawResultCode: %s", err) + return n, fmt.Errorf("decoding Doc: %w", err) } - switch LiquidityPoolWithdrawResultCode(u.Code) { - case LiquidityPoolWithdrawResultCodeLiquidityPoolWithdrawSuccess: - // Void - return n, nil - case LiquidityPoolWithdrawResultCodeLiquidityPoolWithdrawMalformed: - // Void - return n, nil - case LiquidityPoolWithdrawResultCodeLiquidityPoolWithdrawNoTrust: - // Void - return n, nil - case LiquidityPoolWithdrawResultCodeLiquidityPoolWithdrawUnderfunded: - // Void - return n, nil - case LiquidityPoolWithdrawResultCodeLiquidityPoolWithdrawLineFull: - // Void - return n, nil - case LiquidityPoolWithdrawResultCodeLiquidityPoolWithdrawUnderMinimum: - // Void - return n, nil + s.Lib, nTmp, err = d.DecodeString(80) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Lib: %w", err) } - return n, fmt.Errorf("union LiquidityPoolWithdrawResult has invalid Code (LiquidityPoolWithdrawResultCode) switch value '%d'", u.Code) + s.Name, nTmp, err = d.DecodeString(60) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Name: %w", err) + } + var l uint32 + l, nTmp, err = d.DecodeUint() + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ScSpecUdtEnumCaseV0: %w", err) + } + if l > 50 { + return n, fmt.Errorf("decoding ScSpecUdtEnumCaseV0: data size (%d) exceeds size limit (50)", l) + } + s.Cases = nil + if l > 0 { + if il, ok := d.InputLen(); ok && uint(il) < uint(l) { + return n, fmt.Errorf("decoding ScSpecUdtEnumCaseV0: length (%d) exceeds remaining input length (%d)", l, il) + } + s.Cases = make([]ScSpecUdtEnumCaseV0, l) + for i := uint32(0); i < l; i++ { + nTmp, err = s.Cases[i].DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ScSpecUdtEnumCaseV0: %w", err) + } + } + } + return n, nil } // MarshalBinary implements encoding.BinaryMarshaler. -func (s LiquidityPoolWithdrawResult) MarshalBinary() ([]byte, error) { +func (s ScSpecUdtEnumV0) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -33439,98 +49422,84 @@ func (s LiquidityPoolWithdrawResult) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *LiquidityPoolWithdrawResult) UnmarshalBinary(inp []byte) error { +func (s *ScSpecUdtEnumV0) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*LiquidityPoolWithdrawResult)(nil) - _ encoding.BinaryUnmarshaler = (*LiquidityPoolWithdrawResult)(nil) + _ encoding.BinaryMarshaler = (*ScSpecUdtEnumV0)(nil) + _ encoding.BinaryUnmarshaler = (*ScSpecUdtEnumV0)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s LiquidityPoolWithdrawResult) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s ScSpecUdtEnumV0) xdrType() {} -var _ xdrType = (*LiquidityPoolWithdrawResult)(nil) +var _ xdrType = (*ScSpecUdtEnumV0)(nil) -// OperationResultCode is an XDR Enum defines as: +// ScSpecUdtErrorEnumCaseV0 is an XDR Struct defines as: // -// enum OperationResultCode +// struct SCSpecUDTErrorEnumCaseV0 // { -// opINNER = 0, // inner object result is valid -// -// opBAD_AUTH = -1, // too few valid signatures / wrong network -// opNO_ACCOUNT = -2, // source account was not found -// opNOT_SUPPORTED = -3, // operation not supported at this time -// opTOO_MANY_SUBENTRIES = -4, // max number of subentries already reached -// opEXCEEDED_WORK_LIMIT = -5, // operation did too much work -// opTOO_MANY_SPONSORING = -6 // account is sponsoring too many entries +// string doc; +// string name<60>; +// uint32 value; // }; -type OperationResultCode int32 - -const ( - OperationResultCodeOpInner OperationResultCode = 0 - OperationResultCodeOpBadAuth OperationResultCode = -1 - OperationResultCodeOpNoAccount OperationResultCode = -2 - OperationResultCodeOpNotSupported OperationResultCode = -3 - OperationResultCodeOpTooManySubentries OperationResultCode = -4 - OperationResultCodeOpExceededWorkLimit OperationResultCode = -5 - OperationResultCodeOpTooManySponsoring OperationResultCode = -6 -) - -var operationResultCodeMap = map[int32]string{ - 0: "OperationResultCodeOpInner", - -1: "OperationResultCodeOpBadAuth", - -2: "OperationResultCodeOpNoAccount", - -3: "OperationResultCodeOpNotSupported", - -4: "OperationResultCodeOpTooManySubentries", - -5: "OperationResultCodeOpExceededWorkLimit", - -6: "OperationResultCodeOpTooManySponsoring", -} - -// ValidEnum validates a proposed value for this enum. Implements -// the Enum interface for OperationResultCode -func (e OperationResultCode) ValidEnum(v int32) bool { - _, ok := operationResultCodeMap[v] - return ok -} - -// String returns the name of `e` -func (e OperationResultCode) String() string { - name, _ := operationResultCodeMap[int32(e)] - return name +type ScSpecUdtErrorEnumCaseV0 struct { + Doc string `xdrmaxsize:"1024"` + Name string `xdrmaxsize:"60"` + Value Uint32 } // EncodeTo encodes this value using the Encoder. -func (e OperationResultCode) EncodeTo(enc *xdr.Encoder) error { - if _, ok := operationResultCodeMap[int32(e)]; !ok { - return fmt.Errorf("'%d' is not a valid OperationResultCode enum value", e) +func (s *ScSpecUdtErrorEnumCaseV0) EncodeTo(e *xdr.Encoder) error { + var err error + if _, err = e.EncodeString(string(s.Doc)); err != nil { + return err } - _, err := enc.EncodeInt(int32(e)) - return err + if _, err = e.EncodeString(string(s.Name)); err != nil { + return err + } + if err = s.Value.EncodeTo(e); err != nil { + return err + } + return nil } -var _ decoderFrom = (*OperationResultCode)(nil) +var _ decoderFrom = (*ScSpecUdtErrorEnumCaseV0)(nil) // DecodeFrom decodes this value using the Decoder. -func (e *OperationResultCode) DecodeFrom(d *xdr.Decoder) (int, error) { - v, n, err := d.DecodeInt() +func (s *ScSpecUdtErrorEnumCaseV0) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding ScSpecUdtErrorEnumCaseV0: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + var err error + var n, nTmp int + s.Doc, nTmp, err = d.DecodeString(1024) + n += nTmp if err != nil { - return n, fmt.Errorf("decoding OperationResultCode: %s", err) + return n, fmt.Errorf("decoding Doc: %w", err) } - if _, ok := operationResultCodeMap[v]; !ok { - return n, fmt.Errorf("'%d' is not a valid OperationResultCode enum value", v) + s.Name, nTmp, err = d.DecodeString(60) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Name: %w", err) + } + nTmp, err = s.Value.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Uint32: %w", err) } - *e = OperationResultCode(v) return n, nil } // MarshalBinary implements encoding.BinaryMarshaler. -func (s OperationResultCode) MarshalBinary() ([]byte, error) { +func (s ScSpecUdtErrorEnumCaseV0) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -33538,937 +49507,1385 @@ func (s OperationResultCode) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *OperationResultCode) UnmarshalBinary(inp []byte) error { +func (s *ScSpecUdtErrorEnumCaseV0) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*OperationResultCode)(nil) - _ encoding.BinaryUnmarshaler = (*OperationResultCode)(nil) + _ encoding.BinaryMarshaler = (*ScSpecUdtErrorEnumCaseV0)(nil) + _ encoding.BinaryUnmarshaler = (*ScSpecUdtErrorEnumCaseV0)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s OperationResultCode) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s ScSpecUdtErrorEnumCaseV0) xdrType() {} -var _ xdrType = (*OperationResultCode)(nil) +var _ xdrType = (*ScSpecUdtErrorEnumCaseV0)(nil) -// OperationResultTr is an XDR NestedUnion defines as: +// ScSpecUdtErrorEnumV0 is an XDR Struct defines as: // -// union switch (OperationType type) -// { -// case CREATE_ACCOUNT: -// CreateAccountResult createAccountResult; -// case PAYMENT: -// PaymentResult paymentResult; -// case PATH_PAYMENT_STRICT_RECEIVE: -// PathPaymentStrictReceiveResult pathPaymentStrictReceiveResult; -// case MANAGE_SELL_OFFER: -// ManageSellOfferResult manageSellOfferResult; -// case CREATE_PASSIVE_SELL_OFFER: -// ManageSellOfferResult createPassiveSellOfferResult; -// case SET_OPTIONS: -// SetOptionsResult setOptionsResult; -// case CHANGE_TRUST: -// ChangeTrustResult changeTrustResult; -// case ALLOW_TRUST: -// AllowTrustResult allowTrustResult; -// case ACCOUNT_MERGE: -// AccountMergeResult accountMergeResult; -// case INFLATION: -// InflationResult inflationResult; -// case MANAGE_DATA: -// ManageDataResult manageDataResult; -// case BUMP_SEQUENCE: -// BumpSequenceResult bumpSeqResult; -// case MANAGE_BUY_OFFER: -// ManageBuyOfferResult manageBuyOfferResult; -// case PATH_PAYMENT_STRICT_SEND: -// PathPaymentStrictSendResult pathPaymentStrictSendResult; -// case CREATE_CLAIMABLE_BALANCE: -// CreateClaimableBalanceResult createClaimableBalanceResult; -// case CLAIM_CLAIMABLE_BALANCE: -// ClaimClaimableBalanceResult claimClaimableBalanceResult; -// case BEGIN_SPONSORING_FUTURE_RESERVES: -// BeginSponsoringFutureReservesResult beginSponsoringFutureReservesResult; -// case END_SPONSORING_FUTURE_RESERVES: -// EndSponsoringFutureReservesResult endSponsoringFutureReservesResult; -// case REVOKE_SPONSORSHIP: -// RevokeSponsorshipResult revokeSponsorshipResult; -// case CLAWBACK: -// ClawbackResult clawbackResult; -// case CLAWBACK_CLAIMABLE_BALANCE: -// ClawbackClaimableBalanceResult clawbackClaimableBalanceResult; -// case SET_TRUST_LINE_FLAGS: -// SetTrustLineFlagsResult setTrustLineFlagsResult; -// case LIQUIDITY_POOL_DEPOSIT: -// LiquidityPoolDepositResult liquidityPoolDepositResult; -// case LIQUIDITY_POOL_WITHDRAW: -// LiquidityPoolWithdrawResult liquidityPoolWithdrawResult; -// } -type OperationResultTr struct { - Type OperationType - CreateAccountResult *CreateAccountResult - PaymentResult *PaymentResult - PathPaymentStrictReceiveResult *PathPaymentStrictReceiveResult - ManageSellOfferResult *ManageSellOfferResult - CreatePassiveSellOfferResult *ManageSellOfferResult - SetOptionsResult *SetOptionsResult - ChangeTrustResult *ChangeTrustResult - AllowTrustResult *AllowTrustResult - AccountMergeResult *AccountMergeResult - InflationResult *InflationResult - ManageDataResult *ManageDataResult - BumpSeqResult *BumpSequenceResult - ManageBuyOfferResult *ManageBuyOfferResult - PathPaymentStrictSendResult *PathPaymentStrictSendResult - CreateClaimableBalanceResult *CreateClaimableBalanceResult - ClaimClaimableBalanceResult *ClaimClaimableBalanceResult - BeginSponsoringFutureReservesResult *BeginSponsoringFutureReservesResult - EndSponsoringFutureReservesResult *EndSponsoringFutureReservesResult - RevokeSponsorshipResult *RevokeSponsorshipResult - ClawbackResult *ClawbackResult - ClawbackClaimableBalanceResult *ClawbackClaimableBalanceResult - SetTrustLineFlagsResult *SetTrustLineFlagsResult - LiquidityPoolDepositResult *LiquidityPoolDepositResult - LiquidityPoolWithdrawResult *LiquidityPoolWithdrawResult -} - -// SwitchFieldName returns the field name in which this union's -// discriminant is stored -func (u OperationResultTr) SwitchFieldName() string { - return "Type" +// struct SCSpecUDTErrorEnumV0 +// { +// string doc; +// string lib<80>; +// string name<60>; +// SCSpecUDTErrorEnumCaseV0 cases<50>; +// }; +type ScSpecUdtErrorEnumV0 struct { + Doc string `xdrmaxsize:"1024"` + Lib string `xdrmaxsize:"80"` + Name string `xdrmaxsize:"60"` + Cases []ScSpecUdtErrorEnumCaseV0 `xdrmaxsize:"50"` } -// ArmForSwitch returns which field name should be used for storing -// the value for an instance of OperationResultTr -func (u OperationResultTr) ArmForSwitch(sw int32) (string, bool) { - switch OperationType(sw) { - case OperationTypeCreateAccount: - return "CreateAccountResult", true - case OperationTypePayment: - return "PaymentResult", true - case OperationTypePathPaymentStrictReceive: - return "PathPaymentStrictReceiveResult", true - case OperationTypeManageSellOffer: - return "ManageSellOfferResult", true - case OperationTypeCreatePassiveSellOffer: - return "CreatePassiveSellOfferResult", true - case OperationTypeSetOptions: - return "SetOptionsResult", true - case OperationTypeChangeTrust: - return "ChangeTrustResult", true - case OperationTypeAllowTrust: - return "AllowTrustResult", true - case OperationTypeAccountMerge: - return "AccountMergeResult", true - case OperationTypeInflation: - return "InflationResult", true - case OperationTypeManageData: - return "ManageDataResult", true - case OperationTypeBumpSequence: - return "BumpSeqResult", true - case OperationTypeManageBuyOffer: - return "ManageBuyOfferResult", true - case OperationTypePathPaymentStrictSend: - return "PathPaymentStrictSendResult", true - case OperationTypeCreateClaimableBalance: - return "CreateClaimableBalanceResult", true - case OperationTypeClaimClaimableBalance: - return "ClaimClaimableBalanceResult", true - case OperationTypeBeginSponsoringFutureReserves: - return "BeginSponsoringFutureReservesResult", true - case OperationTypeEndSponsoringFutureReserves: - return "EndSponsoringFutureReservesResult", true - case OperationTypeRevokeSponsorship: - return "RevokeSponsorshipResult", true - case OperationTypeClawback: - return "ClawbackResult", true - case OperationTypeClawbackClaimableBalance: - return "ClawbackClaimableBalanceResult", true - case OperationTypeSetTrustLineFlags: - return "SetTrustLineFlagsResult", true - case OperationTypeLiquidityPoolDeposit: - return "LiquidityPoolDepositResult", true - case OperationTypeLiquidityPoolWithdraw: - return "LiquidityPoolWithdrawResult", true +// EncodeTo encodes this value using the Encoder. +func (s *ScSpecUdtErrorEnumV0) EncodeTo(e *xdr.Encoder) error { + var err error + if _, err = e.EncodeString(string(s.Doc)); err != nil { + return err } - return "-", false -} - -// NewOperationResultTr creates a new OperationResultTr. -func NewOperationResultTr(aType OperationType, value interface{}) (result OperationResultTr, err error) { - result.Type = aType - switch OperationType(aType) { - case OperationTypeCreateAccount: - tv, ok := value.(CreateAccountResult) - if !ok { - err = fmt.Errorf("invalid value, must be CreateAccountResult") - return - } - result.CreateAccountResult = &tv - case OperationTypePayment: - tv, ok := value.(PaymentResult) - if !ok { - err = fmt.Errorf("invalid value, must be PaymentResult") - return - } - result.PaymentResult = &tv - case OperationTypePathPaymentStrictReceive: - tv, ok := value.(PathPaymentStrictReceiveResult) - if !ok { - err = fmt.Errorf("invalid value, must be PathPaymentStrictReceiveResult") - return - } - result.PathPaymentStrictReceiveResult = &tv - case OperationTypeManageSellOffer: - tv, ok := value.(ManageSellOfferResult) - if !ok { - err = fmt.Errorf("invalid value, must be ManageSellOfferResult") - return - } - result.ManageSellOfferResult = &tv - case OperationTypeCreatePassiveSellOffer: - tv, ok := value.(ManageSellOfferResult) - if !ok { - err = fmt.Errorf("invalid value, must be ManageSellOfferResult") - return - } - result.CreatePassiveSellOfferResult = &tv - case OperationTypeSetOptions: - tv, ok := value.(SetOptionsResult) - if !ok { - err = fmt.Errorf("invalid value, must be SetOptionsResult") - return - } - result.SetOptionsResult = &tv - case OperationTypeChangeTrust: - tv, ok := value.(ChangeTrustResult) - if !ok { - err = fmt.Errorf("invalid value, must be ChangeTrustResult") - return - } - result.ChangeTrustResult = &tv - case OperationTypeAllowTrust: - tv, ok := value.(AllowTrustResult) - if !ok { - err = fmt.Errorf("invalid value, must be AllowTrustResult") - return - } - result.AllowTrustResult = &tv - case OperationTypeAccountMerge: - tv, ok := value.(AccountMergeResult) - if !ok { - err = fmt.Errorf("invalid value, must be AccountMergeResult") - return - } - result.AccountMergeResult = &tv - case OperationTypeInflation: - tv, ok := value.(InflationResult) - if !ok { - err = fmt.Errorf("invalid value, must be InflationResult") - return - } - result.InflationResult = &tv - case OperationTypeManageData: - tv, ok := value.(ManageDataResult) - if !ok { - err = fmt.Errorf("invalid value, must be ManageDataResult") - return - } - result.ManageDataResult = &tv - case OperationTypeBumpSequence: - tv, ok := value.(BumpSequenceResult) - if !ok { - err = fmt.Errorf("invalid value, must be BumpSequenceResult") - return - } - result.BumpSeqResult = &tv - case OperationTypeManageBuyOffer: - tv, ok := value.(ManageBuyOfferResult) - if !ok { - err = fmt.Errorf("invalid value, must be ManageBuyOfferResult") - return - } - result.ManageBuyOfferResult = &tv - case OperationTypePathPaymentStrictSend: - tv, ok := value.(PathPaymentStrictSendResult) - if !ok { - err = fmt.Errorf("invalid value, must be PathPaymentStrictSendResult") - return - } - result.PathPaymentStrictSendResult = &tv - case OperationTypeCreateClaimableBalance: - tv, ok := value.(CreateClaimableBalanceResult) - if !ok { - err = fmt.Errorf("invalid value, must be CreateClaimableBalanceResult") - return - } - result.CreateClaimableBalanceResult = &tv - case OperationTypeClaimClaimableBalance: - tv, ok := value.(ClaimClaimableBalanceResult) - if !ok { - err = fmt.Errorf("invalid value, must be ClaimClaimableBalanceResult") - return - } - result.ClaimClaimableBalanceResult = &tv - case OperationTypeBeginSponsoringFutureReserves: - tv, ok := value.(BeginSponsoringFutureReservesResult) - if !ok { - err = fmt.Errorf("invalid value, must be BeginSponsoringFutureReservesResult") - return - } - result.BeginSponsoringFutureReservesResult = &tv - case OperationTypeEndSponsoringFutureReserves: - tv, ok := value.(EndSponsoringFutureReservesResult) - if !ok { - err = fmt.Errorf("invalid value, must be EndSponsoringFutureReservesResult") - return - } - result.EndSponsoringFutureReservesResult = &tv - case OperationTypeRevokeSponsorship: - tv, ok := value.(RevokeSponsorshipResult) - if !ok { - err = fmt.Errorf("invalid value, must be RevokeSponsorshipResult") - return - } - result.RevokeSponsorshipResult = &tv - case OperationTypeClawback: - tv, ok := value.(ClawbackResult) - if !ok { - err = fmt.Errorf("invalid value, must be ClawbackResult") - return - } - result.ClawbackResult = &tv - case OperationTypeClawbackClaimableBalance: - tv, ok := value.(ClawbackClaimableBalanceResult) - if !ok { - err = fmt.Errorf("invalid value, must be ClawbackClaimableBalanceResult") - return - } - result.ClawbackClaimableBalanceResult = &tv - case OperationTypeSetTrustLineFlags: - tv, ok := value.(SetTrustLineFlagsResult) - if !ok { - err = fmt.Errorf("invalid value, must be SetTrustLineFlagsResult") - return - } - result.SetTrustLineFlagsResult = &tv - case OperationTypeLiquidityPoolDeposit: - tv, ok := value.(LiquidityPoolDepositResult) - if !ok { - err = fmt.Errorf("invalid value, must be LiquidityPoolDepositResult") - return - } - result.LiquidityPoolDepositResult = &tv - case OperationTypeLiquidityPoolWithdraw: - tv, ok := value.(LiquidityPoolWithdrawResult) - if !ok { - err = fmt.Errorf("invalid value, must be LiquidityPoolWithdrawResult") - return + if _, err = e.EncodeString(string(s.Lib)); err != nil { + return err + } + if _, err = e.EncodeString(string(s.Name)); err != nil { + return err + } + if _, err = e.EncodeUint(uint32(len(s.Cases))); err != nil { + return err + } + for i := 0; i < len(s.Cases); i++ { + if err = s.Cases[i].EncodeTo(e); err != nil { + return err } - result.LiquidityPoolWithdrawResult = &tv } - return + return nil } -// MustCreateAccountResult retrieves the CreateAccountResult value from the union, -// panicing if the value is not set. -func (u OperationResultTr) MustCreateAccountResult() CreateAccountResult { - val, ok := u.GetCreateAccountResult() +var _ decoderFrom = (*ScSpecUdtErrorEnumV0)(nil) - if !ok { - panic("arm CreateAccountResult is not set") +// DecodeFrom decodes this value using the Decoder. +func (s *ScSpecUdtErrorEnumV0) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding ScSpecUdtErrorEnumV0: %w", ErrMaxDecodingDepthReached) } - - return val + maxDepth -= 1 + var err error + var n, nTmp int + s.Doc, nTmp, err = d.DecodeString(1024) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Doc: %w", err) + } + s.Lib, nTmp, err = d.DecodeString(80) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Lib: %w", err) + } + s.Name, nTmp, err = d.DecodeString(60) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Name: %w", err) + } + var l uint32 + l, nTmp, err = d.DecodeUint() + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ScSpecUdtErrorEnumCaseV0: %w", err) + } + if l > 50 { + return n, fmt.Errorf("decoding ScSpecUdtErrorEnumCaseV0: data size (%d) exceeds size limit (50)", l) + } + s.Cases = nil + if l > 0 { + if il, ok := d.InputLen(); ok && uint(il) < uint(l) { + return n, fmt.Errorf("decoding ScSpecUdtErrorEnumCaseV0: length (%d) exceeds remaining input length (%d)", l, il) + } + s.Cases = make([]ScSpecUdtErrorEnumCaseV0, l) + for i := uint32(0); i < l; i++ { + nTmp, err = s.Cases[i].DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ScSpecUdtErrorEnumCaseV0: %w", err) + } + } + } + return n, nil } -// GetCreateAccountResult retrieves the CreateAccountResult value from the union, -// returning ok if the union's switch indicated the value is valid. -func (u OperationResultTr) GetCreateAccountResult() (result CreateAccountResult, ok bool) { - armName, _ := u.ArmForSwitch(int32(u.Type)) - - if armName == "CreateAccountResult" { - result = *u.CreateAccountResult - ok = true - } +// MarshalBinary implements encoding.BinaryMarshaler. +func (s ScSpecUdtErrorEnumV0) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} - return +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *ScSpecUdtErrorEnumV0) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err } -// MustPaymentResult retrieves the PaymentResult value from the union, -// panicing if the value is not set. -func (u OperationResultTr) MustPaymentResult() PaymentResult { - val, ok := u.GetPaymentResult() +var ( + _ encoding.BinaryMarshaler = (*ScSpecUdtErrorEnumV0)(nil) + _ encoding.BinaryUnmarshaler = (*ScSpecUdtErrorEnumV0)(nil) +) - if !ok { - panic("arm PaymentResult is not set") - } +// xdrType signals that this type represents XDR values defined by this package. +func (s ScSpecUdtErrorEnumV0) xdrType() {} - return val -} +var _ xdrType = (*ScSpecUdtErrorEnumV0)(nil) -// GetPaymentResult retrieves the PaymentResult value from the union, -// returning ok if the union's switch indicated the value is valid. -func (u OperationResultTr) GetPaymentResult() (result PaymentResult, ok bool) { - armName, _ := u.ArmForSwitch(int32(u.Type)) +// ScSpecFunctionInputV0 is an XDR Struct defines as: +// +// struct SCSpecFunctionInputV0 +// { +// string doc; +// string name<30>; +// SCSpecTypeDef type; +// }; +type ScSpecFunctionInputV0 struct { + Doc string `xdrmaxsize:"1024"` + Name string `xdrmaxsize:"30"` + Type ScSpecTypeDef +} - if armName == "PaymentResult" { - result = *u.PaymentResult - ok = true +// EncodeTo encodes this value using the Encoder. +func (s *ScSpecFunctionInputV0) EncodeTo(e *xdr.Encoder) error { + var err error + if _, err = e.EncodeString(string(s.Doc)); err != nil { + return err } - - return + if _, err = e.EncodeString(string(s.Name)); err != nil { + return err + } + if err = s.Type.EncodeTo(e); err != nil { + return err + } + return nil } -// MustPathPaymentStrictReceiveResult retrieves the PathPaymentStrictReceiveResult value from the union, -// panicing if the value is not set. -func (u OperationResultTr) MustPathPaymentStrictReceiveResult() PathPaymentStrictReceiveResult { - val, ok := u.GetPathPaymentStrictReceiveResult() +var _ decoderFrom = (*ScSpecFunctionInputV0)(nil) - if !ok { - panic("arm PathPaymentStrictReceiveResult is not set") +// DecodeFrom decodes this value using the Decoder. +func (s *ScSpecFunctionInputV0) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding ScSpecFunctionInputV0: %w", ErrMaxDecodingDepthReached) } - - return val + maxDepth -= 1 + var err error + var n, nTmp int + s.Doc, nTmp, err = d.DecodeString(1024) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Doc: %w", err) + } + s.Name, nTmp, err = d.DecodeString(30) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Name: %w", err) + } + nTmp, err = s.Type.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ScSpecTypeDef: %w", err) + } + return n, nil } -// GetPathPaymentStrictReceiveResult retrieves the PathPaymentStrictReceiveResult value from the union, -// returning ok if the union's switch indicated the value is valid. -func (u OperationResultTr) GetPathPaymentStrictReceiveResult() (result PathPaymentStrictReceiveResult, ok bool) { - armName, _ := u.ArmForSwitch(int32(u.Type)) - - if armName == "PathPaymentStrictReceiveResult" { - result = *u.PathPaymentStrictReceiveResult - ok = true - } +// MarshalBinary implements encoding.BinaryMarshaler. +func (s ScSpecFunctionInputV0) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} - return +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *ScSpecFunctionInputV0) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err } -// MustManageSellOfferResult retrieves the ManageSellOfferResult value from the union, -// panicing if the value is not set. -func (u OperationResultTr) MustManageSellOfferResult() ManageSellOfferResult { - val, ok := u.GetManageSellOfferResult() +var ( + _ encoding.BinaryMarshaler = (*ScSpecFunctionInputV0)(nil) + _ encoding.BinaryUnmarshaler = (*ScSpecFunctionInputV0)(nil) +) - if !ok { - panic("arm ManageSellOfferResult is not set") - } +// xdrType signals that this type represents XDR values defined by this package. +func (s ScSpecFunctionInputV0) xdrType() {} - return val -} +var _ xdrType = (*ScSpecFunctionInputV0)(nil) -// GetManageSellOfferResult retrieves the ManageSellOfferResult value from the union, -// returning ok if the union's switch indicated the value is valid. -func (u OperationResultTr) GetManageSellOfferResult() (result ManageSellOfferResult, ok bool) { - armName, _ := u.ArmForSwitch(int32(u.Type)) +// ScSpecFunctionV0 is an XDR Struct defines as: +// +// struct SCSpecFunctionV0 +// { +// string doc; +// SCSymbol name; +// SCSpecFunctionInputV0 inputs<10>; +// SCSpecTypeDef outputs<1>; +// }; +type ScSpecFunctionV0 struct { + Doc string `xdrmaxsize:"1024"` + Name ScSymbol + Inputs []ScSpecFunctionInputV0 `xdrmaxsize:"10"` + Outputs []ScSpecTypeDef `xdrmaxsize:"1"` +} - if armName == "ManageSellOfferResult" { - result = *u.ManageSellOfferResult - ok = true +// EncodeTo encodes this value using the Encoder. +func (s *ScSpecFunctionV0) EncodeTo(e *xdr.Encoder) error { + var err error + if _, err = e.EncodeString(string(s.Doc)); err != nil { + return err } - - return + if err = s.Name.EncodeTo(e); err != nil { + return err + } + if _, err = e.EncodeUint(uint32(len(s.Inputs))); err != nil { + return err + } + for i := 0; i < len(s.Inputs); i++ { + if err = s.Inputs[i].EncodeTo(e); err != nil { + return err + } + } + if _, err = e.EncodeUint(uint32(len(s.Outputs))); err != nil { + return err + } + for i := 0; i < len(s.Outputs); i++ { + if err = s.Outputs[i].EncodeTo(e); err != nil { + return err + } + } + return nil } -// MustCreatePassiveSellOfferResult retrieves the CreatePassiveSellOfferResult value from the union, -// panicing if the value is not set. -func (u OperationResultTr) MustCreatePassiveSellOfferResult() ManageSellOfferResult { - val, ok := u.GetCreatePassiveSellOfferResult() +var _ decoderFrom = (*ScSpecFunctionV0)(nil) - if !ok { - panic("arm CreatePassiveSellOfferResult is not set") +// DecodeFrom decodes this value using the Decoder. +func (s *ScSpecFunctionV0) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding ScSpecFunctionV0: %w", ErrMaxDecodingDepthReached) } - - return val + maxDepth -= 1 + var err error + var n, nTmp int + s.Doc, nTmp, err = d.DecodeString(1024) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Doc: %w", err) + } + nTmp, err = s.Name.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ScSymbol: %w", err) + } + var l uint32 + l, nTmp, err = d.DecodeUint() + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ScSpecFunctionInputV0: %w", err) + } + if l > 10 { + return n, fmt.Errorf("decoding ScSpecFunctionInputV0: data size (%d) exceeds size limit (10)", l) + } + s.Inputs = nil + if l > 0 { + if il, ok := d.InputLen(); ok && uint(il) < uint(l) { + return n, fmt.Errorf("decoding ScSpecFunctionInputV0: length (%d) exceeds remaining input length (%d)", l, il) + } + s.Inputs = make([]ScSpecFunctionInputV0, l) + for i := uint32(0); i < l; i++ { + nTmp, err = s.Inputs[i].DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ScSpecFunctionInputV0: %w", err) + } + } + } + l, nTmp, err = d.DecodeUint() + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ScSpecTypeDef: %w", err) + } + if l > 1 { + return n, fmt.Errorf("decoding ScSpecTypeDef: data size (%d) exceeds size limit (1)", l) + } + s.Outputs = nil + if l > 0 { + if il, ok := d.InputLen(); ok && uint(il) < uint(l) { + return n, fmt.Errorf("decoding ScSpecTypeDef: length (%d) exceeds remaining input length (%d)", l, il) + } + s.Outputs = make([]ScSpecTypeDef, l) + for i := uint32(0); i < l; i++ { + nTmp, err = s.Outputs[i].DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ScSpecTypeDef: %w", err) + } + } + } + return n, nil } -// GetCreatePassiveSellOfferResult retrieves the CreatePassiveSellOfferResult value from the union, -// returning ok if the union's switch indicated the value is valid. -func (u OperationResultTr) GetCreatePassiveSellOfferResult() (result ManageSellOfferResult, ok bool) { - armName, _ := u.ArmForSwitch(int32(u.Type)) - - if armName == "CreatePassiveSellOfferResult" { - result = *u.CreatePassiveSellOfferResult - ok = true - } +// MarshalBinary implements encoding.BinaryMarshaler. +func (s ScSpecFunctionV0) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} - return +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *ScSpecFunctionV0) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err } -// MustSetOptionsResult retrieves the SetOptionsResult value from the union, -// panicing if the value is not set. -func (u OperationResultTr) MustSetOptionsResult() SetOptionsResult { - val, ok := u.GetSetOptionsResult() +var ( + _ encoding.BinaryMarshaler = (*ScSpecFunctionV0)(nil) + _ encoding.BinaryUnmarshaler = (*ScSpecFunctionV0)(nil) +) - if !ok { - panic("arm SetOptionsResult is not set") - } +// xdrType signals that this type represents XDR values defined by this package. +func (s ScSpecFunctionV0) xdrType() {} - return val -} +var _ xdrType = (*ScSpecFunctionV0)(nil) -// GetSetOptionsResult retrieves the SetOptionsResult value from the union, -// returning ok if the union's switch indicated the value is valid. -func (u OperationResultTr) GetSetOptionsResult() (result SetOptionsResult, ok bool) { - armName, _ := u.ArmForSwitch(int32(u.Type)) +// ScSpecEntryKind is an XDR Enum defines as: +// +// enum SCSpecEntryKind +// { +// SC_SPEC_ENTRY_FUNCTION_V0 = 0, +// SC_SPEC_ENTRY_UDT_STRUCT_V0 = 1, +// SC_SPEC_ENTRY_UDT_UNION_V0 = 2, +// SC_SPEC_ENTRY_UDT_ENUM_V0 = 3, +// SC_SPEC_ENTRY_UDT_ERROR_ENUM_V0 = 4 +// }; +type ScSpecEntryKind int32 - if armName == "SetOptionsResult" { - result = *u.SetOptionsResult - ok = true - } +const ( + ScSpecEntryKindScSpecEntryFunctionV0 ScSpecEntryKind = 0 + ScSpecEntryKindScSpecEntryUdtStructV0 ScSpecEntryKind = 1 + ScSpecEntryKindScSpecEntryUdtUnionV0 ScSpecEntryKind = 2 + ScSpecEntryKindScSpecEntryUdtEnumV0 ScSpecEntryKind = 3 + ScSpecEntryKindScSpecEntryUdtErrorEnumV0 ScSpecEntryKind = 4 +) - return +var scSpecEntryKindMap = map[int32]string{ + 0: "ScSpecEntryKindScSpecEntryFunctionV0", + 1: "ScSpecEntryKindScSpecEntryUdtStructV0", + 2: "ScSpecEntryKindScSpecEntryUdtUnionV0", + 3: "ScSpecEntryKindScSpecEntryUdtEnumV0", + 4: "ScSpecEntryKindScSpecEntryUdtErrorEnumV0", } -// MustChangeTrustResult retrieves the ChangeTrustResult value from the union, -// panicing if the value is not set. -func (u OperationResultTr) MustChangeTrustResult() ChangeTrustResult { - val, ok := u.GetChangeTrustResult() - - if !ok { - panic("arm ChangeTrustResult is not set") - } - - return val +// ValidEnum validates a proposed value for this enum. Implements +// the Enum interface for ScSpecEntryKind +func (e ScSpecEntryKind) ValidEnum(v int32) bool { + _, ok := scSpecEntryKindMap[v] + return ok } -// GetChangeTrustResult retrieves the ChangeTrustResult value from the union, -// returning ok if the union's switch indicated the value is valid. -func (u OperationResultTr) GetChangeTrustResult() (result ChangeTrustResult, ok bool) { - armName, _ := u.ArmForSwitch(int32(u.Type)) +// String returns the name of `e` +func (e ScSpecEntryKind) String() string { + name, _ := scSpecEntryKindMap[int32(e)] + return name +} - if armName == "ChangeTrustResult" { - result = *u.ChangeTrustResult - ok = true +// EncodeTo encodes this value using the Encoder. +func (e ScSpecEntryKind) EncodeTo(enc *xdr.Encoder) error { + if _, ok := scSpecEntryKindMap[int32(e)]; !ok { + return fmt.Errorf("'%d' is not a valid ScSpecEntryKind enum value", e) } - - return + _, err := enc.EncodeInt(int32(e)) + return err } -// MustAllowTrustResult retrieves the AllowTrustResult value from the union, -// panicing if the value is not set. -func (u OperationResultTr) MustAllowTrustResult() AllowTrustResult { - val, ok := u.GetAllowTrustResult() +var _ decoderFrom = (*ScSpecEntryKind)(nil) - if !ok { - panic("arm AllowTrustResult is not set") +// DecodeFrom decodes this value using the Decoder. +func (e *ScSpecEntryKind) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding ScSpecEntryKind: %w", ErrMaxDecodingDepthReached) } - - return val + maxDepth -= 1 + v, n, err := d.DecodeInt() + if err != nil { + return n, fmt.Errorf("decoding ScSpecEntryKind: %w", err) + } + if _, ok := scSpecEntryKindMap[v]; !ok { + return n, fmt.Errorf("'%d' is not a valid ScSpecEntryKind enum value", v) + } + *e = ScSpecEntryKind(v) + return n, nil } -// GetAllowTrustResult retrieves the AllowTrustResult value from the union, -// returning ok if the union's switch indicated the value is valid. -func (u OperationResultTr) GetAllowTrustResult() (result AllowTrustResult, ok bool) { - armName, _ := u.ArmForSwitch(int32(u.Type)) - - if armName == "AllowTrustResult" { - result = *u.AllowTrustResult - ok = true - } +// MarshalBinary implements encoding.BinaryMarshaler. +func (s ScSpecEntryKind) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} - return +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *ScSpecEntryKind) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err } -// MustAccountMergeResult retrieves the AccountMergeResult value from the union, -// panicing if the value is not set. -func (u OperationResultTr) MustAccountMergeResult() AccountMergeResult { - val, ok := u.GetAccountMergeResult() +var ( + _ encoding.BinaryMarshaler = (*ScSpecEntryKind)(nil) + _ encoding.BinaryUnmarshaler = (*ScSpecEntryKind)(nil) +) - if !ok { - panic("arm AccountMergeResult is not set") - } +// xdrType signals that this type represents XDR values defined by this package. +func (s ScSpecEntryKind) xdrType() {} - return val +var _ xdrType = (*ScSpecEntryKind)(nil) + +// ScSpecEntry is an XDR Union defines as: +// +// union SCSpecEntry switch (SCSpecEntryKind kind) +// { +// case SC_SPEC_ENTRY_FUNCTION_V0: +// SCSpecFunctionV0 functionV0; +// case SC_SPEC_ENTRY_UDT_STRUCT_V0: +// SCSpecUDTStructV0 udtStructV0; +// case SC_SPEC_ENTRY_UDT_UNION_V0: +// SCSpecUDTUnionV0 udtUnionV0; +// case SC_SPEC_ENTRY_UDT_ENUM_V0: +// SCSpecUDTEnumV0 udtEnumV0; +// case SC_SPEC_ENTRY_UDT_ERROR_ENUM_V0: +// SCSpecUDTErrorEnumV0 udtErrorEnumV0; +// }; +type ScSpecEntry struct { + Kind ScSpecEntryKind + FunctionV0 *ScSpecFunctionV0 + UdtStructV0 *ScSpecUdtStructV0 + UdtUnionV0 *ScSpecUdtUnionV0 + UdtEnumV0 *ScSpecUdtEnumV0 + UdtErrorEnumV0 *ScSpecUdtErrorEnumV0 } -// GetAccountMergeResult retrieves the AccountMergeResult value from the union, -// returning ok if the union's switch indicated the value is valid. -func (u OperationResultTr) GetAccountMergeResult() (result AccountMergeResult, ok bool) { - armName, _ := u.ArmForSwitch(int32(u.Type)) +// SwitchFieldName returns the field name in which this union's +// discriminant is stored +func (u ScSpecEntry) SwitchFieldName() string { + return "Kind" +} - if armName == "AccountMergeResult" { - result = *u.AccountMergeResult - ok = true +// ArmForSwitch returns which field name should be used for storing +// the value for an instance of ScSpecEntry +func (u ScSpecEntry) ArmForSwitch(sw int32) (string, bool) { + switch ScSpecEntryKind(sw) { + case ScSpecEntryKindScSpecEntryFunctionV0: + return "FunctionV0", true + case ScSpecEntryKindScSpecEntryUdtStructV0: + return "UdtStructV0", true + case ScSpecEntryKindScSpecEntryUdtUnionV0: + return "UdtUnionV0", true + case ScSpecEntryKindScSpecEntryUdtEnumV0: + return "UdtEnumV0", true + case ScSpecEntryKindScSpecEntryUdtErrorEnumV0: + return "UdtErrorEnumV0", true } + return "-", false +} +// NewScSpecEntry creates a new ScSpecEntry. +func NewScSpecEntry(kind ScSpecEntryKind, value interface{}) (result ScSpecEntry, err error) { + result.Kind = kind + switch ScSpecEntryKind(kind) { + case ScSpecEntryKindScSpecEntryFunctionV0: + tv, ok := value.(ScSpecFunctionV0) + if !ok { + err = errors.New("invalid value, must be ScSpecFunctionV0") + return + } + result.FunctionV0 = &tv + case ScSpecEntryKindScSpecEntryUdtStructV0: + tv, ok := value.(ScSpecUdtStructV0) + if !ok { + err = errors.New("invalid value, must be ScSpecUdtStructV0") + return + } + result.UdtStructV0 = &tv + case ScSpecEntryKindScSpecEntryUdtUnionV0: + tv, ok := value.(ScSpecUdtUnionV0) + if !ok { + err = errors.New("invalid value, must be ScSpecUdtUnionV0") + return + } + result.UdtUnionV0 = &tv + case ScSpecEntryKindScSpecEntryUdtEnumV0: + tv, ok := value.(ScSpecUdtEnumV0) + if !ok { + err = errors.New("invalid value, must be ScSpecUdtEnumV0") + return + } + result.UdtEnumV0 = &tv + case ScSpecEntryKindScSpecEntryUdtErrorEnumV0: + tv, ok := value.(ScSpecUdtErrorEnumV0) + if !ok { + err = errors.New("invalid value, must be ScSpecUdtErrorEnumV0") + return + } + result.UdtErrorEnumV0 = &tv + } return } -// MustInflationResult retrieves the InflationResult value from the union, +// MustFunctionV0 retrieves the FunctionV0 value from the union, // panicing if the value is not set. -func (u OperationResultTr) MustInflationResult() InflationResult { - val, ok := u.GetInflationResult() +func (u ScSpecEntry) MustFunctionV0() ScSpecFunctionV0 { + val, ok := u.GetFunctionV0() if !ok { - panic("arm InflationResult is not set") + panic("arm FunctionV0 is not set") } return val } -// GetInflationResult retrieves the InflationResult value from the union, +// GetFunctionV0 retrieves the FunctionV0 value from the union, // returning ok if the union's switch indicated the value is valid. -func (u OperationResultTr) GetInflationResult() (result InflationResult, ok bool) { - armName, _ := u.ArmForSwitch(int32(u.Type)) +func (u ScSpecEntry) GetFunctionV0() (result ScSpecFunctionV0, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Kind)) - if armName == "InflationResult" { - result = *u.InflationResult + if armName == "FunctionV0" { + result = *u.FunctionV0 ok = true } return } -// MustManageDataResult retrieves the ManageDataResult value from the union, +// MustUdtStructV0 retrieves the UdtStructV0 value from the union, // panicing if the value is not set. -func (u OperationResultTr) MustManageDataResult() ManageDataResult { - val, ok := u.GetManageDataResult() +func (u ScSpecEntry) MustUdtStructV0() ScSpecUdtStructV0 { + val, ok := u.GetUdtStructV0() if !ok { - panic("arm ManageDataResult is not set") + panic("arm UdtStructV0 is not set") } return val } -// GetManageDataResult retrieves the ManageDataResult value from the union, +// GetUdtStructV0 retrieves the UdtStructV0 value from the union, // returning ok if the union's switch indicated the value is valid. -func (u OperationResultTr) GetManageDataResult() (result ManageDataResult, ok bool) { - armName, _ := u.ArmForSwitch(int32(u.Type)) +func (u ScSpecEntry) GetUdtStructV0() (result ScSpecUdtStructV0, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Kind)) - if armName == "ManageDataResult" { - result = *u.ManageDataResult + if armName == "UdtStructV0" { + result = *u.UdtStructV0 ok = true } return } -// MustBumpSeqResult retrieves the BumpSeqResult value from the union, +// MustUdtUnionV0 retrieves the UdtUnionV0 value from the union, // panicing if the value is not set. -func (u OperationResultTr) MustBumpSeqResult() BumpSequenceResult { - val, ok := u.GetBumpSeqResult() +func (u ScSpecEntry) MustUdtUnionV0() ScSpecUdtUnionV0 { + val, ok := u.GetUdtUnionV0() if !ok { - panic("arm BumpSeqResult is not set") + panic("arm UdtUnionV0 is not set") } return val } -// GetBumpSeqResult retrieves the BumpSeqResult value from the union, +// GetUdtUnionV0 retrieves the UdtUnionV0 value from the union, // returning ok if the union's switch indicated the value is valid. -func (u OperationResultTr) GetBumpSeqResult() (result BumpSequenceResult, ok bool) { - armName, _ := u.ArmForSwitch(int32(u.Type)) +func (u ScSpecEntry) GetUdtUnionV0() (result ScSpecUdtUnionV0, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Kind)) - if armName == "BumpSeqResult" { - result = *u.BumpSeqResult + if armName == "UdtUnionV0" { + result = *u.UdtUnionV0 ok = true } return } -// MustManageBuyOfferResult retrieves the ManageBuyOfferResult value from the union, +// MustUdtEnumV0 retrieves the UdtEnumV0 value from the union, // panicing if the value is not set. -func (u OperationResultTr) MustManageBuyOfferResult() ManageBuyOfferResult { - val, ok := u.GetManageBuyOfferResult() +func (u ScSpecEntry) MustUdtEnumV0() ScSpecUdtEnumV0 { + val, ok := u.GetUdtEnumV0() if !ok { - panic("arm ManageBuyOfferResult is not set") + panic("arm UdtEnumV0 is not set") } return val } -// GetManageBuyOfferResult retrieves the ManageBuyOfferResult value from the union, +// GetUdtEnumV0 retrieves the UdtEnumV0 value from the union, // returning ok if the union's switch indicated the value is valid. -func (u OperationResultTr) GetManageBuyOfferResult() (result ManageBuyOfferResult, ok bool) { - armName, _ := u.ArmForSwitch(int32(u.Type)) +func (u ScSpecEntry) GetUdtEnumV0() (result ScSpecUdtEnumV0, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Kind)) - if armName == "ManageBuyOfferResult" { - result = *u.ManageBuyOfferResult + if armName == "UdtEnumV0" { + result = *u.UdtEnumV0 ok = true } return } -// MustPathPaymentStrictSendResult retrieves the PathPaymentStrictSendResult value from the union, +// MustUdtErrorEnumV0 retrieves the UdtErrorEnumV0 value from the union, // panicing if the value is not set. -func (u OperationResultTr) MustPathPaymentStrictSendResult() PathPaymentStrictSendResult { - val, ok := u.GetPathPaymentStrictSendResult() +func (u ScSpecEntry) MustUdtErrorEnumV0() ScSpecUdtErrorEnumV0 { + val, ok := u.GetUdtErrorEnumV0() if !ok { - panic("arm PathPaymentStrictSendResult is not set") + panic("arm UdtErrorEnumV0 is not set") } return val } -// GetPathPaymentStrictSendResult retrieves the PathPaymentStrictSendResult value from the union, +// GetUdtErrorEnumV0 retrieves the UdtErrorEnumV0 value from the union, // returning ok if the union's switch indicated the value is valid. -func (u OperationResultTr) GetPathPaymentStrictSendResult() (result PathPaymentStrictSendResult, ok bool) { - armName, _ := u.ArmForSwitch(int32(u.Type)) +func (u ScSpecEntry) GetUdtErrorEnumV0() (result ScSpecUdtErrorEnumV0, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Kind)) - if armName == "PathPaymentStrictSendResult" { - result = *u.PathPaymentStrictSendResult + if armName == "UdtErrorEnumV0" { + result = *u.UdtErrorEnumV0 ok = true } return } -// MustCreateClaimableBalanceResult retrieves the CreateClaimableBalanceResult value from the union, -// panicing if the value is not set. -func (u OperationResultTr) MustCreateClaimableBalanceResult() CreateClaimableBalanceResult { - val, ok := u.GetCreateClaimableBalanceResult() - - if !ok { - panic("arm CreateClaimableBalanceResult is not set") +// EncodeTo encodes this value using the Encoder. +func (u ScSpecEntry) EncodeTo(e *xdr.Encoder) error { + var err error + if err = u.Kind.EncodeTo(e); err != nil { + return err } - - return val + switch ScSpecEntryKind(u.Kind) { + case ScSpecEntryKindScSpecEntryFunctionV0: + if err = (*u.FunctionV0).EncodeTo(e); err != nil { + return err + } + return nil + case ScSpecEntryKindScSpecEntryUdtStructV0: + if err = (*u.UdtStructV0).EncodeTo(e); err != nil { + return err + } + return nil + case ScSpecEntryKindScSpecEntryUdtUnionV0: + if err = (*u.UdtUnionV0).EncodeTo(e); err != nil { + return err + } + return nil + case ScSpecEntryKindScSpecEntryUdtEnumV0: + if err = (*u.UdtEnumV0).EncodeTo(e); err != nil { + return err + } + return nil + case ScSpecEntryKindScSpecEntryUdtErrorEnumV0: + if err = (*u.UdtErrorEnumV0).EncodeTo(e); err != nil { + return err + } + return nil + } + return fmt.Errorf("Kind (ScSpecEntryKind) switch value '%d' is not valid for union ScSpecEntry", u.Kind) } -// GetCreateClaimableBalanceResult retrieves the CreateClaimableBalanceResult value from the union, -// returning ok if the union's switch indicated the value is valid. -func (u OperationResultTr) GetCreateClaimableBalanceResult() (result CreateClaimableBalanceResult, ok bool) { - armName, _ := u.ArmForSwitch(int32(u.Type)) +var _ decoderFrom = (*ScSpecEntry)(nil) - if armName == "CreateClaimableBalanceResult" { - result = *u.CreateClaimableBalanceResult - ok = true +// DecodeFrom decodes this value using the Decoder. +func (u *ScSpecEntry) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding ScSpecEntry: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + var err error + var n, nTmp int + nTmp, err = u.Kind.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ScSpecEntryKind: %w", err) + } + switch ScSpecEntryKind(u.Kind) { + case ScSpecEntryKindScSpecEntryFunctionV0: + u.FunctionV0 = new(ScSpecFunctionV0) + nTmp, err = (*u.FunctionV0).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ScSpecFunctionV0: %w", err) + } + return n, nil + case ScSpecEntryKindScSpecEntryUdtStructV0: + u.UdtStructV0 = new(ScSpecUdtStructV0) + nTmp, err = (*u.UdtStructV0).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ScSpecUdtStructV0: %w", err) + } + return n, nil + case ScSpecEntryKindScSpecEntryUdtUnionV0: + u.UdtUnionV0 = new(ScSpecUdtUnionV0) + nTmp, err = (*u.UdtUnionV0).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ScSpecUdtUnionV0: %w", err) + } + return n, nil + case ScSpecEntryKindScSpecEntryUdtEnumV0: + u.UdtEnumV0 = new(ScSpecUdtEnumV0) + nTmp, err = (*u.UdtEnumV0).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ScSpecUdtEnumV0: %w", err) + } + return n, nil + case ScSpecEntryKindScSpecEntryUdtErrorEnumV0: + u.UdtErrorEnumV0 = new(ScSpecUdtErrorEnumV0) + nTmp, err = (*u.UdtErrorEnumV0).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ScSpecUdtErrorEnumV0: %w", err) + } + return n, nil } + return n, fmt.Errorf("union ScSpecEntry has invalid Kind (ScSpecEntryKind) switch value '%d'", u.Kind) +} - return +// MarshalBinary implements encoding.BinaryMarshaler. +func (s ScSpecEntry) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err } -// MustClaimClaimableBalanceResult retrieves the ClaimClaimableBalanceResult value from the union, -// panicing if the value is not set. -func (u OperationResultTr) MustClaimClaimableBalanceResult() ClaimClaimableBalanceResult { - val, ok := u.GetClaimClaimableBalanceResult() +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *ScSpecEntry) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} - if !ok { - panic("arm ClaimClaimableBalanceResult is not set") - } +var ( + _ encoding.BinaryMarshaler = (*ScSpecEntry)(nil) + _ encoding.BinaryUnmarshaler = (*ScSpecEntry)(nil) +) - return val -} +// xdrType signals that this type represents XDR values defined by this package. +func (s ScSpecEntry) xdrType() {} -// GetClaimClaimableBalanceResult retrieves the ClaimClaimableBalanceResult value from the union, -// returning ok if the union's switch indicated the value is valid. -func (u OperationResultTr) GetClaimClaimableBalanceResult() (result ClaimClaimableBalanceResult, ok bool) { - armName, _ := u.ArmForSwitch(int32(u.Type)) +var _ xdrType = (*ScSpecEntry)(nil) - if armName == "ClaimClaimableBalanceResult" { - result = *u.ClaimClaimableBalanceResult - ok = true - } +// ScValType is an XDR Enum defines as: +// +// enum SCValType +// { +// SCV_BOOL = 0, +// SCV_VOID = 1, +// SCV_ERROR = 2, +// +// // 32 bits is the smallest type in WASM or XDR; no need for u8/u16. +// SCV_U32 = 3, +// SCV_I32 = 4, +// +// // 64 bits is naturally supported by both WASM and XDR also. +// SCV_U64 = 5, +// SCV_I64 = 6, +// +// // Time-related u64 subtypes with their own functions and formatting. +// SCV_TIMEPOINT = 7, +// SCV_DURATION = 8, +// +// // 128 bits is naturally supported by Rust and we use it for Soroban +// // fixed-point arithmetic prices / balances / similar "quantities". These +// // are represented in XDR as a pair of 2 u64s. +// SCV_U128 = 9, +// SCV_I128 = 10, +// +// // 256 bits is the size of sha256 output, ed25519 keys, and the EVM machine +// // word, so for interop use we include this even though it requires a small +// // amount of Rust guest and/or host library code. +// SCV_U256 = 11, +// SCV_I256 = 12, +// +// // Bytes come in 3 flavors, 2 of which have meaningfully different +// // formatting and validity-checking / domain-restriction. +// SCV_BYTES = 13, +// SCV_STRING = 14, +// SCV_SYMBOL = 15, +// +// // Vecs and maps are just polymorphic containers of other ScVals. +// SCV_VEC = 16, +// SCV_MAP = 17, +// +// // Address is the universal identifier for contracts and classic +// // accounts. +// SCV_ADDRESS = 18, +// +// // The following are the internal SCVal variants that are not +// // exposed to the contracts. +// SCV_CONTRACT_INSTANCE = 19, +// +// // SCV_LEDGER_KEY_CONTRACT_INSTANCE and SCV_LEDGER_KEY_NONCE are unique +// // symbolic SCVals used as the key for ledger entries for a contract's +// // instance and an address' nonce, respectively. +// SCV_LEDGER_KEY_CONTRACT_INSTANCE = 20, +// SCV_LEDGER_KEY_NONCE = 21 +// }; +type ScValType int32 - return +const ( + ScValTypeScvBool ScValType = 0 + ScValTypeScvVoid ScValType = 1 + ScValTypeScvError ScValType = 2 + ScValTypeScvU32 ScValType = 3 + ScValTypeScvI32 ScValType = 4 + ScValTypeScvU64 ScValType = 5 + ScValTypeScvI64 ScValType = 6 + ScValTypeScvTimepoint ScValType = 7 + ScValTypeScvDuration ScValType = 8 + ScValTypeScvU128 ScValType = 9 + ScValTypeScvI128 ScValType = 10 + ScValTypeScvU256 ScValType = 11 + ScValTypeScvI256 ScValType = 12 + ScValTypeScvBytes ScValType = 13 + ScValTypeScvString ScValType = 14 + ScValTypeScvSymbol ScValType = 15 + ScValTypeScvVec ScValType = 16 + ScValTypeScvMap ScValType = 17 + ScValTypeScvAddress ScValType = 18 + ScValTypeScvContractInstance ScValType = 19 + ScValTypeScvLedgerKeyContractInstance ScValType = 20 + ScValTypeScvLedgerKeyNonce ScValType = 21 +) + +var scValTypeMap = map[int32]string{ + 0: "ScValTypeScvBool", + 1: "ScValTypeScvVoid", + 2: "ScValTypeScvError", + 3: "ScValTypeScvU32", + 4: "ScValTypeScvI32", + 5: "ScValTypeScvU64", + 6: "ScValTypeScvI64", + 7: "ScValTypeScvTimepoint", + 8: "ScValTypeScvDuration", + 9: "ScValTypeScvU128", + 10: "ScValTypeScvI128", + 11: "ScValTypeScvU256", + 12: "ScValTypeScvI256", + 13: "ScValTypeScvBytes", + 14: "ScValTypeScvString", + 15: "ScValTypeScvSymbol", + 16: "ScValTypeScvVec", + 17: "ScValTypeScvMap", + 18: "ScValTypeScvAddress", + 19: "ScValTypeScvContractInstance", + 20: "ScValTypeScvLedgerKeyContractInstance", + 21: "ScValTypeScvLedgerKeyNonce", } -// MustBeginSponsoringFutureReservesResult retrieves the BeginSponsoringFutureReservesResult value from the union, -// panicing if the value is not set. -func (u OperationResultTr) MustBeginSponsoringFutureReservesResult() BeginSponsoringFutureReservesResult { - val, ok := u.GetBeginSponsoringFutureReservesResult() +// ValidEnum validates a proposed value for this enum. Implements +// the Enum interface for ScValType +func (e ScValType) ValidEnum(v int32) bool { + _, ok := scValTypeMap[v] + return ok +} - if !ok { - panic("arm BeginSponsoringFutureReservesResult is not set") - } +// String returns the name of `e` +func (e ScValType) String() string { + name, _ := scValTypeMap[int32(e)] + return name +} - return val +// EncodeTo encodes this value using the Encoder. +func (e ScValType) EncodeTo(enc *xdr.Encoder) error { + if _, ok := scValTypeMap[int32(e)]; !ok { + return fmt.Errorf("'%d' is not a valid ScValType enum value", e) + } + _, err := enc.EncodeInt(int32(e)) + return err } -// GetBeginSponsoringFutureReservesResult retrieves the BeginSponsoringFutureReservesResult value from the union, -// returning ok if the union's switch indicated the value is valid. -func (u OperationResultTr) GetBeginSponsoringFutureReservesResult() (result BeginSponsoringFutureReservesResult, ok bool) { - armName, _ := u.ArmForSwitch(int32(u.Type)) +var _ decoderFrom = (*ScValType)(nil) - if armName == "BeginSponsoringFutureReservesResult" { - result = *u.BeginSponsoringFutureReservesResult - ok = true +// DecodeFrom decodes this value using the Decoder. +func (e *ScValType) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding ScValType: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + v, n, err := d.DecodeInt() + if err != nil { + return n, fmt.Errorf("decoding ScValType: %w", err) } + if _, ok := scValTypeMap[v]; !ok { + return n, fmt.Errorf("'%d' is not a valid ScValType enum value", v) + } + *e = ScValType(v) + return n, nil +} - return +// MarshalBinary implements encoding.BinaryMarshaler. +func (s ScValType) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err } -// MustEndSponsoringFutureReservesResult retrieves the EndSponsoringFutureReservesResult value from the union, -// panicing if the value is not set. -func (u OperationResultTr) MustEndSponsoringFutureReservesResult() EndSponsoringFutureReservesResult { - val, ok := u.GetEndSponsoringFutureReservesResult() +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *ScValType) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} - if !ok { - panic("arm EndSponsoringFutureReservesResult is not set") - } +var ( + _ encoding.BinaryMarshaler = (*ScValType)(nil) + _ encoding.BinaryUnmarshaler = (*ScValType)(nil) +) - return val -} +// xdrType signals that this type represents XDR values defined by this package. +func (s ScValType) xdrType() {} -// GetEndSponsoringFutureReservesResult retrieves the EndSponsoringFutureReservesResult value from the union, -// returning ok if the union's switch indicated the value is valid. -func (u OperationResultTr) GetEndSponsoringFutureReservesResult() (result EndSponsoringFutureReservesResult, ok bool) { - armName, _ := u.ArmForSwitch(int32(u.Type)) +var _ xdrType = (*ScValType)(nil) - if armName == "EndSponsoringFutureReservesResult" { - result = *u.EndSponsoringFutureReservesResult - ok = true - } +// ScErrorType is an XDR Enum defines as: +// +// enum SCErrorType +// { +// SCE_CONTRACT = 0, // Contract-specific, user-defined codes. +// SCE_WASM_VM = 1, // Errors while interpreting WASM bytecode. +// SCE_CONTEXT = 2, // Errors in the contract's host context. +// SCE_STORAGE = 3, // Errors accessing host storage. +// SCE_OBJECT = 4, // Errors working with host objects. +// SCE_CRYPTO = 5, // Errors in cryptographic operations. +// SCE_EVENTS = 6, // Errors while emitting events. +// SCE_BUDGET = 7, // Errors relating to budget limits. +// SCE_VALUE = 8, // Errors working with host values or SCVals. +// SCE_AUTH = 9 // Errors from the authentication subsystem. +// }; +type ScErrorType int32 - return +const ( + ScErrorTypeSceContract ScErrorType = 0 + ScErrorTypeSceWasmVm ScErrorType = 1 + ScErrorTypeSceContext ScErrorType = 2 + ScErrorTypeSceStorage ScErrorType = 3 + ScErrorTypeSceObject ScErrorType = 4 + ScErrorTypeSceCrypto ScErrorType = 5 + ScErrorTypeSceEvents ScErrorType = 6 + ScErrorTypeSceBudget ScErrorType = 7 + ScErrorTypeSceValue ScErrorType = 8 + ScErrorTypeSceAuth ScErrorType = 9 +) + +var scErrorTypeMap = map[int32]string{ + 0: "ScErrorTypeSceContract", + 1: "ScErrorTypeSceWasmVm", + 2: "ScErrorTypeSceContext", + 3: "ScErrorTypeSceStorage", + 4: "ScErrorTypeSceObject", + 5: "ScErrorTypeSceCrypto", + 6: "ScErrorTypeSceEvents", + 7: "ScErrorTypeSceBudget", + 8: "ScErrorTypeSceValue", + 9: "ScErrorTypeSceAuth", } -// MustRevokeSponsorshipResult retrieves the RevokeSponsorshipResult value from the union, -// panicing if the value is not set. -func (u OperationResultTr) MustRevokeSponsorshipResult() RevokeSponsorshipResult { - val, ok := u.GetRevokeSponsorshipResult() +// ValidEnum validates a proposed value for this enum. Implements +// the Enum interface for ScErrorType +func (e ScErrorType) ValidEnum(v int32) bool { + _, ok := scErrorTypeMap[v] + return ok +} - if !ok { - panic("arm RevokeSponsorshipResult is not set") - } +// String returns the name of `e` +func (e ScErrorType) String() string { + name, _ := scErrorTypeMap[int32(e)] + return name +} - return val +// EncodeTo encodes this value using the Encoder. +func (e ScErrorType) EncodeTo(enc *xdr.Encoder) error { + if _, ok := scErrorTypeMap[int32(e)]; !ok { + return fmt.Errorf("'%d' is not a valid ScErrorType enum value", e) + } + _, err := enc.EncodeInt(int32(e)) + return err } -// GetRevokeSponsorshipResult retrieves the RevokeSponsorshipResult value from the union, -// returning ok if the union's switch indicated the value is valid. -func (u OperationResultTr) GetRevokeSponsorshipResult() (result RevokeSponsorshipResult, ok bool) { - armName, _ := u.ArmForSwitch(int32(u.Type)) +var _ decoderFrom = (*ScErrorType)(nil) - if armName == "RevokeSponsorshipResult" { - result = *u.RevokeSponsorshipResult - ok = true +// DecodeFrom decodes this value using the Decoder. +func (e *ScErrorType) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding ScErrorType: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + v, n, err := d.DecodeInt() + if err != nil { + return n, fmt.Errorf("decoding ScErrorType: %w", err) } + if _, ok := scErrorTypeMap[v]; !ok { + return n, fmt.Errorf("'%d' is not a valid ScErrorType enum value", v) + } + *e = ScErrorType(v) + return n, nil +} - return +// MarshalBinary implements encoding.BinaryMarshaler. +func (s ScErrorType) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err } -// MustClawbackResult retrieves the ClawbackResult value from the union, -// panicing if the value is not set. -func (u OperationResultTr) MustClawbackResult() ClawbackResult { - val, ok := u.GetClawbackResult() +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *ScErrorType) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} - if !ok { - panic("arm ClawbackResult is not set") - } +var ( + _ encoding.BinaryMarshaler = (*ScErrorType)(nil) + _ encoding.BinaryUnmarshaler = (*ScErrorType)(nil) +) - return val -} +// xdrType signals that this type represents XDR values defined by this package. +func (s ScErrorType) xdrType() {} -// GetClawbackResult retrieves the ClawbackResult value from the union, -// returning ok if the union's switch indicated the value is valid. -func (u OperationResultTr) GetClawbackResult() (result ClawbackResult, ok bool) { - armName, _ := u.ArmForSwitch(int32(u.Type)) +var _ xdrType = (*ScErrorType)(nil) - if armName == "ClawbackResult" { - result = *u.ClawbackResult - ok = true - } +// ScErrorCode is an XDR Enum defines as: +// +// enum SCErrorCode +// { +// SCEC_ARITH_DOMAIN = 0, // Some arithmetic was undefined (overflow, divide-by-zero). +// SCEC_INDEX_BOUNDS = 1, // Something was indexed beyond its bounds. +// SCEC_INVALID_INPUT = 2, // User provided some otherwise-bad data. +// SCEC_MISSING_VALUE = 3, // Some value was required but not provided. +// SCEC_EXISTING_VALUE = 4, // Some value was provided where not allowed. +// SCEC_EXCEEDED_LIMIT = 5, // Some arbitrary limit -- gas or otherwise -- was hit. +// SCEC_INVALID_ACTION = 6, // Data was valid but action requested was not. +// SCEC_INTERNAL_ERROR = 7, // The host detected an error in its own logic. +// SCEC_UNEXPECTED_TYPE = 8, // Some type wasn't as expected. +// SCEC_UNEXPECTED_SIZE = 9 // Something's size wasn't as expected. +// }; +type ScErrorCode int32 - return +const ( + ScErrorCodeScecArithDomain ScErrorCode = 0 + ScErrorCodeScecIndexBounds ScErrorCode = 1 + ScErrorCodeScecInvalidInput ScErrorCode = 2 + ScErrorCodeScecMissingValue ScErrorCode = 3 + ScErrorCodeScecExistingValue ScErrorCode = 4 + ScErrorCodeScecExceededLimit ScErrorCode = 5 + ScErrorCodeScecInvalidAction ScErrorCode = 6 + ScErrorCodeScecInternalError ScErrorCode = 7 + ScErrorCodeScecUnexpectedType ScErrorCode = 8 + ScErrorCodeScecUnexpectedSize ScErrorCode = 9 +) + +var scErrorCodeMap = map[int32]string{ + 0: "ScErrorCodeScecArithDomain", + 1: "ScErrorCodeScecIndexBounds", + 2: "ScErrorCodeScecInvalidInput", + 3: "ScErrorCodeScecMissingValue", + 4: "ScErrorCodeScecExistingValue", + 5: "ScErrorCodeScecExceededLimit", + 6: "ScErrorCodeScecInvalidAction", + 7: "ScErrorCodeScecInternalError", + 8: "ScErrorCodeScecUnexpectedType", + 9: "ScErrorCodeScecUnexpectedSize", } -// MustClawbackClaimableBalanceResult retrieves the ClawbackClaimableBalanceResult value from the union, -// panicing if the value is not set. -func (u OperationResultTr) MustClawbackClaimableBalanceResult() ClawbackClaimableBalanceResult { - val, ok := u.GetClawbackClaimableBalanceResult() +// ValidEnum validates a proposed value for this enum. Implements +// the Enum interface for ScErrorCode +func (e ScErrorCode) ValidEnum(v int32) bool { + _, ok := scErrorCodeMap[v] + return ok +} - if !ok { - panic("arm ClawbackClaimableBalanceResult is not set") - } +// String returns the name of `e` +func (e ScErrorCode) String() string { + name, _ := scErrorCodeMap[int32(e)] + return name +} - return val +// EncodeTo encodes this value using the Encoder. +func (e ScErrorCode) EncodeTo(enc *xdr.Encoder) error { + if _, ok := scErrorCodeMap[int32(e)]; !ok { + return fmt.Errorf("'%d' is not a valid ScErrorCode enum value", e) + } + _, err := enc.EncodeInt(int32(e)) + return err } -// GetClawbackClaimableBalanceResult retrieves the ClawbackClaimableBalanceResult value from the union, -// returning ok if the union's switch indicated the value is valid. -func (u OperationResultTr) GetClawbackClaimableBalanceResult() (result ClawbackClaimableBalanceResult, ok bool) { - armName, _ := u.ArmForSwitch(int32(u.Type)) +var _ decoderFrom = (*ScErrorCode)(nil) - if armName == "ClawbackClaimableBalanceResult" { - result = *u.ClawbackClaimableBalanceResult - ok = true +// DecodeFrom decodes this value using the Decoder. +func (e *ScErrorCode) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding ScErrorCode: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + v, n, err := d.DecodeInt() + if err != nil { + return n, fmt.Errorf("decoding ScErrorCode: %w", err) } + if _, ok := scErrorCodeMap[v]; !ok { + return n, fmt.Errorf("'%d' is not a valid ScErrorCode enum value", v) + } + *e = ScErrorCode(v) + return n, nil +} - return +// MarshalBinary implements encoding.BinaryMarshaler. +func (s ScErrorCode) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err } -// MustSetTrustLineFlagsResult retrieves the SetTrustLineFlagsResult value from the union, -// panicing if the value is not set. -func (u OperationResultTr) MustSetTrustLineFlagsResult() SetTrustLineFlagsResult { - val, ok := u.GetSetTrustLineFlagsResult() +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *ScErrorCode) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} - if !ok { - panic("arm SetTrustLineFlagsResult is not set") - } +var ( + _ encoding.BinaryMarshaler = (*ScErrorCode)(nil) + _ encoding.BinaryUnmarshaler = (*ScErrorCode)(nil) +) - return val +// xdrType signals that this type represents XDR values defined by this package. +func (s ScErrorCode) xdrType() {} + +var _ xdrType = (*ScErrorCode)(nil) + +// ScError is an XDR Union defines as: +// +// union SCError switch (SCErrorType type) +// { +// case SCE_CONTRACT: +// uint32 contractCode; +// case SCE_WASM_VM: +// case SCE_CONTEXT: +// case SCE_STORAGE: +// case SCE_OBJECT: +// case SCE_CRYPTO: +// case SCE_EVENTS: +// case SCE_BUDGET: +// case SCE_VALUE: +// case SCE_AUTH: +// SCErrorCode code; +// }; +type ScError struct { + Type ScErrorType + ContractCode *Uint32 + Code *ScErrorCode } -// GetSetTrustLineFlagsResult retrieves the SetTrustLineFlagsResult value from the union, -// returning ok if the union's switch indicated the value is valid. -func (u OperationResultTr) GetSetTrustLineFlagsResult() (result SetTrustLineFlagsResult, ok bool) { - armName, _ := u.ArmForSwitch(int32(u.Type)) +// SwitchFieldName returns the field name in which this union's +// discriminant is stored +func (u ScError) SwitchFieldName() string { + return "Type" +} - if armName == "SetTrustLineFlagsResult" { - result = *u.SetTrustLineFlagsResult - ok = true +// ArmForSwitch returns which field name should be used for storing +// the value for an instance of ScError +func (u ScError) ArmForSwitch(sw int32) (string, bool) { + switch ScErrorType(sw) { + case ScErrorTypeSceContract: + return "ContractCode", true + case ScErrorTypeSceWasmVm: + return "Code", true + case ScErrorTypeSceContext: + return "Code", true + case ScErrorTypeSceStorage: + return "Code", true + case ScErrorTypeSceObject: + return "Code", true + case ScErrorTypeSceCrypto: + return "Code", true + case ScErrorTypeSceEvents: + return "Code", true + case ScErrorTypeSceBudget: + return "Code", true + case ScErrorTypeSceValue: + return "Code", true + case ScErrorTypeSceAuth: + return "Code", true } + return "-", false +} +// NewScError creates a new ScError. +func NewScError(aType ScErrorType, value interface{}) (result ScError, err error) { + result.Type = aType + switch ScErrorType(aType) { + case ScErrorTypeSceContract: + tv, ok := value.(Uint32) + if !ok { + err = errors.New("invalid value, must be Uint32") + return + } + result.ContractCode = &tv + case ScErrorTypeSceWasmVm: + tv, ok := value.(ScErrorCode) + if !ok { + err = errors.New("invalid value, must be ScErrorCode") + return + } + result.Code = &tv + case ScErrorTypeSceContext: + tv, ok := value.(ScErrorCode) + if !ok { + err = errors.New("invalid value, must be ScErrorCode") + return + } + result.Code = &tv + case ScErrorTypeSceStorage: + tv, ok := value.(ScErrorCode) + if !ok { + err = errors.New("invalid value, must be ScErrorCode") + return + } + result.Code = &tv + case ScErrorTypeSceObject: + tv, ok := value.(ScErrorCode) + if !ok { + err = errors.New("invalid value, must be ScErrorCode") + return + } + result.Code = &tv + case ScErrorTypeSceCrypto: + tv, ok := value.(ScErrorCode) + if !ok { + err = errors.New("invalid value, must be ScErrorCode") + return + } + result.Code = &tv + case ScErrorTypeSceEvents: + tv, ok := value.(ScErrorCode) + if !ok { + err = errors.New("invalid value, must be ScErrorCode") + return + } + result.Code = &tv + case ScErrorTypeSceBudget: + tv, ok := value.(ScErrorCode) + if !ok { + err = errors.New("invalid value, must be ScErrorCode") + return + } + result.Code = &tv + case ScErrorTypeSceValue: + tv, ok := value.(ScErrorCode) + if !ok { + err = errors.New("invalid value, must be ScErrorCode") + return + } + result.Code = &tv + case ScErrorTypeSceAuth: + tv, ok := value.(ScErrorCode) + if !ok { + err = errors.New("invalid value, must be ScErrorCode") + return + } + result.Code = &tv + } return } -// MustLiquidityPoolDepositResult retrieves the LiquidityPoolDepositResult value from the union, +// MustContractCode retrieves the ContractCode value from the union, // panicing if the value is not set. -func (u OperationResultTr) MustLiquidityPoolDepositResult() LiquidityPoolDepositResult { - val, ok := u.GetLiquidityPoolDepositResult() +func (u ScError) MustContractCode() Uint32 { + val, ok := u.GetContractCode() if !ok { - panic("arm LiquidityPoolDepositResult is not set") + panic("arm ContractCode is not set") } return val } -// GetLiquidityPoolDepositResult retrieves the LiquidityPoolDepositResult value from the union, +// GetContractCode retrieves the ContractCode value from the union, // returning ok if the union's switch indicated the value is valid. -func (u OperationResultTr) GetLiquidityPoolDepositResult() (result LiquidityPoolDepositResult, ok bool) { +func (u ScError) GetContractCode() (result Uint32, ok bool) { armName, _ := u.ArmForSwitch(int32(u.Type)) - if armName == "LiquidityPoolDepositResult" { - result = *u.LiquidityPoolDepositResult + if armName == "ContractCode" { + result = *u.ContractCode ok = true } return } -// MustLiquidityPoolWithdrawResult retrieves the LiquidityPoolWithdrawResult value from the union, +// MustCode retrieves the Code value from the union, // panicing if the value is not set. -func (u OperationResultTr) MustLiquidityPoolWithdrawResult() LiquidityPoolWithdrawResult { - val, ok := u.GetLiquidityPoolWithdrawResult() +func (u ScError) MustCode() ScErrorCode { + val, ok := u.GetCode() if !ok { - panic("arm LiquidityPoolWithdrawResult is not set") + panic("arm Code is not set") } return val } -// GetLiquidityPoolWithdrawResult retrieves the LiquidityPoolWithdrawResult value from the union, +// GetCode retrieves the Code value from the union, // returning ok if the union's switch indicated the value is valid. -func (u OperationResultTr) GetLiquidityPoolWithdrawResult() (result LiquidityPoolWithdrawResult, ok bool) { +func (u ScError) GetCode() (result ScErrorCode, ok bool) { armName, _ := u.ArmForSwitch(int32(u.Type)) - if armName == "LiquidityPoolWithdrawResult" { - result = *u.LiquidityPoolWithdrawResult + if armName == "Code" { + result = *u.Code ok = true } @@ -34476,346 +50893,410 @@ func (u OperationResultTr) GetLiquidityPoolWithdrawResult() (result LiquidityPoo } // EncodeTo encodes this value using the Encoder. -func (u OperationResultTr) EncodeTo(e *xdr.Encoder) error { +func (u ScError) EncodeTo(e *xdr.Encoder) error { var err error if err = u.Type.EncodeTo(e); err != nil { return err } - switch OperationType(u.Type) { - case OperationTypeCreateAccount: - if err = (*u.CreateAccountResult).EncodeTo(e); err != nil { - return err - } - return nil - case OperationTypePayment: - if err = (*u.PaymentResult).EncodeTo(e); err != nil { - return err - } - return nil - case OperationTypePathPaymentStrictReceive: - if err = (*u.PathPaymentStrictReceiveResult).EncodeTo(e); err != nil { - return err - } - return nil - case OperationTypeManageSellOffer: - if err = (*u.ManageSellOfferResult).EncodeTo(e); err != nil { - return err - } - return nil - case OperationTypeCreatePassiveSellOffer: - if err = (*u.CreatePassiveSellOfferResult).EncodeTo(e); err != nil { - return err - } - return nil - case OperationTypeSetOptions: - if err = (*u.SetOptionsResult).EncodeTo(e); err != nil { - return err - } - return nil - case OperationTypeChangeTrust: - if err = (*u.ChangeTrustResult).EncodeTo(e); err != nil { - return err - } - return nil - case OperationTypeAllowTrust: - if err = (*u.AllowTrustResult).EncodeTo(e); err != nil { - return err - } - return nil - case OperationTypeAccountMerge: - if err = (*u.AccountMergeResult).EncodeTo(e); err != nil { - return err - } - return nil - case OperationTypeInflation: - if err = (*u.InflationResult).EncodeTo(e); err != nil { - return err - } - return nil - case OperationTypeManageData: - if err = (*u.ManageDataResult).EncodeTo(e); err != nil { - return err - } - return nil - case OperationTypeBumpSequence: - if err = (*u.BumpSeqResult).EncodeTo(e); err != nil { - return err - } - return nil - case OperationTypeManageBuyOffer: - if err = (*u.ManageBuyOfferResult).EncodeTo(e); err != nil { - return err - } - return nil - case OperationTypePathPaymentStrictSend: - if err = (*u.PathPaymentStrictSendResult).EncodeTo(e); err != nil { - return err - } - return nil - case OperationTypeCreateClaimableBalance: - if err = (*u.CreateClaimableBalanceResult).EncodeTo(e); err != nil { + switch ScErrorType(u.Type) { + case ScErrorTypeSceContract: + if err = (*u.ContractCode).EncodeTo(e); err != nil { return err } return nil - case OperationTypeClaimClaimableBalance: - if err = (*u.ClaimClaimableBalanceResult).EncodeTo(e); err != nil { + case ScErrorTypeSceWasmVm: + if err = (*u.Code).EncodeTo(e); err != nil { return err } return nil - case OperationTypeBeginSponsoringFutureReserves: - if err = (*u.BeginSponsoringFutureReservesResult).EncodeTo(e); err != nil { + case ScErrorTypeSceContext: + if err = (*u.Code).EncodeTo(e); err != nil { return err } return nil - case OperationTypeEndSponsoringFutureReserves: - if err = (*u.EndSponsoringFutureReservesResult).EncodeTo(e); err != nil { + case ScErrorTypeSceStorage: + if err = (*u.Code).EncodeTo(e); err != nil { return err } return nil - case OperationTypeRevokeSponsorship: - if err = (*u.RevokeSponsorshipResult).EncodeTo(e); err != nil { + case ScErrorTypeSceObject: + if err = (*u.Code).EncodeTo(e); err != nil { return err } return nil - case OperationTypeClawback: - if err = (*u.ClawbackResult).EncodeTo(e); err != nil { + case ScErrorTypeSceCrypto: + if err = (*u.Code).EncodeTo(e); err != nil { return err } return nil - case OperationTypeClawbackClaimableBalance: - if err = (*u.ClawbackClaimableBalanceResult).EncodeTo(e); err != nil { + case ScErrorTypeSceEvents: + if err = (*u.Code).EncodeTo(e); err != nil { return err } return nil - case OperationTypeSetTrustLineFlags: - if err = (*u.SetTrustLineFlagsResult).EncodeTo(e); err != nil { + case ScErrorTypeSceBudget: + if err = (*u.Code).EncodeTo(e); err != nil { return err } return nil - case OperationTypeLiquidityPoolDeposit: - if err = (*u.LiquidityPoolDepositResult).EncodeTo(e); err != nil { + case ScErrorTypeSceValue: + if err = (*u.Code).EncodeTo(e); err != nil { return err } return nil - case OperationTypeLiquidityPoolWithdraw: - if err = (*u.LiquidityPoolWithdrawResult).EncodeTo(e); err != nil { + case ScErrorTypeSceAuth: + if err = (*u.Code).EncodeTo(e); err != nil { return err } return nil } - return fmt.Errorf("Type (OperationType) switch value '%d' is not valid for union OperationResultTr", u.Type) + return fmt.Errorf("Type (ScErrorType) switch value '%d' is not valid for union ScError", u.Type) } -var _ decoderFrom = (*OperationResultTr)(nil) +var _ decoderFrom = (*ScError)(nil) // DecodeFrom decodes this value using the Decoder. -func (u *OperationResultTr) DecodeFrom(d *xdr.Decoder) (int, error) { +func (u *ScError) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding ScError: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = u.Type.DecodeFrom(d) + nTmp, err = u.Type.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding OperationType: %s", err) + return n, fmt.Errorf("decoding ScErrorType: %w", err) } - switch OperationType(u.Type) { - case OperationTypeCreateAccount: - u.CreateAccountResult = new(CreateAccountResult) - nTmp, err = (*u.CreateAccountResult).DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding CreateAccountResult: %s", err) - } - return n, nil - case OperationTypePayment: - u.PaymentResult = new(PaymentResult) - nTmp, err = (*u.PaymentResult).DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding PaymentResult: %s", err) - } - return n, nil - case OperationTypePathPaymentStrictReceive: - u.PathPaymentStrictReceiveResult = new(PathPaymentStrictReceiveResult) - nTmp, err = (*u.PathPaymentStrictReceiveResult).DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding PathPaymentStrictReceiveResult: %s", err) - } - return n, nil - case OperationTypeManageSellOffer: - u.ManageSellOfferResult = new(ManageSellOfferResult) - nTmp, err = (*u.ManageSellOfferResult).DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding ManageSellOfferResult: %s", err) - } - return n, nil - case OperationTypeCreatePassiveSellOffer: - u.CreatePassiveSellOfferResult = new(ManageSellOfferResult) - nTmp, err = (*u.CreatePassiveSellOfferResult).DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding ManageSellOfferResult: %s", err) - } - return n, nil - case OperationTypeSetOptions: - u.SetOptionsResult = new(SetOptionsResult) - nTmp, err = (*u.SetOptionsResult).DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding SetOptionsResult: %s", err) - } - return n, nil - case OperationTypeChangeTrust: - u.ChangeTrustResult = new(ChangeTrustResult) - nTmp, err = (*u.ChangeTrustResult).DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding ChangeTrustResult: %s", err) - } - return n, nil - case OperationTypeAllowTrust: - u.AllowTrustResult = new(AllowTrustResult) - nTmp, err = (*u.AllowTrustResult).DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding AllowTrustResult: %s", err) - } - return n, nil - case OperationTypeAccountMerge: - u.AccountMergeResult = new(AccountMergeResult) - nTmp, err = (*u.AccountMergeResult).DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding AccountMergeResult: %s", err) - } - return n, nil - case OperationTypeInflation: - u.InflationResult = new(InflationResult) - nTmp, err = (*u.InflationResult).DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding InflationResult: %s", err) - } - return n, nil - case OperationTypeManageData: - u.ManageDataResult = new(ManageDataResult) - nTmp, err = (*u.ManageDataResult).DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding ManageDataResult: %s", err) - } - return n, nil - case OperationTypeBumpSequence: - u.BumpSeqResult = new(BumpSequenceResult) - nTmp, err = (*u.BumpSeqResult).DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding BumpSequenceResult: %s", err) - } - return n, nil - case OperationTypeManageBuyOffer: - u.ManageBuyOfferResult = new(ManageBuyOfferResult) - nTmp, err = (*u.ManageBuyOfferResult).DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding ManageBuyOfferResult: %s", err) - } - return n, nil - case OperationTypePathPaymentStrictSend: - u.PathPaymentStrictSendResult = new(PathPaymentStrictSendResult) - nTmp, err = (*u.PathPaymentStrictSendResult).DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding PathPaymentStrictSendResult: %s", err) - } - return n, nil - case OperationTypeCreateClaimableBalance: - u.CreateClaimableBalanceResult = new(CreateClaimableBalanceResult) - nTmp, err = (*u.CreateClaimableBalanceResult).DecodeFrom(d) + switch ScErrorType(u.Type) { + case ScErrorTypeSceContract: + u.ContractCode = new(Uint32) + nTmp, err = (*u.ContractCode).DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding CreateClaimableBalanceResult: %s", err) + return n, fmt.Errorf("decoding Uint32: %w", err) } return n, nil - case OperationTypeClaimClaimableBalance: - u.ClaimClaimableBalanceResult = new(ClaimClaimableBalanceResult) - nTmp, err = (*u.ClaimClaimableBalanceResult).DecodeFrom(d) + case ScErrorTypeSceWasmVm: + u.Code = new(ScErrorCode) + nTmp, err = (*u.Code).DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding ClaimClaimableBalanceResult: %s", err) + return n, fmt.Errorf("decoding ScErrorCode: %w", err) } return n, nil - case OperationTypeBeginSponsoringFutureReserves: - u.BeginSponsoringFutureReservesResult = new(BeginSponsoringFutureReservesResult) - nTmp, err = (*u.BeginSponsoringFutureReservesResult).DecodeFrom(d) + case ScErrorTypeSceContext: + u.Code = new(ScErrorCode) + nTmp, err = (*u.Code).DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding BeginSponsoringFutureReservesResult: %s", err) + return n, fmt.Errorf("decoding ScErrorCode: %w", err) } return n, nil - case OperationTypeEndSponsoringFutureReserves: - u.EndSponsoringFutureReservesResult = new(EndSponsoringFutureReservesResult) - nTmp, err = (*u.EndSponsoringFutureReservesResult).DecodeFrom(d) + case ScErrorTypeSceStorage: + u.Code = new(ScErrorCode) + nTmp, err = (*u.Code).DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding EndSponsoringFutureReservesResult: %s", err) + return n, fmt.Errorf("decoding ScErrorCode: %w", err) } return n, nil - case OperationTypeRevokeSponsorship: - u.RevokeSponsorshipResult = new(RevokeSponsorshipResult) - nTmp, err = (*u.RevokeSponsorshipResult).DecodeFrom(d) + case ScErrorTypeSceObject: + u.Code = new(ScErrorCode) + nTmp, err = (*u.Code).DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding RevokeSponsorshipResult: %s", err) + return n, fmt.Errorf("decoding ScErrorCode: %w", err) } return n, nil - case OperationTypeClawback: - u.ClawbackResult = new(ClawbackResult) - nTmp, err = (*u.ClawbackResult).DecodeFrom(d) + case ScErrorTypeSceCrypto: + u.Code = new(ScErrorCode) + nTmp, err = (*u.Code).DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding ClawbackResult: %s", err) + return n, fmt.Errorf("decoding ScErrorCode: %w", err) } return n, nil - case OperationTypeClawbackClaimableBalance: - u.ClawbackClaimableBalanceResult = new(ClawbackClaimableBalanceResult) - nTmp, err = (*u.ClawbackClaimableBalanceResult).DecodeFrom(d) + case ScErrorTypeSceEvents: + u.Code = new(ScErrorCode) + nTmp, err = (*u.Code).DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding ClawbackClaimableBalanceResult: %s", err) + return n, fmt.Errorf("decoding ScErrorCode: %w", err) } return n, nil - case OperationTypeSetTrustLineFlags: - u.SetTrustLineFlagsResult = new(SetTrustLineFlagsResult) - nTmp, err = (*u.SetTrustLineFlagsResult).DecodeFrom(d) + case ScErrorTypeSceBudget: + u.Code = new(ScErrorCode) + nTmp, err = (*u.Code).DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding SetTrustLineFlagsResult: %s", err) + return n, fmt.Errorf("decoding ScErrorCode: %w", err) } return n, nil - case OperationTypeLiquidityPoolDeposit: - u.LiquidityPoolDepositResult = new(LiquidityPoolDepositResult) - nTmp, err = (*u.LiquidityPoolDepositResult).DecodeFrom(d) + case ScErrorTypeSceValue: + u.Code = new(ScErrorCode) + nTmp, err = (*u.Code).DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding LiquidityPoolDepositResult: %s", err) + return n, fmt.Errorf("decoding ScErrorCode: %w", err) } return n, nil - case OperationTypeLiquidityPoolWithdraw: - u.LiquidityPoolWithdrawResult = new(LiquidityPoolWithdrawResult) - nTmp, err = (*u.LiquidityPoolWithdrawResult).DecodeFrom(d) + case ScErrorTypeSceAuth: + u.Code = new(ScErrorCode) + nTmp, err = (*u.Code).DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding LiquidityPoolWithdrawResult: %s", err) + return n, fmt.Errorf("decoding ScErrorCode: %w", err) } return n, nil } - return n, fmt.Errorf("union OperationResultTr has invalid Type (OperationType) switch value '%d'", u.Type) + return n, fmt.Errorf("union ScError has invalid Type (ScErrorType) switch value '%d'", u.Type) +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (s ScError) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *ScError) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} + +var ( + _ encoding.BinaryMarshaler = (*ScError)(nil) + _ encoding.BinaryUnmarshaler = (*ScError)(nil) +) + +// xdrType signals that this type represents XDR values defined by this package. +func (s ScError) xdrType() {} + +var _ xdrType = (*ScError)(nil) + +// UInt128Parts is an XDR Struct defines as: +// +// struct UInt128Parts { +// uint64 hi; +// uint64 lo; +// }; +type UInt128Parts struct { + Hi Uint64 + Lo Uint64 +} + +// EncodeTo encodes this value using the Encoder. +func (s *UInt128Parts) EncodeTo(e *xdr.Encoder) error { + var err error + if err = s.Hi.EncodeTo(e); err != nil { + return err + } + if err = s.Lo.EncodeTo(e); err != nil { + return err + } + return nil +} + +var _ decoderFrom = (*UInt128Parts)(nil) + +// DecodeFrom decodes this value using the Decoder. +func (s *UInt128Parts) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding UInt128Parts: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + var err error + var n, nTmp int + nTmp, err = s.Hi.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Uint64: %w", err) + } + nTmp, err = s.Lo.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Uint64: %w", err) + } + return n, nil +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (s UInt128Parts) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *UInt128Parts) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} + +var ( + _ encoding.BinaryMarshaler = (*UInt128Parts)(nil) + _ encoding.BinaryUnmarshaler = (*UInt128Parts)(nil) +) + +// xdrType signals that this type represents XDR values defined by this package. +func (s UInt128Parts) xdrType() {} + +var _ xdrType = (*UInt128Parts)(nil) + +// Int128Parts is an XDR Struct defines as: +// +// struct Int128Parts { +// int64 hi; +// uint64 lo; +// }; +type Int128Parts struct { + Hi Int64 + Lo Uint64 +} + +// EncodeTo encodes this value using the Encoder. +func (s *Int128Parts) EncodeTo(e *xdr.Encoder) error { + var err error + if err = s.Hi.EncodeTo(e); err != nil { + return err + } + if err = s.Lo.EncodeTo(e); err != nil { + return err + } + return nil +} + +var _ decoderFrom = (*Int128Parts)(nil) + +// DecodeFrom decodes this value using the Decoder. +func (s *Int128Parts) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding Int128Parts: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + var err error + var n, nTmp int + nTmp, err = s.Hi.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Int64: %w", err) + } + nTmp, err = s.Lo.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Uint64: %w", err) + } + return n, nil +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (s Int128Parts) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *Int128Parts) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} + +var ( + _ encoding.BinaryMarshaler = (*Int128Parts)(nil) + _ encoding.BinaryUnmarshaler = (*Int128Parts)(nil) +) + +// xdrType signals that this type represents XDR values defined by this package. +func (s Int128Parts) xdrType() {} + +var _ xdrType = (*Int128Parts)(nil) + +// UInt256Parts is an XDR Struct defines as: +// +// struct UInt256Parts { +// uint64 hi_hi; +// uint64 hi_lo; +// uint64 lo_hi; +// uint64 lo_lo; +// }; +type UInt256Parts struct { + HiHi Uint64 + HiLo Uint64 + LoHi Uint64 + LoLo Uint64 +} + +// EncodeTo encodes this value using the Encoder. +func (s *UInt256Parts) EncodeTo(e *xdr.Encoder) error { + var err error + if err = s.HiHi.EncodeTo(e); err != nil { + return err + } + if err = s.HiLo.EncodeTo(e); err != nil { + return err + } + if err = s.LoHi.EncodeTo(e); err != nil { + return err + } + if err = s.LoLo.EncodeTo(e); err != nil { + return err + } + return nil +} + +var _ decoderFrom = (*UInt256Parts)(nil) + +// DecodeFrom decodes this value using the Decoder. +func (s *UInt256Parts) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding UInt256Parts: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + var err error + var n, nTmp int + nTmp, err = s.HiHi.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Uint64: %w", err) + } + nTmp, err = s.HiLo.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Uint64: %w", err) + } + nTmp, err = s.LoHi.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Uint64: %w", err) + } + nTmp, err = s.LoLo.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Uint64: %w", err) + } + return n, nil } // MarshalBinary implements encoding.BinaryMarshaler. -func (s OperationResultTr) MarshalBinary() ([]byte, error) { +func (s UInt256Parts) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -34823,168 +51304,275 @@ func (s OperationResultTr) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *OperationResultTr) UnmarshalBinary(inp []byte) error { +func (s *UInt256Parts) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*OperationResultTr)(nil) - _ encoding.BinaryUnmarshaler = (*OperationResultTr)(nil) + _ encoding.BinaryMarshaler = (*UInt256Parts)(nil) + _ encoding.BinaryUnmarshaler = (*UInt256Parts)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s OperationResultTr) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s UInt256Parts) xdrType() {} -var _ xdrType = (*OperationResultTr)(nil) +var _ xdrType = (*UInt256Parts)(nil) -// OperationResult is an XDR Union defines as: +// Int256Parts is an XDR Struct defines as: // -// union OperationResult switch (OperationResultCode code) +// struct Int256Parts { +// int64 hi_hi; +// uint64 hi_lo; +// uint64 lo_hi; +// uint64 lo_lo; +// }; +type Int256Parts struct { + HiHi Int64 + HiLo Uint64 + LoHi Uint64 + LoLo Uint64 +} + +// EncodeTo encodes this value using the Encoder. +func (s *Int256Parts) EncodeTo(e *xdr.Encoder) error { + var err error + if err = s.HiHi.EncodeTo(e); err != nil { + return err + } + if err = s.HiLo.EncodeTo(e); err != nil { + return err + } + if err = s.LoHi.EncodeTo(e); err != nil { + return err + } + if err = s.LoLo.EncodeTo(e); err != nil { + return err + } + return nil +} + +var _ decoderFrom = (*Int256Parts)(nil) + +// DecodeFrom decodes this value using the Decoder. +func (s *Int256Parts) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding Int256Parts: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + var err error + var n, nTmp int + nTmp, err = s.HiHi.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Int64: %w", err) + } + nTmp, err = s.HiLo.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Uint64: %w", err) + } + nTmp, err = s.LoHi.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Uint64: %w", err) + } + nTmp, err = s.LoLo.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Uint64: %w", err) + } + return n, nil +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (s Int256Parts) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *Int256Parts) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} + +var ( + _ encoding.BinaryMarshaler = (*Int256Parts)(nil) + _ encoding.BinaryUnmarshaler = (*Int256Parts)(nil) +) + +// xdrType signals that this type represents XDR values defined by this package. +func (s Int256Parts) xdrType() {} + +var _ xdrType = (*Int256Parts)(nil) + +// ContractExecutableType is an XDR Enum defines as: +// +// enum ContractExecutableType // { -// case opINNER: -// union switch (OperationType type) -// { -// case CREATE_ACCOUNT: -// CreateAccountResult createAccountResult; -// case PAYMENT: -// PaymentResult paymentResult; -// case PATH_PAYMENT_STRICT_RECEIVE: -// PathPaymentStrictReceiveResult pathPaymentStrictReceiveResult; -// case MANAGE_SELL_OFFER: -// ManageSellOfferResult manageSellOfferResult; -// case CREATE_PASSIVE_SELL_OFFER: -// ManageSellOfferResult createPassiveSellOfferResult; -// case SET_OPTIONS: -// SetOptionsResult setOptionsResult; -// case CHANGE_TRUST: -// ChangeTrustResult changeTrustResult; -// case ALLOW_TRUST: -// AllowTrustResult allowTrustResult; -// case ACCOUNT_MERGE: -// AccountMergeResult accountMergeResult; -// case INFLATION: -// InflationResult inflationResult; -// case MANAGE_DATA: -// ManageDataResult manageDataResult; -// case BUMP_SEQUENCE: -// BumpSequenceResult bumpSeqResult; -// case MANAGE_BUY_OFFER: -// ManageBuyOfferResult manageBuyOfferResult; -// case PATH_PAYMENT_STRICT_SEND: -// PathPaymentStrictSendResult pathPaymentStrictSendResult; -// case CREATE_CLAIMABLE_BALANCE: -// CreateClaimableBalanceResult createClaimableBalanceResult; -// case CLAIM_CLAIMABLE_BALANCE: -// ClaimClaimableBalanceResult claimClaimableBalanceResult; -// case BEGIN_SPONSORING_FUTURE_RESERVES: -// BeginSponsoringFutureReservesResult beginSponsoringFutureReservesResult; -// case END_SPONSORING_FUTURE_RESERVES: -// EndSponsoringFutureReservesResult endSponsoringFutureReservesResult; -// case REVOKE_SPONSORSHIP: -// RevokeSponsorshipResult revokeSponsorshipResult; -// case CLAWBACK: -// ClawbackResult clawbackResult; -// case CLAWBACK_CLAIMABLE_BALANCE: -// ClawbackClaimableBalanceResult clawbackClaimableBalanceResult; -// case SET_TRUST_LINE_FLAGS: -// SetTrustLineFlagsResult setTrustLineFlagsResult; -// case LIQUIDITY_POOL_DEPOSIT: -// LiquidityPoolDepositResult liquidityPoolDepositResult; -// case LIQUIDITY_POOL_WITHDRAW: -// LiquidityPoolWithdrawResult liquidityPoolWithdrawResult; -// } -// tr; -// case opBAD_AUTH: -// case opNO_ACCOUNT: -// case opNOT_SUPPORTED: -// case opTOO_MANY_SUBENTRIES: -// case opEXCEEDED_WORK_LIMIT: -// case opTOO_MANY_SPONSORING: +// CONTRACT_EXECUTABLE_WASM = 0, +// CONTRACT_EXECUTABLE_STELLAR_ASSET = 1 +// }; +type ContractExecutableType int32 + +const ( + ContractExecutableTypeContractExecutableWasm ContractExecutableType = 0 + ContractExecutableTypeContractExecutableStellarAsset ContractExecutableType = 1 +) + +var contractExecutableTypeMap = map[int32]string{ + 0: "ContractExecutableTypeContractExecutableWasm", + 1: "ContractExecutableTypeContractExecutableStellarAsset", +} + +// ValidEnum validates a proposed value for this enum. Implements +// the Enum interface for ContractExecutableType +func (e ContractExecutableType) ValidEnum(v int32) bool { + _, ok := contractExecutableTypeMap[v] + return ok +} + +// String returns the name of `e` +func (e ContractExecutableType) String() string { + name, _ := contractExecutableTypeMap[int32(e)] + return name +} + +// EncodeTo encodes this value using the Encoder. +func (e ContractExecutableType) EncodeTo(enc *xdr.Encoder) error { + if _, ok := contractExecutableTypeMap[int32(e)]; !ok { + return fmt.Errorf("'%d' is not a valid ContractExecutableType enum value", e) + } + _, err := enc.EncodeInt(int32(e)) + return err +} + +var _ decoderFrom = (*ContractExecutableType)(nil) + +// DecodeFrom decodes this value using the Decoder. +func (e *ContractExecutableType) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding ContractExecutableType: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + v, n, err := d.DecodeInt() + if err != nil { + return n, fmt.Errorf("decoding ContractExecutableType: %w", err) + } + if _, ok := contractExecutableTypeMap[v]; !ok { + return n, fmt.Errorf("'%d' is not a valid ContractExecutableType enum value", v) + } + *e = ContractExecutableType(v) + return n, nil +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (s ContractExecutableType) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *ContractExecutableType) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} + +var ( + _ encoding.BinaryMarshaler = (*ContractExecutableType)(nil) + _ encoding.BinaryUnmarshaler = (*ContractExecutableType)(nil) +) + +// xdrType signals that this type represents XDR values defined by this package. +func (s ContractExecutableType) xdrType() {} + +var _ xdrType = (*ContractExecutableType)(nil) + +// ContractExecutable is an XDR Union defines as: +// +// union ContractExecutable switch (ContractExecutableType type) +// { +// case CONTRACT_EXECUTABLE_WASM: +// Hash wasm_hash; +// case CONTRACT_EXECUTABLE_STELLAR_ASSET: // void; // }; -type OperationResult struct { - Code OperationResultCode - Tr *OperationResultTr +type ContractExecutable struct { + Type ContractExecutableType + WasmHash *Hash } // SwitchFieldName returns the field name in which this union's // discriminant is stored -func (u OperationResult) SwitchFieldName() string { - return "Code" +func (u ContractExecutable) SwitchFieldName() string { + return "Type" } // ArmForSwitch returns which field name should be used for storing -// the value for an instance of OperationResult -func (u OperationResult) ArmForSwitch(sw int32) (string, bool) { - switch OperationResultCode(sw) { - case OperationResultCodeOpInner: - return "Tr", true - case OperationResultCodeOpBadAuth: - return "", true - case OperationResultCodeOpNoAccount: - return "", true - case OperationResultCodeOpNotSupported: - return "", true - case OperationResultCodeOpTooManySubentries: - return "", true - case OperationResultCodeOpExceededWorkLimit: - return "", true - case OperationResultCodeOpTooManySponsoring: +// the value for an instance of ContractExecutable +func (u ContractExecutable) ArmForSwitch(sw int32) (string, bool) { + switch ContractExecutableType(sw) { + case ContractExecutableTypeContractExecutableWasm: + return "WasmHash", true + case ContractExecutableTypeContractExecutableStellarAsset: return "", true } return "-", false } -// NewOperationResult creates a new OperationResult. -func NewOperationResult(code OperationResultCode, value interface{}) (result OperationResult, err error) { - result.Code = code - switch OperationResultCode(code) { - case OperationResultCodeOpInner: - tv, ok := value.(OperationResultTr) +// NewContractExecutable creates a new ContractExecutable. +func NewContractExecutable(aType ContractExecutableType, value interface{}) (result ContractExecutable, err error) { + result.Type = aType + switch ContractExecutableType(aType) { + case ContractExecutableTypeContractExecutableWasm: + tv, ok := value.(Hash) if !ok { - err = fmt.Errorf("invalid value, must be OperationResultTr") + err = errors.New("invalid value, must be Hash") return } - result.Tr = &tv - case OperationResultCodeOpBadAuth: - // void - case OperationResultCodeOpNoAccount: - // void - case OperationResultCodeOpNotSupported: - // void - case OperationResultCodeOpTooManySubentries: - // void - case OperationResultCodeOpExceededWorkLimit: - // void - case OperationResultCodeOpTooManySponsoring: + result.WasmHash = &tv + case ContractExecutableTypeContractExecutableStellarAsset: // void } return } -// MustTr retrieves the Tr value from the union, +// MustWasmHash retrieves the WasmHash value from the union, // panicing if the value is not set. -func (u OperationResult) MustTr() OperationResultTr { - val, ok := u.GetTr() +func (u ContractExecutable) MustWasmHash() Hash { + val, ok := u.GetWasmHash() if !ok { - panic("arm Tr is not set") + panic("arm WasmHash is not set") } return val } -// GetTr retrieves the Tr value from the union, +// GetWasmHash retrieves the WasmHash value from the union, // returning ok if the union's switch indicated the value is valid. -func (u OperationResult) GetTr() (result OperationResultTr, ok bool) { - armName, _ := u.ArmForSwitch(int32(u.Code)) +func (u ContractExecutable) GetWasmHash() (result Hash, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) - if armName == "Tr" { - result = *u.Tr + if armName == "WasmHash" { + result = *u.WasmHash ok = true } @@ -34992,83 +51580,57 @@ func (u OperationResult) GetTr() (result OperationResultTr, ok bool) { } // EncodeTo encodes this value using the Encoder. -func (u OperationResult) EncodeTo(e *xdr.Encoder) error { +func (u ContractExecutable) EncodeTo(e *xdr.Encoder) error { var err error - if err = u.Code.EncodeTo(e); err != nil { + if err = u.Type.EncodeTo(e); err != nil { return err } - switch OperationResultCode(u.Code) { - case OperationResultCodeOpInner: - if err = (*u.Tr).EncodeTo(e); err != nil { + switch ContractExecutableType(u.Type) { + case ContractExecutableTypeContractExecutableWasm: + if err = (*u.WasmHash).EncodeTo(e); err != nil { return err } return nil - case OperationResultCodeOpBadAuth: - // Void - return nil - case OperationResultCodeOpNoAccount: - // Void - return nil - case OperationResultCodeOpNotSupported: - // Void - return nil - case OperationResultCodeOpTooManySubentries: - // Void - return nil - case OperationResultCodeOpExceededWorkLimit: - // Void - return nil - case OperationResultCodeOpTooManySponsoring: + case ContractExecutableTypeContractExecutableStellarAsset: // Void return nil } - return fmt.Errorf("Code (OperationResultCode) switch value '%d' is not valid for union OperationResult", u.Code) + return fmt.Errorf("Type (ContractExecutableType) switch value '%d' is not valid for union ContractExecutable", u.Type) } -var _ decoderFrom = (*OperationResult)(nil) +var _ decoderFrom = (*ContractExecutable)(nil) // DecodeFrom decodes this value using the Decoder. -func (u *OperationResult) DecodeFrom(d *xdr.Decoder) (int, error) { +func (u *ContractExecutable) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding ContractExecutable: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = u.Code.DecodeFrom(d) + nTmp, err = u.Type.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding OperationResultCode: %s", err) + return n, fmt.Errorf("decoding ContractExecutableType: %w", err) } - switch OperationResultCode(u.Code) { - case OperationResultCodeOpInner: - u.Tr = new(OperationResultTr) - nTmp, err = (*u.Tr).DecodeFrom(d) + switch ContractExecutableType(u.Type) { + case ContractExecutableTypeContractExecutableWasm: + u.WasmHash = new(Hash) + nTmp, err = (*u.WasmHash).DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding OperationResultTr: %s", err) + return n, fmt.Errorf("decoding Hash: %w", err) } return n, nil - case OperationResultCodeOpBadAuth: - // Void - return n, nil - case OperationResultCodeOpNoAccount: - // Void - return n, nil - case OperationResultCodeOpNotSupported: - // Void - return n, nil - case OperationResultCodeOpTooManySubentries: - // Void - return n, nil - case OperationResultCodeOpExceededWorkLimit: - // Void - return n, nil - case OperationResultCodeOpTooManySponsoring: + case ContractExecutableTypeContractExecutableStellarAsset: // Void return n, nil } - return n, fmt.Errorf("union OperationResult has invalid Code (OperationResultCode) switch value '%d'", u.Code) + return n, fmt.Errorf("union ContractExecutable has invalid Type (ContractExecutableType) switch value '%d'", u.Type) } // MarshalBinary implements encoding.BinaryMarshaler. -func (s OperationResult) MarshalBinary() ([]byte, error) { +func (s ContractExecutable) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -35076,135 +51638,87 @@ func (s OperationResult) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *OperationResult) UnmarshalBinary(inp []byte) error { +func (s *ContractExecutable) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*OperationResult)(nil) - _ encoding.BinaryUnmarshaler = (*OperationResult)(nil) + _ encoding.BinaryMarshaler = (*ContractExecutable)(nil) + _ encoding.BinaryUnmarshaler = (*ContractExecutable)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s OperationResult) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s ContractExecutable) xdrType() {} -var _ xdrType = (*OperationResult)(nil) +var _ xdrType = (*ContractExecutable)(nil) -// TransactionResultCode is an XDR Enum defines as: +// ScAddressType is an XDR Enum defines as: // -// enum TransactionResultCode +// enum SCAddressType // { -// txFEE_BUMP_INNER_SUCCESS = 1, // fee bump inner transaction succeeded -// txSUCCESS = 0, // all operations succeeded -// -// txFAILED = -1, // one of the operations failed (none were applied) -// -// txTOO_EARLY = -2, // ledger closeTime before minTime -// txTOO_LATE = -3, // ledger closeTime after maxTime -// txMISSING_OPERATION = -4, // no operation was specified -// txBAD_SEQ = -5, // sequence number does not match source account -// -// txBAD_AUTH = -6, // too few valid signatures / wrong network -// txINSUFFICIENT_BALANCE = -7, // fee would bring account below reserve -// txNO_ACCOUNT = -8, // source account not found -// txINSUFFICIENT_FEE = -9, // fee is too small -// txBAD_AUTH_EXTRA = -10, // unused signatures attached to transaction -// txINTERNAL_ERROR = -11, // an unknown error occurred -// -// txNOT_SUPPORTED = -12, // transaction type not supported -// txFEE_BUMP_INNER_FAILED = -13, // fee bump inner transaction failed -// txBAD_SPONSORSHIP = -14, // sponsorship not confirmed -// txBAD_MIN_SEQ_AGE_OR_GAP = -// -15, // minSeqAge or minSeqLedgerGap conditions not met -// txMALFORMED = -16 // precondition is invalid +// SC_ADDRESS_TYPE_ACCOUNT = 0, +// SC_ADDRESS_TYPE_CONTRACT = 1 // }; -type TransactionResultCode int32 +type ScAddressType int32 const ( - TransactionResultCodeTxFeeBumpInnerSuccess TransactionResultCode = 1 - TransactionResultCodeTxSuccess TransactionResultCode = 0 - TransactionResultCodeTxFailed TransactionResultCode = -1 - TransactionResultCodeTxTooEarly TransactionResultCode = -2 - TransactionResultCodeTxTooLate TransactionResultCode = -3 - TransactionResultCodeTxMissingOperation TransactionResultCode = -4 - TransactionResultCodeTxBadSeq TransactionResultCode = -5 - TransactionResultCodeTxBadAuth TransactionResultCode = -6 - TransactionResultCodeTxInsufficientBalance TransactionResultCode = -7 - TransactionResultCodeTxNoAccount TransactionResultCode = -8 - TransactionResultCodeTxInsufficientFee TransactionResultCode = -9 - TransactionResultCodeTxBadAuthExtra TransactionResultCode = -10 - TransactionResultCodeTxInternalError TransactionResultCode = -11 - TransactionResultCodeTxNotSupported TransactionResultCode = -12 - TransactionResultCodeTxFeeBumpInnerFailed TransactionResultCode = -13 - TransactionResultCodeTxBadSponsorship TransactionResultCode = -14 - TransactionResultCodeTxBadMinSeqAgeOrGap TransactionResultCode = -15 - TransactionResultCodeTxMalformed TransactionResultCode = -16 + ScAddressTypeScAddressTypeAccount ScAddressType = 0 + ScAddressTypeScAddressTypeContract ScAddressType = 1 ) -var transactionResultCodeMap = map[int32]string{ - 1: "TransactionResultCodeTxFeeBumpInnerSuccess", - 0: "TransactionResultCodeTxSuccess", - -1: "TransactionResultCodeTxFailed", - -2: "TransactionResultCodeTxTooEarly", - -3: "TransactionResultCodeTxTooLate", - -4: "TransactionResultCodeTxMissingOperation", - -5: "TransactionResultCodeTxBadSeq", - -6: "TransactionResultCodeTxBadAuth", - -7: "TransactionResultCodeTxInsufficientBalance", - -8: "TransactionResultCodeTxNoAccount", - -9: "TransactionResultCodeTxInsufficientFee", - -10: "TransactionResultCodeTxBadAuthExtra", - -11: "TransactionResultCodeTxInternalError", - -12: "TransactionResultCodeTxNotSupported", - -13: "TransactionResultCodeTxFeeBumpInnerFailed", - -14: "TransactionResultCodeTxBadSponsorship", - -15: "TransactionResultCodeTxBadMinSeqAgeOrGap", - -16: "TransactionResultCodeTxMalformed", +var scAddressTypeMap = map[int32]string{ + 0: "ScAddressTypeScAddressTypeAccount", + 1: "ScAddressTypeScAddressTypeContract", } // ValidEnum validates a proposed value for this enum. Implements -// the Enum interface for TransactionResultCode -func (e TransactionResultCode) ValidEnum(v int32) bool { - _, ok := transactionResultCodeMap[v] +// the Enum interface for ScAddressType +func (e ScAddressType) ValidEnum(v int32) bool { + _, ok := scAddressTypeMap[v] return ok } // String returns the name of `e` -func (e TransactionResultCode) String() string { - name, _ := transactionResultCodeMap[int32(e)] +func (e ScAddressType) String() string { + name, _ := scAddressTypeMap[int32(e)] return name } // EncodeTo encodes this value using the Encoder. -func (e TransactionResultCode) EncodeTo(enc *xdr.Encoder) error { - if _, ok := transactionResultCodeMap[int32(e)]; !ok { - return fmt.Errorf("'%d' is not a valid TransactionResultCode enum value", e) +func (e ScAddressType) EncodeTo(enc *xdr.Encoder) error { + if _, ok := scAddressTypeMap[int32(e)]; !ok { + return fmt.Errorf("'%d' is not a valid ScAddressType enum value", e) } _, err := enc.EncodeInt(int32(e)) return err } -var _ decoderFrom = (*TransactionResultCode)(nil) +var _ decoderFrom = (*ScAddressType)(nil) // DecodeFrom decodes this value using the Decoder. -func (e *TransactionResultCode) DecodeFrom(d *xdr.Decoder) (int, error) { +func (e *ScAddressType) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding ScAddressType: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 v, n, err := d.DecodeInt() if err != nil { - return n, fmt.Errorf("decoding TransactionResultCode: %s", err) + return n, fmt.Errorf("decoding ScAddressType: %w", err) } - if _, ok := transactionResultCodeMap[v]; !ok { - return n, fmt.Errorf("'%d' is not a valid TransactionResultCode enum value", v) + if _, ok := scAddressTypeMap[v]; !ok { + return n, fmt.Errorf("'%d' is not a valid ScAddressType enum value", v) } - *e = TransactionResultCode(v) + *e = ScAddressType(v) return n, nil } // MarshalBinary implements encoding.BinaryMarshaler. -func (s TransactionResultCode) MarshalBinary() ([]byte, error) { +func (s ScAddressType) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -35212,169 +51726,124 @@ func (s TransactionResultCode) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *TransactionResultCode) UnmarshalBinary(inp []byte) error { +func (s *ScAddressType) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*TransactionResultCode)(nil) - _ encoding.BinaryUnmarshaler = (*TransactionResultCode)(nil) + _ encoding.BinaryMarshaler = (*ScAddressType)(nil) + _ encoding.BinaryUnmarshaler = (*ScAddressType)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s TransactionResultCode) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s ScAddressType) xdrType() {} -var _ xdrType = (*TransactionResultCode)(nil) +var _ xdrType = (*ScAddressType)(nil) -// InnerTransactionResultResult is an XDR NestedUnion defines as: +// ScAddress is an XDR Union defines as: // -// union switch (TransactionResultCode code) -// { -// // txFEE_BUMP_INNER_SUCCESS is not included -// case txSUCCESS: -// case txFAILED: -// OperationResult results<>; -// case txTOO_EARLY: -// case txTOO_LATE: -// case txMISSING_OPERATION: -// case txBAD_SEQ: -// case txBAD_AUTH: -// case txINSUFFICIENT_BALANCE: -// case txNO_ACCOUNT: -// case txINSUFFICIENT_FEE: -// case txBAD_AUTH_EXTRA: -// case txINTERNAL_ERROR: -// case txNOT_SUPPORTED: -// // txFEE_BUMP_INNER_FAILED is not included -// case txBAD_SPONSORSHIP: -// case txBAD_MIN_SEQ_AGE_OR_GAP: -// case txMALFORMED: -// void; -// } -type InnerTransactionResultResult struct { - Code TransactionResultCode - Results *[]OperationResult +// union SCAddress switch (SCAddressType type) +// { +// case SC_ADDRESS_TYPE_ACCOUNT: +// AccountID accountId; +// case SC_ADDRESS_TYPE_CONTRACT: +// Hash contractId; +// }; +type ScAddress struct { + Type ScAddressType + AccountId *AccountId + ContractId *Hash } // SwitchFieldName returns the field name in which this union's // discriminant is stored -func (u InnerTransactionResultResult) SwitchFieldName() string { - return "Code" +func (u ScAddress) SwitchFieldName() string { + return "Type" } // ArmForSwitch returns which field name should be used for storing -// the value for an instance of InnerTransactionResultResult -func (u InnerTransactionResultResult) ArmForSwitch(sw int32) (string, bool) { - switch TransactionResultCode(sw) { - case TransactionResultCodeTxSuccess: - return "Results", true - case TransactionResultCodeTxFailed: - return "Results", true - case TransactionResultCodeTxTooEarly: - return "", true - case TransactionResultCodeTxTooLate: - return "", true - case TransactionResultCodeTxMissingOperation: - return "", true - case TransactionResultCodeTxBadSeq: - return "", true - case TransactionResultCodeTxBadAuth: - return "", true - case TransactionResultCodeTxInsufficientBalance: - return "", true - case TransactionResultCodeTxNoAccount: - return "", true - case TransactionResultCodeTxInsufficientFee: - return "", true - case TransactionResultCodeTxBadAuthExtra: - return "", true - case TransactionResultCodeTxInternalError: - return "", true - case TransactionResultCodeTxNotSupported: - return "", true - case TransactionResultCodeTxBadSponsorship: - return "", true - case TransactionResultCodeTxBadMinSeqAgeOrGap: - return "", true - case TransactionResultCodeTxMalformed: - return "", true +// the value for an instance of ScAddress +func (u ScAddress) ArmForSwitch(sw int32) (string, bool) { + switch ScAddressType(sw) { + case ScAddressTypeScAddressTypeAccount: + return "AccountId", true + case ScAddressTypeScAddressTypeContract: + return "ContractId", true } return "-", false } -// NewInnerTransactionResultResult creates a new InnerTransactionResultResult. -func NewInnerTransactionResultResult(code TransactionResultCode, value interface{}) (result InnerTransactionResultResult, err error) { - result.Code = code - switch TransactionResultCode(code) { - case TransactionResultCodeTxSuccess: - tv, ok := value.([]OperationResult) +// NewScAddress creates a new ScAddress. +func NewScAddress(aType ScAddressType, value interface{}) (result ScAddress, err error) { + result.Type = aType + switch ScAddressType(aType) { + case ScAddressTypeScAddressTypeAccount: + tv, ok := value.(AccountId) if !ok { - err = fmt.Errorf("invalid value, must be []OperationResult") + err = errors.New("invalid value, must be AccountId") return } - result.Results = &tv - case TransactionResultCodeTxFailed: - tv, ok := value.([]OperationResult) + result.AccountId = &tv + case ScAddressTypeScAddressTypeContract: + tv, ok := value.(Hash) if !ok { - err = fmt.Errorf("invalid value, must be []OperationResult") + err = errors.New("invalid value, must be Hash") return } - result.Results = &tv - case TransactionResultCodeTxTooEarly: - // void - case TransactionResultCodeTxTooLate: - // void - case TransactionResultCodeTxMissingOperation: - // void - case TransactionResultCodeTxBadSeq: - // void - case TransactionResultCodeTxBadAuth: - // void - case TransactionResultCodeTxInsufficientBalance: - // void - case TransactionResultCodeTxNoAccount: - // void - case TransactionResultCodeTxInsufficientFee: - // void - case TransactionResultCodeTxBadAuthExtra: - // void - case TransactionResultCodeTxInternalError: - // void - case TransactionResultCodeTxNotSupported: - // void - case TransactionResultCodeTxBadSponsorship: - // void - case TransactionResultCodeTxBadMinSeqAgeOrGap: - // void - case TransactionResultCodeTxMalformed: - // void + result.ContractId = &tv } return } -// MustResults retrieves the Results value from the union, +// MustAccountId retrieves the AccountId value from the union, // panicing if the value is not set. -func (u InnerTransactionResultResult) MustResults() []OperationResult { - val, ok := u.GetResults() +func (u ScAddress) MustAccountId() AccountId { + val, ok := u.GetAccountId() if !ok { - panic("arm Results is not set") + panic("arm AccountId is not set") } return val } -// GetResults retrieves the Results value from the union, +// GetAccountId retrieves the AccountId value from the union, // returning ok if the union's switch indicated the value is valid. -func (u InnerTransactionResultResult) GetResults() (result []OperationResult, ok bool) { - armName, _ := u.ArmForSwitch(int32(u.Code)) +func (u ScAddress) GetAccountId() (result AccountId, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) - if armName == "Results" { - result = *u.Results + if armName == "AccountId" { + result = *u.AccountId + ok = true + } + + return +} + +// MustContractId retrieves the ContractId value from the union, +// panicing if the value is not set. +func (u ScAddress) MustContractId() Hash { + val, ok := u.GetContractId() + + if !ok { + panic("arm ContractId is not set") + } + + return val +} + +// GetContractId retrieves the ContractId value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u ScAddress) GetContractId() (result Hash, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) + + if armName == "ContractId" { + result = *u.ContractId ok = true } @@ -35382,178 +51851,64 @@ func (u InnerTransactionResultResult) GetResults() (result []OperationResult, ok } // EncodeTo encodes this value using the Encoder. -func (u InnerTransactionResultResult) EncodeTo(e *xdr.Encoder) error { +func (u ScAddress) EncodeTo(e *xdr.Encoder) error { var err error - if err = u.Code.EncodeTo(e); err != nil { - return err - } - switch TransactionResultCode(u.Code) { - case TransactionResultCodeTxSuccess: - if _, err = e.EncodeUint(uint32(len((*u.Results)))); err != nil { + if err = u.Type.EncodeTo(e); err != nil { + return err + } + switch ScAddressType(u.Type) { + case ScAddressTypeScAddressTypeAccount: + if err = (*u.AccountId).EncodeTo(e); err != nil { return err } - for i := 0; i < len((*u.Results)); i++ { - if err = (*u.Results)[i].EncodeTo(e); err != nil { - return err - } - } return nil - case TransactionResultCodeTxFailed: - if _, err = e.EncodeUint(uint32(len((*u.Results)))); err != nil { + case ScAddressTypeScAddressTypeContract: + if err = (*u.ContractId).EncodeTo(e); err != nil { return err } - for i := 0; i < len((*u.Results)); i++ { - if err = (*u.Results)[i].EncodeTo(e); err != nil { - return err - } - } - return nil - case TransactionResultCodeTxTooEarly: - // Void - return nil - case TransactionResultCodeTxTooLate: - // Void - return nil - case TransactionResultCodeTxMissingOperation: - // Void - return nil - case TransactionResultCodeTxBadSeq: - // Void - return nil - case TransactionResultCodeTxBadAuth: - // Void - return nil - case TransactionResultCodeTxInsufficientBalance: - // Void - return nil - case TransactionResultCodeTxNoAccount: - // Void - return nil - case TransactionResultCodeTxInsufficientFee: - // Void - return nil - case TransactionResultCodeTxBadAuthExtra: - // Void - return nil - case TransactionResultCodeTxInternalError: - // Void - return nil - case TransactionResultCodeTxNotSupported: - // Void - return nil - case TransactionResultCodeTxBadSponsorship: - // Void - return nil - case TransactionResultCodeTxBadMinSeqAgeOrGap: - // Void - return nil - case TransactionResultCodeTxMalformed: - // Void return nil } - return fmt.Errorf("Code (TransactionResultCode) switch value '%d' is not valid for union InnerTransactionResultResult", u.Code) + return fmt.Errorf("Type (ScAddressType) switch value '%d' is not valid for union ScAddress", u.Type) } -var _ decoderFrom = (*InnerTransactionResultResult)(nil) +var _ decoderFrom = (*ScAddress)(nil) // DecodeFrom decodes this value using the Decoder. -func (u *InnerTransactionResultResult) DecodeFrom(d *xdr.Decoder) (int, error) { +func (u *ScAddress) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding ScAddress: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = u.Code.DecodeFrom(d) + nTmp, err = u.Type.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding TransactionResultCode: %s", err) + return n, fmt.Errorf("decoding ScAddressType: %w", err) } - switch TransactionResultCode(u.Code) { - case TransactionResultCodeTxSuccess: - u.Results = new([]OperationResult) - var l uint32 - l, nTmp, err = d.DecodeUint() + switch ScAddressType(u.Type) { + case ScAddressTypeScAddressTypeAccount: + u.AccountId = new(AccountId) + nTmp, err = (*u.AccountId).DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding OperationResult: %s", err) - } - (*u.Results) = nil - if l > 0 { - (*u.Results) = make([]OperationResult, l) - for i := uint32(0); i < l; i++ { - nTmp, err = (*u.Results)[i].DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding OperationResult: %s", err) - } - } + return n, fmt.Errorf("decoding AccountId: %w", err) } return n, nil - case TransactionResultCodeTxFailed: - u.Results = new([]OperationResult) - var l uint32 - l, nTmp, err = d.DecodeUint() + case ScAddressTypeScAddressTypeContract: + u.ContractId = new(Hash) + nTmp, err = (*u.ContractId).DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding OperationResult: %s", err) - } - (*u.Results) = nil - if l > 0 { - (*u.Results) = make([]OperationResult, l) - for i := uint32(0); i < l; i++ { - nTmp, err = (*u.Results)[i].DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding OperationResult: %s", err) - } - } + return n, fmt.Errorf("decoding Hash: %w", err) } return n, nil - case TransactionResultCodeTxTooEarly: - // Void - return n, nil - case TransactionResultCodeTxTooLate: - // Void - return n, nil - case TransactionResultCodeTxMissingOperation: - // Void - return n, nil - case TransactionResultCodeTxBadSeq: - // Void - return n, nil - case TransactionResultCodeTxBadAuth: - // Void - return n, nil - case TransactionResultCodeTxInsufficientBalance: - // Void - return n, nil - case TransactionResultCodeTxNoAccount: - // Void - return n, nil - case TransactionResultCodeTxInsufficientFee: - // Void - return n, nil - case TransactionResultCodeTxBadAuthExtra: - // Void - return n, nil - case TransactionResultCodeTxInternalError: - // Void - return n, nil - case TransactionResultCodeTxNotSupported: - // Void - return n, nil - case TransactionResultCodeTxBadSponsorship: - // Void - return n, nil - case TransactionResultCodeTxBadMinSeqAgeOrGap: - // Void - return n, nil - case TransactionResultCodeTxMalformed: - // Void - return n, nil } - return n, fmt.Errorf("union InnerTransactionResultResult has invalid Code (TransactionResultCode) switch value '%d'", u.Code) + return n, fmt.Errorf("union ScAddress has invalid Type (ScAddressType) switch value '%d'", u.Type) } // MarshalBinary implements encoding.BinaryMarshaler. -func (s InnerTransactionResultResult) MarshalBinary() ([]byte, error) { +func (s ScAddress) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -35561,96 +51916,164 @@ func (s InnerTransactionResultResult) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *InnerTransactionResultResult) UnmarshalBinary(inp []byte) error { +func (s *ScAddress) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*InnerTransactionResultResult)(nil) - _ encoding.BinaryUnmarshaler = (*InnerTransactionResultResult)(nil) + _ encoding.BinaryMarshaler = (*ScAddress)(nil) + _ encoding.BinaryUnmarshaler = (*ScAddress)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s InnerTransactionResultResult) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s ScAddress) xdrType() {} -var _ xdrType = (*InnerTransactionResultResult)(nil) +var _ xdrType = (*ScAddress)(nil) -// InnerTransactionResultExt is an XDR NestedUnion defines as: +// ScsymbolLimit is an XDR Const defines as: // -// union switch (int v) -// { -// case 0: -// void; -// } -type InnerTransactionResultExt struct { - V int32 -} +// const SCSYMBOL_LIMIT = 32; +const ScsymbolLimit = 32 -// SwitchFieldName returns the field name in which this union's -// discriminant is stored -func (u InnerTransactionResultExt) SwitchFieldName() string { - return "V" -} +// ScVec is an XDR Typedef defines as: +// +// typedef SCVal SCVec<>; +type ScVec []ScVal -// ArmForSwitch returns which field name should be used for storing -// the value for an instance of InnerTransactionResultExt -func (u InnerTransactionResultExt) ArmForSwitch(sw int32) (string, bool) { - switch int32(sw) { - case 0: - return "", true +// EncodeTo encodes this value using the Encoder. +func (s ScVec) EncodeTo(e *xdr.Encoder) error { + var err error + if _, err = e.EncodeUint(uint32(len(s))); err != nil { + return err } - return "-", false + for i := 0; i < len(s); i++ { + if err = s[i].EncodeTo(e); err != nil { + return err + } + } + return nil } -// NewInnerTransactionResultExt creates a new InnerTransactionResultExt. -func NewInnerTransactionResultExt(v int32, value interface{}) (result InnerTransactionResultExt, err error) { - result.V = v - switch int32(v) { - case 0: - // void +var _ decoderFrom = (*ScVec)(nil) + +// DecodeFrom decodes this value using the Decoder. +func (s *ScVec) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding ScVec: %w", ErrMaxDecodingDepthReached) } - return + maxDepth -= 1 + var err error + var n, nTmp int + var l uint32 + l, nTmp, err = d.DecodeUint() + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ScVal: %w", err) + } + (*s) = nil + if l > 0 { + if il, ok := d.InputLen(); ok && uint(il) < uint(l) { + return n, fmt.Errorf("decoding ScVal: length (%d) exceeds remaining input length (%d)", l, il) + } + (*s) = make([]ScVal, l) + for i := uint32(0); i < l; i++ { + nTmp, err = (*s)[i].DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ScVal: %w", err) + } + } + } + return n, nil +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (s ScVec) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err } +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *ScVec) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} + +var ( + _ encoding.BinaryMarshaler = (*ScVec)(nil) + _ encoding.BinaryUnmarshaler = (*ScVec)(nil) +) + +// xdrType signals that this type represents XDR values defined by this package. +func (s ScVec) xdrType() {} + +var _ xdrType = (*ScVec)(nil) + +// ScMap is an XDR Typedef defines as: +// +// typedef SCMapEntry SCMap<>; +type ScMap []ScMapEntry + // EncodeTo encodes this value using the Encoder. -func (u InnerTransactionResultExt) EncodeTo(e *xdr.Encoder) error { +func (s ScMap) EncodeTo(e *xdr.Encoder) error { var err error - if _, err = e.EncodeInt(int32(u.V)); err != nil { + if _, err = e.EncodeUint(uint32(len(s))); err != nil { return err } - switch int32(u.V) { - case 0: - // Void - return nil + for i := 0; i < len(s); i++ { + if err = s[i].EncodeTo(e); err != nil { + return err + } } - return fmt.Errorf("V (int32) switch value '%d' is not valid for union InnerTransactionResultExt", u.V) + return nil } -var _ decoderFrom = (*InnerTransactionResultExt)(nil) +var _ decoderFrom = (*ScMap)(nil) // DecodeFrom decodes this value using the Decoder. -func (u *InnerTransactionResultExt) DecodeFrom(d *xdr.Decoder) (int, error) { +func (s *ScMap) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding ScMap: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - u.V, nTmp, err = d.DecodeInt() + var l uint32 + l, nTmp, err = d.DecodeUint() n += nTmp if err != nil { - return n, fmt.Errorf("decoding Int: %s", err) + return n, fmt.Errorf("decoding ScMapEntry: %w", err) } - switch int32(u.V) { - case 0: - // Void - return n, nil + (*s) = nil + if l > 0 { + if il, ok := d.InputLen(); ok && uint(il) < uint(l) { + return n, fmt.Errorf("decoding ScMapEntry: length (%d) exceeds remaining input length (%d)", l, il) + } + (*s) = make([]ScMapEntry, l) + for i := uint32(0); i < l; i++ { + nTmp, err = (*s)[i].DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ScMapEntry: %w", err) + } + } } - return n, fmt.Errorf("union InnerTransactionResultExt has invalid V (int32) switch value '%d'", u.V) + return n, nil } // MarshalBinary implements encoding.BinaryMarshaler. -func (s InnerTransactionResultExt) MarshalBinary() ([]byte, error) { +func (s ScMap) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -35658,111 +52081,59 @@ func (s InnerTransactionResultExt) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *InnerTransactionResultExt) UnmarshalBinary(inp []byte) error { +func (s *ScMap) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*InnerTransactionResultExt)(nil) - _ encoding.BinaryUnmarshaler = (*InnerTransactionResultExt)(nil) + _ encoding.BinaryMarshaler = (*ScMap)(nil) + _ encoding.BinaryUnmarshaler = (*ScMap)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s InnerTransactionResultExt) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s ScMap) xdrType() {} -var _ xdrType = (*InnerTransactionResultExt)(nil) +var _ xdrType = (*ScMap)(nil) -// InnerTransactionResult is an XDR Struct defines as: -// -// struct InnerTransactionResult -// { -// // Always 0. Here for binary compatibility. -// int64 feeCharged; +// ScBytes is an XDR Typedef defines as: // -// union switch (TransactionResultCode code) -// { -// // txFEE_BUMP_INNER_SUCCESS is not included -// case txSUCCESS: -// case txFAILED: -// OperationResult results<>; -// case txTOO_EARLY: -// case txTOO_LATE: -// case txMISSING_OPERATION: -// case txBAD_SEQ: -// case txBAD_AUTH: -// case txINSUFFICIENT_BALANCE: -// case txNO_ACCOUNT: -// case txINSUFFICIENT_FEE: -// case txBAD_AUTH_EXTRA: -// case txINTERNAL_ERROR: -// case txNOT_SUPPORTED: -// // txFEE_BUMP_INNER_FAILED is not included -// case txBAD_SPONSORSHIP: -// case txBAD_MIN_SEQ_AGE_OR_GAP: -// case txMALFORMED: -// void; -// } -// result; -// -// // reserved for future use -// union switch (int v) -// { -// case 0: -// void; -// } -// ext; -// }; -type InnerTransactionResult struct { - FeeCharged Int64 - Result InnerTransactionResultResult - Ext InnerTransactionResultExt -} +// typedef opaque SCBytes<>; +type ScBytes []byte // EncodeTo encodes this value using the Encoder. -func (s *InnerTransactionResult) EncodeTo(e *xdr.Encoder) error { +func (s ScBytes) EncodeTo(e *xdr.Encoder) error { var err error - if err = s.FeeCharged.EncodeTo(e); err != nil { - return err - } - if err = s.Result.EncodeTo(e); err != nil { - return err - } - if err = s.Ext.EncodeTo(e); err != nil { + if _, err = e.EncodeOpaque(s[:]); err != nil { return err } return nil } -var _ decoderFrom = (*InnerTransactionResult)(nil) +var _ decoderFrom = (*ScBytes)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *InnerTransactionResult) DecodeFrom(d *xdr.Decoder) (int, error) { +func (s *ScBytes) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding ScBytes: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = s.FeeCharged.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Int64: %s", err) - } - nTmp, err = s.Result.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding InnerTransactionResultResult: %s", err) - } - nTmp, err = s.Ext.DecodeFrom(d) + (*s), nTmp, err = d.DecodeOpaque(0) n += nTmp if err != nil { - return n, fmt.Errorf("decoding InnerTransactionResultExt: %s", err) + return n, fmt.Errorf("decoding ScBytes: %w", err) } return n, nil } // MarshalBinary implements encoding.BinaryMarshaler. -func (s InnerTransactionResult) MarshalBinary() ([]byte, error) { +func (s ScBytes) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -35770,69 +52141,61 @@ func (s InnerTransactionResult) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *InnerTransactionResult) UnmarshalBinary(inp []byte) error { +func (s *ScBytes) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*InnerTransactionResult)(nil) - _ encoding.BinaryUnmarshaler = (*InnerTransactionResult)(nil) + _ encoding.BinaryMarshaler = (*ScBytes)(nil) + _ encoding.BinaryUnmarshaler = (*ScBytes)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s InnerTransactionResult) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s ScBytes) xdrType() {} -var _ xdrType = (*InnerTransactionResult)(nil) +var _ xdrType = (*ScBytes)(nil) -// InnerTransactionResultPair is an XDR Struct defines as: +// ScString is an XDR Typedef defines as: // -// struct InnerTransactionResultPair -// { -// Hash transactionHash; // hash of the inner transaction -// InnerTransactionResult result; // result for the inner transaction -// }; -type InnerTransactionResultPair struct { - TransactionHash Hash - Result InnerTransactionResult -} +// typedef string SCString<>; +type ScString string // EncodeTo encodes this value using the Encoder. -func (s *InnerTransactionResultPair) EncodeTo(e *xdr.Encoder) error { +func (s ScString) EncodeTo(e *xdr.Encoder) error { var err error - if err = s.TransactionHash.EncodeTo(e); err != nil { - return err - } - if err = s.Result.EncodeTo(e); err != nil { + if _, err = e.EncodeString(string(s)); err != nil { return err } return nil } -var _ decoderFrom = (*InnerTransactionResultPair)(nil) +var _ decoderFrom = (*ScString)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *InnerTransactionResultPair) DecodeFrom(d *xdr.Decoder) (int, error) { +func (s *ScString) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding ScString: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = s.TransactionHash.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Hash: %s", err) - } - nTmp, err = s.Result.DecodeFrom(d) + var v string + v, nTmp, err = d.DecodeString(0) n += nTmp if err != nil { - return n, fmt.Errorf("decoding InnerTransactionResult: %s", err) + return n, fmt.Errorf("decoding ScString: %w", err) } + *s = ScString(v) return n, nil } // MarshalBinary implements encoding.BinaryMarshaler. -func (s InnerTransactionResultPair) MarshalBinary() ([]byte, error) { +func (s ScString) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -35840,420 +52203,219 @@ func (s InnerTransactionResultPair) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *InnerTransactionResultPair) UnmarshalBinary(inp []byte) error { +func (s *ScString) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*InnerTransactionResultPair)(nil) - _ encoding.BinaryUnmarshaler = (*InnerTransactionResultPair)(nil) + _ encoding.BinaryMarshaler = (*ScString)(nil) + _ encoding.BinaryUnmarshaler = (*ScString)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s InnerTransactionResultPair) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s ScString) xdrType() {} -var _ xdrType = (*InnerTransactionResultPair)(nil) +var _ xdrType = (*ScString)(nil) -// TransactionResultResult is an XDR NestedUnion defines as: +// ScSymbol is an XDR Typedef defines as: // -// union switch (TransactionResultCode code) -// { -// case txFEE_BUMP_INNER_SUCCESS: -// case txFEE_BUMP_INNER_FAILED: -// InnerTransactionResultPair innerResultPair; -// case txSUCCESS: -// case txFAILED: -// OperationResult results<>; -// case txTOO_EARLY: -// case txTOO_LATE: -// case txMISSING_OPERATION: -// case txBAD_SEQ: -// case txBAD_AUTH: -// case txINSUFFICIENT_BALANCE: -// case txNO_ACCOUNT: -// case txINSUFFICIENT_FEE: -// case txBAD_AUTH_EXTRA: -// case txINTERNAL_ERROR: -// case txNOT_SUPPORTED: -// // case txFEE_BUMP_INNER_FAILED: handled above -// case txBAD_SPONSORSHIP: -// case txBAD_MIN_SEQ_AGE_OR_GAP: -// case txMALFORMED: -// void; -// } -type TransactionResultResult struct { - Code TransactionResultCode - InnerResultPair *InnerTransactionResultPair - Results *[]OperationResult -} +// typedef string SCSymbol; +type ScSymbol string -// SwitchFieldName returns the field name in which this union's -// discriminant is stored -func (u TransactionResultResult) SwitchFieldName() string { - return "Code" +// XDRMaxSize implements the Sized interface for ScSymbol +func (e ScSymbol) XDRMaxSize() int { + return 32 } -// ArmForSwitch returns which field name should be used for storing -// the value for an instance of TransactionResultResult -func (u TransactionResultResult) ArmForSwitch(sw int32) (string, bool) { - switch TransactionResultCode(sw) { - case TransactionResultCodeTxFeeBumpInnerSuccess: - return "InnerResultPair", true - case TransactionResultCodeTxFeeBumpInnerFailed: - return "InnerResultPair", true - case TransactionResultCodeTxSuccess: - return "Results", true - case TransactionResultCodeTxFailed: - return "Results", true - case TransactionResultCodeTxTooEarly: - return "", true - case TransactionResultCodeTxTooLate: - return "", true - case TransactionResultCodeTxMissingOperation: - return "", true - case TransactionResultCodeTxBadSeq: - return "", true - case TransactionResultCodeTxBadAuth: - return "", true - case TransactionResultCodeTxInsufficientBalance: - return "", true - case TransactionResultCodeTxNoAccount: - return "", true - case TransactionResultCodeTxInsufficientFee: - return "", true - case TransactionResultCodeTxBadAuthExtra: - return "", true - case TransactionResultCodeTxInternalError: - return "", true - case TransactionResultCodeTxNotSupported: - return "", true - case TransactionResultCodeTxBadSponsorship: - return "", true - case TransactionResultCodeTxBadMinSeqAgeOrGap: - return "", true - case TransactionResultCodeTxMalformed: - return "", true +// EncodeTo encodes this value using the Encoder. +func (s ScSymbol) EncodeTo(e *xdr.Encoder) error { + var err error + if _, err = e.EncodeString(string(s)); err != nil { + return err } - return "-", false + return nil } -// NewTransactionResultResult creates a new TransactionResultResult. -func NewTransactionResultResult(code TransactionResultCode, value interface{}) (result TransactionResultResult, err error) { - result.Code = code - switch TransactionResultCode(code) { - case TransactionResultCodeTxFeeBumpInnerSuccess: - tv, ok := value.(InnerTransactionResultPair) - if !ok { - err = fmt.Errorf("invalid value, must be InnerTransactionResultPair") - return - } - result.InnerResultPair = &tv - case TransactionResultCodeTxFeeBumpInnerFailed: - tv, ok := value.(InnerTransactionResultPair) - if !ok { - err = fmt.Errorf("invalid value, must be InnerTransactionResultPair") - return - } - result.InnerResultPair = &tv - case TransactionResultCodeTxSuccess: - tv, ok := value.([]OperationResult) - if !ok { - err = fmt.Errorf("invalid value, must be []OperationResult") - return - } - result.Results = &tv - case TransactionResultCodeTxFailed: - tv, ok := value.([]OperationResult) - if !ok { - err = fmt.Errorf("invalid value, must be []OperationResult") - return - } - result.Results = &tv - case TransactionResultCodeTxTooEarly: - // void - case TransactionResultCodeTxTooLate: - // void - case TransactionResultCodeTxMissingOperation: - // void - case TransactionResultCodeTxBadSeq: - // void - case TransactionResultCodeTxBadAuth: - // void - case TransactionResultCodeTxInsufficientBalance: - // void - case TransactionResultCodeTxNoAccount: - // void - case TransactionResultCodeTxInsufficientFee: - // void - case TransactionResultCodeTxBadAuthExtra: - // void - case TransactionResultCodeTxInternalError: - // void - case TransactionResultCodeTxNotSupported: - // void - case TransactionResultCodeTxBadSponsorship: - // void - case TransactionResultCodeTxBadMinSeqAgeOrGap: - // void - case TransactionResultCodeTxMalformed: - // void +var _ decoderFrom = (*ScSymbol)(nil) + +// DecodeFrom decodes this value using the Decoder. +func (s *ScSymbol) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding ScSymbol: %w", ErrMaxDecodingDepthReached) } - return + maxDepth -= 1 + var err error + var n, nTmp int + var v string + v, nTmp, err = d.DecodeString(32) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ScSymbol: %w", err) + } + *s = ScSymbol(v) + return n, nil } -// MustInnerResultPair retrieves the InnerResultPair value from the union, -// panicing if the value is not set. -func (u TransactionResultResult) MustInnerResultPair() InnerTransactionResultPair { - val, ok := u.GetInnerResultPair() +// MarshalBinary implements encoding.BinaryMarshaler. +func (s ScSymbol) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *ScSymbol) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} + +var ( + _ encoding.BinaryMarshaler = (*ScSymbol)(nil) + _ encoding.BinaryUnmarshaler = (*ScSymbol)(nil) +) - if !ok { - panic("arm InnerResultPair is not set") - } +// xdrType signals that this type represents XDR values defined by this package. +func (s ScSymbol) xdrType() {} - return val -} +var _ xdrType = (*ScSymbol)(nil) -// GetInnerResultPair retrieves the InnerResultPair value from the union, -// returning ok if the union's switch indicated the value is valid. -func (u TransactionResultResult) GetInnerResultPair() (result InnerTransactionResultPair, ok bool) { - armName, _ := u.ArmForSwitch(int32(u.Code)) +// ScNonceKey is an XDR Struct defines as: +// +// struct SCNonceKey { +// int64 nonce; +// }; +type ScNonceKey struct { + Nonce Int64 +} - if armName == "InnerResultPair" { - result = *u.InnerResultPair - ok = true +// EncodeTo encodes this value using the Encoder. +func (s *ScNonceKey) EncodeTo(e *xdr.Encoder) error { + var err error + if err = s.Nonce.EncodeTo(e); err != nil { + return err } - - return + return nil } -// MustResults retrieves the Results value from the union, -// panicing if the value is not set. -func (u TransactionResultResult) MustResults() []OperationResult { - val, ok := u.GetResults() +var _ decoderFrom = (*ScNonceKey)(nil) - if !ok { - panic("arm Results is not set") +// DecodeFrom decodes this value using the Decoder. +func (s *ScNonceKey) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding ScNonceKey: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + var err error + var n, nTmp int + nTmp, err = s.Nonce.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Int64: %w", err) } + return n, nil +} - return val +// MarshalBinary implements encoding.BinaryMarshaler. +func (s ScNonceKey) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err } -// GetResults retrieves the Results value from the union, -// returning ok if the union's switch indicated the value is valid. -func (u TransactionResultResult) GetResults() (result []OperationResult, ok bool) { - armName, _ := u.ArmForSwitch(int32(u.Code)) +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *ScNonceKey) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} - if armName == "Results" { - result = *u.Results - ok = true - } +var ( + _ encoding.BinaryMarshaler = (*ScNonceKey)(nil) + _ encoding.BinaryUnmarshaler = (*ScNonceKey)(nil) +) - return +// xdrType signals that this type represents XDR values defined by this package. +func (s ScNonceKey) xdrType() {} + +var _ xdrType = (*ScNonceKey)(nil) + +// ScContractInstance is an XDR Struct defines as: +// +// struct SCContractInstance { +// ContractExecutable executable; +// SCMap* storage; +// }; +type ScContractInstance struct { + Executable ContractExecutable + Storage *ScMap } // EncodeTo encodes this value using the Encoder. -func (u TransactionResultResult) EncodeTo(e *xdr.Encoder) error { +func (s *ScContractInstance) EncodeTo(e *xdr.Encoder) error { var err error - if err = u.Code.EncodeTo(e); err != nil { + if err = s.Executable.EncodeTo(e); err != nil { return err } - switch TransactionResultCode(u.Code) { - case TransactionResultCodeTxFeeBumpInnerSuccess: - if err = (*u.InnerResultPair).EncodeTo(e); err != nil { - return err - } - return nil - case TransactionResultCodeTxFeeBumpInnerFailed: - if err = (*u.InnerResultPair).EncodeTo(e); err != nil { - return err - } - return nil - case TransactionResultCodeTxSuccess: - if _, err = e.EncodeUint(uint32(len((*u.Results)))); err != nil { - return err - } - for i := 0; i < len((*u.Results)); i++ { - if err = (*u.Results)[i].EncodeTo(e); err != nil { - return err - } - } - return nil - case TransactionResultCodeTxFailed: - if _, err = e.EncodeUint(uint32(len((*u.Results)))); err != nil { + if _, err = e.EncodeBool(s.Storage != nil); err != nil { + return err + } + if s.Storage != nil { + if err = (*s.Storage).EncodeTo(e); err != nil { return err } - for i := 0; i < len((*u.Results)); i++ { - if err = (*u.Results)[i].EncodeTo(e); err != nil { - return err - } - } - return nil - case TransactionResultCodeTxTooEarly: - // Void - return nil - case TransactionResultCodeTxTooLate: - // Void - return nil - case TransactionResultCodeTxMissingOperation: - // Void - return nil - case TransactionResultCodeTxBadSeq: - // Void - return nil - case TransactionResultCodeTxBadAuth: - // Void - return nil - case TransactionResultCodeTxInsufficientBalance: - // Void - return nil - case TransactionResultCodeTxNoAccount: - // Void - return nil - case TransactionResultCodeTxInsufficientFee: - // Void - return nil - case TransactionResultCodeTxBadAuthExtra: - // Void - return nil - case TransactionResultCodeTxInternalError: - // Void - return nil - case TransactionResultCodeTxNotSupported: - // Void - return nil - case TransactionResultCodeTxBadSponsorship: - // Void - return nil - case TransactionResultCodeTxBadMinSeqAgeOrGap: - // Void - return nil - case TransactionResultCodeTxMalformed: - // Void - return nil } - return fmt.Errorf("Code (TransactionResultCode) switch value '%d' is not valid for union TransactionResultResult", u.Code) + return nil } -var _ decoderFrom = (*TransactionResultResult)(nil) +var _ decoderFrom = (*ScContractInstance)(nil) // DecodeFrom decodes this value using the Decoder. -func (u *TransactionResultResult) DecodeFrom(d *xdr.Decoder) (int, error) { +func (s *ScContractInstance) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding ScContractInstance: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = u.Code.DecodeFrom(d) + nTmp, err = s.Executable.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding TransactionResultCode: %s", err) + return n, fmt.Errorf("decoding ContractExecutable: %w", err) } - switch TransactionResultCode(u.Code) { - case TransactionResultCodeTxFeeBumpInnerSuccess: - u.InnerResultPair = new(InnerTransactionResultPair) - nTmp, err = (*u.InnerResultPair).DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding InnerTransactionResultPair: %s", err) - } - return n, nil - case TransactionResultCodeTxFeeBumpInnerFailed: - u.InnerResultPair = new(InnerTransactionResultPair) - nTmp, err = (*u.InnerResultPair).DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding InnerTransactionResultPair: %s", err) - } - return n, nil - case TransactionResultCodeTxSuccess: - u.Results = new([]OperationResult) - var l uint32 - l, nTmp, err = d.DecodeUint() - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding OperationResult: %s", err) - } - (*u.Results) = nil - if l > 0 { - (*u.Results) = make([]OperationResult, l) - for i := uint32(0); i < l; i++ { - nTmp, err = (*u.Results)[i].DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding OperationResult: %s", err) - } - } - } - return n, nil - case TransactionResultCodeTxFailed: - u.Results = new([]OperationResult) - var l uint32 - l, nTmp, err = d.DecodeUint() + var b bool + b, nTmp, err = d.DecodeBool() + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ScMap: %w", err) + } + s.Storage = nil + if b { + s.Storage = new(ScMap) + nTmp, err = s.Storage.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding OperationResult: %s", err) - } - (*u.Results) = nil - if l > 0 { - (*u.Results) = make([]OperationResult, l) - for i := uint32(0); i < l; i++ { - nTmp, err = (*u.Results)[i].DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding OperationResult: %s", err) - } - } + return n, fmt.Errorf("decoding ScMap: %w", err) } - return n, nil - case TransactionResultCodeTxTooEarly: - // Void - return n, nil - case TransactionResultCodeTxTooLate: - // Void - return n, nil - case TransactionResultCodeTxMissingOperation: - // Void - return n, nil - case TransactionResultCodeTxBadSeq: - // Void - return n, nil - case TransactionResultCodeTxBadAuth: - // Void - return n, nil - case TransactionResultCodeTxInsufficientBalance: - // Void - return n, nil - case TransactionResultCodeTxNoAccount: - // Void - return n, nil - case TransactionResultCodeTxInsufficientFee: - // Void - return n, nil - case TransactionResultCodeTxBadAuthExtra: - // Void - return n, nil - case TransactionResultCodeTxInternalError: - // Void - return n, nil - case TransactionResultCodeTxNotSupported: - // Void - return n, nil - case TransactionResultCodeTxBadSponsorship: - // Void - return n, nil - case TransactionResultCodeTxBadMinSeqAgeOrGap: - // Void - return n, nil - case TransactionResultCodeTxMalformed: - // Void - return n, nil } - return n, fmt.Errorf("union TransactionResultResult has invalid Code (TransactionResultCode) switch value '%d'", u.Code) + return n, nil } // MarshalBinary implements encoding.BinaryMarshaler. -func (s TransactionResultResult) MarshalBinary() ([]byte, error) { +func (s ScContractInstance) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -36261,500 +52423,1157 @@ func (s TransactionResultResult) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *TransactionResultResult) UnmarshalBinary(inp []byte) error { +func (s *ScContractInstance) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*TransactionResultResult)(nil) - _ encoding.BinaryUnmarshaler = (*TransactionResultResult)(nil) + _ encoding.BinaryMarshaler = (*ScContractInstance)(nil) + _ encoding.BinaryUnmarshaler = (*ScContractInstance)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s TransactionResultResult) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s ScContractInstance) xdrType() {} -var _ xdrType = (*TransactionResultResult)(nil) +var _ xdrType = (*ScContractInstance)(nil) -// TransactionResultExt is an XDR NestedUnion defines as: +// ScVal is an XDR Union defines as: // -// union switch (int v) -// { -// case 0: -// void; -// } -type TransactionResultExt struct { - V int32 +// union SCVal switch (SCValType type) +// { +// +// case SCV_BOOL: +// bool b; +// case SCV_VOID: +// void; +// case SCV_ERROR: +// SCError error; +// +// case SCV_U32: +// uint32 u32; +// case SCV_I32: +// int32 i32; +// +// case SCV_U64: +// uint64 u64; +// case SCV_I64: +// int64 i64; +// case SCV_TIMEPOINT: +// TimePoint timepoint; +// case SCV_DURATION: +// Duration duration; +// +// case SCV_U128: +// UInt128Parts u128; +// case SCV_I128: +// Int128Parts i128; +// +// case SCV_U256: +// UInt256Parts u256; +// case SCV_I256: +// Int256Parts i256; +// +// case SCV_BYTES: +// SCBytes bytes; +// case SCV_STRING: +// SCString str; +// case SCV_SYMBOL: +// SCSymbol sym; +// +// // Vec and Map are recursive so need to live +// // behind an option, due to xdrpp limitations. +// case SCV_VEC: +// SCVec *vec; +// case SCV_MAP: +// SCMap *map; +// +// case SCV_ADDRESS: +// SCAddress address; +// +// // Special SCVals reserved for system-constructed contract-data +// // ledger keys, not generally usable elsewhere. +// case SCV_LEDGER_KEY_CONTRACT_INSTANCE: +// void; +// case SCV_LEDGER_KEY_NONCE: +// SCNonceKey nonce_key; +// +// case SCV_CONTRACT_INSTANCE: +// SCContractInstance instance; +// }; +type ScVal struct { + Type ScValType + B *bool + Error *ScError + U32 *Uint32 + I32 *Int32 + U64 *Uint64 + I64 *Int64 + Timepoint *TimePoint + Duration *Duration + U128 *UInt128Parts + I128 *Int128Parts + U256 *UInt256Parts + I256 *Int256Parts + Bytes *ScBytes + Str *ScString + Sym *ScSymbol + Vec **ScVec + Map **ScMap + Address *ScAddress + NonceKey *ScNonceKey + Instance *ScContractInstance } // SwitchFieldName returns the field name in which this union's // discriminant is stored -func (u TransactionResultExt) SwitchFieldName() string { - return "V" +func (u ScVal) SwitchFieldName() string { + return "Type" } // ArmForSwitch returns which field name should be used for storing -// the value for an instance of TransactionResultExt -func (u TransactionResultExt) ArmForSwitch(sw int32) (string, bool) { - switch int32(sw) { - case 0: +// the value for an instance of ScVal +func (u ScVal) ArmForSwitch(sw int32) (string, bool) { + switch ScValType(sw) { + case ScValTypeScvBool: + return "B", true + case ScValTypeScvVoid: + return "", true + case ScValTypeScvError: + return "Error", true + case ScValTypeScvU32: + return "U32", true + case ScValTypeScvI32: + return "I32", true + case ScValTypeScvU64: + return "U64", true + case ScValTypeScvI64: + return "I64", true + case ScValTypeScvTimepoint: + return "Timepoint", true + case ScValTypeScvDuration: + return "Duration", true + case ScValTypeScvU128: + return "U128", true + case ScValTypeScvI128: + return "I128", true + case ScValTypeScvU256: + return "U256", true + case ScValTypeScvI256: + return "I256", true + case ScValTypeScvBytes: + return "Bytes", true + case ScValTypeScvString: + return "Str", true + case ScValTypeScvSymbol: + return "Sym", true + case ScValTypeScvVec: + return "Vec", true + case ScValTypeScvMap: + return "Map", true + case ScValTypeScvAddress: + return "Address", true + case ScValTypeScvLedgerKeyContractInstance: return "", true + case ScValTypeScvLedgerKeyNonce: + return "NonceKey", true + case ScValTypeScvContractInstance: + return "Instance", true } return "-", false } -// NewTransactionResultExt creates a new TransactionResultExt. -func NewTransactionResultExt(v int32, value interface{}) (result TransactionResultExt, err error) { - result.V = v - switch int32(v) { - case 0: +// NewScVal creates a new ScVal. +func NewScVal(aType ScValType, value interface{}) (result ScVal, err error) { + result.Type = aType + switch ScValType(aType) { + case ScValTypeScvBool: + tv, ok := value.(bool) + if !ok { + err = errors.New("invalid value, must be bool") + return + } + result.B = &tv + case ScValTypeScvVoid: + // void + case ScValTypeScvError: + tv, ok := value.(ScError) + if !ok { + err = errors.New("invalid value, must be ScError") + return + } + result.Error = &tv + case ScValTypeScvU32: + tv, ok := value.(Uint32) + if !ok { + err = errors.New("invalid value, must be Uint32") + return + } + result.U32 = &tv + case ScValTypeScvI32: + tv, ok := value.(Int32) + if !ok { + err = errors.New("invalid value, must be Int32") + return + } + result.I32 = &tv + case ScValTypeScvU64: + tv, ok := value.(Uint64) + if !ok { + err = errors.New("invalid value, must be Uint64") + return + } + result.U64 = &tv + case ScValTypeScvI64: + tv, ok := value.(Int64) + if !ok { + err = errors.New("invalid value, must be Int64") + return + } + result.I64 = &tv + case ScValTypeScvTimepoint: + tv, ok := value.(TimePoint) + if !ok { + err = errors.New("invalid value, must be TimePoint") + return + } + result.Timepoint = &tv + case ScValTypeScvDuration: + tv, ok := value.(Duration) + if !ok { + err = errors.New("invalid value, must be Duration") + return + } + result.Duration = &tv + case ScValTypeScvU128: + tv, ok := value.(UInt128Parts) + if !ok { + err = errors.New("invalid value, must be UInt128Parts") + return + } + result.U128 = &tv + case ScValTypeScvI128: + tv, ok := value.(Int128Parts) + if !ok { + err = errors.New("invalid value, must be Int128Parts") + return + } + result.I128 = &tv + case ScValTypeScvU256: + tv, ok := value.(UInt256Parts) + if !ok { + err = errors.New("invalid value, must be UInt256Parts") + return + } + result.U256 = &tv + case ScValTypeScvI256: + tv, ok := value.(Int256Parts) + if !ok { + err = errors.New("invalid value, must be Int256Parts") + return + } + result.I256 = &tv + case ScValTypeScvBytes: + tv, ok := value.(ScBytes) + if !ok { + err = errors.New("invalid value, must be ScBytes") + return + } + result.Bytes = &tv + case ScValTypeScvString: + tv, ok := value.(ScString) + if !ok { + err = errors.New("invalid value, must be ScString") + return + } + result.Str = &tv + case ScValTypeScvSymbol: + tv, ok := value.(ScSymbol) + if !ok { + err = errors.New("invalid value, must be ScSymbol") + return + } + result.Sym = &tv + case ScValTypeScvVec: + tv, ok := value.(*ScVec) + if !ok { + err = errors.New("invalid value, must be *ScVec") + return + } + result.Vec = &tv + case ScValTypeScvMap: + tv, ok := value.(*ScMap) + if !ok { + err = errors.New("invalid value, must be *ScMap") + return + } + result.Map = &tv + case ScValTypeScvAddress: + tv, ok := value.(ScAddress) + if !ok { + err = errors.New("invalid value, must be ScAddress") + return + } + result.Address = &tv + case ScValTypeScvLedgerKeyContractInstance: // void + case ScValTypeScvLedgerKeyNonce: + tv, ok := value.(ScNonceKey) + if !ok { + err = errors.New("invalid value, must be ScNonceKey") + return + } + result.NonceKey = &tv + case ScValTypeScvContractInstance: + tv, ok := value.(ScContractInstance) + if !ok { + err = errors.New("invalid value, must be ScContractInstance") + return + } + result.Instance = &tv } return } -// EncodeTo encodes this value using the Encoder. -func (u TransactionResultExt) EncodeTo(e *xdr.Encoder) error { - var err error - if _, err = e.EncodeInt(int32(u.V)); err != nil { - return err +// MustB retrieves the B value from the union, +// panicing if the value is not set. +func (u ScVal) MustB() bool { + val, ok := u.GetB() + + if !ok { + panic("arm B is not set") } - switch int32(u.V) { - case 0: - // Void - return nil + + return val +} + +// GetB retrieves the B value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u ScVal) GetB() (result bool, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) + + if armName == "B" { + result = *u.B + ok = true } - return fmt.Errorf("V (int32) switch value '%d' is not valid for union TransactionResultExt", u.V) + + return } -var _ decoderFrom = (*TransactionResultExt)(nil) +// MustError retrieves the Error value from the union, +// panicing if the value is not set. +func (u ScVal) MustError() ScError { + val, ok := u.GetError() -// DecodeFrom decodes this value using the Decoder. -func (u *TransactionResultExt) DecodeFrom(d *xdr.Decoder) (int, error) { - var err error - var n, nTmp int - u.V, nTmp, err = d.DecodeInt() - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Int: %s", err) + if !ok { + panic("arm Error is not set") } - switch int32(u.V) { - case 0: - // Void - return n, nil + + return val +} + +// GetError retrieves the Error value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u ScVal) GetError() (result ScError, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) + + if armName == "Error" { + result = *u.Error + ok = true } - return n, fmt.Errorf("union TransactionResultExt has invalid V (int32) switch value '%d'", u.V) + + return } -// MarshalBinary implements encoding.BinaryMarshaler. -func (s TransactionResultExt) MarshalBinary() ([]byte, error) { - b := bytes.Buffer{} - e := xdr.NewEncoder(&b) - err := s.EncodeTo(e) - return b.Bytes(), err +// MustU32 retrieves the U32 value from the union, +// panicing if the value is not set. +func (u ScVal) MustU32() Uint32 { + val, ok := u.GetU32() + + if !ok { + panic("arm U32 is not set") + } + + return val } -// UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *TransactionResultExt) UnmarshalBinary(inp []byte) error { - r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) - return err +// GetU32 retrieves the U32 value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u ScVal) GetU32() (result Uint32, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) + + if armName == "U32" { + result = *u.U32 + ok = true + } + + return } -var ( - _ encoding.BinaryMarshaler = (*TransactionResultExt)(nil) - _ encoding.BinaryUnmarshaler = (*TransactionResultExt)(nil) -) +// MustI32 retrieves the I32 value from the union, +// panicing if the value is not set. +func (u ScVal) MustI32() Int32 { + val, ok := u.GetI32() -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s TransactionResultExt) xdrType() {} + if !ok { + panic("arm I32 is not set") + } -var _ xdrType = (*TransactionResultExt)(nil) + return val +} -// TransactionResult is an XDR Struct defines as: -// -// struct TransactionResult -// { -// int64 feeCharged; // actual fee charged for the transaction -// -// union switch (TransactionResultCode code) -// { -// case txFEE_BUMP_INNER_SUCCESS: -// case txFEE_BUMP_INNER_FAILED: -// InnerTransactionResultPair innerResultPair; -// case txSUCCESS: -// case txFAILED: -// OperationResult results<>; -// case txTOO_EARLY: -// case txTOO_LATE: -// case txMISSING_OPERATION: -// case txBAD_SEQ: -// case txBAD_AUTH: -// case txINSUFFICIENT_BALANCE: -// case txNO_ACCOUNT: -// case txINSUFFICIENT_FEE: -// case txBAD_AUTH_EXTRA: -// case txINTERNAL_ERROR: -// case txNOT_SUPPORTED: -// // case txFEE_BUMP_INNER_FAILED: handled above -// case txBAD_SPONSORSHIP: -// case txBAD_MIN_SEQ_AGE_OR_GAP: -// case txMALFORMED: -// void; -// } -// result; -// -// // reserved for future use -// union switch (int v) -// { -// case 0: -// void; -// } -// ext; -// }; -type TransactionResult struct { - FeeCharged Int64 - Result TransactionResultResult - Ext TransactionResultExt +// GetI32 retrieves the I32 value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u ScVal) GetI32() (result Int32, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) + + if armName == "I32" { + result = *u.I32 + ok = true + } + + return } -// EncodeTo encodes this value using the Encoder. -func (s *TransactionResult) EncodeTo(e *xdr.Encoder) error { - var err error - if err = s.FeeCharged.EncodeTo(e); err != nil { - return err +// MustU64 retrieves the U64 value from the union, +// panicing if the value is not set. +func (u ScVal) MustU64() Uint64 { + val, ok := u.GetU64() + + if !ok { + panic("arm U64 is not set") } - if err = s.Result.EncodeTo(e); err != nil { - return err + + return val +} + +// GetU64 retrieves the U64 value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u ScVal) GetU64() (result Uint64, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) + + if armName == "U64" { + result = *u.U64 + ok = true } - if err = s.Ext.EncodeTo(e); err != nil { - return err + + return +} + +// MustI64 retrieves the I64 value from the union, +// panicing if the value is not set. +func (u ScVal) MustI64() Int64 { + val, ok := u.GetI64() + + if !ok { + panic("arm I64 is not set") } - return nil + + return val +} + +// GetI64 retrieves the I64 value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u ScVal) GetI64() (result Int64, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) + + if armName == "I64" { + result = *u.I64 + ok = true + } + + return } -var _ decoderFrom = (*TransactionResult)(nil) +// MustTimepoint retrieves the Timepoint value from the union, +// panicing if the value is not set. +func (u ScVal) MustTimepoint() TimePoint { + val, ok := u.GetTimepoint() -// DecodeFrom decodes this value using the Decoder. -func (s *TransactionResult) DecodeFrom(d *xdr.Decoder) (int, error) { - var err error - var n, nTmp int - nTmp, err = s.FeeCharged.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Int64: %s", err) - } - nTmp, err = s.Result.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding TransactionResultResult: %s", err) + if !ok { + panic("arm Timepoint is not set") } - nTmp, err = s.Ext.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding TransactionResultExt: %s", err) + + return val +} + +// GetTimepoint retrieves the Timepoint value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u ScVal) GetTimepoint() (result TimePoint, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) + + if armName == "Timepoint" { + result = *u.Timepoint + ok = true } - return n, nil + + return } -// MarshalBinary implements encoding.BinaryMarshaler. -func (s TransactionResult) MarshalBinary() ([]byte, error) { - b := bytes.Buffer{} - e := xdr.NewEncoder(&b) - err := s.EncodeTo(e) - return b.Bytes(), err +// MustDuration retrieves the Duration value from the union, +// panicing if the value is not set. +func (u ScVal) MustDuration() Duration { + val, ok := u.GetDuration() + + if !ok { + panic("arm Duration is not set") + } + + return val } -// UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *TransactionResult) UnmarshalBinary(inp []byte) error { - r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) - return err +// GetDuration retrieves the Duration value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u ScVal) GetDuration() (result Duration, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) + + if armName == "Duration" { + result = *u.Duration + ok = true + } + + return } -var ( - _ encoding.BinaryMarshaler = (*TransactionResult)(nil) - _ encoding.BinaryUnmarshaler = (*TransactionResult)(nil) -) +// MustU128 retrieves the U128 value from the union, +// panicing if the value is not set. +func (u ScVal) MustU128() UInt128Parts { + val, ok := u.GetU128() -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s TransactionResult) xdrType() {} + if !ok { + panic("arm U128 is not set") + } -var _ xdrType = (*TransactionResult)(nil) + return val +} -// Hash is an XDR Typedef defines as: -// -// typedef opaque Hash[32]; -type Hash [32]byte +// GetU128 retrieves the U128 value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u ScVal) GetU128() (result UInt128Parts, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) -// XDRMaxSize implements the Sized interface for Hash -func (e Hash) XDRMaxSize() int { - return 32 + if armName == "U128" { + result = *u.U128 + ok = true + } + + return } -// EncodeTo encodes this value using the Encoder. -func (s *Hash) EncodeTo(e *xdr.Encoder) error { - var err error - if _, err = e.EncodeFixedOpaque(s[:]); err != nil { - return err +// MustI128 retrieves the I128 value from the union, +// panicing if the value is not set. +func (u ScVal) MustI128() Int128Parts { + val, ok := u.GetI128() + + if !ok { + panic("arm I128 is not set") } - return nil + + return val } -var _ decoderFrom = (*Hash)(nil) +// GetI128 retrieves the I128 value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u ScVal) GetI128() (result Int128Parts, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) -// DecodeFrom decodes this value using the Decoder. -func (s *Hash) DecodeFrom(d *xdr.Decoder) (int, error) { - var err error - var n, nTmp int - nTmp, err = d.DecodeFixedOpaqueInplace(s[:]) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Hash: %s", err) + if armName == "I128" { + result = *u.I128 + ok = true } - return n, nil + + return } -// MarshalBinary implements encoding.BinaryMarshaler. -func (s Hash) MarshalBinary() ([]byte, error) { - b := bytes.Buffer{} - e := xdr.NewEncoder(&b) - err := s.EncodeTo(e) - return b.Bytes(), err +// MustU256 retrieves the U256 value from the union, +// panicing if the value is not set. +func (u ScVal) MustU256() UInt256Parts { + val, ok := u.GetU256() + + if !ok { + panic("arm U256 is not set") + } + + return val } -// UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *Hash) UnmarshalBinary(inp []byte) error { - r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) - return err +// GetU256 retrieves the U256 value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u ScVal) GetU256() (result UInt256Parts, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) + + if armName == "U256" { + result = *u.U256 + ok = true + } + + return } -var ( - _ encoding.BinaryMarshaler = (*Hash)(nil) - _ encoding.BinaryUnmarshaler = (*Hash)(nil) -) +// MustI256 retrieves the I256 value from the union, +// panicing if the value is not set. +func (u ScVal) MustI256() Int256Parts { + val, ok := u.GetI256() -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s Hash) xdrType() {} + if !ok { + panic("arm I256 is not set") + } -var _ xdrType = (*Hash)(nil) + return val +} -// Uint256 is an XDR Typedef defines as: -// -// typedef opaque uint256[32]; -type Uint256 [32]byte +// GetI256 retrieves the I256 value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u ScVal) GetI256() (result Int256Parts, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) -// XDRMaxSize implements the Sized interface for Uint256 -func (e Uint256) XDRMaxSize() int { - return 32 + if armName == "I256" { + result = *u.I256 + ok = true + } + + return } -// EncodeTo encodes this value using the Encoder. -func (s *Uint256) EncodeTo(e *xdr.Encoder) error { - var err error - if _, err = e.EncodeFixedOpaque(s[:]); err != nil { - return err +// MustBytes retrieves the Bytes value from the union, +// panicing if the value is not set. +func (u ScVal) MustBytes() ScBytes { + val, ok := u.GetBytes() + + if !ok { + panic("arm Bytes is not set") } - return nil + + return val } -var _ decoderFrom = (*Uint256)(nil) +// GetBytes retrieves the Bytes value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u ScVal) GetBytes() (result ScBytes, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) -// DecodeFrom decodes this value using the Decoder. -func (s *Uint256) DecodeFrom(d *xdr.Decoder) (int, error) { - var err error - var n, nTmp int - nTmp, err = d.DecodeFixedOpaqueInplace(s[:]) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Uint256: %s", err) + if armName == "Bytes" { + result = *u.Bytes + ok = true } - return n, nil + + return } -// MarshalBinary implements encoding.BinaryMarshaler. -func (s Uint256) MarshalBinary() ([]byte, error) { - b := bytes.Buffer{} - e := xdr.NewEncoder(&b) - err := s.EncodeTo(e) - return b.Bytes(), err +// MustStr retrieves the Str value from the union, +// panicing if the value is not set. +func (u ScVal) MustStr() ScString { + val, ok := u.GetStr() + + if !ok { + panic("arm Str is not set") + } + + return val } -// UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *Uint256) UnmarshalBinary(inp []byte) error { - r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) - return err +// GetStr retrieves the Str value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u ScVal) GetStr() (result ScString, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) + + if armName == "Str" { + result = *u.Str + ok = true + } + + return } -var ( - _ encoding.BinaryMarshaler = (*Uint256)(nil) - _ encoding.BinaryUnmarshaler = (*Uint256)(nil) -) +// MustSym retrieves the Sym value from the union, +// panicing if the value is not set. +func (u ScVal) MustSym() ScSymbol { + val, ok := u.GetSym() -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s Uint256) xdrType() {} + if !ok { + panic("arm Sym is not set") + } -var _ xdrType = (*Uint256)(nil) + return val +} -// Uint32 is an XDR Typedef defines as: -// -// typedef unsigned int uint32; -type Uint32 uint32 +// GetSym retrieves the Sym value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u ScVal) GetSym() (result ScSymbol, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) -// EncodeTo encodes this value using the Encoder. -func (s Uint32) EncodeTo(e *xdr.Encoder) error { - var err error - if _, err = e.EncodeUint(uint32(s)); err != nil { - return err + if armName == "Sym" { + result = *u.Sym + ok = true } - return nil + + return } -var _ decoderFrom = (*Uint32)(nil) +// MustVec retrieves the Vec value from the union, +// panicing if the value is not set. +func (u ScVal) MustVec() *ScVec { + val, ok := u.GetVec() -// DecodeFrom decodes this value using the Decoder. -func (s *Uint32) DecodeFrom(d *xdr.Decoder) (int, error) { - var err error - var n, nTmp int - var v uint32 - v, nTmp, err = d.DecodeUint() - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Unsigned int: %s", err) + if !ok { + panic("arm Vec is not set") } - *s = Uint32(v) - return n, nil + + return val } -// MarshalBinary implements encoding.BinaryMarshaler. -func (s Uint32) MarshalBinary() ([]byte, error) { - b := bytes.Buffer{} - e := xdr.NewEncoder(&b) - err := s.EncodeTo(e) - return b.Bytes(), err +// GetVec retrieves the Vec value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u ScVal) GetVec() (result *ScVec, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) + + if armName == "Vec" { + result = *u.Vec + ok = true + } + + return } -// UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *Uint32) UnmarshalBinary(inp []byte) error { - r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) - return err +// MustMap retrieves the Map value from the union, +// panicing if the value is not set. +func (u ScVal) MustMap() *ScMap { + val, ok := u.GetMap() + + if !ok { + panic("arm Map is not set") + } + + return val } -var ( - _ encoding.BinaryMarshaler = (*Uint32)(nil) - _ encoding.BinaryUnmarshaler = (*Uint32)(nil) -) +// GetMap retrieves the Map value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u ScVal) GetMap() (result *ScMap, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s Uint32) xdrType() {} + if armName == "Map" { + result = *u.Map + ok = true + } -var _ xdrType = (*Uint32)(nil) + return +} -// Int32 is an XDR Typedef defines as: -// -// typedef int int32; -type Int32 int32 +// MustAddress retrieves the Address value from the union, +// panicing if the value is not set. +func (u ScVal) MustAddress() ScAddress { + val, ok := u.GetAddress() -// EncodeTo encodes this value using the Encoder. -func (s Int32) EncodeTo(e *xdr.Encoder) error { - var err error - if _, err = e.EncodeInt(int32(s)); err != nil { - return err + if !ok { + panic("arm Address is not set") } - return nil + + return val } -var _ decoderFrom = (*Int32)(nil) +// GetAddress retrieves the Address value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u ScVal) GetAddress() (result ScAddress, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) -// DecodeFrom decodes this value using the Decoder. -func (s *Int32) DecodeFrom(d *xdr.Decoder) (int, error) { - var err error - var n, nTmp int - var v int32 - v, nTmp, err = d.DecodeInt() - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Int: %s", err) + if armName == "Address" { + result = *u.Address + ok = true } - *s = Int32(v) - return n, nil + + return } -// MarshalBinary implements encoding.BinaryMarshaler. -func (s Int32) MarshalBinary() ([]byte, error) { - b := bytes.Buffer{} - e := xdr.NewEncoder(&b) - err := s.EncodeTo(e) - return b.Bytes(), err +// MustNonceKey retrieves the NonceKey value from the union, +// panicing if the value is not set. +func (u ScVal) MustNonceKey() ScNonceKey { + val, ok := u.GetNonceKey() + + if !ok { + panic("arm NonceKey is not set") + } + + return val } -// UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *Int32) UnmarshalBinary(inp []byte) error { - r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) - return err +// GetNonceKey retrieves the NonceKey value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u ScVal) GetNonceKey() (result ScNonceKey, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) + + if armName == "NonceKey" { + result = *u.NonceKey + ok = true + } + + return } -var ( - _ encoding.BinaryMarshaler = (*Int32)(nil) - _ encoding.BinaryUnmarshaler = (*Int32)(nil) -) +// MustInstance retrieves the Instance value from the union, +// panicing if the value is not set. +func (u ScVal) MustInstance() ScContractInstance { + val, ok := u.GetInstance() -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s Int32) xdrType() {} + if !ok { + panic("arm Instance is not set") + } -var _ xdrType = (*Int32)(nil) + return val +} -// Uint64 is an XDR Typedef defines as: -// -// typedef unsigned hyper uint64; -type Uint64 uint64 +// GetInstance retrieves the Instance value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u ScVal) GetInstance() (result ScContractInstance, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) + + if armName == "Instance" { + result = *u.Instance + ok = true + } + + return +} // EncodeTo encodes this value using the Encoder. -func (s Uint64) EncodeTo(e *xdr.Encoder) error { +func (u ScVal) EncodeTo(e *xdr.Encoder) error { var err error - if _, err = e.EncodeUhyper(uint64(s)); err != nil { + if err = u.Type.EncodeTo(e); err != nil { return err } - return nil + switch ScValType(u.Type) { + case ScValTypeScvBool: + if _, err = e.EncodeBool(bool((*u.B))); err != nil { + return err + } + return nil + case ScValTypeScvVoid: + // Void + return nil + case ScValTypeScvError: + if err = (*u.Error).EncodeTo(e); err != nil { + return err + } + return nil + case ScValTypeScvU32: + if err = (*u.U32).EncodeTo(e); err != nil { + return err + } + return nil + case ScValTypeScvI32: + if err = (*u.I32).EncodeTo(e); err != nil { + return err + } + return nil + case ScValTypeScvU64: + if err = (*u.U64).EncodeTo(e); err != nil { + return err + } + return nil + case ScValTypeScvI64: + if err = (*u.I64).EncodeTo(e); err != nil { + return err + } + return nil + case ScValTypeScvTimepoint: + if err = (*u.Timepoint).EncodeTo(e); err != nil { + return err + } + return nil + case ScValTypeScvDuration: + if err = (*u.Duration).EncodeTo(e); err != nil { + return err + } + return nil + case ScValTypeScvU128: + if err = (*u.U128).EncodeTo(e); err != nil { + return err + } + return nil + case ScValTypeScvI128: + if err = (*u.I128).EncodeTo(e); err != nil { + return err + } + return nil + case ScValTypeScvU256: + if err = (*u.U256).EncodeTo(e); err != nil { + return err + } + return nil + case ScValTypeScvI256: + if err = (*u.I256).EncodeTo(e); err != nil { + return err + } + return nil + case ScValTypeScvBytes: + if err = (*u.Bytes).EncodeTo(e); err != nil { + return err + } + return nil + case ScValTypeScvString: + if err = (*u.Str).EncodeTo(e); err != nil { + return err + } + return nil + case ScValTypeScvSymbol: + if err = (*u.Sym).EncodeTo(e); err != nil { + return err + } + return nil + case ScValTypeScvVec: + if _, err = e.EncodeBool((*u.Vec) != nil); err != nil { + return err + } + if (*u.Vec) != nil { + if err = (*(*u.Vec)).EncodeTo(e); err != nil { + return err + } + } + return nil + case ScValTypeScvMap: + if _, err = e.EncodeBool((*u.Map) != nil); err != nil { + return err + } + if (*u.Map) != nil { + if err = (*(*u.Map)).EncodeTo(e); err != nil { + return err + } + } + return nil + case ScValTypeScvAddress: + if err = (*u.Address).EncodeTo(e); err != nil { + return err + } + return nil + case ScValTypeScvLedgerKeyContractInstance: + // Void + return nil + case ScValTypeScvLedgerKeyNonce: + if err = (*u.NonceKey).EncodeTo(e); err != nil { + return err + } + return nil + case ScValTypeScvContractInstance: + if err = (*u.Instance).EncodeTo(e); err != nil { + return err + } + return nil + } + return fmt.Errorf("Type (ScValType) switch value '%d' is not valid for union ScVal", u.Type) } -var _ decoderFrom = (*Uint64)(nil) +var _ decoderFrom = (*ScVal)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *Uint64) DecodeFrom(d *xdr.Decoder) (int, error) { +func (u *ScVal) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding ScVal: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - var v uint64 - v, nTmp, err = d.DecodeUhyper() + nTmp, err = u.Type.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Unsigned hyper: %s", err) + return n, fmt.Errorf("decoding ScValType: %w", err) + } + switch ScValType(u.Type) { + case ScValTypeScvBool: + u.B = new(bool) + (*u.B), nTmp, err = d.DecodeBool() + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Bool: %w", err) + } + return n, nil + case ScValTypeScvVoid: + // Void + return n, nil + case ScValTypeScvError: + u.Error = new(ScError) + nTmp, err = (*u.Error).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ScError: %w", err) + } + return n, nil + case ScValTypeScvU32: + u.U32 = new(Uint32) + nTmp, err = (*u.U32).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Uint32: %w", err) + } + return n, nil + case ScValTypeScvI32: + u.I32 = new(Int32) + nTmp, err = (*u.I32).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Int32: %w", err) + } + return n, nil + case ScValTypeScvU64: + u.U64 = new(Uint64) + nTmp, err = (*u.U64).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Uint64: %w", err) + } + return n, nil + case ScValTypeScvI64: + u.I64 = new(Int64) + nTmp, err = (*u.I64).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Int64: %w", err) + } + return n, nil + case ScValTypeScvTimepoint: + u.Timepoint = new(TimePoint) + nTmp, err = (*u.Timepoint).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding TimePoint: %w", err) + } + return n, nil + case ScValTypeScvDuration: + u.Duration = new(Duration) + nTmp, err = (*u.Duration).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Duration: %w", err) + } + return n, nil + case ScValTypeScvU128: + u.U128 = new(UInt128Parts) + nTmp, err = (*u.U128).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding UInt128Parts: %w", err) + } + return n, nil + case ScValTypeScvI128: + u.I128 = new(Int128Parts) + nTmp, err = (*u.I128).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Int128Parts: %w", err) + } + return n, nil + case ScValTypeScvU256: + u.U256 = new(UInt256Parts) + nTmp, err = (*u.U256).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding UInt256Parts: %w", err) + } + return n, nil + case ScValTypeScvI256: + u.I256 = new(Int256Parts) + nTmp, err = (*u.I256).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Int256Parts: %w", err) + } + return n, nil + case ScValTypeScvBytes: + u.Bytes = new(ScBytes) + nTmp, err = (*u.Bytes).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ScBytes: %w", err) + } + return n, nil + case ScValTypeScvString: + u.Str = new(ScString) + nTmp, err = (*u.Str).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ScString: %w", err) + } + return n, nil + case ScValTypeScvSymbol: + u.Sym = new(ScSymbol) + nTmp, err = (*u.Sym).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ScSymbol: %w", err) + } + return n, nil + case ScValTypeScvVec: + u.Vec = new(*ScVec) + var b bool + b, nTmp, err = d.DecodeBool() + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ScVec: %w", err) + } + (*u.Vec) = nil + if b { + (*u.Vec) = new(ScVec) + nTmp, err = (*u.Vec).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ScVec: %w", err) + } + } + return n, nil + case ScValTypeScvMap: + u.Map = new(*ScMap) + var b bool + b, nTmp, err = d.DecodeBool() + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ScMap: %w", err) + } + (*u.Map) = nil + if b { + (*u.Map) = new(ScMap) + nTmp, err = (*u.Map).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ScMap: %w", err) + } + } + return n, nil + case ScValTypeScvAddress: + u.Address = new(ScAddress) + nTmp, err = (*u.Address).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ScAddress: %w", err) + } + return n, nil + case ScValTypeScvLedgerKeyContractInstance: + // Void + return n, nil + case ScValTypeScvLedgerKeyNonce: + u.NonceKey = new(ScNonceKey) + nTmp, err = (*u.NonceKey).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ScNonceKey: %w", err) + } + return n, nil + case ScValTypeScvContractInstance: + u.Instance = new(ScContractInstance) + nTmp, err = (*u.Instance).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ScContractInstance: %w", err) + } + return n, nil } - *s = Uint64(v) - return n, nil + return n, fmt.Errorf("union ScVal has invalid Type (ScValType) switch value '%d'", u.Type) } // MarshalBinary implements encoding.BinaryMarshaler. -func (s Uint64) MarshalBinary() ([]byte, error) { +func (s ScVal) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -36762,56 +53581,74 @@ func (s Uint64) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *Uint64) UnmarshalBinary(inp []byte) error { +func (s *ScVal) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*Uint64)(nil) - _ encoding.BinaryUnmarshaler = (*Uint64)(nil) + _ encoding.BinaryMarshaler = (*ScVal)(nil) + _ encoding.BinaryUnmarshaler = (*ScVal)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s Uint64) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s ScVal) xdrType() {} -var _ xdrType = (*Uint64)(nil) +var _ xdrType = (*ScVal)(nil) -// Int64 is an XDR Typedef defines as: +// ScMapEntry is an XDR Struct defines as: // -// typedef hyper int64; -type Int64 int64 +// struct SCMapEntry +// { +// SCVal key; +// SCVal val; +// }; +type ScMapEntry struct { + Key ScVal + Val ScVal +} // EncodeTo encodes this value using the Encoder. -func (s Int64) EncodeTo(e *xdr.Encoder) error { +func (s *ScMapEntry) EncodeTo(e *xdr.Encoder) error { var err error - if _, err = e.EncodeHyper(int64(s)); err != nil { + if err = s.Key.EncodeTo(e); err != nil { + return err + } + if err = s.Val.EncodeTo(e); err != nil { return err } return nil } -var _ decoderFrom = (*Int64)(nil) +var _ decoderFrom = (*ScMapEntry)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *Int64) DecodeFrom(d *xdr.Decoder) (int, error) { +func (s *ScMapEntry) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding ScMapEntry: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - var v int64 - v, nTmp, err = d.DecodeHyper() + nTmp, err = s.Key.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Hyper: %s", err) + return n, fmt.Errorf("decoding ScVal: %w", err) + } + nTmp, err = s.Val.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ScVal: %w", err) } - *s = Int64(v) return n, nil } // MarshalBinary implements encoding.BinaryMarshaler. -func (s Int64) MarshalBinary() ([]byte, error) { +func (s ScMapEntry) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -36819,270 +53656,189 @@ func (s Int64) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *Int64) UnmarshalBinary(inp []byte) error { +func (s *ScMapEntry) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*Int64)(nil) - _ encoding.BinaryUnmarshaler = (*Int64)(nil) + _ encoding.BinaryMarshaler = (*ScMapEntry)(nil) + _ encoding.BinaryUnmarshaler = (*ScMapEntry)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s Int64) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s ScMapEntry) xdrType() {} -var _ xdrType = (*Int64)(nil) +var _ xdrType = (*ScMapEntry)(nil) -// ExtensionPoint is an XDR Union defines as: +// StoredTransactionSet is an XDR Union defines as: // -// union ExtensionPoint switch (int v) +// union StoredTransactionSet switch (int v) // { // case 0: -// void; +// TransactionSet txSet; +// case 1: +// GeneralizedTransactionSet generalizedTxSet; // }; -type ExtensionPoint struct { - V int32 +type StoredTransactionSet struct { + V int32 + TxSet *TransactionSet + GeneralizedTxSet *GeneralizedTransactionSet } // SwitchFieldName returns the field name in which this union's // discriminant is stored -func (u ExtensionPoint) SwitchFieldName() string { +func (u StoredTransactionSet) SwitchFieldName() string { return "V" } // ArmForSwitch returns which field name should be used for storing -// the value for an instance of ExtensionPoint -func (u ExtensionPoint) ArmForSwitch(sw int32) (string, bool) { +// the value for an instance of StoredTransactionSet +func (u StoredTransactionSet) ArmForSwitch(sw int32) (string, bool) { switch int32(sw) { case 0: - return "", true + return "TxSet", true + case 1: + return "GeneralizedTxSet", true } return "-", false } -// NewExtensionPoint creates a new ExtensionPoint. -func NewExtensionPoint(v int32, value interface{}) (result ExtensionPoint, err error) { +// NewStoredTransactionSet creates a new StoredTransactionSet. +func NewStoredTransactionSet(v int32, value interface{}) (result StoredTransactionSet, err error) { result.V = v switch int32(v) { case 0: - // void + tv, ok := value.(TransactionSet) + if !ok { + err = errors.New("invalid value, must be TransactionSet") + return + } + result.TxSet = &tv + case 1: + tv, ok := value.(GeneralizedTransactionSet) + if !ok { + err = errors.New("invalid value, must be GeneralizedTransactionSet") + return + } + result.GeneralizedTxSet = &tv } return } -// EncodeTo encodes this value using the Encoder. -func (u ExtensionPoint) EncodeTo(e *xdr.Encoder) error { - var err error - if _, err = e.EncodeInt(int32(u.V)); err != nil { - return err - } - switch int32(u.V) { - case 0: - // Void - return nil - } - return fmt.Errorf("V (int32) switch value '%d' is not valid for union ExtensionPoint", u.V) -} - -var _ decoderFrom = (*ExtensionPoint)(nil) +// MustTxSet retrieves the TxSet value from the union, +// panicing if the value is not set. +func (u StoredTransactionSet) MustTxSet() TransactionSet { + val, ok := u.GetTxSet() -// DecodeFrom decodes this value using the Decoder. -func (u *ExtensionPoint) DecodeFrom(d *xdr.Decoder) (int, error) { - var err error - var n, nTmp int - u.V, nTmp, err = d.DecodeInt() - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Int: %s", err) - } - switch int32(u.V) { - case 0: - // Void - return n, nil + if !ok { + panic("arm TxSet is not set") } - return n, fmt.Errorf("union ExtensionPoint has invalid V (int32) switch value '%d'", u.V) -} - -// MarshalBinary implements encoding.BinaryMarshaler. -func (s ExtensionPoint) MarshalBinary() ([]byte, error) { - b := bytes.Buffer{} - e := xdr.NewEncoder(&b) - err := s.EncodeTo(e) - return b.Bytes(), err -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *ExtensionPoint) UnmarshalBinary(inp []byte) error { - r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) - return err -} - -var ( - _ encoding.BinaryMarshaler = (*ExtensionPoint)(nil) - _ encoding.BinaryUnmarshaler = (*ExtensionPoint)(nil) -) - -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s ExtensionPoint) xdrType() {} - -var _ xdrType = (*ExtensionPoint)(nil) - -// CryptoKeyType is an XDR Enum defines as: -// -// enum CryptoKeyType -// { -// KEY_TYPE_ED25519 = 0, -// KEY_TYPE_PRE_AUTH_TX = 1, -// KEY_TYPE_HASH_X = 2, -// KEY_TYPE_ED25519_SIGNED_PAYLOAD = 3, -// // MUXED enum values for supported type are derived from the enum values -// // above by ORing them with 0x100 -// KEY_TYPE_MUXED_ED25519 = 0x100 -// }; -type CryptoKeyType int32 - -const ( - CryptoKeyTypeKeyTypeEd25519 CryptoKeyType = 0 - CryptoKeyTypeKeyTypePreAuthTx CryptoKeyType = 1 - CryptoKeyTypeKeyTypeHashX CryptoKeyType = 2 - CryptoKeyTypeKeyTypeEd25519SignedPayload CryptoKeyType = 3 - CryptoKeyTypeKeyTypeMuxedEd25519 CryptoKeyType = 256 -) - -var cryptoKeyTypeMap = map[int32]string{ - 0: "CryptoKeyTypeKeyTypeEd25519", - 1: "CryptoKeyTypeKeyTypePreAuthTx", - 2: "CryptoKeyTypeKeyTypeHashX", - 3: "CryptoKeyTypeKeyTypeEd25519SignedPayload", - 256: "CryptoKeyTypeKeyTypeMuxedEd25519", -} -// ValidEnum validates a proposed value for this enum. Implements -// the Enum interface for CryptoKeyType -func (e CryptoKeyType) ValidEnum(v int32) bool { - _, ok := cryptoKeyTypeMap[v] - return ok + return val } -// String returns the name of `e` -func (e CryptoKeyType) String() string { - name, _ := cryptoKeyTypeMap[int32(e)] - return name -} +// GetTxSet retrieves the TxSet value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u StoredTransactionSet) GetTxSet() (result TransactionSet, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.V)) -// EncodeTo encodes this value using the Encoder. -func (e CryptoKeyType) EncodeTo(enc *xdr.Encoder) error { - if _, ok := cryptoKeyTypeMap[int32(e)]; !ok { - return fmt.Errorf("'%d' is not a valid CryptoKeyType enum value", e) + if armName == "TxSet" { + result = *u.TxSet + ok = true } - _, err := enc.EncodeInt(int32(e)) - return err + + return } -var _ decoderFrom = (*CryptoKeyType)(nil) +// MustGeneralizedTxSet retrieves the GeneralizedTxSet value from the union, +// panicing if the value is not set. +func (u StoredTransactionSet) MustGeneralizedTxSet() GeneralizedTransactionSet { + val, ok := u.GetGeneralizedTxSet() -// DecodeFrom decodes this value using the Decoder. -func (e *CryptoKeyType) DecodeFrom(d *xdr.Decoder) (int, error) { - v, n, err := d.DecodeInt() - if err != nil { - return n, fmt.Errorf("decoding CryptoKeyType: %s", err) - } - if _, ok := cryptoKeyTypeMap[v]; !ok { - return n, fmt.Errorf("'%d' is not a valid CryptoKeyType enum value", v) + if !ok { + panic("arm GeneralizedTxSet is not set") } - *e = CryptoKeyType(v) - return n, nil -} - -// MarshalBinary implements encoding.BinaryMarshaler. -func (s CryptoKeyType) MarshalBinary() ([]byte, error) { - b := bytes.Buffer{} - e := xdr.NewEncoder(&b) - err := s.EncodeTo(e) - return b.Bytes(), err -} -// UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *CryptoKeyType) UnmarshalBinary(inp []byte) error { - r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) - return err + return val } -var ( - _ encoding.BinaryMarshaler = (*CryptoKeyType)(nil) - _ encoding.BinaryUnmarshaler = (*CryptoKeyType)(nil) -) - -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s CryptoKeyType) xdrType() {} - -var _ xdrType = (*CryptoKeyType)(nil) - -// PublicKeyType is an XDR Enum defines as: -// -// enum PublicKeyType -// { -// PUBLIC_KEY_TYPE_ED25519 = KEY_TYPE_ED25519 -// }; -type PublicKeyType int32 - -const ( - PublicKeyTypePublicKeyTypeEd25519 PublicKeyType = 0 -) - -var publicKeyTypeMap = map[int32]string{ - 0: "PublicKeyTypePublicKeyTypeEd25519", -} +// GetGeneralizedTxSet retrieves the GeneralizedTxSet value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u StoredTransactionSet) GetGeneralizedTxSet() (result GeneralizedTransactionSet, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.V)) -// ValidEnum validates a proposed value for this enum. Implements -// the Enum interface for PublicKeyType -func (e PublicKeyType) ValidEnum(v int32) bool { - _, ok := publicKeyTypeMap[v] - return ok -} + if armName == "GeneralizedTxSet" { + result = *u.GeneralizedTxSet + ok = true + } -// String returns the name of `e` -func (e PublicKeyType) String() string { - name, _ := publicKeyTypeMap[int32(e)] - return name + return } // EncodeTo encodes this value using the Encoder. -func (e PublicKeyType) EncodeTo(enc *xdr.Encoder) error { - if _, ok := publicKeyTypeMap[int32(e)]; !ok { - return fmt.Errorf("'%d' is not a valid PublicKeyType enum value", e) +func (u StoredTransactionSet) EncodeTo(e *xdr.Encoder) error { + var err error + if _, err = e.EncodeInt(int32(u.V)); err != nil { + return err } - _, err := enc.EncodeInt(int32(e)) - return err + switch int32(u.V) { + case 0: + if err = (*u.TxSet).EncodeTo(e); err != nil { + return err + } + return nil + case 1: + if err = (*u.GeneralizedTxSet).EncodeTo(e); err != nil { + return err + } + return nil + } + return fmt.Errorf("V (int32) switch value '%d' is not valid for union StoredTransactionSet", u.V) } -var _ decoderFrom = (*PublicKeyType)(nil) +var _ decoderFrom = (*StoredTransactionSet)(nil) // DecodeFrom decodes this value using the Decoder. -func (e *PublicKeyType) DecodeFrom(d *xdr.Decoder) (int, error) { - v, n, err := d.DecodeInt() +func (u *StoredTransactionSet) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding StoredTransactionSet: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + var err error + var n, nTmp int + u.V, nTmp, err = d.DecodeInt() + n += nTmp if err != nil { - return n, fmt.Errorf("decoding PublicKeyType: %s", err) + return n, fmt.Errorf("decoding Int: %w", err) } - if _, ok := publicKeyTypeMap[v]; !ok { - return n, fmt.Errorf("'%d' is not a valid PublicKeyType enum value", v) + switch int32(u.V) { + case 0: + u.TxSet = new(TransactionSet) + nTmp, err = (*u.TxSet).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding TransactionSet: %w", err) + } + return n, nil + case 1: + u.GeneralizedTxSet = new(GeneralizedTransactionSet) + nTmp, err = (*u.GeneralizedTxSet).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding GeneralizedTransactionSet: %w", err) + } + return n, nil } - *e = PublicKeyType(v) - return n, nil + return n, fmt.Errorf("union StoredTransactionSet has invalid V (int32) switch value '%d'", u.V) } // MarshalBinary implements encoding.BinaryMarshaler. -func (s PublicKeyType) MarshalBinary() ([]byte, error) { +func (s StoredTransactionSet) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -37090,88 +53846,84 @@ func (s PublicKeyType) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *PublicKeyType) UnmarshalBinary(inp []byte) error { +func (s *StoredTransactionSet) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*PublicKeyType)(nil) - _ encoding.BinaryUnmarshaler = (*PublicKeyType)(nil) + _ encoding.BinaryMarshaler = (*StoredTransactionSet)(nil) + _ encoding.BinaryUnmarshaler = (*StoredTransactionSet)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s PublicKeyType) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s StoredTransactionSet) xdrType() {} -var _ xdrType = (*PublicKeyType)(nil) +var _ xdrType = (*StoredTransactionSet)(nil) -// SignerKeyType is an XDR Enum defines as: +// StoredDebugTransactionSet is an XDR Struct defines as: // -// enum SignerKeyType +// struct StoredDebugTransactionSet // { -// SIGNER_KEY_TYPE_ED25519 = KEY_TYPE_ED25519, -// SIGNER_KEY_TYPE_PRE_AUTH_TX = KEY_TYPE_PRE_AUTH_TX, -// SIGNER_KEY_TYPE_HASH_X = KEY_TYPE_HASH_X, -// SIGNER_KEY_TYPE_ED25519_SIGNED_PAYLOAD = KEY_TYPE_ED25519_SIGNED_PAYLOAD +// StoredTransactionSet txSet; +// uint32 ledgerSeq; +// StellarValue scpValue; // }; -type SignerKeyType int32 - -const ( - SignerKeyTypeSignerKeyTypeEd25519 SignerKeyType = 0 - SignerKeyTypeSignerKeyTypePreAuthTx SignerKeyType = 1 - SignerKeyTypeSignerKeyTypeHashX SignerKeyType = 2 - SignerKeyTypeSignerKeyTypeEd25519SignedPayload SignerKeyType = 3 -) - -var signerKeyTypeMap = map[int32]string{ - 0: "SignerKeyTypeSignerKeyTypeEd25519", - 1: "SignerKeyTypeSignerKeyTypePreAuthTx", - 2: "SignerKeyTypeSignerKeyTypeHashX", - 3: "SignerKeyTypeSignerKeyTypeEd25519SignedPayload", -} - -// ValidEnum validates a proposed value for this enum. Implements -// the Enum interface for SignerKeyType -func (e SignerKeyType) ValidEnum(v int32) bool { - _, ok := signerKeyTypeMap[v] - return ok -} - -// String returns the name of `e` -func (e SignerKeyType) String() string { - name, _ := signerKeyTypeMap[int32(e)] - return name +type StoredDebugTransactionSet struct { + TxSet StoredTransactionSet + LedgerSeq Uint32 + ScpValue StellarValue } // EncodeTo encodes this value using the Encoder. -func (e SignerKeyType) EncodeTo(enc *xdr.Encoder) error { - if _, ok := signerKeyTypeMap[int32(e)]; !ok { - return fmt.Errorf("'%d' is not a valid SignerKeyType enum value", e) +func (s *StoredDebugTransactionSet) EncodeTo(e *xdr.Encoder) error { + var err error + if err = s.TxSet.EncodeTo(e); err != nil { + return err } - _, err := enc.EncodeInt(int32(e)) - return err + if err = s.LedgerSeq.EncodeTo(e); err != nil { + return err + } + if err = s.ScpValue.EncodeTo(e); err != nil { + return err + } + return nil } -var _ decoderFrom = (*SignerKeyType)(nil) +var _ decoderFrom = (*StoredDebugTransactionSet)(nil) // DecodeFrom decodes this value using the Decoder. -func (e *SignerKeyType) DecodeFrom(d *xdr.Decoder) (int, error) { - v, n, err := d.DecodeInt() +func (s *StoredDebugTransactionSet) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding StoredDebugTransactionSet: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + var err error + var n, nTmp int + nTmp, err = s.TxSet.DecodeFrom(d, maxDepth) + n += nTmp if err != nil { - return n, fmt.Errorf("decoding SignerKeyType: %s", err) + return n, fmt.Errorf("decoding StoredTransactionSet: %w", err) } - if _, ok := signerKeyTypeMap[v]; !ok { - return n, fmt.Errorf("'%d' is not a valid SignerKeyType enum value", v) + nTmp, err = s.LedgerSeq.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Uint32: %w", err) + } + nTmp, err = s.ScpValue.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding StellarValue: %w", err) } - *e = SignerKeyType(v) return n, nil } // MarshalBinary implements encoding.BinaryMarshaler. -func (s SignerKeyType) MarshalBinary() ([]byte, error) { +func (s StoredDebugTransactionSet) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -37179,134 +53931,142 @@ func (s SignerKeyType) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *SignerKeyType) UnmarshalBinary(inp []byte) error { +func (s *StoredDebugTransactionSet) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*SignerKeyType)(nil) - _ encoding.BinaryUnmarshaler = (*SignerKeyType)(nil) + _ encoding.BinaryMarshaler = (*StoredDebugTransactionSet)(nil) + _ encoding.BinaryUnmarshaler = (*StoredDebugTransactionSet)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s SignerKeyType) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s StoredDebugTransactionSet) xdrType() {} -var _ xdrType = (*SignerKeyType)(nil) +var _ xdrType = (*StoredDebugTransactionSet)(nil) -// PublicKey is an XDR Union defines as: +// PersistedScpStateV0 is an XDR Struct defines as: // -// union PublicKey switch (PublicKeyType type) +// struct PersistedSCPStateV0 // { -// case PUBLIC_KEY_TYPE_ED25519: -// uint256 ed25519; +// SCPEnvelope scpEnvelopes<>; +// SCPQuorumSet quorumSets<>; +// StoredTransactionSet txSets<>; // }; -type PublicKey struct { - Type PublicKeyType - Ed25519 *Uint256 +type PersistedScpStateV0 struct { + ScpEnvelopes []ScpEnvelope + QuorumSets []ScpQuorumSet + TxSets []StoredTransactionSet } -// SwitchFieldName returns the field name in which this union's -// discriminant is stored -func (u PublicKey) SwitchFieldName() string { - return "Type" -} - -// ArmForSwitch returns which field name should be used for storing -// the value for an instance of PublicKey -func (u PublicKey) ArmForSwitch(sw int32) (string, bool) { - switch PublicKeyType(sw) { - case PublicKeyTypePublicKeyTypeEd25519: - return "Ed25519", true +// EncodeTo encodes this value using the Encoder. +func (s *PersistedScpStateV0) EncodeTo(e *xdr.Encoder) error { + var err error + if _, err = e.EncodeUint(uint32(len(s.ScpEnvelopes))); err != nil { + return err } - return "-", false -} - -// NewPublicKey creates a new PublicKey. -func NewPublicKey(aType PublicKeyType, value interface{}) (result PublicKey, err error) { - result.Type = aType - switch PublicKeyType(aType) { - case PublicKeyTypePublicKeyTypeEd25519: - tv, ok := value.(Uint256) - if !ok { - err = fmt.Errorf("invalid value, must be Uint256") - return + for i := 0; i < len(s.ScpEnvelopes); i++ { + if err = s.ScpEnvelopes[i].EncodeTo(e); err != nil { + return err } - result.Ed25519 = &tv } - return -} - -// MustEd25519 retrieves the Ed25519 value from the union, -// panicing if the value is not set. -func (u PublicKey) MustEd25519() Uint256 { - val, ok := u.GetEd25519() - - if !ok { - panic("arm Ed25519 is not set") + if _, err = e.EncodeUint(uint32(len(s.QuorumSets))); err != nil { + return err } - - return val -} - -// GetEd25519 retrieves the Ed25519 value from the union, -// returning ok if the union's switch indicated the value is valid. -func (u PublicKey) GetEd25519() (result Uint256, ok bool) { - armName, _ := u.ArmForSwitch(int32(u.Type)) - - if armName == "Ed25519" { - result = *u.Ed25519 - ok = true + for i := 0; i < len(s.QuorumSets); i++ { + if err = s.QuorumSets[i].EncodeTo(e); err != nil { + return err + } } - - return -} - -// EncodeTo encodes this value using the Encoder. -func (u PublicKey) EncodeTo(e *xdr.Encoder) error { - var err error - if err = u.Type.EncodeTo(e); err != nil { + if _, err = e.EncodeUint(uint32(len(s.TxSets))); err != nil { return err } - switch PublicKeyType(u.Type) { - case PublicKeyTypePublicKeyTypeEd25519: - if err = (*u.Ed25519).EncodeTo(e); err != nil { + for i := 0; i < len(s.TxSets); i++ { + if err = s.TxSets[i].EncodeTo(e); err != nil { return err } - return nil } - return fmt.Errorf("Type (PublicKeyType) switch value '%d' is not valid for union PublicKey", u.Type) + return nil } -var _ decoderFrom = (*PublicKey)(nil) +var _ decoderFrom = (*PersistedScpStateV0)(nil) // DecodeFrom decodes this value using the Decoder. -func (u *PublicKey) DecodeFrom(d *xdr.Decoder) (int, error) { +func (s *PersistedScpStateV0) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding PersistedScpStateV0: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = u.Type.DecodeFrom(d) + var l uint32 + l, nTmp, err = d.DecodeUint() n += nTmp if err != nil { - return n, fmt.Errorf("decoding PublicKeyType: %s", err) + return n, fmt.Errorf("decoding ScpEnvelope: %w", err) } - switch PublicKeyType(u.Type) { - case PublicKeyTypePublicKeyTypeEd25519: - u.Ed25519 = new(Uint256) - nTmp, err = (*u.Ed25519).DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Uint256: %s", err) + s.ScpEnvelopes = nil + if l > 0 { + if il, ok := d.InputLen(); ok && uint(il) < uint(l) { + return n, fmt.Errorf("decoding ScpEnvelope: length (%d) exceeds remaining input length (%d)", l, il) + } + s.ScpEnvelopes = make([]ScpEnvelope, l) + for i := uint32(0); i < l; i++ { + nTmp, err = s.ScpEnvelopes[i].DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ScpEnvelope: %w", err) + } } - return n, nil } - return n, fmt.Errorf("union PublicKey has invalid Type (PublicKeyType) switch value '%d'", u.Type) + l, nTmp, err = d.DecodeUint() + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ScpQuorumSet: %w", err) + } + s.QuorumSets = nil + if l > 0 { + if il, ok := d.InputLen(); ok && uint(il) < uint(l) { + return n, fmt.Errorf("decoding ScpQuorumSet: length (%d) exceeds remaining input length (%d)", l, il) + } + s.QuorumSets = make([]ScpQuorumSet, l) + for i := uint32(0); i < l; i++ { + nTmp, err = s.QuorumSets[i].DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ScpQuorumSet: %w", err) + } + } + } + l, nTmp, err = d.DecodeUint() + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding StoredTransactionSet: %w", err) + } + s.TxSets = nil + if l > 0 { + if il, ok := d.InputLen(); ok && uint(il) < uint(l) { + return n, fmt.Errorf("decoding StoredTransactionSet: length (%d) exceeds remaining input length (%d)", l, il) + } + s.TxSets = make([]StoredTransactionSet, l) + for i := uint32(0); i < l; i++ { + nTmp, err = s.TxSets[i].DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding StoredTransactionSet: %w", err) + } + } + } + return n, nil } // MarshalBinary implements encoding.BinaryMarshaler. -func (s PublicKey) MarshalBinary() ([]byte, error) { +func (s PersistedScpStateV0) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -37314,71 +54074,114 @@ func (s PublicKey) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *PublicKey) UnmarshalBinary(inp []byte) error { +func (s *PersistedScpStateV0) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*PublicKey)(nil) - _ encoding.BinaryUnmarshaler = (*PublicKey)(nil) + _ encoding.BinaryMarshaler = (*PersistedScpStateV0)(nil) + _ encoding.BinaryUnmarshaler = (*PersistedScpStateV0)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s PublicKey) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s PersistedScpStateV0) xdrType() {} -var _ xdrType = (*PublicKey)(nil) +var _ xdrType = (*PersistedScpStateV0)(nil) -// SignerKeyEd25519SignedPayload is an XDR NestedStruct defines as: +// PersistedScpStateV1 is an XDR Struct defines as: // -// struct -// { -// /* Public key that must sign the payload. */ -// uint256 ed25519; -// /* Payload to be raw signed by ed25519. */ -// opaque payload<64>; -// } -type SignerKeyEd25519SignedPayload struct { - Ed25519 Uint256 - Payload []byte `xdrmaxsize:"64"` +// struct PersistedSCPStateV1 +// { +// // Tx sets are saved separately +// SCPEnvelope scpEnvelopes<>; +// SCPQuorumSet quorumSets<>; +// }; +type PersistedScpStateV1 struct { + ScpEnvelopes []ScpEnvelope + QuorumSets []ScpQuorumSet } // EncodeTo encodes this value using the Encoder. -func (s *SignerKeyEd25519SignedPayload) EncodeTo(e *xdr.Encoder) error { +func (s *PersistedScpStateV1) EncodeTo(e *xdr.Encoder) error { var err error - if err = s.Ed25519.EncodeTo(e); err != nil { + if _, err = e.EncodeUint(uint32(len(s.ScpEnvelopes))); err != nil { return err } - if _, err = e.EncodeOpaque(s.Payload[:]); err != nil { + for i := 0; i < len(s.ScpEnvelopes); i++ { + if err = s.ScpEnvelopes[i].EncodeTo(e); err != nil { + return err + } + } + if _, err = e.EncodeUint(uint32(len(s.QuorumSets))); err != nil { return err } + for i := 0; i < len(s.QuorumSets); i++ { + if err = s.QuorumSets[i].EncodeTo(e); err != nil { + return err + } + } return nil } -var _ decoderFrom = (*SignerKeyEd25519SignedPayload)(nil) +var _ decoderFrom = (*PersistedScpStateV1)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *SignerKeyEd25519SignedPayload) DecodeFrom(d *xdr.Decoder) (int, error) { +func (s *PersistedScpStateV1) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding PersistedScpStateV1: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = s.Ed25519.DecodeFrom(d) + var l uint32 + l, nTmp, err = d.DecodeUint() n += nTmp if err != nil { - return n, fmt.Errorf("decoding Uint256: %s", err) + return n, fmt.Errorf("decoding ScpEnvelope: %w", err) } - s.Payload, nTmp, err = d.DecodeOpaque(64) + s.ScpEnvelopes = nil + if l > 0 { + if il, ok := d.InputLen(); ok && uint(il) < uint(l) { + return n, fmt.Errorf("decoding ScpEnvelope: length (%d) exceeds remaining input length (%d)", l, il) + } + s.ScpEnvelopes = make([]ScpEnvelope, l) + for i := uint32(0); i < l; i++ { + nTmp, err = s.ScpEnvelopes[i].DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ScpEnvelope: %w", err) + } + } + } + l, nTmp, err = d.DecodeUint() n += nTmp if err != nil { - return n, fmt.Errorf("decoding Payload: %s", err) + return n, fmt.Errorf("decoding ScpQuorumSet: %w", err) + } + s.QuorumSets = nil + if l > 0 { + if il, ok := d.InputLen(); ok && uint(il) < uint(l) { + return n, fmt.Errorf("decoding ScpQuorumSet: length (%d) exceeds remaining input length (%d)", l, il) + } + s.QuorumSets = make([]ScpQuorumSet, l) + for i := uint32(0); i < l; i++ { + nTmp, err = s.QuorumSets[i].DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ScpQuorumSet: %w", err) + } + } } return n, nil } // MarshalBinary implements encoding.BinaryMarshaler. -func (s SignerKeyEd25519SignedPayload) MarshalBinary() ([]byte, error) { +func (s PersistedScpStateV1) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -37386,205 +54189,124 @@ func (s SignerKeyEd25519SignedPayload) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *SignerKeyEd25519SignedPayload) UnmarshalBinary(inp []byte) error { +func (s *PersistedScpStateV1) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*SignerKeyEd25519SignedPayload)(nil) - _ encoding.BinaryUnmarshaler = (*SignerKeyEd25519SignedPayload)(nil) + _ encoding.BinaryMarshaler = (*PersistedScpStateV1)(nil) + _ encoding.BinaryUnmarshaler = (*PersistedScpStateV1)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s SignerKeyEd25519SignedPayload) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s PersistedScpStateV1) xdrType() {} -var _ xdrType = (*SignerKeyEd25519SignedPayload)(nil) +var _ xdrType = (*PersistedScpStateV1)(nil) -// SignerKey is an XDR Union defines as: +// PersistedScpState is an XDR Union defines as: // -// union SignerKey switch (SignerKeyType type) +// union PersistedSCPState switch (int v) // { -// case SIGNER_KEY_TYPE_ED25519: -// uint256 ed25519; -// case SIGNER_KEY_TYPE_PRE_AUTH_TX: -// /* SHA-256 Hash of TransactionSignaturePayload structure */ -// uint256 preAuthTx; -// case SIGNER_KEY_TYPE_HASH_X: -// /* Hash of random 256 bit preimage X */ -// uint256 hashX; -// case SIGNER_KEY_TYPE_ED25519_SIGNED_PAYLOAD: -// struct -// { -// /* Public key that must sign the payload. */ -// uint256 ed25519; -// /* Payload to be raw signed by ed25519. */ -// opaque payload<64>; -// } ed25519SignedPayload; +// case 0: +// PersistedSCPStateV0 v0; +// case 1: +// PersistedSCPStateV1 v1; // }; -type SignerKey struct { - Type SignerKeyType - Ed25519 *Uint256 - PreAuthTx *Uint256 - HashX *Uint256 - Ed25519SignedPayload *SignerKeyEd25519SignedPayload +type PersistedScpState struct { + V int32 + V0 *PersistedScpStateV0 + V1 *PersistedScpStateV1 } // SwitchFieldName returns the field name in which this union's // discriminant is stored -func (u SignerKey) SwitchFieldName() string { - return "Type" +func (u PersistedScpState) SwitchFieldName() string { + return "V" } // ArmForSwitch returns which field name should be used for storing -// the value for an instance of SignerKey -func (u SignerKey) ArmForSwitch(sw int32) (string, bool) { - switch SignerKeyType(sw) { - case SignerKeyTypeSignerKeyTypeEd25519: - return "Ed25519", true - case SignerKeyTypeSignerKeyTypePreAuthTx: - return "PreAuthTx", true - case SignerKeyTypeSignerKeyTypeHashX: - return "HashX", true - case SignerKeyTypeSignerKeyTypeEd25519SignedPayload: - return "Ed25519SignedPayload", true +// the value for an instance of PersistedScpState +func (u PersistedScpState) ArmForSwitch(sw int32) (string, bool) { + switch int32(sw) { + case 0: + return "V0", true + case 1: + return "V1", true } return "-", false } -// NewSignerKey creates a new SignerKey. -func NewSignerKey(aType SignerKeyType, value interface{}) (result SignerKey, err error) { - result.Type = aType - switch SignerKeyType(aType) { - case SignerKeyTypeSignerKeyTypeEd25519: - tv, ok := value.(Uint256) - if !ok { - err = fmt.Errorf("invalid value, must be Uint256") - return - } - result.Ed25519 = &tv - case SignerKeyTypeSignerKeyTypePreAuthTx: - tv, ok := value.(Uint256) - if !ok { - err = fmt.Errorf("invalid value, must be Uint256") - return - } - result.PreAuthTx = &tv - case SignerKeyTypeSignerKeyTypeHashX: - tv, ok := value.(Uint256) +// NewPersistedScpState creates a new PersistedScpState. +func NewPersistedScpState(v int32, value interface{}) (result PersistedScpState, err error) { + result.V = v + switch int32(v) { + case 0: + tv, ok := value.(PersistedScpStateV0) if !ok { - err = fmt.Errorf("invalid value, must be Uint256") + err = errors.New("invalid value, must be PersistedScpStateV0") return } - result.HashX = &tv - case SignerKeyTypeSignerKeyTypeEd25519SignedPayload: - tv, ok := value.(SignerKeyEd25519SignedPayload) + result.V0 = &tv + case 1: + tv, ok := value.(PersistedScpStateV1) if !ok { - err = fmt.Errorf("invalid value, must be SignerKeyEd25519SignedPayload") + err = errors.New("invalid value, must be PersistedScpStateV1") return } - result.Ed25519SignedPayload = &tv - } - return -} - -// MustEd25519 retrieves the Ed25519 value from the union, -// panicing if the value is not set. -func (u SignerKey) MustEd25519() Uint256 { - val, ok := u.GetEd25519() - - if !ok { - panic("arm Ed25519 is not set") - } - - return val -} - -// GetEd25519 retrieves the Ed25519 value from the union, -// returning ok if the union's switch indicated the value is valid. -func (u SignerKey) GetEd25519() (result Uint256, ok bool) { - armName, _ := u.ArmForSwitch(int32(u.Type)) - - if armName == "Ed25519" { - result = *u.Ed25519 - ok = true - } - - return -} - -// MustPreAuthTx retrieves the PreAuthTx value from the union, -// panicing if the value is not set. -func (u SignerKey) MustPreAuthTx() Uint256 { - val, ok := u.GetPreAuthTx() - - if !ok { - panic("arm PreAuthTx is not set") - } - - return val -} - -// GetPreAuthTx retrieves the PreAuthTx value from the union, -// returning ok if the union's switch indicated the value is valid. -func (u SignerKey) GetPreAuthTx() (result Uint256, ok bool) { - armName, _ := u.ArmForSwitch(int32(u.Type)) - - if armName == "PreAuthTx" { - result = *u.PreAuthTx - ok = true + result.V1 = &tv } - return } -// MustHashX retrieves the HashX value from the union, +// MustV0 retrieves the V0 value from the union, // panicing if the value is not set. -func (u SignerKey) MustHashX() Uint256 { - val, ok := u.GetHashX() +func (u PersistedScpState) MustV0() PersistedScpStateV0 { + val, ok := u.GetV0() if !ok { - panic("arm HashX is not set") + panic("arm V0 is not set") } return val } -// GetHashX retrieves the HashX value from the union, +// GetV0 retrieves the V0 value from the union, // returning ok if the union's switch indicated the value is valid. -func (u SignerKey) GetHashX() (result Uint256, ok bool) { - armName, _ := u.ArmForSwitch(int32(u.Type)) +func (u PersistedScpState) GetV0() (result PersistedScpStateV0, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.V)) - if armName == "HashX" { - result = *u.HashX + if armName == "V0" { + result = *u.V0 ok = true } return } -// MustEd25519SignedPayload retrieves the Ed25519SignedPayload value from the union, +// MustV1 retrieves the V1 value from the union, // panicing if the value is not set. -func (u SignerKey) MustEd25519SignedPayload() SignerKeyEd25519SignedPayload { - val, ok := u.GetEd25519SignedPayload() +func (u PersistedScpState) MustV1() PersistedScpStateV1 { + val, ok := u.GetV1() if !ok { - panic("arm Ed25519SignedPayload is not set") + panic("arm V1 is not set") } return val } -// GetEd25519SignedPayload retrieves the Ed25519SignedPayload value from the union, +// GetV1 retrieves the V1 value from the union, // returning ok if the union's switch indicated the value is valid. -func (u SignerKey) GetEd25519SignedPayload() (result SignerKeyEd25519SignedPayload, ok bool) { - armName, _ := u.ArmForSwitch(int32(u.Type)) +func (u PersistedScpState) GetV1() (result PersistedScpStateV1, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.V)) - if armName == "Ed25519SignedPayload" { - result = *u.Ed25519SignedPayload + if armName == "V1" { + result = *u.V1 ok = true } @@ -37592,86 +54314,64 @@ func (u SignerKey) GetEd25519SignedPayload() (result SignerKeyEd25519SignedPaylo } // EncodeTo encodes this value using the Encoder. -func (u SignerKey) EncodeTo(e *xdr.Encoder) error { +func (u PersistedScpState) EncodeTo(e *xdr.Encoder) error { var err error - if err = u.Type.EncodeTo(e); err != nil { + if _, err = e.EncodeInt(int32(u.V)); err != nil { return err } - switch SignerKeyType(u.Type) { - case SignerKeyTypeSignerKeyTypeEd25519: - if err = (*u.Ed25519).EncodeTo(e); err != nil { - return err - } - return nil - case SignerKeyTypeSignerKeyTypePreAuthTx: - if err = (*u.PreAuthTx).EncodeTo(e); err != nil { - return err - } - return nil - case SignerKeyTypeSignerKeyTypeHashX: - if err = (*u.HashX).EncodeTo(e); err != nil { + switch int32(u.V) { + case 0: + if err = (*u.V0).EncodeTo(e); err != nil { return err } return nil - case SignerKeyTypeSignerKeyTypeEd25519SignedPayload: - if err = (*u.Ed25519SignedPayload).EncodeTo(e); err != nil { + case 1: + if err = (*u.V1).EncodeTo(e); err != nil { return err } return nil } - return fmt.Errorf("Type (SignerKeyType) switch value '%d' is not valid for union SignerKey", u.Type) + return fmt.Errorf("V (int32) switch value '%d' is not valid for union PersistedScpState", u.V) } -var _ decoderFrom = (*SignerKey)(nil) +var _ decoderFrom = (*PersistedScpState)(nil) // DecodeFrom decodes this value using the Decoder. -func (u *SignerKey) DecodeFrom(d *xdr.Decoder) (int, error) { +func (u *PersistedScpState) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding PersistedScpState: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = u.Type.DecodeFrom(d) + u.V, nTmp, err = d.DecodeInt() n += nTmp if err != nil { - return n, fmt.Errorf("decoding SignerKeyType: %s", err) + return n, fmt.Errorf("decoding Int: %w", err) } - switch SignerKeyType(u.Type) { - case SignerKeyTypeSignerKeyTypeEd25519: - u.Ed25519 = new(Uint256) - nTmp, err = (*u.Ed25519).DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Uint256: %s", err) - } - return n, nil - case SignerKeyTypeSignerKeyTypePreAuthTx: - u.PreAuthTx = new(Uint256) - nTmp, err = (*u.PreAuthTx).DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Uint256: %s", err) - } - return n, nil - case SignerKeyTypeSignerKeyTypeHashX: - u.HashX = new(Uint256) - nTmp, err = (*u.HashX).DecodeFrom(d) + switch int32(u.V) { + case 0: + u.V0 = new(PersistedScpStateV0) + nTmp, err = (*u.V0).DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Uint256: %s", err) + return n, fmt.Errorf("decoding PersistedScpStateV0: %w", err) } return n, nil - case SignerKeyTypeSignerKeyTypeEd25519SignedPayload: - u.Ed25519SignedPayload = new(SignerKeyEd25519SignedPayload) - nTmp, err = (*u.Ed25519SignedPayload).DecodeFrom(d) + case 1: + u.V1 = new(PersistedScpStateV1) + nTmp, err = (*u.V1).DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding SignerKeyEd25519SignedPayload: %s", err) + return n, fmt.Errorf("decoding PersistedScpStateV1: %w", err) } return n, nil } - return n, fmt.Errorf("union SignerKey has invalid Type (SignerKeyType) switch value '%d'", u.Type) + return n, fmt.Errorf("union PersistedScpState has invalid V (int32) switch value '%d'", u.V) } // MarshalBinary implements encoding.BinaryMarshaler. -func (s SignerKey) MarshalBinary() ([]byte, error) { +func (s PersistedScpState) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -37679,59 +54379,65 @@ func (s SignerKey) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *SignerKey) UnmarshalBinary(inp []byte) error { +func (s *PersistedScpState) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*SignerKey)(nil) - _ encoding.BinaryUnmarshaler = (*SignerKey)(nil) + _ encoding.BinaryMarshaler = (*PersistedScpState)(nil) + _ encoding.BinaryUnmarshaler = (*PersistedScpState)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s SignerKey) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s PersistedScpState) xdrType() {} -var _ xdrType = (*SignerKey)(nil) +var _ xdrType = (*PersistedScpState)(nil) -// Signature is an XDR Typedef defines as: +// ConfigSettingContractExecutionLanesV0 is an XDR Struct defines as: // -// typedef opaque Signature<64>; -type Signature []byte - -// XDRMaxSize implements the Sized interface for Signature -func (e Signature) XDRMaxSize() int { - return 64 +// struct ConfigSettingContractExecutionLanesV0 +// { +// // maximum number of Soroban transactions per ledger +// uint32 ledgerMaxTxCount; +// }; +type ConfigSettingContractExecutionLanesV0 struct { + LedgerMaxTxCount Uint32 } // EncodeTo encodes this value using the Encoder. -func (s Signature) EncodeTo(e *xdr.Encoder) error { +func (s *ConfigSettingContractExecutionLanesV0) EncodeTo(e *xdr.Encoder) error { var err error - if _, err = e.EncodeOpaque(s[:]); err != nil { + if err = s.LedgerMaxTxCount.EncodeTo(e); err != nil { return err } return nil } -var _ decoderFrom = (*Signature)(nil) +var _ decoderFrom = (*ConfigSettingContractExecutionLanesV0)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *Signature) DecodeFrom(d *xdr.Decoder) (int, error) { +func (s *ConfigSettingContractExecutionLanesV0) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding ConfigSettingContractExecutionLanesV0: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - (*s), nTmp, err = d.DecodeOpaque(64) + nTmp, err = s.LedgerMaxTxCount.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Signature: %s", err) + return n, fmt.Errorf("decoding Uint32: %w", err) } return n, nil } // MarshalBinary implements encoding.BinaryMarshaler. -func (s Signature) MarshalBinary() ([]byte, error) { +func (s ConfigSettingContractExecutionLanesV0) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -37739,59 +54445,100 @@ func (s Signature) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *Signature) UnmarshalBinary(inp []byte) error { +func (s *ConfigSettingContractExecutionLanesV0) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*Signature)(nil) - _ encoding.BinaryUnmarshaler = (*Signature)(nil) + _ encoding.BinaryMarshaler = (*ConfigSettingContractExecutionLanesV0)(nil) + _ encoding.BinaryUnmarshaler = (*ConfigSettingContractExecutionLanesV0)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s Signature) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s ConfigSettingContractExecutionLanesV0) xdrType() {} -var _ xdrType = (*Signature)(nil) +var _ xdrType = (*ConfigSettingContractExecutionLanesV0)(nil) -// SignatureHint is an XDR Typedef defines as: +// ConfigSettingContractComputeV0 is an XDR Struct defines as: // -// typedef opaque SignatureHint[4]; -type SignatureHint [4]byte - -// XDRMaxSize implements the Sized interface for SignatureHint -func (e SignatureHint) XDRMaxSize() int { - return 4 +// struct ConfigSettingContractComputeV0 +// { +// // Maximum instructions per ledger +// int64 ledgerMaxInstructions; +// // Maximum instructions per transaction +// int64 txMaxInstructions; +// // Cost of 10000 instructions +// int64 feeRatePerInstructionsIncrement; +// +// // Memory limit per transaction. Unlike instructions, there is no fee +// // for memory, just the limit. +// uint32 txMemoryLimit; +// }; +type ConfigSettingContractComputeV0 struct { + LedgerMaxInstructions Int64 + TxMaxInstructions Int64 + FeeRatePerInstructionsIncrement Int64 + TxMemoryLimit Uint32 } // EncodeTo encodes this value using the Encoder. -func (s *SignatureHint) EncodeTo(e *xdr.Encoder) error { +func (s *ConfigSettingContractComputeV0) EncodeTo(e *xdr.Encoder) error { var err error - if _, err = e.EncodeFixedOpaque(s[:]); err != nil { + if err = s.LedgerMaxInstructions.EncodeTo(e); err != nil { + return err + } + if err = s.TxMaxInstructions.EncodeTo(e); err != nil { + return err + } + if err = s.FeeRatePerInstructionsIncrement.EncodeTo(e); err != nil { + return err + } + if err = s.TxMemoryLimit.EncodeTo(e); err != nil { return err } return nil } -var _ decoderFrom = (*SignatureHint)(nil) +var _ decoderFrom = (*ConfigSettingContractComputeV0)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *SignatureHint) DecodeFrom(d *xdr.Decoder) (int, error) { +func (s *ConfigSettingContractComputeV0) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding ConfigSettingContractComputeV0: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = d.DecodeFixedOpaqueInplace(s[:]) + nTmp, err = s.LedgerMaxInstructions.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Int64: %w", err) + } + nTmp, err = s.TxMaxInstructions.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Int64: %w", err) + } + nTmp, err = s.FeeRatePerInstructionsIncrement.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Int64: %w", err) + } + nTmp, err = s.TxMemoryLimit.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding SignatureHint: %s", err) + return n, fmt.Errorf("decoding Uint32: %w", err) } return n, nil } // MarshalBinary implements encoding.BinaryMarshaler. -func (s SignatureHint) MarshalBinary() ([]byte, error) { +func (s ConfigSettingContractComputeV0) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -37799,85 +54546,221 @@ func (s SignatureHint) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *SignatureHint) UnmarshalBinary(inp []byte) error { +func (s *ConfigSettingContractComputeV0) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*SignatureHint)(nil) - _ encoding.BinaryUnmarshaler = (*SignatureHint)(nil) + _ encoding.BinaryMarshaler = (*ConfigSettingContractComputeV0)(nil) + _ encoding.BinaryUnmarshaler = (*ConfigSettingContractComputeV0)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s SignatureHint) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s ConfigSettingContractComputeV0) xdrType() {} -var _ xdrType = (*SignatureHint)(nil) +var _ xdrType = (*ConfigSettingContractComputeV0)(nil) -// NodeId is an XDR Typedef defines as: +// ConfigSettingContractLedgerCostV0 is an XDR Struct defines as: // -// typedef PublicKey NodeID; -type NodeId PublicKey - -// SwitchFieldName returns the field name in which this union's -// discriminant is stored -func (u NodeId) SwitchFieldName() string { - return PublicKey(u).SwitchFieldName() -} - -// ArmForSwitch returns which field name should be used for storing -// the value for an instance of PublicKey -func (u NodeId) ArmForSwitch(sw int32) (string, bool) { - return PublicKey(u).ArmForSwitch(sw) -} - -// NewNodeId creates a new NodeId. -func NewNodeId(aType PublicKeyType, value interface{}) (result NodeId, err error) { - u, err := NewPublicKey(aType, value) - result = NodeId(u) - return -} - -// MustEd25519 retrieves the Ed25519 value from the union, -// panicing if the value is not set. -func (u NodeId) MustEd25519() Uint256 { - return PublicKey(u).MustEd25519() -} - -// GetEd25519 retrieves the Ed25519 value from the union, -// returning ok if the union's switch indicated the value is valid. -func (u NodeId) GetEd25519() (result Uint256, ok bool) { - return PublicKey(u).GetEd25519() +// struct ConfigSettingContractLedgerCostV0 +// { +// // Maximum number of ledger entry read operations per ledger +// uint32 ledgerMaxReadLedgerEntries; +// // Maximum number of bytes that can be read per ledger +// uint32 ledgerMaxReadBytes; +// // Maximum number of ledger entry write operations per ledger +// uint32 ledgerMaxWriteLedgerEntries; +// // Maximum number of bytes that can be written per ledger +// uint32 ledgerMaxWriteBytes; +// +// // Maximum number of ledger entry read operations per transaction +// uint32 txMaxReadLedgerEntries; +// // Maximum number of bytes that can be read per transaction +// uint32 txMaxReadBytes; +// // Maximum number of ledger entry write operations per transaction +// uint32 txMaxWriteLedgerEntries; +// // Maximum number of bytes that can be written per transaction +// uint32 txMaxWriteBytes; +// +// int64 feeReadLedgerEntry; // Fee per ledger entry read +// int64 feeWriteLedgerEntry; // Fee per ledger entry write +// +// int64 feeRead1KB; // Fee for reading 1KB +// +// // The following parameters determine the write fee per 1KB. +// // Write fee grows linearly until bucket list reaches this size +// int64 bucketListTargetSizeBytes; +// // Fee per 1KB write when the bucket list is empty +// int64 writeFee1KBBucketListLow; +// // Fee per 1KB write when the bucket list has reached `bucketListTargetSizeBytes` +// int64 writeFee1KBBucketListHigh; +// // Write fee multiplier for any additional data past the first `bucketListTargetSizeBytes` +// uint32 bucketListWriteFeeGrowthFactor; +// }; +type ConfigSettingContractLedgerCostV0 struct { + LedgerMaxReadLedgerEntries Uint32 + LedgerMaxReadBytes Uint32 + LedgerMaxWriteLedgerEntries Uint32 + LedgerMaxWriteBytes Uint32 + TxMaxReadLedgerEntries Uint32 + TxMaxReadBytes Uint32 + TxMaxWriteLedgerEntries Uint32 + TxMaxWriteBytes Uint32 + FeeReadLedgerEntry Int64 + FeeWriteLedgerEntry Int64 + FeeRead1Kb Int64 + BucketListTargetSizeBytes Int64 + WriteFee1KbBucketListLow Int64 + WriteFee1KbBucketListHigh Int64 + BucketListWriteFeeGrowthFactor Uint32 } // EncodeTo encodes this value using the Encoder. -func (s NodeId) EncodeTo(e *xdr.Encoder) error { +func (s *ConfigSettingContractLedgerCostV0) EncodeTo(e *xdr.Encoder) error { var err error - if err = PublicKey(s).EncodeTo(e); err != nil { + if err = s.LedgerMaxReadLedgerEntries.EncodeTo(e); err != nil { + return err + } + if err = s.LedgerMaxReadBytes.EncodeTo(e); err != nil { + return err + } + if err = s.LedgerMaxWriteLedgerEntries.EncodeTo(e); err != nil { + return err + } + if err = s.LedgerMaxWriteBytes.EncodeTo(e); err != nil { + return err + } + if err = s.TxMaxReadLedgerEntries.EncodeTo(e); err != nil { + return err + } + if err = s.TxMaxReadBytes.EncodeTo(e); err != nil { + return err + } + if err = s.TxMaxWriteLedgerEntries.EncodeTo(e); err != nil { + return err + } + if err = s.TxMaxWriteBytes.EncodeTo(e); err != nil { + return err + } + if err = s.FeeReadLedgerEntry.EncodeTo(e); err != nil { + return err + } + if err = s.FeeWriteLedgerEntry.EncodeTo(e); err != nil { + return err + } + if err = s.FeeRead1Kb.EncodeTo(e); err != nil { + return err + } + if err = s.BucketListTargetSizeBytes.EncodeTo(e); err != nil { + return err + } + if err = s.WriteFee1KbBucketListLow.EncodeTo(e); err != nil { + return err + } + if err = s.WriteFee1KbBucketListHigh.EncodeTo(e); err != nil { + return err + } + if err = s.BucketListWriteFeeGrowthFactor.EncodeTo(e); err != nil { return err } return nil } -var _ decoderFrom = (*NodeId)(nil) +var _ decoderFrom = (*ConfigSettingContractLedgerCostV0)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *NodeId) DecodeFrom(d *xdr.Decoder) (int, error) { +func (s *ConfigSettingContractLedgerCostV0) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding ConfigSettingContractLedgerCostV0: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = (*PublicKey)(s).DecodeFrom(d) + nTmp, err = s.LedgerMaxReadLedgerEntries.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Uint32: %w", err) + } + nTmp, err = s.LedgerMaxReadBytes.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Uint32: %w", err) + } + nTmp, err = s.LedgerMaxWriteLedgerEntries.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Uint32: %w", err) + } + nTmp, err = s.LedgerMaxWriteBytes.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Uint32: %w", err) + } + nTmp, err = s.TxMaxReadLedgerEntries.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Uint32: %w", err) + } + nTmp, err = s.TxMaxReadBytes.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Uint32: %w", err) + } + nTmp, err = s.TxMaxWriteLedgerEntries.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Uint32: %w", err) + } + nTmp, err = s.TxMaxWriteBytes.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Uint32: %w", err) + } + nTmp, err = s.FeeReadLedgerEntry.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Int64: %w", err) + } + nTmp, err = s.FeeWriteLedgerEntry.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Int64: %w", err) + } + nTmp, err = s.FeeRead1Kb.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Int64: %w", err) + } + nTmp, err = s.BucketListTargetSizeBytes.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Int64: %w", err) + } + nTmp, err = s.WriteFee1KbBucketListLow.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Int64: %w", err) + } + nTmp, err = s.WriteFee1KbBucketListHigh.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Int64: %w", err) + } + nTmp, err = s.BucketListWriteFeeGrowthFactor.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding PublicKey: %s", err) + return n, fmt.Errorf("decoding Uint32: %w", err) } return n, nil } // MarshalBinary implements encoding.BinaryMarshaler. -func (s NodeId) MarshalBinary() ([]byte, error) { +func (s ConfigSettingContractLedgerCostV0) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -37885,59 +54768,64 @@ func (s NodeId) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *NodeId) UnmarshalBinary(inp []byte) error { +func (s *ConfigSettingContractLedgerCostV0) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*NodeId)(nil) - _ encoding.BinaryUnmarshaler = (*NodeId)(nil) + _ encoding.BinaryMarshaler = (*ConfigSettingContractLedgerCostV0)(nil) + _ encoding.BinaryUnmarshaler = (*ConfigSettingContractLedgerCostV0)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s NodeId) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s ConfigSettingContractLedgerCostV0) xdrType() {} -var _ xdrType = (*NodeId)(nil) +var _ xdrType = (*ConfigSettingContractLedgerCostV0)(nil) -// Curve25519Secret is an XDR Struct defines as: +// ConfigSettingContractHistoricalDataV0 is an XDR Struct defines as: // -// struct Curve25519Secret +// struct ConfigSettingContractHistoricalDataV0 // { -// opaque key[32]; +// int64 feeHistorical1KB; // Fee for storing 1KB in archives // }; -type Curve25519Secret struct { - Key [32]byte `xdrmaxsize:"32"` +type ConfigSettingContractHistoricalDataV0 struct { + FeeHistorical1Kb Int64 } // EncodeTo encodes this value using the Encoder. -func (s *Curve25519Secret) EncodeTo(e *xdr.Encoder) error { +func (s *ConfigSettingContractHistoricalDataV0) EncodeTo(e *xdr.Encoder) error { var err error - if _, err = e.EncodeFixedOpaque(s.Key[:]); err != nil { + if err = s.FeeHistorical1Kb.EncodeTo(e); err != nil { return err } return nil } -var _ decoderFrom = (*Curve25519Secret)(nil) +var _ decoderFrom = (*ConfigSettingContractHistoricalDataV0)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *Curve25519Secret) DecodeFrom(d *xdr.Decoder) (int, error) { +func (s *ConfigSettingContractHistoricalDataV0) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding ConfigSettingContractHistoricalDataV0: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = d.DecodeFixedOpaqueInplace(s.Key[:]) + nTmp, err = s.FeeHistorical1Kb.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Key: %s", err) + return n, fmt.Errorf("decoding Int64: %w", err) } return n, nil } // MarshalBinary implements encoding.BinaryMarshaler. -func (s Curve25519Secret) MarshalBinary() ([]byte, error) { +func (s ConfigSettingContractHistoricalDataV0) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -37945,59 +54833,76 @@ func (s Curve25519Secret) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *Curve25519Secret) UnmarshalBinary(inp []byte) error { +func (s *ConfigSettingContractHistoricalDataV0) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*Curve25519Secret)(nil) - _ encoding.BinaryUnmarshaler = (*Curve25519Secret)(nil) + _ encoding.BinaryMarshaler = (*ConfigSettingContractHistoricalDataV0)(nil) + _ encoding.BinaryUnmarshaler = (*ConfigSettingContractHistoricalDataV0)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s Curve25519Secret) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s ConfigSettingContractHistoricalDataV0) xdrType() {} -var _ xdrType = (*Curve25519Secret)(nil) +var _ xdrType = (*ConfigSettingContractHistoricalDataV0)(nil) -// Curve25519Public is an XDR Struct defines as: +// ConfigSettingContractEventsV0 is an XDR Struct defines as: // -// struct Curve25519Public +// struct ConfigSettingContractEventsV0 // { -// opaque key[32]; +// // Maximum size of events that a contract call can emit. +// uint32 txMaxContractEventsSizeBytes; +// // Fee for generating 1KB of contract events. +// int64 feeContractEvents1KB; // }; -type Curve25519Public struct { - Key [32]byte `xdrmaxsize:"32"` +type ConfigSettingContractEventsV0 struct { + TxMaxContractEventsSizeBytes Uint32 + FeeContractEvents1Kb Int64 } // EncodeTo encodes this value using the Encoder. -func (s *Curve25519Public) EncodeTo(e *xdr.Encoder) error { +func (s *ConfigSettingContractEventsV0) EncodeTo(e *xdr.Encoder) error { var err error - if _, err = e.EncodeFixedOpaque(s.Key[:]); err != nil { + if err = s.TxMaxContractEventsSizeBytes.EncodeTo(e); err != nil { + return err + } + if err = s.FeeContractEvents1Kb.EncodeTo(e); err != nil { return err } return nil } -var _ decoderFrom = (*Curve25519Public)(nil) +var _ decoderFrom = (*ConfigSettingContractEventsV0)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *Curve25519Public) DecodeFrom(d *xdr.Decoder) (int, error) { +func (s *ConfigSettingContractEventsV0) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding ConfigSettingContractEventsV0: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = d.DecodeFixedOpaqueInplace(s.Key[:]) + nTmp, err = s.TxMaxContractEventsSizeBytes.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Uint32: %w", err) + } + nTmp, err = s.FeeContractEvents1Kb.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Key: %s", err) + return n, fmt.Errorf("decoding Int64: %w", err) } return n, nil } // MarshalBinary implements encoding.BinaryMarshaler. -func (s Curve25519Public) MarshalBinary() ([]byte, error) { +func (s ConfigSettingContractEventsV0) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -38005,59 +54910,88 @@ func (s Curve25519Public) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *Curve25519Public) UnmarshalBinary(inp []byte) error { +func (s *ConfigSettingContractEventsV0) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*Curve25519Public)(nil) - _ encoding.BinaryUnmarshaler = (*Curve25519Public)(nil) + _ encoding.BinaryMarshaler = (*ConfigSettingContractEventsV0)(nil) + _ encoding.BinaryUnmarshaler = (*ConfigSettingContractEventsV0)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s Curve25519Public) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s ConfigSettingContractEventsV0) xdrType() {} -var _ xdrType = (*Curve25519Public)(nil) +var _ xdrType = (*ConfigSettingContractEventsV0)(nil) -// HmacSha256Key is an XDR Struct defines as: +// ConfigSettingContractBandwidthV0 is an XDR Struct defines as: // -// struct HmacSha256Key +// struct ConfigSettingContractBandwidthV0 // { -// opaque key[32]; +// // Maximum sum of all transaction sizes in the ledger in bytes +// uint32 ledgerMaxTxsSizeBytes; +// // Maximum size in bytes for a transaction +// uint32 txMaxSizeBytes; +// +// // Fee for 1 KB of transaction size +// int64 feeTxSize1KB; // }; -type HmacSha256Key struct { - Key [32]byte `xdrmaxsize:"32"` +type ConfigSettingContractBandwidthV0 struct { + LedgerMaxTxsSizeBytes Uint32 + TxMaxSizeBytes Uint32 + FeeTxSize1Kb Int64 } // EncodeTo encodes this value using the Encoder. -func (s *HmacSha256Key) EncodeTo(e *xdr.Encoder) error { +func (s *ConfigSettingContractBandwidthV0) EncodeTo(e *xdr.Encoder) error { var err error - if _, err = e.EncodeFixedOpaque(s.Key[:]); err != nil { + if err = s.LedgerMaxTxsSizeBytes.EncodeTo(e); err != nil { + return err + } + if err = s.TxMaxSizeBytes.EncodeTo(e); err != nil { + return err + } + if err = s.FeeTxSize1Kb.EncodeTo(e); err != nil { return err } return nil } -var _ decoderFrom = (*HmacSha256Key)(nil) +var _ decoderFrom = (*ConfigSettingContractBandwidthV0)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *HmacSha256Key) DecodeFrom(d *xdr.Decoder) (int, error) { +func (s *ConfigSettingContractBandwidthV0) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding ConfigSettingContractBandwidthV0: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = d.DecodeFixedOpaqueInplace(s.Key[:]) + nTmp, err = s.LedgerMaxTxsSizeBytes.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Uint32: %w", err) + } + nTmp, err = s.TxMaxSizeBytes.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Uint32: %w", err) + } + nTmp, err = s.FeeTxSize1Kb.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Key: %s", err) + return n, fmt.Errorf("decoding Int64: %w", err) } return n, nil } // MarshalBinary implements encoding.BinaryMarshaler. -func (s HmacSha256Key) MarshalBinary() ([]byte, error) { +func (s ConfigSettingContractBandwidthV0) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -38065,59 +54999,176 @@ func (s HmacSha256Key) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *HmacSha256Key) UnmarshalBinary(inp []byte) error { +func (s *ConfigSettingContractBandwidthV0) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*HmacSha256Key)(nil) - _ encoding.BinaryUnmarshaler = (*HmacSha256Key)(nil) + _ encoding.BinaryMarshaler = (*ConfigSettingContractBandwidthV0)(nil) + _ encoding.BinaryUnmarshaler = (*ConfigSettingContractBandwidthV0)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s HmacSha256Key) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s ConfigSettingContractBandwidthV0) xdrType() {} -var _ xdrType = (*HmacSha256Key)(nil) +var _ xdrType = (*ConfigSettingContractBandwidthV0)(nil) -// HmacSha256Mac is an XDR Struct defines as: +// ContractCostType is an XDR Enum defines as: // -// struct HmacSha256Mac -// { -// opaque mac[32]; +// enum ContractCostType { +// // Cost of running 1 wasm instruction +// WasmInsnExec = 0, +// // Cost of allocating a slice of memory (in bytes) +// MemAlloc = 1, +// // Cost of copying a slice of bytes into a pre-allocated memory +// MemCpy = 2, +// // Cost of comparing two slices of memory +// MemCmp = 3, +// // Cost of a host function dispatch, not including the actual work done by +// // the function nor the cost of VM invocation machinary +// DispatchHostFunction = 4, +// // Cost of visiting a host object from the host object storage. Exists to +// // make sure some baseline cost coverage, i.e. repeatly visiting objects +// // by the guest will always incur some charges. +// VisitObject = 5, +// // Cost of serializing an xdr object to bytes +// ValSer = 6, +// // Cost of deserializing an xdr object from bytes +// ValDeser = 7, +// // Cost of computing the sha256 hash from bytes +// ComputeSha256Hash = 8, +// // Cost of computing the ed25519 pubkey from bytes +// ComputeEd25519PubKey = 9, +// // Cost of verifying ed25519 signature of a payload. +// VerifyEd25519Sig = 10, +// // Cost of instantiation a VM from wasm bytes code. +// VmInstantiation = 11, +// // Cost of instantiation a VM from a cached state. +// VmCachedInstantiation = 12, +// // Cost of invoking a function on the VM. If the function is a host function, +// // additional cost will be covered by `DispatchHostFunction`. +// InvokeVmFunction = 13, +// // Cost of computing a keccak256 hash from bytes. +// ComputeKeccak256Hash = 14, +// // Cost of computing an ECDSA secp256k1 signature from bytes. +// ComputeEcdsaSecp256k1Sig = 15, +// // Cost of recovering an ECDSA secp256k1 key from a signature. +// RecoverEcdsaSecp256k1Key = 16, +// // Cost of int256 addition (`+`) and subtraction (`-`) operations +// Int256AddSub = 17, +// // Cost of int256 multiplication (`*`) operation +// Int256Mul = 18, +// // Cost of int256 division (`/`) operation +// Int256Div = 19, +// // Cost of int256 power (`exp`) operation +// Int256Pow = 20, +// // Cost of int256 shift (`shl`, `shr`) operation +// Int256Shift = 21, +// // Cost of drawing random bytes using a ChaCha20 PRNG +// ChaCha20DrawBytes = 22 // }; -type HmacSha256Mac struct { - Mac [32]byte `xdrmaxsize:"32"` +type ContractCostType int32 + +const ( + ContractCostTypeWasmInsnExec ContractCostType = 0 + ContractCostTypeMemAlloc ContractCostType = 1 + ContractCostTypeMemCpy ContractCostType = 2 + ContractCostTypeMemCmp ContractCostType = 3 + ContractCostTypeDispatchHostFunction ContractCostType = 4 + ContractCostTypeVisitObject ContractCostType = 5 + ContractCostTypeValSer ContractCostType = 6 + ContractCostTypeValDeser ContractCostType = 7 + ContractCostTypeComputeSha256Hash ContractCostType = 8 + ContractCostTypeComputeEd25519PubKey ContractCostType = 9 + ContractCostTypeVerifyEd25519Sig ContractCostType = 10 + ContractCostTypeVmInstantiation ContractCostType = 11 + ContractCostTypeVmCachedInstantiation ContractCostType = 12 + ContractCostTypeInvokeVmFunction ContractCostType = 13 + ContractCostTypeComputeKeccak256Hash ContractCostType = 14 + ContractCostTypeComputeEcdsaSecp256k1Sig ContractCostType = 15 + ContractCostTypeRecoverEcdsaSecp256k1Key ContractCostType = 16 + ContractCostTypeInt256AddSub ContractCostType = 17 + ContractCostTypeInt256Mul ContractCostType = 18 + ContractCostTypeInt256Div ContractCostType = 19 + ContractCostTypeInt256Pow ContractCostType = 20 + ContractCostTypeInt256Shift ContractCostType = 21 + ContractCostTypeChaCha20DrawBytes ContractCostType = 22 +) + +var contractCostTypeMap = map[int32]string{ + 0: "ContractCostTypeWasmInsnExec", + 1: "ContractCostTypeMemAlloc", + 2: "ContractCostTypeMemCpy", + 3: "ContractCostTypeMemCmp", + 4: "ContractCostTypeDispatchHostFunction", + 5: "ContractCostTypeVisitObject", + 6: "ContractCostTypeValSer", + 7: "ContractCostTypeValDeser", + 8: "ContractCostTypeComputeSha256Hash", + 9: "ContractCostTypeComputeEd25519PubKey", + 10: "ContractCostTypeVerifyEd25519Sig", + 11: "ContractCostTypeVmInstantiation", + 12: "ContractCostTypeVmCachedInstantiation", + 13: "ContractCostTypeInvokeVmFunction", + 14: "ContractCostTypeComputeKeccak256Hash", + 15: "ContractCostTypeComputeEcdsaSecp256k1Sig", + 16: "ContractCostTypeRecoverEcdsaSecp256k1Key", + 17: "ContractCostTypeInt256AddSub", + 18: "ContractCostTypeInt256Mul", + 19: "ContractCostTypeInt256Div", + 20: "ContractCostTypeInt256Pow", + 21: "ContractCostTypeInt256Shift", + 22: "ContractCostTypeChaCha20DrawBytes", +} + +// ValidEnum validates a proposed value for this enum. Implements +// the Enum interface for ContractCostType +func (e ContractCostType) ValidEnum(v int32) bool { + _, ok := contractCostTypeMap[v] + return ok +} + +// String returns the name of `e` +func (e ContractCostType) String() string { + name, _ := contractCostTypeMap[int32(e)] + return name } // EncodeTo encodes this value using the Encoder. -func (s *HmacSha256Mac) EncodeTo(e *xdr.Encoder) error { - var err error - if _, err = e.EncodeFixedOpaque(s.Mac[:]); err != nil { - return err +func (e ContractCostType) EncodeTo(enc *xdr.Encoder) error { + if _, ok := contractCostTypeMap[int32(e)]; !ok { + return fmt.Errorf("'%d' is not a valid ContractCostType enum value", e) } - return nil + _, err := enc.EncodeInt(int32(e)) + return err } -var _ decoderFrom = (*HmacSha256Mac)(nil) +var _ decoderFrom = (*ContractCostType)(nil) -// DecodeFrom decodes this value using the Decoder. -func (s *HmacSha256Mac) DecodeFrom(d *xdr.Decoder) (int, error) { - var err error - var n, nTmp int - nTmp, err = d.DecodeFixedOpaqueInplace(s.Mac[:]) - n += nTmp +// DecodeFrom decodes this value using the Decoder. +func (e *ContractCostType) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding ContractCostType: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + v, n, err := d.DecodeInt() if err != nil { - return n, fmt.Errorf("decoding Mac: %s", err) + return n, fmt.Errorf("decoding ContractCostType: %w", err) + } + if _, ok := contractCostTypeMap[v]; !ok { + return n, fmt.Errorf("'%d' is not a valid ContractCostType enum value", v) } + *e = ContractCostType(v) return n, nil } // MarshalBinary implements encoding.BinaryMarshaler. -func (s HmacSha256Mac) MarshalBinary() ([]byte, error) { +func (s ContractCostType) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -38125,78 +55176,85 @@ func (s HmacSha256Mac) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *HmacSha256Mac) UnmarshalBinary(inp []byte) error { +func (s *ContractCostType) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*HmacSha256Mac)(nil) - _ encoding.BinaryUnmarshaler = (*HmacSha256Mac)(nil) + _ encoding.BinaryMarshaler = (*ContractCostType)(nil) + _ encoding.BinaryUnmarshaler = (*ContractCostType)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s HmacSha256Mac) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s ContractCostType) xdrType() {} -var _ xdrType = (*HmacSha256Mac)(nil) +var _ xdrType = (*ContractCostType)(nil) -// BitmapIndex is an XDR Struct defines as: +// ContractCostParamEntry is an XDR Struct defines as: +// +// struct ContractCostParamEntry { +// // use `ext` to add more terms (e.g. higher order polynomials) in the future +// ExtensionPoint ext; // -// struct BitmapIndex { -// uint32 firstBit; -// uint32 lastBit; -// Value bitmap; +// int64 constTerm; +// int64 linearTerm; // }; -type BitmapIndex struct { - FirstBit Uint32 - LastBit Uint32 - Bitmap Value +type ContractCostParamEntry struct { + Ext ExtensionPoint + ConstTerm Int64 + LinearTerm Int64 } // EncodeTo encodes this value using the Encoder. -func (s *BitmapIndex) EncodeTo(e *xdr.Encoder) error { +func (s *ContractCostParamEntry) EncodeTo(e *xdr.Encoder) error { var err error - if err = s.FirstBit.EncodeTo(e); err != nil { + if err = s.Ext.EncodeTo(e); err != nil { return err } - if err = s.LastBit.EncodeTo(e); err != nil { + if err = s.ConstTerm.EncodeTo(e); err != nil { return err } - if err = s.Bitmap.EncodeTo(e); err != nil { + if err = s.LinearTerm.EncodeTo(e); err != nil { return err } return nil } -var _ decoderFrom = (*BitmapIndex)(nil) +var _ decoderFrom = (*ContractCostParamEntry)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *BitmapIndex) DecodeFrom(d *xdr.Decoder) (int, error) { +func (s *ContractCostParamEntry) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding ContractCostParamEntry: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = s.FirstBit.DecodeFrom(d) + nTmp, err = s.Ext.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Uint32: %s", err) + return n, fmt.Errorf("decoding ExtensionPoint: %w", err) } - nTmp, err = s.LastBit.DecodeFrom(d) + nTmp, err = s.ConstTerm.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Uint32: %s", err) + return n, fmt.Errorf("decoding Int64: %w", err) } - nTmp, err = s.Bitmap.DecodeFrom(d) + nTmp, err = s.LinearTerm.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Value: %s", err) + return n, fmt.Errorf("decoding Int64: %w", err) } return n, nil } // MarshalBinary implements encoding.BinaryMarshaler. -func (s BitmapIndex) MarshalBinary() ([]byte, error) { +func (s ContractCostParamEntry) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -38204,68 +55262,153 @@ func (s BitmapIndex) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *BitmapIndex) UnmarshalBinary(inp []byte) error { +func (s *ContractCostParamEntry) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*BitmapIndex)(nil) - _ encoding.BinaryUnmarshaler = (*BitmapIndex)(nil) + _ encoding.BinaryMarshaler = (*ContractCostParamEntry)(nil) + _ encoding.BinaryUnmarshaler = (*ContractCostParamEntry)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s BitmapIndex) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s ContractCostParamEntry) xdrType() {} -var _ xdrType = (*BitmapIndex)(nil) +var _ xdrType = (*ContractCostParamEntry)(nil) -// TrieIndex is an XDR Struct defines as: +// StateArchivalSettings is an XDR Struct defines as: +// +// struct StateArchivalSettings { +// uint32 maxEntryTTL; +// uint32 minTemporaryTTL; +// uint32 minPersistentTTL; +// +// // rent_fee = wfee_rate_average / rent_rate_denominator_for_type +// int64 persistentRentRateDenominator; +// int64 tempRentRateDenominator; // -// struct TrieIndex { -// uint32 version_; // goxdr gives an error if we simply use "version" as an identifier -// TrieNode root; +// // max number of entries that emit archival meta in a single ledger +// uint32 maxEntriesToArchive; +// +// // Number of snapshots to use when calculating average BucketList size +// uint32 bucketListSizeWindowSampleSize; +// +// // Maximum number of bytes that we scan for eviction per ledger +// uint64 evictionScanSize; +// +// // Lowest BucketList level to be scanned to evict entries +// uint32 startingEvictionScanLevel; // }; -type TrieIndex struct { - Version Uint32 - Root TrieNode +type StateArchivalSettings struct { + MaxEntryTtl Uint32 + MinTemporaryTtl Uint32 + MinPersistentTtl Uint32 + PersistentRentRateDenominator Int64 + TempRentRateDenominator Int64 + MaxEntriesToArchive Uint32 + BucketListSizeWindowSampleSize Uint32 + EvictionScanSize Uint64 + StartingEvictionScanLevel Uint32 } // EncodeTo encodes this value using the Encoder. -func (s *TrieIndex) EncodeTo(e *xdr.Encoder) error { +func (s *StateArchivalSettings) EncodeTo(e *xdr.Encoder) error { var err error - if err = s.Version.EncodeTo(e); err != nil { + if err = s.MaxEntryTtl.EncodeTo(e); err != nil { + return err + } + if err = s.MinTemporaryTtl.EncodeTo(e); err != nil { + return err + } + if err = s.MinPersistentTtl.EncodeTo(e); err != nil { + return err + } + if err = s.PersistentRentRateDenominator.EncodeTo(e); err != nil { + return err + } + if err = s.TempRentRateDenominator.EncodeTo(e); err != nil { + return err + } + if err = s.MaxEntriesToArchive.EncodeTo(e); err != nil { + return err + } + if err = s.BucketListSizeWindowSampleSize.EncodeTo(e); err != nil { + return err + } + if err = s.EvictionScanSize.EncodeTo(e); err != nil { return err } - if err = s.Root.EncodeTo(e); err != nil { + if err = s.StartingEvictionScanLevel.EncodeTo(e); err != nil { return err } return nil } -var _ decoderFrom = (*TrieIndex)(nil) +var _ decoderFrom = (*StateArchivalSettings)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *TrieIndex) DecodeFrom(d *xdr.Decoder) (int, error) { +func (s *StateArchivalSettings) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding StateArchivalSettings: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = s.Version.DecodeFrom(d) + nTmp, err = s.MaxEntryTtl.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Uint32: %w", err) + } + nTmp, err = s.MinTemporaryTtl.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Uint32: %w", err) + } + nTmp, err = s.MinPersistentTtl.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Uint32: %w", err) + } + nTmp, err = s.PersistentRentRateDenominator.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Int64: %w", err) + } + nTmp, err = s.TempRentRateDenominator.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Int64: %w", err) + } + nTmp, err = s.MaxEntriesToArchive.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Uint32: %w", err) + } + nTmp, err = s.BucketListSizeWindowSampleSize.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Uint32: %s", err) + return n, fmt.Errorf("decoding Uint32: %w", err) } - nTmp, err = s.Root.DecodeFrom(d) + nTmp, err = s.EvictionScanSize.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding TrieNode: %s", err) + return n, fmt.Errorf("decoding Uint64: %w", err) + } + nTmp, err = s.StartingEvictionScanLevel.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Uint32: %w", err) } return n, nil } // MarshalBinary implements encoding.BinaryMarshaler. -func (s TrieIndex) MarshalBinary() ([]byte, error) { +func (s StateArchivalSettings) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -38273,68 +55416,83 @@ func (s TrieIndex) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *TrieIndex) UnmarshalBinary(inp []byte) error { +func (s *StateArchivalSettings) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*TrieIndex)(nil) - _ encoding.BinaryUnmarshaler = (*TrieIndex)(nil) + _ encoding.BinaryMarshaler = (*StateArchivalSettings)(nil) + _ encoding.BinaryUnmarshaler = (*StateArchivalSettings)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s TrieIndex) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s StateArchivalSettings) xdrType() {} -var _ xdrType = (*TrieIndex)(nil) +var _ xdrType = (*StateArchivalSettings)(nil) -// TrieNodeChild is an XDR Struct defines as: +// EvictionIterator is an XDR Struct defines as: // -// struct TrieNodeChild { -// opaque key[1]; -// TrieNode node; +// struct EvictionIterator { +// uint32 bucketListLevel; +// bool isCurrBucket; +// uint64 bucketFileOffset; // }; -type TrieNodeChild struct { - Key [1]byte `xdrmaxsize:"1"` - Node TrieNode +type EvictionIterator struct { + BucketListLevel Uint32 + IsCurrBucket bool + BucketFileOffset Uint64 } // EncodeTo encodes this value using the Encoder. -func (s *TrieNodeChild) EncodeTo(e *xdr.Encoder) error { +func (s *EvictionIterator) EncodeTo(e *xdr.Encoder) error { var err error - if _, err = e.EncodeFixedOpaque(s.Key[:]); err != nil { + if err = s.BucketListLevel.EncodeTo(e); err != nil { return err } - if err = s.Node.EncodeTo(e); err != nil { + if _, err = e.EncodeBool(bool(s.IsCurrBucket)); err != nil { + return err + } + if err = s.BucketFileOffset.EncodeTo(e); err != nil { return err } return nil } -var _ decoderFrom = (*TrieNodeChild)(nil) +var _ decoderFrom = (*EvictionIterator)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *TrieNodeChild) DecodeFrom(d *xdr.Decoder) (int, error) { +func (s *EvictionIterator) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding EvictionIterator: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = d.DecodeFixedOpaqueInplace(s.Key[:]) + nTmp, err = s.BucketListLevel.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Key: %s", err) + return n, fmt.Errorf("decoding Uint32: %w", err) } - nTmp, err = s.Node.DecodeFrom(d) + s.IsCurrBucket, nTmp, err = d.DecodeBool() n += nTmp if err != nil { - return n, fmt.Errorf("decoding TrieNode: %s", err) + return n, fmt.Errorf("decoding Bool: %w", err) + } + nTmp, err = s.BucketFileOffset.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Uint64: %w", err) } return n, nil } // MarshalBinary implements encoding.BinaryMarshaler. -func (s TrieNodeChild) MarshalBinary() ([]byte, error) { +func (s EvictionIterator) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -38342,87 +55500,84 @@ func (s TrieNodeChild) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *TrieNodeChild) UnmarshalBinary(inp []byte) error { +func (s *EvictionIterator) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*TrieNodeChild)(nil) - _ encoding.BinaryUnmarshaler = (*TrieNodeChild)(nil) + _ encoding.BinaryMarshaler = (*EvictionIterator)(nil) + _ encoding.BinaryUnmarshaler = (*EvictionIterator)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s TrieNodeChild) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s EvictionIterator) xdrType() {} -var _ xdrType = (*TrieNodeChild)(nil) +var _ xdrType = (*EvictionIterator)(nil) -// TrieNode is an XDR Struct defines as: +// ContractCostCountLimit is an XDR Const defines as: // -// struct TrieNode { -// Value prefix; -// Value value; -// TrieNodeChild children<>; -// }; -type TrieNode struct { - Prefix Value - Value Value - Children []TrieNodeChild +// const CONTRACT_COST_COUNT_LIMIT = 1024; +const ContractCostCountLimit = 1024 + +// ContractCostParams is an XDR Typedef defines as: +// +// typedef ContractCostParamEntry ContractCostParams; +type ContractCostParams []ContractCostParamEntry + +// XDRMaxSize implements the Sized interface for ContractCostParams +func (e ContractCostParams) XDRMaxSize() int { + return 1024 } // EncodeTo encodes this value using the Encoder. -func (s *TrieNode) EncodeTo(e *xdr.Encoder) error { +func (s ContractCostParams) EncodeTo(e *xdr.Encoder) error { var err error - if err = s.Prefix.EncodeTo(e); err != nil { - return err - } - if err = s.Value.EncodeTo(e); err != nil { - return err - } - if _, err = e.EncodeUint(uint32(len(s.Children))); err != nil { + if _, err = e.EncodeUint(uint32(len(s))); err != nil { return err } - for i := 0; i < len(s.Children); i++ { - if err = s.Children[i].EncodeTo(e); err != nil { + for i := 0; i < len(s); i++ { + if err = s[i].EncodeTo(e); err != nil { return err } } return nil } -var _ decoderFrom = (*TrieNode)(nil) +var _ decoderFrom = (*ContractCostParams)(nil) // DecodeFrom decodes this value using the Decoder. -func (s *TrieNode) DecodeFrom(d *xdr.Decoder) (int, error) { +func (s *ContractCostParams) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding ContractCostParams: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - nTmp, err = s.Prefix.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Value: %s", err) - } - nTmp, err = s.Value.DecodeFrom(d) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Value: %s", err) - } var l uint32 l, nTmp, err = d.DecodeUint() n += nTmp if err != nil { - return n, fmt.Errorf("decoding TrieNodeChild: %s", err) + return n, fmt.Errorf("decoding ContractCostParamEntry: %w", err) } - s.Children = nil + if l > 1024 { + return n, fmt.Errorf("decoding ContractCostParamEntry: data size (%d) exceeds size limit (1024)", l) + } + (*s) = nil if l > 0 { - s.Children = make([]TrieNodeChild, l) + if il, ok := d.InputLen(); ok && uint(il) < uint(l) { + return n, fmt.Errorf("decoding ContractCostParamEntry: length (%d) exceeds remaining input length (%d)", l, il) + } + (*s) = make([]ContractCostParamEntry, l) for i := uint32(0); i < l; i++ { - nTmp, err = s.Children[i].DecodeFrom(d) + nTmp, err = (*s)[i].DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding TrieNodeChild: %s", err) + return n, fmt.Errorf("decoding ContractCostParamEntry: %w", err) } } } @@ -38430,7 +55585,7 @@ func (s *TrieNode) DecodeFrom(d *xdr.Decoder) (int, error) { } // MarshalBinary implements encoding.BinaryMarshaler. -func (s TrieNode) MarshalBinary() ([]byte, error) { +func (s ContractCostParams) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -38438,86 +55593,692 @@ func (s TrieNode) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *TrieNode) UnmarshalBinary(inp []byte) error { +func (s *ContractCostParams) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*TrieNode)(nil) - _ encoding.BinaryUnmarshaler = (*TrieNode)(nil) + _ encoding.BinaryMarshaler = (*ContractCostParams)(nil) + _ encoding.BinaryUnmarshaler = (*ContractCostParams)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s TrieNode) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s ContractCostParams) xdrType() {} -var _ xdrType = (*TrieNode)(nil) +var _ xdrType = (*ContractCostParams)(nil) -// SerializedLedgerCloseMeta is an XDR Union defines as: +// ConfigSettingId is an XDR Enum defines as: // -// union SerializedLedgerCloseMeta switch (int v) +// enum ConfigSettingID // { -// case 0: -// LedgerCloseMeta v0; +// CONFIG_SETTING_CONTRACT_MAX_SIZE_BYTES = 0, +// CONFIG_SETTING_CONTRACT_COMPUTE_V0 = 1, +// CONFIG_SETTING_CONTRACT_LEDGER_COST_V0 = 2, +// CONFIG_SETTING_CONTRACT_HISTORICAL_DATA_V0 = 3, +// CONFIG_SETTING_CONTRACT_EVENTS_V0 = 4, +// CONFIG_SETTING_CONTRACT_BANDWIDTH_V0 = 5, +// CONFIG_SETTING_CONTRACT_COST_PARAMS_CPU_INSTRUCTIONS = 6, +// CONFIG_SETTING_CONTRACT_COST_PARAMS_MEMORY_BYTES = 7, +// CONFIG_SETTING_CONTRACT_DATA_KEY_SIZE_BYTES = 8, +// CONFIG_SETTING_CONTRACT_DATA_ENTRY_SIZE_BYTES = 9, +// CONFIG_SETTING_STATE_ARCHIVAL = 10, +// CONFIG_SETTING_CONTRACT_EXECUTION_LANES = 11, +// CONFIG_SETTING_BUCKETLIST_SIZE_WINDOW = 12, +// CONFIG_SETTING_EVICTION_ITERATOR = 13 // }; -type SerializedLedgerCloseMeta struct { - V int32 - V0 *LedgerCloseMeta +type ConfigSettingId int32 + +const ( + ConfigSettingIdConfigSettingContractMaxSizeBytes ConfigSettingId = 0 + ConfigSettingIdConfigSettingContractComputeV0 ConfigSettingId = 1 + ConfigSettingIdConfigSettingContractLedgerCostV0 ConfigSettingId = 2 + ConfigSettingIdConfigSettingContractHistoricalDataV0 ConfigSettingId = 3 + ConfigSettingIdConfigSettingContractEventsV0 ConfigSettingId = 4 + ConfigSettingIdConfigSettingContractBandwidthV0 ConfigSettingId = 5 + ConfigSettingIdConfigSettingContractCostParamsCpuInstructions ConfigSettingId = 6 + ConfigSettingIdConfigSettingContractCostParamsMemoryBytes ConfigSettingId = 7 + ConfigSettingIdConfigSettingContractDataKeySizeBytes ConfigSettingId = 8 + ConfigSettingIdConfigSettingContractDataEntrySizeBytes ConfigSettingId = 9 + ConfigSettingIdConfigSettingStateArchival ConfigSettingId = 10 + ConfigSettingIdConfigSettingContractExecutionLanes ConfigSettingId = 11 + ConfigSettingIdConfigSettingBucketlistSizeWindow ConfigSettingId = 12 + ConfigSettingIdConfigSettingEvictionIterator ConfigSettingId = 13 +) + +var configSettingIdMap = map[int32]string{ + 0: "ConfigSettingIdConfigSettingContractMaxSizeBytes", + 1: "ConfigSettingIdConfigSettingContractComputeV0", + 2: "ConfigSettingIdConfigSettingContractLedgerCostV0", + 3: "ConfigSettingIdConfigSettingContractHistoricalDataV0", + 4: "ConfigSettingIdConfigSettingContractEventsV0", + 5: "ConfigSettingIdConfigSettingContractBandwidthV0", + 6: "ConfigSettingIdConfigSettingContractCostParamsCpuInstructions", + 7: "ConfigSettingIdConfigSettingContractCostParamsMemoryBytes", + 8: "ConfigSettingIdConfigSettingContractDataKeySizeBytes", + 9: "ConfigSettingIdConfigSettingContractDataEntrySizeBytes", + 10: "ConfigSettingIdConfigSettingStateArchival", + 11: "ConfigSettingIdConfigSettingContractExecutionLanes", + 12: "ConfigSettingIdConfigSettingBucketlistSizeWindow", + 13: "ConfigSettingIdConfigSettingEvictionIterator", +} + +// ValidEnum validates a proposed value for this enum. Implements +// the Enum interface for ConfigSettingId +func (e ConfigSettingId) ValidEnum(v int32) bool { + _, ok := configSettingIdMap[v] + return ok +} + +// String returns the name of `e` +func (e ConfigSettingId) String() string { + name, _ := configSettingIdMap[int32(e)] + return name +} + +// EncodeTo encodes this value using the Encoder. +func (e ConfigSettingId) EncodeTo(enc *xdr.Encoder) error { + if _, ok := configSettingIdMap[int32(e)]; !ok { + return fmt.Errorf("'%d' is not a valid ConfigSettingId enum value", e) + } + _, err := enc.EncodeInt(int32(e)) + return err +} + +var _ decoderFrom = (*ConfigSettingId)(nil) + +// DecodeFrom decodes this value using the Decoder. +func (e *ConfigSettingId) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding ConfigSettingId: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + v, n, err := d.DecodeInt() + if err != nil { + return n, fmt.Errorf("decoding ConfigSettingId: %w", err) + } + if _, ok := configSettingIdMap[v]; !ok { + return n, fmt.Errorf("'%d' is not a valid ConfigSettingId enum value", v) + } + *e = ConfigSettingId(v) + return n, nil +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (s ConfigSettingId) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *ConfigSettingId) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} + +var ( + _ encoding.BinaryMarshaler = (*ConfigSettingId)(nil) + _ encoding.BinaryUnmarshaler = (*ConfigSettingId)(nil) +) + +// xdrType signals that this type represents XDR values defined by this package. +func (s ConfigSettingId) xdrType() {} + +var _ xdrType = (*ConfigSettingId)(nil) + +// ConfigSettingEntry is an XDR Union defines as: +// +// union ConfigSettingEntry switch (ConfigSettingID configSettingID) +// { +// case CONFIG_SETTING_CONTRACT_MAX_SIZE_BYTES: +// uint32 contractMaxSizeBytes; +// case CONFIG_SETTING_CONTRACT_COMPUTE_V0: +// ConfigSettingContractComputeV0 contractCompute; +// case CONFIG_SETTING_CONTRACT_LEDGER_COST_V0: +// ConfigSettingContractLedgerCostV0 contractLedgerCost; +// case CONFIG_SETTING_CONTRACT_HISTORICAL_DATA_V0: +// ConfigSettingContractHistoricalDataV0 contractHistoricalData; +// case CONFIG_SETTING_CONTRACT_EVENTS_V0: +// ConfigSettingContractEventsV0 contractEvents; +// case CONFIG_SETTING_CONTRACT_BANDWIDTH_V0: +// ConfigSettingContractBandwidthV0 contractBandwidth; +// case CONFIG_SETTING_CONTRACT_COST_PARAMS_CPU_INSTRUCTIONS: +// ContractCostParams contractCostParamsCpuInsns; +// case CONFIG_SETTING_CONTRACT_COST_PARAMS_MEMORY_BYTES: +// ContractCostParams contractCostParamsMemBytes; +// case CONFIG_SETTING_CONTRACT_DATA_KEY_SIZE_BYTES: +// uint32 contractDataKeySizeBytes; +// case CONFIG_SETTING_CONTRACT_DATA_ENTRY_SIZE_BYTES: +// uint32 contractDataEntrySizeBytes; +// case CONFIG_SETTING_STATE_ARCHIVAL: +// StateArchivalSettings stateArchivalSettings; +// case CONFIG_SETTING_CONTRACT_EXECUTION_LANES: +// ConfigSettingContractExecutionLanesV0 contractExecutionLanes; +// case CONFIG_SETTING_BUCKETLIST_SIZE_WINDOW: +// uint64 bucketListSizeWindow<>; +// case CONFIG_SETTING_EVICTION_ITERATOR: +// EvictionIterator evictionIterator; +// }; +type ConfigSettingEntry struct { + ConfigSettingId ConfigSettingId + ContractMaxSizeBytes *Uint32 + ContractCompute *ConfigSettingContractComputeV0 + ContractLedgerCost *ConfigSettingContractLedgerCostV0 + ContractHistoricalData *ConfigSettingContractHistoricalDataV0 + ContractEvents *ConfigSettingContractEventsV0 + ContractBandwidth *ConfigSettingContractBandwidthV0 + ContractCostParamsCpuInsns *ContractCostParams + ContractCostParamsMemBytes *ContractCostParams + ContractDataKeySizeBytes *Uint32 + ContractDataEntrySizeBytes *Uint32 + StateArchivalSettings *StateArchivalSettings + ContractExecutionLanes *ConfigSettingContractExecutionLanesV0 + BucketListSizeWindow *[]Uint64 + EvictionIterator *EvictionIterator } // SwitchFieldName returns the field name in which this union's // discriminant is stored -func (u SerializedLedgerCloseMeta) SwitchFieldName() string { - return "V" +func (u ConfigSettingEntry) SwitchFieldName() string { + return "ConfigSettingId" } // ArmForSwitch returns which field name should be used for storing -// the value for an instance of SerializedLedgerCloseMeta -func (u SerializedLedgerCloseMeta) ArmForSwitch(sw int32) (string, bool) { - switch int32(sw) { - case 0: - return "V0", true +// the value for an instance of ConfigSettingEntry +func (u ConfigSettingEntry) ArmForSwitch(sw int32) (string, bool) { + switch ConfigSettingId(sw) { + case ConfigSettingIdConfigSettingContractMaxSizeBytes: + return "ContractMaxSizeBytes", true + case ConfigSettingIdConfigSettingContractComputeV0: + return "ContractCompute", true + case ConfigSettingIdConfigSettingContractLedgerCostV0: + return "ContractLedgerCost", true + case ConfigSettingIdConfigSettingContractHistoricalDataV0: + return "ContractHistoricalData", true + case ConfigSettingIdConfigSettingContractEventsV0: + return "ContractEvents", true + case ConfigSettingIdConfigSettingContractBandwidthV0: + return "ContractBandwidth", true + case ConfigSettingIdConfigSettingContractCostParamsCpuInstructions: + return "ContractCostParamsCpuInsns", true + case ConfigSettingIdConfigSettingContractCostParamsMemoryBytes: + return "ContractCostParamsMemBytes", true + case ConfigSettingIdConfigSettingContractDataKeySizeBytes: + return "ContractDataKeySizeBytes", true + case ConfigSettingIdConfigSettingContractDataEntrySizeBytes: + return "ContractDataEntrySizeBytes", true + case ConfigSettingIdConfigSettingStateArchival: + return "StateArchivalSettings", true + case ConfigSettingIdConfigSettingContractExecutionLanes: + return "ContractExecutionLanes", true + case ConfigSettingIdConfigSettingBucketlistSizeWindow: + return "BucketListSizeWindow", true + case ConfigSettingIdConfigSettingEvictionIterator: + return "EvictionIterator", true } return "-", false } -// NewSerializedLedgerCloseMeta creates a new SerializedLedgerCloseMeta. -func NewSerializedLedgerCloseMeta(v int32, value interface{}) (result SerializedLedgerCloseMeta, err error) { - result.V = v - switch int32(v) { - case 0: - tv, ok := value.(LedgerCloseMeta) +// NewConfigSettingEntry creates a new ConfigSettingEntry. +func NewConfigSettingEntry(configSettingId ConfigSettingId, value interface{}) (result ConfigSettingEntry, err error) { + result.ConfigSettingId = configSettingId + switch ConfigSettingId(configSettingId) { + case ConfigSettingIdConfigSettingContractMaxSizeBytes: + tv, ok := value.(Uint32) if !ok { - err = fmt.Errorf("invalid value, must be LedgerCloseMeta") + err = errors.New("invalid value, must be Uint32") return } - result.V0 = &tv + result.ContractMaxSizeBytes = &tv + case ConfigSettingIdConfigSettingContractComputeV0: + tv, ok := value.(ConfigSettingContractComputeV0) + if !ok { + err = errors.New("invalid value, must be ConfigSettingContractComputeV0") + return + } + result.ContractCompute = &tv + case ConfigSettingIdConfigSettingContractLedgerCostV0: + tv, ok := value.(ConfigSettingContractLedgerCostV0) + if !ok { + err = errors.New("invalid value, must be ConfigSettingContractLedgerCostV0") + return + } + result.ContractLedgerCost = &tv + case ConfigSettingIdConfigSettingContractHistoricalDataV0: + tv, ok := value.(ConfigSettingContractHistoricalDataV0) + if !ok { + err = errors.New("invalid value, must be ConfigSettingContractHistoricalDataV0") + return + } + result.ContractHistoricalData = &tv + case ConfigSettingIdConfigSettingContractEventsV0: + tv, ok := value.(ConfigSettingContractEventsV0) + if !ok { + err = errors.New("invalid value, must be ConfigSettingContractEventsV0") + return + } + result.ContractEvents = &tv + case ConfigSettingIdConfigSettingContractBandwidthV0: + tv, ok := value.(ConfigSettingContractBandwidthV0) + if !ok { + err = errors.New("invalid value, must be ConfigSettingContractBandwidthV0") + return + } + result.ContractBandwidth = &tv + case ConfigSettingIdConfigSettingContractCostParamsCpuInstructions: + tv, ok := value.(ContractCostParams) + if !ok { + err = errors.New("invalid value, must be ContractCostParams") + return + } + result.ContractCostParamsCpuInsns = &tv + case ConfigSettingIdConfigSettingContractCostParamsMemoryBytes: + tv, ok := value.(ContractCostParams) + if !ok { + err = errors.New("invalid value, must be ContractCostParams") + return + } + result.ContractCostParamsMemBytes = &tv + case ConfigSettingIdConfigSettingContractDataKeySizeBytes: + tv, ok := value.(Uint32) + if !ok { + err = errors.New("invalid value, must be Uint32") + return + } + result.ContractDataKeySizeBytes = &tv + case ConfigSettingIdConfigSettingContractDataEntrySizeBytes: + tv, ok := value.(Uint32) + if !ok { + err = errors.New("invalid value, must be Uint32") + return + } + result.ContractDataEntrySizeBytes = &tv + case ConfigSettingIdConfigSettingStateArchival: + tv, ok := value.(StateArchivalSettings) + if !ok { + err = errors.New("invalid value, must be StateArchivalSettings") + return + } + result.StateArchivalSettings = &tv + case ConfigSettingIdConfigSettingContractExecutionLanes: + tv, ok := value.(ConfigSettingContractExecutionLanesV0) + if !ok { + err = errors.New("invalid value, must be ConfigSettingContractExecutionLanesV0") + return + } + result.ContractExecutionLanes = &tv + case ConfigSettingIdConfigSettingBucketlistSizeWindow: + tv, ok := value.([]Uint64) + if !ok { + err = errors.New("invalid value, must be []Uint64") + return + } + result.BucketListSizeWindow = &tv + case ConfigSettingIdConfigSettingEvictionIterator: + tv, ok := value.(EvictionIterator) + if !ok { + err = errors.New("invalid value, must be EvictionIterator") + return + } + result.EvictionIterator = &tv } return } -// MustV0 retrieves the V0 value from the union, +// MustContractMaxSizeBytes retrieves the ContractMaxSizeBytes value from the union, // panicing if the value is not set. -func (u SerializedLedgerCloseMeta) MustV0() LedgerCloseMeta { - val, ok := u.GetV0() +func (u ConfigSettingEntry) MustContractMaxSizeBytes() Uint32 { + val, ok := u.GetContractMaxSizeBytes() if !ok { - panic("arm V0 is not set") + panic("arm ContractMaxSizeBytes is not set") } return val } -// GetV0 retrieves the V0 value from the union, +// GetContractMaxSizeBytes retrieves the ContractMaxSizeBytes value from the union, // returning ok if the union's switch indicated the value is valid. -func (u SerializedLedgerCloseMeta) GetV0() (result LedgerCloseMeta, ok bool) { - armName, _ := u.ArmForSwitch(int32(u.V)) +func (u ConfigSettingEntry) GetContractMaxSizeBytes() (result Uint32, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.ConfigSettingId)) - if armName == "V0" { - result = *u.V0 + if armName == "ContractMaxSizeBytes" { + result = *u.ContractMaxSizeBytes + ok = true + } + + return +} + +// MustContractCompute retrieves the ContractCompute value from the union, +// panicing if the value is not set. +func (u ConfigSettingEntry) MustContractCompute() ConfigSettingContractComputeV0 { + val, ok := u.GetContractCompute() + + if !ok { + panic("arm ContractCompute is not set") + } + + return val +} + +// GetContractCompute retrieves the ContractCompute value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u ConfigSettingEntry) GetContractCompute() (result ConfigSettingContractComputeV0, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.ConfigSettingId)) + + if armName == "ContractCompute" { + result = *u.ContractCompute + ok = true + } + + return +} + +// MustContractLedgerCost retrieves the ContractLedgerCost value from the union, +// panicing if the value is not set. +func (u ConfigSettingEntry) MustContractLedgerCost() ConfigSettingContractLedgerCostV0 { + val, ok := u.GetContractLedgerCost() + + if !ok { + panic("arm ContractLedgerCost is not set") + } + + return val +} + +// GetContractLedgerCost retrieves the ContractLedgerCost value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u ConfigSettingEntry) GetContractLedgerCost() (result ConfigSettingContractLedgerCostV0, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.ConfigSettingId)) + + if armName == "ContractLedgerCost" { + result = *u.ContractLedgerCost + ok = true + } + + return +} + +// MustContractHistoricalData retrieves the ContractHistoricalData value from the union, +// panicing if the value is not set. +func (u ConfigSettingEntry) MustContractHistoricalData() ConfigSettingContractHistoricalDataV0 { + val, ok := u.GetContractHistoricalData() + + if !ok { + panic("arm ContractHistoricalData is not set") + } + + return val +} + +// GetContractHistoricalData retrieves the ContractHistoricalData value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u ConfigSettingEntry) GetContractHistoricalData() (result ConfigSettingContractHistoricalDataV0, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.ConfigSettingId)) + + if armName == "ContractHistoricalData" { + result = *u.ContractHistoricalData + ok = true + } + + return +} + +// MustContractEvents retrieves the ContractEvents value from the union, +// panicing if the value is not set. +func (u ConfigSettingEntry) MustContractEvents() ConfigSettingContractEventsV0 { + val, ok := u.GetContractEvents() + + if !ok { + panic("arm ContractEvents is not set") + } + + return val +} + +// GetContractEvents retrieves the ContractEvents value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u ConfigSettingEntry) GetContractEvents() (result ConfigSettingContractEventsV0, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.ConfigSettingId)) + + if armName == "ContractEvents" { + result = *u.ContractEvents + ok = true + } + + return +} + +// MustContractBandwidth retrieves the ContractBandwidth value from the union, +// panicing if the value is not set. +func (u ConfigSettingEntry) MustContractBandwidth() ConfigSettingContractBandwidthV0 { + val, ok := u.GetContractBandwidth() + + if !ok { + panic("arm ContractBandwidth is not set") + } + + return val +} + +// GetContractBandwidth retrieves the ContractBandwidth value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u ConfigSettingEntry) GetContractBandwidth() (result ConfigSettingContractBandwidthV0, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.ConfigSettingId)) + + if armName == "ContractBandwidth" { + result = *u.ContractBandwidth + ok = true + } + + return +} + +// MustContractCostParamsCpuInsns retrieves the ContractCostParamsCpuInsns value from the union, +// panicing if the value is not set. +func (u ConfigSettingEntry) MustContractCostParamsCpuInsns() ContractCostParams { + val, ok := u.GetContractCostParamsCpuInsns() + + if !ok { + panic("arm ContractCostParamsCpuInsns is not set") + } + + return val +} + +// GetContractCostParamsCpuInsns retrieves the ContractCostParamsCpuInsns value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u ConfigSettingEntry) GetContractCostParamsCpuInsns() (result ContractCostParams, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.ConfigSettingId)) + + if armName == "ContractCostParamsCpuInsns" { + result = *u.ContractCostParamsCpuInsns + ok = true + } + + return +} + +// MustContractCostParamsMemBytes retrieves the ContractCostParamsMemBytes value from the union, +// panicing if the value is not set. +func (u ConfigSettingEntry) MustContractCostParamsMemBytes() ContractCostParams { + val, ok := u.GetContractCostParamsMemBytes() + + if !ok { + panic("arm ContractCostParamsMemBytes is not set") + } + + return val +} + +// GetContractCostParamsMemBytes retrieves the ContractCostParamsMemBytes value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u ConfigSettingEntry) GetContractCostParamsMemBytes() (result ContractCostParams, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.ConfigSettingId)) + + if armName == "ContractCostParamsMemBytes" { + result = *u.ContractCostParamsMemBytes + ok = true + } + + return +} + +// MustContractDataKeySizeBytes retrieves the ContractDataKeySizeBytes value from the union, +// panicing if the value is not set. +func (u ConfigSettingEntry) MustContractDataKeySizeBytes() Uint32 { + val, ok := u.GetContractDataKeySizeBytes() + + if !ok { + panic("arm ContractDataKeySizeBytes is not set") + } + + return val +} + +// GetContractDataKeySizeBytes retrieves the ContractDataKeySizeBytes value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u ConfigSettingEntry) GetContractDataKeySizeBytes() (result Uint32, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.ConfigSettingId)) + + if armName == "ContractDataKeySizeBytes" { + result = *u.ContractDataKeySizeBytes + ok = true + } + + return +} + +// MustContractDataEntrySizeBytes retrieves the ContractDataEntrySizeBytes value from the union, +// panicing if the value is not set. +func (u ConfigSettingEntry) MustContractDataEntrySizeBytes() Uint32 { + val, ok := u.GetContractDataEntrySizeBytes() + + if !ok { + panic("arm ContractDataEntrySizeBytes is not set") + } + + return val +} + +// GetContractDataEntrySizeBytes retrieves the ContractDataEntrySizeBytes value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u ConfigSettingEntry) GetContractDataEntrySizeBytes() (result Uint32, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.ConfigSettingId)) + + if armName == "ContractDataEntrySizeBytes" { + result = *u.ContractDataEntrySizeBytes + ok = true + } + + return +} + +// MustStateArchivalSettings retrieves the StateArchivalSettings value from the union, +// panicing if the value is not set. +func (u ConfigSettingEntry) MustStateArchivalSettings() StateArchivalSettings { + val, ok := u.GetStateArchivalSettings() + + if !ok { + panic("arm StateArchivalSettings is not set") + } + + return val +} + +// GetStateArchivalSettings retrieves the StateArchivalSettings value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u ConfigSettingEntry) GetStateArchivalSettings() (result StateArchivalSettings, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.ConfigSettingId)) + + if armName == "StateArchivalSettings" { + result = *u.StateArchivalSettings + ok = true + } + + return +} + +// MustContractExecutionLanes retrieves the ContractExecutionLanes value from the union, +// panicing if the value is not set. +func (u ConfigSettingEntry) MustContractExecutionLanes() ConfigSettingContractExecutionLanesV0 { + val, ok := u.GetContractExecutionLanes() + + if !ok { + panic("arm ContractExecutionLanes is not set") + } + + return val +} + +// GetContractExecutionLanes retrieves the ContractExecutionLanes value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u ConfigSettingEntry) GetContractExecutionLanes() (result ConfigSettingContractExecutionLanesV0, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.ConfigSettingId)) + + if armName == "ContractExecutionLanes" { + result = *u.ContractExecutionLanes + ok = true + } + + return +} + +// MustBucketListSizeWindow retrieves the BucketListSizeWindow value from the union, +// panicing if the value is not set. +func (u ConfigSettingEntry) MustBucketListSizeWindow() []Uint64 { + val, ok := u.GetBucketListSizeWindow() + + if !ok { + panic("arm BucketListSizeWindow is not set") + } + + return val +} + +// GetBucketListSizeWindow retrieves the BucketListSizeWindow value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u ConfigSettingEntry) GetBucketListSizeWindow() (result []Uint64, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.ConfigSettingId)) + + if armName == "BucketListSizeWindow" { + result = *u.BucketListSizeWindow + ok = true + } + + return +} + +// MustEvictionIterator retrieves the EvictionIterator value from the union, +// panicing if the value is not set. +func (u ConfigSettingEntry) MustEvictionIterator() EvictionIterator { + val, ok := u.GetEvictionIterator() + + if !ok { + panic("arm EvictionIterator is not set") + } + + return val +} + +// GetEvictionIterator retrieves the EvictionIterator value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u ConfigSettingEntry) GetEvictionIterator() (result EvictionIterator, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.ConfigSettingId)) + + if armName == "EvictionIterator" { + result = *u.EvictionIterator ok = true } @@ -38525,47 +56286,240 @@ func (u SerializedLedgerCloseMeta) GetV0() (result LedgerCloseMeta, ok bool) { } // EncodeTo encodes this value using the Encoder. -func (u SerializedLedgerCloseMeta) EncodeTo(e *xdr.Encoder) error { +func (u ConfigSettingEntry) EncodeTo(e *xdr.Encoder) error { var err error - if _, err = e.EncodeInt(int32(u.V)); err != nil { + if err = u.ConfigSettingId.EncodeTo(e); err != nil { return err } - switch int32(u.V) { - case 0: - if err = (*u.V0).EncodeTo(e); err != nil { + switch ConfigSettingId(u.ConfigSettingId) { + case ConfigSettingIdConfigSettingContractMaxSizeBytes: + if err = (*u.ContractMaxSizeBytes).EncodeTo(e); err != nil { + return err + } + return nil + case ConfigSettingIdConfigSettingContractComputeV0: + if err = (*u.ContractCompute).EncodeTo(e); err != nil { + return err + } + return nil + case ConfigSettingIdConfigSettingContractLedgerCostV0: + if err = (*u.ContractLedgerCost).EncodeTo(e); err != nil { + return err + } + return nil + case ConfigSettingIdConfigSettingContractHistoricalDataV0: + if err = (*u.ContractHistoricalData).EncodeTo(e); err != nil { + return err + } + return nil + case ConfigSettingIdConfigSettingContractEventsV0: + if err = (*u.ContractEvents).EncodeTo(e); err != nil { + return err + } + return nil + case ConfigSettingIdConfigSettingContractBandwidthV0: + if err = (*u.ContractBandwidth).EncodeTo(e); err != nil { + return err + } + return nil + case ConfigSettingIdConfigSettingContractCostParamsCpuInstructions: + if err = (*u.ContractCostParamsCpuInsns).EncodeTo(e); err != nil { + return err + } + return nil + case ConfigSettingIdConfigSettingContractCostParamsMemoryBytes: + if err = (*u.ContractCostParamsMemBytes).EncodeTo(e); err != nil { + return err + } + return nil + case ConfigSettingIdConfigSettingContractDataKeySizeBytes: + if err = (*u.ContractDataKeySizeBytes).EncodeTo(e); err != nil { + return err + } + return nil + case ConfigSettingIdConfigSettingContractDataEntrySizeBytes: + if err = (*u.ContractDataEntrySizeBytes).EncodeTo(e); err != nil { + return err + } + return nil + case ConfigSettingIdConfigSettingStateArchival: + if err = (*u.StateArchivalSettings).EncodeTo(e); err != nil { + return err + } + return nil + case ConfigSettingIdConfigSettingContractExecutionLanes: + if err = (*u.ContractExecutionLanes).EncodeTo(e); err != nil { + return err + } + return nil + case ConfigSettingIdConfigSettingBucketlistSizeWindow: + if _, err = e.EncodeUint(uint32(len((*u.BucketListSizeWindow)))); err != nil { + return err + } + for i := 0; i < len((*u.BucketListSizeWindow)); i++ { + if err = (*u.BucketListSizeWindow)[i].EncodeTo(e); err != nil { + return err + } + } + return nil + case ConfigSettingIdConfigSettingEvictionIterator: + if err = (*u.EvictionIterator).EncodeTo(e); err != nil { return err } return nil } - return fmt.Errorf("V (int32) switch value '%d' is not valid for union SerializedLedgerCloseMeta", u.V) + return fmt.Errorf("ConfigSettingId (ConfigSettingId) switch value '%d' is not valid for union ConfigSettingEntry", u.ConfigSettingId) } -var _ decoderFrom = (*SerializedLedgerCloseMeta)(nil) +var _ decoderFrom = (*ConfigSettingEntry)(nil) // DecodeFrom decodes this value using the Decoder. -func (u *SerializedLedgerCloseMeta) DecodeFrom(d *xdr.Decoder) (int, error) { +func (u *ConfigSettingEntry) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding ConfigSettingEntry: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 var err error var n, nTmp int - u.V, nTmp, err = d.DecodeInt() + nTmp, err = u.ConfigSettingId.DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding Int: %s", err) + return n, fmt.Errorf("decoding ConfigSettingId: %w", err) } - switch int32(u.V) { - case 0: - u.V0 = new(LedgerCloseMeta) - nTmp, err = (*u.V0).DecodeFrom(d) + switch ConfigSettingId(u.ConfigSettingId) { + case ConfigSettingIdConfigSettingContractMaxSizeBytes: + u.ContractMaxSizeBytes = new(Uint32) + nTmp, err = (*u.ContractMaxSizeBytes).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Uint32: %w", err) + } + return n, nil + case ConfigSettingIdConfigSettingContractComputeV0: + u.ContractCompute = new(ConfigSettingContractComputeV0) + nTmp, err = (*u.ContractCompute).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ConfigSettingContractComputeV0: %w", err) + } + return n, nil + case ConfigSettingIdConfigSettingContractLedgerCostV0: + u.ContractLedgerCost = new(ConfigSettingContractLedgerCostV0) + nTmp, err = (*u.ContractLedgerCost).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ConfigSettingContractLedgerCostV0: %w", err) + } + return n, nil + case ConfigSettingIdConfigSettingContractHistoricalDataV0: + u.ContractHistoricalData = new(ConfigSettingContractHistoricalDataV0) + nTmp, err = (*u.ContractHistoricalData).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ConfigSettingContractHistoricalDataV0: %w", err) + } + return n, nil + case ConfigSettingIdConfigSettingContractEventsV0: + u.ContractEvents = new(ConfigSettingContractEventsV0) + nTmp, err = (*u.ContractEvents).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ConfigSettingContractEventsV0: %w", err) + } + return n, nil + case ConfigSettingIdConfigSettingContractBandwidthV0: + u.ContractBandwidth = new(ConfigSettingContractBandwidthV0) + nTmp, err = (*u.ContractBandwidth).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ConfigSettingContractBandwidthV0: %w", err) + } + return n, nil + case ConfigSettingIdConfigSettingContractCostParamsCpuInstructions: + u.ContractCostParamsCpuInsns = new(ContractCostParams) + nTmp, err = (*u.ContractCostParamsCpuInsns).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ContractCostParams: %w", err) + } + return n, nil + case ConfigSettingIdConfigSettingContractCostParamsMemoryBytes: + u.ContractCostParamsMemBytes = new(ContractCostParams) + nTmp, err = (*u.ContractCostParamsMemBytes).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ContractCostParams: %w", err) + } + return n, nil + case ConfigSettingIdConfigSettingContractDataKeySizeBytes: + u.ContractDataKeySizeBytes = new(Uint32) + nTmp, err = (*u.ContractDataKeySizeBytes).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Uint32: %w", err) + } + return n, nil + case ConfigSettingIdConfigSettingContractDataEntrySizeBytes: + u.ContractDataEntrySizeBytes = new(Uint32) + nTmp, err = (*u.ContractDataEntrySizeBytes).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Uint32: %w", err) + } + return n, nil + case ConfigSettingIdConfigSettingStateArchival: + u.StateArchivalSettings = new(StateArchivalSettings) + nTmp, err = (*u.StateArchivalSettings).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding StateArchivalSettings: %w", err) + } + return n, nil + case ConfigSettingIdConfigSettingContractExecutionLanes: + u.ContractExecutionLanes = new(ConfigSettingContractExecutionLanesV0) + nTmp, err = (*u.ContractExecutionLanes).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ConfigSettingContractExecutionLanesV0: %w", err) + } + return n, nil + case ConfigSettingIdConfigSettingBucketlistSizeWindow: + u.BucketListSizeWindow = new([]Uint64) + var l uint32 + l, nTmp, err = d.DecodeUint() + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Uint64: %w", err) + } + (*u.BucketListSizeWindow) = nil + if l > 0 { + if il, ok := d.InputLen(); ok && uint(il) < uint(l) { + return n, fmt.Errorf("decoding Uint64: length (%d) exceeds remaining input length (%d)", l, il) + } + (*u.BucketListSizeWindow) = make([]Uint64, l) + for i := uint32(0); i < l; i++ { + nTmp, err = (*u.BucketListSizeWindow)[i].DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Uint64: %w", err) + } + } + } + return n, nil + case ConfigSettingIdConfigSettingEvictionIterator: + u.EvictionIterator = new(EvictionIterator) + nTmp, err = (*u.EvictionIterator).DecodeFrom(d, maxDepth) n += nTmp if err != nil { - return n, fmt.Errorf("decoding LedgerCloseMeta: %s", err) + return n, fmt.Errorf("decoding EvictionIterator: %w", err) } return n, nil } - return n, fmt.Errorf("union SerializedLedgerCloseMeta has invalid V (int32) switch value '%d'", u.V) + return n, fmt.Errorf("union ConfigSettingEntry has invalid ConfigSettingId (ConfigSettingId) switch value '%d'", u.ConfigSettingId) } // MarshalBinary implements encoding.BinaryMarshaler. -func (s SerializedLedgerCloseMeta) MarshalBinary() ([]byte, error) { +func (s ConfigSettingEntry) MarshalBinary() ([]byte, error) { b := bytes.Buffer{} e := xdr.NewEncoder(&b) err := s.EncodeTo(e) @@ -38573,22 +56527,23 @@ func (s SerializedLedgerCloseMeta) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *SerializedLedgerCloseMeta) UnmarshalBinary(inp []byte) error { +func (s *ConfigSettingEntry) UnmarshalBinary(inp []byte) error { r := bytes.NewReader(inp) - d := xdr.NewDecoder(r) - _, err := s.DecodeFrom(d) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) return err } var ( - _ encoding.BinaryMarshaler = (*SerializedLedgerCloseMeta)(nil) - _ encoding.BinaryUnmarshaler = (*SerializedLedgerCloseMeta)(nil) + _ encoding.BinaryMarshaler = (*ConfigSettingEntry)(nil) + _ encoding.BinaryUnmarshaler = (*ConfigSettingEntry)(nil) ) -// xdrType signals that this type is an type representing -// representing XDR values defined by this package. -func (s SerializedLedgerCloseMeta) xdrType() {} +// xdrType signals that this type represents XDR values defined by this package. +func (s ConfigSettingEntry) xdrType() {} -var _ xdrType = (*SerializedLedgerCloseMeta)(nil) +var _ xdrType = (*ConfigSettingEntry)(nil) var fmtTest = fmt.Sprint("this is a dummy usage of fmt")