Merge branch 'release/v1.20.0' into iand/issue-9849-config
This commit is contained in:
commit
e73dc3eb74
@ -328,56 +328,6 @@ jobs:
|
||||
- run: ./scripts/generate-checksums.sh
|
||||
- run: ./scripts/publish-checksums.sh
|
||||
|
||||
build-appimage:
|
||||
machine:
|
||||
image: ubuntu-2004:202111-02
|
||||
steps:
|
||||
- checkout
|
||||
- attach_workspace:
|
||||
at: /tmp/workspace
|
||||
- run:
|
||||
name: Update Go
|
||||
command: |
|
||||
sudo rm -rf /usr/local/go && \
|
||||
curl -L https://golang.org/dl/go`cat GO_VERSION_MIN`.linux-amd64.tar.gz -o /tmp/go.tar.gz && \
|
||||
sudo tar -C /usr/local -xvf /tmp/go.tar.gz
|
||||
- run: go version
|
||||
- run:
|
||||
name: install appimage-builder
|
||||
command: |
|
||||
# appimage-builder requires /dev/snd to exist. It creates containers during the testing phase
|
||||
# that pass sound devices from the host to the testing container. (hard coded!)
|
||||
# https://github.com/AppImageCrafters/appimage-builder/blob/master/appimagebuilder/modules/test/execution_test.py#L54
|
||||
# Circleci doesn't provide a working sound device; this is enough to fake it.
|
||||
if [ ! -e /dev/snd ]
|
||||
then
|
||||
sudo mkdir /dev/snd
|
||||
sudo mknod /dev/snd/ControlC0 c 1 2
|
||||
fi
|
||||
|
||||
# docs: https://appimage-builder.readthedocs.io/en/latest/intro/install.html
|
||||
sudo apt update
|
||||
sudo apt install -y python3-pip python3-setuptools patchelf desktop-file-utils libgdk-pixbuf2.0-dev fakeroot strace
|
||||
sudo curl -Lo /usr/local/bin/appimagetool https://github.com/AppImage/AppImageKit/releases/download/continuous/appimagetool-x86_64.AppImage
|
||||
sudo chmod +x /usr/local/bin/appimagetool
|
||||
sudo pip3 install appimage-builder
|
||||
- run:
|
||||
name: install lotus dependencies
|
||||
command: sudo apt install ocl-icd-opencl-dev libhwloc-dev
|
||||
- run:
|
||||
name: build appimage
|
||||
command: |
|
||||
sed -i "s/version: latest/version: ${CIRCLE_TAG:-latest}/" AppImageBuilder.yml
|
||||
make appimage
|
||||
- run: |
|
||||
mkdir -p /tmp/workspace/appimage && \
|
||||
mv Lotus-*.AppImage /tmp/workspace/appimage/
|
||||
- persist_to_workspace:
|
||||
root: /tmp/workspace
|
||||
paths:
|
||||
- appimage
|
||||
|
||||
|
||||
gofmt:
|
||||
executor: golang
|
||||
steps:
|
||||
@ -444,72 +394,6 @@ jobs:
|
||||
lint-all:
|
||||
<<: *lint
|
||||
|
||||
publish:
|
||||
description: publish binary artifacts
|
||||
executor: ubuntu
|
||||
parameters:
|
||||
linux:
|
||||
default: false
|
||||
description: publish linux binaries?
|
||||
type: boolean
|
||||
appimage:
|
||||
default: false
|
||||
description: publish appimage binaries?
|
||||
type: boolean
|
||||
steps:
|
||||
- run:
|
||||
name: Install git jq curl
|
||||
command: apt update && apt install -y git jq curl sudo
|
||||
- checkout
|
||||
- git_fetch_all_tags
|
||||
- checkout
|
||||
- install_ipfs
|
||||
- attach_workspace:
|
||||
at: /tmp/workspace
|
||||
- when:
|
||||
condition: << parameters.linux >>
|
||||
steps:
|
||||
- run: ./scripts/build-arch-bundle.sh linux
|
||||
- run: ./scripts/publish-arch-release.sh linux
|
||||
- when:
|
||||
condition: << parameters.appimage >>
|
||||
steps:
|
||||
- run: ./scripts/build-appimage-bundle.sh
|
||||
- run: ./scripts/publish-arch-release.sh appimage
|
||||
|
||||
publish-snapcraft:
|
||||
description: build and push snapcraft
|
||||
machine:
|
||||
image: ubuntu-2004:202104-01
|
||||
resource_class: 2xlarge
|
||||
parameters:
|
||||
channel:
|
||||
type: string
|
||||
default: "edge"
|
||||
description: snapcraft channel
|
||||
snap-name:
|
||||
type: string
|
||||
default: 'lotus-filecoin'
|
||||
description: name of snap in snap store
|
||||
steps:
|
||||
- checkout
|
||||
- run:
|
||||
name: Install snapcraft
|
||||
command: sudo snap install snapcraft --classic
|
||||
- run:
|
||||
name: Build << parameters.snap-name >> snap
|
||||
command: |
|
||||
if [ "<< parameters.snap-name >>" != 'lotus-filecoin' ]; then
|
||||
cat snap/snapcraft.yaml | sed 's/lotus-filecoin/lotus/' > edited-snapcraft.yaml
|
||||
mv edited-snapcraft.yaml snap/snapcraft.yaml
|
||||
fi
|
||||
|
||||
snapcraft --use-lxd --debug
|
||||
- run:
|
||||
name: Publish snap to << parameters.channel >> channel
|
||||
shell: /bin/bash -o pipefail
|
||||
command: |
|
||||
snapcraft upload *.snap --release << parameters.channel >>
|
||||
build-docker:
|
||||
description: >
|
||||
Publish to Dockerhub
|
||||
@ -550,7 +434,7 @@ jobs:
|
||||
equal: [ mainnet, <<parameters.network>> ]
|
||||
steps:
|
||||
- when:
|
||||
condition: <parameters.push>>
|
||||
condition: <<parameters.push>>
|
||||
steps:
|
||||
- docker/build:
|
||||
image: filecoin/<<parameters.image>>
|
||||
@ -561,7 +445,7 @@ jobs:
|
||||
command: |
|
||||
docker push filecoin/<<parameters.image>>:<<parameters.channel>>
|
||||
if [[ ! -z $CIRCLE_SHA ]]; then
|
||||
docker image tag filecoin/<<parameters.image>>:<<parameters.channel>>> filecoin/<<parameters.image>>:"${CIRCLE_SHA:0:7}"
|
||||
docker image tag filecoin/<<parameters.image>>:<<parameters.channel>> filecoin/<<parameters.image>>:"${CIRCLE_SHA:0:7}"
|
||||
docker push filecoin/<<parameters.image>>:"${CIRCLE_SHA:0:7}"
|
||||
fi
|
||||
if [[ ! -z $CIRCLE_TAG ]]; then
|
||||
@ -730,6 +614,11 @@ workflows:
|
||||
suite: itest-eth_balance
|
||||
target: "./itests/eth_balance_test.go"
|
||||
|
||||
- test:
|
||||
name: test-itest-eth_block_hash
|
||||
suite: itest-eth_block_hash
|
||||
target: "./itests/eth_block_hash_test.go"
|
||||
|
||||
- test:
|
||||
name: test-itest-eth_deploy
|
||||
suite: itest-eth_deploy
|
||||
@ -1063,71 +952,6 @@ workflows:
|
||||
branches:
|
||||
only:
|
||||
- /^release\/v\d+\.\d+\.\d+(-rc\d+)?$/
|
||||
- build-appimage:
|
||||
name: "Build AppImage"
|
||||
filters:
|
||||
branches:
|
||||
only:
|
||||
- /^release\/v\d+\.\d+\.\d+(-rc\d+)?$/
|
||||
tags:
|
||||
only:
|
||||
- /^v\d+\.\d+\.\d+(-rc\d+)?$/
|
||||
- publish:
|
||||
name: "Publish AppImage"
|
||||
appimage: true
|
||||
requires:
|
||||
- "Build AppImage"
|
||||
filters:
|
||||
branches:
|
||||
ignore:
|
||||
- /.*/
|
||||
tags:
|
||||
only:
|
||||
- /^v\d+\.\d+\.\d+(-rc\d+)?$/
|
||||
- publish-snapcraft:
|
||||
name: "Publish Snapcraft (lotus / stable)"
|
||||
channel: stable
|
||||
snap-name: lotus
|
||||
filters:
|
||||
branches:
|
||||
ignore:
|
||||
- /.*/
|
||||
tags:
|
||||
only:
|
||||
- /^v\d+\.\d+\.\d+$/
|
||||
- publish-snapcraft:
|
||||
name: "Publish Snapcraft (lotus / candidate)"
|
||||
channel: candidate
|
||||
snap-name: lotus
|
||||
filters:
|
||||
branches:
|
||||
ignore:
|
||||
- /.*/
|
||||
tags:
|
||||
only:
|
||||
- /^v\d+\.\d+\.\d+-rc\d+$/
|
||||
- publish-snapcraft:
|
||||
name: "Publish Snapcraft (lotus-filecoin / stable)"
|
||||
channel: stable
|
||||
snap-name: lotus-filecoin
|
||||
filters:
|
||||
branches:
|
||||
ignore:
|
||||
- /.*/
|
||||
tags:
|
||||
only:
|
||||
- /^v\d+\.\d+\.\d+$/
|
||||
- publish-snapcraft:
|
||||
name: "Publish Snapcraft (lotus-filecoin / candidate)"
|
||||
channel: candidate
|
||||
snap-name: lotus-filecoin
|
||||
filters:
|
||||
branches:
|
||||
ignore:
|
||||
- /.*/
|
||||
tags:
|
||||
only:
|
||||
- /^v\d+\.\d+\.\d+-rc\d+$/
|
||||
- build-docker:
|
||||
name: "Docker push (lotus-all-in-one / stable / mainnet)"
|
||||
image: lotus-all-in-one
|
||||
@ -1363,14 +1187,6 @@ workflows:
|
||||
only:
|
||||
- master
|
||||
jobs:
|
||||
- publish-snapcraft:
|
||||
name: "Publish Snapcraft (lotus / edge)"
|
||||
channel: edge
|
||||
snap-name: lotus
|
||||
- publish-snapcraft:
|
||||
name: "Publish Snapcraft (lotus-filecoin / edge)"
|
||||
channel: edge
|
||||
snap-name: lotus-filecoin
|
||||
- build-docker:
|
||||
name: "Docker (lotus-all-in-one / nightly / mainnet)"
|
||||
image: lotus-all-in-one
|
||||
|
@ -107,13 +107,11 @@ func main() {
|
||||
// form the input data.
|
||||
type data struct {
|
||||
Networks []string
|
||||
SnapNames []string
|
||||
ItestFiles []string
|
||||
UnitSuites map[string]string
|
||||
}
|
||||
in := data{
|
||||
Networks: []string{"mainnet", "butterflynet", "calibnet", "debug"},
|
||||
SnapNames: []string{"lotus", "lotus-filecoin"},
|
||||
ItestFiles: itests,
|
||||
UnitSuites: func() map[string]string {
|
||||
ret := make(map[string]string)
|
||||
|
@ -328,56 +328,6 @@ jobs:
|
||||
- run: ./scripts/generate-checksums.sh
|
||||
- run: ./scripts/publish-checksums.sh
|
||||
|
||||
build-appimage:
|
||||
machine:
|
||||
image: ubuntu-2004:202111-02
|
||||
steps:
|
||||
- checkout
|
||||
- attach_workspace:
|
||||
at: /tmp/workspace
|
||||
- run:
|
||||
name: Update Go
|
||||
command: |
|
||||
sudo rm -rf /usr/local/go && \
|
||||
curl -L https://golang.org/dl/go`cat GO_VERSION_MIN`.linux-amd64.tar.gz -o /tmp/go.tar.gz && \
|
||||
sudo tar -C /usr/local -xvf /tmp/go.tar.gz
|
||||
- run: go version
|
||||
- run:
|
||||
name: install appimage-builder
|
||||
command: |
|
||||
# appimage-builder requires /dev/snd to exist. It creates containers during the testing phase
|
||||
# that pass sound devices from the host to the testing container. (hard coded!)
|
||||
# https://github.com/AppImageCrafters/appimage-builder/blob/master/appimagebuilder/modules/test/execution_test.py#L54
|
||||
# Circleci doesn't provide a working sound device; this is enough to fake it.
|
||||
if [ ! -e /dev/snd ]
|
||||
then
|
||||
sudo mkdir /dev/snd
|
||||
sudo mknod /dev/snd/ControlC0 c 1 2
|
||||
fi
|
||||
|
||||
# docs: https://appimage-builder.readthedocs.io/en/latest/intro/install.html
|
||||
sudo apt update
|
||||
sudo apt install -y python3-pip python3-setuptools patchelf desktop-file-utils libgdk-pixbuf2.0-dev fakeroot strace
|
||||
sudo curl -Lo /usr/local/bin/appimagetool https://github.com/AppImage/AppImageKit/releases/download/continuous/appimagetool-x86_64.AppImage
|
||||
sudo chmod +x /usr/local/bin/appimagetool
|
||||
sudo pip3 install appimage-builder
|
||||
- run:
|
||||
name: install lotus dependencies
|
||||
command: sudo apt install ocl-icd-opencl-dev libhwloc-dev
|
||||
- run:
|
||||
name: build appimage
|
||||
command: |
|
||||
sed -i "s/version: latest/version: ${CIRCLE_TAG:-latest}/" AppImageBuilder.yml
|
||||
make appimage
|
||||
- run: |
|
||||
mkdir -p /tmp/workspace/appimage && \
|
||||
mv Lotus-*.AppImage /tmp/workspace/appimage/
|
||||
- persist_to_workspace:
|
||||
root: /tmp/workspace
|
||||
paths:
|
||||
- appimage
|
||||
|
||||
|
||||
gofmt:
|
||||
executor: golang
|
||||
steps:
|
||||
@ -444,72 +394,6 @@ jobs:
|
||||
lint-all:
|
||||
<<: *lint
|
||||
|
||||
publish:
|
||||
description: publish binary artifacts
|
||||
executor: ubuntu
|
||||
parameters:
|
||||
linux:
|
||||
default: false
|
||||
description: publish linux binaries?
|
||||
type: boolean
|
||||
appimage:
|
||||
default: false
|
||||
description: publish appimage binaries?
|
||||
type: boolean
|
||||
steps:
|
||||
- run:
|
||||
name: Install git jq curl
|
||||
command: apt update && apt install -y git jq curl sudo
|
||||
- checkout
|
||||
- git_fetch_all_tags
|
||||
- checkout
|
||||
- install_ipfs
|
||||
- attach_workspace:
|
||||
at: /tmp/workspace
|
||||
- when:
|
||||
condition: << parameters.linux >>
|
||||
steps:
|
||||
- run: ./scripts/build-arch-bundle.sh linux
|
||||
- run: ./scripts/publish-arch-release.sh linux
|
||||
- when:
|
||||
condition: << parameters.appimage >>
|
||||
steps:
|
||||
- run: ./scripts/build-appimage-bundle.sh
|
||||
- run: ./scripts/publish-arch-release.sh appimage
|
||||
|
||||
publish-snapcraft:
|
||||
description: build and push snapcraft
|
||||
machine:
|
||||
image: ubuntu-2004:202104-01
|
||||
resource_class: 2xlarge
|
||||
parameters:
|
||||
channel:
|
||||
type: string
|
||||
default: "edge"
|
||||
description: snapcraft channel
|
||||
snap-name:
|
||||
type: string
|
||||
default: 'lotus-filecoin'
|
||||
description: name of snap in snap store
|
||||
steps:
|
||||
- checkout
|
||||
- run:
|
||||
name: Install snapcraft
|
||||
command: sudo snap install snapcraft --classic
|
||||
- run:
|
||||
name: Build << parameters.snap-name >> snap
|
||||
command: |
|
||||
if [ "<< parameters.snap-name >>" != 'lotus-filecoin' ]; then
|
||||
cat snap/snapcraft.yaml | sed 's/lotus-filecoin/lotus/' > edited-snapcraft.yaml
|
||||
mv edited-snapcraft.yaml snap/snapcraft.yaml
|
||||
fi
|
||||
|
||||
snapcraft --use-lxd --debug
|
||||
- run:
|
||||
name: Publish snap to << parameters.channel >> channel
|
||||
shell: /bin/bash -o pipefail
|
||||
command: |
|
||||
snapcraft upload *.snap --release << parameters.channel >>
|
||||
build-docker:
|
||||
description: >
|
||||
Publish to Dockerhub
|
||||
@ -550,7 +434,7 @@ jobs:
|
||||
equal: [ mainnet, <<parameters.network>> ]
|
||||
steps:
|
||||
- when:
|
||||
condition: <parameters.push>>
|
||||
condition: <<parameters.push>>
|
||||
steps:
|
||||
- docker/build:
|
||||
image: filecoin/<<parameters.image>>
|
||||
@ -561,7 +445,7 @@ jobs:
|
||||
command: |
|
||||
docker push filecoin/<<parameters.image>>:<<parameters.channel>>
|
||||
if [["[[ ! -z $CIRCLE_SHA ]]"]]; then
|
||||
docker image tag filecoin/<<parameters.image>>:<<parameters.channel>>> filecoin/<<parameters.image>>:"${CIRCLE_SHA:0:7}"
|
||||
docker image tag filecoin/<<parameters.image>>:<<parameters.channel>> filecoin/<<parameters.image>>:"${CIRCLE_SHA:0:7}"
|
||||
docker push filecoin/<<parameters.image>>:"${CIRCLE_SHA:0:7}"
|
||||
fi
|
||||
if [["[[ ! -z $CIRCLE_TAG ]]"]]; then
|
||||
@ -698,51 +582,6 @@ workflows:
|
||||
branches:
|
||||
only:
|
||||
- /^release\/v\d+\.\d+\.\d+(-rc\d+)?$/
|
||||
- build-appimage:
|
||||
name: "Build AppImage"
|
||||
filters:
|
||||
branches:
|
||||
only:
|
||||
- /^release\/v\d+\.\d+\.\d+(-rc\d+)?$/
|
||||
tags:
|
||||
only:
|
||||
- /^v\d+\.\d+\.\d+(-rc\d+)?$/
|
||||
- publish:
|
||||
name: "Publish AppImage"
|
||||
appimage: true
|
||||
requires:
|
||||
- "Build AppImage"
|
||||
filters:
|
||||
branches:
|
||||
ignore:
|
||||
- /.*/
|
||||
tags:
|
||||
only:
|
||||
- /^v\d+\.\d+\.\d+(-rc\d+)?$/
|
||||
[[- range .SnapNames]]
|
||||
- publish-snapcraft:
|
||||
name: "Publish Snapcraft ([[.]] / stable)"
|
||||
channel: stable
|
||||
snap-name: [[.]]
|
||||
filters:
|
||||
branches:
|
||||
ignore:
|
||||
- /.*/
|
||||
tags:
|
||||
only:
|
||||
- /^v\d+\.\d+\.\d+$/
|
||||
- publish-snapcraft:
|
||||
name: "Publish Snapcraft ([[.]] / candidate)"
|
||||
channel: candidate
|
||||
snap-name: [[.]]
|
||||
filters:
|
||||
branches:
|
||||
ignore:
|
||||
- /.*/
|
||||
tags:
|
||||
only:
|
||||
- /^v\d+\.\d+\.\d+-rc\d+$/
|
||||
[[- end]]
|
||||
[[- range .Networks]]
|
||||
- build-docker:
|
||||
name: "Docker push (lotus-all-in-one / stable / [[.]])"
|
||||
@ -845,12 +684,6 @@ workflows:
|
||||
only:
|
||||
- master
|
||||
jobs:
|
||||
[[- range .SnapNames]]
|
||||
- publish-snapcraft:
|
||||
name: "Publish Snapcraft ([[.]] / edge)"
|
||||
channel: edge
|
||||
snap-name: [[.]]
|
||||
[[- end]]
|
||||
[[- range .Networks]]
|
||||
- build-docker:
|
||||
name: "Docker (lotus-all-in-one / nightly / [[.]])"
|
||||
|
6
Makefile
6
Makefile
@ -84,12 +84,6 @@ butterflynet: build-devnets
|
||||
interopnet: GOFLAGS+=-tags=interopnet
|
||||
interopnet: build-devnets
|
||||
|
||||
wallabynet: GOFLAGS+=-tags=wallabynet
|
||||
wallabynet: build-devnets
|
||||
|
||||
hyperspacenet: GOFLAGS+=-tags=hyperspacenet
|
||||
hyperspacenet: build-devnets
|
||||
|
||||
lotus: $(BUILD_DEPS)
|
||||
rm -f lotus
|
||||
$(GOCC) build $(GOFLAGS) -o lotus ./cmd/lotus
|
||||
|
@ -836,6 +836,9 @@ type FullNode interface {
|
||||
// Unsubscribe from a websocket subscription
|
||||
EthUnsubscribe(ctx context.Context, id ethtypes.EthSubscriptionID) (bool, error) //perm:write
|
||||
|
||||
// Returns the client version
|
||||
Web3ClientVersion(ctx context.Context) (string, error) //perm:read
|
||||
|
||||
// CreateBackup creates node backup onder the specified file name. The
|
||||
// method requires that the lotus daemon is running with the
|
||||
// LOTUS_BACKUP_BASE_PATH environment variable set to some path, and that
|
||||
|
@ -41,4 +41,6 @@ func CreateEthRPCAliases(as apitypes.Aliaser) {
|
||||
|
||||
as.AliasMethod("net_version", "Filecoin.NetVersion")
|
||||
as.AliasMethod("net_listening", "Filecoin.NetListening")
|
||||
|
||||
as.AliasMethod("web3_clientVersion", "Filecoin.Web3ClientVersion")
|
||||
}
|
||||
|
@ -4096,3 +4096,18 @@ func (mr *MockFullNodeMockRecorder) WalletVerify(arg0, arg1, arg2, arg3 interfac
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "WalletVerify", reflect.TypeOf((*MockFullNode)(nil).WalletVerify), arg0, arg1, arg2, arg3)
|
||||
}
|
||||
|
||||
// Web3ClientVersion mocks base method.
|
||||
func (m *MockFullNode) Web3ClientVersion(arg0 context.Context) (string, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Web3ClientVersion", arg0)
|
||||
ret0, _ := ret[0].(string)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// Web3ClientVersion indicates an expected call of Web3ClientVersion.
|
||||
func (mr *MockFullNodeMockRecorder) Web3ClientVersion(arg0 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Web3ClientVersion", reflect.TypeOf((*MockFullNode)(nil).Web3ClientVersion), arg0)
|
||||
}
|
||||
|
@ -582,6 +582,8 @@ type FullNodeStruct struct {
|
||||
WalletValidateAddress func(p0 context.Context, p1 string) (address.Address, error) `perm:"read"`
|
||||
|
||||
WalletVerify func(p0 context.Context, p1 address.Address, p2 []byte, p3 *crypto.Signature) (bool, error) `perm:"read"`
|
||||
|
||||
Web3ClientVersion func(p0 context.Context) (string, error) `perm:"read"`
|
||||
}
|
||||
}
|
||||
|
||||
@ -3936,6 +3938,17 @@ func (s *FullNodeStub) WalletVerify(p0 context.Context, p1 address.Address, p2 [
|
||||
return false, ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *FullNodeStruct) Web3ClientVersion(p0 context.Context) (string, error) {
|
||||
if s.Internal.Web3ClientVersion == nil {
|
||||
return "", ErrNotSupported
|
||||
}
|
||||
return s.Internal.Web3ClientVersion(p0)
|
||||
}
|
||||
|
||||
func (s *FullNodeStub) Web3ClientVersion(p0 context.Context) (string, error) {
|
||||
return "", ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *GatewayStruct) ChainGetBlockMessages(p0 context.Context, p1 cid.Cid) (*BlockMessages, error) {
|
||||
if s.Internal.ChainGetBlockMessages == nil {
|
||||
return nil, ErrNotSupported
|
||||
|
@ -1,6 +1,6 @@
|
||||
#!/bin/bash
|
||||
|
||||
NETWORKS=(devnet mainnet caterpillarnet butterflynet testing testing-fake-proofs calibrationnet hyperspace)
|
||||
NETWORKS=(devnet mainnet caterpillarnet butterflynet testing testing-fake-proofs calibrationnet)
|
||||
|
||||
set -e
|
||||
|
||||
|
@ -1,4 +0,0 @@
|
||||
/dns4/de0.bootstrap.wallaby.network/tcp/1337/p2p/12D3KooWHAvUVk5XuxSwi2dNLWbTDDRSGeHxMuWdQ3SQpRuNHbLz
|
||||
/dns4/de1.bootstrap.wallaby.network/tcp/1337/p2p/12D3KooWBRqtxhJCtiLmCwKgAQozJtdGinEDdJGoS5oHw7vCjMGc
|
||||
/dns4/ca0.bootstrap.wallaby.network/tcp/1337/p2p/12D3KooWCApBpUk7EX9pmEfyky1gKC6N2KJ74S1AwFfvnkDqw3pK
|
||||
/dns4/sg0.bootstrap.wallaby.network/tcp/1337/p2p/12D3KooWLnYqr4hRoNHBJQVXsFGkDoKuoVfw5R2ASw1bHzrWU5Px
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -1,94 +0,0 @@
|
||||
//go:build hyperspacenet
|
||||
// +build hyperspacenet
|
||||
|
||||
package build
|
||||
|
||||
import (
|
||||
"github.com/ipfs/go-cid"
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
"github.com/filecoin-project/go-state-types/abi"
|
||||
actorstypes "github.com/filecoin-project/go-state-types/actors"
|
||||
"github.com/filecoin-project/go-state-types/network"
|
||||
builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin"
|
||||
|
||||
"github.com/filecoin-project/lotus/chain/actors/policy"
|
||||
)
|
||||
|
||||
var NetworkBundle = "hyperspace"
|
||||
var BundleOverrides map[actorstypes.Version]string
|
||||
var ActorDebugging = false
|
||||
|
||||
const BootstrappersFile = "hyperspacenet.pi"
|
||||
const GenesisFile = "hyperspacenet.car"
|
||||
|
||||
const GenesisNetworkVersion = network.Version18
|
||||
|
||||
var UpgradeBreezeHeight = abi.ChainEpoch(-1)
|
||||
|
||||
const BreezeGasTampingDuration = 120
|
||||
|
||||
var UpgradeSmokeHeight = abi.ChainEpoch(-1)
|
||||
var UpgradeIgnitionHeight = abi.ChainEpoch(-2)
|
||||
var UpgradeRefuelHeight = abi.ChainEpoch(-3)
|
||||
var UpgradeTapeHeight = abi.ChainEpoch(-4)
|
||||
|
||||
var UpgradeAssemblyHeight = abi.ChainEpoch(-5)
|
||||
var UpgradeLiftoffHeight = abi.ChainEpoch(-6)
|
||||
|
||||
var UpgradeKumquatHeight = abi.ChainEpoch(-7)
|
||||
var UpgradeCalicoHeight = abi.ChainEpoch(-9)
|
||||
var UpgradePersianHeight = abi.ChainEpoch(-10)
|
||||
var UpgradeOrangeHeight = abi.ChainEpoch(-11)
|
||||
var UpgradeClausHeight = abi.ChainEpoch(-12)
|
||||
|
||||
var UpgradeTrustHeight = abi.ChainEpoch(-13)
|
||||
|
||||
var UpgradeNorwegianHeight = abi.ChainEpoch(-14)
|
||||
|
||||
var UpgradeTurboHeight = abi.ChainEpoch(-15)
|
||||
|
||||
var UpgradeHyperdriveHeight = abi.ChainEpoch(-16)
|
||||
var UpgradeChocolateHeight = abi.ChainEpoch(-17)
|
||||
var UpgradeOhSnapHeight = abi.ChainEpoch(-18)
|
||||
var UpgradeSkyrHeight = abi.ChainEpoch(-19)
|
||||
var UpgradeSharkHeight = abi.ChainEpoch(-20)
|
||||
var UpgradeHyggeHeight = abi.ChainEpoch(-21)
|
||||
|
||||
var DrandSchedule = map[abi.ChainEpoch]DrandEnum{
|
||||
0: DrandMainnet,
|
||||
}
|
||||
|
||||
var SupportedProofTypes = []abi.RegisteredSealProof{
|
||||
abi.RegisteredSealProof_StackedDrg512MiBV1,
|
||||
abi.RegisteredSealProof_StackedDrg32GiBV1,
|
||||
abi.RegisteredSealProof_StackedDrg64GiBV1,
|
||||
}
|
||||
var ConsensusMinerMinPower = abi.NewStoragePower(16 << 30)
|
||||
var MinVerifiedDealSize = abi.NewStoragePower(1 << 20)
|
||||
var PreCommitChallengeDelay = abi.ChainEpoch(10)
|
||||
|
||||
func init() {
|
||||
policy.SetSupportedProofTypes(SupportedProofTypes...)
|
||||
policy.SetConsensusMinerMinPower(ConsensusMinerMinPower)
|
||||
policy.SetMinVerifiedDealSize(MinVerifiedDealSize)
|
||||
policy.SetPreCommitChallengeDelay(PreCommitChallengeDelay)
|
||||
|
||||
BuildType = BuildHyperspacenet
|
||||
SetAddressNetwork(address.Testnet)
|
||||
Devnet = true
|
||||
|
||||
}
|
||||
|
||||
const BlockDelaySecs = uint64(builtin2.EpochDurationSeconds)
|
||||
|
||||
const PropagationDelaySecs = uint64(6)
|
||||
|
||||
// BootstrapPeerThreshold is the minimum number peers we need to track for a sync worker to start
|
||||
const BootstrapPeerThreshold = 2
|
||||
|
||||
// ChainId defines the chain ID used in the Ethereum JSON-RPC endpoint.
|
||||
// As per https://github.com/ethereum-lists/chains
|
||||
const Eip155ChainId = 3141
|
||||
|
||||
var WhitelistedBlock = cid.Undef
|
@ -1,5 +1,5 @@
|
||||
//go:build !debug && !2k && !testground && !calibnet && !butterflynet && !interopnet && !wallabynet && !hyperspacenet
|
||||
// +build !debug,!2k,!testground,!calibnet,!butterflynet,!interopnet,!wallabynet,!hyperspacenet
|
||||
//go:build !debug && !2k && !testground && !calibnet && !butterflynet && !interopnet
|
||||
// +build !debug,!2k,!testground,!calibnet,!butterflynet,!interopnet
|
||||
|
||||
package build
|
||||
|
||||
|
@ -42,9 +42,6 @@ var (
|
||||
|
||||
AllowableClockDriftSecs = uint64(1)
|
||||
|
||||
Finality = policy.ChainFinality
|
||||
ForkLengthThreshold = Finality
|
||||
|
||||
SlashablePowerDelay = 20
|
||||
InteractivePoRepConfidence = 6
|
||||
|
||||
@ -130,6 +127,9 @@ var (
|
||||
GenesisFile = ""
|
||||
)
|
||||
|
||||
const Finality = policy.ChainFinality
|
||||
const ForkLengthThreshold = Finality
|
||||
|
||||
const BootstrapPeerThreshold = 1
|
||||
|
||||
// ChainId defines the chain ID used in the Ethereum JSON-RPC endpoint.
|
||||
|
@ -1,94 +0,0 @@
|
||||
//go:build wallabynet
|
||||
// +build wallabynet
|
||||
|
||||
package build
|
||||
|
||||
import (
|
||||
"github.com/ipfs/go-cid"
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
"github.com/filecoin-project/go-state-types/abi"
|
||||
actorstypes "github.com/filecoin-project/go-state-types/actors"
|
||||
"github.com/filecoin-project/go-state-types/network"
|
||||
builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin"
|
||||
|
||||
"github.com/filecoin-project/lotus/chain/actors/policy"
|
||||
)
|
||||
|
||||
var NetworkBundle = "wallaby"
|
||||
var BundleOverrides map[actorstypes.Version]string
|
||||
var ActorDebugging = false
|
||||
|
||||
const BootstrappersFile = "wallabynet.pi"
|
||||
const GenesisFile = "wallabynet.car"
|
||||
|
||||
const GenesisNetworkVersion = network.Version18
|
||||
|
||||
var UpgradeBreezeHeight = abi.ChainEpoch(-1)
|
||||
|
||||
const BreezeGasTampingDuration = 120
|
||||
|
||||
var UpgradeSmokeHeight = abi.ChainEpoch(-1)
|
||||
var UpgradeIgnitionHeight = abi.ChainEpoch(-2)
|
||||
var UpgradeRefuelHeight = abi.ChainEpoch(-3)
|
||||
var UpgradeTapeHeight = abi.ChainEpoch(-4)
|
||||
|
||||
var UpgradeAssemblyHeight = abi.ChainEpoch(-5)
|
||||
var UpgradeLiftoffHeight = abi.ChainEpoch(-6)
|
||||
|
||||
var UpgradeKumquatHeight = abi.ChainEpoch(-7)
|
||||
var UpgradeCalicoHeight = abi.ChainEpoch(-9)
|
||||
var UpgradePersianHeight = abi.ChainEpoch(-10)
|
||||
var UpgradeOrangeHeight = abi.ChainEpoch(-11)
|
||||
var UpgradeClausHeight = abi.ChainEpoch(-12)
|
||||
|
||||
var UpgradeTrustHeight = abi.ChainEpoch(-13)
|
||||
|
||||
var UpgradeNorwegianHeight = abi.ChainEpoch(-14)
|
||||
|
||||
var UpgradeTurboHeight = abi.ChainEpoch(-15)
|
||||
|
||||
var UpgradeHyperdriveHeight = abi.ChainEpoch(-16)
|
||||
var UpgradeChocolateHeight = abi.ChainEpoch(-17)
|
||||
var UpgradeOhSnapHeight = abi.ChainEpoch(-18)
|
||||
var UpgradeSkyrHeight = abi.ChainEpoch(-19)
|
||||
var UpgradeSharkHeight = abi.ChainEpoch(-20)
|
||||
var UpgradeHyggeHeight = abi.ChainEpoch(-21)
|
||||
|
||||
var DrandSchedule = map[abi.ChainEpoch]DrandEnum{
|
||||
0: DrandMainnet,
|
||||
}
|
||||
|
||||
var SupportedProofTypes = []abi.RegisteredSealProof{
|
||||
abi.RegisteredSealProof_StackedDrg512MiBV1,
|
||||
abi.RegisteredSealProof_StackedDrg32GiBV1,
|
||||
abi.RegisteredSealProof_StackedDrg64GiBV1,
|
||||
}
|
||||
var ConsensusMinerMinPower = abi.NewStoragePower(16 << 30)
|
||||
var MinVerifiedDealSize = abi.NewStoragePower(1 << 20)
|
||||
var PreCommitChallengeDelay = abi.ChainEpoch(10)
|
||||
|
||||
func init() {
|
||||
policy.SetSupportedProofTypes(SupportedProofTypes...)
|
||||
policy.SetConsensusMinerMinPower(ConsensusMinerMinPower)
|
||||
policy.SetMinVerifiedDealSize(MinVerifiedDealSize)
|
||||
policy.SetPreCommitChallengeDelay(PreCommitChallengeDelay)
|
||||
|
||||
BuildType = BuildWallabynet
|
||||
SetAddressNetwork(address.Testnet)
|
||||
Devnet = true
|
||||
|
||||
}
|
||||
|
||||
const BlockDelaySecs = uint64(builtin2.EpochDurationSeconds)
|
||||
|
||||
const PropagationDelaySecs = uint64(6)
|
||||
|
||||
// BootstrapPeerThreshold is the minimum number peers we need to track for a sync worker to start
|
||||
const BootstrapPeerThreshold = 2
|
||||
|
||||
// ChainId defines the chain ID used in the Ethereum JSON-RPC endpoint.
|
||||
// As per https://github.com/ethereum-lists/chains
|
||||
const Eip155ChainId = 31415
|
||||
|
||||
var WhitelistedBlock = cid.Undef
|
@ -6,15 +6,13 @@ var CurrentCommit string
|
||||
var BuildType int
|
||||
|
||||
const (
|
||||
BuildDefault = 0
|
||||
BuildMainnet = 0x1
|
||||
Build2k = 0x2
|
||||
BuildDebug = 0x3
|
||||
BuildCalibnet = 0x4
|
||||
BuildInteropnet = 0x5
|
||||
BuildButterflynet = 0x7
|
||||
BuildWallabynet = 0x8
|
||||
BuildHyperspacenet = 0x9
|
||||
BuildDefault = 0
|
||||
BuildMainnet = 0x1
|
||||
Build2k = 0x2
|
||||
BuildDebug = 0x3
|
||||
BuildCalibnet = 0x4
|
||||
BuildInteropnet = 0x5
|
||||
BuildButterflynet = 0x7
|
||||
)
|
||||
|
||||
func BuildTypeString() string {
|
||||
@ -33,10 +31,6 @@ func BuildTypeString() string {
|
||||
return "+interopnet"
|
||||
case BuildButterflynet:
|
||||
return "+butterflynet"
|
||||
case BuildWallabynet:
|
||||
return "+wallabynet"
|
||||
case BuildHyperspacenet:
|
||||
return "+hyperspacenet"
|
||||
default:
|
||||
return "+huh?"
|
||||
}
|
||||
|
@ -20,7 +20,12 @@ import (
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
)
|
||||
|
||||
const indexed uint8 = 0x01
|
||||
func isIndexedValue(b uint8) bool {
|
||||
// currently we mark the full entry as indexed if either the key
|
||||
// or the value are indexed; in the future we will need finer-grained
|
||||
// management of indices
|
||||
return b&(types.EventFlagIndexedKey|types.EventFlagIndexedValue) > 0
|
||||
}
|
||||
|
||||
type EventFilter struct {
|
||||
id types.FilterID
|
||||
@ -100,9 +105,18 @@ func (f *EventFilter) CollectEvents(ctx context.Context, te *TipSetEvents, rever
|
||||
continue
|
||||
}
|
||||
|
||||
entries := make([]types.EventEntry, len(ev.Entries))
|
||||
for i, entry := range ev.Entries {
|
||||
entries[i] = types.EventEntry{
|
||||
Flags: entry.Flags,
|
||||
Key: entry.Key,
|
||||
Value: entry.Value,
|
||||
}
|
||||
}
|
||||
|
||||
// event matches filter, so record it
|
||||
cev := &CollectedEvent{
|
||||
Entries: ev.Entries,
|
||||
Entries: entries,
|
||||
EmitterAddr: addr,
|
||||
EventIdx: evIdx,
|
||||
Reverted: revert,
|
||||
@ -200,7 +214,7 @@ func (f *EventFilter) matchKeys(ees []types.EventEntry) bool {
|
||||
matched := map[string]bool{}
|
||||
for _, ee := range ees {
|
||||
// Skip an entry that is not indexable
|
||||
if ee.Flags&indexed != indexed {
|
||||
if !isIndexedValue(ee.Flags) {
|
||||
continue
|
||||
}
|
||||
|
||||
@ -212,7 +226,7 @@ func (f *EventFilter) matchKeys(ees []types.EventEntry) bool {
|
||||
}
|
||||
|
||||
wantlist, ok := f.keys[keyname]
|
||||
if !ok {
|
||||
if !ok || len(wantlist) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
@ -266,13 +280,13 @@ func (te *TipSetEvents) messages(ctx context.Context) ([]executedMessage, error)
|
||||
}
|
||||
|
||||
type executedMessage struct {
|
||||
msg *types.Message
|
||||
msg types.ChainMsg
|
||||
rct *types.MessageReceipt
|
||||
// events extracted from receipt
|
||||
evs []*types.Event
|
||||
}
|
||||
|
||||
func (e *executedMessage) Message() *types.Message {
|
||||
func (e *executedMessage) Message() types.ChainMsg {
|
||||
return e.msg
|
||||
}
|
||||
|
||||
@ -428,7 +442,7 @@ func (m *EventFilterManager) loadExecutedMessages(ctx context.Context, msgTs, rc
|
||||
ems := make([]executedMessage, len(msgs))
|
||||
|
||||
for i := 0; i < len(msgs); i++ {
|
||||
ems[i].msg = msgs[i].VMMessage()
|
||||
ems[i].msg = msgs[i]
|
||||
|
||||
var rct types.MessageReceipt
|
||||
found, err := arr.Get(uint64(i), &rct)
|
||||
|
@ -1,7 +1,6 @@
|
||||
package filter
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"database/sql"
|
||||
"errors"
|
||||
@ -11,7 +10,6 @@ import (
|
||||
|
||||
"github.com/ipfs/go-cid"
|
||||
_ "github.com/mattn/go-sqlite3"
|
||||
cbg "github.com/whyrusleeping/cbor-gen"
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
@ -153,13 +151,6 @@ func (ei *EventIndex) CollectEvents(ctx context.Context, te *TipSetEvents, rever
|
||||
return xerrors.Errorf("prepare insert entry: %w", err)
|
||||
}
|
||||
|
||||
isIndexedValue := func(b uint8) bool {
|
||||
// currently we mark the full entry as indexed if either the key
|
||||
// or the value are indexed; in the future we will need finer-grained
|
||||
// management of indices
|
||||
return b&(types.EventFlagIndexedKey|types.EventFlagIndexedValue) > 0
|
||||
}
|
||||
|
||||
for msgIdx, em := range ems {
|
||||
for evIdx, ev := range em.Events() {
|
||||
addr, found := addressLookups[ev.Emitter]
|
||||
@ -198,13 +189,12 @@ func (ei *EventIndex) CollectEvents(ctx context.Context, te *TipSetEvents, rever
|
||||
}
|
||||
|
||||
for _, entry := range ev.Entries {
|
||||
value := decodeLogBytes(entry.Value)
|
||||
_, err := stmtEntry.Exec(
|
||||
lastID, // event_id
|
||||
isIndexedValue(entry.Flags), // indexed
|
||||
[]byte{entry.Flags}, // flags
|
||||
entry.Key, // key
|
||||
value, // value
|
||||
entry.Value, // value
|
||||
)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("exec insert entry: %w", err)
|
||||
@ -220,21 +210,6 @@ func (ei *EventIndex) CollectEvents(ctx context.Context, te *TipSetEvents, rever
|
||||
return nil
|
||||
}
|
||||
|
||||
// decodeLogBytes decodes a CBOR-serialized array into its original form.
|
||||
//
|
||||
// This function swallows errors and returns the original array if it failed
|
||||
// to decode.
|
||||
func decodeLogBytes(orig []byte) []byte {
|
||||
if orig == nil {
|
||||
return orig
|
||||
}
|
||||
decoded, err := cbg.ReadByteArray(bytes.NewReader(orig), uint64(len(orig)))
|
||||
if err != nil {
|
||||
return orig
|
||||
}
|
||||
return decoded
|
||||
}
|
||||
|
||||
// PrefillFilter fills a filter's collection of events from the historic index
|
||||
func (ei *EventIndex) PrefillFilter(ctx context.Context, f *EventFilter) error {
|
||||
clauses := []string{}
|
||||
|
@ -13,10 +13,13 @@ import (
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
"github.com/filecoin-project/go-state-types/crypto"
|
||||
|
||||
"github.com/filecoin-project/lotus/api"
|
||||
"github.com/filecoin-project/lotus/chain/messagepool"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
"github.com/filecoin-project/lotus/chain/types/ethtypes"
|
||||
"github.com/filecoin-project/lotus/chain/wallet/key"
|
||||
"github.com/filecoin-project/lotus/node/modules/dtypes"
|
||||
)
|
||||
|
||||
@ -66,15 +69,24 @@ func (ms *MessageSigner) SignMessage(ctx context.Context, msg *types.Message, sp
|
||||
// Sign the message with the nonce
|
||||
msg.Nonce = nonce
|
||||
|
||||
keyInfo, err := ms.wallet.WalletExport(ctx, msg.From)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
sb, err := SigningBytes(msg, key.ActSigType(keyInfo.Type))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
mb, err := msg.ToStorageBlock()
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("serializing message: %w", err)
|
||||
}
|
||||
|
||||
sig, err := ms.wallet.WalletSign(ctx, msg.From, mb.Cid().Bytes(), api.MsgMeta{
|
||||
sig, err := ms.wallet.WalletSign(ctx, msg.From, sb, api.MsgMeta{
|
||||
Type: api.MTChainMsg,
|
||||
Extra: mb.RawData(),
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("failed to sign message: %w, addr=%s", err, msg.From)
|
||||
}
|
||||
@ -187,3 +199,19 @@ func (ms *MessageSigner) SaveNonce(ctx context.Context, addr address.Address, no
|
||||
func (ms *MessageSigner) dstoreKey(addr address.Address) datastore.Key {
|
||||
return datastore.KeyWithNamespaces([]string{dsKeyActorNonce, addr.String()})
|
||||
}
|
||||
|
||||
func SigningBytes(msg *types.Message, sigType crypto.SigType) ([]byte, error) {
|
||||
if sigType == crypto.SigTypeDelegated {
|
||||
txArgs, err := ethtypes.EthTxArgsFromMessage(msg)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("failed to reconstruct eth transaction: %w", err)
|
||||
}
|
||||
rlpEncodedMsg, err := txArgs.ToRlpUnsignedMsg()
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("failed to repack eth rlp message: %w", err)
|
||||
}
|
||||
return rlpEncodedMsg, nil
|
||||
}
|
||||
|
||||
return msg.Cid().Bytes(), nil
|
||||
}
|
||||
|
@ -22,7 +22,7 @@ import (
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
)
|
||||
|
||||
const TIPSETKEY_BACKFILL_RANGE = 2 * build.Finality
|
||||
const TipsetkeyBackfillRange = 2 * build.Finality
|
||||
|
||||
func (cs *ChainStore) UnionStore() bstore.Blockstore {
|
||||
return bstore.Union(cs.stateBlockstore, cs.chainBlockstore)
|
||||
@ -116,7 +116,7 @@ func (cs *ChainStore) Import(ctx context.Context, r io.Reader) (*types.TipSet, e
|
||||
}
|
||||
|
||||
ts := root
|
||||
for i := 0; i < int(TIPSETKEY_BACKFILL_RANGE); i++ {
|
||||
for i := 0; i < int(TipsetkeyBackfillRange); i++ {
|
||||
err = cs.PersistTipset(ctx, ts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -384,7 +384,19 @@ func (cs *ChainStore) PutTipSet(ctx context.Context, ts *types.TipSet) error {
|
||||
if err != nil {
|
||||
return xerrors.Errorf("errored while expanding tipset: %w", err)
|
||||
}
|
||||
log.Debugf("expanded %s into %s\n", ts.Cids(), expanded.Cids())
|
||||
|
||||
if expanded.Key() != ts.Key() {
|
||||
log.Debugf("expanded %s into %s\n", ts.Cids(), expanded.Cids())
|
||||
|
||||
tsBlk, err := expanded.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.MaybeTakeHeavierTipSet(ctx, expanded); err != nil {
|
||||
return xerrors.Errorf("MaybeTakeHeavierTipSet failed in PutTipSet: %w", err)
|
||||
|
@ -12,13 +12,11 @@ import (
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
gocrypto "github.com/filecoin-project/go-crypto"
|
||||
"github.com/filecoin-project/go-state-types/abi"
|
||||
"github.com/filecoin-project/go-state-types/big"
|
||||
builtintypes "github.com/filecoin-project/go-state-types/builtin"
|
||||
typescrypto "github.com/filecoin-project/go-state-types/crypto"
|
||||
|
||||
"github.com/filecoin-project/lotus/build"
|
||||
"github.com/filecoin-project/lotus/chain/actors"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
)
|
||||
|
||||
@ -63,6 +61,7 @@ func EthTxArgsFromMessage(msg *types.Message) (EthTxArgs, error) {
|
||||
to *EthAddress
|
||||
params []byte
|
||||
paramsReader = bytes.NewReader(msg.Params)
|
||||
err error
|
||||
)
|
||||
|
||||
if msg.Version != 0 {
|
||||
@ -72,11 +71,10 @@ func EthTxArgsFromMessage(msg *types.Message) (EthTxArgs, error) {
|
||||
if msg.To == builtintypes.EthereumAddressManagerActorAddr {
|
||||
switch msg.Method {
|
||||
case builtintypes.MethodsEAM.CreateExternal:
|
||||
var create abi.CborBytes
|
||||
if err := create.UnmarshalCBOR(paramsReader); err != nil {
|
||||
return EthTxArgs{}, err
|
||||
params, err = cbg.ReadByteArray(paramsReader, uint64(len(msg.Params)))
|
||||
if err != nil {
|
||||
return EthTxArgs{}, xerrors.Errorf("failed to read params byte array: %w", err)
|
||||
}
|
||||
params = create
|
||||
default:
|
||||
return EthTxArgs{}, fmt.Errorf("unsupported EAM method")
|
||||
}
|
||||
@ -103,11 +101,6 @@ func EthTxArgsFromMessage(msg *types.Message) (EthTxArgs, error) {
|
||||
if err != nil {
|
||||
return EthTxArgs{}, xerrors.Errorf("failed to read params byte array: %w", err)
|
||||
}
|
||||
|
||||
if len(params) == 0 {
|
||||
// Otherwise, we don't get a guaranteed round-trip.
|
||||
return EthTxArgs{}, xerrors.Errorf("cannot invoke contracts with empty parameters from an eth-account")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -115,6 +108,11 @@ func EthTxArgsFromMessage(msg *types.Message) (EthTxArgs, error) {
|
||||
return EthTxArgs{}, xerrors.Errorf("extra data found in params")
|
||||
}
|
||||
|
||||
if len(params) == 0 && msg.Method != builtintypes.MethodSend {
|
||||
// Otherwise, we don't get a guaranteed round-trip.
|
||||
return EthTxArgs{}, xerrors.Errorf("msgs with empty parameters from an eth-account must be Sends (MethodNum: %d)", msg.Method)
|
||||
}
|
||||
|
||||
return EthTxArgs{
|
||||
ChainID: build.Eip155ChainId,
|
||||
Nonce: int(msg.Nonce),
|
||||
@ -143,12 +141,13 @@ func (tx *EthTxArgs) ToUnsignedMessage(from address.Address) (*types.Message, er
|
||||
if len(tx.Input) == 0 {
|
||||
return nil, xerrors.New("cannot call CreateExternal without params")
|
||||
}
|
||||
inputParams := abi.CborBytes(tx.Input)
|
||||
params, err = actors.SerializeParams(&inputParams)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to serialize Create params: %w", err)
|
||||
|
||||
buf := new(bytes.Buffer)
|
||||
if err = cbg.WriteByteArray(buf, tx.Input); err != nil {
|
||||
return nil, xerrors.Errorf("failed to serialize Create params: %w", err)
|
||||
}
|
||||
|
||||
params = buf.Bytes()
|
||||
} else {
|
||||
to, err = tx.To.ToFilecoinAddress()
|
||||
if err != nil {
|
||||
|
@ -36,10 +36,7 @@ var ErrInvalidAddress = errors.New("invalid Filecoin Eth address")
|
||||
type EthUint64 uint64
|
||||
|
||||
func (e EthUint64) MarshalJSON() ([]byte, error) {
|
||||
if e == 0 {
|
||||
return json.Marshal("0x0")
|
||||
}
|
||||
return json.Marshal(fmt.Sprintf("0x%x", e))
|
||||
return json.Marshal(e.Hex())
|
||||
}
|
||||
|
||||
func (e *EthUint64) UnmarshalJSON(b []byte) error {
|
||||
@ -64,6 +61,13 @@ func EthUint64FromHex(s string) (EthUint64, error) {
|
||||
return EthUint64(parsedInt), nil
|
||||
}
|
||||
|
||||
func (e EthUint64) Hex() string {
|
||||
if e == 0 {
|
||||
return "0x0"
|
||||
}
|
||||
return fmt.Sprintf("0x%x", e)
|
||||
}
|
||||
|
||||
// EthBigInt represents a large integer whose zero value serializes to "0x0".
|
||||
type EthBigInt big.Int
|
||||
|
||||
@ -360,14 +364,7 @@ func (h *EthHash) UnmarshalJSON(b []byte) error {
|
||||
}
|
||||
|
||||
func decodeHexString(s string, expectedLen int) ([]byte, error) {
|
||||
// Strip the leading 0x or 0X prefix since hex.DecodeString does not support it.
|
||||
if strings.HasPrefix(s, "0x") || strings.HasPrefix(s, "0X") {
|
||||
s = s[2:]
|
||||
}
|
||||
// Sometimes clients will omit a leading zero in a byte; pad so we can decode correctly.
|
||||
if len(s)%2 == 1 {
|
||||
s = "0" + s
|
||||
}
|
||||
s = handleHexStringPrefix(s)
|
||||
if len(s) != expectedLen*2 {
|
||||
return nil, xerrors.Errorf("expected hex string length sans prefix %d, got %d", expectedLen*2, len(s))
|
||||
}
|
||||
@ -378,6 +375,27 @@ func decodeHexString(s string, expectedLen int) ([]byte, error) {
|
||||
return b, nil
|
||||
}
|
||||
|
||||
func DecodeHexString(s string) ([]byte, error) {
|
||||
s = handleHexStringPrefix(s)
|
||||
b, err := hex.DecodeString(s)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("cannot parse hex value: %w", err)
|
||||
}
|
||||
return b, nil
|
||||
}
|
||||
|
||||
func handleHexStringPrefix(s string) string {
|
||||
// Strip the leading 0x or 0X prefix since hex.DecodeString does not support it.
|
||||
if strings.HasPrefix(s, "0x") || strings.HasPrefix(s, "0X") {
|
||||
s = s[2:]
|
||||
}
|
||||
// Sometimes clients will omit a leading zero in a byte; pad so we can decode correctly.
|
||||
if len(s)%2 == 1 {
|
||||
s = "0" + s
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
func EthHashFromCid(c cid.Cid) (EthHash, error) {
|
||||
return ParseEthHash(c.Hash().HexString()[8:])
|
||||
}
|
||||
|
@ -291,7 +291,10 @@ func DumpActorState(i *ActorRegistry, act *types.Actor, b []byte) (interface{},
|
||||
|
||||
um := actInfo.vmActor.State()
|
||||
if um == nil {
|
||||
// TODO::FVM @arajasek I would like to assert that we have the empty object here
|
||||
if act.Code != EmptyObjectCid {
|
||||
return nil, xerrors.Errorf("actor with code %s should only have empty object (%s) as its Head, instead has %s", act.Code, EmptyObjectCid, act.Head)
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
if err := um.UnmarshalCBOR(bytes.NewReader(b)); err != nil {
|
||||
|
@ -1517,6 +1517,8 @@ func GetAsks(ctx context.Context, api lapi.FullNode) ([]QueriedAsk, error) {
|
||||
}
|
||||
}(miner)
|
||||
}
|
||||
|
||||
wg.Wait()
|
||||
}()
|
||||
|
||||
loop:
|
||||
@ -1590,6 +1592,8 @@ loop:
|
||||
lk.Unlock()
|
||||
}(miner)
|
||||
}
|
||||
|
||||
wg.Wait()
|
||||
}()
|
||||
|
||||
loop2:
|
||||
|
68
cli/evm.go
68
cli/evm.go
@ -38,25 +38,13 @@ var EvmCmd = &cli.Command{
|
||||
}
|
||||
|
||||
var EvmGetInfoCmd = &cli.Command{
|
||||
Name: "stat",
|
||||
Usage: "Print eth/filecoin addrs and code cid",
|
||||
Flags: []cli.Flag{
|
||||
&cli.StringFlag{
|
||||
Name: "filAddr",
|
||||
Usage: "Filecoin address",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "ethAddr",
|
||||
Usage: "Ethereum address",
|
||||
},
|
||||
},
|
||||
Name: "stat",
|
||||
Usage: "Print eth/filecoin addrs and code cid",
|
||||
ArgsUsage: "address",
|
||||
Action: func(cctx *cli.Context) error {
|
||||
|
||||
filAddr := cctx.String("filAddr")
|
||||
ethAddr := cctx.String("ethAddr")
|
||||
|
||||
var faddr address.Address
|
||||
var eaddr ethtypes.EthAddress
|
||||
if cctx.NArg() != 1 {
|
||||
return IncorrectNumArgs(cctx)
|
||||
}
|
||||
|
||||
api, closer, err := GetFullNodeAPI(cctx)
|
||||
if err != nil {
|
||||
@ -65,26 +53,25 @@ var EvmGetInfoCmd = &cli.Command{
|
||||
defer closer()
|
||||
ctx := ReqContext(cctx)
|
||||
|
||||
if filAddr != "" {
|
||||
addr, err := address.NewFromString(filAddr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
eaddr, faddr, err = ethAddrFromFilecoinAddress(ctx, addr, api)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else if ethAddr != "" {
|
||||
eaddr, err = ethtypes.ParseEthAddress(ethAddr)
|
||||
if err != nil {
|
||||
return err
|
||||
addrString := cctx.Args().Get(0)
|
||||
|
||||
var faddr address.Address
|
||||
var eaddr ethtypes.EthAddress
|
||||
addr, err := address.NewFromString(addrString)
|
||||
if err != nil { // This isn't a filecoin address
|
||||
eaddr, err = ethtypes.ParseEthAddress(addrString)
|
||||
if err != nil { // This isn't an Eth address either
|
||||
return xerrors.Errorf("address is not a filecoin or eth address")
|
||||
}
|
||||
faddr, err = eaddr.ToFilecoinAddress()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
return xerrors.Errorf("Neither filAddr nor ethAddr specified")
|
||||
eaddr, faddr, err = ethAddrFromFilecoinAddress(ctx, addr, api)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
actor, err := api.StateGetActor(ctx, faddr, types.EmptyTSK)
|
||||
@ -97,7 +84,6 @@ var EvmGetInfoCmd = &cli.Command{
|
||||
fmt.Println("Code cid: ", actor.Code.String())
|
||||
|
||||
return nil
|
||||
|
||||
},
|
||||
}
|
||||
|
||||
@ -121,7 +107,7 @@ var EvmCallSimulateCmd = &cli.Command{
|
||||
return err
|
||||
}
|
||||
|
||||
params, err := hex.DecodeString(cctx.Args().Get(2))
|
||||
params, err := ethtypes.DecodeHexString(cctx.Args().Get(2))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -165,7 +151,7 @@ var EvmGetContractAddress = &cli.Command{
|
||||
return err
|
||||
}
|
||||
|
||||
salt, err := hex.DecodeString(cctx.Args().Get(1))
|
||||
salt, err := ethtypes.DecodeHexString(cctx.Args().Get(1))
|
||||
if err != nil {
|
||||
return xerrors.Errorf("Could not decode salt: %w", err)
|
||||
}
|
||||
@ -184,7 +170,7 @@ var EvmGetContractAddress = &cli.Command{
|
||||
|
||||
return err
|
||||
}
|
||||
contract, err := hex.DecodeString(string(contractHex))
|
||||
contract, err := ethtypes.DecodeHexString(string(contractHex))
|
||||
if err != nil {
|
||||
return xerrors.Errorf("Could not decode contract file: %w", err)
|
||||
}
|
||||
@ -233,7 +219,7 @@ var EvmDeployCmd = &cli.Command{
|
||||
return xerrors.Errorf("failed to read contract: %w", err)
|
||||
}
|
||||
if cctx.Bool("hex") {
|
||||
contract, err = hex.DecodeString(string(contract))
|
||||
contract, err = ethtypes.DecodeHexString(string(contract))
|
||||
if err != nil {
|
||||
return xerrors.Errorf("failed to decode contract: %w", err)
|
||||
}
|
||||
@ -345,8 +331,8 @@ var EvmInvokeCmd = &cli.Command{
|
||||
defer closer()
|
||||
ctx := ReqContext(cctx)
|
||||
|
||||
if argc := cctx.Args().Len(); argc < 2 || argc > 3 {
|
||||
return xerrors.Errorf("must pass the address, entry point and (optionally) input data")
|
||||
if argc := cctx.Args().Len(); argc != 2 {
|
||||
return xerrors.Errorf("must pass the address and calldata")
|
||||
}
|
||||
|
||||
addr, err := address.NewFromString(cctx.Args().Get(0))
|
||||
@ -355,7 +341,7 @@ var EvmInvokeCmd = &cli.Command{
|
||||
}
|
||||
|
||||
var calldata []byte
|
||||
calldata, err = hex.DecodeString(cctx.Args().Get(2))
|
||||
calldata, err = ethtypes.DecodeHexString(cctx.Args().Get(1))
|
||||
if err != nil {
|
||||
return xerrors.Errorf("decoding hex input data: %w", err)
|
||||
}
|
||||
@ -388,7 +374,7 @@ var EvmInvokeCmd = &cli.Command{
|
||||
To: addr,
|
||||
From: fromAddr,
|
||||
Value: val,
|
||||
Method: abi.MethodNum(2),
|
||||
Method: builtintypes.MethodsEVM.InvokeContract,
|
||||
Params: calldata,
|
||||
}
|
||||
|
||||
|
17
cli/send.go
17
cli/send.go
@ -13,6 +13,7 @@ import (
|
||||
|
||||
"github.com/filecoin-project/lotus/chain/actors/builtin"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
"github.com/filecoin-project/lotus/chain/types/ethtypes"
|
||||
)
|
||||
|
||||
var sendCmd = &cli.Command{
|
||||
@ -24,6 +25,10 @@ var sendCmd = &cli.Command{
|
||||
Name: "from",
|
||||
Usage: "optionally specify the account to send funds from",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "from-eth-addr",
|
||||
Usage: "optionally specify the eth addr to send funds from",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "gas-premium",
|
||||
Usage: "specify gas price to use in AttoFIL",
|
||||
@ -98,6 +103,18 @@ var sendCmd = &cli.Command{
|
||||
}
|
||||
|
||||
params.From = addr
|
||||
} else if from := cctx.String("from-eth-addr"); from != "" {
|
||||
eaddr, err := ethtypes.ParseEthAddress(from)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
faddr, err := eaddr.ToFilecoinAddress()
|
||||
if err != nil {
|
||||
fmt.Println("error on conversion to faddr")
|
||||
return err
|
||||
}
|
||||
fmt.Println("f4 addr: ", faddr)
|
||||
params.From = faddr
|
||||
}
|
||||
|
||||
if cctx.IsSet("gas-premium") {
|
||||
|
@ -776,7 +776,9 @@ var StateGetActorCmd = &cli.Command{
|
||||
fmt.Printf("Nonce:\t\t%d\n", a.Nonce)
|
||||
fmt.Printf("Code:\t\t%s (%s)\n", a.Code, strtype)
|
||||
fmt.Printf("Head:\t\t%s\n", a.Head)
|
||||
fmt.Printf("Delegated address:\t\t%s\n", a.Address)
|
||||
if a.Address != nil {
|
||||
fmt.Printf("Delegated address:\t\t%s\n", a.Address)
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
|
@ -291,6 +291,8 @@
|
||||
* [WalletSignMessage](#WalletSignMessage)
|
||||
* [WalletValidateAddress](#WalletValidateAddress)
|
||||
* [WalletVerify](#WalletVerify)
|
||||
* [Web3](#Web3)
|
||||
* [Web3ClientVersion](#Web3ClientVersion)
|
||||
##
|
||||
|
||||
|
||||
@ -9207,3 +9209,16 @@ Inputs:
|
||||
|
||||
Response: `true`
|
||||
|
||||
## Web3
|
||||
|
||||
|
||||
### Web3ClientVersion
|
||||
Returns the client version
|
||||
|
||||
|
||||
Perms: read
|
||||
|
||||
Inputs: `null`
|
||||
|
||||
Response: `"string value"`
|
||||
|
||||
|
@ -181,15 +181,16 @@ CATEGORY:
|
||||
BASIC
|
||||
|
||||
OPTIONS:
|
||||
--force Deprecated: use global 'force-send' (default: false)
|
||||
--from value optionally specify the account to send funds from
|
||||
--gas-feecap value specify gas fee cap to use in AttoFIL (default: "0")
|
||||
--gas-limit value specify gas limit (default: 0)
|
||||
--gas-premium value specify gas price to use in AttoFIL (default: "0")
|
||||
--method value specify method to invoke (default: 0)
|
||||
--nonce value specify the nonce to use (default: 0)
|
||||
--params-hex value specify invocation parameters in hex
|
||||
--params-json value specify invocation parameters in json
|
||||
--force Deprecated: use global 'force-send' (default: false)
|
||||
--from value optionally specify the account to send funds from
|
||||
--from-eth-addr value optionally specify the eth addr to send funds from
|
||||
--gas-feecap value specify gas fee cap to use in AttoFIL (default: "0")
|
||||
--gas-limit value specify gas limit (default: 0)
|
||||
--gas-premium value specify gas price to use in AttoFIL (default: "0")
|
||||
--method value specify method to invoke (default: 0)
|
||||
--nonce value specify the nonce to use (default: 0)
|
||||
--params-hex value specify invocation parameters in hex
|
||||
--params-json value specify invocation parameters in json
|
||||
|
||||
```
|
||||
|
||||
@ -2595,11 +2596,10 @@ NAME:
|
||||
lotus evm stat - Print eth/filecoin addrs and code cid
|
||||
|
||||
USAGE:
|
||||
lotus evm stat [command options] [arguments...]
|
||||
lotus evm stat [command options] address
|
||||
|
||||
OPTIONS:
|
||||
--ethAddr value Ethereum address
|
||||
--filAddr value Filecoin address
|
||||
--help, -h show help (default: false)
|
||||
|
||||
```
|
||||
|
||||
|
@ -293,63 +293,13 @@
|
||||
#Tracing = false
|
||||
|
||||
|
||||
[ActorEvent]
|
||||
# EnableRealTimeFilterAPI enables APIs that can create and query filters for actor events as they are emitted.
|
||||
#
|
||||
# type: bool
|
||||
# env var: LOTUS_ACTOREVENT_ENABLEREALTIMEFILTERAPI
|
||||
#EnableRealTimeFilterAPI = false
|
||||
|
||||
# EnableHistoricFilterAPI enables APIs that can create and query filters for actor events that occurred in the past.
|
||||
# A queryable index of events will be maintained.
|
||||
#
|
||||
# type: bool
|
||||
# env var: LOTUS_ACTOREVENT_ENABLEHISTORICFILTERAPI
|
||||
#EnableHistoricFilterAPI = false
|
||||
|
||||
# FilterTTL specifies the time to live for actor event filters. Filters that haven't been accessed longer than
|
||||
# this time become eligible for automatic deletion.
|
||||
#
|
||||
# type: Duration
|
||||
# env var: LOTUS_ACTOREVENT_FILTERTTL
|
||||
#FilterTTL = "24h0m0s"
|
||||
|
||||
# MaxFilters specifies the maximum number of filters that may exist at any one time.
|
||||
#
|
||||
# type: int
|
||||
# env var: LOTUS_ACTOREVENT_MAXFILTERS
|
||||
#MaxFilters = 100
|
||||
|
||||
# MaxFilterResults specifies the maximum number of results that can be accumulated by an actor event filter.
|
||||
#
|
||||
# type: int
|
||||
# env var: LOTUS_ACTOREVENT_MAXFILTERRESULTS
|
||||
#MaxFilterResults = 10000
|
||||
|
||||
# MaxFilterHeightRange specifies the maximum range of heights that can be used in a filter (to avoid querying
|
||||
# the entire chain)
|
||||
#
|
||||
# type: uint64
|
||||
# env var: LOTUS_ACTOREVENT_MAXFILTERHEIGHTRANGE
|
||||
#MaxFilterHeightRange = 2880
|
||||
|
||||
# ActorEventDatabasePath is the full path to a sqlite database that will be used to index actor events to
|
||||
# support the historic filter APIs. If the database does not exist it will be created. The directory containing
|
||||
# the database must already exist and be writeable. If a relative path is provided here, sqlite treats it as
|
||||
# relative to the CWD (current working directory).
|
||||
#
|
||||
# type: string
|
||||
# env var: LOTUS_ACTOREVENT_ACTOREVENTDATABASEPATH
|
||||
#ActorEventDatabasePath = ""
|
||||
|
||||
|
||||
[Fevm]
|
||||
# EnableEthHashToFilecoinCidMapping enables storing a mapping of eth transaction hashes to filecoin message Cids
|
||||
# You will not be able to look up ethereum transactions by their hash if this is disabled.
|
||||
# EnableEthRPC enables eth_ rpc, and enables storing a mapping of eth transaction hashes to filecoin message Cids.
|
||||
# This will also enable the RealTimeFilterAPI and HistoricFilterAPI by default, but they can be disabled by config options above.
|
||||
#
|
||||
# type: bool
|
||||
# env var: LOTUS_FEVM_ENABLEETHHASHTOFILECOINCIDMAPPING
|
||||
#EnableEthHashToFilecoinCidMapping = false
|
||||
# env var: LOTUS_FEVM_ENABLEETHRPC
|
||||
#EnableEthRPC = false
|
||||
|
||||
# EthTxHashMappingLifetimeDays the transaction hash lookup database will delete mappings that have been stored for more than x days
|
||||
# Set to 0 to keep all mappings
|
||||
@ -358,4 +308,56 @@
|
||||
# env var: LOTUS_FEVM_ETHTXHASHMAPPINGLIFETIMEDAYS
|
||||
#EthTxHashMappingLifetimeDays = 0
|
||||
|
||||
[Fevm.Events]
|
||||
# EnableEthRPC enables APIs that
|
||||
# DisableRealTimeFilterAPI will disable the RealTimeFilterAPI that can create and query filters for actor events as they are emitted.
|
||||
# The API is enabled when EnableEthRPC is true, but can be disabled selectively with this flag.
|
||||
#
|
||||
# type: bool
|
||||
# env var: LOTUS_FEVM_EVENTS_DISABLEREALTIMEFILTERAPI
|
||||
#DisableRealTimeFilterAPI = false
|
||||
|
||||
# DisableHistoricFilterAPI will disable the HistoricFilterAPI that can create and query filters for actor events
|
||||
# that occurred in the past. HistoricFilterAPI maintains a queryable index of events.
|
||||
# The API is enabled when EnableEthRPC is true, but can be disabled selectively with this flag.
|
||||
#
|
||||
# type: bool
|
||||
# env var: LOTUS_FEVM_EVENTS_DISABLEHISTORICFILTERAPI
|
||||
#DisableHistoricFilterAPI = false
|
||||
|
||||
# FilterTTL specifies the time to live for actor event filters. Filters that haven't been accessed longer than
|
||||
# this time become eligible for automatic deletion.
|
||||
#
|
||||
# type: Duration
|
||||
# env var: LOTUS_FEVM_EVENTS_FILTERTTL
|
||||
#FilterTTL = "24h0m0s"
|
||||
|
||||
# MaxFilters specifies the maximum number of filters that may exist at any one time.
|
||||
#
|
||||
# type: int
|
||||
# env var: LOTUS_FEVM_EVENTS_MAXFILTERS
|
||||
#MaxFilters = 100
|
||||
|
||||
# MaxFilterResults specifies the maximum number of results that can be accumulated by an actor event filter.
|
||||
#
|
||||
# type: int
|
||||
# env var: LOTUS_FEVM_EVENTS_MAXFILTERRESULTS
|
||||
#MaxFilterResults = 10000
|
||||
|
||||
# MaxFilterHeightRange specifies the maximum range of heights that can be used in a filter (to avoid querying
|
||||
# the entire chain)
|
||||
#
|
||||
# type: uint64
|
||||
# env var: LOTUS_FEVM_EVENTS_MAXFILTERHEIGHTRANGE
|
||||
#MaxFilterHeightRange = 2880
|
||||
|
||||
# DatabasePath is the full path to a sqlite database that will be used to index actor events to
|
||||
# support the historic filter APIs. If the database does not exist it will be created. The directory containing
|
||||
# the database must already exist and be writeable. If a relative path is provided here, sqlite treats it as
|
||||
# relative to the CWD (current working directory).
|
||||
#
|
||||
# type: string
|
||||
# env var: LOTUS_FEVM_EVENTS_DATABASEPATH
|
||||
#DatabasePath = ""
|
||||
|
||||
|
||||
|
1
itests/contracts/EventMatrix.hex
Normal file
1
itests/contracts/EventMatrix.hex
Normal file
@ -0,0 +1 @@
|
||||
608060405234801561001057600080fd5b506105eb806100206000396000f3fe608060405234801561001057600080fd5b50600436106100a95760003560e01c8063c755553811610071578063c755553814610198578063cbfc3b58146101c6578063cc6f8faf14610212578063cd5b6c3d14610254578063e2a614731461028c578063fb62b28b146102d8576100a9565b80630919b8be146100ae5780636199074d146100e657806366eef3461461012857806375091b1f14610132578063a63ae81a1461016a575b600080fd5b6100e4600480360360408110156100c457600080fd5b81019080803590602001909291908035906020019092919050505061031a565b005b610126600480360360608110156100fc57600080fd5b8101908080359060200190929190803590602001909291908035906020019092919050505061035d565b005b610130610391565b005b6101686004803603604081101561014857600080fd5b8101908080359060200190929190803590602001909291905050506103bf565b005b6101966004803603602081101561018057600080fd5b81019080803590602001909291905050506103fb565b005b6101c4600480360360208110156101ae57600080fd5b8101908080359060200190929190505050610435565b005b610210600480360360808110156101dc57600080fd5b8101908080359060200190929190803590602001909291908035906020019092919080359060200190929190505050610465565b005b6102526004803603606081101561022857600080fd5b810190808035906020019092919080359060200190929190803590602001909291905050506104ba565b005b61028a6004803603604081101561026a57600080fd5b8101908080359060200190929190803590602001909291905050506104f8565b005b6102d6600480360360808110156102a257600080fd5b810190808035906020019092919080359060200190929190803590602001909291908035906020019092919050505061052a565b005b610318600480360360608110156102ee57600080fd5b8101908080359060200190929190803590602001909291908035906020019092919050505061056a565b005b7f5469c6b769315f5668523937f05ca07d4cc87849432bc5f5907f1d90fa73b9f98282604051808381526020018281526020019250505060405180910390a15050565b8082847fb89dabcdb7ff41f1794c0da92f65ece6c19b6b0caeac5407b2a721efe27c080460405160405180910390a4505050565b7fc3f6f1c76bd4e74ee5782052b0b4f8bd5c50b86c3c5a2f52638e03066e50a91b60405160405180910390a1565b817f6709824ebe5f6e620ca3f4b02a3428e8ce2dc97c550816eaeeb3a342b214bd85826040518082815260200191505060405180910390a25050565b7fc804e53d6048af1b3e6a352e246d5f3864fea9d635ace499e023a58c383b3a88816040518082815260200191505060405180910390a150565b807f44a227a31429ab5eb00daf6611c6422f10571619f2267e0e149e9ebe6d2a5d0560405160405180910390a250565b7f28d45631a87b2a52a9625f8520fa37ff8c4d926cdf17042e241985da5cb7b850848484846040518085815260200184815260200183815260200182815260200194505050505060405180910390a150505050565b81837fcd5fe5fbc1d27b90036997224cea7aa565e3779622867265081f636b3a5ccb08836040518082815260200191505060405180910390a3505050565b80827f232f09cef3babc26e58d1cc1346c0a8bc626ffe600c9605b5d747783eda484a760405160405180910390a35050565b8183857f812e73dbcf7e267f27ecb1383bfc902a6650b41b6e7d03ac265108c369673d95846040518082815260200191505060405180910390a450505050565b7fd4d143faaf60340ad98e1f2c96fc26f5695834c21b5200edad339ee7e9a372cc83838360405180848152602001838152602001828152602001935050505060405180910390a150505056fea265627a7a72315820954561fde80ab925299e0a9f3356b01f64fb1976dd335ac2ebd9367441e29f0564736f6c63430005110032
|
51
itests/contracts/EventMatrix.sol
Normal file
51
itests/contracts/EventMatrix.sol
Normal file
@ -0,0 +1,51 @@
|
||||
pragma solidity ^0.5.0;
|
||||
|
||||
contract EventMatrix {
|
||||
event EventZeroData();
|
||||
event EventOneData(uint a);
|
||||
event EventTwoData(uint a, uint b);
|
||||
event EventThreeData(uint a, uint b, uint c);
|
||||
event EventFourData(uint a, uint b, uint c, uint d);
|
||||
|
||||
event EventOneIndexed(uint indexed a);
|
||||
event EventTwoIndexed(uint indexed a, uint indexed b);
|
||||
event EventThreeIndexed(uint indexed a, uint indexed b, uint indexed c);
|
||||
|
||||
event EventOneIndexedWithData(uint indexed a, uint b);
|
||||
event EventTwoIndexedWithData(uint indexed a, uint indexed b, uint c);
|
||||
event EventThreeIndexedWithData(uint indexed a, uint indexed b, uint indexed c, uint d);
|
||||
|
||||
function logEventZeroData() public {
|
||||
emit EventZeroData();
|
||||
}
|
||||
function logEventOneData(uint a) public {
|
||||
emit EventOneData(a);
|
||||
}
|
||||
function logEventTwoData(uint a, uint b) public {
|
||||
emit EventTwoData(a,b);
|
||||
}
|
||||
function logEventThreeData(uint a, uint b, uint c) public {
|
||||
emit EventThreeData(a,b,c);
|
||||
}
|
||||
function logEventFourData(uint a, uint b, uint c, uint d) public {
|
||||
emit EventFourData(a,b,c,d);
|
||||
}
|
||||
function logEventOneIndexed(uint a) public {
|
||||
emit EventOneIndexed(a);
|
||||
}
|
||||
function logEventTwoIndexed(uint a, uint b) public {
|
||||
emit EventTwoIndexed(a,b);
|
||||
}
|
||||
function logEventThreeIndexed(uint a, uint b, uint c) public {
|
||||
emit EventThreeIndexed(a,b,c);
|
||||
}
|
||||
function logEventOneIndexedWithData(uint a, uint b) public {
|
||||
emit EventOneIndexedWithData(a,b);
|
||||
}
|
||||
function logEventTwoIndexedWithData(uint a, uint b, uint c) public {
|
||||
emit EventTwoIndexedWithData(a,b,c);
|
||||
}
|
||||
function logEventThreeIndexedWithData(uint a, uint b, uint c, uint d) public {
|
||||
emit EventThreeIndexedWithData(a,b,c,d);
|
||||
}
|
||||
}
|
1
itests/contracts/RecCall.hex
Normal file
1
itests/contracts/RecCall.hex
Normal file
@ -0,0 +1 @@
|
||||
608060405234801561001057600080fd5b5061025b806100206000396000f3fe60806040526004361061001e5760003560e01c8063cb7786d714610023575b600080fd5b61003d60048036038101906100389190610129565b61003f565b005b600083036100d15760008111156100cc573073ffffffffffffffffffffffffffffffffffffffff1663cb7786d7838460018561007b91906101ab565b6040518463ffffffff1660e01b8152600401610099939291906101ee565b600060405180830381600087803b1580156100b357600080fd5b505af11580156100c7573d6000803e3d6000fd5b505050505b6100e9565b6100e86001846100e191906101ab565b838361003f565b5b505050565b600080fd5b6000819050919050565b610106816100f3565b811461011157600080fd5b50565b600081359050610123816100fd565b92915050565b600080600060608486031215610142576101416100ee565b5b600061015086828701610114565b935050602061016186828701610114565b925050604061017286828701610114565b9150509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60006101b6826100f3565b91506101c1836100f3565b92508282039050818111156101d9576101d861017c565b5b92915050565b6101e8816100f3565b82525050565b600060608201905061020360008301866101df565b61021060208301856101df565b61021d60408301846101df565b94935050505056fea26469706673582212209a21ff59c642e2970917c07bf498271c2a6df8e3929677952c0c2d8031db15cc64736f6c63430008110033
|
16
itests/contracts/RecCall.sol
Normal file
16
itests/contracts/RecCall.sol
Normal file
@ -0,0 +1,16 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.8.17;
|
||||
|
||||
contract StackRecCall {
|
||||
function exec1(uint256 n, uint256 m, uint256 r) public payable {
|
||||
if(n == 0) {
|
||||
if(r > 0) {
|
||||
StackRecCall(address(this)).exec1(m, m, r-1);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
exec1(n-1, m, r);
|
||||
}
|
||||
}
|
1
itests/contracts/StackFunc.hex
Normal file
1
itests/contracts/StackFunc.hex
Normal file
@ -0,0 +1 @@
|
||||
608060405234801561001057600080fd5b50610162806100206000396000f3fe60806040526004361061001e5760003560e01c8063c38e07dd14610023575b600080fd5b61003d6004803603810190610038919061009c565b61003f565b005b600081031561005e5761005d60018261005891906100f8565b61003f565b5b50565b600080fd5b6000819050919050565b61007981610066565b811461008457600080fd5b50565b60008135905061009681610070565b92915050565b6000602082840312156100b2576100b1610061565b5b60006100c084828501610087565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061010382610066565b915061010e83610066565b9250828203905081811115610126576101256100c9565b5b9291505056fea2646970667358221220ee8f18bfd33b1e0156cfe68e9071dd32960b370c7e63ec53c62dd48e28cb5d3b64736f6c63430008110033
|
12
itests/contracts/StackFunc.sol
Normal file
12
itests/contracts/StackFunc.sol
Normal file
@ -0,0 +1,12 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.8.17;
|
||||
|
||||
contract StackSelf {
|
||||
function exec1(uint256 n) public payable {
|
||||
if(n == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
exec1(n-1);
|
||||
}
|
||||
}
|
47
itests/contracts/events.asm
Normal file
47
itests/contracts/events.asm
Normal file
@ -0,0 +1,47 @@
|
||||
# https://github.com/filecoin-project/builtin-actors/blob/b1ba61053de2ceaddd5116e87823d20a8f5e38d7/actors/evm/tests/events.rs
|
||||
# method dispatch:
|
||||
# - 0x00000000 -> log_zero_data
|
||||
# - 0x00000001 -> log_zero_nodata
|
||||
# - 0x00000002 -> log_four_data
|
||||
%dispatch_begin()
|
||||
%dispatch(0x00, log_zero_data)
|
||||
%dispatch(0x01, log_zero_nodata)
|
||||
%dispatch(0x02, log_four_data)
|
||||
%dispatch_end()
|
||||
#### log a zero topic event with data
|
||||
log_zero_data:
|
||||
jumpdest
|
||||
push8 0x1122334455667788
|
||||
push1 0x00
|
||||
mstore
|
||||
push1 0x08
|
||||
push1 0x18 ## index 24 into memory as mstore writes a full word
|
||||
log0
|
||||
push1 0x00
|
||||
push1 0x00
|
||||
return
|
||||
#### log a zero topic event with no data
|
||||
log_zero_nodata:
|
||||
jumpdest
|
||||
push1 0x00
|
||||
push1 0x00
|
||||
log0
|
||||
push1 0x00
|
||||
push1 0x00
|
||||
return
|
||||
#### log a four topic event with data
|
||||
log_four_data:
|
||||
jumpdest
|
||||
push8 0x1122334455667788
|
||||
push1 0x00
|
||||
mstore
|
||||
push4 0x4444
|
||||
push3 0x3333
|
||||
push2 0x2222
|
||||
push2 0x1111
|
||||
push1 0x08
|
||||
push1 0x18 ## index 24 into memory as mstore writes a full word
|
||||
log4
|
||||
push1 0x00
|
||||
push1 0x00
|
||||
return
|
@ -33,7 +33,7 @@ func TestDealPadding(t *testing.T) {
|
||||
dh := kit.NewDealHarness(t, client, miner, miner)
|
||||
|
||||
ctx := context.Background()
|
||||
client.WaitTillChain(ctx, kit.BlockMinedBy(miner.ActorAddr))
|
||||
client.WaitTillChain(ctx, kit.BlocksMinedByAll(miner.ActorAddr))
|
||||
|
||||
// Create a random file, would originally be a 256-byte sector
|
||||
res, inFile := client.CreateImportFile(ctx, 1, 200)
|
||||
|
@ -52,7 +52,7 @@ func TestFirstDealEnablesMining(t *testing.T) {
|
||||
providerMined := make(chan struct{})
|
||||
|
||||
go func() {
|
||||
_ = client.WaitTillChain(ctx, kit.BlockMinedBy(provider.ActorAddr))
|
||||
_ = client.WaitTillChain(ctx, kit.BlocksMinedByAll(provider.ActorAddr))
|
||||
close(providerMined)
|
||||
}()
|
||||
|
||||
|
@ -11,6 +11,8 @@ import (
|
||||
|
||||
"github.com/filecoin-project/go-state-types/abi"
|
||||
"github.com/filecoin-project/go-state-types/big"
|
||||
builtin2 "github.com/filecoin-project/go-state-types/builtin"
|
||||
"github.com/filecoin-project/go-state-types/builtin/v10/eam"
|
||||
"github.com/filecoin-project/go-state-types/exitcode"
|
||||
|
||||
"github.com/filecoin-project/lotus/api"
|
||||
@ -313,3 +315,51 @@ func TestEthAccountAbstractionFailsFromEvmActor(t *testing.T) {
|
||||
require.Error(t, err, "expected gas estimation to fail")
|
||||
require.Contains(t, err.Error(), "SysErrSenderInvalid")
|
||||
}
|
||||
|
||||
func TestEthAccountManagerPermissions(t *testing.T) {
|
||||
kit.QuietMiningLogs()
|
||||
|
||||
client, _, ens := kit.EnsembleMinimal(t, kit.MockProofs(), kit.ThroughRPC())
|
||||
ens.InterconnectAll().BeginMining(10 * time.Millisecond)
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
|
||||
defer cancel()
|
||||
|
||||
// setup f1/f3/f4 accounts
|
||||
|
||||
wsp, err := client.WalletNew(ctx, types.KTSecp256k1)
|
||||
require.NoError(t, err)
|
||||
|
||||
wbl, err := client.WalletNew(ctx, types.KTBLS)
|
||||
require.NoError(t, err)
|
||||
|
||||
wdl, err := client.WalletNew(ctx, types.KTDelegated)
|
||||
require.NoError(t, err)
|
||||
|
||||
def := client.DefaultKey.Address
|
||||
|
||||
// send some funds
|
||||
client.ExpectSend(ctx, def, wsp, types.FromFil(10), "")
|
||||
client.ExpectSend(ctx, def, wbl, types.FromFil(10), "")
|
||||
client.ExpectSend(ctx, def, wdl, types.FromFil(10), "")
|
||||
require.NoError(t, err)
|
||||
|
||||
// make sure that EAM only allows CreateExternal to be called by accounts
|
||||
client.ExpectSend(ctx, wsp, builtin2.EthereumAddressManagerActorAddr, big.Zero(), "not one of supported (18)", client.MakeSendCall(builtin2.MethodsEAM.Create, &eam.CreateParams{Nonce: 0}))
|
||||
client.ExpectSend(ctx, wbl, builtin2.EthereumAddressManagerActorAddr, big.Zero(), "not one of supported (18)", client.MakeSendCall(builtin2.MethodsEAM.Create, &eam.CreateParams{Nonce: 0}))
|
||||
client.ExpectSend(ctx, wdl, builtin2.EthereumAddressManagerActorAddr, big.Zero(), "not one of supported (18)", client.MakeSendCall(builtin2.MethodsEAM.Create, &eam.CreateParams{Nonce: 0}))
|
||||
|
||||
client.ExpectSend(ctx, wsp, builtin2.EthereumAddressManagerActorAddr, big.Zero(), "not one of supported (18)", client.MakeSendCall(builtin2.MethodsEAM.Create2, &eam.Create2Params{}))
|
||||
client.ExpectSend(ctx, wbl, builtin2.EthereumAddressManagerActorAddr, big.Zero(), "not one of supported (18)", client.MakeSendCall(builtin2.MethodsEAM.Create2, &eam.Create2Params{}))
|
||||
client.ExpectSend(ctx, wdl, builtin2.EthereumAddressManagerActorAddr, big.Zero(), "not one of supported (18)", client.MakeSendCall(builtin2.MethodsEAM.Create2, &eam.Create2Params{}))
|
||||
|
||||
contractHex, err := os.ReadFile("contracts/SimpleCoin.hex")
|
||||
require.NoError(t, err)
|
||||
contract, err := hex.DecodeString(string(contractHex))
|
||||
require.NoError(t, err)
|
||||
contractParams := abi.CborBytes(contract)
|
||||
|
||||
client.ExpectSend(ctx, wsp, builtin2.EthereumAddressManagerActorAddr, big.Zero(), "", client.MakeSendCall(builtin2.MethodsEAM.CreateExternal, &contractParams))
|
||||
client.ExpectSend(ctx, wbl, builtin2.EthereumAddressManagerActorAddr, big.Zero(), "", client.MakeSendCall(builtin2.MethodsEAM.CreateExternal, &contractParams))
|
||||
client.ExpectSend(ctx, wdl, builtin2.EthereumAddressManagerActorAddr, big.Zero(), "", client.MakeSendCall(builtin2.MethodsEAM.CreateExternal, &contractParams))
|
||||
}
|
||||
|
65
itests/eth_block_hash_test.go
Normal file
65
itests/eth_block_hash_test.go
Normal file
@ -0,0 +1,65 @@
|
||||
package itests
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/filecoin-project/go-state-types/abi"
|
||||
|
||||
"github.com/filecoin-project/lotus/itests/kit"
|
||||
)
|
||||
|
||||
// TestEthBlockHashesCorrect_MultiBlockTipset validates that blocks retrieved through
|
||||
// EthGetBlockByNumber are identical to blocks retrieved through
|
||||
// EthGetBlockByHash, when using the block hash returned by the former.
|
||||
//
|
||||
// Specifically, it checks the system behaves correctly with multiblock tipsets.
|
||||
//
|
||||
// Catches regressions around https://github.com/filecoin-project/lotus/issues/10061.
|
||||
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
|
||||
n1, m1, m2, ens := kit.EnsembleOneTwo(t,
|
||||
kit.MockProofs(),
|
||||
kit.ThroughRPC(),
|
||||
)
|
||||
ens.InterconnectAll().BeginMining(blocktime)
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
|
||||
n1.WaitTillChain(ctx, kit.HeightAtLeast(abi.ChainEpoch(25)))
|
||||
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)
|
||||
n2.WaitTillChain(ctx, kit.BlocksMinedByAll(m1.ActorAddr, m2.ActorAddr))
|
||||
defer cancel()
|
||||
|
||||
head, err := n2.ChainHead(context.Background())
|
||||
require.NoError(t, err)
|
||||
|
||||
// let the chain run a little bit longer to minimise the chance of reorgs
|
||||
n2.WaitTillChain(ctx, kit.HeightAtLeast(head.Height()+50))
|
||||
|
||||
head, err = n2.ChainHead(context.Background())
|
||||
require.NoError(t, err)
|
||||
|
||||
for i := 1; i <= int(head.Height()); i++ {
|
||||
hex := fmt.Sprintf("0x%x", i)
|
||||
|
||||
ethBlockA, err := n2.EthGetBlockByNumber(ctx, hex, true)
|
||||
require.NoError(t, err)
|
||||
|
||||
ethBlockB, err := n2.EthGetBlockByHash(ctx, ethBlockA.Hash, true)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, ethBlockA, ethBlockB)
|
||||
}
|
||||
}
|
@ -20,7 +20,6 @@ import (
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
"github.com/filecoin-project/lotus/chain/types/ethtypes"
|
||||
"github.com/filecoin-project/lotus/itests/kit"
|
||||
"github.com/filecoin-project/lotus/node/config"
|
||||
)
|
||||
|
||||
// TestDeployment smoke tests the deployment of a contract via the
|
||||
@ -36,13 +35,7 @@ func TestDeployment(t *testing.T) {
|
||||
client, _, ens := kit.EnsembleMinimal(
|
||||
t,
|
||||
kit.MockProofs(),
|
||||
kit.ThroughRPC(),
|
||||
kit.WithCfgOpt(func(cfg *config.FullNode) error {
|
||||
cfg.ActorEvent.EnableRealTimeFilterAPI = true
|
||||
return nil
|
||||
}),
|
||||
kit.EthTxHashLookup(),
|
||||
)
|
||||
kit.ThroughRPC())
|
||||
ens.InterconnectAll().BeginMining(blockTime)
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
|
||||
@ -100,6 +93,7 @@ func TestDeployment(t *testing.T) {
|
||||
|
||||
mpoolTx, err := client.EthGetTransactionByHash(ctx, &hash)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, mpoolTx)
|
||||
|
||||
// require that the hashes are identical
|
||||
require.Equal(t, hash, mpoolTx.Hash)
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -16,7 +16,6 @@ import (
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
"github.com/filecoin-project/lotus/chain/types/ethtypes"
|
||||
"github.com/filecoin-project/lotus/itests/kit"
|
||||
"github.com/filecoin-project/lotus/node/config"
|
||||
)
|
||||
|
||||
// TestTransactionHashLookup tests to see if lotus correctly stores a mapping from ethereum transaction hash to
|
||||
@ -29,7 +28,6 @@ func TestTransactionHashLookup(t *testing.T) {
|
||||
t,
|
||||
kit.MockProofs(),
|
||||
kit.ThroughRPC(),
|
||||
kit.EthTxHashLookup(),
|
||||
)
|
||||
ens.InterconnectAll().BeginMining(blocktime)
|
||||
|
||||
@ -112,86 +110,6 @@ func TestTransactionHashLookup(t *testing.T) {
|
||||
require.Equal(t, uint64(*chainTx.TransactionIndex), uint64(0)) // only transaction
|
||||
}
|
||||
|
||||
// TestTransactionHashLookupNoDb tests to see if looking up eth transactions by hash breaks without the lookup table
|
||||
func TestTransactionHashLookupNoDb(t *testing.T) {
|
||||
kit.QuietMiningLogs()
|
||||
|
||||
blocktime := 1 * time.Second
|
||||
client, _, ens := kit.EnsembleMinimal(
|
||||
t,
|
||||
kit.MockProofs(),
|
||||
kit.ThroughRPC(),
|
||||
kit.WithCfgOpt(func(cfg *config.FullNode) error {
|
||||
cfg.Fevm.EnableEthHashToFilecoinCidMapping = false
|
||||
return nil
|
||||
}),
|
||||
)
|
||||
ens.InterconnectAll().BeginMining(blocktime)
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
|
||||
defer cancel()
|
||||
|
||||
// install contract
|
||||
contractHex, err := os.ReadFile("./contracts/SimpleCoin.hex")
|
||||
require.NoError(t, err)
|
||||
|
||||
contract, err := hex.DecodeString(string(contractHex))
|
||||
require.NoError(t, err)
|
||||
|
||||
// create a new Ethereum account
|
||||
key, ethAddr, deployer := client.EVM().NewAccount()
|
||||
|
||||
// send some funds to the f410 address
|
||||
kit.SendFunds(ctx, t, client, deployer, types.FromFil(10))
|
||||
|
||||
gaslimit, err := client.EthEstimateGas(ctx, ethtypes.EthCall{
|
||||
From: ðAddr,
|
||||
Data: contract,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
maxPriorityFeePerGas, err := client.EthMaxPriorityFeePerGas(ctx)
|
||||
require.NoError(t, err)
|
||||
|
||||
// now deploy a contract from the embryo, and validate it went well
|
||||
tx := ethtypes.EthTxArgs{
|
||||
ChainID: build.Eip155ChainId,
|
||||
Value: big.Zero(),
|
||||
Nonce: 0,
|
||||
MaxFeePerGas: types.NanoFil,
|
||||
MaxPriorityFeePerGas: big.Int(maxPriorityFeePerGas),
|
||||
GasLimit: int(gaslimit),
|
||||
Input: contract,
|
||||
V: big.Zero(),
|
||||
R: big.Zero(),
|
||||
S: big.Zero(),
|
||||
}
|
||||
|
||||
client.EVM().SignTransaction(&tx, key.PrivateKey)
|
||||
|
||||
rawTxHash, err := tx.TxHash()
|
||||
require.NoError(t, err)
|
||||
|
||||
hash := client.EVM().SubmitTransaction(ctx, &tx)
|
||||
require.Equal(t, rawTxHash, hash)
|
||||
|
||||
// We shouldn't be able to find the tx
|
||||
mpoolTx, err := client.EthGetTransactionByHash(ctx, &hash)
|
||||
require.NoError(t, err)
|
||||
require.Nil(t, mpoolTx)
|
||||
|
||||
// Wait for message to land on chain, we can't know exactly when because we can't find it.
|
||||
time.Sleep(20 * blocktime)
|
||||
receipt, err := client.EthGetTransactionReceipt(ctx, hash)
|
||||
require.NoError(t, err)
|
||||
require.Nil(t, receipt)
|
||||
|
||||
// We still shouldn't be able to find the tx
|
||||
chainTx, err := client.EthGetTransactionByHash(ctx, &hash)
|
||||
require.NoError(t, err)
|
||||
require.Nil(t, chainTx)
|
||||
}
|
||||
|
||||
// TestTransactionHashLookupBlsFilecoinMessage tests to see if lotus can find a BLS Filecoin Message using the transaction hash
|
||||
func TestTransactionHashLookupBlsFilecoinMessage(t *testing.T) {
|
||||
kit.QuietMiningLogs()
|
||||
@ -201,7 +119,6 @@ func TestTransactionHashLookupBlsFilecoinMessage(t *testing.T) {
|
||||
t,
|
||||
kit.MockProofs(),
|
||||
kit.ThroughRPC(),
|
||||
kit.EthTxHashLookup(),
|
||||
)
|
||||
ens.InterconnectAll().BeginMining(blocktime)
|
||||
|
||||
@ -271,7 +188,6 @@ func TestTransactionHashLookupSecpFilecoinMessage(t *testing.T) {
|
||||
t,
|
||||
kit.MockProofs(),
|
||||
kit.ThroughRPC(),
|
||||
kit.EthTxHashLookup(),
|
||||
)
|
||||
ens.InterconnectAll().BeginMining(blocktime)
|
||||
|
||||
@ -348,7 +264,6 @@ func TestTransactionHashLookupNonexistentMessage(t *testing.T) {
|
||||
t,
|
||||
kit.MockProofs(),
|
||||
kit.ThroughRPC(),
|
||||
kit.EthTxHashLookup(),
|
||||
)
|
||||
ens.InterconnectAll().BeginMining(blocktime)
|
||||
|
||||
@ -379,7 +294,6 @@ func TestEthGetMessageCidByTransactionHashEthTx(t *testing.T) {
|
||||
t,
|
||||
kit.MockProofs(),
|
||||
kit.ThroughRPC(),
|
||||
kit.EthTxHashLookup(),
|
||||
)
|
||||
ens.InterconnectAll().BeginMining(blocktime)
|
||||
|
||||
@ -476,7 +390,6 @@ func TestEthGetMessageCidByTransactionHashSecp(t *testing.T) {
|
||||
t,
|
||||
kit.MockProofs(),
|
||||
kit.ThroughRPC(),
|
||||
kit.EthTxHashLookup(),
|
||||
)
|
||||
ens.InterconnectAll().BeginMining(blocktime)
|
||||
|
||||
@ -547,7 +460,6 @@ func TestEthGetMessageCidByTransactionHashBLS(t *testing.T) {
|
||||
t,
|
||||
kit.MockProofs(),
|
||||
kit.ThroughRPC(),
|
||||
kit.EthTxHashLookup(),
|
||||
)
|
||||
ens.InterconnectAll().BeginMining(blocktime)
|
||||
|
||||
|
@ -21,7 +21,7 @@ import (
|
||||
|
||||
func TestValueTransferValidSignature(t *testing.T) {
|
||||
blockTime := 100 * time.Millisecond
|
||||
client, _, ens := kit.EnsembleMinimal(t, kit.MockProofs(), kit.ThroughRPC(), kit.EthTxHashLookup())
|
||||
client, _, ens := kit.EnsembleMinimal(t, kit.MockProofs(), kit.ThroughRPC())
|
||||
|
||||
ens.InterconnectAll().BeginMining(blockTime)
|
||||
|
||||
@ -106,7 +106,7 @@ func TestLegacyTransaction(t *testing.T) {
|
||||
func TestContractDeploymentValidSignature(t *testing.T) {
|
||||
|
||||
blockTime := 100 * time.Millisecond
|
||||
client, _, ens := kit.EnsembleMinimal(t, kit.MockProofs(), kit.ThroughRPC(), kit.EthTxHashLookup())
|
||||
client, _, ens := kit.EnsembleMinimal(t, kit.MockProofs(), kit.ThroughRPC())
|
||||
|
||||
ens.InterconnectAll().BeginMining(blockTime)
|
||||
|
||||
@ -167,7 +167,7 @@ func TestContractDeploymentValidSignature(t *testing.T) {
|
||||
|
||||
func TestContractInvocation(t *testing.T) {
|
||||
blockTime := 100 * time.Millisecond
|
||||
client, _, ens := kit.EnsembleMinimal(t, kit.MockProofs(), kit.ThroughRPC(), kit.EthTxHashLookup())
|
||||
client, _, ens := kit.EnsembleMinimal(t, kit.MockProofs(), kit.ThroughRPC())
|
||||
|
||||
ens.InterconnectAll().BeginMining(blockTime)
|
||||
|
||||
|
@ -12,6 +12,7 @@ import (
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
|
||||
"github.com/filecoin-project/lotus/chain/types/ethtypes"
|
||||
"github.com/filecoin-project/lotus/itests/kit"
|
||||
)
|
||||
|
||||
@ -45,22 +46,22 @@ func TestFEVMEvents(t *testing.T) {
|
||||
require.NoError(err)
|
||||
t.Logf("actor ID address is %s", idAddr)
|
||||
|
||||
// var (
|
||||
// earliest = "earliest"
|
||||
// latest = "latest"
|
||||
// )
|
||||
//
|
||||
// // Install a filter.
|
||||
// filter, err := client.EthNewFilter(ctx, &api.EthFilterSpec{
|
||||
// FromBlock: &earliest,
|
||||
// ToBlock: &latest,
|
||||
// })
|
||||
// require.NoError(err)
|
||||
//
|
||||
// // No logs yet.
|
||||
// res, err := client.EthGetFilterLogs(ctx, filter)
|
||||
// require.NoError(err)
|
||||
// require.Empty(res.NewLogs)
|
||||
var (
|
||||
earliest = "earliest"
|
||||
latest = "latest"
|
||||
)
|
||||
|
||||
// Install a filter.
|
||||
filter, err := client.EthNewFilter(ctx, ðtypes.EthFilterSpec{
|
||||
FromBlock: &earliest,
|
||||
ToBlock: &latest,
|
||||
})
|
||||
require.NoError(err)
|
||||
|
||||
// No logs yet.
|
||||
res, err := client.EthGetFilterLogs(ctx, filter)
|
||||
require.NoError(err)
|
||||
require.Empty(res.Results)
|
||||
|
||||
// log a zero topic event with data
|
||||
ret := client.EVM().InvokeSolidity(ctx, fromAddr, idAddr, []byte{0x00, 0x00, 0x00, 0x00}, nil)
|
||||
|
@ -2,6 +2,7 @@ package itests
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/binary"
|
||||
"encoding/hex"
|
||||
"testing"
|
||||
"time"
|
||||
@ -10,6 +11,7 @@ import (
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
builtintypes "github.com/filecoin-project/go-state-types/builtin"
|
||||
"github.com/filecoin-project/go-state-types/exitcode"
|
||||
"github.com/filecoin-project/go-state-types/manifest"
|
||||
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
@ -38,9 +40,9 @@ func inputDataFromFrom(ctx context.Context, t *testing.T, client *kit.TestFullNo
|
||||
|
||||
func setupFEVMTest(t *testing.T) (context.Context, context.CancelFunc, *kit.TestFullNode) {
|
||||
kit.QuietMiningLogs()
|
||||
blockTime := 100 * time.Millisecond
|
||||
blockTime := 5 * time.Millisecond
|
||||
client, _, ens := kit.EnsembleMinimal(t, kit.MockProofs(), kit.ThroughRPC())
|
||||
ens.InterconnectAll().BeginMining(blockTime)
|
||||
ens.InterconnectAll().BeginMiningMustPost(blockTime)
|
||||
ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
|
||||
return ctx, cancel, client
|
||||
}
|
||||
@ -132,3 +134,85 @@ func TestFEVMDelegateCall(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, result, expectedResultActor)
|
||||
}
|
||||
|
||||
func TestEVMRpcDisable(t *testing.T) {
|
||||
client, _, _ := kit.EnsembleMinimal(t, kit.MockProofs(), kit.ThroughRPC(), kit.DisableEthRPC())
|
||||
|
||||
_, err := client.EthBlockNumber(context.Background())
|
||||
require.ErrorContains(t, err, "module disabled, enable with Fevm.EnableEthRPC")
|
||||
}
|
||||
|
||||
// TestFEVMRecursiveFuncCall deploys a contract and makes a recursive function calls
|
||||
func TestFEVMRecursiveFuncCall(t *testing.T) {
|
||||
ctx, cancel, client := setupFEVMTest(t)
|
||||
defer cancel()
|
||||
|
||||
//install contract Actor
|
||||
filenameActor := "contracts/StackFunc.hex"
|
||||
fromAddr, actorAddr := client.EVM().DeployContractFromFilename(ctx, filenameActor)
|
||||
|
||||
testN := func(n int, ex exitcode.ExitCode) func(t *testing.T) {
|
||||
return func(t *testing.T) {
|
||||
inputData := make([]byte, 32)
|
||||
binary.BigEndian.PutUint64(inputData[24:], uint64(n))
|
||||
|
||||
client.EVM().InvokeContractByFuncNameExpectExit(ctx, fromAddr, actorAddr, "exec1(uint256)", inputData, ex)
|
||||
}
|
||||
}
|
||||
|
||||
t.Run("n=0", testN(0, exitcode.Ok))
|
||||
t.Run("n=1", testN(1, exitcode.Ok))
|
||||
t.Run("n=20", testN(20, exitcode.Ok))
|
||||
t.Run("n=200", testN(200, exitcode.Ok))
|
||||
t.Run("n=507", testN(507, exitcode.Ok))
|
||||
t.Run("n=508", testN(508, exitcode.ExitCode(23))) // 23 means stack overflow
|
||||
}
|
||||
|
||||
// TestFEVMRecursiveActorCall deploys a contract and makes a recursive actor calls
|
||||
func TestFEVMRecursiveActorCall(t *testing.T) {
|
||||
ctx, cancel, client := setupFEVMTest(t)
|
||||
defer cancel()
|
||||
|
||||
//install contract Actor
|
||||
filenameActor := "contracts/RecCall.hex"
|
||||
fromAddr, actorAddr := client.EVM().DeployContractFromFilename(ctx, filenameActor)
|
||||
|
||||
testN := func(n, r int, ex exitcode.ExitCode) func(t *testing.T) {
|
||||
return func(t *testing.T) {
|
||||
inputData := make([]byte, 32*3)
|
||||
binary.BigEndian.PutUint64(inputData[24:], uint64(n))
|
||||
binary.BigEndian.PutUint64(inputData[32+24:], uint64(n))
|
||||
binary.BigEndian.PutUint64(inputData[32+32+24:], uint64(r))
|
||||
|
||||
client.EVM().InvokeContractByFuncNameExpectExit(ctx, fromAddr, actorAddr, "exec1(uint256,uint256,uint256)", inputData, ex)
|
||||
}
|
||||
}
|
||||
|
||||
t.Run("n=0,r=1", testN(0, 1, exitcode.Ok))
|
||||
t.Run("n=1,r=1", testN(1, 1, exitcode.Ok))
|
||||
t.Run("n=20,r=1", testN(20, 1, exitcode.Ok))
|
||||
t.Run("n=200,r=1", testN(200, 1, exitcode.Ok))
|
||||
t.Run("n=251,r=1", testN(251, 1, exitcode.Ok))
|
||||
|
||||
t.Run("n=252,r=1-fails", testN(252, 1, exitcode.ExitCode(23))) // 23 means stack overflow
|
||||
|
||||
t.Run("n=0,r=10", testN(0, 10, exitcode.Ok))
|
||||
t.Run("n=1,r=10", testN(1, 10, exitcode.Ok))
|
||||
t.Run("n=20,r=10", testN(20, 10, exitcode.Ok))
|
||||
t.Run("n=200,r=10", testN(200, 10, exitcode.Ok))
|
||||
t.Run("n=251,r=10", testN(251, 10, exitcode.Ok))
|
||||
|
||||
t.Run("n=252,r=10-fails", testN(252, 10, exitcode.ExitCode(23)))
|
||||
|
||||
t.Run("n=0,r=32", testN(0, 32, exitcode.Ok))
|
||||
t.Run("n=1,r=32", testN(1, 32, exitcode.Ok))
|
||||
t.Run("n=20,r=32", testN(20, 32, exitcode.Ok))
|
||||
t.Run("n=200,r=32", testN(200, 32, exitcode.Ok))
|
||||
t.Run("n=251,r=32", testN(251, 32, exitcode.Ok))
|
||||
|
||||
t.Run("n=0,r=254", testN(0, 254, exitcode.Ok))
|
||||
t.Run("n=251,r=170", testN(251, 170, exitcode.Ok))
|
||||
|
||||
t.Run("n=0,r=255-fails", testN(0, 255, exitcode.ExitCode(33))) // 33 means transaction reverted
|
||||
t.Run("n=251,r=171-fails", testN(251, 171, exitcode.ExitCode(33)))
|
||||
}
|
||||
|
@ -21,8 +21,10 @@ import (
|
||||
builtintypes "github.com/filecoin-project/go-state-types/builtin"
|
||||
"github.com/filecoin-project/go-state-types/builtin/v10/eam"
|
||||
"github.com/filecoin-project/go-state-types/crypto"
|
||||
"github.com/filecoin-project/go-state-types/exitcode"
|
||||
|
||||
"github.com/filecoin-project/lotus/api"
|
||||
"github.com/filecoin-project/lotus/build"
|
||||
"github.com/filecoin-project/lotus/chain/actors"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
"github.com/filecoin-project/lotus/chain/types/ethtypes"
|
||||
@ -83,6 +85,9 @@ func (e *EVM) DeployContractFromFilename(ctx context.Context, binFilename string
|
||||
contractHex, err := os.ReadFile(binFilename)
|
||||
require.NoError(e.t, err)
|
||||
|
||||
// strip any trailing newlines from the file
|
||||
contractHex = bytes.TrimRight(contractHex, "\n")
|
||||
|
||||
contract, err := hex.DecodeString(string(contractHex))
|
||||
require.NoError(e.t, err)
|
||||
|
||||
@ -106,11 +111,12 @@ func (e *EVM) InvokeSolidity(ctx context.Context, sender address.Address, target
|
||||
params = buffer.Bytes()
|
||||
|
||||
msg := &types.Message{
|
||||
To: target,
|
||||
From: sender,
|
||||
Value: big.Zero(),
|
||||
Method: builtintypes.MethodsEVM.InvokeContract,
|
||||
Params: params,
|
||||
To: target,
|
||||
From: sender,
|
||||
Value: big.Zero(),
|
||||
Method: builtintypes.MethodsEVM.InvokeContract,
|
||||
GasLimit: build.BlockGasLimit, // note: we hardcode block gas limit due to slightly broken gas estimation - https://github.com/filecoin-project/lotus/issues/10041
|
||||
Params: params,
|
||||
}
|
||||
|
||||
e.t.Log("sending invoke message")
|
||||
@ -234,12 +240,18 @@ func (e *EVM) ComputeContractAddress(deployer ethtypes.EthAddress, nonce uint64)
|
||||
func (e *EVM) InvokeContractByFuncName(ctx context.Context, fromAddr address.Address, idAddr address.Address, funcSignature string, inputData []byte) []byte {
|
||||
entryPoint := CalcFuncSignature(funcSignature)
|
||||
wait := e.InvokeSolidity(ctx, fromAddr, idAddr, entryPoint, inputData)
|
||||
require.True(e.t, wait.Receipt.ExitCode.IsSuccess(), "contract execution failed")
|
||||
require.True(e.t, wait.Receipt.ExitCode.IsSuccess(), "contract execution failed: %d", wait.Receipt.ExitCode)
|
||||
result, err := cbg.ReadByteArray(bytes.NewBuffer(wait.Receipt.Return), uint64(len(wait.Receipt.Return)))
|
||||
require.NoError(e.t, err)
|
||||
return result
|
||||
}
|
||||
|
||||
func (e *EVM) InvokeContractByFuncNameExpectExit(ctx context.Context, fromAddr address.Address, idAddr address.Address, funcSignature string, inputData []byte, exit exitcode.ExitCode) {
|
||||
entryPoint := CalcFuncSignature(funcSignature)
|
||||
wait := e.InvokeSolidity(ctx, fromAddr, idAddr, entryPoint, inputData)
|
||||
require.Equal(e.t, exit, wait.Receipt.ExitCode)
|
||||
}
|
||||
|
||||
// function signatures are the first 4 bytes of the hash of the function name and types
|
||||
func CalcFuncSignature(funcName string) []byte {
|
||||
hasher := sha3.NewLegacyKeccak256()
|
||||
|
@ -1,6 +1,9 @@
|
||||
package kit
|
||||
|
||||
import (
|
||||
"io"
|
||||
"log"
|
||||
|
||||
logging "github.com/ipfs/go-log/v2"
|
||||
|
||||
"github.com/filecoin-project/lotus/lib/lotuslog"
|
||||
@ -20,3 +23,13 @@ func QuietMiningLogs() {
|
||||
_ = logging.SetLogLevel("rpc", "ERROR")
|
||||
_ = logging.SetLogLevel("dht/RtRefreshManager", "ERROR")
|
||||
}
|
||||
|
||||
func QuietAllLogsExcept(names ...string) {
|
||||
log.SetOutput(io.Discard) // suppress LogDatastore messages
|
||||
|
||||
lotuslog.SetupLogLevels()
|
||||
logging.SetAllLoggers(logging.LevelError)
|
||||
for _, name := range names {
|
||||
_ = logging.SetLogLevel(name, "INFO")
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package kit
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"testing"
|
||||
@ -10,9 +11,11 @@ import (
|
||||
"github.com/libp2p/go-libp2p/core/peer"
|
||||
"github.com/multiformats/go-multiaddr"
|
||||
"github.com/stretchr/testify/require"
|
||||
cbg "github.com/whyrusleeping/cbor-gen"
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
"github.com/filecoin-project/go-state-types/abi"
|
||||
"github.com/filecoin-project/go-state-types/exitcode"
|
||||
|
||||
"github.com/filecoin-project/lotus/api"
|
||||
"github.com/filecoin-project/lotus/api/v1api"
|
||||
@ -124,6 +127,50 @@ func (f *TestFullNode) AssignPrivKey(pkey *Libp2p) {
|
||||
f.Pkey = pkey
|
||||
}
|
||||
|
||||
type SendCall struct {
|
||||
Method abi.MethodNum
|
||||
Params []byte
|
||||
}
|
||||
|
||||
func (f *TestFullNode) MakeSendCall(m abi.MethodNum, params cbg.CBORMarshaler) SendCall {
|
||||
var b bytes.Buffer
|
||||
err := params.MarshalCBOR(&b)
|
||||
require.NoError(f.t, err)
|
||||
return SendCall{
|
||||
Method: m,
|
||||
Params: b.Bytes(),
|
||||
}
|
||||
}
|
||||
|
||||
func (f *TestFullNode) ExpectSend(ctx context.Context, from, to address.Address, value types.BigInt, errContains string, sc ...SendCall) *types.SignedMessage {
|
||||
msg := &types.Message{From: from, To: to, Value: value}
|
||||
|
||||
if len(sc) == 1 {
|
||||
msg.Method = sc[0].Method
|
||||
msg.Params = sc[0].Params
|
||||
}
|
||||
|
||||
_, err := f.GasEstimateMessageGas(ctx, msg, nil, types.EmptyTSK)
|
||||
if errContains != "" {
|
||||
require.ErrorContains(f.t, err, errContains)
|
||||
return nil
|
||||
}
|
||||
require.NoError(f.t, err)
|
||||
|
||||
if errContains == "" {
|
||||
m, err := f.MpoolPushMessage(ctx, msg, nil)
|
||||
require.NoError(f.t, err)
|
||||
|
||||
r, err := f.StateWaitMsg(ctx, m.Cid(), 1, api.LookbackNoLimit, true)
|
||||
require.NoError(f.t, err)
|
||||
|
||||
require.Equal(f.t, exitcode.Ok, r.Receipt.ExitCode)
|
||||
return m
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ChainPredicate encapsulates a chain condition.
|
||||
type ChainPredicate func(set *types.TipSet) bool
|
||||
|
||||
@ -135,13 +182,21 @@ func HeightAtLeast(target abi.ChainEpoch) ChainPredicate {
|
||||
}
|
||||
}
|
||||
|
||||
// BlockMinedBy returns a ChainPredicate that is satisfied when we observe the
|
||||
// first block mined by the specified miner.
|
||||
func BlockMinedBy(miner address.Address) ChainPredicate {
|
||||
// BlocksMinedByAll returns a ChainPredicate that is satisfied when we observe a
|
||||
// tipset including blocks from all the specified miners, in no particular order.
|
||||
func BlocksMinedByAll(miner ...address.Address) ChainPredicate {
|
||||
return func(ts *types.TipSet) bool {
|
||||
seen := make([]bool, len(miner))
|
||||
var done int
|
||||
for _, b := range ts.Blocks() {
|
||||
if b.Miner == miner {
|
||||
return true
|
||||
for i, m := range miner {
|
||||
if b.Miner != m || seen[i] {
|
||||
continue
|
||||
}
|
||||
seen[i] = true
|
||||
if done++; done == len(miner) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
|
@ -58,6 +58,15 @@ var DefaultNodeOpts = nodeOpts{
|
||||
sectors: DefaultPresealsPerBootstrapMiner,
|
||||
sectorSize: abi.SectorSize(2 << 10), // 2KiB.
|
||||
|
||||
cfgOpts: []CfgOption{
|
||||
func(cfg *config.FullNode) error {
|
||||
// test defaults
|
||||
|
||||
cfg.Fevm.EnableEthRPC = true
|
||||
return nil
|
||||
},
|
||||
},
|
||||
|
||||
workerTasks: []sealtasks.TaskType{sealtasks.TTFetch, sealtasks.TTCommit1, sealtasks.TTFinalize, sealtasks.TTFinalizeUnsealed},
|
||||
workerStorageOpt: func(store paths.Store) paths.Store { return store },
|
||||
}
|
||||
@ -281,25 +290,16 @@ func SplitstoreMessges() NodeOpt {
|
||||
})
|
||||
}
|
||||
|
||||
func RealTimeFilterAPI() NodeOpt {
|
||||
func WithEthRPC() NodeOpt {
|
||||
return WithCfgOpt(func(cfg *config.FullNode) error {
|
||||
cfg.ActorEvent.EnableRealTimeFilterAPI = true
|
||||
cfg.Fevm.EnableEthRPC = true
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func HistoricFilterAPI(dbpath string) NodeOpt {
|
||||
func DisableEthRPC() NodeOpt {
|
||||
return WithCfgOpt(func(cfg *config.FullNode) error {
|
||||
cfg.ActorEvent.EnableRealTimeFilterAPI = true
|
||||
cfg.ActorEvent.EnableHistoricFilterAPI = true
|
||||
cfg.ActorEvent.ActorEventDatabasePath = dbpath
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func EthTxHashLookup() NodeOpt {
|
||||
return WithCfgOpt(func(cfg *config.FullNode) error {
|
||||
cfg.Fevm.EnableEthHashToFilecoinCidMapping = true
|
||||
cfg.Fevm.EnableEthRPC = false
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
@ -351,13 +351,11 @@ func splitStorePruneIndex(ctx context.Context, t *testing.T, n *kit.TestFullNode
|
||||
}
|
||||
|
||||
func ipldExists(ctx context.Context, t *testing.T, c cid.Cid, n *kit.TestFullNode) bool {
|
||||
_, err := n.ChainReadObj(ctx, c)
|
||||
if ipld.IsNotFound(err) {
|
||||
return false
|
||||
} else if err != nil {
|
||||
t.Fatalf("ChainReadObj failure on existence check: %s", err)
|
||||
found, err := n.ChainHasObj(ctx, c)
|
||||
if err != nil {
|
||||
t.Fatalf("ChainHasObj failure: %s", err)
|
||||
}
|
||||
return true
|
||||
return found
|
||||
}
|
||||
|
||||
// Create on chain unreachable garbage for a network to exercise splitstore
|
||||
@ -414,12 +412,10 @@ func (g *Garbager) Exists(ctx context.Context, c cid.Cid) bool {
|
||||
return false
|
||||
} else if err != nil {
|
||||
g.t.Fatalf("ChainReadObj failure on existence check: %s", err)
|
||||
return false // unreachable
|
||||
} else {
|
||||
return true
|
||||
}
|
||||
|
||||
g.t.Fatal("unreachable")
|
||||
return false
|
||||
}
|
||||
|
||||
func (g *Garbager) newPeerID(ctx context.Context) abi.ChainEpoch {
|
||||
|
@ -68,7 +68,7 @@ func (delegatedSigner) Verify(sig []byte, a address.Address, msg []byte) error {
|
||||
}
|
||||
|
||||
if maybeaddr != a {
|
||||
return fmt.Errorf("signature did not match")
|
||||
return fmt.Errorf("signature did not match maybeaddr: %s, signer: %s", maybeaddr, a)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -259,9 +259,10 @@ func ConfigFullNode(c interface{}) Option {
|
||||
// Actor event filtering support
|
||||
Override(new(events.EventAPI), From(new(modules.EventAPI))),
|
||||
// in lite-mode Eth event api is provided by gateway
|
||||
ApplyIf(isFullNode, Override(new(full.EthEventAPI), modules.EthEventAPI(cfg.ActorEvent))),
|
||||
ApplyIf(isFullNode, Override(new(full.EthEventAPI), modules.EthEventAPI(cfg.Fevm))),
|
||||
|
||||
Override(new(full.EthModuleAPI), modules.EthModuleAPI(cfg.Fevm)),
|
||||
If(cfg.Fevm.EnableEthRPC, Override(new(full.EthModuleAPI), modules.EthModuleAPI(cfg.Fevm))),
|
||||
If(!cfg.Fevm.EnableEthRPC, Override(new(full.EthModuleAPI), &full.EthModuleDummy{})),
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -99,17 +99,17 @@ func DefaultFullNode() *FullNode {
|
||||
},
|
||||
},
|
||||
Cluster: *DefaultUserRaftConfig(),
|
||||
ActorEvent: ActorEventConfig{
|
||||
EnableRealTimeFilterAPI: false,
|
||||
EnableHistoricFilterAPI: false,
|
||||
FilterTTL: Duration(time.Hour * 24),
|
||||
MaxFilters: 100,
|
||||
MaxFilterResults: 10000,
|
||||
MaxFilterHeightRange: 2880, // conservative limit of one day
|
||||
},
|
||||
Fevm: FevmConfig{
|
||||
EnableEthHashToFilecoinCidMapping: false,
|
||||
EthTxHashMappingLifetimeDays: 0,
|
||||
EnableEthRPC: false,
|
||||
EthTxHashMappingLifetimeDays: 0,
|
||||
Events: Events{
|
||||
DisableRealTimeFilterAPI: false,
|
||||
DisableHistoricFilterAPI: false,
|
||||
FilterTTL: Duration(time.Hour * 24),
|
||||
MaxFilters: 100,
|
||||
MaxFilterResults: 10000,
|
||||
MaxFilterHeightRange: 2880, // conservative limit of one day
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -29,56 +29,6 @@ var Doc = map[string][]DocField{
|
||||
Comment: ``,
|
||||
},
|
||||
},
|
||||
"ActorEventConfig": []DocField{
|
||||
{
|
||||
Name: "EnableRealTimeFilterAPI",
|
||||
Type: "bool",
|
||||
|
||||
Comment: `EnableRealTimeFilterAPI enables APIs that can create and query filters for actor events as they are emitted.`,
|
||||
},
|
||||
{
|
||||
Name: "EnableHistoricFilterAPI",
|
||||
Type: "bool",
|
||||
|
||||
Comment: `EnableHistoricFilterAPI enables APIs that can create and query filters for actor events that occurred in the past.
|
||||
A queryable index of events will be maintained.`,
|
||||
},
|
||||
{
|
||||
Name: "FilterTTL",
|
||||
Type: "Duration",
|
||||
|
||||
Comment: `FilterTTL specifies the time to live for actor event filters. Filters that haven't been accessed longer than
|
||||
this time become eligible for automatic deletion.`,
|
||||
},
|
||||
{
|
||||
Name: "MaxFilters",
|
||||
Type: "int",
|
||||
|
||||
Comment: `MaxFilters specifies the maximum number of filters that may exist at any one time.`,
|
||||
},
|
||||
{
|
||||
Name: "MaxFilterResults",
|
||||
Type: "int",
|
||||
|
||||
Comment: `MaxFilterResults specifies the maximum number of results that can be accumulated by an actor event filter.`,
|
||||
},
|
||||
{
|
||||
Name: "MaxFilterHeightRange",
|
||||
Type: "uint64",
|
||||
|
||||
Comment: `MaxFilterHeightRange specifies the maximum range of heights that can be used in a filter (to avoid querying
|
||||
the entire chain)`,
|
||||
},
|
||||
{
|
||||
Name: "ActorEventDatabasePath",
|
||||
Type: "string",
|
||||
|
||||
Comment: `ActorEventDatabasePath is the full path to a sqlite database that will be used to index actor events to
|
||||
support the historic filter APIs. If the database does not exist it will be created. The directory containing
|
||||
the database must already exist and be writeable. If a relative path is provided here, sqlite treats it as
|
||||
relative to the CWD (current working directory).`,
|
||||
},
|
||||
},
|
||||
"Backup": []DocField{
|
||||
{
|
||||
Name: "DisableMetadataLog",
|
||||
@ -391,6 +341,59 @@ see https://lotus.filecoin.io/storage-providers/advanced-configurations/market/#
|
||||
Comment: ``,
|
||||
},
|
||||
},
|
||||
"Events": []DocField{
|
||||
{
|
||||
Name: "DisableRealTimeFilterAPI",
|
||||
Type: "bool",
|
||||
|
||||
Comment: `EnableEthRPC enables APIs that
|
||||
DisableRealTimeFilterAPI will disable the RealTimeFilterAPI that can create and query filters for actor events as they are emitted.
|
||||
The API is enabled when EnableEthRPC is true, but can be disabled selectively with this flag.`,
|
||||
},
|
||||
{
|
||||
Name: "DisableHistoricFilterAPI",
|
||||
Type: "bool",
|
||||
|
||||
Comment: `DisableHistoricFilterAPI will disable the HistoricFilterAPI that can create and query filters for actor events
|
||||
that occurred in the past. HistoricFilterAPI maintains a queryable index of events.
|
||||
The API is enabled when EnableEthRPC is true, but can be disabled selectively with this flag.`,
|
||||
},
|
||||
{
|
||||
Name: "FilterTTL",
|
||||
Type: "Duration",
|
||||
|
||||
Comment: `FilterTTL specifies the time to live for actor event filters. Filters that haven't been accessed longer than
|
||||
this time become eligible for automatic deletion.`,
|
||||
},
|
||||
{
|
||||
Name: "MaxFilters",
|
||||
Type: "int",
|
||||
|
||||
Comment: `MaxFilters specifies the maximum number of filters that may exist at any one time.`,
|
||||
},
|
||||
{
|
||||
Name: "MaxFilterResults",
|
||||
Type: "int",
|
||||
|
||||
Comment: `MaxFilterResults specifies the maximum number of results that can be accumulated by an actor event filter.`,
|
||||
},
|
||||
{
|
||||
Name: "MaxFilterHeightRange",
|
||||
Type: "uint64",
|
||||
|
||||
Comment: `MaxFilterHeightRange specifies the maximum range of heights that can be used in a filter (to avoid querying
|
||||
the entire chain)`,
|
||||
},
|
||||
{
|
||||
Name: "DatabasePath",
|
||||
Type: "string",
|
||||
|
||||
Comment: `DatabasePath is the full path to a sqlite database that will be used to index actor events to
|
||||
support the historic filter APIs. If the database does not exist it will be created. The directory containing
|
||||
the database must already exist and be writeable. If a relative path is provided here, sqlite treats it as
|
||||
relative to the CWD (current working directory).`,
|
||||
},
|
||||
},
|
||||
"FeeConfig": []DocField{
|
||||
{
|
||||
Name: "DefaultMaxFee",
|
||||
@ -401,11 +404,11 @@ see https://lotus.filecoin.io/storage-providers/advanced-configurations/market/#
|
||||
},
|
||||
"FevmConfig": []DocField{
|
||||
{
|
||||
Name: "EnableEthHashToFilecoinCidMapping",
|
||||
Name: "EnableEthRPC",
|
||||
Type: "bool",
|
||||
|
||||
Comment: `EnableEthHashToFilecoinCidMapping enables storing a mapping of eth transaction hashes to filecoin message Cids
|
||||
You will not be able to look up ethereum transactions by their hash if this is disabled.`,
|
||||
Comment: `EnableEthRPC enables eth_ rpc, and enables storing a mapping of eth transaction hashes to filecoin message Cids.
|
||||
This will also enable the RealTimeFilterAPI and HistoricFilterAPI by default, but they can be disabled by config options above.`,
|
||||
},
|
||||
{
|
||||
Name: "EthTxHashMappingLifetimeDays",
|
||||
@ -414,6 +417,12 @@ You will not be able to look up ethereum transactions by their hash if this is d
|
||||
Comment: `EthTxHashMappingLifetimeDays the transaction hash lookup database will delete mappings that have been stored for more than x days
|
||||
Set to 0 to keep all mappings`,
|
||||
},
|
||||
{
|
||||
Name: "Events",
|
||||
Type: "Events",
|
||||
|
||||
Comment: ``,
|
||||
},
|
||||
},
|
||||
"FullNode": []DocField{
|
||||
{
|
||||
@ -446,12 +455,6 @@ Set to 0 to keep all mappings`,
|
||||
|
||||
Comment: ``,
|
||||
},
|
||||
{
|
||||
Name: "ActorEvent",
|
||||
Type: "ActorEventConfig",
|
||||
|
||||
Comment: ``,
|
||||
},
|
||||
{
|
||||
Name: "Fevm",
|
||||
Type: "FevmConfig",
|
||||
|
@ -27,7 +27,6 @@ type FullNode struct {
|
||||
Fees FeeConfig
|
||||
Chainstore Chainstore
|
||||
Cluster UserRaftConfig
|
||||
ActorEvent ActorEventConfig
|
||||
Fevm FevmConfig
|
||||
}
|
||||
|
||||
@ -660,13 +659,28 @@ type UserRaftConfig struct {
|
||||
Tracing bool
|
||||
}
|
||||
|
||||
type ActorEventConfig struct {
|
||||
// EnableRealTimeFilterAPI enables APIs that can create and query filters for actor events as they are emitted.
|
||||
EnableRealTimeFilterAPI bool
|
||||
type FevmConfig struct {
|
||||
// EnableEthRPC enables eth_ rpc, and enables storing a mapping of eth transaction hashes to filecoin message Cids.
|
||||
// This will also enable the RealTimeFilterAPI and HistoricFilterAPI by default, but they can be disabled by config options above.
|
||||
EnableEthRPC bool
|
||||
|
||||
// EnableHistoricFilterAPI enables APIs that can create and query filters for actor events that occurred in the past.
|
||||
// A queryable index of events will be maintained.
|
||||
EnableHistoricFilterAPI bool
|
||||
// EthTxHashMappingLifetimeDays the transaction hash lookup database will delete mappings that have been stored for more than x days
|
||||
// Set to 0 to keep all mappings
|
||||
EthTxHashMappingLifetimeDays int
|
||||
|
||||
Events Events
|
||||
}
|
||||
|
||||
type Events struct {
|
||||
// EnableEthRPC enables APIs that
|
||||
// DisableRealTimeFilterAPI will disable the RealTimeFilterAPI that can create and query filters for actor events as they are emitted.
|
||||
// The API is enabled when EnableEthRPC is true, but can be disabled selectively with this flag.
|
||||
DisableRealTimeFilterAPI bool
|
||||
|
||||
// DisableHistoricFilterAPI will disable the HistoricFilterAPI that can create and query filters for actor events
|
||||
// that occurred in the past. HistoricFilterAPI maintains a queryable index of events.
|
||||
// The API is enabled when EnableEthRPC is true, but can be disabled selectively with this flag.
|
||||
DisableHistoricFilterAPI bool
|
||||
|
||||
// FilterTTL specifies the time to live for actor event filters. Filters that haven't been accessed longer than
|
||||
// this time become eligible for automatic deletion.
|
||||
@ -682,23 +696,14 @@ type ActorEventConfig struct {
|
||||
// the entire chain)
|
||||
MaxFilterHeightRange uint64
|
||||
|
||||
// ActorEventDatabasePath is the full path to a sqlite database that will be used to index actor events to
|
||||
// DatabasePath is the full path to a sqlite database that will be used to index actor events to
|
||||
// support the historic filter APIs. If the database does not exist it will be created. The directory containing
|
||||
// the database must already exist and be writeable. If a relative path is provided here, sqlite treats it as
|
||||
// relative to the CWD (current working directory).
|
||||
ActorEventDatabasePath string
|
||||
DatabasePath string
|
||||
|
||||
// Others, not implemented yet:
|
||||
// Set a limit on the number of active websocket subscriptions (may be zero)
|
||||
// Set a timeout for subscription clients
|
||||
// Set upper bound on index size
|
||||
}
|
||||
|
||||
type FevmConfig struct {
|
||||
// EnableEthHashToFilecoinCidMapping enables storing a mapping of eth transaction hashes to filecoin message Cids
|
||||
// You will not be able to look up ethereum transactions by their hash if this is disabled.
|
||||
EnableEthHashToFilecoinCidMapping bool
|
||||
// EthTxHashMappingLifetimeDays the transaction hash lookup database will delete mappings that have been stored for more than x days
|
||||
// Set to 0 to keep all mappings
|
||||
EthTxHashMappingLifetimeDays int
|
||||
}
|
||||
|
@ -4,106 +4,122 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
"github.com/ipfs/go-cid"
|
||||
|
||||
"github.com/filecoin-project/lotus/api"
|
||||
"github.com/filecoin-project/lotus/chain/types/ethtypes"
|
||||
)
|
||||
|
||||
var ErrImplementMe = errors.New("Not implemented yet")
|
||||
var ErrModuleDisabled = errors.New("module disabled, enable with Fevm.EnableEthRPC / LOTUS_FEVM_ENABLEETHPRC")
|
||||
|
||||
type EthModuleDummy struct{}
|
||||
|
||||
func (e *EthModuleDummy) EthGetMessageCidByTransactionHash(ctx context.Context, txHash *ethtypes.EthHash) (*cid.Cid, error) {
|
||||
return nil, ErrModuleDisabled
|
||||
}
|
||||
|
||||
func (e *EthModuleDummy) EthGetTransactionHashByCid(ctx context.Context, cid cid.Cid) (*ethtypes.EthHash, error) {
|
||||
return nil, ErrModuleDisabled
|
||||
}
|
||||
|
||||
func (e *EthModuleDummy) EthBlockNumber(ctx context.Context) (ethtypes.EthUint64, error) {
|
||||
return 0, ErrImplementMe
|
||||
return 0, ErrModuleDisabled
|
||||
}
|
||||
|
||||
func (e *EthModuleDummy) EthAccounts(ctx context.Context) ([]ethtypes.EthAddress, error) {
|
||||
return nil, ErrImplementMe
|
||||
return nil, ErrModuleDisabled
|
||||
}
|
||||
|
||||
func (e *EthModuleDummy) EthGetBlockTransactionCountByNumber(ctx context.Context, blkNum ethtypes.EthUint64) (ethtypes.EthUint64, error) {
|
||||
return 0, ErrImplementMe
|
||||
return 0, ErrModuleDisabled
|
||||
}
|
||||
|
||||
func (e *EthModuleDummy) EthGetBlockTransactionCountByHash(ctx context.Context, blkHash ethtypes.EthHash) (ethtypes.EthUint64, error) {
|
||||
return 0, ErrImplementMe
|
||||
return 0, ErrModuleDisabled
|
||||
}
|
||||
|
||||
func (e *EthModuleDummy) EthGetBlockByHash(ctx context.Context, blkHash ethtypes.EthHash, fullTxInfo bool) (ethtypes.EthBlock, error) {
|
||||
return ethtypes.EthBlock{}, ErrImplementMe
|
||||
return ethtypes.EthBlock{}, ErrModuleDisabled
|
||||
}
|
||||
|
||||
func (e *EthModuleDummy) EthGetBlockByNumber(ctx context.Context, blkNum string, fullTxInfo bool) (ethtypes.EthBlock, error) {
|
||||
return ethtypes.EthBlock{}, ErrImplementMe
|
||||
return ethtypes.EthBlock{}, ErrModuleDisabled
|
||||
}
|
||||
|
||||
func (e *EthModuleDummy) EthGetTransactionByHash(ctx context.Context, txHash *ethtypes.EthHash) (*ethtypes.EthTx, error) {
|
||||
return nil, ErrImplementMe
|
||||
return nil, ErrModuleDisabled
|
||||
}
|
||||
|
||||
func (e *EthModuleDummy) EthGetTransactionCount(ctx context.Context, sender ethtypes.EthAddress, blkOpt string) (ethtypes.EthUint64, error) {
|
||||
return 0, ErrImplementMe
|
||||
return 0, ErrModuleDisabled
|
||||
}
|
||||
|
||||
func (e *EthModuleDummy) EthGetTransactionReceipt(ctx context.Context, txHash ethtypes.EthHash) (*api.EthTxReceipt, error) {
|
||||
return nil, ErrImplementMe
|
||||
return nil, ErrModuleDisabled
|
||||
}
|
||||
|
||||
func (e *EthModuleDummy) EthGetTransactionByBlockHashAndIndex(ctx context.Context, blkHash ethtypes.EthHash, txIndex ethtypes.EthUint64) (ethtypes.EthTx, error) {
|
||||
return ethtypes.EthTx{}, ErrImplementMe
|
||||
return ethtypes.EthTx{}, ErrModuleDisabled
|
||||
}
|
||||
|
||||
func (e *EthModuleDummy) EthGetTransactionByBlockNumberAndIndex(ctx context.Context, blkNum ethtypes.EthUint64, txIndex ethtypes.EthUint64) (ethtypes.EthTx, error) {
|
||||
return ethtypes.EthTx{}, ErrImplementMe
|
||||
return ethtypes.EthTx{}, ErrModuleDisabled
|
||||
}
|
||||
|
||||
func (e *EthModuleDummy) EthGetCode(ctx context.Context, address ethtypes.EthAddress, blkOpt string) (ethtypes.EthBytes, error) {
|
||||
return nil, ErrImplementMe
|
||||
return nil, ErrModuleDisabled
|
||||
}
|
||||
|
||||
func (e *EthModuleDummy) EthGetStorageAt(ctx context.Context, address ethtypes.EthAddress, position ethtypes.EthBytes, blkParam string) (ethtypes.EthBytes, error) {
|
||||
return nil, ErrImplementMe
|
||||
return nil, ErrModuleDisabled
|
||||
}
|
||||
|
||||
func (e *EthModuleDummy) EthGetBalance(ctx context.Context, address ethtypes.EthAddress, blkParam string) (ethtypes.EthBigInt, error) {
|
||||
return ethtypes.EthBigIntZero, ErrImplementMe
|
||||
return ethtypes.EthBigIntZero, ErrModuleDisabled
|
||||
}
|
||||
|
||||
func (e *EthModuleDummy) EthFeeHistory(ctx context.Context, blkCount ethtypes.EthUint64, newestBlk string, rewardPercentiles []float64) (ethtypes.EthFeeHistory, error) {
|
||||
return ethtypes.EthFeeHistory{}, ErrImplementMe
|
||||
return ethtypes.EthFeeHistory{}, ErrModuleDisabled
|
||||
}
|
||||
|
||||
func (e *EthModuleDummy) EthChainId(ctx context.Context) (ethtypes.EthUint64, error) {
|
||||
return 0, ErrImplementMe
|
||||
return 0, ErrModuleDisabled
|
||||
}
|
||||
|
||||
func (e *EthModuleDummy) NetVersion(ctx context.Context) (string, error) {
|
||||
return "", ErrImplementMe
|
||||
return "", ErrModuleDisabled
|
||||
}
|
||||
|
||||
func (e *EthModuleDummy) NetListening(ctx context.Context) (bool, error) {
|
||||
return false, ErrImplementMe
|
||||
return false, ErrModuleDisabled
|
||||
}
|
||||
|
||||
func (e *EthModuleDummy) EthProtocolVersion(ctx context.Context) (ethtypes.EthUint64, error) {
|
||||
return 0, ErrImplementMe
|
||||
return 0, ErrModuleDisabled
|
||||
}
|
||||
|
||||
func (e *EthModuleDummy) EthGasPrice(ctx context.Context) (ethtypes.EthBigInt, error) {
|
||||
return ethtypes.EthBigIntZero, ErrImplementMe
|
||||
return ethtypes.EthBigIntZero, ErrModuleDisabled
|
||||
}
|
||||
|
||||
func (e *EthModuleDummy) EthEstimateGas(ctx context.Context, tx ethtypes.EthCall) (ethtypes.EthUint64, error) {
|
||||
return 0, ErrImplementMe
|
||||
return 0, ErrModuleDisabled
|
||||
}
|
||||
|
||||
func (e *EthModuleDummy) EthCall(ctx context.Context, tx ethtypes.EthCall, blkParam string) (ethtypes.EthBytes, error) {
|
||||
return nil, ErrImplementMe
|
||||
return nil, ErrModuleDisabled
|
||||
}
|
||||
|
||||
func (e *EthModuleDummy) EthMaxPriorityFeePerGas(ctx context.Context) (ethtypes.EthBigInt, error) {
|
||||
return ethtypes.EthBigIntZero, ErrImplementMe
|
||||
return ethtypes.EthBigIntZero, ErrModuleDisabled
|
||||
}
|
||||
|
||||
func (e *EthModuleDummy) EthSendRawTransaction(ctx context.Context, rawTx ethtypes.EthBytes) (ethtypes.EthHash, error) {
|
||||
return ethtypes.EthHash{}, ErrImplementMe
|
||||
return ethtypes.EthHash{}, ErrModuleDisabled
|
||||
}
|
||||
|
||||
func (e *EthModuleDummy) Web3ClientVersion(ctx context.Context) (string, error) {
|
||||
return "", ErrModuleDisabled
|
||||
}
|
||||
|
||||
var _ EthModuleAPI = &EthModuleDummy{}
|
||||
|
@ -64,6 +64,7 @@ type EthModuleAPI interface {
|
||||
EthCall(ctx context.Context, tx ethtypes.EthCall, blkParam string) (ethtypes.EthBytes, error)
|
||||
EthMaxPriorityFeePerGas(ctx context.Context) (ethtypes.EthBigInt, error)
|
||||
EthSendRawTransaction(ctx context.Context, rawTx ethtypes.EthBytes) (ethtypes.EthHash, error)
|
||||
Web3ClientVersion(ctx context.Context) (string, error)
|
||||
}
|
||||
|
||||
type EthEventAPI interface {
|
||||
@ -257,14 +258,11 @@ func (a *EthModule) EthGetTransactionByHash(ctx context.Context, txHash *ethtype
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
c := cid.Undef
|
||||
if a.EthTxHashManager != nil {
|
||||
var err error
|
||||
c, err = a.EthTxHashManager.TransactionHashLookup.GetCidFromHash(*txHash)
|
||||
if err != nil {
|
||||
log.Debug("could not find transaction hash %s in lookup table", txHash.String())
|
||||
}
|
||||
c, err := a.EthTxHashManager.TransactionHashLookup.GetCidFromHash(*txHash)
|
||||
if err != nil {
|
||||
log.Debug("could not find transaction hash %s in lookup table", txHash.String())
|
||||
}
|
||||
|
||||
// This isn't an eth transaction we have the mapping for, so let's look it up as a filecoin message
|
||||
if c == cid.Undef {
|
||||
c = txHash.ToCid()
|
||||
@ -306,25 +304,22 @@ func (a *EthModule) EthGetMessageCidByTransactionHash(ctx context.Context, txHas
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
c := cid.Undef
|
||||
if a.EthTxHashManager != nil {
|
||||
var err error
|
||||
c, err = a.EthTxHashManager.TransactionHashLookup.GetCidFromHash(*txHash)
|
||||
// We fall out of the first condition and continue
|
||||
if errors.Is(err, ethhashlookup.ErrNotFound) {
|
||||
log.Debug("could not find transaction hash %s in lookup table", txHash.String())
|
||||
} else if err != nil {
|
||||
return nil, xerrors.Errorf("database error: %w", err)
|
||||
} else {
|
||||
return &c, nil
|
||||
}
|
||||
c, err := a.EthTxHashManager.TransactionHashLookup.GetCidFromHash(*txHash)
|
||||
// We fall out of the first condition and continue
|
||||
if errors.Is(err, ethhashlookup.ErrNotFound) {
|
||||
log.Debug("could not find transaction hash %s in lookup table", txHash.String())
|
||||
} else if err != nil {
|
||||
return nil, xerrors.Errorf("database error: %w", err)
|
||||
} else {
|
||||
return &c, nil
|
||||
}
|
||||
|
||||
// This isn't an eth transaction we have the mapping for, so let's try looking it up as a filecoin message
|
||||
if c == cid.Undef {
|
||||
c = txHash.ToCid()
|
||||
}
|
||||
|
||||
_, err := a.StateAPI.Chain.GetSignedMessage(ctx, c)
|
||||
_, err = a.StateAPI.Chain.GetSignedMessage(ctx, c)
|
||||
if err == nil {
|
||||
// This is an Eth Tx, Secp message, Or BLS message in the mpool
|
||||
return &c, nil
|
||||
@ -369,14 +364,11 @@ func (a *EthModule) EthGetTransactionCount(ctx context.Context, sender ethtypes.
|
||||
}
|
||||
|
||||
func (a *EthModule) EthGetTransactionReceipt(ctx context.Context, txHash ethtypes.EthHash) (*api.EthTxReceipt, error) {
|
||||
c := cid.Undef
|
||||
if a.EthTxHashManager != nil {
|
||||
var err error
|
||||
c, err = a.EthTxHashManager.TransactionHashLookup.GetCidFromHash(txHash)
|
||||
if err != nil {
|
||||
log.Debug("could not find transaction hash %s in lookup table", txHash.String())
|
||||
}
|
||||
c, err := a.EthTxHashManager.TransactionHashLookup.GetCidFromHash(txHash)
|
||||
if err != nil {
|
||||
log.Debug("could not find transaction hash %s in lookup table", txHash.String())
|
||||
}
|
||||
|
||||
// This isn't an eth transaction we have the mapping for, so let's look it up as a filecoin message
|
||||
if c == cid.Undef {
|
||||
c = txHash.ToCid()
|
||||
@ -509,18 +501,8 @@ func (a *EthModule) EthGetStorageAt(ctx context.Context, ethAddr ethtypes.EthAdd
|
||||
return nil, fmt.Errorf("failed to construct system sender address: %w", err)
|
||||
}
|
||||
|
||||
// TODO super duper hack (raulk). The EVM runtime actor uses the U256 parameter type in
|
||||
// GetStorageAtParams, which serializes as a hex-encoded string. It should serialize
|
||||
// as bytes. We didn't get to fix in time for Iron, so for now we just pass
|
||||
// through the hex-encoded value passed through the Eth JSON-RPC API, by remarshalling it.
|
||||
// We don't fix this at origin (builtin-actors) because we are not updating the bundle
|
||||
// for Iron.
|
||||
tmp, err := position.MarshalJSON()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
params, err := actors.SerializeParams(&evm.GetStorageAtParams{
|
||||
StorageKey: tmp[1 : len(tmp)-1], // TODO strip the JSON-encoding quotes -- yuck
|
||||
StorageKey: position,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to serialize parameters: %w", err)
|
||||
@ -723,6 +705,10 @@ func (a *EthModule) EthSendRawTransaction(ctx context.Context, rawTx ethtypes.Et
|
||||
return ethtypes.EthHashFromTxBytes(rawTx), nil
|
||||
}
|
||||
|
||||
func (a *EthModule) Web3ClientVersion(ctx context.Context) (string, error) {
|
||||
return build.UserVersion(), nil
|
||||
}
|
||||
|
||||
func (a *EthModule) ethCallToFilecoinMessage(ctx context.Context, tx ethtypes.EthCall) (*types.Message, error) {
|
||||
var from address.Address
|
||||
if tx.From == nil || *tx.From == (ethtypes.EthAddress{}) {
|
||||
@ -836,8 +822,9 @@ func (a *EthModule) EthEstimateGas(ctx context.Context, tx ethtypes.EthCall) (et
|
||||
func (a *EthModule) EthCall(ctx context.Context, tx ethtypes.EthCall, blkParam string) (ethtypes.EthBytes, error) {
|
||||
msg, err := a.ethCallToFilecoinMessage(ctx, tx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, xerrors.Errorf("failed to convert ethcall to filecoin message: %w", err)
|
||||
}
|
||||
|
||||
ts, err := a.parseBlkParam(ctx, blkParam)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("cannot parse block param: %s", blkParam)
|
||||
@ -845,11 +832,17 @@ func (a *EthModule) EthCall(ctx context.Context, tx ethtypes.EthCall, blkParam s
|
||||
|
||||
invokeResult, err := a.applyMessage(ctx, msg, ts.Key())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, xerrors.Errorf("failed to apply message: %w", err)
|
||||
}
|
||||
if len(invokeResult.MsgRct.Return) > 0 {
|
||||
|
||||
if msg.To == builtintypes.EthereumAddressManagerActorAddr {
|
||||
// As far as I can tell, the Eth API always returns empty on contract deployment
|
||||
return ethtypes.EthBytes{}, nil
|
||||
|
||||
} else if len(invokeResult.MsgRct.Return) > 0 {
|
||||
return cbg.ReadByteArray(bytes.NewReader(invokeResult.MsgRct.Return), uint64(len(invokeResult.MsgRct.Return)))
|
||||
}
|
||||
|
||||
return ethtypes.EthBytes{}, nil
|
||||
}
|
||||
|
||||
@ -961,18 +954,20 @@ func (e *EthEvent) installEthFilterSpec(ctx context.Context, filterSpec *ethtype
|
||||
// Here the client is looking for events between the head and some future height
|
||||
ts := e.Chain.GetHeaviestTipSet()
|
||||
if maxHeight-ts.Height() > e.MaxFilterHeightRange {
|
||||
return nil, xerrors.Errorf("invalid epoch range")
|
||||
return nil, xerrors.Errorf("invalid epoch range: to block is too far in the future (maximum: %d)", e.MaxFilterHeightRange)
|
||||
}
|
||||
} else if minHeight >= 0 && maxHeight == -1 {
|
||||
// Here the client is looking for events between some time in the past and the current head
|
||||
ts := e.Chain.GetHeaviestTipSet()
|
||||
if ts.Height()-minHeight > e.MaxFilterHeightRange {
|
||||
return nil, xerrors.Errorf("invalid epoch range")
|
||||
return nil, xerrors.Errorf("invalid epoch range: from block is too far in the past (maximum: %d)", e.MaxFilterHeightRange)
|
||||
}
|
||||
|
||||
} else if minHeight >= 0 && maxHeight >= 0 {
|
||||
if minHeight > maxHeight || maxHeight-minHeight > e.MaxFilterHeightRange {
|
||||
return nil, xerrors.Errorf("invalid epoch range")
|
||||
if minHeight > maxHeight {
|
||||
return nil, xerrors.Errorf("invalid epoch range: to block (%d) must be after from block (%d)", minHeight, maxHeight)
|
||||
} else if maxHeight-minHeight > e.MaxFilterHeightRange {
|
||||
return nil, xerrors.Errorf("invalid epoch range: range between to and from blocks is too large (maximum: %d)", e.MaxFilterHeightRange)
|
||||
}
|
||||
}
|
||||
|
||||
@ -987,14 +982,9 @@ func (e *EthEvent) installEthFilterSpec(ctx context.Context, filterSpec *ethtype
|
||||
addresses = append(addresses, a)
|
||||
}
|
||||
|
||||
for idx, vals := range filterSpec.Topics {
|
||||
// Ethereum topics are emitted using `LOG{0..4}` opcodes resulting in topics1..4
|
||||
key := fmt.Sprintf("topic%d", idx+1)
|
||||
keyvals := make([][]byte, len(vals))
|
||||
for i, v := range vals {
|
||||
keyvals[i] = v[:]
|
||||
}
|
||||
keys[key] = keyvals
|
||||
keys, err := parseEthTopics(filterSpec.Topics)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return e.EventFilterManager.Install(ctx, minHeight, maxHeight, tipsetCid, addresses, keys)
|
||||
@ -1019,7 +1009,6 @@ func (e *EthEvent) EthNewFilter(ctx context.Context, filterSpec *ethtypes.EthFil
|
||||
|
||||
return ethtypes.EthFilterID{}, err
|
||||
}
|
||||
|
||||
return ethtypes.EthFilterID(f.ID()), nil
|
||||
}
|
||||
|
||||
@ -1143,14 +1132,12 @@ func (e *EthEvent) EthSubscribe(ctx context.Context, eventType string, params *e
|
||||
case EthSubscribeEventTypeLogs:
|
||||
keys := map[string][][]byte{}
|
||||
if params != nil {
|
||||
for idx, vals := range params.Topics {
|
||||
// Ethereum topics are emitted using `LOG{0..4}` opcodes resulting in topics1..4
|
||||
key := fmt.Sprintf("topic%d", idx+1)
|
||||
keyvals := make([][]byte, len(vals))
|
||||
for i, v := range vals {
|
||||
keyvals[i] = v[:]
|
||||
}
|
||||
keys[key] = keyvals
|
||||
var err error
|
||||
keys, err = parseEthTopics(params.Topics)
|
||||
if err != nil {
|
||||
// clean up any previous filters added and stop the sub
|
||||
_, _ = e.EthUnsubscribe(ctx, sub.id)
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
@ -1237,7 +1224,10 @@ func ethFilterResultFromEvents(evs []*filter.CollectedEvent, sa StateAPI) (*etht
|
||||
var err error
|
||||
|
||||
for _, entry := range ev.Entries {
|
||||
value := ethtypes.EthBytes(leftpad32(decodeLogBytes(entry.Value)))
|
||||
value, err := cborDecodeTopicValue(entry.Value)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if entry.Key == ethtypes.EthTopic1 || entry.Key == ethtypes.EthTopic2 || entry.Key == ethtypes.EthTopic3 || entry.Key == ethtypes.EthTopic4 {
|
||||
log.Topics = append(log.Topics, value)
|
||||
} else {
|
||||
@ -1780,7 +1770,10 @@ func newEthTxReceipt(ctx context.Context, tx ethtypes.EthTx, lookup *api.MsgLook
|
||||
}
|
||||
|
||||
for _, entry := range evt.Entries {
|
||||
value := ethtypes.EthBytes(leftpad32(decodeLogBytes(entry.Value)))
|
||||
value, err := cborDecodeTopicValue(entry.Value)
|
||||
if err != nil {
|
||||
return api.EthTxReceipt{}, xerrors.Errorf("failed to decode event log value: %w", err)
|
||||
}
|
||||
if entry.Key == ethtypes.EthTopic1 || entry.Key == ethtypes.EthTopic2 || entry.Key == ethtypes.EthTopic3 || entry.Key == ethtypes.EthTopic4 {
|
||||
l.Topics = append(l.Topics, value)
|
||||
} else {
|
||||
@ -1891,25 +1884,6 @@ func EthTxHashGC(ctx context.Context, retentionDays int, manager *EthTxHashManag
|
||||
}
|
||||
}
|
||||
|
||||
// decodeLogBytes decodes a CBOR-serialized array into its original form.
|
||||
//
|
||||
// This function swallows errors and returns the original array if it failed
|
||||
// to decode.
|
||||
func decodeLogBytes(orig []byte) []byte {
|
||||
if orig == nil {
|
||||
return orig
|
||||
}
|
||||
decoded, err := cbg.ReadByteArray(bytes.NewReader(orig), uint64(len(orig)))
|
||||
if err != nil {
|
||||
return orig
|
||||
}
|
||||
return decoded
|
||||
}
|
||||
|
||||
// TODO we could also emit full EVM words from the EVM runtime, but not doing so
|
||||
// makes the contract slightly cheaper (and saves storage bytes), at the expense
|
||||
// of having to left pad in the API, which is a pretty acceptable tradeoff at
|
||||
// face value. There may be other protocol implications to consider.
|
||||
func leftpad32(orig []byte) []byte {
|
||||
needed := 32 - len(orig)
|
||||
if needed <= 0 {
|
||||
@ -1919,3 +1893,51 @@ func leftpad32(orig []byte) []byte {
|
||||
copy(ret[needed:], orig)
|
||||
return ret
|
||||
}
|
||||
|
||||
func trimLeadingZeros(b []byte) []byte {
|
||||
for i := range b {
|
||||
if b[i] != 0 {
|
||||
return b[i:]
|
||||
}
|
||||
}
|
||||
return []byte{}
|
||||
}
|
||||
|
||||
func cborEncodeTopicValue(orig []byte) ([]byte, error) {
|
||||
var buf bytes.Buffer
|
||||
err := cbg.WriteByteArray(&buf, trimLeadingZeros(orig))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return buf.Bytes(), nil
|
||||
}
|
||||
|
||||
func cborDecodeTopicValue(orig []byte) ([]byte, error) {
|
||||
if len(orig) == 0 {
|
||||
return orig, nil
|
||||
}
|
||||
decoded, err := cbg.ReadByteArray(bytes.NewReader(orig), uint64(len(orig)))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return leftpad32(decoded), nil
|
||||
}
|
||||
|
||||
func parseEthTopics(topics ethtypes.EthTopicSpec) (map[string][][]byte, error) {
|
||||
keys := map[string][][]byte{}
|
||||
for idx, vals := range topics {
|
||||
if len(vals) == 0 {
|
||||
continue
|
||||
}
|
||||
// Ethereum topics are emitted using `LOG{0..4}` opcodes resulting in topics1..4
|
||||
key := fmt.Sprintf("topic%d", idx+1)
|
||||
for _, v := range vals {
|
||||
encodedVal, err := cborEncodeTopicValue(v[:])
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("failed to encode topic value")
|
||||
}
|
||||
keys[key] = append(keys[key], encodedVal)
|
||||
}
|
||||
}
|
||||
return keys, nil
|
||||
}
|
||||
|
@ -11,9 +11,11 @@ import (
|
||||
"github.com/filecoin-project/go-state-types/crypto"
|
||||
|
||||
"github.com/filecoin-project/lotus/api"
|
||||
"github.com/filecoin-project/lotus/chain/messagesigner"
|
||||
"github.com/filecoin-project/lotus/chain/stmgr"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
"github.com/filecoin-project/lotus/chain/wallet"
|
||||
"github.com/filecoin-project/lotus/chain/wallet/key"
|
||||
"github.com/filecoin-project/lotus/lib/sigs"
|
||||
)
|
||||
|
||||
@ -51,12 +53,20 @@ func (a *WalletAPI) WalletSignMessage(ctx context.Context, k address.Address, ms
|
||||
return nil, xerrors.Errorf("failed to resolve ID address: %w", keyAddr)
|
||||
}
|
||||
|
||||
keyInfo, err := a.Wallet.WalletExport(ctx, k)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
sb, err := messagesigner.SigningBytes(msg, key.ActSigType(keyInfo.Type))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
mb, err := msg.ToStorageBlock()
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("serializing message: %w", err)
|
||||
}
|
||||
|
||||
sig, err := a.Wallet.WalletSign(ctx, keyAddr, mb.Cid().Bytes(), api.MsgMeta{
|
||||
sig, err := a.Wallet.WalletSign(ctx, keyAddr, sb, api.MsgMeta{
|
||||
Type: api.MTChainMsg,
|
||||
Extra: mb.RawData(),
|
||||
})
|
||||
|
@ -2,6 +2,7 @@ package modules
|
||||
|
||||
import (
|
||||
"context"
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
"github.com/multiformats/go-varint"
|
||||
@ -20,6 +21,7 @@ import (
|
||||
"github.com/filecoin-project/lotus/node/config"
|
||||
"github.com/filecoin-project/lotus/node/impl/full"
|
||||
"github.com/filecoin-project/lotus/node/modules/helpers"
|
||||
"github.com/filecoin-project/lotus/node/repo"
|
||||
)
|
||||
|
||||
type EventAPI struct {
|
||||
@ -31,16 +33,16 @@ type EventAPI struct {
|
||||
|
||||
var _ events.EventAPI = &EventAPI{}
|
||||
|
||||
func EthEventAPI(cfg config.ActorEventConfig) func(helpers.MetricsCtx, fx.Lifecycle, *store.ChainStore, *stmgr.StateManager, EventAPI, *messagepool.MessagePool, full.StateAPI, full.ChainAPI) (*full.EthEvent, error) {
|
||||
return func(mctx helpers.MetricsCtx, lc fx.Lifecycle, cs *store.ChainStore, sm *stmgr.StateManager, evapi EventAPI, mp *messagepool.MessagePool, stateapi full.StateAPI, chainapi full.ChainAPI) (*full.EthEvent, error) {
|
||||
func EthEventAPI(cfg config.FevmConfig) func(helpers.MetricsCtx, repo.LockedRepo, fx.Lifecycle, *store.ChainStore, *stmgr.StateManager, EventAPI, *messagepool.MessagePool, full.StateAPI, full.ChainAPI) (*full.EthEvent, 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) (*full.EthEvent, error) {
|
||||
ctx := helpers.LifecycleCtx(mctx, lc)
|
||||
|
||||
ee := &full.EthEvent{
|
||||
Chain: cs,
|
||||
MaxFilterHeightRange: abi.ChainEpoch(cfg.MaxFilterHeightRange),
|
||||
MaxFilterHeightRange: abi.ChainEpoch(cfg.Events.MaxFilterHeightRange),
|
||||
}
|
||||
|
||||
if !cfg.EnableRealTimeFilterAPI {
|
||||
if !cfg.EnableEthRPC || cfg.Events.DisableRealTimeFilterAPI {
|
||||
// all event functionality is disabled
|
||||
// the historic filter API relies on the real time one
|
||||
return ee, nil
|
||||
@ -51,21 +53,32 @@ func EthEventAPI(cfg config.ActorEventConfig) func(helpers.MetricsCtx, fx.Lifecy
|
||||
StateAPI: stateapi,
|
||||
ChainAPI: chainapi,
|
||||
}
|
||||
ee.FilterStore = filter.NewMemFilterStore(cfg.MaxFilters)
|
||||
ee.FilterStore = filter.NewMemFilterStore(cfg.Events.MaxFilters)
|
||||
|
||||
// Start garbage collection for filters
|
||||
lc.Append(fx.Hook{
|
||||
OnStart: func(context.Context) error {
|
||||
go ee.GC(ctx, time.Duration(cfg.FilterTTL))
|
||||
go ee.GC(ctx, time.Duration(cfg.Events.FilterTTL))
|
||||
return nil
|
||||
},
|
||||
})
|
||||
|
||||
// Enable indexing of actor events
|
||||
var eventIndex *filter.EventIndex
|
||||
if cfg.EnableHistoricFilterAPI {
|
||||
if !cfg.Events.DisableHistoricFilterAPI {
|
||||
var dbPath string
|
||||
if cfg.Events.DatabasePath == "" {
|
||||
sqlitePath, err := r.SqlitePath()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dbPath = filepath.Join(sqlitePath, "events.db")
|
||||
} else {
|
||||
dbPath = cfg.Events.DatabasePath
|
||||
}
|
||||
|
||||
var err error
|
||||
eventIndex, err = filter.NewEventIndex(cfg.ActorEventDatabasePath)
|
||||
eventIndex, err = filter.NewEventIndex(dbPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -103,13 +116,13 @@ func EthEventAPI(cfg config.ActorEventConfig) func(helpers.MetricsCtx, fx.Lifecy
|
||||
return *actor.Address, true
|
||||
},
|
||||
|
||||
MaxFilterResults: cfg.MaxFilterResults,
|
||||
MaxFilterResults: cfg.Events.MaxFilterResults,
|
||||
}
|
||||
ee.TipSetFilterManager = &filter.TipSetFilterManager{
|
||||
MaxFilterResults: cfg.MaxFilterResults,
|
||||
MaxFilterResults: cfg.Events.MaxFilterResults,
|
||||
}
|
||||
ee.MemPoolFilterManager = &filter.MemPoolFilterManager{
|
||||
MaxFilterResults: cfg.MaxFilterResults,
|
||||
MaxFilterResults: cfg.Events.MaxFilterResults,
|
||||
}
|
||||
|
||||
const ChainHeadConfidence = 1
|
||||
|
@ -19,26 +19,12 @@ import (
|
||||
|
||||
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) {
|
||||
em := &full.EthModule{
|
||||
Chain: cs,
|
||||
Mpool: mp,
|
||||
StateManager: sm,
|
||||
ChainAPI: chainapi,
|
||||
MpoolAPI: mpoolapi,
|
||||
StateAPI: stateapi,
|
||||
}
|
||||
|
||||
if !cfg.EnableEthHashToFilecoinCidMapping {
|
||||
// mapping functionality disabled. Nothing to do here
|
||||
return em, nil
|
||||
}
|
||||
|
||||
dbPath, err := r.SqlitePath()
|
||||
sqlitePath, err := r.SqlitePath()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
transactionHashLookup, err := ethhashlookup.NewTransactionHashLookup(filepath.Join(dbPath, "txhash.db"))
|
||||
transactionHashLookup, err := ethhashlookup.NewTransactionHashLookup(filepath.Join(sqlitePath, "txhash.db"))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -54,8 +40,6 @@ func EthModuleAPI(cfg config.FevmConfig) func(helpers.MetricsCtx, repo.LockedRep
|
||||
TransactionHashLookup: transactionHashLookup,
|
||||
}
|
||||
|
||||
em.EthTxHashManager = ðTxHashManager
|
||||
|
||||
const ChainHeadConfidence = 1
|
||||
|
||||
ctx := helpers.LifecycleCtx(mctx, lc)
|
||||
@ -80,6 +64,16 @@ func EthModuleAPI(cfg config.FevmConfig) func(helpers.MetricsCtx, repo.LockedRep
|
||||
},
|
||||
})
|
||||
|
||||
return em, nil
|
||||
return &full.EthModule{
|
||||
Chain: cs,
|
||||
Mpool: mp,
|
||||
StateManager: sm,
|
||||
|
||||
ChainAPI: chainapi,
|
||||
MpoolAPI: mpoolapi,
|
||||
StateAPI: stateapi,
|
||||
|
||||
EthTxHashManager: ðTxHashManager,
|
||||
}, nil
|
||||
}
|
||||
}
|
||||
|
@ -1,26 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
set -ex
|
||||
|
||||
REQUIRED=(
|
||||
"ipfs"
|
||||
"sha512sum"
|
||||
)
|
||||
for REQUIRE in "${REQUIRED[@]}"
|
||||
do
|
||||
command -v "${REQUIRE}" >/dev/null 2>&1 || echo >&2 "'${REQUIRE}' must be installed"
|
||||
done
|
||||
|
||||
mkdir bundle
|
||||
pushd bundle
|
||||
|
||||
export IPFS_PATH=`mktemp -d`
|
||||
ipfs init
|
||||
ipfs daemon &
|
||||
PID="$!"
|
||||
trap "kill -9 ${PID}" EXIT
|
||||
sleep 30
|
||||
|
||||
cp "/tmp/workspace/appimage/Lotus-${CIRCLE_TAG}-x86_64.AppImage" .
|
||||
sha512sum "Lotus-${CIRCLE_TAG}-x86_64.AppImage" > "Lotus-${CIRCLE_TAG}-x86_64.AppImage.sha512"
|
||||
ipfs add -q "Lotus-${CIRCLE_TAG}-x86_64.AppImage" > "Lotus-${CIRCLE_TAG}-x86_64.AppImage.cid"
|
||||
popd
|
@ -1,46 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
set -ex
|
||||
|
||||
ARCH=$1
|
||||
|
||||
REQUIRED=(
|
||||
"ipfs"
|
||||
"sha512sum"
|
||||
)
|
||||
for REQUIRE in "${REQUIRED[@]}"
|
||||
do
|
||||
command -v "${REQUIRE}" >/dev/null 2>&1 || echo >&2 "'${REQUIRE}' must be installed"
|
||||
done
|
||||
|
||||
mkdir bundle
|
||||
pushd bundle
|
||||
|
||||
BINARIES=(
|
||||
"lotus"
|
||||
"lotus-miner"
|
||||
"lotus-worker"
|
||||
)
|
||||
|
||||
export IPFS_PATH=`mktemp -d`
|
||||
ipfs init
|
||||
ipfs daemon &
|
||||
PID="$!"
|
||||
trap "kill -9 ${PID}" EXIT
|
||||
sleep 30
|
||||
|
||||
mkdir -p "${ARCH}/lotus"
|
||||
pushd "${ARCH}"
|
||||
for BINARY in "${BINARIES[@]}"
|
||||
do
|
||||
cp "../../${ARCH}/${BINARY}" "lotus/"
|
||||
chmod +x "lotus/${BINARY}"
|
||||
done
|
||||
|
||||
tar -zcvf "../lotus_${CIRCLE_TAG}_${ARCH}-amd64.tar.gz" lotus
|
||||
popd
|
||||
rm -rf "${ARCH}"
|
||||
|
||||
sha512sum "lotus_${CIRCLE_TAG}_${ARCH}-amd64.tar.gz" > "lotus_${CIRCLE_TAG}_${ARCH}-amd64.tar.gz.sha512"
|
||||
|
||||
ipfs add -q "lotus_${CIRCLE_TAG}_${ARCH}-amd64.tar.gz" > "lotus_${CIRCLE_TAG}_${ARCH}-amd64.tar.gz.cid"
|
||||
popd
|
@ -1,121 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
set -e
|
||||
|
||||
ARCH=$1
|
||||
|
||||
pushd bundle
|
||||
|
||||
# make sure we have a token set, api requests won't work otherwise
|
||||
if [ -z "${GITHUB_TOKEN}" ]; then
|
||||
echo "\${GITHUB_TOKEN} not set, publish failed"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
REQUIRED=(
|
||||
"jq"
|
||||
"curl"
|
||||
)
|
||||
for REQUIRE in "${REQUIRED[@]}"
|
||||
do
|
||||
command -v "${REQUIRE}" >/dev/null 2>&1 || echo >&2 "'${REQUIRE}' must be installed"
|
||||
done
|
||||
|
||||
#see if the release already exists by tag
|
||||
RELEASE_RESPONSE=`
|
||||
curl \
|
||||
--header "Authorization: token ${GITHUB_TOKEN}" \
|
||||
"https://api.github.com/repos/${CIRCLE_PROJECT_USERNAME}/${CIRCLE_PROJECT_REPONAME}/releases/tags/${CIRCLE_TAG}"
|
||||
`
|
||||
RELEASE_ID=`echo "${RELEASE_RESPONSE}" | jq '.id'`
|
||||
|
||||
if [ "${RELEASE_ID}" = "null" ]; then
|
||||
echo "creating release"
|
||||
|
||||
COND_CREATE_DISCUSSION=""
|
||||
PRERELEASE=true
|
||||
if [[ ${CIRCLE_TAG} =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
|
||||
COND_CREATE_DISCUSSION="\"discussion_category_name\": \"announcement\","
|
||||
PRERELEASE=false
|
||||
fi
|
||||
|
||||
RELEASE_DATA="{
|
||||
\"tag_name\": \"${CIRCLE_TAG}\",
|
||||
\"target_commitish\": \"${CIRCLE_SHA1}\",
|
||||
${COND_CREATE_DISCUSSION}
|
||||
\"name\": \"${CIRCLE_TAG}\",
|
||||
\"body\": \"\",
|
||||
\"prerelease\": ${PRERELEASE}
|
||||
}"
|
||||
|
||||
# create it if it doesn't exist yet
|
||||
RELEASE_RESPONSE=`
|
||||
curl \
|
||||
--request POST \
|
||||
--header "Authorization: token ${GITHUB_TOKEN}" \
|
||||
--header "Content-Type: application/json" \
|
||||
--data "${RELEASE_DATA}" \
|
||||
"https://api.github.com/repos/$CIRCLE_PROJECT_USERNAME/${CIRCLE_PROJECT_REPONAME}/releases"
|
||||
`
|
||||
else
|
||||
echo "release already exists"
|
||||
fi
|
||||
|
||||
RELEASE_UPLOAD_URL=`echo "${RELEASE_RESPONSE}" | jq -r '.upload_url' | cut -d'{' -f1`
|
||||
echo "Preparing to send artifacts to ${RELEASE_UPLOAD_URL}"
|
||||
|
||||
if [ $ARCH = 'linux' ]; then
|
||||
artifacts=(
|
||||
"lotus_${CIRCLE_TAG}_linux-amd64.tar.gz"
|
||||
"lotus_${CIRCLE_TAG}_linux-amd64.tar.gz.cid"
|
||||
"lotus_${CIRCLE_TAG}_linux-amd64.tar.gz.sha512"
|
||||
)
|
||||
elif [ $ARCH = 'darwin' ]; then
|
||||
artifacts=(
|
||||
"lotus_${CIRCLE_TAG}_darwin-amd64.tar.gz"
|
||||
"lotus_${CIRCLE_TAG}_darwin-amd64.tar.gz.cid"
|
||||
"lotus_${CIRCLE_TAG}_darwin-amd64.tar.gz.sha512"
|
||||
)
|
||||
elif [ $ARCH = 'appimage' ]; then
|
||||
artifacts=(
|
||||
"Lotus-${CIRCLE_TAG}-x86_64.AppImage"
|
||||
"Lotus-${CIRCLE_TAG}-x86_64.AppImage.cid"
|
||||
"Lotus-${CIRCLE_TAG}-x86_64.AppImage.sha512"
|
||||
)
|
||||
else
|
||||
echo "$1 is not a supported architecture to publish a release for" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
for RELEASE_FILE in "${artifacts[@]}"
|
||||
do
|
||||
echo "Uploading ${RELEASE_FILE}..."
|
||||
curl \
|
||||
--request POST \
|
||||
--fail \
|
||||
--header "Authorization: token ${GITHUB_TOKEN}" \
|
||||
--header "Content-Type: application/octet-stream" \
|
||||
--data-binary "@${RELEASE_FILE}" \
|
||||
"$RELEASE_UPLOAD_URL?name=$(basename "${RELEASE_FILE}")"
|
||||
|
||||
echo "Uploaded ${RELEASE_FILE}"
|
||||
done
|
||||
|
||||
popd
|
||||
|
||||
miscellaneous=(
|
||||
"README.md"
|
||||
"LICENSE-MIT"
|
||||
"LICENSE-APACHE"
|
||||
)
|
||||
for MISC in "${miscellaneous[@]}"
|
||||
do
|
||||
echo "Uploading release bundle: ${MISC}"
|
||||
curl \
|
||||
--request POST \
|
||||
--header "Authorization: token ${GITHUB_TOKEN}" \
|
||||
--header "Content-Type: application/octet-stream" \
|
||||
--data-binary "@${MISC}" \
|
||||
"$RELEASE_UPLOAD_URL?name=$(basename "${MISC}")"
|
||||
|
||||
echo "Release bundle uploaded: ${MISC}"
|
||||
done
|
Loading…
Reference in New Issue
Block a user