diff --git a/.circleci/config.yml b/.circleci/config.yml index cb7756274..5fcb83145 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -63,7 +63,7 @@ commands: name: Install Rust command: | curl https://sh.rustup.rs -sSf | sh -s -- -y - - run: make deps lotus + - run: make deps download-params: steps: - restore_cache: @@ -304,9 +304,7 @@ jobs: darwin: true darwin-architecture: arm64 - run: | - export CPATH=$(brew --prefix)/include - export LIBRARY_PATH=$(brew --prefix)/lib - make lotus lotus-miner lotus-worker + export CPATH=$(brew --prefix)/include && export LIBRARY_PATH=$(brew --prefix)/lib && make lotus lotus-miner lotus-worker - run: otool -hv lotus - run: name: check tag and version output match @@ -812,6 +810,12 @@ workflows: - build suite: itest-mpool_push_with_uuid target: "./itests/mpool_push_with_uuid_test.go" + - test: + name: test-itest-msgindex + requires: + - build + suite: itest-msgindex + target: "./itests/msgindex_test.go" - test: name: test-itest-multisig requires: @@ -878,6 +882,12 @@ workflows: - build suite: itest-sdr_upgrade target: "./itests/sdr_upgrade_test.go" + - test: + name: test-itest-sealing_resources + requires: + - build + suite: itest-sealing_resources + target: "./itests/sealing_resources_test.go" - test: name: test-itest-sector_finalize_early requires: @@ -1063,6 +1073,7 @@ workflows: branches: only: - /^release\/v\d+\.\d+\.\d+(-rc\d+)?$/ + - /^ci\/.*$/ tags: only: - /^v\d+\.\d+\.\d+(-rc\d+)?$/ @@ -1072,6 +1083,7 @@ workflows: branches: only: - /^release\/v\d+\.\d+\.\d+(-rc\d+)?$/ + - /^ci\/.*$/ tags: only: - /^v\d+\.\d+\.\d+(-rc\d+)?$/ @@ -1081,6 +1093,7 @@ workflows: branches: only: - /^release\/v\d+\.\d+\.\d+(-rc\d+)?$/ + - /^ci\/.*$/ tags: only: - /^v\d+\.\d+\.\d+(-rc\d+)?$/ @@ -1093,7 +1106,7 @@ workflows: filters: branches: ignore: - - /.*/ + - /^.*$/ tags: only: - /^v\d+\.\d+\.\d+(-rc\d+)?$/ @@ -1108,6 +1121,7 @@ workflows: branches: only: - /^release\/v\d+\.\d+\.\d+(-rc\d+)?$/ + - /^ci\/.*$/ - build-docker: name: "Docker push (lotus-all-in-one / stable / mainnet)" image: lotus-all-in-one diff --git a/.circleci/template.yml b/.circleci/template.yml index 382965615..cd8aeb663 100644 --- a/.circleci/template.yml +++ b/.circleci/template.yml @@ -63,7 +63,7 @@ commands: name: Install Rust command: | curl https://sh.rustup.rs -sSf | sh -s -- -y - - run: make deps lotus + - run: make deps download-params: steps: - restore_cache: @@ -304,9 +304,7 @@ jobs: darwin: true darwin-architecture: arm64 - run: | - export CPATH=$(brew --prefix)/include - export LIBRARY_PATH=$(brew --prefix)/lib - make lotus lotus-miner lotus-worker + export CPATH=$(brew --prefix)/include && export LIBRARY_PATH=$(brew --prefix)/lib && make lotus lotus-miner lotus-worker - run: otool -hv lotus - run: name: check tag and version output match @@ -583,6 +581,7 @@ workflows: branches: only: - /^release\/v\d+\.\d+\.\d+(-rc\d+)?$/ + - /^ci\/.*$/ tags: only: - /^v\d+\.\d+\.\d+(-rc\d+)?$/ @@ -592,6 +591,7 @@ workflows: branches: only: - /^release\/v\d+\.\d+\.\d+(-rc\d+)?$/ + - /^ci\/.*$/ tags: only: - /^v\d+\.\d+\.\d+(-rc\d+)?$/ @@ -601,6 +601,7 @@ workflows: branches: only: - /^release\/v\d+\.\d+\.\d+(-rc\d+)?$/ + - /^ci\/.*$/ tags: only: - /^v\d+\.\d+\.\d+(-rc\d+)?$/ @@ -613,7 +614,7 @@ workflows: filters: branches: ignore: - - /.*/ + - /^.*$/ tags: only: - /^v\d+\.\d+\.\d+(-rc\d+)?$/ @@ -628,6 +629,7 @@ workflows: branches: only: - /^release\/v\d+\.\d+\.\d+(-rc\d+)?$/ + - /^ci\/.*$/ [[- range .Networks]] - build-docker: name: "Docker push (lotus-all-in-one / stable / [[.]])" diff --git a/.gitignore b/.gitignore index 2e9dcd0ff..23a0631c3 100644 --- a/.gitignore +++ b/.gitignore @@ -52,3 +52,4 @@ 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 +!extern/test-vectors diff --git a/CHANGELOG.md b/CHANGELOG.md index 650becb25..17cf7a8c7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Lotus changelog +# UNRELEASED + +## New features +- feat: Added new environment variable `LOTUS_EXEC_TRACE_CACHE_SIZE` to configure execution trace cache size ([filecoin-project/lotus#10585](https://github.com/filecoin-project/lotus/pull/10585)) + - If unset, we default to caching 16 most recent execution traces. Node operatores may want to set this to 0 while exchanges may want to crank it up. + # v1.23.0 / 2023-04-21 This is the stable feature release for the upcoming MANDATORY network upgrade at `2023-04-27T13:00:00Z`, epoch `2809800`. This feature release delivers the nv19 Lighting and nv20 Thunder network upgrade for mainnet, and includes numerous improvements and enhancements for node operators, ETH RPC-providers and storage providers. @@ -606,10 +612,6 @@ verifiedregistry bafk2bzacedej3dnr62g2je2abmyjg3xqv4otvh6e26du5fcrhvw7zgcaaez3a ### Dependencies github.com/filecoin-project/go-state-types (v0.11.0-rc1 -> v0.11.1): -<<<<<<< HEAD -======= - ->>>>>>> releases # v1.20.4 / 2023-03-17 This is a patch release intended to alleviate performance issues reported by some users since the nv18 upgrade. diff --git a/Dockerfile.lotus b/Dockerfile.lotus deleted file mode 100644 index 91373b62f..000000000 --- a/Dockerfile.lotus +++ /dev/null @@ -1,273 +0,0 @@ -##### DEPRECATED - -FROM golang:1.19.7-buster AS builder-deps -MAINTAINER Lotus Development Team - -RUN apt-get update && apt-get install -y ca-certificates build-essential clang ocl-icd-opencl-dev ocl-icd-libopencl1 jq libhwloc-dev - -ENV XDG_CACHE_HOME="/tmp" - -### taken from https://github.com/rust-lang/docker-rust/blob/master/1.63.0/buster/Dockerfile -ENV RUSTUP_HOME=/usr/local/rustup \ - CARGO_HOME=/usr/local/cargo \ - PATH=/usr/local/cargo/bin:$PATH \ - RUST_VERSION=1.63.0 - -RUN set -eux; \ - dpkgArch="$(dpkg --print-architecture)"; \ - case "${dpkgArch##*-}" in \ - amd64) rustArch='x86_64-unknown-linux-gnu'; rustupSha256='5cc9ffd1026e82e7fb2eec2121ad71f4b0f044e88bca39207b3f6b769aaa799c' ;; \ - arm64) rustArch='aarch64-unknown-linux-gnu'; rustupSha256='e189948e396d47254103a49c987e7fb0e5dd8e34b200aa4481ecc4b8e41fb929' ;; \ - *) echo >&2 "unsupported architecture: ${dpkgArch}"; exit 1 ;; \ - esac; \ - url="https://static.rust-lang.org/rustup/archive/1.25.1/${rustArch}/rustup-init"; \ - wget "$url"; \ - echo "${rustupSha256} *rustup-init" | sha256sum -c -; \ - chmod +x rustup-init; \ - ./rustup-init -y --no-modify-path --profile minimal --default-toolchain $RUST_VERSION --default-host ${rustArch}; \ - rm rustup-init; \ - chmod -R a+w $RUSTUP_HOME $CARGO_HOME; \ - rustup --version; \ - cargo --version; \ - rustc --version; -### end rust - -FROM builder-deps AS builder-local -MAINTAINER Lotus Development Team - -COPY ./ /opt/filecoin -WORKDIR /opt/filecoin - -### make configurable filecoin-ffi build -ARG FFI_BUILD_FROM_SOURCE=0 -ENV FFI_BUILD_FROM_SOURCE=${FFI_BUILD_FROM_SOURCE} - -RUN make clean deps - - -FROM builder-local AS builder-test -MAINTAINER Lotus Development Team - -WORKDIR /opt/filecoin - -RUN make debug - - -FROM builder-local AS builder -MAINTAINER Lotus Development Team - -WORKDIR /opt/filecoin - -ARG RUSTFLAGS="" -ARG GOFLAGS="" - -RUN make lotus lotus-miner lotus-worker lotus-shed lotus-wallet lotus-gateway lotus-stats - - -FROM ubuntu:20.04 AS base -MAINTAINER Lotus Development Team - -# Base resources -COPY --from=builder /etc/ssl/certs /etc/ssl/certs -COPY --from=builder /lib/*/libdl.so.2 /lib/ -COPY --from=builder /lib/*/librt.so.1 /lib/ -COPY --from=builder /lib/*/libgcc_s.so.1 /lib/ -COPY --from=builder /lib/*/libutil.so.1 /lib/ -COPY --from=builder /usr/lib/*/libltdl.so.7 /lib/ -COPY --from=builder /usr/lib/*/libnuma.so.1 /lib/ -COPY --from=builder /usr/lib/*/libhwloc.so.5 /lib/ -COPY --from=builder /usr/lib/*/libOpenCL.so.1 /lib/ - -RUN useradd -r -u 532 -U fc \ - && mkdir -p /etc/OpenCL/vendors \ - && echo "libnvidia-opencl.so.1" > /etc/OpenCL/vendors/nvidia.icd - -### -FROM base AS lotus -MAINTAINER Lotus Development Team - -COPY --from=builder /opt/filecoin/lotus /usr/local/bin/ -COPY --from=builder /opt/filecoin/lotus-shed /usr/local/bin/ -COPY scripts/docker-lotus-entrypoint.sh / - -ENV FILECOIN_PARAMETER_CACHE /var/tmp/filecoin-proof-parameters -ENV LOTUS_PATH /var/lib/lotus -ENV DOCKER_LOTUS_IMPORT_SNAPSHOT https://fil-chain-snapshots-fallback.s3.amazonaws.com/mainnet/minimal_finality_stateroots_latest.car -ENV DOCKER_LOTUS_IMPORT_WALLET "" - -RUN mkdir /var/lib/lotus /var/tmp/filecoin-proof-parameters -RUN chown fc: /var/lib/lotus /var/tmp/filecoin-proof-parameters - -VOLUME /var/lib/lotus -VOLUME /var/tmp/filecoin-proof-parameters - -USER fc - -EXPOSE 1234 - -ENTRYPOINT ["/docker-lotus-entrypoint.sh"] - -CMD ["-help"] - -### -FROM base AS lotus-wallet -MAINTAINER Lotus Development Team - -COPY --from=builder /opt/filecoin/lotus-wallet /usr/local/bin/ - -ENV WALLET_PATH /var/lib/lotus-wallet - -RUN mkdir /var/lib/lotus-wallet -RUN chown fc: /var/lib/lotus-wallet - -VOLUME /var/lib/lotus-wallet - -USER fc - -EXPOSE 1777 - -ENTRYPOINT ["/usr/local/bin/lotus-wallet"] - -CMD ["-help"] - -### -FROM base AS lotus-gateway -MAINTAINER Lotus Development Team - -COPY --from=builder /opt/filecoin/lotus-gateway /usr/local/bin/ - -USER fc - -EXPOSE 1234 - -ENTRYPOINT ["/usr/local/bin/lotus-gateway"] - -CMD ["-help"] - - -### -FROM base AS lotus-miner -MAINTAINER Lotus Development Team - -COPY --from=builder /opt/filecoin/lotus-miner /usr/local/bin/ -COPY scripts/docker-lotus-miner-entrypoint.sh / - -ENV FILECOIN_PARAMETER_CACHE /var/tmp/filecoin-proof-parameters -ENV LOTUS_MINER_PATH /var/lib/lotus-miner - -RUN mkdir /var/lib/lotus-miner /var/tmp/filecoin-proof-parameters -RUN chown fc: /var/lib/lotus-miner /var/tmp/filecoin-proof-parameters - -VOLUME /var/lib/lotus-miner -VOLUME /var/tmp/filecoin-proof-parameters - -USER fc - -EXPOSE 2345 - -ENTRYPOINT ["/docker-lotus-miner-entrypoint.sh"] - -CMD ["-help"] - - -### -FROM base AS lotus-worker -MAINTAINER Lotus Development Team - -COPY --from=builder /opt/filecoin/lotus-worker /usr/local/bin/ - -ENV FILECOIN_PARAMETER_CACHE /var/tmp/filecoin-proof-parameters -ENV LOTUS_WORKER_PATH /var/lib/lotus-worker - -RUN mkdir /var/lib/lotus-worker -RUN chown fc: /var/lib/lotus-worker - -VOLUME /var/lib/lotus-worker - -USER fc - -EXPOSE 3456 - -ENTRYPOINT ["/usr/local/bin/lotus-worker"] - -CMD ["-help"] - - -### -from base as lotus-all-in-one - -ENV FILECOIN_PARAMETER_CACHE /var/tmp/filecoin-proof-parameters -ENV LOTUS_MINER_PATH /var/lib/lotus-miner -ENV LOTUS_PATH /var/lib/lotus -ENV LOTUS_WORKER_PATH /var/lib/lotus-worker -ENV WALLET_PATH /var/lib/lotus-wallet -ENV DOCKER_LOTUS_IMPORT_SNAPSHOT https://fil-chain-snapshots-fallback.s3.amazonaws.com/mainnet/minimal_finality_stateroots_latest.car - -COPY --from=builder /opt/filecoin/lotus /usr/local/bin/ -COPY --from=builder /opt/filecoin/lotus-shed /usr/local/bin/ -COPY --from=builder /opt/filecoin/lotus-wallet /usr/local/bin/ -COPY --from=builder /opt/filecoin/lotus-gateway /usr/local/bin/ -COPY --from=builder /opt/filecoin/lotus-miner /usr/local/bin/ -COPY --from=builder /opt/filecoin/lotus-worker /usr/local/bin/ -COPY --from=builder /opt/filecoin/lotus-stats /usr/local/bin/ - -RUN mkdir /var/tmp/filecoin-proof-parameters -RUN mkdir /var/lib/lotus -RUN mkdir /var/lib/lotus-miner -RUN mkdir /var/lib/lotus-worker -RUN mkdir /var/lib/lotus-wallet -RUN chown fc: /var/tmp/filecoin-proof-parameters -RUN chown fc: /var/lib/lotus -RUN chown fc: /var/lib/lotus-miner -RUN chown fc: /var/lib/lotus-worker -RUN chown fc: /var/lib/lotus-wallet - - -VOLUME /var/tmp/filecoin-proof-parameters -VOLUME /var/lib/lotus -VOLUME /var/lib/lotus-miner -VOLUME /var/lib/lotus-worker -VOLUME /var/lib/lotus-wallet - -EXPOSE 1234 -EXPOSE 2345 -EXPOSE 3456 -EXPOSE 1777 - -### -from base as lotus-test - -ENV FILECOIN_PARAMETER_CACHE /var/tmp/filecoin-proof-parameters -ENV LOTUS_MINER_PATH /var/lib/lotus-miner -ENV LOTUS_PATH /var/lib/lotus -ENV LOTUS_WORKER_PATH /var/lib/lotus-worker -ENV WALLET_PATH /var/lib/lotus-wallet - -COPY --from=builder-test /opt/filecoin/lotus /usr/local/bin/ -COPY --from=builder-test /opt/filecoin/lotus-miner /usr/local/bin/ -COPY --from=builder-test /opt/filecoin/lotus-worker /usr/local/bin/ -COPY --from=builder-test /opt/filecoin/lotus-seed /usr/local/bin/ - -RUN mkdir /var/tmp/filecoin-proof-parameters -RUN mkdir /var/lib/lotus -RUN mkdir /var/lib/lotus-miner -RUN mkdir /var/lib/lotus-worker -RUN mkdir /var/lib/lotus-wallet -RUN chown fc: /var/tmp/filecoin-proof-parameters -RUN chown fc: /var/lib/lotus -RUN chown fc: /var/lib/lotus-miner -RUN chown fc: /var/lib/lotus-worker -RUN chown fc: /var/lib/lotus-wallet - - -VOLUME /var/tmp/filecoin-proof-parameters -VOLUME /var/lib/lotus -VOLUME /var/lib/lotus-miner -VOLUME /var/lib/lotus-worker -VOLUME /var/lib/lotus-wallet - -EXPOSE 1234 -EXPOSE 2345 -EXPOSE 3456 -EXPOSE 1777 - diff --git a/api/api_full.go b/api/api_full.go index 6ce061865..af62c3b0c 100644 --- a/api/api_full.go +++ b/api/api_full.go @@ -7,8 +7,8 @@ import ( "time" "github.com/google/uuid" + blocks "github.com/ipfs/go-block-format" "github.com/ipfs/go-cid" - blocks "github.com/ipfs/go-libipfs/blocks" "github.com/libp2p/go-libp2p/core/peer" "github.com/filecoin-project/go-address" @@ -297,8 +297,10 @@ type FullNode interface { MpoolGetNonce(context.Context, address.Address) (uint64, error) //perm:read MpoolSub(context.Context) (<-chan MpoolUpdate, error) //perm:read - // MpoolClear clears pending messages from the mpool - MpoolClear(context.Context, bool) error //perm:write + // MpoolClear clears pending messages from the mpool. + // If clearLocal is true, ALL messages will be cleared. + // If clearLocal is false, local messages will be protected, all others will be cleared. + MpoolClear(ctx context.Context, clearLocal bool) error //perm:write // MpoolGetConfig returns (a copy of) the current mpool config MpoolGetConfig(context.Context) (*types.MpoolConfig, error) //perm:read @@ -810,6 +812,7 @@ type FullNode interface { EthGetStorageAt(ctx context.Context, address ethtypes.EthAddress, position ethtypes.EthBytes, blkParam string) (ethtypes.EthBytes, error) //perm:read EthGetBalance(ctx context.Context, address ethtypes.EthAddress, blkParam string) (ethtypes.EthBigInt, error) //perm:read EthChainId(ctx context.Context) (ethtypes.EthUint64, error) //perm:read + EthSyncing(ctx context.Context) (ethtypes.EthSyncingResult, error) //perm:read NetVersion(ctx context.Context) (string, error) //perm:read NetListening(ctx context.Context) (bool, error) //perm:read EthProtocolVersion(ctx context.Context) (ethtypes.EthUint64, error) //perm:read @@ -827,23 +830,23 @@ type FullNode interface { // Polling method for a filter, returns event logs which occurred since last poll. // (requires write perm since timestamp of last filter execution will be written) - EthGetFilterChanges(ctx context.Context, id ethtypes.EthFilterID) (*ethtypes.EthFilterResult, error) //perm:write + EthGetFilterChanges(ctx context.Context, id ethtypes.EthFilterID) (*ethtypes.EthFilterResult, error) //perm:read // Returns event logs matching filter with given id. // (requires write perm since timestamp of last filter execution will be written) - EthGetFilterLogs(ctx context.Context, id ethtypes.EthFilterID) (*ethtypes.EthFilterResult, error) //perm:write + EthGetFilterLogs(ctx context.Context, id ethtypes.EthFilterID) (*ethtypes.EthFilterResult, error) //perm:read // Installs a persistent filter based on given filter spec. - EthNewFilter(ctx context.Context, filter *ethtypes.EthFilterSpec) (ethtypes.EthFilterID, error) //perm:write + EthNewFilter(ctx context.Context, filter *ethtypes.EthFilterSpec) (ethtypes.EthFilterID, error) //perm:read // Installs a persistent filter to notify when a new block arrives. - EthNewBlockFilter(ctx context.Context) (ethtypes.EthFilterID, error) //perm:write + EthNewBlockFilter(ctx context.Context) (ethtypes.EthFilterID, error) //perm:read // Installs a persistent filter to notify when new messages arrive in the message pool. - EthNewPendingTransactionFilter(ctx context.Context) (ethtypes.EthFilterID, error) //perm:write + EthNewPendingTransactionFilter(ctx context.Context) (ethtypes.EthFilterID, error) //perm:read // Uninstalls a filter with given id. - EthUninstallFilter(ctx context.Context, id ethtypes.EthFilterID) (bool, error) //perm:write + EthUninstallFilter(ctx context.Context, id ethtypes.EthFilterID) (bool, error) //perm:read // Subscribe to different event types using websockets // eventTypes is one or more of: @@ -852,10 +855,10 @@ 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, params jsonrpc.RawParams) (ethtypes.EthSubscriptionID, error) //perm:write + EthSubscribe(ctx context.Context, params jsonrpc.RawParams) (ethtypes.EthSubscriptionID, error) //perm:read // Unsubscribe from a websocket subscription - EthUnsubscribe(ctx context.Context, id ethtypes.EthSubscriptionID) (bool, error) //perm:write + EthUnsubscribe(ctx context.Context, id ethtypes.EthSubscriptionID) (bool, error) //perm:read // Returns the client version Web3ClientVersion(ctx context.Context) (string, error) //perm:read diff --git a/api/api_gateway.go b/api/api_gateway.go index 4389fc34b..0fa329724 100644 --- a/api/api_gateway.go +++ b/api/api_gateway.go @@ -3,8 +3,8 @@ package api import ( "context" + blocks "github.com/ipfs/go-block-format" "github.com/ipfs/go-cid" - blocks "github.com/ipfs/go-libipfs/blocks" "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-jsonrpc" @@ -33,6 +33,9 @@ import ( // * Generate openrpc blobs type Gateway interface { + StateMinerSectorCount(context.Context, address.Address, types.TipSetKey) (MinerSectors, error) + GasEstimateGasPremium(context.Context, uint64, address.Address, int64, types.TipSetKey) (types.BigInt, error) + StateReplay(context.Context, types.TipSetKey, cid.Cid) (*InvocResult, error) ChainHasObj(context.Context, cid.Cid) (bool, error) ChainPutObj(context.Context, blocks.Block) error ChainHead(ctx context.Context) (*types.TipSet, error) @@ -95,6 +98,7 @@ type Gateway interface { EthGetStorageAt(ctx context.Context, address ethtypes.EthAddress, position ethtypes.EthBytes, blkParam string) (ethtypes.EthBytes, error) EthGetBalance(ctx context.Context, address ethtypes.EthAddress, blkParam string) (ethtypes.EthBigInt, error) EthChainId(ctx context.Context) (ethtypes.EthUint64, error) + EthSyncing(ctx context.Context) (ethtypes.EthSyncingResult, error) NetVersion(ctx context.Context) (string, error) NetListening(ctx context.Context) (bool, error) EthProtocolVersion(ctx context.Context) (ethtypes.EthUint64, error) diff --git a/api/api_net.go b/api/api_net.go index 404c707b4..cfcd8d87e 100644 --- a/api/api_net.go +++ b/api/api_net.go @@ -73,5 +73,5 @@ type CommonNet interface { type NatInfo struct { Reachability network.Reachability - PublicAddr string + PublicAddrs []string } diff --git a/api/api_storage.go b/api/api_storage.go index 9e65c1ced..a9e632998 100644 --- a/api/api_storage.go +++ b/api/api_storage.go @@ -129,6 +129,8 @@ type StorageMiner interface { SectorMatchPendingPiecesToOpenSectors(ctx context.Context) error //perm:admin // SectorAbortUpgrade can be called on sectors that are in the process of being upgraded to abort it SectorAbortUpgrade(context.Context, abi.SectorNumber) error //perm:admin + // SectorUnseal unseals the provided sector + SectorUnseal(ctx context.Context, number abi.SectorNumber) error //perm:admin // SectorNumAssignerMeta returns sector number assigner metadata - reserved/allocated SectorNumAssignerMeta(ctx context.Context) (NumAssignerMeta, error) //perm:read diff --git a/api/docgen/docgen.go b/api/docgen/docgen.go index 0a0470446..7a9993bb7 100644 --- a/api/docgen/docgen.go +++ b/api/docgen/docgen.go @@ -14,9 +14,9 @@ import ( "unicode" "github.com/google/uuid" + blocks "github.com/ipfs/go-block-format" "github.com/ipfs/go-cid" "github.com/ipfs/go-graphsync" - blocks "github.com/ipfs/go-libipfs/blocks" textselector "github.com/ipld/go-ipld-selector-text-lite" pubsub "github.com/libp2p/go-libp2p-pubsub" "github.com/libp2p/go-libp2p/core/metrics" diff --git a/api/eth_aliases.go b/api/eth_aliases.go index ccf0317d9..ca0f861ac 100644 --- a/api/eth_aliases.go +++ b/api/eth_aliases.go @@ -21,6 +21,7 @@ func CreateEthRPCAliases(as apitypes.Aliaser) { as.AliasMethod("eth_getStorageAt", "Filecoin.EthGetStorageAt") as.AliasMethod("eth_getBalance", "Filecoin.EthGetBalance") as.AliasMethod("eth_chainId", "Filecoin.EthChainId") + as.AliasMethod("eth_syncing", "Filecoin.EthSyncing") as.AliasMethod("eth_feeHistory", "Filecoin.EthFeeHistory") as.AliasMethod("eth_protocolVersion", "Filecoin.EthProtocolVersion") as.AliasMethod("eth_maxPriorityFeePerGas", "Filecoin.EthMaxPriorityFeePerGas") diff --git a/api/mocks/mock_full.go b/api/mocks/mock_full.go index 83efbffdb..0b0e3ca4c 100644 --- a/api/mocks/mock_full.go +++ b/api/mocks/mock_full.go @@ -12,8 +12,8 @@ import ( gomock "github.com/golang/mock/gomock" uuid "github.com/google/uuid" + blocks "github.com/ipfs/go-block-format" cid "github.com/ipfs/go-cid" - blocks "github.com/ipfs/go-libipfs/blocks" metrics "github.com/libp2p/go-libp2p/core/metrics" network0 "github.com/libp2p/go-libp2p/core/network" peer "github.com/libp2p/go-libp2p/core/peer" @@ -1476,6 +1476,21 @@ func (mr *MockFullNodeMockRecorder) EthSubscribe(arg0, arg1 interface{}) *gomock return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EthSubscribe", reflect.TypeOf((*MockFullNode)(nil).EthSubscribe), arg0, arg1) } +// EthSyncing mocks base method. +func (m *MockFullNode) EthSyncing(arg0 context.Context) (ethtypes.EthSyncingResult, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "EthSyncing", arg0) + ret0, _ := ret[0].(ethtypes.EthSyncingResult) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// EthSyncing indicates an expected call of EthSyncing. +func (mr *MockFullNodeMockRecorder) EthSyncing(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EthSyncing", reflect.TypeOf((*MockFullNode)(nil).EthSyncing), arg0) +} + // EthUninstallFilter mocks base method. func (m *MockFullNode) EthUninstallFilter(arg0 context.Context, arg1 ethtypes.EthFilterID) (bool, error) { m.ctrl.T.Helper() diff --git a/api/proxy_gen.go b/api/proxy_gen.go index 843471381..459fd5864 100644 --- a/api/proxy_gen.go +++ b/api/proxy_gen.go @@ -8,8 +8,8 @@ import ( "time" "github.com/google/uuid" + blocks "github.com/ipfs/go-block-format" "github.com/ipfs/go-cid" - blocks "github.com/ipfs/go-libipfs/blocks" "github.com/libp2p/go-libp2p/core/metrics" "github.com/libp2p/go-libp2p/core/network" "github.com/libp2p/go-libp2p/core/peer" @@ -274,9 +274,9 @@ type FullNodeMethods struct { EthGetCode func(p0 context.Context, p1 ethtypes.EthAddress, p2 string) (ethtypes.EthBytes, error) `perm:"read"` - EthGetFilterChanges func(p0 context.Context, p1 ethtypes.EthFilterID) (*ethtypes.EthFilterResult, error) `perm:"write"` + EthGetFilterChanges func(p0 context.Context, p1 ethtypes.EthFilterID) (*ethtypes.EthFilterResult, error) `perm:"read"` - EthGetFilterLogs func(p0 context.Context, p1 ethtypes.EthFilterID) (*ethtypes.EthFilterResult, error) `perm:"write"` + EthGetFilterLogs func(p0 context.Context, p1 ethtypes.EthFilterID) (*ethtypes.EthFilterResult, error) `perm:"read"` EthGetLogs func(p0 context.Context, p1 *ethtypes.EthFilterSpec) (*ethtypes.EthFilterResult, error) `perm:"read"` @@ -302,21 +302,23 @@ type FullNodeMethods struct { EthMaxPriorityFeePerGas func(p0 context.Context) (ethtypes.EthBigInt, error) `perm:"read"` - EthNewBlockFilter func(p0 context.Context) (ethtypes.EthFilterID, error) `perm:"write"` + EthNewBlockFilter func(p0 context.Context) (ethtypes.EthFilterID, error) `perm:"read"` - EthNewFilter func(p0 context.Context, p1 *ethtypes.EthFilterSpec) (ethtypes.EthFilterID, error) `perm:"write"` + EthNewFilter func(p0 context.Context, p1 *ethtypes.EthFilterSpec) (ethtypes.EthFilterID, error) `perm:"read"` - EthNewPendingTransactionFilter func(p0 context.Context) (ethtypes.EthFilterID, error) `perm:"write"` + EthNewPendingTransactionFilter func(p0 context.Context) (ethtypes.EthFilterID, error) `perm:"read"` EthProtocolVersion func(p0 context.Context) (ethtypes.EthUint64, error) `perm:"read"` EthSendRawTransaction func(p0 context.Context, p1 ethtypes.EthBytes) (ethtypes.EthHash, error) `perm:"read"` - EthSubscribe func(p0 context.Context, p1 jsonrpc.RawParams) (ethtypes.EthSubscriptionID, error) `perm:"write"` + EthSubscribe func(p0 context.Context, p1 jsonrpc.RawParams) (ethtypes.EthSubscriptionID, error) `perm:"read"` - EthUninstallFilter func(p0 context.Context, p1 ethtypes.EthFilterID) (bool, error) `perm:"write"` + EthSyncing func(p0 context.Context) (ethtypes.EthSyncingResult, error) `perm:"read"` - EthUnsubscribe func(p0 context.Context, p1 ethtypes.EthSubscriptionID) (bool, error) `perm:"write"` + EthUninstallFilter func(p0 context.Context, p1 ethtypes.EthFilterID) (bool, error) `perm:"read"` + + EthUnsubscribe func(p0 context.Context, p1 ethtypes.EthSubscriptionID) (bool, error) `perm:"read"` FilecoinAddressToEthAddress func(p0 context.Context, p1 address.Address) (ethtypes.EthAddress, error) `perm:"read"` @@ -722,10 +724,14 @@ type GatewayMethods struct { EthSubscribe func(p0 context.Context, p1 jsonrpc.RawParams) (ethtypes.EthSubscriptionID, error) `` + EthSyncing func(p0 context.Context) (ethtypes.EthSyncingResult, error) `` + EthUninstallFilter func(p0 context.Context, p1 ethtypes.EthFilterID) (bool, error) `` EthUnsubscribe func(p0 context.Context, p1 ethtypes.EthSubscriptionID) (bool, error) `` + GasEstimateGasPremium func(p0 context.Context, p1 uint64, p2 address.Address, p3 int64, p4 types.TipSetKey) (types.BigInt, error) `` + GasEstimateMessageGas func(p0 context.Context, p1 *types.Message, p2 *MessageSendSpec, p3 types.TipSetKey) (*types.Message, error) `` MpoolGetNonce func(p0 context.Context, p1 address.Address) (uint64, error) `` @@ -768,12 +774,16 @@ type GatewayMethods struct { StateMinerProvingDeadline func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (*dline.Info, error) `` + StateMinerSectorCount func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (MinerSectors, error) `` + StateNetworkName func(p0 context.Context) (dtypes.NetworkName, error) `` StateNetworkVersion func(p0 context.Context, p1 types.TipSetKey) (apitypes.NetworkVersion, error) `` StateReadState func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (*ActorState, error) `` + StateReplay func(p0 context.Context, p1 types.TipSetKey, p2 cid.Cid) (*InvocResult, error) `` + StateSearchMsg func(p0 context.Context, p1 types.TipSetKey, p2 cid.Cid, p3 abi.ChainEpoch, p4 bool) (*MsgLookup, error) `` StateSectorGetInfo func(p0 context.Context, p1 address.Address, p2 abi.SectorNumber, p3 types.TipSetKey) (*miner.SectorOnChainInfo, error) `` @@ -1079,6 +1089,8 @@ type StorageMinerMethods struct { SectorTerminatePending func(p0 context.Context) ([]abi.SectorID, error) `perm:"admin"` + SectorUnseal func(p0 context.Context, p1 abi.SectorNumber) error `perm:"admin"` + SectorsList func(p0 context.Context) ([]abi.SectorNumber, error) `perm:"read"` SectorsListInStates func(p0 context.Context, p1 []SectorState) ([]abi.SectorNumber, error) `perm:"read"` @@ -2414,6 +2426,17 @@ func (s *FullNodeStub) EthSubscribe(p0 context.Context, p1 jsonrpc.RawParams) (e return *new(ethtypes.EthSubscriptionID), ErrNotSupported } +func (s *FullNodeStruct) EthSyncing(p0 context.Context) (ethtypes.EthSyncingResult, error) { + if s.Internal.EthSyncing == nil { + return *new(ethtypes.EthSyncingResult), ErrNotSupported + } + return s.Internal.EthSyncing(p0) +} + +func (s *FullNodeStub) EthSyncing(p0 context.Context) (ethtypes.EthSyncingResult, error) { + return *new(ethtypes.EthSyncingResult), ErrNotSupported +} + func (s *FullNodeStruct) EthUninstallFilter(p0 context.Context, p1 ethtypes.EthFilterID) (bool, error) { if s.Internal.EthUninstallFilter == nil { return false, ErrNotSupported @@ -4592,6 +4615,17 @@ func (s *GatewayStub) EthSubscribe(p0 context.Context, p1 jsonrpc.RawParams) (et return *new(ethtypes.EthSubscriptionID), ErrNotSupported } +func (s *GatewayStruct) EthSyncing(p0 context.Context) (ethtypes.EthSyncingResult, error) { + if s.Internal.EthSyncing == nil { + return *new(ethtypes.EthSyncingResult), ErrNotSupported + } + return s.Internal.EthSyncing(p0) +} + +func (s *GatewayStub) EthSyncing(p0 context.Context) (ethtypes.EthSyncingResult, error) { + return *new(ethtypes.EthSyncingResult), ErrNotSupported +} + func (s *GatewayStruct) EthUninstallFilter(p0 context.Context, p1 ethtypes.EthFilterID) (bool, error) { if s.Internal.EthUninstallFilter == nil { return false, ErrNotSupported @@ -4614,6 +4648,17 @@ func (s *GatewayStub) EthUnsubscribe(p0 context.Context, p1 ethtypes.EthSubscrip return false, ErrNotSupported } +func (s *GatewayStruct) GasEstimateGasPremium(p0 context.Context, p1 uint64, p2 address.Address, p3 int64, p4 types.TipSetKey) (types.BigInt, error) { + if s.Internal.GasEstimateGasPremium == nil { + return *new(types.BigInt), ErrNotSupported + } + return s.Internal.GasEstimateGasPremium(p0, p1, p2, p3, p4) +} + +func (s *GatewayStub) GasEstimateGasPremium(p0 context.Context, p1 uint64, p2 address.Address, p3 int64, p4 types.TipSetKey) (types.BigInt, error) { + return *new(types.BigInt), ErrNotSupported +} + func (s *GatewayStruct) GasEstimateMessageGas(p0 context.Context, p1 *types.Message, p2 *MessageSendSpec, p3 types.TipSetKey) (*types.Message, error) { if s.Internal.GasEstimateMessageGas == nil { return nil, ErrNotSupported @@ -4845,6 +4890,17 @@ func (s *GatewayStub) StateMinerProvingDeadline(p0 context.Context, p1 address.A return nil, ErrNotSupported } +func (s *GatewayStruct) StateMinerSectorCount(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (MinerSectors, error) { + if s.Internal.StateMinerSectorCount == nil { + return *new(MinerSectors), ErrNotSupported + } + return s.Internal.StateMinerSectorCount(p0, p1, p2) +} + +func (s *GatewayStub) StateMinerSectorCount(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (MinerSectors, error) { + return *new(MinerSectors), ErrNotSupported +} + func (s *GatewayStruct) StateNetworkName(p0 context.Context) (dtypes.NetworkName, error) { if s.Internal.StateNetworkName == nil { return *new(dtypes.NetworkName), ErrNotSupported @@ -4878,6 +4934,17 @@ func (s *GatewayStub) StateReadState(p0 context.Context, p1 address.Address, p2 return nil, ErrNotSupported } +func (s *GatewayStruct) StateReplay(p0 context.Context, p1 types.TipSetKey, p2 cid.Cid) (*InvocResult, error) { + if s.Internal.StateReplay == nil { + return nil, ErrNotSupported + } + return s.Internal.StateReplay(p0, p1, p2) +} + +func (s *GatewayStub) StateReplay(p0 context.Context, p1 types.TipSetKey, p2 cid.Cid) (*InvocResult, error) { + return nil, ErrNotSupported +} + func (s *GatewayStruct) StateSearchMsg(p0 context.Context, p1 types.TipSetKey, p2 cid.Cid, p3 abi.ChainEpoch, p4 bool) (*MsgLookup, error) { if s.Internal.StateSearchMsg == nil { return nil, ErrNotSupported @@ -6385,6 +6452,17 @@ func (s *StorageMinerStub) SectorTerminatePending(p0 context.Context) ([]abi.Sec return *new([]abi.SectorID), ErrNotSupported } +func (s *StorageMinerStruct) SectorUnseal(p0 context.Context, p1 abi.SectorNumber) error { + if s.Internal.SectorUnseal == nil { + return ErrNotSupported + } + return s.Internal.SectorUnseal(p0, p1) +} + +func (s *StorageMinerStub) SectorUnseal(p0 context.Context, p1 abi.SectorNumber) error { + return ErrNotSupported +} + func (s *StorageMinerStruct) SectorsList(p0 context.Context) ([]abi.SectorNumber, error) { if s.Internal.SectorsList == nil { return *new([]abi.SectorNumber), ErrNotSupported diff --git a/api/types.go b/api/types.go index 7ff413867..625b770c5 100644 --- a/api/types.go +++ b/api/types.go @@ -314,31 +314,30 @@ type NetworkParams struct { } type ForkUpgradeParams struct { - UpgradeSmokeHeight abi.ChainEpoch - UpgradeBreezeHeight abi.ChainEpoch - UpgradeIgnitionHeight abi.ChainEpoch - UpgradeLiftoffHeight abi.ChainEpoch - UpgradeAssemblyHeight abi.ChainEpoch - UpgradeRefuelHeight abi.ChainEpoch - UpgradeTapeHeight abi.ChainEpoch - UpgradeKumquatHeight abi.ChainEpoch - UpgradePriceListOopsHeight abi.ChainEpoch - BreezeGasTampingDuration abi.ChainEpoch - UpgradeCalicoHeight abi.ChainEpoch - UpgradePersianHeight abi.ChainEpoch - UpgradeOrangeHeight abi.ChainEpoch - UpgradeClausHeight abi.ChainEpoch - UpgradeTrustHeight abi.ChainEpoch - UpgradeNorwegianHeight abi.ChainEpoch - UpgradeTurboHeight abi.ChainEpoch - UpgradeHyperdriveHeight abi.ChainEpoch - UpgradeChocolateHeight abi.ChainEpoch - UpgradeOhSnapHeight abi.ChainEpoch - UpgradeSkyrHeight abi.ChainEpoch - UpgradeSharkHeight abi.ChainEpoch - UpgradeHyggeHeight abi.ChainEpoch - UpgradeLightningHeight abi.ChainEpoch - UpgradeThunderHeight abi.ChainEpoch + UpgradeSmokeHeight abi.ChainEpoch + UpgradeBreezeHeight abi.ChainEpoch + UpgradeIgnitionHeight abi.ChainEpoch + UpgradeLiftoffHeight abi.ChainEpoch + UpgradeAssemblyHeight abi.ChainEpoch + UpgradeRefuelHeight abi.ChainEpoch + UpgradeTapeHeight abi.ChainEpoch + UpgradeKumquatHeight abi.ChainEpoch + BreezeGasTampingDuration abi.ChainEpoch + UpgradeCalicoHeight abi.ChainEpoch + UpgradePersianHeight abi.ChainEpoch + UpgradeOrangeHeight abi.ChainEpoch + UpgradeClausHeight abi.ChainEpoch + UpgradeTrustHeight abi.ChainEpoch + UpgradeNorwegianHeight abi.ChainEpoch + UpgradeTurboHeight abi.ChainEpoch + UpgradeHyperdriveHeight abi.ChainEpoch + UpgradeChocolateHeight abi.ChainEpoch + UpgradeOhSnapHeight abi.ChainEpoch + UpgradeSkyrHeight abi.ChainEpoch + UpgradeSharkHeight abi.ChainEpoch + UpgradeHyggeHeight abi.ChainEpoch + UpgradeLightningHeight abi.ChainEpoch + UpgradeThunderHeight abi.ChainEpoch } type NonceMapType map[address.Address]uint64 diff --git a/api/v0api/full.go b/api/v0api/full.go index 86a4ce47a..322f72449 100644 --- a/api/v0api/full.go +++ b/api/v0api/full.go @@ -3,8 +3,8 @@ package v0api import ( "context" + blocks "github.com/ipfs/go-block-format" "github.com/ipfs/go-cid" - blocks "github.com/ipfs/go-libipfs/blocks" textselector "github.com/ipld/go-ipld-selector-text-lite" "github.com/libp2p/go-libp2p/core/peer" diff --git a/api/v0api/gateway.go b/api/v0api/gateway.go index 2a0bfb2f7..30eb0d1c4 100644 --- a/api/v0api/gateway.go +++ b/api/v0api/gateway.go @@ -3,8 +3,8 @@ package v0api import ( "context" + blocks "github.com/ipfs/go-block-format" "github.com/ipfs/go-cid" - blocks "github.com/ipfs/go-libipfs/blocks" "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-state-types/abi" @@ -35,6 +35,9 @@ import ( // * Generate openrpc blobs type Gateway interface { + StateMinerSectorCount(context.Context, address.Address, types.TipSetKey) (api.MinerSectors, error) + GasEstimateGasPremium(context.Context, uint64, address.Address, int64, types.TipSetKey) (types.BigInt, error) + StateReplay(context.Context, types.TipSetKey, cid.Cid) (*api.InvocResult, error) ChainHasObj(context.Context, cid.Cid) (bool, error) ChainPutObj(context.Context, blocks.Block) error ChainHead(ctx context.Context) (*types.TipSet, error) diff --git a/api/v0api/proxy_gen.go b/api/v0api/proxy_gen.go index 3d4a60f1c..069527ae8 100644 --- a/api/v0api/proxy_gen.go +++ b/api/v0api/proxy_gen.go @@ -5,8 +5,8 @@ package v0api import ( "context" + blocks "github.com/ipfs/go-block-format" "github.com/ipfs/go-cid" - blocks "github.com/ipfs/go-libipfs/blocks" "github.com/libp2p/go-libp2p/core/peer" "golang.org/x/xerrors" @@ -449,6 +449,8 @@ type GatewayMethods struct { ChainReadObj func(p0 context.Context, p1 cid.Cid) ([]byte, error) `` + GasEstimateGasPremium func(p0 context.Context, p1 uint64, p2 address.Address, p3 int64, p4 types.TipSetKey) (types.BigInt, error) `` + GasEstimateMessageGas func(p0 context.Context, p1 *types.Message, p2 *api.MessageSendSpec, p3 types.TipSetKey) (*types.Message, error) `` MpoolGetNonce func(p0 context.Context, p1 address.Address) (uint64, error) `` @@ -487,10 +489,14 @@ type GatewayMethods struct { StateMinerProvingDeadline func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (*dline.Info, error) `` + StateMinerSectorCount func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (api.MinerSectors, error) `` + StateNetworkName func(p0 context.Context) (dtypes.NetworkName, error) `` StateNetworkVersion func(p0 context.Context, p1 types.TipSetKey) (abinetwork.Version, error) `` + StateReplay func(p0 context.Context, p1 types.TipSetKey, p2 cid.Cid) (*api.InvocResult, error) `` + StateSearchMsg func(p0 context.Context, p1 cid.Cid) (*api.MsgLookup, error) `` StateSectorGetInfo func(p0 context.Context, p1 address.Address, p2 abi.SectorNumber, p3 types.TipSetKey) (*miner.SectorOnChainInfo, error) `` @@ -2674,6 +2680,17 @@ func (s *GatewayStub) ChainReadObj(p0 context.Context, p1 cid.Cid) ([]byte, erro return *new([]byte), ErrNotSupported } +func (s *GatewayStruct) GasEstimateGasPremium(p0 context.Context, p1 uint64, p2 address.Address, p3 int64, p4 types.TipSetKey) (types.BigInt, error) { + if s.Internal.GasEstimateGasPremium == nil { + return *new(types.BigInt), ErrNotSupported + } + return s.Internal.GasEstimateGasPremium(p0, p1, p2, p3, p4) +} + +func (s *GatewayStub) GasEstimateGasPremium(p0 context.Context, p1 uint64, p2 address.Address, p3 int64, p4 types.TipSetKey) (types.BigInt, error) { + return *new(types.BigInt), ErrNotSupported +} + func (s *GatewayStruct) GasEstimateMessageGas(p0 context.Context, p1 *types.Message, p2 *api.MessageSendSpec, p3 types.TipSetKey) (*types.Message, error) { if s.Internal.GasEstimateMessageGas == nil { return nil, ErrNotSupported @@ -2883,6 +2900,17 @@ func (s *GatewayStub) StateMinerProvingDeadline(p0 context.Context, p1 address.A return nil, ErrNotSupported } +func (s *GatewayStruct) StateMinerSectorCount(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (api.MinerSectors, error) { + if s.Internal.StateMinerSectorCount == nil { + return *new(api.MinerSectors), ErrNotSupported + } + return s.Internal.StateMinerSectorCount(p0, p1, p2) +} + +func (s *GatewayStub) StateMinerSectorCount(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (api.MinerSectors, error) { + return *new(api.MinerSectors), ErrNotSupported +} + func (s *GatewayStruct) StateNetworkName(p0 context.Context) (dtypes.NetworkName, error) { if s.Internal.StateNetworkName == nil { return *new(dtypes.NetworkName), ErrNotSupported @@ -2905,6 +2933,17 @@ func (s *GatewayStub) StateNetworkVersion(p0 context.Context, p1 types.TipSetKey return *new(abinetwork.Version), ErrNotSupported } +func (s *GatewayStruct) StateReplay(p0 context.Context, p1 types.TipSetKey, p2 cid.Cid) (*api.InvocResult, error) { + if s.Internal.StateReplay == nil { + return nil, ErrNotSupported + } + return s.Internal.StateReplay(p0, p1, p2) +} + +func (s *GatewayStub) StateReplay(p0 context.Context, p1 types.TipSetKey, p2 cid.Cid) (*api.InvocResult, error) { + return nil, ErrNotSupported +} + func (s *GatewayStruct) StateSearchMsg(p0 context.Context, p1 cid.Cid) (*api.MsgLookup, error) { if s.Internal.StateSearchMsg == nil { return nil, ErrNotSupported diff --git a/api/v0api/v0mocks/mock_full.go b/api/v0api/v0mocks/mock_full.go index a4adfc944..7a722ed25 100644 --- a/api/v0api/v0mocks/mock_full.go +++ b/api/v0api/v0mocks/mock_full.go @@ -11,8 +11,8 @@ import ( gomock "github.com/golang/mock/gomock" uuid "github.com/google/uuid" + blocks "github.com/ipfs/go-block-format" cid "github.com/ipfs/go-cid" - blocks "github.com/ipfs/go-libipfs/blocks" metrics "github.com/libp2p/go-libp2p/core/metrics" network0 "github.com/libp2p/go-libp2p/core/network" peer "github.com/libp2p/go-libp2p/core/peer" diff --git a/blockstore/api.go b/blockstore/api.go index 251deb13a..090f53e5a 100644 --- a/blockstore/api.go +++ b/blockstore/api.go @@ -3,8 +3,8 @@ package blockstore import ( "context" + blocks "github.com/ipfs/go-block-format" "github.com/ipfs/go-cid" - blocks "github.com/ipfs/go-libipfs/blocks" "golang.org/x/xerrors" ) diff --git a/blockstore/autobatch.go b/blockstore/autobatch.go index 3cb8eafa6..d41d521ef 100644 --- a/blockstore/autobatch.go +++ b/blockstore/autobatch.go @@ -5,9 +5,9 @@ import ( "sync" "time" + block "github.com/ipfs/go-block-format" "github.com/ipfs/go-cid" ipld "github.com/ipfs/go-ipld-format" - block "github.com/ipfs/go-libipfs/blocks" "golang.org/x/xerrors" ) diff --git a/blockstore/badger/blockstore.go b/blockstore/badger/blockstore.go index 3a789a178..a49e88f85 100644 --- a/blockstore/badger/blockstore.go +++ b/blockstore/badger/blockstore.go @@ -13,9 +13,9 @@ import ( "github.com/dgraph-io/badger/v2" "github.com/dgraph-io/badger/v2/options" "github.com/dgraph-io/badger/v2/pb" + blocks "github.com/ipfs/go-block-format" "github.com/ipfs/go-cid" ipld "github.com/ipfs/go-ipld-format" - blocks "github.com/ipfs/go-libipfs/blocks" logger "github.com/ipfs/go-log/v2" pool "github.com/libp2p/go-buffer-pool" "github.com/multiformats/go-base32" @@ -746,6 +746,20 @@ func (b *Blockstore) Put(ctx context.Context, block blocks.Block) error { } put := func(db *badger.DB) error { + // Check if we have it before writing it. + switch err := db.View(func(txn *badger.Txn) error { + _, err := txn.Get(k) + return err + }); err { + case badger.ErrKeyNotFound: + case nil: + // Already exists, skip the put. + return nil + default: + return err + } + + // Then write it. err := db.Update(func(txn *badger.Txn) error { return txn.Set(k, block.RawData()) }) @@ -801,12 +815,33 @@ func (b *Blockstore) PutMany(ctx context.Context, blocks []blocks.Block) error { keys = append(keys, k) } + err := b.db.View(func(txn *badger.Txn) error { + for i, k := range keys { + switch _, err := txn.Get(k); err { + case badger.ErrKeyNotFound: + case nil: + keys[i] = nil + default: + // Something is actually wrong + return err + } + } + return nil + }) + if err != nil { + return err + } + put := func(db *badger.DB) error { batch := db.NewWriteBatch() defer batch.Cancel() for i, block := range blocks { k := keys[i] + if k == nil { + // skipped because we already have it. + continue + } if err := batch.Set(k, block.RawData()); err != nil { return err } diff --git a/blockstore/badger/blockstore_test.go b/blockstore/badger/blockstore_test.go index bf85104bb..d253f37d9 100644 --- a/blockstore/badger/blockstore_test.go +++ b/blockstore/badger/blockstore_test.go @@ -10,8 +10,8 @@ import ( "strings" "testing" + blocks "github.com/ipfs/go-block-format" "github.com/ipfs/go-cid" - blocks "github.com/ipfs/go-libipfs/blocks" "github.com/stretchr/testify/require" "golang.org/x/sync/errgroup" diff --git a/blockstore/badger/blockstore_test_suite.go b/blockstore/badger/blockstore_test_suite.go index 877eb6e6b..7db155901 100644 --- a/blockstore/badger/blockstore_test_suite.go +++ b/blockstore/badger/blockstore_test_suite.go @@ -9,10 +9,10 @@ import ( "strings" "testing" + blocks "github.com/ipfs/go-block-format" "github.com/ipfs/go-cid" u "github.com/ipfs/go-ipfs-util" ipld "github.com/ipfs/go-ipld-format" - blocks "github.com/ipfs/go-libipfs/blocks" "github.com/stretchr/testify/require" "github.com/filecoin-project/lotus/blockstore" diff --git a/blockstore/buffered.go b/blockstore/buffered.go index bc37b2f69..2a789b637 100644 --- a/blockstore/buffered.go +++ b/blockstore/buffered.go @@ -4,9 +4,9 @@ import ( "context" "os" + block "github.com/ipfs/go-block-format" "github.com/ipfs/go-cid" ipld "github.com/ipfs/go-ipld-format" - block "github.com/ipfs/go-libipfs/blocks" ) // buflog is a logger for the buffered blockstore. It is subscoped from the diff --git a/blockstore/discard.go b/blockstore/discard.go index 878797561..158c7cfbb 100644 --- a/blockstore/discard.go +++ b/blockstore/discard.go @@ -4,8 +4,8 @@ import ( "context" "io" + blocks "github.com/ipfs/go-block-format" "github.com/ipfs/go-cid" - blocks "github.com/ipfs/go-libipfs/blocks" ) var _ Blockstore = (*discardstore)(nil) diff --git a/blockstore/fallback.go b/blockstore/fallback.go index 9fab960f5..de948b346 100644 --- a/blockstore/fallback.go +++ b/blockstore/fallback.go @@ -5,9 +5,9 @@ import ( "sync" "time" + blocks "github.com/ipfs/go-block-format" "github.com/ipfs/go-cid" ipld "github.com/ipfs/go-ipld-format" - blocks "github.com/ipfs/go-libipfs/blocks" "golang.org/x/xerrors" ) diff --git a/blockstore/idstore.go b/blockstore/idstore.go index ae807076d..fb575dca7 100644 --- a/blockstore/idstore.go +++ b/blockstore/idstore.go @@ -4,8 +4,8 @@ import ( "context" "io" + blocks "github.com/ipfs/go-block-format" "github.com/ipfs/go-cid" - blocks "github.com/ipfs/go-libipfs/blocks" mh "github.com/multiformats/go-multihash" "golang.org/x/xerrors" ) diff --git a/blockstore/ipfs.go b/blockstore/ipfs.go index c7dbb480a..7b356cd0e 100644 --- a/blockstore/ipfs.go +++ b/blockstore/ipfs.go @@ -5,9 +5,9 @@ import ( "context" "io" + blocks "github.com/ipfs/go-block-format" "github.com/ipfs/go-cid" httpapi "github.com/ipfs/go-ipfs-http-client" - blocks "github.com/ipfs/go-libipfs/blocks" iface "github.com/ipfs/interface-go-ipfs-core" "github.com/ipfs/interface-go-ipfs-core/options" "github.com/ipfs/interface-go-ipfs-core/path" diff --git a/blockstore/mem.go b/blockstore/mem.go index 5b06634de..8dbf4b719 100644 --- a/blockstore/mem.go +++ b/blockstore/mem.go @@ -3,9 +3,9 @@ package blockstore import ( "context" + blocks "github.com/ipfs/go-block-format" "github.com/ipfs/go-cid" ipld "github.com/ipfs/go-ipld-format" - blocks "github.com/ipfs/go-libipfs/blocks" ) // NewMemory returns a temporary memory-backed blockstore. diff --git a/blockstore/mem_test.go b/blockstore/mem_test.go index 6a5e0d2d1..4d4a77624 100644 --- a/blockstore/mem_test.go +++ b/blockstore/mem_test.go @@ -4,8 +4,8 @@ import ( "context" "testing" + blocks "github.com/ipfs/go-block-format" "github.com/ipfs/go-cid" - blocks "github.com/ipfs/go-libipfs/blocks" mh "github.com/multiformats/go-multihash" "github.com/stretchr/testify/require" ) diff --git a/blockstore/net.go b/blockstore/net.go index 62aceed71..c4a88cfc9 100644 --- a/blockstore/net.go +++ b/blockstore/net.go @@ -8,9 +8,9 @@ import ( "sync" "sync/atomic" + blocks "github.com/ipfs/go-block-format" "github.com/ipfs/go-cid" ipld "github.com/ipfs/go-ipld-format" - blocks "github.com/ipfs/go-libipfs/blocks" "github.com/libp2p/go-msgio" cbg "github.com/whyrusleeping/cbor-gen" "golang.org/x/xerrors" diff --git a/blockstore/net_serve.go b/blockstore/net_serve.go index b58d2a5fd..2540c845e 100644 --- a/blockstore/net_serve.go +++ b/blockstore/net_serve.go @@ -5,9 +5,9 @@ import ( "context" "encoding/binary" + block "github.com/ipfs/go-block-format" "github.com/ipfs/go-cid" ipld "github.com/ipfs/go-ipld-format" - block "github.com/ipfs/go-libipfs/blocks" "github.com/libp2p/go-msgio" cbg "github.com/whyrusleeping/cbor-gen" "golang.org/x/xerrors" diff --git a/blockstore/net_test.go b/blockstore/net_test.go index 6c3060a98..d8c33818e 100644 --- a/blockstore/net_test.go +++ b/blockstore/net_test.go @@ -6,8 +6,8 @@ import ( "io" "testing" + block "github.com/ipfs/go-block-format" ipld "github.com/ipfs/go-ipld-format" - block "github.com/ipfs/go-libipfs/blocks" "github.com/libp2p/go-msgio" "github.com/stretchr/testify/require" ) diff --git a/blockstore/splitstore/debug.go b/blockstore/splitstore/debug.go index c870a44e1..f059ae4ce 100644 --- a/blockstore/splitstore/debug.go +++ b/blockstore/splitstore/debug.go @@ -12,8 +12,8 @@ import ( "sync" "time" + blocks "github.com/ipfs/go-block-format" "github.com/ipfs/go-cid" - blocks "github.com/ipfs/go-libipfs/blocks" "go.uber.org/multierr" "golang.org/x/xerrors" ) diff --git a/blockstore/splitstore/splitstore.go b/blockstore/splitstore/splitstore.go index 2d51ce423..1f1ba0e99 100644 --- a/blockstore/splitstore/splitstore.go +++ b/blockstore/splitstore/splitstore.go @@ -8,10 +8,10 @@ import ( "sync/atomic" "time" + blocks "github.com/ipfs/go-block-format" "github.com/ipfs/go-cid" dstore "github.com/ipfs/go-datastore" ipld "github.com/ipfs/go-ipld-format" - blocks "github.com/ipfs/go-libipfs/blocks" logging "github.com/ipfs/go-log/v2" "go.opencensus.io/stats" "go.uber.org/multierr" @@ -164,7 +164,7 @@ type SplitStore struct { path string mx sync.Mutex - warmupEpoch abi.ChainEpoch // protected by mx + warmupEpoch atomic.Int64 baseEpoch abi.ChainEpoch // protected by compaction lock pruneEpoch abi.ChainEpoch // protected by compaction lock @@ -684,9 +684,7 @@ func (s *SplitStore) View(ctx context.Context, cid cid.Cid, cb func([]byte) erro } func (s *SplitStore) isWarm() bool { - s.mx.Lock() - defer s.mx.Unlock() - return s.warmupEpoch > 0 + return s.warmupEpoch.Load() > 0 } // State tracking @@ -757,7 +755,7 @@ func (s *SplitStore) Start(chain ChainAccessor, us stmgr.UpgradeSchedule) error bs, err = s.ds.Get(s.ctx, warmupEpochKey) switch err { case nil: - s.warmupEpoch = bytesToEpoch(bs) + s.warmupEpoch.Store(bytesToInt64(bs)) case dstore.ErrNotFound: warmup = true @@ -791,7 +789,7 @@ func (s *SplitStore) Start(chain ChainAccessor, us stmgr.UpgradeSchedule) error return xerrors.Errorf("error loading compaction index: %w", err) } - log.Infow("starting splitstore", "baseEpoch", s.baseEpoch, "warmupEpoch", s.warmupEpoch) + log.Infow("starting splitstore", "baseEpoch", s.baseEpoch, "warmupEpoch", s.warmupEpoch.Load()) if warmup { err = s.warmup(curTs) diff --git a/blockstore/splitstore/splitstore_check.go b/blockstore/splitstore/splitstore_check.go index 2645c78c5..bdc706271 100644 --- a/blockstore/splitstore/splitstore_check.go +++ b/blockstore/splitstore/splitstore_check.go @@ -145,7 +145,7 @@ func (s *SplitStore) doCheck(curTs *types.TipSet) error { func (s *SplitStore) Info() map[string]interface{} { info := make(map[string]interface{}) info["base epoch"] = s.baseEpoch - info["warmup epoch"] = s.warmupEpoch + info["warmup epoch"] = s.warmupEpoch.Load() info["compactions"] = s.compactionIndex info["prunes"] = s.pruneIndex info["compacting"] = s.compacting == 1 diff --git a/blockstore/splitstore/splitstore_compact.go b/blockstore/splitstore/splitstore_compact.go index 644816d8e..534565bf3 100644 --- a/blockstore/splitstore/splitstore_compact.go +++ b/blockstore/splitstore/splitstore_compact.go @@ -10,9 +10,9 @@ import ( "sync/atomic" "time" + blocks "github.com/ipfs/go-block-format" "github.com/ipfs/go-cid" ipld "github.com/ipfs/go-ipld-format" - blocks "github.com/ipfs/go-libipfs/blocks" cbg "github.com/whyrusleeping/cbor-gen" "go.opencensus.io/stats" "golang.org/x/sync/errgroup" @@ -455,7 +455,7 @@ func (s *SplitStore) protectTxnRefs(markSet MarkSet) error { // transactionally protect a reference by walking the object and marking. // concurrent markings are short circuited by checking the markset. func (s *SplitStore) doTxnProtect(root cid.Cid, markSet MarkSet) (int64, error) { - if err := s.checkYield(); err != nil { + if err := s.checkClosing(); err != nil { return 0, err } @@ -1114,13 +1114,17 @@ func (s *SplitStore) walkChain(ts *types.TipSet, inclState, inclMsgs abi.ChainEp if err := walkBlock(c); err != nil { return xerrors.Errorf("error walking block (cid: %s): %w", c, err) } + + if err := s.checkYield(); err != nil { + return xerrors.Errorf("check yield: %w", err) + } } return nil }) } if err := g.Wait(); err != nil { - return err + return xerrors.Errorf("walkBlock workers errored: %w", err) } } @@ -1153,8 +1157,8 @@ func (s *SplitStore) walkObject(c cid.Cid, visitor ObjectVisitor, f func(cid.Cid } // check this before recursing - if err := s.checkYield(); err != nil { - return 0, err + if err := s.checkClosing(); err != nil { + return 0, xerrors.Errorf("check closing: %w", err) } var links []cid.Cid @@ -1222,8 +1226,8 @@ func (s *SplitStore) walkObjectIncomplete(c cid.Cid, visitor ObjectVisitor, f, m } // check this before recursing - if err := s.checkYield(); err != nil { - return sz, err + if err := s.checkClosing(); err != nil { + return sz, xerrors.Errorf("check closing: %w", err) } var links []cid.Cid diff --git a/blockstore/splitstore/splitstore_expose.go b/blockstore/splitstore/splitstore_expose.go index 7461e338d..931836129 100644 --- a/blockstore/splitstore/splitstore_expose.go +++ b/blockstore/splitstore/splitstore_expose.go @@ -4,9 +4,9 @@ import ( "context" "errors" + blocks "github.com/ipfs/go-block-format" "github.com/ipfs/go-cid" ipld "github.com/ipfs/go-ipld-format" - blocks "github.com/ipfs/go-libipfs/blocks" bstore "github.com/filecoin-project/lotus/blockstore" ) diff --git a/blockstore/splitstore/splitstore_reify.go b/blockstore/splitstore/splitstore_reify.go index 07efedead..7f54de55f 100644 --- a/blockstore/splitstore/splitstore_reify.go +++ b/blockstore/splitstore/splitstore_reify.go @@ -5,8 +5,8 @@ import ( "runtime" "sync/atomic" + blocks "github.com/ipfs/go-block-format" "github.com/ipfs/go-cid" - blocks "github.com/ipfs/go-libipfs/blocks" "golang.org/x/xerrors" ) diff --git a/blockstore/splitstore/splitstore_test.go b/blockstore/splitstore/splitstore_test.go index 68e1bfb65..63e77b47e 100644 --- a/blockstore/splitstore/splitstore_test.go +++ b/blockstore/splitstore/splitstore_test.go @@ -11,11 +11,11 @@ import ( "testing" "time" + blocks "github.com/ipfs/go-block-format" "github.com/ipfs/go-cid" "github.com/ipfs/go-datastore" dssync "github.com/ipfs/go-datastore/sync" ipld "github.com/ipfs/go-ipld-format" - blocks "github.com/ipfs/go-libipfs/blocks" logging "github.com/ipfs/go-log/v2" mh "github.com/multiformats/go-multihash" @@ -429,7 +429,7 @@ func testSplitStoreReification(t *testing.T, f func(context.Context, blockstore. } defer ss.Close() //nolint - ss.warmupEpoch = 1 + ss.warmupEpoch.Store(1) go ss.reifyOrchestrator() waitForReification := func() { @@ -529,7 +529,7 @@ func testSplitStoreReificationLimit(t *testing.T, f func(context.Context, blocks } defer ss.Close() //nolint - ss.warmupEpoch = 1 + ss.warmupEpoch.Store(1) go ss.reifyOrchestrator() waitForReification := func() { diff --git a/blockstore/splitstore/splitstore_warmup.go b/blockstore/splitstore/splitstore_warmup.go index 23bbad7ca..7fb6f3b9d 100644 --- a/blockstore/splitstore/splitstore_warmup.go +++ b/blockstore/splitstore/splitstore_warmup.go @@ -5,9 +5,9 @@ import ( "sync/atomic" "time" + blocks "github.com/ipfs/go-block-format" "github.com/ipfs/go-cid" ipld "github.com/ipfs/go-ipld-format" - blocks "github.com/ipfs/go-libipfs/blocks" "golang.org/x/xerrors" "github.com/filecoin-project/go-state-types/abi" @@ -136,9 +136,8 @@ func (s *SplitStore) doWarmup(curTs *types.TipSet) error { if err != nil { return xerrors.Errorf("error saving warm up epoch: %w", err) } - s.mx.Lock() - s.warmupEpoch = epoch - s.mx.Unlock() + + s.warmupEpoch.Store(int64(epoch)) // also save the compactionIndex, as this is used as an indicator of warmup for upgraded nodes err = s.ds.Put(s.ctx, compactionIndexKey, int64ToBytes(s.compactionIndex)) diff --git a/blockstore/sync.go b/blockstore/sync.go index 652943dca..4f0cf830e 100644 --- a/blockstore/sync.go +++ b/blockstore/sync.go @@ -4,8 +4,8 @@ import ( "context" "sync" + blocks "github.com/ipfs/go-block-format" "github.com/ipfs/go-cid" - blocks "github.com/ipfs/go-libipfs/blocks" ) // NewMemorySync returns a thread-safe in-memory blockstore. diff --git a/blockstore/timed.go b/blockstore/timed.go index 3deabb7b8..01e089a9f 100644 --- a/blockstore/timed.go +++ b/blockstore/timed.go @@ -6,9 +6,9 @@ import ( "sync" "time" + blocks "github.com/ipfs/go-block-format" "github.com/ipfs/go-cid" ipld "github.com/ipfs/go-ipld-format" - blocks "github.com/ipfs/go-libipfs/blocks" "github.com/raulk/clock" "go.uber.org/multierr" ) diff --git a/blockstore/timed_test.go b/blockstore/timed_test.go index fb3aa00c9..931f14507 100644 --- a/blockstore/timed_test.go +++ b/blockstore/timed_test.go @@ -6,8 +6,8 @@ import ( "testing" "time" + blocks "github.com/ipfs/go-block-format" "github.com/ipfs/go-cid" - blocks "github.com/ipfs/go-libipfs/blocks" "github.com/raulk/clock" "github.com/stretchr/testify/require" ) diff --git a/blockstore/union.go b/blockstore/union.go index ae6f81955..e7fafbbbd 100644 --- a/blockstore/union.go +++ b/blockstore/union.go @@ -3,9 +3,9 @@ package blockstore import ( "context" + blocks "github.com/ipfs/go-block-format" "github.com/ipfs/go-cid" ipld "github.com/ipfs/go-ipld-format" - blocks "github.com/ipfs/go-libipfs/blocks" ) type unionBlockstore []Blockstore diff --git a/blockstore/union_test.go b/blockstore/union_test.go index 47aab852a..579489947 100644 --- a/blockstore/union_test.go +++ b/blockstore/union_test.go @@ -5,7 +5,7 @@ import ( "context" "testing" - blocks "github.com/ipfs/go-libipfs/blocks" + blocks "github.com/ipfs/go-block-format" "github.com/stretchr/testify/require" ) diff --git a/build/openrpc/full.json.gz b/build/openrpc/full.json.gz index 7d621f3ee..8e12e7ed3 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 1988262e5..2fa38e648 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 47bda504c..164434f3b 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 204fa2477..f56329b05 100644 Binary files a/build/openrpc/worker.json.gz and b/build/openrpc/worker.json.gz differ diff --git a/build/params_testground.go b/build/params_testground.go index ab19474b1..278edd40b 100644 --- a/build/params_testground.go +++ b/build/params_testground.go @@ -9,6 +9,7 @@ package build import ( "math/big" + "time" "github.com/ipfs/go-cid" @@ -137,3 +138,7 @@ const BootstrapPeerThreshold = 1 // ChainId defines the chain ID used in the Ethereum JSON-RPC endpoint. // As per https://github.com/ethereum-lists/chains const Eip155ChainId = 31415926 + +// Reducing the delivery delay for equivocation of +// consistent broadcast to just half a second. +var CBDeliveryDelay = 500 * time.Millisecond diff --git a/build/version.go b/build/version.go index de16623a5..2b7cbeda2 100644 --- a/build/version.go +++ b/build/version.go @@ -37,7 +37,7 @@ func BuildTypeString() string { } // BuildVersion is the local build version -const BuildVersion = "1.23.0" +const BuildVersion = "1.23.2-dev" func UserVersion() string { if os.Getenv("LOTUS_VERSION_IGNORE_COMMIT") == "1" { diff --git a/chain/consensus/compute_state.go b/chain/consensus/compute_state.go index b7914cdf6..6b08519af 100644 --- a/chain/consensus/compute_state.go +++ b/chain/consensus/compute_state.go @@ -110,6 +110,7 @@ func (t *TipSetExecutor) ApplyBlocks(ctx context.Context, TipSetGetter: stmgr.TipSetGetterForTipset(sm.ChainStore(), ts), Tracing: vmTracing, ReturnEvents: sm.ChainStore().IsStoringEvents(), + ExecutionLane: vm.ExecutionLanePriority, } return sm.VMConstructor()(ctx, vmopt) diff --git a/chain/consensus/filcns/filecoin.go b/chain/consensus/filcns/filecoin.go index 2e3baa4db..509eb8a5e 100644 --- a/chain/consensus/filcns/filecoin.go +++ b/chain/consensus/filcns/filecoin.go @@ -382,13 +382,21 @@ func (filec *FilecoinEC) VerifyWinningPoStProof(ctx context.Context, nv network. return nil } -func (filec *FilecoinEC) IsEpochBeyondCurrMax(epoch abi.ChainEpoch) bool { +func (filec *FilecoinEC) IsEpochInConsensusRange(epoch abi.ChainEpoch) bool { if filec.genesis == nil { + return true + } + + // Don't try to sync anything before finality. Don't propagate such blocks either. + // + // We use _our_ current head, not the expected head, because the network's head can lag on + // catch-up (after a network outage). + if epoch < filec.store.GetHeaviestTipSet().Height()-build.Finality { return false } now := uint64(build.Clock.Now().Unix()) - return epoch > (abi.ChainEpoch((now-filec.genesis.MinTimestamp())/build.BlockDelaySecs) + MaxHeightDrift) + return epoch <= (abi.ChainEpoch((now-filec.genesis.MinTimestamp())/build.BlockDelaySecs) + MaxHeightDrift) } func (filec *FilecoinEC) minerIsValid(ctx context.Context, maddr address.Address, baseTs *types.TipSet) error { diff --git a/chain/consensus/iface.go b/chain/consensus/iface.go index 10c3ead74..9449cb5a4 100644 --- a/chain/consensus/iface.go +++ b/chain/consensus/iface.go @@ -32,9 +32,10 @@ type Consensus interface { // the block (signature verifications, VRF checks, message validity, etc.) ValidateBlock(ctx context.Context, b *types.FullBlock) (err error) - // IsEpochBeyondCurrMax is used to configure the fork rules for longest-chain - // consensus protocols. - IsEpochBeyondCurrMax(epoch abi.ChainEpoch) bool + // IsEpochInConsensusRange returns true if the epoch is "in range" for consensus. That is: + // - It's not before finality. + // - It's not too far in the future. + IsEpochInConsensusRange(epoch abi.ChainEpoch) bool // CreateBlock implements all the logic required to propose and assemble a new Filecoin block. // @@ -65,23 +66,24 @@ func ValidateBlockPubsub(ctx context.Context, cns Consensus, self bool, msg *pub stats.Record(ctx, metrics.BlockReceived.M(1)) - recordFailureFlagPeer := func(what string) { - // bv.Validate will flag the peer in that case - panic(what) - } - blk, what, err := decodeAndCheckBlock(msg) if err != nil { log.Error("got invalid block over pubsub: ", err) - recordFailureFlagPeer(what) return pubsub.ValidationReject, what } + if !cns.IsEpochInConsensusRange(blk.Header.Height) { + // We ignore these blocks instead of rejecting to avoid breaking the network if + // we're recovering from an outage (e.g., where nobody agrees on where "head" is + // currently). + log.Warnf("received block outside of consensus range (%d)", blk.Header.Height) + return pubsub.ValidationIgnore, "invalid_block_height" + } + // validate the block meta: the Message CID in the header must match the included messages err = validateMsgMeta(ctx, blk) if err != nil { log.Warnf("error validating message metadata: %s", err) - recordFailureFlagPeer("invalid_block_meta") return pubsub.ValidationReject, "invalid_block_meta" } @@ -91,7 +93,6 @@ func ValidateBlockPubsub(ctx context.Context, cns Consensus, self bool, msg *pub log.Warn("ignoring block msg: ", err) return pubsub.ValidationIgnore, reject } - recordFailureFlagPeer(reject) return pubsub.ValidationReject, reject } diff --git a/chain/events/events.go b/chain/events/events.go index 86aded64d..c68b62a64 100644 --- a/chain/events/events.go +++ b/chain/events/events.go @@ -47,7 +47,7 @@ type Events struct { *hcEvents } -func NewEventsWithConfidence(ctx context.Context, api EventAPI, gcConfidence abi.ChainEpoch) (*Events, error) { +func newEventsWithGCConfidence(ctx context.Context, api EventAPI, gcConfidence abi.ChainEpoch) (*Events, error) { cache := newCache(api, gcConfidence) ob := newObserver(cache, gcConfidence) @@ -63,5 +63,5 @@ func NewEventsWithConfidence(ctx context.Context, api EventAPI, gcConfidence abi func NewEvents(ctx context.Context, api EventAPI) (*Events, error) { gcConfidence := 2 * build.ForkLengthThreshold - return NewEventsWithConfidence(ctx, api, gcConfidence) + return newEventsWithGCConfidence(ctx, api, gcConfidence) } diff --git a/chain/events/events_test.go b/chain/events/events_test.go index ad2dc8e71..e2450909c 100644 --- a/chain/events/events_test.go +++ b/chain/events/events_test.go @@ -174,13 +174,16 @@ func (fcs *fakeCS) makeTs(t *testing.T, parents []cid.Cid, h abi.ChainEpoch, msg }, }) + require.NoError(t, err) + + fcs.mu.Lock() + defer fcs.mu.Unlock() + if fcs.tipsets == nil { fcs.tipsets = map[types.TipSetKey]*types.TipSet{} } fcs.tipsets[ts.Key()] = ts - require.NoError(t, err) - return ts } diff --git a/chain/events/observer.go b/chain/events/observer.go index 72b9deaee..446218585 100644 --- a/chain/events/observer.go +++ b/chain/events/observer.go @@ -125,7 +125,7 @@ func (o *observer) listenHeadChangesOnce(ctx context.Context) error { for changes := range notifs { if err := o.applyChanges(ctx, changes); err != nil { - return err + return xerrors.Errorf("failed to apply a change notification: %w", err) } } diff --git a/chain/events/state/mock/api.go b/chain/events/state/mock/api.go index 680e304f5..cdec42659 100644 --- a/chain/events/state/mock/api.go +++ b/chain/events/state/mock/api.go @@ -4,8 +4,8 @@ import ( "context" "sync" + blocks "github.com/ipfs/go-block-format" "github.com/ipfs/go-cid" - blocks "github.com/ipfs/go-libipfs/blocks" "golang.org/x/xerrors" "github.com/filecoin-project/go-address" diff --git a/chain/gen/gen.go b/chain/gen/gen.go index 8e3c41a89..98610cd6c 100644 --- a/chain/gen/gen.go +++ b/chain/gen/gen.go @@ -34,6 +34,7 @@ import ( "github.com/filecoin-project/lotus/chain/consensus" "github.com/filecoin-project/lotus/chain/consensus/filcns" genesis2 "github.com/filecoin-project/lotus/chain/gen/genesis" + "github.com/filecoin-project/lotus/chain/index" "github.com/filecoin-project/lotus/chain/rand" "github.com/filecoin-project/lotus/chain/stmgr" "github.com/filecoin-project/lotus/chain/store" @@ -256,7 +257,7 @@ func NewGeneratorWithSectorsAndUpgradeSchedule(numSectors int, us stmgr.UpgradeS //return nil, xerrors.Errorf("creating drand beacon: %w", err) //} - sm, err := stmgr.NewStateManager(cs, consensus.NewTipSetExecutor(filcns.RewardFunc), sys, us, beac, ds) + sm, err := stmgr.NewStateManager(cs, consensus.NewTipSetExecutor(filcns.RewardFunc), sys, us, beac, ds, index.DummyMsgIndex) if err != nil { return nil, xerrors.Errorf("initing stmgr: %w", err) } diff --git a/chain/gen/genesis/genblock.go b/chain/gen/genesis/genblock.go index 930b3ccff..f26659cdf 100644 --- a/chain/gen/genesis/genblock.go +++ b/chain/gen/genesis/genblock.go @@ -3,8 +3,8 @@ package genesis import ( "encoding/hex" + blocks "github.com/ipfs/go-block-format" "github.com/ipfs/go-cid" - blocks "github.com/ipfs/go-libipfs/blocks" "github.com/multiformats/go-multihash" ) diff --git a/chain/index/interface.go b/chain/index/interface.go new file mode 100644 index 000000000..f875a94bf --- /dev/null +++ b/chain/index/interface.go @@ -0,0 +1,45 @@ +package index + +import ( + "context" + "errors" + + "github.com/ipfs/go-cid" + + "github.com/filecoin-project/go-state-types/abi" +) + +var ErrNotFound = errors.New("message not found") +var ErrClosed = errors.New("index closed") + +// MsgInfo is the Message metadata the index tracks. +type MsgInfo struct { + // the message this record refers to + Message cid.Cid + // the tipset where this message was included + TipSet cid.Cid + // the epoch where this message was included + Epoch abi.ChainEpoch +} + +// MsgIndex is the interface to the message index +type MsgIndex interface { + // GetMsgInfo retrieves the message metadata through the index. + // The lookup is done using the onchain message Cid; that is the signed message Cid + // for SECP messages and unsigned message Cid for BLS messages. + GetMsgInfo(ctx context.Context, m cid.Cid) (MsgInfo, error) + // Close closes the index + Close() error +} + +type dummyMsgIndex struct{} + +func (dummyMsgIndex) GetMsgInfo(ctx context.Context, m cid.Cid) (MsgInfo, error) { + return MsgInfo{}, ErrNotFound +} + +func (dummyMsgIndex) Close() error { + return nil +} + +var DummyMsgIndex MsgIndex = dummyMsgIndex{} diff --git a/chain/index/msgindex.go b/chain/index/msgindex.go new file mode 100644 index 000000000..39ba487f2 --- /dev/null +++ b/chain/index/msgindex.go @@ -0,0 +1,553 @@ +package index + +import ( + "context" + "database/sql" + "errors" + "io/fs" + "os" + "path" + "sync" + "time" + + "github.com/ipfs/go-cid" + logging "github.com/ipfs/go-log/v2" + _ "github.com/mattn/go-sqlite3" + "golang.org/x/xerrors" + + "github.com/filecoin-project/go-state-types/abi" + + "github.com/filecoin-project/lotus/chain/store" + "github.com/filecoin-project/lotus/chain/types" +) + +var log = logging.Logger("msgindex") + +var dbName = "msgindex.db" +var dbDefs = []string{ + `CREATE TABLE IF NOT EXISTS messages ( + cid VARCHAR(80) PRIMARY KEY ON CONFLICT REPLACE, + tipset_cid VARCHAR(80) NOT NULL, + epoch INTEGER NOT NULL + )`, + `CREATE INDEX IF NOT EXISTS tipset_cids ON messages (tipset_cid) + `, + `CREATE TABLE IF NOT EXISTS _meta ( + version UINT64 NOT NULL UNIQUE + )`, + `INSERT OR IGNORE INTO _meta (version) VALUES (1)`, +} +var dbPragmas = []string{} + +const ( + // prepared stmts + dbqGetMessageInfo = "SELECT tipset_cid, epoch FROM messages WHERE cid = ?" + dbqInsertMessage = "INSERT INTO messages VALUES (?, ?, ?)" + dbqDeleteTipsetMessages = "DELETE FROM messages WHERE tipset_cid = ?" + // reconciliation + dbqCountMessages = "SELECT COUNT(*) FROM messages" + dbqMinEpoch = "SELECT MIN(epoch) FROM messages" + dbqCountTipsetMessages = "SELECT COUNT(*) FROM messages WHERE tipset_cid = ?" + dbqDeleteMessagesByEpoch = "DELETE FROM messages WHERE epoch >= ?" +) + +// coalescer configuration (TODO: use observer instead) +// these are exposed to make tests snappy +var ( + CoalesceMinDelay = time.Second + CoalesceMaxDelay = 15 * time.Second + CoalesceMergeInterval = time.Second +) + +// chain store interface; we could use store.ChainStore directly, +// but this simplifies unit testing. +type ChainStore interface { + SubscribeHeadChanges(f store.ReorgNotifee) + MessagesForTipset(ctx context.Context, ts *types.TipSet) ([]types.ChainMsg, error) + GetHeaviestTipSet() *types.TipSet + GetTipSetFromKey(ctx context.Context, tsk types.TipSetKey) (*types.TipSet, error) +} + +var _ ChainStore = (*store.ChainStore)(nil) + +type msgIndex struct { + cs ChainStore + + db *sql.DB + selectMsgStmt *sql.Stmt + insertMsgStmt *sql.Stmt + deleteTipSetStmt *sql.Stmt + + sema chan struct{} + mx sync.Mutex + pend []headChange + + cancel func() + workers sync.WaitGroup + closeLk sync.RWMutex + closed bool +} + +var _ MsgIndex = (*msgIndex)(nil) + +type headChange struct { + rev []*types.TipSet + app []*types.TipSet +} + +func NewMsgIndex(lctx context.Context, basePath string, cs ChainStore) (MsgIndex, error) { + var ( + dbPath string + exists bool + err error + ) + + err = os.MkdirAll(basePath, 0755) + if err != nil { + return nil, xerrors.Errorf("error creating msgindex base directory: %w", err) + } + + dbPath = path.Join(basePath, dbName) + _, err = os.Stat(dbPath) + switch { + case err == nil: + exists = true + + case errors.Is(err, fs.ErrNotExist): + + case err != nil: + return nil, xerrors.Errorf("error stating msgindex database: %w", err) + } + + db, err := sql.Open("sqlite3", dbPath) + if err != nil { + // TODO [nice to have]: automaticaly delete corrupt databases + // but for now we can just error and let the operator delete. + return nil, xerrors.Errorf("error opening msgindex database: %w", err) + } + + if err := prepareDB(db); err != nil { + return nil, xerrors.Errorf("error creating msgindex database: %w", err) + } + + // TODO we may consider populating the index when first creating the db + if exists { + if err := reconcileIndex(db, cs); err != nil { + return nil, xerrors.Errorf("error reconciling msgindex database: %w", err) + } + } + + ctx, cancel := context.WithCancel(lctx) + + msgIndex := &msgIndex{ + db: db, + cs: cs, + sema: make(chan struct{}, 1), + cancel: cancel, + } + + err = msgIndex.prepareStatements() + if err != nil { + if err := db.Close(); err != nil { + log.Errorf("error closing msgindex database: %s", err) + } + + return nil, xerrors.Errorf("error preparing msgindex database statements: %w", err) + } + + rnf := store.WrapHeadChangeCoalescer( + msgIndex.onHeadChange, + CoalesceMinDelay, + CoalesceMaxDelay, + CoalesceMergeInterval, + ) + cs.SubscribeHeadChanges(rnf) + + msgIndex.workers.Add(1) + go msgIndex.background(ctx) + + return msgIndex, nil +} + +func PopulateAfterSnapshot(lctx context.Context, basePath string, cs ChainStore) error { + err := os.MkdirAll(basePath, 0755) + if err != nil { + return xerrors.Errorf("error creating msgindex base directory: %w", err) + } + + dbPath := path.Join(basePath, dbName) + + // if a database already exists, we try to delete it and create a new one + if _, err := os.Stat(dbPath); err == nil { + if err = os.Remove(dbPath); err != nil { + return xerrors.Errorf("msgindex already exists at %s and can't be deleted", dbPath) + } + } + + db, err := sql.Open("sqlite3", dbPath) + if err != nil { + return xerrors.Errorf("error opening msgindex database: %w", err) + } + defer func() { + if err := db.Close(); err != nil { + log.Errorf("error closing msgindex database: %s", err) + } + }() + + if err := prepareDB(db); err != nil { + return xerrors.Errorf("error creating msgindex database: %w", err) + } + + tx, err := db.Begin() + if err != nil { + return xerrors.Errorf("error when starting transaction: %w", err) + } + + rollback := func() { + if err := tx.Rollback(); err != nil { + log.Errorf("error in rollback: %s", err) + } + } + + insertStmt, err := tx.Prepare(dbqInsertMessage) + if err != nil { + rollback() + return xerrors.Errorf("error preparing insertStmt: %w", err) + } + + curTs := cs.GetHeaviestTipSet() + startHeight := curTs.Height() + for curTs != nil { + tscid, err := curTs.Key().Cid() + if err != nil { + rollback() + return xerrors.Errorf("error computing tipset cid: %w", err) + } + + tskey := tscid.String() + epoch := int64(curTs.Height()) + + msgs, err := cs.MessagesForTipset(lctx, curTs) + if err != nil { + log.Infof("stopping import after %d tipsets", startHeight-curTs.Height()) + break + } + + for _, msg := range msgs { + key := msg.Cid().String() + if _, err := insertStmt.Exec(key, tskey, epoch); err != nil { + rollback() + return xerrors.Errorf("error inserting message: %w", err) + } + } + + curTs, err = cs.GetTipSetFromKey(lctx, curTs.Parents()) + if err != nil { + rollback() + return xerrors.Errorf("error walking chain: %w", err) + } + } + + err = tx.Commit() + if err != nil { + return xerrors.Errorf("error committing transaction: %w", err) + } + + return nil +} + +// init utilities +func prepareDB(db *sql.DB) error { + for _, stmt := range dbDefs { + if _, err := db.Exec(stmt); err != nil { + return xerrors.Errorf("error executing sql statement '%s': %w", stmt, err) + } + } + + for _, stmt := range dbPragmas { + if _, err := db.Exec(stmt); err != nil { + return xerrors.Errorf("error executing sql statement '%s': %w", stmt, err) + } + } + + return nil +} + +func reconcileIndex(db *sql.DB, cs ChainStore) error { + // Invariant: after reconciliation, every tipset in the index is in the current chain; ie either + // the chain head or reachable by walking the chain. + // Algorithm: + // 1. Count messages in index; if none, trivially reconciled. + // TODO we may consider populating the index in that case + // 2. Find the minimum tipset in the index; this will mark the end of the reconciliation walk + // 3. Walk from current tipset until we find a tipset in the index. + // 4. Delete (revert!) all tipsets above the found tipset. + // 5. If the walk ends in the boundary epoch, then delete everything. + // + + row := db.QueryRow(dbqCountMessages) + + var result int64 + if err := row.Scan(&result); err != nil { + return xerrors.Errorf("error counting messages: %w", err) + } + + if result == 0 { + return nil + } + + row = db.QueryRow(dbqMinEpoch) + if err := row.Scan(&result); err != nil { + return xerrors.Errorf("error finding boundary epoch: %w", err) + } + + boundaryEpoch := abi.ChainEpoch(result) + + countMsgsStmt, err := db.Prepare(dbqCountTipsetMessages) + if err != nil { + return xerrors.Errorf("error preparing statement: %w", err) + } + + curTs := cs.GetHeaviestTipSet() + for curTs != nil && curTs.Height() >= boundaryEpoch { + tsCid, err := curTs.Key().Cid() + if err != nil { + return xerrors.Errorf("error computing tipset cid: %w", err) + } + + key := tsCid.String() + row = countMsgsStmt.QueryRow(key) + if err := row.Scan(&result); err != nil { + return xerrors.Errorf("error counting messages: %w", err) + } + + if result > 0 { + // found it! + boundaryEpoch = curTs.Height() + 1 + break + } + + // walk up + parents := curTs.Parents() + curTs, err = cs.GetTipSetFromKey(context.TODO(), parents) + if err != nil { + return xerrors.Errorf("error walking chain: %w", err) + } + } + + // delete everything above the minEpoch + if _, err = db.Exec(dbqDeleteMessagesByEpoch, int64(boundaryEpoch)); err != nil { + return xerrors.Errorf("error deleting stale reorged out message: %w", err) + } + + return nil +} + +func (x *msgIndex) prepareStatements() error { + stmt, err := x.db.Prepare(dbqGetMessageInfo) + if err != nil { + return xerrors.Errorf("prepare selectMsgStmt: %w", err) + } + x.selectMsgStmt = stmt + + stmt, err = x.db.Prepare(dbqInsertMessage) + if err != nil { + return xerrors.Errorf("prepare insertMsgStmt: %w", err) + } + x.insertMsgStmt = stmt + + stmt, err = x.db.Prepare(dbqDeleteTipsetMessages) + if err != nil { + return xerrors.Errorf("prepare deleteTipSetStmt: %w", err) + } + x.deleteTipSetStmt = stmt + + return nil +} + +// head change notifee +func (x *msgIndex) onHeadChange(rev, app []*types.TipSet) error { + x.closeLk.RLock() + defer x.closeLk.RUnlock() + + if x.closed { + return nil + } + + // do it in the background to avoid blocking head change processing + x.mx.Lock() + x.pend = append(x.pend, headChange{rev: rev, app: app}) + pendLen := len(x.pend) + x.mx.Unlock() + + // complain loudly if this is building backlog + if pendLen > 10 { + log.Warnf("message index head change processing is building backlog: %d pending head changes", pendLen) + } + + select { + case x.sema <- struct{}{}: + default: + } + + return nil +} + +func (x *msgIndex) background(ctx context.Context) { + defer x.workers.Done() + + for { + select { + case <-x.sema: + err := x.processHeadChanges(ctx) + if err != nil { + // we can't rely on an inconsistent index, so shut it down. + log.Errorf("error processing head change notifications: %s; shutting down message index", err) + if err2 := x.Close(); err2 != nil { + log.Errorf("error shutting down index: %s", err2) + } + } + + case <-ctx.Done(): + return + } + } +} + +func (x *msgIndex) processHeadChanges(ctx context.Context) error { + x.mx.Lock() + pend := x.pend + x.pend = nil + x.mx.Unlock() + + tx, err := x.db.Begin() + if err != nil { + return xerrors.Errorf("error creating transaction: %w", err) + } + + for _, hc := range pend { + for _, ts := range hc.rev { + if err := x.doRevert(ctx, tx, ts); err != nil { + if err2 := tx.Rollback(); err2 != nil { + log.Errorf("error rolling back transaction: %s", err2) + } + return xerrors.Errorf("error reverting %s: %w", ts, err) + } + } + + for _, ts := range hc.app { + if err := x.doApply(ctx, tx, ts); err != nil { + if err2 := tx.Rollback(); err2 != nil { + log.Errorf("error rolling back transaction: %s", err2) + } + return xerrors.Errorf("error applying %s: %w", ts, err) + } + } + } + + return tx.Commit() +} + +func (x *msgIndex) doRevert(ctx context.Context, tx *sql.Tx, ts *types.TipSet) error { + tskey, err := ts.Key().Cid() + if err != nil { + return xerrors.Errorf("error computing tipset cid: %w", err) + } + + key := tskey.String() + _, err = tx.Stmt(x.deleteTipSetStmt).Exec(key) + return err +} + +func (x *msgIndex) doApply(ctx context.Context, tx *sql.Tx, ts *types.TipSet) error { + tscid, err := ts.Key().Cid() + if err != nil { + return xerrors.Errorf("error computing tipset cid: %w", err) + } + + tskey := tscid.String() + epoch := int64(ts.Height()) + + msgs, err := x.cs.MessagesForTipset(ctx, ts) + if err != nil { + return xerrors.Errorf("error retrieving messages for tipset %s: %w", ts, err) + } + + insertStmt := tx.Stmt(x.insertMsgStmt) + for _, msg := range msgs { + key := msg.Cid().String() + if _, err := insertStmt.Exec(key, tskey, epoch); err != nil { + return xerrors.Errorf("error inserting message: %w", err) + } + } + + return nil +} + +// interface +func (x *msgIndex) GetMsgInfo(ctx context.Context, m cid.Cid) (MsgInfo, error) { + x.closeLk.RLock() + defer x.closeLk.RUnlock() + + if x.closed { + return MsgInfo{}, ErrClosed + } + + var ( + tipset string + epoch int64 + ) + + key := m.String() + row := x.selectMsgStmt.QueryRow(key) + err := row.Scan(&tipset, &epoch) + switch { + case err == sql.ErrNoRows: + return MsgInfo{}, ErrNotFound + + case err != nil: + return MsgInfo{}, xerrors.Errorf("error querying msgindex database: %w", err) + } + + tipsetCid, err := cid.Decode(tipset) + if err != nil { + return MsgInfo{}, xerrors.Errorf("error decoding tipset cid: %w", err) + } + + return MsgInfo{ + Message: m, + TipSet: tipsetCid, + Epoch: abi.ChainEpoch(epoch), + }, nil +} + +func (x *msgIndex) Close() error { + x.closeLk.Lock() + defer x.closeLk.Unlock() + + if x.closed { + return nil + } + + x.closed = true + + x.cancel() + x.workers.Wait() + + return x.db.Close() +} + +// informal apis for itests; not exposed in the main interface +func (x *msgIndex) CountMessages() (int64, error) { + x.closeLk.RLock() + defer x.closeLk.RUnlock() + + if x.closed { + return 0, ErrClosed + } + + var result int64 + row := x.db.QueryRow(dbqCountMessages) + err := row.Scan(&result) + return result, err +} diff --git a/chain/index/msgindex_test.go b/chain/index/msgindex_test.go new file mode 100644 index 000000000..bf4bc6190 --- /dev/null +++ b/chain/index/msgindex_test.go @@ -0,0 +1,307 @@ +package index + +import ( + "context" + "errors" + "math/rand" + "os" + "testing" + "time" + + blocks "github.com/ipfs/go-block-format" + "github.com/ipfs/go-cid" + "github.com/stretchr/testify/require" + + "github.com/filecoin-project/go-address" + + "github.com/filecoin-project/lotus/chain/store" + "github.com/filecoin-project/lotus/chain/types" + "github.com/filecoin-project/lotus/chain/types/mock" +) + +func TestBasicMsgIndex(t *testing.T) { + // the most basic of tests: + // 1. Create an index with mock chain store + // 2. Advance the chain for a few tipsets + // 3. Verify that the index contains all messages with the correct tipset/epoch + cs := newMockChainStore() + cs.genesis() + + tmp := t.TempDir() + t.Cleanup(func() { _ = os.RemoveAll(tmp) }) + + msgIndex, err := NewMsgIndex(context.Background(), tmp, cs) + require.NoError(t, err) + + defer msgIndex.Close() //nolint + + for i := 0; i < 10; i++ { + t.Logf("advance to epoch %d", i+1) + err := cs.advance() + require.NoError(t, err) + } + + waitForCoalescerAfterLastEvent() + + t.Log("verifying index") + verifyIndex(t, cs, msgIndex) +} + +func TestReorgMsgIndex(t *testing.T) { + // slightly more nuanced test that includes reorgs + // 1. Create an index with mock chain store + // 2. Advance/Reorg the chain for a few tipsets + // 3. Verify that the index contains all messages with the correct tipset/epoch + cs := newMockChainStore() + cs.genesis() + + tmp := t.TempDir() + t.Cleanup(func() { _ = os.RemoveAll(tmp) }) + + msgIndex, err := NewMsgIndex(context.Background(), tmp, cs) + require.NoError(t, err) + + defer msgIndex.Close() //nolint + + for i := 0; i < 10; i++ { + t.Logf("advance to epoch %d", i+1) + err := cs.advance() + require.NoError(t, err) + } + + waitForCoalescerAfterLastEvent() + + // a simple reorg + t.Log("doing reorg") + reorgme := cs.curTs + reorgmeParent, err := cs.GetTipSetFromKey(context.Background(), reorgme.Parents()) + require.NoError(t, err) + cs.setHead(reorgmeParent) + reorgmeChild := cs.makeBlk() + err = cs.reorg([]*types.TipSet{reorgme}, []*types.TipSet{reorgmeChild}) + require.NoError(t, err) + + waitForCoalescerAfterLastEvent() + + t.Log("verifying index") + verifyIndex(t, cs, msgIndex) + + t.Log("verifying that reorged messages are not present") + verifyMissing(t, cs, msgIndex, reorgme) +} + +func TestReconcileMsgIndex(t *testing.T) { + // test that exercises the reconciliation code paths + // 1. Create and populate a basic msgindex, similar to TestBasicMsgIndex. + // 2. Close it + // 3. Reorg the mock chain store + // 4. Reopen the index to trigger reconciliation + // 5. Enxure that only the stable messages remain. + cs := newMockChainStore() + cs.genesis() + + tmp := t.TempDir() + t.Cleanup(func() { _ = os.RemoveAll(tmp) }) + + msgIndex, err := NewMsgIndex(context.Background(), tmp, cs) + require.NoError(t, err) + + for i := 0; i < 10; i++ { + t.Logf("advance to epoch %d", i+1) + err := cs.advance() + require.NoError(t, err) + } + + waitForCoalescerAfterLastEvent() + + // Close it and reorg + err = msgIndex.Close() + require.NoError(t, err) + cs.notify = nil + + // a simple reorg + t.Log("doing reorg") + reorgme := cs.curTs + reorgmeParent, err := cs.GetTipSetFromKey(context.Background(), reorgme.Parents()) + require.NoError(t, err) + cs.setHead(reorgmeParent) + reorgmeChild := cs.makeBlk() + err = cs.reorg([]*types.TipSet{reorgme}, []*types.TipSet{reorgmeChild}) + require.NoError(t, err) + + // reopen to reconcile + msgIndex, err = NewMsgIndex(context.Background(), tmp, cs) + require.NoError(t, err) + + defer msgIndex.Close() //nolint + + t.Log("verifying index") + // need to step one up because the last tipset is not known by the index + cs.setHead(reorgmeParent) + verifyIndex(t, cs, msgIndex) + + t.Log("verifying that reorged and unknown messages are not present") + verifyMissing(t, cs, msgIndex, reorgme, reorgmeChild) +} + +func verifyIndex(t *testing.T, cs *mockChainStore, msgIndex MsgIndex) { + for ts := cs.curTs; ts.Height() > 0; { + t.Logf("verify at height %d", ts.Height()) + blks := ts.Blocks() + if len(blks) == 0 { + break + } + + tsCid, err := ts.Key().Cid() + require.NoError(t, err) + + msgs, err := cs.MessagesForTipset(context.Background(), ts) + require.NoError(t, err) + for _, m := range msgs { + minfo, err := msgIndex.GetMsgInfo(context.Background(), m.Cid()) + require.NoError(t, err) + require.Equal(t, tsCid, minfo.TipSet) + require.Equal(t, ts.Height(), minfo.Epoch) + } + + parents := ts.Parents() + ts, err = cs.GetTipSetFromKey(context.Background(), parents) + require.NoError(t, err) + } +} + +func verifyMissing(t *testing.T, cs *mockChainStore, msgIndex MsgIndex, missing ...*types.TipSet) { + for _, ts := range missing { + msgs, err := cs.MessagesForTipset(context.Background(), ts) + require.NoError(t, err) + for _, m := range msgs { + _, err := msgIndex.GetMsgInfo(context.Background(), m.Cid()) + require.Equal(t, ErrNotFound, err) + } + } +} + +type mockChainStore struct { + notify store.ReorgNotifee + + curTs *types.TipSet + tipsets map[types.TipSetKey]*types.TipSet + msgs map[types.TipSetKey][]types.ChainMsg + + nonce uint64 +} + +var _ ChainStore = (*mockChainStore)(nil) + +var systemAddr address.Address +var rng *rand.Rand + +func init() { + systemAddr, _ = address.NewIDAddress(0) + rng = rand.New(rand.NewSource(314159)) + + // adjust those to make tests snappy + CoalesceMinDelay = 100 * time.Millisecond + CoalesceMaxDelay = time.Second + CoalesceMergeInterval = 100 * time.Millisecond +} + +func newMockChainStore() *mockChainStore { + return &mockChainStore{ + tipsets: make(map[types.TipSetKey]*types.TipSet), + msgs: make(map[types.TipSetKey][]types.ChainMsg), + } +} + +func (cs *mockChainStore) genesis() { + genBlock := mock.MkBlock(nil, 0, 0) + genTs := mock.TipSet(genBlock) + cs.msgs[genTs.Key()] = nil + cs.setHead(genTs) +} + +func (cs *mockChainStore) setHead(ts *types.TipSet) { + cs.curTs = ts + cs.tipsets[ts.Key()] = ts +} + +func (cs *mockChainStore) advance() error { + ts := cs.makeBlk() + return cs.reorg(nil, []*types.TipSet{ts}) +} + +func (cs *mockChainStore) reorg(rev, app []*types.TipSet) error { + for _, ts := range rev { + parents := ts.Parents() + cs.curTs = cs.tipsets[parents] + } + + for _, ts := range app { + cs.tipsets[ts.Key()] = ts + cs.curTs = ts + } + + if cs.notify != nil { + return cs.notify(rev, app) + } + + return nil +} + +func (cs *mockChainStore) makeBlk() *types.TipSet { + height := cs.curTs.Height() + 1 + + blk := mock.MkBlock(cs.curTs, uint64(height), uint64(height)) + blk.Messages = cs.makeGarbageCid() + + ts := mock.TipSet(blk) + msg1 := cs.makeMsg() + msg2 := cs.makeMsg() + cs.msgs[ts.Key()] = []types.ChainMsg{msg1, msg2} + + return ts +} + +func (cs *mockChainStore) makeMsg() *types.Message { + nonce := cs.nonce + cs.nonce++ + return &types.Message{To: systemAddr, From: systemAddr, Nonce: nonce} +} + +func (cs *mockChainStore) makeGarbageCid() cid.Cid { + garbage := blocks.NewBlock([]byte{byte(rng.Intn(256)), byte(rng.Intn(256)), byte(rng.Intn(256))}) + return garbage.Cid() +} + +func (cs *mockChainStore) SubscribeHeadChanges(f store.ReorgNotifee) { + cs.notify = f +} + +func (cs *mockChainStore) MessagesForTipset(ctx context.Context, ts *types.TipSet) ([]types.ChainMsg, error) { + msgs, ok := cs.msgs[ts.Key()] + if !ok { + return nil, errors.New("unknown tipset") + } + + return msgs, nil +} + +func (cs *mockChainStore) GetHeaviestTipSet() *types.TipSet { + return cs.curTs +} + +func (cs *mockChainStore) GetTipSetFromKey(ctx context.Context, tsk types.TipSetKey) (*types.TipSet, error) { + ts, ok := cs.tipsets[tsk] + if !ok { + return nil, errors.New("unknown tipset") + } + return ts, nil +} + +func waitForCoalescerAfterLastEvent() { + // It can take up to CoalesceMinDelay for the coalescer timer to fire after the last event. + // When the timer fires, it can wait up to CoalesceMinDelay again for more events. + // Therefore the total wait is 2 * CoalesceMinDelay. + // Then we wait another second for the listener (the index) to actually process events. + time.Sleep(2*CoalesceMinDelay + time.Second) +} diff --git a/chain/messagepool/check.go b/chain/messagepool/check.go index b1e2a2778..17829057a 100644 --- a/chain/messagepool/check.go +++ b/chain/messagepool/check.go @@ -32,14 +32,18 @@ func (mp *MessagePool) CheckMessages(ctx context.Context, protos []*api.MessageP // CheckPendingMessages performs a set of logical sets for all messages pending from a given actor func (mp *MessagePool) CheckPendingMessages(ctx context.Context, from address.Address) ([][]api.MessageCheckStatus, error) { var msgs []*types.Message - mp.lk.Lock() - mset, ok := mp.pending[from] + mp.lk.RLock() + mset, ok, err := mp.getPendingMset(ctx, from) + if err != nil { + return nil, xerrors.Errorf("errored while getting pending mset: %w", err) + } if ok { + msgs = make([]*types.Message, 0, len(mset.msgs)) for _, sm := range mset.msgs { msgs = append(msgs, &sm.Message) } } - mp.lk.Unlock() + mp.lk.RUnlock() if len(msgs) == 0 { return nil, nil @@ -58,13 +62,16 @@ func (mp *MessagePool) CheckReplaceMessages(ctx context.Context, replace []*type msgMap := make(map[address.Address]map[uint64]*types.Message) count := 0 - mp.lk.Lock() + mp.lk.RLock() for _, m := range replace { mmap, ok := msgMap[m.From] if !ok { mmap = make(map[uint64]*types.Message) msgMap[m.From] = mmap - mset, ok := mp.pending[m.From] + mset, ok, err := mp.getPendingMset(ctx, m.From) + if err != nil { + return nil, xerrors.Errorf("errored while getting pending mset: %w", err) + } if ok { count += len(mset.msgs) for _, sm := range mset.msgs { @@ -76,7 +83,7 @@ func (mp *MessagePool) CheckReplaceMessages(ctx context.Context, replace []*type } mmap[m.Nonce] = m } - mp.lk.Unlock() + mp.lk.RUnlock() msgs := make([]*types.Message, 0, count) start := 0 @@ -103,9 +110,9 @@ func (mp *MessagePool) checkMessages(ctx context.Context, msgs []*types.Message, if mp.api.IsLite() { return nil, nil } - mp.curTsLk.Lock() + mp.curTsLk.RLock() curTs := mp.curTs - mp.curTsLk.Unlock() + mp.curTsLk.RUnlock() epoch := curTs.Height() + 1 @@ -143,22 +150,25 @@ func (mp *MessagePool) checkMessages(ctx context.Context, msgs []*types.Message, st, ok := state[m.From] if !ok { - mp.lk.Lock() - mset, ok := mp.pending[m.From] + mp.lk.RLock() + mset, ok, err := mp.getPendingMset(ctx, m.From) + if err != nil { + return nil, xerrors.Errorf("errored while getting pending mset: %w", err) + } if ok && !interned { st = &actorState{nextNonce: mset.nextNonce, requiredFunds: mset.requiredFunds} for _, m := range mset.msgs { st.requiredFunds = new(stdbig.Int).Add(st.requiredFunds, m.Message.Value.Int) } state[m.From] = st - mp.lk.Unlock() + mp.lk.RUnlock() check.OK = true check.Hint = map[string]interface{}{ "nonce": st.nextNonce, } } else { - mp.lk.Unlock() + mp.lk.RUnlock() stateNonce, err := mp.getStateNonce(ctx, m.From, curTs) if err != nil { diff --git a/chain/messagepool/messagepool.go b/chain/messagepool/messagepool.go index 0d787bd50..50f64f903 100644 --- a/chain/messagepool/messagepool.go +++ b/chain/messagepool/messagepool.go @@ -118,7 +118,7 @@ func init() { } type MessagePool struct { - lk sync.Mutex + lk sync.RWMutex ds dtypes.MetadataDS @@ -137,9 +137,9 @@ type MessagePool struct { // do NOT access this map directly, use getPendingMset, setPendingMset, deletePendingMset, forEachPending, and clearPending respectively pending map[address.Address]*msgSet - keyCache map[address.Address]address.Address + keyCache *lru.Cache[address.Address, address.Address] - curTsLk sync.Mutex // DO NOT LOCK INSIDE lk + curTsLk sync.RWMutex // DO NOT LOCK INSIDE lk curTs *types.TipSet cfgLk sync.RWMutex @@ -169,13 +169,13 @@ type MessagePool struct { sigValCache *lru.TwoQueueCache[string, struct{}] - nonceCache *lru.Cache[nonceCacheKey, uint64] + stateNonceCache *lru.Cache[stateNonceCacheKey, uint64] evtTypes [3]journal.EventType journal journal.Journal } -type nonceCacheKey struct { +type stateNonceCacheKey struct { tsk types.TipSetKey addr address.Address } @@ -371,7 +371,8 @@ func (ms *msgSet) toSlice() []*types.SignedMessage { func New(ctx context.Context, api Provider, ds dtypes.MetadataDS, us stmgr.UpgradeSchedule, netName dtypes.NetworkName, j journal.Journal) (*MessagePool, error) { cache, _ := lru.New2Q[cid.Cid, crypto.Signature](build.BlsSignatureCacheSize) verifcache, _ := lru.New2Q[string, struct{}](build.VerifSigCacheSize) - noncecache, _ := lru.New[nonceCacheKey, uint64](256) + stateNonceCache, _ := lru.New[stateNonceCacheKey, uint64](32768) // 32k * ~200 bytes = 6MB + keycache, _ := lru.New[address.Address, address.Address](1_000_000) cfg, err := loadConfig(ctx, ds) if err != nil { @@ -383,26 +384,26 @@ func New(ctx context.Context, api Provider, ds dtypes.MetadataDS, us stmgr.Upgra } mp := &MessagePool{ - ds: ds, - addSema: make(chan struct{}, 1), - closer: make(chan struct{}), - repubTk: build.Clock.Ticker(RepublishInterval), - repubTrigger: make(chan struct{}, 1), - localAddrs: make(map[address.Address]struct{}), - pending: make(map[address.Address]*msgSet), - keyCache: make(map[address.Address]address.Address), - minGasPrice: types.NewInt(0), - getNtwkVersion: us.GetNtwkVersion, - pruneTrigger: make(chan struct{}, 1), - pruneCooldown: make(chan struct{}, 1), - blsSigCache: cache, - sigValCache: verifcache, - nonceCache: noncecache, - changes: lps.New(50), - localMsgs: namespace.Wrap(ds, datastore.NewKey(localMsgsDs)), - api: api, - netName: netName, - cfg: cfg, + ds: ds, + addSema: make(chan struct{}, 1), + closer: make(chan struct{}), + repubTk: build.Clock.Ticker(RepublishInterval), + repubTrigger: make(chan struct{}, 1), + localAddrs: make(map[address.Address]struct{}), + pending: make(map[address.Address]*msgSet), + keyCache: keycache, + minGasPrice: types.NewInt(0), + getNtwkVersion: us.GetNtwkVersion, + pruneTrigger: make(chan struct{}, 1), + pruneCooldown: make(chan struct{}, 1), + blsSigCache: cache, + sigValCache: verifcache, + stateNonceCache: stateNonceCache, + changes: lps.New(50), + localMsgs: namespace.Wrap(ds, datastore.NewKey(localMsgsDs)), + api: api, + netName: netName, + cfg: cfg, evtTypes: [...]journal.EventType{ evtTypeMpoolAdd: j.RegisterEventType("mpool", "add"), evtTypeMpoolRemove: j.RegisterEventType("mpool", "remove"), @@ -447,12 +448,8 @@ func New(ctx context.Context, api Provider, ds dtypes.MetadataDS, us stmgr.Upgra return mp, nil } -func (mp *MessagePool) TryForEachPendingMessage(f func(cid.Cid) error) error { - // avoid deadlocks in splitstore compaction when something else needs to access the blockstore - // while holding the mpool lock - if !mp.lk.TryLock() { - return xerrors.Errorf("mpool TryForEachPendingMessage: could not acquire lock") - } +func (mp *MessagePool) ForEachPendingMessage(f func(cid.Cid) error) error { + mp.lk.Lock() defer mp.lk.Unlock() for _, mset := range mp.pending { @@ -473,9 +470,18 @@ func (mp *MessagePool) TryForEachPendingMessage(f func(cid.Cid) error) error { } func (mp *MessagePool) resolveToKey(ctx context.Context, addr address.Address) (address.Address, error) { + //if addr is not an ID addr, then it is already resolved to a key + if addr.Protocol() != address.ID { + return addr, nil + } + return mp.resolveToKeyFromID(ctx, addr) +} + +func (mp *MessagePool) resolveToKeyFromID(ctx context.Context, addr address.Address) (address.Address, error) { + // check the cache - a, f := mp.keyCache[addr] - if f { + a, ok := mp.keyCache.Get(addr) + if ok { return a, nil } @@ -486,9 +492,7 @@ func (mp *MessagePool) resolveToKey(ctx context.Context, addr address.Address) ( } // place both entries in the cache (may both be key addresses, which is fine) - mp.keyCache[addr] = ka - mp.keyCache[ka] = ka - + mp.keyCache.Add(addr, ka) return ka, nil } @@ -741,8 +745,7 @@ func (mp *MessagePool) checkMessage(ctx context.Context, m *types.SignedMessage) } if err := mp.VerifyMsgSig(m); err != nil { - log.Warnf("signature verification failed: %s", err) - return err + return xerrors.Errorf("signature verification failed: %s", err) } return nil @@ -763,7 +766,28 @@ func (mp *MessagePool) Add(ctx context.Context, m *types.SignedMessage) error { <-mp.addSema }() + mp.curTsLk.RLock() + tmpCurTs := mp.curTs + mp.curTsLk.RUnlock() + + //ensures computations are cached without holding lock + _, _ = mp.api.GetActorAfter(m.Message.From, tmpCurTs) + _, _ = mp.getStateNonce(ctx, m.Message.From, tmpCurTs) + mp.curTsLk.Lock() + if tmpCurTs == mp.curTs { + //with the lock enabled, mp.curTs is the same Ts as we just had, so we know that our computations are cached + } else { + //curTs has been updated so we want to cache the new one: + tmpCurTs = mp.curTs + //we want to release the lock, cache the computations then grab it again + mp.curTsLk.Unlock() + _, _ = mp.api.GetActorAfter(m.Message.From, tmpCurTs) + _, _ = mp.getStateNonce(ctx, m.Message.From, tmpCurTs) + mp.curTsLk.Lock() + //now that we have the lock, we continue, we could do this as a loop forever, but that's bad to loop forever, and this was added as an optimization and it seems once is enough because the computation < block time + } + defer mp.curTsLk.Unlock() _, err = mp.addTs(ctx, m, mp.curTs, false, false) @@ -852,9 +876,6 @@ func (mp *MessagePool) addTs(ctx context.Context, m *types.SignedMessage, curTs return false, xerrors.Errorf("minimum expected nonce is %d: %w", snonce, ErrNonceTooLow) } - mp.lk.Lock() - defer mp.lk.Unlock() - senderAct, err := mp.api.GetActorAfter(m.Message.From, curTs) if err != nil { return false, xerrors.Errorf("failed to get sender actor: %w", err) @@ -869,6 +890,9 @@ func (mp *MessagePool) addTs(ctx context.Context, m *types.SignedMessage, curTs return false, xerrors.Errorf("sender actor %s is not a valid top-level sender", m.Message.From) } + mp.lk.Lock() + defer mp.lk.Unlock() + publish, err := mp.verifyMsgBeforeAdd(ctx, m, curTs, local) if err != nil { return false, xerrors.Errorf("verify msg failed: %w", err) @@ -940,13 +964,11 @@ func (mp *MessagePool) addLocked(ctx context.Context, m *types.SignedMessage, st } if _, err := mp.api.PutMessage(ctx, m); err != nil { - log.Warnf("mpooladd cs.PutMessage failed: %s", err) - return err + return xerrors.Errorf("mpooladd cs.PutMessage failed: %s", err) } if _, err := mp.api.PutMessage(ctx, &m.Message); err != nil { - log.Warnf("mpooladd cs.PutMessage failed: %s", err) - return err + return xerrors.Errorf("mpooladd cs.PutMessage failed: %s", err) } // Note: If performance becomes an issue, making this getOrCreatePendingMset will save some work @@ -1001,19 +1023,19 @@ func (mp *MessagePool) addLocked(ctx context.Context, m *types.SignedMessage, st } func (mp *MessagePool) GetNonce(ctx context.Context, addr address.Address, _ types.TipSetKey) (uint64, error) { - mp.curTsLk.Lock() - defer mp.curTsLk.Unlock() + mp.curTsLk.RLock() + defer mp.curTsLk.RUnlock() - mp.lk.Lock() - defer mp.lk.Unlock() + mp.lk.RLock() + defer mp.lk.RUnlock() return mp.getNonceLocked(ctx, addr, mp.curTs) } // GetActor should not be used. It is only here to satisfy interface mess caused by lite node handling func (mp *MessagePool) GetActor(_ context.Context, addr address.Address, _ types.TipSetKey) (*types.Actor, error) { - mp.curTsLk.Lock() - defer mp.curTsLk.Unlock() + mp.curTsLk.RLock() + defer mp.curTsLk.RUnlock() return mp.api.GetActorAfter(addr, mp.curTs) } @@ -1046,24 +1068,52 @@ func (mp *MessagePool) getStateNonce(ctx context.Context, addr address.Address, done := metrics.Timer(ctx, metrics.MpoolGetNonceDuration) defer done() - nk := nonceCacheKey{ + nk := stateNonceCacheKey{ tsk: ts.Key(), addr: addr, } - n, ok := mp.nonceCache.Get(nk) + n, ok := mp.stateNonceCache.Get(nk) if ok { return n, nil } - act, err := mp.api.GetActorAfter(addr, ts) + // get the nonce from the actor before ts + actor, err := mp.api.GetActorBefore(addr, ts) + if err != nil { + return 0, err + } + nextNonce := actor.Nonce + + raddr, err := mp.resolveToKey(ctx, addr) if err != nil { return 0, err } - mp.nonceCache.Add(nk, act.Nonce) + // loop over all messages sent by 'addr' and find the highest nonce + messages, err := mp.api.MessagesForTipset(ctx, ts) + if err != nil { + return 0, err + } + for _, message := range messages { + msg := message.VMMessage() - return act.Nonce, nil + maddr, err := mp.resolveToKey(ctx, msg.From) + if err != nil { + log.Warnf("failed to resolve message from address: %s", err) + continue + } + + if maddr == raddr { + if n := msg.Nonce + 1; n > nextNonce { + nextNonce = n + } + } + } + + mp.stateNonceCache.Add(nk, nextNonce) + + return nextNonce, nil } func (mp *MessagePool) getStateBalance(ctx context.Context, addr address.Address, ts *types.TipSet) (types.BigInt, error) { @@ -1164,11 +1214,11 @@ func (mp *MessagePool) remove(ctx context.Context, from address.Address, nonce u } func (mp *MessagePool) Pending(ctx context.Context) ([]*types.SignedMessage, *types.TipSet) { - mp.curTsLk.Lock() - defer mp.curTsLk.Unlock() + mp.curTsLk.RLock() + defer mp.curTsLk.RUnlock() - mp.lk.Lock() - defer mp.lk.Unlock() + mp.lk.RLock() + defer mp.lk.RUnlock() return mp.allPending(ctx) } @@ -1184,11 +1234,11 @@ func (mp *MessagePool) allPending(ctx context.Context) ([]*types.SignedMessage, } func (mp *MessagePool) PendingFor(ctx context.Context, a address.Address) ([]*types.SignedMessage, *types.TipSet) { - mp.curTsLk.Lock() - defer mp.curTsLk.Unlock() + mp.curTsLk.RLock() + defer mp.curTsLk.RUnlock() - mp.lk.Lock() - defer mp.lk.Unlock() + mp.lk.RLock() + defer mp.lk.RUnlock() return mp.pendingFor(ctx, a), mp.curTs } @@ -1237,9 +1287,9 @@ func (mp *MessagePool) HeadChange(ctx context.Context, revert []*types.TipSet, a maybeRepub := func(cid cid.Cid) { if !repubTrigger { - mp.lk.Lock() + mp.lk.RLock() _, republished := mp.republished[cid] - mp.lk.Unlock() + mp.lk.RUnlock() if republished { repubTrigger = true } @@ -1310,9 +1360,9 @@ func (mp *MessagePool) HeadChange(ctx context.Context, revert []*types.TipSet, a } if len(revert) > 0 && futureDebug { - mp.lk.Lock() + mp.lk.RLock() msgs, ts := mp.allPending(ctx) - mp.lk.Unlock() + mp.lk.RUnlock() buckets := map[address.Address]*statBucket{} diff --git a/chain/messagepool/messagepool_test.go b/chain/messagepool/messagepool_test.go index 20da2317e..a781b5074 100644 --- a/chain/messagepool/messagepool_test.go +++ b/chain/messagepool/messagepool_test.go @@ -120,6 +120,22 @@ func (tma *testMpoolAPI) PubSubPublish(string, []byte) error { return nil } +func (tma *testMpoolAPI) GetActorBefore(addr address.Address, ts *types.TipSet) (*types.Actor, error) { + balance, ok := tma.balance[addr] + if !ok { + balance = types.NewInt(1000e6) + tma.balance[addr] = balance + } + + nonce := tma.statenonce[addr] + + return &types.Actor{ + Code: builtin2.AccountActorCodeID, + Nonce: nonce, + Balance: balance, + }, nil +} + func (tma *testMpoolAPI) GetActorAfter(addr address.Address, ts *types.TipSet) (*types.Actor, error) { // regression check for load bug if ts == nil { diff --git a/chain/messagepool/provider.go b/chain/messagepool/provider.go index 123a2607e..764e6c13a 100644 --- a/chain/messagepool/provider.go +++ b/chain/messagepool/provider.go @@ -2,6 +2,7 @@ package messagepool import ( "context" + "errors" "time" "github.com/ipfs/go-cid" @@ -27,6 +28,7 @@ type Provider interface { SubscribeHeadChanges(func(rev, app []*types.TipSet) error) *types.TipSet PutMessage(ctx context.Context, m types.ChainMsg) (cid.Cid, error) PubSubPublish(string, []byte) error + GetActorBefore(address.Address, *types.TipSet) (*types.Actor, error) GetActorAfter(address.Address, *types.TipSet) (*types.Actor, error) StateDeterministicAddressAtFinality(context.Context, address.Address, *types.TipSet) (address.Address, error) StateNetworkVersion(context.Context, abi.ChainEpoch) network.Version @@ -58,6 +60,23 @@ func (mpp *mpoolProvider) IsLite() bool { return mpp.lite != nil } +func (mpp *mpoolProvider) getActorLite(addr address.Address, ts *types.TipSet) (*types.Actor, error) { + if !mpp.IsLite() { + return nil, errors.New("should not use getActorLite on non lite Provider") + } + + n, err := mpp.lite.GetNonce(context.TODO(), addr, ts.Key()) + if err != nil { + return nil, xerrors.Errorf("getting nonce over lite: %w", err) + } + a, err := mpp.lite.GetActor(context.TODO(), addr, ts.Key()) + if err != nil { + return nil, xerrors.Errorf("getting actor over lite: %w", err) + } + a.Nonce = n + return a, nil +} + func (mpp *mpoolProvider) SubscribeHeadChanges(cb func(rev, app []*types.TipSet) error) *types.TipSet { mpp.sm.ChainStore().SubscribeHeadChanges( store.WrapHeadChangeCoalescer( @@ -77,18 +96,17 @@ func (mpp *mpoolProvider) PubSubPublish(k string, v []byte) error { return mpp.ps.Publish(k, v) // nolint } +func (mpp *mpoolProvider) GetActorBefore(addr address.Address, ts *types.TipSet) (*types.Actor, error) { + if mpp.IsLite() { + return mpp.getActorLite(addr, ts) + } + + return mpp.sm.LoadActor(context.TODO(), addr, ts) +} + func (mpp *mpoolProvider) GetActorAfter(addr address.Address, ts *types.TipSet) (*types.Actor, error) { if mpp.IsLite() { - n, err := mpp.lite.GetNonce(context.TODO(), addr, ts.Key()) - if err != nil { - return nil, xerrors.Errorf("getting nonce over lite: %w", err) - } - a, err := mpp.lite.GetActor(context.TODO(), addr, ts.Key()) - if err != nil { - return nil, xerrors.Errorf("getting actor over lite: %w", err) - } - a.Nonce = n - return a, nil + return mpp.getActorLite(addr, ts) } stcid, _, err := mpp.sm.TipSetState(context.TODO(), ts) diff --git a/chain/messagepool/repub.go b/chain/messagepool/repub.go index 9a1e19b60..a87d5e08a 100644 --- a/chain/messagepool/repub.go +++ b/chain/messagepool/repub.go @@ -20,19 +20,23 @@ const repubMsgLimit = 30 var RepublishBatchDelay = 100 * time.Millisecond func (mp *MessagePool) republishPendingMessages(ctx context.Context) error { - mp.curTsLk.Lock() + mp.curTsLk.RLock() ts := mp.curTs + mp.curTsLk.RUnlock() baseFee, err := mp.api.ChainComputeBaseFee(context.TODO(), ts) if err != nil { - mp.curTsLk.Unlock() return xerrors.Errorf("computing basefee: %w", err) } baseFeeLowerBound := getBaseFeeLowerBound(baseFee, baseFeeLowerBoundFactor) pending := make(map[address.Address]map[uint64]*types.SignedMessage) + mp.lk.Lock() mp.republished = nil // clear this to avoid races triggering an early republish + mp.lk.Unlock() + + mp.lk.RLock() mp.forEachLocal(ctx, func(ctx context.Context, actor address.Address) { mset, ok, err := mp.getPendingMset(ctx, actor) if err != nil { @@ -53,9 +57,7 @@ func (mp *MessagePool) republishPendingMessages(ctx context.Context) error { } pending[actor] = pend }) - - mp.lk.Unlock() - mp.curTsLk.Unlock() + mp.lk.RUnlock() if len(pending) == 0 { return nil @@ -176,8 +178,8 @@ loop: republished[m.Cid()] = struct{}{} } - mp.lk.Lock() // update the republished set so that we can trigger early republish from head changes + mp.lk.Lock() mp.republished = republished mp.lk.Unlock() diff --git a/chain/messagepool/selection.go b/chain/messagepool/selection.go index bd5044128..163bd76f9 100644 --- a/chain/messagepool/selection.go +++ b/chain/messagepool/selection.go @@ -40,11 +40,21 @@ type msgChain struct { } func (mp *MessagePool) SelectMessages(ctx context.Context, ts *types.TipSet, tq float64) ([]*types.SignedMessage, error) { - mp.curTsLk.Lock() - defer mp.curTsLk.Unlock() + mp.curTsLk.RLock() + defer mp.curTsLk.RUnlock() - mp.lk.Lock() - defer mp.lk.Unlock() + mp.lk.RLock() + defer mp.lk.RUnlock() + + // See if we need to prune before selection; excessive buildup can lead to slow selection, + // so prune if we have too many messages (ignoring the cooldown). + mpCfg := mp.getConfig() + if mp.currentSize > mpCfg.SizeLimitHigh { + log.Infof("too many messages; pruning before selection") + if err := mp.pruneMessages(ctx, ts); err != nil { + log.Warnf("error pruning excess messages: %s", err) + } + } // if the ticket quality is high enough that the first block has higher probability // than any other block, then we don't bother with optimal selection because the diff --git a/chain/stmgr/execute.go b/chain/stmgr/execute.go index f85ff7c04..bed857833 100644 --- a/chain/stmgr/execute.go +++ b/chain/stmgr/execute.go @@ -128,10 +128,47 @@ func (sm *StateManager) ExecutionTraceWithMonitor(ctx context.Context, ts *types } func (sm *StateManager) ExecutionTrace(ctx context.Context, ts *types.TipSet) (cid.Cid, []*api.InvocResult, error) { + tsKey := ts.Key() + + // check if we have the trace for this tipset in the cache + if execTraceCacheSize > 0 { + sm.execTraceCacheLock.Lock() + if entry, ok := sm.execTraceCache.Get(tsKey); ok { + // we have to make a deep copy since caller can modify the invocTrace + // and we don't want that to change what we store in cache + invocTraceCopy := makeDeepCopy(entry.invocTrace) + sm.execTraceCacheLock.Unlock() + return entry.postStateRoot, invocTraceCopy, nil + } + sm.execTraceCacheLock.Unlock() + } + var invocTrace []*api.InvocResult st, err := sm.ExecutionTraceWithMonitor(ctx, ts, &InvocationTracer{trace: &invocTrace}) if err != nil { return cid.Undef, nil, err } + + if execTraceCacheSize > 0 { + invocTraceCopy := makeDeepCopy(invocTrace) + + sm.execTraceCacheLock.Lock() + sm.execTraceCache.Add(tsKey, tipSetCacheEntry{st, invocTraceCopy}) + sm.execTraceCacheLock.Unlock() + } + return st, invocTrace, nil } + +func makeDeepCopy(invocTrace []*api.InvocResult) []*api.InvocResult { + c := make([]*api.InvocResult, len(invocTrace)) + for i, ir := range invocTrace { + if ir == nil { + continue + } + tmp := *ir + c[i] = &tmp + } + + return c +} diff --git a/chain/stmgr/forks_test.go b/chain/stmgr/forks_test.go index caf2c22ce..bf8793488 100644 --- a/chain/stmgr/forks_test.go +++ b/chain/stmgr/forks_test.go @@ -36,6 +36,7 @@ import ( "github.com/filecoin-project/lotus/chain/consensus" "github.com/filecoin-project/lotus/chain/consensus/filcns" "github.com/filecoin-project/lotus/chain/gen" + "github.com/filecoin-project/lotus/chain/index" "github.com/filecoin-project/lotus/chain/stmgr" . "github.com/filecoin-project/lotus/chain/stmgr" "github.com/filecoin-project/lotus/chain/types" @@ -168,7 +169,7 @@ func TestForkHeightTriggers(t *testing.T) { } return st.Flush(ctx) - }}}, cg.BeaconSchedule(), datastore.NewMapDatastore()) + }}}, cg.BeaconSchedule(), datastore.NewMapDatastore(), index.DummyMsgIndex) if err != nil { t.Fatal(err) } @@ -286,7 +287,7 @@ func testForkRefuseCall(t *testing.T, nullsBefore, nullsAfter int) { root cid.Cid, height abi.ChainEpoch, ts *types.TipSet) (cid.Cid, error) { migrationCount++ return root, nil - }}}, cg.BeaconSchedule(), datastore.NewMapDatastore()) + }}}, cg.BeaconSchedule(), datastore.NewMapDatastore(), index.DummyMsgIndex) if err != nil { t.Fatal(err) } @@ -504,7 +505,7 @@ func TestForkPreMigration(t *testing.T) { return nil }, }}}, - }, cg.BeaconSchedule(), datastore.NewMapDatastore()) + }, cg.BeaconSchedule(), datastore.NewMapDatastore(), index.DummyMsgIndex) if err != nil { t.Fatal(err) } @@ -579,6 +580,7 @@ func TestDisablePreMigration(t *testing.T) { }, cg.BeaconSchedule(), datastore.NewMapDatastore(), + index.DummyMsgIndex, ) require.NoError(t, err) require.NoError(t, sm.Start(context.Background())) @@ -633,6 +635,7 @@ func TestMigrtionCache(t *testing.T) { }, cg.BeaconSchedule(), metadataDs, + index.DummyMsgIndex, ) require.NoError(t, err) require.NoError(t, sm.Start(context.Background())) @@ -685,6 +688,7 @@ func TestMigrtionCache(t *testing.T) { }, cg.BeaconSchedule(), metadataDs, + index.DummyMsgIndex, ) require.NoError(t, err) sm.SetVMConstructor(func(ctx context.Context, vmopt *vm.VMOpts) (vm.Interface, error) { diff --git a/chain/stmgr/searchwait.go b/chain/stmgr/searchwait.go index 468f33db7..356ace23c 100644 --- a/chain/stmgr/searchwait.go +++ b/chain/stmgr/searchwait.go @@ -10,6 +10,7 @@ import ( "github.com/filecoin-project/go-state-types/abi" + "github.com/filecoin-project/lotus/chain/index" "github.com/filecoin-project/lotus/chain/store" "github.com/filecoin-project/lotus/chain/types" ) @@ -18,6 +19,7 @@ import ( // happened, with an optional limit to how many epochs it will search. It guarantees that the message has been on // chain for at least confidence epochs without being reverted before returning. func (sm *StateManager) WaitForMessage(ctx context.Context, mcid cid.Cid, confidence uint64, lookbackLimit abi.ChainEpoch, allowReplaced bool) (*types.TipSet, *types.MessageReceipt, cid.Cid, error) { + // TODO use the index to speed this up. ctx, cancel := context.WithCancel(ctx) defer cancel() @@ -55,10 +57,15 @@ func (sm *StateManager) WaitForMessage(ctx context.Context, mcid cid.Cid, confid var backFm cid.Cid backSearchWait := make(chan struct{}) go func() { - fts, r, foundMsg, err := sm.searchBackForMsg(ctx, head[0].Val, msg, lookbackLimit, allowReplaced) - if err != nil { - log.Warnf("failed to look back through chain for message: %v", err) - return + fts, r, foundMsg, err := sm.searchForIndexedMsg(ctx, mcid, msg) + + found := (err == nil && r != nil && foundMsg.Defined()) + if !found { + fts, r, foundMsg, err = sm.searchBackForMsg(ctx, head[0].Val, msg, lookbackLimit, allowReplaced) + if err != nil { + log.Warnf("failed to look back through chain for message: %v", err) + return + } } backTs = fts @@ -145,7 +152,30 @@ func (sm *StateManager) SearchForMessage(ctx context.Context, head *types.TipSet return head, r, foundMsg, nil } - fts, r, foundMsg, err := sm.searchBackForMsg(ctx, head, msg, lookbackLimit, allowReplaced) + fts, r, foundMsg, err := sm.searchForIndexedMsg(ctx, mcid, msg) + + switch { + case err == nil: + if r != nil && foundMsg.Defined() { + return fts, r, foundMsg, nil + } + + // debug log this, it's noteworthy + if r == nil { + log.Debugf("missing receipt for message in index for %s", mcid) + } + if !foundMsg.Defined() { + log.Debugf("message %s not found", mcid) + } + + case errors.Is(err, index.ErrNotFound): + // ok for the index to have incomplete data + + default: + log.Warnf("error searching message index: %s", err) + } + + fts, r, foundMsg, err = sm.searchBackForMsg(ctx, head, msg, lookbackLimit, allowReplaced) if err != nil { log.Warnf("failed to look back through chain for message %s", mcid) @@ -159,6 +189,44 @@ func (sm *StateManager) SearchForMessage(ctx context.Context, head *types.TipSet return fts, r, foundMsg, nil } +func (sm *StateManager) searchForIndexedMsg(ctx context.Context, mcid cid.Cid, m types.ChainMsg) (*types.TipSet, *types.MessageReceipt, cid.Cid, error) { + minfo, err := sm.msgIndex.GetMsgInfo(ctx, mcid) + if err != nil { + return nil, nil, cid.Undef, xerrors.Errorf("error looking up message in index: %w", err) + } + + // check the height against the current tipset; minimum execution confidence requires that the + // inclusion tipset height is lower than the current head + 1 + curTs := sm.cs.GetHeaviestTipSet() + if curTs.Height() <= minfo.Epoch+1 { + return nil, nil, cid.Undef, xerrors.Errorf("indexed message does not appear before the current tipset; index epoch: %d, current epoch: %d", minfo.Epoch, curTs.Height()) + } + + // now get the execution tipset + // TODO optimization: the index should have it implicitly so we can return it in the msginfo. + xts, err := sm.cs.GetTipsetByHeight(ctx, minfo.Epoch+1, curTs, false) + if err != nil { + return nil, nil, cid.Undef, xerrors.Errorf("error looking up execution tipset: %w", err) + } + + // check that the parent of the execution index is indeed the inclusion tipset + parent := xts.Parents() + parentCid, err := parent.Cid() + if err != nil { + return nil, nil, cid.Undef, xerrors.Errorf("error computing tipset cid: %w", err) + } + + if !parentCid.Equals(minfo.TipSet) { + return nil, nil, cid.Undef, xerrors.Errorf("inclusion tipset mismatch: have %s, expected %s", parentCid, minfo.TipSet) + } + + r, foundMsg, err := sm.tipsetExecutedMessage(ctx, xts, mcid, m.VMMessage(), false) + if err != nil { + return nil, nil, cid.Undef, xerrors.Errorf("error in tipstExecutedMessage: %w", err) + } + return xts, r, foundMsg, nil +} + // searchBackForMsg searches up to limit tipsets backwards from the given // tipset for a message receipt. // If limit is diff --git a/chain/stmgr/stmgr.go b/chain/stmgr/stmgr.go index 575e6ac2e..12b991e57 100644 --- a/chain/stmgr/stmgr.go +++ b/chain/stmgr/stmgr.go @@ -3,8 +3,11 @@ package stmgr import ( "context" "fmt" + "os" + "strconv" "sync" + lru "github.com/hashicorp/golang-lru/v2" "github.com/ipfs/go-cid" dstore "github.com/ipfs/go-datastore" cbor "github.com/ipfs/go-ipld-cbor" @@ -25,6 +28,7 @@ import ( "github.com/filecoin-project/lotus/chain/actors/builtin/paych" "github.com/filecoin-project/lotus/chain/actors/policy" "github.com/filecoin-project/lotus/chain/beacon" + "github.com/filecoin-project/lotus/chain/index" "github.com/filecoin-project/lotus/chain/rand" "github.com/filecoin-project/lotus/chain/state" "github.com/filecoin-project/lotus/chain/store" @@ -38,6 +42,7 @@ import ( const LookbackNoLimit = api.LookbackNoLimit const ReceiptAmtBitwidth = 3 +var execTraceCacheSize = 16 var log = logging.Logger("statemgr") type StateManagerAPI interface { @@ -70,6 +75,17 @@ func (m *migrationResultCache) keyForMigration(root cid.Cid) dstore.Key { return dstore.NewKey(kStr) } +func init() { + if s := os.Getenv("LOTUS_EXEC_TRACE_CACHE_SIZE"); s != "" { + letc, err := strconv.Atoi(s) + if err != nil { + log.Errorf("failed to parse 'LOTUS_EXEC_TRACE_CACHE_SIZE' env var: %s", err) + } else { + execTraceCacheSize = letc + } + } +} + func (m *migrationResultCache) Get(ctx context.Context, root cid.Cid) (cid.Cid, bool, error) { k := m.keyForMigration(root) @@ -135,6 +151,15 @@ type StateManager struct { tsExec Executor tsExecMonitor ExecMonitor beacon beacon.Schedule + + msgIndex index.MsgIndex + + // We keep a small cache for calls to ExecutionTrace which helps improve + // performance for node operators like exchanges and block explorers + execTraceCache *lru.ARCCache[types.TipSetKey, tipSetCacheEntry] + // We need a lock while making the copy as to prevent other callers + // overwrite the cache while making the copy + execTraceCacheLock sync.Mutex } // Caches a single state tree @@ -143,7 +168,12 @@ type treeCache struct { tree *state.StateTree } -func NewStateManager(cs *store.ChainStore, exec Executor, sys vm.SyscallBuilder, us UpgradeSchedule, beacon beacon.Schedule, metadataDs dstore.Batching) (*StateManager, error) { +type tipSetCacheEntry struct { + postStateRoot cid.Cid + invocTrace []*api.InvocResult +} + +func NewStateManager(cs *store.ChainStore, exec Executor, sys vm.SyscallBuilder, us UpgradeSchedule, beacon beacon.Schedule, metadataDs dstore.Batching, msgIndex index.MsgIndex) (*StateManager, error) { // If we have upgrades, make sure they're in-order and make sense. if err := us.Validate(); err != nil { return nil, err @@ -182,6 +212,16 @@ func NewStateManager(cs *store.ChainStore, exec Executor, sys vm.SyscallBuilder, } } + log.Debugf("execTraceCache size: %d", execTraceCacheSize) + var execTraceCache *lru.ARCCache[types.TipSetKey, tipSetCacheEntry] + var err error + if execTraceCacheSize > 0 { + execTraceCache, err = lru.NewARC[types.TipSetKey, tipSetCacheEntry](execTraceCacheSize) + if err != nil { + return nil, err + } + } + return &StateManager{ networkVersions: networkVersions, latestVersion: lastVersion, @@ -197,12 +237,14 @@ func NewStateManager(cs *store.ChainStore, exec Executor, sys vm.SyscallBuilder, root: cid.Undef, tree: nil, }, - compWait: make(map[string]chan struct{}), + compWait: make(map[string]chan struct{}), + msgIndex: msgIndex, + execTraceCache: execTraceCache, }, nil } -func NewStateManagerWithUpgradeScheduleAndMonitor(cs *store.ChainStore, exec Executor, sys vm.SyscallBuilder, us UpgradeSchedule, b beacon.Schedule, em ExecMonitor, metadataDs dstore.Batching) (*StateManager, error) { - sm, err := NewStateManager(cs, exec, sys, us, b, metadataDs) +func NewStateManagerWithUpgradeScheduleAndMonitor(cs *store.ChainStore, exec Executor, sys vm.SyscallBuilder, us UpgradeSchedule, b beacon.Schedule, em ExecMonitor, metadataDs dstore.Batching, msgIndex index.MsgIndex) (*StateManager, error) { + sm, err := NewStateManager(cs, exec, sys, us, b, metadataDs, msgIndex) if err != nil { return nil, err } diff --git a/chain/store/messages.go b/chain/store/messages.go index c39cb3f9b..3686f74f4 100644 --- a/chain/store/messages.go +++ b/chain/store/messages.go @@ -3,10 +3,10 @@ package store import ( "context" + block "github.com/ipfs/go-block-format" "github.com/ipfs/go-cid" cbor "github.com/ipfs/go-ipld-cbor" ipld "github.com/ipfs/go-ipld-format" - block "github.com/ipfs/go-libipfs/blocks" cbg "github.com/whyrusleeping/cbor-gen" "golang.org/x/xerrors" @@ -114,12 +114,35 @@ func (cs *ChainStore) BlockMsgsForTipset(ctx context.Context, ts *types.TipSet) return nil, xerrors.Errorf("failed to load state tree at tipset %s: %w", ts, err) } + useIds := false selectMsg := func(m *types.Message) (bool, error) { var sender address.Address if ts.Height() >= build.UpgradeHyperdriveHeight { - sender, err = st.LookupID(m.From) - if err != nil { - return false, err + if useIds { + sender, err = st.LookupID(m.From) + if err != nil { + return false, xerrors.Errorf("failed to resolve sender: %w", err) + } + } else { + if m.From.Protocol() != address.ID { + // we haven't been told to use IDs, just use the robust addr + sender = m.From + } else { + // uh-oh, we actually have an ID-sender! + useIds = true + for robust, nonce := range applied { + resolved, err := st.LookupID(robust) + if err != nil { + return false, xerrors.Errorf("failed to resolve sender: %w", err) + } + applied[resolved] = nonce + } + + sender, err = st.LookupID(m.From) + if err != nil { + return false, xerrors.Errorf("failed to resolve sender: %w", err) + } + } } } else { sender = m.From diff --git a/chain/store/snapshot.go b/chain/store/snapshot.go index da568d0fb..92bc238a6 100644 --- a/chain/store/snapshot.go +++ b/chain/store/snapshot.go @@ -3,13 +3,15 @@ package store import ( "bytes" "context" + "errors" "fmt" "io" "sync" "time" + blocks "github.com/ipfs/go-block-format" "github.com/ipfs/go-cid" - blocks "github.com/ipfs/go-libipfs/blocks" + format "github.com/ipfs/go-ipld-format" "github.com/ipld/go-car" carutil "github.com/ipld/go-car/util" carv2 "github.com/ipld/go-car/v2" @@ -121,11 +123,9 @@ func (cs *ChainStore) Import(ctx context.Context, r io.Reader) (*types.TipSet, e } ts := root + tssToPersist := make([]*types.TipSet, 0, TipsetkeyBackfillRange) for i := 0; i < int(TipsetkeyBackfillRange); i++ { - err = cs.PersistTipset(ctx, ts) - if err != nil { - return nil, err - } + tssToPersist = append(tssToPersist, ts) parentTsKey := ts.Parents() ts, err = cs.LoadTipSet(ctx, parentTsKey) if ts == nil || err != nil { @@ -134,6 +134,10 @@ func (cs *ChainStore) Import(ctx context.Context, r io.Reader) (*types.TipSet, e } } + if err := cs.PersistTipsets(ctx, tssToPersist); err != nil { + return nil, xerrors.Errorf("failed to persist tipsets: %w", err) + } + return root, nil } @@ -167,8 +171,11 @@ func (t walkSchedTaskType) String() string { } type walkTask struct { - c cid.Cid - taskType walkSchedTaskType + c cid.Cid + taskType walkSchedTaskType + topLevelTaskType walkSchedTaskType + blockCid cid.Cid + epoch abi.ChainEpoch } // an ever growing FIFO @@ -317,8 +324,11 @@ func newWalkScheduler(ctx context.Context, store bstore.Blockstore, cfg walkSche cancel() // kill workers return nil, ctx.Err() case s.workerTasks.in <- walkTask{ - c: b.Cid(), - taskType: blockTask, + c: b.Cid(), + taskType: blockTask, + topLevelTaskType: blockTask, + blockCid: b.Cid(), + epoch: cfg.head.Height(), }: } } @@ -363,6 +373,9 @@ func (s *walkScheduler) enqueueIfNew(task walkTask) { //log.Infow("ignored", "cid", todo.c.String()) return } + + // This lets through RAW and CBOR blocks, the only two types that we + // end up writing to the exported CAR. if task.c.Prefix().Codec != cid.Raw && task.c.Prefix().Codec != cid.DagCBOR { //log.Infow("ignored", "cid", todo.c.String()) return @@ -416,8 +429,17 @@ func (s *walkScheduler) processTask(t walkTask, workerN int) error { } blk, err := s.store.Get(s.ctx, t.c) + if errors.Is(err, format.ErrNotFound{}) && t.topLevelTaskType == receiptTask { + log.Debugw("ignoring not-found block in Receipts", + "block", t.blockCid, + "epoch", t.epoch, + "cid", t.c) + return nil + } if err != nil { - return xerrors.Errorf("writing object to car, bs.Get: %w", err) + return xerrors.Errorf( + "blockstore.Get(%s). Task: %s. Block: %s (%s). Epoch: %d. Err: %w", + t.c, t.taskType, t.topLevelTaskType, t.blockCid, t.epoch, err) } s.results <- taskResult{ @@ -425,15 +447,19 @@ func (s *walkScheduler) processTask(t walkTask, workerN int) error { b: blk, } + // We exported the ipld block. If it wasn't a CBOR block, there's nothing + // else to do and we can bail out early as it won't have any links + // etc. + if t.c.Prefix().Codec != cid.DagCBOR || t.c.Prefix().MhType == mh.IDENTITY { + return nil + } + + rawData := blk.RawData() + // extract relevant dags to walk from the block if t.taskType == blockTask { - blk := t.c - data, err := s.store.Get(s.ctx, blk) - if err != nil { - return err - } var b types.BlockHeader - if err := b.UnmarshalCBOR(bytes.NewBuffer(data.RawData())); err != nil { + if err := b.UnmarshalCBOR(bytes.NewBuffer(rawData)); err != nil { return xerrors.Errorf("unmarshalling block header (cid=%s): %w", blk, err) } if b.Height%1_000 == 0 { @@ -443,13 +469,19 @@ func (s *walkScheduler) processTask(t walkTask, workerN int) error { log.Info("exporting genesis block") for i := range b.Parents { s.enqueueIfNew(walkTask{ - c: b.Parents[i], - taskType: dagTask, + c: b.Parents[i], + taskType: dagTask, + topLevelTaskType: blockTask, + blockCid: b.Parents[i], + epoch: 0, }) } s.enqueueIfNew(walkTask{ - c: b.ParentStateRoot, - taskType: stateTask, + c: b.ParentStateRoot, + taskType: stateTask, + topLevelTaskType: stateTask, + blockCid: t.c, + epoch: 0, }) return s.sendFinish(workerN) @@ -457,33 +489,45 @@ func (s *walkScheduler) processTask(t walkTask, workerN int) error { // enqueue block parents for i := range b.Parents { s.enqueueIfNew(walkTask{ - c: b.Parents[i], - taskType: blockTask, + c: b.Parents[i], + taskType: blockTask, + topLevelTaskType: blockTask, + blockCid: b.Parents[i], + epoch: b.Height, }) } if s.cfg.tail.Height() >= b.Height { - log.Debugw("tail reached: only blocks will be exported from now until genesis", "cid", blk.String()) + log.Debugw("tail reached: only blocks will be exported from now until genesis", "cid", t.c.String()) return nil } if s.cfg.includeMessages { // enqueue block messages s.enqueueIfNew(walkTask{ - c: b.Messages, - taskType: messageTask, + c: b.Messages, + taskType: messageTask, + topLevelTaskType: messageTask, + blockCid: t.c, + epoch: b.Height, }) } if s.cfg.includeReceipts { // enqueue block receipts s.enqueueIfNew(walkTask{ - c: b.ParentMessageReceipts, - taskType: receiptTask, + c: b.ParentMessageReceipts, + taskType: receiptTask, + topLevelTaskType: receiptTask, + blockCid: t.c, + epoch: b.Height, }) } if s.cfg.includeState { s.enqueueIfNew(walkTask{ - c: b.ParentStateRoot, - taskType: stateTask, + c: b.ParentStateRoot, + taskType: stateTask, + topLevelTaskType: stateTask, + blockCid: t.c, + epoch: b.Height, }) } @@ -491,16 +535,22 @@ func (s *walkScheduler) processTask(t walkTask, workerN int) error { } // Not a chain-block: we scan for CIDs in the raw block-data - return cbg.ScanForLinks(bytes.NewReader(blk.RawData()), func(c cid.Cid) { - if t.c.Prefix().Codec != cid.DagCBOR || t.c.Prefix().MhType == mh.IDENTITY { - return - } - + err = cbg.ScanForLinks(bytes.NewReader(rawData), func(c cid.Cid) { s.enqueueIfNew(walkTask{ - c: c, - taskType: dagTask, + c: c, + taskType: dagTask, + topLevelTaskType: t.topLevelTaskType, + blockCid: t.blockCid, + epoch: t.epoch, }) }) + + if err != nil { + return xerrors.Errorf( + "ScanForLinks(%s). Task: %s. Block: %s (%s). Epoch: %d. Err: %w", + t.c, t.taskType, t.topLevelTaskType, t.blockCid, t.epoch, err) + } + return nil } func (cs *ChainStore) ExportRange( diff --git a/chain/store/store.go b/chain/store/store.go index d7188a7bf..fd12b88a5 100644 --- a/chain/store/store.go +++ b/chain/store/store.go @@ -12,11 +12,11 @@ import ( "time" lru "github.com/hashicorp/golang-lru/v2" + block "github.com/ipfs/go-block-format" "github.com/ipfs/go-cid" dstore "github.com/ipfs/go-datastore" "github.com/ipfs/go-datastore/query" cbor "github.com/ipfs/go-ipld-cbor" - block "github.com/ipfs/go-libipfs/blocks" logging "github.com/ipfs/go-log/v2" "go.opencensus.io/stats" "go.opencensus.io/trace" @@ -378,7 +378,7 @@ func (cs *ChainStore) SetGenesis(ctx context.Context, b *types.BlockHeader) erro } func (cs *ChainStore) PutTipSet(ctx context.Context, ts *types.TipSet) error { - if err := cs.PersistTipset(ctx, ts); err != nil { + if err := cs.PersistTipsets(ctx, []*types.TipSet{ts}); err != nil { return xerrors.Errorf("failed to persist tipset: %w", err) } @@ -425,6 +425,11 @@ func (cs *ChainStore) MaybeTakeHeavierTipSet(ctx context.Context, ts *types.TipS } defer cs.heaviestLk.Unlock() + + if ts.Equals(cs.heaviest) { + return nil + } + w, err := cs.weight(ctx, cs.StateBlockstore(), ts) if err != nil { return err @@ -639,22 +644,10 @@ func (cs *ChainStore) reorgWorker(ctx context.Context, initialNotifees []ReorgNo func (cs *ChainStore) takeHeaviestTipSet(ctx context.Context, ts *types.TipSet) error { _, span := trace.StartSpan(ctx, "takeHeaviestTipSet") defer span.End() - - if cs.heaviest != nil { // buf - if len(cs.reorgCh) > 0 { - log.Warnf("Reorg channel running behind, %d reorgs buffered", len(cs.reorgCh)) - } - cs.reorgCh <- reorg{ - old: cs.heaviest, - new: ts, - } - } else { - log.Warnf("no heaviest tipset found, using %s", ts.Cids()) - } - span.AddAttributes(trace.BoolAttribute("newHead", true)) log.Infof("New heaviest tipset! %s (height=%d)", ts.Cids(), ts.Height()) + prevHeaviest := cs.heaviest cs.heaviest = ts if err := cs.writeHead(ctx, ts); err != nil { @@ -662,6 +655,18 @@ func (cs *ChainStore) takeHeaviestTipSet(ctx context.Context, ts *types.TipSet) return err } + if prevHeaviest != nil { // buf + if len(cs.reorgCh) > 0 { + log.Warnf("Reorg channel running behind, %d reorgs buffered", len(cs.reorgCh)) + } + cs.reorgCh <- reorg{ + old: prevHeaviest, + new: ts, + } + } else { + log.Warnf("no previous heaviest tipset found, using %s", ts.Cids()) + } + return nil } @@ -970,18 +975,25 @@ func (cs *ChainStore) AddToTipSetTracker(ctx context.Context, b *types.BlockHead return nil } -func (cs *ChainStore) PersistTipset(ctx context.Context, ts *types.TipSet) error { - if err := cs.persistBlockHeaders(ctx, ts.Blocks()...); err != nil { +func (cs *ChainStore) PersistTipsets(ctx context.Context, tipsets []*types.TipSet) error { + toPersist := make([]*types.BlockHeader, 0, len(tipsets)*int(build.BlocksPerEpoch)) + tsBlks := make([]block.Block, 0, len(tipsets)) + for _, ts := range tipsets { + toPersist = append(toPersist, ts.Blocks()...) + tsBlk, err := ts.Key().ToStorageBlock() + if err != nil { + return xerrors.Errorf("failed to get tipset key block: %w", err) + } + + tsBlks = append(tsBlks, tsBlk) + } + + if err := cs.persistBlockHeaders(ctx, toPersist...); err != nil { return xerrors.Errorf("failed to persist block headers: %w", err) } - tsBlk, err := ts.Key().ToStorageBlock() - if err != nil { - return xerrors.Errorf("failed to get tipset key block: %w", err) - } - - if err = cs.chainLocalBlockstore.Put(ctx, tsBlk); err != nil { - return xerrors.Errorf("failed to put tipset key block: %w", err) + if err := cs.chainLocalBlockstore.PutMany(ctx, tsBlks); err != nil { + return xerrors.Errorf("failed to put tipset key blocks: %w", err) } return nil diff --git a/chain/store/store_test.go b/chain/store/store_test.go index cc72acc95..cea0fdc2a 100644 --- a/chain/store/store_test.go +++ b/chain/store/store_test.go @@ -18,6 +18,7 @@ import ( "github.com/filecoin-project/lotus/chain/consensus" "github.com/filecoin-project/lotus/chain/consensus/filcns" "github.com/filecoin-project/lotus/chain/gen" + "github.com/filecoin-project/lotus/chain/index" "github.com/filecoin-project/lotus/chain/stmgr" "github.com/filecoin-project/lotus/chain/store" "github.com/filecoin-project/lotus/chain/types" @@ -214,7 +215,7 @@ func TestChainExportImportFull(t *testing.T) { t.Fatal("imported chain differed from exported chain") } - sm, err := stmgr.NewStateManager(cs, consensus.NewTipSetExecutor(filcns.RewardFunc), nil, filcns.DefaultUpgradeSchedule(), cg.BeaconSchedule(), ds) + sm, err := stmgr.NewStateManager(cs, consensus.NewTipSetExecutor(filcns.RewardFunc), nil, filcns.DefaultUpgradeSchedule(), cg.BeaconSchedule(), ds, index.DummyMsgIndex) if err != nil { t.Fatal(err) } diff --git a/chain/sub/incoming.go b/chain/sub/incoming.go index f641f0ff9..533314a4f 100644 --- a/chain/sub/incoming.go +++ b/chain/sub/incoming.go @@ -8,9 +8,9 @@ import ( "time" lru "github.com/hashicorp/golang-lru/v2" + blocks "github.com/ipfs/go-block-format" bserv "github.com/ipfs/go-blockservice" "github.com/ipfs/go-cid" - blocks "github.com/ipfs/go-libipfs/blocks" logging "github.com/ipfs/go-log/v2" "github.com/ipni/storetheindex/announce/message" pubsub "github.com/libp2p/go-libp2p-pubsub" diff --git a/chain/sub/incoming_test.go b/chain/sub/incoming_test.go index 03f880c58..0a9504a88 100644 --- a/chain/sub/incoming_test.go +++ b/chain/sub/incoming_test.go @@ -7,8 +7,8 @@ import ( "testing" "github.com/golang/mock/gomock" + blocks "github.com/ipfs/go-block-format" "github.com/ipfs/go-cid" - blocks "github.com/ipfs/go-libipfs/blocks" "github.com/ipni/storetheindex/announce/message" pubsub "github.com/libp2p/go-libp2p-pubsub" pb "github.com/libp2p/go-libp2p-pubsub/pb" diff --git a/chain/sync.go b/chain/sync.go index db7b7fc04..7830a9771 100644 --- a/chain/sync.go +++ b/chain/sync.go @@ -11,10 +11,10 @@ import ( "github.com/Gurpartap/async" "github.com/hashicorp/go-multierror" + blocks "github.com/ipfs/go-block-format" "github.com/ipfs/go-cid" cbor "github.com/ipfs/go-ipld-cbor" ipld "github.com/ipfs/go-ipld-format" - blocks "github.com/ipfs/go-libipfs/blocks" logging "github.com/ipfs/go-log/v2" "github.com/libp2p/go-libp2p/core/connmgr" "github.com/libp2p/go-libp2p/core/peer" @@ -208,8 +208,8 @@ func (syncer *Syncer) InformNewHead(from peer.ID, fts *store.FullTipSet) bool { return false } - if syncer.consensus.IsEpochBeyondCurrMax(fts.TipSet().Height()) { - log.Errorf("Received block with impossibly large height %d", fts.TipSet().Height()) + if !syncer.consensus.IsEpochInConsensusRange(fts.TipSet().Height()) { + log.Infof("received block outside of consensus range at height %d", fts.TipSet().Height()) return false } @@ -228,7 +228,7 @@ func (syncer *Syncer) InformNewHead(from peer.ID, fts *store.FullTipSet) bool { // TODO: IMPORTANT(GARBAGE) this needs to be put in the 'temporary' side of // the blockstore - if err := syncer.store.PersistTipset(ctx, fts.TipSet()); err != nil { + if err := syncer.store.PersistTipsets(ctx, []*types.TipSet{fts.TipSet()}); err != nil { log.Warn("failed to persist incoming block header: ", err) return false } @@ -1193,17 +1193,16 @@ func (syncer *Syncer) collectChain(ctx context.Context, ts *types.TipSet, hts *t span.AddAttributes(trace.Int64Attribute("syncChainLength", int64(len(headers)))) if !headers[0].Equals(ts) { - log.Errorf("collectChain headers[0] should be equal to sync target. Its not: %s != %s", headers[0].Cids(), ts.Cids()) + return xerrors.Errorf("collectChain synced %s, wanted to sync %s", headers[0].Cids(), ts.Cids()) } ss.SetStage(api.StagePersistHeaders) - for _, ts := range headers { - if err := syncer.store.PersistTipset(ctx, ts); err != nil { - err = xerrors.Errorf("failed to persist synced tipset to the chainstore: %w", err) - ss.Error(err) - return err - } + // Write tipsets from oldest to newest. + if err := syncer.store.PersistTipsets(ctx, headers); err != nil { + err = xerrors.Errorf("failed to persist synced tipset to the chainstore: %w", err) + ss.Error(err) + return err } ss.SetStage(api.StageMessages) diff --git a/chain/types/blockheader.go b/chain/types/blockheader.go index 559569ba0..3117e3122 100644 --- a/chain/types/blockheader.go +++ b/chain/types/blockheader.go @@ -4,8 +4,8 @@ import ( "bytes" "math/big" + block "github.com/ipfs/go-block-format" "github.com/ipfs/go-cid" - block "github.com/ipfs/go-libipfs/blocks" "github.com/minio/blake2b-simd" "golang.org/x/xerrors" @@ -13,8 +13,6 @@ import ( "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/crypto" "github.com/filecoin-project/go-state-types/proof" - - "github.com/filecoin-project/lotus/build" ) type Ticket struct { @@ -195,36 +193,6 @@ func CidArrsContains(a []cid.Cid, b cid.Cid) bool { return false } -var blocksPerEpoch = NewInt(build.BlocksPerEpoch) - -const sha256bits = 256 - -func IsTicketWinner(vrfTicket []byte, mypow BigInt, totpow BigInt) bool { - /* - Need to check that - (h(vrfout) + 1) / (max(h) + 1) <= e * myPower / totalPower - max(h) == 2^256-1 - which in terms of integer math means: - (h(vrfout) + 1) * totalPower <= e * myPower * 2^256 - in 2^256 space, it is equivalent to: - h(vrfout) * totalPower < e * myPower * 2^256 - - */ - - h := blake2b.Sum256(vrfTicket) - - lhs := BigFromBytes(h[:]).Int - lhs = lhs.Mul(lhs, totpow.Int) - - // rhs = sectorSize * 2^256 - // rhs = sectorSize << 256 - rhs := new(big.Int).Lsh(mypow.Int, sha256bits) - rhs = rhs.Mul(rhs, blocksPerEpoch.Int) - - // h(vrfout) * totalPower < e * sectorSize * 2^256? - return lhs.Cmp(rhs) < 0 -} - func (t *Ticket) Equals(ot *Ticket) bool { return bytes.Equal(t.VRFProof, ot.VRFProof) } diff --git a/chain/types/electionproof.go b/chain/types/electionproof.go index 6f59c7713..f3168becb 100644 --- a/chain/types/electionproof.go +++ b/chain/types/electionproof.go @@ -100,6 +100,7 @@ func polyval(p []*big.Int, x *big.Int) *big.Int { // computes lambda in Q.256 func lambda(power, totalPower *big.Int) *big.Int { + blocksPerEpoch := NewInt(build.BlocksPerEpoch) lam := new(big.Int).Mul(power, blocksPerEpoch.Int) // Q.0 lam = lam.Lsh(lam, precision) // Q.256 lam = lam.Div(lam /* Q.256 */, totalPower /* Q.0 */) // Q.256 diff --git a/chain/types/ethtypes/eth_types.go b/chain/types/ethtypes/eth_types.go index f157c7f94..64f67f662 100644 --- a/chain/types/ethtypes/eth_types.go +++ b/chain/types/ethtypes/eth_types.go @@ -238,6 +238,30 @@ func (c *EthCall) UnmarshalJSON(b []byte) error { return nil } +type EthSyncingResult struct { + DoneSync bool + StartingBlock EthUint64 + CurrentBlock EthUint64 + HighestBlock EthUint64 +} + +func (sr EthSyncingResult) MarshalJSON() ([]byte, error) { + if sr.DoneSync { + // when done syncing, the json response should be '"result": false' + return []byte("false"), nil + } + + // need to do an anonymous struct to avoid infinite recursion + return json.Marshal(&struct { + StartingBlock EthUint64 `json:"startingblock"` + CurrentBlock EthUint64 `json:"currentblock"` + HighestBlock EthUint64 `json:"highestblock"` + }{ + StartingBlock: sr.StartingBlock, + CurrentBlock: sr.CurrentBlock, + HighestBlock: sr.HighestBlock}) +} + const ( EthAddressLength = 20 EthHashLength = 32 @@ -548,12 +572,12 @@ func (h EthSubscriptionID) String() string { } type EthFilterSpec struct { - // Interpreted as an epoch or one of "latest" for last mined block, "earliest" for first, + // Interpreted as an epoch (in hex) or one of "latest" for last mined block, "earliest" for first, // "pending" for not yet committed messages. // Optional, default: "latest". FromBlock *string `json:"fromBlock,omitempty"` - // Interpreted as an epoch or one of "latest" for last mined block, "earliest" for first, + // Interpreted as an epoch (in hex) or one of "latest" for last mined block, "earliest" for first, // "pending" for not yet committed messages. // Optional, default: "latest". ToBlock *string `json:"toBlock,omitempty"` diff --git a/chain/types/message.go b/chain/types/message.go index 4304ba659..473289ead 100644 --- a/chain/types/message.go +++ b/chain/types/message.go @@ -5,8 +5,8 @@ import ( "encoding/json" "fmt" + block "github.com/ipfs/go-block-format" "github.com/ipfs/go-cid" - block "github.com/ipfs/go-libipfs/blocks" "golang.org/x/xerrors" "github.com/filecoin-project/go-address" @@ -220,12 +220,17 @@ func (m *Message) ValidForBlockInclusion(minGas int64, version network.Version) } // EffectiveGasPremium returns the effective gas premium claimable by the miner -// given the supplied base fee. +// given the supplied base fee. This method is not used anywhere except the Eth API. // // Filecoin clamps the gas premium at GasFeeCap - BaseFee, if lower than the -// specified premium. +// specified premium. Returns 0 if GasFeeCap is less than BaseFee. func (m *Message) EffectiveGasPremium(baseFee abi.TokenAmount) abi.TokenAmount { available := big.Sub(m.GasFeeCap, baseFee) + // It's possible that storage providers may include messages with gasFeeCap less than the baseFee + // In such cases, their reward should be viewed as zero + if available.LessThan(big.NewInt(0)) { + available = big.NewInt(0) + } if big.Cmp(m.GasPremium, available) <= 0 { return m.GasPremium } diff --git a/chain/types/signedmessage.go b/chain/types/signedmessage.go index dc867c5e5..168531714 100644 --- a/chain/types/signedmessage.go +++ b/chain/types/signedmessage.go @@ -4,8 +4,8 @@ import ( "bytes" "encoding/json" + block "github.com/ipfs/go-block-format" "github.com/ipfs/go-cid" - block "github.com/ipfs/go-libipfs/blocks" "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/crypto" diff --git a/chain/types/tipset_key.go b/chain/types/tipset_key.go index 50753ffd2..15e655da7 100644 --- a/chain/types/tipset_key.go +++ b/chain/types/tipset_key.go @@ -7,8 +7,8 @@ import ( "io" "strings" + block "github.com/ipfs/go-block-format" "github.com/ipfs/go-cid" - block "github.com/ipfs/go-libipfs/blocks" typegen "github.com/whyrusleeping/cbor-gen" "github.com/filecoin-project/go-state-types/abi" diff --git a/chain/vm/execution.go b/chain/vm/execution.go new file mode 100644 index 000000000..ea3a97193 --- /dev/null +++ b/chain/vm/execution.go @@ -0,0 +1,192 @@ +package vm + +import ( + "context" + "os" + "strconv" + "sync" + + "github.com/ipfs/go-cid" + "go.opencensus.io/stats" + "go.opencensus.io/tag" + + "github.com/filecoin-project/lotus/chain/types" + "github.com/filecoin-project/lotus/metrics" +) + +const ( + // DefaultAvailableExecutionLanes is the number of available execution lanes; it is the bound of + // concurrent active executions. + // This is the default value in filecoin-ffi + DefaultAvailableExecutionLanes = 4 + // DefaultPriorityExecutionLanes is the number of reserved execution lanes for priority computations. + // This is purely userspace, but we believe it is a reasonable default, even with more available + // lanes. + DefaultPriorityExecutionLanes = 2 +) + +// the execution environment; see below for definition, methods, and initialization +var execution *executionEnv + +// implementation of vm executor with simple sanity check preventing use after free. +type vmExecutor struct { + vmi Interface + lane ExecutionLane +} + +var _ Interface = (*vmExecutor)(nil) + +func newVMExecutor(vmi Interface, lane ExecutionLane) Interface { + return &vmExecutor{vmi: vmi, lane: lane} +} + +func (e *vmExecutor) ApplyMessage(ctx context.Context, cmsg types.ChainMsg) (*ApplyRet, error) { + token := execution.getToken(e.lane) + defer token.Done() + + return e.vmi.ApplyMessage(ctx, cmsg) +} + +func (e *vmExecutor) ApplyImplicitMessage(ctx context.Context, msg *types.Message) (*ApplyRet, error) { + token := execution.getToken(e.lane) + defer token.Done() + + return e.vmi.ApplyImplicitMessage(ctx, msg) +} + +func (e *vmExecutor) Flush(ctx context.Context) (cid.Cid, error) { + return e.vmi.Flush(ctx) +} + +type executionToken struct { + lane ExecutionLane + reserved int +} + +func (token *executionToken) Done() { + execution.putToken(token) +} + +type executionEnv struct { + mx *sync.Mutex + cond *sync.Cond + + // available executors + available int + // reserved executors + reserved int +} + +func (e *executionEnv) getToken(lane ExecutionLane) *executionToken { + metricsUp(metrics.VMExecutionWaiting, lane) + defer metricsDown(metrics.VMExecutionWaiting, lane) + + e.mx.Lock() + defer e.mx.Unlock() + + switch lane { + case ExecutionLaneDefault: + for e.available <= e.reserved { + e.cond.Wait() + } + + e.available-- + + metricsUp(metrics.VMExecutionRunning, lane) + return &executionToken{lane: lane, reserved: 0} + + case ExecutionLanePriority: + for e.available == 0 { + e.cond.Wait() + } + + e.available-- + + reserving := 0 + if e.reserved > 0 { + e.reserved-- + reserving = 1 + } + + metricsUp(metrics.VMExecutionRunning, lane) + return &executionToken{lane: lane, reserved: reserving} + + default: + // already checked at interface boundary in NewVM, so this is appropriate + panic("bogus execution lane") + } +} + +func (e *executionEnv) putToken(token *executionToken) { + e.mx.Lock() + defer e.mx.Unlock() + + e.available++ + e.reserved += token.reserved + + // Note: Signal is unsound, because a priority token could wake up a non-priority + // goroutnie and lead to deadlock. So Broadcast it must be. + e.cond.Broadcast() + + metricsDown(metrics.VMExecutionRunning, token.lane) +} + +func metricsUp(metric *stats.Int64Measure, lane ExecutionLane) { + metricsAdjust(metric, lane, 1) +} + +func metricsDown(metric *stats.Int64Measure, lane ExecutionLane) { + metricsAdjust(metric, lane, -1) +} + +func metricsAdjust(metric *stats.Int64Measure, lane ExecutionLane, delta int) { + laneName := "default" + if lane > ExecutionLaneDefault { + laneName = "priority" + } + + ctx, _ := tag.New( + context.Background(), + tag.Upsert(metrics.ExecutionLane, laneName), + ) + stats.Record(ctx, metric.M(int64(delta))) +} + +func init() { + var err error + + available := DefaultAvailableExecutionLanes + if concurrency := os.Getenv("LOTUS_FVM_CONCURRENCY"); concurrency != "" { + available, err = strconv.Atoi(concurrency) + if err != nil { + panic(err) + } + } + + priority := DefaultPriorityExecutionLanes + if reserved := os.Getenv("LOTUS_FVM_CONCURRENCY_RESERVED"); reserved != "" { + priority, err = strconv.Atoi(reserved) + if err != nil { + panic(err) + } + } + + // some sanity checks + if available < 2 { + panic("insufficient execution concurrency") + } + + if available <= priority { + panic("insufficient default execution concurrency") + } + + mx := &sync.Mutex{} + cond := sync.NewCond(mx) + + execution = &executionEnv{ + mx: mx, + cond: cond, + available: available, + reserved: priority, + } +} diff --git a/chain/vm/vm.go b/chain/vm/vm.go index c8e3f2519..58afc14bc 100644 --- a/chain/vm/vm.go +++ b/chain/vm/vm.go @@ -7,9 +7,9 @@ import ( "sync/atomic" "time" + block "github.com/ipfs/go-block-format" "github.com/ipfs/go-cid" cbor "github.com/ipfs/go-ipld-cbor" - block "github.com/ipfs/go-libipfs/blocks" logging "github.com/ipfs/go-log/v2" mh "github.com/multiformats/go-multihash" cbg "github.com/whyrusleeping/cbor-gen" @@ -250,6 +250,8 @@ type VMOpts struct { Tracing bool // ReturnEvents decodes and returns emitted events. ReturnEvents bool + // ExecutionLane specifies the execution priority of the created vm + ExecutionLane ExecutionLane } func NewLegacyVM(ctx context.Context, opts *VMOpts) (*LegacyVM, error) { diff --git a/chain/vm/vmi.go b/chain/vm/vmi.go index 01b32d4ad..042621ca2 100644 --- a/chain/vm/vmi.go +++ b/chain/vm/vmi.go @@ -2,6 +2,7 @@ package vm import ( "context" + "fmt" "os" cid "github.com/ipfs/go-cid" @@ -17,6 +18,15 @@ var ( StatApplied uint64 ) +type ExecutionLane int + +const ( + // ExecutionLaneDefault signifies a default, non prioritized execution lane. + ExecutionLaneDefault ExecutionLane = iota + // ExecutionLanePriority signifies a prioritized execution lane with reserved resources. + ExecutionLanePriority +) + type Interface interface { // Applies the given message onto the VM's current state, returning the result of the execution ApplyMessage(ctx context.Context, cmsg types.ChainMsg) (*ApplyRet, error) @@ -33,7 +43,7 @@ type Interface interface { // Message failures, unexpected terminations,gas costs, etc. should all be ignored. var useFvmDebug = os.Getenv("LOTUS_FVM_DEVELOPER_DEBUG") == "1" -func NewVM(ctx context.Context, opts *VMOpts) (Interface, error) { +func makeVM(ctx context.Context, opts *VMOpts) (Interface, error) { if opts.NetworkVersion >= network.Version16 { if useFvmDebug { return NewDualExecutionFVM(ctx, opts) @@ -43,3 +53,18 @@ func NewVM(ctx context.Context, opts *VMOpts) (Interface, error) { return NewLegacyVM(ctx, opts) } + +func NewVM(ctx context.Context, opts *VMOpts) (Interface, error) { + switch opts.ExecutionLane { + case ExecutionLaneDefault, ExecutionLanePriority: + default: + return nil, fmt.Errorf("invalid execution lane: %d", opts.ExecutionLane) + } + + vmi, err := makeVM(ctx, opts) + if err != nil { + return nil, err + } + + return newVMExecutor(vmi, opts.ExecutionLane), nil +} diff --git a/cli/chain.go b/cli/chain.go index 4344b0773..c0d54fd63 100644 --- a/cli/chain.go +++ b/cli/chain.go @@ -388,7 +388,7 @@ var ChainSetHeadCmd = &cli.Command{ defer closer() ctx := ReqContext(cctx) - if cctx.NArg() != 1 { + if !cctx.Bool("genesis") && !cctx.IsSet("epoch") && cctx.NArg() != 1 { return IncorrectNumArgs(cctx) } diff --git a/cli/net.go b/cli/net.go index 6b10dbffc..516b44b7f 100644 --- a/cli/net.go +++ b/cli/net.go @@ -367,7 +367,7 @@ func AddrInfoFromArg(ctx context.Context, cctx *cli.Context) ([]peer.AddrInfo, e pis = append(pis, pi) } - return pis, err + return pis, nil } var NetId = &cli.Command{ @@ -445,8 +445,8 @@ var NetReachability = &cli.Command{ } fmt.Println("AutoNAT status: ", i.Reachability.String()) - if i.PublicAddr != "" { - fmt.Println("Public address: ", i.PublicAddr) + if len(i.PublicAddrs) > 0 { + fmt.Println("Public address:", i.PublicAddrs) } return nil }, diff --git a/cli/state.go b/cli/state.go index 3099bff17..9031ba870 100644 --- a/cli/state.go +++ b/cli/state.go @@ -1268,7 +1268,7 @@ var compStateMsg = ` {{end}} {{if ne .MsgRct.ExitCode 0}} -
Error:
{{.Error}}
+
Exit:
{{.MsgRct.ExitCode}}
{{end}}
@@ -1372,7 +1372,14 @@ func isVerySlow(t time.Duration) bool { } func JsonParams(code cid.Cid, method abi.MethodNum, params []byte) (string, error) { - p, err := stmgr.GetParamType(consensus.NewActorRegistry(), code, method) // todo use api for correct actor registry + ar := consensus.NewActorRegistry() + + _, found := ar.Methods[code][method] + if !found { + return fmt.Sprintf("raw:%x", params), nil + } + + p, err := stmgr.GetParamType(ar, code, method) // todo use api for correct actor registry if err != nil { return "", err } diff --git a/cmd/lotus-bench/import.go b/cmd/lotus-bench/import.go index babf9342b..9f43d9538 100644 --- a/cmd/lotus-bench/import.go +++ b/cmd/lotus-bench/import.go @@ -35,6 +35,7 @@ import ( badgerbs "github.com/filecoin-project/lotus/blockstore/badger" "github.com/filecoin-project/lotus/chain/consensus" "github.com/filecoin-project/lotus/chain/consensus/filcns" + "github.com/filecoin-project/lotus/chain/index" "github.com/filecoin-project/lotus/chain/stmgr" "github.com/filecoin-project/lotus/chain/store" "github.com/filecoin-project/lotus/chain/types" @@ -228,7 +229,7 @@ var importBenchCmd = &cli.Command{ defer cs.Close() //nolint:errcheck // TODO: We need to supply the actual beacon after v14 - stm, err := stmgr.NewStateManager(cs, consensus.NewTipSetExecutor(filcns.RewardFunc), vm.Syscalls(verifier), filcns.DefaultUpgradeSchedule(), nil, metadataDs) + stm, err := stmgr.NewStateManager(cs, consensus.NewTipSetExecutor(filcns.RewardFunc), vm.Syscalls(verifier), filcns.DefaultUpgradeSchedule(), nil, metadataDs, index.DummyMsgIndex) if err != nil { return err } diff --git a/cmd/lotus-fountain/main.go b/cmd/lotus-fountain/main.go index 14968cb72..fe417dddb 100644 --- a/cmd/lotus-fountain/main.go +++ b/cmd/lotus-fountain/main.go @@ -7,6 +7,7 @@ import ( "net" "net/http" "os" + "strings" "time" rice "github.com/GeertJohan/go.rice" @@ -22,6 +23,7 @@ import ( "github.com/filecoin-project/lotus/chain/actors" "github.com/filecoin-project/lotus/chain/actors/builtin/verifreg" "github.com/filecoin-project/lotus/chain/types" + "github.com/filecoin-project/lotus/chain/types/ethtypes" lcli "github.com/filecoin-project/lotus/cli" ) @@ -217,18 +219,34 @@ func (h *handler) ServeHTTP(w http.ResponseWriter, r *http.Request) { return } - to, err := address.NewFromString(r.FormValue("address")) - if err != nil { + addressInput := r.FormValue("address") + + var filecoinAddress address.Address + var decodeError error + + if strings.HasPrefix(addressInput, "0x") { + ethAddress, err := ethtypes.ParseEthAddress(addressInput) + if err != nil { + http.Error(w, err.Error(), http.StatusBadRequest) + return + } + + filecoinAddress, decodeError = ethAddress.ToFilecoinAddress() + } else { + filecoinAddress, decodeError = address.NewFromString(addressInput) + } + + if decodeError != nil { http.Error(w, err.Error(), http.StatusBadRequest) return } - if to == address.Undef { + if filecoinAddress == address.Undef { http.Error(w, "empty address", http.StatusBadRequest) return } // Limit based on wallet address - limiter := h.limiter.GetWalletLimiter(to.String()) + limiter := h.limiter.GetWalletLimiter(filecoinAddress.String()) if !limiter.Allow() { http.Error(w, http.StatusText(http.StatusTooManyRequests)+": wallet limit", http.StatusTooManyRequests) return @@ -282,6 +300,7 @@ func (h *handler) ServeHTTP(w http.ResponseWriter, r *http.Request) { return } + if err != nil { http.Error(w, err.Error(), http.StatusBadRequest) return diff --git a/cmd/lotus-fountain/site/funds.html b/cmd/lotus-fountain/site/funds.html index c6916239f..ae7a4041b 100644 --- a/cmd/lotus-fountain/site/funds.html +++ b/cmd/lotus-fountain/site/funds.html @@ -15,7 +15,7 @@
- [SENDING FUNDS] + SENDING FUNDS
diff --git a/cmd/lotus-fountain/site/index.html b/cmd/lotus-fountain/site/index.html index 4dc3df478..5398cf4f1 100644 --- a/cmd/lotus-fountain/site/index.html +++ b/cmd/lotus-fountain/site/index.html @@ -8,10 +8,10 @@
- [LOTUS DEVNET FAUCET] + LOTUS DEVNET FAUCET
[LOTUS DEVNET GRANT DATACAP] diff --git a/cmd/lotus-fountain/site/main.css b/cmd/lotus-fountain/site/main.css index bcdb24c2e..e2670d123 100644 --- a/cmd/lotus-fountain/site/main.css +++ b/cmd/lotus-fountain/site/main.css @@ -1,7 +1,6 @@ body { - font-family: 'monospace'; - background: #1f1f1f; - color: #f0f0f0; + font-family: 'Helvetica Neue', sans-serif; + background-color: #f0f0f0; padding: 0; margin: 0; } @@ -9,21 +8,22 @@ body { .Index { width: 100vw; height: 100vh; - background: #1a1a1a; - color: #f0f0f0; - font-family: monospace; + background-color: #f0f0f0; + color: #333; + font-family: 'Helvetica Neue', sans-serif; display: grid; grid-template-columns: auto 40vw auto; grid-template-rows: auto auto auto 3em; grid-template-areas: - ". . . ." - ". main main ." - ". . . ." - "footer footer footer footer"; + ". . . ." + ". main main ." + ". . . ." + "footer footer footer footer"; } + .Index-footer { - background: #2a2a2a; + background-color: #333; grid-area: footer; } @@ -34,23 +34,49 @@ body { .Index-nodes { grid-area: main; - background: #2a2a2a; } .Index-node { margin: 5px; padding: 15px; - background: #1f1f1f; + background-color: #fff; + box-shadow: 0 0 5px rgba(0, 0, 0, 0.1); +} + +span { + display: block; + margin-bottom: 5px; +} + +input[type="text"] { + width: 100%; + padding: 10px; + border-radius: 5px; + border: 1px solid #ccc; + margin-bottom: 10px; +} + +button { + background-color: #4c9aff; + color: #fff; + border: none; + border-radius: 5px; + padding: 10px 20px; + font-size: 1.2em; +} + +button:hover { + background-color: #555; } a:link { - color: #50f020; + color: #333; } a:visited { - color: #50f020; + color: #333; } a:hover { - color: #30a00a; + color: #555; } diff --git a/cmd/lotus-miner/actor.go b/cmd/lotus-miner/actor.go index bec2202b4..f0c52278a 100644 --- a/cmd/lotus-miner/actor.go +++ b/cmd/lotus-miner/actor.go @@ -1166,7 +1166,7 @@ var actorConfirmChangeWorker = &cli.Command{ var actorConfirmChangeBeneficiary = &cli.Command{ Name: "confirm-change-beneficiary", Usage: "Confirm a beneficiary address change", - ArgsUsage: "[minerAddress]", + ArgsUsage: "[minerID]", Flags: []cli.Flag{ &cli.BoolFlag{ Name: "really-do-it", diff --git a/cmd/lotus-miner/info.go b/cmd/lotus-miner/info.go index 974635eb2..6d8ade340 100644 --- a/cmd/lotus-miner/info.go +++ b/cmd/lotus-miner/info.go @@ -325,14 +325,12 @@ func handleMiningInfo(ctx context.Context, cctx *cli.Context, fullapi v1api.Full } } - { - fmt.Println() - - ws, err := nodeApi.WorkerStats(ctx) - if err != nil { - return xerrors.Errorf("getting worker stats: %w", err) - } + fmt.Println() + ws, err := nodeApi.WorkerStats(ctx) + if err != nil { + fmt.Printf("ERROR: getting worker stats: %s\n", err) + } else { workersByType := map[string]int{ sealtasks.WorkerSealing: 0, sealtasks.WorkerWindowPoSt: 0, diff --git a/cmd/lotus-miner/main.go b/cmd/lotus-miner/main.go index 3cc796168..911e98e26 100644 --- a/cmd/lotus-miner/main.go +++ b/cmd/lotus-miner/main.go @@ -43,16 +43,16 @@ func main() { backupCmd, lcli.WithCategory("chain", actorCmd), lcli.WithCategory("chain", infoCmd), - lcli.WithCategory("market", storageDealsCmd), - lcli.WithCategory("market", retrievalDealsCmd), - lcli.WithCategory("market", dataTransfersCmd), - lcli.WithCategory("market", dagstoreCmd), - lcli.WithCategory("market", indexProvCmd), + lcli.WithCategory("market", setHidden(storageDealsCmd)), + lcli.WithCategory("market", setHidden(retrievalDealsCmd)), + lcli.WithCategory("market", setHidden(dataTransfersCmd)), + lcli.WithCategory("market", setHidden(dagstoreCmd)), + lcli.WithCategory("market", setHidden(indexProvCmd)), lcli.WithCategory("storage", sectorsCmd), lcli.WithCategory("storage", provingCmd), lcli.WithCategory("storage", storageCmd), lcli.WithCategory("storage", sealingCmd), - lcli.WithCategory("retrieval", piecesCmd), + lcli.WithCategory("retrieval", setHidden(piecesCmd)), } jaeger := tracing.SetupJaegerTracing("lotus") @@ -86,6 +86,7 @@ func main() { // adapt the Net* commands to always hit the node running the markets // subsystem, as that is the only one that runs a libp2p node. netCmd := *lcli.NetCmd // make a copy. + netCmd.Hidden = true prev := netCmd.Before netCmd.Before = func(c *cli.Context) error { if prev != nil { @@ -137,11 +138,12 @@ func main() { &cli.StringFlag{ Name: FlagMarketsRepo, EnvVars: []string{"LOTUS_MARKETS_PATH"}, - Usage: fmt.Sprintf("Markets repo path"), + Hidden: true, }, &cli.BoolFlag{ - Name: "call-on-markets", - Usage: "(experimental; may be removed) call this command against a markets node; use only with common commands like net, auth, pprof, etc. whose target may be ambiguous", + Name: "call-on-markets", + Usage: "(experimental; may be removed) call this command against a markets node; use only with common commands like net, auth, pprof, etc. whose target may be ambiguous", + Hidden: true, }, cliutil.FlagVeryVerbose, }, @@ -190,3 +192,8 @@ func getActorAddress(ctx context.Context, cctx *cli.Context) (maddr address.Addr return maddr, nil } + +func setHidden(cmd *cli.Command) *cli.Command { + cmd.Hidden = true + return cmd +} diff --git a/cmd/lotus-miner/sectors.go b/cmd/lotus-miner/sectors.go index 8d3a4c884..4d241b282 100644 --- a/cmd/lotus-miner/sectors.go +++ b/cmd/lotus-miner/sectors.go @@ -67,6 +67,7 @@ var sectorsCmd = &cli.Command{ sectorsBatching, sectorsRefreshPieceMatchingCmd, sectorsCompactPartitionsCmd, + sectorsUnsealCmd, }, } @@ -1392,6 +1393,12 @@ var sectorsRemoveCmd = &cli.Command{ return xerrors.Errorf("could not parse sector number: %w", err) } + // Check if the sector exists + _, err = minerAPI.SectorsStatus(ctx, abi.SectorNumber(id), false) + if err != nil { + return xerrors.Errorf("sectorID %d has not been created yet: %w", id, err) + } + return minerAPI.SectorRemove(ctx, abi.SectorNumber(id)) }, } @@ -1915,10 +1922,31 @@ var sectorsBatchingPendingCommit = &cli.Command{ for _, sector := range pending { fmt.Println(sector.Number) } - return nil - } - fmt.Println("No sectors queued to be committed") + reader := bufio.NewReader(os.Stdin) + fmt.Print("Do you want to publish these sectors now? (yes/no): ") + userInput, err := reader.ReadString('\n') + if err != nil { + return xerrors.Errorf("reading user input: %w", err) + } + userInput = strings.ToLower(strings.TrimSpace(userInput)) + + if userInput == "yes" { + err := cctx.Set("publish-now", "true") + if err != nil { + return xerrors.Errorf("setting publish-now flag: %w", err) + } + return cctx.Command.Action(cctx) + } else if userInput == "no" { + return nil + } else { + fmt.Println("Invalid input. Please answer with 'yes' or 'no'.") + return nil + } + + } else { + fmt.Println("No sectors queued to be committed") + } return nil }, } @@ -1973,10 +2001,31 @@ var sectorsBatchingPendingPreCommit = &cli.Command{ for _, sector := range pending { fmt.Println(sector.Number) } - return nil - } - fmt.Println("No sectors queued to be committed") + reader := bufio.NewReader(os.Stdin) + fmt.Print("Do you want to publish these sectors now? (yes/no): ") + userInput, err := reader.ReadString('\n') + if err != nil { + return xerrors.Errorf("reading user input: %w", err) + } + userInput = strings.ToLower(strings.TrimSpace(userInput)) + + if userInput == "yes" { + err := cctx.Set("publish-now", "true") + if err != nil { + return xerrors.Errorf("setting publish-now flag: %w", err) + } + return cctx.Command.Action(cctx) + } else if userInput == "no" { + return nil + } else { + fmt.Println("Invalid input. Please answer with 'yes' or 'no'.") + return nil + } + + } else { + fmt.Println("No sectors queued to be committed") + } return nil }, } @@ -2248,3 +2297,27 @@ var sectorsNumbersFreeCmd = &cli.Command{ return minerAPI.SectorNumFree(ctx, cctx.Args().First()) }, } + +var sectorsUnsealCmd = &cli.Command{ + Name: "unseal", + Usage: "unseal a sector", + ArgsUsage: "[sector number]", + Action: func(cctx *cli.Context) error { + minerAPI, closer, err := lcli.GetStorageMinerAPI(cctx) + if err != nil { + return err + } + defer closer() + ctx := lcli.ReqContext(cctx) + if cctx.NArg() != 1 { + return lcli.IncorrectNumArgs(cctx) + } + + sectorNum, err := strconv.ParseUint(cctx.Args().Get(0), 10, 64) + if err != nil { + return xerrors.Errorf("could not parse sector number: %w", err) + } + + return minerAPI.SectorUnseal(ctx, abi.SectorNumber(sectorNum)) + }, +} diff --git a/cmd/lotus-shed/actor.go b/cmd/lotus-shed/actor.go index 183ca1a9e..8562b63c3 100644 --- a/cmd/lotus-shed/actor.go +++ b/cmd/lotus-shed/actor.go @@ -968,7 +968,7 @@ var actorProposeChangeBeneficiary = &cli.Command{ var actorConfirmChangeBeneficiary = &cli.Command{ Name: "confirm-change-beneficiary", Usage: "Confirm a beneficiary address change", - ArgsUsage: "[minerAddress]", + ArgsUsage: "[minerID]", Flags: []cli.Flag{ &cli.BoolFlag{ Name: "really-do-it", diff --git a/cmd/lotus-shed/balances.go b/cmd/lotus-shed/balances.go index bae281583..28569cd12 100644 --- a/cmd/lotus-shed/balances.go +++ b/cmd/lotus-shed/balances.go @@ -35,6 +35,7 @@ import ( "github.com/filecoin-project/lotus/chain/consensus" "github.com/filecoin-project/lotus/chain/consensus/filcns" "github.com/filecoin-project/lotus/chain/gen/genesis" + "github.com/filecoin-project/lotus/chain/index" "github.com/filecoin-project/lotus/chain/state" "github.com/filecoin-project/lotus/chain/stmgr" "github.com/filecoin-project/lotus/chain/store" @@ -513,7 +514,7 @@ var chainBalanceStateCmd = &cli.Command{ cst := cbor.NewCborStore(bs) store := adt.WrapStore(ctx, cst) - sm, err := stmgr.NewStateManager(cs, consensus.NewTipSetExecutor(filcns.RewardFunc), vm.Syscalls(ffiwrapper.ProofVerifier), filcns.DefaultUpgradeSchedule(), nil, mds) + sm, err := stmgr.NewStateManager(cs, consensus.NewTipSetExecutor(filcns.RewardFunc), vm.Syscalls(ffiwrapper.ProofVerifier), filcns.DefaultUpgradeSchedule(), nil, mds, index.DummyMsgIndex) if err != nil { return err } @@ -737,7 +738,7 @@ var chainPledgeCmd = &cli.Command{ cst := cbor.NewCborStore(bs) store := adt.WrapStore(ctx, cst) - sm, err := stmgr.NewStateManager(cs, consensus.NewTipSetExecutor(filcns.RewardFunc), vm.Syscalls(ffiwrapper.ProofVerifier), filcns.DefaultUpgradeSchedule(), nil, mds) + sm, err := stmgr.NewStateManager(cs, consensus.NewTipSetExecutor(filcns.RewardFunc), vm.Syscalls(ffiwrapper.ProofVerifier), filcns.DefaultUpgradeSchedule(), nil, mds, index.DummyMsgIndex) if err != nil { return err } diff --git a/cmd/lotus-shed/chainwatch.go b/cmd/lotus-shed/chainwatch.go new file mode 100644 index 000000000..a7435a63f --- /dev/null +++ b/cmd/lotus-shed/chainwatch.go @@ -0,0 +1,383 @@ +package main + +import ( + "container/list" + "context" + "database/sql" + "fmt" + "hash/crc32" + "strconv" + "sync" + "time" + + "github.com/ipfs/go-cid" + "github.com/urfave/cli/v2" + + "github.com/filecoin-project/lotus/api" + "github.com/filecoin-project/lotus/chain/store" + "github.com/filecoin-project/lotus/chain/types" + cliutil "github.com/filecoin-project/lotus/cli/util" +) + +var chainwatchCmd = &cli.Command{ + Name: "chainwatch", + Usage: "lotus chainwatch", + Flags: []cli.Flag{ + &cli.StringFlag{ + Name: "db", + EnvVars: []string{"CHAINWATCH_DB"}, + Value: "./chainwatch.db", + }, + }, + Subcommands: []*cli.Command{ + chainwatchRunCmd, + chainwatchDotCmd, + }, +} + +var chainwatchDotCmd = &cli.Command{ + Name: "dot", + Usage: "generate dot graphs", + ArgsUsage: " ", + Action: func(cctx *cli.Context) error { + st, err := cwOpenStorage(cctx.String("db")) + if err != nil { + return err + } + + minH, err := strconv.ParseInt(cctx.Args().Get(0), 10, 32) + if err != nil { + return err + } + tosee, err := strconv.ParseInt(cctx.Args().Get(1), 10, 32) + if err != nil { + return err + } + maxH := minH + tosee + + res, err := st.db.Query(`select block, parent, b.miner, b.height, p.height from block_parents + inner join blocks b on block_parents.block = b.cid + inner join blocks p on block_parents.parent = p.cid +where b.height > ? and b.height < ?`, minH, maxH) + + if err != nil { + return err + } + + fmt.Println("digraph D {") + + for res.Next() { + var block, parent, miner string + var height, ph uint64 + if err := res.Scan(&block, &parent, &miner, &height, &ph); err != nil { + return err + } + + bc, err := cid.Parse(block) + if err != nil { + return err + } + + has := st.hasBlock(bc) + + col := crc32.Checksum([]byte(miner), crc32.MakeTable(crc32.Castagnoli))&0xc0c0c0c0 + 0x30303030 + + hasstr := "" + if !has { + //col = 0xffffffff + hasstr = " UNSYNCED" + } + + nulls := height - ph - 1 + for i := uint64(0); i < nulls; i++ { + name := block + "NP" + fmt.Sprint(i) + + fmt.Printf("%s [label = \"NULL:%d\", fillcolor = \"#ffddff\", style=filled, forcelabels=true]\n%s -> %s\n", + name, height-nulls+i, name, parent) + + parent = name + } + + fmt.Printf("%s [label = \"%s:%d%s\", fillcolor = \"#%06x\", style=filled, forcelabels=true]\n%s -> %s\n", block, miner, height, hasstr, col, block, parent) + } + if res.Err() != nil { + return res.Err() + } + + fmt.Println("}") + + return nil + }, +} + +var chainwatchRunCmd = &cli.Command{ + Name: "run", + Usage: "Start lotus chainwatch", + + Action: func(cctx *cli.Context) error { + api, closer, err := cliutil.GetFullNodeAPIV1(cctx) + if err != nil { + return err + } + defer closer() + ctx := cliutil.ReqContext(cctx) + + v, err := api.Version(ctx) + if err != nil { + return err + } + + log.Infof("Remote version: %s", v.Version) + + st, err := cwOpenStorage(cctx.String("db")) // todo flag + if err != nil { + return err + } + defer st.close() // nolint:errcheck + + cwRunSyncer(ctx, api, st) + go cwSubBlocks(ctx, api, st) + + <-ctx.Done() + return nil + }, +} + +func cwSubBlocks(ctx context.Context, api api.FullNode, st *cwStorage) { + sub, err := api.SyncIncomingBlocks(ctx) + if err != nil { + log.Error(err) + return + } + + for bh := range sub { + err := st.storeHeaders(map[cid.Cid]*types.BlockHeader{ + bh.Cid(): bh, + }, false) + if err != nil { + log.Error(err) + } + } +} + +func cwRunSyncer(ctx context.Context, api api.FullNode, st *cwStorage) { + notifs, err := api.ChainNotify(ctx) + if err != nil { + panic(err) + } + go func() { + for notif := range notifs { + for _, change := range notif { + switch change.Type { + case store.HCCurrent: + fallthrough + case store.HCApply: + syncHead(ctx, api, st, change.Val) + case store.HCRevert: + log.Warnf("revert todo") + } + } + } + }() +} + +func syncHead(ctx context.Context, api api.FullNode, st *cwStorage, ts *types.TipSet) { + log.Infof("Getting headers / actors") + + toSync := map[cid.Cid]*types.BlockHeader{} + toVisit := list.New() + + for _, header := range ts.Blocks() { + toVisit.PushBack(header) + } + + for toVisit.Len() > 0 { + bh := toVisit.Remove(toVisit.Back()).(*types.BlockHeader) + + if _, seen := toSync[bh.Cid()]; seen || st.hasBlock(bh.Cid()) { + continue + } + + toSync[bh.Cid()] = bh + + if len(toSync)%500 == 10 { + log.Infof("todo: (%d) %s", len(toSync), bh.Cid()) + } + + if len(bh.Parents) == 0 { + continue + } + + if bh.Height <= 530000 { + continue + } + + pts, err := api.ChainGetTipSet(ctx, types.NewTipSetKey(bh.Parents...)) + if err != nil { + log.Error(err) + continue + } + + for _, header := range pts.Blocks() { + toVisit.PushBack(header) + } + } + + log.Infof("Syncing %d blocks", len(toSync)) + + log.Infof("Persisting headers") + if err := st.storeHeaders(toSync, true); err != nil { + log.Error(err) + return + } + + log.Infof("Sync done") +} + +type cwStorage struct { + db *sql.DB + + headerLk sync.Mutex +} + +func cwOpenStorage(dbSource string) (*cwStorage, error) { + db, err := sql.Open("sqlite3", dbSource) + if err != nil { + return nil, err + } + + st := &cwStorage{db: db} + + return st, st.setup() +} + +func (st *cwStorage) setup() error { + tx, err := st.db.Begin() + if err != nil { + return err + } + _, err = tx.Exec(` +create table if not exists blocks +( + cid text not null + constraint blocks_pk + primary key, + parentWeight numeric not null, + parentStateRoot text not null, + height int not null, + miner text not null + constraint blocks_id_address_map_miner_fk + references id_address_map (address), + timestamp int not null, + vrfproof blob +); + +create unique index if not exists block_cid_uindex + on blocks (cid); + +create table if not exists blocks_synced +( + cid text not null + constraint blocks_synced_pk + primary key + constraint blocks_synced_blocks_cid_fk + references blocks, + add_ts int not null +); + +create unique index if not exists blocks_synced_cid_uindex + on blocks_synced (cid); + +create table if not exists block_parents +( + block text not null + constraint block_parents_blocks_cid_fk + references blocks, + parent text not null + constraint block_parents_blocks_cid_fk_2 + references blocks +); + +create unique index if not exists block_parents_block_parent_uindex + on block_parents (block, parent); + +create unique index if not exists blocks_cid_uindex + on blocks (cid); +`) + if err != nil { + return err + } + return tx.Commit() +} + +func (st *cwStorage) hasBlock(bh cid.Cid) bool { + var exitsts bool + err := st.db.QueryRow(`select exists (select 1 FROM blocks_synced where cid=?)`, bh.String()).Scan(&exitsts) + if err != nil { + log.Error(err) + return false + } + return exitsts +} + +func (st *cwStorage) storeHeaders(bhs map[cid.Cid]*types.BlockHeader, sync bool) error { + st.headerLk.Lock() + defer st.headerLk.Unlock() + + tx, err := st.db.Begin() + if err != nil { + return err + } + + stmt, err := tx.Prepare(`insert into blocks (cid, parentWeight, parentStateRoot, height, miner, "timestamp", vrfproof) values (?, ?, ?, ?, ?, ?, ?) on conflict do nothing`) + if err != nil { + return err + } + defer stmt.Close() // nolint:errcheck + for _, bh := range bhs { + if _, err := stmt.Exec(bh.Cid().String(), + bh.ParentWeight.String(), + bh.ParentStateRoot.String(), + bh.Height, + bh.Miner.String(), + bh.Timestamp, + bh.Ticket.VRFProof, + ); err != nil { + return err + } + } + + stmt2, err := tx.Prepare(`insert into block_parents (block, parent) values (?, ?) on conflict do nothing`) + if err != nil { + return err + } + defer stmt2.Close() // nolint:errcheck + for _, bh := range bhs { + for _, parent := range bh.Parents { + if _, err := stmt2.Exec(bh.Cid().String(), parent.String()); err != nil { + return err + } + } + } + + if sync { + stmt, err := tx.Prepare(`insert into blocks_synced (cid, add_ts) values (?, ?) on conflict do nothing`) + if err != nil { + return err + } + defer stmt.Close() // nolint:errcheck + now := time.Now().Unix() + + for _, bh := range bhs { + if _, err := stmt.Exec(bh.Cid().String(), now); err != nil { + return err + } + } + } + + return tx.Commit() +} + +func (st *cwStorage) close() error { + return st.db.Close() +} diff --git a/cmd/lotus-shed/datastore-vlog.go b/cmd/lotus-shed/datastore-vlog.go index af412df19..936d33849 100644 --- a/cmd/lotus-shed/datastore-vlog.go +++ b/cmd/lotus-shed/datastore-vlog.go @@ -12,8 +12,8 @@ import ( "strings" "github.com/dgraph-io/badger/v2/y" + block "github.com/ipfs/go-block-format" "github.com/ipfs/go-cid" - block "github.com/ipfs/go-libipfs/blocks" "github.com/mitchellh/go-homedir" "github.com/multiformats/go-base32" "github.com/urfave/cli/v2" diff --git a/cmd/lotus-shed/export.go b/cmd/lotus-shed/export.go index d67fa4493..459de3383 100644 --- a/cmd/lotus-shed/export.go +++ b/cmd/lotus-shed/export.go @@ -15,11 +15,11 @@ import ( "github.com/dgraph-io/badger/v2" "github.com/dgraph-io/badger/v2/pb" "github.com/dustin/go-humanize" + block "github.com/ipfs/go-block-format" "github.com/ipfs/go-blockservice" "github.com/ipfs/go-cid" offline "github.com/ipfs/go-ipfs-exchange-offline" ipld "github.com/ipfs/go-ipld-format" - block "github.com/ipfs/go-libipfs/blocks" "github.com/ipfs/go-merkledag" "github.com/ipld/go-car" "github.com/multiformats/go-base32" diff --git a/cmd/lotus-shed/fevmanalytics.go b/cmd/lotus-shed/fevmanalytics.go new file mode 100644 index 000000000..19416b77e --- /dev/null +++ b/cmd/lotus-shed/fevmanalytics.go @@ -0,0 +1,257 @@ +package main + +import ( + "fmt" + "os" + "path/filepath" + + "github.com/ipfs/go-cid" + cbor "github.com/ipfs/go-ipld-cbor" + "github.com/urfave/cli/v2" + "golang.org/x/net/context" + "golang.org/x/xerrors" + + "github.com/filecoin-project/go-address" + "github.com/filecoin-project/go-state-types/abi" + "github.com/filecoin-project/go-state-types/big" + + badgerbs "github.com/filecoin-project/lotus/blockstore/badger" + "github.com/filecoin-project/lotus/chain/actors/adt" + "github.com/filecoin-project/lotus/chain/actors/builtin" + evm2 "github.com/filecoin-project/lotus/chain/actors/builtin/evm" + "github.com/filecoin-project/lotus/chain/state" + "github.com/filecoin-project/lotus/chain/types" + "github.com/filecoin-project/lotus/node/repo" +) + +var FevmAnalyticsCmd = &cli.Command{ + Name: "evm-analytics", + Usage: "Get FEVM related metrics", + Flags: []cli.Flag{ + &cli.StringFlag{ + Name: "repo", + Value: "~/.lotus", + }, + }, + Subcommands: []*cli.Command{ + FevmBalanceCmd, + FevmActorsCmd, + }, +} + +var FevmBalanceCmd = &cli.Command{ + Name: "evm-balance", + Usage: "Balances in eth accounts, evm contracts and placeholders", + ArgsUsage: "[state root]", + + Action: func(cctx *cli.Context) error { + if cctx.NArg() != 1 { + return xerrors.New("only needs state root") + } + + if !cctx.Args().Present() { + return fmt.Errorf("must pass state root") + } + + sroot, err := cid.Decode(cctx.Args().First()) + if err != nil { + return fmt.Errorf("failed to parse input: %w", err) + } + + fsrepo, err := repo.NewFS(cctx.String("repo")) + if err != nil { + return err + } + + lkrepo, err := fsrepo.Lock(repo.FullNode) + if err != nil { + return err + } + + defer lkrepo.Close() //nolint:errcheck + + path, err := lkrepo.SplitstorePath() + if err != nil { + return err + } + + path = filepath.Join(path, "hot.badger") + if err := os.MkdirAll(path, 0755); err != nil { + return err + } + + opts, err := repo.BadgerBlockstoreOptions(repo.HotBlockstore, path, lkrepo.Readonly()) + if err != nil { + return err + } + + bs, err := badgerbs.Open(opts) + if err != nil { + return err + } + + cst := cbor.NewCborStore(bs) + st, err := state.LoadStateTree(cst, sroot) + if err != nil { + return err + } + + fmt.Println("iterating over all actors") + count := 0 + balanceEvm := abi.NewTokenAmount(0) + balanceEthAccount := abi.NewTokenAmount(0) + balancePlaceholder := abi.NewTokenAmount(0) + + err = st.ForEach(func(addr address.Address, act *types.Actor) error { + if count%200000 == 0 { + fmt.Println("processed /n", count) + } + count++ + + if builtin.IsEvmActor(act.Code) { + balanceEvm = types.BigAdd(balanceEvm, act.Balance) + } + + if builtin.IsEthAccountActor(act.Code) { + balanceEthAccount = types.BigAdd(balanceEthAccount, act.Balance) + } + + if builtin.IsPlaceholderActor(act.Code) { + balancePlaceholder = types.BigAdd(balancePlaceholder, act.Balance) + } + + return nil + }) + if err != nil { + return err + } + + fmt.Println("balances in Eth contracts: ", balanceEvm) + fmt.Println("balances in Eth accounts: ", balanceEthAccount) + fmt.Println("balances in placeholder: ", balancePlaceholder) + fmt.Println("Total balances: ", big.Add(big.Add(balanceEthAccount, balancePlaceholder), balanceEvm)) + return nil + }, +} + +var FevmActorsCmd = &cli.Command{ + Name: "evm-actors", + Usage: "actors # in eth accounts, evm contracts and placeholders", + ArgsUsage: "[state root]", + + Action: func(cctx *cli.Context) error { + if cctx.NArg() != 1 { + return xerrors.New("only needs state root") + } + + if !cctx.Args().Present() { + return fmt.Errorf("must pass state root") + } + + sroot, err := cid.Decode(cctx.Args().First()) + if err != nil { + return fmt.Errorf("failed to parse input: %w", err) + } + + fsrepo, err := repo.NewFS(cctx.String("repo")) + if err != nil { + return err + } + + lkrepo, err := fsrepo.Lock(repo.FullNode) + if err != nil { + return err + } + + defer lkrepo.Close() //nolint:errcheck + + path, err := lkrepo.SplitstorePath() + if err != nil { + return err + } + + path = filepath.Join(path, "hot.badger") + if err := os.MkdirAll(path, 0755); err != nil { + return err + } + + opts, err := repo.BadgerBlockstoreOptions(repo.HotBlockstore, path, lkrepo.Readonly()) + if err != nil { + return err + } + + bs, err := badgerbs.Open(opts) + if err != nil { + return err + } + + ctx := context.TODO() + cst := cbor.NewCborStore(bs) + store := adt.WrapStore(ctx, cst) + + st, err := state.LoadStateTree(cst, sroot) + if err != nil { + return err + } + + fmt.Println("iterating over all actors") + count := 0 + EvmCount := 0 + EthAccountCount := 0 + PlaceholderCount := 0 + ea := []cid.Cid{} + + err = st.ForEach(func(addr address.Address, act *types.Actor) error { + if count%200000 == 0 { + fmt.Println("processed /n", count) + } + count++ + + if builtin.IsEvmActor(act.Code) { + EvmCount++ + e, err := evm2.Load(store, act) + if err != nil { + return xerrors.Errorf("fail to load evm actor: %w", err) + } + bcid, err := e.GetBytecodeCID() + if err != nil { + return err + } + + ea = append(ea, bcid) + } + + if builtin.IsEthAccountActor(act.Code) { + EthAccountCount++ + } + + if builtin.IsPlaceholderActor(act.Code) { + PlaceholderCount++ + } + + return nil + }) + if err != nil { + return err + } + + uniquesa := unique(ea) + fmt.Println("# of EVM contracts: ", EvmCount) + fmt.Println("# of unqiue EVM contracts: ", len(uniquesa)) + fmt.Println("b# of Eth accounts: ", EthAccountCount) + fmt.Println("# of placeholder: ", PlaceholderCount) + return nil + }, +} + +func unique(intSlice []cid.Cid) []cid.Cid { + keys := make(map[cid.Cid]bool) + list := []cid.Cid{} + for _, entry := range intSlice { + if _, value := keys[entry]; !value { + keys[entry] = true + list = append(list, entry) + } + } + return list +} diff --git a/cmd/lotus-shed/gas-estimation.go b/cmd/lotus-shed/gas-estimation.go index ab455ebae..e02e2a722 100644 --- a/cmd/lotus-shed/gas-estimation.go +++ b/cmd/lotus-shed/gas-estimation.go @@ -20,6 +20,7 @@ import ( "github.com/filecoin-project/lotus/chain/beacon/drand" "github.com/filecoin-project/lotus/chain/consensus" "github.com/filecoin-project/lotus/chain/consensus/filcns" + "github.com/filecoin-project/lotus/chain/index" "github.com/filecoin-project/lotus/chain/stmgr" "github.com/filecoin-project/lotus/chain/store" "github.com/filecoin-project/lotus/chain/types" @@ -111,7 +112,7 @@ var gasTraceCmd = &cli.Command{ cs := store.NewChainStore(bs, bs, mds, filcns.Weight, nil) defer cs.Close() //nolint:errcheck - sm, err := stmgr.NewStateManager(cs, consensus.NewTipSetExecutor(filcns.RewardFunc), vm.Syscalls(ffiwrapper.ProofVerifier), filcns.DefaultUpgradeSchedule(), shd, mds) + sm, err := stmgr.NewStateManager(cs, consensus.NewTipSetExecutor(filcns.RewardFunc), vm.Syscalls(ffiwrapper.ProofVerifier), filcns.DefaultUpgradeSchedule(), shd, mds, index.DummyMsgIndex) if err != nil { return err } @@ -212,7 +213,7 @@ var replayOfflineCmd = &cli.Command{ cs := store.NewChainStore(bs, bs, mds, filcns.Weight, nil) defer cs.Close() //nolint:errcheck - sm, err := stmgr.NewStateManager(cs, consensus.NewTipSetExecutor(filcns.RewardFunc), vm.Syscalls(ffiwrapper.ProofVerifier), filcns.DefaultUpgradeSchedule(), shd, mds) + sm, err := stmgr.NewStateManager(cs, consensus.NewTipSetExecutor(filcns.RewardFunc), vm.Syscalls(ffiwrapper.ProofVerifier), filcns.DefaultUpgradeSchedule(), shd, mds, index.DummyMsgIndex) if err != nil { return err } diff --git a/cmd/lotus-shed/import-car.go b/cmd/lotus-shed/import-car.go index 4c636a3af..973e7b31b 100644 --- a/cmd/lotus-shed/import-car.go +++ b/cmd/lotus-shed/import-car.go @@ -7,8 +7,8 @@ import ( "io" "os" + block "github.com/ipfs/go-block-format" "github.com/ipfs/go-cid" - block "github.com/ipfs/go-libipfs/blocks" "github.com/ipld/go-car" "github.com/urfave/cli/v2" "golang.org/x/xerrors" diff --git a/cmd/lotus-shed/invariants.go b/cmd/lotus-shed/invariants.go index b759e2c2c..45ad43170 100644 --- a/cmd/lotus-shed/invariants.go +++ b/cmd/lotus-shed/invariants.go @@ -21,6 +21,7 @@ import ( "github.com/filecoin-project/lotus/chain/actors" "github.com/filecoin-project/lotus/chain/consensus" "github.com/filecoin-project/lotus/chain/consensus/filcns" + "github.com/filecoin-project/lotus/chain/index" "github.com/filecoin-project/lotus/chain/stmgr" "github.com/filecoin-project/lotus/chain/store" "github.com/filecoin-project/lotus/chain/types" @@ -90,7 +91,7 @@ var invariantsCmd = &cli.Command{ cs := store.NewChainStore(bs, bs, mds, filcns.Weight, nil) defer cs.Close() //nolint:errcheck - sm, err := stmgr.NewStateManager(cs, consensus.NewTipSetExecutor(filcns.RewardFunc), vm.Syscalls(ffiwrapper.ProofVerifier), filcns.DefaultUpgradeSchedule(), nil, mds) + sm, err := stmgr.NewStateManager(cs, consensus.NewTipSetExecutor(filcns.RewardFunc), vm.Syscalls(ffiwrapper.ProofVerifier), filcns.DefaultUpgradeSchedule(), nil, mds, index.DummyMsgIndex) if err != nil { return err } diff --git a/cmd/lotus-shed/main.go b/cmd/lotus-shed/main.go index 19072dd71..9cb1cd32c 100644 --- a/cmd/lotus-shed/main.go +++ b/cmd/lotus-shed/main.go @@ -26,6 +26,7 @@ func main() { base32Cmd, base16Cmd, bitFieldCmd, + chainwatchCmd, cronWcCmd, frozenMinersCmd, dealLabelCmd, @@ -83,6 +84,9 @@ func main() { invariantsCmd, gasTraceCmd, replayOfflineCmd, + msgindexCmd, + FevmAnalyticsCmd, + mismatchesCmd, } app := &cli.App{ diff --git a/cmd/lotus-shed/market.go b/cmd/lotus-shed/market.go index 98e3d36b7..4436e3c40 100644 --- a/cmd/lotus-shed/market.go +++ b/cmd/lotus-shed/market.go @@ -7,7 +7,6 @@ import ( "os" "path" - "github.com/ipfs/go-cid" "github.com/ipfs/go-datastore" dsq "github.com/ipfs/go-datastore/query" levelds "github.com/ipfs/go-ds-leveldb" @@ -65,26 +64,22 @@ var marketCronStateCmd = &cli.Command{ if err != nil { return err } - a, err := api.StateReadState(ctx, builtin.StorageMarketActorAddr, ts.Key()) - if err != nil { - return err - } - st, ok := a.State.(map[string]interface{}) - if !ok { - return xerrors.Errorf("failed to cast state map to expected form") - } - dealOpsRaw, ok := st["DealOpsByEpoch"].(map[string]interface{}) - if !ok { - return xerrors.Errorf("failed to read sectors root from state") - } - // string is of the form "/:bafy.." so [2:] to drop the path - dealOpsRoot, err := cid.Parse(dealOpsRaw["/"]) - if err != nil { - return err - } + bs := ReadOnlyAPIBlockstore{api} adtStore := adt.WrapStore(ctx, ipldcbor.NewCborStore(&bs)) - dealOpsEpochSet, err := adt.AsMap(adtStore, dealOpsRoot, builtin.DefaultHamtBitwidth) + + mAct, err := api.StateGetActor(ctx, builtin.StorageMarketActorAddr, ts.Key()) + if err != nil { + return err + } + + var mSt market11.State + err = adtStore.Get(ctx, mAct.Head, &mSt) + if err != nil { + return err + } + + dealOpsEpochSet, err := adt.AsMap(adtStore, mSt.DealOpsByEpoch, builtin.DefaultHamtBitwidth) if err != nil { return err } @@ -100,7 +95,7 @@ var marketCronStateCmd = &cli.Command{ return err } - dealOpsMultiMap, err := market11.AsSetMultimap(adtStore, dealOpsRoot, builtin.DefaultHamtBitwidth, builtin.DefaultHamtBitwidth) + dealOpsMultiMap, err := market11.AsSetMultimap(adtStore, mSt.DealOpsByEpoch, builtin.DefaultHamtBitwidth, builtin.DefaultHamtBitwidth) if err != nil { return err } diff --git a/cmd/lotus-shed/migrations.go b/cmd/lotus-shed/migrations.go index 53719f5af..82a1afddf 100644 --- a/cmd/lotus-shed/migrations.go +++ b/cmd/lotus-shed/migrations.go @@ -45,6 +45,7 @@ import ( "github.com/filecoin-project/lotus/chain/actors/builtin/verifreg" "github.com/filecoin-project/lotus/chain/consensus" "github.com/filecoin-project/lotus/chain/consensus/filcns" + "github.com/filecoin-project/lotus/chain/index" "github.com/filecoin-project/lotus/chain/state" "github.com/filecoin-project/lotus/chain/stmgr" "github.com/filecoin-project/lotus/chain/store" @@ -72,6 +73,7 @@ var migrationsCmd = &cli.Command{ }, }, Action: func(cctx *cli.Context) error { + fmt.Println("REMINDER: If you are running this, you likely want to ALSO run the continuity testing tool!") ctx := context.TODO() if cctx.NArg() != 2 { @@ -155,7 +157,7 @@ var migrationsCmd = &cli.Command{ defer cs.Close() //nolint:errcheck // Note: we use a map datastore for the metadata to avoid writing / using cached migration results in the metadata store - sm, err := stmgr.NewStateManager(cs, consensus.NewTipSetExecutor(filcns.RewardFunc), vm.Syscalls(ffiwrapper.ProofVerifier), filcns.DefaultUpgradeSchedule(), nil, datastore.NewMapDatastore()) + sm, err := stmgr.NewStateManager(cs, consensus.NewTipSetExecutor(filcns.RewardFunc), vm.Syscalls(ffiwrapper.ProofVerifier), filcns.DefaultUpgradeSchedule(), nil, datastore.NewMapDatastore(), index.DummyMsgIndex) if err != nil { return err } diff --git a/cmd/lotus-shed/miner.go b/cmd/lotus-shed/miner.go index 1772ced63..a8bb93744 100644 --- a/cmd/lotus-shed/miner.go +++ b/cmd/lotus-shed/miner.go @@ -12,9 +12,9 @@ import ( "strings" "github.com/docker/go-units" + block "github.com/ipfs/go-block-format" "github.com/ipfs/go-cid" ipldcbor "github.com/ipfs/go-ipld-cbor" - block "github.com/ipfs/go-libipfs/blocks" "github.com/mitchellh/go-homedir" "github.com/urfave/cli/v2" cbg "github.com/whyrusleeping/cbor-gen" diff --git a/cmd/lotus-shed/mismatches.go b/cmd/lotus-shed/mismatches.go new file mode 100644 index 000000000..223158e0f --- /dev/null +++ b/cmd/lotus-shed/mismatches.go @@ -0,0 +1,54 @@ +package main + +import ( + "fmt" + + "github.com/urfave/cli/v2" + + lcli "github.com/filecoin-project/lotus/cli" +) + +var mismatchesCmd = &cli.Command{ + Name: "mismatches", + Description: "Walk up the chain, recomputing state, and reporting any mismatches", + Action: func(cctx *cli.Context) error { + srv, err := lcli.GetFullNodeServices(cctx) + if err != nil { + return err + } + defer srv.Close() //nolint:errcheck + + api := srv.FullNodeAPI() + ctx := lcli.ReqContext(cctx) + + checkTs, err := api.ChainHead(ctx) + if err != nil { + return err + } + + for checkTs.Height() != 0 { + if checkTs.Height()%10000 == 0 { + fmt.Println("Reached height ", checkTs.Height()) + } + + execTsk := checkTs.Parents() + execTs, err := api.ChainGetTipSet(ctx, execTsk) + if err != nil { + return err + } + + st, err := api.StateCompute(ctx, execTs.Height(), nil, execTsk) + if err != nil { + return err + } + + if st.Root != checkTs.ParentState() { + fmt.Println("consensus mismatch found at height ", execTs.Height()) + } + + checkTs = execTs + } + + return nil + }, +} diff --git a/cmd/lotus-shed/msgindex.go b/cmd/lotus-shed/msgindex.go new file mode 100644 index 000000000..fae733bbe --- /dev/null +++ b/cmd/lotus-shed/msgindex.go @@ -0,0 +1,221 @@ +package main + +import ( + "database/sql" + "fmt" + "path" + + "github.com/ipfs/go-cid" + _ "github.com/mattn/go-sqlite3" + "github.com/mitchellh/go-homedir" + "github.com/urfave/cli/v2" + "golang.org/x/xerrors" + + "github.com/filecoin-project/go-state-types/abi" + + lcli "github.com/filecoin-project/lotus/cli" +) + +var msgindexCmd = &cli.Command{ + Name: "msgindex", + Usage: "Tools for managing the message index", + Subcommands: []*cli.Command{ + msgindexBackfillCmd, + msgindexPruneCmd, + }, +} + +var msgindexBackfillCmd = &cli.Command{ + Name: "backfill", + Usage: "Backfill the message index for a number of epochs starting from a specified height", + Flags: []cli.Flag{ + &cli.IntFlag{ + Name: "from", + Value: 0, + Usage: "height to start the backfill; uses the current head if omitted", + }, + &cli.IntFlag{ + Name: "epochs", + Value: 1800, + Usage: "number of epochs to backfill; defaults to 1800 (2 finalities)", + }, + &cli.StringFlag{ + Name: "repo", + Value: "~/.lotus", + Usage: "path to the repo", + }, + }, + Action: func(cctx *cli.Context) error { + api, closer, err := lcli.GetFullNodeAPI(cctx) + if err != nil { + return err + } + + defer closer() + ctx := lcli.ReqContext(cctx) + + curTs, err := api.ChainHead(ctx) + if err != nil { + return err + } + + startHeight := int64(cctx.Int("from")) + if startHeight == 0 { + startHeight = int64(curTs.Height()) - 1 + } + epochs := cctx.Int("epochs") + + basePath, err := homedir.Expand(cctx.String("repo")) + if err != nil { + return err + } + + dbPath := path.Join(basePath, "sqlite", "msgindex.db") + db, err := sql.Open("sqlite3", dbPath) + if err != nil { + return err + } + + defer func() { + err := db.Close() + if err != nil { + fmt.Printf("ERROR: closing db: %s", err) + } + }() + + tx, err := db.Begin() + if err != nil { + return err + } + + insertStmt, err := tx.Prepare("INSERT INTO messages VALUES (?, ?, ?)") + if err != nil { + return err + } + + insertMsg := func(cid, tsCid cid.Cid, epoch abi.ChainEpoch) error { + key := cid.String() + tskey := tsCid.String() + if _, err := insertStmt.Exec(key, tskey, int64(epoch)); err != nil { + return err + } + + return nil + } + rollback := func() { + if err := tx.Rollback(); err != nil { + fmt.Printf("ERROR: rollback: %s", err) + } + } + + for i := 0; i < epochs; i++ { + epoch := abi.ChainEpoch(startHeight - int64(i)) + + ts, err := api.ChainGetTipSetByHeight(ctx, epoch, curTs.Key()) + if err != nil { + rollback() + return err + } + + tsCid, err := ts.Key().Cid() + if err != nil { + rollback() + return err + } + + msgs, err := api.ChainGetMessagesInTipset(ctx, ts.Key()) + if err != nil { + rollback() + return err + } + + for _, msg := range msgs { + if err := insertMsg(msg.Cid, tsCid, epoch); err != nil { + rollback() + return err + } + } + } + + if err := tx.Commit(); err != nil { + return err + } + + return nil + }, +} + +var msgindexPruneCmd = &cli.Command{ + Name: "prune", + Usage: "Prune the message index for messages included before a given epoch", + Flags: []cli.Flag{ + &cli.IntFlag{ + Name: "from", + Usage: "height to start the prune; if negative it indicates epochs from current head", + }, + &cli.StringFlag{ + Name: "repo", + Value: "~/.lotus", + Usage: "path to the repo", + }, + }, + Action: func(cctx *cli.Context) error { + api, closer, err := lcli.GetFullNodeAPI(cctx) + if err != nil { + return err + } + + defer closer() + ctx := lcli.ReqContext(cctx) + + startHeight := int64(cctx.Int("from")) + if startHeight < 0 { + curTs, err := api.ChainHead(ctx) + if err != nil { + return err + } + + startHeight += int64(curTs.Height()) + + if startHeight < 0 { + return xerrors.Errorf("bogus start height %d", startHeight) + } + } + + basePath, err := homedir.Expand(cctx.String("repo")) + if err != nil { + return err + } + + dbPath := path.Join(basePath, "sqlite", "msgindex.db") + db, err := sql.Open("sqlite3", dbPath) + if err != nil { + return err + } + + defer func() { + err := db.Close() + if err != nil { + fmt.Printf("ERROR: closing db: %s", err) + } + }() + + tx, err := db.Begin() + if err != nil { + return err + } + + if _, err := tx.Exec("DELETE FROM messages WHERE epoch < ?", startHeight); err != nil { + if err := tx.Rollback(); err != nil { + fmt.Printf("ERROR: rollback: %s", err) + } + return err + } + + if err := tx.Commit(); err != nil { + return err + } + + return nil + }, +} diff --git a/cmd/lotus-shed/state-stats.go b/cmd/lotus-shed/state-stats.go index 28fa79778..e07c63589 100644 --- a/cmd/lotus-shed/state-stats.go +++ b/cmd/lotus-shed/state-stats.go @@ -26,6 +26,7 @@ import ( "github.com/filecoin-project/lotus/chain/actors/builtin" "github.com/filecoin-project/lotus/chain/consensus" "github.com/filecoin-project/lotus/chain/consensus/filcns" + "github.com/filecoin-project/lotus/chain/index" "github.com/filecoin-project/lotus/chain/stmgr" "github.com/filecoin-project/lotus/chain/store" "github.com/filecoin-project/lotus/chain/types" @@ -308,7 +309,7 @@ to reduce the number of decode operations performed by caching the decoded objec } tsExec := consensus.NewTipSetExecutor(filcns.RewardFunc) - sm, err := stmgr.NewStateManager(cs, tsExec, vm.Syscalls(ffiwrapper.ProofVerifier), filcns.DefaultUpgradeSchedule(), nil, mds) + sm, err := stmgr.NewStateManager(cs, tsExec, vm.Syscalls(ffiwrapper.ProofVerifier), filcns.DefaultUpgradeSchedule(), nil, mds, index.DummyMsgIndex) if err != nil { return err } diff --git a/cmd/lotus-sim/simulation/block.go b/cmd/lotus-sim/simulation/block.go index 4dddba921..7cf5a6be6 100644 --- a/cmd/lotus-sim/simulation/block.go +++ b/cmd/lotus-sim/simulation/block.go @@ -80,7 +80,7 @@ func (sim *Simulation) makeTipSet(ctx context.Context, messages []*types.Message return nil, xerrors.Errorf("failed to create new tipset: %w", err) } - err = sim.Node.Chainstore.PersistTipset(ctx, newTipSet) + err = sim.Node.Chainstore.PersistTipsets(ctx, []*types.TipSet{newTipSet}) if err != nil { return nil, xerrors.Errorf("failed to persist block headers: %w", err) } diff --git a/cmd/lotus-sim/simulation/node.go b/cmd/lotus-sim/simulation/node.go index 9b37da6c8..f232e0d21 100644 --- a/cmd/lotus-sim/simulation/node.go +++ b/cmd/lotus-sim/simulation/node.go @@ -12,6 +12,7 @@ import ( "github.com/filecoin-project/lotus/blockstore" "github.com/filecoin-project/lotus/chain/consensus" "github.com/filecoin-project/lotus/chain/consensus/filcns" + "github.com/filecoin-project/lotus/chain/index" "github.com/filecoin-project/lotus/chain/stmgr" "github.com/filecoin-project/lotus/chain/store" "github.com/filecoin-project/lotus/chain/types" @@ -106,7 +107,7 @@ func (nd *Node) LoadSim(ctx context.Context, name string) (*Simulation, error) { if err != nil { return nil, xerrors.Errorf("failed to create upgrade schedule for simulation %s: %w", name, err) } - sim.StateManager, err = stmgr.NewStateManager(nd.Chainstore, consensus.NewTipSetExecutor(filcns.RewardFunc), vm.Syscalls(mock.Verifier), us, nil, nd.MetadataDS) + sim.StateManager, err = stmgr.NewStateManager(nd.Chainstore, consensus.NewTipSetExecutor(filcns.RewardFunc), vm.Syscalls(mock.Verifier), us, nil, nd.MetadataDS, index.DummyMsgIndex) if err != nil { return nil, xerrors.Errorf("failed to create state manager for simulation %s: %w", name, err) } @@ -125,7 +126,7 @@ func (nd *Node) CreateSim(ctx context.Context, name string, head *types.TipSet) if err != nil { return nil, err } - sm, err := stmgr.NewStateManager(nd.Chainstore, consensus.NewTipSetExecutor(filcns.RewardFunc), vm.Syscalls(mock.Verifier), filcns.DefaultUpgradeSchedule(), nil, nd.MetadataDS) + sm, err := stmgr.NewStateManager(nd.Chainstore, consensus.NewTipSetExecutor(filcns.RewardFunc), vm.Syscalls(mock.Verifier), filcns.DefaultUpgradeSchedule(), nil, nd.MetadataDS, index.DummyMsgIndex) if err != nil { return nil, xerrors.Errorf("creating state manager: %w", err) } diff --git a/cmd/lotus-sim/simulation/simulation.go b/cmd/lotus-sim/simulation/simulation.go index 294f4cfbc..47d06aeda 100644 --- a/cmd/lotus-sim/simulation/simulation.go +++ b/cmd/lotus-sim/simulation/simulation.go @@ -17,6 +17,7 @@ import ( "github.com/filecoin-project/lotus/chain/consensus" "github.com/filecoin-project/lotus/chain/consensus/filcns" + "github.com/filecoin-project/lotus/chain/index" "github.com/filecoin-project/lotus/chain/stmgr" "github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/vm" @@ -201,7 +202,7 @@ func (sim *Simulation) SetUpgradeHeight(nv network.Version, epoch abi.ChainEpoch if err != nil { return err } - sm, err := stmgr.NewStateManager(sim.Node.Chainstore, consensus.NewTipSetExecutor(filcns.RewardFunc), vm.Syscalls(mock.Verifier), newUpgradeSchedule, nil, sim.Node.MetadataDS) + sm, err := stmgr.NewStateManager(sim.Node.Chainstore, consensus.NewTipSetExecutor(filcns.RewardFunc), vm.Syscalls(mock.Verifier), newUpgradeSchedule, nil, sim.Node.MetadataDS, index.DummyMsgIndex) if err != nil { return err } diff --git a/cmd/lotus-worker/main.go b/cmd/lotus-worker/main.go index e0a931274..944791275 100644 --- a/cmd/lotus-worker/main.go +++ b/cmd/lotus-worker/main.go @@ -275,6 +275,12 @@ var runCmd = &cli.Command{ Name: "http-server-timeout", Value: "30s", }, + &cli.BoolFlag{ + Name: "data-cid", + Usage: "Run the data-cid task. true|false", + Value: true, + DefaultText: "inherits --addpiece", + }, }, Before: func(cctx *cli.Context) error { if cctx.IsSet("address") { @@ -295,6 +301,13 @@ var runCmd = &cli.Command{ } } + // ensure tmpdir exists + td := os.TempDir() + if err := os.MkdirAll(td, 0755); err != nil { + return xerrors.Errorf("ensuring temp dir %s exists: %w", td, err) + } + + // Check file descriptor limit limit, _, err := ulimit.GetLimit() switch { case err == ulimit.ErrUnsupported: @@ -379,8 +392,19 @@ var runCmd = &cli.Command{ } } + ttDataCidDefault := false if (workerType == sealtasks.WorkerSealing || cctx.IsSet("addpiece")) && cctx.Bool("addpiece") { - taskTypes = append(taskTypes, sealtasks.TTAddPiece, sealtasks.TTDataCid) + taskTypes = append(taskTypes, sealtasks.TTAddPiece) + ttDataCidDefault = true + } + if workerType == sealtasks.WorkerSealing { + if cctx.IsSet("data-cid") { + if cctx.Bool("data-cid") { + taskTypes = append(taskTypes, sealtasks.TTDataCid) + } + } else if ttDataCidDefault { + taskTypes = append(taskTypes, sealtasks.TTDataCid) + } } if (workerType == sealtasks.WorkerSealing || cctx.IsSet("sector-download")) && cctx.Bool("sector-download") { taskTypes = append(taskTypes, sealtasks.TTDownloadSector) diff --git a/cmd/lotus/daemon.go b/cmd/lotus/daemon.go index 3803c0f5d..fbb9dfd9a 100644 --- a/cmd/lotus/daemon.go +++ b/cmd/lotus/daemon.go @@ -10,8 +10,8 @@ import ( "encoding/json" "fmt" "io" - "net/http" "os" + "path" "runtime/pprof" "strings" @@ -34,6 +34,7 @@ import ( "github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/chain/consensus" "github.com/filecoin-project/lotus/chain/consensus/filcns" + "github.com/filecoin-project/lotus/chain/index" "github.com/filecoin-project/lotus/chain/stmgr" "github.com/filecoin-project/lotus/chain/store" "github.com/filecoin-project/lotus/chain/types" @@ -41,10 +42,12 @@ import ( lcli "github.com/filecoin-project/lotus/cli" "github.com/filecoin-project/lotus/journal" "github.com/filecoin-project/lotus/journal/fsjournal" + "github.com/filecoin-project/lotus/lib/httpreader" "github.com/filecoin-project/lotus/lib/peermgr" "github.com/filecoin-project/lotus/lib/ulimit" "github.com/filecoin-project/lotus/metrics" "github.com/filecoin-project/lotus/node" + "github.com/filecoin-project/lotus/node/config" "github.com/filecoin-project/lotus/node/modules" "github.com/filecoin-project/lotus/node/modules/dtypes" "github.com/filecoin-project/lotus/node/modules/testing" @@ -431,18 +434,13 @@ func ImportChain(ctx context.Context, r repo.Repo, fname string, snapshot bool) var rd io.Reader var l int64 if strings.HasPrefix(fname, "http://") || strings.HasPrefix(fname, "https://") { - resp, err := http.Get(fname) //nolint:gosec + rrd, err := httpreader.NewResumableReader(ctx, fname) if err != nil { - return err - } - defer resp.Body.Close() //nolint:errcheck - - if resp.StatusCode != http.StatusOK { - return xerrors.Errorf("fetching chain CAR failed with non-200 response: %d", resp.StatusCode) + return xerrors.Errorf("fetching chain CAR failed: setting up resumable reader: %w", err) } - rd = resp.Body - l = resp.ContentLength + rd = rrd + l = rrd.ContentLength() } else { fname, err = homedir.Expand(fname) if err != nil { @@ -539,7 +537,7 @@ func ImportChain(ctx context.Context, r repo.Repo, fname string, snapshot bool) } // TODO: We need to supply the actual beacon after v14 - stm, err := stmgr.NewStateManager(cst, consensus.NewTipSetExecutor(filcns.RewardFunc), vm.Syscalls(ffiwrapper.ProofVerifier), filcns.DefaultUpgradeSchedule(), nil, mds) + stm, err := stmgr.NewStateManager(cst, consensus.NewTipSetExecutor(filcns.RewardFunc), vm.Syscalls(ffiwrapper.ProofVerifier), filcns.DefaultUpgradeSchedule(), nil, mds, index.DummyMsgIndex) if err != nil { return err } @@ -556,5 +554,23 @@ func ImportChain(ctx context.Context, r repo.Repo, fname string, snapshot bool) return err } + // populate the message index if user has EnableMsgIndex enabled + // + c, err := lr.Config() + if err != nil { + return err + } + cfg, ok := c.(*config.FullNode) + if !ok { + return xerrors.Errorf("invalid config for repo, got: %T", c) + } + if cfg.Index.EnableMsgIndex { + log.Info("populating message index...") + if err := index.PopulateAfterSnapshot(ctx, path.Join(lr.Path(), "sqlite"), cst); err != nil { + return err + } + log.Info("populating message index done") + } + return nil } diff --git a/cmd/tvx/extract_many.go b/cmd/tvx/extract_many.go index 96ce2473b..7c8d306d8 100644 --- a/cmd/tvx/extract_many.go +++ b/cmd/tvx/extract_many.go @@ -7,18 +7,20 @@ import ( "log" "os" "path/filepath" + "regexp" "strconv" "strings" "github.com/fatih/color" "github.com/hashicorp/go-multierror" "github.com/ipfs/go-cid" - "github.com/multiformats/go-multihash" "github.com/urfave/cli/v2" "github.com/filecoin-project/go-state-types/abi" + actorstypes "github.com/filecoin-project/go-state-types/actors" "github.com/filecoin-project/go-state-types/exitcode" + "github.com/filecoin-project/lotus/chain/actors" "github.com/filecoin-project/lotus/chain/consensus" ) @@ -67,6 +69,8 @@ var extractManyCmd = &cli.Command{ }, } +var actorCodeRegex = regexp.MustCompile(`^fil/(?P\d+)/(?P\w+)$`) + func runExtractMany(c *cli.Context) error { // LOTUS_DISABLE_VM_BUF disables what's called "VM state tree buffering", // which stashes write operations in a BufferedBlockstore @@ -114,8 +118,6 @@ func runExtractMany(c *cli.Context) error { log.Println(color.GreenString("csv sanity check succeeded; header contains fields: %v", header)) } - codeCidBuilder := cid.V1Builder{Codec: cid.Raw, MhType: multihash.IDENTITY} - var ( generated []string merr = new(multierror.Error) @@ -153,9 +155,21 @@ func runExtractMany(c *cli.Context) error { return fmt.Errorf("invalid method number: %s", methodnumstr) } - codeCid, err := codeCidBuilder.Sum([]byte(actorcode)) - if err != nil { - return fmt.Errorf("failed to compute actor code CID") + // Lookup the code CID. + var codeCid cid.Cid + if matches := actorCodeRegex.FindStringSubmatch(actorcode); len(matches) == 3 { + av, err := strconv.Atoi(matches[1]) + if err != nil { + return fmt.Errorf("invalid actor version %q in actor code %q", matches[1], actorcode) + } + an := matches[2] + if k, ok := actors.GetActorCodeID(actorstypes.Version(av), an); ok { + codeCid = k + } else { + return fmt.Errorf("unknown actor code %q", actorcode) + } + } else { + return fmt.Errorf("invalid actor code %q", actorcode) } // Lookup the method in actor method table. diff --git a/cmd/tvx/stores.go b/cmd/tvx/stores.go index b863ffa74..9035c482a 100644 --- a/cmd/tvx/stores.go +++ b/cmd/tvx/stores.go @@ -6,6 +6,7 @@ import ( "sync" "github.com/fatih/color" + blocks "github.com/ipfs/go-block-format" "github.com/ipfs/go-blockservice" "github.com/ipfs/go-cid" ds "github.com/ipfs/go-datastore" @@ -14,7 +15,6 @@ import ( offline "github.com/ipfs/go-ipfs-exchange-offline" cbor "github.com/ipfs/go-ipld-cbor" format "github.com/ipfs/go-ipld-format" - blocks "github.com/ipfs/go-libipfs/blocks" "github.com/ipfs/go-merkledag" "golang.org/x/xerrors" diff --git a/conformance/driver.go b/conformance/driver.go index 2680a7154..eb5973f72 100644 --- a/conformance/driver.go +++ b/conformance/driver.go @@ -22,6 +22,7 @@ import ( "github.com/filecoin-project/lotus/chain/actors/builtin" "github.com/filecoin-project/lotus/chain/consensus" "github.com/filecoin-project/lotus/chain/consensus/filcns" + "github.com/filecoin-project/lotus/chain/index" "github.com/filecoin-project/lotus/chain/state" "github.com/filecoin-project/lotus/chain/stmgr" "github.com/filecoin-project/lotus/chain/store" @@ -108,7 +109,7 @@ func (d *Driver) ExecuteTipset(bs blockstore.Blockstore, ds ds.Batching, params cs = store.NewChainStore(bs, bs, ds, filcns.Weight, nil) tse = consensus.NewTipSetExecutor(filcns.RewardFunc) - sm, err = stmgr.NewStateManager(cs, tse, syscalls, filcns.DefaultUpgradeSchedule(), nil, ds) + sm, err = stmgr.NewStateManager(cs, tse, syscalls, filcns.DefaultUpgradeSchedule(), nil, ds, index.DummyMsgIndex) ) if err != nil { return nil, err @@ -296,12 +297,12 @@ func (d *Driver) ExecuteMessage(bs blockstore.Blockstore, params ExecuteMessageP } var root cid.Cid - if d.vmFlush { + if lvm, ok := vmi.(*vm.LegacyVM); ok && !d.vmFlush { + root, err = lvm.StateTree().(*state.StateTree).Flush(d.ctx) + } else { // flush the VM, committing the state tree changes and forcing a // recursive copy from the temporary blockstore to the real blockstore. root, err = vmi.Flush(d.ctx) - } else { - root, err = vmi.(*vm.LegacyVM).StateTree().(*state.StateTree).Flush(d.ctx) } return ret, root, err diff --git a/conformance/runner.go b/conformance/runner.go index 827c10a5c..09d4c0621 100644 --- a/conformance/runner.go +++ b/conformance/runner.go @@ -13,12 +13,12 @@ import ( "github.com/fatih/color" "github.com/hashicorp/go-multierror" + blocks "github.com/ipfs/go-block-format" "github.com/ipfs/go-blockservice" "github.com/ipfs/go-cid" ds "github.com/ipfs/go-datastore" offline "github.com/ipfs/go-ipfs-exchange-offline" format "github.com/ipfs/go-ipld-format" - blocks "github.com/ipfs/go-libipfs/blocks" "github.com/ipfs/go-merkledag" "github.com/ipld/go-car" diff --git a/documentation/en/api-v0-methods-miner.md b/documentation/en/api-v0-methods-miner.md index f14acfbd3..997778069 100644 --- a/documentation/en/api-v0-methods-miner.md +++ b/documentation/en/api-v0-methods-miner.md @@ -159,6 +159,7 @@ * [SectorTerminate](#SectorTerminate) * [SectorTerminateFlush](#SectorTerminateFlush) * [SectorTerminatePending](#SectorTerminatePending) + * [SectorUnseal](#SectorUnseal) * [Sectors](#Sectors) * [SectorsList](#SectorsList) * [SectorsListInStates](#SectorsListInStates) @@ -1701,7 +1702,9 @@ Response: ```json { "Reachability": 1, - "PublicAddr": "string value" + "PublicAddrs": [ + "string value" + ] } ``` @@ -3415,6 +3418,21 @@ Response: ] ``` +### SectorUnseal +SectorUnseal unseals the provided sector + + +Perms: admin + +Inputs: +```json +[ + 9 +] +``` + +Response: `{}` + ## Sectors @@ -5192,7 +5210,7 @@ Response: "0": { "MinMemory": 2048, "MaxMemory": 2048, - "GPUUtilization": 0, + "GPUUtilization": 1, "MaxParallelism": 1, "MaxParallelismGPU": 0, "BaseMinMemory": 2048, @@ -5201,7 +5219,7 @@ Response: "1": { "MinMemory": 8388608, "MaxMemory": 8388608, - "GPUUtilization": 0, + "GPUUtilization": 1, "MaxParallelism": 1, "MaxParallelismGPU": 0, "BaseMinMemory": 8388608, @@ -5210,7 +5228,7 @@ Response: "2": { "MinMemory": 1073741824, "MaxMemory": 1073741824, - "GPUUtilization": 0, + "GPUUtilization": 1, "MaxParallelism": 1, "MaxParallelismGPU": 0, "BaseMinMemory": 1073741824, @@ -5219,25 +5237,25 @@ Response: "3": { "MinMemory": 4294967296, "MaxMemory": 4294967296, - "GPUUtilization": 0, + "GPUUtilization": 1, "MaxParallelism": 1, - "MaxParallelismGPU": 0, + "MaxParallelismGPU": 6, "BaseMinMemory": 1073741824, "MaxConcurrent": 0 }, "4": { "MinMemory": 8589934592, "MaxMemory": 8589934592, - "GPUUtilization": 0, + "GPUUtilization": 1, "MaxParallelism": 1, - "MaxParallelismGPU": 0, + "MaxParallelismGPU": 6, "BaseMinMemory": 1073741824, "MaxConcurrent": 0 }, "5": { "MinMemory": 2048, "MaxMemory": 2048, - "GPUUtilization": 0, + "GPUUtilization": 1, "MaxParallelism": 1, "MaxParallelismGPU": 0, "BaseMinMemory": 2048, @@ -5246,7 +5264,7 @@ Response: "6": { "MinMemory": 8388608, "MaxMemory": 8388608, - "GPUUtilization": 0, + "GPUUtilization": 1, "MaxParallelism": 1, "MaxParallelismGPU": 0, "BaseMinMemory": 8388608, @@ -5255,7 +5273,7 @@ Response: "7": { "MinMemory": 1073741824, "MaxMemory": 1073741824, - "GPUUtilization": 0, + "GPUUtilization": 1, "MaxParallelism": 1, "MaxParallelismGPU": 0, "BaseMinMemory": 1073741824, @@ -5264,18 +5282,18 @@ Response: "8": { "MinMemory": 4294967296, "MaxMemory": 4294967296, - "GPUUtilization": 0, + "GPUUtilization": 1, "MaxParallelism": 1, - "MaxParallelismGPU": 0, + "MaxParallelismGPU": 6, "BaseMinMemory": 1073741824, "MaxConcurrent": 0 }, "9": { "MinMemory": 8589934592, "MaxMemory": 8589934592, - "GPUUtilization": 0, + "GPUUtilization": 1, "MaxParallelism": 1, - "MaxParallelismGPU": 0, + "MaxParallelismGPU": 6, "BaseMinMemory": 1073741824, "MaxConcurrent": 0 } @@ -5284,7 +5302,7 @@ Response: "0": { "MinMemory": 2048, "MaxMemory": 2048, - "GPUUtilization": 0, + "GPUUtilization": 1, "MaxParallelism": 1, "MaxParallelismGPU": 0, "BaseMinMemory": 2048, @@ -5293,7 +5311,7 @@ Response: "1": { "MinMemory": 8388608, "MaxMemory": 8388608, - "GPUUtilization": 0, + "GPUUtilization": 1, "MaxParallelism": 1, "MaxParallelismGPU": 0, "BaseMinMemory": 8388608, @@ -5302,7 +5320,7 @@ Response: "2": { "MinMemory": 1073741824, "MaxMemory": 1073741824, - "GPUUtilization": 0, + "GPUUtilization": 1, "MaxParallelism": 1, "MaxParallelismGPU": 0, "BaseMinMemory": 1073741824, @@ -5311,25 +5329,25 @@ Response: "3": { "MinMemory": 4294967296, "MaxMemory": 4294967296, - "GPUUtilization": 0, + "GPUUtilization": 1, "MaxParallelism": 1, - "MaxParallelismGPU": 0, + "MaxParallelismGPU": 6, "BaseMinMemory": 1073741824, "MaxConcurrent": 0 }, "4": { "MinMemory": 8589934592, "MaxMemory": 8589934592, - "GPUUtilization": 0, + "GPUUtilization": 1, "MaxParallelism": 1, - "MaxParallelismGPU": 0, + "MaxParallelismGPU": 6, "BaseMinMemory": 1073741824, "MaxConcurrent": 0 }, "5": { "MinMemory": 2048, "MaxMemory": 2048, - "GPUUtilization": 0, + "GPUUtilization": 1, "MaxParallelism": 1, "MaxParallelismGPU": 0, "BaseMinMemory": 2048, @@ -5338,7 +5356,7 @@ Response: "6": { "MinMemory": 8388608, "MaxMemory": 8388608, - "GPUUtilization": 0, + "GPUUtilization": 1, "MaxParallelism": 1, "MaxParallelismGPU": 0, "BaseMinMemory": 8388608, @@ -5347,7 +5365,7 @@ Response: "7": { "MinMemory": 1073741824, "MaxMemory": 1073741824, - "GPUUtilization": 0, + "GPUUtilization": 1, "MaxParallelism": 1, "MaxParallelismGPU": 0, "BaseMinMemory": 1073741824, @@ -5356,18 +5374,18 @@ Response: "8": { "MinMemory": 4294967296, "MaxMemory": 4294967296, - "GPUUtilization": 0, + "GPUUtilization": 1, "MaxParallelism": 1, - "MaxParallelismGPU": 0, + "MaxParallelismGPU": 6, "BaseMinMemory": 1073741824, "MaxConcurrent": 0 }, "9": { "MinMemory": 8589934592, "MaxMemory": 8589934592, - "GPUUtilization": 0, + "GPUUtilization": 1, "MaxParallelism": 1, - "MaxParallelismGPU": 0, + "MaxParallelismGPU": 6, "BaseMinMemory": 1073741824, "MaxConcurrent": 0 } diff --git a/documentation/en/api-v0-methods-worker.md b/documentation/en/api-v0-methods-worker.md index dab251a7c..d7d0f092e 100644 --- a/documentation/en/api-v0-methods-worker.md +++ b/documentation/en/api-v0-methods-worker.md @@ -1135,7 +1135,7 @@ Response: "0": { "MinMemory": 2048, "MaxMemory": 2048, - "GPUUtilization": 0, + "GPUUtilization": 1, "MaxParallelism": 1, "MaxParallelismGPU": 0, "BaseMinMemory": 2048, @@ -1144,7 +1144,7 @@ Response: "1": { "MinMemory": 8388608, "MaxMemory": 8388608, - "GPUUtilization": 0, + "GPUUtilization": 1, "MaxParallelism": 1, "MaxParallelismGPU": 0, "BaseMinMemory": 8388608, @@ -1153,7 +1153,7 @@ Response: "2": { "MinMemory": 1073741824, "MaxMemory": 1073741824, - "GPUUtilization": 0, + "GPUUtilization": 1, "MaxParallelism": 1, "MaxParallelismGPU": 0, "BaseMinMemory": 1073741824, @@ -1162,25 +1162,25 @@ Response: "3": { "MinMemory": 4294967296, "MaxMemory": 4294967296, - "GPUUtilization": 0, + "GPUUtilization": 1, "MaxParallelism": 1, - "MaxParallelismGPU": 0, + "MaxParallelismGPU": 6, "BaseMinMemory": 1073741824, "MaxConcurrent": 0 }, "4": { "MinMemory": 8589934592, "MaxMemory": 8589934592, - "GPUUtilization": 0, + "GPUUtilization": 1, "MaxParallelism": 1, - "MaxParallelismGPU": 0, + "MaxParallelismGPU": 6, "BaseMinMemory": 1073741824, "MaxConcurrent": 0 }, "5": { "MinMemory": 2048, "MaxMemory": 2048, - "GPUUtilization": 0, + "GPUUtilization": 1, "MaxParallelism": 1, "MaxParallelismGPU": 0, "BaseMinMemory": 2048, @@ -1189,7 +1189,7 @@ Response: "6": { "MinMemory": 8388608, "MaxMemory": 8388608, - "GPUUtilization": 0, + "GPUUtilization": 1, "MaxParallelism": 1, "MaxParallelismGPU": 0, "BaseMinMemory": 8388608, @@ -1198,7 +1198,7 @@ Response: "7": { "MinMemory": 1073741824, "MaxMemory": 1073741824, - "GPUUtilization": 0, + "GPUUtilization": 1, "MaxParallelism": 1, "MaxParallelismGPU": 0, "BaseMinMemory": 1073741824, @@ -1207,18 +1207,18 @@ Response: "8": { "MinMemory": 4294967296, "MaxMemory": 4294967296, - "GPUUtilization": 0, + "GPUUtilization": 1, "MaxParallelism": 1, - "MaxParallelismGPU": 0, + "MaxParallelismGPU": 6, "BaseMinMemory": 1073741824, "MaxConcurrent": 0 }, "9": { "MinMemory": 8589934592, "MaxMemory": 8589934592, - "GPUUtilization": 0, + "GPUUtilization": 1, "MaxParallelism": 1, - "MaxParallelismGPU": 0, + "MaxParallelismGPU": 6, "BaseMinMemory": 1073741824, "MaxConcurrent": 0 } @@ -1227,7 +1227,7 @@ Response: "0": { "MinMemory": 2048, "MaxMemory": 2048, - "GPUUtilization": 0, + "GPUUtilization": 1, "MaxParallelism": 1, "MaxParallelismGPU": 0, "BaseMinMemory": 2048, @@ -1236,7 +1236,7 @@ Response: "1": { "MinMemory": 8388608, "MaxMemory": 8388608, - "GPUUtilization": 0, + "GPUUtilization": 1, "MaxParallelism": 1, "MaxParallelismGPU": 0, "BaseMinMemory": 8388608, @@ -1245,7 +1245,7 @@ Response: "2": { "MinMemory": 1073741824, "MaxMemory": 1073741824, - "GPUUtilization": 0, + "GPUUtilization": 1, "MaxParallelism": 1, "MaxParallelismGPU": 0, "BaseMinMemory": 1073741824, @@ -1254,25 +1254,25 @@ Response: "3": { "MinMemory": 4294967296, "MaxMemory": 4294967296, - "GPUUtilization": 0, + "GPUUtilization": 1, "MaxParallelism": 1, - "MaxParallelismGPU": 0, + "MaxParallelismGPU": 6, "BaseMinMemory": 1073741824, "MaxConcurrent": 0 }, "4": { "MinMemory": 8589934592, "MaxMemory": 8589934592, - "GPUUtilization": 0, + "GPUUtilization": 1, "MaxParallelism": 1, - "MaxParallelismGPU": 0, + "MaxParallelismGPU": 6, "BaseMinMemory": 1073741824, "MaxConcurrent": 0 }, "5": { "MinMemory": 2048, "MaxMemory": 2048, - "GPUUtilization": 0, + "GPUUtilization": 1, "MaxParallelism": 1, "MaxParallelismGPU": 0, "BaseMinMemory": 2048, @@ -1281,7 +1281,7 @@ Response: "6": { "MinMemory": 8388608, "MaxMemory": 8388608, - "GPUUtilization": 0, + "GPUUtilization": 1, "MaxParallelism": 1, "MaxParallelismGPU": 0, "BaseMinMemory": 8388608, @@ -1290,7 +1290,7 @@ Response: "7": { "MinMemory": 1073741824, "MaxMemory": 1073741824, - "GPUUtilization": 0, + "GPUUtilization": 1, "MaxParallelism": 1, "MaxParallelismGPU": 0, "BaseMinMemory": 1073741824, @@ -1299,18 +1299,18 @@ Response: "8": { "MinMemory": 4294967296, "MaxMemory": 4294967296, - "GPUUtilization": 0, + "GPUUtilization": 1, "MaxParallelism": 1, - "MaxParallelismGPU": 0, + "MaxParallelismGPU": 6, "BaseMinMemory": 1073741824, "MaxConcurrent": 0 }, "9": { "MinMemory": 8589934592, "MaxMemory": 8589934592, - "GPUUtilization": 0, + "GPUUtilization": 1, "MaxParallelism": 1, - "MaxParallelismGPU": 0, + "MaxParallelismGPU": 6, "BaseMinMemory": 1073741824, "MaxConcurrent": 0 } diff --git a/documentation/en/api-v0-methods.md b/documentation/en/api-v0-methods.md index 95678782a..431d90acd 100644 --- a/documentation/en/api-v0-methods.md +++ b/documentation/en/api-v0-methods.md @@ -3710,7 +3710,9 @@ Response: ```json { "Reachability": 1, - "PublicAddr": "string value" + "PublicAddrs": [ + "string value" + ] } ``` @@ -5428,7 +5430,6 @@ Response: "UpgradeRefuelHeight": 10101, "UpgradeTapeHeight": 10101, "UpgradeKumquatHeight": 10101, - "UpgradePriceListOopsHeight": 10101, "BreezeGasTampingDuration": 10101, "UpgradeCalicoHeight": 10101, "UpgradePersianHeight": 10101, diff --git a/documentation/en/api-v1-unstable-methods.md b/documentation/en/api-v1-unstable-methods.md index 6a81465e2..645df4f9d 100644 --- a/documentation/en/api-v1-unstable-methods.md +++ b/documentation/en/api-v1-unstable-methods.md @@ -103,6 +103,7 @@ * [EthProtocolVersion](#EthProtocolVersion) * [EthSendRawTransaction](#EthSendRawTransaction) * [EthSubscribe](#EthSubscribe) + * [EthSyncing](#EthSyncing) * [EthUninstallFilter](#EthUninstallFilter) * [EthUnsubscribe](#EthUnsubscribe) * [Filecoin](#Filecoin) @@ -2598,7 +2599,7 @@ Polling method for a filter, returns event logs which occurred since last poll. (requires write perm since timestamp of last filter execution will be written) -Perms: write +Perms: read Inputs: ```json @@ -2619,7 +2620,7 @@ Returns event logs matching filter with given id. (requires write perm since timestamp of last filter execution will be written) -Perms: write +Perms: read Inputs: ```json @@ -2990,7 +2991,7 @@ Response: `"0x0"` Installs a persistent filter to notify when a new block arrives. -Perms: write +Perms: read Inputs: `null` @@ -3000,7 +3001,7 @@ Response: `"0x37690cfec6c1bf4c3b9288c7a5d783e98731e90b0a4c177c2a374c7a9427355e"` Installs a persistent filter based on given filter spec. -Perms: write +Perms: read Inputs: ```json @@ -3021,7 +3022,7 @@ Response: `"0x37690cfec6c1bf4c3b9288c7a5d783e98731e90b0a4c177c2a374c7a9427355e"` Installs a persistent filter to notify when new messages arrive in the message pool. -Perms: write +Perms: read Inputs: `null` @@ -3060,7 +3061,7 @@ params contains additional parameters used with the log event type The client will receive a stream of EthSubscriptionResponse values until EthUnsubscribe is called. -Perms: write +Perms: read Inputs: ```json @@ -3071,11 +3072,20 @@ Inputs: Response: `"0x37690cfec6c1bf4c3b9288c7a5d783e98731e90b0a4c177c2a374c7a9427355e"` +### EthSyncing + + +Perms: read + +Inputs: `null` + +Response: `false` + ### EthUninstallFilter Uninstalls a filter with given id. -Perms: write +Perms: read Inputs: ```json @@ -3090,7 +3100,7 @@ Response: `true` Unsubscribe from a websocket subscription -Perms: write +Perms: read Inputs: ```json @@ -3941,7 +3951,9 @@ Response: ``` ### MpoolClear -MpoolClear clears pending messages from the mpool +MpoolClear clears pending messages from the mpool. +If clearLocal is true, ALL messages will be cleared. +If clearLocal is false, local messages will be protected, all others will be cleared. Perms: write @@ -5020,7 +5032,9 @@ Response: ```json { "Reachability": 1, - "PublicAddr": "string value" + "PublicAddrs": [ + "string value" + ] } ``` @@ -6928,7 +6942,6 @@ Response: "UpgradeRefuelHeight": 10101, "UpgradeTapeHeight": 10101, "UpgradeKumquatHeight": 10101, - "UpgradePriceListOopsHeight": 10101, "BreezeGasTampingDuration": 10101, "UpgradeCalicoHeight": 10101, "UpgradePersianHeight": 10101, diff --git a/documentation/en/cli-lotus-miner.md b/documentation/en/cli-lotus-miner.md index 018fd6957..7c646a3b4 100644 --- a/documentation/en/cli-lotus-miner.md +++ b/documentation/en/cli-lotus-miner.md @@ -7,7 +7,7 @@ USAGE: lotus-miner [global options] command [command options] [arguments...] VERSION: - 1.23.0 + 1.23.2-dev COMMANDS: init Initialize a lotus miner repo @@ -25,16 +25,6 @@ COMMANDS: log Manage logging wait-api Wait for lotus api to come online fetch-params Fetch proving parameters - MARKET: - storage-deals Manage storage deals and related configuration - retrieval-deals Manage retrieval deals and related configuration - data-transfers Manage data transfers - dagstore Manage the dagstore on the markets subsystem - index Manage the index provider on the markets subsystem - NETWORK: - net Manage P2P Network - RETRIEVAL: - pieces interact with the piecestore STORAGE: sectors interact with sector store proving View proving information @@ -43,10 +33,8 @@ COMMANDS: GLOBAL OPTIONS: --actor value, -a value specify other actor to query / manipulate - --call-on-markets (experimental; may be removed) call this command against a markets node; use only with common commands like net, auth, pprof, etc. whose target may be ambiguous (default: false) --color use color in display output (default: depends on output being a TTY) --help, -h show help (default: false) - --markets-repo value Markets repo path [$LOTUS_MARKETS_PATH] --miner-repo value, --storagerepo value Specify miner repo path. flag(storagerepo) and env(LOTUS_STORAGE_PATH) are DEPRECATION, will REMOVE SOON (default: "~/.lotusminer") [$LOTUS_MINER_PATH, $LOTUS_STORAGE_PATH] --version, -v print the version (default: false) --vv enables very verbose mode, useful for debugging the CLI (default: false) @@ -412,7 +400,7 @@ NAME: lotus-miner actor confirm-change-beneficiary - Confirm a beneficiary address change USAGE: - lotus-miner actor confirm-change-beneficiary [command options] [minerAddress] + lotus-miner actor confirm-change-beneficiary [command options] [minerID] OPTIONS: --existing-beneficiary send confirmation from the existing beneficiary address (default: false) @@ -607,1041 +595,6 @@ OPTIONS: ``` -## lotus-miner storage-deals -``` -NAME: - lotus-miner storage-deals - Manage storage deals and related configuration - -USAGE: - lotus-miner storage-deals command [command options] [arguments...] - -COMMANDS: - import-data Manually import data for a deal - list List all deals for this miner - selection Configure acceptance criteria for storage deal proposals - set-ask Configure the miner's ask - get-ask Print the miner's ask - set-blocklist Set the miner's list of blocklisted piece CIDs - get-blocklist List the contents of the miner's piece CID blocklist - reset-blocklist Remove all entries from the miner's piece CID blocklist - set-seal-duration Set the expected time, in minutes, that you expect sealing sectors to take. Deals that start before this duration will be rejected. - pending-publish list deals waiting in publish queue - retry-publish retry publishing a deal - help, h Shows a list of commands or help for one command - -OPTIONS: - --help, -h show help (default: false) - -``` - -### lotus-miner storage-deals import-data -``` -NAME: - lotus-miner storage-deals import-data - Manually import data for a deal - -USAGE: - lotus-miner storage-deals import-data [command options] - -OPTIONS: - --help, -h show help (default: false) - -``` - -### lotus-miner storage-deals list -``` -NAME: - lotus-miner storage-deals list - List all deals for this miner - -USAGE: - lotus-miner storage-deals list [command options] [arguments...] - -OPTIONS: - --format value output format of data, supported: table, json (default: "table") - --verbose, -v (default: false) - --watch watch deal updates in real-time, rather than a one time list (default: false) - -``` - -### lotus-miner storage-deals selection -``` -NAME: - lotus-miner storage-deals selection - Configure acceptance criteria for storage deal proposals - -USAGE: - lotus-miner storage-deals selection command [command options] [arguments...] - -COMMANDS: - list List storage deal proposal selection criteria - reset Reset storage deal proposal selection criteria to default values - reject Configure criteria which necessitate automatic rejection - help, h Shows a list of commands or help for one command - -OPTIONS: - --help, -h show help (default: false) - -``` - -#### lotus-miner storage-deals selection list -``` -NAME: - lotus-miner storage-deals selection list - List storage deal proposal selection criteria - -USAGE: - lotus-miner storage-deals selection list [command options] [arguments...] - -OPTIONS: - --help, -h show help (default: false) - -``` - -#### lotus-miner storage-deals selection reset -``` -NAME: - lotus-miner storage-deals selection reset - Reset storage deal proposal selection criteria to default values - -USAGE: - lotus-miner storage-deals selection reset [command options] [arguments...] - -OPTIONS: - --help, -h show help (default: false) - -``` - -#### lotus-miner storage-deals selection reject -``` -NAME: - lotus-miner storage-deals selection reject - Configure criteria which necessitate automatic rejection - -USAGE: - lotus-miner storage-deals selection reject [command options] [arguments...] - -OPTIONS: - --offline (default: false) - --online (default: false) - --unverified (default: false) - --verified (default: false) - -``` - -### lotus-miner storage-deals set-ask -``` -NAME: - lotus-miner storage-deals set-ask - Configure the miner's ask - -USAGE: - lotus-miner storage-deals set-ask [command options] [arguments...] - -OPTIONS: - --max-piece-size SIZE Set maximum piece size (w/bit-padding, in bytes) in ask to SIZE (default: miner sector size) - --min-piece-size SIZE Set minimum piece size (w/bit-padding, in bytes) in ask to SIZE (default: 256B) - --price PRICE Set the price of the ask for unverified deals (specified as FIL / GiB / Epoch) to PRICE. - --verified-price PRICE Set the price of the ask for verified deals (specified as FIL / GiB / Epoch) to PRICE - -``` - -### lotus-miner storage-deals get-ask -``` -NAME: - lotus-miner storage-deals get-ask - Print the miner's ask - -USAGE: - lotus-miner storage-deals get-ask [command options] [arguments...] - -OPTIONS: - --help, -h show help (default: false) - -``` - -### lotus-miner storage-deals set-blocklist -``` -NAME: - lotus-miner storage-deals set-blocklist - Set the miner's list of blocklisted piece CIDs - -USAGE: - lotus-miner storage-deals set-blocklist [command options] [ (optional, will read from stdin if omitted)] - -OPTIONS: - --help, -h show help (default: false) - -``` - -### lotus-miner storage-deals get-blocklist -``` -NAME: - lotus-miner storage-deals get-blocklist - List the contents of the miner's piece CID blocklist - -USAGE: - lotus-miner storage-deals get-blocklist [command options] [arguments...] - -OPTIONS: - -``` - -### lotus-miner storage-deals reset-blocklist -``` -NAME: - lotus-miner storage-deals reset-blocklist - Remove all entries from the miner's piece CID blocklist - -USAGE: - lotus-miner storage-deals reset-blocklist [command options] [arguments...] - -OPTIONS: - --help, -h show help (default: false) - -``` - -### lotus-miner storage-deals set-seal-duration -``` -NAME: - lotus-miner storage-deals set-seal-duration - Set the expected time, in minutes, that you expect sealing sectors to take. Deals that start before this duration will be rejected. - -USAGE: - lotus-miner storage-deals set-seal-duration [command options] - -OPTIONS: - --help, -h show help (default: false) - -``` - -### lotus-miner storage-deals pending-publish -``` -NAME: - lotus-miner storage-deals pending-publish - list deals waiting in publish queue - -USAGE: - lotus-miner storage-deals pending-publish [command options] [arguments...] - -OPTIONS: - --publish-now send a publish message now (default: false) - -``` - -### lotus-miner storage-deals retry-publish -``` -NAME: - lotus-miner storage-deals retry-publish - retry publishing a deal - -USAGE: - lotus-miner storage-deals retry-publish [command options] - -OPTIONS: - --help, -h show help (default: false) - -``` - -## lotus-miner retrieval-deals -``` -NAME: - lotus-miner retrieval-deals - Manage retrieval deals and related configuration - -USAGE: - lotus-miner retrieval-deals command [command options] [arguments...] - -COMMANDS: - selection Configure acceptance criteria for retrieval deal proposals - set-ask Configure the provider's retrieval ask - get-ask Get the provider's current retrieval ask configured by the provider in the ask-store using the set-ask CLI command - help, h Shows a list of commands or help for one command - -OPTIONS: - --help, -h show help (default: false) - -``` - -### lotus-miner retrieval-deals selection -``` -NAME: - lotus-miner retrieval-deals selection - Configure acceptance criteria for retrieval deal proposals - -USAGE: - lotus-miner retrieval-deals selection command [command options] [arguments...] - -COMMANDS: - list List retrieval deal proposal selection criteria - reset Reset retrieval deal proposal selection criteria to default values - reject Configure criteria which necessitate automatic rejection - help, h Shows a list of commands or help for one command - -OPTIONS: - --help, -h show help (default: false) - -``` - -#### lotus-miner retrieval-deals selection list -``` -NAME: - lotus-miner retrieval-deals selection list - List retrieval deal proposal selection criteria - -USAGE: - lotus-miner retrieval-deals selection list [command options] [arguments...] - -OPTIONS: - --help, -h show help (default: false) - -``` - -#### lotus-miner retrieval-deals selection reset -``` -NAME: - lotus-miner retrieval-deals selection reset - Reset retrieval deal proposal selection criteria to default values - -USAGE: - lotus-miner retrieval-deals selection reset [command options] [arguments...] - -OPTIONS: - --help, -h show help (default: false) - -``` - -#### lotus-miner retrieval-deals selection reject -``` -NAME: - lotus-miner retrieval-deals selection reject - Configure criteria which necessitate automatic rejection - -USAGE: - lotus-miner retrieval-deals selection reject [command options] [arguments...] - -OPTIONS: - --offline (default: false) - --online (default: false) - -``` - -### lotus-miner retrieval-deals set-ask -``` -NAME: - lotus-miner retrieval-deals set-ask - Configure the provider's retrieval ask - -USAGE: - lotus-miner retrieval-deals set-ask [command options] [arguments...] - -OPTIONS: - --payment-interval value Set the payment interval (in bytes) for retrieval (default: 1MiB) - --payment-interval-increase value Set the payment interval increase (in bytes) for retrieval (default: 1MiB) - --price value Set the price of the ask for retrievals (FIL/GiB) - --unseal-price value Set the price to unseal - -``` - -### lotus-miner retrieval-deals get-ask -``` -NAME: - lotus-miner retrieval-deals get-ask - Get the provider's current retrieval ask configured by the provider in the ask-store using the set-ask CLI command - -USAGE: - lotus-miner retrieval-deals get-ask [command options] [arguments...] - -OPTIONS: - --help, -h show help (default: false) - -``` - -## lotus-miner data-transfers -``` -NAME: - lotus-miner data-transfers - Manage data transfers - -USAGE: - lotus-miner data-transfers command [command options] [arguments...] - -COMMANDS: - list List ongoing data transfers for this miner - restart Force restart a stalled data transfer - cancel Force cancel a data transfer - diagnostics Get detailed diagnostics on active transfers with a specific peer - help, h Shows a list of commands or help for one command - -OPTIONS: - --help, -h show help (default: false) - -``` - -### lotus-miner data-transfers list -``` -NAME: - lotus-miner data-transfers list - List ongoing data transfers for this miner - -USAGE: - lotus-miner data-transfers list [command options] [arguments...] - -OPTIONS: - --completed show completed data transfers (default: false) - --show-failed show failed/cancelled transfers (default: false) - --verbose, -v print verbose transfer details (default: false) - --watch watch deal updates in real-time, rather than a one time list (default: false) - -``` - -### lotus-miner data-transfers restart -``` -NAME: - lotus-miner data-transfers restart - Force restart a stalled data transfer - -USAGE: - lotus-miner data-transfers restart [command options] [arguments...] - -OPTIONS: - --initiator specify only transfers where peer is/is not initiator (default: false) - --peerid value narrow to transfer with specific peer - -``` - -### lotus-miner data-transfers cancel -``` -NAME: - lotus-miner data-transfers cancel - Force cancel a data transfer - -USAGE: - lotus-miner data-transfers cancel [command options] [arguments...] - -OPTIONS: - --cancel-timeout value time to wait for cancel to be sent to client (default: 5s) - --initiator specify only transfers where peer is/is not initiator (default: false) - --peerid value narrow to transfer with specific peer - -``` - -### lotus-miner data-transfers diagnostics -``` -NAME: - lotus-miner data-transfers diagnostics - Get detailed diagnostics on active transfers with a specific peer - -USAGE: - lotus-miner data-transfers diagnostics [command options] [arguments...] - -OPTIONS: - --help, -h show help (default: false) - -``` - -## lotus-miner dagstore -``` -NAME: - lotus-miner dagstore - Manage the dagstore on the markets subsystem - -USAGE: - lotus-miner dagstore command [command options] [arguments...] - -COMMANDS: - list-shards List all shards known to the dagstore, with their current status - register-shard Register a shard - initialize-shard Initialize the specified shard - recover-shard Attempt to recover a shard in errored state - initialize-all Initialize all uninitialized shards, streaming results as they're produced; only shards for unsealed pieces are initialized by default - gc Garbage collect the dagstore - lookup-pieces Lookup pieces that a given CID belongs to - help, h Shows a list of commands or help for one command - -OPTIONS: - --help, -h show help (default: false) - -``` - -### lotus-miner dagstore list-shards -``` -NAME: - lotus-miner dagstore list-shards - List all shards known to the dagstore, with their current status - -USAGE: - lotus-miner dagstore list-shards [command options] [arguments...] - -OPTIONS: - --help, -h show help (default: false) - -``` - -### lotus-miner dagstore register-shard -``` -NAME: - lotus-miner dagstore register-shard - Register a shard - -USAGE: - lotus-miner dagstore register-shard [command options] [key] - -OPTIONS: - --help, -h show help (default: false) - -``` - -### lotus-miner dagstore initialize-shard -``` -NAME: - lotus-miner dagstore initialize-shard - Initialize the specified shard - -USAGE: - lotus-miner dagstore initialize-shard [command options] [key] - -OPTIONS: - --help, -h show help (default: false) - -``` - -### lotus-miner dagstore recover-shard -``` -NAME: - lotus-miner dagstore recover-shard - Attempt to recover a shard in errored state - -USAGE: - lotus-miner dagstore recover-shard [command options] [key] - -OPTIONS: - --help, -h show help (default: false) - -``` - -### lotus-miner dagstore initialize-all -``` -NAME: - lotus-miner dagstore initialize-all - Initialize all uninitialized shards, streaming results as they're produced; only shards for unsealed pieces are initialized by default - -USAGE: - lotus-miner dagstore initialize-all [command options] [arguments...] - -OPTIONS: - --concurrency value maximum shards to initialize concurrently at a time; use 0 for unlimited (default: 0) - --include-sealed initialize sealed pieces as well (default: false) - -``` - -### lotus-miner dagstore gc -``` -NAME: - lotus-miner dagstore gc - Garbage collect the dagstore - -USAGE: - lotus-miner dagstore gc [command options] [arguments...] - -OPTIONS: - --help, -h show help (default: false) - -``` - -### lotus-miner dagstore lookup-pieces -``` -NAME: - lotus-miner dagstore lookup-pieces - Lookup pieces that a given CID belongs to - -USAGE: - lotus-miner dagstore lookup-pieces [command options] - -OPTIONS: - --help, -h show help (default: false) - -``` - -## lotus-miner index -``` -NAME: - lotus-miner index - Manage the index provider on the markets subsystem - -USAGE: - lotus-miner index command [command options] [arguments...] - -COMMANDS: - announce Announce a deal to indexers so they can download its index - announce-all Announce all active deals to indexers so they can download the indices - help, h Shows a list of commands or help for one command - -OPTIONS: - --help, -h show help (default: false) - -``` - -### lotus-miner index announce -``` -NAME: - lotus-miner index announce - Announce a deal to indexers so they can download its index - -USAGE: - lotus-miner index announce [command options] - -OPTIONS: - --help, -h show help (default: false) - -``` - -### lotus-miner index announce-all -``` -NAME: - lotus-miner index announce-all - Announce all active deals to indexers so they can download the indices - -USAGE: - lotus-miner index announce-all [command options] [arguments...] - -OPTIONS: - --help, -h show help (default: false) - -``` - -## lotus-miner net -``` -NAME: - lotus-miner net - Manage P2P Network - -USAGE: - lotus-miner net command [command options] [arguments...] - -COMMANDS: - peers Print peers - ping Ping peers - connect Connect to a peer - disconnect Disconnect from a peer - listen List listen addresses - id Get node identity - find-peer, findpeer Find the addresses of a given peerID - scores Print peers' pubsub scores - reachability Print information about reachability from the internet - bandwidth Print bandwidth usage information - block Manage network connection gating rules - stat Report resource usage for a scope - limit Get or set resource limits for a scope - protect Add one or more peer IDs to the list of protected peer connections - unprotect Remove one or more peer IDs from the list of protected peer connections. - list-protected List the peer IDs with protected connection. - help, h Shows a list of commands or help for one command - -OPTIONS: - --help, -h show help (default: false) - -``` - -### lotus-miner net peers -``` -NAME: - lotus-miner net peers - Print peers - -USAGE: - lotus-miner net peers [command options] [arguments...] - -OPTIONS: - --agent, -a Print agent name (default: false) - --extended, -x Print extended peer information in json (default: false) - -``` - -### lotus-miner net ping -``` -NAME: - lotus-miner net ping - Ping peers - -USAGE: - lotus-miner net ping [command options] [peerMultiaddr] - -OPTIONS: - --count value, -c value specify the number of times it should ping (default: 10) - --interval value, -i value minimum time between pings (default: 1s) - -``` - -### lotus-miner net connect -``` -NAME: - lotus-miner net connect - Connect to a peer - -USAGE: - lotus-miner net connect [command options] [peerMultiaddr|minerActorAddress] - -OPTIONS: - --help, -h show help (default: false) - -``` - -### lotus-miner net disconnect -``` -NAME: - lotus-miner net disconnect - Disconnect from a peer - -USAGE: - lotus-miner net disconnect [command options] [peerID] - -OPTIONS: - --help, -h show help (default: false) - -``` - -### lotus-miner net listen -``` -NAME: - lotus-miner net listen - List listen addresses - -USAGE: - lotus-miner net listen [command options] [arguments...] - -OPTIONS: - --help, -h show help (default: false) - -``` - -### lotus-miner net id -``` -NAME: - lotus-miner net id - Get node identity - -USAGE: - lotus-miner net id [command options] [arguments...] - -OPTIONS: - --help, -h show help (default: false) - -``` - -#### lotus-miner net find-peer, findpeer -``` -``` - -### lotus-miner net scores -``` -NAME: - lotus-miner net scores - Print peers' pubsub scores - -USAGE: - lotus-miner net scores [command options] [arguments...] - -OPTIONS: - --extended, -x print extended peer scores in json (default: false) - -``` - -### lotus-miner net reachability -``` -NAME: - lotus-miner net reachability - Print information about reachability from the internet - -USAGE: - lotus-miner net reachability [command options] [arguments...] - -OPTIONS: - --help, -h show help (default: false) - -``` - -### lotus-miner net bandwidth -``` -NAME: - lotus-miner net bandwidth - Print bandwidth usage information - -USAGE: - lotus-miner net bandwidth [command options] [arguments...] - -OPTIONS: - --by-peer list bandwidth usage by peer (default: false) - --by-protocol list bandwidth usage by protocol (default: false) - -``` - -### lotus-miner net block -``` -NAME: - lotus-miner net block - Manage network connection gating rules - -USAGE: - lotus-miner net block command [command options] [arguments...] - -COMMANDS: - add Add connection gating rules - remove Remove connection gating rules - list list connection gating rules - help, h Shows a list of commands or help for one command - -OPTIONS: - --help, -h show help (default: false) - -``` - -#### lotus-miner net block add -``` -NAME: - lotus-miner net block add - Add connection gating rules - -USAGE: - lotus-miner net block add command [command options] [arguments...] - -COMMANDS: - peer Block a peer - ip Block an IP address - subnet Block an IP subnet - help, h Shows a list of commands or help for one command - -OPTIONS: - --help, -h show help (default: false) - -``` - -##### lotus-miner net block add peer -``` -NAME: - lotus-miner net block add peer - Block a peer - -USAGE: - lotus-miner net block add peer [command options] ... - -OPTIONS: - --help, -h show help (default: false) - -``` - -##### lotus-miner net block add ip -``` -NAME: - lotus-miner net block add ip - Block an IP address - -USAGE: - lotus-miner net block add ip [command options] ... - -OPTIONS: - --help, -h show help (default: false) - -``` - -##### lotus-miner net block add subnet -``` -NAME: - lotus-miner net block add subnet - Block an IP subnet - -USAGE: - lotus-miner net block add subnet [command options] ... - -OPTIONS: - --help, -h show help (default: false) - -``` - -#### lotus-miner net block remove -``` -NAME: - lotus-miner net block remove - Remove connection gating rules - -USAGE: - lotus-miner net block remove command [command options] [arguments...] - -COMMANDS: - peer Unblock a peer - ip Unblock an IP address - subnet Unblock an IP subnet - help, h Shows a list of commands or help for one command - -OPTIONS: - --help, -h show help (default: false) - -``` - -##### lotus-miner net block remove peer -``` -NAME: - lotus-miner net block remove peer - Unblock a peer - -USAGE: - lotus-miner net block remove peer [command options] ... - -OPTIONS: - --help, -h show help (default: false) - -``` - -##### lotus-miner net block remove ip -``` -NAME: - lotus-miner net block remove ip - Unblock an IP address - -USAGE: - lotus-miner net block remove ip [command options] ... - -OPTIONS: - --help, -h show help (default: false) - -``` - -##### lotus-miner net block remove subnet -``` -NAME: - lotus-miner net block remove subnet - Unblock an IP subnet - -USAGE: - lotus-miner net block remove subnet [command options] ... - -OPTIONS: - --help, -h show help (default: false) - -``` - -#### lotus-miner net block list -``` -NAME: - lotus-miner net block list - list connection gating rules - -USAGE: - lotus-miner net block list [command options] [arguments...] - -OPTIONS: - --help, -h show help (default: false) - -``` - -### lotus-miner net stat -``` -NAME: - lotus-miner net stat - Report resource usage for a scope - -USAGE: - lotus-miner net stat [command options] scope - -DESCRIPTION: - Report resource usage for a scope. - - The scope can be one of the following: - - system -- reports the system aggregate resource usage. - - transient -- reports the transient resource usage. - - svc: -- reports the resource usage of a specific service. - - proto: -- reports the resource usage of a specific protocol. - - peer: -- reports the resource usage of a specific peer. - - all -- reports the resource usage for all currently active scopes. - - -OPTIONS: - --json (default: false) - -``` - -### lotus-miner net limit -``` -NAME: - lotus-miner net limit - Get or set resource limits for a scope - -USAGE: - lotus-miner net limit [command options] scope [limit] - -DESCRIPTION: - Get or set resource limits for a scope. - - The scope can be one of the following: - - system -- reports the system aggregate resource usage. - - transient -- reports the transient resource usage. - - svc: -- reports the resource usage of a specific service. - - proto: -- reports the resource usage of a specific protocol. - - peer: -- reports the resource usage of a specific peer. - - The limit is json-formatted, with the same structure as the limits file. - - -OPTIONS: - --set set the limit for a scope (default: false) - -``` - -### lotus-miner net protect -``` -NAME: - lotus-miner net protect - Add one or more peer IDs to the list of protected peer connections - -USAGE: - lotus-miner net protect [command options] [...] - -OPTIONS: - --help, -h show help (default: false) - -``` - -### lotus-miner net unprotect -``` -NAME: - lotus-miner net unprotect - Remove one or more peer IDs from the list of protected peer connections. - -USAGE: - lotus-miner net unprotect [command options] [...] - -OPTIONS: - --help, -h show help (default: false) - -``` - -### lotus-miner net list-protected -``` -NAME: - lotus-miner net list-protected - List the peer IDs with protected connection. - -USAGE: - lotus-miner net list-protected [command options] [arguments...] - -OPTIONS: - --help, -h show help (default: false) - -``` - -## lotus-miner pieces -``` -NAME: - lotus-miner pieces - interact with the piecestore - -USAGE: - lotus-miner pieces command [command options] [arguments...] - -DESCRIPTION: - The piecestore is a database that tracks and manages data that is made available to the retrieval market - -COMMANDS: - list-pieces list registered pieces - list-cids list registered payload CIDs - piece-info get registered information for a given piece CID - cid-info get registered information for a given payload CID - help, h Shows a list of commands or help for one command - -OPTIONS: - --help, -h show help (default: false) - -``` - -### lotus-miner pieces list-pieces -``` -NAME: - lotus-miner pieces list-pieces - list registered pieces - -USAGE: - lotus-miner pieces list-pieces [command options] [arguments...] - -OPTIONS: - --help, -h show help (default: false) - -``` - -### lotus-miner pieces list-cids -``` -NAME: - lotus-miner pieces list-cids - list registered payload CIDs - -USAGE: - lotus-miner pieces list-cids [command options] [arguments...] - -OPTIONS: - --verbose, -v (default: false) - -``` - -### lotus-miner pieces piece-info -``` -NAME: - lotus-miner pieces piece-info - get registered information for a given piece CID - -USAGE: - lotus-miner pieces piece-info [command options] [arguments...] - -OPTIONS: - --help, -h show help (default: false) - -``` - -### lotus-miner pieces cid-info -``` -NAME: - lotus-miner pieces cid-info - get registered information for a given payload CID - -USAGE: - lotus-miner pieces cid-info [command options] [arguments...] - -OPTIONS: - --help, -h show help (default: false) - -``` - ## lotus-miner sectors ``` NAME: @@ -1671,6 +624,7 @@ COMMANDS: batching manage batch sector operations match-pending-pieces force a refreshed match of pending pieces to open sectors without manually waiting for more deals compact-partitions removes dead sectors from partitions and reduces the number of partitions used if possible + unseal unseal a sector help, h Shows a list of commands or help for one command OPTIONS: @@ -2086,6 +1040,19 @@ OPTIONS: ``` +### lotus-miner sectors unseal +``` +NAME: + lotus-miner sectors unseal - unseal a sector + +USAGE: + lotus-miner sectors unseal [command options] [sector number] + +OPTIONS: + --help, -h show help (default: false) + +``` + ## lotus-miner proving ``` NAME: diff --git a/documentation/en/cli-lotus-worker.md b/documentation/en/cli-lotus-worker.md index da92e3de1..cb3d34729 100644 --- a/documentation/en/cli-lotus-worker.md +++ b/documentation/en/cli-lotus-worker.md @@ -7,7 +7,7 @@ USAGE: lotus-worker [global options] command [command options] [arguments...] VERSION: - 1.23.0 + 1.23.2-dev COMMANDS: run Start lotus worker @@ -38,6 +38,7 @@ USAGE: OPTIONS: --addpiece enable addpiece (default: true) [$LOTUS_WORKER_ADDPIECE] --commit enable commit (default: true) [$LOTUS_WORKER_COMMIT] + --data-cid Run the data-cid task. true|false (default: inherits --addpiece) --http-server-timeout value (default: "30s") --listen value host address and port the worker api will listen on (default: "0.0.0.0:3456") [$LOTUS_WORKER_LISTEN] --name value custom worker name (default: hostname) [$LOTUS_WORKER_NAME] diff --git a/documentation/en/cli-lotus.md b/documentation/en/cli-lotus.md index b51c19324..9fe755cde 100644 --- a/documentation/en/cli-lotus.md +++ b/documentation/en/cli-lotus.md @@ -7,7 +7,7 @@ USAGE: lotus [global options] command [command options] [arguments...] VERSION: - 1.23.0 + 1.23.2-dev COMMANDS: daemon Start a lotus daemon process diff --git a/documentation/en/default-lotus-config.toml b/documentation/en/default-lotus-config.toml index 25cd350c8..cd9332356 100644 --- a/documentation/en/default-lotus-config.toml +++ b/documentation/en/default-lotus-config.toml @@ -390,3 +390,11 @@ #DatabasePath = "" +[Index] + # EnableMsgIndex enables indexing of messages on chain. + # + # type: bool + # env var: LOTUS_INDEX_ENABLEMSGINDEX + #EnableMsgIndex = false + + diff --git a/documentation/en/default-lotus-miner-config.toml b/documentation/en/default-lotus-miner-config.toml index 584def608..0c8ef4411 100644 --- a/documentation/en/default-lotus-miner-config.toml +++ b/documentation/en/default-lotus-miner-config.toml @@ -143,7 +143,7 @@ # type: bool # env var: LOTUS_SUBSYSTEMS_ENABLEMARKETS - #EnableMarkets = true + #EnableMarkets = false # type: string # env var: LOTUS_SUBSYSTEMS_SEALERAPIINFO @@ -657,6 +657,16 @@ # env var: LOTUS_SEALING_AGGREGATEABOVEBASEFEE #AggregateAboveBaseFee = "0.00000000032 FIL" + # When submitting several sector prove commit messages simultaneously, this option allows you to + # stagger the number of prove commits submitted per epoch + # This is done because gas estimates for ProveCommits are non deterministic and increasing as a large + # number of sectors get committed within the same epoch resulting in occasionally failed msgs. + # Submitting a smaller number of prove commits per epoch would reduce the possibility of failed msgs + # + # type: uint64 + # env var: LOTUS_SEALING_MAXSECTORPROVECOMMITSSUBMITTEDPEREPOCH + #MaxSectorProveCommitsSubmittedPerEpoch = 20 + # type: uint64 # env var: LOTUS_SEALING_TERMINATEBATCHMAX #TerminateBatchMax = 100 diff --git a/extern/filecoin-ffi b/extern/filecoin-ffi index 86698251a..de34caff9 160000 --- a/extern/filecoin-ffi +++ b/extern/filecoin-ffi @@ -1 +1 @@ -Subproject commit 86698251ab87eec6944320a01998623155c01276 +Subproject commit de34caff946d598edb299566d951b44b9b7f7dd4 diff --git a/gateway/node.go b/gateway/node.go index b263a75bd..d0ff53402 100644 --- a/gateway/node.go +++ b/gateway/node.go @@ -5,8 +5,8 @@ import ( "fmt" "time" + blocks "github.com/ipfs/go-block-format" "github.com/ipfs/go-cid" - blocks "github.com/ipfs/go-libipfs/blocks" "go.opencensus.io/stats" "golang.org/x/time/rate" @@ -43,6 +43,9 @@ const ( // TargetAPI defines the API methods that the Node depends on // (to make it easy to mock for tests) type TargetAPI interface { + GasEstimateGasPremium(context.Context, uint64, address.Address, int64, types.TipSetKey) (types.BigInt, error) + StateReplay(context.Context, types.TipSetKey, cid.Cid) (*api.InvocResult, error) + StateMinerSectorCount(context.Context, address.Address, types.TipSetKey) (api.MinerSectors, error) Version(context.Context) (api.APIVersion, error) ChainGetParentMessages(context.Context, cid.Cid) ([]api.Message, error) ChainGetParentReceipts(context.Context, cid.Cid) ([]*types.MessageReceipt, error) @@ -112,6 +115,7 @@ type TargetAPI interface { EthGetStorageAt(ctx context.Context, address ethtypes.EthAddress, position ethtypes.EthBytes, blkParam string) (ethtypes.EthBytes, error) EthGetBalance(ctx context.Context, address ethtypes.EthAddress, blkParam string) (ethtypes.EthBigInt, error) EthChainId(ctx context.Context) (ethtypes.EthUint64, error) + EthSyncing(ctx context.Context) (ethtypes.EthSyncingResult, error) NetVersion(ctx context.Context) (string, error) NetListening(ctx context.Context) (bool, error) EthProtocolVersion(ctx context.Context) (ethtypes.EthUint64, error) diff --git a/gateway/proxy_eth.go b/gateway/proxy_eth.go index 3342875c3..b992c9ea9 100644 --- a/gateway/proxy_eth.go +++ b/gateway/proxy_eth.go @@ -252,6 +252,14 @@ func (gw *Node) EthChainId(ctx context.Context) (ethtypes.EthUint64, error) { return gw.target.EthChainId(ctx) } +func (gw *Node) EthSyncing(ctx context.Context) (ethtypes.EthSyncingResult, error) { + if err := gw.limit(ctx, basicRateLimitTokens); err != nil { + return ethtypes.EthSyncingResult{}, err + } + + return gw.target.EthSyncing(ctx) +} + func (gw *Node) NetVersion(ctx context.Context) (string, error) { if err := gw.limit(ctx, stateRateLimitTokens); err != nil { return "", err diff --git a/gateway/proxy_fil.go b/gateway/proxy_fil.go index 8007e1e7b..c15a78f5f 100644 --- a/gateway/proxy_fil.go +++ b/gateway/proxy_fil.go @@ -3,8 +3,8 @@ package gateway import ( "context" + blocks "github.com/ipfs/go-block-format" "github.com/ipfs/go-cid" - blocks "github.com/ipfs/go-libipfs/blocks" "golang.org/x/xerrors" "github.com/filecoin-project/go-address" @@ -23,6 +23,36 @@ import ( "github.com/filecoin-project/lotus/node/modules/dtypes" ) +func (gw *Node) StateReplay(ctx context.Context, tsk types.TipSetKey, c cid.Cid) (*api.InvocResult, error) { + if err := gw.limit(ctx, chainRateLimitTokens); err != nil { + return nil, err + } + if err := gw.checkTipsetKey(ctx, tsk); err != nil { + return nil, err + } + return gw.target.StateReplay(ctx, tsk, c) +} + +func (gw *Node) GasEstimateGasPremium(ctx context.Context, nblocksincl uint64, sender address.Address, gaslimit int64, tsk types.TipSetKey) (types.BigInt, error) { + if err := gw.limit(ctx, chainRateLimitTokens); err != nil { + return types.BigInt{}, err + } + if err := gw.checkTipsetKey(ctx, tsk); err != nil { + return types.BigInt{}, err + } + return gw.target.GasEstimateGasPremium(ctx, nblocksincl, sender, gaslimit, tsk) +} + +func (gw *Node) StateMinerSectorCount(ctx context.Context, m address.Address, tsk types.TipSetKey) (api.MinerSectors, error) { + if err := gw.limit(ctx, chainRateLimitTokens); err != nil { + return api.MinerSectors{}, err + } + if err := gw.checkTipsetKey(ctx, tsk); err != nil { + return api.MinerSectors{}, err + } + return gw.target.StateMinerSectorCount(ctx, m, tsk) +} + func (gw *Node) Discover(ctx context.Context) (apitypes.OpenRPCDocument, error) { return build.OpenRPCDiscoverJSON_Gateway(), nil } diff --git a/go.mod b/go.mod index 5c8922a90..50f9b40b8 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ retract v1.20.2 // Wrongfully cherry picked PR, use v1.20.2+ instead. require ( contrib.go.opencensus.io/exporter/prometheus v0.4.0 - github.com/BurntSushi/toml v1.1.0 + github.com/BurntSushi/toml v1.2.1 github.com/DataDog/zstd v1.4.5 github.com/GeertJohan/go.rice v1.0.3 github.com/Gurpartap/async v0.0.0-20180927173644-4f7f499dd9ee @@ -16,8 +16,8 @@ require ( github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d github.com/alecthomas/jsonschema v0.0.0-20200530073317-71f438968921 github.com/buger/goterm v1.0.3 - github.com/chzyer/readline v1.5.0 - github.com/containerd/cgroups v1.0.4 + github.com/chzyer/readline v1.5.1 + github.com/containerd/cgroups v1.1.0 github.com/coreos/go-systemd/v22 v22.5.0 github.com/detailyang/go-fallocate v0.0.0-20180908115635-432fa640bd2e github.com/dgraph-io/badger/v2 v2.2007.4 @@ -42,7 +42,7 @@ 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.27.0-rc1 - github.com/filecoin-project/go-jsonrpc v0.2.3 + github.com/filecoin-project/go-jsonrpc v0.3.1 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.11.1 @@ -77,8 +77,10 @@ require ( github.com/icza/backscanner v0.0.0-20210726202459-ac2ffc679f94 github.com/influxdata/influxdb1-client v0.0.0-20200827194710-b269163b24ab github.com/ipfs/bbloom v0.0.4 + github.com/ipfs/boxo v0.8.0 + github.com/ipfs/go-block-format v0.1.2 github.com/ipfs/go-blockservice v0.5.0 - github.com/ipfs/go-cid v0.4.0 + github.com/ipfs/go-cid v0.4.1 github.com/ipfs/go-cidutil v0.1.0 github.com/ipfs/go-datastore v0.6.0 github.com/ipfs/go-ds-badger2 v0.1.3 @@ -86,7 +88,7 @@ require ( github.com/ipfs/go-ds-measure v0.2.0 github.com/ipfs/go-fs-lock v0.0.7 github.com/ipfs/go-graphsync v0.14.3 - github.com/ipfs/go-ipfs-blockstore v1.2.0 + github.com/ipfs/go-ipfs-blockstore v1.3.0 github.com/ipfs/go-ipfs-blocksutil v0.0.1 github.com/ipfs/go-ipfs-chunker v0.0.5 github.com/ipfs/go-ipfs-ds-help v1.1.0 @@ -97,17 +99,16 @@ require ( github.com/ipfs/go-ipfs-util v0.0.2 github.com/ipfs/go-ipld-cbor v0.0.6 github.com/ipfs/go-ipld-format v0.4.0 - github.com/ipfs/go-libipfs v0.7.0 github.com/ipfs/go-log/v2 v2.5.1 - github.com/ipfs/go-merkledag v0.9.0 + github.com/ipfs/go-merkledag v0.10.0 github.com/ipfs/go-metrics-interface v0.0.1 github.com/ipfs/go-metrics-prometheus v0.0.2 - github.com/ipfs/go-unixfs v0.4.3 - github.com/ipfs/go-unixfsnode v1.5.2 + github.com/ipfs/go-unixfs v0.4.5 + github.com/ipfs/go-unixfsnode v1.6.0 github.com/ipfs/interface-go-ipfs-core v0.11.1 github.com/ipld/go-car v0.5.0 - github.com/ipld/go-car/v2 v2.7.0 - github.com/ipld/go-codec-dagpb v1.5.0 + github.com/ipld/go-car/v2 v2.10.0 + github.com/ipld/go-codec-dagpb v1.6.0 github.com/ipld/go-ipld-prime v0.20.0 github.com/ipld/go-ipld-selector-text-lite v0.0.1 github.com/ipni/index-provider v0.11.0 @@ -115,24 +116,24 @@ require ( github.com/kelseyhightower/envconfig v1.4.0 github.com/koalacxr/quantile v0.0.1 github.com/libp2p/go-buffer-pool v0.1.0 - github.com/libp2p/go-libp2p v0.26.2 + github.com/libp2p/go-libp2p v0.27.3 github.com/libp2p/go-libp2p-consensus v0.0.1 github.com/libp2p/go-libp2p-gorpc v0.5.0 - github.com/libp2p/go-libp2p-kad-dht v0.21.0 + github.com/libp2p/go-libp2p-kad-dht v0.21.1 github.com/libp2p/go-libp2p-pubsub v0.9.3 github.com/libp2p/go-libp2p-raft v0.4.0 github.com/libp2p/go-libp2p-record v0.2.0 github.com/libp2p/go-libp2p-routing-helpers v0.4.0 github.com/libp2p/go-maddr-filter v0.1.0 github.com/libp2p/go-msgio v0.3.0 - github.com/mattn/go-isatty v0.0.17 + github.com/mattn/go-isatty v0.0.18 github.com/mattn/go-sqlite3 v1.14.16 github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1 github.com/mitchellh/go-homedir v1.1.0 github.com/multiformats/go-base32 v0.1.0 - github.com/multiformats/go-multiaddr v0.8.0 + github.com/multiformats/go-multiaddr v0.9.0 github.com/multiformats/go-multiaddr-dns v0.3.1 - github.com/multiformats/go-multibase v0.1.1 + github.com/multiformats/go-multibase v0.2.0 github.com/multiformats/go-multihash v0.2.1 github.com/multiformats/go-varint v0.0.7 github.com/open-rpc/meta-schema v0.0.0-20201029221707-1b72ef2ea333 @@ -140,7 +141,7 @@ require ( github.com/prometheus/client_golang v1.14.0 github.com/raulk/clock v1.1.0 github.com/raulk/go-watchdog v1.3.0 - github.com/stretchr/testify v1.8.1 + github.com/stretchr/testify v1.8.2 github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 github.com/urfave/cli/v2 v2.16.3 github.com/whyrusleeping/bencher v0.0.0-20190829221104-bb6607aa8bba @@ -151,21 +152,21 @@ require ( github.com/xorcare/golden v0.6.1-0.20191112154924-b87f686d7542 github.com/zyedidia/generic v1.2.1 go.opencensus.io v0.24.0 - go.opentelemetry.io/otel v1.12.0 + go.opentelemetry.io/otel v1.14.0 go.opentelemetry.io/otel/bridge/opencensus v0.33.0 go.opentelemetry.io/otel/exporters/jaeger v1.2.0 go.opentelemetry.io/otel/sdk v1.11.1 go.uber.org/atomic v1.10.0 - go.uber.org/fx v1.18.2 - go.uber.org/multierr v1.9.0 + go.uber.org/fx v1.19.2 + go.uber.org/multierr v1.11.0 go.uber.org/zap v1.24.0 - golang.org/x/crypto v0.5.0 - golang.org/x/exp v0.0.0-20230129154200-a960b3787bd2 - golang.org/x/net v0.7.0 + golang.org/x/crypto v0.7.0 + golang.org/x/exp v0.0.0-20230321023759-10a507213a29 + golang.org/x/net v0.8.0 golang.org/x/sync v0.1.0 - golang.org/x/sys v0.5.0 + golang.org/x/sys v0.7.0 golang.org/x/time v0.0.0-20220722155302-e5dcc9cfc0b9 - golang.org/x/tools v0.3.0 + golang.org/x/tools v0.7.0 golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 gopkg.in/cheggaaa/pb.v1 v1.0.28 gotest.tools v2.2.0+incompatible @@ -177,7 +178,7 @@ require ( github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect github.com/StackExchange/wmi v1.2.1 // indirect github.com/akavel/rsrc v0.8.0 // indirect - github.com/alecthomas/units v0.0.0-20210927113745-59d0afb8317a // indirect + github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 // indirect github.com/armon/go-metrics v0.3.9 // indirect github.com/benbjohnson/clock v1.3.0 // indirect github.com/beorn7/perks v1.0.1 // indirect @@ -185,7 +186,7 @@ require ( github.com/boltdb/bolt v1.3.1 // indirect github.com/cespare/xxhash v1.1.0 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect - github.com/cilium/ebpf v0.4.0 // indirect + github.com/cilium/ebpf v0.9.1 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect github.com/crackcomm/go-gitignore v0.0.0-20170627025303-887ab5e44cc3 // indirect github.com/cskr/pubsub v1.0.2 // indirect @@ -216,25 +217,24 @@ require ( github.com/go-openapi/jsonpointer v0.19.3 // indirect github.com/go-openapi/jsonreference v0.19.4 // indirect github.com/go-openapi/swag v0.19.11 // indirect - github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 // indirect + github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect github.com/godbus/dbus/v5 v5.1.0 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/glog v1.0.0 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect - github.com/golang/protobuf v1.5.2 // indirect + github.com/golang/protobuf v1.5.3 // indirect github.com/golang/snappy v0.0.4 // indirect github.com/google/go-cmp v0.5.9 // indirect github.com/google/gopacket v1.1.19 // indirect - github.com/google/pprof v0.0.0-20221203041831-ce31453925ec // indirect + github.com/google/pprof v0.0.0-20230405160723-4a4c7d95572b // indirect github.com/hannahhoward/cbor-gen-for v0.0.0-20230214144701-5d17c9d5243c // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-immutable-radix v1.3.1 // indirect github.com/hashicorp/go-msgpack v0.5.5 // indirect github.com/hashicorp/golang-lru v0.6.0 // indirect - github.com/huin/goupnp v1.0.3 // indirect + github.com/huin/goupnp v1.1.0 // indirect github.com/iancoleman/orderedmap v0.1.0 // indirect github.com/ipfs/go-bitfield v1.1.0 // indirect - github.com/ipfs/go-block-format v0.1.1 // indirect github.com/ipfs/go-filestore v1.2.0 // indirect github.com/ipfs/go-ipfs-cmds v0.8.2 // indirect github.com/ipfs/go-ipfs-delay v0.0.1 // indirect @@ -243,6 +243,7 @@ require ( github.com/ipfs/go-ipfs-pq v0.0.3 // indirect github.com/ipfs/go-ipld-legacy v0.1.1 // indirect github.com/ipfs/go-ipns v0.3.0 // indirect + github.com/ipfs/go-libipfs v0.7.0 // indirect github.com/ipfs/go-log v1.0.5 // indirect github.com/ipfs/go-path v0.3.1 // indirect github.com/ipfs/go-peertaskqueue v0.8.1 // indirect @@ -258,12 +259,12 @@ require ( github.com/josharian/intern v1.0.0 // indirect github.com/jpillora/backoff v1.0.0 // indirect github.com/kilic/bls12-381 v0.1.0 // indirect - github.com/klauspost/compress v1.15.12 // indirect - github.com/klauspost/cpuid/v2 v2.2.3 // indirect - github.com/koron/go-ssdp v0.0.3 // indirect + github.com/klauspost/compress v1.16.4 // indirect + github.com/klauspost/cpuid/v2 v2.2.4 // indirect + github.com/koron/go-ssdp v0.0.4 // indirect github.com/libp2p/go-cidranger v1.1.0 // indirect github.com/libp2p/go-flow-metrics v0.1.0 // indirect - github.com/libp2p/go-libp2p-asn-util v0.2.0 // indirect + github.com/libp2p/go-libp2p-asn-util v0.3.0 // indirect github.com/libp2p/go-libp2p-gostream v0.6.0 // indirect github.com/libp2p/go-libp2p-kbucket v0.5.0 // indirect github.com/libp2p/go-nat v0.1.0 // indirect @@ -277,18 +278,18 @@ require ( github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-runewidth v0.0.10 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect - github.com/miekg/dns v1.1.50 // indirect + github.com/miekg/dns v1.1.53 // indirect github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b // indirect github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc // indirect github.com/minio/sha256-simd v1.0.0 // indirect github.com/mr-tron/base58 v1.2.0 // indirect github.com/multiformats/go-base36 v0.2.0 // indirect github.com/multiformats/go-multiaddr-fmt v0.1.0 // indirect - github.com/multiformats/go-multicodec v0.8.0 // indirect + github.com/multiformats/go-multicodec v0.8.1 // indirect github.com/multiformats/go-multistream v0.4.1 // indirect github.com/nikkolasg/hexjson v0.1.0 // indirect github.com/nkovacs/streamquote v1.0.0 // indirect - github.com/onsi/ginkgo/v2 v2.5.1 // indirect + github.com/onsi/ginkgo/v2 v2.9.2 // indirect github.com/opencontainers/runtime-spec v1.0.2 // indirect github.com/opentracing/opentracing-go v1.2.0 // indirect github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 // indirect @@ -296,12 +297,12 @@ require ( github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/prometheus/client_model v0.3.0 // indirect - github.com/prometheus/common v0.37.0 // indirect - github.com/prometheus/procfs v0.8.0 // indirect + github.com/prometheus/common v0.42.0 // indirect + github.com/prometheus/procfs v0.9.0 // indirect github.com/prometheus/statsd_exporter v0.21.0 // indirect github.com/quic-go/qpack v0.4.0 // indirect - github.com/quic-go/qtls-go1-19 v0.2.1 // indirect - github.com/quic-go/qtls-go1-20 v0.1.1 // indirect + github.com/quic-go/qtls-go1-19 v0.3.2 // indirect + github.com/quic-go/qtls-go1-20 v0.2.2 // indirect github.com/quic-go/quic-go v0.33.0 // indirect github.com/quic-go/webtransport-go v0.5.2 // indirect github.com/rivo/uniseg v0.1.0 // indirect @@ -324,15 +325,15 @@ require ( github.com/zondax/ledger-go v0.12.1 // indirect go.opentelemetry.io/otel/metric v0.33.0 // indirect go.opentelemetry.io/otel/sdk/metric v0.33.0 // indirect - go.opentelemetry.io/otel/trace v1.12.0 // indirect - go.uber.org/dig v1.15.0 // indirect + go.opentelemetry.io/otel/trace v1.14.0 // indirect + go.uber.org/dig v1.16.1 // indirect go4.org v0.0.0-20200411211856-f5505b9728dd // indirect - golang.org/x/mod v0.7.0 // indirect - golang.org/x/term v0.5.0 // indirect - golang.org/x/text v0.7.0 // indirect + golang.org/x/mod v0.10.0 // indirect + golang.org/x/term v0.6.0 // indirect + golang.org/x/text v0.8.0 // indirect google.golang.org/genproto v0.0.0-20210917145530-b395a37504d4 // indirect google.golang.org/grpc v1.45.0 // indirect - google.golang.org/protobuf v1.28.1 // indirect + google.golang.org/protobuf v1.30.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect howett.net/plist v0.0.0-20181124034731-591f970eefbb // indirect diff --git a/go.sum b/go.sum index c256baa36..b895ba0ef 100644 --- a/go.sum +++ b/go.sum @@ -45,8 +45,8 @@ github.com/AndreasBriese/bbloom v0.0.0-20180913140656-343706a395b7/go.mod h1:bOv github.com/AndreasBriese/bbloom v0.0.0-20190306092124-e2d15f34fcf9/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8= github.com/AndreasBriese/bbloom v0.0.0-20190825152654-46b345b51c96 h1:cTp8I5+VIoKjsnZuH8vjyaysT/ses3EvZeaV/1UkF2M= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/toml v1.1.0 h1:ksErzDEI1khOiGPgpwuI7x2ebx/uXQNw7xJpn9Eq1+I= -github.com/BurntSushi/toml v1.1.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/BurntSushi/toml v1.2.1 h1:9F2/+DoOYIOksmaJFPw1tGFy1eDnIJXg+UHjuD8lTak= +github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/DataDog/datadog-go v2.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= @@ -91,8 +91,8 @@ github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuy github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= -github.com/alecthomas/units v0.0.0-20210927113745-59d0afb8317a h1:E/8AP5dFtMhl5KPJz66Kt9G0n+7Sn41Fy1wv9/jHOrc= -github.com/alecthomas/units v0.0.0-20210927113745-59d0afb8317a/go.mod h1:OMCwj8VM1Kc9e19TLln2VL61YJF0x1XFtfdL4JdbSyE= +github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 h1:s6gZFSlWYmbqAuRjVTiNNhvNRfY2Wxp9nhfyel4rklc= +github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137/go.mod h1:OMCwj8VM1Kc9e19TLln2VL61YJF0x1XFtfdL4JdbSyE= github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= @@ -148,22 +148,21 @@ github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cheekybits/genny v1.0.0/go.mod h1:+tQajlRqAUrPI7DOSpB0XAqZYtQakVtB7wXkRAgjxjQ= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= -github.com/chzyer/logex v1.2.0 h1:+eqR0HfOetur4tgnC8ftU5imRnhi4te+BadWS95c5AM= -github.com/chzyer/logex v1.2.0/go.mod h1:9+9sk7u7pGNWYMkh0hdiL++6OeibzJccyQU4p4MedaY= +github.com/chzyer/logex v1.2.1 h1:XHDu3E6q+gdHgsdTPH6ImJMIp436vR6MPtH8gP05QzM= +github.com/chzyer/logex v1.2.1/go.mod h1:JLbx6lG2kDbNRFnfkgvh4eRJRPX1QCoOIWomwysCBrQ= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= -github.com/chzyer/readline v1.5.0 h1:lSwwFrbNviGePhkewF1az4oLmcwqCZijQ2/Wi3BGHAI= -github.com/chzyer/readline v1.5.0/go.mod h1:x22KAscuvRqlLoK9CsoYsmxoXZMMFVyOl86cAH8qUic= +github.com/chzyer/readline v1.5.1 h1:upd/6fQk4src78LMRzh5vItIt361/o4uq553V8B5sGI= +github.com/chzyer/readline v1.5.1/go.mod h1:Eh+b79XXUwfKfcPLepksvw2tcLE/Ct21YObkaSkeBlk= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= -github.com/chzyer/test v0.0.0-20210722231415-061457976a23 h1:dZ0/VyGgQdVGAss6Ju0dt5P0QltE0SFY5Woh6hbIfiQ= -github.com/chzyer/test v0.0.0-20210722231415-061457976a23/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/chzyer/test v1.0.0 h1:p3BQDXSxOhOG0P9z6/hGnII4LGiEPOYBhs8asl/fC04= +github.com/chzyer/test v1.0.0/go.mod h1:2JlltgoNkt4TW/z9V/IzDdFaMTM2JPIi26O1pF38GC8= github.com/cilium/ebpf v0.2.0/go.mod h1:To2CFviqOWL/M0gIMsvSMlqe7em/l1ALkX1PyjrX2Qs= -github.com/cilium/ebpf v0.4.0 h1:QlHdikaxALkqWasW8hAC1mfR0jdmvbfaBdBPFmRSglA= -github.com/cilium/ebpf v0.4.0/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs= +github.com/cilium/ebpf v0.9.1 h1:64sn2K3UKw8NbP/blsixRpF3nXuyhz/VjRlRzvlBRu4= +github.com/cilium/ebpf v0.9.1/go.mod h1:+OhNOIXx/Fnu1IE8bJz2dzOA+VSfyTfdNUVdlQnxUFY= github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE= @@ -179,8 +178,8 @@ github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:z github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= github.com/codegangsta/cli v1.20.0/go.mod h1:/qJNoX69yVSKu5o4jLyXAENLRyk1uhi7zkbQ3slBdOA= github.com/containerd/cgroups v0.0.0-20201119153540-4cbc285b3327/go.mod h1:ZJeTFisyysqgcCdecO57Dj79RfL0LNeGiFUqLYQRYLE= -github.com/containerd/cgroups v1.0.4 h1:jN/mbWBEaz+T1pi5OFtnkQ+8qnmEbAr1Oo1FRm5B0dA= -github.com/containerd/cgroups v1.0.4/go.mod h1:nLNQtsF7Sl2HxNebu77i1R0oDlhiTG+kO4JTrUzo6IA= +github.com/containerd/cgroups v1.1.0 h1:v8rEWFl6EoqHB+swVNjVoCJE8o3jX7e8nqBGPLaDFBM= +github.com/containerd/cgroups v1.1.0/go.mod h1:6ppBcbh/NOOUU+dMKrykgaBnK9lCIBxHqJDGwsa1mIw= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= @@ -331,8 +330,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.2.3 h1:xdixRQfLbD8gt56dpBNKiya9gvI/79nNM13IHKTfm5E= -github.com/filecoin-project/go-jsonrpc v0.2.3/go.mod h1:jBSvPTl8V1N7gSTuCR4bis8wnQnIjHbRPpROol6iQKM= +github.com/filecoin-project/go-jsonrpc v0.3.1 h1:qwvAUc5VwAkooquKJmfz9R2+F8znhiqcNHYjEp/NM10= +github.com/filecoin-project/go-jsonrpc v0.3.1/go.mod h1:jBSvPTl8V1N7gSTuCR4bis8wnQnIjHbRPpROol6iQKM= github.com/filecoin-project/go-padreader v0.0.0-20200903213702-ed5fae088b20/go.mod h1:mPn+LRRd5gEKNAtc+r3ScpW2JRU/pj4NBKdADYWHiak= github.com/filecoin-project/go-padreader v0.0.1 h1:8h2tVy5HpoNbr2gBRr+WD6zV6VD6XHig+ynSGJg8ZOs= github.com/filecoin-project/go-padreader v0.0.1/go.mod h1:VYVPJqwpsfmtoHnAmPx6MUwmrK6HIcDqZJiuZhtmfLQ= @@ -390,7 +389,7 @@ github.com/frankban/quicktest v1.14.3/go.mod h1:mgiwOwqx65TmIk1wJ6Q7wvnVMocbUork github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= -github.com/fsnotify/fsnotify v1.5.4 h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwVZI= +github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= github.com/gbrlsnchs/jwt/v3 v3.0.1 h1:lbUmgAKpxnClrKloyIwpxm4OuWeDl5wLk52G91ODPw4= github.com/gbrlsnchs/jwt/v3 v3.0.1/go.mod h1:AncDcjXz18xetI3A6STfXq2w+LuTx8pQ8bGEwRN8zVM= github.com/gdamore/encoding v1.0.0 h1:+7OoQ1Bc6eTm5niUzBa0Ctsh6JbMW6Ra+YNuAtDBdko= @@ -413,7 +412,6 @@ github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2 github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgOZ7o= github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= -github.com/go-kit/log v0.2.0/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= github.com/go-kit/log v0.2.1 h1:MRVx0/zhvdseW+Gza6N9rVzU/IVzaeE1SFI4raAhmBU= github.com/go-kit/log v0.2.1/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= @@ -454,8 +452,8 @@ github.com/go-playground/validator/v10 v10.2.0 h1:KgJ0snyC2R9VXYN2rneOtQcw5aHQB1 github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI= github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/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/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= +github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= github.com/go-yaml/yaml v2.1.0+incompatible/go.mod h1:w2MrLa16VYP0jy6N7M5kHaCkaLENm+P+Tv+MfurjSw0= 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= @@ -517,8 +515,9 @@ github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QD github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= +github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= @@ -556,8 +555,8 @@ github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hf github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20221203041831-ce31453925ec h1:fR20TYVVwhK4O7r7y+McjRYyaTH6/vjwJOajE+XhlzM= -github.com/google/pprof v0.0.0-20221203041831-ce31453925ec/go.mod h1:dDKJzRmX4S37WGHujM7tX//fmj1uioxKzKxz3lo4HJo= +github.com/google/pprof v0.0.0-20230405160723-4a4c7d95572b h1:Qcx5LM0fSiks9uCyFZwDBUasd3lxd1RM0GYpL+Li5o4= +github.com/google/pprof v0.0.0-20230405160723-4a4c7d95572b/go.mod h1:79YE0hCXdHag9sBkw2o+N/YnZtTkXi0UT9Nnixa5eYk= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -650,8 +649,8 @@ github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/J github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg= github.com/huin/goupnp v1.0.0/go.mod h1:n9v9KO1tAxYH82qOn+UTIFQDmx5n1Zxd/ClZDMX7Bnc= -github.com/huin/goupnp v1.0.3 h1:N8No57ls+MnjlB+JPiCVSOyy/ot7MJTqlo7rn+NYSqQ= -github.com/huin/goupnp v1.0.3/go.mod h1:ZxNlw5WqJj6wSsRK5+YfflQGXYfccj5VgQsMNixHM7Y= +github.com/huin/goupnp v1.1.0 h1:gEe0Dp/lZmPZiDFzJJaOfUpOvv2MKUkoBX8lDrn9vKU= +github.com/huin/goupnp v1.1.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8= github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150/go.mod h1:PpLOETDnJ0o3iZrZfqZzyLl6l7F3c6L1oWn7OICBi6o= github.com/iancoleman/orderedmap v0.0.0-20190318233801-ac98e3ecb4b0/go.mod h1:N0Wam8K1arqPXNWjMo21EXnBPOPp36vB07FNRdD2geA= github.com/iancoleman/orderedmap v0.1.0 h1:2orAxZBJsvimgEBmMWfXaFlzSG2fbQil5qzP3F6cCkg= @@ -670,6 +669,8 @@ github.com/influxdata/influxdb1-client v0.0.0-20200827194710-b269163b24ab/go.mod github.com/ipfs/bbloom v0.0.1/go.mod h1:oqo8CVWsJFMOZqTglBG4wydCE4IQA/G2/SEofB0rjUI= github.com/ipfs/bbloom v0.0.4 h1:Gi+8EGJ2y5qiD5FbsbpX/TMNcJw8gSqr7eyjHa4Fhvs= github.com/ipfs/bbloom v0.0.4/go.mod h1:cS9YprKXpoZ9lT0n/Mw/a6/aFV6DTjTLYHeA+gyqMG0= +github.com/ipfs/boxo v0.8.0 h1:UdjAJmHzQHo/j3g3b1bAcAXCj/GM6iTwvSlBDvPBNBs= +github.com/ipfs/boxo v0.8.0/go.mod h1:RIsi4CnTyQ7AUsNn5gXljJYZlQrHBMnJp94p73liFiA= github.com/ipfs/go-bitfield v1.1.0 h1:fh7FIo8bSwaJEh6DdTWbCeZ1eqOaOkKFI74SCnsWbGA= github.com/ipfs/go-bitfield v1.1.0/go.mod h1:paqf1wjq/D2BBmzfTVFlJQ9IlFOZpg422HL0HqsGWHU= github.com/ipfs/go-bitswap v0.1.0/go.mod h1:FFJEf18E9izuCqUtHxbWEvq+reg7o4CW5wSAE1wsxj0= @@ -680,8 +681,8 @@ github.com/ipfs/go-bitswap v0.11.0 h1:j1WVvhDX1yhG32NTC9xfxnqycqYIlhzEzLXG/cU1Hy github.com/ipfs/go-block-format v0.0.1/go.mod h1:DK/YYcsSUIVAFNwo/KZCdIIbpN0ROH/baNLgayt4pFc= github.com/ipfs/go-block-format v0.0.2/go.mod h1:AWR46JfpcObNfg3ok2JHDUfdiHRgWhJgCQF+KIgOPJY= github.com/ipfs/go-block-format v0.0.3/go.mod h1:4LmD4ZUw0mhO+JSKdpWwrzATiEfM7WWgQ8H5l6P8MVk= -github.com/ipfs/go-block-format v0.1.1 h1:129vSO3zwbsYADcyQWcOYiuCpAqt462SFfqFHdFJhhI= -github.com/ipfs/go-block-format v0.1.1/go.mod h1:+McEIT+g52p+zz5xGAABGSOKrzmrdX97bc0USBdWPUs= +github.com/ipfs/go-block-format v0.1.2 h1:GAjkfhVx1f4YTODS6Esrj1wt2HhrtwTnhEr+DyPUaJo= +github.com/ipfs/go-block-format v0.1.2/go.mod h1:mACVcrxarQKstUU3Yf/RdwbC4DzPV6++rO2a3d+a/KE= github.com/ipfs/go-blockservice v0.1.0/go.mod h1:hzmMScl1kXHg3M2BjTymbVPjv627N7sYcvYaKbop39M= github.com/ipfs/go-blockservice v0.2.1/go.mod h1:k6SiwmgyYgs4M/qt+ww6amPeUH9EISLRBnvUurKJhi8= github.com/ipfs/go-blockservice v0.3.0/go.mod h1:P5ppi8IHDC7O+pA0AlGTF09jruB2h+oP3wVVaZl8sfk= @@ -699,8 +700,8 @@ github.com/ipfs/go-cid v0.0.7/go.mod h1:6Ux9z5e+HpkQdckYoX1PG/6xqKspzlEIR5SDmgqg github.com/ipfs/go-cid v0.1.0/go.mod h1:rH5/Xv83Rfy8Rw6xG+id3DYAMUVmem1MowoKwdXmN2o= github.com/ipfs/go-cid v0.2.0/go.mod h1:P+HXFDF4CVhaVayiEb4wkAy7zBHxBwsJyt0Y5U6MLro= github.com/ipfs/go-cid v0.3.2/go.mod h1:gQ8pKqT/sUxGY+tIwy1RPpAojYu7jAyCp5Tz1svoupw= -github.com/ipfs/go-cid v0.4.0 h1:a4pdZq0sx6ZSxbCizebnKiMCx/xI/aBBFlB73IgH4rA= -github.com/ipfs/go-cid v0.4.0/go.mod h1:uQHwDeX4c6CtyrFwdqyhpNcxVewur1M7l7fNU7LKwZk= +github.com/ipfs/go-cid v0.4.1 h1:A/T3qGvxi4kpKWWcPC/PgbvDA2bjVLO7n4UeVwnbs/s= +github.com/ipfs/go-cid v0.4.1/go.mod h1:uQHwDeX4c6CtyrFwdqyhpNcxVewur1M7l7fNU7LKwZk= github.com/ipfs/go-cidutil v0.1.0 h1:RW5hO7Vcf16dplUU60Hs0AKDkQAVPVplr7lk97CFL+Q= github.com/ipfs/go-cidutil v0.1.0/go.mod h1:e7OEVBMIv9JaOxt9zaGEmAoSlXW9jdFZ5lP/0PwcfpA= github.com/ipfs/go-datastore v0.0.1/go.mod h1:d4KVXhMt913cLBEI/PXAy6ko+W7e9AhyAKBGh803qeE= @@ -743,8 +744,9 @@ github.com/ipfs/go-ipfs-blockstore v0.0.1/go.mod h1:d3WClOmRQKFnJ0Jz/jj/zmksX0ma github.com/ipfs/go-ipfs-blockstore v0.1.0/go.mod h1:5aD0AvHPi7mZc6Ci1WCAhiBQu2IsfTduLl+422H6Rqw= github.com/ipfs/go-ipfs-blockstore v0.2.1/go.mod h1:jGesd8EtCM3/zPgx+qr0/feTXGUeRai6adgwC+Q+JvE= github.com/ipfs/go-ipfs-blockstore v1.1.2/go.mod h1:w51tNR9y5+QXB0wkNcHt4O2aSZjTdqaEWaQdSxEyUOY= -github.com/ipfs/go-ipfs-blockstore v1.2.0 h1:n3WTeJ4LdICWs/0VSfjHrlqpPpl6MZ+ySd3j8qz0ykw= github.com/ipfs/go-ipfs-blockstore v1.2.0/go.mod h1:eh8eTFLiINYNSNawfZOC7HOxNTxpB1PFuA5E1m/7exE= +github.com/ipfs/go-ipfs-blockstore v1.3.0 h1:m2EXaWgwTzAfsmt5UdJ7Is6l4gJcaM/A12XwJyvYvMM= +github.com/ipfs/go-ipfs-blockstore v1.3.0/go.mod h1:KgtZyc9fq+P2xJUiCAzbRdhhqJHvsw8u2Dlqy2MyRTE= github.com/ipfs/go-ipfs-blocksutil v0.0.1 h1:Eh/H4pc1hsvhzsQoMEP3Bke/aW5P5rVM1IWFJMcGIPQ= github.com/ipfs/go-ipfs-blocksutil v0.0.1/go.mod h1:Yq4M86uIOmxmGPUHv/uI7uKqZNtLb449gwKqXjIsnRk= github.com/ipfs/go-ipfs-chunker v0.0.1/go.mod h1:tWewYK0we3+rMbOh7pPFGDyypCtvGcBFymgY4rSDLAw= @@ -832,8 +834,8 @@ github.com/ipfs/go-merkledag v0.2.4/go.mod h1:SQiXrtSts3KGNmgOzMICy5c0POOpUNQLvB github.com/ipfs/go-merkledag v0.3.2/go.mod h1:fvkZNNZixVW6cKSZ/JfLlON5OlgTXNdRLz0p6QG/I2M= github.com/ipfs/go-merkledag v0.5.1/go.mod h1:cLMZXx8J08idkp5+id62iVftUQV+HlYJ3PIhDfZsjA4= github.com/ipfs/go-merkledag v0.6.0/go.mod h1:9HSEwRd5sV+lbykiYP+2NC/3o6MZbKNaa4hfNcH5iH0= -github.com/ipfs/go-merkledag v0.9.0 h1:DFC8qZ96Dz1hMT7dtIpcY524eFFDiEWAF8hNJHWW2pk= -github.com/ipfs/go-merkledag v0.9.0/go.mod h1:bPHqkHt5OZ0p1n3iqPeDiw2jIBkjAytRjS3WSBwjq90= +github.com/ipfs/go-merkledag v0.10.0 h1:IUQhj/kzTZfam4e+LnaEpoiZ9vZF6ldimVlby+6OXL4= +github.com/ipfs/go-merkledag v0.10.0/go.mod h1:zkVav8KiYlmbzUzNM6kENzkdP5+qR7+2mCwxkQ6GIj8= github.com/ipfs/go-metrics-interface v0.0.1 h1:j+cpbjYvu4R8zbleSs36gvB7jR+wsL2fGD6n0jO4kdg= github.com/ipfs/go-metrics-interface v0.0.1/go.mod h1:6s6euYU4zowdslK0GKHmqaIZ3j/b/tL7HTWtJ4VPgWY= github.com/ipfs/go-metrics-prometheus v0.0.2 h1:9i2iljLg12S78OhC6UAiXi176xvQGiZaGVF1CUVdE+s= @@ -845,10 +847,10 @@ github.com/ipfs/go-peertaskqueue v0.7.0/go.mod h1:M/akTIE/z1jGNXMU7kFB4TeSEFvj68 github.com/ipfs/go-peertaskqueue v0.8.1 h1:YhxAs1+wxb5jk7RvS0LHdyiILpNmRIRnZVztekOF0pg= github.com/ipfs/go-peertaskqueue v0.8.1/go.mod h1:Oxxd3eaK279FxeydSPPVGHzbwVeHjatZ2GA8XD+KbPU= github.com/ipfs/go-unixfs v0.2.2-0.20190827150610-868af2e9e5cb/go.mod h1:IwAAgul1UQIcNZzKPYZWOCijryFBeCV79cNubPzol+k= -github.com/ipfs/go-unixfs v0.4.3 h1:EdDc1sNZNFDUlo4UrVAvvAofVI5EwTnKu8Nv8mgXkWQ= -github.com/ipfs/go-unixfs v0.4.3/go.mod h1:TSG7G1UuT+l4pNj91raXAPkX0BhJi3jST1FDTfQ5QyM= -github.com/ipfs/go-unixfsnode v1.5.2 h1:CvsiTt58W2uR5dD8bqQv+aAY0c1qolmXmSyNbPHYiew= -github.com/ipfs/go-unixfsnode v1.5.2/go.mod h1:NlOebRwYx8lMCNMdhAhEspYPBD3obp7TE0LvBqHY+ks= +github.com/ipfs/go-unixfs v0.4.5 h1:wj8JhxvV1G6CD7swACwSKYa+NgtdWC1RUit+gFnymDU= +github.com/ipfs/go-unixfs v0.4.5/go.mod h1:BIznJNvt/gEx/ooRMI4Us9K8+qeGO7vx1ohnbk8gjFg= +github.com/ipfs/go-unixfsnode v1.6.0 h1:JOSA02yaLylRNi2rlB4ldPr5VcZhcnaIVj5zNLcOjDo= +github.com/ipfs/go-unixfsnode v1.6.0/go.mod h1:PVfoyZkX1B34qzT3vJO4nsLUpRCyhnMuHBznRcXirlk= github.com/ipfs/go-verifcid v0.0.1/go.mod h1:5Hrva5KBeIog4A+UpqlaIU+DEstipcJYQQZc0g37pY0= github.com/ipfs/go-verifcid v0.0.2 h1:XPnUv0XmdH+ZIhLGKg6U2vaPaRDXb9urMyNVCE7uvTs= github.com/ipfs/go-verifcid v0.0.2/go.mod h1:40cD9x1y4OWnFXbLNJYRe7MpNvWlMn3LZAG5Wb4xnPU= @@ -861,12 +863,12 @@ github.com/ipld/go-car v0.1.0/go.mod h1:RCWzaUh2i4mOEkB3W45Vc+9jnS/M6Qay5ooytiBH github.com/ipld/go-car v0.5.0 h1:kcCEa3CvYMs0iE5BzD5sV7O2EwMiCIp3uF8tA6APQT8= github.com/ipld/go-car v0.5.0/go.mod h1:ppiN5GWpjOZU9PgpAZ9HbZd9ZgSpwPMr48fGRJOWmvE= github.com/ipld/go-car/v2 v2.1.1/go.mod h1:+2Yvf0Z3wzkv7NeI69i8tuZ+ft7jyjPYIWZzeVNeFcI= -github.com/ipld/go-car/v2 v2.7.0 h1:OFxJl6X6Ii7y7wYX4R+P8q9+vuz4vaY2Y9u1GHzfxbE= -github.com/ipld/go-car/v2 v2.7.0/go.mod h1:qoqfgPnQYcaAYcfphctffdaNWJIWBR2QN4pjuKUtgao= +github.com/ipld/go-car/v2 v2.10.0 h1:0Wrt0uk3IoBge1PjEokXsS1eOX6v8QxeTxjPQ9TH71M= +github.com/ipld/go-car/v2 v2.10.0/go.mod h1:mBZ4d86IKvL7eKhNHhQgywQ5coZHAGhmG1P+cMrdby8= github.com/ipld/go-codec-dagpb v1.2.0/go.mod h1:6nBN7X7h8EOsEejZGqC7tej5drsdBAXbMHyBT+Fne5s= github.com/ipld/go-codec-dagpb v1.3.0/go.mod h1:ga4JTU3abYApDC3pZ00BC2RSvC3qfBb9MSJkMLSwnhA= -github.com/ipld/go-codec-dagpb v1.5.0 h1:RspDRdsJpLfgCI0ONhTAnbHdySGD4t+LHSPK4X1+R0k= -github.com/ipld/go-codec-dagpb v1.5.0/go.mod h1:0yRIutEFD8o1DGVqw4RSHh+BUTlJA9XWldxaaWR/o4g= +github.com/ipld/go-codec-dagpb v1.6.0 h1:9nYazfyu9B1p3NAgfVdpRco3Fs2nFC72DqVsMj6rOcc= +github.com/ipld/go-codec-dagpb v1.6.0/go.mod h1:ANzFhfP2uMJxRBr8CE+WQWs5UsNa0pYtmKZ+agnUw9s= github.com/ipld/go-ipld-adl-hamt v0.0.0-20220616142416-9004dbd839e0 h1:QAI/Ridj0+foHD6epbxmB4ugxz9B4vmNdYSmQLGa05E= github.com/ipld/go-ipld-adl-hamt v0.0.0-20220616142416-9004dbd839e0/go.mod h1:odxGcpiQZLzP5+yGu84Ljo8y3EzCvNAQKEodHNsHLXA= github.com/ipld/go-ipld-prime v0.0.2-0.20191108012745-28a82f04c785/go.mod h1:bDDSvVz7vaK12FNvMeRYnpRFkSUPNQOiCYQezMD/P3w= @@ -926,7 +928,6 @@ github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/u github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= -github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/jtolds/gls v4.2.1+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= @@ -950,13 +951,13 @@ github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+o github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.12.3/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= -github.com/klauspost/compress v1.15.12 h1:YClS/PImqYbn+UILDnqxQCZ3RehC9N318SU3kElDUEM= -github.com/klauspost/compress v1.15.12/go.mod h1:QPwzmACJjUTFsnSHH934V6woptycfrDDJnH7hvFVbGM= +github.com/klauspost/compress v1.16.4 h1:91KN02FnsOYhuunwU4ssRe8lc2JosWmizWa91B5v1PU= +github.com/klauspost/compress v1.16.4/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.0.6/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= -github.com/klauspost/cpuid/v2 v2.2.3 h1:sxCkb+qR91z4vsqw4vGGZlDgPz3G7gjaLyK3V8y70BU= -github.com/klauspost/cpuid/v2 v2.2.3/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY= +github.com/klauspost/cpuid/v2 v2.2.4 h1:acbojRNwl3o09bUq+yDCtZFc1aiwaAAxtcn8YkZXnvk= +github.com/klauspost/cpuid/v2 v2.2.4/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY= 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= @@ -964,8 +965,8 @@ github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxv 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= -github.com/koron/go-ssdp v0.0.3 h1:JivLMY45N76b4p/vsWGOKewBQu6uf39y8l+AQ7sDKx8= -github.com/koron/go-ssdp v0.0.3/go.mod h1:b2MxI6yh02pKrsyNoQUsk4+YNikaGhe4894J+Q5lDvA= +github.com/koron/go-ssdp v0.0.4 h1:1IDwrghSKYM7yLf7XCzbByg2sJ/JcNOZRXS2jczTwz0= +github.com/koron/go-ssdp v0.0.4/go.mod h1:oDXq+E5IL5q0U8uSBcoAXzTzInwy5lEgC91HoKtbmZk= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= @@ -1004,10 +1005,10 @@ github.com/libp2p/go-libp2p v0.7.0/go.mod h1:hZJf8txWeCduQRDC/WSqBGMxaTHCOYHt2xS github.com/libp2p/go-libp2p v0.7.4/go.mod h1:oXsBlTLF1q7pxr+9w6lqzS1ILpyHsaBPniVO7zIHGMw= github.com/libp2p/go-libp2p v0.8.1/go.mod h1:QRNH9pwdbEBpx5DTJYg+qxcVaDMAz3Ee/qDKwXujH5o= github.com/libp2p/go-libp2p v0.14.3/go.mod h1:d12V4PdKbpL0T1/gsUNN8DfgMuRPDX8bS2QxCZlwRH0= -github.com/libp2p/go-libp2p v0.26.2 h1:eHEoW/696FP7/6DxOvcrKfTD6Bi0DExxiMSZUJxswA0= -github.com/libp2p/go-libp2p v0.26.2/go.mod h1:x75BN32YbwuY0Awm2Uix4d4KOz+/4piInkp4Wr3yOo8= -github.com/libp2p/go-libp2p-asn-util v0.2.0 h1:rg3+Os8jbnO5DxkC7K/Utdi+DkY3q/d1/1q+8WeNAsw= -github.com/libp2p/go-libp2p-asn-util v0.2.0/go.mod h1:WoaWxbHKBymSN41hWSq/lGKJEca7TNm58+gGJi2WsLI= +github.com/libp2p/go-libp2p v0.27.3 h1:tkV/zm3KCZ4R5er9Xcs2pt0YNB4JH0iBfGAtHJdLHRs= +github.com/libp2p/go-libp2p v0.27.3/go.mod h1:FAvvfQa/YOShUYdiSS03IR9OXzkcJXwcNA2FUCh9ImE= +github.com/libp2p/go-libp2p-asn-util v0.3.0 h1:gMDcMyYiZKkocGXDQ5nsUQyquC9+H+iLEQHwOCZ7s8s= +github.com/libp2p/go-libp2p-asn-util v0.3.0/go.mod h1:B1mcOrKUE35Xq/ASTmQ4tN3LNzVVaMNmq2NACuqyB9w= github.com/libp2p/go-libp2p-autonat v0.1.0/go.mod h1:1tLf2yXxiE/oKGtDwPYWTSYG3PtvYlJmg7NeVtPRqH8= github.com/libp2p/go-libp2p-autonat v0.1.1/go.mod h1:OXqkeGOY2xJVWKAGV2inNF5aKN/djNA3fdpCWloIudE= github.com/libp2p/go-libp2p-autonat v0.2.0/go.mod h1:DX+9teU4pEEoZUqR1PiMlqliONQdNbfzE1C718tcViI= @@ -1055,8 +1056,8 @@ github.com/libp2p/go-libp2p-gorpc v0.5.0 h1:mmxxAPdP3JzpYH4KcDf4csXnqtd1HazLPfdy github.com/libp2p/go-libp2p-gorpc v0.5.0/go.mod h1:GpHuvY3m0YFkd0+inOGo4HDtc4up9OS/mBPXvEpNuRY= github.com/libp2p/go-libp2p-gostream v0.6.0 h1:QfAiWeQRce6pqnYfmIVWJFXNdDyfiR/qkCnjyaZUPYU= github.com/libp2p/go-libp2p-gostream v0.6.0/go.mod h1:Nywu0gYZwfj7Jc91PQvbGU8dIpqbQQkjWgDuOrFaRdA= -github.com/libp2p/go-libp2p-kad-dht v0.21.0 h1:J0Yd22VA+sk0CJRGMgtfHvLVIkZDyJ3AJGiljywIw5U= -github.com/libp2p/go-libp2p-kad-dht v0.21.0/go.mod h1:Bhm9diAFmc6qcWAr084bHNL159srVZRKADdp96Qqd1I= +github.com/libp2p/go-libp2p-kad-dht v0.21.1 h1:xpfp8/t9+X2ip1l8Umap1/UGNnJ3RHJgKGAEsnRAlTo= +github.com/libp2p/go-libp2p-kad-dht v0.21.1/go.mod h1:Oy8wvbdjpB70eS5AaFaI68tOtrdo3KylTvXDjikxqFo= github.com/libp2p/go-libp2p-kbucket v0.5.0 h1:g/7tVm8ACHDxH29BGrpsQlnNeu+6OF1A9bno/4/U1oA= github.com/libp2p/go-libp2p-kbucket v0.5.0/go.mod h1:zGzGCpQd78b5BNTDGHNDLaTt9aDK/A02xeZp9QeFC4U= github.com/libp2p/go-libp2p-loggables v0.1.0/go.mod h1:EyumB2Y6PrYjr55Q3/tiJ/o3xoDasoRYM7nOzEpoa90= @@ -1226,8 +1227,8 @@ github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Ky github.com/mattn/go-isatty v0.0.13/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= -github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng= -github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.18 h1:DOKFKCQ7FNG2L1rbrmstDN4QVRdS89Nkh85u68Uwp98= +github.com/mattn/go-isatty v0.0.18/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-runewidth v0.0.10 h1:CoZ3S2P7pvtP45xOtBw+/mDL2z0RKI576gSkzRRpdGg= @@ -1243,8 +1244,8 @@ github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3N github.com/miekg/dns v1.1.12/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/miekg/dns v1.1.28/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM= github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI= -github.com/miekg/dns v1.1.50 h1:DQUfb9uc6smULcREF09Uc+/Gd46YWqJd5DbpPE9xkcA= -github.com/miekg/dns v1.1.50/go.mod h1:e3IlAVfNqAllflbibAZEWOXOQ+Ynzk/dDozDxY7XnME= +github.com/miekg/dns v1.1.53 h1:ZBkuHr5dxHtB1caEOlZTLPo7D3L3TWckgUUs/RHfDxw= +github.com/miekg/dns v1.1.53/go.mod h1:uInx36IzPl7FYnDcMeVWxj9byh7DutNykX4G9Sj60FY= github.com/mikioh/tcp v0.0.0-20190314235350-803a9b46060c h1:bzE/A84HN25pxAuk9Eej1Kz9OUelF97nAc82bDquQI8= github.com/mikioh/tcp v0.0.0-20190314235350-803a9b46060c/go.mod h1:0SQS9kMwD2VsyFEB++InYyBJroV/FRmBgcydeSUcJms= github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b h1:z78hV3sbSMAUoyUMM0I83AUIT6Hu17AWfgjzIbtrYFc= @@ -1275,7 +1276,6 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= -github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/mr-tron/base58 v1.1.0/go.mod h1:xcD2VGqlgYjBdcBLw+TuYLr8afG+Hj8g2eTVqeSzSU8= github.com/mr-tron/base58 v1.1.1/go.mod h1:xcD2VGqlgYjBdcBLw+TuYLr8afG+Hj8g2eTVqeSzSU8= github.com/mr-tron/base58 v1.1.2/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= @@ -1300,8 +1300,8 @@ github.com/multiformats/go-multiaddr v0.2.2/go.mod h1:NtfXiOtHvghW9KojvtySjH5y0u github.com/multiformats/go-multiaddr v0.3.0/go.mod h1:dF9kph9wfJ+3VLAaeBqo9Of8x4fJxp6ggJGteB8HQTI= github.com/multiformats/go-multiaddr v0.3.1/go.mod h1:uPbspcUPd5AfaP6ql3ujFY+QWzmBD8uLLL4bXW0XfGc= github.com/multiformats/go-multiaddr v0.3.3/go.mod h1:lCKNGP1EQ1eZ35Za2wlqnabm9xQkib3fyB+nZXHLag0= -github.com/multiformats/go-multiaddr v0.8.0 h1:aqjksEcqK+iD/Foe1RRFsGZh8+XFiGo7FgUCZlpv3LU= -github.com/multiformats/go-multiaddr v0.8.0/go.mod h1:Fs50eBDWvZu+l3/9S6xAE7ZYj6yhxlvaVZjakWN7xRs= +github.com/multiformats/go-multiaddr v0.9.0 h1:3h4V1LHIk5w4hJHekMKWALPXErDfz/sggzwC/NcqbDQ= +github.com/multiformats/go-multiaddr v0.9.0/go.mod h1:mI67Lb1EeTOYb8GQfL/7wpIZwc46ElrvzhYnoJOmTT0= github.com/multiformats/go-multiaddr-dns v0.0.1/go.mod h1:9kWcqw/Pj6FwxAwW38n/9403szc57zJPs45fmnznu3Q= github.com/multiformats/go-multiaddr-dns v0.0.2/go.mod h1:9kWcqw/Pj6FwxAwW38n/9403szc57zJPs45fmnznu3Q= github.com/multiformats/go-multiaddr-dns v0.2.0/go.mod h1:TJ5pr5bBO7Y1B18djPuRsVkduhQH2YqYSbxWJzYGdK0= @@ -1320,13 +1320,13 @@ github.com/multiformats/go-multiaddr-net v0.1.5/go.mod h1:ilNnaM9HbmVFqsb/qcNysj github.com/multiformats/go-multiaddr-net v0.2.0/go.mod h1:gGdH3UXny6U3cKKYCvpXI5rnK7YaOIEOPVDI9tsJbEA= github.com/multiformats/go-multibase v0.0.1/go.mod h1:bja2MqRZ3ggyXtZSEDKpl0uO/gviWFaSteVbWT51qgs= github.com/multiformats/go-multibase v0.0.3/go.mod h1:5+1R4eQrT3PkYZ24C3W2Ue2tPwIdYQD509ZjSb5y9Oc= -github.com/multiformats/go-multibase v0.1.1 h1:3ASCDsuLX8+j4kx58qnJ4YFq/JWTJpCyDW27ztsVTOI= -github.com/multiformats/go-multibase v0.1.1/go.mod h1:ZEjHE+IsUrgp5mhlEAYjMtZwK1k4haNkcaPg9aoe1a8= +github.com/multiformats/go-multibase v0.2.0 h1:isdYCVLvksgWlMW9OZRYJEa9pZETFivncJHmHnnd87g= +github.com/multiformats/go-multibase v0.2.0/go.mod h1:bFBZX4lKCA/2lyOFSAoKH5SS6oPyjtnzK/XTFDPkNuk= github.com/multiformats/go-multicodec v0.3.0/go.mod h1:qGGaQmioCDh+TeFOnxrbU0DaIPw8yFgAZgFG0V7p1qQ= github.com/multiformats/go-multicodec v0.3.1-0.20210902112759-1539a079fd61/go.mod h1:1Hj/eHRaVWSXiSNNfcEPcwZleTmdNP81xlxDLnWU9GQ= github.com/multiformats/go-multicodec v0.6.0/go.mod h1:GUC8upxSBE4oG+q3kWZRw/+6yC1BqO550bjhWsJbZlw= -github.com/multiformats/go-multicodec v0.8.0 h1:evBmgkbSQux+Ds2IgfhkO38Dl2GDtRW8/Rp6YiSHX/Q= -github.com/multiformats/go-multicodec v0.8.0/go.mod h1:GUC8upxSBE4oG+q3kWZRw/+6yC1BqO550bjhWsJbZlw= +github.com/multiformats/go-multicodec v0.8.1 h1:ycepHwavHafh3grIbR1jIXnKCsFm0fqsfEOsJ8NtKE8= +github.com/multiformats/go-multicodec v0.8.1/go.mod h1:L3QTQvMIaVBkXOXXtVmYE+LI16i14xuaojr/H7Ai54k= github.com/multiformats/go-multihash v0.0.1/go.mod h1:w/5tugSrLEbWqlcgJabL3oHFKTwfvkofsjW2Qa1ct4U= github.com/multiformats/go-multihash v0.0.5/go.mod h1:lt/HCbqlQwlPBz7lv0sQCdtfcMtlJvakRUn/0Ual8po= github.com/multiformats/go-multihash v0.0.8/go.mod h1:YSLudS+Pi8NHE7o6tb3D8vrpKa63epEDmG8nTduyAew= @@ -1378,15 +1378,15 @@ github.com/onsi/ginkgo v1.12.0/go.mod h1:oUhWkIvk5aDxtKvDDuw8gItl8pKl42LzjC9KZE0 github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= -github.com/onsi/ginkgo/v2 v2.5.1 h1:auzK7OI497k6x4OvWq+TKAcpcSAlod0doAH72oIN0Jw= -github.com/onsi/ginkgo/v2 v2.5.1/go.mod h1:63DOGlLAH8+REH8jUGdL3YpCpu7JODesutUjdENfUAc= +github.com/onsi/ginkgo/v2 v2.9.2 h1:BA2GMJOtfGAfagzYtrAlufIP0lq6QERkFmHLMLPwFSU= +github.com/onsi/ginkgo/v2 v2.9.2/go.mod h1:WHcJJG2dIlcCqVfBAwUCrJxSPFb6v4azBwgxeMeDuts= github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.9.0/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= -github.com/onsi/gomega v1.24.0 h1:+0glovB9Jd6z3VR+ScSwQqXVTIfJcGA9UBM8yzQxhqg= +github.com/onsi/gomega v1.27.4 h1:Z2AnStgsdSayCMDiCU42qIz+HLqEPcgiOCXjAU/w+8E= github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= github.com/open-rpc/meta-schema v0.0.0-20201029221707-1b72ef2ea333 h1:CznVS40zms0Dj5he4ERo+fRPtO0qxUk8lA8Xu3ddet0= github.com/open-rpc/meta-schema v0.0.0-20201029221707-1b72ef2ea333/go.mod h1:Ag6rSXkHIckQmjFBCweJEEt1mrTPBv8b9W4aU/NQWfI= @@ -1443,7 +1443,6 @@ github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3O github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= github.com/prometheus/client_golang v1.10.0/go.mod h1:WJM3cc3yu7XKBKa/I8WeZm+V3eltZnBwfENSU7mdogU= github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= -github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= github.com/prometheus/client_golang v1.14.0 h1:nJdhIvne2eSX/XRAFV9PcvFFRbrjbcTUj0VP62TMhnw= github.com/prometheus/client_golang v1.14.0/go.mod h1:8vpkKitgIVNcqrRBWh1C4TIUQgYNtG/XQE4E/Zae36Y= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= @@ -1464,9 +1463,8 @@ github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB8 github.com/prometheus/common v0.18.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s= github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= github.com/prometheus/common v0.28.0/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= -github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= -github.com/prometheus/common v0.37.0 h1:ccBbHCgIiT9uSoFY0vX8H3zsNR5eLt17/RQLUvn8pXE= -github.com/prometheus/common v0.37.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA= +github.com/prometheus/common v0.42.0 h1:EKsfXEYo4JpWMHH5cg+KOUWeuJSov1Id8zGR8eeI1YM= +github.com/prometheus/common v0.42.0/go.mod h1:xBwqVerjNdUDjgODMpudtOMwlOwf2SaTr1yjz4b7Zbc= github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= @@ -1476,17 +1474,16 @@ github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsT github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/procfs v0.8.0 h1:ODq8ZFEaYeCaZOJlZZdJA2AbQR98dSHSM1KW/You5mo= -github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4= +github.com/prometheus/procfs v0.9.0 h1:wzCHvIvM5SxWqYvwgVL7yJY8Lz3PKn49KQtpgMYJfhI= +github.com/prometheus/procfs v0.9.0/go.mod h1:+pB4zwohETzFnmlpe6yd2lSc+0/46IYZRB/chUwxUZY= github.com/prometheus/statsd_exporter v0.21.0 h1:hA05Q5RFeIjgwKIYEdFd59xu5Wwaznf33yKI+pyX6T8= github.com/prometheus/statsd_exporter v0.21.0/go.mod h1:rbT83sZq2V+p73lHhPZfMc3MLCHmSHelCh9hSGYNLTQ= github.com/quic-go/qpack v0.4.0 h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo= github.com/quic-go/qpack v0.4.0/go.mod h1:UZVnYIfi5GRk+zI9UMaCPsmZ2xKJP7XBUvVyT1Knj9A= -github.com/quic-go/qtls-go1-19 v0.2.1 h1:aJcKNMkH5ASEJB9FXNeZCyTEIHU1J7MmHyz1Q1TSG1A= -github.com/quic-go/qtls-go1-19 v0.2.1/go.mod h1:ySOI96ew8lnoKPtSqx2BlI5wCpUVPT05RMAlajtnyOI= -github.com/quic-go/qtls-go1-20 v0.1.1 h1:KbChDlg82d3IHqaj2bn6GfKRj84Per2VGf5XV3wSwQk= -github.com/quic-go/qtls-go1-20 v0.1.1/go.mod h1:JKtK6mjbAVcUTN/9jZpvLbGxvdWIKS8uT7EiStoU1SM= +github.com/quic-go/qtls-go1-19 v0.3.2 h1:tFxjCFcTQzK+oMxG6Zcvp4Dq8dx4yD3dDiIiyc86Z5U= +github.com/quic-go/qtls-go1-19 v0.3.2/go.mod h1:ySOI96ew8lnoKPtSqx2BlI5wCpUVPT05RMAlajtnyOI= +github.com/quic-go/qtls-go1-20 v0.2.2 h1:WLOPx6OY/hxtTxKV1Zrq20FtXtDEkeY00CGQm8GEa3E= +github.com/quic-go/qtls-go1-20 v0.2.2/go.mod h1:JKtK6mjbAVcUTN/9jZpvLbGxvdWIKS8uT7EiStoU1SM= github.com/quic-go/quic-go v0.33.0 h1:ItNoTDN/Fm/zBlq769lLJc8ECe9gYaW40veHCCco7y0= github.com/quic-go/quic-go v0.33.0/go.mod h1:YMuhaAV9/jIu0XclDXwZPAsP/2Kgr5yMYhe9oxhhOFA= github.com/quic-go/webtransport-go v0.5.2 h1:GA6Bl6oZY+g/flt00Pnu0XtivSD8vukOu3lYhJjnGEk= @@ -1599,8 +1596,9 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= +github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ= 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= @@ -1734,8 +1732,8 @@ go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= go.opentelemetry.io/otel v0.20.0/go.mod h1:Y3ugLH2oa81t5QO+Lty+zXf8zC9L26ax4Nzoxm/dooo= go.opentelemetry.io/otel v1.2.0/go.mod h1:aT17Fk0Z1Nor9e0uisf98LrntPGMnk4frBO9+dkf69I= -go.opentelemetry.io/otel v1.12.0 h1:IgfC7kqQrRccIKuB7Cl+SRUmsKbEwSGPr0Eu+/ht1SQ= -go.opentelemetry.io/otel v1.12.0/go.mod h1:geaoz0L0r1BEOR81k7/n9W4TCXYCJ7bPO7K374jQHG0= +go.opentelemetry.io/otel v1.14.0 h1:/79Huy8wbf5DnIPhemGB+zEPVwnN6fuQybr/SRXa6hM= +go.opentelemetry.io/otel v1.14.0/go.mod h1:o4buv+dJzx8rohcUeRmWUZhqupFvzWis188WlggnNeU= go.opentelemetry.io/otel/bridge/opencensus v0.33.0 h1:DnSFYr/VxUVwkHL0UoaMcxx74Jugb1HO0B08cYBmi0c= go.opentelemetry.io/otel/bridge/opencensus v0.33.0/go.mod h1:gylOY4P2e7kPYc6T9M8XfQ5+RK4+evGorTOOy+gO4Nc= go.opentelemetry.io/otel/exporters/jaeger v1.2.0 h1:C/5Egj3MJBXRJi22cSl07suqPqtZLnLFmH//OxETUEc= @@ -1752,8 +1750,8 @@ go.opentelemetry.io/otel/sdk/metric v0.33.0 h1:oTqyWfksgKoJmbrs2q7O7ahkJzt+Ipeki go.opentelemetry.io/otel/sdk/metric v0.33.0/go.mod h1:xdypMeA21JBOvjjzDUtD0kzIcHO/SPez+a8HOzJPGp0= go.opentelemetry.io/otel/trace v0.20.0/go.mod h1:6GjCW8zgDjwGHGa6GkyeB8+/5vjT16gUEi0Nf1iBdgw= go.opentelemetry.io/otel/trace v1.2.0/go.mod h1:N5FLswTubnxKxOJHM7XZC074qpeEdLy3CgAVsdMucK0= -go.opentelemetry.io/otel/trace v1.12.0 h1:p28in++7Kd0r2d8gSt931O57fdjUyWxkVbESuILAeUc= -go.opentelemetry.io/otel/trace v1.12.0/go.mod h1:pHlgBynn6s25qJ2szD+Bv+iwKJttjHSI3lUAyf0GNuQ= +go.opentelemetry.io/otel/trace v1.14.0 h1:wp2Mmvj41tDsyAJXiWDWpfNsOiIyd38fy85pyKcFq/M= +go.opentelemetry.io/otel/trace v1.14.0/go.mod h1:8avnQLK+CG77yNLUae4ea2JDQ6iT+gozhnZjy/rw9G8= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= @@ -1762,10 +1760,10 @@ go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ= go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= -go.uber.org/dig v1.15.0 h1:vq3YWr8zRj1eFGC7Gvf907hE0eRjPTZ1d3xHadD6liE= -go.uber.org/dig v1.15.0/go.mod h1:pKHs0wMynzL6brANhB2hLMro+zalv1osARTviTcqHLM= -go.uber.org/fx v1.18.2 h1:bUNI6oShr+OVFQeU8cDNbnN7VFsu+SsjHzUF51V/GAU= -go.uber.org/fx v1.18.2/go.mod h1:g0V1KMQ66zIRk8bLu3Ea5Jt2w/cHlOIp4wdRsgh0JaY= +go.uber.org/dig v1.16.1 h1:+alNIBsl0qfY0j6epRubp/9obgtrObRAc5aD+6jbWY8= +go.uber.org/dig v1.16.1/go.mod h1:557JTAUZT5bUK0SvCwikmLPPtdQhfvLYtO5tJgQSbnk= +go.uber.org/fx v1.19.2 h1:SyFgYQFr1Wl0AYstE8vyYIzP4bFz2URrScjwC4cwUvY= +go.uber.org/fx v1.19.2/go.mod h1:43G1VcqSzbIv77y00p1DRAsyZS8WdzuYdhZXmEUkMyQ= go.uber.org/goleak v1.0.0/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= go.uber.org/goleak v1.1.11-0.20210813005559-691160354723/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= go.uber.org/goleak v1.1.12 h1:gZAh5/EyT/HQwlpkCy6wTpqfH9H8Lz8zbm3dZh+OyzA= @@ -1775,8 +1773,8 @@ go.uber.org/multierr v1.4.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+ go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= go.uber.org/multierr v1.7.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95ak= -go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI= -go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTVQ= +go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= +go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= @@ -1829,8 +1827,8 @@ golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5y golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw= -golang.org/x/crypto v0.5.0 h1:U/0M97KRkSFvyD/3FSmdP5W5swImpNgle/EHFhOsQPE= -golang.org/x/crypto v0.5.0/go.mod h1:NK/OQwhpMQP3MwtdjgLlYHnH9ebylxKWv3e0fK+mkQU= +golang.org/x/crypto v0.7.0 h1:AvwMYaRytfdeVt3u6mLaxYtErKYjxA2OXjJ1HHq6t3A= +golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -1844,8 +1842,8 @@ golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EH golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= golang.org/x/exp v0.0.0-20210615023648-acb5c1269671/go.mod h1:DVyR6MI7P4kEQgvZJSj1fQGrWIi2RzIrfYWycwheUAc= golang.org/x/exp v0.0.0-20210714144626-1041f73d31d8/go.mod h1:DVyR6MI7P4kEQgvZJSj1fQGrWIi2RzIrfYWycwheUAc= -golang.org/x/exp v0.0.0-20230129154200-a960b3787bd2 h1:5sPMf9HJXrvBWIamTw+rTST0bZ3Mho2n1p58M0+W99c= -golang.org/x/exp v0.0.0-20230129154200-a960b3787bd2/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= +golang.org/x/exp v0.0.0-20230321023759-10a507213a29 h1:ooxPy7fPvB4kwsA2h+iBNHkAbp/4JxTSwCmvdjEYmug= +golang.org/x/exp v0.0.0-20230321023759-10a507213a29/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -1872,8 +1870,8 @@ golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.7.0 h1:LapD9S96VoQRhi/GrNTqeBJFrUjs5UHCAtTlgwA5oZA= -golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.10.0 h1:lFO9qtOdlre5W1jxS3r/4szv2/6iXxScdzjoBMXNhYk= +golang.org/x/mod v0.10.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1929,14 +1927,11 @@ golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLd golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210423184538-5f58ad60dda6/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= -golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g= -golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ= +golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -1945,7 +1940,6 @@ golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4Iltr golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= golang.org/x/perf v0.0.0-20180704124530-6e6d33e29852/go.mod h1:JLpeXjPJfIyPr5TlbXLkXWLhP8nz10XfvxElABhCtcw= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -2052,7 +2046,6 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -2062,15 +2055,16 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= -golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU= +golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.5.0 h1:n2a8QNdAb0sZNpU9R1ALUXBbY+w51fCQDN+7EdxNBsY= -golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.6.0 h1:clScbb1cHjoCkyRbWwBEUZ5H/tIFu5TAXIqaZD0Gcjw= +golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -2080,8 +2074,8 @@ golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo= -golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68= +golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -2147,10 +2141,9 @@ golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.3.0 h1:SrNbZl6ECOS1qFzgTdQfWXZM9XBkiA6tkFrH9YSTPHM= -golang.org/x/tools v0.3.0/go.mod h1:/rWhSS2+zyEVwoJf8YAX6L2f0ntZ7Kn/mGgAWcipA5k= +golang.org/x/tools v0.7.0 h1:W4OVu8VVOaIO0yzWMNdepAulS7YfoS3Zabrm8DOXXU4= +golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -2262,8 +2255,8 @@ google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlba google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= -google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= +google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/itests/batch_deal_test.go b/itests/batch_deal_test.go index d1bb40531..68b276a0c 100644 --- a/itests/batch_deal_test.go +++ b/itests/batch_deal_test.go @@ -37,6 +37,8 @@ func TestBatchDealInput(t *testing.T) { run := func(piece, deals, expectSectors int) func(t *testing.T) { return func(t *testing.T) { + t.Logf("batchtest start") + ctx := context.Background() publishPeriod := 10 * time.Second @@ -73,6 +75,8 @@ func TestBatchDealInput(t *testing.T) { err := miner.MarketSetAsk(ctx, big.Zero(), big.Zero(), 200, 128, 32<<30) require.NoError(t, err) + t.Logf("batchtest ask set") + checkNoPadding := func() { sl, err := miner.SectorsListNonGenesis(ctx) require.NoError(t, err) @@ -118,26 +122,27 @@ func TestBatchDealInput(t *testing.T) { }() } + t.Logf("batchtest deals started") + // Wait for maxDealsPerMsg of the deals to be published for i := 0; i < int(maxDealsPerMsg); i++ { <-done } + t.Logf("batchtest deals published") + checkNoPadding() + t.Logf("batchtest no padding") + sl, err := miner.SectorsListNonGenesis(ctx) require.NoError(t, err) require.Equal(t, len(sl), expectSectors) + + t.Logf("batchtest done") } } t.Run("4-p1600B", run(1600, 4, 4)) t.Run("4-p513B", run(513, 4, 2)) - if !testing.Short() { - t.Run("32-p257B", run(257, 32, 8)) - - // fixme: this appears to break data-transfer / markets in some really creative ways - //t.Run("32-p10B", run(10, 32, 2)) - // t.Run("128-p10B", run(10, 128, 8)) - } } diff --git a/itests/deals_partial_retrieval_dm-level_test.go b/itests/deals_partial_retrieval_dm-level_test.go index e3414c191..4e59b163b 100644 --- a/itests/deals_partial_retrieval_dm-level_test.go +++ b/itests/deals_partial_retrieval_dm-level_test.go @@ -9,8 +9,8 @@ import ( "testing" "time" + blocks "github.com/ipfs/go-block-format" "github.com/ipfs/go-cid" - blocks "github.com/ipfs/go-libipfs/blocks" "github.com/ipld/go-car" textselector "github.com/ipld/go-ipld-selector-text-lite" "github.com/stretchr/testify/require" diff --git a/itests/deals_partial_retrieval_test.go b/itests/deals_partial_retrieval_test.go index e2dae9aff..0bbf23da0 100644 --- a/itests/deals_partial_retrieval_test.go +++ b/itests/deals_partial_retrieval_test.go @@ -9,8 +9,8 @@ import ( "testing" "time" + blocks "github.com/ipfs/go-block-format" "github.com/ipfs/go-cid" - blocks "github.com/ipfs/go-libipfs/blocks" "github.com/ipld/go-car" "github.com/stretchr/testify/require" "golang.org/x/xerrors" diff --git a/itests/eth_balance_test.go b/itests/eth_balance_test.go index d5f151227..116587902 100644 --- a/itests/eth_balance_test.go +++ b/itests/eth_balance_test.go @@ -121,15 +121,24 @@ func TestEthBalanceCorrectLookup(t *testing.T) { require.NoError(t, err) require.True(t, ml.Receipt.ExitCode.IsSuccess()) - bal, err := client.EVM().EthGetBalance(ctx, ethAddr, strconv.FormatInt(int64(ml.Height-2), 10)) + execTs, err := client.ChainGetTipSet(ctx, ml.TipSet) + require.NoError(t, err) + + inclTs, err := client.ChainGetTipSet(ctx, execTs.Parents()) + require.NoError(t, err) + + inclTsParents, err := client.ChainGetTipSet(ctx, inclTs.Parents()) + require.NoError(t, err) + + bal, err := client.EVM().EthGetBalance(ctx, ethAddr, strconv.FormatInt(int64(inclTsParents.Height()), 10)) require.NoError(t, err) require.Equal(t, int64(0), bal.Int64()) - bal, err = client.EVM().EthGetBalance(ctx, ethAddr, strconv.FormatInt(int64(ml.Height-1), 10)) + bal, err = client.EVM().EthGetBalance(ctx, ethAddr, strconv.FormatInt(int64(inclTs.Height()), 10)) require.NoError(t, err) require.Equal(t, val, bal.Int64()) - bal, err = client.EVM().EthGetBalance(ctx, ethAddr, strconv.FormatInt(int64(ml.Height), 10)) + bal, err = client.EVM().EthGetBalance(ctx, ethAddr, strconv.FormatInt(int64(execTs.Height()), 10)) require.NoError(t, err) require.Equal(t, val, bal.Int64()) } diff --git a/itests/eth_block_hash_test.go b/itests/eth_block_hash_test.go index db21375c5..b582c84e3 100644 --- a/itests/eth_block_hash_test.go +++ b/itests/eth_block_hash_test.go @@ -24,7 +24,7 @@ import ( func TestEthBlockHashesCorrect_MultiBlockTipset(t *testing.T) { // miner is connected to the first node, and we want to observe the chain // from the second node. - blocktime := 100 * time.Millisecond + blocktime := 250 * time.Millisecond n1, m1, m2, ens := kit.EnsembleOneTwo(t, kit.MockProofs(), kit.ThroughRPC(), @@ -32,14 +32,14 @@ func TestEthBlockHashesCorrect_MultiBlockTipset(t *testing.T) { ens.InterconnectAll().BeginMining(blocktime) ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) - n1.WaitTillChain(ctx, kit.HeightAtLeast(abi.ChainEpoch(25))) + n1.WaitTillChain(ctx, kit.HeightAtLeast(abi.ChainEpoch(5))) defer cancel() var n2 kit.TestFullNode ens.FullNode(&n2, kit.ThroughRPC()).Start().Connect(n2, n1) // find the first tipset where all miners mined a block. - ctx, cancel = context.WithTimeout(context.Background(), 1*time.Minute) + ctx, cancel = context.WithTimeout(context.Background(), 5*time.Minute) n2.WaitTillChain(ctx, kit.BlocksMinedByAll(m1.ActorAddr, m2.ActorAddr)) defer cancel() diff --git a/itests/eth_deploy_test.go b/itests/eth_deploy_test.go index bbdadb1d5..ce4c94a28 100644 --- a/itests/eth_deploy_test.go +++ b/itests/eth_deploy_test.go @@ -29,18 +29,13 @@ import ( // TestDeployment smoke tests the deployment of a contract via the // Ethereum JSON-RPC endpoint, from an EEOA. func TestDeployment(t *testing.T) { - // TODO::FVM @raulk the contract installation and invocation can be lifted into utility methods - // He who writes the second test, shall do that. - // kit.QuietMiningLogs() - - // reasonable blocktime so that the tx sits in the mpool for a bit during the test. - // although this is non-deterministic... - blockTime := 1 * time.Second + blockTime := 100 * time.Millisecond client, _, ens := kit.EnsembleMinimal( t, kit.MockProofs(), kit.ThroughRPC()) - ens.InterconnectAll().BeginMining(blockTime) + + miners := ens.InterconnectAll().BeginMining(blockTime) ctx, cancel := context.WithTimeout(context.Background(), time.Minute) defer cancel() @@ -93,6 +88,11 @@ func TestDeployment(t *testing.T) { pendingFilter, err := client.EthNewPendingTransactionFilter(ctx) require.NoError(t, err) + // Pause so we can test that everything works while the message is in the message pool. + for _, miner := range miners { + miner.Pause() + } + hash := client.EVM().SubmitTransaction(ctx, &tx) mpoolTx, err := client.EthGetTransactionByHash(ctx, &hash) @@ -103,31 +103,40 @@ func TestDeployment(t *testing.T) { require.Equal(t, hash, mpoolTx.Hash) // these fields should be nil because the tx hasn't landed on chain. - // TODO::FVM @raulk We can either skip the assertion if the msg has already - // landed, or pause mining between the embryo creation and this assertion. require.Nil(t, mpoolTx.BlockNumber) require.Nil(t, mpoolTx.BlockHash) require.Nil(t, mpoolTx.TransactionIndex) + // We should be able to get the message CID immediately. + mCid, err := client.EthGetMessageCidByTransactionHash(ctx, &hash) + require.NoError(t, err) + require.NotNil(t, mCid) + + // ... and it should map back to the transaction hash. + mHash, err := client.EthGetTransactionHashByCid(ctx, *mCid) + require.NoError(t, err) + require.NotNil(t, mHash) + require.Equal(t, hash, *mHash) + changes, err := client.EthGetFilterChanges(ctx, pendingFilter) require.NoError(t, err) require.Len(t, changes.Results, 1) require.Equal(t, hash.String(), changes.Results[0]) - var receipt *api.EthTxReceipt - for i := 0; i < 20; i++ { - // TODO::FVM @raulk The right time to exit this loop isn't after - // 20 iterations, but when StateWaitMsg returns -- let's wait on that - // event while continuing to make this assertion - receipt, err = client.EthGetTransactionReceipt(ctx, hash) - if err != nil || receipt == nil { - time.Sleep(500 * time.Millisecond) - continue - } - break + // Unpause mining. + for _, miner := range miners { + miner.Restart() } + + // Wait for the message to land. + _, err = client.StateWaitMsg(ctx, *mCid, 3, api.LookbackNoLimit, false) + require.NoError(t, err) + + // Then lookup the receipt. + receipt, err := client.EthGetTransactionReceipt(ctx, hash) require.NoError(t, err) require.NotNil(t, receipt) + // logs must be an empty array, not a nil value, to avoid tooling compatibility issues require.Empty(t, receipt.Logs) // a correctly formed logs bloom, albeit empty, has 256 zeroes @@ -173,21 +182,16 @@ func TestDeployment(t *testing.T) { require.Nil(t, err) require.True(t, reflect.DeepEqual(block1, block2)) - // should be able to get the block using latest as well - block3, err := client.EthGetBlockByNumber(ctx, "latest", false) - require.Nil(t, err) - require.True(t, reflect.DeepEqual(block2, block3)) - // verify that the block contains full tx objects - block4, err := client.EthGetBlockByHash(ctx, *chainTx.BlockHash, true) + block3, err := client.EthGetBlockByHash(ctx, *chainTx.BlockHash, true) require.Nil(t, err) - require.Equal(t, block4.Hash, *chainTx.BlockHash) - require.Equal(t, block4.Number, *chainTx.BlockNumber) + require.Equal(t, block3.Hash, *chainTx.BlockHash) + require.Equal(t, block3.Number, *chainTx.BlockNumber) // the call went through json-rpc and the response was unmarshaled // into map[string]interface{}, so it has to be converted into ethtypes.EthTx var foundTx *ethtypes.EthTx - for _, obj := range block4.Transactions { + for _, obj := range block3.Transactions { j, err := json.Marshal(obj) require.Nil(t, err) @@ -202,10 +206,10 @@ func TestDeployment(t *testing.T) { require.NotNil(t, foundTx) require.True(t, reflect.DeepEqual(*foundTx, *chainTx)) - // make sure the block got from EthGetBlockByNumber is the same - block5, err := client.EthGetBlockByNumber(ctx, blkNum, true) + // make sure the _full_ block got from EthGetBlockByNumber is the same + block4, err := client.EthGetBlockByNumber(ctx, blkNum, true) require.Nil(t, err) - require.True(t, reflect.DeepEqual(block4, block5)) + require.True(t, reflect.DeepEqual(block3, block4)) // Verify that the deployer is now an account. client.AssertActorType(ctx, deployer, manifest.EthAccountKey) diff --git a/itests/eth_fee_history_test.go b/itests/eth_fee_history_test.go index a792c7f0e..b611efeb1 100644 --- a/itests/eth_fee_history_test.go +++ b/itests/eth_fee_history_test.go @@ -50,19 +50,6 @@ func TestEthFeeHistory(t *testing.T) { ctx, cancel := context.WithTimeout(context.Background(), time.Minute) defer cancel() - heads, err := client.ChainNotify(ctx) - require.NoError(err) - - // Save the full view of the tipsets to calculate the answer when there are null rounds - tsHeights := []int{1} - go func() { - for chg := range heads { - for _, c := range chg { - tsHeights = append(tsHeights, int(c.Val.Height())) - } - } - }() - miner := ens.InterconnectAll().BeginMining(blockTime) client.WaitTillChain(ctx, kit.HeightAtLeast(7)) @@ -89,6 +76,16 @@ func TestEthFeeHistory(t *testing.T) { } }() + currTs, err := client.ChainHead(ctx) + require.NoError(err) + + var tsHeights []int + for currTs.Height() != 0 { + tsHeights = append(tsHeights, int(currTs.Height())) + currTs, err = client.ChainGetTipSet(ctx, currTs.Parents()) + require.NoError(err) + } + sort.Ints(tsHeights) // because of the deferred execution, the last tipset is not executed yet, diff --git a/itests/eth_filter_test.go b/itests/eth_filter_test.go index 1104bec13..62ab5db54 100644 --- a/itests/eth_filter_test.go +++ b/itests/eth_filter_test.go @@ -425,6 +425,11 @@ func TestEthNewFilterDefaultSpec(t *testing.T) { elogs, err := parseEthLogsFromFilterResult(res) require.NoError(err) AssertEthLogs(t, elogs, expected, received) + + // giving a number to fromBlock/toBlock needs to be in hex format, so make sure passing in decimal fails + blockNrInDecimal := "2812200" + _, err = client.EthNewFilter(ctx, ðtypes.EthFilterSpec{FromBlock: &blockNrInDecimal, ToBlock: &blockNrInDecimal}) + require.Error(err, "expected error when fromBlock/toBlock is not in hex format") } func TestEthGetLogsBasic(t *testing.T) { diff --git a/itests/kit/blockminer.go b/itests/kit/blockminer.go index 4cd0cc671..cbe352dd5 100644 --- a/itests/kit/blockminer.go +++ b/itests/kit/blockminer.go @@ -245,7 +245,8 @@ func (bm *BlockMiner) MineBlocksMustPost(ctx context.Context, blocktime time.Dur case ctx.Err() != nil: // context fired. return default: // log error - bm.t.Error(err) + bm.t.Logf("MINEBLOCKS-post loop error: %+v", err) + return } } }() @@ -291,7 +292,8 @@ func (bm *BlockMiner) MineBlocks(ctx context.Context, blocktime time.Duration) { case ctx.Err() != nil: // context fired. return default: // log error - bm.t.Error(err) + bm.t.Logf("MINEBLOCKS loop error: %+v", err) + return } } }() diff --git a/itests/kit/client.go b/itests/kit/client.go index 134b6b1ce..f7e465760 100644 --- a/itests/kit/client.go +++ b/itests/kit/client.go @@ -80,7 +80,7 @@ func RunClientTest(t *testing.T, cmds []*lcli.Command, clientNode *TestFullNode) dealStatus := "" for { // client list-deals - out = clientCLI.RunCmd("client", "list-deals") + out = clientCLI.RunCmd("client", "list-deals", "--show-failed") fmt.Println("list-deals:\n", out) lines := strings.Split(out, "\n") diff --git a/itests/kit/deals.go b/itests/kit/deals.go index 39b7857d7..f4c551526 100644 --- a/itests/kit/deals.go +++ b/itests/kit/deals.go @@ -9,9 +9,9 @@ import ( "testing" "time" + "github.com/ipfs/boxo/files" "github.com/ipfs/go-cid" ipld "github.com/ipfs/go-ipld-format" - "github.com/ipfs/go-libipfs/files" dag "github.com/ipfs/go-merkledag" dstest "github.com/ipfs/go-merkledag/test" unixfile "github.com/ipfs/go-unixfs/file" diff --git a/itests/kit/files.go b/itests/kit/files.go index dbf7d2cd7..063dcf7e0 100644 --- a/itests/kit/files.go +++ b/itests/kit/files.go @@ -9,6 +9,7 @@ import ( "os" "testing" + "github.com/ipfs/boxo/files" "github.com/ipfs/go-blockservice" "github.com/ipfs/go-cid" "github.com/ipfs/go-cidutil" @@ -18,7 +19,6 @@ import ( chunk "github.com/ipfs/go-ipfs-chunker" offline "github.com/ipfs/go-ipfs-exchange-offline" ipldformat "github.com/ipfs/go-ipld-format" - "github.com/ipfs/go-libipfs/files" "github.com/ipfs/go-merkledag" "github.com/ipfs/go-unixfs/importer/balanced" ihelper "github.com/ipfs/go-unixfs/importer/helpers" diff --git a/itests/msgindex_test.go b/itests/msgindex_test.go new file mode 100644 index 000000000..cb5fd85c9 --- /dev/null +++ b/itests/msgindex_test.go @@ -0,0 +1,124 @@ +package itests + +import ( + "context" + "os" + "sync" + "testing" + "time" + + "github.com/stretchr/testify/require" + + "github.com/filecoin-project/go-state-types/big" + "github.com/filecoin-project/go-state-types/exitcode" + + lapi "github.com/filecoin-project/lotus/api" + "github.com/filecoin-project/lotus/chain/index" + "github.com/filecoin-project/lotus/chain/store" + "github.com/filecoin-project/lotus/chain/types" + "github.com/filecoin-project/lotus/itests/kit" + "github.com/filecoin-project/lotus/node" +) + +func init() { + // adjust those to make tests snappy + index.CoalesceMinDelay = time.Millisecond + index.CoalesceMaxDelay = 10 * time.Millisecond + index.CoalesceMergeInterval = time.Millisecond +} + +func testMsgIndex( + t *testing.T, + name string, + run func(t *testing.T, makeMsgIndex func(cs *store.ChainStore) (index.MsgIndex, error)), + check func(t *testing.T, i int, msgIndex index.MsgIndex), +) { + + // create the message indices in the test context + var mx sync.Mutex + var tmpDirs []string + var msgIndices []index.MsgIndex + + t.Cleanup(func() { + for _, msgIndex := range msgIndices { + _ = msgIndex.Close() + } + + for _, tmp := range tmpDirs { + _ = os.RemoveAll(tmp) + } + }) + + makeMsgIndex := func(cs *store.ChainStore) (index.MsgIndex, error) { + var err error + tmp := t.TempDir() + msgIndex, err := index.NewMsgIndex(context.Background(), tmp, cs) + if err == nil { + mx.Lock() + tmpDirs = append(tmpDirs, tmp) + msgIndices = append(msgIndices, msgIndex) + mx.Unlock() + } + return msgIndex, err + } + + t.Run(name, func(t *testing.T) { + run(t, makeMsgIndex) + }) + + if len(msgIndices) == 0 { + t.Fatal("no message indices") + } + + for i, msgIndex := range msgIndices { + check(t, i, msgIndex) + } +} + +func checkNonEmptyMsgIndex(t *testing.T, _ int, msgIndex index.MsgIndex) { + mi, ok := msgIndex.(interface{ CountMessages() (int64, error) }) + if !ok { + t.Fatal("index does not allow counting") + } + count, err := mi.CountMessages() + require.NoError(t, err) + require.NotEqual(t, count, 0) +} + +func TestMsgIndex(t *testing.T) { + testMsgIndex(t, "testSearchMsg", testSearchMsgWithIndex, checkNonEmptyMsgIndex) +} + +func testSearchMsgWithIndex(t *testing.T, makeMsgIndex func(cs *store.ChainStore) (index.MsgIndex, error)) { + // copy of apiSuite.testSearchMsgWith; needs to be copied or else CI is angry, tests are built individually there + ctx := context.Background() + + full, _, ens := kit.EnsembleMinimal(t, kit.ConstructorOpts(node.Override(new(index.MsgIndex), makeMsgIndex))) + + senderAddr, err := full.WalletDefaultAddress(ctx) + require.NoError(t, err) + + msg := &types.Message{ + From: senderAddr, + To: senderAddr, + Value: big.Zero(), + } + + ens.BeginMining(100 * time.Millisecond) + + sm, err := full.MpoolPushMessage(ctx, msg, nil) + require.NoError(t, err) + + //stm: @CHAIN_STATE_WAIT_MSG_001 + res, err := full.StateWaitMsg(ctx, sm.Cid(), 1, lapi.LookbackNoLimit, true) + require.NoError(t, err) + + require.Equal(t, exitcode.Ok, res.Receipt.ExitCode, "message not successful") + + //stm: @CHAIN_STATE_SEARCH_MSG_001 + searchRes, err := full.StateSearchMsg(ctx, types.EmptyTSK, sm.Cid(), lapi.LookbackNoLimit, true) + require.NoError(t, err) + require.NotNil(t, searchRes) + + require.Equalf(t, res.TipSet, searchRes.TipSet, "search ts: %s, different from wait ts: %s", searchRes.TipSet, res.TipSet) +} diff --git a/itests/paych_api_test.go b/itests/paych_api_test.go index ea7e73dbc..f8ecb5377 100644 --- a/itests/paych_api_test.go +++ b/itests/paych_api_test.go @@ -10,7 +10,6 @@ import ( cbor "github.com/ipfs/go-ipld-cbor" "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" paychtypes "github.com/filecoin-project/go-state-types/builtin/v8/paych" @@ -19,7 +18,6 @@ import ( "github.com/filecoin-project/lotus/blockstore" "github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/chain/actors/adt" - "github.com/filecoin-project/lotus/chain/actors/builtin" "github.com/filecoin-project/lotus/chain/actors/builtin/paych" "github.com/filecoin-project/lotus/chain/actors/policy" "github.com/filecoin-project/lotus/chain/events" @@ -52,8 +50,7 @@ func TestPaymentChannelsAPI(t *testing.T) { Miner(&miner, &paymentCreator, kit.WithAllSubsystems()). Start(). InterconnectAll() - bms := ens.BeginMiningMustPost(blockTime) - bm := bms[0] + ens.BeginMiningMustPost(blockTime) waitRecvInSync := func() { // paymentCreator is the block miner, in some cases paymentReceiver may fall behind, so we wait for it to catch up @@ -197,7 +194,12 @@ func TestPaymentChannelsAPI(t *testing.T) { require.Errorf(t, err, "Expected shortfall error of %d", excessAmt) // wait for the settlement period to pass before collecting - waitForBlocks(ctx, t, bm, paymentReceiver, receiverAddr, policy.PaychSettleDelay) + head, err := paymentReceiver.ChainHead(ctx) + require.NoError(t, err) + + settleHeight := head.Height() + policy.PaychSettleDelay + 5 + paymentReceiver.WaitTillChain(ctx, kit.HeightAtLeast(settleHeight)) + paymentCreator.WaitTillChain(ctx, kit.HeightAtLeast(settleHeight)) creatorPreCollectBalance, err := paymentCreator.WalletBalance(ctx, createrAddr) require.NoError(t, err) @@ -226,31 +228,6 @@ func TestPaymentChannelsAPI(t *testing.T) { require.EqualValues(t, abi.NewTokenAmount(expectedRefund), delta, "did not send correct funds from creator: expected %d, got %d", expectedRefund, delta) } -func waitForBlocks(ctx context.Context, t *testing.T, bm *kit.BlockMiner, paymentReceiver kit.TestFullNode, receiverAddr address.Address, count int) { - // We need to add null blocks in batches, if we add too many the chain can't sync - batchSize := 60 - for i := 0; i < count; i += batchSize { - size := batchSize - if i > count { - size = count - i - } - - // Add a batch of null blocks to advance the chain quicker through finalities. - bm.InjectNulls(abi.ChainEpoch(size - 1)) - - // Add a real block - m, err := paymentReceiver.MpoolPushMessage(ctx, &types.Message{ - To: builtin.BurntFundsActorAddr, - From: receiverAddr, - Value: types.NewInt(0), - }, nil) - require.NoError(t, err) - - _, err = paymentReceiver.StateWaitMsg(ctx, m.Cid(), 1, api.LookbackNoLimit, true) - require.NoError(t, err) - } -} - func waitForMessage(ctx context.Context, t *testing.T, paymentCreator kit.TestFullNode, msgCid cid.Cid, duration time.Duration, desc string) *api.MsgLookup { ctx, cancel := context.WithTimeout(ctx, duration) defer cancel() diff --git a/itests/sealing_resources_test.go b/itests/sealing_resources_test.go new file mode 100644 index 000000000..85779fd88 --- /dev/null +++ b/itests/sealing_resources_test.go @@ -0,0 +1,64 @@ +package itests + +import ( + "context" + "os" + "testing" + "time" + + "github.com/stretchr/testify/require" + + "github.com/filecoin-project/lotus/itests/kit" + "github.com/filecoin-project/lotus/storage/sealer/storiface" +) + +// Regression check for a fix introduced in https://github.com/filecoin-project/lotus/pull/10633 +func TestPledgeMaxConcurrentGet(t *testing.T) { + require.NoError(t, os.Setenv("GET_2K_MAX_CONCURRENT", "1")) + t.Cleanup(func() { + require.NoError(t, os.Unsetenv("GET_2K_MAX_CONCURRENT")) + }) + + kit.QuietMiningLogs() + + blockTime := 50 * time.Millisecond + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + _, miner, ens := kit.EnsembleMinimal(t, kit.NoStorage()) // no mock proofs + ens.InterconnectAll().BeginMiningMustPost(blockTime) + + // separate sealed and storage paths so that finalize move needs to happen + miner.AddStorage(ctx, t, func(meta *storiface.LocalStorageMeta) { + meta.CanSeal = true + }) + miner.AddStorage(ctx, t, func(meta *storiface.LocalStorageMeta) { + meta.CanStore = true + }) + + // NOTE: This test only repros the issue when Fetch tasks take ~10s, there's + // no great way to do that in a non-horribly-hacky way + + /* The horribly hacky way: + + diff --git a/storage/sealer/sched_worker.go b/storage/sealer/sched_worker.go + index 35acd755d..76faec859 100644 + --- a/storage/sealer/sched_worker.go + +++ b/storage/sealer/sched_worker.go + @@ -513,6 +513,10 @@ func (sw *schedWorker) startProcessingTask(req *WorkerRequest) error { + tw.start() + err = <-werr + + + if req.TaskType == sealtasks.TTFetch { + + time.Sleep(10 * time.Second) + + } + + + select { + case req.ret <- workerResponse{err: err}: + case <-req.Ctx.Done(): + + */ + + miner.PledgeSectors(ctx, 3, 0, nil) +} diff --git a/itests/sector_finalize_early_test.go b/itests/sector_finalize_early_test.go index fb7d9d94d..87e1384a2 100644 --- a/itests/sector_finalize_early_test.go +++ b/itests/sector_finalize_early_test.go @@ -30,7 +30,8 @@ func TestDealsWithFinalizeEarly(t *testing.T) { var blockTime = 50 * time.Millisecond - client, miner, ens := kit.EnsembleMinimal(t, kit.ThroughRPC(), kit.MutateSealingConfig(func(sc *config.SealingConfig) { sc.FinalizeEarly = true })) // no mock proofs. + // We use two miners so that in case the actively tested miner misses PoSt, we still have a blockchain + client, miner, _, ens := kit.EnsembleOneTwo(t, kit.ThroughRPC(), kit.MutateSealingConfig(func(sc *config.SealingConfig) { sc.FinalizeEarly = true })) // no mock proofs. ens.InterconnectAll().BeginMining(blockTime) dh := kit.NewDealHarness(t, client, miner, miner) diff --git a/itests/sector_import_full_test.go b/itests/sector_import_full_test.go index 35fc3e623..e4ec5e141 100644 --- a/itests/sector_import_full_test.go +++ b/itests/sector_import_full_test.go @@ -65,7 +65,8 @@ func TestSectorImport(t *testing.T) { //////// // Start a miner node - client, miner, ens := kit.EnsembleMinimal(t, kit.ThroughRPC()) + // We use two miners so that in case the actively tested miner misses PoSt, we still have a blockchain + client, miner, _, ens := kit.EnsembleOneTwo(t, kit.ThroughRPC()) ens.InterconnectAll().BeginMining(blockTime) ctx := context.Background() diff --git a/itests/sector_import_simple_test.go b/itests/sector_import_simple_test.go index 0cf7e098b..f34438694 100644 --- a/itests/sector_import_simple_test.go +++ b/itests/sector_import_simple_test.go @@ -39,7 +39,9 @@ func TestSectorImportAfterPC2(t *testing.T) { //////// // Start a miner node - client, miner, ens := kit.EnsembleMinimal(t, kit.ThroughRPC()) + // We use two miners so that in case the actively tested miner misses PoSt, we still have a blockchain + client, miner, _, ens := kit.EnsembleOneTwo(t, kit.ThroughRPC()) + ens.InterconnectAll().BeginMining(blockTime) ctx := context.Background() diff --git a/lib/httpreader/resumable.go b/lib/httpreader/resumable.go new file mode 100644 index 000000000..dacefeccc --- /dev/null +++ b/lib/httpreader/resumable.go @@ -0,0 +1,122 @@ +package httpreader + +import ( + "context" + "fmt" + "io" + "net/http" + "strconv" + + logging "github.com/ipfs/go-log/v2" + "go.uber.org/multierr" + "golang.org/x/xerrors" +) + +var log = logging.Logger("httpreader") + +type ResumableReader struct { + ctx context.Context + initialURL string + finalURL *string + position int64 + contentLength int64 + client *http.Client + reader io.ReadCloser +} + +func NewResumableReader(ctx context.Context, url string) (*ResumableReader, error) { + finalURL := "" + + client := &http.Client{ + CheckRedirect: func(req *http.Request, via []*http.Request) error { + finalURL = req.URL.String() + if len(via) >= 10 { + return xerrors.New("stopped after 10 redirects") + } + return nil + }, + } + + r := &ResumableReader{ + ctx: ctx, + initialURL: url, + finalURL: &finalURL, + position: 0, + client: client, + } + + req, err := http.NewRequestWithContext(ctx, "GET", url, nil) + if err != nil { + return nil, err + } + + resp, err := r.client.Do(req) + if err != nil { + return nil, err + } + + if resp.StatusCode != http.StatusOK { + return nil, fmt.Errorf("failed to fetch resource, status code: %d", resp.StatusCode) + } + + contentLength, err := strconv.ParseInt(resp.Header.Get("Content-Length"), 10, 64) + if err != nil { + if err = resp.Body.Close(); err != nil { + err = multierr.Append(err, err) + } + return nil, err + } + + r.contentLength = contentLength + r.reader = resp.Body + + return r, nil +} + +func (r *ResumableReader) ContentLength() int64 { + return r.contentLength +} + +func (r *ResumableReader) Read(p []byte) (n int, err error) { + for { + if r.reader == nil { + reqURL := r.initialURL + if *r.finalURL != "" { + reqURL = *r.finalURL + } + + req, err := http.NewRequestWithContext(r.ctx, "GET", reqURL, nil) + if err != nil { + return 0, err + } + req.Header.Set("Range", fmt.Sprintf("bytes=%d-", r.position)) + resp, err := r.client.Do(req) + if err != nil { + return 0, err + } + + if resp.StatusCode != http.StatusOK && resp.StatusCode != http.StatusPartialContent { + return 0, fmt.Errorf("non-resumable status code: %d", resp.StatusCode) + } + r.reader = resp.Body + } + + n, err = r.reader.Read(p) + r.position += int64(n) + + if err == io.EOF || err == io.ErrUnexpectedEOF { + if r.position == r.contentLength { + if err := r.reader.Close(); err != nil { + log.Warnf("error closing reader: %+v", err) + } + return n, io.EOF + } + if err := r.reader.Close(); err != nil { + log.Warnf("error closing reader: %+v", err) + } + r.reader = nil + } else { + return n, err + } + } +} diff --git a/lib/unixfs/filestore.go b/lib/unixfs/filestore.go index 0a0b61c4c..678520b27 100644 --- a/lib/unixfs/filestore.go +++ b/lib/unixfs/filestore.go @@ -6,6 +6,7 @@ import ( "io" "os" + "github.com/ipfs/boxo/files" "github.com/ipfs/go-blockservice" "github.com/ipfs/go-cid" "github.com/ipfs/go-cidutil" @@ -13,7 +14,6 @@ import ( chunker "github.com/ipfs/go-ipfs-chunker" offline "github.com/ipfs/go-ipfs-exchange-offline" ipld "github.com/ipfs/go-ipld-format" - "github.com/ipfs/go-libipfs/files" "github.com/ipfs/go-merkledag" "github.com/ipfs/go-unixfs/importer/balanced" ihelper "github.com/ipfs/go-unixfs/importer/helpers" diff --git a/lib/unixfs/filestore_test.go b/lib/unixfs/filestore_test.go index 67d380701..2f5e2d939 100644 --- a/lib/unixfs/filestore_test.go +++ b/lib/unixfs/filestore_test.go @@ -9,10 +9,10 @@ import ( "strings" "testing" + "github.com/ipfs/boxo/files" "github.com/ipfs/go-blockservice" "github.com/ipfs/go-cid" offline "github.com/ipfs/go-ipfs-exchange-offline" - "github.com/ipfs/go-libipfs/files" "github.com/ipfs/go-merkledag" unixfile "github.com/ipfs/go-unixfs/file" carv2 "github.com/ipld/go-car/v2" diff --git a/markets/dagstore/blockstore.go b/markets/dagstore/blockstore.go index 593204ec8..317cb08b9 100644 --- a/markets/dagstore/blockstore.go +++ b/markets/dagstore/blockstore.go @@ -4,9 +4,9 @@ import ( "context" "io" + blocks "github.com/ipfs/go-block-format" "github.com/ipfs/go-cid" bstore "github.com/ipfs/go-ipfs-blockstore" - blocks "github.com/ipfs/go-libipfs/blocks" "golang.org/x/xerrors" "github.com/filecoin-project/dagstore" diff --git a/markets/storageadapter/api.go b/markets/storageadapter/api.go index 3105f2261..b93ffdfbb 100644 --- a/markets/storageadapter/api.go +++ b/markets/storageadapter/api.go @@ -3,9 +3,9 @@ package storageadapter import ( "context" + blocks "github.com/ipfs/go-block-format" "github.com/ipfs/go-cid" cbor "github.com/ipfs/go-ipld-cbor" - blocks "github.com/ipfs/go-libipfs/blocks" "golang.org/x/xerrors" "github.com/filecoin-project/go-address" diff --git a/markets/storageadapter/ondealsectorcommitted_test.go b/markets/storageadapter/ondealsectorcommitted_test.go index 592c22db7..1d7519ff9 100644 --- a/markets/storageadapter/ondealsectorcommitted_test.go +++ b/markets/storageadapter/ondealsectorcommitted_test.go @@ -10,8 +10,8 @@ import ( "testing" "time" + blocks "github.com/ipfs/go-block-format" "github.com/ipfs/go-cid" - blocks "github.com/ipfs/go-libipfs/blocks" "github.com/stretchr/testify/require" "golang.org/x/xerrors" diff --git a/metrics/metrics.go b/metrics/metrics.go index ca638ac27..13627a663 100644 --- a/metrics/metrics.go +++ b/metrics/metrics.go @@ -58,6 +58,9 @@ var ( ProtocolID, _ = tag.NewKey("proto") Direction, _ = tag.NewKey("direction") UseFD, _ = tag.NewKey("use_fd") + + // vm execution + ExecutionLane, _ = tag.NewKey("lane") ) // Measures @@ -121,6 +124,8 @@ var ( VMApplyFlush = stats.Float64("vm/applyblocks_flush", "Time spent flushing vm state", stats.UnitMilliseconds) VMSends = stats.Int64("vm/sends", "Counter for sends processed by the VM", stats.UnitDimensionless) VMApplied = stats.Int64("vm/applied", "Counter for messages (including internal messages) processed by the VM", stats.UnitDimensionless) + VMExecutionWaiting = stats.Int64("vm/execution_waiting", "Counter for VM executions waiting to be assigned to a lane", stats.UnitDimensionless) + VMExecutionRunning = stats.Int64("vm/execution_running", "Counter for running VM executions", stats.UnitDimensionless) // miner WorkerCallsStarted = stats.Int64("sealing/worker_calls_started", "Counter of started worker tasks", stats.UnitDimensionless) @@ -363,6 +368,16 @@ var ( Measure: VMApplied, Aggregation: view.LastValue(), } + VMExecutionWaitingView = &view.View{ + Measure: VMExecutionWaiting, + Aggregation: view.Sum(), + TagKeys: []tag.Key{ExecutionLane}, + } + VMExecutionRunningView = &view.View{ + Measure: VMExecutionRunning, + Aggregation: view.Sum(), + TagKeys: []tag.Key{ExecutionLane}, + } // miner WorkerCallsStartedView = &view.View{ @@ -727,6 +742,8 @@ var ChainNodeViews = append([]*view.View{ VMApplyFlushView, VMSendsView, VMAppliedView, + VMExecutionWaitingView, + VMExecutionRunningView, }, DefaultViews...) var MinerNodeViews = append([]*view.View{ diff --git a/node/builder.go b/node/builder.go index 76c93cbc6..75162f5ea 100644 --- a/node/builder.go +++ b/node/builder.go @@ -24,6 +24,7 @@ import ( "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/chain/beacon" + "github.com/filecoin-project/lotus/chain/index" "github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/journal" "github.com/filecoin-project/lotus/journal/alerting" @@ -390,6 +391,7 @@ func Test() Option { Unset(new(*peermgr.PeerMgr)), Override(new(beacon.Schedule), testing.RandomBeacon), Override(new(*storageadapter.DealPublisher), storageadapter.NewDealPublisher(nil, storageadapter.PublishMsgConfig{})), + Override(new(index.MsgIndex), modules.DummyMsgIndex), ) } diff --git a/node/builder_chain.go b/node/builder_chain.go index d334d782e..fcdb26162 100644 --- a/node/builder_chain.go +++ b/node/builder_chain.go @@ -20,6 +20,7 @@ import ( "github.com/filecoin-project/lotus/chain/events" "github.com/filecoin-project/lotus/chain/exchange" "github.com/filecoin-project/lotus/chain/gen/slashfilter" + "github.com/filecoin-project/lotus/chain/index" "github.com/filecoin-project/lotus/chain/market" "github.com/filecoin-project/lotus/chain/messagepool" "github.com/filecoin-project/lotus/chain/messagesigner" @@ -275,6 +276,10 @@ func ConfigFullNode(c interface{}) Option { Override(new(full.EthEventAPI), &full.EthModuleDummy{}), ), ), + + // enable message index for full node when configured by the user, otherwise use dummy. + If(cfg.Index.EnableMsgIndex, Override(new(index.MsgIndex), modules.MsgIndex)), + If(!cfg.Index.EnableMsgIndex, Override(new(index.MsgIndex), modules.DummyMsgIndex)), ) } diff --git a/node/config/def.go b/node/config/def.go index 4020e4ca6..703288288 100644 --- a/node/config/def.go +++ b/node/config/def.go @@ -151,9 +151,10 @@ func DefaultStorageMiner() *StorageMiner { BatchPreCommitAboveBaseFee: types.FIL(types.BigMul(types.PicoFil, types.NewInt(320))), // 0.32 nFIL AggregateAboveBaseFee: types.FIL(types.BigMul(types.PicoFil, types.NewInt(320))), // 0.32 nFIL - TerminateBatchMin: 1, - TerminateBatchMax: 100, - TerminateBatchWait: Duration(5 * time.Minute), + TerminateBatchMin: 1, + TerminateBatchMax: 100, + TerminateBatchWait: Duration(5 * time.Minute), + MaxSectorProveCommitsSubmittedPerEpoch: 20, }, Proving: ProvingConfig{ @@ -229,7 +230,7 @@ func DefaultStorageMiner() *StorageMiner { EnableMining: true, EnableSealing: true, EnableSectorStorage: true, - EnableMarkets: true, + EnableMarkets: false, }, Fees: MinerFeeConfig{ diff --git a/node/config/doc_gen.go b/node/config/doc_gen.go index c62084708..26a254bad 100644 --- a/node/config/doc_gen.go +++ b/node/config/doc_gen.go @@ -461,6 +461,20 @@ Set to 0 to keep all mappings`, Comment: ``, }, + { + Name: "Index", + Type: "IndexConfig", + + Comment: ``, + }, + }, + "IndexConfig": []DocField{ + { + Name: "EnableMsgIndex", + Type: "bool", + + Comment: `EnableMsgIndex enables indexing of messages on chain.`, + }, }, "IndexProviderConfig": []DocField{ { @@ -1229,6 +1243,16 @@ sending precommit messages to the chain individually`, Comment: `network BaseFee below which to stop doing commit aggregation, instead submitting proofs to the chain individually`, + }, + { + Name: "MaxSectorProveCommitsSubmittedPerEpoch", + Type: "uint64", + + Comment: `When submitting several sector prove commit messages simultaneously, this option allows you to +stagger the number of prove commits submitted per epoch +This is done because gas estimates for ProveCommits are non deterministic and increasing as a large +number of sectors get committed within the same epoch resulting in occasionally failed msgs. +Submitting a smaller number of prove commits per epoch would reduce the possibility of failed msgs`, }, { Name: "TerminateBatchMax", diff --git a/node/config/types.go b/node/config/types.go index 5b952d35e..5cbd21bf3 100644 --- a/node/config/types.go +++ b/node/config/types.go @@ -28,6 +28,7 @@ type FullNode struct { Chainstore Chainstore Cluster UserRaftConfig Fevm FevmConfig + Index IndexConfig } // // Common @@ -421,6 +422,13 @@ type SealingConfig struct { // submitting proofs to the chain individually AggregateAboveBaseFee types.FIL + // When submitting several sector prove commit messages simultaneously, this option allows you to + // stagger the number of prove commits submitted per epoch + // This is done because gas estimates for ProveCommits are non deterministic and increasing as a large + // number of sectors get committed within the same epoch resulting in occasionally failed msgs. + // Submitting a smaller number of prove commits per epoch would reduce the possibility of failed msgs + MaxSectorProveCommitsSubmittedPerEpoch uint64 + TerminateBatchMax uint64 TerminateBatchMin uint64 TerminateBatchWait Duration @@ -726,3 +734,8 @@ type Events struct { // Set a timeout for subscription clients // Set upper bound on index size } + +type IndexConfig struct { + // EnableMsgIndex enables indexing of messages on chain. + EnableMsgIndex bool +} diff --git a/node/impl/client/client.go b/node/impl/client/client.go index e45d537e2..860b50d84 100644 --- a/node/impl/client/client.go +++ b/node/impl/client/client.go @@ -13,12 +13,12 @@ import ( "sync" "time" + "github.com/ipfs/boxo/files" "github.com/ipfs/go-blockservice" "github.com/ipfs/go-cid" bstore "github.com/ipfs/go-ipfs-blockstore" offline "github.com/ipfs/go-ipfs-exchange-offline" format "github.com/ipfs/go-ipld-format" - "github.com/ipfs/go-libipfs/files" logging "github.com/ipfs/go-log/v2" "github.com/ipfs/go-merkledag" unixfile "github.com/ipfs/go-unixfs/file" diff --git a/node/impl/client/client_test.go b/node/impl/client/client_test.go index 032fef55a..3feaac096 100644 --- a/node/impl/client/client_test.go +++ b/node/impl/client/client_test.go @@ -10,13 +10,13 @@ import ( "strings" "testing" + "github.com/ipfs/boxo/files" "github.com/ipfs/go-blockservice" "github.com/ipfs/go-cid" "github.com/ipfs/go-datastore" dssync "github.com/ipfs/go-datastore/sync" blockstore "github.com/ipfs/go-ipfs-blockstore" offline "github.com/ipfs/go-ipfs-exchange-offline" - "github.com/ipfs/go-libipfs/files" "github.com/ipfs/go-merkledag" unixfile "github.com/ipfs/go-unixfs/file" "github.com/ipld/go-car" diff --git a/node/impl/full/chain.go b/node/impl/full/chain.go index d0f36ce48..addca2b97 100644 --- a/node/impl/full/chain.go +++ b/node/impl/full/chain.go @@ -15,12 +15,12 @@ import ( "sync" "time" + blocks "github.com/ipfs/go-block-format" "github.com/ipfs/go-blockservice" "github.com/ipfs/go-cid" offline "github.com/ipfs/go-ipfs-exchange-offline" cbor "github.com/ipfs/go-ipld-cbor" ipld "github.com/ipfs/go-ipld-format" - blocks "github.com/ipfs/go-libipfs/blocks" logging "github.com/ipfs/go-log/v2" "github.com/ipfs/go-merkledag" mh "github.com/multiformats/go-multihash" diff --git a/node/impl/full/dummy.go b/node/impl/full/dummy.go index a4a125d6f..918e84d10 100644 --- a/node/impl/full/dummy.go +++ b/node/impl/full/dummy.go @@ -102,6 +102,10 @@ func (e *EthModuleDummy) EthChainId(ctx context.Context) (ethtypes.EthUint64, er return 0, ErrModuleDisabled } +func (e *EthModuleDummy) EthSyncing(ctx context.Context) (ethtypes.EthSyncingResult, error) { + return ethtypes.EthSyncingResult{}, ErrModuleDisabled +} + func (e *EthModuleDummy) NetVersion(ctx context.Context) (string, error) { return "", ErrModuleDisabled } diff --git a/node/impl/full/eth.go b/node/impl/full/eth.go index e2c39ed87..2f1b30fad 100644 --- a/node/impl/full/eth.go +++ b/node/impl/full/eth.go @@ -9,6 +9,7 @@ import ( "os" "sort" "strconv" + "strings" "sync" "time" @@ -66,6 +67,7 @@ type EthModuleAPI interface { EthGetBalance(ctx context.Context, address ethtypes.EthAddress, blkParam string) (ethtypes.EthBigInt, error) EthFeeHistory(ctx context.Context, p jsonrpc.RawParams) (ethtypes.EthFeeHistory, error) EthChainId(ctx context.Context) (ethtypes.EthUint64, error) + EthSyncing(ctx context.Context) (ethtypes.EthSyncingResult, error) NetVersion(ctx context.Context) (string, error) NetListening(ctx context.Context) (bool, error) EthProtocolVersion(ctx context.Context) (ethtypes.EthUint64, error) @@ -132,6 +134,7 @@ type EthModule struct { ChainAPI MpoolAPI StateAPI + SyncAPI } var _ EthModuleAPI = (*EthModule)(nil) @@ -387,7 +390,7 @@ func (a *EthModule) EthGetTransactionCount(ctx context.Context, sender ethtypes. ts, err := a.parseBlkParam(ctx, blkParam, false) if err != nil { - return ethtypes.EthUint64(0), xerrors.Errorf("cannot parse block param: %s", blkParam) + return ethtypes.EthUint64(0), xerrors.Errorf("failed to process block param: %s; %w", blkParam, err) } // First, handle the case where the "sender" is an EVM actor. @@ -475,7 +478,7 @@ func (a *EthModule) EthGetCode(ctx context.Context, ethAddr ethtypes.EthAddress, ts, err := a.parseBlkParam(ctx, blkParam, false) if err != nil { - return nil, xerrors.Errorf("cannot parse block param: %s", blkParam) + return nil, xerrors.Errorf("failed to process block param: %s; %w", blkParam, err) } // StateManager.Call will panic if there is no parent @@ -554,7 +557,7 @@ func (a *EthModule) EthGetCode(ctx context.Context, ethAddr ethtypes.EthAddress, func (a *EthModule) EthGetStorageAt(ctx context.Context, ethAddr ethtypes.EthAddress, position ethtypes.EthBytes, blkParam string) (ethtypes.EthBytes, error) { ts, err := a.parseBlkParam(ctx, blkParam, false) if err != nil { - return nil, xerrors.Errorf("cannot parse block param: %s", blkParam) + return nil, xerrors.Errorf("failed to process block param: %s; %w", blkParam, err) } l := len(position) @@ -650,7 +653,7 @@ func (a *EthModule) EthGetBalance(ctx context.Context, address ethtypes.EthAddre ts, err := a.parseBlkParam(ctx, blkParam, false) if err != nil { - return ethtypes.EthBigInt{}, xerrors.Errorf("cannot parse block param: %s", blkParam) + return ethtypes.EthBigInt{}, xerrors.Errorf("failed to process block param: %s; %w", blkParam, err) } st, _, err := a.StateManager.TipSetState(ctx, ts) @@ -672,6 +675,42 @@ func (a *EthModule) EthChainId(ctx context.Context) (ethtypes.EthUint64, error) return ethtypes.EthUint64(build.Eip155ChainId), nil } +func (a *EthModule) EthSyncing(ctx context.Context) (ethtypes.EthSyncingResult, error) { + state, err := a.SyncAPI.SyncState(ctx) + if err != nil { + return ethtypes.EthSyncingResult{}, fmt.Errorf("failed calling SyncState: %w", err) + } + + if len(state.ActiveSyncs) == 0 { + return ethtypes.EthSyncingResult{}, errors.New("no active syncs, try again") + } + + working := -1 + for i, ss := range state.ActiveSyncs { + if ss.Stage == api.StageIdle { + continue + } + working = i + } + if working == -1 { + working = len(state.ActiveSyncs) - 1 + } + + ss := state.ActiveSyncs[working] + if ss.Base == nil || ss.Target == nil { + return ethtypes.EthSyncingResult{}, errors.New("missing syncing information, try again") + } + + res := ethtypes.EthSyncingResult{ + DoneSync: ss.Stage == api.StageSyncComplete, + CurrentBlock: ethtypes.EthUint64(ss.Height), + StartingBlock: ethtypes.EthUint64(ss.Base.Height()), + HighestBlock: ethtypes.EthUint64(ss.Target.Height()), + } + + return res, nil +} + func (a *EthModule) EthFeeHistory(ctx context.Context, p jsonrpc.RawParams) (ethtypes.EthFeeHistory, error) { params, err := jsonrpc.DecodeParams[ethtypes.EthFeeHistoryParams](p) if err != nil { @@ -1081,7 +1120,7 @@ func (a *EthModule) EthCall(ctx context.Context, tx ethtypes.EthCall, blkParam s ts, err := a.parseBlkParam(ctx, blkParam, false) if err != nil { - return nil, xerrors.Errorf("cannot parse block param: %s", blkParam) + return nil, xerrors.Errorf("failed to process block param: %s; %w", blkParam, err) } invokeResult, err := a.applyMessage(ctx, msg, ts.Key()) @@ -1170,7 +1209,7 @@ func (e *EthEvent) installEthFilterSpec(ctx context.Context, filterSpec *ethtype return nil, xerrors.Errorf("must not specify block hash and from/to block") } - // TODO: derive a tipset hash from eth hash - might need to push this down into the EventFilterManager + tipsetCid = filterSpec.BlockHash.ToCid() } else { if filterSpec.FromBlock == nil || *filterSpec.FromBlock == "latest" { ts := e.Chain.GetHeaviestTipSet() @@ -1180,6 +1219,9 @@ func (e *EthEvent) installEthFilterSpec(ctx context.Context, filterSpec *ethtype } else if *filterSpec.FromBlock == "pending" { return nil, api.ErrNotSupported } else { + if !strings.HasPrefix(*filterSpec.FromBlock, "0x") { + return nil, xerrors.Errorf("FromBlock is not a hex") + } epoch, err := ethtypes.EthUint64FromHex(*filterSpec.FromBlock) if err != nil { return nil, xerrors.Errorf("invalid epoch") @@ -1195,6 +1237,9 @@ func (e *EthEvent) installEthFilterSpec(ctx context.Context, filterSpec *ethtype } else if *filterSpec.ToBlock == "pending" { return nil, api.ErrNotSupported } else { + if !strings.HasPrefix(*filterSpec.ToBlock, "0x") { + return nil, xerrors.Errorf("ToBlock is not a hex") + } epoch, err := ethtypes.EthUint64FromHex(*filterSpec.ToBlock) if err != nil { return nil, xerrors.Errorf("invalid epoch") diff --git a/node/impl/full/eth_test.go b/node/impl/full/eth_test.go index 87c0852fb..63dbb447e 100644 --- a/node/impl/full/eth_test.go +++ b/node/impl/full/eth_test.go @@ -114,7 +114,7 @@ func TestReward(t *testing.T) { {maxFeePerGas: big.NewInt(600), maxPriorityFeePerGas: big.NewInt(500), answer: big.NewInt(500)}, {maxFeePerGas: big.NewInt(600), maxPriorityFeePerGas: big.NewInt(600), answer: big.NewInt(500)}, {maxFeePerGas: big.NewInt(600), maxPriorityFeePerGas: big.NewInt(1000), answer: big.NewInt(500)}, - {maxFeePerGas: big.NewInt(50), maxPriorityFeePerGas: big.NewInt(200), answer: big.NewInt(-50)}, + {maxFeePerGas: big.NewInt(50), maxPriorityFeePerGas: big.NewInt(200), answer: big.NewInt(0)}, } for _, tc := range testcases { msg := &types.Message{GasFeeCap: tc.maxFeePerGas, GasPremium: tc.maxPriorityFeePerGas} diff --git a/node/impl/full/gas.go b/node/impl/full/gas.go index 4ff943f36..c5b22354a 100644 --- a/node/impl/full/gas.go +++ b/node/impl/full/gas.go @@ -378,18 +378,6 @@ func gasEstimateGasLimit( } ret = (ret * int64(transitionalMulti*1024)) >> 10 - // Special case for PaymentChannel collect, which is deleting actor - // We ignore errors in this special case since they CAN occur, - // and we just want to detect existing payment channel actors - st, err := smgr.ParentState(ts) - if err == nil { - act, err := st.GetActor(msg.To) - if err == nil && lbuiltin.IsPaymentChannelActor(act.Code) && msgIn.Method == builtin.MethodsPaych.Collect { - // add the refunded gas for DestroyActor back into the gas used - ret += 76e3 - } - } - return ret, nil } @@ -400,6 +388,11 @@ func (m *GasModule) GasEstimateMessageGas(ctx context.Context, msg *types.Messag return nil, err } msg.GasLimit = int64(float64(gasLimit) * m.Mpool.GetConfig().GasLimitOverestimation) + + // Gas overestimation can cause us to exceed the block gas limit, cap it. + if msg.GasLimit > build.BlockGasLimit { + msg.GasLimit = build.BlockGasLimit + } } if msg.GasPremium == types.EmptyInt || types.BigCmp(msg.GasPremium, types.NewInt(0)) == 0 { diff --git a/node/impl/net/net.go b/node/impl/net/net.go index 271c56ea5..5341092ce 100644 --- a/node/impl/net/net.go +++ b/node/impl/net/net.go @@ -16,6 +16,7 @@ import ( "github.com/libp2p/go-libp2p/p2p/net/swarm" "github.com/libp2p/go-libp2p/p2p/protocol/ping" ma "github.com/multiformats/go-multiaddr" + manet "github.com/multiformats/go-multiaddr/net" "go.uber.org/fx" "golang.org/x/xerrors" @@ -134,7 +135,7 @@ func (a *NetAPI) NetFindPeer(ctx context.Context, p peer.ID) (peer.AddrInfo, err return a.Router.FindPeer(ctx, p) } -func (a *NetAPI) NetAutoNatStatus(ctx context.Context) (i api.NatInfo, err error) { +func (a *NetAPI) NetAutoNatStatus(context.Context) (i api.NatInfo, err error) { autonat := a.RawHost.(*basichost.BasicHost).GetAutoNat() if autonat == nil { @@ -143,18 +144,18 @@ func (a *NetAPI) NetAutoNatStatus(ctx context.Context) (i api.NatInfo, err error }, nil } - var maddr string + var addrs []string if autonat.Status() == network.ReachabilityPublic { - pa, err := autonat.PublicAddr() - if err != nil { - return api.NatInfo{}, err + for _, addr := range a.Host.Addrs() { + if manet.IsPublicAddr(addr) { + addrs = append(addrs, addr.String()) + } } - maddr = pa.String() } return api.NatInfo{ Reachability: autonat.Status(), - PublicAddr: maddr, + PublicAddrs: addrs, }, nil } diff --git a/node/impl/storminer.go b/node/impl/storminer.go index 44ef7ee6a..e4fa41c78 100644 --- a/node/impl/storminer.go +++ b/node/impl/storminer.go @@ -254,6 +254,33 @@ func (sm *StorageMinerAPI) SectorsUnsealPiece(ctx context.Context, sector storif return sm.StorageMgr.SectorsUnsealPiece(ctx, sector, offset, size, randomness, commd) } +func (sm *StorageMinerAPI) SectorUnseal(ctx context.Context, sectorNum abi.SectorNumber) error { + + status, err := sm.Miner.SectorsStatus(ctx, sectorNum, false) + if err != nil { + return err + } + + minerAddr, err := sm.ActorAddress(ctx) + if err != nil { + return err + } + minerID, err := address.IDFromAddress(minerAddr) + if err != nil { + return err + } + + sector := storiface.SectorRef{ + ID: abi.SectorID{ + Miner: abi.ActorID(minerID), + Number: sectorNum, + }, + ProofType: status.SealProof, + } + + return sm.StorageMgr.SectorsUnsealPiece(ctx, sector, storiface.UnpaddedByteIndex(0), abi.UnpaddedPieceSize(0), status.Ticket.Value, status.CommD) +} + // List all staged sectors func (sm *StorageMinerAPI) SectorsList(context.Context) ([]abi.SectorNumber, error) { sectors, err := sm.Miner.ListSectors() diff --git a/node/modules/actorevent.go b/node/modules/actorevent.go index 55a79a59a..68a6990ce 100644 --- a/node/modules/actorevent.go +++ b/node/modules/actorevent.go @@ -130,7 +130,7 @@ func EthEventAPI(cfg config.FevmConfig) func(helpers.MetricsCtx, repo.LockedRepo lc.Append(fx.Hook{ OnStart: func(context.Context) error { - ev, err := events.NewEventsWithConfidence(ctx, &evapi, ChainHeadConfidence) + ev, err := events.NewEvents(ctx, &evapi) if err != nil { return err } diff --git a/node/modules/chain.go b/node/modules/chain.go index 0c3bad2c7..f91defc43 100644 --- a/node/modules/chain.go +++ b/node/modules/chain.go @@ -4,9 +4,9 @@ import ( "context" "time" + "github.com/ipfs/boxo/bitswap" + "github.com/ipfs/boxo/bitswap/network" "github.com/ipfs/go-blockservice" - "github.com/ipfs/go-libipfs/bitswap" - "github.com/ipfs/go-libipfs/bitswap/network" "github.com/libp2p/go-libp2p/core/host" "github.com/libp2p/go-libp2p/core/routing" "go.uber.org/fx" @@ -21,6 +21,7 @@ import ( "github.com/filecoin-project/lotus/chain/consensus/filcns" "github.com/filecoin-project/lotus/chain/exchange" "github.com/filecoin-project/lotus/chain/gen/slashfilter" + "github.com/filecoin-project/lotus/chain/index" "github.com/filecoin-project/lotus/chain/messagepool" "github.com/filecoin-project/lotus/chain/stmgr" "github.com/filecoin-project/lotus/chain/store" @@ -69,7 +70,7 @@ func MessagePool(lc fx.Lifecycle, mctx helpers.MetricsCtx, us stmgr.UpgradeSched return mp.Close() }, }) - protector.AddProtector(mp.TryForEachPendingMessage) + protector.AddProtector(mp.ForEachPendingMessage) return mp, nil } @@ -123,7 +124,7 @@ func NetworkName(mctx helpers.MetricsCtx, ctx := helpers.LifecycleCtx(mctx, lc) - sm, err := stmgr.NewStateManager(cs, tsexec, syscalls, us, nil, nil) + sm, err := stmgr.NewStateManager(cs, tsexec, syscalls, us, nil, nil, index.DummyMsgIndex) if err != nil { return "", err } diff --git a/node/modules/ethmodule.go b/node/modules/ethmodule.go index eba6c54d1..f7f4508c4 100644 --- a/node/modules/ethmodule.go +++ b/node/modules/ethmodule.go @@ -18,8 +18,8 @@ import ( "github.com/filecoin-project/lotus/node/repo" ) -func EthModuleAPI(cfg config.FevmConfig) func(helpers.MetricsCtx, repo.LockedRepo, fx.Lifecycle, *store.ChainStore, *stmgr.StateManager, EventAPI, *messagepool.MessagePool, full.StateAPI, full.ChainAPI, full.MpoolAPI) (*full.EthModule, error) { - return func(mctx helpers.MetricsCtx, r repo.LockedRepo, lc fx.Lifecycle, cs *store.ChainStore, sm *stmgr.StateManager, evapi EventAPI, mp *messagepool.MessagePool, stateapi full.StateAPI, chainapi full.ChainAPI, mpoolapi full.MpoolAPI) (*full.EthModule, error) { +func EthModuleAPI(cfg config.FevmConfig) func(helpers.MetricsCtx, repo.LockedRepo, fx.Lifecycle, *store.ChainStore, *stmgr.StateManager, EventAPI, *messagepool.MessagePool, full.StateAPI, full.ChainAPI, full.MpoolAPI, full.SyncAPI) (*full.EthModule, error) { + return func(mctx helpers.MetricsCtx, r repo.LockedRepo, lc fx.Lifecycle, cs *store.ChainStore, sm *stmgr.StateManager, evapi EventAPI, mp *messagepool.MessagePool, stateapi full.StateAPI, chainapi full.ChainAPI, mpoolapi full.MpoolAPI, syncapi full.SyncAPI) (*full.EthModule, error) { sqlitePath, err := r.SqlitePath() if err != nil { return nil, err @@ -54,12 +54,10 @@ func EthModuleAPI(cfg config.FevmConfig) func(helpers.MetricsCtx, repo.LockedRep } } - const ChainHeadConfidence = 1 - ctx := helpers.LifecycleCtx(mctx, lc) lc.Append(fx.Hook{ OnStart: func(context.Context) error { - ev, err := events.NewEventsWithConfidence(ctx, &evapi, ChainHeadConfidence) + ev, err := events.NewEvents(ctx, &evapi) if err != nil { return err } @@ -86,6 +84,7 @@ func EthModuleAPI(cfg config.FevmConfig) func(helpers.MetricsCtx, repo.LockedRep ChainAPI: chainapi, MpoolAPI: mpoolapi, StateAPI: stateapi, + SyncAPI: syncapi, EthTxHashManager: ðTxHashManager, }, nil diff --git a/node/modules/msgindex.go b/node/modules/msgindex.go new file mode 100644 index 000000000..72e9840ba --- /dev/null +++ b/node/modules/msgindex.go @@ -0,0 +1,36 @@ +package modules + +import ( + "context" + + "go.uber.org/fx" + + "github.com/filecoin-project/lotus/chain/index" + "github.com/filecoin-project/lotus/chain/store" + "github.com/filecoin-project/lotus/node/modules/helpers" + "github.com/filecoin-project/lotus/node/repo" +) + +func MsgIndex(lc fx.Lifecycle, mctx helpers.MetricsCtx, cs *store.ChainStore, r repo.LockedRepo) (index.MsgIndex, error) { + basePath, err := r.SqlitePath() + if err != nil { + return nil, err + } + + msgIndex, err := index.NewMsgIndex(helpers.LifecycleCtx(mctx, lc), basePath, cs) + if err != nil { + return nil, err + } + + lc.Append(fx.Hook{ + OnStop: func(_ context.Context) error { + return msgIndex.Close() + }, + }) + + return msgIndex, nil +} + +func DummyMsgIndex() index.MsgIndex { + return index.DummyMsgIndex +} diff --git a/node/modules/stmgr.go b/node/modules/stmgr.go index b8f6f4776..f3eaee219 100644 --- a/node/modules/stmgr.go +++ b/node/modules/stmgr.go @@ -4,14 +4,15 @@ import ( "go.uber.org/fx" "github.com/filecoin-project/lotus/chain/beacon" + "github.com/filecoin-project/lotus/chain/index" "github.com/filecoin-project/lotus/chain/stmgr" "github.com/filecoin-project/lotus/chain/store" "github.com/filecoin-project/lotus/chain/vm" "github.com/filecoin-project/lotus/node/modules/dtypes" ) -func StateManager(lc fx.Lifecycle, cs *store.ChainStore, exec stmgr.Executor, sys vm.SyscallBuilder, us stmgr.UpgradeSchedule, b beacon.Schedule, metadataDs dtypes.MetadataDS) (*stmgr.StateManager, error) { - sm, err := stmgr.NewStateManager(cs, exec, sys, us, b, metadataDs) +func StateManager(lc fx.Lifecycle, cs *store.ChainStore, exec stmgr.Executor, sys vm.SyscallBuilder, us stmgr.UpgradeSchedule, b beacon.Schedule, metadataDs dtypes.MetadataDS, msgIndex index.MsgIndex) (*stmgr.StateManager, error) { + sm, err := stmgr.NewStateManager(cs, exec, sys, us, b, metadataDs, msgIndex) if err != nil { return nil, err } diff --git a/node/modules/storageminer.go b/node/modules/storageminer.go index 4e4e2dde1..a4147d83d 100644 --- a/node/modules/storageminer.go +++ b/node/modules/storageminer.go @@ -1014,9 +1014,10 @@ func NewSetSealConfigFunc(r repo.LockedRepo) (dtypes.SetSealingConfigFunc, error AggregateAboveBaseFee: types.FIL(cfg.AggregateAboveBaseFee), BatchPreCommitAboveBaseFee: types.FIL(cfg.BatchPreCommitAboveBaseFee), - TerminateBatchMax: cfg.TerminateBatchMax, - TerminateBatchMin: cfg.TerminateBatchMin, - TerminateBatchWait: config.Duration(cfg.TerminateBatchWait), + TerminateBatchMax: cfg.TerminateBatchMax, + TerminateBatchMin: cfg.TerminateBatchMin, + TerminateBatchWait: config.Duration(cfg.TerminateBatchWait), + MaxSectorProveCommitsSubmittedPerEpoch: cfg.MaxSectorProveCommitsSubmittedPerEpoch, } c.SetSealingConfig(newCfg) }) @@ -1051,13 +1052,14 @@ func ToSealingConfig(dealmakingCfg config.DealmakingConfig, sealingCfg config.Se PreCommitBatchWait: time.Duration(sealingCfg.PreCommitBatchWait), PreCommitBatchSlack: time.Duration(sealingCfg.PreCommitBatchSlack), - AggregateCommits: sealingCfg.AggregateCommits, - MinCommitBatch: sealingCfg.MinCommitBatch, - MaxCommitBatch: sealingCfg.MaxCommitBatch, - CommitBatchWait: time.Duration(sealingCfg.CommitBatchWait), - CommitBatchSlack: time.Duration(sealingCfg.CommitBatchSlack), - AggregateAboveBaseFee: types.BigInt(sealingCfg.AggregateAboveBaseFee), - BatchPreCommitAboveBaseFee: types.BigInt(sealingCfg.BatchPreCommitAboveBaseFee), + AggregateCommits: sealingCfg.AggregateCommits, + MinCommitBatch: sealingCfg.MinCommitBatch, + MaxCommitBatch: sealingCfg.MaxCommitBatch, + CommitBatchWait: time.Duration(sealingCfg.CommitBatchWait), + CommitBatchSlack: time.Duration(sealingCfg.CommitBatchSlack), + AggregateAboveBaseFee: types.BigInt(sealingCfg.AggregateAboveBaseFee), + BatchPreCommitAboveBaseFee: types.BigInt(sealingCfg.BatchPreCommitAboveBaseFee), + MaxSectorProveCommitsSubmittedPerEpoch: sealingCfg.MaxSectorProveCommitsSubmittedPerEpoch, TerminateBatchMax: sealingCfg.TerminateBatchMax, TerminateBatchMin: sealingCfg.TerminateBatchMin, diff --git a/node/modules/tracer/tracer.go b/node/modules/tracer/tracer.go index 0d0a156d9..b9b56e80c 100644 --- a/node/modules/tracer/tracer.go +++ b/node/modules/tracer/tracer.go @@ -31,7 +31,7 @@ const ( type LotusTraceEvent struct { Type pubsub_pb.TraceEvent_Type `json:"type,omitempty"` - PeerID string `json:"peerID,omitempty"` + PeerID []byte `json:"peerID,omitempty"` Timestamp *int64 `json:"timestamp,omitempty"` PeerScore TraceEventPeerScore `json:"peerScore,omitempty"` SourceAuth string `json:"sourceAuth,omitempty"` @@ -46,7 +46,7 @@ type TopicScore struct { } type TraceEventPeerScore struct { - PeerID string `json:"peerID"` + PeerID []byte `json:"peerID"` Score float64 `json:"score"` AppSpecificScore float64 `json:"appSpecificScore"` IPColocationFactor float64 `json:"ipColocationFactor"` @@ -77,11 +77,11 @@ func (lt *lotusTracer) PeerScores(scores map[peer.ID]*pubsub.PeerScoreSnapshot) evt := &LotusTraceEvent{ Type: *TraceEventPeerScores.Enum(), - PeerID: lt.pid.Pretty(), Timestamp: &now, + PeerID: []byte(lt.pid), SourceAuth: lt.sa, PeerScore: TraceEventPeerScore{ - PeerID: pid.Pretty(), + PeerID: []byte(pid), Score: score.Score, AppSpecificScore: score.AppSpecificScore, IPColocationFactor: score.IPColocationFactor, @@ -104,7 +104,6 @@ func (lt *lotusTracer) TraceLotusEvent(evt *LotusTraceEvent) { log.Errorf("error while transporting peer scores: %s", err) } } - } func (lt *lotusTracer) Trace(evt *pubsub_pb.TraceEvent) { diff --git a/node/modules/tracer/tracer_test.go b/node/modules/tracer/tracer_test.go index 7ade67861..f0d7b2c0b 100644 --- a/node/modules/tracer/tracer_test.go +++ b/node/modules/tracer/tracer_test.go @@ -30,16 +30,15 @@ func (ttt *testTracerTransport) Transport(evt TracerTransportEvent) error { } func TestTracer_PeerScores(t *testing.T) { - testTransport := NewTestTraceTransport(t, func(t *testing.T, evt TracerTransportEvent) { - require.Equal(t, peerIDA.Pretty(), evt.lotusTraceEvent.PeerID) + require.Equal(t, []byte(peerIDA), evt.lotusTraceEvent.PeerID) require.Equal(t, "source-auth-token-test", evt.lotusTraceEvent.SourceAuth) require.Equal(t, float64(32), evt.lotusTraceEvent.PeerScore.Score) n := time.Now().UnixNano() require.LessOrEqual(t, *evt.lotusTraceEvent.Timestamp, n) - require.Equal(t, peerIDA.Pretty(), evt.lotusTraceEvent.PeerScore.PeerID) + require.Equal(t, []byte(peerIDA), evt.lotusTraceEvent.PeerScore.PeerID) require.Equal(t, 1, len(evt.lotusTraceEvent.PeerScore.Topics)) topic := evt.lotusTraceEvent.PeerScore.Topics[0] @@ -85,7 +84,6 @@ func TestTracer_PubSubTrace(t *testing.T) { PeerID: []byte(peerIDA), Timestamp: &n, }) - } func TestTracer_MultipleTransports(t *testing.T) { diff --git a/storage/paths/localstorage_cached.go b/storage/paths/localstorage_cached.go index af43d1696..31e2528ff 100644 --- a/storage/paths/localstorage_cached.go +++ b/storage/paths/localstorage_cached.go @@ -1,6 +1,7 @@ package paths import ( + "os" "sync" "time" @@ -103,7 +104,9 @@ func (c *cachedLocalStorage) DiskUsage(path string) (int64, error) { go func() { du, err := c.base.DiskUsage(path) if err != nil { - log.Errorw("error getting disk usage", "path", path, "error", err) + if !os.IsNotExist(err) { + log.Errorw("error getting disk usage", "path", path, "error", err) + } } resCh <- diskUsageResult{ usage: du, diff --git a/storage/paths/remote.go b/storage/paths/remote.go index 852936153..06bd39bf1 100644 --- a/storage/paths/remote.go +++ b/storage/paths/remote.go @@ -236,6 +236,10 @@ func (r *Remote) acquireFromRemote(ctx context.Context, s abi.SectorID, fileType err = r.fetchThrottled(ctx, url, tempDest) if err != nil { merr = multierror.Append(merr, xerrors.Errorf("fetch error %s (storage %s) -> %s: %w", url, info.ID, tempDest, err)) + // fetching failed, remove temp file + if rerr := os.RemoveAll(tempDest); rerr != nil { + merr = multierror.Append(merr, xerrors.Errorf("removing temp dest (post-err cleanup): %w", rerr)) + } continue } diff --git a/storage/pipeline/commit_batch.go b/storage/pipeline/commit_batch.go index b5651c5fb..9948b5432 100644 --- a/storage/pipeline/commit_batch.go +++ b/storage/pipeline/commit_batch.go @@ -37,6 +37,7 @@ var aggFeeDen = big.NewInt(100) type CommitBatcherApi interface { MpoolPushMessage(context.Context, *types.Message, *api.MessageSendSpec) (*types.SignedMessage, error) + GasEstimateMessageGas(context.Context, *types.Message, *api.MessageSendSpec, types.TipSetKey) (*types.Message, error) StateMinerInfo(context.Context, address.Address, types.TipSetKey) (api.MinerInfo, error) ChainHead(ctx context.Context) (*types.TipSet, error) @@ -234,7 +235,11 @@ func (b *CommitBatcher) maybeStartBatch(notif bool) ([]sealiface.CommitBatchRes, if individual { res, err = b.processIndividually(cfg) } else { - res, err = b.processBatch(cfg) + var sectors []abi.SectorNumber + for sn := range b.todo { + sectors = append(sectors, sn) + } + res, err = b.processBatch(cfg, sectors) } if err != nil { @@ -264,13 +269,13 @@ func (b *CommitBatcher) maybeStartBatch(notif bool) ([]sealiface.CommitBatchRes, return res, nil } -func (b *CommitBatcher) processBatch(cfg sealiface.Config) ([]sealiface.CommitBatchRes, error) { +func (b *CommitBatcher) processBatch(cfg sealiface.Config, sectors []abi.SectorNumber) ([]sealiface.CommitBatchRes, error) { ts, err := b.api.ChainHead(b.mctx) if err != nil { return nil, err } - total := len(b.todo) + total := len(sectors) res := sealiface.CommitBatchRes{ FailedSectors: map[abi.SectorNumber]string{}, @@ -284,24 +289,19 @@ func (b *CommitBatcher) processBatch(cfg sealiface.Config) ([]sealiface.CommitBa infos := make([]proof.AggregateSealVerifyInfo, 0, total) collateral := big.Zero() - for id, p := range b.todo { - if len(infos) >= cfg.MaxCommitBatch { - log.Infow("commit batch full") - break - } + for _, sector := range sectors { + res.Sectors = append(res.Sectors, sector) - res.Sectors = append(res.Sectors, id) - - sc, err := b.getSectorCollateral(id, ts.Key()) + sc, err := b.getSectorCollateral(sector, ts.Key()) if err != nil { - res.FailedSectors[id] = err.Error() + res.FailedSectors[sector] = err.Error() continue } collateral = big.Add(collateral, sc) - params.SectorNumbers.Set(uint64(id)) - infos = append(infos, p.Info) + params.SectorNumbers.Set(uint64(sector)) + infos = append(infos, b.todo[sector].Info) } if len(infos) == 0 { @@ -318,17 +318,20 @@ func (b *CommitBatcher) processBatch(cfg sealiface.Config) ([]sealiface.CommitBa mid, err := address.IDFromAddress(b.maddr) if err != nil { + res.Error = err.Error() return []sealiface.CommitBatchRes{res}, xerrors.Errorf("getting miner id: %w", err) } nv, err := b.api.StateNetworkVersion(b.mctx, ts.Key()) if err != nil { + res.Error = err.Error() log.Errorf("getting network version: %s", err) return []sealiface.CommitBatchRes{res}, xerrors.Errorf("getting network version: %s", err) } arp, err := b.aggregateProofType(nv) if err != nil { + res.Error = err.Error() return []sealiface.CommitBatchRes{res}, xerrors.Errorf("getting aggregate proof type: %w", err) } @@ -339,16 +342,19 @@ func (b *CommitBatcher) processBatch(cfg sealiface.Config) ([]sealiface.CommitBa Infos: infos, }, proofs) if err != nil { + res.Error = err.Error() return []sealiface.CommitBatchRes{res}, xerrors.Errorf("aggregating proofs: %w", err) } enc := new(bytes.Buffer) if err := params.MarshalCBOR(enc); err != nil { + res.Error = err.Error() return []sealiface.CommitBatchRes{res}, xerrors.Errorf("couldn't serialize ProveCommitAggregateParams: %w", err) } mi, err := b.api.StateMinerInfo(b.mctx, b.maddr, types.EmptyTSK) if err != nil { + res.Error = err.Error() return []sealiface.CommitBatchRes{res}, xerrors.Errorf("couldn't get miner info: %w", err) } @@ -356,6 +362,7 @@ func (b *CommitBatcher) processBatch(cfg sealiface.Config) ([]sealiface.CommitBa aggFeeRaw, err := policy.AggregateProveCommitNetworkFee(nv, len(infos), ts.MinTicketBlock().ParentBaseFee) if err != nil { + res.Error = err.Error() log.Errorf("getting aggregate commit network fee: %s", err) return []sealiface.CommitBatchRes{res}, xerrors.Errorf("getting aggregate commit network fee: %s", err) } @@ -365,6 +372,7 @@ func (b *CommitBatcher) processBatch(cfg sealiface.Config) ([]sealiface.CommitBa needFunds := big.Add(collateral, aggFee) needFunds, err = collateralSendAmount(b.mctx, b.api, b.maddr, cfg, needFunds) if err != nil { + res.Error = err.Error() return []sealiface.CommitBatchRes{res}, err } @@ -372,9 +380,28 @@ func (b *CommitBatcher) processBatch(cfg sealiface.Config) ([]sealiface.CommitBa from, _, err := b.addrSel.AddressFor(b.mctx, b.api, mi, api.CommitAddr, goodFunds, needFunds) if err != nil { + res.Error = err.Error() return []sealiface.CommitBatchRes{res}, xerrors.Errorf("no good address found: %w", err) } + _, err = simulateMsgGas(b.mctx, b.api, from, b.maddr, builtin.MethodsMiner.ProveCommitAggregate, needFunds, maxFee, enc.Bytes()) + + if err != nil && (!api.ErrorIsIn(err, []error{&api.ErrOutOfGas{}}) || len(sectors) < miner.MinAggregatedSectors*2) { + log.Errorf("simulating CommitBatch message failed: %s", err) + res.Error = err.Error() + return []sealiface.CommitBatchRes{res}, xerrors.Errorf("simulating CommitBatch message failed: %w", err) + } + + // If we're out of gas, split the batch in half and evaluate again + if api.ErrorIsIn(err, []error{&api.ErrOutOfGas{}}) { + log.Warnf("CommitAggregate message ran out of gas, splitting batch in half and trying again (sectors: %d)", len(sectors)) + mid := len(sectors) / 2 + ret0, _ := b.processBatch(cfg, sectors[:mid]) + ret1, _ := b.processBatch(cfg, sectors[mid:]) + + return append(ret0, ret1...), nil + } + mcid, err := sendMsg(b.mctx, b.api, from, b.maddr, builtin.MethodsMiner.ProveCommitAggregate, needFunds, maxFee, enc.Bytes()) if err != nil { return []sealiface.CommitBatchRes{res}, xerrors.Errorf("sending message failed: %w", err) @@ -388,6 +415,7 @@ func (b *CommitBatcher) processBatch(cfg sealiface.Config) ([]sealiface.CommitBa } func (b *CommitBatcher) processIndividually(cfg sealiface.Config) ([]sealiface.CommitBatchRes, error) { + mi, err := b.api.StateMinerInfo(b.mctx, b.maddr, types.EmptyTSK) if err != nil { return nil, xerrors.Errorf("couldn't get miner info: %w", err) @@ -414,12 +442,31 @@ func (b *CommitBatcher) processIndividually(cfg sealiface.Config) ([]sealiface.C var res []sealiface.CommitBatchRes + sectorsProcessed := 0 + for sn, info := range b.todo { r := sealiface.CommitBatchRes{ Sectors: []abi.SectorNumber{sn}, FailedSectors: map[abi.SectorNumber]string{}, } + if cfg.MaxSectorProveCommitsSubmittedPerEpoch > 0 && + uint64(sectorsProcessed) >= cfg.MaxSectorProveCommitsSubmittedPerEpoch { + + tmp := ts + for tmp.Height() <= ts.Height() { + tmp, err = b.api.ChainHead(b.mctx) + if err != nil { + log.Errorf("getting chain head: %+v", err) + return nil, err + } + time.Sleep(3 * time.Second) + } + + sectorsProcessed = 0 + ts = tmp + } + mcid, err := b.processSingle(cfg, mi, &avail, sn, info, ts.Key()) if err != nil { log.Errorf("process single error: %+v", err) // todo: return to user @@ -429,6 +476,8 @@ func (b *CommitBatcher) processIndividually(cfg sealiface.Config) ([]sealiface.C } res = append(res, r) + + sectorsProcessed++ } return res, nil diff --git a/storage/pipeline/commit_batch_test.go b/storage/pipeline/commit_batch_test.go index a8948edcf..15c2100cb 100644 --- a/storage/pipeline/commit_batch_test.go +++ b/storage/pipeline/commit_batch_test.go @@ -201,7 +201,7 @@ func TestCommitBatcher(t *testing.T) { if batch { s.EXPECT().StateNetworkVersion(gomock.Any(), gomock.Any()).Return(network.Version13, nil) - //s.EXPECT().ChainBaseFee(gomock.Any(), gomock.Any()).Return(basefee, nil) + s.EXPECT().GasEstimateMessageGas(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(&types.Message{GasLimit: 100000}, nil) } s.EXPECT().MpoolPushMessage(gomock.Any(), funMatcher(func(i interface{}) bool { @@ -224,6 +224,48 @@ func TestCommitBatcher(t *testing.T) { } } + expectProcessBatch := func(expect []abi.SectorNumber, aboveBalancer, failOnePCI bool, gasOverLimit bool) action { + return func(t *testing.T, s *mocks.MockCommitBatcherApi, pcb *pipeline.CommitBatcher) promise { + s.EXPECT().StateMinerInfo(gomock.Any(), gomock.Any(), gomock.Any()).Return(api.MinerInfo{Owner: t0123, Worker: t0123}, nil) + + ti := len(expect) + batch := false + if ti >= minBatch { + batch = true + ti = 1 + } + + if !aboveBalancer { + batch = false + ti = len(expect) + } + + pciC := len(expect) + if failOnePCI { + s.EXPECT().StateSectorPreCommitInfo(gomock.Any(), gomock.Any(), abi.SectorNumber(1), gomock.Any()).Return(nil, nil).Times(1) // not found + pciC = len(expect) - 1 + if !batch { + ti-- + } + } + s.EXPECT().StateSectorPreCommitInfo(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(&minertypes.SectorPreCommitOnChainInfo{ + PreCommitDeposit: big.Zero(), + }, nil).Times(pciC) + s.EXPECT().StateMinerInitialPledgeCollateral(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(big.Zero(), nil).Times(pciC) + + if batch { + s.EXPECT().StateNetworkVersion(gomock.Any(), gomock.Any()).Return(network.Version18, nil) + if gasOverLimit { + s.EXPECT().GasEstimateMessageGas(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(nil, &api.ErrOutOfGas{}) + } else { + s.EXPECT().GasEstimateMessageGas(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(&types.Message{GasLimit: 100000}, nil) + } + + } + return nil + } + } + flush := func(expect []abi.SectorNumber, aboveBalancer, failOnePCI bool) action { return func(t *testing.T, s *mocks.MockCommitBatcherApi, pcb *pipeline.CommitBatcher) promise { _ = expectSend(expect, aboveBalancer, failOnePCI)(t, s, pcb) @@ -309,6 +351,14 @@ func TestCommitBatcher(t *testing.T) { addSectors(getSectors(maxBatch), true), }, }, + "addMax-aboveBalancer-gasAboveLimit": { + actions: []action{ + expectProcessBatch(getSectors(maxBatch), true, false, true), + expectSend(getSectors(maxBatch)[:maxBatch/2], true, false), + expectSend(getSectors(maxBatch)[maxBatch/2:], true, false), + addSectors(getSectors(maxBatch), true), + }, + }, "addSingle-belowBalancer": { actions: []action{ addSector(0, false), diff --git a/storage/pipeline/mocks/api.go b/storage/pipeline/mocks/api.go index 066fe996e..5c67a1c42 100644 --- a/storage/pipeline/mocks/api.go +++ b/storage/pipeline/mocks/api.go @@ -94,6 +94,21 @@ func (mr *MockSealingAPIMockRecorder) ChainReadObj(arg0, arg1 interface{}) *gomo return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ChainReadObj", reflect.TypeOf((*MockSealingAPI)(nil).ChainReadObj), arg0, arg1) } +// GasEstimateMessageGas mocks base method. +func (m *MockSealingAPI) GasEstimateMessageGas(arg0 context.Context, arg1 *types.Message, arg2 *api.MessageSendSpec, arg3 types.TipSetKey) (*types.Message, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GasEstimateMessageGas", arg0, arg1, arg2, arg3) + ret0, _ := ret[0].(*types.Message) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GasEstimateMessageGas indicates an expected call of GasEstimateMessageGas. +func (mr *MockSealingAPIMockRecorder) GasEstimateMessageGas(arg0, arg1, arg2, arg3 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GasEstimateMessageGas", reflect.TypeOf((*MockSealingAPI)(nil).GasEstimateMessageGas), arg0, arg1, arg2, arg3) +} + // MpoolPushMessage mocks base method. func (m *MockSealingAPI) MpoolPushMessage(arg0 context.Context, arg1 *types.Message, arg2 *api.MessageSendSpec) (*types.SignedMessage, error) { m.ctrl.T.Helper() diff --git a/storage/pipeline/mocks/mock_commit_batcher.go b/storage/pipeline/mocks/mock_commit_batcher.go index c4e7e3eef..431a47c73 100644 --- a/storage/pipeline/mocks/mock_commit_batcher.go +++ b/storage/pipeline/mocks/mock_commit_batcher.go @@ -58,6 +58,21 @@ func (mr *MockCommitBatcherApiMockRecorder) ChainHead(arg0 interface{}) *gomock. return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ChainHead", reflect.TypeOf((*MockCommitBatcherApi)(nil).ChainHead), arg0) } +// GasEstimateMessageGas mocks base method. +func (m *MockCommitBatcherApi) GasEstimateMessageGas(arg0 context.Context, arg1 *types.Message, arg2 *api.MessageSendSpec, arg3 types.TipSetKey) (*types.Message, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GasEstimateMessageGas", arg0, arg1, arg2, arg3) + ret0, _ := ret[0].(*types.Message) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GasEstimateMessageGas indicates an expected call of GasEstimateMessageGas. +func (mr *MockCommitBatcherApiMockRecorder) GasEstimateMessageGas(arg0, arg1, arg2, arg3 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GasEstimateMessageGas", reflect.TypeOf((*MockCommitBatcherApi)(nil).GasEstimateMessageGas), arg0, arg1, arg2, arg3) +} + // MpoolPushMessage mocks base method. func (m *MockCommitBatcherApi) MpoolPushMessage(arg0 context.Context, arg1 *types.Message, arg2 *api.MessageSendSpec) (*types.SignedMessage, error) { m.ctrl.T.Helper() diff --git a/storage/pipeline/mocks/mock_precommit_batcher.go b/storage/pipeline/mocks/mock_precommit_batcher.go index 2d514eb7e..68cce7fb0 100644 --- a/storage/pipeline/mocks/mock_precommit_batcher.go +++ b/storage/pipeline/mocks/mock_precommit_batcher.go @@ -58,6 +58,21 @@ func (mr *MockPreCommitBatcherApiMockRecorder) ChainHead(arg0 interface{}) *gomo return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ChainHead", reflect.TypeOf((*MockPreCommitBatcherApi)(nil).ChainHead), arg0) } +// GasEstimateMessageGas mocks base method. +func (m *MockPreCommitBatcherApi) GasEstimateMessageGas(arg0 context.Context, arg1 *types.Message, arg2 *api.MessageSendSpec, arg3 types.TipSetKey) (*types.Message, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GasEstimateMessageGas", arg0, arg1, arg2, arg3) + ret0, _ := ret[0].(*types.Message) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GasEstimateMessageGas indicates an expected call of GasEstimateMessageGas. +func (mr *MockPreCommitBatcherApiMockRecorder) GasEstimateMessageGas(arg0, arg1, arg2, arg3 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GasEstimateMessageGas", reflect.TypeOf((*MockPreCommitBatcherApi)(nil).GasEstimateMessageGas), arg0, arg1, arg2, arg3) +} + // MpoolPushMessage mocks base method. func (m *MockPreCommitBatcherApi) MpoolPushMessage(arg0 context.Context, arg1 *types.Message, arg2 *api.MessageSendSpec) (*types.SignedMessage, error) { m.ctrl.T.Helper() diff --git a/storage/pipeline/precommit_batch.go b/storage/pipeline/precommit_batch.go index 9bc624329..63e263662 100644 --- a/storage/pipeline/precommit_batch.go +++ b/storage/pipeline/precommit_batch.go @@ -31,6 +31,7 @@ import ( type PreCommitBatcherApi interface { MpoolPushMessage(context.Context, *types.Message, *api.MessageSendSpec) (*types.SignedMessage, error) + GasEstimateMessageGas(context.Context, *types.Message, *api.MessageSendSpec, types.TipSetKey) (*types.Message, error) StateMinerInfo(context.Context, address.Address, types.TipSetKey) (api.MinerInfo, error) StateMinerAvailableBalance(context.Context, address.Address, types.TipSetKey) (big.Int, error) ChainHead(ctx context.Context) (*types.TipSet, error) @@ -319,17 +320,12 @@ func (b *PreCommitBatcher) processSingle(cfg sealiface.Config, mi api.MinerInfo, return mcid, nil } -func (b *PreCommitBatcher) processBatch(cfg sealiface.Config, tsk types.TipSetKey, bf abi.TokenAmount, nv network.Version) ([]sealiface.PreCommitBatchRes, error) { +func (b *PreCommitBatcher) processPreCommitBatch(cfg sealiface.Config, bf abi.TokenAmount, entries []*preCommitEntry, nv network.Version) ([]sealiface.PreCommitBatchRes, error) { params := miner.PreCommitSectorBatchParams{} deposit := big.Zero() var res sealiface.PreCommitBatchRes - for _, p := range b.todo { - if len(params.Sectors) >= cfg.MaxPreCommitBatch { - log.Infow("precommit batch full") - break - } - + for _, p := range entries { res.Sectors = append(res.Sectors, p.pci.SectorNumber) params.Sectors = append(params.Sectors, *infoToPreCommitSectorParams(p.pci)) deposit = big.Add(deposit, p.deposit) @@ -337,11 +333,13 @@ func (b *PreCommitBatcher) processBatch(cfg sealiface.Config, tsk types.TipSetKe enc := new(bytes.Buffer) if err := params.MarshalCBOR(enc); err != nil { + res.Error = err.Error() return []sealiface.PreCommitBatchRes{res}, xerrors.Errorf("couldn't serialize PreCommitSectorBatchParams: %w", err) } mi, err := b.api.StateMinerInfo(b.mctx, b.maddr, types.EmptyTSK) if err != nil { + res.Error = err.Error() return []sealiface.PreCommitBatchRes{res}, xerrors.Errorf("couldn't get miner info: %w", err) } @@ -350,6 +348,7 @@ func (b *PreCommitBatcher) processBatch(cfg sealiface.Config, tsk types.TipSetKe aggFeeRaw, err := policy.AggregatePreCommitNetworkFee(nv, len(params.Sectors), bf) if err != nil { log.Errorf("getting aggregate precommit network fee: %s", err) + res.Error = err.Error() return []sealiface.PreCommitBatchRes{res}, xerrors.Errorf("getting aggregate precommit network fee: %s", err) } @@ -368,18 +367,42 @@ func (b *PreCommitBatcher) processBatch(cfg sealiface.Config, tsk types.TipSetKe return []sealiface.PreCommitBatchRes{res}, xerrors.Errorf("no good address found: %w", err) } - mcid, err := sendMsg(b.mctx, b.api, from, b.maddr, builtin.MethodsMiner.PreCommitSectorBatch, needFunds, maxFee, enc.Bytes()) - if err != nil { - return []sealiface.PreCommitBatchRes{res}, xerrors.Errorf("sending message failed: %w", err) + _, err = simulateMsgGas(b.mctx, b.api, from, b.maddr, builtin.MethodsMiner.PreCommitSectorBatch, needFunds, maxFee, enc.Bytes()) + + if err != nil && (!api.ErrorIsIn(err, []error{&api.ErrOutOfGas{}}) || len(entries) == 1) { + res.Error = err.Error() + return []sealiface.PreCommitBatchRes{res}, xerrors.Errorf("simulating PreCommitBatch message failed: %w", err) } + // If we're out of gas, split the batch in half and evaluate again + if api.ErrorIsIn(err, []error{&api.ErrOutOfGas{}}) { + log.Warnf("PreCommitBatch out of gas, splitting batch in half and trying again") + mid := len(entries) / 2 + ret0, _ := b.processPreCommitBatch(cfg, bf, entries[:mid], nv) + ret1, _ := b.processPreCommitBatch(cfg, bf, entries[mid:], nv) + + return append(ret0, ret1...), nil + } + + // If state call succeeds, we can send the message for real + mcid, err := sendMsg(b.mctx, b.api, from, b.maddr, builtin.MethodsMiner.PreCommitSectorBatch, needFunds, maxFee, enc.Bytes()) + if err != nil { + res.Error = err.Error() + return []sealiface.PreCommitBatchRes{res}, xerrors.Errorf("pushing message to mpool: %w", err) + } res.Msg = &mcid - - log.Infow("Sent PreCommitSectorBatch message", "cid", mcid, "from", from, "sectors", len(b.todo)) - return []sealiface.PreCommitBatchRes{res}, nil } +func (b *PreCommitBatcher) processBatch(cfg sealiface.Config, tsk types.TipSetKey, bf abi.TokenAmount, nv network.Version) ([]sealiface.PreCommitBatchRes, error) { + var pcEntries []*preCommitEntry + for _, p := range b.todo { + pcEntries = append(pcEntries, p) + } + + return b.processPreCommitBatch(cfg, bf, pcEntries, nv) +} + // register PreCommit, wait for batch message, return message CID func (b *PreCommitBatcher) AddPreCommit(ctx context.Context, s SectorInfo, deposit abi.TokenAmount, in *miner.SectorPreCommitInfo) (res sealiface.PreCommitBatchRes, err error) { ts, err := b.api.ChainHead(b.mctx) diff --git a/storage/pipeline/precommit_batch_test.go b/storage/pipeline/precommit_batch_test.go index 1779128bd..6951faad7 100644 --- a/storage/pipeline/precommit_batch_test.go +++ b/storage/pipeline/precommit_batch_test.go @@ -156,21 +156,34 @@ func TestPrecommitBatcher(t *testing.T) { } //stm: @CHAIN_STATE_MINER_INFO_001, @CHAIN_STATE_NETWORK_VERSION_001 - expectSend := func(expect []abi.SectorNumber) action { + expectSend := func(expect []abi.SectorNumber, gasOverLimit bool) action { + return func(t *testing.T, s *mocks.MockPreCommitBatcherApi, pcb *pipeline.PreCommitBatcher) promise { + s.EXPECT().StateMinerInfo(gomock.Any(), gomock.Any(), gomock.Any()).Return(api.MinerInfo{Owner: t0123, Worker: t0123}, nil) + if gasOverLimit { + s.EXPECT().GasEstimateMessageGas(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(nil, &api.ErrOutOfGas{}) + } else { + s.EXPECT().GasEstimateMessageGas(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(&types.Message{GasLimit: 100000}, nil) + } + + if !gasOverLimit { + s.EXPECT().MpoolPushMessage(gomock.Any(), funMatcher(func(i interface{}) bool { + b := i.(*types.Message) + var params miner6.PreCommitSectorBatchParams + require.NoError(t, params.UnmarshalCBOR(bytes.NewReader(b.Params))) + for s, number := range expect { + require.Equal(t, number, params.Sectors[s].SectorNumber) + } + return true + }), gomock.Any()).Return(dummySmsg, nil) + } + return nil + } + } + + expectInitialCalls := func() action { return func(t *testing.T, s *mocks.MockPreCommitBatcherApi, pcb *pipeline.PreCommitBatcher) promise { s.EXPECT().ChainHead(gomock.Any()).Return(makeBFTs(t, big.NewInt(10001), 1), nil) s.EXPECT().StateNetworkVersion(gomock.Any(), gomock.Any()).Return(network.Version14, nil) - - s.EXPECT().StateMinerInfo(gomock.Any(), gomock.Any(), gomock.Any()).Return(api.MinerInfo{Owner: t0123, Worker: t0123}, nil) - s.EXPECT().MpoolPushMessage(gomock.Any(), funMatcher(func(i interface{}) bool { - b := i.(*types.Message) - var params miner6.PreCommitSectorBatchParams - require.NoError(t, params.UnmarshalCBOR(bytes.NewReader(b.Params))) - for s, number := range expect { - require.Equal(t, number, params.Sectors[s].SectorNumber) - } - return true - }), gomock.Any()).Return(dummySmsg, nil) return nil } } @@ -198,7 +211,8 @@ func TestPrecommitBatcher(t *testing.T) { flush := func(expect []abi.SectorNumber) action { return func(t *testing.T, s *mocks.MockPreCommitBatcherApi, pcb *pipeline.PreCommitBatcher) promise { - _ = expectSend(expect)(t, s, pcb) + _ = expectInitialCalls()(t, s, pcb) + _ = expectSend(expect, false)(t, s, pcb) r, err := pcb.Flush(ctx) require.NoError(t, err) @@ -240,7 +254,17 @@ func TestPrecommitBatcher(t *testing.T) { }, "addMax": { actions: []action{ - expectSend(getSectors(maxBatch)), + expectInitialCalls(), + expectSend(getSectors(maxBatch), false), + addSectors(getSectors(maxBatch), true), + }, + }, + "addMax-gasAboveLimit": { + actions: []action{ + expectInitialCalls(), + expectSend(getSectors(maxBatch), true), + expectSend(getSectors(maxBatch)[:maxBatch/2], false), + expectSend(getSectors(maxBatch)[maxBatch/2:], false), addSectors(getSectors(maxBatch), true), }, }, diff --git a/storage/pipeline/sealiface/config.go b/storage/pipeline/sealiface/config.go index 2db155d5c..67fba27a6 100644 --- a/storage/pipeline/sealiface/config.go +++ b/storage/pipeline/sealiface/config.go @@ -58,6 +58,8 @@ type Config struct { AggregateAboveBaseFee abi.TokenAmount BatchPreCommitAboveBaseFee abi.TokenAmount + MaxSectorProveCommitsSubmittedPerEpoch uint64 + TerminateBatchMax uint64 TerminateBatchMin uint64 TerminateBatchWait time.Duration diff --git a/storage/pipeline/sealing.go b/storage/pipeline/sealing.go index 0fadb6131..d664de1e2 100644 --- a/storage/pipeline/sealing.go +++ b/storage/pipeline/sealing.go @@ -64,6 +64,7 @@ type SealingAPI interface { StateMinerDeadlines(context.Context, address.Address, types.TipSetKey) ([]api.Deadline, error) StateMinerPartitions(ctx context.Context, m address.Address, dlIdx uint64, tsk types.TipSetKey) ([]api.Partition, error) MpoolPushMessage(context.Context, *types.Message, *api.MessageSendSpec) (*types.SignedMessage, error) + GasEstimateMessageGas(context.Context, *types.Message, *api.MessageSendSpec, types.TipSetKey) (*types.Message, error) ChainHead(ctx context.Context) (*types.TipSet, error) ChainGetMessage(ctx context.Context, mc cid.Cid) (*types.Message, error) StateGetRandomnessFromBeacon(ctx context.Context, personalization crypto.DomainSeparationTag, randEpoch abi.ChainEpoch, entropy []byte, tsk types.TipSetKey) (abi.Randomness, error) diff --git a/storage/pipeline/states_proving.go b/storage/pipeline/states_proving.go index bed61a452..500dcab48 100644 --- a/storage/pipeline/states_proving.go +++ b/storage/pipeline/states_proving.go @@ -81,7 +81,12 @@ func (m *Sealing) handleTerminating(ctx statemachine.Context, sector SectorInfo) func (m *Sealing) handleTerminateWait(ctx statemachine.Context, sector SectorInfo) error { if sector.TerminateMessage == nil { - return xerrors.New("entered TerminateWait with nil TerminateMessage") + ts, err := m.Api.ChainHead(ctx.Context()) + if err != nil { + return ctx.Send(SectorTerminateFailed{xerrors.Errorf("getting chain head: %w", err)}) + } + + return ctx.Send(SectorTerminated{TerminatedAt: ts.Height()}) } mw, err := m.Api.StateWaitMsg(ctx.Context(), *sector.TerminateMessage, build.MessageConfidence, api.LookbackNoLimit, true) diff --git a/storage/pipeline/utils.go b/storage/pipeline/utils.go index 3f8d534cb..ce4283b6c 100644 --- a/storage/pipeline/utils.go +++ b/storage/pipeline/utils.go @@ -94,6 +94,21 @@ func collateralSendAmount(ctx context.Context, api interface { return collateral, nil } +func simulateMsgGas(ctx context.Context, sa interface { + GasEstimateMessageGas(context.Context, *types.Message, *api.MessageSendSpec, types.TipSetKey) (*types.Message, error) +}, + from, to address.Address, method abi.MethodNum, value, maxFee abi.TokenAmount, params []byte) (*types.Message, error) { + msg := types.Message{ + To: to, + From: from, + Value: value, + Method: method, + Params: params, + } + + return sa.GasEstimateMessageGas(ctx, &msg, nil, types.EmptyTSK) +} + func sendMsg(ctx context.Context, sa interface { MpoolPushMessage(context.Context, *types.Message, *api.MessageSendSpec) (*types.SignedMessage, error) }, from, to address.Address, method abi.MethodNum, value, maxFee abi.TokenAmount, params []byte) (cid.Cid, error) { diff --git a/storage/sealer/manager.go b/storage/sealer/manager.go index db5f9a589..3f496b7de 100644 --- a/storage/sealer/manager.go +++ b/storage/sealer/manager.go @@ -319,6 +319,15 @@ func (m *Manager) SectorsUnsealPiece(ctx context.Context, sector storiface.Secto return xerrors.Errorf("acquiring unseal sector lock: %w", err) } + // Check if sealed or update sector file exists + s, err := m.index.StorageFindSector(ctx, sector.ID, storiface.FTSealed|storiface.FTUpdate, 0, false) + if err != nil { + return xerrors.Errorf("finding sealed or updated sector: %w", err) + } + if len(s) == 0 { + return xerrors.Errorf("sealed or updated sector file not found for sector %d", sector.ID) + } + // if the selected worker does NOT have the sealed files for the sector, instruct it to fetch it from a worker that has them and // put it in the sealing scratch space. sealFetch := PrepareAction{ diff --git a/storage/sealer/manager_post.go b/storage/sealer/manager_post.go index a6f43903c..27a71ef8c 100644 --- a/storage/sealer/manager_post.go +++ b/storage/sealer/manager_post.go @@ -85,7 +85,7 @@ func (m *Manager) GenerateWindowPoSt(ctx context.Context, minerID abi.ActorID, p log.Info("GenerateWindowPoSt run at lotus-miner") p, s, err := m.localProver.GenerateWindowPoSt(ctx, minerID, postProofType, sectorInfo, randomness) if err != nil { - return nil, nil, xerrors.Errorf("local prover: %w", err) + return p, s, xerrors.Errorf("local prover: %w", err) } return p, s, nil diff --git a/storage/sealer/manager_test.go b/storage/sealer/manager_test.go index cdc135916..8acd474a3 100644 --- a/storage/sealer/manager_test.go +++ b/storage/sealer/manager_test.go @@ -17,6 +17,7 @@ import ( "github.com/google/uuid" "github.com/ipfs/go-datastore" + syncds "github.com/ipfs/go-datastore/sync" logging "github.com/ipfs/go-log/v2" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -143,7 +144,7 @@ func TestSimple(t *testing.T) { logging.SetAllLoggers(logging.LevelDebug) ctx := context.Background() - m, lstor, _, _, cleanup := newTestMgr(ctx, t, datastore.NewMapDatastore()) + m, lstor, _, _, cleanup := newTestMgr(ctx, t, syncds.MutexWrap(datastore.NewMapDatastore())) defer cleanup() localTasks := []sealtasks.TaskType{ @@ -200,7 +201,7 @@ func (m NullReader) NullBytes() int64 { func TestSnapDeals(t *testing.T) { logging.SetAllLoggers(logging.LevelWarn) ctx := context.Background() - m, lstor, stor, idx, cleanup := newTestMgr(ctx, t, datastore.NewMapDatastore()) + m, lstor, stor, idx, cleanup := newTestMgr(ctx, t, syncds.MutexWrap(datastore.NewMapDatastore())) defer cleanup() localTasks := []sealtasks.TaskType{ @@ -208,7 +209,7 @@ func TestSnapDeals(t *testing.T) { sealtasks.TTFetch, sealtasks.TTReplicaUpdate, sealtasks.TTProveReplicaUpdate1, sealtasks.TTProveReplicaUpdate2, sealtasks.TTUnseal, sealtasks.TTRegenSectorKey, sealtasks.TTFinalizeUnsealed, } - wds := datastore.NewMapDatastore() + wds := syncds.MutexWrap(datastore.NewMapDatastore()) w := NewLocalWorker(WorkerConfig{TaskTypes: localTasks}, stor, lstor, idx, m, statestore.New(wds)) err := m.AddWorker(ctx, w) @@ -329,7 +330,7 @@ func TestSnapDeals(t *testing.T) { func TestSnarkPackV2(t *testing.T) { logging.SetAllLoggers(logging.LevelWarn) ctx := context.Background() - m, lstor, stor, idx, cleanup := newTestMgr(ctx, t, datastore.NewMapDatastore()) + m, lstor, stor, idx, cleanup := newTestMgr(ctx, t, syncds.MutexWrap(datastore.NewMapDatastore())) defer cleanup() localTasks := []sealtasks.TaskType{ @@ -337,7 +338,7 @@ func TestSnarkPackV2(t *testing.T) { sealtasks.TTFetch, sealtasks.TTReplicaUpdate, sealtasks.TTProveReplicaUpdate1, sealtasks.TTProveReplicaUpdate2, sealtasks.TTUnseal, sealtasks.TTRegenSectorKey, sealtasks.TTFinalizeUnsealed, } - wds := datastore.NewMapDatastore() + wds := syncds.MutexWrap(datastore.NewMapDatastore()) w := NewLocalWorker(WorkerConfig{TaskTypes: localTasks}, stor, lstor, idx, m, statestore.New(wds)) err := m.AddWorker(ctx, w) @@ -471,7 +472,7 @@ func TestRedoPC1(t *testing.T) { logging.SetAllLoggers(logging.LevelDebug) ctx := context.Background() - m, lstor, _, _, cleanup := newTestMgr(ctx, t, datastore.NewMapDatastore()) + m, lstor, _, _, cleanup := newTestMgr(ctx, t, syncds.MutexWrap(datastore.NewMapDatastore())) defer cleanup() localTasks := []sealtasks.TaskType{ @@ -524,7 +525,7 @@ func TestRestartManager(t *testing.T) { ctx, done := context.WithCancel(context.Background()) defer done() - ds := datastore.NewMapDatastore() + ds := syncds.MutexWrap(datastore.NewMapDatastore()) m, lstor, _, _, cleanup := newTestMgr(ctx, t, ds) defer cleanup() @@ -622,7 +623,7 @@ func TestRestartWorker(t *testing.T) { ctx, done := context.WithCancel(context.Background()) defer done() - ds := datastore.NewMapDatastore() + ds := syncds.MutexWrap(datastore.NewMapDatastore()) m, lstor, stor, idx, cleanup := newTestMgr(ctx, t, ds) defer cleanup() @@ -631,7 +632,7 @@ func TestRestartWorker(t *testing.T) { sealtasks.TTAddPiece, sealtasks.TTFetch, } - wds := datastore.NewMapDatastore() + wds := syncds.MutexWrap(datastore.NewMapDatastore()) arch := make(chan chan apres) w := newLocalWorker(func() (storiface.Storage, error) { @@ -695,7 +696,7 @@ func TestReenableWorker(t *testing.T) { ctx, done := context.WithCancel(context.Background()) defer done() - ds := datastore.NewMapDatastore() + ds := syncds.MutexWrap(datastore.NewMapDatastore()) m, lstor, stor, idx, cleanup := newTestMgr(ctx, t, ds) defer cleanup() @@ -768,7 +769,7 @@ func TestResUse(t *testing.T) { ctx, done := context.WithCancel(context.Background()) defer done() - ds := datastore.NewMapDatastore() + ds := syncds.MutexWrap(datastore.NewMapDatastore()) m, lstor, stor, idx, cleanup := newTestMgr(ctx, t, ds) defer cleanup() @@ -777,7 +778,7 @@ func TestResUse(t *testing.T) { sealtasks.TTAddPiece, sealtasks.TTFetch, } - wds := datastore.NewMapDatastore() + wds := syncds.MutexWrap(datastore.NewMapDatastore()) arch := make(chan chan apres) w := newLocalWorker(func() (storiface.Storage, error) { @@ -826,7 +827,7 @@ func TestResOverride(t *testing.T) { ctx, done := context.WithCancel(context.Background()) defer done() - ds := datastore.NewMapDatastore() + ds := syncds.MutexWrap(datastore.NewMapDatastore()) m, lstor, stor, idx, cleanup := newTestMgr(ctx, t, ds) defer cleanup() @@ -835,7 +836,7 @@ func TestResOverride(t *testing.T) { sealtasks.TTAddPiece, sealtasks.TTFetch, } - wds := datastore.NewMapDatastore() + wds := syncds.MutexWrap(datastore.NewMapDatastore()) arch := make(chan chan apres) w := newLocalWorker(func() (storiface.Storage, error) { diff --git a/storage/sealer/sched_assigner_common.go b/storage/sealer/sched_assigner_common.go index d676d410d..ffc21b0dd 100644 --- a/storage/sealer/sched_assigner_common.go +++ b/storage/sealer/sched_assigner_common.go @@ -103,7 +103,7 @@ func (a *AssignerCommon) TrySched(sh *Scheduler) { needRes := worker.Info.Resources.ResourceSpec(task.Sector.ProofType, task.TaskType) // TODO: allow bigger windows - if !windows[wnd].Allocated.CanHandleRequest(task.SealTask(), needRes, windowRequest.Worker, "schedAcceptable", worker.Info) { + if !windows[wnd].Allocated.CanHandleRequest(task.SchedId, task.SealTask(), needRes, windowRequest.Worker, "schedAcceptable", worker.Info) { continue } diff --git a/storage/sealer/sched_assigner_darts.go b/storage/sealer/sched_assigner_darts.go index e28b70e78..134698fbf 100644 --- a/storage/sealer/sched_assigner_darts.go +++ b/storage/sealer/sched_assigner_darts.go @@ -37,7 +37,7 @@ func RandomWS(sh *Scheduler, queueLen int, acceptableWindows [][]int, windows [] log.Debugf("SCHED try assign sqi:%d sector %d to window %d (awi:%d)", sqi, task.Sector.ID.Number, wnd, i) - if !windows[wnd].Allocated.CanHandleRequest(task.SealTask(), res, wid, "schedAssign", w.Info) { + if !windows[wnd].Allocated.CanHandleRequest(task.SchedId, task.SealTask(), res, wid, "schedAssign", w.Info) { continue } @@ -71,7 +71,7 @@ func RandomWS(sh *Scheduler, queueLen int, acceptableWindows [][]int, windows [] "worker", bestWid, "choices", len(choices)) - windows[selectedWindow].Allocated.Add(task.SealTask(), info.Resources, needRes) + windows[selectedWindow].Allocated.Add(task.SchedId, task.SealTask(), info.Resources, needRes) windows[selectedWindow].Todo = append(windows[selectedWindow].Todo, task) rmQueue = append(rmQueue, sqi) diff --git a/storage/sealer/sched_assigner_spread.go b/storage/sealer/sched_assigner_spread.go index 0a62b7406..b1ac4c8e9 100644 --- a/storage/sealer/sched_assigner_spread.go +++ b/storage/sealer/sched_assigner_spread.go @@ -35,7 +35,7 @@ func SpreadWS(queued bool) func(sh *Scheduler, queueLen int, acceptableWindows [ log.Debugf("SCHED try assign sqi:%d sector %d to window %d (awi:%d)", sqi, task.Sector.ID.Number, wnd, i) - if !windows[wnd].Allocated.CanHandleRequest(task.SealTask(), res, wid, "schedAssign", w.Info) { + if !windows[wnd].Allocated.CanHandleRequest(task.SchedId, task.SealTask(), res, wid, "schedAssign", w.Info) { continue } @@ -71,7 +71,7 @@ func SpreadWS(queued bool) func(sh *Scheduler, queueLen int, acceptableWindows [ "assigned", bestAssigned) workerAssigned[bestWid]++ - windows[selectedWindow].Allocated.Add(task.SealTask(), info.Resources, needRes) + windows[selectedWindow].Allocated.Add(task.SchedId, task.SealTask(), info.Resources, needRes) windows[selectedWindow].Todo = append(windows[selectedWindow].Todo, task) rmQueue = append(rmQueue, sqi) diff --git a/storage/sealer/sched_assigner_spread_tasks.go b/storage/sealer/sched_assigner_spread_tasks.go index 09cf98046..f98e7b745 100644 --- a/storage/sealer/sched_assigner_spread_tasks.go +++ b/storage/sealer/sched_assigner_spread_tasks.go @@ -41,7 +41,7 @@ func SpreadTasksWS(queued bool) func(sh *Scheduler, queueLen int, acceptableWind log.Debugf("SCHED try assign sqi:%d sector %d to window %d (awi:%d)", sqi, task.Sector.ID.Number, wnd, i) - if !windows[wnd].Allocated.CanHandleRequest(task.SealTask(), res, wid, "schedAssign", w.Info) { + if !windows[wnd].Allocated.CanHandleRequest(task.SchedId, task.SealTask(), res, wid, "schedAssign", w.Info) { continue } @@ -80,7 +80,7 @@ func SpreadTasksWS(queued bool) func(sh *Scheduler, queueLen int, acceptableWind "assigned", bestAssigned) workerAssigned[bestWid]++ - windows[selectedWindow].Allocated.Add(task.SealTask(), info.Resources, needRes) + windows[selectedWindow].Allocated.Add(task.SchedId, task.SealTask(), info.Resources, needRes) windows[selectedWindow].Todo = append(windows[selectedWindow].Todo, task) rmQueue = append(rmQueue, sqi) diff --git a/storage/sealer/sched_assigner_utilization.go b/storage/sealer/sched_assigner_utilization.go index 1e75d904a..c81c9f187 100644 --- a/storage/sealer/sched_assigner_utilization.go +++ b/storage/sealer/sched_assigner_utilization.go @@ -35,7 +35,7 @@ func LowestUtilizationWS(sh *Scheduler, queueLen int, acceptableWindows [][]int, log.Debugf("SCHED try assign sqi:%d sector %d to window %d (awi:%d)", sqi, task.Sector.ID.Number, wnd, i) // TODO: allow bigger windows - if !windows[wnd].Allocated.CanHandleRequest(task.SealTask(), res, wid, "schedAssign", w.Info) { + if !windows[wnd].Allocated.CanHandleRequest(task.SchedId, task.SealTask(), res, wid, "schedAssign", w.Info) { continue } @@ -82,7 +82,7 @@ func LowestUtilizationWS(sh *Scheduler, queueLen int, acceptableWindows [][]int, "worker", bestWid, "utilization", bestUtilization) - workerUtil[bestWid] += windows[selectedWindow].Allocated.Add(task.SealTask(), info.Resources, needRes) + workerUtil[bestWid] += windows[selectedWindow].Allocated.Add(task.SchedId, task.SealTask(), info.Resources, needRes) windows[selectedWindow].Todo = append(windows[selectedWindow].Todo, task) rmQueue = append(rmQueue, sqi) diff --git a/storage/sealer/sched_post.go b/storage/sealer/sched_post.go index 0e0c39768..c6bd81829 100644 --- a/storage/sealer/sched_post.go +++ b/storage/sealer/sched_post.go @@ -7,6 +7,7 @@ import ( "sync" "time" + "github.com/google/uuid" "github.com/hashicorp/go-multierror" "golang.org/x/xerrors" @@ -110,7 +111,7 @@ func (ps *poStScheduler) Schedule(ctx context.Context, primary bool, spt abi.Reg for i, selected := range candidates { worker := ps.workers[selected.id] - err := worker.active.withResources(selected.id, worker.Info, ps.postType.SealTask(spt), selected.res, &ps.lk, func() error { + err := worker.active.withResources(uuid.UUID{}, selected.id, worker.Info, ps.postType.SealTask(spt), selected.res, &ps.lk, func() error { ps.lk.Unlock() defer ps.lk.Lock() @@ -148,7 +149,7 @@ func (ps *poStScheduler) readyWorkers(spt abi.RegisteredSealProof) (bool, []cand continue } - if !wr.active.CanHandleRequest(ps.postType.SealTask(spt), needRes, wid, "post-readyWorkers", wr.Info) { + if !wr.active.CanHandleRequest(uuid.UUID{}, ps.postType.SealTask(spt), needRes, wid, "post-readyWorkers", wr.Info) { continue } diff --git a/storage/sealer/sched_resources.go b/storage/sealer/sched_resources.go index 597f36dbe..a423def9f 100644 --- a/storage/sealer/sched_resources.go +++ b/storage/sealer/sched_resources.go @@ -3,6 +3,8 @@ package sealer import ( "sync" + "github.com/google/uuid" + "github.com/filecoin-project/lotus/storage/sealer/sealtasks" "github.com/filecoin-project/lotus/storage/sealer/storiface" ) @@ -20,7 +22,7 @@ type ActiveResources struct { } type taskCounter struct { - taskCounters map[sealtasks.SealTaskType]int + taskCounters map[sealtasks.SealTaskType]map[uuid.UUID]int // this lock is technically redundant, as ActiveResources is always accessed // with the worker lock, but let's not panic if we ever change that @@ -29,34 +31,48 @@ type taskCounter struct { func newTaskCounter() *taskCounter { return &taskCounter{ - taskCounters: map[sealtasks.SealTaskType]int{}, + taskCounters: make(map[sealtasks.SealTaskType]map[uuid.UUID]int), } } -func (tc *taskCounter) Add(tt sealtasks.SealTaskType) { +func (tc *taskCounter) Add(tt sealtasks.SealTaskType, schedID uuid.UUID) { tc.lk.Lock() defer tc.lk.Unlock() - tc.taskCounters[tt]++ + tc.getUnlocked(tt)[schedID]++ } -func (tc *taskCounter) Free(tt sealtasks.SealTaskType) { +func (tc *taskCounter) Free(tt sealtasks.SealTaskType, schedID uuid.UUID) { tc.lk.Lock() defer tc.lk.Unlock() - tc.taskCounters[tt]-- + m := tc.getUnlocked(tt) + if m[schedID] <= 1 { + delete(m, schedID) + } else { + m[schedID]-- + } } -func (tc *taskCounter) Get(tt sealtasks.SealTaskType) int { - tc.lk.Lock() - defer tc.lk.Unlock() +func (tc *taskCounter) getUnlocked(tt sealtasks.SealTaskType) map[uuid.UUID]int { + if tc.taskCounters[tt] == nil { + tc.taskCounters[tt] = make(map[uuid.UUID]int) + } + return tc.taskCounters[tt] } +func (tc *taskCounter) Get(tt sealtasks.SealTaskType) map[uuid.UUID]int { + tc.lk.Lock() + defer tc.lk.Unlock() + + return tc.getUnlocked(tt) +} + func (tc *taskCounter) Sum() int { tc.lk.Lock() defer tc.lk.Unlock() sum := 0 for _, v := range tc.taskCounters { - sum += v + sum += len(v) } return sum } @@ -64,8 +80,8 @@ func (tc *taskCounter) Sum() int { func (tc *taskCounter) ForEach(cb func(tt sealtasks.SealTaskType, count int)) { tc.lk.Lock() defer tc.lk.Unlock() - for tt, count := range tc.taskCounters { - cb(tt, count) + for tt, v := range tc.taskCounters { + cb(tt, len(v)) } } @@ -75,8 +91,8 @@ func NewActiveResources(tc *taskCounter) *ActiveResources { } } -func (a *ActiveResources) withResources(id storiface.WorkerID, wr storiface.WorkerInfo, tt sealtasks.SealTaskType, r storiface.Resources, locker sync.Locker, cb func() error) error { - for !a.CanHandleRequest(tt, r, id, "withResources", wr) { +func (a *ActiveResources) withResources(schedID uuid.UUID, id storiface.WorkerID, wr storiface.WorkerInfo, tt sealtasks.SealTaskType, r storiface.Resources, locker sync.Locker, cb func() error) error { + for !a.CanHandleRequest(schedID, tt, r, id, "withResources", wr) { if a.cond == nil { a.cond = sync.NewCond(locker) } @@ -85,11 +101,11 @@ func (a *ActiveResources) withResources(id storiface.WorkerID, wr storiface.Work a.waiting-- } - a.Add(tt, wr.Resources, r) + a.Add(schedID, tt, wr.Resources, r) err := cb() - a.Free(tt, wr.Resources, r) + a.Free(schedID, tt, wr.Resources, r) return err } @@ -100,7 +116,7 @@ func (a *ActiveResources) hasWorkWaiting() bool { } // add task resources to ActiveResources and return utilization difference -func (a *ActiveResources) Add(tt sealtasks.SealTaskType, wr storiface.WorkerResources, r storiface.Resources) float64 { +func (a *ActiveResources) Add(schedID uuid.UUID, tt sealtasks.SealTaskType, wr storiface.WorkerResources, r storiface.Resources) float64 { startUtil := a.utilization(wr) if r.GPUUtilization > 0 { @@ -109,19 +125,19 @@ func (a *ActiveResources) Add(tt sealtasks.SealTaskType, wr storiface.WorkerReso a.cpuUse += r.Threads(wr.CPUs, len(wr.GPUs)) a.memUsedMin += r.MinMemory a.memUsedMax += r.MaxMemory - a.taskCounters.Add(tt) + a.taskCounters.Add(tt, schedID) return a.utilization(wr) - startUtil } -func (a *ActiveResources) Free(tt sealtasks.SealTaskType, wr storiface.WorkerResources, r storiface.Resources) { +func (a *ActiveResources) Free(schedID uuid.UUID, tt sealtasks.SealTaskType, wr storiface.WorkerResources, r storiface.Resources) { if r.GPUUtilization > 0 { a.gpuUsed -= r.GPUUtilization } a.cpuUse -= r.Threads(wr.CPUs, len(wr.GPUs)) a.memUsedMin -= r.MinMemory a.memUsedMax -= r.MaxMemory - a.taskCounters.Free(tt) + a.taskCounters.Free(tt, schedID) if a.cond != nil { a.cond.Broadcast() @@ -130,9 +146,10 @@ func (a *ActiveResources) Free(tt sealtasks.SealTaskType, wr storiface.WorkerRes // CanHandleRequest evaluates if the worker has enough available resources to // handle the request. -func (a *ActiveResources) CanHandleRequest(tt sealtasks.SealTaskType, needRes storiface.Resources, wid storiface.WorkerID, caller string, info storiface.WorkerInfo) bool { +func (a *ActiveResources) CanHandleRequest(schedID uuid.UUID, tt sealtasks.SealTaskType, needRes storiface.Resources, wid storiface.WorkerID, caller string, info storiface.WorkerInfo) bool { if needRes.MaxConcurrent > 0 { - if a.taskCounters.Get(tt) >= needRes.MaxConcurrent { + tasks := a.taskCounters.Get(tt) + if len(tasks) >= needRes.MaxConcurrent && (schedID == uuid.UUID{} || tasks[schedID] == 0) { log.Debugf("sched: not scheduling on worker %s for %s; at task limit tt=%s, curcount=%d", wid, caller, tt, a.taskCounters.Get(tt)) return false } @@ -226,7 +243,7 @@ func (a *ActiveResources) taskCount(tt *sealtasks.SealTaskType) int { return a.taskCounters.Sum() } - return a.taskCounters.Get(*tt) + return len(a.taskCounters.Get(*tt)) } func (wh *WorkerHandle) Utilization() float64 { diff --git a/storage/sealer/sched_test.go b/storage/sealer/sched_test.go index 07731e934..2e2b05ab2 100644 --- a/storage/sealer/sched_test.go +++ b/storage/sealer/sched_test.go @@ -698,7 +698,7 @@ func TestWindowCompact(t *testing.T) { TaskType: task, Sector: storiface.SectorRef{ProofType: spt}, }) - window.Allocated.Add(task.SealTask(spt), wh.Info.Resources, storiface.ResourceTable[task][spt]) + window.Allocated.Add(uuid.UUID{}, task.SealTask(spt), wh.Info.Resources, storiface.ResourceTable[task][spt]) } wh.activeWindows = append(wh.activeWindows, window) @@ -717,7 +717,7 @@ func TestWindowCompact(t *testing.T) { for ti, task := range tasks { require.Equal(t, task, wh.activeWindows[wi].Todo[ti].TaskType, "%d, %d", wi, ti) - expectRes.Add(task.SealTask(spt), wh.Info.Resources, storiface.ResourceTable[task][spt]) + expectRes.Add(uuid.UUID{}, task.SealTask(spt), wh.Info.Resources, storiface.ResourceTable[task][spt]) } require.Equal(t, expectRes.cpuUse, wh.activeWindows[wi].Allocated.cpuUse, "%d", wi) diff --git a/storage/sealer/sched_worker.go b/storage/sealer/sched_worker.go index b6efc851a..35acd755d 100644 --- a/storage/sealer/sched_worker.go +++ b/storage/sealer/sched_worker.go @@ -294,14 +294,14 @@ func (sw *schedWorker) workerCompactWindows() { for ti, todo := range window.Todo { needRes := worker.Info.Resources.ResourceSpec(todo.Sector.ProofType, todo.TaskType) - if !lower.Allocated.CanHandleRequest(todo.SealTask(), needRes, sw.wid, "compactWindows", worker.Info) { + if !lower.Allocated.CanHandleRequest(todo.SchedId, todo.SealTask(), needRes, sw.wid, "compactWindows", worker.Info) { continue } moved = append(moved, ti) lower.Todo = append(lower.Todo, todo) - lower.Allocated.Add(todo.SealTask(), worker.Info.Resources, needRes) - window.Allocated.Free(todo.SealTask(), worker.Info.Resources, needRes) + lower.Allocated.Add(todo.SchedId, todo.SealTask(), worker.Info.Resources, needRes) + window.Allocated.Free(todo.SchedId, todo.SealTask(), worker.Info.Resources, needRes) } if len(moved) > 0 { @@ -355,7 +355,7 @@ assignLoop: worker.lk.Lock() for t, todo := range firstWindow.Todo { needResPrep := worker.Info.Resources.PrepResourceSpec(todo.Sector.ProofType, todo.TaskType, todo.prepare.PrepType) - if worker.preparing.CanHandleRequest(todo.PrepSealTask(), needResPrep, sw.wid, "startPreparing", worker.Info) { + if worker.preparing.CanHandleRequest(todo.SchedId, todo.PrepSealTask(), needResPrep, sw.wid, "startPreparing", worker.Info) { tidx = t break } @@ -416,7 +416,7 @@ assignLoop: } needRes := worker.Info.Resources.ResourceSpec(todo.Sector.ProofType, todo.TaskType) - if worker.active.CanHandleRequest(todo.SealTask(), needRes, sw.wid, "startPreparing", worker.Info) { + if worker.active.CanHandleRequest(todo.SchedId, todo.SealTask(), needRes, sw.wid, "startPreparing", worker.Info) { tidx = t break } @@ -457,7 +457,7 @@ func (sw *schedWorker) startProcessingTask(req *WorkerRequest) error { needResPrep := w.Info.Resources.PrepResourceSpec(req.Sector.ProofType, req.TaskType, req.prepare.PrepType) w.lk.Lock() - w.preparing.Add(req.PrepSealTask(), w.Info.Resources, needResPrep) + w.preparing.Add(req.SchedId, req.PrepSealTask(), w.Info.Resources, needResPrep) w.lk.Unlock() go func() { @@ -468,7 +468,7 @@ func (sw *schedWorker) startProcessingTask(req *WorkerRequest) error { w.lk.Lock() if err != nil { - w.preparing.Free(req.PrepSealTask(), w.Info.Resources, needResPrep) + w.preparing.Free(req.SchedId, req.PrepSealTask(), w.Info.Resources, needResPrep) w.lk.Unlock() select { @@ -497,11 +497,12 @@ func (sw *schedWorker) startProcessingTask(req *WorkerRequest) error { }() // wait (if needed) for resources in the 'active' window - err = w.active.withResources(sw.wid, w.Info, req.SealTask(), needRes, &w.lk, func() error { - w.preparing.Free(req.PrepSealTask(), w.Info.Resources, needResPrep) + err = w.active.withResources(req.SchedId, sw.wid, w.Info, req.SealTask(), needRes, &w.lk, func() error { + w.preparing.Free(req.SchedId, req.PrepSealTask(), w.Info.Resources, needResPrep) w.lk.Unlock() defer w.lk.Lock() // we MUST return locked from this function + // make sure the worker loop sees that the prepare task has finished select { case sw.taskDone <- struct{}{}: case <-sh.closing: @@ -525,6 +526,12 @@ func (sw *schedWorker) startProcessingTask(req *WorkerRequest) error { w.lk.Unlock() + // make sure the worker loop sees that the task has finished + select { + case sw.taskDone <- struct{}{}: + default: // there is a notification pending already + } + // This error should always be nil, since nothing is setting it, but just to be safe: if err != nil { log.Errorf("error executing worker (withResources): %+v", err) @@ -539,7 +546,7 @@ func (sw *schedWorker) startProcessingReadyTask(req *WorkerRequest) error { needRes := w.Info.Resources.ResourceSpec(req.Sector.ProofType, req.TaskType) - w.active.Add(req.SealTask(), w.Info.Resources, needRes) + w.active.Add(req.SchedId, req.SealTask(), w.Info.Resources, needRes) go func() { // Do the work! @@ -557,7 +564,7 @@ func (sw *schedWorker) startProcessingReadyTask(req *WorkerRequest) error { w.lk.Lock() - w.active.Free(req.SealTask(), w.Info.Resources, needRes) + w.active.Free(req.SchedId, req.SealTask(), w.Info.Resources, needRes) select { case sw.taskDone <- struct{}{}: diff --git a/storage/sealer/storiface/resources.go b/storage/sealer/storiface/resources.go index be5c34d0f..0fd80d79a 100644 --- a/storage/sealer/storiface/resources.go +++ b/storage/sealer/storiface/resources.go @@ -342,7 +342,9 @@ var ResourceTable = map[sealtasks.TaskType]map[abi.RegisteredSealProof]Resources MaxMemory: 8 << 30, MinMemory: 8 << 30, - MaxParallelism: 1, + MaxParallelism: 1, + MaxParallelismGPU: 6, + GPUUtilization: 1.0, BaseMinMemory: 1 << 30, }, @@ -350,7 +352,9 @@ var ResourceTable = map[sealtasks.TaskType]map[abi.RegisteredSealProof]Resources MaxMemory: 4 << 30, MinMemory: 4 << 30, - MaxParallelism: 1, + MaxParallelism: 1, + MaxParallelismGPU: 6, + GPUUtilization: 1.0, BaseMinMemory: 1 << 30, }, @@ -359,6 +363,7 @@ var ResourceTable = map[sealtasks.TaskType]map[abi.RegisteredSealProof]Resources MinMemory: 1 << 30, MaxParallelism: 1, + GPUUtilization: 1.0, BaseMinMemory: 1 << 30, }, @@ -367,6 +372,7 @@ var ResourceTable = map[sealtasks.TaskType]map[abi.RegisteredSealProof]Resources MinMemory: 2 << 10, MaxParallelism: 1, + GPUUtilization: 1.0, BaseMinMemory: 2 << 10, }, @@ -375,6 +381,7 @@ var ResourceTable = map[sealtasks.TaskType]map[abi.RegisteredSealProof]Resources MinMemory: 8 << 20, MaxParallelism: 1, + GPUUtilization: 1.0, BaseMinMemory: 8 << 20, },