mirror of https://github.com/certusone/vouch.git
Add sync committee contribution strategy.
This commit is contained in:
parent
d7efbd856b
commit
945c85fb30
13
go.mod
13
go.mod
|
@ -1,24 +1,21 @@
|
||||||
module github.com/attestantio/vouch
|
module github.com/attestantio/vouch
|
||||||
|
|
||||||
go 1.14
|
go 1.16
|
||||||
|
|
||||||
require (
|
require (
|
||||||
cloud.google.com/go v0.81.0 // indirect
|
cloud.google.com/go v0.81.0 // indirect
|
||||||
github.com/OneOfOne/xxhash v1.2.5 // indirect
|
github.com/attestantio/go-eth2-client v0.7.0
|
||||||
github.com/attestantio/go-eth2-client v0.7.0-beta.2
|
|
||||||
github.com/aws/aws-sdk-go v1.38.30
|
github.com/aws/aws-sdk-go v1.38.30
|
||||||
github.com/grpc-ecosystem/grpc-gateway v1.16.0 // indirect
|
github.com/grpc-ecosystem/grpc-gateway v1.16.0 // indirect
|
||||||
github.com/mitchellh/go-homedir v1.1.0
|
github.com/mitchellh/go-homedir v1.1.0
|
||||||
github.com/nbutton23/zxcvbn-go v0.0.0-20210217022336-fa2cb2858354 // indirect
|
|
||||||
github.com/opentracing/opentracing-go v1.2.0
|
github.com/opentracing/opentracing-go v1.2.0
|
||||||
github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5 // indirect
|
github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5 // indirect
|
||||||
github.com/pkg/errors v0.9.1
|
github.com/pkg/errors v0.9.1
|
||||||
github.com/prometheus/client_golang v1.9.0
|
github.com/prometheus/client_golang v1.9.0
|
||||||
github.com/prometheus/procfs v0.6.0 // indirect
|
github.com/prometheus/procfs v0.6.0 // indirect
|
||||||
github.com/prysmaticlabs/go-bitfield v0.0.0-20210607200045-4da71aaf6c2d
|
github.com/prysmaticlabs/go-bitfield v0.0.0-20210809151128-385d8c5e3fb7
|
||||||
github.com/rs/zerolog v1.21.0
|
github.com/rs/zerolog v1.23.0
|
||||||
github.com/sasha-s/go-deadlock v0.2.0
|
github.com/sasha-s/go-deadlock v0.2.0
|
||||||
github.com/sirupsen/logrus v1.6.0
|
|
||||||
github.com/spf13/afero v1.5.1 // indirect
|
github.com/spf13/afero v1.5.1 // indirect
|
||||||
github.com/spf13/pflag v1.0.5
|
github.com/spf13/pflag v1.0.5
|
||||||
github.com/spf13/viper v1.7.1
|
github.com/spf13/viper v1.7.1
|
||||||
|
@ -35,7 +32,7 @@ require (
|
||||||
github.com/wealdtech/go-eth2-wallet-store-scratch v1.6.2
|
github.com/wealdtech/go-eth2-wallet-store-scratch v1.6.2
|
||||||
github.com/wealdtech/go-eth2-wallet-types/v2 v2.8.4
|
github.com/wealdtech/go-eth2-wallet-types/v2 v2.8.4
|
||||||
github.com/wealdtech/go-majordomo v1.0.1
|
github.com/wealdtech/go-majordomo v1.0.1
|
||||||
go.uber.org/atomic v1.7.0 // indirect
|
go.uber.org/atomic v1.7.0
|
||||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
|
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
|
||||||
google.golang.org/grpc v1.38.0
|
google.golang.org/grpc v1.38.0
|
||||||
gotest.tools v2.2.0+incompatible
|
gotest.tools v2.2.0+incompatible
|
||||||
|
|
28
go.sum
28
go.sum
|
@ -47,8 +47,6 @@ github.com/HdrHistogram/hdrhistogram-go v0.9.0 h1:dpujRju0R4M/QZzcnR1LH1qm+TVG3U
|
||||||
github.com/HdrHistogram/hdrhistogram-go v0.9.0/go.mod h1:nxrse8/Tzg2tg3DZcZjm6qEclQKK70g0KxO61gFFZD4=
|
github.com/HdrHistogram/hdrhistogram-go v0.9.0/go.mod h1:nxrse8/Tzg2tg3DZcZjm6qEclQKK70g0KxO61gFFZD4=
|
||||||
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
|
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
|
||||||
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
||||||
github.com/OneOfOne/xxhash v1.2.5 h1:zl/OfRA6nftbBK9qTohYBJ5xvw6C/oNKizR7cZGl3cI=
|
|
||||||
github.com/OneOfOne/xxhash v1.2.5/go.mod h1:eZbhyaAYD41SGSSsnmcpxVoRiQ/MPUTjUdIIOT9Um7Q=
|
|
||||||
github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo=
|
github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo=
|
||||||
github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI=
|
github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI=
|
||||||
github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g=
|
github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g=
|
||||||
|
@ -70,10 +68,8 @@ github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6l
|
||||||
github.com/attestantio/dirk v1.0.2 h1:CYIRgQIbPqshwvgNJt98vV/ljhZmnAqfhQujoIpvGKg=
|
github.com/attestantio/dirk v1.0.2 h1:CYIRgQIbPqshwvgNJt98vV/ljhZmnAqfhQujoIpvGKg=
|
||||||
github.com/attestantio/dirk v1.0.2/go.mod h1:QHXxAnKD9cpuPC7STamSW2nPXEn7YTypcNFPAKfWTFQ=
|
github.com/attestantio/dirk v1.0.2/go.mod h1:QHXxAnKD9cpuPC7STamSW2nPXEn7YTypcNFPAKfWTFQ=
|
||||||
github.com/attestantio/go-eth2-client v0.6.15/go.mod h1:Hya4fp1ZLWAFI64qMhNbQgfY4StWiHulW4CFwu+vP3s=
|
github.com/attestantio/go-eth2-client v0.6.15/go.mod h1:Hya4fp1ZLWAFI64qMhNbQgfY4StWiHulW4CFwu+vP3s=
|
||||||
github.com/attestantio/go-eth2-client v0.6.28 h1:FmyUTzO/Lhhl10kINqzhbnShmg3hUGvex2H8m1BVUKw=
|
github.com/attestantio/go-eth2-client v0.7.0 h1:3N4TfKIqS2DS5jCBMqbAzUeL+9LB9Te0froT4NtIDoE=
|
||||||
github.com/attestantio/go-eth2-client v0.6.28/go.mod h1:OlJziQa8y46JEBzjOsvmA+n72yHqui+xNLAHOUbg/VU=
|
github.com/attestantio/go-eth2-client v0.7.0/go.mod h1:kEK9iAAOBoADO5wEkd84FEOzjT1zXgVWveQsqn+uBGg=
|
||||||
github.com/attestantio/go-eth2-client v0.7.0-beta.2 h1:fYkoAd66aKpzVq2hu5zq+bTtYvpJhXFyUvo6RLd2dMM=
|
|
||||||
github.com/attestantio/go-eth2-client v0.7.0-beta.2/go.mod h1:kEK9iAAOBoADO5wEkd84FEOzjT1zXgVWveQsqn+uBGg=
|
|
||||||
github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU=
|
github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU=
|
||||||
github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
|
github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
|
||||||
github.com/aws/aws-sdk-go v1.33.17/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0=
|
github.com/aws/aws-sdk-go v1.33.17/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0=
|
||||||
|
@ -103,7 +99,6 @@ github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGX
|
||||||
github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
|
github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
|
||||||
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
|
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
|
||||||
github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8=
|
github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8=
|
||||||
github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd h1:qMd81Ts1T2OTKmB4acZcyKaMtRnY5Y44NuXGX2GFJ1w=
|
|
||||||
github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI=
|
github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI=
|
||||||
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
|
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
|
||||||
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
|
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
|
||||||
|
@ -113,6 +108,7 @@ github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3Ee
|
||||||
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
||||||
github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
||||||
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
||||||
|
github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
|
||||||
github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
|
github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
|
||||||
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
|
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
|
||||||
github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
|
github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
|
||||||
|
@ -152,7 +148,6 @@ github.com/fatih/color v1.10.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGE
|
||||||
github.com/ferranbt/fastssz v0.0.0-20200728110133-0b6e349af87a/go.mod h1:DyEu2iuLBnb/T51BlsiO3yLYdJC6UbGMrIkqK1KmQxM=
|
github.com/ferranbt/fastssz v0.0.0-20200728110133-0b6e349af87a/go.mod h1:DyEu2iuLBnb/T51BlsiO3yLYdJC6UbGMrIkqK1KmQxM=
|
||||||
github.com/ferranbt/fastssz v0.0.0-20201030134205-9b9624098321/go.mod h1:DyEu2iuLBnb/T51BlsiO3yLYdJC6UbGMrIkqK1KmQxM=
|
github.com/ferranbt/fastssz v0.0.0-20201030134205-9b9624098321/go.mod h1:DyEu2iuLBnb/T51BlsiO3yLYdJC6UbGMrIkqK1KmQxM=
|
||||||
github.com/ferranbt/fastssz v0.0.0-20210120143747-11b9eff30ea9/go.mod h1:DyEu2iuLBnb/T51BlsiO3yLYdJC6UbGMrIkqK1KmQxM=
|
github.com/ferranbt/fastssz v0.0.0-20210120143747-11b9eff30ea9/go.mod h1:DyEu2iuLBnb/T51BlsiO3yLYdJC6UbGMrIkqK1KmQxM=
|
||||||
github.com/ferranbt/fastssz v0.0.0-20210316165225-412ceaa5950e/go.mod h1:DyEu2iuLBnb/T51BlsiO3yLYdJC6UbGMrIkqK1KmQxM=
|
|
||||||
github.com/ferranbt/fastssz v0.0.0-20210526181520-7df50c8568f8 h1:zhTRgKvm7CQxlGwJ7KfqT1AYDr2Q/caS6qrC7fwEtxU=
|
github.com/ferranbt/fastssz v0.0.0-20210526181520-7df50c8568f8 h1:zhTRgKvm7CQxlGwJ7KfqT1AYDr2Q/caS6qrC7fwEtxU=
|
||||||
github.com/ferranbt/fastssz v0.0.0-20210526181520-7df50c8568f8/go.mod h1:DyEu2iuLBnb/T51BlsiO3yLYdJC6UbGMrIkqK1KmQxM=
|
github.com/ferranbt/fastssz v0.0.0-20210526181520-7df50c8568f8/go.mod h1:DyEu2iuLBnb/T51BlsiO3yLYdJC6UbGMrIkqK1KmQxM=
|
||||||
github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4=
|
github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4=
|
||||||
|
@ -170,7 +165,6 @@ github.com/go-kit/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgO
|
||||||
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
|
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
|
||||||
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
|
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
|
||||||
github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
|
github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
|
||||||
github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A=
|
|
||||||
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
|
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
|
||||||
github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q=
|
github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q=
|
||||||
github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8=
|
github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8=
|
||||||
|
@ -184,6 +178,7 @@ github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/me
|
||||||
github.com/goccy/go-yaml v1.8.4/go.mod h1:U/jl18uSupI5rdI2jmuCswEA2htH9eXfferR3KfscvA=
|
github.com/goccy/go-yaml v1.8.4/go.mod h1:U/jl18uSupI5rdI2jmuCswEA2htH9eXfferR3KfscvA=
|
||||||
github.com/goccy/go-yaml v1.8.9 h1:4AEXg2qx+/w29jXnXpMY6mTckmYu1TMoHteKuMf0HFg=
|
github.com/goccy/go-yaml v1.8.9 h1:4AEXg2qx+/w29jXnXpMY6mTckmYu1TMoHteKuMf0HFg=
|
||||||
github.com/goccy/go-yaml v1.8.9/go.mod h1:U/jl18uSupI5rdI2jmuCswEA2htH9eXfferR3KfscvA=
|
github.com/goccy/go-yaml v1.8.9/go.mod h1:U/jl18uSupI5rdI2jmuCswEA2htH9eXfferR3KfscvA=
|
||||||
|
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||||
github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s=
|
github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s=
|
||||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||||
github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||||
|
@ -226,7 +221,6 @@ github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw
|
||||||
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||||
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||||
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||||
github.com/golang/snappy v0.0.2 h1:aeE13tS0IiQgFjYdoL8qN3K1N2bXXtI6Vi51/y7BpMw=
|
|
||||||
github.com/golang/snappy v0.0.2/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
github.com/golang/snappy v0.0.2/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||||
github.com/golang/snappy v0.0.3 h1:fHPg5GQYlCeLIPB9BZqMVR5nR9A+IM5zcgeTdjMYmLA=
|
github.com/golang/snappy v0.0.3 h1:fHPg5GQYlCeLIPB9BZqMVR5nR9A+IM5zcgeTdjMYmLA=
|
||||||
github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||||
|
@ -348,7 +342,6 @@ github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa02
|
||||||
github.com/klauspost/cpuid/v2 v2.0.6 h1:dQ5ueTiftKxp0gyjKSx5+8BtPWkyQbd95m8Gys/RarI=
|
github.com/klauspost/cpuid/v2 v2.0.6 h1:dQ5ueTiftKxp0gyjKSx5+8BtPWkyQbd95m8Gys/RarI=
|
||||||
github.com/klauspost/cpuid/v2 v2.0.6/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
github.com/klauspost/cpuid/v2 v2.0.6/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
||||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||||
github.com/konsorten/go-windows-terminal-sequences v1.0.3 h1:CE8S1cTafDpPvMhIxNJKvHsGVBgn1xWYf1NbHQhywc8=
|
|
||||||
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||||
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
|
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
|
||||||
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
||||||
|
@ -407,8 +400,6 @@ github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzE
|
||||||
github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w=
|
github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w=
|
||||||
github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w=
|
github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w=
|
||||||
github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
|
github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
|
||||||
github.com/nbutton23/zxcvbn-go v0.0.0-20210217022336-fa2cb2858354 h1:4kuARK6Y6FxaNu/BnU2OAaLF86eTVhP2hjTB6iMvItA=
|
|
||||||
github.com/nbutton23/zxcvbn-go v0.0.0-20210217022336-fa2cb2858354/go.mod h1:KSVJerMDfblTH7p5MZaTt+8zaT2iEk3AkVb9PQdZuE8=
|
|
||||||
github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs=
|
github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs=
|
||||||
github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA=
|
github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA=
|
||||||
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
|
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
|
||||||
|
@ -486,10 +477,9 @@ github.com/prysmaticlabs/ethereumapis v0.0.0-20200812153649-a842fc47c2c3 h1:0f++
|
||||||
github.com/prysmaticlabs/ethereumapis v0.0.0-20200812153649-a842fc47c2c3/go.mod h1:k7b2dxy6RppCG6kmOJkNOXzRpEoTdsPygc2aQhsUsZk=
|
github.com/prysmaticlabs/ethereumapis v0.0.0-20200812153649-a842fc47c2c3/go.mod h1:k7b2dxy6RppCG6kmOJkNOXzRpEoTdsPygc2aQhsUsZk=
|
||||||
github.com/prysmaticlabs/go-bitfield v0.0.0-20200322041314-62c2aee71669/go.mod h1:hCwmef+4qXWjv0jLDbQdWnL0Ol7cS7/lCSS26WR+u6s=
|
github.com/prysmaticlabs/go-bitfield v0.0.0-20200322041314-62c2aee71669/go.mod h1:hCwmef+4qXWjv0jLDbQdWnL0Ol7cS7/lCSS26WR+u6s=
|
||||||
github.com/prysmaticlabs/go-bitfield v0.0.0-20200618145306-2ae0807bef65/go.mod h1:hCwmef+4qXWjv0jLDbQdWnL0Ol7cS7/lCSS26WR+u6s=
|
github.com/prysmaticlabs/go-bitfield v0.0.0-20200618145306-2ae0807bef65/go.mod h1:hCwmef+4qXWjv0jLDbQdWnL0Ol7cS7/lCSS26WR+u6s=
|
||||||
github.com/prysmaticlabs/go-bitfield v0.0.0-20210202205921-7fcea7c45dc8 h1:18+Qqobq3HAUY0hgIhPGSqmLFnaLLocemmU7+Sj2aYQ=
|
|
||||||
github.com/prysmaticlabs/go-bitfield v0.0.0-20210202205921-7fcea7c45dc8/go.mod h1:hCwmef+4qXWjv0jLDbQdWnL0Ol7cS7/lCSS26WR+u6s=
|
|
||||||
github.com/prysmaticlabs/go-bitfield v0.0.0-20210607200045-4da71aaf6c2d h1:46gKr69IlRpv/ENdlzG0SWo5nMLKJxS3tI5NOSdZndQ=
|
|
||||||
github.com/prysmaticlabs/go-bitfield v0.0.0-20210607200045-4da71aaf6c2d/go.mod h1:hCwmef+4qXWjv0jLDbQdWnL0Ol7cS7/lCSS26WR+u6s=
|
github.com/prysmaticlabs/go-bitfield v0.0.0-20210607200045-4da71aaf6c2d/go.mod h1:hCwmef+4qXWjv0jLDbQdWnL0Ol7cS7/lCSS26WR+u6s=
|
||||||
|
github.com/prysmaticlabs/go-bitfield v0.0.0-20210809151128-385d8c5e3fb7 h1:0tVE4tdWQK9ZpYygoV7+vS6QkDvQVySboMVEIxBJmXw=
|
||||||
|
github.com/prysmaticlabs/go-bitfield v0.0.0-20210809151128-385d8c5e3fb7/go.mod h1:wmuf/mdK4VMD+jA9ThwcUKjg3a2XWM9cVfFYjDyY4j4=
|
||||||
github.com/r3labs/sse/v2 v2.3.0 h1:R/UMa0ML6AYKQ8irQNHhY+204lz1LytDIdKhCxSVAd8=
|
github.com/r3labs/sse/v2 v2.3.0 h1:R/UMa0ML6AYKQ8irQNHhY+204lz1LytDIdKhCxSVAd8=
|
||||||
github.com/r3labs/sse/v2 v2.3.0/go.mod h1:hUrYMKfu9WquG9MyI0r6TKiNH+6Sw/QPKm2YbNbU5g8=
|
github.com/r3labs/sse/v2 v2.3.0/go.mod h1:hUrYMKfu9WquG9MyI0r6TKiNH+6Sw/QPKm2YbNbU5g8=
|
||||||
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
|
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
|
||||||
|
@ -499,8 +489,9 @@ github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFR
|
||||||
github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ=
|
github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ=
|
||||||
github.com/rs/zerolog v1.19.0/go.mod h1:IzD0RJ65iWH0w97OQQebJEvTZYvsCUm9WVLWBQrJRjo=
|
github.com/rs/zerolog v1.19.0/go.mod h1:IzD0RJ65iWH0w97OQQebJEvTZYvsCUm9WVLWBQrJRjo=
|
||||||
github.com/rs/zerolog v1.20.0/go.mod h1:IzD0RJ65iWH0w97OQQebJEvTZYvsCUm9WVLWBQrJRjo=
|
github.com/rs/zerolog v1.20.0/go.mod h1:IzD0RJ65iWH0w97OQQebJEvTZYvsCUm9WVLWBQrJRjo=
|
||||||
github.com/rs/zerolog v1.21.0 h1:Q3vdXlfLNT+OftyBHsU0Y445MD+8m8axjKgf2si0QcM=
|
|
||||||
github.com/rs/zerolog v1.21.0/go.mod h1:ZPhntP/xmq1nnND05hhpAh2QMhSsA4UN3MGZ6O2J3hM=
|
github.com/rs/zerolog v1.21.0/go.mod h1:ZPhntP/xmq1nnND05hhpAh2QMhSsA4UN3MGZ6O2J3hM=
|
||||||
|
github.com/rs/zerolog v1.23.0 h1:UskrK+saS9P9Y789yNNulYKdARjPZuS35B8gJF2x60g=
|
||||||
|
github.com/rs/zerolog v1.23.0/go.mod h1:6c7hFfxPOy7TacJc4Fcdi24/J0NKYGzjG8FWRI916Qo=
|
||||||
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
|
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
|
||||||
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||||
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
|
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
|
||||||
|
@ -513,7 +504,6 @@ github.com/shibukawa/configdir v0.0.0-20170330084843-e180dbdc8da0/go.mod h1:7Awj
|
||||||
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||||
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||||
github.com/sirupsen/logrus v1.6.0 h1:UBcNElsrwanuuMsnGSlYmtmgbb23qDR5dG+6X6Oo89I=
|
|
||||||
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
|
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
|
||||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
||||||
github.com/smartystreets/assertions v1.0.0 h1:UVQPSSmc3qtTi+zPPkCXvZX9VvW/xT/NsRvKfwY81a8=
|
github.com/smartystreets/assertions v1.0.0 h1:UVQPSSmc3qtTi+zPPkCXvZX9VvW/xT/NsRvKfwY81a8=
|
||||||
|
@ -523,7 +513,6 @@ github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9
|
||||||
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
|
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
|
||||||
github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY=
|
github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY=
|
||||||
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
||||||
github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI=
|
|
||||||
github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
||||||
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
|
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
|
||||||
github.com/spf13/afero v1.4.1/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I=
|
github.com/spf13/afero v1.4.1/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I=
|
||||||
|
@ -550,7 +539,6 @@ github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5J
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A=
|
github.com/stretchr/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A=
|
||||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/testify v1.1.4/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
|
||||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||||
|
|
64
main.go
64
main.go
|
@ -70,6 +70,8 @@ import (
|
||||||
firstattestationdatastrategy "github.com/attestantio/vouch/strategies/attestationdata/first"
|
firstattestationdatastrategy "github.com/attestantio/vouch/strategies/attestationdata/first"
|
||||||
bestbeaconblockproposalstrategy "github.com/attestantio/vouch/strategies/beaconblockproposal/best"
|
bestbeaconblockproposalstrategy "github.com/attestantio/vouch/strategies/beaconblockproposal/best"
|
||||||
firstbeaconblockproposalstrategy "github.com/attestantio/vouch/strategies/beaconblockproposal/first"
|
firstbeaconblockproposalstrategy "github.com/attestantio/vouch/strategies/beaconblockproposal/first"
|
||||||
|
bestsynccommitteecontributionstrategy "github.com/attestantio/vouch/strategies/synccommitteecontribution/best"
|
||||||
|
firstsynccommitteecontributionstrategy "github.com/attestantio/vouch/strategies/synccommitteecontribution/first"
|
||||||
"github.com/attestantio/vouch/util"
|
"github.com/attestantio/vouch/util"
|
||||||
"github.com/aws/aws-sdk-go/aws/credentials"
|
"github.com/aws/aws-sdk-go/aws/credentials"
|
||||||
homedir "github.com/mitchellh/go-homedir"
|
homedir "github.com/mitchellh/go-homedir"
|
||||||
|
@ -89,7 +91,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// ReleaseVersion is the release version for the code.
|
// ReleaseVersion is the release version for the code.
|
||||||
var ReleaseVersion = "1.1.0"
|
var ReleaseVersion = "1.2.0-pre"
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
os.Exit(main2())
|
os.Exit(main2())
|
||||||
|
@ -424,6 +426,12 @@ func startServices(ctx context.Context, majordomo majordomo.Service) error {
|
||||||
return errors.Wrap(err, "failed to start beacon committee subscriber service")
|
return errors.Wrap(err, "failed to start beacon committee subscriber service")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log.Trace().Msg("Selecting sync committee contribution provider")
|
||||||
|
syncCommitteeContributionProvider, err := selectSyncCommitteeContributionProvider(ctx, monitor, eth2Client)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, "failed to select sync committee contribution provider")
|
||||||
|
}
|
||||||
|
|
||||||
log.Trace().Msg("Starting sync committee aggregator")
|
log.Trace().Msg("Starting sync committee aggregator")
|
||||||
syncCommitteeAggregator, err = standardsynccommitteeaggregator.New(ctx,
|
syncCommitteeAggregator, err = standardsynccommitteeaggregator.New(ctx,
|
||||||
standardsynccommitteeaggregator.WithLogLevel(logLevel(viper.GetString("synccommitteeaggregator.log-level"))),
|
standardsynccommitteeaggregator.WithLogLevel(logLevel(viper.GetString("synccommitteeaggregator.log-level"))),
|
||||||
|
@ -432,7 +440,7 @@ func startServices(ctx context.Context, majordomo majordomo.Service) error {
|
||||||
standardsynccommitteeaggregator.WithBeaconBlockRootProvider(eth2Client.(eth2client.BeaconBlockRootProvider)),
|
standardsynccommitteeaggregator.WithBeaconBlockRootProvider(eth2Client.(eth2client.BeaconBlockRootProvider)),
|
||||||
standardsynccommitteeaggregator.WithContributionAndProofSigner(signerSvc.(signer.ContributionAndProofSigner)),
|
standardsynccommitteeaggregator.WithContributionAndProofSigner(signerSvc.(signer.ContributionAndProofSigner)),
|
||||||
standardsynccommitteeaggregator.WithValidatingAccountsProvider(accountManager.(accountmanager.ValidatingAccountsProvider)),
|
standardsynccommitteeaggregator.WithValidatingAccountsProvider(accountManager.(accountmanager.ValidatingAccountsProvider)),
|
||||||
standardsynccommitteeaggregator.WithSyncCommitteeContributionProvider(eth2Client.(eth2client.SyncCommitteeContributionProvider)),
|
standardsynccommitteeaggregator.WithSyncCommitteeContributionProvider(syncCommitteeContributionProvider),
|
||||||
standardsynccommitteeaggregator.WithSyncCommitteeContributionsSubmitter(submitterStrategy.(submitter.SyncCommitteeContributionsSubmitter)),
|
standardsynccommitteeaggregator.WithSyncCommitteeContributionsSubmitter(submitterStrategy.(submitter.SyncCommitteeContributionsSubmitter)),
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -932,6 +940,58 @@ func selectBeaconBlockProposalProvider(ctx context.Context,
|
||||||
return beaconBlockProposalProvider, nil
|
return beaconBlockProposalProvider, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func selectSyncCommitteeContributionProvider(ctx context.Context,
|
||||||
|
monitor metrics.Service,
|
||||||
|
eth2Client eth2client.Service,
|
||||||
|
) (eth2client.SyncCommitteeContributionProvider, error) {
|
||||||
|
var syncCommitteeContributionProvider eth2client.SyncCommitteeContributionProvider
|
||||||
|
var err error
|
||||||
|
switch viper.GetString("strategies.synccommitteecontribution.style") {
|
||||||
|
case "best":
|
||||||
|
log.Info().Msg("Starting best sync committee contribution strategy")
|
||||||
|
syncCommitteeContributionProviders := make(map[string]eth2client.SyncCommitteeContributionProvider)
|
||||||
|
for _, address := range viper.GetStringSlice("strategies.synccommitteecontribution.beacon-node-addresses") {
|
||||||
|
client, err := fetchClient(ctx, address)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, fmt.Sprintf("failed to fetch client %s for sync committee contribution strategy", address))
|
||||||
|
}
|
||||||
|
syncCommitteeContributionProviders[address] = client.(eth2client.SyncCommitteeContributionProvider)
|
||||||
|
}
|
||||||
|
syncCommitteeContributionProvider, err = bestsynccommitteecontributionstrategy.New(ctx,
|
||||||
|
bestsynccommitteecontributionstrategy.WithClientMonitor(monitor.(metrics.ClientMonitor)),
|
||||||
|
bestsynccommitteecontributionstrategy.WithProcessConcurrency(util.ProcessConcurrency("strategies.synccommitteecontribution.best")),
|
||||||
|
bestsynccommitteecontributionstrategy.WithLogLevel(logLevel(viper.GetString("strategies.synccommitteecontribution.log-level"))),
|
||||||
|
bestsynccommitteecontributionstrategy.WithSyncCommitteeContributionProviders(syncCommitteeContributionProviders),
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "failed to start best sync committee contribution strategy")
|
||||||
|
}
|
||||||
|
case "first":
|
||||||
|
log.Info().Msg("Starting first sync committee contribution strategy")
|
||||||
|
syncCommitteeContributionProviders := make(map[string]eth2client.SyncCommitteeContributionProvider)
|
||||||
|
for _, address := range viper.GetStringSlice("strategies.synccommitteecontribution.beacon-node-addresses") {
|
||||||
|
client, err := fetchClient(ctx, address)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, fmt.Sprintf("failed to fetch client %s for sync committee contribution strategy", address))
|
||||||
|
}
|
||||||
|
syncCommitteeContributionProviders[address] = client.(eth2client.SyncCommitteeContributionProvider)
|
||||||
|
}
|
||||||
|
syncCommitteeContributionProvider, err = firstsynccommitteecontributionstrategy.New(ctx,
|
||||||
|
firstsynccommitteecontributionstrategy.WithClientMonitor(monitor.(metrics.ClientMonitor)),
|
||||||
|
firstsynccommitteecontributionstrategy.WithLogLevel(logLevel(viper.GetString("strategies.synccommitteecontribution.log-level"))),
|
||||||
|
firstsynccommitteecontributionstrategy.WithSyncCommitteeContributionProviders(syncCommitteeContributionProviders),
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "failed to start first sync committee contribution strategy")
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
log.Info().Msg("Starting simple sync committee contribution strategy")
|
||||||
|
syncCommitteeContributionProvider = eth2Client.(eth2client.SyncCommitteeContributionProvider)
|
||||||
|
}
|
||||||
|
|
||||||
|
return syncCommitteeContributionProvider, nil
|
||||||
|
}
|
||||||
|
|
||||||
func selectSubmitterStrategy(ctx context.Context, monitor metrics.Service, eth2Client eth2client.Service) (submitter.Service, error) {
|
func selectSubmitterStrategy(ctx context.Context, monitor metrics.Service, eth2Client eth2client.Service) (submitter.Service, error) {
|
||||||
var submitter submitter.Service
|
var submitter submitter.Service
|
||||||
var err error
|
var err error
|
||||||
|
|
|
@ -1381,3 +1381,82 @@ func (m *ValidatorsWithoutBalanceProvider) ValidatorsWithoutBalance(ctx context.
|
||||||
}
|
}
|
||||||
return res, nil
|
return res, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SyncCommitteeContributionProvider is a mock for eth2client.SyncCommitteeContributionProvider.
|
||||||
|
type SyncCommitteeContributionProvider struct{}
|
||||||
|
|
||||||
|
// NewSyncCommitteeContributionProvider returns a mock attestation data provider.
|
||||||
|
func NewSyncCommitteeContributionProvider() eth2client.SyncCommitteeContributionProvider {
|
||||||
|
return &SyncCommitteeContributionProvider{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// SyncCommitteeContribution is a mock.
|
||||||
|
func (m *SyncCommitteeContributionProvider) SyncCommitteeContribution(ctx context.Context, slot phase0.Slot, subcommitteeIndex uint64, beaconBlockRoot phase0.Root) (*altair.SyncCommitteeContribution, error) {
|
||||||
|
aggregationBits := bitfield.NewBitvector128()
|
||||||
|
aggregationBits.SetBitAt(1, true)
|
||||||
|
aggregationBits.SetBitAt(3, true)
|
||||||
|
aggregationBits.SetBitAt(8, true)
|
||||||
|
aggregationBits.SetBitAt(12, true)
|
||||||
|
aggregationBits.SetBitAt(65, true)
|
||||||
|
aggregationBits.SetBitAt(77, true)
|
||||||
|
return &altair.SyncCommitteeContribution{
|
||||||
|
Slot: slot,
|
||||||
|
BeaconBlockRoot: beaconBlockRoot,
|
||||||
|
SubcommitteeIndex: subcommitteeIndex,
|
||||||
|
AggregationBits: aggregationBits,
|
||||||
|
Signature: phase0.BLSSignature([96]byte{
|
||||||
|
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
|
||||||
|
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
|
||||||
|
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
|
||||||
|
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
|
||||||
|
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
|
||||||
|
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
|
||||||
|
}),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ErroringSyncCommitteeContributionProvider is a mock for eth2client.SyncCommitteeContributionProvider.
|
||||||
|
type ErroringSyncCommitteeContributionProvider struct{}
|
||||||
|
|
||||||
|
// NewErroringSyncCommitteeContributionProvider returns a mock attestation data provider.
|
||||||
|
func NewErroringSyncCommitteeContributionProvider() eth2client.SyncCommitteeContributionProvider {
|
||||||
|
return &ErroringSyncCommitteeContributionProvider{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// SyncCommitteeContribution is a mock.
|
||||||
|
func (m *ErroringSyncCommitteeContributionProvider) SyncCommitteeContribution(ctx context.Context, slot phase0.Slot, subcommitteeIndex uint64, beaconBlockRoot phase0.Root) (*altair.SyncCommitteeContribution, error) {
|
||||||
|
return nil, errors.New("mock error")
|
||||||
|
}
|
||||||
|
|
||||||
|
// NilSyncCommitteeContributionProvider is a mock for eth2client.SyncCommitteeContributionProvider.
|
||||||
|
type NilSyncCommitteeContributionProvider struct{}
|
||||||
|
|
||||||
|
// NewNilSyncCommitteeContributionProvider returns a mock attestation data provider.
|
||||||
|
func NewNilSyncCommitteeContributionProvider() eth2client.SyncCommitteeContributionProvider {
|
||||||
|
return &NilSyncCommitteeContributionProvider{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// SyncCommitteeContribution is a mock.
|
||||||
|
func (m *NilSyncCommitteeContributionProvider) SyncCommitteeContribution(ctx context.Context, slot phase0.Slot, subcommitteeIndex uint64, beaconBlockRoot phase0.Root) (*altair.SyncCommitteeContribution, error) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SleepySyncCommitteeContributionProvider is a mock for eth2client.SyncCommitteeContributionProvider.
|
||||||
|
type SleepySyncCommitteeContributionProvider struct {
|
||||||
|
wait time.Duration
|
||||||
|
next eth2client.SyncCommitteeContributionProvider
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewSleepySyncCommitteeContributionProvider returns a mock attestation data provider.
|
||||||
|
func NewSleepySyncCommitteeContributionProvider(wait time.Duration, next eth2client.SyncCommitteeContributionProvider) eth2client.SyncCommitteeContributionProvider {
|
||||||
|
return &SleepySyncCommitteeContributionProvider{
|
||||||
|
wait: wait,
|
||||||
|
next: next,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// SyncCommitteeContribution is a mock.
|
||||||
|
func (m *SleepySyncCommitteeContributionProvider) SyncCommitteeContribution(ctx context.Context, slot phase0.Slot, subcommitteeIndex uint64, beaconBlockRoot phase0.Root) (*altair.SyncCommitteeContribution, error) {
|
||||||
|
time.Sleep(m.wait)
|
||||||
|
return m.next.SyncCommitteeContribution(ctx, slot, subcommitteeIndex, beaconBlockRoot)
|
||||||
|
}
|
||||||
|
|
|
@ -19,6 +19,7 @@ import (
|
||||||
|
|
||||||
eth2client "github.com/attestantio/go-eth2-client"
|
eth2client "github.com/attestantio/go-eth2-client"
|
||||||
"github.com/attestantio/go-eth2-client/spec/phase0"
|
"github.com/attestantio/go-eth2-client/spec/phase0"
|
||||||
|
"github.com/attestantio/vouch/util"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -31,6 +32,7 @@ type aggregateAttestationResponse struct {
|
||||||
// AggregateAttestation provides the aggregate attestation from a number of beacon nodes.
|
// AggregateAttestation provides the aggregate attestation from a number of beacon nodes.
|
||||||
func (s *Service) AggregateAttestation(ctx context.Context, slot phase0.Slot, attestationDataRoot phase0.Root) (*phase0.Attestation, error) {
|
func (s *Service) AggregateAttestation(ctx context.Context, slot phase0.Slot, attestationDataRoot phase0.Root) (*phase0.Attestation, error) {
|
||||||
started := time.Now()
|
started := time.Now()
|
||||||
|
log := util.LogWithID(ctx, log, "strategy_id")
|
||||||
|
|
||||||
// We create a cancelable context with a timeout. If the context times out we take the best to date.
|
// We create a cancelable context with a timeout. If the context times out we take the best to date.
|
||||||
ctx, cancel := context.WithTimeout(ctx, s.timeout)
|
ctx, cancel := context.WithTimeout(ctx, s.timeout)
|
||||||
|
|
|
@ -74,7 +74,7 @@ func WithAggregateAttestationProviders(providers map[string]eth2client.Aggregate
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// WithTimeout sets the timeout for beacon block proposal requests.
|
// WithTimeout sets the timeout for requests.
|
||||||
func WithTimeout(timeout time.Duration) Parameter {
|
func WithTimeout(timeout time.Duration) Parameter {
|
||||||
return parameterFunc(func(p *parameters) {
|
return parameterFunc(func(p *parameters) {
|
||||||
p.timeout = timeout
|
p.timeout = timeout
|
||||||
|
|
|
@ -19,12 +19,14 @@ import (
|
||||||
|
|
||||||
eth2client "github.com/attestantio/go-eth2-client"
|
eth2client "github.com/attestantio/go-eth2-client"
|
||||||
"github.com/attestantio/go-eth2-client/spec/phase0"
|
"github.com/attestantio/go-eth2-client/spec/phase0"
|
||||||
|
"github.com/attestantio/vouch/util"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
// AggregateAttestation provides the aggregate attestation from a number of beacon nodes.
|
// AggregateAttestation provides the aggregate attestation from a number of beacon nodes.
|
||||||
func (s *Service) AggregateAttestation(ctx context.Context, slot phase0.Slot, attestationDataRoot phase0.Root) (*phase0.Attestation, error) {
|
func (s *Service) AggregateAttestation(ctx context.Context, slot phase0.Slot, attestationDataRoot phase0.Root) (*phase0.Attestation, error) {
|
||||||
started := time.Now()
|
started := time.Now()
|
||||||
|
log := util.LogWithID(ctx, log, "strategy_id")
|
||||||
|
|
||||||
// We create a cancelable context with a timeout. When a provider responds we cancel the context to cancel the other requests.
|
// We create a cancelable context with a timeout. When a provider responds we cancel the context to cancel the other requests.
|
||||||
ctx, cancel := context.WithTimeout(ctx, s.timeout)
|
ctx, cancel := context.WithTimeout(ctx, s.timeout)
|
||||||
|
|
|
@ -65,7 +65,7 @@ func WithAggregateAttestationProviders(providers map[string]eth2client.Aggregate
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// WithTimeout sets the timeout for beacon block proposal requests.
|
// WithTimeout sets the timeout for requests.
|
||||||
func WithTimeout(timeout time.Duration) Parameter {
|
func WithTimeout(timeout time.Duration) Parameter {
|
||||||
return parameterFunc(func(p *parameters) {
|
return parameterFunc(func(p *parameters) {
|
||||||
p.timeout = timeout
|
p.timeout = timeout
|
||||||
|
|
|
@ -19,6 +19,7 @@ import (
|
||||||
|
|
||||||
eth2client "github.com/attestantio/go-eth2-client"
|
eth2client "github.com/attestantio/go-eth2-client"
|
||||||
"github.com/attestantio/go-eth2-client/spec/phase0"
|
"github.com/attestantio/go-eth2-client/spec/phase0"
|
||||||
|
"github.com/attestantio/vouch/util"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -31,7 +32,7 @@ type attestationDataResponse struct {
|
||||||
// AttestationData provides the best attestation data from a number of beacon nodes.
|
// AttestationData provides the best attestation data from a number of beacon nodes.
|
||||||
func (s *Service) AttestationData(ctx context.Context, slot phase0.Slot, committeeIndex phase0.CommitteeIndex) (*phase0.AttestationData, error) {
|
func (s *Service) AttestationData(ctx context.Context, slot phase0.Slot, committeeIndex phase0.CommitteeIndex) (*phase0.AttestationData, error) {
|
||||||
started := time.Now()
|
started := time.Now()
|
||||||
log := log.With().Uint64("slot", uint64(slot)).Logger()
|
log := util.LogWithID(ctx, log, "strategy_id").With().Uint64("slot", uint64(slot)).Logger()
|
||||||
|
|
||||||
// We create a cancelable context with a timeout. If the context times out we take the best to date.
|
// We create a cancelable context with a timeout. If the context times out we take the best to date.
|
||||||
ctx, cancel := context.WithTimeout(ctx, s.timeout)
|
ctx, cancel := context.WithTimeout(ctx, s.timeout)
|
||||||
|
|
|
@ -74,7 +74,7 @@ func WithAttestationDataProviders(providers map[string]eth2client.AttestationDat
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// WithTimeout sets the timeout for beacon block proposal requests.
|
// WithTimeout sets the timeout for requests.
|
||||||
func WithTimeout(timeout time.Duration) Parameter {
|
func WithTimeout(timeout time.Duration) Parameter {
|
||||||
return parameterFunc(func(p *parameters) {
|
return parameterFunc(func(p *parameters) {
|
||||||
p.timeout = timeout
|
p.timeout = timeout
|
||||||
|
|
|
@ -19,12 +19,14 @@ import (
|
||||||
|
|
||||||
eth2client "github.com/attestantio/go-eth2-client"
|
eth2client "github.com/attestantio/go-eth2-client"
|
||||||
"github.com/attestantio/go-eth2-client/spec/phase0"
|
"github.com/attestantio/go-eth2-client/spec/phase0"
|
||||||
|
"github.com/attestantio/vouch/util"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
// AttestationData provides the first attestation data from a number of beacon nodes.
|
// AttestationData provides the first attestation data from a number of beacon nodes.
|
||||||
func (s *Service) AttestationData(ctx context.Context, slot phase0.Slot, committeeIndex phase0.CommitteeIndex) (*phase0.AttestationData, error) {
|
func (s *Service) AttestationData(ctx context.Context, slot phase0.Slot, committeeIndex phase0.CommitteeIndex) (*phase0.AttestationData, error) {
|
||||||
started := time.Now()
|
started := time.Now()
|
||||||
|
log := util.LogWithID(ctx, log, "strategy_id")
|
||||||
|
|
||||||
// We create a cancelable context with a timeout. When a provider responds we cancel the context to cancel the other requests.
|
// We create a cancelable context with a timeout. When a provider responds we cancel the context to cancel the other requests.
|
||||||
ctx, cancel := context.WithTimeout(ctx, s.timeout)
|
ctx, cancel := context.WithTimeout(ctx, s.timeout)
|
||||||
|
|
|
@ -65,7 +65,7 @@ func WithAttestationDataProviders(providers map[string]eth2client.AttestationDat
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// WithTimeout sets the timeout for beacon block proposal requests.
|
// WithTimeout sets the timeout for requests.
|
||||||
func WithTimeout(timeout time.Duration) Parameter {
|
func WithTimeout(timeout time.Duration) Parameter {
|
||||||
return parameterFunc(func(p *parameters) {
|
return parameterFunc(func(p *parameters) {
|
||||||
p.timeout = timeout
|
p.timeout = timeout
|
||||||
|
|
|
@ -22,6 +22,7 @@ import (
|
||||||
eth2client "github.com/attestantio/go-eth2-client"
|
eth2client "github.com/attestantio/go-eth2-client"
|
||||||
"github.com/attestantio/go-eth2-client/spec"
|
"github.com/attestantio/go-eth2-client/spec"
|
||||||
"github.com/attestantio/go-eth2-client/spec/phase0"
|
"github.com/attestantio/go-eth2-client/spec/phase0"
|
||||||
|
"github.com/attestantio/vouch/util"
|
||||||
"golang.org/x/sync/semaphore"
|
"golang.org/x/sync/semaphore"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -33,6 +34,7 @@ func (s *Service) BeaconBlockProposal(ctx context.Context, slot phase0.Slot, ran
|
||||||
bestProvider := ""
|
bestProvider := ""
|
||||||
|
|
||||||
started := time.Now()
|
started := time.Now()
|
||||||
|
log := util.LogWithID(ctx, log, "strategy_id")
|
||||||
sem := semaphore.NewWeighted(s.processConcurrency)
|
sem := semaphore.NewWeighted(s.processConcurrency)
|
||||||
var wg sync.WaitGroup
|
var wg sync.WaitGroup
|
||||||
for name, provider := range s.beaconBlockProposalProviders {
|
for name, provider := range s.beaconBlockProposalProviders {
|
||||||
|
|
|
@ -53,7 +53,7 @@ func WithLogLevel(logLevel zerolog.Level) Parameter {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// WithTimeout sets the timeout for beacon block proposal requests.
|
// WithTimeout sets the timeout for requests.
|
||||||
func WithTimeout(timeout time.Duration) Parameter {
|
func WithTimeout(timeout time.Duration) Parameter {
|
||||||
return parameterFunc(func(p *parameters) {
|
return parameterFunc(func(p *parameters) {
|
||||||
p.timeout = timeout
|
p.timeout = timeout
|
||||||
|
|
|
@ -65,7 +65,7 @@ func WithBeaconBlockProposalProviders(providers map[string]eth2client.BeaconBloc
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// WithTimeout sets the timeout for beacon block proposal requests.
|
// WithTimeout sets the timeout for requests.
|
||||||
func WithTimeout(timeout time.Duration) Parameter {
|
func WithTimeout(timeout time.Duration) Parameter {
|
||||||
return parameterFunc(func(p *parameters) {
|
return parameterFunc(func(p *parameters) {
|
||||||
p.timeout = timeout
|
p.timeout = timeout
|
||||||
|
|
|
@ -0,0 +1,112 @@
|
||||||
|
// Copyright © 2021 Attestant Limited.
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
// Package best is a strategy that obtains sync committee contributions
|
||||||
|
// from multiple nodes and selects the best one.
|
||||||
|
package best
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"runtime"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
eth2client "github.com/attestantio/go-eth2-client"
|
||||||
|
"github.com/attestantio/vouch/services/metrics"
|
||||||
|
nullmetrics "github.com/attestantio/vouch/services/metrics/null"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
"github.com/rs/zerolog"
|
||||||
|
)
|
||||||
|
|
||||||
|
type parameters struct {
|
||||||
|
logLevel zerolog.Level
|
||||||
|
clientMonitor metrics.ClientMonitor
|
||||||
|
processConcurrency int64
|
||||||
|
syncCommitteeContributionProviders map[string]eth2client.SyncCommitteeContributionProvider
|
||||||
|
timeout time.Duration
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parameter is the interface for service parameters.
|
||||||
|
type Parameter interface {
|
||||||
|
apply(*parameters)
|
||||||
|
}
|
||||||
|
|
||||||
|
type parameterFunc func(*parameters)
|
||||||
|
|
||||||
|
func (f parameterFunc) apply(p *parameters) {
|
||||||
|
f(p)
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithLogLevel sets the log level for the module.
|
||||||
|
func WithLogLevel(logLevel zerolog.Level) Parameter {
|
||||||
|
return parameterFunc(func(p *parameters) {
|
||||||
|
p.logLevel = logLevel
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithClientMonitor sets the client monitor for the service.
|
||||||
|
func WithClientMonitor(monitor metrics.ClientMonitor) Parameter {
|
||||||
|
return parameterFunc(func(p *parameters) {
|
||||||
|
p.clientMonitor = monitor
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithProcessConcurrency sets the concurrency for the service.
|
||||||
|
func WithProcessConcurrency(concurrency int64) Parameter {
|
||||||
|
return parameterFunc(func(p *parameters) {
|
||||||
|
p.processConcurrency = concurrency
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithSyncCommitteeContributionProviders sets the sync committee contribution providers.
|
||||||
|
func WithSyncCommitteeContributionProviders(providers map[string]eth2client.SyncCommitteeContributionProvider) Parameter {
|
||||||
|
return parameterFunc(func(p *parameters) {
|
||||||
|
p.syncCommitteeContributionProviders = providers
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithTimeout sets the timeout for requests.
|
||||||
|
func WithTimeout(timeout time.Duration) Parameter {
|
||||||
|
return parameterFunc(func(p *parameters) {
|
||||||
|
p.timeout = timeout
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// parseAndCheckParameters parses and checks parameters to ensure that mandatory parameters are present and correct.
|
||||||
|
func parseAndCheckParameters(params ...Parameter) (*parameters, error) {
|
||||||
|
parameters := parameters{
|
||||||
|
logLevel: zerolog.GlobalLevel(),
|
||||||
|
timeout: 2 * time.Second,
|
||||||
|
clientMonitor: nullmetrics.New(context.Background()),
|
||||||
|
processConcurrency: int64(runtime.GOMAXPROCS(-1)),
|
||||||
|
}
|
||||||
|
for _, p := range params {
|
||||||
|
if params != nil {
|
||||||
|
p.apply(¶meters)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if parameters.timeout == 0 {
|
||||||
|
return nil, errors.New("no timeout specified")
|
||||||
|
}
|
||||||
|
if parameters.clientMonitor == nil {
|
||||||
|
return nil, errors.New("no client monitor specified")
|
||||||
|
}
|
||||||
|
if parameters.processConcurrency == 0 {
|
||||||
|
return nil, errors.New("no process concurrency specified")
|
||||||
|
}
|
||||||
|
if len(parameters.syncCommitteeContributionProviders) == 0 {
|
||||||
|
return nil, errors.New("no sync committee contribution providers specified")
|
||||||
|
}
|
||||||
|
|
||||||
|
return ¶meters, nil
|
||||||
|
}
|
|
@ -0,0 +1,43 @@
|
||||||
|
// Copyright © 2021 Attestant Limited.
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package best
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/attestantio/go-eth2-client/spec/altair"
|
||||||
|
)
|
||||||
|
|
||||||
|
// scoreSyncCommitteeContribution generates a score for an aggregate attestation.
|
||||||
|
// The score is relative to the completeness of the aggregate.
|
||||||
|
func (s *Service) scoreSyncCommitteeContribution(ctx context.Context,
|
||||||
|
name string,
|
||||||
|
contribution *altair.SyncCommitteeContribution,
|
||||||
|
) float64 {
|
||||||
|
if contribution == nil {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
score := float64(contribution.AggregationBits.Count())
|
||||||
|
|
||||||
|
log.Trace().
|
||||||
|
Str("provider", name).
|
||||||
|
Uint64("sync_committee_slot", uint64(contribution.Slot)).
|
||||||
|
Uint64("subcommittee_index", contribution.SubcommitteeIndex).
|
||||||
|
Str("beacon_block_root", fmt.Sprintf("%#x", contribution.BeaconBlockRoot)).
|
||||||
|
Float64("score", score).
|
||||||
|
Msg("Scored sync committee contribution")
|
||||||
|
return score
|
||||||
|
}
|
|
@ -0,0 +1,60 @@
|
||||||
|
// Copyright © 2021 Attestant Limited.
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package best
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
eth2client "github.com/attestantio/go-eth2-client"
|
||||||
|
"github.com/attestantio/vouch/services/metrics"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
"github.com/rs/zerolog"
|
||||||
|
zerologger "github.com/rs/zerolog/log"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Service is the provider for attestation data.
|
||||||
|
type Service struct {
|
||||||
|
clientMonitor metrics.ClientMonitor
|
||||||
|
processConcurrency int64
|
||||||
|
syncCommitteeContributionProviders map[string]eth2client.SyncCommitteeContributionProvider
|
||||||
|
timeout time.Duration
|
||||||
|
}
|
||||||
|
|
||||||
|
// module-wide log.
|
||||||
|
var log zerolog.Logger
|
||||||
|
|
||||||
|
// New creates a new attestation data strategy.
|
||||||
|
func New(ctx context.Context, params ...Parameter) (*Service, error) {
|
||||||
|
parameters, err := parseAndCheckParameters(params...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "problem with parameters")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set logging.
|
||||||
|
log = zerologger.With().Str("strategy", "synccommitteecontribution").Str("impl", "best").Logger()
|
||||||
|
if parameters.logLevel != log.GetLevel() {
|
||||||
|
log = log.Level(parameters.logLevel)
|
||||||
|
}
|
||||||
|
|
||||||
|
s := &Service{
|
||||||
|
timeout: parameters.timeout,
|
||||||
|
clientMonitor: parameters.clientMonitor,
|
||||||
|
processConcurrency: parameters.processConcurrency,
|
||||||
|
syncCommitteeContributionProviders: parameters.syncCommitteeContributionProviders,
|
||||||
|
}
|
||||||
|
log.Trace().Int64("process_concurrency", s.processConcurrency).Msg("Set process concurrency")
|
||||||
|
|
||||||
|
return s, nil
|
||||||
|
}
|
|
@ -0,0 +1,114 @@
|
||||||
|
// Copyright © 2021 Attestant Limited.
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package best_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
eth2client "github.com/attestantio/go-eth2-client"
|
||||||
|
"github.com/attestantio/vouch/mock"
|
||||||
|
"github.com/attestantio/vouch/strategies/synccommitteecontribution/best"
|
||||||
|
"github.com/rs/zerolog"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestService(t *testing.T) {
|
||||||
|
syncCommitteeContributionProviders := map[string]eth2client.SyncCommitteeContributionProvider{
|
||||||
|
"localhost:1": mock.NewSyncCommitteeContributionProvider(),
|
||||||
|
}
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
params []best.Parameter
|
||||||
|
err string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "TimeoutZero",
|
||||||
|
params: []best.Parameter{
|
||||||
|
best.WithLogLevel(zerolog.TraceLevel),
|
||||||
|
best.WithTimeout(0),
|
||||||
|
best.WithSyncCommitteeContributionProviders(syncCommitteeContributionProviders),
|
||||||
|
},
|
||||||
|
err: "problem with parameters: no timeout specified",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "ClientMonitorMissing",
|
||||||
|
params: []best.Parameter{
|
||||||
|
best.WithLogLevel(zerolog.TraceLevel),
|
||||||
|
best.WithClientMonitor(nil),
|
||||||
|
best.WithSyncCommitteeContributionProviders(syncCommitteeContributionProviders),
|
||||||
|
},
|
||||||
|
err: "problem with parameters: no client monitor specified",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "SyncCommitteeContributionProvidersNil",
|
||||||
|
params: []best.Parameter{
|
||||||
|
best.WithLogLevel(zerolog.TraceLevel),
|
||||||
|
best.WithSyncCommitteeContributionProviders(nil),
|
||||||
|
},
|
||||||
|
err: "problem with parameters: no sync committee contribution providers specified",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "ProcessConcurrencyZero",
|
||||||
|
params: []best.Parameter{
|
||||||
|
best.WithLogLevel(zerolog.TraceLevel),
|
||||||
|
best.WithSyncCommitteeContributionProviders(syncCommitteeContributionProviders),
|
||||||
|
best.WithProcessConcurrency(0),
|
||||||
|
},
|
||||||
|
err: "problem with parameters: no process concurrency specified",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "SyncCommitteeContributionProvidersEmpty",
|
||||||
|
params: []best.Parameter{
|
||||||
|
best.WithLogLevel(zerolog.TraceLevel),
|
||||||
|
best.WithSyncCommitteeContributionProviders(map[string]eth2client.SyncCommitteeContributionProvider{}),
|
||||||
|
},
|
||||||
|
err: "problem with parameters: no sync committee contribution providers specified",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Good",
|
||||||
|
params: []best.Parameter{
|
||||||
|
best.WithLogLevel(zerolog.TraceLevel),
|
||||||
|
best.WithTimeout(10 * time.Second),
|
||||||
|
best.WithSyncCommitteeContributionProviders(syncCommitteeContributionProviders),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests {
|
||||||
|
t.Run(test.name, func(t *testing.T) {
|
||||||
|
_, err := best.New(context.Background(), test.params...)
|
||||||
|
if test.err != "" {
|
||||||
|
require.EqualError(t, err, test.err)
|
||||||
|
} else {
|
||||||
|
require.NoError(t, err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestInterfaces(t *testing.T) {
|
||||||
|
syncCommitteeContributionProviders := map[string]eth2client.SyncCommitteeContributionProvider{
|
||||||
|
"localhost:1": mock.NewSyncCommitteeContributionProvider(),
|
||||||
|
}
|
||||||
|
|
||||||
|
s, err := best.New(context.Background(),
|
||||||
|
best.WithLogLevel(zerolog.Disabled),
|
||||||
|
best.WithSyncCommitteeContributionProviders(syncCommitteeContributionProviders),
|
||||||
|
)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Implements(t, (*eth2client.SyncCommitteeContributionProvider)(nil), s)
|
||||||
|
}
|
|
@ -0,0 +1,109 @@
|
||||||
|
// Copyright © 2021 Attestant Limited.
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package best
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
eth2client "github.com/attestantio/go-eth2-client"
|
||||||
|
"github.com/attestantio/go-eth2-client/spec/altair"
|
||||||
|
"github.com/attestantio/go-eth2-client/spec/phase0"
|
||||||
|
"github.com/attestantio/vouch/util"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
type syncCommitteeContributionResponse struct {
|
||||||
|
provider string
|
||||||
|
contribution *altair.SyncCommitteeContribution
|
||||||
|
score float64
|
||||||
|
}
|
||||||
|
|
||||||
|
// SyncCommitteeContribution provides the sync committee contribution from a number of beacon nodes.
|
||||||
|
func (s *Service) SyncCommitteeContribution(ctx context.Context, slot phase0.Slot, subcommitteeIndex uint64, beaconBlockRoot phase0.Root) (*altair.SyncCommitteeContribution, error) {
|
||||||
|
started := time.Now()
|
||||||
|
log := util.LogWithID(ctx, log, "strategy_id")
|
||||||
|
|
||||||
|
// We create a cancelable context with a timeout. If the context times out we take the best to date.
|
||||||
|
ctx, cancel := context.WithTimeout(ctx, s.timeout)
|
||||||
|
|
||||||
|
respCh := make(chan *syncCommitteeContributionResponse, len(s.syncCommitteeContributionProviders))
|
||||||
|
errCh := make(chan error, len(s.syncCommitteeContributionProviders))
|
||||||
|
// Kick off the requests.
|
||||||
|
for name, provider := range s.syncCommitteeContributionProviders {
|
||||||
|
go func(ctx context.Context,
|
||||||
|
name string,
|
||||||
|
provider eth2client.SyncCommitteeContributionProvider,
|
||||||
|
respCh chan *syncCommitteeContributionResponse,
|
||||||
|
errCh chan error,
|
||||||
|
) {
|
||||||
|
contribution, err := provider.SyncCommitteeContribution(ctx, slot, subcommitteeIndex, beaconBlockRoot)
|
||||||
|
s.clientMonitor.ClientOperation(name, "sync committee contribution", err == nil, time.Since(started))
|
||||||
|
if err != nil {
|
||||||
|
errCh <- err
|
||||||
|
return
|
||||||
|
}
|
||||||
|
log.Trace().Str("provider", name).Dur("elapsed", time.Since(started)).Msg("Obtained sync committee contribution")
|
||||||
|
if contribution == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
score := s.scoreSyncCommitteeContribution(ctx, name, contribution)
|
||||||
|
respCh <- &syncCommitteeContributionResponse{
|
||||||
|
provider: name,
|
||||||
|
contribution: contribution,
|
||||||
|
score: score,
|
||||||
|
}
|
||||||
|
}(ctx, name, provider, respCh, errCh)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait for all responses (or context done).
|
||||||
|
responded := 0
|
||||||
|
errored := 0
|
||||||
|
bestScore := float64(0)
|
||||||
|
var bestSyncCommitteeContribution *altair.SyncCommitteeContribution
|
||||||
|
bestProvider := ""
|
||||||
|
|
||||||
|
for responded+errored != len(s.syncCommitteeContributionProviders) {
|
||||||
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
// Anyone not responded by now is considered errored.
|
||||||
|
errored = len(s.syncCommitteeContributionProviders) - responded
|
||||||
|
log.Debug().Dur("elapsed", time.Since(started)).Msg("Timed out waiting for responses")
|
||||||
|
case err := <-errCh:
|
||||||
|
errored++
|
||||||
|
log.Warn().Dur("elapsed", time.Since(started)).Err(err).Msg("Error")
|
||||||
|
case resp := <-respCh:
|
||||||
|
responded++
|
||||||
|
if bestSyncCommitteeContribution == nil || resp.score > bestScore {
|
||||||
|
bestSyncCommitteeContribution = resp.contribution
|
||||||
|
bestScore = resp.score
|
||||||
|
bestProvider = resp.provider
|
||||||
|
}
|
||||||
|
log.Trace().Dur("elapsed", time.Since(started)).Msg("Response")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
log.Trace().Dur("elapsed", time.Since(started)).Int("responded", responded).Int("errored", errored).Str("best_provider", bestProvider).Msg("Complete")
|
||||||
|
cancel()
|
||||||
|
|
||||||
|
if bestSyncCommitteeContribution == nil {
|
||||||
|
return nil, errors.New("no sync committee contribution received")
|
||||||
|
}
|
||||||
|
log.Trace().Stringer("sync_committee_contribution", bestSyncCommitteeContribution).Float64("score", bestScore).Msg("Selected best sync committee contribution")
|
||||||
|
if bestProvider != "" {
|
||||||
|
s.clientMonitor.StrategyOperation("best", bestProvider, "sync committee contribution", time.Since(started))
|
||||||
|
}
|
||||||
|
|
||||||
|
return bestSyncCommitteeContribution, nil
|
||||||
|
}
|
|
@ -0,0 +1,84 @@
|
||||||
|
// Copyright © 2021 Attestant Limited.
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package best
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
eth2client "github.com/attestantio/go-eth2-client"
|
||||||
|
"github.com/attestantio/go-eth2-client/spec/altair"
|
||||||
|
"github.com/attestantio/vouch/mock"
|
||||||
|
"github.com/prysmaticlabs/go-bitfield"
|
||||||
|
"github.com/rs/zerolog"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
// populatedBitvector creates a populated bitlist.
|
||||||
|
func populatedBitvector(set uint64) bitfield.Bitvector128 {
|
||||||
|
res := bitfield.NewBitvector128()
|
||||||
|
for i := uint64(0); i < set; i++ {
|
||||||
|
res.SetBitAt(i, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestScore(t *testing.T) {
|
||||||
|
ctx := context.Background()
|
||||||
|
|
||||||
|
s, err := New(ctx,
|
||||||
|
WithLogLevel(zerolog.Disabled),
|
||||||
|
WithSyncCommitteeContributionProviders(map[string]eth2client.SyncCommitteeContributionProvider{
|
||||||
|
"good": mock.NewSyncCommitteeContributionProvider(),
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
contribution *altair.SyncCommitteeContribution
|
||||||
|
score float64
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "Nil",
|
||||||
|
score: 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Empty",
|
||||||
|
contribution: &altair.SyncCommitteeContribution{
|
||||||
|
Slot: 1,
|
||||||
|
SubcommitteeIndex: 2,
|
||||||
|
AggregationBits: populatedBitvector(0),
|
||||||
|
},
|
||||||
|
score: 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Full",
|
||||||
|
contribution: &altair.SyncCommitteeContribution{
|
||||||
|
Slot: 1,
|
||||||
|
SubcommitteeIndex: 2,
|
||||||
|
AggregationBits: populatedBitvector(128),
|
||||||
|
},
|
||||||
|
score: 128,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests {
|
||||||
|
t.Run(test.name, func(t *testing.T) {
|
||||||
|
score := s.scoreSyncCommitteeContribution(ctx, "test", test.contribution)
|
||||||
|
require.Equal(t, test.score, score)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,120 @@
|
||||||
|
// Copyright © 2021 Attestant Limited.
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package best_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
eth2client "github.com/attestantio/go-eth2-client"
|
||||||
|
"github.com/attestantio/go-eth2-client/spec/phase0"
|
||||||
|
"github.com/attestantio/vouch/mock"
|
||||||
|
"github.com/attestantio/vouch/strategies/synccommitteecontribution/best"
|
||||||
|
"github.com/rs/zerolog"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestSyncCommitteeContribution(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
params []best.Parameter
|
||||||
|
slot phase0.Slot
|
||||||
|
subcommitteeIndex uint64
|
||||||
|
beaconBlockRoot phase0.Root
|
||||||
|
err string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "Good",
|
||||||
|
params: []best.Parameter{
|
||||||
|
best.WithLogLevel(zerolog.Disabled),
|
||||||
|
best.WithSyncCommitteeContributionProviders(map[string]eth2client.SyncCommitteeContributionProvider{
|
||||||
|
"good": mock.NewSyncCommitteeContributionProvider(),
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
slot: 12345,
|
||||||
|
subcommitteeIndex: 1,
|
||||||
|
beaconBlockRoot: phase0.Root{
|
||||||
|
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
|
||||||
|
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Timeout",
|
||||||
|
params: []best.Parameter{
|
||||||
|
best.WithLogLevel(zerolog.Disabled),
|
||||||
|
best.WithTimeout(time.Second),
|
||||||
|
best.WithSyncCommitteeContributionProviders(map[string]eth2client.SyncCommitteeContributionProvider{
|
||||||
|
"sleepy": mock.NewSleepySyncCommitteeContributionProvider(5*time.Second, mock.NewSyncCommitteeContributionProvider()),
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
slot: 12345,
|
||||||
|
subcommitteeIndex: 1,
|
||||||
|
beaconBlockRoot: phase0.Root{
|
||||||
|
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
|
||||||
|
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
|
||||||
|
},
|
||||||
|
err: "no sync committee contribution received",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "NilResponse",
|
||||||
|
params: []best.Parameter{
|
||||||
|
best.WithLogLevel(zerolog.Disabled),
|
||||||
|
best.WithTimeout(time.Second),
|
||||||
|
best.WithSyncCommitteeContributionProviders(map[string]eth2client.SyncCommitteeContributionProvider{
|
||||||
|
"nil": mock.NewNilSyncCommitteeContributionProvider(),
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
slot: 12345,
|
||||||
|
subcommitteeIndex: 1,
|
||||||
|
beaconBlockRoot: phase0.Root{
|
||||||
|
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
|
||||||
|
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
|
||||||
|
},
|
||||||
|
err: "no sync committee contribution received",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "GoodMixed",
|
||||||
|
params: []best.Parameter{
|
||||||
|
best.WithLogLevel(zerolog.Disabled),
|
||||||
|
best.WithTimeout(2 * time.Second),
|
||||||
|
best.WithSyncCommitteeContributionProviders(map[string]eth2client.SyncCommitteeContributionProvider{
|
||||||
|
"error": mock.NewErroringSyncCommitteeContributionProvider(),
|
||||||
|
"sleepy": mock.NewSleepySyncCommitteeContributionProvider(time.Second, mock.NewSyncCommitteeContributionProvider()),
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
slot: 12345,
|
||||||
|
subcommitteeIndex: 1,
|
||||||
|
beaconBlockRoot: phase0.Root{
|
||||||
|
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
|
||||||
|
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests {
|
||||||
|
s, err := best.New(context.Background(), test.params...)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
t.Run(test.name, func(t *testing.T) {
|
||||||
|
contribution, err := s.SyncCommitteeContribution(context.Background(), test.slot, test.subcommitteeIndex, test.beaconBlockRoot)
|
||||||
|
if test.err != "" {
|
||||||
|
require.EqualError(t, err, test.err)
|
||||||
|
} else {
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotNil(t, contribution)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,99 @@
|
||||||
|
// Copyright © 2021 Attestant Limited.
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
// Package first is a strategy that obtains sync committee contributions
|
||||||
|
// from multiple nodes and selects the first one returned.
|
||||||
|
package first
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
eth2client "github.com/attestantio/go-eth2-client"
|
||||||
|
"github.com/attestantio/vouch/services/metrics"
|
||||||
|
nullmetrics "github.com/attestantio/vouch/services/metrics/null"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
"github.com/rs/zerolog"
|
||||||
|
)
|
||||||
|
|
||||||
|
type parameters struct {
|
||||||
|
logLevel zerolog.Level
|
||||||
|
clientMonitor metrics.ClientMonitor
|
||||||
|
syncCommitteeContributionProviders map[string]eth2client.SyncCommitteeContributionProvider
|
||||||
|
timeout time.Duration
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parameter is the interface for service parameters.
|
||||||
|
type Parameter interface {
|
||||||
|
apply(*parameters)
|
||||||
|
}
|
||||||
|
|
||||||
|
type parameterFunc func(*parameters)
|
||||||
|
|
||||||
|
func (f parameterFunc) apply(p *parameters) {
|
||||||
|
f(p)
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithLogLevel sets the log level for the module.
|
||||||
|
func WithLogLevel(logLevel zerolog.Level) Parameter {
|
||||||
|
return parameterFunc(func(p *parameters) {
|
||||||
|
p.logLevel = logLevel
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithClientMonitor sets the client monitor for the service.
|
||||||
|
func WithClientMonitor(monitor metrics.ClientMonitor) Parameter {
|
||||||
|
return parameterFunc(func(p *parameters) {
|
||||||
|
p.clientMonitor = monitor
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithSyncCommitteeContributionProviders sets the sync committee contribution providers.
|
||||||
|
func WithSyncCommitteeContributionProviders(providers map[string]eth2client.SyncCommitteeContributionProvider) Parameter {
|
||||||
|
return parameterFunc(func(p *parameters) {
|
||||||
|
p.syncCommitteeContributionProviders = providers
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithTimeout sets the timeout for requests.
|
||||||
|
func WithTimeout(timeout time.Duration) Parameter {
|
||||||
|
return parameterFunc(func(p *parameters) {
|
||||||
|
p.timeout = timeout
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// parseAndCheckParameters parses and checks parameters to ensure that mandatory parameters are present and correct.
|
||||||
|
func parseAndCheckParameters(params ...Parameter) (*parameters, error) {
|
||||||
|
parameters := parameters{
|
||||||
|
logLevel: zerolog.GlobalLevel(),
|
||||||
|
timeout: 2 * time.Second,
|
||||||
|
clientMonitor: nullmetrics.New(context.Background()),
|
||||||
|
}
|
||||||
|
for _, p := range params {
|
||||||
|
if params != nil {
|
||||||
|
p.apply(¶meters)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if parameters.timeout == 0 {
|
||||||
|
return nil, errors.New("no timeout specified")
|
||||||
|
}
|
||||||
|
if parameters.clientMonitor == nil {
|
||||||
|
return nil, errors.New("no client monitor specified")
|
||||||
|
}
|
||||||
|
if len(parameters.syncCommitteeContributionProviders) == 0 {
|
||||||
|
return nil, errors.New("no sync committee contribution providers specified")
|
||||||
|
}
|
||||||
|
|
||||||
|
return ¶meters, nil
|
||||||
|
}
|
|
@ -0,0 +1,57 @@
|
||||||
|
// Copyright © 2021 Attestant Limited.
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package first
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
eth2client "github.com/attestantio/go-eth2-client"
|
||||||
|
"github.com/attestantio/vouch/services/metrics"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
"github.com/rs/zerolog"
|
||||||
|
zerologger "github.com/rs/zerolog/log"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Service is the provider for sync committee contributions.
|
||||||
|
type Service struct {
|
||||||
|
clientMonitor metrics.ClientMonitor
|
||||||
|
syncCommitteeContributionProviders map[string]eth2client.SyncCommitteeContributionProvider
|
||||||
|
timeout time.Duration
|
||||||
|
}
|
||||||
|
|
||||||
|
// module-wide log.
|
||||||
|
var log zerolog.Logger
|
||||||
|
|
||||||
|
// New creates a new attestation data strategy.
|
||||||
|
func New(ctx context.Context, params ...Parameter) (*Service, error) {
|
||||||
|
parameters, err := parseAndCheckParameters(params...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "problem with parameters")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set logging.
|
||||||
|
log = zerologger.With().Str("strategy", "synccommitteecontribution").Str("impl", "first").Logger()
|
||||||
|
if parameters.logLevel != log.GetLevel() {
|
||||||
|
log = log.Level(parameters.logLevel)
|
||||||
|
}
|
||||||
|
|
||||||
|
s := &Service{
|
||||||
|
syncCommitteeContributionProviders: parameters.syncCommitteeContributionProviders,
|
||||||
|
timeout: parameters.timeout,
|
||||||
|
clientMonitor: parameters.clientMonitor,
|
||||||
|
}
|
||||||
|
|
||||||
|
return s, nil
|
||||||
|
}
|
|
@ -0,0 +1,105 @@
|
||||||
|
// Copyright © 2021 Attestant Limited.
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package first_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
eth2client "github.com/attestantio/go-eth2-client"
|
||||||
|
"github.com/attestantio/vouch/mock"
|
||||||
|
"github.com/attestantio/vouch/strategies/synccommitteecontribution/first"
|
||||||
|
"github.com/rs/zerolog"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestService(t *testing.T) {
|
||||||
|
syncCommitteeContributionProviders := map[string]eth2client.SyncCommitteeContributionProvider{
|
||||||
|
"localhost:1": mock.NewSyncCommitteeContributionProvider(),
|
||||||
|
}
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
params []first.Parameter
|
||||||
|
err string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "TimeoutZero",
|
||||||
|
params: []first.Parameter{
|
||||||
|
first.WithLogLevel(zerolog.TraceLevel),
|
||||||
|
first.WithTimeout(0),
|
||||||
|
first.WithSyncCommitteeContributionProviders(syncCommitteeContributionProviders),
|
||||||
|
},
|
||||||
|
err: "problem with parameters: no timeout specified",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "ClientMonitorMissing",
|
||||||
|
params: []first.Parameter{
|
||||||
|
first.WithLogLevel(zerolog.TraceLevel),
|
||||||
|
first.WithClientMonitor(nil),
|
||||||
|
first.WithSyncCommitteeContributionProviders(syncCommitteeContributionProviders),
|
||||||
|
},
|
||||||
|
err: "problem with parameters: no client monitor specified",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "SyncCommitteeContributionProvidersNil",
|
||||||
|
params: []first.Parameter{
|
||||||
|
first.WithLogLevel(zerolog.TraceLevel),
|
||||||
|
first.WithSyncCommitteeContributionProviders(nil),
|
||||||
|
},
|
||||||
|
err: "problem with parameters: no sync committee contribution providers specified",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "SyncCommitteeContributionProvidersEmpty",
|
||||||
|
params: []first.Parameter{
|
||||||
|
first.WithLogLevel(zerolog.TraceLevel),
|
||||||
|
first.WithSyncCommitteeContributionProviders(map[string]eth2client.SyncCommitteeContributionProvider{}),
|
||||||
|
},
|
||||||
|
err: "problem with parameters: no sync committee contribution providers specified",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Good",
|
||||||
|
params: []first.Parameter{
|
||||||
|
first.WithLogLevel(zerolog.TraceLevel),
|
||||||
|
first.WithTimeout(10 * time.Second),
|
||||||
|
first.WithSyncCommitteeContributionProviders(syncCommitteeContributionProviders),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests {
|
||||||
|
t.Run(test.name, func(t *testing.T) {
|
||||||
|
_, err := first.New(context.Background(), test.params...)
|
||||||
|
if test.err != "" {
|
||||||
|
require.EqualError(t, err, test.err)
|
||||||
|
} else {
|
||||||
|
require.NoError(t, err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestInterfaces(t *testing.T) {
|
||||||
|
syncCommitteeContributionProviders := map[string]eth2client.SyncCommitteeContributionProvider{
|
||||||
|
"localhost:1": mock.NewSyncCommitteeContributionProvider(),
|
||||||
|
}
|
||||||
|
|
||||||
|
s, err := first.New(context.Background(),
|
||||||
|
first.WithLogLevel(zerolog.Disabled),
|
||||||
|
first.WithSyncCommitteeContributionProviders(syncCommitteeContributionProviders),
|
||||||
|
)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Implements(t, (*eth2client.SyncCommitteeContributionProvider)(nil), s)
|
||||||
|
}
|
|
@ -0,0 +1,69 @@
|
||||||
|
// Copyright © 2021 Attestant Limited.
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package first
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
eth2client "github.com/attestantio/go-eth2-client"
|
||||||
|
"github.com/attestantio/go-eth2-client/spec/altair"
|
||||||
|
"github.com/attestantio/go-eth2-client/spec/phase0"
|
||||||
|
"github.com/attestantio/vouch/util"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
// SyncCommitteeContribution provides the sync committee contribution from a number of beacon nodes.
|
||||||
|
func (s *Service) SyncCommitteeContribution(ctx context.Context, slot phase0.Slot, subcommitteeIndex uint64, beaconBlockRoot phase0.Root) (*altair.SyncCommitteeContribution, error) {
|
||||||
|
started := time.Now()
|
||||||
|
log := util.LogWithID(ctx, log, "strategy_id")
|
||||||
|
|
||||||
|
// We create a cancelable context with a timeout. When a provider responds we cancel the context to cancel the other requests.
|
||||||
|
ctx, cancel := context.WithTimeout(ctx, s.timeout)
|
||||||
|
|
||||||
|
respCh := make(chan *altair.SyncCommitteeContribution, 1)
|
||||||
|
for name, provider := range s.syncCommitteeContributionProviders {
|
||||||
|
go func(ctx context.Context,
|
||||||
|
name string,
|
||||||
|
provider eth2client.SyncCommitteeContributionProvider,
|
||||||
|
ch chan *altair.SyncCommitteeContribution) {
|
||||||
|
log := log.With().Str("provider", name).Uint64("slot", uint64(slot)).Uint64("subcommittee_index", subcommitteeIndex).Str("beacon_block_root", fmt.Sprintf("%#x", beaconBlockRoot)).Logger()
|
||||||
|
|
||||||
|
contribution, err := provider.SyncCommitteeContribution(ctx, slot, subcommitteeIndex, beaconBlockRoot)
|
||||||
|
s.clientMonitor.ClientOperation(name, "sync committee contribution", err == nil, time.Since(started))
|
||||||
|
if err != nil {
|
||||||
|
log.Warn().Dur("elapsed", time.Since(started)).Err(err).Msg("Failed to obtain sync committee contribution")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if contribution == nil {
|
||||||
|
log.Warn().Dur("elapsed", time.Since(started)).Err(err).Msg("Returned empty sync committee contribution")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
log.Trace().Str("provider", name).Dur("elapsed", time.Since(started)).Msg("Obtained sync committee contribution")
|
||||||
|
|
||||||
|
ch <- contribution
|
||||||
|
}(ctx, name, provider, respCh)
|
||||||
|
}
|
||||||
|
|
||||||
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
cancel()
|
||||||
|
log.Warn().Msg("Failed to obtain sync committee contribution before timeout")
|
||||||
|
return nil, errors.New("failed to obtain sync committee contribution before timeout")
|
||||||
|
case aggregate := <-respCh:
|
||||||
|
cancel()
|
||||||
|
return aggregate, nil
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,121 @@
|
||||||
|
// Copyright © 2021 Attestant Limited.
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package first_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
eth2client "github.com/attestantio/go-eth2-client"
|
||||||
|
"github.com/attestantio/go-eth2-client/spec/phase0"
|
||||||
|
"github.com/attestantio/vouch/mock"
|
||||||
|
"github.com/attestantio/vouch/strategies/synccommitteecontribution/first"
|
||||||
|
"github.com/rs/zerolog"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestSyncCommitteeContribution(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
params []first.Parameter
|
||||||
|
slot phase0.Slot
|
||||||
|
subcommitteeIndex uint64
|
||||||
|
beaconBlockRoot phase0.Root
|
||||||
|
err string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "Good",
|
||||||
|
params: []first.Parameter{
|
||||||
|
first.WithLogLevel(zerolog.Disabled),
|
||||||
|
first.WithSyncCommitteeContributionProviders(map[string]eth2client.SyncCommitteeContributionProvider{
|
||||||
|
"good": mock.NewSyncCommitteeContributionProvider(),
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
slot: 12345,
|
||||||
|
subcommitteeIndex: 1,
|
||||||
|
beaconBlockRoot: phase0.Root{
|
||||||
|
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
|
||||||
|
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Timeout",
|
||||||
|
params: []first.Parameter{
|
||||||
|
first.WithLogLevel(zerolog.Disabled),
|
||||||
|
first.WithTimeout(time.Second),
|
||||||
|
first.WithSyncCommitteeContributionProviders(map[string]eth2client.SyncCommitteeContributionProvider{
|
||||||
|
"sleepy": mock.NewSleepySyncCommitteeContributionProvider(5*time.Second, mock.NewSyncCommitteeContributionProvider()),
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
slot: 12345,
|
||||||
|
subcommitteeIndex: 1,
|
||||||
|
beaconBlockRoot: phase0.Root{
|
||||||
|
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
|
||||||
|
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
|
||||||
|
},
|
||||||
|
err: "failed to obtain sync committee contribution before timeout",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "NilResponse",
|
||||||
|
params: []first.Parameter{
|
||||||
|
first.WithLogLevel(zerolog.Disabled),
|
||||||
|
first.WithTimeout(time.Second),
|
||||||
|
first.WithSyncCommitteeContributionProviders(map[string]eth2client.SyncCommitteeContributionProvider{
|
||||||
|
"nil": mock.NewNilSyncCommitteeContributionProvider(),
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
slot: 12345,
|
||||||
|
subcommitteeIndex: 1,
|
||||||
|
beaconBlockRoot: phase0.Root{
|
||||||
|
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
|
||||||
|
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
|
||||||
|
},
|
||||||
|
// Nil response is invalid, so expect a timeout.
|
||||||
|
err: "failed to obtain sync committee contribution before timeout",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "GoodMixed",
|
||||||
|
params: []first.Parameter{
|
||||||
|
first.WithLogLevel(zerolog.Disabled),
|
||||||
|
first.WithTimeout(2 * time.Second),
|
||||||
|
first.WithSyncCommitteeContributionProviders(map[string]eth2client.SyncCommitteeContributionProvider{
|
||||||
|
"error": mock.NewErroringSyncCommitteeContributionProvider(),
|
||||||
|
"sleepy": mock.NewSleepySyncCommitteeContributionProvider(time.Second, mock.NewSyncCommitteeContributionProvider()),
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
slot: 12345,
|
||||||
|
subcommitteeIndex: 1,
|
||||||
|
beaconBlockRoot: phase0.Root{
|
||||||
|
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
|
||||||
|
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests {
|
||||||
|
s, err := first.New(context.Background(), test.params...)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
t.Run(test.name, func(t *testing.T) {
|
||||||
|
contribution, err := s.SyncCommitteeContribution(context.Background(), test.slot, test.subcommitteeIndex, test.beaconBlockRoot)
|
||||||
|
if test.err != "" {
|
||||||
|
require.EqualError(t, err, test.err)
|
||||||
|
} else {
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotNil(t, contribution)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,36 @@
|
||||||
|
// Copyright © 2021 Attestant Limited.
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package util
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"math/rand"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/rs/zerolog"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
// We seed math.rand here so that we can obtain different IDs for requests.
|
||||||
|
// This is purely used as a way to match request and response entries in logs, so there is no
|
||||||
|
// requirement for this to cryptographically secure.
|
||||||
|
rand.Seed(time.Now().UnixNano())
|
||||||
|
}
|
||||||
|
|
||||||
|
// LogWithID returns a new logger based on the supplied logger with an additional ID field.
|
||||||
|
func LogWithID(ctx context.Context, log zerolog.Logger, tag string) zerolog.Logger {
|
||||||
|
// #nosec G404
|
||||||
|
return log.With().Str(tag, fmt.Sprintf("%02x", rand.Int31())).Logger()
|
||||||
|
}
|
Loading…
Reference in New Issue