From 8970e6d09cb80e277cc004acddfc4c87b50e6075 Mon Sep 17 00:00:00 2001 From: Ishan Date: Wed, 17 Jan 2024 12:17:01 +0100 Subject: [PATCH 1/6] =?UTF-8?q?=F0=9F=8C=B1=20Add=20chain=20utils?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Makefile | 8 ++ go.mod | 39 +++++++- go.sum | 192 ++++++++++++++++++++++++++++++++++++++- pkg/chain/chain.go | 86 ++++++++++++++++++ pkg/chain/chain_mocks.go | 59 ++++++++++++ pkg/chain/chain_test.go | 119 ++++++++++++++++++++++++ pkg/chain/eth_client.go | 64 +++++++++++++ 7 files changed, 563 insertions(+), 4 deletions(-) create mode 100644 pkg/chain/chain_mocks.go create mode 100644 pkg/chain/chain_test.go create mode 100644 pkg/chain/eth_client.go diff --git a/Makefile b/Makefile index ffb9b7d..83d8818 100644 --- a/Makefile +++ b/Makefile @@ -8,11 +8,19 @@ test: @echo "Test packages" @go test -race -shuffle=on -coverprofile=coverage.out -cover $(PKGS) +test.coverage: test + go tool cover -func=coverage.out + +test.coverage.html: test + go tool cover -html=coverage.out + lint: @go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest golangci-lint run + format: gofmt -s -w . + godocs: @go install golang.org/x/tools/cmd/godoc@latest @echo "open http://localhost:6060/pkg/github.com/LiskHQ/op-fault-detector" diff --git a/go.mod b/go.mod index beecaed..c9c98d0 100644 --- a/go.mod +++ b/go.mod @@ -2,6 +2,41 @@ module github.com/LiskHQ/op-fault-detector go 1.21.5 -require go.uber.org/zap v1.26.0 +require ( + github.com/ethereum/go-ethereum v1.13.10 + github.com/stretchr/testify v1.8.4 + go.uber.org/zap v1.26.0 +) -require go.uber.org/multierr v1.10.0 // indirect +require ( + github.com/Microsoft/go-winio v0.6.1 // indirect + github.com/StackExchange/wmi v1.2.1 // indirect + github.com/bits-and-blooms/bitset v1.10.0 // indirect + github.com/btcsuite/btcd/btcec/v2 v2.2.0 // indirect + github.com/consensys/bavard v0.1.13 // indirect + github.com/consensys/gnark-crypto v0.12.1 // indirect + github.com/crate-crypto/go-kzg-4844 v0.7.0 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/deckarep/golang-set/v2 v2.1.0 // indirect + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect + github.com/ethereum/c-kzg-4844 v0.4.0 // indirect + github.com/go-ole/go-ole v1.2.5 // indirect + github.com/gorilla/websocket v1.4.2 // indirect + github.com/holiman/uint256 v1.2.4 // indirect + github.com/mmcloughlin/addchain v0.4.0 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible // indirect + github.com/stretchr/objx v0.5.0 // indirect + github.com/supranational/blst v0.3.11 // indirect + github.com/tklauser/go-sysconf v0.3.12 // indirect + github.com/tklauser/numcpus v0.6.1 // indirect + go.uber.org/multierr v1.10.0 // indirect + golang.org/x/crypto v0.17.0 // indirect + golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa // indirect + golang.org/x/mod v0.14.0 // indirect + golang.org/x/sync v0.5.0 // indirect + golang.org/x/sys v0.15.0 // indirect + golang.org/x/tools v0.15.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect + rsc.io/tmplfunc v0.0.3 // indirect +) diff --git a/go.sum b/go.sum index f39e3a4..6bd8bfe 100644 --- a/go.sum +++ b/go.sum @@ -1,14 +1,202 @@ +github.com/DataDog/zstd v1.4.5 h1:EndNeuB0l9syBZhut0wns3gV1hL8zX8LIu6ZiVHWLIQ= +github.com/DataDog/zstd v1.4.5/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo= +github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= +github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= +github.com/StackExchange/wmi v1.2.1 h1:VIkavFPXSjcnS+O8yTq7NI32k0R5Aj+v39y29VYDOSA= +github.com/StackExchange/wmi v1.2.1/go.mod h1:rcmrprowKIVzvc+NUiLncP2uuArMWLCbu9SBzvHz7e8= +github.com/VictoriaMetrics/fastcache v1.12.1 h1:i0mICQuojGDL3KblA7wUNlY5lOK6a4bwt3uRKnkZU40= +github.com/VictoriaMetrics/fastcache v1.12.1/go.mod h1:tX04vaqcNoQeGLD+ra5pU5sWkuxnzWhEzLwhP9w653o= +github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/bits-and-blooms/bitset v1.10.0 h1:ePXTeiPEazB5+opbv5fr8umg2R/1NlzgDsyepwsSr88= +github.com/bits-and-blooms/bitset v1.10.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= +github.com/btcsuite/btcd/btcec/v2 v2.2.0 h1:fzn1qaOt32TuLjFlkzYSsBC35Q3KUjT1SwPxiMSCF5k= +github.com/btcsuite/btcd/btcec/v2 v2.2.0/go.mod h1:U7MHm051Al6XmscBQ0BoNydpOTsFAn707034b5nY8zU= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 h1:q0rUy8C/TYNBQS1+CGKw68tLOFYSNEs0TFnxxnS9+4U= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= +github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= +github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cockroachdb/errors v1.8.1 h1:A5+txlVZfOqFBDa4mGz2bUWSp0aHElvHX2bKkdbQu+Y= +github.com/cockroachdb/errors v1.8.1/go.mod h1:qGwQn6JmZ+oMjuLwjWzUNqblqk0xl4CVV3SQbGwK7Ac= +github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f h1:o/kfcElHqOiXqcou5a3rIlMc7oJbMQkeLk0VQJ7zgqY= +github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f/go.mod h1:i/u985jwjWRlyHXQbwatDASoW0RMlZ/3i9yJHE2xLkI= +github.com/cockroachdb/pebble v0.0.0-20230928194634-aa077af62593 h1:aPEJyR4rPBvDmeyi+l/FS/VtA00IWvjeFvjen1m1l1A= +github.com/cockroachdb/pebble v0.0.0-20230928194634-aa077af62593/go.mod h1:6hk1eMY/u5t+Cf18q5lFMUA1Rc+Sm5I6Ra1QuPyxXCo= +github.com/cockroachdb/redact v1.0.8 h1:8QG/764wK+vmEYoOlfobpe12EQcS81ukx/a4hdVMxNw= +github.com/cockroachdb/redact v1.0.8/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg= +github.com/cockroachdb/sentry-go v0.6.1-cockroachdb.2 h1:IKgmqgMQlVJIZj19CdocBeSfSaiCbEBZGKODaixqtHM= +github.com/cockroachdb/sentry-go v0.6.1-cockroachdb.2/go.mod h1:8BT+cPK6xvFOcRlk0R8eg+OTkcqI6baNH4xAkpiYVvQ= +github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 h1:zuQyyAKVxetITBuuhv3BI9cMrmStnpT18zmgmTxunpo= +github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06/go.mod h1:7nc4anLGjupUW/PeY5qiNYsdNXj7zopG+eqsS7To5IQ= +github.com/consensys/bavard v0.1.13 h1:oLhMLOFGTLdlda/kma4VOJazblc7IM5y5QPd2A/YjhQ= +github.com/consensys/bavard v0.1.13/go.mod h1:9ItSMtA/dXMAiL7BG6bqW2m3NdSEObYWoH223nGHukI= +github.com/consensys/gnark-crypto v0.12.1 h1:lHH39WuuFgVHONRl3J0LRBtuYdQTumFSDtJF7HpyG8M= +github.com/consensys/gnark-crypto v0.12.1/go.mod h1:v2Gy7L/4ZRosZ7Ivs+9SfUDr0f5UlG+EM5t7MPHiLuY= +github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w= +github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/crate-crypto/go-ipa v0.0.0-20231025140028-3c0104f4b233 h1:d28BXYi+wUpz1KBmiF9bWrjEMacUEREV6MBi2ODnrfQ= +github.com/crate-crypto/go-ipa v0.0.0-20231025140028-3c0104f4b233/go.mod h1:geZJZH3SzKCqnz5VT0q/DyIG/tvu/dZk+VIfXicupJs= +github.com/crate-crypto/go-kzg-4844 v0.7.0 h1:C0vgZRk4q4EZ/JgPfzuSoxdCq3C3mOZMBShovmncxvA= +github.com/crate-crypto/go-kzg-4844 v0.7.0/go.mod h1:1kMhvPgI0Ky3yIa+9lFySEBUBXkYxeOi8ZF1sYioxhc= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/deckarep/golang-set/v2 v2.1.0 h1:g47V4Or+DUdzbs8FxCCmgb6VYd+ptPAngjM6dtGktsI= +github.com/deckarep/golang-set/v2 v2.1.0/go.mod h1:VAky9rY/yGXJOLEDv3OMci+7wtDpOF4IN+y82NBOac4= +github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK09Y2A4Xv7EE0= +github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 h1:YLtO71vCjJRCBcrPMtQ9nqBsqpA1m5sE92cU+pd5Mcc= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= +github.com/ethereum/c-kzg-4844 v0.4.0 h1:3MS1s4JtA868KpJxroZoepdV0ZKBp3u/O5HcZ7R3nlY= +github.com/ethereum/c-kzg-4844 v0.4.0/go.mod h1:VewdlzQmpT5QSrVhbBuGoCdFJkpaJlO1aQputP83wc0= +github.com/ethereum/go-ethereum v1.13.10 h1:Ppdil79nN+Vc+mXfge0AuUgmKWuVv4eMqzoIVSdqZek= +github.com/ethereum/go-ethereum v1.13.10/go.mod h1:sc48XYQxCzH3fG9BcrXCOOgQk2JfZzNAmIKnceogzsA= +github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 h1:FtmdgXiUlNeRsoNMFlKLDt+S+6hbjVMEW6RGQ7aUf7c= +github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= +github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= +github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= +github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff h1:tY80oXqGNY4FhTFhk+o9oFHGINQ/+vhlm8HFzi6znCI= +github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= +github.com/gballet/go-verkle v0.1.1-0.20231031103413-a67434b50f46 h1:BAIP2GihuqhwdILrV+7GJel5lyPV3u1+PgzrWLc0TkE= +github.com/gballet/go-verkle v0.1.1-0.20231031103413-a67434b50f46/go.mod h1:QNpY22eby74jVhqH4WhDLDwxc/vqsern6pW+u2kbkpc= +github.com/go-ole/go-ole v1.2.5 h1:t4MGB5xEDZvXI+0rMjjsfBsD7yAgp/s9ZDkL1JndXwY= +github.com/go-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= +github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw= +github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= +github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= +github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg= +github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= +github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= +github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb h1:PBC98N2aIaM3XXiurYmW7fx4GZkL8feAMVq7nEjURHk= +github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= +github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= +github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/hashicorp/go-bexpr v0.1.10 h1:9kuI5PFotCboP3dkDYFr/wi0gg0QVbSNz5oFRpxn4uE= +github.com/hashicorp/go-bexpr v0.1.10/go.mod h1:oxlubA2vC/gFVfX1A6JGp7ls7uCDlfJn732ehYYg+g0= +github.com/holiman/billy v0.0.0-20230718173358-1c7e68d277a7 h1:3JQNjnMRil1yD0IfZKHF9GxxWKDJGj8I0IqOUol//sw= +github.com/holiman/billy v0.0.0-20230718173358-1c7e68d277a7/go.mod h1:5GuXa7vkL8u9FkFuWdVvfR5ix8hRB7DbOAaYULamFpc= +github.com/holiman/bloomfilter/v2 v2.0.3 h1:73e0e/V0tCydx14a0SCYS/EWCxgwLZ18CZcZKVu0fao= +github.com/holiman/bloomfilter/v2 v2.0.3/go.mod h1:zpoh+gs7qcpqrHr3dB55AMiJwo0iURXE7ZOP9L9hSkA= +github.com/holiman/uint256 v1.2.4 h1:jUc4Nk8fm9jZabQuqr2JzednajVmBpC+oiTiXZJEApU= +github.com/holiman/uint256 v1.2.4/go.mod h1:EOMSn4q6Nyt9P6efbI3bueV4e1b3dGlUCXeiRV4ng7E= +github.com/huin/goupnp v1.3.0 h1:UvLUlWDNpoUdYzb2TCn+MuTWtcjXKSza2n6CBdQ0xXc= +github.com/huin/goupnp v1.3.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8= +github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus= +github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= +github.com/klauspost/compress v1.15.15 h1:EF27CXIuDsYJ6mmvtBRlEuB2UVOqHG1tAXgZ7yIO+lw= +github.com/klauspost/compress v1.15.15/go.mod h1:ZcK2JAFqKOpnBlxcLsJzYfrS9X1akm9fHZNnD9+Vo/4= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= +github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= +github.com/leanovate/gopter v0.2.9 h1:fQjYxZaynp97ozCzfOyOuAGOU4aU/z37zf/tOujFk7c= +github.com/leanovate/gopter v0.2.9/go.mod h1:U2L/78B+KVFIx2VmW6onHJQzXtFb+p5y3y2Sh+Jxxv8= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng= +github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU= +github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 h1:I0XW9+e1XWDxdcEniV4rQAIOPUGDq67JSCiRCgGCZLI= +github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= +github.com/mitchellh/mapstructure v1.4.1 h1:CpVNEelQCZBooIPDn+AR3NpivK/TIKU8bDxdASFVQag= +github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mitchellh/pointerstructure v1.2.0 h1:O+i9nHnXS3l/9Wu7r4NrEdwA2VFTicjUEN1uBnDo34A= +github.com/mitchellh/pointerstructure v1.2.0/go.mod h1:BRAsLI5zgXmw97Lf6s25bs8ohIXc3tViBH44KcwB2g4= +github.com/mmcloughlin/addchain v0.4.0 h1:SobOdjm2xLj1KkXN5/n0xTIWyZA2+s99UCY1iPfkHRY= +github.com/mmcloughlin/addchain v0.4.0/go.mod h1:A86O+tHqZLMNO4w6ZZ4FlVQEadcoqkyU72HC5wJ4RlU= +github.com/mmcloughlin/profile v0.1.1/go.mod h1:IhHD7q1ooxgwTgjxQYkACGA77oFTDdFVejUS1/tS/qU= +github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= +github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= -github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/prometheus/client_golang v1.12.0 h1:C+UIj/QWtmqY13Arb8kwMt5j34/0Z2iKamrJ+ryC0Gg= +github.com/prometheus/client_golang v1.12.0/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= +github.com/prometheus/client_model v0.2.1-0.20210607210712-147c58e9608a h1:CmF68hwI0XsOQ5UwlBopMi2Ow4Pbg32akc4KIVCOm+Y= +github.com/prometheus/client_model v0.2.1-0.20210607210712-147c58e9608a/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w= +github.com/prometheus/common v0.32.1 h1:hWIdL3N2HoUx3B8j3YN9mWor0qhY/NlEKZEaXxuIRh4= +github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= +github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU= +github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= +github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= +github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= +github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= +github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= +github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik= +github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= +github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible h1:Bn1aCHHRnjv4Bl16T8rcaFjYSrGrIZvpiGO6P3Q4GpU= +github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= +github.com/status-im/keycard-go v0.2.0 h1:QDLFswOQu1r5jsycloeQh3bVU8n/NatHHaZobtDnDzA= +github.com/status-im/keycard-go v0.2.0/go.mod h1:wlp8ZLbsmrF6g6WjugPAx+IzoLrkdf9+mHxBEeo3Hbg= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/supranational/blst v0.3.11 h1:LyU6FolezeWAhvQk0k6O/d49jqgO52MSDDfYgbeoEm4= +github.com/supranational/blst v0.3.11/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw= +github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= +github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= +github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU= +github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI= +github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk= +github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY= +github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8= +github.com/tyler-smith/go-bip39 v1.1.0/go.mod h1:gUYDtqQw1JS3ZJ8UWVcGTGqqr6YIN3CWg+kkNaLt55U= +github.com/urfave/cli/v2 v2.25.7 h1:VAzn5oq403l5pHjc4OhD54+XGO9cdKVL/7lDjF+iKUs= +github.com/urfave/cli/v2 v2.25.7/go.mod h1:8qnjx1vcq5s2/wpsqoZFndg2CE5tNFyrTvS6SinrnYQ= +github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU= +github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8= go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk= go.uber.org/goleak v1.2.0/go.mod h1:XJYK+MuIchqpmGmUSAzotztawfKvYLUIgg7guXrwVUo= go.uber.org/multierr v1.10.0 h1:S0h4aNzvfcFsC3dRF1jLoaov7oRaKqRGC/pUEJ2yvPQ= go.uber.org/multierr v1.10.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= +golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k= +golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= +golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa h1:FRnLl4eNAQl8hwxVVC17teOw8kdjVDVAiFMtgUdTSRQ= +golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa/go.mod h1:zk2irFbV9DP96SEBUUAy67IdHUaZuSnrz1n472HUCLE= +golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0= +golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE= +golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= +golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= +golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.15.0 h1:zdAyfUGbYmuVokhzVmghFl2ZJh5QhcfebBgmVPFYA+8= +golang.org/x/tools v0.15.0/go.mod h1:hpksKq4dtpQWS1uQ61JkdqWM3LscIS6Slf+VVkm+wQk= +google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ= +google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8= +gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +rsc.io/tmplfunc v0.0.3 h1:53XFQh69AfOa8Tw0Jm7t+GV7KZhOi6jzsCzTtKbMvzU= +rsc.io/tmplfunc v0.0.3/go.mod h1:AG3sTPzElb1Io3Yg4voV9AGZJuleGAwaVRxL9M49PhA= diff --git a/pkg/chain/chain.go b/pkg/chain/chain.go index d65013d..8756920 100644 --- a/pkg/chain/chain.go +++ b/pkg/chain/chain.go @@ -1,2 +1,88 @@ // Package chain implements everything related to interaction with smart contracts, rpcprovider, etc package chain + +import ( + "context" + "math/big" + + "github.com/LiskHQ/op-fault-detector/pkg/log" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/core/types" +) + +type ChainAPIClient struct { + client *APIClient + log log.Logger +} + +// NewChainAPIClient returns a [ChainAPIClient], wrapping all RPC endpoints to access chain related data. +func NewChainAPIClient(log log.Logger) (*ChainAPIClient, error) { + return &ChainAPIClient{ + log: log, + }, nil +} + +func (c *ChainAPIClient) Connect(ethClientObj EthClientInterface, url string) { + client, err := ethClientObj.Dial(url) + if err != nil { + c.log.Errorf("Error occurred while connecting %w", err) + } + c.client = NewAPIClient(client) +} + +// Returns chainID of the connected node. +func (c *ChainAPIClient) GetChainID() (*big.Int, error) { + chainID, err := c.client.ChainID(context.Background()) + if err != nil { + return nil, err + } + + return chainID, nil +} + +// Returns latest block number from the connected node. +func (c *ChainAPIClient) GetLatestBlockNumber() (uint64, error) { + blockNumber, err := c.client.BlockNumber(context.Background()) + if err != nil { + return 0, err + } + + return blockNumber, nil +} + +// Returns block for a given block number from the connected node. +func (c *ChainAPIClient) GetBlockByNumber(blockNumber *big.Int) (*types.Block, error) { + block, err := c.client.BlockByNumber(context.Background(), blockNumber) + if err != nil { + return nil, err + } + + return block, nil +} + +type ProofResponse struct { + Address common.Address `json:"address"` + AccountProof []hexutil.Bytes `json:"accountProof"` + Balance *hexutil.Big `json:"balance"` + CodeHash common.Hash `json:"codeHash"` + Nonce hexutil.Uint64 `json:"nonce"` + StorageHash common.Hash `json:"storageHash"` + StorageProof []common.Hash `json:"storageProof"` +} + +const ( + RPCEndpointGetProof = "eth_getProof" +) + +// Returns the account and storage values, including the Merkle proof, of the specified account/address. +func (c *ChainAPIClient) GetProof(blockNumber *big.Int, address string) (*ProofResponse, error) { + var result ProofResponse + + rpcClient := &RPCClient{c.client} + if err := rpcClient.Call(&result, RPCEndpointGetProof, address, []string{}, hexutil.EncodeBig(blockNumber)); err != nil { + return nil, err + } + + return &result, nil +} diff --git a/pkg/chain/chain_mocks.go b/pkg/chain/chain_mocks.go new file mode 100644 index 0000000..4a29e57 --- /dev/null +++ b/pkg/chain/chain_mocks.go @@ -0,0 +1,59 @@ +package chain + +import ( + "context" + "math/big" + + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/rpc" + "github.com/stretchr/testify/mock" +) + +// Mock function + +type MockEthClient struct { + mock.Mock +} + +func (e *MockEthClient) Dial(url string) (APIClientInterface, error) { + ret := e.Called(url) + + return ret.Get(0).(APIClientInterface), ret.Error(1) +} + +type MockAPIClient struct { + mock.Mock +} + +func (c *MockAPIClient) ChainID(ctx context.Context) (*big.Int, error) { + ret := c.Called(ctx) + + return ret.Get(0).(*big.Int), ret.Error(1) +} +func (c *MockAPIClient) BlockNumber(ctx context.Context) (uint64, error) { + ret := c.Called(ctx) + + return ret.Get(0).(uint64), ret.Error(1) +} +func (c *MockAPIClient) BlockByNumber(ctx context.Context, number *big.Int) (*types.Block, error) { + ret := c.Called(ctx, number) + + return ret.Get(0).(*types.Block), ret.Error(1) +} +func (c *MockAPIClient) Client() *rpc.Client { + ret := c.Called() + + return ret.Get(0).(*rpc.Client) +} + +type MockRPCClient struct { + mock.Mock +} + +func (c *MockAPIClient) Call(result interface{}, method string, args ...interface{}) error { + ret := c.Called() + + ptr := &result + *ptr = ret.Get(0) + return ret.Error(1) +} diff --git a/pkg/chain/chain_test.go b/pkg/chain/chain_test.go new file mode 100644 index 0000000..5fbfe4c --- /dev/null +++ b/pkg/chain/chain_test.go @@ -0,0 +1,119 @@ +package chain + +import ( + "context" + "math/big" + "testing" + "time" + + "github.com/LiskHQ/op-fault-detector/pkg/log" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/core/types" + "github.com/stretchr/testify/assert" +) + +const ( + fake_url = "localhost:8080" +) + +func TestNewChainAPIClient(t *testing.T) { + log := log.DefaultLogger + + chainClient, _ := NewChainAPIClient(log) + assert.Equal(t, chainClient.log, log) +} + +func TestConnect(t *testing.T) { + log := log.DefaultLogger + ethClientMock := &MockEthClient{} + + apiClientMock := &MockAPIClient{} + ethClientMock.On("Dial", fake_url).Return(apiClientMock, nil) + + chainClient, _ := NewChainAPIClient(log) + chainClient.Connect(ethClientMock, fake_url) + + assert.Equal(t, chainClient.log, log) +} + +func TestGetChainID(t *testing.T) { + log := log.DefaultLogger + ethClientMock := &MockEthClient{} + + apiClientMock := &MockAPIClient{} + ethClientMock.On("Dial", fake_url).Return(apiClientMock, nil) + + chainClient, _ := NewChainAPIClient(log) + chainClient.Connect(ethClientMock, fake_url) + + assert.Equal(t, chainClient.log, log) + + expectedChainID := big.NewInt(2) + apiClientMock.On("ChainID", context.Background()).Return(expectedChainID, nil) + receivedChainID, _ := chainClient.GetChainID() + assert.Equal(t, expectedChainID, receivedChainID) +} + +func TestGetLatestBlockNumber(t *testing.T) { + log := log.DefaultLogger + ethClientMock := &MockEthClient{} + + apiClientMock := &MockAPIClient{} + ethClientMock.On("Dial", fake_url).Return(apiClientMock, nil) + + chainClient, _ := NewChainAPIClient(log) + chainClient.Connect(ethClientMock, fake_url) + + assert.Equal(t, chainClient.log, log) + + expectedLatestBlockNumber := uint64(12345) + apiClientMock.On("BlockNumber", context.Background()).Return(expectedLatestBlockNumber, nil) + receivedLatestBlockNumber, _ := chainClient.GetLatestBlockNumber() + assert.Equal(t, expectedLatestBlockNumber, receivedLatestBlockNumber) +} + +func TestGetBlockByNumber(t *testing.T) { + log := log.DefaultLogger + ethClientMock := &MockEthClient{} + + apiClientMock := &MockAPIClient{} + ethClientMock.On("Dial", fake_url).Return(apiClientMock, nil) + + chainClient, _ := NewChainAPIClient(log) + chainClient.Connect(ethClientMock, fake_url) + + assert.Equal(t, chainClient.log, log) + + blockNumber := big.NewInt(800) + expectedBlock := &types.Block{ + ReceivedAt: time.Now(), + } + apiClientMock.On("BlockByNumber", context.Background(), blockNumber).Return(expectedBlock, nil) + receivedBlock, _ := chainClient.GetBlockByNumber(blockNumber) + assert.Equal(t, expectedBlock, receivedBlock) +} + +func TestGetProof(t *testing.T) { + t.Skip("skipping testing") + log := log.DefaultLogger + ethClientMock := &MockEthClient{} + + apiClientMock := &MockAPIClient{} + ethClientMock.On("Dial", fake_url).Return(apiClientMock, nil) + + chainClient, _ := NewChainAPIClient(log) + chainClient.Connect(ethClientMock, fake_url) + + assert.Equal(t, chainClient.log, log) + + rpcClientMock := &MockRPCClient{} + apiClientMock.On("Client").Return(rpcClientMock, nil) + + address := common.Address{} + blockNumber := big.NewInt(800) + proofResponseExpected := &ProofResponse{} + rpcClientMock.On("Call", proofResponseExpected, RPCEndpointGetProof, address, []string{}, hexutil.EncodeBig(blockNumber)).Return(nil) + proofResponseRecieved, _ := chainClient.GetProof(blockNumber, address.Hex()) + assert.Equal(t, proofResponseExpected, proofResponseRecieved) +} diff --git a/pkg/chain/eth_client.go b/pkg/chain/eth_client.go new file mode 100644 index 0000000..5315464 --- /dev/null +++ b/pkg/chain/eth_client.go @@ -0,0 +1,64 @@ +package chain + +import ( + "context" + "math/big" + + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/ethclient" + "github.com/ethereum/go-ethereum/rpc" +) + +type EthClientInterface interface { + Dial(url string) (APIClientInterface, error) +} + +type EthClient struct{} + +func (e *EthClient) Dial(url string) (APIClientInterface, error) { + client, err := ethclient.Dial(url) + if err != nil { + return nil, err + } + + return client, nil +} + +type APIClientInterface interface { + ChainID(ctx context.Context) (*big.Int, error) + BlockNumber(ctx context.Context) (uint64, error) + BlockByNumber(ctx context.Context, number *big.Int) (*types.Block, error) + Client() *rpc.Client +} + +type APIClient struct { + client APIClientInterface +} + +func NewAPIClient(client APIClientInterface) *APIClient { + return &APIClient{client: client} +} +func (c *APIClient) ChainID(ctx context.Context) (*big.Int, error) { + return c.client.ChainID(context.Background()) +} +func (c *APIClient) BlockNumber(ctx context.Context) (uint64, error) { + return c.client.BlockNumber(context.Background()) +} +func (c *APIClient) BlockByNumber(ctx context.Context, number *big.Int) (*types.Block, error) { + return c.client.BlockByNumber(context.Background(), number) +} +func (c *APIClient) Client() *rpc.Client { + return c.client.Client() +} + +type RPCClientInterface interface { + Call(result interface{}, method string, args ...interface{}) error +} + +type RPCClient struct { + apiClient APIClientInterface +} + +func (c *RPCClient) Call(result interface{}, method string, args ...interface{}) error { + return c.apiClient.Client().Call(result, method, args) +} From d614860463d3f36e9b0a45f753d3223b717580c6 Mon Sep 17 00:00:00 2001 From: Ishan Date: Wed, 17 Jan 2024 18:54:18 +0100 Subject: [PATCH 2/6] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20Update=20interfaces=20?= =?UTF-8?q?and=20rename=20file?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pkg/chain/chain.go | 65 +++++++++++------- .../{chain_mocks.go => chain_mocks_test.go} | 13 +--- pkg/chain/chain_test.go | 68 ++++++------------- pkg/chain/eth_client.go | 64 ----------------- 4 files changed, 62 insertions(+), 148 deletions(-) rename pkg/chain/{chain_mocks.go => chain_mocks_test.go} (78%) delete mode 100644 pkg/chain/eth_client.go diff --git a/pkg/chain/chain.go b/pkg/chain/chain.go index 8756920..19c0e36 100644 --- a/pkg/chain/chain.go +++ b/pkg/chain/chain.go @@ -9,31 +9,51 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/ethclient" + "github.com/ethereum/go-ethereum/rpc" ) -type ChainAPIClient struct { - client *APIClient - log log.Logger +const ( + RPCEndpointGetProof = "eth_getProof" +) + +type APIMethods interface { + ChainID(ctx context.Context) (*big.Int, error) + BlockNumber(ctx context.Context) (uint64, error) + BlockByNumber(ctx context.Context, number *big.Int) (*types.Block, error) + Client() *rpc.Client } -// NewChainAPIClient returns a [ChainAPIClient], wrapping all RPC endpoints to access chain related data. -func NewChainAPIClient(log log.Logger) (*ChainAPIClient, error) { - return &ChainAPIClient{ - log: log, - }, nil +type RPCClient interface { + Call(result interface{}, method string, args ...interface{}) error } -func (c *ChainAPIClient) Connect(ethClientObj EthClientInterface, url string) { - client, err := ethClientObj.Dial(url) +// GetAPIClient return [ChainAPIClient] with client attached. +func GetAPIClient(url string, log log.Logger) (*ChainAPIClient, error) { + client, err := ethclient.Dial(url) if err != nil { - c.log.Errorf("Error occurred while connecting %w", err) + return nil, err } - c.client = NewAPIClient(client) + + return NewChainAPIClient(client, log) +} + +type ChainAPIClient struct { + apiClient APIMethods + log log.Logger +} + +// NewChainAPIClient returns a [ChainAPIClient], wrapping all RPC endpoints to access chain related data. +func NewChainAPIClient(apiClient APIMethods, log log.Logger) (*ChainAPIClient, error) { + return &ChainAPIClient{ + apiClient: apiClient, + log: log, + }, nil } // Returns chainID of the connected node. -func (c *ChainAPIClient) GetChainID() (*big.Int, error) { - chainID, err := c.client.ChainID(context.Background()) +func (c *ChainAPIClient) GetChainID(ctx context.Context) (*big.Int, error) { + chainID, err := c.apiClient.ChainID(ctx) if err != nil { return nil, err } @@ -42,8 +62,8 @@ func (c *ChainAPIClient) GetChainID() (*big.Int, error) { } // Returns latest block number from the connected node. -func (c *ChainAPIClient) GetLatestBlockNumber() (uint64, error) { - blockNumber, err := c.client.BlockNumber(context.Background()) +func (c *ChainAPIClient) GetLatestBlockNumber(ctx context.Context) (uint64, error) { + blockNumber, err := c.apiClient.BlockNumber(ctx) if err != nil { return 0, err } @@ -52,8 +72,8 @@ func (c *ChainAPIClient) GetLatestBlockNumber() (uint64, error) { } // Returns block for a given block number from the connected node. -func (c *ChainAPIClient) GetBlockByNumber(blockNumber *big.Int) (*types.Block, error) { - block, err := c.client.BlockByNumber(context.Background(), blockNumber) +func (c *ChainAPIClient) GetBlockByNumber(ctx context.Context, blockNumber *big.Int) (*types.Block, error) { + block, err := c.apiClient.BlockByNumber(ctx, blockNumber) if err != nil { return nil, err } @@ -71,16 +91,11 @@ type ProofResponse struct { StorageProof []common.Hash `json:"storageProof"` } -const ( - RPCEndpointGetProof = "eth_getProof" -) - // Returns the account and storage values, including the Merkle proof, of the specified account/address. -func (c *ChainAPIClient) GetProof(blockNumber *big.Int, address string) (*ProofResponse, error) { +func (c *ChainAPIClient) GetProof(client RPCClient, blockNumber *big.Int, address string) (*ProofResponse, error) { var result ProofResponse - rpcClient := &RPCClient{c.client} - if err := rpcClient.Call(&result, RPCEndpointGetProof, address, []string{}, hexutil.EncodeBig(blockNumber)); err != nil { + if err := client.Call(&result, RPCEndpointGetProof, address, []string{}, blockNumber); err != nil { return nil, err } diff --git a/pkg/chain/chain_mocks.go b/pkg/chain/chain_mocks_test.go similarity index 78% rename from pkg/chain/chain_mocks.go rename to pkg/chain/chain_mocks_test.go index 4a29e57..192bf88 100644 --- a/pkg/chain/chain_mocks.go +++ b/pkg/chain/chain_mocks_test.go @@ -10,17 +10,6 @@ import ( ) // Mock function - -type MockEthClient struct { - mock.Mock -} - -func (e *MockEthClient) Dial(url string) (APIClientInterface, error) { - ret := e.Called(url) - - return ret.Get(0).(APIClientInterface), ret.Error(1) -} - type MockAPIClient struct { mock.Mock } @@ -50,7 +39,7 @@ type MockRPCClient struct { mock.Mock } -func (c *MockAPIClient) Call(result interface{}, method string, args ...interface{}) error { +func (c *MockRPCClient) Call(result interface{}, method string, args ...interface{}) error { ret := c.Called() ptr := &result diff --git a/pkg/chain/chain_test.go b/pkg/chain/chain_test.go index 5fbfe4c..e3aadf1 100644 --- a/pkg/chain/chain_test.go +++ b/pkg/chain/chain_test.go @@ -2,13 +2,13 @@ package chain import ( "context" + "fmt" "math/big" "testing" "time" "github.com/LiskHQ/op-fault-detector/pkg/log" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/core/types" "github.com/stretchr/testify/assert" ) @@ -20,68 +20,44 @@ const ( func TestNewChainAPIClient(t *testing.T) { log := log.DefaultLogger - chainClient, _ := NewChainAPIClient(log) - assert.Equal(t, chainClient.log, log) -} - -func TestConnect(t *testing.T) { - log := log.DefaultLogger - ethClientMock := &MockEthClient{} - apiClientMock := &MockAPIClient{} - ethClientMock.On("Dial", fake_url).Return(apiClientMock, nil) - - chainClient, _ := NewChainAPIClient(log) - chainClient.Connect(ethClientMock, fake_url) - + chainClient, _ := NewChainAPIClient(apiClientMock, log) assert.Equal(t, chainClient.log, log) } func TestGetChainID(t *testing.T) { + ctx := context.Background() log := log.DefaultLogger - ethClientMock := &MockEthClient{} - apiClientMock := &MockAPIClient{} - ethClientMock.On("Dial", fake_url).Return(apiClientMock, nil) - - chainClient, _ := NewChainAPIClient(log) - chainClient.Connect(ethClientMock, fake_url) + chainClient, _ := NewChainAPIClient(apiClientMock, log) assert.Equal(t, chainClient.log, log) expectedChainID := big.NewInt(2) apiClientMock.On("ChainID", context.Background()).Return(expectedChainID, nil) - receivedChainID, _ := chainClient.GetChainID() + receivedChainID, _ := chainClient.GetChainID(ctx) assert.Equal(t, expectedChainID, receivedChainID) } func TestGetLatestBlockNumber(t *testing.T) { + ctx := context.Background() log := log.DefaultLogger - ethClientMock := &MockEthClient{} - apiClientMock := &MockAPIClient{} - ethClientMock.On("Dial", fake_url).Return(apiClientMock, nil) - - chainClient, _ := NewChainAPIClient(log) - chainClient.Connect(ethClientMock, fake_url) + chainClient, _ := NewChainAPIClient(apiClientMock, log) assert.Equal(t, chainClient.log, log) expectedLatestBlockNumber := uint64(12345) apiClientMock.On("BlockNumber", context.Background()).Return(expectedLatestBlockNumber, nil) - receivedLatestBlockNumber, _ := chainClient.GetLatestBlockNumber() + receivedLatestBlockNumber, _ := chainClient.GetLatestBlockNumber(ctx) assert.Equal(t, expectedLatestBlockNumber, receivedLatestBlockNumber) } func TestGetBlockByNumber(t *testing.T) { + ctx := context.Background() log := log.DefaultLogger - ethClientMock := &MockEthClient{} - apiClientMock := &MockAPIClient{} - ethClientMock.On("Dial", fake_url).Return(apiClientMock, nil) - - chainClient, _ := NewChainAPIClient(log) - chainClient.Connect(ethClientMock, fake_url) + chainClient, _ := NewChainAPIClient(apiClientMock, log) assert.Equal(t, chainClient.log, log) @@ -90,30 +66,28 @@ func TestGetBlockByNumber(t *testing.T) { ReceivedAt: time.Now(), } apiClientMock.On("BlockByNumber", context.Background(), blockNumber).Return(expectedBlock, nil) - receivedBlock, _ := chainClient.GetBlockByNumber(blockNumber) + receivedBlock, _ := chainClient.GetBlockByNumber(ctx, blockNumber) assert.Equal(t, expectedBlock, receivedBlock) } func TestGetProof(t *testing.T) { - t.Skip("skipping testing") + // t.Skipf("Skipping GetProof test") log := log.DefaultLogger - ethClientMock := &MockEthClient{} - apiClientMock := &MockAPIClient{} - ethClientMock.On("Dial", fake_url).Return(apiClientMock, nil) - - chainClient, _ := NewChainAPIClient(log) - chainClient.Connect(ethClientMock, fake_url) + chainClient, _ := NewChainAPIClient(apiClientMock, log) assert.Equal(t, chainClient.log, log) rpcClientMock := &MockRPCClient{} - apiClientMock.On("Client").Return(rpcClientMock, nil) - + // Args for Call() method address := common.Address{} blockNumber := big.NewInt(800) - proofResponseExpected := &ProofResponse{} - rpcClientMock.On("Call", proofResponseExpected, RPCEndpointGetProof, address, []string{}, hexutil.EncodeBig(blockNumber)).Return(nil) - proofResponseRecieved, _ := chainClient.GetProof(blockNumber, address.Hex()) + var proofResponseExpected ProofResponse + + apiClientMock.On("Client").Return(rpcClientMock, nil) + rpcClientMock.On("Call", &proofResponseExpected, RPCEndpointGetProof, address.String(), []string{}, blockNumber).Return(fmt.Println("Error")) + + proofResponseRecieved, _ := chainClient.GetProof(rpcClientMock, blockNumber, address.Hex()) + assert.Equal(t, proofResponseExpected, proofResponseRecieved) } diff --git a/pkg/chain/eth_client.go b/pkg/chain/eth_client.go deleted file mode 100644 index 5315464..0000000 --- a/pkg/chain/eth_client.go +++ /dev/null @@ -1,64 +0,0 @@ -package chain - -import ( - "context" - "math/big" - - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/ethclient" - "github.com/ethereum/go-ethereum/rpc" -) - -type EthClientInterface interface { - Dial(url string) (APIClientInterface, error) -} - -type EthClient struct{} - -func (e *EthClient) Dial(url string) (APIClientInterface, error) { - client, err := ethclient.Dial(url) - if err != nil { - return nil, err - } - - return client, nil -} - -type APIClientInterface interface { - ChainID(ctx context.Context) (*big.Int, error) - BlockNumber(ctx context.Context) (uint64, error) - BlockByNumber(ctx context.Context, number *big.Int) (*types.Block, error) - Client() *rpc.Client -} - -type APIClient struct { - client APIClientInterface -} - -func NewAPIClient(client APIClientInterface) *APIClient { - return &APIClient{client: client} -} -func (c *APIClient) ChainID(ctx context.Context) (*big.Int, error) { - return c.client.ChainID(context.Background()) -} -func (c *APIClient) BlockNumber(ctx context.Context) (uint64, error) { - return c.client.BlockNumber(context.Background()) -} -func (c *APIClient) BlockByNumber(ctx context.Context, number *big.Int) (*types.Block, error) { - return c.client.BlockByNumber(context.Background(), number) -} -func (c *APIClient) Client() *rpc.Client { - return c.client.Client() -} - -type RPCClientInterface interface { - Call(result interface{}, method string, args ...interface{}) error -} - -type RPCClient struct { - apiClient APIClientInterface -} - -func (c *RPCClient) Call(result interface{}, method string, args ...interface{}) error { - return c.apiClient.Client().Call(result, method, args) -} From 9c989ffb5c6154152f37213c6e38613ba2813273 Mon Sep 17 00:00:00 2001 From: Ishan Date: Thu, 18 Jan 2024 10:58:03 +0100 Subject: [PATCH 3/6] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20Fix=20test=20and=20moc?= =?UTF-8?q?king?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pkg/chain/chain_mocks_test.go | 5 +++-- pkg/chain/chain_test.go | 12 +++++------- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/pkg/chain/chain_mocks_test.go b/pkg/chain/chain_mocks_test.go index 192bf88..ede01f8 100644 --- a/pkg/chain/chain_mocks_test.go +++ b/pkg/chain/chain_mocks_test.go @@ -9,7 +9,6 @@ import ( "github.com/stretchr/testify/mock" ) -// Mock function type MockAPIClient struct { mock.Mock } @@ -40,7 +39,9 @@ type MockRPCClient struct { } func (c *MockRPCClient) Call(result interface{}, method string, args ...interface{}) error { - ret := c.Called() + allArgs := []interface{}{result, method} + allArgs = append(allArgs, args...) + ret := c.Called(allArgs...) ptr := &result *ptr = ret.Get(0) diff --git a/pkg/chain/chain_test.go b/pkg/chain/chain_test.go index e3aadf1..7080877 100644 --- a/pkg/chain/chain_test.go +++ b/pkg/chain/chain_test.go @@ -11,10 +11,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" "github.com/stretchr/testify/assert" -) - -const ( - fake_url = "localhost:8080" + "github.com/stretchr/testify/mock" ) func TestNewChainAPIClient(t *testing.T) { @@ -85,9 +82,10 @@ func TestGetProof(t *testing.T) { var proofResponseExpected ProofResponse apiClientMock.On("Client").Return(rpcClientMock, nil) - rpcClientMock.On("Call", &proofResponseExpected, RPCEndpointGetProof, address.String(), []string{}, blockNumber).Return(fmt.Println("Error")) + rpcClientMock.On("Call", mock.AnythingOfType("*chain.ProofResponse"), RPCEndpointGetProof, address.String(), []string{}, blockNumber).Return(fmt.Println("Error")) - proofResponseRecieved, _ := chainClient.GetProof(rpcClientMock, blockNumber, address.Hex()) + proofResponseRecieved, err := chainClient.GetProof(rpcClientMock, blockNumber, address.Hex()) - assert.Equal(t, proofResponseExpected, proofResponseRecieved) + assert.NoError(t, err) + assert.Equal(t, &proofResponseExpected, proofResponseRecieved) } From b9311d4d8569be5cd847f22868d4e08b4f3eb859 Mon Sep 17 00:00:00 2001 From: Ishan Date: Thu, 18 Jan 2024 15:11:50 +0100 Subject: [PATCH 4/6] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20Simplify=20chain=20uti?= =?UTF-8?q?ls?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- go.mod | 5 -- go.sum | 11 ----- pkg/chain/chain.go | 79 +++++++++--------------------- pkg/chain/chain_mocks_test.go | 49 ------------------- pkg/chain/chain_test.go | 91 ----------------------------------- 5 files changed, 24 insertions(+), 211 deletions(-) delete mode 100644 pkg/chain/chain_mocks_test.go delete mode 100644 pkg/chain/chain_test.go diff --git a/go.mod b/go.mod index c9c98d0..6f45dfe 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,6 @@ go 1.21.5 require ( github.com/ethereum/go-ethereum v1.13.10 - github.com/stretchr/testify v1.8.4 go.uber.org/zap v1.26.0 ) @@ -16,7 +15,6 @@ require ( github.com/consensys/bavard v0.1.13 // indirect github.com/consensys/gnark-crypto v0.12.1 // indirect github.com/crate-crypto/go-kzg-4844 v0.7.0 // indirect - github.com/davecgh/go-spew v1.1.1 // indirect github.com/deckarep/golang-set/v2 v2.1.0 // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect github.com/ethereum/c-kzg-4844 v0.4.0 // indirect @@ -24,9 +22,7 @@ require ( github.com/gorilla/websocket v1.4.2 // indirect github.com/holiman/uint256 v1.2.4 // indirect github.com/mmcloughlin/addchain v0.4.0 // indirect - github.com/pmezard/go-difflib v1.0.0 // indirect github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible // indirect - github.com/stretchr/objx v0.5.0 // indirect github.com/supranational/blst v0.3.11 // indirect github.com/tklauser/go-sysconf v0.3.12 // indirect github.com/tklauser/numcpus v0.6.1 // indirect @@ -37,6 +33,5 @@ require ( golang.org/x/sync v0.5.0 // indirect golang.org/x/sys v0.15.0 // indirect golang.org/x/tools v0.15.0 // indirect - gopkg.in/yaml.v3 v3.0.1 // indirect rsc.io/tmplfunc v0.0.3 // indirect ) diff --git a/go.sum b/go.sum index 6bd8bfe..baa8c8b 100644 --- a/go.sum +++ b/go.sum @@ -38,7 +38,6 @@ github.com/crate-crypto/go-ipa v0.0.0-20231025140028-3c0104f4b233 h1:d28BXYi+wUp github.com/crate-crypto/go-ipa v0.0.0-20231025140028-3c0104f4b233/go.mod h1:geZJZH3SzKCqnz5VT0q/DyIG/tvu/dZk+VIfXicupJs= github.com/crate-crypto/go-kzg-4844 v0.7.0 h1:C0vgZRk4q4EZ/JgPfzuSoxdCq3C3mOZMBShovmncxvA= github.com/crate-crypto/go-kzg-4844 v0.7.0/go.mod h1:1kMhvPgI0Ky3yIa+9lFySEBUBXkYxeOi8ZF1sYioxhc= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/deckarep/golang-set/v2 v2.1.0 h1:g47V4Or+DUdzbs8FxCCmgb6VYd+ptPAngjM6dtGktsI= @@ -139,12 +138,6 @@ github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible h1 github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= github.com/status-im/keycard-go v0.2.0 h1:QDLFswOQu1r5jsycloeQh3bVU8n/NatHHaZobtDnDzA= github.com/status-im/keycard-go v0.2.0/go.mod h1:wlp8ZLbsmrF6g6WjugPAx+IzoLrkdf9+mHxBEeo3Hbg= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= -github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= -github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/supranational/blst v0.3.11 h1:LyU6FolezeWAhvQk0k6O/d49jqgO52MSDDfYgbeoEm4= @@ -188,14 +181,10 @@ golang.org/x/tools v0.15.0 h1:zdAyfUGbYmuVokhzVmghFl2ZJh5QhcfebBgmVPFYA+8= golang.org/x/tools v0.15.0/go.mod h1:hpksKq4dtpQWS1uQ61JkdqWM3LscIS6Slf+VVkm+wQk= google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ= google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8= gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= rsc.io/tmplfunc v0.0.3 h1:53XFQh69AfOa8Tw0Jm7t+GV7KZhOi6jzsCzTtKbMvzU= diff --git a/pkg/chain/chain.go b/pkg/chain/chain.go index 19c0e36..33f473c 100644 --- a/pkg/chain/chain.go +++ b/pkg/chain/chain.go @@ -1,4 +1,4 @@ -// Package chain implements everything related to interaction with smart contracts, rpcprovider, etc +// Package chain implements everything related to interaction with smart contracts, rpcprovider, etc. package chain import ( @@ -10,92 +10,61 @@ import ( "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/ethclient" - "github.com/ethereum/go-ethereum/rpc" ) const ( - RPCEndpointGetProof = "eth_getProof" + rpcEndpointGetProof = "eth_getProof" ) -type APIMethods interface { - ChainID(ctx context.Context) (*big.Int, error) - BlockNumber(ctx context.Context) (uint64, error) - BlockByNumber(ctx context.Context, number *big.Int) (*types.Block, error) - Client() *rpc.Client +// ChainAPIClient connects and encapsulates all the methods to interact with the a chain. +type ChainAPIClient struct { + eth *ethclient.Client + log log.Logger } -type RPCClient interface { - Call(result interface{}, method string, args ...interface{}) error +type proofResponse struct { + Address common.Address `json:"address"` + AccountProof []hexutil.Bytes `json:"accountProof"` + Balance *hexutil.Big `json:"balance"` + CodeHash common.Hash `json:"codeHash"` + Nonce hexutil.Uint64 `json:"nonce"` + StorageHash common.Hash `json:"storageHash"` + StorageProof []common.Hash `json:"storageProof"` } // GetAPIClient return [ChainAPIClient] with client attached. -func GetAPIClient(url string, log log.Logger) (*ChainAPIClient, error) { - client, err := ethclient.Dial(url) +func GetAPIClient(ctx context.Context, url string, log log.Logger) (*ChainAPIClient, error) { + client, err := ethclient.DialContext(ctx, url) if err != nil { return nil, err } - return NewChainAPIClient(client, log) -} - -type ChainAPIClient struct { - apiClient APIMethods - log log.Logger -} - -// NewChainAPIClient returns a [ChainAPIClient], wrapping all RPC endpoints to access chain related data. -func NewChainAPIClient(apiClient APIMethods, log log.Logger) (*ChainAPIClient, error) { return &ChainAPIClient{ - apiClient: apiClient, - log: log, + eth: client, + log: log, }, nil } // Returns chainID of the connected node. func (c *ChainAPIClient) GetChainID(ctx context.Context) (*big.Int, error) { - chainID, err := c.apiClient.ChainID(ctx) - if err != nil { - return nil, err - } - - return chainID, nil + return c.eth.ChainID(ctx) } // Returns latest block number from the connected node. func (c *ChainAPIClient) GetLatestBlockNumber(ctx context.Context) (uint64, error) { - blockNumber, err := c.apiClient.BlockNumber(ctx) - if err != nil { - return 0, err - } - - return blockNumber, nil + return c.eth.BlockNumber(ctx) } // Returns block for a given block number from the connected node. func (c *ChainAPIClient) GetBlockByNumber(ctx context.Context, blockNumber *big.Int) (*types.Block, error) { - block, err := c.apiClient.BlockByNumber(ctx, blockNumber) - if err != nil { - return nil, err - } - - return block, nil -} - -type ProofResponse struct { - Address common.Address `json:"address"` - AccountProof []hexutil.Bytes `json:"accountProof"` - Balance *hexutil.Big `json:"balance"` - CodeHash common.Hash `json:"codeHash"` - Nonce hexutil.Uint64 `json:"nonce"` - StorageHash common.Hash `json:"storageHash"` - StorageProof []common.Hash `json:"storageProof"` + return c.eth.BlockByNumber(ctx, blockNumber) } // Returns the account and storage values, including the Merkle proof, of the specified account/address. -func (c *ChainAPIClient) GetProof(client RPCClient, blockNumber *big.Int, address string) (*ProofResponse, error) { - var result ProofResponse +func (c *ChainAPIClient) GetProof(ctx context.Context, blockNumber *big.Int, address common.Address) (*proofResponse, error) { + var result proofResponse - if err := client.Call(&result, RPCEndpointGetProof, address, []string{}, blockNumber); err != nil { + if err := c.eth.Client().CallContext(ctx, &result, rpcEndpointGetProof, address, []string{}, hexutil.Big(*blockNumber)); err != nil { return nil, err } diff --git a/pkg/chain/chain_mocks_test.go b/pkg/chain/chain_mocks_test.go deleted file mode 100644 index ede01f8..0000000 --- a/pkg/chain/chain_mocks_test.go +++ /dev/null @@ -1,49 +0,0 @@ -package chain - -import ( - "context" - "math/big" - - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/rpc" - "github.com/stretchr/testify/mock" -) - -type MockAPIClient struct { - mock.Mock -} - -func (c *MockAPIClient) ChainID(ctx context.Context) (*big.Int, error) { - ret := c.Called(ctx) - - return ret.Get(0).(*big.Int), ret.Error(1) -} -func (c *MockAPIClient) BlockNumber(ctx context.Context) (uint64, error) { - ret := c.Called(ctx) - - return ret.Get(0).(uint64), ret.Error(1) -} -func (c *MockAPIClient) BlockByNumber(ctx context.Context, number *big.Int) (*types.Block, error) { - ret := c.Called(ctx, number) - - return ret.Get(0).(*types.Block), ret.Error(1) -} -func (c *MockAPIClient) Client() *rpc.Client { - ret := c.Called() - - return ret.Get(0).(*rpc.Client) -} - -type MockRPCClient struct { - mock.Mock -} - -func (c *MockRPCClient) Call(result interface{}, method string, args ...interface{}) error { - allArgs := []interface{}{result, method} - allArgs = append(allArgs, args...) - ret := c.Called(allArgs...) - - ptr := &result - *ptr = ret.Get(0) - return ret.Error(1) -} diff --git a/pkg/chain/chain_test.go b/pkg/chain/chain_test.go deleted file mode 100644 index 7080877..0000000 --- a/pkg/chain/chain_test.go +++ /dev/null @@ -1,91 +0,0 @@ -package chain - -import ( - "context" - "fmt" - "math/big" - "testing" - "time" - - "github.com/LiskHQ/op-fault-detector/pkg/log" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/mock" -) - -func TestNewChainAPIClient(t *testing.T) { - log := log.DefaultLogger - - apiClientMock := &MockAPIClient{} - chainClient, _ := NewChainAPIClient(apiClientMock, log) - assert.Equal(t, chainClient.log, log) -} - -func TestGetChainID(t *testing.T) { - ctx := context.Background() - log := log.DefaultLogger - apiClientMock := &MockAPIClient{} - chainClient, _ := NewChainAPIClient(apiClientMock, log) - - assert.Equal(t, chainClient.log, log) - - expectedChainID := big.NewInt(2) - apiClientMock.On("ChainID", context.Background()).Return(expectedChainID, nil) - receivedChainID, _ := chainClient.GetChainID(ctx) - assert.Equal(t, expectedChainID, receivedChainID) -} - -func TestGetLatestBlockNumber(t *testing.T) { - ctx := context.Background() - log := log.DefaultLogger - apiClientMock := &MockAPIClient{} - chainClient, _ := NewChainAPIClient(apiClientMock, log) - - assert.Equal(t, chainClient.log, log) - - expectedLatestBlockNumber := uint64(12345) - apiClientMock.On("BlockNumber", context.Background()).Return(expectedLatestBlockNumber, nil) - receivedLatestBlockNumber, _ := chainClient.GetLatestBlockNumber(ctx) - assert.Equal(t, expectedLatestBlockNumber, receivedLatestBlockNumber) -} - -func TestGetBlockByNumber(t *testing.T) { - ctx := context.Background() - log := log.DefaultLogger - apiClientMock := &MockAPIClient{} - chainClient, _ := NewChainAPIClient(apiClientMock, log) - - assert.Equal(t, chainClient.log, log) - - blockNumber := big.NewInt(800) - expectedBlock := &types.Block{ - ReceivedAt: time.Now(), - } - apiClientMock.On("BlockByNumber", context.Background(), blockNumber).Return(expectedBlock, nil) - receivedBlock, _ := chainClient.GetBlockByNumber(ctx, blockNumber) - assert.Equal(t, expectedBlock, receivedBlock) -} - -func TestGetProof(t *testing.T) { - // t.Skipf("Skipping GetProof test") - log := log.DefaultLogger - apiClientMock := &MockAPIClient{} - chainClient, _ := NewChainAPIClient(apiClientMock, log) - - assert.Equal(t, chainClient.log, log) - - rpcClientMock := &MockRPCClient{} - // Args for Call() method - address := common.Address{} - blockNumber := big.NewInt(800) - var proofResponseExpected ProofResponse - - apiClientMock.On("Client").Return(rpcClientMock, nil) - rpcClientMock.On("Call", mock.AnythingOfType("*chain.ProofResponse"), RPCEndpointGetProof, address.String(), []string{}, blockNumber).Return(fmt.Println("Error")) - - proofResponseRecieved, err := chainClient.GetProof(rpcClientMock, blockNumber, address.Hex()) - - assert.NoError(t, err) - assert.Equal(t, &proofResponseExpected, proofResponseRecieved) -} From 54d47705be9cd8b0f6461321592bab337a6f9848 Mon Sep 17 00:00:00 2001 From: Ishan Date: Thu, 18 Jan 2024 15:38:40 +0100 Subject: [PATCH 5/6] =?UTF-8?q?=F0=9F=92=85=20Improve=20docs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pkg/chain/chain.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/pkg/chain/chain.go b/pkg/chain/chain.go index 33f473c..987bf16 100644 --- a/pkg/chain/chain.go +++ b/pkg/chain/chain.go @@ -16,7 +16,7 @@ const ( rpcEndpointGetProof = "eth_getProof" ) -// ChainAPIClient connects and encapsulates all the methods to interact with the a chain. +// ChainAPIClient connects and encapsulates all the methods to interact with a chain. type ChainAPIClient struct { eth *ethclient.Client log log.Logger @@ -32,7 +32,7 @@ type proofResponse struct { StorageProof []common.Hash `json:"storageProof"` } -// GetAPIClient return [ChainAPIClient] with client attached. +// GetAPIClient returns [ChainAPIClient] with client attached. func GetAPIClient(ctx context.Context, url string, log log.Logger) (*ChainAPIClient, error) { client, err := ethclient.DialContext(ctx, url) if err != nil { @@ -45,22 +45,22 @@ func GetAPIClient(ctx context.Context, url string, log log.Logger) (*ChainAPICli }, nil } -// Returns chainID of the connected node. +// GetChainID returns chainID of a connected node. func (c *ChainAPIClient) GetChainID(ctx context.Context) (*big.Int, error) { return c.eth.ChainID(ctx) } -// Returns latest block number from the connected node. +// GetLatestBlockNumber returns latest block number from a connected node. func (c *ChainAPIClient) GetLatestBlockNumber(ctx context.Context) (uint64, error) { return c.eth.BlockNumber(ctx) } -// Returns block for a given block number from the connected node. +// GetBlockByNumber returns block for a given block number from a connected node. func (c *ChainAPIClient) GetBlockByNumber(ctx context.Context, blockNumber *big.Int) (*types.Block, error) { return c.eth.BlockByNumber(ctx, blockNumber) } -// Returns the account and storage values, including the Merkle proof, of the specified account/address. +// GetProof returns the account and storage values, including the Merkle proof, of the specified account/address. func (c *ChainAPIClient) GetProof(ctx context.Context, blockNumber *big.Int, address common.Address) (*proofResponse, error) { var result proofResponse From 6532aacbe16a1d030556e1ecda36c53ffd6ca072 Mon Sep 17 00:00:00 2001 From: Ishan Date: Thu, 18 Jan 2024 16:30:19 +0100 Subject: [PATCH 6/6] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20Expose=20ProofResponse?= =?UTF-8?q?=20from=20chain?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pkg/chain/chain.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pkg/chain/chain.go b/pkg/chain/chain.go index 987bf16..10b9c86 100644 --- a/pkg/chain/chain.go +++ b/pkg/chain/chain.go @@ -22,7 +22,7 @@ type ChainAPIClient struct { log log.Logger } -type proofResponse struct { +type ProofResponse struct { Address common.Address `json:"address"` AccountProof []hexutil.Bytes `json:"accountProof"` Balance *hexutil.Big `json:"balance"` @@ -61,8 +61,8 @@ func (c *ChainAPIClient) GetBlockByNumber(ctx context.Context, blockNumber *big. } // GetProof returns the account and storage values, including the Merkle proof, of the specified account/address. -func (c *ChainAPIClient) GetProof(ctx context.Context, blockNumber *big.Int, address common.Address) (*proofResponse, error) { - var result proofResponse +func (c *ChainAPIClient) GetProof(ctx context.Context, blockNumber *big.Int, address common.Address) (*ProofResponse, error) { + var result ProofResponse if err := c.eth.Client().CallContext(ctx, &result, rpcEndpointGetProof, address, []string{}, hexutil.Big(*blockNumber)); err != nil { return nil, err