diff --git a/.circleci/config.yml b/.circleci/config.yml index 9315461f8..88635ab2c 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -328,56 +328,6 @@ jobs: - run: ./scripts/generate-checksums.sh - run: ./scripts/publish-checksums.sh - build-appimage: - machine: - image: ubuntu-2004:202111-02 - steps: - - checkout - - attach_workspace: - at: /tmp/workspace - - run: - name: Update Go - command: | - sudo rm -rf /usr/local/go && \ - curl -L https://golang.org/dl/go`cat GO_VERSION_MIN`.linux-amd64.tar.gz -o /tmp/go.tar.gz && \ - sudo tar -C /usr/local -xvf /tmp/go.tar.gz - - run: go version - - run: - name: install appimage-builder - command: | - # appimage-builder requires /dev/snd to exist. It creates containers during the testing phase - # that pass sound devices from the host to the testing container. (hard coded!) - # https://github.com/AppImageCrafters/appimage-builder/blob/master/appimagebuilder/modules/test/execution_test.py#L54 - # Circleci doesn't provide a working sound device; this is enough to fake it. - if [ ! -e /dev/snd ] - then - sudo mkdir /dev/snd - sudo mknod /dev/snd/ControlC0 c 1 2 - fi - - # docs: https://appimage-builder.readthedocs.io/en/latest/intro/install.html - sudo apt update - sudo apt install -y python3-pip python3-setuptools patchelf desktop-file-utils libgdk-pixbuf2.0-dev fakeroot strace - sudo curl -Lo /usr/local/bin/appimagetool https://github.com/AppImage/AppImageKit/releases/download/continuous/appimagetool-x86_64.AppImage - sudo chmod +x /usr/local/bin/appimagetool - sudo pip3 install appimage-builder - - run: - name: install lotus dependencies - command: sudo apt install ocl-icd-opencl-dev libhwloc-dev - - run: - name: build appimage - command: | - sed -i "s/version: latest/version: ${CIRCLE_TAG:-latest}/" AppImageBuilder.yml - make appimage - - run: | - mkdir -p /tmp/workspace/appimage && \ - mv Lotus-*.AppImage /tmp/workspace/appimage/ - - persist_to_workspace: - root: /tmp/workspace - paths: - - appimage - - gofmt: executor: golang steps: @@ -444,72 +394,6 @@ jobs: lint-all: <<: *lint - publish: - description: publish binary artifacts - executor: ubuntu - parameters: - linux: - default: false - description: publish linux binaries? - type: boolean - appimage: - default: false - description: publish appimage binaries? - type: boolean - steps: - - run: - name: Install git jq curl - command: apt update && apt install -y git jq curl sudo - - checkout - - git_fetch_all_tags - - checkout - - install_ipfs - - attach_workspace: - at: /tmp/workspace - - when: - condition: << parameters.linux >> - steps: - - run: ./scripts/build-arch-bundle.sh linux - - run: ./scripts/publish-arch-release.sh linux - - when: - condition: << parameters.appimage >> - steps: - - run: ./scripts/build-appimage-bundle.sh - - run: ./scripts/publish-arch-release.sh appimage - - publish-snapcraft: - description: build and push snapcraft - machine: - image: ubuntu-2004:202104-01 - resource_class: 2xlarge - parameters: - channel: - type: string - default: "edge" - description: snapcraft channel - snap-name: - type: string - default: 'lotus-filecoin' - description: name of snap in snap store - steps: - - checkout - - run: - name: Install snapcraft - command: sudo snap install snapcraft --classic - - run: - name: Build << parameters.snap-name >> snap - command: | - if [ "<< parameters.snap-name >>" != 'lotus-filecoin' ]; then - cat snap/snapcraft.yaml | sed 's/lotus-filecoin/lotus/' > edited-snapcraft.yaml - mv edited-snapcraft.yaml snap/snapcraft.yaml - fi - - snapcraft --use-lxd --debug - - run: - name: Publish snap to << parameters.channel >> channel - shell: /bin/bash -o pipefail - command: | - snapcraft upload *.snap --release << parameters.channel >> build-docker: description: > Publish to Dockerhub @@ -542,6 +426,10 @@ jobs: steps: - setup_remote_docker - checkout + - git_fetch_all_tags + - run: git submodule sync + - run: git submodule update --init + - docker/check: docker-username: DOCKERHUB_USERNAME docker-password: DOCKERHUB_PASSWORD @@ -550,7 +438,7 @@ jobs: equal: [ mainnet, <> ] steps: - when: - condition: > + condition: <> steps: - docker/build: image: filecoin/<> @@ -561,7 +449,7 @@ jobs: command: | docker push filecoin/<>:<> if [[ ! -z $CIRCLE_SHA ]]; then - docker image tag filecoin/<>:<>> filecoin/<>:"${CIRCLE_SHA:0:7}" + docker image tag filecoin/<>:<> filecoin/<>:"${CIRCLE_SHA:0:7}" docker push filecoin/<>:"${CIRCLE_SHA:0:7}" fi if [[ ! -z $CIRCLE_TAG ]]; then @@ -715,6 +603,11 @@ workflows: suite: itest-deals target: "./itests/deals_test.go" + - test: + name: test-itest-decode_params + suite: itest-decode_params + target: "./itests/decode_params_test.go" + - test: name: test-itest-dup_mpool_messages suite: itest-dup_mpool_messages @@ -735,6 +628,16 @@ workflows: suite: itest-eth_block_hash target: "./itests/eth_block_hash_test.go" + - test: + name: test-itest-eth_config + suite: itest-eth_config + target: "./itests/eth_config_test.go" + + - test: + name: test-itest-eth_conformance + suite: itest-eth_conformance + target: "./itests/eth_conformance_test.go" + - test: name: test-itest-eth_deploy suite: itest-eth_deploy @@ -1009,11 +912,6 @@ workflows: - test-conformance: suite: conformance target: "./conformance" - - test-conformance: - name: test-conformance-bleeding-edge - suite: conformance-bleeding-edge - target: "./conformance" - vectors-branch: specs-actors-v7 release: jobs: @@ -1068,71 +966,6 @@ workflows: branches: only: - /^release\/v\d+\.\d+\.\d+(-rc\d+)?$/ - - build-appimage: - name: "Build AppImage" - filters: - branches: - only: - - /^release\/v\d+\.\d+\.\d+(-rc\d+)?$/ - tags: - only: - - /^v\d+\.\d+\.\d+(-rc\d+)?$/ - - publish: - name: "Publish AppImage" - appimage: true - requires: - - "Build AppImage" - filters: - branches: - ignore: - - /.*/ - tags: - only: - - /^v\d+\.\d+\.\d+(-rc\d+)?$/ - - publish-snapcraft: - name: "Publish Snapcraft (lotus / stable)" - channel: stable - snap-name: lotus - filters: - branches: - ignore: - - /.*/ - tags: - only: - - /^v\d+\.\d+\.\d+$/ - - publish-snapcraft: - name: "Publish Snapcraft (lotus / candidate)" - channel: candidate - snap-name: lotus - filters: - branches: - ignore: - - /.*/ - tags: - only: - - /^v\d+\.\d+\.\d+-rc\d+$/ - - publish-snapcraft: - name: "Publish Snapcraft (lotus-filecoin / stable)" - channel: stable - snap-name: lotus-filecoin - filters: - branches: - ignore: - - /.*/ - tags: - only: - - /^v\d+\.\d+\.\d+$/ - - publish-snapcraft: - name: "Publish Snapcraft (lotus-filecoin / candidate)" - channel: candidate - snap-name: lotus-filecoin - filters: - branches: - ignore: - - /.*/ - tags: - only: - - /^v\d+\.\d+\.\d+-rc\d+$/ - build-docker: name: "Docker push (lotus-all-in-one / stable / mainnet)" image: lotus-all-in-one @@ -1368,14 +1201,6 @@ workflows: only: - master jobs: - - publish-snapcraft: - name: "Publish Snapcraft (lotus / edge)" - channel: edge - snap-name: lotus - - publish-snapcraft: - name: "Publish Snapcraft (lotus-filecoin / edge)" - channel: edge - snap-name: lotus-filecoin - build-docker: name: "Docker (lotus-all-in-one / nightly / mainnet)" image: lotus-all-in-one diff --git a/.circleci/gen.go b/.circleci/gen.go index 6cc9cedb1..5d951027a 100644 --- a/.circleci/gen.go +++ b/.circleci/gen.go @@ -107,13 +107,11 @@ func main() { // form the input data. type data struct { Networks []string - SnapNames []string ItestFiles []string UnitSuites map[string]string } in := data{ Networks: []string{"mainnet", "butterflynet", "calibnet", "debug"}, - SnapNames: []string{"lotus", "lotus-filecoin"}, ItestFiles: itests, UnitSuites: func() map[string]string { ret := make(map[string]string) diff --git a/.circleci/template.yml b/.circleci/template.yml index 6906f13f4..724571ac2 100644 --- a/.circleci/template.yml +++ b/.circleci/template.yml @@ -328,56 +328,6 @@ jobs: - run: ./scripts/generate-checksums.sh - run: ./scripts/publish-checksums.sh - build-appimage: - machine: - image: ubuntu-2004:202111-02 - steps: - - checkout - - attach_workspace: - at: /tmp/workspace - - run: - name: Update Go - command: | - sudo rm -rf /usr/local/go && \ - curl -L https://golang.org/dl/go`cat GO_VERSION_MIN`.linux-amd64.tar.gz -o /tmp/go.tar.gz && \ - sudo tar -C /usr/local -xvf /tmp/go.tar.gz - - run: go version - - run: - name: install appimage-builder - command: | - # appimage-builder requires /dev/snd to exist. It creates containers during the testing phase - # that pass sound devices from the host to the testing container. (hard coded!) - # https://github.com/AppImageCrafters/appimage-builder/blob/master/appimagebuilder/modules/test/execution_test.py#L54 - # Circleci doesn't provide a working sound device; this is enough to fake it. - if [ ! -e /dev/snd ] - then - sudo mkdir /dev/snd - sudo mknod /dev/snd/ControlC0 c 1 2 - fi - - # docs: https://appimage-builder.readthedocs.io/en/latest/intro/install.html - sudo apt update - sudo apt install -y python3-pip python3-setuptools patchelf desktop-file-utils libgdk-pixbuf2.0-dev fakeroot strace - sudo curl -Lo /usr/local/bin/appimagetool https://github.com/AppImage/AppImageKit/releases/download/continuous/appimagetool-x86_64.AppImage - sudo chmod +x /usr/local/bin/appimagetool - sudo pip3 install appimage-builder - - run: - name: install lotus dependencies - command: sudo apt install ocl-icd-opencl-dev libhwloc-dev - - run: - name: build appimage - command: | - sed -i "s/version: latest/version: ${CIRCLE_TAG:-latest}/" AppImageBuilder.yml - make appimage - - run: | - mkdir -p /tmp/workspace/appimage && \ - mv Lotus-*.AppImage /tmp/workspace/appimage/ - - persist_to_workspace: - root: /tmp/workspace - paths: - - appimage - - gofmt: executor: golang steps: @@ -444,72 +394,6 @@ jobs: lint-all: <<: *lint - publish: - description: publish binary artifacts - executor: ubuntu - parameters: - linux: - default: false - description: publish linux binaries? - type: boolean - appimage: - default: false - description: publish appimage binaries? - type: boolean - steps: - - run: - name: Install git jq curl - command: apt update && apt install -y git jq curl sudo - - checkout - - git_fetch_all_tags - - checkout - - install_ipfs - - attach_workspace: - at: /tmp/workspace - - when: - condition: << parameters.linux >> - steps: - - run: ./scripts/build-arch-bundle.sh linux - - run: ./scripts/publish-arch-release.sh linux - - when: - condition: << parameters.appimage >> - steps: - - run: ./scripts/build-appimage-bundle.sh - - run: ./scripts/publish-arch-release.sh appimage - - publish-snapcraft: - description: build and push snapcraft - machine: - image: ubuntu-2004:202104-01 - resource_class: 2xlarge - parameters: - channel: - type: string - default: "edge" - description: snapcraft channel - snap-name: - type: string - default: 'lotus-filecoin' - description: name of snap in snap store - steps: - - checkout - - run: - name: Install snapcraft - command: sudo snap install snapcraft --classic - - run: - name: Build << parameters.snap-name >> snap - command: | - if [ "<< parameters.snap-name >>" != 'lotus-filecoin' ]; then - cat snap/snapcraft.yaml | sed 's/lotus-filecoin/lotus/' > edited-snapcraft.yaml - mv edited-snapcraft.yaml snap/snapcraft.yaml - fi - - snapcraft --use-lxd --debug - - run: - name: Publish snap to << parameters.channel >> channel - shell: /bin/bash -o pipefail - command: | - snapcraft upload *.snap --release << parameters.channel >> build-docker: description: > Publish to Dockerhub @@ -542,6 +426,10 @@ jobs: steps: - setup_remote_docker - checkout + - git_fetch_all_tags + - run: git submodule sync + - run: git submodule update --init + - docker/check: docker-username: DOCKERHUB_USERNAME docker-password: DOCKERHUB_PASSWORD @@ -550,7 +438,7 @@ jobs: equal: [ mainnet, <> ] steps: - when: - condition: > + condition: <> steps: - docker/build: image: filecoin/<> @@ -561,7 +449,7 @@ jobs: command: | docker push filecoin/<>:<> if [["[[ ! -z $CIRCLE_SHA ]]"]]; then - docker image tag filecoin/<>:<>> filecoin/<>:"${CIRCLE_SHA:0:7}" + docker image tag filecoin/<>:<> filecoin/<>:"${CIRCLE_SHA:0:7}" docker push filecoin/<>:"${CIRCLE_SHA:0:7}" fi if [["[[ ! -z $CIRCLE_TAG ]]"]]; then @@ -639,11 +527,6 @@ workflows: - test-conformance: suite: conformance target: "./conformance" - - test-conformance: - name: test-conformance-bleeding-edge - suite: conformance-bleeding-edge - target: "./conformance" - vectors-branch: specs-actors-v7 release: jobs: @@ -698,51 +581,6 @@ workflows: branches: only: - /^release\/v\d+\.\d+\.\d+(-rc\d+)?$/ - - build-appimage: - name: "Build AppImage" - filters: - branches: - only: - - /^release\/v\d+\.\d+\.\d+(-rc\d+)?$/ - tags: - only: - - /^v\d+\.\d+\.\d+(-rc\d+)?$/ - - publish: - name: "Publish AppImage" - appimage: true - requires: - - "Build AppImage" - filters: - branches: - ignore: - - /.*/ - tags: - only: - - /^v\d+\.\d+\.\d+(-rc\d+)?$/ - [[- range .SnapNames]] - - publish-snapcraft: - name: "Publish Snapcraft ([[.]] / stable)" - channel: stable - snap-name: [[.]] - filters: - branches: - ignore: - - /.*/ - tags: - only: - - /^v\d+\.\d+\.\d+$/ - - publish-snapcraft: - name: "Publish Snapcraft ([[.]] / candidate)" - channel: candidate - snap-name: [[.]] - filters: - branches: - ignore: - - /.*/ - tags: - only: - - /^v\d+\.\d+\.\d+-rc\d+$/ - [[- end]] [[- range .Networks]] - build-docker: name: "Docker push (lotus-all-in-one / stable / [[.]])" @@ -845,12 +683,6 @@ workflows: only: - master jobs: - [[- range .SnapNames]] - - publish-snapcraft: - name: "Publish Snapcraft ([[.]] / edge)" - channel: edge - snap-name: [[.]] - [[- end]] [[- range .Networks]] - build-docker: name: "Docker (lotus-all-in-one / nightly / [[.]])" diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 65d5fd93a..0cba5457e 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -13,10 +13,14 @@ name: "CodeQL" on: push: - branches: [ master ] + branches: + - master + - 'release/*' pull_request: # The branches below must be a subset of the branches above - branches: [ master ] + branches: + - master + - 'release/*' jobs: analyze: @@ -33,17 +37,17 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v2 + uses: actions/checkout@v3 - - uses: actions/setup-go@v1 + - uses: actions/setup-go@v3 with: go-version: '1.18.8' # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@v1 + uses: github/codeql-action/init@v2 with: - languages: ${{ matrix.language }} + languages: go # If you wish to specify custom queries, you can do so here or in a config file. # By default, queries listed here will override any specified in a config file. # Prefix the list here with "+" to use these queries and those in the config file. @@ -52,7 +56,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@v1 + uses: github/codeql-action/autobuild@v2 # ℹī¸ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -66,4 +70,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v1 + uses: github/codeql-action/analyze@v2 diff --git a/.gitignore b/.gitignore index 5ff2726f2..2e9dcd0ff 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,3 @@ -/AppDir -/appimage-builder-cache -*.AppImage /lotus /lotus-miner /lotus-worker @@ -50,3 +47,8 @@ build/builtin-actors/v* build/builtin-actors/*.car dist/ + + +# The following files are checked into git and result +# in dirty git state if removed from the docker context +!extern/filecoin-ffi/rust/filecoin.pc diff --git a/AppDir/usr/share/icons/icon.svg b/AppDir/usr/share/icons/icon.svg deleted file mode 100644 index da992296a..000000000 --- a/AppDir/usr/share/icons/icon.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/AppImageBuilder.yml b/AppImageBuilder.yml deleted file mode 100644 index 4f1f56bbb..000000000 --- a/AppImageBuilder.yml +++ /dev/null @@ -1,71 +0,0 @@ -version: 1 -AppDir: - path: ./AppDir - app_info: - id: io.filecoin.lotus - name: Lotus - icon: icon - version: latest - exec: usr/bin/lotus - exec_args: $@ - apt: - arch: amd64 - allow_unauthenticated: true - sources: - - sourceline: deb http://archive.ubuntu.com/ubuntu/ focal main restricted - - sourceline: deb http://archive.ubuntu.com/ubuntu/ focal-updates main restricted - - sourceline: deb http://archive.ubuntu.com/ubuntu/ focal universe - - sourceline: deb http://archive.ubuntu.com/ubuntu/ focal-updates universe - - sourceline: deb http://archive.ubuntu.com/ubuntu/ focal multiverse - - sourceline: deb http://archive.ubuntu.com/ubuntu/ focal-updates multiverse - - sourceline: deb http://archive.ubuntu.com/ubuntu/ focal-backports main restricted - universe multiverse - - sourceline: deb http://security.ubuntu.com/ubuntu focal-security main restricted - - sourceline: deb http://security.ubuntu.com/ubuntu focal-security universe - - sourceline: deb http://security.ubuntu.com/ubuntu focal-security multiverse - - sourceline: deb https://cli-assets.heroku.com/apt ./ - - sourceline: deb http://ppa.launchpad.net/openjdk-r/ppa/ubuntu focal main - - sourceline: deb http://ppa.launchpad.net/git-core/ppa/ubuntu focal main - - sourceline: deb http://archive.canonical.com/ubuntu focal partner - include: - - ocl-icd-libopencl1 - - libhwloc15 - exclude: [] - files: - include: - - /usr/lib/x86_64-linux-gnu/libgcc_s.so.1 - - /usr/lib/x86_64-linux-gnu/libpthread-2.31.so - - /usr/lib/x86_64-linux-gnu/libm-2.31.so - - /usr/lib/x86_64-linux-gnu/libdl-2.31.so - - /usr/lib/x86_64-linux-gnu/libc-2.31.so - - /usr/lib/x86_64-linux-gnu/libudev.so.1.6.17 - exclude: - - usr/share/man - - usr/share/doc/*/README.* - - usr/share/doc/*/changelog.* - - usr/share/doc/*/NEWS.* - - usr/share/doc/*/TODO.* - test: - fedora: - image: appimagecrafters/tests-env:fedora-30 - command: ./AppRun - use_host_x: false - debian: - image: appimagecrafters/tests-env:debian-stable - command: ./AppRun - use_host_x: false - arch: - image: appimagecrafters/tests-env:archlinux-latest - command: ./AppRun - use_host_x: false - centos: - image: appimagecrafters/tests-env:centos-7 - command: ./AppRun - use_host_x: false - ubuntu: - image: appimagecrafters/tests-env:ubuntu-xenial - command: ./AppRun - use_host_x: false -AppImage: - arch: x86_64 - diff --git a/Dockerfile b/Dockerfile index 5c147e930..81089517b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -33,6 +33,8 @@ RUN set -eux; \ COPY ./ /opt/filecoin WORKDIR /opt/filecoin +RUN scripts/docker-git-state-check.sh + ### make configurable filecoin-ffi build ARG FFI_BUILD_FROM_SOURCE=0 ENV FFI_BUILD_FROM_SOURCE=${FFI_BUILD_FROM_SOURCE} diff --git a/Makefile b/Makefile index c085faafb..023ca61f5 100644 --- a/Makefile +++ b/Makefile @@ -84,12 +84,6 @@ butterflynet: build-devnets interopnet: GOFLAGS+=-tags=interopnet interopnet: build-devnets -wallabynet: GOFLAGS+=-tags=wallabynet -wallabynet: build-devnets - -hyperspacenet: GOFLAGS+=-tags=hyperspacenet -hyperspacenet: build-devnets - lotus: $(BUILD_DEPS) rm -f lotus $(GOCC) build $(GOFLAGS) -o lotus ./cmd/lotus @@ -304,7 +298,7 @@ actors-gen: actors-code-gen fiximports .PHONY: actors-gen bundle-gen: - $(GOCC) run ./gen/bundle + $(GOCC) run ./gen/bundle $(RELEASE) $(GOCC) fmt ./build/... .PHONY: bundle-gen @@ -360,7 +354,7 @@ docsgen-openrpc-gateway: docsgen-openrpc-bin fiximports: ./scripts/fiximports -gen: actors-code-gen type-gen cfgdoc-gen docsgen api-gen circleci bundle-gen fiximports +gen: actors-code-gen type-gen cfgdoc-gen docsgen api-gen circleci fiximports @echo ">>> IF YOU'VE MODIFIED THE CLI OR CONFIG, REMEMBER TO ALSO MAKE docsgen-cli" .PHONY: gen diff --git a/api/api_full.go b/api/api_full.go index b17fad3b5..20870adce 100644 --- a/api/api_full.go +++ b/api/api_full.go @@ -16,6 +16,7 @@ import ( datatransfer "github.com/filecoin-project/go-data-transfer" "github.com/filecoin-project/go-fil-markets/retrievalmarket" "github.com/filecoin-project/go-fil-markets/storagemarket" + "github.com/filecoin-project/go-jsonrpc" "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/big" "github.com/filecoin-project/go-state-types/builtin/v8/paych" @@ -831,11 +832,14 @@ type FullNode interface { // - logs: notify new event logs that match a criteria // params contains additional parameters used with the log event type // The client will receive a stream of EthSubscriptionResponse values until EthUnsubscribe is called. - EthSubscribe(ctx context.Context, eventType string, params *ethtypes.EthSubscriptionParams) (<-chan ethtypes.EthSubscriptionResponse, error) //perm:write + EthSubscribe(ctx context.Context, params jsonrpc.RawParams) (ethtypes.EthSubscriptionID, error) //perm:write // Unsubscribe from a websocket subscription EthUnsubscribe(ctx context.Context, id ethtypes.EthSubscriptionID) (bool, error) //perm:write + // Returns the client version + Web3ClientVersion(ctx context.Context) (string, error) //perm:read + // CreateBackup creates node backup onder the specified file name. The // method requires that the lotus daemon is running with the // LOTUS_BACKUP_BASE_PATH environment variable set to some path, and that @@ -846,6 +850,12 @@ type FullNode interface { RaftLeader(ctx context.Context) (peer.ID, error) //perm:read } +// reverse interface to the client, called after EthSubscribe +type EthSubscriber interface { + // note: the parameter is ethtypes.EthSubscriptionResponse serialized as json object + EthSubscription(ctx context.Context, r jsonrpc.RawParams) error // rpc_method:eth_subscription notify:true +} + type StorageAsk struct { Response *storagemarket.StorageAsk diff --git a/api/api_gateway.go b/api/api_gateway.go index c78710026..1f7cce8e3 100644 --- a/api/api_gateway.go +++ b/api/api_gateway.go @@ -7,6 +7,7 @@ import ( "github.com/ipfs/go-cid" "github.com/filecoin-project/go-address" + "github.com/filecoin-project/go-jsonrpc" "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/builtin/v9/miner" "github.com/filecoin-project/go-state-types/dline" @@ -78,6 +79,8 @@ type Gateway interface { EthGetBlockByHash(ctx context.Context, blkHash ethtypes.EthHash, fullTxInfo bool) (ethtypes.EthBlock, error) EthGetBlockByNumber(ctx context.Context, blkNum string, fullTxInfo bool) (ethtypes.EthBlock, error) EthGetTransactionByHash(ctx context.Context, txHash *ethtypes.EthHash) (*ethtypes.EthTx, error) + EthGetTransactionHashByCid(ctx context.Context, cid cid.Cid) (*ethtypes.EthHash, error) + EthGetMessageCidByTransactionHash(ctx context.Context, txHash *ethtypes.EthHash) (*cid.Cid, error) EthGetTransactionCount(ctx context.Context, sender ethtypes.EthAddress, blkOpt string) (ethtypes.EthUint64, error) EthGetTransactionReceipt(ctx context.Context, txHash ethtypes.EthHash) (*EthTxReceipt, error) EthGetTransactionByBlockHashAndIndex(ctx context.Context, blkHash ethtypes.EthHash, txIndex ethtypes.EthUint64) (ethtypes.EthTx, error) @@ -102,6 +105,7 @@ type Gateway interface { EthNewBlockFilter(ctx context.Context) (ethtypes.EthFilterID, error) EthNewPendingTransactionFilter(ctx context.Context) (ethtypes.EthFilterID, error) EthUninstallFilter(ctx context.Context, id ethtypes.EthFilterID) (bool, error) - EthSubscribe(ctx context.Context, eventType string, params *ethtypes.EthSubscriptionParams) (<-chan ethtypes.EthSubscriptionResponse, error) + EthSubscribe(ctx context.Context, params jsonrpc.RawParams) (ethtypes.EthSubscriptionID, error) EthUnsubscribe(ctx context.Context, id ethtypes.EthSubscriptionID) (bool, error) + Web3ClientVersion(ctx context.Context) (string, error) } diff --git a/api/client/client.go b/api/client/client.go index 32583097e..8b159c5b1 100644 --- a/api/client/client.go +++ b/api/client/client.go @@ -35,10 +35,10 @@ func NewFullNodeRPCV0(ctx context.Context, addr string, requestHeader http.Heade } // NewFullNodeRPCV1 creates a new http jsonrpc client. -func NewFullNodeRPCV1(ctx context.Context, addr string, requestHeader http.Header) (api.FullNode, jsonrpc.ClientCloser, error) { +func NewFullNodeRPCV1(ctx context.Context, addr string, requestHeader http.Header, opts ...jsonrpc.Option) (api.FullNode, jsonrpc.ClientCloser, error) { var res v1api.FullNodeStruct closer, err := jsonrpc.NewMergeClient(ctx, addr, "Filecoin", - api.GetInternalStructs(&res), requestHeader, jsonrpc.WithErrors(api.RPCErrors)) + api.GetInternalStructs(&res), requestHeader, append([]jsonrpc.Option{jsonrpc.WithErrors(api.RPCErrors)}, opts...)...) return &res, closer, err } diff --git a/api/eth_aliases.go b/api/eth_aliases.go index cf69bfff7..ccf0317d9 100644 --- a/api/eth_aliases.go +++ b/api/eth_aliases.go @@ -41,4 +41,6 @@ func CreateEthRPCAliases(as apitypes.Aliaser) { as.AliasMethod("net_version", "Filecoin.NetVersion") as.AliasMethod("net_listening", "Filecoin.NetListening") + + as.AliasMethod("web3_clientVersion", "Filecoin.Web3ClientVersion") } diff --git a/api/mocks/mock_full.go b/api/mocks/mock_full.go index b32fc7d8b..c944e2de1 100644 --- a/api/mocks/mock_full.go +++ b/api/mocks/mock_full.go @@ -23,6 +23,7 @@ import ( bitfield "github.com/filecoin-project/go-bitfield" datatransfer "github.com/filecoin-project/go-data-transfer" retrievalmarket "github.com/filecoin-project/go-fil-markets/retrievalmarket" + jsonrpc "github.com/filecoin-project/go-jsonrpc" auth "github.com/filecoin-project/go-jsonrpc/auth" abi "github.com/filecoin-project/go-state-types/abi" big "github.com/filecoin-project/go-state-types/big" @@ -1388,18 +1389,18 @@ func (mr *MockFullNodeMockRecorder) EthSendRawTransaction(arg0, arg1 interface{} } // EthSubscribe mocks base method. -func (m *MockFullNode) EthSubscribe(arg0 context.Context, arg1 string, arg2 *ethtypes.EthSubscriptionParams) (<-chan ethtypes.EthSubscriptionResponse, error) { +func (m *MockFullNode) EthSubscribe(arg0 context.Context, arg1 jsonrpc.RawParams) (ethtypes.EthSubscriptionID, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "EthSubscribe", arg0, arg1, arg2) - ret0, _ := ret[0].(<-chan ethtypes.EthSubscriptionResponse) + ret := m.ctrl.Call(m, "EthSubscribe", arg0, arg1) + ret0, _ := ret[0].(ethtypes.EthSubscriptionID) ret1, _ := ret[1].(error) return ret0, ret1 } // EthSubscribe indicates an expected call of EthSubscribe. -func (mr *MockFullNodeMockRecorder) EthSubscribe(arg0, arg1, arg2 interface{}) *gomock.Call { +func (mr *MockFullNodeMockRecorder) EthSubscribe(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EthSubscribe", reflect.TypeOf((*MockFullNode)(nil).EthSubscribe), arg0, arg1, arg2) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EthSubscribe", reflect.TypeOf((*MockFullNode)(nil).EthSubscribe), arg0, arg1) } // EthUninstallFilter mocks base method. @@ -4096,3 +4097,18 @@ func (mr *MockFullNodeMockRecorder) WalletVerify(arg0, arg1, arg2, arg3 interfac mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "WalletVerify", reflect.TypeOf((*MockFullNode)(nil).WalletVerify), arg0, arg1, arg2, arg3) } + +// Web3ClientVersion mocks base method. +func (m *MockFullNode) Web3ClientVersion(arg0 context.Context) (string, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Web3ClientVersion", arg0) + ret0, _ := ret[0].(string) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Web3ClientVersion indicates an expected call of Web3ClientVersion. +func (mr *MockFullNodeMockRecorder) Web3ClientVersion(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Web3ClientVersion", reflect.TypeOf((*MockFullNode)(nil).Web3ClientVersion), arg0) +} diff --git a/api/proxy_gen.go b/api/proxy_gen.go index aaa1d87c7..794456eae 100644 --- a/api/proxy_gen.go +++ b/api/proxy_gen.go @@ -22,6 +22,7 @@ import ( "github.com/filecoin-project/go-fil-markets/piecestore" "github.com/filecoin-project/go-fil-markets/retrievalmarket" "github.com/filecoin-project/go-fil-markets/storagemarket" + "github.com/filecoin-project/go-jsonrpc" "github.com/filecoin-project/go-jsonrpc/auth" "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/builtin/v8/paych" @@ -49,42 +50,46 @@ import ( var ErrNotSupported = xerrors.New("method not supported") type ChainIOStruct struct { - Internal struct { - ChainHasObj func(p0 context.Context, p1 cid.Cid) (bool, error) `` + Internal ChainIOMethods +} - ChainPutObj func(p0 context.Context, p1 blocks.Block) error `` +type ChainIOMethods struct { + ChainHasObj func(p0 context.Context, p1 cid.Cid) (bool, error) `` - ChainReadObj func(p0 context.Context, p1 cid.Cid) ([]byte, error) `` - } + ChainPutObj func(p0 context.Context, p1 blocks.Block) error `` + + ChainReadObj func(p0 context.Context, p1 cid.Cid) ([]byte, error) `` } type ChainIOStub struct { } type CommonStruct struct { - Internal struct { - AuthNew func(p0 context.Context, p1 []auth.Permission) ([]byte, error) `perm:"admin"` + Internal CommonMethods +} - AuthVerify func(p0 context.Context, p1 string) ([]auth.Permission, error) `perm:"read"` +type CommonMethods struct { + AuthNew func(p0 context.Context, p1 []auth.Permission) ([]byte, error) `perm:"admin"` - Closing func(p0 context.Context) (<-chan struct{}, error) `perm:"read"` + AuthVerify func(p0 context.Context, p1 string) ([]auth.Permission, error) `perm:"read"` - Discover func(p0 context.Context) (apitypes.OpenRPCDocument, error) `perm:"read"` + Closing func(p0 context.Context) (<-chan struct{}, error) `perm:"read"` - LogAlerts func(p0 context.Context) ([]alerting.Alert, error) `perm:"admin"` + Discover func(p0 context.Context) (apitypes.OpenRPCDocument, error) `perm:"read"` - LogList func(p0 context.Context) ([]string, error) `perm:"write"` + LogAlerts func(p0 context.Context) ([]alerting.Alert, error) `perm:"admin"` - LogSetLevel func(p0 context.Context, p1 string, p2 string) error `perm:"write"` + LogList func(p0 context.Context) ([]string, error) `perm:"write"` - Session func(p0 context.Context) (uuid.UUID, error) `perm:"read"` + LogSetLevel func(p0 context.Context, p1 string, p2 string) error `perm:"write"` - Shutdown func(p0 context.Context) error `perm:"admin"` + Session func(p0 context.Context) (uuid.UUID, error) `perm:"read"` - StartTime func(p0 context.Context) (time.Time, error) `perm:"read"` + Shutdown func(p0 context.Context) error `perm:"admin"` - Version func(p0 context.Context) (APIVersion, error) `perm:"read"` - } + StartTime func(p0 context.Context) (time.Time, error) `perm:"read"` + + Version func(p0 context.Context) (APIVersion, error) `perm:"read"` } type CommonStub struct { @@ -95,8 +100,10 @@ type CommonNetStruct struct { NetStruct - Internal struct { - } + Internal CommonNetMethods +} + +type CommonNetMethods struct { } type CommonNetStub struct { @@ -105,484 +112,499 @@ type CommonNetStub struct { NetStub } +type EthSubscriberStruct struct { + Internal EthSubscriberMethods +} + +type EthSubscriberMethods struct { + EthSubscription func(p0 context.Context, p1 jsonrpc.RawParams) error `notify:"true"rpc_method:"eth_subscription"` +} + +type EthSubscriberStub struct { +} + type FullNodeStruct struct { CommonStruct NetStruct - Internal struct { - ChainBlockstoreInfo func(p0 context.Context) (map[string]interface{}, error) `perm:"read"` + Internal FullNodeMethods +} - ChainCheckBlockstore func(p0 context.Context) error `perm:"admin"` +type FullNodeMethods struct { + ChainBlockstoreInfo func(p0 context.Context) (map[string]interface{}, error) `perm:"read"` - ChainDeleteObj func(p0 context.Context, p1 cid.Cid) error `perm:"admin"` + ChainCheckBlockstore func(p0 context.Context) error `perm:"admin"` - ChainExport func(p0 context.Context, p1 abi.ChainEpoch, p2 bool, p3 types.TipSetKey) (<-chan []byte, error) `perm:"read"` + ChainDeleteObj func(p0 context.Context, p1 cid.Cid) error `perm:"admin"` - ChainGetBlock func(p0 context.Context, p1 cid.Cid) (*types.BlockHeader, error) `perm:"read"` + ChainExport func(p0 context.Context, p1 abi.ChainEpoch, p2 bool, p3 types.TipSetKey) (<-chan []byte, error) `perm:"read"` - ChainGetBlockMessages func(p0 context.Context, p1 cid.Cid) (*BlockMessages, error) `perm:"read"` + ChainGetBlock func(p0 context.Context, p1 cid.Cid) (*types.BlockHeader, error) `perm:"read"` - ChainGetEvents func(p0 context.Context, p1 cid.Cid) ([]types.Event, error) `perm:"read"` + ChainGetBlockMessages func(p0 context.Context, p1 cid.Cid) (*BlockMessages, error) `perm:"read"` - ChainGetGenesis func(p0 context.Context) (*types.TipSet, error) `perm:"read"` + ChainGetEvents func(p0 context.Context, p1 cid.Cid) ([]types.Event, error) `perm:"read"` - ChainGetMessage func(p0 context.Context, p1 cid.Cid) (*types.Message, error) `perm:"read"` + ChainGetGenesis func(p0 context.Context) (*types.TipSet, error) `perm:"read"` - ChainGetMessagesInTipset func(p0 context.Context, p1 types.TipSetKey) ([]Message, error) `perm:"read"` + ChainGetMessage func(p0 context.Context, p1 cid.Cid) (*types.Message, error) `perm:"read"` - ChainGetNode func(p0 context.Context, p1 string) (*IpldObject, error) `perm:"read"` + ChainGetMessagesInTipset func(p0 context.Context, p1 types.TipSetKey) ([]Message, error) `perm:"read"` - ChainGetParentMessages func(p0 context.Context, p1 cid.Cid) ([]Message, error) `perm:"read"` + ChainGetNode func(p0 context.Context, p1 string) (*IpldObject, error) `perm:"read"` - ChainGetParentReceipts func(p0 context.Context, p1 cid.Cid) ([]*types.MessageReceipt, error) `perm:"read"` + ChainGetParentMessages func(p0 context.Context, p1 cid.Cid) ([]Message, error) `perm:"read"` - ChainGetPath func(p0 context.Context, p1 types.TipSetKey, p2 types.TipSetKey) ([]*HeadChange, error) `perm:"read"` + ChainGetParentReceipts func(p0 context.Context, p1 cid.Cid) ([]*types.MessageReceipt, error) `perm:"read"` - ChainGetTipSet func(p0 context.Context, p1 types.TipSetKey) (*types.TipSet, error) `perm:"read"` + ChainGetPath func(p0 context.Context, p1 types.TipSetKey, p2 types.TipSetKey) ([]*HeadChange, error) `perm:"read"` - ChainGetTipSetAfterHeight func(p0 context.Context, p1 abi.ChainEpoch, p2 types.TipSetKey) (*types.TipSet, error) `perm:"read"` + ChainGetTipSet func(p0 context.Context, p1 types.TipSetKey) (*types.TipSet, error) `perm:"read"` - ChainGetTipSetByHeight func(p0 context.Context, p1 abi.ChainEpoch, p2 types.TipSetKey) (*types.TipSet, error) `perm:"read"` + ChainGetTipSetAfterHeight func(p0 context.Context, p1 abi.ChainEpoch, p2 types.TipSetKey) (*types.TipSet, error) `perm:"read"` - ChainHasObj func(p0 context.Context, p1 cid.Cid) (bool, error) `perm:"read"` + ChainGetTipSetByHeight func(p0 context.Context, p1 abi.ChainEpoch, p2 types.TipSetKey) (*types.TipSet, error) `perm:"read"` - ChainHead func(p0 context.Context) (*types.TipSet, error) `perm:"read"` + ChainHasObj func(p0 context.Context, p1 cid.Cid) (bool, error) `perm:"read"` - ChainNotify func(p0 context.Context) (<-chan []*HeadChange, error) `perm:"read"` + ChainHead func(p0 context.Context) (*types.TipSet, error) `perm:"read"` - ChainPrune func(p0 context.Context, p1 PruneOpts) error `perm:"admin"` + ChainNotify func(p0 context.Context) (<-chan []*HeadChange, error) `perm:"read"` - ChainPutObj func(p0 context.Context, p1 blocks.Block) error `perm:"admin"` + ChainPrune func(p0 context.Context, p1 PruneOpts) error `perm:"admin"` - ChainReadObj func(p0 context.Context, p1 cid.Cid) ([]byte, error) `perm:"read"` + ChainPutObj func(p0 context.Context, p1 blocks.Block) error `perm:"admin"` - ChainSetHead func(p0 context.Context, p1 types.TipSetKey) error `perm:"admin"` + ChainReadObj func(p0 context.Context, p1 cid.Cid) ([]byte, error) `perm:"read"` - ChainStatObj func(p0 context.Context, p1 cid.Cid, p2 cid.Cid) (ObjStat, error) `perm:"read"` + ChainSetHead func(p0 context.Context, p1 types.TipSetKey) error `perm:"admin"` - ChainTipSetWeight func(p0 context.Context, p1 types.TipSetKey) (types.BigInt, error) `perm:"read"` + ChainStatObj func(p0 context.Context, p1 cid.Cid, p2 cid.Cid) (ObjStat, error) `perm:"read"` - ClientCalcCommP func(p0 context.Context, p1 string) (*CommPRet, error) `perm:"write"` + ChainTipSetWeight func(p0 context.Context, p1 types.TipSetKey) (types.BigInt, error) `perm:"read"` - ClientCancelDataTransfer func(p0 context.Context, p1 datatransfer.TransferID, p2 peer.ID, p3 bool) error `perm:"write"` + ClientCalcCommP func(p0 context.Context, p1 string) (*CommPRet, error) `perm:"write"` - ClientCancelRetrievalDeal func(p0 context.Context, p1 retrievalmarket.DealID) error `perm:"write"` + ClientCancelDataTransfer func(p0 context.Context, p1 datatransfer.TransferID, p2 peer.ID, p3 bool) error `perm:"write"` - ClientDataTransferUpdates func(p0 context.Context) (<-chan DataTransferChannel, error) `perm:"write"` + ClientCancelRetrievalDeal func(p0 context.Context, p1 retrievalmarket.DealID) error `perm:"write"` - ClientDealPieceCID func(p0 context.Context, p1 cid.Cid) (DataCIDSize, error) `perm:"read"` + ClientDataTransferUpdates func(p0 context.Context) (<-chan DataTransferChannel, error) `perm:"write"` - ClientDealSize func(p0 context.Context, p1 cid.Cid) (DataSize, error) `perm:"read"` + ClientDealPieceCID func(p0 context.Context, p1 cid.Cid) (DataCIDSize, error) `perm:"read"` - ClientExport func(p0 context.Context, p1 ExportRef, p2 FileRef) error `perm:"admin"` + ClientDealSize func(p0 context.Context, p1 cid.Cid) (DataSize, error) `perm:"read"` - ClientFindData func(p0 context.Context, p1 cid.Cid, p2 *cid.Cid) ([]QueryOffer, error) `perm:"read"` + ClientExport func(p0 context.Context, p1 ExportRef, p2 FileRef) error `perm:"admin"` - ClientGenCar func(p0 context.Context, p1 FileRef, p2 string) error `perm:"write"` + ClientFindData func(p0 context.Context, p1 cid.Cid, p2 *cid.Cid) ([]QueryOffer, error) `perm:"read"` - ClientGetDealInfo func(p0 context.Context, p1 cid.Cid) (*DealInfo, error) `perm:"read"` + ClientGenCar func(p0 context.Context, p1 FileRef, p2 string) error `perm:"write"` - ClientGetDealStatus func(p0 context.Context, p1 uint64) (string, error) `perm:"read"` + ClientGetDealInfo func(p0 context.Context, p1 cid.Cid) (*DealInfo, error) `perm:"read"` - ClientGetDealUpdates func(p0 context.Context) (<-chan DealInfo, error) `perm:"write"` + ClientGetDealStatus func(p0 context.Context, p1 uint64) (string, error) `perm:"read"` - ClientGetRetrievalUpdates func(p0 context.Context) (<-chan RetrievalInfo, error) `perm:"write"` + ClientGetDealUpdates func(p0 context.Context) (<-chan DealInfo, error) `perm:"write"` - ClientHasLocal func(p0 context.Context, p1 cid.Cid) (bool, error) `perm:"write"` + ClientGetRetrievalUpdates func(p0 context.Context) (<-chan RetrievalInfo, error) `perm:"write"` - ClientImport func(p0 context.Context, p1 FileRef) (*ImportRes, error) `perm:"admin"` + ClientHasLocal func(p0 context.Context, p1 cid.Cid) (bool, error) `perm:"write"` - ClientListDataTransfers func(p0 context.Context) ([]DataTransferChannel, error) `perm:"write"` + ClientImport func(p0 context.Context, p1 FileRef) (*ImportRes, error) `perm:"admin"` - ClientListDeals func(p0 context.Context) ([]DealInfo, error) `perm:"write"` + ClientListDataTransfers func(p0 context.Context) ([]DataTransferChannel, error) `perm:"write"` - ClientListImports func(p0 context.Context) ([]Import, error) `perm:"write"` + ClientListDeals func(p0 context.Context) ([]DealInfo, error) `perm:"write"` - ClientListRetrievals func(p0 context.Context) ([]RetrievalInfo, error) `perm:"write"` + ClientListImports func(p0 context.Context) ([]Import, error) `perm:"write"` - ClientMinerQueryOffer func(p0 context.Context, p1 address.Address, p2 cid.Cid, p3 *cid.Cid) (QueryOffer, error) `perm:"read"` + ClientListRetrievals func(p0 context.Context) ([]RetrievalInfo, error) `perm:"write"` - ClientQueryAsk func(p0 context.Context, p1 peer.ID, p2 address.Address) (*StorageAsk, error) `perm:"read"` + ClientMinerQueryOffer func(p0 context.Context, p1 address.Address, p2 cid.Cid, p3 *cid.Cid) (QueryOffer, error) `perm:"read"` - ClientRemoveImport func(p0 context.Context, p1 imports.ID) error `perm:"admin"` + ClientQueryAsk func(p0 context.Context, p1 peer.ID, p2 address.Address) (*StorageAsk, error) `perm:"read"` - ClientRestartDataTransfer func(p0 context.Context, p1 datatransfer.TransferID, p2 peer.ID, p3 bool) error `perm:"write"` + ClientRemoveImport func(p0 context.Context, p1 imports.ID) error `perm:"admin"` - ClientRetrieve func(p0 context.Context, p1 RetrievalOrder) (*RestrievalRes, error) `perm:"admin"` + ClientRestartDataTransfer func(p0 context.Context, p1 datatransfer.TransferID, p2 peer.ID, p3 bool) error `perm:"write"` - ClientRetrieveTryRestartInsufficientFunds func(p0 context.Context, p1 address.Address) error `perm:"write"` + ClientRetrieve func(p0 context.Context, p1 RetrievalOrder) (*RestrievalRes, error) `perm:"admin"` - ClientRetrieveWait func(p0 context.Context, p1 retrievalmarket.DealID) error `perm:"admin"` + ClientRetrieveTryRestartInsufficientFunds func(p0 context.Context, p1 address.Address) error `perm:"write"` - ClientStartDeal func(p0 context.Context, p1 *StartDealParams) (*cid.Cid, error) `perm:"admin"` + ClientRetrieveWait func(p0 context.Context, p1 retrievalmarket.DealID) error `perm:"admin"` - ClientStatelessDeal func(p0 context.Context, p1 *StartDealParams) (*cid.Cid, error) `perm:"write"` + ClientStartDeal func(p0 context.Context, p1 *StartDealParams) (*cid.Cid, error) `perm:"admin"` - CreateBackup func(p0 context.Context, p1 string) error `perm:"admin"` + ClientStatelessDeal func(p0 context.Context, p1 *StartDealParams) (*cid.Cid, error) `perm:"write"` - EthAccounts func(p0 context.Context) ([]ethtypes.EthAddress, error) `perm:"read"` + CreateBackup func(p0 context.Context, p1 string) error `perm:"admin"` - EthBlockNumber func(p0 context.Context) (ethtypes.EthUint64, error) `perm:"read"` + EthAccounts func(p0 context.Context) ([]ethtypes.EthAddress, error) `perm:"read"` - EthCall func(p0 context.Context, p1 ethtypes.EthCall, p2 string) (ethtypes.EthBytes, error) `perm:"read"` + EthBlockNumber func(p0 context.Context) (ethtypes.EthUint64, error) `perm:"read"` - EthChainId func(p0 context.Context) (ethtypes.EthUint64, error) `perm:"read"` + EthCall func(p0 context.Context, p1 ethtypes.EthCall, p2 string) (ethtypes.EthBytes, error) `perm:"read"` - EthEstimateGas func(p0 context.Context, p1 ethtypes.EthCall) (ethtypes.EthUint64, error) `perm:"read"` + EthChainId func(p0 context.Context) (ethtypes.EthUint64, error) `perm:"read"` - EthFeeHistory func(p0 context.Context, p1 ethtypes.EthUint64, p2 string, p3 []float64) (ethtypes.EthFeeHistory, error) `perm:"read"` + EthEstimateGas func(p0 context.Context, p1 ethtypes.EthCall) (ethtypes.EthUint64, error) `perm:"read"` - EthGasPrice func(p0 context.Context) (ethtypes.EthBigInt, error) `perm:"read"` + EthFeeHistory func(p0 context.Context, p1 ethtypes.EthUint64, p2 string, p3 []float64) (ethtypes.EthFeeHistory, error) `perm:"read"` - EthGetBalance func(p0 context.Context, p1 ethtypes.EthAddress, p2 string) (ethtypes.EthBigInt, error) `perm:"read"` + EthGasPrice func(p0 context.Context) (ethtypes.EthBigInt, error) `perm:"read"` - EthGetBlockByHash func(p0 context.Context, p1 ethtypes.EthHash, p2 bool) (ethtypes.EthBlock, error) `perm:"read"` + EthGetBalance func(p0 context.Context, p1 ethtypes.EthAddress, p2 string) (ethtypes.EthBigInt, error) `perm:"read"` - EthGetBlockByNumber func(p0 context.Context, p1 string, p2 bool) (ethtypes.EthBlock, error) `perm:"read"` + EthGetBlockByHash func(p0 context.Context, p1 ethtypes.EthHash, p2 bool) (ethtypes.EthBlock, error) `perm:"read"` - EthGetBlockTransactionCountByHash func(p0 context.Context, p1 ethtypes.EthHash) (ethtypes.EthUint64, error) `perm:"read"` + EthGetBlockByNumber func(p0 context.Context, p1 string, p2 bool) (ethtypes.EthBlock, error) `perm:"read"` - EthGetBlockTransactionCountByNumber func(p0 context.Context, p1 ethtypes.EthUint64) (ethtypes.EthUint64, error) `perm:"read"` + EthGetBlockTransactionCountByHash func(p0 context.Context, p1 ethtypes.EthHash) (ethtypes.EthUint64, error) `perm:"read"` - EthGetCode func(p0 context.Context, p1 ethtypes.EthAddress, p2 string) (ethtypes.EthBytes, error) `perm:"read"` + EthGetBlockTransactionCountByNumber func(p0 context.Context, p1 ethtypes.EthUint64) (ethtypes.EthUint64, error) `perm:"read"` - EthGetFilterChanges func(p0 context.Context, p1 ethtypes.EthFilterID) (*ethtypes.EthFilterResult, error) `perm:"write"` + EthGetCode func(p0 context.Context, p1 ethtypes.EthAddress, p2 string) (ethtypes.EthBytes, error) `perm:"read"` - EthGetFilterLogs func(p0 context.Context, p1 ethtypes.EthFilterID) (*ethtypes.EthFilterResult, error) `perm:"write"` + EthGetFilterChanges func(p0 context.Context, p1 ethtypes.EthFilterID) (*ethtypes.EthFilterResult, error) `perm:"write"` - EthGetLogs func(p0 context.Context, p1 *ethtypes.EthFilterSpec) (*ethtypes.EthFilterResult, error) `perm:"read"` + EthGetFilterLogs func(p0 context.Context, p1 ethtypes.EthFilterID) (*ethtypes.EthFilterResult, error) `perm:"write"` - EthGetMessageCidByTransactionHash func(p0 context.Context, p1 *ethtypes.EthHash) (*cid.Cid, error) `perm:"read"` + EthGetLogs func(p0 context.Context, p1 *ethtypes.EthFilterSpec) (*ethtypes.EthFilterResult, error) `perm:"read"` - EthGetStorageAt func(p0 context.Context, p1 ethtypes.EthAddress, p2 ethtypes.EthBytes, p3 string) (ethtypes.EthBytes, error) `perm:"read"` + EthGetMessageCidByTransactionHash func(p0 context.Context, p1 *ethtypes.EthHash) (*cid.Cid, error) `perm:"read"` - EthGetTransactionByBlockHashAndIndex func(p0 context.Context, p1 ethtypes.EthHash, p2 ethtypes.EthUint64) (ethtypes.EthTx, error) `perm:"read"` + EthGetStorageAt func(p0 context.Context, p1 ethtypes.EthAddress, p2 ethtypes.EthBytes, p3 string) (ethtypes.EthBytes, error) `perm:"read"` - EthGetTransactionByBlockNumberAndIndex func(p0 context.Context, p1 ethtypes.EthUint64, p2 ethtypes.EthUint64) (ethtypes.EthTx, error) `perm:"read"` + EthGetTransactionByBlockHashAndIndex func(p0 context.Context, p1 ethtypes.EthHash, p2 ethtypes.EthUint64) (ethtypes.EthTx, error) `perm:"read"` - EthGetTransactionByHash func(p0 context.Context, p1 *ethtypes.EthHash) (*ethtypes.EthTx, error) `perm:"read"` + EthGetTransactionByBlockNumberAndIndex func(p0 context.Context, p1 ethtypes.EthUint64, p2 ethtypes.EthUint64) (ethtypes.EthTx, error) `perm:"read"` - EthGetTransactionCount func(p0 context.Context, p1 ethtypes.EthAddress, p2 string) (ethtypes.EthUint64, error) `perm:"read"` + EthGetTransactionByHash func(p0 context.Context, p1 *ethtypes.EthHash) (*ethtypes.EthTx, error) `perm:"read"` - EthGetTransactionHashByCid func(p0 context.Context, p1 cid.Cid) (*ethtypes.EthHash, error) `perm:"read"` + EthGetTransactionCount func(p0 context.Context, p1 ethtypes.EthAddress, p2 string) (ethtypes.EthUint64, error) `perm:"read"` - EthGetTransactionReceipt func(p0 context.Context, p1 ethtypes.EthHash) (*EthTxReceipt, error) `perm:"read"` + EthGetTransactionHashByCid func(p0 context.Context, p1 cid.Cid) (*ethtypes.EthHash, error) `perm:"read"` - EthMaxPriorityFeePerGas func(p0 context.Context) (ethtypes.EthBigInt, error) `perm:"read"` + EthGetTransactionReceipt func(p0 context.Context, p1 ethtypes.EthHash) (*EthTxReceipt, error) `perm:"read"` - EthNewBlockFilter func(p0 context.Context) (ethtypes.EthFilterID, error) `perm:"write"` + EthMaxPriorityFeePerGas func(p0 context.Context) (ethtypes.EthBigInt, error) `perm:"read"` - EthNewFilter func(p0 context.Context, p1 *ethtypes.EthFilterSpec) (ethtypes.EthFilterID, error) `perm:"write"` + EthNewBlockFilter func(p0 context.Context) (ethtypes.EthFilterID, error) `perm:"write"` - EthNewPendingTransactionFilter func(p0 context.Context) (ethtypes.EthFilterID, error) `perm:"write"` + EthNewFilter func(p0 context.Context, p1 *ethtypes.EthFilterSpec) (ethtypes.EthFilterID, error) `perm:"write"` - EthProtocolVersion func(p0 context.Context) (ethtypes.EthUint64, error) `perm:"read"` + EthNewPendingTransactionFilter func(p0 context.Context) (ethtypes.EthFilterID, error) `perm:"write"` - EthSendRawTransaction func(p0 context.Context, p1 ethtypes.EthBytes) (ethtypes.EthHash, error) `perm:"read"` + EthProtocolVersion func(p0 context.Context) (ethtypes.EthUint64, error) `perm:"read"` - EthSubscribe func(p0 context.Context, p1 string, p2 *ethtypes.EthSubscriptionParams) (<-chan ethtypes.EthSubscriptionResponse, error) `perm:"write"` + EthSendRawTransaction func(p0 context.Context, p1 ethtypes.EthBytes) (ethtypes.EthHash, error) `perm:"read"` - EthUninstallFilter func(p0 context.Context, p1 ethtypes.EthFilterID) (bool, error) `perm:"write"` + EthSubscribe func(p0 context.Context, p1 jsonrpc.RawParams) (ethtypes.EthSubscriptionID, error) `perm:"write"` - EthUnsubscribe func(p0 context.Context, p1 ethtypes.EthSubscriptionID) (bool, error) `perm:"write"` + EthUninstallFilter func(p0 context.Context, p1 ethtypes.EthFilterID) (bool, error) `perm:"write"` - GasEstimateFeeCap func(p0 context.Context, p1 *types.Message, p2 int64, p3 types.TipSetKey) (types.BigInt, error) `perm:"read"` + EthUnsubscribe func(p0 context.Context, p1 ethtypes.EthSubscriptionID) (bool, error) `perm:"write"` - GasEstimateGasLimit func(p0 context.Context, p1 *types.Message, p2 types.TipSetKey) (int64, error) `perm:"read"` + GasEstimateFeeCap func(p0 context.Context, p1 *types.Message, p2 int64, p3 types.TipSetKey) (types.BigInt, error) `perm:"read"` - GasEstimateGasPremium func(p0 context.Context, p1 uint64, p2 address.Address, p3 int64, p4 types.TipSetKey) (types.BigInt, error) `perm:"read"` + GasEstimateGasLimit func(p0 context.Context, p1 *types.Message, p2 types.TipSetKey) (int64, error) `perm:"read"` - GasEstimateMessageGas func(p0 context.Context, p1 *types.Message, p2 *MessageSendSpec, p3 types.TipSetKey) (*types.Message, error) `perm:"read"` + GasEstimateGasPremium func(p0 context.Context, p1 uint64, p2 address.Address, p3 int64, p4 types.TipSetKey) (types.BigInt, error) `perm:"read"` - MarketAddBalance func(p0 context.Context, p1 address.Address, p2 address.Address, p3 types.BigInt) (cid.Cid, error) `perm:"sign"` + GasEstimateMessageGas func(p0 context.Context, p1 *types.Message, p2 *MessageSendSpec, p3 types.TipSetKey) (*types.Message, error) `perm:"read"` - MarketGetReserved func(p0 context.Context, p1 address.Address) (types.BigInt, error) `perm:"sign"` + MarketAddBalance func(p0 context.Context, p1 address.Address, p2 address.Address, p3 types.BigInt) (cid.Cid, error) `perm:"sign"` - MarketReleaseFunds func(p0 context.Context, p1 address.Address, p2 types.BigInt) error `perm:"sign"` + MarketGetReserved func(p0 context.Context, p1 address.Address) (types.BigInt, error) `perm:"sign"` - MarketReserveFunds func(p0 context.Context, p1 address.Address, p2 address.Address, p3 types.BigInt) (cid.Cid, error) `perm:"sign"` + MarketReleaseFunds func(p0 context.Context, p1 address.Address, p2 types.BigInt) error `perm:"sign"` - MarketWithdraw func(p0 context.Context, p1 address.Address, p2 address.Address, p3 types.BigInt) (cid.Cid, error) `perm:"sign"` + MarketReserveFunds func(p0 context.Context, p1 address.Address, p2 address.Address, p3 types.BigInt) (cid.Cid, error) `perm:"sign"` - MinerCreateBlock func(p0 context.Context, p1 *BlockTemplate) (*types.BlockMsg, error) `perm:"write"` + MarketWithdraw func(p0 context.Context, p1 address.Address, p2 address.Address, p3 types.BigInt) (cid.Cid, error) `perm:"sign"` - MinerGetBaseInfo func(p0 context.Context, p1 address.Address, p2 abi.ChainEpoch, p3 types.TipSetKey) (*MiningBaseInfo, error) `perm:"read"` + MinerCreateBlock func(p0 context.Context, p1 *BlockTemplate) (*types.BlockMsg, error) `perm:"write"` - MpoolBatchPush func(p0 context.Context, p1 []*types.SignedMessage) ([]cid.Cid, error) `perm:"write"` + MinerGetBaseInfo func(p0 context.Context, p1 address.Address, p2 abi.ChainEpoch, p3 types.TipSetKey) (*MiningBaseInfo, error) `perm:"read"` - MpoolBatchPushMessage func(p0 context.Context, p1 []*types.Message, p2 *MessageSendSpec) ([]*types.SignedMessage, error) `perm:"sign"` + MpoolBatchPush func(p0 context.Context, p1 []*types.SignedMessage) ([]cid.Cid, error) `perm:"write"` - MpoolBatchPushUntrusted func(p0 context.Context, p1 []*types.SignedMessage) ([]cid.Cid, error) `perm:"write"` + MpoolBatchPushMessage func(p0 context.Context, p1 []*types.Message, p2 *MessageSendSpec) ([]*types.SignedMessage, error) `perm:"sign"` - MpoolCheckMessages func(p0 context.Context, p1 []*MessagePrototype) ([][]MessageCheckStatus, error) `perm:"read"` + MpoolBatchPushUntrusted func(p0 context.Context, p1 []*types.SignedMessage) ([]cid.Cid, error) `perm:"write"` - MpoolCheckPendingMessages func(p0 context.Context, p1 address.Address) ([][]MessageCheckStatus, error) `perm:"read"` + MpoolCheckMessages func(p0 context.Context, p1 []*MessagePrototype) ([][]MessageCheckStatus, error) `perm:"read"` - MpoolCheckReplaceMessages func(p0 context.Context, p1 []*types.Message) ([][]MessageCheckStatus, error) `perm:"read"` + MpoolCheckPendingMessages func(p0 context.Context, p1 address.Address) ([][]MessageCheckStatus, error) `perm:"read"` - MpoolClear func(p0 context.Context, p1 bool) error `perm:"write"` + MpoolCheckReplaceMessages func(p0 context.Context, p1 []*types.Message) ([][]MessageCheckStatus, error) `perm:"read"` - MpoolGetConfig func(p0 context.Context) (*types.MpoolConfig, error) `perm:"read"` + MpoolClear func(p0 context.Context, p1 bool) error `perm:"write"` - MpoolGetNonce func(p0 context.Context, p1 address.Address) (uint64, error) `perm:"read"` + MpoolGetConfig func(p0 context.Context) (*types.MpoolConfig, error) `perm:"read"` - MpoolPending func(p0 context.Context, p1 types.TipSetKey) ([]*types.SignedMessage, error) `perm:"read"` + MpoolGetNonce func(p0 context.Context, p1 address.Address) (uint64, error) `perm:"read"` - MpoolPush func(p0 context.Context, p1 *types.SignedMessage) (cid.Cid, error) `perm:"write"` + MpoolPending func(p0 context.Context, p1 types.TipSetKey) ([]*types.SignedMessage, error) `perm:"read"` - MpoolPushMessage func(p0 context.Context, p1 *types.Message, p2 *MessageSendSpec) (*types.SignedMessage, error) `perm:"sign"` + MpoolPush func(p0 context.Context, p1 *types.SignedMessage) (cid.Cid, error) `perm:"write"` - MpoolPushUntrusted func(p0 context.Context, p1 *types.SignedMessage) (cid.Cid, error) `perm:"write"` + MpoolPushMessage func(p0 context.Context, p1 *types.Message, p2 *MessageSendSpec) (*types.SignedMessage, error) `perm:"sign"` - MpoolSelect func(p0 context.Context, p1 types.TipSetKey, p2 float64) ([]*types.SignedMessage, error) `perm:"read"` + MpoolPushUntrusted func(p0 context.Context, p1 *types.SignedMessage) (cid.Cid, error) `perm:"write"` - MpoolSetConfig func(p0 context.Context, p1 *types.MpoolConfig) error `perm:"admin"` + MpoolSelect func(p0 context.Context, p1 types.TipSetKey, p2 float64) ([]*types.SignedMessage, error) `perm:"read"` - MpoolSub func(p0 context.Context) (<-chan MpoolUpdate, error) `perm:"read"` + MpoolSetConfig func(p0 context.Context, p1 *types.MpoolConfig) error `perm:"admin"` - MsigAddApprove func(p0 context.Context, p1 address.Address, p2 address.Address, p3 uint64, p4 address.Address, p5 address.Address, p6 bool) (*MessagePrototype, error) `perm:"sign"` + MpoolSub func(p0 context.Context) (<-chan MpoolUpdate, error) `perm:"read"` - MsigAddCancel func(p0 context.Context, p1 address.Address, p2 address.Address, p3 uint64, p4 address.Address, p5 bool) (*MessagePrototype, error) `perm:"sign"` + MsigAddApprove func(p0 context.Context, p1 address.Address, p2 address.Address, p3 uint64, p4 address.Address, p5 address.Address, p6 bool) (*MessagePrototype, error) `perm:"sign"` - MsigAddPropose func(p0 context.Context, p1 address.Address, p2 address.Address, p3 address.Address, p4 bool) (*MessagePrototype, error) `perm:"sign"` + MsigAddCancel func(p0 context.Context, p1 address.Address, p2 address.Address, p3 uint64, p4 address.Address, p5 bool) (*MessagePrototype, error) `perm:"sign"` - MsigApprove func(p0 context.Context, p1 address.Address, p2 uint64, p3 address.Address) (*MessagePrototype, error) `perm:"sign"` + MsigAddPropose func(p0 context.Context, p1 address.Address, p2 address.Address, p3 address.Address, p4 bool) (*MessagePrototype, error) `perm:"sign"` - MsigApproveTxnHash func(p0 context.Context, p1 address.Address, p2 uint64, p3 address.Address, p4 address.Address, p5 types.BigInt, p6 address.Address, p7 uint64, p8 []byte) (*MessagePrototype, error) `perm:"sign"` + MsigApprove func(p0 context.Context, p1 address.Address, p2 uint64, p3 address.Address) (*MessagePrototype, error) `perm:"sign"` - MsigCancel func(p0 context.Context, p1 address.Address, p2 uint64, p3 address.Address) (*MessagePrototype, error) `perm:"sign"` + MsigApproveTxnHash func(p0 context.Context, p1 address.Address, p2 uint64, p3 address.Address, p4 address.Address, p5 types.BigInt, p6 address.Address, p7 uint64, p8 []byte) (*MessagePrototype, error) `perm:"sign"` - MsigCancelTxnHash func(p0 context.Context, p1 address.Address, p2 uint64, p3 address.Address, p4 types.BigInt, p5 address.Address, p6 uint64, p7 []byte) (*MessagePrototype, error) `perm:"sign"` + MsigCancel func(p0 context.Context, p1 address.Address, p2 uint64, p3 address.Address) (*MessagePrototype, error) `perm:"sign"` - MsigCreate func(p0 context.Context, p1 uint64, p2 []address.Address, p3 abi.ChainEpoch, p4 types.BigInt, p5 address.Address, p6 types.BigInt) (*MessagePrototype, error) `perm:"sign"` + MsigCancelTxnHash func(p0 context.Context, p1 address.Address, p2 uint64, p3 address.Address, p4 types.BigInt, p5 address.Address, p6 uint64, p7 []byte) (*MessagePrototype, error) `perm:"sign"` - MsigGetAvailableBalance func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (types.BigInt, error) `perm:"read"` + MsigCreate func(p0 context.Context, p1 uint64, p2 []address.Address, p3 abi.ChainEpoch, p4 types.BigInt, p5 address.Address, p6 types.BigInt) (*MessagePrototype, error) `perm:"sign"` - MsigGetPending func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) ([]*MsigTransaction, error) `perm:"read"` + MsigGetAvailableBalance func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (types.BigInt, error) `perm:"read"` - MsigGetVested func(p0 context.Context, p1 address.Address, p2 types.TipSetKey, p3 types.TipSetKey) (types.BigInt, error) `perm:"read"` + MsigGetPending func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) ([]*MsigTransaction, error) `perm:"read"` - MsigGetVestingSchedule func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (MsigVesting, error) `perm:"read"` + MsigGetVested func(p0 context.Context, p1 address.Address, p2 types.TipSetKey, p3 types.TipSetKey) (types.BigInt, error) `perm:"read"` - MsigPropose func(p0 context.Context, p1 address.Address, p2 address.Address, p3 types.BigInt, p4 address.Address, p5 uint64, p6 []byte) (*MessagePrototype, error) `perm:"sign"` + MsigGetVestingSchedule func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (MsigVesting, error) `perm:"read"` - MsigRemoveSigner func(p0 context.Context, p1 address.Address, p2 address.Address, p3 address.Address, p4 bool) (*MessagePrototype, error) `perm:"sign"` + MsigPropose func(p0 context.Context, p1 address.Address, p2 address.Address, p3 types.BigInt, p4 address.Address, p5 uint64, p6 []byte) (*MessagePrototype, error) `perm:"sign"` - MsigSwapApprove func(p0 context.Context, p1 address.Address, p2 address.Address, p3 uint64, p4 address.Address, p5 address.Address, p6 address.Address) (*MessagePrototype, error) `perm:"sign"` + MsigRemoveSigner func(p0 context.Context, p1 address.Address, p2 address.Address, p3 address.Address, p4 bool) (*MessagePrototype, error) `perm:"sign"` - MsigSwapCancel func(p0 context.Context, p1 address.Address, p2 address.Address, p3 uint64, p4 address.Address, p5 address.Address) (*MessagePrototype, error) `perm:"sign"` + MsigSwapApprove func(p0 context.Context, p1 address.Address, p2 address.Address, p3 uint64, p4 address.Address, p5 address.Address, p6 address.Address) (*MessagePrototype, error) `perm:"sign"` - MsigSwapPropose func(p0 context.Context, p1 address.Address, p2 address.Address, p3 address.Address, p4 address.Address) (*MessagePrototype, error) `perm:"sign"` + MsigSwapCancel func(p0 context.Context, p1 address.Address, p2 address.Address, p3 uint64, p4 address.Address, p5 address.Address) (*MessagePrototype, error) `perm:"sign"` - NetListening func(p0 context.Context) (bool, error) `perm:"read"` + MsigSwapPropose func(p0 context.Context, p1 address.Address, p2 address.Address, p3 address.Address, p4 address.Address) (*MessagePrototype, error) `perm:"sign"` - NetVersion func(p0 context.Context) (string, error) `perm:"read"` + NetListening func(p0 context.Context) (bool, error) `perm:"read"` - NodeStatus func(p0 context.Context, p1 bool) (NodeStatus, error) `perm:"read"` + NetVersion func(p0 context.Context) (string, error) `perm:"read"` - PaychAllocateLane func(p0 context.Context, p1 address.Address) (uint64, error) `perm:"sign"` + NodeStatus func(p0 context.Context, p1 bool) (NodeStatus, error) `perm:"read"` - PaychAvailableFunds func(p0 context.Context, p1 address.Address) (*ChannelAvailableFunds, error) `perm:"sign"` + PaychAllocateLane func(p0 context.Context, p1 address.Address) (uint64, error) `perm:"sign"` - PaychAvailableFundsByFromTo func(p0 context.Context, p1 address.Address, p2 address.Address) (*ChannelAvailableFunds, error) `perm:"sign"` + PaychAvailableFunds func(p0 context.Context, p1 address.Address) (*ChannelAvailableFunds, error) `perm:"sign"` - PaychCollect func(p0 context.Context, p1 address.Address) (cid.Cid, error) `perm:"sign"` + PaychAvailableFundsByFromTo func(p0 context.Context, p1 address.Address, p2 address.Address) (*ChannelAvailableFunds, error) `perm:"sign"` - PaychFund func(p0 context.Context, p1 address.Address, p2 address.Address, p3 types.BigInt) (*ChannelInfo, error) `perm:"sign"` + PaychCollect func(p0 context.Context, p1 address.Address) (cid.Cid, error) `perm:"sign"` - PaychGet func(p0 context.Context, p1 address.Address, p2 address.Address, p3 types.BigInt, p4 PaychGetOpts) (*ChannelInfo, error) `perm:"sign"` + PaychFund func(p0 context.Context, p1 address.Address, p2 address.Address, p3 types.BigInt) (*ChannelInfo, error) `perm:"sign"` - PaychGetWaitReady func(p0 context.Context, p1 cid.Cid) (address.Address, error) `perm:"sign"` + PaychGet func(p0 context.Context, p1 address.Address, p2 address.Address, p3 types.BigInt, p4 PaychGetOpts) (*ChannelInfo, error) `perm:"sign"` - PaychList func(p0 context.Context) ([]address.Address, error) `perm:"read"` + PaychGetWaitReady func(p0 context.Context, p1 cid.Cid) (address.Address, error) `perm:"sign"` - PaychNewPayment func(p0 context.Context, p1 address.Address, p2 address.Address, p3 []VoucherSpec) (*PaymentInfo, error) `perm:"sign"` + PaychList func(p0 context.Context) ([]address.Address, error) `perm:"read"` - PaychSettle func(p0 context.Context, p1 address.Address) (cid.Cid, error) `perm:"sign"` + PaychNewPayment func(p0 context.Context, p1 address.Address, p2 address.Address, p3 []VoucherSpec) (*PaymentInfo, error) `perm:"sign"` - PaychStatus func(p0 context.Context, p1 address.Address) (*PaychStatus, error) `perm:"read"` + PaychSettle func(p0 context.Context, p1 address.Address) (cid.Cid, error) `perm:"sign"` - PaychVoucherAdd func(p0 context.Context, p1 address.Address, p2 *paych.SignedVoucher, p3 []byte, p4 types.BigInt) (types.BigInt, error) `perm:"write"` + PaychStatus func(p0 context.Context, p1 address.Address) (*PaychStatus, error) `perm:"read"` - PaychVoucherCheckSpendable func(p0 context.Context, p1 address.Address, p2 *paych.SignedVoucher, p3 []byte, p4 []byte) (bool, error) `perm:"read"` + PaychVoucherAdd func(p0 context.Context, p1 address.Address, p2 *paych.SignedVoucher, p3 []byte, p4 types.BigInt) (types.BigInt, error) `perm:"write"` - PaychVoucherCheckValid func(p0 context.Context, p1 address.Address, p2 *paych.SignedVoucher) error `perm:"read"` + PaychVoucherCheckSpendable func(p0 context.Context, p1 address.Address, p2 *paych.SignedVoucher, p3 []byte, p4 []byte) (bool, error) `perm:"read"` - PaychVoucherCreate func(p0 context.Context, p1 address.Address, p2 types.BigInt, p3 uint64) (*VoucherCreateResult, error) `perm:"sign"` + PaychVoucherCheckValid func(p0 context.Context, p1 address.Address, p2 *paych.SignedVoucher) error `perm:"read"` - PaychVoucherList func(p0 context.Context, p1 address.Address) ([]*paych.SignedVoucher, error) `perm:"write"` + PaychVoucherCreate func(p0 context.Context, p1 address.Address, p2 types.BigInt, p3 uint64) (*VoucherCreateResult, error) `perm:"sign"` - PaychVoucherSubmit func(p0 context.Context, p1 address.Address, p2 *paych.SignedVoucher, p3 []byte, p4 []byte) (cid.Cid, error) `perm:"sign"` + PaychVoucherList func(p0 context.Context, p1 address.Address) ([]*paych.SignedVoucher, error) `perm:"write"` - RaftLeader func(p0 context.Context) (peer.ID, error) `perm:"read"` + PaychVoucherSubmit func(p0 context.Context, p1 address.Address, p2 *paych.SignedVoucher, p3 []byte, p4 []byte) (cid.Cid, error) `perm:"sign"` - RaftState func(p0 context.Context) (*RaftStateData, error) `perm:"read"` + RaftLeader func(p0 context.Context) (peer.ID, error) `perm:"read"` - StateAccountKey func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (address.Address, error) `perm:"read"` + RaftState func(p0 context.Context) (*RaftStateData, error) `perm:"read"` - StateActorCodeCIDs func(p0 context.Context, p1 abinetwork.Version) (map[string]cid.Cid, error) `perm:"read"` + StateAccountKey func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (address.Address, error) `perm:"read"` - StateActorManifestCID func(p0 context.Context, p1 abinetwork.Version) (cid.Cid, error) `perm:"read"` + StateActorCodeCIDs func(p0 context.Context, p1 abinetwork.Version) (map[string]cid.Cid, error) `perm:"read"` - StateAllMinerFaults func(p0 context.Context, p1 abi.ChainEpoch, p2 types.TipSetKey) ([]*Fault, error) `perm:"read"` + StateActorManifestCID func(p0 context.Context, p1 abinetwork.Version) (cid.Cid, error) `perm:"read"` - StateCall func(p0 context.Context, p1 *types.Message, p2 types.TipSetKey) (*InvocResult, error) `perm:"read"` + StateAllMinerFaults func(p0 context.Context, p1 abi.ChainEpoch, p2 types.TipSetKey) ([]*Fault, error) `perm:"read"` - StateChangedActors func(p0 context.Context, p1 cid.Cid, p2 cid.Cid) (map[string]types.Actor, error) `perm:"read"` + StateCall func(p0 context.Context, p1 *types.Message, p2 types.TipSetKey) (*InvocResult, error) `perm:"read"` - StateCirculatingSupply func(p0 context.Context, p1 types.TipSetKey) (abi.TokenAmount, error) `perm:"read"` + StateChangedActors func(p0 context.Context, p1 cid.Cid, p2 cid.Cid) (map[string]types.Actor, error) `perm:"read"` - StateCompute func(p0 context.Context, p1 abi.ChainEpoch, p2 []*types.Message, p3 types.TipSetKey) (*ComputeStateOutput, error) `perm:"read"` + StateCirculatingSupply func(p0 context.Context, p1 types.TipSetKey) (abi.TokenAmount, error) `perm:"read"` - StateComputeDataCID func(p0 context.Context, p1 address.Address, p2 abi.RegisteredSealProof, p3 []abi.DealID, p4 types.TipSetKey) (cid.Cid, error) `perm:"read"` + StateCompute func(p0 context.Context, p1 abi.ChainEpoch, p2 []*types.Message, p3 types.TipSetKey) (*ComputeStateOutput, error) `perm:"read"` - StateDealProviderCollateralBounds func(p0 context.Context, p1 abi.PaddedPieceSize, p2 bool, p3 types.TipSetKey) (DealCollateralBounds, error) `perm:"read"` + StateComputeDataCID func(p0 context.Context, p1 address.Address, p2 abi.RegisteredSealProof, p3 []abi.DealID, p4 types.TipSetKey) (cid.Cid, error) `perm:"read"` - StateDecodeParams func(p0 context.Context, p1 address.Address, p2 abi.MethodNum, p3 []byte, p4 types.TipSetKey) (interface{}, error) `perm:"read"` + StateDealProviderCollateralBounds func(p0 context.Context, p1 abi.PaddedPieceSize, p2 bool, p3 types.TipSetKey) (DealCollateralBounds, error) `perm:"read"` - StateEncodeParams func(p0 context.Context, p1 cid.Cid, p2 abi.MethodNum, p3 json.RawMessage) ([]byte, error) `perm:"read"` + StateDecodeParams func(p0 context.Context, p1 address.Address, p2 abi.MethodNum, p3 []byte, p4 types.TipSetKey) (interface{}, error) `perm:"read"` - StateGetActor func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (*types.Actor, error) `perm:"read"` + StateEncodeParams func(p0 context.Context, p1 cid.Cid, p2 abi.MethodNum, p3 json.RawMessage) ([]byte, error) `perm:"read"` - StateGetAllocation func(p0 context.Context, p1 address.Address, p2 verifregtypes.AllocationId, p3 types.TipSetKey) (*verifregtypes.Allocation, error) `perm:"read"` + StateGetActor func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (*types.Actor, error) `perm:"read"` - StateGetAllocationForPendingDeal func(p0 context.Context, p1 abi.DealID, p2 types.TipSetKey) (*verifregtypes.Allocation, error) `perm:"read"` + StateGetAllocation func(p0 context.Context, p1 address.Address, p2 verifregtypes.AllocationId, p3 types.TipSetKey) (*verifregtypes.Allocation, error) `perm:"read"` - StateGetAllocations func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (map[verifregtypes.AllocationId]verifregtypes.Allocation, error) `perm:"read"` + StateGetAllocationForPendingDeal func(p0 context.Context, p1 abi.DealID, p2 types.TipSetKey) (*verifregtypes.Allocation, error) `perm:"read"` - StateGetBeaconEntry func(p0 context.Context, p1 abi.ChainEpoch) (*types.BeaconEntry, error) `perm:"read"` + StateGetAllocations func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (map[verifregtypes.AllocationId]verifregtypes.Allocation, error) `perm:"read"` - StateGetClaim func(p0 context.Context, p1 address.Address, p2 verifregtypes.ClaimId, p3 types.TipSetKey) (*verifregtypes.Claim, error) `perm:"read"` + StateGetBeaconEntry func(p0 context.Context, p1 abi.ChainEpoch) (*types.BeaconEntry, error) `perm:"read"` - StateGetClaims func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (map[verifregtypes.ClaimId]verifregtypes.Claim, error) `perm:"read"` + StateGetClaim func(p0 context.Context, p1 address.Address, p2 verifregtypes.ClaimId, p3 types.TipSetKey) (*verifregtypes.Claim, error) `perm:"read"` - StateGetNetworkParams func(p0 context.Context) (*NetworkParams, error) `perm:"read"` + StateGetClaims func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (map[verifregtypes.ClaimId]verifregtypes.Claim, error) `perm:"read"` - StateGetRandomnessFromBeacon func(p0 context.Context, p1 crypto.DomainSeparationTag, p2 abi.ChainEpoch, p3 []byte, p4 types.TipSetKey) (abi.Randomness, error) `perm:"read"` + StateGetNetworkParams func(p0 context.Context) (*NetworkParams, error) `perm:"read"` - StateGetRandomnessFromTickets func(p0 context.Context, p1 crypto.DomainSeparationTag, p2 abi.ChainEpoch, p3 []byte, p4 types.TipSetKey) (abi.Randomness, error) `perm:"read"` + StateGetRandomnessFromBeacon func(p0 context.Context, p1 crypto.DomainSeparationTag, p2 abi.ChainEpoch, p3 []byte, p4 types.TipSetKey) (abi.Randomness, error) `perm:"read"` - StateListActors func(p0 context.Context, p1 types.TipSetKey) ([]address.Address, error) `perm:"read"` + StateGetRandomnessFromTickets func(p0 context.Context, p1 crypto.DomainSeparationTag, p2 abi.ChainEpoch, p3 []byte, p4 types.TipSetKey) (abi.Randomness, error) `perm:"read"` - StateListMessages func(p0 context.Context, p1 *MessageMatch, p2 types.TipSetKey, p3 abi.ChainEpoch) ([]cid.Cid, error) `perm:"read"` + StateListActors func(p0 context.Context, p1 types.TipSetKey) ([]address.Address, error) `perm:"read"` - StateListMiners func(p0 context.Context, p1 types.TipSetKey) ([]address.Address, error) `perm:"read"` + StateListMessages func(p0 context.Context, p1 *MessageMatch, p2 types.TipSetKey, p3 abi.ChainEpoch) ([]cid.Cid, error) `perm:"read"` - StateLookupID func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (address.Address, error) `perm:"read"` + StateListMiners func(p0 context.Context, p1 types.TipSetKey) ([]address.Address, error) `perm:"read"` - StateLookupRobustAddress func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (address.Address, error) `perm:"read"` + StateLookupID func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (address.Address, error) `perm:"read"` - StateMarketBalance func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (MarketBalance, error) `perm:"read"` + StateLookupRobustAddress func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (address.Address, error) `perm:"read"` - StateMarketDeals func(p0 context.Context, p1 types.TipSetKey) (map[string]*MarketDeal, error) `perm:"read"` + StateMarketBalance func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (MarketBalance, error) `perm:"read"` - StateMarketParticipants func(p0 context.Context, p1 types.TipSetKey) (map[string]MarketBalance, error) `perm:"read"` + StateMarketDeals func(p0 context.Context, p1 types.TipSetKey) (map[string]*MarketDeal, error) `perm:"read"` - StateMarketStorageDeal func(p0 context.Context, p1 abi.DealID, p2 types.TipSetKey) (*MarketDeal, error) `perm:"read"` + StateMarketParticipants func(p0 context.Context, p1 types.TipSetKey) (map[string]MarketBalance, error) `perm:"read"` - StateMinerActiveSectors func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) ([]*miner.SectorOnChainInfo, error) `perm:"read"` + StateMarketStorageDeal func(p0 context.Context, p1 abi.DealID, p2 types.TipSetKey) (*MarketDeal, error) `perm:"read"` - StateMinerAllocated func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (*bitfield.BitField, error) `perm:"read"` + StateMinerActiveSectors func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) ([]*miner.SectorOnChainInfo, error) `perm:"read"` - StateMinerAvailableBalance func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (types.BigInt, error) `perm:"read"` + StateMinerAllocated func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (*bitfield.BitField, error) `perm:"read"` - StateMinerDeadlines func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) ([]Deadline, error) `perm:"read"` + StateMinerAvailableBalance func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (types.BigInt, error) `perm:"read"` - StateMinerFaults func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (bitfield.BitField, error) `perm:"read"` + StateMinerDeadlines func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) ([]Deadline, error) `perm:"read"` - StateMinerInfo func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (MinerInfo, error) `perm:"read"` + StateMinerFaults func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (bitfield.BitField, error) `perm:"read"` - StateMinerInitialPledgeCollateral func(p0 context.Context, p1 address.Address, p2 miner.SectorPreCommitInfo, p3 types.TipSetKey) (types.BigInt, error) `perm:"read"` + StateMinerInfo func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (MinerInfo, error) `perm:"read"` - StateMinerPartitions func(p0 context.Context, p1 address.Address, p2 uint64, p3 types.TipSetKey) ([]Partition, error) `perm:"read"` + StateMinerInitialPledgeCollateral func(p0 context.Context, p1 address.Address, p2 miner.SectorPreCommitInfo, p3 types.TipSetKey) (types.BigInt, error) `perm:"read"` - StateMinerPower func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (*MinerPower, error) `perm:"read"` + StateMinerPartitions func(p0 context.Context, p1 address.Address, p2 uint64, p3 types.TipSetKey) ([]Partition, error) `perm:"read"` - StateMinerPreCommitDepositForPower func(p0 context.Context, p1 address.Address, p2 miner.SectorPreCommitInfo, p3 types.TipSetKey) (types.BigInt, error) `perm:"read"` + StateMinerPower func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (*MinerPower, error) `perm:"read"` - StateMinerProvingDeadline func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (*dline.Info, error) `perm:"read"` + StateMinerPreCommitDepositForPower func(p0 context.Context, p1 address.Address, p2 miner.SectorPreCommitInfo, p3 types.TipSetKey) (types.BigInt, error) `perm:"read"` - StateMinerRecoveries func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (bitfield.BitField, error) `perm:"read"` + StateMinerProvingDeadline func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (*dline.Info, error) `perm:"read"` - StateMinerSectorAllocated func(p0 context.Context, p1 address.Address, p2 abi.SectorNumber, p3 types.TipSetKey) (bool, error) `perm:"read"` + StateMinerRecoveries func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (bitfield.BitField, error) `perm:"read"` - StateMinerSectorCount func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (MinerSectors, error) `perm:"read"` + StateMinerSectorAllocated func(p0 context.Context, p1 address.Address, p2 abi.SectorNumber, p3 types.TipSetKey) (bool, error) `perm:"read"` - StateMinerSectors func(p0 context.Context, p1 address.Address, p2 *bitfield.BitField, p3 types.TipSetKey) ([]*miner.SectorOnChainInfo, error) `perm:"read"` + StateMinerSectorCount func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (MinerSectors, error) `perm:"read"` - StateNetworkName func(p0 context.Context) (dtypes.NetworkName, error) `perm:"read"` + StateMinerSectors func(p0 context.Context, p1 address.Address, p2 *bitfield.BitField, p3 types.TipSetKey) ([]*miner.SectorOnChainInfo, error) `perm:"read"` - StateNetworkVersion func(p0 context.Context, p1 types.TipSetKey) (apitypes.NetworkVersion, error) `perm:"read"` + StateNetworkName func(p0 context.Context) (dtypes.NetworkName, error) `perm:"read"` - StateReadState func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (*ActorState, error) `perm:"read"` + StateNetworkVersion func(p0 context.Context, p1 types.TipSetKey) (apitypes.NetworkVersion, error) `perm:"read"` - StateReplay func(p0 context.Context, p1 types.TipSetKey, p2 cid.Cid) (*InvocResult, error) `perm:"read"` + StateReadState func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (*ActorState, error) `perm:"read"` - StateSearchMsg func(p0 context.Context, p1 types.TipSetKey, p2 cid.Cid, p3 abi.ChainEpoch, p4 bool) (*MsgLookup, error) `perm:"read"` + StateReplay func(p0 context.Context, p1 types.TipSetKey, p2 cid.Cid) (*InvocResult, error) `perm:"read"` - StateSectorExpiration func(p0 context.Context, p1 address.Address, p2 abi.SectorNumber, p3 types.TipSetKey) (*lminer.SectorExpiration, error) `perm:"read"` + StateSearchMsg func(p0 context.Context, p1 types.TipSetKey, p2 cid.Cid, p3 abi.ChainEpoch, p4 bool) (*MsgLookup, error) `perm:"read"` - StateSectorGetInfo func(p0 context.Context, p1 address.Address, p2 abi.SectorNumber, p3 types.TipSetKey) (*miner.SectorOnChainInfo, error) `perm:"read"` + StateSectorExpiration func(p0 context.Context, p1 address.Address, p2 abi.SectorNumber, p3 types.TipSetKey) (*lminer.SectorExpiration, error) `perm:"read"` - StateSectorPartition func(p0 context.Context, p1 address.Address, p2 abi.SectorNumber, p3 types.TipSetKey) (*lminer.SectorLocation, error) `perm:"read"` + StateSectorGetInfo func(p0 context.Context, p1 address.Address, p2 abi.SectorNumber, p3 types.TipSetKey) (*miner.SectorOnChainInfo, error) `perm:"read"` - StateSectorPreCommitInfo func(p0 context.Context, p1 address.Address, p2 abi.SectorNumber, p3 types.TipSetKey) (*miner.SectorPreCommitOnChainInfo, error) `perm:"read"` + StateSectorPartition func(p0 context.Context, p1 address.Address, p2 abi.SectorNumber, p3 types.TipSetKey) (*lminer.SectorLocation, error) `perm:"read"` - StateVMCirculatingSupplyInternal func(p0 context.Context, p1 types.TipSetKey) (CirculatingSupply, error) `perm:"read"` + StateSectorPreCommitInfo func(p0 context.Context, p1 address.Address, p2 abi.SectorNumber, p3 types.TipSetKey) (*miner.SectorPreCommitOnChainInfo, error) `perm:"read"` - StateVerifiedClientStatus func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (*abi.StoragePower, error) `perm:"read"` + StateVMCirculatingSupplyInternal func(p0 context.Context, p1 types.TipSetKey) (CirculatingSupply, error) `perm:"read"` - StateVerifiedRegistryRootKey func(p0 context.Context, p1 types.TipSetKey) (address.Address, error) `perm:"read"` + StateVerifiedClientStatus func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (*abi.StoragePower, error) `perm:"read"` - StateVerifierStatus func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (*abi.StoragePower, error) `perm:"read"` + StateVerifiedRegistryRootKey func(p0 context.Context, p1 types.TipSetKey) (address.Address, error) `perm:"read"` - StateWaitMsg func(p0 context.Context, p1 cid.Cid, p2 uint64, p3 abi.ChainEpoch, p4 bool) (*MsgLookup, error) `perm:"read"` + StateVerifierStatus func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (*abi.StoragePower, error) `perm:"read"` - SyncCheckBad func(p0 context.Context, p1 cid.Cid) (string, error) `perm:"read"` + StateWaitMsg func(p0 context.Context, p1 cid.Cid, p2 uint64, p3 abi.ChainEpoch, p4 bool) (*MsgLookup, error) `perm:"read"` - SyncCheckpoint func(p0 context.Context, p1 types.TipSetKey) error `perm:"admin"` + SyncCheckBad func(p0 context.Context, p1 cid.Cid) (string, error) `perm:"read"` - SyncIncomingBlocks func(p0 context.Context) (<-chan *types.BlockHeader, error) `perm:"read"` + SyncCheckpoint func(p0 context.Context, p1 types.TipSetKey) error `perm:"admin"` - SyncMarkBad func(p0 context.Context, p1 cid.Cid) error `perm:"admin"` + SyncIncomingBlocks func(p0 context.Context) (<-chan *types.BlockHeader, error) `perm:"read"` - SyncState func(p0 context.Context) (*SyncState, error) `perm:"read"` + SyncMarkBad func(p0 context.Context, p1 cid.Cid) error `perm:"admin"` - SyncSubmitBlock func(p0 context.Context, p1 *types.BlockMsg) error `perm:"write"` + SyncState func(p0 context.Context) (*SyncState, error) `perm:"read"` - SyncUnmarkAllBad func(p0 context.Context) error `perm:"admin"` + SyncSubmitBlock func(p0 context.Context, p1 *types.BlockMsg) error `perm:"write"` - SyncUnmarkBad func(p0 context.Context, p1 cid.Cid) error `perm:"admin"` + SyncUnmarkAllBad func(p0 context.Context) error `perm:"admin"` - SyncValidateTipset func(p0 context.Context, p1 types.TipSetKey) (bool, error) `perm:"read"` + SyncUnmarkBad func(p0 context.Context, p1 cid.Cid) error `perm:"admin"` - WalletBalance func(p0 context.Context, p1 address.Address) (types.BigInt, error) `perm:"read"` + SyncValidateTipset func(p0 context.Context, p1 types.TipSetKey) (bool, error) `perm:"read"` - WalletDefaultAddress func(p0 context.Context) (address.Address, error) `perm:"write"` + WalletBalance func(p0 context.Context, p1 address.Address) (types.BigInt, error) `perm:"read"` - WalletDelete func(p0 context.Context, p1 address.Address) error `perm:"admin"` + WalletDefaultAddress func(p0 context.Context) (address.Address, error) `perm:"write"` - WalletExport func(p0 context.Context, p1 address.Address) (*types.KeyInfo, error) `perm:"admin"` + WalletDelete func(p0 context.Context, p1 address.Address) error `perm:"admin"` - WalletHas func(p0 context.Context, p1 address.Address) (bool, error) `perm:"write"` + WalletExport func(p0 context.Context, p1 address.Address) (*types.KeyInfo, error) `perm:"admin"` - WalletImport func(p0 context.Context, p1 *types.KeyInfo) (address.Address, error) `perm:"admin"` + WalletHas func(p0 context.Context, p1 address.Address) (bool, error) `perm:"write"` - WalletList func(p0 context.Context) ([]address.Address, error) `perm:"write"` + WalletImport func(p0 context.Context, p1 *types.KeyInfo) (address.Address, error) `perm:"admin"` - WalletNew func(p0 context.Context, p1 types.KeyType) (address.Address, error) `perm:"write"` + WalletList func(p0 context.Context) ([]address.Address, error) `perm:"write"` - WalletSetDefault func(p0 context.Context, p1 address.Address) error `perm:"write"` + WalletNew func(p0 context.Context, p1 types.KeyType) (address.Address, error) `perm:"write"` - WalletSign func(p0 context.Context, p1 address.Address, p2 []byte) (*crypto.Signature, error) `perm:"sign"` + WalletSetDefault func(p0 context.Context, p1 address.Address) error `perm:"write"` - WalletSignMessage func(p0 context.Context, p1 address.Address, p2 *types.Message) (*types.SignedMessage, error) `perm:"sign"` + WalletSign func(p0 context.Context, p1 address.Address, p2 []byte) (*crypto.Signature, error) `perm:"sign"` - WalletValidateAddress func(p0 context.Context, p1 string) (address.Address, error) `perm:"read"` + WalletSignMessage func(p0 context.Context, p1 address.Address, p2 *types.Message) (*types.SignedMessage, error) `perm:"sign"` - WalletVerify func(p0 context.Context, p1 address.Address, p2 []byte, p3 *crypto.Signature) (bool, error) `perm:"read"` - } + WalletValidateAddress func(p0 context.Context, p1 string) (address.Address, error) `perm:"read"` + + WalletVerify func(p0 context.Context, p1 address.Address, p2 []byte, p3 *crypto.Signature) (bool, error) `perm:"read"` + + Web3ClientVersion func(p0 context.Context) (string, error) `perm:"read"` } type FullNodeStub struct { @@ -592,215 +614,227 @@ type FullNodeStub struct { } type GatewayStruct struct { - Internal struct { - ChainGetBlockMessages func(p0 context.Context, p1 cid.Cid) (*BlockMessages, error) `` + Internal GatewayMethods +} - ChainGetGenesis func(p0 context.Context) (*types.TipSet, error) `` +type GatewayMethods struct { + ChainGetBlockMessages func(p0 context.Context, p1 cid.Cid) (*BlockMessages, error) `` - ChainGetMessage func(p0 context.Context, p1 cid.Cid) (*types.Message, error) `` + ChainGetGenesis func(p0 context.Context) (*types.TipSet, error) `` - ChainGetParentMessages func(p0 context.Context, p1 cid.Cid) ([]Message, error) `` + ChainGetMessage func(p0 context.Context, p1 cid.Cid) (*types.Message, error) `` - ChainGetParentReceipts func(p0 context.Context, p1 cid.Cid) ([]*types.MessageReceipt, error) `` + ChainGetParentMessages func(p0 context.Context, p1 cid.Cid) ([]Message, error) `` - ChainGetPath func(p0 context.Context, p1 types.TipSetKey, p2 types.TipSetKey) ([]*HeadChange, error) `` + ChainGetParentReceipts func(p0 context.Context, p1 cid.Cid) ([]*types.MessageReceipt, error) `` - ChainGetTipSet func(p0 context.Context, p1 types.TipSetKey) (*types.TipSet, error) `` + ChainGetPath func(p0 context.Context, p1 types.TipSetKey, p2 types.TipSetKey) ([]*HeadChange, error) `` - ChainGetTipSetAfterHeight func(p0 context.Context, p1 abi.ChainEpoch, p2 types.TipSetKey) (*types.TipSet, error) `` + ChainGetTipSet func(p0 context.Context, p1 types.TipSetKey) (*types.TipSet, error) `` - ChainGetTipSetByHeight func(p0 context.Context, p1 abi.ChainEpoch, p2 types.TipSetKey) (*types.TipSet, error) `` + ChainGetTipSetAfterHeight func(p0 context.Context, p1 abi.ChainEpoch, p2 types.TipSetKey) (*types.TipSet, error) `` - ChainHasObj func(p0 context.Context, p1 cid.Cid) (bool, error) `` + ChainGetTipSetByHeight func(p0 context.Context, p1 abi.ChainEpoch, p2 types.TipSetKey) (*types.TipSet, error) `` - ChainHead func(p0 context.Context) (*types.TipSet, error) `` + ChainHasObj func(p0 context.Context, p1 cid.Cid) (bool, error) `` - ChainNotify func(p0 context.Context) (<-chan []*HeadChange, error) `` + ChainHead func(p0 context.Context) (*types.TipSet, error) `` - ChainPutObj func(p0 context.Context, p1 blocks.Block) error `` + ChainNotify func(p0 context.Context) (<-chan []*HeadChange, error) `` - ChainReadObj func(p0 context.Context, p1 cid.Cid) ([]byte, error) `` + ChainPutObj func(p0 context.Context, p1 blocks.Block) error `` - Discover func(p0 context.Context) (apitypes.OpenRPCDocument, error) `` + ChainReadObj func(p0 context.Context, p1 cid.Cid) ([]byte, error) `` - EthAccounts func(p0 context.Context) ([]ethtypes.EthAddress, error) `` + Discover func(p0 context.Context) (apitypes.OpenRPCDocument, error) `` - EthBlockNumber func(p0 context.Context) (ethtypes.EthUint64, error) `` + EthAccounts func(p0 context.Context) ([]ethtypes.EthAddress, error) `` - EthCall func(p0 context.Context, p1 ethtypes.EthCall, p2 string) (ethtypes.EthBytes, error) `` + EthBlockNumber func(p0 context.Context) (ethtypes.EthUint64, error) `` - EthChainId func(p0 context.Context) (ethtypes.EthUint64, error) `` + EthCall func(p0 context.Context, p1 ethtypes.EthCall, p2 string) (ethtypes.EthBytes, error) `` - EthEstimateGas func(p0 context.Context, p1 ethtypes.EthCall) (ethtypes.EthUint64, error) `` + EthChainId func(p0 context.Context) (ethtypes.EthUint64, error) `` - EthFeeHistory func(p0 context.Context, p1 ethtypes.EthUint64, p2 string, p3 []float64) (ethtypes.EthFeeHistory, error) `` + EthEstimateGas func(p0 context.Context, p1 ethtypes.EthCall) (ethtypes.EthUint64, error) `` - EthGasPrice func(p0 context.Context) (ethtypes.EthBigInt, error) `` + EthFeeHistory func(p0 context.Context, p1 ethtypes.EthUint64, p2 string, p3 []float64) (ethtypes.EthFeeHistory, error) `` - EthGetBalance func(p0 context.Context, p1 ethtypes.EthAddress, p2 string) (ethtypes.EthBigInt, error) `` + EthGasPrice func(p0 context.Context) (ethtypes.EthBigInt, error) `` - EthGetBlockByHash func(p0 context.Context, p1 ethtypes.EthHash, p2 bool) (ethtypes.EthBlock, error) `` + EthGetBalance func(p0 context.Context, p1 ethtypes.EthAddress, p2 string) (ethtypes.EthBigInt, error) `` - EthGetBlockByNumber func(p0 context.Context, p1 string, p2 bool) (ethtypes.EthBlock, error) `` + EthGetBlockByHash func(p0 context.Context, p1 ethtypes.EthHash, p2 bool) (ethtypes.EthBlock, error) `` - EthGetBlockTransactionCountByHash func(p0 context.Context, p1 ethtypes.EthHash) (ethtypes.EthUint64, error) `` + EthGetBlockByNumber func(p0 context.Context, p1 string, p2 bool) (ethtypes.EthBlock, error) `` - EthGetBlockTransactionCountByNumber func(p0 context.Context, p1 ethtypes.EthUint64) (ethtypes.EthUint64, error) `` + EthGetBlockTransactionCountByHash func(p0 context.Context, p1 ethtypes.EthHash) (ethtypes.EthUint64, error) `` - EthGetCode func(p0 context.Context, p1 ethtypes.EthAddress, p2 string) (ethtypes.EthBytes, error) `` + EthGetBlockTransactionCountByNumber func(p0 context.Context, p1 ethtypes.EthUint64) (ethtypes.EthUint64, error) `` - EthGetFilterChanges func(p0 context.Context, p1 ethtypes.EthFilterID) (*ethtypes.EthFilterResult, error) `` + EthGetCode func(p0 context.Context, p1 ethtypes.EthAddress, p2 string) (ethtypes.EthBytes, error) `` - EthGetFilterLogs func(p0 context.Context, p1 ethtypes.EthFilterID) (*ethtypes.EthFilterResult, error) `` + EthGetFilterChanges func(p0 context.Context, p1 ethtypes.EthFilterID) (*ethtypes.EthFilterResult, error) `` - EthGetLogs func(p0 context.Context, p1 *ethtypes.EthFilterSpec) (*ethtypes.EthFilterResult, error) `` + EthGetFilterLogs func(p0 context.Context, p1 ethtypes.EthFilterID) (*ethtypes.EthFilterResult, error) `` - EthGetStorageAt func(p0 context.Context, p1 ethtypes.EthAddress, p2 ethtypes.EthBytes, p3 string) (ethtypes.EthBytes, error) `` + EthGetLogs func(p0 context.Context, p1 *ethtypes.EthFilterSpec) (*ethtypes.EthFilterResult, error) `` - EthGetTransactionByBlockHashAndIndex func(p0 context.Context, p1 ethtypes.EthHash, p2 ethtypes.EthUint64) (ethtypes.EthTx, error) `` + EthGetMessageCidByTransactionHash func(p0 context.Context, p1 *ethtypes.EthHash) (*cid.Cid, error) `` - EthGetTransactionByBlockNumberAndIndex func(p0 context.Context, p1 ethtypes.EthUint64, p2 ethtypes.EthUint64) (ethtypes.EthTx, error) `` + EthGetStorageAt func(p0 context.Context, p1 ethtypes.EthAddress, p2 ethtypes.EthBytes, p3 string) (ethtypes.EthBytes, error) `` - EthGetTransactionByHash func(p0 context.Context, p1 *ethtypes.EthHash) (*ethtypes.EthTx, error) `` + EthGetTransactionByBlockHashAndIndex func(p0 context.Context, p1 ethtypes.EthHash, p2 ethtypes.EthUint64) (ethtypes.EthTx, error) `` - EthGetTransactionCount func(p0 context.Context, p1 ethtypes.EthAddress, p2 string) (ethtypes.EthUint64, error) `` + EthGetTransactionByBlockNumberAndIndex func(p0 context.Context, p1 ethtypes.EthUint64, p2 ethtypes.EthUint64) (ethtypes.EthTx, error) `` - EthGetTransactionReceipt func(p0 context.Context, p1 ethtypes.EthHash) (*EthTxReceipt, error) `` + EthGetTransactionByHash func(p0 context.Context, p1 *ethtypes.EthHash) (*ethtypes.EthTx, error) `` - EthMaxPriorityFeePerGas func(p0 context.Context) (ethtypes.EthBigInt, error) `` + EthGetTransactionCount func(p0 context.Context, p1 ethtypes.EthAddress, p2 string) (ethtypes.EthUint64, error) `` - EthNewBlockFilter func(p0 context.Context) (ethtypes.EthFilterID, error) `` + EthGetTransactionHashByCid func(p0 context.Context, p1 cid.Cid) (*ethtypes.EthHash, error) `` - EthNewFilter func(p0 context.Context, p1 *ethtypes.EthFilterSpec) (ethtypes.EthFilterID, error) `` + EthGetTransactionReceipt func(p0 context.Context, p1 ethtypes.EthHash) (*EthTxReceipt, error) `` - EthNewPendingTransactionFilter func(p0 context.Context) (ethtypes.EthFilterID, error) `` + EthMaxPriorityFeePerGas func(p0 context.Context) (ethtypes.EthBigInt, error) `` - EthProtocolVersion func(p0 context.Context) (ethtypes.EthUint64, error) `` + EthNewBlockFilter func(p0 context.Context) (ethtypes.EthFilterID, error) `` - EthSendRawTransaction func(p0 context.Context, p1 ethtypes.EthBytes) (ethtypes.EthHash, error) `` + EthNewFilter func(p0 context.Context, p1 *ethtypes.EthFilterSpec) (ethtypes.EthFilterID, error) `` - EthSubscribe func(p0 context.Context, p1 string, p2 *ethtypes.EthSubscriptionParams) (<-chan ethtypes.EthSubscriptionResponse, error) `` + EthNewPendingTransactionFilter func(p0 context.Context) (ethtypes.EthFilterID, error) `` - EthUninstallFilter func(p0 context.Context, p1 ethtypes.EthFilterID) (bool, error) `` + EthProtocolVersion func(p0 context.Context) (ethtypes.EthUint64, error) `` - EthUnsubscribe func(p0 context.Context, p1 ethtypes.EthSubscriptionID) (bool, error) `` + EthSendRawTransaction func(p0 context.Context, p1 ethtypes.EthBytes) (ethtypes.EthHash, error) `` - GasEstimateMessageGas func(p0 context.Context, p1 *types.Message, p2 *MessageSendSpec, p3 types.TipSetKey) (*types.Message, error) `` + EthSubscribe func(p0 context.Context, p1 jsonrpc.RawParams) (ethtypes.EthSubscriptionID, error) `` - MpoolPush func(p0 context.Context, p1 *types.SignedMessage) (cid.Cid, error) `` + EthUninstallFilter func(p0 context.Context, p1 ethtypes.EthFilterID) (bool, error) `` - MsigGetAvailableBalance func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (types.BigInt, error) `` + EthUnsubscribe func(p0 context.Context, p1 ethtypes.EthSubscriptionID) (bool, error) `` - MsigGetPending func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) ([]*MsigTransaction, error) `` + GasEstimateMessageGas func(p0 context.Context, p1 *types.Message, p2 *MessageSendSpec, p3 types.TipSetKey) (*types.Message, error) `` - MsigGetVested func(p0 context.Context, p1 address.Address, p2 types.TipSetKey, p3 types.TipSetKey) (types.BigInt, error) `` + MpoolPush func(p0 context.Context, p1 *types.SignedMessage) (cid.Cid, error) `` - MsigGetVestingSchedule func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (MsigVesting, error) `` + MsigGetAvailableBalance func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (types.BigInt, error) `` - NetListening func(p0 context.Context) (bool, error) `` + MsigGetPending func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) ([]*MsigTransaction, error) `` - NetVersion func(p0 context.Context) (string, error) `` + MsigGetVested func(p0 context.Context, p1 address.Address, p2 types.TipSetKey, p3 types.TipSetKey) (types.BigInt, error) `` - StateAccountKey func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (address.Address, error) `` + MsigGetVestingSchedule func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (MsigVesting, error) `` - StateDealProviderCollateralBounds func(p0 context.Context, p1 abi.PaddedPieceSize, p2 bool, p3 types.TipSetKey) (DealCollateralBounds, error) `` + NetListening func(p0 context.Context) (bool, error) `` - StateGetActor func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (*types.Actor, error) `` + NetVersion func(p0 context.Context) (string, error) `` - StateListMiners func(p0 context.Context, p1 types.TipSetKey) ([]address.Address, error) `` + StateAccountKey func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (address.Address, error) `` - StateLookupID func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (address.Address, error) `` + StateDealProviderCollateralBounds func(p0 context.Context, p1 abi.PaddedPieceSize, p2 bool, p3 types.TipSetKey) (DealCollateralBounds, error) `` - StateMarketBalance func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (MarketBalance, error) `` + StateGetActor func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (*types.Actor, error) `` - StateMarketStorageDeal func(p0 context.Context, p1 abi.DealID, p2 types.TipSetKey) (*MarketDeal, error) `` + StateListMiners func(p0 context.Context, p1 types.TipSetKey) ([]address.Address, error) `` - StateMinerInfo func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (MinerInfo, error) `` + StateLookupID func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (address.Address, error) `` - StateMinerPower func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (*MinerPower, error) `` + StateMarketBalance func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (MarketBalance, error) `` - StateMinerProvingDeadline func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (*dline.Info, error) `` + StateMarketStorageDeal func(p0 context.Context, p1 abi.DealID, p2 types.TipSetKey) (*MarketDeal, error) `` - StateNetworkVersion func(p0 context.Context, p1 types.TipSetKey) (apitypes.NetworkVersion, error) `` + StateMinerInfo func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (MinerInfo, error) `` - StateReadState func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (*ActorState, error) `perm:"read"` + StateMinerPower func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (*MinerPower, error) `` - StateSearchMsg func(p0 context.Context, p1 types.TipSetKey, p2 cid.Cid, p3 abi.ChainEpoch, p4 bool) (*MsgLookup, error) `` + StateMinerProvingDeadline func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (*dline.Info, error) `` - StateSectorGetInfo func(p0 context.Context, p1 address.Address, p2 abi.SectorNumber, p3 types.TipSetKey) (*miner.SectorOnChainInfo, error) `` + StateNetworkVersion func(p0 context.Context, p1 types.TipSetKey) (apitypes.NetworkVersion, error) `` - StateVerifiedClientStatus func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (*abi.StoragePower, error) `` + StateReadState func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (*ActorState, error) `perm:"read"` - StateWaitMsg func(p0 context.Context, p1 cid.Cid, p2 uint64, p3 abi.ChainEpoch, p4 bool) (*MsgLookup, error) `` + StateSearchMsg func(p0 context.Context, p1 types.TipSetKey, p2 cid.Cid, p3 abi.ChainEpoch, p4 bool) (*MsgLookup, error) `` - Version func(p0 context.Context) (APIVersion, error) `` + StateSectorGetInfo func(p0 context.Context, p1 address.Address, p2 abi.SectorNumber, p3 types.TipSetKey) (*miner.SectorOnChainInfo, error) `` - WalletBalance func(p0 context.Context, p1 address.Address) (types.BigInt, error) `` - } + StateVerifiedClientStatus func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (*abi.StoragePower, error) `` + + StateWaitMsg func(p0 context.Context, p1 cid.Cid, p2 uint64, p3 abi.ChainEpoch, p4 bool) (*MsgLookup, error) `` + + Version func(p0 context.Context) (APIVersion, error) `` + + WalletBalance func(p0 context.Context, p1 address.Address) (types.BigInt, error) `` + + Web3ClientVersion func(p0 context.Context) (string, error) `` } type GatewayStub struct { } type NetStruct struct { - Internal struct { - ID func(p0 context.Context) (peer.ID, error) `perm:"read"` + Internal NetMethods +} - NetAddrsListen func(p0 context.Context) (peer.AddrInfo, error) `perm:"read"` +type NetMethods struct { + ID func(p0 context.Context) (peer.ID, error) `perm:"read"` - NetAgentVersion func(p0 context.Context, p1 peer.ID) (string, error) `perm:"read"` + NetAddrsListen func(p0 context.Context) (peer.AddrInfo, error) `perm:"read"` - NetAutoNatStatus func(p0 context.Context) (NatInfo, error) `perm:"read"` + NetAgentVersion func(p0 context.Context, p1 peer.ID) (string, error) `perm:"read"` - NetBandwidthStats func(p0 context.Context) (metrics.Stats, error) `perm:"read"` + NetAutoNatStatus func(p0 context.Context) (NatInfo, error) `perm:"read"` - NetBandwidthStatsByPeer func(p0 context.Context) (map[string]metrics.Stats, error) `perm:"read"` + NetBandwidthStats func(p0 context.Context) (metrics.Stats, error) `perm:"read"` - NetBandwidthStatsByProtocol func(p0 context.Context) (map[protocol.ID]metrics.Stats, error) `perm:"read"` + NetBandwidthStatsByPeer func(p0 context.Context) (map[string]metrics.Stats, error) `perm:"read"` - NetBlockAdd func(p0 context.Context, p1 NetBlockList) error `perm:"admin"` + NetBandwidthStatsByProtocol func(p0 context.Context) (map[protocol.ID]metrics.Stats, error) `perm:"read"` - NetBlockList func(p0 context.Context) (NetBlockList, error) `perm:"read"` + NetBlockAdd func(p0 context.Context, p1 NetBlockList) error `perm:"admin"` - NetBlockRemove func(p0 context.Context, p1 NetBlockList) error `perm:"admin"` + NetBlockList func(p0 context.Context) (NetBlockList, error) `perm:"read"` - NetConnect func(p0 context.Context, p1 peer.AddrInfo) error `perm:"write"` + NetBlockRemove func(p0 context.Context, p1 NetBlockList) error `perm:"admin"` - NetConnectedness func(p0 context.Context, p1 peer.ID) (network.Connectedness, error) `perm:"read"` + NetConnect func(p0 context.Context, p1 peer.AddrInfo) error `perm:"write"` - NetDisconnect func(p0 context.Context, p1 peer.ID) error `perm:"write"` + NetConnectedness func(p0 context.Context, p1 peer.ID) (network.Connectedness, error) `perm:"read"` - NetFindPeer func(p0 context.Context, p1 peer.ID) (peer.AddrInfo, error) `perm:"read"` + NetDisconnect func(p0 context.Context, p1 peer.ID) error `perm:"write"` - NetLimit func(p0 context.Context, p1 string) (NetLimit, error) `perm:"read"` + NetFindPeer func(p0 context.Context, p1 peer.ID) (peer.AddrInfo, error) `perm:"read"` - NetPeerInfo func(p0 context.Context, p1 peer.ID) (*ExtendedPeerInfo, error) `perm:"read"` + NetLimit func(p0 context.Context, p1 string) (NetLimit, error) `perm:"read"` - NetPeers func(p0 context.Context) ([]peer.AddrInfo, error) `perm:"read"` + NetPeerInfo func(p0 context.Context, p1 peer.ID) (*ExtendedPeerInfo, error) `perm:"read"` - NetPing func(p0 context.Context, p1 peer.ID) (time.Duration, error) `perm:"read"` + NetPeers func(p0 context.Context) ([]peer.AddrInfo, error) `perm:"read"` - NetProtectAdd func(p0 context.Context, p1 []peer.ID) error `perm:"admin"` + NetPing func(p0 context.Context, p1 peer.ID) (time.Duration, error) `perm:"read"` - NetProtectList func(p0 context.Context) ([]peer.ID, error) `perm:"read"` + NetProtectAdd func(p0 context.Context, p1 []peer.ID) error `perm:"admin"` - NetProtectRemove func(p0 context.Context, p1 []peer.ID) error `perm:"admin"` + NetProtectList func(p0 context.Context) ([]peer.ID, error) `perm:"read"` - NetPubsubScores func(p0 context.Context) ([]PubsubScore, error) `perm:"read"` + NetProtectRemove func(p0 context.Context, p1 []peer.ID) error `perm:"admin"` - NetSetLimit func(p0 context.Context, p1 string, p2 NetLimit) error `perm:"admin"` + NetPubsubScores func(p0 context.Context) ([]PubsubScore, error) `perm:"read"` - NetStat func(p0 context.Context, p1 string) (NetStat, error) `perm:"read"` - } + NetSetLimit func(p0 context.Context, p1 string, p2 NetLimit) error `perm:"admin"` + + NetStat func(p0 context.Context, p1 string) (NetStat, error) `perm:"read"` } type NetStub struct { } type SignableStruct struct { - Internal struct { - Sign func(p0 context.Context, p1 SignFunc) error `` - } + Internal SignableMethods +} + +type SignableMethods struct { + Sign func(p0 context.Context, p1 SignFunc) error `` } type SignableStub struct { @@ -811,271 +845,273 @@ type StorageMinerStruct struct { NetStruct - Internal struct { - ActorAddress func(p0 context.Context) (address.Address, error) `perm:"read"` + Internal StorageMinerMethods +} - ActorAddressConfig func(p0 context.Context) (AddressConfig, error) `perm:"read"` +type StorageMinerMethods struct { + ActorAddress func(p0 context.Context) (address.Address, error) `perm:"read"` - ActorSectorSize func(p0 context.Context, p1 address.Address) (abi.SectorSize, error) `perm:"read"` + ActorAddressConfig func(p0 context.Context) (AddressConfig, error) `perm:"read"` - ActorWithdrawBalance func(p0 context.Context, p1 abi.TokenAmount) (cid.Cid, error) `perm:"admin"` + ActorSectorSize func(p0 context.Context, p1 address.Address) (abi.SectorSize, error) `perm:"read"` - BeneficiaryWithdrawBalance func(p0 context.Context, p1 abi.TokenAmount) (cid.Cid, error) `perm:"admin"` + ActorWithdrawBalance func(p0 context.Context, p1 abi.TokenAmount) (cid.Cid, error) `perm:"admin"` - CheckProvable func(p0 context.Context, p1 abi.RegisteredPoStProof, p2 []storiface.SectorRef) (map[abi.SectorNumber]string, error) `perm:"admin"` + BeneficiaryWithdrawBalance func(p0 context.Context, p1 abi.TokenAmount) (cid.Cid, error) `perm:"admin"` - ComputeDataCid func(p0 context.Context, p1 abi.UnpaddedPieceSize, p2 storiface.Data) (abi.PieceInfo, error) `perm:"admin"` + CheckProvable func(p0 context.Context, p1 abi.RegisteredPoStProof, p2 []storiface.SectorRef) (map[abi.SectorNumber]string, error) `perm:"admin"` - ComputeProof func(p0 context.Context, p1 []builtinactors.ExtendedSectorInfo, p2 abi.PoStRandomness, p3 abi.ChainEpoch, p4 abinetwork.Version) ([]builtinactors.PoStProof, error) `perm:"read"` + ComputeDataCid func(p0 context.Context, p1 abi.UnpaddedPieceSize, p2 storiface.Data) (abi.PieceInfo, error) `perm:"admin"` - ComputeWindowPoSt func(p0 context.Context, p1 uint64, p2 types.TipSetKey) ([]miner.SubmitWindowedPoStParams, error) `perm:"admin"` + ComputeProof func(p0 context.Context, p1 []builtinactors.ExtendedSectorInfo, p2 abi.PoStRandomness, p3 abi.ChainEpoch, p4 abinetwork.Version) ([]builtinactors.PoStProof, error) `perm:"read"` - CreateBackup func(p0 context.Context, p1 string) error `perm:"admin"` + ComputeWindowPoSt func(p0 context.Context, p1 uint64, p2 types.TipSetKey) ([]miner.SubmitWindowedPoStParams, error) `perm:"admin"` - DagstoreGC func(p0 context.Context) ([]DagstoreShardResult, error) `perm:"admin"` + CreateBackup func(p0 context.Context, p1 string) error `perm:"admin"` - DagstoreInitializeAll func(p0 context.Context, p1 DagstoreInitializeAllParams) (<-chan DagstoreInitializeAllEvent, error) `perm:"write"` + DagstoreGC func(p0 context.Context) ([]DagstoreShardResult, error) `perm:"admin"` - DagstoreInitializeShard func(p0 context.Context, p1 string) error `perm:"write"` + DagstoreInitializeAll func(p0 context.Context, p1 DagstoreInitializeAllParams) (<-chan DagstoreInitializeAllEvent, error) `perm:"write"` - DagstoreListShards func(p0 context.Context) ([]DagstoreShardInfo, error) `perm:"read"` + DagstoreInitializeShard func(p0 context.Context, p1 string) error `perm:"write"` - DagstoreLookupPieces func(p0 context.Context, p1 cid.Cid) ([]DagstoreShardInfo, error) `perm:"admin"` + DagstoreListShards func(p0 context.Context) ([]DagstoreShardInfo, error) `perm:"read"` - DagstoreRecoverShard func(p0 context.Context, p1 string) error `perm:"write"` + DagstoreLookupPieces func(p0 context.Context, p1 cid.Cid) ([]DagstoreShardInfo, error) `perm:"admin"` - DagstoreRegisterShard func(p0 context.Context, p1 string) error `perm:"admin"` + DagstoreRecoverShard func(p0 context.Context, p1 string) error `perm:"write"` - DealsConsiderOfflineRetrievalDeals func(p0 context.Context) (bool, error) `perm:"admin"` + DagstoreRegisterShard func(p0 context.Context, p1 string) error `perm:"admin"` - DealsConsiderOfflineStorageDeals func(p0 context.Context) (bool, error) `perm:"admin"` + DealsConsiderOfflineRetrievalDeals func(p0 context.Context) (bool, error) `perm:"admin"` - DealsConsiderOnlineRetrievalDeals func(p0 context.Context) (bool, error) `perm:"admin"` + DealsConsiderOfflineStorageDeals func(p0 context.Context) (bool, error) `perm:"admin"` - DealsConsiderOnlineStorageDeals func(p0 context.Context) (bool, error) `perm:"admin"` + DealsConsiderOnlineRetrievalDeals func(p0 context.Context) (bool, error) `perm:"admin"` - DealsConsiderUnverifiedStorageDeals func(p0 context.Context) (bool, error) `perm:"admin"` + DealsConsiderOnlineStorageDeals func(p0 context.Context) (bool, error) `perm:"admin"` - DealsConsiderVerifiedStorageDeals func(p0 context.Context) (bool, error) `perm:"admin"` + DealsConsiderUnverifiedStorageDeals func(p0 context.Context) (bool, error) `perm:"admin"` - DealsImportData func(p0 context.Context, p1 cid.Cid, p2 string) error `perm:"admin"` + DealsConsiderVerifiedStorageDeals func(p0 context.Context) (bool, error) `perm:"admin"` - DealsList func(p0 context.Context) ([]*MarketDeal, error) `perm:"admin"` + DealsImportData func(p0 context.Context, p1 cid.Cid, p2 string) error `perm:"admin"` - DealsPieceCidBlocklist func(p0 context.Context) ([]cid.Cid, error) `perm:"admin"` + DealsList func(p0 context.Context) ([]*MarketDeal, error) `perm:"admin"` - DealsSetConsiderOfflineRetrievalDeals func(p0 context.Context, p1 bool) error `perm:"admin"` + DealsPieceCidBlocklist func(p0 context.Context) ([]cid.Cid, error) `perm:"admin"` - DealsSetConsiderOfflineStorageDeals func(p0 context.Context, p1 bool) error `perm:"admin"` + DealsSetConsiderOfflineRetrievalDeals func(p0 context.Context, p1 bool) error `perm:"admin"` - DealsSetConsiderOnlineRetrievalDeals func(p0 context.Context, p1 bool) error `perm:"admin"` + DealsSetConsiderOfflineStorageDeals func(p0 context.Context, p1 bool) error `perm:"admin"` - DealsSetConsiderOnlineStorageDeals func(p0 context.Context, p1 bool) error `perm:"admin"` + DealsSetConsiderOnlineRetrievalDeals func(p0 context.Context, p1 bool) error `perm:"admin"` - DealsSetConsiderUnverifiedStorageDeals func(p0 context.Context, p1 bool) error `perm:"admin"` + DealsSetConsiderOnlineStorageDeals func(p0 context.Context, p1 bool) error `perm:"admin"` - DealsSetConsiderVerifiedStorageDeals func(p0 context.Context, p1 bool) error `perm:"admin"` + DealsSetConsiderUnverifiedStorageDeals func(p0 context.Context, p1 bool) error `perm:"admin"` - DealsSetPieceCidBlocklist func(p0 context.Context, p1 []cid.Cid) error `perm:"admin"` + DealsSetConsiderVerifiedStorageDeals func(p0 context.Context, p1 bool) error `perm:"admin"` - IndexerAnnounceAllDeals func(p0 context.Context) error `perm:"admin"` + DealsSetPieceCidBlocklist func(p0 context.Context, p1 []cid.Cid) error `perm:"admin"` - IndexerAnnounceDeal func(p0 context.Context, p1 cid.Cid) error `perm:"admin"` + IndexerAnnounceAllDeals func(p0 context.Context) error `perm:"admin"` - MarketCancelDataTransfer func(p0 context.Context, p1 datatransfer.TransferID, p2 peer.ID, p3 bool) error `perm:"write"` + IndexerAnnounceDeal func(p0 context.Context, p1 cid.Cid) error `perm:"admin"` - MarketDataTransferDiagnostics func(p0 context.Context, p1 peer.ID) (*TransferDiagnostics, error) `perm:"write"` + MarketCancelDataTransfer func(p0 context.Context, p1 datatransfer.TransferID, p2 peer.ID, p3 bool) error `perm:"write"` - MarketDataTransferUpdates func(p0 context.Context) (<-chan DataTransferChannel, error) `perm:"write"` + MarketDataTransferDiagnostics func(p0 context.Context, p1 peer.ID) (*TransferDiagnostics, error) `perm:"write"` - MarketGetAsk func(p0 context.Context) (*storagemarket.SignedStorageAsk, error) `perm:"read"` + MarketDataTransferUpdates func(p0 context.Context) (<-chan DataTransferChannel, error) `perm:"write"` - MarketGetDealUpdates func(p0 context.Context) (<-chan storagemarket.MinerDeal, error) `perm:"read"` + MarketGetAsk func(p0 context.Context) (*storagemarket.SignedStorageAsk, error) `perm:"read"` - MarketGetRetrievalAsk func(p0 context.Context) (*retrievalmarket.Ask, error) `perm:"read"` + MarketGetDealUpdates func(p0 context.Context) (<-chan storagemarket.MinerDeal, error) `perm:"read"` - MarketImportDealData func(p0 context.Context, p1 cid.Cid, p2 string) error `perm:"write"` + MarketGetRetrievalAsk func(p0 context.Context) (*retrievalmarket.Ask, error) `perm:"read"` - MarketListDataTransfers func(p0 context.Context) ([]DataTransferChannel, error) `perm:"write"` + MarketImportDealData func(p0 context.Context, p1 cid.Cid, p2 string) error `perm:"write"` - MarketListDeals func(p0 context.Context) ([]*MarketDeal, error) `perm:"read"` + MarketListDataTransfers func(p0 context.Context) ([]DataTransferChannel, error) `perm:"write"` - MarketListIncompleteDeals func(p0 context.Context) ([]storagemarket.MinerDeal, error) `perm:"read"` + MarketListDeals func(p0 context.Context) ([]*MarketDeal, error) `perm:"read"` - MarketListRetrievalDeals func(p0 context.Context) ([]retrievalmarket.ProviderDealState, error) `perm:"read"` + MarketListIncompleteDeals func(p0 context.Context) ([]storagemarket.MinerDeal, error) `perm:"read"` - MarketPendingDeals func(p0 context.Context) (PendingDealInfo, error) `perm:"write"` + MarketListRetrievalDeals func(p0 context.Context) ([]retrievalmarket.ProviderDealState, error) `perm:"read"` - MarketPublishPendingDeals func(p0 context.Context) error `perm:"admin"` + MarketPendingDeals func(p0 context.Context) (PendingDealInfo, error) `perm:"write"` - MarketRestartDataTransfer func(p0 context.Context, p1 datatransfer.TransferID, p2 peer.ID, p3 bool) error `perm:"write"` + MarketPublishPendingDeals func(p0 context.Context) error `perm:"admin"` - MarketRetryPublishDeal func(p0 context.Context, p1 cid.Cid) error `perm:"admin"` + MarketRestartDataTransfer func(p0 context.Context, p1 datatransfer.TransferID, p2 peer.ID, p3 bool) error `perm:"write"` - MarketSetAsk func(p0 context.Context, p1 types.BigInt, p2 types.BigInt, p3 abi.ChainEpoch, p4 abi.PaddedPieceSize, p5 abi.PaddedPieceSize) error `perm:"admin"` + MarketRetryPublishDeal func(p0 context.Context, p1 cid.Cid) error `perm:"admin"` - MarketSetRetrievalAsk func(p0 context.Context, p1 *retrievalmarket.Ask) error `perm:"admin"` + MarketSetAsk func(p0 context.Context, p1 types.BigInt, p2 types.BigInt, p3 abi.ChainEpoch, p4 abi.PaddedPieceSize, p5 abi.PaddedPieceSize) error `perm:"admin"` - MiningBase func(p0 context.Context) (*types.TipSet, error) `perm:"read"` + MarketSetRetrievalAsk func(p0 context.Context, p1 *retrievalmarket.Ask) error `perm:"admin"` - PiecesGetCIDInfo func(p0 context.Context, p1 cid.Cid) (*piecestore.CIDInfo, error) `perm:"read"` + MiningBase func(p0 context.Context) (*types.TipSet, error) `perm:"read"` - PiecesGetPieceInfo func(p0 context.Context, p1 cid.Cid) (*piecestore.PieceInfo, error) `perm:"read"` + PiecesGetCIDInfo func(p0 context.Context, p1 cid.Cid) (*piecestore.CIDInfo, error) `perm:"read"` - PiecesListCidInfos func(p0 context.Context) ([]cid.Cid, error) `perm:"read"` + PiecesGetPieceInfo func(p0 context.Context, p1 cid.Cid) (*piecestore.PieceInfo, error) `perm:"read"` - PiecesListPieces func(p0 context.Context) ([]cid.Cid, error) `perm:"read"` + PiecesListCidInfos func(p0 context.Context) ([]cid.Cid, error) `perm:"read"` - PledgeSector func(p0 context.Context) (abi.SectorID, error) `perm:"write"` + PiecesListPieces func(p0 context.Context) ([]cid.Cid, error) `perm:"read"` - RecoverFault func(p0 context.Context, p1 []abi.SectorNumber) ([]cid.Cid, error) `perm:"admin"` + PledgeSector func(p0 context.Context) (abi.SectorID, error) `perm:"write"` - ReturnAddPiece func(p0 context.Context, p1 storiface.CallID, p2 abi.PieceInfo, p3 *storiface.CallError) error `perm:"admin"` + RecoverFault func(p0 context.Context, p1 []abi.SectorNumber) ([]cid.Cid, error) `perm:"admin"` - ReturnDataCid func(p0 context.Context, p1 storiface.CallID, p2 abi.PieceInfo, p3 *storiface.CallError) error `perm:"admin"` + ReturnAddPiece func(p0 context.Context, p1 storiface.CallID, p2 abi.PieceInfo, p3 *storiface.CallError) error `perm:"admin"` - ReturnDownloadSector func(p0 context.Context, p1 storiface.CallID, p2 *storiface.CallError) error `perm:"admin"` + ReturnDataCid func(p0 context.Context, p1 storiface.CallID, p2 abi.PieceInfo, p3 *storiface.CallError) error `perm:"admin"` - ReturnFetch func(p0 context.Context, p1 storiface.CallID, p2 *storiface.CallError) error `perm:"admin"` + ReturnDownloadSector func(p0 context.Context, p1 storiface.CallID, p2 *storiface.CallError) error `perm:"admin"` - ReturnFinalizeReplicaUpdate func(p0 context.Context, p1 storiface.CallID, p2 *storiface.CallError) error `perm:"admin"` + ReturnFetch func(p0 context.Context, p1 storiface.CallID, p2 *storiface.CallError) error `perm:"admin"` - ReturnFinalizeSector func(p0 context.Context, p1 storiface.CallID, p2 *storiface.CallError) error `perm:"admin"` + ReturnFinalizeReplicaUpdate func(p0 context.Context, p1 storiface.CallID, p2 *storiface.CallError) error `perm:"admin"` - ReturnGenerateSectorKeyFromData func(p0 context.Context, p1 storiface.CallID, p2 *storiface.CallError) error `perm:"admin"` + ReturnFinalizeSector func(p0 context.Context, p1 storiface.CallID, p2 *storiface.CallError) error `perm:"admin"` - ReturnMoveStorage func(p0 context.Context, p1 storiface.CallID, p2 *storiface.CallError) error `perm:"admin"` + ReturnGenerateSectorKeyFromData func(p0 context.Context, p1 storiface.CallID, p2 *storiface.CallError) error `perm:"admin"` - ReturnProveReplicaUpdate1 func(p0 context.Context, p1 storiface.CallID, p2 storiface.ReplicaVanillaProofs, p3 *storiface.CallError) error `perm:"admin"` + ReturnMoveStorage func(p0 context.Context, p1 storiface.CallID, p2 *storiface.CallError) error `perm:"admin"` - ReturnProveReplicaUpdate2 func(p0 context.Context, p1 storiface.CallID, p2 storiface.ReplicaUpdateProof, p3 *storiface.CallError) error `perm:"admin"` + ReturnProveReplicaUpdate1 func(p0 context.Context, p1 storiface.CallID, p2 storiface.ReplicaVanillaProofs, p3 *storiface.CallError) error `perm:"admin"` - ReturnReadPiece func(p0 context.Context, p1 storiface.CallID, p2 bool, p3 *storiface.CallError) error `perm:"admin"` + ReturnProveReplicaUpdate2 func(p0 context.Context, p1 storiface.CallID, p2 storiface.ReplicaUpdateProof, p3 *storiface.CallError) error `perm:"admin"` - ReturnReleaseUnsealed func(p0 context.Context, p1 storiface.CallID, p2 *storiface.CallError) error `perm:"admin"` + ReturnReadPiece func(p0 context.Context, p1 storiface.CallID, p2 bool, p3 *storiface.CallError) error `perm:"admin"` - ReturnReplicaUpdate func(p0 context.Context, p1 storiface.CallID, p2 storiface.ReplicaUpdateOut, p3 *storiface.CallError) error `perm:"admin"` + ReturnReleaseUnsealed func(p0 context.Context, p1 storiface.CallID, p2 *storiface.CallError) error `perm:"admin"` - ReturnSealCommit1 func(p0 context.Context, p1 storiface.CallID, p2 storiface.Commit1Out, p3 *storiface.CallError) error `perm:"admin"` + ReturnReplicaUpdate func(p0 context.Context, p1 storiface.CallID, p2 storiface.ReplicaUpdateOut, p3 *storiface.CallError) error `perm:"admin"` - ReturnSealCommit2 func(p0 context.Context, p1 storiface.CallID, p2 storiface.Proof, p3 *storiface.CallError) error `perm:"admin"` + ReturnSealCommit1 func(p0 context.Context, p1 storiface.CallID, p2 storiface.Commit1Out, p3 *storiface.CallError) error `perm:"admin"` - ReturnSealPreCommit1 func(p0 context.Context, p1 storiface.CallID, p2 storiface.PreCommit1Out, p3 *storiface.CallError) error `perm:"admin"` + ReturnSealCommit2 func(p0 context.Context, p1 storiface.CallID, p2 storiface.Proof, p3 *storiface.CallError) error `perm:"admin"` - ReturnSealPreCommit2 func(p0 context.Context, p1 storiface.CallID, p2 storiface.SectorCids, p3 *storiface.CallError) error `perm:"admin"` + ReturnSealPreCommit1 func(p0 context.Context, p1 storiface.CallID, p2 storiface.PreCommit1Out, p3 *storiface.CallError) error `perm:"admin"` - ReturnUnsealPiece func(p0 context.Context, p1 storiface.CallID, p2 *storiface.CallError) error `perm:"admin"` + ReturnSealPreCommit2 func(p0 context.Context, p1 storiface.CallID, p2 storiface.SectorCids, p3 *storiface.CallError) error `perm:"admin"` - RuntimeSubsystems func(p0 context.Context) (MinerSubsystems, error) `perm:"read"` + ReturnUnsealPiece func(p0 context.Context, p1 storiface.CallID, p2 *storiface.CallError) error `perm:"admin"` - SealingAbort func(p0 context.Context, p1 storiface.CallID) error `perm:"admin"` + RuntimeSubsystems func(p0 context.Context) (MinerSubsystems, error) `perm:"read"` - SealingRemoveRequest func(p0 context.Context, p1 uuid.UUID) error `perm:"admin"` + SealingAbort func(p0 context.Context, p1 storiface.CallID) error `perm:"admin"` - SealingSchedDiag func(p0 context.Context, p1 bool) (interface{}, error) `perm:"admin"` + SealingRemoveRequest func(p0 context.Context, p1 uuid.UUID) error `perm:"admin"` - SectorAbortUpgrade func(p0 context.Context, p1 abi.SectorNumber) error `perm:"admin"` + SealingSchedDiag func(p0 context.Context, p1 bool) (interface{}, error) `perm:"admin"` - SectorAddPieceToAny func(p0 context.Context, p1 abi.UnpaddedPieceSize, p2 storiface.Data, p3 PieceDealInfo) (SectorOffset, error) `perm:"admin"` + SectorAbortUpgrade func(p0 context.Context, p1 abi.SectorNumber) error `perm:"admin"` - SectorCommitFlush func(p0 context.Context) ([]sealiface.CommitBatchRes, error) `perm:"admin"` + SectorAddPieceToAny func(p0 context.Context, p1 abi.UnpaddedPieceSize, p2 storiface.Data, p3 PieceDealInfo) (SectorOffset, error) `perm:"admin"` - SectorCommitPending func(p0 context.Context) ([]abi.SectorID, error) `perm:"admin"` + SectorCommitFlush func(p0 context.Context) ([]sealiface.CommitBatchRes, error) `perm:"admin"` - SectorGetExpectedSealDuration func(p0 context.Context) (time.Duration, error) `perm:"read"` + SectorCommitPending func(p0 context.Context) ([]abi.SectorID, error) `perm:"admin"` - SectorGetSealDelay func(p0 context.Context) (time.Duration, error) `perm:"read"` + SectorGetExpectedSealDuration func(p0 context.Context) (time.Duration, error) `perm:"read"` - SectorMarkForUpgrade func(p0 context.Context, p1 abi.SectorNumber, p2 bool) error `perm:"admin"` + SectorGetSealDelay func(p0 context.Context) (time.Duration, error) `perm:"read"` - SectorMatchPendingPiecesToOpenSectors func(p0 context.Context) error `perm:"admin"` + SectorMarkForUpgrade func(p0 context.Context, p1 abi.SectorNumber, p2 bool) error `perm:"admin"` - SectorNumAssignerMeta func(p0 context.Context) (NumAssignerMeta, error) `perm:"read"` + SectorMatchPendingPiecesToOpenSectors func(p0 context.Context) error `perm:"admin"` - SectorNumFree func(p0 context.Context, p1 string) error `perm:"admin"` + SectorNumAssignerMeta func(p0 context.Context) (NumAssignerMeta, error) `perm:"read"` - SectorNumReservations func(p0 context.Context) (map[string]bitfield.BitField, error) `perm:"read"` + SectorNumFree func(p0 context.Context, p1 string) error `perm:"admin"` - SectorNumReserve func(p0 context.Context, p1 string, p2 bitfield.BitField, p3 bool) error `perm:"admin"` + SectorNumReservations func(p0 context.Context) (map[string]bitfield.BitField, error) `perm:"read"` - SectorNumReserveCount func(p0 context.Context, p1 string, p2 uint64) (bitfield.BitField, error) `perm:"admin"` + SectorNumReserve func(p0 context.Context, p1 string, p2 bitfield.BitField, p3 bool) error `perm:"admin"` - SectorPreCommitFlush func(p0 context.Context) ([]sealiface.PreCommitBatchRes, error) `perm:"admin"` + SectorNumReserveCount func(p0 context.Context, p1 string, p2 uint64) (bitfield.BitField, error) `perm:"admin"` - SectorPreCommitPending func(p0 context.Context) ([]abi.SectorID, error) `perm:"admin"` + SectorPreCommitFlush func(p0 context.Context) ([]sealiface.PreCommitBatchRes, error) `perm:"admin"` - SectorReceive func(p0 context.Context, p1 RemoteSectorMeta) error `perm:"admin"` + SectorPreCommitPending func(p0 context.Context) ([]abi.SectorID, error) `perm:"admin"` - SectorRemove func(p0 context.Context, p1 abi.SectorNumber) error `perm:"admin"` + SectorReceive func(p0 context.Context, p1 RemoteSectorMeta) error `perm:"admin"` - SectorSetExpectedSealDuration func(p0 context.Context, p1 time.Duration) error `perm:"write"` + SectorRemove func(p0 context.Context, p1 abi.SectorNumber) error `perm:"admin"` - SectorSetSealDelay func(p0 context.Context, p1 time.Duration) error `perm:"write"` + SectorSetExpectedSealDuration func(p0 context.Context, p1 time.Duration) error `perm:"write"` - SectorStartSealing func(p0 context.Context, p1 abi.SectorNumber) error `perm:"write"` + SectorSetSealDelay func(p0 context.Context, p1 time.Duration) error `perm:"write"` - SectorTerminate func(p0 context.Context, p1 abi.SectorNumber) error `perm:"admin"` + SectorStartSealing func(p0 context.Context, p1 abi.SectorNumber) error `perm:"write"` - SectorTerminateFlush func(p0 context.Context) (*cid.Cid, error) `perm:"admin"` + SectorTerminate func(p0 context.Context, p1 abi.SectorNumber) error `perm:"admin"` - SectorTerminatePending func(p0 context.Context) ([]abi.SectorID, error) `perm:"admin"` + SectorTerminateFlush func(p0 context.Context) (*cid.Cid, error) `perm:"admin"` - SectorsList func(p0 context.Context) ([]abi.SectorNumber, error) `perm:"read"` + SectorTerminatePending func(p0 context.Context) ([]abi.SectorID, error) `perm:"admin"` - SectorsListInStates func(p0 context.Context, p1 []SectorState) ([]abi.SectorNumber, error) `perm:"read"` + SectorsList func(p0 context.Context) ([]abi.SectorNumber, error) `perm:"read"` - SectorsRefs func(p0 context.Context) (map[string][]SealedRef, error) `perm:"read"` + SectorsListInStates func(p0 context.Context, p1 []SectorState) ([]abi.SectorNumber, error) `perm:"read"` - SectorsStatus func(p0 context.Context, p1 abi.SectorNumber, p2 bool) (SectorInfo, error) `perm:"read"` + SectorsRefs func(p0 context.Context) (map[string][]SealedRef, error) `perm:"read"` - SectorsSummary func(p0 context.Context) (map[SectorState]int, error) `perm:"read"` + SectorsStatus func(p0 context.Context, p1 abi.SectorNumber, p2 bool) (SectorInfo, error) `perm:"read"` - SectorsUnsealPiece func(p0 context.Context, p1 storiface.SectorRef, p2 storiface.UnpaddedByteIndex, p3 abi.UnpaddedPieceSize, p4 abi.SealRandomness, p5 *cid.Cid) error `perm:"admin"` + SectorsSummary func(p0 context.Context) (map[SectorState]int, error) `perm:"read"` - SectorsUpdate func(p0 context.Context, p1 abi.SectorNumber, p2 SectorState) error `perm:"admin"` + SectorsUnsealPiece func(p0 context.Context, p1 storiface.SectorRef, p2 storiface.UnpaddedByteIndex, p3 abi.UnpaddedPieceSize, p4 abi.SealRandomness, p5 *cid.Cid) error `perm:"admin"` - StorageAddLocal func(p0 context.Context, p1 string) error `perm:"admin"` + SectorsUpdate func(p0 context.Context, p1 abi.SectorNumber, p2 SectorState) error `perm:"admin"` - StorageAttach func(p0 context.Context, p1 storiface.StorageInfo, p2 fsutil.FsStat) error `perm:"admin"` + StorageAddLocal func(p0 context.Context, p1 string) error `perm:"admin"` - StorageAuthVerify func(p0 context.Context, p1 string) ([]auth.Permission, error) `perm:"read"` + StorageAttach func(p0 context.Context, p1 storiface.StorageInfo, p2 fsutil.FsStat) error `perm:"admin"` - StorageBestAlloc func(p0 context.Context, p1 storiface.SectorFileType, p2 abi.SectorSize, p3 storiface.PathType) ([]storiface.StorageInfo, error) `perm:"admin"` + StorageAuthVerify func(p0 context.Context, p1 string) ([]auth.Permission, error) `perm:"read"` - StorageDeclareSector func(p0 context.Context, p1 storiface.ID, p2 abi.SectorID, p3 storiface.SectorFileType, p4 bool) error `perm:"admin"` + StorageBestAlloc func(p0 context.Context, p1 storiface.SectorFileType, p2 abi.SectorSize, p3 storiface.PathType) ([]storiface.StorageInfo, error) `perm:"admin"` - StorageDetach func(p0 context.Context, p1 storiface.ID, p2 string) error `perm:"admin"` + StorageDeclareSector func(p0 context.Context, p1 storiface.ID, p2 abi.SectorID, p3 storiface.SectorFileType, p4 bool) error `perm:"admin"` - StorageDetachLocal func(p0 context.Context, p1 string) error `perm:"admin"` + StorageDetach func(p0 context.Context, p1 storiface.ID, p2 string) error `perm:"admin"` - StorageDropSector func(p0 context.Context, p1 storiface.ID, p2 abi.SectorID, p3 storiface.SectorFileType) error `perm:"admin"` + StorageDetachLocal func(p0 context.Context, p1 string) error `perm:"admin"` - StorageFindSector func(p0 context.Context, p1 abi.SectorID, p2 storiface.SectorFileType, p3 abi.SectorSize, p4 bool) ([]storiface.SectorStorageInfo, error) `perm:"admin"` + StorageDropSector func(p0 context.Context, p1 storiface.ID, p2 abi.SectorID, p3 storiface.SectorFileType) error `perm:"admin"` - StorageGetLocks func(p0 context.Context) (storiface.SectorLocks, error) `perm:"admin"` + StorageFindSector func(p0 context.Context, p1 abi.SectorID, p2 storiface.SectorFileType, p3 abi.SectorSize, p4 bool) ([]storiface.SectorStorageInfo, error) `perm:"admin"` - StorageInfo func(p0 context.Context, p1 storiface.ID) (storiface.StorageInfo, error) `perm:"admin"` + StorageGetLocks func(p0 context.Context) (storiface.SectorLocks, error) `perm:"admin"` - StorageList func(p0 context.Context) (map[storiface.ID][]storiface.Decl, error) `perm:"admin"` + StorageInfo func(p0 context.Context, p1 storiface.ID) (storiface.StorageInfo, error) `perm:"admin"` - StorageLocal func(p0 context.Context) (map[storiface.ID]string, error) `perm:"admin"` + StorageList func(p0 context.Context) (map[storiface.ID][]storiface.Decl, error) `perm:"admin"` - StorageLock func(p0 context.Context, p1 abi.SectorID, p2 storiface.SectorFileType, p3 storiface.SectorFileType) error `perm:"admin"` + StorageLocal func(p0 context.Context) (map[storiface.ID]string, error) `perm:"admin"` - StorageRedeclareLocal func(p0 context.Context, p1 *storiface.ID, p2 bool) error `perm:"admin"` + StorageLock func(p0 context.Context, p1 abi.SectorID, p2 storiface.SectorFileType, p3 storiface.SectorFileType) error `perm:"admin"` - StorageReportHealth func(p0 context.Context, p1 storiface.ID, p2 storiface.HealthReport) error `perm:"admin"` + StorageRedeclareLocal func(p0 context.Context, p1 *storiface.ID, p2 bool) error `perm:"admin"` - StorageStat func(p0 context.Context, p1 storiface.ID) (fsutil.FsStat, error) `perm:"admin"` + StorageReportHealth func(p0 context.Context, p1 storiface.ID, p2 storiface.HealthReport) error `perm:"admin"` - StorageTryLock func(p0 context.Context, p1 abi.SectorID, p2 storiface.SectorFileType, p3 storiface.SectorFileType) (bool, error) `perm:"admin"` + StorageStat func(p0 context.Context, p1 storiface.ID) (fsutil.FsStat, error) `perm:"admin"` - WorkerConnect func(p0 context.Context, p1 string) error `perm:"admin"` + StorageTryLock func(p0 context.Context, p1 abi.SectorID, p2 storiface.SectorFileType, p3 storiface.SectorFileType) (bool, error) `perm:"admin"` - WorkerJobs func(p0 context.Context) (map[uuid.UUID][]storiface.WorkerJob, error) `perm:"admin"` + WorkerConnect func(p0 context.Context, p1 string) error `perm:"admin"` - WorkerStats func(p0 context.Context) (map[uuid.UUID]storiface.WorkerStats, error) `perm:"admin"` - } + WorkerJobs func(p0 context.Context) (map[uuid.UUID][]storiface.WorkerJob, error) `perm:"admin"` + + WorkerStats func(p0 context.Context) (map[uuid.UUID]storiface.WorkerStats, error) `perm:"admin"` } type StorageMinerStub struct { @@ -1085,102 +1121,106 @@ type StorageMinerStub struct { } type WalletStruct struct { - Internal struct { - WalletDelete func(p0 context.Context, p1 address.Address) error `perm:"admin"` + Internal WalletMethods +} - WalletExport func(p0 context.Context, p1 address.Address) (*types.KeyInfo, error) `perm:"admin"` +type WalletMethods struct { + WalletDelete func(p0 context.Context, p1 address.Address) error `perm:"admin"` - WalletHas func(p0 context.Context, p1 address.Address) (bool, error) `perm:"admin"` + WalletExport func(p0 context.Context, p1 address.Address) (*types.KeyInfo, error) `perm:"admin"` - WalletImport func(p0 context.Context, p1 *types.KeyInfo) (address.Address, error) `perm:"admin"` + WalletHas func(p0 context.Context, p1 address.Address) (bool, error) `perm:"admin"` - WalletList func(p0 context.Context) ([]address.Address, error) `perm:"admin"` + WalletImport func(p0 context.Context, p1 *types.KeyInfo) (address.Address, error) `perm:"admin"` - WalletNew func(p0 context.Context, p1 types.KeyType) (address.Address, error) `perm:"admin"` + WalletList func(p0 context.Context) ([]address.Address, error) `perm:"admin"` - WalletSign func(p0 context.Context, p1 address.Address, p2 []byte, p3 MsgMeta) (*crypto.Signature, error) `perm:"admin"` - } + WalletNew func(p0 context.Context, p1 types.KeyType) (address.Address, error) `perm:"admin"` + + WalletSign func(p0 context.Context, p1 address.Address, p2 []byte, p3 MsgMeta) (*crypto.Signature, error) `perm:"admin"` } type WalletStub struct { } type WorkerStruct struct { - Internal struct { - AddPiece func(p0 context.Context, p1 storiface.SectorRef, p2 []abi.UnpaddedPieceSize, p3 abi.UnpaddedPieceSize, p4 storiface.Data) (storiface.CallID, error) `perm:"admin"` + Internal WorkerMethods +} - DataCid func(p0 context.Context, p1 abi.UnpaddedPieceSize, p2 storiface.Data) (storiface.CallID, error) `perm:"admin"` +type WorkerMethods struct { + AddPiece func(p0 context.Context, p1 storiface.SectorRef, p2 []abi.UnpaddedPieceSize, p3 abi.UnpaddedPieceSize, p4 storiface.Data) (storiface.CallID, error) `perm:"admin"` - DownloadSectorData func(p0 context.Context, p1 storiface.SectorRef, p2 bool, p3 map[storiface.SectorFileType]storiface.SectorLocation) (storiface.CallID, error) `perm:"admin"` + DataCid func(p0 context.Context, p1 abi.UnpaddedPieceSize, p2 storiface.Data) (storiface.CallID, error) `perm:"admin"` - Enabled func(p0 context.Context) (bool, error) `perm:"admin"` + DownloadSectorData func(p0 context.Context, p1 storiface.SectorRef, p2 bool, p3 map[storiface.SectorFileType]storiface.SectorLocation) (storiface.CallID, error) `perm:"admin"` - Fetch func(p0 context.Context, p1 storiface.SectorRef, p2 storiface.SectorFileType, p3 storiface.PathType, p4 storiface.AcquireMode) (storiface.CallID, error) `perm:"admin"` + Enabled func(p0 context.Context) (bool, error) `perm:"admin"` - FinalizeReplicaUpdate func(p0 context.Context, p1 storiface.SectorRef) (storiface.CallID, error) `perm:"admin"` + Fetch func(p0 context.Context, p1 storiface.SectorRef, p2 storiface.SectorFileType, p3 storiface.PathType, p4 storiface.AcquireMode) (storiface.CallID, error) `perm:"admin"` - FinalizeSector func(p0 context.Context, p1 storiface.SectorRef) (storiface.CallID, error) `perm:"admin"` + FinalizeReplicaUpdate func(p0 context.Context, p1 storiface.SectorRef) (storiface.CallID, error) `perm:"admin"` - GenerateSectorKeyFromData func(p0 context.Context, p1 storiface.SectorRef, p2 cid.Cid) (storiface.CallID, error) `perm:"admin"` + FinalizeSector func(p0 context.Context, p1 storiface.SectorRef) (storiface.CallID, error) `perm:"admin"` - GenerateWindowPoSt func(p0 context.Context, p1 abi.RegisteredPoStProof, p2 abi.ActorID, p3 []storiface.PostSectorChallenge, p4 int, p5 abi.PoStRandomness) (storiface.WindowPoStResult, error) `perm:"admin"` + GenerateSectorKeyFromData func(p0 context.Context, p1 storiface.SectorRef, p2 cid.Cid) (storiface.CallID, error) `perm:"admin"` - GenerateWinningPoSt func(p0 context.Context, p1 abi.RegisteredPoStProof, p2 abi.ActorID, p3 []storiface.PostSectorChallenge, p4 abi.PoStRandomness) ([]proof.PoStProof, error) `perm:"admin"` + GenerateWindowPoSt func(p0 context.Context, p1 abi.RegisteredPoStProof, p2 abi.ActorID, p3 []storiface.PostSectorChallenge, p4 int, p5 abi.PoStRandomness) (storiface.WindowPoStResult, error) `perm:"admin"` - Info func(p0 context.Context) (storiface.WorkerInfo, error) `perm:"admin"` + GenerateWinningPoSt func(p0 context.Context, p1 abi.RegisteredPoStProof, p2 abi.ActorID, p3 []storiface.PostSectorChallenge, p4 abi.PoStRandomness) ([]proof.PoStProof, error) `perm:"admin"` - MoveStorage func(p0 context.Context, p1 storiface.SectorRef, p2 storiface.SectorFileType) (storiface.CallID, error) `perm:"admin"` + Info func(p0 context.Context) (storiface.WorkerInfo, error) `perm:"admin"` - Paths func(p0 context.Context) ([]storiface.StoragePath, error) `perm:"admin"` + MoveStorage func(p0 context.Context, p1 storiface.SectorRef, p2 storiface.SectorFileType) (storiface.CallID, error) `perm:"admin"` - ProcessSession func(p0 context.Context) (uuid.UUID, error) `perm:"admin"` + Paths func(p0 context.Context) ([]storiface.StoragePath, error) `perm:"admin"` - ProveReplicaUpdate1 func(p0 context.Context, p1 storiface.SectorRef, p2 cid.Cid, p3 cid.Cid, p4 cid.Cid) (storiface.CallID, error) `perm:"admin"` + ProcessSession func(p0 context.Context) (uuid.UUID, error) `perm:"admin"` - ProveReplicaUpdate2 func(p0 context.Context, p1 storiface.SectorRef, p2 cid.Cid, p3 cid.Cid, p4 cid.Cid, p5 storiface.ReplicaVanillaProofs) (storiface.CallID, error) `perm:"admin"` + ProveReplicaUpdate1 func(p0 context.Context, p1 storiface.SectorRef, p2 cid.Cid, p3 cid.Cid, p4 cid.Cid) (storiface.CallID, error) `perm:"admin"` - ReleaseUnsealed func(p0 context.Context, p1 storiface.SectorRef, p2 []storiface.Range) (storiface.CallID, error) `perm:"admin"` + ProveReplicaUpdate2 func(p0 context.Context, p1 storiface.SectorRef, p2 cid.Cid, p3 cid.Cid, p4 cid.Cid, p5 storiface.ReplicaVanillaProofs) (storiface.CallID, error) `perm:"admin"` - Remove func(p0 context.Context, p1 abi.SectorID) error `perm:"admin"` + ReleaseUnsealed func(p0 context.Context, p1 storiface.SectorRef, p2 []storiface.Range) (storiface.CallID, error) `perm:"admin"` - ReplicaUpdate func(p0 context.Context, p1 storiface.SectorRef, p2 []abi.PieceInfo) (storiface.CallID, error) `perm:"admin"` + Remove func(p0 context.Context, p1 abi.SectorID) error `perm:"admin"` - SealCommit1 func(p0 context.Context, p1 storiface.SectorRef, p2 abi.SealRandomness, p3 abi.InteractiveSealRandomness, p4 []abi.PieceInfo, p5 storiface.SectorCids) (storiface.CallID, error) `perm:"admin"` + ReplicaUpdate func(p0 context.Context, p1 storiface.SectorRef, p2 []abi.PieceInfo) (storiface.CallID, error) `perm:"admin"` - SealCommit2 func(p0 context.Context, p1 storiface.SectorRef, p2 storiface.Commit1Out) (storiface.CallID, error) `perm:"admin"` + SealCommit1 func(p0 context.Context, p1 storiface.SectorRef, p2 abi.SealRandomness, p3 abi.InteractiveSealRandomness, p4 []abi.PieceInfo, p5 storiface.SectorCids) (storiface.CallID, error) `perm:"admin"` - SealPreCommit1 func(p0 context.Context, p1 storiface.SectorRef, p2 abi.SealRandomness, p3 []abi.PieceInfo) (storiface.CallID, error) `perm:"admin"` + SealCommit2 func(p0 context.Context, p1 storiface.SectorRef, p2 storiface.Commit1Out) (storiface.CallID, error) `perm:"admin"` - SealPreCommit2 func(p0 context.Context, p1 storiface.SectorRef, p2 storiface.PreCommit1Out) (storiface.CallID, error) `perm:"admin"` + SealPreCommit1 func(p0 context.Context, p1 storiface.SectorRef, p2 abi.SealRandomness, p3 []abi.PieceInfo) (storiface.CallID, error) `perm:"admin"` - Session func(p0 context.Context) (uuid.UUID, error) `perm:"admin"` + SealPreCommit2 func(p0 context.Context, p1 storiface.SectorRef, p2 storiface.PreCommit1Out) (storiface.CallID, error) `perm:"admin"` - SetEnabled func(p0 context.Context, p1 bool) error `perm:"admin"` + Session func(p0 context.Context) (uuid.UUID, error) `perm:"admin"` - Shutdown func(p0 context.Context) error `perm:"admin"` + SetEnabled func(p0 context.Context, p1 bool) error `perm:"admin"` - StorageAddLocal func(p0 context.Context, p1 string) error `perm:"admin"` + Shutdown func(p0 context.Context) error `perm:"admin"` - StorageDetachAll func(p0 context.Context) error `perm:"admin"` + StorageAddLocal func(p0 context.Context, p1 string) error `perm:"admin"` - StorageDetachLocal func(p0 context.Context, p1 string) error `perm:"admin"` + StorageDetachAll func(p0 context.Context) error `perm:"admin"` - StorageLocal func(p0 context.Context) (map[storiface.ID]string, error) `perm:"admin"` + StorageDetachLocal func(p0 context.Context, p1 string) error `perm:"admin"` - StorageRedeclareLocal func(p0 context.Context, p1 *storiface.ID, p2 bool) error `perm:"admin"` + StorageLocal func(p0 context.Context) (map[storiface.ID]string, error) `perm:"admin"` - TaskDisable func(p0 context.Context, p1 sealtasks.TaskType) error `perm:"admin"` + StorageRedeclareLocal func(p0 context.Context, p1 *storiface.ID, p2 bool) error `perm:"admin"` - TaskEnable func(p0 context.Context, p1 sealtasks.TaskType) error `perm:"admin"` + TaskDisable func(p0 context.Context, p1 sealtasks.TaskType) error `perm:"admin"` - TaskTypes func(p0 context.Context) (map[sealtasks.TaskType]struct{}, error) `perm:"admin"` + TaskEnable func(p0 context.Context, p1 sealtasks.TaskType) error `perm:"admin"` - UnsealPiece func(p0 context.Context, p1 storiface.SectorRef, p2 storiface.UnpaddedByteIndex, p3 abi.UnpaddedPieceSize, p4 abi.SealRandomness, p5 cid.Cid) (storiface.CallID, error) `perm:"admin"` + TaskTypes func(p0 context.Context) (map[sealtasks.TaskType]struct{}, error) `perm:"admin"` - Version func(p0 context.Context) (Version, error) `perm:"admin"` + UnsealPiece func(p0 context.Context, p1 storiface.SectorRef, p2 storiface.UnpaddedByteIndex, p3 abi.UnpaddedPieceSize, p4 abi.SealRandomness, p5 cid.Cid) (storiface.CallID, error) `perm:"admin"` - WaitQuiet func(p0 context.Context) error `perm:"admin"` - } + Version func(p0 context.Context) (Version, error) `perm:"admin"` + + WaitQuiet func(p0 context.Context) error `perm:"admin"` } type WorkerStub struct { @@ -1340,6 +1380,17 @@ func (s *CommonStub) Version(p0 context.Context) (APIVersion, error) { return *new(APIVersion), ErrNotSupported } +func (s *EthSubscriberStruct) EthSubscription(p0 context.Context, p1 jsonrpc.RawParams) error { + if s.Internal.EthSubscription == nil { + return ErrNotSupported + } + return s.Internal.EthSubscription(p0, p1) +} + +func (s *EthSubscriberStub) EthSubscription(p0 context.Context, p1 jsonrpc.RawParams) error { + return ErrNotSupported +} + func (s *FullNodeStruct) ChainBlockstoreInfo(p0 context.Context) (map[string]interface{}, error) { if s.Internal.ChainBlockstoreInfo == nil { return *new(map[string]interface{}), ErrNotSupported @@ -2275,15 +2326,15 @@ func (s *FullNodeStub) EthSendRawTransaction(p0 context.Context, p1 ethtypes.Eth return *new(ethtypes.EthHash), ErrNotSupported } -func (s *FullNodeStruct) EthSubscribe(p0 context.Context, p1 string, p2 *ethtypes.EthSubscriptionParams) (<-chan ethtypes.EthSubscriptionResponse, error) { +func (s *FullNodeStruct) EthSubscribe(p0 context.Context, p1 jsonrpc.RawParams) (ethtypes.EthSubscriptionID, error) { if s.Internal.EthSubscribe == nil { - return nil, ErrNotSupported + return *new(ethtypes.EthSubscriptionID), ErrNotSupported } - return s.Internal.EthSubscribe(p0, p1, p2) + return s.Internal.EthSubscribe(p0, p1) } -func (s *FullNodeStub) EthSubscribe(p0 context.Context, p1 string, p2 *ethtypes.EthSubscriptionParams) (<-chan ethtypes.EthSubscriptionResponse, error) { - return nil, ErrNotSupported +func (s *FullNodeStub) EthSubscribe(p0 context.Context, p1 jsonrpc.RawParams) (ethtypes.EthSubscriptionID, error) { + return *new(ethtypes.EthSubscriptionID), ErrNotSupported } func (s *FullNodeStruct) EthUninstallFilter(p0 context.Context, p1 ethtypes.EthFilterID) (bool, error) { @@ -3936,6 +3987,17 @@ func (s *FullNodeStub) WalletVerify(p0 context.Context, p1 address.Address, p2 [ return false, ErrNotSupported } +func (s *FullNodeStruct) Web3ClientVersion(p0 context.Context) (string, error) { + if s.Internal.Web3ClientVersion == nil { + return "", ErrNotSupported + } + return s.Internal.Web3ClientVersion(p0) +} + +func (s *FullNodeStub) Web3ClientVersion(p0 context.Context) (string, error) { + return "", ErrNotSupported +} + func (s *GatewayStruct) ChainGetBlockMessages(p0 context.Context, p1 cid.Cid) (*BlockMessages, error) { if s.Internal.ChainGetBlockMessages == nil { return nil, ErrNotSupported @@ -4277,6 +4339,17 @@ func (s *GatewayStub) EthGetLogs(p0 context.Context, p1 *ethtypes.EthFilterSpec) return nil, ErrNotSupported } +func (s *GatewayStruct) EthGetMessageCidByTransactionHash(p0 context.Context, p1 *ethtypes.EthHash) (*cid.Cid, error) { + if s.Internal.EthGetMessageCidByTransactionHash == nil { + return nil, ErrNotSupported + } + return s.Internal.EthGetMessageCidByTransactionHash(p0, p1) +} + +func (s *GatewayStub) EthGetMessageCidByTransactionHash(p0 context.Context, p1 *ethtypes.EthHash) (*cid.Cid, error) { + return nil, ErrNotSupported +} + func (s *GatewayStruct) EthGetStorageAt(p0 context.Context, p1 ethtypes.EthAddress, p2 ethtypes.EthBytes, p3 string) (ethtypes.EthBytes, error) { if s.Internal.EthGetStorageAt == nil { return *new(ethtypes.EthBytes), ErrNotSupported @@ -4332,6 +4405,17 @@ func (s *GatewayStub) EthGetTransactionCount(p0 context.Context, p1 ethtypes.Eth return *new(ethtypes.EthUint64), ErrNotSupported } +func (s *GatewayStruct) EthGetTransactionHashByCid(p0 context.Context, p1 cid.Cid) (*ethtypes.EthHash, error) { + if s.Internal.EthGetTransactionHashByCid == nil { + return nil, ErrNotSupported + } + return s.Internal.EthGetTransactionHashByCid(p0, p1) +} + +func (s *GatewayStub) EthGetTransactionHashByCid(p0 context.Context, p1 cid.Cid) (*ethtypes.EthHash, error) { + return nil, ErrNotSupported +} + func (s *GatewayStruct) EthGetTransactionReceipt(p0 context.Context, p1 ethtypes.EthHash) (*EthTxReceipt, error) { if s.Internal.EthGetTransactionReceipt == nil { return nil, ErrNotSupported @@ -4409,15 +4493,15 @@ func (s *GatewayStub) EthSendRawTransaction(p0 context.Context, p1 ethtypes.EthB return *new(ethtypes.EthHash), ErrNotSupported } -func (s *GatewayStruct) EthSubscribe(p0 context.Context, p1 string, p2 *ethtypes.EthSubscriptionParams) (<-chan ethtypes.EthSubscriptionResponse, error) { +func (s *GatewayStruct) EthSubscribe(p0 context.Context, p1 jsonrpc.RawParams) (ethtypes.EthSubscriptionID, error) { if s.Internal.EthSubscribe == nil { - return nil, ErrNotSupported + return *new(ethtypes.EthSubscriptionID), ErrNotSupported } - return s.Internal.EthSubscribe(p0, p1, p2) + return s.Internal.EthSubscribe(p0, p1) } -func (s *GatewayStub) EthSubscribe(p0 context.Context, p1 string, p2 *ethtypes.EthSubscriptionParams) (<-chan ethtypes.EthSubscriptionResponse, error) { - return nil, ErrNotSupported +func (s *GatewayStub) EthSubscribe(p0 context.Context, p1 jsonrpc.RawParams) (ethtypes.EthSubscriptionID, error) { + return *new(ethtypes.EthSubscriptionID), ErrNotSupported } func (s *GatewayStruct) EthUninstallFilter(p0 context.Context, p1 ethtypes.EthFilterID) (bool, error) { @@ -4728,6 +4812,17 @@ func (s *GatewayStub) WalletBalance(p0 context.Context, p1 address.Address) (typ return *new(types.BigInt), ErrNotSupported } +func (s *GatewayStruct) Web3ClientVersion(p0 context.Context) (string, error) { + if s.Internal.Web3ClientVersion == nil { + return "", ErrNotSupported + } + return s.Internal.Web3ClientVersion(p0) +} + +func (s *GatewayStub) Web3ClientVersion(p0 context.Context) (string, error) { + return "", ErrNotSupported +} + func (s *NetStruct) ID(p0 context.Context) (peer.ID, error) { if s.Internal.ID == nil { return *new(peer.ID), ErrNotSupported @@ -6942,6 +7037,7 @@ func (s *WorkerStub) WaitQuiet(p0 context.Context) error { var _ ChainIO = new(ChainIOStruct) var _ Common = new(CommonStruct) var _ CommonNet = new(CommonNetStruct) +var _ EthSubscriber = new(EthSubscriberStruct) var _ FullNode = new(FullNodeStruct) var _ Gateway = new(GatewayStruct) var _ Net = new(NetStruct) diff --git a/api/v0api/proxy_gen.go b/api/v0api/proxy_gen.go index b1a07dacc..4acf2e111 100644 --- a/api/v0api/proxy_gen.go +++ b/api/v0api/proxy_gen.go @@ -39,383 +39,385 @@ type FullNodeStruct struct { NetStruct - Internal struct { - BeaconGetEntry func(p0 context.Context, p1 abi.ChainEpoch) (*types.BeaconEntry, error) `perm:"read"` + Internal FullNodeMethods +} - ChainDeleteObj func(p0 context.Context, p1 cid.Cid) error `perm:"admin"` +type FullNodeMethods struct { + BeaconGetEntry func(p0 context.Context, p1 abi.ChainEpoch) (*types.BeaconEntry, error) `perm:"read"` - ChainExport func(p0 context.Context, p1 abi.ChainEpoch, p2 bool, p3 types.TipSetKey) (<-chan []byte, error) `perm:"read"` + ChainDeleteObj func(p0 context.Context, p1 cid.Cid) error `perm:"admin"` - ChainGetBlock func(p0 context.Context, p1 cid.Cid) (*types.BlockHeader, error) `perm:"read"` + ChainExport func(p0 context.Context, p1 abi.ChainEpoch, p2 bool, p3 types.TipSetKey) (<-chan []byte, error) `perm:"read"` - ChainGetBlockMessages func(p0 context.Context, p1 cid.Cid) (*api.BlockMessages, error) `perm:"read"` + ChainGetBlock func(p0 context.Context, p1 cid.Cid) (*types.BlockHeader, error) `perm:"read"` - ChainGetGenesis func(p0 context.Context) (*types.TipSet, error) `perm:"read"` + ChainGetBlockMessages func(p0 context.Context, p1 cid.Cid) (*api.BlockMessages, error) `perm:"read"` - ChainGetMessage func(p0 context.Context, p1 cid.Cid) (*types.Message, error) `perm:"read"` + ChainGetGenesis func(p0 context.Context) (*types.TipSet, error) `perm:"read"` - ChainGetMessagesInTipset func(p0 context.Context, p1 types.TipSetKey) ([]api.Message, error) `perm:"read"` + ChainGetMessage func(p0 context.Context, p1 cid.Cid) (*types.Message, error) `perm:"read"` - ChainGetNode func(p0 context.Context, p1 string) (*api.IpldObject, error) `perm:"read"` + ChainGetMessagesInTipset func(p0 context.Context, p1 types.TipSetKey) ([]api.Message, error) `perm:"read"` - ChainGetParentMessages func(p0 context.Context, p1 cid.Cid) ([]api.Message, error) `perm:"read"` + ChainGetNode func(p0 context.Context, p1 string) (*api.IpldObject, error) `perm:"read"` - ChainGetParentReceipts func(p0 context.Context, p1 cid.Cid) ([]*types.MessageReceipt, error) `perm:"read"` + ChainGetParentMessages func(p0 context.Context, p1 cid.Cid) ([]api.Message, error) `perm:"read"` - ChainGetPath func(p0 context.Context, p1 types.TipSetKey, p2 types.TipSetKey) ([]*api.HeadChange, error) `perm:"read"` + ChainGetParentReceipts func(p0 context.Context, p1 cid.Cid) ([]*types.MessageReceipt, error) `perm:"read"` - ChainGetRandomnessFromBeacon func(p0 context.Context, p1 types.TipSetKey, p2 crypto.DomainSeparationTag, p3 abi.ChainEpoch, p4 []byte) (abi.Randomness, error) `perm:"read"` + ChainGetPath func(p0 context.Context, p1 types.TipSetKey, p2 types.TipSetKey) ([]*api.HeadChange, error) `perm:"read"` - ChainGetRandomnessFromTickets func(p0 context.Context, p1 types.TipSetKey, p2 crypto.DomainSeparationTag, p3 abi.ChainEpoch, p4 []byte) (abi.Randomness, error) `perm:"read"` + ChainGetRandomnessFromBeacon func(p0 context.Context, p1 types.TipSetKey, p2 crypto.DomainSeparationTag, p3 abi.ChainEpoch, p4 []byte) (abi.Randomness, error) `perm:"read"` - ChainGetTipSet func(p0 context.Context, p1 types.TipSetKey) (*types.TipSet, error) `perm:"read"` + ChainGetRandomnessFromTickets func(p0 context.Context, p1 types.TipSetKey, p2 crypto.DomainSeparationTag, p3 abi.ChainEpoch, p4 []byte) (abi.Randomness, error) `perm:"read"` - ChainGetTipSetByHeight func(p0 context.Context, p1 abi.ChainEpoch, p2 types.TipSetKey) (*types.TipSet, error) `perm:"read"` + ChainGetTipSet func(p0 context.Context, p1 types.TipSetKey) (*types.TipSet, error) `perm:"read"` - ChainHasObj func(p0 context.Context, p1 cid.Cid) (bool, error) `perm:"read"` + ChainGetTipSetByHeight func(p0 context.Context, p1 abi.ChainEpoch, p2 types.TipSetKey) (*types.TipSet, error) `perm:"read"` - ChainHead func(p0 context.Context) (*types.TipSet, error) `perm:"read"` + ChainHasObj func(p0 context.Context, p1 cid.Cid) (bool, error) `perm:"read"` - ChainNotify func(p0 context.Context) (<-chan []*api.HeadChange, error) `perm:"read"` + ChainHead func(p0 context.Context) (*types.TipSet, error) `perm:"read"` - ChainPutObj func(p0 context.Context, p1 blocks.Block) error `` + ChainNotify func(p0 context.Context) (<-chan []*api.HeadChange, error) `perm:"read"` - ChainReadObj func(p0 context.Context, p1 cid.Cid) ([]byte, error) `perm:"read"` + ChainPutObj func(p0 context.Context, p1 blocks.Block) error `` - ChainSetHead func(p0 context.Context, p1 types.TipSetKey) error `perm:"admin"` + ChainReadObj func(p0 context.Context, p1 cid.Cid) ([]byte, error) `perm:"read"` - ChainStatObj func(p0 context.Context, p1 cid.Cid, p2 cid.Cid) (api.ObjStat, error) `perm:"read"` + ChainSetHead func(p0 context.Context, p1 types.TipSetKey) error `perm:"admin"` - ChainTipSetWeight func(p0 context.Context, p1 types.TipSetKey) (types.BigInt, error) `perm:"read"` + ChainStatObj func(p0 context.Context, p1 cid.Cid, p2 cid.Cid) (api.ObjStat, error) `perm:"read"` - ClientCalcCommP func(p0 context.Context, p1 string) (*api.CommPRet, error) `perm:"write"` + ChainTipSetWeight func(p0 context.Context, p1 types.TipSetKey) (types.BigInt, error) `perm:"read"` - ClientCancelDataTransfer func(p0 context.Context, p1 datatransfer.TransferID, p2 peer.ID, p3 bool) error `perm:"write"` + ClientCalcCommP func(p0 context.Context, p1 string) (*api.CommPRet, error) `perm:"write"` - ClientCancelRetrievalDeal func(p0 context.Context, p1 retrievalmarket.DealID) error `perm:"write"` + ClientCancelDataTransfer func(p0 context.Context, p1 datatransfer.TransferID, p2 peer.ID, p3 bool) error `perm:"write"` - ClientDataTransferUpdates func(p0 context.Context) (<-chan api.DataTransferChannel, error) `perm:"write"` + ClientCancelRetrievalDeal func(p0 context.Context, p1 retrievalmarket.DealID) error `perm:"write"` - ClientDealPieceCID func(p0 context.Context, p1 cid.Cid) (api.DataCIDSize, error) `perm:"read"` + ClientDataTransferUpdates func(p0 context.Context) (<-chan api.DataTransferChannel, error) `perm:"write"` - ClientDealSize func(p0 context.Context, p1 cid.Cid) (api.DataSize, error) `perm:"read"` + ClientDealPieceCID func(p0 context.Context, p1 cid.Cid) (api.DataCIDSize, error) `perm:"read"` - ClientFindData func(p0 context.Context, p1 cid.Cid, p2 *cid.Cid) ([]api.QueryOffer, error) `perm:"read"` + ClientDealSize func(p0 context.Context, p1 cid.Cid) (api.DataSize, error) `perm:"read"` - ClientGenCar func(p0 context.Context, p1 api.FileRef, p2 string) error `perm:"write"` + ClientFindData func(p0 context.Context, p1 cid.Cid, p2 *cid.Cid) ([]api.QueryOffer, error) `perm:"read"` - ClientGetDealInfo func(p0 context.Context, p1 cid.Cid) (*api.DealInfo, error) `perm:"read"` + ClientGenCar func(p0 context.Context, p1 api.FileRef, p2 string) error `perm:"write"` - ClientGetDealStatus func(p0 context.Context, p1 uint64) (string, error) `perm:"read"` + ClientGetDealInfo func(p0 context.Context, p1 cid.Cid) (*api.DealInfo, error) `perm:"read"` - ClientGetDealUpdates func(p0 context.Context) (<-chan api.DealInfo, error) `perm:"write"` + ClientGetDealStatus func(p0 context.Context, p1 uint64) (string, error) `perm:"read"` - ClientGetRetrievalUpdates func(p0 context.Context) (<-chan api.RetrievalInfo, error) `perm:"write"` + ClientGetDealUpdates func(p0 context.Context) (<-chan api.DealInfo, error) `perm:"write"` - ClientHasLocal func(p0 context.Context, p1 cid.Cid) (bool, error) `perm:"write"` + ClientGetRetrievalUpdates func(p0 context.Context) (<-chan api.RetrievalInfo, error) `perm:"write"` - ClientImport func(p0 context.Context, p1 api.FileRef) (*api.ImportRes, error) `perm:"admin"` + ClientHasLocal func(p0 context.Context, p1 cid.Cid) (bool, error) `perm:"write"` - ClientListDataTransfers func(p0 context.Context) ([]api.DataTransferChannel, error) `perm:"write"` + ClientImport func(p0 context.Context, p1 api.FileRef) (*api.ImportRes, error) `perm:"admin"` - ClientListDeals func(p0 context.Context) ([]api.DealInfo, error) `perm:"write"` + ClientListDataTransfers func(p0 context.Context) ([]api.DataTransferChannel, error) `perm:"write"` - ClientListImports func(p0 context.Context) ([]api.Import, error) `perm:"write"` + ClientListDeals func(p0 context.Context) ([]api.DealInfo, error) `perm:"write"` - ClientListRetrievals func(p0 context.Context) ([]api.RetrievalInfo, error) `perm:"write"` + ClientListImports func(p0 context.Context) ([]api.Import, error) `perm:"write"` - ClientMinerQueryOffer func(p0 context.Context, p1 address.Address, p2 cid.Cid, p3 *cid.Cid) (api.QueryOffer, error) `perm:"read"` + ClientListRetrievals func(p0 context.Context) ([]api.RetrievalInfo, error) `perm:"write"` - ClientQueryAsk func(p0 context.Context, p1 peer.ID, p2 address.Address) (*storagemarket.StorageAsk, error) `perm:"read"` + ClientMinerQueryOffer func(p0 context.Context, p1 address.Address, p2 cid.Cid, p3 *cid.Cid) (api.QueryOffer, error) `perm:"read"` - ClientRemoveImport func(p0 context.Context, p1 imports.ID) error `perm:"admin"` + ClientQueryAsk func(p0 context.Context, p1 peer.ID, p2 address.Address) (*storagemarket.StorageAsk, error) `perm:"read"` - ClientRestartDataTransfer func(p0 context.Context, p1 datatransfer.TransferID, p2 peer.ID, p3 bool) error `perm:"write"` + ClientRemoveImport func(p0 context.Context, p1 imports.ID) error `perm:"admin"` - ClientRetrieve func(p0 context.Context, p1 RetrievalOrder, p2 *api.FileRef) error `perm:"admin"` + ClientRestartDataTransfer func(p0 context.Context, p1 datatransfer.TransferID, p2 peer.ID, p3 bool) error `perm:"write"` - ClientRetrieveTryRestartInsufficientFunds func(p0 context.Context, p1 address.Address) error `perm:"write"` + ClientRetrieve func(p0 context.Context, p1 RetrievalOrder, p2 *api.FileRef) error `perm:"admin"` - ClientRetrieveWithEvents func(p0 context.Context, p1 RetrievalOrder, p2 *api.FileRef) (<-chan marketevents.RetrievalEvent, error) `perm:"admin"` + ClientRetrieveTryRestartInsufficientFunds func(p0 context.Context, p1 address.Address) error `perm:"write"` - ClientStartDeal func(p0 context.Context, p1 *api.StartDealParams) (*cid.Cid, error) `perm:"admin"` + ClientRetrieveWithEvents func(p0 context.Context, p1 RetrievalOrder, p2 *api.FileRef) (<-chan marketevents.RetrievalEvent, error) `perm:"admin"` - ClientStatelessDeal func(p0 context.Context, p1 *api.StartDealParams) (*cid.Cid, error) `perm:"write"` + ClientStartDeal func(p0 context.Context, p1 *api.StartDealParams) (*cid.Cid, error) `perm:"admin"` - CreateBackup func(p0 context.Context, p1 string) error `perm:"admin"` + ClientStatelessDeal func(p0 context.Context, p1 *api.StartDealParams) (*cid.Cid, error) `perm:"write"` - GasEstimateFeeCap func(p0 context.Context, p1 *types.Message, p2 int64, p3 types.TipSetKey) (types.BigInt, error) `perm:"read"` + CreateBackup func(p0 context.Context, p1 string) error `perm:"admin"` - GasEstimateGasLimit func(p0 context.Context, p1 *types.Message, p2 types.TipSetKey) (int64, error) `perm:"read"` + GasEstimateFeeCap func(p0 context.Context, p1 *types.Message, p2 int64, p3 types.TipSetKey) (types.BigInt, error) `perm:"read"` - GasEstimateGasPremium func(p0 context.Context, p1 uint64, p2 address.Address, p3 int64, p4 types.TipSetKey) (types.BigInt, error) `perm:"read"` + GasEstimateGasLimit func(p0 context.Context, p1 *types.Message, p2 types.TipSetKey) (int64, error) `perm:"read"` - GasEstimateMessageGas func(p0 context.Context, p1 *types.Message, p2 *api.MessageSendSpec, p3 types.TipSetKey) (*types.Message, error) `perm:"read"` + GasEstimateGasPremium func(p0 context.Context, p1 uint64, p2 address.Address, p3 int64, p4 types.TipSetKey) (types.BigInt, error) `perm:"read"` - MarketAddBalance func(p0 context.Context, p1 address.Address, p2 address.Address, p3 types.BigInt) (cid.Cid, error) `perm:"sign"` + GasEstimateMessageGas func(p0 context.Context, p1 *types.Message, p2 *api.MessageSendSpec, p3 types.TipSetKey) (*types.Message, error) `perm:"read"` - MarketGetReserved func(p0 context.Context, p1 address.Address) (types.BigInt, error) `perm:"sign"` + MarketAddBalance func(p0 context.Context, p1 address.Address, p2 address.Address, p3 types.BigInt) (cid.Cid, error) `perm:"sign"` - MarketReleaseFunds func(p0 context.Context, p1 address.Address, p2 types.BigInt) error `perm:"sign"` + MarketGetReserved func(p0 context.Context, p1 address.Address) (types.BigInt, error) `perm:"sign"` - MarketReserveFunds func(p0 context.Context, p1 address.Address, p2 address.Address, p3 types.BigInt) (cid.Cid, error) `perm:"sign"` + MarketReleaseFunds func(p0 context.Context, p1 address.Address, p2 types.BigInt) error `perm:"sign"` - MarketWithdraw func(p0 context.Context, p1 address.Address, p2 address.Address, p3 types.BigInt) (cid.Cid, error) `perm:"sign"` + MarketReserveFunds func(p0 context.Context, p1 address.Address, p2 address.Address, p3 types.BigInt) (cid.Cid, error) `perm:"sign"` - MinerCreateBlock func(p0 context.Context, p1 *api.BlockTemplate) (*types.BlockMsg, error) `perm:"write"` + MarketWithdraw func(p0 context.Context, p1 address.Address, p2 address.Address, p3 types.BigInt) (cid.Cid, error) `perm:"sign"` - MinerGetBaseInfo func(p0 context.Context, p1 address.Address, p2 abi.ChainEpoch, p3 types.TipSetKey) (*api.MiningBaseInfo, error) `perm:"read"` + MinerCreateBlock func(p0 context.Context, p1 *api.BlockTemplate) (*types.BlockMsg, error) `perm:"write"` - MpoolBatchPush func(p0 context.Context, p1 []*types.SignedMessage) ([]cid.Cid, error) `perm:"write"` + MinerGetBaseInfo func(p0 context.Context, p1 address.Address, p2 abi.ChainEpoch, p3 types.TipSetKey) (*api.MiningBaseInfo, error) `perm:"read"` - MpoolBatchPushMessage func(p0 context.Context, p1 []*types.Message, p2 *api.MessageSendSpec) ([]*types.SignedMessage, error) `perm:"sign"` + MpoolBatchPush func(p0 context.Context, p1 []*types.SignedMessage) ([]cid.Cid, error) `perm:"write"` - MpoolBatchPushUntrusted func(p0 context.Context, p1 []*types.SignedMessage) ([]cid.Cid, error) `perm:"write"` + MpoolBatchPushMessage func(p0 context.Context, p1 []*types.Message, p2 *api.MessageSendSpec) ([]*types.SignedMessage, error) `perm:"sign"` - MpoolClear func(p0 context.Context, p1 bool) error `perm:"write"` + MpoolBatchPushUntrusted func(p0 context.Context, p1 []*types.SignedMessage) ([]cid.Cid, error) `perm:"write"` - MpoolGetConfig func(p0 context.Context) (*types.MpoolConfig, error) `perm:"read"` + MpoolClear func(p0 context.Context, p1 bool) error `perm:"write"` - MpoolGetNonce func(p0 context.Context, p1 address.Address) (uint64, error) `perm:"read"` + MpoolGetConfig func(p0 context.Context) (*types.MpoolConfig, error) `perm:"read"` - MpoolPending func(p0 context.Context, p1 types.TipSetKey) ([]*types.SignedMessage, error) `perm:"read"` + MpoolGetNonce func(p0 context.Context, p1 address.Address) (uint64, error) `perm:"read"` - MpoolPush func(p0 context.Context, p1 *types.SignedMessage) (cid.Cid, error) `perm:"write"` + MpoolPending func(p0 context.Context, p1 types.TipSetKey) ([]*types.SignedMessage, error) `perm:"read"` - MpoolPushMessage func(p0 context.Context, p1 *types.Message, p2 *api.MessageSendSpec) (*types.SignedMessage, error) `perm:"sign"` + MpoolPush func(p0 context.Context, p1 *types.SignedMessage) (cid.Cid, error) `perm:"write"` - MpoolPushUntrusted func(p0 context.Context, p1 *types.SignedMessage) (cid.Cid, error) `perm:"write"` + MpoolPushMessage func(p0 context.Context, p1 *types.Message, p2 *api.MessageSendSpec) (*types.SignedMessage, error) `perm:"sign"` - MpoolSelect func(p0 context.Context, p1 types.TipSetKey, p2 float64) ([]*types.SignedMessage, error) `perm:"read"` + MpoolPushUntrusted func(p0 context.Context, p1 *types.SignedMessage) (cid.Cid, error) `perm:"write"` - MpoolSetConfig func(p0 context.Context, p1 *types.MpoolConfig) error `perm:"admin"` + MpoolSelect func(p0 context.Context, p1 types.TipSetKey, p2 float64) ([]*types.SignedMessage, error) `perm:"read"` - MpoolSub func(p0 context.Context) (<-chan api.MpoolUpdate, error) `perm:"read"` + MpoolSetConfig func(p0 context.Context, p1 *types.MpoolConfig) error `perm:"admin"` - MsigAddApprove func(p0 context.Context, p1 address.Address, p2 address.Address, p3 uint64, p4 address.Address, p5 address.Address, p6 bool) (cid.Cid, error) `perm:"sign"` + MpoolSub func(p0 context.Context) (<-chan api.MpoolUpdate, error) `perm:"read"` - MsigAddCancel func(p0 context.Context, p1 address.Address, p2 address.Address, p3 uint64, p4 address.Address, p5 bool) (cid.Cid, error) `perm:"sign"` + MsigAddApprove func(p0 context.Context, p1 address.Address, p2 address.Address, p3 uint64, p4 address.Address, p5 address.Address, p6 bool) (cid.Cid, error) `perm:"sign"` - MsigAddPropose func(p0 context.Context, p1 address.Address, p2 address.Address, p3 address.Address, p4 bool) (cid.Cid, error) `perm:"sign"` + MsigAddCancel func(p0 context.Context, p1 address.Address, p2 address.Address, p3 uint64, p4 address.Address, p5 bool) (cid.Cid, error) `perm:"sign"` - MsigApprove func(p0 context.Context, p1 address.Address, p2 uint64, p3 address.Address) (cid.Cid, error) `perm:"sign"` + MsigAddPropose func(p0 context.Context, p1 address.Address, p2 address.Address, p3 address.Address, p4 bool) (cid.Cid, error) `perm:"sign"` - MsigApproveTxnHash func(p0 context.Context, p1 address.Address, p2 uint64, p3 address.Address, p4 address.Address, p5 types.BigInt, p6 address.Address, p7 uint64, p8 []byte) (cid.Cid, error) `perm:"sign"` + MsigApprove func(p0 context.Context, p1 address.Address, p2 uint64, p3 address.Address) (cid.Cid, error) `perm:"sign"` - MsigCancel func(p0 context.Context, p1 address.Address, p2 uint64, p3 address.Address, p4 types.BigInt, p5 address.Address, p6 uint64, p7 []byte) (cid.Cid, error) `perm:"sign"` + MsigApproveTxnHash func(p0 context.Context, p1 address.Address, p2 uint64, p3 address.Address, p4 address.Address, p5 types.BigInt, p6 address.Address, p7 uint64, p8 []byte) (cid.Cid, error) `perm:"sign"` - MsigCreate func(p0 context.Context, p1 uint64, p2 []address.Address, p3 abi.ChainEpoch, p4 types.BigInt, p5 address.Address, p6 types.BigInt) (cid.Cid, error) `perm:"sign"` + MsigCancel func(p0 context.Context, p1 address.Address, p2 uint64, p3 address.Address, p4 types.BigInt, p5 address.Address, p6 uint64, p7 []byte) (cid.Cid, error) `perm:"sign"` - MsigGetAvailableBalance func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (types.BigInt, error) `perm:"read"` + MsigCreate func(p0 context.Context, p1 uint64, p2 []address.Address, p3 abi.ChainEpoch, p4 types.BigInt, p5 address.Address, p6 types.BigInt) (cid.Cid, error) `perm:"sign"` - MsigGetPending func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) ([]*api.MsigTransaction, error) `perm:"read"` + MsigGetAvailableBalance func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (types.BigInt, error) `perm:"read"` - MsigGetVested func(p0 context.Context, p1 address.Address, p2 types.TipSetKey, p3 types.TipSetKey) (types.BigInt, error) `perm:"read"` + MsigGetPending func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) ([]*api.MsigTransaction, error) `perm:"read"` - MsigGetVestingSchedule func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (api.MsigVesting, error) `perm:"read"` + MsigGetVested func(p0 context.Context, p1 address.Address, p2 types.TipSetKey, p3 types.TipSetKey) (types.BigInt, error) `perm:"read"` - MsigPropose func(p0 context.Context, p1 address.Address, p2 address.Address, p3 types.BigInt, p4 address.Address, p5 uint64, p6 []byte) (cid.Cid, error) `perm:"sign"` + MsigGetVestingSchedule func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (api.MsigVesting, error) `perm:"read"` - MsigRemoveSigner func(p0 context.Context, p1 address.Address, p2 address.Address, p3 address.Address, p4 bool) (cid.Cid, error) `perm:"sign"` + MsigPropose func(p0 context.Context, p1 address.Address, p2 address.Address, p3 types.BigInt, p4 address.Address, p5 uint64, p6 []byte) (cid.Cid, error) `perm:"sign"` - MsigSwapApprove func(p0 context.Context, p1 address.Address, p2 address.Address, p3 uint64, p4 address.Address, p5 address.Address, p6 address.Address) (cid.Cid, error) `perm:"sign"` + MsigRemoveSigner func(p0 context.Context, p1 address.Address, p2 address.Address, p3 address.Address, p4 bool) (cid.Cid, error) `perm:"sign"` - MsigSwapCancel func(p0 context.Context, p1 address.Address, p2 address.Address, p3 uint64, p4 address.Address, p5 address.Address) (cid.Cid, error) `perm:"sign"` + MsigSwapApprove func(p0 context.Context, p1 address.Address, p2 address.Address, p3 uint64, p4 address.Address, p5 address.Address, p6 address.Address) (cid.Cid, error) `perm:"sign"` - MsigSwapPropose func(p0 context.Context, p1 address.Address, p2 address.Address, p3 address.Address, p4 address.Address) (cid.Cid, error) `perm:"sign"` + MsigSwapCancel func(p0 context.Context, p1 address.Address, p2 address.Address, p3 uint64, p4 address.Address, p5 address.Address) (cid.Cid, error) `perm:"sign"` - PaychAllocateLane func(p0 context.Context, p1 address.Address) (uint64, error) `perm:"sign"` + MsigSwapPropose func(p0 context.Context, p1 address.Address, p2 address.Address, p3 address.Address, p4 address.Address) (cid.Cid, error) `perm:"sign"` - PaychAvailableFunds func(p0 context.Context, p1 address.Address) (*api.ChannelAvailableFunds, error) `perm:"sign"` + PaychAllocateLane func(p0 context.Context, p1 address.Address) (uint64, error) `perm:"sign"` - PaychAvailableFundsByFromTo func(p0 context.Context, p1 address.Address, p2 address.Address) (*api.ChannelAvailableFunds, error) `perm:"sign"` + PaychAvailableFunds func(p0 context.Context, p1 address.Address) (*api.ChannelAvailableFunds, error) `perm:"sign"` - PaychCollect func(p0 context.Context, p1 address.Address) (cid.Cid, error) `perm:"sign"` + PaychAvailableFundsByFromTo func(p0 context.Context, p1 address.Address, p2 address.Address) (*api.ChannelAvailableFunds, error) `perm:"sign"` - PaychGet func(p0 context.Context, p1 address.Address, p2 address.Address, p3 types.BigInt) (*api.ChannelInfo, error) `perm:"sign"` + PaychCollect func(p0 context.Context, p1 address.Address) (cid.Cid, error) `perm:"sign"` - PaychGetWaitReady func(p0 context.Context, p1 cid.Cid) (address.Address, error) `perm:"sign"` + PaychGet func(p0 context.Context, p1 address.Address, p2 address.Address, p3 types.BigInt) (*api.ChannelInfo, error) `perm:"sign"` - PaychList func(p0 context.Context) ([]address.Address, error) `perm:"read"` + PaychGetWaitReady func(p0 context.Context, p1 cid.Cid) (address.Address, error) `perm:"sign"` - PaychNewPayment func(p0 context.Context, p1 address.Address, p2 address.Address, p3 []api.VoucherSpec) (*api.PaymentInfo, error) `perm:"sign"` + PaychList func(p0 context.Context) ([]address.Address, error) `perm:"read"` - PaychSettle func(p0 context.Context, p1 address.Address) (cid.Cid, error) `perm:"sign"` + PaychNewPayment func(p0 context.Context, p1 address.Address, p2 address.Address, p3 []api.VoucherSpec) (*api.PaymentInfo, error) `perm:"sign"` - PaychStatus func(p0 context.Context, p1 address.Address) (*api.PaychStatus, error) `perm:"read"` + PaychSettle func(p0 context.Context, p1 address.Address) (cid.Cid, error) `perm:"sign"` - PaychVoucherAdd func(p0 context.Context, p1 address.Address, p2 *paych.SignedVoucher, p3 []byte, p4 types.BigInt) (types.BigInt, error) `perm:"write"` + PaychStatus func(p0 context.Context, p1 address.Address) (*api.PaychStatus, error) `perm:"read"` - PaychVoucherCheckSpendable func(p0 context.Context, p1 address.Address, p2 *paych.SignedVoucher, p3 []byte, p4 []byte) (bool, error) `perm:"read"` + PaychVoucherAdd func(p0 context.Context, p1 address.Address, p2 *paych.SignedVoucher, p3 []byte, p4 types.BigInt) (types.BigInt, error) `perm:"write"` - PaychVoucherCheckValid func(p0 context.Context, p1 address.Address, p2 *paych.SignedVoucher) error `perm:"read"` + PaychVoucherCheckSpendable func(p0 context.Context, p1 address.Address, p2 *paych.SignedVoucher, p3 []byte, p4 []byte) (bool, error) `perm:"read"` - PaychVoucherCreate func(p0 context.Context, p1 address.Address, p2 types.BigInt, p3 uint64) (*api.VoucherCreateResult, error) `perm:"sign"` + PaychVoucherCheckValid func(p0 context.Context, p1 address.Address, p2 *paych.SignedVoucher) error `perm:"read"` - PaychVoucherList func(p0 context.Context, p1 address.Address) ([]*paych.SignedVoucher, error) `perm:"write"` + PaychVoucherCreate func(p0 context.Context, p1 address.Address, p2 types.BigInt, p3 uint64) (*api.VoucherCreateResult, error) `perm:"sign"` - PaychVoucherSubmit func(p0 context.Context, p1 address.Address, p2 *paych.SignedVoucher, p3 []byte, p4 []byte) (cid.Cid, error) `perm:"sign"` + PaychVoucherList func(p0 context.Context, p1 address.Address) ([]*paych.SignedVoucher, error) `perm:"write"` - StateAccountKey func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (address.Address, error) `perm:"read"` + PaychVoucherSubmit func(p0 context.Context, p1 address.Address, p2 *paych.SignedVoucher, p3 []byte, p4 []byte) (cid.Cid, error) `perm:"sign"` - StateActorCodeCIDs func(p0 context.Context, p1 abinetwork.Version) (map[string]cid.Cid, error) `perm:"read"` + StateAccountKey func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (address.Address, error) `perm:"read"` - StateActorManifestCID func(p0 context.Context, p1 abinetwork.Version) (cid.Cid, error) `perm:"read"` + StateActorCodeCIDs func(p0 context.Context, p1 abinetwork.Version) (map[string]cid.Cid, error) `perm:"read"` - StateAllMinerFaults func(p0 context.Context, p1 abi.ChainEpoch, p2 types.TipSetKey) ([]*api.Fault, error) `perm:"read"` + StateActorManifestCID func(p0 context.Context, p1 abinetwork.Version) (cid.Cid, error) `perm:"read"` - StateCall func(p0 context.Context, p1 *types.Message, p2 types.TipSetKey) (*api.InvocResult, error) `perm:"read"` + StateAllMinerFaults func(p0 context.Context, p1 abi.ChainEpoch, p2 types.TipSetKey) ([]*api.Fault, error) `perm:"read"` - StateChangedActors func(p0 context.Context, p1 cid.Cid, p2 cid.Cid) (map[string]types.Actor, error) `perm:"read"` + StateCall func(p0 context.Context, p1 *types.Message, p2 types.TipSetKey) (*api.InvocResult, error) `perm:"read"` - StateCirculatingSupply func(p0 context.Context, p1 types.TipSetKey) (abi.TokenAmount, error) `perm:"read"` + StateChangedActors func(p0 context.Context, p1 cid.Cid, p2 cid.Cid) (map[string]types.Actor, error) `perm:"read"` - StateCompute func(p0 context.Context, p1 abi.ChainEpoch, p2 []*types.Message, p3 types.TipSetKey) (*api.ComputeStateOutput, error) `perm:"read"` + StateCirculatingSupply func(p0 context.Context, p1 types.TipSetKey) (abi.TokenAmount, error) `perm:"read"` - StateDealProviderCollateralBounds func(p0 context.Context, p1 abi.PaddedPieceSize, p2 bool, p3 types.TipSetKey) (api.DealCollateralBounds, error) `perm:"read"` + StateCompute func(p0 context.Context, p1 abi.ChainEpoch, p2 []*types.Message, p3 types.TipSetKey) (*api.ComputeStateOutput, error) `perm:"read"` - StateDecodeParams func(p0 context.Context, p1 address.Address, p2 abi.MethodNum, p3 []byte, p4 types.TipSetKey) (interface{}, error) `perm:"read"` + StateDealProviderCollateralBounds func(p0 context.Context, p1 abi.PaddedPieceSize, p2 bool, p3 types.TipSetKey) (api.DealCollateralBounds, error) `perm:"read"` - StateGetActor func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (*types.Actor, error) `perm:"read"` + StateDecodeParams func(p0 context.Context, p1 address.Address, p2 abi.MethodNum, p3 []byte, p4 types.TipSetKey) (interface{}, error) `perm:"read"` - StateGetAllocation func(p0 context.Context, p1 address.Address, p2 verifregtypes.AllocationId, p3 types.TipSetKey) (*verifregtypes.Allocation, error) `perm:"read"` + StateGetActor func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (*types.Actor, error) `perm:"read"` - StateGetAllocationForPendingDeal func(p0 context.Context, p1 abi.DealID, p2 types.TipSetKey) (*verifregtypes.Allocation, error) `perm:"read"` + StateGetAllocation func(p0 context.Context, p1 address.Address, p2 verifregtypes.AllocationId, p3 types.TipSetKey) (*verifregtypes.Allocation, error) `perm:"read"` - StateGetAllocations func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (map[verifregtypes.AllocationId]verifregtypes.Allocation, error) `perm:"read"` + StateGetAllocationForPendingDeal func(p0 context.Context, p1 abi.DealID, p2 types.TipSetKey) (*verifregtypes.Allocation, error) `perm:"read"` - StateGetClaim func(p0 context.Context, p1 address.Address, p2 verifregtypes.ClaimId, p3 types.TipSetKey) (*verifregtypes.Claim, error) `perm:"read"` + StateGetAllocations func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (map[verifregtypes.AllocationId]verifregtypes.Allocation, error) `perm:"read"` - StateGetClaims func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (map[verifregtypes.ClaimId]verifregtypes.Claim, error) `perm:"read"` + StateGetClaim func(p0 context.Context, p1 address.Address, p2 verifregtypes.ClaimId, p3 types.TipSetKey) (*verifregtypes.Claim, error) `perm:"read"` - StateGetNetworkParams func(p0 context.Context) (*api.NetworkParams, error) `perm:"read"` + StateGetClaims func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (map[verifregtypes.ClaimId]verifregtypes.Claim, error) `perm:"read"` - StateGetRandomnessFromBeacon func(p0 context.Context, p1 crypto.DomainSeparationTag, p2 abi.ChainEpoch, p3 []byte, p4 types.TipSetKey) (abi.Randomness, error) `perm:"read"` + StateGetNetworkParams func(p0 context.Context) (*api.NetworkParams, error) `perm:"read"` - StateGetRandomnessFromTickets func(p0 context.Context, p1 crypto.DomainSeparationTag, p2 abi.ChainEpoch, p3 []byte, p4 types.TipSetKey) (abi.Randomness, error) `perm:"read"` + StateGetRandomnessFromBeacon func(p0 context.Context, p1 crypto.DomainSeparationTag, p2 abi.ChainEpoch, p3 []byte, p4 types.TipSetKey) (abi.Randomness, error) `perm:"read"` - StateGetReceipt func(p0 context.Context, p1 cid.Cid, p2 types.TipSetKey) (*types.MessageReceipt, error) `perm:"read"` + StateGetRandomnessFromTickets func(p0 context.Context, p1 crypto.DomainSeparationTag, p2 abi.ChainEpoch, p3 []byte, p4 types.TipSetKey) (abi.Randomness, error) `perm:"read"` - StateListActors func(p0 context.Context, p1 types.TipSetKey) ([]address.Address, error) `perm:"read"` + StateGetReceipt func(p0 context.Context, p1 cid.Cid, p2 types.TipSetKey) (*types.MessageReceipt, error) `perm:"read"` - StateListMessages func(p0 context.Context, p1 *api.MessageMatch, p2 types.TipSetKey, p3 abi.ChainEpoch) ([]cid.Cid, error) `perm:"read"` + StateListActors func(p0 context.Context, p1 types.TipSetKey) ([]address.Address, error) `perm:"read"` - StateListMiners func(p0 context.Context, p1 types.TipSetKey) ([]address.Address, error) `perm:"read"` + StateListMessages func(p0 context.Context, p1 *api.MessageMatch, p2 types.TipSetKey, p3 abi.ChainEpoch) ([]cid.Cid, error) `perm:"read"` - StateLookupID func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (address.Address, error) `perm:"read"` + StateListMiners func(p0 context.Context, p1 types.TipSetKey) ([]address.Address, error) `perm:"read"` - StateMarketBalance func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (api.MarketBalance, error) `perm:"read"` + StateLookupID func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (address.Address, error) `perm:"read"` - StateMarketDeals func(p0 context.Context, p1 types.TipSetKey) (map[string]*api.MarketDeal, error) `perm:"read"` + StateMarketBalance func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (api.MarketBalance, error) `perm:"read"` - StateMarketParticipants func(p0 context.Context, p1 types.TipSetKey) (map[string]api.MarketBalance, error) `perm:"read"` + StateMarketDeals func(p0 context.Context, p1 types.TipSetKey) (map[string]*api.MarketDeal, error) `perm:"read"` - StateMarketStorageDeal func(p0 context.Context, p1 abi.DealID, p2 types.TipSetKey) (*api.MarketDeal, error) `perm:"read"` + StateMarketParticipants func(p0 context.Context, p1 types.TipSetKey) (map[string]api.MarketBalance, error) `perm:"read"` - StateMinerActiveSectors func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) ([]*miner.SectorOnChainInfo, error) `perm:"read"` + StateMarketStorageDeal func(p0 context.Context, p1 abi.DealID, p2 types.TipSetKey) (*api.MarketDeal, error) `perm:"read"` - StateMinerAvailableBalance func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (types.BigInt, error) `perm:"read"` + StateMinerActiveSectors func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) ([]*miner.SectorOnChainInfo, error) `perm:"read"` - StateMinerDeadlines func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) ([]api.Deadline, error) `perm:"read"` + StateMinerAvailableBalance func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (types.BigInt, error) `perm:"read"` - StateMinerFaults func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (bitfield.BitField, error) `perm:"read"` + StateMinerDeadlines func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) ([]api.Deadline, error) `perm:"read"` - StateMinerInfo func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (api.MinerInfo, error) `perm:"read"` + StateMinerFaults func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (bitfield.BitField, error) `perm:"read"` - StateMinerInitialPledgeCollateral func(p0 context.Context, p1 address.Address, p2 miner.SectorPreCommitInfo, p3 types.TipSetKey) (types.BigInt, error) `perm:"read"` + StateMinerInfo func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (api.MinerInfo, error) `perm:"read"` - StateMinerPartitions func(p0 context.Context, p1 address.Address, p2 uint64, p3 types.TipSetKey) ([]api.Partition, error) `perm:"read"` + StateMinerInitialPledgeCollateral func(p0 context.Context, p1 address.Address, p2 miner.SectorPreCommitInfo, p3 types.TipSetKey) (types.BigInt, error) `perm:"read"` - StateMinerPower func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (*api.MinerPower, error) `perm:"read"` + StateMinerPartitions func(p0 context.Context, p1 address.Address, p2 uint64, p3 types.TipSetKey) ([]api.Partition, error) `perm:"read"` - StateMinerPreCommitDepositForPower func(p0 context.Context, p1 address.Address, p2 miner.SectorPreCommitInfo, p3 types.TipSetKey) (types.BigInt, error) `perm:"read"` + StateMinerPower func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (*api.MinerPower, error) `perm:"read"` - StateMinerProvingDeadline func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (*dline.Info, error) `perm:"read"` + StateMinerPreCommitDepositForPower func(p0 context.Context, p1 address.Address, p2 miner.SectorPreCommitInfo, p3 types.TipSetKey) (types.BigInt, error) `perm:"read"` - StateMinerRecoveries func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (bitfield.BitField, error) `perm:"read"` + StateMinerProvingDeadline func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (*dline.Info, error) `perm:"read"` - StateMinerSectorAllocated func(p0 context.Context, p1 address.Address, p2 abi.SectorNumber, p3 types.TipSetKey) (bool, error) `perm:"read"` + StateMinerRecoveries func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (bitfield.BitField, error) `perm:"read"` - StateMinerSectorCount func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (api.MinerSectors, error) `perm:"read"` + StateMinerSectorAllocated func(p0 context.Context, p1 address.Address, p2 abi.SectorNumber, p3 types.TipSetKey) (bool, error) `perm:"read"` - StateMinerSectors func(p0 context.Context, p1 address.Address, p2 *bitfield.BitField, p3 types.TipSetKey) ([]*miner.SectorOnChainInfo, error) `perm:"read"` + StateMinerSectorCount func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (api.MinerSectors, error) `perm:"read"` - StateNetworkName func(p0 context.Context) (dtypes.NetworkName, error) `perm:"read"` + StateMinerSectors func(p0 context.Context, p1 address.Address, p2 *bitfield.BitField, p3 types.TipSetKey) ([]*miner.SectorOnChainInfo, error) `perm:"read"` - StateNetworkVersion func(p0 context.Context, p1 types.TipSetKey) (apitypes.NetworkVersion, error) `perm:"read"` + StateNetworkName func(p0 context.Context) (dtypes.NetworkName, error) `perm:"read"` - StateReadState func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (*api.ActorState, error) `perm:"read"` + StateNetworkVersion func(p0 context.Context, p1 types.TipSetKey) (apitypes.NetworkVersion, error) `perm:"read"` - StateReplay func(p0 context.Context, p1 types.TipSetKey, p2 cid.Cid) (*api.InvocResult, error) `perm:"read"` + StateReadState func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (*api.ActorState, error) `perm:"read"` - StateSearchMsg func(p0 context.Context, p1 cid.Cid) (*api.MsgLookup, error) `perm:"read"` + StateReplay func(p0 context.Context, p1 types.TipSetKey, p2 cid.Cid) (*api.InvocResult, error) `perm:"read"` - StateSearchMsgLimited func(p0 context.Context, p1 cid.Cid, p2 abi.ChainEpoch) (*api.MsgLookup, error) `perm:"read"` + StateSearchMsg func(p0 context.Context, p1 cid.Cid) (*api.MsgLookup, error) `perm:"read"` - StateSectorExpiration func(p0 context.Context, p1 address.Address, p2 abi.SectorNumber, p3 types.TipSetKey) (*lminer.SectorExpiration, error) `perm:"read"` + StateSearchMsgLimited func(p0 context.Context, p1 cid.Cid, p2 abi.ChainEpoch) (*api.MsgLookup, error) `perm:"read"` - StateSectorGetInfo func(p0 context.Context, p1 address.Address, p2 abi.SectorNumber, p3 types.TipSetKey) (*miner.SectorOnChainInfo, error) `perm:"read"` + StateSectorExpiration func(p0 context.Context, p1 address.Address, p2 abi.SectorNumber, p3 types.TipSetKey) (*lminer.SectorExpiration, error) `perm:"read"` - StateSectorPartition func(p0 context.Context, p1 address.Address, p2 abi.SectorNumber, p3 types.TipSetKey) (*lminer.SectorLocation, error) `perm:"read"` + StateSectorGetInfo func(p0 context.Context, p1 address.Address, p2 abi.SectorNumber, p3 types.TipSetKey) (*miner.SectorOnChainInfo, error) `perm:"read"` - StateSectorPreCommitInfo func(p0 context.Context, p1 address.Address, p2 abi.SectorNumber, p3 types.TipSetKey) (miner.SectorPreCommitOnChainInfo, error) `perm:"read"` + StateSectorPartition func(p0 context.Context, p1 address.Address, p2 abi.SectorNumber, p3 types.TipSetKey) (*lminer.SectorLocation, error) `perm:"read"` - StateVMCirculatingSupplyInternal func(p0 context.Context, p1 types.TipSetKey) (api.CirculatingSupply, error) `perm:"read"` + StateSectorPreCommitInfo func(p0 context.Context, p1 address.Address, p2 abi.SectorNumber, p3 types.TipSetKey) (miner.SectorPreCommitOnChainInfo, error) `perm:"read"` - StateVerifiedClientStatus func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (*abi.StoragePower, error) `perm:"read"` + StateVMCirculatingSupplyInternal func(p0 context.Context, p1 types.TipSetKey) (api.CirculatingSupply, error) `perm:"read"` - StateVerifiedRegistryRootKey func(p0 context.Context, p1 types.TipSetKey) (address.Address, error) `perm:"read"` + StateVerifiedClientStatus func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (*abi.StoragePower, error) `perm:"read"` - StateVerifierStatus func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (*abi.StoragePower, error) `perm:"read"` + StateVerifiedRegistryRootKey func(p0 context.Context, p1 types.TipSetKey) (address.Address, error) `perm:"read"` - StateWaitMsg func(p0 context.Context, p1 cid.Cid, p2 uint64) (*api.MsgLookup, error) `perm:"read"` + StateVerifierStatus func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (*abi.StoragePower, error) `perm:"read"` - StateWaitMsgLimited func(p0 context.Context, p1 cid.Cid, p2 uint64, p3 abi.ChainEpoch) (*api.MsgLookup, error) `perm:"read"` + StateWaitMsg func(p0 context.Context, p1 cid.Cid, p2 uint64) (*api.MsgLookup, error) `perm:"read"` - SyncCheckBad func(p0 context.Context, p1 cid.Cid) (string, error) `perm:"read"` + StateWaitMsgLimited func(p0 context.Context, p1 cid.Cid, p2 uint64, p3 abi.ChainEpoch) (*api.MsgLookup, error) `perm:"read"` - SyncCheckpoint func(p0 context.Context, p1 types.TipSetKey) error `perm:"admin"` + SyncCheckBad func(p0 context.Context, p1 cid.Cid) (string, error) `perm:"read"` - SyncIncomingBlocks func(p0 context.Context) (<-chan *types.BlockHeader, error) `perm:"read"` + SyncCheckpoint func(p0 context.Context, p1 types.TipSetKey) error `perm:"admin"` - SyncMarkBad func(p0 context.Context, p1 cid.Cid) error `perm:"admin"` + SyncIncomingBlocks func(p0 context.Context) (<-chan *types.BlockHeader, error) `perm:"read"` - SyncState func(p0 context.Context) (*api.SyncState, error) `perm:"read"` + SyncMarkBad func(p0 context.Context, p1 cid.Cid) error `perm:"admin"` - SyncSubmitBlock func(p0 context.Context, p1 *types.BlockMsg) error `perm:"write"` + SyncState func(p0 context.Context) (*api.SyncState, error) `perm:"read"` - SyncUnmarkAllBad func(p0 context.Context) error `perm:"admin"` + SyncSubmitBlock func(p0 context.Context, p1 *types.BlockMsg) error `perm:"write"` - SyncUnmarkBad func(p0 context.Context, p1 cid.Cid) error `perm:"admin"` + SyncUnmarkAllBad func(p0 context.Context) error `perm:"admin"` - SyncValidateTipset func(p0 context.Context, p1 types.TipSetKey) (bool, error) `perm:"read"` + SyncUnmarkBad func(p0 context.Context, p1 cid.Cid) error `perm:"admin"` - WalletBalance func(p0 context.Context, p1 address.Address) (types.BigInt, error) `perm:"read"` + SyncValidateTipset func(p0 context.Context, p1 types.TipSetKey) (bool, error) `perm:"read"` - WalletDefaultAddress func(p0 context.Context) (address.Address, error) `perm:"write"` + WalletBalance func(p0 context.Context, p1 address.Address) (types.BigInt, error) `perm:"read"` - WalletDelete func(p0 context.Context, p1 address.Address) error `perm:"admin"` + WalletDefaultAddress func(p0 context.Context) (address.Address, error) `perm:"write"` - WalletExport func(p0 context.Context, p1 address.Address) (*types.KeyInfo, error) `perm:"admin"` + WalletDelete func(p0 context.Context, p1 address.Address) error `perm:"admin"` - WalletHas func(p0 context.Context, p1 address.Address) (bool, error) `perm:"write"` + WalletExport func(p0 context.Context, p1 address.Address) (*types.KeyInfo, error) `perm:"admin"` - WalletImport func(p0 context.Context, p1 *types.KeyInfo) (address.Address, error) `perm:"admin"` + WalletHas func(p0 context.Context, p1 address.Address) (bool, error) `perm:"write"` - WalletList func(p0 context.Context) ([]address.Address, error) `perm:"write"` + WalletImport func(p0 context.Context, p1 *types.KeyInfo) (address.Address, error) `perm:"admin"` - WalletNew func(p0 context.Context, p1 types.KeyType) (address.Address, error) `perm:"write"` + WalletList func(p0 context.Context) ([]address.Address, error) `perm:"write"` - WalletSetDefault func(p0 context.Context, p1 address.Address) error `perm:"write"` + WalletNew func(p0 context.Context, p1 types.KeyType) (address.Address, error) `perm:"write"` - WalletSign func(p0 context.Context, p1 address.Address, p2 []byte) (*crypto.Signature, error) `perm:"sign"` + WalletSetDefault func(p0 context.Context, p1 address.Address) error `perm:"write"` - WalletSignMessage func(p0 context.Context, p1 address.Address, p2 *types.Message) (*types.SignedMessage, error) `perm:"sign"` + WalletSign func(p0 context.Context, p1 address.Address, p2 []byte) (*crypto.Signature, error) `perm:"sign"` - WalletValidateAddress func(p0 context.Context, p1 string) (address.Address, error) `perm:"read"` + WalletSignMessage func(p0 context.Context, p1 address.Address, p2 *types.Message) (*types.SignedMessage, error) `perm:"sign"` - WalletVerify func(p0 context.Context, p1 address.Address, p2 []byte, p3 *crypto.Signature) (bool, error) `perm:"read"` - } + WalletValidateAddress func(p0 context.Context, p1 string) (address.Address, error) `perm:"read"` + + WalletVerify func(p0 context.Context, p1 address.Address, p2 []byte, p3 *crypto.Signature) (bool, error) `perm:"read"` } type FullNodeStub struct { @@ -425,71 +427,73 @@ type FullNodeStub struct { } type GatewayStruct struct { - Internal struct { - ChainGetBlockMessages func(p0 context.Context, p1 cid.Cid) (*api.BlockMessages, error) `` + Internal GatewayMethods +} - ChainGetMessage func(p0 context.Context, p1 cid.Cid) (*types.Message, error) `` +type GatewayMethods struct { + ChainGetBlockMessages func(p0 context.Context, p1 cid.Cid) (*api.BlockMessages, error) `` - ChainGetTipSet func(p0 context.Context, p1 types.TipSetKey) (*types.TipSet, error) `` + ChainGetMessage func(p0 context.Context, p1 cid.Cid) (*types.Message, error) `` - ChainGetTipSetByHeight func(p0 context.Context, p1 abi.ChainEpoch, p2 types.TipSetKey) (*types.TipSet, error) `` + ChainGetTipSet func(p0 context.Context, p1 types.TipSetKey) (*types.TipSet, error) `` - ChainHasObj func(p0 context.Context, p1 cid.Cid) (bool, error) `` + ChainGetTipSetByHeight func(p0 context.Context, p1 abi.ChainEpoch, p2 types.TipSetKey) (*types.TipSet, error) `` - ChainHead func(p0 context.Context) (*types.TipSet, error) `` + ChainHasObj func(p0 context.Context, p1 cid.Cid) (bool, error) `` - ChainNotify func(p0 context.Context) (<-chan []*api.HeadChange, error) `` + ChainHead func(p0 context.Context) (*types.TipSet, error) `` - ChainPutObj func(p0 context.Context, p1 blocks.Block) error `` + ChainNotify func(p0 context.Context) (<-chan []*api.HeadChange, error) `` - ChainReadObj func(p0 context.Context, p1 cid.Cid) ([]byte, error) `` + ChainPutObj func(p0 context.Context, p1 blocks.Block) error `` - GasEstimateMessageGas func(p0 context.Context, p1 *types.Message, p2 *api.MessageSendSpec, p3 types.TipSetKey) (*types.Message, error) `` + ChainReadObj func(p0 context.Context, p1 cid.Cid) ([]byte, error) `` - MpoolPush func(p0 context.Context, p1 *types.SignedMessage) (cid.Cid, error) `` + GasEstimateMessageGas func(p0 context.Context, p1 *types.Message, p2 *api.MessageSendSpec, p3 types.TipSetKey) (*types.Message, error) `` - MsigGetAvailableBalance func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (types.BigInt, error) `` + MpoolPush func(p0 context.Context, p1 *types.SignedMessage) (cid.Cid, error) `` - MsigGetPending func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) ([]*api.MsigTransaction, error) `` + MsigGetAvailableBalance func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (types.BigInt, error) `` - MsigGetVested func(p0 context.Context, p1 address.Address, p2 types.TipSetKey, p3 types.TipSetKey) (types.BigInt, error) `` + MsigGetPending func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) ([]*api.MsigTransaction, error) `` - StateAccountKey func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (address.Address, error) `` + MsigGetVested func(p0 context.Context, p1 address.Address, p2 types.TipSetKey, p3 types.TipSetKey) (types.BigInt, error) `` - StateDealProviderCollateralBounds func(p0 context.Context, p1 abi.PaddedPieceSize, p2 bool, p3 types.TipSetKey) (api.DealCollateralBounds, error) `` + StateAccountKey func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (address.Address, error) `` - StateGetActor func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (*types.Actor, error) `` + StateDealProviderCollateralBounds func(p0 context.Context, p1 abi.PaddedPieceSize, p2 bool, p3 types.TipSetKey) (api.DealCollateralBounds, error) `` - StateGetReceipt func(p0 context.Context, p1 cid.Cid, p2 types.TipSetKey) (*types.MessageReceipt, error) `` + StateGetActor func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (*types.Actor, error) `` - StateListMiners func(p0 context.Context, p1 types.TipSetKey) ([]address.Address, error) `` + StateGetReceipt func(p0 context.Context, p1 cid.Cid, p2 types.TipSetKey) (*types.MessageReceipt, error) `` - StateLookupID func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (address.Address, error) `` + StateListMiners func(p0 context.Context, p1 types.TipSetKey) ([]address.Address, error) `` - StateMarketBalance func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (api.MarketBalance, error) `` + StateLookupID func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (address.Address, error) `` - StateMarketStorageDeal func(p0 context.Context, p1 abi.DealID, p2 types.TipSetKey) (*api.MarketDeal, error) `` + StateMarketBalance func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (api.MarketBalance, error) `` - StateMinerInfo func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (api.MinerInfo, error) `` + StateMarketStorageDeal func(p0 context.Context, p1 abi.DealID, p2 types.TipSetKey) (*api.MarketDeal, error) `` - StateMinerPower func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (*api.MinerPower, error) `` + StateMinerInfo func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (api.MinerInfo, error) `` - StateMinerProvingDeadline func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (*dline.Info, error) `` + StateMinerPower func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (*api.MinerPower, error) `` - StateNetworkVersion func(p0 context.Context, p1 types.TipSetKey) (abinetwork.Version, error) `` + StateMinerProvingDeadline func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (*dline.Info, error) `` - StateSearchMsg func(p0 context.Context, p1 cid.Cid) (*api.MsgLookup, error) `` + StateNetworkVersion func(p0 context.Context, p1 types.TipSetKey) (abinetwork.Version, error) `` - StateSectorGetInfo func(p0 context.Context, p1 address.Address, p2 abi.SectorNumber, p3 types.TipSetKey) (*miner.SectorOnChainInfo, error) `` + StateSearchMsg func(p0 context.Context, p1 cid.Cid) (*api.MsgLookup, error) `` - StateVerifiedClientStatus func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (*abi.StoragePower, error) `` + StateSectorGetInfo func(p0 context.Context, p1 address.Address, p2 abi.SectorNumber, p3 types.TipSetKey) (*miner.SectorOnChainInfo, error) `` - StateWaitMsg func(p0 context.Context, p1 cid.Cid, p2 uint64) (*api.MsgLookup, error) `` + StateVerifiedClientStatus func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (*abi.StoragePower, error) `` - Version func(p0 context.Context) (api.APIVersion, error) `` + StateWaitMsg func(p0 context.Context, p1 cid.Cid, p2 uint64) (*api.MsgLookup, error) `` - WalletBalance func(p0 context.Context, p1 address.Address) (types.BigInt, error) `` - } + Version func(p0 context.Context) (api.APIVersion, error) `` + + WalletBalance func(p0 context.Context, p1 address.Address) (types.BigInt, error) `` } type GatewayStub struct { diff --git a/build/actors/pack.sh b/build/actors/pack.sh index 2702c80d5..863a3c5c7 100755 --- a/build/actors/pack.sh +++ b/build/actors/pack.sh @@ -1,6 +1,6 @@ #!/bin/bash -NETWORKS=(devnet mainnet caterpillarnet butterflynet testing testing-fake-proofs calibrationnet hyperspace) +NETWORKS=(devnet mainnet caterpillarnet butterflynet testing testing-fake-proofs calibrationnet) set -e @@ -52,4 +52,4 @@ popd echo "Generating metadata..." -make -C ../../ bundle-gen +make -C ../../ RELEASE="$RELEASE" bundle-gen diff --git a/build/actors/v10.tar.zst b/build/actors/v10.tar.zst index b0c9e5ce8..70208151e 100644 Binary files a/build/actors/v10.tar.zst and b/build/actors/v10.tar.zst differ diff --git a/build/actors/v9.tar.zst b/build/actors/v9.tar.zst index 55d0eba0b..f19c7db4c 100644 Binary files a/build/actors/v9.tar.zst and b/build/actors/v9.tar.zst differ diff --git a/build/bootstrap/butterflynet.pi b/build/bootstrap/butterflynet.pi index 556b5d14f..1def01c7c 100644 --- a/build/bootstrap/butterflynet.pi +++ b/build/bootstrap/butterflynet.pi @@ -1,2 +1,2 @@ -/dns4/bootstrap-0.butterfly.fildev.network/tcp/1347/p2p/12D3KooWKeDMuJbouvypr1nL2qRruhNVXzv4QiLsZRh6gnvLkc7p -/dns4/bootstrap-1.butterfly.fildev.network/tcp/1347/p2p/12D3KooWSsACNHLGoJbPqeitNY7tom19Nxq8x5ag36eTwmgcAeLo +/dns4/bootstrap-0.butterfly.fildev.network/tcp/1347/p2p/12D3KooWHkVVMJ1rfVLM5poNrgwTJiaDkpDLkPqQ9zVuNPQ7AJ6p +/dns4/bootstrap-1.butterfly.fildev.network/tcp/1347/p2p/12D3KooWRyzqeQd51HCvVK3nvegmnBsYYPLSZbxR3Q9XAoUrUZ18 diff --git a/build/bootstrap/wallabynet.pi b/build/bootstrap/wallabynet.pi deleted file mode 100644 index 322e550bb..000000000 --- a/build/bootstrap/wallabynet.pi +++ /dev/null @@ -1,4 +0,0 @@ -/dns4/de0.bootstrap.wallaby.network/tcp/1337/p2p/12D3KooWHAvUVk5XuxSwi2dNLWbTDDRSGeHxMuWdQ3SQpRuNHbLz -/dns4/de1.bootstrap.wallaby.network/tcp/1337/p2p/12D3KooWBRqtxhJCtiLmCwKgAQozJtdGinEDdJGoS5oHw7vCjMGc -/dns4/ca0.bootstrap.wallaby.network/tcp/1337/p2p/12D3KooWCApBpUk7EX9pmEfyky1gKC6N2KJ74S1AwFfvnkDqw3pK -/dns4/sg0.bootstrap.wallaby.network/tcp/1337/p2p/12D3KooWLnYqr4hRoNHBJQVXsFGkDoKuoVfw5R2ASw1bHzrWU5Px \ No newline at end of file diff --git a/build/builtin_actors.go b/build/builtin_actors.go index 4d283919e..50aecde40 100644 --- a/build/builtin_actors.go +++ b/build/builtin_actors.go @@ -95,10 +95,11 @@ func loadManifests(netw string) error { } type BuiltinActorsMetadata struct { - Network string - Version actorstypes.Version - ManifestCid cid.Cid - Actors map[string]cid.Cid + Network string + Version actorstypes.Version + ManifestCid cid.Cid + Actors map[string]cid.Cid + BundleGitTag string } // ReadEmbeddedBuiltinActorsMetadata reads the metadata from the embedded built-in actor bundles. diff --git a/build/builtin_actors_gen.go b/build/builtin_actors_gen.go index 38d4c49ed..df504f51d 100644 --- a/build/builtin_actors_gen.go +++ b/build/builtin_actors_gen.go @@ -31,46 +31,42 @@ var EmbeddedBuiltinActorsMetadata []*BuiltinActorsMetadata = []*BuiltinActorsMet }, { Network: "butterflynet", Version: 9, - ManifestCid: MustParseCid("bafy2bzaceba5qgs4z3imhlxwds5vamahngatvuuglbv5yl3ftfiosj6ud5chs"), + ManifestCid: MustParseCid("bafy2bzacec35by4erhcdgcsgzp7yb3j57utydlxxfc73m3k5pep67ehvvyv6i"), Actors: map[string]cid.Cid{ - "account": MustParseCid("bafk2bzacebd5zetyjtragjwrv2nqktct6u2pmsi4eifbanovxohx3a7lszjxi"), - "cron": MustParseCid("bafk2bzacecrszortqkc7har77ssgajglymv6ftrqvmdko5h2yqqh5k2qospl2"), - "datacap": MustParseCid("bafk2bzacecapjnxnyw4talwqv5ajbtbkzmzqiosztj5cb3sortyp73ndjl76e"), - "eam": MustParseCid("bafk2bzacecflry2dyjqj6fhpovkbcbei377zabectznuxsf6bxggsve7bsxga"), - "ethaccount": MustParseCid("bafk2bzacedl4pmkfxkzoqajs6im3ranmopozsmxjcxsnk3kwvd3vv7mfwwrf4"), - "evm": MustParseCid("bafk2bzacebgzvmvwv7rsnnhp3zhqbiqkumvyrc7pazfovpptgpgtqkalrli74"), - "init": MustParseCid("bafk2bzacecbxp66q3ytjkg37nyv4rmzezbfaigvx4i5yhvqbm5gg4amjeaias"), - "multisig": MustParseCid("bafk2bzacecjltag3mn75dsnmrmopjow27buxqhabissowayqlmavrcfetqswc"), - "paymentchannel": MustParseCid("bafk2bzacednzxg263eqbl2imwz3uhujov63tjkffieyl4hl3dhrgxyhwep6hc"), - "placeholder": MustParseCid("bafk2bzaceaamp2a35vpfml4skap4dffklzae2urcm34mtwwce2lvhaons3a5y"), - "reward": MustParseCid("bafk2bzacectp23cxsbbdrr3uggnw7f263qll5wkkfzqhn5yq37ae2ehdjdzri"), - "storagemarket": MustParseCid("bafk2bzacea45ko3ezkpeujsniovncwnizc4wsxd7kyckskhs7gvzwthzb2mqe"), - "storageminer": MustParseCid("bafk2bzaced74qthwrl3gahcf7o3vrdrodbcqhlplh6fykbgy5sd2iyouhq44c"), - "storagepower": MustParseCid("bafk2bzaceduksv6wqthr5fgp7mx5prv6gzul2oozf3svrjbuggc4bgokdxgfy"), - "system": MustParseCid("bafk2bzacebe6j2ius6clbbr7dypsg54jzmn5xablzunph7ebedw6yhwla4cj2"), - "verifiedregistry": MustParseCid("bafk2bzacebu4joy25gneu2qv3qfm3ktakzalndjrbhekeqrqk3zhotv6nyy2g"), + "account": MustParseCid("bafk2bzaceajsdln7v4chxqoukiw7lxw6aexg5qdsaex2hgelz2sbu24iblhzg"), + "cron": MustParseCid("bafk2bzacecgrwmgnqhybn3l23uvwf2n2vrcfjrprfzgd44uxers2pgr5mhsue"), + "datacap": MustParseCid("bafk2bzacebyier2ceh27acbrq2ccv4efvzotl6qntnlrxdsrik6i4tembz6qw"), + "init": MustParseCid("bafk2bzaceberhto43wnf4pklkd4c7d36kzslngyzyms4op7shxuswv3dtvfxu"), + "multisig": MustParseCid("bafk2bzaceaclpbrhoqdruvsuqqgknvy2k5dywzmjoehk4uarce3uvt3w2rewu"), + "paymentchannel": MustParseCid("bafk2bzacedzp56g5cg73oilloak3kf7u667rdkd5pgnhe2cljmr3o7ykcrzuk"), + "reward": MustParseCid("bafk2bzacebczbwfbbi6mvppbjcozatasjiaohvjjiqcy65ccuuyyw3xiixhk2"), + "storagemarket": MustParseCid("bafk2bzaceawqexy6t2ybzh3jjwhbs7icbg5vqnedbbge4e4r4pfp7spkcadsu"), + "storageminer": MustParseCid("bafk2bzacearemd7pn2jj26fdtqd4di27lfhpng3vp5chepm7qnmdzgiqr6wfi"), + "storagepower": MustParseCid("bafk2bzaceddc7fiaxfobfegqaobf5xinjgmhsa5iu4yi6klvc3jmjimcdvgyg"), + "system": MustParseCid("bafk2bzacedylltr57b2n6zpadh4i2c2kis4fzzvhao3kgvfaggrrbqyacew7q"), + "verifiedregistry": MustParseCid("bafk2bzacecjkesz766626ab4svnzpq3jfs26a75vfktlfaku5fjdao2eyiqyq"), }, }, { Network: "butterflynet", Version: 10, - ManifestCid: MustParseCid("bafy2bzaced2wq4k4i2deknam6ehbynaoo37bhysud7eze7su3ftlaggwwjuje"), + ManifestCid: MustParseCid("bafy2bzacecicijumaz6c5vpqwidz3kmfkn64wp76odwfo6ekvzjbx4gizrara"), Actors: map[string]cid.Cid{ - "account": MustParseCid("bafk2bzacebd5zetyjtragjwrv2nqktct6u2pmsi4eifbanovxohx3a7lszjxi"), - "cron": MustParseCid("bafk2bzacecrszortqkc7har77ssgajglymv6ftrqvmdko5h2yqqh5k2qospl2"), - "datacap": MustParseCid("bafk2bzacecapjnxnyw4talwqv5ajbtbkzmzqiosztj5cb3sortyp73ndjl76e"), - "eam": MustParseCid("bafk2bzacebsvtqzp7g7vpufbyqrwwcpuo2yu3y7kenm7auidyiwzcv6jdw724"), - "ethaccount": MustParseCid("bafk2bzacedl4pmkfxkzoqajs6im3ranmopozsmxjcxsnk3kwvd3vv7mfwwrf4"), - "evm": MustParseCid("bafk2bzacedx5wdyaihi22pwqqqtfxmuwh5acem46mzaep3znmhh5bsuqmxogq"), - "init": MustParseCid("bafk2bzacecbxp66q3ytjkg37nyv4rmzezbfaigvx4i5yhvqbm5gg4amjeaias"), - "multisig": MustParseCid("bafk2bzacecjltag3mn75dsnmrmopjow27buxqhabissowayqlmavrcfetqswc"), - "paymentchannel": MustParseCid("bafk2bzacednzxg263eqbl2imwz3uhujov63tjkffieyl4hl3dhrgxyhwep6hc"), - "placeholder": MustParseCid("bafk2bzaceaamp2a35vpfml4skap4dffklzae2urcm34mtwwce2lvhaons3a5y"), - "reward": MustParseCid("bafk2bzacectp23cxsbbdrr3uggnw7f263qll5wkkfzqhn5yq37ae2ehdjdzri"), - "storagemarket": MustParseCid("bafk2bzacea45ko3ezkpeujsniovncwnizc4wsxd7kyckskhs7gvzwthzb2mqe"), - "storageminer": MustParseCid("bafk2bzaced74qthwrl3gahcf7o3vrdrodbcqhlplh6fykbgy5sd2iyouhq44c"), - "storagepower": MustParseCid("bafk2bzaceduksv6wqthr5fgp7mx5prv6gzul2oozf3svrjbuggc4bgokdxgfy"), - "system": MustParseCid("bafk2bzacebe6j2ius6clbbr7dypsg54jzmn5xablzunph7ebedw6yhwla4cj2"), - "verifiedregistry": MustParseCid("bafk2bzacebu4joy25gneu2qv3qfm3ktakzalndjrbhekeqrqk3zhotv6nyy2g"), + "account": MustParseCid("bafk2bzacedknkusm7lnhjpfe7djkxu6kwlqclsq7yk3s7h2wqtet2teul7hla"), + "cron": MustParseCid("bafk2bzacecvf4au52ks3btpfedsffhzkjvtogawsmpypjo4ddolszmszj62om"), + "datacap": MustParseCid("bafk2bzacecrgz4pzuonchcpbugavlmdrsakmz2qsjlpbt22yxum5r33tqkrls"), + "eam": MustParseCid("bafk2bzacecb4i45ifsj3kyeoglherbtc4dc37qrfa7meq37qtpio5gr6jcely"), + "ethaccount": MustParseCid("bafk2bzacec4l6ya2bate7r3yv7sutfhp4fmtcoxun36d4ltfdslczdgms2sx2"), + "evm": MustParseCid("bafk2bzacecicn2uu4wkdy23tifrevyferwfirqm2sipmmj3ctxfp3xrqntcvs"), + "init": MustParseCid("bafk2bzaceagvocld6zunqwrky2czyaao2azwbpwq7jcjv3fab5lmgbhxst5mi"), + "multisig": MustParseCid("bafk2bzaceaj27lzwb4le2rnpnughce45msvv2ezjmqiqpeazpgbzqq75jdudq"), + "paymentchannel": MustParseCid("bafk2bzaceaazgcdtp4jwezulxpuzjz76st3lumudwdvwbb5t6xzpssku5i6ha"), + "placeholder": MustParseCid("bafk2bzacedfvut2myeleyq67fljcrw4kkmn5pb5dpyozovj7jpoez5irnc3ro"), + "reward": MustParseCid("bafk2bzacebvqwn475gljvwlklfnmebunhsc6lj2vyr6s5qr4jehzx5de2wils"), + "storagemarket": MustParseCid("bafk2bzaceberatlfjmzke7gd3hlisvhvkduu4fbsbqymt3nyybszd34vbul32"), + "storageminer": MustParseCid("bafk2bzacedjhhhx32aec25jewhk7qhxjhsjzapi3nc2mrqbdls43hj77r3zc2"), + "storagepower": MustParseCid("bafk2bzacedhl3j7b5dzbtu772y3shmdijsiqqv36j5u2jmvb53job6curj7sk"), + "system": MustParseCid("bafk2bzaceakoq47k4ro3x4f7wd46yk6n33g2vuiiwbps5o2e5qhkhraxgvf5c"), + "verifiedregistry": MustParseCid("bafk2bzaced2fw523rkzw5rsca7a3v7isjgqyifpwxbs5dzdz5nipwes6cjdjk"), }, }, { Network: "calibrationnet", @@ -110,24 +106,24 @@ var EmbeddedBuiltinActorsMetadata []*BuiltinActorsMetadata = []*BuiltinActorsMet }, { Network: "calibrationnet", Version: 10, - ManifestCid: MustParseCid("bafy2bzacearpwvmcqlailxyq2d2wtzmtudxqhvfot77tbdqotek5qiq5hyhzg"), + ManifestCid: MustParseCid("bafy2bzaceafl4uxyttmhccmv3246hzxu6yknal4f7ugsbpcu46kvkf6mvfvri"), Actors: map[string]cid.Cid{ - "account": MustParseCid("bafk2bzacea7zmrdz2rjbzlbmrmx3ko6pm3cbyqxxgogiqldsccbqffuok7m6s"), - "cron": MustParseCid("bafk2bzacec7bxugi7ouh75nglycy7qwdq7e2hnku3w6yafq4fwdwvvq2mtrl2"), - "datacap": MustParseCid("bafk2bzacedii4stmlo3ccdff7eevcolmgnuxy5ftkzbzwtkqa4iinlfzq4mei"), - "eam": MustParseCid("bafk2bzacedykxiyewqijj5nksr7qi6o4wu5yz4rezb747ntql4rpidyfdpes4"), - "ethaccount": MustParseCid("bafk2bzacecgbcbh3uk7olcfdqo44no5nxxayeqnycdznrlekqigbifor2revm"), - "evm": MustParseCid("bafk2bzaceau5n66rabegik55kymni6uyk7n7jb5eymfywybs543yifpl7du2m"), - "init": MustParseCid("bafk2bzacea7lxnvgxupwwgoxlmwtrca75w73qabe324wnwx43qranbgf5zdqo"), - "multisig": MustParseCid("bafk2bzacear5eu5gpbjlroqkmsgpqerzc4aemp2uqcaeq7s2h4ur4ucgpzesg"), - "paymentchannel": MustParseCid("bafk2bzacecwxuruxawcru7xfcx3rmt4hmhlfh4hi6jvfumerazz6jpvfmxxcw"), - "placeholder": MustParseCid("bafk2bzaceaamp2a35vpfml4skap4dffklzae2urcm34mtwwce2lvhaons3a5y"), - "reward": MustParseCid("bafk2bzacebk4syfvyk7kbxelk7ajo4vuxcc24k5ry52mvi3qtadlucy2vqlay"), - "storagemarket": MustParseCid("bafk2bzaced2rfzwup3jlwovblx2y7q64w6mshbtn2nmampi4zfd3b4oplkp5c"), - "storageminer": MustParseCid("bafk2bzacecden66gfmmgylmr47myn4murqmbt3ycyxqayn54yzhcsda32rp3m"), - "storagepower": MustParseCid("bafk2bzacebxvco3shuhdnzjmmme3olbffdgpab7j3onfncksi762k3agjhzaa"), - "system": MustParseCid("bafk2bzacednnhpk5kno67bkomiohweglryqvgnqz4cbks6eomidai677fat5w"), - "verifiedregistry": MustParseCid("bafk2bzaceawecz24xbz7robn7ck7k2mprkewvup6q346whbfiybcrvy63qcsa"), + "account": MustParseCid("bafk2bzaced5aa6fukm56jrjbhh5sewj2kv5mejrkjhsbx26b4xmg7x42cbkus"), + "cron": MustParseCid("bafk2bzaceautoih7urvvrubgktnmq4oqlsfqyk5mwatkj5dn42d7v7wn4hbi2"), + "datacap": MustParseCid("bafk2bzacectwanemh5tn7ojovprhag6ikvdfs4evzu2tdyg4tx6nr4qdnsyra"), + "eam": MustParseCid("bafk2bzacecxllkzu2hjcqs2br7xq7iplp4ol7ae6k4pxlwy4lzrj2b6dwaucq"), + "ethaccount": MustParseCid("bafk2bzacechpkotxlk342wp5xkpzgcz46me5nm7gdr2krfbf7zkmrgom6j4oq"), + "evm": MustParseCid("bafk2bzacedsaquz6rsixcl4bs4tdemfsxdy6rvv5klwodaetjn7iozwpkqxqa"), + "init": MustParseCid("bafk2bzaceadfoajypcb3ocklgbu6qzad2tpvrz6yrdu7kofd6wq2vssvpqnda"), + "multisig": MustParseCid("bafk2bzacecy7yahpaunojdmaxd2lposejij3sg7orn6du7zqfyuecya3uoije"), + "paymentchannel": MustParseCid("bafk2bzacebxgoj2ql5eft4sbccnj6l3ubm5qagvjmegh2atk5wrjw4xsoqy6e"), + "placeholder": MustParseCid("bafk2bzacedfvut2myeleyq67fljcrw4kkmn5pb5dpyozovj7jpoez5irnc3ro"), + "reward": MustParseCid("bafk2bzaceac5aeqc7honlhs7do6n37ps56ljgx3gnoalmkz4rfy2as6nmonfu"), + "storagemarket": MustParseCid("bafk2bzacedsorzdsgjblcm7iexzxxcx5u3pqyxefn544klyv4gk357kp5fvb4"), + "storageminer": MustParseCid("bafk2bzacedvaorqhrkr3mootp4ltgzebphpqqyyj5wcyylq5dnlupxeyydagm"), + "storagepower": MustParseCid("bafk2bzacecz2u6772repwsr6x6tbbm2z4bdy4uxxlvwm6r6ggfgox6sp2buiu"), + "system": MustParseCid("bafk2bzaceafo3uoxhi6nebe3nygkmiq532cvt2iq4ikcxnioi5fqnrthnpi2q"), + "verifiedregistry": MustParseCid("bafk2bzacecw3t525evmi4g27wgqr6bowz7jgkzflr6haosej5aa3mide63edk"), }, }, { Network: "caterpillarnet", @@ -176,24 +172,24 @@ var EmbeddedBuiltinActorsMetadata []*BuiltinActorsMetadata = []*BuiltinActorsMet }, { Network: "caterpillarnet", Version: 10, - ManifestCid: MustParseCid("bafy2bzacebxr4uvnf5g3373shjzbaca6pf4th6nnfubytjfbrlxcpvbjw4ane"), + ManifestCid: MustParseCid("bafy2bzaceajatwdn4jlfiweb2cuwqtnrdwdxlju2vvejlqsytocnc76xnwm2g"), Actors: map[string]cid.Cid{ - "account": MustParseCid("bafk2bzacedfms6w3ghqtljpgsfuiqa6ztjx7kcuin6myjezj6rypj3zjbqms6"), - "cron": MustParseCid("bafk2bzaceaganmlpozvy4jywigs46pfrtdmhjjey6uyhpurplqbasojsislba"), - "datacap": MustParseCid("bafk2bzacebafqqe3wv5ytkfwmqzbmchgem66pw6yq6rl7w6vlhqsbkxnisswq"), - "eam": MustParseCid("bafk2bzacedwk5eqczflcsuisqsyeomgkpg54olojjq2ieb2ozu5s45wfwluti"), - "ethaccount": MustParseCid("bafk2bzaceburkmtd63nmzxpux5rcxsbqr6x5didl2ce7al32g4tqrvo4pjz2i"), - "evm": MustParseCid("bafk2bzacedbroioygjnbjtc7ykcjjs4wfbwnaa6gkzubi7c5enifoqqqu66s6"), - "init": MustParseCid("bafk2bzaced23r54kwuebl7t6mdantbby5qpfduxwxfryeliof2enyqzhokix6"), - "multisig": MustParseCid("bafk2bzacebcn3rib6j6jvclys7dkf62hco45ssgamczkrtzt6xyewd6gt3mtu"), - "paymentchannel": MustParseCid("bafk2bzacecvas4leo44pqdguj22nnwqoqdgwajzrpm5d6ltkehc37ni6p6doq"), - "placeholder": MustParseCid("bafk2bzaceaamp2a35vpfml4skap4dffklzae2urcm34mtwwce2lvhaons3a5y"), - "reward": MustParseCid("bafk2bzacebiizh4ohvv6p4uxjusoygex4wxcgvudqmdl2fsh6ft6s2zt4tz6q"), - "storagemarket": MustParseCid("bafk2bzacedhkidshm7w2sqlw7izvaieyhkvmyhfsem6t6qfnkh7dnwqe56po2"), - "storageminer": MustParseCid("bafk2bzacedcmsibwfwhkp3sabmbyjmhqibyhjf3wwst7u5bkb2k6xpun3xevg"), - "storagepower": MustParseCid("bafk2bzacecrgnpypxnxzgglhlitaallfee3dl4ejy3y63knl7llnwba4ycf7i"), - "system": MustParseCid("bafk2bzacecl7gizbe52xj6sfm5glubkhrdblmzuwlid6lxrwr5zhcmv4dl2ew"), - "verifiedregistry": MustParseCid("bafk2bzacebzndvdqtdck2y35smcxezldgh6nm6rbkj3g3fmiknsgg2uah235y"), + "account": MustParseCid("bafk2bzacedqtev5u55huwir5pustw5ixxjzemaq67idea73mhfxb655vn6fba"), + "cron": MustParseCid("bafk2bzacec5f4javbqxjkt5lewqxs5j2it4xbwxqpcm4u5bdo6hhaibpiwad4"), + "datacap": MustParseCid("bafk2bzacec4mswfkqkvuoebimktkb3hnpl4dzclkdqyi5h7skzpl3dm73hwak"), + "eam": MustParseCid("bafk2bzacebqion6rzshb3vou32ohpat4gd2lkrihwswsthtkh3wt3ucvno3z4"), + "ethaccount": MustParseCid("bafk2bzacebnmviobduaxspr5xmmszmibs6fikdjzyxpszweooxxjxez47tr7e"), + "evm": MustParseCid("bafk2bzacebxwy5ktfrhtikwnoklcuvp4znxyh7kf2c6emdedqjtlqqnupfuqc"), + "init": MustParseCid("bafk2bzaceb37ao4tett62uxjklsaewcvauysu5he6flpk74fpfyhs4j4nlmhw"), + "multisig": MustParseCid("bafk2bzacebx6sasdjd5frk75cwcfng752f7hfdllvb5isc37zjzlsgnh2e5lq"), + "paymentchannel": MustParseCid("bafk2bzacediht5lgorndb77tr4ll2qpzziokzyuztunttod73gq6vc4fn7vrc"), + "placeholder": MustParseCid("bafk2bzacedfvut2myeleyq67fljcrw4kkmn5pb5dpyozovj7jpoez5irnc3ro"), + "reward": MustParseCid("bafk2bzacebagt36uxbahizev4pelp4v57duuerqu43ejgi7i2vvofyfpkicre"), + "storagemarket": MustParseCid("bafk2bzaced5fv3zrg4iedwj2vrfzobwyyuecyb6p463pbvz7deqmpftyqpbuc"), + "storageminer": MustParseCid("bafk2bzacebs7w7oy4ef3v6em7w3pqb2ywd44eqkyqm53hqtwhatniblmoiio6"), + "storagepower": MustParseCid("bafk2bzacecbp4h5o3562myp4j7gzznc2txpdijams55kk3ctjat3hfwd64mwy"), + "system": MustParseCid("bafk2bzacea447pmvgz63rvfv3ktxf5pmi5ujq2xf4ognmoe3o7wvn6sq3cs3o"), + "verifiedregistry": MustParseCid("bafk2bzacednk3yfr7kgqfcy3mlowaoaocdcdfc6pv76akiagkircgyesiw7zs"), }, }, { Network: "devnet", @@ -233,24 +229,24 @@ var EmbeddedBuiltinActorsMetadata []*BuiltinActorsMetadata = []*BuiltinActorsMet }, { Network: "devnet", Version: 10, - ManifestCid: MustParseCid("bafy2bzacebixrjysarwxdadewlllfp4rwfoejxstwdutghghei54uvuuxlsbq"), + ManifestCid: MustParseCid("bafy2bzacedwfwgngpn52a7zzqfun37dl6brh4ue6d7y3kcs5gsz5hzbppo7ic"), Actors: map[string]cid.Cid{ - "account": MustParseCid("bafk2bzacebb5txxkfexeaxa2th3rckxsxchzyss3ijgqbicf265h7rre2rvhm"), - "cron": MustParseCid("bafk2bzacecotn4gwluhamoqwnzgbg7ogehv26o5xnhjzltnzfv6utrlyanzek"), - "datacap": MustParseCid("bafk2bzacea4hket2srrtbewkf3tip6ellwpxdfbrzt5u47y57i2k6iojqqgba"), - "eam": MustParseCid("bafk2bzacecxm2gr6tevzzan6oqp6aiqydjm5b7eo34mlzo5jdm7mnlbbueikq"), - "ethaccount": MustParseCid("bafk2bzacedh4y3zvtgft3i6ift4rpptgr2dx67pvenowvq7yaspuf25gqgcdc"), - "evm": MustParseCid("bafk2bzacec26myls7vg6anr5yjbb2r75dryhdzwlwnrhjcyuhahlaoxdrua6i"), - "init": MustParseCid("bafk2bzacedof2ckc6w2qboxzxv4w67njcug4ut4cq3nnlrfybzsvlgnp4kt24"), - "multisig": MustParseCid("bafk2bzacec4eqajjqhl53tnkbs7glu7njlbtlditi7lxhvw33ezmxk6jae46y"), - "paymentchannel": MustParseCid("bafk2bzacec6nvdprqja7dy3qp5islebbbh2ifiyg2p7arbe6pocjhfe6xwkfy"), - "placeholder": MustParseCid("bafk2bzaceaamp2a35vpfml4skap4dffklzae2urcm34mtwwce2lvhaons3a5y"), - "reward": MustParseCid("bafk2bzacecqaoqksjotl4wwsqt2wf6kqv6s372afi3r5on4bqj3u3a44px2rm"), - "storagemarket": MustParseCid("bafk2bzaceb7yefqlzyoxkgoug5k4kizy63izrg5udartw5l4d6j53xjwdxbg4"), - "storageminer": MustParseCid("bafk2bzaceagmuxcgdj65yuvtfrcup5viwkhhhlzslpdd4j6v6qxmhxtcssc6u"), - "storagepower": MustParseCid("bafk2bzacedt2qu6ykj3bjsfhchg2gxvc6asfb7c4tmranl76n4ojut5d6sgqm"), - "system": MustParseCid("bafk2bzacebp4ysxqv4cy633pgdxjlbwkwqkokc2fgez77y73abpt5hkthczn6"), - "verifiedregistry": MustParseCid("bafk2bzaceb7odugx7meltvt2gra4vogn2g6avbgysivvdccldylusjcfsnfhy"), + "account": MustParseCid("bafk2bzacebyyteba37hzusnw6nek4cc2t3tripnpmaqcjyan4jlrosxml4us2"), + "cron": MustParseCid("bafk2bzaceddvv6uvff77qqwar76dhhzgdthsgrt66wy47a4axq2isfsu3isqa"), + "datacap": MustParseCid("bafk2bzaceapgpfwhtarq323r7ccvb2jc4yedgtdjnn5w3jgr75ayh3ctqdilk"), + "eam": MustParseCid("bafk2bzacealsu5v4552tqzwefu6htk43oixucyviwpam2can57tthwzea2erm"), + "ethaccount": MustParseCid("bafk2bzaceasdkzg5t6joexhuqiigagueb4fwkyczod5h4ipabkl5he5p6pss2"), + "evm": MustParseCid("bafk2bzacec2rienkocd7d52htiutyy26zszk5zzu47iqev3v2yca5peqgtcoc"), + "init": MustParseCid("bafk2bzacedq4e2x3zbopkxgvsryrc2lakqac6dhelt6vjqvoxqghzwmhhen2o"), + "multisig": MustParseCid("bafk2bzaceaeqphqg7jeudjwiveugre5spemixlwnvvdywdnd4hv5spj2of4is"), + "paymentchannel": MustParseCid("bafk2bzaceaey7zxzfsallib7bdinlnbysivlithvogz2nmyd2qnxcsbwfolgq"), + "placeholder": MustParseCid("bafk2bzacedfvut2myeleyq67fljcrw4kkmn5pb5dpyozovj7jpoez5irnc3ro"), + "reward": MustParseCid("bafk2bzacec7n2iijqcrar6ztbue7sqexvuwwsif6svmzx4qfehppyom4ftyju"), + "storagemarket": MustParseCid("bafk2bzacedmyiyvcbm2zepqib5lrjxzutcc533wbkwfmcwrb5pcjsn7ucsqww"), + "storageminer": MustParseCid("bafk2bzaceai3i4ilksmjc5wmtb2hkrylrn3kfkmcyzp77vn36gc76yqor3h2i"), + "storagepower": MustParseCid("bafk2bzaceccwx5vmarswywl3spmbqfkuw4672ilsv4pyi3ytvz5vrap4ktsyk"), + "system": MustParseCid("bafk2bzacecacjaj6bgwxtywl7leqxusrcwidm6fyfibqanqgli7ueupdbib5c"), + "verifiedregistry": MustParseCid("bafk2bzacedspjal4tdnzfrn6qi4vpsikdhoeqokaizffj6lsru4kap5woyurm"), }, }, { Network: "hyperspace", @@ -274,50 +270,6 @@ var EmbeddedBuiltinActorsMetadata []*BuiltinActorsMetadata = []*BuiltinActorsMet "system": MustParseCid("bafk2bzacedo2hfopt6gy52goj7fot5qwzhtnysmgo7h25crq4clpugkerjabk"), "verifiedregistry": MustParseCid("bafk2bzacea7rfkjrixaidksnmjehglmavyt56nyeu3sfxu2e3dcpf62oab6tw"), }, -}, { - Network: "hyperspace", - Version: 9, - ManifestCid: MustParseCid("bafy2bzacedvffumcvf72f2btjqvece3kpcdorxq5tq76iwcmqbzvsiu526cqm"), - Actors: map[string]cid.Cid{ - "account": MustParseCid("bafk2bzacecim7uybic2qprbkjhowg7qkniv4zywj5h5g4u4ss72urco2akzuo"), - "cron": MustParseCid("bafk2bzaceahgq64awp4f7li3hdgimc4upqvdvltpmeywckvens33umcxt424a"), - "datacap": MustParseCid("bafk2bzacebkxn52ttooaslkwncijk3bgd3tm2zw7vijdhwvg2cxnxbrzmmq5e"), - "eam": MustParseCid("bafk2bzaceczhgub5anrnaf7ol65mu54gsgwcj6c6m3yhet7rhxm2l6kz4s4ru"), - "ethaccount": MustParseCid("bafk2bzacealn5enbxyxbfs7gbsjbyma2zk3bcr7okvflxhpr753d4eh6ixooa"), - "evm": MustParseCid("bafk2bzacedljkrmazyewawpnddrkzrt55556374dw2pm2hokgkompgzw4vx5y"), - "init": MustParseCid("bafk2bzacec55gyyaqjrw7zughywocgwcjvv6k5fijjpjw4xgckuqz6pjtff5a"), - "multisig": MustParseCid("bafk2bzaceblozbdzybdivvjdiid4jwm2jc6x5a66sunh2vvwsqba6wzqmr7i6"), - "paymentchannel": MustParseCid("bafk2bzacealcyke5a6n24efs6qe4iikynpk2twqssyugy7jcyf6p6shgw2iwa"), - "placeholder": MustParseCid("bafk2bzaceaamp2a35vpfml4skap4dffklzae2urcm34mtwwce2lvhaons3a5y"), - "reward": MustParseCid("bafk2bzacebafzaqhwsm3nmsfwcd6ngvx6ev6zlcpyfljqh4kb77vok6opban6"), - "storagemarket": MustParseCid("bafk2bzacecrjfg4p7fxznsdkoobs4po2ve3ywixrirrk6netgxh63qqaefamg"), - "storageminer": MustParseCid("bafk2bzaceb3ctd4atxwhdkmlg4i63zxo5aopknlj7l5kaiqr22xpcmico6vg4"), - "storagepower": MustParseCid("bafk2bzacecvcix3ugopvby2vah5wwiu5cqjedwzwkanmr34kdoc4f3o6p7nsq"), - "system": MustParseCid("bafk2bzacedo2hfopt6gy52goj7fot5qwzhtnysmgo7h25crq4clpugkerjabk"), - "verifiedregistry": MustParseCid("bafk2bzacea7rfkjrixaidksnmjehglmavyt56nyeu3sfxu2e3dcpf62oab6tw"), - }, -}, { - Network: "hyperspace", - Version: 10, - ManifestCid: MustParseCid("bafy2bzaced6hc7ujjmypg6mkrxdmf32oh2udhmhpmwkqyxusdkxoi2uoodyxg"), - Actors: map[string]cid.Cid{ - "account": MustParseCid("bafk2bzacecim7uybic2qprbkjhowg7qkniv4zywj5h5g4u4ss72urco2akzuo"), - "cron": MustParseCid("bafk2bzaceahgq64awp4f7li3hdgimc4upqvdvltpmeywckvens33umcxt424a"), - "datacap": MustParseCid("bafk2bzacebkxn52ttooaslkwncijk3bgd3tm2zw7vijdhwvg2cxnxbrzmmq5e"), - "eam": MustParseCid("bafk2bzaceaftiqwpx6dcjfqxyq7pazn2p55diukf32pz74755vj7pgg5joexw"), - "ethaccount": MustParseCid("bafk2bzacealn5enbxyxbfs7gbsjbyma2zk3bcr7okvflxhpr753d4eh6ixooa"), - "evm": MustParseCid("bafk2bzacea6etsvrqejjl7uej5dxlswja5gxzqyggsjjvg27timvtiedf7nsg"), - "init": MustParseCid("bafk2bzacec55gyyaqjrw7zughywocgwcjvv6k5fijjpjw4xgckuqz6pjtff5a"), - "multisig": MustParseCid("bafk2bzaceblozbdzybdivvjdiid4jwm2jc6x5a66sunh2vvwsqba6wzqmr7i6"), - "paymentchannel": MustParseCid("bafk2bzacealcyke5a6n24efs6qe4iikynpk2twqssyugy7jcyf6p6shgw2iwa"), - "placeholder": MustParseCid("bafk2bzaceaamp2a35vpfml4skap4dffklzae2urcm34mtwwce2lvhaons3a5y"), - "reward": MustParseCid("bafk2bzacebafzaqhwsm3nmsfwcd6ngvx6ev6zlcpyfljqh4kb77vok6opban6"), - "storagemarket": MustParseCid("bafk2bzacecrjfg4p7fxznsdkoobs4po2ve3ywixrirrk6netgxh63qqaefamg"), - "storageminer": MustParseCid("bafk2bzaceb3ctd4atxwhdkmlg4i63zxo5aopknlj7l5kaiqr22xpcmico6vg4"), - "storagepower": MustParseCid("bafk2bzacecvcix3ugopvby2vah5wwiu5cqjedwzwkanmr34kdoc4f3o6p7nsq"), - "system": MustParseCid("bafk2bzacedo2hfopt6gy52goj7fot5qwzhtnysmgo7h25crq4clpugkerjabk"), - "verifiedregistry": MustParseCid("bafk2bzacea7rfkjrixaidksnmjehglmavyt56nyeu3sfxu2e3dcpf62oab6tw"), - }, }, { Network: "mainnet", Version: 8, @@ -356,24 +308,24 @@ var EmbeddedBuiltinActorsMetadata []*BuiltinActorsMetadata = []*BuiltinActorsMet }, { Network: "mainnet", Version: 10, - ManifestCid: MustParseCid("bafy2bzacea5vylkbby7rb42fknkk4g4byhj7hkqlxp4z4urydi3vlpwsgllik"), + ManifestCid: MustParseCid("bafy2bzaceanax3ruj24in364mbozrpmcyn7jf2vrxshppsgufwxemvzf6fp26"), Actors: map[string]cid.Cid{ - "account": MustParseCid("bafk2bzacedsn6i2flkpk6sb4iuejo7gfl5n6fhsdawggtbsihlrrjtvs7oepu"), - "cron": MustParseCid("bafk2bzacecw4guere7ba2canyi2622lw52b5qbn7iubckcp5cwlmx2kw7qqwy"), - "datacap": MustParseCid("bafk2bzaceat2ncckd2jjjqcovd3ib4sylwff7jk7rlk6gr5d2gmrrc7isrmu2"), - "eam": MustParseCid("bafk2bzacebbpu5smjrjqpkrvvlhcpk23yvlovlndqmwzhfz5kuuph54tdw732"), - "ethaccount": MustParseCid("bafk2bzacedmwzkbytxfn7exmxxosomvix4mpyxrmupeqw45aofqmdq5q7mgqe"), - "evm": MustParseCid("bafk2bzacechkf43lmddynxmc35hvz5kwr3fdxrbg6fxbcvysfsihgiopbrb7o"), - "init": MustParseCid("bafk2bzacec6276d7ls3hhuqibqorn3yp45mv7hroczf3bgb6jkhmbb2zqt3bw"), - "multisig": MustParseCid("bafk2bzaceahggxrnjj3w3cgtko54srssqyhcs4x6y55ytego6jf2owg5piw3y"), - "paymentchannel": MustParseCid("bafk2bzaceaobaqjamso57bkjv3n4ilv7lfropgrncnnej666w3tegmr4cfgve"), - "placeholder": MustParseCid("bafk2bzaceaamp2a35vpfml4skap4dffklzae2urcm34mtwwce2lvhaons3a5y"), - "reward": MustParseCid("bafk2bzacecqet4s7abe4owznq2wtdefe2z2w5isbde2gj7u3hwgf54di4r7hy"), - "storagemarket": MustParseCid("bafk2bzacebgk2q2ktrqauzop6ha4pcq5gpf6g24hprxnp6wdmlzf724e5sx7i"), - "storageminer": MustParseCid("bafk2bzacecqrm4tlmzci7vilmcchr4lq2e6yyrlhy6ofbuecjna2phmbq4h2a"), - "storagepower": MustParseCid("bafk2bzaceco674a5e5lpv5leui65bljxzgyc2ypdquaow55iuckmq5rvsghr6"), - "system": MustParseCid("bafk2bzacedlt3zcsbw2vucbydptbcfudw5y5pkhhxe26m7pjod6rkxkuzn52w"), - "verifiedregistry": MustParseCid("bafk2bzacea2eehyf7h3m6ydh46piu2gtr4fawpqzh3brtmybgi2tyxf5nwj6m"), + "account": MustParseCid("bafk2bzacedw7633eh64r7azo5eihahnnshqs6ahfbovqfxijscpirfksw6gfe"), + "cron": MustParseCid("bafk2bzacebka3yrzfzotza5q22weufktf5azw2ew7ui5eeigxqbkzzp4ndkf2"), + "datacap": MustParseCid("bafk2bzaceawihbc7ovxq5ifj2op67u26lakybo63kgl57vyipn5rkfi4rppfq"), + "eam": MustParseCid("bafk2bzacedtzbyjyqvtvbx245uuvf4rndnbyxttavwnfo4l72oxpjiiyldh6a"), + "ethaccount": MustParseCid("bafk2bzaceapcifcyvqnbuqq2zgf4kqoypl2xj4mfqefzfp6upevmqygxayfb4"), + "evm": MustParseCid("bafk2bzaced36v7kakhej6m6jailrnojjtkqxf3ybfw4pttasxtzzczxi5fkks"), + "init": MustParseCid("bafk2bzacebqi3szlok75xn7hhtmtmnvoekwdkuhakhr4dpuxmfxvpcrhr2cog"), + "multisig": MustParseCid("bafk2bzacebsc6qdm5772h7aa6bdf3ujerpihc6cdb2zpqz4sldktk423asq2c"), + "paymentchannel": MustParseCid("bafk2bzacebxuh4n66s6vclyp73k4ee2fdxrnjouozqcf3huprobjdk6sf73g6"), + "placeholder": MustParseCid("bafk2bzacedfvut2myeleyq67fljcrw4kkmn5pb5dpyozovj7jpoez5irnc3ro"), + "reward": MustParseCid("bafk2bzacebwlo5udozvs7v4wbtwjtg7jdyw5g6kjws4uqfpwsqhvn6d5u6rr6"), + "storagemarket": MustParseCid("bafk2bzacebbzaj2m3hhtnpk3fz67vudb7yfyquscczksny5z2iiztp6qsbemu"), + "storageminer": MustParseCid("bafk2bzacebdb6kxpqnmiyvpgugoqtnshl362titnku6h6nmil7crodv7vjk6i"), + "storagepower": MustParseCid("bafk2bzacebqavpt7iqtcn5rlsi5cpk5l3ocrxcqcakk25hxf2zbffrzifec3w"), + "system": MustParseCid("bafk2bzacec3m3b6kktp43nrf5ow33yaehokvz2zzpa5qsrstoqwh3liv4eyba"), + "verifiedregistry": MustParseCid("bafk2bzacedufe6cnihk5anxwboprfsmbuy7nxo3peqfrdesxhgptoircbt7ca"), }, }, { Network: "testing", @@ -413,24 +365,24 @@ var EmbeddedBuiltinActorsMetadata []*BuiltinActorsMetadata = []*BuiltinActorsMet }, { Network: "testing", Version: 10, - ManifestCid: MustParseCid("bafy2bzacea7tbn4p232ecrjvlp2uvpci5pexqjqq2vpv4t5ihktpja2zsj3ek"), + ManifestCid: MustParseCid("bafy2bzacecdqjm4vzjqna4kvhe6ngpyimlp3qp73gjlbr3ymjaz7udkqm5k64"), Actors: map[string]cid.Cid{ - "account": MustParseCid("bafk2bzaceds3iy5qjgr3stoywxt4uxvhybca23q7d2kxhitedgudrkhxaxa6o"), - "cron": MustParseCid("bafk2bzacebxp4whb4ocqxnbvqlz3kckarabtyvhjbhqvrdwhejuffwactyiss"), - "datacap": MustParseCid("bafk2bzacedepm3zas6vqryruwiz7d3axkneo7v66q65gf2dlpfd53pjlycrg4"), - "eam": MustParseCid("bafk2bzacea2uascrtv6xnsqlxyf3tcf4onpgrs7frh55p6dnrdeum2uup7wx4"), - "ethaccount": MustParseCid("bafk2bzacecbhz4ipg773lsovgpjysm6fxl2i7y2wuxadqnt4s4vm3nd2qodb4"), - "evm": MustParseCid("bafk2bzaceabwn4i62od3i4qkuj5zx4vn5w5cbcl53tqnszk6kl43bfl55hl6c"), - "init": MustParseCid("bafk2bzacebqym5i5eciyyyzsimu73z6bkffpm5hzjpx3gwcm64pm2fh7okrja"), - "multisig": MustParseCid("bafk2bzacecmlyngek7qvj5ezaaitadrycapup3mbty4ijlzun6g23tcoysxle"), - "paymentchannel": MustParseCid("bafk2bzacedspin4hxpgnxkjen3hsxpcc52oc5q4ypukl4qq6vaytcgmmi7hl4"), - "placeholder": MustParseCid("bafk2bzaceaamp2a35vpfml4skap4dffklzae2urcm34mtwwce2lvhaons3a5y"), - "reward": MustParseCid("bafk2bzacecmumnnqkqnoa23hhsfgwccwvmksr2q65tznbves6x2a6fhwvtm7a"), - "storagemarket": MustParseCid("bafk2bzacea2re4nxba7mtlrwdxabu2i3l2fwbuw2veb4p7qbvrsaocgablqvi"), - "storageminer": MustParseCid("bafk2bzacecixm7d7d5ltsp6mubzw5s3fv335cjuwwy7oqovujn3xlyk6twivs"), - "storagepower": MustParseCid("bafk2bzaced5lqpftacjsflcgfwlm32gzckpi3ndj3kd3prtqqi2lfj3uhl2je"), - "system": MustParseCid("bafk2bzaceaafqf7lwaiqx5po6b3l4dfg4xsr5qhfk3bjgoi7qke2mfy3shla4"), - "verifiedregistry": MustParseCid("bafk2bzacec2ouguts4z335vetmdeifpk5fkqthcmrwshk7yxbw2uohddfu5lo"), + "account": MustParseCid("bafk2bzacecfg6coqk3sn7m7g5b5akafe25qd2po4jhp5kmup4htw5iavtrca6"), + "cron": MustParseCid("bafk2bzaceblrexwzuiiqm5u77zx4xapruki3u2wzq3ca5kf72dkkv7xl3zr2a"), + "datacap": MustParseCid("bafk2bzacedbarmlig6u2tioxjqlvmlroz7pdxtqqjugtzdwg33gcsuv4zus7e"), + "eam": MustParseCid("bafk2bzacecnupv35lhealursu4osdtxjerbfqkdbugprnuctkwykmn4mlsob6"), + "ethaccount": MustParseCid("bafk2bzaceduxlxe2sasshmuvw2vzxzkkdg2e2iud6h5omcct2lszyh4xhayr2"), + "evm": MustParseCid("bafk2bzacebwhijcnwtjbyvs4czuxv6ldg3kjpv364ja3omofaacly67k4ri5k"), + "init": MustParseCid("bafk2bzaceckdouclxeccuduf42hx5draalc6iospmndsrey4mjywfv7owbdfa"), + "multisig": MustParseCid("bafk2bzacectozlgryut7dttrd6jx5uhhf5qda7tglgsoq2ccszcu34mgnpdsy"), + "paymentchannel": MustParseCid("bafk2bzacedpmrg2pseig5ollv4e6ymf7357enxflm3thsxbmz5if6anp6xpzw"), + "placeholder": MustParseCid("bafk2bzacedfvut2myeleyq67fljcrw4kkmn5pb5dpyozovj7jpoez5irnc3ro"), + "reward": MustParseCid("bafk2bzacea6f7fxmfjy6bxo3jojgz7tsrmpag2pvz6yff3d4gs7jt5tr3f7ly"), + "storagemarket": MustParseCid("bafk2bzacedaopo7s23du2xosguopbjhip7zadzaquzeuhlniqgmuplsiamozq"), + "storageminer": MustParseCid("bafk2bzaceam2xfi3g7jjeby6zrauirm3cpbvfun4k2baftogckdgbrfvxsbus"), + "storagepower": MustParseCid("bafk2bzaceaeytro4ruhhhtyeatggxqpoxeqcjzg2qvutthkk4hl3wmz4xc66w"), + "system": MustParseCid("bafk2bzacedteuhprsuwcz5hqoomhy2ozyh5afmmcgughjfbak2mux3da3izvu"), + "verifiedregistry": MustParseCid("bafk2bzacedfmjez4jrix3sgpy3c3iuwemmsl446tfwwzmw7rag3imwomayzes"), }, }, { Network: "testing-fake-proofs", @@ -468,25 +420,26 @@ var EmbeddedBuiltinActorsMetadata []*BuiltinActorsMetadata = []*BuiltinActorsMet "verifiedregistry": MustParseCid("bafk2bzaceatmqip2o3ausbntvdhj7yemu6hb3b5yqv6hm42gylbbmz7geocpm"), }, }, { - Network: "testing-fake-proofs", - Version: 10, - ManifestCid: MustParseCid("bafy2bzacecyqfyzmw72234rvbk6vzq2omnmt3cbfezkq2h3ewnn33w42b2s62"), + Network: "testing-fake-proofs", + Version: 10, + BundleGitTag: "dev/20230114-pre-rc.2", + ManifestCid: MustParseCid("bafy2bzacedc2lel545tjyh66n4mrrpiomx557xeatmo2nzig3b3l22dnaxhbg"), Actors: map[string]cid.Cid{ - "account": MustParseCid("bafk2bzaceds3iy5qjgr3stoywxt4uxvhybca23q7d2kxhitedgudrkhxaxa6o"), - "cron": MustParseCid("bafk2bzacebxp4whb4ocqxnbvqlz3kckarabtyvhjbhqvrdwhejuffwactyiss"), - "datacap": MustParseCid("bafk2bzacedepm3zas6vqryruwiz7d3axkneo7v66q65gf2dlpfd53pjlycrg4"), - "eam": MustParseCid("bafk2bzacea2uascrtv6xnsqlxyf3tcf4onpgrs7frh55p6dnrdeum2uup7wx4"), - "ethaccount": MustParseCid("bafk2bzacecbhz4ipg773lsovgpjysm6fxl2i7y2wuxadqnt4s4vm3nd2qodb4"), - "evm": MustParseCid("bafk2bzaceabwn4i62od3i4qkuj5zx4vn5w5cbcl53tqnszk6kl43bfl55hl6c"), - "init": MustParseCid("bafk2bzacebqym5i5eciyyyzsimu73z6bkffpm5hzjpx3gwcm64pm2fh7okrja"), - "multisig": MustParseCid("bafk2bzacecmlyngek7qvj5ezaaitadrycapup3mbty4ijlzun6g23tcoysxle"), - "paymentchannel": MustParseCid("bafk2bzacedspin4hxpgnxkjen3hsxpcc52oc5q4ypukl4qq6vaytcgmmi7hl4"), - "placeholder": MustParseCid("bafk2bzaceaamp2a35vpfml4skap4dffklzae2urcm34mtwwce2lvhaons3a5y"), - "reward": MustParseCid("bafk2bzacecmumnnqkqnoa23hhsfgwccwvmksr2q65tznbves6x2a6fhwvtm7a"), - "storagemarket": MustParseCid("bafk2bzacea2re4nxba7mtlrwdxabu2i3l2fwbuw2veb4p7qbvrsaocgablqvi"), - "storageminer": MustParseCid("bafk2bzacedz4mmupganqbwe6mz4636zepooh5ipxb36tybsrf6ynewrfdihl6"), - "storagepower": MustParseCid("bafk2bzacedcqv6k2fszpfb7zpw6q6c6fe2u7g2zefabcntp46xgv3owosgymy"), - "system": MustParseCid("bafk2bzaceaafqf7lwaiqx5po6b3l4dfg4xsr5qhfk3bjgoi7qke2mfy3shla4"), - "verifiedregistry": MustParseCid("bafk2bzacec2ouguts4z335vetmdeifpk5fkqthcmrwshk7yxbw2uohddfu5lo"), + "account": MustParseCid("bafk2bzacecfg6coqk3sn7m7g5b5akafe25qd2po4jhp5kmup4htw5iavtrca6"), + "cron": MustParseCid("bafk2bzaceblrexwzuiiqm5u77zx4xapruki3u2wzq3ca5kf72dkkv7xl3zr2a"), + "datacap": MustParseCid("bafk2bzacedbarmlig6u2tioxjqlvmlroz7pdxtqqjugtzdwg33gcsuv4zus7e"), + "eam": MustParseCid("bafk2bzacecnupv35lhealursu4osdtxjerbfqkdbugprnuctkwykmn4mlsob6"), + "ethaccount": MustParseCid("bafk2bzaceduxlxe2sasshmuvw2vzxzkkdg2e2iud6h5omcct2lszyh4xhayr2"), + "evm": MustParseCid("bafk2bzacebwhijcnwtjbyvs4czuxv6ldg3kjpv364ja3omofaacly67k4ri5k"), + "init": MustParseCid("bafk2bzaceckdouclxeccuduf42hx5draalc6iospmndsrey4mjywfv7owbdfa"), + "multisig": MustParseCid("bafk2bzacectozlgryut7dttrd6jx5uhhf5qda7tglgsoq2ccszcu34mgnpdsy"), + "paymentchannel": MustParseCid("bafk2bzacedpmrg2pseig5ollv4e6ymf7357enxflm3thsxbmz5if6anp6xpzw"), + "placeholder": MustParseCid("bafk2bzacedfvut2myeleyq67fljcrw4kkmn5pb5dpyozovj7jpoez5irnc3ro"), + "reward": MustParseCid("bafk2bzacea6f7fxmfjy6bxo3jojgz7tsrmpag2pvz6yff3d4gs7jt5tr3f7ly"), + "storagemarket": MustParseCid("bafk2bzacedaopo7s23du2xosguopbjhip7zadzaquzeuhlniqgmuplsiamozq"), + "storageminer": MustParseCid("bafk2bzacecweqgs7k452vertmz66hjz2ymrgdbn4ycduyho3znoqv56ay4xlw"), + "storagepower": MustParseCid("bafk2bzaceapnz6icrfdgjcr7d2rknak5wirxxbh7mmo7kfutacxys22xrapbe"), + "system": MustParseCid("bafk2bzacedteuhprsuwcz5hqoomhy2ozyh5afmmcgughjfbak2mux3da3izvu"), + "verifiedregistry": MustParseCid("bafk2bzacedfmjez4jrix3sgpy3c3iuwemmsl446tfwwzmw7rag3imwomayzes"), }, }} diff --git a/build/builtin_actors_test.go b/build/builtin_actors_test.go index 858a8b3a1..bb133bdab 100644 --- a/build/builtin_actors_test.go +++ b/build/builtin_actors_test.go @@ -17,7 +17,13 @@ func TestEmbeddedMetadata(t *testing.T) { metadata, err := build.ReadEmbeddedBuiltinActorsMetadata() require.NoError(t, err) - require.Equal(t, metadata, build.EmbeddedBuiltinActorsMetadata) + for i, v1 := range metadata { + v2 := build.EmbeddedBuiltinActorsMetadata[i] + require.Equal(t, v1.Network, v2.Network) + require.Equal(t, v1.Version, v2.Version) + require.Equal(t, v1.ManifestCid, v2.ManifestCid) + require.Equal(t, v1.Actors, v2.Actors) + } } // Test that we're registering the manifest correctly. diff --git a/build/genesis/butterflynet.car b/build/genesis/butterflynet.car index 71a1c684e..cb0c4162b 100644 Binary files a/build/genesis/butterflynet.car and b/build/genesis/butterflynet.car differ diff --git a/build/openrpc/full.json.gz b/build/openrpc/full.json.gz index d7a354461..a33ab9ab3 100644 Binary files a/build/openrpc/full.json.gz and b/build/openrpc/full.json.gz differ diff --git a/build/openrpc/gateway.json.gz b/build/openrpc/gateway.json.gz index 74a9f3221..f8dc51639 100644 Binary files a/build/openrpc/gateway.json.gz and b/build/openrpc/gateway.json.gz differ diff --git a/build/openrpc/miner.json.gz b/build/openrpc/miner.json.gz index d3750150c..be2151d62 100644 Binary files a/build/openrpc/miner.json.gz and b/build/openrpc/miner.json.gz differ diff --git a/build/openrpc/worker.json.gz b/build/openrpc/worker.json.gz index e84f7f5d1..d8130e9e1 100644 Binary files a/build/openrpc/worker.json.gz and b/build/openrpc/worker.json.gz differ diff --git a/build/params_2k.go b/build/params_2k.go index 081007dd1..962b2f9ba 100644 --- a/build/params_2k.go +++ b/build/params_2k.go @@ -23,7 +23,7 @@ var NetworkBundle = "devnet" var BundleOverrides map[actorstypes.Version]string var ActorDebugging = true -const GenesisNetworkVersion = network.Version18 +const GenesisNetworkVersion = network.Version17 var UpgradeBreezeHeight = abi.ChainEpoch(-1) @@ -59,7 +59,7 @@ var UpgradeSkyrHeight = abi.ChainEpoch(-19) var UpgradeSharkHeight = abi.ChainEpoch(-20) -var UpgradeHyggeHeight = abi.ChainEpoch(-21) +var UpgradeHyggeHeight = abi.ChainEpoch(30) var DrandSchedule = map[abi.ChainEpoch]DrandEnum{ 0: DrandMainnet, diff --git a/build/params_butterfly.go b/build/params_butterfly.go index 7cd02bce9..b00381b44 100644 --- a/build/params_butterfly.go +++ b/build/params_butterfly.go @@ -19,7 +19,7 @@ var DrandSchedule = map[abi.ChainEpoch]DrandEnum{ 0: DrandMainnet, } -const GenesisNetworkVersion = network.Version16 +const GenesisNetworkVersion = network.Version17 var NetworkBundle = "butterflynet" var BundleOverrides map[actorstypes.Version]string diff --git a/build/params_hyperspace.go b/build/params_hyperspace.go deleted file mode 100644 index 1e75c6bfa..000000000 --- a/build/params_hyperspace.go +++ /dev/null @@ -1,94 +0,0 @@ -//go:build hyperspacenet -// +build hyperspacenet - -package build - -import ( - "github.com/ipfs/go-cid" - - "github.com/filecoin-project/go-address" - "github.com/filecoin-project/go-state-types/abi" - actorstypes "github.com/filecoin-project/go-state-types/actors" - "github.com/filecoin-project/go-state-types/network" - builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin" - - "github.com/filecoin-project/lotus/chain/actors/policy" -) - -var NetworkBundle = "hyperspace" -var BundleOverrides map[actorstypes.Version]string -var ActorDebugging = false - -const BootstrappersFile = "hyperspacenet.pi" -const GenesisFile = "hyperspacenet.car" - -const GenesisNetworkVersion = network.Version18 - -var UpgradeBreezeHeight = abi.ChainEpoch(-1) - -const BreezeGasTampingDuration = 120 - -var UpgradeSmokeHeight = abi.ChainEpoch(-1) -var UpgradeIgnitionHeight = abi.ChainEpoch(-2) -var UpgradeRefuelHeight = abi.ChainEpoch(-3) -var UpgradeTapeHeight = abi.ChainEpoch(-4) - -var UpgradeAssemblyHeight = abi.ChainEpoch(-5) -var UpgradeLiftoffHeight = abi.ChainEpoch(-6) - -var UpgradeKumquatHeight = abi.ChainEpoch(-7) -var UpgradeCalicoHeight = abi.ChainEpoch(-9) -var UpgradePersianHeight = abi.ChainEpoch(-10) -var UpgradeOrangeHeight = abi.ChainEpoch(-11) -var UpgradeClausHeight = abi.ChainEpoch(-12) - -var UpgradeTrustHeight = abi.ChainEpoch(-13) - -var UpgradeNorwegianHeight = abi.ChainEpoch(-14) - -var UpgradeTurboHeight = abi.ChainEpoch(-15) - -var UpgradeHyperdriveHeight = abi.ChainEpoch(-16) -var UpgradeChocolateHeight = abi.ChainEpoch(-17) -var UpgradeOhSnapHeight = abi.ChainEpoch(-18) -var UpgradeSkyrHeight = abi.ChainEpoch(-19) -var UpgradeSharkHeight = abi.ChainEpoch(-20) -var UpgradeHyggeHeight = abi.ChainEpoch(-21) - -var DrandSchedule = map[abi.ChainEpoch]DrandEnum{ - 0: DrandMainnet, -} - -var SupportedProofTypes = []abi.RegisteredSealProof{ - abi.RegisteredSealProof_StackedDrg512MiBV1, - abi.RegisteredSealProof_StackedDrg32GiBV1, - abi.RegisteredSealProof_StackedDrg64GiBV1, -} -var ConsensusMinerMinPower = abi.NewStoragePower(16 << 30) -var MinVerifiedDealSize = abi.NewStoragePower(1 << 20) -var PreCommitChallengeDelay = abi.ChainEpoch(10) - -func init() { - policy.SetSupportedProofTypes(SupportedProofTypes...) - policy.SetConsensusMinerMinPower(ConsensusMinerMinPower) - policy.SetMinVerifiedDealSize(MinVerifiedDealSize) - policy.SetPreCommitChallengeDelay(PreCommitChallengeDelay) - - BuildType = BuildHyperspacenet - SetAddressNetwork(address.Testnet) - Devnet = true - -} - -const BlockDelaySecs = uint64(builtin2.EpochDurationSeconds) - -const PropagationDelaySecs = uint64(6) - -// BootstrapPeerThreshold is the minimum number peers we need to track for a sync worker to start -const BootstrapPeerThreshold = 2 - -// ChainId defines the chain ID used in the Ethereum JSON-RPC endpoint. -// As per https://github.com/ethereum-lists/chains -const Eip155ChainId = 3141 - -var WhitelistedBlock = cid.Undef diff --git a/build/params_mainnet.go b/build/params_mainnet.go index f95525dbc..e29fa4567 100644 --- a/build/params_mainnet.go +++ b/build/params_mainnet.go @@ -1,5 +1,5 @@ -//go:build !debug && !2k && !testground && !calibnet && !butterflynet && !interopnet && !wallabynet && !hyperspacenet -// +build !debug,!2k,!testground,!calibnet,!butterflynet,!interopnet,!wallabynet,!hyperspacenet +//go:build !debug && !2k && !testground && !calibnet && !butterflynet && !interopnet +// +build !debug,!2k,!testground,!calibnet,!butterflynet,!interopnet package build diff --git a/build/params_testground.go b/build/params_testground.go index ed818f4a5..17ea5a59b 100644 --- a/build/params_testground.go +++ b/build/params_testground.go @@ -42,9 +42,6 @@ var ( AllowableClockDriftSecs = uint64(1) - Finality = policy.ChainFinality - ForkLengthThreshold = Finality - SlashablePowerDelay = 20 InteractivePoRepConfidence = 6 @@ -130,6 +127,9 @@ var ( GenesisFile = "" ) +const Finality = policy.ChainFinality +const ForkLengthThreshold = Finality + const BootstrapPeerThreshold = 1 // ChainId defines the chain ID used in the Ethereum JSON-RPC endpoint. diff --git a/build/params_wallaby.go b/build/params_wallaby.go deleted file mode 100644 index c5279bfd0..000000000 --- a/build/params_wallaby.go +++ /dev/null @@ -1,94 +0,0 @@ -//go:build wallabynet -// +build wallabynet - -package build - -import ( - "github.com/ipfs/go-cid" - - "github.com/filecoin-project/go-address" - "github.com/filecoin-project/go-state-types/abi" - actorstypes "github.com/filecoin-project/go-state-types/actors" - "github.com/filecoin-project/go-state-types/network" - builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin" - - "github.com/filecoin-project/lotus/chain/actors/policy" -) - -var NetworkBundle = "wallaby" -var BundleOverrides map[actorstypes.Version]string -var ActorDebugging = false - -const BootstrappersFile = "wallabynet.pi" -const GenesisFile = "wallabynet.car" - -const GenesisNetworkVersion = network.Version18 - -var UpgradeBreezeHeight = abi.ChainEpoch(-1) - -const BreezeGasTampingDuration = 120 - -var UpgradeSmokeHeight = abi.ChainEpoch(-1) -var UpgradeIgnitionHeight = abi.ChainEpoch(-2) -var UpgradeRefuelHeight = abi.ChainEpoch(-3) -var UpgradeTapeHeight = abi.ChainEpoch(-4) - -var UpgradeAssemblyHeight = abi.ChainEpoch(-5) -var UpgradeLiftoffHeight = abi.ChainEpoch(-6) - -var UpgradeKumquatHeight = abi.ChainEpoch(-7) -var UpgradeCalicoHeight = abi.ChainEpoch(-9) -var UpgradePersianHeight = abi.ChainEpoch(-10) -var UpgradeOrangeHeight = abi.ChainEpoch(-11) -var UpgradeClausHeight = abi.ChainEpoch(-12) - -var UpgradeTrustHeight = abi.ChainEpoch(-13) - -var UpgradeNorwegianHeight = abi.ChainEpoch(-14) - -var UpgradeTurboHeight = abi.ChainEpoch(-15) - -var UpgradeHyperdriveHeight = abi.ChainEpoch(-16) -var UpgradeChocolateHeight = abi.ChainEpoch(-17) -var UpgradeOhSnapHeight = abi.ChainEpoch(-18) -var UpgradeSkyrHeight = abi.ChainEpoch(-19) -var UpgradeSharkHeight = abi.ChainEpoch(-20) -var UpgradeHyggeHeight = abi.ChainEpoch(-21) - -var DrandSchedule = map[abi.ChainEpoch]DrandEnum{ - 0: DrandMainnet, -} - -var SupportedProofTypes = []abi.RegisteredSealProof{ - abi.RegisteredSealProof_StackedDrg512MiBV1, - abi.RegisteredSealProof_StackedDrg32GiBV1, - abi.RegisteredSealProof_StackedDrg64GiBV1, -} -var ConsensusMinerMinPower = abi.NewStoragePower(16 << 30) -var MinVerifiedDealSize = abi.NewStoragePower(1 << 20) -var PreCommitChallengeDelay = abi.ChainEpoch(10) - -func init() { - policy.SetSupportedProofTypes(SupportedProofTypes...) - policy.SetConsensusMinerMinPower(ConsensusMinerMinPower) - policy.SetMinVerifiedDealSize(MinVerifiedDealSize) - policy.SetPreCommitChallengeDelay(PreCommitChallengeDelay) - - BuildType = BuildWallabynet - SetAddressNetwork(address.Testnet) - Devnet = true - -} - -const BlockDelaySecs = uint64(builtin2.EpochDurationSeconds) - -const PropagationDelaySecs = uint64(6) - -// BootstrapPeerThreshold is the minimum number peers we need to track for a sync worker to start -const BootstrapPeerThreshold = 2 - -// ChainId defines the chain ID used in the Ethereum JSON-RPC endpoint. -// As per https://github.com/ethereum-lists/chains -const Eip155ChainId = 31415 - -var WhitelistedBlock = cid.Undef diff --git a/build/version.go b/build/version.go index 4946059e2..70e27ad50 100644 --- a/build/version.go +++ b/build/version.go @@ -6,15 +6,13 @@ var CurrentCommit string var BuildType int const ( - BuildDefault = 0 - BuildMainnet = 0x1 - Build2k = 0x2 - BuildDebug = 0x3 - BuildCalibnet = 0x4 - BuildInteropnet = 0x5 - BuildButterflynet = 0x7 - BuildWallabynet = 0x8 - BuildHyperspacenet = 0x9 + BuildDefault = 0 + BuildMainnet = 0x1 + Build2k = 0x2 + BuildDebug = 0x3 + BuildCalibnet = 0x4 + BuildInteropnet = 0x5 + BuildButterflynet = 0x7 ) func BuildTypeString() string { @@ -33,10 +31,6 @@ func BuildTypeString() string { return "+interopnet" case BuildButterflynet: return "+butterflynet" - case BuildWallabynet: - return "+wallabynet" - case BuildHyperspacenet: - return "+hyperspacenet" default: return "+huh?" } diff --git a/chain/actors/builtin/builtin.go b/chain/actors/builtin/builtin.go index 116ed35d0..414a11e72 100644 --- a/chain/actors/builtin/builtin.go +++ b/chain/actors/builtin/builtin.go @@ -26,6 +26,7 @@ import ( var SystemActorAddr = builtin.SystemActorAddr var BurntFundsActorAddr = builtin.BurntFundsActorAddr var CronActorAddr = builtin.CronActorAddr +var EthereumAddressManagerActorAddr = builtin.EthereumAddressManagerActorAddr var SaftAddress = makeAddress("t0122") var ReserveAddress = makeAddress("t090") var RootVerifierAddress = makeAddress("t080") diff --git a/chain/actors/builtin/builtin.go.template b/chain/actors/builtin/builtin.go.template index 977217b1a..3b737c47e 100644 --- a/chain/actors/builtin/builtin.go.template +++ b/chain/actors/builtin/builtin.go.template @@ -26,6 +26,7 @@ import ( var SystemActorAddr = builtin.SystemActorAddr var BurntFundsActorAddr = builtin.BurntFundsActorAddr var CronActorAddr = builtin.CronActorAddr +var EthereumAddressManagerActorAddr = builtin.EthereumAddressManagerActorAddr var SaftAddress = makeAddress("t0122") var ReserveAddress = makeAddress("t090") var RootVerifierAddress = makeAddress("t080") diff --git a/chain/actors/builtin/evm/actor.go.template b/chain/actors/builtin/evm/actor.go.template index d20db6bcb..aa23b5f11 100644 --- a/chain/actors/builtin/evm/actor.go.template +++ b/chain/actors/builtin/evm/actor.go.template @@ -49,4 +49,8 @@ type State interface { Nonce() (uint64, error) GetState() interface{} + + GetBytecode() ([]byte, error) + GetBytecodeCID() (cid.Cid, error) + GetBytecodeHash() ([32]byte, error) } diff --git a/chain/actors/builtin/evm/evm.go b/chain/actors/builtin/evm/evm.go index 120ca66f8..f55a2177d 100644 --- a/chain/actors/builtin/evm/evm.go +++ b/chain/actors/builtin/evm/evm.go @@ -49,4 +49,8 @@ type State interface { Nonce() (uint64, error) GetState() interface{} + + GetBytecode() ([]byte, error) + GetBytecodeCID() (cid.Cid, error) + GetBytecodeHash() ([32]byte, error) } diff --git a/chain/actors/builtin/evm/state.go.template b/chain/actors/builtin/evm/state.go.template index acc78dc0f..eb55a8463 100644 --- a/chain/actors/builtin/evm/state.go.template +++ b/chain/actors/builtin/evm/state.go.template @@ -21,12 +21,12 @@ func load{{.v}}(store adt.Store, root cid.Cid) (State, error) { func make{{.v}}(store adt.Store, bytecode cid.Cid) (State, error) { out := state{{.v}}{store: store} - s, err := evm{{.v}}.ConstructState(store, bytecode) - if err != nil { - return nil, err - } + s, err := evm{{.v}}.ConstructState(store, bytecode) + if err != nil { + return nil, err + } - out.State = *s + out.State = *s return &out, nil } @@ -42,4 +42,26 @@ func (s *state{{.v}}) Nonce() (uint64, error) { func (s *state{{.v}}) GetState() interface{} { return &s.State -} \ No newline at end of file +} + +func (s *state{{.v}}) GetBytecodeCID() (cid.Cid, error) { + return s.State.Bytecode, nil +} + +func (s *state{{.v}}) GetBytecodeHash() ([32]byte, error) { + return s.State.BytecodeHash, nil +} + +func (s *state{{.v}}) GetBytecode() ([]byte, error) { + bc, err := s.GetBytecodeCID() + if err != nil { + return nil, err + } + + var byteCode abi.CborBytesTransparent + if err := s.store.Get(s.store.Context(), bc, &byteCode); err != nil { + return nil, err + } + + return byteCode, nil +} diff --git a/chain/actors/builtin/evm/v10.go b/chain/actors/builtin/evm/v10.go index 78a4a2383..77a09037b 100644 --- a/chain/actors/builtin/evm/v10.go +++ b/chain/actors/builtin/evm/v10.go @@ -3,6 +3,7 @@ package evm import ( "github.com/ipfs/go-cid" + "github.com/filecoin-project/go-state-types/abi" evm10 "github.com/filecoin-project/go-state-types/builtin/v10/evm" "github.com/filecoin-project/lotus/chain/actors/adt" @@ -43,3 +44,25 @@ func (s *state10) Nonce() (uint64, error) { func (s *state10) GetState() interface{} { return &s.State } + +func (s *state10) GetBytecodeCID() (cid.Cid, error) { + return s.State.Bytecode, nil +} + +func (s *state10) GetBytecodeHash() ([32]byte, error) { + return s.State.BytecodeHash, nil +} + +func (s *state10) GetBytecode() ([]byte, error) { + bc, err := s.GetBytecodeCID() + if err != nil { + return nil, err + } + + var byteCode abi.CborBytesTransparent + if err := s.store.Get(s.store.Context(), bc, &byteCode); err != nil { + return nil, err + } + + return byteCode, nil +} diff --git a/chain/consensus/filcns/compute_state.go b/chain/consensus/filcns/compute_state.go index 4b1ff245d..13dbc2069 100644 --- a/chain/consensus/filcns/compute_state.go +++ b/chain/consensus/filcns/compute_state.go @@ -5,11 +5,13 @@ import ( "sync/atomic" "github.com/ipfs/go-cid" + cbor "github.com/ipfs/go-ipld-cbor" cbg "github.com/whyrusleeping/cbor-gen" "go.opencensus.io/stats" "go.opencensus.io/trace" "golang.org/x/xerrors" + amt4 "github.com/filecoin-project/go-amt-ipld/v4" "github.com/filecoin-project/go-state-types/abi" actorstypes "github.com/filecoin-project/go-state-types/actors" "github.com/filecoin-project/go-state-types/big" @@ -89,11 +91,11 @@ func (t *TipSetExecutor) ApplyBlocks(ctx context.Context, }() ctx = blockstore.WithHotView(ctx) - makeVmWithBaseStateAndEpoch := func(base cid.Cid, e abi.ChainEpoch) (vm.Interface, error) { + makeVm := func(base cid.Cid, e abi.ChainEpoch, timestamp uint64) (vm.Interface, error) { vmopt := &vm.VMOpts{ StateBase: base, Epoch: e, - Timestamp: ts.MinTimestamp(), + Timestamp: timestamp, Rand: r, Bstore: sm.ChainStore().StateBlockstore(), Actors: NewActorRegistry(), @@ -104,6 +106,7 @@ func (t *TipSetExecutor) ApplyBlocks(ctx context.Context, LookbackState: stmgr.LookbackStateGetterForTipset(sm, ts), TipSetGetter: stmgr.TipSetGetterForTipset(sm.ChainStore(), ts), Tracing: vmTracing, + ReturnEvents: sm.ChainStore().IsStoringEvents(), } return sm.VMConstructor()(ctx, vmopt) @@ -138,10 +141,22 @@ func (t *TipSetExecutor) ApplyBlocks(ctx context.Context, return nil } + // May get filled with the genesis block header if there are null rounds + // for which to backfill cron execution. + var genesis *types.BlockHeader + + // There were null rounds in between the current epoch and the parent epoch. for i := parentEpoch; i < epoch; i++ { var err error if i > parentEpoch { - vmCron, err := makeVmWithBaseStateAndEpoch(pstate, i) + if genesis == nil { + if genesis, err = sm.ChainStore().GetGenesis(ctx); err != nil { + return cid.Undef, cid.Undef, xerrors.Errorf("failed to get genesis when backfilling null rounds: %w", err) + } + } + + ts := genesis.Timestamp + build.BlockDelaySecs*(uint64(i)) + vmCron, err := makeVm(pstate, i, ts) if err != nil { return cid.Undef, cid.Undef, xerrors.Errorf("making cron vm: %w", err) } @@ -168,13 +183,18 @@ func (t *TipSetExecutor) ApplyBlocks(ctx context.Context, partDone() partDone = metrics.Timer(ctx, metrics.VMApplyMessages) - vmi, err := makeVmWithBaseStateAndEpoch(pstate, epoch) + vmi, err := makeVm(pstate, epoch, ts.MinTimestamp()) if err != nil { return cid.Undef, cid.Undef, xerrors.Errorf("making vm: %w", err) } - var receipts []cbg.CBORMarshaler - processedMsgs := make(map[cid.Cid]struct{}) + var ( + receipts []*types.MessageReceipt + storingEvents = sm.ChainStore().IsStoringEvents() + events [][]types.Event + processedMsgs = make(map[cid.Cid]struct{}) + ) + for _, b := range bms { penalty := types.NewInt(0) gasReward := big.Zero() @@ -193,6 +213,11 @@ func (t *TipSetExecutor) ApplyBlocks(ctx context.Context, gasReward = big.Add(gasReward, r.GasCosts.MinerTip) penalty = big.Add(penalty, r.GasCosts.MinerPenalty) + if storingEvents { + // Appends nil when no events are returned to preserve positional alignment. + events = append(events, r.Events) + } + if em != nil { if err := em.MessageApplied(ctx, ts, cm.Cid(), m, r, false); err != nil { return cid.Undef, cid.Undef, err @@ -258,6 +283,23 @@ func (t *TipSetExecutor) ApplyBlocks(ctx context.Context, return cid.Undef, cid.Undef, xerrors.Errorf("failed to build receipts amt: %w", err) } + // Slice will be empty if not storing events. + for i, evs := range events { + if len(evs) == 0 { + continue + } + switch root, err := t.StoreEventsAMT(ctx, sm.ChainStore(), evs); { + case err != nil: + return cid.Undef, cid.Undef, xerrors.Errorf("failed to store events amt: %w", err) + case i >= len(receipts): + return cid.Undef, cid.Undef, xerrors.Errorf("assertion failed: receipt and events array lengths inconsistent") + case receipts[i].EventsRoot == nil: + return cid.Undef, cid.Undef, xerrors.Errorf("assertion failed: VM returned events with no events root") + case root != *receipts[i].EventsRoot: + return cid.Undef, cid.Undef, xerrors.Errorf("assertion failed: returned events AMT root does not match derived") + } + } + st, err := vmi.Flush(ctx) if err != nil { return cid.Undef, cid.Undef, xerrors.Errorf("vm flush failed: %w", err) @@ -316,4 +358,13 @@ func (t *TipSetExecutor) ExecuteTipSet(ctx context.Context, return t.ApplyBlocks(ctx, sm, parentEpoch, pstate, fbmsgs, blks[0].Height, r, em, vmTracing, baseFee, ts) } +func (t *TipSetExecutor) StoreEventsAMT(ctx context.Context, cs *store.ChainStore, events []types.Event) (cid.Cid, error) { + cst := cbor.NewCborStore(cs.ChainBlockstore()) + objs := make([]cbg.CBORMarshaler, len(events)) + for i := 0; i < len(events); i++ { + objs[i] = &events[i] + } + return amt4.FromArray(ctx, cst, objs, amt4.UseTreeBitWidth(types.EventAMTBitwidth)) +} + var _ stmgr.Executor = &TipSetExecutor{} diff --git a/chain/ethhashlookup/eth_transaction_hash_lookup.go b/chain/ethhashlookup/eth_transaction_hash_lookup.go index 85cb84db1..d93680912 100644 --- a/chain/ethhashlookup/eth_transaction_hash_lookup.go +++ b/chain/ethhashlookup/eth_transaction_hash_lookup.go @@ -67,34 +67,28 @@ func (ei *EthTxHashLookup) UpsertHash(txHash ethtypes.EthHash, c cid.Cid) error } func (ei *EthTxHashLookup) GetCidFromHash(txHash ethtypes.EthHash) (cid.Cid, error) { - q, err := ei.db.Query("SELECT cid FROM eth_tx_hashes WHERE hash = :hash;", sql.Named("hash", txHash.String())) - if err != nil { - return cid.Undef, err - } + row := ei.db.QueryRow("SELECT cid FROM eth_tx_hashes WHERE hash = :hash;", sql.Named("hash", txHash.String())) var c string - if !q.Next() { - return cid.Undef, ErrNotFound - } - err = q.Scan(&c) + err := row.Scan(&c) if err != nil { + if err == sql.ErrNoRows { + return cid.Undef, ErrNotFound + } return cid.Undef, err } return cid.Decode(c) } func (ei *EthTxHashLookup) GetHashFromCid(c cid.Cid) (ethtypes.EthHash, error) { - q, err := ei.db.Query("SELECT hash FROM eth_tx_hashes WHERE cid = :cid;", sql.Named("cid", c.String())) - if err != nil { - return ethtypes.EmptyEthHash, err - } + row := ei.db.QueryRow("SELECT hash FROM eth_tx_hashes WHERE cid = :cid;", sql.Named("cid", c.String())) var hashString string - if !q.Next() { - return ethtypes.EmptyEthHash, ErrNotFound - } - err = q.Scan(&hashString) + err := row.Scan(&c) if err != nil { + if err == sql.ErrNoRows { + return ethtypes.EmptyEthHash, ErrNotFound + } return ethtypes.EmptyEthHash, err } return ethtypes.ParseEthHash(hashString) diff --git a/chain/events/filter/event.go b/chain/events/filter/event.go index 7d59ad8bd..b821a2f83 100644 --- a/chain/events/filter/event.go +++ b/chain/events/filter/event.go @@ -20,7 +20,12 @@ import ( "github.com/filecoin-project/lotus/chain/types" ) -const indexed uint8 = 0x01 +func isIndexedValue(b uint8) bool { + // currently we mark the full entry as indexed if either the key + // or the value are indexed; in the future we will need finer-grained + // management of indices + return b&(types.EventFlagIndexedKey|types.EventFlagIndexedValue) > 0 +} type EventFilter struct { id types.FilterID @@ -100,18 +105,9 @@ func (f *EventFilter) CollectEvents(ctx context.Context, te *TipSetEvents, rever continue } - decodedEntries := make([]types.EventEntry, len(ev.Entries)) - for i, entry := range ev.Entries { - decodedEntries[i] = types.EventEntry{ - Flags: entry.Flags, - Key: entry.Key, - Value: decodeLogBytes(entry.Value), - } - } - // event matches filter, so record it cev := &CollectedEvent{ - Entries: decodedEntries, + Entries: ev.Entries, EmitterAddr: addr, EventIdx: evIdx, Reverted: revert, @@ -209,7 +205,7 @@ func (f *EventFilter) matchKeys(ees []types.EventEntry) bool { matched := map[string]bool{} for _, ee := range ees { // Skip an entry that is not indexable - if ee.Flags&indexed != indexed { + if !isIndexedValue(ee.Flags) { continue } @@ -221,7 +217,7 @@ func (f *EventFilter) matchKeys(ees []types.EventEntry) bool { } wantlist, ok := f.keys[keyname] - if !ok { + if !ok || len(wantlist) == 0 { continue } diff --git a/chain/events/filter/event_test.go b/chain/events/filter/event_test.go index 80c4c7fc0..329573bc1 100644 --- a/chain/events/filter/event_test.go +++ b/chain/events/filter/event_test.go @@ -287,6 +287,7 @@ func fakeEvent(emitter abi.ActorID, indexed []kv, unindexed []kv) *types.Event { ev.Entries = append(ev.Entries, types.EventEntry{ Flags: 0x01, Key: in.k, + Codec: cid.Raw, Value: in.v, }) } @@ -295,6 +296,7 @@ func fakeEvent(emitter abi.ActorID, indexed []kv, unindexed []kv) *types.Event { ev.Entries = append(ev.Entries, types.EventEntry{ Flags: 0x00, Key: in.k, + Codec: cid.Raw, Value: in.v, }) } diff --git a/chain/events/filter/index.go b/chain/events/filter/index.go index 1920a91fe..ab4e24493 100644 --- a/chain/events/filter/index.go +++ b/chain/events/filter/index.go @@ -1,7 +1,6 @@ package filter import ( - "bytes" "context" "database/sql" "errors" @@ -11,7 +10,6 @@ import ( "github.com/ipfs/go-cid" _ "github.com/mattn/go-sqlite3" - cbg "github.com/whyrusleeping/cbor-gen" "golang.org/x/xerrors" "github.com/filecoin-project/go-address" @@ -49,6 +47,7 @@ var ddls = []string{ indexed INTEGER NOT NULL, flags BLOB NOT NULL, key TEXT NOT NULL, + codec INTEGER, value BLOB NOT NULL )`, @@ -69,8 +68,8 @@ const ( VALUES(?, ?, ?, ?, ?, ?, ?, ?)` insertEntry = `INSERT OR IGNORE INTO event_entry - (event_id, indexed, flags, key, value) - VALUES(?, ?, ?, ?, ?)` + (event_id, indexed, flags, key, codec, value) + VALUES(?, ?, ?, ?, ?, ?)` ) type EventIndex struct { @@ -153,13 +152,6 @@ func (ei *EventIndex) CollectEvents(ctx context.Context, te *TipSetEvents, rever return xerrors.Errorf("prepare insert entry: %w", err) } - isIndexedValue := func(b uint8) bool { - // currently we mark the full entry as indexed if either the key - // or the value are indexed; in the future we will need finer-grained - // management of indices - return b&(types.EventFlagIndexedKey|types.EventFlagIndexedValue) > 0 - } - for msgIdx, em := range ems { for evIdx, ev := range em.Events() { addr, found := addressLookups[ev.Emitter] @@ -198,13 +190,13 @@ func (ei *EventIndex) CollectEvents(ctx context.Context, te *TipSetEvents, rever } for _, entry := range ev.Entries { - value := decodeLogBytes(entry.Value) _, err := stmtEntry.Exec( lastID, // event_id isIndexedValue(entry.Flags), // indexed []byte{entry.Flags}, // flags entry.Key, // key - value, // value + entry.Codec, // codec + entry.Value, // value ) if err != nil { return xerrors.Errorf("exec insert entry: %w", err) @@ -220,21 +212,6 @@ func (ei *EventIndex) CollectEvents(ctx context.Context, te *TipSetEvents, rever return nil } -// decodeLogBytes decodes a CBOR-serialized array into its original form. -// -// This function swallows errors and returns the original array if it failed -// to decode. -func decodeLogBytes(orig []byte) []byte { - if len(orig) == 0 { - return orig - } - decoded, err := cbg.ReadByteArray(bytes.NewReader(orig), uint64(len(orig))) - if err != nil { - return orig - } - return decoded -} - // PrefillFilter fills a filter's collection of events from the historic index func (ei *EventIndex) PrefillFilter(ctx context.Context, f *EventFilter) error { clauses := []string{} @@ -276,7 +253,7 @@ func (ei *EventIndex) PrefillFilter(ctx context.Context, f *EventFilter) error { subclauses := []string{} for _, val := range vals { subclauses = append(subclauses, fmt.Sprintf("%s.value=?", joinAlias)) - values = append(values, trimLeadingZeros(val)) + values = append(values, val) } clauses = append(clauses, "("+strings.Join(subclauses, " OR ")+")") } @@ -295,6 +272,7 @@ func (ei *EventIndex) PrefillFilter(ctx context.Context, f *EventFilter) error { event.reverted, event_entry.flags, event_entry.key, + event_entry.codec, event_entry.value FROM event JOIN event_entry ON event.id=event_entry.event_id` @@ -344,6 +322,7 @@ func (ei *EventIndex) PrefillFilter(ctx context.Context, f *EventFilter) error { reverted bool flags []byte key string + codec uint64 value []byte } @@ -359,6 +338,7 @@ func (ei *EventIndex) PrefillFilter(ctx context.Context, f *EventFilter) error { &row.reverted, &row.flags, &row.key, + &row.codec, &row.value, ); err != nil { return xerrors.Errorf("read prefill row: %w", err) @@ -403,6 +383,7 @@ func (ei *EventIndex) PrefillFilter(ctx context.Context, f *EventFilter) error { ce.Entries = append(ce.Entries, types.EventEntry{ Flags: row.flags[0], Key: row.key, + Codec: row.codec, Value: row.value, }) @@ -423,12 +404,3 @@ func (ei *EventIndex) PrefillFilter(ctx context.Context, f *EventFilter) error { return nil } - -func trimLeadingZeros(b []byte) []byte { - for i := range b { - if b[i] != 0 { - return b[i:] - } - } - return []byte{} -} diff --git a/chain/messagesigner/messagesigner.go b/chain/messagesigner/messagesigner.go index 6a622dd57..84dd6d0aa 100644 --- a/chain/messagesigner/messagesigner.go +++ b/chain/messagesigner/messagesigner.go @@ -202,7 +202,7 @@ func (ms *MessageSigner) dstoreKey(addr address.Address) datastore.Key { func SigningBytes(msg *types.Message, sigType crypto.SigType) ([]byte, error) { if sigType == crypto.SigTypeDelegated { - txArgs, err := ethtypes.EthTxArgsFromMessage(msg) + txArgs, err := ethtypes.EthTxArgsFromUnsignedEthMessage(msg) if err != nil { return nil, xerrors.Errorf("failed to reconstruct eth transaction: %w", err) } diff --git a/chain/signatures.go b/chain/signatures.go index c70ef5b74..1dc67fd2c 100644 --- a/chain/signatures.go +++ b/chain/signatures.go @@ -22,7 +22,7 @@ func AuthenticateMessage(msg *types.SignedMessage, signer address.Address) error typ := msg.Signature.Type switch typ { case crypto.SigTypeDelegated: - txArgs, err := ethtypes.EthTxArgsFromMessage(&msg.Message) + txArgs, err := ethtypes.EthTxArgsFromUnsignedEthMessage(&msg.Message) if err != nil { return xerrors.Errorf("failed to reconstruct eth transaction: %w", err) } diff --git a/chain/stmgr/supply.go b/chain/stmgr/supply.go index 89708097e..a48ff36c7 100644 --- a/chain/stmgr/supply.go +++ b/chain/stmgr/supply.go @@ -403,7 +403,8 @@ func (sm *StateManager) GetCirculatingSupply(ctx context.Context, height abi.Cha a == builtin.CronActorAddr || a == builtin.BurntFundsActorAddr || a == builtin.SaftAddress || - a == builtin.ReserveAddress: + a == builtin.ReserveAddress || + a == builtin.EthereumAddressManagerActorAddr: unCirc = big.Add(unCirc, actor.Balance) @@ -421,7 +422,12 @@ func (sm *StateManager) GetCirculatingSupply(ctx context.Context, height abi.Cha circ = big.Add(circ, big.Sub(actor.Balance, lb)) unCirc = big.Add(unCirc, lb) - case builtin.IsAccountActor(actor.Code) || builtin.IsPaymentChannelActor(actor.Code): + case builtin.IsAccountActor(actor.Code) || + builtin.IsPaymentChannelActor(actor.Code) || + builtin.IsEthAccountActor(actor.Code) || + builtin.IsEvmActor(actor.Code) || + builtin.IsPlaceholderActor(actor.Code): + circ = big.Add(circ, actor.Balance) case builtin.IsStorageMinerActor(actor.Code): diff --git a/chain/store/messages.go b/chain/store/messages.go index 5e2880c4a..1ee1f8ad4 100644 --- a/chain/store/messages.go +++ b/chain/store/messages.go @@ -256,6 +256,20 @@ func (cs *ChainStore) MessagesForBlock(ctx context.Context, b *types.BlockHeader return blsmsgs, secpkmsgs, nil } +func (cs *ChainStore) SecpkMessagesForBlock(ctx context.Context, b *types.BlockHeader) ([]*types.SignedMessage, error) { + _, secpkcids, err := cs.ReadMsgMetaCids(ctx, b.Messages) + if err != nil { + return nil, err + } + + secpkmsgs, err := cs.LoadSignedMessagesFromCids(ctx, secpkcids) + if err != nil { + return nil, xerrors.Errorf("loading secpk messages for block: %w", err) + } + + return secpkmsgs, nil +} + func (cs *ChainStore) GetParentReceipt(ctx context.Context, b *types.BlockHeader, i int) (*types.MessageReceipt, error) { // block headers use adt0, for now. a, err := blockadt.AsArray(cs.ActorStore(ctx), b.ParentMessageReceipts) diff --git a/chain/store/snapshot.go b/chain/store/snapshot.go index 3c264d192..e90a60611 100644 --- a/chain/store/snapshot.go +++ b/chain/store/snapshot.go @@ -22,7 +22,7 @@ import ( "github.com/filecoin-project/lotus/chain/types" ) -const TIPSETKEY_BACKFILL_RANGE = 2 * build.Finality +const TipsetkeyBackfillRange = 2 * build.Finality func (cs *ChainStore) UnionStore() bstore.Blockstore { return bstore.Union(cs.stateBlockstore, cs.chainBlockstore) @@ -116,7 +116,7 @@ func (cs *ChainStore) Import(ctx context.Context, r io.Reader) (*types.TipSet, e } ts := root - for i := 0; i < int(TIPSETKEY_BACKFILL_RANGE); i++ { + for i := 0; i < int(TipsetkeyBackfillRange); i++ { err = cs.PersistTipset(ctx, ts) if err != nil { return nil, err diff --git a/chain/store/store.go b/chain/store/store.go index 6dc17d766..2773f1ad3 100644 --- a/chain/store/store.go +++ b/chain/store/store.go @@ -126,6 +126,8 @@ type ChainStore struct { evtTypes [1]journal.EventType journal journal.Journal + storeEvents bool + cancelFn context.CancelFunc wg sync.WaitGroup } @@ -680,7 +682,7 @@ func FlushValidationCache(ctx context.Context, ds dstore.Batching) error { // If this is addressed (blockcache goes into its own sub-namespace) then // strings.HasPrefix(...) below can be skipped // - //Prefix: blockValidationCacheKeyPrefix.String() + // Prefix: blockValidationCacheKeyPrefix.String() KeysOnly: true, }) if err != nil { @@ -1202,6 +1204,16 @@ func (cs *ChainStore) Weight(ctx context.Context, hts *types.TipSet) (types.BigI return cs.weight(ctx, cs.StateBlockstore(), hts) } +// StoreEvents marks this ChainStore as storing events. +func (cs *ChainStore) StoreEvents(store bool) { + cs.storeEvents = store +} + +// IsStoringEvents indicates if this ChainStore is storing events. +func (cs *ChainStore) IsStoringEvents() bool { + return cs.storeEvents +} + // true if ts1 wins according to the filecoin tie-break rule func breakWeightTie(ts1, ts2 *types.TipSet) bool { s := len(ts1.Blocks()) diff --git a/chain/types/cbor_gen.go b/chain/types/cbor_gen.go index 709f7dd88..314b2be6c 100644 --- a/chain/types/cbor_gen.go +++ b/chain/types/cbor_gen.go @@ -1943,7 +1943,7 @@ func (t *Event) UnmarshalCBOR(r io.Reader) (err error) { return nil } -var lengthBufEventEntry = []byte{131} +var lengthBufEventEntry = []byte{132} func (t *EventEntry) MarshalCBOR(w io.Writer) error { if t == nil { @@ -1974,6 +1974,12 @@ func (t *EventEntry) MarshalCBOR(w io.Writer) error { return err } + // t.Codec (uint64) (uint64) + + if err := cw.WriteMajorTypeHeader(cbg.MajUnsignedInt, uint64(t.Codec)); err != nil { + return err + } + // t.Value ([]uint8) (slice) if len(t.Value) > cbg.ByteArrayMaxLen { return xerrors.Errorf("Byte array in field t.Value was too long") @@ -2008,7 +2014,7 @@ func (t *EventEntry) UnmarshalCBOR(r io.Reader) (err error) { return fmt.Errorf("cbor input should be of type array") } - if extra != 3 { + if extra != 4 { return fmt.Errorf("cbor input had wrong number of fields") } @@ -2035,6 +2041,20 @@ func (t *EventEntry) UnmarshalCBOR(r io.Reader) (err error) { t.Key = string(sval) } + // t.Codec (uint64) (uint64) + + { + + maj, extra, err = cr.ReadHeader() + if err != nil { + return err + } + if maj != cbg.MajUnsignedInt { + return fmt.Errorf("wrong type for uint64 field") + } + t.Codec = uint64(extra) + + } // t.Value ([]uint8) (slice) maj, extra, err = cr.ReadHeader() diff --git a/chain/types/ethtypes/eth_transactions.go b/chain/types/ethtypes/eth_transactions.go index b6ae22169..5c2283d2b 100644 --- a/chain/types/ethtypes/eth_transactions.go +++ b/chain/types/ethtypes/eth_transactions.go @@ -12,13 +12,11 @@ import ( "github.com/filecoin-project/go-address" gocrypto "github.com/filecoin-project/go-crypto" - "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/big" builtintypes "github.com/filecoin-project/go-state-types/builtin" typescrypto "github.com/filecoin-project/go-state-types/crypto" "github.com/filecoin-project/lotus/build" - "github.com/filecoin-project/lotus/chain/actors" "github.com/filecoin-project/lotus/chain/types" ) @@ -39,7 +37,8 @@ type EthTx struct { Gas EthUint64 `json:"gas"` MaxFeePerGas EthBigInt `json:"maxFeePerGas"` MaxPriorityFeePerGas EthBigInt `json:"maxPriorityFeePerGas"` - V EthBigInt `json:"v"` + AccessList []EthHash `json:"accessList"` + V EthBigInt `json:"yParity"` R EthBigInt `json:"r"` S EthBigInt `json:"s"` } @@ -58,11 +57,50 @@ type EthTxArgs struct { S big.Int `json:"s"` } -func EthTxArgsFromMessage(msg *types.Message) (EthTxArgs, error) { +// EthTxFromSignedEthMessage does NOT populate: +// - BlockHash +// - BlockNumber +// - TransactionIndex +// - From +// - Hash +func EthTxFromSignedEthMessage(smsg *types.SignedMessage) (EthTx, error) { + if smsg.Signature.Type != typescrypto.SigTypeDelegated { + return EthTx{}, xerrors.Errorf("signature is not delegated type, is type: %d", smsg.Signature.Type) + } + + txArgs, err := EthTxArgsFromUnsignedEthMessage(&smsg.Message) + if err != nil { + return EthTx{}, xerrors.Errorf("failed to convert the unsigned message: %w", err) + } + + r, s, v, err := RecoverSignature(smsg.Signature) + if err != nil { + return EthTx{}, xerrors.Errorf("failed to recover signature: %w", err) + } + + return EthTx{ + Nonce: EthUint64(txArgs.Nonce), + ChainID: EthUint64(txArgs.ChainID), + To: txArgs.To, + Value: EthBigInt(txArgs.Value), + Type: Eip1559TxType, + Gas: EthUint64(txArgs.GasLimit), + MaxFeePerGas: EthBigInt(txArgs.MaxFeePerGas), + MaxPriorityFeePerGas: EthBigInt(txArgs.MaxPriorityFeePerGas), + AccessList: []EthHash{}, + V: v, + R: r, + S: s, + Input: txArgs.Input, + }, nil +} + +func EthTxArgsFromUnsignedEthMessage(msg *types.Message) (EthTxArgs, error) { var ( to *EthAddress params []byte paramsReader = bytes.NewReader(msg.Params) + err error ) if msg.Version != 0 { @@ -72,11 +110,10 @@ func EthTxArgsFromMessage(msg *types.Message) (EthTxArgs, error) { if msg.To == builtintypes.EthereumAddressManagerActorAddr { switch msg.Method { case builtintypes.MethodsEAM.CreateExternal: - var create abi.CborBytes - if err := create.UnmarshalCBOR(paramsReader); err != nil { - return EthTxArgs{}, err + params, err = cbg.ReadByteArray(paramsReader, uint64(len(msg.Params))) + if err != nil { + return EthTxArgs{}, xerrors.Errorf("failed to read params byte array: %w", err) } - params = create default: return EthTxArgs{}, fmt.Errorf("unsupported EAM method") } @@ -103,11 +140,6 @@ func EthTxArgsFromMessage(msg *types.Message) (EthTxArgs, error) { if err != nil { return EthTxArgs{}, xerrors.Errorf("failed to read params byte array: %w", err) } - - if len(params) == 0 { - // Otherwise, we don't get a guaranteed round-trip. - return EthTxArgs{}, xerrors.Errorf("cannot invoke contracts with empty parameters from an eth-account") - } } } @@ -115,6 +147,11 @@ func EthTxArgsFromMessage(msg *types.Message) (EthTxArgs, error) { return EthTxArgs{}, xerrors.Errorf("extra data found in params") } + if len(params) == 0 && msg.Method != builtintypes.MethodSend { + // Otherwise, we don't get a guaranteed round-trip. + return EthTxArgs{}, xerrors.Errorf("msgs with empty parameters from an eth-account must be Sends (MethodNum: %d)", msg.Method) + } + return EthTxArgs{ ChainID: build.Eip155ChainId, Nonce: int(msg.Nonce), @@ -143,12 +180,13 @@ func (tx *EthTxArgs) ToUnsignedMessage(from address.Address) (*types.Message, er if len(tx.Input) == 0 { return nil, xerrors.New("cannot call CreateExternal without params") } - inputParams := abi.CborBytes(tx.Input) - params, err = actors.SerializeParams(&inputParams) - if err != nil { - return nil, fmt.Errorf("failed to serialize Create params: %w", err) + + buf := new(bytes.Buffer) + if err = cbg.WriteByteArray(buf, tx.Input); err != nil { + return nil, xerrors.Errorf("failed to serialize Create params: %w", err) } + params = buf.Bytes() } else { to, err = tx.To.ToFilecoinAddress() if err != nil { diff --git a/chain/types/ethtypes/eth_types.go b/chain/types/ethtypes/eth_types.go index af27ec58c..0c455c0f0 100644 --- a/chain/types/ethtypes/eth_types.go +++ b/chain/types/ethtypes/eth_types.go @@ -22,13 +22,14 @@ import ( builtintypes "github.com/filecoin-project/go-state-types/builtin" "github.com/filecoin-project/lotus/build" + "github.com/filecoin-project/lotus/lib/must" ) var ( - EthTopic1 = "topic1" - EthTopic2 = "topic2" - EthTopic3 = "topic3" - EthTopic4 = "topic4" + EthTopic1 = "t1" + EthTopic2 = "t2" + EthTopic3 = "t3" + EthTopic4 = "t4" ) var ErrInvalidAddress = errors.New("invalid Filecoin Eth address") @@ -150,7 +151,7 @@ type EthBlock struct { GasLimit EthUint64 `json:"gasLimit"` GasUsed EthUint64 `json:"gasUsed"` Timestamp EthUint64 `json:"timestamp"` - Extradata []byte `json:"extraData"` + Extradata EthBytes `json:"extraData"` MixHash EthHash `json:"mixHash"` Nonce EthNonce `json:"nonce"` BaseFeePerGas EthBigInt `json:"baseFeePerGas"` @@ -160,21 +161,32 @@ type EthBlock struct { Uncles []EthHash `json:"uncles"` } +const EthBloomSize = 2048 + var ( - EmptyEthBloom = [256]byte{} - EmptyEthHash = EthHash{} - EmptyEthInt = EthUint64(0) - EmptyEthNonce = [8]byte{0, 0, 0, 0, 0, 0, 0, 0} + EmptyEthBloom = [EthBloomSize / 8]byte{} + FullEthBloom = [EthBloomSize / 8]byte{} + EmptyEthHash = EthHash{} + EmptyUncleHash = must.One(ParseEthHash("0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347")) // Keccak-256 of an RLP of an empty array + EmptyRootHash = must.One(ParseEthHash("0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421")) // Keccak-256 hash of the RLP of null + EmptyEthInt = EthUint64(0) + EmptyEthNonce = [8]byte{0, 0, 0, 0, 0, 0, 0, 0} ) -func NewEthBlock() EthBlock { - return EthBlock{ - Sha3Uncles: EmptyEthHash, +func init() { + for i := range FullEthBloom { + FullEthBloom[i] = 0xff + } +} + +func NewEthBlock(hasTransactions bool) EthBlock { + b := EthBlock{ + Sha3Uncles: EmptyUncleHash, // Sha3Uncles set to a hardcoded value which is used by some clients to determine if has no uncles. StateRoot: EmptyEthHash, - TransactionsRoot: EmptyEthHash, + TransactionsRoot: EmptyRootHash, // TransactionsRoot set to a hardcoded value which is used by some clients to determine if has no transactions. ReceiptsRoot: EmptyEthHash, Difficulty: EmptyEthInt, - LogsBloom: EmptyEthBloom[:], + LogsBloom: FullEthBloom[:], Extradata: []byte{}, MixHash: EmptyEthHash, Nonce: EmptyEthNonce, @@ -182,6 +194,11 @@ func NewEthBlock() EthBlock { Uncles: []EthHash{}, Transactions: []interface{}{}, } + if hasTransactions { + b.TransactionsRoot = EmptyEthHash + } + + return b } type EthCall struct { @@ -369,15 +386,20 @@ func (h *EthHash) UnmarshalJSON(b []byte) error { return nil } +func (h EthHash) String() string { + return "0x" + hex.EncodeToString(h[:]) +} + +// Should ONLY be used for blocks and Filecoin messages. Eth transactions expect a different hashing scheme. +func (h EthHash) ToCid() cid.Cid { + // err is always nil + mh, _ := multihash.EncodeName(h[:], "blake2b-256") + + return cid.NewCidV1(cid.DagCBOR, mh) +} + func decodeHexString(s string, expectedLen int) ([]byte, error) { - // Strip the leading 0x or 0X prefix since hex.DecodeString does not support it. - if strings.HasPrefix(s, "0x") || strings.HasPrefix(s, "0X") { - s = s[2:] - } - // Sometimes clients will omit a leading zero in a byte; pad so we can decode correctly. - if len(s)%2 == 1 { - s = "0" + s - } + s = handleHexStringPrefix(s) if len(s) != expectedLen*2 { return nil, xerrors.Errorf("expected hex string length sans prefix %d, got %d", expectedLen*2, len(s)) } @@ -388,6 +410,31 @@ func decodeHexString(s string, expectedLen int) ([]byte, error) { return b, nil } +func DecodeHexString(s string) ([]byte, error) { + s = handleHexStringPrefix(s) + b, err := hex.DecodeString(s) + if err != nil { + return nil, xerrors.Errorf("cannot parse hex value: %w", err) + } + return b, nil +} + +func DecodeHexStringTrimSpace(s string) ([]byte, error) { + return DecodeHexString(strings.TrimSpace(s)) +} + +func handleHexStringPrefix(s string) string { + // Strip the leading 0x or 0X prefix since hex.DecodeString does not support it. + if strings.HasPrefix(s, "0x") || strings.HasPrefix(s, "0X") { + s = s[2:] + } + // Sometimes clients will omit a leading zero in a byte; pad so we can decode correctly. + if len(s)%2 == 1 { + s = "0" + s + } + return s +} + func EthHashFromCid(c cid.Cid) (EthHash, error) { return ParseEthHash(c.Hash().HexString()[8:]) } @@ -412,20 +459,19 @@ func EthHashFromTxBytes(b []byte) EthHash { return ethHash } -func (h EthHash) String() string { - return "0x" + hex.EncodeToString(h[:]) -} +func EthBloomSet(f EthBytes, data []byte) { + hasher := sha3.NewLegacyKeccak256() + hasher.Write(data) + hash := hasher.Sum(nil) -// Should ONLY be used for blocks and Filecoin messages. Eth transactions expect a different hashing scheme. -func (h EthHash) ToCid() cid.Cid { - // err is always nil - mh, _ := multihash.EncodeName(h[:], "blake2b-256") - - return cid.NewCidV1(cid.DagCBOR, mh) + for i := 0; i < 3; i++ { + n := binary.BigEndian.Uint16(hash[i*2:]) % EthBloomSize + f[(EthBloomSize/8)-(n/8)-1] |= 1 << (n % 8) + } } type EthFeeHistory struct { - OldestBlock uint64 `json:"oldestBlock"` + OldestBlock EthUint64 `json:"oldestBlock"` BaseFeePerGas []EthBigInt `json:"baseFeePerGas"` GasUsedRatio []float64 `json:"gasUsedRatio"` Reward *[][]EthBigInt `json:"reward,omitempty"` @@ -433,9 +479,33 @@ type EthFeeHistory struct { type EthFilterID EthHash +func (h EthFilterID) MarshalJSON() ([]byte, error) { + return (EthHash)(h).MarshalJSON() +} + +func (h *EthFilterID) UnmarshalJSON(b []byte) error { + return (*EthHash)(h).UnmarshalJSON(b) +} + +func (h EthFilterID) String() string { + return (EthHash)(h).String() +} + // An opaque identifier generated by the Lotus node to refer to an active subscription. type EthSubscriptionID EthHash +func (h EthSubscriptionID) MarshalJSON() ([]byte, error) { + return (EthHash)(h).MarshalJSON() +} + +func (h *EthSubscriptionID) UnmarshalJSON(b []byte) error { + return (*EthHash)(h).UnmarshalJSON(b) +} + +func (h EthSubscriptionID) String() string { + return (EthHash)(h).String() +} + type EthFilterSpec struct { // Interpreted as an epoch or one of "latest" for last mined block, "earliest" for first, // "pending" for not yet committed messages. @@ -587,10 +657,53 @@ type EthLog struct { BlockNumber EthUint64 `json:"blockNumber"` } +// EthSubscribeParams handles raw jsonrpc params for eth_subscribe +type EthSubscribeParams struct { + EventType string + Params *EthSubscriptionParams +} + +func (e *EthSubscribeParams) UnmarshalJSON(b []byte) error { + var params []json.RawMessage + err := json.Unmarshal(b, ¶ms) + if err != nil { + return err + } + switch len(params) { + case 2: + err = json.Unmarshal(params[1], &e.Params) + if err != nil { + return err + } + fallthrough + case 1: + err = json.Unmarshal(params[0], &e.EventType) + if err != nil { + return err + } + default: + return xerrors.Errorf("expected 1 or 2 params, got %d", len(params)) + } + return nil +} + +func (e EthSubscribeParams) MarshalJSON() ([]byte, error) { + if e.Params != nil { + return json.Marshal([]interface{}{e.EventType, e.Params}) + } + return json.Marshal([]interface{}{e.EventType}) +} + type EthSubscriptionParams struct { // List of topics to be matched. // Optional, default: empty list Topics EthTopicSpec `json:"topics,omitempty"` + + // Actor address or a list of addresses from which event logs should originate. + // Optional, default nil. + // The JSON decoding must treat a string as equivalent to an array with one value, for example + // "0x8888f1f195afa192cfee86069858" must be decoded as [ "0x8888f1f195afa192cfee86069858" ] + Address EthAddressList `json:"address"` } type EthSubscriptionResponse struct { diff --git a/chain/types/ethtypes/eth_types_test.go b/chain/types/ethtypes/eth_types_test.go index b05557b07..7d49ab1b9 100644 --- a/chain/types/ethtypes/eth_types_test.go +++ b/chain/types/ethtypes/eth_types_test.go @@ -96,6 +96,48 @@ func TestEthHash(t *testing.T) { h1, err := EthHashFromCid(c) require.Nil(t, err) require.Equal(t, h, h1) + + jm, err := json.Marshal(h) + require.NoError(t, err) + require.Equal(t, hash, string(jm)) + } +} + +func TestEthFilterID(t *testing.T) { + testcases := []string{ + `"0x013dbb9442ca9667baccc6230fcd5c1c4b2d4d2870f4bd20681d4d47cfd15184"`, + `"0xab8653edf9f51785664a643b47605a7ba3d917b5339a0724e7642c114d0e4738"`, + } + + for _, hash := range testcases { + var h EthFilterID + err := h.UnmarshalJSON([]byte(hash)) + + require.Nil(t, err) + require.Equal(t, h.String(), strings.Replace(hash, `"`, "", -1)) + + jm, err := json.Marshal(h) + require.NoError(t, err) + require.Equal(t, hash, string(jm)) + } +} + +func TestEthSubscriptionID(t *testing.T) { + testcases := []string{ + `"0x013dbb9442ca9667baccc6230fcd5c1c4b2d4d2870f4bd20681d4d47cfd15184"`, + `"0xab8653edf9f51785664a643b47605a7ba3d917b5339a0724e7642c114d0e4738"`, + } + + for _, hash := range testcases { + var h EthSubscriptionID + err := h.UnmarshalJSON([]byte(hash)) + + require.Nil(t, err) + require.Equal(t, h.String(), strings.Replace(hash, `"`, "", -1)) + + jm, err := json.Marshal(h) + require.NoError(t, err) + require.Equal(t, hash, string(jm)) } } diff --git a/chain/types/event.go b/chain/types/event.go index 00c25ca4c..91b0e95d3 100644 --- a/chain/types/event.go +++ b/chain/types/event.go @@ -1,9 +1,20 @@ package types import ( + "bytes" + "fmt" + + cbg "github.com/whyrusleeping/cbor-gen" + "github.com/filecoin-project/go-state-types/abi" ) +// EventEntry flags defined in fvm_shared +const ( + EventFlagIndexedKey = 0b00000001 + EventFlagIndexedValue = 0b00000010 +) + type Event struct { // The ID of the actor that emitted this event. Emitter abi.ActorID @@ -19,14 +30,32 @@ type EventEntry struct { // The key of this event entry Key string - // Any DAG-CBOR encodeable type. + // The event value's codec + Codec uint64 + + // The event value Value []byte } type FilterID [32]byte // compatible with EthHash -// EventEntry flags defined in fvm_shared -const ( - EventFlagIndexedKey = 0b00000001 - EventFlagIndexedValue = 0b00000010 -) +// DecodeEvents decodes a CBOR list of CBOR-encoded events. +func DecodeEvents(input []byte) ([]Event, error) { + r := bytes.NewReader(input) + typ, len, err := cbg.NewCborReader(r).ReadHeader() + if err != nil { + return nil, fmt.Errorf("failed to read events: %w", err) + } + if typ != cbg.MajArray { + return nil, fmt.Errorf("expected a CBOR list, was major type %d", typ) + } + events := make([]Event, 0, len) + for i := 0; i < int(len); i++ { + var evt Event + if err := evt.UnmarshalCBOR(r); err != nil { + return nil, fmt.Errorf("failed to parse event: %w", err) + } + events = append(events, evt) + } + return events, nil +} diff --git a/chain/vm/fvm.go b/chain/vm/fvm.go index a81bc10d6..8e78e58d9 100644 --- a/chain/vm/fvm.go +++ b/chain/vm/fvm.go @@ -287,6 +287,9 @@ func (x *FvmExtern) workerKeyAtLookback(ctx context.Context, minerId address.Add type FVM struct { fvm *ffi.FVM nv network.Version + + // returnEvents specifies whether to parse and return events when applying messages. + returnEvents bool } func defaultFVMOpts(ctx context.Context, opts *VMOpts) (*ffi.FVMOpts, error) { @@ -335,10 +338,13 @@ func NewFVM(ctx context.Context, opts *VMOpts) (*FVM, error) { return nil, xerrors.Errorf("failed to create FVM: %w", err) } - return &FVM{ - fvm: fvm, - nv: opts.NetworkVersion, - }, nil + ret := &FVM{ + fvm: fvm, + nv: opts.NetworkVersion, + returnEvents: opts.ReturnEvents, + } + + return ret, nil } func NewDebugFVM(ctx context.Context, opts *VMOpts) (*FVM, error) { @@ -438,10 +444,13 @@ func NewDebugFVM(ctx context.Context, opts *VMOpts) (*FVM, error) { return nil, err } - return &FVM{ - fvm: fvm, - nv: opts.NetworkVersion, - }, nil + ret := &FVM{ + fvm: fvm, + nv: opts.NetworkVersion, + returnEvents: opts.ReturnEvents, + } + + return ret, nil } func (vm *FVM) ApplyMessage(ctx context.Context, cmsg types.ChainMsg) (*ApplyRet, error) { @@ -493,7 +502,7 @@ func (vm *FVM) ApplyMessage(ctx context.Context, cmsg types.ChainMsg) (*ApplyRet et.Error = aerr.Error() } - return &ApplyRet{ + applyRet := &ApplyRet{ MessageReceipt: receipt, GasCosts: &GasOutputs{ BaseFeeBurn: ret.BaseFeeBurn, @@ -507,7 +516,16 @@ func (vm *FVM) ApplyMessage(ctx context.Context, cmsg types.ChainMsg) (*ApplyRet ActorErr: aerr, ExecutionTrace: et, Duration: duration, - }, nil + } + + if vm.returnEvents && len(ret.EventsBytes) > 0 { + applyRet.Events, err = types.DecodeEvents(ret.EventsBytes) + if err != nil { + return nil, fmt.Errorf("failed to decode events returned by the FVM: %w", err) + } + } + + return applyRet, nil } func (vm *FVM) ApplyImplicitMessage(ctx context.Context, cmsg *types.Message) (*ApplyRet, error) { @@ -565,6 +583,13 @@ func (vm *FVM) ApplyImplicitMessage(ctx context.Context, cmsg *types.Message) (* Duration: duration, } + if vm.returnEvents && len(ret.EventsBytes) > 0 { + applyRet.Events, err = types.DecodeEvents(ret.EventsBytes) + if err != nil { + return nil, fmt.Errorf("failed to decode events returned by the FVM: %w", err) + } + } + if ret.ExitCode != 0 { return applyRet, fmt.Errorf("implicit message failed with exit code: %d and error: %w", ret.ExitCode, applyRet.ActorErr) } diff --git a/chain/vm/gas.go b/chain/vm/gas.go index c9007d3f1..cb0c5def9 100644 --- a/chain/vm/gas.go +++ b/chain/vm/gas.go @@ -213,6 +213,16 @@ var Prices = map[abi.ChainEpoch]Pricelist{ verifyReplicaUpdate: 36316136, }, + build.UpgradeHyggeHeight: &pricelistV0{ + computeGasMulti: 1, + storageGasMulti: 1300, // only applies to messages/return values. + + onChainMessageComputeBase: 38863 + 475000, // includes the actor update cost + onChainMessageStorageBase: 36, + onChainMessageStoragePerByte: 1, + + onChainReturnValuePerByte: 1, + }, } // PricelistByEpoch finds the latest prices for the given epoch diff --git a/chain/vm/invoker.go b/chain/vm/invoker.go index 47bd2e326..cea17f61d 100644 --- a/chain/vm/invoker.go +++ b/chain/vm/invoker.go @@ -291,7 +291,10 @@ func DumpActorState(i *ActorRegistry, act *types.Actor, b []byte) (interface{}, um := actInfo.vmActor.State() if um == nil { - // TODO::FVM @arajasek I would like to assert that we have the empty object here + if act.Head != EmptyObjectCid { + return nil, xerrors.Errorf("actor with code %s should only have empty object (%s) as its Head, instead has %s", act.Code, EmptyObjectCid, act.Head) + } + return nil, nil } if err := um.UnmarshalCBOR(bytes.NewReader(b)); err != nil { diff --git a/chain/vm/vm.go b/chain/vm/vm.go index e18c4aea9..dcebe2b17 100644 --- a/chain/vm/vm.go +++ b/chain/vm/vm.go @@ -236,6 +236,8 @@ type VMOpts struct { LookbackState LookbackStateGetter TipSetGetter TipSetGetter Tracing bool + // ReturnEvents decodes and returns emitted events. + ReturnEvents bool } func NewLegacyVM(ctx context.Context, opts *VMOpts) (*LegacyVM, error) { @@ -282,6 +284,7 @@ type ApplyRet struct { ExecutionTrace types.ExecutionTrace Duration time.Duration GasCosts *GasOutputs + Events []types.Event } func (vm *LegacyVM) send(ctx context.Context, msg *types.Message, parent *Runtime, diff --git a/cli/client.go b/cli/client.go index 1c41262a5..a8355f9a1 100644 --- a/cli/client.go +++ b/cli/client.go @@ -1517,6 +1517,8 @@ func GetAsks(ctx context.Context, api lapi.FullNode) ([]QueriedAsk, error) { } }(miner) } + + wg.Wait() }() loop: @@ -1590,6 +1592,8 @@ loop: lk.Unlock() }(miner) } + + wg.Wait() }() loop2: diff --git a/cli/evm.go b/cli/evm.go index 738788448..2169a3486 100644 --- a/cli/evm.go +++ b/cli/evm.go @@ -38,25 +38,13 @@ var EvmCmd = &cli.Command{ } var EvmGetInfoCmd = &cli.Command{ - Name: "stat", - Usage: "Print eth/filecoin addrs and code cid", - Flags: []cli.Flag{ - &cli.StringFlag{ - Name: "filAddr", - Usage: "Filecoin address", - }, - &cli.StringFlag{ - Name: "ethAddr", - Usage: "Ethereum address", - }, - }, + Name: "stat", + Usage: "Print eth/filecoin addrs and code cid", + ArgsUsage: "address", Action: func(cctx *cli.Context) error { - - filAddr := cctx.String("filAddr") - ethAddr := cctx.String("ethAddr") - - var faddr address.Address - var eaddr ethtypes.EthAddress + if cctx.NArg() != 1 { + return IncorrectNumArgs(cctx) + } api, closer, err := GetFullNodeAPI(cctx) if err != nil { @@ -65,26 +53,25 @@ var EvmGetInfoCmd = &cli.Command{ defer closer() ctx := ReqContext(cctx) - if filAddr != "" { - addr, err := address.NewFromString(filAddr) - if err != nil { - return err - } - eaddr, faddr, err = ethAddrFromFilecoinAddress(ctx, addr, api) - if err != nil { - return err - } - } else if ethAddr != "" { - eaddr, err = ethtypes.ParseEthAddress(ethAddr) - if err != nil { - return err + addrString := cctx.Args().Get(0) + + var faddr address.Address + var eaddr ethtypes.EthAddress + addr, err := address.NewFromString(addrString) + if err != nil { // This isn't a filecoin address + eaddr, err = ethtypes.ParseEthAddress(addrString) + if err != nil { // This isn't an Eth address either + return xerrors.Errorf("address is not a filecoin or eth address") } faddr, err = eaddr.ToFilecoinAddress() if err != nil { return err } } else { - return xerrors.Errorf("Neither filAddr nor ethAddr specified") + eaddr, faddr, err = ethAddrFromFilecoinAddress(ctx, addr, api) + if err != nil { + return err + } } actor, err := api.StateGetActor(ctx, faddr, types.EmptyTSK) @@ -97,7 +84,6 @@ var EvmGetInfoCmd = &cli.Command{ fmt.Println("Code cid: ", actor.Code.String()) return nil - }, } @@ -121,7 +107,7 @@ var EvmCallSimulateCmd = &cli.Command{ return err } - params, err := hex.DecodeString(cctx.Args().Get(2)) + params, err := ethtypes.DecodeHexStringTrimSpace(cctx.Args().Get(2)) if err != nil { return err } @@ -165,7 +151,7 @@ var EvmGetContractAddress = &cli.Command{ return err } - salt, err := hex.DecodeString(cctx.Args().Get(1)) + salt, err := ethtypes.DecodeHexStringTrimSpace(cctx.Args().Get(1)) if err != nil { return xerrors.Errorf("Could not decode salt: %w", err) } @@ -184,7 +170,7 @@ var EvmGetContractAddress = &cli.Command{ return err } - contract, err := hex.DecodeString(string(contractHex)) + contract, err := ethtypes.DecodeHexStringTrimSpace(string(contractHex)) if err != nil { return xerrors.Errorf("Could not decode contract file: %w", err) } @@ -233,7 +219,7 @@ var EvmDeployCmd = &cli.Command{ return xerrors.Errorf("failed to read contract: %w", err) } if cctx.Bool("hex") { - contract, err = hex.DecodeString(string(contract)) + contract, err = ethtypes.DecodeHexStringTrimSpace(string(contract)) if err != nil { return xerrors.Errorf("failed to decode contract: %w", err) } @@ -355,7 +341,7 @@ var EvmInvokeCmd = &cli.Command{ } var calldata []byte - calldata, err = hex.DecodeString(cctx.Args().Get(1)) + calldata, err = ethtypes.DecodeHexStringTrimSpace(cctx.Args().Get(1)) if err != nil { return xerrors.Errorf("decoding hex input data: %w", err) } diff --git a/cli/send.go b/cli/send.go index 3e390584d..e18aa544e 100644 --- a/cli/send.go +++ b/cli/send.go @@ -117,6 +117,17 @@ var sendCmd = &cli.Command{ params.From = faddr } + if params.From.Protocol() == address.Delegated { + if !(params.To.Protocol() == address.ID || params.To.Protocol() == address.Delegated) { + api := srv.FullNodeAPI() + // Resolve id addr if possible. + params.To, err = api.StateLookupID(ctx, params.To, types.EmptyTSK) + if err != nil { + return xerrors.Errorf("f4 addresses can only send to other f4 or id addresses. could not find id address for %s", params.To.String()) + } + } + } + if cctx.IsSet("gas-premium") { gp, err := types.BigFromString(cctx.String("gas-premium")) if err != nil { diff --git a/cli/state.go b/cli/state.go index 9513098d3..3d629bb0b 100644 --- a/cli/state.go +++ b/cli/state.go @@ -776,7 +776,9 @@ var StateGetActorCmd = &cli.Command{ fmt.Printf("Nonce:\t\t%d\n", a.Nonce) fmt.Printf("Code:\t\t%s (%s)\n", a.Code, strtype) fmt.Printf("Head:\t\t%s\n", a.Head) - fmt.Printf("Delegated address:\t\t%s\n", a.Address) + if a.Address != nil { + fmt.Printf("Delegated address:\t\t%s\n", a.Address) + } return nil }, @@ -1352,7 +1354,7 @@ func ComputeStateHTMLTempl(w io.Writer, ts *types.TipSet, o *api.ComputeStateOut "GetMethod": getMethod, "ToFil": toFil, "JsonParams": JsonParams, - "JsonReturn": jsonReturn, + "JsonReturn": JsonReturn, "IsSlow": isSlow, "IsVerySlow": isVerySlow, "IntExit": func(i exitcode.ExitCode) int64 { return int64(i) }, @@ -1438,7 +1440,7 @@ func JsonParams(code cid.Cid, method abi.MethodNum, params []byte) (string, erro return string(b), err } -func jsonReturn(code cid.Cid, method abi.MethodNum, ret []byte) (string, error) { +func JsonReturn(code cid.Cid, method abi.MethodNum, ret []byte) (string, error) { methodMeta, found := filcns.NewActorRegistry().Methods[code][method] // TODO: use remote if !found { return "", fmt.Errorf("method %d not found on actor %s", method, code) @@ -1547,7 +1549,7 @@ func printReceiptReturn(ctx context.Context, api v0api.FullNode, m *types.Messag return err } - jret, err := jsonReturn(act.Code, m.Method, r.Return) + jret, err := JsonReturn(act.Code, m.Method, r.Return) if err != nil { return err } @@ -1687,7 +1689,7 @@ var StateCallCmd = &cli.Command{ return xerrors.Errorf("getting actor: %w", err) } - retStr, err := jsonReturn(act.Code, abi.MethodNum(method), ret.MsgRct.Return) + retStr, err := JsonReturn(act.Code, abi.MethodNum(method), ret.MsgRct.Return) if err != nil { return xerrors.Errorf("decoding return: %w", err) } diff --git a/cli/util/api.go b/cli/util/api.go index b35974c69..1d6928c3f 100644 --- a/cli/util/api.go +++ b/cli/util/api.go @@ -319,11 +319,33 @@ func GetFullNodeAPIV1Single(ctx *cli.Context) (v1api.FullNode, jsonrpc.ClientClo return v1API, closer, nil } -func GetFullNodeAPIV1(ctx *cli.Context) (v1api.FullNode, jsonrpc.ClientCloser, error) { +type GetFullNodeOptions struct { + ethSubHandler api.EthSubscriber +} + +type GetFullNodeOption func(*GetFullNodeOptions) + +func FullNodeWithEthSubscribtionHandler(sh api.EthSubscriber) GetFullNodeOption { + return func(opts *GetFullNodeOptions) { + opts.ethSubHandler = sh + } +} + +func GetFullNodeAPIV1(ctx *cli.Context, opts ...GetFullNodeOption) (v1api.FullNode, jsonrpc.ClientCloser, error) { if tn, ok := ctx.App.Metadata["testnode-full"]; ok { return tn.(v1api.FullNode), func() {}, nil } + var options GetFullNodeOptions + for _, opt := range opts { + opt(&options) + } + + var rpcOpts []jsonrpc.Option + if options.ethSubHandler != nil { + rpcOpts = append(rpcOpts, jsonrpc.WithClientHandler("Filecoin", options.ethSubHandler), jsonrpc.WithClientHandlerAlias("eth_subscription", "Filecoin.EthSubscription")) + } + heads, err := GetRawAPIMulti(ctx, repo.FullNode, "v1") if err != nil { return nil, nil, err @@ -337,7 +359,7 @@ func GetFullNodeAPIV1(ctx *cli.Context) (v1api.FullNode, jsonrpc.ClientCloser, e var closers []jsonrpc.ClientCloser for _, head := range heads { - v1api, closer, err := client.NewFullNodeRPCV1(ctx.Context, head.addr, head.header) + v1api, closer, err := client.NewFullNodeRPCV1(ctx.Context, head.addr, head.header, rpcOpts...) if err != nil { log.Warnf("Not able to establish connection to node with addr: ", head.addr) continue diff --git a/cmd/lotus-gateway/main.go b/cmd/lotus-gateway/main.go index 89b2152dd..2023551ef 100644 --- a/cmd/lotus-gateway/main.go +++ b/cmd/lotus-gateway/main.go @@ -162,7 +162,9 @@ var runCmd = &cli.Command{ log.Fatalf("Cannot register the view: %v", err) } - api, closer, err := lcli.GetFullNodeAPIV1(cctx) + subHnd := gateway.NewEthSubHandler() + + api, closer, err := lcli.GetFullNodeAPIV1(cctx, cliutil.FullNodeWithEthSubscribtionHandler(subHnd)) if err != nil { return err } @@ -195,7 +197,7 @@ var runCmd = &cli.Command{ return xerrors.Errorf("failed to convert endpoint address to multiaddr: %w", err) } - gwapi := gateway.NewNode(api, lookbackCap, waitLookback, rateLimit, rateLimitTimeout) + gwapi := gateway.NewNode(api, subHnd, lookbackCap, waitLookback, rateLimit, rateLimitTimeout) h, err := gateway.Handler(gwapi, api, perConnRateLimit, connPerMinute, serverOptions...) if err != nil { return xerrors.Errorf("failed to set up gateway HTTP handler") diff --git a/cmd/lotus-shed/balances.go b/cmd/lotus-shed/balances.go index 9ce4faf72..c647f3b8e 100644 --- a/cmd/lotus-shed/balances.go +++ b/cmd/lotus-shed/balances.go @@ -454,8 +454,9 @@ var chainBalanceStateCmd = &cli.Command{ Description: "Produces a csv file of all account balances from a given stateroot", Flags: []cli.Flag{ &cli.StringFlag{ - Name: "repo", - Value: "~/.lotus", + Name: "repo", + Value: "~/.lotus", + EnvVars: []string{"LOTUS_PATH"}, }, &cli.BoolFlag{ Name: "miner-info", @@ -677,8 +678,9 @@ var chainPledgeCmd = &cli.Command{ Description: "Calculate sector pledge numbers", Flags: []cli.Flag{ &cli.StringFlag{ - Name: "repo", - Value: "~/.lotus", + Name: "repo", + Value: "~/.lotus", + EnvVars: []string{"LOTUS_PATH"}, }, }, ArgsUsage: "[stateroot epoch]", diff --git a/cmd/lotus-shed/datastore.go b/cmd/lotus-shed/datastore.go index 5614e34f6..d6b932954 100644 --- a/cmd/lotus-shed/datastore.go +++ b/cmd/lotus-shed/datastore.go @@ -41,6 +41,11 @@ var datastoreListCmd = &cli.Command{ Name: "list", Description: "list datastore keys", Flags: []cli.Flag{ + &cli.StringFlag{ + Name: "repo", + Value: "~/.lotus", + EnvVars: []string{"LOTUS_PATH"}, + }, &cli.StringFlag{ Name: "repo-type", Usage: "node type (FullNode, StorageMiner, Worker, Wallet)", @@ -110,6 +115,11 @@ var datastoreGetCmd = &cli.Command{ Name: "get", Description: "list datastore keys", Flags: []cli.Flag{ + &cli.StringFlag{ + Name: "repo", + Value: "~/.lotus", + EnvVars: []string{"LOTUS_PATH"}, + }, &cli.StringFlag{ Name: "repo-type", Usage: "node type (FullNode, StorageMiner, Worker, Wallet)", @@ -123,7 +133,7 @@ var datastoreGetCmd = &cli.Command{ }, ArgsUsage: "[namespace key]", Action: func(cctx *cli.Context) error { - logging.SetLogLevel("badger", "ERROR") // nolint:errcheck + _ = logging.SetLogLevel("badger", "ERROR") r, err := repo.NewFS(cctx.String("repo")) if err != nil { diff --git a/cmd/lotus-shed/deal-label.go b/cmd/lotus-shed/deal-label.go index 417d13701..2baa751a9 100644 --- a/cmd/lotus-shed/deal-label.go +++ b/cmd/lotus-shed/deal-label.go @@ -24,8 +24,9 @@ var dealLabelCmd = &cli.Command{ Usage: "Scrape state to report on how many deals have non UTF-8 labels", Flags: []cli.Flag{ &cli.StringFlag{ - Name: "repo", - Value: "~/.lotus", + Name: "repo", + Value: "~/.lotus", + EnvVars: []string{"LOTUS_PATH"}, }, }, Action: func(cctx *cli.Context) error { diff --git a/cmd/lotus-shed/diff.go b/cmd/lotus-shed/diff.go index 981dc850c..e29d9ca6d 100644 --- a/cmd/lotus-shed/diff.go +++ b/cmd/lotus-shed/diff.go @@ -33,8 +33,9 @@ var diffMinerStates = &cli.Command{ ArgsUsage: " ", Flags: []cli.Flag{ &cli.StringFlag{ - Name: "repo", - Value: "~/.lotus", + Name: "repo", + Value: "~/.lotus", + EnvVars: []string{"LOTUS_PATH"}, }, }, Action: func(cctx *cli.Context) error { diff --git a/cmd/lotus-shed/eth.go b/cmd/lotus-shed/eth.go new file mode 100644 index 000000000..1ebe2fb59 --- /dev/null +++ b/cmd/lotus-shed/eth.go @@ -0,0 +1,72 @@ +package main + +import ( + "fmt" + "reflect" + + "github.com/urfave/cli/v2" + + "github.com/filecoin-project/go-state-types/abi" + + "github.com/filecoin-project/lotus/chain/types" + lcli "github.com/filecoin-project/lotus/cli" +) + +var ethCmd = &cli.Command{ + Name: "eth", + Description: "Ethereum compatibility related commands", + Flags: []cli.Flag{ + &cli.StringFlag{ + Name: "repo", + Value: "~/.lotus", + }, + }, + Subcommands: []*cli.Command{ + checkTipsetsCmd, + }, +} + +var checkTipsetsCmd = &cli.Command{ + Name: "check-tipsets", + Description: "Check that eth_getBlockByNumber and eth_getBlockByHash consistently return tipsets", + Action: func(cctx *cli.Context) error { + api, closer, err := lcli.GetFullNodeAPIV1(cctx) + if err != nil { + return err + } + + defer closer() + ctx := lcli.ReqContext(cctx) + + head, err := api.ChainHead(ctx) + if err != nil { + return err + } + + height := head.Height() + fmt.Println("Current height:", height) + for i := int64(height); i > 0; i-- { + if _, err := api.ChainGetTipSetByHeight(ctx, abi.ChainEpoch(i), types.EmptyTSK); err != nil { + fmt.Printf("[FAIL] failed to get tipset @%d from Lotus: %s\n", i, err) + continue + } + hex := fmt.Sprintf("0x%x", i) + ethBlockA, err := api.EthGetBlockByNumber(ctx, hex, false) + if err != nil { + fmt.Printf("[FAIL] failed to get tipset @%d via eth_getBlockByNumber: %s\n", i, err) + continue + } + ethBlockB, err := api.EthGetBlockByHash(ctx, ethBlockA.Hash, false) + if err != nil { + fmt.Printf("[FAIL] failed to get tipset @%d via eth_getBlockByHash: %s\n", i, err) + continue + } + if equal := reflect.DeepEqual(ethBlockA, ethBlockB); equal { + fmt.Printf("[OK] blocks received via eth_getBlockByNumber and eth_getBlockByHash for tipset @%d are identical\n", i) + } else { + fmt.Printf("[FAIL] blocks received via eth_getBlockByNumber and eth_getBlockByHash for tipset @%d are NOT identical\n", i) + } + } + return nil + }, +} diff --git a/cmd/lotus-shed/export-car.go b/cmd/lotus-shed/export-car.go index 5cb4737ea..e32dbb2cf 100644 --- a/cmd/lotus-shed/export-car.go +++ b/cmd/lotus-shed/export-car.go @@ -35,8 +35,9 @@ var exportCarCmd = &cli.Command{ Description: "Export a car from repo", Flags: []cli.Flag{ &cli.StringFlag{ - Name: "repo", - Value: "~/.lotus", + Name: "repo", + Value: "~/.lotus", + EnvVars: []string{"LOTUS_PATH"}, }, }, ArgsUsage: "[outfile] [root cid]", diff --git a/cmd/lotus-shed/export.go b/cmd/lotus-shed/export.go index 459de3383..ab6d88698 100644 --- a/cmd/lotus-shed/export.go +++ b/cmd/lotus-shed/export.go @@ -42,8 +42,9 @@ var exportChainCmd = &cli.Command{ Description: "Export chain from repo (requires node to be offline)", Flags: []cli.Flag{ &cli.StringFlag{ - Name: "repo", - Value: "~/.lotus", + Name: "repo", + Value: "~/.lotus", + EnvVars: []string{"LOTUS_PATH"}, }, &cli.StringFlag{ Name: "tipset", @@ -146,8 +147,9 @@ var exportRawCmd = &cli.Command{ Description: "Export raw blocks from repo (requires node to be offline)", Flags: []cli.Flag{ &cli.StringFlag{ - Name: "repo", - Value: "~/.lotus", + Name: "repo", + Value: "~/.lotus", + EnvVars: []string{"LOTUS_PATH"}, }, &cli.StringFlag{ Name: "car-size", diff --git a/cmd/lotus-shed/fip-0036.go b/cmd/lotus-shed/fip-0036.go index 485302b9b..1929eb4dd 100644 --- a/cmd/lotus-shed/fip-0036.go +++ b/cmd/lotus-shed/fip-0036.go @@ -58,12 +58,6 @@ var fip36PollCmd = &cli.Command{ Name: "fip36poll", Usage: "Process the FIP0036 FilPoll result", ArgsUsage: "[state root, votes]", - Flags: []cli.Flag{ - &cli.StringFlag{ - Name: "repo", - Value: "~/.lotus", - }, - }, Subcommands: []*cli.Command{ finalResultCmd, }, @@ -75,8 +69,9 @@ var finalResultCmd = &cli.Command{ ArgsUsage: "[state root] [height] [votes json]", Flags: []cli.Flag{ &cli.StringFlag{ - Name: "repo", - Value: "~/.lotus", + Name: "repo", + Value: "~/.lotus", + EnvVars: []string{"LOTUS_PATH"}, }, }, diff --git a/cmd/lotus-shed/gas-estimation.go b/cmd/lotus-shed/gas-estimation.go index cf56ea03d..669c1c345 100644 --- a/cmd/lotus-shed/gas-estimation.go +++ b/cmd/lotus-shed/gas-estimation.go @@ -42,8 +42,9 @@ var gasTraceCmd = &cli.Command{ ArgsUsage: "[migratedStateRootCid networkVersion messageCid]", Flags: []cli.Flag{ &cli.StringFlag{ - Name: "repo", - Value: "~/.lotus", + Name: "repo", + Value: "~/.lotus", + EnvVars: []string{"LOTUS_PATH"}, }, }, Action: func(cctx *cli.Context) error { @@ -146,8 +147,9 @@ var replayOfflineCmd = &cli.Command{ ArgsUsage: "[messageCid]", Flags: []cli.Flag{ &cli.StringFlag{ - Name: "repo", - Value: "~/.lotus", + Name: "repo", + Value: "~/.lotus", + EnvVars: []string{"LOTUS_PATH"}, }, &cli.Int64Flag{ Name: "lookback-limit", diff --git a/cmd/lotus-shed/import-car.go b/cmd/lotus-shed/import-car.go index 973e7b31b..6bba1d980 100644 --- a/cmd/lotus-shed/import-car.go +++ b/cmd/lotus-shed/import-car.go @@ -19,6 +19,13 @@ import ( var importCarCmd = &cli.Command{ Name: "import-car", Description: "Import a car file into node chain blockstore", + Flags: []cli.Flag{ + &cli.StringFlag{ + Name: "repo", + Value: "~/.lotus", + EnvVars: []string{"LOTUS_PATH"}, + }, + }, Action: func(cctx *cli.Context) error { r, err := repo.NewFS(cctx.String("repo")) if err != nil { @@ -96,6 +103,13 @@ var importCarCmd = &cli.Command{ var importObjectCmd = &cli.Command{ Name: "import-obj", Usage: "import a raw ipld object into your datastore", + Flags: []cli.Flag{ + &cli.StringFlag{ + Name: "repo", + Value: "~/.lotus", + EnvVars: []string{"LOTUS_PATH"}, + }, + }, Action: func(cctx *cli.Context) error { r, err := repo.NewFS(cctx.String("repo")) if err != nil { diff --git a/cmd/lotus-shed/invariants.go b/cmd/lotus-shed/invariants.go index e48f301c4..953674ed0 100644 --- a/cmd/lotus-shed/invariants.go +++ b/cmd/lotus-shed/invariants.go @@ -35,8 +35,9 @@ var invariantsCmd = &cli.Command{ ArgsUsage: "[StateRootCid, height]", Flags: []cli.Flag{ &cli.StringFlag{ - Name: "repo", - Value: "~/.lotus", + Name: "repo", + Value: "~/.lotus", + EnvVars: []string{"LOTUS_PATH"}, }, }, Action: func(cctx *cli.Context) error { diff --git a/cmd/lotus-shed/keyinfo.go b/cmd/lotus-shed/keyinfo.go index 38f5ee6fe..1c322f7d6 100644 --- a/cmd/lotus-shed/keyinfo.go +++ b/cmd/lotus-shed/keyinfo.go @@ -146,9 +146,14 @@ var keyinfoImportCmd = &cli.Command{ Examples env LOTUS_PATH=/var/lib/lotus lotus-shed keyinfo import libp2p-host.keyinfo`, + Flags: []cli.Flag{ + &cli.StringFlag{ + Name: "repo", + Value: "~/.lotus", + EnvVars: []string{"LOTUS_PATH"}, + }, + }, Action: func(cctx *cli.Context) error { - flagRepo := cctx.String("repo") - var input io.Reader if cctx.NArg() == 0 { input = os.Stdin @@ -177,7 +182,7 @@ var keyinfoImportCmd = &cli.Command{ return err } - fsrepo, err := repo.NewFS(flagRepo) + fsrepo, err := repo.NewFS(cctx.String("repo")) if err != nil { return err } diff --git a/cmd/lotus-shed/main.go b/cmd/lotus-shed/main.go index 6f84739fa..c0d0043f1 100644 --- a/cmd/lotus-shed/main.go +++ b/cmd/lotus-shed/main.go @@ -1,7 +1,6 @@ package main import ( - "fmt" "os" logging "github.com/ipfs/go-log/v2" @@ -49,6 +48,7 @@ func main() { minerCmd, mpoolStatsCmd, exportChainCmd, + ethCmd, exportCarCmd, consensusCmd, syncCmd, @@ -88,19 +88,6 @@ func main() { Version: build.UserVersion(), Commands: local, Flags: []cli.Flag{ - &cli.StringFlag{ - Name: "repo", - EnvVars: []string{"LOTUS_PATH"}, - Hidden: true, - Value: "~/.lotus", // TODO: Consider XDG_DATA_HOME - }, - &cli.StringFlag{ - Name: "miner-repo", - Aliases: []string{"storagerepo"}, - EnvVars: []string{"LOTUS_MINER_PATH", "LOTUS_STORAGE_PATH"}, - Value: "~/.lotusminer", // TODO: Consider XDG_DATA_HOME - Usage: fmt.Sprintf("Specify miner repo path. flag storagerepo and env LOTUS_STORAGE_PATH are DEPRECATION, will REMOVE SOON"), - }, &cli.StringFlag{ Name: "log-level", Value: "info", diff --git a/cmd/lotus-shed/market.go b/cmd/lotus-shed/market.go index 0c5e7c81d..6d86c90b9 100644 --- a/cmd/lotus-shed/market.go +++ b/cmd/lotus-shed/market.go @@ -124,8 +124,9 @@ var marketExportDatastoreCmd = &cli.Command{ Description: "export markets datastore key/values to a file", Flags: []cli.Flag{ &cli.StringFlag{ - Name: "repo", - Usage: "path to the repo", + Name: "repo", + Value: "~/.lotus", + EnvVars: []string{"LOTUS_PATH"}, }, &cli.StringFlag{ Name: "backup-dir", @@ -241,8 +242,9 @@ var marketImportDatastoreCmd = &cli.Command{ Description: "import markets datastore key/values from a backup file", Flags: []cli.Flag{ &cli.StringFlag{ - Name: "repo", - Usage: "path to the repo", + Name: "repo", + Value: "~/.lotus", + EnvVars: []string{"LOTUS_PATH"}, }, &cli.StringFlag{ Name: "backup-path", diff --git a/cmd/lotus-shed/migrations.go b/cmd/lotus-shed/migrations.go index a7e0ee34f..e0336283a 100644 --- a/cmd/lotus-shed/migrations.go +++ b/cmd/lotus-shed/migrations.go @@ -54,8 +54,9 @@ var migrationsCmd = &cli.Command{ ArgsUsage: "[new network version, block to look back from]", Flags: []cli.Flag{ &cli.StringFlag{ - Name: "repo", - Value: "~/.lotus", + Name: "repo", + Value: "~/.lotus", + EnvVars: []string{"LOTUS_PATH"}, }, &cli.BoolFlag{ Name: "skip-pre-migration", diff --git a/cmd/lotus-shed/miner-peerid.go b/cmd/lotus-shed/miner-peerid.go index e43063797..fdf8dae8d 100644 --- a/cmd/lotus-shed/miner-peerid.go +++ b/cmd/lotus-shed/miner-peerid.go @@ -26,10 +26,12 @@ import ( var minerPeeridCmd = &cli.Command{ Name: "miner-peerid", - Usage: "Scrape state to find a miner based on peerid", Flags: []cli.Flag{ + Usage: "Scrape state to find a miner based on peerid", + Flags: []cli.Flag{ &cli.StringFlag{ - Name: "repo", - Value: "~/.lotus", + Name: "repo", + Value: "~/.lotus", + EnvVars: []string{"LOTUS_PATH"}, }, }, Action: func(cctx *cli.Context) error { diff --git a/cmd/lotus-shed/miner-types.go b/cmd/lotus-shed/miner-types.go index 822d037aa..15e5db265 100644 --- a/cmd/lotus-shed/miner-types.go +++ b/cmd/lotus-shed/miner-types.go @@ -28,10 +28,12 @@ import ( var minerTypesCmd = &cli.Command{ Name: "miner-types", - Usage: "Scrape state to report on how many miners of each WindowPoStProofType exist", Flags: []cli.Flag{ + Usage: "Scrape state to report on how many miners of each WindowPoStProofType exist", + Flags: []cli.Flag{ &cli.StringFlag{ - Name: "repo", - Value: "~/.lotus", + Name: "repo", + Value: "~/.lotus", + EnvVars: []string{"LOTUS_PATH"}, }, }, Action: func(cctx *cli.Context) error { diff --git a/cmd/lotus-shed/msig.go b/cmd/lotus-shed/msig.go index ccc932c93..96ba91219 100644 --- a/cmd/lotus-shed/msig.go +++ b/cmd/lotus-shed/msig.go @@ -43,8 +43,9 @@ var multisigGetAllCmd = &cli.Command{ ArgsUsage: "[state root]", Flags: []cli.Flag{ &cli.StringFlag{ - Name: "repo", - Value: "~/.lotus", + Name: "repo", + Value: "~/.lotus", + EnvVars: []string{"LOTUS_PATH"}, }, }, Action: func(cctx *cli.Context) error { diff --git a/cmd/lotus-shed/nonce-fix.go b/cmd/lotus-shed/nonce-fix.go index d69c8a48d..d68f22e0b 100644 --- a/cmd/lotus-shed/nonce-fix.go +++ b/cmd/lotus-shed/nonce-fix.go @@ -17,12 +17,6 @@ import ( var noncefix = &cli.Command{ Name: "noncefix", Flags: []cli.Flag{ - &cli.StringFlag{ - Name: "repo", - EnvVars: []string{"LOTUS_PATH"}, - Hidden: true, - Value: "~/.lotus", // TODO: Consider XDG_DATA_HOME - }, &cli.Uint64Flag{ Name: "start", }, diff --git a/cmd/lotus-shed/pruning.go b/cmd/lotus-shed/pruning.go index 275f3bc0a..1b6553057 100644 --- a/cmd/lotus-shed/pruning.go +++ b/cmd/lotus-shed/pruning.go @@ -86,8 +86,9 @@ var stateTreePruneCmd = &cli.Command{ Description: "Deletes old state root data from local chainstore", Flags: []cli.Flag{ &cli.StringFlag{ - Name: "repo", - Value: "~/.lotus", + Name: "repo", + Value: "~/.lotus", + EnvVars: []string{"LOTUS_PATH"}, }, &cli.Int64Flag{ Name: "keep-from-lookback", diff --git a/cmd/lotus-shed/splitstore.go b/cmd/lotus-shed/splitstore.go index e8c45a0c5..348f2e36d 100644 --- a/cmd/lotus-shed/splitstore.go +++ b/cmd/lotus-shed/splitstore.go @@ -39,8 +39,9 @@ var splitstoreRollbackCmd = &cli.Command{ Description: "rollbacks a splitstore installation", Flags: []cli.Flag{ &cli.StringFlag{ - Name: "repo", - Value: "~/.lotus", + Name: "repo", + Value: "~/.lotus", + EnvVars: []string{"LOTUS_PATH"}, }, &cli.BoolFlag{ Name: "gc-coldstore", @@ -129,8 +130,9 @@ var splitstoreClearCmd = &cli.Command{ Description: "clears a splitstore installation for restart from snapshot", Flags: []cli.Flag{ &cli.StringFlag{ - Name: "repo", - Value: "~/.lotus", + Name: "repo", + Value: "~/.lotus", + EnvVars: []string{"LOTUS_PATH"}, }, &cli.BoolFlag{ Name: "keys-only", diff --git a/cmd/lotus-shed/terminations.go b/cmd/lotus-shed/terminations.go index c5f35995a..c9e3d26bb 100644 --- a/cmd/lotus-shed/terminations.go +++ b/cmd/lotus-shed/terminations.go @@ -33,8 +33,9 @@ var terminationsCmd = &cli.Command{ ArgsUsage: "[block to look back from] [lookback period (epochs)]", Flags: []cli.Flag{ &cli.StringFlag{ - Name: "repo", - Value: "~/.lotus", + Name: "repo", + Value: "~/.lotus", + EnvVars: []string{"LOTUS_PATH"}, }, }, Action: func(cctx *cli.Context) error { diff --git a/documentation/en/api-v1-unstable-methods.md b/documentation/en/api-v1-unstable-methods.md index 2c853754b..b7050febd 100644 --- a/documentation/en/api-v1-unstable-methods.md +++ b/documentation/en/api-v1-unstable-methods.md @@ -291,6 +291,8 @@ * [WalletSignMessage](#WalletSignMessage) * [WalletValidateAddress](#WalletValidateAddress) * [WalletVerify](#WalletVerify) +* [Web3](#Web3) + * [Web3ClientVersion](#Web3ClientVersion) ## @@ -642,6 +644,7 @@ Response: { "Flags": 7, "Key": "string value", + "Codec": 42, "Value": "Ynl0ZSBhcnJheQ==" } ] @@ -2340,7 +2343,7 @@ Inputs: Response: ```json { - "oldestBlock": 42, + "oldestBlock": "0x5", "baseFeePerGas": [ "0x0" ], @@ -2405,7 +2408,7 @@ Response: "gasLimit": "0x5", "gasUsed": "0x5", "timestamp": "0x5", - "extraData": "Ynl0ZSBhcnJheQ==", + "extraData": "0x07", "mixHash": "0x37690cfec6c1bf4c3b9288c7a5d783e98731e90b0a4c177c2a374c7a9427355e", "nonce": "0x0707070707070707", "baseFeePerGas": "0x0", @@ -2449,7 +2452,7 @@ Response: "gasLimit": "0x5", "gasUsed": "0x5", "timestamp": "0x5", - "extraData": "Ynl0ZSBhcnJheQ==", + "extraData": "0x07", "mixHash": "0x37690cfec6c1bf4c3b9288c7a5d783e98731e90b0a4c177c2a374c7a9427355e", "nonce": "0x0707070707070707", "baseFeePerGas": "0x0", @@ -2518,40 +2521,7 @@ Perms: write Inputs: ```json [ - [ - 55, - 105, - 12, - 254, - 198, - 193, - 191, - 76, - 59, - 146, - 136, - 199, - 165, - 215, - 131, - 233, - 135, - 49, - 233, - 11, - 10, - 76, - 23, - 124, - 42, - 55, - 76, - 122, - 148, - 39, - 53, - 94 - ] + "0x37690cfec6c1bf4c3b9288c7a5d783e98731e90b0a4c177c2a374c7a9427355e" ] ``` @@ -2572,40 +2542,7 @@ Perms: write Inputs: ```json [ - [ - 55, - 105, - 12, - 254, - 198, - 193, - 191, - 76, - 59, - 146, - 136, - 199, - 165, - 215, - 131, - 233, - 135, - 49, - 233, - 11, - 10, - 76, - 23, - 124, - 42, - 55, - 76, - 122, - 148, - 39, - 53, - 94 - ] + "0x37690cfec6c1bf4c3b9288c7a5d783e98731e90b0a4c177c2a374c7a9427355e" ] ``` @@ -2707,7 +2644,10 @@ Response: "gas": "0x5", "maxFeePerGas": "0x0", "maxPriorityFeePerGas": "0x0", - "v": "0x0", + "accessList": [ + "0x37690cfec6c1bf4c3b9288c7a5d783e98731e90b0a4c177c2a374c7a9427355e" + ], + "yParity": "0x0", "r": "0x0", "s": "0x0" } @@ -2743,7 +2683,10 @@ Response: "gas": "0x5", "maxFeePerGas": "0x0", "maxPriorityFeePerGas": "0x0", - "v": "0x0", + "accessList": [ + "0x37690cfec6c1bf4c3b9288c7a5d783e98731e90b0a4c177c2a374c7a9427355e" + ], + "yParity": "0x0", "r": "0x0", "s": "0x0" } @@ -2778,7 +2721,10 @@ Response: "gas": "0x5", "maxFeePerGas": "0x0", "maxPriorityFeePerGas": "0x0", - "v": "0x0", + "accessList": [ + "0x37690cfec6c1bf4c3b9288c7a5d783e98731e90b0a4c177c2a374c7a9427355e" + ], + "yParity": "0x0", "r": "0x0", "s": "0x0" } @@ -2879,43 +2825,7 @@ Perms: write Inputs: `null` -Response: -```json -[ - 55, - 105, - 12, - 254, - 198, - 193, - 191, - 76, - 59, - 146, - 136, - 199, - 165, - 215, - 131, - 233, - 135, - 49, - 233, - 11, - 10, - 76, - 23, - 124, - 42, - 55, - 76, - 122, - 148, - 39, - 53, - 94 -] -``` +Response: `"0x37690cfec6c1bf4c3b9288c7a5d783e98731e90b0a4c177c2a374c7a9427355e"` ### EthNewFilter Installs a persistent filter based on given filter spec. @@ -2936,43 +2846,7 @@ Inputs: ] ``` -Response: -```json -[ - 55, - 105, - 12, - 254, - 198, - 193, - 191, - 76, - 59, - 146, - 136, - 199, - 165, - 215, - 131, - 233, - 135, - 49, - 233, - 11, - 10, - 76, - 23, - 124, - 42, - 55, - 76, - 122, - 148, - 39, - 53, - 94 -] -``` +Response: `"0x37690cfec6c1bf4c3b9288c7a5d783e98731e90b0a4c177c2a374c7a9427355e"` ### EthNewPendingTransactionFilter Installs a persistent filter to notify when new messages arrive in the message pool. @@ -2982,43 +2856,7 @@ Perms: write Inputs: `null` -Response: -```json -[ - 55, - 105, - 12, - 254, - 198, - 193, - 191, - 76, - 59, - 146, - 136, - 199, - 165, - 215, - 131, - 233, - 135, - 49, - 233, - 11, - 10, - 76, - 23, - 124, - 42, - 55, - 76, - 122, - 148, - 39, - 53, - 94 -] -``` +Response: `"0x37690cfec6c1bf4c3b9288c7a5d783e98731e90b0a4c177c2a374c7a9427355e"` ### EthProtocolVersion @@ -3058,57 +2896,11 @@ Perms: write Inputs: ```json [ - "string value", - { - "topics": [ - [ - "0x37690cfec6c1bf4c3b9288c7a5d783e98731e90b0a4c177c2a374c7a9427355e" - ] - ] - } + "Bw==" ] ``` -Response: -```json -{ - "subscription": [ - 55, - 105, - 12, - 254, - 198, - 193, - 191, - 76, - 59, - 146, - 136, - 199, - 165, - 215, - 131, - 233, - 135, - 49, - 233, - 11, - 10, - 76, - 23, - 124, - 42, - 55, - 76, - 122, - 148, - 39, - 53, - 94 - ], - "result": {} -} -``` +Response: `"0x37690cfec6c1bf4c3b9288c7a5d783e98731e90b0a4c177c2a374c7a9427355e"` ### EthUninstallFilter Uninstalls a filter with given id. @@ -3119,40 +2911,7 @@ Perms: write Inputs: ```json [ - [ - 55, - 105, - 12, - 254, - 198, - 193, - 191, - 76, - 59, - 146, - 136, - 199, - 165, - 215, - 131, - 233, - 135, - 49, - 233, - 11, - 10, - 76, - 23, - 124, - 42, - 55, - 76, - 122, - 148, - 39, - 53, - 94 - ] + "0x37690cfec6c1bf4c3b9288c7a5d783e98731e90b0a4c177c2a374c7a9427355e" ] ``` @@ -3167,40 +2926,7 @@ Perms: write Inputs: ```json [ - [ - 55, - 105, - 12, - 254, - 198, - 193, - 191, - 76, - 59, - 146, - 136, - 199, - 165, - 215, - 131, - 233, - 135, - 49, - 233, - 11, - 10, - 76, - 23, - 124, - 42, - 55, - 76, - 122, - 148, - 39, - 53, - 94 - ] + "0x37690cfec6c1bf4c3b9288c7a5d783e98731e90b0a4c177c2a374c7a9427355e" ] ``` @@ -9207,3 +8933,16 @@ Inputs: Response: `true` +## Web3 + + +### Web3ClientVersion +Returns the client version + + +Perms: read + +Inputs: `null` + +Response: `"string value"` + diff --git a/documentation/en/cli-lotus.md b/documentation/en/cli-lotus.md index 5e0c7a305..04d6611bf 100644 --- a/documentation/en/cli-lotus.md +++ b/documentation/en/cli-lotus.md @@ -2596,11 +2596,10 @@ NAME: lotus evm stat - Print eth/filecoin addrs and code cid USAGE: - lotus evm stat [command options] [arguments...] + lotus evm stat [command options] address OPTIONS: - --ethAddr value Ethereum address - --filAddr value Filecoin address + --help, -h show help (default: false) ``` diff --git a/extern/filecoin-ffi b/extern/filecoin-ffi index 86eac2161..9e4fe7547 160000 --- a/extern/filecoin-ffi +++ b/extern/filecoin-ffi @@ -1 +1 @@ -Subproject commit 86eac2161f442945bffee3fbfe7d094c20b48dd3 +Subproject commit 9e4fe75471f635a4ba91f17ee76f75200eb91de8 diff --git a/extern/test-vectors b/extern/test-vectors index d9a75a787..28b0c45ea 160000 --- a/extern/test-vectors +++ b/extern/test-vectors @@ -1 +1 @@ -Subproject commit d9a75a7873aee0db28b87e3970d2ea16a2f37c6a +Subproject commit 28b0c45eab4c302864af0aeaaff813625cfafe97 diff --git a/gateway/eth_sub.go b/gateway/eth_sub.go new file mode 100644 index 000000000..76d913983 --- /dev/null +++ b/gateway/eth_sub.go @@ -0,0 +1,71 @@ +package gateway + +import ( + "context" + "sync" + + "github.com/filecoin-project/go-jsonrpc" + + "github.com/filecoin-project/lotus/api" + "github.com/filecoin-project/lotus/chain/types/ethtypes" +) + +type EthSubHandler struct { + queued map[ethtypes.EthSubscriptionID][]ethtypes.EthSubscriptionResponse + sinks map[ethtypes.EthSubscriptionID]func(context.Context, *ethtypes.EthSubscriptionResponse) error + + lk sync.Mutex +} + +func NewEthSubHandler() *EthSubHandler { + return &EthSubHandler{ + queued: make(map[ethtypes.EthSubscriptionID][]ethtypes.EthSubscriptionResponse), + sinks: make(map[ethtypes.EthSubscriptionID]func(context.Context, *ethtypes.EthSubscriptionResponse) error), + } +} + +func (e *EthSubHandler) AddSub(ctx context.Context, id ethtypes.EthSubscriptionID, sink func(context.Context, *ethtypes.EthSubscriptionResponse) error) error { + e.lk.Lock() + defer e.lk.Unlock() + + for _, p := range e.queued[id] { + p := p // copy + if err := sink(ctx, &p); err != nil { + return err + } + } + delete(e.queued, id) + e.sinks[id] = sink + return nil +} + +func (e *EthSubHandler) RemoveSub(id ethtypes.EthSubscriptionID) { + e.lk.Lock() + defer e.lk.Unlock() + + delete(e.sinks, id) + delete(e.queued, id) +} + +func (e *EthSubHandler) EthSubscription(ctx context.Context, r jsonrpc.RawParams) error { + p, err := jsonrpc.DecodeParams[ethtypes.EthSubscriptionResponse](r) + if err != nil { + return err + } + + e.lk.Lock() + + sink := e.sinks[p.SubscriptionID] + + if sink == nil { + e.queued[p.SubscriptionID] = append(e.queued[p.SubscriptionID], p) + e.lk.Unlock() + return nil + } + + e.lk.Unlock() + + return sink(ctx, &p) // todo track errors and auto-unsubscribe on rpc conn close? +} + +var _ api.EthSubscriber = (*EthSubHandler)(nil) diff --git a/gateway/handler.go b/gateway/handler.go index e9bee6d52..54ab2467f 100644 --- a/gateway/handler.go +++ b/gateway/handler.go @@ -27,14 +27,14 @@ const perConnLimiterKey perConnLimiterKeyType = "limiter" type filterTrackerKeyType string -const filterTrackerKey filterTrackerKeyType = "filterTracker" +const statefulCallTrackerKey filterTrackerKeyType = "statefulCallTracker" // Handler returns a gateway http.Handler, to be mounted as-is on the server. func Handler(gwapi lapi.Gateway, api lapi.FullNode, rateLimit int64, connPerMinute int64, opts ...jsonrpc.ServerOption) (http.Handler, error) { m := mux.NewRouter() serveRpc := func(path string, hnd interface{}) { - rpcServer := jsonrpc.NewServer(append(opts, jsonrpc.WithServerErrors(lapi.RPCErrors))...) + rpcServer := jsonrpc.NewServer(append(opts, jsonrpc.WithReverseClient[lapi.EthSubscriberMethods]("Filecoin"), jsonrpc.WithServerErrors(lapi.RPCErrors))...) rpcServer.Register("Filecoin", hnd) rpcServer.AliasMethod("rpc.discover", "Filecoin.Discover") @@ -90,7 +90,7 @@ func (h RateLimiterHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { r = r.WithContext(context.WithValue(r.Context(), perConnLimiterKey, h.limiter)) // also add a filter tracker to the context - r = r.WithContext(context.WithValue(r.Context(), filterTrackerKey, newFilterTracker())) + r = r.WithContext(context.WithValue(r.Context(), statefulCallTrackerKey, newStatefulCallTracker())) h.handler.ServeHTTP(w, r) } diff --git a/gateway/node.go b/gateway/node.go index f18189ae2..c41f0ceb0 100644 --- a/gateway/node.go +++ b/gateway/node.go @@ -12,6 +12,7 @@ import ( "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-bitfield" + "github.com/filecoin-project/go-jsonrpc" "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/dline" "github.com/filecoin-project/go-state-types/network" @@ -93,6 +94,8 @@ type TargetAPI interface { EthGetBlockByHash(ctx context.Context, blkHash ethtypes.EthHash, fullTxInfo bool) (ethtypes.EthBlock, error) EthGetBlockByNumber(ctx context.Context, blkNum string, fullTxInfo bool) (ethtypes.EthBlock, error) EthGetTransactionByHash(ctx context.Context, txHash *ethtypes.EthHash) (*ethtypes.EthTx, error) + EthGetTransactionHashByCid(ctx context.Context, cid cid.Cid) (*ethtypes.EthHash, error) + EthGetMessageCidByTransactionHash(ctx context.Context, txHash *ethtypes.EthHash) (*cid.Cid, error) EthGetTransactionCount(ctx context.Context, sender ethtypes.EthAddress, blkOpt string) (ethtypes.EthUint64, error) EthGetTransactionReceipt(ctx context.Context, txHash ethtypes.EthHash) (*api.EthTxReceipt, error) EthGetTransactionByBlockHashAndIndex(ctx context.Context, blkHash ethtypes.EthHash, txIndex ethtypes.EthUint64) (ethtypes.EthTx, error) @@ -117,14 +120,16 @@ type TargetAPI interface { EthNewBlockFilter(ctx context.Context) (ethtypes.EthFilterID, error) EthNewPendingTransactionFilter(ctx context.Context) (ethtypes.EthFilterID, error) EthUninstallFilter(ctx context.Context, id ethtypes.EthFilterID) (bool, error) - EthSubscribe(ctx context.Context, eventType string, params *ethtypes.EthSubscriptionParams) (<-chan ethtypes.EthSubscriptionResponse, error) + EthSubscribe(ctx context.Context, params jsonrpc.RawParams) (ethtypes.EthSubscriptionID, error) EthUnsubscribe(ctx context.Context, id ethtypes.EthSubscriptionID) (bool, error) + Web3ClientVersion(ctx context.Context) (string, error) } var _ TargetAPI = *new(api.FullNode) // gateway depends on latest type Node struct { target TargetAPI + subHnd *EthSubHandler lookbackCap time.Duration stateWaitLookbackLimit abi.ChainEpoch rateLimiter *rate.Limiter @@ -141,7 +146,7 @@ var ( ) // NewNode creates a new gateway node. -func NewNode(api TargetAPI, lookbackCap time.Duration, stateWaitLookbackLimit abi.ChainEpoch, rateLimit int64, rateLimitTimeout time.Duration) *Node { +func NewNode(api TargetAPI, sHnd *EthSubHandler, lookbackCap time.Duration, stateWaitLookbackLimit abi.ChainEpoch, rateLimit int64, rateLimitTimeout time.Duration) *Node { var limit rate.Limit if rateLimit == 0 { limit = rate.Inf @@ -150,6 +155,7 @@ func NewNode(api TargetAPI, lookbackCap time.Duration, stateWaitLookbackLimit ab } return &Node{ target: api, + subHnd: sHnd, lookbackCap: lookbackCap, stateWaitLookbackLimit: stateWaitLookbackLimit, rateLimiter: rate.NewLimiter(limit, stateRateLimitTokens), diff --git a/gateway/node_test.go b/gateway/node_test.go index 805767dc6..aa33e8bfb 100644 --- a/gateway/node_test.go +++ b/gateway/node_test.go @@ -89,7 +89,7 @@ func TestGatewayAPIChainGetTipSetByHeight(t *testing.T) { tt := tt t.Run(tt.name, func(t *testing.T) { mock := &mockGatewayDepsAPI{} - a := NewNode(mock, DefaultLookbackCap, DefaultStateWaitLookbackLimit, 0, time.Minute) + a := NewNode(mock, nil, DefaultLookbackCap, DefaultStateWaitLookbackLimit, 0, time.Minute) // Create tipsets from genesis up to tskh and return the highest ts := mock.createTipSets(tt.args.tskh, tt.args.genesisTS) @@ -245,7 +245,7 @@ func TestGatewayVersion(t *testing.T) { //stm: @GATEWAY_NODE_GET_VERSION_001 ctx := context.Background() mock := &mockGatewayDepsAPI{} - a := NewNode(mock, DefaultLookbackCap, DefaultStateWaitLookbackLimit, 0, time.Minute) + a := NewNode(mock, nil, DefaultLookbackCap, DefaultStateWaitLookbackLimit, 0, time.Minute) v, err := a.Version(ctx) require.NoError(t, err) @@ -256,7 +256,7 @@ func TestGatewayLimitTokensAvailable(t *testing.T) { ctx := context.Background() mock := &mockGatewayDepsAPI{} tokens := 3 - a := NewNode(mock, DefaultLookbackCap, DefaultStateWaitLookbackLimit, int64(tokens), time.Minute) + a := NewNode(mock, nil, DefaultLookbackCap, DefaultStateWaitLookbackLimit, int64(tokens), time.Minute) require.NoError(t, a.limit(ctx, tokens), "requests should not be limited when there are enough tokens available") } @@ -264,7 +264,7 @@ func TestGatewayLimitTokensNotAvailable(t *testing.T) { ctx := context.Background() mock := &mockGatewayDepsAPI{} tokens := 3 - a := NewNode(mock, DefaultLookbackCap, DefaultStateWaitLookbackLimit, int64(1), time.Millisecond) + a := NewNode(mock, nil, DefaultLookbackCap, DefaultStateWaitLookbackLimit, int64(1), time.Millisecond) var err error // try to be rate limited for i := 0; i <= 1000; i++ { diff --git a/gateway/proxy_eth.go b/gateway/proxy_eth.go index fcad213d9..40b68f500 100644 --- a/gateway/proxy_eth.go +++ b/gateway/proxy_eth.go @@ -3,12 +3,15 @@ package gateway import ( "bytes" "context" + "encoding/json" "fmt" "sync" "time" + "github.com/ipfs/go-cid" "golang.org/x/xerrors" + "github.com/filecoin-project/go-jsonrpc" "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/big" @@ -17,6 +20,14 @@ import ( "github.com/filecoin-project/lotus/chain/types/ethtypes" ) +func (gw *Node) Web3ClientVersion(ctx context.Context) (string, error) { + if err := gw.limit(ctx, stateRateLimitTokens); err != nil { + return "", err + } + + return gw.target.Web3ClientVersion(ctx) +} + func (gw *Node) EthAccounts(ctx context.Context) ([]ethtypes.EthAddress, error) { // gateway provides public API, so it can't hold user accounts return []ethtypes.EthAddress{}, nil @@ -141,6 +152,22 @@ func (gw *Node) EthGetTransactionByHash(ctx context.Context, txHash *ethtypes.Et return gw.target.EthGetTransactionByHash(ctx, txHash) } +func (gw *Node) EthGetTransactionHashByCid(ctx context.Context, cid cid.Cid) (*ethtypes.EthHash, error) { + if err := gw.limit(ctx, stateRateLimitTokens); err != nil { + return nil, err + } + + return gw.target.EthGetTransactionHashByCid(ctx, cid) +} + +func (gw *Node) EthGetMessageCidByTransactionHash(ctx context.Context, txHash *ethtypes.EthHash) (*cid.Cid, error) { + if err := gw.limit(ctx, stateRateLimitTokens); err != nil { + return nil, err + } + + return gw.target.EthGetMessageCidByTransactionHash(ctx, txHash) +} + func (gw *Node) EthGetTransactionCount(ctx context.Context, sender ethtypes.EthAddress, blkOpt string) (ethtypes.EthUint64, error) { if err := gw.limit(ctx, stateRateLimitTokens); err != nil { return 0, err @@ -352,7 +379,7 @@ func (gw *Node) EthGetFilterChanges(ctx context.Context, id ethtypes.EthFilterID return nil, err } - ft := filterTrackerFromContext(ctx) + ft := statefulCallFromContext(ctx) ft.lk.Lock() _, ok := ft.userFilters[id] ft.lk.Unlock() @@ -369,7 +396,7 @@ func (gw *Node) EthGetFilterLogs(ctx context.Context, id ethtypes.EthFilterID) ( return nil, err } - ft := filterTrackerFromContext(ctx) + ft := statefulCallFromContext(ctx) ft.lk.Lock() _, ok := ft.userFilters[id] ft.lk.Unlock() @@ -417,7 +444,7 @@ func (gw *Node) EthUninstallFilter(ctx context.Context, id ethtypes.EthFilterID) } // check if the filter belongs to this connection - ft := filterTrackerFromContext(ctx) + ft := statefulCallFromContext(ctx) ft.lk.Lock() defer ft.lk.Unlock() @@ -434,18 +461,88 @@ func (gw *Node) EthUninstallFilter(ctx context.Context, id ethtypes.EthFilterID) return ok, nil } -func (gw *Node) EthSubscribe(ctx context.Context, eventType string, params *ethtypes.EthSubscriptionParams) (<-chan ethtypes.EthSubscriptionResponse, error) { - return nil, xerrors.Errorf("not implemented") +func (gw *Node) EthSubscribe(ctx context.Context, p jsonrpc.RawParams) (ethtypes.EthSubscriptionID, error) { + // validate params + _, err := jsonrpc.DecodeParams[ethtypes.EthSubscribeParams](p) + if err != nil { + return ethtypes.EthSubscriptionID{}, xerrors.Errorf("decoding params: %w", err) + } + + if err := gw.limit(ctx, stateRateLimitTokens); err != nil { + return ethtypes.EthSubscriptionID{}, err + } + + if gw.subHnd == nil { + return ethtypes.EthSubscriptionID{}, xerrors.New("subscription support not enabled") + } + + ethCb, ok := jsonrpc.ExtractReverseClient[api.EthSubscriberMethods](ctx) + if !ok { + return ethtypes.EthSubscriptionID{}, xerrors.Errorf("connection doesn't support callbacks") + } + + ft := statefulCallFromContext(ctx) + ft.lk.Lock() + defer ft.lk.Unlock() + + if len(ft.userSubscriptions) >= EthMaxFiltersPerConn { + return ethtypes.EthSubscriptionID{}, fmt.Errorf("too many subscriptions") + } + + sub, err := gw.target.EthSubscribe(ctx, p) + if err != nil { + return ethtypes.EthSubscriptionID{}, err + } + + err = gw.subHnd.AddSub(ctx, sub, func(ctx context.Context, response *ethtypes.EthSubscriptionResponse) error { + outParam, err := json.Marshal(response) + if err != nil { + return err + } + + return ethCb.EthSubscription(ctx, outParam) + }) + if err != nil { + return ethtypes.EthSubscriptionID{}, err + } + + ft.userSubscriptions[sub] = time.Now() + + return sub, err } func (gw *Node) EthUnsubscribe(ctx context.Context, id ethtypes.EthSubscriptionID) (bool, error) { - return false, xerrors.Errorf("not implemented") + if err := gw.limit(ctx, stateRateLimitTokens); err != nil { + return false, err + } + + // check if the filter belongs to this connection + ft := statefulCallFromContext(ctx) + ft.lk.Lock() + defer ft.lk.Unlock() + + if _, ok := ft.userSubscriptions[id]; !ok { + return false, nil + } + + ok, err := gw.target.EthUnsubscribe(ctx, id) + if err != nil { + return false, err + } + + delete(ft.userSubscriptions, id) + + if gw.subHnd != nil { + gw.subHnd.RemoveSub(id) + } + + return ok, nil } var EthMaxFiltersPerConn = 16 // todo make this configurable func addUserFilterLimited(ctx context.Context, cb func() (ethtypes.EthFilterID, error)) (ethtypes.EthFilterID, error) { - ft := filterTrackerFromContext(ctx) + ft := statefulCallFromContext(ctx) ft.lk.Lock() defer ft.lk.Unlock() @@ -463,19 +560,21 @@ func addUserFilterLimited(ctx context.Context, cb func() (ethtypes.EthFilterID, return id, nil } -func filterTrackerFromContext(ctx context.Context) *filterTracker { - return ctx.Value(filterTrackerKey).(*filterTracker) +func statefulCallFromContext(ctx context.Context) *statefulCallTracker { + return ctx.Value(statefulCallTrackerKey).(*statefulCallTracker) } -type filterTracker struct { +type statefulCallTracker struct { lk sync.Mutex - userFilters map[ethtypes.EthFilterID]time.Time + userFilters map[ethtypes.EthFilterID]time.Time + userSubscriptions map[ethtypes.EthSubscriptionID]time.Time } // called per request (ws connection) -func newFilterTracker() *filterTracker { - return &filterTracker{ - userFilters: make(map[ethtypes.EthFilterID]time.Time), +func newStatefulCallTracker() *statefulCallTracker { + return &statefulCallTracker{ + userFilters: make(map[ethtypes.EthFilterID]time.Time), + userSubscriptions: make(map[ethtypes.EthSubscriptionID]time.Time), } } diff --git a/gen/api/proxygen.go b/gen/api/proxygen.go index f756c0d0c..75fbc668c 100644 --- a/gen/api/proxygen.go +++ b/gen/api/proxygen.go @@ -259,7 +259,7 @@ func generate(path, pkg, outpkg, outfile string) error { if len(tf) != 2 { continue } - if tf[0] != "perm" { // todo: allow more tag types + if tf[0] != "perm" && tf[0] != "rpc_method" && tf[0] != "notify" { // todo: allow more tag types continue } info.Methods[mname].Tags[tf[0]] = tf @@ -302,12 +302,14 @@ type {{.Num}}Struct struct { {{range .Include}} {{.}}Struct {{end}} - Internal struct { + Internal {{.Num}}Methods +} + +type {{.Num}}Methods struct { {{range .Methods}} {{.Num}} func({{.NamedParams}}) ({{.Results}}) `+"`"+`{{range .Tags}}{{index . 0}}:"{{index . 1}}"{{end}}`+"`"+` {{end}} } -} type {{.Num}}Stub struct { {{range .Include}} diff --git a/gen/bundle/bundle.go b/gen/bundle/bundle.go index c7655157e..666ce9f66 100644 --- a/gen/bundle/bundle.go +++ b/gen/bundle/bundle.go @@ -20,6 +20,7 @@ var EmbeddedBuiltinActorsMetadata []*BuiltinActorsMetadata = []*BuiltinActorsMet {{- range . }} { Network: {{printf "%q" .Network}}, Version: {{.Version}}, + {{if .BundleGitTag}} BundleGitTag: {{printf "%q" .BundleGitTag}}, {{end}} ManifestCid: MustParseCid({{printf "%q" .ManifestCid}}), Actors: map[string]cid.Cid { {{- range $name, $cid := .Actors }} @@ -37,6 +38,12 @@ func main() { panic(err) } + if len(os.Args) > 1 { + for _, m := range metadata { + m.BundleGitTag = os.Args[1] + } + } + fi, err := os.Create("./build/builtin_actors_gen.go") if err != nil { panic(err) diff --git a/go.mod b/go.mod index 485bfb5a4..f32f2f7ee 100644 --- a/go.mod +++ b/go.mod @@ -40,11 +40,11 @@ require ( github.com/filecoin-project/go-fil-commcid v0.1.0 github.com/filecoin-project/go-fil-commp-hashhash v0.1.0 github.com/filecoin-project/go-fil-markets v1.25.2 - github.com/filecoin-project/go-jsonrpc v0.1.9 + github.com/filecoin-project/go-jsonrpc v0.2.1 github.com/filecoin-project/go-legs v0.4.4 github.com/filecoin-project/go-padreader v0.0.1 github.com/filecoin-project/go-paramfetch v0.0.4 - github.com/filecoin-project/go-state-types v0.10.0-alpha-10 + github.com/filecoin-project/go-state-types v0.10.0-alpha-11 github.com/filecoin-project/go-statemachine v1.0.2 github.com/filecoin-project/go-statestore v0.2.0 github.com/filecoin-project/go-storedcounter v0.1.0 @@ -62,10 +62,12 @@ require ( github.com/gbrlsnchs/jwt/v3 v3.0.1 github.com/gdamore/tcell/v2 v2.2.0 github.com/go-kit/kit v0.12.0 + github.com/go-openapi/spec v0.19.11 github.com/golang/mock v1.6.0 github.com/google/uuid v1.3.0 github.com/gorilla/mux v1.8.0 github.com/gorilla/websocket v1.5.0 + github.com/gregdhill/go-openrpc v0.0.0-20220114144539-ae6f44720487 github.com/hako/durafmt v0.0.0-20200710122514-c0fb7b4da026 github.com/hannahhoward/go-pubsub v0.0.0-20200423002714-8d62886cc36e github.com/hashicorp/go-multierror v1.1.1 @@ -145,6 +147,7 @@ require ( github.com/whyrusleeping/cbor-gen v0.0.0-20221021053955-c138aae13722 github.com/whyrusleeping/ledger-filecoin-go v0.9.1-0.20201010031517-c3dcc1bddce4 github.com/whyrusleeping/multiaddr-filter v0.0.0-20160516205228-e903e4adabd7 + github.com/xeipuuv/gojsonschema v1.2.0 github.com/xorcare/golden v0.6.1-0.20191112154924-b87f686d7542 go.opencensus.io v0.23.0 go.opentelemetry.io/otel v1.11.1 @@ -213,7 +216,6 @@ require ( github.com/go-ole/go-ole v1.2.5 // indirect github.com/go-openapi/jsonpointer v0.19.3 // indirect github.com/go-openapi/jsonreference v0.19.4 // indirect - github.com/go-openapi/spec v0.19.11 // indirect github.com/go-openapi/swag v0.19.11 // indirect github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 // indirect github.com/godbus/dbus/v5 v5.1.0 // indirect @@ -324,6 +326,8 @@ require ( github.com/whyrusleeping/chunker v0.0.0-20181014151217-fe64bd25879f // indirect github.com/whyrusleeping/go-keyspace v0.0.0-20160322163242-5b898ac5add1 // indirect github.com/whyrusleeping/timecache v0.0.0-20160911033111-cfcb2f1abfee // indirect + github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f // indirect + github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect github.com/zondax/hid v0.9.1 // indirect github.com/zondax/ledger-go v0.12.1 // indirect diff --git a/go.sum b/go.sum index 6ae2f7c4b..c0fa2bbcb 100644 --- a/go.sum +++ b/go.sum @@ -340,8 +340,8 @@ github.com/filecoin-project/go-hamt-ipld/v2 v2.0.0/go.mod h1:7aWZdaQ1b16BVoQUYR+ github.com/filecoin-project/go-hamt-ipld/v3 v3.0.1/go.mod h1:gXpNmr3oQx8l3o7qkGyDjJjYSRX7hp/FGOStdqrWyDI= github.com/filecoin-project/go-hamt-ipld/v3 v3.1.0 h1:rVVNq0x6RGQIzCo1iiJlGFm9AGIZzeifggxtKMU7zmI= github.com/filecoin-project/go-hamt-ipld/v3 v3.1.0/go.mod h1:bxmzgT8tmeVQA1/gvBwFmYdT8SOFUwB3ovSUfG1Ux0g= -github.com/filecoin-project/go-jsonrpc v0.1.9 h1:HRWLxo7HAWzI3xZGeFG4LZJoYpms+Q+8kwmMTLnyS3A= -github.com/filecoin-project/go-jsonrpc v0.1.9/go.mod h1:XBBpuKIMaXIIzeqzO1iucq4GvbF8CxmXRFoezRh+Cx4= +github.com/filecoin-project/go-jsonrpc v0.2.1 h1:xfxkfIAO300sPiV59DnxnCb4sdTtWYlRz/TsP+ByT2E= +github.com/filecoin-project/go-jsonrpc v0.2.1/go.mod h1:jBSvPTl8V1N7gSTuCR4bis8wnQnIjHbRPpROol6iQKM= github.com/filecoin-project/go-legs v0.4.4 h1:mpMmAOOnamaz0CV9rgeKhEWA8j9kMC+f+UGCGrxKaZo= github.com/filecoin-project/go-legs v0.4.4/go.mod h1:JQ3hA6xpJdbR8euZ2rO0jkxaMxeidXf0LDnVuqPAe9s= github.com/filecoin-project/go-padreader v0.0.0-20200903213702-ed5fae088b20/go.mod h1:mPn+LRRd5gEKNAtc+r3ScpW2JRU/pj4NBKdADYWHiak= @@ -356,8 +356,8 @@ github.com/filecoin-project/go-state-types v0.1.0/go.mod h1:ezYnPf0bNkTsDibL/psS github.com/filecoin-project/go-state-types v0.1.6/go.mod h1:UwGVoMsULoCK+bWjEdd/xLCvLAQFBC7EDT477SKml+Q= github.com/filecoin-project/go-state-types v0.1.8/go.mod h1:UwGVoMsULoCK+bWjEdd/xLCvLAQFBC7EDT477SKml+Q= github.com/filecoin-project/go-state-types v0.1.10/go.mod h1:UwGVoMsULoCK+bWjEdd/xLCvLAQFBC7EDT477SKml+Q= -github.com/filecoin-project/go-state-types v0.10.0-alpha-10 h1:QUpSayVFUADlrtzCh7SDNlbuaNSlYPBR46Nt7WpFl9I= -github.com/filecoin-project/go-state-types v0.10.0-alpha-10/go.mod h1:FPgQE05BFwZxKw/vCuIaIrzfJKo4RPQQMMPGd43dAFI= +github.com/filecoin-project/go-state-types v0.10.0-alpha-11 h1:lfrbmLXaC3vQk1gQCUwtTuY1U2ANrgDsJ7+VapBjRCo= +github.com/filecoin-project/go-state-types v0.10.0-alpha-11/go.mod h1:aLIas+W8BWAfpLWEPUOGMPBdhcVwoCG4pIQSQk26024= github.com/filecoin-project/go-statemachine v0.0.0-20200925024713-05bd7c71fbfe/go.mod h1:FGwQgZAt2Gh5mjlwJUlVB62JeYdo+if0xWxSEfBD9ig= github.com/filecoin-project/go-statemachine v1.0.2 h1:421SSWBk8GIoCoWYYTE/d+qCWccgmRH0uXotXRDjUbc= github.com/filecoin-project/go-statemachine v1.0.2/go.mod h1:jZdXXiHa61n4NmgWFG4w8tnqgvZVHYbJ3yW7+y8bF54= @@ -451,6 +451,7 @@ github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwoh github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8= github.com/go-openapi/jsonreference v0.19.4 h1:3Vw+rh13uq2JFNxgnMTGE1rnoieU9FmyE1gvnyylsYg= github.com/go-openapi/jsonreference v0.19.4/go.mod h1:RdybgQwPxbL4UEjuAruzK1x3nE69AqPYEJeo/TWfEeg= +github.com/go-openapi/spec v0.19.2/go.mod h1:sCxk3jxKgioEJikev4fgkNmwS+3kuYdJtcsZsD5zxMY= github.com/go-openapi/spec v0.19.7/go.mod h1:Hm2Jr4jv8G1ciIAo+frC/Ft+rR2kQDh8JHKHb3gWUSk= github.com/go-openapi/spec v0.19.11 h1:ogU5q8dtp3MMPn59a9VRrPKVxvJHEs5P7yNMR5sNnis= github.com/go-openapi/spec v0.19.11/go.mod h1:vqK/dIdLGCosfvYsQV3WfC7N3TiZSnGY2RZKoFK7X28= @@ -464,6 +465,10 @@ github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LB github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= +github.com/gobuffalo/envy v1.7.0/go.mod h1:n7DRkBerg/aorDM8kbduw5dN3oXGswK5liaSCx4T5NI= +github.com/gobuffalo/logger v1.0.0/go.mod h1:2zbswyIUa45I+c+FLXuWl9zSWEiVuthsk8ze5s8JvPs= +github.com/gobuffalo/packd v0.3.0/go.mod h1:zC7QkmNkYVGKPw4tHpBQ+ml7W/3tIebgeo1b36chA3Q= +github.com/gobuffalo/packr/v2 v2.6.0/go.mod h1:sgEE1xNZ6G0FNN5xn9pevVu4nywaxHvgup67xisti08= github.com/godbus/dbus v0.0.0-20190402143921-271e53dc4968/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw= github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= @@ -586,6 +591,8 @@ github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/ad github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/gregdhill/go-openrpc v0.0.0-20220114144539-ae6f44720487 h1:NyaWOSkqFK1d9o+HLfnMIGzrHuUUPeBNIZyi5Zoe/lY= +github.com/gregdhill/go-openrpc v0.0.0-20220114144539-ae6f44720487/go.mod h1:a1eRkbhd3DYpRH2lnuUsVG+QMTI+v0hGnsis8C9hMrA= github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-middleware v1.1.0/go.mod h1:f5nM7jw/oeRSadq3xCzHAvxcr8HZnzsqU6ILg/0NiiE= @@ -665,6 +672,7 @@ github.com/icza/backscanner v0.0.0-20210726202459-ac2ffc679f94 h1:9tcYMdi+7Rb1y0 github.com/icza/backscanner v0.0.0-20210726202459-ac2ffc679f94/go.mod h1:GYeBD1CF7AqnKZK+UCytLcY3G+UKo0ByXX/3xfdNyqQ= github.com/icza/mighty v0.0.0-20180919140131-cfd07d671de6 h1:8UsGZ2rr2ksmEru6lToqnXgA8Mz1DP11X4zSJ159C3k= github.com/icza/mighty v0.0.0-20180919140131-cfd07d671de6/go.mod h1:xQig96I1VNBDIWGCdTt54nHt6EeI639SmHycLYL7FkA= +github.com/imdario/mergo v0.3.7/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= github.com/influxdata/influxdb1-client v0.0.0-20200827194710-b269163b24ab h1:HqW4xhhynfjrtEiiSGcQUd6vrK23iMam1FO8rI7mwig= @@ -824,7 +832,6 @@ github.com/ipfs/go-log/v2 v2.0.1/go.mod h1:O7P1lJt27vWHhOwQmcFEvlmo49ry2VY2+JfBW github.com/ipfs/go-log/v2 v2.0.2/go.mod h1:O7P1lJt27vWHhOwQmcFEvlmo49ry2VY2+JfBWFaa9+0= github.com/ipfs/go-log/v2 v2.0.3/go.mod h1:O7P1lJt27vWHhOwQmcFEvlmo49ry2VY2+JfBWFaa9+0= github.com/ipfs/go-log/v2 v2.0.5/go.mod h1:eZs4Xt4ZUJQFM3DlanGhy7TkwwawCZcSByscwkWG+dw= -github.com/ipfs/go-log/v2 v2.0.8/go.mod h1:eZs4Xt4ZUJQFM3DlanGhy7TkwwawCZcSByscwkWG+dw= github.com/ipfs/go-log/v2 v2.1.1/go.mod h1:2v2nsGfZsvvAJz13SyFzf9ObaqwHiHxsPLEHntrv9KM= github.com/ipfs/go-log/v2 v2.1.2-0.20200626104915-0016c0b4b3e4/go.mod h1:2v2nsGfZsvvAJz13SyFzf9ObaqwHiHxsPLEHntrv9KM= github.com/ipfs/go-log/v2 v2.1.2/go.mod h1:2v2nsGfZsvvAJz13SyFzf9ObaqwHiHxsPLEHntrv9KM= @@ -924,6 +931,7 @@ github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht github.com/jmespath/go-jmespath v0.3.0/go.mod h1:9QtRXoHjLGCJ5IBSaohpXITPlowMeeYCZ7fLUTSywik= github.com/joeshaw/multierror v0.0.0-20140124173710-69b34d4ec901 h1:rp+c0RAYOWj8l6qbCUTSiRLG/iKnW3K3/QfPPuSsBt4= github.com/joeshaw/multierror v0.0.0-20140124173710-69b34d4ec901/go.mod h1:Z86h9688Y0wesXCyonoVr47MasHilkuLMqGhRZ4Hpak= +github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= github.com/jonboulle/clockwork v0.1.1-0.20190114141812-62fb9bc030d1/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= github.com/jonboulle/clockwork v0.2.2 h1:UOGuzwb1PwsrDAObMuhUnj0p5ULPj8V/xJ7Kx9qUBdQ= @@ -952,6 +960,7 @@ github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7V github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= github.com/kabukky/httpscerts v0.0.0-20150320125433-617593d7dcb3/go.mod h1:BYpt4ufZiIGv2nXn4gMxnfKV306n3mWXgNu/d2TqdTU= github.com/kami-zh/go-capturer v0.0.0-20171211120116-e492ea43421d/go.mod h1:P2viExyCEfeWGU259JnaQ34Inuec4R38JCyBx2edgD0= +github.com/karrick/godirwalk v1.10.12/go.mod h1:RoGL9dQei4vP9ilrpETWE8CLOZ1kiN0LhBygSwrAsHA= github.com/kelseyhightower/envconfig v1.4.0 h1:Im6hONhd3pLkfDFsbRgu68RDNkGF1r3dvMUtDTo2cv8= github.com/kelseyhightower/envconfig v1.4.0/go.mod h1:cccZRl6mQpaq41TPp5QxidR+Sa3axMbJDNb//FQX6Gg= github.com/kilic/bls12-381 v0.0.0-20200607163746-32e1441c8a9f/go.mod h1:XXfR6YFCRSrkEXbNlIyDsgXVNJWVUV30m/ebkVy9n6s= @@ -977,6 +986,7 @@ github.com/klauspost/cpuid/v2 v2.1.1/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8t github.com/koalacxr/quantile v0.0.1 h1:wAW+SQ286Erny9wOjVww96t8ws+x5Zj6AKHDULUK+o0= github.com/koalacxr/quantile v0.0.1/go.mod h1:bGN/mCZLZ4lrSDHRQ6Lglj9chowGux8sGUIND+DQeD0= 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.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/koron/go-ssdp v0.0.0-20180514024734-4a0ed625a78b/go.mod h1:5Ky9EC2xfoUKUor0Hjgi2BJhCSXJfMOFlmyYrVKGQMk= github.com/koron/go-ssdp v0.0.0-20191105050749-2e1c40ed0b5d/go.mod h1:5Ky9EC2xfoUKUor0Hjgi2BJhCSXJfMOFlmyYrVKGQMk= @@ -991,6 +1001,7 @@ github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.3/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA= 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= @@ -1694,6 +1705,7 @@ github.com/rivo/uniseg v0.1.0 h1:+2KBaVoUmb9XzDsrx/Ct0W/EYOSFf/nWTauy++DprtY= github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= +github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rogpeppe/go-internal v1.8.1 h1:geMPLpDpQOgVyCg5z5GoRwLHepNdb71NXb67XFkP+Eg= @@ -1780,6 +1792,7 @@ github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3 github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI= 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.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= github.com/stretchr/objx v0.4.0 h1:M2gUjqZET1qApGOWNSnZ49BAIMX4F/1plDv3+l31EJ4= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= @@ -1796,6 +1809,8 @@ github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpP github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA= +github.com/test-go/testify v1.1.4 h1:Tf9lntrKUMHiXQ07qBScBTSA0dhYQlu83hswqelv1iE= +github.com/test-go/testify v1.1.4/go.mod h1:rH7cfJo/47vWGdi4GPj16x3/t1xGOj2YxzmNQzk2ghU= github.com/texttheater/golang-levenshtein v0.0.0-20180516184445-d188e65d659e/go.mod h1:XDKHRm5ThF8YJjx001LtgelzsoaEcvnA7lVWz9EeX3g= github.com/tidwall/gjson v1.6.0 h1:9VEQWz6LLMUsUl6PueE49ir4Ka6CzLymOAZDxpFsTDc= github.com/tidwall/gjson v1.6.0/go.mod h1:P256ACg0Mn+j1RXIDXoss50DeIABTYK1PULOJHhxOls= @@ -1881,6 +1896,12 @@ github.com/whyrusleeping/multiaddr-filter v0.0.0-20160516205228-e903e4adabd7/go. github.com/whyrusleeping/timecache v0.0.0-20160911033111-cfcb2f1abfee h1:lYbXeSvJi5zk5GLKVuid9TVjS9a0OmLIDKTfoZBL6Ow= github.com/whyrusleeping/timecache v0.0.0-20160911033111-cfcb2f1abfee/go.mod h1:m2aV4LZI4Aez7dP5PMyVKEHhUyEJ/RjmPEDOpDvudHg= github.com/x-cray/logrus-prefixed-formatter v0.5.2/go.mod h1:2duySbKsL6M18s5GU7VPsoEPHyzalCE06qoARUCeBBE= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= +github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74= +github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xorcare/golden v0.6.0/go.mod h1:7T39/ZMvaSEZlBPoYfVFmsBLmUl3uz9IuzWj/U6FtvQ= github.com/xorcare/golden v0.6.1-0.20191112154924-b87f686d7542 h1:oWgZJmC1DorFZDpfMfWg7xk29yEOZiXmo/wZl+utTI8= @@ -2005,6 +2026,7 @@ golang.org/x/crypto v0.0.0-20190530122614-20be4c3c3ed5/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190618222545-ea8f1a30c443/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190621222207-cc06ce4a13d4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190927123631-a832865fa7ad/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= @@ -2192,12 +2214,14 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7w 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-20190515120540-06a5c4944438/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190523142557-0e01d883c5c5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190524122548-abf6ff778158/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190524152521-dbbf3f1254d4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190526052359-791d8a0f4d09/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190610200419-93c9922d18ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -2309,6 +2333,7 @@ golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBn golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= diff --git a/itests/contracts/AutoSelfDestruct.hex b/itests/contracts/AutoSelfDestruct.hex new file mode 100644 index 000000000..f5128bf30 --- /dev/null +++ b/itests/contracts/AutoSelfDestruct.hex @@ -0,0 +1 @@ +608060405234801561001057600080fd5b5061001f61002460201b60201c565b61003d565b3373ffffffffffffffffffffffffffffffffffffffff16ff5b60848061004b6000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c806383197ef014602d575b600080fd5b60336035565b005b3373ffffffffffffffffffffffffffffffffffffffff16fffea26469706673582212208d48a69a112633756d84552847610df29b02ac89dd39e4e295066e99a45e809664736f6c63430008110033 \ No newline at end of file diff --git a/itests/contracts/AutoSelfDestruct.sol b/itests/contracts/AutoSelfDestruct.sol new file mode 100644 index 000000000..bdb165f5d --- /dev/null +++ b/itests/contracts/AutoSelfDestruct.sol @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.17; + +contract AutoSelfDestruct { + constructor() { + destroy(); + } + function destroy() public { + selfdestruct(payable(msg.sender)); + } +} diff --git a/itests/contracts/Constructor.hex b/itests/contracts/Constructor.hex new file mode 100644 index 000000000..e46d5bcd1 --- /dev/null +++ b/itests/contracts/Constructor.hex @@ -0,0 +1 @@ +608060405234801561001057600080fd5b506103ca806100206000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c806358f5ebb614610030575b600080fd5b61004a60048036038101906100459190610123565b610060565b6040516100579190610191565b60405180910390f35b60008082604051610070906100db565b61007a91906101bb565b604051809103906000f080158015610096573d6000803e3d6000fd5b5090507f3a5c468996b00310e3e82919e3af9cce21d49c40c39a2627a9f946e1a54d886232846040516100ca9291906101d6565b60405180910390a180915050919050565b6101958061020083390190565b600080fd5b6000819050919050565b610100816100ed565b811461010b57600080fd5b50565b60008135905061011d816100f7565b92915050565b600060208284031215610139576101386100e8565b5b60006101478482850161010e565b91505092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061017b82610150565b9050919050565b61018b81610170565b82525050565b60006020820190506101a66000830184610182565b92915050565b6101b5816100ed565b82525050565b60006020820190506101d060008301846101ac565b92915050565b60006040820190506101eb6000830185610182565b6101f860208301846101ac565b939250505056fe608060405234801561001057600080fd5b506040516101953803806101958339818101604052810190610032919061007a565b80600081905550506100a7565b600080fd5b6000819050919050565b61005781610044565b811461006257600080fd5b50565b6000815190506100748161004e565b92915050565b6000602082840312156100905761008f61003f565b5b600061009e84828501610065565b91505092915050565b60e0806100b56000396000f3fe6080604052348015600f57600080fd5b506004361060325760003560e01c80638381f58a146037578063eeb4e367146051575b600080fd5b603d606b565b604051604891906091565b60405180910390f35b60576071565b604051606291906091565b60405180910390f35b60005481565b60008054905090565b6000819050919050565b608b81607a565b82525050565b600060208201905060a460008301846084565b9291505056fea2646970667358221220451c388f24a935fc5f5eef536207cbd982254ac8521d49937bb10e5079e3924164736f6c63430008110033a264697066735822122027da159d84a9bdcd5aff5755c4602f7099db638f7a95d715c76454c99511146f64736f6c63430008110033 \ No newline at end of file diff --git a/itests/contracts/Constructor.sol b/itests/contracts/Constructor.sol new file mode 100644 index 000000000..a85d13269 --- /dev/null +++ b/itests/contracts/Constructor.sol @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.2; + + +contract Test_contract { + uint256 public number; + + constructor(uint256 _number) { + number = _number; + } + + function get_number() public view returns (uint256) { + return number; + } +} + +contract App { + + event NewTest(address sender, uint256 number); + + function new_Test(uint256 number) + public + returns (address) + { + address mynew = address(new Test_contract({_number: number})); + emit NewTest(tx.origin, number); + return mynew; + } +} diff --git a/itests/contracts/Create2Factory.hex b/itests/contracts/Create2Factory.hex new file mode 100644 index 000000000..006874306 --- /dev/null +++ b/itests/contracts/Create2Factory.hex @@ -0,0 +1 @@ +608060405234801561001057600080fd5b506109fb806100206000396000f3fe608060405234801561001057600080fd5b506004361061004c5760003560e01c80632b85ba3814610051578063732768dd146100815780637c3e4053146100b2578063bb29998e146100e2575b600080fd5b61006b60048036038101906100669190610473565b610112565b60405161007891906104e1565b60405180910390f35b61009b60048036038101906100969190610473565b61013f565b6040516100a9929190610517565b60405180910390f35b6100cc60048036038101906100c79190610473565b61027e565b6040516100d991906104e1565b60405180910390f35b6100fc60048036038101906100f7919061056c565b6102c0565b60405161010991906104e1565b60405180910390f35b6000816000819055506000806101278461013f565b915091508161013557600080fd5b8092505050919050565b60008060008360405160240161015591906105a8565b6040516020818303038152906040527f7c3e4053000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505090506000803073ffffffffffffffffffffffffffffffffffffffff16836040516101fc9190610634565b600060405180830381855af49150503d8060008114610237576040519150601f19603f3d011682016040523d82523d6000602084013e61023c565b606091505b5091509150811561026e5760008180602001905181019061025d9190610689565b905082819550955050505050610279565b816000945094505050505b915091565b6000818260405161028e9061042b565b61029891906105a8565b8190604051809103906000f59050801580156102b8573d6000803e3d6000fd5b509050919050565b6000808290508073ffffffffffffffffffffffffffffffffffffffff166383197ef06040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561030e57600080fd5b505af1158015610322573d6000803e3d6000fd5b5050505060008173ffffffffffffffffffffffffffffffffffffffff166367e404ce6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610373573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061039791906106cb565b905060006104128373ffffffffffffffffffffffffffffffffffffffff1663bfa0b1336040518163ffffffff1660e01b8152600401602060405180830381865afa1580156103e9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061040d919061070d565b61013f565b509050801561042057600080fd5b819350505050919050565b61028b8061073b83390190565b600080fd5b6000819050919050565b6104508161043d565b811461045b57600080fd5b50565b60008135905061046d81610447565b92915050565b60006020828403121561048957610488610438565b5b60006104978482850161045e565b91505092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006104cb826104a0565b9050919050565b6104db816104c0565b82525050565b60006020820190506104f660008301846104d2565b92915050565b60008115159050919050565b610511816104fc565b82525050565b600060408201905061052c6000830185610508565b61053960208301846104d2565b9392505050565b610549816104c0565b811461055457600080fd5b50565b60008135905061056681610540565b92915050565b60006020828403121561058257610581610438565b5b600061059084828501610557565b91505092915050565b6105a28161043d565b82525050565b60006020820190506105bd6000830184610599565b92915050565b600081519050919050565b600081905092915050565b60005b838110156105f75780820151818401526020810190506105dc565b60008484015250505050565b600061060e826105c3565b61061881856105ce565b93506106288185602086016105d9565b80840191505092915050565b60006106408284610603565b915081905092915050565b6000610656826104a0565b9050919050565b6106668161064b565b811461067157600080fd5b50565b6000815190506106838161065d565b92915050565b60006020828403121561069f5761069e610438565b5b60006106ad84828501610674565b91505092915050565b6000815190506106c581610540565b92915050565b6000602082840312156106e1576106e0610438565b5b60006106ef848285016106b6565b91505092915050565b60008151905061070781610447565b92915050565b60006020828403121561072357610722610438565b5b6000610731848285016106f8565b9150509291505056fe608060405234801561001057600080fd5b5060405161028b38038061028b833981810160405281019061003291906100ba565b326000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600181905550506100e7565b600080fd5b6000819050919050565b61009781610084565b81146100a257600080fd5b50565b6000815190506100b48161008e565b92915050565b6000602082840312156100d0576100cf61007f565b5b60006100de848285016100a5565b91505092915050565b610195806100f66000396000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c806367e404ce1461004657806383197ef014610064578063bfa0b1331461006e575b600080fd5b61004e61008c565b60405161005b9190610110565b60405180910390f35b61006c6100b0565b005b6100766100c9565b6040516100839190610144565b60405180910390f35b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b3373ffffffffffffffffffffffffffffffffffffffff16ff5b60015481565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006100fa826100cf565b9050919050565b61010a816100ef565b82525050565b60006020820190506101256000830184610101565b92915050565b6000819050919050565b61013e8161012b565b82525050565b60006020820190506101596000830184610135565b9291505056fea26469706673582212208252a57fdfc00b722b7063f2d28dd8c5a36b469462c89da52bcf17ccdda2de6764736f6c63430008110033a26469706673582212200edf974d1735ee81f671df7e60300ab28168b8cb22cc3e59180ef743c4a526c964736f6c63430008110033 \ No newline at end of file diff --git a/itests/contracts/Create2Factory.sol b/itests/contracts/Create2Factory.sol new file mode 100644 index 000000000..ffec40822 --- /dev/null +++ b/itests/contracts/Create2Factory.sol @@ -0,0 +1,67 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.17; +contract Create2Factory { + + bytes32 savedSalt; + + // Returns the address of the newly deployed contract + function deploy( + bytes32 _salt + ) public returns (address) { + // This syntax is a newer way to invoke create2 without assembly, you just need to pass salt + // https://docs.soliditylang.org/en/latest/control-structures.html#salted-contract-creations-create2 + savedSalt = _salt; + (bool success, address ret) = deployDelegateCall(_salt); + require(success); + return ret; + } + + function deployDelegateCall( + bytes32 _salt + ) public returns (bool, address) { + bytes memory data = abi.encodeWithSignature("_deploy(bytes32)", _salt); + (bool success, bytes memory returnedData) = address(this).delegatecall(data); + if(success){ + (address ret) = abi.decode(returnedData, (address)); + return (success, ret); + }else{ + return (success, address(0)); + } + } + + function _deploy(bytes32 _salt) public returns (address) { + // https://solidity-by-example.org/app/create1/ + // This syntax is a newer way to invoke create2 without assembly, you just need to pass salt + // https://docs.soliditylang.org/en/latest/control-structures.html#salted-contract-creations-create2 + return address(new SelfDestruct{salt: _salt}(_salt)); + } + + function test(address _address) public returns (address){ + + // run destroy() on _address + SelfDestruct selfDestruct = SelfDestruct(_address); + selfDestruct.destroy(); + + //verify data can still be accessed + address ret = selfDestruct.sender(); + + // attempt and fail to deploy contract using salt + (bool success, ) = deployDelegateCall(selfDestruct.salt()); + require(!success); + + return ret; + } +} + +contract SelfDestruct { + address public sender; + bytes32 public salt; + constructor(bytes32 _salt) { + sender = tx.origin; + salt=_salt; + } + function destroy() public { + selfdestruct(payable(msg.sender)); + } +} + diff --git a/itests/contracts/DelegatecallStorage.hex b/itests/contracts/DelegatecallStorage.hex index 7ce9ef210..966e9e906 100644 --- a/itests/contracts/DelegatecallStorage.hex +++ b/itests/contracts/DelegatecallStorage.hex @@ -1 +1 @@ -608060405234801561001057600080fd5b50610477806100206000396000f3fe6080604052600436106100345760003560e01c806361bc221a146100395780638ada066e14610064578063d1e0f3081461008f575b600080fd5b34801561004557600080fd5b5061004e6100bf565b60405161005b919061022c565b60405180910390f35b34801561007057600080fd5b506100796100c5565b604051610086919061022c565b60405180910390f35b6100a960048036038101906100a491906102d6565b6100ce565b6040516100b6919061022c565b60405180910390f35b60005481565b60008054905090565b6000808373ffffffffffffffffffffffffffffffffffffffff16836040516024016100f9919061022c565b6040516020818303038152906040527f6466414b000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506040516101839190610387565b600060405180830381855af49150503d80600081146101be576040519150601f19603f3d011682016040523d82523d6000602084013e6101c3565b606091505b5050905080610207576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016101fe90610421565b60405180910390fd5b60005491505092915050565b6000819050919050565b61022681610213565b82525050565b6000602082019050610241600083018461021d565b92915050565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006102778261024c565b9050919050565b6102878161026c565b811461029257600080fd5b50565b6000813590506102a48161027e565b92915050565b6102b381610213565b81146102be57600080fd5b50565b6000813590506102d0816102aa565b92915050565b600080604083850312156102ed576102ec610247565b5b60006102fb85828601610295565b925050602061030c858286016102c1565b9150509250929050565b600081519050919050565b600081905092915050565b60005b8381101561034a57808201518184015260208101905061032f565b60008484015250505050565b600061036182610316565b61036b8185610321565b935061037b81856020860161032c565b80840191505092915050565b60006103938284610356565b915081905092915050565b600082825260208201905092915050565b7f4572726f72206d6573736167653a2044656c656761746563616c6c206661696c60008201527f6564000000000000000000000000000000000000000000000000000000000000602082015250565b600061040b60228361039e565b9150610416826103af565b604082019050919050565b6000602082019050818103600083015261043a816103fe565b905091905056fea26469706673582212203663909b8221e9b87047be99420c00339af1430c085260df209b909ed8e0f05164736f6c63430008110033 \ No newline at end of file +608060405234801561001057600080fd5b5061087e806100206000396000f3fe6080604052600436106100555760003560e01c80630712ede21461005a57806361bc221a1461008a5780637da3c3ab146100b55780638ada066e146100cc578063bed56f47146100f7578063d1e0f30814610127575b600080fd5b610074600480360381019061006f919061060f565b610157565b604051610081919061065e565b60405180910390f35b34801561009657600080fd5b5061009f610298565b6040516100ac919061065e565b60405180910390f35b3480156100c157600080fd5b506100ca61029e565b005b3480156100d857600080fd5b506100e16102e1565b6040516100ee919061065e565b60405180910390f35b610111600480360381019061010c919061060f565b6102ea565b60405161011e919061065e565b60405180910390f35b610141600480360381019061013c919061060f565b610431565b60405161014e919061065e565b60405180910390f35b6000808373ffffffffffffffffffffffffffffffffffffffff1683604051602401610182919061065e565b6040516020818303038152906040527f6466414b000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505060405161020c91906106ea565b600060405180830381855af49150503d8060008114610247576040519150601f19603f3d011682016040523d82523d6000602084013e61024c565b606091505b505090506000610291576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102889061075e565b60405180910390fd5b5092915050565b60005481565b60006102df576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102d69061075e565b60405180910390fd5b565b60008054905090565b6000808373ffffffffffffffffffffffffffffffffffffffff16848460405160240161031792919061078d565b6040516020818303038152906040527fbed56f47000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506040516103a191906106ea565b600060405180830381855af49150503d80600081146103dc576040519150601f19603f3d011682016040523d82523d6000602084013e6103e1565b606091505b5050905080610425576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161041c90610828565b60405180910390fd5b60005491505092915050565b6000808373ffffffffffffffffffffffffffffffffffffffff168360405160240161045c919061065e565b6040516020818303038152906040527f6466414b000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506040516104e691906106ea565b600060405180830381855af49150503d8060008114610521576040519150601f19603f3d011682016040523d82523d6000602084013e610526565b606091505b505090508061056a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161056190610828565b60405180910390fd5b60005491505092915050565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006105a68261057b565b9050919050565b6105b68161059b565b81146105c157600080fd5b50565b6000813590506105d3816105ad565b92915050565b6000819050919050565b6105ec816105d9565b81146105f757600080fd5b50565b600081359050610609816105e3565b92915050565b6000806040838503121561062657610625610576565b5b6000610634858286016105c4565b9250506020610645858286016105fa565b9150509250929050565b610658816105d9565b82525050565b6000602082019050610673600083018461064f565b92915050565b600081519050919050565b600081905092915050565b60005b838110156106ad578082015181840152602081019050610692565b60008484015250505050565b60006106c482610679565b6106ce8185610684565b93506106de81856020860161068f565b80840191505092915050565b60006106f682846106b9565b915081905092915050565b600082825260208201905092915050565b7f696e74656e74696f6e616c6c79207468726f77696e67206572726f7200000000600082015250565b6000610748601c83610701565b915061075382610712565b602082019050919050565b600060208201905081810360008301526107778161073b565b9050919050565b6107878161059b565b82525050565b60006040820190506107a2600083018561077e565b6107af602083018461064f565b9392505050565b7f4572726f72206d6573736167653a2044656c656761746563616c6c206661696c60008201527f6564000000000000000000000000000000000000000000000000000000000000602082015250565b6000610812602283610701565b915061081d826107b6565b604082019050919050565b6000602082019050818103600083015261084181610805565b905091905056fea2646970667358221220b2a3ae7e2a9ffc78e3e2a7aadb2885435c5e51aa9d3f07372a0dffb6238aa1db64736f6c63430008110033 \ No newline at end of file diff --git a/itests/contracts/DelegatecallStorage.sol b/itests/contracts/DelegatecallStorage.sol index 434cd934e..15e672082 100644 --- a/itests/contracts/DelegatecallStorage.sol +++ b/itests/contracts/DelegatecallStorage.sol @@ -5,13 +5,29 @@ contract DelegatecallStorage { uint public counter; function getCounter() public view returns (uint){ - return counter; + return counter; } function setVars(address _contract, uint _counter) public payable returns (uint){ + (bool success, ) = _contract.delegatecall( + abi.encodeWithSignature("setVars(uint256)", _counter) + ); + require(success, 'Error message: Delegatecall failed'); + return counter; + } + function setVarsSelf(address _contract, uint _counter) public payable returns (uint){ + (bool success, ) = _contract.delegatecall( + abi.encodeWithSignature("setVarsSelf(address,uint256)", _contract, _counter) + ); + require(success, 'Error message: Delegatecall failed'); + return counter; + } + function setVarsRevert(address _contract, uint _counter) public payable returns (uint){ (bool success, ) = _contract.delegatecall( abi.encodeWithSignature("setVars(uint256)", _counter) ); - require(success, 'Error message: Delegatecall failed'); - return counter; + require(false,"intentionally throwing error"); + } + function revert() public{ + require(false,"intentionally throwing error"); } } diff --git a/itests/contracts/DeployValueTest.hex b/itests/contracts/DeployValueTest.hex new file mode 100644 index 000000000..535704abf --- /dev/null +++ b/itests/contracts/DeployValueTest.hex @@ -0,0 +1 @@ +60806040523460405161001190610073565b6040518091039082f090508015801561002e573d6000803e3d6000fd5b506000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555061007f565b60c78061031683390190565b6102888061008e6000396000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c80630e3608df146100465780634313b53114610064578063b0d22c6214610082575b600080fd5b61004e6100a0565b60405161005b919061017d565b60405180910390f35b61006c610137565b60405161007991906101d9565b60405180910390f35b61008a61015b565b604051610097919061017d565b60405180910390f35b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166312065fe06040518163ffffffff1660e01b8152600401602060405180830381865afa15801561010e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101329190610225565b905090565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60006007905090565b6000819050919050565b61017781610164565b82525050565b6000602082019050610192600083018461016e565b92915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006101c382610198565b9050919050565b6101d3816101b8565b82525050565b60006020820190506101ee60008301846101ca565b92915050565b600080fd5b61020281610164565b811461020d57600080fd5b50565b60008151905061021f816101f9565b92915050565b60006020828403121561023b5761023a6101f4565b5b600061024984828501610210565b9150509291505056fea2646970667358221220c24abd10dbe58d92bfe62cb351771fcdc45d54241a8ce7085f2a75179c67cd8a64736f6c63430008110033608060405260b5806100126000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c806312065fe014602d575b600080fd5b60336047565b604051603e91906066565b60405180910390f35b600047905090565b6000819050919050565b606081604f565b82525050565b6000602082019050607960008301846059565b9291505056fea26469706673582212207123972a300833ee01aebf99e4bdf8ecf9f01c0d3dd776048bd41803c6855c0e64736f6c63430008110033 \ No newline at end of file diff --git a/itests/contracts/DeployValueTest.sol b/itests/contracts/DeployValueTest.sol new file mode 100644 index 000000000..fe261b014 --- /dev/null +++ b/itests/contracts/DeployValueTest.sol @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.17; + + + +contract DeployValueTest { + address public newContract; + + constructor() payable { + newContract = address(new NewContract{value: msg.value}()); + } + + function getConst() public view returns (uint) { + return 7; + } + + function getNewContractBalance() public view returns (uint) { + return NewContract(newContract).getBalance(); + } +} + +contract NewContract { + constructor() payable { + } + + function getBalance() public view returns (uint) { + return address(this).balance; + } +} diff --git a/itests/contracts/EventMatrix.hex b/itests/contracts/EventMatrix.hex index 2b3ad91ad..be831e397 100644 --- a/itests/contracts/EventMatrix.hex +++ b/itests/contracts/EventMatrix.hex @@ -1 +1 @@ -608060405234801561001057600080fd5b506105eb806100206000396000f3fe608060405234801561001057600080fd5b50600436106100a95760003560e01c8063c755553811610071578063c755553814610198578063cbfc3b58146101c6578063cc6f8faf14610212578063cd5b6c3d14610254578063e2a614731461028c578063fb62b28b146102d8576100a9565b80630919b8be146100ae5780636199074d146100e657806366eef3461461012857806375091b1f14610132578063a63ae81a1461016a575b600080fd5b6100e4600480360360408110156100c457600080fd5b81019080803590602001909291908035906020019092919050505061031a565b005b610126600480360360608110156100fc57600080fd5b8101908080359060200190929190803590602001909291908035906020019092919050505061035d565b005b610130610391565b005b6101686004803603604081101561014857600080fd5b8101908080359060200190929190803590602001909291905050506103bf565b005b6101966004803603602081101561018057600080fd5b81019080803590602001909291905050506103fb565b005b6101c4600480360360208110156101ae57600080fd5b8101908080359060200190929190505050610435565b005b610210600480360360808110156101dc57600080fd5b8101908080359060200190929190803590602001909291908035906020019092919080359060200190929190505050610465565b005b6102526004803603606081101561022857600080fd5b810190808035906020019092919080359060200190929190803590602001909291905050506104ba565b005b61028a6004803603604081101561026a57600080fd5b8101908080359060200190929190803590602001909291905050506104f8565b005b6102d6600480360360808110156102a257600080fd5b810190808035906020019092919080359060200190929190803590602001909291908035906020019092919050505061052a565b005b610318600480360360608110156102ee57600080fd5b8101908080359060200190929190803590602001909291908035906020019092919050505061056a565b005b7f5469c6b769315f5668523937f05ca07d4cc87849432bc5f5907f1d90fa73b9f98282604051808381526020018281526020019250505060405180910390a15050565b8082847fb89dabcdb7ff41f1794c0da92f65ece6c19b6b0caeac5407b2a721efe27c080460405160405180910390a4505050565b7fc3f6f1c76bd4e74ee5782052b0b4f8bd5c50b86c3c5a2f52638e03066e50a91b60405160405180910390a1565b817f6709824ebe5f6e620ca3f4b02a3428e8ce2dc97c550816eaeeb3a342b214bd85826040518082815260200191505060405180910390a25050565b7fc804e53d6048af1b3e6a352e246d5f3864fea9d635ace499e023a58c383b3a88816040518082815260200191505060405180910390a150565b807f44a227a31429ab5eb00daf6611c6422f10571619f2267e0e149e9ebe6d2a5d0560405160405180910390a250565b7f28d45631a87b2a52a9625f8520fa37ff8c4d926cdf17042e241985da5cb7b850848484846040518085815260200184815260200183815260200182815260200194505050505060405180910390a150505050565b81837fcd5fe5fbc1d27b90036997224cea7aa565e3779622867265081f636b3a5ccb08836040518082815260200191505060405180910390a3505050565b80827f232f09cef3babc26e58d1cc1346c0a8bc626ffe600c9605b5d747783eda484a760405160405180910390a35050565b8183857f812e73dbcf7e267f27ecb1383bfc902a6650b41b6e7d03ac265108c369673d95846040518082815260200191505060405180910390a450505050565b7fd4d143faaf60340ad98e1f2c96fc26f5695834c21b5200edad339ee7e9a372cc83838360405180848152602001838152602001828152602001935050505060405180910390a150505056fea265627a7a72315820954561fde80ab925299e0a9f3356b01f64fb1976dd335ac2ebd9367441e29f0564736f6c63430005110032 +608060405234801561001057600080fd5b506106af806100206000396000f3fe608060405234801561001057600080fd5b50600436106100a95760003560e01c8063c755553811610071578063c755553814610128578063cbfc3b5814610144578063cc6f8faf14610160578063cd5b6c3d1461017c578063e2a6147314610198578063fb62b28b146101b4576100a9565b80630919b8be146100ae5780636199074d146100ca57806366eef346146100e657806375091b1f146100f0578063a63ae81a1461010c575b600080fd5b6100c860048036038101906100c39190610483565b6101d0565b005b6100e460048036038101906100df91906104c3565b61020d565b005b6100ee610241565b005b61010a60048036038101906101059190610483565b61026f565b005b61012660048036038101906101219190610516565b6102ab565b005b610142600480360381019061013d9190610516565b6102e5565b005b61015e60048036038101906101599190610543565b610315565b005b61017a600480360381019061017591906104c3565b610358565b005b61019660048036038101906101919190610483565b610396565b005b6101b260048036038101906101ad9190610543565b6103c8565b005b6101ce60048036038101906101c991906104c3565b610408565b005b7f5469c6b769315f5668523937f05ca07d4cc87849432bc5f5907f1d90fa73b9f982826040516102019291906105b9565b60405180910390a15050565b8082847fb89dabcdb7ff41f1794c0da92f65ece6c19b6b0caeac5407b2a721efe27c080460405160405180910390a4505050565b7fc3f6f1c76bd4e74ee5782052b0b4f8bd5c50b86c3c5a2f52638e03066e50a91b60405160405180910390a1565b817f6709824ebe5f6e620ca3f4b02a3428e8ce2dc97c550816eaeeb3a342b214bd858260405161029f91906105e2565b60405180910390a25050565b7fc804e53d6048af1b3e6a352e246d5f3864fea9d635ace499e023a58c383b3a88816040516102da91906105e2565b60405180910390a150565b807f44a227a31429ab5eb00daf6611c6422f10571619f2267e0e149e9ebe6d2a5d0560405160405180910390a250565b7f28d45631a87b2a52a9625f8520fa37ff8c4d926cdf17042e241985da5cb7b8508484848460405161034a94939291906105fd565b60405180910390a150505050565b81837fcd5fe5fbc1d27b90036997224cea7aa565e3779622867265081f636b3a5ccb088360405161038991906105e2565b60405180910390a3505050565b80827f232f09cef3babc26e58d1cc1346c0a8bc626ffe600c9605b5d747783eda484a760405160405180910390a35050565b8183857f812e73dbcf7e267f27ecb1383bfc902a6650b41b6e7d03ac265108c369673d95846040516103fa91906105e2565b60405180910390a450505050565b7fd4d143faaf60340ad98e1f2c96fc26f5695834c21b5200edad339ee7e9a372cc83838360405161043b93929190610642565b60405180910390a1505050565b600080fd5b6000819050919050565b6104608161044d565b811461046b57600080fd5b50565b60008135905061047d81610457565b92915050565b6000806040838503121561049a57610499610448565b5b60006104a88582860161046e565b92505060206104b98582860161046e565b9150509250929050565b6000806000606084860312156104dc576104db610448565b5b60006104ea8682870161046e565b93505060206104fb8682870161046e565b925050604061050c8682870161046e565b9150509250925092565b60006020828403121561052c5761052b610448565b5b600061053a8482850161046e565b91505092915050565b6000806000806080858703121561055d5761055c610448565b5b600061056b8782880161046e565b945050602061057c8782880161046e565b935050604061058d8782880161046e565b925050606061059e8782880161046e565b91505092959194509250565b6105b38161044d565b82525050565b60006040820190506105ce60008301856105aa565b6105db60208301846105aa565b9392505050565b60006020820190506105f760008301846105aa565b92915050565b600060808201905061061260008301876105aa565b61061f60208301866105aa565b61062c60408301856105aa565b61063960608301846105aa565b95945050505050565b600060608201905061065760008301866105aa565b61066460208301856105aa565b61067160408301846105aa565b94935050505056fea26469706673582212201b2f4de851da592b926eb2cd07ccfbbd02270fde6dee2459ba942e5dcf5685d364736f6c63430008110033 \ No newline at end of file diff --git a/itests/contracts/EventMatrix.sol b/itests/contracts/EventMatrix.sol index bd008e27b..f1d63c69e 100644 --- a/itests/contracts/EventMatrix.sol +++ b/itests/contracts/EventMatrix.sol @@ -1,4 +1,5 @@ -pragma solidity ^0.5.0; +// SPDX-License-Identifier: MIT +pragma solidity >=0.5.0; contract EventMatrix { event EventZeroData(); diff --git a/itests/contracts/ExternalRecursiveCallSimple.hex b/itests/contracts/ExternalRecursiveCallSimple.hex new file mode 100644 index 000000000..03d79fe2d --- /dev/null +++ b/itests/contracts/ExternalRecursiveCallSimple.hex @@ -0,0 +1 @@ +608060405234801561001057600080fd5b506101ee806100206000396000f3fe60806040526004361061001e5760003560e01c8063c38e07dd14610023575b600080fd5b61003d600480360381019061003891906100fe565b61003f565b005b60008111156100c0573073ffffffffffffffffffffffffffffffffffffffff1663c38e07dd600183610071919061015a565b6040518263ffffffff1660e01b815260040161008d919061019d565b600060405180830381600087803b1580156100a757600080fd5b505af11580156100bb573d6000803e3d6000fd5b505050505b50565b600080fd5b6000819050919050565b6100db816100c8565b81146100e657600080fd5b50565b6000813590506100f8816100d2565b92915050565b600060208284031215610114576101136100c3565b5b6000610122848285016100e9565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000610165826100c8565b9150610170836100c8565b92508282039050818111156101885761018761012b565b5b92915050565b610197816100c8565b82525050565b60006020820190506101b2600083018461018e565b9291505056fea264697066735822122033d012e17f5d7a62bb724021b5c4e0d109aeb28d1cd5b5c0a0b1b801c0b5032164736f6c63430008110033 \ No newline at end of file diff --git a/itests/contracts/ExternalRecursiveCallSimple.sol b/itests/contracts/ExternalRecursiveCallSimple.sol new file mode 100644 index 000000000..97a27811b --- /dev/null +++ b/itests/contracts/ExternalRecursiveCallSimple.sol @@ -0,0 +1,13 @@ + +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.17; + +contract StackRecCallExp { + function exec1(uint256 r) public payable { + if(r > 0) { + StackRecCallExp(address(this)).exec1(r-1); + } + + return; + } +} diff --git a/itests/contracts/GasLimitSend.hex b/itests/contracts/GasLimitSend.hex new file mode 100644 index 000000000..ac4927d38 --- /dev/null +++ b/itests/contracts/GasLimitSend.hex @@ -0,0 +1 @@ +608060405234801561001057600080fd5b5061027c806100206000396000f3fe6080604052600436106100385760003560e01c80630bc07a88146100435780633da767881461005a578063f0ba84401461008557610039565b5b6100416100c2565b005b34801561004f57600080fd5b506100586100c2565b005b34801561006657600080fd5b5061006f61010d565b60405161007c9190610156565b60405180910390f35b34801561009157600080fd5b506100ac60048036038101906100a791906101a2565b610119565b6040516100b99190610156565b60405180910390f35b60005b606481101561010a5760008190806001815401808255809150506001900390600052602060002001600090919091909150558080610102906101fe565b9150506100c5565b50565b60008080549050905090565b6000818154811061012957600080fd5b906000526020600020016000915090505481565b6000819050919050565b6101508161013d565b82525050565b600060208201905061016b6000830184610147565b92915050565b600080fd5b61017f8161013d565b811461018a57600080fd5b50565b60008135905061019c81610176565b92915050565b6000602082840312156101b8576101b7610171565b5b60006101c68482850161018d565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60006102098261013d565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361023b5761023a6101cf565b5b60018201905091905056fea2646970667358221220c56d78e0c60a01681eee1b76c95e7b214d16a512c944e31cfee71eb727c1e44064736f6c63430008110033 \ No newline at end of file diff --git a/itests/contracts/GasLimitSend.sol b/itests/contracts/GasLimitSend.sol new file mode 100644 index 000000000..b5a91e14d --- /dev/null +++ b/itests/contracts/GasLimitSend.sol @@ -0,0 +1,34 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.17; + +contract GasLimitTest { + address payable receiver; + constructor(){ + address mynew = address(new GasLimitTestReceiver()); + receiver = payable(mynew); + } + function send() public payable{ + receiver.transfer(msg.value); + } + function expensiveTest() public{ + GasLimitTestReceiver(receiver).expensive(); + } + function getDataLength() public returns (uint256) { + return GasLimitTestReceiver(receiver).getDataLength(); + } +} + +contract GasLimitTestReceiver { + uint256[] public data; + fallback() external payable { + expensive(); + } + function expensive() public{ + for (uint256 i = 0; i < 100; i++) { + data.push(i); + } + } + function getDataLength() public view returns (uint256) { + return data.length; + } +} diff --git a/itests/contracts/GasSendTest.hex b/itests/contracts/GasSendTest.hex new file mode 100644 index 000000000..b41be3463 --- /dev/null +++ b/itests/contracts/GasSendTest.hex @@ -0,0 +1 @@ +608060405234801561001057600080fd5b5060b68061001f6000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c80630c55699c14602d575b600080fd5b60336047565b604051603e91906067565b60405180910390f35b60006007905090565b6000819050919050565b6061816050565b82525050565b6000602082019050607a6000830184605a565b9291505056fea2646970667358221220c0f2da1b01178b54afba1ddf14f30307a03cdb66f61b4e1dc342079561db009064736f6c63430008110033 \ No newline at end of file diff --git a/itests/contracts/GasSendTest.sol b/itests/contracts/GasSendTest.sol new file mode 100644 index 000000000..b422bda26 --- /dev/null +++ b/itests/contracts/GasSendTest.sol @@ -0,0 +1,9 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.17; + +contract GasLimitTestReceiver { + function x() public returns (uint256){ + return 7; + } +} + diff --git a/itests/contracts/NotPayable.hex b/itests/contracts/NotPayable.hex new file mode 100644 index 000000000..c08070029 --- /dev/null +++ b/itests/contracts/NotPayable.hex @@ -0,0 +1 @@ +6080604052348015600f57600080fd5b50604780601d6000396000f3fe6080604052348015600f57600080fd5b00fea26469706673582212200cd38951eddebe3692dc8921afb65a04fbe64e10d5e261806330156459bf227264736f6c63430008110033 \ No newline at end of file diff --git a/itests/contracts/NotPayable.sol b/itests/contracts/NotPayable.sol new file mode 100644 index 000000000..9b9a06e08 --- /dev/null +++ b/itests/contracts/NotPayable.sol @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.17; + +//sending eth should fall because fallback is not payable +contract NotPayable { + fallback() external {} +} diff --git a/itests/contracts/RecCall.hex b/itests/contracts/RecCall.hex new file mode 100644 index 000000000..b8de20213 --- /dev/null +++ b/itests/contracts/RecCall.hex @@ -0,0 +1 @@ +608060405234801561001057600080fd5b5061025b806100206000396000f3fe60806040526004361061001e5760003560e01c8063cb7786d714610023575b600080fd5b61003d60048036038101906100389190610129565b61003f565b005b600083036100d15760008111156100cc573073ffffffffffffffffffffffffffffffffffffffff1663cb7786d7838460018561007b91906101ab565b6040518463ffffffff1660e01b8152600401610099939291906101ee565b600060405180830381600087803b1580156100b357600080fd5b505af11580156100c7573d6000803e3d6000fd5b505050505b6100e9565b6100e86001846100e191906101ab565b838361003f565b5b505050565b600080fd5b6000819050919050565b610106816100f3565b811461011157600080fd5b50565b600081359050610123816100fd565b92915050565b600080600060608486031215610142576101416100ee565b5b600061015086828701610114565b935050602061016186828701610114565b925050604061017286828701610114565b9150509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60006101b6826100f3565b91506101c1836100f3565b92508282039050818111156101d9576101d861017c565b5b92915050565b6101e8816100f3565b82525050565b600060608201905061020360008301866101df565b61021060208301856101df565b61021d60408301846101df565b94935050505056fea26469706673582212209a21ff59c642e2970917c07bf498271c2a6df8e3929677952c0c2d8031db15cc64736f6c63430008110033 \ No newline at end of file diff --git a/itests/contracts/RecCall.sol b/itests/contracts/RecCall.sol new file mode 100644 index 000000000..f89611f0e --- /dev/null +++ b/itests/contracts/RecCall.sol @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.17; + +contract StackRecCall { + function exec1(uint256 n, uint256 m, uint256 r) public payable { + if(n == 0) { + if(r > 0) { + StackRecCall(address(this)).exec1(m, m, r-1); + } + + return; + } + + exec1(n-1, m, r); + } +} diff --git a/itests/contracts/Recursive.hex b/itests/contracts/Recursive.hex new file mode 100644 index 000000000..b211aafd9 --- /dev/null +++ b/itests/contracts/Recursive.hex @@ -0,0 +1 @@ +608060405234801561001057600080fd5b506102d9806100206000396000f3fe608060405234801561001057600080fd5b50600436106100575760003560e01c8063032cec451461005c57806372536f3c1461007a57806399fdb86e14610098578063d2aac3ea146100b6578063ec49254c146100d4575b600080fd5b610064610104565b60405161007191906101c7565b60405180910390f35b610082610115565b60405161008f91906101c7565b60405180910390f35b6100a0610126565b6040516100ad91906101c7565b60405180910390f35b6100be610137565b6040516100cb91906101c7565b60405180910390f35b6100ee60048036038101906100e99190610213565b610148565b6040516100fb91906101c7565b60405180910390f35b60006101106001610148565b905090565b6000610121600a610148565b905090565b60006101326002610148565b905090565b60006101436000610148565b905090565b6000808211156101a5577f3110e0ccd510fcbb471c933ad12161c459e8735b5bde2eea61a659c2e2f0a3cc8260405161018191906101c7565b60405180910390a161019e600183610199919061026f565b610148565b90506101a9565b8190505b919050565b6000819050919050565b6101c1816101ae565b82525050565b60006020820190506101dc60008301846101b8565b92915050565b600080fd5b6101f0816101ae565b81146101fb57600080fd5b50565b60008135905061020d816101e7565b92915050565b600060208284031215610229576102286101e2565b5b6000610237848285016101fe565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061027a826101ae565b9150610285836101ae565b925082820390508181111561029d5761029c610240565b5b9291505056fea26469706673582212206178e15eb87e2f766b94ec09a6a860878c93d72a31de225e1684da1755f917c764736f6c63430008110033 \ No newline at end of file diff --git a/itests/contracts/Recursive.sol b/itests/contracts/Recursive.sol new file mode 100644 index 000000000..aa8fe62b0 --- /dev/null +++ b/itests/contracts/Recursive.sol @@ -0,0 +1,26 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.17; + +contract Recursive { + event RecursiveCallEvent(uint256 count); + + function recursive10() public returns (uint256){ + return recursiveCall(10); + } + function recursive2() public returns (uint256){ + return recursiveCall(2); + } + function recursive1() public returns (uint256){ + return recursiveCall(1); + } + function recursive0() public returns (uint256){ + return recursiveCall(0); + } + function recursiveCall(uint256 count) public returns (uint256) { + if (count > 0) { + emit RecursiveCallEvent(count); + return recursiveCall(count-1); + } + return count; + } +} diff --git a/itests/contracts/RecursiveDelegeatecall.hex b/itests/contracts/RecursiveDelegeatecall.hex new file mode 100644 index 000000000..d8337c258 --- /dev/null +++ b/itests/contracts/RecursiveDelegeatecall.hex @@ -0,0 +1 @@ +608060405234801561001057600080fd5b50610459806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80633af3f24f1461003b578063ec49254c14610059575b600080fd5b610043610089565b6040516100509190610221565b60405180910390f35b610073600480360381019061006e919061026d565b61008f565b6040516100809190610221565b60405180910390f35b60005481565b60007faab69767807d0ab32f0099452739da31b76ecd3e8694bb49898829c8bf9d063582306040516100c29291906102db565b60405180910390a160016000808282546100dc9190610333565b9250508190555060018211156101ff576001826100f99190610367565b91506000803073ffffffffffffffffffffffffffffffffffffffff16846040516024016101269190610221565b6040516020818303038152906040527fec49254c000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506040516101b0919061040c565b600060405180830381855af49150503d80600081146101eb576040519150601f19603f3d011682016040523d82523d6000602084013e6101f0565b606091505b50915091508392505050610203565b8190505b919050565b6000819050919050565b61021b81610208565b82525050565b60006020820190506102366000830184610212565b92915050565b600080fd5b61024a81610208565b811461025557600080fd5b50565b60008135905061026781610241565b92915050565b6000602082840312156102835761028261023c565b5b600061029184828501610258565b91505092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006102c58261029a565b9050919050565b6102d5816102ba565b82525050565b60006040820190506102f06000830185610212565b6102fd60208301846102cc565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061033e82610208565b915061034983610208565b925082820190508082111561036157610360610304565b5b92915050565b600061037282610208565b915061037d83610208565b925082820390508181111561039557610394610304565b5b92915050565b600081519050919050565b600081905092915050565b60005b838110156103cf5780820151818401526020810190506103b4565b60008484015250505050565b60006103e68261039b565b6103f081856103a6565b93506104008185602086016103b1565b80840191505092915050565b600061041882846103db565b91508190509291505056fea2646970667358221220e70fbbfaccd3fbb084623d6d06895fba1abc5fefc181215b56ab1e43db79c7fb64736f6c63430008110033 \ No newline at end of file diff --git a/itests/contracts/RecursiveDelegeatecall.sol b/itests/contracts/RecursiveDelegeatecall.sol new file mode 100644 index 000000000..cd1b693c0 --- /dev/null +++ b/itests/contracts/RecursiveDelegeatecall.sol @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.17; + +contract RecursiveDelegatecall { + event RecursiveCallEvent(uint256 count, address self); + uint256 public totalCalls; + + function recursiveCall(uint256 count) public returns (uint256) { + emit RecursiveCallEvent(count, address(this)); + totalCalls += 1; + if (count > 1) { + count -= 1; + (bool success, bytes memory returnedData) = address(this) + .delegatecall( + abi.encodeWithSignature("recursiveCall(uint256)", count) + ); + return count; + } + return count; + } +} diff --git a/itests/contracts/SelfDestruct.hex b/itests/contracts/SelfDestruct.hex new file mode 100644 index 000000000..c2f91b803 --- /dev/null +++ b/itests/contracts/SelfDestruct.hex @@ -0,0 +1 @@ +6080604052348015600f57600080fd5b5060848061001e6000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c806383197ef014602d575b600080fd5b60336035565b005b3373ffffffffffffffffffffffffffffffffffffffff16fffea2646970667358221220d4aa109d42268586e7ce4f0fafb0ebbd04c412c6c7e8c387b009a08ecdff864264736f6c63430008110033 \ No newline at end of file diff --git a/itests/contracts/SelfDestruct.sol b/itests/contracts/SelfDestruct.sol new file mode 100644 index 000000000..6c4ff9188 --- /dev/null +++ b/itests/contracts/SelfDestruct.sol @@ -0,0 +1,8 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.17; + +contract SelfDestruct { + function destroy() public { + selfdestruct(payable(msg.sender)); + } +} diff --git a/itests/contracts/StackFunc.hex b/itests/contracts/StackFunc.hex new file mode 100644 index 000000000..1a3d1202e --- /dev/null +++ b/itests/contracts/StackFunc.hex @@ -0,0 +1 @@ +608060405234801561001057600080fd5b50610162806100206000396000f3fe60806040526004361061001e5760003560e01c8063c38e07dd14610023575b600080fd5b61003d6004803603810190610038919061009c565b61003f565b005b600081031561005e5761005d60018261005891906100f8565b61003f565b5b50565b600080fd5b6000819050919050565b61007981610066565b811461008457600080fd5b50565b60008135905061009681610070565b92915050565b6000602082840312156100b2576100b1610061565b5b60006100c084828501610087565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061010382610066565b915061010e83610066565b9250828203905081811115610126576101256100c9565b5b9291505056fea2646970667358221220ee8f18bfd33b1e0156cfe68e9071dd32960b370c7e63ec53c62dd48e28cb5d3b64736f6c63430008110033 \ No newline at end of file diff --git a/itests/contracts/StackFunc.sol b/itests/contracts/StackFunc.sol new file mode 100644 index 000000000..7084901c6 --- /dev/null +++ b/itests/contracts/StackFunc.sol @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.17; + +contract StackSelf { + function exec1(uint256 n) public payable { + if(n == 0) { + return; + } + + exec1(n-1); + } +} \ No newline at end of file diff --git a/itests/contracts/TestApp.hex b/itests/contracts/TestApp.hex new file mode 100644 index 000000000..bf1830071 --- /dev/null +++ b/itests/contracts/TestApp.hex @@ -0,0 +1 @@ +608060405234801561001057600080fd5b50612e80806100206000396000f3fe60806040523480156200001157600080fd5b5060043610620000a05760003560e01c8063883a8410116200006f578063883a84101462000181578063c483289114620001bb578063d65c239c14620001dd578063dc33b0041462000213578063eae185c4146200024b57620000a0565b806308eaae9614620000a5578063120f83c414620000db5780632db0de8514620001115780637f823290146200014b575b600080fd5b620000c36004803603810190620000bd919062001a74565b62000281565b604051620000d2919062001b1f565b60405180910390f35b620000f96004803603810190620000f3919062001b6d565b620005b4565b60405162000108919062001bb0565b60405180910390f35b6200012f600480360381019062000129919062001bcd565b62000600565b6040516200014295949392919062001c88565b60405180910390f35b62000169600480360381019062000163919062001cec565b620006d3565b60405162000178919062001f0c565b60405180910390f35b6200019f600480360381019062000199919062001f30565b62000d53565b604051620001b295949392919062001c88565b60405180910390f35b620001c562000e68565b604051620001d4919062001bb0565b60405180910390f35b620001fb6004803603810190620001f5919062001f77565b62000e72565b6040516200020a919062001f0c565b60405180910390f35b6200023160048036038101906200022b919062001b6d565b6200127e565b604051620002429392919062001fdb565b60405180910390f35b62000269600480360381019062000263919062001f77565b620012d5565b60405162000278919062001f0c565b60405180910390f35b600080838360405162000294906200176c565b620002a192919062002018565b604051809103906000f080158015620002be573d6000803e3d6000fd5b509050600260003273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160149054906101000a900460ff16620003f4576200032181620016ba565b600260003273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008201518160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060208201518160000160146101000a81548160ff0219169083151502179055506040820151816001019080519060200190620003e59291906200177a565b50606082015181600201559050505b600260003273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600101819080600181540180825580915050600190039060005260206000200160009091909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506001600260003273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206002016000828254620004ec91906200207b565b925050819055506000819080600181540180825580915050600190039060005260206000200160009091909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060018060008282546200056a91906200207b565b925050819055507f1e91349225b89f401c5f81de959b2a1cbc472147eeefbf4e367a6b7d2dfcd3bc32604051620005a2919062001b1f565b60405180910390a18091505092915050565b6000600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600201549050919050565b6000806000606060008086815481106200061f576200061e620020b6565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663909747956040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000695573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190620006c0919062002191565b9450945094509450945091939590929450565b606060008367ffffffffffffffff811115620006f457620006f3620018f2565b5b6040519080825280602002602001820160405280156200073157816020015b6200071d62001809565b815260200190600190039081620007135790505b50905060008390505b8481101562000d4757600260008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060010184826200079391906200207b565b81548110620007a757620007a6620020b6565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16828583620007e1919062002238565b81518110620007f557620007f4620020b6565b5b60200260200101516000019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050600260008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060010184826200088391906200207b565b81548110620008975762000896620020b6565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16632212dbc36040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200090d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000933919062002273565b82858362000942919062002238565b81518110620009565762000955620020b6565b5b60200260200101516020018181525050600260008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206001018482620009b691906200207b565b81548110620009ca57620009c9620020b6565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a8d509ff6040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000a40573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000a669190620022a5565b82858362000a75919062002238565b8151811062000a895762000a88620020b6565b5b60200260200101516040019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050600260008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600101848262000b1791906200207b565b8154811062000b2b5762000b2a620020b6565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16630cb1851a6040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000ba1573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525081019062000bcc9190620022d7565b82858362000bdb919062002238565b8151811062000bef5762000bee620020b6565b5b602002602001015160600181905250600260008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600101848262000c4e91906200207b565b8154811062000c625762000c61620020b6565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663eeb4e3676040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000cd8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000cfe919062002273565b82858362000d0d919062002238565b8151811062000d215762000d20620020b6565b5b60200260200101516080018181525050808062000d3e9062002328565b9150506200073a565b50809150509392505050565b600080600060606000600260008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600101868154811062000db35762000db2620020b6565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663909747956040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000e29573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525081019062000e54919062002191565b945094509450945094509295509295909350565b6000600154905090565b606060008367ffffffffffffffff81111562000e935762000e92620018f2565b5b60405190808252806020026020018201604052801562000ed057816020015b62000ebc62001809565b81526020019060019003908162000eb25790505b50905060008390505b848110156200127357600080858362000ef391906200207b565b8154811062000f075762000f06620020b6565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508083868462000f44919062002238565b8151811062000f585762000f57620020b6565b5b60200260200101516000019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508073ffffffffffffffffffffffffffffffffffffffff16632212dbc36040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000fe2573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062001008919062002273565b83868462001017919062002238565b815181106200102b576200102a620020b6565b5b602002602001015160200181815250508073ffffffffffffffffffffffffffffffffffffffff1663a8d509ff6040518163ffffffff1660e01b8152600401602060405180830381865afa15801562001087573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620010ad9190620022a5565b838684620010bc919062002238565b81518110620010d057620010cf620020b6565b5b60200260200101516040019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508073ffffffffffffffffffffffffffffffffffffffff16630cb1851a6040518163ffffffff1660e01b8152600401600060405180830381865afa1580156200115a573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190620011859190620022d7565b83868462001194919062002238565b81518110620011a857620011a7620020b6565b5b6020026020010151606001819052508073ffffffffffffffffffffffffffffffffffffffff1663eeb4e3676040518163ffffffff1660e01b8152600401602060405180830381865afa15801562001203573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062001229919062002273565b83868462001238919062002238565b815181106200124c576200124b620020b6565b5b602002602001015160800181815250505080806200126a9062002328565b91505062000ed9565b508091505092915050565b60026020528060005260406000206000915090508060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16908060000160149054906101000a900460ff16908060020154905083565b606060008367ffffffffffffffff811115620012f657620012f5620018f2565b5b6040519080825280602002602001820160405280156200133357816020015b6200131f62001809565b815260200190600190039081620013155790505b50905060005b84811015620016af576000806001868460015462001358919062002238565b62001364919062002238565b62001370919062002238565b81548110620013845762001383620020b6565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905080838381518110620013c857620013c7620020b6565b5b60200260200101516000019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508073ffffffffffffffffffffffffffffffffffffffff16632212dbc36040518163ffffffff1660e01b8152600401602060405180830381865afa15801562001452573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062001478919062002273565b8383815181106200148e576200148d620020b6565b5b602002602001015160200181815250508073ffffffffffffffffffffffffffffffffffffffff1663a8d509ff6040518163ffffffff1660e01b8152600401602060405180830381865afa158015620014ea573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620015109190620022a5565b838381518110620015265762001525620020b6565b5b60200260200101516040019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508073ffffffffffffffffffffffffffffffffffffffff16630cb1851a6040518163ffffffff1660e01b8152600401600060405180830381865afa158015620015b0573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190620015db9190620022d7565b838381518110620015f157620015f0620020b6565b5b6020026020010151606001819052508073ffffffffffffffffffffffffffffffffffffffff1663eeb4e3676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200164c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062001672919062002273565b838381518110620016885762001687620020b6565b5b60200260200101516080018181525050508080620016a69062002328565b91505062001339565b508091505092915050565b620016c462001864565b60606003839080600181540180825580915050600190039060005260206000200160009091909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060405180608001604052808473ffffffffffffffffffffffffffffffffffffffff1681526020016001151581526020018281526020016000815250915050919050565b610ad5806200237683390190565b828054828255906000526020600020908101928215620017f6579160200282015b82811115620017f55782518260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550916020019190600101906200179b565b5b509050620018059190620018a4565b5090565b6040518060a00160405280600073ffffffffffffffffffffffffffffffffffffffff16815260200160008152602001600073ffffffffffffffffffffffffffffffffffffffff16815260200160608152602001600081525090565b6040518060800160405280600073ffffffffffffffffffffffffffffffffffffffff16815260200160001515815260200160608152602001600081525090565b5b80821115620018bf576000816000905550600101620018a5565b5090565b6000604051905090565b600080fd5b600080fd5b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6200192c82620018e1565b810181811067ffffffffffffffff821117156200194e576200194d620018f2565b5b80604052505050565b600062001963620018c3565b905062001971828262001921565b919050565b600067ffffffffffffffff821115620019945762001993620018f2565b5b6200199f82620018e1565b9050602081019050919050565b82818337600083830152505050565b6000620019d2620019cc8462001976565b62001957565b905082815260208101848484011115620019f157620019f0620018dc565b5b620019fe848285620019ac565b509392505050565b600082601f83011262001a1e5762001a1d620018d7565b5b813562001a30848260208601620019bb565b91505092915050565b6000819050919050565b62001a4e8162001a39565b811462001a5a57600080fd5b50565b60008135905062001a6e8162001a43565b92915050565b6000806040838503121562001a8e5762001a8d620018cd565b5b600083013567ffffffffffffffff81111562001aaf5762001aae620018d2565b5b62001abd8582860162001a06565b925050602062001ad08582860162001a5d565b9150509250929050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600062001b078262001ada565b9050919050565b62001b198162001afa565b82525050565b600060208201905062001b36600083018462001b0e565b92915050565b62001b478162001afa565b811462001b5357600080fd5b50565b60008135905062001b678162001b3c565b92915050565b60006020828403121562001b865762001b85620018cd565b5b600062001b968482850162001b56565b91505092915050565b62001baa8162001a39565b82525050565b600060208201905062001bc7600083018462001b9f565b92915050565b60006020828403121562001be65762001be5620018cd565b5b600062001bf68482850162001a5d565b91505092915050565b600081519050919050565b600082825260208201905092915050565b60005b8381101562001c3b57808201518184015260208101905062001c1e565b60008484015250505050565b600062001c548262001bff565b62001c60818562001c0a565b935062001c7281856020860162001c1b565b62001c7d81620018e1565b840191505092915050565b600060a08201905062001c9f600083018862001b0e565b62001cae602083018762001b9f565b62001cbd604083018662001b0e565b818103606083015262001cd1818562001c47565b905062001ce2608083018462001b9f565b9695505050505050565b60008060006060848603121562001d085762001d07620018cd565b5b600062001d188682870162001b56565b935050602062001d2b8682870162001a5d565b925050604062001d3e8682870162001a5d565b9150509250925092565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b62001d7f8162001afa565b82525050565b62001d908162001a39565b82525050565b600082825260208201905092915050565b600062001db48262001bff565b62001dc0818562001d96565b935062001dd281856020860162001c1b565b62001ddd81620018e1565b840191505092915050565b600060a08301600083015162001e02600086018262001d74565b50602083015162001e17602086018262001d85565b50604083015162001e2c604086018262001d74565b506060830151848203606086015262001e46828262001da7565b915050608083015162001e5d608086018262001d85565b508091505092915050565b600062001e76838362001de8565b905092915050565b6000602082019050919050565b600062001e988262001d48565b62001ea4818562001d53565b93508360208202850162001eb88562001d64565b8060005b8581101562001efa578484038952815162001ed8858262001e68565b945062001ee58362001e7e565b925060208a0199505060018101905062001ebc565b50829750879550505050505092915050565b6000602082019050818103600083015262001f28818462001e8b565b905092915050565b6000806040838503121562001f4a5762001f49620018cd565b5b600062001f5a8582860162001b56565b925050602062001f6d8582860162001a5d565b9150509250929050565b6000806040838503121562001f915762001f90620018cd565b5b600062001fa18582860162001a5d565b925050602062001fb48582860162001a5d565b9150509250929050565b60008115159050919050565b62001fd58162001fbe565b82525050565b600060608201905062001ff2600083018662001b0e565b62002001602083018562001fca565b62002010604083018462001b9f565b949350505050565b6000604082019050818103600083015262002034818562001c47565b905062002045602083018462001b9f565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000620020888262001a39565b9150620020958362001a39565b9250828201905080821115620020b057620020af6200204c565b5b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600081519050620020f68162001b3c565b92915050565b6000815190506200210d8162001a43565b92915050565b60006200212a620021248462001976565b62001957565b905082815260208101848484011115620021495762002148620018dc565b5b6200215684828562001c1b565b509392505050565b600082601f830112620021765762002175620018d7565b5b81516200218884826020860162002113565b91505092915050565b600080600080600060a08688031215620021b057620021af620018cd565b5b6000620021c088828901620020e5565b9550506020620021d388828901620020fc565b9450506040620021e688828901620020e5565b935050606086015167ffffffffffffffff8111156200220a5762002209620018d2565b5b62002218888289016200215e565b92505060806200222b88828901620020fc565b9150509295509295909350565b6000620022458262001a39565b9150620022528362001a39565b92508282039050818111156200226d576200226c6200204c565b5b92915050565b6000602082840312156200228c576200228b620018cd565b5b60006200229c84828501620020fc565b91505092915050565b600060208284031215620022be57620022bd620018cd565b5b6000620022ce84828501620020e5565b91505092915050565b600060208284031215620022f057620022ef620018cd565b5b600082015167ffffffffffffffff811115620023115762002310620018d2565b5b6200231f848285016200215e565b91505092915050565b6000620023358262001a39565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036200236a57620023696200204c565b5b60018201905091905056fe60806040523480156200001157600080fd5b5060405162000ad538038062000ad583398181016040528101906200003791906200026e565b32600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555042600081905550816002908162000090919062000515565b50806003819055505050620005fc565b6000604051905090565b600080fd5b600080fd5b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6200010982620000be565b810181811067ffffffffffffffff821117156200012b576200012a620000cf565b5b80604052505050565b600062000140620000a0565b90506200014e8282620000fe565b919050565b600067ffffffffffffffff821115620001715762000170620000cf565b5b6200017c82620000be565b9050602081019050919050565b60005b83811015620001a95780820151818401526020810190506200018c565b60008484015250505050565b6000620001cc620001c68462000153565b62000134565b905082815260208101848484011115620001eb57620001ea620000b9565b5b620001f884828562000189565b509392505050565b600082601f830112620002185762000217620000b4565b5b81516200022a848260208601620001b5565b91505092915050565b6000819050919050565b620002488162000233565b81146200025457600080fd5b50565b60008151905062000268816200023d565b92915050565b60008060408385031215620002885762000287620000aa565b5b600083015167ffffffffffffffff811115620002a957620002a8620000af565b5b620002b78582860162000200565b9250506020620002ca8582860162000257565b9150509250929050565b600081519050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b600060028204905060018216806200032757607f821691505b6020821081036200033d576200033c620002df565b5b50919050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b600060088302620003a77fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8262000368565b620003b3868362000368565b95508019841693508086168417925050509392505050565b6000819050919050565b6000620003f6620003f0620003ea8462000233565b620003cb565b62000233565b9050919050565b6000819050919050565b6200041283620003d5565b6200042a6200042182620003fd565b84845462000375565b825550505050565b600090565b6200044162000432565b6200044e81848462000407565b505050565b5b8181101562000476576200046a60008262000437565b60018101905062000454565b5050565b601f821115620004c5576200048f8162000343565b6200049a8462000358565b81016020851015620004aa578190505b620004c2620004b98562000358565b83018262000453565b50505b505050565b600082821c905092915050565b6000620004ea60001984600802620004ca565b1980831691505092915050565b6000620005058383620004d7565b9150826002028217905092915050565b6200052082620002d4565b67ffffffffffffffff8111156200053c576200053b620000cf565b5b6200054882546200030e565b620005558282856200047a565b600060209050601f8311600181146200058d576000841562000578578287015190505b620005848582620004f7565b865550620005f4565b601f1984166200059d8662000343565b60005b82811015620005c757848901518255600182019150602085019450602081019050620005a0565b86831015620005e75784890151620005e3601f891682620004d7565b8355505b6001600288020188555050505b505050505050565b6104c9806200060c6000396000f3fe608060405234801561001057600080fd5b50600436106100575760003560e01c80630cb1851a1461005c5780632212dbc31461007a5780639097479514610098578063a8d509ff146100ba578063eeb4e367146100d8575b600080fd5b6100646100f6565b6040516100719190610327565b60405180910390f35b610082610188565b60405161008f9190610362565b60405180910390f35b6100a0610191565b6040516100b19594939291906103be565b60405180910390f35b6100c2610263565b6040516100cf9190610418565b60405180910390f35b6100e061028d565b6040516100ed9190610362565b60405180910390f35b60606002805461010590610462565b80601f016020809104026020016040519081016040528092919081815260200182805461013190610462565b801561017e5780601f106101535761010080835404028352916020019161017e565b820191906000526020600020905b81548152906001019060200180831161016157829003601f168201915b5050505050905090565b60008054905090565b60008060006060600030600054600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1660026003548180546101d290610462565b80601f01602080910402602001604051908101604052809291908181526020018280546101fe90610462565b801561024b5780601f106102205761010080835404028352916020019161024b565b820191906000526020600020905b81548152906001019060200180831161022e57829003601f168201915b50505050509150945094509450945094509091929394565b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6000600354905090565b600081519050919050565b600082825260208201905092915050565b60005b838110156102d15780820151818401526020810190506102b6565b60008484015250505050565b6000601f19601f8301169050919050565b60006102f982610297565b61030381856102a2565b93506103138185602086016102b3565b61031c816102dd565b840191505092915050565b6000602082019050818103600083015261034181846102ee565b905092915050565b6000819050919050565b61035c81610349565b82525050565b60006020820190506103776000830184610353565b92915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006103a88261037d565b9050919050565b6103b88161039d565b82525050565b600060a0820190506103d360008301886103af565b6103e06020830187610353565b6103ed60408301866103af565b81810360608301526103ff81856102ee565b905061040e6080830184610353565b9695505050505050565b600060208201905061042d60008301846103af565b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b6000600282049050600182168061047a57607f821691505b60208210810361048d5761048c610433565b5b5091905056fea264697066735822122096ba86e2c854094a9f7774cf59534923c219cc0ab6e812963e86557d6743467c64736f6c63430008110033a2646970667358221220b58cd7b4415159e845caf380c6ffa231afa779fa9b6af3b83d7b80ca521527a464736f6c63430008110033 \ No newline at end of file diff --git a/itests/contracts/TestApp.sol b/itests/contracts/TestApp.sol new file mode 100644 index 000000000..072eb7a61 --- /dev/null +++ b/itests/contracts/TestApp.sol @@ -0,0 +1,211 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.2; +pragma experimental ABIEncoderV2; + +contract Test_contract { + uint256 timestamp; + address sender; + string text; + uint256 number; + + constructor(string memory _text, uint256 _number) { + sender = tx.origin; + timestamp = block.timestamp; + text = _text; + number = _number; + } + + function getall() + public + view + returns ( + address, + uint256, + address, + string memory, + uint256 + ) + { + return (address(this), timestamp, sender, text, number); + } + + function get_timestamp() public view returns (uint256) { + return timestamp; + } + + function get_sender() public view returns (address) { + return sender; + } + + function get_text() public view returns (string memory) { + return text; + } + + function get_number() public view returns (uint256) { + return number; + } +} + +contract App { + address[] Test_list; + uint256 Test_list_length; + + function get_Test_list_length() public view returns (uint256) { + return Test_list_length; + } + + struct Test_getter { + address _address; + uint256 timestamp; + address sender; + string text; + uint256 number; + } + + function get_Test_N(uint256 index) + public + view + returns ( + address, + uint256, + address, + string memory, + uint256 + ) + { + return Test_contract(Test_list[index]).getall(); + } + + function get_first_Test_N(uint256 count, uint256 offset) + public + view + returns (Test_getter[] memory) + { + Test_getter[] memory getters = new Test_getter[](count); + for (uint256 i = offset; i < count; i++) { + Test_contract myTest = Test_contract(Test_list[i + offset]); + getters[i - offset]._address = address(myTest); + getters[i - offset].timestamp = myTest.get_timestamp(); + getters[i - offset].sender = myTest.get_sender(); + getters[i - offset].text = myTest.get_text(); + getters[i - offset].number = myTest.get_number(); + } + return getters; + } + + function get_last_Test_N(uint256 count, uint256 offset) + public + view + returns (Test_getter[] memory) + { + Test_getter[] memory getters = new Test_getter[](count); + for (uint256 i = 0; i < count; i++) { + Test_contract myTest = + Test_contract(Test_list[Test_list_length - i - offset - 1]); + getters[i]._address = address(myTest); + + getters[i].timestamp = myTest.get_timestamp(); + getters[i].sender = myTest.get_sender(); + getters[i].text = myTest.get_text(); + getters[i].number = myTest.get_number(); + } + return getters; + } + + function get_Test_user_length(address user) public view returns (uint256) { + return user_map[user].Test_list_length; + } + + function get_Test_user_N(address user, uint256 index) + public + view + returns ( + address, + uint256, + address, + string memory, + uint256 + ) + { + return Test_contract(user_map[user].Test_list[index]).getall(); + } + + function get_last_Test_user_N( + address user, + uint256 count, + uint256 offset + ) public view returns (Test_getter[] memory) { + Test_getter[] memory getters = new Test_getter[](count); + + for (uint256 i = offset; i < count; i++) { + getters[i - offset]._address = user_map[user].Test_list[i + offset]; + getters[i - offset].timestamp = Test_contract( + user_map[user].Test_list[i + offset] + ) + .get_timestamp(); + getters[i - offset].sender = Test_contract( + user_map[user].Test_list[i + offset] + ) + .get_sender(); + getters[i - offset].text = Test_contract( + user_map[user].Test_list[i + offset] + ) + .get_text(); + getters[i - offset].number = Test_contract( + user_map[user].Test_list[i + offset] + ) + .get_number(); + } + return getters; + } + + struct UserInfo { + address owner; + bool exists; + address[] Test_list; + uint256 Test_list_length; + } + mapping(address => UserInfo) public user_map; + address[] UserInfoList; + uint256 UserInfoListLength; + + event NewTest(address sender); + + function new_Test(string memory text, uint256 number) + public + returns (address) + { + address mynew = + address(new Test_contract({_text: text, _number: number})); + + if (!user_map[tx.origin].exists) { + user_map[tx.origin] = create_user_on_new_Test(mynew); + } + user_map[tx.origin].Test_list.push(mynew); + + user_map[tx.origin].Test_list_length += 1; + + Test_list.push(mynew); + Test_list_length += 1; + + emit NewTest(tx.origin); + + return mynew; + } + + function create_user_on_new_Test(address addr) + private + returns (UserInfo memory) + { + address[] memory Test_list_; + + UserInfoList.push(addr); + return + UserInfo({ + exists: true, + owner: addr, + Test_list: Test_list_, + Test_list_length: 0 + }); + } +} diff --git a/itests/contracts/ValueSender.hex b/itests/contracts/ValueSender.hex new file mode 100644 index 000000000..ed69dacdb --- /dev/null +++ b/itests/contracts/ValueSender.hex @@ -0,0 +1 @@ +608060405234801561001057600080fd5b506106dc806100206000396000f3fe60806040526004361061002d5760003560e01c8063dbdc275d14610072578063fd75295a1461009d5761006d565b3661006d577f34fb9cb8f63eaccc6c0beefc202db703e529c3bf9ce83f485b398af7fd679308333460405161006392919061020f565b60405180910390a1005b600080fd5b34801561007e57600080fd5b506100876100b9565b6040516100949190610238565b60405180910390f35b6100b760048036038101906100b29190610296565b610125565b005b6000806040516100c8906101a8565b604051809103906000f0801580156100e4573d6000803e3d6000fd5b5090507f8db3b20eed31d927a4f613b5c11765212e129cf726d025649650665569ea683b816040516101169190610238565b60405180910390a18091505090565b7f34fb9cb8f63eaccc6c0beefc202db703e529c3bf9ce83f485b398af7fd6793088134604051610156929190610322565b60405180910390a18073ffffffffffffffffffffffffffffffffffffffff166108fc349081150290604051600060405180830381858888f193505050501580156101a4573d6000803e3d6000fd5b5050565b61035b8061034c83390190565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006101e0826101b5565b9050919050565b6101f0816101d5565b82525050565b6000819050919050565b610209816101f6565b82525050565b600060408201905061022460008301856101e7565b6102316020830184610200565b9392505050565b600060208201905061024d60008301846101e7565b92915050565b600080fd5b6000610263826101b5565b9050919050565b61027381610258565b811461027e57600080fd5b50565b6000813590506102908161026a565b92915050565b6000602082840312156102ac576102ab610253565b5b60006102ba84828501610281565b91505092915050565b6000819050919050565b60006102e86102e36102de846101b5565b6102c3565b6101b5565b9050919050565b60006102fa826102cd565b9050919050565b600061030c826102ef565b9050919050565b61031c81610301565b82525050565b60006040820190506103376000830185610313565b6103446020830184610200565b939250505056fe608060405234801561001057600080fd5b50336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506102fb806100606000396000f3fe60806040526004361061002d5760003560e01c806337cb6570146100725780639cb8a26a1461007c5761006d565b3661006d577fe1494f56a1ccfd8c7361f2ca5b8fd2b1a2fe11773821ac29534f09f4a0637d603334604051610063929190610214565b60405180910390a1005b600080fd5b61007a610093565b005b34801561008857600080fd5b50610091610155565b005b7f76cff203b0794a9e9013657ecb172f2d6e8de5941fd11a6bfbc0fb6014a5f07960008054906101000a900473ffffffffffffffffffffffffffffffffffffffff16476040516100e492919061029c565b60405180910390a160008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc479081150290604051600060405180830381858888f19350505050158015610152573d6000803e3d6000fd5b50565b7f1cbd47e7b0f55dc1a45ba8ebada53eaa1712b3e3e86f49a12c008ff22334569060405160405180910390a160008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16ff5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006101e5826101ba565b9050919050565b6101f5816101da565b82525050565b6000819050919050565b61020e816101fb565b82525050565b600060408201905061022960008301856101ec565b6102366020830184610205565b9392505050565b6000819050919050565b600061026261025d610258846101ba565b61023d565b6101ba565b9050919050565b600061027482610247565b9050919050565b600061028682610269565b9050919050565b6102968161027b565b82525050565b60006040820190506102b1600083018561028d565b6102be6020830184610205565b939250505056fea2646970667358221220bdf21908b1c91973a8440fe81130e0077cf83c8f8e9a053d8a0c3063391aa40764736f6c63430008110033a26469706673582212202e514fe078dfcf4f1142a088c57cfa71ada74d72ee0cc4a46b7e1141cdbaeeed64736f6c63430008110033 \ No newline at end of file diff --git a/itests/contracts/ValueSender.sol b/itests/contracts/ValueSender.sol new file mode 100644 index 000000000..1be682b25 --- /dev/null +++ b/itests/contracts/ValueSender.sol @@ -0,0 +1,54 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.17; + +contract A { + event LogCreateB(address _bAddress); + event LogSendEthA(address _bAddress, uint _value); + event LogReceiveEthA(address _bAddress, uint _value); + + // Function to create a new instance of contract B and return its address + function createB() public returns (address) { + address bAddress = address(new B()); + emit LogCreateB(bAddress); + return bAddress; + } + + // Payable method to accept eth and an address for B and send the eth to B + function sendEthToB(address payable _bAddress) public payable { + emit LogSendEthA(_bAddress, msg.value); + _bAddress.transfer(msg.value); + } + + // Payable function to accept the eth + receive() external payable { + emit LogSendEthA(msg.sender, msg.value); + } +} + +contract B { + event LogSelfDestruct(); + event LogSendEthToA(address _to, uint _value); + event LogReceiveEth(address from, uint value); + address payable creator; + + constructor(){ + creator = payable(msg.sender); + } + + // Payable function to accept the eth + receive() external payable { + emit LogReceiveEth(msg.sender, msg.value); + } + + // Method to send ether to contract A + function sendEthToA() public payable { + emit LogSendEthToA(creator,address(this).balance); + creator.transfer(address(this).balance); + } + + // Self destruct method to send eth to its creator + function selfDestruct() public { + emit LogSelfDestruct(); + selfdestruct(creator); + } +} diff --git a/itests/contracts/compile.sh b/itests/contracts/compile.sh old mode 100755 new mode 100644 index 1163ad9a6..029bff46c --- a/itests/contracts/compile.sh +++ b/itests/contracts/compile.sh @@ -1,6 +1,19 @@ +set -eu +set -o pipefail + #use the solc compiler https://docs.soliditylang.org/en/v0.8.17/installing-solidity.html # to compile all of the .sol files to their corresponding evm binary files stored as .hex # solc outputs to stdout a format that we just want to grab the last line of and then remove the trailing newline on that line -find -type f -name \*.sol -print0 | - xargs -0 -I{} bash -c 'solc --bin {} |tail -n1 | tr -d "\n" > $(echo {} | sed -e s/.sol$/.hex/)' +find . -name \*.sol -print0 | + xargs -0 -I{} bash -euc -o pipefail 'solc --bin {} |tail -n1 | tr -d "\n" > $(echo {} | sed -e s/.sol$/.hex/)' + + + +#for these contracts we have 2 contracts in the same solidity file +#this command grabs the correct bytecode for us +for filename in Constructor TestApp ValueSender Create2Factory DeployValueTest; do + echo $filename + solc --bin $filename.sol | tail -n5|head -n1 | tr -d "\n" > $filename.hex +done + diff --git a/itests/decode_params_test.go b/itests/decode_params_test.go new file mode 100644 index 000000000..6a4a8c681 --- /dev/null +++ b/itests/decode_params_test.go @@ -0,0 +1,124 @@ +// stm: #integration +package itests + +import ( + "bytes" + "encoding/json" + "testing" + + "github.com/stretchr/testify/require" + + "github.com/filecoin-project/go-address" + "github.com/filecoin-project/go-state-types/abi" + actorstypes "github.com/filecoin-project/go-state-types/actors" + "github.com/filecoin-project/go-state-types/builtin" + "github.com/filecoin-project/go-state-types/builtin/v10/eam" + "github.com/filecoin-project/go-state-types/cbor" + "github.com/filecoin-project/go-state-types/manifest" + + "github.com/filecoin-project/lotus/build" + "github.com/filecoin-project/lotus/chain/actors" + "github.com/filecoin-project/lotus/cli" +) + +type marshalable interface { + cbor.Marshaler + cbor.Unmarshaler +} + +type testCase struct { + ActorKey string + MethodNum abi.MethodNum + retVal marshalable +} + +// Used './lotus state replay --show-trace ' to get params/return to decode. +func TestDecodeParams(t *testing.T) { + testCborBytes := abi.CborBytes([]byte{1, 2, 3}) + + testCases := []testCase{ + { + ActorKey: manifest.EvmKey, + MethodNum: builtin.MethodsEVM.InvokeContract, + retVal: &testCborBytes, + }, + { + ActorKey: manifest.EamKey, + MethodNum: builtin.MethodsEAM.CreateExternal, + retVal: &testCborBytes, + }, + } + + for _, _tc := range testCases { + tc := _tc + t.Run(tc.ActorKey+" "+tc.MethodNum.String(), func(t *testing.T) { + av, err := actorstypes.VersionForNetwork(build.TestNetworkVersion) + require.NoError(t, err) + actorCodeCid, found := actors.GetActorCodeID(av, tc.ActorKey) + require.True(t, found) + + buf := bytes.NewBuffer(nil) + if err := tc.retVal.MarshalCBOR(buf); err != nil { + t.Fatal(err) + } + + paramString, err := cli.JsonParams(actorCodeCid, tc.MethodNum, buf.Bytes()) + require.NoError(t, err) + + jsonParams, err := json.MarshalIndent(tc.retVal, "", " ") + require.NoError(t, err) + require.Equal(t, string(jsonParams), paramString) + }) + } +} + +func TestDecodeReturn(t *testing.T) { + testCborBytes := abi.CborBytes([]byte{1, 2, 3}) + + robustAddr, err := address.NewIDAddress(12345) + require.NoError(t, err) + + //ethAddr, err := ethtypes.ParseEthAddress("d4c5fb16488Aa48081296299d54b0c648C9333dA") + //require.NoError(t, err) + + testReturn := eam.CreateExternalReturn{ + ActorID: 12345, + RobustAddress: &robustAddr, + EthAddress: [20]byte{}, + } + + testCases := []testCase{ + { + ActorKey: manifest.EvmKey, + MethodNum: builtin.MethodsEVM.InvokeContract, + retVal: &testCborBytes, + }, + { + ActorKey: manifest.EamKey, + MethodNum: builtin.MethodsEAM.CreateExternal, + retVal: &testReturn, + }, + } + + for _, _tc := range testCases { + tc := _tc + t.Run(tc.ActorKey+" "+tc.MethodNum.String(), func(t *testing.T) { + av, err := actorstypes.VersionForNetwork(build.TestNetworkVersion) + require.NoError(t, err) + actorCodeCid, found := actors.GetActorCodeID(av, tc.ActorKey) + require.True(t, found) + + buf := bytes.NewBuffer(nil) + if err := tc.retVal.MarshalCBOR(buf); err != nil { + t.Fatal(err) + } + + returnString, err := cli.JsonReturn(actorCodeCid, tc.MethodNum, buf.Bytes()) + require.NoError(t, err) + + jsonReturn, err := json.MarshalIndent(tc.retVal, "", " ") + require.NoError(t, err) + require.Equal(t, string(jsonReturn), returnString) + }) + } +} diff --git a/itests/eth_account_abstraction_test.go b/itests/eth_account_abstraction_test.go index 692e4646f..e6d9723bf 100644 --- a/itests/eth_account_abstraction_test.go +++ b/itests/eth_account_abstraction_test.go @@ -11,6 +11,8 @@ import ( "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/big" + builtin2 "github.com/filecoin-project/go-state-types/builtin" + "github.com/filecoin-project/go-state-types/builtin/v10/eam" "github.com/filecoin-project/go-state-types/exitcode" "github.com/filecoin-project/lotus/api" @@ -70,7 +72,7 @@ func TestEthAccountAbstraction(t *testing.T) { msgFromPlaceholder, err = client.GasEstimateMessageGas(ctx, msgFromPlaceholder, nil, types.EmptyTSK) require.NoError(t, err) - txArgs, err := ethtypes.EthTxArgsFromMessage(msgFromPlaceholder) + txArgs, err := ethtypes.EthTxArgsFromUnsignedEthMessage(msgFromPlaceholder) require.NoError(t, err) digest, err := txArgs.ToRlpUnsignedMsg() @@ -106,7 +108,7 @@ func TestEthAccountAbstraction(t *testing.T) { msgFromPlaceholder, err = client.GasEstimateMessageGas(ctx, msgFromPlaceholder, nil, types.EmptyTSK) require.NoError(t, err) - txArgs, err = ethtypes.EthTxArgsFromMessage(msgFromPlaceholder) + txArgs, err = ethtypes.EthTxArgsFromUnsignedEthMessage(msgFromPlaceholder) require.NoError(t, err) digest, err = txArgs.ToRlpUnsignedMsg() @@ -178,7 +180,7 @@ func TestEthAccountAbstractionFailure(t *testing.T) { require.NoError(t, err) msgFromPlaceholder.Value = abi.TokenAmount(types.MustParseFIL("1000")) - txArgs, err := ethtypes.EthTxArgsFromMessage(msgFromPlaceholder) + txArgs, err := ethtypes.EthTxArgsFromUnsignedEthMessage(msgFromPlaceholder) require.NoError(t, err) digest, err := txArgs.ToRlpUnsignedMsg() @@ -216,7 +218,7 @@ func TestEthAccountAbstractionFailure(t *testing.T) { msgFromPlaceholder, err = client.GasEstimateMessageGas(ctx, msgFromPlaceholder, nil, types.EmptyTSK) require.NoError(t, err) - txArgs, err = ethtypes.EthTxArgsFromMessage(msgFromPlaceholder) + txArgs, err = ethtypes.EthTxArgsFromUnsignedEthMessage(msgFromPlaceholder) require.NoError(t, err) digest, err = txArgs.ToRlpUnsignedMsg() @@ -313,3 +315,51 @@ func TestEthAccountAbstractionFailsFromEvmActor(t *testing.T) { require.Error(t, err, "expected gas estimation to fail") require.Contains(t, err.Error(), "SysErrSenderInvalid") } + +func TestEthAccountManagerPermissions(t *testing.T) { + kit.QuietMiningLogs() + + client, _, ens := kit.EnsembleMinimal(t, kit.MockProofs(), kit.ThroughRPC()) + ens.InterconnectAll().BeginMining(10 * time.Millisecond) + + ctx, cancel := context.WithTimeout(context.Background(), time.Minute) + defer cancel() + + // setup f1/f3/f4 accounts + + wsp, err := client.WalletNew(ctx, types.KTSecp256k1) + require.NoError(t, err) + + wbl, err := client.WalletNew(ctx, types.KTBLS) + require.NoError(t, err) + + wdl, err := client.WalletNew(ctx, types.KTDelegated) + require.NoError(t, err) + + def := client.DefaultKey.Address + + // send some funds + client.ExpectSend(ctx, def, wsp, types.FromFil(10), "") + client.ExpectSend(ctx, def, wbl, types.FromFil(10), "") + client.ExpectSend(ctx, def, wdl, types.FromFil(10), "") + require.NoError(t, err) + + // make sure that EAM only allows CreateExternal to be called by accounts + client.ExpectSend(ctx, wsp, builtin2.EthereumAddressManagerActorAddr, big.Zero(), "not one of supported (18)", client.MakeSendCall(builtin2.MethodsEAM.Create, &eam.CreateParams{Nonce: 0})) + client.ExpectSend(ctx, wbl, builtin2.EthereumAddressManagerActorAddr, big.Zero(), "not one of supported (18)", client.MakeSendCall(builtin2.MethodsEAM.Create, &eam.CreateParams{Nonce: 0})) + client.ExpectSend(ctx, wdl, builtin2.EthereumAddressManagerActorAddr, big.Zero(), "not one of supported (18)", client.MakeSendCall(builtin2.MethodsEAM.Create, &eam.CreateParams{Nonce: 0})) + + client.ExpectSend(ctx, wsp, builtin2.EthereumAddressManagerActorAddr, big.Zero(), "not one of supported (18)", client.MakeSendCall(builtin2.MethodsEAM.Create2, &eam.Create2Params{})) + client.ExpectSend(ctx, wbl, builtin2.EthereumAddressManagerActorAddr, big.Zero(), "not one of supported (18)", client.MakeSendCall(builtin2.MethodsEAM.Create2, &eam.Create2Params{})) + client.ExpectSend(ctx, wdl, builtin2.EthereumAddressManagerActorAddr, big.Zero(), "not one of supported (18)", client.MakeSendCall(builtin2.MethodsEAM.Create2, &eam.Create2Params{})) + + contractHex, err := os.ReadFile("contracts/SimpleCoin.hex") + require.NoError(t, err) + contract, err := hex.DecodeString(string(contractHex)) + require.NoError(t, err) + contractParams := abi.CborBytes(contract) + + client.ExpectSend(ctx, wsp, builtin2.EthereumAddressManagerActorAddr, big.Zero(), "", client.MakeSendCall(builtin2.MethodsEAM.CreateExternal, &contractParams)) + client.ExpectSend(ctx, wbl, builtin2.EthereumAddressManagerActorAddr, big.Zero(), "", client.MakeSendCall(builtin2.MethodsEAM.CreateExternal, &contractParams)) + client.ExpectSend(ctx, wdl, builtin2.EthereumAddressManagerActorAddr, big.Zero(), "", client.MakeSendCall(builtin2.MethodsEAM.CreateExternal, &contractParams)) +} diff --git a/itests/eth_config_test.go b/itests/eth_config_test.go new file mode 100644 index 000000000..8b74d011a --- /dev/null +++ b/itests/eth_config_test.go @@ -0,0 +1,62 @@ +// stm: #integration +package itests + +import ( + "context" + "testing" + + "github.com/stretchr/testify/require" + + "github.com/filecoin-project/lotus/chain/types/ethtypes" + "github.com/filecoin-project/lotus/itests/kit" + "github.com/filecoin-project/lotus/node/impl/full" +) + +func TestEthFilterAPIDisabledViaConfig(t *testing.T) { + ctx := context.Background() + + kit.QuietMiningLogs() + + // pass kit.DisableEthRPC() so RealTimeFilterAPI will not be enabled + client, _, _ := kit.EnsembleMinimal(t, kit.MockProofs(), kit.ThroughRPC(), kit.DisableEthRPC()) + + _, err := client.EthNewPendingTransactionFilter(ctx) + require.NotNil(t, err) + require.Equal(t, err.Error(), full.ErrModuleDisabled.Error()) + + _, err = client.EthGetLogs(ctx, ðtypes.EthFilterSpec{}) + require.NotNil(t, err) + require.Equal(t, err.Error(), full.ErrModuleDisabled.Error()) + + _, err = client.EthGetFilterChanges(ctx, ethtypes.EthFilterID{}) + require.NotNil(t, err) + require.Equal(t, err.Error(), full.ErrModuleDisabled.Error()) + + _, err = client.EthGetFilterLogs(ctx, ethtypes.EthFilterID{}) + require.NotNil(t, err) + require.Equal(t, err.Error(), full.ErrModuleDisabled.Error()) + + _, err = client.EthNewFilter(ctx, ðtypes.EthFilterSpec{}) + require.NotNil(t, err) + require.Equal(t, err.Error(), full.ErrModuleDisabled.Error()) + + _, err = client.EthNewBlockFilter(ctx) + require.NotNil(t, err) + require.Equal(t, err.Error(), full.ErrModuleDisabled.Error()) + + _, err = client.EthNewPendingTransactionFilter(ctx) + require.NotNil(t, err) + require.Equal(t, err.Error(), full.ErrModuleDisabled.Error()) + + _, err = client.EthUninstallFilter(ctx, ethtypes.EthFilterID{}) + require.NotNil(t, err) + require.Equal(t, err.Error(), full.ErrModuleDisabled.Error()) + + _, err = client.EthSubscribe(ctx, []byte("{}")) + require.NotNil(t, err) + require.Equal(t, err.Error(), full.ErrModuleDisabled.Error()) + + _, err = client.EthUnsubscribe(ctx, ethtypes.EthSubscriptionID{}) + require.NotNil(t, err) + require.Equal(t, err.Error(), full.ErrModuleDisabled.Error()) +} diff --git a/itests/eth_conformance_test.go b/itests/eth_conformance_test.go new file mode 100644 index 000000000..c190e03fe --- /dev/null +++ b/itests/eth_conformance_test.go @@ -0,0 +1,514 @@ +package itests + +import ( + "bytes" + "context" + "encoding/binary" + "encoding/hex" + "encoding/json" + "os" + "strings" + "testing" + "time" + + "github.com/go-openapi/spec" + "github.com/gregdhill/go-openrpc/parse" + orpctypes "github.com/gregdhill/go-openrpc/types" + manet "github.com/multiformats/go-multiaddr/net" + "github.com/stretchr/testify/require" + "github.com/xeipuuv/gojsonschema" + + "github.com/filecoin-project/go-address" + "github.com/filecoin-project/go-jsonrpc" + "github.com/filecoin-project/go-state-types/big" + + "github.com/filecoin-project/lotus/build" + "github.com/filecoin-project/lotus/chain/types" + "github.com/filecoin-project/lotus/chain/types/ethtypes" + "github.com/filecoin-project/lotus/chain/wallet/key" + "github.com/filecoin-project/lotus/itests/kit" +) + +// TODO generate this using reflection. It's the same as the EthAPI except every return value is a json.RawMessage +type ethAPIRaw struct { + EthAccounts func(context.Context) (json.RawMessage, error) + EthBlockNumber func(context.Context) (json.RawMessage, error) + EthCall func(context.Context, ethtypes.EthCall, string) (json.RawMessage, error) + EthChainId func(context.Context) (json.RawMessage, error) + EthEstimateGas func(context.Context, ethtypes.EthCall) (json.RawMessage, error) + EthFeeHistory func(context.Context, ethtypes.EthUint64, string, []float64) (json.RawMessage, error) + EthGasPrice func(context.Context) (json.RawMessage, error) + EthGetBalance func(context.Context, ethtypes.EthAddress, string) (json.RawMessage, error) + EthGetBlockByHash func(context.Context, ethtypes.EthHash, bool) (json.RawMessage, error) + EthGetBlockByNumber func(context.Context, string, bool) (json.RawMessage, error) + EthGetBlockTransactionCountByHash func(context.Context, ethtypes.EthHash) (json.RawMessage, error) + EthGetBlockTransactionCountByNumber func(context.Context, ethtypes.EthUint64) (json.RawMessage, error) + EthGetCode func(context.Context, ethtypes.EthAddress, string) (json.RawMessage, error) + EthGetFilterChanges func(context.Context, ethtypes.EthFilterID) (json.RawMessage, error) + EthGetFilterLogs func(context.Context, ethtypes.EthFilterID) (json.RawMessage, error) + EthGetLogs func(context.Context, *ethtypes.EthFilterSpec) (json.RawMessage, error) + EthGetStorageAt func(context.Context, ethtypes.EthAddress, ethtypes.EthBytes, string) (json.RawMessage, error) + EthGetTransactionByBlockHashAndIndex func(context.Context, ethtypes.EthHash, ethtypes.EthUint64) (json.RawMessage, error) + EthGetTransactionByBlockNumberAndIndex func(context.Context, ethtypes.EthUint64, ethtypes.EthUint64) (json.RawMessage, error) + EthGetTransactionByHash func(context.Context, *ethtypes.EthHash) (json.RawMessage, error) + EthGetTransactionCount func(context.Context, ethtypes.EthAddress, string) (json.RawMessage, error) + EthGetTransactionReceipt func(context.Context, ethtypes.EthHash) (json.RawMessage, error) + EthMaxPriorityFeePerGas func(context.Context) (json.RawMessage, error) + EthNewBlockFilter func(context.Context) (json.RawMessage, error) + EthNewFilter func(context.Context, *ethtypes.EthFilterSpec) (json.RawMessage, error) + EthNewPendingTransactionFilter func(context.Context) (json.RawMessage, error) + EthSendRawTransaction func(context.Context, ethtypes.EthBytes) (json.RawMessage, error) + EthSubscribe func(context.Context, string, *ethtypes.EthSubscriptionParams) (json.RawMessage, error) + EthUninstallFilter func(context.Context, ethtypes.EthFilterID) (json.RawMessage, error) + EthUnsubscribe func(context.Context, ethtypes.EthSubscriptionID) (json.RawMessage, error) +} + +func TestEthOpenRPCConformance(t *testing.T) { + kit.QuietAllLogsExcept("events", "messagepool") + + // specs/eth_openrpc.json is built from https://github.com/ethereum/execution-apis + specJSON, err := os.ReadFile("specs/eth_openrpc.json") + require.NoError(t, err) + + specParsed := orpctypes.NewOpenRPCSpec1() + err = json.Unmarshal(specJSON, specParsed) + require.NoError(t, err) + parse.GetTypes(specParsed, specParsed.Objects) + + schemas := make(map[string]spec.Schema) + for _, method := range specParsed.Methods { + if method.Result != nil { + schemas[method.Name] = method.Result.Schema + } + } + + ctx, cancel := context.WithTimeout(context.Background(), time.Minute) + defer cancel() + + client, _, ens := kit.EnsembleMinimal(t, kit.MockProofs(), kit.ThroughRPC(), kit.WithEthRPC()) + ens.InterconnectAll().BeginMining(10 * time.Millisecond) + + contractHex, err := os.ReadFile("contracts/EventMatrix.hex") + require.NoError(t, err) + + // strip any trailing newlines from the file + contractHex = bytes.TrimRight(contractHex, "\n") + + contractBin, err := hex.DecodeString(string(contractHex)) + require.NoError(t, err) + + senderKey, senderEthAddr, senderFilAddr := client.EVM().NewAccount() + _, receiverEthAddr, _ := client.EVM().NewAccount() + kit.SendFunds(ctx, t, client, senderFilAddr, types.FromFil(1000)) + + deployerAddr, err := client.EVM().WalletDefaultAddress(ctx) + require.NoError(t, err) + + pendingTransactionFilterID, err := client.EthNewPendingTransactionFilter(ctx) + require.NoError(t, err) + + blockFilterID, err := client.EthNewBlockFilter(ctx) + require.NoError(t, err) + + filterAllLogs := kit.NewEthFilterBuilder().FromBlockEpoch(0).Filter() + + logFilterID, err := client.EthNewFilter(ctx, filterAllLogs) + require.NoError(t, err) + + uninstallableFilterID, err := client.EthNewFilter(ctx, filterAllLogs) + require.NoError(t, err) + + rawSignedEthTx := createRawSignedEthTx(ctx, t, client, senderEthAddr, receiverEthAddr, senderKey, contractBin) + + result := client.EVM().DeployContract(ctx, deployerAddr, contractBin) + contractAddr, err := address.NewIDAddress(result.ActorID) + require.NoError(t, err) + + contractEthAddr := ethtypes.EthAddress(result.EthAddress) + + messageWithEvents, blockHashWithMessage, blockNumberWithMessage := waitForMessageWithEvents(ctx, t, client, deployerAddr, contractAddr) + + // create a json-rpc client that returns raw json responses + var ethapi ethAPIRaw + + netAddr, err := manet.ToNetAddr(client.ListenAddr) + require.NoError(t, err) + rpcAddr := "ws://" + netAddr.String() + "/rpc/v1" + + closer, err := jsonrpc.NewClient(ctx, rpcAddr, "Filecoin", ðapi, nil) + require.NoError(t, err) + defer closer() + + testCases := []struct { + method string + variant string // suffix applied to the test name to distinguish different variants of a method call + call func(*ethAPIRaw) (json.RawMessage, error) + skipReason string + }{ + // Alphabetical order + + { + method: "eth_accounts", + call: func(a *ethAPIRaw) (json.RawMessage, error) { + return ethapi.EthAccounts(context.Background()) + }, + }, + + { + method: "eth_blockNumber", + call: func(a *ethAPIRaw) (json.RawMessage, error) { + return ethapi.EthBlockNumber(context.Background()) + }, + }, + + { + method: "eth_call", + variant: "latest", + call: func(a *ethAPIRaw) (json.RawMessage, error) { + return ethapi.EthCall(context.Background(), ethtypes.EthCall{ + From: &senderEthAddr, + Data: contractBin, + }, "latest") + }, + }, + + { + method: "eth_chainId", + call: func(a *ethAPIRaw) (json.RawMessage, error) { + return ethapi.EthChainId(context.Background()) + }, + }, + + { + method: "eth_estimateGas", + call: func(a *ethAPIRaw) (json.RawMessage, error) { + return ethapi.EthEstimateGas(context.Background(), ethtypes.EthCall{ + From: &senderEthAddr, + Data: contractBin, + }) + }, + }, + + { + method: "eth_feeHistory", + call: func(a *ethAPIRaw) (json.RawMessage, error) { + return ethapi.EthFeeHistory(context.Background(), ethtypes.EthUint64(2), "", nil) + }, + }, + + { + method: "eth_gasPrice", + call: func(a *ethAPIRaw) (json.RawMessage, error) { + return ethapi.EthGasPrice(context.Background()) + }, + }, + + { + method: "eth_getBalance", + variant: "blocknumber", + call: func(a *ethAPIRaw) (json.RawMessage, error) { + return ethapi.EthGetBalance(context.Background(), contractEthAddr, "0x0") + }, + }, + + { + method: "eth_getBlockByHash", + variant: "txhashes", + call: func(a *ethAPIRaw) (json.RawMessage, error) { + return ethapi.EthGetBlockByHash(context.Background(), blockHashWithMessage, false) + }, + }, + + { + method: "eth_getBlockByHash", + variant: "txfull", + call: func(a *ethAPIRaw) (json.RawMessage, error) { + return ethapi.EthGetBlockByHash(context.Background(), blockHashWithMessage, true) + }, + }, + + { + method: "eth_getBlockByNumber", + variant: "earliest", + call: func(a *ethAPIRaw) (json.RawMessage, error) { + return ethapi.EthGetBlockByNumber(context.Background(), "earliest", true) + }, + skipReason: "earliest block is not supported", + }, + + { + method: "eth_getBlockByNumber", + variant: "pending", + call: func(a *ethAPIRaw) (json.RawMessage, error) { + return ethapi.EthGetBlockByNumber(context.Background(), "pending", true) + }, + }, + + { + method: "eth_getBlockByNumber", + call: func(a *ethAPIRaw) (json.RawMessage, error) { + return ethapi.EthGetBlockByNumber(context.Background(), blockNumberWithMessage.Hex(), true) + }, + }, + + { + method: "eth_getBlockTransactionCountByHash", + call: func(a *ethAPIRaw) (json.RawMessage, error) { + return ethapi.EthGetBlockTransactionCountByHash(context.Background(), blockHashWithMessage) + }, + }, + + { + method: "eth_getBlockTransactionCountByNumber", + call: func(a *ethAPIRaw) (json.RawMessage, error) { + return ethapi.EthGetBlockTransactionCountByNumber(context.Background(), blockNumberWithMessage) + }, + }, + + { + method: "eth_getCode", + variant: "blocknumber", + call: func(a *ethAPIRaw) (json.RawMessage, error) { + return ethapi.EthGetCode(context.Background(), contractEthAddr, blockNumberWithMessage.Hex()) + }, + }, + + { + method: "eth_getFilterChanges", + variant: "pendingtransaction", + call: func(a *ethAPIRaw) (json.RawMessage, error) { + return a.EthGetFilterChanges(ctx, pendingTransactionFilterID) + }, + }, + + { + method: "eth_getFilterChanges", + variant: "block", + call: func(a *ethAPIRaw) (json.RawMessage, error) { + return a.EthGetFilterChanges(ctx, blockFilterID) + }, + }, + + { + method: "eth_getFilterChanges", + variant: "logs", + call: func(a *ethAPIRaw) (json.RawMessage, error) { + return a.EthGetFilterChanges(ctx, logFilterID) + }, + }, + + { + method: "eth_getFilterLogs", + call: func(a *ethAPIRaw) (json.RawMessage, error) { + return a.EthGetFilterLogs(ctx, logFilterID) + }, + }, + + { + method: "eth_getLogs", + call: func(a *ethAPIRaw) (json.RawMessage, error) { + return ethapi.EthGetLogs(context.Background(), filterAllLogs) + }, + }, + + { + method: "eth_getStorageAt", + variant: "blocknumber", + call: func(a *ethAPIRaw) (json.RawMessage, error) { + return ethapi.EthGetStorageAt(context.Background(), contractEthAddr, ethtypes.EthBytes{0}, "0x0") + }, + }, + + { + method: "eth_getTransactionByBlockHashAndIndex", + call: func(a *ethAPIRaw) (json.RawMessage, error) { + return ethapi.EthGetTransactionByBlockHashAndIndex(context.Background(), blockHashWithMessage, ethtypes.EthUint64(0)) + }, + skipReason: "unimplemented", + }, + + { + method: "eth_getTransactionByBlockNumberAndIndex", + call: func(a *ethAPIRaw) (json.RawMessage, error) { + return ethapi.EthGetTransactionByBlockNumberAndIndex(context.Background(), blockNumberWithMessage, ethtypes.EthUint64(0)) + }, + skipReason: "unimplemented", + }, + + { + method: "eth_getTransactionByHash", + call: func(a *ethAPIRaw) (json.RawMessage, error) { + return ethapi.EthGetTransactionByHash(context.Background(), &messageWithEvents) + }, + }, + + { + method: "eth_getTransactionCount", + variant: "blocknumber", + call: func(a *ethAPIRaw) (json.RawMessage, error) { + return ethapi.EthGetTransactionCount(context.Background(), senderEthAddr, blockNumberWithMessage.Hex()) + }, + }, + + { + method: "eth_getTransactionReceipt", + call: func(a *ethAPIRaw) (json.RawMessage, error) { + return ethapi.EthGetTransactionReceipt(context.Background(), messageWithEvents) + }, + }, + + { + method: "eth_maxPriorityFeePerGas", + call: func(a *ethAPIRaw) (json.RawMessage, error) { + return ethapi.EthMaxPriorityFeePerGas(context.Background()) + }, + }, + + { + method: "eth_newBlockFilter", + call: func(a *ethAPIRaw) (json.RawMessage, error) { + return ethapi.EthNewBlockFilter(context.Background()) + }, + }, + + { + method: "eth_newFilter", + call: func(a *ethAPIRaw) (json.RawMessage, error) { + return ethapi.EthNewFilter(context.Background(), filterAllLogs) + }, + }, + + { + method: "eth_newPendingTransactionFilter", + call: func(a *ethAPIRaw) (json.RawMessage, error) { + return ethapi.EthNewPendingTransactionFilter(context.Background()) + }, + }, + + { + method: "eth_sendRawTransaction", + call: func(a *ethAPIRaw) (json.RawMessage, error) { + return ethapi.EthSendRawTransaction(context.Background(), rawSignedEthTx) + }, + }, + { + method: "eth_uninstallFilter", + call: func(a *ethAPIRaw) (json.RawMessage, error) { + return a.EthUninstallFilter(ctx, uninstallableFilterID) + }, + }, + } + + for _, tc := range testCases { + tc := tc + name := tc.method + if tc.variant != "" { + name += "_" + tc.variant + } + t.Run(name, func(t *testing.T) { + if tc.skipReason != "" { + t.Skipf(tc.skipReason) + } + + schema, ok := schemas[tc.method] + require.True(t, ok, "method not found in openrpc spec") + + resp, err := tc.call(ðapi) + require.NoError(t, err) + + respJson, err := json.Marshal(resp) + require.NoError(t, err) + + loader := gojsonschema.NewGoLoader(schema) + resploader := gojsonschema.NewBytesLoader(respJson) + result, err := gojsonschema.Validate(loader, resploader) + require.NoError(t, err) + + if !result.Valid() { + if len(result.Errors()) == 1 && strings.Contains(result.Errors()[0].String(), "Must validate one and only one schema (oneOf)") { + // Ignore this error, since it seems the openrpc spec can't handle it + // New transaction and block filters have the same schema: an array of 32 byte hashes + return + } + + niceRespJson, err := json.MarshalIndent(resp, "", " ") + if err == nil { + t.Logf("response was %s", niceRespJson) + } + + schemaJson, err := json.MarshalIndent(schema, "", " ") + if err == nil { + t.Logf("schema was %s", schemaJson) + } + + // check against https://www.jsonschemavalidator.net/ + + for _, desc := range result.Errors() { + t.Logf("- %s\n", desc) + } + + t.Errorf("response did not validate") + } + }) + } +} + +func createRawSignedEthTx(ctx context.Context, t *testing.T, client *kit.TestFullNode, senderEthAddr ethtypes.EthAddress, receiverEthAddr ethtypes.EthAddress, senderKey *key.Key, contractBin []byte) []byte { + gaslimit, err := client.EthEstimateGas(ctx, ethtypes.EthCall{ + From: &senderEthAddr, + Data: contractBin, + }) + require.NoError(t, err) + + maxPriorityFeePerGas, err := client.EthMaxPriorityFeePerGas(ctx) + require.NoError(t, err) + + tx := ethtypes.EthTxArgs{ + ChainID: build.Eip155ChainId, + Value: big.NewInt(100), + Nonce: 0, + To: &receiverEthAddr, + MaxFeePerGas: types.NanoFil, + MaxPriorityFeePerGas: big.Int(maxPriorityFeePerGas), + GasLimit: int(gaslimit), + V: big.Zero(), + R: big.Zero(), + S: big.Zero(), + } + + client.EVM().SignTransaction(&tx, senderKey.PrivateKey) + signed, err := tx.ToRlpSignedMsg() + require.NoError(t, err) + return signed +} + +func waitForMessageWithEvents(ctx context.Context, t *testing.T, client *kit.TestFullNode, sender address.Address, target address.Address) (ethtypes.EthHash, ethtypes.EthHash, ethtypes.EthUint64) { + vals := []uint64{44, 27, 19, 12} + inputData := []byte{} + for _, v := range vals { + buf := make([]byte, 32) + binary.BigEndian.PutUint64(buf[24:], v) + inputData = append(inputData, buf...) + } + + // send a message that exercises event logs + ret, err := client.EVM().InvokeSolidity(ctx, sender, target, kit.EventMatrixContract.Fn["logEventThreeIndexedWithData"], inputData) + require.NoError(t, err) + require.True(t, ret.Receipt.ExitCode.IsSuccess(), "contract execution failed") + + msgHash, err := client.EthGetTransactionHashByCid(ctx, ret.Message) + require.NoError(t, err) + require.NotNil(t, msgHash) + + ts, err := client.ChainGetTipSet(ctx, ret.TipSet) + require.NoError(t, err) + + blockNumber := ethtypes.EthUint64(ts.Height()) + + tsCid, err := ts.Key().Cid() + require.NoError(t, err) + + blockHash, err := ethtypes.EthHashFromCid(tsCid) + require.NoError(t, err) + return *msgHash, blockHash, blockNumber +} diff --git a/itests/eth_deploy_test.go b/itests/eth_deploy_test.go index 98038de7b..bbdadb1d5 100644 --- a/itests/eth_deploy_test.go +++ b/itests/eth_deploy_test.go @@ -11,12 +11,16 @@ import ( "time" "github.com/stretchr/testify/require" + "golang.org/x/crypto/sha3" "github.com/filecoin-project/go-state-types/big" "github.com/filecoin-project/go-state-types/manifest" + gstStore "github.com/filecoin-project/go-state-types/store" "github.com/filecoin-project/lotus/api" + "github.com/filecoin-project/lotus/blockstore" "github.com/filecoin-project/lotus/build" + "github.com/filecoin-project/lotus/chain/actors/builtin/evm" "github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types/ethtypes" "github.com/filecoin-project/lotus/itests/kit" @@ -219,4 +223,32 @@ func TestDeployment(t *testing.T) { require.NoError(t, err) client.AssertActorType(ctx, contractAddr, "evm") + + // Check bytecode and bytecode hash match. + contractAct, err := client.StateGetActor(ctx, contractAddr, types.EmptyTSK) + require.NoError(t, err) + + bs := blockstore.NewAPIBlockstore(client) + ctxStore := gstStore.WrapBlockStore(ctx, bs) + + evmSt, err := evm.Load(ctxStore, contractAct) + require.NoError(t, err) + + byteCodeCid, err := evmSt.GetBytecodeCID() + require.NoError(t, err) + + byteCode, err := bs.Get(ctx, byteCodeCid) + require.NoError(t, err) + + byteCodeHashChain, err := evmSt.GetBytecodeHash() + require.NoError(t, err) + + hasher := sha3.NewLegacyKeccak256() + hasher.Write(byteCode.RawData()) + byteCodeHash := hasher.Sum(nil) + require.Equal(t, byteCodeHashChain[:], byteCodeHash) + + byteCodeSt, err := evmSt.GetBytecode() + require.NoError(t, err) + require.Equal(t, byteCode.RawData(), byteCodeSt) } diff --git a/itests/eth_filter_test.go b/itests/eth_filter_test.go index aba61f934..59e0e6337 100644 --- a/itests/eth_filter_test.go +++ b/itests/eth_filter_test.go @@ -1,4 +1,3 @@ -// stm: #integration package itests import ( @@ -8,6 +7,7 @@ import ( "encoding/hex" "encoding/json" "fmt" + "math/bits" "os" "sort" "strconv" @@ -17,11 +17,10 @@ import ( "github.com/ipfs/go-cid" "github.com/stretchr/testify/require" - cbg "github.com/whyrusleeping/cbor-gen" - "golang.org/x/crypto/sha3" "golang.org/x/xerrors" "github.com/filecoin-project/go-address" + "github.com/filecoin-project/go-jsonrpc" "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/big" @@ -30,55 +29,9 @@ import ( "github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types/ethtypes" "github.com/filecoin-project/lotus/itests/kit" + res "github.com/filecoin-project/lotus/lib/result" ) -// SolidityContractDef holds information about one of the test contracts -type SolidityContractDef struct { - Filename string // filename of the hex of the contract, e.g. contracts/EventMatrix.hex - Fn map[string][]byte // mapping of function names to 32-bit selector - Ev map[string][]byte // mapping of event names to 256-bit signature hashes -} - -var EventMatrixContract = SolidityContractDef{ - Filename: "contracts/EventMatrix.hex", - Fn: map[string][]byte{ - "logEventZeroData": ethFunctionHash("logEventZeroData()"), - "logEventOneData": ethFunctionHash("logEventOneData(uint256)"), - "logEventTwoData": ethFunctionHash("logEventTwoData(uint256,uint256)"), - "logEventThreeData": ethFunctionHash("logEventThreeData(uint256,uint256,uint256)"), - "logEventFourData": ethFunctionHash("logEventFourData(uint256,uint256,uint256,uint256)"), - "logEventOneIndexed": ethFunctionHash("logEventOneIndexed(uint256)"), - "logEventTwoIndexed": ethFunctionHash("logEventTwoIndexed(uint256,uint256)"), - "logEventThreeIndexed": ethFunctionHash("logEventThreeIndexed(uint256,uint256,uint256)"), - "logEventOneIndexedWithData": ethFunctionHash("logEventOneIndexedWithData(uint256,uint256)"), - "logEventTwoIndexedWithData": ethFunctionHash("logEventTwoIndexedWithData(uint256,uint256,uint256)"), - "logEventThreeIndexedWithData": ethFunctionHash("logEventThreeIndexedWithData(uint256,uint256,uint256,uint256)"), - }, - Ev: map[string][]byte{ - "EventZeroData": ethTopicHash("EventZeroData()"), - "EventOneData": ethTopicHash("EventOneData(uint256)"), - "EventTwoData": ethTopicHash("EventTwoData(uint256,uint256)"), - "EventThreeData": ethTopicHash("EventThreeData(uint256,uint256,uint256)"), - "EventFourData": ethTopicHash("EventFourData(uint256,uint256,uint256,uint256)"), - "EventOneIndexed": ethTopicHash("EventOneIndexed(uint256)"), - "EventTwoIndexed": ethTopicHash("EventTwoIndexed(uint256,uint256)"), - "EventThreeIndexed": ethTopicHash("EventThreeIndexed(uint256,uint256,uint256)"), - "EventOneIndexedWithData": ethTopicHash("EventOneIndexedWithData(uint256,uint256)"), - "EventTwoIndexedWithData": ethTopicHash("EventTwoIndexedWithData(uint256,uint256,uint256)"), - "EventThreeIndexedWithData": ethTopicHash("EventThreeIndexedWithData(uint256,uint256,uint256,uint256)"), - }, -} - -var EventsContract = SolidityContractDef{ - Filename: "contracts/events.bin", - Fn: map[string][]byte{ - "log_zero_data": {0x00, 0x00, 0x00, 0x00}, - "log_zero_nodata": {0x00, 0x00, 0x00, 0x01}, - "log_four_data": {0x00, 0x00, 0x00, 0x02}, - }, - Ev: map[string][]byte{}, -} - func TestEthNewPendingTransactionFilter(t *testing.T) { ctx, cancel := context.WithTimeout(context.Background(), time.Minute) defer cancel() @@ -287,7 +240,7 @@ func TestEthNewBlockFilter(t *testing.T) { } } -func TestEthNewFilterCatchAll(t *testing.T) { +func TestEthNewFilterDefaultSpec(t *testing.T) { require := require.New(t) kit.QuietAllLogsExcept("events", "messagepool") @@ -338,7 +291,7 @@ func TestEthNewFilterCatchAll(t *testing.T) { paddedEthBytes([]byte{0x33, 0x33}), paddedEthBytes([]byte{0x44, 0x44}), }, - Data: paddedEthBytes([]byte{0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88}), + Data: []byte{0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88}, }, { Address: ethContractAddr, @@ -348,7 +301,7 @@ func TestEthNewFilterCatchAll(t *testing.T) { paddedEthBytes([]byte{0x33, 0x33}), paddedEthBytes([]byte{0x44, 0x44}), }, - Data: paddedEthBytes([]byte{0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88}), + Data: []byte{0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88}, }, { Address: ethContractAddr, @@ -358,7 +311,7 @@ func TestEthNewFilterCatchAll(t *testing.T) { paddedEthBytes([]byte{0x33, 0x33}), paddedEthBytes([]byte{0x44, 0x44}), }, - Data: paddedEthBytes([]byte{0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88}), + Data: []byte{0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88}, }, } @@ -367,7 +320,7 @@ func TestEthNewFilterCatchAll(t *testing.T) { AssertEthLogs(t, elogs, expected, received) } -func TestEthGetLogsAll(t *testing.T) { +func TestEthGetLogsBasic(t *testing.T) { require := require.New(t) kit.QuietAllLogsExcept("events", "messagepool") @@ -383,7 +336,7 @@ func TestEthGetLogsAll(t *testing.T) { ethContractAddr, received := invokeLogFourData(t, client, invocations) // Build filter spec - spec := newEthFilterBuilder(). + spec := kit.NewEthFilterBuilder(). FromBlockEpoch(0). Topic1OneOf(paddedEthHash([]byte{0x11, 0x11})). Filter() @@ -397,7 +350,7 @@ func TestEthGetLogsAll(t *testing.T) { paddedEthBytes([]byte{0x33, 0x33}), paddedEthBytes([]byte{0x44, 0x44}), }, - Data: paddedEthBytes([]byte{0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88}), + Data: []byte{0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88}, }, } @@ -410,45 +363,7 @@ func TestEthGetLogsAll(t *testing.T) { AssertEthLogs(t, elogs, expected, received) } -func TestEthGetLogsByTopic(t *testing.T) { - require := require.New(t) - - kit.QuietAllLogsExcept("events", "messagepool") - - blockTime := 100 * time.Millisecond - - client, _, ens := kit.EnsembleMinimal(t, kit.MockProofs(), kit.ThroughRPC()) - ens.InterconnectAll().BeginMining(blockTime) - - invocations := 1 - ethContractAddr, received := invokeLogFourData(t, client, invocations) - - // find log by known topic1 - var spec ethtypes.EthFilterSpec - err := json.Unmarshal([]byte(`{"fromBlock":"0x0","topics":["0x0000000000000000000000000000000000000000000000000000000000001111"]}`), &spec) - require.NoError(err) - - res, err := client.EthGetLogs(context.Background(), &spec) - require.NoError(err) - - expected := []ExpectedEthLog{ - { - Address: ethContractAddr, - Topics: []ethtypes.EthBytes{ - paddedEthBytes([]byte{0x11, 0x11}), - paddedEthBytes([]byte{0x22, 0x22}), - paddedEthBytes([]byte{0x33, 0x33}), - paddedEthBytes([]byte{0x44, 0x44}), - }, - Data: paddedEthBytes([]byte{0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88}), - }, - } - elogs, err := parseEthLogsFromFilterResult(res) - require.NoError(err) - AssertEthLogs(t, elogs, expected, received) -} - -func TestEthSubscribeLogs(t *testing.T) { +func TestEthSubscribeLogsNoTopicSpec(t *testing.T) { require := require.New(t) kit.QuietAllLogsExcept("events", "messagepool") @@ -477,15 +392,15 @@ func TestEthSubscribeLogs(t *testing.T) { t.Logf("actor ID address is %s", idAddr) // install filter - respCh, err := client.EthSubscribe(ctx, "logs", nil) + subId, err := client.EthSubscribe(ctx, res.Wrap[jsonrpc.RawParams](json.Marshal(ethtypes.EthSubscribeParams{EventType: "logs"})).Assert(require.NoError)) require.NoError(err) - subResponses := []ethtypes.EthSubscriptionResponse{} - go func() { - for resp := range respCh { - subResponses = append(subResponses, resp) - } - }() + var subResponses []ethtypes.EthSubscriptionResponse + err = client.EthSubRouter.AddSub(ctx, subId, func(ctx context.Context, resp *ethtypes.EthSubscriptionResponse) error { + subResponses = append(subResponses, *resp) + return nil + }) + require.NoError(err) const iterations = 10 ethContractAddr, messages := invokeLogFourData(t, client, iterations) @@ -500,7 +415,7 @@ func TestEthSubscribeLogs(t *testing.T) { paddedEthBytes([]byte{0x33, 0x33}), paddedEthBytes([]byte{0x44, 0x44}), }, - Data: paddedEthBytes([]byte{0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88}), + Data: []byte{0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88}, } } @@ -509,6 +424,51 @@ func TestEthSubscribeLogs(t *testing.T) { AssertEthLogs(t, elogs, expected, messages) } +func TestTxReceiptBloom(t *testing.T) { + blockTime := 50 * time.Millisecond + client, _, ens := kit.EnsembleMinimal( + t, + kit.MockProofs(), + kit.ThroughRPC()) + ens.InterconnectAll().BeginMining(blockTime) + + ctx, cancel := context.WithTimeout(context.Background(), time.Minute) + defer cancel() + + fromAddr, idAddr := client.EVM().DeployContractFromFilename(ctx, "contracts/EventMatrix.hex") + + _, ml, err := client.EVM().InvokeContractByFuncName(ctx, fromAddr, idAddr, "logEventZeroData()", nil) + require.NoError(t, err) + + th, err := client.EthGetTransactionHashByCid(ctx, ml.Message) + require.NoError(t, err) + require.NotNil(t, th) + + receipt, err := client.EthGetTransactionReceipt(ctx, *th) + require.NoError(t, err) + require.NotNil(t, receipt) + require.Len(t, receipt.Logs, 1) + + // computed by calling EventMatrix/logEventZeroData in remix + // note this only contains topic bits + matchMask := "0x00000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + + maskBytes, err := hex.DecodeString(matchMask[2:]) + require.NoError(t, err) + + bitsSet := 0 + for i, maskByte := range maskBytes { + bitsSet += bits.OnesCount8(receipt.LogsBloom[i]) + + if maskByte > 0 { + require.True(t, maskByte&receipt.LogsBloom[i] > 0) + } + } + + // 3 bits from the topic, 3 bits from the address + require.Equal(t, 6, bitsSet) +} + func TestEthGetLogs(t *testing.T) { require := require.New(t) kit.QuietAllLogsExcept("events", "messagepool") @@ -522,539 +482,10 @@ func TestEthGetLogs(t *testing.T) { defer cancel() // Set up the test fixture with a standard list of invocations - contract1, contract2, messages := invokeEventMatrix(ctx, t, client) + contract1, contract2, invocations := prepareEventMatrixInvocations(ctx, t, client) + testCases := getCombinationFilterTestCases(contract1, contract2, "0x0") - testCases := []struct { - name string - spec *ethtypes.EthFilterSpec - expected []ExpectedEthLog - }{ - { - name: "find all EventZeroData events", - spec: newEthFilterBuilder().FromBlockEpoch(0).Topic1OneOf(paddedEthHash(EventMatrixContract.Ev["EventZeroData"])).Filter(), - - expected: []ExpectedEthLog{ - { - Address: contract1, - Topics: []ethtypes.EthBytes{ - EventMatrixContract.Ev["EventZeroData"], - }, - Data: nil, - }, - { - Address: contract2, - Topics: []ethtypes.EthBytes{ - EventMatrixContract.Ev["EventZeroData"], - }, - Data: nil, - }, - }, - }, - { - name: "find all EventOneData events", - spec: newEthFilterBuilder().FromBlockEpoch(0).Topic1OneOf(paddedEthHash(EventMatrixContract.Ev["EventOneData"])).Filter(), - - expected: []ExpectedEthLog{ - { - Address: contract1, - Topics: []ethtypes.EthBytes{ - EventMatrixContract.Ev["EventOneData"], - }, - Data: packUint64Values(23), - }, - { - Address: contract1, - Topics: []ethtypes.EthBytes{ - EventMatrixContract.Ev["EventOneData"], - }, - Data: packUint64Values(44), - }, - }, - }, - { - name: "find all EventTwoData events", - spec: newEthFilterBuilder().FromBlockEpoch(0).Topic1OneOf(paddedEthHash(EventMatrixContract.Ev["EventTwoData"])).Filter(), - - expected: []ExpectedEthLog{ - { - Address: contract1, - Topics: []ethtypes.EthBytes{ - EventMatrixContract.Ev["EventTwoData"], - }, - Data: packUint64Values(555, 666), - }, - }, - }, - { - name: "find all EventThreeData events", - spec: newEthFilterBuilder().FromBlockEpoch(0).Topic1OneOf(paddedEthHash(EventMatrixContract.Ev["EventThreeData"])).Filter(), - - expected: []ExpectedEthLog{ - { - Address: contract1, - Topics: []ethtypes.EthBytes{ - EventMatrixContract.Ev["EventThreeData"], - }, - Data: packUint64Values(1, 2, 3), - }, - }, - }, - { - name: "find all EventOneIndexed events", - spec: newEthFilterBuilder().FromBlockEpoch(0).Topic1OneOf(paddedEthHash(EventMatrixContract.Ev["EventOneIndexed"])).Filter(), - - expected: []ExpectedEthLog{ - { - Address: contract1, - Topics: []ethtypes.EthBytes{ - EventMatrixContract.Ev["EventOneIndexed"], - paddedUint64(44), - }, - Data: nil, - }, - }, - }, - { - name: "find all EventTwoIndexed events", - spec: newEthFilterBuilder().FromBlockEpoch(0).Topic1OneOf(paddedEthHash(EventMatrixContract.Ev["EventTwoIndexed"])).Filter(), - - expected: []ExpectedEthLog{ - { - Address: contract2, - Topics: []ethtypes.EthBytes{ - EventMatrixContract.Ev["EventTwoIndexed"], - paddedUint64(44), - paddedUint64(19), - }, - Data: nil, - }, - { - Address: contract1, - Topics: []ethtypes.EthBytes{ - EventMatrixContract.Ev["EventTwoIndexed"], - paddedUint64(40), - paddedUint64(20), - }, - Data: nil, - }, - }, - }, - { - name: "find all EventThreeIndexed events", - spec: newEthFilterBuilder().FromBlockEpoch(0).Topic1OneOf(paddedEthHash(EventMatrixContract.Ev["EventThreeIndexed"])).Filter(), - - expected: []ExpectedEthLog{ - { - Address: contract2, - Topics: []ethtypes.EthBytes{ - EventMatrixContract.Ev["EventThreeIndexed"], - paddedUint64(44), - paddedUint64(27), - paddedUint64(19), - }, - Data: nil, - }, - }, - }, - { - name: "find all EventOneIndexedWithData events", - spec: newEthFilterBuilder().FromBlockEpoch(0).Topic1OneOf(paddedEthHash(EventMatrixContract.Ev["EventOneIndexedWithData"])).Filter(), - - expected: []ExpectedEthLog{ - { - Address: contract1, - Topics: []ethtypes.EthBytes{ - EventMatrixContract.Ev["EventOneIndexedWithData"], - paddedUint64(44), - }, - Data: paddedUint64(19), - }, - { - Address: contract1, - Topics: []ethtypes.EthBytes{ - EventMatrixContract.Ev["EventOneIndexedWithData"], - paddedUint64(46), - }, - Data: paddedUint64(12), - }, - { - Address: contract2, - Topics: []ethtypes.EthBytes{ - EventMatrixContract.Ev["EventOneIndexedWithData"], - paddedUint64(50), - }, - Data: paddedUint64(9), - }, - }, - }, - { - name: "find all EventTwoIndexedWithData events", - spec: newEthFilterBuilder().FromBlockEpoch(0).Topic1OneOf(paddedEthHash(EventMatrixContract.Ev["EventTwoIndexedWithData"])).Filter(), - - expected: []ExpectedEthLog{ - { - Address: contract1, - Topics: []ethtypes.EthBytes{ - EventMatrixContract.Ev["EventTwoIndexedWithData"], - paddedUint64(44), - paddedUint64(27), - }, - Data: paddedUint64(19), - }, - { - Address: contract1, - Topics: []ethtypes.EthBytes{ - EventMatrixContract.Ev["EventTwoIndexedWithData"], - paddedUint64(46), - paddedUint64(27), - }, - Data: paddedUint64(19), - }, - { - Address: contract1, - Topics: []ethtypes.EthBytes{ - EventMatrixContract.Ev["EventTwoIndexedWithData"], - paddedUint64(46), - paddedUint64(14), - }, - Data: paddedUint64(19), - }, - }, - }, - { - name: "find all EventThreeIndexedWithData events", - spec: newEthFilterBuilder().FromBlockEpoch(0).Topic1OneOf(paddedEthHash(EventMatrixContract.Ev["EventThreeIndexedWithData"])).Filter(), - - expected: []ExpectedEthLog{ - { - Address: contract1, - Topics: []ethtypes.EthBytes{ - EventMatrixContract.Ev["EventThreeIndexedWithData"], - paddedUint64(44), - paddedUint64(27), - paddedUint64(19), - }, - Data: paddedUint64(12), - }, - }, - }, - - { - name: "find all events from contract2", - spec: newEthFilterBuilder().FromBlockEpoch(0).AddressOneOf(contract2).Filter(), - - expected: []ExpectedEthLog{ - { - Address: contract2, - Topics: []ethtypes.EthBytes{ - EventMatrixContract.Ev["EventZeroData"], - }, - Data: nil, - }, - { - Address: contract2, - Topics: []ethtypes.EthBytes{ - EventMatrixContract.Ev["EventThreeIndexed"], - paddedUint64(44), - paddedUint64(27), - paddedUint64(19), - }, - Data: nil, - }, - { - Address: contract2, - Topics: []ethtypes.EthBytes{ - EventMatrixContract.Ev["EventTwoIndexed"], - paddedUint64(44), - paddedUint64(19), - }, - Data: nil, - }, - { - Address: contract2, - Topics: []ethtypes.EthBytes{ - EventMatrixContract.Ev["EventOneIndexedWithData"], - paddedUint64(50), - }, - Data: paddedUint64(9), - }, - }, - }, - - { - name: "find all events with topic2 of 44", - spec: newEthFilterBuilder().FromBlockEpoch(0).Topic2OneOf(paddedEthHash(paddedUint64(44))).Filter(), - - expected: []ExpectedEthLog{ - { - Address: contract1, - Topics: []ethtypes.EthBytes{ - EventMatrixContract.Ev["EventOneIndexed"], - paddedUint64(44), - }, - Data: nil, - }, - { - Address: contract2, - Topics: []ethtypes.EthBytes{ - EventMatrixContract.Ev["EventTwoIndexed"], - paddedUint64(44), - paddedUint64(19), - }, - Data: nil, - }, - { - Address: contract2, - Topics: []ethtypes.EthBytes{ - EventMatrixContract.Ev["EventThreeIndexed"], - paddedUint64(44), - paddedUint64(27), - paddedUint64(19), - }, - Data: nil, - }, - { - Address: contract1, - Topics: []ethtypes.EthBytes{ - EventMatrixContract.Ev["EventOneIndexedWithData"], - paddedUint64(44), - }, - Data: paddedUint64(19), - }, - { - Address: contract1, - Topics: []ethtypes.EthBytes{ - EventMatrixContract.Ev["EventTwoIndexedWithData"], - paddedUint64(44), - paddedUint64(27), - }, - Data: paddedUint64(19), - }, - { - Address: contract1, - Topics: []ethtypes.EthBytes{ - EventMatrixContract.Ev["EventThreeIndexedWithData"], - paddedUint64(44), - paddedUint64(27), - paddedUint64(19), - }, - Data: paddedUint64(12), - }, - }, - }, - - { - name: "find all events with topic2 of 44 from contract2", - spec: newEthFilterBuilder().FromBlockEpoch(0).AddressOneOf(contract2).Topic2OneOf(paddedEthHash(paddedUint64(44))).Filter(), - - expected: []ExpectedEthLog{ - { - Address: contract2, - Topics: []ethtypes.EthBytes{ - EventMatrixContract.Ev["EventThreeIndexed"], - paddedUint64(44), - paddedUint64(27), - paddedUint64(19), - }, - Data: nil, - }, - { - Address: contract2, - Topics: []ethtypes.EthBytes{ - EventMatrixContract.Ev["EventTwoIndexed"], - paddedUint64(44), - paddedUint64(19), - }, - Data: nil, - }, - }, - }, - - { - name: "find all EventOneIndexedWithData events from contract1 or contract2", - spec: newEthFilterBuilder(). - FromBlockEpoch(0). - AddressOneOf(contract1, contract2). - Topic1OneOf(paddedEthHash(EventMatrixContract.Ev["EventOneIndexedWithData"])). - Filter(), - - expected: []ExpectedEthLog{ - { - Address: contract1, - Topics: []ethtypes.EthBytes{ - EventMatrixContract.Ev["EventOneIndexedWithData"], - paddedUint64(44), - }, - Data: paddedUint64(19), - }, - { - Address: contract1, - Topics: []ethtypes.EthBytes{ - EventMatrixContract.Ev["EventOneIndexedWithData"], - paddedUint64(46), - }, - Data: paddedUint64(12), - }, - { - Address: contract2, - Topics: []ethtypes.EthBytes{ - EventMatrixContract.Ev["EventOneIndexedWithData"], - paddedUint64(50), - }, - Data: paddedUint64(9), - }, - }, - }, - - { - name: "find all events with topic2 of 46", - spec: newEthFilterBuilder().FromBlockEpoch(0).Topic2OneOf(paddedEthHash(paddedUint64(46))).Filter(), - - expected: []ExpectedEthLog{ - { - Address: contract1, - Topics: []ethtypes.EthBytes{ - EventMatrixContract.Ev["EventOneIndexedWithData"], - paddedUint64(46), - }, - Data: paddedUint64(12), - }, - { - Address: contract1, - Topics: []ethtypes.EthBytes{ - EventMatrixContract.Ev["EventTwoIndexedWithData"], - paddedUint64(46), - paddedUint64(27), - }, - Data: paddedUint64(19), - }, - { - Address: contract1, - Topics: []ethtypes.EthBytes{ - EventMatrixContract.Ev["EventTwoIndexedWithData"], - paddedUint64(46), - paddedUint64(14), - }, - Data: paddedUint64(19), - }, - }, - }, - { - name: "find all events with topic2 of 50", - spec: newEthFilterBuilder().FromBlockEpoch(0).Topic2OneOf(paddedEthHash(paddedUint64(50))).Filter(), - - expected: []ExpectedEthLog{ - { - Address: contract2, - Topics: []ethtypes.EthBytes{ - EventMatrixContract.Ev["EventOneIndexedWithData"], - paddedUint64(50), - }, - Data: paddedUint64(9), - }, - }, - }, - { - name: "find all events with topic2 of 46 or 50", - spec: newEthFilterBuilder().FromBlockEpoch(0).Topic2OneOf(paddedEthHash(paddedUint64(46)), paddedEthHash(paddedUint64(50))).Filter(), - - expected: []ExpectedEthLog{ - { - Address: contract1, - Topics: []ethtypes.EthBytes{ - EventMatrixContract.Ev["EventOneIndexedWithData"], - paddedUint64(46), - }, - Data: paddedUint64(12), - }, - { - Address: contract1, - Topics: []ethtypes.EthBytes{ - EventMatrixContract.Ev["EventTwoIndexedWithData"], - paddedUint64(46), - paddedUint64(27), - }, - Data: paddedUint64(19), - }, - { - Address: contract1, - Topics: []ethtypes.EthBytes{ - EventMatrixContract.Ev["EventTwoIndexedWithData"], - paddedUint64(46), - paddedUint64(14), - }, - Data: paddedUint64(19), - }, - { - Address: contract2, - Topics: []ethtypes.EthBytes{ - EventMatrixContract.Ev["EventOneIndexedWithData"], - paddedUint64(50), - }, - Data: paddedUint64(9), - }, - }, - }, - - { - name: "find all events with topic1 of EventTwoIndexedWithData and topic3 of 27", - spec: newEthFilterBuilder(). - FromBlockEpoch(0). - Topic1OneOf(paddedEthHash(EventMatrixContract.Ev["EventTwoIndexedWithData"])). - Topic3OneOf(paddedEthHash(paddedUint64(27))). - Filter(), - - expected: []ExpectedEthLog{ - { - Address: contract1, - Topics: []ethtypes.EthBytes{ - EventMatrixContract.Ev["EventTwoIndexedWithData"], - paddedUint64(44), - paddedUint64(27), - }, - Data: paddedUint64(19), - }, - { - Address: contract1, - Topics: []ethtypes.EthBytes{ - EventMatrixContract.Ev["EventTwoIndexedWithData"], - paddedUint64(46), - paddedUint64(27), - }, - Data: paddedUint64(19), - }, - }, - }, - - { - name: "find all events with topic1 of EventTwoIndexedWithData or EventOneIndexed and topic2 of 44", - spec: newEthFilterBuilder(). - FromBlockEpoch(0). - Topic1OneOf(paddedEthHash(EventMatrixContract.Ev["EventTwoIndexedWithData"]), paddedEthHash(EventMatrixContract.Ev["EventOneIndexed"])). - Topic2OneOf(paddedEthHash(paddedUint64(44))). - Filter(), - - expected: []ExpectedEthLog{ - { - Address: contract1, - Topics: []ethtypes.EthBytes{ - EventMatrixContract.Ev["EventTwoIndexedWithData"], - paddedUint64(44), - paddedUint64(27), - }, - Data: paddedUint64(19), - }, - { - Address: contract1, - Topics: []ethtypes.EthBytes{ - EventMatrixContract.Ev["EventOneIndexed"], - paddedUint64(44), - }, - Data: nil, - }, - }, - }, - } + messages := invokeAndWaitUntilAllOnChain(t, client, invocations) for _, tc := range testCases { tc := tc // appease the lint despot @@ -1069,6 +500,173 @@ func TestEthGetLogs(t *testing.T) { } } +func TestEthGetFilterChanges(t *testing.T) { + require := require.New(t) + kit.QuietAllLogsExcept("events", "messagepool") + + blockTime := 100 * time.Millisecond + + client, _, ens := kit.EnsembleMinimal(t, kit.MockProofs(), kit.ThroughRPC()) + ens.InterconnectAll().BeginMining(blockTime) + + ctx, cancel := context.WithTimeout(context.Background(), time.Minute) + defer cancel() + + // Set up the test fixture with a standard list of invocations + contract1, contract2, invocations := prepareEventMatrixInvocations(ctx, t, client) + + // Get the test cases + testCases := getCombinationFilterTestCases(contract1, contract2, "latest") + + testFilters := map[string]ethtypes.EthFilterID{} + // Create all the filters + for _, tc := range testCases { + filterID, err := client.EthNewFilter(ctx, tc.spec) + require.NoError(err) + testFilters[tc.name] = filterID + } + + // Perform all the invocations + messages := invokeAndWaitUntilAllOnChain(t, client, invocations) + + for _, tc := range testCases { + tc := tc // appease the lint despot + t.Run(tc.name, func(t *testing.T) { + filterID, ok := testFilters[tc.name] + require.True(ok) + + // Look for events that the filter has accumulated + res, err := client.EthGetFilterChanges(ctx, filterID) + require.NoError(err) + + elogs, err := parseEthLogsFromFilterResult(res) + require.NoError(err) + AssertEthLogs(t, elogs, tc.expected, messages) + }) + } +} + +func TestEthSubscribeLogs(t *testing.T) { + require := require.New(t) + kit.QuietAllLogsExcept("events", "messagepool") + + blockTime := 100 * time.Millisecond + + client, _, ens := kit.EnsembleMinimal(t, kit.MockProofs(), kit.ThroughRPC()) + ens.InterconnectAll().BeginMining(blockTime) + + ctx, cancel := context.WithTimeout(context.Background(), time.Minute) + defer cancel() + + // Set up the test fixture with a standard list of invocations + contract1, contract2, invocations := prepareEventMatrixInvocations(ctx, t, client) + + // Get the test cases + testCases := getTopicFilterTestCases(contract1, contract2, "latest") + + testResponses := map[string]chan ethtypes.EthSubscriptionResponse{} + + // Create all the filters + for _, tc := range testCases { + // subscribe to topics in filter + subParam, err := json.Marshal(ethtypes.EthSubscribeParams{ + EventType: "logs", + Params: ðtypes.EthSubscriptionParams{ + Topics: tc.spec.Topics, + Address: tc.spec.Address, + }, + }) + require.NoError(err) + + subId, err := client.EthSubscribe(ctx, subParam) + require.NoError(err) + + responseCh := make(chan ethtypes.EthSubscriptionResponse, len(invocations)) + testResponses[tc.name] = responseCh + + err = client.EthSubRouter.AddSub(ctx, subId, func(ctx context.Context, resp *ethtypes.EthSubscriptionResponse) error { + responseCh <- *resp + return nil + }) + require.NoError(err) + } + + // Perform all the invocations + messages := invokeAndWaitUntilAllOnChain(t, client, invocations) + + // wait a little for subscriptions to gather results + time.Sleep(blockTime * 6) + + for _, tc := range testCases { + tc := tc // appease the lint despot + t.Run(tc.name, func(t *testing.T) { + responseCh, ok := testResponses[tc.name] + require.True(ok) + + // don't expect any more responses + close(responseCh) + + var elogs []*ethtypes.EthLog + for resp := range responseCh { + rmap, ok := resp.Result.(map[string]interface{}) + require.True(ok, "expected subscription result entry to be map[string]interface{}, but was %T", resp.Result) + + elog, err := ParseEthLog(rmap) + require.NoError(err) + + elogs = append(elogs, elog) + } + AssertEthLogs(t, elogs, tc.expected, messages) + }) + } +} + +func TestEthGetFilterLogs(t *testing.T) { + require := require.New(t) + kit.QuietAllLogsExcept("events", "messagepool") + + blockTime := 100 * time.Millisecond + + client, _, ens := kit.EnsembleMinimal(t, kit.MockProofs(), kit.ThroughRPC()) + ens.InterconnectAll().BeginMining(blockTime) + + ctx, cancel := context.WithTimeout(context.Background(), time.Minute) + defer cancel() + + // Set up the test fixture with a standard list of invocations + contract1, contract2, invocations := prepareEventMatrixInvocations(ctx, t, client) + + // Get the test cases + testCases := getCombinationFilterTestCases(contract1, contract2, "latest") + + testFilters := map[string]ethtypes.EthFilterID{} + // Create all the filters + for _, tc := range testCases { + filterID, err := client.EthNewFilter(ctx, tc.spec) + require.NoError(err) + testFilters[tc.name] = filterID + } + + // Perform all the invocations + messages := invokeAndWaitUntilAllOnChain(t, client, invocations) + + for _, tc := range testCases { + tc := tc // appease the lint despot + t.Run(tc.name, func(t *testing.T) { + filterID, ok := testFilters[tc.name] + require.True(ok) + + // Look for events that the filter has accumulated + res, err := client.EthGetFilterLogs(ctx, filterID) + require.NoError(err) + + elogs, err := parseEthLogsFromFilterResult(res) + require.NoError(err) + AssertEthLogs(t, elogs, tc.expected, messages) + }) + } +} + func TestEthGetLogsWithBlockRanges(t *testing.T) { require := require.New(t) kit.QuietAllLogsExcept("events", "messagepool") @@ -1090,8 +688,8 @@ func TestEthGetLogsWithBlockRanges(t *testing.T) { // Select events for partitioning for _, m := range messages { - if bytes.Equal(m.invocation.Selector, EventMatrixContract.Fn["logEventTwoIndexedWithData"]) { - addr := getContractEthAddress(ctx, t, client, m.invocation.Target) + if bytes.Equal(m.invocation.Selector, kit.EventMatrixContract.Fn["logEventTwoIndexedWithData"]) { + addr := getEthAddress(ctx, t, client, m.invocation.Target) args := unpackUint64Values(m.invocation.Data) require.Equal(3, len(args), "logEventTwoIndexedWithData should have 3 arguments") @@ -1099,7 +697,7 @@ func TestEthGetLogsWithBlockRanges(t *testing.T) { expectedByHeight[m.ts.Height()] = append(expectedByHeight[m.ts.Height()], ExpectedEthLog{ Address: addr, Topics: []ethtypes.EthBytes{ - EventMatrixContract.Ev["EventTwoIndexedWithData"], + kit.EventMatrixContract.Ev["EventTwoIndexedWithData"], paddedUint64(args[0]), paddedUint64(args[1]), }, @@ -1164,7 +762,7 @@ func TestEthGetLogsWithBlockRanges(t *testing.T) { require.True(len(partition3.expected) > 0, "partition should have events") // these are the topics we selected for partitioning earlier - topics := []ethtypes.EthHash{paddedEthHash(EventMatrixContract.Ev["EventTwoIndexedWithData"])} + topics := []ethtypes.EthHash{paddedEthHash(kit.EventMatrixContract.Ev["EventTwoIndexedWithData"])} union := func(lists ...[]ExpectedEthLog) []ExpectedEthLog { ret := []ExpectedEthLog{} @@ -1181,91 +779,91 @@ func TestEthGetLogsWithBlockRanges(t *testing.T) { }{ { name: "find all events from genesis", - spec: newEthFilterBuilder().FromBlockEpoch(0).Topic1OneOf(topics...).Filter(), + spec: kit.NewEthFilterBuilder().FromBlockEpoch(0).Topic1OneOf(topics...).Filter(), expected: union(partition1.expected, partition2.expected, partition3.expected), }, { name: "find all from start of partition1", - spec: newEthFilterBuilder().FromBlockEpoch(partition1.start).Topic1OneOf(topics...).Filter(), + spec: kit.NewEthFilterBuilder().FromBlockEpoch(partition1.start).Topic1OneOf(topics...).Filter(), expected: union(partition1.expected, partition2.expected, partition3.expected), }, { name: "find all from start of partition2", - spec: newEthFilterBuilder().FromBlockEpoch(partition2.start).Topic1OneOf(topics...).Filter(), + spec: kit.NewEthFilterBuilder().FromBlockEpoch(partition2.start).Topic1OneOf(topics...).Filter(), expected: union(partition2.expected, partition3.expected), }, { name: "find all from start of partition3", - spec: newEthFilterBuilder().FromBlockEpoch(partition3.start).Topic1OneOf(topics...).Filter(), + spec: kit.NewEthFilterBuilder().FromBlockEpoch(partition3.start).Topic1OneOf(topics...).Filter(), expected: union(partition3.expected), }, { name: "find none after end of partition3", - spec: newEthFilterBuilder().FromBlockEpoch(partition3.end + 1).Topic1OneOf(topics...).Filter(), + spec: kit.NewEthFilterBuilder().FromBlockEpoch(partition3.end + 1).Topic1OneOf(topics...).Filter(), expected: nil, }, { name: "find all events from genesis to end of partition1", - spec: newEthFilterBuilder().FromBlockEpoch(0).ToBlockEpoch(partition1.end).Topic1OneOf(topics...).Filter(), + spec: kit.NewEthFilterBuilder().FromBlockEpoch(0).ToBlockEpoch(partition1.end).Topic1OneOf(topics...).Filter(), expected: union(partition1.expected), }, { name: "find all events from genesis to end of partition2", - spec: newEthFilterBuilder().FromBlockEpoch(0).ToBlockEpoch(partition2.end).Topic1OneOf(topics...).Filter(), + spec: kit.NewEthFilterBuilder().FromBlockEpoch(0).ToBlockEpoch(partition2.end).Topic1OneOf(topics...).Filter(), expected: union(partition1.expected, partition2.expected), }, { name: "find all events from genesis to end of partition3", - spec: newEthFilterBuilder().FromBlockEpoch(0).ToBlockEpoch(partition3.end).Topic1OneOf(topics...).Filter(), + spec: kit.NewEthFilterBuilder().FromBlockEpoch(0).ToBlockEpoch(partition3.end).Topic1OneOf(topics...).Filter(), expected: union(partition1.expected, partition2.expected, partition3.expected), }, { name: "find none from genesis to start of partition1", - spec: newEthFilterBuilder().FromBlockEpoch(0).ToBlockEpoch(partition1.start - 1).Topic1OneOf(topics...).Filter(), + spec: kit.NewEthFilterBuilder().FromBlockEpoch(0).ToBlockEpoch(partition1.start - 1).Topic1OneOf(topics...).Filter(), expected: nil, }, { name: "find all events in partition1", - spec: newEthFilterBuilder().FromBlockEpoch(partition1.start).ToBlockEpoch(partition1.end).Topic1OneOf(topics...).Filter(), + spec: kit.NewEthFilterBuilder().FromBlockEpoch(partition1.start).ToBlockEpoch(partition1.end).Topic1OneOf(topics...).Filter(), expected: union(partition1.expected), }, { name: "find all events in partition2", - spec: newEthFilterBuilder().FromBlockEpoch(partition2.start).ToBlockEpoch(partition2.end).Topic1OneOf(topics...).Filter(), + spec: kit.NewEthFilterBuilder().FromBlockEpoch(partition2.start).ToBlockEpoch(partition2.end).Topic1OneOf(topics...).Filter(), expected: union(partition2.expected), }, { name: "find all events in partition3", - spec: newEthFilterBuilder().FromBlockEpoch(partition3.start).ToBlockEpoch(partition3.end).Topic1OneOf(topics...).Filter(), + spec: kit.NewEthFilterBuilder().FromBlockEpoch(partition3.start).ToBlockEpoch(partition3.end).Topic1OneOf(topics...).Filter(), expected: union(partition3.expected), }, { name: "find all events from earliest to end of partition1", - spec: newEthFilterBuilder().FromBlock("earliest").ToBlockEpoch(partition1.end).Topic1OneOf(topics...).Filter(), + spec: kit.NewEthFilterBuilder().FromBlock("earliest").ToBlockEpoch(partition1.end).Topic1OneOf(topics...).Filter(), expected: union(partition1.expected), }, { name: "find all events from start of partition3 to latest", - spec: newEthFilterBuilder().FromBlockEpoch(partition3.start).ToBlock("latest").Topic1OneOf(topics...).Filter(), + spec: kit.NewEthFilterBuilder().FromBlockEpoch(partition3.start).ToBlock("latest").Topic1OneOf(topics...).Filter(), expected: union(partition3.expected), }, { name: "find all events from earliest to latest", - spec: newEthFilterBuilder().FromBlock("earliest").ToBlock("latest").Topic1OneOf(topics...).Filter(), + spec: kit.NewEthFilterBuilder().FromBlock("earliest").ToBlock("latest").Topic1OneOf(topics...).Filter(), expected: union(partition1.expected, partition2.expected, partition3.expected), }, } @@ -1283,6 +881,108 @@ func TestEthGetLogsWithBlockRanges(t *testing.T) { } } +func TestEthNewFilterMergesHistoricWithRealtime(t *testing.T) { + require := require.New(t) + + kit.QuietAllLogsExcept("events", "messagepool") + + blockTime := 100 * time.Millisecond + client, _, ens := kit.EnsembleMinimal(t, kit.MockProofs(), kit.ThroughRPC()) + ens.InterconnectAll().BeginMining(blockTime) + + ctx, cancel := context.WithTimeout(context.Background(), time.Minute) + defer cancel() + + sender, contract := client.EVM().DeployContractFromFilename(ctx, kit.EventMatrixContract.Filename) + + // generate some events before the creation of the filter + preInvocations := []Invocation{ + { + Sender: sender, + Target: contract, + Selector: kit.EventMatrixContract.Fn["logEventOneData"], + Data: packUint64Values(1), + }, + { + Sender: sender, + Target: contract, + Selector: kit.EventMatrixContract.Fn["logEventOneIndexed"], + Data: packUint64Values(2), + }, + } + + messages := invokeAndWaitUntilAllOnChain(t, client, preInvocations) + + // now install filter + spec := kit.NewEthFilterBuilder().FromBlock("earliest").Filter() + + filterID, err := client.EthNewFilter(ctx, spec) + require.NoError(err) + + // generate some events after the creation of the filter + postInvocations := []Invocation{ + { + Sender: sender, + Target: contract, + Selector: kit.EventMatrixContract.Fn["logEventOneData"], + Data: packUint64Values(3), + }, + { + Sender: sender, + Target: contract, + Selector: kit.EventMatrixContract.Fn["logEventOneIndexed"], + Data: packUint64Values(4), + }, + } + + postMessages := invokeAndWaitUntilAllOnChain(t, client, postInvocations) + for k, v := range postMessages { + messages[k] = v + } + + // collect filter results + res, err := client.EthGetFilterChanges(ctx, filterID) + require.NoError(err) + + ethContractAddr := getEthAddress(ctx, t, client, contract) + + // expect to see 2 messages from before the filter was installed and 2 after + expected := []ExpectedEthLog{ + { + Address: ethContractAddr, + Topics: []ethtypes.EthBytes{ + kit.EventMatrixContract.Ev["EventOneData"], + }, + Data: paddedUint64(1), + }, + { + Address: ethContractAddr, + Topics: []ethtypes.EthBytes{ + kit.EventMatrixContract.Ev["EventOneIndexed"], + paddedUint64(2), + }, + }, + { + Address: ethContractAddr, + Topics: []ethtypes.EthBytes{ + kit.EventMatrixContract.Ev["EventOneData"], + }, + Data: paddedUint64(3), + }, + { + Address: ethContractAddr, + Topics: []ethtypes.EthBytes{ + kit.EventMatrixContract.Ev["EventOneIndexed"], + paddedUint64(4), + }, + }, + } + + elogs, err := parseEthLogsFromFilterResult(res) + require.NoError(err) + AssertEthLogs(t, elogs, expected, messages) +} + // ------------------------------------------------------------------------------- // end of tests // ------------------------------------------------------------------------------- @@ -1295,7 +995,7 @@ type msgInTipset struct { reverted bool } -func getContractEthAddress(ctx context.Context, t *testing.T, client *kit.TestFullNode, addr address.Address) ethtypes.EthAddress { +func getEthAddress(ctx context.Context, t *testing.T, client *kit.TestFullNode, addr address.Address) ethtypes.EthAddress { head, err := client.ChainHead(ctx) require.NoError(t, err) @@ -1392,7 +1092,8 @@ func invokeAndWaitUntilAllOnChain(t *testing.T, client *kit.TestFullNode, invoca } } } - ret := client.EVM().InvokeSolidity(ctx, inv.Sender, inv.Target, inv.Selector, inv.Data) + ret, err := client.EVM().InvokeSolidity(ctx, inv.Sender, inv.Target, inv.Selector, inv.Data) + require.NoError(err) require.True(ret.Receipt.ExitCode.IsSuccess(), "contract execution failed") invocationMap[ret.Message] = inv @@ -1432,28 +1133,28 @@ func invokeLogFourData(t *testing.T, client *kit.TestFullNode, iterations int) ( ctx, cancel := context.WithTimeout(context.Background(), time.Minute) defer cancel() - fromAddr, idAddr := client.EVM().DeployContractFromFilename(ctx, EventsContract.Filename) + fromAddr, idAddr := client.EVM().DeployContractFromFilename(ctx, kit.EventsContract.Filename) invocations := make([]Invocation, iterations) for i := range invocations { invocations[i] = Invocation{ Sender: fromAddr, Target: idAddr, - Selector: EventsContract.Fn["log_four_data"], + Selector: kit.EventsContract.Fn["log_four_data"], Data: nil, } } messages := invokeAndWaitUntilAllOnChain(t, client, invocations) - ethAddr := getContractEthAddress(ctx, t, client, idAddr) + ethAddr := getEthAddress(ctx, t, client, idAddr) return ethAddr, messages } -func invokeEventMatrix(ctx context.Context, t *testing.T, client *kit.TestFullNode) (ethtypes.EthAddress, ethtypes.EthAddress, map[ethtypes.EthHash]msgInTipset) { - sender1, contract1 := client.EVM().DeployContractFromFilename(ctx, EventMatrixContract.Filename) - sender2, contract2 := client.EVM().DeployContractFromFilename(ctx, EventMatrixContract.Filename) +func prepareEventMatrixInvocations(ctx context.Context, t *testing.T, client *kit.TestFullNode) (ethtypes.EthAddress, ethtypes.EthAddress, []Invocation) { + sender1, contract1 := client.EVM().DeployContractFromFilename(ctx, kit.EventMatrixContract.Filename) + sender2, contract2 := client.EVM().DeployContractFromFilename(ctx, kit.EventMatrixContract.Filename) invocations := []Invocation{ // log EventZeroData() @@ -1461,7 +1162,7 @@ func invokeEventMatrix(ctx context.Context, t *testing.T, client *kit.TestFullNo { Sender: sender1, Target: contract1, - Selector: EventMatrixContract.Fn["logEventZeroData"], + Selector: kit.EventMatrixContract.Fn["logEventZeroData"], Data: nil, }, @@ -1471,7 +1172,7 @@ func invokeEventMatrix(ctx context.Context, t *testing.T, client *kit.TestFullNo { Sender: sender1, Target: contract1, - Selector: EventMatrixContract.Fn["logEventOneData"], + Selector: kit.EventMatrixContract.Fn["logEventOneData"], Data: packUint64Values(23), }, @@ -1481,7 +1182,7 @@ func invokeEventMatrix(ctx context.Context, t *testing.T, client *kit.TestFullNo { Sender: sender1, Target: contract1, - Selector: EventMatrixContract.Fn["logEventOneIndexed"], + Selector: kit.EventMatrixContract.Fn["logEventOneIndexed"], Data: packUint64Values(44), }, @@ -1492,7 +1193,7 @@ func invokeEventMatrix(ctx context.Context, t *testing.T, client *kit.TestFullNo { Sender: sender2, Target: contract2, - Selector: EventMatrixContract.Fn["logEventTwoIndexed"], + Selector: kit.EventMatrixContract.Fn["logEventTwoIndexed"], Data: packUint64Values(44, 19), }, @@ -1502,7 +1203,7 @@ func invokeEventMatrix(ctx context.Context, t *testing.T, client *kit.TestFullNo { Sender: sender1, Target: contract1, - Selector: EventMatrixContract.Fn["logEventOneData"], + Selector: kit.EventMatrixContract.Fn["logEventOneData"], Data: packUint64Values(44), }, @@ -1512,7 +1213,7 @@ func invokeEventMatrix(ctx context.Context, t *testing.T, client *kit.TestFullNo { Sender: sender1, Target: contract1, - Selector: EventMatrixContract.Fn["logEventTwoData"], + Selector: kit.EventMatrixContract.Fn["logEventTwoData"], Data: packUint64Values(555, 666), }, @@ -1521,7 +1222,7 @@ func invokeEventMatrix(ctx context.Context, t *testing.T, client *kit.TestFullNo { Sender: sender2, Target: contract2, - Selector: EventMatrixContract.Fn["logEventZeroData"], + Selector: kit.EventMatrixContract.Fn["logEventZeroData"], Data: nil, }, @@ -1531,7 +1232,7 @@ func invokeEventMatrix(ctx context.Context, t *testing.T, client *kit.TestFullNo { Sender: sender1, Target: contract1, - Selector: EventMatrixContract.Fn["logEventThreeData"], + Selector: kit.EventMatrixContract.Fn["logEventThreeData"], Data: packUint64Values(1, 2, 3), }, @@ -1543,7 +1244,7 @@ func invokeEventMatrix(ctx context.Context, t *testing.T, client *kit.TestFullNo { Sender: sender1, Target: contract2, - Selector: EventMatrixContract.Fn["logEventThreeIndexed"], + Selector: kit.EventMatrixContract.Fn["logEventThreeIndexed"], Data: packUint64Values(44, 27, 19), }, @@ -1554,7 +1255,7 @@ func invokeEventMatrix(ctx context.Context, t *testing.T, client *kit.TestFullNo { Sender: sender1, Target: contract1, - Selector: EventMatrixContract.Fn["logEventOneIndexedWithData"], + Selector: kit.EventMatrixContract.Fn["logEventOneIndexedWithData"], Data: packUint64Values(44, 19), }, @@ -1565,7 +1266,7 @@ func invokeEventMatrix(ctx context.Context, t *testing.T, client *kit.TestFullNo { Sender: sender1, Target: contract1, - Selector: EventMatrixContract.Fn["logEventOneIndexedWithData"], + Selector: kit.EventMatrixContract.Fn["logEventOneIndexedWithData"], Data: packUint64Values(46, 12), }, @@ -1577,7 +1278,7 @@ func invokeEventMatrix(ctx context.Context, t *testing.T, client *kit.TestFullNo { Sender: sender1, Target: contract1, - Selector: EventMatrixContract.Fn["logEventTwoIndexedWithData"], + Selector: kit.EventMatrixContract.Fn["logEventTwoIndexedWithData"], Data: packUint64Values(44, 27, 19), }, @@ -1590,7 +1291,7 @@ func invokeEventMatrix(ctx context.Context, t *testing.T, client *kit.TestFullNo { Sender: sender1, Target: contract1, - Selector: EventMatrixContract.Fn["logEventThreeIndexedWithData"], + Selector: kit.EventMatrixContract.Fn["logEventThreeIndexedWithData"], Data: packUint64Values(44, 27, 19, 12), }, @@ -1601,7 +1302,7 @@ func invokeEventMatrix(ctx context.Context, t *testing.T, client *kit.TestFullNo { Sender: sender2, Target: contract2, - Selector: EventMatrixContract.Fn["logEventOneIndexedWithData"], + Selector: kit.EventMatrixContract.Fn["logEventOneIndexedWithData"], Data: packUint64Values(50, 9), }, @@ -1613,7 +1314,7 @@ func invokeEventMatrix(ctx context.Context, t *testing.T, client *kit.TestFullNo { Sender: sender1, Target: contract1, - Selector: EventMatrixContract.Fn["logEventTwoIndexedWithData"], + Selector: kit.EventMatrixContract.Fn["logEventTwoIndexedWithData"], Data: packUint64Values(46, 27, 19), }, @@ -1625,7 +1326,7 @@ func invokeEventMatrix(ctx context.Context, t *testing.T, client *kit.TestFullNo { Sender: sender1, Target: contract1, - Selector: EventMatrixContract.Fn["logEventTwoIndexedWithData"], + Selector: kit.EventMatrixContract.Fn["logEventTwoIndexedWithData"], Data: packUint64Values(46, 14, 19), }, // log EventTwoIndexed(44,19) from contract1 @@ -1635,17 +1336,571 @@ func invokeEventMatrix(ctx context.Context, t *testing.T, client *kit.TestFullNo { Sender: sender1, Target: contract1, - Selector: EventMatrixContract.Fn["logEventTwoIndexed"], + Selector: kit.EventMatrixContract.Fn["logEventTwoIndexed"], Data: packUint64Values(40, 20), }, } + ethAddr1 := getEthAddress(ctx, t, client, contract1) + ethAddr2 := getEthAddress(ctx, t, client, contract2) + + return ethAddr1, ethAddr2, invocations +} + +func invokeEventMatrix(ctx context.Context, t *testing.T, client *kit.TestFullNode) (ethtypes.EthAddress, ethtypes.EthAddress, map[ethtypes.EthHash]msgInTipset) { + ethAddr1, ethAddr2, invocations := prepareEventMatrixInvocations(ctx, t, client) messages := invokeAndWaitUntilAllOnChain(t, client, invocations) - ethAddr1 := getContractEthAddress(ctx, t, client, contract1) - ethAddr2 := getContractEthAddress(ctx, t, client, contract2) return ethAddr1, ethAddr2, messages } +type filterTestCase struct { + name string + spec *ethtypes.EthFilterSpec + expected []ExpectedEthLog +} + +// getTopicFilterTestCases returns filter test cases that only include topic criteria +func getTopicFilterTestCases(contract1, contract2 ethtypes.EthAddress, fromBlock string) []filterTestCase { + return []filterTestCase{ + { + name: "find all EventZeroData events", + spec: kit.NewEthFilterBuilder().FromBlock(fromBlock).Topic1OneOf(paddedEthHash(kit.EventMatrixContract.Ev["EventZeroData"])).Filter(), + + expected: []ExpectedEthLog{ + { + Address: contract1, + Topics: []ethtypes.EthBytes{ + kit.EventMatrixContract.Ev["EventZeroData"], + }, + Data: nil, + }, + { + Address: contract2, + Topics: []ethtypes.EthBytes{ + kit.EventMatrixContract.Ev["EventZeroData"], + }, + Data: nil, + }, + }, + }, + { + name: "find all EventOneData events", + spec: kit.NewEthFilterBuilder().FromBlock(fromBlock).Topic1OneOf(paddedEthHash(kit.EventMatrixContract.Ev["EventOneData"])).Filter(), + + expected: []ExpectedEthLog{ + { + Address: contract1, + Topics: []ethtypes.EthBytes{ + kit.EventMatrixContract.Ev["EventOneData"], + }, + Data: packUint64Values(23), + }, + { + Address: contract1, + Topics: []ethtypes.EthBytes{ + kit.EventMatrixContract.Ev["EventOneData"], + }, + Data: packUint64Values(44), + }, + }, + }, + { + name: "find all EventTwoData events", + spec: kit.NewEthFilterBuilder().FromBlock(fromBlock).Topic1OneOf(paddedEthHash(kit.EventMatrixContract.Ev["EventTwoData"])).Filter(), + + expected: []ExpectedEthLog{ + { + Address: contract1, + Topics: []ethtypes.EthBytes{ + kit.EventMatrixContract.Ev["EventTwoData"], + }, + Data: packUint64Values(555, 666), + }, + }, + }, + { + name: "find all EventThreeData events", + spec: kit.NewEthFilterBuilder().FromBlock(fromBlock).Topic1OneOf(paddedEthHash(kit.EventMatrixContract.Ev["EventThreeData"])).Filter(), + + expected: []ExpectedEthLog{ + { + Address: contract1, + Topics: []ethtypes.EthBytes{ + kit.EventMatrixContract.Ev["EventThreeData"], + }, + Data: packUint64Values(1, 2, 3), + }, + }, + }, + { + name: "find all EventOneIndexed events", + spec: kit.NewEthFilterBuilder().FromBlock(fromBlock).Topic1OneOf(paddedEthHash(kit.EventMatrixContract.Ev["EventOneIndexed"])).Filter(), + + expected: []ExpectedEthLog{ + { + Address: contract1, + Topics: []ethtypes.EthBytes{ + kit.EventMatrixContract.Ev["EventOneIndexed"], + paddedUint64(44), + }, + Data: nil, + }, + }, + }, + { + name: "find all EventTwoIndexed events", + spec: kit.NewEthFilterBuilder().FromBlock(fromBlock).Topic1OneOf(paddedEthHash(kit.EventMatrixContract.Ev["EventTwoIndexed"])).Filter(), + + expected: []ExpectedEthLog{ + { + Address: contract2, + Topics: []ethtypes.EthBytes{ + kit.EventMatrixContract.Ev["EventTwoIndexed"], + paddedUint64(44), + paddedUint64(19), + }, + Data: nil, + }, + { + Address: contract1, + Topics: []ethtypes.EthBytes{ + kit.EventMatrixContract.Ev["EventTwoIndexed"], + paddedUint64(40), + paddedUint64(20), + }, + Data: nil, + }, + }, + }, + { + name: "find all EventThreeIndexed events", + spec: kit.NewEthFilterBuilder().FromBlock(fromBlock).Topic1OneOf(paddedEthHash(kit.EventMatrixContract.Ev["EventThreeIndexed"])).Filter(), + + expected: []ExpectedEthLog{ + { + Address: contract2, + Topics: []ethtypes.EthBytes{ + kit.EventMatrixContract.Ev["EventThreeIndexed"], + paddedUint64(44), + paddedUint64(27), + paddedUint64(19), + }, + Data: nil, + }, + }, + }, + { + name: "find all EventOneIndexedWithData events", + spec: kit.NewEthFilterBuilder().FromBlock(fromBlock).Topic1OneOf(paddedEthHash(kit.EventMatrixContract.Ev["EventOneIndexedWithData"])).Filter(), + + expected: []ExpectedEthLog{ + { + Address: contract1, + Topics: []ethtypes.EthBytes{ + kit.EventMatrixContract.Ev["EventOneIndexedWithData"], + paddedUint64(44), + }, + Data: paddedUint64(19), + }, + { + Address: contract1, + Topics: []ethtypes.EthBytes{ + kit.EventMatrixContract.Ev["EventOneIndexedWithData"], + paddedUint64(46), + }, + Data: paddedUint64(12), + }, + { + Address: contract2, + Topics: []ethtypes.EthBytes{ + kit.EventMatrixContract.Ev["EventOneIndexedWithData"], + paddedUint64(50), + }, + Data: paddedUint64(9), + }, + }, + }, + { + name: "find all EventTwoIndexedWithData events", + spec: kit.NewEthFilterBuilder().FromBlock(fromBlock).Topic1OneOf(paddedEthHash(kit.EventMatrixContract.Ev["EventTwoIndexedWithData"])).Filter(), + + expected: []ExpectedEthLog{ + { + Address: contract1, + Topics: []ethtypes.EthBytes{ + kit.EventMatrixContract.Ev["EventTwoIndexedWithData"], + paddedUint64(44), + paddedUint64(27), + }, + Data: paddedUint64(19), + }, + { + Address: contract1, + Topics: []ethtypes.EthBytes{ + kit.EventMatrixContract.Ev["EventTwoIndexedWithData"], + paddedUint64(46), + paddedUint64(27), + }, + Data: paddedUint64(19), + }, + { + Address: contract1, + Topics: []ethtypes.EthBytes{ + kit.EventMatrixContract.Ev["EventTwoIndexedWithData"], + paddedUint64(46), + paddedUint64(14), + }, + Data: paddedUint64(19), + }, + }, + }, + { + name: "find all EventThreeIndexedWithData events", + spec: kit.NewEthFilterBuilder().FromBlock(fromBlock).Topic1OneOf(paddedEthHash(kit.EventMatrixContract.Ev["EventThreeIndexedWithData"])).Filter(), + + expected: []ExpectedEthLog{ + { + Address: contract1, + Topics: []ethtypes.EthBytes{ + kit.EventMatrixContract.Ev["EventThreeIndexedWithData"], + paddedUint64(44), + paddedUint64(27), + paddedUint64(19), + }, + Data: paddedUint64(12), + }, + }, + }, + + { + name: "find all events with topic2 of 44", + spec: kit.NewEthFilterBuilder().FromBlock(fromBlock).Topic2OneOf(paddedEthHash(paddedUint64(44))).Filter(), + + expected: []ExpectedEthLog{ + { + Address: contract1, + Topics: []ethtypes.EthBytes{ + kit.EventMatrixContract.Ev["EventOneIndexed"], + paddedUint64(44), + }, + Data: nil, + }, + { + Address: contract2, + Topics: []ethtypes.EthBytes{ + kit.EventMatrixContract.Ev["EventTwoIndexed"], + paddedUint64(44), + paddedUint64(19), + }, + Data: nil, + }, + { + Address: contract2, + Topics: []ethtypes.EthBytes{ + kit.EventMatrixContract.Ev["EventThreeIndexed"], + paddedUint64(44), + paddedUint64(27), + paddedUint64(19), + }, + Data: nil, + }, + { + Address: contract1, + Topics: []ethtypes.EthBytes{ + kit.EventMatrixContract.Ev["EventOneIndexedWithData"], + paddedUint64(44), + }, + Data: paddedUint64(19), + }, + { + Address: contract1, + Topics: []ethtypes.EthBytes{ + kit.EventMatrixContract.Ev["EventTwoIndexedWithData"], + paddedUint64(44), + paddedUint64(27), + }, + Data: paddedUint64(19), + }, + { + Address: contract1, + Topics: []ethtypes.EthBytes{ + kit.EventMatrixContract.Ev["EventThreeIndexedWithData"], + paddedUint64(44), + paddedUint64(27), + paddedUint64(19), + }, + Data: paddedUint64(12), + }, + }, + }, + { + name: "find all events with topic2 of 46", + spec: kit.NewEthFilterBuilder().FromBlock(fromBlock).Topic2OneOf(paddedEthHash(paddedUint64(46))).Filter(), + + expected: []ExpectedEthLog{ + { + Address: contract1, + Topics: []ethtypes.EthBytes{ + kit.EventMatrixContract.Ev["EventOneIndexedWithData"], + paddedUint64(46), + }, + Data: paddedUint64(12), + }, + { + Address: contract1, + Topics: []ethtypes.EthBytes{ + kit.EventMatrixContract.Ev["EventTwoIndexedWithData"], + paddedUint64(46), + paddedUint64(27), + }, + Data: paddedUint64(19), + }, + { + Address: contract1, + Topics: []ethtypes.EthBytes{ + kit.EventMatrixContract.Ev["EventTwoIndexedWithData"], + paddedUint64(46), + paddedUint64(14), + }, + Data: paddedUint64(19), + }, + }, + }, + { + name: "find all events with topic2 of 50", + spec: kit.NewEthFilterBuilder().FromBlock(fromBlock).Topic2OneOf(paddedEthHash(paddedUint64(50))).Filter(), + + expected: []ExpectedEthLog{ + { + Address: contract2, + Topics: []ethtypes.EthBytes{ + kit.EventMatrixContract.Ev["EventOneIndexedWithData"], + paddedUint64(50), + }, + Data: paddedUint64(9), + }, + }, + }, + { + name: "find all events with topic2 of 46 or 50", + spec: kit.NewEthFilterBuilder().FromBlock(fromBlock).Topic2OneOf(paddedEthHash(paddedUint64(46)), paddedEthHash(paddedUint64(50))).Filter(), + + expected: []ExpectedEthLog{ + { + Address: contract1, + Topics: []ethtypes.EthBytes{ + kit.EventMatrixContract.Ev["EventOneIndexedWithData"], + paddedUint64(46), + }, + Data: paddedUint64(12), + }, + { + Address: contract1, + Topics: []ethtypes.EthBytes{ + kit.EventMatrixContract.Ev["EventTwoIndexedWithData"], + paddedUint64(46), + paddedUint64(27), + }, + Data: paddedUint64(19), + }, + { + Address: contract1, + Topics: []ethtypes.EthBytes{ + kit.EventMatrixContract.Ev["EventTwoIndexedWithData"], + paddedUint64(46), + paddedUint64(14), + }, + Data: paddedUint64(19), + }, + { + Address: contract2, + Topics: []ethtypes.EthBytes{ + kit.EventMatrixContract.Ev["EventOneIndexedWithData"], + paddedUint64(50), + }, + Data: paddedUint64(9), + }, + }, + }, + + { + name: "find all events with topic1 of EventTwoIndexedWithData and topic3 of 27", + spec: kit.NewEthFilterBuilder(). + FromBlockEpoch(0). + Topic1OneOf(paddedEthHash(kit.EventMatrixContract.Ev["EventTwoIndexedWithData"])). + Topic3OneOf(paddedEthHash(paddedUint64(27))). + Filter(), + + expected: []ExpectedEthLog{ + { + Address: contract1, + Topics: []ethtypes.EthBytes{ + kit.EventMatrixContract.Ev["EventTwoIndexedWithData"], + paddedUint64(44), + paddedUint64(27), + }, + Data: paddedUint64(19), + }, + { + Address: contract1, + Topics: []ethtypes.EthBytes{ + kit.EventMatrixContract.Ev["EventTwoIndexedWithData"], + paddedUint64(46), + paddedUint64(27), + }, + Data: paddedUint64(19), + }, + }, + }, + + { + name: "find all events with topic1 of EventTwoIndexedWithData or EventOneIndexed and topic2 of 44", + spec: kit.NewEthFilterBuilder(). + FromBlockEpoch(0). + Topic1OneOf(paddedEthHash(kit.EventMatrixContract.Ev["EventTwoIndexedWithData"]), paddedEthHash(kit.EventMatrixContract.Ev["EventOneIndexed"])). + Topic2OneOf(paddedEthHash(paddedUint64(44))). + Filter(), + + expected: []ExpectedEthLog{ + { + Address: contract1, + Topics: []ethtypes.EthBytes{ + kit.EventMatrixContract.Ev["EventTwoIndexedWithData"], + paddedUint64(44), + paddedUint64(27), + }, + Data: paddedUint64(19), + }, + { + Address: contract1, + Topics: []ethtypes.EthBytes{ + kit.EventMatrixContract.Ev["EventOneIndexed"], + paddedUint64(44), + }, + Data: nil, + }, + }, + }, + } +} + +// getAddressFilterTestCases returns filter test cases include address criteria +func getAddressFilterTestCases(contract1, contract2 ethtypes.EthAddress, fromBlock string) []filterTestCase { + return []filterTestCase{ + { + name: "find all events from contract2", + spec: kit.NewEthFilterBuilder().FromBlock(fromBlock).AddressOneOf(contract2).Filter(), + + expected: []ExpectedEthLog{ + { + Address: contract2, + Topics: []ethtypes.EthBytes{ + kit.EventMatrixContract.Ev["EventZeroData"], + }, + Data: nil, + }, + { + Address: contract2, + Topics: []ethtypes.EthBytes{ + kit.EventMatrixContract.Ev["EventThreeIndexed"], + paddedUint64(44), + paddedUint64(27), + paddedUint64(19), + }, + Data: nil, + }, + { + Address: contract2, + Topics: []ethtypes.EthBytes{ + kit.EventMatrixContract.Ev["EventTwoIndexed"], + paddedUint64(44), + paddedUint64(19), + }, + Data: nil, + }, + { + Address: contract2, + Topics: []ethtypes.EthBytes{ + kit.EventMatrixContract.Ev["EventOneIndexedWithData"], + paddedUint64(50), + }, + Data: paddedUint64(9), + }, + }, + }, + + { + name: "find all events with topic2 of 44 from contract2", + spec: kit.NewEthFilterBuilder().FromBlock(fromBlock).AddressOneOf(contract2).Topic2OneOf(paddedEthHash(paddedUint64(44))).Filter(), + + expected: []ExpectedEthLog{ + { + Address: contract2, + Topics: []ethtypes.EthBytes{ + kit.EventMatrixContract.Ev["EventThreeIndexed"], + paddedUint64(44), + paddedUint64(27), + paddedUint64(19), + }, + Data: nil, + }, + { + Address: contract2, + Topics: []ethtypes.EthBytes{ + kit.EventMatrixContract.Ev["EventTwoIndexed"], + paddedUint64(44), + paddedUint64(19), + }, + Data: nil, + }, + }, + }, + + { + name: "find all EventOneIndexedWithData events from contract1 or contract2", + spec: kit.NewEthFilterBuilder(). + FromBlockEpoch(0). + AddressOneOf(contract1, contract2). + Topic1OneOf(paddedEthHash(kit.EventMatrixContract.Ev["EventOneIndexedWithData"])). + Filter(), + + expected: []ExpectedEthLog{ + { + Address: contract1, + Topics: []ethtypes.EthBytes{ + kit.EventMatrixContract.Ev["EventOneIndexedWithData"], + paddedUint64(44), + }, + Data: paddedUint64(19), + }, + { + Address: contract1, + Topics: []ethtypes.EthBytes{ + kit.EventMatrixContract.Ev["EventOneIndexedWithData"], + paddedUint64(46), + }, + Data: paddedUint64(12), + }, + { + Address: contract2, + Topics: []ethtypes.EthBytes{ + kit.EventMatrixContract.Ev["EventOneIndexedWithData"], + paddedUint64(50), + }, + Data: paddedUint64(9), + }, + }, + }, + } +} + +func getCombinationFilterTestCases(contract1, contract2 ethtypes.EthAddress, fromBlock string) []filterTestCase { + topicCases := getTopicFilterTestCases(contract1, contract2, fromBlock) + addressCases := getAddressFilterTestCases(contract1, contract2, fromBlock) + + return append(topicCases, addressCases...) +} + type ExpectedEthLog struct { // Address is the address of the actor that produced the event log. Address ethtypes.EthAddress `json:"address"` @@ -1658,8 +1913,10 @@ type ExpectedEthLog struct { } func AssertEthLogs(t *testing.T, actual []*ethtypes.EthLog, expected []ExpectedEthLog, messages map[ethtypes.EthHash]msgInTipset) { + t.Helper() require := require.New(t) - // require.Equal(len(expected), len(actual), "number of results equal to expected") + + t.Logf("got %d ethlogs, wanted %d", len(actual), len(expected)) formatTopics := func(topics []ethtypes.EthBytes) string { ss := make([]string, len(topics)) @@ -1673,7 +1930,7 @@ func AssertEthLogs(t *testing.T, actual []*ethtypes.EthLog, expected []ExpectedE for _, elog := range actual { msg, exists := messages[elog.TransactionHash] - require.True(exists, "message seen on chain") + require.True(exists, "message not seen on chain") tsCid, err := msg.ts.Key().Cid() require.NoError(err) @@ -1726,7 +1983,7 @@ func AssertEthLogs(t *testing.T, actual []*ethtypes.EthLog, expected []ExpectedE buf.WriteString(fmt.Sprintf("event %d\n", i)) buf.WriteString(fmt.Sprintf(" emitter: %v\n", ev.Emitter)) for _, en := range ev.Entries { - buf.WriteString(fmt.Sprintf(" %s=%x\n", en.Key, decodeLogBytes(en.Value))) + buf.WriteString(fmt.Sprintf(" %s=%x\n", en.Key, en.Value)) } } @@ -1749,23 +2006,16 @@ func AssertEthLogs(t *testing.T, actual []*ethtypes.EthLog, expected []ExpectedE func parseEthLogsFromSubscriptionResponses(subResponses []ethtypes.EthSubscriptionResponse) ([]*ethtypes.EthLog, error) { elogs := make([]*ethtypes.EthLog, 0, len(subResponses)) for i := range subResponses { - rlist, ok := subResponses[i].Result.([]interface{}) + rmap, ok := subResponses[i].Result.(map[string]interface{}) if !ok { - return nil, xerrors.Errorf("expected subscription result to be []interface{}, but was %T", subResponses[i].Result) + return nil, xerrors.Errorf("expected subscription result entry to be map[string]interface{}, but was %T", subResponses[i].Result) } - for _, r := range rlist { - rmap, ok := r.(map[string]interface{}) - if !ok { - return nil, xerrors.Errorf("expected subscription result entry to be map[string]interface{}, but was %T", r) - } - - elog, err := ParseEthLog(rmap) - if err != nil { - return nil, err - } - elogs = append(elogs, elog) + elog, err := ParseEthLog(rmap) + if err != nil { + return nil, err } + elogs = append(elogs, elog) } return elogs, nil @@ -1929,18 +2179,6 @@ func paddedEthHash(orig []byte) ethtypes.EthHash { return ret } -func ethTopicHash(sig string) []byte { - hasher := sha3.NewLegacyKeccak256() - hasher.Write([]byte(sig)) - return hasher.Sum(nil) -} - -func ethFunctionHash(sig string) []byte { - hasher := sha3.NewLegacyKeccak256() - hasher.Write([]byte(sig)) - return hasher.Sum(nil)[:4] -} - func packUint64Values(vals ...uint64) []byte { ret := []byte{} for _, v := range vals { @@ -1962,86 +2200,3 @@ func unpackUint64Values(data []byte) []uint64 { } return vals } - -func newEthFilterBuilder() *ethFilterBuilder { return ðFilterBuilder{} } - -type ethFilterBuilder struct { - filter ethtypes.EthFilterSpec -} - -func (e *ethFilterBuilder) Filter() *ethtypes.EthFilterSpec { return &e.filter } - -func (e *ethFilterBuilder) FromBlock(v string) *ethFilterBuilder { - e.filter.FromBlock = &v - return e -} - -func (e *ethFilterBuilder) FromBlockEpoch(v abi.ChainEpoch) *ethFilterBuilder { - s := ethtypes.EthUint64(v).Hex() - e.filter.FromBlock = &s - return e -} - -func (e *ethFilterBuilder) ToBlock(v string) *ethFilterBuilder { - e.filter.ToBlock = &v - return e -} - -func (e *ethFilterBuilder) ToBlockEpoch(v abi.ChainEpoch) *ethFilterBuilder { - s := ethtypes.EthUint64(v).Hex() - e.filter.ToBlock = &s - return e -} - -func (e *ethFilterBuilder) BlockHash(h ethtypes.EthHash) *ethFilterBuilder { - e.filter.BlockHash = &h - return e -} - -func (e *ethFilterBuilder) AddressOneOf(as ...ethtypes.EthAddress) *ethFilterBuilder { - e.filter.Address = as - return e -} - -func (e *ethFilterBuilder) Topic1OneOf(hs ...ethtypes.EthHash) *ethFilterBuilder { - if len(e.filter.Topics) == 0 { - e.filter.Topics = make(ethtypes.EthTopicSpec, 1) - } - e.filter.Topics[0] = hs - return e -} - -func (e *ethFilterBuilder) Topic2OneOf(hs ...ethtypes.EthHash) *ethFilterBuilder { - for len(e.filter.Topics) < 2 { - e.filter.Topics = append(e.filter.Topics, nil) - } - e.filter.Topics[1] = hs - return e -} - -func (e *ethFilterBuilder) Topic3OneOf(hs ...ethtypes.EthHash) *ethFilterBuilder { - for len(e.filter.Topics) < 3 { - e.filter.Topics = append(e.filter.Topics, nil) - } - e.filter.Topics[2] = hs - return e -} - -func (e *ethFilterBuilder) Topic4OneOf(hs ...ethtypes.EthHash) *ethFilterBuilder { - for len(e.filter.Topics) < 4 { - e.filter.Topics = append(e.filter.Topics, nil) - } - e.filter.Topics[3] = hs - return e -} - -func decodeLogBytes(orig []byte) []byte { - if len(orig) == 0 { - return orig - } - decoded, err := cbg.ReadByteArray(bytes.NewReader(orig), uint64(len(orig))) - if err != nil { - return orig - } - return decoded -} diff --git a/itests/eth_transactions_test.go b/itests/eth_transactions_test.go index 0c8f1baa5..9afeb7bd5 100644 --- a/itests/eth_transactions_test.go +++ b/itests/eth_transactions_test.go @@ -83,6 +83,23 @@ func TestValueTransferValidSignature(t *testing.T) { // Success. require.EqualValues(t, ethtypes.EthUint64(0x1), receipt.Status) + + ethTx, err := client.EthGetTransactionByHash(ctx, &hash) + require.Nil(t, err) + require.EqualValues(t, ethAddr, ethTx.From) + require.EqualValues(t, ethAddr2, *ethTx.To) + require.EqualValues(t, tx.ChainID, ethTx.ChainID) + require.EqualValues(t, tx.Nonce, ethTx.Nonce) + require.EqualValues(t, hash, ethTx.Hash) + require.EqualValues(t, tx.Value, ethTx.Value) + require.EqualValues(t, 2, ethTx.Type) + require.EqualValues(t, ethtypes.EthBytes{}, ethTx.Input) + require.EqualValues(t, tx.GasLimit, ethTx.Gas) + require.EqualValues(t, tx.MaxFeePerGas, ethTx.MaxFeePerGas) + require.EqualValues(t, tx.MaxPriorityFeePerGas, ethTx.MaxPriorityFeePerGas) + require.EqualValues(t, tx.V, ethTx.V) + require.EqualValues(t, tx.R, ethTx.R) + require.EqualValues(t, tx.S, ethTx.S) } func TestLegacyTransaction(t *testing.T) { @@ -100,11 +117,9 @@ func TestLegacyTransaction(t *testing.T) { require.NoError(t, err) _, err = client.EVM().EthSendRawTransaction(ctx, txBytes) require.ErrorContains(t, err, "legacy transaction is not supported") - } func TestContractDeploymentValidSignature(t *testing.T) { - blockTime := 100 * time.Millisecond client, _, ens := kit.EnsembleMinimal(t, kit.MockProofs(), kit.ThroughRPC()) @@ -253,7 +268,6 @@ func TestContractInvocation(t *testing.T) { // Success. require.EqualValues(t, ethtypes.EthUint64(0x1), receipt.Status) - } func deployContractTx(ctx context.Context, client *kit.TestFullNode, ethAddr ethtypes.EthAddress, contract []byte) (*ethtypes.EthTxArgs, error) { diff --git a/itests/fevm_address_test.go b/itests/fevm_address_test.go index a23e96860..9eaac4647 100644 --- a/itests/fevm_address_test.go +++ b/itests/fevm_address_test.go @@ -6,7 +6,6 @@ import ( "encoding/hex" "os" "testing" - "time" "github.com/stretchr/testify/require" "golang.org/x/crypto/sha3" @@ -44,14 +43,43 @@ func effectiveEthAddressForCreate(t *testing.T, sender address.Address) ethtypes panic("unreachable") } +func createAndDeploy(ctx context.Context, t *testing.T, client *kit.TestFullNode, fromAddr address.Address, contract []byte) *api.MsgLookup { + // Create and deploy evm actor + + method := builtintypes.MethodsEAM.CreateExternal + contractParams := abi.CborBytes(contract) + params, actorsErr := actors.SerializeParams(&contractParams) + require.NoError(t, actorsErr) + + createMsg := &types.Message{ + To: builtintypes.EthereumAddressManagerActorAddr, + From: fromAddr, + Value: big.Zero(), + Method: method, + Params: params, + } + smsg, err := client.MpoolPushMessage(ctx, createMsg, nil) + require.NoError(t, err) + + wait, err := client.StateWaitMsg(ctx, smsg.Cid(), 0, 0, false) + require.NoError(t, err) + require.Equal(t, exitcode.Ok, wait.Receipt.ExitCode) + return wait +} + +func getEthAddressTX(ctx context.Context, t *testing.T, client *kit.TestFullNode, wait *api.MsgLookup, ethAddr ethtypes.EthAddress) ethtypes.EthAddress { + // Check if eth address returned from CreateExternal is the same as eth address predicted at the start + var createExternalReturn eam.CreateExternalReturn + err := createExternalReturn.UnmarshalCBOR(bytes.NewReader(wait.Receipt.Return)) + require.NoError(t, err) + + createdEthAddr, err := ethtypes.CastEthAddress(createExternalReturn.EthAddress[:]) + require.NoError(t, err) + return createdEthAddr +} + func TestAddressCreationBeforeDeploy(t *testing.T) { - kit.QuietMiningLogs() - - blockTime := 100 * time.Millisecond - client, _, ens := kit.EnsembleMinimal(t, kit.MockProofs(), kit.ThroughRPC()) - ens.InterconnectAll().BeginMining(blockTime) - - ctx, cancel := context.WithTimeout(context.Background(), time.Minute) + ctx, cancel, client := kit.SetupFEVMTest(t) defer cancel() // install contract @@ -72,22 +100,11 @@ func TestAddressCreationBeforeDeploy(t *testing.T) { contractFilAddr, err := ethAddr.ToFilecoinAddress() require.NoError(t, err) - // Send contract address some funds - + //transfer half the wallet balance bal, err := client.WalletBalance(ctx, client.DefaultKey.Address) require.NoError(t, err) sendAmount := big.Div(bal, big.NewInt(2)) - - sendMsg := &types.Message{ - From: fromAddr, - To: contractFilAddr, - Value: sendAmount, - } - signedMsg, err := client.MpoolPushMessage(ctx, sendMsg, nil) - require.NoError(t, err) - mLookup, err := client.StateWaitMsg(ctx, signedMsg.Cid(), 3, api.LookbackNoLimit, true) - require.NoError(t, err) - require.Equal(t, exitcode.Ok, mLookup.Receipt.ExitCode) + client.EVM().TransferValueOrFail(ctx, fromAddr, contractFilAddr, sendAmount) // Check if actor at new address is a placeholder actor actor, err := client.StateGetActor(ctx, contractFilAddr, types.EmptyTSK) @@ -95,40 +112,69 @@ func TestAddressCreationBeforeDeploy(t *testing.T) { require.True(t, builtin.IsPlaceholderActor(actor.Code)) // Create and deploy evm actor - - method := builtintypes.MethodsEAM.CreateExternal - contractParams := abi.CborBytes(contract) - params, err := actors.SerializeParams(&contractParams) - require.NoError(t, err) - - createMsg := &types.Message{ - To: builtintypes.EthereumAddressManagerActorAddr, - From: fromAddr, - Value: big.Zero(), - Method: method, - Params: params, - } - smsg, err := client.MpoolPushMessage(ctx, createMsg, nil) - require.NoError(t, err) - - wait, err := client.StateWaitMsg(ctx, smsg.Cid(), 0, 0, false) - require.NoError(t, err) - require.Equal(t, exitcode.Ok, wait.Receipt.ExitCode) + wait := createAndDeploy(ctx, t, client, fromAddr, contract) // Check if eth address returned from CreateExternal is the same as eth address predicted at the start - var createExternalReturn eam.CreateExternalReturn - err = createExternalReturn.UnmarshalCBOR(bytes.NewReader(wait.Receipt.Return)) - require.NoError(t, err) - - createdEthAddr, err := ethtypes.CastEthAddress(createExternalReturn.EthAddress[:]) - require.NoError(t, err) + createdEthAddr := getEthAddressTX(ctx, t, client, wait, ethAddr) require.Equal(t, ethAddr, createdEthAddr) // Check if newly deployed actor still has funds actorPostCreate, err := client.StateGetActor(ctx, contractFilAddr, types.EmptyTSK) require.NoError(t, err) - require.Equal(t, actorPostCreate.Balance, sendAmount) require.True(t, builtin.IsEvmActor(actorPostCreate.Code)) } + +func TestDeployAddressMultipleTimes(t *testing.T) { + ctx, cancel, client := kit.SetupFEVMTest(t) + defer cancel() + + // install contract + contractHex, err := os.ReadFile("contracts/SimpleCoin.hex") + require.NoError(t, err) + + contract, err := hex.DecodeString(string(contractHex)) + require.NoError(t, err) + + fromAddr, err := client.WalletDefaultAddress(ctx) + require.NoError(t, err) + + // We hash the f1/f3 address into the EVM's address space when deploying contracts from + // accounts. + effectiveEvmAddress := effectiveEthAddressForCreate(t, fromAddr) + ethAddr := client.EVM().ComputeContractAddress(effectiveEvmAddress, 1) + + contractFilAddr, err := ethAddr.ToFilecoinAddress() + require.NoError(t, err) + + // Send contract address small funds to init + sendAmount := big.NewInt(2) + client.EVM().TransferValueOrFail(ctx, fromAddr, contractFilAddr, sendAmount) + + // Check if actor at new address is a placeholder actor + actor, err := client.StateGetActor(ctx, contractFilAddr, types.EmptyTSK) + require.NoError(t, err) + require.True(t, builtin.IsPlaceholderActor(actor.Code)) + + // Create and deploy evm actor + wait := createAndDeploy(ctx, t, client, fromAddr, contract) + + // Check if eth address returned from CreateExternal is the same as eth address predicted at the start + createdEthAddr := getEthAddressTX(ctx, t, client, wait, ethAddr) + require.Equal(t, ethAddr, createdEthAddr) + + // Check if newly deployed actor still has funds + actorPostCreate, err := client.StateGetActor(ctx, contractFilAddr, types.EmptyTSK) + require.NoError(t, err) + require.Equal(t, actorPostCreate.Balance, sendAmount) + require.True(t, builtin.IsEvmActor(actorPostCreate.Code)) + + // Create and deploy evm actor + wait = createAndDeploy(ctx, t, client, fromAddr, contract) + + // Check that this time eth address returned from CreateExternal is not the same as eth address predicted at the start + createdEthAddr = getEthAddressTX(ctx, t, client, wait, ethAddr) + require.NotEqual(t, ethAddr, createdEthAddr) + +} diff --git a/itests/fevm_events_test.go b/itests/fevm_events_test.go index 30dd7015f..458ac3470 100644 --- a/itests/fevm_events_test.go +++ b/itests/fevm_events_test.go @@ -12,6 +12,7 @@ import ( "github.com/filecoin-project/go-address" + "github.com/filecoin-project/lotus/chain/types/ethtypes" "github.com/filecoin-project/lotus/itests/kit" ) @@ -45,38 +46,41 @@ func TestFEVMEvents(t *testing.T) { require.NoError(err) t.Logf("actor ID address is %s", idAddr) - // var ( - // earliest = "earliest" - // latest = "latest" - // ) - // - // // Install a filter. - // filter, err := client.EthNewFilter(ctx, &api.EthFilterSpec{ - // FromBlock: &earliest, - // ToBlock: &latest, - // }) - // require.NoError(err) - // - // // No logs yet. - // res, err := client.EthGetFilterLogs(ctx, filter) - // require.NoError(err) - // require.Empty(res.NewLogs) + var ( + earliest = "earliest" + latest = "latest" + ) + + // Install a filter. + filter, err := client.EthNewFilter(ctx, ðtypes.EthFilterSpec{ + FromBlock: &earliest, + ToBlock: &latest, + }) + require.NoError(err) + + // No logs yet. + res, err := client.EthGetFilterLogs(ctx, filter) + require.NoError(err) + require.Empty(res.Results) // log a zero topic event with data - ret := client.EVM().InvokeSolidity(ctx, fromAddr, idAddr, []byte{0x00, 0x00, 0x00, 0x00}, nil) + ret, err := client.EVM().InvokeSolidity(ctx, fromAddr, idAddr, []byte{0x00, 0x00, 0x00, 0x00}, nil) + require.NoError(err) require.True(ret.Receipt.ExitCode.IsSuccess(), "contract execution failed") require.NotNil(ret.Receipt.EventsRoot) fmt.Println(ret) fmt.Printf("Events:\n %+v\n", client.EVM().LoadEvents(ctx, *ret.Receipt.EventsRoot)) // log a zero topic event with no data - ret = client.EVM().InvokeSolidity(ctx, fromAddr, idAddr, []byte{0x00, 0x00, 0x00, 0x01}, nil) + ret, err = client.EVM().InvokeSolidity(ctx, fromAddr, idAddr, []byte{0x00, 0x00, 0x00, 0x01}, nil) + require.NoError(err) require.True(ret.Receipt.ExitCode.IsSuccess(), "contract execution failed") fmt.Println(ret) fmt.Printf("Events:\n %+v\n", client.EVM().LoadEvents(ctx, *ret.Receipt.EventsRoot)) // log a four topic event with data - ret = client.EVM().InvokeSolidity(ctx, fromAddr, idAddr, []byte{0x00, 0x00, 0x00, 0x02}, nil) + ret, err = client.EVM().InvokeSolidity(ctx, fromAddr, idAddr, []byte{0x00, 0x00, 0x00, 0x02}, nil) + require.NoError(err) require.True(ret.Receipt.ExitCode.IsSuccess(), "contract execution failed") fmt.Println(ret) fmt.Printf("Events:\n %+v\n", client.EVM().LoadEvents(ctx, *ret.Receipt.EventsRoot)) diff --git a/itests/fevm_test.go b/itests/fevm_test.go index e05b0e2cc..6cdd440dd 100644 --- a/itests/fevm_test.go +++ b/itests/fevm_test.go @@ -1,17 +1,23 @@ package itests import ( + "bytes" "context" + "crypto/rand" + "encoding/binary" "encoding/hex" + "fmt" "testing" - "time" "github.com/stretchr/testify/require" "github.com/filecoin-project/go-address" + "github.com/filecoin-project/go-state-types/big" builtintypes "github.com/filecoin-project/go-state-types/builtin" + "github.com/filecoin-project/go-state-types/exitcode" "github.com/filecoin-project/go-state-types/manifest" + "github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types/ethtypes" "github.com/filecoin-project/lotus/itests/kit" @@ -36,19 +42,141 @@ func inputDataFromFrom(ctx context.Context, t *testing.T, client *kit.TestFullNo return inputData } -func setupFEVMTest(t *testing.T) (context.Context, context.CancelFunc, *kit.TestFullNode) { - kit.QuietMiningLogs() - blockTime := 100 * time.Millisecond - client, _, ens := kit.EnsembleMinimal(t, kit.MockProofs(), kit.ThroughRPC()) - ens.InterconnectAll().BeginMining(blockTime) - ctx, cancel := context.WithTimeout(context.Background(), time.Minute) - return ctx, cancel, client +func decodeOutputToUint64(output []byte) (uint64, error) { + var result uint64 + buf := bytes.NewReader(output[len(output)-8:]) + err := binary.Read(buf, binary.BigEndian, &result) + return result, err +} +func buildInputFromuint64(number uint64) []byte { + // Convert the number to a binary uint64 array + binaryNumber := make([]byte, 8) + binary.BigEndian.PutUint64(binaryNumber, number) + return inputDataFromArray(binaryNumber) +} + +// recursive delegate calls that fail due to gas limits are currently getting to 229 iterations +// before running out of gas +func recursiveDelegatecallFail(ctx context.Context, t *testing.T, client *kit.TestFullNode, filename string, count uint64) { + expectedIterationsBeforeFailing := int(220) + fromAddr, idAddr := client.EVM().DeployContractFromFilename(ctx, filename) + t.Log("recursion count - ", count) + inputData := buildInputFromuint64(count) + _, _, err := client.EVM().InvokeContractByFuncName(ctx, fromAddr, idAddr, "recursiveCall(uint256)", inputData) + + require.NoError(t, err) + + result, _, err := client.EVM().InvokeContractByFuncName(ctx, fromAddr, idAddr, "totalCalls()", []byte{}) + require.NoError(t, err) + + resultUint, err := decodeOutputToUint64(result) + require.NoError(t, err) + + require.NotEqual(t, int(resultUint), int(count)) + require.Equal(t, expectedIterationsBeforeFailing, int(resultUint)) +} +func recursiveDelegatecallSuccess(ctx context.Context, t *testing.T, client *kit.TestFullNode, filename string, count uint64) { + t.Log("Count - ", count) + + fromAddr, idAddr := client.EVM().DeployContractFromFilename(ctx, filename) + inputData := buildInputFromuint64(count) + _, _, err := client.EVM().InvokeContractByFuncName(ctx, fromAddr, idAddr, "recursiveCall(uint256)", inputData) + require.NoError(t, err) + + result, _, err := client.EVM().InvokeContractByFuncName(ctx, fromAddr, idAddr, "totalCalls()", []byte{}) + require.NoError(t, err) + + resultUint, err := decodeOutputToUint64(result) + require.NoError(t, err) + + require.Equal(t, int(count), int(resultUint)) +} + +// TestFEVMRecursive does a basic fevm contract installation and invocation +func TestFEVMRecursive(t *testing.T) { + callCounts := []uint64{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 100, 230, 330} + ctx, cancel, client := kit.SetupFEVMTest(t) + defer cancel() + filename := "contracts/Recursive.hex" + fromAddr, idAddr := client.EVM().DeployContractFromFilename(ctx, filename) + + // Successful calls + for _, callCount := range callCounts { + callCount := callCount // linter unhappy unless callCount is local to loop + t.Run(fmt.Sprintf("TestFEVMRecursive%d", callCount), func(t *testing.T) { + _, _, err := client.EVM().InvokeContractByFuncName(ctx, fromAddr, idAddr, "recursiveCall(uint256)", buildInputFromuint64(callCount)) + require.NoError(t, err) + }) + } + +} + +func TestFEVMRecursiveFail(t *testing.T) { + ctx, cancel, client := kit.SetupFEVMTest(t) + defer cancel() + filename := "contracts/Recursive.hex" + fromAddr, idAddr := client.EVM().DeployContractFromFilename(ctx, filename) + + // Unsuccessful calls + failCallCounts := []uint64{340, 400, 600, 850, 1000} + for _, failCallCount := range failCallCounts { + failCallCount := failCallCount // linter unhappy unless callCount is local to loop + t.Run(fmt.Sprintf("TestFEVMRecursiveFail%d", failCallCount), func(t *testing.T) { + _, wait, err := client.EVM().InvokeContractByFuncName(ctx, fromAddr, idAddr, "recursiveCall(uint256)", buildInputFromuint64(failCallCount)) + require.Error(t, err) + require.Equal(t, exitcode.ExitCode(37), wait.Receipt.ExitCode) + }) + } +} + +func TestFEVMRecursive1(t *testing.T) { + callCount := 1 + ctx, cancel, client := kit.SetupFEVMTest(t) + defer cancel() + filename := "contracts/Recursive.hex" + fromAddr, idAddr := client.EVM().DeployContractFromFilename(ctx, filename) + _, ret, err := client.EVM().InvokeContractByFuncName(ctx, fromAddr, idAddr, "recursive1()", []byte{}) + require.NoError(t, err) + events := client.EVM().LoadEvents(ctx, *ret.Receipt.EventsRoot) + require.Equal(t, callCount, len(events)) +} +func TestFEVMRecursive2(t *testing.T) { + ctx, cancel, client := kit.SetupFEVMTest(t) + defer cancel() + filename := "contracts/Recursive.hex" + fromAddr, idAddr := client.EVM().DeployContractFromFilename(ctx, filename) + _, ret, err := client.EVM().InvokeContractByFuncName(ctx, fromAddr, idAddr, "recursive2()", []byte{}) + require.NoError(t, err) + events := client.EVM().LoadEvents(ctx, *ret.Receipt.EventsRoot) + require.Equal(t, 2, len(events)) +} + +// TestFEVMRecursiveDelegatecallCount tests the maximum delegatecall recursion depth. It currently +// succeeds succeeds up to 237 times. +func TestFEVMRecursiveDelegatecallCount(t *testing.T) { + + ctx, cancel, client := kit.SetupFEVMTest(t) + defer cancel() + + highestSuccessCount := uint64(225) + + filename := "contracts/RecursiveDelegeatecall.hex" + recursiveDelegatecallSuccess(ctx, t, client, filename, uint64(1)) + recursiveDelegatecallSuccess(ctx, t, client, filename, uint64(2)) + recursiveDelegatecallSuccess(ctx, t, client, filename, uint64(10)) + recursiveDelegatecallSuccess(ctx, t, client, filename, uint64(100)) + recursiveDelegatecallSuccess(ctx, t, client, filename, highestSuccessCount) + + recursiveDelegatecallFail(ctx, t, client, filename, highestSuccessCount+1) + recursiveDelegatecallFail(ctx, t, client, filename, uint64(1000)) + recursiveDelegatecallFail(ctx, t, client, filename, uint64(10000000)) + } // TestFEVMBasic does a basic fevm contract installation and invocation func TestFEVMBasic(t *testing.T) { - ctx, cancel, client := setupFEVMTest(t) + ctx, cancel, client := kit.SetupFEVMTest(t) defer cancel() filename := "contracts/SimpleCoin.hex" @@ -58,7 +186,8 @@ func TestFEVMBasic(t *testing.T) { // invoke the contract with owner { inputData := inputDataFromFrom(ctx, t, client, fromAddr) - result := client.EVM().InvokeContractByFuncName(ctx, fromAddr, idAddr, "getBalance(address)", inputData) + result, _, err := client.EVM().InvokeContractByFuncName(ctx, fromAddr, idAddr, "getBalance(address)", inputData) + require.NoError(t, err) expectedResult, err := hex.DecodeString("0000000000000000000000000000000000000000000000000000000000002710") require.NoError(t, err) @@ -68,8 +197,9 @@ func TestFEVMBasic(t *testing.T) { // invoke the contract with non owner { inputData := inputDataFromFrom(ctx, t, client, fromAddr) - inputData[31]++ // change the pub address to one that has 0 balance by incrementing the last byte of the address - result := client.EVM().InvokeContractByFuncName(ctx, fromAddr, idAddr, "getBalance(address)", inputData) + inputData[31]++ // change the pub address to one that has 0 balance by modifying the last byte of the address + result, _, err := client.EVM().InvokeContractByFuncName(ctx, fromAddr, idAddr, "getBalance(address)", inputData) + require.NoError(t, err) expectedResult, err := hex.DecodeString("0000000000000000000000000000000000000000000000000000000000000000") require.NoError(t, err) @@ -79,7 +209,7 @@ func TestFEVMBasic(t *testing.T) { // TestFEVMETH0 tests that the ETH0 actor is in genesis func TestFEVMETH0(t *testing.T) { - ctx, cancel, client := setupFEVMTest(t) + ctx, cancel, client := kit.SetupFEVMTest(t) defer cancel() eth0id, err := address.NewIDAddress(1001) @@ -98,7 +228,47 @@ func TestFEVMETH0(t *testing.T) { // TestFEVMDelegateCall deploys two contracts and makes a delegate call transaction func TestFEVMDelegateCall(t *testing.T) { - ctx, cancel, client := setupFEVMTest(t) + ctx, cancel, client := kit.SetupFEVMTest(t) + defer cancel() + + //install contract Actor + filenameActor := "contracts/DelegatecallActor.hex" + fromAddr, actorAddr := client.EVM().DeployContractFromFilename(ctx, filenameActor) + //install contract Storage + filenameStorage := "contracts/DelegatecallStorage.hex" + fromAddrStorage, storageAddr := client.EVM().DeployContractFromFilename(ctx, filenameStorage) + require.Equal(t, fromAddr, fromAddrStorage) + + //call Contract Storage which makes a delegatecall to contract Actor + //this contract call sets the "counter" variable to 7, from default value 0 + inputDataContract := inputDataFromFrom(ctx, t, client, actorAddr) + inputDataValue := inputDataFromArray([]byte{7}) + inputData := append(inputDataContract, inputDataValue...) + + //verify that the returned value of the call to setvars is 7 + result, _, err := client.EVM().InvokeContractByFuncName(ctx, fromAddr, storageAddr, "setVars(address,uint256)", inputData) + require.NoError(t, err) + expectedResult, err := hex.DecodeString("0000000000000000000000000000000000000000000000000000000000000007") + require.NoError(t, err) + require.Equal(t, result, expectedResult) + + //test the value is 7 a second way by calling the getter + result, _, err = client.EVM().InvokeContractByFuncName(ctx, fromAddr, storageAddr, "getCounter()", []byte{}) + require.NoError(t, err) + require.Equal(t, result, expectedResult) + + //test the value is 0 via calling the getter on the Actor contract + result, _, err = client.EVM().InvokeContractByFuncName(ctx, fromAddr, actorAddr, "getCounter()", []byte{}) + require.NoError(t, err) + expectedResultActor, err := hex.DecodeString("0000000000000000000000000000000000000000000000000000000000000000") + require.NoError(t, err) + require.Equal(t, result, expectedResultActor) +} + +// TestFEVMDelegateCallRevert makes a delegatecall action and then calls revert. +// the state should not have changed because of the revert +func TestFEVMDelegateCallRevert(t *testing.T) { + ctx, cancel, client := kit.SetupFEVMTest(t) defer cancel() //install contract Actor @@ -117,20 +287,245 @@ func TestFEVMDelegateCall(t *testing.T) { inputData := append(inputDataContract, inputDataValue...) //verify that the returned value of the call to setvars is 7 - result := client.EVM().InvokeContractByFuncName(ctx, fromAddr, storageAddr, "setVars(address,uint256)", inputData) - expectedResult, err := hex.DecodeString("0000000000000000000000000000000000000000000000000000000000000007") - require.NoError(t, err) - require.Equal(t, result, expectedResult) + _, wait, err := client.EVM().InvokeContractByFuncName(ctx, fromAddr, storageAddr, "setVarsRevert(address,uint256)", inputData) + require.Error(t, err) + require.Equal(t, exitcode.ExitCode(33), wait.Receipt.ExitCode) - //test the value is 7 via calling the getter - result = client.EVM().InvokeContractByFuncName(ctx, fromAddr, storageAddr, "getCounter()", []byte{}) + //test the value is 0 via calling the getter and was not set to 7 + expectedResult, err := hex.DecodeString("0000000000000000000000000000000000000000000000000000000000000000") + require.NoError(t, err) + result, _, err := client.EVM().InvokeContractByFuncName(ctx, fromAddr, storageAddr, "getCounter()", []byte{}) + require.NoError(t, err) require.Equal(t, result, expectedResult) //test the value is 0 via calling the getter on the Actor contract - result = client.EVM().InvokeContractByFuncName(ctx, fromAddr, actorAddr, "getCounter()", []byte{}) - expectedResultActor, err := hex.DecodeString("0000000000000000000000000000000000000000000000000000000000000000") + result, _, err = client.EVM().InvokeContractByFuncName(ctx, fromAddr, actorAddr, "getCounter()", []byte{}) require.NoError(t, err) - require.Equal(t, result, expectedResultActor) + require.Equal(t, result, expectedResult) +} + +// TestFEVMSimpleRevert makes a call that is a simple revert +func TestFEVMSimpleRevert(t *testing.T) { + ctx, cancel, client := kit.SetupFEVMTest(t) + defer cancel() + + //install contract Actor + filenameStorage := "contracts/DelegatecallStorage.hex" + fromAddr, contractAddr := client.EVM().DeployContractFromFilename(ctx, filenameStorage) + + //call revert + _, wait, err := client.EVM().InvokeContractByFuncName(ctx, fromAddr, contractAddr, "revert()", []byte{}) + + require.Equal(t, wait.Receipt.ExitCode, exitcode.ExitCode(33)) + require.Error(t, err) +} + +// TestFEVMSelfDestruct creates a contract that just has a self destruct feature and calls it +func TestFEVMSelfDestruct(t *testing.T) { + ctx, cancel, client := kit.SetupFEVMTest(t) + defer cancel() + + //install contract Actor + filenameStorage := "contracts/SelfDestruct.hex" + fromAddr, contractAddr := client.EVM().DeployContractFromFilename(ctx, filenameStorage) + + //call destroy + _, _, err := client.EVM().InvokeContractByFuncName(ctx, fromAddr, contractAddr, "destroy()", []byte{}) + require.NoError(t, err) + + //call destroy a second time and also no error + _, _, err = client.EVM().InvokeContractByFuncName(ctx, fromAddr, contractAddr, "destroy()", []byte{}) + require.NoError(t, err) +} + +// TestFEVMTestApp deploys a fairly complex app contract and confirms it works as expected +func TestFEVMTestApp(t *testing.T) { + ctx, cancel, client := kit.SetupFEVMTest(t) + defer cancel() + + //install contract Actor + filenameStorage := "contracts/TestApp.hex" + fromAddr, contractAddr := client.EVM().DeployContractFromFilename(ctx, filenameStorage) + + inputData, err := hex.DecodeString("0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000066162636465660000000000000000000000000000000000000000000000000000") // sending string "abcdef" and int 7 - constructed using remix + require.NoError(t, err) + _, _, err = client.EVM().InvokeContractByFuncName(ctx, fromAddr, contractAddr, "new_Test(string,uint256)", inputData) + require.NoError(t, err) + + inputData, err = hex.DecodeString("0000000000000000000000000000000000000000000000000000000000000000") + require.NoError(t, err) + + _, _, err = client.EVM().InvokeContractByFuncName(ctx, fromAddr, contractAddr, "get_Test_N(uint256)", inputData) + require.NoError(t, err) + +} + +// TestFEVMTestApp creates a contract that just has a self destruct feature and calls it +func TestFEVMTestConstructor(t *testing.T) { + ctx, cancel, client := kit.SetupFEVMTest(t) + defer cancel() + + //install contract Actor + filenameStorage := "contracts/Constructor.hex" + fromAddr, contractAddr := client.EVM().DeployContractFromFilename(ctx, filenameStorage) + + //input = uint256{7}. set value and confirm tx success + inputData, err := hex.DecodeString("0000000000000000000000000000000000000000000000000000000000000007") + require.NoError(t, err) + _, _, err = client.EVM().InvokeContractByFuncName(ctx, fromAddr, contractAddr, "new_Test(uint256)", inputData) + require.NoError(t, err) + +} + +// TestFEVMAutoSelfDestruct creates a contract that just has a self destruct feature and calls it +func TestFEVMAutoSelfDestruct(t *testing.T) { + ctx, cancel, client := kit.SetupFEVMTest(t) + defer cancel() + + //install contract Actor + filenameStorage := "contracts/AutoSelfDestruct.hex" + fromAddr, contractAddr := client.EVM().DeployContractFromFilename(ctx, filenameStorage) + + //call destroy + _, _, err := client.EVM().InvokeContractByFuncName(ctx, fromAddr, contractAddr, "destroy()", []byte{}) + require.NoError(t, err) +} + +// TestFEVMTestApp creates a contract that just has a self destruct feature and calls it +func TestFEVMTestSendToContract(t *testing.T) { + ctx, cancel, client := kit.SetupFEVMTest(t) + defer cancel() + + bal, err := client.WalletBalance(ctx, client.DefaultKey.Address) + require.NoError(t, err) + + //install contract TestApp + filenameStorage := "contracts/SelfDestruct.hex" + fromAddr, contractAddr := client.EVM().DeployContractFromFilename(ctx, filenameStorage) + + //transfer half balance to contract + + sendAmount := big.Div(bal, big.NewInt(2)) + client.EVM().TransferValueOrFail(ctx, fromAddr, contractAddr, sendAmount) + + //call self destruct which should return balance + _, _, err = client.EVM().InvokeContractByFuncName(ctx, fromAddr, contractAddr, "destroy()", []byte{}) + require.NoError(t, err) + + finalBalanceMinimum := types.FromFil(uint64(99_999_999)) // 100 million FIL - 1 FIL for gas upper bounds + finalBal, err := client.WalletBalance(ctx, client.DefaultKey.Address) + require.NoError(t, err) + require.Equal(t, true, finalBal.GreaterThan(finalBalanceMinimum)) +} + +// creates a contract that would fail when tx are sent to it +// on eth but on fevm it succeeds +// example failing on testnet https://goerli.etherscan.io/address/0x2ff1525e060169dbf97b9461758c8f701f107cd2 +func TestFEVMTestNotPayable(t *testing.T) { + + ctx, cancel, client := kit.SetupFEVMTest(t) + defer cancel() + + fromAddr := client.DefaultKey.Address + t.Log("from - ", fromAddr) + + //create contract A + filenameStorage := "contracts/NotPayable.hex" + fromAddr, contractAddr := client.EVM().DeployContractFromFilename(ctx, filenameStorage) + sendAmount := big.NewInt(10_000_000) + + client.EVM().TransferValueOrFail(ctx, fromAddr, contractAddr, sendAmount) + +} + +// tx to non function succeeds +func TestFEVMSendCall(t *testing.T) { + ctx, cancel, client := kit.SetupFEVMTest(t) + defer cancel() + + //install contract + filenameActor := "contracts/GasSendTest.hex" + fromAddr, contractAddr := client.EVM().DeployContractFromFilename(ctx, filenameActor) + + _, _, err := client.EVM().InvokeContractByFuncName(ctx, fromAddr, contractAddr, "x()", []byte{}) + require.NoError(t, err) +} + +// creates a contract that would fail when tx are sent to it +// on eth but on fevm it succeeds +// example on goerli of tx failing https://goerli.etherscan.io/address/0xec037bdc9a79420985a53a49fdae3ccf8989909b +func TestFEVMSendGasLimit(t *testing.T) { + ctx, cancel, client := kit.SetupFEVMTest(t) + defer cancel() + + //install contract + filenameActor := "contracts/GasLimitSend.hex" + fromAddr, contractAddr := client.EVM().DeployContractFromFilename(ctx, filenameActor) + + //send $ to contract + //transfer 1 attoFIL to contract + sendAmount := big.MustFromString("1") + + client.EVM().TransferValueOrFail(ctx, fromAddr, contractAddr, sendAmount) + _, _, err := client.EVM().InvokeContractByFuncName(ctx, fromAddr, contractAddr, "getDataLength()", []byte{}) + require.NoError(t, err) + +} + +// TestFEVMDelegateCall deploys the two contracts in TestFEVMDelegateCall but instead of A calling B, A calls A which should cause A to cause A in an infinite loop and should give a reasonable error +func TestFEVMDelegateCallRecursiveFail(t *testing.T) { + //TODO change the gas limit of this invocation and confirm that the number of errors is + // different + ctx, cancel, client := kit.SetupFEVMTest(t) + defer cancel() + + //install contract Actor + filenameActor := "contracts/DelegatecallStorage.hex" + fromAddr, actorAddr := client.EVM().DeployContractFromFilename(ctx, filenameActor) + + //any data will do for this test that fails + inputDataContract := inputDataFromFrom(ctx, t, client, actorAddr) + inputDataValue := inputDataFromArray([]byte{7}) + inputData := append(inputDataContract, inputDataValue...) + + //verify that we run out of gas then revert. + _, wait, err := client.EVM().InvokeContractByFuncName(ctx, fromAddr, actorAddr, "setVarsSelf(address,uint256)", inputData) + require.Error(t, err) + require.Equal(t, exitcode.ExitCode(33), wait.Receipt.ExitCode) + + //assert no fatal errors but still there are errors:: + errorAny := "fatal error" + require.NotContains(t, err.Error(), errorAny) +} + +// TestFEVMTestSendValueThroughContracts creates A and B contract and exchanges value +// and self destructs and accounts for value sent +func TestFEVMTestSendValueThroughContractsAndDestroy(t *testing.T) { + + ctx, cancel, client := kit.SetupFEVMTest(t) + defer cancel() + + fromAddr := client.DefaultKey.Address + t.Log("from - ", fromAddr) + + //create contract A + filenameStorage := "contracts/ValueSender.hex" + fromAddr, contractAddr := client.EVM().DeployContractFromFilename(ctx, filenameStorage) + + //create contract B + ret, _, err := client.EVM().InvokeContractByFuncName(ctx, fromAddr, contractAddr, "createB()", []byte{}) + require.NoError(t, err) + + ethAddr, err := ethtypes.CastEthAddress(ret[12:]) + require.NoError(t, err) + contractBAddress, err := ethAddr.ToFilecoinAddress() + require.NoError(t, err) + t.Log("contractBAddress - ", contractBAddress) + + //self destruct contract B + _, _, err = client.EVM().InvokeContractByFuncName(ctx, fromAddr, contractBAddress, "selfDestruct()", []byte{}) + require.NoError(t, err) + } func TestEVMRpcDisable(t *testing.T) { @@ -139,3 +534,255 @@ func TestEVMRpcDisable(t *testing.T) { _, err := client.EthBlockNumber(context.Background()) require.ErrorContains(t, err, "module disabled, enable with Fevm.EnableEthRPC") } + +// TestFEVMRecursiveFuncCall deploys a contract and makes a recursive function calls +func TestFEVMRecursiveFuncCall(t *testing.T) { + ctx, cancel, client := kit.SetupFEVMTest(t) + defer cancel() + + //install contract Actor + filenameActor := "contracts/StackFunc.hex" + fromAddr, actorAddr := client.EVM().DeployContractFromFilename(ctx, filenameActor) + + testN := func(n int, ex exitcode.ExitCode) func(t *testing.T) { + return func(t *testing.T) { + inputData := make([]byte, 32) + binary.BigEndian.PutUint64(inputData[24:], uint64(n)) + client.EVM().InvokeContractByFuncNameExpectExit(ctx, fromAddr, actorAddr, "exec1(uint256)", inputData, ex) + } + } + + t.Run("n=0", testN(0, exitcode.Ok)) + t.Run("n=1", testN(1, exitcode.Ok)) + t.Run("n=20", testN(20, exitcode.Ok)) + t.Run("n=200", testN(200, exitcode.Ok)) + t.Run("n=507", testN(507, exitcode.Ok)) + t.Run("n=508", testN(508, exitcode.ExitCode(37))) // 37 means stack overflow +} + +// TestFEVMRecursiveActorCall deploys a contract and makes a recursive actor calls +func TestFEVMRecursiveActorCall(t *testing.T) { + ctx, cancel, client := kit.SetupFEVMTest(t) + defer cancel() + + //install contract Actor + filenameActor := "contracts/RecCall.hex" + fromAddr, actorAddr := client.EVM().DeployContractFromFilename(ctx, filenameActor) + + testN := func(n, r int, ex exitcode.ExitCode) func(t *testing.T) { + return func(t *testing.T) { + inputData := make([]byte, 32*3) + binary.BigEndian.PutUint64(inputData[24:], uint64(n)) + binary.BigEndian.PutUint64(inputData[32+24:], uint64(n)) + binary.BigEndian.PutUint64(inputData[32+32+24:], uint64(r)) + + client.EVM().InvokeContractByFuncNameExpectExit(ctx, fromAddr, actorAddr, "exec1(uint256,uint256,uint256)", inputData, ex) + } + } + + t.Run("n=0,r=1", testN(0, 1, exitcode.Ok)) + t.Run("n=1,r=1", testN(1, 1, exitcode.Ok)) + t.Run("n=20,r=1", testN(20, 1, exitcode.Ok)) + t.Run("n=200,r=1", testN(200, 1, exitcode.Ok)) + t.Run("n=251,r=1", testN(251, 1, exitcode.Ok)) + + t.Run("n=252,r=1-fails", testN(252, 1, exitcode.ExitCode(37))) // 37 means stack overflow + + t.Run("n=0,r=10", testN(0, 10, exitcode.Ok)) + t.Run("n=1,r=10", testN(1, 10, exitcode.Ok)) + t.Run("n=20,r=10", testN(20, 10, exitcode.Ok)) + t.Run("n=200,r=10", testN(200, 10, exitcode.Ok)) + t.Run("n=251,r=10", testN(251, 10, exitcode.Ok)) + + t.Run("n=252,r=10-fails", testN(252, 10, exitcode.ExitCode(37))) + + t.Run("n=0,r=32", testN(0, 32, exitcode.Ok)) + t.Run("n=1,r=32", testN(1, 32, exitcode.Ok)) + t.Run("n=20,r=32", testN(20, 32, exitcode.Ok)) + t.Run("n=200,r=32", testN(200, 32, exitcode.Ok)) + t.Run("n=251,r=32", testN(251, 32, exitcode.Ok)) + + t.Run("n=0,r=252", testN(0, 252, exitcode.Ok)) + t.Run("n=251,r=166", testN(251, 166, exitcode.Ok)) + + t.Run("n=0,r=253-fails", testN(0, 253, exitcode.ExitCode(33))) // 33 means transaction reverted + t.Run("n=251,r=167-fails", testN(251, 167, exitcode.ExitCode(33))) +} + +// TestFEVMRecursiveActorCallEstimate +func TestFEVMRecursiveActorCallEstimate(t *testing.T) { + ctx, cancel, client := kit.SetupFEVMTest(t) + defer cancel() + + //install contract Actor + filenameActor := "contracts/ExternalRecursiveCallSimple.hex" + _, actorAddr := client.EVM().DeployContractFromFilename(ctx, filenameActor) + + contractAddr, err := ethtypes.EthAddressFromFilecoinAddress(actorAddr) + require.NoError(t, err) + + // create a new Ethereum account + key, ethAddr, ethFilAddr := client.EVM().NewAccount() + kit.SendFunds(ctx, t, client, ethFilAddr, types.FromFil(1000)) + + makeParams := func(r int) []byte { + funcSignature := "exec1(uint256)" + entryPoint := kit.CalcFuncSignature(funcSignature) + + inputData := make([]byte, 32) + binary.BigEndian.PutUint64(inputData[24:], uint64(r)) + + params := append(entryPoint, inputData...) + + return params + } + + testN := func(r int) func(t *testing.T) { + return func(t *testing.T) { + t.Logf("running with %d recursive calls", r) + + params := makeParams(r) + gaslimit, err := client.EthEstimateGas(ctx, ethtypes.EthCall{ + From: ðAddr, + To: &contractAddr, + Data: params, + }) + require.NoError(t, err) + require.LessOrEqual(t, int64(gaslimit), build.BlockGasLimit) + + t.Logf("EthEstimateGas GasLimit=%d", gaslimit) + + maxPriorityFeePerGas, err := client.EthMaxPriorityFeePerGas(ctx) + require.NoError(t, err) + + nonce, err := client.MpoolGetNonce(ctx, ethFilAddr) + require.NoError(t, err) + + tx := ðtypes.EthTxArgs{ + ChainID: build.Eip155ChainId, + To: &contractAddr, + Value: big.Zero(), + Nonce: int(nonce), + MaxFeePerGas: types.NanoFil, + MaxPriorityFeePerGas: big.Int(maxPriorityFeePerGas), + GasLimit: int(gaslimit), + Input: params, + V: big.Zero(), + R: big.Zero(), + S: big.Zero(), + } + + client.EVM().SignTransaction(tx, key.PrivateKey) + hash := client.EVM().SubmitTransaction(ctx, tx) + + smsg, err := tx.ToSignedMessage() + require.NoError(t, err) + + _, err = client.StateWaitMsg(ctx, smsg.Cid(), 0, 0, false) + require.NoError(t, err) + + receipt, err := client.EthGetTransactionReceipt(ctx, hash) + require.NoError(t, err) + require.NotNil(t, receipt) + + t.Logf("Receipt GasUsed=%d", receipt.GasUsed) + t.Logf("Ratio %0.2f", float64(receipt.GasUsed)/float64(gaslimit)) + t.Logf("Overestimate %0.2f", ((float64(gaslimit)/float64(receipt.GasUsed))-1)*100) + + require.EqualValues(t, ethtypes.EthUint64(1), receipt.Status) + } + } + + t.Run("n=1", testN(1)) + t.Run("n=2", testN(2)) + t.Run("n=3", testN(3)) + t.Run("n=4", testN(4)) + t.Run("n=5", testN(5)) + t.Run("n=10", testN(10)) + t.Run("n=20", testN(20)) + t.Run("n=30", testN(30)) + t.Run("n=40", testN(40)) + t.Run("n=50", testN(50)) + t.Run("n=100", testN(100)) +} + +// TestFEVM deploys a contract while sending value to it +func TestFEVMDeployWithValue(t *testing.T) { + ctx, cancel, client := kit.SetupFEVMTest(t) + defer cancel() + + //testValue is the amount sent when the contract is created + //at the end we check that the new contract has a balance of testValue + testValue := big.NewInt(20) + + // deploy DeployValueTest which creates NewContract + // testValue is sent to DeployValueTest and that amount is + // also sent to NewContract + filenameActor := "contracts/DeployValueTest.hex" + fromAddr, idAddr := client.EVM().DeployContractFromFilenameWithValue(ctx, filenameActor, testValue) + + //call getNewContractBalance to find the value of NewContract + ret, _, err := client.EVM().InvokeContractByFuncName(ctx, fromAddr, idAddr, "getNewContractBalance()", []byte{}) + require.NoError(t, err) + + contractBalance, err := decodeOutputToUint64(ret) + require.NoError(t, err) + + //require balance of NewContract is testValue + require.Equal(t, testValue.Uint64(), contractBalance) +} + +func TestFEVMDestroyCreate2(t *testing.T) { + ctx, cancel, client := kit.SetupFEVMTest(t) + defer cancel() + + //deploy create2 factory contract + filename := "contracts/Create2Factory.hex" + fromAddr, idAddr := client.EVM().DeployContractFromFilename(ctx, filename) + + //construct salt for create2 + salt := make([]byte, 32) + _, err := rand.Read(salt) + require.NoError(t, err) + + //deploy contract using create2 factory + selfDestructAddress, _, err := client.EVM().InvokeContractByFuncName(ctx, fromAddr, idAddr, "deploy(bytes32)", salt) + require.NoError(t, err) + + //convert to filecoin actor address so we can call InvokeContractByFuncName + ea, err := ethtypes.CastEthAddress(selfDestructAddress[12:]) + require.NoError(t, err) + selfDestructAddressActor, err := ea.ToFilecoinAddress() + require.NoError(t, err) + + //read sender property from contract + ret, _, err := client.EVM().InvokeContractByFuncName(ctx, fromAddr, selfDestructAddressActor, "sender()", []byte{}) + require.NoError(t, err) + + //assert contract has correct data + ethFromAddr := inputDataFromFrom(ctx, t, client, fromAddr) + require.Equal(t, ethFromAddr, ret) + + //run test() which 1.calls sefldestruct 2. verifies sender() is the correct value 3. attempts and fails to deploy via create2 + testSenderAddress, _, err := client.EVM().InvokeContractByFuncName(ctx, fromAddr, idAddr, "test(address)", selfDestructAddress) + require.NoError(t, err) + require.Equal(t, testSenderAddress, ethFromAddr) + + //read sender() but get response of 0x0 because of self destruct + senderAfterDestroy, _, err := client.EVM().InvokeContractByFuncName(ctx, fromAddr, selfDestructAddressActor, "sender()", []byte{}) + require.NoError(t, err) + require.Equal(t, []byte{}, senderAfterDestroy) + + // deploy new contract at same address usign same salt + newAddressSelfDestruct, _, err := client.EVM().InvokeContractByFuncName(ctx, fromAddr, idAddr, "deploy(bytes32)", salt) + require.NoError(t, err) + require.Equal(t, newAddressSelfDestruct, selfDestructAddress) + + //verify sender() property is correct + senderSecondCall, _, err := client.EVM().InvokeContractByFuncName(ctx, fromAddr, selfDestructAddressActor, "sender()", []byte{}) + require.NoError(t, err) + + //assert contract has correct data + require.Equal(t, ethFromAddr, senderSecondCall) + +} diff --git a/itests/gas_estimation_test.go b/itests/gas_estimation_test.go index 42cad8611..24013c885 100644 --- a/itests/gas_estimation_test.go +++ b/itests/gas_estimation_test.go @@ -2,16 +2,23 @@ package itests import ( "context" + "math" "testing" "time" "github.com/stretchr/testify/require" + "github.com/filecoin-project/go-address" + "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/big" + "github.com/filecoin-project/go-state-types/exitcode" "github.com/filecoin-project/lotus/api" + "github.com/filecoin-project/lotus/build" + "github.com/filecoin-project/lotus/chain/actors/builtin" "github.com/filecoin-project/lotus/chain/actors/builtin/account" "github.com/filecoin-project/lotus/chain/types" + "github.com/filecoin-project/lotus/chain/vm" "github.com/filecoin-project/lotus/itests/kit" ) @@ -37,8 +44,9 @@ func TestEstimateGasNoFunds(t *testing.T) { sm, err := client.MpoolPushMessage(ctx, msg, nil) require.NoError(t, err) - _, err = client.StateWaitMsg(ctx, sm.Cid(), 3, api.LookbackNoLimit, true) + ret, err := client.StateWaitMsg(ctx, sm.Cid(), 3, api.LookbackNoLimit, true) require.NoError(t, err) + require.True(t, ret.Receipt.ExitCode.IsSuccess()) // Make sure we can estimate gas even if we have no funds. msg2 := &types.Message{ @@ -52,3 +60,110 @@ func TestEstimateGasNoFunds(t *testing.T) { require.NoError(t, err) require.NotZero(t, limit) } + +// Make sure that we correctly calculate the inclusion cost. Especially, make sure the FVM and Lotus +// agree and that: +// 1. The FVM will never charge _less_ than the inclusion cost. +// 2. The FVM will never fine a storage provider for including a message that costs exactly the +// inclusion cost. +func TestEstimateInclusion(t *testing.T) { + ctx := context.Background() + + kit.QuietMiningLogs() + + // We need this to be "correct" in this test so that lotus can get the correct gas value + // (which, unfortunately, looks at the height and not the current network version). + oldPrices := vm.Prices + vm.Prices = map[abi.ChainEpoch]vm.Pricelist{ + 0: oldPrices[build.UpgradeHyggeHeight], + } + t.Cleanup(func() { vm.Prices = oldPrices }) + + client, _, ens := kit.EnsembleMinimal(t, kit.MockProofs()) + ens.InterconnectAll().BeginMining(10 * time.Millisecond) + + // First, try sending a message that should have no fees beyond the inclusion cost. I.e., it + // does absolutely nothing: + msg := &types.Message{ + From: client.DefaultKey.Address, + To: client.DefaultKey.Address, + Value: big.Zero(), + GasLimit: 0, + GasFeeCap: abi.NewTokenAmount(10000), + GasPremium: big.Zero(), + } + + burntBefore, err := client.WalletBalance(ctx, builtin.BurntFundsActorAddr) + require.NoError(t, err) + balanceBefore, err := client.WalletBalance(ctx, client.DefaultKey.Address) + require.NoError(t, err) + + // Sign the message and compute the correct inclusion cost. + var smsg *types.SignedMessage + for i := 0; ; i++ { + var err error + smsg, err = client.WalletSignMessage(ctx, client.DefaultKey.Address, msg) + require.NoError(t, err) + estimatedGas := vm.PricelistByEpoch(math.MaxInt).OnChainMessage(smsg.ChainLength()).Total() + if estimatedGas == msg.GasLimit { + break + } + // Try 10 times to get the right gas value. + require.Less(t, i, 10, "unable to estimate gas: %s != %s", estimatedGas, msg.GasLimit) + msg.GasLimit = estimatedGas + } + + cid, err := client.MpoolPush(ctx, smsg) + require.NoError(t, err) + ret, err := client.StateWaitMsg(ctx, cid, 3, api.LookbackNoLimit, true) + require.NoError(t, err) + require.True(t, ret.Receipt.ExitCode.IsSuccess()) + require.Equal(t, msg.GasLimit, ret.Receipt.GasUsed) + + // Then try sending a message of the same size that tries to create an actor. This should + // get successfully included, but fail with out of gas: + + // Mutate the last byte to get a new address of the same length. + toBytes := msg.To.Bytes() + toBytes[len(toBytes)-1] += 1 //nolint:golint + newAddr, err := address.NewFromBytes(toBytes) + require.NoError(t, err) + + msg.Nonce = 1 + msg.To = newAddr + smsg, err = client.WalletSignMessage(ctx, client.DefaultKey.Address, msg) + require.NoError(t, err) + + cid, err = client.MpoolPush(ctx, smsg) + require.NoError(t, err) + ret, err = client.StateWaitMsg(ctx, cid, 3, api.LookbackNoLimit, true) + require.NoError(t, err) + require.Equal(t, ret.Receipt.ExitCode, exitcode.SysErrOutOfGas) + require.Equal(t, msg.GasLimit, ret.Receipt.GasUsed) + + // Now make sure that the client is the only contributor to the burnt funds actor (the + // miners should not have been fined for either message). + + burntAfter, err := client.WalletBalance(ctx, builtin.BurntFundsActorAddr) + require.NoError(t, err) + balanceAfter, err := client.WalletBalance(ctx, client.DefaultKey.Address) + require.NoError(t, err) + + burnt := big.Sub(burntAfter, burntBefore) + spent := big.Sub(balanceBefore, balanceAfter) + + require.Equal(t, burnt, spent) + + // Finally, try to submit a message with too little gas. This should fail. + + msg.Nonce = 2 + msg.To = msg.From + msg.GasLimit -= 1 //nolint:golint + + smsg, err = client.WalletSignMessage(ctx, client.DefaultKey.Address, msg) + require.NoError(t, err) + + _, err = client.MpoolPush(ctx, smsg) + require.ErrorContains(t, err, "will not be included in a block") + require.ErrorContains(t, err, "cannot be less than the cost of storing a message") +} diff --git a/itests/gateway_test.go b/itests/gateway_test.go index b9c861bf3..d20b3bd1a 100644 --- a/itests/gateway_test.go +++ b/itests/gateway_test.go @@ -290,7 +290,7 @@ func startNodes( ens.InterconnectAll().BeginMining(blocktime) // Create a gateway server in front of the full node - gwapi := gateway.NewNode(full, lookbackCap, stateWaitLookbackLimit, 0, time.Minute) + gwapi := gateway.NewNode(full, nil, lookbackCap, stateWaitLookbackLimit, 0, time.Minute) handler, err := gateway.Handler(gwapi, full, 0, 0) require.NoError(t, err) diff --git a/itests/kit/ensemble.go b/itests/kit/ensemble.go index 8b92202dc..6d4ca1c12 100644 --- a/itests/kit/ensemble.go +++ b/itests/kit/ensemble.go @@ -47,6 +47,7 @@ import ( "github.com/filecoin-project/lotus/chain/wallet/key" "github.com/filecoin-project/lotus/cmd/lotus-seed/seed" "github.com/filecoin-project/lotus/cmd/lotus-worker/sealworker" + "github.com/filecoin-project/lotus/gateway" "github.com/filecoin-project/lotus/genesis" "github.com/filecoin-project/lotus/markets/idxprov" "github.com/filecoin-project/lotus/markets/idxprov/idxprov_test" @@ -210,7 +211,7 @@ func (n *Ensemble) FullNode(full *TestFullNode, opts ...NodeOpt) *Ensemble { n.genesis.accounts = append(n.genesis.accounts, genacc) } - *full = TestFullNode{t: n.t, options: options, DefaultKey: key} + *full = TestFullNode{t: n.t, options: options, DefaultKey: key, EthSubRouter: gateway.NewEthSubHandler()} n.inactive.fullnodes = append(n.inactive.fullnodes, full) return n diff --git a/itests/kit/evm.go b/itests/kit/evm.go index 46aaf52db..8a764793c 100644 --- a/itests/kit/evm.go +++ b/itests/kit/evm.go @@ -5,10 +5,14 @@ import ( "context" "encoding/binary" "encoding/hex" + "errors" "fmt" "os" + "testing" + "time" "github.com/ipfs/go-cid" + logging "github.com/ipfs/go-log/v2" "github.com/multiformats/go-varint" "github.com/stretchr/testify/require" cbg "github.com/whyrusleeping/cbor-gen" @@ -21,8 +25,10 @@ import ( builtintypes "github.com/filecoin-project/go-state-types/builtin" "github.com/filecoin-project/go-state-types/builtin/v10/eam" "github.com/filecoin-project/go-state-types/crypto" + "github.com/filecoin-project/go-state-types/exitcode" "github.com/filecoin-project/lotus/api" + "github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/chain/actors" "github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types/ethtypes" @@ -37,26 +43,18 @@ func (f *TestFullNode) EVM() *EVM { return &EVM{f} } -func (e *EVM) DeployContract(ctx context.Context, sender address.Address, bytecode []byte) eam.CreateReturn { +func (e *EVM) DeployContractWithValue(ctx context.Context, sender address.Address, bytecode []byte, value big.Int) eam.CreateReturn { require := require.New(e.t) - nonce, err := e.MpoolGetNonce(ctx, sender) - if err != nil { - nonce = 0 // assume a zero nonce on error (e.g. sender doesn't exist). - } - - var salt [32]byte - binary.BigEndian.PutUint64(salt[:], nonce) - method := builtintypes.MethodsEAM.CreateExternal initcode := abi.CborBytes(bytecode) - params, err := actors.SerializeParams(&initcode) - require.NoError(err) + params, errActors := actors.SerializeParams(&initcode) + require.NoError(errActors) msg := &types.Message{ To: builtintypes.EthereumAddressManagerActorAddr, From: sender, - Value: big.Zero(), + Value: value, Method: method, Params: params, } @@ -78,8 +76,11 @@ func (e *EVM) DeployContract(ctx context.Context, sender address.Address, byteco return result } +func (e *EVM) DeployContract(ctx context.Context, sender address.Address, bytecode []byte) eam.CreateReturn { + return e.DeployContractWithValue(ctx, sender, bytecode, big.Zero()) +} -func (e *EVM) DeployContractFromFilename(ctx context.Context, binFilename string) (address.Address, address.Address) { +func (e *EVM) DeployContractFromFilenameWithValue(ctx context.Context, binFilename string, value big.Int) (address.Address, address.Address) { contractHex, err := os.ReadFile(binFilename) require.NoError(e.t, err) @@ -92,39 +93,51 @@ func (e *EVM) DeployContractFromFilename(ctx context.Context, binFilename string fromAddr, err := e.WalletDefaultAddress(ctx) require.NoError(e.t, err) - result := e.DeployContract(ctx, fromAddr, contract) + result := e.DeployContractWithValue(ctx, fromAddr, contract, value) idAddr, err := address.NewIDAddress(result.ActorID) require.NoError(e.t, err) return fromAddr, idAddr } +func (e *EVM) DeployContractFromFilename(ctx context.Context, binFilename string) (address.Address, address.Address) { + return e.DeployContractFromFilenameWithValue(ctx, binFilename, big.Zero()) +} -func (e *EVM) InvokeSolidity(ctx context.Context, sender address.Address, target address.Address, selector []byte, inputData []byte) *api.MsgLookup { - require := require.New(e.t) - +func (e *EVM) InvokeSolidity(ctx context.Context, sender address.Address, target address.Address, selector []byte, inputData []byte) (*api.MsgLookup, error) { params := append(selector, inputData...) var buffer bytes.Buffer err := cbg.WriteByteArray(&buffer, params) - require.NoError(err) + if err != nil { + return nil, err + } params = buffer.Bytes() msg := &types.Message{ - To: target, - From: sender, - Value: big.Zero(), - Method: builtintypes.MethodsEVM.InvokeContract, - Params: params, + To: target, + From: sender, + Value: big.Zero(), + Method: builtintypes.MethodsEVM.InvokeContract, + GasLimit: build.BlockGasLimit, // note: we hardcode block gas limit due to slightly broken gas estimation - https://github.com/filecoin-project/lotus/issues/10041 + Params: params, } e.t.Log("sending invoke message") smsg, err := e.MpoolPushMessage(ctx, msg, nil) - require.NoError(err) + if err != nil { + return nil, err + } e.t.Log("waiting for message to execute") wait, err := e.StateWaitMsg(ctx, smsg.Cid(), 0, 0, false) - require.NoError(err) - - return wait + if err != nil { + return nil, err + } + if !wait.Receipt.ExitCode.IsSuccess() { + result, err := e.StateReplay(ctx, types.EmptyTSK, wait.Message) + require.NoError(e.t, err) + e.t.Log(result.Error) + } + return wait, nil } // LoadEvents loads all events in an event AMT. @@ -234,13 +247,28 @@ func (e *EVM) ComputeContractAddress(deployer ethtypes.EthAddress, nonce uint64) return *(*ethtypes.EthAddress)(hasher.Sum(nil)[12:]) } -func (e *EVM) InvokeContractByFuncName(ctx context.Context, fromAddr address.Address, idAddr address.Address, funcSignature string, inputData []byte) []byte { +func (e *EVM) InvokeContractByFuncName(ctx context.Context, fromAddr address.Address, idAddr address.Address, funcSignature string, inputData []byte) ([]byte, *api.MsgLookup, error) { entryPoint := CalcFuncSignature(funcSignature) - wait := e.InvokeSolidity(ctx, fromAddr, idAddr, entryPoint, inputData) - require.True(e.t, wait.Receipt.ExitCode.IsSuccess(), "contract execution failed") + wait, err := e.InvokeSolidity(ctx, fromAddr, idAddr, entryPoint, inputData) + if err != nil { + return nil, wait, err + } + if !wait.Receipt.ExitCode.IsSuccess() { + result, err := e.StateReplay(ctx, types.EmptyTSK, wait.Message) + require.NoError(e.t, err) + return nil, wait, errors.New(result.Error) + } result, err := cbg.ReadByteArray(bytes.NewBuffer(wait.Receipt.Return), uint64(len(wait.Receipt.Return))) - require.NoError(e.t, err) - return result + if err != nil { + return nil, wait, err + } + return result, wait, nil +} + +func (e *EVM) InvokeContractByFuncNameExpectExit(ctx context.Context, fromAddr address.Address, idAddr address.Address, funcSignature string, inputData []byte, exit exitcode.ExitCode) { + entryPoint := CalcFuncSignature(funcSignature) + wait, _ := e.InvokeSolidity(ctx, fromAddr, idAddr, entryPoint, inputData) + require.Equal(e.t, exit, wait.Receipt.ExitCode) } // function signatures are the first 4 bytes of the hash of the function name and types @@ -301,3 +329,114 @@ func removeLeadingZeros(data []byte) []byte { } return data[firstNonZeroIndex:] } + +func SetupFEVMTest(t *testing.T) (context.Context, context.CancelFunc, *TestFullNode) { + // make all logs extra quiet for fevm tests + lvl, err := logging.LevelFromString("error") + if err != nil { + panic(err) + } + logging.SetAllLoggers(lvl) + + blockTime := 100 * time.Millisecond + client, _, ens := EnsembleMinimal(t, MockProofs(), ThroughRPC()) + ens.InterconnectAll().BeginMining(blockTime) + ctx, cancel := context.WithTimeout(context.Background(), time.Minute) + + // require that the initial balance is 100 million FIL in setup + // this way other tests can count on this initial wallet balance + fromAddr := client.DefaultKey.Address + bal, err := client.WalletBalance(ctx, fromAddr) + require.NoError(t, err) + originalBalance := types.FromFil(uint64(100_000_000)) // 100 million FIL + require.Equal(t, originalBalance, bal) + + return ctx, cancel, client +} + +func (e *EVM) TransferValueOrFail(ctx context.Context, fromAddr address.Address, toAddr address.Address, sendAmount big.Int) { + sendMsg := &types.Message{ + From: fromAddr, + To: toAddr, + Value: sendAmount, + } + signedMsg, err := e.MpoolPushMessage(ctx, sendMsg, nil) + require.NoError(e.t, err) + mLookup, err := e.StateWaitMsg(ctx, signedMsg.Cid(), 3, api.LookbackNoLimit, true) + require.NoError(e.t, err) + require.Equal(e.t, exitcode.Ok, mLookup.Receipt.ExitCode) +} + +func NewEthFilterBuilder() *EthFilterBuilder { + return &EthFilterBuilder{} +} + +type EthFilterBuilder struct { + filter ethtypes.EthFilterSpec +} + +func (e *EthFilterBuilder) Filter() *ethtypes.EthFilterSpec { return &e.filter } + +func (e *EthFilterBuilder) FromBlock(v string) *EthFilterBuilder { + e.filter.FromBlock = &v + return e +} + +func (e *EthFilterBuilder) FromBlockEpoch(v abi.ChainEpoch) *EthFilterBuilder { + s := ethtypes.EthUint64(v).Hex() + e.filter.FromBlock = &s + return e +} + +func (e *EthFilterBuilder) ToBlock(v string) *EthFilterBuilder { + e.filter.ToBlock = &v + return e +} + +func (e *EthFilterBuilder) ToBlockEpoch(v abi.ChainEpoch) *EthFilterBuilder { + s := ethtypes.EthUint64(v).Hex() + e.filter.ToBlock = &s + return e +} + +func (e *EthFilterBuilder) BlockHash(h ethtypes.EthHash) *EthFilterBuilder { + e.filter.BlockHash = &h + return e +} + +func (e *EthFilterBuilder) AddressOneOf(as ...ethtypes.EthAddress) *EthFilterBuilder { + e.filter.Address = as + return e +} + +func (e *EthFilterBuilder) Topic1OneOf(hs ...ethtypes.EthHash) *EthFilterBuilder { + if len(e.filter.Topics) == 0 { + e.filter.Topics = make(ethtypes.EthTopicSpec, 1) + } + e.filter.Topics[0] = hs + return e +} + +func (e *EthFilterBuilder) Topic2OneOf(hs ...ethtypes.EthHash) *EthFilterBuilder { + for len(e.filter.Topics) < 2 { + e.filter.Topics = append(e.filter.Topics, nil) + } + e.filter.Topics[1] = hs + return e +} + +func (e *EthFilterBuilder) Topic3OneOf(hs ...ethtypes.EthHash) *EthFilterBuilder { + for len(e.filter.Topics) < 3 { + e.filter.Topics = append(e.filter.Topics, nil) + } + e.filter.Topics[2] = hs + return e +} + +func (e *EthFilterBuilder) Topic4OneOf(hs ...ethtypes.EthHash) *EthFilterBuilder { + for len(e.filter.Topics) < 4 { + e.filter.Topics = append(e.filter.Topics, nil) + } + e.filter.Topics[3] = hs + return e +} diff --git a/itests/kit/node_full.go b/itests/kit/node_full.go index 4546f5a03..3e80ed688 100644 --- a/itests/kit/node_full.go +++ b/itests/kit/node_full.go @@ -1,6 +1,7 @@ package kit import ( + "bytes" "context" "fmt" "testing" @@ -10,15 +11,18 @@ import ( "github.com/libp2p/go-libp2p/core/peer" "github.com/multiformats/go-multiaddr" "github.com/stretchr/testify/require" + cbg "github.com/whyrusleeping/cbor-gen" "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-state-types/abi" + "github.com/filecoin-project/go-state-types/exitcode" "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/api/v1api" "github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/wallet/key" cliutil "github.com/filecoin-project/lotus/cli/util" + "github.com/filecoin-project/lotus/gateway" "github.com/filecoin-project/lotus/node" ) @@ -43,6 +47,10 @@ type TestFullNode struct { Stop node.StopFunc + // gateway handler makes it convenient to register callbalks per topic, so we + // also use it for tests + EthSubRouter *gateway.EthSubHandler + options nodeOpts } @@ -124,6 +132,50 @@ func (f *TestFullNode) AssignPrivKey(pkey *Libp2p) { f.Pkey = pkey } +type SendCall struct { + Method abi.MethodNum + Params []byte +} + +func (f *TestFullNode) MakeSendCall(m abi.MethodNum, params cbg.CBORMarshaler) SendCall { + var b bytes.Buffer + err := params.MarshalCBOR(&b) + require.NoError(f.t, err) + return SendCall{ + Method: m, + Params: b.Bytes(), + } +} + +func (f *TestFullNode) ExpectSend(ctx context.Context, from, to address.Address, value types.BigInt, errContains string, sc ...SendCall) *types.SignedMessage { + msg := &types.Message{From: from, To: to, Value: value} + + if len(sc) == 1 { + msg.Method = sc[0].Method + msg.Params = sc[0].Params + } + + _, err := f.GasEstimateMessageGas(ctx, msg, nil, types.EmptyTSK) + if errContains != "" { + require.ErrorContains(f.t, err, errContains) + return nil + } + require.NoError(f.t, err) + + if errContains == "" { + m, err := f.MpoolPushMessage(ctx, msg, nil) + require.NoError(f.t, err) + + r, err := f.StateWaitMsg(ctx, m.Cid(), 1, api.LookbackNoLimit, true) + require.NoError(f.t, err) + + require.Equal(f.t, exitcode.Ok, r.Receipt.ExitCode) + return m + } + + return nil +} + // ChainPredicate encapsulates a chain condition. type ChainPredicate func(set *types.TipSet) bool diff --git a/itests/kit/rpc.go b/itests/kit/rpc.go index f8c2c6e53..5d40ac3e9 100644 --- a/itests/kit/rpc.go +++ b/itests/kit/rpc.go @@ -13,6 +13,8 @@ import ( manet "github.com/multiformats/go-multiaddr/net" "github.com/stretchr/testify/require" + "github.com/filecoin-project/go-jsonrpc" + "github.com/filecoin-project/lotus/api/client" "github.com/filecoin-project/lotus/cmd/lotus-worker/sealworker" "github.com/filecoin-project/lotus/node" @@ -52,7 +54,12 @@ func fullRpc(t *testing.T, f *TestFullNode) (*TestFullNode, Closer) { fmt.Printf("FULLNODE RPC ENV FOR CLI DEBUGGING `export FULLNODE_API_INFO=%s`\n", "ws://"+srv.Listener.Addr().String()) sendItestdNotif("FULLNODE_API_INFO", t.Name(), "ws://"+srv.Listener.Addr().String()) - cl, stop, err := client.NewFullNodeRPCV1(context.Background(), "ws://"+srv.Listener.Addr().String()+"/rpc/v1", nil) + rpcOpts := []jsonrpc.Option{ + jsonrpc.WithClientHandler("Filecoin", f.EthSubRouter), + jsonrpc.WithClientHandlerAlias("eth_subscription", "Filecoin.EthSubscription"), + } + + cl, stop, err := client.NewFullNodeRPCV1(context.Background(), "ws://"+srv.Listener.Addr().String()+"/rpc/v1", nil, rpcOpts...) require.NoError(t, err) f.ListenAddr, f.ListenURL, f.FullNode = maddr, srv.URL, cl diff --git a/itests/kit/solidity.go b/itests/kit/solidity.go new file mode 100644 index 000000000..ea9d452f4 --- /dev/null +++ b/itests/kit/solidity.go @@ -0,0 +1,64 @@ +package kit + +import ( + "golang.org/x/crypto/sha3" +) + +func EthTopicHash(sig string) []byte { + hasher := sha3.NewLegacyKeccak256() + hasher.Write([]byte(sig)) + return hasher.Sum(nil) +} + +func EthFunctionHash(sig string) []byte { + hasher := sha3.NewLegacyKeccak256() + hasher.Write([]byte(sig)) + return hasher.Sum(nil)[:4] +} + +// SolidityContractDef holds information about one of the test contracts +type SolidityContractDef struct { + Filename string // filename of the hex of the contract, e.g. contracts/EventMatrix.hex + Fn map[string][]byte // mapping of function names to 32-bit selector + Ev map[string][]byte // mapping of event names to 256-bit signature hashes +} + +var EventMatrixContract = SolidityContractDef{ + Filename: "contracts/EventMatrix.hex", + Fn: map[string][]byte{ + "logEventZeroData": EthFunctionHash("logEventZeroData()"), + "logEventOneData": EthFunctionHash("logEventOneData(uint256)"), + "logEventTwoData": EthFunctionHash("logEventTwoData(uint256,uint256)"), + "logEventThreeData": EthFunctionHash("logEventThreeData(uint256,uint256,uint256)"), + "logEventFourData": EthFunctionHash("logEventFourData(uint256,uint256,uint256,uint256)"), + "logEventOneIndexed": EthFunctionHash("logEventOneIndexed(uint256)"), + "logEventTwoIndexed": EthFunctionHash("logEventTwoIndexed(uint256,uint256)"), + "logEventThreeIndexed": EthFunctionHash("logEventThreeIndexed(uint256,uint256,uint256)"), + "logEventOneIndexedWithData": EthFunctionHash("logEventOneIndexedWithData(uint256,uint256)"), + "logEventTwoIndexedWithData": EthFunctionHash("logEventTwoIndexedWithData(uint256,uint256,uint256)"), + "logEventThreeIndexedWithData": EthFunctionHash("logEventThreeIndexedWithData(uint256,uint256,uint256,uint256)"), + }, + Ev: map[string][]byte{ + "EventZeroData": EthTopicHash("EventZeroData()"), + "EventOneData": EthTopicHash("EventOneData(uint256)"), + "EventTwoData": EthTopicHash("EventTwoData(uint256,uint256)"), + "EventThreeData": EthTopicHash("EventThreeData(uint256,uint256,uint256)"), + "EventFourData": EthTopicHash("EventFourData(uint256,uint256,uint256,uint256)"), + "EventOneIndexed": EthTopicHash("EventOneIndexed(uint256)"), + "EventTwoIndexed": EthTopicHash("EventTwoIndexed(uint256,uint256)"), + "EventThreeIndexed": EthTopicHash("EventThreeIndexed(uint256,uint256,uint256)"), + "EventOneIndexedWithData": EthTopicHash("EventOneIndexedWithData(uint256,uint256)"), + "EventTwoIndexedWithData": EthTopicHash("EventTwoIndexedWithData(uint256,uint256,uint256)"), + "EventThreeIndexedWithData": EthTopicHash("EventThreeIndexedWithData(uint256,uint256,uint256,uint256)"), + }, +} + +var EventsContract = SolidityContractDef{ + Filename: "contracts/events.bin", + Fn: map[string][]byte{ + "log_zero_data": {0x00, 0x00, 0x00, 0x00}, + "log_zero_nodata": {0x00, 0x00, 0x00, 0x01}, + "log_four_data": {0x00, 0x00, 0x00, 0x02}, + }, + Ev: map[string][]byte{}, +} diff --git a/itests/specs/eth_openrpc.json b/itests/specs/eth_openrpc.json new file mode 100644 index 000000000..ed13614e9 --- /dev/null +++ b/itests/specs/eth_openrpc.json @@ -0,0 +1,4392 @@ +{ + "openrpc": "1.2.4", + "info": { + "title": "Ethereum JSON-RPC Specification", + "description": "A specification of the standard interface for Ethereum clients.", + "license": { + "name": "CC0-1.0", + "url": "https://creativecommons.org/publicdomain/zero/1.0/legalcode" + }, + "version": "0.0.0" + }, + "methods": [ + { + "name": "eth_getBlockByHash", + "summary": "Returns information about a block by hash.", + "params": [ + { + "name": "Block hash", + "required": true, + "schema": { + "title": "32 byte hex value", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + } + }, + { + "name": "Hydrated transactions", + "required": true, + "schema": { + "title": "hydrated", + "type": "boolean" + } + } + ], + "result": { + "name": "Block information", + "schema": { + "title": "Block object", + "type": "object", + "required": [ + "parentHash", + "sha3Uncles", + "miner", + "stateRoot", + "transactionsRoot", + "receiptsRoot", + "logsBloom", + "number", + "gasLimit", + "gasUsed", + "timestamp", + "extraData", + "mixHash", + "nonce", + "size", + "transactions", + "uncles" + ], + "properties": { + "parentHash": { + "title": "Parent block hash", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + }, + "sha3Uncles": { + "title": "Ommers hash", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + }, + "miner": { + "title": "Coinbase", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$" + }, + "stateRoot": { + "title": "State root", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + }, + "transactionsRoot": { + "title": "Transactions root", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + }, + "receiptsRoot": { + "title": "Receipts root", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + }, + "logsBloom": { + "title": "Bloom filter", + "type": "string", + "pattern": "^0x[0-9a-f]{512}$" + }, + "difficulty": { + "title": "Difficulty", + "type": "string", + "pattern": "^0x[0-9a-f]*$" + }, + "number": { + "title": "Number", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "gasLimit": { + "title": "Gas limit", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "gasUsed": { + "title": "Gas used", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "timestamp": { + "title": "Timestamp", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "extraData": { + "title": "Extra data", + "type": "string", + "pattern": "^0x[0-9a-f]*$" + }, + "mixHash": { + "title": "Mix hash", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + }, + "nonce": { + "title": "Nonce", + "type": "string", + "pattern": "^0x[0-9a-f]{16}$" + }, + "totalDifficulty": { + "title": "Total difficult", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "baseFeePerGas": { + "title": "Base fee per gas", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "size": { + "title": "Block size", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "transactions": { + "anyOf": [ + { + "title": "Transaction hashes", + "type": "array", + "items": { + "title": "32 byte hex value", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + } + }, + { + "title": "Full transactions", + "type": "array", + "items": { + "oneOf": [ + { + "title": "Signed 1559 Transaction", + "type": "object", + "required": [ + "accessList", + "chainId", + "gas", + "input", + "maxFeePerGas", + "maxPriorityFeePerGas", + "nonce", + "r", + "s", + "type", + "value", + "yParity" + ], + "properties": { + "type": { + "title": "type", + "type": "string", + "pattern": "^0x([0-9,a-f,A-F]?){1,2}$" + }, + "nonce": { + "title": "nonce", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "to": { + "title": "to address", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$" + }, + "gas": { + "title": "gas limit", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "value": { + "title": "value", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "input": { + "title": "input data", + "type": "string", + "pattern": "^0x[0-9a-f]*$" + }, + "maxPriorityFeePerGas": { + "title": "max priority fee per gas", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "Maximum fee per gas the sender is willing to pay to miners in wei" + }, + "maxFeePerGas": { + "title": "max fee per gas", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "The maximum total fee per gas the sender is willing to pay (includes the network / base fee and miner / priority fee) in wei" + }, + "accessList": { + "title": "accessList", + "type": "array", + "description": "EIP-2930 access list", + "items": { + "title": "Access list entry", + "type": "object", + "properties": { + "address": { + "title": "hex encoded address", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$" + }, + "storageKeys": { + "type": "array", + "items": { + "title": "32 byte hex value", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + } + } + } + } + }, + "chainId": { + "title": "chainId", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "Chain ID that this transaction is valid on." + }, + "yParity": { + "title": "yParity", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "The parity (0 for even, 1 for odd) of the y-value of the secp256k1 signature." + }, + "r": { + "title": "r", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "s": { + "title": "s", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + } + } + }, + { + "title": "Signed 2930 Transaction", + "type": "object", + "required": [ + "accessList", + "chainId", + "gas", + "gasPrice", + "input", + "nonce", + "r", + "s", + "type", + "value", + "yParity" + ], + "properties": { + "type": { + "title": "type", + "type": "string", + "pattern": "^0x([0-9,a-f,A-F]?){1,2}$" + }, + "nonce": { + "title": "nonce", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "to": { + "title": "to address", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$" + }, + "gas": { + "title": "gas limit", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "value": { + "title": "value", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "input": { + "title": "input data", + "type": "string", + "pattern": "^0x[0-9a-f]*$" + }, + "gasPrice": { + "title": "gas price", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "The gas price willing to be paid by the sender in wei" + }, + "accessList": { + "title": "accessList", + "type": "array", + "description": "EIP-2930 access list", + "items": { + "title": "Access list entry", + "type": "object", + "properties": { + "address": { + "title": "hex encoded address", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$" + }, + "storageKeys": { + "type": "array", + "items": { + "title": "32 byte hex value", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + } + } + } + } + }, + "chainId": { + "title": "chainId", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "Chain ID that this transaction is valid on." + }, + "yParity": { + "title": "yParity", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "The parity (0 for even, 1 for odd) of the y-value of the secp256k1 signature." + }, + "r": { + "title": "r", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "s": { + "title": "s", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + } + } + }, + { + "title": "Signed Legacy Transaction", + "type": "object", + "required": [ + "gas", + "gasPrice", + "input", + "nonce", + "r", + "s", + "type", + "v", + "value" + ], + "properties": { + "type": { + "title": "type", + "type": "string", + "pattern": "^0x([0-9,a-f,A-F]?){1,2}$" + }, + "nonce": { + "title": "nonce", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "to": { + "title": "to address", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$" + }, + "gas": { + "title": "gas limit", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "value": { + "title": "value", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "input": { + "title": "input data", + "type": "string", + "pattern": "^0x[0-9a-f]*$" + }, + "gasPrice": { + "title": "gas price", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "The gas price willing to be paid by the sender in wei" + }, + "chainId": { + "title": "chainId", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "Chain ID that this transaction is valid on." + }, + "v": { + "title": "v", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "r": { + "title": "r", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "s": { + "title": "s", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + } + } + } + ] + } + } + ] + }, + "uncles": { + "title": "Uncles", + "type": "array", + "items": { + "title": "32 byte hex value", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + } + } + } + } + } + }, + { + "name": "eth_getBlockByNumber", + "summary": "Returns information about a block by number.", + "params": [ + { + "name": "Block", + "required": true, + "schema": { + "title": "Block number or tag", + "oneOf": [ + { + "title": "Block number", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + { + "title": "Block tag", + "type": "string", + "enum": [ + "earliest", + "finalized", + "safe", + "latest", + "pending" + ], + "description": "`earliest`: The lowest numbered block the client has available; `finalized`: The most recent crypto-economically secure block, cannot be re-orged outside of manual intervention driven by community coordination; `safe`: The most recent block that is safe from re-orgs under honest majority and certain synchronicity assumptions; `latest`: The most recent block in the canonical chain observed by the client, this block may be re-orged out of the canonical chain even under healthy/normal conditions; `pending`: A sample next block built by the client on top of `latest` and containing the set of transactions usually taken from local mempool. Before the merge transition is finalized, any call querying for `finalized` or `safe` block MUST be responded to with `-39001: Unknown block` error" + } + ] + } + }, + { + "name": "Hydrated transactions", + "required": true, + "schema": { + "title": "hydrated", + "type": "boolean" + } + } + ], + "result": { + "name": "Block information", + "schema": { + "title": "Block object", + "type": "object", + "required": [ + "parentHash", + "sha3Uncles", + "miner", + "stateRoot", + "transactionsRoot", + "receiptsRoot", + "logsBloom", + "number", + "gasLimit", + "gasUsed", + "timestamp", + "extraData", + "mixHash", + "nonce", + "size", + "transactions", + "uncles" + ], + "properties": { + "parentHash": { + "title": "Parent block hash", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + }, + "sha3Uncles": { + "title": "Ommers hash", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + }, + "miner": { + "title": "Coinbase", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$" + }, + "stateRoot": { + "title": "State root", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + }, + "transactionsRoot": { + "title": "Transactions root", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + }, + "receiptsRoot": { + "title": "Receipts root", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + }, + "logsBloom": { + "title": "Bloom filter", + "type": "string", + "pattern": "^0x[0-9a-f]{512}$" + }, + "difficulty": { + "title": "Difficulty", + "type": "string", + "pattern": "^0x[0-9a-f]*$" + }, + "number": { + "title": "Number", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "gasLimit": { + "title": "Gas limit", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "gasUsed": { + "title": "Gas used", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "timestamp": { + "title": "Timestamp", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "extraData": { + "title": "Extra data", + "type": "string", + "pattern": "^0x[0-9a-f]*$" + }, + "mixHash": { + "title": "Mix hash", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + }, + "nonce": { + "title": "Nonce", + "type": "string", + "pattern": "^0x[0-9a-f]{16}$" + }, + "totalDifficulty": { + "title": "Total difficult", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "baseFeePerGas": { + "title": "Base fee per gas", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "size": { + "title": "Block size", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "transactions": { + "anyOf": [ + { + "title": "Transaction hashes", + "type": "array", + "items": { + "title": "32 byte hex value", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + } + }, + { + "title": "Full transactions", + "type": "array", + "items": { + "oneOf": [ + { + "title": "Signed 1559 Transaction", + "type": "object", + "required": [ + "accessList", + "chainId", + "gas", + "input", + "maxFeePerGas", + "maxPriorityFeePerGas", + "nonce", + "r", + "s", + "type", + "value", + "yParity" + ], + "properties": { + "type": { + "title": "type", + "type": "string", + "pattern": "^0x([0-9,a-f,A-F]?){1,2}$" + }, + "nonce": { + "title": "nonce", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "to": { + "title": "to address", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$" + }, + "gas": { + "title": "gas limit", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "value": { + "title": "value", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "input": { + "title": "input data", + "type": "string", + "pattern": "^0x[0-9a-f]*$" + }, + "maxPriorityFeePerGas": { + "title": "max priority fee per gas", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "Maximum fee per gas the sender is willing to pay to miners in wei" + }, + "maxFeePerGas": { + "title": "max fee per gas", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "The maximum total fee per gas the sender is willing to pay (includes the network / base fee and miner / priority fee) in wei" + }, + "accessList": { + "title": "accessList", + "type": "array", + "description": "EIP-2930 access list", + "items": { + "title": "Access list entry", + "type": "object", + "properties": { + "address": { + "title": "hex encoded address", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$" + }, + "storageKeys": { + "type": "array", + "items": { + "title": "32 byte hex value", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + } + } + } + } + }, + "chainId": { + "title": "chainId", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "Chain ID that this transaction is valid on." + }, + "yParity": { + "title": "yParity", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "The parity (0 for even, 1 for odd) of the y-value of the secp256k1 signature." + }, + "r": { + "title": "r", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "s": { + "title": "s", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + } + } + }, + { + "title": "Signed 2930 Transaction", + "type": "object", + "required": [ + "accessList", + "chainId", + "gas", + "gasPrice", + "input", + "nonce", + "r", + "s", + "type", + "value", + "yParity" + ], + "properties": { + "type": { + "title": "type", + "type": "string", + "pattern": "^0x([0-9,a-f,A-F]?){1,2}$" + }, + "nonce": { + "title": "nonce", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "to": { + "title": "to address", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$" + }, + "gas": { + "title": "gas limit", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "value": { + "title": "value", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "input": { + "title": "input data", + "type": "string", + "pattern": "^0x[0-9a-f]*$" + }, + "gasPrice": { + "title": "gas price", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "The gas price willing to be paid by the sender in wei" + }, + "accessList": { + "title": "accessList", + "type": "array", + "description": "EIP-2930 access list", + "items": { + "title": "Access list entry", + "type": "object", + "properties": { + "address": { + "title": "hex encoded address", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$" + }, + "storageKeys": { + "type": "array", + "items": { + "title": "32 byte hex value", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + } + } + } + } + }, + "chainId": { + "title": "chainId", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "Chain ID that this transaction is valid on." + }, + "yParity": { + "title": "yParity", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "The parity (0 for even, 1 for odd) of the y-value of the secp256k1 signature." + }, + "r": { + "title": "r", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "s": { + "title": "s", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + } + } + }, + { + "title": "Signed Legacy Transaction", + "type": "object", + "required": [ + "gas", + "gasPrice", + "input", + "nonce", + "r", + "s", + "type", + "v", + "value" + ], + "properties": { + "type": { + "title": "type", + "type": "string", + "pattern": "^0x([0-9,a-f,A-F]?){1,2}$" + }, + "nonce": { + "title": "nonce", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "to": { + "title": "to address", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$" + }, + "gas": { + "title": "gas limit", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "value": { + "title": "value", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "input": { + "title": "input data", + "type": "string", + "pattern": "^0x[0-9a-f]*$" + }, + "gasPrice": { + "title": "gas price", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "The gas price willing to be paid by the sender in wei" + }, + "chainId": { + "title": "chainId", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "Chain ID that this transaction is valid on." + }, + "v": { + "title": "v", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "r": { + "title": "r", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "s": { + "title": "s", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + } + } + } + ] + } + } + ] + }, + "uncles": { + "title": "Uncles", + "type": "array", + "items": { + "title": "32 byte hex value", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + } + } + } + } + } + }, + { + "name": "eth_getBlockTransactionCountByHash", + "summary": "Returns the number of transactions in a block from a block matching the given block hash.", + "params": [ + { + "name": "Block hash", + "schema": { + "title": "32 byte hex value", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + } + } + ], + "result": { + "name": "Transaction count", + "schema": { + "title": "hex encoded unsigned integer", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + } + } + }, + { + "name": "eth_getBlockTransactionCountByNumber", + "summary": "Returns the number of transactions in a block matching the given block number.", + "params": [ + { + "name": "Block", + "schema": { + "title": "Block number or tag", + "oneOf": [ + { + "title": "Block number", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + { + "title": "Block tag", + "type": "string", + "enum": [ + "earliest", + "finalized", + "safe", + "latest", + "pending" + ], + "description": "`earliest`: The lowest numbered block the client has available; `finalized`: The most recent crypto-economically secure block, cannot be re-orged outside of manual intervention driven by community coordination; `safe`: The most recent block that is safe from re-orgs under honest majority and certain synchronicity assumptions; `latest`: The most recent block in the canonical chain observed by the client, this block may be re-orged out of the canonical chain even under healthy/normal conditions; `pending`: A sample next block built by the client on top of `latest` and containing the set of transactions usually taken from local mempool. Before the merge transition is finalized, any call querying for `finalized` or `safe` block MUST be responded to with `-39001: Unknown block` error" + } + ] + } + } + ], + "result": { + "name": "Transaction count", + "schema": { + "title": "hex encoded unsigned integer", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + } + } + }, + { + "name": "eth_getUncleCountByBlockHash", + "summary": "Returns the number of uncles in a block from a block matching the given block hash.", + "params": [ + { + "name": "Block hash", + "schema": { + "title": "32 byte hex value", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + } + } + ], + "result": { + "name": "Uncle count", + "schema": { + "title": "hex encoded unsigned integer", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + } + } + }, + { + "name": "eth_getUncleCountByBlockNumber", + "summary": "Returns the number of transactions in a block matching the given block number.", + "params": [ + { + "name": "Block", + "schema": { + "title": "Block number or tag", + "oneOf": [ + { + "title": "Block number", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + { + "title": "Block tag", + "type": "string", + "enum": [ + "earliest", + "finalized", + "safe", + "latest", + "pending" + ], + "description": "`earliest`: The lowest numbered block the client has available; `finalized`: The most recent crypto-economically secure block, cannot be re-orged outside of manual intervention driven by community coordination; `safe`: The most recent block that is safe from re-orgs under honest majority and certain synchronicity assumptions; `latest`: The most recent block in the canonical chain observed by the client, this block may be re-orged out of the canonical chain even under healthy/normal conditions; `pending`: A sample next block built by the client on top of `latest` and containing the set of transactions usually taken from local mempool. Before the merge transition is finalized, any call querying for `finalized` or `safe` block MUST be responded to with `-39001: Unknown block` error" + } + ] + } + } + ], + "result": { + "name": "Uncle count", + "schema": { + "title": "hex encoded unsigned integer", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + } + } + }, + { + "name": "eth_chainId", + "summary": "Returns the chain ID of the current network.", + "params": [], + "result": { + "name": "Chain ID", + "schema": { + "title": "hex encoded unsigned integer", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + } + } + }, + { + "name": "eth_syncing", + "summary": "Returns an object with data about the sync status or false.", + "params": [], + "result": { + "name": "Syncing status", + "schema": { + "title": "Syncing status", + "oneOf": [ + { + "title": "Syncing progress", + "type": "object", + "properties": { + "startingBlock": { + "title": "Starting block", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "currentBlock": { + "title": "Current block", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "highestBlock": { + "title": "Highest block", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + } + } + }, + { + "title": "Not syncing", + "description": "Should always return false if not syncing.", + "type": "boolean" + } + ] + } + } + }, + { + "name": "eth_coinbase", + "summary": "Returns the client coinbase address.", + "params": [], + "result": { + "name": "Coinbase address", + "schema": { + "title": "hex encoded address", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$" + } + } + }, + { + "name": "eth_accounts", + "summary": "Returns a list of addresses owned by client.", + "params": [], + "result": { + "name": "Accounts", + "schema": { + "title": "Accounts", + "type": "array", + "items": { + "title": "hex encoded address", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$" + } + } + } + }, + { + "name": "eth_blockNumber", + "summary": "Returns the number of most recent block.", + "params": [], + "result": { + "name": "Block number", + "schema": { + "title": "hex encoded unsigned integer", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + } + } + }, + { + "name": "eth_call", + "summary": "Executes a new message call immediately without creating a transaction on the block chain.", + "params": [ + { + "name": "Transaction", + "required": true, + "schema": { + "type": "object", + "title": "Transaction object generic to all types", + "properties": { + "type": { + "title": "type", + "type": "string", + "pattern": "^0x([0-9,a-f,A-F]?){1,2}$" + }, + "nonce": { + "title": "nonce", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "to": { + "title": "to address", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$" + }, + "from": { + "title": "from address", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$" + }, + "gas": { + "title": "gas limit", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "value": { + "title": "value", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "input": { + "title": "input data", + "type": "string", + "pattern": "^0x[0-9a-f]*$" + }, + "gasPrice": { + "title": "gas price", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "The gas price willing to be paid by the sender in wei" + }, + "maxPriorityFeePerGas": { + "title": "max priority fee per gas", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "Maximum fee per gas the sender is willing to pay to miners in wei" + }, + "maxFeePerGas": { + "title": "max fee per gas", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "The maximum total fee per gas the sender is willing to pay (includes the network / base fee and miner / priority fee) in wei" + }, + "accessList": { + "title": "accessList", + "type": "array", + "description": "EIP-2930 access list", + "items": { + "title": "Access list entry", + "type": "object", + "properties": { + "address": { + "title": "hex encoded address", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$" + }, + "storageKeys": { + "type": "array", + "items": { + "title": "32 byte hex value", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + } + } + } + } + }, + "chainId": { + "title": "chainId", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "Chain ID that this transaction is valid on." + } + } + } + }, + { + "name": "Block", + "required": false, + "schema": { + "title": "Block number, tag, or block hash", + "anyOf": [ + { + "title": "Block number", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + { + "title": "Block tag", + "type": "string", + "enum": [ + "earliest", + "finalized", + "safe", + "latest", + "pending" + ], + "description": "`earliest`: The lowest numbered block the client has available; `finalized`: The most recent crypto-economically secure block, cannot be re-orged outside of manual intervention driven by community coordination; `safe`: The most recent block that is safe from re-orgs under honest majority and certain synchronicity assumptions; `latest`: The most recent block in the canonical chain observed by the client, this block may be re-orged out of the canonical chain even under healthy/normal conditions; `pending`: A sample next block built by the client on top of `latest` and containing the set of transactions usually taken from local mempool. Before the merge transition is finalized, any call querying for `finalized` or `safe` block MUST be responded to with `-39001: Unknown block` error" + }, + { + "title": "Block hash", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + } + ] + } + } + ], + "result": { + "name": "Return data", + "schema": { + "title": "hex encoded bytes", + "type": "string", + "pattern": "^0x[0-9a-f]*$" + } + } + }, + { + "name": "eth_estimateGas", + "summary": "Generates and returns an estimate of how much gas is necessary to allow the transaction to complete.", + "params": [ + { + "name": "Transaction", + "required": true, + "schema": { + "type": "object", + "title": "Transaction object generic to all types", + "properties": { + "type": { + "title": "type", + "type": "string", + "pattern": "^0x([0-9,a-f,A-F]?){1,2}$" + }, + "nonce": { + "title": "nonce", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "to": { + "title": "to address", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$" + }, + "from": { + "title": "from address", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$" + }, + "gas": { + "title": "gas limit", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "value": { + "title": "value", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "input": { + "title": "input data", + "type": "string", + "pattern": "^0x[0-9a-f]*$" + }, + "gasPrice": { + "title": "gas price", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "The gas price willing to be paid by the sender in wei" + }, + "maxPriorityFeePerGas": { + "title": "max priority fee per gas", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "Maximum fee per gas the sender is willing to pay to miners in wei" + }, + "maxFeePerGas": { + "title": "max fee per gas", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "The maximum total fee per gas the sender is willing to pay (includes the network / base fee and miner / priority fee) in wei" + }, + "accessList": { + "title": "accessList", + "type": "array", + "description": "EIP-2930 access list", + "items": { + "title": "Access list entry", + "type": "object", + "properties": { + "address": { + "title": "hex encoded address", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$" + }, + "storageKeys": { + "type": "array", + "items": { + "title": "32 byte hex value", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + } + } + } + } + }, + "chainId": { + "title": "chainId", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "Chain ID that this transaction is valid on." + } + } + } + }, + { + "name": "Block", + "required": false, + "schema": { + "title": "Block number or tag", + "oneOf": [ + { + "title": "Block number", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + { + "title": "Block tag", + "type": "string", + "enum": [ + "earliest", + "finalized", + "safe", + "latest", + "pending" + ], + "description": "`earliest`: The lowest numbered block the client has available; `finalized`: The most recent crypto-economically secure block, cannot be re-orged outside of manual intervention driven by community coordination; `safe`: The most recent block that is safe from re-orgs under honest majority and certain synchronicity assumptions; `latest`: The most recent block in the canonical chain observed by the client, this block may be re-orged out of the canonical chain even under healthy/normal conditions; `pending`: A sample next block built by the client on top of `latest` and containing the set of transactions usually taken from local mempool. Before the merge transition is finalized, any call querying for `finalized` or `safe` block MUST be responded to with `-39001: Unknown block` error" + } + ] + } + } + ], + "result": { + "name": "Gas used", + "schema": { + "title": "hex encoded unsigned integer", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + } + } + }, + { + "name": "eth_createAccessList", + "summary": "Generates an access list for a transaction.", + "params": [ + { + "name": "Transaction", + "required": true, + "schema": { + "type": "object", + "title": "Transaction object generic to all types", + "properties": { + "type": { + "title": "type", + "type": "string", + "pattern": "^0x([0-9,a-f,A-F]?){1,2}$" + }, + "nonce": { + "title": "nonce", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "to": { + "title": "to address", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$" + }, + "from": { + "title": "from address", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$" + }, + "gas": { + "title": "gas limit", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "value": { + "title": "value", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "input": { + "title": "input data", + "type": "string", + "pattern": "^0x[0-9a-f]*$" + }, + "gasPrice": { + "title": "gas price", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "The gas price willing to be paid by the sender in wei" + }, + "maxPriorityFeePerGas": { + "title": "max priority fee per gas", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "Maximum fee per gas the sender is willing to pay to miners in wei" + }, + "maxFeePerGas": { + "title": "max fee per gas", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "The maximum total fee per gas the sender is willing to pay (includes the network / base fee and miner / priority fee) in wei" + }, + "accessList": { + "title": "accessList", + "type": "array", + "description": "EIP-2930 access list", + "items": { + "title": "Access list entry", + "type": "object", + "properties": { + "address": { + "title": "hex encoded address", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$" + }, + "storageKeys": { + "type": "array", + "items": { + "title": "32 byte hex value", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + } + } + } + } + }, + "chainId": { + "title": "chainId", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "Chain ID that this transaction is valid on." + } + } + } + }, + { + "name": "Block", + "required": false, + "schema": { + "title": "Block number or tag", + "oneOf": [ + { + "title": "Block number", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + { + "title": "Block tag", + "type": "string", + "enum": [ + "earliest", + "finalized", + "safe", + "latest", + "pending" + ], + "description": "`earliest`: The lowest numbered block the client has available; `finalized`: The most recent crypto-economically secure block, cannot be re-orged outside of manual intervention driven by community coordination; `safe`: The most recent block that is safe from re-orgs under honest majority and certain synchronicity assumptions; `latest`: The most recent block in the canonical chain observed by the client, this block may be re-orged out of the canonical chain even under healthy/normal conditions; `pending`: A sample next block built by the client on top of `latest` and containing the set of transactions usually taken from local mempool. Before the merge transition is finalized, any call querying for `finalized` or `safe` block MUST be responded to with `-39001: Unknown block` error" + } + ] + } + } + ], + "result": { + "name": "Gas used", + "schema": { + "title": "Access list result", + "type": "object", + "properties": { + "accessList": { + "title": "accessList", + "type": "array", + "items": { + "title": "Access list entry", + "type": "object", + "properties": { + "address": { + "title": "hex encoded address", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$" + }, + "storageKeys": { + "type": "array", + "items": { + "title": "32 byte hex value", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + } + } + } + } + }, + "error": { + "title": "error", + "type": "string" + }, + "gasUsed": { + "title": "Gas used", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + } + } + } + } + }, + { + "name": "eth_gasPrice", + "summary": "Returns the current price per gas in wei.", + "params": [], + "result": { + "name": "Gas price", + "schema": { + "title": "Gas price", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + } + } + }, + { + "name": "eth_maxPriorityFeePerGas", + "summary": "Returns the current maxPriorityFeePerGas per gas in wei.", + "params": [], + "result": { + "name": "Max priority fee per gas", + "schema": { + "title": "Max priority fee per gas", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + } + } + }, + { + "name": "eth_feeHistory", + "summary": "Transaction fee history", + "description": "Returns transaction base fee per gas and effective priority fee per gas for the requested/supported block range.", + "params": [ + { + "name": "blockCount", + "description": "Requested range of blocks. Clients will return less than the requested range if not all blocks are available.", + "required": true, + "schema": { + "title": "hex encoded unsigned integer", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + } + }, + { + "name": "newestBlock", + "description": "Highest block of the requested range.", + "required": true, + "schema": { + "title": "Block number or tag", + "oneOf": [ + { + "title": "Block number", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + { + "title": "Block tag", + "type": "string", + "enum": [ + "earliest", + "finalized", + "safe", + "latest", + "pending" + ], + "description": "`earliest`: The lowest numbered block the client has available; `finalized`: The most recent crypto-economically secure block, cannot be re-orged outside of manual intervention driven by community coordination; `safe`: The most recent block that is safe from re-orgs under honest majority and certain synchronicity assumptions; `latest`: The most recent block in the canonical chain observed by the client, this block may be re-orged out of the canonical chain even under healthy/normal conditions; `pending`: A sample next block built by the client on top of `latest` and containing the set of transactions usually taken from local mempool. Before the merge transition is finalized, any call querying for `finalized` or `safe` block MUST be responded to with `-39001: Unknown block` error" + } + ] + } + }, + { + "name": "rewardPercentiles", + "description": "A monotonically increasing list of percentile values. For each block in the requested range, the transactions will be sorted in ascending order by effective tip per gas and the coresponding effective tip for the percentile will be determined, accounting for gas consumed.", + "required": true, + "schema": { + "title": "rewardPercentiles", + "type": "array", + "items": { + "title": "rewardPercentile", + "description": "Floating point value between 0 and 100.", + "type": "number" + } + } + } + ], + "result": { + "name": "feeHistoryResult", + "description": "Fee history for the returned block range. This can be a subsection of the requested range if not all blocks are available.", + "schema": { + "title": "feeHistoryResults", + "description": "Fee history results.", + "type": "object", + "required": [ + "oldestBlock", + "baseFeePerGas", + "gasUsedRatio" + ], + "properties": { + "oldestBlock": { + "title": "oldestBlock", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "Lowest number block of returned range." + }, + "baseFeePerGas": { + "title": "baseFeePerGasArray", + "description": "An array of block base fees per gas. This includes the next block after the newest of the returned range, because this value can be derived from the newest block. Zeroes are returned for pre-EIP-1559 blocks.", + "type": "array", + "items": { + "title": "hex encoded unsigned integer", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + } + }, + "reward": { + "title": "rewardArray", + "description": "A two-dimensional array of effective priority fees per gas at the requested block percentiles.", + "type": "array", + "items": { + "title": "rewardPercentile", + "description": "An array of effective priority fee per gas data points from a single block. All zeroes are returned if the block is empty.", + "type": "array", + "items": { + "title": "rewardPercentile", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "A given percentile sample of effective priority fees per gas from a single block in ascending order, weighted by gas used. Zeroes are returned if the block is empty." + } + } + } + } + } + } + }, + { + "name": "eth_newFilter", + "summary": "Creates a filter object, based on filter options, to notify when the state changes (logs).", + "params": [ + { + "name": "Filter", + "schema": { + "title": "filter", + "type": "object", + "properties": { + "fromBlock": { + "title": "from block", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "toBlock": { + "title": "to block", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "address": { + "title": "Address(es)", + "oneOf": [ + { + "title": "Address", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$" + }, + { + "title": "Addresses", + "type": "array", + "items": { + "title": "hex encoded address", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$" + } + } + ] + }, + "topics": { + "title": "Topics", + "type": "array", + "items": { + "title": "Filter Topic List Entry", + "oneOf": [ + { + "title": "Any Topic Match", + "type": "null" + }, + { + "title": "Single Topic Match", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + }, + { + "title": "Multiple Topic Match", + "type": "array", + "items": { + "title": "32 hex encoded bytes", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + } + } + ] + } + } + } + } + } + ], + "result": { + "name": "Filter Identifier", + "schema": { + "title": "hex encoded unsigned integer", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + } + } + }, + { + "name": "eth_newBlockFilter", + "summary": "Creates a filter in the node, to notify when a new block arrives.", + "params": [], + "result": { + "name": "Filter Identifier", + "schema": { + "title": "hex encoded unsigned integer", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + } + } + }, + { + "name": "eth_newPendingTransactionFilter", + "summary": "Creates a filter in the node, to notify when new pending transactions arrive.", + "params": [], + "result": { + "name": "Filter Identifier", + "schema": { + "title": "hex encoded unsigned integer", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + } + } + }, + { + "name": "eth_uninstallFilter", + "summary": "Uninstalls a filter with given id.", + "params": [ + { + "name": "Filter Identifier", + "schema": { + "title": "hex encoded unsigned integer", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + } + } + ], + "result": { + "name": "Success", + "schema": { + "type": "boolean" + } + } + }, + { + "name": "eth_getFilterChanges", + "summary": "Polling method for a filter, which returns an array of logs which occurred since last poll.", + "params": [ + { + "name": "Filter Identifier", + "schema": { + "title": "hex encoded unsigned integer", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + } + } + ], + "result": { + "name": "Log objects", + "schema": { + "title": "Filter results", + "oneOf": [ + { + "title": "new block hashes", + "type": "array", + "items": { + "title": "32 byte hex value", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + } + }, + { + "title": "new transaction hashes", + "type": "array", + "items": { + "title": "32 byte hex value", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + } + }, + { + "title": "new logs", + "type": "array", + "items": { + "title": "log", + "type": "object", + "required": [ + "transactionHash" + ], + "properties": { + "removed": { + "title": "removed", + "type": "boolean" + }, + "logIndex": { + "title": "log index", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "transactionIndex": { + "title": "transaction index", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "transactionHash": { + "title": "transaction hash", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + }, + "blockHash": { + "title": "block hash", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + }, + "blockNumber": { + "title": "block number", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "address": { + "title": "address", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$" + }, + "data": { + "title": "data", + "type": "string", + "pattern": "^0x[0-9a-f]*$" + }, + "topics": { + "title": "topics", + "type": "array", + "items": { + "title": "32 hex encoded bytes", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + } + } + } + } + } + ] + } + } + }, + { + "name": "eth_getFilterLogs", + "summary": "Returns an array of all logs matching filter with given id.", + "params": [ + { + "name": "Filter Identifier", + "schema": { + "title": "hex encoded unsigned integer", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + } + } + ], + "result": { + "name": "Log objects", + "schema": { + "title": "Filter results", + "oneOf": [ + { + "title": "new block hashes", + "type": "array", + "items": { + "title": "32 byte hex value", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + } + }, + { + "title": "new transaction hashes", + "type": "array", + "items": { + "title": "32 byte hex value", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + } + }, + { + "title": "new logs", + "type": "array", + "items": { + "title": "log", + "type": "object", + "required": [ + "transactionHash" + ], + "properties": { + "removed": { + "title": "removed", + "type": "boolean" + }, + "logIndex": { + "title": "log index", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "transactionIndex": { + "title": "transaction index", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "transactionHash": { + "title": "transaction hash", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + }, + "blockHash": { + "title": "block hash", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + }, + "blockNumber": { + "title": "block number", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "address": { + "title": "address", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$" + }, + "data": { + "title": "data", + "type": "string", + "pattern": "^0x[0-9a-f]*$" + }, + "topics": { + "title": "topics", + "type": "array", + "items": { + "title": "32 hex encoded bytes", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + } + } + } + } + } + ] + } + } + }, + { + "name": "eth_getLogs", + "summary": "Returns an array of all logs matching filter with given id.", + "params": [ + { + "name": "Filter", + "schema": { + "title": "filter", + "type": "object", + "properties": { + "fromBlock": { + "title": "from block", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "toBlock": { + "title": "to block", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "address": { + "title": "Address(es)", + "oneOf": [ + { + "title": "Address", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$" + }, + { + "title": "Addresses", + "type": "array", + "items": { + "title": "hex encoded address", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$" + } + } + ] + }, + "topics": { + "title": "Topics", + "type": "array", + "items": { + "title": "Filter Topic List Entry", + "oneOf": [ + { + "title": "Any Topic Match", + "type": "null" + }, + { + "title": "Single Topic Match", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + }, + { + "title": "Multiple Topic Match", + "type": "array", + "items": { + "title": "32 hex encoded bytes", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + } + } + ] + } + } + } + } + } + ], + "result": { + "name": "Log objects", + "schema": { + "title": "Filter results", + "oneOf": [ + { + "title": "new block hashes", + "type": "array", + "items": { + "title": "32 byte hex value", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + } + }, + { + "title": "new transaction hashes", + "type": "array", + "items": { + "title": "32 byte hex value", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + } + }, + { + "title": "new logs", + "type": "array", + "items": { + "title": "log", + "type": "object", + "required": [ + "transactionHash" + ], + "properties": { + "removed": { + "title": "removed", + "type": "boolean" + }, + "logIndex": { + "title": "log index", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "transactionIndex": { + "title": "transaction index", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "transactionHash": { + "title": "transaction hash", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + }, + "blockHash": { + "title": "block hash", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + }, + "blockNumber": { + "title": "block number", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "address": { + "title": "address", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$" + }, + "data": { + "title": "data", + "type": "string", + "pattern": "^0x[0-9a-f]*$" + }, + "topics": { + "title": "topics", + "type": "array", + "items": { + "title": "32 hex encoded bytes", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + } + } + } + } + } + ] + } + } + }, + { + "name": "eth_mining", + "summary": "Returns whether the client is actively mining new blocks.", + "params": [], + "result": { + "name": "Mining status", + "schema": { + "title": "miningStatus", + "type": "boolean" + } + } + }, + { + "name": "eth_hashrate", + "summary": "Returns the number of hashes per second that the node is mining with.", + "params": [], + "result": { + "name": "Mining status", + "schema": { + "title": "Hashrate", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + } + } + }, + { + "name": "eth_getWork", + "summary": "Returns the hash of the current block, the seedHash, and the boundary condition to be met (“target”).", + "params": [], + "result": { + "name": "Current work", + "schema": { + "type": "array", + "items": [ + { + "title": "Proof-of-work hash", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + }, + { + "title": "seed hash", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + }, + { + "title": "difficulty", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + } + ] + } + } + }, + { + "name": "eth_submitWork", + "summary": "Used for submitting a proof-of-work solution.", + "params": [ + { + "name": "nonce", + "required": true, + "schema": { + "title": "8 hex encoded bytes", + "type": "string", + "pattern": "^0x[0-9a-f]{16}$" + } + }, + { + "name": "hash", + "required": true, + "schema": { + "title": "32 hex encoded bytes", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + } + }, + { + "name": "digest", + "required": true, + "schema": { + "title": "32 hex encoded bytes", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + } + } + ], + "result": { + "name": "Success", + "schema": { + "type": "boolean" + } + } + }, + { + "name": "eth_submitHashrate", + "summary": "Used for submitting mining hashrate.", + "params": [ + { + "name": "Hashrate", + "required": true, + "schema": { + "title": "32 hex encoded bytes", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + } + }, + { + "name": "ID", + "required": true, + "schema": { + "title": "32 hex encoded bytes", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + } + } + ], + "result": { + "name": "Success", + "schema": { + "type": "boolean" + } + } + }, + { + "name": "eth_sign", + "summary": "Returns an EIP-191 signature over the provided data.", + "params": [ + { + "name": "Address", + "required": true, + "schema": { + "title": "hex encoded address", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$" + } + }, + { + "name": "Message", + "required": true, + "schema": { + "title": "hex encoded bytes", + "type": "string", + "pattern": "^0x[0-9a-f]*$" + } + } + ], + "result": { + "name": "Signature", + "schema": { + "title": "65 hex encoded bytes", + "type": "string", + "pattern": "^0x[0-9a-f]{65}$" + } + } + }, + { + "name": "eth_signTransaction", + "summary": "Returns an RLP encoded transaction signed by the specified account.", + "params": [ + { + "name": "Transaction", + "required": true, + "schema": { + "type": "object", + "title": "Transaction object generic to all types", + "properties": { + "type": { + "title": "type", + "type": "string", + "pattern": "^0x([0-9,a-f,A-F]?){1,2}$" + }, + "nonce": { + "title": "nonce", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "to": { + "title": "to address", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$" + }, + "from": { + "title": "from address", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$" + }, + "gas": { + "title": "gas limit", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "value": { + "title": "value", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "input": { + "title": "input data", + "type": "string", + "pattern": "^0x[0-9a-f]*$" + }, + "gasPrice": { + "title": "gas price", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "The gas price willing to be paid by the sender in wei" + }, + "maxPriorityFeePerGas": { + "title": "max priority fee per gas", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "Maximum fee per gas the sender is willing to pay to miners in wei" + }, + "maxFeePerGas": { + "title": "max fee per gas", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "The maximum total fee per gas the sender is willing to pay (includes the network / base fee and miner / priority fee) in wei" + }, + "accessList": { + "title": "accessList", + "type": "array", + "description": "EIP-2930 access list", + "items": { + "title": "Access list entry", + "type": "object", + "properties": { + "address": { + "title": "hex encoded address", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$" + }, + "storageKeys": { + "type": "array", + "items": { + "title": "32 byte hex value", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + } + } + } + } + }, + "chainId": { + "title": "chainId", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "Chain ID that this transaction is valid on." + } + } + } + } + ], + "result": { + "name": "Encoded transaction", + "schema": { + "title": "hex encoded bytes", + "type": "string", + "pattern": "^0x[0-9a-f]*$" + } + } + }, + { + "name": "eth_getBalance", + "summary": "Returns the balance of the account of given address.", + "params": [ + { + "name": "Address", + "required": true, + "schema": { + "title": "hex encoded address", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$" + } + }, + { + "name": "Block", + "required": false, + "schema": { + "title": "Block number, tag, or block hash", + "anyOf": [ + { + "title": "Block number", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + { + "title": "Block tag", + "type": "string", + "enum": [ + "earliest", + "finalized", + "safe", + "latest", + "pending" + ], + "description": "`earliest`: The lowest numbered block the client has available; `finalized`: The most recent crypto-economically secure block, cannot be re-orged outside of manual intervention driven by community coordination; `safe`: The most recent block that is safe from re-orgs under honest majority and certain synchronicity assumptions; `latest`: The most recent block in the canonical chain observed by the client, this block may be re-orged out of the canonical chain even under healthy/normal conditions; `pending`: A sample next block built by the client on top of `latest` and containing the set of transactions usually taken from local mempool. Before the merge transition is finalized, any call querying for `finalized` or `safe` block MUST be responded to with `-39001: Unknown block` error" + }, + { + "title": "Block hash", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + } + ] + } + } + ], + "result": { + "name": "Balance", + "schema": { + "title": "hex encoded unsigned integer", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + } + } + }, + { + "name": "eth_getStorageAt", + "summary": "Returns the value from a storage position at a given address.", + "params": [ + { + "name": "Address", + "required": true, + "schema": { + "title": "hex encoded address", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$" + } + }, + { + "name": "Storage slot", + "required": true, + "schema": { + "title": "hex encoded 256 bit unsigned integer", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]{0,31})|0$" + } + }, + { + "name": "Block", + "required": false, + "schema": { + "title": "Block number, tag, or block hash", + "anyOf": [ + { + "title": "Block number", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + { + "title": "Block tag", + "type": "string", + "enum": [ + "earliest", + "finalized", + "safe", + "latest", + "pending" + ], + "description": "`earliest`: The lowest numbered block the client has available; `finalized`: The most recent crypto-economically secure block, cannot be re-orged outside of manual intervention driven by community coordination; `safe`: The most recent block that is safe from re-orgs under honest majority and certain synchronicity assumptions; `latest`: The most recent block in the canonical chain observed by the client, this block may be re-orged out of the canonical chain even under healthy/normal conditions; `pending`: A sample next block built by the client on top of `latest` and containing the set of transactions usually taken from local mempool. Before the merge transition is finalized, any call querying for `finalized` or `safe` block MUST be responded to with `-39001: Unknown block` error" + }, + { + "title": "Block hash", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + } + ] + } + } + ], + "result": { + "name": "Value", + "schema": { + "title": "hex encoded bytes", + "type": "string", + "pattern": "^0x[0-9a-f]*$" + } + } + }, + { + "name": "eth_getTransactionCount", + "summary": "Returns the number of transactions sent from an address.", + "params": [ + { + "name": "Address", + "required": true, + "schema": { + "title": "hex encoded address", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$" + } + }, + { + "name": "Block", + "required": false, + "schema": { + "title": "Block number, tag, or block hash", + "anyOf": [ + { + "title": "Block number", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + { + "title": "Block tag", + "type": "string", + "enum": [ + "earliest", + "finalized", + "safe", + "latest", + "pending" + ], + "description": "`earliest`: The lowest numbered block the client has available; `finalized`: The most recent crypto-economically secure block, cannot be re-orged outside of manual intervention driven by community coordination; `safe`: The most recent block that is safe from re-orgs under honest majority and certain synchronicity assumptions; `latest`: The most recent block in the canonical chain observed by the client, this block may be re-orged out of the canonical chain even under healthy/normal conditions; `pending`: A sample next block built by the client on top of `latest` and containing the set of transactions usually taken from local mempool. Before the merge transition is finalized, any call querying for `finalized` or `safe` block MUST be responded to with `-39001: Unknown block` error" + }, + { + "title": "Block hash", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + } + ] + } + } + ], + "result": { + "name": "Transaction count", + "schema": { + "title": "hex encoded unsigned integer", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + } + } + }, + { + "name": "eth_getCode", + "summary": "Returns code at a given address.", + "params": [ + { + "name": "Address", + "required": true, + "schema": { + "title": "hex encoded address", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$" + } + }, + { + "name": "Block", + "required": false, + "schema": { + "title": "Block number, tag, or block hash", + "anyOf": [ + { + "title": "Block number", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + { + "title": "Block tag", + "type": "string", + "enum": [ + "earliest", + "finalized", + "safe", + "latest", + "pending" + ], + "description": "`earliest`: The lowest numbered block the client has available; `finalized`: The most recent crypto-economically secure block, cannot be re-orged outside of manual intervention driven by community coordination; `safe`: The most recent block that is safe from re-orgs under honest majority and certain synchronicity assumptions; `latest`: The most recent block in the canonical chain observed by the client, this block may be re-orged out of the canonical chain even under healthy/normal conditions; `pending`: A sample next block built by the client on top of `latest` and containing the set of transactions usually taken from local mempool. Before the merge transition is finalized, any call querying for `finalized` or `safe` block MUST be responded to with `-39001: Unknown block` error" + }, + { + "title": "Block hash", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + } + ] + } + } + ], + "result": { + "name": "Bytecode", + "schema": { + "title": "hex encoded bytes", + "type": "string", + "pattern": "^0x[0-9a-f]*$" + } + } + }, + { + "name": "eth_getProof", + "summary": "Returns the merkle proof for a given account and optionally some storage keys.", + "params": [ + { + "name": "Address", + "required": true, + "schema": { + "title": "hex encoded address", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$" + } + }, + { + "name": "StorageKeys", + "required": true, + "schema": { + "title": "Storage keys", + "type": "array", + "items": { + "title": "32 hex encoded bytes", + "type": "string", + "pattern": "^0x[0-9a-f]{0,64}$" + } + } + }, + { + "name": "Block", + "required": true, + "schema": { + "title": "Block number, tag, or block hash", + "anyOf": [ + { + "title": "Block number", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + { + "title": "Block tag", + "type": "string", + "enum": [ + "earliest", + "finalized", + "safe", + "latest", + "pending" + ], + "description": "`earliest`: The lowest numbered block the client has available; `finalized`: The most recent crypto-economically secure block, cannot be re-orged outside of manual intervention driven by community coordination; `safe`: The most recent block that is safe from re-orgs under honest majority and certain synchronicity assumptions; `latest`: The most recent block in the canonical chain observed by the client, this block may be re-orged out of the canonical chain even under healthy/normal conditions; `pending`: A sample next block built by the client on top of `latest` and containing the set of transactions usually taken from local mempool. Before the merge transition is finalized, any call querying for `finalized` or `safe` block MUST be responded to with `-39001: Unknown block` error" + }, + { + "title": "Block hash", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + } + ] + } + } + ], + "result": { + "name": "Account", + "schema": { + "title": "Account proof", + "type": "object", + "required": [ + "address", + "accountProof", + "balance", + "codeHash", + "nonce", + "storageHash", + "storageProof" + ], + "properties": { + "address": { + "title": "address", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$" + }, + "accountProof": { + "title": "accountProof", + "type": "array", + "items": { + "title": "hex encoded bytes", + "type": "string", + "pattern": "^0x[0-9a-f]*$" + } + }, + "balance": { + "title": "balance", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]{0,31})|0$" + }, + "codeHash": { + "title": "codeHash", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + }, + "nonce": { + "title": "nonce", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]{0,15})|0$" + }, + "storageHash": { + "title": "storageHash", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + }, + "storageProof": { + "title": "Storage proofs", + "type": "array", + "items": { + "title": "Storage proof", + "type": "object", + "required": [ + "key", + "value", + "proof" + ], + "properties": { + "key": { + "title": "key", + "type": "string", + "pattern": "^0x[0-9a-f]{0,64}$" + }, + "value": { + "title": "value", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]{0,31})|0$" + }, + "proof": { + "title": "proof", + "type": "array", + "items": { + "title": "hex encoded bytes", + "type": "string", + "pattern": "^0x[0-9a-f]*$" + } + } + } + } + } + } + } + } + }, + { + "name": "eth_sendTransaction", + "summary": "Signs and submits a transaction.", + "params": [ + { + "name": "Transaction", + "required": true, + "schema": { + "type": "object", + "title": "Transaction object generic to all types", + "properties": { + "type": { + "title": "type", + "type": "string", + "pattern": "^0x([0-9,a-f,A-F]?){1,2}$" + }, + "nonce": { + "title": "nonce", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "to": { + "title": "to address", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$" + }, + "from": { + "title": "from address", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$" + }, + "gas": { + "title": "gas limit", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "value": { + "title": "value", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "input": { + "title": "input data", + "type": "string", + "pattern": "^0x[0-9a-f]*$" + }, + "gasPrice": { + "title": "gas price", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "The gas price willing to be paid by the sender in wei" + }, + "maxPriorityFeePerGas": { + "title": "max priority fee per gas", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "Maximum fee per gas the sender is willing to pay to miners in wei" + }, + "maxFeePerGas": { + "title": "max fee per gas", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "The maximum total fee per gas the sender is willing to pay (includes the network / base fee and miner / priority fee) in wei" + }, + "accessList": { + "title": "accessList", + "type": "array", + "description": "EIP-2930 access list", + "items": { + "title": "Access list entry", + "type": "object", + "properties": { + "address": { + "title": "hex encoded address", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$" + }, + "storageKeys": { + "type": "array", + "items": { + "title": "32 byte hex value", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + } + } + } + } + }, + "chainId": { + "title": "chainId", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "Chain ID that this transaction is valid on." + } + } + } + } + ], + "result": { + "name": "Transaction hash", + "schema": { + "title": "32 byte hex value", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + } + } + }, + { + "name": "eth_sendRawTransaction", + "summary": "Submits a raw transaction.", + "params": [ + { + "name": "Transaction", + "required": true, + "schema": { + "title": "hex encoded bytes", + "type": "string", + "pattern": "^0x[0-9a-f]*$" + } + } + ], + "result": { + "name": "Transaction hash", + "schema": { + "title": "32 byte hex value", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + } + } + }, + { + "name": "eth_getTransactionByHash", + "summary": "Returns the information about a transaction requested by transaction hash.", + "params": [ + { + "name": "Transaction hash", + "required": true, + "schema": { + "title": "32 byte hex value", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + } + } + ], + "result": { + "name": "Transaction information", + "schema": { + "type": "object", + "title": "Transaction information", + "required": [ + "blockHash", + "blockNumber", + "from", + "hash", + "transactionIndex" + ], + "oneOf": [ + { + "title": "Signed 1559 Transaction", + "type": "object", + "required": [ + "accessList", + "chainId", + "gas", + "input", + "maxFeePerGas", + "maxPriorityFeePerGas", + "nonce", + "r", + "s", + "type", + "value", + "yParity" + ], + "properties": { + "type": { + "title": "type", + "type": "string", + "pattern": "^0x([0-9,a-f,A-F]?){1,2}$" + }, + "nonce": { + "title": "nonce", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "to": { + "title": "to address", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$" + }, + "gas": { + "title": "gas limit", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "value": { + "title": "value", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "input": { + "title": "input data", + "type": "string", + "pattern": "^0x[0-9a-f]*$" + }, + "maxPriorityFeePerGas": { + "title": "max priority fee per gas", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "Maximum fee per gas the sender is willing to pay to miners in wei" + }, + "maxFeePerGas": { + "title": "max fee per gas", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "The maximum total fee per gas the sender is willing to pay (includes the network / base fee and miner / priority fee) in wei" + }, + "accessList": { + "title": "accessList", + "type": "array", + "description": "EIP-2930 access list", + "items": { + "title": "Access list entry", + "type": "object", + "properties": { + "address": { + "title": "hex encoded address", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$" + }, + "storageKeys": { + "type": "array", + "items": { + "title": "32 byte hex value", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + } + } + } + } + }, + "chainId": { + "title": "chainId", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "Chain ID that this transaction is valid on." + }, + "yParity": { + "title": "yParity", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "The parity (0 for even, 1 for odd) of the y-value of the secp256k1 signature." + }, + "r": { + "title": "r", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "s": { + "title": "s", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + } + } + }, + { + "title": "Signed 2930 Transaction", + "type": "object", + "required": [ + "accessList", + "chainId", + "gas", + "gasPrice", + "input", + "nonce", + "r", + "s", + "type", + "value", + "yParity" + ], + "properties": { + "type": { + "title": "type", + "type": "string", + "pattern": "^0x([0-9,a-f,A-F]?){1,2}$" + }, + "nonce": { + "title": "nonce", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "to": { + "title": "to address", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$" + }, + "gas": { + "title": "gas limit", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "value": { + "title": "value", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "input": { + "title": "input data", + "type": "string", + "pattern": "^0x[0-9a-f]*$" + }, + "gasPrice": { + "title": "gas price", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "The gas price willing to be paid by the sender in wei" + }, + "accessList": { + "title": "accessList", + "type": "array", + "description": "EIP-2930 access list", + "items": { + "title": "Access list entry", + "type": "object", + "properties": { + "address": { + "title": "hex encoded address", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$" + }, + "storageKeys": { + "type": "array", + "items": { + "title": "32 byte hex value", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + } + } + } + } + }, + "chainId": { + "title": "chainId", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "Chain ID that this transaction is valid on." + }, + "yParity": { + "title": "yParity", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "The parity (0 for even, 1 for odd) of the y-value of the secp256k1 signature." + }, + "r": { + "title": "r", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "s": { + "title": "s", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + } + } + }, + { + "title": "Signed Legacy Transaction", + "type": "object", + "required": [ + "gas", + "gasPrice", + "input", + "nonce", + "r", + "s", + "type", + "v", + "value" + ], + "properties": { + "type": { + "title": "type", + "type": "string", + "pattern": "^0x([0-9,a-f,A-F]?){1,2}$" + }, + "nonce": { + "title": "nonce", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "to": { + "title": "to address", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$" + }, + "gas": { + "title": "gas limit", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "value": { + "title": "value", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "input": { + "title": "input data", + "type": "string", + "pattern": "^0x[0-9a-f]*$" + }, + "gasPrice": { + "title": "gas price", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "The gas price willing to be paid by the sender in wei" + }, + "chainId": { + "title": "chainId", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "Chain ID that this transaction is valid on." + }, + "v": { + "title": "v", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "r": { + "title": "r", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "s": { + "title": "s", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + } + } + } + ], + "properties": { + "blockHash": { + "title": "block hash", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + }, + "blockNumber": { + "title": "block number", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "from": { + "title": "from address", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$" + }, + "hash": { + "title": "transaction hash", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + }, + "transactionIndex": { + "title": "transaction index", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + } + } + } + } + }, + { + "name": "eth_getTransactionByBlockHashAndIndex", + "summary": "Returns information about a transaction by block hash and transaction index position.", + "params": [ + { + "name": "Block hash", + "required": true, + "schema": { + "title": "32 byte hex value", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + } + }, + { + "name": "Transaction index", + "required": true, + "schema": { + "title": "hex encoded unsigned integer", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + } + } + ], + "result": { + "name": "Transaction information", + "schema": { + "type": "object", + "title": "Transaction information", + "required": [ + "blockHash", + "blockNumber", + "from", + "hash", + "transactionIndex" + ], + "oneOf": [ + { + "title": "Signed 1559 Transaction", + "type": "object", + "required": [ + "accessList", + "chainId", + "gas", + "input", + "maxFeePerGas", + "maxPriorityFeePerGas", + "nonce", + "r", + "s", + "type", + "value", + "yParity" + ], + "properties": { + "type": { + "title": "type", + "type": "string", + "pattern": "^0x([0-9,a-f,A-F]?){1,2}$" + }, + "nonce": { + "title": "nonce", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "to": { + "title": "to address", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$" + }, + "gas": { + "title": "gas limit", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "value": { + "title": "value", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "input": { + "title": "input data", + "type": "string", + "pattern": "^0x[0-9a-f]*$" + }, + "maxPriorityFeePerGas": { + "title": "max priority fee per gas", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "Maximum fee per gas the sender is willing to pay to miners in wei" + }, + "maxFeePerGas": { + "title": "max fee per gas", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "The maximum total fee per gas the sender is willing to pay (includes the network / base fee and miner / priority fee) in wei" + }, + "accessList": { + "title": "accessList", + "type": "array", + "description": "EIP-2930 access list", + "items": { + "title": "Access list entry", + "type": "object", + "properties": { + "address": { + "title": "hex encoded address", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$" + }, + "storageKeys": { + "type": "array", + "items": { + "title": "32 byte hex value", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + } + } + } + } + }, + "chainId": { + "title": "chainId", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "Chain ID that this transaction is valid on." + }, + "yParity": { + "title": "yParity", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "The parity (0 for even, 1 for odd) of the y-value of the secp256k1 signature." + }, + "r": { + "title": "r", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "s": { + "title": "s", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + } + } + }, + { + "title": "Signed 2930 Transaction", + "type": "object", + "required": [ + "accessList", + "chainId", + "gas", + "gasPrice", + "input", + "nonce", + "r", + "s", + "type", + "value", + "yParity" + ], + "properties": { + "type": { + "title": "type", + "type": "string", + "pattern": "^0x([0-9,a-f,A-F]?){1,2}$" + }, + "nonce": { + "title": "nonce", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "to": { + "title": "to address", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$" + }, + "gas": { + "title": "gas limit", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "value": { + "title": "value", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "input": { + "title": "input data", + "type": "string", + "pattern": "^0x[0-9a-f]*$" + }, + "gasPrice": { + "title": "gas price", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "The gas price willing to be paid by the sender in wei" + }, + "accessList": { + "title": "accessList", + "type": "array", + "description": "EIP-2930 access list", + "items": { + "title": "Access list entry", + "type": "object", + "properties": { + "address": { + "title": "hex encoded address", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$" + }, + "storageKeys": { + "type": "array", + "items": { + "title": "32 byte hex value", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + } + } + } + } + }, + "chainId": { + "title": "chainId", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "Chain ID that this transaction is valid on." + }, + "yParity": { + "title": "yParity", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "The parity (0 for even, 1 for odd) of the y-value of the secp256k1 signature." + }, + "r": { + "title": "r", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "s": { + "title": "s", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + } + } + }, + { + "title": "Signed Legacy Transaction", + "type": "object", + "required": [ + "gas", + "gasPrice", + "input", + "nonce", + "r", + "s", + "type", + "v", + "value" + ], + "properties": { + "type": { + "title": "type", + "type": "string", + "pattern": "^0x([0-9,a-f,A-F]?){1,2}$" + }, + "nonce": { + "title": "nonce", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "to": { + "title": "to address", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$" + }, + "gas": { + "title": "gas limit", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "value": { + "title": "value", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "input": { + "title": "input data", + "type": "string", + "pattern": "^0x[0-9a-f]*$" + }, + "gasPrice": { + "title": "gas price", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "The gas price willing to be paid by the sender in wei" + }, + "chainId": { + "title": "chainId", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "Chain ID that this transaction is valid on." + }, + "v": { + "title": "v", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "r": { + "title": "r", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "s": { + "title": "s", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + } + } + } + ], + "properties": { + "blockHash": { + "title": "block hash", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + }, + "blockNumber": { + "title": "block number", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "from": { + "title": "from address", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$" + }, + "hash": { + "title": "transaction hash", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + }, + "transactionIndex": { + "title": "transaction index", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + } + } + } + } + }, + { + "name": "eth_getTransactionByBlockNumberAndIndex", + "summary": "Returns information about a transaction by block number and transaction index position.", + "params": [ + { + "name": "Block", + "required": true, + "schema": { + "title": "Block number or tag", + "oneOf": [ + { + "title": "Block number", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + { + "title": "Block tag", + "type": "string", + "enum": [ + "earliest", + "finalized", + "safe", + "latest", + "pending" + ], + "description": "`earliest`: The lowest numbered block the client has available; `finalized`: The most recent crypto-economically secure block, cannot be re-orged outside of manual intervention driven by community coordination; `safe`: The most recent block that is safe from re-orgs under honest majority and certain synchronicity assumptions; `latest`: The most recent block in the canonical chain observed by the client, this block may be re-orged out of the canonical chain even under healthy/normal conditions; `pending`: A sample next block built by the client on top of `latest` and containing the set of transactions usually taken from local mempool. Before the merge transition is finalized, any call querying for `finalized` or `safe` block MUST be responded to with `-39001: Unknown block` error" + } + ] + } + }, + { + "name": "Transaction index", + "required": true, + "schema": { + "title": "hex encoded unsigned integer", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + } + } + ], + "result": { + "name": "Transaction information", + "schema": { + "type": "object", + "title": "Transaction information", + "required": [ + "blockHash", + "blockNumber", + "from", + "hash", + "transactionIndex" + ], + "oneOf": [ + { + "title": "Signed 1559 Transaction", + "type": "object", + "required": [ + "accessList", + "chainId", + "gas", + "input", + "maxFeePerGas", + "maxPriorityFeePerGas", + "nonce", + "r", + "s", + "type", + "value", + "yParity" + ], + "properties": { + "type": { + "title": "type", + "type": "string", + "pattern": "^0x([0-9,a-f,A-F]?){1,2}$" + }, + "nonce": { + "title": "nonce", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "to": { + "title": "to address", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$" + }, + "gas": { + "title": "gas limit", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "value": { + "title": "value", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "input": { + "title": "input data", + "type": "string", + "pattern": "^0x[0-9a-f]*$" + }, + "maxPriorityFeePerGas": { + "title": "max priority fee per gas", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "Maximum fee per gas the sender is willing to pay to miners in wei" + }, + "maxFeePerGas": { + "title": "max fee per gas", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "The maximum total fee per gas the sender is willing to pay (includes the network / base fee and miner / priority fee) in wei" + }, + "accessList": { + "title": "accessList", + "type": "array", + "description": "EIP-2930 access list", + "items": { + "title": "Access list entry", + "type": "object", + "properties": { + "address": { + "title": "hex encoded address", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$" + }, + "storageKeys": { + "type": "array", + "items": { + "title": "32 byte hex value", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + } + } + } + } + }, + "chainId": { + "title": "chainId", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "Chain ID that this transaction is valid on." + }, + "yParity": { + "title": "yParity", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "The parity (0 for even, 1 for odd) of the y-value of the secp256k1 signature." + }, + "r": { + "title": "r", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "s": { + "title": "s", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + } + } + }, + { + "title": "Signed 2930 Transaction", + "type": "object", + "required": [ + "accessList", + "chainId", + "gas", + "gasPrice", + "input", + "nonce", + "r", + "s", + "type", + "value", + "yParity" + ], + "properties": { + "type": { + "title": "type", + "type": "string", + "pattern": "^0x([0-9,a-f,A-F]?){1,2}$" + }, + "nonce": { + "title": "nonce", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "to": { + "title": "to address", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$" + }, + "gas": { + "title": "gas limit", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "value": { + "title": "value", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "input": { + "title": "input data", + "type": "string", + "pattern": "^0x[0-9a-f]*$" + }, + "gasPrice": { + "title": "gas price", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "The gas price willing to be paid by the sender in wei" + }, + "accessList": { + "title": "accessList", + "type": "array", + "description": "EIP-2930 access list", + "items": { + "title": "Access list entry", + "type": "object", + "properties": { + "address": { + "title": "hex encoded address", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$" + }, + "storageKeys": { + "type": "array", + "items": { + "title": "32 byte hex value", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + } + } + } + } + }, + "chainId": { + "title": "chainId", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "Chain ID that this transaction is valid on." + }, + "yParity": { + "title": "yParity", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "The parity (0 for even, 1 for odd) of the y-value of the secp256k1 signature." + }, + "r": { + "title": "r", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "s": { + "title": "s", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + } + } + }, + { + "title": "Signed Legacy Transaction", + "type": "object", + "required": [ + "gas", + "gasPrice", + "input", + "nonce", + "r", + "s", + "type", + "v", + "value" + ], + "properties": { + "type": { + "title": "type", + "type": "string", + "pattern": "^0x([0-9,a-f,A-F]?){1,2}$" + }, + "nonce": { + "title": "nonce", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "to": { + "title": "to address", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$" + }, + "gas": { + "title": "gas limit", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "value": { + "title": "value", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "input": { + "title": "input data", + "type": "string", + "pattern": "^0x[0-9a-f]*$" + }, + "gasPrice": { + "title": "gas price", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "The gas price willing to be paid by the sender in wei" + }, + "chainId": { + "title": "chainId", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "Chain ID that this transaction is valid on." + }, + "v": { + "title": "v", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "r": { + "title": "r", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "s": { + "title": "s", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + } + } + } + ], + "properties": { + "blockHash": { + "title": "block hash", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + }, + "blockNumber": { + "title": "block number", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "from": { + "title": "from address", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$" + }, + "hash": { + "title": "transaction hash", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + }, + "transactionIndex": { + "title": "transaction index", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + } + } + } + } + }, + { + "name": "eth_getTransactionReceipt", + "summary": "Returns the receipt of a transaction by transaction hash.", + "params": [ + { + "name": "Transaction hash", + "schema": { + "title": "32 byte hex value", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + } + } + ], + "result": { + "name": "Receipt Information", + "schema": { + "type": "object", + "title": "Receipt info", + "required": [ + "blockHash", + "blockNumber", + "from", + "cumulativeGasUsed", + "gasUsed", + "logs", + "logsBloom", + "transactionHash", + "transactionIndex", + "effectiveGasPrice" + ], + "properties": { + "transactionHash": { + "title": "transaction hash", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + }, + "transactionIndex": { + "title": "transaction index", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "blockHash": { + "title": "block hash", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + }, + "blockNumber": { + "title": "block number", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "from": { + "title": "from", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$" + }, + "to": { + "title": "to", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$", + "description": "Address of the receiver or null in a contract creation transaction." + }, + "cumulativeGasUsed": { + "title": "cumulative gas used", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "The sum of gas used by this transaction and all preceding transactions in the same block." + }, + "gasUsed": { + "title": "gas used", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "The amount of gas used for this specific transaction alone." + }, + "contractAddress": { + "title": "contract address", + "description": "The contract address created, if the transaction was a contract creation, otherwise null.", + "oneOf": [ + { + "title": "hex encoded address", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$" + }, + { + "name": null, + "type": "null" + } + ] + }, + "logs": { + "title": "logs", + "type": "array", + "items": { + "title": "log", + "type": "object", + "required": [ + "transactionHash" + ], + "properties": { + "removed": { + "title": "removed", + "type": "boolean" + }, + "logIndex": { + "title": "log index", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "transactionIndex": { + "title": "transaction index", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "transactionHash": { + "title": "transaction hash", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + }, + "blockHash": { + "title": "block hash", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + }, + "blockNumber": { + "title": "block number", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "address": { + "title": "address", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$" + }, + "data": { + "title": "data", + "type": "string", + "pattern": "^0x[0-9a-f]*$" + }, + "topics": { + "title": "topics", + "type": "array", + "items": { + "title": "32 hex encoded bytes", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + } + } + } + } + }, + "logsBloom": { + "title": "logs bloom", + "type": "string", + "pattern": "^0x[0-9a-f]{512}$" + }, + "root": { + "title": "state root", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$", + "description": "The post-transaction state root. Only specified for transactions included before the Byzantium upgrade." + }, + "status": { + "title": "status", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "Either 1 (success) or 0 (failure). Only specified for transactions included after the Byzantium upgrade." + }, + "effectiveGasPrice": { + "title": "effective gas price", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "The actual value per gas deducted from the senders account. Before EIP-1559, this is equal to the transaction's gas price. After, it is equal to baseFeePerGas + min(maxFeePerGas - baseFeePerGas, maxPriorityFeePerGas)." + } + } + } + } + }, + { + "name": "debug_getRawHeader", + "summary": "Returns an RLP-encoded header.", + "params": [ + { + "name": "Block", + "required": true, + "schema": { + "title": "Block number or tag", + "oneOf": [ + { + "title": "Block number", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + { + "title": "Block tag", + "type": "string", + "enum": [ + "earliest", + "finalized", + "safe", + "latest", + "pending" + ], + "description": "`earliest`: The lowest numbered block the client has available; `finalized`: The most recent crypto-economically secure block, cannot be re-orged outside of manual intervention driven by community coordination; `safe`: The most recent block that is safe from re-orgs under honest majority and certain synchronicity assumptions; `latest`: The most recent block in the canonical chain observed by the client, this block may be re-orged out of the canonical chain even under healthy/normal conditions; `pending`: A sample next block built by the client on top of `latest` and containing the set of transactions usually taken from local mempool. Before the merge transition is finalized, any call querying for `finalized` or `safe` block MUST be responded to with `-39001: Unknown block` error" + } + ] + } + } + ], + "result": { + "name": "Header RLP", + "schema": { + "title": "hex encoded bytes", + "type": "string", + "pattern": "^0x[0-9a-f]*$" + } + } + }, + { + "name": "debug_getRawBlock", + "summary": "Returns an RLP-encoded block.", + "params": [ + { + "name": "Block", + "required": true, + "schema": { + "title": "Block number or tag", + "oneOf": [ + { + "title": "Block number", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + { + "title": "Block tag", + "type": "string", + "enum": [ + "earliest", + "finalized", + "safe", + "latest", + "pending" + ], + "description": "`earliest`: The lowest numbered block the client has available; `finalized`: The most recent crypto-economically secure block, cannot be re-orged outside of manual intervention driven by community coordination; `safe`: The most recent block that is safe from re-orgs under honest majority and certain synchronicity assumptions; `latest`: The most recent block in the canonical chain observed by the client, this block may be re-orged out of the canonical chain even under healthy/normal conditions; `pending`: A sample next block built by the client on top of `latest` and containing the set of transactions usually taken from local mempool. Before the merge transition is finalized, any call querying for `finalized` or `safe` block MUST be responded to with `-39001: Unknown block` error" + } + ] + } + } + ], + "result": { + "name": "Block RLP", + "schema": { + "title": "hex encoded bytes", + "type": "string", + "pattern": "^0x[0-9a-f]*$" + } + } + }, + { + "name": "debug_getRawTransaction", + "summary": "Returns an array of EIP-2718 binary-encoded transactions.", + "params": [ + { + "name": "Transaction hash", + "required": true, + "schema": { + "title": "32 byte hex value", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + } + } + ], + "result": { + "name": "EIP-2718 binary-encoded transaction", + "schema": { + "title": "hex encoded bytes", + "type": "string", + "pattern": "^0x[0-9a-f]*$" + } + } + }, + { + "name": "debug_getRawReceipts", + "summary": "Returns an array of EIP-2718 binary-encoded receipts.", + "params": [ + { + "name": "Block", + "required": true, + "schema": { + "title": "Block number or tag", + "oneOf": [ + { + "title": "Block number", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + { + "title": "Block tag", + "type": "string", + "enum": [ + "earliest", + "finalized", + "safe", + "latest", + "pending" + ], + "description": "`earliest`: The lowest numbered block the client has available; `finalized`: The most recent crypto-economically secure block, cannot be re-orged outside of manual intervention driven by community coordination; `safe`: The most recent block that is safe from re-orgs under honest majority and certain synchronicity assumptions; `latest`: The most recent block in the canonical chain observed by the client, this block may be re-orged out of the canonical chain even under healthy/normal conditions; `pending`: A sample next block built by the client on top of `latest` and containing the set of transactions usually taken from local mempool. Before the merge transition is finalized, any call querying for `finalized` or `safe` block MUST be responded to with `-39001: Unknown block` error" + } + ] + } + } + ], + "result": { + "name": "Receipts", + "schema": { + "title": "Receipt array", + "type": "array", + "items": { + "title": "hex encoded bytes", + "type": "string", + "pattern": "^0x[0-9a-f]*$" + } + } + } + }, + { + "name": "debug_getBadBlocks", + "summary": "Returns an array of recent bad blocks that the client has seen on the network.", + "params": [], + "result": { + "name": "Blocks", + "schema": { + "title": "Bad block array", + "type": "array", + "items": { + "title": "Bad block", + "type": "object", + "required": [ + "block", + "hash", + "rlp" + ], + "properties": { + "block": { + "title": "Block", + "type": "string", + "pattern": "^0x[0-9a-f]*$" + }, + "hash": { + "title": "Hash", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + }, + "rlp": { + "title": "RLP", + "type": "string", + "pattern": "^0x[0-9a-f]*$" + } + } + } + } + } + } + ], + "components": {} +} diff --git a/itests/splitstore_test.go b/itests/splitstore_test.go index b5339d24c..4bbe56536 100644 --- a/itests/splitstore_test.go +++ b/itests/splitstore_test.go @@ -351,13 +351,11 @@ func splitStorePruneIndex(ctx context.Context, t *testing.T, n *kit.TestFullNode } func ipldExists(ctx context.Context, t *testing.T, c cid.Cid, n *kit.TestFullNode) bool { - _, err := n.ChainReadObj(ctx, c) - if ipld.IsNotFound(err) { - return false - } else if err != nil { - t.Fatalf("ChainReadObj failure on existence check: %s", err) + found, err := n.ChainHasObj(ctx, c) + if err != nil { + t.Fatalf("ChainHasObj failure: %s", err) } - return true + return found } // Create on chain unreachable garbage for a network to exercise splitstore @@ -414,12 +412,10 @@ func (g *Garbager) Exists(ctx context.Context, c cid.Cid) bool { return false } else if err != nil { g.t.Fatalf("ChainReadObj failure on existence check: %s", err) + return false // unreachable } else { return true } - - g.t.Fatal("unreachable") - return false } func (g *Garbager) newPeerID(ctx context.Context) abi.ChainEpoch { diff --git a/lib/must/must.go b/lib/must/must.go new file mode 100644 index 000000000..e072b4e04 --- /dev/null +++ b/lib/must/must.go @@ -0,0 +1,9 @@ +package must + +func One[R any](r R, err error) R { + if err != nil { + panic(err) + } + + return r +} diff --git a/lib/result/result.go b/lib/result/result.go index bec839d7a..56a9ffab7 100644 --- a/lib/result/result.go +++ b/lib/result/result.go @@ -30,6 +30,12 @@ func Wrap[T any](value T, err error) Result[T] { } } -func (r *Result[T]) Unwrap() (T, error) { +func (r Result[T]) Unwrap() (T, error) { return r.Value, r.Error } + +func (r Result[T]) Assert(noErrFn func(err error, msgAndArgs ...interface{})) T { + noErrFn(r.Error) + + return r.Value +} diff --git a/node/builder.go b/node/builder.go index ddba82112..88b67a96d 100644 --- a/node/builder.go +++ b/node/builder.go @@ -126,6 +126,8 @@ const ( SetApiEndpointKey + StoreEventsKey + _nInvokes // keep this last ) diff --git a/node/builder_chain.go b/node/builder_chain.go index 545c061b2..4e5bad61d 100644 --- a/node/builder_chain.go +++ b/node/builder_chain.go @@ -219,6 +219,11 @@ func ConfigFullNode(c interface{}) Option { Override(SetupFallbackBlockstoresKey, modules.InitFallbackBlockstores), ), + // If the Eth JSON-RPC is enabled, enable storing events at the ChainStore. + // This is the case even if real-time and historic filtering are disabled, + // as it enables us to serve logs in eth_getTransactionReceipt. + If(cfg.Fevm.EnableEthRPC, Override(StoreEventsKey, modules.EnableStoringEvents)), + Override(new(dtypes.ClientImportMgr), modules.ClientImportMgr), Override(new(dtypes.ClientBlockstore), modules.ClientBlockstore), @@ -258,11 +263,18 @@ func ConfigFullNode(c interface{}) Option { // Actor event filtering support Override(new(events.EventAPI), From(new(modules.EventAPI))), - // in lite-mode Eth event api is provided by gateway - ApplyIf(isFullNode, Override(new(full.EthEventAPI), modules.EthEventAPI(cfg.Fevm))), - If(cfg.Fevm.EnableEthRPC, Override(new(full.EthModuleAPI), modules.EthModuleAPI(cfg.Fevm))), - If(!cfg.Fevm.EnableEthRPC, Override(new(full.EthModuleAPI), &full.EthModuleDummy{})), + // in lite-mode Eth api is provided by gateway + ApplyIf(isFullNode, + If(cfg.Fevm.EnableEthRPC, + Override(new(full.EthModuleAPI), modules.EthModuleAPI(cfg.Fevm)), + Override(new(full.EthEventAPI), modules.EthEventAPI(cfg.Fevm)), + ), + If(!cfg.Fevm.EnableEthRPC, + Override(new(full.EthModuleAPI), &full.EthModuleDummy{}), + Override(new(full.EthEventAPI), &full.EthModuleDummy{}), + ), + ), ) } diff --git a/node/impl/full/dummy.go b/node/impl/full/dummy.go index aa1450212..0b4b0080c 100644 --- a/node/impl/full/dummy.go +++ b/node/impl/full/dummy.go @@ -6,11 +6,13 @@ import ( "github.com/ipfs/go-cid" + "github.com/filecoin-project/go-jsonrpc" + "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/chain/types/ethtypes" ) -var ErrModuleDisabled = errors.New("module disabled, enable with Fevm.EnableEthRPC / LOTUS_FEVM_ENABLEETHPRC") +var ErrModuleDisabled = errors.New("module disabled, enable with Fevm.EnableEthRPC / LOTUS_FEVM_ENABLEETHRPC") type EthModuleDummy struct{} @@ -118,4 +120,45 @@ func (e *EthModuleDummy) EthSendRawTransaction(ctx context.Context, rawTx ethtyp return ethtypes.EthHash{}, ErrModuleDisabled } +func (e *EthModuleDummy) Web3ClientVersion(ctx context.Context) (string, error) { + return "", ErrModuleDisabled +} + +func (e *EthModuleDummy) EthGetLogs(ctx context.Context, filter *ethtypes.EthFilterSpec) (*ethtypes.EthFilterResult, error) { + return ðtypes.EthFilterResult{}, ErrModuleDisabled +} + +func (e *EthModuleDummy) EthGetFilterChanges(ctx context.Context, id ethtypes.EthFilterID) (*ethtypes.EthFilterResult, error) { + return ðtypes.EthFilterResult{}, ErrModuleDisabled +} + +func (e *EthModuleDummy) EthGetFilterLogs(ctx context.Context, id ethtypes.EthFilterID) (*ethtypes.EthFilterResult, error) { + return ðtypes.EthFilterResult{}, ErrModuleDisabled +} + +func (e *EthModuleDummy) EthNewFilter(ctx context.Context, filter *ethtypes.EthFilterSpec) (ethtypes.EthFilterID, error) { + return ethtypes.EthFilterID{}, ErrModuleDisabled +} + +func (e *EthModuleDummy) EthNewBlockFilter(ctx context.Context) (ethtypes.EthFilterID, error) { + return ethtypes.EthFilterID{}, ErrModuleDisabled +} + +func (e *EthModuleDummy) EthNewPendingTransactionFilter(ctx context.Context) (ethtypes.EthFilterID, error) { + return ethtypes.EthFilterID{}, ErrModuleDisabled +} + +func (e *EthModuleDummy) EthUninstallFilter(ctx context.Context, id ethtypes.EthFilterID) (bool, error) { + return false, ErrModuleDisabled +} + +func (e *EthModuleDummy) EthSubscribe(ctx context.Context, params jsonrpc.RawParams) (ethtypes.EthSubscriptionID, error) { + return ethtypes.EthSubscriptionID{}, ErrModuleDisabled +} + +func (e *EthModuleDummy) EthUnsubscribe(ctx context.Context, id ethtypes.EthSubscriptionID) (bool, error) { + return false, ErrModuleDisabled +} + var _ EthModuleAPI = &EthModuleDummy{} +var _ EthEventAPI = &EthModuleDummy{} diff --git a/node/impl/full/eth.go b/node/impl/full/eth.go index 7eb992a22..bfbd6dbda 100644 --- a/node/impl/full/eth.go +++ b/node/impl/full/eth.go @@ -3,6 +3,7 @@ package full import ( "bytes" "context" + "encoding/json" "errors" "fmt" "strconv" @@ -16,12 +17,14 @@ import ( "golang.org/x/xerrors" "github.com/filecoin-project/go-address" + "github.com/filecoin-project/go-jsonrpc" "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/big" builtintypes "github.com/filecoin-project/go-state-types/builtin" "github.com/filecoin-project/go-state-types/builtin/v10/eam" "github.com/filecoin-project/go-state-types/builtin/v10/evm" "github.com/filecoin-project/go-state-types/crypto" + "github.com/filecoin-project/go-state-types/exitcode" "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/build" @@ -64,6 +67,7 @@ type EthModuleAPI interface { EthCall(ctx context.Context, tx ethtypes.EthCall, blkParam string) (ethtypes.EthBytes, error) EthMaxPriorityFeePerGas(ctx context.Context) (ethtypes.EthBigInt, error) EthSendRawTransaction(ctx context.Context, rawTx ethtypes.EthBytes) (ethtypes.EthHash, error) + Web3ClientVersion(ctx context.Context) (string, error) } type EthEventAPI interface { @@ -74,13 +78,15 @@ type EthEventAPI interface { EthNewBlockFilter(ctx context.Context) (ethtypes.EthFilterID, error) EthNewPendingTransactionFilter(ctx context.Context) (ethtypes.EthFilterID, error) EthUninstallFilter(ctx context.Context, id ethtypes.EthFilterID) (bool, error) - EthSubscribe(ctx context.Context, eventType string, params *ethtypes.EthSubscriptionParams) (<-chan ethtypes.EthSubscriptionResponse, error) + EthSubscribe(ctx context.Context, params jsonrpc.RawParams) (ethtypes.EthSubscriptionID, error) EthUnsubscribe(ctx context.Context, id ethtypes.EthSubscriptionID) (bool, error) } var ( _ EthModuleAPI = *new(api.FullNode) _ EthEventAPI = *new(api.FullNode) + + _ EthModuleAPI = *new(api.Gateway) ) // EthModule provides the default implementation of the standard Ethereum JSON-RPC API. @@ -131,6 +137,7 @@ type EthEvent struct { FilterStore filter.FilterStore SubManager *EthSubscriptionManager MaxFilterHeightRange abi.ChainEpoch + SubscribtionCtx context.Context } var _ EthEventAPI = (*EthEvent)(nil) @@ -211,7 +218,7 @@ func (a *EthModule) EthGetBlockByHash(ctx context.Context, blkHash ethtypes.EthH if err != nil { return ethtypes.EthBlock{}, xerrors.Errorf("error loading tipset %s: %w", ts, err) } - return newEthBlockFromFilecoinTipSet(ctx, ts, fullTxInfo, a.Chain, a.ChainAPI, a.StateAPI) + return newEthBlockFromFilecoinTipSet(ctx, ts, fullTxInfo, a.Chain, a.StateAPI) } func (a *EthModule) parseBlkParam(ctx context.Context, blkParam string) (tipset *types.TipSet, err error) { @@ -248,7 +255,7 @@ func (a *EthModule) EthGetBlockByNumber(ctx context.Context, blkParam string, fu if err != nil { return ethtypes.EthBlock{}, err } - return newEthBlockFromFilecoinTipSet(ctx, ts, fullTxInfo, a.Chain, a.ChainAPI, a.StateAPI) + return newEthBlockFromFilecoinTipSet(ctx, ts, fullTxInfo, a.Chain, a.StateAPI) } func (a *EthModule) EthGetTransactionByHash(ctx context.Context, txHash *ethtypes.EthHash) (*ethtypes.EthTx, error) { @@ -269,8 +276,8 @@ func (a *EthModule) EthGetTransactionByHash(ctx context.Context, txHash *ethtype // first, try to get the cid from mined transactions msgLookup, err := a.StateAPI.StateSearchMsg(ctx, types.EmptyTSK, c, api.LookbackNoLimit, true) - if err == nil { - tx, err := newEthTxFromFilecoinMessageLookup(ctx, msgLookup, -1, a.Chain, a.StateAPI) + if err == nil && msgLookup != nil { + tx, err := newEthTxFromMessageLookup(ctx, msgLookup, -1, a.Chain, a.StateAPI) if err == nil { return &tx, nil } @@ -286,7 +293,7 @@ func (a *EthModule) EthGetTransactionByHash(ctx context.Context, txHash *ethtype for _, p := range pending { if p.Cid() == c { - tx, err := NewEthTxFromFilecoinMessage(ctx, p, a.StateAPI) + tx, err := newEthTxFromSignedMessage(ctx, p, a.StateAPI) if err != nil { return nil, fmt.Errorf("could not convert Filecoin message into tx: %s", err) } @@ -335,7 +342,7 @@ func (a *EthModule) EthGetMessageCidByTransactionHash(ctx context.Context, txHas } func (a *EthModule) EthGetTransactionHashByCid(ctx context.Context, cid cid.Cid) (*ethtypes.EthHash, error) { - hash, err := EthTxHashFromFilecoinMessageCid(ctx, cid, a.StateAPI) + hash, err := EthTxHashFromMessageCid(ctx, cid, a.StateAPI) if hash == ethtypes.EmptyEthHash { // not found return nil, nil @@ -378,7 +385,7 @@ func (a *EthModule) EthGetTransactionReceipt(ctx context.Context, txHash ethtype return nil, nil } - tx, err := newEthTxFromFilecoinMessageLookup(ctx, msgLookup, -1, a.Chain, a.StateAPI) + tx, err := newEthTxFromMessageLookup(ctx, msgLookup, -1, a.Chain, a.StateAPI) if err != nil { return nil, nil } @@ -440,6 +447,11 @@ func (a *EthModule) EthGetCode(ctx context.Context, ethAddr ethtypes.EthAddress, return nil, xerrors.Errorf("cannot parse block param: %s", blkParam) } + // StateManager.Call will panic if there is no parent + if ts.Height() == 0 { + return nil, xerrors.Errorf("block param must not specify genesis block") + } + // Try calling until we find a height with no migration. var res *api.InvocResult for { @@ -500,18 +512,8 @@ func (a *EthModule) EthGetStorageAt(ctx context.Context, ethAddr ethtypes.EthAdd return nil, fmt.Errorf("failed to construct system sender address: %w", err) } - // TODO super duper hack (raulk). The EVM runtime actor uses the U256 parameter type in - // GetStorageAtParams, which serializes as a hex-encoded string. It should serialize - // as bytes. We didn't get to fix in time for Iron, so for now we just pass - // through the hex-encoded value passed through the Eth JSON-RPC API, by remarshalling it. - // We don't fix this at origin (builtin-actors) because we are not updating the bundle - // for Iron. - tmp, err := position.MarshalJSON() - if err != nil { - panic(err) - } params, err := actors.SerializeParams(&evm.GetStorageAtParams{ - StorageKey: tmp[1 : len(tmp)-1], // TODO strip the JSON-encoding quotes -- yuck + StorageKey: position, }) if err != nil { return nil, fmt.Errorf("failed to serialize parameters: %w", err) @@ -614,7 +616,7 @@ func (a *EthModule) EthFeeHistory(ctx context.Context, blkCount ethtypes.EthUint for ts.Height() >= abi.ChainEpoch(oldestBlkHeight) { // Unfortunately we need to rebuild the full message view so we can // totalize gas used in the tipset. - block, err := newEthBlockFromFilecoinTipSet(ctx, ts, false, a.Chain, a.ChainAPI, a.StateAPI) + block, err := newEthBlockFromFilecoinTipSet(ctx, ts, false, a.Chain, a.StateAPI) if err != nil { return ethtypes.EthFeeHistory{}, fmt.Errorf("cannot create eth block: %v", err) } @@ -640,7 +642,7 @@ func (a *EthModule) EthFeeHistory(ctx context.Context, blkCount ethtypes.EthUint } return ethtypes.EthFeeHistory{ - OldestBlock: oldestBlkHeight, + OldestBlock: ethtypes.EthUint64(oldestBlkHeight), BaseFeePerGas: baseFeeArray, GasUsedRatio: gasUsedRatioArray, }, nil @@ -699,13 +701,6 @@ func (a *EthModule) EthSendRawTransaction(ctx context.Context, rawTx ethtypes.Et return ethtypes.EmptyEthHash, err } - _, err = a.StateAPI.StateGetActor(ctx, smsg.Message.To, types.EmptyTSK) - if err != nil { - // if actor does not exist on chain yet, set the method to 0 because - // placeholders only implement method 0 - smsg.Message.Method = builtinactors.MethodSend - } - _, err = a.MpoolAPI.MpoolPush(ctx, smsg) if err != nil { return ethtypes.EmptyEthHash, err @@ -714,6 +709,10 @@ func (a *EthModule) EthSendRawTransaction(ctx context.Context, rawTx ethtypes.Et return ethtypes.EthHashFromTxBytes(rawTx), nil } +func (a *EthModule) Web3ClientVersion(ctx context.Context) (string, error) { + return build.UserVersion(), nil +} + func (a *EthModule) ethCallToFilecoinMessage(ctx context.Context, tx ethtypes.EthCall) (*types.Message, error) { var from address.Address if tx.From == nil || *tx.From == (ethtypes.EthAddress{}) { @@ -816,19 +815,145 @@ func (a *EthModule) EthEstimateGas(ctx context.Context, tx ethtypes.EthCall) (et // gas estimation actually run. msg.GasLimit = 0 - msg, err = a.GasAPI.GasEstimateMessageGas(ctx, msg, nil, types.EmptyTSK) + ts := a.Chain.GetHeaviestTipSet() + msg, err = a.GasAPI.GasEstimateMessageGas(ctx, msg, nil, ts.Key()) if err != nil { - return ethtypes.EthUint64(0), err + return ethtypes.EthUint64(0), xerrors.Errorf("failed to estimate gas: %w", err) } - return ethtypes.EthUint64(msg.GasLimit), nil + expectedGas, err := ethGasSearch(ctx, a.Chain, a.Stmgr, a.Mpool, msg, ts) + if err != nil { + log.Errorw("expected gas", "err", err) + } + + return ethtypes.EthUint64(expectedGas), nil +} + +// gasSearch does an exponential search to find a gas value to execute the +// message with. It first finds a high gas limit that allows the message to execute +// by doubling the previous gas limit until it succeeds then does a binary +// search till it gets within a range of 1% +func gasSearch( + ctx context.Context, + smgr *stmgr.StateManager, + msgIn *types.Message, + priorMsgs []types.ChainMsg, + ts *types.TipSet, +) (int64, error) { + msg := *msgIn + + high := msg.GasLimit + low := msg.GasLimit + + canSucceed := func(limit int64) (bool, error) { + msg.GasLimit = limit + + res, err := smgr.CallWithGas(ctx, &msg, priorMsgs, ts) + if err != nil { + return false, xerrors.Errorf("CallWithGas failed: %w", err) + } + + if res.MsgRct.ExitCode.IsSuccess() { + return true, nil + } + + return false, nil + } + + for { + ok, err := canSucceed(high) + if err != nil { + return -1, xerrors.Errorf("searching for high gas limit failed: %w", err) + } + if ok { + break + } + + low = high + high = high * 2 + + if high > build.BlockGasLimit { + high = build.BlockGasLimit + break + } + } + + checkThreshold := high / 100 + for (high - low) > checkThreshold { + median := (low + high) / 2 + ok, err := canSucceed(median) + if err != nil { + return -1, xerrors.Errorf("searching for optimal gas limit failed: %w", err) + } + + if ok { + high = median + } else { + low = median + } + + checkThreshold = median / 100 + } + + return high, nil +} + +func traceContainsExitCode(et types.ExecutionTrace, ex exitcode.ExitCode) bool { + if et.MsgRct.ExitCode == ex { + return true + } + + for _, et := range et.Subcalls { + if traceContainsExitCode(et, ex) { + return true + } + } + + return false +} + +// ethGasSearch executes a message for gas estimation using the previously estimated gas. +// If the message fails due to an out of gas error then a gas search is performed. +// See gasSearch. +func ethGasSearch( + ctx context.Context, + cstore *store.ChainStore, + smgr *stmgr.StateManager, + mpool *messagepool.MessagePool, + msgIn *types.Message, + ts *types.TipSet, +) (int64, error) { + msg := *msgIn + currTs := ts + + res, priorMsgs, ts, err := gasEstimateCallWithGas(ctx, cstore, smgr, mpool, &msg, currTs) + if err != nil { + return -1, xerrors.Errorf("gas estimation failed: %w", err) + } + + if res.MsgRct.ExitCode.IsSuccess() { + return msg.GasLimit, nil + } + + if traceContainsExitCode(res.ExecutionTrace, exitcode.SysErrOutOfGas) { + ret, err := gasSearch(ctx, smgr, &msg, priorMsgs, ts) + if err != nil { + return -1, xerrors.Errorf("gas estimation search failed: %w", err) + } + + ret = int64(float64(ret) * mpool.GetConfig().GasLimitOverestimation) + return ret, nil + } + + return -1, xerrors.Errorf("message execution failed: exit %s, reason: %s", res.MsgRct.ExitCode, res.Error) } func (a *EthModule) EthCall(ctx context.Context, tx ethtypes.EthCall, blkParam string) (ethtypes.EthBytes, error) { msg, err := a.ethCallToFilecoinMessage(ctx, tx) if err != nil { - return nil, err + return nil, xerrors.Errorf("failed to convert ethcall to filecoin message: %w", err) } + ts, err := a.parseBlkParam(ctx, blkParam) if err != nil { return nil, xerrors.Errorf("cannot parse block param: %s", blkParam) @@ -836,11 +961,16 @@ func (a *EthModule) EthCall(ctx context.Context, tx ethtypes.EthCall, blkParam s invokeResult, err := a.applyMessage(ctx, msg, ts.Key()) if err != nil { - return nil, err + return nil, xerrors.Errorf("failed to apply message: %w", err) } - if len(invokeResult.MsgRct.Return) > 0 { + + if msg.To == builtintypes.EthereumAddressManagerActorAddr { + // As far as I can tell, the Eth API always returns empty on contract deployment + return ethtypes.EthBytes{}, nil + } else if len(invokeResult.MsgRct.Return) > 0 { return cbg.ReadByteArray(bytes.NewReader(invokeResult.MsgRct.Return), uint64(len(invokeResult.MsgRct.Return))) } + return ethtypes.EthBytes{}, nil } @@ -980,17 +1110,9 @@ func (e *EthEvent) installEthFilterSpec(ctx context.Context, filterSpec *ethtype addresses = append(addresses, a) } - for idx, vals := range filterSpec.Topics { - if len(vals) == 0 { - continue - } - // Ethereum topics are emitted using `LOG{0..4}` opcodes resulting in topics1..4 - key := fmt.Sprintf("topic%d", idx+1) - for _, v := range vals { - buf := make([]byte, len(v[:])) - copy(buf, v[:]) - keys[key] = append(keys[key], buf) - } + keys, err := parseEthTopics(filterSpec.Topics) + if err != nil { + return nil, err } return e.EventFilterManager.Install(ctx, minHeight, maxHeight, tipsetCid, addresses, keys) @@ -1015,7 +1137,6 @@ func (e *EthEvent) EthNewFilter(ctx context.Context, filterSpec *ethtypes.EthFil return ethtypes.EthFilterID{}, err } - return ethtypes.EthFilterID(f.ID()), nil } @@ -1114,54 +1235,71 @@ const ( EthSubscribeEventTypeLogs = "logs" ) -func (e *EthEvent) EthSubscribe(ctx context.Context, eventType string, params *ethtypes.EthSubscriptionParams) (<-chan ethtypes.EthSubscriptionResponse, error) { - if e.SubManager == nil { - return nil, api.ErrNotSupported - } - // Note that go-jsonrpc will set the method field of the response to "xrpc.ch.val" but the ethereum api expects the name of the - // method to be "eth_subscription". This probably doesn't matter in practice. - - sub, err := e.SubManager.StartSubscription(ctx) +func (e *EthEvent) EthSubscribe(ctx context.Context, p jsonrpc.RawParams) (ethtypes.EthSubscriptionID, error) { + params, err := jsonrpc.DecodeParams[ethtypes.EthSubscribeParams](p) if err != nil { - return nil, err + return ethtypes.EthSubscriptionID{}, xerrors.Errorf("decoding params: %w", err) } - switch eventType { + if e.SubManager == nil { + return ethtypes.EthSubscriptionID{}, api.ErrNotSupported + } + + ethCb, ok := jsonrpc.ExtractReverseClient[api.EthSubscriberMethods](ctx) + if !ok { + return ethtypes.EthSubscriptionID{}, xerrors.Errorf("connection doesn't support callbacks") + } + + sub, err := e.SubManager.StartSubscription(e.SubscribtionCtx, ethCb.EthSubscription) + if err != nil { + return ethtypes.EthSubscriptionID{}, err + } + + switch params.EventType { case EthSubscribeEventTypeHeads: f, err := e.TipSetFilterManager.Install(ctx) if err != nil { // clean up any previous filters added and stop the sub _, _ = e.EthUnsubscribe(ctx, sub.id) - return nil, err + return ethtypes.EthSubscriptionID{}, err } sub.addFilter(ctx, f) case EthSubscribeEventTypeLogs: keys := map[string][][]byte{} - if params != nil { - for idx, vals := range params.Topics { - // Ethereum topics are emitted using `LOG{0..4}` opcodes resulting in topics1..4 - key := fmt.Sprintf("topic%d", idx+1) - keyvals := make([][]byte, len(vals)) - for i, v := range vals { - keyvals[i] = v[:] - } - keys[key] = keyvals + if params.Params != nil { + var err error + keys, err = parseEthTopics(params.Params.Topics) + if err != nil { + // clean up any previous filters added and stop the sub + _, _ = e.EthUnsubscribe(ctx, sub.id) + return ethtypes.EthSubscriptionID{}, err } } - f, err := e.EventFilterManager.Install(ctx, -1, -1, cid.Undef, []address.Address{}, keys) + var addresses []address.Address + if params.Params != nil { + for _, ea := range params.Params.Address { + a, err := ea.ToFilecoinAddress() + if err != nil { + return ethtypes.EthSubscriptionID{}, xerrors.Errorf("invalid address %x", ea) + } + addresses = append(addresses, a) + } + } + + f, err := e.EventFilterManager.Install(ctx, -1, -1, cid.Undef, addresses, keys) if err != nil { // clean up any previous filters added and stop the sub _, _ = e.EthUnsubscribe(ctx, sub.id) - return nil, err + return ethtypes.EthSubscriptionID{}, err } sub.addFilter(ctx, f) default: - return nil, xerrors.Errorf("unsupported event type: %s", eventType) + return ethtypes.EthSubscriptionID{}, xerrors.Errorf("unsupported event type: %s", params.EventType) } - return sub.out, nil + return sub.id, nil } func (e *EthEvent) EthUnsubscribe(ctx context.Context, id ethtypes.EthSubscriptionID) (bool, error) { @@ -1233,11 +1371,14 @@ func ethFilterResultFromEvents(evs []*filter.CollectedEvent, sa StateAPI) (*etht var err error for _, entry := range ev.Entries { - value := ethtypes.EthBytes(leftpad32(entry.Value)) // value has already been cbor-decoded but see https://github.com/filecoin-project/ref-fvm/issues/1345 + // Skip all events that aren't "raw" data. + if entry.Codec != cid.Raw { + continue + } if entry.Key == ethtypes.EthTopic1 || entry.Key == ethtypes.EthTopic2 || entry.Key == ethtypes.EthTopic3 || entry.Key == ethtypes.EthTopic4 { - log.Topics = append(log.Topics, value) + log.Topics = append(log.Topics, entry.Value) } else { - log.Data = value + log.Data = entry.Value } } @@ -1246,7 +1387,7 @@ func ethFilterResultFromEvents(evs []*filter.CollectedEvent, sa StateAPI) (*etht return nil, err } - log.TransactionHash, err = EthTxHashFromFilecoinMessageCid(context.TODO(), ev.MsgCid, sa) + log.TransactionHash, err = EthTxHashFromMessageCid(context.TODO(), ev.MsgCid, sa) if err != nil { return nil, err } @@ -1288,7 +1429,7 @@ func ethFilterResultFromMessages(cs []*types.SignedMessage, sa StateAPI) (*ethty res := ðtypes.EthFilterResult{} for _, c := range cs { - hash, err := EthTxHashFromSignedFilecoinMessage(context.TODO(), c, sa) + hash, err := EthTxHashFromSignedMessage(context.TODO(), c, sa) if err != nil { return nil, err } @@ -1307,7 +1448,7 @@ type EthSubscriptionManager struct { subs map[ethtypes.EthSubscriptionID]*ethSubscription } -func (e *EthSubscriptionManager) StartSubscription(ctx context.Context) (*ethSubscription, error) { // nolint +func (e *EthSubscriptionManager) StartSubscription(ctx context.Context, out ethSubscriptionCallback) (*ethSubscription, error) { // nolint rawid, err := uuid.NewRandom() if err != nil { return nil, xerrors.Errorf("new uuid: %w", err) @@ -1323,7 +1464,7 @@ func (e *EthSubscriptionManager) StartSubscription(ctx context.Context) (*ethSub ChainAPI: e.ChainAPI, id: id, in: make(chan interface{}, 200), - out: make(chan ethtypes.EthSubscriptionResponse, 20), + out: out, quit: quit, } @@ -1353,13 +1494,15 @@ func (e *EthSubscriptionManager) StopSubscription(ctx context.Context, id ethtyp return sub.filters, nil } +type ethSubscriptionCallback func(context.Context, jsonrpc.RawParams) error + type ethSubscription struct { Chain *store.ChainStore StateAPI StateAPI ChainAPI ChainAPI id ethtypes.EthSubscriptionID in chan interface{} - out chan ethtypes.EthSubscriptionResponse + out ethSubscriptionCallback mu sync.Mutex filters []filter.Filter @@ -1374,40 +1517,50 @@ func (e *ethSubscription) addFilter(ctx context.Context, f filter.Filter) { e.filters = append(e.filters, f) } +func (e *ethSubscription) send(ctx context.Context, v interface{}) { + resp := ethtypes.EthSubscriptionResponse{ + SubscriptionID: e.id, + Result: v, + } + + outParam, err := json.Marshal(resp) + if err != nil { + log.Warnw("marshaling subscription response", "sub", e.id, "error", err) + return + } + + if err := e.out(ctx, outParam); err != nil { + log.Warnw("sending subscription response", "sub", e.id, "error", err) + return + } +} + func (e *ethSubscription) start(ctx context.Context) { for { select { case <-ctx.Done(): return case v := <-e.in: - resp := ethtypes.EthSubscriptionResponse{ - SubscriptionID: e.id, - } - - var err error switch vt := v.(type) { case *filter.CollectedEvent: - resp.Result, err = ethFilterResultFromEvents([]*filter.CollectedEvent{vt}, e.StateAPI) + evs, err := ethFilterResultFromEvents([]*filter.CollectedEvent{vt}, e.StateAPI) + if err != nil { + continue + } + + for _, r := range evs.Results { + e.send(ctx, r) + } case *types.TipSet: - eb, err := newEthBlockFromFilecoinTipSet(ctx, vt, true, e.Chain, e.ChainAPI, e.StateAPI) + ev, err := newEthBlockFromFilecoinTipSet(ctx, vt, true, e.Chain, e.StateAPI) if err != nil { break } - resp.Result = eb + e.send(ctx, ev) default: log.Warnf("unexpected subscription value type: %T", vt) } - - if err != nil { - continue - } - - select { - case e.out <- resp: - default: - // Skip if client is not reading responses - } } } } @@ -1418,12 +1571,11 @@ func (e *ethSubscription) stop() { if e.quit != nil { e.quit() - close(e.out) e.quit = nil } } -func newEthBlockFromFilecoinTipSet(ctx context.Context, ts *types.TipSet, fullTxInfo bool, cs *store.ChainStore, ca ChainAPI, sa StateAPI) (ethtypes.EthBlock, error) { +func newEthBlockFromFilecoinTipSet(ctx context.Context, ts *types.TipSet, fullTxInfo bool, cs *store.ChainStore, sa StateAPI) (ethtypes.EthBlock, error) { parent, err := cs.LoadTipSet(ctx, ts.Parents()) if err != nil { return ethtypes.EthBlock{}, err @@ -1451,7 +1603,7 @@ func newEthBlockFromFilecoinTipSet(ctx context.Context, ts *types.TipSet, fullTx return ethtypes.EthBlock{}, xerrors.Errorf("error loading messages for tipset: %v: %w", ts, err) } - block := ethtypes.NewEthBlock() + block := ethtypes.NewEthBlock(len(msgs) > 0) // this seems to be a very expensive way to get gasUsed of the block. may need to find an efficient way to do it gasUsed := int64(0) @@ -1462,7 +1614,7 @@ func newEthBlockFromFilecoinTipSet(ctx context.Context, ts *types.TipSet, fullTx } gasUsed += msgLookup.Receipt.GasUsed - tx, err := newEthTxFromFilecoinMessageLookup(ctx, msgLookup, txIdx, cs, sa) + tx, err := newEthTxFromMessageLookup(ctx, msgLookup, txIdx, cs, sa) if err != nil { return ethtypes.EthBlock{}, nil } @@ -1522,11 +1674,11 @@ func lookupEthAddress(ctx context.Context, addr address.Address, sa StateAPI) (e return ethtypes.EthAddressFromFilecoinAddress(idAddr) } -func EthTxHashFromFilecoinMessageCid(ctx context.Context, c cid.Cid, sa StateAPI) (ethtypes.EthHash, error) { +func EthTxHashFromMessageCid(ctx context.Context, c cid.Cid, sa StateAPI) (ethtypes.EthHash, error) { smsg, err := sa.Chain.GetSignedMessage(ctx, c) if err == nil { // This is an Eth Tx, Secp message, Or BLS message in the mpool - return EthTxHashFromSignedFilecoinMessage(ctx, smsg, sa) + return EthTxHashFromSignedMessage(ctx, smsg, sa) } _, err = sa.Chain.GetMessage(ctx, c) @@ -1538,93 +1690,51 @@ func EthTxHashFromFilecoinMessageCid(ctx context.Context, c cid.Cid, sa StateAPI return ethtypes.EmptyEthHash, nil } -func EthTxHashFromSignedFilecoinMessage(ctx context.Context, smsg *types.SignedMessage, sa StateAPI) (ethtypes.EthHash, error) { +func EthTxHashFromSignedMessage(ctx context.Context, smsg *types.SignedMessage, sa StateAPI) (ethtypes.EthHash, error) { if smsg.Signature.Type == crypto.SigTypeDelegated { - ethTx, err := NewEthTxFromFilecoinMessage(ctx, smsg, sa) + ethTx, err := newEthTxFromSignedMessage(ctx, smsg, sa) if err != nil { return ethtypes.EmptyEthHash, err } return ethTx.Hash, nil + } else if smsg.Signature.Type == crypto.SigTypeSecp256k1 { + return ethtypes.EthHashFromCid(smsg.Cid()) + } else { // BLS message + return ethtypes.EthHashFromCid(smsg.Message.Cid()) } - - return ethtypes.EthHashFromCid(smsg.Cid()) } -func NewEthTxFromFilecoinMessage(ctx context.Context, smsg *types.SignedMessage, sa StateAPI) (ethtypes.EthTx, error) { - // Ignore errors here so we can still parse non-eth messages - fromEthAddr, _ := lookupEthAddress(ctx, smsg.Message.From, sa) - toEthAddr, _ := lookupEthAddress(ctx, smsg.Message.To, sa) - - toAddr := &toEthAddr - input := smsg.Message.Params +func newEthTxFromSignedMessage(ctx context.Context, smsg *types.SignedMessage, sa StateAPI) (ethtypes.EthTx, error) { + var tx ethtypes.EthTx var err error - // Check to see if we need to decode as contract deployment. - // We don't need to resolve the to address, because there's only one form (an ID). - if smsg.Message.To == builtintypes.EthereumAddressManagerActorAddr { - switch smsg.Message.Method { - case builtintypes.MethodsEAM.Create: - toAddr = nil - var params eam.CreateParams - err = params.UnmarshalCBOR(bytes.NewReader(smsg.Message.Params)) - input = params.Initcode - case builtintypes.MethodsEAM.Create2: - toAddr = nil - var params eam.Create2Params - err = params.UnmarshalCBOR(bytes.NewReader(smsg.Message.Params)) - input = params.Initcode - case builtintypes.MethodsEAM.CreateExternal: - toAddr = nil - var params abi.CborBytes - err = params.UnmarshalCBOR(bytes.NewReader(smsg.Message.Params)) - input = []byte(params) - } - if err != nil { - return ethtypes.EthTx{}, err - } - } - // Otherwise, try to decode as a cbor byte array. - // TODO: Actually check if this is an ethereum call. This code will work for demo purposes, but is not correct. - if toAddr != nil { - if decodedParams, err := cbg.ReadByteArray(bytes.NewReader(smsg.Message.Params), uint64(len(smsg.Message.Params))); err == nil { - input = decodedParams - } - } - - r, s, v, err := ethtypes.RecoverSignature(smsg.Signature) - if err != nil { - // we don't want to return error if the message is not an Eth tx - r, s, v = ethtypes.EthBigIntZero, ethtypes.EthBigIntZero, ethtypes.EthBigIntZero - } - - tx := ethtypes.EthTx{ - Nonce: ethtypes.EthUint64(smsg.Message.Nonce), - ChainID: ethtypes.EthUint64(build.Eip155ChainId), - From: fromEthAddr, - To: toAddr, - Value: ethtypes.EthBigInt(smsg.Message.Value), - Type: ethtypes.EthUint64(2), - Input: input, - Gas: ethtypes.EthUint64(smsg.Message.GasLimit), - MaxFeePerGas: ethtypes.EthBigInt(smsg.Message.GasFeeCap), - MaxPriorityFeePerGas: ethtypes.EthBigInt(smsg.Message.GasPremium), - V: v, - R: r, - S: s, - } // This is an eth tx if smsg.Signature.Type == crypto.SigTypeDelegated { + tx, err = ethtypes.EthTxFromSignedEthMessage(smsg) + if err != nil { + return ethtypes.EthTx{}, xerrors.Errorf("failed to convert from signed message: %w", err) + } + tx.Hash, err = tx.TxHash() if err != nil { - return tx, err + return ethtypes.EthTx{}, xerrors.Errorf("failed to calculate hash for ethTx: %w", err) } - } else if smsg.Signature.Type == crypto.SigTypeUnknown { // BLS Filecoin message - tx.Hash, err = ethtypes.EthHashFromCid(smsg.Message.Cid()) + + fromAddr, err := lookupEthAddress(ctx, smsg.Message.From, sa) + if err != nil { + return ethtypes.EthTx{}, xerrors.Errorf("failed to resolve Ethereum address: %w", err) + } + + tx.From = fromAddr + } else if smsg.Signature.Type == crypto.SigTypeSecp256k1 { // Secp Filecoin Message + tx = ethTxFromNativeMessage(ctx, smsg.VMMessage(), sa) + tx.Hash, err = ethtypes.EthHashFromCid(smsg.Cid()) if err != nil { return tx, err } - } else { // Secp Filecoin Message - tx.Hash, err = ethtypes.EthHashFromCid(smsg.Cid()) + } else { // BLS Filecoin message + tx = ethTxFromNativeMessage(ctx, smsg.VMMessage(), sa) + tx.Hash, err = ethtypes.EthHashFromCid(smsg.Message.Cid()) if err != nil { return tx, err } @@ -1633,14 +1743,33 @@ func NewEthTxFromFilecoinMessage(ctx context.Context, smsg *types.SignedMessage, return tx, nil } -// newEthTxFromFilecoinMessageLookup creates an ethereum transaction from filecoin message lookup. If a negative txIdx is passed -// into the function, it looksup the transaction index of the message in the tipset, otherwise it uses the txIdx passed into the -// function -func newEthTxFromFilecoinMessageLookup(ctx context.Context, msgLookup *api.MsgLookup, txIdx int, cs *store.ChainStore, sa StateAPI) (ethtypes.EthTx, error) { - if msgLookup == nil { - return ethtypes.EthTx{}, fmt.Errorf("msg does not exist") +// ethTxFromNativeMessage does NOT populate: +// - BlockHash +// - BlockNumber +// - TransactionIndex +// - Hash +func ethTxFromNativeMessage(ctx context.Context, msg *types.Message, sa StateAPI) ethtypes.EthTx { + // We don't care if we error here, conversion is best effort for non-eth transactions + from, _ := lookupEthAddress(ctx, msg.From, sa) + to, _ := lookupEthAddress(ctx, msg.To, sa) + return ethtypes.EthTx{ + To: &to, + From: from, + Nonce: ethtypes.EthUint64(msg.Nonce), + ChainID: ethtypes.EthUint64(build.Eip155ChainId), + Value: ethtypes.EthBigInt(msg.Value), + Type: ethtypes.Eip1559TxType, + Gas: ethtypes.EthUint64(msg.GasLimit), + MaxFeePerGas: ethtypes.EthBigInt(msg.GasFeeCap), + MaxPriorityFeePerGas: ethtypes.EthBigInt(msg.GasPremium), + AccessList: []ethtypes.EthHash{}, } +} +// newEthTxFromMessageLookup creates an ethereum transaction from filecoin message lookup. If a negative txIdx is passed +// into the function, it looks up the transaction index of the message in the tipset, otherwise it uses the txIdx passed into the +// function +func newEthTxFromMessageLookup(ctx context.Context, msgLookup *api.MsgLookup, txIdx int, cs *store.ChainStore, sa StateAPI) (ethtypes.EthTx, error) { ts, err := cs.LoadTipSet(ctx, msgLookup.TipSet) if err != nil { return ethtypes.EthTx{}, err @@ -1689,13 +1818,13 @@ func newEthTxFromFilecoinMessageLookup(ctx context.Context, msgLookup *api.MsgLo smsg = &types.SignedMessage{ Message: *msg, Signature: crypto.Signature{ - Type: crypto.SigTypeUnknown, + Type: crypto.SigTypeBLS, Data: nil, }, } } - tx, err := NewEthTxFromFilecoinMessage(ctx, smsg, sa) + tx, err := newEthTxFromSignedMessage(ctx, smsg, sa) if err != nil { return ethtypes.EthTx{}, err } @@ -1741,16 +1870,6 @@ func newEthTxReceipt(ctx context.Context, tx ethtypes.EthTx, lookup *api.MsgLook LogsBloom: ethtypes.EmptyEthBloom[:], } - if receipt.To == nil && lookup.Receipt.ExitCode.IsSuccess() { - // Create and Create2 return the same things. - var ret eam.CreateReturn - if err := ret.UnmarshalCBOR(bytes.NewReader(lookup.Receipt.Return)); err != nil { - return api.EthTxReceipt{}, xerrors.Errorf("failed to parse contract creation result: %w", err) - } - addr := ethtypes.EthAddress(ret.EthAddress) - receipt.ContractAddress = &addr - } - if lookup.Receipt.ExitCode.IsSuccess() { receipt.Status = 1 } @@ -1758,12 +1877,25 @@ func newEthTxReceipt(ctx context.Context, tx ethtypes.EthTx, lookup *api.MsgLook receipt.Status = 0 } - if len(events) > 0 { - // TODO return a dummy non-zero bloom to signal that there are logs - // need to figure out how worth it is to populate with a real bloom - // should be feasible here since we are iterating over the logs anyway - receipt.LogsBloom[255] = 0x01 + receipt.GasUsed = ethtypes.EthUint64(lookup.Receipt.GasUsed) + // TODO: handle CumulativeGasUsed + receipt.CumulativeGasUsed = ethtypes.EmptyEthInt + + effectiveGasPrice := big.Div(replay.GasCost.TotalCost, big.NewInt(lookup.Receipt.GasUsed)) + receipt.EffectiveGasPrice = ethtypes.EthBigInt(effectiveGasPrice) + + if receipt.To == nil && lookup.Receipt.ExitCode.IsSuccess() { + // Create and Create2 return the same things. + var ret eam.CreateExternalReturn + if err := ret.UnmarshalCBOR(bytes.NewReader(lookup.Receipt.Return)); err != nil { + return api.EthTxReceipt{}, xerrors.Errorf("failed to parse contract creation result: %w", err) + } + addr := ethtypes.EthAddress(ret.EthAddress) + receipt.ContractAddress = &addr + } + + if len(events) > 0 { receipt.Logs = make([]ethtypes.EthLog, 0, len(events)) for i, evt := range events { l := ethtypes.EthLog{ @@ -1776,11 +1908,15 @@ func newEthTxReceipt(ctx context.Context, tx ethtypes.EthTx, lookup *api.MsgLook } for _, entry := range evt.Entries { - value := ethtypes.EthBytes(leftpad32(entry.Value)) // value has already been cbor-decoded but see https://github.com/filecoin-project/ref-fvm/issues/1345 + // Ignore any non-raw values/keys. + if entry.Codec != cid.Raw { + continue + } if entry.Key == ethtypes.EthTopic1 || entry.Key == ethtypes.EthTopic2 || entry.Key == ethtypes.EthTopic3 || entry.Key == ethtypes.EthTopic4 { - l.Topics = append(l.Topics, value) + ethtypes.EthBloomSet(receipt.LogsBloom, entry.Value) + l.Topics = append(l.Topics, entry.Value) } else { - l.Data = value + l.Data = entry.Value } } @@ -1794,18 +1930,11 @@ func newEthTxReceipt(ctx context.Context, tx ethtypes.EthTx, lookup *api.MsgLook return api.EthTxReceipt{}, xerrors.Errorf("failed to resolve Ethereum address: %w", err) } + ethtypes.EthBloomSet(receipt.LogsBloom, l.Address[:]) receipt.Logs = append(receipt.Logs, l) } } - receipt.GasUsed = ethtypes.EthUint64(lookup.Receipt.GasUsed) - - // TODO: handle CumulativeGasUsed - receipt.CumulativeGasUsed = ethtypes.EmptyEthInt - - effectiveGasPrice := big.Div(replay.GasCost.TotalCost, big.NewInt(lookup.Receipt.GasUsed)) - receipt.EffectiveGasPrice = ethtypes.EthBigInt(effectiveGasPrice) - return receipt, nil } @@ -1821,7 +1950,7 @@ func (m *EthTxHashManager) Apply(ctx context.Context, from, to *types.TipSet) er continue } - hash, err := EthTxHashFromSignedFilecoinMessage(ctx, smsg, m.StateAPI) + hash, err := EthTxHashFromSignedMessage(ctx, smsg, m.StateAPI) if err != nil { return err } @@ -1845,6 +1974,52 @@ func (m *EthTxHashManager) Revert(ctx context.Context, from, to *types.TipSet) e return nil } +func (m *EthTxHashManager) PopulateExistingMappings(ctx context.Context, minHeight abi.ChainEpoch) error { + if minHeight < build.UpgradeHyggeHeight { + minHeight = build.UpgradeHyggeHeight + } + + ts := m.StateAPI.Chain.GetHeaviestTipSet() + for ts.Height() > minHeight { + for _, block := range ts.Blocks() { + msgs, err := m.StateAPI.Chain.SecpkMessagesForBlock(ctx, block) + if err != nil { + // If we can't find the messages, we've either imported from snapshot or pruned the store + log.Debug("exiting message mapping population at epoch ", ts.Height()) + return nil + } + + for _, msg := range msgs { + m.ProcessSignedMessage(ctx, msg) + } + } + + var err error + ts, err = m.StateAPI.Chain.GetTipSetFromKey(ctx, ts.Parents()) + if err != nil { + return err + } + } + + return nil +} + +func (m *EthTxHashManager) ProcessSignedMessage(ctx context.Context, msg *types.SignedMessage) { + if msg.Signature.Type != crypto.SigTypeDelegated { + return + } + + ethTx, err := newEthTxFromSignedMessage(ctx, msg, m.StateAPI) + if err != nil { + log.Errorf("error converting filecoin message to eth tx: %s", err) + } + + err = m.TransactionHashLookup.UpsertHash(ethTx.Hash, msg.Cid()) + if err != nil { + log.Errorf("error inserting tx mapping to db: %s", err) + } +} + func WaitForMpoolUpdates(ctx context.Context, ch <-chan api.MpoolUpdate, manager *EthTxHashManager) { for { select { @@ -1854,19 +2029,8 @@ func WaitForMpoolUpdates(ctx context.Context, ch <-chan api.MpoolUpdate, manager if u.Type != api.MpoolAdd { continue } - if u.Message.Signature.Type != crypto.SigTypeDelegated { - continue - } - ethTx, err := NewEthTxFromFilecoinMessage(ctx, u.Message, manager.StateAPI) - if err != nil { - log.Errorf("error converting filecoin message to eth tx: %s", err) - } - - err = manager.TransactionHashLookup.UpsertHash(ethTx.Hash, u.Message.Cid()) - if err != nil { - log.Errorf("error inserting tx mapping to db: %s", err) - } + manager.ProcessSignedMessage(ctx, u.Message) } } } @@ -1887,16 +2051,18 @@ func EthTxHashGC(ctx context.Context, retentionDays int, manager *EthTxHashManag } } -// TODO we could also emit full EVM words from the EVM runtime, but not doing so -// makes the contract slightly cheaper (and saves storage bytes), at the expense -// of having to left pad in the API, which is a pretty acceptable tradeoff at -// face value. There may be other protocol implications to consider. -func leftpad32(orig []byte) []byte { - needed := 32 - len(orig) - if needed <= 0 { - return orig +func parseEthTopics(topics ethtypes.EthTopicSpec) (map[string][][]byte, error) { + keys := map[string][][]byte{} + for idx, vals := range topics { + if len(vals) == 0 { + continue + } + // Ethereum topics are emitted using `LOG{0..4}` opcodes resulting in topics1..4 + key := fmt.Sprintf("t%d", idx+1) + for _, v := range vals { + v := v // copy the ethhash to avoid repeatedly referencing the same one. + keys[key] = append(keys[key], v[:]) + } } - ret := make([]byte, 32) - copy(ret[needed:], orig) - return ret + return keys, nil } diff --git a/node/impl/full/gas.go b/node/impl/full/gas.go index 435e2c65b..c0e328bc9 100644 --- a/node/impl/full/gas.go +++ b/node/impl/full/gas.go @@ -248,22 +248,23 @@ func (m *GasModule) GasEstimateGasLimit(ctx context.Context, msgIn *types.Messag } return gasEstimateGasLimit(ctx, m.Chain, m.Stmgr, m.Mpool, msgIn, ts) } -func gasEstimateGasLimit( + +// gasEstimateCallWithGas invokes a message "msgIn" on the earliest available tipset with pending +// messages in the message pool. The function returns the result of the message invocation, the +// pending messages, the tipset used for the invocation, and an error if occurred. +// The returned information can be used to make subsequent calls to CallWithGas with the same parameters. +func gasEstimateCallWithGas( ctx context.Context, cstore *store.ChainStore, smgr *stmgr.StateManager, mpool *messagepool.MessagePool, msgIn *types.Message, currTs *types.TipSet, -) (int64, error) { +) (*api.InvocResult, []types.ChainMsg, *types.TipSet, error) { msg := *msgIn - msg.GasLimit = build.BlockGasLimit - msg.GasFeeCap = big.Zero() - msg.GasPremium = big.Zero() - fromA, err := smgr.ResolveToDeterministicAddress(ctx, msgIn.From, currTs) if err != nil { - return -1, xerrors.Errorf("getting key address: %w", err) + return nil, []types.ChainMsg{}, nil, xerrors.Errorf("getting key address: %w", err) } pending, ts := mpool.PendingFor(ctx, fromA) @@ -284,12 +285,34 @@ func gasEstimateGasLimit( } ts, err = cstore.GetTipSetFromKey(ctx, ts.Parents()) if err != nil { - return -1, xerrors.Errorf("getting parent tipset: %w", err) + return nil, []types.ChainMsg{}, nil, xerrors.Errorf("getting parent tipset: %w", err) } } if err != nil { - return -1, xerrors.Errorf("CallWithGas failed: %w", err) + return nil, []types.ChainMsg{}, nil, xerrors.Errorf("CallWithGas failed: %w", err) } + + return res, priorMsgs, ts, nil +} + +func gasEstimateGasLimit( + ctx context.Context, + cstore *store.ChainStore, + smgr *stmgr.StateManager, + mpool *messagepool.MessagePool, + msgIn *types.Message, + currTs *types.TipSet, +) (int64, error) { + msg := *msgIn + msg.GasLimit = build.BlockGasLimit + msg.GasFeeCap = big.Zero() + msg.GasPremium = big.Zero() + + res, _, ts, err := gasEstimateCallWithGas(ctx, cstore, smgr, mpool, &msg, currTs) + if err != nil { + return -1, xerrors.Errorf("gas estimation failed: %w", err) + } + if res.MsgRct.ExitCode == exitcode.SysErrOutOfGas { return -1, &api.ErrOutOfGas{} } @@ -300,6 +323,8 @@ func gasEstimateGasLimit( ret := res.MsgRct.GasUsed + log.Infow("GasEstimateMessageGas CallWithGas Result", "GasUsed", ret, "ExitCode", res.MsgRct.ExitCode) + transitionalMulti := 1.0 // Overestimate gas around the upgrade if ts.Height() <= build.UpgradeSkyrHeight && (build.UpgradeSkyrHeight-ts.Height() <= 20) { diff --git a/node/modules/actorevent.go b/node/modules/actorevent.go index eb5afb8e6..55a79a59a 100644 --- a/node/modules/actorevent.go +++ b/node/modules/actorevent.go @@ -40,6 +40,7 @@ func EthEventAPI(cfg config.FevmConfig) func(helpers.MetricsCtx, repo.LockedRepo ee := &full.EthEvent{ Chain: cs, MaxFilterHeightRange: abi.ChainEpoch(cfg.Events.MaxFilterHeightRange), + SubscribtionCtx: ctx, } if !cfg.EnableEthRPC || cfg.Events.DisableRealTimeFilterAPI { diff --git a/node/modules/chain.go b/node/modules/chain.go index 49418d883..6129f0345 100644 --- a/node/modules/chain.go +++ b/node/modules/chain.go @@ -181,3 +181,7 @@ func NewSlashFilter(ds dtypes.MetadataDS) *slashfilter.SlashFilter { func UpgradeSchedule() stmgr.UpgradeSchedule { return filcns.DefaultUpgradeSchedule() } + +func EnableStoringEvents(cs *store.ChainStore) { + cs.StoreEvents(true) +} diff --git a/node/modules/ethmodule.go b/node/modules/ethmodule.go index 9889233f4..eba6c54d1 100644 --- a/node/modules/ethmodule.go +++ b/node/modules/ethmodule.go @@ -2,6 +2,7 @@ package modules import ( "context" + "os" "path/filepath" "go.uber.org/fx" @@ -24,7 +25,13 @@ func EthModuleAPI(cfg config.FevmConfig) func(helpers.MetricsCtx, repo.LockedRep return nil, err } - transactionHashLookup, err := ethhashlookup.NewTransactionHashLookup(filepath.Join(sqlitePath, "txhash.db")) + dbPath := filepath.Join(sqlitePath, "txhash.db") + + // Check if the db exists, if not, we'll back-fill some entries + _, err = os.Stat(dbPath) + dbAlreadyExists := err == nil + + transactionHashLookup, err := ethhashlookup.NewTransactionHashLookup(dbPath) if err != nil { return nil, err } @@ -40,6 +47,13 @@ func EthModuleAPI(cfg config.FevmConfig) func(helpers.MetricsCtx, repo.LockedRep TransactionHashLookup: transactionHashLookup, } + if !dbAlreadyExists { + err = ethTxHashManager.PopulateExistingMappings(mctx, 0) + if err != nil { + return nil, err + } + } + const ChainHeadConfidence = 1 ctx := helpers.LifecycleCtx(mctx, lc) diff --git a/node/rpc.go b/node/rpc.go index a96e6e3ac..cacd33526 100644 --- a/node/rpc.go +++ b/node/rpc.go @@ -75,7 +75,7 @@ func FullNodeHandler(a v1api.FullNode, permissioned bool, opts ...jsonrpc.Server m := mux.NewRouter() serveRpc := func(path string, hnd interface{}) { - rpcServer := jsonrpc.NewServer(append(opts, jsonrpc.WithServerErrors(api.RPCErrors))...) + rpcServer := jsonrpc.NewServer(append(opts, jsonrpc.WithReverseClient[api.EthSubscriberMethods]("Filecoin"), jsonrpc.WithServerErrors(api.RPCErrors))...) rpcServer.Register("Filecoin", hnd) rpcServer.AliasMethod("rpc.discover", "Filecoin.Discover") @@ -94,8 +94,9 @@ func FullNodeHandler(a v1api.FullNode, permissioned bool, opts ...jsonrpc.Server fnapi = api.PermissionedFullAPI(fnapi) } + var v0 v0api.FullNode = &(struct{ v0api.FullNode }{&v0api.WrapperV1Full{FullNode: fnapi}}) serveRpc("/rpc/v1", fnapi) - serveRpc("/rpc/v0", &v0api.WrapperV1Full{FullNode: fnapi}) + serveRpc("/rpc/v0", v0) // Import handler handleImportFunc := handleImport(a.(*impl.FullNodeAPI)) diff --git a/scripts/build-appimage-bundle.sh b/scripts/build-appimage-bundle.sh deleted file mode 100755 index d4ce6de77..000000000 --- a/scripts/build-appimage-bundle.sh +++ /dev/null @@ -1,26 +0,0 @@ -#!/usr/bin/env bash -set -ex - -REQUIRED=( - "ipfs" - "sha512sum" -) -for REQUIRE in "${REQUIRED[@]}" -do - command -v "${REQUIRE}" >/dev/null 2>&1 || echo >&2 "'${REQUIRE}' must be installed" -done - -mkdir bundle -pushd bundle - -export IPFS_PATH=`mktemp -d` -ipfs init -ipfs daemon & -PID="$!" -trap "kill -9 ${PID}" EXIT -sleep 30 - -cp "/tmp/workspace/appimage/Lotus-${CIRCLE_TAG}-x86_64.AppImage" . -sha512sum "Lotus-${CIRCLE_TAG}-x86_64.AppImage" > "Lotus-${CIRCLE_TAG}-x86_64.AppImage.sha512" -ipfs add -q "Lotus-${CIRCLE_TAG}-x86_64.AppImage" > "Lotus-${CIRCLE_TAG}-x86_64.AppImage.cid" -popd diff --git a/scripts/build-arch-bundle.sh b/scripts/build-arch-bundle.sh deleted file mode 100755 index 27b4218f5..000000000 --- a/scripts/build-arch-bundle.sh +++ /dev/null @@ -1,46 +0,0 @@ -#!/usr/bin/env bash -set -ex - -ARCH=$1 - -REQUIRED=( - "ipfs" - "sha512sum" -) -for REQUIRE in "${REQUIRED[@]}" -do - command -v "${REQUIRE}" >/dev/null 2>&1 || echo >&2 "'${REQUIRE}' must be installed" -done - -mkdir bundle -pushd bundle - -BINARIES=( - "lotus" - "lotus-miner" - "lotus-worker" -) - -export IPFS_PATH=`mktemp -d` -ipfs init -ipfs daemon & -PID="$!" -trap "kill -9 ${PID}" EXIT -sleep 30 - -mkdir -p "${ARCH}/lotus" -pushd "${ARCH}" -for BINARY in "${BINARIES[@]}" -do - cp "../../${ARCH}/${BINARY}" "lotus/" - chmod +x "lotus/${BINARY}" -done - -tar -zcvf "../lotus_${CIRCLE_TAG}_${ARCH}-amd64.tar.gz" lotus -popd -rm -rf "${ARCH}" - -sha512sum "lotus_${CIRCLE_TAG}_${ARCH}-amd64.tar.gz" > "lotus_${CIRCLE_TAG}_${ARCH}-amd64.tar.gz.sha512" - -ipfs add -q "lotus_${CIRCLE_TAG}_${ARCH}-amd64.tar.gz" > "lotus_${CIRCLE_TAG}_${ARCH}-amd64.tar.gz.cid" -popd diff --git a/scripts/docker-git-state-check.sh b/scripts/docker-git-state-check.sh new file mode 100755 index 000000000..6075ebf84 --- /dev/null +++ b/scripts/docker-git-state-check.sh @@ -0,0 +1,12 @@ +set -e + +if [ -z "$(git status --porcelain)" ]; then + echo "PASSED: Working directory clean" +else + echo "FAILED: Working directory not clean." + echo "This is likely because the .dockerignore file has removed something checked into git." + echo "Add the missing files listed below to the .dockerignore to fix this issue:" + echo "$(git status)" + exit 1 +fi + diff --git a/scripts/publish-arch-release.sh b/scripts/publish-arch-release.sh deleted file mode 100755 index b47ad53fe..000000000 --- a/scripts/publish-arch-release.sh +++ /dev/null @@ -1,121 +0,0 @@ -#!/usr/bin/env bash -set -e - -ARCH=$1 - -pushd bundle - -# make sure we have a token set, api requests won't work otherwise -if [ -z "${GITHUB_TOKEN}" ]; then - echo "\${GITHUB_TOKEN} not set, publish failed" - exit 1 -fi - -REQUIRED=( - "jq" - "curl" -) -for REQUIRE in "${REQUIRED[@]}" -do - command -v "${REQUIRE}" >/dev/null 2>&1 || echo >&2 "'${REQUIRE}' must be installed" -done - -#see if the release already exists by tag -RELEASE_RESPONSE=` - curl \ - --header "Authorization: token ${GITHUB_TOKEN}" \ - "https://api.github.com/repos/${CIRCLE_PROJECT_USERNAME}/${CIRCLE_PROJECT_REPONAME}/releases/tags/${CIRCLE_TAG}" -` -RELEASE_ID=`echo "${RELEASE_RESPONSE}" | jq '.id'` - -if [ "${RELEASE_ID}" = "null" ]; then - echo "creating release" - - COND_CREATE_DISCUSSION="" - PRERELEASE=true - if [[ ${CIRCLE_TAG} =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then - COND_CREATE_DISCUSSION="\"discussion_category_name\": \"announcement\"," - PRERELEASE=false - fi - - RELEASE_DATA="{ - \"tag_name\": \"${CIRCLE_TAG}\", - \"target_commitish\": \"${CIRCLE_SHA1}\", - ${COND_CREATE_DISCUSSION} - \"name\": \"${CIRCLE_TAG}\", - \"body\": \"\", - \"prerelease\": ${PRERELEASE} - }" - - # create it if it doesn't exist yet - RELEASE_RESPONSE=` - curl \ - --request POST \ - --header "Authorization: token ${GITHUB_TOKEN}" \ - --header "Content-Type: application/json" \ - --data "${RELEASE_DATA}" \ - "https://api.github.com/repos/$CIRCLE_PROJECT_USERNAME/${CIRCLE_PROJECT_REPONAME}/releases" - ` -else - echo "release already exists" -fi - -RELEASE_UPLOAD_URL=`echo "${RELEASE_RESPONSE}" | jq -r '.upload_url' | cut -d'{' -f1` -echo "Preparing to send artifacts to ${RELEASE_UPLOAD_URL}" - -if [ $ARCH = 'linux' ]; then -artifacts=( - "lotus_${CIRCLE_TAG}_linux-amd64.tar.gz" - "lotus_${CIRCLE_TAG}_linux-amd64.tar.gz.cid" - "lotus_${CIRCLE_TAG}_linux-amd64.tar.gz.sha512" -) -elif [ $ARCH = 'darwin' ]; then -artifacts=( - "lotus_${CIRCLE_TAG}_darwin-amd64.tar.gz" - "lotus_${CIRCLE_TAG}_darwin-amd64.tar.gz.cid" - "lotus_${CIRCLE_TAG}_darwin-amd64.tar.gz.sha512" -) -elif [ $ARCH = 'appimage' ]; then -artifacts=( - "Lotus-${CIRCLE_TAG}-x86_64.AppImage" - "Lotus-${CIRCLE_TAG}-x86_64.AppImage.cid" - "Lotus-${CIRCLE_TAG}-x86_64.AppImage.sha512" -) -else - echo "$1 is not a supported architecture to publish a release for" 1>&2 - exit 1 -fi - -for RELEASE_FILE in "${artifacts[@]}" -do - echo "Uploading ${RELEASE_FILE}..." - curl \ - --request POST \ - --fail \ - --header "Authorization: token ${GITHUB_TOKEN}" \ - --header "Content-Type: application/octet-stream" \ - --data-binary "@${RELEASE_FILE}" \ - "$RELEASE_UPLOAD_URL?name=$(basename "${RELEASE_FILE}")" - - echo "Uploaded ${RELEASE_FILE}" -done - -popd - -miscellaneous=( - "README.md" - "LICENSE-MIT" - "LICENSE-APACHE" -) -for MISC in "${miscellaneous[@]}" -do - echo "Uploading release bundle: ${MISC}" - curl \ - --request POST \ - --header "Authorization: token ${GITHUB_TOKEN}" \ - --header "Content-Type: application/octet-stream" \ - --data-binary "@${MISC}" \ - "$RELEASE_UPLOAD_URL?name=$(basename "${MISC}")" - - echo "Release bundle uploaded: ${MISC}" -done diff --git a/snap/local/icon.svg b/snap/local/icon.svg deleted file mode 100644 index da992296a..000000000 --- a/snap/local/icon.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml deleted file mode 100644 index 8c7323a2b..000000000 --- a/snap/snapcraft.yaml +++ /dev/null @@ -1,96 +0,0 @@ -name: lotus-filecoin -base: core20 -version: latest -summary: filecoin daemon/client -icon: snap/local/icon.svg -description: | - Filecoin is a peer-to-peer network that stores files on the internet - with built-in economic incentives to ensure files are stored reliably over time - - For documentation and additional information, please see the following resources - - https://filecoin.io - - https://fil.org - - https://lotus.filecoin.io - - https://github.com/filecoin-project/lotus - -confinement: strict - -parts: - lotus: - plugin: make - source: ./ - build-snaps: - - go - - rustup - build-packages: - - git - - jq - - libhwloc-dev - - ocl-icd-opencl-dev - - pkg-config - stage-packages: - - libhwloc15 - - ocl-icd-libopencl1 - override-build: | - LDFLAGS="" make lotus lotus-miner lotus-worker - cp lotus lotus-miner lotus-worker $SNAPCRAFT_PART_INSTALL - cp scripts/snap-lotus-entrypoint.sh $SNAPCRAFT_PART_INSTALL - -layout: - /var/lib/lotus: - symlink: $SNAP_COMMON/lotus - /var/lib/lotus-miner: - symlink: $SNAP_COMMON/lotus-miner - /var/lib/lotus-worker: - symlink: $SNAP_COMMON/lotus-worker - -apps: - lotus: - command: lotus - plugs: - - network - - network-bind - - home - environment: - FIL_PROOFS_PARAMETER_CACHE: $SNAP_USER_COMMON/filecoin-proof-parameters - LOTUS_PATH: $SNAP_COMMON/lotus - LOTUS_MINER_PATH: $SNAP_COMMON/lotus-miner - LOTUS_WORKER_PATH: $SNAP_COMMON/lotus-worker - lotus-miner: - command: lotus-miner - plugs: - - network - - network-bind - - opengl - environment: - FIL_PROOFS_PARAMETER_CACHE: $SNAP_USER_COMMON/filecoin-proof-parameters - LOTUS_PATH: $SNAP_COMMON/lotus - LOTUS_MINER_PATH: $SNAP_COMMON/lotus-miner - LOTUS_WORKER_PATH: $SNAP_COMMON/lotus-worker - lotus-worker: - command: lotus-worker - plugs: - - network - - network-bind - - opengl - environment: - FIL_PROOFS_PARAMETER_CACHE: $SNAP_USER_COMMON/filecoin-proof-parameters - LOTUS_PATH: $SNAP_COMMON/lotus - LOTUS_MINER_PATH: $SNAP_COMMON/lotus-miner - LOTUS_WORKER_PATH: $SNAP_COMMON/lotus-worker - lotus-daemon: - command: snap-lotus-entrypoint.sh - daemon: simple - install-mode: disable - plugs: - - network - - network-bind - environment: - FIL_PROOFS_PARAMETER_CACHE: $SNAP_COMMON/filecoin-proof-parameters - LOTUS_PATH: $SNAP_COMMON/lotus - LOTUS_MINER_PATH: $SNAP_COMMON/lotus-miner - LOTUS_WORKER_PATH: $SNAP_COMMON/lotus-worker