gateway: Limits and proxy for eth_ methods

This commit is contained in:
Łukasz Magiera 2023-01-05 14:00:34 +01:00
parent 708618d11c
commit 22231dc34f
6 changed files with 379 additions and 535 deletions

View File

@ -1,339 +0,0 @@
module github.com/filecoin-project/lotus
go 1.18
retract v1.14.0 // Accidentally force-pushed tag, use v1.14.1+ instead.
require (
contrib.go.opencensus.io/exporter/prometheus v0.4.0
github.com/BurntSushi/toml v1.1.0
github.com/DataDog/zstd v1.4.1
github.com/GeertJohan/go.rice v1.0.2
github.com/Gurpartap/async v0.0.0-20180927173644-4f7f499dd9ee
github.com/Kubuxu/imtui v0.0.0-20210401140320-41663d68d0fa
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d
github.com/alecthomas/jsonschema v0.0.0-20200530073317-71f438968921
github.com/buger/goterm v1.0.3
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e
github.com/containerd/cgroups v1.0.4
github.com/coreos/go-systemd/v22 v22.3.2
github.com/detailyang/go-fallocate v0.0.0-20180908115635-432fa640bd2e
github.com/dgraph-io/badger/v2 v2.2007.3
github.com/docker/go-units v0.4.0
github.com/drand/drand v1.3.0
github.com/drand/kyber v1.1.7
github.com/dustin/go-humanize v1.0.0
github.com/elastic/go-sysinfo v1.7.0
github.com/elastic/gosigar v0.14.2
github.com/etclabscore/go-openrpc-reflect v0.0.36
github.com/fatih/color v1.13.0
github.com/filecoin-project/dagstore v0.5.2
github.com/filecoin-project/filecoin-ffi v0.30.4-0.20200910194244-f640612a1a1f
github.com/filecoin-project/go-address v1.0.0
github.com/filecoin-project/go-bitfield v0.2.4
github.com/filecoin-project/go-cbor-util v0.0.1
github.com/filecoin-project/go-commp-utils v0.1.3
github.com/filecoin-project/go-crypto v0.0.1
github.com/filecoin-project/go-data-transfer v1.15.2
github.com/filecoin-project/go-fil-commcid v0.1.0
github.com/filecoin-project/go-fil-commp-hashhash v0.1.0
github.com/filecoin-project/go-fil-markets v1.24.0
github.com/filecoin-project/go-jsonrpc v0.1.8
github.com/filecoin-project/go-legs v0.4.4
github.com/filecoin-project/go-padreader v0.0.1
github.com/filecoin-project/go-paramfetch v0.0.4
github.com/filecoin-project/go-state-types v0.1.12-beta
github.com/filecoin-project/go-statemachine v1.0.2
github.com/filecoin-project/go-statestore v0.2.0
github.com/filecoin-project/go-storedcounter v0.1.0
github.com/filecoin-project/index-provider v0.8.1
github.com/filecoin-project/pubsub v1.0.0
github.com/filecoin-project/specs-actors v0.9.15
github.com/filecoin-project/specs-actors/v2 v2.3.6
github.com/filecoin-project/specs-actors/v3 v3.1.2
github.com/filecoin-project/specs-actors/v4 v4.0.2
github.com/filecoin-project/specs-actors/v5 v5.0.6
github.com/filecoin-project/specs-actors/v6 v6.0.2
github.com/filecoin-project/specs-actors/v7 v7.0.1
github.com/filecoin-project/specs-actors/v8 v8.0.1
github.com/filecoin-project/test-vectors/schema v0.0.5
github.com/gbrlsnchs/jwt/v3 v3.0.1
github.com/gdamore/tcell/v2 v2.2.0
github.com/go-kit/kit v0.12.0
github.com/golang/mock v1.6.0
github.com/google/uuid v1.3.0
github.com/gorilla/mux v1.7.4
github.com/gorilla/websocket v1.5.0
github.com/hako/durafmt v0.0.0-20200710122514-c0fb7b4da026
github.com/hannahhoward/go-pubsub v0.0.0-20200423002714-8d62886cc36e
github.com/hashicorp/go-multierror v1.1.1
github.com/hashicorp/golang-lru v0.5.4
github.com/icza/backscanner v0.0.0-20210726202459-ac2ffc679f94
github.com/influxdata/influxdb1-client v0.0.0-20200827194710-b269163b24ab
github.com/ipfs/bbloom v0.0.4
github.com/ipfs/go-bitswap v0.10.2
github.com/ipfs/go-block-format v0.0.3
github.com/ipfs/go-blockservice v0.4.0
github.com/ipfs/go-cid v0.2.0
github.com/ipfs/go-cidutil v0.1.0
github.com/ipfs/go-datastore v0.5.1
github.com/ipfs/go-ds-badger2 v0.1.2
github.com/ipfs/go-ds-leveldb v0.5.0
github.com/ipfs/go-ds-measure v0.2.0
github.com/ipfs/go-fs-lock v0.0.7
github.com/ipfs/go-graphsync v0.13.1
github.com/ipfs/go-ipfs-blockstore v1.2.0
github.com/ipfs/go-ipfs-blocksutil v0.0.1
github.com/ipfs/go-ipfs-chunker v0.0.5
github.com/ipfs/go-ipfs-ds-help v1.1.0
github.com/ipfs/go-ipfs-exchange-interface v0.2.0
github.com/ipfs/go-ipfs-exchange-offline v0.3.0
github.com/ipfs/go-ipfs-files v0.1.1
github.com/ipfs/go-ipfs-http-client v0.4.0
github.com/ipfs/go-ipfs-routing v0.2.1
github.com/ipfs/go-ipfs-util v0.0.2
github.com/ipfs/go-ipld-cbor v0.0.6
github.com/ipfs/go-ipld-format v0.4.0
github.com/ipfs/go-log/v2 v2.5.1
github.com/ipfs/go-merkledag v0.8.0
github.com/ipfs/go-metrics-interface v0.0.1
github.com/ipfs/go-metrics-prometheus v0.0.2
github.com/ipfs/go-unixfs v0.3.1
github.com/ipfs/go-unixfsnode v1.4.0
github.com/ipfs/interface-go-ipfs-core v0.7.0
github.com/ipld/go-car v0.4.0
github.com/ipld/go-car/v2 v2.4.1
github.com/ipld/go-codec-dagpb v1.3.2
github.com/ipld/go-ipld-prime v0.17.0
github.com/ipld/go-ipld-selector-text-lite v0.0.1
github.com/kelseyhightower/envconfig v1.4.0
github.com/koalacxr/quantile v0.0.1
github.com/libp2p/go-buffer-pool v0.1.0
github.com/libp2p/go-libp2p v0.22.0
github.com/libp2p/go-libp2p-kad-dht v0.18.0
github.com/libp2p/go-libp2p-peerstore v0.8.0
github.com/libp2p/go-libp2p-pubsub v0.8.0
github.com/libp2p/go-libp2p-record v0.2.0
github.com/libp2p/go-libp2p-routing-helpers v0.2.3
github.com/libp2p/go-maddr-filter v0.1.0
github.com/mattn/go-isatty v0.0.16
github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1
github.com/mitchellh/go-homedir v1.1.0
github.com/multiformats/go-base32 v0.0.4
github.com/multiformats/go-multiaddr v0.6.0
github.com/multiformats/go-multiaddr-dns v0.3.1
github.com/multiformats/go-multibase v0.1.1
github.com/multiformats/go-multihash v0.2.1
github.com/multiformats/go-varint v0.0.6
github.com/open-rpc/meta-schema v0.0.0-20201029221707-1b72ef2ea333
github.com/opentracing/opentracing-go v1.2.0
github.com/polydawn/refmt v0.0.0-20201211092308-30ac6d18308e
github.com/prometheus/client_golang v1.12.1
github.com/raulk/clock v1.1.0
github.com/raulk/go-watchdog v1.3.0
github.com/stretchr/testify v1.8.0
github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7
github.com/urfave/cli/v2 v2.8.1
github.com/whyrusleeping/bencher v0.0.0-20190829221104-bb6607aa8bba
github.com/whyrusleeping/cbor-gen v0.0.0-20220514204315-f29c37e9c44c
github.com/whyrusleeping/ledger-filecoin-go v0.9.1-0.20201010031517-c3dcc1bddce4
github.com/whyrusleeping/multiaddr-filter v0.0.0-20160516205228-e903e4adabd7
github.com/xorcare/golden v0.6.1-0.20191112154924-b87f686d7542
go.opencensus.io v0.23.0
go.opentelemetry.io/otel v1.7.0
go.opentelemetry.io/otel/bridge/opencensus v0.25.0
go.opentelemetry.io/otel/exporters/jaeger v1.2.0
go.opentelemetry.io/otel/sdk v1.2.0
go.uber.org/fx v1.15.0
go.uber.org/multierr v1.8.0
go.uber.org/zap v1.22.0
golang.org/x/net v0.0.0-20220812174116-3211cb980234
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab
golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac
golang.org/x/tools v0.1.12
golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f
gopkg.in/cheggaaa/pb.v1 v1.0.28
gotest.tools v2.2.0+incompatible
)
require (
github.com/GeertJohan/go.incremental v1.0.0 // indirect
github.com/PuerkitoBio/purell v1.1.1 // indirect
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect
github.com/StackExchange/wmi v1.2.1 // indirect
github.com/Stebalien/go-bitfield v0.0.1 // indirect
github.com/akavel/rsrc v0.8.0 // indirect
github.com/alecthomas/units v0.0.0-20210927113745-59d0afb8317a // indirect
github.com/benbjohnson/clock v1.3.0 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/bep/debounce v1.2.0 // indirect
github.com/cespare/xxhash v1.1.0 // indirect
github.com/cespare/xxhash/v2 v2.1.2 // indirect
github.com/cheekybits/genny v1.0.0 // indirect
github.com/cilium/ebpf v0.4.0 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.1 // indirect
github.com/crackcomm/go-gitignore v0.0.0-20170627025303-887ab5e44cc3 // indirect
github.com/cskr/pubsub v1.0.2 // indirect
github.com/daaku/go.zipexe v1.0.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c // indirect
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0 // indirect
github.com/dgraph-io/ristretto v0.1.0 // indirect
github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2 // indirect
github.com/drand/kyber-bls12381 v0.2.1 // indirect
github.com/elastic/go-windows v1.0.0 // indirect
github.com/etclabscore/go-jsonschema-walk v0.0.6 // indirect
github.com/filecoin-project/go-amt-ipld/v2 v2.1.0 // indirect
github.com/filecoin-project/go-amt-ipld/v3 v3.1.0 // indirect
github.com/filecoin-project/go-amt-ipld/v4 v4.0.0 // indirect
github.com/filecoin-project/go-commp-utils/nonffi v0.0.0-20220905160352-62059082a837 // indirect
github.com/filecoin-project/go-ds-versioning v0.1.1 // indirect
github.com/filecoin-project/go-hamt-ipld v0.1.5 // indirect
github.com/filecoin-project/go-hamt-ipld/v2 v2.0.0 // indirect
github.com/filecoin-project/go-hamt-ipld/v3 v3.1.0 // indirect
github.com/filecoin-project/storetheindex v0.4.17 // indirect
github.com/flynn/noise v1.0.0 // indirect
github.com/francoispqt/gojay v1.2.13 // indirect
github.com/fsnotify/fsnotify v1.5.4 // indirect
github.com/gdamore/encoding v1.0.0 // indirect
github.com/go-kit/log v0.2.0 // indirect
github.com/go-logfmt/logfmt v0.5.1 // indirect
github.com/go-logr/logr v1.2.3 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-ole/go-ole v1.2.5 // indirect
github.com/go-openapi/jsonpointer v0.19.3 // indirect
github.com/go-openapi/jsonreference v0.19.4 // indirect
github.com/go-openapi/spec v0.19.11 // indirect
github.com/go-openapi/swag v0.19.11 // indirect
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 // indirect
github.com/godbus/dbus/v5 v5.1.0 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/glog v1.0.0 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/protobuf v1.5.2 // indirect
github.com/golang/snappy v0.0.4 // indirect
github.com/google/go-cmp v0.5.8 // indirect
github.com/google/gopacket v1.1.19 // indirect
github.com/hannahhoward/cbor-gen-for v0.0.0-20200817222906-ea96cece81f1 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/huin/goupnp v1.0.3 // indirect
github.com/iancoleman/orderedmap v0.1.0 // indirect
github.com/ipfs/go-bitfield v1.0.0 // indirect
github.com/ipfs/go-filestore v1.2.0 // indirect
github.com/ipfs/go-ipfs-cmds v0.7.0 // indirect
github.com/ipfs/go-ipfs-config v0.18.0 // indirect
github.com/ipfs/go-ipfs-delay v0.0.1 // indirect
github.com/ipfs/go-ipfs-posinfo v0.0.1 // indirect
github.com/ipfs/go-ipfs-pq v0.0.2 // indirect
github.com/ipfs/go-ipld-legacy v0.1.1 // indirect
github.com/ipfs/go-ipns v0.2.0 // indirect
github.com/ipfs/go-log v1.0.5 // indirect
github.com/ipfs/go-path v0.3.0 // indirect
github.com/ipfs/go-peertaskqueue v0.7.1 // indirect
github.com/ipfs/go-verifcid v0.0.1 // indirect
github.com/ipsn/go-secp256k1 v0.0.0-20180726113642-9d62b9f0bc52 // indirect
github.com/jackpal/go-nat-pmp v1.0.2 // indirect
github.com/jbenet/go-random v0.0.0-20190219211222-123a90aedc0c // indirect
github.com/jbenet/go-temp-err-catcher v0.1.0 // indirect
github.com/jbenet/goprocess v0.1.4 // indirect
github.com/jessevdk/go-flags v1.4.0 // indirect
github.com/joeshaw/multierror v0.0.0-20140124173710-69b34d4ec901 // indirect
github.com/jonboulle/clockwork v0.2.2 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/jpillora/backoff v1.0.0 // indirect
github.com/kilic/bls12-381 v0.0.0-20200820230200-6b2c19996391 // indirect
github.com/klauspost/compress v1.15.1 // indirect
github.com/klauspost/cpuid/v2 v2.1.0 // indirect
github.com/koron/go-ssdp v0.0.3 // indirect
github.com/libp2p/go-cidranger v1.1.0 // indirect
github.com/libp2p/go-flow-metrics v0.1.0 // indirect
github.com/libp2p/go-libp2p-asn-util v0.2.0 // indirect
github.com/libp2p/go-libp2p-connmgr v0.4.0 // indirect
github.com/libp2p/go-libp2p-core v0.20.0 // indirect
github.com/libp2p/go-libp2p-gostream v0.4.0 // indirect
github.com/libp2p/go-libp2p-kbucket v0.5.0 // indirect
github.com/libp2p/go-libp2p-noise v0.5.0 // indirect
github.com/libp2p/go-libp2p-tls v0.5.0 // indirect
github.com/libp2p/go-msgio v0.2.0 // indirect
github.com/libp2p/go-nat v0.1.0 // indirect
github.com/libp2p/go-netroute v0.2.0 // indirect
github.com/libp2p/go-openssl v0.1.0 // indirect
github.com/libp2p/go-reuseport v0.2.0 // indirect
github.com/libp2p/go-yamux/v3 v3.1.2 // indirect
github.com/lucas-clemente/quic-go v0.28.1 // indirect
github.com/lucasb-eyer/go-colorful v1.0.3 // indirect
github.com/magefile/mage v1.9.0 // indirect
github.com/mailru/easyjson v0.7.6 // indirect
github.com/marten-seemann/qtls-go1-16 v0.1.5 // indirect
github.com/marten-seemann/qtls-go1-17 v0.1.2 // indirect
github.com/marten-seemann/qtls-go1-18 v0.1.2 // indirect
github.com/marten-seemann/qtls-go1-19 v0.1.0 // indirect
github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd // indirect
github.com/mattn/go-colorable v0.1.9 // indirect
github.com/mattn/go-pointer v0.0.1 // indirect
github.com/mattn/go-runewidth v0.0.10 // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect
github.com/miekg/dns v1.1.50 // indirect
github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b // indirect
github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc // indirect
github.com/minio/sha256-simd v1.0.0 // indirect
github.com/mr-tron/base58 v1.2.0 // indirect
github.com/multiformats/go-base36 v0.1.0 // indirect
github.com/multiformats/go-multiaddr-fmt v0.1.0 // indirect
github.com/multiformats/go-multicodec v0.5.0 // indirect
github.com/multiformats/go-multistream v0.3.3 // indirect
github.com/nikkolasg/hexjson v0.0.0-20181101101858-78e39397e00c // indirect
github.com/nkovacs/streamquote v1.0.0 // indirect
github.com/nxadm/tail v1.4.8 // indirect
github.com/onsi/ginkgo v1.16.5 // indirect
github.com/opencontainers/runtime-spec v1.0.2 // indirect
github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 // indirect
github.com/petar/GoLLRB v0.0.0-20210522233825-ae3b015fd3e9 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/prometheus/client_model v0.2.0 // indirect
github.com/prometheus/common v0.37.0 // indirect
github.com/prometheus/procfs v0.8.0 // indirect
github.com/prometheus/statsd_exporter v0.21.0 // indirect
github.com/rivo/uniseg v0.1.0 // indirect
github.com/rs/cors v1.7.0 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/shirou/gopsutil v2.18.12+incompatible // indirect
github.com/sirupsen/logrus v1.8.1 // indirect
github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572 // indirect
github.com/spaolacci/murmur3 v1.1.0 // indirect
github.com/uber/jaeger-client-go v2.25.0+incompatible // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect
github.com/valyala/fasttemplate v1.0.1 // indirect
github.com/whyrusleeping/cbor v0.0.0-20171005072247-63513f603b11 // indirect
github.com/whyrusleeping/chunker v0.0.0-20181014151217-fe64bd25879f // indirect
github.com/whyrusleeping/go-keyspace v0.0.0-20160322163242-5b898ac5add1 // indirect
github.com/whyrusleeping/timecache v0.0.0-20160911033111-cfcb2f1abfee // indirect
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect
github.com/zondax/hid v0.9.1-0.20220302062450-5552068d2266 // indirect
github.com/zondax/ledger-go v0.12.1 // indirect
go.opentelemetry.io/otel/metric v0.25.0 // indirect
go.opentelemetry.io/otel/sdk/export/metric v0.25.0 // indirect
go.opentelemetry.io/otel/trace v1.7.0 // indirect
go.uber.org/atomic v1.10.0 // indirect
go.uber.org/dig v1.12.0 // indirect
go4.org v0.0.0-20200411211856-f5505b9728dd // indirect
golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e // indirect
golang.org/x/exp v0.0.0-20220426173459-3bcf042a4bf5 // indirect
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect
golang.org/x/text v0.3.7 // indirect
google.golang.org/genproto v0.0.0-20210917145530-b395a37504d4 // indirect
google.golang.org/grpc v1.45.0 // indirect
google.golang.org/protobuf v1.28.1 // indirect
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
howett.net/plist v0.0.0-20181124034731-591f970eefbb // indirect
lukechampine.com/blake3 v1.1.7 // indirect
)
replace github.com/filecoin-project/filecoin-ffi => ./extern/filecoin-ffi
replace github.com/filecoin-project/test-vectors => ./extern/test-vectors

View File

@ -1,5 +0,0 @@
commit 2f35a39e435c52270a2d6a4c376325569f3de06a
Author: Łukasz Magiera <magik6k@gmail.com>
Date: Tue Oct 11 10:59:27 2022 +0200
cli docsgen

View File

@ -1,2 +0,0 @@
On branch feat/buildinfo
nothing to commit (use -u to show untracked files)

View File

@ -25,6 +25,10 @@ type perConnLimiterKeyType string
const perConnLimiterKey perConnLimiterKeyType = "limiter" const perConnLimiterKey perConnLimiterKeyType = "limiter"
type filterTrackerKeyType string
const filterTrackerKey filterTrackerKeyType = "filterTracker"
// Handler returns a gateway http.Handler, to be mounted as-is on the server. // Handler returns a gateway http.Handler, to be mounted as-is on the server.
func Handler(gwapi lapi.Gateway, api lapi.FullNode, rateLimit int64, connPerMinute int64, opts ...jsonrpc.ServerOption) (http.Handler, error) { func Handler(gwapi lapi.Gateway, api lapi.FullNode, rateLimit int64, connPerMinute int64, opts ...jsonrpc.ServerOption) (http.Handler, error) {
m := mux.NewRouter() m := mux.NewRouter()
@ -83,8 +87,12 @@ type RateLimiterHandler struct {
} }
func (h RateLimiterHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { func (h RateLimiterHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
r2 := r.WithContext(context.WithValue(r.Context(), perConnLimiterKey, h.limiter)) r = r.WithContext(context.WithValue(r.Context(), perConnLimiterKey, h.limiter))
h.handler.ServeHTTP(w, r2)
// also add a filter tracker to the context
r = r.WithContext(context.WithValue(r.Context(), filterTrackerKey, newFilterTracker()))
h.handler.ServeHTTP(w, r)
} }
// this blocks new connections if there have already been too many. // this blocks new connections if there have already been too many.

View File

@ -20,6 +20,7 @@ import (
"github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/actors/builtin/miner" "github.com/filecoin-project/lotus/chain/actors/builtin/miner"
"github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/chain/types/ethtypes"
_ "github.com/filecoin-project/lotus/lib/sigs/bls" _ "github.com/filecoin-project/lotus/lib/sigs/bls"
_ "github.com/filecoin-project/lotus/lib/sigs/delegated" _ "github.com/filecoin-project/lotus/lib/sigs/delegated"
_ "github.com/filecoin-project/lotus/lib/sigs/secp" _ "github.com/filecoin-project/lotus/lib/sigs/secp"
@ -86,38 +87,38 @@ type TargetAPI interface {
StateVMCirculatingSupplyInternal(context.Context, types.TipSetKey) (api.CirculatingSupply, error) StateVMCirculatingSupplyInternal(context.Context, types.TipSetKey) (api.CirculatingSupply, error)
WalletBalance(context.Context, address.Address) (types.BigInt, error) WalletBalance(context.Context, address.Address) (types.BigInt, error)
EthBlockNumber(ctx context.Context) (api.EthUint64, error) EthBlockNumber(ctx context.Context) (ethtypes.EthUint64, error)
EthGetBlockTransactionCountByNumber(ctx context.Context, blkNum api.EthUint64) (api.EthUint64, error) EthGetBlockTransactionCountByNumber(ctx context.Context, blkNum ethtypes.EthUint64) (ethtypes.EthUint64, error)
EthGetBlockTransactionCountByHash(ctx context.Context, blkHash api.EthHash) (api.EthUint64, error) EthGetBlockTransactionCountByHash(ctx context.Context, blkHash ethtypes.EthHash) (ethtypes.EthUint64, error)
EthGetBlockByHash(ctx context.Context, blkHash api.EthHash, fullTxInfo bool) (api.EthBlock, error) EthGetBlockByHash(ctx context.Context, blkHash ethtypes.EthHash, fullTxInfo bool) (ethtypes.EthBlock, error)
EthGetBlockByNumber(ctx context.Context, blkNum string, fullTxInfo bool) (api.EthBlock, error) EthGetBlockByNumber(ctx context.Context, blkNum string, fullTxInfo bool) (ethtypes.EthBlock, error)
EthGetTransactionByHash(ctx context.Context, txHash *api.EthHash) (*api.EthTx, error) EthGetTransactionByHash(ctx context.Context, txHash *ethtypes.EthHash) (*ethtypes.EthTx, error)
EthGetTransactionCount(ctx context.Context, sender api.EthAddress, blkOpt string) (api.EthUint64, error) EthGetTransactionCount(ctx context.Context, sender ethtypes.EthAddress, blkOpt string) (ethtypes.EthUint64, error)
EthGetTransactionReceipt(ctx context.Context, txHash api.EthHash) (*api.EthTxReceipt, error) EthGetTransactionReceipt(ctx context.Context, txHash ethtypes.EthHash) (*api.EthTxReceipt, error)
EthGetTransactionByBlockHashAndIndex(ctx context.Context, blkHash api.EthHash, txIndex api.EthUint64) (api.EthTx, error) EthGetTransactionByBlockHashAndIndex(ctx context.Context, blkHash ethtypes.EthHash, txIndex ethtypes.EthUint64) (ethtypes.EthTx, error)
EthGetTransactionByBlockNumberAndIndex(ctx context.Context, blkNum api.EthUint64, txIndex api.EthUint64) (api.EthTx, error) EthGetTransactionByBlockNumberAndIndex(ctx context.Context, blkNum ethtypes.EthUint64, txIndex ethtypes.EthUint64) (ethtypes.EthTx, error)
EthGetCode(ctx context.Context, address api.EthAddress, blkOpt string) (api.EthBytes, error) EthGetCode(ctx context.Context, address ethtypes.EthAddress, blkOpt string) (ethtypes.EthBytes, error)
EthGetStorageAt(ctx context.Context, address api.EthAddress, position api.EthBytes, blkParam string) (api.EthBytes, error) EthGetStorageAt(ctx context.Context, address ethtypes.EthAddress, position ethtypes.EthBytes, blkParam string) (ethtypes.EthBytes, error)
EthGetBalance(ctx context.Context, address api.EthAddress, blkParam string) (api.EthBigInt, error) EthGetBalance(ctx context.Context, address ethtypes.EthAddress, blkParam string) (ethtypes.EthBigInt, error)
EthChainId(ctx context.Context) (api.EthUint64, error) EthChainId(ctx context.Context) (ethtypes.EthUint64, error)
NetVersion(ctx context.Context) (string, error) NetVersion(ctx context.Context) (string, error)
NetListening(ctx context.Context) (bool, error) NetListening(ctx context.Context) (bool, error)
EthProtocolVersion(ctx context.Context) (api.EthUint64, error) EthProtocolVersion(ctx context.Context) (ethtypes.EthUint64, error)
EthGasPrice(ctx context.Context) (api.EthBigInt, error) EthGasPrice(ctx context.Context) (ethtypes.EthBigInt, error)
EthFeeHistory(ctx context.Context, blkCount api.EthUint64, newestBlk string, rewardPercentiles []float64) (api.EthFeeHistory, error) EthFeeHistory(ctx context.Context, blkCount ethtypes.EthUint64, newestBlk string, rewardPercentiles []float64) (ethtypes.EthFeeHistory, error)
EthMaxPriorityFeePerGas(ctx context.Context) (api.EthBigInt, error) EthMaxPriorityFeePerGas(ctx context.Context) (ethtypes.EthBigInt, error)
EthEstimateGas(ctx context.Context, tx api.EthCall) (api.EthUint64, error) EthEstimateGas(ctx context.Context, tx ethtypes.EthCall) (ethtypes.EthUint64, error)
EthCall(ctx context.Context, tx api.EthCall, blkParam string) (api.EthBytes, error) EthCall(ctx context.Context, tx ethtypes.EthCall, blkParam string) (ethtypes.EthBytes, error)
EthSendRawTransaction(ctx context.Context, rawTx api.EthBytes) (api.EthHash, error) EthSendRawTransaction(ctx context.Context, rawTx ethtypes.EthBytes) (ethtypes.EthHash, error)
EthGetLogs(ctx context.Context, filter *api.EthFilterSpec) (*api.EthFilterResult, error) EthGetLogs(ctx context.Context, filter *ethtypes.EthFilterSpec) (*ethtypes.EthFilterResult, error)
EthGetFilterChanges(ctx context.Context, id api.EthFilterID) (*api.EthFilterResult, error) EthGetFilterChanges(ctx context.Context, id ethtypes.EthFilterID) (*ethtypes.EthFilterResult, error)
EthGetFilterLogs(ctx context.Context, id api.EthFilterID) (*api.EthFilterResult, error) EthGetFilterLogs(ctx context.Context, id ethtypes.EthFilterID) (*ethtypes.EthFilterResult, error)
EthNewFilter(ctx context.Context, filter *api.EthFilterSpec) (api.EthFilterID, error) EthNewFilter(ctx context.Context, filter *ethtypes.EthFilterSpec) (ethtypes.EthFilterID, error)
EthNewBlockFilter(ctx context.Context) (api.EthFilterID, error) EthNewBlockFilter(ctx context.Context) (ethtypes.EthFilterID, error)
EthNewPendingTransactionFilter(ctx context.Context) (api.EthFilterID, error) EthNewPendingTransactionFilter(ctx context.Context) (ethtypes.EthFilterID, error)
EthUninstallFilter(ctx context.Context, id api.EthFilterID) (bool, error) EthUninstallFilter(ctx context.Context, id ethtypes.EthFilterID) (bool, error)
EthSubscribe(ctx context.Context, eventType string, params *api.EthSubscriptionParams) (<-chan api.EthSubscriptionResponse, error) EthSubscribe(ctx context.Context, eventType string, params *ethtypes.EthSubscriptionParams) (<-chan ethtypes.EthSubscriptionResponse, error)
EthUnsubscribe(ctx context.Context, id api.EthSubscriptionID) (bool, error) EthUnsubscribe(ctx context.Context, id ethtypes.EthSubscriptionID) (bool, error)
} }
var _ TargetAPI = *new(api.FullNode) // gateway depends on latest var _ TargetAPI = *new(api.FullNode) // gateway depends on latest

View File

@ -1,140 +1,236 @@
package gateway package gateway
import ( import (
"bytes"
"context" "context"
"fmt"
"sync"
"time"
"golang.org/x/xerrors"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/big" "github.com/filecoin-project/go-state-types/big"
"github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/chain/types/ethtypes"
) )
func (gw *Node) EthAccounts(ctx context.Context) ([]api.EthAddress, error) { func (gw *Node) EthAccounts(ctx context.Context) ([]ethtypes.EthAddress, error) {
// gateway provides public API, so it can't hold user accounts // gateway provides public API, so it can't hold user accounts
return []api.EthAddress{}, nil return []ethtypes.EthAddress{}, nil
} }
func (gw *Node) EthBlockNumber(ctx context.Context) (api.EthUint64, error) { func (gw *Node) EthBlockNumber(ctx context.Context) (ethtypes.EthUint64, error) {
if err := gw.limit(ctx, stateRateLimitTokens); err != nil { if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
return 0, err return 0, err
} }
//TODO implement me return gw.target.EthBlockNumber(ctx)
panic("implement me")
} }
func (gw *Node) EthGetBlockTransactionCountByNumber(ctx context.Context, blkNum api.EthUint64) (api.EthUint64, error) { func (gw *Node) EthGetBlockTransactionCountByNumber(ctx context.Context, blkNum ethtypes.EthUint64) (ethtypes.EthUint64, error) {
if err := gw.limit(ctx, stateRateLimitTokens); err != nil { if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
return 0, err return 0, err
} }
//TODO implement me head, err := gw.target.ChainHead(ctx)
panic("implement me") if err != nil {
return 0, err
}
if err := gw.checkTipsetHeight(head, abi.ChainEpoch(blkNum)); err != nil {
return 0, err
} }
func (gw *Node) EthGetBlockTransactionCountByHash(ctx context.Context, blkHash api.EthHash) (api.EthUint64, error) { return gw.target.EthGetBlockTransactionCountByNumber(ctx, blkNum)
}
func (gw *Node) tskByEthHash(ctx context.Context, blkHash ethtypes.EthHash) (types.TipSetKey, error) {
tskCid := blkHash.ToCid()
tskBlk, err := gw.target.ChainReadObj(ctx, tskCid)
if err != nil {
return types.EmptyTSK, err
}
tsk := new(types.TipSetKey)
if err := tsk.UnmarshalCBOR(bytes.NewReader(tskBlk)); err != nil {
return types.EmptyTSK, xerrors.Errorf("cannot unmarshal block into tipset key: %w", err)
}
return *tsk, nil
}
func (gw *Node) checkBlkHash(ctx context.Context, blkHash ethtypes.EthHash) error {
tsk, err := gw.tskByEthHash(ctx, blkHash)
if err != nil {
return err
}
return gw.checkTipsetKey(ctx, tsk)
}
func (gw *Node) checkBlkParam(ctx context.Context, blkParam string) error {
if blkParam == "earliest" {
// also not supported in node impl
return fmt.Errorf("block param \"earliest\" is not supported")
}
switch blkParam {
case "pending", "latest":
// those will be recent enough, so we don't need to check
return nil
default:
var num ethtypes.EthUint64
err := num.UnmarshalJSON([]byte(`"` + blkParam + `"`))
if err != nil {
return fmt.Errorf("cannot parse block number: %v", err)
}
head, err := gw.target.ChainHead(ctx)
if err != nil {
return err
}
if err := gw.checkTipsetHeight(head, abi.ChainEpoch(num)); err != nil {
return err
}
}
return nil
}
func (gw *Node) EthGetBlockTransactionCountByHash(ctx context.Context, blkHash ethtypes.EthHash) (ethtypes.EthUint64, error) {
if err := gw.limit(ctx, stateRateLimitTokens); err != nil { if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
return 0, err return 0, err
} }
//TODO implement me if err := gw.checkBlkHash(ctx, blkHash); err != nil {
panic("implement me") return 0, err
} }
func (gw *Node) EthGetBlockByHash(ctx context.Context, blkHash api.EthHash, fullTxInfo bool) (api.EthBlock, error) { return gw.target.EthGetBlockTransactionCountByHash(ctx, blkHash)
}
func (gw *Node) EthGetBlockByHash(ctx context.Context, blkHash ethtypes.EthHash, fullTxInfo bool) (ethtypes.EthBlock, error) {
if err := gw.limit(ctx, stateRateLimitTokens); err != nil { if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
return api.EthBlock{}, err return ethtypes.EthBlock{}, err
} }
//TODO implement me if err := gw.checkBlkHash(ctx, blkHash); err != nil {
panic("implement me") return ethtypes.EthBlock{}, err
} }
func (gw *Node) EthGetBlockByNumber(ctx context.Context, blkNum string, fullTxInfo bool) (api.EthBlock, error) { return gw.target.EthGetBlockByHash(ctx, blkHash, fullTxInfo)
}
func (gw *Node) EthGetBlockByNumber(ctx context.Context, blkNum string, fullTxInfo bool) (ethtypes.EthBlock, error) {
if err := gw.limit(ctx, stateRateLimitTokens); err != nil { if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
return api.EthBlock{}, err return ethtypes.EthBlock{}, err
} }
//TODO implement me if err := gw.checkBlkParam(ctx, blkNum); err != nil {
panic("implement me") return ethtypes.EthBlock{}, err
} }
func (gw *Node) EthGetTransactionByHash(ctx context.Context, txHash *api.EthHash) (*api.EthTx, error) { return gw.target.EthGetBlockByNumber(ctx, blkNum, fullTxInfo)
}
func (gw *Node) EthGetTransactionByHash(ctx context.Context, txHash *ethtypes.EthHash) (*ethtypes.EthTx, error) {
if err := gw.limit(ctx, stateRateLimitTokens); err != nil { if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
return nil, err return nil, err
} }
//TODO implement me return gw.target.EthGetTransactionByHash(ctx, txHash)
panic("implement me")
} }
func (gw *Node) EthGetTransactionCount(ctx context.Context, sender api.EthAddress, blkOpt string) (api.EthUint64, error) { func (gw *Node) EthGetTransactionCount(ctx context.Context, sender ethtypes.EthAddress, blkOpt string) (ethtypes.EthUint64, error) {
if err := gw.limit(ctx, stateRateLimitTokens); err != nil { if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
return 0, err return 0, err
} }
//TODO implement me
panic("implement me") if err := gw.checkBlkParam(ctx, blkOpt); err != nil {
return 0, err
} }
func (gw *Node) EthGetTransactionReceipt(ctx context.Context, txHash api.EthHash) (*api.EthTxReceipt, error) { return gw.target.EthGetTransactionCount(ctx, sender, blkOpt)
}
func (gw *Node) EthGetTransactionReceipt(ctx context.Context, txHash ethtypes.EthHash) (*api.EthTxReceipt, error) {
if err := gw.limit(ctx, stateRateLimitTokens); err != nil { if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
return nil, err return nil, err
} }
//TODO implement me return gw.target.EthGetTransactionReceipt(ctx, txHash)
panic("implement me")
} }
func (gw *Node) EthGetTransactionByBlockHashAndIndex(ctx context.Context, blkHash api.EthHash, txIndex api.EthUint64) (api.EthTx, error) { func (gw *Node) EthGetTransactionByBlockHashAndIndex(ctx context.Context, blkHash ethtypes.EthHash, txIndex ethtypes.EthUint64) (ethtypes.EthTx, error) {
if err := gw.limit(ctx, stateRateLimitTokens); err != nil { if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
return api.EthTx{}, err return ethtypes.EthTx{}, err
} }
//TODO implement me if err := gw.checkBlkHash(ctx, blkHash); err != nil {
panic("implement me") return ethtypes.EthTx{}, err
} }
func (gw *Node) EthGetTransactionByBlockNumberAndIndex(ctx context.Context, blkNum api.EthUint64, txIndex api.EthUint64) (api.EthTx, error) { return gw.target.EthGetTransactionByBlockHashAndIndex(ctx, blkHash, txIndex)
}
func (gw *Node) EthGetTransactionByBlockNumberAndIndex(ctx context.Context, blkNum ethtypes.EthUint64, txIndex ethtypes.EthUint64) (ethtypes.EthTx, error) {
if err := gw.limit(ctx, stateRateLimitTokens); err != nil { if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
return api.EthTx{}, err return ethtypes.EthTx{}, err
} }
//TODO implement me head, err := gw.target.ChainHead(ctx)
panic("implement me") if err != nil {
return ethtypes.EthTx{}, err
}
if err := gw.checkTipsetHeight(head, abi.ChainEpoch(blkNum)); err != nil {
return ethtypes.EthTx{}, err
} }
func (gw *Node) EthGetCode(ctx context.Context, address api.EthAddress, blkOpt string) (api.EthBytes, error) { return gw.target.EthGetTransactionByBlockNumberAndIndex(ctx, blkNum, txIndex)
}
func (gw *Node) EthGetCode(ctx context.Context, address ethtypes.EthAddress, blkOpt string) (ethtypes.EthBytes, error) {
if err := gw.limit(ctx, stateRateLimitTokens); err != nil { if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
return nil, err return nil, err
} }
//TODO implement me if err := gw.checkBlkParam(ctx, blkOpt); err != nil {
panic("implement me") return nil, err
} }
func (gw *Node) EthGetStorageAt(ctx context.Context, address api.EthAddress, position api.EthBytes, blkParam string) (api.EthBytes, error) { return gw.target.EthGetCode(ctx, address, blkOpt)
}
func (gw *Node) EthGetStorageAt(ctx context.Context, address ethtypes.EthAddress, position ethtypes.EthBytes, blkParam string) (ethtypes.EthBytes, error) {
if err := gw.limit(ctx, stateRateLimitTokens); err != nil { if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
return nil, err return nil, err
} }
//TODO implement me if err := gw.checkBlkParam(ctx, blkParam); err != nil {
panic("implement me") return nil, err
} }
func (gw *Node) EthGetBalance(ctx context.Context, address api.EthAddress, blkParam string) (api.EthBigInt, error) { return gw.target.EthGetStorageAt(ctx, address, position, blkParam)
}
func (gw *Node) EthGetBalance(ctx context.Context, address ethtypes.EthAddress, blkParam string) (ethtypes.EthBigInt, error) {
if err := gw.limit(ctx, stateRateLimitTokens); err != nil { if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
return api.EthBigInt(big.Zero()), err return ethtypes.EthBigInt(big.Zero()), err
} }
//TODO implement me if err := gw.checkBlkParam(ctx, blkParam); err != nil {
panic("implement me") return ethtypes.EthBigInt(big.Zero()), err
} }
func (gw *Node) EthChainId(ctx context.Context) (api.EthUint64, error) { return gw.target.EthGetBalance(ctx, address, blkParam)
}
func (gw *Node) EthChainId(ctx context.Context) (ethtypes.EthUint64, error) {
if err := gw.limit(ctx, stateRateLimitTokens); err != nil { if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
return 0, err return 0, err
} }
//TODO implement me
panic("implement me") return gw.target.EthChainId(ctx)
} }
func (gw *Node) NetVersion(ctx context.Context) (string, error) { func (gw *Node) NetVersion(ctx context.Context) (string, error) {
@ -142,8 +238,7 @@ func (gw *Node) NetVersion(ctx context.Context) (string, error) {
return "", err return "", err
} }
//TODO implement me return gw.target.NetVersion(ctx)
panic("implement me")
} }
func (gw *Node) NetListening(ctx context.Context) (bool, error) { func (gw *Node) NetListening(ctx context.Context) (bool, error) {
@ -151,150 +246,236 @@ func (gw *Node) NetListening(ctx context.Context) (bool, error) {
return false, err return false, err
} }
//TODO implement me return gw.target.NetListening(ctx)
panic("implement me")
} }
func (gw *Node) EthProtocolVersion(ctx context.Context) (api.EthUint64, error) { func (gw *Node) EthProtocolVersion(ctx context.Context) (ethtypes.EthUint64, error) {
if err := gw.limit(ctx, stateRateLimitTokens); err != nil { if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
return 0, err return 0, err
} }
//TODO implement me
panic("implement me") return gw.target.EthProtocolVersion(ctx)
} }
func (gw *Node) EthGasPrice(ctx context.Context) (api.EthBigInt, error) { func (gw *Node) EthGasPrice(ctx context.Context) (ethtypes.EthBigInt, error) {
if err := gw.limit(ctx, stateRateLimitTokens); err != nil { if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
return api.EthBigInt(big.Zero()), err return ethtypes.EthBigInt(big.Zero()), err
}
//TODO implement me
panic("implement me")
} }
func (gw *Node) EthFeeHistory(ctx context.Context, blkCount api.EthUint64, newestBlk string, rewardPercentiles []float64) (api.EthFeeHistory, error) { return gw.target.EthGasPrice(ctx)
}
var EthFeeHistoryMaxBlockCount = 128 // this seems to be expensive; todo: figure out what is a good number that works with everything
func (gw *Node) EthFeeHistory(ctx context.Context, blkCount ethtypes.EthUint64, newestBlk string, rewardPercentiles []float64) (ethtypes.EthFeeHistory, error) {
if err := gw.limit(ctx, stateRateLimitTokens); err != nil { if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
return api.EthFeeHistory{}, err return ethtypes.EthFeeHistory{}, err
} }
//TODO implement me if err := gw.checkBlkParam(ctx, newestBlk); err != nil {
panic("implement me") return ethtypes.EthFeeHistory{}, err
} }
func (gw *Node) EthMaxPriorityFeePerGas(ctx context.Context) (api.EthBigInt, error) { if blkCount > ethtypes.EthUint64(EthFeeHistoryMaxBlockCount) {
return ethtypes.EthFeeHistory{}, fmt.Errorf("block count too high")
}
return gw.target.EthFeeHistory(ctx, blkCount, newestBlk, rewardPercentiles)
}
func (gw *Node) EthMaxPriorityFeePerGas(ctx context.Context) (ethtypes.EthBigInt, error) {
if err := gw.limit(ctx, stateRateLimitTokens); err != nil { if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
return api.EthBigInt(big.Zero()), err return ethtypes.EthBigInt(big.Zero()), err
}
//TODO implement me
panic("implement me")
} }
func (gw *Node) EthEstimateGas(ctx context.Context, tx api.EthCall) (api.EthUint64, error) { return gw.target.EthMaxPriorityFeePerGas(ctx)
}
func (gw *Node) EthEstimateGas(ctx context.Context, tx ethtypes.EthCall) (ethtypes.EthUint64, error) {
if err := gw.limit(ctx, stateRateLimitTokens); err != nil { if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
return 0, err return 0, err
} }
//TODO implement me
panic("implement me") // todo limit gas? to what?
return gw.target.EthEstimateGas(ctx, tx)
} }
func (gw *Node) EthCall(ctx context.Context, tx api.EthCall, blkParam string) (api.EthBytes, error) { func (gw *Node) EthCall(ctx context.Context, tx ethtypes.EthCall, blkParam string) (ethtypes.EthBytes, error) {
if err := gw.limit(ctx, stateRateLimitTokens); err != nil { if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
return nil, err return nil, err
} }
//TODO implement me if err := gw.checkBlkParam(ctx, blkParam); err != nil {
panic("implement me") return nil, err
} }
func (gw *Node) EthSendRawTransaction(ctx context.Context, rawTx api.EthBytes) (api.EthHash, error) { // todo limit gas? to what?
return gw.target.EthCall(ctx, tx, blkParam)
}
func (gw *Node) EthSendRawTransaction(ctx context.Context, rawTx ethtypes.EthBytes) (ethtypes.EthHash, error) {
if err := gw.limit(ctx, stateRateLimitTokens); err != nil { if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
return api.EthHash{}, err return ethtypes.EthHash{}, err
} }
//TODO implement me return gw.target.EthSendRawTransaction(ctx, rawTx)
panic("implement me")
} }
func (gw *Node) EthGetLogs(ctx context.Context, filter *api.EthFilterSpec) (*api.EthFilterResult, error) { func (gw *Node) EthGetLogs(ctx context.Context, filter *ethtypes.EthFilterSpec) (*ethtypes.EthFilterResult, error) {
if err := gw.limit(ctx, stateRateLimitTokens); err != nil { if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
return nil, err return nil, err
} }
//TODO implement me if filter.FromBlock != nil {
panic("implement me") if err := gw.checkBlkParam(ctx, *filter.FromBlock); err != nil {
}
func (gw *Node) EthGetFilterChanges(ctx context.Context, id api.EthFilterID) (*api.EthFilterResult, error) {
if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
return nil, err return nil, err
} }
//TODO implement me
panic("implement me")
} }
if filter.ToBlock != nil {
func (gw *Node) EthGetFilterLogs(ctx context.Context, id api.EthFilterID) (*api.EthFilterResult, error) { if err := gw.checkBlkParam(ctx, *filter.ToBlock); err != nil {
if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
return nil, err return nil, err
} }
}
if filter.BlockHash != nil {
if err := gw.checkBlkHash(ctx, *filter.BlockHash); err != nil {
return nil, err
}
}
//TODO implement me return gw.target.EthGetLogs(ctx, filter)
panic("implement me")
} }
/* FILTERS: Those are stateful.. figure out how to properly either bind them to users, or time out? */ /* FILTERS: Those are stateful.. figure out how to properly either bind them to users, or time out? */
func (gw *Node) EthNewFilter(ctx context.Context, filter *api.EthFilterSpec) (api.EthFilterID, error) { func (gw *Node) EthGetFilterChanges(ctx context.Context, id ethtypes.EthFilterID) (*ethtypes.EthFilterResult, error) {
if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
return api.EthFilterID{}, err
}
//TODO implement me
panic("implement me")
}
func (gw *Node) EthNewBlockFilter(ctx context.Context) (api.EthFilterID, error) {
if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
return api.EthFilterID{}, err
}
//TODO implement me
panic("implement me")
}
func (gw *Node) EthNewPendingTransactionFilter(ctx context.Context) (api.EthFilterID, error) {
if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
return api.EthFilterID{}, err
}
//TODO implement me
panic("implement me")
}
func (gw *Node) EthUninstallFilter(ctx context.Context, id api.EthFilterID) (bool, error) {
// todo rate limit this?
if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
return false, err
}
//TODO implement me
panic("implement me")
}
func (gw *Node) EthSubscribe(ctx context.Context, eventType string, params *api.EthSubscriptionParams) (<-chan api.EthSubscriptionResponse, error) {
if err := gw.limit(ctx, stateRateLimitTokens); err != nil { if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
return nil, err return nil, err
} }
//TODO implement me ft := filterTrackerFromContext(ctx)
panic("implement me") ft.lk.Lock()
_, ok := ft.userFilters[id]
ft.lk.Unlock()
if !ok {
return nil, nil
} }
func (gw *Node) EthUnsubscribe(ctx context.Context, id api.EthSubscriptionID) (bool, error) { return gw.target.EthGetFilterChanges(ctx, id)
// todo should we actually rate limit this }
func (gw *Node) EthGetFilterLogs(ctx context.Context, id ethtypes.EthFilterID) (*ethtypes.EthFilterResult, error) {
if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
return nil, err
}
ft := filterTrackerFromContext(ctx)
ft.lk.Lock()
_, ok := ft.userFilters[id]
ft.lk.Unlock()
if !ok {
return nil, nil
}
return gw.target.EthGetFilterLogs(ctx, id)
}
func (gw *Node) EthNewFilter(ctx context.Context, filter *ethtypes.EthFilterSpec) (ethtypes.EthFilterID, error) {
if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
return ethtypes.EthFilterID{}, err
}
return addUserFilterLimited(ctx, func() (ethtypes.EthFilterID, error) {
return gw.target.EthNewFilter(ctx, filter)
})
}
func (gw *Node) EthNewBlockFilter(ctx context.Context) (ethtypes.EthFilterID, error) {
if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
return ethtypes.EthFilterID{}, err
}
return addUserFilterLimited(ctx, func() (ethtypes.EthFilterID, error) {
return gw.target.EthNewBlockFilter(ctx)
})
}
func (gw *Node) EthNewPendingTransactionFilter(ctx context.Context) (ethtypes.EthFilterID, error) {
if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
return ethtypes.EthFilterID{}, err
}
return addUserFilterLimited(ctx, func() (ethtypes.EthFilterID, error) {
return gw.target.EthNewPendingTransactionFilter(ctx)
})
}
func (gw *Node) EthUninstallFilter(ctx context.Context, id ethtypes.EthFilterID) (bool, error) {
if err := gw.limit(ctx, stateRateLimitTokens); err != nil { if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
return false, err return false, err
} }
//TODO implement me // check if the filter belongs to this connection
panic("implement me") ft := filterTrackerFromContext(ctx)
ft.lk.Lock()
defer ft.lk.Unlock()
if _, ok := ft.userFilters[id]; !ok {
return false, nil
}
ok, err := gw.target.EthUninstallFilter(ctx, id)
if err != nil {
return false, err
}
delete(ft.userFilters, id)
return ok, nil
}
func (gw *Node) EthSubscribe(ctx context.Context, eventType string, params *ethtypes.EthSubscriptionParams) (<-chan ethtypes.EthSubscriptionResponse, error) {
return nil, xerrors.Errorf("not implemented")
}
func (gw *Node) EthUnsubscribe(ctx context.Context, id ethtypes.EthSubscriptionID) (bool, error) {
return false, xerrors.Errorf("not implemented")
}
var EthMaxFiltersPerConn = 16 // todo make this configurable
func addUserFilterLimited(ctx context.Context, cb func() (ethtypes.EthFilterID, error)) (ethtypes.EthFilterID, error) {
ft := filterTrackerFromContext(ctx)
ft.lk.Lock()
defer ft.lk.Unlock()
if len(ft.userFilters) >= EthMaxFiltersPerConn {
return ethtypes.EthFilterID{}, fmt.Errorf("too many filters")
}
id, err := cb()
if err != nil {
return id, err
}
ft.userFilters[id] = time.Now()
return id, nil
}
func filterTrackerFromContext(ctx context.Context) *filterTracker {
return ctx.Value(filterTrackerKey).(*filterTracker)
}
type filterTracker struct {
lk sync.Mutex
userFilters map[ethtypes.EthFilterID]time.Time
}
// called per request (ws connection)
func newFilterTracker() *filterTracker {
return &filterTracker{
userFilters: make(map[ethtypes.EthFilterID]time.Time),
}
} }